@koda-sl/baker-cli 0.74.0 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,136 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=1080, height=1920" />
6
+ <script src="./gsap.min.js"></script>
7
+ <style>
8
+ /* The "talking head on a video call" pattern — see the creative-canvas-ads
9
+ skill's references/hyperframes/talking-head-and-overlays.md. Presenter
10
+ (the `background` video) starts full-bleed, then shrinks to a corner PIP
11
+ pill while #content takes the stage. Replace #content with a real
12
+ screenshot <img> you drop in this dir, or nest a catalog block. Drop
13
+ brand-bold.otf / brand-regular.otf for on-brand type. */
14
+ @font-face {
15
+ font-family: 'BrandFont';
16
+ src: url('./brand-bold.otf') format('opentype'), url('./brand-bold.ttf') format('truetype');
17
+ font-weight: 700 900;
18
+ font-display: swap;
19
+ }
20
+ @font-face {
21
+ font-family: 'BrandFont';
22
+ src: url('./brand-regular.otf') format('opentype'), url('./brand-regular.ttf') format('truetype');
23
+ font-weight: 100 600;
24
+ font-display: swap;
25
+ }
26
+ * { margin: 0; padding: 0; box-sizing: border-box; }
27
+ html, body { width: 1080px; height: 1920px; overflow: hidden; background: #000; }
28
+ #root { position: absolute; inset: 0; font-family: 'BrandFont', 'Helvetica Neue', Arial, sans-serif; }
29
+
30
+ /* Content stage — sits BEHIND the presenter (DOM order: #content first, then
31
+ #video-wrap → the pill paints on top). Swap this panel for a screenshot. */
32
+ #content {
33
+ position: absolute; inset: 0; background: {{bg_color}}; color: {{text_color}};
34
+ display: flex; flex-direction: column; justify-content: center;
35
+ padding: 160px 96px; opacity: 0;
36
+ }
37
+ #content .kicker { width: 120px; height: 8px; background: {{accent_color}}; border-radius: 4px; transform: scaleX(0); transform-origin: left center; margin-bottom: 40px; }
38
+ #content .headline { font-size: 104px; font-weight: 900; line-height: 1.08; letter-spacing: -1px; text-wrap: balance; }
39
+
40
+ /* Presenter video — full-bleed at first, then TRANSFORM-scaled into a corner
41
+ pill. Transforms only: never animate left/top/width/height — they trigger
42
+ layout, and the renderer's parallel per-frame seeks can desync layout-driven
43
+ geometry (see references/hyperframes/composition-engine.md). The pill chrome
44
+ (radius/ring) is applied at PIP time and pre-multiplied for the scale. */
45
+ #video-wrap { position: absolute; top: 0; left: 0; width: 1080px; height: 1920px; overflow: hidden; transform-origin: 0 0; }
46
+ #bg { width: 100%; height: 100%; object-fit: cover; }
47
+
48
+ /* Floating glass claim card. */
49
+ #claim {
50
+ position: absolute; left: 64px; bottom: 360px; max-width: 720px;
51
+ padding: 36px 44px; border-radius: 24px;
52
+ background: rgba(255,255,255,0.10); backdrop-filter: blur(18px) saturate(140%);
53
+ -webkit-backdrop-filter: blur(18px) saturate(140%);
54
+ border: 1px solid rgba(255,255,255,0.22);
55
+ color: {{text_color}}; font-size: 46px; font-weight: 700; line-height: 1.2;
56
+ opacity: 0; transform: translateY(24px);
57
+ }
58
+
59
+ /* Caption band. */
60
+ #caption {
61
+ position: absolute; left: 50%; bottom: 150px; transform: translateX(-50%);
62
+ width: 88%; text-align: center; color: {{text_color}};
63
+ font-size: 56px; font-weight: 800; line-height: 1.15;
64
+ text-shadow: 0 2px 8px rgba(0,0,0,0.6), 0 0 2px rgba(0,0,0,0.9);
65
+ opacity: 0;
66
+ }
67
+ #caption .u { display: inline-block; height: 6px; width: 120px; background: {{accent_color}}; border-radius: 3px; vertical-align: middle; margin-left: 16px; transform: scaleX(0); transform-origin: left center; }
68
+ </style>
69
+ </head>
70
+ <body>
71
+ <div id="root" data-composition-id="video-call" data-start="0" data-duration="{{duration}}" data-width="1080" data-height="1920">
72
+ <div id="content">
73
+ <div class="kicker" id="kicker"></div>
74
+ <div class="headline" id="headline">{{headline}}</div>
75
+ </div>
76
+ <div id="video-wrap">
77
+ <video id="bg" src="background.mp4" muted></video>
78
+ </div>
79
+ <div id="claim">{{claim}}</div>
80
+ <div id="caption"><span id="caption-text">{{caption}}</span><span class="u" id="caption-u"></span></div>
81
+ </div>
82
+
83
+ <script>
84
+ (() => {
85
+ var DURATION = parseFloat('{{duration}}') || 8;
86
+ var PIP_AT = parseFloat('{{pip_at_s}}'); if (!(PIP_AT >= 0)) PIP_AT = 2;
87
+ var hasHeadline = ((document.getElementById('headline').textContent) || '').trim().length > 0;
88
+ var hasClaim = ((document.getElementById('claim').textContent) || '').trim().length > 0;
89
+ var hasCaption = ((document.getElementById('caption-text').textContent) || '').trim().length > 0;
90
+ if (!hasClaim) document.getElementById('claim').style.display = 'none';
91
+ if (!hasCaption) document.getElementById('caption').style.display = 'none';
92
+ // Kicker sits at scaleX(0) but still holds its layout box + 40px bottom margin,
93
+ // so hide it outright when there's no headline (the default) — no dead space.
94
+ if (!hasHeadline) document.getElementById('kicker').style.display = 'none';
95
+
96
+ // Top-right PIP pill, 9:16 to MATCH the full frame so a single UNIFORM scale
97
+ // shrinks the presenter without distorting the video (non-uniform scaleX/scaleY
98
+ // would squish it). Edit x/y for another corner. Transforms only.
99
+ var PILL = { x: 672, y: 56, w: 360, h: 640 };
100
+ var s = PILL.w / 1080; // === PILL.h / 1920 (uniform)
101
+ var k = 1 / s; // pre-multiplier so the chrome lands crisp at the target size after scaling
102
+
103
+ var tl = gsap.timeline({ paused: true });
104
+
105
+ // Presenter shrinks into the pill; content stage fades up underneath. The pill
106
+ // chrome (radius + white ring) is set at PIP time and pre-multiplied by k so,
107
+ // once the element is scaled by s, it reads as ~28px radius + a crisp ring.
108
+ tl.set('#video-wrap', {
109
+ borderRadius: 28 * k,
110
+ boxShadow: '0 ' + 24 * k + 'px ' + 60 * k + 'px ' + (-20 * k) + 'px rgba(0,0,0,0.45), 0 0 0 ' + 6 * k + 'px rgba(255,255,255,0.7), 0 0 0 ' + 8 * k + 'px rgba(11,16,32,0.18)',
111
+ }, PIP_AT);
112
+ tl.fromTo('#video-wrap',
113
+ { x: 0, y: 0, scale: 1 },
114
+ { x: PILL.x, y: PILL.y, scale: s, duration: 0.6, ease: 'power2.inOut' },
115
+ PIP_AT);
116
+ tl.fromTo('#content', { opacity: 0 }, { opacity: 1, duration: 0.4, ease: 'power2.out' }, PIP_AT + 0.1);
117
+ if (hasHeadline) tl.fromTo('#kicker', { scaleX: 0 }, { scaleX: 1, duration: 0.4, ease: 'power3.out' }, PIP_AT + 0.25);
118
+
119
+ // Glass claim card rises in.
120
+ if (hasClaim) tl.fromTo('#claim', { opacity: 0, y: 24 }, { opacity: 1, y: 0, duration: 0.45, ease: 'power2.out' }, PIP_AT + 0.45);
121
+
122
+ // Caption fades in with an accent underline wipe.
123
+ if (hasCaption) {
124
+ tl.fromTo('#caption', { opacity: 0 }, { opacity: 1, duration: 0.35, ease: 'power1.out' }, PIP_AT + 0.6);
125
+ tl.fromTo('#caption-u', { scaleX: 0 }, { scaleX: 1, duration: 0.4, ease: 'power3.out' }, PIP_AT + 0.7);
126
+ }
127
+
128
+ // Hold to the full duration.
129
+ tl.to({}, { duration: 0.01 }, Math.max(0.02, DURATION - 0.01));
130
+
131
+ window.__timelines = window.__timelines || {};
132
+ window.__timelines["video-call"] = tl;
133
+ })();
134
+ </script>
135
+ </body>
136
+ </html>
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "video-call",
3
+ "title": "Talking head on a video call — presenter shrinks to a PIP pill over content",
4
+ "description": "The 'AI person showing you something on a call' pattern. The presenter video starts full-bleed, then at pip_at_s shrinks into a rounded corner PIP pill while a content card (a claim, or your screen-share/app-UI image) takes the stage; a glass claim card and a caption band animate in. The presenter clip is the `background` input. Replace the #content panel with a real screenshot <img> you drop in this dir, or nest a catalog block (npx hyperframes add …) — see the creative-canvas-ads skill's references/hyperframes/talking-head-and-overlays.md. Drop brand-bold.otf / brand-regular.otf for on-brand type. Fixed 1080x1920; copy + edit width/height for other ratios.",
5
+ "width": 1080,
6
+ "height": 1920,
7
+ "fps": 30,
8
+ "default_duration": 8,
9
+ "inputs": {
10
+ "background": {
11
+ "kind": "video",
12
+ "required": true,
13
+ "staged_as": "background.mp4",
14
+ "description": "The presenter / talking-head clip (e.g. a Seedance native-voiced scene)."
15
+ }
16
+ },
17
+ "params": {
18
+ "headline": { "kind": "string", "default": "", "description": "Big line on the content stage (what the presenter is showing)." },
19
+ "claim": { "kind": "string", "default": "", "description": "Short proof/claim on the floating glass card (optional)." },
20
+ "caption": { "kind": "string", "default": "", "description": "A caption line in the lower band (optional)." },
21
+ "pip_at_s": { "kind": "number", "default": 2, "min": 0, "max": 30, "description": "When the presenter shrinks to the corner pill." },
22
+ "bg_color": { "kind": "color", "default": "#0b1020", "description": "Content-stage background (behind the presenter)." },
23
+ "text_color": { "kind": "color", "default": "#ffffff" },
24
+ "accent_color": { "kind": "color", "default": "#5b8cff", "description": "Headline accent + caption underline + pill ring tint." }
25
+ }
26
+ }
@@ -8,17 +8,33 @@
8
8
  /* ═══════════════════════════════════════════════════════════════════════
9
9
  OVERLAY LAYER — PAINT THIS YOURSELF.
10
10
 
11
+ This is a REAL Hyperframes composition (hyperframe_render runs the genuine
12
+ `npx hyperframes` renderer), so it can do FAR more than the seeded text.
13
+
11
14
  The scaffold seeds #overlay-root (below) with the reference ad's overlays
12
15
  as plain HTML elements — real text, a position class, and data-start/
13
16
  data-dur timing. This file is YOURS: restyle every rule here, add classes,
14
17
  build a lower-third bar or a scrolling ticker, drop a logo image into this
15
- dir and reference it with <img>. The only contract is:
18
+ dir and reference it with <img>. The simple contract for a seeded element:
16
19
 
17
20
  • keep each overlay element inside #overlay-root
18
21
  • keep its data-start / data-dur (seconds) — the runtime shows/hides by them
19
22
  • (optional) data-anim="fade|slide_up|slide_down|pop" for a canned entrance
20
23
 
21
- The runtime makes NO styling decisions. How it looks is 100% your CSS/markup.
24
+ …and the richer capabilities (see the two commented slots in #overlay-root,
25
+ and the full docs under the creative-canvas-ads skill's references/hyperframes/):
26
+
27
+ • PULL A READY-MADE BLOCK — `npx hyperframes add <id>` (run in THIS dir;
28
+ lands in compositions/) then nest it with a <div data-composition-src>
29
+ clip. ~97 blocks: lower-thirds, social-proof cards, stat counters, charts,
30
+ code, logo stings. `npx hyperframes catalog --type block` lists them.
31
+ • CAPTIONS — drive a karaoke/themed/kinetic caption track off the
32
+ transcript (sound-off feed). `npx hyperframes add caption-highlight`.
33
+ • MOTION — animate with GSAP using the named motion-rule vocabulary, not
34
+ just the four canned entrances.
35
+
36
+ The seeded runtime decides only WHEN a plain element shows; everything
37
+ else — look, motion, nested blocks — is your CSS/markup/GSAP.
22
38
  For on-brand type, drop brand-bold.otf / brand-regular.otf into this dir.
23
39
  ═══════════════════════════════════════════════════════════════════════ */
