tylerdickey.com
Nine tokens form the William Morris palette. They are defined once, as CSS custom properties on :root in dickey.css, with a dark set under prefers-color-scheme: dark (the same mechanism as interoperable.tylerdickey.com; data-theme="light" on <html> forces light). Reference them by token name, never by raw hex value, and do not redeclare them on a page wrapper: a local copy shadows the dark set and that page stays light.
--ink
#36361F
Body text — Dinn Grey
--ink-deep
#000000
Headings — Tintenschwarz
--forest
#006341
Links — Verde
--orange
#D97814
Ornaments, rules, borders — Dickey Orange
--slate
#494A65
Accents — Tyler Blue
--grey
#4A525A
Meta text, secondary — Daring Gray
--rule
#D9D0BF
Soft dividers — Warm Rule
--parchment
#F7F3EB
Page background — Parchment
--specimen
#EAE5D8
Panels, code ground — Specimen
These colours exist in the colour system but are not part of the WM editorial token set. Use sparingly and contextually.
Tyler Blue
#494A65Joseph Yellow
#F5EC8ADickey Orange
#D97814Verde
#006341Verkehrsrot
#FF0000Obra Blue
#E5FFFFTintenschwarz
#000000Daring Gray
#4A525ADinn Grey
#36361FLake District Slate
#333A3FCornflower Blue
#6495EDEdison Motors Blue
#042069Weyland Blue
#2998B5Yutani Yellow
#FCCC0BThe site follows the system setting. A toggle at the top right of the header (NavBar.php) switches it: a sun in light mode, a crescent moon in dark, one click to swap. The choice is kept in localStorage as theme and applied as data-theme on <html>. Until someone clicks, the page follows the system.
Same roles, warm dark ground. Dark is not a second design.
| Token | Light | Dark | Role |
|---|---|---|---|
--ink | #36361F | #E8E2D4 | Body text, nav text |
--ink-deep | #000000 | #FFFFFF | Headings |
--forest | #006341 | #4FBC8C | Links, current nav |
--orange | #D97814 | #E89B4A | Hover, rules, ornaments |
--orange-text | #A04A00 | #E89B4A | Text orange on light backgrounds (4.5:1 or more) |
--slate | #494A65 | #A9A9C4 | Sub-headings, code |
--grey | #4A525A | #9BA3AB | Meta, secondary text |
--parchment | #F7F3EB | #1B1B14 | Ground |
--rule | #D9D0BF | #3D3D30 | Borders, dividers |
--specimen | #EAE5D8 | #24241B | Panels, code ground |
Three blocks at the top of dickey.css. The second is the system setting; the third is the header toggle forcing dark.
:root {
--ink: #36361F; /* …nine tokens */
color-scheme: light;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--ink: #E8E2D4; /* …nine tokens */
color-scheme: dark;
}
}
:root[data-theme="dark"] {
--ink: #E8E2D4; /* the same nine values */
color-scheme: dark;
}
var(--token). A hardcoded palette hex stays light in dark mode.--bs-body-color, --bs-body-bg, --bs-emphasis-color, --bs-secondary-color, --bs-border-color and --bs-tertiary-bg. All six point at the tokens on :root, so .text-muted, borders and cards follow.document.documentElement.dataset.theme = 'dark' in the console, or use the toggle.All pages use Crimson Pro by Sebastian Kosch, served via Google Fonts. It is set globally via --bs-body-font-family in dickey.css. Scoped page wrappers explicitly declare font-family: 'Crimson Pro', Georgia, serif to ensure inheritance is explicit.
Page Title (h1 — italic, weight 300)
<!-- Page h1: large, italic, weight 300 -->
<h1>Page Title</h1>
<!-- Section h2: inline-block, orange underline rule -->
<h2>Section Heading</h2>
<!-- Sub-heading h3 -->
<h3>Sub-heading</h3>
“There are no passengers on Spaceship Earth. We are all crew.”
<figure>
<blockquote class="blockquote">
<p class="mb-0 hanging-quote">“Quote text.”</p>
</blockquote>
<figcaption class="blockquote-footer">Attribution</figcaption>
</figure>
Small italic attribution or date line. Appears below a heading or after a short piece of prose. Never inside a paragraph.
<span class="entry-meta">—Tyler Dickey, February 2020</span>
“Timbs for my hooligans in Brooklyn”
<p class="pull-quote">“Quote text.”</p>
Reference dickey.css inline, or use a block:
body {
font-size: 1.125rem;
}
<code>inline code</code>
<pre><code>block code</code></pre>
Three ornamental elements are used across the site. Each has a specific function — do not substitute one for another.
A matching pair of hedera leaves brackets the page title. Dickey Orange, centred, above the <h1>. Used on every WM redesigned page.
<header class="[page]-header">
<span class="[page]-bracket" aria-hidden="true">❦ ❧</span>
<h1>Page Title</h1>
</header>
Section break between major content blocks. Never used inside a section — only between them. Always aria-hidden="true".
<p class="dinkus" aria-hidden="true">⁂</p>
A single hedera closes every page. The last element before the footer include.
<p class="colophon" aria-hidden="true">❧</p>
All custom CSS lives in /stylesheets/dickey.css. No <style> blocks in PHP files. No separate per-page CSS files.
Every page has a single wrapper <div> with a unique class: .about-page, .podcasts-page, etc. All CSS for that page is nested under that class. This prevents rules bleeding across pages.
/* ══ [pagename].php — William Morris editorial layout ══ */
.[pagename]-page {
/* colour tokens come from :root; do not redeclare them here */
font-family: 'Crimson Pro', Georgia, serif;
font-size: 19px;
line-height: 1.65;
color: var(--ink);
max-width: 680px;
margin: 0 auto;
padding: 3rem 1.5rem 5rem;
}
.[pagename]-header {
text-align: center;
margin-bottom: 2.5rem;
padding-bottom: 2rem;
border-bottom: 2px solid var(--orange);
}
.[pagename]-bracket {
font-family: Georgia, 'Times New Roman', serif;
font-size: 1.5rem;
color: var(--orange);
letter-spacing: 0.6em;
display: block;
margin-bottom: 0.75rem;
line-height: 1;
}
.[pagename]-header h1 {
font-family: 'Crimson Pro', Georgia, serif;
font-size: 3.25rem;
font-weight: 300;
font-style: italic;
color: var(--ink-deep);
letter-spacing: -0.01em;
line-height: 1.1;
margin: 0;
}
.[pagename]-page a {
color: var(--forest);
}
.[pagename]-page a:hover,
.[pagename]-page a:focus {
color: var(--orange);
}
@media (max-width: 600px) {
.[pagename]-page { font-size: 17px; padding: 2rem 1rem 4rem; }
.[pagename]-header h1 { font-size: 2.4rem; }
}
These are defined globally and available on all pages. Do not redefine them inside scoped page blocks.
| Class | Purpose |
|---|---|
.dinkus | Centred asterism section break |
.colophon | Centred closing hedera leaf |
.entry-meta | Small italic Daring Gray attribution line |
.section-link | Resource/podcast title link (bold, forest green) |
.section-desc | Description paragraph below a section-link |
.pull-quote | Large italic pull quote |
.hanging-quote | Negative text-indent for opening quote marks |
.dropcap | Large drop capital for opening paragraphs |
.external | External link marker (appends ↗ icon via CSS) |
a { text-decoration: none } — override at scoped level: .[page]-page a { text-decoration: underline }body { font-size: 1.125rem } — scope your font-size to the page wrapper.navbar, .navbar * { font-size: 20px !important } — never touch thisInteroperable runs on Ghost at interoperable.tylerdickey.com and shares this system without sharing code. One block of CSS pasted into Ghost carries the nine tokens, Crimson Pro, the dark mechanism and the conventions below. dickey.css is the source: change it here first, then mirror it there.
:root| Thing | tylerdickey.com | Interoperable |
|---|---|---|
| Root size | 16px | 11.2px (Ghost sets html to 70%). Multiply a rem value here by 1.43 |
| Footer | Ink band, orange rule | Parchment, thin rule |
| Colour scheme | Header toggle: sun or crescent moon | Follows the system only |
| Bootstrap | Bridged to the tokens | Not used |
| PNG logos | — | Inverted in the header and footer; on a light plate inside posts |
| External links | class="external", target, rel | Icon matched by href; Ghost cannot add the attributes |
A parity check compares the two palettes. When a token changes, change both.
Used for resource lists, podcast entries, telephony references — anywhere a link title is followed by a short description. The link uses the global .section-link class; the paragraph uses .section-desc.
A short description of the resource, what it is and why it is here.
<a href="URL" target="_blank" rel="noopener noreferrer"
class="external section-link">Title</a>
<p class="section-desc">Description text.</p>
A .podcast-entry wraps a section-link and optional editor's choice star. Entries are separated by a var(--rule) bottom border.
About all the thought that goes into the things we don’t think about—the unnoticed architecture and design of the world around us.
<div class="podcast-entry">
<a href="URL" class="external section-link">Title</a>
<!-- Editor's Choice marker: the year is optional -->
<sup class="editors-choice"><span class="visually-hidden">Editor’s Choice, </span>
<i class="bi bi-star-fill" aria-hidden="true"></i><em>2025</em></sup>
<p class="section-desc">Description.</p>
</div>
Standard header structure used on every WM redesigned page. The bracket span is purely ornamental; always aria-hidden="true".
<header class="[page]-header">
<span class="[page]-bracket" aria-hidden="true">
❦ ❧
</span>
<h1>Page Title</h1>
<!-- Optional subtitle: -->
<p class="[page]-sub">Subtitle or tagline</p>
</header>
Used on the About page for inline footnotes. The superscript link toggles a .collapse div below the paragraph.
Some text with a footnote.1
1 The footnote content appears here when expanded.
<p>Text with a footnote.<sup><a data-bs-toggle="collapse"
href="#fn-1" role="button" aria-expanded="false"
aria-controls="fn-1">1</a></sup></p>
<div class="collapse about-footnote" id="fn-1">
<p><sup>1</sup> Footnote content.</p>
</div>
The changelog's From and To date pickers, shown live. This is the same component and the same bundle as the changelog page.
<div class="filter-row date-row" role="group" aria-labelledby="label-date">
<span class="filter-label" id="label-date">By date</span>
<!-- the picker mounts here -->
<div id="cl-date-range" class="cl-date-range"></div>
</div>
<script src="js/changelog-dates.js" defer></script>
Two inputs, From and To, each with a calendar button. The calendar opens on the entered date, or on today if none is set.
cl-dates event with ISO dates. Reset sends cl-dates-reset to clear the pickers. The presets send cl-dates-set to move them.The source is in build/changelog-dates. Its bundle, js/changelog-dates.js, is built with pinned versions of React Aria, React and @internationalized/date. The inputs keep a fixed width of 6.5rem, and the calendar is 17rem wide.
Tufte-style margin notes: a note set into the wide margin beside the text, where the eye can cross to it and back without leaving its place. A static-CSS engine—counters for numbering, a hidden checkbox for the mobile pop-in, notes floated into the gutter with a negative margin. No JavaScript.
Two kinds, two jobs. A sidenote is numbered and anchored to a point in the text—the direct replacement for a footnote. A margin note is unnumbered—free-floating text, used as a one-line paragraph summary that lets a reader skim the page by its margins.
The engine needs a two-part width structure so a margin exists to float into: a wide .sn-article wrapping a narrower .sn-body reading measure (~700px). Behaviour is fixed by screen width—wide screens use both margins (author places each note left or right); medium screens move every note to one right-hand gutter; on mobile notes collapse, and tapping the marker pops the note open in place.
Set the treatment with data-tr="a|b|c" on the .sn-doc wrapper. A (Numeral) is the default and the recommendation—lightest, reads as type rather than UI, survives reader-mode and print. B (Hedera) suits short, sparsely-noted essays where the house ornament has room to breathe; C (Ruled aside) earns its keep on citation-heavy pages where a firmer boundary aids scanning.
Set in cold type.Orange superscript, hairline rule above the note. Quiet and Tufte-classic.
Set in cold type.A hedera leaf marks the note instead of a bare number—more in keeping with the house ornament.
Set in cold type.A boxed aside with an orange rule and a numbered tab.
Three elements in source order: the label.sn-num marker, a hidden input.sn-check (the mobile toggle), and the note span. The note sits immediately after its anchor, so a screen reader meets it in the right place; markers are aria-hidden decoration and the toggle is a native checkbox, so it works by keyboard.
<!-- page wrapper: wide outer, narrow measure -->
<article class="sn-article">
<div class="sn-body">
<div class="sn-doc" data-tr="a">
<!-- numbered sidenote -->
<p>Text that needs a note.<label for="sn-1"
class="sn-num" aria-hidden="true"></label><input
type="checkbox" id="sn-1" class="sn-check"><span
class="sidenote">This is a sidenote.</span></p>
<!-- same, opted onto the LEFT gutter -->
<span class="sidenote left">…</span>
<!-- unnumbered margin note -->
<label for="mn-1" class="mn-toggle"
aria-hidden="true">❧</label><input type="checkbox"
id="mn-1" class="sn-check"><span
class="marginnote">A summary of this paragraph.</span>
</div>
</div>
</article>
A diagram or photograph sits in the gutter exactly as a sidenote does—a thumbnail with a caption, tapping opens it full-size in a pure-CSS lightbox. Figures carry their own Fig. N numbering, independent of the sidenote sequence, and never collapse on mobile—they drop inline at full width.
<label for="fig-1" class="fig-ref">(fig. 1)</label><input
type="checkbox" id="fig-1" class="fig-check">
<span class="sidenote figure">
<label for="fig-1" class="fig-thumb">
<img src="earthrise.jpg" alt="…"></label>
<span class="fig-cap">‘Earthrise’, Apollo 8, 1968.</span>
<label for="fig-1" class="fig-lightbox">
<img src="earthrise.jpg" alt="…">
<span class="fig-x">×</span></label>
</span>
Authoring. Notes aren't written by hand—they're ordinary Markdown footnotes rewritten into these spans at build time (a Pandoc workflow with pandoc-sidenote does exactly this), so existing posts gain sidenotes with no change to how they're written. Reach for the JavaScript fallback (in the spirit of gwern’s sidenotes.js) only on a genuinely note-dense page, where static notes could collide.
Full rules are in CLAUDE.md. This section summarises the most frequently applied conventions.
<a href="...">Read more</a>.target="_blank" rel="noopener noreferrer" class="external".target, no rel, no class="external".
The current style guide for all BBC News output — spelling, punctuation, grammar, accuracy, and impartiality.
Purdue OWLThe Purdue Online Writing Lab. Writing resources, citation formats, and instructional material covering most style guides.