@struq/skill 0.5.1 → 0.5.3

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.
Files changed (65) hide show
  1. package/README.md +137 -100
  2. package/package.json +5 -3
  3. package/skills/struq/SKILL.md +168 -165
  4. package/skills/struq/blocks/CATALOG.md +49 -46
  5. package/skills/struq/blocks/backgrounds/background-aurora.tsx +2 -1
  6. package/skills/struq/blocks/backgrounds/background-facets.tsx +5 -3
  7. package/skills/struq/blocks/backgrounds/background-silk.tsx +6 -2
  8. package/skills/struq/blocks/catalog.json +50 -5
  9. package/skills/struq/blocks/film.json +11 -7
  10. package/skills/struq/blocks/footers/footer-contact.tsx +8 -78
  11. package/skills/struq/blocks/headers/header-bar.tsx +144 -29
  12. package/skills/struq/blocks/headers/menu-curtain.tsx +36 -19
  13. package/skills/struq/blocks/heroes/hero-poster.tsx +36 -10
  14. package/skills/struq/blocks/kit/HeroCanvas.tsx +6 -2
  15. package/skills/struq/blocks/kit/SplitHeadline.tsx +2 -1
  16. package/skills/struq/blocks/kit/accent.ts +29 -3
  17. package/skills/struq/blocks/kit/blocks.css +530 -6
  18. package/skills/struq/blocks/kit/feel.ts +183 -0
  19. package/skills/struq/blocks/kit/gsap.ts +9 -6
  20. package/skills/struq/blocks/kit/middle/PlaceHours.tsx +254 -0
  21. package/skills/struq/blocks/kit/middle/ProcessStrip.tsx +428 -0
  22. package/skills/struq/blocks/kit/middle/ServicesList.tsx +496 -0
  23. package/skills/struq/blocks/kit/middle/entrance.ts +98 -0
  24. package/skills/struq/blocks/kit/middle/hours.ts +154 -0
  25. package/skills/struq/blocks/kit/middle/index.ts +14 -0
  26. package/skills/struq/blocks/kit/motion/HoverLink.tsx +33 -0
  27. package/skills/struq/blocks/kit/motion/ImageCurtain.tsx +79 -0
  28. package/skills/struq/blocks/kit/motion/MaskWipe.tsx +91 -0
  29. package/skills/struq/blocks/kit/motion/Pressable.tsx +58 -0
  30. package/skills/struq/blocks/kit/motion/RevealText.tsx +103 -0
  31. package/skills/struq/blocks/kit/motion/Rise.tsx +77 -0
  32. package/skills/struq/blocks/kit/motion/ScrubLine.tsx +108 -0
  33. package/skills/struq/blocks/kit/motion/index.ts +11 -0
  34. package/skills/struq/blocks/kit/quiet/Close.tsx +178 -52
  35. package/skills/struq/blocks/kit/quiet/Statement.tsx +3 -2
  36. package/skills/struq/blocks/kit/subject/AppScreen.tsx +388 -0
  37. package/skills/struq/blocks/kit/subject/Document.tsx +742 -0
  38. package/skills/struq/blocks/kit/subject/Mark.tsx +44 -0
  39. package/skills/struq/blocks/kit/subject/PatternPaper.tsx +410 -0
  40. package/skills/struq/blocks/kit/subject/SectionDrawing.tsx +349 -0
  41. package/skills/struq/blocks/kit/subject/Ticket.tsx +354 -0
  42. package/skills/struq/blocks/kit/subject/build.ts +66 -0
  43. package/skills/struq/blocks/kit/subject/draw.ts +196 -0
  44. package/skills/struq/blocks/kit/subject/drawings.ts +373 -0
  45. package/skills/struq/blocks/kit/subject/format.ts +122 -0
  46. package/skills/struq/blocks/kit/subject/index.ts +11 -0
  47. package/skills/struq/blocks/kit/subject/patterns.ts +204 -0
  48. package/skills/struq/blocks/preloaders/preloader-stack.tsx +75 -22
  49. package/skills/struq/blocks/showpieces/hero-opener.tsx +55 -7
  50. package/skills/struq/blocks/showpieces/image-to-fullbleed.tsx +64 -6
  51. package/skills/struq/blocks/showpieces/manifesto-scrub.tsx +56 -3
  52. package/skills/struq/blocks/showpieces/panel-wipe.tsx +93 -11
  53. package/skills/struq/blocks/showpieces/wordmark-finale.tsx +38 -5
  54. package/skills/struq/canon/canon.json +1 -1
  55. package/skills/struq/references/art-direction.md +51 -0
  56. package/skills/struq/scripts/blocks.mjs +56 -20
  57. package/skills/struq/scripts/canon.mjs +36 -7
  58. package/skills/struq/scripts/check.mjs +417 -11
  59. package/skills/struq/scripts/draw.mjs +49 -0
  60. package/skills/struq/scripts/film-check.mjs +28 -4
  61. package/skills/struq/scripts/gate.mjs +13 -3
  62. package/skills/struq/scripts/hand.mjs +222 -0
  63. package/skills/struq/scripts/images.mjs +12 -3
  64. package/skills/struq/scripts/look.mjs +1184 -0
  65. package/skills/struq/scripts/stamp.mjs +47 -0
