# 0nlyType

A design system for type and silence. Two typefaces, one accent, and a great deal of space. Read INTENT.md first; this file is the how.

- Library: a shadcn registry. `npx shadcn@latest add https://thedirectors.agency/ui/r/<item>.json`
- Items: `registry/0nlytype/ui/<item>.tsx`, each with a sidecar `registry/0nlytype/styles/<item>.css`
- Base: `registry/0nlytype/styles/{tokens,base,fonts}.css` (the `0nlytype` base item)
- Specimen: `specimen/index.html`, the original static page, served at `/specimen/`. It still uses the old `f-` names; everything else uses `ot-`.

## Principles

1. **Silence is structure.** Space does the layout. A hairline appears only where space alone can't hold two things apart.
2. **Type is the only ornament.** Weight, width, size, tracking and order carry every level of hierarchy. No icons, fills or shadows.
3. **Ours in roman, yours in italic.** Interface text is the voice, upright. Anything the person chose, typed or set turns into the expression italic: a picked option, a typed value, a switch state, a slider value, a named item they own. Display uses `--ot-expression-scale`; text uses the same face in its reading grade, with more ink, a little air and a text-size optical cut where available. Musical and foreign terms are italic too (`.ot-term`), by book convention.
4. **One note of colour.** One accent marks where you are: the current page, the chosen option, focus. At most one accent mark in view. Crimson is only for errors. The highlighter is only for reading marks.
5. **Nothing moves unless you do.** Motion answers an action, then rests. Pointing sketches in pencil; choosing inks it in. The overture plays once per browser, on the home page's first visit, and can be skipped. A demonstration of a component waits for a Demonstrate press. The owner-approved exceptions (2026-10-01) are marquee, text-ribbon and word-relay autoplay: each is pausable and off under reduced motion.

## Conventions

- Tokens are `--ot-*`. Component classes are `ot-<name>`.
- States live on native attributes (`:checked`, `:disabled`, `[aria-selected]`, `[aria-invalid]`, `[aria-current]`, `[aria-pressed]`, `[aria-busy]`). Variants live on `data-variant`, and size on `data-size`.
- `[data-force~="hover"]` and `[data-force~="focus"]` pin a state for documentation rows.
- Every control is built on the right native element, so the React port can use native elements or Radix without changing the look.
- Four switches on `<html>`, all optional:
  - `data-mode="day | nocturne"`
  - `data-scheme="blueprint | statue | silence | riso"` (no attribute means cotton)
  - `data-key="ultramarine | viridian | ember | violet"`, which overrides the scheme's accent and is declared last so it always wins
  - `data-pair="press | paris | salon"` (no attribute means parma)
- One creative move per component, and only one, drawn from the poster references (see "Where each move comes from"). Likewise one motion per component, named as an articulation (see "Motion").
- `[hidden]` always wins over a component's `display`.
- Copy: sentence case, active verbs. An action keeps its name through the flow (Upload, Uploading, Uploaded). Errors say what to fix and never apologise.

## Tokens

### Colour

| Token | Day | Nocturne | Role |
|---|---|---|---|
| `--ot-paper` | `#f2f3f0` | `#10111c` | The page |
| `--ot-ink` | `#000` | `#e9eaec` | Display type, the statement block |
| `--ot-graphite` | `#4a4b50` | `#b4b5bc` | Body text |
| `--ot-pencil` | `#6b6c71` | `#83848c` | Placeholders, captions, done or off |
| `--ot-rule` | ink at 14% (`color-mix`) | same | Hairlines |
| `--ot-rule-strong` | ink at 42% (`color-mix`) | same | Baselines, ticks, rings |
| `--ot-accent` | `#2b2bee` | `#8c8cff` | Where you are |
| `--ot-signal` | `#c8102e` | `#ff6b7f` | Errors only |
| `--ot-mark` | `#ffe45a` | same | Selection, `<mark>`, link hover |
| `--ot-on-mark` | `#000` | same | Text on the highlighter |

Keys (`--ot-accent`, day / nocturne): ultramarine `#2b2bee` / `#8c8cff`, viridian `#0b6e4f` / `#4fd1a5`, ember `#b83d00` / `#ff8a4c`, violet `#6a1b9a` / `#c58cf2`. Every key clears 4.5:1 on every scheme's paper (lowest: ember on silence, 4.56).

Schemes move paper, ink, graphite, pencil, accent and signal together. The rules follow the ink. Values are listed as day, then Nocturne.

| Scheme | Paper | Ink | Pencil | Accent | From |
|---|---|---|---|---|---|
| cotton (house) | `#f2f3f0` / `#10111c` | `#000` / `#e9eaec` | `#6b6c71` / `#83848c` | `#2b2bee` / `#8c8cff` | "It has to be design." |
| blueprint | `#edf0f7` / `#0a1766` | `#0c1b8f` / `#f0f2ff` | `#58608f` / `#929ad0` | `#c23d00` / `#ff9557` | The calendar posters' one orange dot |
| statue | `#ebeae5` / `#0d1528` | `#14213d` / `#eee7d7` | `#5f687e` / `#938d80` | `#875600` / `#e3b04f` | The Renaissance and Greek statue prints |
| silence | `#e2e8e3` / `#0c1c18` | `#0e2a23` / `#e1ebe6` | `#4f6962` / `#7a918a` | `#1b3de0` / `#93a6ff` | "the silence that heals" |
| riso | `#f6f5f2` / `#1a1537` | `#25286b` / `#f8eef5` | `#636591` / `#9d92ab` | `#b8005f` / `#ff62b0` | Two-drum risograph prints |

All text colours (ink, graphite, pencil, accent, signal) clear 4.5:1 on their paper in both modes. Checked with a script, and live on the specimen's palette.

### Type

- `--ot-voice`: a grotesque. Everything the interface says.
- `--ot-expression`: an italic serif. Everything the person says back.
- `--ot-expression-scale`: lifts the display italic until the two x-heights meet. It's set per pair; text roles locally use the reading scale below.

| Pair | Voice | Expression | Scale |
|---|---|---|---|
| parma (house) | Archivo (width 62–125, weight 100–900) | Bodoni Moda (optical size 6–96) | 1.15 |
| press | Schibsted Grotesk (weight 400–900) | Newsreader (optical size 6–72) | 1.1 |
| paris | Instrument Sans (width 75–100, weight 400–700) | EB Garamond | 1.24 |
| salon | Bricolage Grotesque (optical size, width 75–100, weight 200–800) | Cormorant | 1.26 |

**The expression's reading grade.** The italic is the same family at every size. At the text steps (`pp`, `p`, `mp`), thin display strokes need more ink and small counters need room. `base.css` applies one shared grade to typed inputs and textareas, editable text, selected values, text-size personal words, prose `em` / `i` and quotations, and small italic labels. `--ot-reading` is the local scale and supplies `--ot-expression-scale` on the expression element itself, never on a panel. Existing leading and component geometry stay with the sidecar. `.ot-reading` opts a new text-size expression into the same rule; use it on the italic, not a parent containing roman or display type.

| Pair | `--ot-expression-text-opsz` | `--ot-expression-text-weight` | `--ot-expression-text-tracking` | `--ot-expression-text-scale` |
|---|---|---|---|---|
| parma | 6 | 500 | 0.012em | 1.18 |
| press | 6 | 500 | 0.01em | 1.12 |
| paris | No optical-size axis | 500 | 0.015em | 1.3 |
| salon | No optical-size axis | 600 | 0.015em | 1.38 |

For Bodoni Moda and Newsreader, `--ot-expression-text-variation` pins `"opsz"` to `--ot-expression-text-opsz` with automatic optical sizing off. Garamond and Cormorant use `normal` variation settings and their real weight axes. Small italic prose and labels use full `--ot-ink`, rather than graphite or pencil; intentional accent states, ink reversals, invisible measurement copies, disabled controls and roman placeholders keep their own colours. On cotton paper, ink is 18.85:1 by day and 15.59:1 in nocturne; contrast is measured independently of the font's stroke quality.

Display italics keep their original optical sizing, weight, tracking, scale and colour: hero lines, titles, large figures, the overprint and signature fields, sforzando choices, statement relays and fitted type. Do not apply a reading grade to a whole component to catch a small label. Cormorant remains Cormorant; if a use still cannot be read at 16px after grading, propose a text-italic companion for owner review rather than silently substituting a family.

The width moves (the title's exhale, the statement button, the disclosure) only travel as far as each voice's width axis allows. Schibsted has no width axis, so under press they change weight only.
- `--ot-measure`: 62ch.

Dynamics: text steps by a fourth, headings by a fifth. Each size has `-lh` (leading) and `-tr` (tracking) companions.

| Token | Size | Leading | Tracking | Use |
|---|---|---|---|---|
| `--ot-pp` | 13px | 1.45 | 0.01em | Labels, captions |
| `--ot-p` | 17px | 1.6 | 0 | Body |
| `--ot-mp` | 22px | 1.45 | −0.005em | Lead, control text |
| `--ot-mf` | 32px | 1.15 | −0.015em | Heading in a section |
| `--ot-f` | 48px | 1.05 | −0.025em | Section heading, dialog question |
| `--ot-ff` | 72px | 0.95 | −0.035em | Page title |
| `--ot-fff` | clamp(64px, 11vw, 160px) | 0.9 | −0.045em | Movement titles |
| `--ot-ffff` | clamp(64px, 17.5vw, 272px) | 0.82 | −0.055em | The overture only |

### Space, line, shape

- `--ot-space-1` … `--ot-space-10`: 4, 8, 12, 18, 27, 40, 60, 90, 135, 200 (perfect fifths).
- `--ot-hairline` 1px, `--ot-stroke` 1.5px, `--ot-dot` 7px, `--ot-gutter` 24px, `--ot-margin` clamp(20px, 5vw, 80px).
- Grid: 12 columns. Columns 1–3 are the margin (names, notes), 4–12 the stave (the work). One column below 860px.
- Separation, nearest to farthest. Every boundary on a page is one of five, and each has its own space. The farther apart two things are in meaning, the more silence between them, and a nearer pair never gets more space than a farther one. Silence does the separating; a line appears only where space can't.

| Boundary | Space | For example |
|---|---|---|
| Within one thing: a label and its value, a figure and its name, a title and its note | `--ot-space-1`–`3` (4–12) | a state's label over it; a stat's name under its figure |
| A rule and the heading hung under it | `--ot-space-5` (27) on a docs page, `--ot-space-6` (40) on the landing page | a section's rule, then its h2 |
| A heading and what it names | one step more than its rule: `--ot-space-6` (40), `--ot-space-7` (60) on the landing page; `--ot-space-3` (12) under a p-size subheading | an h2 and its lead; a table's name and the table |
| One block and the next inside a section | `--ot-space-7` (60) | a lead and its example; two tables |
| One section and the next | `--ot-space-8` (90) on a docs page, `--ot-space-9` (135) on the landing page, all of it before the rule | the end of Usage, then Contract's rule |

- A section begins at one rule, and only one. Its heading hangs just under that rule, or stands on the rule its content opens with (a list of rows, the steps, as SPECTRA's title stands on its line); then the section draws none of its own. A heading never floats between two lines. The first section after a page's head, and the coda at the end of one, begin in silence alone.
- Hairlines part siblings of one kind: rows, steps, the rows of a table. A boundary between two kinds of thing is silence. A line stands beside what it belongs to, not across the gutter from it.
- When space alone can't carry a boundary (a phone, a dense list), the type changes, one thing at a time and in this order: a step of size, then a step of weight, then the colour, where pencil names a thing, graphite is its body and ink is the thing itself. Two blocks of one kind in one section each carry a visible name, a p-size line in ink, above them.
- Indentation says belonging. A nested list steps in by the width of its dash, so its dash hangs under its parent's words. Items in a list take half a paragraph's pause between them, so a long item still reads as one. Whatever hangs (a list's dash, a quotation mark) hangs into empty margin, never against a line; where the margin is too narrow for it, it steps in.
- Shape vocabulary, complete: hairline, dot, ring, arc, cross, corner marks, parentheses, pill (tags only), and arrows only where there's a direction.

### Tempo

| Token | Value | Use |
|---|---|---|
| `--ot-allegro` | 160ms | Hover, press |
| `--ot-moderato` | 320ms | A state changes |
| `--ot-andante` | 640ms | Panels, toasts, dialogs |
| `--ot-adagio` | 1400ms | The overture, once |
| `--ot-exhale` | cubic-bezier(.16, 1, .3, 1) | Arriving |
| `--ot-breath` | cubic-bezier(.65, 0, .35, 1) | Moving between states |
| `--ot-spiccato` | cubic-bezier(.34, 1.5, .5, 1) | Landing: one small rebound (about 8%) for dots, rings, frames |
| `--ot-arpeggio` | 36ms | The step between things that arrive in turn |

Under `prefers-reduced-motion: reduce`, every tempo is 1ms and the arpeggio is 0: things still change but don't travel. Script-driven motion (rolls, the radio's stretch, tag removal, dusk and dawn) checks the same query and applies the change directly.

## Components

Each contract lists anatomy, states and keyboard behaviour. "Yours" marks where the italic expression appears.

### ot-btn (button)
- Underneath: native `<button>`, plus Slot for `asChild`.
- Anatomy: `<button class="ot-btn" data-variant="statement | bracket | quiet | overture | crescendo | stave | ink | space | repeat">` holding `<span class="ot-btn-label" data-text="Label"><span>Label</span></span>` (Button writes the label wrapper; `data-text` is present when the label is plain text). Optional `data-size="l"`.
- One box. Every variant shares the line-height 1.2 and `--py` (0.7em) vertical padding, and centres its label, so the family stands at one height on one baseline: 2.6em, which is also a 44px target at the base size. Bracket's parentheses are drawn outside the flow so the label alone sets the baseline. Focus is the one accent ring (`--ot-stroke`, 4px offset) on every variant.
- Nothing moves its neighbours. The label reserves its widest state: `.ot-btn-label::after` is an invisible copy set at the hover weight and width (`--w-on`, `--s-on`) sharing the label's grid cell, so the button is always as wide as its widest state and the letters swell inside it. Everything else that moves (corners, parentheses, the hairpin, the dot, the staves, the ink) is absolute or transformed. If the label holds elements rather than text, there is no copy and the swell isn't reserved.
- The family. Statement: reversed type in an ink block, one per view. On hover the letters widen (`font-stretch` to 114%, inside the reserved width) and corner marks close in (`ot-corners`), landing with spiccato. Pressed, it drops 1px and the corners clasp. Bracket: `( Label )`; the parentheses step apart on hover and close in on press. Quiet: a hairline underline that retracts and redraws at stroke width. Both lines are transitions, so leaving part-way rewinds from where they are: the stroke goes back to the start and the hairline returns behind it. Pressed, it drops 1px.
- The heroes, for the big call to action; all type-led, and each steps down one size on a phone.
  - Overture: light (200) type that swells to heavy (800) as you come to it; the accent full stop that follows the word (its room is always reserved) lands with spiccato. Pressed, the weight settles at 560. Size `m` is the `mf` step, `l` is `f`.
  - Crescendo: the hairpin that says "grow louder". At rest it is barely open (0.16em), a pencil sign under the word; closed flat, it read as an empty field's line. Pointing opens them across the word and inks them, and the word swells a weight (450 to 600, inside the reserved width). Pressed, the hairpin opens wide in the accent. The hairpin is an image mask, so its lines stay one hairline however far it opens, and it mirrors in right-to-left.
  - Stave: the word in the expression italic (it is a term) between two staves of five hairlines that never cross it. At rest each stave is a short stub beside the word; pointing runs them out to the button's edges (mirrored right to left); pressed, they draw in.
  - Ink: an outlined hairline block. Pointing fills it with ink from the side the pointer came in (`data-edge`, set on pointer enter and leave, so the ink also leaves toward the side you go) and the words reverse to paper. With no pointer (keyboard) the ink comes from the inline start, so it mirrors right to left.
- The measures, for actions that live in a line of their own.
  - Space: after the bottom line of "It has to be design." ("→ Watch this space.") and the Renaissance poster's spread top row. The words, in tracked capitals, spread across the whole line: the button is as wide as its container and the spaces between the words take the room (`.ot-btn-gap`, real spaces, so the name reads as one phrase). Pointing or focusing closes the spaces, the phrase gathers at the line's end, and the silence it leaves becomes a hairline arrow leading to it (`.ot-btn-lead`, which grows as the gaps shrink: `flex-grow` on both). Pressed, the arrowhead steps forward. The arrow mirrors right to left. A label that holds elements rather than text keeps the ordinary label and doesn't spread.
  - Repeat: the word between repeat signs, a thick and a thin bar at each end (one layer of four gradients on `::before`). At rest only the closing sign has its dots (`::after`), which in a score already means "go back to the beginning". Pointing inks the bars and sets the opening dots (`.ot-btn-label::before`), landing with spiccato, so the passage is framed to go round; pressed, they settle. For Try again, Replay, Start over.
- States: rest, hover, focus (accent outline; the heroes and the measures also show their hover on `:focus-visible`), disabled (pencil; the block or outline goes to the rule; no hover), busy (`aria-busy="true"` plus the doing word and `ot-dots`; no hover, progress cursor). Forced colours: the blocks get a `ButtonText` border, and the ink and dots use `Highlight`.
- Keyboard: native button.

### ot-dots (spinner)
- Underneath: native.
- Anatomy: `<span class="ot-dots" data-variant="…" aria-hidden="true"><span class="ot-dots-art" aria-hidden="true"><i></i>…</span></span>`. The default, `dots`, is what a busy button holds, beside its present-tense word ("Saving"). Given a `label`, the root is instead `role="status"` (polite) with the label in a `.ot-sr`. Optional `data-size="l"` stands it alone at the `f` step; otherwise everything is in em and it takes the size of its line.
- Shown only while something the person started is running: the one thing that moves by itself, so every loop is slow and eased like breathing. The art stands on the baseline in a box a capital tall, so it reads as one more glyph; strokes stay hairlines at any size.
- The family, each a way a score or a page writes a wait:
  - dots (default): three periods on the baseline, each lifting as it brightens, in turn.
  - round: three voices on one hairline ring, each entering a beat after the last, as a round's voices do; they gather at the top and the foot and spread between.
  - metronome: a stroke rod on a hairline foot, a dot for its weight, swinging a slow beat.
  - fermata: the hold. The arc draws in the reading direction (mirrored right to left), the dot lands under it with spiccato, the pause is held, then the arc lifts away the way it was drawn.
  - breath: a dot breathes in and opens into a hairline ring, holds, and closes into a dot again.
  - arpeggio: four notes of a chord rising (a third, a third, a fourth), struck in turn with spiccato and let ring.
  - word: the label itself in the voice, pencilled; the ink runs through it letter by letter and leaves in the same order. It is always read.
- Reduced motion: nothing travels. Each stops on a frame that still reads as unfinished (the periods trail off, the voices stand apart, the sign of the hold, a small ring, the chord rising in strength, the first letters inked) and the whole mark dims and returns, 2800ms each way, so it still reads as busy. `data-force="reduced"` pins that in the docs.
- Forced colours: the marks keep the forced colour of the words around them (ButtonText in a button); the word pencils in GrayText.

### ot-check (checkbox)
- Underneath: native checkbox; the tally is a `Fraction`.
- Anatomy: `<label class="ot-check" data-variant="strike | stet | circled"><input type="checkbox"><span>Words</span></label>`; circled adds `<svg class="ot-check-loop" aria-hidden="true">` holding one path. A group is `<fieldset class="ot-checklist">` with a legend.
- Strike (the default), for things done. Hover sketches the strike as a pencil hairline (`--ot-rule-strong`). Checked: an accent strike draws left to right at 60% height, running 0.18em past both ends of the words the way a pen does. Weight drops to 300 and the colour goes to pencil. Unchecking lifts the strike away to the right.
- Stet, for things kept, where a strike would read as "no". The proofreader's "let it stand": a row of dots under the words (a dotted underline, so it wraps with them). Pointing pencils the dots in; checking sets them down in the accent, a touch lower, with spiccato.
- Circled, for things chosen. One pen loop round the words, after the collage's accent rings: it comes in at the upper left, runs round clockwise and on past where it began, as a hand never quite closes a circle. Pointing draws it in pencil, checking inks it in the accent at `--ot-stroke`. A loop has no heading to leave by, so it fades, then resets unseen.
- Stet and circled: checked words are yours, so they turn italic in ink, at the expression scale but on the list's own line (`line-height: 1lh`), so nothing below moves.
- The tally is the `Fraction` item: "*2* / 5 done", the yours part in italic. Each figure that changes turns over on its own wheel, up when the count grows and down when it shrinks, the carry a step behind. It mounts with its first count, so nothing turns over on load. The tally follows controlled values, child changes and native form resets as well as change events.
- States: rest, hover (ink), focus (outline on the words), checked, disabled. Right to left the strike runs right to left and the loop starts at the upper right. Forced colours: the loop is `CanvasText`, `Highlight` when checked; the stet dots take the forced text colour.
- Keyboard: Tab to focus, Space toggles.

### ot-choice (radio-group)
- Underneath: native radios, plus a hook that places the marks.
- Anatomy: `<fieldset class="ot-choice" data-variant="legato | glissando | ballot | sforzando" data-orientation="horizontal | vertical">`, a legend, then `<label><input type="radio"><span class="ot-choice-word">Words</span><span class="ot-choice-yours" aria-hidden="true">Words</span></label>` for each option; the roman names the radio, and the italic copy shares its grid cell. Legato adds `<svg class="ot-choice-slur">` and `<span class="ot-choice-dot">`; ballot adds `<svg class="ot-choice-ballot" aria-hidden="true">` to each label.
- Yours: the chosen word cross-fades into the italic (the roman leaves at allegro, the italic arrives at moderato, so the two are never printed over each other), and the unchosen words step back to pencil. Script adds `data-ready` once the marks are placed, so the first render never moves.
- Legato (default). One accent dot sits under the chosen word (`--ot-choice-drop`, 0.66em below it, so small words keep it as close); in a column it hangs in the margin before the word. Script sets `--ot-choice-x` and `--ot-choice-y`, measured from the slur's own corner so a legend doesn't shift it. Choosing, the dot glides along a slur, a curve that bows away from the words (out into the margin, in a column) and stays shallow however far it goes; it is drawn out along the curve like a drop of ink (longest at mid-flight) and lands round, and a longer glide takes a little longer, never past `--ot-andante`. Pointing at an unchosen word sketches that slur in pencil from the dot to a hairline ring where the dot would land (`label::before`); leaving, the line passes through the way it was drawn, and choosing uses it up as the dot runs along it.
- Glissando. No dot. Script lays the words end to end on one line of reading (`--ot-choice-s` for each word's start), and the italic shows only inside a lens on that line (`--ot-choice-a` to `-b`, with a 0.2em seam). Choosing moves the lens leading edge first, so the italic wipes through every word between, then gathers itself into the chosen word, whichever row the words wrap onto. Then an accent full stop lands with spiccato just after the italic's last letter. Its room is always kept, so nothing moves its neighbours. Pointing sketches the stop as a pencil ring there.
- Ballot. The cross a hand sets in the box after a name on a ballot paper. Every word keeps a margin after it (1.2em, inside the label, so the pointer and focus include it, nothing moves, and the words still line up under the legend), and there the chosen word gets a pen cross in the accent (`.ot-choice-ballot`, one path with `pathLength=1`): two strokes as tall as a capital and never quite square, a short one down to the right and then a longer one, set off higher, that bows and runs past it. The dash runs on from the first stroke into the second, so the pen writes one, lifts and writes the other. Choosing writes the new cross (breath) while the one it leaves passes through, its tail following its head off the page. Pointing sketches the cross in pencil; leaving, the pencil passes through the same way, and choosing inks the sketch where it stands. Right to left, the margin and the cross mirror, so the short stroke still comes first.
- Sforzando. The poster's scale contrast. The words stand in a column, set heavy (780) and narrow (72%) in the voice and packed close at `--ot-mf`; the chosen one's roman steps out and its italic, in the accent, swells to 1.75× from its baseline with spiccato, the sudden accent the mark is named for. It runs up under the word above, which stays on top and reads, the way "has" crosses "It" on the poster. Nothing reflows: the swell is a scale. Focus rings the swell itself. It sets its own column, so `orientation` doesn't apply.
- States: rest, hover, focus (accent outline around the word), chosen, disabled (pencil at 55%). Right to left, the dot hangs on the inline start, the lens runs right to left, the cross mirrors and the swell grows from the right. Forced colours: the dot, the stop, the chosen cross and focus use `Highlight`, the slur, rings and pencil crosses `CanvasText`.
- Keyboard: native radio group (arrow keys move the choice). Under reduced motion the marks move straight to their places, and a cross is simply there.

### ot-dial (dial)
- Underneath: the arc is native radios with no script; the tuner and dynamics are a native range plus a hook; the tumbler is a native number input (`role="spinbutton"`) plus a hook.
- Arc anatomy: `<fieldset class="ot-dial" data-variant="arc" style="--n: 7">`, a legend, then `.ot-dial-face` holding one `<label style="--i: 0…n-1" data-text="N"><input type="radio"><span>N</span></label>` per option, then `.ot-dial-arc`, `.ot-dial-dot`, and an optional `.ot-dial-unit`.
- Arc: options sit on an arc from 170° to 10°. `--sel` is a registered number, set by `:has()` rules (up to 9 options) and transitioned over `--ot-andante` with `--ot-spiccato`, so the dial swings a touch past and settles. Every option derives its distance from it, so the whole dial rolls: the chosen number swells to 2.4× and cross-fades to italic, the others fade from ink toward pencil by distance, and the accent dot travels the inner arc. It works without script. Keyboard: native radio group.
- Tuner anatomy: `<fieldset class="ot-dial" data-variant="tuner">`, a legend, then `.ot-dial-face` (`aria-hidden`) holding `.ot-dial-read` (a `.ot-dial-drum` and an optional `.ot-dial-unit`) and `.ot-dial-scale` (a `.ot-dial-tick` per step, `style="--v: i"` and `data-kind="minor | half | major"`, a major one holding its numeral, then `.ot-dial-index`), then `<input type="range" class="ot-sr">`. The range is the control: it takes focus and keys, carries the value to screen readers (`aria-valuetext` with the unit) and submits the form.
- Tuner: for more numbers than fit in view, a long scale on the rim of a wheel seen edge on. The script keeps one position, `--pos` in steps, and writes it to the face each frame; CSS sets every tick at the angle (v − pos) / `--k` on a radius of `--k` × `--ot-dial-pitch` (15 × 13px, 10px under 520px), so ticks spread under the index and crowd, narrow and fade as the rim turns away. Only the ticks within 34 steps of the index exist; the rest are made as the wheel brings them round. The index is an ink stroke standing through the rim with the accent dot on top, the slider's hand. A numeral inks as it passes the index.
- Yours: the tuner's reading above the scale, a large italic numeral on a drum that turns with the wheel like a counter (`data-a` and `data-b` are the two numbers in view, `--f` how far it has turned between them), with the unit after it in roman.
- Turning the tuner: drag it sideways and the value follows the wheel step by step; a flick coasts and lands on a step with one small swing past; past either end the rim gives a little under the hand and springs back. A tap turns it to the mark under the finger; a tap on a coasting wheel stops it. A sideways swipe always turns it; the plain scroll wheel only once it has focus, and at either end it hands the scroll back to the page (it marks the face `data-lenis-prevent-wheel` while it claims a scroll, so a smooth scroller leaves it alone). While it's held (`data-held` on the root) the reading lifts 5px and settles back with spiccato. Under reduced motion there is no coast, spring or roll: the wheel and the reading step straight to the value.
- States: rest, hover (the arc's number inks), focus (the arc's number, or the tuner's face, in the accent outline), chosen, held (tuner), disabled (45% opacity; `disabled` goes on the fieldset). Tuner keyboard: arrows step, Page Up / Page Down jump a major mark, Home / End go to the ends.
- Dynamics anatomy: `<fieldset class="ot-dial" data-variant="dynamics" style="--u; --chars">`, a legend, then `.ot-dial-face` (`aria-hidden`) holding `.ot-dial-loud` (the numeral and an optional unit) and `.ot-dial-marking` with `data-mark`, then `<input type="range" class="ot-sr">` with `aria-valuetext` such as "60, mezzo forte".
- Dynamics: the score's dynamics as a control. The type scale is already named for them; here the number is set at the size of its loudness. `--u` is how far along the range it is, and `--e = (9^u − 1) / 8` bends it the way loudness is heard, so the numeral grows from `--ot-p` to `--ot-fff` slowly at first and then fast. Under it, in the expression italic and the accent, its marking: niente at nothing (in pencil), then ppp to fff. The face keeps the room of the loudest numeral, so the page never reflows as it swells. Drag up or right to get louder (260px spans the range), scroll once focused, or use the range's keys; the numeral follows the hand while held (`data-held`) and settles with spiccato after a key or a scroll.
- Tumbler anatomy: `<fieldset class="ot-dial" data-variant="tumbler">`, a legend, then `.ot-dial-face` (`dir="ltr"`, `aria-hidden`) holding `.ot-dial-figures` (`style="--at"`, one `.ot-dial-figure` per place with `data-k`, and `data-lead` on a leading zero, then `.ot-dial-cursor`) and an optional unit, then `<input type="number" role="spinbutton" inputmode="none" class="ot-sr">`, described by a hint.
- Tumbler: a whole number set one figure at a time, like the wheels of a combination lock, with the figure you turn held in accent parentheses, as the poster writes 20(25). Whole numbers run from min (at least 0) to max; max decides how many figures there are, and leading zeros stand in pencil. The parentheses slide between figures (`--at`, moderato, spiccato) and open a little while held. A figure that changes rolls in from below or above, the way it turned, units first and each place one arpeggio later. Keyboard: up and down turn the held figure by its place (so up on the tens adds ten, and it carries), left and right move the parentheses, a typed digit sets the figure and steps right, Home and End go to min and max. Pointer: tap a figure to hold it, drag up or down to turn it (a step every 24px); scroll once focused. Figures always read left to right; right to left, only the legend moves.
- Forced colours: the parentheses and the marking use `Highlight`. Reduced motion: the swell, the roll and the parentheses change without travel.

### ot-picks (picks)
- Underneath: native radios, plus a hook that places pizzicato's dot and string and register's crosses.
- Anatomy: `<fieldset class="ot-picks" data-variant="pizzicato | rubric | watermark | register">`, a legend, then `<label><input type="radio">…any content…</label>` per pick, usually `<span class="ot-pick-title">` and `<span class="ot-pick-description">`. A plain-text title is written as `<span aria-hidden data-initial><span class="ot-pick-initial" data-text><span>I</span></span><span class="ot-pick-rest" data-text><span>nitial</span></span></span>` plus the whole name in `.ot-sr`. A name in a script without capitals (its first letter is the same upper and lower case) is marked `data-caseless` and not split: the initial holds a pilcrow and the rest holds the whole name. Pizzicato adds `.ot-picks-string` and `.ot-picks-dot`; register adds `.ot-picks-origin` and two `.ot-picks-cross` (`data-corner="start | end"`).
- For choices that carry their own content, such as a specimen or a swatch. Yours: the chosen title crosses into the italic (a cross-fade of an italic copy in the same cell, so nothing moves), and its description steps up from pencil to graphite.
- Pizzicato (the default): one accent dot hangs in the margin beside the chosen title, level with its x-height. Pointing at another sketches a hairline ring where the dot would land; pressing tightens it. Choosing another slides the dot there (`--ot-picks-y`, moderato, breath) along a hairline string that runs the length of the list; the string is pulled aside as the dot travels, let go on arrival, rings in five shrinking half-swings and fades back to silence (`data-plucked`, a registered `--ot-picks-d`). The title turns italic as the dot lands. Script measures the picks (`--ot-picks-top`, `--ot-picks-len`, `--ot-picks-y`) on choice, resize and font load, and sets `data-placed`; until then the chosen pick's hover ring, filled in the accent, stands in for the dot, so nothing jumps at hydration. A first choice is plucked where it lands.
- Rubric: the chosen title's initial is lifted out of the word and hung in the margin, two lines deep (title and the first description line), in the italic and the accent, the way a rubricator painted a section's one red letter. Every pick keeps the margin (`--ot-space-7`, inside the label so focus and the pointer include the capital), so nothing reflows: the capital grows from its place in the word into the margin (andante, exhale) while a ghost of the small letter narrows to nothing and the rest of the name closes up to the edge and turns italic. Pointing leans the initial italic in place. A pick without a description keeps that second line free. It mirrors in right-to-left. A cased name on a right-to-left page (a Latin name among Arabic) begins at the end away from the margin, so its initial has nowhere to hang: the name stays whole, in its own order (an isolated left-to-right run), and the pilcrow hangs in the margin instead. A pick given `dir="ltr"` is a left-to-right block and hangs its capital in its own margin. A name without capitals, as in Arabic, Hebrew, Devanagari or Han, has no initial to hang, and lifting its first letter out would break a joined word; there the rubricator's other mark, an accent pilcrow (mirrored right to left), grows into the margin instead, and the name stays whole.
- Watermark: the chosen title lies behind the list, huge (`--ot-fff` in the expression italic) and faint (ink at 8%), set against the list's foot and end edge and cropped by them, the way a sheet shows its mould's mark held to the light and the poster's ghost numerals stand behind its words. Each title carries its own mark (`.ot-pick-title::before`, from `data-text`), so choosing another fades one mark down while the next comes up out of the paper (andante, exhale); nothing travels. The title itself crosses into the italic as pizzicato's does. Forced colours drop the mark. A title with rich content has no mark.
- Register: the printer's registration crosses, as the posters mark their corners with a pair of + signs. Two accent crosses stand off the chosen pick's far corners, the top of its start side and the foot of its end side, by `--ot-picks-out`. Script measures them (`--ot-picks-x0`, `-y0`, `-x1`, `-y1`) from `.ot-picks-origin` on choice, resize and font load. Choosing another sends the pair there (moderato, breath), the far one two arpeggio steps behind, each turning a quarter the way the pick went (`--ot-picks-turn`); a cross turned a quarter is the same cross, so it only reads as turning while it moves. Pointing sketches the pair in pencil at that pick. Until it's measured, the chosen pick's own pair stands in, inked. Each pick keeps `--ot-space-5` either side for the crosses.
- States: rest, hover (ink), focus (accent outline around the label), chosen, disabled (pencil at 55%, no hover). Forced colours: the dot, the rubric capital and the register crosses use `Highlight`, the ring, string and pencil crosses `CanvasText`. Reduced motion: every tempo collapses, so the dot and capital arrive without travel.
- Keyboard: native radio group (Tab into the chosen pick, arrow keys move the choice).
- The specimen uses it for the pair and scheme pickers.
### ot-switch (switch)
- Underneath: native checkbox with `role="switch"`.
- Anatomy: `<label class="ot-switch" data-variant="sentence | either | question"><input type="checkbox" role="switch" aria-label="Name"> Sentence is …</label>`. Sentence ends `<span class="ot-switch-state" aria-hidden="true"><span>on</span><span>off</span></span><span class="ot-switch-stop" aria-hidden="true"></span>`; either ends `<span class="ot-switch-either" aria-hidden="true"><span>on</span><span class="ot-switch-or">/</span><span>off</span></span>`; question ends `<span class="ot-switch-ask" aria-hidden="true"><span>.</span><span>?</span></span>`.
- Sentence (the default). Yours: the state word, in italic, rolls vertically between on and off. Off is pencil. The full stop is the state too: `.ot-switch-stop` is a filled dot when on and a hairline ring when off (the calendar's done and to-come). Ink fills it from the rim inward, and drains back out (an inset `box-shadow` over `--ot-andante`; kept under forced colours).
- Either. A printed form's "delete as appropriate": both words stand in the italic, "on / off", and the one that doesn't apply is struck out in graphite and steps back to pencil. Pointing pencils a hairline through the one that holds, since that's the one you'd strike. Switching lifts the old strike off to the right and draws the new one from the left.
- Question. After "It has to be design.", where "the concept of passion?" is answered by "the voice of reason.": off, the sentence asks, in graphite, ending on an italic question mark in pencil. On, the hook is wiped away from the top down to its dot, which stays as the full stop, and the sentence inks. Switching off, the hook grows back up out of the dot. The full stop shares the question mark's grid cell, so the line never moves. Pass the sentence without its last mark.
- States: on, off, hover (sentence: the underline darkens; either: the pencil sketch; question: the mark inks), focus (accent outline round the state; round the whole sentence for question), disabled. Right to left, either's strikes run right to left.
- Keyboard: Space toggles.

### ot-mode-toggle (mode-toggle)
- Underneath: native `<button>` with `aria-pressed` (pressed means Nocturne), except stop, dimmer and noon, which are real switches: `role="switch"` with `aria-checked` for Nocturne. Its name is "Night mode" and never changes; the state says which.
- Anatomy: `<button class="ot-mode" data-variant="eclipse | horizon | words | fermata | sentence | knockout | hour | stop | dimmer | noon" aria-pressed aria-label="Night mode"><span class="ot-mode-art" aria-hidden="true">…</span></button>`. For the switches, `role="switch"` and `aria-checked` replace `aria-pressed`, and `data-scene` names the scene change (`ot-dissolve`, `ot-dim`, `ot-fall`). Sizes are in `em`, so it takes the size of the text around it; the hit area is 0.4em wider than the drawing, and in a bar (`.bar-mode`) at least 44px tall.
- It only reports the choice: `mode` / `defaultMode` / `onModeChange(mode, event)`. The page applies it (`document.documentElement.dataset.mode = mode`). The site's `useTheme()` does, through a view transition: the appearance hook reads the pressed control's `data-scene` and passes it as the transition's type (`startViewTransition({ update, types })`), and the sidecar draws that scene change under `:active-view-transition-type()`, with the body's colour transition off so the new sheet is final at once and the overlay catching no pointer. Without view transitions, or under reduced motion, the scheme swaps instantly; a browser without transition types gets the appearance's circle.
- Each switch is one pair, a toggle and its scene change, answering the press and then resting. After a press the pointing sketch rests (`data-rested`) until the pointer leaves or focus moves on. Both words are always set (stop) or the word never changes width (dimmer, noon's initial cell is as wide as its M), so nothing in a bar moves; all three fit a 320px bar.
- Stop, with dissolve: after the calendar's month set over its year, and the full stop of "Renaissance.". Day over Night, flush to the inline end, and the full stop after the one you read by; the other word steps back to pencil. Pressing sets the stop down one line to Night, or raises it back to Day (moderato, spiccato). Pointing pencils a hairline ring where it would land and lifts the other word to graphite. The page dissolves: the new sheet comes up through the still old one at allegro, so the grey middle is only a glance and the stop lands after the page has turned.
- Dimmer, with dim: a lamp's fader in one word. Night stands in pencil by day and in ink at night. Pressing brings the ink up through the letters in reading order, one arpeggio apart, or lowers it from the last letter; pointing moves the fader one notch (N inks by day, t steps back to pencil at night). The page follows like a light: going to night the day sheet dims (`brightness`) and the night comes up through it; going to day the day sheet arrives dim and its light is raised. Both ways the page passes through the same dimmed day, whose type stays legible. Moderato.
- Noon, with fall: Noon and Moon are one letter apart, so only the initial rolls and "oon" never moves: the N sets below the line and the M comes down from above as night falls, and the N rises back at dawn. The new sheet falls from the top edge, where the switch is, on one straight line (moderato), both ways, so the answer starts at the press and reads down the page.
- Eclipse: a ring and a disc that fills it; by day the whole sun, and at night a mask bites the disc from the upper right and leaves a crescent on the moon's rim (registered `--ot-mode-x`, mirrored in RTL). The disc meets the ring: with a gap between them, day read as a checked radio. Horizon: a hairline; the dot stands above it filled by day and sets below it as a ring at night, landing with spiccato. Words: drawn like a select, since it sits in sentences beside them. The word you read by stands in the italic on a hairline, with ↕ in the pencil where a select has ↓; pointing inks both and nudges the arrow toward the other word. Choosing rolls it the way the sun goes: night comes down from above, day comes up from below, and the hairline narrows or widens to the new word. Fermata: the sign as an eye; the lid arc comes down over the dot at night and closes. Sentence: "Read by light." / "Read by night."; the last word rolls (light in from below, night in from above) and the full stop is a dot or a ring.
- Knockout: after "the uncreative", where part of a word is reversed out of an ink block. It reads "midday": `mid` in heavy roman on the paper, the half you chose in the italic (`.ot-mode-block`). At night the ink falls over the second half from above, the way Nocturne falls over the page, and "night" reverses out of it; at dawn the ink lifts back up. Pointing lets a sliver of ink fall by day, or lifts it a little at night.
- Hour: after the numbers used as data in "the silence that heals". Noon by day and midnight at night: 12:00 and 00:00, the hour yours in the italic and the minutes ours in pencil, in tabular figures and always left to right. A clock only goes forward, so whichever way you choose, the hour turns forward, out at the top and in from below, the units first and the tens one step behind like a carry. It turns only after the mode has changed (`data-turned`), so nothing rolls on first paint.
- States: rest (graphite; stop and dimmer carry the state in ink against pencil), hover (ink, or the switch's sketch), focus (accent outline), disabled. Right to left, stop's words and full stop mirror to the inline end; dimmer and noon keep the English word left to right. Reduced motion (also `data-force="reduced"`) changes at once. Forced colours restate every part in system colours: stop's stop and ring in ButtonText, the word not in use and dimmer's day word in GrayText.
- Keyboard: Space or Enter.
- The site's bar uses dimmer; Tune uses sentence.

### ot-relay (word-relay)
- Underneath: native `<button>`.
- Anatomy: `.ot-relay-frame` holds the native `<button class="ot-relay" data-variant="statement">` and the sibling `.ot-relay-pause` word button beneath it (never a nested button). The sentence button holds `.ot-relay-lead` (the sentence, ours), `.ot-relay-word` (aria-hidden, the word that rolls) and a `.ot-sr` copy of the chosen word, so the button's name is the whole sentence. Person-driven changes are polite live updates; automatic changes keep the live region off.
- sentence (the default): mode-toggle's sentence, for any set of words. The lead is in the roman and graphite; the word is yours, in the expression italic and ink, on a hairline that hugs it. Pressing rolls it on to the next word (out at the top, in from below; back the other way), and the word's box eases from the old width to the new (moderato, breath), so the line follows the word. The last wraps to the first. Autoplay rolls to the next word every `interval` milliseconds (2400 by default, at least 1000); pressing or using the keys resets that reading interval.
- statement: after "It has to be design.", where heavy condensed roman is answered by a large italic that overlaps it, the one accent on the italic word and its full stop. The lead stands heavy (800) and narrow (75%) in ink; the word drops under it half again as large, in the italic and the accent, rising 0.42em into the line above with a halo of the paper round its letters (`--ot-relay-ground`), so it cuts the roman where they cross. Pointing sketches a pencil hairline under it.
- Props: `words` (each with its own punctuation), `index` / `defaultIndex` / `onIndexChange(index)`. Controlled relays request the next index for both person-driven and automatic changes; the owner updates `index`. Disabled or single-word relays do not autoplay.
- States: rest, hover (sentence: ink, and the hairline inks; statement: the pencil hairline), focus (accent outline), disabled.
- Keyboard: Space or Enter goes to the next word; Down and Right to the next, Up and Left to the one before (Left and Right mirrored right to left); Home and End to the first and the last. Reduced motion: the word changes at once. Forced colours: the hairline and the word in CanvasText; the statement separates its two lines so the forced background cannot cover the lead.
- Autoplay (owner-approved exception, 2026-10-01): `autoplay` defaults to true; false keeps only person-driven behaviour and omits the pause control. `defaultPaused` starts it paused. The small roman `( pause )` / `( play )` button sits beneath the item at inline start, with `pauseLabel` / `playLabel` for its visible and accessible words. Explicit pause persists until play. Hover, focus within, an off-screen IntersectionObserver entry and a hidden tab suspend it; the person's scroll, drag, key or press takes over, and leaving interaction gives it 1600ms of rest before resuming. Reduced motion disables autoplay entirely and hides the unused control; `data-force="reduced"` shows that still state in docs. The clock uses rAF time deltas, cancels on unmount and never catches up hidden time.
- Autoplay states: autoplaying, paused (play available), reduced motion (still); the pause button is a separate keyboard stop with visible accent focus and native Enter/Space activation.

### ot-appearance (appearance)
- Underneath: native, through `picks` and `mode-toggle`, plus a hook that reads and writes the four switches on `<html>`.
- Anatomy: `<div class="ot-appearance">` holding `<p class="ot-appearance-answer"><output>…</output> <button class="ot-mode" data-variant="sentence">…</button></p>` and `<div class="ot-appearance-picks">` with three `ot-picks` (pizzicato): Scheme (cotton, blueprint, statue, silence, riso), Key ("its own", its description naming the scheme's own accent, then ultramarine, viridian, ember, violet) and Pair (parma, press, paris, salon, each with its faces as the description).
- The move, after "Healthy habits → for creatives", where the voice runs into the italic on one line of thought: the choice is written back as one sentence over the lists, "Cotton, in ultramarine, set in Archivo and Bodoni.", and the night toggle finishes it, "Read by light." Ours in roman and graphite; yours, the three words you chose, in the italic and ink. The sentence is an `<output>` for the three lists, so a reader hears the new sentence after each choice. No key reads the scheme's own accent by name (cotton ultramarine, blueprint orange, statue gold, silence cobalt, riso magenta).
- Layout: the lists stand two across with the pair under them, or three across once the control is 36rem wide (a container query); the answer steps up from `--ot-mp` to `--ot-mf` there. The picks are set at `--ot-p`, closer than a standalone list. One accent in view: only the list you're in, or were last in (`data-here`, the scheme to begin with), marks its choice with the accent dot; the others set theirs in ink, and their italic titles still say what's chosen.
- It writes only the four switches (`data-mode`, `data-scheme`, `data-key`, `data-pair`; cotton and parma are no attribute) and keeps them together as one JSON object under `0nlytype-theme` in localStorage. `useAppearance()` reads `<html>` through a MutationObserver, so a head script, the page and every control agree. With `value` it holds nothing and writes nothing: `onValueChange(value, from)` reports.
- Motion: the new appearance opens over the old as a circle from the control you touched (a view transition, andante, exhale, so the circle is already wide as the press lands; `--ot-appearance-x`, `--ot-appearance-y` on `<html>`). Under the circle the colours are already new, so the body's own colour fade is off for as long as the transition runs (`:active-view-transition`). Reduced motion, or no view transitions, changes it at once, and there the body's colour fade stays.
- Faces: a pair's fonts load only when the page first asks for them. Pointing at or focusing the pair list fetches every pair's faces (`warmPairs()`), and choosing a pair whose faces have not arrived waits up to 400ms for them before the page turns, so the new page opens already set in its letters. The control shows the choice at once while it waits; a second change made meanwhile builds on it. The page restores the stored choice before first paint with a one-line script in `<head>` (the docs site's `theme-script.tsx`).
- States: those of picks and the mode toggle. Keyboard: Tab through the toggle and the three groups; arrow keys move each choice.
- The site's bar opens it from Tune, in a popover, beside the dimmer toggle.

### ot-ruler (slider)
- Underneath: native range, plus a hook for the readout.
- Anatomy: `.ot-ruler[data-variant="dimension | spread | dynamics"]` holding a label, an `<output>`, `.ot-ruler-hand` (the `<input type="range">`, and for spread `.ot-ruler-letters`) and `.ot-ruler-scale` of `<span style="--n: 0…1">`. Script sets `--p` (0–1). Spread and dynamics need a string label; they keep it in the DOM as `.ot-sr` and draw it `aria-hidden`.
- The track is a ruler: minor ticks every 5%, major every 25%, and the filled part in ink. The thumb is an ink hairline topped by the accent dot (`--h` tall).
- Dimension (the default). Yours: the value, a large italic numeral set in the gap of a dimension line (after Paul Rand), `.ot-ruler-value`. The line runs from zero to the thumb, with a tick at each end, and always stays true to the hand: when the gap is too short for the figure, script sets `data-outside` and the figure stands outside, past the far tick, as a draughtsman sets it.
- Spread. After "Renaissance.", whose words are spread to the edges: the label's letters, in capitals, are the ruler's marks, set out across its whole length over a single baseline (`--h: 64px`). The hand stands through them and inks every letter it has passed, splitting the one it stands in, as "the uncreative" splits its word (`background-clip: text`). Your number, `.ot-ruler-corner`, waits in the far corner; the scale keeps only its two ends.
- Dynamics. The score marks loudness pp to ff in italic under the notes. Here the label, `.ot-ruler-loud`, is as loud as the value: its weight runs 100 to 900 and its width 62% to 125% with the hand (as far as the pair's voice allows), with your number after it; its size is set from its letter count and the ruler's width (a size container), so at its heaviest it still fits one line and nothing reflows while you drag. The scale reads pp p mp mf f ff as `.ot-term`, and the nearest marking inks (`data-on`).
- The value and unit are one text node, isolated left to right; a shorter number never shifts a separate unit node. The ruler and the figure's placement still follow the page direction.
- While the thumb is held (`:active`), the value lifts 5px, and it drops back with spiccato when you let go.
- States: rest, focus (outline 8px out), disabled (45% opacity). Right to left, zero is on the right, the fill, the ink through the letters and the outside figure follow. Forced colours: the ruler restates its tokens in system colours (`CanvasText`, `GrayText`, `Highlight` for the dot).
- Keyboard: arrows step, Page Up / Page Down jump, Home / End go to the ends.

### ot-field (field)
- Underneath: native input and textarea, plus a hook for the counter. The count and filled state follow controlled values, child changes and native form resets as well as input events.
- Anatomy: `.ot-field` holding a `.ot-label`, an optional `.ot-field-count`, then the `input` or `textarea`, then an optional `.ot-field-hint` or `.ot-field-error`. The counter stays at the inline end and reads count / limit, isolated left to right even on an RTL page.
- No box, only a baseline. Focus draws the accent line outward from where the pointer touched it (script sets `--o`, a percentage) or from the left for the keyboard, and shows the counter. The placeholder steps back to half strength on focus.
- Yours: the typed value, in the italic. The placeholder stays in the voice, in pencil.
- Textarea: ruled like paper, with lines every `--lh` (2.25rem) that scroll with the text.
- A search input (`type="search"`) draws no native clear mark, whose blue × belongs to no scheme; Escape clears it.
- States: rest, focus, filled, error (`aria-invalid="true"` turns both lines crimson; the message in `.ot-field-error` is linked with `aria-describedby`), disabled (dotted baseline).
- The error is a callout, after Weingart: a crimson hairline pill hung from the baseline by a leader line, with a dot where it meets the line. A textarea's ruled lines turn crimson too. It arrives in order: the dot lands, the leader drops, then the pill and its words.
- Error copy says what to fix: "Check the address. It needs a domain after the @, like studio.com."
- Variant `overprint` (after "It has to be design."): the label is set in the voice as a heavy condensed word at `--ot-f`, and your italic is printed over its lower half, knocked out of it by a paper outline (`-webkit-text-stroke` in `--ot-paper`, painted under the fill). There's no placeholder; the label is the prompt. Arriving, the word draws in its width (Inhale) and your words and caret take the accent, so the baseline stays a hairline.
- Variant `signature` (the printed form's signature line): a cross (`.ot-field-mark`) stands at the start of the line and the label becomes a caption under it. Your words are set larger, at `--ot-mf`. Arriving, the + turns a quarter to the × of "sign here" and inks; once written (`data-filled`) it stays × in pencil. The caption holds the start under the line, so the error callout hangs from the end.

### ot-form (form)
- Underneath: a native `<form>` with `noValidate`, plus a hook. The browser's own constraint validation decides what's wrong; the form only says it the 0nlyType way.
- Anatomy: `<form class="ot-form">` holding `ot-field`s on a grid and one `FormSubmit`, a statement button.
- On submit it checks every control. Each invalid one gets its Field's error callout (the control's `data-error`, else the browser's message), `aria-invalid` and `aria-describedby`, and focus goes to the first. Typing clears or updates that field's error.
- Sending: `FormSubmit` goes busy and says so (`busy="Sending"`), with the breathing periods. A second submit while one runs is ignored.
- Copy: the button names the action (Send, Save), never Submit. Errors say what to fix.
- Sent: `FormSubmit sent="Sent"` says so once `onSubmit` resolves, until anything is changed, so the action keeps one name: Send, Sending, Sent.
- Variants go on `data-variant`: grid (the default), letter, postmark.
- Letter, after Weingart's letter to AIGA: the form is a letter, our words in roman prose and each field a blank in it that you fill in italic. The prose names each blank, so its label, hint and callout are kept for screen readers only (the control still gets `aria-invalid` and `aria-describedby`). A textarea stays a block, the letter's body. After a failed send, what's still wrong is said once, in a postscript under the letter (`FormPostscript`): "P.S." in ink, then each thing to fix in the signal, each a link that takes focus to its blank. It arrives once and shortens as you fix things.
- Postmark, after the postal hand stamp: once sent, a postmark comes down on the form's end corner, beside the button that sent it and clear of what you wrote (`FormPostmark`, `role="status"`). A double ring set askew, "Sent", the day large as the dot calendar sets it, the month and year, the time. It is ink, so the one accent stays with you. It lands once with spiccato, and lifts off as soon as anything is changed. Right to left it leans the other way; reduced motion, it is simply there; forced colours, `CanvasText` rings on `Canvas`.

### ot-select (select)
- Underneath: native `<select>`.
- Anatomy: `<p class="ot-select">Sort by <span class="ot-select-box"><select>…</select></span></p>`.
- Yours: the chosen option, italic over a hairline. A small ↓ follows it.
- Where `appearance: base-select` is supported, the open list is restyled: the current option has an accent dot beside it, and the hovered option is highlighted. The list drops in 6px and its options arrive in turn (`sibling-index()` × `--ot-arpeggio`, where supported).
- Keyboard: native select.
- Variants go on `data-variant`: underline (the default), compose, ruby. Both drawn variants keep the native select for focus, keyboard and list; its own words are made transparent and a copy is set in the same place for script to move. The hairline moves to the box and stretches between the old word's width and the new one's.
- Compose, after the compositor distributing type back to the case: choosing a new word resets it letter by letter. Letters the two words share slide across to their new places; the rest of the old word falls away in pencil and the new letters drop in, spiccato, as sorts set into the stick. "newest" to "oldest" keeps its *e*, *s* and *t*.
- Ruby, after Japanese ruby and the posters' small notes hung by a large italic: the other choices ride small above the word, ours (roman, pencil) over yours (italic, ink), so every option is in view without opening anything. Clicking one sets it: the two words cross, the picked one down onto the line and the old one up into the ruby, while the others glide aside. The ruby is `aria-hidden`; the select is still the control. Pointing a ruby word draws a hairline under it.
- Drawn variants: reduced motion swaps words at once. Right to left the word keeps its own direction (`dir="auto"`) and the ruby hangs from the right. Forced colours drop the copy and show the select's own text.

### ot-progress (progress)
- Underneath: native `<progress>`, named by a native `<label>` (or `aria-label="Progress"` without one). Leave out `value` (or pass `null`) and it is indeterminate.
- Anatomy: `.ot-progress` (`data-variant`, `data-state="loading|complete|indeterminate"`) holding `.ot-progress-label`, the variant's figure (`aria-hidden`), and `<progress>`. One number, `--ot-progress-p` (0–1, a registered property), is eased at andante, so the fill, the numeral and the ink glide together.
- The label keeps the action's name: "Uploading 12 files", then "Uploaded 12 files". It carries no full stop; every variant ends the same way: when it's done, a full stop lands (spiccato).
- `hairline` (default): a line fills in ink toward a ring, and the percentage, `.ot-progress-value`, is set as a large italic numeral that ticks through every number on its way (a CSS counter on the eased value, rounded down, so it never says 100 early). Done, the ring fills into a full stop.
- `sentence`: the words are the bar. The label is set large and inks in from pencil, in reading order, with a soft wet edge, sliced across lines so a wrapped sentence inks line after line. Yours (italic) inks in with it. Done, a full stop drops onto the baseline. The native bar is visually hidden.
- `count`: for things you can count. A `ot-fraction` (count of total) rolls as each item lands, and `.ot-progress-units` shows one ring per item, like days on the calendar: done is a dot (`data-done`, spiccato pop), the one under way an ink ring (`data-now`), the rest pencil rings. Up to 100 rings; past that each ring stands for a share. Screen readers hear "4 of 8" (`aria-valuetext`).
- `parentheses`: from 20(25). The label stands in the middle of the measure between two thin parentheses (`.ot-progress-paren`, weight 100), and the work still to do is the silence inside them. Two `.ot-progress-rest` spacers share the free space by (1 − p) (`flex-grow`, fed by the eased number), so as the work goes the parentheses close on the words from both ends; done, they hold them and the full stop lands inside. Flex, so right to left mirrors, and the glyphs mirror themselves. The native bar is visually hidden.
- `tally`: how a hand counts. A `ot-fraction` as in count, and `.ot-progress-tally`: one stroke per item in gates of five (`<b>`), four standing and the fifth crossing them, so the count reads in fives at a glance. To come, a stroke is a pencil hairline; as its item lands, ink draws down it (the fifth, across it); the next one waits in ink (`data-now`). Done, a dot lands after the last gate. Up to 100 strokes. Screen readers hear "7 of 12".
- Indeterminate: the number stands back and a stroke reads along, only while it runs: a segment passes along the line, a band of ink passes through the words, the rings and the strokes ink in turn, and the parentheses listen, drawing a little way in and back. Reduced motion: no pass, a still rule, the parentheses at the ends. Right to left: the line fills and the words ink from the right; the gates mirror.

### ot-timer (timer)
- Underneath: native buttons plus a hook.
- Anatomy: `<div class="ot-timer" role="group" aria-label="Writing timer" data-variant="ring | horizon" data-state="idle | running | paused | done">` holding `.ot-timer-face` (`aria-hidden`, one `ot-ring` from radial-chart with its dot at the arc's start), `.ot-timer-read` (`.ot-timer-time` with `role="timer"`, holding the aria-hidden `.ot-timer-figures` and the time in words in a `.ot-sr`; then `.ot-timer-words`: `.ot-timer-label` and `.ot-timer-note`), `.ot-timer-actions` (two bracket `ot-btn`s) and a polite live region (`.ot-sr`).
- SPECTRA's huge figures against tiny print, inside the calendar's ring. The time is set in tabular figures at weight 200, as large as the ring allows (fewer figures set larger, by `--ot-timer-chars`): mm:ss, or h:mm:ss from an hour. Under it the label and one line of small print in pencil: the length when ready, "Ends 14:35" while it runs, Paused, Done.
- ring (the default): the ring is the time left. It starts full with the accent dot at the top; as the time goes the dot runs clockwise like a clock's hand and the arc behind it empties, so what is left always runs from the dot on round to the top.
- horizon: the Eclipse. A half ring stands on a horizon; the dot crosses it from the start of the line to its end like the sun, and what's left of the arc is the day still to go. The time stands on the line, its words under it. Right to left, the sun crosses the other way.
- It counts only because the person pressed Start. It follows the wall clock (a deadline, checked four times a second and again on coming back to the tab), so a hidden tab never falls behind. The arc is drawn from the clock every frame; the figures change once a second, each changed figure turning over downward like a counter's wheel (`roll`), the units first and the carry one arpeggio behind. Paused, the time steps back to pencil. Done, the ring is empty, the dot stands at the top and a full stop lands after 00:00 (spiccato); `onComplete` is called once.
- The presses: Start, then Pause and Resume in the same place, and Start again when done; Reset (disabled when ready) sweeps the ring back to full at andante. The two stand either side of the centre line, so a changed name never moves the other.
- Screen readers hear it politely and never every second: on each press ("Started, 25 minutes left."), every five minutes, each of the last five, at thirty seconds, and "Time is up." The time can be read on demand from the timer role. Keyboard: native buttons. Reduced motion: the arc steps once a second and the figures change without turning.
- `defaultElapsed` opens a session picked up again, paused. `data-force="running | paused | done"` pins a state for the docs without counting.

### ot-toast (toast)
- Underneath: hook: a tiny store and a `<Toaster />`.
- Anatomy: `.ot-toaster` (`aria-live="polite"`, fixed bottom left), holding `.ot-toast` elements. Each is a sentence, `svg.ot-toast-timer` (a fermata: arc `pathLength="1"` plus an accent dot) hung up against its full stop, the way the sign is written over the note it holds, and an optional bracket action.
- The fermata's arc empties over `--life`. Pointing at the toast or focusing it holds the pause, which is literally what a fermata means. At most three toasts show at once. The toast rises, then its sentence is written in from the left. It leaves with `data-leaving`: it sinks and fades, then its height closes so the toasts above settle down into the space.
- Yours: the item's name inside the sentence, e.g. "Archived *Spring notes*."
- `variant` sits on the Toaster (`data-variant`); each keeps the fermata as its clock, unseen, and pointing still holds the stay. `footnote`: the book's note at the foot of the page. A short ink rule draws in over the first note, and each note carries its number (`.ot-toast-n`) hung in the margin so the sentences keep one edge under the rule. Numbers count up while notes stand and start again at 1 on an empty page; only the newest takes the accent, the rest are pencil. One frame holds the whole foot, not one per note. `dateline`: the frame row of a poster, each toast in its frame holding a sentence, a hairline and the time it happened (`time.ot-toast-time`, the reader's own clock). The hairline (`.ot-toast-rule`) runs out toward the time while the toast stays. Right to left, the rule runs out the other way and the sentence writes in from the right. When a page mounts a second `<Toaster />`, the one mounted last shows the toasts and the others fall silent, so nothing is read out twice.

### ot-dialog (dialog)
- Underneath: native `<dialog>` with `showModal()`, plus a hook.
- Anatomy: `<dialog class="ot-dialog" closedby="any">` holding `<form method="dialog">`, the `.ot-dialog-title` question, `.ot-dialog-body`, then `.ot-dialog-actions` with a bracket (safe, `autofocus`) and a statement (the action).
- It's set like a poster: corner marks instead of a box (`ot-corners`), an `ot-meta` row of facts along the top (`.ot-dialog-meta`), and the question set large, with the item as yours ("Delete *Spring notes*?"). The backdrop is paper at 86% with a blur. Opening is one short phrase: the corners open out into place, the meta rule draws from the left, and the question breathes out from weight 500 and width 88%.
- Keyboard: focus goes to the safe answer; Escape closes; a click outside closes. Smooth scrolling pauses while it's open.
- `variant` on DialogContent. `reply` (after "It has to be design."): the question is ours, heavy (800) and narrow (width 72%); the answers are yours, bare `DialogClose` buttons set large in the italic. The answer you point at, or that holds focus, inks and takes a full stop in the accent (`content: "." / ""`, so it isn't read out); pointing at one takes the stop from the other, so only one is ever in view. Opening focuses the safe answer, so it opens with its stop. `ruled` (after "Less is more."): a grid of ink hairlines to the dialog's edges. The meta's two facts go to the top corners; the question is set at `--ot-ff` in the left cell, each of its lines standing on a hairline that draws across from the start as it opens; the detail sits ragged on the far side, set to the end; the answers take the cells below, the safe one at the start, the action at the far end. Below 40rem the grid folds to one column.
- Alert dialog: for what can't be undone, `role="alertdialog" closedby="closerequest"` with `aria-describedby` on the body. It closes only with Escape or an answer, never a stray click. Any dialog can carry a form (the specimen's rename); `[data-close]` buttons close it without submitting.

### ot-empty (empty)
- Underneath: native.
- Anatomy: `.ot-empty` (`data-variant="arc | tacet | blank"`) holding an optional `.ot-empty-figure` (aria-hidden, its text in a `<span>`), then `.ot-empty-title`, one sentence of direction, and one action.
- An invitation to act, not a mood. Every variant answers the person reaching for the action (pointing at or focusing it; `data-force="hover"` on the button pins it for the docs).
- `arc` (default): the zero is thin, wide and cropped to its top half, so "nothing" reads as the fermata's arc. Reaching for the action raises the arc a little.
- `tacet`: what a score prints on a part with nothing to play, "it is silent". The figure is the term (pass `Tacet`), set in the expression italic, as musical terms are, at the movement-title size. Reaching for the action is your entry, so the word dies away (morendo): it fades to the rule and its letters loosen a little.
- `blank`: the printer's page left blank on purpose. The words spread to the corners, as the posters' labels do: what is missing at the top start, what to do at the top end in a narrow ragged column, the action at the foot's end. The middle is silence with one small pencil line in it (the figure: "This space is left blank on purpose."). Reaching for the action, that line pales and loosens: it makes room. The region is at least `min(34rem, 80vh)` tall; right to left, the corners mirror.

### ot-tabs (tabs)
- Underneath: Radix Tabs.
- Anatomy: `<div class="ot-tabs-root" data-variant="line | rubato | open">` (Radix Root) holding `<div class="ot-tabs" role="tablist">`, then `<button role="tab" aria-selected>` for each tab, with an optional count in `<sup>`, then `<span class="ot-tabs-line">`; then the panels.
- line (the default): the ink line follows the selected tab through `--x` (left), `--r` (right inset) and `--y`, like an inchworm: script sets `data-dir="left | right"`, and the leading edge moves first while the trailing edge follows 110ms later.
- Optional `.ot-tabs-count` (aria-hidden) sets the number showing huge and thin, cropped by the rule it sinks into. It rolls when the number changes (up when it grows, down when it shrinks), and hides below 700px.
- rubato: "robbed time", the performer's give and take inside a bar that keeps its length. No line: the chosen word is the mark. It widens and thickens (font-stretch 75% to 125%, weight 300 to 600, andante, breath) while the others condense and lighten to give it the room, and the words are spread to both ends of a bar held to 26 `mp` ems, so the bar keeps its length while they give and take. Pointing leans a word a little wider (90%, 350) in pencil. Voices without a width axis change weight only.
- open: the words stacked large (`mf`, 300; `mp` below 40rem) like a headline beside the panel, with one hairline standing between the two columns ("Less is more."). The hairline breaks beside the chosen word, so the word opens onto its panel: the choice is marked by a missing line. The hairline overhangs the stack by space-4 at both ends, so the first or last word breaks it too. The break moves as the line does, leading edge first (`data-dir="up | down"`, the trailing segment 110ms behind), from `--t` and `--b`, the chosen tab's insets. It sets `orientation="vertical"` unless you pass one. Forced colours draw the lines in CanvasText.
- Keyboard: roving tabindex. Left and Right arrows (Up and Down in open) move and select, Home / End go to the ends. Radix writes `dir` on the root, so without a `dir` the tabs take the direction of the page around them as they mount: on a right-to-left page the words run from the right and Left and Right swap. It reads the page's direction once, at mount, as the menus do: a page that changes `dir` afterwards passes `dir` itself, or remounts the tabs.

### ot-rows (rows)
- Underneath: native list.
- Anatomy: `<ul class="ot-rows" data-variant="ditto | trail">` with `<li><a class="ot-rows-link">`, holding `.ot-rows-title`, `.ot-rows-kind`, `.ot-rows-meta`, and the → drawn after them (empty alt text).
- reverse (the default, no attribute). On hover or focus, the row reverses: an ink block rolls on and the text turns to paper. The title steps 8px forward and the arrow comes in. Script sets `data-edge="top | bottom"` on pointer enter and leave, so the ink comes in from the side your hand entered and leaves toward the side it goes. Moving down the list, one block of ink seems to travel with you.
- ditto: the ledger's and the typed list's ditto mark. A kind or a meta (a year) that repeats the row above is set as a ditto mark (″, pencil, centred over the word it stands for), so only what changes is written out and the marks make a rhythm down the columns, the barcode rhythm of SPECTRA. Rows works the repeats out after every render (`data-ditto` on the cell) and the words stay in the page, so a screen reader hears every row in full. Pointing at or focusing a row spells its dittos back into words (allegro); no ink block, the title steps and the arrow comes in. Sort the rows so the repeats fall together.
- trail: after "28 December", the index keeps count of where you've been. A ring hangs in the margin before each row (space-3, stepping in below 40rem): a hairline ring in rule-strong for a row not yet opened, filled with ink once the browser has visited the link (`:visited`, which only allows colours, so the ring's paper fill is opaque and nothing is stored), the accent for the row with `aria-current` (where you are, the one accent). Pointing inks the ring's line and it grows a quarter with spiccato. No ink block. Forced colours draw it in CanvasText, VisitedText and Highlight.
- Narrow (below 40rem) the title takes its own line and the kind and meta sit under it, a space-1 below, so a long title never runs into its kind.
- Keyboard: Tab through the links; focus shows what pointing shows.

### ot-pager (pagination)
- Underneath: native links. The current page is a link with `aria-current="page"`; a step with nowhere to go is a `<span aria-disabled="true">`, in rule-strong.
- Anatomy: `<nav aria-label="Pages">` holding `<ul class="ot-pager" data-variant="numbers | folio | neighbours | barcode | thumb">` of `<li>`, each a page link (two-digit numbers), a step (`.ot-pager-step`, the arrow drawn in CSS with empty alt text), or a gap (`.ot-pager-gap`, read as "More pages").
- numbers (the default): a 3px dot sits under each number; the current page's dot is 6px and in the accent, and it lands with spiccato. Pointing at another page draws a hairline ring there.
- Weight falls with distance (600, then 350 for the neighbours, then 200), after the WOVE poster. Colour never drops below pencil, so contrast holds at AA.
- Long runs: `paginationRange(current, total, siblings = 1)` gives the ends, the current page and its siblings, and a gap for each run left out, always in the same number of slots (siblings * 2 + 5). A gap has the same outer width as a two-digit page link, two figures plus 7px padding on each side, and never stands for a single page, so paging moves nothing beside the pager.
- Below 40rem the numbers drop a size to `p`, use a space-1 gap between the padded targets, and the steps keep only their arrows (their words stay for screen readers), so a long run holds one line on a phone. Number links and steps keep a minimum 24px target width.
- folio: the current page over the total, as a book sets its folio. The number stands in ink at 600 on its accent dot; a leaning hairline that thins at both ends (the fraction's pen stroke); then the total small, upright and a little wide, in graphite. The total is plain, aria-hidden text; the current page's name carries it ("Page 7 of 24"). The steps are arrows alone. It mirrors in RTL, stroke and all.
- neighbours: the pages either side, by name, at the two ends of the line: a small word ("Previous", "Next", at `pp` 500 in graphite) over the name at `mf` 300 in ink, hung on a hairline arrow as the notes are in "It has to be design." (the arrow input group's drawn shaft and open head, `space-6` long, pointing the way the step goes and mirrored in RTL). There's no current page in view, so no accent. Pointing thickens the name to 450 at moderato, as nearness does in the numbers, inks the word and the arrow, and steps the arrow `space-1` its way. A step with nowhere to go is left out.
- barcode: every page a hairline, SPECTRA's barcode read the way the dot calendar reads its days: the pages behind you in ink, the pages ahead in pencil, yours a 3px line in the accent, 26px tall to the others' 16, with its number set small (`pp` 600, ink) above it. The other numbers are there, transparent, for their names ("Page 9 of 24"); pointing at or focusing a line lifts it to 22px in graphite and shows its number in place of yours, so one number is ever in view. Each hairline is centred in a non-shrinking 24px-wide target, so the pitch is 24px; the steps are arrows alone. When the run is wider than the nav, it scrolls sideways inside it with horizontal overscroll contained, even without a site wrapper. The current page is revealed on mount, page changes and nav resizes by scrolling only the nav horizontally, never moving the page vertically. The run and arrows mirror in RTL. Every page is a link, so Tab walks the run; it suits runs up to about 40.
- thumb: a dictionary's thumb index set the way "the uncreative" sets its word: the alphabet as one heavy (700), tight word at `mf`, the current letter reversed out of an accent block in paper. Letters with nothing under them stay in the word, thin (200) and pencil, as an aria-hidden item that isn't a link. Pointing sketches the block in rule; choosing inks it in the accent. Each letter is at least 24px wide; below 40rem the word breaks in two rows of 13, so every letter stays a wide enough target.
- Forced colours: the dots and lines are drawn in CanvasText and GrayText, the current one in Highlight; the thumb's block is Highlight with HighlightText.
- Keyboard: Tab through the links; Enter follows. Pagers that turn in place (the example) keep focus in the pager when a step runs out, on the current page.

### ot-crumbs (breadcrumb)
- Underneath: native list.
- Anatomy: `<nav class="ot-crumbs" aria-label="Breadcrumb"><ol>…</ol></nav>`. The dividers are drawn hairlines, leaning 24° like slashes. Pointing at a step darkens the hairlines on either side and leans them in (14° and −14°), so they hold it like a pair of brackets. Each hairline runs the whole line, descender to cap, so it reads as drawn, not typed. The current item is yours: the italic, in ink, with `aria-current="page"`.
- `variant` on the nav (`data-variant`): `slashes` (the default), `stack` or `elide`.
- stack: "It / has / to be / design." One step a line, each set 1.2em further in, the way here in a heavy narrow roman (700, width 75%) and where you are the large italic at the foot (`f` at the expression scale). No hairlines: the stair divides it. Pointing at a step, or focusing it, sets every step below it back in pencil: what you would leave.
- elide: for a long path. The first step and the last two stay; each step between is elided to a full stop in pencil, so the ellipsis counts what it holds, and the hairlines between them close. For a still pointer (a 240ms wait) or at once for focus, each stop opens back into its word, in turn. Every step stays a link in the page, so a screen reader hears the whole path and Tab reaches each one; the stops are drawn (`content: "." / ""`) and never read.
- Keyboard: Tab through the links. Right to left, the leans mirror and a stack steps in from the right.

### ot-disclose (accordion)
- Underneath: native `<details>`.
- Anatomy: `<div class="ot-accordion" data-variant="cross | run-in | gloss" data-orientation="horizontal">` holding `<details class="ot-disclose"><summary>Question</summary><div class="ot-disclose-body">…</div></details>` for each question.
- cross (the default): questions ruled off. The + winds 45° into × with spiccato, and the question exhales as it opens: it swells a fifth, from `mp` to `mf`, and goes wide and light (width 112%, weight 300), so the open question becomes the heading of its answer, as the big words of "Less is more." stand over their note. The + keeps its size. The content opens by animating block-size (`::details-content`) over `--ot-andante`, and the answer settles into the space.
- run-in: the book's run-in head. No rules; the questions are paragraphs held apart by space. Each question is set heavy (600) and floats at the start of its own line; closed, a pencil ellipsis trails after it (pointing inks it). Open, the ellipsis goes and the answer runs on from the question on the same line, light (300) in graphite, as one paragraph; it is written in line by line from the question, a steep soft-edged wipe that steps down a line as it crosses one (mirrored right to left). Held to the measure; `p` size below 40rem. Forced colours drop the wipe.
- gloss: the answer is hung beside its question in the outer column (3 : 2), flush to the outer edge and ragged toward the question, the way a sidenote glosses the line it stands by (the notes of "Less is more." and "the silence that heals"). Space holds the columns apart; no rule stands between. The question keeps its size and exhales only in width and weight. Open, the gloss arrives from the question's side (mirrored right to left). Below 40rem it drops under the question, indented a quarter.
- horizontal (`orientation="horizontal"`, `data-orientation`): after "Healthy habits", its notes stacked a word to a line in narrow ragged columns, and the hairline grid of "Less is more.". The questions stand side by side as columns of `space-9` between hairlines, each name stacked a word to a line; the open one widens (flex-grow over `--ot-andante`, exhale) and its name steps up from the stack onto one line as it exhales into the heading of its answer (`mf`, wide and light); the answer arrives once the column has made room. Closed columns keep their width, so the row ends in silence. It has its own form, so `data-variant` is not set and the + is set aside: the column says it opens. Below 40rem the columns stack under hairlines and the + returns.
- Keyboard: native (Enter or Space on the summary). Single opens one at a time through the native `name` attribute. Horizontal: Left and Right walk the columns (mirrored right to left), Home and End go to the ends.

### ot-month (calendar)
- Underneath: hook (a grid with a roving tab stop).
- From the "28 December" poster: a huge numeral, the month over the year beside it and the weekday at the far side, then a grid of large discs, one per day. The grid of discs is the picture: time spent and time left, at a glance.
- Anatomy: `.ot-month[data-variant="dots | ruler | ghost | parenthesis"]` holding `.ot-month-head` (`.ot-month-at` with the numeral `.ot-month-date` and `.ot-month-dayname`, the `.ot-month-title` month in caps over the year, `.ot-month-nav` with two hairline chevrons), then `.ot-month-grid` with 7 `<abbr>` weekday heads and weeks of `<button role="gridcell" class="ot-month-day" data-when="past | today | future" aria-selected>` each holding `.ot-month-disc` > `.ot-month-n`, today with `aria-current="date"`, then `.ot-month-foot`. Before the 1st there is only paper (`.ot-month-gap`); after the last day, nothing: the neighbouring months never show.
- dots (default): gone is a solid ink disc, today the one accent disc, to come a hairline ring (`--ot-rule-strong`). The number is reversed out of the ink it sits on, like "the uncreative": paper on ink (over 15:1 in day and nocturne), paper on the accent (the accent clears 4.5:1 on paper in every scheme and key, so paper on it does too), and pencil inside a ring so the days to come stay back. `--f` is how full of ink a disc is, from the bottom.
- dots, the wait: the days between today and the chosen day are half-moons (`data-between`), after the eclipse poster: ink under a horizon, the number in the open sky above it, no ring. As in the poster, the disc is narrower than its horizon: the moon is about half its day's width, and the horizon is one `--ot-rule-strong` hairline that runs on through the gaps from today to yours, so the wait reads as one span and stays lighter than the days gone. Once you choose (or turn the month), they wax in turn toward your day (`--k` × `--ot-arpeggio`).
- dots, yours: the chosen day is circled, like a date on a paper calendar: an ink ring at stroke width outside its disc, its number in the italic, larger. It adds no second accent; chosen today, the accent disc is circled. Pointing sketches the same ring in pencil, drawn round from the top (`--sweep`, a conic mask); choosing inks it and it lands with spiccato.
- ruler: the month as one measured line, after Paul Rand's dimension lines and SPECTRA's huge type against tiny data. A tick a day (`.ot-month-disc` restyled) on a baseline that is ink as far as today; the weeks' first days and the 1st stand taller and carry their number (every day is numbered once the line is 40rem long; a label gives way to a neighbouring today or yours). Today is the accent tick with a dot at its head, yours a full ink tick with a ring at its head and its number in italic. The numeral stands over its tick, clamped inside the line, with the weekday beside it on the side facing the middle. Under the line, `.ot-month-span` measures the wait as a dimension from today to your day with the count under its middle, open at an end that runs off the month. The rows become `display: contents`, so the grid is one row of `--days` columns; the weekday heads stay for screen readers only.
- ghost: after "the silence that heals", numbers as data against huge ghost numerals. The days are figures only, no discs: gone in pencil, to come in ink, today the accent figure (700), yours in the italic. Behind them `.ot-month-at` becomes the ghost: the chosen day (else today) stands over its month's number (`.ot-month-mo`, "24" over "09"), light (200), at 58cqi of the month's own width so it holds at popover size, in half the rule's tone, cropped by the month's end and foot edges (`overflow: clip`, `container-type: inline-size`). The grid is read through it. It turns italic with yours, at four fifths of the size. The head is the month over the year with the chevrons at the far side; the weekday name is left to the column heads. Pointing sketches a pencil hairline under the figure, drawn out from its middle. Forced colours drop the ghost; the italic still marks yours.
- parenthesis: after "20(25)", the typographic parenthetical. The month is set as one running line of figures at `mp` that wraps like a sentence (the rows become `display: contents`; the weekday heads stay for screen readers only), a wider space (0.6em) closing each week. The time from today to your day, whichever comes first, is an parenthesis: `data-paren="open"` hangs a "(" before the first of the two and `data-paren="close"` a ")" after the other, both light (200) and a little taller than the figures, hung in the space between figures (absolutely placed, like hanging punctuation) so nothing reflows. The figures inside are set heavier (650). An aside that began last month only closes here. Gone is pencil, to come is ink, today the accent, yours the italic. Pointing sketches pencil parentheses round a figure; choosing inks the aside and its parentheses land with spiccato. Right to left, the parentheses mirror with the text (bidi mirroring).
- Focus in ghost and parenthesis is a ring, not a box: the day is rounded (`border-radius: 50%`) so the outline draws an ellipse round the figure; parenthesis draws it with no offset.
- ruler, the hand: the ticks are narrow, so pressing and dragging along the line sketches the day under the pointer in pencil, and letting go chooses it (`data-scrub`, pointer capture, `touch-action: pan-y`). A key's click still chooses.
- Yours, in every variant: the big numeral turns to the chosen day in the italic, and the weekday follows it. dots and parenthesis roll it; ruler glides it along the line; ghost sets a new ghost that surfaces.
- The foot: one tracked line in caps that says something true: "12 days to go", "Tomorrow", "Today is the day", "The last day of September", "9 days left in September". English only; `caption` replaces it or, as null, removes it.
- Turning the month, the days sweep in, in reading order, from the side you turned toward (`data-turn="next | prev"` on the grid, `--d` = the cell's place), mirrored right to left.
- States: rest, gone / today / the wait / yours / to come, chosen today, hover, focus (on the day that holds the tab stop), disabled days, and for ruler the wait run on from another month; ghost with a chosen day, with none (today behind) and pointed; parenthesis enclosing the wait, run on from another month, and pointed. The keyboard is the same in every variant, the running line included.
- Keyboard: roving tabindex; arrow keys move by a day (following the direction) or a week, Page Up and Page Down by month, Home and End to the ends of the week; Enter or Space chooses. Each day is named in full: "Wednesday 30 September 2026, today".

### ot-tag (badge)
- Underneath: native.
- Anatomy: `<span class="ot-tag" data-variant="ink | accent">`, or a removable `<button class="ot-tag" data-removable aria-label="Remove X">`.
- The label sits in a `<span>`. Pointing at or focusing a removable tag strikes the word, as the checkbox does.
- The one rounded shape. A removed tag, already struck, closes up (its width goes to 0) while its neighbours slide into the space, and focus moves to the next.
- The word is set as Weingart set his callouts: small, a little heavy and narrow (500, width 92%, in ink), so it holds as type inside its hairline; the ink pill knocks it out heavier and narrower still (650, 88%). Forced colours draw the pill as a CanvasText outline and the strike as a line-through.
- series: the written list. No pill: sibling tags are one sentence ("Showing work in *Identity*, *Web* and *Motion*."), the tags in the expression italic because they are yours, the commas and the "and" ours, in the voice and graphite. The punctuation is worked out in CSS from each tag's place among its siblings (`:nth-last-child(… of …)`), and a leaving tag stops counting at once, so as a tag closes up the list re-sets itself around the gap ("Identity and Motion"). `--and` on the tags changes the conjunction. Removable series tags keep the strike and the close-up.
- seal: a coin. `legend` is set round the rim between two hairline rings (SVG `textPath`, `textLength` spread to the whole circle so the letters stand evenly, closing on a dot), the face in the middle at `mf` 250. It's space-8 across and named as an image ("01, First edition · 2026"). Pointing turns the legend 30° (andante, breath), as a coin turns in the fingers; it turns back when you leave.

### ot-note (note)
- Underneath: native, on hover and focus.
- Anatomy: `<button class="ot-note" aria-describedby="id">Term<span class="ot-note-text" id="id" aria-hidden="true">Note</span></button>`.
- A dotted underline. On hover or focus, the highlighter marks the term, a dot anchors the leader line, the line draws down, and the ink pill holding the note spreads from the line's tip (`clip-path: circle()`). Leaving plays the same four steps in reverse order.
- Keyboard: focus shows it, and Escape dismisses it.
- `variant` (`data-variant`, none for leader): `leader`, `ossia`, `expand` or `revise`.
- ossia: the score's ossia, a small bar printed over the staff, and the interlinear gloss. The note is always there: a few words at `pp` in pencil in the line space above the term, starting where the term starts and free to run past its end. The term's line opens to hold it (the term is an inline block with the note's height above it), and the term is in ink so the two read as a pair. Pointing inks the note. It is plain text in the page, read as "term (note)" (the parentheses are for screen readers only). Nothing to focus.
- expand: an abbreviation that opens into its words. The term's letters are found in the note in order (the start of a word, or a capital inside one: *H*yper*T*ext), and pressing it moves them apart while each word grows out of its initial (inline size to auto, moderato, exhale); a word with no initial ("and") grows whole. The initials stay in ink and the rest arrives in graphite, so the abbreviation stays readable inside its long form; the dotted line goes. It is a span with `role="button"`, `aria-expanded` and `dir="auto"`, because a native button can't break across lines and the words must; the visible letters are aria-hidden, the name is the abbreviation and the description the note. Enter or Space toggles, Escape closes. If the letters can't be found, it falls back to leader.
- revise: the editor's correction, after the Basquiat sheet's struck headline and the typed corrections of the Weingart letter (a caret swap, done by hand). `children` is the word in the text and `note` the word that replaces it (a word or a short phrase; it doesn't break). At rest the word is dotted like the others. Pointing sketches a hairline strike in pencil, as the checkbox does. Pressing strikes it in ink at `--ot-stroke`, the pen running a little past the word (0.1em, short of the word before), and the struck word steps back to pencil; then the replacement is written in after it in the italic, its box opening from the start (inline size to auto, moderato, exhale) so the sentence makes room as a pen moves. Pressing again, or Escape, lifts both. It is a span with `role="button"` and `aria-expanded`, so a struck phrase can wrap; the drawn words are aria-hidden and a `.ot-sr` reads the term, or once pressed `<del>` the term and `<ins>` the replacement. The space before the replacement is a real one, so where it wraps the space falls away at the break. Right to left the strike draws from the right. Forced colours: a plain line-through.

### ot-toggle (toggle)
- Underneath: Radix Toggle.
- Anatomy: `<button class="ot-toggle" data-variant="fermata | tenuto | aside | guides" type="button" aria-pressed="false">` holding `<span class="ot-toggle-label" data-text="Word"><span>Word</span></span>` (aside adds an `aria-hidden` `<small class="ot-toggle-note">` after the word). The label shares its grid cell with an italic copy of itself (`::after`, from `data-text`, hidden from screen readers), so the button is always as wide as its wider state and nothing beside it moves. A label that holds elements has no copy and turns italic in place.
- Held, the word is yours, so it turns italic. The marks are the button's own `::before` and `::after`, drawn from two registered numbers (`--ot-toggle-draw` for the pencil sketch, `--ot-toggle-ink` for the tenuto's pen), so the whole move is a transition. Every stroke passes through: it draws from the start and leaves toward the end, mirrored right to left.
- One box: both variants keep room for the arc above (0.8em) and the line below (`--y`, 0.3em), so a fermata and a tenuto side by side stand on one baseline, and the word stands at the start of its box, in line with its label.
- fermata (default): the sign for a note held longer than written. Pointing sketches the arc over the word in pencil from its start foot. Held, the arc inks at stroke width, the dot lands under it with spiccato, and the word leans into the italic: the roman shears forward as it fades, and the italic arrives upright and settles into its slant. Pressed, the sign comes down toward the word.
- The roman and its italic copy start at one edge but aren't one width, so script reads both (`--ot-toggle-r`, `--ot-toggle-i`) and fermata, aside and guides centre or end their marks on the face you see (`--w`); a mark centred on the button sat a few px off the word. Fonts arriving and resizes put the marks straight there (`data-still`); only a press moves them.
- tenuto: the line under a note held its full value. Pointing sketches it under the word in pencil. Held, a pen (a dot, seen only while it moves) runs along the line from the start, inking it, and behind the pen the word is rewritten in the italic. Released, the pen passes again: the ink leaves ahead of it and the roman comes back behind it. The line, the pen and both masks read one number, so they never part.
- aside: after "It has to be design.", whose tiny notes hang on hairline arrows beside the words. Pointing sketches a hairline beside the word in pencil. Held, it inks, an arrowhead lands on its end against the word, and a small note in our voice (`note`, "on" by default) is written at its tail on the word's baseline. The note and arrow take no room, so nothing beside the word moves; the arrow points back at the word, mirrored right to left.
- guides: after Paul Rand's "design", whose letters stand on a dotted construction grid. Pointing sketches the word's baseline in dots from the start. Held, the x-height line is drawn in dots from the end, the two pass through each other across the word, and it leans into the italic between them: the word shown standing on the lines it is set on.
- States: rest, hover (the pencil sketch), focus (the accent outline), held, disabled (pencil at 55%; nothing sketches), each for all four variants. Forced colours: the marks use `ButtonText`, the pencil sketch, the dots and the aside's arrow at rest `GrayText`.
- Keyboard: native button; Space and Enter hold and release. The aside's note is `aria-hidden`: aria-pressed already says the word is held.

### ot-toggles (toggle-group)
- Underneath: Radix ToggleGroup: `type="multiple"` is a toolbar of `aria-pressed` buttons, `type="single"` a radio group. Needs no other item's classes.
- Anatomy: `<div class="ot-toggles" data-variant="slur | bracket | fingering | margin" aria-label="Name">` of `<button class="ot-toggles-item" data-value="…">`, each word in a `ot-toggles-word` cell that also holds its italic copy (from `data-text`), so a word is always as wide as its wider state and nothing beside it moves when it turns. Last, an `aria-hidden` `ot-toggles-marks` layer where script draws one `ot-toggles-mark` per run of held neighbours from `--l`, `--r`, `--t`, `--h`.
- Held, a word is yours: the roman sinks away as the italic rises into its place. Its mark stretches over the held words beside it; when two runs join, one mark stretches and the other fades where it stands. Held one at a time, the mark glides to the new word, leading edge first.
- Marks are measured from the face you see: the held italic, or the roman at rest (which carries its own pencil sketch), never the shared cell, so a slur, a pair or a number sits even on the word.
- slur (default): hairlines stand between the words, and the held run is tied under one engraved slur (a border on a half-ellipse, so it swells in the middle and tapers to points; it bows deeper the further it reaches). The hairline between two held words lies down under the slur, and none stands at the start of a wrapped line. Pointing sketches a pencil slur from the middle out.
- bracket: no hairlines; the held run is set in italic parentheses, after 20(25), and neighbours share one pair. Pointing sketches a pencil pair standing a little apart; holding closes the ink pair in. The room for the parentheses hangs into the margin, so words at rest line up with the label.
- fingering: after the score's fingering, the small numbers over the notes that say which finger plays each, and the "01" of "Less is more.". No hairlines. Each held word carries a small italic numeral over its middle: the order you held them in (`--n`, the value's order). Pointing at a free word pencils the number it would get (`--next`); holding inks it and it lands with spiccato; letting one go counts the later ones down. Meant for `type="multiple"`.
- margin: after the book's side head, set in the margin beside the column it heads. The words stand in a column, flush against one hairline, with an empty margin as wide as the column on its other side (two equal tracks). Held, a word crosses the hairline into the margin and turns italic, flush against the hairline's other side, so what you hold reads down the margin and the rest down the column. Pointing leans the word toward the hairline. Mirrored right to left.
- The focus ring rings the button, so it holds the word with its mark, and closes in from 12px with spiccato. The first word of each line starts at its cell's start edge; the rest are centred in theirs.
- States: rest, hover (pencil mark), focus, held, held together, disabled (the mark in pencil); fingering pointed at, held in turn and disabled; margin pointed at, held and focus.
- Keyboard: Tab into the group, arrows rove (all four arrows, so the margin's column reads with Up and Down) (following the direction), Home and End, Space or Enter holds. Left without `dir`, the group takes the page's direction.

### ot-btn-group (button-group)
- Underneath: native.
- Anatomy: `<div class="ot-btn-group" role="group" data-variant="parentheses | column | sentence" aria-label="Name">` of `ot-btn` buttons (no variant). The sentence is a `<span>`, since it sits inside a paragraph, and writes `.ot-btn-group-sep` (`aria-hidden`) between its buttons.
- Parentheses: one pair holds the set, after 20(25), and hairlines stand between the actions. Pointing draws a line under one; it passes through.
- Column: after "Less is more." and Healthy habits, the actions stacked as a narrow ragged column at tight leading, with no rules between. Pointing hangs the poster's short heavy dash in the margin beside the action; it grows out from the word and goes back into it, and a press lengthens it. It hangs into the inline-start margin, mirrored right to left.
- Sentence: the actions written into running text as a list, the way prose names choices: "copy the link, email it, or export a PDF". The group takes the text's size; each action is ink on a pencil hairline, and pointing passes an ink line through it. `conjunction` sets the last word between ("or" by default).
- Keyboard: Tab between buttons.

### ot-input-group (input-group)
- Underneath: native.
- Anatomy: `.ot-input-group` holding `.ot-input-group-text` (prefix), the `input`, then optional suffix text or a quiet `ot-btn`. It sits inside an `ot-field`.
- Ours and yours on one line: the prefix and suffix stay upright in pencil, the typed part is italic between them. The accent line draws only under your part (the input is its anchor), from where you touched it.
- A suffix follows your words (the input is as wide as what's in it, `field-sizing: content`), so an address reads as one phrase. A touch on the empty part of the line writes in the input.
- `InputGroupText` takes `agree`, the forms of a unit by plural category, and agrees with the number typed: 1 night, 3 nights.
- Variant `legend` (after the "28 December" calendar and the 14 / 08 of "the silence that heals"): your figure is set large, at `--ot-ff`, and our words stand stacked beside it in two small lines, the first in ink, the second in pencil. The input comes first.
- Variant `arrow` (after "It has to be design.": "Watch this space."): a hairline arrow (the group's `::before`, drawn by a mask) runs from your words to the action at the end. The shaft gives way as you write, inks once what you wrote is valid, and steps forward when you point at the action. It turns round right to left.
- A search input draws no native clear mark, as in `ot-field`.
- States: rest, focus, error (`aria-invalid="true"`), disabled.

### ot-code (input-otp)
- Underneath: native input, plus a hook.
- Anatomy: `<div class="ot-code">` holding one `<input inputmode="numeric" autocomplete="one-time-code" maxlength="6">` and six `.ot-code-slot` spans split three and three by `.ot-code-sep`, a leaning hairline. Script copies the digits into the slots and sets `data-here` on the next slot and `data-state="done | wrong"` on the box.
- Each digit drops onto its baseline in italic (`ot-drop-in`); the waiting line is the accent. Whole, the lines ink in turn. Wrong, they turn crimson together and an `ot-field-error` says why.
- One real input underneath, so paste, autofill and the keyboard all work natively.
- Variant `close-up` (the proofreader's close-up mark; the tight tracking of "the uncreative"): a dot waits for each digit, the next one in the accent. Whole, the spaces close and the halves meet in one tight figure; the mark's two arcs land over and under the join. Wrong, the spaces open again in crimson.
- Variant `lyric` (the score's lyric line; a cheque's sum in words): each digit is read back in words under its line (`.ot-code-word`, ours, upright), with a comma at the halfway breath and a full stop at the end, so the code can be checked aloud against the message. Whole, the words ink.

### ot-combo (combobox)
- Underneath: cmdk inside a Radix Popover.
- Anatomy: `.ot-field.ot-combo-field` holding the label and the trigger, `<button class="ot-combo" role="combobox" aria-haspopup="listbox" aria-expanded aria-controls>`, whose `.ot-combo-value` shows the chosen label, or the placeholder with `data-placeholder`. It opens `.ot-combo-pop` (the popover) holding a `ot-command`: its input to narrow the list, then `.ot-command-list` (`role="listbox"`) of `.ot-command-option` rows (`role="option"`); `.ot-command-empty` says what to try when nothing matches. Pencil has no trigger and no panel: `.ot-combo-pencil` holds its own `<input role="combobox">` on the line, `<ul class="ot-combo-list" role="listbox">` of `<li role="option">` under it, and `.ot-combo-empty`.
- In each suggestion, the letters you typed are wrapped in `<mark>` (the highlighter), and the suggestions arrive in turn. The active option carries a dot (`aria-selected`). The picked value is yours, in italic.
- Keyboard: Down and Up move through the list, Enter takes one, Escape closes it.
- Variants go on `data-variant`: list (the default), concordance, pencil.
- Concordance, after the concordance's keyword-in-context column and Rand's grid: the suggestions are set so what you typed lines up in one column, highlighted, with each word's start set to the left of it and the rest running on to the right. As you type, the rows glide sideways to keep the match on that axis. A long suggestion ends in an ellipsis.
- Pencil, after the letter-cutter's pencilled layout ("pointing sketches in pencil, choosing inks"): no panel. The rest of the best match is pencilled after your words, in place, and the few others are listed in flow under the line. Tab (or the arrow toward the end, at the end of the line) inks the pencilled rest; Down and Up change which match is pencilled; Enter takes it; Escape puts back what was there. Choosing turns the word from pencil to ink. Its own input is the combobox, with `aria-activedescendant` on its own listbox. Forced colours set the pencilled rest in `GrayText`. Pencil forwards native input props and the caller's ref to its input; caller accessibility associations take precedence over a Field's, and handlers run before internal behaviour.
- `multiple` (with list or concordance): any number of choices, `value` an array in the order they were chosen. The line (`.ot-combo-many`, a `PopoverAnchor`) writes them as one sentence with the badge's series tags ("*Didot*, *Futura* and *Univers*"): yours in the italic, ours the commas and the "and". Each word is a removable tag: pressing it strikes it and the sentence closes up round the gap, focus moving to the next word, or to the line after the last. The rest of the line, after the last word, is the trigger (it reads "3 chosen" to a screen reader); the baseline runs under the whole line and takes the accent on focus. The list stays open while you choose, Enter toggles the row under the dot, and a chosen row turns into the italic instead of taking the accent (many choices, one accent); rows carry `aria-checked` in a list marked `aria-multiselectable`. With `name`, each chosen value is sent as its own hidden input; disabled choices submit none. The pencil stays single.

### ot-date (date-picker)
- Underneath: Radix Popover holding the calendar.
- Anatomy: `<button class="ot-date" popovertarget="id" aria-haspopup="dialog">` inside a sentence, opening an `ot-pop` that holds an `ot-month`. `data-set` marks a chosen date.
- A date inside a sentence, like the select. The month hangs from it on a leader line; choosing a day writes it into the sentence in italic and closes the popover.
- `variant` passes to the month (dots, ruler, ghost or parenthesis); each holds at popover size (the ghost is sized to the month's width, the parenthesis line wraps to it), where `--big` steps the numeral down to `--ot-ff`. Opening focuses the day that holds the month's tab stop (the chosen day, else today).
- Keyboard: the month's own (arrows move by day or week, Enter chooses); Escape closes.

### ot-number (number-input)
- Underneath: a native text input with `role="spinbutton"`, plus a hook.
- Anatomy: `<div class="ot-number" data-variant="line | scale">` holding `.ot-number-reading` (`.ot-number-cell`, which stacks the `input.ot-number-input` and `.ot-number-figures` of `.ot-number-figure` spans, `aria-hidden`, in one grid cell; then an optional `.ot-number-unit`), a bracket `ot-btn.ot-number-less` and `.ot-number-more` (`tabIndex -1`), for scale `.ot-number-tape` (`aria-hidden`, `style="--at"`, the value in steps), and with `name` a hidden input that submits the plain number. `data-editing` while you type, `data-held` while the ruler is dragged.
- A field's baseline, and the accent line grows from where you touched it. Yours: the figure, in italic tabular figures, formatted by `Intl.NumberFormat` (`format`, `locale`, fixed to `en` so the first paint agrees). What you see is the figures layer; the input underneath holds the plain figures (the locale's decimal mark, no grouping), and a touch or a keystroke shows them to edit, with the caret in the accent. Leaving, Enter or a step reads what you typed (locale digits and decimal marks are normalized; grouping, currency and spaces are ignored), clamps it to `min` and `max`, and shows it formatted again; Escape puts back the value. Something that isn't a number goes back to the last number.
- `unit` is ours, upright in pencil after the figure, and follows it (`field-sizing: content`), so the line reads as one phrase; forms by plural category agree with the number (1 guest, 3 guests), and screen readers hear it in `aria-valuetext`.
- Line (the default): less and more stand in brackets at the line's end, the words of "Less is more."; at an end the word that can't go further goes pencil and is disabled. Each step turns the figures over like a counter's wheels: if the number keeps its length only the figures that changed turn, the units first and each place one `--ot-arpeggio` later, up as it grows and down as it shrinks; otherwise it turns over whole. Steps count from `min` (or zero) in whole steps, so 0.1 + 0.2 lands on 0.3.
- Scale: the dial's tuner drawn small, and Paul Rand's dimension ticks. Your figure is set at `--ot-f` over the index, less and more at the two ends of its line, and the baseline is the edge of a ruler whose ticks hang from it, one per step (`--ot-number-pitch`, 10px) and a longer one every ten, fading at both ends. The index is an ink stroke standing through the ruler; focus draws the accent along its edge. Stepping slides the ruler a tick (moderato, spiccato); drag it sideways and it follows the hand, a step a tick, and the figures change without turning while it's held. The row always reads left to right, as the tumbler's figures do.
- States: empty (the placeholder in our voice, in pencil), rest, focus, typing, at an end, error (`aria-invalid`, from a Field: the line crimson), disabled (the dotted baseline, pencil figures). Forced colours restate the tokens in system colours.
- Keyboard: Up and Down step, Page Up and Page Down step ten, Home and End go to `min` and `max`, Enter commits, Escape puts back. Less and more are for the hand and keep focus where it was.

### ot-drop (dropzone)
- Underneath: a native file input, plus a hook.
- Anatomy: `<div class="ot-drop" data-variant="corners | ghost">` holding `<label class="ot-drop-zone ot-corners">` (the file input as `.ot-sr`, for ghost `.ot-drop-ghost` (`aria-hidden`), `.ot-drop-words` ending in `.ot-link` "choose", then an optional `.ot-drop-hint` that describes the input), then an `ot-attachments` list of what's held. `data-over` while files are carried over it, `data-disabled`.
- An area defined only by its corner marks (`ot-corners`, `--ot-corner` at `--ot-space-4`), after "the silence that heals": a frame that doesn't close. The sentence is the control: "Drop files here, or choose". The whole area is the input's label, so a click anywhere opens the picker; Tab reaches the real input, and focus draws the highlighter through "choose" (the link's own look) and sets the corners in the accent.
- Pointing sketches the corners in pencil. Carry files over it and the corners close in by `--ot-space-4` and ink, landing with spiccato, and the words ink; let go or leave and they spring back out. The corners' colour is a registered `--ot-drop-c`, so it crosses over rather than jumps.
- What's held is listed as attachment rows, each waiting (`idle`, the hairline ring of a file still to go) with its size and a bracket Remove. Each drop or choice adds to them, and the same file isn't held twice. A refused file is a crimson row that says what to fix: "This takes PDF, PNG or SVG. Choose another file." or "Choose one under 10 MB; this is 14.2 MB." The real input always holds exactly what's listed (through a `DataTransfer`), so a form sends what you see. Resetting the form clears the files and refused rows, and calls `onFilesChange` with no files, as removing the last file does. `list={false}` leaves the listing to you, for rows with upload progress.
- Ghost: after the huge ghost numerals behind "the silence that heals". The number of files you carry stands huge and faint behind the words (`--ot-fff` in the expression italic, ink at 8%, 14% while over), set against the area's foot and end and cropped by them, two figures as the poster's 14 and 08. Dropped, it stays as the number held. It turns over as the count moves, up as files come and down as they go.
- States: rest, hover, focus, files over it, holding, refused (the row), disabled (the corners at the rule, the words in pencil). Forced colours: the corners are `GrayText`, `Highlight` on focus, `CanvasText` while over; the ghost is dropped.
- Keyboard: Tab to the input; Enter or Space opens the picker (native). Remove is a button.

### Form
- A composition, not a class: fields on the grid and one statement button to send it. On a failed send, each field gets its callout, the line turns crimson, and focus goes to the first error. While sending, the button is busy and says so ("Sending" with `ot-dots`). Nothing shakes and nothing apologises.

### ot-alert (alert)
- Underneath: native.
- Anatomy: `<div class="ot-alert" role="status">` (or `role="alert"` for errors) holding `.ot-alert-title`, a sentence, and optional `.ot-alert-actions`. `data-variant="error"` for what went wrong. `data-arriving` plays the entrance.
- A double bar, the sign in a score that something changes here. It draws down the margin, then the words arrive beside it in turn. Crimson only for an error, and then it says what to do. An error wears the final bar instead, thin then thick: what was happening stopped here.
- `cue` (after "It has to be design."'s "Watch this space."): a hairline arrow runs in from the margin, `clamp(40px, 12vw, 135px)` long, and stops at the first word of the title, at its x-height. Arriving, the line draws from the start, the head lands, then the words arrive. Right to left, it comes in from the right. For a notice that stands across a page.
- `errata`: the printer's errata slip. `AlertCorrection` sets "for *was* read *now*": the two in large italic (`del` and `ins`, so a screen reader hears the change), the one withdrawn stepped back to pencil, "for" and "read" small and upright between them on the same baseline. Arriving, the old words fade from ink to pencil and the new ones write in from the start. No bar.

### ot-skeleton (skeleton)
- Underneath: native.
- Anatomy: `<div class="ot-skeleton" data-variant="baseline | metrics | words" aria-hidden="true">` of empty lines, with an optional `.ot-skeleton-ring` for an avatar. Set `aria-busy="true"` on the region it stands in for; nothing moves until it is true, and nothing moves under reduced motion.
- `baseline` (default): baselines where the words will be, at the length they'll run. A pencil stroke reads along each line in turn (`ot-read`), the way an eye would.
- `metrics`: from Paul Rand's construction grid. Before a letter is drawn, the letterer rules its guides: the baseline in a hairline and, one real x-height of the voice above it (`1ex`, so it changes with the pair), a dotted line. Each line takes the font size its height implies (a body line is 1.7em of leading), so a headline's guides are a headline's. While loading, the dotted line is ruled out from the start of each line in turn and passes off the far end (from the right, right to left).
- `words`: a layout dummy's greeking. Each line is broken at word spaces by two runs of gaps (every 5em and every 7em) that intersect into words of one to five ems and repeat only after 35; each line starts the pattern elsewhere, so no two lines share a rhythm. The reading stroke now reads word by word.
- Forced colours: the skeleton keeps drawing its own lines, in GrayText, so it doesn't vanish.

### ot-pop (popover)
- Underneath: Radix Popover.
- Anatomy: `<div class="ot-pop" popover>` opened by a button with `popovertarget`. Anchor positioning places it under the opener (`position-area`), using the implicit anchor.
- Hung from what opened it on a leader line, after Weingart: the dot lands on the opener's edge, the line drops, and the panel settles below.
- Keyboard: Escape or a click elsewhere puts it away (native popover light dismiss).
- Variants go on `data-variant` of the panel (`PopoverContent variant`): leader (the default), brace, cut. Both new ones hang above or below the trigger and drop the leader.
- Brace, after the brace that joins a score's staves and the underbrace that sums a span: the panel loses its box and a hairline brace over its words gathers their whole width to one point at the trigger's middle. The ends curl at the words' edges; the arms and the point are Radix's arrow (`.ot-pop-brace-point` inside `.ot-pop-brace-arms`), so the point stays over the trigger when the panel shifts to stay on screen and the brace goes lopsided rather than point at nothing. Centred by default. Beside the trigger there's no width to gather, so the brace isn't drawn.
- Cut, after SPECTRA's title cut by a line: the panel's top edge, in ink, falls through the trigger's words at half their height (`--radix-popover-trigger-height`), and the panel rides over their lower half. There is no leader: the join is the cut. Flipped above, it cuts from the top and leaves the lower half.
- Keyboard and screen readers: Radix's popover in all three; the brace is `aria-hidden`. Reduced motion: the panel appears and the brace is whole. Right to left: the leader measures from the start edge, the brace is symmetric, the cut has no direction. Forced colours: the panel keeps a border in CanvasText (its hairline is a box-shadow, which forced colours drop; a border because Radix's menus set an inline `outline: none` on the panel), the brace panel stays boxless, the leader is drawn in CanvasText, and the brace is a border, which follows the text colour.

### ot-menu, ot-menubar (dropdown-menu, context-menu, menubar)
- Underneath: Radix DropdownMenu, ContextMenu and Menubar.
- Anatomy: `<div class="ot-pop ot-menu" popover role="menu">` holding `.ot-menu-label` headings and `<button class="ot-menu-item" role="menuitem">` (or `menuitemcheckbox` with `aria-checked`), each with optional `.ot-menu-keys`. `data-variant="danger"` for a destructive item. A menubar is `<div class="ot-menubar" role="menubar">` of `.ot-menubar-trigger` buttons on a hairline; each menu is a `ot-menu` hung in that hairline. A context menu is an `ot-menu` with `data-at="point"`, placed where the person pressed.
- The item you point at is marked with the highlighter. Items arrive in turn. A menubar opens its hairline into a pocket under the open word: the menu rises over the rule, its paper hides the rule there, and its sides and foot carry the same line on, down, along and back up. The word and its menu are one shape, with no leader and no stroke. The menu unrolls down out of the line and rolls back up into it. Its words stand under the word, and the bar's words sit in from the rule's ends by a menu's own inset, so the first menu folds from the rule too. With no room below, it turns above the words in a whole frame. Focus on a word is the accent stroke laid on the rule under it. A context menu spreads from the point like ink (`ot-spread`); it opens toward the line's end and down from the point, back from it without room, and on a phone slides in to fit. A submenu opens beside its item; on a narrow screen, with room on neither side, it drops open under the item, in by the words' inset, the next level of an outline, and hangs from the item on the popover's leader (`data-drop`): the dot on the marked item's foot, the line dropping over a strip of paper. The item's arrow turns down while it is open. Shortcut keys (`dir="ltr"`) read ⌘Z in either direction. Without a `dir`, each menu takes the direction of the page around its trigger or bar, so on a right-to-left page it hangs from the right end, submenus open to the left, and the arrow keys mirror.
- `variant` on the list (`DropdownMenuContent`, `ContextMenuContent`; `data-variant`): `list` (the default) or `leaders`, and also `marginalia` on a dropdown menu or `orbit` on a context menu. On the `Menubar` root: `pocket` (the default), `leaders` or `caption`. Under every variant a context menu's point is pinned by a cross, the register mark of "the uncreative", over the menu's corner, and the menu spreads from it.
- leaders: a book's contents page. Each word is joined to its keys (or a submenu's arrow) by a row of leader dots in `rule-strong`; a word with neither has none, and the words don't wrap. The highlighter stands down: the word you point at inks, and its dots ink from the word to its keys, passing through as the highlighter does. Submenus keep the leaders. A menubar set to `leaders` sets every menu so, in its pocket.
- marginalia (dropdown menu): the small notes on hairline arrows of "It has to be design.". Each item's `hint` is a note (`pp`, graphite, at most 13em) hung beside the list at the height of the word you point at, on a hairline arrow pointing back at it; it glides from word to word, and a word without a hint leaves the margin empty. The list keeps its highlighter. With no room beside the list (under 220px) the note stands under it as its caption, without the arrow. The note is aria-hidden: each item carries its hint as its `aria-description`.
- orbit (context menu): after WOVE. The words stand on an arc bowed away from the point, one dot on the arc for each; the one you point at inks and its dot lands as the accent. The arc is the panel's edge: the paper lies only outside it, and the panel's hairline and shadow stand down. Every row is one step high, and the words swing out to the arc as they arrive. Put items straight in the list (a group counts as one step); a separator is a step of silence with a short rule in it. In forced colours the arc gives way to a framed panel and the dots stay.
- caption (menubar): the label at the far end of the SHAPES / GRADIENTS frame, and an editor's status line. The bar's far end keeps a small line of where you are, the path from the open word to the item you point at, parted by slashes (File / Export / As PDF); its last step inks and arrives as you move. At rest it shows the bar's `aria-label` in pencil. Below 40rem only the last step shows. It is aria-hidden, since the menus already name the path.
- Forced colours: the highlighter gives way to the system's `Highlight`; leaders' dots and the marginalia arrow are `CanvasText`; orbit's pointed dot is `Highlight`. Reduced motion: the dots, the note and the caption move straight to their places.
- Keyboard: Down and Up move, Home and End go to the ends, Enter runs, Escape closes, Tab closes and moves on. Right opens a submenu and Left closes it (mirrored right to left). In a menubar, Down opens, and Left and Right move between menus, open or closed. The context menu opens with the ContextMenu key or Shift+F10.

### ot-navmenu (navigation-menu)
- Underneath: Radix NavigationMenu.
- Anatomy: `<nav class="ot-navmenu">` of small trigger buttons (`aria-expanded`, `aria-controls`) and `.ot-navmenu-panel` panels of large links.
- Small words open a panel of large names, the scale contrast of a poster. The panel's rule draws across, the names arrive in turn, and the trigger's arrow turns. It opens on pointing (after a short wait) or pressing, and closes on leaving.
- `variant` on the root (`data-variant`): `names` (the default), `lead` or `inline`.
- lead: a magazine's contents page, and WOVE's "03 Ambient". The names stand small (`mp`, graphite) in a narrow column; the one pointed at or focused (the first, at first) is inked there and set beside the column as the headline at `ff` 200, its `<small>` line under it in graphite. The headline is an aria-hidden copy (`.ot-navmenu-lead`); the links keep their own names. Below 40rem the headline stands down and the names keep their lines.
- inline: "Healthy habits → for creatives", one line of thought. The trigger's arrow is → (← right to left). A press, never a passing pointer, opens the names into the line after the word, larger (`mf` 200) on the same baseline; the words after it make room, and the other words step back to pencil. The `<small>` lines stay for screen readers only. Below 40rem the names drop to `mp` and may wrap.
- Keyboard: Enter or Space toggles a panel; Escape closes it and returns focus to its trigger. Tab moves from an open trigger into its names. Without a `dir`, the menu takes the direction of the page around it as it mounts, so it mirrors on a right-to-left page. It reads it once, at mount, as the menus do: a page that changes `dir` afterwards passes `dir` itself, or remounts the menu.

### ot-command (command)
- Underneath: cmdk; `CommandDialog` puts it in a Radix Dialog.
- Anatomy: `.ot-command[data-variant="headline | mesostic | index"]` holding `<input class="ot-command-input" role="combobox">`, `.ot-command-list` (`role="listbox"`) of `.ot-command-group` headings and `.ot-command-option` rows (`.ot-command-name`, split at the first match into `.ot-command-before` and `.ot-command-key`; `.ot-command-hint`; the arrow drawn after, with empty alt text), then `.ot-command-empty`. `defaultSearch` opens it on a query.
- What you type is set as large as a headline, in italic. Matches are marked with the highlighter; the chosen row steps forward and shows its arrow. Rows arrive in turn as the list changes.
- mesostic: John Cage's mesostics and the printed concordance (key word in context). Every row is set on one vertical axis at the place your words appear: the part before the match set flush against the axis from the left, the match and the rest from the right. The found letters stand on the axis in roman capitals at 600 in ink, with no highlighter, so the query reads straight down through the results; later matches in the same row aren't marked. The query itself is typed on the same axis above them, and the group headings and empty copy start there too. The axis is the middle of the rows less the arrow's column (`space-6`, `space-5` on a phone). Hints stand at the start of the row, as a concordance's locators do; on a phone they drop under the key. Nothing steps forward (that would break the axis): the chosen line inks and its arrow shows. In RTL the columns mirror, so the text before the match sits right of the axis, as it reads.
- index: a book's index, run in. Each group's name hangs in the margin (`7rem`) as the headword, and its rows run on after it as one paragraph at `mp`, sub-entries parted by semicolons and closed with a full stop, hints small after each name as locators. Matches are marked with the highlighter; the chosen entry is underlined with a hairline in ink. Rows that stop matching leave the sentence, which closes up; the entries fade in in turn. Below 40rem the headword sits over its paragraph.
- Keyboard: Down and Up move, Enter runs, in every variant (the index moves along the sentence in reading order). Empty copy names something to try.
- The chosen row is brought into view only while you're in the palette, so mounting one never scrolls the page.
- `CommandDialog`: the ⌘K palette; `variant` and `defaultSearch` pass through. A Radix Dialog holds the command over a dimmed page, with a visually hidden title. The page registers the shortcut; the item doesn't.

### ot-steps (steps)
- Underneath: native `<ol>`.
- Anatomy: `<ol class="ot-steps" data-variant="margin | rise | cascade">` of `<li class="ot-step">`, each with an `h3.ot-step-title` and its text. `data-current` marks where the person is and sets `aria-current="step"`; `data-done` marks what's behind them.
- margin (the default): the numbers are a real sequence, so they are set large and thin at `--ot-f` in the margin, in two figures as the posters number ("Less is more." 01), in pencil. Done steps' numbers go to ink; the current number takes the accent and lands with spiccato. A hairline stands between steps.
- rise: the numerals stand huge and thin (`--ot-ff`, weight 100) on one rule-strong hairline running across the page, a column to each step, like letters cut by a line in SPECTRA and Paul Rand's grid. A step to come is sunk into the line, only the top of its figures showing; reached, its numeral rises out whole in the accent (andante, exhale), and it stays standing in ink once done. Below 40rem the steps stack, each on its own line, at `--ot-f`.
- cascade: no numerals. The titles (`mf`, 300) are set as one broken headline that steps across the page a space-8 at a time (space-5 below 40rem; the stair stops at the fifth step), the way "Healthy habits → for creatives" breaks its line, so the order is read in the space itself. Behind you in pencil, ahead in graphite; where you are in ink, with the accent arrow after the title pointing on to the next (it steps forward into place with spiccato when the sequence moves on; ← right to left). The last step, reached, closes the headline with an accent full stop instead.
- folio: the compact one, after SPECTRA's large 1/3 beside its small notes and "Less is more."'s 01. The sequence folds into one `ot-fraction` at `--ot-ff` (`--ot-f` below 40rem) in `.ot-steps-folio`: where you are in the accent italic ("02"), of how many small and upright after the pen stroke ("/05"), in two figures. Only the step you're on is shown beside it (`data-shown`), its title on the figure's baseline and its text under it in graphite; the other steps stay in the `<ol>`, visually hidden, so a screen reader hears the whole order and `aria-current`. Moving on, the figure turns over figure by figure (the fraction's roll). All done, the figure goes to ink.
- `value` / `defaultValue` / `onValueChange` on Steps: the step you're on, counted from 1 as the numerals are; the steps before it are done, and one past the last means all done. A Step's own `current` and `done` win when given. With `onValueChange`, a done step's title is a `<button class="ot-step-back">` back to it (not in folio, whose done steps are hidden); pointing or focus draws a hairline under it.
- Only for real sequences. A list that isn't an order is `ot-rows` or plain prose.

### ot-tour (tour)
- Underneath: native `<dialog>` with `showModal()`, through the dialog item.
- Anatomy: `<dialog class="ot-tour">` the size of the window and see-through (no backdrop), holding `<svg class="ot-tour-lead" aria-hidden="true">` (a `line.ot-tour-line` and a `circle.ot-tour-dot`) and `.ot-tour-callout`: `.ot-tour-head` (the `h2.ot-tour-title` and `.ot-tour-count`, "03/04" with "Step 3 of 4" for screen readers), `.ot-tour-text`, then `.ot-tour-actions` (End, Back, Next or Done).
- After the Weingart letter: each step is an ink callout, its head in bold and the count at its far end as a corner note, hung on a long leader line that ends in a dot on the thing it is about. The dot is the accent (look here), set on the target's edge facing the callout; the leader leans off it toward the roomier side of the window and the callout hangs a space-7 beyond, held inside the window. A step with no target stands alone in the middle with no leader. Each step arrives as the note does, in turn: the dot lands (spiccato), the leader draws out, the callout spreads from the leader's tip (`clip-path: circle()`).
- It moves only when the person does: Next, Back, or the arrow keys (swapped right to left); a target out of view is scrolled to the middle first. It never plays by itself. The last step's Next reads "Done." and closes; End or Escape stops it anywhere. Uncontrolled, it starts again from the first step each time it opens.
- Keyboard and screen readers: focus opens on Next and stays on the control that moved it (Back, or Next once Back is gone). The title names the dialog and the text describes it; Next and Back are described by the count, the title and the text, so each new step is read as focus lands. On the ink the focus ring is in the paper's colour.
- Reduced motion: each step appears whole, and the scroll jumps. Forced colours: the callout keeps a border in CanvasText, the leader is CanvasText and the dot Highlight.

### ot-source (source)
- Underneath: build-time highlighting with sugar-high, plus a Copy hook.
- Anatomy: `<figure class="ot-source">` (an inline-size container) holding `.ot-source-frame`: a `figcaption.ot-source-meta` (the file name, its extension in pencil, and Copy), then `<pre class="ot-source-code" tabindex="0"><code>` with one `.sh__line` per line, each carrying its depth as `--i`.
- Code is type, set in the voice at 88% width. Weight is the only highlighting: keywords are ink at 500, signs recede to pencil, and what someone wrote (strings, JSX text, comments) is the expression italic. There's no second colour.
- Indentation is space you can see: a proportional face makes two spaces nearly nothing, so each leading space becomes half an em. Lines wrap rather than scroll sideways, and a turnover hangs a step further in, like verse.
- A bracket joins the lines like a system in a score, and the line numbers stand before it like bar numbers (none for a single line). When the frame is 34rem or wider, the file's name and Copy stand in the margin, the way a score names its instrument; narrower, they sit above the lines.
- Copy is a quiet button. It keeps its name through the flow: the label rolls from Copy to Copied, then back, and the accent runs down the bracket once.
- gloss (`data-variant="gloss"`): the glossed manuscript, and Knuth's literate programming. A line that is only a `//` comment is what someone wrote about the code, so it becomes a note (`.sh__line[data-gloss]`; neighbouring notes travel together in one `.ot-source-gloss`). When the frame is 46rem or wider the note leaves the lines for the outer margin, drops its slashes and stands in small italic level with the line it explains (an absolutely placed block keeps its place in the flow), while the code closes up and keeps its true line numbers. Notes on neighbouring lines queue, the later one stepping down just clear of the one above, as a book's sidenotes do. Pointing at a note inks the line it explains, and pointing at the line inks its note. Narrower, the notes stay in the lines.
- passage (`data-variant="passage"`, `passage={[from, to]}`): the reader's pencil line down the margin beside the lines that matter. The bracket that joined the system gathers to the passage (`.sh__line[data-passage]`, drawn per line with hooks at its ends) and inks; the passage is ink and every other line recedes to pencil at weight 400. Copying runs the accent down the passage line by line, then it settles back to ink.
- Unwrapped (`wrap={false}`, `data-wrap="off"`): SPECTRA's word cropped by the frame. Each line is kept whole and runs on past the frame's end, and the lines scroll sideways inside `<code>` (which then takes the focus, so the arrow keys scroll it). The lines stop being positioned, so the numbers and the passage's line are placed from the `<pre>`, outside the scroller: they keep their place while the code slides under the bracket.
- `language`: the language named in the margin under the file's name (`.ot-source-lang`), in the pencil's small capitals, as a score marks its key. Only when given.
- Code reads left to right on any page: the `<pre>` carries `dir="ltr"`, so a right-to-left page doesn't reorder it; the margin and the meta still follow the page.
- Keyboard: the code block takes focus so a screen reader can land on it; Copy is a button.

### ot-command-line (command-line)
- Underneath: native, plus a hook that shares the runner pick between every command line and remembers it (`localStorage` key `0db-runner`).
- Anatomy: `<figure class="ot-command-line">` holding an optional `.ot-command-line-runners` radio group (npm, pnpm, yarn, bun), then `.ot-command-line-row`: `<code class="ot-command-line-text">` and Copy.
- One line to type, set on a baseline like a field already filled in. The runner and the address recede to pencil; the command is ink; `emphasis`, the part of an address that's the reader's, is the expression italic. A long line breaks after a slash or a dot and its turnover hangs; the emphasised name moves to a new line whole with what follows it, and breaks after a hyphen only when it's wider than the line.
- The runner words are a radio group: the chosen one turns italic with the dot beneath it, and every command line on the page follows.
- Copying draws the baseline in the accent, left to right, then lets it go; the label rolls from Copy to Copied.
- parsed (`data-variant="parsed"`, `glosses`): the interlinear gloss, a linguist's word-by-word reading, and the dictionary entry of "the uncreative", the part of speech set small under the word. Each glossed word (`.ot-command-line-word`) stands over a short rule the width of the word, its gloss (`.ot-command-line-gloss`) hung beneath in small pencil type; the words keep one baseline and each column is as wide as its word or its gloss. Pointing at a word inks its rule and its gloss. The glosses are hidden from screen readers and read once after the command instead, word by word.
- synopsis (`data-variant="synopsis"`, `blank`): a manual page's synopsis, where the words you replace are set in italic. The `emphasis` becomes a blank you write in (`input.ot-command-line-blank`, labelled by `blank`), in your italic on a hairline of its own; it grows with what you write (`field-sizing: content`, with `size` as the fallback), spaces are refused, an empty blank shows the original in pencil, and Copy copies your line. Focus draws the accent under your part only.
- The command reads left to right on any page (`dir="ltr"` on the `<code>`); a long address breaks after a slash, never inside `//`.
- Keyboard: arrows move between runners; the synopsis blank is a text field; Copy is a button.

### ot-contour (contour)
- Underneath: native, plus a hook that lays the lines out with pretext (`@chenglou/pretext`, loaded when it's needed).
- Anatomy: `<p class="ot-contour" data-shape data-variant="tale | cola">` holding the text for readers (`.ot-sr`) and `.ot-contour-lines`, one aria-hidden block per line, each carrying `--t`, how far through the text it starts, and `--i`, its index. In `cola` the lines are grouped by phrase in `.ot-contour-colon`, a turnover marked `data-turn`.
- edge (the default, no attribute): a paragraph set to a contour, the way a score draws a swell. Each line is laid to its own width: `diminuendo` narrows to the end, `crescendo` opens towards it, `hairpin` swells and closes, centred. Every line but the last is then spread to its width, mostly in the word gaps (at most 0.3em a gap) and a little in the letters, and takes one more word when the gaps can close by 0.06em to hold it, so the edge is the hairpin's straight line rather than a ragged stair. The browser never re-wraps them.
- tale: after the Mouse's Tale in *Alice* (1865), where the type shrinks as the tail thins. `shape` sets the size of the type instead of the width (`least` is the smallest share of the inherited size, never under 10px), and every line holds half the measure in its own size, so the tail narrows as the type does. The lines swing about the middle on a slow wave, one swing every seven lines. Moving a fine pointer across the paragraph moves the wave along (`--phase`, a full turn across its width) and the lines further down follow later (each line's glide is `--ot-andante` plus one `--ot-arpeggio` for each line above it), so the tail swishes after the hand; leaving lets it come to rest. Touch and reduced motion get the still tail. Right to left it swings from the other side.
- cola: *per cola et commata*, the way Jerome set scripture to be read aloud. A line to each phrase, broken after a comma, a colon, a full stop, a question or a dash, so the ragged edge is the rhythm of the speech. A phrase longer than the measure turns over, hung 1.5em in (at the inline start, so it mirrors right to left). Pointing at a phrase keeps it in ink while the others rest in pencil (moderato); the paragraph is one reading, so nothing is focusable.
- `data-fade` lets the colour follow the shape, ink where it's loud and pencil where it's quiet, so the quietest line still reads.
- It lays out again when its width changes or `<html>` changes face (it watches the pair, scheme, mode and key attributes, not `class`, which smooth scrolling toggles on every scroll). Before the fonts arrive, or without script, it's a plain paragraph. Forced colours: the text is system text and the pointing colours fall away.

### ot-melody (melody)
- Underneath: native, plus a hook that measures and lays the words out with pretext (`@chenglou/pretext`, loaded when it's needed).
- Anatomy: `<figure class="ot-melody" tabindex="0" aria-label>` holding one `.ot-melody-stave` per line, each with a `.ot-melody-staff` (five hairlines in `--ot-rule`, an opening barline, and a closing one), an `svg.ot-melody-marks` (the engraving) and its `.ot-melody-note` words, positioned by pretext's measures. The last stave ends on a double bar.
- The engraving is the marks a singer reads, in pencil and nothing else: a slur over each phrase (the words up to a comma or a full stop, never across a stave), a pen stroke that swells in the middle and thins to nothing at its ends, bowed just enough to clear every word it passes over and leaning toward the end that needs the lift; a fermata (an arc over a dot) above the staff over the last word; and under the first word its dynamic, `.ot-melody-dynamic`, in the bold italic. The dynamic is the type size the melody is set at, since the sizes are dynamics already: at `--ot-mp` it's *mp*. A word's letters wear a halo of the paper (`--ot-melody-ground`), so the lines and slurs stop just short of them.
- A sentence set on a stave, each word a note: its baseline sits on a line or in a space, following `contour` (steps, 0 the bottom line, 8 the top, odd numbers the spaces). Without one, the sentence writes its own tune: long words rise, the phrase rocks, and it comes home to where it began.
- The words are spaced evenly across the measure and wrap onto a new stave when it's full; the last stave keeps to a moderate gap, a rest rather than a stretch. No word stands alone on the last stave: it takes one from the stave before when that one can spare it.
- Pointing at a word sounds it: it takes the accent, lifts a little and lands, and the words after it do the same in turn, one `--ot-arpeggio` apart, then settle back to ink. The last word, under its fermata, holds the accent for as long again before it lets go. The same word sounded twice starts over.
- Keyboard: the figure is one focus stop, and Enter plays the phrase from the first word. The words are aria-hidden; the figure's label is the plain sentence. Under reduced motion there's no lift and no travel: the sounded words hold the accent until you leave.
- It lays out again when its width changes or `<html>` changes face. Before the fonts arrive, or without script, it's the plain sentence.
- `variant` (`data-variant`): `stave` (the default), `noteheads` or `cutaway`.
- noteheads: after the calendar poster's discs and the score's lyric underlay. Each word's note is a disc (`.ot-melody-head`) one staff space across on its step, with no stem, and the words are sung under the staff on one lyric baseline (below the lowest disc too), each under its disc. No slurs, since every word is one note. The fermata stands over the last disc, and the dynamic goes above the staff over the first, where a vocal score puts it to keep the words below clear. The discs say where you are in the song, as the poster says where you are in the month: to come in hairline rings (`--ot-rule-strong`, filled with the ground), sung in ink, the word you're at in the accent. Pointing at a word or its disc moves there, and the discs fill or empty in turn from where you were, one `--ot-arpeggio` apart; leaving lets it go. Keyboard: the arrows step along the words (mirrored right to left), Home and End go to the first and the last, Enter sings it through to the last, Escape and blur let it go. Reduced motion: the discs change at once.
- cutaway: after the cutaway score, which drops an instrument's staff while it rests. The continuous staff and its barlines are not drawn; under each word, and 0.12em beyond it, a piece of the five lines (`.ot-melody-bit`) stands instead, so the silences between the words are paper and the slurs carry across them. Everything else, the tune, the marks and the arpeggio, is the stave's.
- Forced colours: the discs ring and fill in CanvasText, the one you're at in Highlight; the staff lines are GrayText, and the words drop their halo, which would be forced to the text colour.

### ot-reverb (reverb)
- Underneath: native, plus a hook that measures the echoes' drift with pretext (`@chenglou/pretext`, loaded when it's needed).
- Anatomy: `<p class="ot-reverb">` holding the phrase as `.ot-reverb-line`, then an aria-hidden `.ot-reverb-echoes` with one `.ot-reverb-echo` per echo and a closing `.ot-reverb-rest`.
- A phrase that echoes into silence. Each echo is quieter: the colour steps from ink through graphite to pencil and then fades by opacity, the letters open a little each time, and the size steps down a dynamic (`from`, mf by default: mf, mp, p, pp, and it stays at pp).
- Each echo is shifted right by the width of the previous echo's first word, measured in that echo's own type, so they drift like a canon. The last thing is a rest: a hairline at pp in pencil.
- Pointing at it lets the echoes breathe out: each drifts a little further, one `--ot-arpeggio` after the last, and settles back on leave. Arriving isn't a move: the shifts are placed before the easing switches on.
- The phrase is read once. The echoes and the rest are aria-hidden and can't be selected. Before pretext has measured, or without script, the echoes simply stack.
- `variant` (`data-variant`): `canon` (the default), `antiphon` or `vowels`.
- antiphon: after cori spezzati, the two choirs Gabrieli set on opposite sides of San Marco to answer each other. The echoes don't drift: they come back from either wall of the measure in turn (`data-side`), the first from the far one, each a dynamic quieter and fading as the canon's do, and the rest waits at the wall the next answer would come from. Pointing opens every echo's letters by as much again, one `--ot-arpeggio` after the last. Right to left, the walls swap with the text.
- vowels: after a live room, where the reverberation masks the short consonants first and the vowels ring on. Every echo keeps the phrase's size and tracking, so it lies letter for letter under it, and each loses letters in a fixed order (consonants and punctuation first, then vowels, hashed from their place) until the last keeps about a tenth. A lost letter (`.ot-reverb-lost`) keeps its place and goes silent, so what is left stands in columns; spaces are never lost, and letters are split by grapheme, so a mark stays with its letter. The echoes wrap where the phrase wraps, so the columns hold on every line. Pointing sketches the lost letters back in pencil, one echo after another.

### ot-gather (gather)
- Underneath: native, plus a hook that measures every letter with pretext (`@chenglou/pretext`, loaded when it's needed) and an IntersectionObserver.
- Anatomy: `<h2 | h3 | p class="ot-gather" data-variant="forme | coil" data-by="word | line">` holding the real text (`.ot-gather-text`) and, while it runs, an aria-hidden `.ot-gather-glyphs` with one span per piece (a letter, a word or a row), each carrying where it starts (`--dx`, `--dy`, and for the variants `--sx` or `--r`) and its place in the order (`--n`, and `--s` from 0 to 1). `data-phase` is `wait`, `dust`, `gather` or `scrub`, and is absent when it's plain.
- A line whose letters start as dust: scattered by a fixed hash of their index, at most 1.2em off their place, at pp opacity. They settle into place when the line scrolls into view (once) or, if it hasn't yet, when it's pointed at. Each letter travels for `--ot-andante`, one `--ot-arpeggio` after the last.
- Each letter's place is its x in the real line, kerning included, and its row, so the settled state is the real layout. When the last letter lands the real text is given back, so selecting and copying work; the text is in the DOM throughout for readers.
- forme: letterpress type stands in the chase mirrored and is read the right way round only once it's printed. Each row starts as its own mirror image, every letter flipped and at its mirrored place in the row, in pencil at full strength so the backwards line can be read; settling, each letter crosses to its place, turning over as it goes (it narrows to nothing halfway, like a sort turned in the fingers), and inks as it lands.
- coil: the text wound up like a ribbon. Every letter is set along one Archimedean spiral beside the first row's start (a little more than a letter's height between turns, the first letter on the outermost turn, each turned to the curve), at half strength; settling, the letters leave it in reading order, so it unwinds from its free end and lays itself along the line. Right to left the coil sits at the right and winds the other way.
- Pass a dynamic class (`ot-f`, `ot-mf`…) for the size; the line wraps and aligns as the text would (start and end follow the direction).
- The variants keep the one motion: the same travel, timing and hand-back as the dust; only where the letters start differs.
- by (`by`, `data-by`): what travels as one piece, after Split Text. letter (the default) is each letter. word sets each word down whole, as "Less / is / more." stands a word to a row and "Healthy habits" sets its notes a word to a line; each leaves `4 × --ot-arpeggio` after the last. line casts each row whole, as a Linotype casts a slug, `8 × --ot-arpeggio` apart. A piece is measured and placed as a letter is (its x in the real line, kerning included), so every variant works by any piece: a forme word or row is mirrored whole at its mirrored place, a coil word or row lies along the spiral turned to the curve.
- scrub (`scrub`, `data-phase="scrub"`): the settle follows the scroll instead of playing once, after scroll-reveal. `--p` runs from 0, as the line's top comes in at the foot of the view, to 1, once it's two fifths down from the top (or as far as the page can scroll; a line already in view when the page opens starts as dust and sets over the scroll left before that point). Each piece leaves as `--p` passes its place in the order (`--s × 0.6`) and lands 0.4 of the scroll later, travelling linearly with no transition, so it stops when the scroll stops and scatters back when you scroll back. At 1 the real text is given back and the pieces wait out of sight; below 1 they take over again. `--p` is read from the real layout in a frame asked for by the scroll event, which runs after a smooth scroller's own frame (Lenis moves the page itself), so the letters and the page move in the same frame. Pointing does nothing in a scrub: the scroll is the only hand. By word it is word-stream: words arriving one by one as you read down.
- In prose (article headings): put `Gather` in place of a heading inside `Prose` (`<Prose><Gather as="h2">…</Gather><p>…</p></Prose>`). The heading takes the prose's size, weight and spacing, and settles as you reach it; the paragraphs under it are already there. The gather always wraps greedily as pretext does (`text-wrap: wrap`, over the prose's balance), so its letters land where the heading's own lines fall.
- Under reduced motion, without script, or before pretext arrives, it's just the line. It measures again only when its width or face changes, so a scroll never cuts a settle short. Pending imports, font measurements and scroll frames stop when it is released; a failed font load restores the plain line.

### ot-wake (wake)
- Underneath: native, plus a hook that lays the lines out with pretext (`@chenglou/pretext`, loaded when it's needed).
- Anatomy: `<p class="ot-wake">` holding `.ot-wake-plain` (the text, always in the flow), `.ot-wake-lines` (aria-hidden runs, one span per run, shown only while the wake is open) and, with `mark`, `.ot-wake-ring`.
- A paragraph that parts around your hand like water. A fine pointer (not touch, not reduced motion) opens a circle of `radius` em (3.2) under it; each row the circle crosses is set as two runs, one either side, sharing one cursor through the text, so the words are pushed on rather than hidden. A run too short to read stays empty.
- The circle's radius eases in as the pointer arrives and out as it leaves, and it follows the pointer a little behind. The frame loop runs only while something is still moving. `data-live` is set on the paragraph while the wake is drawn; the plain text goes transparent then and stays in the flow, so nothing below it moves. Two lines of room under the paragraph (`--ot-wake-room`) hold what the circle pushes on.
- No shape is drawn by default; `mark` draws a hairline ring inside the hole. Touch, keyboard and reduced motion get the plain paragraph, which is also what a screen reader reads. It measures again when its width changes or `<html>` changes face.
- `variant` (`data-variant`; none for the default, `circle`): `river`, `caesura` or `weight`. All keep the plain paragraph for readers, touch, keyboard and reduced motion, and river and caesura are set right to left in a right-to-left paragraph (each run hangs from its end, the first run on the right); weight takes its places from the laid-out text, so it follows any direction.
- river: the typesetter's river of white, the fault a compositor spends a career closing, made on purpose. A gutter half the radius wide runs the paragraph's whole height at the hand's x; every row is set as two runs either side of it, sharing one cursor, so the paragraph reads as two columns that follow you from edge to edge. `mark` draws a hairline down the middle of the river, the length of the text.
- weight: the letterpress's impression, and the heavy condensed roman of "It has to be design.". Nothing parts: the letters within the radius press heavier on the face's weight axis (to 800, cosine falloff, `--t` from 0 to 1 per letter) and, where the face has a width axis, narrower by as much as the weight widened them (the script finds that width once, per face), so each keeps its set width. The letters are a layer (`.ot-wake-lines`) placed from the plain text itself, each measured by a range and centred on its own place, so no line reflows; the room under the paragraph is not needed. It rests under a still hand and eases back as the hand leaves. `mark` draws a hairline ring round the reach. Without a width axis (press) the pressed letters simply crowd.
- caesura: the pause in the middle of a verse, a breath where the line allows it. The paragraph opens at the line you point at: the rows above stay, the rows below drop by the breath (the radius, at most the two lines of room), and the line under the hand sits between them, held apart, the share above and below following where on the line the hand is. `mark` sets a rule in each breath, the held line between two hairlines, as the "Less is more." poster sets its lines.

### ot-calligram (calligram)
- Underneath: native, plus a hook that lays the lines out with pretext.
- Anatomy: `<p class="ot-calligram" data-shape | data-variant="rain | mirror">` holding the text for readers (`.ot-sr`), `.ot-calligram-lines` (aria-hidden, one block per line, each carrying `--t`, how far it is from the shape's widest part) and, for `fermata`, `.ot-calligram-dot`. Rain fills the lines with `.ot-calligram-streak`s of one span per letter (`--j`, its place down the streak); mirror with one `.ot-calligram-side` per side (`--x`, `--a` its turn), then `.ot-calligram-centre`, which is read.
- fill (the default): the paragraph fills `shape`.
- A paragraph that fills a shape, as Apollinaire's calligrams did. Each line is as wide as the shape's chord at its height and is centred in it, spread to both sides by its gaps and a little by its letters, so the outline is only implied: nothing is drawn. `circle` is the 0 of 0nlyType, `fermata` a half-disc of text over one accent dot, `wave` widths that swell and narrow like a sound wave (eleven rows a swell).
- The circle and the half-disc are filled exactly: the size of the type is found (it never exceeds twice the inherited size) so the last word lands in the last row, and the box has its own aspect ratio, so nothing moves when the lines arrive. `size` is the shape's width (default 34rem, never wider than its space). The wave takes the inherited size and its height follows its rows.
- rain: after Apollinaire's "Il pleut" (1916), where the words run down the page in slanting streaks. The words fall in streaks, a letter to a drop (0.8em apart, upright, centred on the streak), each letter a sixth of an em further over than the one above, so every streak leans the same way, as rain does in wind. A word is never split unless it's longer than a streak; a space is an empty drop. The streaks stand 2.2em apart, as long as they need to be for all of them to fit the width, and each starts a few drops late by a fixed hash, so the tops are ragged and the feet fall where they fall. Read left to right, each top to bottom; right to left the streaks run from the right and lean the other way. With `data-fade` each streak darkens as it falls, the drop at its foot in ink. Its height follows its streaks.
- mirror: after his "Cœur couronne et miroir" (1918), where the words make a mirror frame around his name. The paragraph is the frame of a square: a line to each side, clockwise from the top, each turned to face out (the right side reads downward, the foot upside down, the left side upward), each spread to its side's length by its gaps; when a ring is full the next begins a line inside it, so a long text spirals in until the words run out. The last line stays unspread, so the frame closes on a pause. What is left in the middle holds `centre` in the expression italic, as large as that room allows (at most six times the inherited size), because it is yours; it is real text, read after the paragraph. Right to left the frame runs counter-clockwise from the top right. The square's box has its own aspect ratio, so nothing moves when it's laid.
- `data-fade` lets the colour follow the shape, ink at the widest and pencil at the narrowest. It is a still ornament in every variant: pointing shows nothing. It lays out again when its width changes or `<html>` changes face (it watches the pair, scheme, mode and key attributes, not `class`, which smooth scrolling toggles on every scroll). Before that it is a plain paragraph. Forced colours: the text is system text and the fermata's dot is CanvasText.

### ot-measure (measure)
- Underneath: native, plus a hook that lays the lines out with pretext; the handle is a `role="slider"`.
- Anatomy: `<div class="ot-measure">` holding `.ot-measure-read` (the count and the verdict, aria-hidden), `.ot-measure-stage` with `.ot-measure-track` (a hairline, the comfortable range in the accent), `.ot-measure-handle` (the slider: a hairline down the paragraph's right edge, `.ot-measure-ring` on the track) and `.ot-measure-body` (the text once for readers in `.ot-sr`, the lines aria-hidden).
- A paragraph whose measure you set by dragging its right edge; pressing the track moves the handle there. Pretext lays the lines again whenever the width changes, so they follow the hand. The count is in the expression italic ("62 characters a line", the average character of this text, so it is what the lines really hold); under it, in pencil, the verdict: under 45 "too short to read in", 45 to 75 "comfortable" (that range is the accent on the track), over 75 "the eye loses the next line". The handle stops at the edge of its container; on a narrow screen the paragraph sets a size down so the comfortable range is still there.
- Keyboard: the handle is focusable; left and right (or down and up) step one character, Page steps ten, Home and End go to the ends. `aria-valuenow` is characters a line and `aria-valuetext` says the verdict. Focus draws the accent ring around the handle's ring.
- The count's number stands at `mf` and its words a dynamic down beside it, on one baseline. The comfortable range's ends are marked over the track in small pencil figures (`.ot-measure-at`, 45 and 75), where the page is wide enough to hold them. Right to left, the edge is the line's end on the left, and the drag and the arrows follow it. The readout is the library's English, each part its own left-to-right run, so a right-to-left page still reads "30 characters a line".
- `variant` (`data-variant`): `track` (the default), `alphabets` or `columns`.
- alphabets: after a type specimen's lowercase alphabet length. The track is a ruler of lowercase alphabets (`.ot-measure-abc`, a span a letter) in the paragraph's own face and size, measured letter by letter with its kerning, so it is a true rule for this face. The letters inside the measure are graphite, those beyond a rule's grey, and the letter the edge cuts is the accent, with the handle's hairline running down through it; there is no ring. The count reads in alphabets to the quarter ("2½ alphabets a line"); the verdict still counts characters, and `aria-valuetext` says both. The comfortable range is a hairline under the ruler. Focus draws the handle's line in the accent at stroke weight. The ruler is Latin; a right-to-left page should use the track.
- columns: after the narrow ragged columns of "Healthy habits →". The paragraph takes as many columns of the measure as its space holds (`--cols`), two ems apart (`--gap`), balanced, never more than it has lines. The handle is the first column's edge, so narrowing the line brings another column in and widening takes one away; the verdict says how many ("too short to read in, in three columns").
- Forced colours: the hairlines in CanvasText, the comfortable range and the cut letter in Highlight.

### ot-waterfall (waterfall)
- Underneath: native, plus a hook that lays the lines out with pretext.
- Anatomy: `<div class="ot-waterfall">` holding the text for readers once (`.ot-sr`) and, per dynamic, an aria-hidden `.ot-waterfall-row`: `.ot-waterfall-mark` (the dynamic, in the expression italic, pencil), `.ot-waterfall-text` (the line) and `.ot-waterfall-px` (its size).
- A type specimen waterfall: the same words at every dynamic from `from` (ffff) to `to` (pp), loudest first. Each line takes as many whole words as the measure holds at its size (pretext counts them) and never wraps or ellipsises (`white-space: nowrap; overflow-x: clip` is only a safety). Its tracking then opens by up to a twentieth of an em to reach the edge, unless the line already holds all the words. A first word wider than the line sets that line smaller instead of breaking; a quieter line is never set louder than the one above it.
- Pointing at a line shows its size in pixels in pencil at its end; on a narrow container the size takes the mark's place. `italic` sets the specimen in the expression face. It lays out again when its width changes or `<html>` changes face; before that each line is the plain text, clipped.
- `variant` (`data-variant`; none for the default, `specimen`): `decay` or `solo`.
- decay: a note after its attack. The sentence is read once instead of repeated: each line takes up where the one above stopped, a dynamic quieter, filled and tracked to the measure the same way; the quietest line says the rest and wraps as a paragraph does. A line with nothing left to say is hidden. It is still: the fall is in the sizes, not in time.
- solo: the mixing desk's solo button. Pointing at a line keeps it in ink and sends every other line back to a rule (`--ot-rule-strong`), its dynamic's mark inked and its size shown, so you hear one size alone; the colour eases (`--ot-andante`). Leaving brings every line back. A pointer aid only: the rows are aria-hidden and the text is read once.

### ot-marquee (marquee)
- Underneath: native, plus a hook that reads scroll and an elapsed-time animation clock.
- Anatomy: `<div class="ot-marquee" data-variant="ticker | counter">` holding `.ot-marquee-frame` (overflow clip, a zero minimum inline size, inside a `minmax(0, 1fr)` grid column) and the `.ot-marquee-pause` word button beneath it. The frame holds one `.ot-marquee-row` (two for counter; `data-back` on the one that runs towards the start), each a `.ot-marquee-track` of `.ot-marquee-words` lists. The first list of the first row is the one readers get (`aria-label` from `label`); the copies that fill the band are aria-hidden and inert. `--o` is how far it has travelled, wrapped to one run (`--period`).
- A band of words that drifts at 24px per second by default. Scrolling takes over immediately: its position is the accumulated drift plus how far the band has risen through the view times `speed` (0.4), read after a smooth scroller's frame. It runs back when you scroll back and resumes drifting after a short rest. Scrolling down it reads along, the words coming in at the end and leaving at the start; `reverse` turns both drift and scroll round. The duplicated track is clipped by its own frame and can never set the page's width.
- band (the default): after "Renaissance." and "Less is more.", every word a statement closed by its own full stop, and after SPECTRA, set so large in a light weight that the frame's ends crop it. Pass a dynamic class (`ot-fff`, `ot-ff`) for the size.
- ticker: small capitals, widely spaced (`--ot-space-7`), in graphite between two hairlines, after the Renaissance poster's top row and the SHAPES / GRADIENTS frame row. No full stops: these are labels, not statements.
- counter: after SPECTRA's two rows. The band twice, the upper row cut at its head and the lower at its feet, meeting on one hairline and running opposite ways during drift and scroll.
- It measures again when its width or one run's width changes (a new face or size), so it needs no watch on `<html>`. Right to left the words read and travel the other way. Reduced motion: the words stand still and wrap as one list, the copies and the second row gone.
- Autoplay (owner-approved exception, 2026-10-01): `autoplay` defaults to true; false keeps only person-driven behaviour and omits the pause control. `defaultPaused` starts it paused. The small roman `( pause )` / `( play )` button sits beneath the item at inline start, with `pauseLabel` / `playLabel` for its visible and accessible words. Explicit pause persists until play. Hover, focus within, an off-screen IntersectionObserver entry and a hidden tab suspend it; the person's scroll, drag, key or press takes over, and leaving interaction gives it 1600ms of rest before resuming. Reduced motion disables autoplay entirely and hides the unused control; `data-force="reduced"` shows that still state in docs. The clock uses rAF time deltas, cancels on unmount and never catches up hidden time.
- Autoplay states: autoplaying, paused (play available), reduced motion (still); the pause button is a separate keyboard stop with visible accent focus and native Enter/Space activation.

### ot-ribbon (text-ribbon)
- Underneath: native, plus a hook that measures every letter with pretext (`@chenglou/pretext`, loaded when it's needed); the stage is a `role="slider"`.
- Anatomy: `<div class="ot-ribbon" data-variant="wave">` holding the phrase once for readers (`.ot-sr`) and `.ot-ribbon-stage` (the slider, one focus stop), followed by the `.ot-ribbon-pause` word button beneath it. The stage holds `.ot-ribbon-plain` (the phrase, until it's laid), an aria-hidden `svg.ot-ribbon-guide` and an aria-hidden `.ot-ribbon-letters`: one span per letter and a `.ot-ribbon-dot` between each repeat, each placed by the hook and carrying `--d`, its distance from the middle of the curve, 0 to 1.
- arc (the default): after WOVE, figures set round an arc with dots on it, fading and shrinking by distance. The phrase is repeated round an arch that spans 100°, each letter at its place in the real line (kerning included) and turned to the curve. At the crest it stands at full size in ink; toward the ends it shrinks (to 58%) and falls to pencil, and it fades out at the very ends. A hairline guide (`--ot-rule`) runs 0.55em inside the letters, carrying a pencil dot between each repeat and one ink dot fixed at the crest, the "here" of WOVE's dial. The stage's height is reserved from its width in CSS (container units), so nothing moves when it's laid.
- The phrase drifts at 0.6em per second. Drag it along (sideways; on touch the page still scrolls up and down), use the keys, or scroll the page to take over. Scroll carries it 0.6 of the page's movement, read from the real layout after a smooth scroller (Lenis) has moved it. Person-driven changes have no inertia; autoplay resumes after a short rest.
- wave: after the script that sweeps through the capitals of "Less stress. More creativity.". The phrase rides a slow wave across the measure (0.6em high, a swell every 12em or more), every letter the same size and in ink, fading in and out only at the edges; the dots ride a guide under it.
- Keyboard: Left and Right move it an em, Page Up and Page Down four, Home back to where it began. `aria-valuenow` is how far round the repeat it has gone, 0 to 100. Focus draws the accent outline and turns the crest dot to the accent. The letters are aria-hidden and the phrase is read once.
- Under reduced motion neither autoplay nor scroll carries it: it shows the still curve; the drag and the keys still work. It lays out again when its width changes or `<html>` changes face (it watches the pair, scheme, mode and key attributes, not `class`, which smooth scrolling toggles on every scroll). Before that, or without script, it's the plain phrase. The letters are placed left to right one by one, so it is for Latin phrases; the drag and the arrows follow the screen, not the page's direction. Forced colours: the letters and dots in CanvasText, the guide in GrayText.
- Autoplay (owner-approved exception, 2026-10-01): `autoplay` defaults to true; false keeps only person-driven behaviour and omits the pause control. `defaultPaused` starts it paused. The small roman `( pause )` / `( play )` button sits beneath the item at inline start, with `pauseLabel` / `playLabel` for its visible and accessible words. Explicit pause persists until play. Hover, focus within, an off-screen IntersectionObserver entry and a hidden tab suspend it; the person's scroll, drag, key or press takes over, and leaving interaction gives it 1600ms of rest before resuming. Reduced motion disables autoplay entirely and hides the unused control; `data-force="reduced"` shows that still state in docs. The clock uses rAF time deltas, cancels on unmount and never catches up hidden time.
- Autoplay states: autoplaying, paused (play available), reduced motion (still); the pause button is a separate keyboard stop with visible accent focus and native Enter/Space activation.

### ot-sidebar (sidebar)
- Underneath: native, plus a hook; a sheet on narrow screens.
- Anatomy: `<nav class="ot-sidebar ot-scroll">` holding `.ot-sidebar-list` (with `.ot-sidebar-head`, groups, and a `.ot-scrollbar` as the nav's last child). A group is `.ot-sidebar-label` (`.ot-sidebar-i` the numeral or initial, `.ot-sidebar-rest` the remainder) over `.ot-sidebar-links`; a link is `.ot-sidebar-link` holding `.ot-sidebar-text`. `aria-current="page"` on the current one. `data-folded` folds the list; `data-compact` sets it a size down with the links closed up, for a long index. While folded, one `.ot-sidebar-callout` (aria-hidden, `position: fixed`, `pointer-events: none`) is placed beside whatever is pointed at or focused.
- Unfolded: words, with a dot before the current page and a ring before the one pointed at. Folded: a ruler about 3rem wide (`--ot-sidebar-rail`) on the column's own hairline. Each group keeps its roman numeral ("VI Controls" keeps VI) or else its initial, in pencil (ink for the group you are in); each link is a short tick off the hairline that stretches when pointed at; the current page's tick is the longest, with the accent dot at its far end. Both modes say the same thing: where you are, and what each thing is called.
- Pointing at a tick, or focusing it, names it in the margin: a leader line is drawn from the tick to its full name, the group's name beneath, and any `preview` (a sentence) after a beat. Pointing at a numeral names the whole group. It stays inside the window, never takes the pointer, and Escape puts it away. The words stay in the page as the link's accessible name, folded or not; the callout is a pointer aid and is hidden from assistive technology.
- The words fold away in turn (`--ot-arpeggio`) while the ticks grow; with reduced motion it is instant.
- Scrolling: the nav is the scroller and takes the scrollbar's rail, which rides the column's own hairline (`--line: 0`). Folded ticks are 1.5rem tall so each is a target.
- `variant` on the list (`data-variant`): `words` (the default), `chapter` or `numerals`. Both apply unfolded, in the column and the sheet; folded, every variant is the same ruler.
- chapter: a book's running contents, open only at the chapter you are reading. The group holding the current page stands open, its label in ink; every other group keeps only its label. A still pointer (a 240ms wait) opens one under its name, and focus opens it at once, so Tab still reaches every link; leaving closes it. The links stay in the page for assistive technology.
- numerals: "14 Where my feet stand, 08 there i take a photo". Each group's place (01, 02, a CSS counter, drawn and not read) stands large in the margin (`f` 300, tabular), in pencil, ink for the group you are in or point into. The label, a leading roman numeral and all, and the links sit small beside it (`pp` over `p`), from the numeral's cap height; the numerals share one column (subgrid), so they align. A roman numeral isn't set large: at display size a grotesque's I is a bar.
- Keyboard: links (Tab moves tick to tick and shows each name), plus the fold button you give it (`aria-expanded`, `aria-controls` naming the nav). Below 860px the same words open in a sheet and never fold.

### ot-card (card)
- Underneath: native.
- Anatomy: `<article class="ot-card" data-variant="rule | epigraph | ledger">` holding an optional `.ot-card-figure` (one giant letter, aria-hidden), `.ot-card-title` with `.ot-card-link`, `.ot-card-body`, `.ot-card-foot`, and for the ledger `<dl class="ot-card-sum">` (a `<div>` of `<dt>` and `<dd>` per line, the last the total).
- A column under a rule, not a box. The giant letter hangs from the rule with its top cut off by it, the way SPECTRA's line cuts its word, so the stroke that passes along the rule when you point at the card passes over the cut. The link's hit area covers the card; focus rings the whole card in the accent.
- Epigraph: someone else's words about the work, set before its name the way a book sets a quotation before a chapter. The quotation stands first, indented to the end of the column, in the expression italic (italic here by the book's convention for epigraphs, like `.ot-term`, not because the reader typed it), its attribution flush to the end after a short rule, as the em dash would stand. The rule leaves the top of the card and opens the title below instead, like a chapter's head, and pointing passes the stroke along it there.
- Ledger: for what something costs. The lines of `.ot-card-sum` add up in tabular figures, in a column as wide as the total; the total, large and light, is ruled off the way an account is, a single rule over it and a double rule under it, both only as wide as the figures. Nothing else changes: it keeps the rule and its stroke.
- Forced colours: the rule becomes a border, since background images are dropped.

### ot-peek (hover-card)
- Underneath: Radix HoverCard.
- Anatomy: `<span class="ot-peek"><a>Name</a><span class="ot-peek-card">` holding `.ot-peek-name` (aria-hidden), a sentence and `.ot-peek-meta`.
- The name, set large and cut by the card's top edge through its ascenders (and by its end, when long), slides in to meet you. It is decorative and not selectable (`user-select: none`): a selection would only paint a slab of yellow across the crop. It waits 450ms for the pointer; focus shows it at once. While the card is open its trigger holds the link's highlighter (`data-state="open"`), black on yellow, so you can see what the card belongs to. The card's text meets 4.5:1 on its paper in every scheme and mode: the body (graphite) 7.1 to 10.6, the meta line (pencil) 4.63 (statue, day) to 5.91, the name (ink) 11.7 to 18.9; selected, 16.5. Where anchor positioning exists, the card flips or centres rather than leave the screen.
- Variants go on `data-variant` of the card (`HoverCardContent variant`): name (the default), entry, quote.
- Entry, after "the uncreative": a dictionary entry for the word you point at. `HoverCardName` given a headword with its syllable points and stress mark (`gro·ˈtesque`) sets it heavy at `--ot-mf` and breaks it at each point with a dot (`.ot-peek-point`); the stressed syllable is reversed out of the ink (`.ot-peek-stress`, paper on ink, over 15:1). Then the part of speech in the italic (`.ot-term`, as dictionaries set it), the senses as an `<ol>` with bold figures hung in the margin, and the word's history in `HoverCardMeta`. The headword is decorative; the trigger is the word.
- Quote, after the magazine pull quote: what the person said, as a `<blockquote>` in the italic (their words, not ours) at `--ot-mp`, in ink. The opening mark hangs in the margin at the size of a title and the card's top edge cuts its tails, the name's crop moved to the mark. The attribution, in `HoverCardMeta`, is ours.
- Keyboard: focus opens every variant at once. Reduced motion: the points and the mark are simply there. Right to left: the name slides the other way and the margin (the senses' figures, the mark) is on the right. Forced colours: the reversed syllable keeps its ink as a system colour pair.

### ot-tip (tooltip)
- Underneath: Radix Tooltip.
- Anatomy: `<span class="ot-tip">` holding the control (with `aria-describedby`) and `.ot-tip-text`.
- A whisper in parentheses above the thing it names. The parentheses are thin (200) and taller than the words, in ink, as 20(25) sets them round its figures, so the whisper reads as an aside held apart. It waits for a still pointer; focus shows it at once. Escape sets `data-hush` until the pointer or focus leaves.
- Variants go on `data-variant` (`TooltipContent variant`): whisper (the default), initials, beside.
- Initials, after "the uncreative" reversing part of its word: for a key or an abbreviation. The letters the control shows are marked with `<b>` in the whisper's words and reversed out of the ink (paper on ink), so the whisper shows where G, or CMYK, comes from. Screen readers hear the words whole.
- Beside, after the small notes hung beside "It has to be design.": the whisper on the control's own line, after it, on a hairline that runs from the control, with no parentheses (the line holds it apart). It sits at the line's end: the right, or the left on a right-to-left page (read from the page as it opens; pass `side` on a mixed page). Whichever side Radix settles on, the line faces the control; flipped above or below, the line is dropped.
- Reduced motion: the initials and the line are simply there. Forced colours: the line is drawn in CanvasText and the initials are reversed in Canvas on CanvasText.

### ot-sheet, ot-drawer (sheet, drawer)
- Underneath: native `<dialog>`, through the dialog item.
- Anatomy: `<dialog class="ot-sheet" closedby="any">` with `.ot-sheet-spine` (the title again, aria-hidden). `<dialog class="ot-drawer" closedby="any">` with `<button class="ot-drawer-handle">`. Both share the dialog backdrop.
- A sheet is a page slid in from the end edge, its title running up the spine like a book's (`ot-spine`), in its own column: the sheet's start padding, on the left, or the right in right-to-left. A drawer rises from below and lands with spiccato; its handle is the fermata's arc. Dragging the handle down sets `--pull` and `data-pulling`, and past a threshold it closes.
- Keyboard: Escape closes; the handle closes on Enter. Smooth scrolling pauses while open.
- Sheet variants go on `data-variant` (`SheetContent variant`): spine (the default), shelf, rag, fold.
- Shelf, after books standing on a shelf: a sheet opened from inside a shelf sheet stands in front of it, one spine column narrower, so the spine behind stays in view, set back to pencil, and is the way back: pointing at it (the bare backdrop) or Escape puts the front sheet away and focus returns to the control that opened it. Only the front sheet blurs the page. Below 40rem the column is space-7 and the spine mf.
- Rag, after "Healthy habits" cut from its paper and "Less is more." set flush right: the words stand flush to the window's edge and rag toward the page, and the paper is cut to that rag, a step for every line, with a hairline along the cut. The script reads the line boxes (after the fonts), draws `<svg class="ot-sheet-rag" aria-hidden="true">` behind them and sets `data-laid`; until then it is plain paper with its edge. The box hangs from the top only as tall as its words, and a click on its bare part is a click outside. Start and end sides only. It re-cuts on resize and when `<html>` changes its face. Forced colours: Canvas paper, CanvasText cut.
- Fold, after the index entry that opens to its page and "Less is more." set between its hairlines: the row that opened it unfolds into the page. Before it opens (and again before it closes) the sheet writes the opener's box to `--fold-t/r/b/l`; the page is clipped to that band and opens out to the window, the row's two hairlines (ink, `::before` and `::after`) riding the clip's edges to the top and the foot, while the row's name (its `rows-title`, or the trigger's own words) grows into the title, set at `--ot-ff` (`--ot-f` below 40rem), by a transform measured from one to the other so their first lines meet. The rest arrives once there is room. A reversed row opens from its ink (`data-from-ink`: the page starts ink and washes to paper). Put away, it folds back into the row and the title flies back to the name. The whole window, no spine; `side` is ignored. The trigger remembers itself (`SheetTrigger`), so open it from `<Row asChild><SheetTrigger>` with one Sheet round the Rows; opened by state alone, a line across the middle parts. Reduced motion: it opens at once. Forced colours: the lines in CanvasText.
- Panels (`SheetPanels`, `.ot-sheet-panels` holding `nav.ot-sheet-spine.ot-sheet-trail` and `section.ot-sheet-panel` pages): pages inside one sheet, the chapters of the book on its spine, and the scale contrast of "It has to be design.". The spine becomes the trail, read up from the foot (right to left as well): the names you came through small (`mp`) in the pencil, the one you are in large (`f`, 200) in ink, `aria-current="page"`. Stepping in (`SheetPanelLink to`), the name you left shrinks into the trail and the new one writes up the spine; the new page slides in from the sheet's own edge while the old one leaves the other way, the two crossing in one grid cell (`hidden` and `inert` on the pages you are not in, the exit kept by `display` allow-discrete). The small names are buttons and the way back. Focus goes to the new page's heading, and going back returns it to the link that stepped in; the sheet scrolls to the top. Each opening starts at the root, whose title names the dialog. Below 40rem the trail is `mf` over `p`. It belongs to the sheet, not the drawer: a sheet is already a page with a spine to carry the path, where a drawer is a tray whose height the thirds decide.
- Drawer variants go on `data-variant` (`DrawerContent variant`): arc (the default), thirds, solid.
- Thirds, after SPECTRA's "1/3": the drawer stops at a third, two thirds or the whole height, and the share stands at the top end corner as a Fraction (aria-hidden), thin and large. The handle is then `role="slider"` (vertical, 1 to 3, "2 of 3"): drag it to the nearest third, or lower than half a third to put it away; a tap or Enter raises it a third, round to one; the arrow keys, Home and End step it. Each opening starts at a third.
- Solid, after the compositor's leads: pulling the arc first takes the silence out between the drawer's parts (`--solid` from 0 to 1 closes the gaps and the padding), as type is set solid when the leads come out; only once it is set solid does the drawer itself move, and letting go past that closes it. Its give is the height it loses, measured on pointerdown. Keyboard as arc.

### ot-collapse (collapsible)
- Underneath: native `<details>`.
- Anatomy: `<details class="ot-collapse">` whose `<summary>` is the tail of a list ("and 4 more"), then `.ot-collapse-list`.
- A list that ends in the rest of itself. The rest opens at reading speed through `::details-content`, and its lines arrive in turn.
- Keyboard: native.
- Variants go on `data-variant` (`Collapsible variant`): tail (the default), catchword, sotto. Tail's words are set as the list's caption, pp, straight under the last rule. Catchword and sotto set their summary as `.ot-collapse-cue` with two spans (the words, then `openLabel`).
- Catchword, after the printer's catchword: the first name of the rest waits at the foot, flush to the far edge, as the next page's first word waits under the last line. Opening, it steps back to the start (the summary is a container, so it travels `100cqi` less its own width) and grows into the first row of the rest, which follow it. Give the summary an `aria-label` that says what it does ("Show 4 more, from Tidewater").
- Sotto, after SPECTRA's fine print and the score's sotto voce: the rest is never hidden, only said under the breath, as one run of pp pencil fine print; the whole run is the control and inks when pointed at. Opening says it in full: each name grows into its own row, in turn, and the words to set it small again follow. The summary lies over the run in the same grid cell; its words are visually hidden while closed.
- Reduced motion: it opens at once. Right-to-left: the catchword waits at the left. Forced colours: rules and text keep their system colours.

### ot-resize (resizable)
- Underneath: hook (a separator you can drag or move with the arrow keys).
- Anatomy: `.ot-resize` holding two `.ot-resize-pane`, `<div class="ot-resize-handle" role="separator" tabindex="0" aria-valuenow>` between them, and `.ot-resize-dim` (aria-hidden). Script sets `--split` (a percentage) and `data-dragging`.
- Take the rule and it inks; while held, each pane's share is drawn as a dimension, after Paul Rand.
- Keyboard: Left and Right move it by 5, Home and End go to 20 and 80.
- The frame is a construction line, dotted in rule-strong, after Rand's working drawings: it marks where the panes may go rather than boxing them.
- Variants go on `data-variant` (`ResizablePanelGroup variant`): rule (the default), fit, flow.
- Fit, after "It has to be design." set heavy and condensed, and wood type locked up to the measure: each pane's `<h3 class="ot-resize-title" data-slot="resizable-title"><span>` is set in 800 to fill its pane edge to edge. The script moves Archivo's width axis first (62% as the pane narrows, 125% as it widens), and changes the size only past those ends, so narrowing a pane condenses its word before it shrinks it. It sets `data-set` once measured, and re-sets on every resize and when `<html>` changes its face.
- Flow, after the newspaper's continued column: the group's `text` runs through the panes as `.ot-resize-flow` paragraphs of `.ot-resize-line` lines (aria-hidden; the whole text once, in the first, as `.ot-sr`). The first pane holds as many lines as its height does, and the rest carry on at the top of the next, at its measure, the first of them in ink; move the rule and the break moves. pretext lays the lines; until it has, the first pane holds the plain paragraph. The group takes a fixed height (17rem).
- Forced colours: the rules and dimensions are drawn in CanvasText (Highlight when taken).

### ot-scroll (scroll-area)
- Underneath: native overflow, with the scrollbar.
- Anatomy: `<div class="ot-scroll" data-slot="scroll-area" data-variant="ruled | catchword | wheel" tabindex="0" role="region" aria-label>` holding two rails last (catchword puts `<div class="ot-scroll-foot" aria-hidden="true"><span class="ot-scroll-catchword"></span></div>` before them): a `.ot-scrollbar` down the side and a `.ot-scrollbar[data-axis="x"]` along the bottom, each hidden until there's something to scroll its way. The rail also sets `data-lenis-prevent` on it while there is something to scroll down, so smooth scrolling leaves it alone.
- It wears the page's rail, not a lighter one: 1.5rem wide with the hairline 0.5rem in (`--line`), an ink thumb as long as the view. `sections` (`{ id, num, name }[]`, one per element inside with that id) put a tick on both rails: pointing at the rail brings their numbers down it in turn, pointing at a tick names it, pressing one scrolls there (at once with reduced motion), and the section in the middle of the view is ink. A section too near the end to reach the top keeps its own place inside the thumb's last stretch, so the last ticks never pile up. The box is short, so each number leans into it as its tick nears an end (by `--at`); sideways, the ticks rise from the rail with their numbers above. With no sections it is the bare rail.
- A rule appears at an edge only while there's more beyond it. Pure CSS: paper backgrounds that scroll (`background-attachment: local`) cover rules that don't.
- Catchword, after the printer's catchword (the first word of the next page set alone at the foot of this one, so the reader goes on): while there's more below, a foot line of paper (`.ot-scroll-foot`, sticky, 1.625rem, the rule on its lower edge) rides the bottom of the box and the text passes under it; on it, at the far end and clear of the rail, waits the first word whose line runs under the foot, in pencil at `--ot-pp`. Script (`useCatchword`) finds it by walking the box's text on scroll, resize, change and font load, skipping anything aria-hidden, and sets `data-idle` when there is none (at the end the word and the rule go). Each new word turns in (`data-turn`: rises 0.6em and fades up, allegro, exhale). Pointing inks it; pressing it turns the box so that line stands at the top (smooth, at once with reduced motion) without moving focus. It is a pointer aid, hidden from assistive technology: the word is in the box.
- Wheel, after WOVE, where numbers ride an arc, shrinking and fading by their distance from the chosen one: the children of the box's first child (the rows of one list) turn on an arc as the box scrolls. The row in the middle stands at the start edge, full size, in ink; toward the top and bottom the rows fall back along the curve toward the rail by up to `--ot-scroll-arc` (`--ot-space-7`, offset by the square of the distance), shrink to 0.84 and step back through graphite and pencil to the strong rule. Each row runs on its own view timeline (`animation-timeline: view()`), so the wheel keeps time with the scroll, smooth scrolling included, and nothing moves at rest. The box keeps `--ot-scroll-arc` clear at its end so no row is cut, and hides sideways overflow. Right-to-left bows the other way. With reduced motion only the ink changes.
- Every scroller in the library carries the rail: the command list (so the combobox too), the dialog, sheet and drawer, the thread and the sidebar. Nothing on the site scrolls on the browser's own bar. Code and text areas don't scroll at all (they wrap and grow); the native select's picker and the carousel's track hide the bar.

### ot-scrollbar (scrollbar)
- Underneath: hook (`useScrollbar`).
- Anatomy: `<div class="ot-scrollbar" aria-hidden="true"><span class="ot-scrollbar-thumb"></span></div>` placed anywhere inside a scroller (it finds the nearest one around it: a cmdk list keeps it inside its sizer). `data-axis="x"` runs it along the bottom of a box that scrolls sideways (right-to-left reverses it: `--dir`). `data-variant="page"` fixes it to the window's inline end instead, and takes one `<span class="ot-scrollbar-mark" data-num data-name style="--at; --i">` per section. `data-variant="numeral"` and `data-variant="leaves"` are inner rails with another look (down the side only); leaves adds `<span class="ot-scrollbar-leaves">`, which the script fills with one `<span class="ot-scrollbar-leaf" data-leaf="3/7">` per disc.
- Script sets `--view` (the share in view, with a thumb of at least `min` px), `--max` (how far the box scrolls), `--dir`, `data-idle` when there's nothing to scroll, then `data-ready`; it then marks the host `data-scrollbar-host` (`="pin"` when it also had to be given `position: relative`) and, while there is something to scroll, `data-lenis-prevent`. It re-measures on resize and on any change inside the box, including its content growing or a disclosure opening; scrolling uses the saved measurements. It turns on only for a fine pointer with scroll timelines; otherwise the thin native stroke stays.
- Page scrolling optionally goes through `window.__otScrollTo(target: number, immediate: boolean)`. Install this adapter to send page marks and dragging through a smooth scroller; dragging passes `true`, so it stops any active easing and follows the pointer at once. Without it the page uses native scrolling. Inner rails always stay native. The item has no site or smooth-scroller dependency; the site exposes `scrollPageTo` through this hook and removes it on unmount.
- The site has one page rail, in the root layout (`PageRail`, which is `ReadingTrail variant="rail"`): elements with an `id` and `data-rail="Name"` become its marks, numbered in order.
- A ruler: a hairline and an ink thumb as long as the view. Inside a scroller, the rail is pinned by the scroller's own timeline (`animation-timeline: scroll(nearest)`, translating by `--max`), so it stays on the edge with no script running while you scroll. The thumb rides the same timeline. On the page, a mark shows where each section begins, and the current one is ink (`data-now`).
- Pointing sketches: pointing at a scroller darkens its rail; pointing at the rail thickens the thumb, and on the page the numbers arrive down the rail in turn, with a mark's name when you point at it. Holding the thumb (`data-dragging`) inks it in the accent, because it marks where you are.
- Pointer only: pressing a page mark goes to its section, pressing the rail centres the thumb there, and the thumb drags. Pressing doesn't move focus, so an open list stays open. The keyboard scrolls as always, which is why the rail is hidden from assistive technology.
- Down the side of a box, a mark's number leans into the box as its mark nears the top or bottom (by `--at`), so the first is never cut off by the box's top edge; the page's rail is tall enough not to.
- Numeral, after "the silence that heals" (14 / 08), where numbers are the data: the thumb is a figure, how far down you are from 00 to 100 (`decimal-leading-zero`, tabular, `--ot-p`), riding the hairline on a 0.375rem ink dot. It counts through every number as the box scrolls: a counter on a registered `--ot-scrollbar-read` that the scroller's own timeline drives, so it keeps time with smooth scrolling and needs no script while you scroll. At rest the figure is pencil; pointing inks it and swells the dot; holding (or dragging it) puts both in the accent. The rail is 3.25rem wide. Section marks work as on the ruler.
- Leaves, after the "Less but better" calendar (gone, today, to come): no thumb, but a disc for every screenful (a leaf) of the box, stacked down from the top of the rail, 0.625rem on a 1.125rem step. Those you've read are ink (`data-read`), the one you're on is the one accent (`data-now`), those to come are hairline rings. When they won't fit down the rail, a disc holds as many leaves as it must. Script lays them on resize and change and marks them on scroll. Pointing at a disc swells it and names its place ("3/7"); pressing it turns the box to that leaf (smooth, at once with reduced motion).
- Forced colours: the rail keeps its own colours (`forced-color-adjust: none`), remapped to CanvasText, GrayText and Highlight, because the thumb, the dot and the discs are drawn as backgrounds.
- Once the rail is running, the host's own bar is gone (`scrollbar-width: none` on `[data-scrollbar-host]`). Without the rail (touch, or before the script) every scroller gets a thin stroke on a clear track (`scrollbar-color` from `:root`, `scrollbar-width: thin`) that darkens from rule to pencil when pointed at; Safari, which lacks `scrollbar-color`, gets a hairline thumb that thickens.

### ot-trail (reading-trail)
- Underneath: hook (reads the window's scroll), composed of `item` and, for the rail, `scrollbar`.
- Anatomy: `<nav class="ot-trail" data-variant="contents | rail" aria-label="On this page">` holding `ul.ot-items.ot-trail-list` of `li.ot-item.ot-trail-step` (`data-state="read | now | ahead"`), each a link `a.ot-trail-link` (`aria-current="location"` on the one you are in) with `.ot-trail-num` and `.ot-trail-name`, the item's leader, and its folio at the end (aria-hidden). Script sets `--ot-trail-read` (0 to 1, how much of the section you are in is read) on the root. The rail adds `p.ot-trail-head` (aria-hidden) and a `ot-scrollbar` with `data-variant="page"`. `pinned` fixes the place for documentation. With no sections the root is a plain `div`, not an empty landmark.
- A contents page that reads along with you: each section's number and name, a dotted leader, and where on the page it is reached (00 to 100), as a book's contents give the page. What you've read keeps its leader in ink and its name in pencil; the section you are in has its number in the accent, its name and folio in ink, and its leader inks as far as you've read it; what's ahead waits on the dots. A section counts as reached when its top meets the middle of the window, as the scrollbar marks it; those too near the end to reach it share the last stretch.
- Contents (the default), after contents pages and SPECTRA's numbers-as-data: the list above, for a side column or the head of a page.
- Rail, after the title on a book's spine and the page scrollbar (Paul Rand's dimension lines): the scrollbar already marks where each section begins; the trail adds which one you are in. Its number (accent) and name run down beside the rail, set vertically like a spine, and turn in when you reach the next section. The head steps aside while you point at the rail, where the scrollbar's own numbers arrive. For the keyboard and screen readers, who can't use the rail, the contents stay in the page and come out beside the rail when focus reaches them. `--ot-trail-top` keeps both clear of a fixed bar. The head shows only where the rail does (a fine pointer and scroll timelines).
- Keyboard: the links are the page's own anchors. Right to left the leader inks from the right and the rail's head moves to the left edge. Forced colours: the current number is Highlight.

### ot-ratio (aspect-ratio)
- Underneath: native `aspect-ratio`.
- Anatomy: `<div class="ot-ratio" data-variant="crop | diagonal | square" data-orient="landscape | portrait | square" style="--ratio: 1.7778">`, with a `ot-fraction` naming it (aria-hidden; a `.ot-sr` says "16 by 9"), and for the square `.ot-ratio-rest` holding the remainder's fraction. `--ratio` is a registered number, so it eases; registered, it doesn't inherit, so `--r` carries it to the parts and pseudo-elements. The fraction keeps to the frame (`min(--ot-f, 17cqi)`).
- A frame kept to a ratio and marked like a printer's crop: short lines outside each corner and nothing between them, no border. Change `--ratio` and the frame eases to it while the fraction rolls.
- Diagonal: the paste-up artist's scaling line, a hairline from the foot of the start edge to the head of the end edge. Any frame whose corner lies on it has the same ratio, which is how a picture was scaled before software. The ratio is written along the line, standing on it (`rotate(-atan2(1, --r))`), so as the frame eases the line and the words swing together. Mirrored in right-to-left.
- Square: the largest square is ruled off from the start edge, or from the head when the frame stands tall, the way a book designer finds the square in a page and the rectangle it leaves. The ratio sits in the square; what's left is named by its own ratio in the pencil (16 : 9 leaves 7 : 9, 4 : 5 leaves 4 : 1). The rule is a background placed at `100% / --r`, so it glides as the frame eases, and its length is clamped to nothing at 1 : 1, where there is nothing left. The remainder's name fades back in once the rule has arrived.
- Forced colours keep the marks and lines (they are background images) in CanvasText.

### ot-figure (figure)
- Underneath: native `<figure>` and `<img>`, plus a hook that notices a picture that couldn't load.
- Anatomy: `<figure class="ot-figure" data-variant="plate | margin">` holding a `ot-ratio` frame (`.ot-figure-frame`, the aspect ratio's crop) with the `<img class="ot-figure-img">` and `.ot-figure-alt` (the alt text again, aria-hidden), then `<figcaption class="ot-figure-caption">` with `.ot-figure-number` (a `.ot-sr` "Figure " before it) and a `ot-meta` row (`.ot-figure-lines`) of `.ot-figure-text` and `.ot-figure-credit`. `data-missing` marks a picture that failed.
- The type-led answer to image masking: the job of framing a picture, without its silhouettes. The picture is cropped to a ratio (3 : 2 by default, the 35mm negative; `position` holds the subject) and marked like a printer's proof, the aspect ratio's trim marks outside its corners and no border. Then it is named in type, as "the silence that heals" sets its camera and its archive under its picture: the number as data (`--ot-mp`, light, tabular), the caption in the voice, and the credit in the pencil at the far end of the row, held apart by the meta row's flexing hairline. No filter, no mask, no hover zoom: the picture is shown as it is. Change `ratio` and the frame eases to it, the picture recropping inside.
- A picture that can't load leaves its frame: the marks stay and the alt text is set inside them in the pencil, the way a layout holds a place for a picture to come. The `<img>` stays for readers.
- `variant` (`data-variant`; none for the default, `plate`): `margin`.
- margin: a side caption, as a book sets one in the columns kept for notes (3 of 12, a `--ot-space-6` gap clear of the marks). The number stands at the head, larger and lighter (`--ot-mf`, weight 200), level with the picture's top; the caption and the credit stand at the foot, level with its foot, one under the other. Where the two can't stand side by side (the picture under 20rem, the caption under 9rem) the caption falls under the picture. Right to left the margin is on the right.
- Nothing to focus: a figure is read, not used.

### ot-carousel (carousel)
- Underneath: scroll snap, plus a hook.
- Anatomy: `<div class="ot-carousel" data-variant="poster | line | shelf" role="region" aria-roledescription="carousel">` holding `.ot-carousel-track` (scroll-snap, `tabindex="0"`) of `.ot-carousel-slide` (`role="group"`, "n of m", `data-current` on the one you're on) with `.ot-carousel-title`, then `.ot-carousel-nav` with ← and → buttons around `.ot-carousel-count` (`.ot-carousel-now`). On the shelf each closed slide also holds `.ot-carousel-spine`, a button over it.
- One poster at a time, each name set so large it is cropped: it sinks under a hairline that cuts off its feet, the way SPECTRA's rule crops its word, and a name wider than the frame runs off its end. The count rolls the way you travel; the slide whose start edge is nearest the track's start is the one you're on, read on scroll, so it stays true while you swipe.
- Line: every name runs on as one line of display type, each closed by a full stop, and you read along it. The name at the start is the one you're on: it inks, its full stop takes the accent and its facts appear under it; the rest wait in pencil, the next one cropped by the frame's end. A spacer after the last name lets it, too, come to the start, the end of the line. Forced colours set the waiting names in GrayText.
- Shelf: the slides stand as spines, a hairline between each, their names running up them in the pencil like books on a shelf (the sheet's spine, made a whole shelf). The one you take out widens and turns to face you, its name sinking under its hairline and cropped by the next spine; the one you put back narrows into a spine. The track doesn't scroll. Pointing at a spine inks its name; clicking takes it out.
- Keyboard: Left and Right on the track, Home and End, or the buttons. Keys in inputs, textareas, selects and editable text stay with those controls; a key already handled by a slide stays handled. The spines are pointer targets only (`tabindex="-1"`): the keyboard has the track and the buttons.

### ot-segue (segue)
- Underneath: native, plus a hook. With `scrub`, it reads the scroll.
- Anatomy: `<div class="ot-segue" data-variant="horizon" data-scrub>` holding one `.ot-segue-scene` per scene (`data-current` on the one showing, `data-label` its name; during a crossing `data-part="from | to"`), each around a `SegueScene` (`.ot-segue-body`, a named group when it has a `label`); then an aria-hidden `.ot-segue-line` with its `.ot-segue-caption` (the number, then the name), and a polite `.ot-sr` that says "2 of 3: Theme" when the scene changes. While crossing the root carries `data-phase="cross | scrub"`, `data-edge` (`left | right | bottom | top`, the edge the line comes in from) and `--ot-segue-p` (0 to 1, registered, so the pressed crossing is one transition).
- One scene at a time, as a film cuts from shot to shot with a wipe. The scenes stand in one cell, so the frame is as tall as its tallest scene and nothing below it moves. Change `value` and one hairline in ink crosses the frame (`--ot-andante`, `--ot-breath`), carrying the next scene's number and name in small type on its trailing side, as the SHAPES / GRADIENTS rule carries a date and a name. Behind the line the next scene is already there, drifting its last `--ot-segue-drift` (27px) into place; ahead of it the last scene is pushed on by as much. Going back, the line crosses the other way. A second change mid-crossing arrives at once and crosses again from there. At rest there is no line, no frame and no chrome: only the scene.
- It is the one hairline scene change for every dissolve (wave-wipe, dither-dissolve, grain-dissolve, pixel-swap): the change is the line, and it moves only when the person does.
- horizon (`data-variant="horizon"`): after Eclipse, the soft side of one level line. The line rises from the foot and the next scene comes up under it, its name just under the line at the start; going back, it sets from the head.
- scrub (`scrub`, `data-scrub`): the crossings follow the scroll, after the scrub gather. As the frame's middle rises from four fifths of the way down the view to one fifth (or as far as the page can scroll), it passes through every scene in turn; the line stands as far across as the scroll has gone, stops when the scroll stops and goes back when you scroll back. The scene past halfway is the current one. It is read from the real layout in a frame asked for by the scroll event, which runs after a smooth scroller's own frame, so the line and the page move together. Every scene stays with readers, in order (the hidden ones are transparent, not removed), and there is no announcement.
- Keyboard: the scenes hold their own controls; the ones not showing are `inert` and hidden from readers outside a scrub. In a scrub all text remains readable in order, but inactive scenes accept no pointer activation and their controls leave the tab order. If focus is in a scene as it becomes inactive, it moves to the current scene's wrapper without scrolling. The control that changes the scene is yours: a quiet button, a key, an answer.
- Right to left, the wipe comes in from the right. Reduced motion: the scene changes at once and nothing travels; a scrub changes halfway. Forced colours: the line is CanvasText and the caption drops its halo.

### ot-table (table)
- Underneath: native `<table>`.
- Anatomy: `<table class="ot-table">` with header `<button>`s inside `<th aria-sort>`, numeric cells marked `data-num`, `.ot-table-name` for the row's name, and `<input type="checkbox" class="ot-table-pick">` per row plus one to choose all.
- Hairline rows and tabular figures. The sorted column is set in ink (`data-sorted`). Re-sorting, the rows glide to their new places (FLIP: `TableBody` measures each row's `offsetTop` after every render and animates the difference, andante on the breath; still under reduced motion). Choosing a row fills its ring with spiccato and its name turns italic (`data-picked`); the foot counts the picks.
- `variant` on the table (`data-variant`): `ink` (the default), `forte` or `cross`.
- forte: SPECTRA's giant type against tiny data. The sorted column is also set loud, in large thin figures (`mf`, weight 250; `mp` below 40rem), on the same baselines as the small print of the rest. Re-sorted, the loudness passes from one column to the next (moderato, breath) as the rows glide.
- cross: a road atlas's distance chart. Point at a cell, or focus something inside it, and its row and its column cross in ink, their headings too; the cell where they meet is the accent, the one place you are; the rest steps back to pencil. It is a reading aid only: every figure reads in full without it, and screen readers get the table's own headers. Written for up to eight columns (one rule each); below 30rem the chart steps down to small print so it keeps its columns. Forced colours: the meeting cell is Highlight.
- Keyboard: native buttons and checkboxes; in a cross chart, focus inside a cell crosses it.

### ot-data-table (data-table)
- Underneath: `table`, `pagination` and `select`, composed; native controls throughout.
- Anatomy: `<div class="ot-data-table" data-variant="folio | tail">` holding `.ot-data-table-filter` (a sentence, "Show [all] projects", its chosen word a `ot-select`), the `ot-table`, and `.ot-data-table-foot`: `.ot-data-table-count` (`role="status"`, "1 to 8 of 24 projects") and either the folio pager or, in a tail, `.ot-data-table-more`. Rows that come into view carry `data-arriving` and `--k`, their place in the turn.
- The filter is a sentence, not a toolbar: the chosen word is italic, as yours, and the noun ends it. Narrowing returns to the first page and the rows that stay glide to their places, as the table's do on a re-sort; the sorted column is in ink (forte sets it loud). Pressing a heading sorts by it, a numeric column largest first; pressing again turns the order round.
- `variant`: folio (the default): a page at a time; the count stands at the start of the foot line in pencil, the book's folio (the page over the total, `pagination`'s folio) at its end. Turning a page keeps focus in the pager, and the new page's rows arrive in turn. tail: the table ends in the rest of itself, as the collapsible does: "and 16 more" is the control, straight under the last rule; the next rows arrive in turn under it, and once all are shown it says Show fewer.
- Empty: a filter that keeps nothing says so in a line ("No print projects.") and offers "Show all projects"; there is no picture.
- Keyboard: native buttons, links and the select. Reduced motion: the tempos fall to nothing, so rows simply appear.

### ot-chart (chart)
- Underneath: our own markup, plus a hook.
- Anatomy: `<figure class="ot-chart" data-variant="stems | spark | isotype" style="--n: 9; --m: 1">` holding `.ot-chart-read` (`.ot-chart-value`, a large rolling number, and its label), `.ot-chart-plot` of `<button class="ot-chart-bar" style="--v: 0–1" aria-label>`, then `.ot-chart-axis`. `data-now` marks the current bar. Spark renders spans instead (phrasing content, so it can sit in a `<p>`), the plot first and the reading after it; isotype's bars each hold `<i>` dots (`data-on`, `data-top`) and it ends with `.ot-chart-key`.
- stems (the default): hairlines and dots against one very large number, as the posters set tiny data beside giant type. The number is as large as the chart allows (16% of its width, between `--ot-ff` and `--ot-fff`), so the scale contrast is SPECTRA's. Pointing at or focusing a bar inks its line, swells its dot and rolls the number to it; leaving rolls it back to now. The current month is the accent.
- spark: Tufte's sparkline, a chart the size of a word, set inside the sentence that talks about it. The stems stand on the baseline as tall as a capital, spanning the data's own range so the shape shows at that size; the accent dot sits on now, as Tufte marks the last point in red, and the number follows in the text's own size at weight 500, with "visits in September" after it as part of the line. Pointing rolls the number, as in stems. The stems are small targets, which the inline exception allows; each is still a labelled button for the keyboard.
- isotype: Otto Neurath's rule, count, don't scale. Each bar is a column of dots and one dot is a fixed amount (`each`, by default a tenth of the ceiling): what was had in ink, the room left to the ceiling in hairline rings, so the grid of discs is the picture, as in "28 December". Now's top dot is the one accent. A key under the axis says what a dot counts ("One dot, 500 visits"). Pointing at a column sets every other column back to rule-strong and counts its dots up from the bottom, one after another, as the number rolls.
- Series (`series`, stems): two or more read at once, each its own voice. The stems are solid, dotted and dashed, topped by a ring, a disc and a ring; the readout names them roman, italic and pencil, as "It has to be design." pairs the faces, each name after a short swatch of its line. Grouped (the default), a column's stems stand side by side a `--ot-space-2` apart, now's first dot the accent; `stacked`, one stem per column is cut into a length per series with a dot at every joint, and the top joint is the accent. Each is a `.ot-chart-mark` (`data-series`, `--b` and `--v` from 0 to 1) inside the column's button. Written for up to three.
- The readout for several series: the one giant number becomes a short list (`.ot-chart-read[data-list]`: `.ot-chart-at`, then `.ot-chart-list` of `.ot-chart-row`s, each a `.ot-chart-value` and a `.ot-chart-name`). The figures stand flush right in one column at `--ot-mf` to `--ot-f`, weight 200, as on a ledger, and each rolls on its own, only if it changed. Stacked, a hairline is ruled under the figures and the sum stands beneath it ("39 enquiries in all"), a sum set as on paper.
- Horizontal (`orientation`, stems; `data-orientation="horizontal"`): a ledger. The whole names stand in a column at the start, pencil, and each line runs out from an ink baseline on the start edge to its dot, one row (`--ot-space-6`) each, rules at the quarters; the name the number reads is inked. Series stack or group along the row the same way.
- Keyboard: Tab enters the plot at the bar the number is on (one tab stop, a roving tabindex); Left and Right, or Up and Down, move to the next bar, Home and End jump to the ends. Right to left, Left and Right follow the page. Focus rolls the number as pointing does.

### ot-meter (meter)
- Underneath: native `<meter>`, named by a native `<label>`. A known reading within limits, such as storage used or a budget balance; use progress for completion and slider for input.
- Anatomy: `.ot-meter` holding `.ot-meter-label`, `.ot-meter-scale` (the visual reading, rule, index and two limits, all `aria-hidden`), a visually hidden native meter, and optional `.ot-meter-note`. Every part carries `data-slot`.
- Creative move: Paul Rand's dimension lines. A large italic figure stands above a hairline between two end ticks; one accent index marks the exact reading. The empty measure stays empty. The space on either side of the figure shares the remaining width in proportion to the reading, keeping it inside both limits without measuring in script. Longer readings step down from ff toward mf to fit their measure, using the formatted length and container width; exceptionally long text still wraps in flow above the line rather than covering it. Labels and notes wrap too. Units and limits are roman; the reading is yours, in italic.
- `value` is clamped to finite `min` and `max`, shared by the visible reading and native meter. Negative ranges work; non-finite values, an overflowing span and max not greater than min throw a RangeError. `format` sets all three figures and `unit` follows them as supplied. `low`, `high` and `optimum` retain the native semantics without introducing another colour.
- The formatted reading names the value through `aria-valuetext`; callers can override it. The note joins any supplied `aria-describedby`. `id`, `ref` and other native meter props reach the meter; `className`, `style`, `hidden`, `dir` and `lang` apply to the root. It is a reading, with no tab stop or keyboard interaction.
- Motion: legato. When the reading changes, one eased number drives the space around the figure and the index at moderato, so they glide together and an interrupted update continues from the current position; there is no entrance or autonomous loop. Reduced motion changes directly. Flex and logical positioning mirror the scale in right to left, including a locally overridden direction. Readings and limits use left-to-right `bdi`, so even a signed number without a lettered unit keeps its sign before the number; localized text retains its own bidi marks. Forced colours keeps the index in Highlight.

### ot-stat (stat)
- Underneath: native `<dl>`; each `Stat` is a `<div>` of `<dt>` (what it counts) and `<dd>`s (the figure, and a note).
- Anatomy: `<dl class="ot-stats" data-variant="beside | grid" style="--row-len">` of `<div class="ot-stat" style="--len">` holding `.ot-stat-label`, `.ot-stat-figure` (a `ot-fraction` with no total, set in the stat's own face: roman, thin, the cell's size; its figures turn on their own wheels and it is read whole) and `.ot-stat-note`.
- crop (the default): SPECTRA's giant thin figures (weight 200), set as large as the cell allows; one hairline runs under the whole row and cuts off their feet (text-box trimmed to the cap height), the name small beneath. A row shares one size, set by its longest figure (`--row-len`), so the figures stand on one line. Numbers are grouped by a thin space, as SI sets them, since the crop would cut a comma's tail.
- beside: WOVE's 03 and the "14/08" of "the silence that heals": the figure heavy (700) and whole, its name and a line about it set beside it, their caps on its cap line. The stats stand in a list, figures flush to one edge in tabular figures so the units line up, the words in one column.
- grid: "Less is more.": each stat a cell of a hairline grid, the lines between cells only; the name in the cell's first corner, the figure in the far one.
- A changed value turns over like a counter's wheels (the Fraction's): only the digits that changed turn, the units first and each carry one arpeggio behind, down for a smaller value and up for a larger; a figure that gains or loses a place turns over whole. Nothing moves until the value does.

### ot-radial (radial-chart)
- Underneath: our own markup, plus a hook.
- Anatomy: `<figure class="ot-radial" data-variant="ring | horizon" style="--n: 3" aria-label>` holding `.ot-radial-face` (`aria-hidden`) of one `ot-ring` per series (`style="--i"`, and `data-shown` on the one the number reads), `<figcaption class="ot-radial-read">` (`.ot-radial-value`, a large rolling number, then `.ot-radial-words`: `.ot-radial-name` and `.ot-radial-of`), and, with more than one series, `<ul class="ot-radial-key">` of one `<button>` per series.
- The ring, exported as `Ring` so the timer and the pie chart stand on it: `<span class="ot-ring" data-head="end | start" style="--ot-ring-p; --ot-ring-from" aria-hidden="true">` holding `.ot-ring-head`, a zero-width radius rotating about the ring's centre so its invisible box never projects beyond the circle. The calendar's vocabulary: a hairline ring in rule-strong for the room still to go, the arc inked on it at `--ot-stroke` for what was had, and a dot at one end of the arc. Both strokes are inset box-shadows cut by a conic mask, as the dot calendar sweeps its days, so they stay one hairline and one stroke at any size. `--ot-ring-p` (how much, 0–1) and `--ot-ring-from` (where the arc begins, 0–1) are registered numbers eased at andante. The parent sets `--ot-ring-sweep` (the share of a turn the ring spans, 1 by default) and `--ot-ring-start` (0deg is the top; it runs clockwise); `--ot-ring-inset`, `--ot-ring-ink`, `--ot-ring-track` and `--ot-ring-head` step it in and colour it. A pie is several rings on one circle, each with its own `from`, and `head="none"`.
- ring (the default): "28 December". One ring per series, concentric, the first outermost, each starting at the top and running clockwise. The number stands inside the innermost ring as large as it allows (weight 200: SPECTRA's scale against the small print), the series' name and "of 30 days" under it. The dot of the series the number reads is the one accent; the others are ink.
- horizon: the Eclipse. Half rings stand on a hairline horizon that runs a step past them on both sides, and everything else is said below it: the number stands on the line (its baseline trimmed to it), its words under the line. Right to left, the half rings rise from the right.
- Pointing at a ring (the nearest by radius) or pointing at or focusing its name in the key inks it: the other rings step back to rule-strong, the accent dot moves to its ring and the number rolls to it, up if it is larger. Leaving rolls it back to now. A changed value glides at andante; nothing draws itself in on arrival.
- Screen readers: the figure is named by `label` and the readout is its caption; each key button reads its name, value and "of 30 days". Keyboard: native buttons. Forced colours: the track is GrayText, the arc CanvasText, the dot Highlight.

### ot-line-chart (line-chart)
- Underneath: chart's frame (`ChartFrame`), plus a hook. `LineChart` and `AreaChart` share `ChartLines`, which lays an SVG under chart's points.
- Anatomy: `<figure class="ot-chart ot-line-chart" data-variant="linear | smooth | step">` holding chart's `.ot-chart-read`, then `.ot-chart-plot` with `<svg class="ot-line-chart-draw" aria-hidden>` (a `<g data-series>` per series, each a `.ot-line-chart-line`) under chart's `<button class="ot-chart-bar">` per point, then `.ot-chart-axis`. Several series add chart's `.ot-chart-mark`s and list readout.
- POINT and SPECTRA: tiny data against one giant number. One ink hairline runs through the points, drawn in pixels (measured with a ResizeObserver) so it stays a hairline at every width, and a paper ring sits on each point like a bead on a thread; now's ring is the one accent. The number above is chart's, as large as the chart allows. Pointing at a column, or focusing it, swells its ring, inks it, and drops the bar chart's own stem from the ring to the baseline (moderato, exhale), as if the line were the tops of the stems with the stems taken away; the number rolls to it and back to now when you leave. Before the plot is measured, only the rings show.
- Series: the second line is dotted graphite and the third dashed pencil; the readout becomes chart's short list, named roman, italic and pencil. Lines are not stacked.
- linear (the default): straight from point to point.
- smooth: the sweep of "Less stress. More creativity."'s script through its capitals, made honest: a monotone cubic (Fritsch and Carlson) through every point that never overshoots one, so the curve never claims a value the data doesn't have.
- step: Paul Rand's dimension lines, right angles only. Each point holds level across its own column and the line stands upright between columns, the draughtsman's line.
- Keyboard: chart's. Right to left the drawing is mirrored with the columns.

### ot-area-chart (area-chart)
- Underneath: line-chart's `ChartLines`, plus a hook.
- Anatomy: `<figure class="ot-chart ot-area-chart" data-variant="linear | smooth | step">`, as line-chart, each series' `<g>` also holding a `<pattern>` of one-pixel rules and a `.ot-area-chart-drops` path filled with it.
- SPECTRA's barcode laid under a line. There is no fill: the volume is drawn as hairlines dropped from the line to the baseline at a close, even rhythm (one every three pixels, pencil), so the shape is made of the barcode's own marks and the space between them. The line along the top is ink; the rings and the pointed drop are line-chart's, and so is the rolling number.
- Series stack in order from the baseline, and each band keeps its own rhythm, three, six and twelve pixels apart (the second and third in rule-strong), so the bands read by density, not colour; the readout's swatches are samples of each rhythm. The readout lists each band, then a rule and the sum ("690 hours in all"). Written for up to three.
- The path styles are line-chart's. Stepped, the drops stand as a histogram.
- Keyboard: chart's. Forced colours: the drops are GrayText.

### ot-pie (pie-chart)
- Underneath: radial-chart's `Ring`, stacked, plus a hook; the key is native buttons.
- Anatomy: `<figure class="ot-pie" data-variant="ring | horizon" style="--n" aria-label>` holding `.ot-pie-face` (`aria-hidden`) of `.ot-pie-arcs`, one `ot-ring` per share (`head="none"`, its own `from`, `data-shown` on the one the number reads) and one `.ot-pie-tick` per share (`style="--t"`, its arc's middle), then `<figcaption class="ot-pie-read">` (`.ot-pie-value`, a large rolling number, and `.ot-pie-words`: `.ot-pie-name`, `.ot-pie-of`), then `<ul class="ot-pie-key" role="group" aria-label>` of one `<li role="none">` per share, each holding a `<button>` (`.ot-pie-place`, `.ot-pie-key-name`, `.ot-pie-key-value`, and the share in `.ot-sr`).
- ring (the default): "28 December"'s rings. One hairline ring cut into arcs, one per share, clockwise from the top, with a gap of paper between each (a hundredth of the turn, never more than half an arc): no wedges, no fills, and no track under the arcs, so the gaps are the page. Each arc is numbered 01, 02, 03 at its middle, just outside the ring, in the pencil small print and upright; the key under the ring is a contents page of the same numbers, name and figure. The total stands inside as one very large number (weight 200, SPECTRA's scale against the small print) with "visits in all" under it.
- horizon: the Eclipse. The half ring stands on a hairline horizon that runs past it on both sides, and everything else is said below it: the total stands on the line (cap to baseline, so its feet are on it), its words under the line.
- Pointing at an arc (read by its angle, within a finger of the ring) or at its name, or focusing its name, inks that arc in the accent and swells it to three hairlines; the other arcs step back to rule-strong, its number inks, and the total rolls down to its share, "28%" (the sign small and raised; under 1%, "<1"), with the name and "820 of 2,950 visits" under it. Leaving rolls it back up to the total. At rest nothing carries the accent. A changed value glides at andante, as the ring does.
- One share is a whole ring with no gap and no numbers; nothing to share is the bare hairline ring and "0".
- Keyboard: the key is one tab stop (`rove`, round); Up and Down or Left and Right move through the shares and wrap, Home and End jump. Right to left, the arcs, their numbers and the pointer all run counter-clockwise. Screen readers: the figure is named by `label`, the readout is its caption, and each key button reads its name, figure and share of the total. Forced colours: the arcs and their numbers are CanvasText; the pointed arc is told by its weight.

### ot-radar (radar-chart)
- Underneath: the grid item (`variant="dots"`) as the sheet, an SVG drawn in pixels, plus a hook; the axis names are native buttons.
- Anatomy: `<figure class="ot-radar" style="--n; --m">` holding a `ot-grid[data-variant="dots"].ot-radar-sheet`, inside it `.ot-radar-plot` (`role="group"`, `aria-label`, square, `--r` the rim's radius) of `<svg class="ot-radar-draw" aria-hidden>` (`.ot-radar-build`: the construction polygons at the quarters and the spokes; a `.ot-radar-series` per series, `data-series`, each a `.ot-radar-line` and a `.ot-radar-bead` per point; and, while an axis is measured, `.ot-radar-dims`, one `.ot-radar-dim` per series), `.ot-radar-figure` (one series), and one `<button class="ot-radar-axis" style="--c; --s">` per axis. With series, `<figcaption class="ot-radar-key">` of `.ot-radar-name`s, each after a `.ot-radar-swatch`.
- Paul Rand's "design": a dotted construction sheet, lettered and numbered along its border, with registration crosses at its corners (the grid item's), and on it dotted construction polygons at each quarter and dotted spokes, the rim a step firmer. The shape is one ink hairline through the values, clockwise from the top, a paper bead on each point, as line-chart threads its rings. Each axis is named at its end in small caps (`all-small-caps`, pencil), hung off the spoke in the direction it runs. The rim's radius is a third of the plot, less where the plot is narrow, so the names keep 76px beside it and stay off the sheet's lettered border.
- Pointing at an axis (the nearest by angle) or at its name, or focusing its name, inks the name, fills its bead of the first series in the accent (the one accent in view, with spiccato), and measures the value off as Rand's dimension line: a hairline stepped a little off the spoke, from the centre to the point, ticked at both ends and drawn out from the centre (moderato, exhale). One series sets its figure beside the line, "9/10", the rim's value after it in pencil (SPECTRA's fractions). With series, each series has its own dimension line, one step further from the spoke, in its own line's voice, and the key gives each figure.
- Series (`series`): the second is dashed graphite and named in italic, the third dotted pencil (chart's voices: roman, italic, pencil). Written for up to three.
- Fewer than three axes draw no shape: a line says "A radar needs three measures or more; this one has 2."
- Keyboard: the names are one tab stop (`rove`, round); the arrows go round the axes and wrap, Home and End jump to the first and last. Right to left the drawing, the names and the arrows mirror. Screen readers: each name reads "Width range: 10 of 10" (with series, each series' figure). Forced colours: the lines CanvasText, the construction GrayText, the measured bead Highlight.

### ot-avatar (avatar)
- Underneath: native.
- Anatomy: `<span class="ot-avatar" role="img" aria-label="Name">` holding an initial; `data-size="s | l"`, `data-here` for presence. A group is `<span class="ot-avatars" role="group">`, ending in an optional `data-count` avatar ("+3").
- A person is a ring and their initial, in italic, since a name is theirs. Someone here carries the accent dot. A group overlaps, and steps apart when pointed at.
- `variant` on the avatar (`data-variant`): `ring` (the default), `monogram` or `fit`. Both drop the ring: the type is the whole mark. Each carries `dir="auto"`, so its letters follow the name's own script, not the page's.
- monogram: "It has to be design." The given initial in the large italic (`opsz` 12, so its hairlines hold) printed over the family initial in a heavy narrow roman (800, width 62%), cut out of it by a paper outline (`paint-order: stroke fill`), as "has" crosses "It". Here now, the italic takes the accent, as "design." does, and there is no dot. Pointed at, the italic steps off the roman toward the start (spiccato) so both letters read. A group of monograms stands side by side instead of overlapping. One name gives one letter.
- fit: "Less is more.", big type set to its measure. The given name alone (or `fallback`), measured in its own face on a canvas and set to fill one width (1.8 times the avatar's size), capped at 1.1 times the size, so "Ada" stands large and "Wolfgang" small. It re-measures when the pair changes; until measured it shows at half the size. Pending font measurements stop when the avatar is released; a failed font load keeps the fallback size. Here now hangs an accent full stop outside the measure, as hanging punctuation does. A group stacks fitted names between hairlines, a count last in small voice.

### ot-item (item)
- Underneath: native.
- Anatomy: `<ul class="ot-items">` of `<li class="ot-item">` holding `.ot-item-body` (`.ot-item-title`, `.ot-item-desc`), `.ot-item-leader` (aria-hidden), then `.ot-item-end` (a value or an action).
- A ledger line: what it is, a dotted leader, what you can do. As on a contents page, the title, the dots and the value share one baseline (the picture at the start centres on the line). Pointing at the line inks the leader from one end to the other.
- `variant` on the group (`data-variant`): `leader` (the default), `lineation` or `words`.
- lineation: a critical edition's line numbers. Every fifth line carries its number (a CSS counter, `pp`, pencil) hung in the margin on the line's baseline; the line you point at or focus shows its own, in ink. The numbers are drawn (`content: counter() / ""`), since the list already says where you are. Below 40rem the margin is too narrow, so the numbers step in and every line makes room for them.
- words: SPECTRA's small print run along a contents line. The description runs in after the title (`pp`, pencil, one line) where the dots would be; a long one runs out in an ellipsis just before the value, and a short one leaves the dots to finish the line. Pointing inks the words to graphite with their leader. The whole sentence stays in the page for screen readers.

### ot-feed (activity-feed)
- Underneath: native, composed of `item`, `avatar`, `marker` and `collapsible`.
- Anatomy: `<section class="ot-feed" data-variant="ledger | almanac | lapse" aria-label>` holding day markers and `ul.ot-items.ot-feed-run` of `li.ot-item.ot-feed-entry` (`data-newest` on the first when nothing is new). Each entry: `.ot-feed-bead` (aria-hidden: an `s` avatar, or `.ot-feed-dot` for what the system did), the title (`b.ot-feed-who`, then what happened, the object in `.ot-yours`), an optional detail, the leader, and `<time>` at the end. Past `initial`, the rest waits in a `details.ot-feed-more` whose summary says "and 4 more"; `fresh` puts a ribbon marker ("Where you left off") before the first entry you've seen. `at` is read as written ("2026-09-30T09:52") and formatted in UTC, so the server and the page agree.
- A history set as a ledger, newest first: who in ink, what they did in graphite, a dotted leader to the time. One hairline runs down the margin through each stretch of entries, starting and stopping at the beads on the first lines; the newest bead is the one accent (the ring of its avatar, or its dot). No cards, no icons: a person is their initial, the system a full stop.
- Ledger (the default), after contents pages: days are divider markers ("Today", "Yesterday", or the date), each day's entries hung on its own thread.
- Almanac, after the "Less but better" calendar: each day opens on its date set huge and heavy (`--ot-f`, 700, tight), the month over the year in small capitals beside it and the weekday (or `days` label) at the far end, the way the calendar sets a leaf.
- Lapse, after Principle 1 and the marker's lapse: the time between entries is given as silence. A quiet of an hour or more breaks the thread with a lapse marker ("5 hours earlier") whose room grows with how long it went quiet; a new day is a lapse named for the day.
- Pointing at an entry inks its leader and its time (the item's move). Opening the rest, its entries arrive down the line in turn. Right to left the thread and beads move to the right. Forced colours: the thread and dots are CanvasText, the newest Highlight.

### ot-tree (tree)
- Underneath: native `<details>` and `<summary>` for folders; `item` rows for leaves (a `<button>`, or a link with `href`); `collapsible` for a long folder's rest.
- Anatomy: `<div class="ot-tree" data-variant="outline">` of `ul.ot-tree-list`; each `li.ot-tree-node` (`data-kind="leaf | folder"`) is a leaf `.ot-item.ot-tree-row` holding `.ot-tree-name`, or a `details.ot-tree-folder` whose `summary.ot-tree-row` holds the name, its count as a raised `sup.ot-tree-count` (read as ", 3 items") and an optional value after the item's leader. A folder longer than `limit` ends in `li.ot-tree-tail`.
- branch (the default): contents pages and Paul Rand's dimension lines. A hairline branch hangs from under each open folder's first letter and every name sits on it at a dot; the last one stops the branch at its dot. A leaf is a small graphite dot, a closed folder a hairline ring, an open one a filled dot; the chosen leaf's dot is the one accent (it lands with spiccato) and its name turns italic, as yours. No icons, no boxes: the depth is read off the lines.
- outline: a book's decimal contents and the numbers-as-data of "the silence that heals": each name numbered by its place (1, 1.2, 1.2.3) in a pencil column, flush at every depth and without lines; top-level names set firm. An open folder's number inks, the chosen leaf's is the accent.
- Opening a folder you touched draws its branch down (`ot-draw-y`) and its names arrive in turn; folders open from the start are simply there. The contents slide open (`::details-content`).
- Keyboard: Tab and Enter or Space work natively. The arrows walk it as a tree: Up and Down through what shows, Right to open a folder or step into it, Left to close it or step out to its folder, Home and End to the ends; Left and Right follow the page right to left.

### ot-swap (swapy)
- Underneath: native buttons on `rows`, plus a hook.
- Anatomy: `<div class="ot-swap" data-variant="transpose">` holding a `ot-rows` list (`aria-label`), each `<li data-id data-held>` holding `.ot-swap-n` (the place, aria-hidden), `.ot-rows-title`, `.ot-rows-kind`, `.ot-rows-meta` and `<button class="ot-swap-move" aria-pressed>` (the words move and moving in one cell, then `.ot-swap-arrow`); a hint and a polite status in `.ot-sr`. Transpose adds `svg.ot-swap-arc` and `.ot-swap-tr`, both aria-hidden. `data-holding` on the root while a row is held; `data-dragging` while the pointer carries it.
- Rows you put in order by hand. A word is the handle: "move ↕", graphite, the arrow pencil; pointing inks both and nudges the arrow. Press it and the row is held, the word says moving, the arrow keys carry it, and pressing again sets it down. Or drag the word: the held row goes to the place under your hand, read from the layout so nothing jitters, and is set down where you let go. There is no drag ghost: the row itself travels.
- Default, after "the uncreative": the held row reverses out of an ink block that prints across it from the inline start, the words turn to paper, and the name steps forward and sets heavier and tighter (300 to 560, -0.035em). Every row that changes place glides there (moderato, breath) and its number turns over the way it went, the numbers being data (01, 02 in pencil tabular figures, always left to right). Only the held row inks, so one block travels with your hand.
- Transpose, after the proofreader's transposition mark: no ink. The held name turns italic (yours now, at the expression scale on the row's own line height, so nothing reflows) and the others step back to pencil. In the margin (`--ot-swap-margin`, space-7, space-6 below 40rem) a hairline loop runs from the place it was picked up to the place it is now, ending in an ink dot, with a pencil italic tr by its middle. Set down, the mark fades: the correction is made.
- Screen readers hear each step once, politely: "Halden picked up, 2 of 5.", "Halden, 3 of 5.", "Halden set down, 3 of 5.", "Halden put back, 2 of 5.". The word's name says the row and its place.
- States: rest, pointed at (`data-force="hover"` pins the first row's word), held, disabled (pencil, no handles). Right to left the block prints from the right, the loop hangs in the right margin and the figures still read left to right. Forced colours: the held row is `Highlight` with `HighlightText`, the loop `CanvasText`. Reduced motion: rows and numbers change place without travel.
- Keyboard on the word: Space or Enter picks up and sets down; Up and Down carry the row (picking it up if needed); Home and End take it to the ends; Escape puts it back; leaving the word sets it down.

### ot-prose (typography)
- Underneath: native.
- Anatomy: `<article class="ot-prose">` wrapping plain HTML: headings, `p`, `.ot-prose-lead`, `blockquote`, lists, `code`.
- Text-size `em`, `i` and block quotations use the expression reading grade from base. Nested italics do not multiply the scale again. Italics inside display headings keep their display settings.
- swiss (the default, `data-variant="swiss"`): set for reading at `--ot-measure`. Headings step by the dynamics; quotes are in the expression; quote marks and list dashes hang in the margin so the edge stays true (`hanging-punctuation` where supported); numbered lists step in instead, a number being too wide to hang, so the numbers stand on the edge. A nested list steps in by its dash, so its dash hangs under its parent's words, and list items take half a paragraph's pause (0.5em) between them. Code is the voice, condensed.
- book: the page of a book, by the compositor's rule "indent or space, never both" (Tschichold's Penguin rules, Bringhurst). Paragraphs follow on with no space between them, each indented an em and a half, and the first after a heading or a break flush; they are justified and hyphenated, with old-style figures where the face has them. The opening line after a heading is set in spaced capitals (`::first-line`, so it re-sets itself at every width). A break (`hr`) is a dinkus of three spaced dots instead of a rule. Quotes are indented both sides at body size.
- run-on: the scribe's paragraph. A passage's paragraphs run on as one block, and where each begins a pilcrow (¶, the expression face, ink, decorative to screen readers) stands in the line: the silence between paragraphs is kept as one mark. The lead and anything that isn't a paragraph stay blocks. For short passages; long reading wants swiss or book.

### ot-msg, ot-bubble, ot-reactions (message)
- Underneath: native.
- Anatomy: `<article class="ot-msg" data-from="them | you" data-variant="script | quote">` holding an `ot-avatar`, `.ot-msg-head`, `.ot-msg-body` (optionally a `<p class="ot-bubble" data-variant="ink | mark">`), and `.ot-msg-foot` with `.ot-msg-status` (`data-read`). Reactions are `<span class="ot-reactions">` of `<button class="ot-tag" aria-pressed>` with `.ot-reaction-count`.
- No balloons. Of the speech bubble, only its tail is left: a leaning hairline. What you wrote sits on the other side, in italic. Sent is a ring; read, it fills to a dot. New messages write in from the inline start (`ot-message-write`, from the right on a right-to-left page). A reaction you add turns italic and its count rolls. A bubble can be `ink` (reversed out of a block, the tail beneath it) or `mark` (a highlighter behind the words; selected inside it, the words reverse to ink, as in a mark).
- Script, after the printed play text. No face and no tail. The name stands in the margin in spaced capitals with a full stop, the time under it in parentheses like a stage direction, and the words sit in one column for everyone, on the name's baseline. Nobody is placed on a side: who is speaking shows only in the type, theirs roman and yours italic, which is the house rule with nothing else holding it up. Narrow (below 30rem) the name runs in above the words. Right to left, the margin is on the right.
- Quote, after the typographer's own speech balloon, the quotation mark, set at the scale of "It has to be design.". No face and no tail: a large pencil italic mark (`::before`, `--ot-ff`, aria-hidden by its empty alt text) stands where the face was. Theirs opens (“) at the top of the start; yours closes (”) at the foot of the end, so an exchange is framed from both sides. Arriving, the mark lands with spiccato before the words write in. Right to left the mark is mirrored. Forced colours: the mark is `GrayText`.
- Typing (`MessageTyping`, `<p class="ot-bubble ot-typing" role="status" data-writing>`): the other side is writing. Of a message only the tail and three periods are there, where the words will be, sketched in pencil until the message inks them in; the periods breathe in turn, as a busy button's do (`ot-dots`). It shows only while `writing` is true, which the caller drives from the real typing state, so it is not motion that plays by itself. Not writing, it stays mounted as an empty, silent status (`.ot-sr`) that takes no room, so its `label` ("Ada is writing") is heard when writing starts. Alone it stands after the last message; given a face (a `Message` holding a `MessageAvatar` and a `MessageBody` with the typing in place of a bubble) that message folds away with it while nobody writes. In the script variant the periods stand in the column after the name, a line about to be spoken. Reduced motion: the periods trail off and dim, as the spinner's do.

### ot-marker (marker)
- Underneath: native.
- Anatomy: `<p class="ot-marker">` for a status (with `.ot-marker-dot`), or `data-variant="divider | ribbon | lapse"`. A lapse carries `--lapse` (0–1, from `minutes`). A divider may carry `data-orientation="vertical"`. `data-arriving` plays it.
- A quiet line in the flow. A divider draws its rules outward from the word, as if the word pushed them apart; the word stands on them, as "Less is more." sets its rules on the baselines.
- Rule: a divider with no word is a plain rule (`role="separator"`): the two rules meet, one unbroken hairline, and arriving it still draws outward from its middle. Vertical (`orientation="vertical"`, divider only): the rule stands up between two things in a row, as tall as the row, as "Less is more." rules its columns. The marker turns on its side (`writing-mode: vertical-rl`), so a word reads down it like a book's spine, the rules running above and below it and drawing outward from it.
- Ribbon: where you left off, after the ribbon sewn into a book to keep your place. One accent line (`--ot-stroke`) runs from the inline start to the word at the end ("New"), in the accent, because it marks where you are. Arriving, it draws from where you started reading. It is the one accent in a thread; forced colours draw it in Highlight.
- Lapse: a pause in the conversation, given as silence (Principle 1, literally). No rule at all: the room above and below the words and the space between their letters both grow with how long it went quiet, on a log scale from a minute (a breath) to a week (the widest). The words stay centred however far they're tracked. A joined script (Arabic, Persian, Urdu, by `lang`) is never tracked apart; its word spaces widen instead. Arriving, the silence opens and the letters spread.

### ot-agent (agent-state)
- Underneath: native, composed from `marker` (its status line) and `spinner`.
- Anatomy: `<p class="ot-marker ot-agent" data-state="ready | thinking | working | input | done" data-variant="word" role="status" aria-live="polite">` holding `.ot-agent-mark` (aria-hidden) and `.ot-agent-word`. `aria-busy` while thinking or working. `data-turned` once the state has changed.
- Where an agent is, as the words say it: Ready, Thinking, Working, Needs your input, Done (`agentStateWords`; `children` gives other words, "Reading the brief"). The mark lives the life of a day on the "28 December" calendar: ready is a hairline ring (to come), thinking is the ring breathing (the breath spinner), working is three voices going round it (the round spinner), input is the one accent disc (now: it's your turn), done is the disc filled in ink (gone by) with the word stepped back to pencil. The word is graphite at rest and ink while the agent is busy or waiting on you.
- It moves only while `state` is thinking or working, which the caller drives from the agent's real state, so it is not motion that plays by itself; the loops are the spinner's, slow and eased. When the state changes the new ring or disc lands with spiccato (never on first paint).
- word (`variant="word"`): no mark. The word carries the state: inked letter by letter while busy (the word spinner, its copy for readers in a `.ot-sr`), set in the accent when it's your turn, pencil when done.
- A polite status, so each change is heard once. Reduced motion: the spinners' own still frames. Right to left the mark leads from the right. Forced colours: the ring and the ink disc in CanvasText, the accent in Highlight.

### ot-agent-chat (agent-chat)
- Underneath: native, composed from `thread`, `message`, `attachment`, `field`, `dialog`, `radio-group`, `progress`, `marker`, `agent-state`, `button` and `kbd`. The composer is the one new piece.
- Anatomy: `<section class="ot-agent-chat" data-variant="callout">` holding `header.ot-agent-chat-head` (an `h2` and a `ot-agent` status), `.ot-agent-chat-thread` (a `ot-thread`) and `form.ot-agent-compose` (`data-over` while files are dragged over it) with a `ot-field` textarea, `ul.ot-attachments.ot-agent-encl` (enclosure), and `.ot-agent-compose-actions` (Attach, a hidden multiple file input, `.ot-agent-compose-hint` with two `ot-kbd`, then Send or Stop). In the thread: `div.ot-agent-note` around a `ot-marker` status (a note, or a permission's receipt with `data-decision="pending | allowed | denied"`) or a sentence `ot-progress` (the work), and `div.ot-agent-choice` (`data-answered`) holding a vertical `ot-choice` and a bracket Continue.
- After "It has to be design.": the agent's words are ours, in roman; yours arrive in italic, in the thread and on the composer's ruled lines. When it asks permission the question is heavy and narrow and the answers are large in italic (the dialog's reply surface, an alert). Deny has the focus and Escape denies, so nothing is allowed by default; the question and your answer stay behind as a receipt, "Read last season's timetable? Allowed once.", the answer italic because it's yours. A choice is the radio words in a column; answered, only your word stays inked. The work is a sentence that inks in at the size of the messages and ends in a full stop.
- The composer: Enter starts a new line, ⌘ Enter (Ctrl Enter elsewhere, `aria-keyshortcuts`) sends. Files come by Attach or by dropping them on the composer and are written under the box as a letter's "Encl. (2)"; dragged over, the count takes the incoming files and a pencil italic line says "Let go to enclose all 2." before anything is added. While the agent is busy, Send gives way to a bracket Stop and the box stays open for your next words. An error hangs from the box as the field's callout. Send and Stop keep the far end, wrapped or not; below 22rem the key hint gives way. Every word is a prop with an English default (`sendLabel`, `stopLabel`, `attachLabel`, `sendsLabel`, `dropLabel(count)`; on the permission `allowLabel`, `denyLabel`, `allowedLabel`, `deniedLabel`, `metaLabel`, `pendingLabel`), so a right-to-left page reads in its own language.
- Callout (`data-variant="callout"`), after the Weingart letter: the notes, receipts and the work leave the column and hang at the far side, reversed out of ink pills (the tokens are swapped inside, so the work sentence inks in reverse), each on a hairline leader that reaches back toward the conversation and ends in a dot.
- Typing: keep a `MessageTyping` mounted last in the thread and drive `writing`; when the reply comes, set writing false and add the new `Message` with `arriving` before it. The header's `ot-agent` is the one live status for where the agent is.
- Right to left the whole column mirrors and the leaders reach the other way. Reduced motion: the parts' own still frames. Forced colours: the pills are Canvas with a CanvasText edge and leader.

### ot-attach (attachment)
- Underneath: native.
- Anatomy: `<ul class="ot-attachments" data-variant="reverse | enclosure">` of `<li class="ot-attach" data-state="idle | uploading | processing | done | error">` holding `.ot-attach-ext` (`data-ext`), `.ot-attach-body` (`.ot-attach-name`, `.ot-attach-meta`), and `svg.ot-attach-ring` (`.ot-attach-track`, `.ot-attach-arc`, `.ot-attach-fill`). Script sets `--p` (0–1). Enclosure sets `data-count`, `data-enclosure-label` from `enclosureLabel` (default `"Encl."`) and `aria-label="Enclosures"` (overridable through the native prop).
- A file's extension is its picture, set wide and thin. A ring counts it in and goes pencil while it's checked; when it's safe the ring closes and gives way to a full stop (`--ot-dot`), which lands with spiccato: a ring round a dot would read as a chosen radio. Failed, the ring turns crimson and the line says what happened, with a bracket Remove. Narrow (below 30rem), Remove steps down under the name so the name keeps the width. `removeLabel` gives the button its word (default `"Remove"`); its accessible name is that word followed by the file name.
- Reverse, after "the uncreative", where part of a word is reversed out of an ink block. No ring: the extension is set heavy and tight, and a block (`.ot-attach-ext::after`, the same letters in paper) prints across it as `--p` grows, so each letter turns from ink on paper to paper on ink as the file arrives. Checking, the block is pencil; safe, it is ink; failed, it stops in crimson where the connection dropped. Right to left it prints from the right. Forced colours: the block is `CanvasText` with the letters in `Canvas`.
- Enclosure, after the business letter's enclosure line (the Weingart letter). The list is one sentence: "Encl. (2)", then each file's name, yours in italic, its size or status in parentheses, a semicolon between and a full stop at the end. The extension and a safe file's ring are dropped; a small ring stays inline while a file is on its way. Meant for what has been sent, under a message. The name and parenthesised status wrap to the available measure, including long unbroken names; no content is hidden to fit.

### ot-thread (thread)
- Underneath: native, with the scrollbar.
- Anatomy: `.ot-thread` holding `.ot-thread-scroll` (`role="log"`, `data-lenis-prevent`) of messages and markers, and `<button class="ot-thread-latest" hidden>` holding `.ot-thread-new`.
- It keeps to the latest message while you're at the end. Scrolled back, it stops following, and new messages are counted in an ink pill whose count rolls; pressing it focuses the log before taking you down, so focus stays there when the button disappears. Content sits at the bottom (`align-content: safe end`) while the thread is short.
- Variants on `.ot-thread` (`data-variant="rests | running"`).
- Rests, after the principle that silence is structure and the score's multi-bar rest. The space before each message is the silence before it: script reads each header's `<time dateTime>` and sets `--ot-rest` to log2(1 + minutes), and the gap is `--ot-rest × 1.25 × --ot-space-2` on a base of `--ot-space-3`, capped at `--ot-space-9`. Quick replies sit close; a morning's wait opens wide. A pause of an hour or more (`data-rest="3 hours later"`) is said in that silence as the marker's lapse says it: the words in pencil at `pp`, centred (`::after`, aria-hidden), their letters spread by `--ot-lapse`, the lapse's own scale from a minute to a week. The two share one voice for a pause: the lapse is a marker you place, rests measures every gap for you. A day divider starts the count again. Nothing moves.
- Running, after a book's running head and the SHAPES / GRADIENTS frame row. Scrolled back past a day's divider, the top edge carries `.ot-thread-head` (aria-hidden, since the log says it all): the day at the start, the time of the first message in view at the end, a hairline between them. It hides while the day's own divider is in view. When you cross into another day the word rolls, up going on, down going back.

### ot-quest (questionnaire)
- Underneath: native form.
- Anatomy: `<form class="ot-quest" data-variant="sentence | interview | definition">` holding `.ot-quest-head` (an `ot-fraction` count and a filling hairline), in an interview `<ol class="ot-quest-log">`, `.ot-quest-step` sections each with a `.ot-quest-q` question and its controls, `.ot-quest-actions` (Skip, Next), then `.ot-quest-said` (`aria-live="polite"`) holding, in a definition, `.ot-quest-entry` (`.ot-quest-word`, `.ot-quest-kind`), and `.ot-quest-sentence`. `defaultAnswers` and `defaultStep` resume one.
- One question at a time, set large. The count rolls and the hairline fills; each question turns in from the side you're heading (`ot-turn`). At the end your answers are written into one sentence, arriving word by word, in italic, because every word of it is yours.
- Interview: after the printed interview's Q and A. Every question asked stays above the next, small and roman, with your answer under it in italic; Q and A hang in the margin in pencil and step in below 860px. Each answer is a button: pressing it goes back to that question (a hairline sketches under it when pointed at). A skipped one says so in pencil. At the end the whole transcript stands over the sentence.
- Definition: after "the uncreative" (poster VI and its definition). The end is a dictionary entry: the headword (yours, so in the large italic) reversed out of an ink block that draws across behind it from the inline start, the part of speech under it small in roman, then the sense in italic at the lead size, a usage in quotation marks if you wrote one. `entry(answers)` gives the word and its part of speech. Forced colours: Canvas on CanvasText.
- Keyboard: native form controls; focus moves to each new question (to the chosen answer when you go back to one).

### Direction (right to left)
- Every component uses logical properties and `:is([dir="rtl"], [dir="rtl"] *)` where a stroke has a direction. The page's own `dir` is the switch; there is no wrapper to add. Radix writes a `dir` of its own, so each Radix-based item (the menus, the menubar, the toggle group, the tabs, the navigation menu) takes the direction of the page around it as it mounts, once: a later change of the page's `dir` isn't followed. Pass `dir` to set it yourself. Right to left, the crumbs' hairlines lean the other way, the checkbox strike runs from the right, and a field's accent line grows from the right for the keyboard.
- Arabic has no italic, and the pairs have no Arabic, so the system face stands in and what you type stays upright there.

### ot-link (link)
- Underneath: native `<a>`. Its CSS lives in base.css, so every item may use it. `.ot-prose a` is the same link.
- One link. At rest, a hairline under the words in the current colour, clear of the descenders. Pointing, focusing (`:focus-visible`) or holding its card open (`data-state="open"`, a hover card's trigger) draws the highlighter through the whole word, ascenders and descenders included, on from the left and off to the right (mirrored right to left), and the hairline gives way to it. The stroke runs 0.12em past each end, like a pen overshooting, while the words stay put. The letters turn `--ot-on-mark` exactly where the stroke has reached (two layers clipped to the text), so they are never dark on dark in Nocturne. The hairline and the overshoot come back once the pen has passed.
- Focus: the stroke, with the accent line under it at `--ot-stroke` in place of the outline box (forced colours keep the outline). Pressed (`:active`): the line snaps back under the stroke in ink, at `--ot-stroke`. Read (`:visited`): the line fades to pencil; browsers let `:visited` change colour only, which is why the line is the box's bottom border and not a painted layer.
- `external` (the component prop): opens in a new tab, with "(opens in a new tab)" for screen readers, and a ↗ that hangs just past the end of the words, off the line, on the last line however the link wraps; the link keeps room for it, so it can't be stranded at the start of a line. Pointing sends it a step the way it points.
- `data-variant="quiet"`: the line in `--ot-rule-strong`, for a run of links that already reads as links (an index, a programme), so the run isn't a barcode. `--ot-link-line` sets the line's colour directly.
- `data-variant="reference"`: after the book's reference marks. No line; a raised mark after the words in the printer's order (* † ‡ § ‖ ¶, then doubled, a CSS counter with `@counter-style ot-notes`), numbered down the page. The mark says there is more; pointing strokes the words and the mark together. The mark is generated content with empty alternative text, so screen readers read only the words. For sources and definitions in running text.
- `data-variant="address"`: after the printed page, where a link is spelled out so a reader can go there. Pointing or focusing writes where it goes, small, pencil and in parentheses (no scheme, no `www.`, no trailing slash), after the words from where they end, clear of the ↗ on an external link. A wrapping `.ot-link-addressed` span holds the link and its `.ot-link-address` sibling, reserving the address's measure even at rest so revealing it moves nothing. When there is no room beside the words, the address steps under; long addresses wrap. Use it for a link on its own line (a list, a footer). The address is `aria-hidden`; it isn't drawn with `asChild`.
- Docs rows pin states with `data-force`: `hover`, `focus`, `press`, `visited`.

### ot-kbd (kbd)
- Underneath: native `<kbd>`. Its CSS lives in base.css, so every item may use it.
- A key, drawn as the corners of its cap (the corner marks the statement button and the dialog wear), with room inside for its name, on the text's baseline. `data-pressed` presses it: the corners run together into the whole cap and ink in, and the key goes down a little (the specimen presses the G key along with your keyboard).
- A key is its own left-to-right run (`direction: ltr; unicode-bidi: isolate`), so ⌘K reads ⌘K on a right-to-left page too.
- `data-variant="typewriter"`: after the round keys of the machine Weingart's letter was typed on, and the dot calendar's discs. The key is a hairline ring (an ellipse for a word such as Esc). Pressed, it inks into a disc with the letter reversed out of it in paper, goes down and lands with one small rebound. Forced colours draw it in CanvasText and reverse it to Canvas.
- `data-variant="chord"`: after the figured bass, where the notes to play with the bass are stacked small beside it. Given a combination as a string (`⌘⇧S`, or `Ctrl+Shift+S`), the key stands a little larger and its modifiers stack small before it, in graphite, in one cap: keys held together, read as one. The text keeps its order, so it is read as written. Pressed, the cap closes and the figures ink.

### ot-fraction (fraction)
- Underneath: native. Its CSS lives in base.css, so every item may use it.
- `<span class="ot-fraction"><span class="ot-yours">2</span><i><span class="ot-sr"> of </span></i><span>5</span></span>`. A display fraction, read aloud as "2 of 5".
- The part that's yours stands large in the italic, up on the left; what it counts toward sits small, light and a little wide, down on the right, on the same baseline, so the words after it ("done") read on one line with both. Between them the solidus is a pen stroke: a leaning hairline that thins out at both ends and dips just under the line. Pointing inks the stroke and the total.
- `<Fraction count total>` turns a changed number over the way the count went (up as it grows, down as it shrinks), figure by figure like a counter's wheels: only the figures that changed turn, the units first and the carry one `--ot-arpeggio` behind (19 to 20 turns both, 12 to 13 only the 3). A number that gains or loses a figure, or changes shape, or a word, turns over whole. Each figure is a `.ot-fraction-figure`; the number is read aloud whole. The stroke ticks once, like a pen. Without motion the number simply changes.
- The figures read left to right in every direction: the fraction is its own isolated left-to-right run (`direction: ltr; unicode-bidi: isolate`), so in a right-to-left page it still reads "18/24", never "42/81"; only the words around it change sides.
- Alone: `total` is optional. Without one the stroke and the total go, and the count stands by itself, a rolling figure of yours at the same size in the italic (a streak, a score, words written); a figure that isn't the person's is a `stat`. Numbers grouped or pointed (3 466, 0.75) turn figure by figure as whole numbers do, the marks between them staying put; the readout does too.
- `variant` (`data-variant`; none for the default, `solidus`): `vinculum` or `readout`. Only the solidus ticks. Without a total there is nothing to relate, and every variant is the count alone.
- vinculum: the built-up fraction, as a printer sets one. The count stands over a level bar and the total under it, centred; the bar is a gauge, inked from its start for the share done (`--share`, set by the component from count over total) and a rule for the rest, from the right in a right-to-left page. As the count moves the ink eases along the bar (`--ot-andante`), while the figures turn on their wheels. A total of nothing leaves the bar a rule.
- readout: after SPECTRA, where Ikeda prints 1/3 beside 0.13. The share as a decimal to two places (0.75), in the voice, pp, pencil, hung at the top after the total (`.ot-fraction-readout`, aria-hidden: the fraction already says it). It turns over with the count; pointing takes it to graphite with the total.

### ot-meta (meta)
- Underneath: native. Its CSS lives in base.css, so every item may use it.
- A frame row of words held apart by flexing hairlines, level on the first line's baseline. The row never wraps, so no hairline is left at the end of a line pointing at nothing: where the words don't fit, each one stacks in its place (balanced), tops level, as the corner notes of "Healthy habits" do.
- `data-variant="proportional"` with `at`: after the score's proportional (space) notation, where distance is time. Each hairline is as long as the interval between its neighbours (`--ot-span`, set from `at`), in `--ot-rule-strong` because here the line is data. Where the row is too narrow, the hairlines fall to their shortest.
- `data-variant="credits"` with `MetaItem label`: after Ikeda's SPECTRA credits. No hairlines between; one rule over small columns hung from it, each a pencil label over its value in ink, figures tabular. The columns wrap.

### ot-corners (corners)
- Underneath: native. Its CSS lives in base.css, so every item may use it.
- Four corner marks as one `::after`. It frames without closing. Tune it with `--ot-corner` (length), `--ot-corner-inset` and `--ot-corner-colour`. Forced colours draw them in CanvasText.
- `data-variant="viewfinder"`: after the camera's framing marks ("the silence that heals" names the phone it was shot on). At rest the marks frame the whole. Point at or focus a part (a direct child) and they glide onto it, a step outside it, and lock with one small rebound; leaving, they open back out to the whole. For the keyboard the marks are the focus ring: in the accent, and the part draws no outline of its own. A tap leaves the frame where the finger put it. The component sets `--ot-aim-x/y/w/h`.
- `data-variant="glide"`: the viewfinder's marks lent to a group of controls, at any depth (a toolbar, a row of links, a form's actions); the job of a target cursor, done with the one frame the page already owns instead of a cursor of its own. At rest there is no frame. Point at or focus a control and one frame fades in round it, `--ot-space-2` outside, then glides from control to control over moderato with breath, and moves only when the pointer or focus moves. Leaving, it goes back to the focused control if there is one, or fades where it was. Disabled controls are passed over; a touch shows nothing. For the keyboard the frame is the focus ring, in the accent, and the controls draw no outline of their own; forced colours draw it in CanvasText, and Highlight on focus. Arriving from rest it only fades, so it never flies in from a corner; under reduced motion it is simply there, on the control you are at. Positions are measured from the box, so right to left needs nothing of its own.
- `data-variant="kagi"`: after the Japanese corner brackets 「 」, where the corner mark is the quotation mark. Only two corners at `--ot-stroke`, the opening one before the first word and the closing one after the last (`box-decoration-break: slice`), however many lines the words cross; right to left they mirror. A word joiner keeps the opening mark with its first word. Put it on a `<q>` with `asChild`; its own quotation marks are dropped.

### ot-grid (grid)
- Underneath: native. A server component; it never moves.
- Anatomy: `<div class="ot-grid" data-variant="rules | dots" style="--ot-grid-cell">` holding four `.ot-grid-cross` (`data-corner="start-top | end-top | start-foot | end-foot"`), two `.ot-grid-ticks` (`data-axis="columns | rows"`, `aria-hidden`), then the content.
- A quiet structure behind a section, drawn as a construction sheet. Rules (the default): a faint square grid in `--ot-rule`, from "the silence that heals" and "Less is more.". Dots: the rules left out and a fine point on each crossing in `--ot-rule-strong`, from Paul Rand's dotted sheet.
- A registration cross (two pencil hairlines, `--ot-space-3` long) is centred on each corner of the box, as poster 4 marks its corners with + signs. The first row and column are the sheet's border: the columns numbered 01, 02, 03 along the top and the rows lettered A, B, C down the start edge (Rand's dimension letters), each label hugging the corner where its line begins, in `--ot-pp` pencil tabular figures, clipped where the box ends (48 columns and 26 rows are labelled; the lines go on past them). The content has one cell of padding, so it stands on a line.
- `cell` sets the square (a number of pixels or any length, `--ot-grid-cell`, default `--ot-space-7`). Right to left, the grid, the numbers and the letters run from the right edge.


### ot-tiling (tiling)
- Underneath: native CSS grid. `Tiling` and `Tile` keep their static server-rendered markup, responsive rules and crosses. `TilingEditor` is an opt-in interactive part in the same client entry; every part is server-renderable, with no browser work during render.
- Anatomy: `<div class="ot-tiling" data-variant="rules | crosses">` (the container its narrow layouts are measured against) holding `.ot-tiling-sheet`, the grid, of `.ot-tile`s (`data-place="start-top | end-top | start-foot | end-foot"`, `--span` and `--rows` from `span` and `rows`). Each tile's lines are its `::before`.
- The type-led answer to the bento grid, after "Less is more.": tiles on the 12-column grid held apart by space (`--ot-space-6`) and one ink hairline, never boxed, filled or rounded. Named for the tiling of a plane, which leaves no gaps and no overlaps: neighbours share an edge, so each tile draws only its start and top edge, halfway into the gap, and one line serves both sides (the top line whole, the start line under it, so no pixel is drawn twice). The edges that would fall on the tiling's own border lie half a gap outside it and are clipped, so nothing frames the whole; the lines that stay run a step (`--ot-space-2`) past the edge, as a draughtsman's construction lines overrun, and focus rings keep that step of room.
- A tile's content keeps to one corner (`place`), as the poster keeps its notes; the end corners set it flush to the end. A child with `margin-block-start: auto` goes to the foot, so one tall tile can hold a note at its head and a paragraph at its foot. Type is the content: a headline a word to a tile, standing at the foot on its line; a large number in the last corner.
- Narrow (a tiling under 40rem, by container query), twelve columns' gaps alone would outgrow it, so the sheet falls to two columns: a tile of 6 columns or fewer takes one, a wider one both. Under 24rem it is one column, every tile the whole width and one row high.
- `variant` (`data-variant`; none for the default, `rules`): `crosses`.
- crosses: after "the uncreative", which marks the corners of its block with + signs. No lines: the space alone holds the tiles apart (Principle 1), and a registration cross in the pencil (`--ot-space-3` arms) stands on every corner of every tile, where neighbours' crosses coincide; the outer ones stand half a gap outside the block, unclipped.
- Right to left the start edge, and so the vertical lines, are on the right. Forced colours keep the lines and crosses in CanvasText.

- Editor anatomy: `.ot-tiling.ot-tiling-editor` holds a named action group, a one-line pointer hint, a keyboard-focusable region, numbered columns and the sheet of focusable tiles. Twelve columns fit its container at every width, keeping saved coordinates stable and every resize corner reachable on touch. Fixed row tracks use space-8 through space-9, independent of content height.
- Its move is the drafting sheet: large personal words in expression italic, faint construction guides (dots for crosses), and one separate hairline boundary per editable tile. These functional boundaries never share, overlap or use the static tiling's overrunning lines. A held tile lifts in ink without fill or shadow; a dotted accent hairline previews its landing cells. The end corner has a visible corner mark that grows on hover, within a space-6 hit area; all four edges offer resize marks on hover, selection or focus. A small fraction-style column × row figure accompanies the held tile, left to right and isolated.
- `TilingLayout` is a plain array of `{ id, label, column, row, span, rows }`, with exported `TilingItem` and `TilingEditorProps`. Coordinates are positive whole numbers from 1 at inline start; spans stay within twelve columns, rows at least 1. Ids and labels are non-empty, ids unique, rectangles non-overlapping. Invalid supplied layouts show an alert. Empty space is allowed. Moving onto a matching rectangle swaps the two tiles; other collisions keep neighbours' columns and reflow them down in reading order, preserving content and preventing overlap. Geometry clamps at the grid edges and one-cell minimum.
- `value`, `defaultValue` and `onValueChange` offer controlled or uncontrolled data. Gestures preview locally, including reflow; pointer release or keyboard drop commits a fresh array. Escape or pointer cancellation discards the whole preview without changing saved data. A new external controlled value takes priority over a pending preview. Add and Remove commit directly. `renderTile` supplies content separately. `copyLayout` offers saved JSON on the page and the clipboard, with a selectable fallback when access fails. `defaultHeld` starts a holding specimen. New tiles take the first free four-column space, one row high.
- Drag the whole tile with pointer or touch; six pixels distinguish a drag from a content click. Capture begins only after the threshold, and dragging suppresses the trailing click. Inputs, editable text and descendants marked `data-tiling-no-drag` retain their pointer interaction. Pull the end corner to resize both spans; edges change their own dimension, keeping the opposite edge fixed. RTL mirrors horizontal deltas, keys and the end corner. Click selects a tile for Remove; the selection remains after a drop. Add focuses the new tile, Remove focuses its neighbour or Add when empty.
- Keyboard: Tab reaches each tile and resize control. Enter or Space picks up and drops. Arrows move, Shift + arrows resize; on a corner or edge control arrows resize that dimension. Escape discards the preview. Tab remains normal navigation. The pointer hint is one line, “Drag to move. Drag the corner to resize.” The keyboard line appears only while focus is within the sheet, without moving it. Focus is visible; a polite, atomic live region announces position, size, placement, cancellation, deletion, limits and clipboard results. Forced colours retain boundaries, guides, handles and Highlight landing marks.
- Motion: Glide, answering edits only. The held tile follows the pointer directly; snapping moves the landing outline and reflows neighbours. Neighbours, keyboard edits and the released tile glide over moderato with breath. Resize snaps to whole tracks, with allegro corner growth. Mounts and external updates are still; reduced motion places geometry directly. States: static rules and crosses, editing, holding, RTL editing, interactive content and empty.

### ot-expand (scroll-expand)
- Underneath: native, plus a hook that reads the scroll from the real layout; made of `corners` and `meta`.
- Anatomy: `<figure class="ot-expand" data-variant="horizon">` holding `.ot-expand-frame` (a `ot-corners`) round `.ot-expand-plate` (the content), then `figcaption.ot-expand-caption` with a `ot-meta` row: the caption's words, then `.ot-expand-share` (aria-hidden). The hook sets `--p`, 0 to 1.
- mark (the default): after the printer's crop marks and the frame of SHAPES / GRADIENTS. The plate is cropped (a clip-path) to a small square in the middle (`--ot-expand-mark`, `--ot-space-8`), and the four corner marks, `--ot-space-4` long, stand a step (`--ot-space-2`) outside the crop, as crop marks stand outside the trim. As the page scrolls the crop opens to the whole plate. The caption's row is as wide as the crop (never narrower than 20rem or its space), so its hairlines draw out as it opens, the rule that carries the date and the name; the row ends on the share of the measure the crop has reached, in pencil tabular figures (0.42), as SPECTRA sets 0.13.
- Scrubbed: `--p` is 0 as the plate's top comes in at the foot of the view and 1 once its middle is at the middle of the view (or as far as the page can scroll). It is read from the real layout in a frame asked for by the scroll event, which runs after a smooth scroller (Lenis) has moved the page, so the crop and the page move in the same frame. Nothing eases: it stops when you stop and closes when you scroll back. `progress` pins it.
- horizon: after Eclipse, the disc standing on one line. The crop starts as a hairline across the whole measure (the horizon, drawn in `--ot-rule-strong` while it's shut, and gone by a quarter open) and opens up and down from it; the caption stays full width.
- The whole plate is in the flow and read from the start; only the view of it is cropped. Nothing to focus. Reduced motion, or no script: it stands open. It is symmetric, so right to left changes nothing. Forced colours: the marks and the horizon in CanvasText.

### ot-sign (sign)
- Underneath: hook. Pretext measures the word, kerning included, and the sign is laid out from those widths.
- Anatomy: `<span class="ot-sign" data-variant="dots | words | fill" role="img" aria-label="word"><span class="ot-sign-glyph">…</span>…</span>`: one element per letter or leader, placed by `--x`, `--y`, `--r` and `--k`, since each one travels on its own when the word is said. An empty label hides it (`aria-hidden="true"`), for a control that already says the word.
- An icon made of its own word, after the ampersand (the word "et" worn down into a mark) and Apollinaire's calligrams. Each sign is published three times, one registry item per variant (`sign-<name>-dots`, `-words`, `-fill`), all built on this primitive. The drawings come from Lucide (ISC) converted to strokes a word can read along, or are drawn for 0nlyType; a sign that can't be read in all three variants is left out rather than shipped.
- Variants:
  - `dots`: each stroke ruled in middle-dot leaders, at every size; the leaders grow more slowly than the sign, so a large one is drawn finer. The letters wait unseen at the dots and rise out of them when said.
  - `words`: from 40px up the word is set once, whole, where it reads best: along the drawing's longest straight run (an arrow's word runs toward its head; a ring's word sits on its arc), never upside down (and a word of two letters never turned past 30°, since on end "up" reads "dn"), never kinking more than 20° between letters, tracked no wider than 0.08em and never split across strokes. Every other stroke is ruled in pencil leaders, so the drawing stays quiet and the word is the one thing in ink. Where no stroke holds the word at a size a person reads (a chevron's two short arms, a star, a user), the drawing is drawn a little smaller and the word stands straight beneath it, as a legend under a picture. Stroke words are at least 10px, legends at least 9px. Below 40px no letter can hold a stroke: the sign is drawn as `dots`, and the docs size control says so.
  - `fill`: the word set in rows that fill the drawing's silhouette, running on from one row to the next as a paragraph runs round a picture; each run is spread to its ends so the edge of the type is the outline. A drawing's inner strokes (an eye, a keyhole, a clock's hands) are cut out of the silhouette as lines of paper, so the detail still reads.
- Laid out on the server from a table of advances, so the first paint already shows the sign; Pretext then sets it again with the face's real kerning. The smaller the sign, the heavier its letters (800 at 16px to 500 at 128px), as a punchcutter cuts optical sizes.
- Yours: `face="italic"` (`data-face="italic"`) sets it in the expression: a sign for something that belongs to the person (their mail, their home).
- Said: pointing at the sign, or at the control it sits in, or focusing that control makes the drawing say its word. The letters leave the drawing in reading order, one arpeggio apart, and stand up as the plain word across the middle, no wider than half again the sign (a caption's 11px floor aside); the rest sketch out in pencil and go quiet. Leaving winds them back, last letter first.
- Right to left: a sign that points the way the reader goes (`mirror` in its shape: arrows, chevrons, send, undo) turns round, its strokes still read forwards.
- States: rest, hover, focus. Reduced motion: the word and the drawing change places without travel. Forced colours use CanvasText.

### Globals
- `mark`, `::selection`, and the link on hover: the highlighter, one thing. `--ot-on-mark` on `--ot-mark` is 16.5:1 in every scheme and mode (the highlighter is yellow in Nocturne too; it is the one thing that keeps its colour). `mark` overshoots the words by 0.12em like the link. Selecting inside a highlight reverses to paper on ink (11.7:1 or better), or the selection would vanish into it.
- `:focus-visible`: an accent outline at `--ot-stroke`, offset 4px.

## The overture

### On the home page

- It plays on a browser's first visit to the top of the home page, and never again. A script in the hero's own HTML decides before the hero paints: it reads one boolean, `0nlytype-overture-seen`, in localStorage (falling back once to the older `0db-overture-seen`, so a returning visitor is not shown it again), writes the new key, and only then marks `<html>` with `data-overture-at` (0: its clock counts from the navigation's start). A page whose HTML arrives after the deadline doesn't play it and counts it as seen. One key, one value, no personal data, written before the overture starts, so a reload, back navigation or second tab never replays it. If storage can't be read or written (disabled, private mode, quota) nothing plays and the page arrives settled; nothing waits on storage.
- It is three things on one clock, and nothing else. The letters of the two hands settle into place in a stagger (200ms across the drawing, 150ms for each letter) while the hands close the gap between them to its final width; and as they close, the accent dot of the zero lights over `--ot-allegro`, from `--ot-moderato`. All of it ends by one deadline, 480ms after the page was asked for (owner 2026-10-26: the hero is whole within half a second). That clock is the same inline script that began it, not React, so it ends on time however late the framework's JavaScript arrives. The hands and the zero are drawn when it does arrive; they use only the navigation budget left at mount, at most 350ms, and draw settled immediately when it is exhausted. Layout spends that same budget. The wordmark CSS subtracts elapsed navigation time too; an inline deadline marks `data-hero-settled` on every visit, including when storage is unavailable, so late HTML or CSS cannot restart it.
- It is skippable by anything the person does: any key but Tab and the modifiers (Enter and Space on Skip intro itself are its click, so one press cannot also activate the action that focus moves to), a press, a touch, the wheel or a scroll. A real "Skip intro" bracket button, in the HTML and shown only while it plays, reaches the same end for keyboards and screen readers, before the page's JavaScript has loaded as well as after; the first forward Tab from the document reaches it directly, and if it had focus, focus moves on to the first action. Asking for reduced motion, before or during, ends it.
- Later visits, a link to a part of the page, reduced motion and unavailable storage arrive settled: the hands at rest at their final gap, the dot lit. A reduced-motion visit counts as seen.
- Every load still has one entrance (owner decision 2026-10-11): the hands come in from the sides in at most 350ms, shortened to the navigation budget left at mount, and the name writes itself in ("0nly" rises, "Type." is written in, the full stop lands, all ended by 0.5s). It plays once a load, never on a resize, and not at all under reduced motion or after the 480ms navigation deadline. The dot is lit from the start; only the overture lights it.
- Docs page titles are still: no motion on an information page.

### The specimen

- The title exhales from weight 800 and width 62% to weight 200 and width 112% over `--ot-adagio`, once the fonts are in.
- The manifesto is laid out with `@chenglou/pretext` (`prepareWithSegments` once, `layoutNextLine` per row). Rows that cross the pause's circle are split into two runs that share one cursor. Runs narrower than 160px (half the width on phones) stay empty.
- The fermata sign sits in the hole: an ink arc that draws once and an accent dot. It eases toward the pointer (0.08 per frame), a tap or click places it, and it stays where it's left. Under reduced motion it jumps on click and never follows.
- The real paragraph stays in the DOM, visually hidden, for screen readers and as the fallback if pretext doesn't load.

## Where each move comes from

| Component | Reference | Move |
|---|---|---|
| Sign (`sign`) | The ampersand ("et" worn down into a mark); Apollinaire, *Calligrammes*, 1918 | An icon made of its own word; pointing says the word |
| Statement button (`button`) | "the silence that heals" corners | Corner marks close in on hover |
| Space button (`button`) | "It has to be design." ("Watch this space."); the Renaissance top row | The words spread across the line; gathered, the silence they leave becomes the arrow |
| Repeat button (`button`) | The score's repeat signs | The word between repeat bars; the opening dots set it to go round |
| Checkbox (`checkbox`) | Weingart letter | The pen overshoots; the tally is a fraction |
| Stet checkbox (`checkbox`) | The proofreader's stet | Dots under the words: let it stand |
| Circled checkbox (`checkbox`) | Collage accent rings | One pen loop round the words |
| Radio (`radio-group`) | "It has to be design."; the score's slur | Chosen word turns italic; the rest step back. The dot rides a slur, or the italic slides to the word and sets a full stop |
| Radio, ballot (`radio-group`) | A ballot paper's cross; the collages' pen marks | A hand cross written after the chosen word |
| Radio, sforzando (`radio-group`) | "It has to be design." scale contrast; the score's sfz | Heavy narrow words in a column; the chosen italic swells under the word above |
| Dial (`dial`) | WOVE; Paul Rand dimension lines | Numbers on an arc; the dial rolls. Or a scale on the rim of a wheel you turn, your number read above it |
| Dial, dynamics (`dial`) | The score's dynamics, which name the type scale | The number is set at the size of its loudness, its marking under it |
| Dial, tumbler (`dial`) | The poster's 20(25); a combination lock's wheels | Figure by figure, the one you turn held in parentheses |
| Picks (`picks`) | The score's pizzicato; the rubricated initial | A plucked string carries the dot; or the chosen initial hangs in the margin (a pilcrow, for a script without capitals) |
| Picks, watermark (`picks`) | The poster's ghost numerals; the papermaker's watermark | The chosen name lies huge and faint behind the list |
| Picks, register (`picks`) | The posters' + corner signs; the printer's registration marks | Two crosses mark the chosen pick's far corners |
| Switch (`switch`) | "28 December" dots | The full stop is a dot or a ring |
| Either switch (`switch`) | A printed form's "delete as appropriate" | Both words stand; the one that doesn't apply is struck out |
| Question switch (`switch`) | "It has to be design." (passion? / reason.) | The question mark's hook lifts and leaves a full stop |
| Mode toggle (`mode-toggle`) | The fermata sign; "28 December" dots | A disc, a dot or an eyelid crosses from day to night |
| Knockout mode toggle (`mode-toggle`) | "the uncreative" | Midday to midnight: the second half reversed out of the ink |
| Hour mode toggle (`mode-toggle`) | "the silence that heals" numbers as data | Noon and midnight as 12:00 and 00:00 |
| Stop mode toggle (`mode-toggle`) | The calendar's month over its year; "Renaissance." full stop | Day over Night; the full stop sets from one to the other |
| Dimmer mode toggle (`mode-toggle`) | "the silence that heals" (the page as a lit room); a lamp's fader | One word taking the ink letter by letter; the page's light lowered |
| Noon mode toggle (`mode-toggle`) | "It has to be design." (one letter carries the change) | Noon and Moon, one letter apart; the new sheet falls from the top |
| Word relay (`word-relay`) | Mode toggle's sentence; "It has to be design." (the italic word) | The last word rolls on to the next; the line follows it |
| Statement word relay (`word-relay`) | "It has to be design." scale contrast | Heavy narrow roman; the chosen word large in the italic and the accent, cutting across it |
| Appearance (`appearance`) | "Healthy habits → for creatives"; the score's pizzicato (picks) | The choice written back as one sentence, yours in the italic; the night toggle finishes it |
| Grid (`grid`) | "the silence that heals" faint grid; "Less is more."; the posters' + corner signs | A faint square grid with a cross on each corner and a lettered, numbered border |
| Dots grid (`grid`) | Paul Rand's dotted construction grid and dimension letters | A fine point on each crossing, the rules left out |
| Meter (`meter`) | Paul Rand dimension lines | An italic reading above an empty measure, one index between its limits |
| Slider (`slider`) | Paul Rand dimension lines | Value set in a dimension from zero |
| Spread slider (`slider`) | "Renaissance."; "the uncreative" | The label's letters are the ruler's marks; the hand inks them |
| Dynamics slider (`slider`) | The score's dynamics | The label is as loud as the value |
| Field error (`field`) | Weingart callouts | Pill on a leader line from the baseline |
| Overprint field (`field`) | "It has to be design." | Your italic printed over a heavy condensed label, knocked out in paper |
| Signature field (`field`) | The printed form's signature line | A cross where you write; the label a caption under the line |
| Compose select (`select`) | The compositor distributing type | The word resets letter by letter; shared letters stay in the stick |
| Ruby select (`select`) | Japanese ruby; the small notes hung by a big italic | The other choices ride small above the word |
| Letter form (`form`) | Weingart letter; the postscript | The fields are blanks in prose; what's wrong is said once, in a P.S. |
| Postmark form (`form`) | The postal hand stamp; the dot calendar's day; the collage's hand rings | Sent, the day and the time in a double ring, set askew |
| Progress (`progress`) | Dot calendar | A ring per item fills; the words ink in; done lands a full stop |
| Parentheses progress (`progress`) | 20(25) | The work still to do is the silence inside the parentheses |
| Tally progress (`progress`) | The hand's tally; Basquiat sheet | One stroke per item, the fifth crossing the four |
| Timer (`timer`) | SPECTRA numbers; "28 December" ring | The time large inside a ring that empties behind the accent dot |
| Horizon timer (`timer`) | Eclipse | The dot crosses a half ring like the sun over the horizon |
| Toast (`toast`) | The fermata sign | The arc over the last word empties; pointing holds it |
| Footnote toast (`toast`) | A book's footnotes | Numbered notes under a short rule |
| Dateline toast (`toast`) | SHAPES / GRADIENTS frame row | The sentence and its time on a hairline that runs out |
| Dialog (`dialog`) | SHAPES / GRADIENTS frame | Corners and a metadata row |
| Reply dialog (`dialog`) | "It has to be design." | Heavy roman question, the answers yours in large italic |
| Ruled dialog (`dialog`) | "Less is more." | The question on ruled lines in a grid of hairlines |
| Empty state (`empty`) | SPECTRA crop | Half a zero, which is an arc |
| Tacet empty state (`empty`) | The score's tacet; "It has to be design." | The part's word for silence, set large in the italic |
| Blank empty state (`empty`) | A page left blank on purpose; "Renaissance." corners | The words at the corners, silence in the middle |
| Tabs (`tabs`) | POINT / SPECTRA | A giant, cropped count |
| Tabs, rubato (`tabs`) | The performer's rubato | The chosen word takes its width from the others; the bar keeps its length |
| Tabs, open (`tabs`) | "Less is more." | The rule beside the stacked words breaks at the chosen one |
| Steps (`steps`) | "Less is more." 01 | Large thin figures in the margin |
| Steps, rise (`steps`) | SPECTRA; Paul Rand's grid | Numerals sunk into a line rise out as you reach them |
| Steps, cascade (`steps`) | "Healthy habits → for creatives" | The titles step across the page; an arrow points on |
| Steps, folio (`steps`) | SPECTRA's 1/3; "Less is more." 01 | The whole sequence folded into one fraction beside the step you're on |
| Tour (`tour`) | Weingart letter | Ink callouts hung on leader lines that end in a dot on the thing they are about |
| Index rows (`rows`) | "the uncreative" | The row reverses out of ink |
| Ditto rows (`rows`) | The ledger's ditto mark; SPECTRA's barcode rhythm | What repeats the row above is a ditto mark; pointing spells it out |
| Trail rows (`rows`) | "28 December" dots | A ring per row fills with ink once you've been there; where you are is the accent |
| Swapy (`swapy`) | "the uncreative" | The row you hold reverses out of ink and travels with your hand |
| Transpose swapy (`swapy`) | The proofreader's transposition mark | A loop in the margin from where the row was to where it is, the held name in italic |
| Pager (`pagination`) | WOVE | Weight falls with distance |
| Folio pager (`pagination`) | A book's folio; the fraction | The page over the total, on a leaning stroke |
| Fraction (`fraction`) | 20(25); a display fraction | Yours large in italic, the total small, a pen stroke between; or yours alone, turning over |
| Vinculum fraction (`fraction`) | The printer's built-up fraction; the dot calendar's gone and to come | The count over a bar that is also a gauge of the share |
| Readout fraction (`fraction`) | SPECTRA's 1/3 beside 0.13 | The share hung small after the total as a decimal |
| Neighbours pager (`pagination`) | End-of-chapter pages; "It has to be design." notes on hairline arrows | The pages either side, named at the two ends, each hung on an arrow |
| Barcode pager (`pagination`) | SPECTRA's barcode; "28 December" dots | Every page a line: behind in ink, ahead in pencil, yours in the accent |
| Thumb pager (`pagination`) | A dictionary's thumb index; "the uncreative" | The alphabet as one word, the current letter reversed out |
| Breadcrumbs (`breadcrumb`) | Swiss diagonals | Drawn, leaning hairlines |
| Stack breadcrumbs (`breadcrumb`) | "It has to be design." | The path as a stair, heavy narrow roman down to the large italic |
| Elided breadcrumbs (`breadcrumb`) | Elision in quotation (…) | A full stop for each step left out |
| Disclosure (`accordion`) | The overture; "Less is more." | The question exhales and swells into the heading of its answer |
| Disclosure, run-in (`accordion`) | The book's run-in head | The answer runs on from the question, in one paragraph |
| Disclosure, gloss (`accordion`) | The sidenote; "Less is more." notes | The answer hung beside its question in the outer column |
| Disclosure, horizontal (`accordion`) | "Healthy habits" narrow columns; "Less is more." hairline grid | The open column widens and its name steps up from a stack onto one line |
| Month (`calendar`) | "28 December" dots; half-circle eclipse; "the uncreative" | A disc a day, the number reversed out of the ink; the wait as half-moons; yours circled |
| Month, ruler (`calendar`) | Paul Rand dimension lines; SPECTRA | The month as a measured line; the wait as a dimension |
| Month, ghost (`calendar`) | "the silence that heals" ghost numerals (14 / 08) | The days as figures, read through the date set huge and faint behind them |
| Month, parenthesis (`calendar`) | "20(25)"; the typographic parenthetical | The month as a running line of figures; the wait as an aside in parentheses |
| Tag (`badge`) | The checkbox; Weingart callouts | Removing strikes the word |
| Series tags (`badge`) | The written list (serial punctuation); "Healthy habits → for creatives" | Tags written as one sentence; the commas and "and" re-set as one leaves |
| Seal (`badge`) | A coin's legend; WOVE's numbers on an arc | The legend set round a ring, the face in the middle |
| Marginalia (`note`) | Weingart letter | Highlighter, anchor dot, leader line |
| Ossia note (`note`) | The score's ossia; the interlinear gloss | The note set small over the word, always there |
| Expand note (`note`) | The abbreviation and its long form | The letters move apart and the words grow out of them |
| Revise note (`note`) | Basquiat's struck headline; the Weingart letter's typed page | The word struck through in ink, and the right one written in after it in the italic |
| Toggle (`toggle`) | The fermata sign; the score's tenuto | Held, the word turns italic under the arc and dot, or behind a pen along the line |
| Toggle group (`toggle-group`) | The score's slur; 20(25) | Held neighbours are tied under one slur, or share one pair of parentheses |
| Aside toggle (`toggle`) | "It has to be design." | A tiny note hung beside the held word on a hairline arrow |
| Guides toggle (`toggle`) | Paul Rand, "design" | The held word shown on its dotted baseline and x-height |
| Fingering group (`toggle-group`) | The score's fingering; "Less is more." 01 | Each held word numbered in the order you held it |
| Margin group (`toggle-group`) | The book's side head | A held word crosses the hairline into the margin |
| Button group (`button-group`) | 20(25) | Parentheses hold the set; hairlines stand between |
| Column group (`button-group`) | "Less is more." corner column; Healthy habits | A ragged column; a heavy dash hung in the margin |
| Sentence group (`button-group`) | Healthy habits → (one line of thought); the written list | The actions written into the sentence |
| Input group (`input-group`) | "It has to be design." | Ours upright, yours italic, on one line |
| Legend input group (`input-group`) | "28 December" dots; "the silence that heals" 14 / 08 | Your figure large, our words stacked beside it, the unit agreeing |
| Arrow input group (`input-group`) | "It has to be design.": "Watch this space." | A hairline arrow from your words to the action |
| One-time code (`input-otp`) | "Less is more." rules | Short baselines, three and three |
| Close-up code (`input-otp`) | The proofreader's close-up mark; "the uncreative" | Dots wait; whole, the code closes into one figure |
| Lyric code (`input-otp`) | The score's lyric line; a cheque's sum in words | Each digit read back in words under it |
| Number input (`number-input`) | "Less is more."; the counter's wheels | Less and more in brackets at the line's end; the changed figures turn over |
| Scale number input (`number-input`) | The dial's tuner; Paul Rand dimension ticks | Your figure over the index of a ruler that hangs from the baseline |
| Dropzone (`dropzone`) | "the silence that heals" corners | The area is only its corner marks; files carried over close them in |
| Ghost dropzone (`dropzone`) | "the silence that heals" ghost numerals | The number of files carried stands huge and faint behind the words |
| Combobox, menu, command (`combobox`, `dropdown-menu`, `context-menu`, `command`) | Weingart letter | The highlighter marks what matches |
| Concordance combobox (`combobox`) | The concordance's keyword column; Paul Rand's grid | What you typed stands in one column down the list |
| Pencil combobox (`combobox`) | The letter-cutter's pencilled layout | The rest of the name pencilled after your words; Tab inks it |
| Multiple combobox (`combobox`) | The written list (serial punctuation); ours roman, yours italic | The choices written on the line as one sentence; a chosen row turns italic |
| Date picker, popover (`date-picker`, `popover`) | Weingart callouts | Hung from the opener on a leader line |
| Brace popover (`popover`) | The score's brace; the underbrace | The panel's width gathered to one point at the opener |
| Cut popover (`popover`) | SPECTRA | The panel's edge cuts through the opener's words |
| Alert (`alert`) | The score's double bar | Two bars down the margin; an error, the final bar |
| Cue alert (`alert`) | "It has to be design.": Watch this space | A hairline arrow runs from the margin to the words |
| Errata alert (`alert`) | A book's errata slip | "for *was* read *now*" |
| Skeleton (`skeleton`) | "Less is more." rules | Baselines where the words will be |
| Metrics skeleton (`skeleton`) | Paul Rand construction grid | The letterer's guides: baseline and a dotted x-height |
| Words skeleton (`skeleton`) | A layout dummy's greeking | Lines broken at word spaces |
| Navigation menu (`navigation-menu`) | POINT / SPECTRA | Small words open large names |
| Lead navigation menu (`navigation-menu`) | WOVE; a magazine's contents page | The name you point at stands as the headline beside the list |
| Inline navigation menu (`navigation-menu`) | "Healthy habits → for creatives" | The names open into the line of thought |
| Menubar (`menubar`) | SHAPES / GRADIENTS frame; the folder tab | A frame row of words on a hairline that opens into a pocket under the word |
| Leaders menu (`dropdown-menu`, `context-menu`, `menubar`) | A book's contents page | Leader dots join each word to its keys |
| Marginalia menu (`dropdown-menu`) | "It has to be design." notes on hairline arrows | The word you point at is explained in the margin |
| Orbit context menu (`context-menu`) | WOVE | The words stand on an arc bowed away from the point |
| Context menu point (`context-menu`) | "the uncreative" register crosses | A cross pins where you pressed |
| Caption menubar (`menubar`) | SHAPES / GRADIENTS frame label; an editor's status line | The path to where you are, at the bar's far end |
| Command (`command`) | "the uncreative" | What you type, set as a headline |
| Mesostic command (`command`) | John Cage's mesostics; the printed concordance | Every row set on one axis at its match, your query on the axis above |
| Index command (`command`) | A book's run-in index | Each group a headword with its rows run on as a sentence |
| Sidebar (`sidebar`) | "It has to be design." | Folded, each word keeps its initial |
| Chapter sidebar (`sidebar`) | A book's running contents | Only the chapter you are in stands open |
| Numerals sidebar (`sidebar`) | "the silence that heals" (14 / 08) | Each group's number large, its links small beside it |
| Card (`card`) | SPECTRA crop | A giant letter hanging from the rule, cut off by it |
| Epigraph card (`card`) | A book's epigraph | Their words before the name, indented to the end, the rule opening the title |
| Ledger card (`card`) | The accountant's ruled-off total | A single rule over the total and a double rule under it |
| Hover card (`hover-card`) | POINT crop | The name cut by the card's top edge |
| Entry hover card (`hover-card`) | "the uncreative"; the dictionary entry | The headword broken at its syllables, the stressed one reversed out of the ink |
| Quote hover card (`hover-card`) | The pull quote; POINT crop | Their words in the italic, the opening mark hung in the margin and cut by the edge |
| Tooltip (`tooltip`) | 20(25) | A whisper in thin, tall parentheses |
| Initials tooltip (`tooltip`) | "the uncreative" | The key's letters reversed out of ink in the words they come from |
| Beside tooltip (`tooltip`) | "It has to be design." notes | The whisper on the control's line, on a hairline from it |
| Sheet (`sheet`) | Book spines | The title runs up the spine |
| Drawer (`drawer`) | The fermata sign | The handle is the arc |
| Shelf sheet (`sheet`) | Books on a shelf | The sheet behind shows its spine, and is the way back |
| Rag sheet (`sheet`) | "Healthy habits" silhouette; "Less is more." flush right | The paper is cut to the rag of its lines |
| Fold sheet (`sheet`) | The index entry that opens to its page; "Less is more." hairlines | The row's hairlines part into the page; its name grows into the title |
| Sheet panels (`sheet`) | Book spines; "It has to be design." scale contrast | The spine is the trail: the page you are in large, the way back small below it |
| Thirds drawer (`drawer`) | SPECTRA's "1/3" | It stops at thirds; the share is the fraction in the corner |
| Solid drawer (`drawer`) | The compositor's leads (set solid) | The pull takes out the silence first, then the drawer |
| Collapsible (`collapsible`) | "the silence that heals" captions | "and 4 more" is the control |
| Catchword collapsible (`collapsible`) | The printer's catchword | The rest's first name waits at the foot, then steps up into its row |
| Sotto collapsible (`collapsible`) | SPECTRA's fine print; the score's sotto voce | The rest is said small, never hidden; opening says it in full |
| Resizable, aspect ratio (`resizable`, `aspect-ratio`) | Paul Rand dimension lines | Shares measured; a printer's crop marks |
| Fit resizable (`resizable`) | "It has to be design." heavy condensed; wood type locked to the measure | The title fills its pane, condensing before it shrinks |
| Flow resizable (`resizable`) | The newspaper's continued column | One paragraph runs through the panes; the rule moves the break |
| Diagonal aspect ratio (`aspect-ratio`) | The paste-up artist's scaling diagonal | The ratio written along the line that keeps it |
| Square aspect ratio (`aspect-ratio`) | The book designer's square in the page | The square ruled off, the rest named by its own ratio |
| Figure (`figure`) | "the silence that heals" (camera and archive under the picture); a printer's crop marks | A picture cropped to a ratio, named in type: number, caption, credit spread to the far end |
| Margin figure (`figure`) | A book's side caption in the note columns | The number at the head of the margin, the caption at its foot, level with the picture |
| Scroll area (`scroll-area`) | "Less is more." rules; Paul Rand dimension lines | A rule only where there's more; the box as a ruler, ticked at each section |
| Scrollbar (`scrollbar`) | Paul Rand dimension lines | The page as a ruler, marked at each movement |
| Numeral scrollbar (`scrollbar`) | "the silence that heals" (14 / 08) | The thumb is a figure: how far down you are |
| Leaves scrollbar (`scrollbar`) | "Less but better" calendar | A disc a screenful: read in ink, here in the accent, to come in rings |
| Reading trail (`reading-trail`) | Contents pages; SPECTRA's numbers | The section you are in carries the accent and its leader inks as you read it; folios say where each is reached |
| Rail reading trail (`reading-trail`) | A book's spine; Paul Rand's dimension lines | The section you are in runs down beside the page's rail like the title on a spine |
| Catchword scroll area (`scroll-area`) | The printer's catchword | The first word below waits alone on the foot line |
| Wheel scroll area (`scroll-area`) | WOVE | The rows turn on an arc, the middle one in ink |
| Carousel (`carousel`) | POINT / SPECTRA | One poster at a time, the name sunk under a hairline |
| Segue (`segue`) | The film editor's wipe; SHAPES / GRADIENTS (a hairline carrying a date and a name) | One hairline crosses and the next scene is behind it, its name carried on the line |
| Horizon segue (`segue`) | Eclipse | The line rises like a horizon and the next scene comes up under it |
| Scrub segue (`segue`) | The reader's own pace (the scrub gather) | The line stands as far across as the scroll has gone |
| Marquee (`marquee`) | "Renaissance."; SPECTRA crop | Huge light words, each closed by a full stop, cropped by the frame, drifting until the reader takes over |
| Ticker marquee (`marquee`) | The Renaissance top row; SHAPES / GRADIENTS frame row | Small capitals running between two hairlines |
| Counter marquee (`marquee`) | SPECTRA's two cropped rows | Two rows cut at head and feet, meeting on a hairline, running opposite ways |
| Line carousel (`carousel`) | "It has to be design." (the accent full stop); SPECTRA crop | The names as one line of type, read along |
| Shelf carousel (`carousel`) | Books on a shelf | Spines with the names running up them; one taken out faces you |
| Table (`table`) | Renaissance two-colour | Only the sorted column in ink |
| Forte table (`table`) | SPECTRA; the score's forte | The sorted column set loud, in large thin figures, against small print |
| Cross table (`table`) | A road atlas's distance chart; "Renaissance." two colours | The row and column you point at cross in ink, the meeting cell the accent |
| Data table (`data-table`) | "Renaissance." two colours; the book's folio | The filter a sentence, the sorted column in ink, the count and the folio on the foot line |
| Tail data table (`data-table`) | The collapsible's tail; "the silence that heals" captions | The table ends in the rest of itself: "and 16 more" |
| Chart (`chart`) | POINT / SPECTRA | Tiny data against one giant number |
| Spark chart (`chart`) | Tufte's sparklines; "Healthy habits →" one line of thought | A chart the size of a word, set in the sentence |
| Isotype chart (`chart`) | Neurath's Isotype; "28 December" dots | Count, don't scale: a column of dots per month, rings for the room left |
| Series chart (`chart`) | "It has to be design." two faces; a ledger's sum | Each series its own line and voice; the giant number becomes a ruled list, the sum under the rule |
| Horizontal chart (`chart`) | A ledger, contents-page names | Names in a column at the start, lines run out from the start edge |
| Stat (`stat`) | SPECTRA crop; POINT | Giant thin figures cut off by the one hairline under the row |
| Beside stat (`stat`) | WOVE's 03; "the silence that heals" 14/08 | A heavy figure with its name and a line set beside it |
| Grid stat (`stat`) | "Less is more." | A hairline grid, the name in one corner and the figure in the far one |
| Radial chart (`radial-chart`) | "28 December" rings; SPECTRA | A ring per series, inked as far as it has got, one giant number inside |
| Horizon radial chart (`radial-chart`) | Eclipse | Half rings on a horizon; the number on the line, its words below it |
| Line chart (`line-chart`) | POINT / SPECTRA | One hairline with a ring per point; pointing drops the stem it stands for |
| Smooth line (`line-chart`) | "Less stress. More creativity." script | One monotone sweep through the points, never past them |
| Step line (`line-chart`) | Paul Rand's dimension lines | Right angles only, level across each column |
| Area chart (`area-chart`) | SPECTRA barcode | No fill: the volume is hairlines dropped at barcode rhythm; stacked bands differ by density |
| Pie chart (`pie-chart`) | "28 December" rings; SPECTRA | A ring cut into numbered arcs with paper between them, the total one giant number inside |
| Horizon pie chart (`pie-chart`) | Eclipse | Half a cut ring on a horizon; the total on the line, its words below it |
| Radar chart (`radar-chart`) | Paul Rand's dotted construction grid and dimension lines | A hairline shape on a dotted sheet, the measured axis read as a ticked dimension line |
| Avatar (`avatar`) | "28 December" dots | A ring, an initial, the presence dot |
| Monogram avatar (`avatar`) | "It has to be design."; the stationer's monogram | The given initial in italic cut over the family initial in heavy roman; here, the italic is the accent |
| Fit avatar (`avatar`) | "Less is more."; type set to its measure | The given name set to fill one width; a group stacks between hairlines |
| Item (`item`) | Contents pages | A dotted leader joins name and value |
| Lineation items (`item`) | A critical edition's line numbers | Every fifth line numbered in the margin; the line you point at shows its own |
| Words items (`item`) | SPECTRA's small print; contents pages | The description runs along the leader and runs out before the value |
| Tree (`tree`) | Contents pages; Paul Rand's dimension lines | Names on hairline branches, each hanging from its folder's first letter; ring, dot and accent |
| Activity feed (`activity-feed`) | Contents pages; "Less but better" calendar | A ledger of what happened: who, what, a leader to when; one hairline threads the beads, the newest in the accent |
| Almanac activity feed (`activity-feed`) | "Less but better" calendar | Each day opens on its date set huge and heavy, month and year beside it |
| Lapse activity feed (`activity-feed`) | Principle 1; the marker's lapse | The quiet between entries is given as silence that grows with the gap |
| Outline tree (`tree`) | The book's decimal contents; "the silence that heals" numbers as data | The depth is in the numbers: 1, 1.2, 1.2.3 |
| Prose (`typography`) | Swiss typesetting | Hanging punctuation keeps the edge true |
| Book prose (`typography`) | The book page: "indent or space, never both" | Paragraphs indented, not spaced; the opening line in capitals; a dinkus for a break |
| Run-on prose (`typography`) | The scribe's pilcrow | Paragraphs run on as one block, a ¶ where each begins |
| Source (`source`) | The score's system bracket and bar numbers | A bracket joins the lines; the file's name stands in the margin |
| Gloss source (`source`) | The glossed manuscript; Knuth's literate programming | Comments leave the code for the outer margin, level with their line |
| Passage source (`source`) | The reader's pencil line in the margin | The bracket gathers to the lines that matter; the rest recede |
| Unwrapped source (`source`) | SPECTRA crop; the score's key signature | Lines run whole past the frame and slide under the fixed bracket; the language in small capitals |
| Command line (`command-line`) | A printed form's filled-in line | One line on a baseline; your part in italic |
| Parsed command line (`command-line`) | The interlinear gloss; "the uncreative" definition | Each word over a short rule, its gloss beneath |
| Synopsis command line (`command-line`) | A manual page's synopsis | Your part is a blank you write in; Copy copies your line |
| Message (`message`) | "It has to be design." | Theirs roman, yours italic; only the tail |
| Script message (`message`) | The printed play text | The name in the margin; only the type says who speaks |
| Quote message (`message`) | The quotation mark as the printed balloon; "It has to be design." scale | A large mark opens theirs and closes yours |
| Marker (`marker`) | "Less is more." rules | Rules pushed apart by the word, which stands on them |
| Ribbon marker (`marker`) | The ribbon in a book; one accent for where you are | One accent line across the page where you left off |
| Lapse marker (`marker`) | Principle 1; "Renaissance." spread labels | The pause given as room and tracking, longer silence, more of both |
| Rule marker (`marker`) | "Less is more." rules its rows and columns | A wordless rule, lying or standing; a word stood up reads down it like a spine |
| Typing (`message`) | The ellipsis; the busy button's periods | Only the tail and three periods where their words will be, in pencil |
| Agent state (`agent-state`) | "28 December" discs; the busy button's present-tense word | A ring to come, the accent disc for your turn, an ink disc when done; the ring breathes or goes round while it works |
| Word agent state (`agent-state`) | The word spinner | No mark: the word is inked letter by letter while busy, and takes the accent when it's your turn |
| Agent chat (`agent-chat`) | "It has to be design." (theirs roman, yours italic) | The agent's words roman, yours italic; its question heavy and narrow, your answer large in italic and kept as a receipt |
| Callout agent chat (`agent-chat`) | Weingart letter's callouts | The work and the receipts hang at the far side in reversed pills on leader lines that end in dots |
| Attachment (`attachment`) | "the uncreative" | The extension is the picture |
| Reverse attachment (`attachment`) | "the uncreative" | The extension reversed out of ink, printed across as it arrives |
| Enclosure attachment (`attachment`) | Weingart letter; the letter's enclosure line | "Encl. (2)", the files run on in one sentence |
| Message scroller (`thread`) | WOVE | The new count rolls in an ink pill |
| Rests thread (`thread`) | "Silence is structure"; the score's multi-bar rest; the marker's lapse | The gap is the time between; a long pause is said in it as a lapse |
| Running thread (`thread`) | A book's running head; SHAPES / GRADIENTS frame row | Scrolled back, the day and time ride the top edge on a hairline |
| Questionnaire (`questionnaire`) | Healthy habits → | Your answers written as one sentence |
| Interview questionnaire (`questionnaire`) | The printed interview's Q and A | What's been asked stays as a transcript; press an answer to go back |
| Definition questionnaire (`questionnaire`) | "the uncreative" | The end as a dictionary entry, your headword reversed out of ink |
| Melody (`melody`) | The score | The sentence sits on a stave, a word to a line or space |
| Reverb (`reverb`) | The score's dynamics | The phrase echoes quieter and drifts, ending on a rest |
| Antiphon reverb (`reverb`) | Gabrieli's cori spezzati at San Marco; the Renaissance poster's labels spread to the walls | The echoes answer from either wall in turn |
| Vowels reverb (`reverb`) | A live room, where the consonants are lost first; "the silence that heals" grid | Each echo loses its consonants in place; the vowels ring on in columns |
| Noteheads melody (`melody`) | "Less but better" calendar; the score's lyric underlay | Discs on the staff: sung in ink, here in the accent, to come in rings |
| Cutaway melody (`melody`) | The cutaway score; "Less is more." | The staff is drawn only under the words |
| Measure (`measure`) | Paul Rand dimension lines; SPECTRA's small figures | The paragraph's edge on a track, the comfortable range marked 45 to 75 |
| Alphabets measure (`measure`) | A type specimen's lowercase alphabet length | The track is a ruler of alphabets; the edge cuts a letter in the accent |
| Columns measure (`measure`) | "Healthy habits →" narrow columns | Narrowing the line brings another column in |
| Gather (`gather`) | Dust | The letters settle from scatter to the real layout |
| Link (`link`) | Weingart letter's highlighter | The highlighter passes through the word |
| Reference link (`link`) | The book's reference marks (* † ‡ § ‖ ¶) | No line; a raised mark says there is more |
| Address link (`link`) | The printed page's spelled-out address; 20(25) | Pointing writes where it goes, in parentheses, after the words |
| Key (`kbd`) | "the silence that heals" corners | A key drawn as the corners of its cap |
| Typewriter key (`kbd`) | Weingart's typed letter; "28 December" dots | A ring that inks into a disc, the letter reversed out |
| Chord key (`kbd`) | The figured bass | Modifiers stacked small beside the key, in one cap |
| Corners (`corners`) | "the silence that heals" corners | A frame that doesn't close |
| Viewfinder corners (`corners`) | A camera's framing marks; "the silence that heals" | The frame glides onto what you point at and locks |
| Glide corners (`corners`) | The viewfinder's marks, following focus from control to control; the job of a target cursor | One frame carries across a group, and appears only while you are in it |
| Kagi corners (`corners`) | The Japanese corner brackets 「 」 | Two corners quote a phrase across its lines |
| Tiling (`tiling`) | "Less is more."; Paul Rand's overrunning construction lines | Tiles held apart by one shared hairline, none round the outside; notes kept to the corners |
| Crosses tiling (`tiling`) | "the uncreative" + corner signs | No lines: a registration cross on every tile's corners |
| Editable tiling (`tiling`) | Paul Rand's construction sheet; "the silence that heals" corner marks | A tile lifts in ink, its landing cells dotted in the accent; a growing corner and small span figures make the geometry tangible |
| Meta (`meta`) | SHAPES / GRADIENTS frame row; "Healthy habits" corner notes | Words held apart by hairlines; stacked where they don't fit |
| Scroll expand (`scroll-expand`) | The printer's crop marks; SHAPES / GRADIENTS frame | Crop marks open from a small mark to the measure as you scroll; the caption's rule draws out with them |
| Horizon scroll expand (`scroll-expand`) | Eclipse | The plate opens up and down from a hairline horizon |
| Proportional meta (`meta`) | The score's proportional notation | Each hairline as long as the interval it stands for |
| Credits meta (`meta`) | SPECTRA credits | One rule, small columns of label over value |
| Forme gather (`gather`) | The letterpress forme, type set mirrored in the chase | The line starts as its own mirror image and prints the right way round |
| Coil gather (`gather`) | A ribbon wound on itself; WOVE's figures along an arc | The text starts wound in a spiral and unwinds onto the line |
| Gather by word, by line (`gather`) | "Less is more." a word to a row; the Linotype slug | Whole words, or whole rows cast at once, settle instead of letters |
| Scrub gather (`gather`) | The reader's own pace; a score read at sight | The settle is the scroll: it stops with you and undoes itself backwards |
| Contour (`contour`) | The score's hairpin | The lines taper along a straight edge |
| Tale contour (`contour`) | Carroll's Mouse's Tale (1865) | The type shrinks as the tail winds down the page |
| Cola contour (`contour`) | *Per cola et commata*, text set to be read aloud | A line to each phrase; the edge is the rhythm of speech |
| Calligram (`calligram`) | Apollinaire's calligrams | The paragraph fills the shape; the outline is only implied |
| Rain calligram (`calligram`) | Apollinaire, "Il pleut" (1916) | The words fall in leaning streaks of letters |
| Mirror calligram (`calligram`) | Apollinaire, "Cœur couronne et miroir" (1918); "Healthy habits →" corner notes | The paragraph is the frame; one italic word in the middle |
| Wake (`wake`) | Water parting round a hand; Eclipse's one soft side | The paragraph parts round the pointer and the words move on |
| River wake (`wake`) | The typesetter's river of white; "Less is more." hairline columns | A gutter down the whole paragraph that follows your hand |
| Caesura wake (`wake`) | The caesura in verse and song; "Less is more." lines between hairlines | The line you point at is held apart, a breath above and below |
| Weight wake (`wake`) | The letterpress impression; "It has to be design." heavy condensed roman | Letters under the hand press heavier and narrower, keeping their places |
| Waterfall (`waterfall`) | The foundry's specimen waterfall; the score's dynamics | One sentence at every dynamic, each line filled to the measure |
| Decay waterfall (`waterfall`) | A note's decay after its attack; "It has to be design." scale contrast | The sentence read once, falling a dynamic every line |
| Solo waterfall (`waterfall`) | The mixing desk's solo button | Point at one size and the others fall back to a rule |
| Text ribbon (`text-ribbon`) | WOVE (figures along an arc); the fermata arc | The phrase round an arch, largest at the crest and fading by distance |
| Wave text ribbon (`text-ribbon`) | "Less stress. More creativity." sweeping script | The phrase rides a slow wave across the measure |

### Shared moves
A move serves more than one component only when it is the same idea on purpose. It keeps one name wherever it appears, so it reads as a move of the system and not a coincidence. The shared ones:
- **quote** (message, hover-card): speech marked by the typographer's own balloon, a quotation mark at a title's size hung in the margin before the words, which are in the italic because they are someone's own. The message's marks frame an exchange from both sides; the hover card's is cut by the card's top edge.
- **the dictionary entry** (hover-card `entry`, questionnaire `definition`): the entry of "the uncreative": headword, part of speech, sense, with part of the headword reversed out of the ink. Whose word it is decides the face: the hover card's headword is ours, heavy roman broken at its syllables with the stressed one reversed; the questionnaire's is yours, the whole word in the large italic reversed out.
- **catchword** (scroll-area, collapsible): the printer's catchword, the first word of what comes next waiting alone at the foot, flush to the far edge. The scroll area's is the first word below the view; the collapsible's is the first name of the rest, which grows into its row as it opens.
- **shelf** (carousel, sheet): books on a shelf. What isn't open shows only its spine, and the one you take out faces you. The carousel is a whole shelf of slides, their names running up the spines; the shelf sheet keeps the spine of the sheet behind in view, and it is the way back.
- **fit** (avatar, resizable): type locked up to its measure, as "It has to be design." sets its words edge to edge: one word set to fill a width. The avatar fits a name to a fixed width, so a short name stands large; the resizable pane refits its title as you move the rule, width axis first and size after.
- **dynamics** (slider, dial): the score's dynamics, which already name the type scale, made a control. The value gets louder as it grows, with its marking (pp to ff) in the italic. The two range controls take the two ways type gets louder: the slider's label in weight and width, the dial's numeral in size.
- **gloss** (accordion, source): the sidenote, a note standing in the outer margin beside the line it glosses, flush to the outer edge, with no rule between. The accordion hangs the answer beside its question; the source moves a comment out of the code, level with its line. The interlinear gloss, set over or under the word (note `ossia`, command-line `parsed`), is a different move.
- **circled** (checkbox; calendar `dots`): a ring drawn round what you chose, after the collage's accent rings. The checkbox's is one pen loop round the words, the calendar's an ink ring round the day. The radio group uses the ballot's cross instead, so one choice is never mistaken for several.

## Motion

The owner brought Lenis smooth scrolling back to the site on 2026-10-27 because the landing's scroll-linked animations looked bad with native scrolling, reversing the 2026-10-10 decision. It loads only on the first wheel, pointer press or key event, outside the hero's initial load, and stays off under reduced motion. Scroll-linked pieces read the page in a frame asked for by the scroll event, after the scroller moves it. Anchors use the page's scroll-padding and each target's scroll-margin, with no second offset. Local scrollers and wheel controls keep their `data-lenis-prevent` and `data-lenis-prevent-wheel` marks.

The landing's running section head keeps its title's actual font-size and opening measure, so its lines rebreak as it shrinks. Section typography, direction, padding, column, note fit and unwrapped line widths are cached before hand-over and refreshed on viewport, font and theme changes (including `dir`). Its scroll frame reads the bar and section rects together before it writes. Baseline markers are read after layout in `ResizeObserver`, then the number's shift and the section-rule push-out are written before paint. The pin uses layout containment without paint containment, so its paper and blur keep their reach. Only the bar receives `--pin-k`, rather than inheriting it through the entire document. Phone stacking, right-to-left placement and the fully shrunk reduced-motion head use the same measurements. The landing's live preview of a piece is asked for only once the reading and the page have both been still for 240 ms, and it is fitted and shown only while the page is still: a piece whose example arrives after the page moves again stays unseen until the page has been still for 240 ms, so its fit never runs in a scroll frame.

Three rules, then one articulation per component.

1. **Pointing sketches, choosing inks.** A hover previews in pencil: a hairline strike, a ring, a lean. A commitment draws in ink or the accent.
2. **What's inked lands.** Dots, rings and frames arrive with `--ot-spiccato`, one small rebound.
3. **Strokes pass through.** A stroke drawn on hover leaves the way it was heading: in from the left, off to the right. This uses `background-position` with a `0s` transition, so the anchor flips at once while the size animates.
4. **Demonstrations wait.** An item whose behaviour can be shown (58 scripted ones today, in `components/site/demo-scores.ts`) never plays on its own. Its docs example and the landing's stage offer a Demonstrate bracket button; pressed, it plays one pass from the example's defaults and the button becomes Stop. Stopping, or touching the example, hands it back. Under reduced motion the pass still runs, as instant steps, because the person asked. Discovery only looks; `npm run check:motion` proves that for every scripted entry.

| Component | Articulation | What moves |
|---|---|---|
| Sign (`sign`) | Said | The letters leave the drawing in reading order, one arpeggio apart, and stand up as the plain word; echoes sketch out in pencil |
| Statement button (`button`) | Accent (a pressed note) | Hover widens it; press makes it heavier and narrower, and the corners clasp |
| Bracket button (`button`) | Spiccato | The parentheses step apart and rebound |
| Quiet button (`button`) | Pass-through | The line leaves to the right and redraws from the left |
| Space button (`button`) | Gather | The spaces close, the phrase gathers at the end and the arrow draws in behind it; pressed, the head steps on |
| Repeat button (`button`) | Pencil, then ink | The bars ink and the opening dots land with spiccato |
| Loading (`spinner`) | Breath | The periods lift as they brighten |
| Round (`spinner`) | Canon | Three voices chase round the ring, gathering and spreading |
| Metronome (`spinner`) | Breath | The rod swings a slow beat |
| Fermata (`spinner`) | Held | The arc draws, the dot lands, the hold, the arc lifts |
| Breath (`spinner`) | Breath | The dot opens into a ring and closes |
| Arpeggio (`spinner`) | Arpeggio | The notes rise, struck in turn, and ring |
| Word (`spinner`) | Written | The ink runs through the word and leaves |
| Checkbox (`checkbox`) | Pencil, then ink | A hairline sketch on hover, then the accent strike; the tally's figures turn on their wheels |
| Stet checkbox (`checkbox`) | Pencil, then ink | Pointing pencils the dots in; checking sets them down in the accent with spiccato, and the words turn italic |
| Circled checkbox (`checkbox`) | Written | Pointing draws the loop in pencil; checking inks it; it fades when it goes |
| Radio (`radio-group`) | Legato | The dot glides along a slur, drawn out like a drop of ink; pointing sketches the slur in pencil to a ring |
| Radio, glissando (`radio-group`) | Glissando | The italic wipes through the words between, leading edge first; the full stop lands |
| Radio, ballot (`radio-group`) | Written | The pen writes the cross, one stroke then the other; the old cross passes through; pointing sketches it in pencil |
| Radio, sforzando (`radio-group`) | Sforzando | The chosen italic swells sharply from its baseline; the one it leaves falls back at once |
| Dial (`dial`) | Spiccato | The dial swings a touch past its stop |
| Tuner dial (`dial`) | Coast | The wheel follows the hand, coasts after a flick and lands on a step with one swing past; the reading turns like a counter |
| Dial, dynamics (`dial`) | Crescendo | The numeral grows with the hand, slowly then fast, and its marking changes under it |
| Dial, tumbler (`dial`) | Tumbler | A changed figure rolls in the way it turned, units first; the parentheses slide to the next figure |
| Picks (`picks`) | Pizzicato | A ring on hover; the dot slides to the choice along a string that is plucked and rings to silence |
| Picks, rubric (`picks`) | Rubrication | The initial leans on hover; chosen, it grows into the margin as a two-line accent capital and the name closes up in italic |
| Picks, watermark (`picks`) | Held to the light | One mark fades down and the next comes up out of the paper |
| Picks, register (`picks`) | Register | Pencil crosses on hover; chosen, the accent pair travels to the new corners, turning a quarter, the far one a beat behind |
| Switch (`switch`) | Legato | The word rolls; ink fills the full stop from its rim |
| Either switch (`switch`) | Pass-through | The strike lifts off one word to the right and draws through the other from the left |
| Question switch (`switch`) | Answer | The hook wipes down to its dot, which stays as the full stop; the sentence inks |
| Mode toggle (`mode-toggle`) | Legato | The disc slides, the dot sets, the lid closes, the word rolls |
| Knockout mode toggle (`mode-toggle`) | Dusk and dawn | The ink falls over the second half from above and night reverses out; at dawn it lifts |
| Hour mode toggle (`mode-toggle`) | Carry | The hour turns forward either way, the units first and the tens one step behind |
| Stop mode toggle (`mode-toggle`) | Set | The full stop sets one line, landing with spiccato; the page dissolves at allegro; reduced motion swaps instantly |
| Dimmer mode toggle (`mode-toggle`) | Fader | The ink comes up through the letters in reading order, or drains from the last; the page dims to night or is raised to day, moderato |
| Noon mode toggle (`mode-toggle`) | Nightfall | Only the initial rolls, N down and M from above; the new sheet falls from the top edge on one straight line, moderato |
| Word relay (`word-relay`) | Roll | Every 2400ms by default, or on press/keys, the word turns over and the line follows its width; pausable, off under reduced motion (owner-approved 2026-10-01) |
| Appearance (`appearance`) | Opening | The new page opens over the old as a circle from the control you touched |
| Meter (`meter`) | Legato | A changed figure and its index glide to their new places, then rest |
| Slider (`slider`) | Lift | The value rises while the hand is on it |
| Spread slider (`slider`) | Ink follows | The ink runs through the letters with the hand |
| Dynamics slider (`slider`) | Swell | The word grows heavier and wider with the hand |
| Field (`field`) | From the touch | The accent line grows out from where you touched it |
| Field error (`field`) | Arpeggio | Dot, leader, pill, in that order |
| Overprint field (`field`) | Inhale | Arriving, the label draws in its width and your words take the accent |
| Signature field (`field`) | Spiccato | Arriving, the + turns to × and inks; written, it steps back to pencil |
| Select (`select`) | Arpeggio | The options arrive in turn |
| Compose select (`select`) | Composing | Shared letters slide to their places; the others fall out in pencil and drop in with spiccato; the hairline stretches |
| Ruby select (`select`) | Interlinear | The picked word comes down onto the line as the old one goes up into the ruby; the rest glide aside |
| Letter form (`form`) | Arrive | The postscript arrives once, after a failed send |
| Postmark form (`form`) | Stamp | The postmark comes down from above, turning into its tilt, with spiccato |
| Progress (`progress`) | Andante, then spiccato | The line, the ticking italic numeral and the inked words glide on one eased value; each ring and the closing full stop pop as they land |
| Parentheses progress (`progress`) | Closing | The parentheses glide in on the words from both ends on the eased value; unknown, they draw a little way in and back |
| Tally progress (`progress`) | Written | Ink draws down each stroke as its item lands, and across the fifth; the full stop lands after the last gate |
| Timer (`timer`) | Countdown | Pressed Start, the dot runs clockwise and the arc empties behind it; each changed figure turns over like a counter's wheel; Reset sweeps the ring back; done, the full stop lands |
| Horizon timer (`timer`) | Crossing | The dot crosses the half ring toward the end of the horizon as the arc empties |
| Toast (`toast`) | Written | It rises, the sentence writes in, and the stack closes over the gap when it leaves |
| Footnote toast (`toast`) | Spiccato | The rule draws in over the first note; each note rises and its number lands |
| Dateline toast (`toast`) | Held | The hairline runs out toward the time, and holds while pointed at |
| Dialog (`dialog`) | Breath out | The corners open out, the rule draws, the question exhales |
| Reply dialog (`dialog`) | Spiccato | The answer you point at inks and its accent full stop lands |
| Ruled dialog (`dialog`) | Drawn | The rules under the question draw across from the start |
| Empty state (`empty`) | Rise | The arc lifts as you reach for the action |
| Tacet empty state (`empty`) | Morendo | The word dies away to the rule and loosens as you reach for the action |
| Blank empty state (`empty`) | Making room | The middle line pales and loosens as you reach for the action |
| Tabs (`tabs`) | Inchworm | The leading edge first; the count rolls |
| Tabs, rubato (`tabs`) | Rubato | The chosen word widens and thickens as the others give way |
| Tabs, open (`tabs`) | Inchworm | The break in the rule moves to the chosen word, leading edge first |
| Steps (`steps`) | Spiccato | The current numeral lands |
| Steps, rise (`steps`) | Rise | The reached numeral rises out of the line |
| Steps, cascade (`steps`) | Onward | The arrow steps forward into place |
| Steps, folio (`steps`) | Roll | The figure turns over to the new step, figure by figure |
| Tour (`tour`) | Arpeggio | On Next or Back only: the dot lands, the leader draws out, the callout spreads from its tip |
| Index rows (`rows`) | Roller | The ink follows the pointer in and out |
| Pager (`pagination`) | Pencil, then ink | A ring on hover; the accent dot lands |
| Neighbours pager (`pagination`) | Legato | The name thickens as you point; the word inks and the arrow steps its way |
| Barcode pager (`pagination`) | Spiccato | The line you point at lifts and its number takes the place of yours |
| Thumb pager (`pagination`) | Pencil, then ink | Pointing sketches the block in rule; the chosen letter is reversed out of the accent |
| Breadcrumbs (`breadcrumb`) | Lean | The hairlines either side hold the step you point at |
| Stack breadcrumbs (`breadcrumb`) | Recede | Pointing at a step sets every step below it back in pencil |
| Elided breadcrumbs (`breadcrumb`) | Arpeggio | For a still pointer or focus, each full stop opens back into its word, in turn |
| Disclosure (`accordion`) | Spiccato | The cross winds past; the question swells; the answer settles |
| Disclosure, run-in (`accordion`) | Written | The ellipsis goes and the answer is written on from the question, line by line |
| Disclosure, gloss (`accordion`) | Aside | The gloss arrives from the question's side |
| Disclosure, horizontal (`accordion`) | Widen | The column widens and the name re-sets onto one line; the answer arrives once there's room |
| Month (`calendar`) | Arpeggio | A pencil ring draws round the day you point at and inks when you choose, landing with spiccato; the moons wax in turn; the days sweep in from the turn |
| Month, ruler (`calendar`) | Legato | The numeral glides along the line to your day and the dimension stretches after it; dragging sketches the day under the hand in pencil |
| Month, ghost (`calendar`) | Surfacing | A pencil hairline draws out under the figure you point at; choosing (or turning the month) sets a new ghost that rises into view, the month's number an arpeggio behind the day's |
| Month, parenthesis (`calendar`) | Spiccato | Pointing sketches pencil parentheses round a figure; choosing inks the aside and its parentheses land with one small rebound |
| Tag (`badge`) | Close-up | Struck, then closed; neighbours slide in |
| Series tags (`badge`) | Close-up | As the tag, and the punctuation re-sets round the gap |
| Seal (`badge`) | Turn | Pointing turns the legend 30°, andante; leaving turns it back |
| Marginalia (`note`) | Ink spread | Mark, anchor, line, note; reversed on leaving |
| Ossia note (`note`) | Ink | Pointing inks the note, allegro |
| Expand note (`note`) | Unfurl | Pressed, the words grow out of their initials, moderato, exhale; pressed again, they close |
| Revise note (`note`) | Pencil, then ink, then written | Pointing sketches the strike in pencil; pressed, the pen strikes it in ink and the replacement is written in from the start; pressed again, both lift |
| Ditto rows (`rows`) | Spell out | The ditto marks turn back into words, allegro |
| Trail rows (`rows`) | Spiccato | Pointing inks the ring and it grows a quarter, landing with one rebound |
| Editable tiling (`tiling`) | Glide | The held tile follows the hand; neighbours and the drop glide at moderato with breath. Resizing snaps; its corner grows at allegro. Reduced motion places directly; mounts and external updates stay still |
| Swapy (`swapy`) | Glide | Held, the ink prints across the row; the rows glide to their new places and their numbers turn over |
| Transpose swapy (`swapy`) | Mark | The loop follows the held row through the margin, and fades when it is set down |
| Link (`link`) | Pass-through | The highlighter passes through the word and the line gives way; an external link's ↗ steps the way it points |
| Key (`kbd`) | Press | The corners close and the cap goes down with your key |
| Typewriter key (`kbd`) | Spiccato | Pressed, the ring inks into a disc, goes down and lands with one small rebound |
| Address link (`link`) | Written | Pointing writes the address in from where the words end; leaving, it's taken back the other way |
| Viewfinder corners (`corners`) | Spiccato | The marks glide onto what you point at and lock with one small rebound, then open back out to the whole |
| Glide corners (`corners`) | Glide | Over moderato with breath, the frame glides from control to control and lands without a rebound; from rest it only fades in, and it fades out where it was |
| Scroll expand (`scroll-expand`) | Rubato (the reader's tempo) | The crop and its marks open only as far as the scroll has gone, forwards or back |
| Fraction (`fraction`) | Spiccato | A changed number turns over the way the count went, only the figures that changed, the carry one step behind; the stroke ticks once and settles |
| Vinculum fraction (`fraction`) | Breath | The ink eases along the bar to the new share while the figures turn |
| Readout fraction (`fraction`) | Roll | The decimal turns over with the count |
| Movement bar | Glissando | The movement name rolls up reading on, and down reading back |
| Toggle (`toggle`) | Pencil, then ink | The arc sketches from its start foot on hover; held, it inks, the dot lands and the word leans into the italic |
| Tenuto toggle (`toggle`) | Written | The line sketches on hover; held, a pen inks it and rewrites the word in the italic behind it, and releasing writes it back |
| Aside toggle (`toggle`) | Pencil, then ink | The hairline sketches beside the word; held, it inks, the head lands against the word and the note is written in at its tail |
| Guides toggle (`toggle`) | Pass-through | The baseline sketches in dots from the start; held, the x-height line draws from the end, they pass through the word and it leans into the italic |
| Fingering group (`toggle-group`) | Spiccato | The number lands on the held word; pointing pencils the next one; letting one go counts the later ones down |
| Margin group (`toggle-group`) | Crossing | The held word crosses the hairline into the margin as it turns italic; pointing leans it toward the line |
| Toggle group (`toggle-group`) | Legato | The slur or the pair stretches over a held neighbour and glides to a new choice, leading edge first; the word turns italic as it rises |
| Button group (`button-group`) | Pass-through | The line under an action leaves the way it was heading |
| Column group (`button-group`) | Hang | The dash grows out of the word into the margin and goes back into it |
| Input group (`input-group`) | From the touch | The accent line grows only under your part |
| Arrow input group (`input-group`) | Give way | The shaft shortens as you write, inks when it's ready, and steps toward the action you point at |
| One-time code (`input-otp`) | Drop | Each digit drops onto its line; whole, the lines ink in turn |
| Close-up code (`input-otp`) | Close up | Whole, the spaces close; the two arcs land over and under the join |
| Lyric code (`input-otp`) | Read back | Each word opens from its middle under its digit |
| Number input (`number-input`) | Counter | A step turns the changed figures over, units first, each place an arpeggio later |
| Scale number input (`number-input`) | Slide | A step slides the ruler a tick and lands with spiccato; dragged, it follows the hand |
| Dropzone (`dropzone`) | Close in | Files carried over close the corners in and ink them, landing with spiccato |
| Ghost dropzone (`dropzone`) | Count | The ghost number turns over as files come and go |
| Combobox (`combobox`) | Arpeggio | The suggestions arrive in turn |
| Concordance combobox (`combobox`) | Glide to the axis | As you type, each row glides sideways to keep the match in its column |
| Pencil combobox (`combobox`) | Pencil, then ink | Chosen, the word inks from pencil |
| Multiple combobox (`combobox`) | Close-up | A word taken out is struck, then the sentence closes up and re-sets its commas |
| Date picker (`date-picker`) | Spiccato | The month hangs from the sentence; the date writes in |
| Alert (`alert`) | Double bar | The bars draw down, then the words arrive |
| Cue alert (`alert`) | Cue | The line draws in from the margin, the head lands, the words arrive |
| Errata alert (`alert`) | Written | The old words step back to pencil; the new ones write in |
| Skeleton (`skeleton`) | Reading | A pencil stroke reads along each line in turn |
| Metrics skeleton (`skeleton`) | Ruling | The dotted x-height is ruled out along each line in turn and passes off the end |
| Words skeleton (`skeleton`) | Reading | The pencil stroke reads along each line word by word |
| Popover (`popover`) | Arpeggio | Dot, leader, panel |
| Brace popover (`popover`) | Gather | The arms open out from the middle to the ends of the words, then the ends curl in |
| Cut popover (`popover`) | Cut | The panel's edge rises from the foot of the words to their middle |
| Menu (`dropdown-menu`, `context-menu`) | Arpeggio | Dot, leader, words in turn; a context menu spreads from the point |
| Menubar (`menubar`) | Pocket | The rule folds down around the open menu and back up; the menu unrolls out of it and rolls back in |
| Leaders menu (`dropdown-menu`, `context-menu`, `menubar`) | Pass-through | The dots of the word you point at ink from the word to its keys and leave the same way |
| Marginalia menu (`dropdown-menu`) | Glide | The note glides beside the list to the word you point at |
| Orbit context menu (`context-menu`) | Spiccato | The words swing out to the arc as they arrive; the dot you point at lands as the accent |
| Caption menubar (`menubar`) | Arrive | The path's last step arrives as you move |
| Navigation menu (`navigation-menu`) | Arpeggio | The rule draws across; the names arrive; the arrow turns |
| Lead navigation menu (`navigation-menu`) | Step up | The name you point at steps up into the headline |
| Inline navigation menu (`navigation-menu`) | Opening | The line opens after the word and the words after it make room; the arrow inks and leans toward the names |
| Command (`command`) | Arpeggio | The rows arrive; the chosen one steps forward |
| Mesostic command (`command`) | Ink | The rows arrive on the axis; the chosen line inks and its arrow draws in |
| Index command (`command`) | Arpeggio | The entries fade into the sentence in turn; the chosen one's underline inks |
| Sidebar (`sidebar`) | Fold | The words fold to their initials in turn |
| Chapter sidebar (`sidebar`) | Open | A still pointer opens a closed group under its name; leaving closes it |
| Numerals sidebar (`sidebar`) | Ink | Pointing into a group inks its number |
| Card (`card`) | Pass-through | An ink stroke passes along the rule, over the letter's cut |
| Epigraph card (`card`) | Pass-through | The stroke passes along the rule over the title |
| Hover card (`hover-card`) | Slide | The large name slides in to meet you |
| Entry hover card (`hover-card`) | Spelling out | The headword opens at its breaks and each point lands in turn |
| Quote hover card (`hover-card`) | Spiccato | The mark drops into the margin and lands |
| Tooltip (`tooltip`) | Wait | It appears only for a still pointer |
| Initials tooltip (`tooltip`) | Spiccato | The initials land, then the words are written in round them |
| Beside tooltip (`tooltip`) | Reach | The hairline draws out from the control; the words arrive at its end |
| Sheet (`sheet`) | Spine | The page slides in; the title runs up the spine |
| Drawer (`drawer`) | Spiccato | It lands with a rebound; it follows your drag down |
| Shelf sheet (`sheet`) | Spine | The front sheet slides in over the one behind; that spine sets back to pencil |
| Rag sheet (`sheet`) | Reach | The cut is drawn down its steps as the sheet arrives |
| Fold sheet (`sheet`) | Unfold | The row's hairlines part to the window's edges as its name grows into the title; put away, it folds back |
| Sheet panels (`sheet`) | Spine | The name you left shrinks into the trail and the new one writes up the spine; the pages cross |
| Thirds drawer (`drawer`) | Spiccato | It follows the hand both ways and lands on a third; the fraction's wheels turn |
| Solid drawer (`drawer`) | Legato | The gaps close under the hand, then the drawer follows it down |
| Wake (`wake`) | Wake | The text parts around the pointer; the circle swells as you arrive and closes as you leave |
| River wake (`wake`) | Wake | The gutter opens at your hand, follows it across and closes as you leave |
| Caesura wake (`wake`) | Breath | The paragraph opens at your line and follows you down it, closing as you leave |
| Weight wake (`wake`) | Press | The weight swells under your hand and follows it, rests when you are still, eases back as you leave |
| Solo waterfall (`waterfall`) | Mute | The lines you are not pointing at ease back to a rule |
| Measure (`measure`) | Drag | The right edge follows the hand and the lines are laid again on every move |
| Alphabets measure (`measure`) | Drag | The edge cuts a new letter of the ruler, and that letter takes the accent |
| Columns measure (`measure`) | Drag | Columns come in and go as the line narrows and widens |
| Collapsible (`collapsible`) | Arpeggio | The rest opens at reading speed, line by line |
| Catchword collapsible (`collapsible`) | Arpeggio | The catchword steps back to the start and grows; the rows follow in turn |
| Sotto collapsible (`collapsible`) | Crescendo | Each name grows from fine print into its row, in turn |
| Resizable (`resizable`) | Measure | The rule inks; the dimensions appear while held |
| Fit resizable (`resizable`) | Measure | The titles condense and extend with the rule, frame by frame |
| Flow resizable (`resizable`) | Measure | The lines re-break under the hand as the rule moves |
| Aspect ratio (`aspect-ratio`) | Breath | The frame eases to the ratio; the fraction rolls |
| Diagonal aspect ratio (`aspect-ratio`) | Swing | The line and the ratio written on it swing to the new diagonal with the frame |
| Square aspect ratio (`aspect-ratio`) | Glide | The square's rule glides to its new place; the remainder's name comes back once it lands |
| Figure (`figure`) | Breath | The frame eases to a new ratio and the picture recrops inside it |
| Scrollbar (`scrollbar`) | Arpeggio, then ink | The numbers arrive down the rail; held, the thumb takes the accent |
| Scroll area (`scroll-area`) | Arpeggio, then ink | The page rail's: its sections' numbers arrive down the rail (along it, sideways); held, the thumb takes the accent |
| Numeral scrollbar (`scrollbar`) | Count | The figure counts through every number as you scroll; held, it takes the accent |
| Leaves scrollbar (`scrollbar`) | Ink | The disc you reach takes the accent and the one you leave sets to ink |
| Reading trail (`reading-trail`) | Ink | The current section's leader inks as far as you have read, following the scroll |
| Rail reading trail (`reading-trail`) | Turn | The spine's head rises in when you reach the next section, never on arrival |
| Catchword scroll area (`scroll-area`) | Turn | Each new catchword rises onto the foot line |
| Wheel scroll area (`scroll-area`) | Wheel | The rows ride the arc as you scroll, inking as they pass the middle |
| Carousel (`carousel`) | Roll | The count rolls the way you travel |
| Segue (`segue`) | Wipe | The hairline crosses carrying the next scene's number and name; the next scene drifts in behind it and the last is pushed on; back, it crosses the other way |
| Horizon segue (`segue`) | Sunrise | The line rises from the foot and the next scene comes up under it; back, it sets |
| Scrub segue (`segue`) | Rubato (the reader's tempo) | The line travels only as far as the scroll has gone, forwards or back |
| Marquee (`marquee`) | Rubato (the reader's tempo) | A 24px/s drift yields to scroll; pausable, off under reduced motion (owner-approved 2026-10-01) |
| Counter marquee (`marquee`) | Contrary motion | The two clipped rows drift or scroll opposite ways, sharing the same pause and reduced-motion rules |
| Line carousel (`carousel`) | Reading on | The line slides; the name arriving at the start inks, its full stop takes the accent and its facts appear, while the one you left goes back to pencil |
| Shelf carousel (`carousel`) | Taken out | The spine widens and its name turns to face you; the other narrows back into a spine |
| Table (`table`) | Glide | The rows glide to their new order; a pick's ring lands |
| Forte table (`table`) | Crescendo | Re-sorted, the old column falls quiet as the new one swells, while the rows glide |
| Cross table (`table`) | Ink follows | The crossing inks under the pointer, allegro, and the rest falls to pencil |
| Data table (`data-table`) | Glide, then arrive | Narrowed or sorted, the rows glide; a new page's rows arrive in turn |
| Tail data table (`data-table`) | Arrive | The next rows arrive in turn under the last |
| Chart (`chart`) | Roll | The number rolls to the month you point at, and back |
| Spark chart (`chart`) | Roll | The number in the sentence rolls to the stem you point at, and back |
| Isotype chart (`chart`) | Count | The other columns step back; the pointed column's dots pop up from the bottom in turn with spiccato as the number rolls |
| Series chart (`chart`) | Roll | Each figure in the list that changed rolls its own way; the stems ink |
| Stat (`stat`) | Roll | A changed figure turns over like a counter's wheels, units first, only the digits that changed |
| Radial chart (`radial-chart`) | Roll | The pointed ring inks, the others step back, the accent dot moves to it and the number rolls; a changed value glides at andante |
| Line chart (`line-chart`) | Roll | The ring swells, a drop runs down from it to the baseline (moderato, exhale) and the number rolls; leaving, the drop withdraws |
| Area chart (`area-chart`) | Roll | As line-chart: the drop runs down through the barcode and the numbers roll |
| Pie chart (`pie-chart`) | Roll | The pointed arc inks in the accent and swells, the others step back, and the total rolls down to its share and back up to the total |
| Radar chart (`radar-chart`) | Measure | The dimension line is drawn out from the centre to the point (moderato, exhale), its figure set on it; the bead lands in the accent with spiccato |
| Source (`source`) | Run | Copying runs the accent down the bracket once; the label rolls to Copied |
| Gloss source (`source`) | Answer | Pointing at a note inks its line, and pointing at a line inks its note |
| Passage source (`source`) | Run | Copying runs the accent down the passage, line by line, and it settles back to ink |
| Unwrapped source (`source`) | Slide | Only your scroll moves the lines; the numbers and the bracket stay |
| Command line (`command-line`) | Drawn | Copying draws the baseline in the accent, left to right, and lets it go |
| Parsed command line (`command-line`) | Ink | Pointing at a word inks its rule and its gloss |
| Synopsis command line (`command-line`) | Fill in | The blank grows with what you write; focus draws the accent under it |
| Avatar (`avatar`) | Spiccato | A group steps apart to be counted |
| Monogram avatar (`avatar`) | Spiccato | Pointed at, the italic steps off the roman and rebounds into place |
| Item (`item`) | Ink | The leader inks from one end to the other |
| Lineation items (`item`) | Ink | The pointed line's number inks in the margin |
| Words items (`item`) | Ink | The words ink to graphite with their leader |
| Tree (`tree`) | Grow | Opening a folder draws its branch down and its names arrive in turn; the chosen dot lands |
| Activity feed (`activity-feed`) | Arpeggio | Opened, the rest arrive down the line in turn; pointing inks an entry's leader and time |
| Message (`message`) | Written | New messages write in; the status ring fills to a dot |
| Reactions (`message`) | Roll | Yours turns italic; the count rolls |
| Quote message (`message`) | Spiccato | Arriving, the quotation mark lands, then the words write in |
| Typing (`message`) | Breath | Only while they write: the periods lift as they brighten, in turn |
| Marker (`marker`) | Spread | The rules draw outward from the word, or from the middle of a wordless rule (up and down when it stands) |
| Ribbon marker (`marker`) | Drawn | The accent line draws from the start to the word |
| Lapse marker (`marker`) | Opening | The silence opens around the words and their letters spread |
| Agent state (`agent-state`) | Breath, then canon | Only while thinking (the ring breathes) or working (three voices round it); a new ring or disc lands with spiccato |
| Agent chat (`agent-chat`) | Count in | Files dragged over are counted into the enclosure line before you let go; the rest is its parts' own motion, each answering you or the agent |
| Attachment (`attachment`) | Count in | The ring fills, closes, and gives way to a full stop that lands |
| Reverse attachment (`attachment`) | Print | The ink block runs across the extension as the file arrives |
| Message scroller (`thread`) | Spiccato | The new-messages pill lands; its count rolls |
| Running thread (`thread`) | Roll | Crossing into another day, the running head's day rolls |
| Questionnaire (`questionnaire`) | Turn | Questions turn in from where you're heading; the sentence writes in |
| Interview questionnaire (`questionnaire`) | Minutes | The answered pair is written into the transcript as the next question turns in |
| Definition questionnaire (`questionnaire`) | Reversal | The ink block draws across and the headword appears in it where it has reached; the sense writes in after |
| Melody (`melody`) | Arpeggio | The word you point at sounds, then the rest of the phrase in turn; the last holds under its fermata |
| Reverb (`reverb`) | Decay | The echoes drift a little further while pointed at |
| Antiphon reverb (`reverb`) | Decay | The echoes' letters open while pointed at, one after another |
| Vowels reverb (`reverb`) | Sketch | The lost letters come back in pencil while pointed at |
| Noteheads melody (`melody`) | Ink | The discs fill in turn up to the word you're at, which takes the accent |
| Gather (`gather`) | Settle | The letters fly in from dust and land, one after another |
| Forme gather (`gather`) | Impression | Each letter turns over as it crosses from its mirror to its place, and inks |
| Coil gather (`gather`) | Unwind | The letters leave the spiral in reading order and lay themselves along the line |
| Scrub gather (`gather`) | Rubato (the reader's tempo) | The pieces travel only as far as the scroll has gone, forwards or back |
| Tale contour (`contour`) | Swish | The tail's wave moves with the hand across it; the lines further down follow later |
| Cola contour (`contour`) | Phrasing | The phrase you point at stays in ink; the others rest in pencil |
| Text ribbon (`text-ribbon`) | Carried | A 0.6em/s drift yields to drag, keys and scroll; pausable, off under reduced motion (owner-approved 2026-10-01) |
| Day and Nocturne | Dusk and dawn | A View Transition: Nocturne falls from the top with a soft edge, and day comes up from the bottom. Schemes and keys cross-fade. |

`roll(el, apply, dist, dir)` in the specimen is the one helper for every rolling number (`dir` 1 counts up, −1 counts down). The library ships it as `roll()` in `@/lib/0nlytype/roll`. Fraction, NumberInput and Timer share one digit scheduler: each new target cancels pending carries and in-flight turns before scheduling from the displayed value; unmounting cancels the work too.

## Registry conventions

- One item is four files: `registry/0nlytype/ui/<item>.tsx`, its sidecar `registry/0nlytype/styles/<item>.css`, the docs meta `content/<item>.ts` and the live example `examples/<item>.tsx`. The base pieces (link, kbd, fraction, meta, corners) have no sidecar; their CSS is in base.css.
- Item names follow shadcn where shadcn has the component; the class keeps the poster's word. `slider` renders `.ot-ruler`.
- Sidecars are wrapped in `@layer components`; base.css is in `@layer base`, so a consumer's Tailwind utilities still win. `!important` appears only on `[hidden]` and `.ot-sr`.
- Direction: logical properties, and `:is([dir="rtl"], [dir="rtl"] *)` where a stroke has a direction. Never `:dir()`: Lightning CSS, which Next and Tailwind run, lowers it to a list of `:lang()` that misses a page that only sets `dir`.
- Variants are `data-variant` and `data-size`, never classes. There's no cva.
- React 19: `ref` is a plain prop. `"use client"` appears only in files that need state, effects, handlers or Radix, so every other item works in a Server Component. Each root and part carries `data-slot`; `className` merges through `cn`.
- Imports inside the registry are `@/registry/0nlytype/ui/<x>`, `@/registry/0nlytype/lib/utils` and `@/registry/0nlytype/lib/<x>`. The build rewrites them to `@/components/ui/<x>`, `@/lib/utils` and `@/lib/0nlytype/<x>`.
- `registryDependencies` is the base item plus every sibling an item imports or lists in its meta's `uses` (a sibling whose classes its CSS borrows). npm dependencies come from its imports.
- The registry is held to the shadcn directory's health checks:
  - `registry.json`'s `name` equals the namespace;
  - every item name is distinct;
  - the index and every item validate against the schema;
  - each item installs on its own with `shadcn add --dry-run`;
  - every endpoint answers over HTTPS with `application/json`.

  An item is added only when it does a job of its own. Never add aliases or splits to raise the count.
- `npm run registry:build` writes `registry.json`, `public/r/*.json`, `app/registry.css` and `lib/site/entries.ts`. All four are committed, and `check:registry` fails if they're stale.

## Docs conventions

- The site and the registry live under `/ui` (Next `basePath`), at https://thedirectors.agency/ui. Next's `Link` adds the base path itself; every other same-origin URL (a `fetch`, an `img`, CSS) is built through `lib/site/config.mjs`, never written by hand.
- The docs are built only from 0nlyType items, plus page layout in `app/site.css`. When a page needs something the library lacks, it's built as an item first.
- A scripted example shows a Demonstrate control above it (see Motion, rule 4). Page titles stay still; the overture exists only on the home page.
- Every item page is generated from `content/<item>.ts`, `examples/<item>.tsx` and this file: its contract under `### ot-<class> (<item>)`, and its rows in "Where each move comes from" and "Motion", which name it in backticks.
- `examples/<item>.tsx` default-exports `Example`, the specimen's demo with real copy. An optional `States` export pins each state with `data-force` on the item's root, inside `<State label>`.
- Theme choices live on `<html>` as `data-mode`, `data-scheme`, `data-key` and `data-pair`, stored under `0nlytype-theme` and restored by a script in `<head>` before first paint. The head script reads the older `0db-theme` when the new key is missing, so a returning visitor keeps their choice; only the new key is written.

## Skipped for now

- A destructive button variant. Danger is said in words, through the dialog.
- Date ranges in the calendar.
- A states row for the arc dial. Its states are the radio's; the row shows the tuner.
- A sheet from the start edge. The spine title assumes the end edge.
- A proper Arabic expression face. Right to left, the system face stands in, upright.
- Chart gaps (a missing value breaking the line) and axis ticks beyond the ceiling. Values count as 0 when missing.
