dreative 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -35
- package/dist/server/ai.js +177 -0
- package/dist/server/preview.js +73 -73
- package/dist/ui/index.html +11 -11
- package/package.json +1 -1
- package/skill/dreative/DESIGN.md +25 -1
- package/skill/dreative/PLAN.md +201 -143
- package/skill/dreative/SKILL.md +2 -2
- package/skill/dreative/skills/cinematic.md +232 -232
- package/skill/dreative/skills/immersive.md +223 -223
- package/skill/dreative/skills/media.md +216 -216
- package/skill/dreative/skills/mobile.md +117 -117
- package/skill/dreative/skills/refined.md +102 -102
- package/skill/dreative/skills/ux.md +144 -144
|
@@ -1,216 +1,216 @@
|
|
|
1
|
-
# Dreative Specialist Skill — Media as Motion Material
|
|
2
|
-
|
|
3
|
-
Load this file when `plan.skills` includes `media`, when the plan's blueprint
|
|
4
|
-
contains any `generate-*` media cell, or when the brief involves imagery/video
|
|
5
|
-
on a page with motion dial ≥ 6. It EXTENDS DESIGN.md §7 (sourcing priority and
|
|
6
|
-
bans still apply) and STACKS with motion.md (timing), 3d.md (shader craft), and
|
|
7
|
-
cinematic.md (the living surface). This file exists because agents know how to
|
|
8
|
-
*embed* media but not how to *use* it: award-grade sites (unseen.co family)
|
|
9
|
-
treat images and video as the raw material the motion system acts on — media is
|
|
10
|
-
choreographed, distorted, revealed, and lit, never just placed.
|
|
11
|
-
|
|
12
|
-
## 0. The doctrine
|
|
13
|
-
|
|
14
|
-
- **No bare media at dial ≥ 7.** Every meaningful image/video gets three
|
|
15
|
-
decisions: an **entrance** (how it arrives — reveal, wipe, materialize), an
|
|
16
|
-
**idle** (what it does at rest — loop, drift, ken-burns, nothing-on-purpose),
|
|
17
|
-
and a **response** (what interaction does to it — hover wake, distortion,
|
|
18
|
-
parallax). "None" is a valid answer per axis, but it must be chosen, not
|
|
19
|
-
defaulted.
|
|
20
|
-
- **Media and type arrive as one beat.** Time the media entrance with the
|
|
21
|
-
section's line-mask type reveal (motion.md §4) — image and headline landing
|
|
22
|
-
together reads as choreography; landing separately reads as two plugins.
|
|
23
|
-
- **One treatment vocabulary per page.** Pick 1-2 media treatments and stamp
|
|
24
|
-
them consistently (all work cards hover-wake; all section images curtain-
|
|
25
|
-
reveal). Five different reveal styles = assembled, not designed.
|
|
26
|
-
- **Invent, don't pick.** §2/§3 are springboards, not a menu — the signature
|
|
27
|
-
media treatment should be COMPOSED for this brand and this prompt using the
|
|
28
|
-
grammar in §2.5 (a torn-paper archive scrolls differently than a liquid
|
|
29
|
-
fashion film). Stock-vocabulary media reads as template exactly like stock
|
|
30
|
-
layouts do; if the user's prompt describes an effect ("images tear apart on
|
|
31
|
-
scroll"), build THAT effect for real, at the tier it needs.
|
|
32
|
-
- **Real assets outrank generated ones** (DESIGN.md §7). Generated media fills
|
|
33
|
-
gaps and creates atmosphere; it never replaces the client's product shots.
|
|
34
|
-
|
|
35
|
-
## 1. Production pipeline (generate → grade → compress)
|
|
36
|
-
|
|
37
|
-
When the plan calls for generated media, produce it BEFORE section code
|
|
38
|
-
(PLAN.md §4) and produce it correctly:
|
|
39
|
-
|
|
40
|
-
- **Prompt for the world, grade for the page.** Prompt the brand's physical
|
|
41
|
-
subject (DESIGN.md §7) PLUS the page's light: temperature ("warm tungsten
|
|
42
|
-
side-light", "cool overcast daylight"), palette anchors ("deep green shadows,
|
|
43
|
-
bone highlights"), and grain/mood. Every asset on a page shares ONE lighting
|
|
44
|
-
logic — mismatched light is the #1 generated-media tell.
|
|
45
|
-
- **Exact aspect ratios** from the blueprint (16:9 hero, 4:5 cards, 1:1
|
|
46
|
-
thumbnails, 21:9 banners). Never generate square and crop-hope.
|
|
47
|
-
- **Video loops**: 5-10s, prompt explicitly for seamlessness ("seamless loop,
|
|
48
|
-
continuous motion, no scene change") and slow motion content (drift, steam,
|
|
49
|
-
fabric, water — fast action never loops cleanly). Generate or extract a
|
|
50
|
-
**poster frame** for every video (first frame, same grade).
|
|
51
|
-
- **Image sequences** for scroll scrubs: 40-80 frames of one continuous
|
|
52
|
-
transformation (assemble/rotate/morph). Image-to-video tools can produce
|
|
53
|
-
these from a single generated still; export frames with ffmpeg
|
|
54
|
-
(`ffmpeg -i loop.mp4 -vf fps=12,scale=1280:-1 frames/f_%03d.webp`).
|
|
55
|
-
- **Compress before committing**: images → WebP/AVIF at the largest displayed
|
|
56
|
-
size ×2 max; video → H.264 + AV1 sources, CRF ~28-32, no audio track, ≤ 2-4MB
|
|
57
|
-
per loop (`ffmpeg -i in.mp4 -an -c:v libx264 -crf 30 -movflags +faststart`).
|
|
58
|
-
A 40MB hero loop fails the plan even if it's beautiful.
|
|
59
|
-
- Textures too: grain tiles, masks, mattes, displacement maps — generate them
|
|
60
|
-
instead of hand-rolling SVG (which is banned, DESIGN.md §7).
|
|
61
|
-
|
|
62
|
-
## 2. DOM-tier treatments (no WebGL — the budget vocabulary)
|
|
63
|
-
|
|
64
|
-
80% of the effect at 5% of the cost; the right tier below dial 8 or without a
|
|
65
|
-
canvas already on the page. All honor the floors in §5.
|
|
66
|
-
|
|
67
|
-
- **Curtain / inset reveal**: media enters behind a wipe —
|
|
68
|
-
`clip-path: inset(100% 0 0 0) → inset(0)` (or 2-4 panel slides), 900ms
|
|
69
|
-
expo-out, triggered in-view once, synced to the headline's line-mask.
|
|
70
|
-
- **Hover-woken loop**: still poster crossfades to its video loop on
|
|
71
|
-
hover/focus (240ms), `video.play()` on enter, pause + reset to poster on
|
|
72
|
-
leave. The "living thumbnail" for work/product cards. Preload `metadata`
|
|
73
|
-
only; play() only after the crossfade starts.
|
|
74
|
-
- **Mask-shaped video**: the loop plays inside display type
|
|
75
|
-
(`background-clip: text` on 10vw+ headlines), an arch/circle `clip-path`, or
|
|
76
|
-
the brand mark (SVG mask). Video becomes identity, not a rectangle. One per
|
|
77
|
-
page.
|
|
78
|
-
- **Floating media**: 3-5 images hovering in depth — slow damped drift
|
|
79
|
-
(±6-10px, 4-8s loops, each phase-offset), parallax differential by depth
|
|
80
|
-
layer, soft tinted contact shadow. The "paper sheets in space" look, pure CSS
|
|
81
|
-
+ one IntersectionObserver.
|
|
82
|
-
- **Ken-burns**: slow scale 1.0→1.06 over 12-20s inside a fixed frame,
|
|
83
|
-
alternate direction per instance. The refined register's entire motion budget
|
|
84
|
-
for imagery (refined.md).
|
|
85
|
-
- **Pixel/dither swap**: stepped `image-rendering: pixelated` downscale swap
|
|
86
|
-
(24px mosaic → full res in 4-6 steps) on scroll progress or hover. Digital-
|
|
87
|
-
craft registers.
|
|
88
|
-
- **Inner-zoom parallax**: image at 115% height inside `overflow-hidden` frame,
|
|
89
|
-
`object-position` or translateY driven by scroll (-8%→8%). Media moves, frame
|
|
90
|
-
doesn't — never parallax the frame itself past text.
|
|
91
|
-
- **Scroll-scrubbed `<canvas>` sequence**: preload frames (§1), draw the frame
|
|
92
|
-
for the current damped scroll progress; sticky wrapper ≤ 2.5 viewports
|
|
93
|
-
(motion.md §7's scrub showcase). No WebGL needed.
|
|
94
|
-
|
|
95
|
-
## 2.5 The invention grammar (compose the signature treatment)
|
|
96
|
-
|
|
97
|
-
Every media effect — including any the user describes in their own words — is
|
|
98
|
-
three choices multiplied together. Compose deliberately:
|
|
99
|
-
|
|
100
|
-
- **PROPERTY** (what changes): position/scale · opacity · clip/mask SHAPE
|
|
101
|
-
(inset, circle, arch, brand mark, jagged polygon) · slices/fragments (the
|
|
102
|
-
media cut into strips, tiles, or shards that move independently) · UV
|
|
103
|
-
distortion (WebGL: ripple, stretch, melt, swirl) · resolution (mosaic →
|
|
104
|
-
sharp) · color channels (RGB split, duotone → full color) · blend/exposure
|
|
105
|
-
(media develops like a photo print).
|
|
106
|
-
- **DRIVER** (what pushes it): scroll progress (scrubbed) · scroll VELOCITY
|
|
107
|
-
(agitation that decays) · in-view trigger (one-shot) · hover/focus ·
|
|
108
|
-
cursor position within the element (directional!) · drag · hold · time.
|
|
109
|
-
- **SHAPE OF PROGRESSION** (how it travels across the media): uniform ·
|
|
110
|
-
directional sweep (left→right, top→bottom) · radial from a point (often the
|
|
111
|
-
cursor's entry point) · per-slice stagger · noise-mask (organic, torn) ·
|
|
112
|
-
along the brand mark's silhouette.
|
|
113
|
-
|
|
114
|
-
The user's prompt usually fixes one or two axes; you compose the rest from the
|
|
115
|
-
brand's world. "Tearing" = slices + jagged noise-mask edges, driven by scroll.
|
|
116
|
-
"Video fades from left to right on hover" = opacity/mask, hover-driven,
|
|
117
|
-
directional sweep — a gradient `mask-image` whose position animates, 400ms,
|
|
118
|
-
from the edge the cursor entered. Name the composed treatment in the plan
|
|
119
|
-
blueprint like a signature element, and stamp it consistently (§0).
|
|
120
|
-
|
|
121
|
-
**Worked exotics (copy the construction, not the skin):**
|
|
122
|
-
|
|
123
|
-
- **Paper tear on scroll**: image duplicated into 2-3 layers, each clipped by
|
|
124
|
-
a jagged `clip-path` polygon sharing torn edges; scroll progress translates/
|
|
125
|
-
rotates the pieces apart (±2-6°) with a hairline of background showing
|
|
126
|
-
through; WebGL version displaces UV along a noise seam. Archive/editorial/
|
|
127
|
-
punk registers.
|
|
128
|
-
- **Strip-slice reveal**: media as 5-9 vertical strips (repeated
|
|
129
|
-
`background-image` with offset `background-position`, or plane-per-strip);
|
|
130
|
-
strips slide in staggered from alternating directions, or shear on scroll
|
|
131
|
-
velocity. The classic award-site gallery entrance.
|
|
132
|
-
- **Directional hover wipe**: detect the pointer's entry edge (compare
|
|
133
|
-
enter coordinates to bounds); the reveal (opacity mask, color→duotone,
|
|
134
|
-
still→video crossfade) sweeps FROM that edge. Feels alive because it
|
|
135
|
-
answers the gesture's direction.
|
|
136
|
-
- **Cursor-torch reveal**: media sits dimmed/blurred/halftoned; a radial mask
|
|
137
|
-
tracking the (damped) cursor reveals it sharp and graded — the flashlight
|
|
138
|
-
over an archive. Pair with a "drag to explore" label.
|
|
139
|
-
- **Melt/liquid exit**: on section leave or route change, UV y-displacement
|
|
140
|
-
grows by a noise column pattern — the image drips out of frame (WebGL), or
|
|
141
|
-
budget version: per-strip translateY with eased random offsets.
|
|
142
|
-
- **Shatter/scatter**: media as an instanced tile grid (WebGL) that explodes
|
|
143
|
-
along scroll velocity and reassembles at rest — the §3 plane system with a
|
|
144
|
-
per-instance offset uniform; cap tiles ≤ 400.
|
|
145
|
-
- **Print develop**: media enters as paper-white → exposure/contrast/duotone
|
|
146
|
-
ramps to full grade (CSS `filter` keyframes or a LUT shader), timed with
|
|
147
|
-
the headline reveal. Photography/portfolio registers.
|
|
148
|
-
|
|
149
|
-
Discipline stays the law: the composed treatment must still clear §5's floors,
|
|
150
|
-
DESIGN.md §6's "one sentence of communication value", and one-signature-
|
|
151
|
-
per-page — an inventive effect stamped on every image is as loud as a marquee
|
|
152
|
-
on every section.
|
|
153
|
-
|
|
154
|
-
## 3. WebGL tier — the media plane (the unseen.co mechanic)
|
|
155
|
-
|
|
156
|
-
When dial ≥ 8 or cinematic/immersive is active, media renders THROUGH the
|
|
157
|
-
canvas so shaders can touch it. The core pattern, in order:
|
|
158
|
-
|
|
159
|
-
1. **Sync planes to DOM rects.** Real `<img>`/`<video>` elements stay in the
|
|
160
|
-
document (a11y, SEO, layout, fallback) but render invisible
|
|
161
|
-
(`opacity: 0`, NOT `display:none` — layout must persist). For each, a
|
|
162
|
-
textured plane in an orthographic/fitted scene copies its
|
|
163
|
-
`getBoundingClientRect()` every scroll/resize (rAF-batched; lerp the
|
|
164
|
-
position for the floaty feel). Texture from `TextureLoader` or
|
|
165
|
-
`new THREE.VideoTexture(videoEl)` (video must be `muted playsinline` and
|
|
166
|
-
playing; `texture.colorSpace = SRGBColorSpace`).
|
|
167
|
-
2. **Distortion in the fragment/vertex shader**, uniforms driven by input:
|
|
168
|
-
- *Hover ripple/lens*: damped `uMouse` + `uHoverStrength` 0→1 spring; UV
|
|
169
|
-
displacement by radial falloff or noise.
|
|
170
|
-
- *Velocity stretch / RGB split*: scroll or drag velocity (from Lenis /
|
|
171
|
-
`useScroll`) → vertex bend + per-channel UV offset, hard-clamped, damped
|
|
172
|
-
decay to zero (cinematic.md §2). Peak effect at a fast flick stays legible.
|
|
173
|
-
- *Transition dissolve*: two textures + noise mask `mix()` for gallery/
|
|
174
|
-
route image swaps (3d.md §4).
|
|
175
|
-
3. **Curved/warped planes**: subtle vertex bend (unseen's floating paper
|
|
176
|
-
sheets) — displace z by a small curve of UV.x + scroll velocity.
|
|
177
|
-
|
|
178
|
-
Rules: ONE media-plane system per page owning all planes (one scene, one rAF —
|
|
179
|
-
never a canvas per image); planes pause syncing when off-screen; the DOM
|
|
180
|
-
element remains the interaction target (click/focus/hover listeners on the DOM,
|
|
181
|
-
effects on the plane); reduced-motion and WebGL-failure both fall back to
|
|
182
|
-
simply un-hiding the DOM media (set `opacity: 1`) — this fallback must be
|
|
183
|
-
wired, not theoretical, and it's the first thing runtime verification checks.
|
|
184
|
-
|
|
185
|
-
## 4. Choosing the treatment (the reasoning frame)
|
|
186
|
-
|
|
187
|
-
Per media element, walk this in one line each — it's the media ledger the plan
|
|
188
|
-
blueprint (PLAN.md §2) captures:
|
|
189
|
-
|
|
190
|
-
1. **Role**: hero atmosphere / product evidence / work-card / texture / story
|
|
191
|
-
beat? Evidence media (screenshots, product photos) gets QUIET treatments —
|
|
192
|
-
curtain reveal, ken-burns; atmosphere media can take the loud/invented ones.
|
|
193
|
-
2. **Tier**: does the page already pay for WebGL? If yes, media planes (§3);
|
|
194
|
-
if no, a DOM treatment (§2) or the DOM construction of a §2.5 invention —
|
|
195
|
-
never add a canvas only to distort one image.
|
|
196
|
-
3. **Entrance / idle / response** per §0, matched to register and dial.
|
|
197
|
-
4. **Failure path**: poster/static version named (reduced-motion, load
|
|
198
|
-
failure, mobile tier).
|
|
199
|
-
|
|
200
|
-
## 5. Floors (every treatment, non-negotiable)
|
|
201
|
-
|
|
202
|
-
- `prefers-reduced-motion`: poster frame / static image, no autoplaying loops,
|
|
203
|
-
no scrub (static end-state). Test by toggling it.
|
|
204
|
-
- Videos: `muted autoplay loop playsinline preload="metadata"` + `poster`;
|
|
205
|
-
pause when off-screen (IntersectionObserver) and on `document.hidden`; no
|
|
206
|
-
audio tracks ever on ambient loops.
|
|
207
|
-
- Loading: explicit `width/height` or `aspect-ratio` on every media box (zero
|
|
208
|
-
CLS); LCP image/poster preloaded, everything below the fold lazy; a media box
|
|
209
|
-
is never blank — poster, dominant-color fill, or blur-up while loading.
|
|
210
|
-
- Hover treatments have focus equivalents; touch gets the tap/visible-default
|
|
211
|
-
story (DESIGN.md §13); media planes and canvases are `pointer-events-none`
|
|
212
|
-
unless they ARE the control.
|
|
213
|
-
- Budgets: one video loop playing per view, ≤ 2-4MB per loop, sequences ≤
|
|
214
|
-
~6MB total, `dpr` capped on media-plane canvases (3d.md §7).
|
|
215
|
-
- Alt text carries voice on images; videos that convey content (not
|
|
216
|
-
atmosphere) get a text alternative nearby.
|
|
1
|
+
# Dreative Specialist Skill — Media as Motion Material
|
|
2
|
+
|
|
3
|
+
Load this file when `plan.skills` includes `media`, when the plan's blueprint
|
|
4
|
+
contains any `generate-*` media cell, or when the brief involves imagery/video
|
|
5
|
+
on a page with motion dial ≥ 6. It EXTENDS DESIGN.md §7 (sourcing priority and
|
|
6
|
+
bans still apply) and STACKS with motion.md (timing), 3d.md (shader craft), and
|
|
7
|
+
cinematic.md (the living surface). This file exists because agents know how to
|
|
8
|
+
*embed* media but not how to *use* it: award-grade sites (unseen.co family)
|
|
9
|
+
treat images and video as the raw material the motion system acts on — media is
|
|
10
|
+
choreographed, distorted, revealed, and lit, never just placed.
|
|
11
|
+
|
|
12
|
+
## 0. The doctrine
|
|
13
|
+
|
|
14
|
+
- **No bare media at dial ≥ 7.** Every meaningful image/video gets three
|
|
15
|
+
decisions: an **entrance** (how it arrives — reveal, wipe, materialize), an
|
|
16
|
+
**idle** (what it does at rest — loop, drift, ken-burns, nothing-on-purpose),
|
|
17
|
+
and a **response** (what interaction does to it — hover wake, distortion,
|
|
18
|
+
parallax). "None" is a valid answer per axis, but it must be chosen, not
|
|
19
|
+
defaulted.
|
|
20
|
+
- **Media and type arrive as one beat.** Time the media entrance with the
|
|
21
|
+
section's line-mask type reveal (motion.md §4) — image and headline landing
|
|
22
|
+
together reads as choreography; landing separately reads as two plugins.
|
|
23
|
+
- **One treatment vocabulary per page.** Pick 1-2 media treatments and stamp
|
|
24
|
+
them consistently (all work cards hover-wake; all section images curtain-
|
|
25
|
+
reveal). Five different reveal styles = assembled, not designed.
|
|
26
|
+
- **Invent, don't pick.** §2/§3 are springboards, not a menu — the signature
|
|
27
|
+
media treatment should be COMPOSED for this brand and this prompt using the
|
|
28
|
+
grammar in §2.5 (a torn-paper archive scrolls differently than a liquid
|
|
29
|
+
fashion film). Stock-vocabulary media reads as template exactly like stock
|
|
30
|
+
layouts do; if the user's prompt describes an effect ("images tear apart on
|
|
31
|
+
scroll"), build THAT effect for real, at the tier it needs.
|
|
32
|
+
- **Real assets outrank generated ones** (DESIGN.md §7). Generated media fills
|
|
33
|
+
gaps and creates atmosphere; it never replaces the client's product shots.
|
|
34
|
+
|
|
35
|
+
## 1. Production pipeline (generate → grade → compress)
|
|
36
|
+
|
|
37
|
+
When the plan calls for generated media, produce it BEFORE section code
|
|
38
|
+
(PLAN.md §4) and produce it correctly:
|
|
39
|
+
|
|
40
|
+
- **Prompt for the world, grade for the page.** Prompt the brand's physical
|
|
41
|
+
subject (DESIGN.md §7) PLUS the page's light: temperature ("warm tungsten
|
|
42
|
+
side-light", "cool overcast daylight"), palette anchors ("deep green shadows,
|
|
43
|
+
bone highlights"), and grain/mood. Every asset on a page shares ONE lighting
|
|
44
|
+
logic — mismatched light is the #1 generated-media tell.
|
|
45
|
+
- **Exact aspect ratios** from the blueprint (16:9 hero, 4:5 cards, 1:1
|
|
46
|
+
thumbnails, 21:9 banners). Never generate square and crop-hope.
|
|
47
|
+
- **Video loops**: 5-10s, prompt explicitly for seamlessness ("seamless loop,
|
|
48
|
+
continuous motion, no scene change") and slow motion content (drift, steam,
|
|
49
|
+
fabric, water — fast action never loops cleanly). Generate or extract a
|
|
50
|
+
**poster frame** for every video (first frame, same grade).
|
|
51
|
+
- **Image sequences** for scroll scrubs: 40-80 frames of one continuous
|
|
52
|
+
transformation (assemble/rotate/morph). Image-to-video tools can produce
|
|
53
|
+
these from a single generated still; export frames with ffmpeg
|
|
54
|
+
(`ffmpeg -i loop.mp4 -vf fps=12,scale=1280:-1 frames/f_%03d.webp`).
|
|
55
|
+
- **Compress before committing**: images → WebP/AVIF at the largest displayed
|
|
56
|
+
size ×2 max; video → H.264 + AV1 sources, CRF ~28-32, no audio track, ≤ 2-4MB
|
|
57
|
+
per loop (`ffmpeg -i in.mp4 -an -c:v libx264 -crf 30 -movflags +faststart`).
|
|
58
|
+
A 40MB hero loop fails the plan even if it's beautiful.
|
|
59
|
+
- Textures too: grain tiles, masks, mattes, displacement maps — generate them
|
|
60
|
+
instead of hand-rolling SVG (which is banned, DESIGN.md §7).
|
|
61
|
+
|
|
62
|
+
## 2. DOM-tier treatments (no WebGL — the budget vocabulary)
|
|
63
|
+
|
|
64
|
+
80% of the effect at 5% of the cost; the right tier below dial 8 or without a
|
|
65
|
+
canvas already on the page. All honor the floors in §5.
|
|
66
|
+
|
|
67
|
+
- **Curtain / inset reveal**: media enters behind a wipe —
|
|
68
|
+
`clip-path: inset(100% 0 0 0) → inset(0)` (or 2-4 panel slides), 900ms
|
|
69
|
+
expo-out, triggered in-view once, synced to the headline's line-mask.
|
|
70
|
+
- **Hover-woken loop**: still poster crossfades to its video loop on
|
|
71
|
+
hover/focus (240ms), `video.play()` on enter, pause + reset to poster on
|
|
72
|
+
leave. The "living thumbnail" for work/product cards. Preload `metadata`
|
|
73
|
+
only; play() only after the crossfade starts.
|
|
74
|
+
- **Mask-shaped video**: the loop plays inside display type
|
|
75
|
+
(`background-clip: text` on 10vw+ headlines), an arch/circle `clip-path`, or
|
|
76
|
+
the brand mark (SVG mask). Video becomes identity, not a rectangle. One per
|
|
77
|
+
page.
|
|
78
|
+
- **Floating media**: 3-5 images hovering in depth — slow damped drift
|
|
79
|
+
(±6-10px, 4-8s loops, each phase-offset), parallax differential by depth
|
|
80
|
+
layer, soft tinted contact shadow. The "paper sheets in space" look, pure CSS
|
|
81
|
+
+ one IntersectionObserver.
|
|
82
|
+
- **Ken-burns**: slow scale 1.0→1.06 over 12-20s inside a fixed frame,
|
|
83
|
+
alternate direction per instance. The refined register's entire motion budget
|
|
84
|
+
for imagery (refined.md).
|
|
85
|
+
- **Pixel/dither swap**: stepped `image-rendering: pixelated` downscale swap
|
|
86
|
+
(24px mosaic → full res in 4-6 steps) on scroll progress or hover. Digital-
|
|
87
|
+
craft registers.
|
|
88
|
+
- **Inner-zoom parallax**: image at 115% height inside `overflow-hidden` frame,
|
|
89
|
+
`object-position` or translateY driven by scroll (-8%→8%). Media moves, frame
|
|
90
|
+
doesn't — never parallax the frame itself past text.
|
|
91
|
+
- **Scroll-scrubbed `<canvas>` sequence**: preload frames (§1), draw the frame
|
|
92
|
+
for the current damped scroll progress; sticky wrapper ≤ 2.5 viewports
|
|
93
|
+
(motion.md §7's scrub showcase). No WebGL needed.
|
|
94
|
+
|
|
95
|
+
## 2.5 The invention grammar (compose the signature treatment)
|
|
96
|
+
|
|
97
|
+
Every media effect — including any the user describes in their own words — is
|
|
98
|
+
three choices multiplied together. Compose deliberately:
|
|
99
|
+
|
|
100
|
+
- **PROPERTY** (what changes): position/scale · opacity · clip/mask SHAPE
|
|
101
|
+
(inset, circle, arch, brand mark, jagged polygon) · slices/fragments (the
|
|
102
|
+
media cut into strips, tiles, or shards that move independently) · UV
|
|
103
|
+
distortion (WebGL: ripple, stretch, melt, swirl) · resolution (mosaic →
|
|
104
|
+
sharp) · color channels (RGB split, duotone → full color) · blend/exposure
|
|
105
|
+
(media develops like a photo print).
|
|
106
|
+
- **DRIVER** (what pushes it): scroll progress (scrubbed) · scroll VELOCITY
|
|
107
|
+
(agitation that decays) · in-view trigger (one-shot) · hover/focus ·
|
|
108
|
+
cursor position within the element (directional!) · drag · hold · time.
|
|
109
|
+
- **SHAPE OF PROGRESSION** (how it travels across the media): uniform ·
|
|
110
|
+
directional sweep (left→right, top→bottom) · radial from a point (often the
|
|
111
|
+
cursor's entry point) · per-slice stagger · noise-mask (organic, torn) ·
|
|
112
|
+
along the brand mark's silhouette.
|
|
113
|
+
|
|
114
|
+
The user's prompt usually fixes one or two axes; you compose the rest from the
|
|
115
|
+
brand's world. "Tearing" = slices + jagged noise-mask edges, driven by scroll.
|
|
116
|
+
"Video fades from left to right on hover" = opacity/mask, hover-driven,
|
|
117
|
+
directional sweep — a gradient `mask-image` whose position animates, 400ms,
|
|
118
|
+
from the edge the cursor entered. Name the composed treatment in the plan
|
|
119
|
+
blueprint like a signature element, and stamp it consistently (§0).
|
|
120
|
+
|
|
121
|
+
**Worked exotics (copy the construction, not the skin):**
|
|
122
|
+
|
|
123
|
+
- **Paper tear on scroll**: image duplicated into 2-3 layers, each clipped by
|
|
124
|
+
a jagged `clip-path` polygon sharing torn edges; scroll progress translates/
|
|
125
|
+
rotates the pieces apart (±2-6°) with a hairline of background showing
|
|
126
|
+
through; WebGL version displaces UV along a noise seam. Archive/editorial/
|
|
127
|
+
punk registers.
|
|
128
|
+
- **Strip-slice reveal**: media as 5-9 vertical strips (repeated
|
|
129
|
+
`background-image` with offset `background-position`, or plane-per-strip);
|
|
130
|
+
strips slide in staggered from alternating directions, or shear on scroll
|
|
131
|
+
velocity. The classic award-site gallery entrance.
|
|
132
|
+
- **Directional hover wipe**: detect the pointer's entry edge (compare
|
|
133
|
+
enter coordinates to bounds); the reveal (opacity mask, color→duotone,
|
|
134
|
+
still→video crossfade) sweeps FROM that edge. Feels alive because it
|
|
135
|
+
answers the gesture's direction.
|
|
136
|
+
- **Cursor-torch reveal**: media sits dimmed/blurred/halftoned; a radial mask
|
|
137
|
+
tracking the (damped) cursor reveals it sharp and graded — the flashlight
|
|
138
|
+
over an archive. Pair with a "drag to explore" label.
|
|
139
|
+
- **Melt/liquid exit**: on section leave or route change, UV y-displacement
|
|
140
|
+
grows by a noise column pattern — the image drips out of frame (WebGL), or
|
|
141
|
+
budget version: per-strip translateY with eased random offsets.
|
|
142
|
+
- **Shatter/scatter**: media as an instanced tile grid (WebGL) that explodes
|
|
143
|
+
along scroll velocity and reassembles at rest — the §3 plane system with a
|
|
144
|
+
per-instance offset uniform; cap tiles ≤ 400.
|
|
145
|
+
- **Print develop**: media enters as paper-white → exposure/contrast/duotone
|
|
146
|
+
ramps to full grade (CSS `filter` keyframes or a LUT shader), timed with
|
|
147
|
+
the headline reveal. Photography/portfolio registers.
|
|
148
|
+
|
|
149
|
+
Discipline stays the law: the composed treatment must still clear §5's floors,
|
|
150
|
+
DESIGN.md §6's "one sentence of communication value", and one-signature-
|
|
151
|
+
per-page — an inventive effect stamped on every image is as loud as a marquee
|
|
152
|
+
on every section.
|
|
153
|
+
|
|
154
|
+
## 3. WebGL tier — the media plane (the unseen.co mechanic)
|
|
155
|
+
|
|
156
|
+
When dial ≥ 8 or cinematic/immersive is active, media renders THROUGH the
|
|
157
|
+
canvas so shaders can touch it. The core pattern, in order:
|
|
158
|
+
|
|
159
|
+
1. **Sync planes to DOM rects.** Real `<img>`/`<video>` elements stay in the
|
|
160
|
+
document (a11y, SEO, layout, fallback) but render invisible
|
|
161
|
+
(`opacity: 0`, NOT `display:none` — layout must persist). For each, a
|
|
162
|
+
textured plane in an orthographic/fitted scene copies its
|
|
163
|
+
`getBoundingClientRect()` every scroll/resize (rAF-batched; lerp the
|
|
164
|
+
position for the floaty feel). Texture from `TextureLoader` or
|
|
165
|
+
`new THREE.VideoTexture(videoEl)` (video must be `muted playsinline` and
|
|
166
|
+
playing; `texture.colorSpace = SRGBColorSpace`).
|
|
167
|
+
2. **Distortion in the fragment/vertex shader**, uniforms driven by input:
|
|
168
|
+
- *Hover ripple/lens*: damped `uMouse` + `uHoverStrength` 0→1 spring; UV
|
|
169
|
+
displacement by radial falloff or noise.
|
|
170
|
+
- *Velocity stretch / RGB split*: scroll or drag velocity (from Lenis /
|
|
171
|
+
`useScroll`) → vertex bend + per-channel UV offset, hard-clamped, damped
|
|
172
|
+
decay to zero (cinematic.md §2). Peak effect at a fast flick stays legible.
|
|
173
|
+
- *Transition dissolve*: two textures + noise mask `mix()` for gallery/
|
|
174
|
+
route image swaps (3d.md §4).
|
|
175
|
+
3. **Curved/warped planes**: subtle vertex bend (unseen's floating paper
|
|
176
|
+
sheets) — displace z by a small curve of UV.x + scroll velocity.
|
|
177
|
+
|
|
178
|
+
Rules: ONE media-plane system per page owning all planes (one scene, one rAF —
|
|
179
|
+
never a canvas per image); planes pause syncing when off-screen; the DOM
|
|
180
|
+
element remains the interaction target (click/focus/hover listeners on the DOM,
|
|
181
|
+
effects on the plane); reduced-motion and WebGL-failure both fall back to
|
|
182
|
+
simply un-hiding the DOM media (set `opacity: 1`) — this fallback must be
|
|
183
|
+
wired, not theoretical, and it's the first thing runtime verification checks.
|
|
184
|
+
|
|
185
|
+
## 4. Choosing the treatment (the reasoning frame)
|
|
186
|
+
|
|
187
|
+
Per media element, walk this in one line each — it's the media ledger the plan
|
|
188
|
+
blueprint (PLAN.md §2) captures:
|
|
189
|
+
|
|
190
|
+
1. **Role**: hero atmosphere / product evidence / work-card / texture / story
|
|
191
|
+
beat? Evidence media (screenshots, product photos) gets QUIET treatments —
|
|
192
|
+
curtain reveal, ken-burns; atmosphere media can take the loud/invented ones.
|
|
193
|
+
2. **Tier**: does the page already pay for WebGL? If yes, media planes (§3);
|
|
194
|
+
if no, a DOM treatment (§2) or the DOM construction of a §2.5 invention —
|
|
195
|
+
never add a canvas only to distort one image.
|
|
196
|
+
3. **Entrance / idle / response** per §0, matched to register and dial.
|
|
197
|
+
4. **Failure path**: poster/static version named (reduced-motion, load
|
|
198
|
+
failure, mobile tier).
|
|
199
|
+
|
|
200
|
+
## 5. Floors (every treatment, non-negotiable)
|
|
201
|
+
|
|
202
|
+
- `prefers-reduced-motion`: poster frame / static image, no autoplaying loops,
|
|
203
|
+
no scrub (static end-state). Test by toggling it.
|
|
204
|
+
- Videos: `muted autoplay loop playsinline preload="metadata"` + `poster`;
|
|
205
|
+
pause when off-screen (IntersectionObserver) and on `document.hidden`; no
|
|
206
|
+
audio tracks ever on ambient loops.
|
|
207
|
+
- Loading: explicit `width/height` or `aspect-ratio` on every media box (zero
|
|
208
|
+
CLS); LCP image/poster preloaded, everything below the fold lazy; a media box
|
|
209
|
+
is never blank — poster, dominant-color fill, or blur-up while loading.
|
|
210
|
+
- Hover treatments have focus equivalents; touch gets the tap/visible-default
|
|
211
|
+
story (DESIGN.md §13); media planes and canvases are `pointer-events-none`
|
|
212
|
+
unless they ARE the control.
|
|
213
|
+
- Budgets: one video loop playing per view, ≤ 2-4MB per loop, sequences ≤
|
|
214
|
+
~6MB total, `dpr` capped on media-plane canvases (3d.md §7).
|
|
215
|
+
- Alt text carries voice on images; videos that convey content (not
|
|
216
|
+
atmosphere) get a text alternative nearby.
|