Tokens, not values
85 custom properties in css/tokens.css — colour, type, the Carbon-style spacing scale (--space-01 through --space-12), radius, shadow, duration, and easing. One committed theme lives on :root — no second theme block redeclaring the same property names. css/styles.css — every component in the site — has zero raw colour values except two, and both are deliberate: a physical printed photo (.work-card-media, .about-photo) is pinned regardless of the mat's current colour, documented in place. Zero !important anywhere in the file.
Six fonts, each with a job
All self-hosted, nothing served from a third-party font CDN.
- Inter
- Body text. Self-hosted from rsms.me/inter/.
- Commissioner
- Headings and buttons.
- IBM Plex Mono
- Eyebrows, meta labels, code — the monospace voice that marks this site's own system to itself, like the one on this page.
- Reem Kufi
- RTL headings and buttons, substituting for Commissioner under
[dir="rtl"]. - IBM Plex Sans Arabic
- RTL body, mono, and eyebrow text, substituting for Inter and IBM Plex Mono under
[dir="rtl"]. - Architects Daughter
- Sticky-note handwriting only — the small annotation text on the photo captions and stat cards, never body copy.
Inter, Commissioner, and IBM Plex Mono are Latin-subsetted (see the performance numbers below, and this repo's own docs/FONT-LOADING-PERF-PLAN.md and docs/CLEANUP-PLAN.md for the history behind that).
Accessibility, measured
Verified live in a browser, not inferred from the markup:
- Contrast. Zero WCAG AA failures across every text node on the homepage, across all eleven mat-colour swatches — including the one colour with no pre-solved lookup table entry, which clears AA on its own through a live binary-search derivation (see
js/main.js§4b). - Touch targets. No interactive element under 24×24 CSS px at a 320px viewport.
- Reflow. No horizontal overflow at 320px, in either reading direction.
- Motion. Every transition and animation in
styles.cssroutes through three duration tokens;prefers-reduced-motion: reducecollapses all three to 1ms in one rule, not a per-component opt-out. - Keyboard and structure. One
h1per page, no skipped heading levels, no duplicate IDs, a skip link as the first focusable element, and a visible focus ring on every interactive element — including inside the surface-recolour panel's own radiogroup, which supports arrow-key selection like a native<input type="radio">.
Built for both directions
css/styles.css contains zero physical left/right properties — no margin-left, no text-align: left, no border-right. Every layout rule uses logical properties (margin-inline-start, inset-inline-end, text-align: start) so flipping dir="rtl" mirrors the entire layout without a single direction-specific override. Directional icons carry an .icon-directional class that flips them under [dir="rtl"] — the Prev/Next arrows at the end of every case study are examples of this. Numbers, phone numbers, and email addresses stay left-to-right inside right-to-left text via <bdi> wrapping, so a UAE phone number doesn't get its digit order reversed by the bidi algorithm.
What got measured and fixed
This site went through its own cleanup pass — the same kind of audit its case studies describe doing for other products. Before/after numbers, not estimates:
-
89%
Cut from the site's heaviest images (7.07MB → 0.79MB across 7 files) — three were base64-encoded PNGs wearing an SVG file extension, re-encoded as WebP at the resolution they're actually displayed at; four were genuine vector diagrams that just needed path-precision cleanup, not rasterising.
-
85%
Cut from the favicon (124KB → 18KB) by reducing an auto-traced illustration's coordinate precision to what a 16–32px icon can actually show — verified pixel-identical to the original at both render sizes before shipping.
-
61%
Cut from
tokens.css(82KB → 31.7KB raw) by moving two inline SVG data URIs — the light and dark cutting-mat illustrations — to external, separately-cacheable files once neither turned out to depend on a CSS custom property. -
72%
Cut from four of this site's pages' JavaScript payload (285KB → 78.6KB raw) by splitting page-specific translation content out of the shared script, so a page with no case-study body stops downloading one anyway.
No build step
Plain HTML, CSS, and vanilla JavaScript. No framework, no npm dependency, no bundler in the path between editing a file and it being the deployed site — what's in this repository is what a browser reads. The handful of command-line tools used to prepare assets above (svgo for path precision, fonttools/pyftsubset for font subsetting, sharp for the image re-encodes) ran once each, by hand, to produce a smaller committed file — none of them run again on a visitor's request, and none of them are a dependency of the site itself.