Setting the file. One moment. Master Skeleton · Changelog Video · heygen-com/hyperframes · Skills Docs(opens in a new tab)
examples/master-skeleton.html
HTML·138 lines·8 KB
<
title
>HyperFrames Weekly — <
RANGE
></
title
>
9 <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
10 <style>
11 @font-face { font-family:'ABC Solar Display'; src:url('assets/fonts/ABCSolarDisplay-Bold.woff2') format('woff2'); font-weight:700; font-display:block; }
12 @font-face { font-family:'TT Norms Pro'; src:url('assets/fonts/TT_Norms_Pro_Normal.woff2') format('woff2'); font-weight:400; font-display:block; }
13 @font-face { font-family:'TT Norms Pro'; src:url('assets/fonts/TT_Norms_Pro_Medium.woff2') format('woff2'); font-weight:500; font-display:block; }
14 @font-face { font-family:'TT Norms Mono'; src:url('assets/fonts/tt_norms_pro_mono_regular-webfont.woff2') format('woff2'); font-weight:400; font-display:block; }
15 * { margin: 0; padding: 0; box-sizing: border-box; }
16 html, body { width: 1080px; height: 1080px; background: #0a0c0b; overflow: hidden;
17 font-family: 'TT Norms Pro', sans-serif; color: #f5f6f4; }
18 #bg-video { position: absolute; inset: 0; width: 1080px; height: 1080px; object-fit: cover; }
19 #bg-scrim { position: absolute; inset: 0; background: rgba(8,10,9,.25); }
20 .chrome { position: absolute; z-index: 6; }
21 #kicker-chip { top: 44px; left: 76px; font-family: 'TT Norms Mono', monospace; font-size: 20px;
22 letter-spacing: .06em; color: rgba(245,246,244,.72); background: rgba(255,255,255,.05);
23 border: 1px solid rgba(255,255,255,.14); border-radius: 12px; padding: 10px 18px; }
24 #progress { top: 58px; right: 76px; display: flex; gap: 10px; }
25 #progress .dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(245,246,244,.18); }
26 /* The clip element itself carries NO opacity base and is never targeted by GSAP:
27 the framework owns a clip's visibility window, and `gsap_animates_clip_element`
28 is an ERROR-severity lint rule. Seams animate the inner .swrap instead. */
29 .slide { position: absolute; inset: 0; }
30 .swrap { position: absolute; inset: 0; opacity: 0; }
31 .sec-chip { position: absolute; top: 128px; left: 76px; font-family: 'TT Norms Mono', monospace;
32 font-size: 22px; letter-spacing: .05em; color: rgba(245,246,244,.72);
33 background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.14);
34 border-radius: 12px; padding: 10px 16px; }
35 .sec-head { position: absolute; top: 186px; left: 76px; font-family: 'ABC Solar Display', sans-serif;
36 font-weight: 700; font-size: 54px; letter-spacing: -.01em; color: #f5f6f4; }
37 .glass { background: rgba(10,12,11,.78); border: 1px solid rgba(190,255,205,.32);
38 border-radius: 22px; box-shadow: 0 24px 60px rgba(0,0,0,.5); }
39 /* caption rail — overlay on top of the film, never a reserved band */
40 #cap-line { position: absolute; left: 0; right: 0; top: 990px; height: 52px; text-align: center;
41 z-index: 7; font-family: 'TT Norms Pro', sans-serif; font-weight: 500; font-size: 32px;
42 letter-spacing: .01em; color: rgba(245,246,244,.94);
43 text-shadow: 0 2px 14px rgba(0,0,0,.85), 0 0 3px rgba(0,0,0,.6);
44 white-space: nowrap; pointer-events: none; }
45 .cap-phrase { position: absolute; left: 0; right: 0; }
46 .cap-w { display: inline-block; margin: 0 4px; }
47 </style>
48</head>
49<body>
50 <div id="root" data-composition-id="main" data-start="0" data-duration="<TOTAL>" data-width="1080" data-height="1080">
51 <video id="bg-video" class="clip" src="assets/bg-pattern-<TOTAL>s.mp4" muted data-start="0" data-duration="<TOTAL>" data-track-index="0"></video>
52 <div id="bg-scrim"></div>
53 <div id="kicker-chip" class="chrome">HYPERFRAMES WEEKLY <span style="color:rgba(245,246,244,.66)">· <RANGE></span></div>
54 <div id="progress" class="chrome"><span class="dot" id="dot1"></span><!-- one per theme --></div>
55 <div id="cap-line" class="chrome" data-layout-allow-caption-zone></div>
56
57 <!-- Title (film open — authors its OWN entry; exit is stamped) -->
58 <div id="s-title" class="slide clip" data-start="0" data-duration="<CUT1>" data-track-index="1">
59 <div id="w-title" class="swrap">
60 <!-- mono kicker date · ABC Solar h1 · green rule -->
61 </div>
62 </div>
63
64 <!-- One slide per theme. data-start = EXACTLY the ledger cut time.
65 Every slide holds ONE inner .swrap (#w-*) and the ledger's exit/entry
66 selectors name THAT wrapper, never the #s-* clip element.
67 Shell composed at local t=0; internal beats ≥0.4s after the cut,
68 done ≥0.45s before the next. Put data-layout-allow-overlap only on
69 the specific text blocks that deliberately layer. -->
70 <div id="s-t1" class="slide clip" data-start="<CUT1>" data-duration="<DUR1>" data-track-index="1">
71 <div id="w-t1" class="swrap">
72 <div class="sec-chip">01 · <THEME></div>
73 <div class="sec-head"><HEADLINE></div>
74 <!-- the mock, from references/visualization-registry.md, y ∈ [288, 944] -->
75 </div>
76 </div>
77
78 <!-- s-t2..tN, then outro (kicker · "See what shipped." · green rule · URL chip) -->
79
80 <audio id="bgm" src="bgm.mp3" data-start="0" data-duration="<TOTAL>" data-track-index="2" data-volume="0.14" data-media-start="0"></audio>
81 <audio id="vo" src="voiceover.mp3" data-start="0" data-duration="<TOTAL>" data-track-index="3" data-volume="1.0"></audio>
82 </div>
83
84 <script>
85 gsap.defaults({ overwrite: 'auto' });
86 const tl = gsap.timeline({ paused: true });
87 tl.to({}, { duration: /*<TOTAL>*/ 47 }, 0);
88
89 // chrome in; progress dots via tl.set at each cut (never tl.call)
90 gsap.set('#kicker-chip', { autoAlpha: 0, y: -10 });
91 tl.to('#kicker-chip', { autoAlpha: 1, y: 0, duration: 0.5, ease: 'power3.out' }, 0.1);
92 // tl.set('#dot1', { backgroundColor: '#f5f6f4' }, <CUT1>); …
93
94 // Title entry — authored HERE, never stamped (seam-stamp owns every other
95 // wrapper entry). immediateRender:false is load-bearing: seam-stamp emits a
96 // zero-duration tl.set(#w-title, autoAlpha:0) at the title's cut, and a
97 // zero-duration GSAP tween immediate-renders at BUILD time. Without the flag
98 // this fromTo captures that 0 as its start value and tweens 0 → 0, which the
99 // seam gate reports as `exit-visible … op 0.00` while exit-vector PASSES.
100 tl.fromTo('#w-title', { autoAlpha: 0 },
101 { autoAlpha: 1, duration: 0.30, ease: 'power2.out', immediateRender: false }, 0);
102
103 // ══ per-scene internal beats ══
104 // init states: gsap.set(...) at build time; motion: sequential tl.to(...) only.
105 // Every beat lands on a vo-words.json timestamp (local = master − scene start).
106 // One green (#5ef17c) moment per scene.
107
108 // ══ CAPTION RAIL — paste captions.json "lines" from align-captions.mjs ══
109 (function () {
110 const LINES = /* paste captions.json lines — [{id, end, w:[[display, start],…]},…] */ [];
111 const host = document.getElementById('cap-line');
112 LINES.forEach((line, li) => {
113 const ph = document.createElement('div');
114 ph.className = 'cap-phrase'; ph.id = 'cap-p' + li;
115 line.w.forEach(([txt], wi) => {
116 const s = document.createElement('span');
117 s.className = 'cap-w'; s.id = 'cap-p' + li + '-w' + wi; s.textContent = txt;
118 ph.appendChild(s);
119 });
120 host.appendChild(ph);
121 });
122 gsap.set('.cap-phrase', { autoAlpha: 0 });
123 gsap.set('.cap-w', { autoAlpha: 0 });
124 LINES.forEach((line, li) => {
125 tl.set('#cap-p' + li, { autoAlpha: 1 }, line.w[0][1]);
126 tl.set('#cap-p' + li, { autoAlpha: 0 }, line.end);
127 line.w.forEach(([txt, at], wi) => {
128 tl.to('#cap-p' + li + '-w' + wi, { autoAlpha: 1, duration: 0.12, ease: 'power1.out' }, at);
129 });
130 });
131 })();
132
133 window.__timelines = window.__timelines || {};
134 window.__timelines["main"] = tl;
135 // seam-stamp.mjs inserts the <seams:auto> block after the registration above.
136 </script>
137</body>
138</html>