# Production recipes

Read `agent-playbook.md` for units, adaptation and production approval boundaries. Every parameter below is a proposed default.

## A statement, then a real surface

Stable ID: `title-interface` · Version 1 · 6 s · **proposed-production-default**

**Use:** Open a narrated subject and give a recognizable manual playback cue.

**Avoid:** The recording already starts with an action that cannot tolerate a lead-in; review the timing instead.

### Evidence and contrasts

- **opening-codex** — [A first look at the Codex app](https://www.youtube.com/watch?v=0e-Brv-gS9Q&t=0s), 0.000–9.000 s. A complete title cuts to a formed app, which rests before focused interaction. **editorial-interpretation**. Contrast: contrast: direct cut, not continuous container growth. [Inspection and limits](/videos/openings/#codex-opening).
- **opening-atlas** — [Introducing ChatGPT Atlas](https://www.youtube.com/watch?v=Ej6hnsQgV_c&t=0s), 0.000–14.000 s. A retained icon and later composer precede a gradual reveal of browser context. **editorial-interpretation**. Contrast: contrast: staged reveal of context. [Inspection and limits](/videos/openings/#atlas-opening).

### Capture / input requirements

- Original two-line title; approved presentation font and identity.
- Clean, recognizable first interface state at the delivery aspect ratio.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| title / 20 | `[0.14, 0.32, 0.72, 0.28]` | frame | Original short phrase, left aligned. Baseline grid fixed; masked entry never reflows the text. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| title-build | 0–0.7 | title | Reveal the two lines through a local mask; line two begins at 0.2 s. |
| title-read | 0.7–3 | title | Complete phrase remains still. |
| cue-cut | 3–3 | workspace | Hard cut to the complete interface. This is the recognizable cue, not a claimed automatic sync event. |
| context-read | 3–6 | workspace | Let the surface establish before another movement. |

### Implementation

- Keep title lines at fixed x=.14; do not center every partial word.
- Use a hard cut; the title is not claimed to morph into a window.
- The two-line mask is an original construction, not measured source typography.

```json
{
  "title_font_h": 0.082,
  "line_gap_h": 0.105,
  "line_stagger_s": 0.2,
  "mask_rise_h": 0.035,
  "cue_s": 3
}
```

```bash
python render.py --recipe title-interface --out renders
```

**State contract:** `title` → `workspace-empty`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 3 s; minimum 1 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Typing a long paragraph before the cue.
- Animating the interface before the presenter has time to trigger OBS.
- Treating cue time as actual talking-head start.

### Verify

- The last title frame and first interface frame are adjacent.
- Interface geometry is stationary for the final hold.
- Record cue_s and independently rehearsed start offset.

## Reset the argument without losing the task

Stable ID: `chapter-reset` · Version 1 · 5 s · **proposed-production-default**

**Use:** Speech changes from setup to test, or from one claim to the next.

**Avoid:** The speaker is midway through a dependent action or reading a result.

### Evidence and contrasts

- **chapter-workspace** — [Workspace agents in ChatGPT: Third-party risk management agent](https://www.youtube.com/watch?v=HnSPedbA02Q&t=68s), 68.000–76.000 s. A title separates setup from testing; the same workspace returns. **editorial-interpretation**. Contrast: chapter with typed title. [Inspection and limits](/videos/motion/#test-chapter-reset). Additional consecutive-frame check: [`chapter`](/videos/data/playbook-inspection.json).
- **sidebar-codex** — [A first look at the Codex app](https://www.youtube.com/watch?v=0e-Brv-gS9Q&t=17s), 17.000–22.000 s. Pointer action precedes the wider new-thread framing; the selected excerpt ends before full settlement. **editorial-interpretation**. Contrast: interaction-led progression. [Inspection and limits](/videos/motion/#codex-sidebar-return).

### Capture / input requirements

- Before and after captures from the same task.
- Transcript pause or clause boundary; one short chapter phrase.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| title / 20 | `[0.14, 0.32, 0.72, 0.28]` | frame | Original short phrase, left aligned. Baseline grid fixed; masked entry never reflows the text. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| context | 0–0.6 | workspace | Hold the previous task. |
| chapter | 0.6–3 | title | Hard cut to a short complete phrase; read it. |
| return | 3–5 | workspace | Return to the same task, same crop, same selection. |

### Implementation

- Save the workspace state before inserting the title.
- Use the same window bounds on return; avoid an accidental new-task impression.

```json
{
  "title_font_h": 0.082,
  "cut_in_s": 0.6,
  "cut_out_s": 3
}
```

```bash
python render.py --recipe chapter-reset --out renders
```

**State contract:** `workspace-empty` → `workspace-empty`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 3 s; minimum 1 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Chapter text appears during a critical spoken noun.
- Returning to a reset or unrelated document.

### Verify

- Before and return workspace pixels match for the neutral example.
- Title reading time is not counted as result reading time.

## Establish, push, settle

Stable ID: `context-detail` · Version 1 · 4 s · **proposed-production-default**

**Use:** A small control or output needs larger scale without losing orientation.

**Avoid:** The capture lacks resolution, or a simple cut would explain the change more clearly.

### Evidence and contrasts

- **review-codex** — [A first look at the Codex app](https://www.youtube.com/watch?v=0e-Brv-gS9Q&t=92s), 92.500–98.000 s. The pane is established, then the camera moves, then an inline action opens. **editorial-interpretation**. Contrast: native frames support qualitative deceleration, not an exact ease. [Inspection and limits](/videos/motion/#codex-review-reframe).
- **cut-atlas** — [Introducing ChatGPT Atlas](https://www.youtube.com/watch?v=Ej6hnsQgV_c&t=72s), 72.000–76.000 s. Close crop at 72.300 s is followed by the whole window at 72.333 s. **measured-observation**. Contrast: contrast: adjacent-frame cut rather than a push. [Inspection and limits](/videos/motion/#atlas-context-pullback).

### Capture / input requirements

- Capture width >= output_width * camera_scale; preserve an unscaled master.
- A target rectangle plus at least one nearby orientation landmark.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| establish | 0–1 | workspace | Hold wide context. |
| push | 1–1.5 | workspace | Scale 1 to 1.18 about the focus point with a chosen cubic ease-out. |
| detail-read | 1.5–4 | workspace | Settle completely; keep the pointer and text still. |

### Implementation

- Transform the complete workspace and its pointer together, not the background.
- For point p and pivot a, output q=a+scale*(p-a). Mask the window before applying this transform.
- An alternative is a hard cut like the Atlas comparison. Do not interpolate a reference that was a cut.

```json
{
  "camera_scale": 1.18,
  "camera_pivot_norm": [
    0.62,
    0.5
  ],
  "ease": "1-(1-u)^3",
  "max_upscale_ratio": 1
}
```

```bash
python render.py --recipe context-detail --out renders
```

**State contract:** `workspace-empty` → `workspace-detail`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 1.5 s; minimum 1.5 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Zooming while the viewer reads newly appearing text.
- A pointer that drifts away because it uses another coordinate space.
- Upscaling a compressed crop until labels become soft.

### Verify

- Focus stays within safe bounds at maximum scale.
- No motion remains during the final hold.
- Inspect exported text at 640 x 360, not only at full size.

## Make the next action unambiguous

Stable ID: `pointer-intent` · Version 1 · 3 s · **proposed-production-default**

**Use:** The viewer needs to connect an action with its consequence.

**Avoid:** A recorded native pointer already communicates the action; do not add a duplicate.

### Evidence and contrasts

- **sidebar-codex** — [A first look at the Codex app](https://www.youtube.com/watch?v=0e-Brv-gS9Q&t=17s), 17.000–22.000 s. Pointer action precedes the wider new-thread framing; the selected excerpt ends before full settlement. **editorial-interpretation**. Contrast: interaction-led progression. [Inspection and limits](/videos/motion/#codex-sidebar-return).
- **select-atlas** — [Introducing ChatGPT Atlas](https://www.youtube.com/watch?v=Ej6hnsQgV_c&t=44s), 44.000–50.000 s. Text selection precedes a local control while the page stays in place. **editorial-interpretation**. Contrast: local selection over an email. [Inspection and limits](/videos/motion/#atlas-inline-reveal).

### Capture / input requirements

- Native cursor capture OR a cursor-free capture and an explicit pointer path, never both.
- Control bounds recorded in the capture coordinate system.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| pointer / 30 | `[0.36, 0.4, 0.016, 0.033]` | workspace | One arrow; its tip, not its bounding-box center, follows the path. No second cursor in a production capture. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| orient | 0–0.5 | workspace | Hold the interface before pointer travel. |
| travel | 0.5–1.3 | pointer | Move tip from (.72,.72) to (.36,.40), decelerating. |
| target-dwell | 1.3–3 | pointer | Stop at the input; no click ripple, no continued orbit. |

### Implementation

- Use one short path with no decorative loops.
- Travel ends before typing begins. Pointer dwell carries intent without an annotation.

```json
{
  "cursor_start_norm": [
    0.72,
    0.72
  ],
  "cursor_target_norm": [
    0.36,
    0.4
  ],
  "cursor_width_w": 0.016,
  "ease": "1-(1-u)^3"
}
```

```bash
python render.py --recipe pointer-intent --out renders
```

**State contract:** `workspace-empty` → `input-focused`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 1.3 s; minimum 0.7 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Pointer covers the exact word being discussed.
- Click effect implies a click that never occurred in the product.
- Mouse acceleration from the desktop is mistaken for an authored ease.

### Verify

- Tip arrives inside the input rectangle.
- Final 0.7 s or more is stationary.
- The next recipe inherits the input-target position.

## Separate composing from committing

Stable ID: `type-submit` · Version 1 · 5.5 s · **proposed-production-default**

**Use:** The wording of a request is part of the explanation.

**Avoid:** The wording is long or incidental; show a complete genuine prompt instead.

### Evidence and contrasts

- **task-agent** — [A Look at ChatGPT agent](https://www.youtube.com/watch?v=2wzGS_WUZYQ&t=4s), 4.000–7.000 s. The container grows, the request types, and website content arrives later. **editorial-interpretation**. Contrast: contrast: cursor-attached editorial typing rather than a native caret. [Inspection and limits](/videos/motion/#agent-task-card-entry).
- **select-writing** — [Writing with canvas in ChatGPT](https://www.youtube.com/watch?v=Ks1C-5p04PY&t=82s), 82.000–90.000 s. Selected text and a local toolbar precede the contextual request. **editorial-interpretation**. Contrast: native selected-document interaction. [Inspection and limits](/videos/motion/#selected-text-local-request). Additional consecutive-frame check: [`selection`](/videos/data/playbook-inspection.json).

### Capture / input requirements

- Original short request; ensure it fits the composer without truncation.
- Capture the actual submitted state when adapting this to a real product.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| pointer / 30 | `[0.36, 0.4, 0.016, 0.033]` | workspace | One arrow; its tip, not its bounding-box center, follows the path. No second cursor in a production capture. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| focus | 0–0.4 | pointer | Pointer remains on the input. |
| type | 0.4–2.8 | workspace | Reveal the original prompt at a deterministic editorial cadence. |
| read | 2.8–3.5 | workspace | Complete request holds before submission. |
| to-submit | 3.5–4.1 | pointer | Move to the submit control. |
| submit | 4.1–4.1 | workspace | Button changes state; retain the complete request. |
| pointer-clear | 4.1–4.7 | pointer | Move off the result region to (.94,.88). |
| submitted | 4.7–5.5 | workspace | Hold the pending state. |

### Implementation

- Keep the composer width and baseline constant during typing.
- Caret blink belongs to the input, not an unexplained second cursor.
- The neutral example uses uniform character cadence; neither typing cadence nor 0.8 s pending hold is a product-latency measurement.

```json
{
  "typing_duration_s": 2.4,
  "submit_target_norm": [
    0.83,
    0.465
  ],
  "park_norm": [
    0.94,
    0.88
  ],
  "caret_period_s": 0.5
}
```

```bash
python render.py --recipe type-submit --out renders
```

**State contract:** `input-focused` → `submitted`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 4.7 s; minimum 0.5 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Submitted text differs from the visible request.
- Typing, camera movement, and result animation compete.
- The caret continues blinking over a final result.

### Verify

- Full prompt is visible before submission.
- Submit precedes progress and output.
- No audio stream is exported.

## Selection explains the scope

Stable ID: `selection-action` · Version 1 · 5 s · **proposed-production-default**

**Use:** A change applies to a specific passage or row rather than the whole document.

**Avoid:** The real product does not offer the selected contextual action.

### Evidence and contrasts

- **select-writing** — [Writing with canvas in ChatGPT](https://www.youtube.com/watch?v=Ks1C-5p04PY&t=82s), 82.000–90.000 s. Selected text and a local toolbar precede the contextual request. **editorial-interpretation**. Contrast: native selected-document interaction. [Inspection and limits](/videos/motion/#selected-text-local-request). Additional consecutive-frame check: [`selection`](/videos/data/playbook-inspection.json).
- **select-atlas** — [Introducing ChatGPT Atlas](https://www.youtube.com/watch?v=Ej6hnsQgV_c&t=44s), 44.000–50.000 s. Text selection precedes a local control while the page stays in place. **editorial-interpretation**. Contrast: local selection over an email. [Inspection and limits](/videos/motion/#atlas-inline-reveal).

### Capture / input requirements

- A genuine selectable passage and verified available action.
- Enough context to see that this is a local selection.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| result-surface / 18 | `[0.3, 0.56, 0.58, 0.23]` | workspace | Opaque result-card background only; draw before the highlight. |
| selection / 19 | `[0.319, 0.642, 0.44, 0.04]` | workspace | Tint above the card background and below its glyphs; text itself stays opaque. |
| result / 20 | `[0.3, 0.56, 0.58, 0.23]` | workspace | Result heading and row glyphs only. The separate result-surface layer owns the opaque card background. |
| toolbar / 25 | `[0.32, 0.804, 0.3, 0.055]` | workspace | Local action bar below content, outside the highlighted line. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| orient | 0–0.7 | workspace | Show readable document rows. |
| select | 0.7–1.4 | selection | Extend one translucent highlight across the target row. |
| selection-read | 1.4–1.8 | selection | Hold the selected scope. |
| toolbar | 1.8–2.1 | toolbar | Reveal a local action below the selected row, without moving the document. |
| scope-read | 2.1–5 | workspace | Hold scope and available action; do not claim the edit has completed. |

### Implementation

- Selection is beneath glyphs, not a translucent text layer.
- A selection and a contextual menu are scope evidence, not completion proof.

```json
{
  "selection_opacity": 0.32,
  "selection_row": 0,
  "toolbar_gap_h": 0.014
}
```

```bash
python render.py --recipe selection-action --out renders
```

**State contract:** `document` → `document-selected`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 2.5 s; minimum 1.5 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Highlight obscures text.
- Moving the camera while the selection expands.
- Rendering a fabricated successful edit after a menu opens.

### Verify

- Only the intended row is tinted.
- Toolbar appears after selection is complete.
- The result is explicitly still unmodified.

## Scroll toward a named destination

Stable ID: `scroll-landmark` · Version 1 · 5 s · **proposed-production-default**

**Use:** A result extends below the viewport and one region matters to the spoken point.

**Avoid:** The destination could fit through a better initial crop; avoid scrolling for decoration.

### Evidence and contrasts

- **scroll-calendar** — [Make information visual with ChatGPT](https://www.youtube.com/watch?v=jzmNh8lbSp8&t=44s), 44.000–49.000 s. The generated calendar moves upward while the application frame and presenter inset remain fixed. **editorial-interpretation**. Contrast: document scroll, not a camera zoom. [Inspection and limits](/videos/motion/#list-to-calendar). Additional consecutive-frame check: [`scroll`](/videos/data/playbook-inspection.json).
- **preview-canvas** — [Prototyping with canvas in ChatGPT](https://www.youtube.com/watch?v=JbIvaFh44EY&t=90s), 90.000–98.000 s. Pending gives way to a dashboard; chart content continues drawing after the dashboard appears. **editorial-interpretation**. Contrast: content arrival is not readability onset. [Inspection and limits](/videos/motion/#canvas-code-to-preview). Additional consecutive-frame check: [`preview`](/videos/data/playbook-inspection.json).

### Capture / input requirements

- A tall genuine result with one known destination.
- Record initial and final scroll offsets; avoid responsive reflow between captures.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| document / 20 | `[0.3, 0.34, 0.58, 0.47]` | workspace | Tall content inside a hard viewport mask. The mask stays fixed; the content moves behind it. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| orient | 0–0.8 | workspace | Establish header and visible rows. |
| scroll | 0.8–2.2 | document | Translate only the document upward by .18 frame height. |
| land | 2.2–5 | document | Stop on the named result. Keep header and frame stationary. |

### Implementation

- Use document-space translation, never a whole-frame camera move.
- Fixed header, viewport edges, and pointer separate scroll from zoom.
- No requirement to match the source scroll acceleration.

```json
{
  "scroll_distance_h": 0.18,
  "ease": "1-(1-u)^3",
  "landmark": "Ready to review"
}
```

```bash
python render.py --recipe scroll-landmark --out renders
```

**State contract:** `document-top` → `document-landmark`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 2.2 s; minimum 1.5 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Reading during the scroll.
- Destination hidden under a sticky header.
- Clipped labels leak outside the viewport mask.

### Verify

- Header pixels do not move.
- The destination is fully inside the viewport.
- No content motion remains during the final hold.

## Wait, reveal, then become readable

Stable ID: `progress-result` · Version 1 · 5.5 s · **proposed-production-default**

**Use:** The action has a visible working state before a result.

**Avoid:** A real result failed or is not yet available; capture the failure honestly.

### Evidence and contrasts

- **preview-canvas** — [Prototyping with canvas in ChatGPT](https://www.youtube.com/watch?v=JbIvaFh44EY&t=90s), 90.000–98.000 s. Pending gives way to a dashboard; chart content continues drawing after the dashboard appears. **editorial-interpretation**. Contrast: content arrival is not readability onset. [Inspection and limits](/videos/motion/#canvas-code-to-preview). Additional consecutive-frame check: [`preview`](/videos/data/playbook-inspection.json).
- **patch-ide** — [Shipping code to your IDE with ChatGPT](https://www.youtube.com/watch?v=_WvtdRtG1aY&t=92s), 92.000–100.000 s. A working state gives way to a visible diff and review controls; a later explanation shifts the panel. **editorial-interpretation**. Contrast: contrast: inspectable changes rather than a generated chart; no test-pass claim. [Inspection and limits](/videos/motion/#ide-patch-review).

### Capture / input requirements

- Uncut real run retained privately, including failure and retry states.
- Captured completed output with identifiable content, not merely a success toast.
- If wait is shortened, place a visible time-compression label and record the omitted interval.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| result / 20 | `[0.3, 0.56, 0.58, 0.23]` | workspace | One output card with three original rows. Data and heading remain stable during the reading interval. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| work | 0–1.4 | workspace | Show an explicitly illustrative pending state. |
| reveal | 1.4–1.9 | result | Replace pending with the result container; content fades in. |
| settle | 1.9–2.5 | result | The complete result is now visible; leave a settling allowance. |
| result-read | 2.5–5.5 | result | Hold with no spinner, caret, scroll, or camera movement. |

### Implementation

- Pending and result share a stable slot.
- The neutral crossfade is chosen; production should preserve native result behavior.
- First visible container is not the readability onset. Late chart or row builds delay the start of the hold.

```json
{
  "reveal_duration_s": 0.5,
  "settle_allowance_s": 0.6,
  "loading_dot_period_s": 0.6,
  "latency_status": "illustrative-not-product-latency"
}
```

```bash
python render.py --recipe progress-result --out renders
```

**State contract:** `submitted` → `result-ready`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 2.5 s; minimum 2 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Counting a skeleton as a readable result.
- Cutting out all waiting without disclosure.
- Stopping the footage while a chart is still building.

### Verify

- No result appears before submission.
- Final hold hashes stay identical.
- Latency is not inferred from this edited study.

## Let the proof carry the sentence

Stable ID: `result-hold` · Version 1 · 4 s · **proposed-production-default**

**Use:** Speech names an outcome the viewer must inspect.

**Avoid:** Only a toast or unverified claim is visible; obtain real proof first.

### Evidence and contrasts

- **preview-canvas** — [Prototyping with canvas in ChatGPT](https://www.youtube.com/watch?v=JbIvaFh44EY&t=90s), 90.000–98.000 s. Pending gives way to a dashboard; chart content continues drawing after the dashboard appears. **editorial-interpretation**. Contrast: content arrival is not readability onset. [Inspection and limits](/videos/motion/#canvas-code-to-preview). Additional consecutive-frame check: [`preview`](/videos/data/playbook-inspection.json).
- **result-codex** — [A first look at the Codex app](https://www.youtube.com/watch?v=0e-Brv-gS9Q&t=121s), 121.000–130.000 s. The app output remains visible through the 127.503 s sample; a white closing wordmark is present by 128.003 s. The output changes at late samples, so this is not a nine-second frozen result hold. **measured-observation**. Contrast: single-example finding for the sampled final output-to-title boundary. [Inspection and limits](/videos/films/codex-first-look/).

### Capture / input requirements

- A completed output and the exact sentence that needs it.
- List the essential words or values the viewer must read.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| result / 20 | `[0.3, 0.56, 0.58, 0.23]` | workspace | One output card with three original rows. Data and heading remain stable during the reading interval. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| read | 0–4 | result | Show the completed result and stop all motion. |

### Implementation

- Proposed reading budget: max(3 s, essential_word_count / 3 + .6 s). Validate with a reader; this is not a measured source rule.
- Crop or simplify before shrinking text. Keep the task title and outcome together.

```json
{
  "minimum_body_font_h": 0.035,
  "read_words_per_s": 3,
  "orientation_allowance_s": 0.6,
  "reference_viewport_px": [
    640,
    360
  ]
}
```

```bash
python render.py --recipe result-hold --out renders
```

**State contract:** `result-ready` → `result-ready`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 0 s; minimum 3 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- New movement steals attention during the claim.
- Whole-page proof is technically present but too small.
- Small disclaimer is needed to make a large claim true.

### Verify

- Read all essential result words at 640 x 360.
- Frames at beginning, middle, and end of the hold are pixel-identical.
- Dense results require a longer requested duration.

## Carry one object across the cut

Stable ID: `object-handoff` · Version 1 · 4.5 s · **proposed-production-default**

**Use:** The same artifact changes presentation context.

**Avoid:** Two unrelated outputs would be made to look like one object.

### Evidence and contrasts

- **opening-study** — [Introducing ChatGPT Study Mode](https://www.youtube.com/watch?v=XDYilxy1dn8&t=0s), 0.000–10.000 s. A homework thumbnail reappears inside a composer through a cut; recognizable content preserves identity. **editorial-interpretation**. Contrast: cut-based object continuity. [Inspection and limits](/videos/openings/#study-opening).
- **deck-agent** — [ChatGPT agent Makes Slideshows](https://www.youtube.com/watch?v=szJI9YJNEZk&t=66s), 66.000–74.000 s. An attachment preview is followed by a larger viewer with a thumbnail rail. **editorial-interpretation**. Contrast: contrast: artifact expands into viewing context. [Inspection and limits](/videos/motion/#deck-card-to-viewer).

### Capture / input requirements

- One original asset reused unchanged, or two genuine captures with a verified identity match.
- A saved object ID and normalized anchor in both scenes.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| artifact / 20 | `[0.48, 0.38, 0.26, 0.3]` | workspace | Retained original card with a distinctive stepped path; same asset and bounds in both scenes. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| object-read | 0–2 | artifact | Hold the original artifact on paper. |
| context-cut | 2–2 | workspace | Hard cut to a workspace with the exact same artifact, size, and position. |
| context-read | 2–4.5 | workspace | Surrounding context explains where the object went. |

### Implementation

- Object continuity comes from identity and location, not an invented morph.
- For a moving variant interpolate an explicit common anchor; retain the same asset throughout.

```json
{
  "artifact_rect_norm": [
    0.48,
    0.38,
    0.26,
    0.3
  ],
  "transition": "cut",
  "identity_tolerance_px": 0
}
```

```bash
python render.py --recipe object-handoff --out renders
```

**State contract:** `artifact-isolated` → `artifact-in-workspace`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 2 s; minimum 1.5 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Content swaps while the frame implies continuity.
- Tiny changes to crop, corner radius, or scale cause a jump.
- Calling a cut a morph.

### Verify

- Artifact-region pixels are identical on adjacent cut frames.
- New context does not cover the retained object.

## Finish the proof before the sign-off

Stable ID: `quiet-ending` · Version 1 · 5 s · **proposed-production-default**

**Use:** The final result has been read and the speaker is concluding.

**Avoid:** Speech still depends on a detail that would disappear, or the supplied recording lacks a safe ending tail.

### Evidence and contrasts

- **ending-codex** — [A first look at the Codex app](https://www.youtube.com/watch?v=0e-Brv-gS9Q&t=127s), 127.850–132.610 s. The wordmark departs before a changing mark reaches a quieter pose around 131.131 s. **editorial-interpretation**. Contrast: quiet landmark is visual, not an exact authoring keyframe. [Inspection and limits](/videos/logos/#codex-blossom).
- **ending-atlas** — [Introducing ChatGPT Atlas](https://www.youtube.com/watch?v=Ej6hnsQgV_c&t=89s), 89.650–93.500 s. The outer tile precedes the blue interior and directional symbol; a later URL card is outside this excerpt. **editorial-interpretation**. Contrast: contrast: nested icon build, not wordmark-to-knot deletion. [Inspection and limits](/videos/logos/#atlas-icon).
- **result-codex** — [A first look at the Codex app](https://www.youtube.com/watch?v=0e-Brv-gS9Q&t=121s), 121.000–130.000 s. The app output remains visible through the 127.503 s sample; a white closing wordmark is present by 128.003 s. The output changes at late samples, so this is not a nine-second frozen result hold. **measured-observation**. Contrast: single-example finding for the sampled final output-to-title boundary. [Inspection and limits](/videos/films/codex-first-look/).

### Capture / input requirements

- Original closing phrase and owned identity assets.
- Recording-derived last spoken word, wave, pause onset, and recording end.
- Calibrated cue-to-OBS delay from rehearsal.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| result / 20 | `[0.3, 0.56, 0.58, 0.23]` | workspace | One output card with three original rows. Data and heading remain stable during the reading interval. |
| title / 20 | `[0.14, 0.32, 0.72, 0.28]` | frame | Original short phrase, left aligned. Baseline grid fixed; masked entry never reflows the text. |
| mark / 25 | `[0.14, 0.63, 0.12, 0.08]` | frame | Original three-bar motif. Its shape has no relationship to a source trademark. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| last-proof | 0–1 | result | Retain the completed output for one additional second. |
| ending-cut | 1–1 | title | Cut to an original closing phrase. |
| mark-build | 1.3–2.3 | mark | Three simple bars build at .12 s offsets; no source logo is traced. |
| quiet | 2.6–5 | title | All motion has stopped. Leave a clean ending pose. |

### Implementation

- Separate the source lesson of staged arrival and a quieter tail from the copyrighted mark.
- The proof study is not a synchronized presentation. Final end time must satisfy the paired-timeline contract.

```json
{
  "mark_stagger_s": 0.12,
  "quiet_from_s": 2.6,
  "ending_font_h": 0.082
}
```

```bash
python render.py --recipe quiet-ending --out renders
```

**State contract:** `result-ready` → `ending-quiet`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 2.6 s; minimum 2 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Starting the outro before the final proof is readable.
- Endless spinning mark.
- Subtracting file durations instead of comparing shared-timeline endpoints.
- Inventing a wave or freezing a speaking face.

### Verify

- Quiet interval is at least 2 s in this study.
- No audio stream.
- For production, presentation ends while the recorded wave/pause is still running.

## A label that knows what it belongs to

Stable ID: `anchored-caption` · Version 1 · 4.5 s · **proposed-production-default**

**Use:** Identify an artifact or chapter without displacing the evidence.

**Avoid:** A name label would duplicate the separate talking-head video, or the result occupies the lower edge.

### Evidence and contrasts

- **caption-paired** — [Introducing Agent Plugins](https://www.youtube.com/watch?v=UaeWJK_vv-Y&t=3s), 3.300–7.800 s. Both text fields enter together and leave with a cut. **measured-observation**. Contrast: measured hard-on; no recovered font. [Inspection and limits](/videos/lower-thirds/#paired-id).
- **caption-persistent** — [ChatGPT can now complete tasks on your computer](https://www.youtube.com/watch?v=dB6pOolO7io&t=6s), 6.150–12.800 s. The paired text remains at the same screen position across a camera cut. **measured-observation**. Contrast: contrast: persistent label across a cut. [Inspection and limits](/videos/lower-thirds/#id-across-cut).

### Capture / input requirements

- An original artifact name and short descriptor.
- A clear lower safe band; never import speaker identities from a reference.

### Layers and normalized geometry

`[x,y,width,height]` is normalized to the full frame. Workspace layers inherit the camera; frame layers do not.

| Layer / z | Rectangle | Space | Construction |
| --- | --- | --- | --- |
| field / 0 | `[0, 0, 1, 1]` | frame | Solid warm paper. No moving texture behind readable type. |
| workspace / 10 | `[0.07, 0.12, 0.86, 0.78]` | frame | Original neutral fixture; rounded alpha mask, 1 px border at 1280 width. Clip content before the camera transform. |
| caption / 40 | `[0.07, 0.9, 0.86, 0.075]` | frame | Dark two-field band outside the product window; one baseline, fixed left and right fields. |

### Choreography

Intervals are recipe-local seconds, half-open. A zero-width interval is an instantaneous cut/action. Concurrent layer activity is described explicitly; these are chosen values, not measured source timings.

| Phase | Start–end (s) | Layer | Action / overlap |
| --- | --- | --- | --- |
| establish | 0–0.5 | workspace | Show the artifact first. |
| caption | 0.5–0.5 | caption | Both caption fields switch on together. |
| read | 0.5–4.5 | caption | Keep the caption anchored to the frame, not the moving workspace. |

### Implementation

- The source comparison demonstrates that a label can leave with a cut OR persist across one.
- The example uses a contrasting band for legibility, not a claim that the source has a backing plate.
- Keep a person-ID recipe out of the default separate-presentation workflow.

```json
{
  "caption_font_h": 0.027,
  "caption_gap_w": 0.26,
  "entrance": "hard-on"
}
```

```bash
python render.py --recipe anchored-caption --out renders
```

**State contract:** `workspace-empty` → `workspace-caption`.

### Duration adaptation

Keep all phase onsets fixed. Change only the final settled hold. Reject a total below hold_start_s + minimum_hold_s; split the narrated beat or reduce content instead. Longer speech extends the hold, not typing speed, cursor speed, or product latency.

Final hold begins at 1 s; minimum 2 s. `result-hold` also enforces the essential-word reading floor. The `type-submit` tail is a pending state, so its indicator may still move; it is not counted as readable-result time.

### Failure modes

- Caption covers the output.
- White type becomes unreadable over a changed background.
- Copying a sampled source font as an exact identification.

### Verify

- Fields share a baseline and arrive together.
- Label is outside result bounds.
- Caption stays in screen space through any later camera move.