AXI-007 · Exploration · shipped 2026-09-20

Writing to the grid

On the Snick System a paragraph does not get a page; it gets a block, and a block is a measure — so many characters wide, so many lines tall, fixed by its span on the base grid and its step on the √φ scale. The concept plan scheduled a "copy sprint" to rewrite the client's voice into block-sized punches. This study builds the ruler that sprint would need, then turns the block into the editor: type into it and it tells you, as you go, whether the copy fits — and, for display type, whether the letters land on the grid line or merely near it.

Study A · The measure, read from the fonts

Every cell is characters per line for a block of that span at that step, with the lines it holds in the default two rows underneath. Nothing here is assumed: the stage below is measured for its width and padding, and the average character width comes from the browser setting a sample sentence in the real Schibsted Grotesk at the real size. Resize the window and the ruler re-reads itself for the new edition. Greyed cells are dead measures — fewer than eight characters a line is a word, not a line.

A ruler for the copy sprint. A three-column claim at s5 gets about twenty characters a line and two lines in two rows: forty characters, one breath. That is the punch the plan asked for, as a number.steps s2–s8 · s0 and s1 are annotation, not copy

Study B · The block as editor

Four of these blocks are editable — click into any of them and write. Each reports in its corner: how many lines the copy took of the lines its rows allow, how many characters are left on the last line, and a verdict. Fits is the aim. Loose means the last line is under a third full — a widow in a block that has no room for one. Row +1 means the copy needed more than its rows and the engine gave it the extra row (the v0.1.3 law: type never spills, it grows its row — but look at what happens to the neighbours). Collides means you widened a text block into another one. The bar along the bottom edge is the last line's fill. Widen a block or change its step with the controls; the script only ever writes numbers, and the stylesheet does the rest. The studio's own copy fits at the desktop pair and earns a loose in one block at each smaller pair — the editions recompose the blocks, and the same sentence has a different shape on each.

Write to the span, not to the page.

A block is a measure. Count characters, not words.

THE BLOCK REPORTS; IT NEVER REWRITES. YOUR COPY IS YOURS, WRONG LENGTH AND ALL.

Type never loses. When it needs a row, the row is given.

Nothing is saved. No service, no storage; reload and the copy is the studio's again. Verdicts in each block's corner; the page's summary above right.edition · glass at plane 0 threads behind the copy · slivers on
span
step

Study C · Landing on the line

The concept plan's last technical note named two things "to watch, not lean on yet" — one of them text-box-trim, "for optically perfect block typography". A line of type carries leading above and below its letters; set a display word at the bottom of a block and its baseline floats a few pixels above the edge, its cap height a few pixels below the top of the padding. On a grid that is drawn to be counted, a few pixels is the difference between on the line and near it. The top row is untrimmed. The bottom row asks the browser to trim the line box to the cap height and the alphabetic baseline. The purple rules are the grid's row lines; the table is measured from layout, not from the stylesheet.

Snick

Type

Grid

Snick

Type

Grid

Top row untrimmed, bottom row trimmed. Each block's corner reports its own baseline's distance from the nearest row line and its cap top's distance from the top of its own line box.s7 · 56.6px · the descender of "Type" hangs below the line, as it should

The draw

seed 2463266986 · from the date · pool 191

Second session with the draw, first with it as charter cadence. Five sentences from the archive, seeded by the date. The queue said Manifests or this; the draw did not hesitate:

  1. 1 · 149Two to watch, not lean on yet: anchor positioning for annotation callouts, text-box-trim for optically perfect block typography.the plan's own "not yet" · answered: Study C leans on it, measures it, and rules on whether the wait is over
  2. 2 · 171P2 Astro pipeline: blocks, scores, kind inference, editions; deploy loop to new.lxdintegral.com 2 sessionsthe client build's schedule · considered, not answered here; noted that Study A's table is what a "kind inference" step would consume
  3. 3 · 139The public pages ship CSS and content; the rare interactive block (a dashboard widget, the grid clock) hydrates alone.answered by construction: this page is CSS and copy; one script hydrates the editor and the two measurements, and every word reads without it
  4. 4 · 6It describes, exactly, what a block does when it lands on a grid line.the spec's promise about blocks · turned on the type: what does a letter do when it lands on a grid line? Study C, to a tenth of a pixel
  5. 5 · 155Accessibility is a positioning asset, not a constraint.answered: the editable blocks are real textboxes in reading order, the verdicts are live regions, and the accessibility tree was read back to check
Effect. The queue offered two studies and the draw picked one, then wrote a third of its brief: Study C exists because of draw 1 and 4, and would not have otherwise. The study the queue described — copy under span constraints — is Studies A and B.charter §5 · the draw now lives in the repository as draw.js

The rules, published

argue with the numbers, not the pictures
ConstantValueWhy
measurestage × span ÷ base − 2 × padread from the live stage and its padding, never from the tokens; the ruler is only as honest as its width
character widthcanvas measureText(sample) ÷ 92a 92-character sample sentence set in the block's own font, weight and size; letters, not ems
linesdistinct tops of the range's client rectsthe browser's own line breaks, grouped within 2px; no guessing from height
rows needed⌈(padding + paragraph) ÷ row⌉the block's own need, so a row that grew for a neighbour is not blamed on this block
looselast line < 35% and lines > 1a widow threshold for blocks; one word on a line is loose, one third of a line is not
collidesbounding boxes overlap by > 1pxonly against other text blocks — overlapping an empty field is the plane 0 privilege, not a fault
span clamp1 ≤ s ≤ base − c + 1re-applied at every edition; no block may leave the union grid, whatever it was told at a wider one
stepss1–s8 · 1.55 / 1.25 / 1.1 / 1.02line-height per step in the score, not the script: body breathes, display packs
S editions5–s8 drop one stepthe phone's measure is a third of the desktop's and the type cannot be; the readout reports the size actually set
report350 ms after the last keystrokethe live region speaks when you pause, never per key
trimtrim-both · cap · alphabeticline box cut to cap height above and baseline below; descenders hang, as in metal
baselinetext rect top + font ascentthe font's own ascent from the canvas; validated because the trimmed row measures zero with it

Findings