# Design

Visual system for the KILN website.

## Concept

**The firing.**

A kiln is a dark chamber where raw material is transformed by heat into
something that permanently holds its shape. That is the product, so it is also
the design: **drenched graphite surfaces with the light coming from inside.**

Every competitor in online education is somewhere in the bright blue-to-cyan
band, or in the warm-neutral "tasteful" band. This is neither. It is nearly
black with a single hot accent, and the warmth is *industrial* — fired clay and
ember, not comfort.

## Color

`oklch()` was used to reason about the ramp; hex is authoritative in the
stylesheet because the translucent overlays need `rgba()` for compatibility.

| Token | Hex | Role |
|---|---|---|
| `--char` | `#16120F` | Drenched surfaces, hero, footer, nav |
| `--graphite` | `#241D19` | Body ink on light, dark section fills |
| `--ash` | `#3D332C` | Borders on dark |
| `--clay` | `#B07A5A` | Tertiary, rules, non-text marks |
| `--ember` | `#E0592B` | Primary accent, focus ring, meters |
| `--flame` | `#F59A3C` | **The light.** CTA fills, highlights on dark |
| `--sand` | `#D8B99C` | Muted accent on dark |
| `--wash` | `#F0EAE1` | Alternating light sections |
| `--bone` | `#F8F5F0` | Default light background |

**Strategy: Committed → Drenched.** Roughly 45% of scroll depth is drenched
`--char`/`--graphite`. Light sections are warm off-white, because clay is warm —
this is the one place a warm neutral is load-bearing rather than decorative.

### Contrast (computed, not assumed)

Every pair below was measured with a WCAG 2.2 relative-luminance script before
the token was allowed into the stylesheet.

| Pair | Ratio | Verdict |
|---|---|---|
| `--graphite` on `--bone` | 15.27:1 | AAA — default body |
| `--graphite` on `--wash` | 13.88:1 | AAA — body on washed sections |
| `#5C4F45` on `--bone` | 7.26:1 | AAA — muted body |
| `#75665A` on `--bone` | 5.08:1 | AA — faint labels |
| white on `--char` | 18.62:1 | AAA |
| `#C9BDB2` on `--char` | 10.12:1 | AAA — muted body on dark |
| `--sand` on `--char` | 10.06:1 | AAA — accent on dark |
| `--char` on `--flame` | 8.49:1 | AAA — **the primary CTA** |
| `--ember` on `--char` | 5.00:1 | AA — accents on drenched |
| `--ember` on `--bone` | 3.43:1 | AA-large — focus ring only, never text |

**Hard rule:** `--flame` and `--ember` are never body text on a light
background. They measure 2.02:1 and 3.43:1 there. They are fills and marks.

`--ember` is the focus ring precisely because it is the one accent that clears
3:1 against *both* `--bone` and `--char`, so a single focus token works
everywhere.

## Typography

Two families on a contrast axis, neither of them a reflex pick.

- **Display — Fraunces, weight 800, `opsz` pinned high, `SOFT` 18, `WONK` 1.**

  All three axis settings are load-bearing. `opsz` drives stroke contrast, so
  pinning it keeps a hero headline and a card heading in the same voice instead
  of letting the small sizes render as a flat text cut. `SOFT` takes the
  machined edge off the terminals — the brand is fired clay, not milled steel.
  `WONK` is what stops it reading as a stock serif; switching it off collapses
  the face into something much more anonymous.

  *(Deliberately not Playfair or Bodoni — the two default "editorial serif"
  picks, and both far colder than this brand wants.)*

- **UI / body — Archivo.** A grotesque drawn for high-performance and signage
  use, which gives it a slightly industrial cast at body sizes and keeps it
  legible in dense admin tables. Carries body copy, navigation, labels and forms.

### Scale

Fluid `clamp()`, ratio ≥1.25.

| Step | Size | Use |
|---|---|---|
| `--fs-display` | `clamp(2.6rem, 6.4vw, 5.25rem)` | Hero h1 |
| `--fs-h1` | `clamp(2.1rem, 4.2vw, 3.4rem)` | Section openers |
| `--fs-h2` | `clamp(1.7rem, 2.9vw, 2.4rem)` | Sub-sections |
| `--fs-h3` | `clamp(1.2rem, 1.9vw, 1.45rem)` | Card titles |
| `--fs-body` | `clamp(1rem, 1.1vw, 1.125rem)` | Body |
| `--fs-sm` | `0.9375rem` | Secondary |
| `--fs-label` | `0.75rem` | Labels, tracked `0.14em` |