@@ -1,6 +1,6 @@
1
1
  # Block catalogue
2
2
 
3
- Generated by scripts/release-blocks.mjs from Struq origin/main at a538491. Do not edit: run the release script again.
3
+ Generated by scripts/release-blocks.mjs from Struq origin/main at f98bd198. Do not edit: run the release script again.
4
4
  44 admitted blocks. Install one with `node <skill-dir>/scripts/blocks.mjs add <slug>`; read its file for the props.
5
5
  Every block works light and dark; a variant is a different composition of the same idea, passed as `variant`.
6
6
 
@@ -17,15 +17,15 @@ Variants (`variant`, the first is the default):
17
17
  - `settle`: The cover lifts while the name shrinks and travels into the header's wordmark, which takes over in the same frame.
18
18
 
19
19
  Exports: `PreloaderWordmark`. Packages: @gsap/react, gsap.
20
- Files: `kit/blocks.css`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`, `preloaders/preloader-wordmark.tsx`.
20
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`, `preloaders/preloader-wordmark.tsx`.
21
21
 
22
22
  ### preloader-stack
23
23
  film: role frame · home weight · motif frame · energy 2 · pins 0 · counter
24
24
 
25
- Preloader: the stack. The first paint is the page's ground with the client's name, a quiet count and the first print in a small portrait frame; five or six prints cut inside that frame, each held shorter than the last, ending on the hero's own photo, and the frame then grows to the hero image's exact place and crop (the page marks it data-stack-target) so the cover becomes the hero with no seam, within 2.4 seconds of the first paint, once per session.
25
+ Preloader: the stack. The first paint is the page's ground with the client's name, a quiet count and the first print in a small portrait frame; five or six prints cut inside that frame, each held shorter than the last, ending on the hero's own photo, and the frame then grows to the hero image's exact place and crop (the page marks it data-stack-target) so the cover becomes the hero with no seam, within 2.4 seconds of the first paint, once per session. Before an opening with no photo (opening="photoless", or no hero) it flips palette panels with the name's first letter instead and lands on the opening's own ground.
26
26
 
27
27
  Exports: `PreloaderStack`. Packages: @gsap/react, gsap.
28
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `preloaders/preloader-slices-uncovered.ts`, `preloaders/preloader-stack.tsx`.
28
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `preloaders/preloader-slices-uncovered.ts`, `preloaders/preloader-stack.tsx`.
29
29
 
30
30
  ### preloader-slices
31
31
  film: role frame · home cut · motif cut · energy 2 · pins 0 · counter
@@ -33,7 +33,7 @@ film: role frame · home cut · motif cut · energy 2 · pins 0 · counter
33
33
  Preloader: the slices. The first paint is a dark cover cut into four vertical slices (three on phones), already composed: the client's name large, a caption, a hairline and the count at 000; the count runs to 100 in one move, then the slices drop away left to right, each carrying its strip of the name and count down and off behind a 5px accent edge, uncovering the page from the top onto its own entrance, within 2.4 seconds of the first paint, once per session.
34
34
 
35
35
  Exports: `PreloaderSlices`. Packages: @gsap/react, gsap.
36
- Files: `kit/blocks.css`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`, `preloaders/preloader-slices.tsx`.
36
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`, `preloaders/preloader-slices.tsx`.
37
37
 
38
38
  ### preloader-gate
39
39
  film: role frame · home curtain · motif aperture · energy 2 · pins 0 · counter
