# Recipe controls

## Supported authoring input

The supplied `build/core/adapters/typography.ts` exports
`buildWordmarkContent`. Its source and contract are unchanged from the accepted
core archive. It generates 365 path slots plus word/paper/ink. It does not fit
arbitrary logos or recover the source artwork.

| Input | Exact supported values |
| --- | --- |
| `family` | `compass` (four lobes), `beacon` (three; surface 3 empty) |
| `word` | Required `^O[a-z]{5}$`; capital O plus five lowercase letters |
| `lobeAspect` | Finite `[0.94,1.06]`; default 1 |
| `apertureScale` | Finite `[0.90,1.08]`; default 1 |
| `ink` | Opaque `#RRGGBB`, every channel ≤64; default `#080808` |
| `paper` | Only `#ffffff` |

The actual browser must also measure the complete word ≤760.5 px, using Geist,
weight 650, size 170 px, letter spacing 10 px. There is no font-size fallback or
automatic shrink. Pure builder validation is not the browser-width check.

Supplied pair: `{family:"compass",word:"Origin"}` and
`{family:"beacon",word:"Orchid"}`. Their measured full widths are
548.355224609375 and 597.230224609375 px. The browser-observed line baseline is
154 px from the top of the 187 px line box. Geist is an OFL-licensed substitute,
not the source film's recovered typeface.

```json
{"family":"compass","word":"Origin","lobeAspect":1.02,"apertureScale":0.98}
```

Save a new design JSON and generate props without modifying the frozen recipe:

```bash
node --experimental-strip-types design.mjs --project build/core \
  --design my-design.json --out my-input-props.json
```

The resulting JSON is the complete `{recipe,content}` input accepted by the
supplied Remotion Root. In an existing Remotion application, the direct API is:

```tsx
import {Treatment} from './build/core/src/Treatment';
import {buildWordmarkContent} from './build/core/adapters/typography';
import type {Recipe} from './build/core/src/types';
import selectedRecipe from './build/core/recipes/agent-wordmark-outline-finish.json';

const recipe = selectedRecipe as Recipe;
const content = buildWordmarkContent({family: 'compass', word: 'Origin'});
export const Finish = () => <Treatment recipe={recipe} content={content}/>;
```

Register at 1920×1080, 60 fps, 151 frames; serve the supplied `public/fonts/Geist.ttf`
through Remotion's public directory. `Treatment` owns its current-frame clock
and font-fit gate. No source movie or source PNG is an input. The standalone
fixture runner uses this exact implementation with both frozen contents.

## Geometry and order

- Local 0–39: heavy word in a 760×205 px box; line height 1.1, center aligned,
  origin `(380,0)`. Each native frame has its own horizontal position. Preserve
  those coordinates rather than centering a newly shortened word in the canvas.
- Local 36–39: the lone O uses scale X 1.034, scale Y 0.952 and Y 450.5. Earlier
  frames use scales 1 and Y 450. See the per-frame CSV for X.
- Local 40–112: one 260×260 viewbox per authored pose, with five **ordered**
  path surfaces. Surfaces use white fill and 9.4 px ink stroke. White occlusion
  is part of construction; merging every contour into one unfilled stroke
  changes intersections. Keep surfaces 0→4 in painter order.
- Surface 4 opens the aperture on the native 49–62 clock. The compact topology
  is resolved by 65. The remaining frames deform independently through 112;
  this is not a rigid completed-mark spin.
- Pose 112 is held exactly on `[112,151)`. Do not add fades, rotation, scale,
  path interpolation or a settling wobble during those 39 frames.

The code and CSV contain sampled construction poses; they are not measured
physical rotation angles of the source identity. Family, aspect and aperture
are bounded original design controls, not permissions to use the six-loop brand.

## Observed limits

The SVG exporter is a separate vector serialization, not a flattening of the
Remotion output. Its browser rasterization differs on some subpixel text and
path edges. `PROOF.json` records the measured differences. Editing SVG text in
a program that does not support its embedded font can change the layout; the
Resolve procedure uses the pinned browser-prepared PNG derivative instead.
Source-faithful identity topology, arbitrary words/logos, native Resolve shape
editing and pixel-identical cross-engine glyph rasterization are not supplied.
