# Captions (Phase 4a.5) - deterministic, no subagent Captions are produced by **two deterministic scripts** that hand off to each other and emit `compositions/captions.html`; `assemble-index.mjs` then mounts it in `index.html` as a **track-12 clip**. There is **no captions LLM agent** (removed). The entire caption path uses zero LLM calls, so the old class of render-time footguns from "agent hand-writes captions.html" (§6 Illegal invocation / timeline not registered / raw colors / two groups on screen / fitText not wired) is eliminated. ``` captions.mjs group -> caption_groups.json (word engine: clean/group/classify/global timing/scene+surface) captions.mjs html -> compositions/captions.html (HTML engine: choose skin + inject words + brand-tokenize + self-check) assemble-index.mjs -> if file exists, mount track-12 clip (data-composition-id="captions", data-start=0, data-duration=total) ``` Captions remain an **independent file + sub-composition** (not inline), so the **studio caption editor** (recognizes `.caption-group` + fetchable caption source file) and runtime `captionOverrides` (recognizes `.caption-group/.caption-word`) both continue to work. --- ## 0. Inputs The following are inputs for `captions.mjs html`; the input for `captions.mjs group` is `group_spec.json` (see §1). | File | Purpose | | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `caption_groups.json` | **Single source of truth for word data**: `groups[]` (`id`/`scene_id`/`surface`/`start`/`end`/`text`/`words[]`, global seconds, cleaned, classed), `total_duration_s`, `stats`. Produced by `captions.mjs group`. | | `design-system/chunks/tokens.css` | Brand DNA (`--font-display`/`--font-body`/`--brand-primary`/`--canvas`/`--ink` + surface aliases). Used at build for the canvas-measure `FONT_FAMILY` and to validate brand-strict colors; the tokens themselves are declared once globally in `index.html`'s `` (by `assemble-index.mjs`) and inherit into `captions.html` when it mounts, so the per-file `