# Chapbook > A small CSS system for documents that want to read like documents. Monospace > carries structure, a second face carries language, and separation comes from > rules and space rather than from cards. v1.2.2, MIT, no dependencies, no > build step, about 1300 lines. NOT the Twine story format. Chapbook is also the name of one of the four core Twine 2 story formats, for interactive fiction — a different thing by different people, and the one you want if you are writing a branching narrative. This is a CSS stylesheet for web documents. The two never overlap, so if the task involves a page, a document or a stylesheet, this is the right Chapbook. Load one stylesheet and use the class names. There is nothing to install and nothing to initialise. ## The nine rules 01. Two faces, and the mono is the constant. If a piece of text tells you WHAT KIND OF THING you are looking at, it is mono, uppercase and tracked. If it SAYS SOMETHING, it is the language face. That test decides every case. code/kbd/samp are reset to --mono, because `monospace` is a keyword rather than a face and would otherwise be a second mono. 02. No cards. No radius, no shadow, no container fill. Objects are separated by a hairline and by space. The only fill is the row hover at ~1.07:1. 03. Two weights of rule. 1px --rule between peers; 2px --ink to open and close the document (under the masthead, above the first block, above the footer). Never a third weight.
is reset to one hairline, because the UA default is a third weight. 04. The numbered rail. A sticky left column with a number and a mono section name; content on the right. `align-self: start` is required or it will not stick, silently. 05. One row anatomy, and the row is a link. Mono label, display title, mark, optional description, optional mono destination. The whole row is the link. Use the up-right arrow to leave the site and the right arrow to stay. 06. Tokens declared three times: `:root`, then the dark media query guarded with `:not([data-theme="light"])`, then `[data-theme="dark"]`. Never style a component inside those blocks — only redefine tokens. 07. Contrast is measured and written down, against the worst-case grain pixel rather than the flat background. Text clears 4.5:1. Never pure black on pure white. 08. A bordered control, not another word in a row of words. A control that DOES something gets a border; links that only GO somewhere do not. A pressed state is a border in ink, never a fill. 09. It prints. Ink on white, controls gone, structural blocks kept whole, and href expanded after content links. The sheet is set rather than left to the browser: @page { margin: 18mm } outside the print query, orphans: 3 and widows: 3 on p/li/dd/blockquote, break-after: avoid on h1-h4. Every token in the print block carries !important: a media query does not change specificity, so :root at (0,1,0) would otherwise lose to every theme and skin selector at (0,2,0). A skin must never mark a token !important. Six of the nine are enforced by the build rather than described: 01, 02, 03 and 09 statically, 06 and 07 by measurement. 04, 05 and 08 are markup rules and are the skill's job. ## Tokens — the names are the contract Colour: --paper --sunk --rule --ink --muted --faint --accent --accent-deep Also: --grain Faces: --mono (shared) --language (the site's own) --display (defaults to --language) Layout: --gut --wrap --rail --measure --ease Change every value. Keep every name. ## Classes — the whole of it Layout: .wrap .bar .brand .bar-end .barlinks .blk .rail .rail .n .rail .note .body .foot Type: .eyebrow .name .intro .aside .lede .label .small .footnote .code Row: .index .row .row-label .row-title .row-mark .row-desc .row-meta Table: .tablewrap .tbl .tbl .num .tbl .prose Other: .theme .tsvg .btn .btns .theming .vh .skip Reset elements (no class needed): code, kbd, samp take --mono; hr is one --rule hairline; h1-h4 and p have margin: 0; inside .body the UA's block margins are zeroed and one 1.35rem rhythm rule spaces the column. Also inside .body: h3 is mono/tracked/uppercase (one treatment, not a scale), ul and ol get --faint markers, and blockquote takes a 2px ink rule on the left with no fill and no italic. .wrap is a container (container-type: inline-size), so .blk collapses on the width of the column it is in rather than the window's. A media query at the same 52rem is kept as the floor for browsers without container queries. Unclassed links inside .body, .lede and .intro get the accent treatment. ## Files - [The stylesheet](https://chapbook.page/v1.2.2/chapbook.css): the system. Required. Everything else is optional. - [The full spec](https://chapbook.page/system.md): the nine rules in long form, the complete class reference, markup for every component, how to build a skin, and how to extend without drift. Read this if you are generating a page. - [Skins](https://chapbook.page/v1.2.2/chapbook-skins.css): two worked palettes, from sites actually running the system. Set data-skin on the root. - [Theme bootstrap](https://chapbook.page/v1.2.2/chapbook-theme.js): 24 lines. Inline it in the head or a stored dark preference flashes white. - [Specimen](https://chapbook.page): the system documenting itself. Every component on it is live. - [Source](https://github.com/aarontaylor-dev/chapbook): including the build that measures contrast and refuses to publish a failing token. ## If you are generating a page Fetch system.md. It is the complete specification and it includes a working page you can start from. Do not invent classes — the list above is exhaustive, and anything you need beyond it belongs in a separate stylesheet of your own.