@@ -41,7 +41,7 @@ film: role frame · home curtain · motif aperture · energy 2 · pins 0 · coun
41
41
  Preloader: the gate. The first paint is a shut gate with a hairline ring on its middle line; an accent arc fills the ring on an eased count that waits for the fonts and the hero image (cutting through the client's own marks, one per beat, when given), then the line through the middle lights and the two bars open top and bottom onto the hero, by 2.4 seconds from the first paint, once per session (helper: preloaders/preloader-slices-uncovered.ts).
42
42
 
43
43
  Exports: `PreloaderGate`. Packages: @gsap/react, gsap.
44
- Files: `kit/blocks.css`, `kit/gsap.ts`, `preloaders/preloader-gate.tsx`, `preloaders/preloader-slices-uncovered.ts`.
44
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `preloaders/preloader-gate.tsx`, `preloaders/preloader-slices-uncovered.ts`.
45
45
 
46
46
  ## Page transitions
47
47
 
@@ -51,7 +51,7 @@ film: role frame · home weight · motif frame · energy 2 · pins 0 · none
51
51
  Page transition: the stack. On every link click and on back and forward, a small portrait print of the destination's own hero photo appears where the pointer is (centred for keys and history) and grows to fill the screen while the route loads under it, then settles into the new page's hero at its exact place and crop, so arriving is the preloader's own landing, under 0.9 seconds door to door; a print not decoded in time becomes the destination's name on the page ground and the cover lifts away instead (helper: preloaders/preloader-slices-uncovered.ts).
52
52
 
53
53
  Exports: `PageTransitionStack`. Packages: @gsap/react, gsap, lenis.
54
- Files: `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/gsap.ts`, `page-transitions/page-transition-stack.tsx`, `preloaders/preloader-slices-uncovered.ts`.
54
+ Files: `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `page-transitions/page-transition-stack.tsx`, `preloaders/preloader-slices-uncovered.ts`.
55
55
 
56
56
  ### page-transition-slices
57
57
  film: role frame · home cut · motif cut · energy 2 · pins 0 · none
@@ -59,7 +59,7 @@ film: role frame · home cut · motif cut · energy 2 · pins 0 · none
59
59
  Page transition: the slices. On every link click and on back and forward, the slices of preloader-slices come in from above and close over the page with the destination's name and a running hairline, the route loads under them, and they carry on down and off, uncovering the new page from the top onto its entrance, about 0.65 seconds door to door, with focus, hashes and scroll restored (helper: preloaders/preloader-slices-uncovered.ts).
60
60
 
61
61
  Exports: `PageTransitionSlices`. Packages: @gsap/react, gsap, lenis.
62
- Files: `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/gsap.ts`, `page-transitions/page-transition-slices.tsx`, `preloaders/preloader-slices-uncovered.ts`.
62
+ Files: `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `page-transitions/page-transition-slices.tsx`, `preloaders/preloader-slices-uncovered.ts`.
63
63
 
64
64
  ### page-transition-gate
65
65
  film: role frame · home curtain · motif aperture · energy 2 · pins 0 · none
@@ -67,7 +67,7 @@ film: role frame · home curtain · motif aperture · energy 2 · pins 0 · none
67
67
  Page transition: the gate. On every navigation, back button included, the preloader's bars close carrying the two halves of a frame (a hairline ring and the destination's name), lock into one as the line and the ring light, hold while the route changes, then split the name and open onto the finished page, 0.9 seconds door to door (helper: preloaders/preloader-slices-uncovered.ts).
68
68
 
69
69
  Exports: `GateLink`, `GateStage`, `PageTransitionGate`. Packages: @gsap/react, gsap, lenis.
70
- Files: `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/gsap.ts`, `page-transitions/page-transition-gate.tsx`, `preloaders/preloader-slices-uncovered.ts`.
70
+ Files: `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `page-transitions/page-transition-gate.tsx`, `preloaders/preloader-slices-uncovered.ts`.
71
71
 
72
72
  ## Headers
73
73
 
@@ -83,7 +83,7 @@ Variants (`variant`, the first is the default):
83
83
  - `split`: Wordmark left, links centred with a line gliding under the hovered one, the studio's place (its live time only with clock) and the action right, and a thin rule filling with the page's progress.
84
84
 
85
85
  Exports: `HeaderBar`. Packages: @gsap/react, gsap.
86
- Files: `headers/header-bar.tsx`, `kit/blocks.css`, `kit/gsap.ts`.
86
+ Files: `headers/header-bar.tsx`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/photo-read.ts`.
87
87
 
88
88
  ### menu-curtain
89
89
  film: role frame · home curtain · motif aperture · energy 1 · pins 0 · clock, hover · clock by prop clock
@@ -96,7 +96,7 @@ Variants (`variant`, the first is the default):
96
96
  - `stack`: Three panels grow one after another from the button; a small portrait frame flips through a few prints, then cuts to the hovered link's photo.
97
97
 
98
98
  Exports: `MenuCurtain`. Packages: @gsap/react, gsap, lenis.
99
- Files: `headers/menu-curtain.tsx`, `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`.
99
+ Files: `headers/menu-curtain.tsx`, `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`.
100
100
 
101
101
  ## Heroes
102
102
 
@@ -111,7 +111,7 @@ Variants (`variant`, the first is the default):
111
111
  - `passe`: A print that nearly fills the screen inside a thin mat; the first scroll steps back to a small portrait at the left with the line on the wall beside it.
112
112
 
113
113
  Exports: `HeroFramed`. Packages: @gsap/react, gsap.
114
- Files: `heroes/hero-framed.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
114
+ Files: `heroes/hero-framed.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
115
115
 
116
116
  ### hero-split
117
117
  film: role opening · home none · motif cut · energy 1 · pins 0 · none
@@ -125,7 +125,7 @@ Variants (`variant`, the first is the default):
125
125
  - `opening`: At rest the ground fills the screen and the photo is a strip at the edge; the first scroll opens it to the split while the headline turns to the photo ink as the edge passes.
126
126
 
127
127
  Exports: `HeroSplit`. Packages: @gsap/react, gsap.
128
- Files: `heroes/hero-split.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
128
+ Files: `heroes/hero-split.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
129
129
 
130
130
  ### hero-index
131
131
  film: role opening · home none · motif neutral · energy 1 · pins 0 · hover
@@ -139,7 +139,7 @@ Variants (`variant`, the first is the default):
139
139
  - `doorlopen`: The list centred over the photograph while the hero holds; each stretch of the first scroll raises the next project and steps its name forward.
140
140
 
141
141
  Exports: `HeroIndex`. Packages: @gsap/react, gsap.
142
- Files: `heroes/hero-index.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
142
+ Files: `heroes/hero-index.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
143
143
 
