# Coach Kelvin brand kit: The Lit Door

> He is the door held open. Every surface is the dark outside, and everything he shows you stands in
> the light coming through.

Finished 19 September 2026 from the direction Kelvin chose on 14 September: B's dark, C's door,
pictures that pop, the checkboxes, yellow and violet both, a real photographed door. Shown in full at
`https://kelvinarnott.unforged.me/look/brand/`, the landing page mock at `/look/brand/page/`.

## For the challenge page: how to take the design

1. Add the kit as a dependency of the new Astro project:
   `"@coachkelvin/brand": "file:../06_DESIGN/brand"` (path relative to your project), then
   `npm install`. It brings the two font packages with it.
2. Import once, in the layout: `import "@coachkelvin/brand/brand.css";`
3. Use the CSS variables and classes below. Never type a hex or a font name. If something is
   missing, add it to `06_DESIGN/brand/tokens.json` and regenerate with
   `node scripts/brand-tokens.mjs` in `06_DESIGN`, which re-measures every contrast pair.
4. Start from the mock: `06_DESIGN/src/pages/brand/page.astro` is the page designed in this system,
   section by section. Copy its structure, not its preview banner or its fake form handler.
5. Images: copy what you use from `06_DESIGN/public/img/brand/` into your own `public/`. Names below.

### What the mock already settles, and what it leaves to you

Settled in the mock, after three review rounds: copy and button before the photo on a phone, the
process line ("Apply here. A short call with me to see if it fits. Then you're in."), a button after
every block, the story straight after the hero, basics before levels, the FAQ above the form, a form
that asks for a first name, a WhatsApp number, "Are you training already?" and an optional handle,
the second route "Or message me the word IN on Instagram", OG tags with an absolute image.

Yours, because they need the real build or an answer from Kelvin: the form's endpoint and his
Supabase project, the reminders to the number, the start date and "doors shut" wording (the content
plan owns both) and what happens after day 30. **Settled on 19 September by Andreas: the free 30
days include the full coaching programme**, his training and food plan from day one included. The
mock says so in its "What's in the 30 days" block; public copy does not list the calls in it.

Two traps already hit here: `src/data/photos.json` restricts some of his frames (another person in
shot, a third party logo), and `scripts/brand-qa.mjs` fails the build of any brand file that uses one;
and a section must never start invisible, because link previews and full page screenshots do not
scroll.

## The system in one table

