spec.json
The normative source. Every value the spec sets, with units. Where an implementation and this file disagree, this file is right.
1{
2 "name": "typeset",
3 "version": "2.2.1",
4 "updated": "2026-10-09",
5 "owner": "Adilson Carvalho",
6 "canonical_url": "https://typeset.adilsoncarvalho.com",
7 "intent": "A normative typographic specification for printed documents — essays, letters, reports. This file is the source of truth. CSS, Typst, LaTeX or any other implementation conforms to it; where an implementation and this file disagree, this file is right.",
8 "target": "Paper and PDF at 100% scale. Not screens, not reflowing layouts.",
9 "conformance": [
10 "Every length is absolute. Points (pt) and millimetres (mm) mean the same thing in every engine; 1pt = 1/72in.",
11 "A length given in em is relative to the font size of the element it is declared on, not to the document base.",
12 "line_height is a multiple of the element's own font size, and defines the baseline-to-baseline advance. An engine whose leading is measured between line boxes rather than between baselines must derive its value from the resulting advance, stated per element in baseline_advance.",
13 "An implementation MUST reproduce every value under `properties`. It MAY add anything the target engine needs to achieve them.",
14 "Where an engine cannot express a property, it must fail visibly or degrade as named in `fallback` — never silently.",
15 "Colour is sRGB. Ink is never pure black: #000 blooms on laser output and glares in a backlit PDF.",
16 "Deriving leading: where the engine measures the gap between line boxes rather than between baselines, pin the line box to the band from the baseline up to 1em (in Typst: top-edge: 1em, bottom-edge: 0pt). The advance is then 1em + leading, so leading = (line_height - 1) em, independent of the font's own metrics."
17 ],
18 "foundation": {
19 "page": {
20 "size": "A4",
21 "sizes_mm": {
22 "A4": [
23 210,
24 297
25 ],
26 "A5": [
27 148,
28 210
29 ],
30 "Letter": [
31 215.9,
32 279.4
33 ]
34 },
35 "sizes_note": "Every paper this spec is set for, width before height. `size` names the one a document gets by default; the others are chosen per document. A paper is added here and nowhere else — every page box, text width and column width in this spec is derived from this table and from `margins`.",
36 "margins": {
37 "default": "standard",
38 "symmetric_mm": {
39 "narrow": 10,
40 "standard": 20,
41 "wide": 30
42 },
43 "duplex_inner_mm": {
44 "narrow": 13,
45 "standard": 23,
46 "wide": 33
47 },
48 "duplex_outer_mm": {
49 "narrow": 7,
50 "standard": 17,
51 "wide": 27
52 },
53 "note": "Symmetric is what a document gets unless it asks otherwise: the named size applies to all four sides. Duplex is the explicit opt-in, for a sheet that will be bound — top and bottom stay at the symmetric value, and left and right split into an inner (binding) edge and an outer edge. A duplex pair preserves its symmetric pair's total, inner plus outer equal to twice the symmetric value, and shifts the gutter by 3mm: 20+20=40 becomes 23+17. A document keeps the same text width whichever it chooses, so switching between symmetric and duplex never reflows it."
54 },
55 "text_width": "Not a stated constant: the paper width minus the left and right margins — twice the symmetric value, or inner plus outer for a duplex pair. The two are equal for any one size, by the rule above.",
56 "running_head": {
57 "position": "top centre",
58 "content": "the current level-2 heading, uppercased",
59 "font": "sans",
60 "size": "8pt",
61 "tracking": "0.08em",
62 "color": "ink_faint",
63 "suppressed_on": "first page"
64 },
65 "folio": {
66 "position": "bottom centre",
67 "content": "page number",
68 "font": "serif",
69 "size": "9pt",
70 "numerals": "oldstyle",
71 "color": "ink_muted",
72 "suppressed_on": "first page"
73 }
74 },
75 "fonts": {
76 "serif": {
77 "role": "body text — the reading face",
78 "family": "EB Garamond",
79 "license": "OFL",
80 "fallbacks": [
81 "Iowan Old Style",
82 "Palatino",
83 "Georgia",
84 "serif"
85 ],
86 "weights": [
87 400,
88 600
89 ],
90 "styles": [
91 "normal",
92 "italic"
93 ],
94 "features": [
95 "oldstyle figures",
96 "small caps",
97 "standard ligatures",
98 "kerning"
99 ],
100 "note": "Set no smaller than 11pt. Below that the strokes thin out on office laser output."
101 },
102 "sans": {
103 "role": "headings, tables, captions, labels",
104 "family": "Source Sans 3",
105 "license": "OFL",
106 "fallbacks": [
107 "Helvetica Neue",
108 "Helvetica",
109 "Arial",
110 "sans-serif"
111 ],
112 "weights": [
113 300,
114 600,
115 700
116 ],
117 "styles": [
118 "normal",
119 "italic"
120 ],
121 "note": "Humanist, so it sits with an old-style serif instead of fighting it."
122 },
123 "mono": {
124 "role": "code, listings, technical identifiers",
125 "family": "IBM Plex Mono",
126 "license": "OFL",
127 "fallbacks": [
128 "SF Mono",
129 "Menlo",
130 "Consolas",
131 "monospace"
132 ],
133 "weights": [
134 400,
135 600
136 ],
137 "styles": [
138 "normal",
139 "italic"
140 ],
141 "features": [
142 "ligatures disabled"
143 ],
144 "note": "Monospaced faces run optically large beside a serif; every size below is already corrected for it."
145 },
146 "embedding": "Font files MUST be embedded in the output. A document that resolves its fonts at print time is not reproducible."
147 },
148 "scale": {
149 "ratio": 1.2,
150 "base": "11pt",
151 "steps": {
152 "xs": "8pt",
153 "sm": "9.5pt",
154 "base": "11pt",
155 "h4": "12pt",
156 "h3": "14pt",
157 "h2": "18pt",
158 "h1": "24pt"
159 }
160 },
161 "rhythm": {
162 "line_height": 1.45,
163 "line_height_tight": 1.2,
164 "baseline_advance": "15.95pt",
165 "space": "11pt",
166 "space_note": "One unit of vertical space is 11pt — one line of base leading, near enough. Every gap below is a multiple of it.",
167 "measure": "33em",
168 "measure_mm": 128,
169 "measure_chars": 66,
170 "measure_note": "The single largest legibility lever. Past about 75 characters the return sweep fails and readers re-read lines without noticing; below 45 the eye fixates too often. `measure` is canonical — an em measure follows a type-scale change, where a millimetre one does not. `measure_mm` is derived from it, 33 × the 11pt base, and is kept only as a millimetre convenience for readers who think in paper dimensions; tools/check.mjs asserts the two agree.",
171 "measure_variants": {
172 "narrow": "27em",
173 "wide": "40em"
174 },
175 "measure_position": "Centred, not flush to one edge. The measure is a maximum column width; where foundation.page's text_width (the paper less its margins) is wider than it, the surplus splits evenly between the two sides of the column, so the column sits in the middle of the text area. A template whose measure IS the column, with no surplus to split, is exempt — templates.two-column names its own exemption."
176 },
177 "color": {
178 "ink": {
179 "hex": "#1a1a1a",
180 "role": "body text"
181 },
182 "ink_muted": {
183 "hex": "#5a5a5a",
184 "role": "captions, attributions, secondary text"
185 },
186 "ink_faint": {
187 "hex": "#8a8a8a",
188 "role": "labels, list markers, running heads"
189 },
190 "rule": {
191 "hex": "#c9c4bd",
192 "role": "hairlines, table body rules"
193 },
194 "rule_strong": {
195 "hex": "#6f6a64",
196 "role": "table header and footer rules, block accents"
197 },
198 "wash": {
199 "hex": "#f4f1ec",
200 "role": "code and callout backgrounds"
201 },
202 "accent": {
203 "hex": "#7a1f1f",
204 "role": "drop caps, note markers, fleurons",
205 "note": "Oxblood. Chosen to read as a dark grey when printed in greyscale."
206 }
207 }
208 },
209 "sections": [
210 {
211 "id": "heading",
212 "title": "Headings",
213 "group": "Structure",
214 "principles": [
215 "Sans against the serif body, so hierarchy reads by contrast rather than by size alone.",
216 "Below level 4 the size stops changing and the register shifts instead — small caps, then italic. Six distinct levels inside a 24pt–11pt range.",
217 "Space above is four times the space below: a heading belongs to what follows it.",
218 "A heading MUST NOT be the last thing on a page. This is the most common defect in printed documents."
219 ],
220 "elements": [
221 {
222 "id": "heading-h1",
223 "name": "Heading 1 — document title",
224 "properties": {
225 "font": "sans",
226 "weight": 300,
227 "size": "24pt",
228 "line_height": 1.2,
229 "baseline_advance": "28.8pt",
230 "tracking": "-0.015em",
231 "color": "ink",
232 "align": "left",
233 "space_before": "0",
234 "space_after": "5.5pt",
235 "break_after": "avoid",
236 "break_inside": "avoid",
237 "wrap": "balanced"
238 }
239 },
240 {
241 "id": "heading-h2",
242 "name": "Heading 2 — section",
243 "properties": {
244 "font": "sans",
245 "weight": 600,
246 "size": "18pt",
247 "line_height": 1.2,
248 "baseline_advance": "21.6pt",
249 "tracking": "-0.01em",
250 "color": "ink",
251 "align": "left",
252 "space_before": "22pt",
253 "space_after": "5.5pt",
254 "break_after": "avoid",
255 "break_inside": "avoid",
256 "wrap": "balanced",
257 "sets_running_head": true
258 }
259 },
260 {
261 "id": "heading-h3",
262 "name": "Heading 3 — subsection",
263 "properties": {
264 "font": "sans",
265 "weight": 600,
266 "size": "14pt",
267 "line_height": 1.2,
268 "baseline_advance": "16.8pt",
269 "color": "ink",
270 "align": "left",
271 "space_before": "22pt",
272 "space_after": "5.5pt",
273 "break_after": "avoid"
274 }
275 },
276 {
277 "id": "heading-h4",
278 "name": "Heading 4",
279 "properties": {
280 "font": "sans",
281 "weight": 600,
282 "size": "12pt",
283 "line_height": 1.2,
284 "baseline_advance": "14.4pt",
285 "color": "ink",
286 "align": "left",
287 "space_before": "22pt",
288 "space_after": "5.5pt",
289 "break_after": "avoid"
290 }
291 },
292 {
293 "id": "heading-h5",
294 "name": "Heading 5",
295 "properties": {
296 "font": "serif",
297 "weight": 600,
298 "size": "11pt",
299 "variant": "all small caps",
300 "tracking": "0.06em",
301 "color": "ink",
302 "space_before": "22pt",
303 "space_after": "5.5pt",
304 "break_after": "avoid"
305 },
306 "notes": [
307 "No size change from body — the register carries the level."
308 ]
309 },
310 {
311 "id": "heading-h6",
312 "name": "Heading 6",
313 "properties": {
314 "font": "serif",
315 "weight": 400,
316 "style": "italic",
317 "size": "11pt",
318 "color": "ink",
319 "space_before": "22pt",
320 "space_after": "5.5pt",
321 "break_after": "avoid"
322 }
323 },
324 {
325 "id": "heading-run-in",
326 "name": "Run-in heading",
327 "properties": {
328 "display": "inline with the first line of its paragraph",
329 "separator": " · ",
330 "separator_color": "ink_faint",
331 "space_before": "0",
332 "space_after": "0"
333 },
334 "notes": [
335 "For dense reports where a full heading line is too much vertical cost."
336 ]
337 }
338 ]
339 },
340 {
341 "id": "numbering",
342 "title": "Section numbering",
343 "group": "Structure",
344 "opt_in": "typeset--numbered",
345 "principles": [
346 "Numbers are generated by a counter, never typed. A typed number drifts the moment a section moves.",
347 "Reports are numbered; essays and letters are not. It must be one switch."
348 ],
349 "elements": [
350 {
351 "id": "numbering-h2",
352 "name": "Level-2 number",
353 "properties": {
354 "format": "1",
355 "separator": "two spaces",
356 "color": "ink_faint",
357 "numerals": "lining tabular",
358 "resets": "the level-3 counter"
359 }
360 },
361 {
362 "id": "numbering-h3",
363 "name": "Level-3 number",
364 "properties": {
365 "format": "1.1",
366 "separator": "two spaces",
367 "color": "ink_faint",
368 "numerals": "lining tabular"
369 }
370 }
371 ]
372 },
373 {
374 "id": "paragraph",
375 "title": "Paragraphs",
376 "group": "Prose",
377 "principles": [
378 "Two conventions, one switch. Spaced paragraphs suit documents that get skimmed. Indented paragraphs with no gap suit continuous prose and are the convention of nearly every printed book.",
379 "The first paragraph after any heading, block or break is flush left: the thing above it has already marked the start."
380 ],
381 "elements": [
382 {
383 "id": "paragraph-spaced",
384 "name": "Paragraph — spaced (default)",
385 "properties": {
386 "font": "serif",
387 "weight": 400,
388 "size": "11pt",
389 "line_height": 1.45,
390 "baseline_advance": "15.95pt",
391 "numerals": "oldstyle proportional",
392 "color": "ink",
393 "space_after": "11pt",
394 "first_line_indent": "0",
395 "orphans": 2,
396 "widows": 2,
397 "max_width": "33em"
398 }
399 },
400 {
401 "id": "paragraph-indented",
402 "name": "Paragraph — indented",
403 "opt_in": "typeset--indented",
404 "properties": {
405 "space_after": "0",
406 "first_line_indent": "1.5em",
407 "first_line_indent_after_block": "0"
408 },
409 "notes": [
410 "Applies after a heading, blockquote, figure or section break, and to the first paragraph of the document."
411 ]
412 }
413 ]
414 },
415 {
416 "id": "justification",
417 "title": "Alignment: ragged or justified",
418 "group": "Prose",
419 "opt_in": "typeset--justified",
420 "principles": [
421 "Ragged right is the DEFAULT, and it is a choice rather than an absence — a document states it. Justification buys a clean right edge at the cost of uneven word spacing; a ragged setting keeps the spacing even and gives up the edge. Neither is more correct, but the cost lands differently by document.",
422 "Choose ragged right for a letter, a memorandum, a short note — anything addressed to a person rather than to a readership. Justification reads as institutional, and its even edge is the visual signature of print that was set for strangers.",
423 "Choose justification for continuous prose at a full measure: an essay, a report, a paper. It is mandatory in two columns, where a ragged edge at 49 characters serrates the column.",
424 "These are a single decision. Justification without hyphenation opens rivers of white space; hyphenation without justification breaks words for no gain. Take both or neither.",
425 "Hyphenation is per-language and requires the document language to be declared. An English dictionary applied to Portuguese produces confident nonsense.",
426 "The last line of a paragraph is NEVER stretched. State this explicitly — a paginating engine fragments the text, so the visual last line stops looking like the end of a paragraph and gets justified. It does not reproduce in an unpaginated preview.",
427 "Justification applies to prose only. It MUST NOT reach a subtitle, byline, caption, address block, table cell, heading or listing. In an engine where alignment inherits, every such block declares its own alignment rather than relying on an exception list.",
428 "Alignment inherits, and so does last-line alignment. A block that sets its own alignment — a centred pull quote, a centred section break — must also set its own last-line alignment, or the document's justification flushes its last line (its only line, for a one-liner) to the left."
429 ],
430 "elements": [
431 {
432 "id": "justification-ragged",
433 "name": "Ragged right (default)",
434 "opt_in": "typeset--ragged — names the default; no class needed to get it",
435 "properties": {
436 "align": "left",
437 "align_last_line": "left",
438 "hyphenation": "manual — never automatic",
439 "line_breaking": "high effort: avoid a very short last line, and even out the right edge",
440 "applies_to": [
441 "paragraph",
442 "list item",
443 "blockquote",
444 "definition description",
445 "callout"
446 ]
447 },
448 "notes": [
449 "Hyphenation exists to serve justification. Without justification a hyphen breaks a word for no gain, so it stays off.",
450 "The rag itself is the thing to judge: an even rag reads as deliberate, a rag with one very short line and one very long one reads as an accident."
451 ]
452 },
453 {
454 "id": "justification-justified",
455 "name": "Justified",
456 "properties": {
457 "align": "justify",
458 "align_last_line": "left",
459 "justify_method": "inter-word",
460 "hyphenation": "automatic",
461 "hyphenation_min_word_chars": 6,
462 "hyphenation_min_chars_before_break": 3,
463 "hyphenation_min_chars_after_break": 3,
464 "max_consecutive_hyphens": 2,
465 "applies_to": [
466 "paragraph",
467 "list item",
468 "blockquote",
469 "definition description",
470 "callout"
471 ]
472 },
473 "fallback": "automatic hyphenation, but at the engine's own built-in limits — the four tuning values above are not configurable"
474 },
475 {
476 "id": "justification-exclusions",
477 "name": "Never justified",
478 "properties": {
479 "align": "left",
480 "hyphenation": "manual",
481 "applies_to": [
482 "all headings",
483 "subtitle",
484 "byline",
485 "dateline",
486 "abstract",
487 "attribution",
488 "epigraph",
489 "verse",
490 "caption",
491 "figure caption",
492 "address block",
493 "table cell",
494 "table header",
495 "code block",
496 "table of contents",
497 "bibliography",
498 "endnotes",
499 "sidenote",
500 "letterhead",
501 "salutation",
502 "closing",
503 "signature",
504 "enclosures",
505 "postscript",
506 "definition term"
507 ]
508 }
509 }
510 ]
511 },
512 {
513 "id": "dropcap",
514 "title": "Drop cap",
515 "group": "Prose",
516 "principles": [
517 "For the opening of an essay or a chapter, and nowhere else.",
518 "The size and line height are tuned together to cover exactly three lines. Change the leading and the cap must be retuned.",
519 "The opening words go in small caps. Without them the jump from 33pt to 11pt is too abrupt and the eye skips the first line."
520 ],
521 "elements": [
522 {
523 "id": "dropcap",
524 "name": "Drop cap",
525 "properties": {
526 "font": "serif",
527 "weight": 400,
528 "size": "3.05em",
529 "size_pt": "33.55pt",
530 "line_height": 0.86,
531 "color": "accent",
532 "float": "left",
533 "lines_covered": 3,
534 "padding_right": "0.06em",
535 "padding_top": "0.02em",
536 "first_line_indent": "0"
537 }
538 },
539 {
540 "id": "dropcap-lede",
541 "name": "Opening words",
542 "properties": {
543 "variant": "all small caps",
544 "tracking": "0.04em",
545 "extent": "the first two to four words"
546 }
547 }
548 ]
549 },
550 {
551 "id": "inline",
552 "title": "Inline emphasis",
553 "group": "Prose",
554 "principles": [
555 "Nested emphasis FLIPS to roman rather than compounding. This is correct typographic behaviour and most engines get it wrong by default.",
556 "Superscripts and subscripts must not disturb the line's leading.",
557 "Underline is reserved for insertions. On paper it is a typewriter's substitute for italic, and there is no reason to imitate a typewriter."
558 ],
559 "elements": [
560 {
561 "id": "inline-strong",
562 "name": "Bold",
563 "properties": {
564 "weight": 600
565 },
566 "notes": [
567 "For the load-bearing clause."
568 ]
569 },
570 {
571 "id": "inline-emphasis",
572 "name": "Italic",
573 "properties": {
574 "style": "italic"
575 },
576 "notes": [
577 "For a title or a term of art."
578 ]
579 },
580 {
581 "id": "inline-emphasis-nested",
582 "name": "Nested italic",
583 "properties": {
584 "style": "normal"
585 }
586 },
587 {
588 "id": "inline-small-caps",
589 "name": "Small caps",
590 "properties": {
591 "variant": "all small caps",
592 "tracking": "0.05em",
593 "numerals": "oldstyle"
594 },
595 "notes": [
596 "Named entities, acronyms, stage directions."
597 ]
598 },
599 {
600 "id": "inline-abbr",
601 "name": "Abbreviation",
602 "properties": {
603 "variant": "all small caps",
604 "tracking": "0.05em",
605 "underline": "0.5pt dotted",
606 "underline_color": "ink_faint"
607 }
608 },
609 {
610 "id": "inline-superscript",
611 "name": "Superscript",
612 "properties": {
613 "size": "0.72em",
614 "baseline_shift": "+0.45em",
615 "line_height": 0,
616 "affects_leading": false
617 }
618 },
619 {
620 "id": "inline-subscript",
621 "name": "Subscript",
622 "properties": {
623 "size": "0.72em",
624 "baseline_shift": "-0.22em",
625 "line_height": 0,
626 "affects_leading": false
627 }
628 },
629 {
630 "id": "inline-deleted",
631 "name": "Deletion",
632 "properties": {
633 "decoration": "line-through",
634 "color": "ink_muted"
635 }
636 },
637 {
638 "id": "inline-inserted",
639 "name": "Insertion",
640 "properties": {
641 "decoration": "underline",
642 "underline_offset": "0.15em"
643 }
644 },
645 {
646 "id": "inline-highlight",
647 "name": "Highlight",
648 "properties": {
649 "background": "wash",
650 "bleed": "2pt beyond the glyphs"
651 }
652 },
653 {
654 "id": "inline-kbd",
655 "name": "Key",
656 "properties": {
657 "font": "sans",
658 "size": "0.85em",
659 "padding": "0.15em 0.35em",
660 "border": "0.5pt rule",
661 "border_bottom": "1.5pt rule",
662 "radius": "2pt"
663 }
664 }
665 ]
666 },
667 {
668 "id": "code-inline",
669 "title": "Inline code",
670 "group": "Prose",
671 "elements": [
672 {
673 "id": "code-inline",
674 "name": "Inline code",
675 "properties": {
676 "font": "mono",
677 "size": "0.86em",
678 "ligatures": "disabled",
679 "background": "wash",
680 "padding": "0.1em 0.28em",
681 "radius": "2pt",
682 "wrap": "may break within a word"
683 },
684 "notes": [
685 "The 0.86em corrects for the monospace face running optically large beside the serif.",
686 "Ligatures off: an arrow rendered as one glyph is charming in an editor and wrong in a document that quotes source."
687 ]
688 }
689 ]
690 },
691 {
692 "id": "link",
693 "title": "Links in print",
694 "group": "Prose",
695 "principles": [
696 "Paper has no hover and no click. A URL that carries information must be printed."
697 ],
698 "elements": [
699 {
700 "id": "link",
701 "name": "Link",
702 "properties": {
703 "color": "inherit",
704 "decoration": "underline",
705 "underline_thickness": "0.5pt",
706 "underline_offset": "0.14em",
707 "skip_descenders": true
708 }
709 },
710 {
711 "id": "link-print-url",
712 "name": "Printed URL",
713 "properties": {
714 "content": "the href in parentheses, after the link text",
715 "font": "mono",
716 "size": "0.82em",
717 "color": "ink_muted",
718 "wrap": "may break anywhere",
719 "applies_to": "external (http/https) links only",
720 "excluded": [
721 "internal anchors",
722 "mailto:",
723 "links marked bare"
724 ]
725 }
726 },
727 {
728 "id": "link-bare",
729 "name": "Link — URL suppressed",
730 "properties": {
731 "print_url": false
732 },
733 "notes": [
734 "Opt-out for a link whose URL would be noise in print: a shortened URL, a tracking URL, or one the surrounding sentence already gives."
735 ]
736 }
737 ]
738 },
739 {
740 "id": "numeral",
741 "title": "Numerals",
742 "group": "Prose",
743 "principles": [
744 "Three kinds, three jobs. Getting this wrong is the most visible amateur tell in a set document, and it is one setting.",
745 "Old-style figures have ascenders and descenders and sit inside the x-height. Lining figures are uniform cap height. Tabular figures share one advance width, which is the only reason a column of numbers can align."
746 ],
747 "elements": [
748 {
749 "id": "numeral-prose",
750 "name": "In running prose",
751 "properties": {
752 "numerals": "oldstyle proportional"
753 }
754 },
755 {
756 "id": "numeral-display",
757 "name": "In headings and display",
758 "properties": {
759 "numerals": "lining proportional"
760 }
761 },
762 {
763 "id": "numeral-tabular",
764 "name": "In tables and columns",
765 "properties": {
766 "numerals": "lining tabular"
767 }
768 },
769 {
770 "id": "numeral-fraction",
771 "name": "Fractions",
772 "properties": {
773 "form": "diagonal"
774 }
775 }
776 ]
777 },
778 {
779 "id": "quote",
780 "title": "Quotations",
781 "group": "Blocks",
782 "principles": [
783 "Four jobs, four treatments. A block quote is evidence. An epigraph opens a chapter. A pull quote is display type lifted from the body. Verse preserves the poet's line breaks.",
784 "A pull quote repeats text that already appears in the body, so it MUST NOT be the only place a claim appears — a skimming reader would get the claim without its qualification.",
785 "Attribution always sits outside the quotation. Inside, it becomes part of what was said."
786 ],
787 "elements": [
788 {
789 "id": "quote-blockquote",
790 "name": "Block quote",
791 "properties": {
792 "font": "serif",
793 "size": "10.5pt",
794 "line_height": 1.45,
795 "color": "ink",
796 "space_before": "13.75pt",
797 "space_after": "13.75pt",
798 "indent_left": "16.5pt",
799 "border_left": "1pt rule",
800 "break_inside": "avoid",
801 "last_child_space_after": "0"
802 }
803 },
804 {
805 "id": "quote-attribution",
806 "name": "Attribution",
807 "properties": {
808 "display": "block",
809 "align": "left",
810 "space_before": "5.5pt",
811 "size": "9.5pt",
812 "style": "normal",
813 "color": "ink_muted",
814 "prefix": "em dash and a space"
815 }
816 },
817 {
818 "id": "quote-epigraph",
819 "name": "Epigraph",
820 "properties": {
821 "font": "serif",
822 "style": "italic",
823 "size": "10pt",
824 "color": "ink_muted",
825 "align": "left",
826 "block_alignment": "flush right",
827 "max_width": "24em",
828 "border": "none",
829 "space_after": "22pt"
830 },
831 "notes": [
832 "Cite inside an epigraph is roman, not italic — the surrounding block is already italic."
833 ]
834 },
835 {
836 "id": "quote-pullquote",
837 "name": "Pull quote",
838 "properties": {
839 "font": "sans",
840 "weight": 300,
841 "size": "15pt",
842 "line_height": 1.3,
843 "align": "centre",
844 "wrap": "balanced",
845 "border_top": "1.5pt rule_strong",
846 "border_bottom": "0.5pt rule",
847 "padding_top": "11pt",
848 "padding_bottom": "11pt",
849 "space_before": "16.5pt",
850 "space_after": "16.5pt"
851 }
852 },
853 {
854 "id": "quote-verse",
855 "name": "Verse",
856 "properties": {
857 "font": "serif",
858 "size": "11pt",
859 "align": "left",
860 "line_breaks": "preserved as authored",
861 "indent_left": "22pt",
862 "runover_indent": "1.5em",
863 "border": "none"
864 },
865 "notes": [
866 "Runover lines indent further than the verse line they continue, so a wrapped line cannot be mistaken for a new one."
867 ],
868 "fallback": "in Typst: the left indent and the authored line breaks, but no runover indent — a wrapped line reads the same as one the poet wrote"
869 }
870 ]
871 },
872 {
873 "id": "list",
874 "title": "Lists",
875 "group": "Blocks",
876 "principles": [
877 "The marker's colour, weight and width must be under control. A grey marker with black text reads as one thing; a black marker competes with the first word.",
878 "Runover lines align to the text, never to the marker.",
879 "Two levels of nesting is the limit worth designing for.",
880 "Definition lists are underused: they are the right shape for a glossary, a set of terms, or the field-and-value blocks of a letter."
881 ],
882 "elements": [
883 {
884 "id": "list-unordered",
885 "name": "Unordered list",
886 "properties": {
887 "marker": "·",
888 "marker_color": "ink_muted",
889 "marker_weight": 700,
890 "marker_column_width": "1.4em",
891 "indent": "1.4em",
892 "item_space_after": "2.75pt",
893 "space_after": "11pt"
894 }
895 },
896 {
897 "id": "list-unordered-nested",
898 "name": "Unordered list, nested",
899 "properties": {
900 "marker": "–",
901 "marker_weight": 400,
902 "space_before": "2.75pt"
903 }
904 },
905 {
906 "id": "list-ordered",
907 "name": "Ordered list",
908 "properties": {
909 "marker": "1.",
910 "marker_color": "ink_muted",
911 "numerals": "lining tabular",
912 "marker_column_width": "1.4em",
913 "indent": "1.4em",
914 "item_space_after": "2.75pt"
915 },
916 "notes": [
917 "Tabular numerals so 9 and 10 align."
918 ]
919 },
920 {
921 "id": "list-ordered-nested",
922 "name": "Ordered list, nested",
923 "properties": {
924 "marker": "a."
925 }
926 },
927 {
928 "id": "list-tight",
929 "name": "Tight list",
930 "opt_in": "ts-list-tight",
931 "properties": {
932 "item_space_after": "0"
933 },
934 "notes": [
935 "For enumerations that are not prose."
936 ]
937 },
938 {
939 "id": "list-definition-term",
940 "name": "Definition term",
941 "properties": {
942 "font": "sans",
943 "weight": 600,
944 "size": "9.5pt",
945 "align": "left",
946 "space_before": "6.6pt",
947 "space_before_first": "0",
948 "break_after": "avoid"
949 }
950 },
951 {
952 "id": "list-definition-description",
953 "name": "Definition description",
954 "properties": {
955 "font": "serif",
956 "size": "11pt",
957 "indent_left": "16.5pt",
958 "space_after": "0"
959 }
960 }
961 ]
962 },
963 {
964 "id": "table",
965 "title": "Tables",
966 "group": "Blocks",
967 "principles": [
968 "Rules, not grids. Vertical rules are almost never needed — the columns already read as columns, and every added line is ink competing with data.",
969 "Three horizontal rules only: above the header, below the header, below the body.",
970 "A table is scanned, not read. Sans at 9.5pt; the serif's job is reading.",
971 "Numbers align on their right edge, on tabular figures. Units go in the header, not in every cell.",
972 "A table that spans pages MUST repeat its header on each. Without it, page two of a table is unreadable."
973 ],
974 "elements": [
975 {
976 "id": "table",
977 "name": "Table",
978 "properties": {
979 "font": "sans",
980 "size": "9.5pt",
981 "line_height": 1.35,
982 "numerals": "lining tabular",
983 "width": "full measure",
984 "space_before": "13.75pt",
985 "space_after": "13.75pt",
986 "border_collapse": true
987 }
988 },
989 {
990 "id": "table-header-cell",
991 "name": "Header cell",
992 "properties": {
993 "font": "sans",
994 "weight": 600,
995 "size": "8pt",
996 "case": "uppercase",
997 "tracking": "0.07em",
998 "color": "ink_muted",
999 "align": "left",
1000 "border_top": "1pt rule_strong",
1001 "border_bottom": "1pt rule_strong",
1002 "padding": "0.45em 0.7em 0.45em 0",
1003 "repeats_across_pages": true
1004 }
1005 },
1006 {
1007 "id": "table-cell",
1008 "name": "Body cell",
1009 "properties": {
1010 "align": "left",
1011 "vertical_align": "baseline",
1012 "border_bottom": "0.5pt rule",
1013 "padding": "0.45em 0.7em 0.45em 0",
1014 "last_row_border_bottom": "1pt rule_strong"
1015 }
1016 },
1017 {
1018 "id": "table-cell-numeric",
1019 "name": "Numeric cell",
1020 "properties": {
1021 "align": "right",
1022 "numerals": "lining tabular"
1023 }
1024 },
1025 {
1026 "id": "table-footer-cell",
1027 "name": "Footer cell",
1028 "properties": {
1029 "weight": 600,
1030 "border_bottom": "none"
1031 }
1032 },
1033 {
1034 "id": "table-caption",
1035 "name": "Caption",
1036 "properties": {
1037 "position": "above the table",
1038 "align": "left",
1039 "font": "sans",
1040 "size": "9.5pt",
1041 "color": "ink",
1042 "space_after": "0.5em",
1043 "max_width": "none"
1044 }
1045 },
1046 {
1047 "id": "table-row",
1048 "name": "Row",
1049 "properties": {
1050 "break_inside": "avoid"
1051 }
1052 },
1053 {
1054 "id": "table-zebra",
1055 "name": "Zebra striping",
1056 "opt_in": "ts-table-zebra",
1057 "properties": {
1058 "background": "wash on even body rows"
1059 },
1060 "notes": [
1061 "For wide, dense tables only. Not a default."
1062 ]
1063 },
1064 {
1065 "id": "table-caption-label",
1066 "name": "Caption label",
1067 "properties": {
1068 "weight": 600,
1069 "caps": "all small caps",
1070 "tracking": "0.06em"
1071 }
1072 }
1073 ]
1074 },
1075 {
1076 "id": "codeblock",
1077 "title": "Code blocks",
1078 "group": "Blocks",
1079 "principles": [
1080 "Paper cannot scroll. Lines wrap; they are never clipped.",
1081 "A long listing MUST be allowed to split across pages. Forbidding the break pushes a blank page ahead of it."
1082 ],
1083 "elements": [
1084 {
1085 "id": "codeblock",
1086 "name": "Code block",
1087 "properties": {
1088 "font": "mono",
1089 "size": "8.5pt",
1090 "line_height": 1.45,
1091 "background": "wash",
1092 "border_left": "2pt rule_strong",
1093 "padding": "0.8em 1em",
1094 "space_before": "13.75pt",
1095 "space_after": "13.75pt",
1096 "wrap": "soft-wrap long lines",
1097 "tab_size": 2,
1098 "break_inside": "avoid on screen, allowed in print"
1099 }
1100 }
1101 ]
1102 },
1103 {
1104 "id": "figure",
1105 "title": "Figures & captions",
1106 "group": "Blocks",
1107 "principles": [
1108 "A caption is not a title: it goes below the figure.",
1109 "A figure and its caption stay on one page. This is the one place a no-break rule is unambiguously right.",
1110 "The caption carries a small-caps label so a cross-reference in the text has something to point at."
1111 ],
1112 "elements": [
1113 {
1114 "id": "figure",
1115 "name": "Figure",
1116 "properties": {
1117 "space_before": "16.5pt",
1118 "space_after": "16.5pt",
1119 "break_inside": "avoid",
1120 "image_max_width": "full measure"
1121 }
1122 },
1123 {
1124 "id": "figure-caption",
1125 "name": "Figure caption",
1126 "properties": {
1127 "position": "below the figure",
1128 "font": "sans",
1129 "size": "9.5pt",
1130 "line_height": 1.4,
1131 "color": "ink_muted",
1132 "align": "left",
1133 "space_before": "0.5em",
1134 "border_top": "0.5pt rule",
1135 "padding_top": "0.4em"
1136 }
1137 },
1138 {
1139 "id": "figure-caption-label",
1140 "name": "Figure caption label",
1141 "properties": {
1142 "weight": 600,
1143 "color": "ink",
1144 "caps": "all small caps",
1145 "tracking": "0.06em"
1146 }
1147 }
1148 ]
1149 },
1150 {
1151 "id": "callout",
1152 "title": "Callouts",
1153 "group": "Blocks",
1154 "principles": [
1155 "A callout is an aside the reader may skip without losing the argument. If skipping it would lose the argument, it is a paragraph.",
1156 "Two variants only. A document with five callout colours has none."
1157 ],
1158 "elements": [
1159 {
1160 "id": "callout",
1161 "name": "Callout",
1162 "properties": {
1163 "font": "serif",
1164 "size": "10pt",
1165 "background": "wash",
1166 "border": "0.5pt rule",
1167 "border_left": "2.5pt rule_strong",
1168 "padding": "0.75em 1em",
1169 "space_before": "13.75pt",
1170 "space_after": "13.75pt",
1171 "break_inside": "avoid"
1172 }
1173 },
1174 {
1175 "id": "callout-title",
1176 "name": "Callout title",
1177 "properties": {
1178 "font": "sans",
1179 "weight": 700,
1180 "size": "8pt",
1181 "case": "uppercase",
1182 "tracking": "0.09em",
1183 "color": "ink_muted",
1184 "space_after": "0.35em"
1185 }
1186 },
1187 {
1188 "id": "callout-warning",
1189 "name": "Callout — warning",
1190 "properties": {
1191 "border_left": "2.5pt accent",
1192 "title_color": "accent"
1193 }
1194 }
1195 ]
1196 },
1197 {
1198 "id": "break",
1199 "title": "Section breaks",
1200 "group": "Blocks",
1201 "principles": [
1202 "A blank line cannot survive a page break: if the break falls on the gap, the reader never learns the scene changed. Over a long document this is a certainty, not an accident. The mark MUST be visible.",
1203 "Four registers, one per kind of division."
1204 ],
1205 "elements": [
1206 {
1207 "id": "break-asterisks",
1208 "name": "Break — three asterisks",
1209 "properties": {
1210 "content": "* * *",
1211 "size": "10pt",
1212 "tracking": "0.6em",
1213 "color": "ink_faint",
1214 "align": "centre",
1215 "space_before": "16.5pt",
1216 "space_after": "16.5pt",
1217 "break_after": "avoid"
1218 },
1219 "notes": [
1220 "The default, for a change of scene in prose."
1221 ]
1222 },
1223 {
1224 "id": "break-asterism",
1225 "name": "Break — asterism",
1226 "properties": {
1227 "content": "⁂",
1228 "size": "14pt",
1229 "color": "ink_faint",
1230 "align": "centre"
1231 },
1232 "notes": [
1233 "A heavier division: a change of part."
1234 ]
1235 },
1236 {
1237 "id": "break-fleuron",
1238 "name": "Break — fleuron",
1239 "properties": {
1240 "content": "❦",
1241 "size": "12pt",
1242 "color": "accent",
1243 "align": "centre"
1244 },
1245 "notes": [
1246 "Where the document can afford ornament."
1247 ]
1248 },
1249 {
1250 "id": "break-rule",
1251 "name": "Break — rule",
1252 "properties": {
1253 "border_top": "0.5pt rule",
1254 "content": "none"
1255 },
1256 "notes": [
1257 "Where it cannot. Reports."
1258 ]
1259 }
1260 ]
1261 },
1262 {
1263 "id": "note",
1264 "title": "Footnotes, endnotes & sidenotes",
1265 "group": "Apparatus",
1266 "principles": [
1267 "Bottom-of-page footnotes require an engine that can measure the page while laying it out. Typst and LaTeX do this natively. WeasyPrint 53+ and Prince implement the CSS footnote model. No browser does.",
1268 "Where footnotes are unavailable the note text MUST still live in the document, degrading to a numbered endnotes block — never to a lost note.",
1269 "Sidenotes are the better default where the page can afford the margin: no page-break arithmetic, and the reader never leaves the sentence they are in.",
1270 "The reference mark must not disturb the leading of the line it sits on."
1271 ],
1272 "elements": [
1273 {
1274 "id": "note-marker",
1275 "name": "Reference mark",
1276 "properties": {
1277 "content": "the note number",
1278 "size": "0.7em",
1279 "baseline_shift": "+0.45em",
1280 "line_height": 0,
1281 "color": "accent",
1282 "numerals": "lining",
1283 "decoration": "none",
1284 "brackets": "none",
1285 "affects_leading": false
1286 }
1287 },
1288 {
1289 "id": "note-footnote",
1290 "name": "Footnote",
1291 "properties": {
1292 "position": "foot of the page carrying the mark",
1293 "font": "serif",
1294 "size": "9.5pt",
1295 "line_height": 1.35,
1296 "separator": "a rule above the notes area"
1297 },
1298 "fallback": "an endnotes block at the end of the document"
1299 },
1300 {
1301 "id": "note-endnotes",
1302 "name": "Endnotes block",
1303 "properties": {
1304 "font": "serif",
1305 "size": "9.5pt",
1306 "line_height": 1.4,
1307 "align": "left",
1308 "space_before": "22pt",
1309 "border_top": "0.5pt rule",
1310 "padding_top": "11pt",
1311 "list_indent": "1.8em",
1312 "item_space_after": "0.4em",
1313 "heading": "none — the rule above the block is the only mark it needs"
1314 },
1315 "notes": [
1316 "No 'NOTES' label. In a one-page document the rule plus the numbered list already reads as a notes area, and a heading over two lines of small print is heavier than the thing it labels."
1317 ]
1318 },
1319 {
1320 "id": "note-sidenote",
1321 "name": "Sidenote",
1322 "opt_in": "typeset--sidenotes",
1323 "properties": {
1324 "font": "sans",
1325 "size": "8pt",
1326 "line_height": 1.4,
1327 "color": "ink_muted",
1328 "align": "left",
1329 "width": "11em",
1330 "position": "the right margin, 2em past the text column's own right edge",
1331 "vertical_offset": "-0.3em from the marker's line",
1332 "marker_prefix": "the note number in accent, weight 600",
1333 "measure_when_active": "27em",
1334 "reserved_margin": "14em — the gap plus the note, with an em to spare"
1335 },
1336 "notes": [
1337 "Anchor the note to the text column's right edge, not to the measure. The measure is a maximum: where the reserved margin is the binding constraint the column is narrower than it, and a note offset from the measure lands on top of the text.",
1338 "Sidenotes are positioned, not flowed: a long note followed closely by another will overlap it. Keep each note short and consecutive notes apart — one per paragraph, and not in every paragraph. An implementation cannot fix this, and should not pretend to; it is a constraint on the writing."
1339 ]
1340 }
1341 ]
1342 },
1343 {
1344 "id": "toc",
1345 "title": "Table of contents",
1346 "group": "Apparatus",
1347 "principles": [
1348 "Page numbers require the engine to resolve a cross-reference after pagination. Where it cannot, the entry MUST omit the number rather than print a wrong one — a TOC with wrong numbers is worse than one with none."
1349 ],
1350 "elements": [
1351 {
1352 "id": "toc",
1353 "name": "Table of contents",
1354 "properties": {
1355 "font": "sans",
1356 "size": "9.5pt",
1357 "align": "left"
1358 }
1359 },
1360 {
1361 "id": "toc-entry",
1362 "name": "Entry",
1363 "properties": {
1364 "space_after": "0.35em",
1365 "decoration": "none",
1366 "page_number": "resolved after pagination",
1367 "page_number_numerals": "lining tabular",
1368 "page_number_color": "ink_muted"
1369 },
1370 "fallback": "leaders render, page numbers are omitted"
1371 },
1372 {
1373 "id": "toc-entry-2",
1374 "name": "Entry — level 2",
1375 "properties": {
1376 "indent_left": "1.5em"
1377 }
1378 },
1379 {
1380 "id": "toc-leader",
1381 "name": "Dot leader",
1382 "properties": {
1383 "leader": "dotted 0.5pt rule, colour rule, filling the space between title and number",
1384 "baseline_offset": "-0.15em"
1385 }
1386 }
1387 ]
1388 },
1389 {
1390 "id": "bibliography",
1391 "title": "Bibliography",
1392 "group": "Apparatus",
1393 "principles": [
1394 "Hanging indent, always. The surname is what is being scanned, so it must be the leftmost thing on the entry.",
1395 "The heading is its own element, not an instance of heading-h2, even though it shares h2's scale and weight: the distinct id is what lets it span both columns in the two-column template while an ordinary section heading — heading-h2 through heading-h6 — cannot."
1396 ],
1397 "elements": [
1398 {
1399 "id": "bibliography-heading",
1400 "name": "Heading",
1401 "properties": {
1402 "font": "sans",
1403 "weight": 600,
1404 "size": "18pt",
1405 "line_height": 1.2,
1406 "baseline_advance": "21.6pt",
1407 "tracking": "-0.01em",
1408 "color": "ink",
1409 "align": "left",
1410 "space_before": "22pt",
1411 "space_after": "5.5pt",
1412 "break_after": "avoid",
1413 "break_inside": "avoid",
1414 "wrap": "balanced",
1415 "sets_running_head": true
1416 }
1417 },
1418 {
1419 "id": "bibliography-entry",
1420 "name": "Entry",
1421 "properties": {
1422 "font": "serif",
1423 "size": "9.5pt",
1424 "line_height": 1.4,
1425 "align": "left",
1426 "hanging_indent": "1.8em",
1427 "space_after": "0.55em",
1428 "marker": "none",
1429 "break_inside": "avoid",
1430 "title_style": "italic"
1431 },
1432 "fallback": "in Typst: every property here except the hanging indent — a wrapped line sits flush with the surname instead of indented past it"
1433 }
1434 ]
1435 },
1436 {
1437 "id": "frontmatter",
1438 "title": "Front matter",
1439 "group": "Documents",
1440 "principles": [
1441 "A colophon closes the document, recording how it was made and in what type. It is the one piece of matter that is purely for pleasure, and the cheapest thing here to include."
1442 ],
1443 "elements": [
1444 {
1445 "id": "frontmatter-title-block",
1446 "name": "Title block",
1447 "properties": {
1448 "space_after": "33pt",
1449 "padding_bottom": "11pt",
1450 "border_bottom": "0.5pt rule"
1451 }
1452 },
1453 {
1454 "id": "frontmatter-subtitle",
1455 "name": "Subtitle",
1456 "properties": {
1457 "font": "sans",
1458 "weight": 300,
1459 "size": "14pt",
1460 "line_height": 1.25,
1461 "color": "ink_muted",
1462 "align": "left",
1463 "wrap": "balanced",
1464 "space_after": "11pt"
1465 }
1466 },
1467 {
1468 "id": "frontmatter-byline",
1469 "name": "Byline",
1470 "properties": {
1471 "font": "serif",
1472 "size": "11pt",
1473 "variant": "all small caps",
1474 "tracking": "0.08em",
1475 "align": "left",
1476 "space_after": "0"
1477 }
1478 },
1479 {
1480 "id": "frontmatter-dateline",
1481 "name": "Dateline",
1482 "properties": {
1483 "font": "sans",
1484 "size": "9.5pt",
1485 "color": "ink_muted",
1486 "align": "left",
1487 "space_before": "0.2em"
1488 }
1489 },
1490 {
1491 "id": "frontmatter-abstract",
1492 "name": "Abstract",
1493 "properties": {
1494 "font": "serif",
1495 "size": "10pt",
1496 "line_height": 1.45,
1497 "color": "ink_muted",
1498 "align": "left",
1499 "max_width": "30em",
1500 "space_after": "22pt"
1501 }
1502 },
1503 {
1504 "id": "frontmatter-colophon",
1505 "name": "Colophon",
1506 "properties": {
1507 "font": "serif",
1508 "style": "italic",
1509 "size": "9.5pt",
1510 "color": "ink_muted",
1511 "align": "left",
1512 "max_width": "26em",
1513 "space_before": "33pt",
1514 "padding_top": "11pt",
1515 "border_top": "0.5pt rule",
1516 "break_before": "avoid"
1517 }
1518 },
1519 {
1520 "id": "frontmatter-abstract-label",
1521 "name": "Abstract label",
1522 "properties": {
1523 "display": "block",
1524 "font": "sans",
1525 "size": "xs",
1526 "weight": 700,
1527 "tracking": "0.1em",
1528 "caps": "uppercase",
1529 "color": "ink_faint"
1530 }
1531 }
1532 ]
1533 },
1534 {
1535 "id": "letter",
1536 "title": "Letter",
1537 "group": "Documents",
1538 "principles": [
1539 "A letter is set justified, at 12pt, across the full width its margins leave. It is read once, closely, by one person, and an even page with a quiet edge serves that reading.",
1540 "Sender and address blocks are address data, not a masthead. The name line is set in small caps at body size, and the lines below it a step smaller, so the eye finds who before where. Nothing bold, nothing in the sans, nothing larger than the text: a personal letter does not announce itself.",
1541 "Address blocks are line-broken data, not prose: tighter leading, never justified, line breaks as authored.",
1542 "The letterhead — the addresses and any crest — sits the standard margin from the paper's edge, or at the text's own edge where that is nearer the paper. Where the text sits further in, under a wider margin or a centred measure, the letterhead stays out at the standard margin rather than moving in with it.",
1543 "The signature is the typed name with room above it to sign. No ruled line — a rule is a form to be filled in.",
1544 "A letter carries no running head and no folio.",
1545 "Footnotes belong in a letter as much as in an essay. Where the engine cannot set them at the page foot, the rule plus the numbered note at the end of a one-page letter reads as a footnote area regardless."
1546 ],
1547 "elements": [
1548 {
1549 "id": "letter-page",
1550 "name": "Letter page",
1551 "properties": {
1552 "margin_top_mm": 35,
1553 "margin_bottom_mm": 35,
1554 "margin_sides_mm": 35,
1555 "base_size": "12pt",
1556 "measure": "full — the width the margins leave, about 66 characters on A4",
1557 "justification": "justified",
1558 "running_head": "none",
1559 "folio": "none",
1560 "block_quote": "letter-quote"
1561 },
1562 "derivation": {
1563 "derived_for": "foundation.page.margins.symmetric_mm.standard plus this element's own letter_inset_mm, on every edge. No copy of the standard margin is kept here.",
1564 "letter_inset_mm": 15,
1565 "recompute_when": "foundation.page.margins.symmetric_mm.standard moves. Every margin = symmetric_mm.standard + letter_inset_mm. tools/check.mjs recomputes and renders against all three, in both implementations."
1566 },
1567 "notes": [
1568 "The text sits letter_inset_mm inside the standard margin on every edge. The letterhead — letter-addresses and letter-crest — reaches back out by the same amount, so the addresses and the crest stand at the standard margin and the text is framed inside them.",
1569 "At 12pt, the full width inside 35mm margins on A4 carries about 66 characters: the standard measure, reached by the margin rather than by a cap."
1570 ]
1571 },
1572 {
1573 "id": "letter-sender",
1574 "name": "Sender block",
1575 "properties": {
1576 "font": "serif",
1577 "weight": 400,
1578 "size": "12pt",
1579 "line_height": 1.35,
1580 "color": "ink",
1581 "align": "left",
1582 "line_breaks": "as authored — name, street, suburb and postcode, country",
1583 "space_after": "30pt",
1584 "name_line": "small caps (smcp and c2sc), at body size",
1585 "detail_size": "10.2pt — 0.85 of body"
1586 },
1587 "notes": [
1588 "The name is the one line in small caps, at body size; street, suburb and country sit a step smaller beneath it. Never larger and never bold — that turns a letter into stationery.",
1589 "Omit what you do not use. A personal letter needs no email address and no telephone number."
1590 ]
1591 },
1592 {
1593 "id": "letter-address-block",
1594 "name": "Address block",
1595 "properties": {
1596 "font": "serif",
1597 "size": "12pt",
1598 "line_height": 1.35,
1599 "style": "normal",
1600 "align": "left",
1601 "line_breaks": "as authored",
1602 "space_after": "16.5pt",
1603 "name_line": "small caps (smcp and c2sc), at body size",
1604 "detail_size": "10.2pt — 0.85 of body"
1605 }
1606 },
1607 {
1608 "id": "letter-addresses",
1609 "name": "Address column",
1610 "properties": {
1611 "left_edge": "foundation.page.margins.symmetric_mm.standard from the paper's left edge, or the text's own left edge where that is nearer the paper",
1612 "reach": "how far the text's left edge sits beyond symmetric_mm.standard — from a wider margin, a centred measure or both — or none"
1613 },
1614 "notes": [
1615 "Holds the sender and address blocks. The reach is measured from where the text actually starts, so it follows the page margin and the measure together."
1616 ]
1617 },
1618 {
1619 "id": "letter-crest",
1620 "name": "Crest",
1621 "properties": {
1622 "position": "top right of the first page, its top on the top margin",
1623 "right_edge": "symmetric_mm.standard from the paper's right edge, or the text's own right edge where that is nearer the paper",
1624 "width": "20mm",
1625 "color": "accent, where the mark is drawn in a single ink"
1626 },
1627 "notes": [
1628 "Optional. A letter with no crest leaves the corner empty; nothing moves into it."
1629 ]
1630 },
1631 {
1632 "id": "letter-date",
1633 "name": "Date line",
1634 "properties": {
1635 "numerals": "oldstyle",
1636 "align": "left",
1637 "space_before": "36pt",
1638 "space_after": "24pt"
1639 },
1640 "notes": [
1641 "The date and the line under it are one block. The space after belongs to the pair, not to the date alone.",
1642 "Only the date is required. The line under it, where there is one, is the saint of the day, closed with “ora pro nobis”; with no saint the date stands alone."
1643 ]
1644 },
1645 {
1646 "id": "letter-date-note",
1647 "name": "Line under the date",
1648 "properties": {
1649 "font": "serif",
1650 "style": "italic",
1651 "size": "10.8pt — 0.9 of body",
1652 "color": "ink_muted",
1653 "align": "left",
1654 "space_before": "none — the date's own next line, at body leading",
1655 "space_after": "24pt, the date's"
1656 },
1657 "notes": [
1658 "A dedication, a feast, a devotion — whatever the writer puts under the date. Italic, at body size, immediately beneath."
1659 ]
1660 },
1661 {
1662 "id": "letter-salutation",
1663 "name": "Salutation",
1664 "properties": {
1665 "align": "left",
1666 "space_before": "24pt",
1667 "space_after": "24pt",
1668 "form": "greeting, name, comma — “Dear” unless the writer gives another greeting"
1669 }
1670 },
1671 {
1672 "id": "letter-quote",
1673 "name": "Quotation — in a letter",
1674 "properties": {
1675 "font": "serif",
1676 "style": "italic",
1677 "weight": 400,
1678 "size": "12.6pt — 1.05 of body",
1679 "color": "ink_muted",
1680 "indent_left": "24pt",
1681 "indent_right": "24pt",
1682 "rule": "none",
1683 "space_before": "18pt",
1684 "space_after": "18pt"
1685 },
1686 "notes": [
1687 "A letter quotes a prayer, a line, a remembered phrase. It is set apart by indent and colour, not by a rule: a rule is the essay's quotation, and a letter is not an essay."
1688 ]
1689 },
1690 {
1691 "id": "letter-closing",
1692 "name": "Closing",
1693 "properties": {
1694 "align": "left",
1695 "space_before": "36pt",
1696 "space_after": "24pt",
1697 "form": "closing words and a comma — “Yours sincerely” unless the writer gives others"
1698 }
1699 },
1700 {
1701 "id": "letter-signature",
1702 "name": "Signature block",
1703 "properties": {
1704 "font": "serif",
1705 "size": "12pt",
1706 "align": "left",
1707 "space_before": "36pt — the room to sign",
1708 "rule": "none",
1709 "break_inside": "avoid",
1710 "signature_image_max_height": "16mm"
1711 },
1712 "notes": [
1713 "The typed name only. A ruled line above a name is a form; a letter is not a form."
1714 ]
1715 },
1716 {
1717 "id": "letter-enclosures",
1718 "name": "Enclosures",
1719 "properties": {
1720 "font": "serif",
1721 "size": "12pt",
1722 "align": "left",
1723 "space_before": "24pt",
1724 "label": "same style as the text it introduces — no small caps, no weight change"
1725 },
1726 "notes": [
1727 "Same reasoning as the postscript: \"Enc.\" introduces a sentence, it does not head a section."
1728 ]
1729 },
1730 {
1731 "id": "letter-postscript",
1732 "name": "Postscript",
1733 "properties": {
1734 "font": "serif",
1735 "size": "12pt",
1736 "align": "left",
1737 "space_before": "36pt — the signature's own distance from the closing",
1738 "label": "same style as the text it introduces — no small caps, no weight change"
1739 },
1740 "notes": [
1741 "A postscript is a sentence that happens to begin with \"P.S.\". The label is not a heading."
1742 ]
1743 },
1744 {
1745 "id": "letter-footnote",
1746 "name": "Footnote — in a letter",
1747 "properties": {
1748 "marker": "as the note marker in Apparatus — superscript, accent, no brackets",
1749 "position": "foot of the page where the engine can; otherwise after the signature block",
1750 "font": "serif",
1751 "size": "9.5pt",
1752 "separator": "0.5pt rule above the notes area",
1753 "heading": "none"
1754 },
1755 "fallback": "a numbered note after the signature, under a rule — which on a one-page letter is the page foot anyway"
1756 },
1757 {
1758 "id": "letter-address-label",
1759 "name": "Address label",
1760 "properties": {
1761 "display": "block",
1762 "font": "sans",
1763 "size": "xs",
1764 "tracking": "0.1em",
1765 "caps": "uppercase",
1766 "color": "ink_faint"
1767 }
1768 }
1769 ]
1770 },
1771 {
1772 "id": "utility",
1773 "title": "Pagination utilities",
1774 "group": "Documents",
1775 "principles": [
1776 "The small set of overrides reached for while proofing a real document. Every one of them is a manual decision about a specific page, not a style."
1777 ],
1778 "elements": [
1779 {
1780 "id": "utility-break-before",
1781 "name": "Break before",
1782 "properties": {
1783 "effect": "start this element on a new page"
1784 },
1785 "notes": [
1786 "Chapter openings."
1787 ]
1788 },
1789 {
1790 "id": "utility-break-after",
1791 "name": "Break after",
1792 "properties": {
1793 "effect": "start the next element on a new page"
1794 }
1795 },
1796 {
1797 "id": "utility-keep-together",
1798 "name": "Keep together",
1799 "properties": {
1800 "effect": "never split this element across pages"
1801 },
1802 "notes": [
1803 "A short table, a signature block, a callout."
1804 ]
1805 },
1806 {
1807 "id": "utility-no-hyphens",
1808 "name": "No hyphenation",
1809 "properties": {
1810 "hyphenation": "manual"
1811 }
1812 },
1813 {
1814 "id": "utility-tie",
1815 "name": "Tie",
1816 "properties": {
1817 "effect": "no line break inside"
1818 },
1819 "notes": [
1820 "A figure with its unit, an initial with a surname, a section mark with its number."
1821 ]
1822 },
1823 {
1824 "id": "utility-print-only",
1825 "name": "Print only / screen only",
1826 "properties": {
1827 "effect": "present in one medium, absent in the other"
1828 },
1829 "notes": [
1830 "The URL list a page needs and a screen does not; the navigation a screen needs and a page does not."
1831 ]
1832 },
1833 {
1834 "id": "utility-color-adjust",
1835 "name": "Exact colour",
1836 "properties": {
1837 "effect": "backgrounds and rules survive the output device's ink-saving"
1838 },
1839 "notes": [
1840 "Without it a print dialog can strip every rule in a table."
1841 ]
1842 }
1843 ]
1844 }
1845 ],
1846 "templates": {
1847 "default": "single-column",
1848 "note": "A template sets the page and the scale. Everything under `foundation` and `sections` still applies; a template states only what it overrides, and what it forbids.",
1849 "single-column": {
1850 "name": "Single column",
1851 "use_for": "Essays, letters, reports, memoranda — anything read continuously from start to finish.",
1852 "page": "as foundation.page",
1853 "scale": "as foundation.scale",
1854 "rhythm": "as foundation.rhythm",
1855 "justification": "optional",
1856 "notes": [
1857 "The default. Nothing to opt into."
1858 ]
1859 },
1860 "two-column": {
1861 "name": "Two column, equal",
1862 "opt_in": "typeset--two-column",
1863 "use_for": "Papers, journal articles, newsletters, technical notes — documents that are scanned and referenced as much as read, and where a figure is worth more than an uninterrupted argument.",
1864 "derivation": {
1865 "derived_for": "The paper named in foundation.page.size, at the margin named in foundation.page.margins.default. No copy of either is kept here: every number below is a function of those two and of the gutter.",
1866 "column_gap_mm": 6,
1867 "column_width_mm": 82,
1868 "characters_per_line": {
1869 "11pt": 42,
1870 "10.5pt": 44,
1871 "10pt": 47,
1872 "9.5pt": 49,
1873 "9pt": 52
1874 },
1875 "floor": 45,
1876 "margins_supported": [
1877 "narrow",
1878 "standard"
1879 ],
1880 "conclusion": "An 82mm column carries 42 characters at the 11pt base — below the 45-character floor this spec sets for a line of prose. 10.5pt still falls short, at 44. The base therefore DROPS to 10pt, the first step that clears the floor — but only just, at 47, two characters of headroom. The template drops one step further anyway, to 9.5pt and 49: a floor is not a target, and a bare pass is not the same as room to breathe. This is arithmetic, not preference: an implementation that keeps 11pt or 10.5pt in two columns violates the measure rule, which is the rule everything else in this spec is downstream of.",
1881 "refusal": "Two columns are refused, not set badly, on any paper and margin whose column falls below the floor. That is a computed rule rather than a list of papers: margins_supported names the margins that reach the floor on the paper in foundation.page.size, and tools/check.mjs recomputes it. The checker fails when this declaration disagrees with the arithmetic, when the default margin cannot reach the floor, or when no named margin on the paper can.",
1882 "recompute_when": "The paper in foundation.page.size, the default margin, or the gutter. Characters per line = (foundation.rhythm.measure_chars / measure_mm) x column_mm x (11 / base_pt), rounded; column_mm = (paper width - twice the margin - the gutter) / 2. tools/check.mjs recomputes every number here from foundation.page, so a margin cannot move without these following it or the checker going red."
1883 },
1884 "page": {
1885 "size": "as foundation.page.size",
1886 "margins": "as foundation.page.margins, at the default size — symmetric unless the sheet is bound, duplex if it is. A duplex pair leaves the text width unchanged, so a two-column document does not reflow between them.",
1887 "columns": 2,
1888 "column_widths": "equal — the two columns are the same width, always",
1889 "column_gap_mm": 6,
1890 "column_width_mm": 82,
1891 "column_rule": "none by default; an optional 0.5pt hairline in `rule` where the columns need separating",
1892 "column_balance": "the final page balances its columns to equal height",
1893 "lines_per_column": 54,
1894 "running_head": "as foundation.page — spans the full text width, not a column",
1895 "folio": "as foundation.page"
1896 },
1897 "scale": {
1898 "ratio": 1.2,
1899 "base": "9.5pt",
1900 "steps": {
1901 "xs": "7pt",
1902 "sm": "8.5pt",
1903 "base": "9.5pt",
1904 "h4": "9.5pt",
1905 "h3": "11pt",
1906 "h2": "13pt",
1907 "h1": "20pt"
1908 },
1909 "note": "Every step comes down. A 24pt heading inside an 82mm column takes three lines to say two words; 18pt takes two. The h1 keeps display size because it spans both columns."
1910 },
1911 "rhythm": {
1912 "line_height": 1.4,
1913 "baseline_advance": "13.3pt",
1914 "space": "9.5pt",
1915 "measure": "the column — 82mm, not a character count",
1916 "measure_chars": 49,
1917 "measure_position": "exempt from foundation.rhythm.measure_position — the column has no surplus to split, because the column IS the measure. Centring would have nothing to act on.",
1918 "note": "Leading tightens with the measure: a shorter line needs less vertical separation to keep the return sweep unambiguous."
1919 },
1920 "requirements": [
1921 "Justification with hyphenation is MANDATORY, not optional. At 49 characters a ragged right edge produces a visibly serrated column and word gaps wide enough to read as rivers. This is the one place the spec removes a choice it otherwise offers.",
1922 "The last line of a paragraph is still flush left. Two columns make a stretched last line more visible, not less.",
1923 "Balance the columns on the final page. A last page with one full column and one empty third reads as a printing error.",
1924 "A spanning element must span BOTH columns fully or neither. An element that spans one and a half columns has no correct reading order.",
1925 "Keep a spanning element at the top or the bottom of the page, never mid-column. Interrupting both columns in the middle forces the reader to find their place twice."
1926 ],
1927 "spanning": {
1928 "always": [
1929 "frontmatter-title-block",
1930 "frontmatter-subtitle",
1931 "frontmatter-byline",
1932 "frontmatter-dateline",
1933 "frontmatter-abstract",
1934 "heading-h1",
1935 "bibliography-heading",
1936 "frontmatter-colophon"
1937 ],
1938 "optional": [
1939 "a figure",
1940 "a table",
1941 "a code block",
1942 "a pull quote"
1943 ],
1944 "never": [
1945 "a paragraph",
1946 "a list",
1947 "a block quote",
1948 "a callout",
1949 "heading 2 and below",
1950 "a block of endnotes"
1951 ],
1952 "note": "A wide figure or table opts in per instance. The default is column-width, because a spanning element costs a break in both columns. `always` is element ids, so tools/check.mjs can hold both implementations to it; `optional` and `never` are prose, because they describe author choice and default flow rather than a property either implementation can be held to. Each of those entries is written so that it cannot be read as an id — tools/check.mjs fails if one ever matches an element or section id, which is what keeps the two arms distinguishable by shape now that `figure`, `table`, `list` and `callout` are ids in their own right. `bibliography-heading` is on `always` as its own element, distinct from `heading-h2`: `never`'s \"heading 2 and below\" names the generic heading levels heading-h2 through heading-h6, not a differently-identified element that happens to share their scale — so a bibliography heading may span both columns while an ordinary section heading may not."
1953 },
1954 "forbidden": {
1955 "sidenote": "There is no margin to put it in. Use a footnote or an endnote.",
1956 "dropcap": "A three-line cap at 3.05em is 29pt in an 82mm column — 10mm of the column given to one letter. Open with small caps instead.",
1957 "measure_variants": "narrow and wide are meaningless: the column is the measure."
1958 },
1959 "element_overrides": {
1960 "h1": {
1961 "size": "20pt",
1962 "spans": "both columns",
1963 "space_after": "9.5pt"
1964 },
1965 "h2": {
1966 "size": "13pt",
1967 "space_before": "19pt",
1968 "space_after": "4.75pt"
1969 },
1970 "h3": {
1971 "size": "11pt",
1972 "space_before": "19pt",
1973 "space_after": "4.75pt"
1974 },
1975 "h4": {
1976 "size": "9.5pt",
1977 "space_before": "19pt",
1978 "space_after": "4.75pt"
1979 },
1980 "paragraph": {
1981 "size": "9.5pt",
1982 "line_height": 1.4,
1983 "space_after": "0",
1984 "first_line_indent": "1.25em",
1985 "note": "Indented paragraphs are the default here, not an option: a blank line costs 3% of a column."
1986 },
1987 "blockquote": {
1988 "size": "9pt",
1989 "indent_left": "9.5pt"
1990 },
1991 "table": {
1992 "size": "8pt",
1993 "line_height": 1.3
1994 },
1995 "codeblock": {
1996 "size": "7.5pt",
1997 "line_height": 1.4
1998 },
1999 "figure_caption": {
2000 "size": "8pt"
2001 },
2002 "footnote": {
2003 "size": "8pt",
2004 "note": "Scoped to the page, not the column: one notes area spanning both columns at the page foot."
2005 },
2006 "endnotes": {
2007 "size": "8.5pt"
2008 },
2009 "pullquote": {
2010 "size": "12pt",
2011 "note": "Column width by default. Spanning both columns turns it into a divider, which is a different and heavier thing."
2012 },
2013 "abstract": {
2014 "size": "9pt",
2015 "max_width": "the full text width, set apart above the columns"
2016 }
2017 }
2018 }
2019 }
2020}