Files
whynot-design/README.md
tegwick 9419f166ce
Some checks failed
ci / check (push) Has been cancelled
ci / release (push) Has been cancelled
Seeded claude design
2026-05-23 16:34:14 +02:00

15 KiB
Raw Blame History

@whynot/design

The neutral, mostly-black-and-white visual language for whynot — Tegwick's prototype and market-signal organisation. Wireframe-leaning. Quiet. Built for artefacts that should look deliberately unfinished.

A prototype is a question made tangible. — whynot-control/INTENT.md

This repository is the implementation surface. The language of the system — voice, casing, motifs, the reasoning behind each rule — lives in this README. The artefact — the CSS, the components, the assets — lives in src/ and assets/.

If you're new here, read these in order:

  1. DesignSystemIntroduction.md — how this repo relates to whynot-control, the Claude atelier, and consuming apps. Pipeline, versioning, propagation.
  2. SKILL.md — the Agent Skill manifest. Read this if you (or an agent) will be generating new artefacts in this style.
  3. This README — the full design language: tokens, components, content rules, iconography.
  4. CONTRIBUTING.md — how to propose, review, and ship a change.

Quick start

# in a consuming repo
pnpm add git+ssh://git@gitea.example.com/whynot/whynot-design.git#v0.1.0
// at the app root, once
import "@whynot/design/styles/colors_and_type.css";

// anywhere
import { Button, Tag, Eyebrow, StageDot } from "@whynot/design";

What lives where

Path Contents
tokens/ Source-of-truth design tokens as JSON.
src/styles/colors_and_type.css All CSS variables + semantic element styles. The single file every consumer imports.
src/components/ React components (JSX, no build step).
src/index.js Barrel export.
assets/ Logo, mark, future imagery.
examples/whynot-control/ Live click-through UI kit. Also the Playwright visual-regression target.

The remainder of this README is the full design language — colour reasoning, type stack, content rules, iconography. It is identical to the language defined in the Claude atelier project and should stay in sync. Treat it as authoritative.

CONTENT FUNDAMENTALS

Voice

The voice is quiet, structured, evidence-oriented, and careful about overclaiming. It comes directly out of the AGENT_RULES.md and OPERATING_MODEL.md:

Agent outputs should be concise, evidence-oriented, explicit about uncertainty, and careful to separate idea, hypothesis, signal, and decision.

whynot-control/AGENT_RULES.md

The voice should sound like a careful field-notebook — not a startup landing page, not a product manifesto, not marketing copy.

Casing

  • Sentence case for headings, buttons, labels, links — not Title Case. ("Smallest useful test", not "Smallest Useful Test".)
  • lowercase for the organization name in body: whynot, never WhyNot or WHYNOT. The logo wordmark may use WhyWhyNot for legacy reasons.
  • UPPERCASE is reserved for short eyebrow labels (PROTOTYPE, SIGNAL S2, STAGE, IN BETA) — set in mono, with letterspacing.
  • code-case for repo names, doc names, folder names: whynot-control, INTENT.md, inbox/. Always in monospace.

Person

Third person, with the project as subject. Avoid "we", avoid "you", avoid "I".

  • "A prototype is a question made tangible."
  • "The repository helps the user capture unusual but potentially useful ideas."
  • "We help you discover weird ideas."
  • "You'll love how easy this is."

Direct second-person is reserved for imperatives in a checklist (e.g. "Read INTENT.md.").

Tone

  • Curious, not enthusiastic. "This may be worth a closer look" beats "🚀 huge if true!".
  • Hedged, not promotional. Use may, could, seems, appears to. Avoid will, guaranteed, the best.
  • Distinguish idea / hypothesis / signal / decision. Never collapse them.
  • Lack of signal is also information. Silence is a finding, not a failure.

Phrasing patterns to imitate

Lifted from the existing control documents:

  • "A prototype is a question made tangible."
  • "Signal beats enthusiasm."
  • "Signals are evidence, not vibes."
  • "Capture is not commitment."
  • "Low-cost learning first."
  • "A prototype can be interesting and still be parked."

The pattern is: short declarative claim → small qualifier or counter-claim. Two beats, no exclamation.

Phrasing to avoid

  • "Revolutionize…", "Reimagine…", "Unlock…", "Empower…"
  • "🚀", "", "🔥", any other hype emoji.
  • "We believe…", "We're on a mission to…"
  • "Beta — sign up now!" (use "Closed beta. Invitation only.")
  • Numbers without context ("10x faster"). Use signal-record format instead.

Examples

Avoid Prefer
"Get started — it's free!" "Inbox is open. Capture is not commitment."
"Our amazing new prototype" "Prototype WNO-014. Stage: experiment."
"Users love it!" "S2 — repeated interest, three concrete use-cases."
"Coming soon — sign up!" "Closed beta. Five seats. Ends 2026-04-01."
"🎉 Launched!" "Promoted to Helix on 2026-03-12. See DECISIONS.md."

