---
title: Script
description: The Script Surface — Segments, Role Cues, Dual Text, Selections, Moments and text projections.
---
# Script
The `
```
The import `@narratage/script@1` activates the Script Surface. The `id` attribute lets other
components refer to the Script and its parts.
## Segments
Segments are ordered blocks of spoken content. The tag name **is** the id — it must be unique within
a Script.
```svml
```
- A Segment can be self-closing (``). An empty Segment has structure but no speech tokens; it
does not imply silence or any default duration.
- Segments cannot nest — every Segment is a top-level child of `
```
### Syntax
| Marker | Meaning |
|---|---|
| `@id` | Open, right-absorbing (starts at the next word) |
| `~@id` | Open, left-absorbing (starts at the previous word's end) |
| `@/id` | Close, left-absorbing (ends at the previous word's end) |
| `@/id~` | Close, right-absorbing (ends at the next word's start) |
The `~` suffix/prefix controls whether the boundary snaps to the left or right. Default open is
right-absorbing; default close is left-absorbing.
### Non-contiguous Selections
The same id can appear multiple times to create a Selection with gaps:
```svml
@beat First point. @/beat Then something else. @beat Third point. @/beat
```
`{story.selection.beat}` now covers two disjoint ranges.
### Crossing Selections
Selections are not required to nest like XML tags. They can cross each other:
```svml
@a One @b two @/a three @/b.
```
Selection markers are zero-width and never appear in any text projection. They compile into
`SelectionSet` values containing `Range[]`. Script itself contains no seconds or frame numbers —
timing comes from WhisperX alignment.
Other components reference Selections via `{story.selection.problem}` to bind visual content to
semantic moments in the narrative.
## Moments
Moments are named time **points** (not ranges):
```svml
@ranking! Image generation, video generation, captions and B-roll
all become reusable components.
```
| Marker | Meaning |
|---|---|
| `@id!` | Right-absorbing (point at the next word's start) |
| `~@id!` | Left-absorbing (point at the previous word's end) |
Moments compile into `MomentSet` values containing `Point[]`. Selection and Moment share the same
name namespace — the same id cannot be used for both.
Other components reference Moments via `{story.moment.ranking}`.
## Slots
Variable interpolation for templated Scripts:
```svml
Meet <${product} | ${product_pronunciation}>.
```
Slot ids are 1–64 characters, starting with a letter or underscore. Binding values are literal
text — they cannot inject SVML syntax. Slots are parsed first, then bound.
## Comments and escaping
```svml
Follow us \@svml on social media.
```
Reserved syntax starters must be escaped:
| Escape | Produces |
|---|---|
| `\@` | literal `@` |
| `\<` | literal `<` |
| `\${` | literal `${` |
| `\\` | literal `\` |
Inside Dual Text, also escape `\|` and `\>`.
## Combination example
A complete Script using all constructs together:
```svml
```
This Script declares:
- Four Segments: `hook`, `meeting`, `evidence`, `payoff`
- One Role Cue: `HOST` (consistent across all Segments)
- One Dual Text: `` (displayed as "BCC", spoken as "B C C")
- Three Selections: `whole` (entire Script), `problem`, `solution`, `emphasis`
- One Moment: `ranking` (marks the instant "After the first recap")
Downstream components reference these by name: `{story.segment.hook.dialogue}` for generation,
`{story.selection.problem}` for B-roll timing, `{story.moment.ranking}` for a visual card reveal.