| | Token | Job |
|---|---|---|
| Ground | `--k-ground` (n6 #1E1B16) | the dark outside, every page and board |
| Raised | `--k-groundRaised` (n5) | a panel or field on the dark |
| Light | `--k-light` (n0 #F4EFE6) | the lit room: where his picture stands, and the room sections |
| Ink | `--k-ink`, `--k-inkMuted` | type on the dark |
| Room ink | `--k-roomInk`, `--k-roomInkMuted` | type in the light |
| Door | `--k-door` (y1 #FFAA00) | the button, the jamb and sill line, one word of a headline |
| Mark | `--k-mark` (v1 #8E5BFF) on dark, `--k-markRoom` (v2) in the light | a ticked box, nothing else |
| Focus | `--k-focus` | every focus ring on the dark |

Type: `k-poster`, `k-display`, `k-title`, `k-lead`, `k-body` (Archivo, wide for headlines, normal
for text) and `k-label`, `k-numeral` (IBM Plex Mono). Web sizes are clamps; inside a `.k-board` the
same classes size to the board.

Components in `brand.css`: `.k-btn` (all states; `.k-btn--room` inside a light section, because yellow never sits on the light), `.k-box` (`--room`, `--done`, `--locked`),
`.k-door` with `__room`, `__jamb`, `__sill`, `.k-mat`, `.k-grain`, `.k-foot`, `.k-mark`. Astro
components in `06_DESIGN/src/components/brand/`: `PhotoDoor` (him in the photographed doorway),
`Door`, `Box`, `Mark`, `Foot`.

## Rules that are easy to break

1. **His picture never sits on the dark.** It stands in the light: `PhotoDoor`, a cutout on
   `--k-light`, or a whole frame in `.k-mat`. `scripts/brand-qa.mjs` measures it.
2. Yellow never on the light (1.67), violet and yellow never touching.
3. A ticked box only where it reports something that happened. A stranger sees empty boxes.
4. Generated photographs show places and objects only. Never a person.
5. No em dash, no en dash, no exclamation mark.
6. Every fact about Kelvin comes from his own words. The strings with their sources are in
   `06_DESIGN/src/data/brand/content.json`; the evidence is in
   `00_BRIEF/260919_KEAR_brand-fact-ledger_v1.md`. No price, no date, no client result.

## Images

| File in `public/img/brand/` | What | Use |
|---|---|---|
| `front-3-1600.jpg`, `front-1-1600.jpg` | open doorway, lit room, dark wall | `PhotoDoor`, hero |
| `blade-2`, `blade-4`, `ajar-2`, `ajar-3` | a door ajar, a blade of light on the floor, dark top half | a full bleed section with type on the top |
| `gymv-2`, `gym-2`, `gym-4` | the gym door before sunrise | story, the drag |
| `corner-1`, `corner-2` | the dumbbell corner | the man who trains in one spot |
| `buds-4` | earbuds left on the bench | no headphones |
| `mirror-4` | the mirror with only the door in it | the mirror line |
| `rack-3` | the empty rack | not a bodybuilder |
| `morning-2` | the front door at dawn | say good morning |
| `cut-*.webp` | his own frames, cut out, graded | on the light only |
| `frame-*.jpg` | his whole frames, graded | in a mat, or as footage |
| `avatar.webp` | his face on the light | the profile picture |

Every photograph exists at `-1080.jpg` and `-1600.jpg`. Prompts and the grade are in `IMAGES.md`.

## Instagram, ready to paste

Display name: `Kelvin Arnott | Confidence Coach`

Bio from 28 September, when the page is live (131 characters):

```
The friend who drags you in.
Level 3 PT. Once the smallest guy in the room.
Free 30 days to your first real conversation in the gym
```

Link title: `Apply for the free 30 days`, pointing at the challenge page. "Apply" because the page is an application: a short call with Kelvin follows to see if it fits (agreed 14 September, 45:34 to 46:13).

Line 3 for 21 to 27 September, before the page exists: `Message me IN for the free 30 days`, and no
link in the bio that week, so there is one route in. From 28 September the link points at the page.

Highlights, in this order: Dragged in, Quests, The rules, Real world, Challenge.

Pins: the origin reel of Monday 21 September and the Your 30 days carousel of Monday 28 September.
The ladder post (`pinned-3`) is the third pin once the content plan gives it a posting day; it is not
among the 21 scheduled pieces yet. The profile mock shows all three as the target state. The boards
are in `boards.zip`.

The content plan owns the dates, and it changes the profile three times: Monday 21 September the
week 1 line above, Monday 28 September the link to the page, Monday 5 October its "doors shut" line,
with the Your 30 days carousel unpinned that morning. The covers here show the system with his own
lines; the lines each scheduled piece carries on screen are in the week files
(`07_DELIVERY/03_LAYERS/260919_KEAR_content-week-*_v1.md`). No date or countdown is burned into a
board or a cover: dates live in captions, stories and messages.

Two story templates sit in the same zip. `story-1` carries one quest from his ladder and leaves the
band from 62 to 78 percent of the height empty for a poll sticker, added in the app. `story-2` is the
week one ask, "Message me IN". Both keep everything between 14 and 80 percent of the height, clear
of Instagram's own buttons.

The Sunday recap (`feed-5`) is a template. Its week number, its line and its ticks come from that
week's own caption, and its photograph from the same post. Never carry them over from an older week.