Emoji & punctuation

  • No emoji in body copy, headings, or UI.
  • ? and ! are the brand's punctuation — they appear in the logo and may appear, sparingly, in display headlines (try($idea) until success;, why? why not!).
  • (U+2192) for "promotes to / goes to" links between stages. Not ->.
  • (em dash) for parenthetical, not --.

VISUAL FOUNDATIONS

Overall posture

The system reads like engineering graph paper — precise hairlines, lots of whitespace, monospace labels in margins, content blocks that look like fields in a form rather than cards in a feed. The aesthetic is closer to a Bauhaus wall-chart or a man page than to a SaaS dashboard.

Color

  • Mostly black on white, with a few flat greys.
  • One accent only: a warm yellow (--hi: #FFE14A) lifted from the LEGO brick in the logo. It appears as highlighter / annotation / signal-marker — never as a button fill, never as a hero background.
  • No gradients. Anywhere. Including subtle ones.
  • No tinted whites--paper is a true #FFFFFF; --paper-2 and --paper-3 are barely-warm off-whites (#FAFAF7, #F4F4EF) reserved for sheets and recessed code blocks.
  • Status colors (S0S4 signal strength) are rendered as desaturated grey ramps, not red/yellow/green. S4 ("commercial signal") is the only one that uses the yellow accent, because that's the threshold where a prototype actually matters commercially.

Type

  • Family: IBM Plex Sans for everything UI/body. IBM Plex Mono for labels, code, and stage markers. IBM Plex Serif for the occasional editorial pull-quote. (See font substitution note in Fonts below.)
  • Weights: 300 (display only), 400 (body), 500 (UI / headings), 600 (occasional emphasis). Never 700+ — too marketing.
  • Tracking: tight on display (-0.035em), neutral on body, wide on uppercase labels (0.08em — this is the one signature move).
  • Eyebrows everywhere: short uppercase mono labels above titles (STAGE, SIGNAL, PROTOTYPE). They are the system's main rhythmic element.

Spacing

  • 4px base unit, exposed as --sp-1 (4) through --sp-10 (128).
  • Generous: a content block typically has --sp-7 (48px) of internal padding. Lists separated by --sp-5 (24px) minimum.
  • Section breaks are big (--sp-9, 96px). Reads like a printed report.

Backgrounds

  • --paper (#FFFFFF) by default. Period.
  • --paper-2 for full-width "sheet" sections (e.g. between hero and content).
  • --paper-3 for recessed surfaces only — code blocks, inline pre, inset cards.
  • No images as backgrounds. No hand-drawn illustrations. No repeating patterns. No textures. No noise. No grain. (Exception: a 1px hairline grid may be used on a literal "wireframe" mock; see preview/grid-paper.html.)

Animation

  • Minimal. This is a document system, not a product UI.
  • Transitions on hover only: 120ms ease on text-decoration-color for links, border-color for inputs.
  • No spring physics, no bounce, no fade-in-on-scroll. Anything that draws attention is not in the spirit of "low-cost learning first".
  • Exception: the cursor-blink animation on a <TerminalLine> is permitted because it's a literal terminal motif.

Hover & press states

  • Links — underline color goes from --border-strong to --fg-1 on hover.
  • Buttons (primary, dark)--ink--ink-2 on hover. On press, no transform, just --ink (back to baseline).
  • Buttons (secondary, outline) — border --border--ink. On press, background flashes --bg-3.
  • Cardsdo not have hover states. They are documents, not interactive surfaces. Exception: prototype cards in an index list get a 1px black left border on hover.
  • No scale transforms, no shadow lifts, no glow effects.

Borders

  • 1px solid --border (#E5E5E2) is the default. Used everywhere.
  • --border-strong (#C9C9C5) for section dividers and the outline of a primary block.
  • Hairline --border-soft (#F0F0EC) for internal rules within a card.
  • No double borders, no inset borders, no dashed borders except in one specific case: dashed --border-strong is used to indicate "placeholder / not yet defined" content (see Components / Empty State).

Shadows

  • --shadow-0: none. This is the default. Most cards and panels have no shadow.
  • --shadow-1: 0 1px 0 var(--line) — a 1px bottom-line, used in place of bottom-border on sticky headers.
  • --shadow-2: 0 1px 0 var(--line-strong) — slightly stronger version.
  • --shadow-3 is reserved for floating elements only (a popover, a focus-trapped modal). Even then it's a soft 4-12px diffuse shadow at 10% opacity — never a "card lift" shadow.

Protection gradients vs capsules

  • No protection gradients. Backgrounds are solid; never overlay a gradient to "rescue" text from a busy background, because backgrounds are never busy.
  • Capsules (pills with rounded ends) are used only for --label and tag elements — never for buttons. Buttons are slightly rounded rectangles (--r-2, 4px).

Layout rules

  • Single-column reading width of ~640px for body, ~880px for documents with sidebars.
  • Constant page padding of --sp-7 (48px) on desktop, --sp-4 (16px) on mobile.
  • Sticky element: top navigation bar, height 56px, bottom hairline.
  • Sidebar (where used): 256px fixed width, --paper-2 background, no border on right (uses whitespace to separate from main).
  • Grids for structured data only — never as a "card wall". 12-column with 24px gutters.

Transparency & blur

  • Almost never used. No frosted glass. No backdrop-filter.
  • One permitted use: a rgba(255,255,255,0.92) on the sticky top nav so that scrolled content is faintly visible behind it. No blur.

Imagery

  • Black & white only. All photography (when used) is rendered with filter: grayscale(1) contrast(0.95) — slightly low-contrast, like a Risograph print.
  • Aspect ratios: 4:3 (preferred — feels like a document figure), 1:1 (for portraits / icons). Never 16:9 in body.
  • No people-stock-photography. Prefer objects, diagrams, or screenshots.
  • No AI-generated imagery unless explicitly labelled as such with a [generated] caption.

Corner radii

  • --r-1 (2px) for inputs and tags.
  • --r-2 (4px) for buttons and small cards.
  • --r-3 (8px) for large cards and modals.
  • --r-pill (999px) for label capsules only.
  • --r-0 (0px / square) is the default for documents, sheets, and any element wider than ~600px. Big things are square.

Cards

A "card" in this system is a bordered rectangle, not a shadowed object floating off the page.

  • 1px --border outline.
  • --paper background.
  • 4px or 8px radius depending on size.
  • No shadow.
  • Internal padding --sp-5 (24px) minimum.
  • A monospace eyebrow at top-left + a stage label at top-right is the canonical card header.
  • On hover (when interactive): the top-left eyebrow tints to --fg-1, and a 2px black bar appears flush against the left edge. Nothing else moves.

ICONOGRAPHY

The codebase did not ship an icon font, an icon sprite, or any SVG icons — whynot-control is a documents-only repo. The only visual asset is the LEGO-brick logo.

Approach

  • Lucide icons via CDN is the chosen icon set. It matches the system's stroke weight (1.5px), neutral geometry, and "wireframe artefact" feel better than Material, Heroicons, or Phosphor. Load with <script src="https://unpkg.com/lucide@latest"></script> and call lucide.createIcons().
  • Stroke weight is always 1.5px. Override Lucide's default 2px via stroke-width="1.5" on each <svg> or via CSS.
  • Color: currentColor. Icons inherit from text. No two-tone, no fills.
  • Size: 16px (inline), 20px (button), 24px (heading-adjacent), 32px (feature). Never larger — large icons read as decoration, and decoration is not in the spirit.

When to use icons

  • In navigation labels, button labels, and inline status — only when the icon adds parsing speed. If the word reads faster than the icon, skip the icon.
  • In document margins to mark stage transitions (e.g. → Helix).
  • Not as decorative chrome on cards.
  • Not as "feature icons" in a 3-up grid on a marketing page (this system has no marketing pages).

Emoji

  • Never. Emoji are not used anywhere — in copy, labels, alt text, or as fallback for missing icons.

Unicode characters used as icons

These are allowed and preferred over raster icons in some contexts:

Char Used for
"promotes to" / pipeline arrow
back / previous
· inline bullet separator (in nav, in meta lines)
em dash, in metadata
? ! the brand's signature punctuation, in display headlines only
§ section marker, in long documents
  • The primary mark is the LEGO brick with ? and ! underneath, in pure black & white. assets/whynot-logo.png (300×300 raster, transparent background).
  • For very small uses (favicon, footer mark), a simplified mark is recommended: just the ?! pair in IBM Plex Sans 600, with the brick implied by a 2×4 dot grid above. See preview/logo.html.
  • The brick should never be coloured (no LEGO-red, LEGO-blue, etc). It is always black-outlined on white, or white-outlined on black.
  • Minimum size: 32px square. Below that, fall back to the ?! wordmark.

A note on font substitution

The control repo did not ship font files. IBM Plex Sans / Mono / Serif were chosen as a fresh pairing because:

  • The "Plex" family was designed by IBM as an explicitly neutral, technical-document family — the same use-case as this system.
  • All three (sans, mono, serif) share metrics, so they mix cleanly in templates and tables.
  • They are openly licensed (SIL OFL) and available on Google Fonts.

Plex is currently loaded from Google Fonts (see top of colors_and_type.css). For offline use, drop the .woff2 files into fonts/ and swap the @import for a local @font-face block.

🟨 Substitution flagged: there was no specified brand font; IBM Plex is a choice made here. If whynot later adopts a different brand font, replace --ff-sans / --ff-mono / --ff-serif in colors_and_type.css and everything downstream will follow.