Add HyperFrames skills
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011h6NB8JQtfPc6eRCefEzBB
This commit is contained in:
964 files changed
+142321
No files matched your search
@@ -0,0 +1,164 @@
|
||||
<!--
|
||||
Layout: overlay — video full-bleed, glass card floats on bottom
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Implementation: card.zone = "video-overlay" + leave #video-wrap at
|
||||
full-bleed (no tween needed if it starts full-bleed). The "card" is
|
||||
positioned by CSS inside the video-overlay zone's full-canvas wrapper.
|
||||
|
||||
Recommended storyboard.json card entry (strict v3):
|
||||
{
|
||||
"id": "card-XX",
|
||||
"intent": "cinematic / dramatic moment with glass overlay",
|
||||
"startSec": 8, "endSec": 14,
|
||||
"accentIndex": 0,
|
||||
"zone": "video-overlay",
|
||||
"contentHints": { "kicker": "...", "title": "...", "detail": "..." }
|
||||
}
|
||||
|
||||
GSAP target for #video-wrap (full-bleed — usually unchanged):
|
||||
tl.to('#video-wrap',
|
||||
{ left: 0, top: 0, width: COMPOSITION_W, height: COMPOSITION_H,
|
||||
duration: 0.6, ease: 'power2.inOut' }, START_SEC);
|
||||
// Use defaults: landscape 1920×1080 / portrait 1080×1920 / 4:5 1080×1350
|
||||
|
||||
Recommended card-host inline style (since zone="video-overlay" gives
|
||||
full-canvas bounds, you typically inset the actual card visual via CSS):
|
||||
|
||||
landscape glass card, mid-left:
|
||||
.card[data-card-id="X"] .root {
|
||||
position: absolute; left: 48px; top: 460px;
|
||||
width: 660px; height: 540px;
|
||||
background: rgba(15,16,22,.78);
|
||||
backdrop-filter: blur(22px) saturate(140%);
|
||||
-webkit-backdrop-filter: blur(22px) saturate(140%);
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 30px 80px -20px rgba(0,0,0,.45);
|
||||
}
|
||||
|
||||
portrait glass card, bottom band:
|
||||
.card[data-card-id="X"] .root {
|
||||
position: absolute; left: 24px; top: 1280px;
|
||||
width: 1032px; height: 564px;
|
||||
/* same glass treatment */
|
||||
}
|
||||
|
||||
4:5 glass card (y/h × 0.703):
|
||||
.card[data-card-id="X"] .root {
|
||||
position: absolute; left: 24px; top: 900px;
|
||||
width: 1032px; height: 397px;
|
||||
/* same glass treatment */
|
||||
}
|
||||
|
||||
Legibility gradient (insert as a third absolute layer between video
|
||||
and card-host, in the composition's <div id="stage">):
|
||||
|
||||
<div class="legibility"></div>
|
||||
|
||||
.legibility {
|
||||
position: absolute; inset: 0; pointer-events: none; z-index: 2;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(0,0,0,.55) 0%, transparent 22%,
|
||||
transparent 50%, rgba(0,0,0,.72) 100%);
|
||||
}
|
||||
|
||||
Notes
|
||||
- Card root MUST be transparent or use rgba/glass background — see
|
||||
Pattern A in SKILL.md "Transparent card backgrounds".
|
||||
- Glass without legibility gradient = white-on-white catastrophe over
|
||||
bright video. Always pair them.
|
||||
- Glass on a light video also benefits from a darker base color (use
|
||||
rgba(15,16,22,.78) over rgba(255,255,255,.10) when source has bright
|
||||
daylight / interior shots).
|
||||
-->
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>layout · overlay (video full-bleed, glass card)</title>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #0a0c12;
|
||||
color: #fff;
|
||||
font-family: ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
.stage {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
transform-origin: top left;
|
||||
transform: scale(0.5);
|
||||
background: #0a0c12;
|
||||
overflow: hidden;
|
||||
}
|
||||
.video-region {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
background: #1a1f2e;
|
||||
background-image: repeating-linear-gradient(
|
||||
45deg,
|
||||
transparent 0 12px,
|
||||
rgba(255, 255, 255, 0.05) 12px 13px
|
||||
);
|
||||
}
|
||||
.gradient {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(0, 0, 0, 0.55) 0%, transparent 35%),
|
||||
linear-gradient(180deg, transparent 50%, rgba(0, 0, 0, 0.55) 100%);
|
||||
}
|
||||
.card-region {
|
||||
position: absolute;
|
||||
left: 48px;
|
||||
top: 460px;
|
||||
width: 660px;
|
||||
height: 540px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(18px) saturate(140%);
|
||||
-webkit-backdrop-filter: blur(18px) saturate(140%);
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.45);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font:
|
||||
600 24px/1.3 ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
.label {
|
||||
padding: 12px 18px;
|
||||
border: 1.5px solid rgba(255, 255, 255, 0.7);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.v-label {
|
||||
position: absolute;
|
||||
left: 28px;
|
||||
top: 28px;
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
padding: 8px 14px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 3px;
|
||||
font:
|
||||
600 16px/1 ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.14em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stage">
|
||||
<div class="video-region"><span class="v-label">VIDEO · 1920×1080 (full-bleed)</span></div>
|
||||
<div class="gradient"></div>
|
||||
<div class="card-region"><span class="label">CARD · 660×540 glass</span></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,143 @@
|
||||
<!--
|
||||
Layout: pip — card fills canvas, video rounded PiP in corner
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Implementation: card.zone = "fullscreen" + shrink #video-wrap to a
|
||||
corner pill via GSAP, and add a .pip-pill CSS class for the chrome.
|
||||
|
||||
Recommended storyboard.json card entry (strict v3):
|
||||
{
|
||||
"id": "card-XX",
|
||||
"intent": "content-heavy moment with speaker as small accent",
|
||||
"startSec": 8, "endSec": 14,
|
||||
"accentIndex": 0,
|
||||
"zone": "fullscreen",
|
||||
"contentHints": { "kicker": "...", "title": "...", "detail": "..." }
|
||||
}
|
||||
|
||||
GSAP target for #video-wrap (corner pill — pick one per source aspect):
|
||||
|
||||
landscape (1920×1080), 16:9 source video:
|
||||
tl.set('#video-wrap', { className: 'video-wrapper pip-pill' }, START_SEC);
|
||||
tl.to('#video-wrap',
|
||||
{ left: 1432, top: 28, width: 460, height: 258,
|
||||
duration: 0.6, ease: 'power2.inOut' }, START_SEC);
|
||||
|
||||
landscape, 9:16 source video (vertical phone footage):
|
||||
tl.to('#video-wrap',
|
||||
{ left: 1644, top: 28, width: 248, height: 440, ... }, START_SEC);
|
||||
|
||||
portrait (1080×1920), 16:9 source video:
|
||||
tl.to('#video-wrap',
|
||||
{ left: 690, top: 28, width: 360, height: 203, ... }, START_SEC);
|
||||
|
||||
portrait, 9:16 source video:
|
||||
tl.to('#video-wrap',
|
||||
{ left: 738, top: 28, width: 312, height: 555, ... }, START_SEC);
|
||||
|
||||
4:5 (1080×1350) — y values × 0.703, w/h × 0.703:
|
||||
landscape-source: { left: 690, top: 28, width: 360, height: 203 } → keep, fits
|
||||
portrait-source : { left: 738, top: 28, width: 312, height: 390 }
|
||||
|
||||
Recommended .pip-pill CSS (add to composition <style>):
|
||||
.video-wrapper.pip-pill {
|
||||
border-radius: 14px;
|
||||
box-shadow:
|
||||
0 24px 60px -20px rgba(0,0,0,.45),
|
||||
0 0 0 4px rgba(255,255,255,.7),
|
||||
0 0 0 5px rgba(0,0,0,.18);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
Notes
|
||||
- Card-first composition for content-heavy talks.
|
||||
- Default corner is top-right (above); for bottom-right flip y to
|
||||
canvasH - videoH - 28 (e.g. portrait 16:9 source bottom-right:
|
||||
{ left: 690, top: 1689, width: 360, height: 203 }).
|
||||
- DOM order: card-host appears BEFORE video-wrapper for the pip window
|
||||
so the video pill paints on top of the card. If you keep them in
|
||||
natural DOM order (video first, card second), use z-index on the
|
||||
card-host to push it behind.
|
||||
-->
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>layout · pip (card hero + video pill)</title>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #0a0c12;
|
||||
color: #fff;
|
||||
font-family: ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
.stage {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
transform-origin: top left;
|
||||
transform: scale(0.5);
|
||||
background: #0a0c12;
|
||||
overflow: hidden;
|
||||
}
|
||||
.region {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font:
|
||||
600 24px/1.3 ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
.card-region {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
background: #f1ead8;
|
||||
color: #1a1d2b;
|
||||
}
|
||||
.video-region {
|
||||
left: 1432px;
|
||||
top: 28px;
|
||||
width: 460px;
|
||||
height: 258px;
|
||||
background: #1a1f2e;
|
||||
color: #fff;
|
||||
border-radius: 14px;
|
||||
box-shadow:
|
||||
0 24px 60px -20px rgba(0, 0, 0, 0.45),
|
||||
0 0 0 4px rgba(255, 255, 255, 0.7),
|
||||
0 0 0 5px rgba(0, 0, 0, 0.18);
|
||||
background-image: repeating-linear-gradient(
|
||||
45deg,
|
||||
transparent 0 12px,
|
||||
rgba(255, 255, 255, 0.05) 12px 13px
|
||||
);
|
||||
}
|
||||
.label {
|
||||
padding: 12px 18px;
|
||||
border: 1.5px solid currentColor;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.v-label {
|
||||
font:
|
||||
600 14px/1 ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.14em;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stage">
|
||||
<div class="region card-region"><span class="label">CARD · 1920×1080 (full-bleed)</span></div>
|
||||
<div class="region video-region"><span class="v-label">VIDEO · 460×258 PIP</span></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,121 @@
|
||||
<!--
|
||||
Layout: split — 50/50 side-by-side
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Real schema only has `card.zone` (5 enum values) — there is NO
|
||||
`card.layout` field, and video bounds are composition-level
|
||||
(`videoTrack.bounds`, one-time). The "split look" is implemented by:
|
||||
1. setting card.zone = "side-panel" for each card in this stretch
|
||||
2. tweening #video-wrap to the other half via GSAP between cards
|
||||
|
||||
Recommended storyboard.json card entry (strict v3):
|
||||
{
|
||||
"id": "card-XX",
|
||||
"intent": "speaker + data side-by-side",
|
||||
"startSec": 8, "endSec": 14,
|
||||
"accentIndex": 0,
|
||||
"zone": "side-panel",
|
||||
"contentHints": { "kicker": "...", "title": "...", "detail": "..." }
|
||||
}
|
||||
|
||||
GSAP target for #video-wrap during this card (paste in <script>):
|
||||
landscape (1920×1080):
|
||||
tl.to('#video-wrap',
|
||||
{ left: 960, top: 0, width: 960, height: 1080,
|
||||
duration: 0.6, ease: 'power2.inOut' }, START_SEC);
|
||||
|
||||
portrait (1080×1920) — flips to top/bottom:
|
||||
tl.to('#video-wrap',
|
||||
{ left: 0, top: 960, width: 1080, height: 960,
|
||||
duration: 0.6, ease: 'power2.inOut' }, START_SEC);
|
||||
|
||||
4:5 (1080×1350) — derive by ×0.703 on y/h:
|
||||
tl.to('#video-wrap',
|
||||
{ left: 0, top: 675, width: 1080, height: 675,
|
||||
duration: 0.6, ease: 'power2.inOut' }, START_SEC);
|
||||
|
||||
Notes
|
||||
- Card-host (from card.zone="side-panel") covers half the canvas;
|
||||
opaque card background is fine — it only paints its own half.
|
||||
- Flip card/video sides: swap which side gets the speaker tween.
|
||||
- With 14–18px page-level gap, set composition bg to deep color
|
||||
(e.g. #0a0c12) so the gap reads as a clean separator.
|
||||
-->
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>layout · split (50/50)</title>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #0a0c12;
|
||||
color: #fff;
|
||||
font-family: ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
.stage {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
transform-origin: top left;
|
||||
transform: scale(0.5);
|
||||
background: #0a0c12;
|
||||
overflow: hidden;
|
||||
}
|
||||
.region {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font:
|
||||
600 24px/1.3 ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
.card-region {
|
||||
left: 18px;
|
||||
top: 18px;
|
||||
width: 942px;
|
||||
height: 1044px;
|
||||
background: #f1ead8;
|
||||
color: #1a1d2b;
|
||||
}
|
||||
.video-region {
|
||||
left: 978px;
|
||||
top: 18px;
|
||||
width: 924px;
|
||||
height: 1044px;
|
||||
background: #1a1f2e;
|
||||
background-image: repeating-linear-gradient(
|
||||
45deg,
|
||||
transparent 0 12px,
|
||||
rgba(255, 255, 255, 0.05) 12px 13px
|
||||
);
|
||||
}
|
||||
.label {
|
||||
padding: 12px 18px;
|
||||
border: 1.5px solid currentColor;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.meta {
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
top: -36px;
|
||||
font:
|
||||
12px/1 ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.18em;
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stage">
|
||||
<div class="meta">SPLIT · 1920×1080 · card 960 | video 960</div>
|
||||
<div class="region card-region"><span class="label">CARD · 960×1080</span></div>
|
||||
<div class="region video-region"><span class="label">VIDEO · 960×1080</span></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,109 @@
|
||||
<!--
|
||||
Layout: stack — video on top, card below
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Implementation: card.zone = "lower-third" + tween #video-wrap to top band.
|
||||
|
||||
Recommended storyboard.json card entry (strict v3):
|
||||
{
|
||||
"id": "card-XX",
|
||||
"intent": "talking-head + caption-style summary below",
|
||||
"startSec": 8, "endSec": 14,
|
||||
"accentIndex": 0,
|
||||
"zone": "lower-third",
|
||||
"contentHints": { "kicker": "...", "title": "...", "detail": "..." }
|
||||
}
|
||||
|
||||
GSAP target for #video-wrap (top band):
|
||||
landscape (1920×1080) — video top 52%:
|
||||
tl.to('#video-wrap',
|
||||
{ left: 14, top: 14, width: 1892, height: 548,
|
||||
duration: 0.6, ease: 'power2.inOut' }, START_SEC);
|
||||
|
||||
portrait (1080×1920) — video top 44%:
|
||||
tl.to('#video-wrap',
|
||||
{ left: 0, top: 0, width: 1080, height: 844,
|
||||
duration: 0.6, ease: 'power2.inOut' }, START_SEC);
|
||||
|
||||
4:5 (1080×1350) — y/h × 0.703:
|
||||
tl.to('#video-wrap',
|
||||
{ left: 0, top: 0, width: 1080, height: 593,
|
||||
duration: 0.6, ease: 'power2.inOut' }, START_SEC);
|
||||
|
||||
Notes
|
||||
- Sleek vertical: gives the speaker a wider stage on top.
|
||||
- Card below is a full-width statement — great for one big sentence
|
||||
or one big number.
|
||||
- The `lower-third` zone resolves to bottom 30% by default
|
||||
(`resolveZoneBounds`); for a 48% card adjust the GSAP tween to also
|
||||
move card-host height, or use `zone="whiteboard-area"` + custom CSS.
|
||||
- 14px gap between video and card looks clean — set composition bg to
|
||||
a deep color (#0a0c12) so the gap reads as a separator.
|
||||
-->
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>layout · stack (video top, card bottom)</title>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #0a0c12;
|
||||
color: #fff;
|
||||
font-family: ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
.stage {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
transform-origin: top left;
|
||||
transform: scale(0.5);
|
||||
background: #0a0c12;
|
||||
overflow: hidden;
|
||||
}
|
||||
.region {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font:
|
||||
600 24px/1.3 ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
.video-region {
|
||||
left: 14px;
|
||||
top: 14px;
|
||||
width: 1892px;
|
||||
height: 548px;
|
||||
background: #1a1f2e;
|
||||
background-image: repeating-linear-gradient(
|
||||
45deg,
|
||||
transparent 0 12px,
|
||||
rgba(255, 255, 255, 0.05) 12px 13px
|
||||
);
|
||||
}
|
||||
.card-region {
|
||||
left: 14px;
|
||||
top: 576px;
|
||||
width: 1892px;
|
||||
height: 504px;
|
||||
background: #f1ead8;
|
||||
color: #1a1d2b;
|
||||
}
|
||||
.label {
|
||||
padding: 12px 18px;
|
||||
border: 1.5px solid currentColor;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="stage">
|
||||
<div class="region video-region"><span class="label">VIDEO · 1920×562 (top 52%)</span></div>
|
||||
<div class="region card-region"><span class="label">CARD · 1920×518 (bottom 48%)</span></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user