24
40
  @font-face {
@@ -68,6 +84,27 @@
68
84
  <video id="bg" src="background.mp4" muted></video>
69
85
  <div id="overlay-root">
70
86
  <!--OVERLAYS-->
87
+
88
+ <!-- ── NESTED BLOCK SLOT (optional) ───────────────────────────────────
89
+ For an ANIMATED graphic (lower-third, social-proof/review card, stat
90
+ counter, chart, logo sting), pull a ready-made block instead of a
91
+ static <img>. From this dir:
92
+ npx hyperframes catalog --type block # find one by tag/name
93
+ npx hyperframes add yt-lower-third # writes compositions/yt-lower-third.html
94
+ then uncomment + retime the nested clip (add data-start/data-track-index;
95
+ data-composition-id is optional but if set must match the block's id):
96
+ <div data-composition-src="compositions/yt-lower-third.html"
97
+ data-start="3" data-duration="4.5" data-track-index="2"
98
+ data-width="1920" data-height="1080"></div>
99
+ ──────────────────────────────────────────────────────────────────── -->
100
+
101
+ <!-- ── CAPTION TRACK SLOT (optional, recommended for sound-off feeds) ──
102
+ The feed plays muted — burn in captions from the word-level transcript
103
+ the deconstruct produced. Floor: `npx hyperframes add caption-highlight`
104
+ (TikTok karaoke); escalate by register (caption-kinetic-slam, etc.).
105
+ Wiring + the {id,text,start,end} sync contract:
106
+ references/hyperframes/captions-and-audio.md.
107
+ ──────────────────────────────────────────────────────────────────── -->
71
108
  </div>
72
109
  </div>
73
110