hyperframes 0.1.15 → 0.2.0-alpha.1

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 (41) hide show
  1. package/README.md +3 -3
  2. package/dist/cli.js +3968 -3297
  3. package/dist/skills/hyperframes-captions/SKILL.md +1 -1
  4. package/dist/skills/hyperframes-compose/SKILL.md +1 -0
  5. package/dist/studio/assets/index-Bkp9HQbo.css +1 -0
  6. package/dist/studio/assets/index-DfhSlTti.js +93 -0
  7. package/dist/studio/index.html +2 -2
  8. package/dist/templates/_shared/CLAUDE.md +1 -1
  9. package/package.json +3 -2
  10. package/dist/studio/assets/index-CLmYRLY-.css +0 -1
  11. package/dist/studio/assets/index-CRvFpc0E.js +0 -84
  12. package/dist/templates/decision-tree/compositions/decision_tree.html +0 -420
  13. package/dist/templates/decision-tree/index.html +0 -56
  14. package/dist/templates/generators.ts +0 -32
  15. package/dist/templates/kinetic-type/compositions/main-graphics.html +0 -588
  16. package/dist/templates/kinetic-type/index.html +0 -61
  17. package/dist/templates/nyt-graph/compositions/nyt-chart.html +0 -450
  18. package/dist/templates/nyt-graph/index.html +0 -51
  19. package/dist/templates/play-mode/compositions/captions.html +0 -163
  20. package/dist/templates/play-mode/compositions/intro.html +0 -107
  21. package/dist/templates/play-mode/compositions/stats.html +0 -388
  22. package/dist/templates/play-mode/index.html +0 -239
  23. package/dist/templates/product-promo/assets/figma-cursors.svg +0 -30
  24. package/dist/templates/product-promo/assets/figma-logo-pieces.svg +0 -15
  25. package/dist/templates/product-promo/assets/figma-logo-pills.svg +0 -6
  26. package/dist/templates/product-promo/compositions/scene1-logo-intro.html +0 -189
  27. package/dist/templates/product-promo/compositions/scene2-4-canvas.html +0 -570
  28. package/dist/templates/product-promo/compositions/scene5-logo-outro.html +0 -226
  29. package/dist/templates/product-promo/index.html +0 -158
  30. package/dist/templates/swiss-grid/assets/swiss-grid.svg +0 -116
  31. package/dist/templates/swiss-grid/compositions/captions.html +0 -148
  32. package/dist/templates/swiss-grid/compositions/graphics.html +0 -207
  33. package/dist/templates/swiss-grid/compositions/intro.html +0 -131
  34. package/dist/templates/swiss-grid/index.html +0 -234
  35. package/dist/templates/vignelli/compositions/captions.html +0 -181
  36. package/dist/templates/vignelli/compositions/overlays.html +0 -323
  37. package/dist/templates/vignelli/index.html +0 -190
  38. package/dist/templates/warm-grain/compositions/captions.html +0 -147
  39. package/dist/templates/warm-grain/compositions/graphics.html +0 -164
  40. package/dist/templates/warm-grain/compositions/intro.html +0 -86
  41. package/dist/templates/warm-grain/index.html +0 -294
