AI Design Arena
Drum
DESIGN.md
# Drum — Design System

## Concept

Most roastery sites are laid out. **Drum** is *assembled*. The argument it borrows
from Nintendo.com circa 2001 is that a web page can be a manufactured object —
not a document with regions, but a **faceplate**: injection-molded periwinkle
plates butted edge to edge, each one edge-lit on top and shadow-lined beneath,
with a near-black command layer bolted across it carrying the controls. Nothing
here floats. Every module has a physical edge, and you can see where the seams
are. The layout is a bill of materials.

The subject earns it. A roastery *is* a machine — a drum turning inside a heated
cylinder, a thermocouple, a batch clock, a fixed schedule. First Crack roasts on
Tuesdays and Thursdays and ships within 48 hours, and that is a machine's
timetable, not a mood. So the page is the roaster's own faceplate: brushed
periwinkle plates, silkscreened legends, a chrome-indigo bevel under every one,
and the drum itself leaning out of the masthead as a glossy Y2K product render.
**The machine is the mascot** — there is no character, no face, no anthropomorphic
device anywhere in the system.

And warmth is under law. In a building made of cool chrome, the only warm color
is the color of *action*: nav-gold for the words that take you somewhere, amber
for utility chips and classification marks, signal orange for every forward cue —
the round arrow badges, the chevron chips, the "Order beans" button. Warmth never
decorates. If something is orange and it does not advance you, it is a bug. That
single rationing rule is what keeps a dense, packed, ten-module page navigable:
your eye finds the warm pixels and they are always, only, where you can act.

## Palette

| Token             | Hex       | Role                                                                     |
| ----------------- | --------- | ------------------------------------------------------------------------ |
| `--canvas`        | `#7a8aba` | Periwinkle metallic. The body every plate is stamped from.               |
| `--periwinkle`    | `#8ba1d4` | One step brighter. Raised mid plates — system tiles, rail modules.       |
| `--canvas-soft`   | `#9fbee7` | Pale sky. Secondary nav strip; secondary text **on carbon** (8.10:1).    |
| `--platinum`      | `#dedede` | Platinum gray. Inset content surface — spec rows, form panels.           |
| `--surface`       | `#ffffff` | White. Content cards, readout fields, calendar, speech bubble.           |
| `--carbon`        | `#21242e` | Carbon navy. The command layer (nav, rail, footer) **and all dark ink**. |
| `--carbon-lift`   | `#2c3040` | Carbon, one step up. Hover fill on command-layer buttons only.           |
| `--chrome-indigo` | `#3d4f97` | The bevel shadow line under every plate. Text **only** on white/platinum.|
| `--chrome-light`  | `#a9b8dd` | The bevel highlight on every plate's top/left edge.                      |
| `--muted-indigo`  | `#60619c` | Dotted hairline dividers. Never text.                                    |
| `--floor`         | `#2b3352` | The dark indigo desk the 1000px machine sits on. Carries no text, ever.  |
| `--nav-gold`      | `#e48600` | Nav gold. **Primary nav words on carbon only** (5.68:1).                 |
| `--amber`         | `#ecab37` | Amber. Utility chips, info-box tabs, roast-level marks. A **fill**.      |
| `--signal`        | `#f68d1f` | Signal orange. Every forward cue. A **fill**.                            |
| `--signal-press`  | `#e07a12` | Signal, pressed.                                                         |
| `--tint-index`    | `#acace7` | Page tint — index hero field (lavender).                                 |
| `--tint-beans`    | `#c0d5e6` | Page tint — beans hero field (pale ice).                                 |
| `--tint-about`    | `#206479` | Page tint — about hero field (workshop teal).                            |

Rules:

- **The warmth-rationing law.** `--nav-gold`, `--amber`, and `--signal` are the
  only warm pixels in the building, and each has exactly one job: gold = the
  primary nav words; amber = utility chips, the info-box tab, roast-level marks,
  the footer shipping badge; signal = *forward motion only* (round arrow badges,
  chevron chips, the Order-beans button). **Cool chrome never carries action
  color, and warm color never decorates.** A tasting-note pill in amber, an
  orange rule under a heading, a gold hairline — all forbidden.
