# Composition Authoring
HTML structure, data attributes, timeline contract, and non-negotiable rules.
## Root Structure
Standalone `index.html` — the top-level composition. **Does NOT use ``**. Put the `data-composition-id` div directly in ``.
```html
```
Sub-compositions loaded via `data-composition-src` **DO** use ``:
```html
```
Load from the root: ``
## Data Attributes
### All clips
| Attribute | Required | Values |
| ------------------ | --------------------------------- | ------------------------------------------------------ |
| `id` | Yes | Unique identifier |
| `data-start` | Yes | Seconds, or clip ID reference (`"el-1"`, `"intro + 2"`) |
| `data-duration` | Required for img/div/compositions | Seconds. Video/audio defaults to media duration. |
| `data-track-index` | Yes | Integer. Same-track clips cannot overlap. |
| `data-media-start` | No | Trim offset into source (seconds) |
| `data-volume` | No | 0–1 (default 1) |
`data-track-index` controls timeline layout only — **not** visual layering. Use CSS `z-index` for layering.
### Composition clips
| Attribute | Required | Values |
| ---------------------------- | -------- | -------------------------------------------- |
| `data-composition-id` | Yes | Unique composition ID |
| `data-start` | Yes | Start time (root composition: `"0"`) |
| `data-duration` | Yes | Takes precedence over GSAP timeline duration |
| `data-width` / `data-height` | Yes | Pixel dimensions (1920x1080 or 1080x1920) |
| `data-composition-src` | No | Path to external HTML file |
## Timeline Contract
- Every timeline starts `{ paused: true }` — the player controls playback.
- Register every timeline: `window.__timelines[""] = tl`.
- Duration comes from `data-duration`, not from the GSAP timeline length.
- Framework auto-nests sub-timelines — do NOT manually add them.
- Never create empty tweens just to set duration.
## Non-Negotiable Rules
1. **Deterministic.** No `Math.random()`, `Date.now()`, or time-based logic. Use a seeded PRNG (e.g. mulberry32) if you need pseudo-randomness.
2. **GSAP only on visual properties.** `opacity`, `x`, `y`, `scale`, `rotation`, `color`, `backgroundColor`, `borderRadius`, transforms. Never animate `visibility`, `display`, or call `video.play()`/`audio.play()`.
3. **No property conflicts across timelines.** Never animate the same property on the same element from multiple timelines simultaneously.
4. **No `repeat: -1`.** Infinite-repeat tweens break the capture engine. Compute `repeat: Math.ceil(duration / cycleDuration) - 1`.
5. **Synchronous timeline construction.** Never build timelines inside `async`/`await`, `setTimeout`, or Promises. The capture engine reads `window.__timelines` synchronously after page load. Fonts are embedded by the compiler — no need to wait for load.
6. **Root composition has no `` wrapper.** Only sub-compositions use ``.
7. **Video is always `muted playsinline`.** Audio is always a separate `