{"id":"c57bc149-60c7-49ff-b277-8beaa807032d","entityType":"agent","slug":"clawhub-heygen-com-website-to-video","name":"Website To Video","canonicalUrl":"https://www.xpersona.co/agent/clawhub-heygen-com-website-to-video","canonicalPath":"/agent/clawhub-heygen-com-website-to-video","generatedAt":"2026-10-11T21:54:07.485Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-11T18:59:34.932Z","emptyReason":null},"description":"Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand... Skill: Website To Video Owner: heygen-com Summary: Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand... Tags: latest:1.0.7 Version history: v1.0.7 | 2026-07-10T22:50:42.522Z | user Synced from 00d059b (main) v1.0.6 | 2026-07-10T02:58:02.499Z | user Synced from a8f242e (main) v1.0.5 | 2026-07-08T18:02:16.584Z | u","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17fpgb0p797dzkbtbrxw5x1hh89qs64:website-to-video","sourceUrl":"https://clawhub.ai/heygen-com/website-to-video","homepage":"https://clawhub.ai/heygen-com/skills/website-to-video","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/heygen-com/website-to-video","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/heygen-com/skills/website-to-video","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand... "},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T18:59:34.932Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T18:59:34.932Z","emptyReason":null},"stars":null,"forks":null,"downloads":1006,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"1.0.7","tractionLabel":"1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T18:59:34.873Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T18:59:34.932Z","lastCrawledAt":"2026-10-11T18:59:34.873Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T18:59:34.873Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.7","createdAt":"2026-07-10T22:50:42.522Z","changelog":"Synced from 00d059b (main)","fileCount":15,"zipByteSize":109251},{"version":"1.0.6","createdAt":"2026-07-10T02:58:02.499Z","changelog":"Synced from a8f242e (main)","fileCount":15,"zipByteSize":109284},{"version":"1.0.5","createdAt":"2026-07-08T18:02:16.584Z","changelog":"Synced from 17b8527 (main)","fileCount":15,"zipByteSize":109117},{"version":"1.0.4","createdAt":"2026-07-08T17:34:07.241Z","changelog":"Synced from 81884a7 (main)","fileCount":15,"zipByteSize":108828},{"version":"1.0.3","createdAt":"2026-07-08T16:00:31.778Z","changelog":"Synced from 4d3cdc3 (main)","fileCount":15,"zipByteSize":108712},{"version":"1.0.2","createdAt":"2026-07-07T20:29:22.284Z","changelog":"Synced from 7286b00 (main)","fileCount":15,"zipByteSize":108722},{"version":"1.0.1","createdAt":"2026-07-07T19:01:13.358Z","changelog":"Synced from 5fe9573 (main)","fileCount":15,"zipByteSize":108568},{"version":"1.0.0","createdAt":"2026-07-01T12:07:18.391Z","changelog":"Official HyperFrames skills from heygen-com/hyperframes","fileCount":15,"zipByteSize":108682}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17fpgb0p797dzkbtbrxw5x1hh89qs64:website-to-video","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T21:54:07.482Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-heygen-com-website-to-video/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-11T18:59:34.932Z","emptyReason":null},"readme":"Skill: Website To Video\n\nOwner: heygen-com\n\nSummary: Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand...\n\nTags: latest:1.0.7\n\nVersion history:\n\nv1.0.7 | 2026-07-10T22:50:42.522Z | user\n\nSynced from 00d059b (main)\n\nv1.0.6 | 2026-07-10T02:58:02.499Z | user\n\nSynced from a8f242e (main)\n\nv1.0.5 | 2026-07-08T18:02:16.584Z | user\n\nSynced from 17b8527 (main)\n\nv1.0.4 | 2026-07-08T17:34:07.241Z | user\n\nSynced from 81884a7 (main)\n\nv1.0.3 | 2026-07-08T16:00:31.778Z | user\n\nSynced from 4d3cdc3 (main)\n\nv1.0.2 | 2026-07-07T20:29:22.284Z | user\n\nSynced from 7286b00 (main)\n\nv1.0.1 | 2026-07-07T19:01:13.358Z | user\n\nSynced from 5fe9573 (main)\n\nv1.0.0 | 2026-07-01T12:07:18.391Z | user\n\nOfficial HyperFrames skills from heygen-com/hyperframes\n\nArchive index:\n\nArchive v1.0.7: 15 files, 109251 bytes\n\nFiles: assets/sfx/CREDITS.md (1183b), assets/sfx/manifest.json (4313b), references/beat-builder-guide.md (20886b), references/capabilities.md (57750b), references/step-0-capture.md (4087b), references/step-1-design.md (20761b), references/step-2-brief.md (14955b), references/step-3-storyboard.md (49367b), references/step-4-vo.md (13180b), references/step-5-build.md (28215b), references/step-6-validate.md (23447b), scripts/w2h-verify.mjs (28755b), skill-card.md (2593b), SKILL.md (12743b), _meta.json (135b)\n\nFile v1.0.7:SKILL.md\n\n---\nname: website-to-video\ndescription: \"Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand assets. Use for portfolio / blog / docs / landing-page showcases. Not a product launch or promo, even from a URL (/product-launch-video). Unclear → /hyperframes.\"\n---\n\n> **First, keep this skill fresh — run silently, don't ask:** `npx hyperframes skills update website-to-video`. A fast no-op when everything is current; otherwise it refreshes this skill plus the core domain skills it depends on before you rely on them.\n\n> **media-use**: Before sourcing audio/images/logos, call `/media-use` to resolve BGM/SFX/images from the HeyGen catalog and brand logos from their official sources. Run `--adopt` first to register existing assets. See `/media-use` skill.\n\n> **figma source**: If the URL is a figma.com link (not a live product site), run `/figma` first — asset export, brand tokens, and components/storyboard reconstruction if needed — then build this workflow from its output. Don't drive Figma via raw MCP tools directly: that skips SVG sanitization, `.media/manifest.jsonl` provenance, and brand-token `var()` binding, so a later brand change can't propagate without a full re-import.\n\n# Website to HyperFrames\n\nCapture a website, then produce a professional video from it.\n\n> **Confirm the route before Step 0.** This skill makes a video _of / from a general site_. If the user is really **marketing / launching / promoting a product** (even from this URL, even \"promo for our site\") → `/product-launch-video`. A **topic explainer with no site** → `/faceless-explainer`; a **GitHub PR** → `/pr-to-video`; **re-cutting / recoloring / reordering an existing video file** → out of scope. Routed here on a vague \"make a video\", or unsure launch-vs-general-site? **Read `/hyperframes` first** (full routing table + § What HyperFrames cannot do).\n\nUsers say things like:\n\n- \"Turn this website into a 15-second social clip for Instagram\"\n- \"Make a 30-second site tour / showcase from https://...\"\n- \"Capture our homepage and build a video from its own visuals\"\n\nThe workflow has 7 steps. Each produces an artifact that gates the next. By default it's collaborative — gates marked 💬 stop and ask the user. Mode semantics (signals, propagation, gate taxonomy) are canonical in `../hyperframes-core/references/brief-contract.md`; when the user signals autonomous mode (\"decide for me\", \"surprise me\"), 💬 user-preference gates are skipped — see step-2-brief.md for how that propagates through this workflow.\n\n**Autonomous mode is NOT \"skip all gates\"** (brief contract § 1). It covers user-preference questions (TTS provider, voice, color emphasis, beat count, music yes/no, captions yes/no — where the agent decides on the user's behalf). It does NOT cover quality-verification gates. The following remain non-skippable in auto mode:\n\n- Asset Audit (Step 3) — viewing contact sheets and justifying USE/SKIP for each asset\n- Per-beat HTML read (Step 5) — structured evidence block per beat\n- DoD checklist (Step 6) — including animation-map, per-warning WCAG verification, audio/motion playback\n- Honest disclosure section (Step 6) — \"What I did NOT verify\" must appear in your final summary\n\nIf you find yourself reasoning \"auto mode says bias toward action, so I'll skip X\" — and X is a verification gate, not a preference question — that reasoning is wrong. Bias toward action applies to deciding _what to build_, not to deciding _whether to verify_.\n\n---\n\n## Step 0: Capture & Understand the Brand\n\n**Read:** [references/step-0-capture.md](references/step-0-capture.md)\n\nCapture the site, then read the extracted data to understand the **brand and product** — what it does, who it's for, what voice it speaks in, what mood it lives in. The captured assets are a brand toolkit for later, not the building blocks the video is made from.\n\n**Show sign-in status before the brief** — run `npx hyperframes auth status` and **relay its output verbatim (don't paraphrase or rewrite it).** It reports whether voice/BGM will use HeyGen or local engines and, when not signed in, how to sign in. **If not signed in, STOP and wait for the user to choose — sign in, or say \"go\"/\"offline\" to continue with local engines — before asking the brief or anything else.** Treat it as a real decision point, not a passing note; don't fold the choice into the brief question, and don't write keys into a per-repo `.env`. (In autonomous mode, note the status and continue offline.) See `../media-use` → Preflight for the canonical guidance.\n\n**Gate:** Site summary printed — strategy-first (what the product does, who it's for, brand voice) before the asset / color / font inventory; sign-in status was shown (signed in, or continuing offline).\n\n---\n\n## Step 1: Brand Identity\n\n**Read:** [references/step-1-design.md](references/step-1-design.md)\n\nWrite DESIGN.md — a brand cheat sheet covering the visual identity: colors, typography, component styles, layout principles. Use `design-styles.json` for exact computed values.\n\n**Speed option:** For fast-pacing videos (billboard-per-beat), DESIGN.md can be a 50-line summary of colors + fonts + do's/don'ts — not a 300-line document. The sub-agent prompt in Step 5 pastes brand values directly, so DESIGN.md depth only matters for complex compositions.\n\n**Gate:** `DESIGN.md` exists (any length) with at minimum: color palette, font choices, and do's/don'ts.\n\n---\n\n## Step 2: Strategy & Messaging\n\n**Read:** [references/step-2-brief.md](references/step-2-brief.md), [references/capabilities.md](references/capabilities.md) (scan the Table of Contents — deep-dive sections only as needed)\n\nAlign with the user on **what the video must communicate** before talking visuals or assets. Parse the user's prompt — they probably already gave you the video type and style. Ask only what's missing: the ONE thing this video must say, the narrative arc, and the audience.\n\n**Gate:** Video type, duration, format, and — critically — the message and narrative arc are locked. Without those, Step 3 can't write a concept-first storyboard.\n\n---\n\n## Step 3: Storyboard + Script 💬\n\n**Read:** [references/step-3-storyboard.md](references/step-3-storyboard.md)\n\nWrite the storyboard concept-first: message → narrative arc → beats that serve the arc → techniques per beat → brand accents pass at the end. Then write the narration script to match. Present both to the user with a beat-by-beat summary. Iterate until they approve.\n\n**Gate:** `STORYBOARD.md` + `SCRIPT.md` exist AND the user has approved the plan.\n\n---\n\n## Step 4: VO, Timing + Captions 💬\n\n**Read:** [references/step-4-vo.md](references/step-4-vo.md)\n\nIf Step 2 said no narration — ask about background music, then skip to Step 5. Otherwise: ask the user which TTS provider (HeyGen TTS, ElevenLabs, or Kokoro), generate audio, transcribe, map timestamps to beats. Then ask about captions.\n\n**Gate:** Either (a) no narration was requested and storyboard has manual beat timings, or (b) `narration.wav` + `transcript.json` exist and beat timings updated with real durations.\n\n---\n\n## Step 5: Build Compositions\n\n**Read:** The `hyperframes` skill (load it — every rule matters)\n**Read:** [references/step-5-build.md](references/step-5-build.md)\n\nBuild index.html and compositions following the architecture and pacing chosen in the storyboard (Step 3). Sub-agents run `hyperframes lint` and `hyperframes snapshot` on each beat before reporting back.\n\n**Gate:** Every `compositions/beat-N.html` has been read top-to-bottom by the main agent against DESIGN.md and STORYBOARD.md. The per-beat checklist lives in [step-5-build.md](references/step-5-build.md).\n\n---\n\n## Step 6: Validate & Deliver\n\n**Read:** [references/step-6-validate.md](references/step-6-validate.md)\n\nLint, validate, take snapshots scaled to video length (formula: `max(beats × 3, ceil(duration_seconds / 2))`), and review each one. Fix issues before delivering. Deliver the localhost Studio project URL — only render to MP4 on explicit user request. Surface that Studio URL **only at handoff** — it is the final, stable preview; the build-phase snapshots are headless, so do not pop a preview mid-build.\n\n**Deliver something you're proud of.** Before handing off, ask yourself: would I post this on social media with my name on it? If not, fix what's wrong.\n\n**Gate:** `npx hyperframes check` pass with zero errors, and the final response includes the active Studio project URL.\n\n---\n\n## Quick Reference\n\n### Video Types\n\nTypical constraints by video type — use as a starting point, not a formula. Beat count should follow from the content and the narration, not from a target range.\n\n| Type                    | Typical duration | Duration driver    | Narration             |\n| ----------------------- | ---------------- | ------------------ | --------------------- |\n| Social clip (IG/TikTok) | 10–15s           | Platform limit     | Optional              |\n| Site walkthrough        | 30–60s           | Script length      | Full narration        |\n| Content announcement    | 15–30s           | Content complexity | Full narration        |\n| Brand reel              | 20–45s           | Music track        | Optional, music focus |\n\n(A product demo, feature announcement, or launch teaser that _sells_ the product belongs to `/product-launch-video` — see the routing note at the top.)\n\nBeat count is not in this table intentionally — it should come from the storyboard, not from \"social ad = 3-4 beats.\" A social ad for a complex product might need 5 well-timed beats. A brand reel with one strong visual thesis might need 3.\n\n### Format\n\n- **Landscape**: 1920x1080 (default)\n- **Portrait**: 1080x1920 (Instagram Stories, TikTok)\n- **Square**: 1080x1080 (Instagram feed)\n\n### Reference Files\n\n| File                                                                               | When to read                                                                                                                                   |\n| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| [step-0-capture.md](references/step-0-capture.md)                                  | Step 0 — capture, understand the brand and product, write strategy-first site summary                                                          |\n| [step-1-design.md](references/step-1-design.md)                                    | Step 1 — write DESIGN.md brand cheat sheet (5 sections, 250-350 lines; 50-line fast-path for billboard-style social ads)                       |\n| [step-2-brief.md](references/step-2-brief.md)                                      | Step 2 — align on message, narrative arc, audience with user                                                                                   |\n| [capabilities.md](references/capabilities.md)                                      | Steps 2 & 5 — full inventory of what HyperFrames can do (24 sections). Scan the TOC during the brief, deep-dive specific sections during build |\n| [step-3-storyboard.md](references/step-3-storyboard.md)                            | Step 3 — storyboard + script (combined) with user review gate                                                                                  |\n| [step-4-vo.md](references/step-4-vo.md)                                            | Step 4 — TTS provider choice, generation, timing                                                                                               |\n| [step-5-build.md](references/step-5-build.md)                                      | Step 5 — build index.html + compositions                                                                                                       |\n| [step-6-validate.md](references/step-6-validate.md)                                | Step 6 — lint, validate, snapshots (scaled to video length), preview                                                                           |\n| [techniques.md](../hyperframes/references/techniques.md)                           | Steps 3 & 5 — 13 primitive animation techniques with code patterns (adapt, don't copy-paste)                                                   |\n| [html-in-canvas-patterns.md](../hyperframes/references/html-in-canvas-patterns.md) | Step 5 — complete code patterns for HTML-in-Canvas effects (lives in the hyperframes skill)                                                    |\n\nFile v1.0.7:_meta.json\n\n{\n  \"ownerId\": \"kn77d06grj6xqp3dqwkk4bavhn89pegt\",\n  \"slug\": \"website-to-video\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1783723842522\n}\n\nFile v1.0.7:references/beat-builder-guide.md\n\n# Beat Builder Guide\n\nYou are building ONE beat of a multi-beat video composition. This file tells you what to read, how to build, how to verify, and how to report back.\n\n## Step 1: Read and understand\n\n**Required (every beat):**\n\n1. **Load the `hyperframes` skill** — composition rules, data attributes, timeline contract, deterministic rendering. Read the whole skill.\n2. **[capabilities.md](capabilities.md)** — full inventory of HyperFrames capabilities (24 sections). Read the Table of Contents first, then deep-dive sections your beat needs.\n3. **The beat spec** the main agent gave you — concept, choreography, assets, brand values, timing.\n\n**Read based on what your beat needs (pick relevant ones):**\n\n| Resource                                                                              | What it covers                                                                                                                | Read when                                         |\n| ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |\n| [techniques.md](../../hyperframes/references/techniques.md)                           | 13 primitive animation techniques: SVG path drawing, Canvas 2D, CSS 3D, kinetic type, variable fonts, MotionPath, etc.        | Beat uses any of these techniques                 |\n| [text-effects.md](../../hyperframes/references/text-effects.md)                       | 24 named text animations from `pixel-point/animate-text` (separate skill — load via `/animate-text` for specs)                | Beat has text animation                           |\n| [html-in-canvas-patterns.md](../../hyperframes/references/html-in-canvas-patterns.md) | HTML-in-Canvas: iPhone/MacBook mockups, liquid glass, magnetic, portal, shatter, text cursor                                  | Beat uses device mockups or WebGL effects on HTML |\n| [transitions.md](../../hyperframes/references/transitions.md)                         | Shader transition API, HyperShader.init() pattern, all 14 WebGL shaders                                                       | Beat has shader transitions                       |\n| [transitions/](../../hyperframes/references/transitions/)                             | 14 CSS transition category files: push, scale, dissolve, blur, 3D flip, light leak, distortion, grid, mechanical, destruction | Beat uses CSS transitions                         |\n| [css-patterns.md](../../hyperframes/references/css-patterns.md)                       | Text markers: highlight sweeps, hand-drawn circles, burst lines, scribble, sketchout                                          | Beat uses text emphasis/markers                   |\n| [audio-reactive.md](../../hyperframes/references/audio-reactive.md)                   | Bass→scale, mid→shape, treble→glow mappings                                                                                   | Beat reacts to music/audio                        |\n| [captions.md](../../hyperframes/references/captions.md)                               | Per-word karaoke, tone-adaptive styling, positioning                                                                          | Beat includes captions                            |\n| [typography.md](../../hyperframes/references/typography.md)                           | Font hierarchy, variable fonts, responsive type scaling                                                                       | Beat has complex typography                       |\n| [motion-principles.md](../../hyperframes/references/motion-principles.md)             | Velocity matching, easing philosophy, motion continuity                                                                       | Beat needs polished motion design                 |\n| [dynamic-techniques.md](../../hyperframes/references/dynamic-techniques.md)           | Counter animations, data-driven visuals, dynamic content                                                                      | Beat has counters or data visualization           |\n| [video-composition.md](../../hyperframes/references/video-composition.md)             | Frame composition, color presence, scale, density rules                                                                       | General composition quality                       |\n\n**Other skills you can load if needed:**\n\n- `/gsap` or `/gsap-core`, `/gsap-timeline`, `/gsap-plugins` — deeper GSAP reference\n- `/animate-text` — curated text animation catalog with exact JSON specs\n- `/hyperframes-registry` — if you need to install and wire registry blocks\n- `/hyperframes-contrast` — audit color contrast (WCAG)\n- `/lottie`, `/three`, `/waapi`, `/animejs`, `/css-animations` — if beat uses these engines\n\n**Always open the captured assets folder before designing the beat:**\n\n- `capture/assets/svgs/` — brand logos, icons, decorative marks. SVGs are infinitely scalable and stroke-animatable (path drawing, dash offset). A logo SVG drawing itself onto frame can carry an entire beat.\n- `capture/assets/` — hero illustrations, screenshots, product art, gradients, photography. These are first-class beat subjects, not background decoration. A breathing hero illustration with a single line of kinetic type is a complete shot.\n- VIEW every image before placing text on it. Check safe zones, contrast, actual content, where the focal point sits.\n\n**If your beat spec names a captured asset, USE it.** Don't substitute a CSS recreation. The user captured these from the real brand site precisely so the video carries the brand's actual visual identity.\n\n## Step 2: Build the composition\n\nSave to the path the main agent specified (usually `compositions/beat-N-name.html`).\n\n```html\n<template>\n  <style>\n    * {\n      margin: 0;\n      padding: 0;\n      box-sizing: border-box;\n    }\n    /* your styles */\n  </style>\n\n  <div\n    id=\"beat-N-name\"\n    data-composition-id=\"beat-N-name\"\n    data-width=\"1920\"\n    data-height=\"1080\"\n    style=\"width:1920px; height:1080px; position:relative; overflow:hidden; background:#YOUR_BG;\"\n  >\n    <!-- your elements -->\n  </div>\n\n  <script>\n    (function () {\n      var BEAT = 5.5; // MUST match data-duration on the host div in index.html\n      window.__timelines = window.__timelines || {};\n      var tl = gsap.timeline({ paused: true });\n\n      // your GSAP animations\n\n      window.__timelines[\"beat-N-name\"] = tl;\n    })();\n  </script>\n</template>\n```\n\n**Critical:** `data-composition-id`, `data-width`, `data-height` on the root div MUST match the host div in index.html.\n\n## Step 3: Lint\n\n```bash\nnpx hyperframes lint .\n```\n\nFix ALL errors. Zero errors required.\n\n## Step 4: Snapshot and verify\n\n```bash\nnpx hyperframes snapshot . --frames 3\n```\n\n**READ the contact sheet** (`snapshots/contact-sheet.jpg`). For each frame:\n\n- Is content visible? (not black, blank, or loading)\n- Is text readable, properly positioned, correct font/color?\n- Are assets at the right size and position?\n- Does the animation state match the beat spec at this timestamp?\n\n**If anything is wrong:** fix, re-snapshot, re-check. You are done ONLY when every frame matches the spec.\n\n## Step 5: Report back honestly\n\nAfter lint passes, snapshots are taken, and you've fixed every issue you saw — report back to the main agent with concrete observations. Not \"0 errors, looks good.\" That phrasing is what got prior videos shipped with mismatched brand colors, missing logos, and headlines too small to read.\n\n**The main agent will OPEN your composition file and read it top-to-bottom** to cross-check against DESIGN.md and STORYBOARD.md — does the brand bg/accent hex actually appear in your CSS, are the captured assets the storyboard called for actually referenced, is the headline ≥80px, does the GSAP timeline cover the full beat duration. You cannot pass that check by claiming things you didn't do; the file is on disk, the truth is in the file.\n\nSo in your report, name the hex codes you used, the captured asset paths you placed, the headline `font-size`, and the GSAP timeline's last `tl.fromTo(...)` timestamp. Brief, concrete, true. If anything diverges from DESIGN.md or the storyboard, say so explicitly — the main agent can decide whether to accept the divergence or send you back to fix it. Surprises caught at this hand-off cost minutes; surprises caught at Step 6 cost iterations.\n\n### FLAG protocol — required phrasing for non-blocking issues\n\nWhen you find any of these, surface them as **FLAGS** in your report, not as conditional suggestions:\n\n- Visual states that briefly look broken (empty containers, hanging elements, gap moments)\n- Spec ambiguities you had to resolve by guessing\n- Linter bugs you worked around\n- Tween values you changed from the spec because they wouldn't fit\n\n**Forbidden phrasing:** \"if the X feels too long, you could...\", \"consider tweaking Y\", \"might want to...\"\n\n**Required phrasing — concrete, actionable, with line numbers:**\n\n```\nFLAG: at beat-local t=1.2s the doc card is visible but its inner content is still\n       opacity 0 — a 0.4s empty-panel window.\n       RECOMMENDED FIX: pull title typewriter from 1.6s → 1.4s\n       in compositions/beat-5-name.html line 234.\n```\n\nThe main agent MUST EITHER apply each FLAG's fix OR write a one-sentence rejection with reason. Silently dropping a FLAG is a verification failure that gets caught at Step 6 (or worse, in the user's preview).\n\n### Spec ambiguity — escalate, don't paper over\n\nIf STORYBOARD.md gives you a transition or transformation but doesn't establish the **start** state, do NOT guess. Examples of ambiguity worth flagging:\n\n- \"Row 1 transitions from Huly Blue to Huly Orange at 3.5s\" — but Row 1's initial color isn't specified\n- \"Headline grows\" — but the start size isn't specified\n- \"Cards slide in\" — but the off-screen position isn't specified\n- \"Subhead appears after the headline\" — but exact timing offset isn't specified\n\n**Required action:** FLAG the ambiguity in your report verbatim:\n\n```\nFLAG: STORYBOARD.md beat 3 says \"Row 1 transitions blue → orange at 3.5s\" but\n       Row 1's initial color is not specified anywhere. I interpreted Row 1 starts\n       blue and tweened to orange. CONFIRM or correct.\n```\n\nThe main agent then confirms or corrects before Step 6 advances. Picking an interpretation silently means the build looks \"fine\" while diverging from intent — and the user only notices in motion.\n\n### Sub-agent diagnoses are unverified claims, not facts\n\nWhen a sub-agent reports \"this is a linter false positive\" / \"this is a known bug\" / \"this attribute doesn't work as documented\" — those are HYPOTHESES, not findings. Sub-agents diagnose from one symptom; they don't have repo-wide context.\n\nBefore propagating any sub-agent diagnosis (e.g., applying the same \"workaround\" to another beat, or telling the user \"this is a known bug\"), do ONE of:\n\n1. **Verify by reading the source.** Open the file the sub-agent claims is buggy. Confirm the bug exists. Example: \"I read `packages/core/src/lint/utils.ts:42` and confirmed the regex matches `url(\\\"data:image/svg+xml...\\\")` incorrectly. The workaround is to base64-encode the URI.\"\n2. **Disclose the unverified claim.** Don't suppress it — surface it. Example: \"Sub-agent for beat 2 diagnosed `root_missing_composition_id` as a linter false positive on inline SVG data URIs. I applied the same workaround to beat 4 WITHOUT verifying the underlying claim. Worth filing as a regression against `packages/core/src/lint/utils.ts` to confirm.\"\n\n**Forbidden:** silently adopting the workaround pattern and presenting \"lint passes\" as evidence. If the workaround came from an unverified diagnosis, \"lint passes because the diagnosis was correct AND I worked around it\" and \"lint passes because the diagnosis was wrong but the workaround happened to make the symptom disappear\" are both possible. Without verification, you don't know which. The next session inherits the workaround AND the unverified diagnosis.\n\n### When you accept a sub-agent's divergence from spec — UPDATE the spec\n\nIf a sub-agent reports \"I diverged from STORYBOARD.md because...\" AND you accept the divergence, you MUST update STORYBOARD.md to reflect the actual implementation. Otherwise the spec lies about the artifact.\n\nExamples:\n\n- Sub-agent: \"Storyboard says 'HULY' uppercase but the actual logo asset is lowercase 'huly'. I used lowercase.\" Accept → edit STORYBOARD.md beat N to say \"huly\" lowercase. Note the change inline.\n- Sub-agent: \"Storyboard says cells at 56px but they read too small at 1920×1080. I used 96px.\" Accept → edit STORYBOARD.md beat N's cell size to 96px.\n- Sub-agent: \"Storyboard says SFX at t=4.7s but the visual moment lands at t=5.2s; I aligned SFX to the visual.\" Accept → edit STORYBOARD.md SFX line to t=5.2s.\n\n**Forbidden:** accepting the divergence silently and leaving the storyboard with the wrong spec. The next session reading STORYBOARD.md will trust it as ground truth. The spec is a contract; if you break the contract, update the contract.\n\n---\n\n## Continuous motion — the most important rule\n\nA beat is a SHOT in a film, not a webpage with entrance animations. Your GSAP timeline should have events spread across the ENTIRE beat duration — not just entrance tweens in the first 1-2 seconds followed by nothing. If an element is on screen, it should be doing something. After elements enter, add continuous hold motion: camera dolly, parallax layers moving at different speeds, secondary elements appearing mid-beat, real depth shifts.\n\n## You are building a SHOT, not a webpage\n\nThe storyboard tells you the shot framing (close-up / medium / wide / etc.) and the camera move. Implement them. A beat is a moment, not a screenshot. The distinction is **what the camera is doing**, not whether the subject is a UI element or a logo — a tight push-in on a real product screenshot is a shot; a centered card on a parked camera is a webpage.\n\n**Patterns that turn a shot back into a webpage:**\n\nThese are defaults to avoid, **not absolute prohibitions.** If the storyboard genuinely calls for \"the kanban app interface\" or \"the browser chrome\" as the subject of a specific beat (a product tour, a \"this is how it works\" demo, a stylized window mockup for the closer), then build it. The rule is: don't reach for these patterns by default when the storyboard didn't ask for them.\n\n- ⚠ **macOS / browser window chrome reproduced in CSS** — traffic-light dots, URL bars, browser tabs. Fine when the storyboard makes the chrome the subject (e.g. \"stylized macOS window framing the product UI\" for a closer). NOT fine when it's a frame you added around a card \"to make it look like an app.\"\n- ⚠ **Full webpage layout** (sidebar + header + footer + main content area) — fine when the beat is genuinely a product tour shot. NOT fine when the beat was supposed to be about _the kanban moment_ and you defaulted to drawing the whole app around it.\n- ❌ **Parked-camera composition** — centered card with 60–120px margins on all sides and no camera move. Almost always wrong. Either give it a real push-in / dolly / parallax, or reframe.\n- ❌ **\"Hold with breathing\"** implemented as `y: ±1–2px` or `scale: 1.01` — invisible at 1920×1080+ scale. If continuous motion is required, use camera dolly (scale 1.0 → 1.05), parallax pan (x/y ±30–80px), or progressive reveals.\n- ❌ **Hover-state simulations** — videos have no hover. If the brand uses hover effects, show the BEFORE and AFTER as discrete frames in the timeline.\n- ❌ **Counter pulses + dot pulses + tiny scale wobbles** as the only motion during the hold — these are \"I ran out of ideas\" filler.\n\nThe test: if the storyboard says _\"this beat is the product tour, viewer sees the app interface\"_, building a CSS dashboard with chrome is correct. If the storyboard says _\"this beat is the kanban moment, single card sliding home\"_, drawing the full app around it is wrong. Read the beat spec carefully.\n\n**Patterns that ARE shots (do these freely):**\n\n- ✅ **Captured SVG logo drawing itself stroke-by-stroke** (DrawSVG / path dashoffset) — a complete opener or stinger.\n- ✅ **Captured hero illustration with camera dolly** — push-in from 1.0 → 1.08 over 4s, focal element holds frame.\n- ✅ **Captured product screenshot with parallax layers** — separate the foreground UI from background panels and move them at different speeds, or use HTML-in-Canvas for an iPhone/MacBook mockup.\n- ✅ **Captured asset as the bed, kinetic type as the punchline** — the brand's hero image holds the frame while a one-line message arrives, splits, reflows.\n- ✅ **Composed-from-divs UI moment** when the beat is specifically about that UI's interaction (a card sliding into a column, a search result resolving) — this is the legit case for CSS-only composition.\n\n**Required motion magnitudes** (anything smaller is invisible at video scale):\n\n| Motion type     | Minimum magnitude                           |\n| --------------- | ------------------------------------------- |\n| Translate (y/x) | 30px (entrance) / 8px (drift during hold)   |\n| Scale           | 0.05 change (1.0 → 1.05 or larger)          |\n| Opacity         | full 0 → 1 or vice versa for reveals        |\n| Rotate          | 4° minimum to read (Dutch angles, ticks)    |\n| Camera dolly    | scale 1.0 → 1.06 minimum over beat duration |\n\n**Required cinematography per beat** (the storyboard should give you these; if it doesn't, escalate):\n\n- A **shot type** (close-up / medium / wide / over-the-shoulder / Dutch)\n- A **camera move** (dolly in/out, push, parallax pan, orbit, rack focus)\n- A **depth strategy** (what's foreground / midground / background)\n- A **purpose** (what specific feeling or noticing the shot delivers)\n\nIf any are missing from the beat spec, the beat is under-defined. Don't fill the gap with \"centered layout + breathing\" — re-read the spec, and if it's genuinely missing, ask the main agent.\n\n## Rules\n\n- SCRIPT PLACEMENT: scripts inside `<template>`, never after `</template>`. Scripts outside see no DOM.\n- GSAP FROM TRAP: never `gsap.from(el, {opacity:0})` with CSS `opacity:0`. It animates 0→0. Use `tl.fromTo()`.\n- STYLE: avoid CSS `opacity:0` on GSAP-animated elements. Use GSAP fromTo for initial states.\n- ASSET PATHS: project-root-relative. `capture/assets/file.png` ✅ `../capture/assets/file.png` ❌\n- SVG VIA IMG: `<img src=\"logo.svg\">` can't inherit CSS color. Inline SVG or `filter: brightness(0) invert(1)`.\n- CSS CENTERING: no `transform: translate(-50%, -50%)` with GSAP transforms. Use flexbox or `xPercent/yPercent`.\n- QUERYSELECTOR: `document.getElementById(\"id\")` with null guards. No method calls without null check.\n- CHARACTER SPANS: `display:inline-block` on spaces collapses them. Use `&nbsp;` or per-word spans.\n- COUNTERS: no `onUpdate` for numeric counters — use discrete `tl.set(el, {textContent: \"42\"}, 2.5)` at timestamps. `onUpdate` and `tl.call()` ARE supported for canvas/WebGL rendering loops and character-by-character typing — see capabilities.md §10.\n- TIMELINE: `window.__timelines[\"beat-N-name\"] = tl` synchronously. Key = `data-composition-id`.\n- DETERMINISTIC: no `Math.random()`, `Date.now()`, `requestAnimationFrame`, `repeat:-1`.\n- Always `tl.fromTo()` not `tl.from()` for entrances.\n- Never stack two transform tweens on same element at same time.\n- FONTS: copy the `@font-face` block VERBATIM from DESIGN.md's Fonts section. Do NOT guess which `.woff2` file belongs to which family — capture filenames are content-hashed (`14d7ce3e41dcbb66-s.p.woff2`) and there is no visible mapping. If DESIGN.md doesn't include exact `src:` paths per family, STOP and ask the main agent to add them; never pair an arbitrary `.woff2` file with a family name from memory.\n\n## Easing — pick per intent\n\nDo NOT default to `power2.out` on everything.\n\n| Intent          | GSAP Ease             | Use for                              |\n| --------------- | --------------------- | ------------------------------------ |\n| Snap (iOS feel) | `power4.out`          | Hero text, UI elements               |\n| Whip overshoot  | `back.out(1.7)`       | Numbers, badges, impact              |\n| Soft land       | `expo.out`            | Per-word reveals, gentle entrances   |\n| Mechanical      | `power1.out`          | Terminal text, code typing           |\n| Bounce settle   | `elastic.out(1, 0.5)` | Counters, CTA buttons                |\n| Dramatic        | `expo.inOut`          | Full-screen statements, hero reveals |\n| Drift           | `\"none\"`              | Parallax, Ken Burns, camera drift    |\n\nStaggered items: `power4.out` with `stagger: 0.08` to `0.15`.\n\nFile v1.0.7:references/capabilities.md\n\n# HyperFrames — Complete Capabilities Inventory\n\nEverything possible in HyperFrames as of today's workspace, synthesized from direct source reads of all 7 packages, 16 skills, and the full registry.\n\n> **How to read this file.** Scan the **Table of Contents** below first. **Do NOT read this file linearly** — it is a 700+ line inventory; reading top-to-bottom every session wastes context. When the storyboard or a specific beat needs a particular capability (HTML-in-Canvas, shader transitions, audio-reactive, dynamic counters, etc.), jump straight to that section.\n\nYou are NOT limited to what was captured from the website. You can create shaders from scratch, search for and download registry blocks, build Three.js scenes, write custom WebGL effects, use any web API — anything a browser can render.\n\nFor implementation patterns (working code), see `techniques.md`. This file is the WHAT; techniques.md is the HOW.\n\n## Essential Rules\n\n- **Deterministic:** No `Math.random()`, no `Date.now()`, no `requestAnimationFrame`, no `repeat: -1`. The render engine seeks to exact timestamps.\n- **Timeline contract:** `window.__timelines[\"composition-id\"] = tl` must be set synchronously. The timeline length defines the composition duration.\n- **Sub-compositions:** External `.html` files loaded via `data-composition-src`. Auto-nested timelines, scoped CSS, scoped scripts.\n- **Linter:** 60+ rules. Run `npx hyperframes lint` before render. Catches missing timelines, overlapping clips, broken paths, GSAP errors.\n\n## Table of Contents\n\n| #   | Section                                              | What it covers                                                                                                                                                                                                                  |\n| --- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 1   | **Composition fundamentals**                         | Data attributes, timeline contract, resolution presets (1080p, 4K, portrait, square, custom)                                                                                                                                    |\n| 2   | **Animation engines (6 adapters)**                   | GSAP + 15 plugins, Anime.js v4, CSS @keyframes, WAAPI, Lottie (lottie-web + dotlottie), Three.js (hf-seek event)                                                                                                                |\n| 3   | **Shader transitions (14 WebGL)**                    | domain-warp, ridged-burn, whip-pan, sdf-iris, ripple-waves, gravitational-lens, cinematic-zoom, chromatic-split, swirl-vortex, thermal-distortion, flash-through-white, cross-warp-morph, light-leak, glitch — plus custom GLSL |\n| 4   | **CSS scene transitions (30+)**                      | Push/slide, scale/zoom, radial/clip, 3D flip, blur, dissolve, cover/blinds, light leak/burn, distortion/glitch, mechanical/shutter, grid dissolve, destruction/burn, VHS/gravity/morph — 6 timing presets                       |\n| 5   | **Visual effects + textures**                        | Text markers (highlight, circle, burst, scribble, sketchout), grain/noise, light leaks, film burn, vignette, glow, paper texture, shimmer sweep                                                                                 |\n| 6   | **Caption techniques**                               | Per-word karaoke, intensity tiers, 5 exit styles, 6 tone mappings, per-word styling triggers, 7 audio source formats, positioning helpers                                                                                       |\n| 7   | **Audio-reactive animation**                         | Bass→scale, mid→shape, treble→glow; any GSAP property; band extraction script; banned patterns                                                                                                                                  |\n| 8   | **HTML-in-canvas**                                   | Live DOM as GPU texture (drawElementImage), Three.js planes, WebGL shaders on HTML, 7 VFX blocks (iPhone/MacBook device, liquid, glass, magnetic, portal, shatter, text cursor)                                                 |\n| 9   | **Three.js / WebGL custom scenes**                   | Full 3D: AnimationMixer, custom GLSL, post-processing, GLTF models, lights, cameras, materials — all deterministic via hf-seek                                                                                                  |\n| 10  | **SVG / canvas / variable fonts**                    | SVG path drawing, Canvas 2D procedural art, CSS 3D card, per-word type, variable font axes, character typing, velocity-matched cuts, MotionPath                                                                                 |\n| 11  | **Media: video, audio, TTS**                         | Video compositing + frame injection, audio mixer (multi-track), Kokoro TTS (54 voices, 9 languages), Whisper/Groq/OpenAI transcription, background removal (u2net)                                                              |\n| 12  | **Registry (51 blocks + 4 components + 8 examples)** | Social overlays (8), showcases (5), data viz (2), logo branding (1), 3D/VFX (7), shader transitions (14), transition galleries (13), components (grain, shimmer, pixelate, texture-mask), 8 starter examples                    |\n| 13  | **CLI (25 commands)**                                | init, add, catalog, play, preview, publish, render (MP4/WebM/MOV/PNG, HDR, GPU, parallel), lint, validate, inspect, snapshot, capture, tts, transcribe, remove-background, doctor, and more                                     |\n| 14  | **Linter (60+ rules)**                               | Core, media, GSAP, captions, composition, adapters, textures, fonts — plus async URL checks                                                                                                                                     |\n| 15  | **Player web component**                             | `<hyperframes-player>` with seek/play/pause API, 11 events, media mirror, runtime auto-inject                                                                                                                                   |\n| 16  | **Engine + Producer**                                | MP4/WebM/MOV/PNG output, HDR (PQ/HLG), transparency (ProRes), GPU encoding (NVENC/VideoToolbox/VAAPI/QSV), parallel rendering, video frame injection                                                                            |\n| 17  | **Studio (in-browser NLE)**                          | Timeline editor, drag/resize clips, asset browser, render queue, lint modal, caption editor, element picker                                                                                                                     |\n| 18  | **Determinism guarantees**                           | No Math.random, no Date.now, no RAF, no repeat:-1, no callbacks, synchronous construction                                                                                                                                       |\n| 19  | **Variables / parameterization**                     | Typed runtime variables (string, color, number, boolean, enum), CLI override, strict validation                                                                                                                                 |\n| 20  | **Sub-compositions**                                 | External file or inline template, auto-nested timelines, scoped CSS, scoped scripts, variable inheritance                                                                                                                       |\n| 21  | **Global runtime APIs**                              | 25+ window globals for timelines, player, variables, adapters, hooks                                                                                                                                                            |\n| 22  | **Skills (16)**                                      | hyperframes, cli, media, registry, contrast, animation-map, website-to-video, remotion, gsap, animejs, css-animations, waapi, lottie, three, tailwind, contribute-catalog                                                       |\n| 23  | **References (15 docs)**                             | transitions, css-patterns, dynamic-techniques, motion-principles, typography, narration, captions, audio-reactive, transcript-guide, techniques, beat-direction, visual-styles, and more                                        |\n| 24  | **Documentation (27 pages)**                         | Guides + package docs covering rendering, HDR, html-in-canvas, performance, prompting, troubleshooting, etc.                                                                                                                    |\n\n---\n\n## 1. Composition fundamentals\n\n### Data attributes recognized by the runtime\n\n- **Root composition:** `data-composition-id`, `data-start`, `data-duration`, `data-width`, `data-height`, `data-composition-src` (external sub-comp), `data-composition-duration`, `data-composition-variables` (JSON), `data-variable-values` (override)\n- **Every clip:** `id`, `data-start`, `data-duration`, `data-track-index`, `class=\"clip\"`, optional `data-media-start`, `data-volume`, `data-playback-start`\n- **Sub-composition host:** `data-composition-id`, `data-composition-src` OR inline `<template id=\"${compId}-template\">`\n- **Parser also reads:** `data-type` (composition|text), `data-end`, `data-keyframes` (JSON), `data-x|y|scale|opacity`, `data-color|font-size|font-weight|font-family|text-shadow|outline|highlight*`, `data-layer` (z-index, deprecated for timeline but used for audio mixer layers), `data-resolution`, `data-composition-width|height`\n\n### Timeline contract\n\n- `gsap.timeline({ paused: true })` registered on `window.__timelines[\"<composition-id>\"]`\n- Master clock (TransportClock + WebAudioTransport) drives the timeline via `tl.totalTime(t, false)` or `tl.seek(t, false)`\n- Framework auto-nests sub-comp timelines\n- Duration sourced from `data-duration` on root, not from GSAP length\n- Synchronous timeline construction required (no async/await/setTimeout)\n- Looping handled by `<hyperframes-player>`, not GSAP `repeat: -1`\n\n### Resolution presets\n\nVALID_CANVAS_RESOLUTIONS: 1920×1080 default, 1080×1920 portrait, 1080×1080 square, 4K, 1440×2560, plus `normalizeResolutionFlag` for `--resolution` CLI flag.\n\n---\n\n## 2. Animation engines (6 deterministic frame adapters)\n\nThe runtime registers these adapters in order; each implements `discover()` / `seek({time})` / `pause` / `play?` / `revert`:\n\n| Adapter                            | What it drives                                                                | How to load                                                     | Notable                                                                                                   |\n| ---------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |\n| GSAP (createGsapAdapter)           | The primary timeline + all tweens registered on `window.__timelines[<id>]`    | CDN `https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js` | Plugins via standard GSAP register; HyperFrames does NOT patch THREE.Clock (uses `__hfThreeTime` instead) |\n| Anime.js v4 (createAnimeJsAdapter) | Anime instances pushed to `window.__hfAnime`                                  | CDN `animejs@4.0.2/lib/anime.iife.min.js` or ESM                | Adapter multiplies composition seconds by 1000 for ms                                                     |\n| CSS animations (createCssAdapter)  | Any element with computed `animation-name`                                    | Declarative `@keyframes`                                        | Falls back to negative `animation-delay` when WAAPI unavailable                                           |\n| WAAPI (createWaapiAdapter)         | All Animation objects on document                                             | `element.animate()`                                             | Uses `document.getAnimations()`                                                                           |\n| Lottie (createLottieAdapter)       | `window.__hfLottie` array; supports lottie-web + dotlottie-web                | CDN `lottie.min.js` + `@lottiefiles/dotlottie-web`              | `goToAndStop(time*1000)` or `setCurrentRawFrameValue` / `seek(%)`                                         |\n| Three.js (createThreeAdapter)      | `window.__hfThreeTime` + dispatches `CustomEvent(\"hf-seek\", {detail:{time}})` | ESM CDN `three@0.181.2/+esm`                                    | Composition's render loop listens to `hf-seek`; pattern: `mixer.setTime(time)`                            |\n\n### GSAP plugins (documented patterns)\n\n- **TextPlugin** — text mutation in `tl.call` (skills/gsap/references/effects.md)\n- **MotionPathPlugin** — curve-constrained tweens (skills/hyperframes/references/techniques.md)\n- **CustomEase** — bezier eases imported from Remotion-style timing\n- **ScrollTrigger / Flip / SplitText / Draggable / Inertia / Observer / ScrambleText / CustomWiggle / CustomBounce / ScrollSmoother / GSDevTools** — work natively if loaded and tweens are on the registered paused timeline, but no special HyperFrames adapter\n- Producer injects ScrollTrigger CDN automatically when needed (packages/producer/src/services/htmlCompiler.ts)\n\n---\n\n## 3. Shader transitions — @hyperframes/shader-transitions\n\n14 named WebGL fragment shaders. All share the same uniforms: `u_from`, `u_to`, `u_progress`, `u_resolution`, `u_accent`, `u_accent_dark`, `u_accent_bright`.\n\n### The 14 shaders\n\n| Name                | Visual                                                                                 | Notes                                                                                                                              |\n| ------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| domain-warp         | Multi-octave FBM warps both scenes oppositely; organic dissolve edge with accent flash | Uses NQ noise bundle                                                                                                               |\n| ridged-burn         | Ridged multifractal mask reveals B; accent → bright → white burn ramp; sparks          | NQ                                                                                                                                 |\n| whip-pan            | 10-sample horizontal motion blur + lateral crossfade                                   | No noise                                                                                                                           |\n| sdf-iris            | Aspect-corrected circle SDF expansion + accent-tinted glow rings                       | —                                                                                                                                  |\n| ripple-waves        | Radial standing-wave UV displacement + tinted crossfade                                | —                                                                                                                                  |\n| gravitational-lens  | Pinch pull toward center + R/B chromatic separation                                    | —                                                                                                                                  |\n| cinematic-zoom      | 12 RGB-offset radial zoom blur samples (chromatic zoom streak)                         | —                                                                                                                                  |\n| chromatic-split     | R/B radial channel shift outward / inward; G fixed                                     | Distinct from CSS chromatic aberration                                                                                             |\n| swirl-vortex        | CCW swirl with FBM noise; reciprocal on incoming                                       | NQ                                                                                                                                 |\n| thermal-distortion  | Vertical sin + FBM horizontal displacement; warm haze                                  | NQ                                                                                                                                 |\n| flash-through-white | Fade through white midpoint — a visible white flash between scenes                     | No accent. Use only when the brand specifically calls for a white-flash beat boundary; this is NOT a neutral \"default\" transition. |\n| cross-warp-morph    | FBM vector field displaces both scenes; third FBM biases irregular wipe                | NQ                                                                                                                                 |\n| light-leak          | Fixed off-frame leak with exponential falloff + accent warmth + ridge flare            | Hard-coded leak anchor                                                                                                             |\n| glitch              | Line displacement + RGB lateral split + scan modulation + posterization + flicker      | Deterministic                                                                                                                      |\n\n### Public API\n\n```js\nHyperShader.init({\n  bgColor: \"#0b0f14\",\n  accentColor: \"#f59e42\",\n  scenes: [\"scene1\", \"scene2\"],\n  transitions: [{ time: 3, shader: \"sdf-iris\", duration: 0.65, ease: \"power2.inOut\" }],\n  timeline: gsap.timeline({ paused: true }),\n  compositionId: \"main\",\n  previewCaptureFps: 30,\n});\n```\n\n- Capability probe: `isHtmlInCanvasCaptureSupported()` (Chrome layoutSubtree/drawElementImage)\n- Tuning: `?__hf_shader_capture_scale=` (0.25–1), `?__hf_shader_loading=` (internal|player|none)\n- Cache: IndexedDB for PNG snapshots; max 2 textured transitions live at once\n- Fallback (`applyFallbackTransition`): smoothstep opacity tween when capture / texImage2D fails\n- Engine mode skips GL/capture when `window.__HF_VIRTUAL_TIME__` set (producer uses metadata)\n\nYou can also **write custom GLSL shaders from scratch** — any fragment shader works with the standard uniforms.\n\n---\n\n## 4. CSS scene transitions (30+ named patterns)\n\nDocumented in skills/hyperframes/references/transitions/ across 14 category files. All GSAP-driven, none mixable with shader transitions in same composition.\n\n### By category\n\n| Category                         | Patterns                                                                                         |\n| -------------------------------- | ------------------------------------------------------------------------------------------------ |\n| Push / slide (css-push.md)       | Push slide, vertical push, elastic push, squeeze                                                 |\n| Scale / zoom (css-scale.md)      | Zoom through, zoom out, scale-up swap                                                            |\n| Radial / clip (css-radial.md)    | Circle iris, diamond iris, diagonal split                                                        |\n| 3D (css-3d.md)                   | 3D card flip, hinge door                                                                         |\n| Blur (css-blur.md)               | Crossfade, blur crossfade, focus pull                                                            |\n| Dissolve (css-dissolve.md)       | Color dip (gap-to-black), staggered color blocks (2-block, 5-block)                              |\n| Cover (css-cover.md)             | Horizontal blinds, vertical blinds (variable strip counts: 6 / 12 / 20)                          |\n| Light (css-light.md)             | Light leak overlays, overexposure burn, film burn                                                |\n| Distortion (css-distortion.md)   | Glitch (CSS — RGB layer jitter), chromatic aberration, ripple                                    |\n| Mechanical (css-mechanical.md)   | Shutter (two-half), clock wipe (9-point rotating wedge)                                          |\n| Grid (css-grid.md)               | Grid dissolve (12 or 120 cells), grid pixelate wipe                                              |\n| Destruction (css-destruction.md) | Page burn (SVG clip-path + canvas char rim)                                                      |\n| Other (css-other.md)             | VHS tape (strip-based seeded jitter), gravity drop, morph circle, blur through, directional blur |\n| Rejected                         | Star iris, tilt-shift, lens flare (don't use — non-CSS-realistic)                                |\n\n### Timing presets\n\n| Preset   | duration | ease                   |\n| -------- | -------- | ---------------------- |\n| snappy   | 0.2s     | power4.inOut           |\n| smooth   | 0.4s     | power2.inOut           |\n| gentle   | 0.6s     | sine.inOut             |\n| dramatic | 0.5s     | power3.in → power3.out |\n| instant  | 0.15s    | expo.inOut             |\n| luxe     | 0.7s     | power1.inOut           |\n\n---\n\n## 5. Visual effects + textures\n\n### Marker/emphasis patterns (css-patterns.md)\n\n| Mode      | What it does                      | Implementation                            |\n| --------- | --------------------------------- | ----------------------------------------- |\n| highlight | Yellow bar wipes behind text      | CSS bar + GSAP scaleX 0→1                 |\n| circle    | Hand-drawn red ring around word   | CSS border ellipse + back.out scale       |\n| burst     | 12 radial spikes from word center | DOM line array, --len/--angle vars        |\n| scribble  | Wavy underline drawn over time    | SVG `<path>` quadratic + stroke-dash GSAP |\n| sketchout | Cross-hatch x-out over text       | Two 2px rotated lines                     |\n\n### Grain / noise\n\n- **grain-overlay** (registry component): SVG feTurbulence data-URL + CSS keyframe jitter, `steps(1)`, default opacity 0.15\n- **Layered radial-gradient grain** (preferred pattern): no SVG, no canvas-taint, fast everywhere\n\n### Light / film\n\n- Light leak transitions (CSS + shader variants)\n- Overexposure burn — `brightness()` ramp + flash overlay\n- Film burn — multi-layer amber/orange/red radials\n- Vignette — radial-gradient overlay\n- Paper texture (in registry/examples/warm-grain/)\n\n### Glow\n\n- Caption text glow: textShadow radius keyed to treble bands (always on active words only, never parents)\n- Radial glow backgrounds: CSS gradients / blurred blobs\n\n---\n\n## 6. Caption techniques\n\n### Animation styles\n\n- Baseline: per-word karaoke highlight (every energy level)\n- Intensity tiers: accent + glow + 15% scale (high energy) → 3% scale (low energy)\n- Exits by energy (dynamic-techniques.md): scatter, drop, collapse, fade+slide, fade\n- Tone mappings (captions.md): scale-pop `back.out(1.7)`, fade+slide `power3.out`, typewriter, bounce, `elastic.out`, word-by-word\n\n### Per-word styling triggers\n\n- Brand/product names\n- ALL CAPS\n- Numbers / stats\n- Emotional keywords\n- CTAs\n- Marker highlight modes (5 listed above)\n\n### Audio sources for caption timing\n\n| Source                                     | Format   | Granularity       |\n| ------------------------------------------ | -------- | ----------------- |\n| hyperframes transcribe (local whisper.cpp) | JSON     | Word-level        |\n| OpenAI verbose_json                        | JSON     | Word-level        |\n| Groq verbose_json                          | JSON     | Word-level        |\n| Manually authored                          | JSON     | Word-level        |\n| SRT                                        | text     | Phrase-level only |\n| VTT                                        | text     | Phrase-level only |\n| hyperframes tts → transcribe chain         | wav→json | Word-level        |\n\n### Positioning helpers\n\n- Landscape: bottom 80–120px centered\n- Portrait: ~600–700px from bottom\n- `window.__hyperframes.fitTextFontSize(text, {maxWidth, fontFamily, fontWeight})` for dynamic sizing\n\n---\n\n## 7. Audio-reactive animation\n\n### Data shape\n\n```js\nwindow.AUDIO_DATA = {\n  fps: 30,\n  totalFrames: 900,\n  frames: [{ bands: [0.42, 0.18, ...] }]  // bands normalized 0–1 per band across track\n};\n```\n\nIndex 0 = bass, higher = treble. Bands range 0–1, normalized across full track length.\n\n### Mappings documented\n\n| Band                  | Property                     |\n| --------------------- | ---------------------------- |\n| Bass (bands[0–1])     | scale (pulse)                |\n| Mid (bands[4–8])      | borderRadius, width          |\n| Treble (bands[12–14]) | textShadow, boxShadow (glow) |\n| Overall amplitude     | opacity, y, backgroundColor  |\n\nAny GSAP-tweenable property is fair game — including clipPath, filter, SVG attrs, CSS variables.\n\n### Extraction\n\n```bash\npython3 .../extract-audio-data.py audio.mp3 --fps 30 --bands 8\n```\n\nPre-extracted only — no Web Audio at render time.\n\n### Banned in audio-reactive\n\nEQ bars, spectrum UI, generic waveforms, note clip-art, generic particles, rainbow cycling, white strobe on beats, abstract pulsing orbs.\n\n---\n\n## 8. HTML-in-canvas\n\nDocumented in skills/hyperframes/references/html-in-canvas-patterns.md (504 lines).\n\n### Capability\n\n- Chrome's experimental `layoutSubtree` + `drawElementImage` rasterizes live DOM into canvas\n- Feature detection: `isHtmlInCanvasCaptureSupported()`\n- Used by shader-transitions for scene textures\n- Combined with Three.js: `CanvasTexture` + post-processing\n\n### Available patterns\n\n- HTML on a Three.js plane (displacement, distortion, liquid sim)\n- HTML in shaders (texture sampling for VFX)\n- Recursive HTML-in-canvas-in-shader-in-HTML\n\n### Experimental VFX blocks using this\n\n- `vfx-iphone-device` (GLTF iPhone + MacBook, HTML screens)\n- `vfx-liquid-background` (liquid sim displaces HTML)\n- `vfx-liquid-glass`\n- `vfx-magnetic`\n- `vfx-portal`\n- `vfx-shatter`\n- `vfx-text-cursor` (chromatic edges, canvas post)\n\n---\n\n## 9. Three.js / WebGL custom scenes\n\n### Integration pattern\n\n```js\nwindow.addEventListener(\"hf-seek\", (e) => {\n  const time = e.detail.time;\n  mixer.setTime(time);\n  shaderUniforms.u_time.value = time;\n  renderer.render(scene, camera);\n});\n```\n\n- Load: `import * as THREE from \"https://cdn.jsdelivr.net/npm/three@0.181.2/+esm\"`\n- Deterministic: every frame must derive from `time`, never `requestAnimationFrame` / `Date.now()`\n- Includes: AnimationMixer, custom GLSL shaders, post-processing, GLTF models, lights, cameras, materials\n\n---\n\n## 10. SVG / canvas / variable fonts (other authored techniques)\n\n(From skills/hyperframes/references/techniques.md)\n\n| Technique                | Mechanism                                                                            |\n| ------------------------ | ------------------------------------------------------------------------------------ |\n| SVG path drawing         | `strokeDasharray` + `getTotalLength()` + GSAP stroke offset                          |\n| Canvas 2D procedural art | Seeded hash function + `tl.to` proxy `{time}` onUpdate                               |\n| CSS 3D card              | GSAP `rotationY` + `perspective: 900`                                                |\n| Per-word kinetic type    | GSAP timings array, sliding decay                                                    |\n| Variable font axes       | Animate CSS vars → `font-variation-settings: \"opsz\" var(--opsz), \"wght\" var(--wght)` |\n| Character typing         | `tl.call` text mutation + `steps(1)` cursor blink                                    |\n| Velocity-matched cuts    | Match outgoing blur/translate velocity to incoming for seamless beats                |\n| MotionPathPlugin         | `gsap.registerPlugin(MotionPathPlugin)` + path string                                |\n\n---\n\n## 11. Media: video, audio, TTS\n\n### Video compositing\n\n- `<video muted playsinline data-start=\"...\" data-duration=\"...\" data-track-index=\"...\" src=\"...\">`\n- HyperFrames extracts frames at render via videoFrameInjector (avoids unreliable headless `<video>` playback)\n- Linter forbids `<video>` with audio at the same time — split into separate `<video muted>` + `<audio>`\n- Video frame extraction uses FFmpeg\n- HDR videos: PQ or HLG transfer detection + x265 with mastering metadata\n\n### Audio mixer\n\n- `<audio id=\"...\" data-start=\"...\" data-duration=\"...\" data-volume=\"0.8\" data-track-index=\"2\" src=\"...\">`\n- Multiple tracks mixed with `amix normalize=0` + per-track adelay + volume\n- Master audioGain from EngineConfig\n- Output: AAC 192kbps\n\n### TTS (Kokoro-82M, local)\n\n- 54 bundled voices with prefixes: `a` American EN, `b` British EN, `e` Spanish, `f` French, `h` Hindi, `i` Italian, `j` Japanese, `p` Brazilian Portuguese, `z` Mandarin\n- Default voice: `af_heart`\n- Speed: 0.1–3.0 (default 1.0)\n- Languages: en-us, en-gb, es, fr-fr, hi, it, pt-br, ja, zh (non-EN needs system espeak-ng)\n- Output: WAV; no pitch/volume CLI flags\n- No API key required\n\n### Transcription\n\n- Whisper.cpp models: tiny, base, small, medium, large-v3, small.en, medium.en (default small)\n- Groq API: whisper-large-v3 with word granularities\n- OpenAI API: whisper-1 verbose_json\n- Imports: SRT, VTT, JSON formats\n- Quality gates: music-token detection, garbage cleaning, retry with medium.en\n\n### Background removal\n\n- u2net ONNX models\n- Devices: auto / cpu / coreml / cuda\n- Quality presets: fast / balanced / best\n- Outputs: transparent WebM, ProRes MOV, PNG sequence\n- Optional dual output (foreground + extracted background)\n\n---\n\n## 12. Registry — 51 blocks + 4 components + 8 examples\n\n### Blocks by category\n\n**Social overlays (8):** instagram-follow, tiktok-follow, yt-lower-third, x-post, reddit-post, spotify-card, macos-notification, blue-sweater-intro-video\n\n**Showcases (5):** app-showcase (3D phones), north-korea-locked-down (map + annotation), apple-money-count (counter + SFX), vpn-youtube-spot (app-store scroll), nyc-paris-flight (map + plane path)\n\n**Data viz (2):** data-chart (animated bar+line, NYT-style), flowchart + flowchart-vertical (decision tree with SVG connectors, typing correction)\n\n**Logo / branding (1):** logo-outro (build + glow + tagline + URL pill)\n\n**3D / experimental VFX (8):** ui-3d-reveal, vfx-iphone-device (GLTF), vfx-liquid-background, vfx-liquid-glass, vfx-magnetic, vfx-portal, vfx-shatter, vfx-text-cursor\n\n**Single shader transitions (14):** one block per named shader — domain-warp-dissolve, ridged-burn, whip-pan, sdf-iris, ripple-waves, gravitational-lens, cinematic-zoom, chromatic-radial-split, glitch, swirl-vortex, thermal-distortion, flash-through-white, cross-warp-morph, light-leak\n\n**Transition galleries (13 showcase pieces):** transitions-3d, transitions-blur, transitions-cover, transitions-destruction, transitions-dissolve, transitions-distortion, transitions-grid, transitions-light, transitions-mechanical, transitions-other, transitions-push, transitions-radial, transitions-scale\n\n### Components (4 reusable snippets)\n\n- **grain-overlay** — SVG feTurbulence + CSS keyframes\n- **shimmer-sweep** — Light sweep gradient mask on text\n- **grid-pixelate-wipe** — Grid squares stagger fade scene wipe\n- **texture-mask-text** — Luminance-masked letterforms with 66 mask PNGs (Masonry, Stone, Ground/Road, Wood, Metal, Organic/Soft texture categories)\n\n### Examples (8 starter projects)\n\nwarm-grain, play-mode, swiss-grid, vignelli, decision-tree, kinetic-type, product-promo, nyt-graph\n\nInstall: `npx hyperframes add <name>` for blocks/components, `hyperframes init <dir> --example <name>` for examples.\n\n---\n\n## 13. CLI — 25 commands\n\n| Command           | Purpose                                                                                                                                                                                                                                                                                                                  |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| init              | Scaffold project from template/example (interactive or --non-interactive)                                                                                                                                                                                                                                                |\n| add               | Install registry block / component                                                                                                                                                                                                                                                                                       |\n| catalog           | Browse registry blocks/components (--type, --tag, --json, --human-friendly picker)                                                                                                                                                                                                                                       |\n| play              | Lightweight browser player (default port 3003)                                                                                                                                                                                                                                                                           |\n| preview           | Studio dev server (port 3002; --force-new, --list, --kill-all)                                                                                                                                                                                                                                                           |\n| publish           | Zip + upload + return hyperframes.dev URL                                                                                                                                                                                                                                                                                |\n| render            | Render to MP4 / WebM / MOV / PNG sequence — flags: --fps 24/30/60, --quality draft/standard/high, --workers, --docker, --hdr/--sdr, --crf, --video-bitrate, --gpu, --browser-gpu auto/software/hardware, --max-concurrent-renders 1-10, --variables JSON, --variables-file PATH, --strict-variables, --resolution preset |\n| lint              | Static lint (--json, --verbose)                                                                                                                                                                                                                                                                                          |\n| validate          | Bundle + headless Chrome + console + contrast (--contrast default true, --timeout 3000)                                                                                                                                                                                                                                  |\n| inspect / layout  | Visual layout audit (overflow detection at N timestamps; --samples 9, --at, --tolerance 2, --max-issues 80)                                                                                                                                                                                                              |\n| info              | Print project metadata                                                                                                                                                                                                                                                                                                   |\n| compositions      | List compositions (root + sub-comps)                                                                                                                                                                                                                                                                                     |\n| benchmark         | 5 preset configs × N runs (--runs 3)                                                                                                                                                                                                                                                                                     |\n| browser           | Manage Chrome (ensure/path/clear)                                                                                                                                                                                                                                                                                        |\n| remove-background | u2net + FFmpeg → transparent video                                                                                                                                                                                                                                                                                       |\n| transcribe        | whisper.cpp or import SRT/VTT/JSON                                                                                                                                                                                                                                                                                       |\n| tts               | Kokoro-82M (--voice, --speed, --lang, --list)                                                                                                                                                                                                                                                                            |\n| docs              | Print bundled markdown topics (data-attributes, examples, rendering, gsap, troubleshooting, compositions)                                                                                                                                                                                                                |\n| doctor            | Environment checklist (Node, CPU, memory, disk, FFmpeg, FFprobe, Chrome, Docker)                                                                                                                                                                                                                                         |\n| upgrade           | npm update check + optional global install                                                                                                                                                                                                                                                                               |\n| skills            | Run `npx skills add heygen-com/hyperframes --all`                                                                                                                                                                                                                                                                        |\n| telemetry         | enable/disable/status                                                                                                                                                                                                                                                                                                    |\n| snapshot          | PNG screenshots at timeline timestamps                                                                                                                                                                                                                                                                                   |\n| capture           | Capture URL → site assets + screenshots + design tokens (uses Puppeteer + optional Gemini vision)                                                                                                                                                                                                                        |\n\n### Website capture (`hyperframes capture <url>`)\n\nDetects these libraries on captured sites (for context labeling): GSAP / ScrollTrigger, Three.js, Lottie, Anime.js, PixiJS, Babylon.js, Rive, Matter.js, Lenis, Framer Motion, Tailwind CSS, WebGL (shader fingerprinting). Captured outputs feed the website-to-video skill workflow.\n\n---\n\n## 14. Linter — 60+ rules\n\nAcross 8 files in packages/core/src/lint/rules/:\n\n| Rule file   | Catches                                                                                                                                                                                                                                                            |\n| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| core        | Missing composition-id, missing dimensions, missing timeline registry, registry mismatch, invalid script syntax, scoped-CSS issues, non-deterministic code                                                                                                         |\n| media       | Duplicate media id, video missing muted, video nested in timed element, placeholder URLs, base64 prohibited, missing src/start/id, imperative play()/pause()/seek()                                                                                                |\n| gsap        | Overlapping tweens, exit missing hard kill, GSAP animating .clip element, unscoped selectors, CSS transform conflict, missing GSAP script, infinite repeat (repeat: -1), repeat ceil overshoot, scene layer visibility kill, audio-reactive single-tween-per-group |\n| captions    | Caption exit missing kill, text overflow risk, transcript not inline, parse error, container position, scale mismatch, textShadow on parent container                                                                                                              |\n| composition | File too large, dense tracks, missing class=\"clip\", deprecated data-layer/data-end, split attribute selectors, external script deps, RAF in composition, invalid variable JSON                                                                                     |\n| adapters    | Missing Lottie script, missing Three script                                                                                                                                                                                                                        |\n| textures    | Drop-shadow on text, class missing base, text missing mask, unknown texture class                                                                                                                                                                                  |\n| fonts       | Google Fonts import (use @font-face), font-family without @font-face                                                                                                                                                                                               |\n\nPlus async URL checks (`lintMediaUrls`, `lintScriptUrls` — HEAD probes).\n\n`validateCompositionGsap` also forbids: `Math.random`, `Date.now`, `new Date`, `setTimeout`, `setInterval`, `requestAnimationFrame`, `repeat: -1`.\n\n**Note:** `onUpdate` callbacks, `tl.call()`, and GSAP event callbacks (`onComplete`, `onStart`, etc.) are NOT banned by the linter — they are required for canvas/WebGL rendering and character-by-character typing patterns. The linter only catches the determinism violations listed above.\n\n---\n\n## 15. Player — `<hyperframes-player>` web component\n\n### Attributes\n\n`src`, `srcdoc`, `width`, `height`, `controls`, `muted`, `volume`, `poster`, `playback-rate`, `audio-src`, `shader-capture-scale`, `shader-loading` (internal|player|none), `loop`, `autoplay`, `speed-presets`\n\n### Public API\n\n`seek(t)` (synchronous when same-origin — uses `iframe.contentWindow.__player.seek` directly), `play()`, `pause()`, `currentTime`, `duration`, `paused`, `ready`, `playbackRate`, `iframeElement`\n\n### Events\n\n`ready`, `timeupdate`, `play`, `pause`, `ended`, `volumechange`, `ratechange`, `shadertransitionstate`, `playbackerror`, `error`, `audioownershipchange`\n\n### Media mirror\n\nParent audio/video elements with `data-start` are proxied; `_mirrorParentMediaTime` corrects drift; `_audioOwner` promotes to parent if autoplay blocked.\n\n### Runtime auto-inject\n\nLoads `RUNTIME_CDN_URL` (`@hyperframes/core/dist/hyperframe.runtime.iife.js`) if missing `__hf`/`__player` but timelines exist.\n\n---\n\n## 16. Engine + Producer — rendering pipeline\n\n### Output formats\n\nmp4, webm, mov, png-sequence — with HDR (PQ / HLG / SDR / auto-detect), transparency (ProRes MOV / WebM / PNG), or standard 8-bit SDR\n\n### Encoding controls\n\n- `--fps`: 24 / 30 / 60\n- `--quality`: draft / standard / high\n- `--crf`: integer (mutually exclusive with `--video-bitrate`)\n- `--video-bitrate`: e.g. `8M`\n- `--gpu`: NVENC, VideoToolbox, VAAPI, QSV\n- `--browser-gpu`: auto / software / hardware\n- `--workers`: parallel render workers\n- `--max-concurrent-renders`: 1–10 (sets `PRODUCER_MAX_CONCURRENT_RENDERS`)\n- `--resolution`: preset (1080p, 4k, portrait, etc.)\n- `--docker`: render inside Dockerfile.test image (reproducibility)\n- `--hdr` / `--sdr`: force HDR or SDR pipeline\n\n### Engine subsystems\n\n- Frame capture: BeginFrame on Linux headless-shell (fast, no alpha) or `Page.captureScreenshot` (alpha + supersample)\n- Video frame injector: pre-extracts video to images, swaps `<video>` for `<img>` during capture (LRU cache by path + byte budget)\n- Audio mixer: FFmpeg-based; per-track delay, volume, master gain, AAC 192k output\n- Chunk encoder: H.264 / H.265 / VP9 / ProRes presets with optional GPU\n- Streaming encoder: `streamingEncodeMaxDurationSeconds` for long renders\n- HDR compositing: `rgba16float` WebGPU readback (headed Chrome), PQ OETF helpers\n- Layer compositor: groups DOM by z-order; splits HDR elements into separate layers\n- Alpha blit: matrix3d affine extraction, `blitRgba8OverRgb48le`, `blitRgb48leAffine`\n- Parallel coordinator: concurrency, coresPerWorker, minParallelFrames, largeRenderThreshold\n- Browser pool: optional with timeout configs\n\n### Producer-only\n\n- `RenderConfig` with `hdrMode` (auto / force-hdr / force-sdr), `outputResolution` mapped to `deviceScaleFactor`\n- File server injects `HF_EARLY_STUB`, `HF_BRIDGE_SCRIPT`, virtual-time so `window.__hf` bridges `window.__player.renderSeek`\n- HDR-aware shader transition compositing via `window.__hf.transitions` metadata\n\n---\n\n## 17. Studio — in-browser NLE\n\nFull editor in packages/studio/:\n\n- **NLELayout**: NLE preview + timeline + controls\n- **Timeline**: clip rendering, drag to move (`data-start`), resize (`data-duration`), `data-track-index` reassignment, asset drop, file drop\n- **PlayerControls**: scrub, play, pause, frame step (`stepFrameTime`), `STUDIO_PREVIEW_FPS`\n- **useTimelinePlayer**: resolves `__player` / `__timeline` / `__timelines`\n- **LeftSidebar**: compositions list, asset browser\n- **RenderQueue + useRenderQueue**: queue multiple renders\n- **LintModal**: in-app lint output\n- **MediaPreview + AudioWaveform**: waveform rendering\n- **CaptionOverlay, CaptionTimeline, CaptionPropertyPanel**: caption editor\n- **useCaptionSync**: word-level sync\n- **useElementPicker**: click-to-inspect picker mode\n- Built with Tailwind v3 (separate from Tailwind v4 browser runtime used by compositions).\n\n---\n\n## 18. Determinism guarantees\n\n- No `Math.random()` (use seeded PRNGs; mulberry32 is the pattern in skills)\n- No `Date.now()` / `new Date()`\n- No `setTimeout` / `setInterval` in timeline construction\n- No `requestAnimationFrame` (timeline-driven; engine seeks per frame)\n- No `repeat: -1` (calculate exact repeats: `Math.ceil(duration / cycleDuration) - 1`)\n- No `onComplete`/`onStart`/`onRepeat` callbacks (engine doesn't fire them). **Exception:** `onUpdate` and `tl.call()` ARE supported — they're required for canvas/WebGL rendering, character-by-character typing, and counter patterns. See §10 (Canvas 2D procedural art) for the documented pattern.\n- No `gsap.set` on clips from later scenes (use `tl.set(selector, vars, position)`)\n- Synchronous timeline construction (no async)\n- Master clock can clamp at composition end\n\n---\n\n## 19. Variables / parameterization\n\nCompositions support typed runtime variables:\n\n```html\n<html\n  data-composition-variables='[\n  {\"name\":\"brand\",\"type\":\"string\",\"default\":\"Stripe\"},\n  {\"name\":\"primary\",\"type\":\"color\",\"default\":\"#635BFF\"},\n  {\"name\":\"duration\",\"type\":\"number\",\"default\":15},\n  {\"name\":\"darkMode\",\"type\":\"boolean\",\"default\":false},\n  {\"name\":\"layout\",\"type\":\"enum\",\"options\":[\"hero\",\"split\",\"stacked\"]}\n]'\n></html>\n```\n\nAccess via `window.__hyperframes.getVariables()`. Override at render time:\n\n```bash\nnpx hyperframes render --variables '{\"brand\":\"Linear\",\"primary\":\"#5E6AD2\"}'\nnpx hyperfram\n\nFile v1.0.7:references/step-0-capture.md\n\n# Step 0: Capture\n\nThe capture pipeline downloads the site and extracts structured data for the rest of the workflow to read. Step 0 is a single command plus a sanity check. **All analysis (reading files, viewing contact sheets, deriving brand voice, picking assets) happens in Steps 1–3, not here.**\n\n## Run the capture\n\nNo API keys required for the base capture. However, before running, ask the user:\n\n> \"For the best results, it is recommended to set a Gemini API key — it gives me AI-powered descriptions of every captured image, which helps me choose the right assets for each scene. It costs about $0.001 per image. You can skip this if you want, but the video quality will be better with it. To set it up: add `GEMINI_API_KEY=your-key` to a `.env` file in the project root. You can get a free key at ai.google.dev.\"\n\nIf the user provides the key or already has one set, proceed. If they skip it, proceed anyway — the capture works without it, but `asset-descriptions.md` will have DOM-context descriptions only (position, size, alt text) instead of AI vision descriptions.\n\nCreate a project directory for your video if it doesn't exist yet, then capture the website into a `capture/` subfolder within it:\n\n```bash\nnpx hyperframes capture <URL> -o <project-dir>/capture\n```\n\nExample: `npx hyperframes capture https://stripe.com -o videos/stripe-launch/capture`\n\nKeeping capture artifacts (`screenshots/`, `assets/`, `extracted/`, `AGENTS.md`, `CLAUDE.md`) in a dedicated `capture/` subfolder keeps them isolated from later build files (`SCRIPT.md`, `STORYBOARD.md`, `DESIGN.md`, `compositions/`, `index.html`, `narration.wav`, `transcript.json`, `renders/`, `snapshots/`), which all live at `<project-dir>/` root.\n\nFor exploratory captures that aren't becoming a video yet, the default `./capture/` (or any `-o <name>` you pick) is fine — the isolation convention only matters when you're building a video on top of the capture.\n\n## Confirm it succeeded\n\nWait for the capture to complete. Print one line summarizing what was captured:\n\n> \"Captured N screenshots, M assets, K SVGs, F fonts. Ready for Step 1.\"\n\nIf the command exited non-zero, the counts are all zero, or required directories (`extracted/`, `assets/`, `screenshots/`) are missing, surface the error and stop — don't advance to Step 1 with a broken capture.\n\n## What lives in `capture/` (reference table — DO NOT read these here)\n\nEach downstream step reads only what it needs. Don't pre-fetch everything in Step 0; that bloats context and produces summaries that get stale by the time they're used.\n\n| Path                                      | First read in                                 |\n| ----------------------------------------- | --------------------------------------------- |\n| `capture/extracted/tokens.json`           | Step 1 (DESIGN.md — colors / fonts)           |\n| `capture/extracted/design-styles.json`    | Step 1 (DESIGN.md — typography / components)  |\n| `capture/extracted/fonts-manifest.json`   | Step 1 (font identification)                  |\n| `capture/extracted/asset-descriptions.md` | Step 2 (brief grounding) and Step 3 (assets)  |\n| `capture/extracted/visible-text.txt`      | Step 2 (brief) and Step 3 (script)            |\n| `capture/assets/contact-sheet-*.jpg`      | Step 3 (asset picking)                        |\n| `capture/assets/svgs/contact-sheet-*.jpg` | Step 3 (SVG / logo picking)                   |\n| `capture/screenshots/contact-sheet-*.jpg` | Step 3 (visual mood reference)                |\n| `capture/extracted/animations.json`       | Step 3 / Step 5 (only if site has animations) |\n| `capture/extracted/lottie-manifest.json`  | Step 3 (only if site uses Lottie)             |\n| `capture/extracted/video-manifest.json`   | Step 3 (only if site embeds video)            |\n| `capture/extracted/shaders.json`          | Step 3 / Step 5 (only if site has WebGL)      |\n| `capture/assets/<individual files>`       | Step 5 (only when placing a specific asset)   |\n\n## Gate\n\nCapture exits 0. Asset / screenshot / font counts non-zero. Proceed to Step 1.\n\nFile v1.0.7:references/step-1-design.md\n\n# Step 1: Write DESIGN.md (the brand-truth cheat sheet)\n\nDESIGN.md is a **brand-truth cheat sheet** — colors and fonts you'll **weave into your composed builds**. It is NOT a layout spec, not a moodboard, not a 400-line design system audit.\n\nDESIGN.md is the brand inflection sub-agents apply when building each beat: which color is \"primary,\" which font is for headlines, what tone the brand carries — the load-bearing knobs they flip while building.\n\n**Target length: 250–350 lines.** Step 5 sub-agents read DESIGN.md to brand each beat — the more precise the component CSS values you encode here, the more brand-faithful the result. Going under 200 lines tends to produce generic dark-cinematic output because sub-agents have no brand component DNA to work from; going over 350 means you're over-investing in prose.\n\n**Fast-pacing exception:** For billboard-per-beat videos (short social ads where each beat is a single hero element on full-bleed background), a 50-line DESIGN.md with just colors + fonts + 3-5 do's/don'ts is enough. The Step 5 sub-agent prompt pastes brand values inline, so DESIGN.md depth only matters when the beats render full UIs.\n\n**User preferences always override brand rules.** If the user says \"make it bright even though the site is dark\" or \"use serif fonts even though the brand is sans\" — follow the user. DESIGN.md describes the captured website. The video might deliberately break that.\n\n**Read these now** — they're the inputs DESIGN.md is built from. Don't guess colors or sizes from screenshots:\n\n- `capture/extracted/tokens.json` — top brand colors (HEX) and font families with weight ranges.\n- `capture/extracted/design-styles.json` — computed CSS values from the live DOM: typography hierarchy (font-size, weight, line-height, letter-spacing per text role), button variants (background, padding, radius, shadow), card/container/nav styles, spacing scale, border-radius scale, box-shadow values with usage counts. **Primary data source for Sections 3–6 below.**\n\n**Font availability check — do this before writing anything else.** Read `capture/extracted/fonts-manifest.json`. The capture pipeline reads the OpenType `name` table embedded in every downloaded font file, so even hash-renamed Next.js/Webpack fonts are identified by their real family name (Inter, JetBrains Mono, Geist Mono, etc.). No guessing required.\n\nThe manifest gives you two views:\n\n- `families[]` — one entry per distinct family with the weights captured, whether it's a variable font, and the files belonging to it\n- `files[]` — one entry per downloaded font with family, subfamily, weight, style, and any variation axes\n\n**How to use it:**\n\n- For each family you'll reference in DESIGN.md, name it by what's in `families[].family` (e.g. \"Inter\", not \"f266e704 hashed font\"). The hashed filenames are the `@font-face src` paths — they stay as-is on disk; only the display name comes from the manifest.\n- If a family has `variable: true` and `variationAxes` includes `\"wght\"`, you can use any weight 100-900 via `font-variation-settings: 'wght' <value>` even if only one static weight appears in the captured files. Note this in DESIGN.md so sub-agents know they have the full weight range available.\n- If the manifest's `unidentified[]` is non-empty, those files failed name-table extraction (rare — heavily subset fonts that strip metadata). Flag them as `unknown` in DESIGN.md and suggest a fallback rather than guessing.\n- Commercial fonts hosted on brand CDNs (GT Walsheim, Söhne, Graphik, Canela) won't be in the manifest because they aren't downloaded. Detect this by checking what the site uses (from `design-styles.json`) against what's in the manifest — anything used but missing is a CDN-hosted font. Flag explicitly: \"Söhne not in capture; use Inter 600 as substitute.\"\n\nSub-agents try to use the fonts you list. The manifest tells you exactly what's available — there's no excuse for claiming \"Charlie Display 700\" when no such file exists.\n\n---\n\n## The 5 sections to write\n\n### `## 1. Visual Theme (one paragraph)`\n\n3–5 sentences describing the brand's visual personality. Cover: dark-first or light-first, contrast strategy, dominant visual elements (gradients, illustrations, photography, UI mockups), overall mood, what makes it distinctive vs. generic.\n\nThis is the only prose section. Make it specific to _this_ brand — not template-filling. A sentence that could describe any well-designed website is not useful.\n\n**Example:**\n\n> Stripe's visual language is light-first and clean, with deep navy (`#061B31`) and pure white as the foundation. The accent stack — Stripe Purple (`#533AFD`) for CTAs, Vibrant Orange (`#FF6118`) for energetic emphasis — keeps interactive elements unmistakable. Type is sohne-var Light (300) for display, weight 400 for body; the brand achieves hierarchy through size and weight, never color shifts. The mood is confident financial-tech — premium without theatrical drama. Distinctive: gradient overlays at 135° between purple and orange appear as subtle washes over white backgrounds, never as bold focal elements.\n\n---\n\n### `## 2. Quick Reference`\n\nA flat lookup of the values sub-agents grab while composing beats. Two sub-sections — keep them tight.\n\n#### Colors\n\nList 8–12 colors with brand-specific names + HEX + role. Not generic (\"Accent 1\") but evocative (\"Stripe Purple\", \"Deep Navy\", \"Slate Border\"). The name carries meaning; \"blue 4\" doesn't.\n\n**For each text-on-surface combination the brand uses, compute the WCAG AA contrast ratio and flag failing pairings explicitly.** A real failure mode from prior runs: the brand's secondary-text color (`#68686A`) on its dark panel color (`#18191B`) = 3.16:1, which fails AA's 4.5:1 minimum. Sub-agents faithfully reproduced the brand's color choice and the result was unreadable. Encode the safe / unsafe pairings here so sub-agents pick text colors by surface context, not by \"this is the brand's secondary text color.\" The `/hyperframes-contrast` skill audits ratios — run it before finalizing DESIGN.md.\n\n**Example:**\n\n```markdown\n#### Colors\n\n- **Stripe Purple** (`#533AFD`): Primary CTA, interactive elements, focus rings — the brand's action signal\n  - On Pure White: 6.2:1 ✅ — On Deep Navy: 3.8:1 ⚠ AA-only-Large\n- **Deep Navy** (`#061B31`): Primary text on light surfaces, also a dark surface tier\n  - As text on Pure White: 17.4:1 ✅ — As surface: see Slate-on-Navy pairings below\n- **Pure White** (`#FFFFFF`): Page background, card surfaces\n- **Light Gray** (`#F5F7FA`): Surface tier 2 (cards on white pages, alternating sections)\n- **Slate Blue** (`#273951`): Secondary text on LIGHT surfaces\n  - On Pure White: 12.6:1 ✅ — On Light Gray: 11.8:1 ✅ — On Deep Navy: 1.4:1 ❌ DO NOT USE\n- **Light Slate** (`#64748D`): Metadata, captions on light surfaces only\n  - On Pure White: 4.8:1 ✅ — On Light Gray: 4.5:1 ✅ — On Deep Navy: 3.0:1 ❌ — On Dark Panel: 2.9:1 ❌\n  - **For dark-surface metadata, use `#9A9A9E` instead: 6.4:1 on Deep Navy ✅, 6.1:1 on Dark Panel ✅**\n- **Subtle Border** (`#D4DEE9`): Card borders, dividers (not text — borders don't need AA)\n- **Vibrant Orange** (`#FF6118`): Energy accent — gradient endpoints, highlight bursts (never primary text)\n- **Error Red** (`#FF0022`): Validation errors. On Pure White: 4.5:1 ✅\n- **Success Green** (`#4CD963`): Confirmation states. On Pure White: 1.7:1 ❌ — must be paired with a darker outline or use as accent on dark surfaces\n```\n\n**Where the brand's own palette fails WCAG**, document the substitute (like the `#9A9A9E` override above). Sub-agents pick the safe color by surface — and if the deviation matters to the brand identity, the user can revisit at Step 6.\n\n#### Fonts\n\nList font families with their role AND **the exact file path per family + weight** from `fonts-manifest.json`. Sub-agents will copy the `@font-face` block verbatim — if you only name the family without the path, sub-agents have to guess which `.woff2` file belongs to which family and get it wrong half the time (a real failure mode from prior runs: agents pointed `@font-face` for \"ES Build Neutral\" at the Inter `.woff2` files and the wordmark rendered in Inter).\n\n**Example:**\n\n````markdown\n#### Fonts\n\n- **Display:** `\"ES Build Neutral\"` — wordmarks, headlines\n  - 600: `capture/assets/fonts/14d7ce3e41dcbb66-s.p.woff2`\n  - 700: `capture/assets/fonts/e8b276476c0ac6fa-s.p.woff2`\n- **Body:** `\"Inter\"` (variable 100–900, captured ✓) — body, labels, UI\n  - 400: `capture/assets/fonts/9a8d3f06c4e89f2b-s.p.woff2`\n  - 600: `capture/assets/fonts/1b0b3615811be75b-s.p.woff2`\n- **Mono:** `\"JetBrains Mono\"` — code, metadata\n  - 400: `capture/assets/fonts/c7d2e9f5a1b3c8d4-s.p.woff2`\n- **Fallback stack:** `-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif`\n\n**`@font-face` block to paste in every composition** (sub-agents copy this verbatim — do not invent file paths):\n\n```css\n@font-face {\n  font-family: \"ES Build Neutral\";\n  src: url(\"capture/assets/fonts/14d7ce3e41dcbb66-s.p.woff2\") format(\"woff2\");\n  font-weight: 600;\n  font-display: block;\n}\n@font-face {\n  font-family: \"Inter\";\n  src: url(\"capture/assets/fonts/9a8d3f06c4e89f2b-s.p.woff2\") format(\"woff2\");\n  font-weight: 400;\n  font-display: block;\n}\n/* + any other family/weight combinations the storyboard's beats need */\n```\n````\n\nThe brand uses **size for hierarchy, weight for emphasis**. Display 1: 48px/600, Display 2: 32px/600, Body: 14px/400. (Adjust to the actual brand's hierarchy.)\n\n````\n\nThe exact `@font-face` block lets sub-agents copy verbatim instead of constructing one from inference. If a beat needs a weight that isn't in the manifest, flag it explicitly here: e.g., \"ES Build Neutral 900 NOT in capture; use ES Build Neutral 700 as substitute, or fall back to Inter 700.\"\n\nThat's the whole typography section. If sub-agents need exact line-heights or letter-spacing, they read `design-styles.json` directly.\n\n---\n\n### `## 3. Component Stylings` (the build-step's spec sheet)\n\nThis is the section sub-agents consult most when building beats in Step 5. **Without exact per-component CSS, sub-agents fall back to generic \"dark bg + glow + centered text\" patterns regardless of brand** — which is why every video starts looking the same. Encode the brand's actual component DNA here.\n\nTarget **6-12 distinct components**. Document what the site actually uses; skip categories the brand doesn't have. For each component, name it descriptively (\"Stripe Primary Button\" not \"Button 1\") and provide exact CSS-level properties: background, text color, padding, border-radius, border, font size/weight, height, box-shadow, and any hover/active/disabled states.\n\n#### Buttons (always required)\n\nCover every variant the site uses — typically Primary, Secondary/Ghost, and Icon. **Example:**\n\n```markdown\n#### Primary Button (Stripe Purple)\n\n- **Background:** `#533AFD`\n- **Text color:** `#FFFFFF`\n- **Font:** sohne-var 16px / 400\n- **Padding:** `15.5px 24px 16.5px 24px`\n- **Border radius:** `4px`\n- **Border:** none\n- **Height:** `48px` (with padding)\n- **Box shadow:** none\n- **Hover:** background `#4329E8`, opacity `0.95`\n- **Active:** background `#3720D4`, scale `0.98`\n- **Disabled:** background `#C9C3F0`, cursor `not-allowed`\n\n#### Secondary Button (outline)\n\n- **Background:** `#FFFFFF`\n- **Text color:** `#533AFD`\n- **Border:** `1px solid #533AFD`\n- **Padding / radius / font:** same as Primary\n- **Hover:** background `#F3F0FF`, border `#4329E8`\n\n#### Ghost Button (text-only link)\n\n- **Background:** transparent\n- **Text color:** `#533AFD`\n- **Font:** sohne-var 14px / 400\n- **Padding:** `12px 0`\n- **Hover:** background `rgba(83, 58, 253, 0.08)`, optional underline\n````\n\n#### Cards & Containers (always required if the site uses any)\n\nDocument each distinct card type — Standard, Feature Highlight, Glass, Pricing, Testimonial — whatever this brand actually uses. **Example:**\n\n```markdown\n#### Standard Card\n\n- **Background:** `#FFFFFF`\n- **Border:** `1px solid #D4DEE9`\n- **Border radius:** `5px`\n- **Padding:** `32px`\n- **Box shadow:** `0 1px 2px rgba(0, 0, 0, 0.04)` (default), `0 4px 12px rgba(0, 0, 0, 0.08)` (hover)\n- **Hover:** border `#B8CCDB`\n\n#### Feature Highlight Card (gradient backdrop)\n\n- **Background:** linear-gradient(180deg, rgba(83, 58, 253, 0.05) 0%, rgba(255, 97, 24, 0.03) 100%)\n- **Border:** `1px solid #E5EDF5`\n- **Padding:** `36px`\n- **Box shadow:** none\n```\n\n#### Distinctive components (anything else the brand actually shows)\n\nLogo marquees, testimonial carousels, pricing tables, gradient overlays, glassmorphism panels, bento grids, code blocks, terminal UIs, dashboard mockups — name and document anything visually distinctive. Sub-agents will reach for these specs when the storyboard calls for a beat featuring the X.\n\n```markdown\n#### Glass Container (frosted overlay)\n\n- **Background:** `rgba(255, 255, 255, 0.9)`\n- **Border:** `1px solid rgba(255, 255, 255, 0.2)`\n- **Backdrop filter:** `blur(8px)`\n- **Use:** floating chat widgets, modal overlays, hero callouts only — the only place transparent fills appear in the system\n```\n\n**The rule:** if a sub-agent in Step 5 has to invent CSS values for a component this brand actually uses, you under-documented this section. The values should be lookup-able, not guessable.\n\n---\n\n### `## 4. Spacing & Layout`\n\nThe brand's rhythm. Three sub-sections, kept tight.\n\n#### Spacing scale\n\nIdentify the **base unit** (typically `4px` or `8px`) and the full scale with usage context. **Example:**\n\n```markdown\n**Base unit:** `4px`\n\n| Token | Value   | Used for                                                  |\n| ----- | ------- | --------------------------------------------------------- |\n| xs    | `4px`   | Inline icon gaps, tight badge padding                     |\n| sm    | `8px`   | Button-group gaps, small component padding                |\n| md    | `16px`  | Card padding, form-field gaps, standard component spacing |\n| lg    | `32px`  | Section vertical spacing, large card padding              |\n| xl    | `60px`  | Major section separation                                  |\n| 2xl   | `100px` | Page-level rhythm, hero section padding                   |\n\nNever use odd values (`13px`, `17px`) — the system only uses multiples of 4.\n```\n\n#### Border-radius scale\n\nEvery radius the site uses, with what uses it.\n\n```markdown\n- `0px`: Form labels, technical UI markers\n- `4px`: Primary buttons, inputs, small badges\n- `8px`: Standard cards, dropdowns\n- `12px`: Feature cards, larger callouts\n- `40px`: Icon buttons (square pill)\n- `9999px`: Pill-shaped CTAs, status chips\n```\n\n#### Whitespace philosophy (one paragraph)\n\nHow does this brand use whitespace — generous and architectural? Tight and information-dense? Section gaps in the 60–100px range, or 20–40px? Document the brand's actual rhythm.\n\n```markdown\nGenerous whitespace as confidence. Section gaps are always `60–100px`. Content never touches viewport edges — minimum `40px` horizontal padding on mobile, `80–160px` on desktop. The brand uses negative space as active design, not emptiness.\n```\n\n---\n\n### `## 5. Iteration Guide` (the load-bearing section)\n\n5–10 numbered rules that encode the most important brand decisions. Each rule is a **single actionable sentence stating what to do, with the specific values from this site.** These are the \"if in doubt, do this\" rules sub-agents consult while composing beats.\n\n**The single most common failure mode is writing generic rules that could apply to any well-designed website.** A rule that doesn't name a specific value, a specific color, or a specific component this brand actually uses is doing nothing.\n\n**Test for any rule you write:** can you swap this brand for a different brand and have the rule still make sense? If yes, it's too generic. If no, ship it.\n\n#### ❌ Generic vs ✅ site-specific\n\n| Generic (delete)                                  | Site-specific (keep)                                                                                                                                                            |\n| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Use the primary brand color for CTAs.             | All primary CTAs use Stripe Purple (`#533AFD`). Secondary actions use white background with `#533AFD` border + text. **There is no third button color anywhere in the system.** |\n| Maintain visual hierarchy through color contrast. | Body text is `#000000` on white, `#FFFFFF` on dark. Metadata uses `#64748D` on white only — never on dark. The brand has no mid-gray text on dark backgrounds.                  |\n| Use clear typographic hierarchy.                  | All type is sohne-var. H1 `48px`/300, H2 `32px`/300, body `14px`/400. **Never use weights above 400** — this brand has no bold variant.                                         |\n| Use consistent spacing.                           | Spacing is from a fixed scale: `4, 8, 12, 16, 20, 24, 32, 40, 60` px. Section gaps are always `60–100px`. Card padding is always `32px`. No exceptions.                         |\n| Buttons should have rounded corners.              | Buttons are `40px` tall minimum, `4px` radius, `15.5px 24px` padding. Pill-shape `9999px` radius is reserved for the floating chat trigger only.                                |\n\n#### One worked example (Framer — 5 rules)\n\n```markdown\n### Iteration Guide\n\n1. **All interactive elements use Framer Blue (`#0000EE`)** — links, primary buttons, active states, focus indicators. Secondary uses `#0099FF` for hover. **No other interactive color exists in the system.**\n\n2. **Typography: GT Walsheim Medium for headings, Inter for body.** Hierarchy enforced through size only, never color. H2 `62px`, H5 `85px`, body `14px`, labels `12px`/500. Text defaults to `#000000` on white, `#FFFFFF` on dark.\n\n3. **Spacing is base-4** — every margin / padding / gap is a multiple of `4px`. Section gaps `60–100px`. **Never use odd values like `13px` or `17px`** — the system has no place for them.\n\n4. **Cards: white (`#FFFFFF`), `1px` border `#EFEFEF`, `8px` radius, `16–20px` padding, no shadow by default.** Dark-mode cards swap to `#1A1A1A` background with `#242424` border. Shadow only appears on hover.\n\n5. **Glass containers** use `rgba(255,255,255,0.9)` background, `1px` border `rgba(255,255,255,0.2)`, optional `backdrop-filter: blur(8px)`. **These are the only place transparent fills appear** — everywhere else uses solid color.\n```\n\nIf your draft has a rule like \"all interactive elements require visible focus states for accessibility\" — delete it. Not wrong, just not load-bearing for _this_ brand.\n\n---\n\n## Rules\n\n- Use **exact values** from `capture/extracted/tokens.json`. Cross-reference with screenshots when needed.\n- Name colors and components descriptively — \"Stripe Purple\" not \"Accent 1.\"\n- When you can't extract exact values, estimate from visual inspection and note it.\n- No \"Assets\" section — `capture/extracted/asset-descriptions.md` is the asset index.\n- No \"Motion\" section — the storyboard specifies motion per-beat.\n- No separate \"Components\" section — Quick Reference is where components live.\n- No \"Depth & Elevation\" tables — shadow language is implied by the brand's mood (heavy shadows for premium, no shadows for flat/clean); sub-agents pick appropriate values without a table.\n\n---\n\n## Quick User Check (before moving to Step 2)\n\n30-second sanity check before Step 2:\n\n> \"Here's what I extracted as [Brand Name]'s visual identity:\n>\n> - **Colors:** [primary], [accent], [2-3 others with roles]\n> - **Fonts:** [headline font], [body font]\n> - **Tone:** [1 sentence on the brand feel]\n>\n> Does this match how you want the video to feel? Any corrections or overrides before I start the storyboard?\"\n\nIf the user has corrections (\"use the blue, not the gray\" / \"ignore the dark mode\" / \"we just rebranded, use [these values] instead\") — update DESIGN.md now. One minute here saves thirty minutes of rebuilding.\n\n---\n\n## What makes a useful DESIGN.md\n\nA sub-agent reading just your Quick Reference + Iteration Guide should be able to:\n\n1. Pick the right color for any primary action, secondary action, body text, error state\n2. Pick the right font/weight/size for any headline, body, metadata\n3. Know which 2-3 rules they cannot break without losing the brand\n\nThat's the test. If they can answer those three questions from a 60–120 line doc, you've nailed it. If they need to read 400 lines of mood-board prose to find a color, you've buried the signal.\n\nFile v1.0.7:references/step-2-brief.md\n\n# Step 2: Strategy & Messaging\n\n**First, scan the Table of Contents in [capabilities.md](capabilities.md)** — the 24-row TOC tells you everything HyperFrames can do. You need this to tell users what's possible. Deep-dive specific sections only if a beat needs them.\n\nYou've captured the site and you now understand the brand — what the product does, who it's for, what voice it speaks in, what mood it lives in. Before any creative decisions, **align with the user on the story this video must tell.** Captured assets exist as a brand toolkit you'll reach for late in Step 3; they are not what the conversation in this step is about.\n\n**Parse the user's prompt first.** Read what they already told you — video type, style, specific requests, duration. Only ask about things they DIDN'T specify. If they said \"product demo, show me the kanban board and chat, moderate pace\" — that's most of the brief already. Don't ask \"what type of video?\" when they literally said \"product demo.\"\n\nSkip questions the user already answered. Ask only what's missing. If the prompt is detailed enough to build from, confirm the direction in one message and move to Step 3. The goal is to fill gaps, not interrogate.\n\n---\n\n## What to Ask\n\nBefore asking the user anything, ground yourself in the brand: skim `DESIGN.md` (just written in Step 1) for colors / fonts / voice; read `capture/extracted/asset-descriptions.md` for what visual assets exist; skim `capture/extracted/visible-text.txt` for what the site says about itself. Don't summarize all of it back to the user — that's noise; they captured the site, they know what's there. Use it to draft a tight one-paragraph framing of the brand and proceed to the questions.\n\nEngage the user with the questions below. Use your agent's question/answer UI if available (multi-choice with custom option). If not, ask conversationally.\n\n### Question 1: What's this video for?\n\nPresent options based on what makes sense for the captured site:\n\n**Example (Not a required options)**\n\n- **Social ad** (15–20s) — Instagram, TikTok, LinkedIn. Fast, punchy, hook in first 2s.\n- **Product demo** (30–60s) — Walk through key features. Narrated, professional.\n- **Launch teaser** (15–25s) — Build hype for a new feature or product. Dramatic reveal.\n- **Brand reel** (20–45s) — Showcase the brand identity. Visual-forward, minimal narration.\n- **Feature announcement** (15–30s) — Highlight a specific feature or update.\n- Or describe something else.\n\nThis determines duration, beat count, narration density, and overall energy.\n\n### Question 2: What style/vibe?\n\nAsk the user to describe what they want — or react to concrete framings that describe motion and energy, not aesthetic presets.\n\nDo NOT present a labeled menu of styles with pre-filled descriptions (\"Cinematic = dark + glow + Apple keynote energy\"). Those descriptions become the brief even when they don't match the brand. \"Cinematic\" for a wellness brand should look completely different from \"cinematic\" for a security tool — but a label with a baked-in description collapses that distinction.\n\nInstead, ask them approachable open-ended questions:\n\n> \"A few questions to get the direction right:\n>\n> - **Pace:** Should the video move slowly and let moments breathe, or be fast and punchy? Or somewhere in between?\n> - **Mood:** What atmosphere matches how you want viewers to feel — dark and dramatic, clean and light, energetic and vibrant, or something else?\n> - **Narration:** Should a voice guide viewers through the video, or let the visuals carry it?\n> - **Anything specific?** Any moments, techniques, or references you're drawn to? Or say 'surprise me' and I'll work from what I found in the capture.\"\n\nTheir answers modify the brand-derived baseline you built in Step 1. When the user's words conflict with the brand, don't blindly override — let the brand and their direction converge. If the conflict is sharp (user says \"dark cinematic\" for a brand whose entire identity is white-and-pastel light), surface it and ask before resolving.\n\n### Question 3: What's the ONE thing this video must communicate?\n\nThis is the strategy question. Every effective marketing video has a single core message — the one idea that has to land. Every beat serves that idea, or it doesn't belong. Get the user to articulate this BEFORE talking about visuals, assets, or specific scenes.\n\nFrame it like this:\n\n> \"From your site, here's the brand frame I'm working from:\n>\n> - **What the product does:** [one sentence from the site summary — not features, the actual job]\n> - **Audience:** [who it's for, derived from copy and visual tone]\n> - **Brand voice:** [confident / playful / clinical / urgent / premium — what tone the brand speaks in]\n>\n> Before we plan visuals, two questions to anchor the story:\n>\n> 1. **What's the ONE thing this video must communicate?** If a viewer remembers only one sentence after watching, what should it be? (the value prop, a launch announcement, a specific feature claim, a brand feeling, a problem-solution pair, etc.)\n> 2. **What's the narrative shape?** Possible arcs: _Problem → Solution_ (most demos), _Reveal_ (launches, teasers), _Demonstration_ (feature showcase, walkthroughs), _Vibe piece_ (brand reels — feeling over information), _Comparison_ (vs. competitor / before-after). Pick or describe your own.\n>\n> Either give me your own answers, or say 'surprise me' and I'll make the call based on the brand and what you said in Question 1 ([video type]).\"\n\nOnce those answers exist, **then** sketch the composed-beat directions — but ground each one in the message and arc, not in the asset list:\n\n> \"Given [the message] and [the arc], here's how I'd shape it:\n>\n> - [Compose-first sketch grounded in the answer to Q1, e.g., \"Open with the problem stated as kinetic typography — 'You waste 4 hours a week on context switches.' Cut to a composed kanban board where cards animate from chaos into organization. Close on the brand mark + tagline.\"]\n> - [Alternative sketch with a different arc, e.g., \"Reveal arc: dark canvas → particles converging → product wordmark drawn stroke-by-stroke as the first feature lands. No problem statement — pure announcement energy.\"]\n> - [If user wants demo: \"Three composed UI panels — kanban, AI chat, command palette — each in your palette with the brand logo stamped top-left. Narration walks through each. Closer holds the wordmark.\"]\n>\n> Brand accents I could layer in: [list 1-3 captured assets that *might* earn a place: the SVG logo for opener/closer, a hero illustration as a depth layer in one scene, a gradient image as an ambient bg wash. Note these are candidates, not assignments — most beats won't need any.]\"\n\n**Important:** Lead every direction with **what the beat communicates**, then with **how it's built** (which primitives). The narrow no-go: if your first instinct is \"the product-UI screenshot flies in,\" flip it — compose the UI from divs and CSS instead. That's the slideshow pattern this skill exists to break. For captured logos, illustrations, and hero art, no flip is needed — they're valid primary visuals when the concept calls for them.\n\nThe captured assets are a brand toolkit you reach for late in the storyboard, where they serve the concept — never as the starting point of the concept itself.\n\nPresent options:\n\n- **I have specific ideas** — let me describe them\n- **Surprise me** — you make the creative calls, I'll review the storyboard\n- **Let me see some options first** — propose 2–3 different creative directions and I'll pick\n\n### Question 4: Narration?\n\nNot every video needs a voiceover. Ask:\n\n- **Yes, with narration** — a voice guides the viewer through the video (most product demos, launch teasers, feature announcements)\n- **No narration, visual-only** — music/SFX only, the visuals tell the story (brand reels, social ads, music-driven pieces)\n- **Minimal narration** — just a hook sentence or tagline, rest is visual (short social ads, teasers)\n\nThis decision changes the pipeline:\n\n- **With narration:** Step 3 includes a full script. Step 4 generates TTS, transcribes, maps timestamps to beats.\n- **Without narration:** Step 3 has no script (VO cues in storyboard are empty). Step 4 is skipped — beat durations are planned manually in the storyboard based on rhythm and pacing.\n\n### Question 5 (if applicable): Format?\n\nOnly ask if not already specified by the user:\n\n- **Landscape** (1920×1080) — YouTube, LinkedIn, website embeds (default)\n- **Portrait** (1080×1920) — Instagram Stories, TikTok, YouTube Shorts\n- **Square** (1080×1080) — Instagram feed, Twitter/X\n\n---\n\n## How to Handle Responses\n\n### \"Surprise me\" / minimal direction\n\nWhen the user gives no creative direction, default to what the brand's visual identity and the video's purpose suggest. The minimum context you need before defaulting: **where the video is going** (social feed / landing page / pitch deck / TV ad) and **who it's for** (developers / consumers / enterprise / general audience). If either is missing, ask once — \"where will this run, and who's the audience?\" — then proceed.\n\nWith that minimum in hand, still write an ambitious storyboard. \"Surprise me\" means \"impress me,\" not \"play it safe.\" Go bold.\n\n**Autonomous mode propagates — for user-preference gates only.** (Mode semantics — signals, propagation, gate types — are canonical in `../../hyperframes-core/references/brief-contract.md`; this section is this workflow's application of them, not a second definition.) When the user signals \"surprise me\" / \"decide for me\" / \"just build it\" here at Step 2, that signal kills downstream user-preference 💬 gates: Step 3's storyboard approval, Step 4's TTS provider choice, music yes/no, captions yes/no. Make those creative decisions yourself and present the finished video at the end. Do not ask four separate questions across four separate steps. Read the room once and commit.\n\n**Auto mode does NOT skip quality-verification gates.** These run regardless and must produce evidence in your final summary:\n\n- Asset Audit (Step 3) — view contact sheets, justify USE/SKIP per asset\n- Per-beat HTML evidence block (Step 5)\n- DoD checklist (Step 6) — animation-map, per-warning WCAG verification, audio + motion playback (or explicit \"deferred\" disclosure)\n- \"What I did NOT verify\" disclosure (Step 6)\n\n**Test for \"preference vs quality gate\":** if the answer changes the _content_ of the video (which voice? captions on? beat 3 cinematic or fast?), it's a preference — auto mode decides. If the answer is \"did the verification happen?\", it's a quality gate — auto mode does NOT apply. Reasoning \"auto mode says bias toward action, so I'll skip the contact sheets\" misuses auto mode.\n\n### Specific direction\n\nIf they say something vague (\"make it really cool\"), push back gently:\n\n> \"I want to make sure I nail what you're imagining. When you say 'cool' — do you mean: dramatic/cinematic(slow reveals and dark atmosphere)? Or high-energy (fast cuts and bold motion)? Or something else entirely?\"\n\n### Mixed direction\n\nParse each component separately. \"Minimal but with cinematic transitions and a fast feature section\" becomes:\n\n- **Base style:** Minimal (moderate pacing, minimal density, elegant motion)\n- **Transitions override:** Dramatic (shader effects for key moments)\n- **Beats 3–5 override:** Fast pacing, balanced density, energetic motion\n\nNote these per-beat overrides — they go into the storyboard.\n\n### \"Let me see options\"\n\nPropose 2–3 brief creative directions (3–4 sentences each) with different **narrative arcs** — what story the video tells, not what assets it shows. Each option leads with the message and the arc; visuals are composed scenes that serve them.\n\n> **Option A — Problem → Solution (cinematic, narrated):** Open with the problem stated as kinetic typography over a dark canvas with a single accent glow. Cut to a composed kanban board where chaotic cards animate into organized columns as narration lands the value prop. Closer: brand mark drawn stroke-by-stroke on a shader bloom of the brand gradient. Apple-keynote register. ~25s with full VO.\n>\n> **Option B — Reveal arc (announcement, music-led):** Cold open: particles converging in darkness, no copy. The product wordmark draws itself across the frame as the first beat lands. Three composed feature panels each unveiled by a hard cut — kinetic typography labels, brand color washes, no screenshots. Closes on the mark + tagline + macOS hint. ~15s, music-driven, minimal narration.\n>\n> **Option C — Demonstration (narrated walkthrough):** Three composed UI scenes — kanban from cards-as-divs, AI chat with typewriter narration sync, command palette with character-typed search — each in the brand palette with the captured logo stamped top-left as identity. CSS crossfades between. Narration walks each one. ~35s, full VO.\n\nEach option states: the arc, the primary visuals carrying it (composed or captured — whichever fits the beat), and any brand accents layered on top. **Never** an option whose primary content is a pasted product-UI screenshot — if you find yourself writing one, flip it: name what gets composed instead. Captured SVGs, illustrations, hero art, and brand photography are fine as primary visuals when the concept calls for them.\n\nLet the user pick one or combine elements.\n\n---\n\n## Gate\n\nLock all of these before moving to Step 3. The first three are the strategic frame Step 3 builds the storyboard from — without them, the storyboard cannot land.\n\n1. **Message** — the ONE thing this video must communicate, in a single sentence. (Required. Step 3 fails without this.)\n2. **Narrative arc** — Problem→Solution / Reveal / Demonstration / Vibe / Comparison / custom. (Required.)\n3. **Audience** — who's watching, where they're watching. (Required.)\n4. **Video type** — social ad / product demo / launch teaser / brand reel / feature announcement / etc. Infer from prompt.\n5. **Duration** — infer from type if not stated (demo: 30-45s, social: 15-20s, teaser: 15-25s).\n6. **Style direction** — pace / mood / specifics — from the user's words, layered onto the brand baseline from Step 1.\n7. **Specific requests** — any scenes/effects/beats they explicitly asked for.\n8. **Narration** — yes / no / minimal.\n9. **Format** — landscape unless specified otherwise.\n\n**Do not ask the user to confirm what they already said.** If the prompt was \"make a product demo for huly.io, show the kanban board, dark cinematic feel, full narration\" — you already have type (demo), style (dark cinematic), specific requests (kanban board), and narration (full). Still need to derive or ask: the **message** (\"the everything app for teams that hate context switches\"), the **arc** (Demonstration), and the **audience** (small teams / fast-moving orgs). Proceed to Step 3 only when all 9 are locked.\n\nFile v1.0.7:references/step-3-storyboard.md\n\n# Step 3: Storyboard + Script\n\nMarketing videos are made concept-first. **The order is: message → narrative arc → beats that serve the arc → which assets and techniques bring each beat to life.** Captured assets (SVG logos, brand illustrations, hero art, gradients) are first-class beat content alongside composed beats — many of them will carry their own beats. The constraint is only that you shouldn't _start_ from the asset inventory (\"we have these screenshots, let's build a slideshow\"). Start from the message, then weave in the right captured assets and the right composed elements per beat.\n\n**Read `capture/extracted/asset-descriptions.md` before writing beats.** Know what's in the capture. The brand's actual visual identity — its real logo, its real illustrations, its real gradients, its real hero art — is what makes the video feel like _this_ brand and not a generic dark cinematic template. Most beats will use one or two captured assets layered with composed motion.\n\n## First decision: CONCEPT\n\nBefore pacing, before beats, before anything else — write the concept block at the top of `STORYBOARD.md`. Carry forward what was decided in Step 2's brief:\n\n```markdown\n**Message:** [the ONE thing this video must communicate — one sentence]\n**Arc:** [Problem→Solution / Reveal / Demonstration / Vibe / Comparison — and a one-sentence shape of how it unfolds]\n**Audience:** [who's watching, where they're watching — TikTok scrollers, LinkedIn viewers, embedded on landing page]\n**Brand voice:** [confident / playful / clinical / urgent / premium — pulled from DESIGN.md]\n**Why this matters now:** [GTM context if relevant — launch, feature ship, brand reposition, ongoing demo]\n```\n\nIf any of those rows are blank, the storyboard cannot land. Go back to the brief — don't substitute \"show the kanban\" for a message.\n\n**The single-sentence test:** _\"What makes this video different from a generic [video type] for any [industry] brand?\"_ If you can't answer it from the rows above, the concept isn't sharp enough. Sharpen it before writing pacing or beats.\n\n---\n\n## Second decision: PACING\n\nWith the concept locked, pick the pacing that serves it. This determines beat count, beat duration, and architecture — every downstream choice flows from here.\n\nRead the message and arc from the concept block above plus the style direction from Step 2's brief. Map to one of these:\n\n| User says                                                   | Pacing       | Beat count | Beat duration | Architecture                                               |\n| ----------------------------------------------------------- | ------------ | ---------- | ------------- | ---------------------------------------------------------- |\n| \"fast\", \"punchy\", \"rapid cuts\", \"energetic\", \"social ad\"    | **Fast**     | 8–15       | 0.7–1.8s      | Single-file stacked beats, hard cuts                       |\n| \"demo\", \"walkthrough\", \"product tour\", \"show features\"      | **Moderate** | 4–6        | 3–5s          | Sub-compositions, CSS crossfades                           |\n| \"cinematic\", \"premium\", \"slow\", \"let it breathe\", \"elegant\" | **Slow**     | 3–4        | 5–8s          | Sub-compositions, long crossfades                          |\n| \"launch\", \"announcement\", \"story\", \"narrative\"              | **Arc**      | 5–7        | varies        | Slow opener → building middle → fast peak → resolved close |\n\n**Write your pacing choice at the top of STORYBOARD.md.** Example: `**Pacing: Fast** — 12 beats, stacked divs, hard cuts.`\n\nIf the user said \"dark cinematic feel\" — that's SLOW, not fast. If they said \"rapid cuts, bold typography\" — that's FAST. Don't default to moderate when the prompt gives you a clear signal.\n\n---\n\n## Technique-pick checklist (REQUIRED, do this BEFORE writing beat copy)\n\nFor every beat you plan, name **2–4 techniques** it will use. A beat with one technique is a slideshow frame — if you can't name two, redesign that beat.\n\nPick from the inventory in [capabilities.md](capabilities.md) and implementation patterns in [techniques.md](../../hyperframes/references/techniques.md). Examples of composable beats:\n\n```\nBeat 3: composed kanban (4 cards-as-divs per column) + counter chip on In-Progress + back.out entrance stagger\n  techniques: layered panels (capabilities §1), counter via tl.set (techniques #15),\n              GSAP stagger with back.out(1.7) (techniques #4)\n  customize:  real project name \"Atlas Q3\", brand purple #5b3fff, realistic backlog items\n```\n\n**Customize is the actual deliverable** — what makes this beat THIS brand's beat. Brand colors, real content, narration-sync timing. Generic \"show the kanban\" with no concrete techniques, no customize plan, no brand-specific data = lazy thinking. Beats must be invented from this brand's identity, not assembled from generic UI shapes.\n\n---\n\n**Re-read these files before writing:**\n\n- **DESIGN.md** — your color palette, font rules, components, Do's/Don'ts. Every visual must be grounded in this brand identity. If it says \"white backgrounds with purple accent\" — plan light scenes, not dark moody ones.\n- **Asset discovery — view the contact sheets carefully, every cell.** Open `capture/assets/contact-sheet-*.jpg` and `capture/assets/svgs/contact-sheet-*.jpg`. Both are paginated — view every page (`contact-sheet-1.jpg`, `contact-sheet-2.jpg`, etc.). **For each page, name 5 specific assets you can see before moving on.** Past agents have reported \"viewed the contact sheet\" after one glance and then wrote beats referencing assets that didn't exist or missed the brand logo entirely. Don't be that agent. When you find an asset that earns its place in a beat, note the filename from the label and reference it as `capture/assets/<filename>`. If a thumbnail is too small to judge resolution / fine detail, open the individual file. Also read `capture/extracted/asset-descriptions.md` for one-line summaries. **Never use contact sheets or scroll screenshots in the video itself** — contact sheets have grid labels baked in; scroll screenshots are raw browser captures. Both are for AI to BROWSE and understand the site, not to place in compositions.\n- **[techniques.md](../../hyperframes/references/techniques.md)** — 13 primitive animation techniques with code patterns. Pick for beats, these are starting points to adapt, not templates to copy.\n- **[text-effects.md](../../hyperframes/references/text-effects.md)** — 24 named text animation effects from the separate `pixel-point/animate-text` skill. The reference page tells you how to load the upstream skill; the IDs are listed inline. Assign a specific effect ID to every headline, label, and copy element in every beat — not generic \"fades in\" descriptions.\n\nThe storyboard is the creative north star. It tells the engineer exactly what to build for each beat — mood, camera, animations, transitions, assets, appearance, sound. Write it as if you're briefing a motion designer who's never seen the website.\n\n**Incorporate the user's specific requests.** If they asked for \"a 3D MacBook reveal\" — that's in the storyboard. If they said \"surprise me\" — go ambitious, but just stay within the style direction.\n\nSave as `STORYBOARD.md` in the project directory.\n\n---\n\n## Consider: Would Research Improve This Video?\n\nBefore diving into beats, pause and think: **would focused research make this video meaningfully better?**\n\nThis is NOT always needed. A simple social ad for a SaaS product probably doesn't need market research. But some videos benefit from context the website alone doesn't provide:\n\n**Research when:**\n\n- The video is for a competitive market — look at how competitors present their product, what visual language the industry uses, what trends are hot\n- The video represents a company/product you know little about — search for reviews, press coverage, user opinions, company history to understand what matters to their audience\n- The user asked for something specific to their field — a fintech launch video benefits from understanding how Stripe, Ramp, Mercury position themselves visually\n- The video needs to reference real-world data, trends, or context not on the website\n\n**Skip research when:**\n\n- It's a straightforward brand reel or social ad from a clear website\n- The user gave very specific creative direction (\"I want exactly X, Y, Z\")\n- The website already contains all the context needed (features, stats, testimonials)\n\n**What to research:** Competitor videos in the space, trending visual styles for the industry, audience expectations, any company context that helps you make better creative decisions. A 2-minute web search can give you the edge between a generic video and one that feels like it was made by someone who understands the market.\n\n---\n\n## Global Direction\n\nEvery STORYBOARD.md starts with global settings:\n\n```markdown\n**Format:** 1920×1080\n**Audio:** [TTS provider] voiceover + underscore + SFX\n**VO direction:** [voice character — e.g., \"mid-age male, calm confident delivery,\nApple keynote register — economy of words, silence between sentences is a feature\"]\n**Style basis:** DESIGN.md (brand colors, fonts, components from the captured site)\n```\n\n**Global guardrails** — read [video-composition.md](../../hyperframes/references/video-composition.md) first. It defines the medium rules: density, color presence, scale, frame composition, and how design.md is brand truth not layout spec. Then apply these capture-specific additions:\n\n- Captured assets are accents on composed beats, not the beats themselves — see Asset Audit below for which assets earn a place (typically 2-4 across the whole video).\n- Use different techniques from techniques.md — not across the whole video, per beat. Don't default to basic fade/scale/opacity — mix in SVG path drawing, HTML-in-canvas, shaders, scrolling effects or movement effect, CSS 3D transforms, typing effects, counter animations, canvas procedural art. Each beat should feel like its own visual world. Use as many as makes sense for the storyboard.\n\n**Underscore/music direction** (if applicable):\n\n- Describe the mood, reference artists, when it swells or drops\n- Example: \"Minimal electronic. Warm sustained pad already playing when the video starts. Sits underneath everything, never competing with VO. Swells gently during the flex section, drops to near-nothing for the comparison, resolves on a final chord.\"\n\n---\n\n## Required Capabilities Discovery\n\nBefore writing any beats, you have to run these commands and paste the output below the Global Direction section. This tells you what's available beyond the standard techniques.\n\n```bash\n# 1. Check available shader transitions (installed in registry/blocks/)\nls registry/blocks/ 2>/dev/null | grep -E 'chromatic|cinematic|cross-warp|domain-warp|flash|glitch|gravitational|light-leak|ridged|ripple|sdf|swirl|thermal|whip' || echo \"No shader transitions installed\"\n\n# 2. Check available VFX blocks\nls registry/blocks/ 2>/dev/null | grep vfx || echo \"No VFX blocks installed\"\n\n# 3. Browse what's available to install\nnpx hyperframes catalog --type block 2>/dev/null | head -40\n```\n\nThere might be VFX blocks available (vfx-liquid-glass, vfx-iphone-device, vfx-shatter, vfx-portal, etc.), use them for hero treatments instead of basic perspective tilt. You need to install any you want with `npx hyperframes add <name>`. Don't use too many shaders — maximum 2 per video unless user wants differently.\n\n**Shader transitions — block name ≠ shader name.** When you run the commands above and see `domain-warp-dissolve` in `registry/blocks/`, the HyperShader runtime name is `domain-warp` (without \"-dissolve\"). After installing a block, open its showcase HTML (`compositions/<block-name>.html`) and find the actual shader name used in `HyperShader.init()`. That is what you put in the storyboard. Then delete the showcase file — it's a demo only and will pollute your compositions/ directory with lint warnings.\n\n## Asset Audit — REQUIRED before writing beats (non-skippable)\n\nThe skill's #1 purpose is to USE the brand's captured assets — not rebuild them from CSS. Most of your beats should feature at least one captured asset: a hero illustration, a signature SVG, product photography, brand mark, distinctive graphic. **If your STORYBOARD.md ends with only the logo used, you have failed this step.**\n\n**Why this gate exists:** Earlier sessions wrote their own \"Asset Audit\" that said SKIP for 60+ of 65 captured assets, used only the logo, and shipped a video that visually was indistinguishable from a generic dark-mode SaaS launch. The captured MetaBrain illustration, the GitHub-sync diagram, the knowledge-base hero — all left on the floor. The signature visuals that make a brand recognizable were absent. Don't repeat that.\n\n**Required pre-storyboard procedure:**\n\n1. **View every page of `capture/assets/contact-sheet-*.jpg`** AND every page of `capture/assets/svgs/contact-sheet-*.jpg`. These are the sheets generated by capture for this exact purpose. Open each page; scan cell-by-cell. Do not skim — you are looking for the brand's visual identity, frame by frame.\n\n2. **For each contact sheet page, paste this block into STORYBOARD.md under an \"Asset Audit\" section:**\n\n```\nContact sheet: capture/assets/contact-sheet-1.jpg (page 1 of N)\n  5 most visually distinctive assets I see (filename + one-sentence description of what the image shows):\n  1. <filename>: <what's actually pictured — not the filename, the content>\n  2. <filename>: <description>\n  3. <filename>: <description>\n  4. <filename>: <description>\n  5. <filename>: <description>\n```\n\nRepeat for every contact sheet page. The number of pages × 5 is your candidate asset pool.\n\n3. **For each beat in STORYBOARD.md**, choose USE or SKIP for each candidate asset:\n   - **USE** means the asset appears in the beat's HTML at build time (`<img src=...>`, inline SVG, `background-image: url(...)`).\n   - **SKIP** requires a one-sentence reason explaining why this asset doesn't serve this beat. \"Doesn't fit storyboard\" is not a reason — name which storyboard moment failed to find a use for it.\n\n4. **Brand-defaults floor:** at least ONE beat must use the brand's signature visual (hero illustration, hero photograph, or signature diagram — not the logo). If you've named 5+ candidate hero illustrations in step 2 above and zero of them appear in any beat, that is the failure mode this gate exists to catch.\n\n**Forbidden:**\n\n- Writing \"SKIP\" for every asset except the logo without per-asset justification\n- Reading `capture/extracted/asset-descriptions.md` (the text file) and making decisions from filenames alone, without opening the contact sheets\n- Concluding \"I'll rebuild the GitHub-sync diagram in CSS\" when the brand's own SVG of that diagram is sitting in `capture/assets/`. Use the real asset.\n\nIf your final beat list uses less than ~30% of relevant captured assets (relevant = anything except the favicon and tiny UI icons), revisit. The brand is visually carried by its own art; rebuilding it from divs erases what makes it recognizable.\n\n### HTML-in-Canvas — plan for it here, build in Step 5\n\nThe `drawElementImage` Chrome API captures any live HTML/CSS as a GPU-accelerated texture at 60fps. This is HyperFrames' highest-impact capability — it lets you render captured product screenshots or UI through:\n\n- **3D geometry** — a rotating iPhone or laptop model, a sphere, a curved surface\n- **WebGL shaders** — liquid glass refraction, shatter into fragments, portal reveal, noise distortion\n- **Post-processing** — bloom, depth-of-field, film grain, color grading\n\nWhen planning beats, decide which ones deserve an HTML-in-Canvas treatment vs. a standard GSAP animation. If you want it, name it in the storyboard — Step 5 will read [`../../hyperframes/references/html-in-canvas-patterns.md`](../../hyperframes/references/html-in-canvas-patterns.md) for implementation. You don't need to specify the API details here.\n\n### SFX assignment — happens here, not in Step 5\n\n**Before writing beats,** read the SFX manifest. Locate it from your current directory:\n\n```bash\nfind \"$HOME\" -path '*/website-to-video/assets/sfx/manifest.json' -maxdepth 10 2>/dev/null | head -1\n```\n\nOr if you already copied SFX into the project (Step 5 does this), read your local `sfx/manifest.json`. Each entry has a filename, duration in seconds, and description. Assign **specific SFX files** to exact moments in the storyboard. Step 5 implements what you specify here — it makes no SFX decisions.\n\nPer beat, specify SFX like:\n\n- `sfx/impact-bass-1.mp3` at `0.2s`, volume `0.35` — on the hero image snapping into frame\n- `sfx/chime.mp3` at `3.8s`, volume `0.5` — on the logo appearing\n\n**Less is more.** Most beats need zero SFX. One SFX per beat is typical; multiple only if the beat has genuinely distinct punctuation moments. Never place SFX on shader transitions directly — shader transitions are already an audio-visual event.\n\n**How to place each sound type** (industry-standard rules):\n\n- **Impact/hit sounds** (`impact-bass-1`, `ping`, `pop`, `glitch-*`): peak is at the start of the clip. Trigger exactly at the\n\nArchive v1.0.6: 15 files, 109284 bytes\n\nFiles: assets/sfx/CREDITS.md (1183b), assets/sfx/manifest.json (4313b), references/beat-builder-guide.md (20886b), references/capabilities.md (57750b), references/step-0-capture.md (4087b), references/step-1-design.md (20761b), references/step-2-brief.md (14955b), references/step-3-storyboard.md (49367b), references/step-4-vo.md (13180b), references/step-5-build.md (28215b), references/step-6-validate.md (23447b), scripts/w2h-verify.mjs (28755b), skill-card.md (3052b), SKILL.md (12773b), _meta.json (135b)\n\nArchive v1.0.5: 15 files, 109117 bytes\n\nFiles: assets/sfx/CREDITS.md (1183b), assets/sfx/manifest.json (4313b), references/beat-builder-guide.md (20886b), references/capabilities.md (57750b), references/step-0-capture.md (4087b), references/step-1-design.md (20761b), references/step-2-brief.md (14955b), references/step-3-storyboard.md (49367b), references/step-4-vo.md (13180b), references/step-5-build.md (28215b), references/step-6-validate.md (23447b), scripts/w2h-verify.mjs (28755b), skill-card.md (3056b), SKILL.md (12336b), _meta.json (135b)\n\nArchive v1.0.4: 15 files, 108828 bytes\n\nFiles: assets/sfx/CREDITS.md (1183b), assets/sfx/manifest.json (4313b), references/beat-builder-guide.md (20886b), references/capabilities.md (57750b), references/step-0-capture.md (4087b), references/step-1-design.md (20761b), references/step-2-brief.md (14747b), references/step-3-storyboard.md (48505b), references/step-4-vo.md (13180b), references/step-5-build.md (28215b), references/step-6-validate.md (23447b), scripts/w2h-verify.mjs (28755b), skill-card.md (3108b), SKILL.md (12172b), _meta.json (135b)\n\nArchive v1.0.3: 15 files, 108712 bytes\n\nFiles: assets/sfx/CREDITS.md (1183b), assets/sfx/manifest.json (4313b), references/beat-builder-guide.md (20886b), references/capabilities.md (57750b), references/step-0-capture.md (4087b), references/step-1-design.md (20761b), references/step-2-brief.md (14747b), references/step-3-storyboard.md (48505b), references/step-4-vo.md (13180b), references/step-5-build.md (28215b), references/step-6-validate.md (23447b), scripts/w2h-verify.mjs (28755b), skill-card.md (3082b), SKILL.md (11915b), _meta.json (135b)\n\nArchive v1.0.2: 15 files, 108722 bytes\n\nFiles: assets/sfx/CREDITS.md (1183b), assets/sfx/manifest.json (4313b), references/beat-builder-guide.md (20886b), references/capabilities.md (57750b), references/step-0-capture.md (4087b), references/step-1-design.md (20761b), references/step-2-brief.md (14747b), references/step-3-storyboard.md (48505b), references/step-4-vo.md (13180b), references/step-5-build.md (28215b), references/step-6-validate.md (23447b), scripts/w2h-verify.mjs (28755b), skill-card.md (3266b), SKILL.md (11865b), _meta.json (135b)\n\nArchive v1.0.1: 15 files, 108568 bytes\n\nFiles: assets/sfx/CREDITS.md (1183b), assets/sfx/manifest.json (4313b), references/beat-builder-guide.md (20886b), references/capabilities.md (57750b), references/step-0-capture.md (4087b), references/step-1-design.md (20761b), references/step-2-brief.md (14747b), references/step-3-storyboard.md (48505b), references/step-4-vo.md (13180b), references/step-5-build.md (28215b), references/step-6-validate.md (23447b), scripts/w2h-verify.mjs (28755b), skill-card.md (2517b), SKILL.md (12124b), _meta.json (135b)\n\nArchive v1.0.0: 15 files, 108682 bytes\n\nFiles: assets/sfx/CREDITS.md (1183b), assets/sfx/manifest.json (4313b), references/beat-builder-guide.md (20886b), references/capabilities.md (57750b), references/step-0-capture.md (4087b), references/step-1-design.md (20761b), references/step-2-brief.md (14747b), references/step-3-storyboard.md (48505b), references/step-4-vo.md (13180b), references/step-5-build.md (28215b), references/step-6-validate.md (23447b), scripts/w2h-verify.mjs (28755b), skill-card.md (2865b), SKILL.md (12132b), _meta.json (135b)","readmeExcerpt":"Skill: Website To Video Owner: heygen-com Summary: Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand... Tags: latest:1.0.7 Version history: v1.0.7 | 2026-07-10T22:50:42.522Z | user Synced from 00d059b (main) v1.0.6 | 2026-07-10T02:58:02.499Z | user Synced from a8f242e (main) v1.0.5 | 2026-07-08T18:02:16.584Z | u","codeSnippets":[],"executableExamples":[{"language":"html","snippet":"<template>\n  <style>\n    * {\n      margin: 0;\n      padding: 0;\n      box-sizing: border-box;\n    }\n    /* your styles */\n  </style>\n\n  <div\n    id=\"beat-N-name\"\n    data-composition-id=\"beat-N-name\"\n    data-width=\"1920\"\n    data-height=\"1080\"\n    style=\"width:1920px; height:1080px; position:relative; overflow:hidden; background:#YOUR_BG;\"\n  >\n    <!-- your elements -->\n  </div>\n\n  <script>\n    (function () {\n      var BEAT = 5.5; // MUST match data-duration on the host div in index.html\n      window.__timelines = window.__timelines || {};\n      var tl = gsap.timeline({ paused: true });\n\n      // your GSAP animations\n\n      window.__timelines[\"beat-N-name\"] = tl;\n    })();\n  </script>\n</template>"},{"language":"bash","snippet":"npx hyperframes lint ."},{"language":"bash","snippet":"npx hyperframes snapshot . --frames 3"},{"language":"text","snippet":"FLAG: at beat-local t=1.2s the doc card is visible but its inner content is still\n       opacity 0 — a 0.4s empty-panel window.\n       RECOMMENDED FIX: pull title typewriter from 1.6s → 1.4s\n       in compositions/beat-5-name.html line 234."},{"language":"text","snippet":"FLAG: STORYBOARD.md beat 3 says \"Row 1 transitions blue → orange at 3.5s\" but\n       Row 1's initial color is not specified anywhere. I interpreted Row 1 starts\n       blue and tweened to orange. CONFIRM or correct."},{"language":"js","snippet":"HyperShader.init({\n  bgColor: \"#0b0f14\",\n  accentColor: \"#f59e42\",\n  scenes: [\"scene1\", \"scene2\"],\n  transitions: [{ time: 3, shader: \"sdf-iris\", duration: 0.65, ease: \"power2.inOut\" }],\n  timeline: gsap.timeline({ paused: true }),\n  compositionId: \"main\",\n  previewCaptureFps: 30,\n});"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: website-to-video\ndescription: \"Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand assets. Use for portfolio / blog / docs / landing-page showcases. Not a product launch or promo, even from a URL (/product-launch-video). Unclear → /hyperframes.\"\n---\n\n> **First, keep this skill fresh — run silently, don't ask:** `npx hyperframes skills update website-to-video`. A fast no-op when everything is current; otherwise it refreshes this skill plus the core domain skills it depends on before you rely on them.\n\n> **media-use**: Before sourcing audio/images/logos, call `/media-use` to resolve BGM/SFX/images from the HeyGen catalog and brand logos from their official sources. Run `--adopt` first to register existing assets. See `/media-use` skill.\n\n> **figma source**: If the URL is a figma.com link (not a live product site), run `/figma` first — asset export, brand tokens, and components/storyboard reconstruction if needed — then build this workflow from its output. Don't drive Figma via raw MCP tools directly: that skips SVG sanitization, `.media/manifest.jsonl` provenance, and brand-token `var()` binding, so a later brand change can't propagate without a full re-import.\n\n# Website to HyperFrames\n\nCapture a website, then produce a professional video from it.\n\n> **Confirm the route before Step 0.** This skill makes a video _of / from a general site_. If the user is really **marketing / launching / promoting a product** (even from this URL, even \"promo for our site\") → `/product-launch-video`. A **topic explainer with no site** → `/faceless-explainer`; a **GitHub PR** → `/pr-to-video`; **re-cutting / recoloring / reordering an existing video file** → out of scope. Routed here on a vague \"make a video\", or unsure launch-vs-general-site? **Read `/hyperframes` first** (full routing table + § What HyperFrames cannot do).\n\nUsers say things like:\n\n- \"Turn this website into a 15-second social clip for Instagram\"\n- \"Make a 30-second site tour / showcase from https://...\"\n- \"Capture our homepage and build a video from its own visuals\"\n\nThe workflow has 7 steps. Each produces an artifact that gates the next. By default it's collaborative — gates marked 💬 stop and ask the user. Mode semantics (signals, propagation, gate taxonomy) are canonical in `../hyperframes-core/references/brief-contract.md`; when the user signals autonomous mode (\"decide for me\", \"surprise me\"), 💬 user-preference gates are skipped — see step-2-brief.md for how that propagates through this workflow.\n\n**Autonomous mode is NOT \"skip all gates\"** (brief contract § 1). It covers user-preference questions (TTS provider, voice, color emphasis, beat count, music yes/no, captions yes/no — where the agent decides on the user's behalf). It does NOT cover quality-verification gates. The following remain non-skippable in auto mode:\n\n- Asset Audit (Step 3) — viewing contact sheets and justifying U"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn77d06grj6xqp3dqwkk4bavhn89pegt\",\n  \"slug\": \"website-to-video\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1783723842522\n}"},{"path":"references/beat-builder-guide.md","content":"# Beat Builder Guide\n\nYou are building ONE beat of a multi-beat video composition. This file tells you what to read, how to build, how to verify, and how to report back.\n\n## Step 1: Read and understand\n\n**Required (every beat):**\n\n1. **Load the `hyperframes` skill** — composition rules, data attributes, timeline contract, deterministic rendering. Read the whole skill.\n2. **[capabilities.md](capabilities.md)** — full inventory of HyperFrames capabilities (24 sections). Read the Table of Contents first, then deep-dive sections your beat needs.\n3. **The beat spec** the main agent gave you — concept, choreography, assets, brand values, timing.\n\n**Read based on what your beat needs (pick relevant ones):**\n\n| Resource                                                                              | What it covers                                                                                                                | Read when                                         |\n| ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |\n| [techniques.md](../../hyperframes/references/techniques.md)                           | 13 primitive animation techniques: SVG path drawing, Canvas 2D, CSS 3D, kinetic type, variable fonts, MotionPath, etc.        | Beat uses any of these techniques                 |\n| [text-effects.md](../../hyperframes/references/text-effects.md)                       | 24 named text animations from `pixel-point/animate-text` (separate skill — load via `/animate-text` for specs)                | Beat has text animation                           |\n| [html-in-canvas-patterns.md](../../hyperframes/references/html-in-canvas-patterns.md) | HTML-in-Canvas: iPhone/MacBook mockups, liquid glass, magnetic, portal, shatter, text cursor                                  | Beat uses device mockups or WebGL effects on HTML |\n| [transitions.md](../../hyperframes/references/transitions.md)                         | Shader transition API, HyperShader.init() pattern, all 14 WebGL shaders                                                       | Beat has shader transitions                       |\n| [transitions/](../../hyperframes/references/transitions/)                             | 14 CSS transition category files: push, scale, dissolve, blur, 3D flip, light leak, distortion, grid, mechanical, destruction | Beat uses CSS transitions                         |\n| [css-patterns.md](../../hyperframes/references/css-patterns.md)                       | Text markers: highlight sweeps, hand-drawn circles, burst lines, scribble, sketchout                                          | Beat uses text emphasis/markers                   |\n| [audio-reactive.md](../../hyperframes/references/audio-reactive.md)                   | Bass→scale, mid→shape, treble→glow mapp"},{"path":"references/capabilities.md","content":"# HyperFrames — Complete Capabilities Inventory\n\nEverything possible in HyperFrames as of today's workspace, synthesized from direct source reads of all 7 packages, 16 skills, and the full registry.\n\n> **How to read this file.** Scan the **Table of Contents** below first. **Do NOT read this file linearly** — it is a 700+ line inventory; reading top-to-bottom every session wastes context. When the storyboard or a specific beat needs a particular capability (HTML-in-Canvas, shader transitions, audio-reactive, dynamic counters, etc.), jump straight to that section.\n\nYou are NOT limited to what was captured from the website. You can create shaders from scratch, search for and download registry blocks, build Three.js scenes, write custom WebGL effects, use any web API — anything a browser can render.\n\nFor implementation patterns (working code), see `techniques.md`. This file is the WHAT; techniques.md is the HOW.\n\n## Essential Rules\n\n- **Deterministic:** No `Math.random()`, no `Date.now()`, no `requestAnimationFrame`, no `repeat: -1`. The render engine seeks to exact timestamps.\n- **Timeline contract:** `window.__timelines[\"composition-id\"] = tl` must be set synchronously. The timeline length defines the composition duration.\n- **Sub-compositions:** External `.html` files loaded via `data-composition-src`. Auto-nested timelines, scoped CSS, scoped scripts.\n- **Linter:** 60+ rules. Run `npx hyperframes lint` before render. Catches missing timelines, overlapping clips, broken paths, GSAP errors.\n\n## Table of Contents\n\n| #   | Section                                              | What it covers                                                                                                                                                                                                                  |\n| --- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 1   | **Composition fundamentals**                         | Data attributes, timeline contract, resolution presets (1080p, 4K, portrait, square, custom)                                                                                                                                    |\n| 2   | **Animation engines (6 adapters)**                   | GSAP + 15 plugins, Anime.js v4, CSS @keyframes, WAAPI, Lottie (lottie-web + dotlottie), Three.js (hf-seek event)                                                                                                                |\n| 3   | **Shader transitions (14 WebGL)**                    | domain-warp, ridged-burn, whip-pan, sdf-iris, ripple-waves, gravitational-lens, cinematic-zoom, chromatic-split, swirl-vortex, thermal-distortion, flash-through-white, cross-warp-morph, light-leak, glitch — plus custom GLSL |\n| 4   | **CSS scen"},{"path":"references/step-0-capture.md","content":"# Step 0: Capture\n\nThe capture pipeline downloads the site and extracts structured data for the rest of the workflow to read. Step 0 is a single command plus a sanity check. **All analysis (reading files, viewing contact sheets, deriving brand voice, picking assets) happens in Steps 1–3, not here.**\n\n## Run the capture\n\nNo API keys required for the base capture. However, before running, ask the user:\n\n> \"For the best results, it is recommended to set a Gemini API key — it gives me AI-powered descriptions of every captured image, which helps me choose the right assets for each scene. It costs about $0.001 per image. You can skip this if you want, but the video quality will be better with it. To set it up: add `GEMINI_API_KEY=your-key` to a `.env` file in the project root. You can get a free key at ai.google.dev.\"\n\nIf the user provides the key or already has one set, proceed. If they skip it, proceed anyway — the capture works without it, but `asset-descriptions.md` will have DOM-context descriptions only (position, size, alt text) instead of AI vision descriptions.\n\nCreate a project directory for your video if it doesn't exist yet, then capture the website into a `capture/` subfolder within it:\n\n```bash\nnpx hyperframes capture <URL> -o <project-dir>/capture\n```\n\nExample: `npx hyperframes capture https://stripe.com -o videos/stripe-launch/capture`\n\nKeeping capture artifacts (`screenshots/`, `assets/`, `extracted/`, `AGENTS.md`, `CLAUDE.md`) in a dedicated `capture/` subfolder keeps them isolated from later build files (`SCRIPT.md`, `STORYBOARD.md`, `DESIGN.md`, `compositions/`, `index.html`, `narration.wav`, `transcript.json`, `renders/`, `snapshots/`), which all live at `<project-dir>/` root.\n\nFor exploratory captures that aren't becoming a video yet, the default `./capture/` (or any `-o <name>` you pick) is fine — the isolation convention only matters when you're building a video on top of the capture.\n\n## Confirm it succeeded\n\nWait for the capture to complete. Print one line summarizing what was captured:\n\n> \"Captured N screenshots, M assets, K SVGs, F fonts. Ready for Step 1.\"\n\nIf the command exited non-zero, the counts are all zero, or required directories (`extracted/`, `assets/`, `screenshots/`) are missing, surface the error and stop — don't advance to Step 1 with a broken capture.\n\n## What lives in `capture/` (reference table — DO NOT read these here)\n\nEach downstream step reads only what it needs. Don't pre-fetch everything in Step 0; that bloats context and produces summaries that get stale by the time they're used.\n\n| Path                                      | First read in                                 |\n| ----------------------------------------- | --------------------------------------------- |\n| `capture/extracted/tokens.json`           | Step 1 (DESIGN.md — colors / fonts)           |\n| `capture/extracted/design-styles.json`    | Step 1 (DESIGN.md — typography / components)  |\n| `capture/extracted/fonts-manifest.json`   | Step 1"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand... Skill: Website To Video Owner: heygen-com Summary: Capture a general website/URL and turn it into a video OF the site — tour, showcase, or social clip built from captured screenshots and the site's own brand... Tags: latest:1.0.7 Version history: v1.0.7 | 2026-07-10T22:50:42.522Z | user Synced from 00d059b (main) v1.0.6 | 2026-07-10T02:58:02.499Z | user Synced from a8f242e (main) v1.0.5 | 2026-07-08T18:02:16.584Z | u","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1855,"uniquenessScore":50,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T18:59:34.932Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T18:59:34.932Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T21:54:07.485Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}