Requirement
Hold running body text to a comfortable measure — the number of characters per line.
Target 40–60 characters, and treat roughly 45–75 as the acceptable band. Cap the width of
prose blocks with a max-width expressed in ch (Tailwind's max-w-prose, or an explicit
max-w-[65ch]), rather than letting paragraphs stretch the full viewport on a wide screen.
This is running prose only — instructional text, help copy, descriptions, empty states, long-form guideline and content pages. Headings, table cells, data grids, and short labels are out of scope; they have their own layout logic and are not held to a measure.
Rationale
When a line of prose runs much past ~75 characters the eye has to travel too far to find
the start of the next line, and long blocks become a wall of text; much under ~40 and the
reader hyphenates and re-fixates too often. Both cost reading speed and comprehension. A
single max-width in ch scales the cap to the actual font, so the measure stays
comfortable across breakpoints without hard-coding pixel widths — Utility by Default, and
easy on the reader. It is a strong default with reasonable exceptions (a two-column layout,
a deliberately narrow aside), so it is L2.
Passes when
- A paragraph of body copy sits inside a
max-w-prose(ormax-w-[65ch]) container, so it wraps at a comfortable measure regardless of viewport width. - A long-form content or guideline page constrains its prose column rather than running text edge to edge on a wide monitor.
- A table, data grid, or heading spans its natural width — no measure cap needed, and none expected.
Fails when
- A paragraph of running prose spans the full viewport width with no
max-widthcap, so on a wide screen each line runs well past ~75 characters. - Body copy set in a container wide enough that its lines routinely exceed ~75ch.
How to verify
Hybrid. The checks/type-scan.py measure rule, built in #161, narrows the surface: it
judges ch caps already written against the 75ch ceiling, and treats sub-45ch values as
headings and labels rather than prose. It shares one rule body with LAY-4, which caps the
same thing at 80ch, so a measure past 80ch reports under both ids. Where no cap is written,
or the cap is not in ch, the rule stays quiet (or prints a NOTE) and the measure falls to
the rendered output: verify at a wide viewport and label it "verified manually". The
evaluator judges the remainder: which blocks are genuinely running prose (and so need a
measure cap) versus headings, tables, and data grids (which do not).
Evaluator guidance
Flag: a block of running prose whose lines run the full width of a wide viewport with no measure cap — check the wide-viewport screenshot for paragraphs whose lines are clearly longer than a comfortable measure.
Do not flag: headings, table cells, data grids, code blocks, or short labels; a
deliberately full-width layout element that is not running prose. This is L2 — a reasoned
deviation (e.g. a two-column reading layout, or a narrow aside below the target) takes an
inline dx-waive TYP-6 reason="…"; "forgot to cap it" is not a reason.