← back to Prestige Hyperframes Promo
HyperFrames Prestige promo: 28s HTML->video, cloned-voice VO, FCFS/6-lines + 3 service clips + tip card + CTA
7e2a3d0acddf55c07744a1d90d56dae6d8698566 · 2026-07-12 10:22:27 -0700 · Steve Abrams
Files touched
A .gitignoreA my-video/AGENTS.mdA my-video/CLAUDE.mdA my-video/assets/promo-vo.wavA my-video/assets/svc-ceramic-coating.mp4A my-video/assets/svc-express-wash.mp4A my-video/assets/svc-hand-wash.mp4A my-video/assets/tip-marco.pngA my-video/hyperframes.jsonA my-video/index.htmlA my-video/meta.jsonA my-video/package.json
Diff
commit 7e2a3d0acddf55c07744a1d90d56dae6d8698566
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Jul 12 10:22:27 2026 -0700
HyperFrames Prestige promo: 28s HTML->video, cloned-voice VO, FCFS/6-lines + 3 service clips + tip card + CTA
---
.gitignore | 5 ++
my-video/AGENTS.md | 92 ++++++++++++++++++++
my-video/CLAUDE.md | 92 ++++++++++++++++++++
my-video/assets/promo-vo.wav | Bin 0 -> 2289742 bytes
my-video/assets/svc-ceramic-coating.mp4 | Bin 0 -> 8856767 bytes
my-video/assets/svc-express-wash.mp4 | Bin 0 -> 18929761 bytes
my-video/assets/svc-hand-wash.mp4 | Bin 0 -> 17357043 bytes
my-video/assets/tip-marco.png | Bin 0 -> 1848876 bytes
my-video/hyperframes.json | 9 ++
my-video/index.html | 150 ++++++++++++++++++++++++++++++++
my-video/meta.json | 5 ++
my-video/package.json | 11 +++
12 files changed, 364 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..eb54782
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+node_modules/
+renders/
+*.log
+.DS_Store
+.env*
diff --git a/my-video/AGENTS.md b/my-video/AGENTS.md
new file mode 100644
index 0000000..3e8a31a
--- /dev/null
+++ b/my-video/AGENTS.md
@@ -0,0 +1,92 @@
+# HyperFrames Composition Project
+
+## Skills — USE THESE FIRST
+
+**Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `window.__timelines` registration, `data-*` attribute semantics, shader-compatible CSS rules) that are NOT in generic web docs. Skipping them produces broken compositions.
+
+**Doing anything with HyperFrames?** Start at `/hyperframes` — it tells you what HyperFrames can do and which skill or workflow handles your intent (make a video, TTS / BGM, prep footage, author / animate, render, install blocks), and routes every "make me a…" request (a video, a deck, a composition port) to the right workflow. Read it first, especially when there's no project context to orient you. The workflows it routes to:
+
+- `/product-launch-video` — a **product** URL or brief / script → 60-90s product launch / SaaS / promo video.
+- `/website-to-video` — a **general** website / URL → a video _of_ the site (tour / showcase / social clip from captured visuals); a product **launch / promo** is `/product-launch-video`.
+- `/faceless-explainer` — arbitrary text (topic / article / notes), **no URL, no website capture** → 60-90s faceless explainer.
+- `/embedded-captions` — an existing talking-head video (MP4) → the same footage with captions / subtitles added (rail + embed, or pure-cinematic embed); the footage itself is untouched.
+- `/talking-head-recut` — an existing talking-head / interview / podcast video (MP4) → the same footage **packaged with designed graphic overlays** (kinetic titles, lower-thirds, data callouts, pull-quotes, side panels, pip) synced to the transcript; the clip plays unchanged underneath. (Plain captions/subtitles → `/embedded-captions`.)
+- `/pr-to-video` — a GitHub PR (URL / `owner/repo#N` / "this PR") → 30-90s code-change explainer (changelog / feature reveal / fix / refactor).
+- `/motion-graphics` — a short (typically under 10s) design-led **motion graphic**, motion-is-the-message, no narration: kinetic type, a stat / number count-up, a chart, a logo sting, a lower-third / overlay, or an animated tweet / headline / captured-page highlight; rendered to MP4 or a transparent overlay. Longer / narrated / custom → `/general-video`.
+- `/music-to-video` — a **music track** (audio file, or video to pull audio from) → beat-synced video (lyric / slideshow / kinetic promo). Music drives pacing; user-supplied images / videos are cut onto the same beat grid.
+- `/slideshow` — a **presentation / pitch deck / interactive deck** — discrete slides, fragment reveals, branching, hotspot navigation, presenter mode. Output is a navigable deck, not a rendered video.
+- `/general-video` — fallback for any other video (title card, longer brand / sizzle reel, multi-scene montage, static loop, custom composition); the original hyperframes authoring flow, any length.
+
+**Porting an existing composition?** `/remotion-to-hyperframes` translates a Remotion (React) composition into HyperFrames HTML — a source migration, separate from the creation workflows above.
+
+The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-keyframes`, `/hyperframes-creative`, `/hyperframes-cli`, `/media-use`, `/hyperframes-registry`, `/figma`) and the full capability map live inside `/hyperframes` — it is the single source of truth for which skill handles which intent.
+
+> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
+
+> **Skill missing or stale?** Run `npx hyperframes skills update <name>` to install/refresh
+> the specific skill you need (the `/hyperframes` router does this automatically before
+> entering a workflow), or bare `npx hyperframes skills update` to refresh the core set plus
+> everything already installed — neither pulls the full set. Restart the agent session so
+> newly installed skills load.
+
+## Commands
+
+```bash
+npm run dev # start the preview server (long-running — keep it alive in background)
+npm run check # lint + runtime + layout + motion + contrast (one command)
+npm run render # render to MP4
+npm run publish # publish and get a shareable link
+npx hyperframes lint --verbose # include info-level findings
+npx hyperframes lint --json # machine-readable output for CI
+npx hyperframes docs <topic> # reference docs in terminal
+```
+
+> **`npm run dev` is a long-running server, not a one-shot command.** It blocks until stopped.
+> In Claude Code, always run it with `run_in_background: true`. Never run it as a foreground
+> command — it will time out and the server will die, breaking the browser preview.
+
+## Documentation
+
+**For quick reference**, use the local CLI docs command (no network required):
+
+```bash
+npx hyperframes docs <topic>
+```
+
+Topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `examples`, `troubleshooting`
+
+**For full documentation**, discover pages via the machine-readable index — do NOT guess URLs:
+
+```
+https://hyperframes.heygen.com/llms.txt
+```
+
+## Project Structure
+
+- `index.html` — main composition (root timeline)
+- `compositions/` — sub-compositions referenced via `data-composition-src`
+- `meta.json` — project metadata (id, name)
+- `transcript.json` — whisper word-level transcript (if generated)
+
+## Linting — ALWAYS RUN AFTER CHANGES
+
+After creating or editing any `.html` composition, **always** run the full check before considering the task complete:
+
+```bash
+npm run check
+```
+
+Fix all errors before presenting the result. Warnings should be reviewed before rendering.
+
+## Key Rules
+
+1. Every timed element needs `data-start`, `data-duration`, and `data-track-index`
+2. Elements with timing **MUST** have `class="clip"` — the framework uses this for visibility control
+3. Timelines must be paused and registered on `window.__timelines`:
+ ```js
+ window.__timelines = window.__timelines || {};
+ window.__timelines["composition-id"] = gsap.timeline({ paused: true });
+ ```
+4. Videos use `muted` with a separate `<audio>` element for the audio track
+5. Sub-compositions use `data-composition-src="compositions/file.html"` to reference other HTML files
+6. Only deterministic logic — no `Date.now()`, no `Math.random()`, no network fetches
diff --git a/my-video/CLAUDE.md b/my-video/CLAUDE.md
new file mode 100644
index 0000000..3e8a31a
--- /dev/null
+++ b/my-video/CLAUDE.md
@@ -0,0 +1,92 @@
+# HyperFrames Composition Project
+
+## Skills — USE THESE FIRST
+
+**Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `window.__timelines` registration, `data-*` attribute semantics, shader-compatible CSS rules) that are NOT in generic web docs. Skipping them produces broken compositions.
+
+**Doing anything with HyperFrames?** Start at `/hyperframes` — it tells you what HyperFrames can do and which skill or workflow handles your intent (make a video, TTS / BGM, prep footage, author / animate, render, install blocks), and routes every "make me a…" request (a video, a deck, a composition port) to the right workflow. Read it first, especially when there's no project context to orient you. The workflows it routes to:
+
+- `/product-launch-video` — a **product** URL or brief / script → 60-90s product launch / SaaS / promo video.
+- `/website-to-video` — a **general** website / URL → a video _of_ the site (tour / showcase / social clip from captured visuals); a product **launch / promo** is `/product-launch-video`.
+- `/faceless-explainer` — arbitrary text (topic / article / notes), **no URL, no website capture** → 60-90s faceless explainer.
+- `/embedded-captions` — an existing talking-head video (MP4) → the same footage with captions / subtitles added (rail + embed, or pure-cinematic embed); the footage itself is untouched.
+- `/talking-head-recut` — an existing talking-head / interview / podcast video (MP4) → the same footage **packaged with designed graphic overlays** (kinetic titles, lower-thirds, data callouts, pull-quotes, side panels, pip) synced to the transcript; the clip plays unchanged underneath. (Plain captions/subtitles → `/embedded-captions`.)
+- `/pr-to-video` — a GitHub PR (URL / `owner/repo#N` / "this PR") → 30-90s code-change explainer (changelog / feature reveal / fix / refactor).
+- `/motion-graphics` — a short (typically under 10s) design-led **motion graphic**, motion-is-the-message, no narration: kinetic type, a stat / number count-up, a chart, a logo sting, a lower-third / overlay, or an animated tweet / headline / captured-page highlight; rendered to MP4 or a transparent overlay. Longer / narrated / custom → `/general-video`.
+- `/music-to-video` — a **music track** (audio file, or video to pull audio from) → beat-synced video (lyric / slideshow / kinetic promo). Music drives pacing; user-supplied images / videos are cut onto the same beat grid.
+- `/slideshow` — a **presentation / pitch deck / interactive deck** — discrete slides, fragment reveals, branching, hotspot navigation, presenter mode. Output is a navigable deck, not a rendered video.
+- `/general-video` — fallback for any other video (title card, longer brand / sizzle reel, multi-scene montage, static loop, custom composition); the original hyperframes authoring flow, any length.
+
+**Porting an existing composition?** `/remotion-to-hyperframes` translates a Remotion (React) composition into HyperFrames HTML — a source migration, separate from the creation workflows above.
+
+The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-keyframes`, `/hyperframes-creative`, `/hyperframes-cli`, `/media-use`, `/hyperframes-registry`, `/figma`) and the full capability map live inside `/hyperframes` — it is the single source of truth for which skill handles which intent.
+
+> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
+
+> **Skill missing or stale?** Run `npx hyperframes skills update <name>` to install/refresh
+> the specific skill you need (the `/hyperframes` router does this automatically before
+> entering a workflow), or bare `npx hyperframes skills update` to refresh the core set plus
+> everything already installed — neither pulls the full set. Restart the agent session so
+> newly installed skills load.
+
+## Commands
+
+```bash
+npm run dev # start the preview server (long-running — keep it alive in background)
+npm run check # lint + runtime + layout + motion + contrast (one command)
+npm run render # render to MP4
+npm run publish # publish and get a shareable link
+npx hyperframes lint --verbose # include info-level findings
+npx hyperframes lint --json # machine-readable output for CI
+npx hyperframes docs <topic> # reference docs in terminal
+```
+
+> **`npm run dev` is a long-running server, not a one-shot command.** It blocks until stopped.
+> In Claude Code, always run it with `run_in_background: true`. Never run it as a foreground
+> command — it will time out and the server will die, breaking the browser preview.
+
+## Documentation
+
+**For quick reference**, use the local CLI docs command (no network required):
+
+```bash
+npx hyperframes docs <topic>
+```
+
+Topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `examples`, `troubleshooting`
+
+**For full documentation**, discover pages via the machine-readable index — do NOT guess URLs:
+
+```
+https://hyperframes.heygen.com/llms.txt
+```
+
+## Project Structure
+
+- `index.html` — main composition (root timeline)
+- `compositions/` — sub-compositions referenced via `data-composition-src`
+- `meta.json` — project metadata (id, name)
+- `transcript.json` — whisper word-level transcript (if generated)
+
+## Linting — ALWAYS RUN AFTER CHANGES
+
+After creating or editing any `.html` composition, **always** run the full check before considering the task complete:
+
+```bash
+npm run check
+```
+
+Fix all errors before presenting the result. Warnings should be reviewed before rendering.
+
+## Key Rules
+
+1. Every timed element needs `data-start`, `data-duration`, and `data-track-index`
+2. Elements with timing **MUST** have `class="clip"` — the framework uses this for visibility control
+3. Timelines must be paused and registered on `window.__timelines`:
+ ```js
+ window.__timelines = window.__timelines || {};
+ window.__timelines["composition-id"] = gsap.timeline({ paused: true });
+ ```
+4. Videos use `muted` with a separate `<audio>` element for the audio track
+5. Sub-compositions use `data-composition-src="compositions/file.html"` to reference other HTML files
+6. Only deterministic logic — no `Date.now()`, no `Math.random()`, no network fetches
diff --git a/my-video/assets/promo-vo.wav b/my-video/assets/promo-vo.wav
new file mode 100644
index 0000000..7dc13b8
Binary files /dev/null and b/my-video/assets/promo-vo.wav differ
diff --git a/my-video/assets/svc-ceramic-coating.mp4 b/my-video/assets/svc-ceramic-coating.mp4
new file mode 100644
index 0000000..01e433c
Binary files /dev/null and b/my-video/assets/svc-ceramic-coating.mp4 differ
diff --git a/my-video/assets/svc-express-wash.mp4 b/my-video/assets/svc-express-wash.mp4
new file mode 100644
index 0000000..3d3a00b
Binary files /dev/null and b/my-video/assets/svc-express-wash.mp4 differ
diff --git a/my-video/assets/svc-hand-wash.mp4 b/my-video/assets/svc-hand-wash.mp4
new file mode 100644
index 0000000..39d0c43
Binary files /dev/null and b/my-video/assets/svc-hand-wash.mp4 differ
diff --git a/my-video/assets/tip-marco.png b/my-video/assets/tip-marco.png
new file mode 100644
index 0000000..ddfc442
Binary files /dev/null and b/my-video/assets/tip-marco.png differ
diff --git a/my-video/hyperframes.json b/my-video/hyperframes.json
new file mode 100644
index 0000000..5fb1d6d
--- /dev/null
+++ b/my-video/hyperframes.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://hyperframes.heygen.com/schema/hyperframes.json",
+ "registry": "https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry",
+ "paths": {
+ "blocks": "compositions",
+ "components": "compositions/components",
+ "assets": "assets"
+ }
+}
diff --git a/my-video/index.html b/my-video/index.html
new file mode 100644
index 0000000..7b80ac5
--- /dev/null
+++ b/my-video/index.html
@@ -0,0 +1,150 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=1920, height=1080" />
+ <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
+ <style>
+ * { margin: 0; padding: 0; box-sizing: border-box; }
+ html, body { width: 1920px; height: 1080px; overflow: hidden; background: #05090f; }
+ body { font-family: "Inter", "SF Pro Display", system-ui, sans-serif; color: #eaf2ff; }
+ .full-bleed { position: absolute; inset: 0; width: 1920px; height: 1080px; }
+ .fill-video { position: absolute; inset: 0; width: 1920px; height: 1080px; object-fit: cover; }
+ .scene { position: absolute; inset: 0; display: flex; flex-direction: column;
+ align-items: center; justify-content: center; text-align: center; }
+ .eyebrow { font-weight: 800; font-size: 30px; letter-spacing: 8px; text-transform: uppercase; color: #38bdf8; }
+ .title { font-weight: 900; font-size: 130px; line-height: 1; text-shadow: 0 10px 50px rgba(0,0,0,.6); }
+ .sub { font-weight: 500; font-size: 40px; color: #c2d2e8; margin-top: 18px; }
+ .left { align-items: flex-start; justify-content: flex-end; text-align: left; padding: 0 0 150px 110px; }
+ .cat { display: inline-flex; align-items: center; gap: 12px; padding: 10px 20px; border-radius: 999px;
+ background: rgba(56,189,248,.16); border: 1px solid rgba(56,189,248,.45);
+ color: #38bdf8; font-weight: 800; font-size: 26px; letter-spacing: 3px; text-transform: uppercase; }
+ .svc-name { font-weight: 900; font-size: 96px; margin-top: 20px; text-shadow: 0 8px 40px rgba(0,0,0,.8); }
+ .price { font-weight: 900; font-size: 130px; line-height: .9; color: #38bdf8; text-shadow: 0 0 44px rgba(56,189,248,.5); }
+ .scrim-lr { background: linear-gradient(90deg, rgba(5,9,15,.92) 0%, rgba(5,9,15,.45) 44%, rgba(5,9,15,0) 70%); }
+ .stat { font-weight: 900; font-size: 76px; color: #eaf2ff; }
+ .statlbl { font-weight: 600; font-size: 30px; color: #9fb3cd; letter-spacing: 1px; }
+ .strike { position: absolute; left: 0; top: 54%; height: 12px; background: #fb7185; border-radius: 8px; }
+ .row { display: flex; gap: 80px; margin-top: 44px; }
+ </style>
+ </head>
+ <body>
+ <div id="root" data-composition-id="main" data-start="0" data-duration="28"
+ data-width="1920" data-height="1080">
+
+ <!-- shared animated background (NOT a clip) -->
+ <div id="bg" class="full-bleed"
+ style="background: radial-gradient(60% 60% at 30% 30%, #38bdf822 0%, transparent 60%), linear-gradient(160deg,#0a1424 0%,#0b1728 50%,#060c16 100%);"></div>
+
+ <!-- host audio: cloned-voice VO (root child) -->
+ <audio id="vo" src="assets/promo-vo.wav" data-start="0" data-volume="1"></audio>
+
+ <!-- service video clips (root children, muted, visibility by data-start/duration) -->
+ <video id="v-express" class="fill-video" muted playsinline preload="auto"
+ src="assets/svc-express-wash.mp4" data-start="8.8" data-duration="4.4" data-media-start="0"></video>
+ <video id="v-hand" class="fill-video" muted playsinline preload="auto"
+ src="assets/svc-hand-wash.mp4" data-start="13.0" data-duration="4.2" data-media-start="0"></video>
+ <video id="v-ceramic" class="fill-video" muted playsinline preload="auto"
+ src="assets/svc-ceramic-coating.mp4" data-start="17.0" data-duration="3.2" data-media-start="0"></video>
+
+ <!-- readability scrim over the service montage -->
+ <div id="scrim" class="clip full-bleed scrim-lr" data-start="8.8" data-duration="11.4" data-track-index="2"></div>
+
+ <!-- ── Scene 1: title (0–4.4) ── -->
+ <section id="s-title" class="clip scene" data-start="0" data-duration="4.2" data-track-index="3">
+ <div id="t-eyebrow" class="eyebrow">San Fernando Valley</div>
+ <div id="t-title" class="title">Prestige<br/>Car Wash</div>
+ <div id="t-sub" class="sub">Hand wash · Detail · Ceramic</div>
+ </section>
+
+ <!-- ── Scene 2: the model (4.2–8.8) ── -->
+ <section id="s-model" class="clip scene" data-start="4.2" data-duration="4.6" data-track-index="3">
+ <div style="position:relative; display:inline-block;">
+ <div id="m-head" class="title" style="font-size:104px;">No Appointments</div>
+ <div id="m-strike" class="strike" style="width:0;"></div>
+ </div>
+ <div id="m-fcfs" class="sub" style="font-weight:800; font-size:56px; color:#38bdf8; margin-top:22px;">First Come · First Served</div>
+ <div id="m-stats" class="row">
+ <div><div id="m-6" class="stat">6</div><div class="statlbl">full lines</div></div>
+ <div><div class="stat">Large</div><div class="statlbl">crew on deck</div></div>
+ <div><div class="stat">0</div><div class="statlbl">wait to book</div></div>
+ </div>
+ </section>
+
+ <!-- ── Scene 3: Express (8.8–13) ── -->
+ <section id="s-express" class="clip scene left" data-start="8.8" data-duration="4.2" data-track-index="3">
+ <div class="cat"><span style="width:10px;height:10px;border-radius:10px;background:#38bdf8;"></span> Wash</div>
+ <div class="svc-name">Express Exterior Wash</div>
+ <div id="p-express" class="price">$19</div>
+ </section>
+
+ <!-- ── Scene 4: Hand Wash (13–17) ── -->
+ <section id="s-hand" class="clip scene left" data-start="13.0" data-duration="4.0" data-track-index="3">
+ <div class="cat"><span style="width:10px;height:10px;border-radius:10px;background:#38bdf8;"></span> Signature</div>
+ <div class="svc-name">Premium Hand Wash</div>
+ <div id="p-hand" class="price">$79</div>
+ </section>
+
+ <!-- ── Scene 5: Ceramic (17–20.2) ── -->
+ <section id="s-ceramic" class="clip scene left" data-start="17.0" data-duration="3.2" data-track-index="3">
+ <div class="cat" style="background:rgba(52,211,153,.16);border-color:rgba(52,211,153,.45);color:#34d399;">
+ <span style="width:10px;height:10px;border-radius:10px;background:#34d399;"></span> Protection</div>
+ <div class="svc-name">Ceramic Coating · 9H</div>
+ <div id="p-ceramic" class="price" style="color:#34d399;text-shadow:0 0 44px rgba(52,211,153,.5);">from $999</div>
+ </section>
+
+ <!-- ── Scene 6: Tips (20.2–24) ── -->
+ <section id="s-tips" class="clip scene" data-start="20.2" data-duration="3.8" data-track-index="3">
+ <div id="tip-head" class="title" style="font-size:80px;">Tip the crew directly</div>
+ <div class="sub" style="margin-top:10px;">Scan their card — 100% goes straight to them.</div>
+ <img id="tip-card" src="assets/tip-marco.png" style="height:520px; margin-top:26px; border-radius:22px; box-shadow:0 30px 90px rgba(0,0,0,.7);" />
+ </section>
+
+ <!-- ── Scene 7: CTA (24–28) ── -->
+ <section id="s-cta" class="clip scene" data-start="24.0" data-duration="4.0" data-track-index="3">
+ <div id="c-eyebrow" class="eyebrow" style="color:#34d399;">No appointment · 6 lines · just drive up</div>
+ <div id="c-title" class="title" style="font-size:120px;">Come See Us</div>
+ <div id="c-sub" class="sub" style="font-weight:800;">Prestige Car Wash</div>
+ </section>
+ </div>
+
+ <script>
+ window.__timelines = window.__timelines || {};
+ const tl = gsap.timeline({ paused: true });
+
+ // shared background hue drift across the piece
+ tl.to("#bg", { filter: "hue-rotate(-18deg)", duration: 8.8, ease: "sine.inOut" }, 8.8)
+ .to("#bg", { filter: "hue-rotate(8deg)", duration: 7.8, ease: "sine.inOut" }, 20.2);
+
+ // Scene 1 — title
+ tl.from("#t-eyebrow", { opacity: 0, y: 20, duration: 0.5 }, 0.2)
+ .from("#t-title", { opacity: 0, y: 46, duration: 0.7, ease: "power3.out" }, 0.5)
+ .from("#t-sub", { opacity: 0, y: 20, duration: 0.5 }, 1.1);
+
+ // Scene 2 — model
+ tl.from("#m-head", { opacity: 0, scale: 0.9, duration: 0.5, ease: "back.out(1.6)" }, 4.4)
+ .to("#m-strike", { width: 620, duration: 0.5, ease: "power2.out" }, 4.9)
+ .from("#m-fcfs", { opacity: 0, y: 18, duration: 0.5 }, 5.0)
+ .from("#m-stats", { opacity: 0, y: 24, duration: 0.6 }, 5.6);
+
+ // Service scenes — cat + name + price pop
+ [["express", 8.8], ["hand", 13.0], ["ceramic", 17.0]].forEach(function (row) {
+ var k = row[0], t = row[1];
+ tl.from("#s-" + k + " .cat", { opacity: 0, x: -30, duration: 0.4 }, t + 0.15)
+ .from("#s-" + k + " .svc-name", { opacity: 0, y: 24, duration: 0.5 }, t + 0.3)
+ .from("#p-" + k, { opacity: 0, scale: 0.6, duration: 0.5, ease: "back.out(1.7)" }, t + 0.5);
+ });
+
+ // Scene 6 — tips
+ tl.from("#tip-head", { opacity: 0, y: 20, duration: 0.5 }, 20.4)
+ .from("#tip-card", { opacity: 0, y: 120, duration: 0.7, ease: "power3.out" }, 20.7);
+
+ // Scene 7 — CTA
+ tl.from("#c-eyebrow", { opacity: 0, y: 16, duration: 0.5 }, 24.2)
+ .from("#c-title", { opacity: 0, scale: 0.85, duration: 0.6, ease: "back.out(1.5)" }, 24.5)
+ .from("#c-sub", { opacity: 0, y: 16, duration: 0.5 }, 25.1);
+
+ window.__timelines["main"] = tl;
+ </script>
+ </body>
+</html>
diff --git a/my-video/meta.json b/my-video/meta.json
new file mode 100644
index 0000000..2018bed
--- /dev/null
+++ b/my-video/meta.json
@@ -0,0 +1,5 @@
+{
+ "id": "my-video",
+ "name": "my-video",
+ "createdAt": "2026-07-12T17:16:03.017Z"
+}
\ No newline at end of file
diff --git a/my-video/package.json b/my-video/package.json
new file mode 100644
index 0000000..dc977d9
--- /dev/null
+++ b/my-video/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "my-video",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "npx --yes hyperframes@0.7.54 preview",
+ "check": "npx --yes hyperframes@0.7.54 check",
+ "render": "npx --yes hyperframes@0.7.54 render",
+ "publish": "npx --yes hyperframes@0.7.54 publish"
+ }
+}
(oldest)
·
back to Prestige Hyperframes Promo
·
(newest)