Define the lvl0 palette and ship it as @lvl0/ui #2

Closed
opened 2026-08-23 15:37:07 +02:00 by myrmidex · 1 comment
Owner

Context

There is no single source of truth for the lvl0 visual style. It currently exists as three
divergent copies, reverse-engineered from each other:

File Lines Contents
incr/incr/resources/css/app.css 25 font + glow only, no palette
buckets-old/resources/css/app.css 133 full shadcn-style token set, --radius: 0
buckets-budget/frontend/src/theme.css 100 dark-only oklch palette, fullest of the three

Concrete drift already observed:

  • The 7segment.woff font is duplicated in ≥3 repos (see #1)
  • incr loads the font by relative path with a comment explaining that an absolute
    /fonts/ path 404s against the Vite dev server — buckets uses the absolute path that
    comment warns against
  • Bordeaux does not exist in any shared source. It was introduced in
    anagram-finder/web on 2026-08-23 and is currently defined only there

Canonical palette

Primary is unchanged from buckets-budget, which is the fullest existing implementation.
Bordeaux is new and should be adopted as the official secondary.

Token Value Role
--color-primary oklch(0.637 0.237 25.331) House red. Text, active borders, glow source. Equals Tailwind red-500.
--color-bordeaux oklch(0.258 0.092 26.042) Secondary. Dividers, resting borders, recessed chrome. Equals Tailwind red-950.
--color-background oklch(0.1 0 0) Near-black page ground
--color-card oklch(0.12 0 0) Raised surface
--color-muted oklch(0.2 0 0) Muted surface
--color-muted-foreground oklch(0.5 0.1 25) Muted text
--color-destructive oklch(0.577 0.245 27.325) Destructive actions
--radius 0 Square corners throughout

Chart colours (--chart-1--chart-5) carry over from buckets-budget as-is.

Utilities to ship

  • .glow-red — box-shadow bloom in primary, with :hover and :focus steps
  • .glow-red-text — two-layer text-shadow, for borderless headings. .glow-red haloes the
    box, so it smudges when used on text
  • .glow-bordeaux — with :hover / :focus
  • .glow-bordeaux-line — two-layer variant for 1–2px rules, where a single wide shadow on a
    hairline just fades out
  • .scrollbar-red — covers both scrollbar-color (Firefox) and ::-webkit-scrollbar
  • .font-digital — 7-segment face. Numerals only; letters render badly

Non-obvious rule worth encoding

.glow-bordeaux deliberately emits primary-tinted light, not bordeaux. Bordeaux is
oklch(0.258 …) — too dark to bloom against a near-black ground, so a bordeaux halo is
invisible. Dim element, brighter glow, as CRT phosphor behaves. Anyone reimplementing this
from scratch will get it wrong once.

Package shape

@lvl0/ui
  src/theme.css        @theme tokens
  src/utilities.css    glows, digital, scrollbar
  src/index.css        imports both
  fonts/7segment.woff  (pending #1)
  LICENSE              MIT — see below
  README.md

Consumer usage:

@import 'tailwindcss';
@import '@lvl0/ui';

Licence

MIT, deliberately diverging from the AGPL-3.0-only used across the other lvl0 repos.
This package is meant to be imported: AGPL's copyleft would attach to any consuming work,
which makes it unusable to anyone outside lvl0 and defeats the point of publishing it.
Design systems built for consumption (Primer, Carbon, Polaris, Tailwind) are MIT or Apache-2.0
for this reason. AGPL stays correct for the application repos, where §13 does real work.

Adoption

New projects only. anagram-finder/web is the first consumer — its
resources/css/app.css already defines these tokens locally and can switch to the import.
incr, buckets, and ffr keep their current CSS until touched anyway; retrofitting them is
explicitly out of scope.

Depends on

  • #1 for the font (tokens and utilities can land before it; only the font file is gated)

Acceptance

  • Tokens defined in a Tailwind 4 @theme block
  • All six utilities present, with the glow-bordeaux rationale in a comment
  • anagram-finder/web builds against the package with no visual change
  • MIT LICENSE present
  • Published and installable from the Forgejo registry
## Context There is no single source of truth for the lvl0 visual style. It currently exists as three divergent copies, reverse-engineered from each other: | File | Lines | Contents | |---|---|---| | `incr/incr/resources/css/app.css` | 25 | font + glow only, no palette | | `buckets-old/resources/css/app.css` | 133 | full shadcn-style token set, `--radius: 0` | | `buckets-budget/frontend/src/theme.css` | 100 | dark-only oklch palette, fullest of the three | Concrete drift already observed: - The `7segment.woff` font is duplicated in ≥3 repos (see #1) - `incr` loads the font by **relative** path with a comment explaining that an absolute `/fonts/` path 404s against the Vite dev server — `buckets` uses the absolute path that comment warns against - **Bordeaux does not exist in any shared source.** It was introduced in `anagram-finder/web` on 2026-08-23 and is currently defined only there ## Canonical palette Primary is unchanged from `buckets-budget`, which is the fullest existing implementation. Bordeaux is new and should be adopted as the official secondary. | Token | Value | Role | |---|---|---| | `--color-primary` | `oklch(0.637 0.237 25.331)` | House red. Text, active borders, glow source. Equals Tailwind `red-500`. | | `--color-bordeaux` | `oklch(0.258 0.092 26.042)` | **Secondary.** Dividers, resting borders, recessed chrome. Equals Tailwind `red-950`. | | `--color-background` | `oklch(0.1 0 0)` | Near-black page ground | | `--color-card` | `oklch(0.12 0 0)` | Raised surface | | `--color-muted` | `oklch(0.2 0 0)` | Muted surface | | `--color-muted-foreground` | `oklch(0.5 0.1 25)` | Muted text | | `--color-destructive` | `oklch(0.577 0.245 27.325)` | Destructive actions | | `--radius` | `0` | Square corners throughout | Chart colours (`--chart-1` … `--chart-5`) carry over from `buckets-budget` as-is. ## Utilities to ship - `.glow-red` — box-shadow bloom in primary, with `:hover` and `:focus` steps - `.glow-red-text` — two-layer text-shadow, for borderless headings. `.glow-red` haloes the *box*, so it smudges when used on text - `.glow-bordeaux` — with `:hover` / `:focus` - `.glow-bordeaux-line` — two-layer variant for 1–2px rules, where a single wide shadow on a hairline just fades out - `.scrollbar-red` — covers both `scrollbar-color` (Firefox) and `::-webkit-scrollbar` - `.font-digital` — 7-segment face. **Numerals only**; letters render badly ### Non-obvious rule worth encoding `.glow-bordeaux` deliberately emits **primary**-tinted light, not bordeaux. Bordeaux is `oklch(0.258 …)` — too dark to bloom against a near-black ground, so a bordeaux halo is invisible. Dim element, brighter glow, as CRT phosphor behaves. Anyone reimplementing this from scratch will get it wrong once. ## Package shape ``` @lvl0/ui src/theme.css @theme tokens src/utilities.css glows, digital, scrollbar src/index.css imports both fonts/7segment.woff (pending #1) LICENSE MIT — see below README.md ``` Consumer usage: ```css @import 'tailwindcss'; @import '@lvl0/ui'; ``` ## Licence **MIT**, deliberately diverging from the `AGPL-3.0-only` used across the other lvl0 repos. This package is meant to be *imported*: AGPL's copyleft would attach to any consuming work, which makes it unusable to anyone outside lvl0 and defeats the point of publishing it. Design systems built for consumption (Primer, Carbon, Polaris, Tailwind) are MIT or Apache-2.0 for this reason. AGPL stays correct for the application repos, where §13 does real work. ## Adoption New projects only. `anagram-finder/web` is the first consumer — its `resources/css/app.css` already defines these tokens locally and can switch to the import. `incr`, `buckets`, and `ffr` keep their current CSS until touched anyway; retrofitting them is explicitly out of scope. ## Depends on - #1 for the font (tokens and utilities can land before it; only the font file is gated) ## Acceptance - [ ] Tokens defined in a Tailwind 4 `@theme` block - [ ] All six utilities present, with the glow-bordeaux rationale in a comment - [ ] `anagram-finder/web` builds against the package with no visual change - [ ] MIT `LICENSE` present - [ ] Published and installable from the Forgejo registry
myrmidex added this to the v0.1.0 milestone 2026-08-23 15:37:07 +02:00
myrmidex added the
enhancement
label 2026-08-23 15:37:07 +02:00
myrmidex self-assigned this 2026-08-23 15:37:07 +02:00
myrmidex added a new dependency 2026-08-23 15:37:29 +02:00
myrmidex added a new dependency 2026-08-23 15:37:34 +02:00
Author
Owner

Done — v0.1.0 tagged and installable

All acceptance criteria verified:

  • Tokens in a Tailwind 4 @theme blocksrc/theme.css, 12 tokens
  • Six utilities with the glow-bordeaux rationale in a commentsrc/utilities.css
  • anagram-finder/web builds against the package with no visual change — diffed the
    compiled CSS against a pre-change baseline: 24 of 24 lvl0 utility rules byte-identical,
    zero differing. The font still fingerprints into the build (7segment-Cl-sqT19.woff), now
    resolved from the package rather than a local copy.
  • MIT LICENSE present
  • Published and installable — verified by installing
    git+ssh://git@forge.lvl0.xyz:2222/lvl0/ui.git#v0.1.0 into a clean throwaway project with no
    symlink. All five files present, fonts/OFL.txt alongside fonts/7segment.woff.

Distribution is a tag-pinned git dependency rather than an npm registry publish. For internal
consumers that is sufficient; a registry publish can follow if the package is ever consumed
outside lvl0.

Consumer change

anagram-finder/web @ 49fe4bf — imports @lvl0/ui in resources/css/app.css, drops the
local token and utility blocks, and deletes resources/fonts/ entirely. That also closes
the OFL exposure noted on #1: web no longer redistributes the font at all, so licence text
and font travel together in the package.

Note

While extracting, two scrollbar rules were tidied (#000var(--color-background), and a
color-mix hover). The no-visual-change diff caught both and they were reverted to match
web's originals. Worth revisiting as a deliberate change later — --color-background is the
more correct reference now that the token exists.

Not adopted

incr, buckets, and buckets-budget keep their own divergent CSS, as scoped. The three
copies collapse only when those projects are touched.

## Done — `v0.1.0` tagged and installable All acceptance criteria verified: - **Tokens in a Tailwind 4 `@theme` block** — `src/theme.css`, 12 tokens - **Six utilities with the glow-bordeaux rationale in a comment** — `src/utilities.css` - **`anagram-finder/web` builds against the package with no visual change** — diffed the compiled CSS against a pre-change baseline: **24 of 24 lvl0 utility rules byte-identical**, zero differing. The font still fingerprints into the build (`7segment-Cl-sqT19.woff`), now resolved from the package rather than a local copy. - **MIT `LICENSE` present** - **Published and installable** — verified by installing `git+ssh://git@forge.lvl0.xyz:2222/lvl0/ui.git#v0.1.0` into a clean throwaway project with no symlink. All five files present, `fonts/OFL.txt` alongside `fonts/7segment.woff`. Distribution is a tag-pinned git dependency rather than an npm registry publish. For internal consumers that is sufficient; a registry publish can follow if the package is ever consumed outside lvl0. ### Consumer change `anagram-finder/web` @ `49fe4bf` — imports `@lvl0/ui` in `resources/css/app.css`, drops the local token and utility blocks, and **deletes `resources/fonts/` entirely**. That also closes the OFL exposure noted on #1: `web` no longer redistributes the font at all, so licence text and font travel together in the package. ### Note While extracting, two scrollbar rules were tidied (`#000` → `var(--color-background)`, and a `color-mix` hover). The no-visual-change diff caught both and they were reverted to match `web`'s originals. Worth revisiting as a deliberate change later — `--color-background` is the more correct reference now that the token exists. ### Not adopted `incr`, `buckets`, and `buckets-budget` keep their own divergent CSS, as scoped. The three copies collapse only when those projects are touched.
Sign in to join this conversation.
No labels
bug
ci
docs
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference: lvl0/ui#2
No description provided.