Example: Red Hot Summer Sale¶
Manifest row 03 · built today as betta-red-hot-summer-sale
A five-panel column: RED and HOT on two red panels tilted 4° apart, SUMMER in red on a white
panel, a huge SALE on a red panel, and a two-line blue footer SAVE BIG across / a range of
products!* with SAVE BIG in yellow and the asterisk raised. Every panel carries a soft drop
shadow, wipes on from the left in a 3-frame stagger, and all five breathe on a shared beat.
flowchart TB
subgraph scene["scene-red-hot"]
ROOT["rh-lockup<br/>flowBox column · absolute (120,120)"]
TITLE["rh-title<br/>flowBox row · flow"]
RED["rh-red<br/>text · flow · rot −4 · pulse"]
HOT["rh-hot<br/>text · flow · rot 4 · pulse"]
SUMMER["rh-summer<br/>text · flow · rot 2 · pulse"]
SALE["rh-sale<br/>text · flow · pulse"]
SAVE["rh-save-big<br/>text · flow · rot −2.1 · pulse"]
RED -- flowIn --> TITLE
HOT -- flowIn --> TITLE
TITLE -- flowIn --> ROOT
SUMMER -- flowIn --> ROOT
SALE -- flowIn --> ROOT
SAVE -- flowIn --> ROOT
end
The document¶
{
"id": "scene-red-hot",
"durationInFrames": 75,
"layers": [
{
"id": "rh-lockup",
"type": "flowBox",
"zIndex": 0,
"layout": {
"mode": "absolute",
"16:9": { "x": 120, "y": 120, "w": "content", "h": "content", "anchor": "top-left" },
"9:16": { /* own x/y */ }, "1:1": { /* own x/y */ }
},
// Source gaps: 21 / 9 / 31 between the four rows. One gap here — see Stress points.
"props": { "direction": "column", "alignAcross": "centre", "gap": 20 }
},
{
"id": "rh-title",
"type": "flowBox",
"zIndex": 1,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "rh-lockup", "w": "content", "h": "content" },
"9:16": { /* … */ }, "1:1": { /* … */ }
},
"props": { "direction": "row", "alignAcross": "top", "gap": 43 }
},
{
"id": "rh-red",
"type": "text",
"zIndex": 2,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "rh-title", "w": "content", "h": "content", "rotation": -4 },
"9:16": { /* … */ }, "1:1": { /* … */ }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 151, "color": "#ffffff",
"case": "uppercase", "horizontalAlign": "center" }
},
"props": {
"content": [ { "value": "Red" } ],
"background": { "fill": "#fe2121", "radius": 5,
"padding": { "top": 24, "right": 37, "bottom": 22, "left": 35 } }
},
"effects": [ { "type": "dropShadow", "color": "#000000", "opacity": 0.31, "blurPx": 8, "offsetX": 3.5, "offsetY": 4.3 } ],
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 0 } },
{ "animation": "pulse", "params": { "scale": 1.05, "periodInFrames": 40, "delay": 30 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 0 } }
]
},
{
"id": "rh-hot",
"type": "text",
"zIndex": 2,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "rh-title", "w": "content", "h": "content", "rotation": 4 },
"9:16": { /* … */ }, "1:1": { /* … */ }
},
"typography": { "16:9": { /* as rh-red */ } },
"props": {
"content": [ { "value": "Hot" } ],
"background": { "fill": "#fe2121", "radius": 5,
"padding": { "top": 20, "right": 24, "bottom": 22, "left": 22 } }
},
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 3 } },
{ "animation": "pulse", "params": { "scale": 1.05, "periodInFrames": 40, "delay": 30 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 0 } }
]
},
{
"id": "rh-summer",
"type": "text",
"zIndex": 1,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "rh-lockup", "w": "content", "h": "content", "rotation": 2 },
"9:16": { /* … */ }, "1:1": { /* … */ }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 170, "color": "#fe2121",
"case": "uppercase", "horizontalAlign": "center" }
},
"props": {
"content": [ { "value": "Summer" } ],
"background": { "fill": "#ffffff", "radius": 5,
"padding": { "top": 23, "right": 61, "bottom": 24, "left": 56 } }
},
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 6 } },
{ "animation": "pulse", "params": { "scale": 1.05, "periodInFrames": 40, "delay": 30 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 0 } }
]
},
{
"id": "rh-sale",
"type": "text",
"zIndex": 1,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "rh-lockup", "w": "content", "h": "content" },
"9:16": { /* … */ }, "1:1": { /* … */ }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 290, "color": "#ffffff",
"case": "uppercase", "horizontalAlign": "center" }
},
"props": {
"content": [ { "value": "Sale" } ],
"background": { "fill": "#fe2121", "radius": 5,
"padding": { "top": 47, "right": 52, "bottom": 48, "left": 46 } }
},
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 9 } },
{ "animation": "pulse", "params": { "scale": 1.05, "periodInFrames": 40, "delay": 30 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 0 } }
]
},
// ── Footer: two lines, mixed case, with "SAVE BIG" in yellow as its own run.
{
"id": "rh-save-big",
"type": "text",
"zIndex": 1,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "rh-lockup", "w": "content", "h": "content", "rotation": -2.1 },
"9:16": { /* … */ }, "1:1": { /* … */ }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 58, "color": "#ffffff",
"lineHeight": 0.84, "multiline": true, "horizontalAlign": "center" }
},
"props": {
"content": [
{ "value": "SAVE BIG", "typography": { "color": "#ffd007" } },
{ "value": " across\na range of products!*" }
],
"patterns": [
{ "expression": "\\*$", "typography": { "size": { "ofRoot": 0.58 }, "baseline": 0.5 } }
],
"background": { "fill": "#054f8e", "radius": 2,
"padding": { "top": 12, "right": 58, "bottom": 12, "left": 57 } }
},
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 12 } },
{ "animation": "pulse", "params": { "scale": 1.05, "periodInFrames": 40, "delay": 30 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 0 } }
]
}
]
}
| Note | Field path | Control |
|---|---|---|
| Editable text | rh-*.props.content[*].value |
text |
| Change colours | rh-*.props.background.fill, rh-*.typography[ratio].color, rh-save-big.props.content[0].typography.color |
colour |
| Pulse toggle (headline / Save Big) | rh-*.animations[1] on/off |
no bindable leaf — see Stress points |
| Tilt | rh-*.layout[ratio].rotation |
degrees |
Panel shadows are layer effects
Each panel above carries a drop shadow in the source artwork. A shadow is a per-layer
effect, applied to the whole layer (glyphs and pill together), not a field on
background — see Coordinate System & Sizing.
Where text and its panel need different shadows, they become two layers: a text layer
and a background layer spanning it, each with its own
effects.
What the engine does with it¶
Resolve. Wipes at 0, 3, 6, 9, 12; five continuous scale tracks from pulse; the footer's
asterisk resolves to 58 × 0.58.
Solve. Five texts measure unconstrained — the footer wraps at its authored \n since it is
content-width — then rh-title packs RED and HOT with a 43px gap, then rh-lockup stacks four rows
and centres them. Shadows are paint-only extents contributors; they never enter the packing.
Animate. Each panel pulses about its own content centre; the title row's two members pulse independently. The built component pulses all five about the lockup's centre.
Place. Seven elements, five of them rotated text pills with a drop-shadow filter.
What this shows¶
- The simplest of the seasonal banners in structure — five text layers, one nested row, no
spanning background — and the one that leans hardest on typography: mixed runs, a pattern, a
tight
lineHeight, uppercase viacase. - Runs beat patterns for fixed styling.
SAVE BIGis a run with its own colour; the pattern is reserved for the trailing asterisk, whose position depends on the copy.
Stress points¶
background.shadowdoesn't exist.backgroundSchemahasfill,opacity,radius,paddingonly; every panel here carries a Photoshop drop shadow. The brief already counts "shadow spread" as anextentscontributor (Coordinate System → Bounds) so the field is implied but never declared. Encoded asbackground.shadow: { color, opacity, blurPx, offsetX, offsetY }here.- Uneven column gaps (21 / 9 / 31) with one
gap. Same as 01 and 02. - Pulse pivot and pulse toggle binding. Same as 01.
- Wipe is a clip animation. Same as 01.
rotationon a flow member assumed. Same as 01.- Pattern vs. run precedence.
rh-save-bighas both a run-level colour and a pattern that changes size/baseline on the asterisk. Text Foundation → Typography resolver orders base → run → part/role; wherepatternssit in that chain (they exist in the shipped schema and are used everywhere here) isn't stated.