design: extract document-as-is UI contract (DESIGN.md + DTCG tokens)
Case-B extract of the as-built dark UI into design/: 9-section DESIGN.md, W3C DTCG tokens.tokens.json, brand/palette.css + assets, and inspiration/ provenance (incl. the rendered red-shade decision). Two owner calls layered in: red elevated to the single brand accent (#DC2626), two-tier radius (4px controls / 8px containers). AGENTS.md gains the read-before-UI Design line + design/ in the layout tree; ROADMAP gains the design-checker cleanup backlog. No UI code changed.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
# Inspiration & provenance
|
||||
|
||||
Proof of Work's design was **extracted document-as-is** (Case B) from the existing code on
|
||||
2026-06-19 — there were no prior brand guidelines and no external reference set. So for this
|
||||
repo the "inspiration" is the **as-built UI itself**, plus the brand mark. This folder records
|
||||
the *why/where* behind the contract.
|
||||
|
||||
## De-facto references (the source the look was harvested from)
|
||||
|
||||
- **Brand mark** — [`../brand/logo-kettlebell.png`](../brand/logo-kettlebell.png): a pure-white
|
||||
kettlebell silhouette on near-black. It establishes the core identity directly: **monochrome,
|
||||
white-on-black, no color in the mark.** Everything else follows from this.
|
||||
- **As-built styling surfaces** (where every value was censused by Tailwind-class frequency):
|
||||
- `proof-of-work/app/globals.css` — base bg, heading treatment, scrollbar, layout vars.
|
||||
- `proof-of-work/app/layout.tsx` — fonts (Bebas Neue display, Space Grotesk body), theme color.
|
||||
- `proof-of-work/tailwind.config.ts` — font-family wiring, spacing/radius extensions.
|
||||
- `proof-of-work/components/**` + `proof-of-work/app/main/**` — the inline utility classes that
|
||||
were frequency-ranked to find the canonical neutral (zinc), surface ladder, type scale,
|
||||
radii, and the white-primary / red-error patterns.
|
||||
- `proof-of-work/public/manifest.json` — `theme_color`/`background_color` `#0A0A0A` (the
|
||||
external anchor that confirmed the canonical canvas color).
|
||||
|
||||
## Owner decisions captured in the reconcile (2026-06-19)
|
||||
|
||||
The extract was literal except for two owner-driven calls:
|
||||
|
||||
1. **Red promoted to a brand accent.** As-built, red was error/destructive only. The owner chose
|
||||
to elevate it to *the* accent (still keeping white as the primary button). Canonical red =
|
||||
**`#DC2626`** (Tailwind red-600, "Blood Red"), which also re-tints the error states so the UI
|
||||
carries a single coherent red.
|
||||
- The candidates that were compared on the real `#0A0A0A` background:
|
||||
[`red-accent-candidates.png`](./red-accent-candidates.png) (rendered from
|
||||
[`red-accent-candidates.html`](./red-accent-candidates.html)). Options were Signal `#EF4444`,
|
||||
Blood `#DC2626` *(chosen)*, Vermilion `#FF3B30`, Crimson `#E11D48`.
|
||||
2. **Two-tier radius rule.** The code mixed 4px (`rounded`) and 8px (`rounded-lg`) with no rule;
|
||||
the owner adopted **4px for controls, 8px for containers**.
|
||||
|
||||
Everything else (zinc as the one neutral, white primary button, Bebas-uppercase-tracked
|
||||
headings, flat/border-based depth, dense small type scale) is the as-built look, documented
|
||||
faithfully in [`../DESIGN.md`](../DESIGN.md).
|
||||
@@ -0,0 +1,159 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
* { margin:0; padding:0; box-sizing:border-box; }
|
||||
body {
|
||||
background:#0A0A0A; color:#fff;
|
||||
font-family:'Space Grotesk', system-ui, sans-serif;
|
||||
padding:36px 40px 44px;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.display { font-family:'Bebas Neue', sans-serif; letter-spacing:.05em; text-transform:uppercase; }
|
||||
h1 { font-family:'Bebas Neue',sans-serif; letter-spacing:.06em; font-size:34px; }
|
||||
.sub { color:#a1a1aa; font-size:13px; margin-top:4px; margin-bottom:26px; }
|
||||
.row {
|
||||
display:grid; grid-template-columns:200px 1fr; gap:28px;
|
||||
align-items:center;
|
||||
padding:22px 0; border-top:1px solid #27272a;
|
||||
}
|
||||
/* left: raw swatch + name */
|
||||
.swatch { height:120px; border-radius:8px; }
|
||||
.name { font-family:'Bebas Neue',sans-serif; letter-spacing:.06em; font-size:26px; margin-top:12px; }
|
||||
.hex { color:#71717a; font-size:13px; font-variant-numeric:tabular-nums; }
|
||||
|
||||
/* right: vignette strip */
|
||||
.vignette { display:flex; gap:20px; align-items:stretch; flex-wrap:nowrap; }
|
||||
.card {
|
||||
background:#18181b; border:1px solid #27272a; border-left:4px solid var(--a);
|
||||
border-radius:8px; padding:14px 16px; width:230px;
|
||||
}
|
||||
.card .label { font-family:'Bebas Neue',sans-serif; letter-spacing:.12em; font-size:13px; color:var(--a); }
|
||||
.card .h { font-family:'Bebas Neue',sans-serif; letter-spacing:.05em; font-size:22px; margin-top:6px; }
|
||||
.card .stat { display:flex; align-items:baseline; gap:8px; margin-top:8px; }
|
||||
.card .stat .n { font-size:30px; font-weight:700; font-variant-numeric:tabular-nums; }
|
||||
.card .stat .d { color:var(--a); font-size:14px; font-weight:600; }
|
||||
|
||||
.col { display:flex; flex-direction:column; gap:12px; justify-content:center; }
|
||||
|
||||
/* nav active state */
|
||||
.nav { display:flex; gap:18px; align-items:center; }
|
||||
.nav a { font-family:'Bebas Neue',sans-serif; letter-spacing:.1em; font-size:14px; color:#71717a; padding-bottom:6px; }
|
||||
.nav a.active { color:var(--a); border-bottom:2px solid var(--a); }
|
||||
|
||||
/* badge (accent wash) */
|
||||
.badge {
|
||||
display:inline-block; font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:.08em;
|
||||
color:var(--a); background:color-mix(in srgb, var(--a) 15%, transparent);
|
||||
border:1px solid color-mix(in srgb, var(--a) 45%, transparent);
|
||||
padding:4px 10px; border-radius:4px;
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
.btns { display:flex; gap:10px; }
|
||||
.btn-primary {
|
||||
background:#fff; color:#000; font-weight:700; text-transform:uppercase; letter-spacing:.08em;
|
||||
font-size:12px; padding:9px 16px; border-radius:4px; border:none;
|
||||
}
|
||||
.btn-accent {
|
||||
background:transparent; color:var(--a); border:1px solid var(--a);
|
||||
font-weight:700; text-transform:uppercase; letter-spacing:.08em;
|
||||
font-size:12px; padding:9px 16px; border-radius:4px;
|
||||
}
|
||||
.reflabel { font-size:10px; color:#52525b; text-transform:uppercase; letter-spacing:.1em; margin-top:6px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Proof of Work — red accent candidates</h1>
|
||||
<div class="sub">All on the app background #0A0A0A. White stays the primary button (reference, same in every row); red is used only as an accent: labels, active nav, card edge, stat delta, ghost button, badge.</div>
|
||||
|
||||
<!-- A -->
|
||||
<div class="row" style="--a:#EF4444">
|
||||
<div>
|
||||
<div class="swatch" style="background:#EF4444"></div>
|
||||
<div class="name">A · Signal Red</div>
|
||||
<div class="hex">#EF4444 · Tailwind red-500 (in-family)</div>
|
||||
</div>
|
||||
<div class="vignette">
|
||||
<div class="card">
|
||||
<div class="label">Personal Record</div>
|
||||
<div class="h">Back Squat</div>
|
||||
<div class="stat"><span class="n">142.5</span><span class="d">▲ +5kg</span></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="nav"><a class="active">Today</a><a>History</a><a>Programs</a></div>
|
||||
<span class="badge">PR · Week 6</span>
|
||||
<div class="btns"><button class="btn-primary">Save workout</button><button class="btn-accent">Refine</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- B -->
|
||||
<div class="row" style="--a:#DC2626">
|
||||
<div>
|
||||
<div class="swatch" style="background:#DC2626"></div>
|
||||
<div class="name">B · Blood Red</div>
|
||||
<div class="hex">#DC2626 · Tailwind red-600 (deeper)</div>
|
||||
</div>
|
||||
<div class="vignette">
|
||||
<div class="card">
|
||||
<div class="label">Personal Record</div>
|
||||
<div class="h">Back Squat</div>
|
||||
<div class="stat"><span class="n">142.5</span><span class="d">▲ +5kg</span></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="nav"><a class="active">Today</a><a>History</a><a>Programs</a></div>
|
||||
<span class="badge">PR · Week 6</span>
|
||||
<div class="btns"><button class="btn-primary">Save workout</button><button class="btn-accent">Refine</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- C -->
|
||||
<div class="row" style="--a:#FF3B30">
|
||||
<div>
|
||||
<div class="swatch" style="background:#FF3B30"></div>
|
||||
<div class="name">C · Vermilion</div>
|
||||
<div class="hex">#FF3B30 · hot orange-red</div>
|
||||
</div>
|
||||
<div class="vignette">
|
||||
<div class="card">
|
||||
<div class="label">Personal Record</div>
|
||||
<div class="h">Back Squat</div>
|
||||
<div class="stat"><span class="n">142.5</span><span class="d">▲ +5kg</span></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="nav"><a class="active">Today</a><a>History</a><a>Programs</a></div>
|
||||
<span class="badge">PR · Week 6</span>
|
||||
<div class="btns"><button class="btn-primary">Save workout</button><button class="btn-accent">Refine</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- D -->
|
||||
<div class="row" style="--a:#E11D48">
|
||||
<div>
|
||||
<div class="swatch" style="background:#E11D48"></div>
|
||||
<div class="name">D · Crimson</div>
|
||||
<div class="hex">#E11D48 · cooler, pink-edge (rose-600)</div>
|
||||
</div>
|
||||
<div class="vignette">
|
||||
<div class="card">
|
||||
<div class="label">Personal Record</div>
|
||||
<div class="h">Back Squat</div>
|
||||
<div class="stat"><span class="n">142.5</span><span class="d">▲ +5kg</span></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="nav"><a class="active">Today</a><a>History</a><a>Programs</a></div>
|
||||
<span class="badge">PR · Week 6</span>
|
||||
<div class="btns"><button class="btn-primary">Save workout</button><button class="btn-accent">Refine</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 205 KiB |
Reference in New Issue
Block a user