Example: Bonus Cashback, no value¶
Manifest row 06 · built today as betta-bonus-cashback-duo
The simplest member of the family: Bonus in blue on a yellow panel tipped 5°, Cashback on a
wider yellow panel below it, both shadowed, then two lines of white small print. No amount row at
all. The partner logos beside it in the source are scene-level layers, not part of this lockup.
Panels wipe on from the left four frames apart and breathe together; the small print slides down and
fades in.
flowchart TB
subgraph scene["scene-cashback (one motion graph per ratio)"]
ROOT["duo-root<br/>flowBox · column · absolute (120,120)"]
PANELS["duo-panels<br/>flowBox · column · flow · pulse"]
FOOT["duo-footnotes<br/>flowBox · column · flow"]
BONUS["bonus · text on yellow pill · flow · wipe"]
CASH["cashback · text on yellow pill · flow · wipe"]
FN["footnote · text · flow · slideFade"]
TERMS["terms · text · flow · slideFade"]
PANELS -- flowIn --> ROOT
FOOT -- flowIn --> ROOT
BONUS -- flowIn --> PANELS
CASH -- flowIn --> PANELS
FN -- flowIn --> FOOT
TERMS -- flowIn --> FOOT
end
The document¶
{
"id": "scene-cashback",
"durationInFrames": 75,
"layers": [
{
"id": "duo-root",
"type": "flowBox",
"zIndex": 0,
"layout": {
"mode": "absolute",
"16:9": { "x": 120, "y": 120, "w": "content", "h": "content", "anchor": "top-left" },
"9:16": { /* own position */ },
"1:1": { /* own position */ }
},
"props": { "direction": "column", "alignAcross": "centre", "gap": 20 }
},
// ── The two panels; the pulse lives here and both members inherit it.
{
"id": "duo-panels",
"type": "flowBox",
"zIndex": 0,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "duo-root", "w": "content", "h": "content" },
"9:16": { "flowIn": "duo-root", "w": "content", "h": "content" },
"1:1": { "flowIn": "duo-root", "w": "content", "h": "content" }
},
"props": { "direction": "column", "alignAcross": "centre", "gap": 40 },
"animations": [
{ "animation": "pulse", "params": { "scale": 1.05, "periodInFrames": 40, "delay": 30 } }
]
},
{
"id": "bonus",
"type": "text",
"zIndex": 2,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "duo-panels", "w": "content", "h": "content", "rotation": 5 },
"9:16": { "flowIn": "duo-panels", "w": "content", "h": "content", "rotation": 5 },
"1:1": { "flowIn": "duo-panels", "w": "content", "h": "content", "rotation": 5 }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 183, "color": "#054f8e", "horizontalAlign": "center" }
},
"props": {
"content": [ { "value": "Bonus" } ],
"background": {
"fill": "#ffd100", "radius": 4,
"padding": { "top": 29, "right": 44, "bottom": 32, "left": 38 }
}
},
"effects": [ { "type": "dropShadow", "color": "#000000", "opacity": 0.26, "blurPx": 4, "offsetX": 5, "offsetY": 6 } ],
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 0 } }
]
},
{
"id": "cashback",
"type": "text",
"zIndex": 1,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "duo-panels", "w": "content", "h": "content" },
"9:16": { "flowIn": "duo-panels", "w": "content", "h": "content" },
"1:1": { "flowIn": "duo-panels", "w": "content", "h": "content" }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 179, "color": "#054f8e" }
},
"props": {
"content": [ { "value": "Cashback" } ],
"background": {
"fill": "#ffd100", "radius": 5,
"padding": { "top": 30, "right": 14, "bottom": 31, "left": 14 }
}
},
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 4 } }
]
},
// ── Small print, its own column so it sits outside the pulse.
{
"id": "duo-footnotes",
"type": "flowBox",
"zIndex": 0,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "duo-root", "w": "content", "h": "content" },
"9:16": { "flowIn": "duo-root", "w": "content", "h": "content" },
"1:1": { "flowIn": "duo-root", "w": "content", "h": "content" }
},
"props": { "direction": "column", "alignAcross": "centre", "gap": 3 }
},
{
"id": "footnote",
"type": "text",
"zIndex": 3,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "duo-footnotes", "w": "content", "h": "content" },
"9:16": { "flowIn": "duo-footnotes", "w": "content", "h": "content" },
"1:1": { "flowIn": "duo-footnotes", "w": "content", "h": "content" }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 400, "size": 71, "color": "#ffffff", "tracking": -0.7 }
},
"props": {
"content": [ { "value": "with selected products*" } ],
"patterns": [ { "expression": "\\*$", "typography": { "size": { "ofRoot": 0.58 }, "baseline": 0.45 } } ]
},
"animations": [
{ "animation": "slideFade", "params": { "from": "top", "distance": 28, "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 12 } }
]
},
{
"id": "terms",
"type": "text",
"zIndex": 3,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "duo-footnotes", "w": "content", "h": "content" },
"9:16": { "flowIn": "duo-footnotes", "w": "content", "h": "content" },
"1:1": { "flowIn": "duo-footnotes", "w": "content", "h": "content" }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 400, "size": 30, "color": "#ffffff", "tracking": -0.3 }
},
"props": { "content": [ { "value": "*Via Digital Visa Gift Card. Via redemption. T&Cs apply." } ] },
"animations": [
{ "animation": "slideFade", "params": { "from": "top", "distance": 12, "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 14 } }
]
}
]
}
| Note | Binding target | Control |
|---|---|---|
| Editable text | bonus.props.content[0].value, cashback.props.content[0].value, footnote…, terms… |
text |
| Change colours | *.props.background.fill, *.typography[ratio].color |
colour |
| Pulse toggle per panel | no numeric leaf to bind — see stress points | — |
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. Two { ofRoot } values and four at references resolve; pulse, wipe, and
slideFade expand into tracks.
Solve. Four texts measure content-sized; duo-panels stacks the two pills centred with a 40px
gap, duo-footnotes the two lines with 3px, duo-root the two groups with 20px and lands at
(120, 120). The 5° tilt on bonus is never part of packing.
Animate. The pulse on duo-panels reaches both pills through flow membership; each composes it
with its own tilt about its own content centre after the group's scale about the group centre. The
footnotes don't move after their slide-fade lands.
Place. Seven positioned elements. Two pills, four runs of text, nothing else.
What this shows¶
- The minimum lockup is seven layers, three of them non-visual containers whose only job is to say what pulses and what doesn't.
- No
derivedlayer needed when every panel wraps a single text — the paint-only pill ontextdoes the whole job, tilt included.
Stress points¶
Nothing new beyond the family-wide points recorded on the full stack:
the wipe-versus-transform-only rule, the single gap (this one has 40 / 20 / 3, hence three
columns for four leaves), the unbindable per-panel pulse toggle, and background.shadow. The
tilted-panel and last-baseline points don't arise here because there is no multi-text panel.