Skip to content

brand: navy ink with real contrast, the cyan as one accent, and buttons, states, fields, tables and type as brand's - #21

Merged
aledbf merged 5 commits into
mainfrom
design/hill-climb
Nov 7, 2026
Merged

aledbf merged 5 commits into
mainfrom
design/hill-climb

Conversation

@aledbf

@aledbf aledbf commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

Before and after: https://claude.ai/artifact/XDi41VTD1GT8HVwBePC6mg. This page is private until its owner shares it. It shows every screen of the set with each reviewer's verdict. The type specimen, with three candidate families at DPR 1, is at https://claude.ai/artifact/YTq37peab9dx5QDWYPumbk.

The dark mode was a saturated navy (S 39%) whose four surfaces sat 4% of lightness apart. Its borders were blue-grey and louder than the planes they bound, the accent was a neon cyan with dark text on every row, labels were mint, and every corner was 4 px. The navy and cyan were never the problem; the contrast was. This PR keeps them and fixes that.

What changes

  • Palette. Dark is the navy at its own chroma: #0E1421 → #161E2F → #1F2940 → #2A3550, a step under the avatar's #111827, each step a clear lightness apart, with grey lines. Light is white with a trace of the navy. A darker ink (#0A0E16) read as near-black on the website: its council sent it back to the navy. The one accent is the mark's cyan deepened until white reads on it (#1B7DB4 / #0A6FA3). Labels are slate, not mint. States are softened and stay apart in every colour-vision deficiency.
  • Geometry and elevation.
    • Controls are 6 px.
    • [elevation] gives a soft shadow in light and only a crisp edge in dark, where a black shadow on the scrim drew a second rectangle around the dialog.
    • Dialogs sit on --popover.
    • The scrim is 0.64 of the dark page.
  • Buttons are brand's.
    • [controls] sets the heights (28/32/36), the icon size and the gap.
    • tint.fill derives the hover and pressed fills, with white labels held at 4.5:1 in each state.
    • The rule: one primary per view, in words alone; row actions are quiet secondary buttons plus ⋯.
  • Type.
    • The app's headings are sans (type.heading). The site's are the mono, set tight (type.display, --spin-font-display, -0.035em): the website's council took the mono headings as what made it Spinbox's.
    • Headings are fluid from 390 to 1280 px. --spin-text-display is the landing's headline alone; a page's title is h1 (28–40), and Starlight's --sl-text-h1..h4 follow.
    • Figures are tabular (--spin-numeric).
    • Labels are sentence case, and a mono id or state is set at the size of the text beside it.
  • States are badges on their own tint (tint.badge, --spin-*-badge, --success-subtle…), held at 4.5:1 over page, surface and raised.
  • logos/mark-dark-* is the clear mark with its shadow drawn for the dark page, where the light one's grey shadow read as a pale ring.
  • The laboratory gains the Buttons, States, Fields and Tables sections.

All 144 pairs hold (they were 100). task check passes.

How it was judged

ui-hill-climb/ holds the audit, the direction, the rounds, the screen set, an app specimen drawn only from dist/dashboard.css the way spin's dashboard uses it, and the ledger. Reviewers judged blind, against the brand at 7e17029:

Round Claude Codex Gemini
3 12/12 3/12 10/12
6 (this head) 12/12 8/12 out of quota

Codex's four losses in round 6 are the dialog and the lab's dashboard sample; the scrim went to 0.64 after that round. Round 6 was judged on the darker ink. The website's own council then moved the navy and the site's headings, and those changes are judged on the website's PR.

The font council (Plex, Inter + JetBrains Mono, Geist) found no family that wins. It found the type system problems listed above, which this PR fixes for any family. The family stays IBM Plex.

From the dashboard's rounds (spin-stack/spin#915)

  • dashboard.css exports --link (accent_text). The accent is a fill under a white label; as text on the dark navy it was 4.1:1, and axe flagged color-contrast on nine of the dashboard's shots.
  • muted is raised in both themes again. It is the dashboard's selected navigation, and on light's surface the current page all but vanished.

Left for the consumers

  • Website: copy dist/starlight.css, dist/tokens.css and the logos (mark-dark-256 for the dark header).
  • Dashboard:
    • copy brand.css and logos/;
    • its secondary button should use --secondary + --border (not --input) and --primary-hover (not primary/90);
    • states should be drawn as badges.
  • App findings that are not brand's: column headers on the workspaces list, Delete enabled while the name does not match, filters that do not look clickable, the mobile rows, and a copy button on commands.

🤖 Generated with Claude Code

aledbf and others added 5 commits November 7, 2026 11:44
…ners that are not boxes

The surfaces were the navy at 39% saturation, the accent a neon cyan with dark text on every
row, the labels mint and every corner 4 px: every grey and border read blue, and the eye had
nowhere to rest. Now the surfaces are neutral (S at most 15%) and held apart by lightness, the
accent is the cyan deepened until white reads on it, labels are a slate, controls are 6 px,
and [elevation] gives a soft shadow in light and only a crisp edge in dark, where a black
shadow on the scrim drew a second rectangle around the dialog. Dialogs sit on --popover
(overlay); the dashboard's muted and secondary are the surface in light. All 100 pairs hold.

