返回 ppt-master
shared-standards-core.md
根目录 / skills / ppt-master / references / shared-standards-core.md
1 # Shared SVG Core Standards
2
3 Mandatory reference for every route that authors or regenerates slide visuals through SVG. It owns XML validity, the closed generated-authoring surface, basic converter compatibility, page closure, semantic grouping, shared visual-quality defaults, and fidelity vocabulary.
4
5 **Conditional module routing**:
6
7 | Trigger | Load |
8 |---|---|
9 | Default or Quick Generate; otherwise noncanonical/alpha paint, advanced line or text treatment, gradient/filter/effect, transform, freeform/radial geometry, or constructed style | [`svg-effects.md`](./svg-effects.md) |
10 | A page will use a preset pattern fill or evaluate native chart/table replacement | [`native-data-interface.md`](./native-data-interface.md) before deciding eligibility or emitting metadata |
11 | `pptx_structure.mode: structured` | [`pptx-structure-interface.md`](./pptx-structure-interface.md) |
12
13 **Default — shared aesthetic baseline (may be overridden by explicit user, installed template / brand, or locked / Quick-resolved visual-style requirements)**: Required / Forbidden technical contracts remain absolute. When a higher authority is silent, build clear hierarchy through typography and leading, alignment, negative space, purposeful imagery / icons, and restrained repetition before decoration. Deliberate tightness, imbalance, off-axis placement, or container-heavy structure remains valid when that authority calls for it.
14
15 | Concern | Shared default |
16 |---|---|
17 | Text-block rhythm | Use §4.2 leading. Make the baseline step into a new paragraph visibly larger than the intra-paragraph line step; keep the extra gap between list items smaller than paragraph separation but large enough to scan each item. Repeated peer blocks share one rhythm unless their hierarchy differs. |
18 | Typography roles | Use the fewest semantic text roles that preserve hierarchy, and make their differences legible at slide-thumbnail scale. Consolidate near-neighbor sizes that serve the same role; otherwise distinguish roles through a deliberate combination of size, weight, color, position, and surrounding space. |
19 | Viewing-distance legibility | Resolve delivery context and viewing distance before fixing density and type scale. Preserve necessary text at a readable scale by applying only actions the active route's content and page invariants permit: restructure, shorten, split, or reflow. If none is permitted, surface the unresolved fit instead of silently miniaturizing it. Do not turn this into one universal font-size floor: captions and metadata may be smaller when their role and context remain legible. |
20 | Contrast and semantic encoding | Within the active profile's fidelity boundary, keep meaning-bearing text distinguishable from its actual background. For newly authored distinctions, combine luminance, weight, scale, shape, position, or explicit labeling; color may reinforce meaning but never carry a required distinction alone. When fidelity requires preserving source-only color encoding, reproduce it rather than inventing a cue. Reserve lower-contrast treatment for genuinely secondary metadata that remains legible. |
21 | Natural wrapping | Break at semantic phrase or punctuation boundaries where possible. Reflow the text frame or adjust neighboring geometry before using any permitted local size reduction. Let the final line run naturally shorter; avoid mechanically equal lines or a stranded single-character / single-word line when an earlier natural break preserves meaning. |
22 | Content field | Establish the usable body frame before placing modules. Divide it into one or a small set of macro-regions from information weight and reading order: use unequal weight when the information differs, while true peers may share equal weight. Give each region its own local axes / micro-grid while retaining only the cross-region anchors the composition needs. On a dense page, let the planned content system organize that frame; create breathing room through gutters, module spacing, and intentional voids between semantic clusters. Unorganized residual space that leaves content stranded in one part of the frame is leftover blank, not negative space. |
23 | Alignment and proximity | Establish shared axes from the current composition. Align related titles, copy, labels, images, and diagram nodes to those edges, centers, or baselines; group related elements more tightly than unrelated groups so spacing carries hierarchy. Break an axis only when the offset performs hierarchy, direction, or tension. |
24 | Visual weight | Judge weight from area, darkness, saturation, density, stroke, image detail, and elevation together. Distribute it to support the focal path; symmetry is optional, and deliberate imbalance may create direction. |
25 | Boundary strength | Match the relationship with the lightest sufficient boundary from this expressive ladder: spacing / alignment → rule / bracket → tint field → outline → filled panel → true floating layer. Peer relationships use comparable strength while focus, hierarchy, or material difference may move to a stronger treatment. The ladder is not a required sequence or per-page quota. |
26 | Containers | Use a card or panel when it expresses grouping, hierarchy, boundary, capacity, or a distinct material plane. Otherwise prefer spacing, rules, or direct text / geometry; peer containers share treatment unless a semantic difference justifies contrast. An unplanned repeated web-card grid is a carrier / topology problem, not a reason to suppress meaningful borders, shapes, or containers. |
27 | Titles and page chrome | Treat the semantic page title as part of the current composition rather than an automatic fixed header band; its position, scale, and relationship may change with page role while preserving the active route's content invariants. Add or retain running headers, footers, and page numbers only when they carry navigation, identity, attribution, or another explicit page job. Fidelity profiles preserve required source chrome. |
28
29 **Default — active effects vocabulary (may resolve to no added technique when no visual job is diagnosed)**: Default and Quick Generate complete the already-loaded [`svg-effects.md`](./svg-effects.md) §6.1 job diagnostic, which that file makes mandatory, before completing each page; whether any compatible technique is then added is this default's call, with the Visual Job Router as recall.
30
31 **Fidelity labels**:
32
33 | Label | Meaning |
34 |---|---|
35 | `Native-stable` | Generated PPTX uses the corresponding native DrawingML property or object and retains the documented semantics within the technique-specific limits. |
36 | `Native-normalized` | Export targets an editable DrawingML equivalent, but normalizes the SVG into another structure such as a freeform, run property, or simplified paint/effect. |
37 | `Approximate` | DrawingML has no exact SVG equivalent; export targets the intended effect through a documented approximation, and material differences require output review. |
38 | `Bake-required` | The runtime effect is outside the native contract; pre-render it into an image or rebuild it with explicit supported geometry. |
39
40 **Reading rules**:
41
42 - **Required** / **Forbidden** statements are non-negotiable technical boundaries.
43 - **Conditional** contracts apply only when the corresponding feature is used.
44 - **Reference — not a constraint** passages expose capabilities and recipes; they do not require every page or visual style to use them.
45 - The locked `visual_style` controls whether and how strongly a compatible effect is used. It never expands the technical boundary.
46
47 **Hard rule — generated authoring is fail-closed**: `svg_output/` and reusable
48 template SVGs may use only properties and conditional interfaces explicitly
49 listed in this file or a triggered module in the routing table above. `svg_quality_checker.py` rejects unknown inline visual
50 properties and conditional contracts that have no reliable compatibility
51 mapping; documented fallback forms remain valid and receive warnings.
52
53 **Default — recommended authoring and supported input stay separate (may
54 preserve supported input)**: generated SVG uses one predictable default
55 spelling, while converter-supported equivalent spellings remain valid input.
56 The checker may recommend normalization, but such warnings do not require
57 modification or block export. Only invalid, unsafe, or unreliably convertible
58 input is an error; do not remove converter support to enforce a narrower
59 generation preference.
60
61 **Hard rule — one-way fidelity vocabulary**: the labels above describe the
62 `svg_output/` → generated PPTX path. They do not promise reconstruction of the
63 original SVG syntax, `<defs>` graph, `<use>` structure, path commands, or
64 `<tspan>` layout after PPTX-to-SVG import, nor pixel identity across PowerPoint,
65 LibreOffice, Keynote, and WPS.
66
67 **Hard rule — capability boundary**: a recipe never expands converter support.
68 Use only the target elements and syntax documented by each conditional
69 contract. Unsupported element tags fail preflight; browser-rendered attributes
70 outside these contracts must not be assumed to have a DrawingML mapping.
71
72 ---
73
74
75 ## 1. Required Foundation, Forbidden Features, and Conditional Interfaces
76
77 ### 1.0 Text characters: must be well-formed XML
78
79 SVG is strict XML. Two rules for all text and attribute values:
80
81 | Character category | Required form | Forbidden form |
82 |---|---|---|
83 | Typography & symbols (em dash, en dash, ©, ®, →, ·, NBSP, full-width punctuation, emoji…) | **Raw Unicode characters** — write `—` `–` `©` `®` `→` directly | HTML named entities — `&mdash;` `&ndash;` `&copy;` `&reg;` `&rarr;` `&middot;` `&nbsp;` `&hellip;` `&bull;` etc. |
84 | XML reserved characters (`&`, `<`, `>`, `"`, `'`) | **XML entities only** — `&amp;` `&lt;` `&gt;` `&quot;` `&apos;` (e.g. `R&amp;D`, `error &lt; 5%`) | Bare `&` `<` `>` (e.g. `R&D`, `error < 5%`) |
85
86 One offending character invalidates the file and aborts export.
87
88 **Structural blacklist** (in addition to the character rules above):
89
90 | Banned Feature | Description |
91 |----------------|-------------|
92 | `mask` | Masks |
93 | `<style>` | Embedded stylesheets |
94 | `class` | CSS selector attributes |
95 | External CSS | External stylesheet links |
96 | `<foreignObject>` | Embedded external content |
97 | `textPath` | Text along a path |
98 | `@font-face` | Custom font declarations |
99 | `<animate*>` / `<set>` | SVG animations |
100 | `<script>` / event attributes | Scripts and interactivity |
101 | `<iframe>` | Embedded frames |
102
103 The blacklist above is exhaustive for globally forbidden structural syntax.
104 It is not a positive allowlist for every browser-rendered property. Features
105 that require a restricted form are valid only under the conditional contracts
106 below; unlisted visual properties are unsupported.
107
108 **Hard rule — inline visual-property allowlist**:
109
110 | Property family | Allowed inline `style` properties |
111 |---|---|
112 | Paint and line | `fill`, `stroke`, `stroke-width`, `stroke-dasharray`, `stroke-linecap`, `stroke-linejoin`, `fill-opacity`, `stroke-opacity`, `vector-effect` |
113 | Text | `font-family`, `font-size`, `font-weight`, `font-style`, `text-anchor`, `letter-spacing`, `text-decoration` |
114 | Alpha and definition paint | `opacity`, `stop-color`, `stop-opacity`, `flood-color`, `flood-opacity` |
115 | Literal geometry | The element-specific properties in §2.1 |
116 | Preview-only | `shape-rendering`; it does not change native geometry |
117
118 **Default — ordinary generated paint**: the table allows inline placement of
119 those property names. New solid paint uses uppercase six-digit `#RRGGBB`;
120 `fill` / `stroke` may instead use lowercase `none` or an exact local
121 `url(#id)`. Load [`svg-effects.md`](./svg-effects.md) before authoring any
122 alternative compatible color spelling, alpha/opacity channel, dash/cap/join,
123 gradient, filter, or constructed paint/effect. Existing compatible alternatives
124 remain valid input and receive recommendation warnings rather than errors.
125
126 Conditional properties with a required XML form stay out of inline style:
127 write `filter="url(#id)"`, `clip-path="url(#id)"`, and
128 `marker-start` / `marker-end` as direct attributes. Ordinary-text superscript
129 and subscript likewise use only direct `baseline-shift="super|sub"` on
130 `<tspan>`. `!important`, unknown CSS properties, blend modes, isolation, and
131 backdrop filters fail quality check.
132
133 The table registers property names, not arbitrary CSS values. Ordinary generated
134 text uses a non-empty `font-family`, a finite positive unitless-px `font-size`,
135 `font-weight` of `normal` / `bold` / an integer hundred from `100` through
136 `900`, `font-style` of `normal` / `italic`, and `text-anchor` of `start` /
137 `middle` / `end`. Inheritable text declarations belong only on `<svg>`, `<g>`,
138 `<text>`, or `<tspan>`; `text-anchor` is invalid on `<tspan>`. Load
139 [`svg-effects.md`](./svg-effects.md) §6.7 before authoring tracking,
140 underline/strike, text outline/alpha, gradient text, or text filter effects.
141 Unknown or unmapped declarations fail Checker preflight and native export.
142
143 > **`marker-start` / `marker-end` is conditional** — see §1.1.
144 >
145 > **`clipPath` on `<image>` is conditional** — see §1.2.
146 >
147 > **Static same-document `<use>` is conditional** — see §1.3.
148 >
149 > **Imported native-shape metadata is conditional** — see §1.4.
150 >
151 > **Authored native preset fragments are conditional** — see §1.5.
152 >
153 > **Inline CSS geometry, simple gradients, filters, and approximate group
154 > opacity are conditional** — see §2 and [`svg-effects.md`](./svg-effects.md).
155 >
156 > **PPT preset patterns and native chart/table/template metadata are
157 > conditional** — see [`native-data-interface.md`](./native-data-interface.md) and [`pptx-structure-interface.md`](./pptx-structure-interface.md).
158
159 DrawingML has no arbitrary per-pixel alpha-compositing path. A registered
160 single-image text picture/texture fill follows [`svg-effects.md`](./svg-effects.md)
161 §6.3; arbitrary text-knockout composites, multi-layer image text, and arbitrary
162 alpha composites remain bake-required before SVG export.
163
164 ---
165
166 ### 1.1 Line-end Markers (Conditional Contract)
167
168 `marker-start` and `marker-end` are supported on `<line>` and `<path>` only
169 when the referenced marker fits this native-arrow contract:
170
171 | Concern | Required form |
172 |---|---|
173 | Reference | Exact local `url(#id)` to a `<marker>` in `<defs>` |
174 | Orientation | `orient="auto"` or `orient="auto-start-reverse"`; the latter reverses `marker-start` while behaving like `auto` at `marker-end` |
175 | Shape | One direct shape representing a DrawingML `triangle`, `stealth`, `arrow`, `diamond`, or `oval` line end: a 3-vertex `<polygon>` / closed path (triangle), a simple concave 4-vertex `<polygon>` / closed path (stealth), an open 3-vertex path (arrow), a simple convex 4-vertex `<polygon>` / closed path (diamond), or one `<circle>` / `<ellipse>` (oval) |
176 | Path grammar | Use one explicit `M`/`L` command per vertex. Triangle, stealth, and diamond paths end in `Z`; arrow paths remain open after the third vertex. Do not use `H`, `V`, curves, or an implicit multi-point `L` command inside a marker path |
177 | Color parity | Triangle, stealth, diamond, and oval use a fill matching the parent line stroke. The open arrow uses `fill="none"` and a stroke matching the parent line stroke. DrawingML line ends inherit the line color |
178
179 The converter maps these five shapes to their corresponding DrawingML line-end
180 types. Prefer `<polygon>` for the closed triangle, stealth, and diamond forms;
181 the open arrow form requires `<path>`. Four-vertex shapes must be simple and
182 non-degenerate: convex geometry maps to diamond and concave geometry maps to
183 stealth. Checker and exporter preflight consume this same contract; other
184 marker shapes have no native mapping and block export instead of being silently
185 dropped.
186
187 PPTX import compatibility, tolerant recovery, strict-mode rejection, and
188 diagnostic behavior are indexed in
189 [`conversion.md`](../scripts/docs/conversion.md#import-compatibility-and-recovery-boundary).
190
191 ---
192
193 ### 1.2 Image Clipping (Conditional Contract)
194
195 `clip-path` maps natively only on SVG `<image>` (including an exact crop
196 wrapper's inner image) under this contract. Legacy imported crops may retain
197 an outer-wrapper clip as compatible input:
198
199 | Concern | Required form |
200 |---|---|
201 | SVG-namespace `<clipPath>` defined inside `<defs>` | Converter looks up one exact local id; missing, duplicate, foreign-namespace, or malformed references fail |
202 | Contains exactly one direct SVG-namespace supported shape child | Multiple shapes are not composited |
203 | Shape is one of: `<circle>`, `<ellipse>`, `<rect>` (optional rx/ry), `<path>`, `<polygon>` | These map to DrawingML geometry (preset or custom) |
204 | No `clip-rule` or `fill-rule`, whether direct or in inline `style` | DrawingML picture geometry has no equivalent winding-rule control |
205 | Used only on `<image>` or a compatible legacy imported crop wrapper | Shapes, groups, text, and generalized nested SVG targets are **forbidden** |
206
207 | SVG clip shape | DrawingML output |
208 |---|---|
209 | `<circle>` / `<ellipse>` | Full-frame `<a:prstGeom prst="ellipse"/>`; the child must exactly cover the image frame. A `userSpaceOnUse` circle requires a square physical frame; a normalized `objectBoundingBox` circle may fill any frame |
210 | `<rect>` / `<rect rx="..."/>` | A plain full-frame rect is a compatible no-op; rounded form maps to full-frame `<a:prstGeom prst="roundRect"/>` with one physical radius adjustment. The rect must exactly cover the image frame and cannot express non-uniform physical corner radii |
211 | `<path>` / `<polygon>` | `<a:custGeom>` with coordinates mapped into the image frame |
212
213 `clip-path` on shapes, groups, or text is forbidden; author the target geometry
214 directly instead. Use a path/polygon clip when the intended contour does not
215 cover the full picture frame. A contour that depends on even-odd or another
216 explicit winding rule is outside this mapping and must be rebuilt as one
217 unambiguous visible contour or pre-rendered.
218
219 ---
220
221 ### 1.3 Static Same-Document `<use>` (Conditional Contract)
222
223 **Expansion contract**: Static local reuse is compile-time authoring shorthand. `finalize_svg.py` and
224 native export replace each qualifying instance with cloned primitive content;
225 PPTX-to-SVG import emits the resulting primitives and does **not** reconstruct
226 the original `<use>` / `<symbol>` structure.
227
228 | Concern | Required form |
229 |---|---|
230 | Reference syntax | Author new SVG with the SVG 2 form `href="#id"`. Legacy `xlink:href="#id"` remains read-compatible and Live Preview normalizes it to `href`; if both attributes exist, their values MUST match. |
231 | Referenced target | One of `<symbol>`, `<g>`, `<use>`, `<rect>`, `<circle>`, `<ellipse>`, `<line>`, `<path>`, `<polygon>`, `<polyline>`, `<text>`, or `<image>`. Nested local `<use>` is recursively expanded. |
232 | Instance position | Generated `<use x>` / `<use y>` use finite unitless values; an explicit `px` suffix is read-compatible. Omitted values default to `0`. |
233 | Symbol viewport | A referenced `<symbol>` MUST have a finite four-number `viewBox` with positive width/height. Its `<use>` MUST have positive finite unitless `width` and `height`; an explicit `px` suffix is read-compatible. |
234 | Aspect ratio | Default/aligned `meet` values and plain `preserveAspectRatio="none"` are supported. `slice`, `refX`, and `refY` are forbidden. |
235 | Viewport boundary | Symbol artwork MUST stay inside its `viewBox`; expansion does not reproduce symbol overflow clipping. |
236 | Internal references | Author exact `href="#id"` and `url(#id)` fragments. The expander also reads legacy `xlink:href="#id"` and rewrites all instance-local cloned IDs. |
237 | Structural metadata | Neither the `<use>` instance nor its referenced subtree may carry `data-pptx-layer*`, chart/table replacement metadata (`data-pptx-replace-with`, `data-pptx-replacement-*`, `data-pptx-import-source`, or `data-pptx-fallback-*`), or `data-pptx-placeholder*`. Author those objects directly instead of reusing them. |
238 | Safety limits | A reachable reference chain may contain at most 64 instances, and one SVG may expand at most 10,000 local `<use>` instances. |
239
240 **Forbidden — unsafe local references**:
241
242 - External/file/data URLs, missing targets, conflicting `href` / `xlink:href`,
243 unsupported target elements, and circular reference chains
244 - Duplicate IDs on the referenced target, the `<use>` instance, or anywhere in
245 the reused subtree
246 - Quoted/whitespace CSS fragment variants such as `url('#id')`; use exact
247 `url(#id)` when an internal paint/filter/clip reference must be rewritten
248
249 **Contract example**:
250
251 ```xml
252 <svg xmlns="http://www.w3.org/2000/svg">
253 <defs>
254 <symbol id="statusDot" viewBox="0 0 20 20" preserveAspectRatio="xMidYMid meet">
255 <circle cx="10" cy="10" r="8" fill="#16A34A"/>
256 </symbol>
257 <g id="legendRow">
258 <rect width="120" height="32" rx="8" fill="#F1F5F9"/>
259 <text x="42" y="22" font-size="16" fill="#0F172A">Ready</text>
260 </g>
261 </defs>
262 <use href="#statusDot" x="80" y="120" width="32" height="32"/>
263 <use href="#legendRow" x="120" y="120"/>
264 </svg>
265 ```
266
267 ---
268
269 ### 1.4 Imported Native PowerPoint Shapes (Conditional Contract)
270
271 `pptx_to_svg.py` emits rendering-neutral metadata when a visible SVG object
272 originates from `p:sp`, `p:cxnSp`, or `p:grpSp`. This contract is for lossless
273 import SVGs and unchanged imported objects that remain Slide-local or inside a
274 slot during mirror materialization. Ordinary authored SVG does not need these
275 attributes, and no separate source-payload opt-in marker exists.
276
277 | Metadata | Placement | Required behavior |
278 |---|---|---|
279 | `data-pptx-object` | Logical `<g>` and native carrier | `shape`, `connector`, `group`, or `picture`; never infer the object kind from path appearance. |
280 | `data-pptx-shape-id` + `data-pptx-shape-scope` | Logical `<g>` and carrier | Preserve the source part-scoped identity. Export remaps duplicate Master/Layout/Slide ids into page-unique ids before rebinding connector references. |
281 | `data-pptx-frame="x y width height"` | Logical `<g>` and carrier | Own native `a:xfrm` position and size. Lossless import SVGs and tool-side native records use sufficient precision for exact EMU recovery; the model-facing authoring IR may use the compact page-coordinate spelling defined below. Path bounds, stroke, markers, shadows, and text glyph bounds never replace this frame. |
282 | `data-pptx-prst` | Preset carrier and logical `<g>` | One of the locked 187 DrawingML `ST_ShapeType` values. |
283 | `data-pptx-av-*` | Preset carrier and logical `<g>` | Preserve the complete validated DrawingML adjustment formula, including non-`val` formulas. |
284 | `data-pptx-part="geometry"` | One hidden carrier path | The single native export authority for frame, base fill/line/effect, preset/custom geometry, and object identity. |
285 | `data-pptx-part="geometry-preview"` / `geometry-detail` | Visible preview group/paths | Render the preset's independent path fill/stroke layers. A hash-locked preview group may mirror the carrier's one filter so a multi-path preset renders one aggregate imported effect; these elements are never emitted as duplicate PowerPoint shapes. |
286 | `data-pptx-preview-sha256` | Logical preset `<g>` and carrier | Detect edits to visible preset paths or paint. A stale preview fails quality check/export instead of silently reusing old native metadata. |
287 | `data-pptx-geometry-kind="custom"` + `data-pptx-custgeom` or `data-pptx-custgeom-ref` | Custom-geometry carrier | Preserve the validated original `a:custGeom` subtree. If the visible path hash is unchanged, export writes formulas, handles, connection sites, text rectangle, and path list exactly; edited paths compile from current SVG geometry. |
288 | `data-pptx-start/end-shape-id/site` | Connector logical `<g>` and carrier | Restore `a:stCxn` / `a:endCxn` after scoped shape-id allocation. A connector may retain one zero frame axis; it must not be expanded from visible stroke or marker bounds. |
289 | `data-pptx-shape-style` or `data-pptx-shape-style-ref` | Native carrier | Preserve a relationship-free `p:style` independently of text, including shapes with no visible text. |
290 | `data-pptx-effect-status="unsupported"` + `data-pptx-effect-reason` | Imported `p:sp` / `p:cxnSp` logical object and native carrier; imported `p:pic` carrier and logical object; imported `p:grpSp` logical group; imported table `p:graphicFrame` logical group | Record why an encountered source object or text-run `effectLst` / `effectDag` cannot enter the registered target-specific effect mapping without changing semantics. Checker and export stop with the recorded reason; these attributes are diagnostics, not a preserved effect payload or authoring syntax. |
291 | `metadata[data-pptx-part="txbody"]` with inline Base64 or `data-pptx-ref` | Logical shape `<g>` | Preserve unchanged `p:txBody`, including an empty text body. Content, whitespace, positioning, visible typography, or incompatible child-topology edits invalidate the payload. A source payload with run-level effects then blocks checker/export instead of losing those effects; an effect-free payload uses the normal SVG text fallback. |
292
293 **Hard rule — compact native metadata transport**: Type A mirror
294 materialization moves `p:txBody`, relationship-free `p:style`, and
295 `a:custGeom` payloads into the content-addressed
296 `templates/native_payloads.json.gz` store. It also deduplicates repeated native
297 restoration fields—object identity, frame, preset/custom-geometry guards,
298 preview/text hashes, connector endpoints, payload references, and adjustment
299 formulas—into short `data-pptx-native-ref` records in the same store. Checker,
300 template-structure validation, and export validate and hydrate both layers in
301 memory. Keep Master/Layout, placeholder, layer, editable-object, diagnostic,
302 and editable chart/table metadata inline. Legacy inline Base64 and v1
303 payload-only stores remain readable.
304
305 One effect reason remains its existing plain token. If one imported object has
306 multiple independent unsupported reasons, both marker copies store the same
307 deduplicated, lexicographically sorted compact JSON string array in
308 `data-pptx-effect-reason`; adding a later reason must not overwrite an earlier
309 one. This array is still diagnostic metadata, not an authoring surface.
310
311 **Import/authoring representation split**:
312
313 | Representation | Contract |
314 |---|---|
315 | Lossless import SVG | Keep complete native payload, hidden carriers, and preview evidence in the temporary analysis workspace. It is immutable native-payload backing, not the editable template source. |
316 | Authoring IR bundle | Keep editable SVGs plus model-readable `authoring_summary.json` and tool-only `authoring_manifest.json`. Exclude opaque payload and duplicate hidden carriers from model context while retaining visible shape intent and a stable document-local `data-pptx-source-ref` on each imported logical object. Compact model-facing imported frames and safe transform page coordinates to at most two decimals before hashing the IR. The summary owns the compact current-file index; the manifest owns source paths and initial hashes and never enters model context. |
317 | `standard` / `fidelity` output | Use the compact authored-preset contract (§1.5) for newly authored stock shapes; do not transplant opaque import payload or source topology. |
318 | `mirror` output | Materialize from the edited authoring IR. Rehydrate supported imported metadata only when a Slide-local/slot object's source ref and initial authoring hash still match; otherwise keep the current SVG fallback. Expand fixed Master/Layout group wrappers into direct semantic atoms while preserving source ownership, paint order, and visible appearance. |
319
320 **Hard rule — model-facing page-coordinate precision**:
321
322 | Surface | Precision contract |
323 |---|---|
324 | Imported `data-pptx-frame` in authoring IR | At most two decimals. An unchanged mirror source ref recovers the exact lossless frame before tool-side native-record externalization. |
325 | `data-pptx-bounds` in generated and final template SVG | At most two decimals. |
326 | `translate(...)`, `rotate(... cx cy)`, and `matrix(... e f)` | Translation values and rotation centers use at most two decimals. Keep the rotation angle and matrix `a b c d` coefficients unchanged. |
327 | Protected values | Do not apply this compaction to path/points geometry, normalized crop or nested `viewBox` ratios, gradient offsets, opacity, scale arguments, canonical authored-preset frames, or lossless/tool-side native frames. |
328
329 **Hard rule — authoring source refs**: `data-pptx-source-ref` is reserved for
330 the create-template authoring IR. Its value is unique within one authoring SVG,
331 not across the workspace, and must be resolved through that document's
332 `authoring_manifest.json` record by the owning tool. Models MUST NOT read that
333 machine manifest. Moving a referenced subtree into
334 `icons/imported/` for readability must preserve the attribute and record it in
335 the vector inventory; re-inlining re-establishes the same mapping. Final materialized
336 template SVGs and normal project `svg_output/` must not contain this attribute.
337
338 **Hard rule — structural-layer boundary**: An unchanged imported logical object
339 may keep currently supported metadata while it remains Slide-local or inside a
340 slot. An imported logical `<g>` cannot be assigned to Master/Layout because
341 those layers require direct semantic atoms. Mechanically expand a fixed-layer
342 source group into direct atoms, rebuilding a preset when supported and
343 otherwise retaining the visible SVG fallback. A newly authored compact preset
344 `<g>` from §1.5 is the sole group exception: validation proves that it compiles
345 to exactly one native shape/connector. Do not use this normalization to change
346 ownership or appearance.
347
348 **Hard rule — selective payload**: Do not copy every imported metadata block into
349 an authored template. Keep the full lossless import SVG separately as immutable
350 audit/fallback backing. Mirror may reuse only metadata already supported by the
351 converter on source-ref/hash-matching Slide-local/slot objects; unsupported or
352 edited objects use the current SVG fallback. `data-pptx-replace-with` remains reserved for the
353 optional PowerPoint-native Chart/Table replacement contract.
354
355 **Registry and rendering rules**:
356
357 - The hash-locked shared registry must equal the independent 187-value shape
358 catalog. Missing, duplicate, unknown, or corrupt definitions fail closed.
359 - Preset preview paths come from the shared DrawingML formula evaluator; do not
360 add per-shape Python geometry handlers.
361 - Preset size is controlled only by `data-pptx-frame` / `a:xfrm`. Adjustment
362 formulas control the contour inside that frame and are not rescaled when the
363 frame changes.
364 - A group transform may move, scale, rotate, or flip the complete logical
365 shape without invalidating its preview fingerprint. Editing a generated
366 `geometry-detail` path directly is unsupported unless the carrier metadata
367 and preview fingerprint are regenerated together.
368 - Unknown or malformed SVG transform operations fail closed. DrawingML cannot
369 represent arbitrary shear, so a non-orthogonal transform must stop native
370 export instead of being silently approximated as rotation and scale.
371 - Opaque XML payloads containing any `r:*` relationship attribute are never
372 copied into a new slide part. Relationship-bearing text content and
373 shape-level `a:blipFill` use the existing rebuilt visual fallback and are
374 not covered by atomic `p:sp + p:txBody` rehydration.
375 - Unknown future presets and explicit `unsupported` geometry status never
376 downgrade silently to `rect`; native export stops with the recorded reason.
377
378 **Fidelity boundary**: native preset/custom geometry, logical frame, scoped
379 identity, connector topology, and relationship-free unchanged horizontal
380 text-body semantics on ordinary shape fills are `Native-stable`. The SVG
381 preview paint for gradient/pattern
382 `darken`/`lighten` layers is `Native-normalized`; original group child
383 coordinates, shape-level image-fill reconstruction, and vertical-text
384 reconstruction are also normalized rather than byte-identical OOXML.
385
386 ---
387
388 ### 1.5 Authored Native PowerPoint Presets (Conditional Contract)
389
390 New SVG pages and project-owned canonical reusable templates may opt one
391 complete geometric object into a native DrawingML preset through the
392 deterministic fragment helper. Selection behavior lives in
393 [`native-shape-authoring.md`](./native-shape-authoring.md); this section owns
394 the machine contract. This compact canonical form describes the intended
395 preset, frame, adjustments, paint, and an optional shape effect once, keeps only
396 registry-generated visible SVG paths, and embeds no source OOXML or serialized
397 preview fingerprint.
398
399 | Metadata / structure | Required behavior |
400 |---|---|
401 | `data-pptx-authoring="preset"` | Appears once on the logical `<g>`; distinguishes strict project authoring from legacy/imported metadata. |
402 | `data-pptx-object` | `shape` or `connector`; connector-family presets must use `connector`, and `connector` must use a connector-family preset. Authored connectors require `fill="none"` plus a visible stroke and export as unconnected `p:cxnSp`. |
403 | `data-pptx-prst`, `data-pptx-frame`, `data-pptx-av-*` | Generated together from the locked registry and written once on the logical group. The frame is the helper's exact four-part, space-separated ordinary-decimal spelling and remains authoritative even when visible path bounds differ; commas, scientific notation, leading `+`, and redundant decimal spellings are rejected. |
404 | Local `fill` / `stroke` plus supported paint attributes | Base paint is written once on the group; a visible stroke also carries an explicit width. Canonical page/template authoring keeps channel paint local. Compatible ancestor paint/opacity may compose under the general SVG rules and receives a recommendation warning. |
405 | Optional direct `filter="url(#id)"` | Shape presets only: the helper writes one exact local reference to a direct [`svg-effects.md`](./svg-effects.md) §6.4 filter definition. It compiles once on the complete native shape; connector presets, inline style, ordinary group filters, and child-path filters remain unsupported. |
406 | Ordered direct `<path>` children | Browser-visible registry layers only. Each child writes just its required path-level fill/stroke override; labels and decorations stay outside the atomic group. |
407 | No carrier / wrapper / fingerprint | `data-pptx-part`, hidden geometry carriers, preview wrappers, and `data-pptx-preview-sha256` belong to expanded import/compatibility transport, not canonical project authoring. |
408
409 Generate one fragment at a time:
410
411 ```bash
412 python3 ${SKILL_DIR}/scripts/preset_shape_svg.py render rightArrow \
413 --id p03-growth-arrow \
414 --frame 160 210 320 112 \
415 --fill "#2563EB" \
416 --stroke none \
417 --adjust "adj1=val 50000"
418 ```
419
420 When one native effect is justified, append `--filter-id softShadow`; that id
421 must already name one direct page-level §6.4 filter definition.
422
423 **Hard rule — helper-only metadata**: never add or edit authored preset
424 metadata or registry paths by hand. The compact helper output is atomic.
425 Regenerate it when preset, frame, adjustment, fill, stroke, stroke width, or the
426 filter reference changes. Replace the whole fragment with ordinary SVG when
427 free contour editing is required.
428
429 Template ownership metadata is orthogonal to preset geometry. After inserting
430 the complete helper output, `create-template` may add only the registered
431 `data-pptx-layer`, `data-pptx-editable`, `data-pptx-carrier`, or
432 `data-pptx-role` attribute needed by the surrounding structured contract. It
433 must not change preset/frame/adjustment/paint metadata, the filter reference, or
434 any direct path.
435
436 **Reusable-template boundary**: a project-owned canonical template may retain
437 one complete helper-generated atomic fragment when the stock preset is an exact
438 semantic match and both its paint and optional effect stay inside the authoring
439 boundary below. The fragment is an executable exemplar and one semantic atom,
440 not a freely editable
441 template primitive. It may be Slide-local, the one carrier of an `object` slot,
442 or a direct Master/Layout fixed atom. An adaptation may reuse it unchanged only
443 when preset, frame, adjustments, paint, and the optional filter reference are
444 unchanged; otherwise regenerate the whole fragment with the helper.
445 Imported, mirror, and third-party templates are never upgraded by contour
446 inference.
447
448 **Hard rule — visible page closure**: the helper prints a complete visible
449 fragment to stdout; export never invents its preview. The main Agent inserts
450 that output into the hand-authored page or canonical reusable template. The
451 helper cannot write a project, select layout, or generate a page.
452
453 **Authoring paint/effect boundary**: v1 accepts `none` or six-digit solid HEX
454 fill and stroke, optional fill/stroke opacity, stroke width, line cap, line join,
455 and one shape-only local filter id under [`svg-effects.md`](./svg-effects.md)
456 §6.4.
457 Normal generated pages use `spec_lock.md` for stable semantic color anchors and
458 choose page-local paint from the retained Design Spec, style, and composition context.
459 The lockless [`quick-generate`](../workflows/profiles/quick-generate.md) profile
460 keeps every chosen paint value explicit in the SVG.
461 `create-template` authored templates take their values from the confirmed brief
462 and template `design_spec.md`.
463 Use ordinary SVG for gradients, patterns, or other treatments outside this
464 narrow contract. Registry-derived multi-path darken/lighten colors and
465 other contextual derivatives need no separate lock row unless they become a
466 recurring named role. Mirror preserves source paint under §1.4 instead.
467
468 **Validation**: quality check and export both rerender authored fragments from
469 `preset + frame + adjustments + group paint` and compare every visible path and
470 path-level paint override directly. They separately validate the optional effect
471 reference through §6.4. Registry-path edits, geometry metadata that leaves those
472 paths stale, unknown adjustments, invalid or unresolved filter references,
473 out-of-range frames/transforms,
474 zero-scale transforms, and shear/skew fail closed. Export expands the validated
475 compact group only in memory and reuses the lossless native-shape conversion
476 path. Older authored carrier/preview fragments remain compatible as ordinary
477 Slide-local input and
478 receive a non-blocking migration warning; they do not gain the new compact
479 group's structured-atom exception. `pptx_to_svg` expanded output remains the
480 lossless round-trip form and is not warned as authored input.
481
482 **Fidelity boundary**: an unchanged authored fragment is `Native-stable` as
483 one `p:sp` or `p:cxnSp`. Text remains outside the atomic fragment and may export
484 as a grouped editable text box. Authoring v1 creates only unconnected
485 `p:cxnSp`; it does not accept hand-written endpoint/site metadata. An
486 `actionButton*` preset maps visual geometry only. Preset appearance never
487 invents connector attachment, action behavior, navigation targets, or
488 hyperlinks. Link and navigation behavior is authored explicitly instead — see
489 [`native-hyperlinks.md`](./native-hyperlinks.md).
490
491 ---
492
493 ## 2. Conditional Compatibility Mappings
494
495 ### 2.1 Literal Geometry Lengths and Inline Geometry
496
497 **Hard rule — direct geometry length grammar**: New generated SVG writes the
498 following XML geometry values and `stroke-width` as finite unitless ordinary
499 decimals in the page `viewBox` coordinate space, for example `x="120"` and
500 `stroke-width="2"`. The explicit `px` suffix is read-compatible and receives a
501 recommendation warning. No other unit is registered for this surface.
502
503 | Element / surface | Direct length attributes |
504 |---|---|
505 | `<svg>`, `<rect>`, `<image>`, `<use>` | `x`, `y`, `width`, `height`; `<rect>` also `rx`, `ry` |
506 | `<circle>` | `cx`, `cy`, `r` |
507 | `<ellipse>` | `cx`, `cy`, `rx`, `ry` |
508 | `<line>` | `x1`, `y1`, `x2`, `y2` |
509 | `<text>` / positional `<tspan>` | `x`, `y`; `<tspan>` also `dx`, `dy` |
510 | Any supported painted element | `stroke-width` |
511
512 `width`, `height`, `r`, `rx`, `ry`, and `stroke-width` must be non-negative;
513 the stricter positive `<use>` symbol-viewport rule remains in §1.3. `pt`,
514 `pc` / `pica`, `in`, `cm`, `mm`, `q`, `em`, `rem`, percentages, unknown units,
515 non-finite values, expressions, scientific notation, leading plus signs, and
516 trailing decimal points are invalid here even when generic SVG/CSS defines
517 them. A missing attribute may use its documented SVG/project default; an
518 explicitly supplied invalid value never falls back to that default.
519
520 The following geometry properties may appear in the same element's
521 `style="..."`. The pipeline materializes them as
522 XML geometry attributes before SVG post-processing and native PPTX conversion.
523 An inline geometry declaration overrides an existing same-name XML attribute.
524
525 | Element | Recognized properties |
526 |---|---|
527 | `<rect>` | `x`, `y`, `width`, `height`, `rx`, `ry` |
528 | `<circle>` | `cx`, `cy`, `r` |
529 | `<ellipse>` | `cx`, `cy`, `rx`, `ry` |
530 | `<image>` | `x`, `y`, `width`, `height` |
531 | `<svg>` | `x`, `y`, `width`, `height` |
532 | `<use>` | `x`, `y`, `width`, `height` |
533
534 **Hard rule — inline geometry grammar**: every non-zero value is one finite
535 `px` literal, such as `120px` or `-8.5px`; exact zero may be unitless. `width`,
536 `height`, `rx`, `ry`, and `r` must be non-negative. Percentages, `auto`,
537 `calc()`, `var()`, `!important`, `inherit`, and every other unit are forbidden.
538 Do not put geometry on an unsupported element: line endpoints, text positions,
539 path data, and polygon/polyline points remain XML attributes.
540
541 **Forbidden — CSS geometry cascade**: `<style>`, `class`, selector rules,
542 external stylesheets, and imported styles remain forbidden. This contract is
543 only for literal declarations in an element's own `style` attribute; PPT Master
544 does not compute CSS cascade or custom properties. Root canvas authority remains
545 the `viewBox`, regardless of root `<svg>` compatibility width/height values.
546 The shared coordinate and geometry implementation is
547 [`utils.py`](../scripts/svg_to_pptx/drawingml/utils.py).
548
549 ### 2.2 Group Opacity Compatibility
550
551 **Default — descendant alpha (may preserve compatible group opacity)**: New
552 `svg_output/` and reusable templates put alpha on the affected descendant
553 paint, text run, picture, or supported effect. DrawingML has no isolated
554 group-alpha model, so overlapping descendants can look different when one
555 group value is distributed across them.
556
557 The converter nevertheless accepts `<g opacity="...">` and inline group
558 `opacity` by multiplying group alpha into descendants. That path is
559 `Approximate`; nested group/child alpha multiplies, and `--native-charts-and-tables`
560 rejects transparent native table/chart markers. The quality checker reports a
561 non-blocking fidelity warning so existing or intentionally authored input can
562 continue without modification.
563
564 ---
565
566 ## 3. Canvas Format Quick Reference
567
568 Use the already locked canvas id and exact viewBox. [`canvas-formats.md`](canvas-formats.md) owns format selection; this core owns only SVG conformance on that canvas. The lockless [`quick-generate`](../workflows/profiles/quick-generate.md) profile uses its first SVG to establish the canvas; every remaining page must use the identical viewBox.
569
570 ---
571
572 ## 4. Required Page Contract and Conditional Packaging
573
574 ### 4.0 Complete Page-Design Contract
575
576 | Concern | Requirement |
577 |---|---|
578 | Visible slide result | The completed `svg_output/<slide>.svg` MUST contain every visible text, image, shape, diagram, chart/table fallback, background, and template-derived layout element intended for that slide. External visual assets are valid when the SVG references them explicitly. |
579 | Template/control inputs | Templates, `design_spec.md`, and `spec_lock.md` guide authoring. Do not depend on them to add visible elements after the page SVG is complete. |
580 | PPTX translation | The exporter may map represented SVG content to DrawingML/native objects and deduplicate represented elements into Master/Layout/Slide parts. It MUST NOT invent visible slide content absent from the SVG. |
581 | Excluded package behavior | Speaker notes, animations, transitions, narration audio, PPTX relationships, and direct native-PPTX workflows remain separately owned. They are not part of the SVG page-design contract. |
582
583 **Hard rule — page-design closure**: A final page SVG is the sole visual/design authority for that page on every SVG-authoring route. SVG is not the authority for the entire PPTX package.
584
585 ### 4.1 Semantic SVG Marker Contract
586
587 Semantic markers are minimal compiler hints. Flat pages declare one root `data-pptx-page-role` and omit Master/Layout/layer/placeholder markers. Structured pages carry their final root identity, layer atoms, slots, and native-object metadata from authoring start and omit `data-pptx-page-role`. Use `data-pptx-role` with a stable `id` only when no specialized marker expresses page-frame behavior. Keep ordinary visible content in SVG attributes/text; [`semantic-svg.md`](semantic-svg.md) owns the vocabulary.
588
589 - **Canvas authority**: New authoring writes `viewBox="0 0 W H"` with positive
590 integer pixels from the lock, or from the first SVG when the explicit
591 `quick-generate` profile is active. Numerically equivalent spellings and positive
592 fractional imported dimensions remain compatible; export quantizes once at
593 `1 SVG px = 9,525 EMU`. Invalid/non-finite values, non-zero origin,
594 non-positive size, or unsupported PowerPoint dimensions are errors. All pages
595 and Layout prototypes in one normal build share the numeric canvas and match
596 `spec_lock.md canvas.viewBox`; quick-generate pages match the first SVG;
597 standalone templates match `design_spec.md canvas_viewbox`. Optional root
598 `width`/`height` do not override `viewBox`.
599 Root `<svg>` transform is forbidden; nested crop and `<symbol viewBox>` keep
600 their own contracts.
601 - **Font portability**: resolve an explicit user/template delivery target first;
602 otherwise default to Windows Microsoft PowerPoint with locale following the
603 deck's primary language. Exported Latin/EA faces must be installed or approved
604 on that target. The authoring host's fonts affect SVG preview and measurement
605 only and MUST NOT select PPTX faces; a local counterpart may appear only as a
606 preview tail that preserves the same export resolution. `@font-face` remains
607 forbidden; the typography contract lives in [`strategist.md §g`](strategist.md).
608 - **Icon placeholders**: `<use data-icon="library/name">` is a pipeline-specific
609 form, distinct from local SVG reuse. Follow the contract in
610 [`../templates/icons/README.md`](../templates/icons/README.md).
611 - **Local reuse**: ordinary same-document `<use>` follows §1.3.
612
613 ### 4.2 Editability, Package Promotion, and Text Leading
614
615 These forms are needed only when the stated PPT behavior matters:
616
617 | Desired behavior | Required form |
618 |---|---|
619 | One editable PPT text frame with mixed formatting or multiline prose | Use one `<text>` per logical paragraph and non-positional `<tspan>` children for inline runs. Keep the first authored line as direct text; later lines use direct positioned `<tspan>` children that repeat parent `x` with positive relative `dy`; an all-`<tspan>` form may start at `dy="0"`. Default retains these breaks without PowerPoint wrapping; `--reflow-text` may join eligible lines. A font-size change, list marker, or larger accepted gap starts another paragraph. Sibling `<text>` elements are forbidden as one paragraph's line breaks; they remain valid for independent frames. |
620 | Stable object grouping or object-level animation anchor | Wrap the intended object in `<g id="...">`. Content grouping is **mandatory** per §4.3 — a top-level `<g id>` is also the animation anchor; it is not an optional convenience. |
621 | Native PowerPoint background promotion | Outside structured mode, the first eligible visual layer may be a direct full-canvas `<rect>` or one inside a simple single-child group. Its fill must have a registered native mapping (solid, linear/radial gradient, or preset pattern), and it must have no transform, filter, clip, rounding, or visible stroke. Export writes the fill as Slide `p:bg`; image elements remain pictures. Structured routes use the narrower explicit solid-background ownership contract in [`pptx-structure-interface.md`](./pptx-structure-interface.md). |
622 | Free-design / brand-only PowerPoint structure | Use `pptx_structure.mode: flat`. Keep every represented object Slide-local; export materializes one clean project-owned Master plus one Blank Layout from the current lock, removes stock content placeholders/Layout inventory, and retains only the standard date/footer/slide-number capability hooks. Do not author Master/Layout identities, layers, or placeholder slots. Quick-generate uses the same flat object ownership but converter-default theme scaffolding because no lock exists. |
623 | Reusable template-based PowerPoint Layout | Select one complete authoring SVG per page in `page_layouts`, declare each unique Master/Layout definition once, and assign pages through `page_pptx_layouts`. Strict preserves the prototype contract; adaptive retains its Master and uses a current or new Layout key already declared and assigned by Strategist. Construction cannot extend or mutate that mapping downstream. Non-mirror skin follows `spec_lock`. |
624
625 **Default — leading by role and density (may be overridden for user, template, typeface, legibility, or locked visual-style fit)**: For direct positioned `<tspan>` rows, start multiline titles around `1.2–1.3 × font-size`, dense / small body around `1.4–1.5 ×`, ordinary body around `1.5–1.6 ×`, and large / sparse / breathing body around `1.6–2.0 ×`. These are starting ranges, not checker quotas; display headlines may be tighter when the selected style calls for it. Author the spacing as positive relative `dy`, not CSS/SVG `line-height`, which has no registered DrawingML mapping.
626
627 **Hard rule — supported shape conversion**: Every PPT editability claim in this specification refers to the project converter reading `svg_output/` and emitting native DrawingML. `svg_final/` is a self-contained visual preview that may be inserted into PowerPoint as an SVG picture. PowerPoint's manual Convert-to-Shape operation is unsupported; do not narrow the authoring contract to its undocumented SVG subset.
628
629 ### 4.3 Element Grouping (Mandatory)
630
631 **Hard rule — root groups protect body-text layout**: Every visible direct root `<g>` except a compact helper-authored preset atom declares positive root-coordinate `data-pptx-bounds="x y width height"`. That text-free atom stays top-level when standalone, uses `data-pptx-frame`, and never carries bounds. Frame/native coordinates do not replace bounds on any other group; placeholder bounds also supply the slot frame. On flat pages, make each module zone as generous as the canvas and sibling layout allow without overlapping another module zone. Checker validates this subcanvas against the root `viewBox`, then recursively validates only estimable `<text>` descendants against it using the shared SVG-to-PPTX per-run width estimate, inline-formula native-height envelope, and DrawingML wrapping headroom. It validates every estimable visible text carrier directly against the root `viewBox` with the same per-run estimate before that headroom. Nested groups and all shapes, images, paths, `<use>` instances, effects, and object frames are not module-boundary inputs. Per side, Checker ignores overflow through `1px`; module-boundary overflow warns through `5%` and fails above `5%`, while any larger root-`viewBox` text overflow fails. Bounds do not clip or reflow; unestimable visible text receives an advisory warning. The only page-boundary exception is a wholly off-canvas direct-root Morph endpoint marked `data-pptx-morph-staging="true"`; its own module bounds still apply, retained Morph uses an explicit pair, and the marker never excuses partial page overflow.
632
633 Wrap each logical Slide-local body unit in one descriptive top-level `<g id>`; group count follows the page's semantic units, and each group becomes one stable animation target when animation is enabled. Generic deck-wide animation gives that target one step; an explicit animation sidecar may assign it several ordered effects. Nested implementation groups may remain anonymous and need no bounds; any nested bounds are ignored. Flat pages use ordinary groups; structured slots already qualify, while titles, direct atomic Master/Layout elements, and canvas-level static framing—including background images and full-canvas scrim/decoration rectangles—may remain root primitives. On flat pages, give such static framing a stable `id` plus `data-pptx-role="background"` / `"decoration"`; never add a `<g>` solely to silence an ungrouped-element advisory.
634
635 **Reference — not a constraint**: A top-level semantic group may contain
636 descriptive nested `<g>` edit groups when its internal elements form useful
637 subunits, such as icon + title, value + label, or repeated information rows.
638 Nested groups carry no `data-pptx-bounds` and create no automatic animation
639 step; an unnecessary one-child wrapper may flatten. Choose whether and how
640 deeply to nest from the page's actual editing semantics—there is no default
641 nesting pattern, level, or quota.
642
643 **Structural atoms and slots are excluded automatically.** `data-pptx-layer` and `data-pptx-placeholder` semantics are read first; otherwise explicit `data-pptx-role` values (`background`, `decoration`, `header`, `footer`, `chrome`, `watermark`, `page-number`, `logo`) mark Slide-local static framing (§4.1, [`semantic-svg.md`](semantic-svg.md)). A normal slot group has exactly one direct compatible carrier; several drawing atoms require the explicit composite `object` proxy fallback. Native chart/table carrier groups retain their specialized [`native-data-interface.md`](./native-data-interface.md) contract.
644
645 **What to group** (one `<g id>` per unit):
646
647 | Grouping unit | Contains |
648 |---|---|
649 | Card / panel | Background rect + optional shadow (only if it floats over a photo/colored panel, [`svg-effects.md`](./svg-effects.md) §6.4) + icon + title + body text |
650 | Process step | Number/marker + icon + label + description |
651 | List item | Bullet / number + icon + title + description |
652 | Icon-text combo | Icon element + adjacent label |
653 | Page header | Title + subtitle + accent decoration |
654 | Page footer | Page number + branding |
655 | Decorative cluster | Related decorative shapes (rings, dots, orbs) |
656
657 An authored native preset fragment (§1.5) is already an atomic `<g id>` and
658 counts as one content group. Keep it top-level without `data-pptx-bounds` when
659 it stands alone. When it needs a label or decoration, place the preset and those
660 siblings inside a separate bounded parent content group; never put them inside
661 the preset group itself.
662
663 **Forbidden**:
664
665 - One giant `<g>` around the whole slide (collapses to a single animation step).
666 - Many ungrouped Slide-local `<rect>` / `<text>` / `<path>` atoms — they have no stable sidecar target and selection/editing degrades. Primitive fallback applies only when the root contains no top-level `<g>` at all; it is capped at 8 visible primitives.
667 - One top-level group per icon / text line / mark (too many animation steps).
668 - Anonymous top-level groups — every top-level semantic group needs a descriptive `id`.
669
670 **Naming — required.** A descriptive, page-unique `id` on every top-level content `<g>` (`card-1`, `step-discover`, `header`, `footer`) is mandatory; it is the stable SVG-side animation and trace anchor. An anonymous top-level group still converts, but `animations.json` cannot reference it; an anonymous one-child implementation wrapper may also flatten. Primitive fallback is unrelated and applies only to roots with no top-level groups.
671
672 ```xml
673 <g id="card-benefits-1" data-pptx-bounds="60 115 565 260">
674 <!-- Shadow only if the card floats over a colored panel; on flat white, omit it. -->
675 <rect x="60" y="115" width="565" height="260" rx="20" fill="#FFFFFF" filter="url(#shadow)"/>
676 <use data-icon="chunk-filled/bolt" x="108" y="163" width="44" height="44" fill="#0071E3"/>
677 <g id="card-benefits-metric">
678 <text x="105" y="270" font-size="56" font-weight="bold" fill="#0071E3">10×</text>
679 <text x="250" y="270" font-size="30" font-weight="bold" fill="#1D1D1F">Faster</text>
680 </g>
681 <text x="105" y="310" font-size="18" fill="#6E6E73">Reduce production time from days to hours.</text>
682 </g>
683 ```
684
685 ---
686
687 ## 5. Workflow Authority
688
689 The normal serial post-processing and export workflow belongs to
690 [`generate-pptx.md`](../workflows/generate-pptx.md) Step 7. The explicit
691 direct-generation exception belongs to
692 [`quick-generate.md`](../workflows/profiles/quick-generate.md). This file defines SVG
693 authoring boundaries and intentionally does not mirror commands, flags, or
694 output behavior.
695
696 ---
697
698
699 ## 8. Scope Boundary
700
701 Generate project structure, commands, quality-gate order, and export products
702 are owned by [`generate-pptx.md`](../workflows/generate-pptx.md) and its
703 selected profile. They are intentionally outside this SVG authoring policy.
704
704 lines MARKDOWN