144
144
  ### hero-still
145
145
  film: role opening · home none · motif neutral · energy 1 · pins 0 · clock · clock by prop clock
@@ -153,7 +153,7 @@ Variants (`variant`, the first is the default):
153
153
  - `horizon`: The headline split at the photo's horizon, each half in the ink its side measures for, the halves closing on the horizon.
154
154
 
155
155
  Exports: `HeroStill`. Packages: @gsap/react, gsap.
156
- Files: `heroes/hero-still.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
156
+ Files: `heroes/hero-still.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
157
157
 
158
158
  ### hero-poster
159
159
  film: role opening · home none · motif aperture · energy 3 · pins 1.5 · none
@@ -166,7 +166,7 @@ Variants (`variant`, the first is the default):
166
166
  - `stack`: One word per row with a window of a different crop between each pair; on scroll the rows part and the crops slide into one photograph.
167
167
 
168
168
  Exports: `HeroPoster`. Packages: @gsap/react, gsap.
169
- Files: `heroes/hero-poster.tsx`, `heroes/hero-still.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
169
+ Files: `heroes/hero-poster.tsx`, `heroes/hero-still.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `preloaders/preloader-slices-uncovered.ts`.
170
170
 
171
171
  ## Backgrounds
172
172
 
@@ -181,7 +181,7 @@ Variants (`variant`, the first is the default):
181
181
  - `drift`: Curtains across the upper half, drifting slowly sideways and bending away from the pointer.
182
182
 
183
183
  Exports: `BackgroundAurora`. Packages: @gsap/react, gsap.
184
- Files: `backgrounds/background-aurora.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`.
184
+ Files: `backgrounds/background-aurora.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`.
185
185
 
186
186
  ### background-silk
187
187
  film: role opening · home none · motif field · energy 2 · pins 0 · cursor
@@ -194,7 +194,7 @@ Variants (`variant`, the first is the default):
194
194
  - `drape`: The cloth hangs from the top edge in rounded pleats down to a wavy hem; scrolling the hero away draws the hem down and stretches the pleats.
195
195
 
196
196
  Exports: `BackgroundSilk`. Packages: @gsap/react, gsap.
197
- Files: `backgrounds/background-silk.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`.
197
+ Files: `backgrounds/background-silk.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`.
198
198
 
199
199
  ### background-facets
200
200
  film: role opening · home none · motif field · energy 2 · pins 0 · none
@@ -207,17 +207,17 @@ Variants (`variant`, the first is the default):
207
207
  - `turn`: Diagonal pleats in the upper left cut into planes; the light turns across them as the hero scrolls away and leans toward the pointer.
208
208
 
209
209
  Exports: `BackgroundFacets`. Packages: @gsap/react, gsap.
210
- Files: `backgrounds/background-facets.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`.
210
+ Files: `backgrounds/background-facets.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `preloaders/preloader-slices-uncovered.ts`.
211
211
 
212
212
  ## Showpieces
213
213
 
214
214
  ### hero-opener
215
215
  film: role opening · home none · motif word · energy 2 · pins 1 · magnetic
216
216
 
217
- Hero opener. A full-bleed photo (or the WebGL scene over it) with the display line at 14 to 20vw across it; on scroll it pins, scales down and darkens while the next section slides over.
217
+ Hero opener. A full-bleed photo (or the WebGL scene over it) with the display line at 14 to 20vw across it; on scroll it pins, scales down and darkens while the next section slides over. Without a photo it is type on the inverse ground over the builder's own motif (`backdrop`, an SVG or small canvas from the site's world) or a stock field (`scene`: "dots", "contours" or "none"); the dots default is a fallback, not a choice.
218
218
 
219
219
  Exports: `HeroOpener`. Packages: @gsap/react, @types/three, gsap, three.
220
- Files: `kit/HeroCanvas.tsx`, `kit/MagneticButton.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/scenes/contours.ts`, `kit/scenes/dots.ts`, `kit/scenes/ripple.ts`, `kit/scenes/types.ts`, `preloaders/preloader-slices-uncovered.ts`, `showpieces/hero-opener.tsx`.
220
+ Files: `kit/HeroCanvas.tsx`, `kit/MagneticButton.tsx`, `kit/accent.ts`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/scenes/contours.ts`, `kit/scenes/dots.ts`, `kit/scenes/ripple.ts`, `kit/scenes/types.ts`, `preloaders/preloader-slices-uncovered.ts`, `showpieces/hero-opener.tsx`.
221
221
 
222
222
  ### image-to-fullbleed
223
223
  film: role centerpiece · home none · motif frame · energy 3 · pins 2.2 · none
@@ -225,7 +225,7 @@ film: role centerpiece · home none · motif frame · energy 3 · pins 2.2 · no
225
225
  Image to full bleed. A small image between the two halves of a name unclips to the full screen as the words travel off the edges.
226
226
 
227
227
  Exports: `ImageToFullbleed`. Packages: @gsap/react, gsap.
228
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `showpieces/image-to-fullbleed.tsx`.
228
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `showpieces/image-to-fullbleed.tsx`.
229
229
 
230
230
  ### panel-wipe
