Quaintitative — Design Spec
Design system for quaintitative.com (Jekyll + Tailwind Play CDN + Alpine.js, hosted on GitHub Pages). This spec documents the actual tokens and assets in the repo so the look can be reproduced or extended consistently.
Source of truth:
_includes/head.html(Tailwind config + fonts),assets/css/custom.css(CSS variables + prose),_config.yml(site metadata),assets/images/(brand assets).
1. Brand Assets
Located in assets/images/. All are tracked in git; three had been deleted from the working tree and were restored (2026-07-11).
| File | Format | Dimensions | Size | Purpose | Referenced in |
|---|---|---|---|---|---|
logo.png |
PNG (RGBA, transparent) | 611 × 97 | 15 KB | Wordmark — “Quaintitative” set in a serif italic (Playfair Display), black on transparent. Navbar brand. | _includes/navbar.html:5 (class="h-[22px] w-auto") |
favicon.ico |
PNG (RGBA) — see note | 74 × 92 | 2.4 KB | Favicon / icon mark — ornate serif “Q” (the wordmark’s initial). | _includes/head.html:87-88; _config.yml:20 |
headshot.jpg |
JPEG | 500 × 500 | 61 KB | Profile photo of Gary Ang. | About / author contexts |
me_abstract.png |
PNG (RGBA) | 1024 × 1024 | 1.1 MB | Abstract profile / hero image. | Hero / about contexts |
Logo lockups
- Full wordmark:
logo.png— use for navbar, letterhead, wide contexts. Rendered at ~22px tall in the navbar. - Icon mark: the “Q” from
favicon.ico— use for favicon, avatars, square/social contexts. - Type-set fallback: the wordmark is also reproducible as live text in Playfair Display italic (
font-brand), e.g.index.md:11→<p class="font-brand italic">Quaintitative</p>. Use this when an image can’t be embedded.
⚠️ Favicon caveat: favicon.ico is a PNG file with an .ico extension (74×92, non-square). Browsers tolerate it, but for crisp rendering it should be regenerated as a true multi-resolution .ico (16/32/48px) plus a 180×180 apple-touch-icon.png and a square (1:1) source. Current file is neither square nor a real ICO container.
2. Color System
Defined as CSS custom properties in custom.css and wired into Tailwind via head.html. The site ships light-mode only (the last commit removed the dark-mode toggle & auto-detect); the .dark tokens remain in CSS but are not activated by any UI, since nothing adds the .dark class.
Light (active)
| Token | Value | Role |
|---|---|---|
--background |
#ffffff |
Page background |
--foreground |
#1a1a1a |
Body text (near-black) |
--primary |
#171717 |
Primary / buttons |
--primary-foreground |
#fafafa |
Text on primary |
--secondary |
#f5f5f5 |
Subtle fills (code, table headers) |
--muted |
#f5f5f5 |
Muted surfaces |
--muted-foreground |
#737373 |
Secondary text, link underlines |
--yellow |
#171717 |
Accent (reading-progress bar) — monochrome, not literally yellow |
--yellow-muted |
#f5f5f5 |
Accent muted fill |
--yellow-foreground |
#fafafa |
Text on accent |
--border |
#1f1f1f |
Strong borders (table cells, rules, blockquote) |
--border-subtle |
#e5e5e5 |
Hairline borders |
Dark (defined but dormant)
| Token | Value |
|---|---|
--background |
#1a1a1a |
--foreground |
#fafafa |
--primary |
#e5e5e5 |
--secondary / --muted |
#2a2a2a |
--muted-foreground |
#a3a3a3 |
--border |
rgba(255,255,255,0.5) |
--border-subtle |
rgba(255,255,255,0.1) |
Palette character: strictly monochrome / grayscale — white background, near-black text, gray mutes. No chromatic accent (the --yellow token is a placeholder name kept from the source system govern.simplyboring.ai, but resolves to black). Keep new UI monochrome to stay on-brand.
3. Typography
Three families loaded from Google Fonts (head.html:40) and mapped in the Tailwind config (head.html:49-53).
| Tailwind class | Family | Weights / styles loaded | Usage |
|---|---|---|---|
font-sans (default) |
Inter, system-ui, sans-serif | 400, 500, 600, 700 | Body text, UI, navigation |
font-heading |
Fraunces, Georgia, serif | 400, 600, 700 + italic 400 (optical size 9–144) | Headings h1–h4 (also set globally in custom.css:46-48) |
font-brand |
Playfair Display, Georgia, serif | italic 700 only | Brand wordmark, italic display accents |
Rules
- Headings (
h1–h4) are Fraunces, weight 700, applied globally viacustom.css. In prose,h2gets a bottom border (1px solid var(--border)),h2= 1.5rem,h3= 1.25rem. - Body copy is Inter, line-height 1.75 in prose.
- Playfair Display is reserved for branding (the wordmark), not body or headings — don’t use it for general text.
- Serif-for-headings + sans-for-body is the core type pairing; preserve it.
4. Layout & UI Conventions
From custom.css and the _includes/ partials.
- Prose container (
.prose): the article reading style.- Paragraphs: 1.25em bottom margin, 1.75 line-height.
- Links: foreground color, underlined with a muted underline that darkens to foreground on hover.
- Blockquotes: 3px left border (
--border), italic, muted text. - Code (inline):
--secondarybackground, 0.25rem radius, 0.875em. - Code blocks /
.highlight(Rouge):--secondarybg,1pxborder, 0.5rem radius, horizontal scroll. - Tables: full width, collapsed borders (
1px solid --border), header row on--secondary, 0.875rem. - Images: 0.5rem border-radius.
- Rules (
hr): single hairline on--border.
- Radii: small UI =
0.25rem; blocks/images =0.5rem. - Reading progress bar (
.reading-progress): fixed, top, 3px tall,--yellow(black) fill,z-index: 100. - Scroll-reveal animation (
.reveal): fade-in + 24px upward translate over 0.6s ease;.visibletriggers it (see_includes/scroll-reveal.html). - Icons: UI/social icons are inline SVG (24×24 viewBox), not asset files — see
navbar.html,footer.html,article-card.html. They inheritcurrentColor.
5. Tech Stack & Meta
| Aspect | Value |
|---|---|
| Generator | Jekyll (GitHub Pages), Kramdown + GFM, Rouge highlighter |
| CSS | Tailwind Play CDN (cdn.tailwindcss.com) + custom.css |
| JS | Alpine.js 3 (CDN), scroll-reveal, reading-progress |
| Fonts | Google Fonts: Fraunces, Inter, Playfair Display |
| Plugins | jekyll-seo-tag, jekyll-sitemap, jekyll-feed |
| Domain | quaintitative.com (CNAME) |
| Permalinks | /writing/:slug/ |
| Analytics | Google Analytics G-32E018B354 |
| Social cards | Twitter summary_large_image; @garyangphd |
| Structured data | schema.org Person (Gary Ang) in head.html |
darkMode |
'class' (configured but no toggle ships — light-mode only) |
6. Design Principles
The visual choices above aren’t arbitrary — they encode the brand thesis. Use these to settle any design decision the tokens don’t cover.
- Boring is the point. No gradients, glows, drop shadows, or decorative motion. The design should read as having nothing to hide — the same “not magic, plumbing” stance as the writing. When in doubt, remove it.
- Monochrome forces real hierarchy. With no accent color to lean on, structure has to come from type scale, weight, and whitespace. If a layout only works once you add a color, the layout is wrong — fix the hierarchy, don’t add the color.
- Editorial, not SaaS. Serif headings (Fraunces) and 1.75 line-height signal this is written to be read — a journal, not a product landing page. Long-form reading is the primary surface; treat everything else as secondary to it.
- The word is the mark. Identity lives in type — the Playfair wordmark and the “Q” — not in a symbol or lockup system. A name and a voice, not a badge.
- Approachable over impressive. Plain, generous, uncaptured — the “proximity → possibility” appeal in visual form. Polish should never tip into slick or corporate; the reader should feel let in, not sold to.
- One system, quietly extended. New components inherit existing tokens (
--foreground,--secondary,0.5remradius, the three font families). Don’t introduce new colors, fonts, or radii — extend the system rather than decorate around it.
On the palette’s origin: the color tokens were lifted from
govern.simplyboring.ai(seecustom.css:1-4), which is why the--yellow*tokens resolve to monochrome black — inherited slot names, repurposed as a grayscale accent. If you ever reintroduce a real accent color, override the--yellow*tokens rather than adding new ones (principle 6).
Last updated: 2026-07-11. Regenerate this spec if custom.css, head.html, or assets/images/ change.