Folio

Dark editorial publication

Tri-color ink / bone / lime palette with dramatic dark surfaces. A printed publication that decided to ship as a website. Per-section mode switching (ink / paper / lime), rule-divided composition, mixed sans + serif italic display.

Services

We make things
that work.

See the work →

Palette

background#070708
foreground#e8e8e9
primary#d7df58
accentrgba(232,232,233,0.12)

Install the full kit

npx shadcn@latest add https://ui.comcreate.io/r/folio-init.json

Drops 4 doc/token files plus 7 starter components.

DESIGN.md

# Folio — Design Language

> Dark editorial agency. Tri-color ink / bone / lime with dramatic display type, rule-divided composition, and section-level mode switching.

## Identity

Folio is a printed publication that decided to ship as a website. Pages are dark by default — anchored in `#070708` ink with bone-white type. A single lime (`#d7df58`) carries every callout, every active state, every "look here" moment. Type is a deliberate mix of sans and serif italic in the same headline (setup → emphasis). Rules separate everything; whitespace is treated as content, not as absence.

The language has three modes — dark (default), light (paper), and lime — that switch at the section level, not the page level. A single page might alternate ink → paper → ink → lime → ink, with each section announcing its mood by changing the surface beneath it.

## Palette

### Mode tokens

| Token | Dark (default) | Light (`data-mode="light"`) | Lime (`data-mode="lime"`) |
|-------|----------------|-----------------------------|----------------------------|
| `--background` | `#070708` ink | `#ffffff` paper | `#d7df58` lime |
| `--foreground` | `#e8e8e9` bone | `#070708` ink | `#070708` ink |
| `--muted` | `rgba(232,232,233,0.5)` | `rgba(7,7,8,0.5)` | `rgba(7,7,8,0.6)` |
| `--muted-foreground` | `rgba(232,232,233,0.5)` | `rgba(7,7,8,0.5)` | `rgba(7,7,8,0.6)` |
| `--rule` | `rgba(232,232,233,0.12)` | `rgba(7,7,8,0.12)` | `rgba(7,7,8,0.18)` |
| `--chip` | `rgba(232,232,233,0.12)` | `rgba(7,7,8,0.12)` | `rgba(7,7,8,0.12)` |
| `--accent` | `#d7df58` lime | `#d7df58` lime | (not used) |
| `--primary` | `#e8e8e9` bone | `#070708` ink | `#070708` ink |

### Static brand tokens

| Token | Value | Role |
|-------|-------|------|
| `--color-folio-ink` | `#070708` | The deep |
| `--color-folio-bone` | `#e8e8e9` | The light |
| `--color-folio-paper` | `#ffffff` | The white |
| `--color-folio-lime` | `#d7df58` | The signal |

## Typography

Sans + serif blend. Two families used in tandem.

### Families

| Token | Family | Role |
|-------|--------|------|
| `--font-sans` | Inter Variable (Helvetica fallback) | Body, eyebrows, UI |
| `--font-serif` | Times / Georgia | Italic emphasis inside display headlines |

### Scale

| Tier | Size | Weight | Tracking | Line-height |
|------|------|--------|----------|-------------|
| Display | `clamp(48px, 8vw, 144px)` | 400 | `-0.02em` | `0.92` |
| H1 | `clamp(36px, 5vw, 80px)` | 400 | `-0.015em` | `1.0` |
| H2 | `clamp(28px, 3.5vw, 48px)` | 400 | `-0.01em` | `1.1` |
| H3 | `20px` | 400 | `0` | `1.2` |
| Body large | `18px` | 400 | `0` | `1.55` |
| Body | `16px` | 400 | `0` | `1.5` |
| Overline | `.t-overline` — `12px` / `tracking: 1.32px` / uppercase |
| Caption | `13px` | 400 | `0.01em` | `1.4` |

**Critical rule**: all weights are `400`. Visual hierarchy comes from size and rule placement, never from bold.

### Mixed-family display

The signature display pattern combines sans + serif italic in a single phrase:

```tsx
<h1 className="text-[clamp(48px,8vw,144px)] leading-[0.92] tracking-[-0.02em]">
  We make <em className="font-serif italic">things</em> that work.
</h1>
```

## Spacing & geometry

### Spacing scale