231
231
  film: role centerpiece · home none · motif aperture · energy 3 · pins 1.7 · none
@@ -233,7 +233,7 @@ film: role centerpiece · home none · motif aperture · energy 3 · pins 1.7 ·
233
233
  Panel wipe. Two panels carrying one word each slide apart to reveal a photo, and close again.
234
234
 
235
235
  Exports: `PanelWipe`. Packages: @gsap/react, gsap.
236
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `showpieces/panel-wipe.tsx`.
236
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `showpieces/panel-wipe.tsx`.
237
237
 
238
238
  ### scrub-connector
239
239
  film: role centerpiece · home none · motif line · energy 3 · pins 3 · none
@@ -241,7 +241,7 @@ film: role centerpiece · home none · motif line · energy 3 · pins 3 · none
241
241
  Scrub connector. Two words far apart with a tall slab of ink between them; the slab swings into one thick slash through both words (their letters knocked out where it crosses), then carries the words in on its two ends, turning to the accent as it travels, and seats long and rising between them; the joined pair holds and scrolls away whole.
242
242
 
243
243
  Exports: `ScrubConnector`. Packages: @gsap/react, gsap.
244
- Files: `kit/blocks.css`, `kit/gsap.ts`, `showpieces/scrub-connector.tsx`.
244
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `showpieces/scrub-connector.tsx`.
245
245
 
246
246
  ### project-stack
247
247
  film: role centerpiece · home none · motif neutral · energy 3 · pins 3.3 · none
@@ -249,7 +249,7 @@ film: role centerpiece · home none · motif neutral · energy 3 · pins 3.3 ·
249
249
  Project stack. One project per screen; each slides up full bleed over the last while the one beneath recedes.
250
250
 
251
251
  Exports: `ProjectStack`. Packages: @gsap/react, gsap.
252
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `showpieces/project-stack.tsx`.
252
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `showpieces/project-stack.tsx`.
253
253
 
254
254
  ### manifesto-scrub
255
255
  film: role centerpiece · home none · motif word · energy 3 · pins 2 · none
@@ -257,7 +257,7 @@ film: role centerpiece · home none · motif word · energy 3 · pins 2 · none
257
257
  Manifesto scrub. One large statement that fills word by word, from a faint ink to full ink, as it scrolls through the screen.
258
258
 
259
259
  Exports: `ManifestoScrub`. Packages: @gsap/react, gsap.
260
- Files: `kit/blocks.css`, `kit/gsap.ts`, `showpieces/manifesto-scrub.tsx`.
260
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `showpieces/manifesto-scrub.tsx`.
261
261
 
262
262
  ### fill-rows
263
263
  film: role pattern · home none · motif neutral · energy 1 · pins 0 · hover
@@ -265,7 +265,7 @@ film: role pattern · home none · motif neutral · energy 1 · pins 0 · hover
265
265
  Fill rows. Large hairline rows; on hover or focus a row floods with the accent from below and its detail slides in.
266
266
 
267
267
  Exports: `FillRows`. Packages: @gsap/react, gsap.
268
- Files: `kit/blocks.css`, `kit/gsap.ts`, `showpieces/fill-rows.tsx`.
268
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `showpieces/fill-rows.tsx`.
269
269
 
270
270
  ### pixel-resolve
271
271
  film: role pattern · home none · motif neutral · energy 1 · pins 0 · none
@@ -281,7 +281,7 @@ film: role frame · home none · motif word · energy 1 · pins 0 · clock · cl
281
281
  Wordmark finale. The footer as a finale: the name fitted edge to edge, rising out of a mask, with a closing line and a live local clock.
282
282
 
283
283
  Exports: `WordmarkFinale`. Packages: @gsap/react, gsap.
284
- Files: `kit/blocks.css`, `kit/gsap.ts`, `showpieces/wordmark-finale.tsx`.
284
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `showpieces/wordmark-finale.tsx`.
285
285
 
286
286
  ## Scene transitions
287
287
 
@@ -291,7 +291,7 @@ film: role centerpiece · home none · motif aperture · energy 3 · pins 3 · n
291
291
  Zoom-through. A pinned composed frame (the display line and a lead on the ground, the photo in an upright window with its caption and corner marks) holds; then the camera pushes into the window: the type, nearer the lens, scales away past the edges, the window opens until all four edges leave the screen together, and the photo, deeper than the window, settles out of its push-in to full bleed with its subject held in place; a strip of the ground rises from the bottom edge with the line and caption, and the next section's heading, at the display size of the frame it left, rises out of masks in the photo where its pixels allow a light or dark ink at 4.5:1 (the calm side first, then the window's side), or on bands of ground stepped up from the strip where they do not (or cannot be read), holds, and the pin lets go with the photo drifting slower than the page.
292
292
 
293
293
  Exports: `ZoomThrough`. Packages: @gsap/react, gsap.
294
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `transitions/zoom-through.tsx`.
294
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `transitions/zoom-through.tsx`.
295
295
 
296
296
  ## Sections
297
297
 
@@ -307,7 +307,7 @@ Variants (`variant`, the first is the default):
307
307
  - `doorkijk`: On a short pin a slit of photograph between the statement's two halves opens into a window and pushes them apart.
