# Composition Patterns
## Contents
- Picture-in-picture
- Text behind subject
- Title card with fade
- Slide show with section headers
- Top-level composition example
## Picture-in-Picture (Video in a Frame)
Animate a wrapper div for position/size. The video fills the wrapper. The wrapper has NO data attributes.
```html
```
```js
tl.to(
"#pip-frame",
{ top: 700, left: 1360, width: 500, height: 280, borderRadius: 16, duration: 1 },
10,
);
tl.to("#pip-frame", { left: 40, duration: 0.6 }, 30);
```
## Text Behind Subject (transparent webm overlay)
Put a headline _behind_ a presenter so their silhouette occludes the text. Requires a transparent cutout produced by `npx hyperframes remove-background presenter.mp4 -o presenter.webm`.
Three layers, plus one critical rule:
```html
MAKE IT IN HYPERFRAMES
```
```js
const tl = gsap.timeline({ paused: true });
const CUT = 3.3;
// Reveal headline early
tl.to("#cf-headline", { clipPath: "inset(0 0 0% 0)", duration: 0.6, ease: "expo.out" }, 0.25);
// At the cut, flip the cutout wrapper visible — the presenter's silhouette
// punches through the headline.
tl.set(".cutout-wrap", { opacity: 1 }, CUT);
// Sentinel: extend timeline to the composition's full duration so the
// renderer doesn't bail past the last meaningful tween.
tl.set({}, {}, 6);
window.__timelines["cover-flip"] = tl;
```
**Why a wrapper div, not opacity on the video itself?**
The framework forces `opacity: 1` on any element with `data-start`/`data-duration` while it's "active" — that's how it manages clip lifecycles. A CSS `opacity: 0` on the video element is silently overwritten. Wrap the video in a div with no `data-*` attributes; the wrapper is owned by your CSS/GSAP.
**Why both videos at `data-start="0"`?**
So both decode in sync from t=0. Late-mounting the cutout (`data-start=3.3`) makes Chrome do a seek + decoder warm-up at mount, which can land a frame off the base mp4 — visible as a one-frame jitter at the cut.
**Color match:** `remove-background` defaults to `--quality balanced` (crf 18) which keeps the cutout's RGB nearly identical to the source mp4 — minimal edge halo or color shift when overlaid. Use `--quality best` (crf 12) for hero shots; only drop to `--quality fast` (crf 30) when the cutout sits over a _different_ background and the size matters.
## Title Card with Fade
```html
My Video Title
```
```js
tl.to("#title-card h1", { opacity: 1, duration: 0.6 }, 0.3);
tl.to("#title-card", { opacity: 0, duration: 0.5 }, 4);
```
## Slide Show with Section Headers
Use separate elements on the same track, each with its own time range. Slides auto-mount/unmount based on `data-start`/`data-duration`.
```html
...
...
...
```
## Top-Level Composition Example
```html
```