Skip to content

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 derived layer needed when every panel wraps a single text — the paint-only pill on text does 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.