308
308
 
309
309
  Exports: `AboutStudio`. Packages: @gsap/react, gsap.
310
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/about-studio.tsx`.
310
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/about-studio.tsx`.
311
311
 
312
312
  ### approach
313
313
  film: role pattern · home none · motif line · energy 2 · pins 0 · none
@@ -321,7 +321,7 @@ Variants (`variant`, the first is the default):
321
321
  - `schuif`: An index you scrub by dragging the rule, clicking a stage or using the arrow keys, the photographs wiping across in register while the copy swaps beside them.
322
322
 
323
323
  Exports: `Approach`. Packages: @gsap/react, gsap.
324
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/approach.tsx`.
324
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/approach.tsx`.
325
325
 
326
326
  ### manifesto
327
327
  film: role pattern · home none · motif line · energy 3 · pins 2 · none
@@ -335,7 +335,7 @@ Variants (`variant`, the first is the default):
335
335
  - `split`: A short pin: the first half stands large on the left while the second half arrives on the right one sentence at a time, each rising under the one before, ending on the whole statement in two columns.
336
336
 
337
337
  Exports: `Manifesto`. Packages: @gsap/react, gsap.
338
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `sections/manifesto.tsx`.
338
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `sections/manifesto.tsx`.
339
339
 
340
340
  ### contact-form
341
341
  film: role pattern · home none · motif line · energy 1 · pins 0 · none
@@ -362,7 +362,7 @@ Variants (`variant`, the first is the default):
362
362
  - `pointer`: Plain ground, the line large and still; hovering the link brings a small project frame that follows the pointer while the link's line draws.
363
363
 
364
364
  Exports: `CtaClosing`. Packages: @gsap/react, gsap.
365
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `sections/cta-closing.tsx`.
365
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `sections/cta-closing.tsx`.
366
366
 
367
367
  ### reveals
368
368
  film: role pattern · home none · motif neutral · energy 1 · pins 0 · none
@@ -375,7 +375,7 @@ Variants (`variant`, the first is the default):
375
375
  - `card`: The whole section slides up over the previous one with a hairline shadow on its top edge; the covered section dims and falls behind as the content settles.
376
376
 
377
377
  Exports: `Reveals`. Packages: @gsap/react, gsap.
378
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/reveals.tsx`.
378
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/reveals.tsx`.
379
379
 
380
380
  ### image-trail
381
381
  film: role pattern · home none · motif neutral · energy 1 · pins 0 · cursor, hover
@@ -383,7 +383,7 @@ film: role pattern · home none · motif neutral · energy 1 · pins 0 · cursor
383
383
  Image trail. A list of work at display size; moving the pointer over a row deals that project's photograph at the pointer each time it has travelled a set distance, turned a little with the hand and settling as it lands, while older prints hold, shrink and fade behind it, six at most; a fast hand leaves a longer, wider trail and a still one leaves nothing new; keyboard focus and reduced motion show one print beside the row, and touch and phones show each photograph inline.
384
384
 
385
385
  Exports: `ImageTrail`. Packages: @gsap/react, gsap.
386
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/image-trail.tsx`.
386
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/image-trail.tsx`.
387
387
 
388
388
  ### panel-accordion
389
389
  film: role pattern · home none · motif aperture · energy 1 · pins 0 · hover
@@ -391,7 +391,7 @@ film: role pattern · home none · motif aperture · energy 1 · pins 0 · hover
391
391
  Panel accordion. A full-height row of five tall photo panels like gallery shutters: hover or focus opens one wide while the others narrow, the photograph already full size behind a widening window, its name rising in through a mask; on scroll into view the panels rise from their bottom edge one after another and the first opens on its own; phones stack them as rows that open on tap.
392
392
 
393
393
  Exports: `PanelAccordion`. Packages: @gsap/react, gsap.
394
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/panel-accordion.tsx`.
394
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/panel-accordion.tsx`.
395
395
 
396
396
  ### grid-assembly
397
397
  film: role centerpiece · home none · motif frame · energy 3 · pins 2.5 · none
@@ -399,7 +399,7 @@ film: role centerpiece · home none · motif frame · energy 3 · pins 2.5 · no
399
399
  Grid assembly. A pinned section (250%) opens on nine photos lying at angles in a composed pile, a few past the screen edges, that travel one after another into an editorial grid with exact gaps as the section's line rises in its type cell; the grid holds, then the hero print, a window onto its photo at full size, opens to the full screen while the others are pushed out, the photo never changing scale, and the next line rises on the photo's calmer side, holds, and the photo drifts slower than the page as the pin lets go. Phones open the grid tile by tile; reduced motion and pages without scripts show the grid, then the full-bleed photo with its line.
400
400
 
401
401
  Exports: `GridAssembly`. Packages: @gsap/react, gsap.
402
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `sections/grid-assembly.tsx`.
402
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `sections/grid-assembly.tsx`.
403
403
 
404
404
  ### velocity-type
405
405
  film: role pattern · home none · motif word · energy 2 · pins 0 · marquee
