Design System

ACIDBATH
Visual Language

A cohesive design system built entirely on Iosevka type variants. Multi-theme, responsive, and compatible with Tailwind CSS, shadcn/ui, and Radix UI. Every token, component, and pattern used to build this blog — available to drop into any project.

7 Themes (×2 light/dark)
7 Typography profiles
5 Iosevka variants
11 Spacing steps

Portable files — drop into any project

design-system/tokens.cssAll CSS custom properties — 7 themes, type scale, spacing
design-system/components.cssBase resets + component patterns
design-system/tailwind.config.jsTailwind v3 config
design-system/tailwind-v4-theme.cssTailwind v4 @theme block
design-system/llm-context.mdCompact reference optimized for LLM context windows
design-system/tokens.jsonMachine-readable token data

Themes

7 Themes × Light + Dark

Apply themes by setting data-theme on <html>. All color tokens update automatically via CSS custom properties.

Active: dusk
Anti-flash pattern
Add this inline script to <head> before any CSS to prevent a flash of the wrong theme on page load:

(()=>{ const t=localStorage.getItem('theme')||'dusk'; document.documentElement.dataset.theme=t; })()

Colors

Token Reference

Every color is a CSS custom property. They update automatically when the theme changes — no JS required for color switching.

Backgrounds

--color-background Page bg
--color-background-alt Section fills
--color-background-elevated Cards, popovers
--color-background-hover Interactive hover
--color-background-code Code blocks

Text

--color-foreground Headings, strong
--color-foreground-alt Body paragraphs
--color-foreground-muted Captions, meta

Accents

--color-accent-primary Links, active states, underlines
--color-accent-secondary Deeper hover
--color-accent-muted Tag fills, selection bg, inline code bg

Semantic Status

--color-warning + --color-warning-bg
--color-info + --color-info-bg
--color-success + --color-success-bg
--color-danger + --color-danger-bg
--color-insight + --color-insight-bg
--color-data + --color-data-bg

Structure

--border All borders, dividers
--card Card surface (semi-transparent)
--ring Focus rings

Typography

All Iosevka

One type family across all roles. Iosevka Etoile (quasi-proportional slab) reads like a traditional serif. Iosevka Curly Slab gives headings texture. Pure Iosevka handles code. Deep coherence at every level.

Body · Iosevka Etoile

Signal over hype. Production notes on agents, context engineering, and software that survives contact with reality.

@fontsource/iosevka-etoile · --font-family-body

Headings · Iosevka Curly Slab

Three-Layer AI Operations

@fontsource/iosevka-curly-slab · --font-family-heading

Code · Iosevka

const agent = new Agent({
  model: "claude-sonnet-4",
  tools: [readFile, bash]
});
@fontsource/iosevka · --font-family-mono

Fluid Type Scale

All sizes use clamp(min, preferred, max) — smooth scaling from 375px to 1280px with no breakpoints.

--text-xs CONTEXT ENGINEERING · MARCH 2026 0.72–0.82rem
--text-sm Production patterns for AI agents 0.88–0.98rem
--text-base Ship AI that actually works in production 1.0–1.1rem
--text-lg Context engineering complete guide 1.1–1.35rem
--text-xl Agent Architecture 1.35–1.8rem
--text-2xl Three-Layer Pattern 1.8–2.65rem
--text-3xl Ship AI 2.7–4.8rem

Typography Profiles

Apply via data-typography on <html>. Controls body line-height, font-weight, letter-spacing, and size multipliers.

Spacing & Scale

4px Base Unit

All spacing uses --space-N tokens. Never use raw px or rem values for layout spacing — always go through the scale.

Spacing scale

--space-1
4px
--space-2
8px
--space-3
12px
--space-4
16px
--space-5
20px
--space-6
24px
--space-8
32px
--space-10
40px
--space-12
48px
--space-16
64px
--space-20
80px

Border radius

--radius-sm 10px · Code, inputs, buttons
--radius-md 18px · Modals, tables, forms
--radius-lg 28px · Cards, large surfaces
--radius-full 9999px · Tags, pills, buttons

Transitions

--transition-fast120ms ease · Micro-interactions
--transition-base180ms ease · Hover states
--transition-slow280ms ease · Background changes
(theme switch)500ms ease · All color properties

Components

Live Patterns

Every component uses only design system tokens. Switch themes above to see them all respond.

Section Kicker

Uppercase label with glowing accent dot. Use above section headings to establish context.

Featured Article

Context Engineering: Complete Guide

