Files
hyperframes/skills/talking-head-recut/references/DESIGN_INDEX.md
T
56859b618f refactor(skills): rename graphic-overlays skill to talking-head-recut (#1720)
Rename the `graphic-overlays` workflow skill to `talking-head-recut`:

- move skills/graphic-overlays/ -> skills/talking-head-recut/
- update SKILL.md frontmatter name, H1, and self-references
- update all /graphic-overlays route references (hyperframes router,
  general-video, root + cli-template AGENTS.md/CLAUDE.md, docs, quickstart)
- update telemetry --skill flag, example composition id, timeline key
- update .prettierignore path and scripts/test-skills-fresh.sh

Identifier-only rename: the graphic-overlay card mechanism, design
references, and trigger wording are unchanged.

Co-authored-by: kiritowoo <295860553+kiritowoo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 00:32:51 +08:00

146 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# V—Take Visual Design Library
This directory is a **reference library** for the talking-head-recut skill. Style, layout,
and video frame are three **orthogonal** dimensions you can freely mix when
designing a takeaway video.
```
Style × Layout × VideoFrame
(10) (4) (3) = 120 possible combinations
```
Read a reference file when you decide to use that dimension. Each file is a
self-contained HTML fragment that follows the talking-head-recut card-HTML contract
(scoped `<style>`, no `<script>`, no external URLs, animations only via
`data-anim-*`).
## Layouts — how video and card share the canvas
| key | file | what it does | best for |
| --------- | -------------------------------------------- | ------------------------------------------------------- | --------------------------------------- |
| `split` | [layouts/split.html](layouts/split.html) | 50/50 side-by-side (landscape) or top/bottom (portrait) | speaker + data equal weight |
| `stack` | [layouts/stack.html](layouts/stack.html) | video on top (~52%), card below | talking-head with summary card |
| `pip` | [layouts/pip.html](layouts/pip.html) | card fills canvas, video rounded PiP in corner | content-heavy moment, speaker secondary |
| `overlay` | [layouts/overlay.html](layouts/overlay.html) | video full-bleed, glass card floats on bottom | cinematic / dramatic moments |
A layout is a **two-part recipe**: pick a `card.zone` value to put in
`storyboard.json` AND author a GSAP tween for `#video-wrap` to its
target rect in the composition's `<script>`. Open the layout file's
header for the recommended `zone` + the GSAP statement to paste.
(Earlier docs referenced a `card.layout` field — that field does NOT
exist in the real schema; the strict v3 schema only has `card.zone`.)
## Styles — the card's visual language
| key | file | character | accent | suggested font |
| ------------ | ------------------------------------------------ | ---------------------------------------------------- | --------- | ------------------- |
| `academic` | [styles/academic.html](styles/academic.html) | warm paper · grid · serif · blue highlight | `#2557a7` | serif |
| `editorial` | [styles/editorial.html](styles/editorial.html) | cream · coral block · big italic quote | `#ff3a2d` | Playfair-like serif |
| `minimal` | [styles/minimal.html](styles/minimal.html) | pure black/white · huge type · generous space | `#000` | Inter |
| `spotlight` | [styles/spotlight.html](styles/spotlight.html) | dark purple gradient · glow · dramatic | `#a78bfa` | sans |
| `geom` | [styles/geom.html](styles/geom.html) | chartreuse + hot pink + black collision | `#d4ff00` | Inter bold |
| `whiteboard` | [styles/whiteboard.html](styles/whiteboard.html) | paper · Caveat handwriting · sketched borders | `#ff6b35` | Caveat |
| `audit` | [styles/audit.html](styles/audit.html) | manila paper · justified serif · APPROVED stamp | `#8b1d1d` | serif |
| `terminal` | [styles/terminal.html](styles/terminal.html) | dark · monospace · ASCII border · prompt cursor | `#4ade80` | mono |
| `swiss` | [styles/swiss.html](styles/swiss.html) | white · Helvetica · strict double rules · red accent | `#e8190f` | Helvetica/Inter |
| `xhs` | [styles/xhs.html](styles/xhs.html) | cream + hot pink · chips · #hashtags · ❤️💬 row | `#ff2e63` | sans |
Choose by content tone, not by content type — `academic` works for finance
too if the tone is reflective; `terminal` works for non-tech if the tone is
"engineering rigor".
## Video Frames — decoration around the video element
| key | file | character | when to skip |
| ---------- | -------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------ |
| `clean` | [frames/clean.html](frames/clean.html) | no decoration; raw video | default; safest |
| `hairline` | [frames/hairline.html](frames/hairline.html) | double-stroke + four-corner viewfinder ticks | over `overlay` layout (clashes with full-bleed) |
| `polaroid` | [frames/polaroid.html](frames/polaroid.html) | white photo frame + Caveat label + blue washi tape (no tilt) | over `overlay` layout; portrait PiP gets cramped |
A frame is a decorative div that sits **next to** the `#video-wrap` inside
the composition's `#stage`. It is one-time HTML (not animated), but you can
fade it in/out across cards. See each frame file for the placement snippet
and the inline `<style>` it needs.
## Decision guide (loose, not prescriptive)
| video content | suggested combos |
| -------------------------------- | -------------------------------------------------------- |
| interview / dialogue | `academic` × `stack`, `audit` × `split` |
| product launch / announcement | `editorial` × `overlay`, `geom` × `pip` |
| data analysis / financial report | `audit` × `split`, `swiss` × `stack`, `terminal` × `pip` |
| social clip (9:16) | `xhs` × `overlay`, `editorial` × `stack` |
| technical tutorial | `terminal` × `split`, `whiteboard` × `pip` |
| emotional story / narration | `spotlight` × `overlay`, `whiteboard` × `overlay` |
| minimalist presentation | `minimal` × `split`, `swiss` × `overlay` |
These are starting points only. Look at the transcript, pick the tone, then
pick the visual.
## Portrait sizing — bigger type for mobile
Every `references/styles/*.html` is sized for a **1920×1080 landscape**
preview. When the final composition is **portrait (1080×1920)** — the
default for social / mobile — scale every visual size up so it reads on a
phone held close.
| token | landscape | **portrait** | scale |
| --------------------- | --------- | ------------ | ----- |
| hero title (h1/h2) | 6496px | **88132px** | ×1.35 |
| detail / body | 2430px | **3040px** | ×1.30 |
| kicker / chip / meta | 1418px | **1822px** | ×1.25 |
| primary number / stat | 4860px | **6488px** | ×1.40 |
| horizontal padding | 4064px | **2436px** | ÷1.5 |
`portraitPx ≈ round(landscapePx × 1.3)`. Hero headlines can go ×1.4;
small meta stays at ×1.2. Padding **shrinks** in portrait since the card
is narrower.
For a card that must work in both, use a container query on the card
root: `container-type: inline-size` + `font-size: clamp(64px, 8.5cqi, 132px)`.
## Source aspect ratio independence
Output canvas is independent of source video aspect. Three supported
output ratios (selected by the user in Step 7.0 of SKILL.md):
| ratio | canvas | `storyboard.layout` | best for |
| ------ | --------- | ------------------------------------------------------ | ---------------------------------------------------------- |
| `16:9` | 1920×1080 | `"landscape"` | YouTube / TV / desktop playback |
| `9:16` | 1080×1920 | `"portrait"` | TikTok / Reels / short-form mobile |
| `4:5` | 1080×1350 | `"portrait"` (schema treats 4:5 as portrait since h>w) | Instagram feed / WeChat Moments / works for both platforms |
The layout reference files in `layouts/` document **landscape** and
**portrait** bounds only. For **4:5** derive bounds by proportional
vertical scaling from portrait: `4:5 y/h = round(portrait y/h × 0.703)`,
keep `x/w` identical. The composer doesn't care about the named layout
value; it just uses `composition.width × height`.
- Landscape video on landscape canvas → `videoBounds` matches video aspect, no letterbox
- Portrait video on landscape canvas → `videoBounds` is a narrower box (e.g. `pip` becomes 248×440); empty side filled by card or background
- Landscape video on portrait canvas → `videoBounds` becomes a wide-but-short band; `stack` and `overlay` work best
- Portrait video on portrait canvas → most natural; any layout
The layout reference files show landscape values; for portrait you usually
flip the long axis: `split` becomes top/bottom, `pip` video bubble shrinks
~20%, `overlay` card slot widens to full width.
## Constraints you must obey when copying from these references
1. **No `<script>`** — animations only via `data-anim-*` attributes
2. **No external URLs** — no Google Fonts CDN, no remote images; the
skill provides Caveat / LXGW WenKai TC / Inter / Virgil locally
3. **All `<style>` rules must be prefixed with `.card[data-card-id="..."]`**
the hyperframes sanitizer auto-scopes them, but write them already-scoped to
stay readable
4. **No `on*=` inline handlers**
5. **CSS variables for colors** when you want a card to switch theme cleanly;
inline hex when you want this specific style's signature look
If a reference uses a font you don't have, fall back:
- Playfair Display / Noto Serif SC → `ui-serif, "Songti SC", "Times New Roman", serif`
- Noto Sans SC → `ui-sans-serif, system-ui, sans-serif`
- JetBrains Mono → `ui-monospace, "SF Mono", Menlo, monospace`
- Kalam → `'Caveat', cursive`