@@ -407,7 +407,7 @@ film: role pattern · home none · motif word · energy 2 · pins 0 · marquee
407
407
  Velocity type. Two lines of display type at 15vw run sideways in opposite directions as you scroll, run ahead with its speed, lean back and stretch slightly as if dragged, and settle upright within about 0.4 seconds of stopping, with small photographs sitting between the phrases as their own frames; the belt loops without a seam, and reduced motion and pages without scripts leave the lines at rest.
408
408
 
409
409
  Exports: `VelocityType`. Packages: @gsap/react, gsap.
410
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/velocity-type.tsx`.
410
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/velocity-type.tsx`.
411
411
 
412
412
  ### sticky-chapters
413
413
  film: role pattern · home none · motif neutral · energy 2 · pins 0 · none
@@ -415,7 +415,7 @@ film: role pattern · home none · motif neutral · energy 2 · pins 0 · none
415
415
  Sticky chapters. A process or story in chapters: one large photograph holds still on the left (plain position sticky) while the chapters scroll past on the right; as each reaches the middle its photograph rises over the last from the bottom edge (from the top when scrolling back) out of a push-in, that chapter comes forward while the others step back, and a hairline beside the frame fills as you read; phones and pages without scripts show each photograph inline, reduced motion keeps the frame with hard cuts.
416
416
 
417
417
  Exports: `StickyChapters`. Packages: @gsap/react, gsap.
418
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/sticky-chapters.tsx`.
418
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/sticky-chapters.tsx`.
419
419
 
420
420
  ### film-strip
421
421
  film: role centerpiece · home none · motif frame · energy 3 · pins 3 · none
@@ -423,7 +423,7 @@ film: role centerpiece · home none · motif frame · energy 3 · pins 3 · none
423
423
  Film strip. A pinned reel between two rows of sprocket holes opens on the section's display line beside the first project in the gate; the scroll advances it one frame at a time, portrait frames high and landscape low, each seating at the gate as its photo settles out of a push-in while the title swaps through its mask and a hairline progress line fills; the last stop is the closing frame with the call to action, and on release the strip runs on to the left. Phones swipe a snap row between sprocket rows with titles under the frames; reduced motion and pages without scripts get the same still row.
424
424
 
425
425
  Exports: `FilmStrip`. Packages: @gsap/react, gsap.
426
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/film-strip.tsx`.
426
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/film-strip.tsx`.
427
427
 
428
428
  ### hover-list
429
429
  film: role pattern · home none · motif neutral · energy 1 · pins 0 · cursor, hover
@@ -431,7 +431,7 @@ film: role pattern · home none · motif neutral · energy 1 · pins 0 · cursor
431
431
  Hover reveal list. A list of work at display size, each name with a quiet line of place and year; hovering a row shows its photograph in an upright frame that follows the pointer closely and leans with its speed while the other rows step back, row to row the photograph wipes in the way the pointer travels, and leaving the list folds the frame shut; keyboard focus and reduced motion stand the frame beside the row, and touch and phones show each photograph inline.
432
432
 
433
433
  Exports: `HoverList`. Packages: @gsap/react, gsap.
434
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/hover-list.tsx`.
434
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/hover-list.tsx`.
435
435
 
436
436
  ### split-pair
437
437
  film: role centerpiece · home none · motif cut · energy 3 · pins 3 · none
@@ -439,7 +439,7 @@ film: role centerpiece · home none · motif cut · energy 3 · pins 3 · none
439
439
  Split pair. A pinned pair of tall photos that meet at a hard seam: the word stands whole in ink on the ground with the seam through it; the first photo rises in on the left, turning its half of the letters to the photo's own ink, and holds half and half; the second comes down on the right against it and the pair holds whole, the two photos running against each other at different speeds the whole time, and on release the halves leave at their own speeds so the word shears along the seam.
440
440
 
441
441
  Exports: `SplitPair`. Packages: @gsap/react, gsap.
442
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `sections/split-pair.tsx`.
442
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `kit/photo-read.ts`, `sections/split-pair.tsx`.
443
443
 
444
444
  ### fanned-cards
445
445
  film: role centerpiece · home none · motif neutral · energy 3 · pins 3 · hover
@@ -447,7 +447,7 @@ film: role centerpiece · home none · motif neutral · energy 3 · pins 3 · ho
447
447
  Fanned cards. Services or cases as a hand of photographs played onto the table: a poster heading set on the diagonal, the hand rising into the frame and fanning open large in 3D between its two lines; it holds, then the hand is played from the back, each card flying along an arc toward the lens and turning as it goes, and laid down at its own scale into a spread (the lead card large in front, each card behind it smaller and partly under the one before, all crossing the first line), each title rising from its mask as its card lands; the spread holds, and on release the cards are picked up off the table at their own speeds. Phones get the hand as a still fan; reduced motion gets the spread. Cards lift slightly on hover.
448
448
 
449
449
  Exports: `FannedCards`. Packages: @gsap/react, gsap.
450
- Files: `kit/blocks.css`, `kit/gsap.ts`, `kit/images.ts`, `sections/fanned-cards.tsx`.
450
+ Files: `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/images.ts`, `sections/fanned-cards.tsx`.
451
451
 