- **Even the page tints stay cool.** The three hero fields are the only sanctioned
  accents outside the warm trio, and all three are cool (lavender / ice / teal),
  so warmth remains unambiguously actionable. No fourth tint, and no warm tint.
- **The bevel colors are not text colors.** `--chrome-indigo` and `--chrome-light`
  exist to draw edges. See below for exactly where indigo may be read.

**AA findings (measured, not assumed).** The reference is a 2001 site and was not
accessible. Its own combinations fail in four places; all four are corrected here.

| Combination | Ratio | Verdict |
| --- | --- | --- |
| `--carbon` on `--canvas` #7a8aba | **4.55:1** | Legal — and the **only** legal ink on periwinkle. |
| `--carbon` on `--periwinkle` / `--canvas-soft` / `--platinum` / `--surface` / `--amber` / `--signal` | 6.01 / 8.10 / 11.51 / 15.48 / 7.70 / **6.45** | All legal. Carbon reads on everything. |
| `--chrome-indigo` on `--platinum` / `--surface` | 5.65 / 7.60 | Legal — the secondary ink, **insets only**. |
| `--canvas-soft` on `--carbon` · `--nav-gold` on `--carbon` | 8.10 / 5.68 | Legal — footer/collapsed-nav text; nav words. |
| `--carbon` on `--tint-index` / `--tint-beans` | 7.23 / 10.25 | Legal. |
| **White on `--signal`** (the reference's Submit) | **2.40:1** | **FAILS — corrected.** |
| `--chrome-indigo` on `--canvas` / `--periwinkle` | 2.23 / 2.95 | **FAILS.** Bevel color, not a text color. |
| `--nav-gold` / `--amber` as text on `--surface` | 2.72 / 2.01 | **FAILS.** Both are fills, never ink on white. |
| `--carbon` on `--tint-about` #206479 | 2.33:1 | **FAILS.** On teal, support text is white (6.64:1). |

The two corrections that change the build:

1. **Signal orange never carries white.** Every chevron, arrow glyph, and label on an
   orange fill is `--carbon` (6.45:1). This also fixes a *non-text* failure: an orange
   disc is 2.40:1 on white and 1.42:1 on periwinkle, far below the 3:1 boundary floor —
   so **every signal control carries a 1–2px `--carbon` ring.** The ring, not the fill,
   proves the shape's edge.
2. **The periwinkle canvas admits exactly one text color.** Even pure black tops out at
   6.17:1 on `#7a8aba`, so there is no headroom for a lighter secondary ink — carbon is
   the ceiling. Therefore **running body copy never sits directly on periwinkle.** The
   canvas carries carbon *labels and headings only*; every paragraph, spec value, and
   caption moves onto a `--platinum`, `--surface`, or `--canvas-soft` inset. Not a
   compromise — it is what the reference did with its platinum rows, now made law.

## Typography

Self-hosted woff2 under `assets/fonts/` via `@font-face`. No CDN, no Google Fonts
`<link>`. The reference used Arial/Helvetica with no webfont at all, so the
faithful move is an **Arial-metric open grotesque**, not a lookalike display face:

- **Liberation Sans** (OFL) 400 / 700 — chrome, body, labels, nav, buttons,
  numerals. Metric-compatible with Arial, so the reference's tight 11–14px
  silkscreen-label rhythm lands at the intended widths. (**Arimo** is a drop-in
  substitute if Liberation is unavailable; same metrics.)
- **Archivo Black** (OFL) 400 — the outlined display wordmarks *only*. It stands in
  for Arial Black, whose weight the box-art convention depends on.
- **Silkscreen** (OFL) 400 — the period bitmap voice, shipped but **tightly
  scoped**: stencil numerals on plate corner tabs (`01` `02` `03`) and the calendar
  month caption. Silkscreen only renders crisply on its native pixel grid, so it is
  set at **16px** and nowhere else — *not* at 10–11px, where it turns to mush. Every
  other micro-label is Liberation Sans 700 uppercase.

Type scale (desktop / mobile):

| Role            | Desktop        | Mobile        | Face                 |
| --------------- | -------------- | ------------- | -------------------- |
| Hero wordmark   | 52px / 1.0     | 34px / 1.02   | Archivo Black 400    |
| Plate wordmark  | 26px / 1.05    | 22px / 1.05   | Archivo Black 400    |
| Hero tagline    | 16px / 1.35    | 15px / 1.4    | Liberation Sans 700  |
| Nav link        | 13px / 1.0     | 15px / 1.0    | Liberation Sans 700  |
| UI label        | 11px / 1.15    | 11px / 1.15   | Liberation Sans 700  |
| Link / row title| 14px / 1.4     | 14px / 1.4    | Liberation Sans 700  |
| Body            | 14px / 1.55    | 14px / 1.55   | Liberation Sans 400  |
| Readout figure  | 15px / 1.2     | 15px / 1.2    | Liberation Sans 700  |
| Micro           | 11px / 1.35    | 11px / 1.35   | Liberation Sans 400  |
| Stencil         | 16px / 1.0     | 16px / 1.0    | Silkscreen 400       |

Letter-spacing: UI label and Nav link `+0.5px`; Hero/Plate wordmark `+0.01em`;
everything else `0`. Body, Link, and Micro **never** track.

Principles:

- **Uppercase + 0.5px tracking is the chrome voice.** Every structural label — nav
  words, `section-label-bar` titles, button text, spec keys, the roast-level mark —
  is uppercase Liberation Sans 700 at 11–13px with a half-pixel of tracking. It
  reads as a silkscreened legend printed on a controller shell. Sentence case
  appears *only* in body paragraphs.
- **The outlined-display law.** A hero or origin wordmark is **never** flat text.
  It is always:
  ```css
  .wordmark {
    font-family: "Archivo Black", sans-serif;
    text-transform: uppercase;
    color: #ffffff;
    -webkit-text-stroke: 5px var(--carbon);  /* 3px at Plate size */
    paint-order: stroke fill;                /* stroke behind fill — letterforms stay full */
    text-shadow: 3px 3px 0 var(--chrome-indigo);  /* hard offset, zero blur — 2px at Plate size */
  }
  ```
  `paint-order: stroke fill` is load-bearing; without it the stroke eats the counters
  and the wordmark closes up. The shadow is **hard** (0 blur). A wordmark without the
  outline and the hard offset has lost the box-art reference entirely.
- **Body stays small and quiet.** 14px / 400 / 1.55, bumped from the reference's
  12px because 12px running copy is not defensible — but *not* one pixel further.
  The hierarchy is carried by the labels and the photography, never by big body type.
- **Numerals are tabular.** `font-variant-numeric: tabular-nums` on every brew
  parameter, elevation, and calendar cell, so figures column-align in the readouts.

## Spacing & layout

- **Base unit 4px.** Tokens: `xxs` 2 · `xs` 4 · `sm` 8 · `md` 12 · `lg` 16 · `xl` 24 · `xxl` 32.
- **The fixed canvas.** A **1000px** machine, centered, sitting on the `--floor`
  (`#2b3352`) — the desk. 8px of machine padding; a 984px interior.
- **The split.** `grid-template-columns: 1fr 336px; gap: 12px;` → a **636px content
  column** beside a **336px right action rail**. Roughly 2/3 : 1/3, and the rail is
  part of the command layer, not part of the content.
- **Whitespace is an engineered seam, not breathing room.** Plates butt against each
  other separated by a **12px seam** and their own 1px bevel lines. Plate interior
  padding is **12px** (`md`); large content modules **16px** (`lg`). There is no
  section padding of 48px, 64px, or 80px anywhere in this system. **Do not air it
  out.** The density is the brand: a packed control panel where everything is one
  click away.
- **No narrow reading measure.** Body copy fills its module's width. Do not
  introduce a 640px prose column inside the 636px content column — that is a
  magazine move, and this is not a magazine.
- **Corners.** Default `0px` (sharp). `xs` 2px — chips, badges, readout fields.
  `sm` 4px — small plates, tiles, calendar, spec rows. `md` 6px — form panels.
  `lg` 10px — the speech bubble, and nothing else. `full` 9999px — **only** the
  logo racetrack pill, the calendar's roast-day dot, and the round arrow badges.
  The largest slabs (masthead chrome, footer) are **chamfered**, not rounded:
  ```css
  clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px),
                     calc(100% - 12px) 100%, 0 100%, 0 12px);
  ```
  `clip-path` destroys borders on the cut edges, so a chamfered slab is built as
  **two stacked clipped layers**: an outer `--chrome-indigo` div, and an inner
  `--carbon` div inset by 1px with the same clip. The bevel survives the cut.
- **Touch targets: 44×44px minimum**, no exceptions. The reference's 18–28px
  controls are enlarged: the nav bar goes 28px → **48px**, the subnav strip →
  **44px**, arrow badges → **44px discs**, and the 24px chevron chip is centered
  inside a 44px-tall clickable row. Static, non-interactive elements (calendar day
  cells, roast-day markers, spec readouts) are exempt because they are **not
  focusable and carry no click target** — they are printed, not pressed.

**Responsive strategy** — this is a pre-responsive design and it does **not** reflow
on its own. The collapse is authored:

| Width | Behavior |
| --- | --- |
| ≥1024px | Fixed 1000px machine on the floor. Dual nav. 3-up system tiles. |
| 720–1023px | Machine goes fluid: `width:100%`, 12px page margins. Grid → `1fr 300px`. Nav stays dual; the subnav strip scrolls horizontally. Tiles 3-up. |
| <720px | **Rail stacks beneath the content column.** Dual nav → **one 56px carbon bar**: wordmark + a 44×44 disclosure toggle opening a carbon panel that lists the primary nav words in `--nav-gold`, then a dotted divider, then the secondary strip links in `--canvas-soft` (8.10:1 on carbon). Tiles 1-up. Plates keep every bevel — the machine becomes a *stack* of plates, never a set of airy cards. |

## Bevel & depth

Depth is **physical bevel simulation**. There is no blurred drop-shadow anywhere in
this system. Four levels, all buildable:

**Level 0 — Inset** (recessed into the chrome). List rows, readout fields, the
canvas body itself. Dark edge on top/left, light edge on bottom/right — the
inverse of a plate.
```css
.inset {
  background: var(--platinum);
  border-top:  1px solid var(--chrome-indigo);
  border-left: 1px solid var(--chrome-indigo);
  border-right:  1px solid var(--chrome-light);
  border-bottom: 1px solid var(--chrome-light);
}
```

**Level 1 — Plate** (flush, the default). Content panels, system tiles, the info box.
```css
.plate {
  background: var(--canvas);          /* or --periwinkle for a raised mid plate */
  border-top:  1px solid var(--chrome-light);
  border-left: 1px solid var(--chrome-light);
  border-right:  1px solid var(--chrome-indigo);
  border-bottom: 1px solid var(--chrome-indigo);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.28);  /* hard edge-light: ZERO blur */
}
```
That `inset` is an **edge-light, not an elevation shadow** — blur radius is 0 and it
is inside the box. It is the only `box-shadow` permitted in the system.

**Level 2 — Raised chip** (a pressable control). Utility chips, arrow badges,
Order-beans. Bright top-left, a **doubled** dark bottom-right so it stands proud.
```css
.chip {
  border-top:  1px solid var(--chrome-light);
  border-left: 1px solid var(--chrome-light);
  border-right:  2px solid var(--chrome-indigo);
  border-bottom: 2px solid var(--chrome-indigo);
}
.chip:active {                        /* the bevel inverts — the chip goes down */
  border-width: 2px 1px 1px 2px;
  border-color: var(--chrome-indigo) var(--chrome-light) var(--chrome-light) var(--chrome-indigo);
  transform: translate(1px, 1px);
}
```

**Level 3 — Command slab** (above the chrome). Nav, right rail, footer. Carbon with
the halftone dot-matrix — a repeating radial-gradient reading as a recessed speaker
grille. **This is the only gradient in the system, and it is a texture, not a wash.**
```css
.slab {
  background-color: var(--carbon);
  background-image: radial-gradient(circle at 50% 50%,
    rgba(159,190,231,0.10) 0.5px, transparent 0.6px);
  background-size: 3px 3px;
  border-top:    1px solid #3a3f52;   /* faint top edge-light on the slab */
  border-bottom: 1px solid #000000;
}
```

## Signature

Two elements. Both are the reference's own signatures landing exactly on this
brief's content.

### 1. The roast-schedule calendar widget

The reference's News page carried a white month-calendar with highlighted event
dates. First Crack roasts **Tuesdays and Thursdays**. So the roast schedule is not
a sentence — **it is that calendar.**

A white `--surface` widget, radius `sm` (4px), Level-1 bevel, 8px padding, headed by
a **carbon caption bar** (28px, halftone, chamfered top corners) carrying the month
in **Silkscreen 16px** `--canvas-soft` and the year in Liberation Sans 700 11px.
Below it a 7-column grid, Monday-first:

- Weekday header row: `--platinum` inset, `MO TU WE TH FR SA SU` in UI label
  (11px / 700 / +0.5px) `--carbon`.
- Day cells: 34px tall, white, **11px tabular numerals** in `--carbon` (15.48:1),
  hairline-separated by 1px `--platinum` rules. Cells are **static text, not
  buttons** — no focus, no click, so the 44px floor does not apply.
- **Roast days** — every cell in the Tuesday and Thursday columns — are stamped with
  a `--signal` marker: a filled square, radius `xs` (2px), **with a 1px `--carbon`
  ring** (orange on white is only 2.40:1 and cannot prove its own edge), with the
  numeral in `--carbon` on top (6.45:1).

The payoff is that the markers form **two clean orange stripes running straight down
columns 2 and 4** — the schedule made visible as a machine's duty cycle, which is
the entire point. Render a real month with arithmetically correct leading blanks; if
the build hard-codes one, its blanks must be right for that month.

Beneath the grid: a dotted divider, then a legend row — an 11px signal swatch (carbon
ring) + `ROAST DAY` in UI label — and one line of body copy: *"Orders ship within 48
hours of roast."* The widget's full form lives in the **about** page's roast-schedule
section; a compact single-week strip variant (one row, seven cells) may ride the
**index** right rail.

### 2. The masthead cutout + speech bubble

The reference broke its own rectangular grid with a transparent character cutout
paired with a white speech bubble. Drum keeps the **structure** and drops the
character.

The masthead is a 148px `--canvas` plate, chamfered top-left, spanning the full 984px
interior. Out of it leans **`masthead-roaster`** — a transparent-PNG, Y2K-glossy
product render of the **drum roaster itself**: red-enamel body, chrome drum face,
airbrushed specular highlights, a hard (unblurred) cast shadow baked into the cutout.
It is positioned to break the masthead's bottom edge and **overlap the carbon nav
slab below by ~24px** (`position: relative; z-index: 3; margin-bottom: -24px;`) — a
manufactured object sitting *on top of* the chrome, not inside a box.

Beside it, a white `--surface` speech bubble at radius `lg` (10px) — the one place
10px radius is spent — with a 1px `--carbon` border and a CSS tail (a `::after`
triangle, carbon-outlined), carrying **"Roasting Tuesdays & Thursdays."** in Link
(14px / 700) `--carbon`.

**There is no mascot.** No eyes, no face, no limbs, no anthropomorphic device
anywhere in this design. **The machine is the mascot** — that is the whole concept,
and a friendly bean with a face would destroy it in one image. If the render acquires
a face, regenerate it.

To the masthead's right: the outlined **FIRST CRACK COFFEE ROASTERS** wordmark (Hero
wordmark, per the outlined-display law) over a `--platinum` inset strip reading
`PORTLAND, OREGON · EST. 2019` in UI label `--carbon`.

## Components

- **`nav-primary`** — Level-3 carbon slab, **48px** tall, sharp. Left: the
  `logo-pill` — a white `full`-radius racetrack pill, 1px carbon ring, "FIRST CRACK"
  in Archivo Black 13px `--carbon`. Center: **HOME / BEANS / ABOUT** in Nav link
  (13px / 700 / +0.5px) uppercase `--nav-gold` (5.68:1), each in a 44px-tall hit area
  with 14px side padding. Right: two `--amber` utility chips (Level 2, radius `xs`,
  carbon text, 44px tall) — **BREW GUIDE** → `beans.html#brew`, **CUPPING** →
  `about.html#cupping`. Active page: the word turns `--surface` white and its cell
  takes a 3px `--amber` bottom rule + `aria-current="page"`. Active state is a *mark*
  (amber), never a *forward cue* (signal).
- **`nav-secondary`** — the pale-sky strip directly beneath, `--canvas-soft`, 44px,
  sharp, Level-0 inset. Carbon UI-label links (8.10:1): `SOURCING · PROCESS ·
  ORIGINS · BREW GUIDE · VISIT · CUPPING · SHIPPING`, separated by 1px
  `--chrome-indigo` vertical rules. **Never merge this into the primary bar** — the
  gold-over-pale two-tier command hierarchy is signature.
- **`section-label-bar`** — the silkscreened legend voice; the header of *every*
  module. `--canvas` strip, 32px, sharp, Level-1 bevel, 8px padding: a CSS-drawn
  10×10px carbon 2×2 grid glyph, then an uppercase UI-label title in `--carbon` —
  `SOURCING`, `THE ROAST`, `ORIGINS`, `POUR-OVER`, `ESPRESSO`, `VISIT`,
  `ROAST SCHEDULE`.
- **`system-tile`** — the three origins as console tiles. `--periwinkle` Level-1
  plate, radius `sm`, 8px padding. Top to bottom: a carbon corner tab with the
  **stencil number** (`01`/`02`/`03`, Silkscreen 16px `--canvas-soft`); a 4:3 image
  framed 1px `--chrome-indigo`; the **origin wordmark** in Archivo Black 26px,
  outlined per the display law, over the image's lower-left; an `--amber` roast-level
  mark (radius `xs`, carbon UI-label — `LIGHT` / `MEDIUM` / `DARK`); a `--platinum`
  inset spec strip (`WASHED · 1,950 M`); a 44px `button-icon-arrow` bottom-right.
  3-up on index, 1-up below 720px. On **beans** it expands to a full-width variant:
  image left (280px), specs + tasting notes right in a white inset.
- **`spec-row`** — the reference's news row, repurposed. `--platinum` Level-0 inset,
  radius `sm`, 10px padding, **min-height 44px**. A 12px carbon square glyph, a
  Link-size title in `--chrome-indigo` (5.65:1 on platinum — the one place indigo is
  readable), a trailing `button-arrow-chip`. Carries the index's four process steps
  (`GREEN INTAKE`, `CHARGE`, `FIRST CRACK`, `DROP & COOL`) and its origin list.
- **`form-panel`** — the brew guide. `--platinum` panel, radius `md` (6px), 16px
  padding, capped by a `section-label-bar`. Two side by side on **beans**
  (`POUR-OVER` / `ESPRESSO`), stacking below 720px. Each parameter is a `field-label`
  (Link 14px / 700 `--carbon`) left, and a **readout field** right: white Level-0
  inset, radius `xs`, value in Readout figure with tabular numerals. It is a `<dl>`,
  **not a form control** — it looks like an instrument readout and carries no input
  semantics.
  - Pour-over: `DOSE 15 g` · `WATER 250 g` · `TEMP 94 °C` · `GRIND medium-fine` ·
    `TIME 3:00` · `RATIO 1:16.7`
  - Espresso: `DOSE 18 g in` · `YIELD 36 g out` · `TIME 28 s` · `TEMP 93 °C` ·
    `RATIO 1:2`
- **`info-box`** — the Saturday cupping explainer. White `--surface` card, radius
  `sm`, 1px `--carbon` border, 12px padding, with an **amber header tab** straddling
  its top edge (radius `xs`, carbon UI-label, 7.70:1): `WHAT IS — SATURDAY CUPPING`.
  Body 14px `--carbon`: every Saturday at 10:00, free, no reservation. Lives in the
  **about** rail; may copy into the **index** rail.
- **`rail-button`** — the rail is command layer, so its buttons are Level-3 carbon
  slabs: full-width (336px), 44px, sharp, white UI-label, a CSS-drawn 12px leading
  glyph. Set: `OUR ORIGINS`, `BREW GUIDE`, `VISIT THE ROASTERY`. **The exception is
  the law working:** **`ORDER BEANS`** is the site's one true action, so it is not a
  carbon slab — it is a **`--signal` fill with `--carbon` text** (6.45:1), Level-2
  bevel, radius `xs`, 48px, always first in the rail on every page. → `beans.html`.
- **`button-icon-arrow`** — a **44px** `--signal` `full`-radius disc, **2px `--carbon`
  ring**, carbon chevron (inline SVG path, never a glyph font). The ring carries the
  shape's edge; the fill alone cannot (1.42:1 on periwinkle).
- **`button-arrow-chip`** — a 24px `--signal` chip, radius `xs`, 1px carbon ring,
  carbon chevron, centered in a 44px-tall clickable `spec-row`.
- **`dotted-divider`** — `border-top: 1px dotted var(--muted-indigo);` **Dotted, never
  solid** — a recurring Y2K-chrome tell. Separates sub-sections inside form panels,
  rail modules, and the calendar legend.
- **`cta-band`** (index) — a full-984px chamfered plate on the `--tint-index` field: a
  roaster render right, an outlined Plate wordmark (`SHIPPED WITHIN 48 HOURS`), one
  Hero-tagline line, and the `ORDER BEANS` signal button. The one place the content
  column and the rail merge.
- **`footer`** — a **chamfered** Level-3 carbon slab (two-layer clip), halftone, 24px
  padding. `--canvas-soft` Micro text (8.10:1): `FIRST CRACK COFFEE ROASTERS · 412
  FOUNDRY LANE, PORTLAND, OREGON · EST. 2019`; cafe hours (`WED–SUN · 8:00–15:00`);
  roast days. Links `--canvas-soft` with a 1px dotted underline. One `--amber` badge,
  radius `xs`, carbon UI-label: `SHIPS WITHIN 48 HOURS OF ROAST`.

## Motion

The machine responds instantly or not at all. There is no easing curve in this system
and nothing eases in on scroll.

- **The bevel press is the entire motion language.** On `:active`, a Level-2 chip
  inverts its bevel (dark to top-left, light to bottom-right) and shifts
  `transform: translate(1px, 1px)`. The bevel swap is **not transitioned** — a
  physical button does not tween.
- **Hover** is a fill change only, 90ms linear: `--nav-gold` words brighten to
  `--amber`; carbon `rail-button` fills lift to `--carbon-lift` (white text holds at
  13.09:1); `--signal` fills deepen to `--signal-press` (carbon text holds at 5.13:1).
- **Focus** is a 2px `--carbon` outline with a 2px offset — carbon reads on every
  surface in the system (≥4.55:1 on the lightest, the periwinkle canvas).
- No parallax, no scroll-jacking, no fade-up reveals, no loops, no transitions on
  layout properties.
- Under `prefers-reduced-motion: reduce`, drop the 1px `translate` on press. **Keep
  the bevel inversion and the fill change** — those are *state*, not motion, and
  removing them would remove the press feedback entirely.

## Image treatment

Two registers, and nothing in between.

**Cutout renders** — transparent PNG, **Y2K glossy**: saturated red-enamel and chrome
surfaces, airbrushed specular highlights and a bright hotspot, a **hard-edged (never
blurred) cast shadow** baked into the cutout, three-quarter product-catalog angle.
These break their plate's edge and overlap the chrome. They are objects, not scenery.

**Field plates** — full-bleed photography clipped to a beveled rectangle over a page
tint, always on a **mechanical or textured backdrop**: perforated steel, a shallow
grid, burlap weave, roasted-bean gravel. Every framed image takes a **1px
`--chrome-indigo` edge**. High key, high saturation, hard light.

Never: soft-focus lifestyle warmth, latte art, people, hands cradling a mug, moody
low-key film grain, or a blurred bokeh backdrop. The register is a product catalog
and a machine spec sheet, not a cafe.

**The warmth law governs chrome, not photography.** The roaster is red enamel, the
beans are brown, the flame is orange — images carry all the warmth they want, because
an image is content sitting *inside* a beveled frame, not a UI surface. Do **not**
desaturate the photography trying to obey the palette. The law is only ever violated
by a *styled element* — a fill, a border, a rule, a type color — that is warm without
being actionable. An image is never in scope; a `<div>` always is.

Needed images (referenced `./assets/<id>.png`):

- `masthead-roaster` — **transparent cutout.** A red-enamel drum roaster, three-quarter
  view, chrome drum face and a glass bean-viewing port, airbrushed highlights, hard
  cast shadow, Y2K product-render gloss. **No face, no eyes, no character.** The
  hero object of the whole design.
- `index-hero` — field plate. Roasted beans cascading out of the drum's chute onto a
  perforated-steel tray, hard light, saturated, on a lavender-washed field.
- `index-sourcing` — field plate. Raw green coffee in a burlap sack, cut open, on a
  workshop bench — the sourcing statement.
- `index-process` — field plate. The roaster's control face: gauges, the batch
  thermometer, the drum door — shot square-on like a faceplate.
- `origin-yirgacheffe` — 4:3 tile field. Light-roast pale beans on a bright textured
  backdrop; jasmine, bergamot, dried apricot; a washed-process, high-altitude read.
- `origin-san-agustin` — 4:3 tile field. Medium-roast beans, caramel-brown, warmer
  backdrop; caramel, red plum, cocoa nib.
- `origin-kerinci` — 4:3 tile field. Dark-roast oily beans, deep and glossy, cedar and
  dark-chocolate register, wet-hulled Sumatran backdrop.
- `beans-brew` — field plate. A pour-over cone and a portafilter side by side on steel,
  hard-lit like equipment in a catalog — sits beside the two `form-panel`s.
- `about-space` — field plate. The 412 Foundry Lane roastery interior: machinery,
  bench, sacks, industrial and people-free, bright and square-on.
- `about-cupping` — field plate. The Saturday cupping table shot from directly above:
  bowls and spoons in a rigid grid, laid out like an instrument tray.

## Do / Don't

Do:

- Build **every** region as a beveled plate: `--canvas` body, `--chrome-light` top/left
  edge, `--chrome-indigo` bottom/right shadow line. The page is assembled, not laid out.
- Keep warmth as **wayfinding only** — gold for nav words, amber for utility chips and
  marks, signal for every forward cue. If it is warm, it means "act here."
- Set every structural label in **uppercase Liberation Sans 700 at 11–13px with +0.5px
  tracking**. It is the silkscreened legend voice of the whole machine.
- Render every hero and origin wordmark **outlined + hard-shadowed** Archivo Black with
  `paint-order: stroke fill`.
- Use `--carbon` + halftone for the **command layer** (nav, rail, footer) so system
  controls are visibly a different material from content.
- Let plates **butt together** on 12px seams. Density is the intended texture.
- Default corners to **sharp or chamfered**; spend roundness only on the logo pill, the
  round arrow badges, and the calendar's roast dot.
- Put every `--signal` control inside a **1–2px carbon ring** — the fill cannot prove
  its own edge.

Don't:

- **Don't round every corner into a uniform card system.** If a plate that is not the
  logo pill, an arrow badge, or the speech bubble has a radius above 6px, the design is
  wrong — uniform rounding erases the manufactured-faceplate identity.
- **Don't introduce a soft blurred drop-shadow.** The only legal `box-shadow` is the
  zero-blur `inset 0 1px 0 rgba(255,255,255,0.28)` edge-light. Any shadow with a blur
  radius > 0 is a bug. Depth is hard bevels and pictorial photography.
- **Don't let `--signal` or `--amber` decorate.** No orange rules, no amber tasting-note
  pills, no gold hairlines, no warm background washes. Warm color always means "act
  here." If a warm element is not clickable and is not a classification mark, delete it.
- **Don't add accent colors outside the three page-tint hero fields.** The steady-state
  chrome is strictly cool periwinkle + carbon. No coffee-brown, no cream, no fourth tint.
- **Don't air out the layout.** No section padding above 16px, no prose column narrower
  than its module, no 64px whitespace. The packed, near-fixed density is the brand.
- **Don't flatten the dual nav** into one bar — the gold primary words over the pale
  secondary strip are the command hierarchy, and it only collapses below 720px, into a
  disclosure toggle, on purpose.
- **Don't render a wordmark as flat text.** Without the `-webkit-text-stroke` outline
  and the hard offset `text-shadow`, it is not a box-art wordmark, it is a heading.
- **Don't put white text on `--signal`** (2.40:1), gold or amber text on white
  (2.72:1 / 2.01:1), `--chrome-indigo` text on any periwinkle surface (2.23:1), or body
  copy directly on the periwinkle canvas. Every one of those fails AA.
- **Don't add a mascot, a face, or an anthropomorphic bean.** The machine is the mascot.
- No emoji. No icon fonts. No decorative icon doing a label's job.