@@ -1,181 +0,0 @@
1
- <template id="captions-template">
2
- <div
3
- data-composition-id="captions"
4
- data-width="1080"
5
- data-height="1920"
6
- data-duration="__VIDEO_DURATION__"
7
- >
8
- <div id="captions-container"></div>
9
-
10
- <style>
11
- [data-composition-id="captions"] {
12
- position: absolute;
13
- top: 0;
14
- left: 0;
15
- width: 1080px;
16
- height: 1920px;
17
- font-family: "Helvetica", "Helvetica Neue", Arial, sans-serif;
18
- font-weight: 900; /* Helvetica Black/Bold */
19
- text-transform: uppercase;
20
- pointer-events: none;
21
- }
22
-
23
- [data-composition-id="captions"] #captions-container {
24
- position: absolute;
25
- inset: 0;
26
- }
27
-
28
- [data-composition-id="captions"] .caption-group {
29
- position: absolute;
30
- left: 50%;
31
- transform: translateX(-50%);
32
- width: auto;
33
- max-width: 920px; /* 1080 - 2*80 */
34
- bottom: 672px;
35
- display: flex;
36
- justify-content: center;
37
- align-items: center;
38
- text-align: center;
39
- opacity: 0;
40
- z-index: 10;
41
- }
42
-
43
- [data-composition-id="captions"] .caption-text {
44
- font-size: 64px;
45
- line-height: 1.1;
46
- color: #000000;
47
- background-color: #ffffff;
48
- padding: 15px 30px;
49
- border-top: 8px solid #cc0000; /* Vignelli Red top border accent */
50
- display: inline-block;
51
- letter-spacing: -0.02em; /* Tight Helvetica spacing */
52
- white-space: nowrap; /* Prevent wrapping at the element level */
53
- }
54
- </style>
55
-
56
- <script>
57
- (function () {
58
- const TRANSCRIPT = [
59
- { text: "We", start: 0.14, end: 0.239 },
60
- { text: "asked", start: 0.28, end: 0.459 },
61
- { text: "what", start: 0.5, end: 0.619 },
62
- { text: "you", start: 0.659, end: 0.779 },
63
- { text: "needed.", start: 0.8, end: 1.179 },
64
- { text: "Forty-seven", start: 1.199, end: 1.619 },
65
- { text: "percent", start: 1.699, end: 1.96 },
66
- { text: "of", start: 1.979, end: 2.059 },
67
- { text: "you", start: 2.099, end: 2.299 },
68
- { text: "said", start: 2.319, end: 2.499 },
69
- { text: "motion", start: 2.559, end: 2.839 },
70
- { text: "graphics,", start: 2.899, end: 3.759 },
71
- { text: "sixty-two", start: 3.799, end: 4.159 },
72
- { text: "percent", start: 4.239, end: 4.559 },
73
- { text: "said", start: 4.639, end: 4.799 },
74
- { text: "static", start: 4.859, end: 5.199 },
75
- { text: "content", start: 5.239, end: 5.639 },
76
- { text: "was", start: 5.679, end: 5.779 },
77
- { text: "costing", start: 5.859, end: 6.219 },
78
- { text: "you", start: 6.259, end: 6.339 },
79
- { text: "attention,", start: 6.379, end: 7.299 },
80
- { text: "and", start: 7.319, end: 7.439 },
81
- { text: "three", start: 7.48, end: 7.599 },
82
- { text: "out", start: 7.679, end: 7.779 },
83
- { text: "of", start: 7.799, end: 7.879 },
84
- { text: "four", start: 7.94, end: 8.139 },
85
- { text: "said", start: 8.279, end: 8.46 },
86
- { text: "you", start: 8.519, end: 8.6 },
87
- { text: "know", start: 8.619, end: 8.739 },
88
- { text: "the", start: 8.8, end: 8.88 },
89
- { text: "look", start: 8.92, end: 9.079 },
90
- { text: "you", start: 9.119, end: 9.259 },
91
- { text: "want", start: 9.279, end: 9.619 },
92
- { text: "but", start: 9.779, end: 9.88 },
93
- { text: "don't", start: 9.92, end: 10.1 },
94
- { text: "have", start: 10.159, end: 10.3 },
95
- { text: "the", start: 10.3, end: 10.42 },
96
- { text: "editing", start: 10.5, end: 10.779 },
97
- { text: "skills", start: 10.86, end: 11.139 },
98
- { text: "to", start: 11.159, end: 11.239 },
99
- { text: "get", start: 11.279, end: 11.439 },
100
- { text: "there.", start: 11.46, end: 12.239 },
101
- { text: "So", start: 12.3, end: 12.38 },
102
- { text: "we", start: 12.399, end: 12.519 },
103
- { text: "built", start: 12.539, end: 12.759 },
104
- { text: "Hyperframes", start: 12.84, end: 13.119 },
105
- ];
106
- const tl = gsap.timeline({ paused: true });
107
- const container = document.getElementById("captions-container");
108
-
109
- // Group words into single lines (max words or based on pauses/sentence ends)
110
- function groupTranscript(transcript, maxWords = 3) {
111
- const groups = [];
112
- let currentGroup = [];
113
-
114
- transcript.forEach((word, index) => {
115
- currentGroup.push(word);
116
-
117
- const nextWord = transcript[index + 1];
118
- const isPause = nextWord && nextWord.start - word.end > 0.15;
119
- const isSentenceEnd =
120
- word.text.includes(".") || word.text.includes("?") || word.text.includes("!");
121
-
122
- if (currentGroup.length >= maxWords || isPause || isSentenceEnd || !nextWord) {
123
- groups.push({
124
- words: currentGroup,
125
- start: currentGroup[0].start,
126
- end: currentGroup[currentGroup.length - 1].end,
127
- text: currentGroup.map((w) => w.text).join(" "),
128
- });
129
- currentGroup = [];
130
- }
131
- });
132
- return groups;
133
- }
134
-
135
- const captionGroups = groupTranscript(TRANSCRIPT);
136
-
137
- captionGroups.forEach((group, index) => {
138
- const div = document.createElement("div");
139
- div.className = "caption-group";
140
- div.id = `group-${index}`;
141
-
142
- const textSpan = document.createElement("span");
143
- textSpan.className = "caption-text";
144
- textSpan.innerText = group.text;
145
-
146
- div.appendChild(textSpan);
147
- container.appendChild(div);
148
-
149
- // Animation: Modern "expo.out" transitions
150
- // Entrance
151
- tl.fromTo(
152
- div,
153
- { opacity: 0, y: 20 },
154
- {
155
- opacity: 1,
156
- y: 0,
157
- duration: 0.4,
158
- ease: "expo.out",
159
- },
160
- group.start,
161
- );
162
-
163
- // Exit
164
- tl.to(
165
- div,
166
- {
167
- opacity: 0,
168
- y: -10,
169
- duration: 0.3,
170
- ease: "expo.out",
171
- },
172
- group.end - 0.3,
173
- );
174
- });
175
-
176
- window.__timelines = window.__timelines || {};
177
- window.__timelines["captions"] = tl;
178
- })();
179
- </script>
180
- </div>
181
- </template>
@@ -1,323 +0,0 @@
1
- <template id="overlays-template">
2
- <div data-composition-id="overlays" data-width="1080" data-height="1920" data-duration="16.88">
3
- <!-- 6-Column Grid Overlay (for visual reference during development, hidden by default) -->
4
- <div class="vignelli-grid">
5
- <div class="col"></div>
6
- <div class="col"></div>
7
- <div class="col"></div>
8
- <div class="col"></div>
9
- <div class="col"></div>
10
- <div class="col"></div>
11
- </div>
12
-
13
- <!-- 1. 47% Motion Graphics -->
14
- <div class="overlay-item motion-graphics-stat" id="stat-47">
15
- <div class="red-bar"></div>
16
- <div class="stat-content">
17
- <div class="number">47%</div>
18
- <div class="label">Motion Graphics</div>
19
- </div>
20
- </div>
21
-
22
- <!-- 2. 62% Static Content (Full Canvas) -->
23
- <div class="overlay-item static-content-stat" id="stat-62">
24
- <div class="bg-charcoal"></div>
25
- <div class="full-content">
26
- <div class="large-number">62%</div>
27
- <div class="large-label">Static Content</div>
28
- <div class="red-accent"></div>
29
- </div>
30
- </div>
31
-
32
- <!-- 3. 3 out of 4 lack editing skills -->
33
- <div class="overlay-item editing-skills-stat" id="stat-3-4">
34
- <div class="text-block">
35
- <span class="highlight">3 out of 4</span>
36
- <br />lack editing skills
37
- </div>
38
- <div class="side-bar"></div>
39
- </div>
40
-
41
- <!-- 4. Hyperframes Branding -->
42
- <div class="overlay-item branding-reveal" id="branding">
43
- <div class="logo-container">
44
- <div class="logo-text"><span class="heavy">HYPERFRAMES</span></div>
45
- <div class="logo-underline"></div>
46
- </div>
47
- </div>
48
-
49
- <style>
50
- [data-composition-id="overlays"] {
51
- position: relative;
52
- width: 1080px;
53
- height: 1920px;
54
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
55
- color: #000000;
56
- overflow: hidden;
57
- pointer-events: none;
58
- }
59
-
60
- /* Grid System */
61
- [data-composition-id="overlays"] .vignelli-grid {
62
- position: absolute;
63
- top: 0;
64
- left: 0;
65
- width: 100%;
66
- height: 100%;
67
- display: grid;
68
- grid-template-columns: repeat(6, 1fr);
69
- pointer-events: none;
70
- z-index: 100;
71
- opacity: 0; /* Hidden */
72
- }
73
- [data-composition-id="overlays"] .vignelli-grid .col {
74
- border-right: 1px solid rgba(204, 0, 0, 0.1);
75
- }
76
-
77
- [data-composition-id="overlays"] .overlay-item {
78
- position: absolute;
79
- opacity: 0;
80
- display: flex;
81
- z-index: 10;
82
- }
83
-
84
- /* 1. 47% Stat Styles */
85
- [data-composition-id="overlays"] #stat-47 {
86
- bottom: 200px;
87
- left: 0;
88
- width: 540px; /* 3 columns */
89
- height: 240px;
90
- background: #ffffff;
91
- flex-direction: row;
92
- align-items: stretch;
93
- }
94
- [data-composition-id="overlays"] #stat-47 .red-bar {
95
- width: 20px;
96
- background: #cc0000;
97
- }
98
- [data-composition-id="overlays"] #stat-47 .stat-content {
99
- padding: 40px;
100
- display: flex;
101
- flex-direction: column;
102
- justify-content: center;
103
- }
104
- [data-composition-id="overlays"] #stat-47 .number {
105
- font-size: 120px;
106
- font-weight: 900;
107
- line-height: 1;
108
- letter-spacing: -2px;
109
- }
110
- [data-composition-id="overlays"] #stat-47 .label {
111
- font-size: 32px;
112
- font-weight: 700;
113
- text-transform: uppercase;
114
- margin-top: 10px;
115
- }
116
-
117
- /* 2. 62% Stat Styles (Full Canvas) */
118
- [data-composition-id="overlays"] #stat-62 {
119
- top: 0;
120
- left: 0;
121
- width: 1080px;
122
- height: 1920px;
123
- z-index: 50;
124
- }
125
- [data-composition-id="overlays"] #stat-62 .bg-charcoal {
126
- position: absolute;
127
- top: 0;
128
- left: 0;
129
- width: 100%;
130
- height: 100%;
131
- background: #1a1a1a;
132
- }
133
- [data-composition-id="overlays"] #stat-62 .full-content {
134
- position: relative;
135
- width: 100%;
136
- height: 100%;
137
- display: flex;
138
- flex-direction: column;
139
- justify-content: center;
140
- padding: 0 90px; /* Align with grid */
141
- }
142
- [data-composition-id="overlays"] #stat-62 .large-number {
143
- font-size: 400px;
144
- font-weight: 900;
145
- color: #ffffff;
146
- line-height: 0.8;
147
- letter-spacing: -10px;
148
- }
149
- [data-composition-id="overlays"] #stat-62 .large-label {
150
- font-size: 80px;
151
- font-weight: 700;
152
- color: #ffffff;
153
- text-transform: uppercase;
154
- margin-top: 20px;
155
- max-width: 600px;
156
- }
157
- [data-composition-id="overlays"] #stat-62 .red-accent {
158
- position: absolute;
159
- top: 0;
160
- right: 0;
161
- width: 180px; /* 1 column */
162
- height: 100%;
163
- background: #cc0000;
164
- }
165
-
166
- /* 3. 3 out of 4 Stat Styles */
167
- [data-composition-id="overlays"] #stat-3-4 {
168
- top: 400px;
169
- right: 0;
170
- width: 360px; /* 2 columns */
171
- background: #ffffff;
172
- padding: 40px;
173
- flex-direction: row-reverse;
174
- }
175
- [data-composition-id="overlays"] #stat-3-4 .text-block {
176
- font-size: 48px;
177
- font-weight: 700;
178
- line-height: 1.1;
179
- text-align: right;
180
- }
181
- [data-composition-id="overlays"] #stat-3-4 .highlight {
182
- color: #cc0000;
183
- font-size: 64px;
184
- font-weight: 900;
185
- }
186
- [data-composition-id="overlays"] #stat-3-4 .side-bar {
187
- width: 10px;
188
- background: #000000;
189
- margin-left: 20px;
190
- }
191
-
192
- /* 4. Branding Styles */
193
- [data-composition-id="overlays"] #branding {
194
- bottom: 100px;
195
- left: 90px;
196
- width: 900px;
197
- justify-content: center;
198
- z-index: 60;
199
- }
200
- [data-composition-id="overlays"] #branding .logo-container {
201
- display: flex;
202
- flex-direction: column;
203
- align-items: center;
204
- }
205
- [data-composition-id="overlays"] #branding .logo-text {
206
- font-size: 64px;
207
- letter-spacing: 10px;
208
- color: #000000;
209
- }
210
- [data-composition-id="overlays"] #branding .logo-text .heavy {
211
- font-weight: 900;
212
- }
213
- [data-composition-id="overlays"] #branding .logo-text .light {
214
- font-weight: 300;
215
- }
216
- [data-composition-id="overlays"] #branding .logo-underline {
217
- width: 100%;
218
- height: 8px;
219
- background: #cc0000;
220
- margin-top: 10px;
221
- transform-origin: left;
222
- }
223
- </style>
224
-
225
- <script>
226
- const tl = gsap.timeline({ paused: true });
227
- const TRANSCRIPT = [
228
- { text: "We", start: 0.14, end: 0.239 },
229
- { text: "asked", start: 0.28, end: 0.459 },
230
- { text: "what", start: 0.5, end: 0.619 },
231
- { text: "you", start: 0.659, end: 0.779 },
232
- { text: "needed.", start: 0.8, end: 1.179 },
233
- { text: "Forty-seven", start: 1.199, end: 1.619 },
234
- { text: "percent", start: 1.699, end: 1.96 },
235
- { text: "of", start: 1.979, end: 2.059 },
236
- { text: "you", start: 2.099, end: 2.299 },
237
- { text: "said", start: 2.319, end: 2.499 },
238
- { text: "motion", start: 2.559, end: 2.839 },
239
- { text: "graphics,", start: 2.899, end: 3.759 },
240
- { text: "sixty-two", start: 3.799, end: 4.159 },
241
- { text: "percent", start: 4.239, end: 4.559 },
242
- { text: "said", start: 4.639, end: 4.799 },
243
- { text: "static", start: 4.859, end: 5.199 },
244
- { text: "content", start: 5.239, end: 5.639 },
245
- { text: "was", start: 5.679, end: 5.779 },
246
- { text: "costing", start: 5.859, end: 6.219 },
247
- { text: "you", start: 6.259, end: 6.339 },
248
- { text: "attention,", start: 6.379, end: 7.299 },
249
- { text: "and", start: 7.319, end: 7.439 },
250
- { text: "three", start: 7.48, end: 7.599 },
251
- { text: "out", start: 7.679, end: 7.779 },
252
- { text: "of", start: 7.799, end: 7.879 },
253
- { text: "four", start: 7.94, end: 8.139 },
254
- { text: "said", start: 8.279, end: 8.46 },
255
- { text: "you", start: 8.519, end: 8.6 },
256
- { text: "know", start: 8.619, end: 8.739 },
257
- { text: "the", start: 8.8, end: 8.88 },
258
- { text: "look", start: 8.92, end: 9.079 },
259
- { text: "you", start: 9.119, end: 9.259 },
260
- { text: "want", start: 9.279, end: 9.619 },
261
- { text: "but", start: 9.779, end: 9.88 },
262
- { text: "don't", start: 9.92, end: 10.1 },
263
- { text: "have", start: 10.159, end: 10.3 },
264
- { text: "the", start: 10.3, end: 10.42 },
265
- { text: "editing", start: 10.5, end: 10.779 },
266
- { text: "skills", start: 10.86, end: 11.139 },
267
- { text: "to", start: 11.159, end: 11.239 },
268
- { text: "get", start: 11.279, end: 11.439 },
269
- { text: "there.", start: 11.46, end: 12.239 },
270
- { text: "So", start: 12.3, end: 12.38 },
271
- { text: "we", start: 12.399, end: 12.519 },
272
- { text: "built", start: 12.539, end: 12.759 },
273
- { text: "Hyperframes", start: 12.84, end: 13.119 },
274
- ];
275
-
276
- // Requirement 1: "47% Motion Graphics" (Start: 1.199, End: 3.759)
277
- // Positioned in bottom half, columns 1-3.
278
- tl.fromTo(
279
- "#stat-47",
280
- { x: -540, opacity: 1 },
281
- { x: 0, duration: 0.8, ease: "expo.out" },
282
- 1.199,
283
- );
284
- tl.to("#stat-47", { x: -540, duration: 0.6, ease: "expo.in" }, 3.759 - 0.6);
285
-
286
- // Requirement 2: "62% Static Content" (Start: 3.799, End: 7.299)
287
- // Full canvas moment. Large bold typography across columns.
288
- tl.set("#stat-62", { opacity: 1 }, 3.799);
289
- tl.from("#stat-62 .bg-charcoal", { x: "100%", duration: 0.8, ease: "expo.out" }, 3.799);
290
- tl.from("#stat-62 .red-accent", { x: "100%", duration: 0.8, ease: "expo.out" }, 3.899);
291
- tl.from(
292
- "#stat-62 .large-number",
293
- { y: 100, opacity: 0, duration: 1, ease: "expo.out" },
294
- 4.099,
295
- );
296
- tl.from("#stat-62 .large-label", { y: 50, opacity: 0, duration: 1, ease: "expo.out" }, 4.299);
297
-
298
- tl.to("#stat-62", { x: "-100%", duration: 0.8, ease: "expo.in" }, 7.299 - 0.8);
299
-
300
- // Requirement 3: "3 out of 4 lack editing skills" (Start: 7.319, End: 12.239)
301
- // Positioned in columns 5-6 (right side) to avoid face (x: 300-776)
302
- tl.fromTo(
303
- "#stat-3-4",
304
- { x: 360, opacity: 1 },
305
- { x: 0, duration: 0.8, ease: "expo.out" },
306
- 7.319,
307
- );
308
- tl.to("#stat-3-4", { x: 360, duration: 0.6, ease: "expo.in" }, 12.239 - 0.6);
309
-
310
- // Requirement 4: "Hyperframes" (Start: 12.84, End: 13.84)
311
- tl.set("#branding", { opacity: 1 }, 12.84);
312
- tl.from(
313
- "#branding .logo-text",
314
- { y: 20, opacity: 0, duration: 0.6, ease: "expo.out" },
315
- 12.84,
316
- );
317
- tl.from("#branding .logo-underline", { scaleX: 0, duration: 0.8, ease: "expo.out" }, 13.04);
318
-
319
- window.__timelines = window.__timelines || {};
320
- window.__timelines["overlays"] = tl;
321
- </script>
322
- </div>
323
- </template>
@@ -1,190 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>Massimo Vignelli Video</title>
6
- <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
7
- <style>
8
- body,
9
- html {
10
- margin: 0;
11
- padding: 0;
12
- background: #ffffff;
13
- overflow: hidden;
14
- width: 1080px;
15
- height: 1920px;
16
- font-family: "Helvetica", Arial, sans-serif;
17
- }
18
-
19
- /* 6-Column Grid System */
20
- .grid-container {
21
- position: absolute;
22
- top: 0;
23
- left: 0;
24
- width: 1080px;
25
- height: 1920px;
26
- display: grid;
27
- grid-template-columns: repeat(6, 1fr);
28
- pointer-events: none;
29
- z-index: 1000;
30
- opacity: 0; /* Keep grid invisible but present for layout references */
31
- }
32
-
33
- .grid-column {
34
- border-right: 1px solid rgba(204, 0, 0, 0.2); /* Vignelli Red accent */
35
- }
36
-
37
- #main-composition {
38
- position: relative;
39
- width: 1080px;
40
- height: 1920px;
41
- background: #ffffff;
42
- overflow: hidden;
43
- }
44
-
45
- /* Layer Hosts */
46
- #a-roll-wrapper {
47
- position: absolute;
48
- top: 0;
49
- left: 0;
50
- width: 100%;
51
- height: 100%;
52
- z-index: 10;
53
- overflow: hidden;
54
- }
55
-
56
- #a-roll,
57
- #a-roll-wrapper img.__render_frame__,
58
- #a-roll-wrapper img.__preview_render_frame__ {
59
- position: absolute;
60
- inset: 0;
61
- width: 100%;
62
- height: 100%;
63
- object-fit: cover;
64
- }
65
-
66
- #overlays-comp,
67
- #captions-comp {
68
- position: absolute;
69
- top: 0;
70
- left: 0;
71
- width: 1080px;
72
- height: 1920px;
73
- pointer-events: none;
74
- }
75
-
76
- #overlays-comp {
77
- z-index: 20;
78
- }
79
-
80
- #captions-comp {
81
- z-index: 30;
82
- }
83
-
84
- /* Curtain Transition Layer */
85
- .curtain {
86
- position: absolute;
87
- top: 0;
88
- left: -100%;
89
- width: 100%;
90
- height: 100%;
91
- background: #1a1a1a;
92
- z-index: 25;
93
- pointer-events: none;
94
- }
95
-
96
- .curtain.red {
97
- background: #cc0000;
98
- z-index: 26;
99
- }
100
- </style>
101
- </head>
102
- <body>
103
- <div
104
- id="main-composition"
105
- data-composition-id="main-comp"
106
- data-width="1080"
107
- data-height="1920"
108
- data-start="0"
109
- data-duration="__VIDEO_DURATION__"
110
- >
111
- <!-- A-Roll -->
112
- <div id="a-roll-wrapper">
113
- <video
114
- id="a-roll"
115
- src="__VIDEO_SRC__"
116
- muted
117
- playsinline
118
- data-start="0"
119
- data-duration="__VIDEO_DURATION__"
120
- data-track-index="0"
121
- ></video>
122
- </div>
123
- <audio
124
- id="a-roll-audio"
125
- src="__VIDEO_SRC__"
126
- data-start="0"
127
- data-duration="__VIDEO_DURATION__"
128
- data-track-index="5"
129
- data-volume="1"
130
- ></audio>
131
-
132
- <!-- Transitions -->
133
- <div id="curtain-black" class="curtain"></div>
134
- <div id="curtain-red" class="curtain red"></div>
135
-
136
- <!-- Overlays Composition -->
137
- <div
138
- id="overlays-comp"
139
- data-composition-id="overlays"
140
- data-composition-src="compositions/overlays.html"
141
- data-start="0"
142
- data-duration="__VIDEO_DURATION__"
143
- data-track-index="2"
144
- ></div>
145
-
146
- <!-- Captions Composition -->
147
- <div
148
- id="captions-comp"
149
- data-composition-id="captions"
150
- data-composition-src="compositions/captions.html"
151
- data-start="0"
152
- data-duration="__VIDEO_DURATION__"
153
- data-track-index="3"
154
- ></div>
155
-
156
- <!-- Grid Visualization -->
157
- <div class="grid-container">
158
- <div class="grid-column"></div>
159
- <div class="grid-column"></div>
160
- <div class="grid-column"></div>
161
- <div class="grid-column"></div>
162
- <div class="grid-column"></div>
163
- <div class="grid-column"></div>
164
- </div>
165
-
166
- <script>
167
- const tl = gsap.timeline({ paused: true });
168
-
169
- // Transition: Curtain Pull logic
170
- // A-roll leaves the screen at least once.
171
- // Timing: Let's do a curtain pull at 3.7s (transitioning to the 62% stat)
172
- // and return at 7.3s (end of attention stat).
173
-
174
- // Curtain Out (A-roll hidden)
175
- tl.to("#curtain-black", { left: "0%", duration: 0.2, ease: "power2.inOut" }, 3.5);
176
- tl.to("#a-roll-wrapper", { opacity: 0, duration: 0 }, 3.7);
177
- tl.to("#curtain-black", { left: "100%", duration: 0.4, ease: "power2.inOut" }, 3.7);
178
-
179
- // Curtain In (A-roll return)
180
- tl.set("#curtain-red", { left: "-100%" }, 7.1);
181
- tl.to("#curtain-red", { left: "0%", duration: 0.2, ease: "power2.inOut" }, 7.1);
182
- tl.to("#a-roll-wrapper", { opacity: 1, duration: 0 }, 7.3);
183
- tl.to("#curtain-red", { left: "100%", duration: 0.4, ease: "power2.inOut" }, 7.3);
184
-
185
- window.__timelines = window.__timelines || {};
186
- window.__timelines["main-comp"] = tl;
187
- </script>
188
- </div>
189
- </body>
190
- </html>