ui-hill-climb/ holds the audit, the direction, the rounds, the screen set, an app specimen drawn
only from dist/dashboard.css, and the blind council's ledger: against 7e17029, round 3 won 12/12
for Claude, 10/12 for Gemini (2 ties), 3/12 for Codex, which keeps preferring the navy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… held, one rule for icons

A consumer invented a button's states (the dashboard's primary/90 was lighter in dark and darker
in light, its white label below 4.5:1 in one of them). Now palette.toml's [controls] gives the
heights (28, 32, 36), the icon and the gap, and tint.fill the darkening of a solid fill under
the pointer and pressed; task palette writes --spin-accent-fill-hover/-active,
--spin-destructive-hover/-active, --spin-control/-hover and the dashboard's --primary-hover and
the rest, and holds 20 pairs more: the white label on each state at 4.5:1, a hover told from
rest, a secondary button off the page. The laboratory's Buttons section draws every variant in
every state and size, and where each goes; the site's pills are the same small-radius controls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s apart, its lines grey

The neutral near-black answered the contrast and lost the identity; the navy was never the
problem. Dark is #0A0E16 to #242E40 in clear lightness steps, borders grey, the cyan deepened as
the one accent; light is white with a trace of the navy. The selection's tint is 0.27, since cyan
over navy is close in hue. 120 pairs hold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y, and the mark on dark

A blind council on IBM Plex, Inter + JetBrains Mono and Geist found no family that wins; it found
the system: states in an 11 px mono beside 13 px names, figures that do not line up, a 52 px mono
headline that read as a terminal, uppercase mono labels, inline code broken at its dash. So:

- type.heading: every heading is the sans; the mono is for what a machine says.
- type.fluid: headings grow from the phone's width to the desktop's as clamp()s in rem
  (--spin-text-display/h1/h2/h3, and Starlight's --sl-text-h1..h4).
- type.numeric: tabular figures (--spin-numeric).
- tint.badge: a state is a badge, its word on its own tint, held at 4.5:1 over page, surface and
  raised; the light states darkened for it, success a step toward teal so protans still tell it
  from warning. 144 pairs hold.
- The laboratory draws States, Fields (rest, hover, focus, invalid, disabled; 16 px on touch) and
  Tables (muted sans headers, mono ids, tabular figures, hover and selection).
- logos/mark-dark-*: the clear mark with its shadow drawn for the dark page, where the light
  one's grey shadow read as a pale ring.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…men draws a state as its badge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aledbf
aledbf marked this pull request as ready for review November 7, 2026 15:15
@aledbf
aledbf merged commit 1713b91 into main Nov 7, 2026
2 checks passed
aledbf added a commit to spin-stack/website that referenced this pull request Nov 7, 2026
…, its type

refgen copies brand at b7e4afc (versions.yaml pins the PR's head until it merges, then
`task sources:bump` moves it to main):

- The palette: the navy at its own chroma with clear steps between planes and grey lines, the
  mark's cyan deepened as the one accent, and Starlight's scale fluid from a phone to a desktop.
- Headings in the mono at brand's display tracking (type.display), their word gaps closed: a mono's
  own spacing is what made a large heading read as a terminal.
- Buttons are brand's: the control's height and small corner, the accent solid with a white label,
  a quiet fill and a hairline for the rest, hover and pressed as brand derives them. Starlight's
  primary was the accent's light tint with dark text. The hero's primary is words alone and its
  second action a secondary button.
- The hero's second sentence in the accent's text colour, softer than the neon it was; the
  eyebrow and the story's labels in the sans, sentence case.
- The dark header's mark is the clear one with its shadow drawn for the navy (mark-dark-256).
- A --help or an output wraps in its block; a command scrolls, since a wrap breaks it at a dash.

Judged blind against main (ui-hill-climb/ROUNDS.md): the last round 10/10 for Claude and 5-1 with
4 ties for Codex.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aledbf added a commit to spin-stack/website that referenced this pull request Nov 7, 2026
…, its type

refgen copies brand at b7e4afc (versions.yaml pins the PR's head until it merges, then
`task sources:bump` moves it to main):

- The palette: the navy at its own chroma with clear steps between planes and grey lines, the
  mark's cyan deepened as the one accent, and Starlight's scale fluid from a phone to a desktop.
- Headings in the mono at brand's display tracking (type.display), their word gaps closed: a mono's
  own spacing is what made a large heading read as a terminal.
- Buttons are brand's: the control's height and small corner, the accent solid with a white label,
  a quiet fill and a hairline for the rest, hover and pressed as brand derives them. Starlight's
  primary was the accent's light tint with dark text. The hero's primary is words alone and its
  second action a secondary button.
- The hero's second sentence in the accent's text colour, softer than the neon it was; the
  eyebrow and the story's labels in the sans, sentence case.
- The dark header's mark is the clear one with its shadow drawn for the navy (mark-dark-256).
- A --help or an output wraps in its block; a command scrolls, since a wrap breaks it at a dash.

Judged blind against main (ui-hill-climb/ROUNDS.md): the last round 10/10 for Claude and 5-1 with
4 ties for Codex.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant