# fernworks.dev design language

**Direction: Understory & Paper.** greenline's substance is sediment: durable plain
files a stranger picks up cold. The site is built the same way: documents on paper,
not cards on glass. Opaque surfaces, one hairline, one tinted forest shadow. Mono is
the voice of anything that lives in a file; Geist carries the prose. The Barnsley
fern is the identity and the argument (each frond is the whole fern one iteration
down, which is the product's own recursion). The governing test is the product's
house rule applied to the house: a visitor who lands cold and scrolls once has been
handed the work.

This file is the single source of truth for the design system. The build fails when
`site.css` declares a token this file does not list, or this file names a token the
CSS does not declare. It also fails on raw px in spacing/type/radius declarations
outside the token blocks, on hex colors outside the token blocks, on `style=`
attributes in templates, on em dashes in emitted HTML, on divergence between the two
dark-theme token blocks, and on any contrast pair below its floor.

## Laws

1. One elevated surface class per section; everything else sits flat on `--bg` and
   is grouped by space, not lines.
2. Never omit a timing function; never encode a duration in frames.
3. Sentence case everywhere. No uppercase transforms, no letter-spaced caps.
4. At most one middle dot per prose line.
5. Em dashes never appear in site copy.
6. Hover motion is gated behind `(hover: hover)`; reduced motion keeps fades and
   kills movement.
7. Every pressable has a visible rest state, a focus ring, and press feedback.
8. The fern is the site's only decoration, and it appears once per page at most.

## Color

Both themes define the same token set; the dark set is declared twice (media query
and explicit `data-theme`) and the build asserts the two copies are identical.

| Token            | Light                | Dark                  | Role                               |
| ---------------- | -------------------- | --------------------- | ---------------------------------- |
| `--bg`           | #e9efe7              | #0a0f0c               | page ground                        |
| `--s1`           | #fdfefc              | #101711               | paper surface                      |
| `--s2`           | #f2f6f0              | #151d16               | recessed surface (callouts, code)  |
| `--ink-1`        | #131f18              | #f2f6f2               | headings (14.5:1 / 17.7:1 on bg)   |
| `--ink-2`        | #2a382f              | #ccd7ce               | body (10.5:1 / 13:1)               |
| `--ink-3`        | #4c5c52              | #a6b8ab               | support (6.1:1 / 9.3:1)            |
| `--ink-4`        | #5d6d64              | #93a398               | captions; floor 4.5:1 on bg and s1 |
| `--line`         | #c9d3c5              | rgba(255,255,255,.11) | hairline                           |
| `--line-2`       | #78877d              | rgba(255,255,255,.34) | control border; floor 3:1 on bg    |
| `--accent`       | #0f7a43              | #46d389               | links, actions; floor 4.5:1 on bg  |
| `--accent-deep`  | #0a3d24              | #0f7a43               | deep accent (fern trunk, fills)    |
| `--accent-press` | #0b6236              | #5fe39b               | pressed/hover accent               |
| `--accent-tint`  | rgba(15,122,67,.09)  | rgba(70,211,137,.12)  | accent wash                        |
| `--danger`       | #a3231c              | #f0857b               | errors; floor 4.5:1 on bg          |
| `--danger-tint`  | rgba(163,35,28,.09)  | rgba(240,133,123,.13) | error wash                         |
| `--amber`        | #8a5a10              | #e0a94f               | warnings; floor 4.5:1 on bg        |
| `--amber-tint`   | rgba(176,122,32,.12) | rgba(224,169,79,.14)  | warning wash                       |
| `--fern-deep`    | #06301c              | #0d3a23               | fern color ramp, trunk end         |
| `--fern-tip`     | #0f7a43              | #46d389               | fern color ramp, tip end           |
| `--fern-op`      | .85                  | .6                    | fern canvas opacity                |
| `--grain-op`     | .05                  | .08                   | grain overlay opacity              |
| `--e1`           | tinted 1px shadow    | deep 1px shadow       | resting paper elevation            |
| `--e2`           | tinted lift          | deep lift             | hover/raised elevation             |

## Space

4pt scale, nine steps, the only spacing values on the site: `--sp-1` 4px,
`--sp-2` 8px, `--sp-3` 12px, `--sp-4` 16px, `--sp-5` 24px, `--sp-6` 32px,
`--sp-7` 48px, `--sp-8` 64px, `--sp-9` 96px. The single free value is
`--hero-pad`, clamp(48px, 14vh, 128px), the stage's top breathing room.

## Type

Geist and Geist Mono, self-hosted variable siblings, with metric-matched local
fallbacks (`GeistFB`) declared across the full weight range so headings never
repaint at a wrong weight. Weights: 400, 500, 600 only.

Sizes, seven steps plus display: `--fs-0` 12px, `--fs-1` 13px, `--fs-2` 15px,
`--fs-3` 17px, `--fs-4` 21px, `--fs-5` 28px, `--fs-d` clamp(34px, 4.6vw, 52px).
Families: `--font-sans`, `--font-mono`. Body line-height 1.55; mono 1.6; headings
1.1 to 1.3. Prose measure is capped at 68ch.

## Radius

Radius tracks the size of the thing: `--r-1` 6px (inline code, chips), `--r-2`
10px (controls, code blocks), `--r-3` 14px (paper sheets), `--r-pill` 999px.
Nested corners are concentric: inner radius ≈ outer minus padding.

## Motion

Five curves, one hand (`easing.dev` derived; the house curve kept):

- `--e-enter` cubic-bezier(.2,.7,.3,1): anything arriving or growing
- `--e-exit` cubic-bezier(.55,.055,.675,.19): anything leaving, at ~0.7× its enter
- `--e-move` cubic-bezier(.645,.045,.355,1): both ends anchored (color, position)
- `--e-far` cubic-bezier(.19,1,.22,1): travel over a third of the viewport
- `--e-pop` cubic-bezier(.175,.885,.32,1.1): the one overshoot, the copy checkmark

Durations: `--t-0` 80ms (press), `--t-1` 120ms (color), `--t-2` 180ms (small
movement), `--t-3` 300ms (reveals), `--t-4` 520ms (theme flip). The fern grows in
900ms, time-based, ease-out.

## Layout

One rail: `--rail` 880px with `--gutter` 24px, shared by the topbar and every
page column. Docs widen to `--rail-wide` 1240px at the 1180px breakpoint only.
`--topbar-h` 56px. Breakpoints: 640, 860, 1180. Z scale: `--z-raised` 1,
`--z-nav` 30, `--z-grain` 40.

## Voice

Copy is specific and honest; misses are recorded next to hits. Labels are
sentence case. Invented vocabulary (frontier, harvest, tracer-bullet) gets a
dotted-underline definition link on first use.
