You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: SKILL.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -126,6 +126,8 @@ The Shotstack schema does **not** match CSS or web conventions. Composing Edit J
126
126
127
127
The full ruleset (asset types, fonts, smart-string clip values, top-5 mistakes) lives in `shared/agent-core.md`. The same file is also returned by the Shotstack MCP server's `get_shotstack_guide` tool, so the conventions are identical across surfaces.
128
128
129
+
**For anything that animates, compose motion from the house tokens** — one duration scale (`base` 0.6 s in / `fast` 0.33 s out), one house ease (`power3.out` / `cubic-bezier(0.16,1,0.3,1)`, no overshoot by default), one stagger (`0.13 s`). The *Motion language* section of `agent-core.md` is the summary; [`references/motion.md`](references/motion.md) has the full GSAP/CSS recipes and the brand kit. **Don't invent a new easing or duration per clip** — shared tokens are what make a multi-clip edit feel like one production.
130
+
129
131
## Exit codes
130
132
131
133
| Code | Meaning |
@@ -154,6 +156,7 @@ This skill ships sub-references for the gnarly bits:
154
156
-[`references/positioning.md`](references/positioning.md) — coordinate model, `position`/`offset` (fraction of frame, +y up), clip bounding box & `fit`, text sizing, transform order
155
157
-[`references/caption.md`](references/caption.md) — sizing per resolution, default style, the 5 named presets, alias pattern (asset type: `rich-caption`)
156
158
-[`references/svg.md`](references/svg.md) — required attrs, supported elements
159
+
-[`references/motion.md`](references/motion.md) — **the house motion language**: one duration scale, one ease, one stagger; choreography recipes (GSAP/CSS), the rich-text/transition mappings, and the brand kit. Read before composing any animation.
pulsing CTAs, grain. Each is a **single clip**: paste it into a track's
5
5
`clips[]`, set `start`/`length`, and position with `offset`.
6
6
7
-
Read [`html5.md`](html5.md) first for the rules these obey. The non-negotiables:
7
+
Every snippet here is composed from the house **[`motion.md`](motion.md)** tokens —
8
+
one duration scale (`base` 0.6 s in, `fast` 0.33 s out), one house ease
9
+
(`power3.out` / `cubic-bezier(0.16,1,0.3,1)`), one stagger (`0.13 s`), and a single
10
+
shared palette (ink `#141414`, accent `#D96B82`). That shared vocabulary is what
11
+
makes a set of these clips feel like one production. **When you adapt a snippet,
12
+
keep the tokens** — change the words, the colours and the canvas size, not the
13
+
easings and durations. Read [`motion.md`](motion.md) for the why and the full recipe set.
14
+
15
+
Read [`html5.md`](html5.md) for the rules these obey. The non-negotiables:
8
16
9
17
-**Seekable animation only.** GSAP timelines, GSAP tweens (incl. `onUpdate`), anime.js, Lottie, or CSS `@keyframes`. **Never**`setTimeout`/`setInterval`/`requestAnimationFrame`/`Date.now()`/`gsap.call()` — the renderer seeks by absolute time, it doesn't play.
10
18
-**Size the clip to the content, not the canvas.**`html, body` pinned to the clip's `width`/`height`; place with `offset` (`{x:0,y:0}` is centred, `y` positive is up). Use **px**, never `vw`/`vh`/`%`.
@@ -13,21 +21,51 @@ Read [`html5.md`](html5.md) first for the rules these obey. The non-negotiables:
13
21
-**No network.** gsap/anime/d3/lottie are preloaded; external `<script src>`, `fetch`, remote `<img>`, and remote fonts are all CSP-blocked — inline everything as `data:` URIs.
14
22
-**Fonts:**`timeline.fonts[]` does **not** reach `html5` and remote `@font-face` is blocked. These snippets name a display font first but render in the `system-ui` fallback unless you inline the font as a `data:``@font-face`.
15
23
16
-
Coordinates below assume a **1080×1920 vertical** canvas; adjust `offset` for other sizes. Colours use a neutral ink/accent — swap for your palette.
24
+
Coordinates below assume a **1080×1920 vertical** canvas; adjust `offset` for other sizes.
25
+
26
+
> **Continuous-motion exception.** Looping or drifting effects (the pulse, the sweep, the grain) are *ambient*, not entrances — they correctly use `ease-in-out` / `linear` and their own loop durations rather than the entrance tokens. Everything that *reveals* uses the house entrance tokens.
27
+
28
+
---
29
+
30
+
## 1. Blur reveal — calm text entrance
31
+
32
+
**Category** entrances · **Use when** the default text reveal; the calm house entrance for a title or line — reach for a punchier one (snippet 2) only with intent · **Canvas** 900×300 · **Tags** text, reveal, entrance, blur
33
+
34
+
The reference entrance: opacity, blur and a 16 px rise settle **together** off one tween (one progress, many channels) on the house ease — no overshoot. Quietly cinematic.
`base` (0.6 s) entrance on `power3.out`, then a `hold` (1.5 s) settle. Swap `{{title}}` via top-level `merge[]`. `Clash Display` falls back to `system-ui` unless you inline it as a `data:``@font-face` (see Fonts above).
17
53
18
54
---
19
55
20
-
## 1. Kinetic headline (word-by-word rise)
56
+
## 2. Kinetic headline (word-by-word rise)
21
57
22
-
Big title where each word springs up in sequence. GSAP timeline, fully seekable.
58
+
**Category** entrances · **Use when** a headline needs energy — a hype/hero title where each word punches up in sequence · **Canvas** 980×420 · **Tags** text, reveal, entrance, stagger, hero
59
+
60
+
Each word springs up in sequence. GSAP timeline, fully seekable, on the house stagger.
@@ -37,11 +75,13 @@ Big title where each word springs up in sequence. GSAP timeline, fully seekable.
37
75
}
38
76
```
39
77
40
-
Each word is a `<span>` starting `translateY(120%)`; the trailing empty tween holds the title still before the clip ends. `Anton` falls back to `system-ui` unless you inline it (see Fonts above): `@font-face{font-family:'Anton';src:url('data:font/woff2;base64,…') format('woff2')}`.
78
+
Each word starts `translateY(120%)`, opacity 0; `0.6 s` rise on `power3.out`, words `0.13 s` apart (the house stagger); a trailing empty tween holds the title still. **Punchy variant:** this is the one "hero" spot where a pop is allowed — swap `ease:'power3.out'` for `ease:'back.out(1.4)'` for a gentle overshoot. Keep it to one headline per scene. `Anton` falls back to `system-ui` unless inlined.
41
79
42
80
---
43
81
44
-
## 2. Count-up number / price odometer
82
+
## 3. Count-up number / price odometer
83
+
84
+
**Category** data · **Use when** revealing a value, price, stat or metric · **Canvas** 620×220 · **Tags** number, count, price, data · **Merge-friendly** target value
45
85
46
86
Animate a value from 0 to its target. Seek-safe because the count lives in a **tweened object with `onUpdate`** (fires on seek), never a timer.
47
87
@@ -51,7 +91,7 @@ Animate a value from 0 to its target. Seek-safe because the count lives in a **t
@@ -61,20 +101,22 @@ Animate a value from 0 to its target. Seek-safe because the count lives in a **t
61
101
}
62
102
```
63
103
64
-
Swap `v:395` for any target. For thousands separators use `Math.round(o.v).toLocaleString()`. Pair with a static label on an adjacent `rich-text` track ("FROM", "AUD").
104
+
`slow` (0.8 s) count on `power2.out` (a decelerating settle reads right for a value), then a `hold`. Swap `v:395` for any target; for thousands separators use `Math.round(o.v).toLocaleString()`. Pair with a static label on an adjacent `rich-text` track ("FROM", "AUD").
65
105
66
106
---
67
107
68
-
## 3. Shine / gloss sweep
108
+
## 4. Shine / gloss sweep
69
109
70
-
A specular highlight that slides across text or a card — premium product gloss. Pure CSS keyframe (WAAPI-seekable). Put this clip **above** the thing it shines on, or wrap the content in the same clip.
110
+
**Category** graphics (emphasis) · **Use when** adding premium gloss to a product name, logo or card · **Canvas** 860×280 · **Tags** shine, gloss, emphasis, specular
111
+
112
+
A specular highlight slides across text — premium product gloss. *Continuous* motion (the sweep itself), so it uses `ease-in-out` over `slower` (1.0 s), not an entrance token. Pure CSS keyframe (WAAPI-seekable). Put this clip **above** the thing it shines on, or wrap the content in the same clip.
@@ -85,20 +127,22 @@ A specular highlight that slides across text or a card — premium product gloss
85
127
}
86
128
```
87
129
88
-
`mix-blend-mode: overlay` makes the sweep read as a real highlight rather than a white bar. No JS needed.
130
+
`mix-blend-mode: overlay` makes the sweep read as a real highlight rather than a white bar. No JS needed. The `0.4 s` start delay lets the thing it shines on settle first.
89
131
90
132
---
91
133
92
-
## 4. Pulsing CTA button
134
+
## 5. Pulsing CTA button
135
+
136
+
**Category** graphics (emphasis) · **Use when** drawing the eye to a CTA on an end card · **Canvas** 620×170 · **Tags** cta, button, pulse, loop · **Accent**`#D96B82`
93
137
94
-
A "SHOP NOW" pill with a soft breathing glow — draws the eye on an end card. CSS keyframes loop and seek cleanly.
138
+
A "SHOP NOW" pill with a soft breathing glow. *Ambient loop* — `ease-in-out`, its own 1.6 s cycle (exempt from the entrance tokens). CSS keyframes seek cleanly.
@@ -109,13 +153,15 @@ A "SHOP NOW" pill with a soft breathing glow — draws the eye on an end card. C
109
153
}
110
154
```
111
155
112
-
The clip is wider/taller than the pill so the glow has room (`overflow:hidden` would otherwise clip it). For a non-looping single pop, replace `infinite` with `1`.
156
+
The accent (`#D96B82`) is used here as the single earned colour. The clip is wider/taller than the pill so the glow has room. For a non-looping single pop, replace `infinite` with `1`.
113
157
114
158
---
115
159
116
-
## 5. Film-grain / texture overlay
160
+
## 6. Film-grain / texture overlay
117
161
118
-
A subtle moving grain over the whole frame — adds a moody, analogue feel (great over dark scenes). SVG `feTurbulence`, animated by shifting a slightly-oversized layer so it never reveals an edge. Size this one **to the canvas** and put it on a top track at low opacity.
162
+
**Category** atmosphere · **Use when** adding a moody analogue texture over a dark scene · **Canvas** 1080×1920 (full frame) · **Tags** grain, texture, overlay, atmosphere
163
+
164
+
A subtle moving grain over the whole frame. *Continuous drift* — `steps()`/`linear` is correct here (not an entrance). SVG `feTurbulence`, animated by shifting a slightly-oversized layer so it never reveals an edge. Size this one **to the canvas** and put it on a top track at low opacity.
119
165
120
166
```json
121
167
{
@@ -137,9 +183,24 @@ A `data:` URI is fine **inside an html5 asset's CSS** (it's iframe content, not
137
183
138
184
---
139
185
186
+
## Brand kit — re-skin every snippet at once
187
+
188
+
The snippets share one palette (ink `#141414`, accent `#D96B82`) so a set already looks coherent. To re-skin a whole edit to a brand in one place, lift the colours/font into top-level `merge[]` and reference the tokens in each clip's `css` — `merge` find/replace runs over the `html`/`css` strings too:
Then in any snippet's CSS, swap the literal hex for the token: `color:{{ink}}`, `background:{{accent}}`, `font-family:{{font}}`. One edit re-skins every clip. Keep the accent **earned** — a headline word, a number, a CTA, one glow; everything else neutral. (If you ship a snippet *without* a matching `merge[]` entry, leave the literal hex in — an undefined `{{token}}` renders as invalid CSS.)
199
+
140
200
## Composing these
141
201
142
202
- Each snippet is one clip on its own track. Layer order is top-track-first (see `agent-core.md`) — grain and shine go in **early** tracks, backgrounds in **late** ones.
143
203
- They don't overlap on a single track, so `shotstack validate <file>` stays clean. Run it before rendering.
144
204
- Reuse text via top-level `merge[]` (`{{title}}` in the HTML) — see the lower-third example in `html5.md`.
205
+
- Mix calm and punchy deliberately: a `blur-reveal` title, a `kinetic-headline` hero line, a `count-up` stat, a `shine` on the product, a pulsing CTA — all on the same tokens, so the set reads as one piece.
145
206
- Heavier motion = longer render. Preview in `shotstack studio <file>` before spending credits.
0 commit comments