@editframe/create 0.44.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/index.js +16 -28
  2. package/dist/index.js.map +1 -1
  3. package/dist/skills/editframe-brand-video-generator/README.md +155 -0
  4. package/dist/skills/editframe-brand-video-generator/SKILL.md +207 -0
  5. package/dist/skills/editframe-brand-video-generator/references/brand-examples.md +178 -0
  6. package/dist/skills/editframe-brand-video-generator/references/color-psychology.md +227 -0
  7. package/dist/skills/editframe-brand-video-generator/references/composition-patterns.md +383 -0
  8. package/dist/skills/editframe-brand-video-generator/references/editing.md +66 -0
  9. package/dist/skills/editframe-brand-video-generator/references/emotional-arcs.md +496 -0
  10. package/dist/skills/editframe-brand-video-generator/references/genre-selection.md +135 -0
  11. package/dist/skills/editframe-brand-video-generator/references/transition-styles.md +611 -0
  12. package/dist/skills/editframe-brand-video-generator/references/typography-personalities.md +326 -0
  13. package/dist/skills/editframe-brand-video-generator/references/video-archetypes.md +86 -0
  14. package/dist/skills/editframe-brand-video-generator/references/video-fundamentals.md +169 -0
  15. package/dist/skills/editframe-brand-video-generator/references/visual-metaphors.md +50 -0
  16. package/dist/skills/editframe-composition/SKILL.md +169 -0
  17. package/dist/skills/editframe-composition/references/audio.md +483 -0
  18. package/dist/skills/editframe-composition/references/captions.md +844 -0
  19. package/dist/skills/editframe-composition/references/composition-model.md +73 -0
  20. package/dist/skills/editframe-composition/references/configuration.md +403 -0
  21. package/dist/skills/editframe-composition/references/css-parts.md +105 -0
  22. package/dist/skills/editframe-composition/references/css-variables.md +640 -0
  23. package/dist/skills/editframe-composition/references/entry-points.md +810 -0
  24. package/dist/skills/editframe-composition/references/events.md +499 -0
  25. package/dist/skills/editframe-composition/references/getting-started.md +259 -0
  26. package/dist/skills/editframe-composition/references/hooks.md +234 -0
  27. package/dist/skills/editframe-composition/references/image.md +241 -0
  28. package/dist/skills/editframe-composition/references/r3f.md +580 -0
  29. package/dist/skills/editframe-composition/references/render-api.md +484 -0
  30. package/dist/skills/editframe-composition/references/render-strategies.md +119 -0
  31. package/dist/skills/editframe-composition/references/render-to-video.md +1101 -0
  32. package/dist/skills/editframe-composition/references/scripting.md +606 -0
  33. package/dist/skills/editframe-composition/references/sequencing.md +116 -0
  34. package/dist/skills/editframe-composition/references/server-rendering.md +753 -0
  35. package/dist/skills/editframe-composition/references/surface.md +329 -0
  36. package/dist/skills/editframe-composition/references/text.md +627 -0
  37. package/dist/skills/editframe-composition/references/time-model.md +99 -0
  38. package/dist/skills/editframe-composition/references/timegroup-modes.md +102 -0
  39. package/dist/skills/editframe-composition/references/timegroup.md +457 -0
  40. package/dist/skills/editframe-composition/references/timeline-root.md +398 -0
  41. package/dist/skills/editframe-composition/references/transcription.md +47 -0
  42. package/dist/skills/editframe-composition/references/transitions.md +608 -0
  43. package/dist/skills/editframe-composition/references/use-media-info.md +357 -0
  44. package/dist/skills/editframe-composition/references/video.md +506 -0
  45. package/dist/skills/editframe-composition/references/waveform.md +327 -0
  46. package/dist/skills/editframe-editor-gui/SKILL.md +152 -0
  47. package/dist/skills/editframe-editor-gui/references/active-root-temporal.md +657 -0
  48. package/dist/skills/editframe-editor-gui/references/canvas.md +947 -0
  49. package/dist/skills/editframe-editor-gui/references/controls.md +366 -0
  50. package/dist/skills/editframe-editor-gui/references/dial.md +756 -0
  51. package/dist/skills/editframe-editor-gui/references/editor-toolkit.md +587 -0
  52. package/dist/skills/editframe-editor-gui/references/filmstrip.md +460 -0
  53. package/dist/skills/editframe-editor-gui/references/fit-scale.md +772 -0
  54. package/dist/skills/editframe-editor-gui/references/focus-overlay.md +561 -0
  55. package/dist/skills/editframe-editor-gui/references/hierarchy.md +544 -0
  56. package/dist/skills/editframe-editor-gui/references/overlay-item.md +634 -0
  57. package/dist/skills/editframe-editor-gui/references/overlay-layer.md +429 -0
  58. package/dist/skills/editframe-editor-gui/references/pan-zoom.md +568 -0
  59. package/dist/skills/editframe-editor-gui/references/pause.md +397 -0
  60. package/dist/skills/editframe-editor-gui/references/play.md +370 -0
  61. package/dist/skills/editframe-editor-gui/references/preview.md +391 -0
  62. package/dist/skills/editframe-editor-gui/references/resizable-box.md +749 -0
  63. package/dist/skills/editframe-editor-gui/references/scrubber.md +588 -0
  64. package/dist/skills/editframe-editor-gui/references/thumbnail-strip.md +566 -0
  65. package/dist/skills/editframe-editor-gui/references/time-display.md +492 -0
  66. package/dist/skills/editframe-editor-gui/references/timeline-ruler.md +489 -0
  67. package/dist/skills/editframe-editor-gui/references/timeline.md +604 -0
  68. package/dist/skills/editframe-editor-gui/references/toggle-loop.md +618 -0
  69. package/dist/skills/editframe-editor-gui/references/toggle-play.md +526 -0
  70. package/dist/skills/editframe-editor-gui/references/transform-handles.md +924 -0
  71. package/dist/skills/editframe-editor-gui/references/trim-handles.md +725 -0
  72. package/dist/skills/editframe-editor-gui/references/workbench.md +453 -0
  73. package/dist/skills/editframe-motion-design/SKILL.md +101 -0
  74. package/dist/skills/editframe-motion-design/references/0-editframe.md +299 -0
  75. package/dist/skills/editframe-motion-design/references/1-intent.md +201 -0
  76. package/dist/skills/editframe-motion-design/references/2-physics-model.md +405 -0
  77. package/dist/skills/editframe-motion-design/references/3-attention.md +350 -0
  78. package/dist/skills/editframe-motion-design/references/4-process.md +418 -0
  79. package/dist/skills/editframe-vite-plugin/SKILL.md +75 -0
  80. package/dist/skills/editframe-vite-plugin/references/file-api.md +111 -0
  81. package/dist/skills/editframe-vite-plugin/references/getting-started.md +96 -0
  82. package/dist/skills/editframe-vite-plugin/references/jit-transcoding.md +91 -0
  83. package/dist/skills/editframe-vite-plugin/references/local-assets.md +75 -0
  84. package/dist/skills/editframe-vite-plugin/references/visual-testing.md +136 -0
  85. package/dist/skills/editframe-webhooks/SKILL.md +126 -0
  86. package/dist/skills/editframe-webhooks/references/events.md +382 -0
  87. package/dist/skills/editframe-webhooks/references/getting-started.md +232 -0
  88. package/dist/skills/editframe-webhooks/references/security.md +418 -0
  89. package/dist/skills/editframe-webhooks/references/testing.md +409 -0
  90. package/dist/skills/editframe-webhooks/references/troubleshooting.md +457 -0
  91. package/dist/templates/html/AGENTS.md +13 -0
  92. package/dist/templates/react/AGENTS.md +13 -0
  93. package/dist/utils.js +15 -16
  94. package/dist/utils.js.map +1 -1
  95. package/package.json +1 -1
  96. package/tsdown.config.ts +4 -0
  97. package/dist/detectAgent.js +0 -89
  98. package/dist/detectAgent.js.map +0 -1