452
452
  ## Footers
453
453
 
@@ -462,7 +462,7 @@ Variants (`variant`, the first is the default):
462
462
  - `iris`: The footer is uncovered through an opening that grows from a thin slit at the bottom of the screen to full, the name rising inside it.
463
463
 
464
464
  Exports: `FooterReveal`. Packages: @gsap/react, gsap, lenis.
465
- Files: `footers/footer-reveal.tsx`, `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/gsap.ts`.
465
+ Files: `footers/footer-reveal.tsx`, `kit/SmoothScroll.tsx`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`.
466
466
 
467
467
  ### footer-contact
468
468
  film: role frame · home none · motif word · energy 1 · pins 0 · clock, hover · clock by prop clock
@@ -474,5 +474,8 @@ Variants (`variant`, the first is the default):
474
474
  - `clock`: The city at display size is the centre (with clock, a live clock whose colon breathes once a second); mail, phone, address and hours stand around it like a timetable.
475
475
  - `columns`: A closing line at display size, then three columns (Contact, Studio, Volg ons) with links whose underline draws from the pointer's side.
476
476
 
477
- Exports: `FooterContact`. Packages: @gsap/react, gsap.
478
- Files: `footers/footer-contact.tsx`, `kit/blocks.css`, `kit/gsap.ts`.
477
+ Exports: `FooterContact`. Packages: ,
478
+ },
479
+ nl: {
480
+ days: [, @gsap/react, gsap.
481
+ Files: `footers/footer-contact.tsx`, `kit/blocks.css`, `kit/feel.ts`, `kit/gsap.ts`, `kit/middle/hours.ts`.
@@ -456,8 +456,9 @@ export function BackgroundAurora({ variant = "veil", lines, accent, lead, link,
456
456
  const leave = { now: 0, target: 0 };
457
457
  const ptr = { x: 0.5, y: 0.5, z: 0, tx: 0.5, ty: 0.5, tz: 0 };
458
458
 
459
+ // alpha: a cleared or discarded buffer is transparent, so the hero's own ground shows through, never black.
459
460
  const gl = canvas.getContext("webgl2", {
460
- alpha: false,
461
+ alpha: true,
461
462
  antialias: false,
462
463
  depth: false,
463
464
  stencil: false,
@@ -1145,7 +1145,8 @@ export function BackgroundFacets({ variant = "shard", lines, accent, lead, link,
1145
1145
  };
1146
1146
 
1147
1147
  const start = () => {
1148
- const gl = canvas.getContext("webgl2", { antialias: false, alpha: false, premultipliedAlpha: false, powerPreference: "low-power" });
1148
+ // alpha: a cleared or discarded buffer is transparent, so the section's ground shows, never opaque black.
1149
+ const gl = canvas.getContext("webgl2", { antialias: false, alpha: true, premultipliedAlpha: false, powerPreference: "low-power" });
1149
1150
  if (gl) g = buildGL(gl);
1150
1151
  if (!g && !gl) ctx2d = canvas.getContext("2d");
1151
1152
  else if (!g) {
@@ -1192,7 +1193,8 @@ export function BackgroundFacets({ variant = "shard", lines, accent, lead, link,
1192
1193
 
1193
1194
  const ro = new ResizeObserver(() => {
1194
1195
  measure();
1195
- if (!raf) render();
1196
+ // A resize clears the canvas, and a frame already queued would show it blank first: draw now, in this task.
1197
+ render();
1196
1198
  });
1197
1199
  ro.observe(el);
1198
1200
  if (copy) ro.observe(copy);
@@ -1228,7 +1230,7 @@ export function BackgroundFacets({ variant = "shard", lines, accent, lead, link,
1228
1230
  document.fonts?.ready.then(() => accentFaceReady(el)).then(() => {
1229
1231
  if (gone) return;
1230
1232
  measure();
1231
- if (!raf) render();
1233
+ render();
1232
1234
  });
1233
1235
 
1234
1236
  start();
@@ -357,8 +357,10 @@ function silkField(
357
357
  scratch.height = 1;
358
358
  const ctx2d = scratch.getContext("2d", { willReadFrequently: true });
359
359
 
360
+ // alpha: a cleared or discarded buffer (a resize, a restored context) is transparent, so the hero's own ground
361
+ // shows through, never an opaque black slab. Every pixel the shader writes has alpha 1, so a drawn frame is unchanged.
360
362
  const attrs: WebGLContextAttributes = {
361
- alpha: false,
363
+ alpha: true,
362
364
  antialias: false,
363
365
  depth: false,
364
366
  stencil: false,
@@ -721,9 +723,11 @@ function silkField(
721
723
  const resizeObserver = new ResizeObserver(() => {
722
724
  resize();
723
725
  remeasure();
726
+ // A resize clears the canvas: draw at once, in this task, so a paused loop never leaves it blank.
724
727
  if (reduce) still();
728
+ else if (drawn) draw();
725
729
  });
726
- const io = new IntersectionObserver(
730
+ const io =new IntersectionObserver(
727
731
  (entries) => {
728
732
  onScreen = entries.some((en) => en.isIntersecting);
729
733
  kick();