# Cut the Curve — GSAP code templates Canonical implementations for every variant. Parameters and rules live in `../SKILL.md`; copy code from here. Worker-authored versions tween in-scene elements; registry `gsap_template`s are injector-stamped onto the two clip wrappers (`__OLD__` / `__NEW__` / `__T__` / `__DUR__` tokens — see `seam-craft` for the token table). ## 1. Zoom-Through (forward) ### Worker version (within-scene wrapper swap) ```js var EXIT_START = /* when readable text starts leaving */; var CUT = EXIT_START + 0.2; // Phase 1: Exit — scale/blur accelerate, opacity fades linearly (separate tween) tl.to(".text-a-wrapper", { scale: 1.2, filter: "blur(10px)", // text-scale: 10px duration: 0.2, ease: "power3.in", overwrite: "auto" }, EXIT_START); tl.to(".text-a-wrapper", { opacity: 0.15, duration: 0.2, ease: "none" }, EXIT_START); // Phase 2: Hard cut — matched properties tl.set(".text-a-wrapper", { opacity: 0 }, CUT); tl.set(".text-b-wrapper", { opacity: 0.15, scale: 0.75, filter: "blur(10px)" }, CUT); // Phase 3: Entry — fast initial velocity, long settle tl.to(".text-b-wrapper", { scale: 1, filter: "blur(0px)", opacity: 1, duration: 0.5, ease: "expo.out" }, CUT); ``` ### Registry gsap_template ```js tl.to( __OLD__, { scale: 2.5, opacity: 0, filter: "blur(8px)", duration: __DUR__, ease: "power3.in" }, __T__, ); tl.fromTo( __NEW__, { scale: 0.5, opacity: 0, filter: "blur(8px)" }, { scale: 1, opacity: 1, filter: "blur(0px)", duration: __DUR__, ease: "power3.out" }, __T__, ); ``` ## 2. Inverse Zoom-Through ### Registry gsap_template ```js tl.set(__NEW__, { opacity: 0 }, __T__); tl.to( __OLD__, { scale: 0.8, filter: "blur(10px)", duration: __DUR__ * 0.3, ease: "power3.in" }, __T__, ); tl.to(__OLD__, { opacity: 0.15, duration: __DUR__ * 0.3, ease: "none" }, __T__); tl.set(__OLD__, { opacity: 0 }, __T__ + __DUR__ * 0.3); tl.fromTo( __NEW__, { opacity: 0.15, scale: 1.25, filter: "blur(10px)" }, { opacity: 1, scale: 1, filter: "blur(0px)", duration: __DUR__ * 0.7, ease: "expo.out", immediateRender: false, }, __T__ + __DUR__ * 0.3, ); ``` Worker version: same phases as zoom-through with the scale values flipped (exit `1 → 0.8`, cut-in at `1.25`, entry `1.25 → 1`). ## 3. Cut the Curve ### Worker version (scene layers) ```js var CUT_TIME = /* scene transition point */; // Scene A: hero accelerates leftward (partial travel ~12% of frame) tl.to(".scene-a-layer", { opacity: 0, duration: 0.33, ease: "power2.in" }, CUT_TIME - 0.33); tl.to(".hero-a-wrapper", { x: -230, filter: "blur(8px)", duration: 0.33, ease: "power4.in", // mirrored half of power4.inOut overwrite: "auto" }, CUT_TIME - 0.33); // Hard cut tl.set(".scene-b-layer", { opacity: 1 }, CUT_TIME); tl.set(".hero-b-wrapper", { x: 230, filter: "blur(8px)" }, CUT_TIME); // Scene B: hero decelerates leftward tl.to(".hero-b-wrapper", { x: 0, filter: "blur(0px)", duration: 0.33, ease: "power4.out" // matched velocity at the cut }, CUT_TIME); ``` ### Registry gsap_template `__DX__` = `-1920` (LEFT) / `1920` (RIGHT); `__DY__` = `-1080` (UP) / `1080` (DOWN). The `* 0.12` / `* 0.21` factors yield the ~12% partial travel. ```js // horizontal tl.set(__NEW__, { opacity: 0 }, __T__); tl.to(__OLD__, { x: __DX__ * 0.12, duration: __DUR__ * 0.5, ease: "power4.in" }, __T__); tl.to(__OLD__, { opacity: 0, duration: __DUR__ * 0.47, ease: "power2.in" }, __T__ + __DUR__ * 0.03); tl.fromTo( __NEW__, { x: __DXIN__ * 0.12, opacity: 0.35 }, { x: 0, opacity: 1, duration: __DUR__ * 0.5, ease: "power4.out", immediateRender: false }, __T__ + __DUR__ * 0.5, ); // vertical tl.set(__NEW__, { opacity: 0 }, __T__); tl.to(__OLD__, { y: __DY__ * 0.21, duration: __DUR__ * 0.5, ease: "power4.in" }, __T__); tl.to(__OLD__, { opacity: 0, duration: __DUR__ * 0.47, ease: "power2.in" }, __T__ + __DUR__ * 0.03); tl.fromTo( __NEW__, { y: __DYIN__ * 0.21, opacity: 0.35 }, { y: 0, opacity: 1, duration: __DUR__ * 0.5, ease: "power4.out", immediateRender: false }, __T__ + __DUR__ * 0.5, ); ``` ### Combined cut-the-curve + zoom 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. ```js // Scene A: hero slides left + mild pull + blur tl.to( ".hero-a-wrapper", { x: -230, scale: 0.92, filter: "blur(8px)", duration: 0.33, ease: "power4.in", }, CUT_TIME - 0.33, ); // Cut + Scene B: continues leftward, arrives slightly oversized and retracts tl.set(".hero-b-wrapper", { x: 230, scale: 1.08, filter: "blur(8px)" }, CUT_TIME); tl.to( ".hero-b-wrapper", { x: 0, scale: 1, filter: "blur(0px)", duration: 0.42, ease: "power4.out", }, CUT_TIME, ); ``` ## 4. Waterfall Cut ### DOM + CSS ```html