Design System

tylerdickey.com

Colour system

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

Extended palette

These colours exist in the colour system but are not part of the WM editorial token set. Use sparingly and contextually.

Primary

Tyler Blue

#494A65

Joseph Yellow

#F5EC8A

Dickey Orange

#D97814

Information & Warning

Verde

#006341

Verkehrsrot

#FF0000

Obra Blue

#E5FFFF

Blacks & Tints

Tintenschwarz

#000000

Daring Gray

#4A525A

Dinn Grey

#36361F

Lake District Slate

#333A3F

Additional & Alternative Blues

Cornflower Blue

#6495ED

Edison Motors Blue

#042069

Weyland Blue

#2998B5

Yellows

Yutani Yellow

#FCCC0B

Dark mode

The 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.

Tokens

Same roles, warm dark ground. Dark is not a second design.

TokenLightDarkRole
--ink#36361F#E8E2D4Body text, nav text
--ink-deep#000000#FFFFFFHeadings
--forest#006341#4FBC8CLinks, current nav
--orange#D97814#E89B4AHover, rules, ornaments
--orange-text#A04A00#E89B4AText orange on light backgrounds (4.5:1 or more)
--slate#494A65#A9A9C4Sub-headings, code
--grey#4A525A#9BA3ABMeta, secondary text
--parchment#F7F3EB#1B1B14Ground
--rule#D9D0BF#3D3D30Borders, dividers
--specimen#EAE5D8#24241BPanels, code ground

Mechanism

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;
}

Rules

Typography

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.

Headings

Page Title (h1 — italic, weight 300)

Section Heading

Sub-heading (h3)

<!-- 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>

Blockquote / epigraph

“There are no passengers on Spaceship Earth. We are all crew.”

<figure>
  <blockquote class="blockquote">
    <p class="mb-0 hanging-quote">&ldquo;Quote text.&rdquo;</p>
  </blockquote>
  <figcaption class="blockquote-footer">Attribution</figcaption>
</figure>

Entry meta

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">&mdash;Tyler Dickey, February 2020</span>

Pull quote

“Timbs for my hooligans in Brooklyn”

<p class="pull-quote">&ldquo;Quote text.&rdquo;</p>

Code

Reference dickey.css inline, or use a block:

body {
  font-size: 1.125rem;
}
<code>inline code</code>

<pre><code>block code</code></pre>

Ornaments

Three ornamental elements are used across the site. Each has a specific function — do not substitute one for another.

Page header bracket

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">&#10086;&nbsp;&nbsp;&#10087;</span>
  <h1>Page Title</h1>
</header>

Asterism dinkus

Section break between major content blocks. Never used inside a section — only between them. Always aria-hidden="true".

<p class="dinkus" aria-hidden="true">&#8258;</p>

Closing colophon leaf

A single hedera closes every page. The last element before the footer include.

<p class="colophon" aria-hidden="true">&#10087;</p>

CSS architecture

File location

All custom CSS lives in /stylesheets/dickey.css. No <style> blocks in PHP files. No separate per-page CSS files.

Scoped page wrapper pattern

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; }
}

Global utilities already in dickey.css

These are defined globally and available on all pages. Do not redefine them inside scoped page blocks.

ClassPurpose
.dinkusCentred asterism section break
.colophonCentred closing hedera leaf
.entry-metaSmall italic Daring Gray attribution line
.section-linkResource/podcast title link (bold, forest green)
.section-descDescription paragraph below a section-link
.pull-quoteLarge italic pull quote
.hanging-quoteNegative text-indent for opening quote marks
.dropcapLarge drop capital for opening paragraphs
.externalExternal link marker (appends ↗ icon via CSS)

Known global rules to work with, not against

Interoperable

Interoperable 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.

Shared

Different on purpose

Thingtylerdickey.comInteroperable
Root size16px11.2px (Ghost sets html to 70%). Multiply a rem value here by 1.43
FooterInk band, orange ruleParchment, thin rule
Colour schemeHeader toggle: sun or crescent moonFollows the system only
BootstrapBridged to the tokensNot used
PNG logos—Inverted in the header and footer; on a light plate inside posts
External linksclass="external", target, relIcon matched by href; Ghost cannot add the attributes

A parity check compares the two palettes. When a token changes, change both.

Content patterns

Section link + description

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.

Resource or Podcast Title

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>

Podcast / list entry with star badge

A .podcast-entry wraps a section-link and optional editor's choice star. Entries are separated by a var(--rule) bottom border.

99% Invisible Editor’s Choice,

About all the thought that goes into the things we don’t think about—the unnoticed architecture and design of the world around us.

Articles of Interest Editor’s Choice, 2025

A show about what we wear.

<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&rsquo;s Choice, </span>
    <i class="bi bi-star-fill" aria-hidden="true"></i><em>2025</em></sup>
  <p class="section-desc">Description.</p>
</div>

Page header

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">
    &#10086;&nbsp;&nbsp;&#10087;
  </span>
  <h1>Page Title</h1>
  <!-- Optional subtitle: -->
  <p class="[page]-sub">Subtitle or tagline</p>
</header>

Collapse footnote (Bootstrap)

Used on the About page for inline footnotes. The superscript link toggles a .collapse div below the paragraph.

Some text with a footnote.

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>

Date picker

The changelog's From and To date pickers, shown live. This is the same component and the same bundle as the changelog page.

By date
<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.

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.

Sidenotes

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.

Three treatments

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.

A · Numeral recommended

Set in cold type.Orange superscript, hairline rule above the note. Quiet and Tufte-classic.

B · Hedera

Set in cold type.A hedera leaf marks the note instead of a bare number—more in keeping with the house ornament.

C · Ruled aside

Set in cold type.A boxed aside with an orange rule and a numbered tab.

The markup

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>

Figures in the margin

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.

Elements of style

Full rules are in CLAUDE.md. This section summarises the most frequently applied conventions.

British English

Punctuation

Numerals

Links

Capitalisation

Chyrons (on-screen text)

Logos & iconography

Footer Balls Logo Tyler Dickey Glitched TTT - animated

Additional resources

BBC News Style Guide

The current style guide for all BBC News output — spelling, punctuation, grammar, accuracy, and impartiality.

Purdue OWL

The Purdue Online Writing Lab. Writing resources, citation formats, and instructional material covering most style guides.