Display letter-spacing `-0.02em`. Measure capped at 62ch. `text-wrap: balance`
on h1–h3, `pretty` on prose.

## The mark

A **firing gate**: a stepped, corbelled kiln opening wrapped around a
four-stage heat ramp. The ascending treads encode Know → Iterate → Launch →
Nail while reading at a glance as heat building inside a chamber.

Built on a 96×96 grid; 8–16 unit masses form the gate, four equal 10-unit
treads rise in 8-unit increments. The aperture is open, so the mark takes on
whatever it sits on. The wordmark is drawn as paths on a 56-unit cap height —
10-unit stems, flat terminals, condensed proportions, a deliberately high K
waist — so it renders identically without a font dependency.

Files in `assets/img/`: `logo-lockup.svg`, `logo-glyph.svg`, `logo-stacked.svg`,
`favicon.svg`. Full rationale in `assets/img/RATIONALE.md`.

## Imagery

Full-bleed bands rather than boxed columns — this is the site's main structural
device.

**Every image is mapped through one heat ramp**, an interpolation from `--char`
through ember and flame to a white-hot `#FFE7C9`. That single shared mapping is
what makes procedurally generated compositions and photographs read as one
owned image system.

| Asset | Subject | Origin |
|---|---|---|
| `hero-chamber.jpg` | Nested arch courses receding to the fire | Generated |
| `band-strata.jpg` | Fired clay layers in section, ember seams | Generated |
| `band-aperture.jpg` | A single firing port, straight on | Generated |
| `c-cohort.jpg` | A kiln shelf, twelve slots at different heats | Generated |
| `instructor.jpg` | A faceted clay bust on a plinth | Generated |
| `desk-night.jpg`, `c-planning.jpg`, `c-laptop.jpg` | Workspaces | Photographic, re-toned |

The generated pieces are built by a Python/Pillow script: an emission field in
`[0,1]` assembled from blurred geometry, radial falloffs and particulate, then
pushed through the ramp with film grain and a vignette. Grain is not optional —
without it the compositions read as flat CGI.

**The instructor portrait is a sculpture, not a person.** The slot needs a
portrait and the brand has no photograph to put in it, so it gets a faceted
clay bust on a plinth: three-quarter turn, planes clipped to a silhouette,
lit from the upper left. Dead-on symmetry was tried first and read as a
mannequin; the turn is what makes it read as a carved object.

**Scrims are functional, not decorative.** A flat or directional overlay exists
so text clears contrast — nothing more.

## Motion

Heat: it rises slowly and never bounces.

- `--ease-flow: cubic-bezier(0.16, 1, 0.3, 1)` (ease-out-expo) for entrances
- `--ease-soft: cubic-bezier(0.33, 1, 0.68, 1)` for hovers and state
- Durations 180ms (state) / 420ms (entrance)
- Embers rise from the foot of the hero on 11–23s loops, staggered by negative delay so the field is already populated on first paint
- The method's temperature ramp draws in on scroll, once
- Reveals enhance an already-visible default — content is never gated behind a transition that may not fire

`prefers-reduced-motion: reduce` removes the ember layer entirely and collapses
everything else to opacity-only or instant. The static composition must still
look deliberate.

## Components

- **Buttons.** Primary is `--flame` fill with `--char` text (8.49:1) — the light from inside. Secondary is a hairline outline. Radius 2px throughout. Nothing is a pill.
- **Step nodes are bricks**, not circles: 96×76 at 2px radius, because the nodes are courses in a wall.
- **Course cards** carry a free/paid state as *text plus shape plus* colour (▲ / △), never colour alone.
- **Module rows** are rows, not cards — a curriculum is a list, and a list should look like one.
- **Forms** get 44px minimum targets, visible `:focus-visible` at ≥3:1, and placeholder text at full body contrast.

## Layout

- Content max-width 1240px; prose max-width 62ch
- Fluid section rhythm via `clamp()`, varied deliberately — drenched sections breathe wider than light ones
- Grids use `repeat(auto-fit, minmax(…, 1fr))` for breakpoint-free reflow
- Semantic z-index scale: `--z-sticky: 100`, `--z-backdrop: 200`, `--z-modal: 300`, `--z-toast: 400`. No arbitrary 9999.

## Bans specific to this project

- No pill badges, no gradient text, no glassmorphism, no side-stripe borders
- No circles where a rectangle would do — the brand is masonry
- No tiny uppercase tracked eyebrow above every section — the brand has *one* named kicker system (the K/I/L/N letters), used four times on purpose, nowhere else
- No cool neutrals, and no warm neutrals used as mood rather than meaning
- No stock photography of people
