# Variables and Media
Two separate concerns, grouped because both control "what flows in from outside the HTML": runtime parameters (variables) and external media files (video/audio).
## Variables
Declare variables on the `` element with `data-composition-variables`. Each declaration needs `id`, `type`, `label`, and `default`:
```html
```
**Prefer declarative bindings — no script needed** for direct substitution:
```html
Fallback
```
- `data-var-src="id"` substitutes the element's `src` (URL string or image `{url}`); the authored `src` is the fallback.
- `data-var-text="id"` substitutes the element's own text; element children (nested clips, animated spans) are preserved.
- Every scalar variable is applied automatically as a `--{id}` CSS custom property on the composition root, so `var(--id)` CSS responds to overrides — no `setProperty` boilerplate.
- Bindings resolve identically in preview and render, and per-instance for sub-compositions.
- Caveat: media with audio should keep a real fallback `src` — render audio extraction reads the authored attribute (lint: `media_variable_src_no_fallback`).
For logic beyond direct substitution (loops, conditionals, derived values), read values once during initialization:
```js
const { title, accent } = window.__hyperframes.getVariables();
document.getElementById("title").textContent = title;
```
### Variable Rules
- Supported types and their extra options (consumed by Studio's editing UI):
- `string` — optional `placeholder`, `maxLength`
- `number` — optional `min`, `max`, `step`, `unit`
- `color` — none
- `boolean` — none
- `enum` — **required** `options: [{ "value": "...", "label": "..." }, ...]`
- Always provide useful `default` values so preview works without CLI overrides.
- Use `data-variable-values='{"title":"Pro"}'` on sub-composition hosts for per-instance overrides.
- Use `npx hyperframes render --variables '{"title":"Q4 Report"}'` or `--variables-file` for render-time overrides.
- Add `--strict-variables` in CI: turns undeclared keys, type mismatches, and enum values not in `options` into errors instead of warnings.
- Read values once during init, not on every animation tick — variables don't change mid-render.
- Media color grading can use exact variable references inside `data-color-grading` JSON. Use `$gradingPreset` or `${gradingIntensity}` as the whole field value; the runtime resolves it from the current composition's variables before applying shader adjustments, finishing details, blur/pixelate effects, and custom LUTs.
### Two JSON Shapes (Easy to Confuse)
- `data-composition-variables` is an **array of declarations** (the schema): `[{id, type, label, default}, ...]`
- `--variables` and `data-variable-values` are **objects keyed by id** (the values): `{ title: "Q4", accent: "#fff" }`
## Media
**NON-NEGOTIABLE: `