cut-the-curve
The technique catalog: five velocity-matched SEAMS (zoom-through, INVERSE zoom-through, cut-the-curve, waterfall cut, rack-focus blur-cut) plus the two in-scene techniques — waterfall ENTRY (staggered arrival cascades for title cards / segment openers) and the nudge curve (slow-fast-slow three-phase group slides). Covers partial-travel (~12% of frame) velocity matching via mirrored power4 eases, the Z scale-sign rule, size-scaled blur (10px text / 18-20px full-frame), word-by-word staggered cuts, cascade pacing by element weight, and the 10/65/25 slide ratio. Read before authoring any transition, text-beat handoff, kinetic text entry, or group reposition. [depth, zoom, inverse-zoom, scale-sign, mirrored-zoom, rack-focus, pacing, velocity, cut-the-curve, waterfall, stagger, cascade, kinetic-text, title-card, segment-opener, nudge, slide, easing, group-motion, z-depth, motion-graphics, cinematic, transition, blur, directional-continuity]
1How It Works & Mechanism
One principle governs five seam techniques: cut at the velocity peak with matching direction and speed on both sides; plus two in-scene techniques (§6 waterfall entry / §7 nudge group slide).
Five SEAM techniques, one principle: **cut at peak velocity, match direction and speed on both sides of the cut** — plus the two in-scene techniques (§6 arrivals, §7 slides).
The mechanics of velocity matching break down to 'splitting one power4.inOut in half': exit uses power4.in + entry uses power4.out, sharing equal distance and duration, ensuring speeds match precisely at the cut point.
- **Mirrored eases:** exit `power4.in` + entry `power4.out`, same distance and duration — the two halves of one `power4.inOut`, so velocity matches exactly at the cut.
The default scene boundary is cut-the-curve with partial displacement: ~12% of frame width (~230px under 1920), never a full screen exit; all four directions define explicit start/end values for exit and entry (Left: exit 0→−230 / entry +230→0, and so on).
**Partial travel:** ~12% of frame (≈230px at 1920) — never full off-screen moves. | Direction | Exit | Entry start → end | | --------- | ------------- | ----------------- | | Leftward | `x: 0 → −230` | `x: +230 → 0` |
Fade-out technique: exit opacity completes within ~25–30% of its travel (fade-out ≈ 0.18–0.3s vs motion 0.3–0.34s), while entry ignites halfway through its path around ~0.35 opacity; the final exiting element must die precisely on the cut frame—leaving an idle gap is perceived as dead air.
- **The fade trick:** exit opacity completes at ~25–30% of its travel (fade ≈ 0.18–0.3s vs motion 0.3–0.34s); entry ignites at ~0.35 opacity mid-path. Time the last fading element to die right at the cut — a gap where nothing moves reads as dead air.
Z-axis direction is determined by sign: sharing the same axis is insufficient; the sign of d(scale)/dt must match across both sides (Push: exit 1→1.2 / entry 0.75→1; Pull: exit 1→0.8 / entry 1.25→1); two mirrored types are forbidden—a shrinking exit paired with an entry growing from small (most common, as grow-from-small is the default element entry), and a push exit paired with an oversized contraction. Furthermore, this constraint simultaneously binds the incoming scene's own entrance animation (cut point + ~0.5s window), verified against Seam Gate item 7.
| Push (forward) | growing `1 → 1.2` | growing `0.75 → 1` | zoom-through | | Pull (back) | shrinking `1 → 0.8` | shrinking `1.25 → 1` | inverse zoom-through |
Blur scaling tiers by subject dimension: text scale (titles, phrases) peaks at 10px (20px smudges letterforms, reading as a glitch rather than velocity); full-frame elements (windows, cards, screenshots) peak at 18–20px (slight blur on large surfaces reads as a render hiccup); both sides share identical peak blur on the swap frame; blur the wrapper, never the child elements.
| Text-scale (headline, word group) | **10px** | 20px smears letterforms — the cut reads as a glitch, not speed | | Full-frame surface (window, card, screenshot) | **18–20px** | lighter blur on a big surface reads as a rendering hiccup |
Waterfall cut (§4) and waterfall entry (§6) follow two distinct rule sets and must not be mixed: the seam version ignites midway at 0.35 opacity (fade-in acts as a speed trick), whereas the entry version uses binary tl.set 0→1 (fade-in dulls the snap); the seam axis defaults to X following current with an exit side, while entry defaults to Y with no exit side.
| Opacity | BINARY 0→1 via `tl.set` at entry — never fade | ignites at 0.35 mid-path — the fade IS the velocity trick | | Axis default | Y, from below | X, riding the current | | Outgoing side | none | words ramp out on mirrored power4.in |
Choreography criteria for waterfall entry: relay handoffs are not queues—the next element launches before the prior settles (±2 frames), intervals tighten progressively, and the final element snaps into place; velocity tiers by element weight (anchor/heavy 60–80px, 0.16–0.20s; normal words 40–50px, 0.13–0.16s; light words/punctuation 30–48px, 0.10–0.13s); eases use power4.out, never .inOut for entries; fragment the final word late in the timeline to sustain the climax.
- **Overlap, don't queue** — next element starts within ±2 frames of the previous settling; gaps SHRINK across the cascade; the last element snaps. - **Velocity varies by weight** — heavy/anchor elements travel further and longer; light words/punctuation snap in tight:
The nudge curve (§7) chains three tweens: 10% / 65% / 25% travel mapped across 20% / 18% / 62% duration: initiated with power3.in, followed by a linear burst (~2× average px/frame), and finished with a power4.out long tail; tail duration must be ≥3× launch duration to prevent abrupt stops; reveal new content inside the burst phase (the burst masks its appearance).
| 1 ramp-in | `power3.in` | ~10% | ~20% | barely moves — motion registers, no jolt | | 2 burst | `none` (linear) | ~65% | ~18% | ~2× average px/frame — purposeful | | 3 tail | `power4.out` | ~25% | ~62% | decaying creep to rest — kills the smack |
Rack-focus blur-cut (§5) is the sole variant that makes the cut visible: a defocus blur spike conceals a single-frame hard swap (like pulling focus on a handheld DSLR); exit remains fully opaque until the cut, using power2.in/out eases (imparting optical rather than momentum feel), reserved for narrative beats, capped at ≤ once every ~8s, and strictly forbidden during subtitles or hold shots; blur peaks at ≥6px, typically 8–12px, capped at 16–18px; the cut must land at peak blur.
The one variant where the cut is SEEN: a defocus blur SPIKE hides a single-frame hard swap — a handheld-DSLR focus-pull.
All executable code is organized in examples/gsap-implementation.md: one worker version (modifying scene-internal elements) and one registry version (injectors applied to two clip wrappers using __OLD__/__NEW__/__T__/__DUR__/__DX__/__DY__ placeholders), plus waterfall DOM/CSS/JS, rack-focus, and a tuning range reference table.
All GSAP templates — worker-authored versions, registry `gsap_template`s, the combined cut-the-curve + zoom, waterfall DOM/CSS/JS, rack-focus — live in `examples/gsap-implementation.md`.
Waterfall cut implementation details: ±230px travel, exit 0.34s power4.in, exit fade-out 0.18s launching concurrently with x (words disappear within ~25–30% travel, leaving no motion smearing), exit staggered by +0.022s in reading order (peeling away rather than sliding en masse), entry 0.3s power4.out starting at 0.35 opacity, entry staggered at 0.05s intervals with a 0.84 decay factor; all words must be preset at build time to x:+230 / opacity:0 (relying solely on immediateRender:false leaves unstarted words stranded at visible resting positions).
- Pre-set all words to `x: +230, opacity: 0` at build time — `immediateRender: false` alone leaves un-started words visible at rest.
In registry templates, cut-the-curve incoming displacement uses __DXIN__ / __DYIN__ × 0.12 (horizontal) / × 0.21 (vertical) to express reverse entry movement, whereas seam-craft placeholder tables only list __DX__ / __DY__—revealing unclosed token naming between sides.
`__DX__` = `-1920` (LEFT) / `1920` (RIGHT); `__DY__` = `-1080` (UP) / `1080` (DOWN). The `* 0.12` / `* 0.21` factors yield the ~12% partial travel.
The merged worker/registry variant (cut-the-curve + subtle Z pull) also enforces Z-sign rules: both sides contract (exit 1→0.92, entry 1.08→1), never pairing a shrinking exit with an entry growing from small.
The scale component obeys the Z sign rule: both sides SHRINK (exit `1 → 0.92`, entry `1.08 → 1`) — a consistent mild pull layered on the lateral cut. Never pair a shrinking exit with a grow-from-small entry here.
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| package | 上位 skill 依赖:motion-doctrine(接缝法、电流、账本、Seam Gate 的归属地) |
| package | 同仓组件:transition registry 的 gsap_template(注入器按 token 施加到两个 clip wrapper)、seam-craft(stage ground 前置) |
| package | GSAP(模板代码运行于宿主 composition 的 GSAP 时间线;本 skill 不自带库) |
4Recommended Governance & Evidence
- SKILL.md: Pure prompt directives and rule text with no script execution or external impact
5Second-Pass Verification
- [ok] 「五个接缝」是否每条都有可抄实现(防止目录表吹牛) — examples/gsap-implementation.md 逐条核对:§1 Zoom-Through(worker + registry 两版)、§2 Inverse(registry 版 + 说明 worker 只是翻符号)、§3 Cut the Curve(worker + registry 横/竖两版 + 合并 zoom 版)、§4 Waterfall Cut(DOM/CSS + wordExit/wordEnter 时间线函数)、§5 Rack-Focus、§6 Waterfall Entry、§7 Nudge Curve(含 150px 变体)。声明与实现相符。
- [discrepancy] registry 模板的 token 是否与 seam-craft 的占位符契约一致(跨 skill 引用是否自洽) — 存在一处不闭合:examples 的 registry 模板入场用 `__DXIN__ * 0.12` / `__DYIN__ * 0.21`(而注释只解释 `__DX__ = -1920 (LEFT) / 1920 (RIGHT)`),但 seam-craft 的占位符表只列 `__OLD__ / __NEW__ / __T__ / __DUR__ / __DX__ / __DY__ / __ORIGIN_OUT__ / __ORIGIN_IN__`——**没有 `__DXIN__` / `__DYIN__`**。即这份模板若要真被注入器施加,入场侧的水平/垂直位移 token 名对不上(需注入器额外提供或模板改为取负)。属跨文档的 token 命名漂移,照抄可能注入失败或被替换为空。
- [ok] 难度最高的那条规则(Z 符号绑定入场场景自身入场)是否在别处有一致说法 — cut-the-curve 的 Z 符号段 + 反模式表两处,以及 §2 的 Sign discipline(`the incoming scene arrives as a composed frame inside the retracting wrapper — no grow-from-small intro in the seam window`)措辞一致;motion-doctrine 的 Seam Gate 段亦列 `the Z sign rule … the incoming scene's own entrances are scanned for sign-fighting`,三处自洽。
- [ok] §3 列出的 stage ground 前置与 seam-craft 是否一致(跨页重复会不会打架) — 两页都写 `background: var(--canvas-deep, var(--canvas, #000))`,且本页显式 `(see seam-craft)` 交回详情;无参数冲突。该表达式与代码实现的形式差异(pin 内 canvas-deep 零命中、assemble-index.mjs 实际输出 frame.md canvas 色)已记在 seam-craft 的分析中。
- [ok] 数值是否被第一遍夸大(例:把 rack-focus 的配额写成建议值) — 原文硬写 `≤ once per ~8s; never mid-caption or during a hold`,并给上下限 `≥6px; peak 8–12px, ≤16–18px max`;本 JSON 照录,未软化。
- [ok] 是否存在被遗漏的外部资源(CLI/API/包) — 两文件全文 URL 零命中;无 npx/CLI 调用语句。唯一外部依赖是 GSAP 运行时(由宿主 composition 提供)与同仓的 motion-doctrine / transition registry / seam-craft(文档互指)。
6Verdict & Scenarios
f788ef0474b6f6ce…