Show code
.section-kicker {
  display: inline-flex; align-items: center; gap: 0.65rem;
  font-family: var(--font-family-heading);
  font-size: var(--text-xs); font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.11em;
  color: var(--color-foreground-muted);
}
.section-kicker::before {
  content: ""; width: 0.62rem; height: 0.62rem;
  border-radius: var(--radius-full);
  background: var(--color-accent-primary);
  box-shadow: 0 0 0 0.4rem var(--color-accent-muted);
}

Tags & Badges

Monospace pills. Primary uses --color-accent-muted; muted uses a near-transparent background.

context-engineering agents production
claude typescript llm

Callouts

Pro Tip
Use Iosevka Etoile for body text — it reads like a traditional serif while maintaining the technical character of the Iosevka family.
Architecture note
All themes expose the same CSS custom property names. Switching themes requires only changing the data-theme attribute on <html>. No JS needed for color changes.
Dark mode
Add the theme init script to <head> before your CSS links. This prevents a flash of the wrong theme on cold page loads.
Anti-pattern
Never hardcode colors. Never use fonts other than the Iosevka family. Never use raw px/rem for spacing — always go through the --space-N scale.
shadcn/Radix compatibility
All themes include shadcn/ui aliases — --primary, --card, --ring, --destructive, etc. Components from shadcn/ui work out of the box.

Surface Card

Semi-transparent card with backdrop blur. The primary elevated surface in the design system.

Inside a surface-card

Background: var(--card) · Border: 1px solid var(--border) · Radius: var(--radius-lg) · Blur: backdrop-filter: blur(14px)

Standfirst / Pull Quote

Left accent border lead paragraph. Used for TL;DR and key takeaways at the top of posts.

Production AI engineering is about context, not code. The difference between a demo and a deployed system is usually one thing: how you feed information to the model.

Buttons & Inputs

Navigation

Uppercase mono links with accent underline on active state. The ::after underline sits 0.45rem below the baseline.

Post Card

Note List

Compact date-column grid for listing multiple posts.

LLM Access

Machine-Readable Formats

The design system exposes structured formats optimized for AI agent consumption. Paste the LLM context into any agent's system prompt to generate consistently styled components.

Markdown

LLM Context

Compact structured reference (~3K tokens) covering all tokens, component patterns, and usage rules. Optimized for LLM context windows.

Use in system prompt:

Attach design-system/llm-context.md to your coding agent's context

JSON

Design Tokens

All design tokens as structured JSON — all 14 theme variants, spacing, typography scale, radii, and transitions. Machine-parseable.

Programmatic usage:

fetch('/design-system/tokens.json').then(r => r.json())
Agentic design workflow
When building new components, paste llm-context.md into your agent's context. The agent can then generate components that correctly use var(--space-N) spacing, the right font families, and theme-aware colors — without guessing.

System Prompt Snippet

Add this to any coding agent's system prompt when working in this codebase:

# Design System Rules

You are working in the ACIDBATH design system. Follow these rules strictly:

## Colors — ALWAYS use CSS custom properties
- Background: var(--color-background), var(--color-background-alt), var(--color-background-elevated)
- Text: var(--color-foreground), var(--color-foreground-alt), var(--color-foreground-muted)
- Accent: var(--color-accent-primary), var(--color-accent-secondary), var(--color-accent-muted)
- Borders: var(--border) — NEVER rgba() values directly
- Cards: var(--card) for card backgrounds

## Fonts — ONLY Iosevka variants
- Body: var(--font-family-body)  [Iosevka Etoile]
- Headings: var(--font-family-heading) [Iosevka Curly Slab]
- Code/mono: var(--font-family-mono) [Iosevka]
- UI chrome: var(--font-family-ui) [same as body]

## Spacing — ONLY --space-N tokens
var(--space-1) = 4px  var(--space-2) = 8px  var(--space-3) = 12px
var(--space-4) = 16px var(--space-5) = 20px var(--space-6) = 24px
var(--space-8) = 32px var(--space-10)= 40px var(--space-12)= 48px

## Radii
--radius-sm: 10px (inputs, inline)
--radius-md: 18px (modals, blocks)
--radius-lg: 28px (cards, surfaces)
--radius-full: 9999px (pills, tags)

## Typography sizes
--text-xs through --text-4xl (all use clamp() for fluid scaling)

## Themes
Apply via data-theme on html. Available: dusk, parchment, seaside, olive, ink, moss, azure (+ -dark variants)
Default: dusk

## NEVER
- Hardcode hex colors
- Use font-family other than the --font-family-* tokens
- Use raw px/rem for spacing
- Use opacity on text for muting — use --color-foreground-muted