返回 ppt-master
animations.md
根目录 / skills / ppt-master / references / animations.md
1 # Page Transitions & Per-Element Animations
2
3 Execution contract for generated-PPTX **page transitions** and **per-element
4 object animations**, including deterministic Morph object pairing. This file
5 owns defaults, sidecar semantics, anchor selection, validation, and package
6 read-back.
7
8 ## Capability Menu — Open Here
9
10 Motion here is several separate capabilities, not one dial. Two of them are
11 decided **upstream, while pages are still being authored** — read this menu
12 before the page plan is frozen, not only when a deck is already exported.
13
14 | What the deck needs | Reach for | Decided at |
15 |---|---|---|
16 | Reveal content in step with the narration | Per-element object animation — `-a auto` for generic entrance reveals, or an `animations.json` sidecar for explicit enter/emphasize/move/exit/static lifecycle choreography | Post-processing; §2, §4, [`customize-animations`](../workflows/stages/customize-animations.md) |
17 | A continuous action — slide-in, flip, camera push-in, progressive reveal, camera pan | **Morph: author the action as two static pages, then select Morph and add explicit pairs when identity must be deterministic.** There is no keyframe timeline anywhere in this pipeline; the difference between two ordinary editable slides *is* the animation | **Page authoring (Step 6), then motion post-processing** — §2.1, §3.1 |
18 | A static full-bleed page that should stop looking frozen | Consider slow `path_*` motion on a visually subordinate image or atmospheric layer; §4.1 gives one starting recipe | Post-processing; §4.1 |
19 | Carousel, counting numerals, parallax depth, click-to-reveal flip card | Four recurring recipes assembled from the mechanisms above | §4.2 — the carousel and odometer both need paired pages |
20 | Kiosk or unattended playback | `--auto-advance <seconds>`, optionally with `-t none` | Export; §3 |
21 | Nothing should move | `-t none`, and leave per-element animation at its default `none` | Export; §1 |
22
23 **Hard rule — Morph geometry is an authoring decision; pairing is a later
24 execution decision**: export cannot invent the two visible endpoint states.
25 Author both consecutive pages while `svg_output/` is still being built. For
26 deterministic identity, expose each endpoint as a compatible direct-root group
27 and declare the pair in `animations.json` (§2.1); the source and destination ids
28 and geometry may differ. `-t morph` without explicit pairs leaves matching to
29 PowerPoint's heuristic and is not proof that the intended objects will tween.
30
31 **Reference — not a constraint**: per-element animation stays off by default
32 (§1). Auto-firing element builds on every page are an unsolicited "AI deck"
33 tell; each capability above earns its place per page, not per deck.
34
35 ---
36
37 ## 1. Defaults
38
39 | Layer | Default | Why |
40 |---|---|---|
41 | Page transition | CLI: `fade`, 0.4s | Calm baseline that suits most decks; the public Python builder retains its legacy 0.5s default |
42 | Per-element animation | **`none` (off)** | A page appears as a whole. Auto-firing element builds are an unsolicited "AI deck" tell, so object animation is opt-in. Turn on the content-aware canonical entrance policy with `-a auto`, or select one PowerPoint-native `entrance_*`, `emphasis_*`, `path_*`, or `exit_*` key explicitly |
43
44 To regenerate a deck with different settings, rerun the final checker when its current matching report is absent or stale, then rerun `svg_to_pptx.py` against the same `svg_output/`; the content-generation LLM need not rerun unless authored SVG requires repair. `-s final` is reserved for diagnostic comparison and is not a supported release source. To turn per-element animation on for the whole deck, pass `-a auto`.
45
46 ---
47
48 ## 2. Custom Object-Level Animation
49
50 Per-element animation is off by default. To enable generic entrance reveals
51 deck-wide, pass `-a auto` at export (no config needed). When a deck instead
52 needs a specific object lifecycle—for example enter, move, emphasize, then
53 exit—use the optional `animations.json` sidecar. The SVG remains the visual
54 source; the custom stage may rewrite its grouping hierarchy, ids, and bounds to
55 create better semantic anchors without changing visible output, while the
56 sidecar controls PPTX animation behavior.
57
58 Run the [`customize-animations`](../workflows/stages/customize-animations.md)
59 post-processing stage when the project already carries `animations.json`, when
60 the user explicitly asks to tune animation order/effects/timing/object-level
61 reveals, or when the effective Custom Animations outcome in
62 `design_spec.md §I` is enabled. A §IX `Motion suggestion` remains Strategist
63 advice and informs an active pass, but never triggers the stage alone.
64
65 **Hard rule — semantic anchors before object-targeted sidecar entries**: when
66 object animation is in scope, derive motion units and their lifecycle duties
67 from page meaning and narration, then regroup coarse/fragmented Slide-local
68 content without changing its appearance. Only post-regroup top-level ids are
69 valid object targets.
70
71 ```bash
72 # Inspect the real anchors after the semantic regrouping pass
73 python3 skills/ppt-master/scripts/animation_config.py list-groups <project>
74
75 # Build a neutral editable scaffold from the post-regroup anchors when useful
76 python3 skills/ppt-master/scripts/animation_config.py scaffold <project>
77
78 # Validate references before export
79 python3 skills/ppt-master/scripts/animation_config.py validate <project>
80
81 # Export reads <project>/animations.json automatically when present
82 python3 skills/ppt-master/scripts/svg_to_pptx.py <project>
83 ```
84
85 The scaffold keeps `defaults.animation.effect: none` and may list untouched
86 groups as empty `{}` placeholders; creating it does not opt the deck into
87 object motion. Populate only adopted motion units.
88
89 Sparse sidecar excerpt (unlisted slides inherit resolved defaults):
90
91 ```json
92 {
93 "version": 1,
94 "slides": {
95 "03_threshold": {
96 "groups": {
97 "risk-marker": {
98 "effects": [
99 { "effect": "entrance_fade", "order": 1, "duration": 0.25 },
100 { "effect": "path_right", "effect_options": { "relative": true }, "order": 2, "duration": 0.7 },
101 { "effect": "emphasis_teeter", "order": 3, "duration": 0.45 },
102 { "effect": "exit_fade", "order": 4, "duration": 0.3 }
103 ]
104 }
105 }
106 }
107 }
108 }
109 ```
110
111 Rules:
112
113 - `slides` keys match SVG stems (`03_market.svg` → `03_market`).
114 - `groups` keys match top-level `<g id="...">` anchors.
115 - A populated group block chooses exactly one representation: the
116 backward-compatible single-effect object, or
117 `{ "effects": [row, ...] }`. `effects` is non-empty and mutually exclusive
118 with every legacy single-effect field; each row explicitly names `effect`.
119 An untouched scaffold `{}` remains a neutral placeholder.
120 - `effect: none` in the legacy form removes that group from the object-animation
121 sequence and is useful for overriding inherited generic animation.
122 - `effects[]` permits the same PowerPoint shape to carry several Animation Pane
123 rows. `order` sorts ordinary rows across the slide; ties retain SVG group
124 order and then array order. `trigger_shape` rows keep that relative ordering
125 in separate interactive sequences rather than interleaving with the main
126 sequence. Ordering never changes slide layering.
127 - `delay` is seconds added to that row's resolved Start.
128 - `trigger` may be set per legacy row or `effects[]` row; otherwise it inherits
129 the resolved slide Start mode.
130 - `trigger_shape` is a row-specific reference to another unique, triggerable
131 top-level group. It maps to PowerPoint **Trigger → On Click of**, makes only
132 that row interactive, and uses `delay` as `TriggerDelayTime`. It implies
133 `on-click`; an explicit row `trigger` may accompany it only when also
134 `on-click`.
135 - `duration` overrides the per-row schedule duration. `entrance_appear`
136 remains a 1ms visibility flip, and instantaneous native emphasis presets
137 retain their PowerPoint-authored duration; the configured value still spaces
138 the next `after-previous` row.
139 - `effect_options` requires an explicit canonical `effect` in the same legacy
140 block or `effects[]` row and accepts only parameters PowerPoint exposes for
141 that effect:
142
143 | Option | Applies to |
144 |---|---|
145 | `direction` | Directional Fly/Crawl/Wipe/Peek/Strips/Split/Stretch/Zoom and related entrance/exit effects |
146 | `amount` | Wheel spokes (`1`, `2`, `3`, `4`, `8`), emphasis Spin degrees, or Transparency ratio |
147 | `color` | Color-capable emphasis effects; `#RRGGBB` or `theme:<scheme-color>` |
148 | `font_name` | Change Font; required for `emphasis_change_font`; one installed PowerPoint face, not a CSS list |
149 | `size` | Grow/Shrink |
150 | `relative` | Motion paths (`true` = shape-relative, `false` = fixed slide path) |
151 - Any animation block or effect row may set `repeat_count` or `repeat_duration`
152 (mutually exclusive), `auto_reverse`, `rewind`, `accelerate`, `decelerate`,
153 `bounce_end`, `restart`, `after_effect`, and `sound`. Ratios are `0..1`;
154 `bounce_end` requires an interpolated behavior and cannot combine with
155 `decelerate`; `restart` is `always`, `when-not-active`, or `never`;
156 `after_effect` is `none`, `dim` (with `color`), `hide`, or
157 `hide-on-next-click`; `sound` is a project-relative or absolute `.m4a`,
158 `.mp3`, or `.wav` path.
159 - `Speed` and smooth start/end are not duplicate sidecar fields: they are
160 derived from `duration` and `accelerate`/`decelerate`.
161 - This is the complete parameter surface for the generated top-level-group
162 target model, including multiple ordered effects on one group. PowerPoint
163 paragraph/text-range build fields are intentionally absent because grouped
164 SVG content is not emitted as paragraph builds; media play/pause/stop
165 commands remain in the audio/video workflows.
166 - Run `python3 skills/ppt-master/scripts/pptx_animations.py --describe
167 <canonical_effect>` for that effect's exact option values and full parameter
168 contract.
169 - `--animation none` overrides the sidecar and disables all per-element animation.
170 - An explicit sidecar group may override the legacy chrome-name heuristic, but it cannot override `data-pptx-layer` or an explicit static role/placeholder marker.
171 - Unknown effects, modes, or triggers and invalid numeric/order fields fail validation; no fallback effect is substituted.
172
173 **Inheritance**: the sidecar and its `defaults` block are optional. Unlisted
174 slides and omitted slide fields inherit `defaults.transition` /
175 `defaults.animation`, then CLI/exporter resolution. Explicit CLI flags override
176 the corresponding sidecar default/slide fields; explicit group overrides remain
177 unless `-a none` hard-disables all object motion. Groups inherit the resolved
178 slide duration, Start mode, timing modifiers, after-effect, and sound into each
179 legacy or `effects[]` row. `effect_options` remains coupled to an explicit
180 effect; `trigger_shape` is never inherited; omitted `order`/`delay` use
181 exporter defaults.
182
183 ### 2.1 Deterministic Morph Object Pairing
184
185 When one semantic object continues across two adjacent slides, the destination
186 slide may declare explicit forced-Morph pairs. This is separate from `groups`:
187 Morph owns cross-slide identity, while `groups` owns Animation Pane rows.
188 The generated names follow Microsoft's
189 [forced object-matching convention](https://support.microsoft.com/en-us/powerpoint/morph-transition-tips-and-tricks).
190
191 ```json
192 {
193 "version": 1,
194 "slides": {
195 "02_detail": {
196 "transition": {
197 "effect": "morph",
198 "effect_options": { "morph_by": "object" },
199 "duration": 0.8
200 },
201 "morph": {
202 "from": "01_overview",
203 "pairs": {
204 "hero-image": {
205 "from": "hero-overview",
206 "to": "hero-detail"
207 }
208 }
209 }
210 }
211 }
212 }
213 ```
214
215 - `morph` belongs to the destination slide. `morph.from` must be the
216 immediately preceding SVG stem in export order.
217 - `animation_config.py scaffold` never guesses cross-slide identity. Add pairs
218 from the semantic motion plan after inspecting the final direct-root ids.
219 - Each `pairs` key is a stable identity; its `from` and `to` values are unique
220 direct-root `<g id>` values on the source and destination slides. Supply the
221 key without `!!`; export writes the PowerPoint Selection Pane name
222 `!!<key>` on both objects.
223 - A destination with explicit pairs must explicitly set `effect: morph`.
224 `morph_by` may be omitted for its `object` default or set to `object`;
225 `word`/`character` are rejected. A CLI transition override that changes the
226 resolved effect fails export.
227 - A middle slide may continue the same object into another Morph transition,
228 but the same group must retain the same key. One key cannot name two objects
229 on one slide, and one object cannot carry two keys. Every `!!` key shared by
230 two adjacent Morph pages must be declared in that destination's `pairs`;
231 undeclared forced matches are rejected.
232 - Explicit pairing can coexist with in-slide object animation and remains
233 active when `-a none` disables Animation Pane rows. `--no-animations`
234 disables the sidecar and all page/object motion.
235 - The exporter resolves both group ids to final Slide-local PowerPoint shapes,
236 writes names only after Master/Layout processing, then reopens the package
237 and verifies adjacency, Morph by object, one name per slide, and matching
238 OOXML object types. Missing, structural, moved, ambiguous, or mismatched
239 targets fail instead of falling back to automatic Morph matching.
240
241 ---
242
243 ## 3. Page Transitions
244
245 **Reference — not a constraint**: choose a transition from the relationship
246 between adjacent pages, not from gallery coverage. Run this playbook before
247 selecting a canonical key:
248
249 | Pass | Decision |
250 |---|---|
251 | Relate | Decide whether the destination continues the same object or space, advances in a meaningful direction, opens a new section, or intentionally breaks continuity. |
252 | Diagnose | Name the transition's job: neutral continuity, immediate cut, directional progress, object/state continuity, spatial movement, or a deliberate thematic beat. |
253 | Select | Use the smallest family that performs that job; keep `fade` when no stronger relationship exists. |
254 | Coordinate | Align direction, duration, and recurrence with reading order, narration, and the deck's established motion language. |
255 | Stop | Keep `fade` or `none` when another effect adds no meaning; never vary transitions for catalog coverage. |
256
257 | Page relationship | Candidate family |
258 |---|---|
259 | Ordinary continuation within one section | `fade` |
260 | Immediate change with no continuity to preserve | `none` or `cut` |
261 | Directional steps, timeline, or layer progression | `push` / `wipe`; use `cover` / `uncover` when an overlay relationship is visible |
262 | The same semantic object or scene changes across adjacent pages | `morph`; use §2.1 pairs when identity must be deterministic |
263 | Section opening, key reveal, or marked state boundary | Selective `split` / `reveal` / `shape` / `flash` / `random_bars` |
264 | A repeated collection advances through one spatial frame | `pan` / `conveyor` / `ferris_wheel`; use the §4.2 Morph carousel when individual cards need deterministic identity |
265 | The viewpoint travels around or through a continuous space | `rotate` / `window` / `orbit` / `fly_through` |
266 | The narrative or theme supports a stage, paper, or physical-page metaphor | Selective `fall_over` / `drape` / `curtains` / `wind` / `prestige` / `peel_off` / `page_curl` / `airplane` / `origami` / `doors` |
267 | A disruptive beat represents breakage, collapse, or dispersal | Selective `fracture` / `crush` / `dissolve` / `vortex` / `shred` |
268 | A marked reveal benefits from a geometric, timed, or textured pattern | Selective `checkerboard` / `blinds` / `clock` / `ripple` / `honeycomb` / `glitter` / `comb` |
269 | A card, panel, gallery, or viewpoint visibly turns or changes face | Selective `switch` / `flip` / `gallery` / `cube` / `box` / `zoom` |
270 | Unpredictability is itself the requested behavior | `random`; never use it merely to create variety |
271
272 ```bash
273 # Pick a different effect
274 python3 skills/ppt-master/scripts/svg_to_pptx.py <project> -t push --transition-duration 0.6
275
276 # Remove the visual transition
277 python3 skills/ppt-master/scripts/svg_to_pptx.py <project> -t none
278
279 # Auto-advance every 5 seconds (kiosk-style playback)
280 python3 skills/ppt-master/scripts/svg_to_pptx.py <project> --auto-advance 5
281
282 # Auto-advance with no visual transition
283 python3 skills/ppt-master/scripts/svg_to_pptx.py <project> -t none --auto-advance 5
284 ```
285
286 The native registry covers PowerPoint's complete Subtle, Exciting, and Dynamic
287 Content gallery: 48 canonical keys. New selection, sidecars, plans, conversion
288 traces, and writers use only those keys. Run `pptx_animations.py --list` for
289 the categorized identifiers.
290
291 Eight old low-level names remain accepted only as compatibility inputs. They
292 desugar to a native key plus native `effect_options`: for example, `diamond`
293 becomes `shape` with `shape: diamond`, and `wedge` becomes `clock` with
294 `style: wedge`. They are never selected for new output.
295
296 Effects expose their real PowerPoint Effect Options through
297 `transition.effect_options`. Common examples include Push/Wipe direction,
298 Morph by object/word/character, Reveal through black, Shape geometry, Page
299 Curl direction/pages, Glitter pattern/direction, and Fly Through bounce. Run
300 `pptx_animations.py --describe-transition <effect>` for the exact
301 effect-specific contract; unknown or inapplicable options fail validation.
302 `none` removes the visual effect. Effects that require newer Office namespaces
303 carry a real PowerPoint effect in `mc:Choice` and a `fade` fallback for older
304 consumers; validation requires the requested primary effect and never accepts
305 the fallback as a silent substitute.
306
307 Flags:
308
309 - `-t/--transition` — native effect name, compatibility input, or `none` for no visual transition. Default: `fade`. `none` does not remove an explicitly configured automatic advance.
310 - `--transition-duration` — seconds, default `0.4`.
311 - `--auto-advance` — seconds; click remains enabled, so the slide advances on click or when the timer expires. Omit for presenter-controlled advance.
312
313 **Hard rule — no silent downgrade**: an unknown transition effect, unsupported Effect Option, or invalid/non-finite duration fails export. It is never replaced by `fade`. Recorded narration keeps the resolved visual transition; `-t none --recorded-narration ...` writes narration-driven advance timing without restoring a visual effect.
314
315 ### 3.1 Morph — author an action as the difference between two pages
316
317 Morph tweens objects it can match across consecutive slides. That makes it a general mechanism, not just a transition: **any continuous action can be authored as two static pages plus a Morph transition**, with no keyframe timeline anywhere. Duplicate the page, change one property on one object, and PowerPoint interpolates the rest. Use §2.1 explicit pairs when the match must be deterministic.
318
319 | Change between the two pages | Reads as |
320 |---|---|
321 | Object sits off-canvas, then on-canvas | Slide-in, drawer pull, card extending |
322 | Object rotates | Flip, turn, hinge |
323 | Image container scales up | Camera push-in |
324 | Scrim opacity drops, or a cut contour grows | Progressive reveal |
325 | Same wide image at two `x` offsets | Camera pan (see image-layout-patterns `#C2-01`) |
326
327 Chain three or more pages to build a sequence — extend, hold, retract — where each page is still an ordinary editable slide.
328
329 **Hard rule — matching needs compatible object identity, not identical SVG
330 geometry**: for generated decks, prefer §2.1 deterministic pairs. The source
331 and destination direct-root group ids may differ, and position, size, crop, or
332 other visible state is expected to change; both endpoints must still resolve to
333 one compatible top-level PowerPoint object kind. Automatic Morph without pairs
334 is heuristic and may cross-fade instead of tweening.
335
336 **Give text somewhere to come from.** Morph tweens objects present on both pages; text that only exists on the second page can only fade in. The standard fix is to place the *next* page's copy on the current page just outside the canvas (below), and the *previous* page's copy just outside the opposite edge (above). Each block then slides through the frame instead of blinking, and the deck reads as one continuous surface being scrolled. A wholly off-canvas endpoint must be one direct-root `<g id>` with valid `data-pptx-bounds` and `data-pptx-morph-staging="true"`; when Morph remains enabled, pair it explicitly under §2.1. The marker only declares an intentional invisible endpoint; it cannot excuse a partially clipped group or text carrier.
337
338 **When Morph refuses to match**: PowerPoint pairs compatible object kinds; a
339 shape and a picture will cross-fade instead of tweening. For generated pages,
340 declare the identity through the destination slide's `morph` block (§2.1).
341 The exporter writes the shared `!!<key>` name after structure processing and
342 reads the package back. Do not author `data-pptx-shape-name` for this purpose;
343 that attribute remains importer metadata for mirror/preserve packages
344 ([`svg-effects.md`](./svg-effects.md) §6.6).
345
346 **Not supported — Slide Zoom / Summary Zoom.** Click-to-jump navigation built on PowerPoint's Zoom objects (the "click a portrait, zoom into that section" pattern) has no exporter path. Build click-driven navigation with `trigger_shape` on ordinary object animations instead, or with plain hyperlinks.
347
348 **No 3D**: perspective rotation, extrusion, and shear are outside the SVG contract — `skewX` / `skewY` and shear matrices fail closed ([`svg-effects.md`](./svg-effects.md) §6.8). Build the same impression with 2D means — offset, scale, overlap, and per-facet lightness — rather than attempting a 3D tilt.
349
350 ---
351
352 ## 4. Per-Element Animations
353
354 Off by default — enable deck-wide with `-a auto` (or another effect). Once enabled, three Start modes are available — these mirror PowerPoint's animation-pane "Start" dropdown:
355
356 - **`on-click`** — each click reveals the next group. Use only for a controlled semantic reveal; live delivery alone is insufficient. Forbidden with `--recorded-narration`.
357 - **`with-previous`** — groups start together as one coordinated beat. Stagger ignored.
358 - **`after-previous`** (default) — click-free cascade on slide entry with `--animation-stagger` spacing. Use when controlled reveals are unnecessary.
359
360 **Default — coherent Start rhythm (may override when a semantic beat needs
361 different control)**: Keep one dominant deck rhythm and normally one mode per
362 slide. Mix only for a distinct simultaneous or presenter-controlled beat.
363
364 Enable with `-a auto`, select a canonical effect with
365 `--animation entrance_fade`, and choose Start behavior with
366 `--animation-trigger on-click|with-previous|after-previous`.
367
368 PowerPoint's separate **Trigger → On Click of** behavior uses row-specific
369 `trigger_shape`. It links that row to another top-level group while unlinked
370 rows keep the slide Start mode; it is not a fourth deck-wide Start mode.
371
372 **Mandatory — lifecycle before effect selection**: start from `static`, then
373 classify semantic `initial → action → end` before choosing an effect. Generic
374 staged reveals normally use `enter`; narrower communication jobs select their
375 matching lifecycle instead.
376
377 | Duty | State contract | Use when | Effect family |
378 |---|---|---|---|
379 | `static` | present → hold as reference → present | Motion adds no clarity or intended feeling | No row; legacy `effect: none` only suppresses inheritance |
380 | `enter` | absent → introduce → present | Information should be withheld, ordered, or revealed with narration | `entrance_*`; modes only for generic reveal |
381 | `emphasize` | present → redirect attention → present/altered | An already visible object must regain attention or show a local change; never substitute for its first reveal | Explicit `emphasis_*` |
382 | `move` | state/position A → progress → state/position B | The trajectory carries spatial or causal meaning, or §4.1 adopts subordinate ambient motion; use Morph for cross-page continuity | Explicit `path_*`, or endpoint pages + Morph |
383 | `exit` | present → retire → absent | The same slide must remove, replace, or make room for content; an ordinary page change needs no object exit | Explicit `exit_*` |
384
385 **Default — restrained entrance-led choreography (may override for content,
386 tone, or the request)**: Use entrances for ordinary builds. Add emphasis or
387 exit sparingly, only for a real duty and fitting effect. Multiple `effects[]`
388 rows require multiple duties.
389
390 The registry exposes two layers:
391
392 - **203 PowerPoint-native object presets**: 53 `entrance_*` presets, 33
393 `emphasis_*` effects, 64 `path_*` motion paths, and 53 `exit_*` effects.
394 Examples include `entrance_bounce`, `emphasis_spin`, `path_circle`, and
395 `exit_faded_zoom`. Each native key carries the complete PowerPoint-authored
396 behavior tree, not a generic filter approximation.
397 - **29 legacy compatibility inputs**, listed by `--list`; new output never
398 selects them.
399
400 Run the registry command for the exact categorized key list:
401
402 ```bash
403 python3 skills/ppt-master/scripts/pptx_animations.py --list
404 ```
405
406 Compatibility names normalize before selection and writing: for example,
407 `fade` resolves to `entrance_fade`; every old Fly direction name resolves to
408 `entrance_fly`; every old Wipe direction name resolves to `entrance_wipe`; and
409 `cut` resolves to `entrance_appear` because current PowerPoint has no separate
410 Cut object effect. Directional aliases preserve their old direction through
411 `effect_options`; legacy `wheel` maps to `entrance_wheel` with four spokes.
412 These names are accepted only as compatibility inputs.
413 Automatic selection, new sidecars, conversion traces, and writers use
414 canonical keys.
415
416 The native keys mirror the object-capable `MsoAnimEffect` surface. The four
417 media commands—play, pause, stop, and play from bookmark—are not object effects
418 for SVG groups and remain owned by the audio/video workflows.
419
420 - `auto` handles generic `enter` duties only and maps semantic ids to canonical entrances: charts/tables/timelines use
421 `entrance_wipe`; cards/steps use `entrance_fly`; titles/takeaways use
422 `entrance_fade`; image-like ids cycle a richer pool; unmatched ids cycle
423 fade/wipe/fly/zoom.
424 - `mixed` (legacy mode name) handles generic `enter` duties only and is
425 deterministic. The first animated group on each
426 slide uses `entrance_fade`; later groups cycle through a 16-effect canonical
427 PowerPoint entrance pool across the deck. The mode name remains compatible;
428 it no longer selects hand-authored compatibility rows.
429 - `random` handles generic `enter` duties only and samples from the same
430 canonical PowerPoint entrance pool.
431 Resolution is seeded from the effective deck input, so the same input
432 produces the same choices; `--conversion-trace` records every resolved effect
433 when diagnostics are enabled.
434
435 `entrance_appear` is excluded from every variation pool because it has no
436 visible motion. `auto`, `mixed`, and `random` never satisfy an adopted
437 `emphasize`, `move`, or `exit` duty; those require explicit canonical effects.
438
439 Flags: `-a/--animation` selects effect/mode; `--animation-trigger` selects Start;
440 `--animation-duration` and `--animation-stagger` control base timing;
441 `--animation-config` selects a sidecar; `--no-animations` disables page/object
442 motion but preserves narration audio and recorded advance timing.
443
444 > Note: `--recorded-narration` rejects `on-click` and `trigger_shape`. When either animation sidecar exists, narrated export selects `narration_animations.json`; canonical `animations.json` without that derived file remains a synchronization error. Without sidecars, pass `--inherit-motion-from <base_postflight_report>` for the base deck motion. Pass `--animation-config animations.json` for canonical animation, or `--no-animations` to remove page and object motion.
445
446 ### 4.1 Slow ambient motion — the page that breathes
447
448 **Reference — not a constraint**: ambient motion can keep a static page from
449 feeling frozen when it remains visually subordinate to the message. A common
450 starting recipe is `path_left` or `path_right` on a background image, started
451 `with-previous` and paced much more slowly than a content reveal. The same
452 principle may suit another atmospheric or non-information-bearing layer. Choose
453 duration, distance, and moving-object count from the composition and delivery
454 context.
455
456 Keep a full-bleed moving image covering the canvas at both endpoints; exposing
457 the slide beneath it is a visible failure.
458
459 It pairs naturally with a fixed foreground: with image-layout-patterns `#M1-07`, the scrim and its cut contour stay locked while the world moves behind the cuts, which reads as looking through windows rather than as a sliding photo. The same logic applies to `#M1-10` and `#P1-09`.
460
461 Motion remains subordinate: avoid competing ambient paths or movement that
462 reduces the readability of body copy or data. Multiple coordinated layers are
463 valid when they express one intentional depth or atmosphere relationship.
464
465 ### 4.2 Recurring recipes
466
467 Four combinations that recur constantly in authored decks. Each is built from
468 mechanisms already defined above — none needs a new capability.
469
470 **Carousel** (Morph, §2.1 and §3.1) — hold a fixed row of card frames and rotate the *content* through them: on each page every image advances one position, so the card at centre changes while the frames stay put. Explicitly pair each moving content unit across adjacent pages; the fixed frames stay static and need no pair. Scales to any number of images with one page each.
471
472 **Odometer / counting numerals** (morph or motion path) — build a vertical strip of digits 0–9 and show one through a fixed window formed by background-filled rectangles above and below ([`image-layout-patterns.md`](./image-layout-patterns.md) `#M1-08`). Shift the strip so the target digit lands in the window, then either morph between two pages or run a `path_up` motion on the strip. A small stagger, such as `0.1s`, can make digit columns settle in sequence; synchronized motion is also valid when it fits the intended rhythm.
473
474 **Parallax depth** (morph) — move a background layer a *short* distance and a foreground layer a longer one between two pages. The differing travel is read as depth. Keep both layers' z-order identical on both pages; a layer that changes stacking between pages breaks the tween and the transition jumps.
475
476 **Flip-card / click-to-reveal** (`trigger_shape`, §4) — pair a face group and a back group at the same position, give the face an exit and the back an entrance, and set the back's `trigger_shape` to the face's id. Clicking the face plays both. This is the supported route for click-driven interaction; PowerPoint's Zoom objects are not (§3.1).
477
478 ---
479
480 ## 5. Anchor Logic — Top-Level `<g id="...">`
481
482 Per-element animations are anchored on **top-level `<g id="...">` content
483 groups** in the SVG (e.g. `<g id="cover-title">`, `<g id="card-1">`). IDs must
484 be unique within the page. A backward-compatible single-effect group produces
485 one Animation Pane row; `effects[]` may produce several ordered rows targeting
486 the same PowerPoint shape. Each row inherits the slide Start mode unless it
487 declares its own `trigger`. Nested implementation groups may remain anonymous
488 because the sidecar does not target them.
489
490 **Hard rule — existing groups are not custom-animation intent**: the
491 pre-existing SVG hierarchy is implementation evidence, not an authoritative
492 motion plan. During the custom-animation stage, derive one group per logical
493 motion unit from claims, comparisons, sequence, causality, and narration beats;
494 split coarse wrappers and merge fragmented atoms when needed, then use
495 `list-groups` only after that rewrite. This is also the granularity PowerPoint
496 uses for group-select / group-move. Do not split or merge units to hit a target
497 count.
498
499 **Chrome stays static.** `data-pptx-layer` and explicit static
500 role/placeholder markers are absolute. For marker-free legacy SVGs, chrome-like
501 ids (background, header/footer, decor, watermark, page number, nav, logo, rule)
502 are skipped; an explicit sidecar entry may override only this name heuristic.
503 Keep wrappers and use `effect: none` for static content.
504
505 **Fallback for flat SVGs** (no top-level `<g>` wrappers, only raw `<rect>` / `<text>` / `<path>` at the root):
506
507 - ≤ 8 visible top-level primitives → each becomes one anchor (capped to avoid 70+ atom cascades on dense pages).
508 - > 8 → animation is skipped on that slide. The slide still renders, just without object animation.
509
510 Executors should wrap logical sections in `<g id>` regardless of whether you plan to animate. [`shared-standards-core.md`](./shared-standards-core.md) requires it.
511
512 ---
513
514 ## 6. Validation and Read-Back
515
516 Animation configuration is strict. Export fails on an unknown effect, mode, or
517 trigger; invalid timing/order values; a missing slide/group/`trigger_shape`
518 reference; a self-trigger; or any attempt to animate or trigger from a
519 structural layer. These errors never downgrade or silently omit a target.
520
521 Generated export reads each slide's timing tree back and checks row count/order,
522 including repeated rows on one shape, trigger, trigger shape, shape target,
523 preset class, resolved effect tuple, native behavior signature, duration, and
524 timeline offset. Package validation then checks root
525 timing placement, unique and valid `p:cTn` ids, and every `p:spTgt` reference.
526 Deterministic Morph additionally checks the final adjacent slide parts for the
527 requested `!!` names, one-to-one uniqueness, compatible object types, and a
528 real Morph-by-object transition on the destination.
529 The writer does not emit `p:bldP` for groups or pictures. Direct-PPTX preserve
530 mode tolerates unchanged legacy group/picture `p:bldP` rows from earlier PPT
531 Master exports; new generated packages remain strict.
532
533 Narration injection preserves animation and updates both p14 Choice/Fallback
534 when bounce timing is present; unsupported nested timing fails safely.
535 Direct-PPTX routes fingerprint source
536 object-animation timing before and after their allowed edits, then run
537 structural package validation; they do not author or normalize animation
538 effects.
539
540 ---
541
542 ## 7. Video Adaptation Contract
543
544 Video renderers consume the resolved conversion trace through
545 `video_motion_plan.py`, never a raw sidecar or delay-only inference. The plan
546 locks identity, order, effect, direction, and timing; video may refine only its
547 declared renderer parameters. Unsupported families fail visibly. See
548 [`video-motion-plan.md`](../scripts/docs/video-motion-plan.md).
549
550 ---
551
552 ## 8. Limitations
553
554 - Generated animation belongs to the native PPTX built from `svg_output/`.
555 `svg_final/` is a static preview, and inserting it as one SVG picture does
556 not create object anchors.
557 - PowerPoint OOXML is the compatibility target; other presentation apps may
558 reinterpret individual native behavior trees.
559 - Direct-PPTX routes preserve unknown transition `AlternateContent`; timing
560 edits keep Choice and Fallback advance attributes synchronized.
561
562 ---
563
564 ## 9. Implementation References
565
566 See [`svg-pipeline.md`](../scripts/docs/svg-pipeline.md),
567 [`pptx-transitions.md`](../scripts/docs/pptx-transitions.md),
568 [`pptx-animations.md`](../scripts/docs/pptx-animations.md), and
569 [`video-motion-plan.md`](../scripts/docs/video-motion-plan.md).
570
570 lines MARKDOWN