@@ -0,0 +1,383 @@
1
+ ---
2
+ title: Composition Patterns
3
+ description: Video composition patterns where motion is structural — not decorative. Each pattern includes the animation that makes it work.
4
+ type: reference
5
+ order: 3
6
+ ---
7
+
8
+ # Composition Patterns
9
+
10
+ Each pattern below includes the motion that earns it. A pattern without motion is a layout, not a video pattern.
11
+
12
+ ---
13
+
14
+ ## Word-by-Word Title Reveal
15
+
16
+ Text that builds itself word by word focuses attention on the message as it forms. Each word arriving at a slightly different moment creates rhythm that a static title cannot.
17
+
18
+ ```html live
19
+ <ef-timegroup mode="fixed" duration="4s" class="w-[720px] h-[400px] bg-black flex items-center justify-center">
20
+ <ef-text
21
+ split="word"
22
+ class="text-white text-5xl font-bold text-center max-w-2xl"
23
+ style="animation: 0.5s word-in both; animation-delay: calc(var(--ef-word-index) * 120ms)"
24
+ >The fastest way to ship video</ef-text>
25
+ </ef-timegroup>
26
+ <style>
27
+ @keyframes word-in {
28
+ from { transform: translateY(20px) scale(0.92); opacity: 0; }
29
+ to { transform: translateY(0) scale(1); opacity: 1; }
30
+ }
31
+ </style>
32
+ ```
33
+
34
+ **What motion adds:** Rhythm. The sequence of arrival directs reading order and emphasis. You can accelerate or decelerate the stagger to change the emotional register — tight spacing feels urgent, wide spacing feels deliberate.
35
+
36
+ ---
37
+
38
+ ## Scene with Animated Entry
39
+
40
+ Every element that appears should have a reason for how it arrives. A video background with text that enters from below reads as natural and alive. The same elements placed statically read as a screenshot.
41
+
42
+ ```html live
43
+ <ef-timegroup mode="contain" class="w-[720px] h-[400px] bg-black">
44
+ <ef-video src="https://assets.editframe.com/bars-n-tone.mp4" class="absolute inset-0 size-full object-cover"></ef-video>
45
+ <div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
46
+ <ef-text class="absolute bottom-8 left-8 text-white text-4xl font-bold"
47
+ style="animation: 0.7s enter-up both 0.3s">Your headline here</ef-text>
48
+ <ef-text class="absolute bottom-8 right-8 text-white/70 text-lg"
49
+ style="animation: 0.5s enter-up both 0.6s">supporting context</ef-text>
50
+ </ef-timegroup>
51
+ <style>
52
+ @keyframes enter-up {
53
+ from { transform: translateY(16px); opacity: 0; }
54
+ to { transform: translateY(0); opacity: 1; }
55
+ }
56
+ </style>
57
+ ```
58
+
59
+ **What motion adds:** The staggered entrances sequence the viewer's attention — headline first, then context. The delay prevents information overload at frame one.
60
+
61
+ ---
62
+
63
+ ## Crossfade Sequence
64
+
65
+ Scenes that share a visual or tonal relationship crossfade naturally. The overlap period — when both scenes are simultaneously visible — is where the transition does its narrative work.
66
+
67
+ ```html live
68
+ <ef-timegroup mode="sequence" overlap="1s" class="w-[720px] h-[400px] bg-black">
69
+ <ef-timegroup mode="contain" class="absolute w-full h-full"
70
+ style="animation: 1s fade-out var(--ef-transition-out-start) both">
71
+ <ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="0s" sourceout="3s" class="absolute inset-0 size-full object-cover"></ef-video>
72
+ <ef-text class="absolute bottom-8 left-8 text-white text-3xl font-bold"
73
+ style="animation: 0.6s enter-up both">Before</ef-text>
74
+ </ef-timegroup>
75
+ <ef-timegroup mode="contain" class="absolute w-full h-full"
76
+ style="animation: 1s fade-in both">
77
+ <ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="5s" sourceout="8s" class="absolute inset-0 size-full object-cover"></ef-video>
78
+ <ef-text class="absolute bottom-8 left-8 text-white text-3xl font-bold"
79
+ style="animation: 0.6s enter-up 0.4s both">After</ef-text>
80
+ </ef-timegroup>
81
+ </ef-timegroup>
82
+ <style>
83
+ @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
84
+ @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
85
+ @keyframes enter-up {
86
+ from { transform: translateY(16px); opacity: 0; }
87
+ to { transform: translateY(0); opacity: 1; }
88
+ }
89
+ </style>
90
+ ```
91
+
92
+ **What motion adds:** The overlap creates a moment of co-presence where both states are simultaneously true. Use this for before/after, problem/solution, or any narrative transition where the relationship between scenes matters.
93
+
94
+ ---
95
+
96
+ ## Ken Burns (Kinetic Image)
97
+
98
+ Still photography becomes temporal through slow motion. A 0.8% scale change per second, over 8 seconds, creates a sense of time passing and attention drifting into the image.
99
+
100
+ ```html live
101
+ <ef-timegroup mode="fixed" duration="8s" class="w-[720px] h-[400px] bg-black overflow-hidden">
102
+ <ef-image
103
+ src="https://assets.editframe.com/bars-n-tone.mp4"
104
+ class="absolute inset-0 size-full object-cover"
105
+ style="animation: 8s ken-burns both; transform-origin: center bottom"
106
+ ></ef-image>
107
+ <ef-text
108
+ split="word"
109
+ class="absolute bottom-8 left-8 text-white text-4xl font-bold"
110
+ style="animation: 0.8s enter-up both 1s; animation-delay: calc(1s + var(--ef-word-index) * 120ms)"
111
+ >The place they built it</ef-text>
112
+ </ef-timegroup>
113
+ <style>
114
+ @keyframes ken-burns {
115
+ from { transform: scale(1) translate(0, 0); }
116
+ to { transform: scale(1.12) translate(-1%, -1%); }
117
+ }
118
+ @keyframes enter-up {
119
+ from { transform: translateY(16px); opacity: 0; }
120
+ to { transform: translateY(0); opacity: 1; }
121
+ }
122
+ </style>
123
+ ```
124
+
125
+ **What motion adds:** Documentary weight. The imperceptible drift prevents the eye from settling, creating a sense of contemplation. The text arrives late — after the viewer has settled into the image.
126
+
127
+ ---
128
+
129
+ ## Procedural Canvas (frameTask)
130
+
131
+ **CRITICAL: Canvas Completeness Requirements**
132
+
133
+ A `<canvas>` element without a complete `addFrameTask` script is a broken composition that renders nothing.
134
+
135
+ **Before including ANY canvas element:**
136
+ 1. Write the COMPLETE script first, including the full `addFrameTask` callback with all closing braces
137
+ 2. Verify the script is not truncated — check that it ends with `});` and `</script>`
138
+ 3. If approaching output length limits, STOP and either: (a) simplify the canvas animation, (b) replace with CSS animation, or (c) merge the scene's content into an adjacent scene
139
+ 4. Never leave a canvas scene with placeholder or incomplete code — delete the scene entirely rather than ship broken motion
140
+ 5. **Output token awareness**: If you have generated more than 3,000 tokens of HTML/script content, STOP before adding any new canvas scene. Canvas scripts average 400–600 tokens. Incomplete scripts render as blank screens.
141
+ 6. **Verification step**: Before outputting the closing `</script>` tag, confirm the `addFrameTask` callback has: (a) a complete function body, (b) closing `});` for the callback, (c) closing `});` for the addFrameTask call. **Run this verification IMMEDIATELY after writing each canvas script, before starting the next scene.** Do not batch-verify at the end—by then, output limits may already be exceeded.
142
+
143
+ **Scene 1 canvas completion rule:** Scene 1 establishes the video's visual authority. If Scene 1 contains a canvas element, its `addFrameTask` script MUST be verified complete (all closing braces, full function body) before writing ANY subsequent scene. A truncated Scene 1 canvas breaks the entire video's argument. If approaching output limits before Scene 1's canvas is complete, simplify the canvas animation or replace it with CSS animation—do not proceed to Scene 2 with incomplete Scene 1 code.
144
+
145
+ For concepts that can't be shown with video — data, systems, processes, abstractions — `addFrameTask` gives access to the canvas for per-frame generative graphics. The animation is a pure function of time, so it's fully scrubbable and renderable.
146
+
147
+ **The motion must demonstrate something true about this product that is false about competitors.** Ask: what unit does this product operate on? Show that unit moving. These examples illustrate the thinking pattern — apply the same logic to the brand you're working with:
148
+
149
+ ### Brand visual vocabulary extraction
150
+
151
+ **Before generating any visual element, extract and document:**
152
+ 1. **Typography**: The brand's actual typefaces (not system fonts). If unknown, note 'typography unverified' and use only the brand name in a neutral sans-serif.
153
+ 2. **Product shapes**: Iconic silhouettes the audience recognizes (e.g., a specific bottle shape, packaging form, device outline). These become the visual primitives for canvas animations.
154
+ 3. **Photography style**: The brand's tonal register (dewy/matte, warm/cool, high-contrast/soft).
155
+ 4. **Community artifacts**: Specific touchpoints the audience would recognize (a signature mirror, a named platform, recurring phrases from their content).
156
+
157
+ **If you cannot identify at least two of these four elements, stop and ask the user before proceeding.** Generic brand colors + abstract shapes is never acceptable—even a correct hex code applied to dots or gradients fails the substitute test. Generic 'chaos' or 'frustration' imagery (tangled curves, scattered nodes, visual noise) fails the specificity test just as badly as generic solution imagery. If you cannot identify a brand-specific visual element to animate, use the brand's actual logo as the animated element.
158
+
159
+ For problem/pain scenes specifically:
160
+ - Do NOT use abstract representations of chaos (bezier tangles, particle explosions, visual noise)
161
+ - DO reference the specific predecessor products or workflows this brand replaced
162
+ - Example (browser-native design tool): Show filename-versioning hell ('Final_v3_FINAL_real.psd'), the email-attachment-feedback loop, or the 'someone overwrote my artboard' moment that users recognize
163
+ - Example (opinionated issue tracker): Show the legacy project tool's 47-field issue creation form, the 'which board is this on?' confusion across 12 open tabs, notification spam from issue references, or the exact moment a sprint ceremony produces no actionable output
164
+ - The test: would a user of the OLD workflow immediately recognize this as their specific pain? If the pain could apply to any tool in the category, it's not specific enough.
165
+
166
+ **For environmental/waste problem scenes:**
167
+ - Do NOT show abstract shapes or particles representing waste
168
+ - DO show recognizable objects being discarded: garment silhouettes with visible textures (fleece, denim, puffer quilting), product shapes the audience owns
169
+ - The visual must create discomfort, not aesthetic abstraction. A beautiful gradient with text saying 'gear ends up here' creates no emotional weight. Show the actual pile, the actual landfill texture, the actual garment being thrown away.
170
+ - Example (repair-first outdoor apparel brand): Show the brand's recognizable garment silhouette (the distinctive shoulder yoke, the chest pocket placement) crumpled or falling into a heap. The viewer should think 'that's my jacket.'
171
+ - The test: does the viewer feel a pang of recognition/guilt, or do they observe an information graphic? If the latter, the scene fails.
172
+
173
+ **CRITICAL: Visual specificity is non-negotiable.**
174
+
175
+ 1. **Logo requirement**: Never use placeholder shapes (rectangles, circles, generic icons) for logos. If you cannot access the actual logo, describe it textually and leave a `<!-- TODO: Replace with actual logo SVG -->` comment. Three horizontal lines, generic app icons, or geometric approximations are prohibited.
176
+
177
+ 2. **UI requirement**: For software products, canvas animations must depict recognizable UI patterns from the actual product. Research the product's distinctive interface elements: command palettes, card designs, navigation patterns, specific iconography. Generic 'keyboard keys and circles' could represent any software product.
178
+
179
+ **The substitute test**: Replace the brand name. Could this exact visual appear in a competitor's video unchanged? If yes, the visual fails and must be redesigned with brand-specific elements.
180
+
181
+ - Payments API (unified object model): the same core object threads through every product in the suite → show one object that every system touches simultaneously rather than a pipeline. Speed is generic; the shared object is the differentiator. **Name the actual objects**: PaymentIntent, Customer, Subscription, Price. Show the real field structure (`payment_intent.id`, `customer.id`) appearing identically across Checkout, Billing, Connect. Generic 'unified object' claims without the actual API vocabulary fail the specificity test—a developer should recognize their daily tooling. **Scale metrics must be earned by first showing the mechanism. Show the object flowing through checkout → risk → connect → billing in one continuous motion, THEN reveal the scale that architecture enabled. A metric stated before the architecture is demonstrated is an unsupported claim.**
182
+
183
+ **Beyond unification — what THIS payments API does differently:** Unification is table stakes. Every aggregator claims it. The canvas must show what happens INSIDE the unified layer that competitors cannot replicate:
184
+ - Fraud/risk: Show the risk scoring happening in real-time as the object flows — not a label, a live computation
185
+ - Developer experience: Show the actual CLI commands, webhook events, or dashboard UI that developers recognize as belonging to this specific API
186
+ - Reliability: Visualize what failover looks like at the object level — not abstract "99.99% uptime" text
187
+ - Growth trajectory: Show the same integration scaling from startup to enterprise without code changes
188
+
189
+ The test: swap in a competing payments brand. Would the animation still work? If yes, it's not specific enough.
190
+
191
+ **Problem-state specificity for payments APIs**: Do NOT show generic fintech pain points (payment processing, payouts, fraud detection, reporting). These describe every competitor. Instead show the specific pre-API architecture with **real field name conflicts**: Square's `transaction_id` vs PayPal's `capture_id` vs Braintree's `sale_id`—the actual naming inconsistencies developers must map between. Show the middleware translation layer: `if (provider === 'square') { id = resp.transaction_id } else if (provider === 'paypal') { id = resp.capture_id }`. The pain must be code a developer has actually written, not abstract 'different object models' language.
192
+
193
+ **Solution-state visual requirements for payments APIs**: The solution scene MUST include at least one of: (1) actual code showing the API's syntax elegance (the brand's actual SDK method calls and object names vs. competitor verbosity), (2) the distinctive Dashboard UI aesthetic (the specific card layouts, the typography, the data visualization style), (3) recognizable customer logos that this specific API powers, or (4) the branded visual identity beyond just colors (the brand's particular visual treatments, illustration style, or documentation aesthetic). Generic API response JSON or abstract 'unified platform' diagrams fail the substitute test — any payments company could use them.
194
+
195
+ - Opinionated issue tracker: issues that enter triage exit resolved — no ambiguous state, no "in review forever" → a tangled graph that snaps to a clean DAG; the removal of ambiguity *is* the product. **Content specificity requirement:** Issue titles, labels, and states shown in animations must reference the product's own domain concepts (its named workflow constructs, keyboard shortcuts, specific queue types) or show the product being used to build itself. Generic placeholder text ('API refactor', 'Dashboard bug') fails the substitute test — it could appear in any issue tracker's demo.
196
+ - Browser-native design tool (URL-as-file, multiplayer cursors): There are no files — just URLs. The canvas shows multiple named cursors (with real names like 'Sarah', 'Marcus') moving simultaneously on the same frame. The visual metaphor is the cursor cluster, not abstract collaboration dots. Show the actual component structure: frames nested in frames, the layers panel hierarchy, the distinctive component instance icon. Generic rectangles could be any design tool; the nested frame structure with component instances is this tool's.
197
+ - Backend-as-a-service built on an existing database: The differentiator is not 'unified platform' (every BaaS claims this) but that you retain full database access — row-level security policies written in standard SQL, realtime via database replication (not a proprietary protocol), queryable with any standard client. Show: a single RLS policy that replaces 200 lines of middleware, or the same table queried from browser JS, a mobile app, and a CLI simultaneously. The visual must be impossible to attribute to any competing BaaS product.
198
+
199
+ The pattern: identify the brand's core mechanic (not its marketing position), then find the simplest motion that demonstrates that mechanic in action. The motion should be impossible to misattribute to a different brand.
200
+
201
+ If you could swap the brand name and the canvas animation would still make sense, the animation is decoration.
202
+
203
+ **When showing chaos or pain, make it viscerally uncomfortable — not aesthetically pleasing.** A beautiful tangle of purple bezier curves communicates "elegant complexity." To communicate "I live in this every day and it's exhausting," the visual needs to be overwhelming: too many elements, too fast, overlapping in a way that makes the eye unable to rest. Chaos animations that look designed signal that the problem is aesthetic, not real.
204
+
205
+ **CRITICAL: Canvas animations MUST use addFrameTask, never requestAnimationFrame.** The `requestAnimationFrame` API runs on wall-clock time and will not sync with the composition timeline during rendering. All procedural animation must be driven by `ownCurrentTimeMs` from the addFrameTask callback.
206
+
207
+ **Canvas animations must evolve to match narrative phases.** A canvas that looks the same at second 1 and second 25 is not supporting the story — it's decoration. Before writing any canvas `addFrameTask`, map the narrative phases to distinct visual states:
208
+
209
+ ```
210
+ Narrative phase | Time range | Canvas visual state
211
+ -------------------|------------|--------------------
212
+ Problem/isolation | 0-8s | Single element, muted, sparse
213
+ Transition | 8-12s | Elements begin appearing
214
+ Resolution/energy | 12-25s | Full activity, vibrant
215
+ CTA | 25-30s | Resolve to final state
216
+ ```
217
+
218
+ The `addFrameTask` callback receives `ownCurrentTimeMs` — use it to branch visual behavior:
219
+
220
+ ```javascript
221
+ tg.addFrameTask((info) => {
222
+ const { ownCurrentTimeMs, durationMs } = info;
223
+ const progress = ownCurrentTimeMs / durationMs;
224
+
225
+ // Phase 1: Isolation (0-27%)
226
+ if (progress < 0.27) {
227
+ // Draw single cursor, muted colors
228
+ }
229
+ // Phase 2: First companion appears (27-40%)
230
+ else if (progress < 0.40) {
231
+ // Add second cursor
232
+ }
233
+ // Phase 3: Full collaboration (40-83%)
234
+ else if (progress < 0.83) {
235
+ // All cursors active, vibrant
236
+ }
237
+ // Phase 4: Resolve (83-100%)
238
+ else {
239
+ // Settle into final composition
240
+ }
241
+ });
242
+ ```
243
+
244
+ **Anti-pattern:** A canvas animation where all elements are present from frame 1, contradicting a narrative that claims transformation. If the text says 'you start alone,' the canvas must show alone first.
245
+
246
+ ```html
247
+ <ef-timegroup mode="fixed" duration="6s" id="canvas-scene" class="w-[720px] h-[400px] bg-slate-900">
248
+ <canvas id="particles" class="absolute inset-0 size-full"></canvas>
249
+ <ef-text class="absolute bottom-8 left-8 text-white text-3xl font-bold"
250
+ style="animation: 0.6s enter-up 1s both">Energy in motion</ef-text>
251
+ </ef-timegroup>
252
+
253
+ <script>
254
+ const tg = document.getElementById('canvas-scene');
255
+ const canvas = document.getElementById('particles');
256
+ const ctx = canvas.getContext('2d');
257
+
258
+ tg.addFrameTask((info) => {
259
+ const { ownCurrentTimeMs, durationMs } = info;
260
+ canvas.width = canvas.offsetWidth;
261
+ canvas.height = canvas.offsetHeight;
262
+ const progress = ownCurrentTimeMs / durationMs;
263
+
264
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
265
+
266
+ // 80 particles whose speed and radius scale with progress
267
+ for (let i = 0; i < 80; i++) {
268
+ const seed = i * 137.5;
269
+ const x = (Math.sin(seed + ownCurrentTimeMs * 0.0008) * 0.5 + 0.5) * canvas.width;
270
+ const y = (Math.cos(seed * 0.7 + ownCurrentTimeMs * 0.0006) * 0.5 + 0.5) * canvas.height;
271
+ const r = 2 + Math.sin(seed + progress * Math.PI) * 2;
272
+ const alpha = 0.3 + progress * 0.5;
273
+
274
+ ctx.beginPath();
275
+ ctx.arc(x, y, r, 0, Math.PI * 2);
276
+ ctx.fillStyle = `rgba(99, 179, 237, ${alpha})`;
277
+ ctx.fill();
278
+ }
279
+ });
280
+ </script>
281
+ <style>
282
+ @keyframes enter-up {
283
+ from { transform: translateY(16px); opacity: 0; }
284
+ to { transform: translateY(0); opacity: 1; }
285
+ }
286
+ </style>
287
+ ```
288
+
289
+ **What motion adds:** The particle system is the argument. The concept being communicated — energy, activity, distributed processing, whatever — is visible in the form of the animation, not just stated in text over a stock video.
290
+
291
+ ---
292
+
293
+ ## Progress-Driven Animation
294
+
295
+ `--ef-progress` is a CSS variable that holds the current playback progress (0–1) for any timegroup. It updates every frame. This makes it possible to drive any CSS property as a pure function of time — without keyframes.
296
+
297
+ ```html live
298
+ <ef-timegroup mode="fixed" duration="5s" class="w-[720px] h-[200px] bg-slate-900 flex flex-col items-center justify-center gap-4 p-8">
299
+ <div class="w-full bg-slate-700 rounded-full h-3 overflow-hidden">
300
+ <div class="h-full bg-blue-400 rounded-full transition-none"
301
+ style="width: calc(var(--ef-progress) * 100%)"></div>
302
+ </div>
303
+ <ef-text class="text-white text-2xl">Processing your request</ef-text>
304
+ </ef-timegroup>
305
+ ```
306
+
307
+ **What motion adds:** The progress bar is not decorating a static message — it is the message. The viewer watches time pass as a spatial event. Any numeric or proportional concept can be represented this way.
308
+
309
+ ---
310
+
311
+ ## Persistent Background with Entering Foreground
312
+
313
+ A continuous background (music, ambient video, or canvas) while foreground content animates in and out creates the feeling of a coherent world being revealed in stages, rather than a series of disconnected slides.
314
+
315
+ ```html
316
+ <ef-timegroup mode="fixed" duration="15s" class="absolute w-full h-full">
317
+ <ef-video src="background.mp4" class="absolute inset-0 size-full object-cover opacity-60"></ef-video>
318
+ <ef-audio src="music.mp3" volume="0.2"></ef-audio>
319
+
320
+ <ef-timegroup mode="sequence" class="absolute inset-0">
321
+ <ef-timegroup mode="fixed" duration="4s" class="absolute inset-0 flex items-center justify-center"
322
+ style="animation: 0.5s fade-in both, 0.5s fade-out var(--ef-transition-out-start) both">
323
+ <ef-text split="word" class="text-white text-5xl font-bold text-center"
324
+ style="animation: 0.5s enter-up both; animation-delay: calc(var(--ef-word-index) * 80ms)">
325
+ One thing at a time
326
+ </ef-text>
327
+ </ef-timegroup>
328
+ <ef-timegroup mode="fixed" duration="4s" class="absolute inset-0 flex items-center justify-center"
329
+ style="animation: 0.5s fade-in both, 0.5s fade-out var(--ef-transition-out-start) both">
330
+ <ef-text split="word" class="text-white text-5xl font-bold text-center"
331
+ style="animation: 0.5s enter-up both; animation-delay: calc(var(--ef-word-index) * 80ms)">
332
+ Each idea earns its place
333
+ </ef-text>
334
+ </ef-timegroup>
335
+ </ef-timegroup>
336
+ </ef-timegroup>
337
+ <style>
338
+ @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
339
+ @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
340
+ @keyframes enter-up {
341
+ from { transform: translateY(20px); opacity: 0; }
342
+ to { transform: translateY(0); opacity: 1; }
343
+ }
344
+ </style>
345
+ ```
346
+
347
+ **What motion adds:** The continuous background creates continuity. The foreground entrances and exits create rhythm. Together they produce a sense of a video that lives in one world, not a sequence of separate moments.
348
+
349
+ ---
350
+
351
+ ## Visual Language Consistency
352
+
353
+ Once you establish a visual technique (canvas animations, a particular motion style, a color treatment), maintain it through the final scene. Reverting to simpler techniques at the end breaks the viewer's engagement at the moment it should peak.
354
+
355
+ **Anti-pattern:** Three scenes of sophisticated canvas animation followed by a final scene with static text and basic CSS fades. The CTA scene should be a culmination, not a retreat.
356
+
357
+ **Better:** If scenes 1-3 use orbital particle systems, Scene 4 should show those particles converging into the logo or final message. The motion vocabulary established early must resolve, not disappear.
358
+
359
+ ```html
360
+ <!-- Wrong: Canvas scenes → static text CTA -->
361
+ <ef-timegroup mode="fixed" duration="7s">
362
+ <ef-text class="text-6xl">Design together</ef-text> <!-- Breaks visual momentum -->
363
+ </ef-timegroup>
364
+
365
+ <!-- Right: Canvas animation continues through CTA -->
366
+ <ef-timegroup mode="fixed" duration="7s" id="finale">
367
+ <canvas id="finale-canvas" class="absolute inset-0"></canvas>
368
+ <ef-text class="absolute bottom-8 text-4xl">Design together</ef-text>
369
+ </ef-timegroup>
370
+ <script>
371
+ // Particles from previous scene converge into logo position
372
+ </script>
373
+ ```
374
+
375
+ ---
376
+
377
+ ## Further Reading
378
+
379
+ - [css-variables.md](../composition/references/css-variables.md) — `--ef-progress`, `--ef-duration`, `--ef-transition-*`
380
+ - [scripting.md](../composition/references/scripting.md) — `addFrameTask` and canvas access
381
+ - [text.md](../composition/references/text.md) — `split`, `--ef-word-index`, `--ef-stagger-offset`, `--ef-seed`
382
+ - [transitions.md](../composition/references/transitions.md) — slide, zoom, dissolve between scenes
383
+ - [editing.md](editing.md) — what to cut and when to stop
@@ -0,0 +1,66 @@
1
+ ---
2
+ title: Editing — What to Cut
3
+ description: How to recognize when a scene is not doing work, when a video is complete versus merely finished, and the discipline of omission.
4
+ type: explanation
5
+ order: 5
6
+ ---
7
+
8
+ # Editing — What to Cut
9
+
10
+ Adding scenes is easy. Knowing when to stop, and what to remove, is the actual craft.
11
+
12
+ ## The Test for Every Scene
13
+
14
+ A scene earns its place if it changes the viewer's state — what they feel, believe, or know — in a way that the video requires.
15
+
16
+ Ask: **If this scene were removed, what would the viewer miss?**
17
+
18
+ Not "what information would be absent" — information can be stated more efficiently. What *experience* would be absent? What shift in feeling or understanding would not happen?
19
+
20
+ If the answer is "nothing essential," cut the scene.
21
+
22
+ ## When a Scene Is Not Working
23
+
24
+ **It restates what the previous scene already established.** Two scenes that leave the viewer in the same emotional state are one scene too many. The second one is emphasizing, not progressing.
25
+
26
+ **It exists to include information, not to change state.** "We serve enterprise customers in 40 countries" is information. It can be a caption, a subtitle, a title card at the end. It does not need to be a scene. If the information doesn't require time to land — if it can be understood in a glance — it doesn't justify a scene.
27
+
28
+ **It fills time rather than using it.** A scene that holds for 4 seconds because "it needs to be readable" but could be cut to 2 without losing comprehension is 2 seconds of hollow. Duration should be earned by what's happening, not assigned by convention.
29
+
30
+ **The motion is decorative.** If you can describe a scene as "logo fades in, holds, fades out" — and the fades exist because videos have fades, not because the fading communicates anything — the motion is decoration. Either give the motion meaning or remove it.
31
+
32
+ ## The Compression Test
33
+
34
+ Cut the draft to half its duration. Not in detail — just in structure. Which scenes survive? Those are the video. The rest are padding you added because you were afraid of leaving something out.
35
+
36
+ This doesn't mean the final video is half as long. It means: when you can't cut any further without losing something real, you've found what the video actually is.
37
+
38
+ ## Signs You're Done
39
+
40
+ - Removing any remaining scene would leave a gap the viewer would feel
41
+ - Every motion exists because it adds information or changes the viewer's state, not because videos have motion
42
+ - The first scene creates a condition that the last scene resolves — there's an arc, not just a sequence
43
+ - You've watched it 5 times and nothing is invisible — meaning nothing is wasted
44
+
45
+ ## Signs You're Not Done
46
+
47
+ - You have scenes you're keeping "just to be safe"
48
+ - Any two adjacent scenes leave the viewer in the same emotional state
49
+ - The video makes sense if you watch it with the sound off and the text replaced with placeholders — this means the form is generic
50
+ - You can't say what the viewer should feel at the final frame that they didn't feel at the first frame
51
+
52
+ ## What Omission Creates
53
+
54
+ Every gap you create — a cut that arrives sooner than expected, a title that doesn't fully spell out the implication, a scene that ends before the thought is completed — requires the viewer to participate. Viewers who participate remember what they made. Viewers who are shown everything are passive.
55
+
56
+ The hollow feeling in videos that have everything is often the absence of anything left for the viewer to complete.
57
+
58
+ Leave something out on purpose. Not confusion — gap. The difference: confusion means missing information. A gap means the viewer arrives at the conclusion through their own momentum.
59
+
60
+ ## The One-Sentence Test
61
+
62
+ Before finalizing, complete this sentence:
63
+
64
+ > "This video exists because __________, and without it, the viewer would never ____________."
65
+
66
+ Both blanks must be specific and non-transferable. If either can be completed with generic language that would apply to any brand video, the video is not done yet — or not necessary.