WrenfieldEstate Law Design system
Appearance
The site →

00 · Overview

The Wrenfield design system

One firm, one stylesheet, and a catalogue of every part in it. This is not a description of the site written next to the site — every specimen on these pages is rendered by the same two files the site itself loads, so nothing here can drift out of date without the site breaking at the same moment.

Source tokens.css and wrenfield.cssAppearances Light, dark, systemSpecimens Rendered live, never screenshotted

The catalogue

Five levels, smallest part first. The counts are read off the pages themselves when this one loads.

The rules of the house

Six of them, and every one is a rule the existing stylesheet already keeps. They are written down here so that the next thing added to the site keeps them too.

What the system will not do

A constraint is only real if it is inconvenient at least once.

  1. No component names a colour

    Every rule in wrenfield.css reaches for a working name — --bg, --text, --accent — and never for a hex value. That indirection is the whole reason one seed can change the firm's appearance, and the reason the dark appearance needed no new selectors.

  2. Both appearances are written, neither is derived

    Light and dark are each declared in full in tokens.css. Nothing is computed at runtime, nothing is a filter over the other, and a value that needs to differ is simply written twice.

  3. A rule before a box

    The site separates with a hairline far more often than with a border. Where something does become a card it earns it: a hairline all round, a 4px brand rule along the top, and one of three shadows.

  4. One ask to a page

    One filled button, and it is the thing the page is for. Everything else is a link or a ghost. A page with two primary buttons has not decided what it wants.

  5. An empty slot says it is empty

    A media slot with no picture yet holds its own frame and shows a monogram or a rule. It never collapses, so the grid does not reflow when the photographs arrive, and it never pretends with a stock image.

  6. Nothing is advertised before it works

    The menu button, the appearance toggle and the archive filter are all hidden in the markup and revealed by script. If the script does not run, the site is still a complete set of documents with working links.

One ask, and its alternative

The same section, decided twice.

Do

One filled button, one ghost.

Don't

Two asks competing, and the reader deciding which matters.

Appearance

Three settings, and they follow you out of the catalogue. The switcher in the bar writes the resolved value into the same key the site reads, so choosing dark here and clicking through to the firm's own pages keeps it dark.

The switcher

Light, dark, or whatever the machine is set to. System is a real answer, not an absence of one, and it keeps listening: change the setting on your Mac with this page open and the page follows.

src/assets/js/ds.js

Where the appearance is decided, in the order it is decided
StepWhat happens
ds.njk, in the headReads the stored mode, resolves system against prefers-color-scheme, and stamps data-theme on the root before the first paint. Nothing flashes.
tokens.cssAnswers to :root, [data-theme="light"] and [data-theme="dark"]. Because the light values are addressable on any element and not only on the root, an island of one appearance can sit inside a page of the other.
ds.jsHandles the switch, re-measures every token's resolved value and contrast, and repaints the appearance inside each live page frame.
wf-themeThe resolved value is mirrored into the site's own key, so the choice survives the walk from the catalogue to the firm.

Both, beside the switcher, is the control a design system earns: it splits every stage on the page into a light pane and a dark one so a component can be judged in both at once. It is off on the frames, because a copy of a live page frame is a second page load rather than a specimen.

One component, both appearances

Turn on Both in the bar and this stage splits. Every stage on every page does the same.

.spec-pane

Trust administration

What a successor trustee has to do, in what order, and which of it actually needs a lawyer.

Building a page

The site is a static build, so a new page is a file with front matter and some markup. The front matter is doing more work than it looks like it is.

A page, from nothing

Four decisions, in this order. Everything else is a component off one of the pages in this catalogue.

  1. Decide how it opens

    A full screen hero if the page is asking somebody to write in; a plain band if it is a document; bare if it needs to carry its own full bleed sections. That is the hero and bare pair in the front matter, and nothing else in the file has to know.

  2. Decide the measure

    wide: true if the content is a grid. Leave it off and the content sits on the reading measure inside a .prose wrapper.

  3. Build the middle out of bands

    Each section is a .band, alternating with .band-sunken, with one collection organism inside it. Never a bare div holding its own padding.

  4. Ask for the same thing in the same words

    “Request a consultation.” The shell supplies the legal notice and the footer.

---
title: What a conservatorship costs
eyebrow: Incapacity
description: What the filing, the investigator and the bond come to.
hero: true
heroMedia: image
heroImage: /assets/img/hero-family-1600.jpg
wide: true
---

<section class="band">
  <div class="wrap">
    <p class="eyebrow">What it involves</p>
    <h2>Three costs, and which of them is refundable</h2>
    <div class="svcgrid">
      <div class="card">…</div>
    </div>
  </div>
</section>

<section class="band band-sunken">
  <div class="wrap">
    <p class="eyebrow">Who does this work</p>
    <div class="whorow">…</div>
  </div>
</section>

Where everything lives

Nine files. The catalogue reads three of them directly, which is why its counts are not a claim.

The files

The three counts on the left of the catalogue are parsed out of these at build time, not typed.

Measured at build: 57 tokens across 89 lines, 224 classes across 922 lines
FileWhat is in it
src/assets/css/tokens.cssThe faces, the palette in both appearances, the working names, and the corner, shadow, motion and measure scales.
src/assets/css/wrenfield.cssEvery component on the site. Mentions no colour.
src/assets/css/brand.cssThe brand switcher, which is a demonstration control and not part of the firm's own chrome.
src/assets/css/ds.cssThis catalogue's own chrome. Styles no component.
src/assets/js/main.jsThe appearance toggle, the drawer, the two menus and the archive filter.
src/assets/js/brand-engine.jsOne seed in, a contrast checked theme out, in OKLCH, with a gate that corrects derived text until it clears AA.
src/assets/js/ds.jsThe switcher, the side by side, the markup panels, the measured values and the page frames.
src/_data/ds.jsParses tokens.css and wrenfield.css so the Foundations page is generated from the source of truth rather than transcribed from it.
.eleventy.jsThe spec and group shortcodes: a specimen renders live and prints its own markup, from one source.

Adding to the catalogue

A specimen is written once. The stage and the printed markup are the same string, so they cannot disagree.

{% spec "Primary button", "The one ask on a page.", ".btn" %}
<a class="btn" href="/contact/">Request a consultation</a>
{% endspec %}