Example: Bonus Cashback, three tier¶
Manifest row 08 · built today as betta-bonus-cashback-tiers
Yellow, red, yellow: Bonus in blue on a yellow panel tipped 5°, a red panel tipped the other way
with a white UP TO stack beside a white $400, then Cashback* in blue on a wide yellow panel
with a small raised asterisk, then a single line of tiny uppercase small print. No shadows. Panels
wipe on from the left four frames apart and breathe together; the footnote slides down and fades in.
flowchart TB
subgraph scene["scene-cashback (one motion graph per ratio)"]
ROOT["tiers-root<br/>flowBox · column · absolute (120,120)"]
PANELS["tiers-panels<br/>flowBox · column · flow · pulse"]
BONUS["bonus · text on yellow pill · flow · wipe"]
AMT["amount-row<br/>flowBox · row · flow · wipe"]
PRE["amount-prefix · text 'UP TO' · flow"]
HERO["amount-hero · text price run · flow"]
AMTBG["amount-bg · background · derived"]
CASH["cashback · text 'Cashback*' on yellow pill · flow · wipe"]
FN["footnote · text · flow · slideFade"]
PANELS -- flowIn --> ROOT
FN -- flowIn --> ROOT
BONUS -- flowIn --> PANELS
AMT -- flowIn --> PANELS
CASH -- flowIn --> PANELS
PRE -- flowIn --> AMT
HERO -- flowIn --> AMT
AMTBG -- of --> AMT
end
The document¶
{
"id": "scene-cashback",
"durationInFrames": 75,
"layers": [
{
"id": "tiers-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": 40 }
},
{
"id": "tiers-panels",
"type": "flowBox",
"zIndex": 0,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "tiers-root", "w": "content", "h": "content" },
"9:16": { "flowIn": "tiers-root", "w": "content", "h": "content" },
"1:1": { "flowIn": "tiers-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": 3,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "tiers-panels", "w": "content", "h": "content", "rotation": 5 },
"9:16": { "flowIn": "tiers-panels", "w": "content", "h": "content", "rotation": 5 },
"1:1": { "flowIn": "tiers-panels", "w": "content", "h": "content", "rotation": 5 }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 181, "color": "#054f8e", "horizontalAlign": "center" }
},
"props": {
"content": [ { "value": "Bonus" } ],
"background": { "fill": "#ffd100", "radius": 4, "padding": { "top": 29, "right": 43, "bottom": 32, "left": 39 } }
},
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 0 } }
]
},
{
"id": "amount-row",
"type": "flowBox",
"zIndex": 2,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "tiers-panels", "w": "content", "h": "content", "rotation": -5 },
"9:16": { "flowIn": "tiers-panels", "w": "content", "h": "content", "rotation": -5 },
"1:1": { "flowIn": "tiers-panels", "w": "content", "h": "content", "rotation": -5 }
},
"props": { "direction": "row", "alignAcross": "bottom", "gap": 2 },
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 4 } }
]
},
{
"id": "amount-prefix",
"type": "text",
"zIndex": 2,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "amount-row", "w": "content", "h": "content" },
"9:16": { "flowIn": "amount-row", "w": "content", "h": "content" },
"1:1": { "flowIn": "amount-row", "w": "content", "h": "content" }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 61, "color": "#ffffff",
"case": "uppercase", "lineHeight": 1.2, "multiline": true, "horizontalAlign": "center" }
},
"props": { "content": [ { "value": "up\nto" } ] }
},
{
"id": "amount-hero",
"type": "text",
"zIndex": 2,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "amount-row", "w": "content", "h": "content" },
"9:16": { "flowIn": "amount-row", "w": "content", "h": "content" },
"1:1": { "flowIn": "amount-row", "w": "content", "h": "content" }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 191, "color": "#ffffff" }
},
"props": {
"content": [
{ "price": { "amount": 400, "currency": "AUD", "locale": "en-AU" },
"typography": { "currencySymbol": { "size": { "ofRoot": 0.72 }, "baseline": 0.12 } } }
]
}
},
{
"id": "amount-bg",
"type": "background",
"zIndex": 1,
"layout": {
"mode": "derived",
"16:9": { "of": ["amount-row"], "ofBounds": "extents" },
"9:16": { "of": ["amount-row"], "ofBounds": "extents" },
"1:1": { "of": ["amount-row"], "ofBounds": "extents" }
},
"props": { "fill": "#ff0000", "radius": 4, "padding": { "top": 16, "right": 11, "bottom": 9, "left": 29 } },
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 4 } }
]
},
{
"id": "cashback",
"type": "text",
"zIndex": 3,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "tiers-panels", "w": "content", "h": "content" },
"9:16": { "flowIn": "tiers-panels", "w": "content", "h": "content" },
"1:1": { "flowIn": "tiers-panels", "w": "content", "h": "content" }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 700, "size": 177, "color": "#054f8e" }
},
"props": {
"content": [ { "value": "Cashback*" } ],
// The asterisk is a quarter size and lifted a line and a half: a superscript by pattern.
"patterns": [ { "expression": "\\*$", "typography": { "size": { "ofRoot": 0.26 }, "baseline": 1.5 } } ],
"background": { "fill": "#ffd100", "radius": 5, "padding": { "top": 30, "right": 2, "bottom": 31, "left": 8 } }
},
"animations": [
{ "animation": "wipe", "params": { "direction": "from-left", "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 8 } }
]
},
{
"id": "footnote",
"type": "text",
"zIndex": 4,
"layout": {
"mode": "flow",
"16:9": { "flowIn": "tiers-root", "w": "content", "h": "content" },
"9:16": { "flowIn": "tiers-root", "w": "content", "h": "content" },
"1:1": { "flowIn": "tiers-root", "w": "content", "h": "content" }
},
"typography": {
"16:9": { "family": "GT Eesti Display", "weight": 400, "size": 15, "color": "#ffffff", "case": "uppercase" }
},
"props": { "content": [ { "value": "With selected products. *Via Visa digital gift card. Offer ends 31st May. T&Cs apply" } ] },
"animations": [
{ "animation": "slideFade", "params": { "from": "top", "distance": 8, "durationInFrames": 12 },
"at": { "mode": "cueOffset", "cue": "start", "offsetFrames": 16 } }
]
}
]
}
| Note | Binding target | Control |
|---|---|---|
| Editable text | bonus…value, amount-prefix…value, cashback…value, footnote…value |
text |
| Editable amount | amount-hero.props.content[0].price.amount |
number |
| Change colours | bonus.props.background.fill, amount-bg.props.fill, cashback.props.background.fill, *.typography[ratio].color |
colour |
| Pulse toggle per panel | no numeric leaf — see stress points | — |
What the engine does with it¶
Resolve. $400 formats into parts; the asterisk pattern's { ofRoot: 0.26 } resolves to 46px
against the cashback root of 177; five at references resolve; names expand.
Solve. Four content-sized texts measure — cashback measures Cashback at 177 and * at 46
lifted 1.5 lines, one line, one ink box. amount-row packs on bottoms with a 2px gap; amount-bg
grows the row's extents; tiers-panels stacks three centred with 40px; tiers-root adds the
footnote 40px below.
Animate. Group pulse inherited by three panels, row tilt inherited by prefix and hero, derived fill following the row's animated extents, footnote still.
Place. Nine elements, two paint-only pills, one derived fill.
What this shows¶
- Superscripts are patterns, not layers. The raised asterisk on
Cashback*is one regex on one text layer; the pill hugs the whole ink including the asterisk. - A footnote at 15px uppercase is a first-class text layer with the same machinery as a 191px hero, no special casing.
Stress points¶
The family-wide points from the full stack apply —
wipe versus transform-only, derived background under a -5° row, single gap (37 / 43 / 40 here,
rounded to 40), first-line-only baseline on the UP / TO stack, unbindable pulse toggle. One
addition:
- Does the pill hug the asterisk's raised ink?
cashback's pill is paint-only around itscontentbounds, and a pattern lifting a glyph 1.5 lines makes the ink box taller than the line box. Text Foundation says the pill wraps content plus padding, so the pill should grow to include the lifted asterisk — which is what the reference shows (the asterisk sits inside the yellow). Worth stating explicitly thatcontentbounds for text include pattern-shifted glyphs, since the built code measures "single-line ink" and abaselineshift is exactly the case that leaks past it.