chore: import upstream snapshot with attribution
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
# Cut catalog — within-frame seams (worker-built)
|
||||
|
||||
> **A worker build-recipe (Step 5) — the sibling of `../hyperframes-animation/rules/`, not a second motion doc.** These are within-frame cuts the **frame worker builds INSIDE its own composition** (Z-scale + blur + opacity tweens, or per-word x-staggers, all on the frame's own paused GSAP timeline). They are **not** the between-frame transition: story owns that via `transition_in`, which the harness's injector stamps from a **separate registry vocabulary** (`crossfade` / `blur-crossfade` / `push-slide` / `zoom-through` / `squeeze`) — the catalog names here (**cut-the-curve / inverse-zoom / waterfall**) are **not** valid `transition_in` values. Use this catalog when a frame's shot sequence has an internal seam — a within-scene text/element swap, a **Scene-to-Scene** cut (a `Scene` is a time window WITHIN one frame, **not** a frame-to-frame boundary), or a text-to-text line change — and you want it to read as one continuous move instead of a hard slideshow cut. (`zoom-through` lives in both worlds: a whole-frame wrapper transition in the registry, an element-level Z-cut here — same idea, different scope.)
|
||||
|
||||
Four techniques that create depth and continuity:
|
||||
|
||||
1. **Zoom-Through** — within-scene text swaps, Z-axis, moving TOWARD the viewer
|
||||
2. **Inverse Zoom-Through** — Z-axis swaps moving AWAY from the viewer
|
||||
3. **Cut the Curve** — between-scene transitions on x/y
|
||||
4. **Waterfall Cut** — word-by-word cut-the-curve with staggered exits and entries
|
||||
|
||||
All four are the same underlying principle: **cut at peak velocity, match direction and
|
||||
speed on both sides of the cut.** The differences are axis, scope, and granularity.
|
||||
|
||||
**Choosing which at a seam:** for an UNFINISHED phrase (building one larger idea across
|
||||
several visually distinct scenes that still approach the same point — multi-line text, a
|
||||
run of consecutive cards) use **cut-the-curve** / **waterfall**. For a STATE CHANGE (turning
|
||||
to a NEW part of the video — most often hook → context, between two distinct chapters) use
|
||||
**zoom-through**, and **inverse zoom-through** for an arrival / payoff beat. Chain these so
|
||||
the frame's internal seams feel like one camera moving through the content.
|
||||
|
||||
---
|
||||
|
||||
## Blur Logic (applies to all Z-axis variants)
|
||||
|
||||
Blur sells the speed at the cut, but it must scale with the SUBJECT SIZE:
|
||||
|
||||
| Subject | Peak blur | Why |
|
||||
| ------------------------------------------------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Text-scale (headline, line, word group) | **10px** | At 20px text smears into illegibility — the eye loses the word it was tracking and the cut reads as a glitch, not speed. At 20px letterforms go mushy mid-cut; 10px keeps them readable. |
|
||||
| Full-frame surface (terminal window, card, screenshot) | **18–20px** | Big surfaces have edges and texture that survive heavy blur; lighter blur on a full-frame move reads as a rendering hiccup instead of motion. |
|
||||
|
||||
Both sides of a cut use the SAME peak blur — the value must match at the swap frame.
|
||||
Apply blur to the WRAPPER, never to individual children.
|
||||
|
||||
---
|
||||
|
||||
## 1. Zoom-Through (forward)
|
||||
|
||||
### The Problem
|
||||
|
||||
Text enters, holds, exits. Then next text enters, holds, exits. Each text block is
|
||||
independent — no depth, no continuity. The video feels like a slideshow.
|
||||
|
||||
### The Principle
|
||||
|
||||
A velocity-matched cut on the Z-axis. You **never see both texts at the same time.** The
|
||||
outgoing text scales toward the viewer (accelerating), blur and opacity peak at the cut
|
||||
point hiding a hard swap, and the incoming text continues scaling up from behind
|
||||
(decelerating into the focal plane). One continuous forward motion, two different texts.
|
||||
|
||||
### The Three Phases
|
||||
|
||||
**Phase 1: Exit** — text accelerates forward (toward viewer)
|
||||
|
||||
- Scale: `1.0 -> 1.2`, Blur: `0px -> 10px` (text-scale; see Blur Logic), Opacity: `1.0 -> 0.15`
|
||||
- Scale/blur easing: `power3.in` (steep acceleration)
|
||||
- Opacity easing: `none` (linear — even dimming, separated from scale)
|
||||
- Duration: 0.2s
|
||||
|
||||
**Phase 2: Hard cut** at peak velocity + peak blur
|
||||
|
||||
- Outgoing: `opacity: 0` (instant via `tl.set`)
|
||||
- Incoming: `opacity: 0.15, scale: 0.75, blur: 10px` (instant via `tl.set`)
|
||||
- All properties match at the cut: blur, opacity, and scale DIRECTION (both scaling up)
|
||||
|
||||
**Phase 3: Entry** — text continues forward (growing into focal plane)
|
||||
|
||||
- Scale: `0.75 -> 1.0`, Blur: `10px -> 0px`, Opacity: `0.15 -> 1.0`
|
||||
- Easing: `expo.out` (steep initial burst matching exit velocity, long settle)
|
||||
- Duration: 0.5s
|
||||
|
||||
### Why Opacity Must Be Separate on Exit
|
||||
|
||||
Scale uses `power3.in` but that keeps opacity near 1.0 for most of the tween. Splitting
|
||||
opacity to its own tween with linear ease makes the dimming even. On entry, all properties
|
||||
can share `expo.out`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Inverse Zoom-Through (backward)
|
||||
|
||||
The mirror: the camera "pulls back" instead of pushing through. The outgoing element
|
||||
RECEDES away from the viewer; the incoming element arrives OVERSIZED (as if it had been
|
||||
just behind the camera) and retracts into the focal plane. Both move in the shrinking
|
||||
direction — same-direction rule preserved, just reversed.
|
||||
|
||||
**When to use over the forward variant:** arrival beats. The incoming element lands with
|
||||
presence because it comes from larger-than-frame — right for a payoff line ("That changes
|
||||
today."), a giant reply, or a held end-state. Forward zoom-through reads as _progressing
|
||||
through_ content; inverse reads as _arriving at_ content.
|
||||
|
||||
### The Three Phases
|
||||
|
||||
**Phase 1: Exit** — element recedes (away from viewer)
|
||||
|
||||
- Scale: `1.0 -> 0.8`, Blur: `0px -> 10px` (text-scale)
|
||||
- Scale/blur easing: `power3.in`; Opacity: `1.0 -> 0.15` on `none` (separate tween)
|
||||
- Duration: 0.2s
|
||||
|
||||
**Phase 2: Hard cut**
|
||||
|
||||
- Outgoing: `opacity: 0` via `tl.set`
|
||||
- Incoming: `opacity: 0.15, scale: 1.25, blur: 10px` via `tl.set`
|
||||
|
||||
**Phase 3: Entry** — incoming retracts into place
|
||||
|
||||
- Scale: `1.25 -> 1.0`, Blur: `10px -> 0px`, Opacity: `0.15 -> 1.0`
|
||||
- Easing: `expo.out`, Duration: 0.5s
|
||||
|
||||
---
|
||||
|
||||
## 3. Cut the Curve (Scene Transitions)
|
||||
|
||||
### The Principle
|
||||
|
||||
Use cut-the-curve for **all scene-to-scene transitions** on x and y axes. The outgoing
|
||||
scene's hero element accelerates in one direction, the cut lands mid-motion, and the
|
||||
incoming scene's hero element continues moving in the **same direction** and decelerates.
|
||||
Nothing exits fully off-screen and nothing enters from fully off-screen — **speed plus
|
||||
opacity fading trick the eye**; the partial moves are enough.
|
||||
|
||||
### Same Path, Same Direction
|
||||
|
||||
If Scene A's hero slides left, Scene B's hero enters from the right and continues sliding
|
||||
left. Both move leftward. One continuous motion.
|
||||
|
||||
| Direction | Scene A exit | Scene B entry start | Scene B entry end |
|
||||
| --------- | -------------- | ------------------- | ----------------- |
|
||||
| Leftward | `x: 0 -> -230` | `x: +230` | `x: 0` |
|
||||
| Rightward | `x: 0 -> +230` | `x: -230` | `x: 0` |
|
||||
| Upward | `y: 0 -> -230` | `y: +230` | `y: 0` |
|
||||
| Downward | `y: 0 -> +230` | `y: -230` | `y: 0` |
|
||||
|
||||
### Velocity matching via mirrored eases
|
||||
|
||||
The cleanest match: exit `power4.in` and entry `power4.out` with the SAME distance and
|
||||
duration — mathematically the two halves of one `power4.inOut` composite, so the entering
|
||||
element picks up at exactly the 50% point of the notional path at identical velocity
|
||||
(e.g. 230px / 0.3s ≈ 3,070 px/s at the cut on both sides).
|
||||
|
||||
The fade trick: the exit's opacity completes at ~25–30% of its travel (fade duration
|
||||
≈ 0.18–0.3s vs motion 0.3–0.34s) — the element vanishes while still visibly accelerating,
|
||||
and nothing has to reach the frame edge. Entry fades IN fast from ~0.35 under its
|
||||
deceleration. Time the LAST fading element to die right at the hard cut — gaps where
|
||||
nothing is moving read as awkward dead air.
|
||||
|
||||
### Rules
|
||||
|
||||
- Use cut-the-curve for all scene transitions — it's the default, not an accent
|
||||
- Same direction on both sides; mirrored `.in`/`.out` eases, same distance + duration
|
||||
- Exit duration short (0.2–0.4s), entry duration >= exit duration
|
||||
- Partial travel + fade, never full off-screen moves
|
||||
|
||||
---
|
||||
|
||||
## 4. Waterfall Cut (word-by-word cut-the-curve)
|
||||
|
||||
Cut-the-curve at WORD granularity — the strongest version of the leftward cut for
|
||||
text-to-text seams. Each word of the outgoing line ramps out on its own pronounced curve;
|
||||
each word of the incoming line cascades in mid-flight. The stagger turns the cut into a
|
||||
wave the eye rides across the seam.
|
||||
|
||||
### Exit (per word)
|
||||
|
||||
- Motion: `x: 0 -> -230` over 0.34s on **power4.in** — a much more pronounced ramp than
|
||||
the usual power2: the word barely creeps, then RIPS
|
||||
- Fade: `opacity -> 0` over 0.18s (separate tween, `power1.in`) — completes when the word
|
||||
is only ~25–30% into its travel
|
||||
- Stagger: reading order, ~0.022s per word, timed so the LAST word finishes fading right
|
||||
at the hard cut
|
||||
|
||||
### Entry (per word)
|
||||
|
||||
- `fromTo x: +230 -> 0, opacity: 0.35 -> 1` over 0.3s on **power4.out** — the mirrored
|
||||
back half of the composite; every word ignites already moving at matched velocity
|
||||
- Waterfall stagger with SHRINKING gaps (start 0.05s, multiply by ~0.84 per word) so the
|
||||
cascade accelerates across the line — the cascade should speed up word over word, not run
|
||||
at a flat per-word delay
|
||||
- Pre-set all words to `x: +230, opacity: 0` at build time — `immediateRender: false`
|
||||
alone leaves un-started words sitting visible at rest during the stagger window
|
||||
|
||||
### Whole-line variant
|
||||
|
||||
A single-line beat (e.g. a big intro line) exits as one group with the same pronounced
|
||||
ramp, but stretch its fade to ~0.3s ending ~0.02s before the cut — a lone element that
|
||||
fades early leaves dead air that a word cascade would have covered.
|
||||
|
||||
---
|
||||
|
||||
## Choosing a Variant
|
||||
|
||||
| | Zoom-Through | Inverse Zoom | Cut the Curve | Waterfall Cut |
|
||||
| -------------- | --------------------------- | --------------------------- | ----------------- | ------------------------- |
|
||||
| Scope | Within-scene text swap | Arrival/payoff beat | Between scenes | Text-to-text seam |
|
||||
| Axis | Z, toward viewer | Z, away from viewer | X / Y | X, per-word |
|
||||
| Peak blur | 10px text / 20px full-frame | 10px text / 20px full-frame | none required | none (fade does the work) |
|
||||
| Opacity at cut | 0.15 | 0.15 | exit faded by cut | last word dies at cut |
|
||||
| Feel | progressing through | arriving at | carried sideways | a wave across the seam |
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
| Don't | Why | Instead |
|
||||
| ---------------------------------------- | ------------------------------------------- | ------------------------------------------------------ |
|
||||
| Two texts visible during a zoom-through | Overlapping text breaks the Z-axis illusion | Hard cut at blur peak, one text at a time |
|
||||
| 20px blur on text-scale subjects | Letterforms smear; reads as a glitch | 10px for text, 18–20px only full-frame |
|
||||
| Elements on different paths across a cut | Eye tracks one direction, cut goes another | Same property, same direction |
|
||||
| Mismatched blur/opacity at the swap | Visible flash or brightness jump | Identical values at the cut frame |
|
||||
| Gentle easing on entry (`power2.out`) | Entry velocity feels slower than exit | Mirror the exit: `power4.out` / `expo.out` |
|
||||
| Full off-screen exits / entries | Wastes time and breaks the speed illusion | Partial travel + early fade |
|
||||
| Lone element fading long before its cut | Dead air at the seam | Fade ends ~0.02s before the cut, or use a word cascade |
|
||||
| Zoom-through on body text | Small text at 0.75 scale is unreadable | Only headlines and short phrases |
|
||||
| Scene cuts without cut-the-curve | Static cuts feel like a slideshow | Cut-the-curve is the default |
|
||||
@@ -0,0 +1,156 @@
|
||||
# Motion language — the move vocabulary + the motion doctrine + the seek-safe core
|
||||
|
||||
> The motion layer for **Step 4 (Visual design)**. When you write a frame's **time-coded shot sequence**, you name each scene's move **inline from the vocabulary below** — a named palette of the moves the golden corpus actually uses. Each move carries the **backing rule id** in this skill's local `../hyperframes-animation/rules/`; cite that id so the move resolves to a real recipe when a **frame worker** implements it in Step 5 (the worker reads the rule body in `../hyperframes-animation/rules/<id>.md` — it reproduces the move, it does not guess from the name). You name motion by **role / move name**, never by raw GSAP curve, ms, or stagger formula — the worker maps the curve. Between-frame **transitions are not yours**: story names `transition_in`, the harness injects it; that injected transition **is** the frame's exit. For cuts a worker builds INSIDE a frame (within-scene swaps, scene-to-scene seams), see the catalog in `cut-catalog.md`.
|
||||
|
||||
A good explainer feels like one continuous film — one camera, one motion feel, **smooth and timed to the voiceover** — not a pile of slides that animate once and freeze. In an explainer the development _is_ the teaching: the formula assembling, the diagram gaining a layer, the count-up landing. The doctrine in Part 2 is load-bearing: when in doubt, do what it says.
|
||||
|
||||
---
|
||||
|
||||
# Part 1 — the move vocabulary
|
||||
|
||||
Reach into this palette when naming a scene's motion. Pick the move that matches the beat, name it in the shot sequence, and cite the rule id after `→`. The blueprints (`../hyperframes-animation/blueprints/`) name these same moves in their `rule mapping`; you're drawing from one shared palette. Compose 2–4 across a shot's scenes (entrance → sequential reveal → settle), not all at once.
|
||||
|
||||
## Kinetic type
|
||||
|
||||
- **hard-cut / flash word-swap** — a word or line replaces the previous one on an instant cut (no fade/roll); the swap itself is the beat. → `discrete-text-sequence`
|
||||
- **in-place token cycle** — a fixed line holds and only its variable slot changes, token → token → token. → `discrete-text-sequence`
|
||||
- **per-word staggered reveal** — a phrase assembles word-by-word (or chunk-by-chunk), each landing on its own beat. → `dynamic-content-sequencing`
|
||||
- **kinetic beat-slam** — short phrases slam in on a shared percussive beat array, each with a distinct entrance, resolving on a locked finale; the recipe for "punchy / rhythmic" taglines. → `kinetic-beat-slam`
|
||||
|
||||
## Typewriter
|
||||
|
||||
- **type-on with caret** — text types in character-by-character behind a blinking caret. → `discrete-text-sequence` (+ `context-sensitive-cursor` for the caret blink / color)
|
||||
- **backspace-and-retype** — the line types, deletes the last word(s), and retypes a new one (typo-correction, reframe). → `discrete-text-sequence` (+ `context-sensitive-cursor`)
|
||||
|
||||
## Count-up / data
|
||||
|
||||
- **value-scaled counter** — a number counts up and its font size grows with the value, so the climb itself escalates. → `counting-dynamic-scale`
|
||||
- **bars / progress / star wipe** — a number paired with a graphic that fills: bar-height stagger, a progress bar / ring filling, a fractional star-rating wipe. → `stat-bars-and-fills`
|
||||
|
||||
## Reveal / decode
|
||||
|
||||
- **3D char flip-decode** — characters flip in 3D and resolve from scrambled glyphs to the real text (decryption feel). → `hacker-flip-3d`
|
||||
- **SVG self-draw** — an outline / icon / ring draws itself stroke-by-stroke. → `svg-path-draw`
|
||||
|
||||
## Camera
|
||||
|
||||
- **push / focus / drift** — a sequential camera move on the frame root (pull-back → focus → push) plus continuous micro-drift; the cinematic baseline. → `multi-phase-camera`
|
||||
- **zoom-to-target** — zoom into a non-centered element (scale + counter-translate to keep it framed). → `coordinate-target-zoom`
|
||||
- **pan / focus-lock** — a virtual camera transforming one `.world` wrapper to pan / zoom / lock onto a region. → `viewport-change`
|
||||
- **camera-cursor-tracking** — the viewport locks to a moving focal point (a typing cursor), static framing then focal-locked tracking. → `camera-cursor-tracking`
|
||||
|
||||
## Layout motion
|
||||
|
||||
- **cluster→outward expansion** — elements start clustered at center and expand outward to their final positions in lockstep. → `center-outward-expansion`
|
||||
- **orbit** — elements flip in from 3D space and settle into a continuous elliptical orbit (entry flips in-place at the orbital position). → `orbit-3d-entry`
|
||||
- **split-tilt cards** — two cards side-by-side with opposing rotationY tilts, entering from their respective sides (comparison / before-after). → `split-tilt-cards`
|
||||
- **logo/avatar ring + connectors** — avatars or logos on an elliptical ring with SVG connection lines to a center point, staggered entry. → `avatar-cloud-network`
|
||||
|
||||
## Surface / UI
|
||||
|
||||
- **3D page-scroll reveal** — a full webpage as a tilted 3D card whose internal content scrolls to reveal specific sections. → `3d-page-scroll`
|
||||
- **cursor click + ripple** — a cursor moves to a target, depresses with it on click, and emits an expanding ripple. → `cursor-click-ripple`
|
||||
- **button press** — a tactile press: compression then spring recovery, optional release burst / glow. → `press-release-spring` (or `physics-press-reaction` for a click that compresses cursor + target together)
|
||||
- **keyword glow** — keywords light up with glow + scale + color on an attack-decay-rest envelope, synced to a word rail. → `asr-keyword-glow`
|
||||
|
||||
## Morph / handoff
|
||||
|
||||
- **scale-swap** — two elements at the same screen center hand off: the outgoing cluster shrinks + fades as the incoming one arrives. → `scale-swap-transition`
|
||||
- **card morph-anchor** — a container morphs apparent size + corner radius + surface between two shots, then fades to reveal the real target beneath (HyperFrames uses uniform `scale`, not `width`/`height`). → `card-morph-anchor`
|
||||
|
||||
## Seam cuts (worker-built, inside a frame)
|
||||
|
||||
The velocity-matched cuts a worker authors between a frame's own Scenes. Name the seam in the shot sequence; the recipe is in the catalog, not a single `../hyperframes-animation/rules/` id.
|
||||
|
||||
- **zoom-through / inverse zoom-through** — a within-scene swap on the Z-axis; forward reads "progressing through", inverse reads "arriving at" (payoff). → `cut-catalog.md`
|
||||
- **cut-the-curve** — a scene-to-scene cut where both sides move the same direction at matched velocity. → `cut-catalog.md`
|
||||
- **waterfall cut** — cut-the-curve at word granularity, a wave across a text-to-text seam. → `cut-catalog.md`
|
||||
|
||||
## Emphasis / marker
|
||||
|
||||
- **highlight / circle / burst / scribble** — a marker-drawn emphasis on a word or element: yellow highlight sweep, hand-drawn circle, radiating burst, scribble, or rough sketch-outline. → `css-marker-patterns`
|
||||
|
||||
## Aliveness during a hold (use sparingly — see Part 2)
|
||||
|
||||
- **subtle jitter** — the sanctioned way to keep a settled frame alive: a small, low-amplitude positional/scale jitter on the held element. The motion-graphics trick that reads "alive" without reading "weak." → `sine-wave-loop` (low-amplitude register)
|
||||
- **live SVG internals** — internal SVG parts move so an icon feels alive (rotating hands, oscillating blades, pulsing dots, dash-flow); fine because it's the subject doing something, not a card breathing. → `svg-icon-enrichment`
|
||||
- **finite bounded ambient** — a single bounded breathe/drift on ONE held hero, only when genuinely needed; de-emphasized — prefer sequential reveal or jitter first. → `sine-wave-loop`
|
||||
|
||||
## The added moves — now backed by local rules
|
||||
|
||||
Five moves the golden corpus needs were added to this skill's `../hyperframes-animation/rules/`, rounding out the vocabulary above:
|
||||
|
||||
- **depth-of-field / selective-blur** — blur the off-focus subset to spotlight the focal element → `depth-of-field-blur`
|
||||
- **motion-blur streak** — directional velocity blur on a fast fly-in / camera push-through → `motion-blur-streak`
|
||||
- **3D depth scatter-assemble** — glyphs/elements scatter into a tumbling 3D cloud, then reassemble → `depth-scatter-assemble`
|
||||
- **spring-pop entrance** — the canonical entrance pop; default to a smooth long-tail settle, overshoot only when explicitly playful → `spring-pop-entrance`
|
||||
- **ambient glow / bloom** — un-triggered soft glow blooming behind a static hero → `ambient-glow-bloom`
|
||||
|
||||
---
|
||||
|
||||
# Part 2 — the motion doctrine (load-bearing)
|
||||
|
||||
These four rules are the difference between a clip that reads as a serious explainer and one that reads as an agent-made PowerPoint. Follow them as written.
|
||||
|
||||
## 1. Smooth beats bouncy — `power3` is the default
|
||||
|
||||
Elements should use **long-tail decel curves that let them settle smoothly. `power3` is enough in most cases.** No bouncy, no overshoot, no `back.out` / `bounce.out` / `elastic.out` as a default.
|
||||
|
||||
Bouncy is the **#1 instant turn-off** in user-made Remotion / HyperFrames videos, and the agent almost never gets it right — it thinks bouncy adds emphasis, but it buys that emphasis at the cost of cleanliness. The serious motion-design shops feel the same. **Smooth always wins.** Overshoot is demoted to a **rare, explicitly-playful exception** (a consumer/fun logo slam, a deliberate bell-hit) — never the house style. Name the intent as a long-tail settle; the worker maps `power3` (or `expo.out` on a fast arrival). See `../hyperframes-animation/rules/spring-pop-entrance.md` — it now leads with the smooth settle. (The exact form of that settle is a critically-damped spring; the worker has a baked, seek-safe `springEase` — ζ=1 — in `../hyperframes-animation/adapters/gsap-easing-and-stagger.md` → Spring Eases for when the settle is the hero. Real physics, same doctrine — not a license for bounce.)
|
||||
|
||||
## 2. Sequential reveal in the back ~50%, timed to the voiceover
|
||||
|
||||
This is the anti-PowerPoint mechanism — sharper than "put development in the middle."
|
||||
|
||||
- **Don't dump everything on screen in the first ~25%** of the scene. Rushing all content in up front is exactly what forces the slideshow feel.
|
||||
- **Reveal each piece — a line, a card, even an h1 — when the voiceover mentions it**, sequencing reveals across the **later ~50%** of the scene. Same amount of agent work, but the cut becomes coherent and gains rhythm.
|
||||
- **Less is more.** Fewer things on screen, each arriving on its VO beat, beats a full canvas that animated once and froze.
|
||||
|
||||
Practically: a frame's shot sequence front-loads almost nothing — the entrance carries only what the VO is saying at t=0, and the rest of the elements wait in the timeline for their spoken cue. A reveal maps onto a development-class move from Part 1 (`per-word staggered reveal`, `cluster→outward expansion`, a `count-up`, an `asr-keyword-glow` synced to the word rail).
|
||||
|
||||
## 3. No lazy breathing, no bad pan/push — "no motion over bad motion"
|
||||
|
||||
The agent's two reflexive ways to fake "aliveness" both read cheap:
|
||||
|
||||
- **No lazy breathing.** Scaling cards/text up and down in a circular loop to look "alive" is the cheap tell. Don't reach for it.
|
||||
- **No bad slow pan / push in the back half.** A slow pan or push on elements in the later ~50% of a scene **disrupts the viewer's sightline and causes eye discomfort** — it actively makes the frame worse, not better.
|
||||
|
||||
The fix for both is the same: **stagger element reveals in time with the script** (rule 2). And the governing principle: **"I'd rather have NO motion than BAD motion."** A held, still frame is better than a frame kept "alive" by breathing or a drifting camera. The **only sanctioned aliveness** during a hold is **subtle jitter** — a small low-amplitude jitter that keeps a frame from feeling dead without looking weak (it's in Claude videos now). Everything else holds.
|
||||
|
||||
## 4. Internal seams are velocity-matched cuts
|
||||
|
||||
When a frame has an internal seam — a within-scene swap, a Scene-to-Scene cut, a text-to-text line change — make it a **velocity-matched cut**, not a hard slideshow cut: cut at peak velocity, match direction and speed on both sides. The catalog (the four techniques, the blur logic, and which to use when) is `cut-catalog.md`; the moves are listed under **Seam cuts** in Part 1.
|
||||
|
||||
## One-line summary
|
||||
|
||||
Smooth long-tail (`power3`) over bouncy; reveal sequentially in the back ~50% timed to the VO (not dumped in the first 25%); no lazy breathing and no bad slow pan/push — prefer stillness, with subtle jitter as the only aliveness; cut at peak velocity with matched direction/speed (→ `cut-catalog.md`).
|
||||
|
||||
---
|
||||
|
||||
# Part 3 — the seek-safe core (hard rules)
|
||||
|
||||
The frame is a **paused GSAP timeline seeked frame-by-frame**, so some "continuous" intents from a real-time engine can't render — don't name them. These are non-negotiable regardless of doctrine.
|
||||
|
||||
- **No infinite / forever motion** — "particles loop endlessly," "logo rotates forever," "marquee on repeat." Any aliveness (the subtle jitter, a live SVG internal, a needed bounded ambient) is a **finite tween over the hold**, never `repeat` / `yoyo`.
|
||||
- **No randomness or wall-clock** — no `Math.random` particle fields, no `Date.now` drift. Every render must be identical; name deterministic motion only (stagger and any variation derive from the element index).
|
||||
- **Entrances use `fromTo`** — state the from-state explicitly so a seek to `t=0` lands the element correctly; never rely on a CSS-hidden start (it renders visible before the tween claims it, and flickers under seek).
|
||||
- **No CSS `transition` / `@keyframes` for motion** — CSS animation runs on the browser clock, independent of the HF seek clock; it desyncs and flickers. Drive all motion inside the paused GSAP timeline.
|
||||
- **Entrance + sequential reveal only — no mid-video exit.** The frame unmounts via the harness transition; that injected `transition_in` **is** the exit. Exit motion belongs only to the final frame. (Worker-built seam cuts in `cut-catalog.md` are within-frame, not the frame's exit.)
|
||||
|
||||
## Forbidden — the failure modes
|
||||
|
||||
**Slideshow (the primary failure):** everything dumped on screen in the first ~25%; content enters then freezes; nothing revealed on its VO cue. Fix with rule 2 (sequential reveal timed to the VO).
|
||||
|
||||
**Cheap aliveness:** circular breathing as "life"; a slow pan/push in the back half disrupting the eye; many elements floating independently as "motion." Fix with rule 3 (stillness + subtle jitter only).
|
||||
|
||||
**Bouncy:** `back.out` / `bounce.out` / `elastic.out` as the default entrance; hand-keyed overshoot. Fix with rule 1 (`power3` long-tail; overshoot only when explicitly playful).
|
||||
|
||||
**Always:** no `repeat` / `yoyo`; no `Math.random` / `Date.now`; no all-elements-entering-simultaneously (sequence or stagger).
|
||||
|
||||
## Naming motion in a shot — example
|
||||
|
||||
> Scene 1 (0.0–1.0s): solid field; hero headline enters via **per-word staggered reveal** (`dynamic-content-sequencing`) on a smooth long-tail settle (`power3`); slow **push** on the root (`multi-phase-camera`) holds steady — no back-half re-push.
|
||||
> Scene 2 (1.0–3.0s): as the VO names each step, five mechanism nodes reveal **sequentially** via **cluster→outward expansion** (`center-outward-expansion`), then a **value-scaled counter** (`counting-dynamic-scale`) ticks up beneath them — the back-half reveal, timed to the script, not dumped at t=0.
|
||||
> Scene 3 (3.0–4.2s): hold on the result; **keyword glow** (`asr-keyword-glow`) lands on the payoff word as the VO says it; settles and holds still — at most **subtle jitter** (`sine-wave-loop`, low amplitude) keeps it alive; no breathing, no drift.
|
||||
|
||||
Name the move + its rule id (or `cut-catalog.md` for a seam cut) per scene; let the worker pick curves, ms, and stagger — defaulting to `power3`.
|
||||
@@ -0,0 +1,248 @@
|
||||
# Story design — faceless explainer video
|
||||
|
||||
Use this reference in Step 3 to write `STORYBOARD.md` and `SCRIPT.md` for a faceless explainer — a topic, concept, how-to, listicle, or narrative explainer built from text, with **no product, no website, and no captured assets**.
|
||||
|
||||
This file defines the story: what the video teaches, in what order, and why each frame exists. It does not define layout, visual effects, animation, or final markdown schemas. For exact file syntax, follow `../hyperframes-core/references/storyboard-format.md` and `../hyperframes-core/references/script-format.md`.
|
||||
|
||||
## Read first
|
||||
|
||||
Read these inputs before writing:
|
||||
|
||||
1. `hyperframes.json` — locked brief: angle, length, aspect ratio, language.
|
||||
2. `frame.md` — tone, mood, design system, and register.
|
||||
3. `capture/extracted/visible-text.txt` — the article / notes / topic / brief (the source of **information**).
|
||||
4. `user_script.txt` and `VO_MODE`, when the user pasted a script.
|
||||
|
||||
There is no `asset-descriptions.md` and no `capture/assets/` to inspect — this is faceless. Every visual is invented downstream (Steps 4-5); your job here is the **narrative**, not a visual asset list.
|
||||
|
||||
## Output
|
||||
|
||||
Create two files:
|
||||
|
||||
- `STORYBOARD.md` — the teaching plan, one frame per beat.
|
||||
- `SCRIPT.md` — the locked narration, only for spoken frames.
|
||||
|
||||
Every storyboard frame must include the required fields from the storyboard format reference, plus the narrative metadata below.
|
||||
|
||||
## Core rule
|
||||
|
||||
An article is an information dump. A video is a guided act of understanding.
|
||||
|
||||
Do not follow paragraph order. Reorder, merge, omit, and compress the source text into a clear teaching sequence. Strip the asides; surface the spine. **The single most common failure is paraphrasing the article in order — do not do that.** The input text is the source of information, not a story template.
|
||||
|
||||
## Step 3 method
|
||||
|
||||
### 1. Extract the teaching truth
|
||||
|
||||
From the brief and text, identify:
|
||||
|
||||
- Audience — who the video is speaking to, and what they already (don't) know.
|
||||
- Gap or stakes — the confusion, question, or "why care" the explanation resolves.
|
||||
- Thesis — the one-line idea the viewer should walk away with.
|
||||
- Spine — the 3-6 ideas (mechanisms / steps / items / beats) that build to the thesis.
|
||||
- Evidence — the concrete numbers, examples, comparisons, or worked cases that ground it.
|
||||
- Landing — the takeaway or the call to think / try / act.
|
||||
|
||||
Write the storyboard around the thesis, not around the article's sections.
|
||||
|
||||
### 2. Match the register to `frame.md`
|
||||
|
||||
Use `frame.md` as a soft guide — the visual system tunes the **voice**, not the structure:
|
||||
|
||||
| `frame.md` signal | Story effect |
|
||||
| ------------------------------ | -------------------------------------- |
|
||||
| warm, handmade, notes-like | plain, considered, low-hype; humane |
|
||||
| bold, poster-like, declarative | short punchy beats, confident claims |
|
||||
| friendly, polished, modern | approachable direct address, lighter |
|
||||
| literary, technical-but-human | thoughtful, precise; safe for code/dev |
|
||||
|
||||
The teaching truth decides the arc. The visual system tunes the voice.
|
||||
|
||||
### 3. Choose one explainer structure
|
||||
|
||||
Pick **one** structure (or explicitly name a compound). Do not splice phases from different structures — each is a complete path through understanding.
|
||||
|
||||
| Structure | "It is…" | Use when the payload is… | Body shape |
|
||||
| ------------------- | ------------------------------------------------ | ----------------------------------------------------------- | -------------------------------------------------------------------- |
|
||||
| `concept-explainer` | "what is X, and why does it matter" | one idea/term/phenomenon the audience half-knows | name concept → reveal mechanism layer by layer → land implication |
|
||||
| `how-to-process` | "here is how to do / how X works," ordered steps | a procedure or mechanism with a clear start→finish | a 3-6 step sequence on a consistent visual stage, one move each |
|
||||
| `listicle` | "N things about X" | a set of parallel, co-equal items (tips, mistakes, reasons) | hook → N roughly co-equal items → wrap; rule-of-three is strongest |
|
||||
| `story-explainer` | teach through a narrative arc | case studies, histories, cautionary tales | setup → tension → turn → resolution → lesson; the lesson generalizes |
|
||||
|
||||
**Choosing:** one idea to understand → concept; an ordered procedure → how-to; parallel co-equal items → listicle; a concrete narrative/case → story.
|
||||
|
||||
**Compounds** layer an outer arc with an inner rhythm — e.g. `concept-explainer with process` (ordered steps inside the mechanism phase), `story-explainer with how-to`. Set `arc` in the frontmatter to the chosen structure (or `<outer> with <inner>`). The downstream visual phase reads it for pacing: a process inner rhythm means tighter seams on a consistent stage and shorter frames.
|
||||
|
||||
### 4. Build the frame sequence
|
||||
|
||||
Each frame needs one clear job. Avoid frames that only say "more detail" or "another point."
|
||||
|
||||
For every frame, define (use the storyboard format's fields, with these narrative additions in the frame's metadata + prose):
|
||||
|
||||
- `type` — one of `hook | pain_point | product_intro | feature_showcase | benefit_highlight | social_proof | branding | cta`. This enum is shared with the downstream visual layer for pacing; **repurpose** it for teaching per the mapping below.
|
||||
- `persuasion` — a **named** rhetorical / clarity technique (see catalog), not "explain the idea."
|
||||
- `beat` — the target feeling (see vocabulary).
|
||||
- `scene` — a one-line visual idea, not detailed composition.
|
||||
- `voiceover` — spoken guide text, or empty for silent frames.
|
||||
- `transition_in` — a registry transition name (see Transitions).
|
||||
- `blueprint` _(optional candidate)_ — consult the role→blueprint menu in `../hyperframes-animation/blueprints-index.md`; when a proven shape fits this beat, tag its id (a tag, not a commitment — Step 4 confirms or overrides). Then **write the `voiceover` in the shape that blueprint implies**, so the line is reveal-ready before Step 4 ever runs. Teaching truth still decides which beats exist — never invent, drop, or bend a beat just to fit a shape; omit `blueprint` and write the line plainly when none fits.
|
||||
|
||||
In the prose under each frame, state:
|
||||
|
||||
- `narrativeRole` — the scene's **job** in the explanation (e.g. "Concretizes compound interest as a snowball," not "Shows a chart").
|
||||
- `keyMessage` — the one thing the viewer should understand after this frame (one sentence).
|
||||
|
||||
### Type-enum repurposing (shared enum → explainer roles)
|
||||
|
||||
The enum is shared with the downstream visual layer; map your explainer roles onto it so downstream pacing matches the frame's job:
|
||||
|
||||
| Explainer role you want | Use `type` | Why this value |
|
||||
| -------------------------------- | ------------------- | -------------------------------------------------------------------- |
|
||||
| Hook / curiosity gap | `hook` | The high-leverage opening 3-5s. |
|
||||
| Pain / problem / why-care | `pain_point` | The friction or gap the explanation resolves. |
|
||||
| Name the core concept | `product_intro` | "Introduce the protagonist" — here the protagonist is the **idea**. |
|
||||
| Mechanism / step / item | `feature_showcase` | A unit of the body — one move of a process, one mechanism, one item. |
|
||||
| Implication / payoff / "so what" | `benefit_highlight` | The consequence or value of understanding. |
|
||||
| Evidence / example / data point | `social_proof` | A concrete grounding: a number, a worked example, a comparison. |
|
||||
| Thesis / takeaway / principle | `branding` | The philosophical landing — the generalizable idea, the one line. |
|
||||
| Call to think / try / act | `cta` | The closing ask — try it, watch for it, question it. |
|
||||
|
||||
The body is usually a run of `feature_showcase` (steps/mechanisms/items), interleaved with `benefit_highlight` (implications) and `social_proof` (examples/data). At least one `feature_showcase` or `product_intro` should exist (every explainer has a body and a named idea).
|
||||
|
||||
## Hook strategy
|
||||
|
||||
Pick one opening strategy for the first 3-5 seconds. For explainers the hook opens a cognitive gap or stakes:
|
||||
|
||||
| Strategy | Use when | Example |
|
||||
| ---------------------- | -------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| Shocking statistic | A credible number quantifies the stakes. | "90% of plastic ever made has never been recycled." |
|
||||
| Rhetorical question | Create an immediate cognitive gap. | "Why does time seem to speed up as you get older?" |
|
||||
| Counterintuitive claim | The truth contradicts common belief. | "Adding more lanes to a highway makes traffic worse." |
|
||||
| Pain validation | The audience already feels the confusion. | "Everyone says 'just diversify' — nobody says what that means." |
|
||||
| Visceral metaphor | The idea is abstract and needs to become concrete. | "Your attention is a spotlight, and apps fight over the switch." |
|
||||
| Concept announcement | The term itself is the subject; make it memorable. | "There's a word for this: the bystander effect." |
|
||||
| Direct address | The audience is clearly defined. | "If you've ever rage-quit a recipe halfway — this is for you." |
|
||||
| Imagine / scenario | A thought experiment frames the whole piece. | "Imagine money that loses value if you don't spend it." |
|
||||
| Stakes / consequence | The "why care now" is a real cost or risk. | "Get this one step wrong and the whole batch is ruined." |
|
||||
|
||||
The hook must create curiosity, tension, or stakes. Do not open with a generic definition. Per `../hyperframes-creative/references/story-spine.md`: the hook speaks the viewer's language (the payoff of understanding, never the source text's section headings), and the thesis (`message`) lands by beat 2 — the explanation after that is its evidence.
|
||||
|
||||
## Clarity / rhetoric technique catalog
|
||||
|
||||
`persuasion` is a **named technique** — how this frame makes the idea land or clear — not a vague intent. Combine when several are active (e.g. "Analogy + progressive disclosure").
|
||||
|
||||
| Family | Techniques |
|
||||
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Make-concrete** | Analogy / metaphor · Concretization (abstract → tangible object) · Worked example with real numbers · Anchoring on a familiar referent |
|
||||
| **Reveal-in-order** | Progressive disclosure (one term/layer at a time) · Build-up (simple → general case) · Signposting ("first… then… finally") |
|
||||
| **Contrast** | Before/after · Common-belief vs reality · Comparison of two options · Counterexample (here is when it breaks) |
|
||||
| **Structure** | Rule of three · Numbered enumeration · Question→answer pairing · Frame-then-fill (state the shape, then populate it) |
|
||||
| **Evidence** | Statistical proof · Citation / source · Demonstration (show the mechanism running) · Causal chain (A → B → C) |
|
||||
| **Memory & landing** | Callback (return to the hook's image) · Distillation (compress to one line) · Coined term / mnemonic · Generalization (specific → principle) |
|
||||
|
||||
When no catalog technique fits, name a new one inline and explain its mechanism (e.g. "Subtractive framing: define the concept by what it is _not_ first"). Never write generic "explain the idea."
|
||||
|
||||
## Emotional beats
|
||||
|
||||
`beat` is one word or a short compound phrase (e.g. "Curiosity and clarity"). Avoid generic "positive" / "interested." Explainers ride a comprehension arc:
|
||||
|
||||
- **Negative valley** — _open the gap_ (hook / pain_point): curiosity · puzzlement · surprise · tension · concern · skepticism · recognition · intrigue
|
||||
- **Pivot** — _orient_ (product_intro / concept-naming): clarity · orientation · anticipation · focus
|
||||
- **Build** — _build understanding_ (feature_showcase / benefit_highlight / social_proof): comprehension · "aha" · confidence · fascination · foresight · momentum · conviction · delight · unease (for a caveat) · mastery
|
||||
- **Resolution** — _land_ (branding / cta / final): clarity · satisfaction · resolve · inspiration · inevitability · "now I get it"
|
||||
|
||||
Compound beats are often strongest, e.g. "Surprise + recognition", "Comprehension + delight."
|
||||
|
||||
## The body is a sequence, not a single frame
|
||||
|
||||
An explainer's core is almost always **3-6 body frames on a consistent visual stage**, each advancing one mechanism / step / item / layer, building understanding cumulatively. A single isolated body frame rarely teaches anything.
|
||||
|
||||
- **concept-explainer:** name the concept (`product_intro`) → reveal the mechanism layer by layer (a run of `feature_showcase`, interleaving `benefit_highlight` for "so what" and `social_proof` for a grounding example).
|
||||
- **how-to-process:** `feature_showcase` per step, ordered, on one stage. Carry the object being acted on across adjacent steps (see Continuity).
|
||||
- **listicle:** `feature_showcase` per item; items are parallel, so default to `cut` / `push-slide` between them.
|
||||
- **story-explainer:** frames follow the beats (setup / tension / turn / resolution / lesson); types map per the table (`pain_point` for tension, `branding` for the lesson).
|
||||
|
||||
## Continuity across frames (no worker grouping)
|
||||
|
||||
This framework builds **one frame per worker** — there is no "continue run" that hands several frames to one worker. A sequence of frames reads as one continuous shot through two storyboard-level levers, both yours:
|
||||
|
||||
1. **A consistent stage** — consecutive body frames share the same composition idea (same diagram growing, same number line, same desk), stated in each frame's `scene` so Step 4 and the workers keep the stage stable.
|
||||
2. **A consistent transition** — pick one seam type for a sequence (usually `push-slide <DIR>` for ordered steps, `crossfade` for a soft layer reveal) and repeat it across the run, so the frames feel like one flow rather than separate slides.
|
||||
|
||||
When a single element genuinely _transforms_ between two ideas (a diagram node becomes a chart bar, a formula becomes its result), keep it within **one frame** as a development beat (entrance → the transform → settle) rather than splitting it across a seam — the worker owns that motion. Note the intent in the frame's `scene` / narrative; Step 4 turns it into a time-coded shot sequence (instantiating the candidate `blueprint`).
|
||||
|
||||
## Transitions
|
||||
|
||||
Use only registry transition names in `transition_in`:
|
||||
|
||||
`cut | crossfade | blur-crossfade | push-slide LEFT | push-slide RIGHT | push-slide UP | push-slide DOWN | zoom-through | squeeze`
|
||||
|
||||
Pick 2-3 transition types for the whole video and repeat them. Frame 1 uses `cut` as a placeholder (there is no previous frame). Match the seam to the narrative: ordered steps → a consistent `push-slide`; a soft layer reveal or atmosphere shift → `crossfade` / `blur-crossfade`; zooming into a detail or pulling back → `zoom-through`; a clean topic switch or new list item → `cut`.
|
||||
|
||||
## Faceless visuals — no asset inventory
|
||||
|
||||
Every visual is invented downstream from each frame's `narrativeRole` / `keyMessage` / `scene` — typography, abstract graphics, diagrams, data-viz are all first-class. Therefore:
|
||||
|
||||
- Do **not** write an `asset_candidates` line describing intended diagrams or typography as if they were files. Visual intent belongs in `scene` + `narrativeRole`; the visual phase reads those.
|
||||
- The **only** real asset is a user-supplied image already placed at `public/<basename>`. Then add one line `asset_candidates: public/<basename> — <≤25 words: what it is>`. Never invent paths or reference `capture/`.
|
||||
|
||||
## Script rules
|
||||
|
||||
### If there is no pasted script
|
||||
|
||||
Write tight per-frame narration:
|
||||
|
||||
- 1-2 sentences per spoken frame; usually 6-20 words.
|
||||
- Concrete and human; teach, don't read the article aloud.
|
||||
- **Write each line as discrete cues, not one run-on breath.** Step 5 reveals each on-screen piece _when the voiceover names it_ (the anti-PowerPoint mechanism). A line with clear phrase boundaries — "First the snowball — then the hill — then the speed" — hands the shot its reveal cadence for free; a single long clause leaves the frame nothing to pace to.
|
||||
- **Strong** (concretization): "Compound interest isn't addition, it's a snowball — every turn picks up the snow from the last, then more."
|
||||
- **Weak** (article-paraphrase): "The study, published in 2019, examined three cohorts and found that…" — that is reading, not explaining.
|
||||
|
||||
Avoid: "Unlock the power of…", "Seamless experience", long noun-phrase lists, a frame that is only a filler bridge ("Or…").
|
||||
|
||||
**Silent frames are allowed and common in explainers** — a diagram assembling itself, a worked example animating, a beat of held tension before a turn. Set `voiceover` empty and leave the frame out of `SCRIPT.md`; then `narrativeRole` + `persuasion` must carry what the script doesn't say.
|
||||
|
||||
### If `VO_MODE = restructure`
|
||||
|
||||
Treat `user_script.txt` as source material. Rewrite, reorder, merge, or omit to fit the chosen structure and target length.
|
||||
|
||||
### If `VO_MODE = verbatim`
|
||||
|
||||
Do not rewrite the user's words. Segment the script into frame-sized chunks at sentence or paragraph boundaries (you may split a long sentence at a natural clause boundary, but do not change words). Final duration follows the provided script.
|
||||
|
||||
## Frame template
|
||||
|
||||
Use the exact fields required by the core storyboard format. This is the narrative shape each frame should satisfy:
|
||||
|
||||
```md
|
||||
## Frame N — Short name
|
||||
|
||||
- scene: one clear visual idea
|
||||
- voiceover: "spoken guide text, or empty"
|
||||
- duration: rough estimate in seconds
|
||||
- transition_in: crossfade
|
||||
- status: outline
|
||||
- src: compositions/frames/NN-short-name.html
|
||||
- type: feature_showcase
|
||||
- persuasion: Progressive disclosure
|
||||
- beat: comprehension
|
||||
- blueprint: messaging-multi-phase — candidate shape from the role→blueprint menu; omit when none fits
|
||||
|
||||
narrativeRole: What this frame does in the viewer's understanding.
|
||||
keyMessage: The one idea the viewer should remember.
|
||||
```
|
||||
|
||||
## Final checklist
|
||||
|
||||
Before asking for user approval, verify:
|
||||
|
||||
- One explainer structure is named (compound only when explicitly named); the sequence is narrative-driven, not paragraph-order-driven.
|
||||
- The opening uses a named hook strategy.
|
||||
- Each frame has one job; the body builds cumulatively (a run of `feature_showcase` / `benefit_highlight` / `product_intro`), not a single isolated body frame.
|
||||
- Every frame has `type`, `persuasion` (a named technique from the catalog), and `beat` (specific, not generic).
|
||||
- Each `voiceover` is phrase-segmented into cues (each a piece Step 5 can reveal on), not one run-on clause; a candidate `blueprint:` is tagged wherever a proven shape fits, and omitted where none does.
|
||||
- The emotional arc has meaningful variation matching the structure.
|
||||
- Transitions use only registry names and repeat 2-3 types; frame 1 is `cut`.
|
||||
- A consistent stage + consistent transition carry any multi-frame sequence; a genuine element transform stays inside one frame.
|
||||
- `asset_candidates` is absent (faceless) except a real user-supplied `public/<basename>`.
|
||||
- `SCRIPT.md` contains only locked spoken narration; silent frames are intentional and omitted from it.
|
||||
@@ -0,0 +1,146 @@
|
||||
# Visual design — faceless-explainer per-frame shot method
|
||||
|
||||
> The method behind **Step 4 (Frame visual design)**. You (the orchestrator) read it to **enrich `STORYBOARD.md` frames in place** — story-design wrote the skeleton (each frame's `scene`, `voiceover`, `transition_in`, the narrative fields, and optionally a candidate blueprint id); you add how each frame **looks and moves**. The unit you write per frame is a **time-coded shot sequence** — a shot directed across its whole duration, not a static slide. You write **no HTML** (that's the frame workers). Because the explainer is **faceless, every visual is invented** — typography, abstract graphics, diagrams, data-viz — so you **design** the visual elements rather than select captured assets (there is no `capture/` to read). `frame.md` is your palette/type truth by role. Layout is a compact vocabulary in this file (the **Layout** section below), stated inline per Scene; motion vocabulary + the motion doctrine + the seek-safe core → `motion-language.md`; the proven shapes → `../hyperframes-animation/blueprints-index.md` + `blueprints/<id>.md`; concrete rules resolve in Step 5 from this skill's local `../hyperframes-animation/rules/`. Adding palette theory or a generic font rule here? Wrong home — `frame.md` + `hyperframes-creative`.
|
||||
|
||||
## The unit is a time-coded shot sequence
|
||||
|
||||
A frame's visual layer is **a sequence of time windows paced to the voiceover**, not a bag of effect tags. The failure that reads as PowerPoint is **front-loading**: the agent rushes the whole canvas on screen in the first ~25%, and then it just sits. A time-coded shot sequence written **against the VO** makes that impossible: each window states what is on screen and what is moving, and **nothing appears before the voiceover reaches it.** In an explainer the development _is_ the teaching — the formula assembling term by term, the diagram gaining a layer, the count-up landing the statistic. Let the build _be_ the message.
|
||||
|
||||
Write each frame as a handful of windows cued by the spoken line:
|
||||
|
||||
```
|
||||
Scene 1 (0.0–Xs): only what the VO is saying at t=0 enters — never the whole canvas
|
||||
Scene 2 (Xs–Ys): the next piece reveals as the VO names it (a line / layer / node / stat)
|
||||
… one window per spoken cue — as many or as few as the line calls for
|
||||
Scene N (…–end): content has resolved; hold the read (stillness; subtle jitter at most)
|
||||
```
|
||||
|
||||
- Each `Scene` line names **what's on screen**, **what moves in this window**, and **where it sits** (layout, inline). Times are real seconds across the frame's `duration`.
|
||||
- **Pace reveals to the voiceover; never front-load.** This is the core anti-PowerPoint mechanism (→ `motion-language.md` Part 2 Rule 2). At t=0 show only what the VO is saying then; reveal each further piece — a line, a layer, even an h1 — **when the VO names it**, spreading reveals across the shot and especially the **back ~50%**. **The window count = the number of spoken cues the line calls for** — a two-beat line is two windows, a five-item enumeration is five or six. There is **no fixed count and no mandatory "middle" act**; the only sin is dumping everything up front. (A **silent** frame — a diagram assembling itself, a worked example animating — paces its reveals to the beat instead of the VO; same discipline, no spoken cue.)
|
||||
- **End on a held read.** Once the content has resolved it holds and reads — **prefer stillness to bad motion**: no forced camera drift, no lazy breathing, no back-half pan/push; at most a subtle jitter keeps it alive (→ `motion-language.md`). On a short shot the final reveal and the hold are the **same window** — the hold is not a separate mandatory act. Only the final frame has a real exit; every other frame's exit is the harness transition (story's `transition_in`).
|
||||
- A **deliberately held** frame — content already revealed, now reading still — is legitimate and often right (a climax, a breather, a beat of held tension before a turn). The failure is never "too still"; it is **front-loaded-then-frozen** (everything dumped by ~25%, nothing cued to the VO). Place held beats deliberately for rhythm so the video isn't uniformly busy (allocate them in `## Video direction`). Reveal pacing + holds + the idle budget → `motion-language.md`.
|
||||
|
||||
## Pick the shape — instantiate a blueprint
|
||||
|
||||
Don't invent each shot from scratch. The frame's **role** (its `type` / `beat`) points to a proven shape:
|
||||
|
||||
1. **Match the role to a blueprint.** Open `../hyperframes-animation/blueprints-index.md`, find the frame's role in the **role→blueprint menu**, and pick the blueprint whose intent fits this beat (story may already have named a candidate id — confirm or override it). Read that `blueprints/<id>.md`: it is a short, domain-agnostic, **time-coded shot template with `[slots]`** and a named **signature move** (the thing that makes the shape itself — the SVG ring, the push-THROUGH, the in-place token swap).
|
||||
|
||||
2. **Instantiate its `[slots]` with THIS frame's invented content** — three postures:
|
||||
- **Reproduce** — the blueprint fits the beat and your content maps onto its slots cleanly. Fill every `[slot]` with this frame's word / shape / stat and follow its Scene timing. Write the resulting Scene lines.
|
||||
- **Adapt** — the _structure_ fits but the content / element-count / surface doesn't (or you want a fresher surface to avoid templating). State **what you keep / what you change** in one line, then write the adapted Scene lines. You may extend or vary; you may **never** drop the **signature move** (drop it and you picked the wrong blueprint), and you keep the reveals **paced to the VO** — never collapse the shape to a single front-loaded dump.
|
||||
- **Compose** — no blueprint fits the beat. Build the shot from the **motion vocabulary** in `motion-language.md`: still pace the reveals to the VO across the shot, never fire everything at t=0. Mark it `blueprint: compose`.
|
||||
|
||||
3. **Keep the signature move.** Whichever posture, the blueprint's signature move (named in its file) is the spine of the shot — it usually lands on the shot's key reveal. Carry it through.
|
||||
|
||||
The blueprint's own Scene lines, motion vocabulary, and `rule mapping` are your raw material; you are choosing a shape and casting this frame's invented content into it, not copying an engineering spec.
|
||||
|
||||
## What you add to each frame
|
||||
|
||||
Story-design's `## Frame N` block already carries the narrative. You append the shot. Story's `scene` / `voiceover` / `transition_in` / role fields stay untouched.
|
||||
|
||||
```
|
||||
## Frame 3 — How interest compounds
|
||||
- scene: a snowball rolls downhill, gaining a labeled ring each turn ← refine only if it could read sharper
|
||||
- voiceover: "…" ← story's; leave it
|
||||
- transition_in: crossfade ← story's; leave it
|
||||
- type: feature_showcase ← story's
|
||||
- persuasion: Concretization + progressive disclosure
|
||||
- beat: comprehension
|
||||
- blueprint: dataviz-countup (Adapt) ← you add: the id you instantiated (or "compose")
|
||||
- focal: the snowball ← you add: the INVENTED hero element of this beat
|
||||
- roles: snowball = foreground subject · hill = background gradient (dim ~40%) · ring labels = supporting ← you add: role per invented element
|
||||
- sfx: whoosh-soft, tick ← you add: the sound the beat wants (fetched + mounted at root; never yours to embed)
|
||||
|
||||
Adapt: keep the count-up-ring signature; the trend chart becomes the snowball's labeled rings climbing.
|
||||
Scene 1 (0.0–1.2s): solid hill gradient (dim ~40%); the snowball seats upper-left, a circular progress ring + bold center number anchor it — Centered template, ~50% of frame. Slow push-in runs underneath.
|
||||
Scene 2 (1.2–3.4s): as the VO names each turn, the snowball rolls down and gains one labeled ring per turn (layer-reveal); a small total ticks up beside it (the count-up reveals on its spoken cue, not at t=0). Asymmetric 60/40, 3 depth layers.
|
||||
Scene 3 (3.4–5.0s): land the final ring emphasis dead-center, accent glow blooms behind it and holds; the total reads clean and STILL — no continuing push, no breathing (a held beat beats bad motion). The stillness reads against the prior motion.
|
||||
```
|
||||
|
||||
The lightweight tags:
|
||||
|
||||
- **`blueprint:`** — the id you instantiated (with `(Reproduce)` / `(Adapt)`), or `compose`. One id per frame.
|
||||
- **`focal:`** — which **invented** element is the hero of this beat (a hero word, a diagram node, a chart series, a coined-term card).
|
||||
- **`roles:`** — each invented element's role: `foreground subject` (the thing the eye lands on, text laid around it) · `background` (full-bleed field / gradient / grid, dim 30–50%) · `supporting` (labels, secondary shapes, ambient layers). Since there are no captured assets, you are **designing** these elements, not selecting them — keep them **few and load-bearing**. A user-supplied `public/<basename>` image, if any (named in story's `asset_candidates`), is treated as the `focal` cutout or a `background`.
|
||||
- **`sfx:`** — name the sound the beat wants (an impact for a slam, a whoosh for a push, a tick for a count). The audio script's `fetch-sfx` pass retrieves it and the assembler mounts it at the root — you only **name** it, never embed an `<audio>` element.
|
||||
|
||||
**Layout is stated INLINE in each Scene line** — name the template, density, depth, and hierarchy as part of "where it sits" (`Centered, ~50% of frame`, `asymmetric 60/40, 3 depth layers`), drawing on the **Layout** vocabulary below; never write px / scale / shadow recipes (the worker writes those).
|
||||
|
||||
**Motion is named INLINE in each Scene line** — name the move from `motion-language.md`'s vocabulary (`per-word reveal`, `layer-reveal`, `count-up`, `glow blooms`) and let it settle on a long-tail curve (`power3` default — smooth beats bouncy; see `motion-language.md`). Never write ease curves / ms / stagger (those resolve in Step 5 from this skill's local `../hyperframes-animation/rules/`).
|
||||
|
||||
## Inventing the visual — diagrams, type, data-viz
|
||||
|
||||
This is a **faceless** explainer: the frame's hero is something you **design**, not a screenshot. Three first-class treatments, each invented from the frame's `narrativeRole` / `keyMessage` / `scene`:
|
||||
|
||||
- **Typographic / kinetic type** — the hero word, the coined term, a number, a short enumeration. Treat type as the subject: full-bleed scale, weight contrast, one emphasized term. Strongest for hooks, concept names, takeaways. In a faceless explainer **type is often the primary visual** — lean on the type ramp hard.
|
||||
- **Abstract graphics** — shapes, fields, paths, geometry that _embody_ the idea (the snowball, the spotlight, the staircase-not-cliff). Build the metaphor the script names; don't decorate with generic bokeh.
|
||||
- **Diagram / data-viz** — nodes + edges, a chart, a number line, a formula, a process flow. The build (each part appearing on beat) is the teaching — design it to assemble across the Scenes, not appear whole.
|
||||
|
||||
Make the invented hero **fill 40–60% of the frame** — a diagram big enough to read its labels, a hero word near full-bleed. Don't shrink the one designed element into decoration around empty space.
|
||||
|
||||
## Layout — named inline per Scene
|
||||
|
||||
State each Scene's layout as part of "where it sits." **If the blueprint already implies a composition** (a ring around a center, stations on a wide canvas, two cards from opposite wings), that wins — describe it directly; the vocabulary below is for **composing freely** or a generic beat, not a menu you must pick from. Never write px / scale / shadow (the worker does). One frame's layout can EVOLVE across its Scenes (Scene 1 centered hero → Scene 2 rearranges to a grid). Use **≥3 different framings per video** so it doesn't read as one repeated template; never the same framing twice in a row.
|
||||
|
||||
- **Framing vocabulary** — centered (hero / climax) · rule-of-thirds · split-screen (comparison) · layered-depth (immersive opening / atmosphere) · asymmetric 60/40 or 70/30 (editorial — a dense diagram + a caption rail) · triptych (three items / the rule-of-three landing) · full-width strip (a number line / timeline / enumeration). Vary the framing across the video so it doesn't read as one repeated template — let the beat decide, not a quota.
|
||||
- **Density** — primary visual ≥ 40% of canvas; ≥ 3 depth layers (background + midground + foreground); never a lone small cluster floating in empty space. Openings and closings are prone to emptiness — add environmental layers (dual-radial swell, low-opacity scanlines, a hairline grid, brand-color ambient). Squint test: after blur you can still pick out the #1 element.
|
||||
- **Hierarchy** — combine ≥ 2 of size (3:1) / weight (800 vs 400) / contrast / position (upper-third is golden) / motion, so one element clearly dominates. A title that is only _larger_ (sharing weight/color/spacing with body) reads weak.
|
||||
- **Depth** — layer 2–3 of: size, blur, opacity gradient, overlap, shadow-stack, counter-scale on a push.
|
||||
- **Don't show**: nav bars, footers, scrollbars, real cursors / browser chrome, generic decorative shapes standing in for a designed metaphor, floating bokeh / purple-blue "AI" gradients (the default-AI cliché, banned). A faceless explainer has no real interface — an interface mock is correct **only** when the topic itself is about that interface and the frame intentionally reconstructs it.
|
||||
|
||||
## Portrait & square (non-16:9 canvases)
|
||||
|
||||
The zones, density, hierarchy, and depth principles all still apply; the **aspect ratio** changes, and a wide-frame layout does not transplant into a tall one — design for the storyboard's `format` from the start, never plan landscape and "crop."
|
||||
|
||||
- **Stack vertically, not side-by-side** — split-screen / triptych / 60-40 become top/bottom stacks, vertical step lists, stacked bands. Square tolerates side-by-side only for two compact items.
|
||||
- **Vertical center moves with the canvas** — anchor a centered hero around **y ≈ 0.42 × height** (portrait ≈806, square ≈454), not a fixed 540.
|
||||
- **Type runs larger, fewer words per line** — narrow frames wrap long headlines badly; prefer short kinetic lines, bigger type, more vertical rhythm.
|
||||
- **Travels well to portrait:** Centered, Layered Depth, Full-Width Strip (stacked band), vertical Rule-of-Thirds. **Avoid** wide Split Screen and Triptych — use stacked equivalents.
|
||||
|
||||
## `## Video direction` — write the invariants ONCE
|
||||
|
||||
The whole video shares one look and one motion grammar. Write a **`## Video direction`** block ONCE at the top of `STORYBOARD.md` so every frame inherits it and per-frame Scene lines carry only the **delta**. This block is load-bearing — it is what binds many independent shots into one film. **Keep it.**
|
||||
|
||||
- **palette system** — from `frame.md`: which roles map to which hues. Never invent.
|
||||
- **motion grammar + reveal model** — long-tail eases (`power3` default, smooth over bouncy) + the **VO-paced reveal** model every frame follows (reveal each piece on its spoken cue; never front-load) + what may stay alive during a hold (subtle jitter at most; no lazy breathing) (→ `motion-language.md`).
|
||||
- **rhythm / held-frame allocation** — name the **held / breather frames** (often before a climax or the turn in a story) so the video varies its energy: most frames reveal to the VO, a few hold still (a held read beats bad motion; the anti-monotony discipline; → `motion-language.md`).
|
||||
- **negative list** — what never appears: off-brand textures / effects the pack forbids, **plus both motion failure modes** — slideshow (front-load then freeze) and screensaver (everything floating independently) (→ `motion-language.md`).
|
||||
|
||||
Do **not** repeat these per frame — restating video-level rules in every frame is exactly the bloat this layer prevents.
|
||||
|
||||
## Palette & type — from `frame.md`, never invented
|
||||
|
||||
- **Palette** — `frame.md` (the adopted pack) is the color truth; apply its roles per frame. Generic basics (one accent, tint neutrals, avoid pure `#000`/`#fff`) → `hyperframes-creative/references/house-style.md`.
|
||||
- **Type** — fonts resolve via `frame.md`'s type tokens; reference them **by role** (display / body / mono / the pack's ramp), never by raw family or px. Generic typography craft (embedded fonts, dark-bg optical compensation, `tabular-nums`) → `hyperframes-creative/references/typography.md`. In a faceless explainer type is often the primary visual — the hero word, the coined term, the kinetic enumeration — so lean on the type ramp hard.
|
||||
|
||||
## Caption-band keep-out (plan side)
|
||||
|
||||
The bottom ~17% of the canvas is reserved for the caption pill. Plan every frame's content into the **top ~83%** so nothing important lands in the band (the worker enforces the pixel cutoff; you plan the layout). When captions are enabled, primary content and key visuals **cap at the band top**, and a centered hero anchors at **y ≈ 0.42 × height** (landscape ≈454, portrait ≈806), not the canvas midpoint; background / ambient / surface layers are exempt and may stay full-bleed. Holds even when captions are disabled — bottom-edge consistency.
|
||||
|
||||
## Where the detail lives
|
||||
|
||||
| For… | Read |
|
||||
| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| the proven shapes + role→blueprint menu + how to pick | `../hyperframes-animation/blueprints-index.md` → `blueprints/<id>.md` |
|
||||
| motion — shot model, vocabulary, holds, idle budget, stillness, seek-safe | `motion-language.md` (local) |
|
||||
| layout — framing, density, depth, hierarchy, inventing the visual, caption band | the **Layout** + **Inventing the visual** sections in this file |
|
||||
| concrete eases / ms / stagger + rule recipe bodies (Step 5) | local `../hyperframes-animation/rules/` (the frame worker reads it; you don't) |
|
||||
| palette + type tokens | the project's `frame.md`; basics → `hyperframes-creative` `house-style.md` / `typography.md` |
|
||||
| "produced, not generated" foreground density | `hyperframes-creative/references/video-composition.md` |
|
||||
| within-frame cuts / seams (zoom-through · cut-the-curve · waterfall) | `cut-catalog.md` (the worker builds them inside the composition) |
|
||||
| transitions | story-design owns `transition_in`; you don't touch it |
|
||||
|
||||
## Before you finish — checklist
|
||||
|
||||
- **`## Video direction`** written once at the top (palette · motion grammar + shot model + idle budget · stillness allocation · negative list incl. both failure modes); per-frame entries are deltas, not restatements.
|
||||
- Every frame is a **time-coded shot sequence** with real second windows across its `duration` — not a tag bag.
|
||||
- **No frame front-loads** — at t=0 only what the VO is saying enters; each further piece reveals on its spoken cue, across the back ~50%. Window count follows the VO (or the beat, on a silent frame), not a fixed number.
|
||||
- Every frame names a **`blueprint:`** id (Reproduce / Adapt) or `compose`; an Adapt states keep/change and **keeps the signature move**; nothing collapses to a single front-loaded dump — reveals stay paced to the VO.
|
||||
- **Held frames are deliberate** — allocated in Video direction for rhythm; a held read is fine (prefer stillness to bad motion), but no frame may be front-loaded-then-frozen.
|
||||
- Each frame names its **invented** `focal` + per-element `roles` (foreground / background / supporting), kept few and load-bearing.
|
||||
- The invented hero fills 40–60% of the frame (a diagram big enough to read, a hero word near full-bleed) — not shrunk into decoration around empty space.
|
||||
- Layout named **inline** per Scene (template / density / depth / hierarchy — the **Layout** vocabulary here); motion named **inline** per Scene from the vocabulary (`motion-language.md`). No px / ease curves / ms / JS.
|
||||
- Content planned into the top ~83% (caption band clear).
|
||||
- Palette / type pulled from `frame.md` by role — nothing invented.
|
||||
- You wrote no HTML; every visual is invented (no captured assets).
|
||||
Reference in New Issue
Block a user