| Token | Value | Use |
|-------|-------|-----|
| `space-2` | `8px` | Inline gap |
| `space-4` | `16px` | Chip padding |
| `space-6` | `24px` | Container gutter (mobile) |
| `space-8` | `32px` | Module internal |
| `space-12` | `48px` | Container gutter (desktop) |
| `space-20` | `80px` | Section vertical (mobile) |
| `space-32` | `128px` | Section vertical (desktop) |

### Container

```html
<div class="mx-auto max-w-[1440px] px-6 md:px-12">
```

### Radius

`--radius: 0px` everywhere. The single exception is `.pill` (`999px`).

```css
.pill {
  display: inline-flex;
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 15px;
  letter-spacing: 0.2px;
  border: 1px solid var(--rule);
  background: var(--chip);
  color: var(--foreground);
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.pill:hover { background: var(--foreground); color: var(--background); border-color: var(--foreground); }
.pill--solid { background: var(--foreground); color: var(--background); border-color: transparent; }
.pill--xs { padding: 6px 12px; font-size: 11px; letter-spacing: 0.8px; text-transform: uppercase; }
```

### Rules

Section separators use 1px lines, never `border-t/border-b`:

```tsx
<div className="rule" />
{/* equivalent to <div className="h-px w-full bg-[color:var(--rule)]" /> */}
```

## Motion

| Pattern | Easing | Duration |
|---------|--------|----------|
| Letter reveal | `cubic-bezier(0.2, 0.7, 0.1, 1)` | 900ms |
| Word reveal | `cubic-bezier(0.2, 0.8, 0.2, 1)` | 650ms |
| Theme-section bg transition | `ease` | 350ms |
| Reveal-up | `ease` | 600ms |
| Pill hover | `ease` | 200ms |

### Keyframes (in tokens.css)

```css
@keyframes folio-letter-reveal {
  from { opacity: 0; transform: translateY(0.5em) rotate(1deg); }
  to   { opacity: 1; transform: translateY(0) rotate(0deg); }
}
```

Apply via `.letter.is-in` (toggled by IntersectionObserver).

## Voice & copy

- Editorial, declarative, sometimes sardonic. Sentence-case headlines.
- First-person plural: *"We make things that work."* / *"We're hiring."*
- Numbers under twenty are spelled out: *"Seven services."* / *"Twelve years in."*
- CTAs read like cross-references: *"See the work"*, *"Read the manifesto"*, *"Watch the reel"*.
- Never marketing-speak. No "transform", "revolutionize", "unlock".

## Component recipes

### Diptych services module
A two-column section: left = vertical service list, right = active service body copy + thumbnail. Switching active service is instantaneous.

### Work grid
Four-column grid of project cards. Cards have NO border, NO background fill — just an aspect-ratio image with a small caption underneath.

### Hero wordmark + tagline
Oversized sans/serif blended headline followed by a 1-sentence tagline at body size. Rule below. Eyebrow above.

### Theme alternation
The signature page rhythm: ink hero → paper services → ink work → lime CTA → ink footer. Each section transitions backgrounds with `.theme-section`'s 350ms ease.

## Anti-patterns

- ❌ Bold text. All weights are 400.
- ❌ `border-t` or `border-b` on sections. Use `<div class="rule" />`.
- ❌ Rounded corners on anything but `.pill`.
- ❌ Drop shadows or glows.
- ❌ Parallax or scale animations.
- ❌ Centered text on body copy (centered display is fine).
- ❌ Lime as a small accent dot. It is a full-section surface or it is absent.

## Accessibility

- Mode switches should respect `prefers-color-scheme`: lime mode is always opt-in.
- `prefers-reduced-motion`: disable letter-reveal and word-reveal animations; set `.is-in` immediately.
- `.t-overline` at 12px is the minimum legible size; never go smaller.
- Focus rings: `outline: 2px solid color-mix(in oklab, var(--foreground) 60%, transparent); outline-offset: 2px` (already wired).

## What ships with the pack

- `tokens.css` — `@theme inline` + scoped vars on `[data-designlang="folio"]` with mode variants (`data-mode="light"`, `data-mode="lime"`). Includes `.t-overline`, `.rule`, `.letter` keyframes.
- `CLAUDE.md` / `AGENTS.md` — agent guidance.
- Components (currently mapped from the originals folder; future passes will source directly from the design references): `services-diptych`, `work-grid`, `client-list`, `video-feature`, `purpose-statement`, `text-tout`.
- Foundations — `Button`, `Card`.

Components (6)