body { font-family: var(--serif); font-size: 100%; line-height: 1.3; } /* The monospace font is scaled so its letters are the height of the serif font's, rather than by eye: md_to_pdf.py computes --mono-scale from the two fonts' x-height and cap-height (the same rule the SKS applies), so this stays right if either font is changed. */ code, pre { font-family: var(--mono); font-size: calc(1em * var(--mono-scale, 1)); } /* Once, not twice. A fenced block is
, so both elements match
the rule above and the scale is applied to the scaled size: measured
before this rule, inline code came out at 14.00px and the same code in a
box at 12.26px -- a metric-matched scale silently defeating itself. The
code in a box inherits the pre's size instead. */
pre code {
font-size: 1em;
}
h1, h2, h3, h4, h5, h6 {
font-family: var(--sans);
font-weight: normal;
padding-top: .5rem;
padding-bottom: 0rem;
margin-top: .0rem;
margin-bottom: 0rem;
}
h1 {
font-size: 1.2rem;
}
h2 {
font-size: 1.1rem;
}
h3, h4, h5, h6 {
font-size: 1.0rem;
}
/* The gap between a section number and its title, in a heading and in a
table-of-contents entry alike. The number is plain text in the Markdown
("## 2.9 Keystone correction", "- [2.9 Keystone correction](#29-...)");
md_to_pdf.py wraps it in this span and eats the space that followed it, so
the whole distance is set here. Change --secnum-gap to widen or narrow
it, or give the contents its own gap with a "li .secnum" rule. To rule a
contents into columns rather than merely space it, add
"display: inline-block" and a "min-width" there: the titles then align
instead of each starting one gap after a number of its own width. */
:root {
--secnum-gap: 0.5em;
}
.secnum {
margin-right: var(--secnum-gap);
}
p, ol, ul {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
pre {
/* A code line wider than the page does not overflow or clip when
printing: Chromium shrinks the WHOLE document until it fits, silently,
by a factor that changes with the longest line. Wrapping guarantees
that never happens. md_to_pdf.py --wrap-code breaks shell lines at a
word boundary with a "\" first, which is copy-pasteable; this catches
what it cannot wrap (PowerShell, .ini, ASCII diagrams). */
white-space: pre-wrap;
overflow-wrap: anywhere;
padding-left: 0rem;
border: 1px solid #888;
background-color: #EFE;
}
th {
border-bottom: 1px solid #000;
}
table, th, td {
border: 1px solid gray;
}
@media print {
/* A section title never sits alone at the foot of a page: the break is
forbidden between a heading and whatever follows it, so the heading
moves to the next page with its text. break-inside keeps a heading
that wraps from being split across the fold.
Chromium honours these when it paginates for printing (measured on a
16-page test document: three headings stranded at a page bottom
before, none after, and the page count unchanged). A heading it
cannot honour them for -- one taller than the page -- is laid out
as if they were absent rather than looped over, which is the
specified behaviour for an unsatisfiable avoid.
This does NOT govern how much of the following paragraph comes with
the heading: that is `orphans`, below. */
h1, h2, h3, h4, h5, h6 {
break-after: avoid;
break-inside: avoid;
}
/* A paragraph split by a page break leaves at least two lines on each
side of it: never one line stranded at the foot of a page (orphans),
never one line arriving alone at the top of the next (widows) -- and
with break-after above, that top-of-page line would be the one
directly under a heading the break has just moved. Both properties
are inherited, so declaring them on body covers list items and table
cells too.
Measured on a 16-page test document: Chromium honours both -- with
orphans: 1 it packs the text into 15 pages, and with widows: 1 it
moves a line back across a page boundary (same page count, different
pagination) -- and 2 is ALREADY its default for both, so rendering
with these declarations is byte-identical to rendering without them.
They are here to pin the values, not to change today's output: the CSS
initial value is 2 but a UA is free to differ, and a stylesheet added
after this one could relax it. */
body {
orphans: 2;
widows: 2;
}
pre {
padding: .75rem 1.25rem .75rem 1.25rem;
break-inside: avoid;
}
a[href]:after {
content: none;
}
th, td {
padding: .25rem .75rem;
}
table {
margin-left: 1rem;
margin-bottom: .5rem;
border-collapse: collapse;
}
th {
border-bottom: 1px solid #000;
text-align: left;
padding-right: 2rem;
padding-bottom: 0.2em;
}
tbody tr:first-child td {
padding-top: 0.0em;
}
blockquote {
margin-left: 1rem;
}
table, th, td {
border: 1px solid #BBB;
}
:root {
--link-blue: #042B8C; /* #03216C; */
}
a {
color: var(--link-blue);
}
a, a:link, a:visited {
outline: 0;
text-decoration: none;
}
a:hover {
text-decoration: underline;
text-underline-offset: 0.2em;
text-decoration-thickness: 1px;
outline: 0;
}
/* The page number, in the document's own face.
This is a CSS Paged Media margin box, and it is the reason to prefer
it over md_to_pdf.py's --page-numbers: Chromium's footer template is
rendered in a context of its own that cannot see this stylesheet, so
the number comes out in a generic sans, while var(--serif) here is the
EB Garamond the text is set in. Measured 2026-08-09 on Brave 151:
margin boxes work and count pages. They are recent, though -- an
older Chromium silently prints no number at all.
DO NOT ALSO PASS --page-numbers. The two mechanisms are independent
and both would draw, one over the other, and the flag additionally
widens the bottom margin.
HEIGHT. A margin box is drawn in the margin and cannot be moved out
of it, so where the number sits and how much text a page holds are
one question, not two. Chromium centres the box in the margin band
by default; these declarations pin it to the top of a slightly larger
band instead, which puts the number 27pt above the paper edge rather
than 12 -- a body line higher -- while the padding, all 1.5pt of it,
leaves the text block ending just above it. The text therefore keeps
the line it would otherwise have lost to the raised number: measured,
a document that grew from 3 pages to 4 when the number was raised
alone is back to 3.
THE TIGHT SPOT, and the number to change if it shows. Text and
number now share a narrow band, so on a page whose last line reaches
the bottom of the block they nearly touch: measured worst pages over
three documents, 7.6 / 3.1 / 2.4pt between the last line's box and
the number's. Nothing overlapped, but 2.4pt is close. Giving the
text back only HALF a line -- margin-bottom 0.60in, padding-top
4.4pt, the number within a point of where it is now -- measured
8.4 / 9.1 / 11.4pt instead, and cost no document a page.
var(--serif) is safe here because the body is set in it, so the
webfont is loaded. A face the document does not otherwise use is NOT
loaded for a margin box: var(--mono) in a prose-only document fell
back to the platform monospace, and in one variant the box rendered
nothing whatever -- silently, as ever with print CSS. */
@page {
margin-bottom: 0.56in; /* the number, and little else */
@bottom-center {
content: counter(page) " of " counter(pages);
font-family: var(--serif);
font-size: 9pt;
color: black;
vertical-align: top; /* not centred in the margin band */
padding-top: 1.5pt; /* its distance from the text */
}
}
}