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,49 @@
|
||||
# PORTING — turning a cap_fx3 demo into a first-class theme DNA
|
||||
|
||||
One theme at a time. The demo is the spec; the engine is the law.
|
||||
|
||||
## Inputs
|
||||
|
||||
- Demo: `~/Downloads/cap_fx3/<tNN_name>/` — index.html (bg: scene-reaction + apex
|
||||
setpiece), rail.html (fg alpha: body + furniture + front fx), postfx.json,
|
||||
final_fx.mp4 + strip.png (ground truth of how it should look).
|
||||
- Engine: `scripts/make-theme.cjs` — read the header + the existing paradigms
|
||||
(rail/panel/poem/takeover) and setpieces (detonation/decode/drawon/assembly/
|
||||
colorflip/cpslam/coverword/settle) before writing anything.
|
||||
|
||||
## Process
|
||||
|
||||
1. DECOMPOSE the demo: body paradigm? body entrance/exit verbs? hero setpiece?
|
||||
front fx? plate budget? linkages? Map each piece to an existing registry
|
||||
entry or mark it NEW.
|
||||
2. EXTEND the engine for the NEW pieces only — port the demo's GSAP logic into
|
||||
generator functions, parameterized (sizes, colors, counts, seeds become DNA
|
||||
params). Registries stay generic: paradigms/setpieces are the unit of code,
|
||||
the DNA json is the unit of identity. Match the file's existing code style.
|
||||
`node --check scripts/make-theme.cjs` after every edit.
|
||||
3. WRITE `themes/<name>.json` (drop the tNN\_ prefix). voice/when/register/fonts/
|
||||
palette/body/hero/fx/plate/linkages — follow anchor.json + ordnance.json shape.
|
||||
4. VERIFY on the rooftop fixture:
|
||||
- scaffold: `mkdir ~/Downloads/port_<name>` + symlink source.mp4 / frames_fg /
|
||||
frames_bg + cp matte.fps transcript.json safe-zones.json from
|
||||
`~/Downloads/cap_multi/rooftop/` (frames_bg from `~/Downloads/cap_fx/_frames_bg`).
|
||||
- theme.json: same lines/hero the demo used (read its rail.html data).
|
||||
- `node scripts/make-theme.cjs <dir>` → `preview-frames.cjs <dir> <4 key times>`
|
||||
→ READ the previews; compare against the demo's strip.png. Iterate ≤3 rounds.
|
||||
- full render: `bash scripts/render-theme.sh <dir>` → extract a 12-frame strip
|
||||
around the apex → view → compare to the demo strip. Small deviations OK,
|
||||
note them; the THEME must read identically at a glance.
|
||||
5. REGRESSION: recompile one prior theme project (e.g. `~/Downloads/cap_anchor`,
|
||||
plus the previous port in this batch) — make-theme must still compile and a
|
||||
2-frame preview must look unchanged.
|
||||
6. REGISTER: add the identity row to CATALOG.md (voice/when/needs, author →
|
||||
make-theme) and a line in themes/README.md if it has one.
|
||||
|
||||
## Hard rules
|
||||
|
||||
- The CONTRACT.md disciplines apply verbatim (determinism, physics doctrine,
|
||||
body stability, apex-owns-frame, equal-length keyframes, fonts whitelist,
|
||||
≤ DUR scheduling): `~/Downloads/cap_fx3/CONTRACT.md`.
|
||||
- Never edit existing setpieces'/paradigms' behavior unless fixing a bug —
|
||||
existing themes must not change appearance.
|
||||
- Do NOT commit; the orchestrator reviews and commits per batch.
|
||||
@@ -0,0 +1,244 @@
|
||||
# THEME mode — composed visual constitutions
|
||||
|
||||
Theme mode is the third compiler (`scripts/make-theme.cjs`), beside Standard and
|
||||
Cinematic. It exists because "mode" was a bundle of orthogonal axes pretending
|
||||
to be one switch. A theme DNA composes its identity from registries implemented
|
||||
ONCE in the compiler — **paradigms are the unit of code; DNAs are the unit of
|
||||
identity**. A new look is a JSON file; only a genuinely new paradigm/setpiece
|
||||
(rare) touches the compiler.
|
||||
|
||||
```
|
||||
theme DNA = body PARADIGM how the transcript surface lives
|
||||
× body LAYER fg-alpha (rail.html channel) | bg-embed
|
||||
× hero SETPIECE the climax choreography
|
||||
× front FX flash / rings / sparks / scanband / crowdflash / paflash (fg, over subject)
|
||||
× PLATE budget charge-dim (in-page) + punch/shake/grain (_postfx.sh)
|
||||
× LINKAGES declarative theme interactions
|
||||
```
|
||||
|
||||
Standard and Cinematic were, in retrospect, two fixed points of this space.
|
||||
Standard is now RETIRED (2026-06-12): its rail×embed-climax point is served by
|
||||
the `anchor` theme (rail paradigm × settle setpiece — the quiet default).
|
||||
Cinematic remains a separate compiler; do not re-implement it as a theme yet.
|
||||
|
||||
## Unification roadmap (strangler fig — interface first, engines later)
|
||||
|
||||
The user-facing model is already unified (SKILL.md Step 0): one catalog of
|
||||
LOOKS; classic looks pick a DELIVERY (rail | column), themed looks bind their
|
||||
own. "Standard/Cinematic" are delivery/compiler names, not modes. Remaining
|
||||
phases, each gated on need — never rewrite for tidiness alone:
|
||||
|
||||
- **Phase 2 — one authoring schema.** `lines`/`minors`/`hero` are already
|
||||
~90% shared between standard.json and theme.json; a router that translates a
|
||||
single `caption.json` into the engine-specific file removes the last
|
||||
user-visible seam. cinematic.json's blocks/planes are the odd one — map the
|
||||
common fields, pass engine-specific ones through.
|
||||
- **Phase 3 — engine convergence.** Port a classic delivery into make-theme
|
||||
ONLY when something forces it (e.g. a classic DNA wants a plate budget or a
|
||||
setpiece). Acceptance bar: blind A/B on the cap_multi regression scenes vs
|
||||
the old compiler — swap engines only when indistinguishable or better. Until
|
||||
then the old compilers are the reference implementation of 8 rounds of
|
||||
validated typography (lockup/orbit, multi-climax, ratio-lock, per-plane
|
||||
legibility, occlusion adjudication) — that machinery is the moat, not debt.
|
||||
|
||||
## Body paradigms (registry)
|
||||
|
||||
| paradigm | surface | layer | entrance verbs | exit verbs |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `rail` | lower-third lines, replace | fg | `stamp` (1f hot appear→crush→recoil→cool), `flick` (tube double-flick), `bootflick` (corrupted-cyan boot 1–2f → settles to UI color; minors keep a cyan/red registration shadow). `stamp` minors cool to `palette.minorCool` (default amber) | `drop` (mass falls), `powercut` (bright→ghost→off) |
|
||||
| `panel` | docked glass console, accumulate + typed | fg | `type` (width steps per word, $ prompt, caret blinks) | hold |
|
||||
| `poem` | open-space stanzas, accumulate; letters CONDENSE from seeded dust | fg | `condense` | `drift` (stanza hand-off) + optional dispersal linkage |
|
||||
| `takeover` | full-frame hard-cut cards, plate dimmed throughout | bg | `cut` (+ tension `creep` before silences, auto-detected) | hard cut / blur dissolve |
|
||||
| `lastpage` | manuscript rail (typed serif) + a seeded field of BLURRED apex-word instances haunting the room from t=0 | bg | typed rail; field breathes imperceptibly | rail fades; field resolves at apex (see `rackfocus`) |
|
||||
| `flaprail` | split-flap word tiles on a chyron bar (tag + ROW flip-counter; optional odometer chip docks above the bar while the first emphasis line reads) | fg | `splitflap` (3 flips: wrong word → wrong word → real word clacks on hot, squash → elastic settle → cools to bone; emphasis tiles keep amber text + underline) | flip-to-blank cascade left→right (completes before the next line) |
|
||||
| `ledboard` | amber LED departure strip docked lower-third (`body.board` geometry); lines page by vertical scroll-snap (steps(6)) inside the board window; furniture: green platform tag, ticking seconds clock (stacked digit reel), ⚠ DELAYED blinks then pages to ● ON TIME ~0.7s after the apex, idle LED shimmer in dead air ≥1.2s | fg | `ledwipe-mini` (per-word L→R LED column wipe, clipPath steps(len), + 1-frame arrival flicker; emphasis words get the LED-refresh double-blink; last word gets one late refresh) | scroll-snap page-up (next line pages in at the same instant) |
|
||||
| `vhsrail` | camcorder-playback lower third: every word carries a PERMANENT 1px red+cyan misregistration fringe (split clip-path halves); furniture: ▶ PLAY / ◀◀ REW top-left (REW gag in dead air ≥0.7s + the final rewind), ● REC top-right through the apex window, green timestamp bottom-right with 1 Hz blinking colon, idle tape-drift line in long silences, plus apex-coupled artifacts (1-frame white tear band + head-switching noise bar at REC FREEZE, scrub lines at the apex band on the hero rewind) | fg | `trackglitch` (instant on + 2-frame y-shake + 1-frame band-slice shift of the word's bottom half; emphasis = PAUSE jitter ±1px y oscillation + white noise-band flicker) | REWIND streak left + flat-white echo copy + 2 scrub-line flickers |
|
||||
| `hudrail` | arcade-cabinet HUD: whole frame plays through CRT overlays (scanlines `body.scan` + corner vignette); docked HUD bar (`body.bar` geometry, 2px accent border, glow) with `body.tags` 1UP / CREDIT furniture — the 1UP tag blinks on the classic 0.45s attract cadence all clip; HUD yields (`body.yield`) while the boss lands | fg | `coinpop` (instant-on + steps(2) scale pop from the baseline + 1-frame white coin-blip tick over the word; emphasis = 3-frame palette swap body→accent→magenta→body) | checkerboard dissolve (words vanish in 2 alternating 2-frame passes, line off ≤ DUR−0.02) |
|
||||
| `carbonstrip` | cold-war case-file transcript strip docked on the clearer side (manila gradient, punch holes, faint red `body.watermark`, typed `body.header` that types on by width steps); lines live on up to `body.rows` fixed slots; PAGES (broken at full rows, dead-air gaps > 0.7s, and after the hero hand-off line — it is filed away while the stamp owns the frame); the strip top-shadow breathes during the stamp's dead-still hold and the strip yields (`body.yield`) while it lands; the final page is pulled with the whole strip at clip end | fg | `hammer` (per-char sets 30ms apart, scale 1.35→1 in one frame = the stamp motif at low amplitude; seeded ±1.2px baselines + seeded ribbon-ink opacity; every strike kicks the strip 1px — y-channel locked while the strip itself tweens; emphasis words get a red ink ellipse drawn around them, 0.25s) | X-row over-strike (3 chunks per line, 0.05s apart, lines 0.16s apart) → carriage yank-down feed → return; roomy cadence in dead air, compressed when the next page is close — always completes before the next page's first strike |
|
||||
| `laserrail` | concert lower third: lines centered on a bottom rail (`body.bottomPx`), uppercase laser-green words with a neon text-glow; emphasis words render at `body.minorScale`× with a hotter glow; word centers are BAKED at compile time from the measured char-width table (`assets/fonts/char-widths.json`, ≤3px vs browser ground truth) so the beam aim can't be skewed by font-load timing; per-word furniture = two thin beams (accent from top-left, magenta from top-right) that sweep to CONVERGE on the word 2 frames early + a convergence flare; beams dim ×`yield.beamDim` inside the apex window and the visible line dims to `yield.dim` | fg | `igniteconverge` (beams converge at st−0.083 → flare pop → word snaps on at opacity 1 with brightness 1.85, crush 0.09s power3.in → 2-frame contact squash → elastic settle → brightness cools; emphasis = single 1-frame strobe off/on + lingering beams) | sweeper beam crosses L→R in 0.13s and each word streaks away (x+44, blur 5) as it passes; line off ≤ DUR−0.02 |
|
||||
|
||||
| `stormrail` | rain-washed lower third: ambient rain = `body.rain.count` seeded thin streaks falling on repeating linear cycle tweens (pure f(t), one slanted wind vector, mid-fall at t=0); a second seeded set DOUBLES the rain for ~1s after the strike; lines sit on a bottom gradient scrim (stable reading surface); the visible line dims to `yield.dim` while the bolt lands and its text-shadow flips toward the strike (`hero.params.side`) for the flash frames | fg | `lightningpop` (the apex motif at low amplitude: instant on at brightness 2.2, y+4, scale 1.06 → 0.12s micro settle; emphasis = sheet-lightning double flash, 2-frame brightness 1.9/1.0/1.8 chain — the bg sky double-kisses at the same beats) | wash downward with the rain (y+22, blur 3, 0.18s power1.in); a line facing dead air washes early at lastWord+1.08s; line off ≤ DUR−0.02 |
|
||||
| `holorail` | volumetric projection plate: a scanlined glass slab (`body.plateW`×`plateH`, centered at `H − bottomPx`) with corner brackets + feed tag (`body.tag` / `theme.plateTag` override) boots like a projector turning ON (scaleY 0.03→1 expo + 1-frame flicker) and breathes a finite yoyo luminance cycle sized to the clip length; lines sit centered IN the plate (`lineDy` below plate center) with a constant chromatic-fringe text-shadow (−1.5px accent / +1.5px magenta) and drift slowly in rotationY (it IS a projection); the whole railwrap — plate included — dims to `yield.dim` while the apex lands | fg | `sweepboot` (the apex motif at low amplitude: instant opacity + rising clip-wipe reveal 0.15s + 1-frame x interference glitch at st+0.05/0.09/0.13; emphasis = 2-frame projection DROPOUT at `body.emphDelay`, restores brighter in `palette.em` with a hotter fringe, then settles back — the delay auto-shrinks near the line's exit so dropout+restore always complete) | projector cut — brightness 2.2 pop → collapse to a horizontal slit (scaleY 0.045, 0.07s power3.in) → to a dot (scaleX 0.015, 0.06s) → off at exit+0.15; the plate itself gets the same cut at DUR−0.14 |
|
||||
| `planktonrail` | deep-sea lower third on TWO coexisting row slots: even lines ride the upper row (`H − bottomPx − rowDy`), odd lines the lower (`H − bottomPx`) — couplets share the water like drifting strata. A line clears when its row is next needed (line i+2 in − 0.15) or ~0.3s after its couplet finishes speaking (staggered pair exits, +0.12s on odd rows); the pre-apex leftover clears at heroIn−0.21 while the FEEDING line (last to start before the apex) yields to `yield.dim` instead — no restore unless ≥1.2s of hold remains (it exits dimmed, by design); a line entering during the hold arrives at `yield.enter` and restores at I+`yield.post`; every line floats on a gentle y keyframe drift sized to its window. Furniture: `body.motes` = {count, near, seed} plankton motes on seeded drift walks f(t); the first `near` seed a ring around the apex heart (ring radius scales with hero fontPx/120) and get ATTRACTED to the bloom at I−0.19 (pulled 0.72× toward it, brightening to 0.42 at scale 1.7), wiggle through the hold, and sink at clip end | fg | `glowon` (the apex bloom at low amplitude: 2-frame opacity ramp + radial bloom from word center — scale 0.92→1, blur 5→0, brightness 0.45→1, 0.4s sine.out — while a cyan glow text-shadow grows in; emphasis = slow DOUBLE-BEAT propulsion pulse at st+0.52, 5-key brightness/scale 0.55s, guarded ≤ DUR−0.09) | light sinks — y+15 while dimming, 0.3s power1.in; the last line floats to the end of the clip; line off ≤ DUR−0.02 |
|
||||
| `sheenrail` | iridescent silk lower third on TWO coexisting row slots: even lines ride the upper row (`H − bottomPx − rowDy`), odd lines the lower (`H − bottomPx`) — couplets read together like a woven pair. Words are aurora-gradient ink (background-clip:text over a rose→teal→violet 300% wash whose backgroundPosition drifts f(t) 0%→300% across the whole clip — the body's hold life) above a blurred dark understroke (top+3px, blur 3); a soft radial band scrim sits under the rows (stable reading surface). Line scheduling mirrors planktonrail: a row clears when next needed (line i+2 in − 0.15) or shortly after its couplet finishes speaking (pairEnd + 0.23 + 0.17 on odd rows); the pre-apex leftover clears at heroIn−0.32 while the FEEDING line stays and dims with the railwrap yield (`yield.dim` at I−`pre`, restore at I+`post` — band included); the last line holds to the end | fg | `flowon` (the ribbon's flow at low amplitude: 2-frame opacity + y8 settle 0.38s sine.out; emphasis = ONE bright sheen sweep — a white highlight marches through the word once at st+0.16 (backgroundPosition −80%→180%, 0.42s power2.inOut) + a brightness 1.55 pulse) | dissolve UPWARD — words to y−12, blur 3, 0.32s power1.in staggered 0.035; each line releases `body.streaks` seeded light streaks (rose/teal/violet verticals) that float up from its row (y 14→−78, 0.62s, start clamped ≤ DUR−0.66) |
|
||||
| `scoperail` | oscilloscope lower third: a dark phosphor scope band (`body.bandH`, top border + glass shadow) hosts HUD readouts (`body.hudL` left, sample-rate `· TRIG` + amber trig LED right), a graticule, and an ALWAYS-ALIVE waveform — an SVG polyline rebuilt from baked point-set states (seeded pseudo-RMS envelope at ~12 states/s + 3-frame triplets on word arrivals: speech grows the amplitude, silence flattens it, every word kicks a local gaussian burst at its slot center — burst x BAKED at compile time from the measured char-width table; the hero words kick WIDE bursts spread from `HG.x` toward `HG.x + 0.6·halfW`, where the trace surges to write). Body lines sit centered on the band above the trace with reserved-width slots (sizer + clip — no re-center drift as words arrive); the whole band (lines + wave + HUD) dims to `yield.dim` while the apex writes. At the FINAL transcript word the scope DIES: band x-shake, trig LED panics red then dies, the trace explodes to max-amp chaos for ~0.3s, flatlines, collapses to a single dot (scaleX 0.015) and `body.siglost` stamps with a 2-frame flicker (all clamped ≤ DUR−0.02) | fg | `tracewipe` (the apex pen-write at low amplitude: clip wipes the word in L→R over 0.10s + a 2-frame just-traced flash — flash-white instantly, settle to phosphor green; the death word settles to `palette.em` amber; the trig LED blinks on every arrival; emphasis = a ticking frequency-readout chip above the word, 3 seeded ascending values stepping every 2 frames) | the line collapses INTO the waveform (y+30, 0.13s power2.in) — early into dead air (lastWordStart+0.67), else just before the next line needs the slot; the last line collapses as the trace flatlines (min(NZ+0.33, DUR−0.2)) |
|
||||
| `paperrail` | stop-motion craft table: a kraft strip (torn top edge via seeded polygon clip-path, washi-taped corners, handwritten `body.tag` in the tag font) docked lower-third (`body.strip` geometry, centered by default); body words are cream paper chips (`palette.chip` on `palette.chipEdge` border, hard dy3 shadow) on centered replace-lines; the whole strip jitters ±0.7px every 4 frames (handmade stop-motion weave); the hero slot keeps a red paper star (`palette.accent`, rail↔climax hand-off) that pulses 1.18→1.06→1 as the apex chips land; the FINAL transcript word is an accent-red sign-off chip; emphasis words get a washi-tape slap (steps(2) scale 1.7→1 at `word.start + body.tapeDelay`, chip pressed 1 frame); strip + lines yield (`body.yield`) while the apex lands | fg | `place` (the papermat drop at low amplitude: opacity full in 0 frames + seeded ±2.5° rotation, y −16 + scale 1.06→1 steps(2) 0.12s; hold = rotation-only ~5fps wobble) | `peel` (rotation −8°, y −40, fade, steps(3), staggered 0.03s; last line clamped to finish on frame) |
|
||||
| `popuprail` | pop-up book page: a cream page strip (`body.strip` geometry, center foldline, top border + paper glow inset) unfolds up from the bottom edge (scaleY 0.02→1 back.out at 0.14 — the stage is built) and hosts TWO reading rows (`body.rowA`/`rowB` px above H) that alternate per line; the whole page breathes a gentle y drift sized to the clip; the hero slot keeps a blue paper star chip (`palette.accent` clip-path star, rail↔climax hand-off — spliced into the line whose window holds heroIn); emphasis words land at `body.emPx` weight 800 with a contact squash (1.06/0.93 set → elastic settle) the strip FEELS (1px dip), then flick-wobble (5-key rotationX, squeezed to fit before the fold) with a blue paper strut leaning in behind (scaleY back.out(2)); the FINAL transcript word is a blue sign-off with a strut; page yields (`body.yield`) while the centerfold lands; on the final word the whole page TILTS 2° +x6 (paper physics, `body.tilt:false` opts out) and the strip folds shut on the last frame (scaleY power3.in ≤ DUR−0.017) | fg | `popup` (the centerfold motif at low amplitude: opacity 1 in 0 frames + rotationX 85→0 baseline hinge, 0.25s back.out(1.4), back-shadow grows as it rises) | `fold` (the page closing: rotationX 88 power2.in 0.12s, shadow off, L→R wave staggered 0.045s, slot hidden at +0.13; fold at next line in / lastWord+`body.maxHold` in silence, wave clamped ≤ DUR−0.017) |
|
||||
| `chalkrail` | night-lecture chalk band: a deep-green board strip (`body.strip` geometry, worn top hairline, eraser smudges, handwritten `body.tag` header in the tag font, two chalk sticks bottom-right) docked at the bottom edge hosts `body.rows` reading rows that ACCUMULATE — lines fill the rows top→bottom in phases of rows.length; when the next phase needs the rows an ERASER SWIPE clears the board (blurred light band sweeps across 0.42s at `prevEnd + body.eraseDelay` clamped clear of the next phase, the old words SMEAR out scaleX 1.3 + x+24 + blur(8) staggered 0.06s, faint ghost smudges fade in and STAY — chalk never fully erases); the FINAL transcript word lands in yellow chalk (`palette.em` sign-off); the band yields (`body.yield`) while the apex writes | fg | `scribble` (the chalkwrite verb at low amplitude: 2-frame opacity pop + scribble clip-reveal steps(4) 0.12s + y4 drop-settle + 6 seeded dust specks puffing at the word base, seeded ±2° tilt; emphasis = double underline dashes drawn beneath at st+0.22/+0.38) | eraser-swipe smear between phases (scaleX 1.3, x+24, blur 8, power2.in 0.18s); the final phase holds to clip end |
|
||||
| `markerrail` | street handstyle rail: centered marker lines on a bottom rail (`body.bottomPx`), `palette.body` cream paint with a heavy drop text-shadow; emphasis words take ALTERNATING paint colors (`palette.em`/`em2`, yellow/magenta) + a spray-underline SWOOSH (dash-revealed squiggle viewBox-stretched to the word) with 8 seeded overspray dots that pop and fade; the FINAL transcript word lands BIG (1.5×) in `palette.em` with mini apex-impact physics (crush 0.09s power3.in → 2-frame contact squash → elastic settle — it rides the plate punch); the line visible at the tag's onset yields (`body.yield`, restore only with runway before its buff — else it exits dimmed) | fg | `flick` (the spray-write verb at low amplitude: opacity full in 1 frame at scale 1.18, seeded ±6° rotation settling to ±2°, 1-frame squeak skewX 7, back.out(2.2) settle 0.18s) | ROLLER BUFF (gray paint roller scaleX-sweeps the line 0.15s power2.in, words vanish under it, the wet smear lingers at 0.15 + blur(2) before fading); the last line is never buffed — the sign-off stays painted |
|
||||
| `brushrail` | washi paper band: a deckle-edged band (`body.strip` geometry, two faintly rotated `paperHi`→`paperLo` under-sheets at 0.42 + a translucent `sheetHi`→`sheetLo` main sheet with warm inset shadow) swipes in L→R behind a traveling brush-head shadow (clipPath wipe 0.2s power2.out + blurred `palette.bh` gradient head — the ink gesture at low amplitude), then the under-sheet breathes faintly (0.32 Hz baked f(t)); body lines are centered replace-lines on the band (`fonts.body` serif at `body.fontPx`/`body.weight`, seeded ±1° tilt); emphasis words get a DOUBLE curved ink underline (`palette.ulInk`, fat 7/0.3 wash + tight 2.6/0.95 core, dash-drawn at st+0.12/+0.15); band + the line under the gesture yield (`body.yield`) while the apex lands; the band exits with the last line on one final R→L wipe | fg | `brush-wipe` (the gesture at low amplitude: clipPath inset reveal L→R 0.16s power2.out with a blurred per-word brush-head shadow riding the reveal edge, then vanishing) | wet-cloth WIPE (the reveal in reverse: the line clipPath wipes R→L over 0.10–0.14s power2.in with an erase brush head riding it, at min(next line − 0.136, lastWord + `body.maxHold`); the LAST line and the band wipe together at DUR−0.142) |
|
||||
| `inkrail` | sumi ink on still water: up to THREE fixed reading rows at the bottom center (`body.bottomPx` = last-row center, `body.rowGap` apart; rows cycle in pairs, the closing line takes the third row — the final thought ACCUMULATES instead of replacing); `fonts.body` Mincho serif at `body.fontPx`/`body.weight`/`body.letterSpacing`, `palette.body` ink over a paper-white text-shadow halo (`palette.paper`/`paper2` glow stack — readable on bright skies) with a duplicate blurred dark halo per word; an ink-settling RULE (86%-width gradient hairline, scaleX 0→1 over 0.9s) draws beneath each line at firstWord+0.12; emphasis words shed a faint ink wisp curling off the word top (st+0.55, ±dir by line parity, skipped near clip end); the rows visible under the bloom yield (`body.yield` — dim at heroIn+`delay`, restore at heroIn+`post` only with runway before the exit) | fg | `bleed` (the apex bloom at low amplitude: opacity snaps in 2 frames; blur 12→0 + scale 1.25→1 power2.out carry the bleed — late words bleed faster so they resolve before clip end; the dark halo overshoots scale 1.5→1.04 while its opacity decays 0.5→0.25) | RE-DISSOLVE (blur 9 + scale 1.13 + fade + y−8 power1.in — ink dispersing back into the water) as the line-after-next approaches (= the next occupant of its row, outDur 0.5−0.05·i, never mid-read); the closing TWO lines persist to clip end |
|
||||
| `ransomrail` | kidnapper's collage rail: every transcript word is a cutout chip in one of 4 cycled recipes (cream/`fonts.body` Anton, black/`fonts.dark` Inter-800, newsprint/`fonts.news` Special Elite, accent/`fonts.accent` Permanent Marker — emphasis words snap to the accent chip, never two identical chips in a row) PASTED along the bottom rail line (`body.bottomPx`) with seeded crookedness (rot sign alternates with line+word parity, baseline dy leans the other way), seeded ±px sizes (`body.fontPx`−2..+1, emphasis +3) and torn edges (seeded 12-vertex tear polygon, same paper stock as the apex); chips carry a hard dy5 offset drop-shadow; lines breathe (5-key scale keyframes) through their hold; the whole railwrap yields (`body.yield`, container opacity — never contests per-chip channels) while the apex letters slam | fg | `paste` (the apex slam motif at low amplitude: opacity full in 1 frame at scale 1.12 / rot×1.5 / y−8 → power3.in crush 0.08s → 2-frame contact squash 1.05/0.95 → elastic settle; emphasis = 1-frame RE-PASTE lift at `body.emphDelay` — shadow grows to a flight blur, rotation flips sign for good, then crush + squash + elastic again, rip-runway-guarded) | RIPPED off one by one (rotation ±16/17° throw + y−30 + fade, power2.in, staggered 0.045s) with a 1-frame paper-tear flash under each chip — timed so the rip tail overlaps the next line's pastes a beat (collage chaos, by design); the last line tears off clamped to finish on frame |
|
||||
|
||||
fg body uses the **rail.html alpha-webm channel** (true alpha — dark panels and
|
||||
scrims work; never the screen-blend index_fg path, which can only add light).
|
||||
|
||||
## Hero setpieces (registry)
|
||||
|
||||
| setpiece | what happens | notes |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `detonation` | charge-dim → sheared stencil slices crush in hot → SNAP into register → squash → elastic settle → paint cools to bone → bars/ticks/designation-tag deploy → shear-apart exit | pairs with fx flash/rings/sparks + plate punch/shake |
|
||||
| `decode` | slot-machine glyph reels (steps() ease, seek-safe) lock left→right with RGB jitter → lock snap → CRT power-off exit | pairs with `redact-until-hero` |
|
||||
| `drawon` | the word is WRITTEN stroke-by-stroke from a single-line font (Hershey) — per-stroke paths revealed sequentially at constant pen speed, nib rides `getPointAtLength`, hops at pen lifts; then hum + buzz dip | any word, zero tuning: `gen-stroke-path.py` lays out glyph pen-paths at compile time |
|
||||
| `cpslam` | acid-yellow stencil word slams in BEHIND the subject with REAL diagonal notch cuts (SVG mask = true transparency over footage), chromatic split that settles to a PERMANENT cyan/red registration error, seeded glitch ticks, katakana tag, glitch-out exit | bounded hold (~2.6s default, `params.hold` / `hero.exitAt` override) — a climax is an event, not wallpaper |
|
||||
| `coverword` | the spoken apex word SET IN the replica typeface of the CP2077 cover mark (`assets/brand/CyberpunkReplica.ttf` — lowercase glyphs carry the logo's real brush chops, blade terminals and spikes; logo case = First-upper rest-lower). The setpiece adds only what the font lacks: solid cyan duplicate offset (-7,8), baseline streak merged with the glyph feet + cyan debris, circuit trace off the tail, tear-in slices / living print / tear-out | metric-exact layout from `cyberpunk-widths.json` (advance widths + ink bounds; `fontPx` = target INK height). No digits in the replica → compile ERROR with guidance. Replica font: personal-use license — samurai is already fan-kit non-commercial |
|
||||
| `assembly` | (inline, poem) apex word condenses BIG while star particles fly into it | |
|
||||
| `colorflip` | (inline, takeover) accent-color crush card + dim kick + squash/settle + loom | pairs with fx flash + plate punch/shake |
|
||||
| `flapboard` | split-flap departures board takeover: floodlight dim/scrim swing on, the housing clacks down (rotationX, squash, elastic) behind the subject, one giant flap tile per char flip-cycles 3–5 seeded wrong glyphs then LOCKS left→right across `params.lockWindow` (hot flash → cools to bone) under baked clack y-jitter; lock-complete = big clack + amber glow flicker + rule wipe + steps() status-ticker; hold = loom + one tile re-flutter; exit = tiles flip to blank cascade, housing flips away | pairs with `fx.crowdflash` (pops at lock start/end) and `plate.punchOffset = lockWindow` so the plate punch lands on the lock-complete clack, not the hero onset |
|
||||
| `ledwipe` | transit LED board takeover: cool scrim + dim charge, an amber dot-matrix panel EXPANDS upward (scaleY steps(6)) behind the subject, header tags + unlit LED ghost boot-flicker alive, then the word ILLUMINATES column-by-column (clipPath L→R, steps ≈ 1.4×chars over `params.wipeDur`) hot → cools to amber; contact = cell squash + elastic settle + PA "ding" double brightness pulse; an 8-phase chasing LED-marquee border runs to the exit; hold = glow breathe + seeded-look LED dropouts; exit = word pages up out of the window, panel collapses back down | pairs with `fx.paflash` (amber PA flash at wipe-complete contact). Panel geometry derives from fontPx (`panelH = 44 + 1.42×fontPx + 18`); `params.panelW` fixed, width-fit shrinks the type only. Plate: grain-only (no punch) is the demo register |
|
||||
| `vhsosd` | REC FREEZE camcorder slam: permanent lens vignette (`params.vignette`) + backlight-comp scrim (peak = `plate.charge`, cools to 0.69×) kill the bright sky; the word crushes in as a huge OSD readout — 3 horizontal clip-path tracking bands (`params.bandClips`) sheared (`params.bandShear`) + blurred (power4.in over `params.crush`) SNAP into register on the contact frame, squash → elastic settle; red/cyan misregistration copies cool from ±`misregIn` to ±`misreg` px and keep BREATHING through the hold under tape-weave y jitter (`params.weave`) + slow loom; auto-iris pump (white wash 0.20, dark dip = `plate.dim`); exit at `I + params.hold` = REWIND streak left + flat-white echo copy | pairs with the `vhsrail` paradigm, which emits the fg REC-FREEZE artifacts (tear band, head-switching bar, apex scrub lines, ● REC) at the same I/X times. Plate: grain-only (no punch) is the demo register; hold-life keyframes auto-clamp inside [contact, exit] |
|
||||
| `bossintro` | arcade BOSS INTRO: the room dims (gradient `plate.dim`) behind a CRT edge glow (cyan base wash that pulses on the last emphasis word before the boss and spills magenta on the strobe + the final word); `params.tag` (WARNING) blinks 2× above the word rect; ~COLS×ROWS (`params.rows`, cells 0.7×/0.5× fontPx) seeded pixel blocks fall steps(3) from above into a tight matrix grid covering the word rect, each landing with a 1-frame white tick; at `I + params.flashDelay` the word flashes ON (Press Start 2P, instant at opacity 1, scale 1.15 → steps(3) crush → 2-frame squash → elastic settle) with ±4px chromatic ghost layers + a 3-frame palette strobe (white→cyan→magenta→white); hold = quantized 1.6% breathe + CRT glow cycle + baked block shimmer blinks; exit at `I + params.hold` = per-letter checkerboard dissolve, blocks drop away steps(3) | pairs with the `hudrail` paradigm; emits fg furniture via setpiece fg parts: letterbox bars (`params.letterbox` px) slam in steps(3) with a 1-frame overshoot and retract after the exit, HI-SCORE odometer (accent label, yellow digits) rolls every 0.066s through the hold, 1-frame white tick out. `fx.coinflash` adds the 1-frame radial impact flash at the strike; plate punch anchors at `punchOffset` = `flashDelay` |
|
||||
| `rubberstamp` | the footage becomes an archive page (vignette charge = `plate.charge`, manila sepia wash `params.sepia`, dim kick = `plate.dim` that cools to 0.385×) and the verdict slams in BEHIND the subject as a bordered rubber stamp at `params.rotation`: a manila paper wash lights an instant before contact, the stamp crushes 2.2→1 power4.in over 0.115s, 2-frame contact squash, double-strike ghost print (`opacity 0.35`, offset +5/−4 rot 1.3), two thin-ink patches (`params.patches` clip-path circles in paper color), wet-ink saturate/brightness settle, paper indent shadow bloom; stamps don't move — the hold is DEAD STILL, sold by the breathing indent + a slow paper loom; exit at `C + params.hold` = mechanical 3-frame yank-down cut (the page is filed away), the archive plate releases 0.25s before | contact `C = heroIn + params.crush`; pairs with `fx.inkflecks` (seeded red spatter at C, ballistic with gravity) and `plate.punchOffset = params.crush` so the plate punch lands on the stamp contact; pairs with the `carbonstrip` paradigm (strip yield + shade breathe anchor at the same C); face chrome (border, radius, padding, ghost offset) scales with fontPx from the 120px demo cut |
|
||||
| `lasercage` | concert-blackout laser show: the plate dims to `plate.dim` at t=0 and deepens to `plate.charge` before the drop while haze cones breathe in the top corners; a 6-beam array (alternating accent/magenta, emitters along the top edge) snaps on at I−0.26 and SWEEPS to converge on the word center (staggered 0.022s), a hot core pops at convergence; the word IGNITES behind the subject as an additive glow stack (wide accent blur 0.22×fontPx + magenta fringe offset + tight soft blur + near-white core): scale 1.16 crush power4.in → 2-frame contact squash → elastic settle + 2 controlled strobe pops (brightness 2.05, 1s apart, runway-guarded); a criss-cross beam CAGE (6 lines derived from the word rect) draws itself dash-by-dash around the word and flickers; through the hold the array FANS OUT slowly to floor targets (the iconic concert fan) while the word looms; exit at `heroOut − 0.38` = cage un-draws, beams sweep away L→R (+0.74W) carrying the letters (per-letter streak + blur, stagger auto-clamped ≤ DUR), the room lifts back to 0.12 | word geometry is metric-exact via `assets/fonts/char-widths.json` (cage/spill/flash all derive from `halfW` + `fontPx`); pairs with `fx.laserflash` (accent contact flash at I+0.03, sized 2·halfW+80 × 4.8·fontPx) and the `laserrail` paradigm (same converge-ignite motif at low amplitude); plate punch anchors at `punchOffset` ≈ 0.07 (the ignite contact) |
|
||||
|
||||
| `boltstrike` | THE STRIKE: a slate storm mood (`params.mood`) sits on the room from t=0 and the sky KISSES (1-frame 6% gradient brighten) on every body word — double-kiss on emphasis words, re-flashes at I+0.84/I+1.44 during the hold; the room charge-dims to `plate.charge` under a radial word scrim from I−0.39; a hand-authored branched bolt (5-seg zigzag + 2 branches, haze/glow/core SVG stack in `palette.accent`/`glow`/`core`) flashes 2 frames BEFORE the word — leader 1 → 0.35 → return stroke 1 at contact — with a sky flash; the word slams in (Anton scale 3.1 crush power4.in 0.105s, blur 14→0, brightness 3.2→2.5) → 2-frame contact squash → elastic settle, lit HARD for 2 frames then cools to 1; SIGNATURE: the word's text-shadow flips toward the bolt side for the flash frames; ozone under-glow (accent, blur 26×fontPx/145) blooms at contact and breathes (6-key opacity cycle) through the hold + slow loom + 2-frame lit blips on the sheet re-flashes; the dim releases at the flash, settles to a `plate.dim` storm hold and lifts before the exit; exit at `min(heroOut−0.2, I+params.hold)` = washes downward with the rain (y+38, blur 6) | bolt geometry is baked at compile time as offsets from the word center (halfW/360 × fontPx/145 units, `params.side` flips it); word rect is metric-exact via `assets/fonts/char-widths.json`; word scrim = 2·halfW+380 × 2.28·fontPx; pairs with `fx.strikeflash` (full-frame fg flash with the same leader/return flicker grammar) and the `stormrail` paradigm (rain doubles + shadow flip at the same I); plate punch anchors at `punchOffset` ≈ 0.02 (the return stroke) |
|
||||
| `holoboot` | full volumetric boot behind the subject: a desk emitter dot pops (back.out scale), the projection cone SNAPS wide (scaleX 0.07→1 expo, 0.11s, then dips 0.55→0.95), a seed beam fires up from the emitter (scaleY power3.in, fades after contact), and the word boots with a RISING clip sweep (opacity instant at I−0.055, the reveal is the wipe) into a 7-layer projection stack (dark backing shadow / wide `palette.glow` blur / magenta + cyan chromatic fringes / `palette.core` word / scanline mask / climbing interference bands, band pitch 0.39×fontPx); contact at I+0.07 = brightness 2.3 flash + scaleX 1.07 / scaleY 0.91 squash held 2 frames + elastic settle + 1-frame x interference jumps; fringes blow ±8px then settle to the permanent ±2px registration offset; hold = bands climb −6 pitches, rotationY oscillates [0,6,−7,5,0], glow/cone breathe, emitter dot pulses, slow 1.028 loom; at `I + params.passAt` (≥ I+1.25, runway-guarded) a hand "passes through" the projection (skew 6/−4/0 + blur + fringe blowout + scaleY ripple — pure projection logic); exit at `min(heroOut−0.22, DUR−0.3)` = projector cut: brightness 2.4 → collapse to a horizontal line (scaleY 0.018) → to the base dot (scaleX 0.015), cone fades, dot pops 2.2× and dies. A second smaller emitter cone (`params.coneW`) rises from the desk under the holorail plate ALL video with baked flicker cycles + dot pulses, and gets its own projector cut at DUR−0.2 | word rect is metric-exact via `assets/fonts/char-widths.json` (cone width 2·halfW+80, emitter at cy+2.4·fontPx, all rig geometry derives from `halfW` + `fontPx`; scene scrim is a radial centered on the hero's frame fractions); pairs with `fx.holoflash` (cyan fg lock flash at I+0.075, radial at the same hero fractions) and the `holorail` paradigm (same sweep-boot + interference-glitch motif at low amplitude; the body cone is aimed at ITS plate); plate: grain-only (no punch) is the demo register, scene reaction = `plate.scrim`/`charge`/`dim` |
|
||||
| `biobloom` | bioluminescent BLOOM behind the subject: the abyss grade (`params.mood`) + a breathing vignette (6-key opacity cycle sized to the clip) sit on the room from t=0 — the world is underwater before anything speaks; a creature pre-glow (1.083×/0.717× fontPx ellipse) gathers with a double-beat anticipation at I−0.31 and crushes to a point at I−0.115; a dark pocket scrim (`plate.scrim`, 2·halfW+280 × 2.5·fontPx) opens behind the word zone at I−0.03; the word CONDENSES in (scale 2.35 crush power4.in over `params.crush`, blur 15→2, brightness 2.6→1.7) → 2-frame contact squash (1.09/0.93) → elastic settle while cyan light SPILLS onto the scene (radial at the hero's frame fractions: snap 0.55 at contact → 0.2 → shimmer keyframes); 6 luminous tendrils (paired blurred SVG strokes — glow w9/blur5 + core w3/blur1.1, accent/violet/ice alternating) draw outward from the word rect staggered 0.05s (stagger auto-clamps so the last filament completes before the sink); hold = glow breathes 8–14% (4-key scale/opacity), glow-layer flicker, two counter-drifting caustic gradients shimmer over the text zone, the bloom drifts slowly with the current (`params.drift` on the x channel); exit at `min(heroOut−0.2, DUR−0.3)` = the light SINKS — tendrils (via their HTML wrapper, never gsap-y on inner SVG), caustics, pocket, spill and the word all drift down (+14/+26) while dimming, word blurs out | tendril geometry is hand-authored from the demo and baked at compile time as offsets from the word center (x scaled by halfW/demoHalf, y by fontPx/120, endpoints frame-clamped); word rect is metric-exact via `assets/fonts/char-widths.json` (0.01em tracking); pairs with `fx.sporeburst` (seeded spore puffs burst PAST the bloom at contact in the fg layer, ballistic with slight sink) and the `planktonrail` paradigm (same glow-on motif at low amplitude + mote attraction anchored at the same I); plate: pushIn+grain (no punch) is the demo register — the demo's postfx profile was `push` |
|
||||
| `silkribbon` | aurora silk WRITTEN into the night sky behind the subject: the hero word is a sequential Hershey-stroke reveal (one `<path>` per pen stroke at constant pen speed, `gen-stroke-path.py` baked at compile time — any word, zero tuning) in a blurred halo (`params.haloWidth`, feGaussianBlur 7) + tight core (`params.coreWidth`, white drop-shadow), BOTH stroked by ONE userSpaceOnUse rose→teal→violet linearGradient with reflect spread; SIGNATURE: the gradient's x1/x2 translate f(t) from I−0.07 to the clip end (shift 1.5× the gradient span) so the aurora colors FLOW THROUGH the drawn ribbon during the hold; a soft light mote (blurred halo + core dot) rides the pen, hops at lifts, and blooms out 2.4× at the final stroke; scene reaction = two huge aurora blobs (teal top-left / rose top-right, frame-fraction geometry) drift the sky f(t) from t=0 at `params.wash` and DEEPEN to `params.deepen` as the ribbon writes, a top scrim (`plate.scrim`, 0.653H) charges in at I−0.34 (sky washout guard), a light spill (`params.spill`) tints the sky at I+0.1 once the ribbon completes and flickers gently, and the halo breathes (5-key opacity cycle) through the hold; gentle — no shake, no contact squash: the apex verb is the writing itself; writing window = `params.window` clamped so the ribbon finishes + holds before ENDT = DUR−0.04 | canvas/gradient/spill all derive from `params.targetWidth` (demo: 880 ink on a 1010×280 canvas, baseline 200; svgW = tw+130, spill = (tw+60)×0.51, gradient span = 0.6364·tw), centered at the scene-aware HG (pref top 18, the sky band — same as drawon); pairs with `fx.silkmotes` (seeded aurora motes rise near the ribbon during the hold, fg layer, demo spread fractions keep the face gap) and the `sheenrail` paradigm (same flow motif at low amplitude); plate: pushIn+grain (no punch) is the demo register — the demo's postfx profile was `push` |
|
||||
| `scopetrace` | the scope's own trace LEAPS off the band and WRITES the hero word behind the subject: a surge column (3px, bottom-anchored scaleY pop, landing at the pen-start point parsed from the baked path) jumps from the scope band at I−0.12; the word is a sequential Hershey-stroke reveal (one `<path>` per pen lift at constant pen speed, `gen-stroke-path.py` baked at compile time — any word, zero tuning; punctuation stripped for the pen) drawn CORE-ONLY in a thin phosphor stroke (`params.coreWidth`, bright `palette.bright` + accent drop-shadows — it is a trace, not a tube), nib rides `getPointAtLength` and pops 2.4× at DRAWN; the phosphor FILL (blurred halo strokes, `params.haloWidth`, blur 7) flicker-arrives AFTER the write at FLICK = DRAWN+`params.flickGap` (pre-arm 2 frames early, 5-step 1/0.25/1/0.55/1 blink, core dips 0.55 for a frame); hold = glow hum (7 Hz + 11.3 Hz sine keyframes, f(t)) + 1.6% breathe on an HTML wrapper with transformOrigin at the hero's frame fractions, ending exactly at the collapse; exit = the word COLLAPSES to a flatline (wrapper scaleY 0.02, 0.14s power3.in, same origin) + a horizontal flash bar (2·halfW wide at the word center) that shrinks out — scheduled at nextSpokenWord − `params.clearGap` (clamped ≥ FLICK+0.45, ≤ heroOut) so the trace clears BEFORE the next line speaks; scene reaction = phosphor radial scrim (`plate.scrim` at the hero fractions, I−0.18 → EXIT+0.05) + green spill sized from targetWidth (`params.spill`); second beat: a 1-frame phosphor pulse answers the FINAL transcript word — the same death beat the scoperail finale owns | trace geometry derives from `params.targetWidth` (svgW = tw+140, local baseline 215, ink center ≈ baseline−28 — the demo registration; surge x parsed from the first `M` of the path); centered at the scene-aware HG (pref top 25, ink height 115); pairs with the `scoperail` paradigm (tracewipe = the same pen-write at low amplitude; the paradigm's hero waveform kicks fire at the same word onsets) and needs no front fx; plate: grain-only (no punch) is the demo register |
|
||||
| `papermat` | STOP-MOTION PAPERCUT behind the subject: a torn-edge kraft mat (two seeded torn polygon layers) DROPS from above with steps(2) gravity and slaps down (squash → rest, soft blob shadow); then one torn cream chip per char (`palette.paper`/`paper2`, hero-font ink `palette.ink`) drops with steps(3) gravity + 1-frame overshoot at `I + i·params.step`, each announced by an anticipation shadow 3 frames early, landing crooked (seeded ±3° ±4px), settling through three 12fps poses, then holding an 8fps wobble (baked set chain — the stop-motion heartbeat) while the whole tableau breathes 1.6% (camera-push loom); scene reaction = a warm vignette (`params.vig`) charging with the landing; on the FINAL word the table BUMPS (y4, 1 frame) and the chips SCATTER off down-right steps(4) staggered 0.045s, the mat swept off last (disperse-on-last-word, `hero.exitAt` overrides) | chip geometry derives from `hero.fontPx` (demo ratios: tile 0.91×/1.31× fontPx, pitch tile+14, mat N·pitch+80 × 1.846× fontPx), width-fit shrinks type and chips together; pairs with `fx.paperscraps` (paper scraps puff at each chip contact, fg) and the `paperrail` paradigm (same place verb at low amplitude); plate: grain only is the demo register |
|
||||
| `centerfold` | POP-UP BOOK CENTERFOLD behind the subject: blue + cream 12-point paper starbursts (deterministic starPts polygon, `palette.accent`/`cream` fills with kraft-edge strokes) unfold on a baseline hinge (scaleY 0.03→1 back.out(1.6), cream staggered +0.06) starting I−0.272 while a blob shadow grows beneath; the hero word pops up at I in `params.segs` hinged clip-path segments (rotationX 85→0 back.out(1.4) staggered `params.segStagger` — the body's popup verb at full amplitude); two kraft struts lean in at I+0.33; backdrop + word wobble-settle TOGETHER (one `#cfWob` wrapper owns rotationX, 6-key) then breathe through the hold (word 5-key rotationX + shadow scaleX, both auto-squeezed into the window); scene reaction = a dusk radial scrim at the hero's frame fractions (`params.scrim`, bright-sky insurance) charging with the unfold; exit = the whole spread folds FLAT (segments rotationX 88 staggered, struts/bursts scaleY collapse cream-then-blue, scrim out) at `max(I+segStagger·(segs−1)+0.45, min(heroOut−0.33, DUR−0.39))` — the book closes before the next sentence | burst geometry derives from the word rect (metric-exact via char-widths: burstR = clamp(1.83·fontPx, 0.59·wordW, 0.42·H), box 2R+180 × 2R+fontPx, demo props scale at burstR/220), width-fit shrinks the type first; pairs with `fx.confetti` (seeded ballistic paper confetti launched from the hinge line at I+0.128, fg) and the `popuprail` paradigm (same baseline-hinge verb at low amplitude); plate: grain only is the demo register |
|
||||
| `chalkwrite` | NIGHT LECTURE behind the subject: the lower chalk band grows into a FULL deep-green board (scaleY 0→1 power3.out from the bottom edge at I−0.3, the room dims `params.dim` + vignette `params.vig` with it); the hero word is HAND-WRITTEN in chalk — sequential Hershey stroke reveal (drawon pattern, `gen-stroke-path.py` baked at compile time), dry/rough via seeded ±1px jitter on every pen point (`params.jitterSeed`), a blurred halo (`params.haloWidth`, feGaussianBlur 3.2, group opacity `params.halo`) under a tight core (`params.coreWidth`), a chalk-stick nib (rotated rect) riding the pen — while `params.dustN` dust specks fall from the nib along the path; at write-complete a hand-slap CLAP shakes the board 1 frame (set-chain y 3/−2/1/0; the dust burst lives in the rail, in FRONT: `fx.chalkclap`), then TWO violent accelerating underlines slash beneath (seeded waviness, power3.in, the nib rides them, dust kicks at the ends), the chalk flicks away, and the halo breathes (baked 1.6/3.7 Hz f(t)) through the hold with two slow motes drifting off the letters | geometry registers on the MEASURED ink box (the stroke path is parsed at compile time; ink CENTER lands on scene-aware HG.y, pref top 44): the board rect (`params.boardGap`×inkH above the ink, bottom flush with the frame, width = the body strip), the underlines (inkL+14→inkR−4 at inkBot+30/+50) and the fg clap point (the pen's LAST contact point → HG.clapX/Y/T) all derive from it; x defaults to the board's LEFT margin + tw/2 — a hand writes from the left, never centered on the subject (`theme.hero.x` overrides); pairs with `fx.chalkclap` (12 seeded radial dust specks + a blurred puff at DRAWN, fg) and the `chalkrail` paradigm (same scribble verb at low amplitude); plate: grain only is the demo register; needs `python3` |
|
||||
| `spraytag` | STREET TAG behind the subject: the dusk wall dims (`params.dim`) + a radial scrim charges (`params.scrim`) at I−0.42 as the writer steps up; the can RATTLES at the pen-start point (6 seeded set-chain nib jitters, I−0.30→I−0.02), then the hero word is spray-written stroke by stroke — sequential Hershey dash reveal at constant pen speed (`gen-stroke-path.py` baked at compile time) — as a TRIPLE stack per stroke: fat dark under-stroke `palette.under` (`params.underWidth`, sky-contrast armor) + blurred overspray halo (`params.haloWidth`, feGaussianBlur 7, group opacity `params.haloOpacity`) + wet paint core (`params.coreWidth`, drop-shadow), the glowing nib (r9, `palette.nib`) riding each stroke; `params.osprayN` seeded overspray dots pop near the nib as it passes; nib throws off 2.6× at DRAWN; through the hold `params.drips` seeded DRIPS (paint→`dripMid`→`dripLo` gradient bars) grow from painted low points (x-separated >110px) and KEEP growing, the halo hums (7/11 Hz baked f(t)) and the whole tag looms 1.014; writing window = `params.window` (demo 0.58s) clamped so write + splat + drip fit before ENDT = DUR−0.04 | geometry registers on the MEASURED ink box (ink CENTER lands on scene-aware HG.y, pref top 26 — the sky band, crossing the subject silhouette is the point; tag centers on the hero anchor, `targetWidth` capped at W−140); the pen-finish point is baked onto HG.splatX/Y/T for the fg splat; pairs with `fx.paintsplat` (hot `em2` ring + paint ring + seeded ballistic droplets at DRAWN, fg, in FRONT of the subject) and the `markerrail` paradigm (same flick verb at low amplitude); plate: punch with `punchOffset` ≈ window+0.05 so the punch lands on the splat, not the hero onset; needs `python3` |
|
||||
| `brushwrite` | SUMI-E GESTURE behind the subject: a warm paper wash (`palette.wash`/`wash2` radial, `targetWidth`+380 × `params.washH`) charges at I−0.18 to `params.wash`, settling to `params.washSettle` through the hold; the brush SLAPS down at the first pen point — a start-SPLAT (irregular ink ellipse rotated −24° + 5 seeded satellite dots, scale 0.35→1 power3.out 0.12s; the fg fleck pass rides `fx.brushflecks`) — then the hero word is written in ONE sequential gesture (Hershey dash reveal at constant pen speed, `gen-stroke-path.py` baked at compile time) as a FOUR-layer stack per stroke: blurred bleed (`params.bleedWidth`, feGaussianBlur 6, group hidden until the hold) under fat/mid/core widths (`fatWidth` 0.25 / `midWidth` 0.6 / `coreWidth` 1.0 stroke-opacity = pressure-tapered wet brush), the round ink nib (r7.5, `palette.nib`) riding the pen and flicking off (+42,−30, scale 1.9) at DRAWN; ≤`params.spatterN` spatter droplets eject PERPENDICULAR at the sharpest-curvature points of the gesture (angle-delta > 0.55 rad, te-separated > 0.045s); through the hold the ink BLEEDS into the paper (bleed group fades to `params.bleed` over ≤1.7s) and the whole work breathes 0.6% (`params.breatheHz` baked f(t), svgOrigin = ink center); then the vermilion SEAL chop (`params.sealGlyph`, `palette.seal`/`sealMid`/`sealLo` radial face, `fonts.seal` glyph) stamps at DRAWN+`params.sealDelay` — power4.in crush 0.09s → 2-frame squash → elastic settle + 3 seeded red flecks — skipped entirely if the clip ends too soon; writing window = `params.window` (demo 0.45s) clamped so write + seal + bleed fit before ENDT = DUR−0.04 | geometry registers on the MEASURED ink box (ink CENTER lands on scene-aware HG.y, pref top 19 — the sky band, crossing the subject silhouette is the point; gesture centers on the hero anchor, `targetWidth` capped at W−240 — on scenes with a dark object near the pen start, set `theme.hero.x` so the slap-down lands clear, like the demo's 864); the pen-START point is baked onto HG.fleckX/Y/T for the fg flecks and the seal sits at (inkR−103, inkBot+72) clamped on frame (`params.sealDx/sealDy` override); pairs with `fx.brushflecks` (seeded upward ballistic ink flecks at the slap-down, fg, in FRONT of the subject) and the `brushrail` paradigm (same brush-wipe verb at low amplitude); plate: punch with `punchOffset` ≈ window+`sealDelay` so the punch lands on the seal CONTACT, not the hero onset; needs `python3` |
|
||||
| `ransomnote` | RANSOM NOTE slam behind the subject: one cutout chip per letter (4 recipes cycled, seeded ±13% sizes around `hero.fontPx`, alternating-sign rotations ±2–5°, misaligned baselines ±2–6px, seeded tear-polygon edges) slams in oversized (scale 1.5, rot×1.8, flight drop-shadow) at S_k = I + 0.01 + `params.step`·k, crushes power3.in over 0.085s, and on contact the shadow POPS tight (1-frame filter swap) → 2-frame squash 1.07/0.93 → elastic settle; when the LAST letter lands the whole word takes a collective 1-frame JOLT (y6 → power3.out) + a scene pulse (`params.pulse` full-frame dark blink); hold = slow 5-key loom (the crooked grid never straightens); exit = letters RIPPED off one by one (rot+±15–22° throw, y−34, fade, 1-frame tear flash under each) at ripT = min(lastWord − `params.ripLead`, DUR-clamped), ≥ jolt+0.45; scene reaction = collage scrim (`params.scrim` top-dark gradient) charges at I−0.07, out with the rip | width-fit measures each glyph IN ITS OWN recipe font (`assets/fonts/char-widths.json`) + 0.20em chip padding + 6px margins so the collage never overflows; chip chrome (shadows, space width) scales with fontPx from the 130px demo cut; the setpiece RECOMPUTES `plate.punchOffset` = 0.01 + step·(N−1) + crush from the real letter count so the plate punch always lands on the collective jolt, whatever the hero word length; pairs with the `ransomrail` paradigm (same paste verb + tear flashes at low amplitude, same recipe classes/seeded tear polygon emitted into both layers); no front fx — the flashes live inside the chips |
|
||||
| `inkbloom` | INK DROP IN STILL WATER behind the subject: paper-white radial washes charge the two text zones (`palette.wash` rail wash from t≈0.15, PERSISTS to clip end so the closing body lines keep their ground — it registers on the body row geometry `body.bottomPx`/`rowGap`; `palette.washApex` apex wash at I−0.077, out with the bloom) and a gentle vignette (`params.vig`) STILLS the world while the ink blooms; the drop (ink teardrop, `params.fall` 0.15s) appears above the word point at I−0.08, swells, falls power2.in with a scaleY stretch, squashes 1.7/0.35 on contact (2 frames) and merges into the BLOOM — 3 stacked blurred irregular ink ellipses (`palette.ink`, opacity snaps 0.82/0.62/0.5 then decays) scaling at different rates with counter-rotations (expo.out 1.15/1.35/1.5s) + 2 thin concentric ripple rings expanding 7.2×/9.6× on the water surface; the hero words RESOLVE out of the blob (opacity snaps, blur 16→0 + scale 1.12→1 power2.out) — the FIRST at contact+0.02, the following at their own spoken times (multi-word hero, per-word hand-off); through the hold the glyph edges BREATHE (baked 5-key blur keyframes per word, alternating 0.66/0.5s), the group looms 1.018 and two faint ink wisps curl off the word top (C+0.573/C+0.753, fit-guarded); exit: RE-DISSOLVE (blur 11 + scale 1.15 + fade, 0.52s power1.in) at XOUT = min(I+`params.maxHold`, next body line − `params.clearGap`, DUR−0.6) — the ink clears before the next thought needs the reader | geometry derives from the measured word rect (`assets/fonts/char-widths.json`; kx = halfW/demoHalf, ky = fontPx/132 scale the demo's blob/ring/wisp anchors; pref top 25 — the sky band, crossing the subject silhouette is the point); dark `palette.ink` + its paper washes carry the contrast on bright skies; pairs with the `inkrail` paradigm (same bleed verb at low amplitude); plate: quiet `pushIn`, no punch — the bloom is liquid, not percussive |
|
||||
|
||||
Inline setpieces (`hero.inline: true`) live inside the body paradigm — the hero
|
||||
word stays in `lines`. Embed setpieces own the word: leave it OUT of `lines`
|
||||
(rail↔climax hand-off), except `panel` + `redact-until-hero`, where the words
|
||||
appear in the log as `█████` until the decode locks.
|
||||
|
||||
A setpiece may additionally return `fgCss/fgHtml/fgJs` — those parts are merged
|
||||
into the fg alpha page (rail.html), for furniture that must ride ABOVE the matte
|
||||
(e.g. a verbatim chip that may never be occluded) while the setpiece scenery
|
||||
stays embedded behind the subject.
|
||||
|
||||
## Linkages
|
||||
|
||||
- `redact-until-hero` — panel log shows hero words as blocks; un-redacts at lock
|
||||
- `corrupt-on-last-word` — panel jitters + hue-shifts on the final word
|
||||
- `disperse-on-last-word` — every visible poem letter scatters back to dust
|
||||
- `field-is-the-apex` — (lastpage) the blurred future-field rack-focuses at the
|
||||
apex: every faint line was the apex word all along; the main instance holds,
|
||||
the rest re-blur and die
|
||||
|
||||
## Hard rules inherited (do not relax)
|
||||
|
||||
- determinism: paused GSAP on `window.__timelines["main"]`, seeded PRNG only,
|
||||
set-chains / keyframes, no Math.random/Date.now/CSS-keyframes
|
||||
- 80 ms word sync (timings come from transcript.json via the strict matcher;
|
||||
any uncovered transcript word is a compile ERROR — verbatim completeness)
|
||||
- apex owns the frame: fg furniture must avoid the setpiece rect or yield
|
||||
(`body.yield`) during the hero window
|
||||
- plate punch/shake ALWAYS post-composite (`_postfx.sh`) so subject + text +
|
||||
plate move as one photographed frame (matte never desyncs)
|
||||
|
||||
## SVG gotchas (paid for, do not rediscover)
|
||||
|
||||
- dash patterns restart on EVERY subpath → sequential per-stroke paths, never
|
||||
one dashoffset across a multi-stroke word
|
||||
- round linecap renders a DOT at dashoffset=len → hide each stroke until its turn
|
||||
- inline-block trailing spaces collapse → word gaps via margin, not text spaces
|
||||
- SVG-font glyph y is UP → flip when converting (gen-stroke-path.py does)
|
||||
- NEVER gsap x/y/scale on raw SVG children: it runs `_parseTransform`/getBBox, and
|
||||
zero-area shapes (fan-kit slivers) trip GSAP's bbox hack → `appendChild` on a
|
||||
null docElement in injected-gsap contexts (preview-frames, renderer). Jitter
|
||||
SVG pieces via `attr:{transform:"translate(...)"}` only; scale/loom belongs on
|
||||
an HTML wrapper div. Nuance: a ROOT `<svg>` inside a div has null
|
||||
ownerSVGElement → GSAP classifies it as HTML (CSS transforms, no getBBox), so
|
||||
scale/skew on the svg root is safe — but copying that onto an inner `<g>`
|
||||
becomes the fatal class. attr transforms can't TWEEN — use frame-quantized
|
||||
step chains (identical on screen at 24fps)
|
||||
|
||||
## Timeline ownership rules (audit-derived, do not relax)
|
||||
|
||||
- ONE owner per (target, property) at any instant. A duration tween re-renders
|
||||
every tick until it ends — any set/tween on the same property inside that
|
||||
window gets visually overwritten a frame later (1-frame ghosts, flash-backs).
|
||||
Known shapes: yield dim vs line exit; yield restore vs powercut set-chain;
|
||||
per-word line-y bounces with word gaps < 0.22s. The rail emitter guards these
|
||||
(bounce ownership tracker, dim clamped ≥ line-in, restore only with ≥0.3s
|
||||
runway before exit — else the line exits dimmed, by design).
|
||||
- Inverted clamps: `Math.max(lo, Math.min(hi, x))` with lo > hi silently pins to
|
||||
lo. When a lockup is wider than the frame, CENTER it (x = W/2) instead of
|
||||
clamping — decorative bleed must be symmetric.
|
||||
- The overflow gate only measures elements with direct text nodes — SVG-painted
|
||||
setpieces (mask text + rects) are invisible to it. Do not read its "ok" as
|
||||
proof for svg lockups; judge those on the preview frames.
|
||||
|
||||
## theme.json — full schema
|
||||
|
||||
```json
|
||||
{ "dna": "<themes/*.json name>", // required
|
||||
"lines": [["word","word",...], ...], // required — verbatim transcript tokens, in order,
|
||||
// INCLUDING punctuation ("size.", "noise.")
|
||||
"minors": ["word", ...], // optional — theme's inline emphasis treatment
|
||||
"hero": { "match": "word or phrase", // required — exact transcript tokens (case-insensitive,
|
||||
// punctuation-stripped match); first occurrence wins
|
||||
"text": "DISPLAY FORM", // optional display override
|
||||
"out": 5.9, "exitAt": 3.3 }, // optional window overrides (seconds)
|
||||
"width": 1280, "height": 720, // optional, default 1280x720 (theme DNAs are tuned
|
||||
// for 16:9; vertical needs a DNA variant)
|
||||
"fps": 24, // optional — matte.fps is AUTHORITATIVE when present
|
||||
"panelHeader": "..." } // optional (panel paradigm)
|
||||
```
|
||||
|
||||
Scene awareness (inherited from the existing typography system): when
|
||||
`safe-zones.json` is present the compiler re-anchors the hero setpiece to the
|
||||
measured occlusion bands (`heroBands.profile`, 18–55% occlusion, closest to the
|
||||
setpiece's preferred height) and `heroAnchor.centerXPct`, width-fits the hero
|
||||
font to the actual word, and docks panel/poem furniture on
|
||||
`subject.clearerSide`. Explicit `theme.json` values > scene auto > DNA fallback.
|
||||
|
||||
Expected (benign) log noise: `[Browser:REQUESTFAILED] GET source.mp4
|
||||
net::ERR_ABORTED` during the fg-layer page load, reel-glyph overflow lint
|
||||
lines, and `media_missing_data_start` — all cosmetic; the render is good if
|
||||
render-theme.sh exits 0 and prints the gates summary.
|
||||
|
||||
## Authoring a project (this is ALL a user writes)
|
||||
|
||||
`<project>/theme.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"dna": "ordnance",
|
||||
"lines": [
|
||||
["The", "stars", "were", "only", "limited"],
|
||||
["by", "the", "pixel", "size."],
|
||||
["It's"],
|
||||
["what", "you", "can", "actually"],
|
||||
["recover", "from", "the", "noise."]
|
||||
],
|
||||
"minors": ["stars"],
|
||||
"hero": { "match": "remarkable" }
|
||||
}
|
||||
```
|
||||
|
||||
- `lines` follow the transcript verbatim, in order (compile error otherwise);
|
||||
every transcript word must be covered by `lines` ∪ `hero.match` — the example
|
||||
above omits "remarkable" from `lines` precisely because `hero.match` covers it
|
||||
(it slots between `["It's"]` and `["what",...]`)
|
||||
- leave the hero word(s) out of `lines` for embed setpieces; keep them for
|
||||
inline setpieces and for panel+redact
|
||||
- `takeover`: each line is one CARD — group by beat (1–2 words), not subtitle
|
||||
length; `panel` scrolls automatically past ~5 lines (terminal scroll)
|
||||
- the ordnance "charge" is an edge vignette + rail yield (the center stays
|
||||
clean by design) — judge it at the frame corners, not the center
|
||||
- `minors`: words that get the theme's inline emphasis treatment
|
||||
- preview first: `node scripts/make-theme.cjs <project>` then
|
||||
`node scripts/preview-frames.cjs <project> <t1> <t2> ...` (Visual QA)
|
||||
- then: `bash scripts/render-theme.sh <project>` → **`final_fx.mp4`** (the
|
||||
deliverable; `final.mp4` is pre-plate-reaction)
|
||||
|
||||
Prereqs identical to other modes — `prepare.sh` outputs: transcript.json,
|
||||
frames_fg/, matte.fps, safe-zones.json (scene awareness), source.mp4.
|
||||
frames_bg/ is only needed by preview-frames.cjs, not by the render.
|
||||
|
||||
## Adding a theme DNA
|
||||
|
||||
Copy a `themes/*.json`, change identity fields. You may ONLY combine existing
|
||||
paradigm/setpiece/linkage names — if the look you want needs a new mechanism,
|
||||
that is a registry contribution (this file + make-theme.cjs), reviewed like an
|
||||
engine change. A DNA that needs per-word visual tuning to ship is rejected:
|
||||
**any input, zero hand-fixing** is the acceptance bar (the draw-on lesson).
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "anchor",
|
||||
"voice": "the quiet professional — a verbatim rail that simply reads (2-frame fade-ups, accent emphasis), and one climax that settles into the scene behind the subject with a drawn accent underline. No spectacle: discipline IS the style. This is the conservative default that replaced Standard mode.",
|
||||
"when": "explainers, tutorials, product walkthroughs, corporate and news-adjacent clips — anywhere every word must be read and nothing should show off. Pick it when unsure.",
|
||||
"register": "calm",
|
||||
"fonts": { "body": "Sora", "hero": "Sora", "tag": "Sora" },
|
||||
"palette": { "body": "#F2EFE9", "accent": "#D9B98C", "em": "#EFCB9A" },
|
||||
"body": {
|
||||
"paradigm": "rail",
|
||||
"layer": "fg",
|
||||
"fontPx": 46,
|
||||
"bottomPx": 96,
|
||||
"letterSpacing": "0.012em",
|
||||
"entrance": "fade",
|
||||
"exit": "fade",
|
||||
"minorScale": 1.0,
|
||||
"yield": { "dim": 0.55, "pre": 0.2, "post": 0.9 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "settle",
|
||||
"layer": "bg",
|
||||
"fontPx": 150,
|
||||
"params": {}
|
||||
},
|
||||
"plate": { "dim": 0.16, "pushIn": 0.012, "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "arcade",
|
||||
"voice": "8-bit cabinet attract mode — the whole frame plays through a CRT (scanlines + vignette) above a bordered HUD bar (1UP blinking on the classic cadence, CREDIT 01) where every word coin-pops in on steps(2) with a 1-frame white blip; emphasis words run a cyan→magenta palette swap. The apex is a BOSS INTRO behind the subject: the room dims, WARNING blinks twice, ~64 seeded pixel blocks fall quantized into a matrix grid over the word rect, then the word flashes ON in Press Start 2P with chromatic ghost layers + a 3-frame palette strobe while letterbox bars slam in and a HI-SCORE odometer rolls top-right; everything dissolves checkerboard and the blocks drop away.",
|
||||
"when": "gaming, retro-tech, playful hype, launches, achievement/level-up beats, '像素/街机/8-bit/打游戏' asks — anything that should read as an arcade cabinet boss fight. Loud register; the boss dim + dark HUD bar bring their own contrast on bright skies.",
|
||||
"register": "loud",
|
||||
"fonts": { "body": "Press Start 2P", "hero": "Press Start 2P", "tag": "Press Start 2P" },
|
||||
"palette": {
|
||||
"body": "#FFFFFF",
|
||||
"accent": "#00E5FF",
|
||||
"magenta": "#FF2E88",
|
||||
"yellow": "#FFE600",
|
||||
"credit": "#7ADCFF"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "hudrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 26,
|
||||
"bar": { "h": 70, "inset": 24, "bottom": 50 },
|
||||
"tags": { "left": "1UP", "right": "CREDIT 01" },
|
||||
"scan": 0.06,
|
||||
"textTransform": "uppercase",
|
||||
"yield": { "dim": 0.55, "pre": 0.09, "post": 1.04 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "bossintro",
|
||||
"layer": "bg",
|
||||
"fontPx": 84,
|
||||
"params": {
|
||||
"seed": 13013,
|
||||
"rows": 4,
|
||||
"tag": "WARNING",
|
||||
"flashDelay": 0.14,
|
||||
"hold": 1.24,
|
||||
"letterbox": 44
|
||||
}
|
||||
},
|
||||
"fx": { "coinflash": 0.55 },
|
||||
"plate": {
|
||||
"dim": 0.58,
|
||||
"punch": 0.04,
|
||||
"punchDecay": 9,
|
||||
"punchOffset": 0.14,
|
||||
"shakeAmpX": 7,
|
||||
"shakeAmpY": 5,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.6,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "aurora",
|
||||
"voice": "polar-night elegance — the sky is alive and every caption is woven light. Two huge aurora blobs drift the top of frame all clip; body words are silk serif ink whose rose→teal→violet sheen drifts continuously through the letters (emphasis words get one bright highlight sweep), lines share two coexisting rows like a woven couplet and dissolve UPWARD into drifting light streaks. The apex is a SILK RIBBON: the hero word is hand-WRITTEN into the sky behind the subject stroke by stroke (single-line script font, blurred halo + bright core, a light mote riding the pen) — and the signature: the aurora gradient keeps FLOWING through the drawn ribbon during the hold while a soft spill tints the sky and light motes rise past the subject. Gentle — no shake.",
|
||||
"when": "dreamy / romantic / wonder content, night-sky and travel pieces, poetry, weddings, elegant brand films, '极光/丝带/优雅手写字幕' asks — anything that should feel written by light rather than printed. Soft register; the apex scrim + dark understroke carry contrast on bright skies.",
|
||||
"register": "elegant",
|
||||
"fonts": { "body": "Cormorant Garamond", "strokeFont": "HersheyScript1.svg" },
|
||||
"palette": {
|
||||
"body": "#F2EFF7",
|
||||
"rose": "#FF9EC4",
|
||||
"accent": "#7FE0D4",
|
||||
"violet": "#B9A8FF",
|
||||
"deep": "#070C24"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "sheenrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 48,
|
||||
"bottomPx": 76,
|
||||
"rowDy": 58,
|
||||
"band": { "w": 860, "h": 170 },
|
||||
"streaks": 4,
|
||||
"seed": 20260611,
|
||||
"yield": { "dim": 0.5, "pre": 0.16, "post": 0.62 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "silkribbon",
|
||||
"layer": "bg",
|
||||
"params": {
|
||||
"targetWidth": 880,
|
||||
"window": 0.68,
|
||||
"haloWidth": 18,
|
||||
"coreWidth": 6,
|
||||
"wash": 0.12,
|
||||
"deepen": 0.2,
|
||||
"spill": 0.3
|
||||
}
|
||||
},
|
||||
"fx": { "silkmotes": 6, "seed": 20260612 },
|
||||
"plate": { "scrim": 0.72, "pushIn": 0.012, "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "biolume",
|
||||
"voice": "deep-sea bioluminescence — the clip sinks into an abyss grade with a breathing vignette and every caption is a living light. Body words GLOW ON like jellyfish (2-frame opacity + radial bloom from center while a cyan glow breathes in), emphasis words pulse a slow double-beat (propulsion), lines float on a gentle drift across two coexisting rows and SINK away dimming; seeded plankton motes drift the open water and the ones ringing the apex get pulled into the bloom. The apex is a bioluminescent BLOOM behind the subject: a creature pre-glow double-beats and crushes to a point, the word condenses in, six luminous tendrils draw outward like filaments while caustics shimmer and cyan light spills onto the scene — then all the light sinks back into the deep.",
|
||||
"when": "ocean / nature / science-wonder docs, dreamy or meditative monologues, slow night-time reveals, 'underwater / 深海 / 发光水母' asks — anything that should feel alive and submerged rather than printed. Soft register; the abyss grade + pocket scrim make their own contrast on bright scenes.",
|
||||
"register": "dreamy",
|
||||
"fonts": { "body": "Fredoka", "hero": "Fredoka", "tag": "Fredoka" },
|
||||
"palette": {
|
||||
"body": "#E9FFFA",
|
||||
"accent": "#6DF2E0",
|
||||
"violet": "#9D7BFF",
|
||||
"ice": "#8FE8FF",
|
||||
"core": "#F2FFFD",
|
||||
"em": "#F4FFFD",
|
||||
"mote": "#96F5E8",
|
||||
"spore": "#BDFFF4"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "planktonrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 44,
|
||||
"bottomPx": 70,
|
||||
"rowDy": 58,
|
||||
"motes": { "count": 12, "near": 5, "seed": 2929 },
|
||||
"yield": { "dim": 0.55, "pre": 0.17, "enter": 0.8, "post": 0.63 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "biobloom",
|
||||
"layer": "bg",
|
||||
"fontPx": 120,
|
||||
"params": { "crush": 0.11, "drift": -30, "mood": 0.92 }
|
||||
},
|
||||
"fx": { "sporeburst": 7, "seed": 2930 },
|
||||
"plate": { "scrim": 0.55, "pushIn": 0.012, "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"name": "brush",
|
||||
"voice": "sumi-e study — the lower third is a washi paper band (deckle-edged under-sheets, warm translucent sheet) where every word is brush-WIPED on behind a traveling brush-head shadow in a Mincho serif, seeded ±1° tilt; emphasis words get a double curved ink underline drawn beneath, and spent lines are wiped OFF right-to-left like a wet cloth. At the apex a warm paper wash charges behind the subject and the hero word is written in ONE violent calligraphic gesture — a pressure-tapered wet brush (four stacked stroke widths) slapping down on a start-splat, spattering droplets at the sharpest curves, ink flecks kicking past the subject — then the ink BLEEDS into the paper through the hold and a vermilion SEAL chop stamps the work with the plate punch.",
|
||||
"when": "calm-authority explainers, craft / design / philosophy / Japan-adjacent content, tea-ceremony-paced brand films, meditation and writing channels — anything that wants ink-and-paper elegance with one violent flourish. The dark ink needs a mid/bright scene band (the paper wash supplies its own ground on bright skies).",
|
||||
"register": "contemplative-elegant",
|
||||
"fonts": {
|
||||
"body": "Shippori Mincho",
|
||||
"seal": "Shippori Mincho",
|
||||
"strokeFont": "HersheyScript1.svg"
|
||||
},
|
||||
"palette": {
|
||||
"ink": "#19120b",
|
||||
"nib": "#1a130c",
|
||||
"body": "#221a12",
|
||||
"ulInk": "#2a1c12",
|
||||
"bh": "#281e14",
|
||||
"paperHi": "#efe8d7",
|
||||
"paperLo": "#e7dfcb",
|
||||
"sheetHi": "#f5efe2",
|
||||
"sheetLo": "#ece4d2",
|
||||
"wash": "#f6f0e2",
|
||||
"wash2": "#f4edde",
|
||||
"seal": "#d24a32",
|
||||
"sealMid": "#c03422",
|
||||
"sealLo": "#a92a1a",
|
||||
"sealText": "#f7efe2",
|
||||
"accent": "#c03422"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "brushrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 44,
|
||||
"weight": 600,
|
||||
"strip": { "w": 820, "h": 90, "bottomPx": 61 },
|
||||
"maxHold": 0.78,
|
||||
"seed": 20260611,
|
||||
"yield": { "dim": 0.55, "pre": 0.16, "post": 0.46 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "brushwrite",
|
||||
"layer": "bg",
|
||||
"params": {
|
||||
"targetWidth": 760,
|
||||
"window": 0.45,
|
||||
"bleedWidth": 16,
|
||||
"fatWidth": 18,
|
||||
"midWidth": 10,
|
||||
"coreWidth": 5,
|
||||
"spatterN": 6,
|
||||
"wash": 0.34,
|
||||
"washSettle": 0.27,
|
||||
"washH": 420,
|
||||
"bleed": 0.38,
|
||||
"breatheHz": 0.55,
|
||||
"sealGlyph": "観",
|
||||
"sealDelay": 0.04,
|
||||
"sealSize": 64,
|
||||
"seed": 380611
|
||||
}
|
||||
},
|
||||
"fx": { "brushflecks": 6, "seed": 20260611 },
|
||||
"plate": {
|
||||
"punch": 0.04,
|
||||
"punchDecay": 9,
|
||||
"punchOffset": 0.49,
|
||||
"shakeAmpX": 7,
|
||||
"shakeAmpY": 5,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.6,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "chalkboard",
|
||||
"voice": "night lecture — the lower third is a worn deep-green chalk band where every word is SCRIBBLED in fast chalk (2-frame pop + scribble reveal + dust puff, seeded crooked), emphasis gets double underline dashes and the final word lands in yellow chalk; between sentences an ERASER SWIPE smears the old words off and leaves ghost smudges. At the apex the band grows into a full blackboard behind the subject and the hero word is HAND-WRITTEN 130px tall in chalk stroke by stroke (jittered nib, dust falling from the pen), finished with a hand-slap dust clap and two violent underlines, then the halo breathes.",
|
||||
"when": "education/explainers, science and lecture content, teacher channels, documentary asides, 'professor energy' brand spots. Reads as handwriting, so it suits thoughtful pacing; the deep-green board supplies its own contrast on bright scenes.",
|
||||
"register": "scholarly-warm",
|
||||
"fonts": { "body": "Caveat", "tag": "Caveat", "strokeFont": "HersheyScript1.svg" },
|
||||
"palette": {
|
||||
"body": "#f3f6ee",
|
||||
"em": "#f3d96b",
|
||||
"accent": "#fbf9ef",
|
||||
"chalk": "#fbf9ef",
|
||||
"dust": "#f6f4e9",
|
||||
"board": "#1d3328",
|
||||
"boardHi": "#22392c",
|
||||
"boardLo": "#182b22",
|
||||
"bandHi": "#23392d",
|
||||
"bandLo": "#16271f",
|
||||
"rim": "#8a6a48",
|
||||
"rimLo": "#5f452c"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "chalkrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 52,
|
||||
"strip": { "w": 1200, "h": 148, "bottomPx": 0 },
|
||||
"rows": [26, 82],
|
||||
"tag": "OBSERVATORY — NIGHT LECTURE · wk 07",
|
||||
"seed": 13,
|
||||
"eraseDelay": 0.23,
|
||||
"yield": { "dim": 0.55, "pre": 0.07, "post": 0.41 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "chalkwrite",
|
||||
"layer": "bg",
|
||||
"params": {
|
||||
"targetWidth": 860,
|
||||
"window": 0.78,
|
||||
"coreWidth": 7,
|
||||
"haloWidth": 14,
|
||||
"halo": 0.18,
|
||||
"dustN": 8,
|
||||
"seed": 7,
|
||||
"jitterSeed": 21,
|
||||
"dim": 0.22,
|
||||
"vig": 0.35,
|
||||
"boardGap": 0.554
|
||||
}
|
||||
},
|
||||
"fx": { "chalkclap": 12, "seed": 13 },
|
||||
"plate": { "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "dossier",
|
||||
"voice": "cold-war case file — the clip is typed onto a manila transcript strip (carbon Special Elite hammered in char by char on seeded baselines, red ink circles around the evidence), and the verdict lands as a RUBBER STAMP behind the subject: the footage goes sepia-archival, the stamp crushes in at -8°, double-strike ghost, thin-ink patches, then holds DEAD STILL — sold only by a breathing paper indent — until the page is filed away with a mechanical yank.",
|
||||
"when": "investigations, exposés, true-crime, document-driven storytelling, 'the record shows' narration, declassified/archival framing. Works on any luma (the manila strip is self-lit; the stamp brings its own sepia charge).",
|
||||
"register": "archival-noir",
|
||||
"fonts": { "body": "Special Elite", "hero": "Special Elite", "tag": "Special Elite" },
|
||||
"palette": {
|
||||
"body": "#2b2722",
|
||||
"accent": "#b3271e",
|
||||
"paper": "#d8c49a",
|
||||
"ink": "#8a6f3f",
|
||||
"fleck": "#8e1f17"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "carbonstrip",
|
||||
"layer": "fg",
|
||||
"fontPx": 40,
|
||||
"strip": { "w": 764, "h": 132, "bottomPx": 4 },
|
||||
"rows": [36, 82],
|
||||
"header": "CASE N°018 — TRANSCRIPT OF RECORDING",
|
||||
"watermark": "CONFIDENTIAL",
|
||||
"seed": 180618,
|
||||
"yield": { "dim": 0.55, "pre": 0.02, "post": 0.41 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "rubberstamp",
|
||||
"layer": "bg",
|
||||
"fontPx": 120,
|
||||
"params": {
|
||||
"crush": 0.074,
|
||||
"hold": 2.02,
|
||||
"rotation": -8,
|
||||
"paperRot": 2.4,
|
||||
"sepia": 0.14,
|
||||
"patches": [
|
||||
[27, 36, 0.72],
|
||||
[71, 68, 0.57]
|
||||
]
|
||||
}
|
||||
},
|
||||
"fx": { "inkflecks": 12, "seed": 180618 },
|
||||
"plate": {
|
||||
"charge": 0.32,
|
||||
"dim": 0.26,
|
||||
"punch": 0.04,
|
||||
"punchOffset": 0.074,
|
||||
"punchDecay": 9,
|
||||
"shakeAmpX": 7,
|
||||
"shakeAmpY": 5,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.6,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "graffiti",
|
||||
"voice": "street bombing run — the lower third is a marker rail where words FLICK on crooked like fast handstyles (1-frame squeak skew, seeded rotation, back.out settle); emphasis words take alternating paint colors (yellow/magenta) with a spray-underline swoosh + overspray dots, spent lines are ROLLER-BUFFED away by a gray paint roller whose wet smear lingers, and the final word lands BIG in yellow with the punch. At the apex a writer steps up behind the subject: the dusk wall dims, the can RATTLES, and the hero word is spray-TAGGED stroke by stroke in fat yellow paint (dark under-stroke armor + soft overspray halo + glowing nib), drips grow from the low points through the hold and a magenta paint splat pops at the pen-finish.",
|
||||
"when": "street culture, hip-hop / rap, sneaker and fashion drops, urban sports, skate/BMX, rebellious brand spots — anything that wants real handstyle energy. Loud register; the dark under-stroke armors the tag against bright skies.",
|
||||
"register": "loud-street",
|
||||
"fonts": {
|
||||
"body": "Permanent Marker",
|
||||
"tag": "Permanent Marker",
|
||||
"strokeFont": "HersheyScript1.svg"
|
||||
},
|
||||
"palette": {
|
||||
"body": "#f7f2e7",
|
||||
"accent": "#ffd23f",
|
||||
"em": "#ffd23f",
|
||||
"em2": "#ff2e88",
|
||||
"under": "#241008",
|
||||
"nib": "#fff6d9",
|
||||
"dripMid": "#eab928",
|
||||
"dripLo": "#d8a51d",
|
||||
"rollerHi": "#8d8a86",
|
||||
"rollerLo": "#6f6c69",
|
||||
"roller": "#807d79"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "markerrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 46,
|
||||
"bottomPx": 98,
|
||||
"seed": 20260611,
|
||||
"yield": { "dim": 0.5, "pre": 0.04, "post": 0.17 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "spraytag",
|
||||
"layer": "bg",
|
||||
"params": {
|
||||
"targetWidth": 1000,
|
||||
"window": 0.58,
|
||||
"underWidth": 21,
|
||||
"haloWidth": 36,
|
||||
"coreWidth": 13,
|
||||
"haloOpacity": 0.5,
|
||||
"osprayN": 6,
|
||||
"drips": 3,
|
||||
"seed": 140987,
|
||||
"dim": 0.22,
|
||||
"scrim": 0.62
|
||||
}
|
||||
},
|
||||
"fx": { "paintsplat": 6, "seed": 20260611 },
|
||||
"plate": {
|
||||
"punch": 0.04,
|
||||
"punchDecay": 9,
|
||||
"punchOffset": 0.63,
|
||||
"shakeAmpX": 7,
|
||||
"shakeAmpY": 5,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.6,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "hologram",
|
||||
"voice": "volumetric projection — every caption is LIGHT cast from an emitter. The body rail is a scanlined projection plate fed by a desk cone; words boot with a rising sweep + 1-frame interference glitch + chromatic fringe, emphasis words drop out for 2 frames and restore brighter, lines drift in rotationY and exit with the projector cut (collapse to a slit, then a dot). The apex is the full volumetric boot: emitter dot pop, cone snap, seed beam, 7-layer hologram word with climbing interference bands; a hand passes through it before the projector cuts it to the base dot.",
|
||||
"when": "tech / sci-fi / AI / product-reveal explainers, futuristic UI talk, space and imaging content — anything that should feel projected rather than printed. Sleek register. Needs a lower frame edge for the emitter dots; the apex scrim makes its own contrast on bright scenes.",
|
||||
"register": "sleek",
|
||||
"fonts": { "body": "Orbitron", "hero": "Orbitron", "tag": "Orbitron" },
|
||||
"palette": {
|
||||
"body": "#C7F1FF",
|
||||
"accent": "#7AE8FF",
|
||||
"magenta": "#FF5FD6",
|
||||
"glow": "#3ECCF2",
|
||||
"core": "#EAFBFF",
|
||||
"em": "#F4FEFF",
|
||||
"glowEm": "#A0F2FF",
|
||||
"band": "#D8FAFF",
|
||||
"dot": "#BFF0FF",
|
||||
"dotHot": "#DFF8FF"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "holorail",
|
||||
"layer": "fg",
|
||||
"fontPx": 38,
|
||||
"bottomPx": 108,
|
||||
"plateW": 980,
|
||||
"plateH": 96,
|
||||
"lineDy": 9,
|
||||
"letterSpacing": "0.02em",
|
||||
"tag": "VOLUMETRIC FEED // CH-07",
|
||||
"emphDelay": 0.34,
|
||||
"yield": { "dim": 0.5, "pre": 0.18, "post": 0.37 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "holoboot",
|
||||
"layer": "bg",
|
||||
"fontPx": 118,
|
||||
"params": { "passAt": 1.29, "coneW": 800 }
|
||||
},
|
||||
"fx": { "holoflash": 0.5 },
|
||||
"plate": { "scrim": 0.58, "charge": 0.28, "dim": 0.18, "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "inkwater",
|
||||
"voice": "sumi ink dropped in still water — the scene offers paper-white radial washes to the text zones, then Mincho-serif ink words BLEED into a lower-third of three fixed reading rows (blur + scale carry the bleed over a paper-glow halo, a dark blurred halo overshoots and tightens, an ink-settling hairline draws under each line, emphasis words shed a curling ink wisp) and spent lines re-dissolve upward like ink dispersing. At the apex a dark drop falls into the frame, hits an invisible water surface at the word point and BLOOMS — three stacked blurred ink ellipses at different rates, two thin ripple rings — and the hero words resolve out of the blob (blur 16→0) on their own spoken times while the world stills under a gentle vignette; through the hold the glyph edges breathe and the ink finally re-dissolves before the next thought needs the reader.",
|
||||
"when": "contemplative, literary or scientific-wonder narration, astronomy / nature / memory / essay films, poetry and slow-craft channels — anything spoken quietly that wants one liquid, meditative event instead of an impact. Dark ink needs a mid/bright scene band (the paper washes supply their own ground on bright skies).",
|
||||
"register": "contemplative-still",
|
||||
"fonts": { "body": "Shippori Mincho", "hero": "Shippori Mincho" },
|
||||
"palette": {
|
||||
"body": "#14110e",
|
||||
"ink": "#14110e",
|
||||
"paper": "#fffaee",
|
||||
"paper2": "#fff8e8",
|
||||
"wash": "#fff9ee",
|
||||
"washApex": "#fffaf0",
|
||||
"accent": "#14110e"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "inkrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 46,
|
||||
"weight": 400,
|
||||
"letterSpacing": "0.055em",
|
||||
"rowGap": 56,
|
||||
"bottomPx": 36,
|
||||
"yield": { "dim": 0.5, "delay": 0.12, "post": 1.07 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "inkbloom",
|
||||
"layer": "bg",
|
||||
"fontPx": 132,
|
||||
"params": {
|
||||
"fall": 0.15,
|
||||
"maxHold": 1.75,
|
||||
"clearGap": 0.24,
|
||||
"vig": 0.34,
|
||||
"washRailW": 1180,
|
||||
"washRailH": 300,
|
||||
"washApexH": 430
|
||||
}
|
||||
},
|
||||
"fx": {},
|
||||
"plate": { "pushIn": 0.012, "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "laser",
|
||||
"voice": "concert laser rig — the room goes to blackout and the light operator types the transcript. Every body word is IGNITED where two thin beams (green from the top-left, magenta from the top-right) converge on it two frames early: flare pop, snap-on in laser green, single strobe on emphasis; a sweeper beam carries each line away. The apex is the drop: a 6-beam array sweeps to one hot point, the word ignites behind the subject in an additive glow stack with two controlled strobe pops, a criss-cross beam cage draws itself around it, then the array fans out slow and wide during the hold before the beams sweep everything off L→R.",
|
||||
"when": "music, nightlife, festivals, drops, hype reveals, tech keynote 'one more thing' beats — anything that should read as a light show. Loud register; the concert blackout makes its own contrast on any plate (bright skies included).",
|
||||
"register": "loud",
|
||||
"fonts": { "body": "Audiowide", "hero": "Audiowide", "tag": "Audiowide" },
|
||||
"palette": {
|
||||
"body": "#58ff9d",
|
||||
"accent": "#58ff9d",
|
||||
"magenta": "#ff4df0",
|
||||
"core": "#eefff5",
|
||||
"glowSoft": "#c9ffe2"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "laserrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 40,
|
||||
"bottomPx": 98,
|
||||
"letterSpacing": "0.02em",
|
||||
"wordGapEm": 0.24,
|
||||
"textTransform": "uppercase",
|
||||
"minorScale": 1.325,
|
||||
"yield": { "dim": 0.5, "beamDim": 0.55, "pre": 0.04, "post": 0.9 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "lasercage",
|
||||
"layer": "bg",
|
||||
"fontPx": 100,
|
||||
"params": {}
|
||||
},
|
||||
"fx": { "laserflash": 0.85 },
|
||||
"plate": {
|
||||
"charge": 0.46,
|
||||
"dim": 0.3,
|
||||
"punch": 0.04,
|
||||
"punchDecay": 9,
|
||||
"punchOffset": 0.07,
|
||||
"shakeAmpX": 5,
|
||||
"shakeAmpY": 4,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.5,
|
||||
"grain": 5
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "lastpage",
|
||||
"voice": "the speaker reads from a manuscript that already exists \u2014 a blurred future-transcript haunts the room all video; one rack-focus reveals every faint line was the apex word. The future was only ever one sentence.",
|
||||
"when": "visionary thesis, prophecy-toned founder talks, trailers, literary content. Mid/dark scenes (the field needs air).",
|
||||
"register": "literary-prophetic",
|
||||
"fonts": {
|
||||
"body": "Cormorant Garamond"
|
||||
},
|
||||
"palette": {
|
||||
"body": "#F0E9D8"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "lastpage",
|
||||
"layer": "bg",
|
||||
"fontPx": 44,
|
||||
"bottomPx": 96,
|
||||
"fieldCount": 9,
|
||||
"fieldBlur": 9,
|
||||
"seed": 4242
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "rackfocus",
|
||||
"inline": true,
|
||||
"params": {},
|
||||
"maxHold": 0
|
||||
},
|
||||
"fx": {},
|
||||
"plate": {
|
||||
"pushIn": 0.012,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": ["field-is-the-apex"]
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "neonsign",
|
||||
"voice": "sign district at dusk \u2014 body lines are warm tube light flicking on word by word and dying like power cuts; the apex is a hand-bent neon tube WRITTEN onto the scene stroke by stroke (single-line font draw-on), then it hums.",
|
||||
"when": "lifestyle, night/dusk scenes, music, fashion, mood pieces. Needs a darker or dusk backdrop for the glow to read; rose accent loves cool/dusk palettes.",
|
||||
"register": "creator-warm",
|
||||
"fonts": {
|
||||
"body": "Space Grotesk",
|
||||
"strokeFont": "HersheyScript1.svg"
|
||||
},
|
||||
"palette": {
|
||||
"body": "#ffe9d6",
|
||||
"accent": "#ff3fae",
|
||||
"em": "#ff9ed2"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "rail",
|
||||
"layer": "fg",
|
||||
"fontPx": 46,
|
||||
"bottomPx": 98,
|
||||
"letterSpacing": "0.02em",
|
||||
"entrance": "flick",
|
||||
"exit": "powercut",
|
||||
"emScale": 1.18,
|
||||
"rule": {
|
||||
"width": 560,
|
||||
"color": "#ff9ed2"
|
||||
},
|
||||
"glow": "0 0 7px rgba(255,214,170,0.65), 0 0 22px rgba(255,180,120,0.35), 0 2px 10px rgba(0,0,0,0.55)"
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "drawon",
|
||||
"layer": "bg",
|
||||
"x": 560,
|
||||
"y": 200,
|
||||
"params": {
|
||||
"targetWidth": 640,
|
||||
"window": 0.78,
|
||||
"tubeWidth": 7,
|
||||
"haloWidth": 22,
|
||||
"hum": true,
|
||||
"buzzDipAt": -0.18,
|
||||
"rotate": -3,
|
||||
"spill": 0.38
|
||||
},
|
||||
"maxHold": 0
|
||||
},
|
||||
"fx": {},
|
||||
"plate": {
|
||||
"pushIn": 0.012,
|
||||
"grain": 5
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "nightcity",
|
||||
"voice": "broken-UI hardware register meets the cover mark — body words BOOT in as corrupted cyan for a frame before settling to acid-yellow UI (minors keep a cyan/red registration shadow); the apex word slams in BEHIND the subject SET IN the replica typeface of the CP2077 cover lettering (real brush chops, blade terminals, spikes in the glyphs; logo case), with the cyan duplicate offset, a baseline streak merged into the glyph feet, cyan debris and a circuit trace off the tail. Tear-in slices, living print, tear-out.",
|
||||
"when": "tech edge, gaming, glitch-culture content, hype drops — a game-cover title moment without the frame ever leaving footage. Loud register.",
|
||||
"register": "loud",
|
||||
"fonts": {
|
||||
"body": "Rajdhani",
|
||||
"hero": "Anton",
|
||||
"tag": "Space Grotesk"
|
||||
},
|
||||
"palette": {
|
||||
"body": "#FCEE0A",
|
||||
"accent": "#52BEDC",
|
||||
"hot": "#FCEE0A"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "rail",
|
||||
"layer": "fg",
|
||||
"fontPx": 50,
|
||||
"bottomPx": 96,
|
||||
"letterSpacing": "0.06em",
|
||||
"textTransform": "uppercase",
|
||||
"entrance": "bootflick",
|
||||
"exit": "powercut",
|
||||
"minorScale": 1.3,
|
||||
"yield": {
|
||||
"dim": 0.4,
|
||||
"pre": 0.2,
|
||||
"post": 0.9
|
||||
}
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "coverword",
|
||||
"layer": "bg",
|
||||
"fontPx": 150,
|
||||
"params": {
|
||||
"seed": 77
|
||||
}
|
||||
},
|
||||
"fx": {
|
||||
"flash": 0.55,
|
||||
"seed": 20260611
|
||||
},
|
||||
"plate": {
|
||||
"punch": 0.04,
|
||||
"punchDecay": 9,
|
||||
"shakeAmpX": 6,
|
||||
"shakeAmpY": 4,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.5,
|
||||
"rgbashift": 4,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "ordnance",
|
||||
"voice": "military marking system — everything has mass. Body words STAMP in and cool from hot amber to bone; the apex is a sliced stencil stamp that detonates: sheared slices snap into register, paint cools, positioning bars + designation tag deploy, the room reacts.",
|
||||
"when": "punchy announcements, hype, product drops, sports, anything that should hit. Loud register. Needs a scene that tolerates a charge-dim (any luma).",
|
||||
"register": "loud",
|
||||
"fonts": { "body": "Anton", "hero": "Anton", "tag": "Space Grotesk" },
|
||||
"palette": { "body": "#EDE6D8", "hot": "#FFB347", "accent": "#FFB347" },
|
||||
"body": {
|
||||
"paradigm": "rail",
|
||||
"layer": "fg",
|
||||
"fontPx": 56,
|
||||
"bottomPx": 102,
|
||||
"letterSpacing": "0.03em",
|
||||
"textTransform": "uppercase",
|
||||
"entrance": "stamp",
|
||||
"exit": "drop",
|
||||
"minorScale": 1.4,
|
||||
"yield": { "dim": 0.45, "pre": 0.2, "post": 0.9 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "detonation",
|
||||
"layer": "bg",
|
||||
"x": 640,
|
||||
"y": 268,
|
||||
"fontPx": 178,
|
||||
"params": {
|
||||
"slices": [
|
||||
[0, 61.5],
|
||||
[40.5, 27.5],
|
||||
[74.5, 0]
|
||||
],
|
||||
"sliceShear": [-46, 52, -58],
|
||||
"bars": true,
|
||||
"barWidth": 760,
|
||||
"barDy": 124,
|
||||
"ticks": true,
|
||||
"tag": "APEX-01"
|
||||
}
|
||||
},
|
||||
"fx": { "flash": 0.97, "rings": 2, "sparks": 26, "embers": 7, "seed": 20260611 },
|
||||
"plate": {
|
||||
"charge": 0.5,
|
||||
"dim": 0.32,
|
||||
"punch": 0.045,
|
||||
"punchDecay": 9,
|
||||
"shakeAmpX": 7,
|
||||
"shakeAmpY": 5,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.6,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "papercut",
|
||||
"voice": "stop-motion paper craft — the frame becomes an animator's table. Body words are cream paper chips PLACED one by one on a kraft strip (steps(2) drop, seeded crooked, handmade jitter weave, washi-tape slaps on emphasis, accent-red sign-off chip); the apex is a torn kraft mat slapped down behind the subject where torn-edge letter chips DROP with stepped gravity, land crooked, wobble at 8fps, then a table bump scatters them off-frame on the final word. A red paper star stands in for the hero word on the rail (rail↔climax hand-off).",
|
||||
"when": "craft/DIY, kids and family content, indie product demos, behind-the-scenes, maker channels — anything warm and handmade that suits a 12fps stop-motion heartbeat. Playful register; needs a lower third that tolerates a kraft-paper strip.",
|
||||
"register": "playful",
|
||||
"fonts": { "body": "Inter", "hero": "Anton", "tag": "Caveat" },
|
||||
"palette": {
|
||||
"body": "#2b241b",
|
||||
"ink": "#2b241b",
|
||||
"accent": "#ff4f3f",
|
||||
"accentEdge": "#c93527",
|
||||
"chip": "#f6edd8",
|
||||
"chipEdge": "#cdb98e",
|
||||
"paper": "#f8f0dd",
|
||||
"paper2": "#efe3c6",
|
||||
"tag": "#503d20"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "paperrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 38,
|
||||
"strip": { "w": 1140, "h": 88, "bottomPx": 26 },
|
||||
"tag": "cut & paste · 12 fps",
|
||||
"tapeDelay": 0.25,
|
||||
"seed": 150372,
|
||||
"yield": { "dim": 0.6, "pre": 0.2, "post": 0.9 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "papermat",
|
||||
"layer": "bg",
|
||||
"fontPx": 130,
|
||||
"params": { "step": 0.09, "seed": 151515, "vig": 0.3 }
|
||||
},
|
||||
"fx": { "paperscraps": 3, "seed": 150372 },
|
||||
"plate": { "grain": 6 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "popup",
|
||||
"voice": "a pop-up book opens inside the frame — body words POP UP on a baseline hinge (rotationX back.out, paper overshoot) along a cream page strip that unfolds from the bottom edge (center foldline, two reading rows); emphasis words land bigger with a contact squash the page FEELS, then flick-wobble with a paper strut leaning in behind. The apex is THE CENTERFOLD: blue + cream paper starbursts unfold behind the subject, the hero word pops up in three hinged segments, struts appear, backdrop + word wobble-settle together and breathe — then the whole spread folds flat (the book closing). A blue paper star holds the hero slot on the rail (rail↔climax hand-off); paper confetti flicks past the subject at the pop.",
|
||||
"when": "kids and family content, storytelling, education, greeting-card and wholesome brand spots, picture-book or craft channels — anything warm, rounded and gentle that suits a paper toy theater. Playful register; needs a lower third that tolerates a cream paper strip.",
|
||||
"register": "playful",
|
||||
"fonts": { "body": "Baloo 2", "hero": "Baloo 2", "tag": "Baloo 2" },
|
||||
"palette": {
|
||||
"body": "#33271a",
|
||||
"ink": "#33271a",
|
||||
"accent": "#6cb6e3",
|
||||
"accentEdge": "#3f7fae",
|
||||
"blue": "#2e7cb3",
|
||||
"page": "#f7eed8",
|
||||
"page2": "#f0e4c8",
|
||||
"page3": "#e7d8b4",
|
||||
"pageEdge": "rgba(122,96,54,0.55)",
|
||||
"cream": "#f6ecd4",
|
||||
"creamEdge": "#8a6f45",
|
||||
"kraft1": "#a98f5e",
|
||||
"kraft2": "#cdbb92",
|
||||
"kraft3": "#e6d6af",
|
||||
"strut1": "#4f93c4",
|
||||
"strut2": "#6cb6e3",
|
||||
"conf": ["#f6ecd4", "#6cb6e3", "#e3d2ac", "#f6ecd4", "#6cb6e3", "#33271a", "#f6ecd4", "#e3d2ac"]
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "popuprail",
|
||||
"layer": "fg",
|
||||
"fontPx": 42,
|
||||
"emPx": 52,
|
||||
"strip": { "w": 1230, "h": 124 },
|
||||
"rowA": 70,
|
||||
"rowB": 20,
|
||||
"maxHold": 0.95,
|
||||
"yield": { "dim": 0.55, "pre": 0.03, "post": 0.47 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "centerfold",
|
||||
"layer": "bg",
|
||||
"fontPx": 120,
|
||||
"params": { "segs": 3, "segStagger": 0.07, "scrim": 0.42 }
|
||||
},
|
||||
"fx": { "confetti": 8, "seed": 360372 },
|
||||
"plate": { "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "ransom",
|
||||
"voice": "kidnapper's collage — every word is a cutout chip clipped from a different page (cream Anton, black Inter, newsprint typewriter, accent-yellow marker) and PASTED crooked on the rail with torn edges and misaligned baselines; emphasis words get a 1-frame re-paste lift, spent chips are RIPPED off with paper-tear flashes. The apex: the sky darkens behind a collage scrim and the hero word slams in letter by letter as a ransom note — each letter a different chip, flight shadow popping tight on contact — then the whole word JOLTS as the last letter lands (the plate punches with it), looms crooked through the hold, and is torn off chip by chip.",
|
||||
"when": "true crime, mystery / thriller content, heist energy, punk / DIY zine aesthetics, edgy product drops, unhinged-comedy hooks, \"勒索信/剪贴/拼贴字幕\" asks. Loud register; the solid chip backgrounds carry their own contrast on any scene.",
|
||||
"register": "loud-collage",
|
||||
"fonts": {
|
||||
"body": "Anton",
|
||||
"hero": "Anton",
|
||||
"dark": "Inter",
|
||||
"news": "Special Elite",
|
||||
"accent": "Permanent Marker"
|
||||
},
|
||||
"palette": {
|
||||
"body": "#f5f1e4",
|
||||
"paper": "#f5f1e4",
|
||||
"paperInk": "#17130d",
|
||||
"dark": "#141414",
|
||||
"darkInk": "#f7f5ef",
|
||||
"news": "#d8d3c5",
|
||||
"newsInk": "#262017",
|
||||
"accent": "#ffd23f",
|
||||
"accentInk": "#1c160c",
|
||||
"flash": "#fffdf2"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "ransomrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 46,
|
||||
"bottomPx": 56,
|
||||
"letterSpacing": "0.02em",
|
||||
"emphDelay": 0.23,
|
||||
"seed": 3940,
|
||||
"yield": { "dim": 0.5, "pre": 0.02, "post": 0.71 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "ransomnote",
|
||||
"layer": "bg",
|
||||
"fontPx": 130,
|
||||
"params": {
|
||||
"step": 0.06,
|
||||
"crush": 0.09,
|
||||
"ripStag": 0.045,
|
||||
"ripLead": 0.19,
|
||||
"scrim": 0.44,
|
||||
"pulse": 0.2,
|
||||
"seed": 3939
|
||||
}
|
||||
},
|
||||
"fx": {},
|
||||
"plate": {
|
||||
"punch": 0.04,
|
||||
"punchDecay": 9,
|
||||
"punchOffset": 0.64,
|
||||
"shakeAmpX": 7,
|
||||
"shakeAmpY": 5,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.6,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "scoreboard",
|
||||
"voice": "stadium split-flap departures board — every body word is a mechanical flap tile on a chyron bar that flip-cycles two seeded wrong words before clacking onto the real one (hot amber flash, cools to bone); a ROW counter flips at each line change and an odometer chip rolls beside the first emphasis line. The apex is a board takeover behind the subject: floodlights swing on, a giant departures housing clacks down, one huge flap tile per letter flip-cycles wrong glyphs then locks the word left→right under a crowd-flash, the status ticker types on, one tile re-flutters during the hold.",
|
||||
"when": "sports, transit/travel, scores, countdowns, announcements and reveals — anything that should read as DEPARTURES-board mechanical. Loud register; needs a lower third that tolerates a dark chyron bar.",
|
||||
"register": "loud",
|
||||
"fonts": { "body": "Teko", "hero": "Anton", "tag": "Teko" },
|
||||
"palette": {
|
||||
"body": "#F5EEDD",
|
||||
"hot": "#FFB347",
|
||||
"accent": "#FFB347",
|
||||
"grey": "#B9BEC7",
|
||||
"boardBone": "#F6EFDF"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "flaprail",
|
||||
"layer": "fg",
|
||||
"fontPx": 48,
|
||||
"barH": 96,
|
||||
"letterSpacing": "1px",
|
||||
"seed": 808,
|
||||
"chyron": { "tag": "DEPARTURES", "counter": "ROW" },
|
||||
"chip": { "label": "LIMIT", "value": "1.2", "unit": "PX", "x": 884, "y": 563 },
|
||||
"yield": { "dim": 0.55, "pre": 0.07, "post": 0.47 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "flapboard",
|
||||
"layer": "bg",
|
||||
"fontPx": 138,
|
||||
"params": {
|
||||
"seed": 8088,
|
||||
"glyphs": "ABCDEFGHIKLMNOPRSTUVXYZ0123456789",
|
||||
"lockWindow": 0.34,
|
||||
"gap": 7,
|
||||
"headerLeft": "★ DEPARTURES",
|
||||
"headerRight": "GATE 06 22:40",
|
||||
"tag": "STATUS // NOW BOARDING"
|
||||
}
|
||||
},
|
||||
"fx": { "crowdflash": [0.5, 0.45] },
|
||||
"plate": {
|
||||
"charge": 0.62,
|
||||
"dim": 0.34,
|
||||
"punch": 0.045,
|
||||
"punchDecay": 9,
|
||||
"punchOffset": 0.34,
|
||||
"shakeAmpX": 7,
|
||||
"shakeAmpY": 5,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.6,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "spectrum",
|
||||
"voice": "an oscilloscope is listening — a dark scope band hosts an always-alive waveform (speech grows it, silence flattens it, every word kicks a local burst) and body words are traced on in phosphor mono with a just-traced flash; the apex is the trace itself LEAPING off the scope to hand-write the hero word in a thin phosphor stroke, fill flicker, hum, then collapse to a flatline — and on the final word the whole trace explodes, flatlines to a single dot and stamps SIGNAL LOST.",
|
||||
"when": "science / signal / audio / measurement / astronomy explainers, data-nerd content, retro-lab or synth aesthetics, \"示波器/波形/信号字幕\" asks. The band brings its own dark glass; bright scenes fine.",
|
||||
"register": "tech-retro",
|
||||
"fonts": { "body": "VT323", "tag": "VT323", "strokeFont": "HersheyScript1.svg" },
|
||||
"palette": {
|
||||
"body": "#4dff88",
|
||||
"accent": "#4dff88",
|
||||
"bright": "#d6ffe4",
|
||||
"flash": "#eafff2",
|
||||
"em": "#ffb347",
|
||||
"hud": "#2f8f55",
|
||||
"panic": "#ff5f47"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "scoperail",
|
||||
"layer": "fg",
|
||||
"fontPx": 40,
|
||||
"bandH": 164,
|
||||
"waveTop": 80,
|
||||
"waveH": 84,
|
||||
"lineDy": 34,
|
||||
"hudL": "SPECTRUM // CH1",
|
||||
"siglost": "— SIGNAL LOST —",
|
||||
"waveSeed": 7,
|
||||
"chipSeed": 11,
|
||||
"yield": { "dim": 0.52, "pre": 0.13, "post": 0.97 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "scopetrace",
|
||||
"layer": "bg",
|
||||
"params": {
|
||||
"targetWidth": 720,
|
||||
"window": 0.6,
|
||||
"flickGap": 0.12,
|
||||
"clearGap": 0.215,
|
||||
"coreWidth": 4,
|
||||
"haloWidth": 14,
|
||||
"spill": 0.55
|
||||
}
|
||||
},
|
||||
"fx": {},
|
||||
"plate": { "scrim": 0.62, "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "stardust",
|
||||
"voice": "celestial condensation — letters condense out of drifting dust into an accumulating poem; the apex assembles from inbound star particles; on the final word the entire visible poem disperses back into dust (semantic exit).",
|
||||
"when": "introspective, poetic, memory, science-wonder monologues. The poem column needs one clear side; a soft gradient scrim (behind the subject) handles bright skies.",
|
||||
"register": "poetic",
|
||||
"fonts": { "body": "Cormorant Garamond" },
|
||||
"palette": { "body": "#f7f0dd" },
|
||||
"body": {
|
||||
"paradigm": "poem",
|
||||
"layer": "fg",
|
||||
"fontPx": 58,
|
||||
"left": 84,
|
||||
"stanzaTops": [110, 222, 292],
|
||||
"entrance": "condense",
|
||||
"exit": "drift",
|
||||
"bigScale": 2.0,
|
||||
"emScale": 1.38,
|
||||
"scrim": { "side": "left", "opacity": 0.62 },
|
||||
"seed": 777
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "assembly",
|
||||
"inline": true,
|
||||
"params": { "particles": 22, "spread": 150 }
|
||||
},
|
||||
"fx": {},
|
||||
"plate": { "pushIn": 0.01, "grain": 5 },
|
||||
"linkages": ["disperse-on-last-word"]
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "stomp",
|
||||
"voice": "full-frame typographic takeover — every beat is a hard-cut center card over a dimmed plate; a long-held card creeps with tension into a true VOID, then the apex detonates in the accent color; the final word dissolves to blur.",
|
||||
"when": "hooks, manifestos, ads, hype openers. The plate runs dimmed throughout — content where the words ARE the show. Body stays bg (text behind the subject is the identity).",
|
||||
"register": "takeover",
|
||||
"fonts": { "body": "Anton" },
|
||||
"palette": { "body": "#F5F1E8", "accent": "#FF5C39" },
|
||||
"body": {
|
||||
"paradigm": "takeover",
|
||||
"layer": "bg",
|
||||
"anchors": [
|
||||
[640, 330],
|
||||
[612, 302],
|
||||
[668, 358],
|
||||
[640, 388],
|
||||
[618, 336]
|
||||
],
|
||||
"baseDim": 0.42,
|
||||
"entrance": "cut",
|
||||
"creepScale": 1.1,
|
||||
"hotSnap": 1.18,
|
||||
"sizes": { "function": 150, "content": 200, "minor": 230 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "colorflip",
|
||||
"inline": true,
|
||||
"fontPx": 196,
|
||||
"params": { "crushFrom": 2.6, "dimKick": 0.62, "flash": 0.9, "dissolveLast": true }
|
||||
},
|
||||
"fx": { "flash": 0.9 },
|
||||
"plate": {
|
||||
"punch": 0.05,
|
||||
"punchDecay": 9,
|
||||
"shakeAmpX": 8,
|
||||
"shakeAmpY": 5,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.6,
|
||||
"grain": 7,
|
||||
"minorPunch": 0.02
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "terminal",
|
||||
"voice": "console session — the transcript is a signal log typed into a docked glass panel; the apex decodes out of noise as slot-machine glyph reels, and the log REDACTS the apex words (█████) until the decode locks. The feed corrupts on the final word.",
|
||||
"when": "tech, data, AI, engineering, investigative explainers. Cool scenes preferred (the cyan is scene-motivated on cool/dusk palettes).",
|
||||
"register": "creator-tech",
|
||||
"fonts": { "body": "VT323", "hero": "Orbitron", "tag": "VT323" },
|
||||
"palette": {
|
||||
"body": "#bfeefe",
|
||||
"accent": "#66e0ff",
|
||||
"magenta": "#ff5fd6",
|
||||
"panelBg": "rgba(2,14,22,0.62)",
|
||||
"prompt": "#4d7f93"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "panel",
|
||||
"layer": "fg",
|
||||
"fontPx": 34,
|
||||
"panel": { "left": 36, "bottom": 30, "width": 470, "header": "SIGNAL LOG_" },
|
||||
"entrance": "type",
|
||||
"exit": "hold",
|
||||
"caret": true,
|
||||
"yield": { "dim": 0.68 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "decode",
|
||||
"layer": "bg",
|
||||
"x": 660,
|
||||
"y": 255,
|
||||
"fontPx": 112,
|
||||
"params": {
|
||||
"glyphs": "X017#%/<>+=*KZR",
|
||||
"brackets": true,
|
||||
"lockStagger": 0.045,
|
||||
"exit": "crt-off",
|
||||
"seed": 99
|
||||
}
|
||||
},
|
||||
"fx": { "scanband": true, "lockflash": 0.55 },
|
||||
"plate": {
|
||||
"dim": 0.22,
|
||||
"punch": 0.016,
|
||||
"punchDecay": 10,
|
||||
"shakeAmpX": 0,
|
||||
"shakeAmpY": 0,
|
||||
"rgbashift": 4,
|
||||
"grain": 6
|
||||
},
|
||||
"linkages": ["redact-until-hero", "corrupt-on-last-word"]
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "thunder",
|
||||
"voice": "the storm is the editor — slate storm mood on the room, ambient slanted rain in front of the subject, and the sky 'kisses' (1-frame brighten) on every body word. Body words arrive on a rain-scrimmed lower third with a lit-bright lightning pop; emphasis words get a sheet-lightning double flash mirrored by a double sky-kiss. The apex is THE STRIKE: a hand-authored branched bolt flashes two frames before the word, then the word slams in lit HARD with its shadow flipped toward the bolt, ozone under-glow breathing through the hold while the rain doubles; everything washes downward with the rain.",
|
||||
"when": "dramatic reveals, storm/weather content, epic hype beats, trailer-toned monologues, anything that should land like a thunderclap. Loud register; the charge-dim + word scrim make their own contrast on any plate (bright skies included).",
|
||||
"register": "loud",
|
||||
"fonts": { "body": "Sora", "hero": "Anton", "tag": "Sora" },
|
||||
"palette": {
|
||||
"body": "#EEF4FB",
|
||||
"hero": "#F2F7FF",
|
||||
"accent": "#9FD0FF",
|
||||
"glow": "#CFE8FF",
|
||||
"core": "#FFFFFF"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "stormrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 44,
|
||||
"bottomPx": 98,
|
||||
"letterSpacing": "0.015em",
|
||||
"rain": { "count": 18, "opacity": 0.08, "seed": 9021, "seed2": 4477 },
|
||||
"yield": { "dim": 0.5, "pre": 0.15, "post": 0.29 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "boltstrike",
|
||||
"layer": "bg",
|
||||
"fontPx": 145,
|
||||
"params": { "mood": 0.1, "side": "left", "hold": 2.05 }
|
||||
},
|
||||
"fx": { "strikeflash": 0.55 },
|
||||
"plate": {
|
||||
"charge": 0.3,
|
||||
"dim": 0.22,
|
||||
"punch": 0.04,
|
||||
"punchDecay": 9,
|
||||
"punchOffset": 0.02,
|
||||
"shakeAmpX": 5,
|
||||
"shakeAmpY": 4,
|
||||
"shakeHz": 12,
|
||||
"shakeDecay": 7,
|
||||
"shakeWindow": 0.5,
|
||||
"grain": 5
|
||||
},
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "transit",
|
||||
"voice": "amber LED departure board — the whole video is a station PA system. Body words light column-by-column (L→R LED wipe + 1-frame arrival flicker) on a docked departure strip whose lines page in/out by scroll-snap; furniture: green platform tag, ticking seconds clock, a ⚠ DELAYED → ● ON TIME swap gag after the apex. The apex is a board takeover behind the subject: a big LED panel expands upward inside a chasing marquee border, the word illuminates column-by-column under a PA flash + two brightness 'ding' pulses, glow breathes with LED dropouts, then the word pages up and the panel collapses.",
|
||||
"when": "travel/transit, announcements, schedules, countdowns, retro-terminal or arcade registers — anything that should read as an amber dot-matrix station board. Mid-loud register; needs a lower third that tolerates a dark LED strip.",
|
||||
"register": "loud",
|
||||
"fonts": { "body": "VT323", "hero": "VT323", "tag": "VT323" },
|
||||
"palette": {
|
||||
"body": "#FFB000",
|
||||
"hot": "#FFE9B8",
|
||||
"accent": "#FFB000",
|
||||
"green": "#36E57A",
|
||||
"warn": "#FF9E3D"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "ledboard",
|
||||
"layer": "fg",
|
||||
"fontPx": 46,
|
||||
"letterSpacing": "0.05em",
|
||||
"board": { "left": 140, "width": 1000, "h": 116, "bottom": 30 },
|
||||
"header": {
|
||||
"plt": "PLT 4",
|
||||
"clockPrefix": "19:42:0",
|
||||
"statusWait": "⚠ DELAYED",
|
||||
"statusOk": "● ON TIME"
|
||||
},
|
||||
"yield": { "dim": 0.5, "pre": 0.2, "post": 0.9 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "ledwipe",
|
||||
"layer": "bg",
|
||||
"x": 620,
|
||||
"y": 444,
|
||||
"fontPx": 120,
|
||||
"params": {
|
||||
"panelW": 1080,
|
||||
"wipeDur": 0.3,
|
||||
"headerLeft": "NOW ARRIVING ▸ 19:42",
|
||||
"headerRight": "GATE A4"
|
||||
}
|
||||
},
|
||||
"fx": { "paflash": 0.5 },
|
||||
"plate": { "charge": 0.5, "dim": 0.2, "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "vhs",
|
||||
"voice": "camcorder tape playback — the whole frame is a VHS deck. A permanent lens vignette and OSD furniture (▶ PLAY, ● REC, green blinking timestamp) frame the clip; body words are an OSD lower third with a permanent 1px red+cyan misregistration fringe, arriving by tracking glitch (instant on + 2-frame y-shake + 1-frame band-slice shift) and exiting as REWIND streaks with flat-white echoes + scrub lines; the deck flips PLAY→REW in dead air. The apex is REC FREEZE: a 1-frame white tear band + head-switching noise bar, then the word slams in as a huge OSD readout behind the subject — three tracking-sliced bands shear in and SNAP into register, heavy red/cyan misregistration cools and keeps breathing through the hold under tape-weave jitter and an auto-iris pump, then the whole readout REWINDS off left.",
|
||||
"when": "retro / nostalgia / found-footage / home-video registers, music and lifestyle edits, '90s tech content, '录像带/VHS/复古/DV' asks — anything that should read as a tape being played back. Mid-loud register; the backlight-comp scrim makes its own contrast on bright skies.",
|
||||
"register": "retro-analog",
|
||||
"fonts": { "body": "VT323", "hero": "VT323", "tag": "VT323" },
|
||||
"palette": {
|
||||
"body": "#F2F2EE",
|
||||
"hot": "#FFFFFF",
|
||||
"accent": "#D9F7D2",
|
||||
"red": "#FF2E2E",
|
||||
"cyan": "#3FE8E8",
|
||||
"green": "#B9FFB0"
|
||||
},
|
||||
"body": {
|
||||
"paradigm": "vhsrail",
|
||||
"layer": "fg",
|
||||
"fontPx": 44,
|
||||
"bottomPx": 108,
|
||||
"letterSpacing": "0.04em",
|
||||
"osd": { "ts": ["JUN.11 2026 PM 7", "42"] },
|
||||
"yield": { "dim": 0.55, "pre": 0.02, "post": 0.9 }
|
||||
},
|
||||
"hero": {
|
||||
"setpiece": "vhsosd",
|
||||
"layer": "bg",
|
||||
"x": 640,
|
||||
"y": 268,
|
||||
"fontPx": 150,
|
||||
"params": {
|
||||
"bandClips": [
|
||||
[0, 64],
|
||||
[36, 30],
|
||||
[70, 0]
|
||||
],
|
||||
"bandShear": [-46, 40, -34],
|
||||
"misregIn": 11,
|
||||
"misreg": 3,
|
||||
"weave": [-2, 1, -1, 2, -1, 1, -2, 0],
|
||||
"vignette": 0.34,
|
||||
"crush": 0.1,
|
||||
"hold": 1.69
|
||||
}
|
||||
},
|
||||
"plate": { "charge": 0.55, "dim": 0.12, "grain": 5 },
|
||||
"linkages": []
|
||||
}
|
||||
Reference in New Issue
Block a user