diff --git a/README.md b/README.md index 0da0649..7ef73ed 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,84 @@ -# ui +# lvl0/ui +The shared visual style for lvl0 projects — palette, glow utilities, and the seven-segment +display font. Published as `@lvl0/ui`. + +Red-on-black terminal aesthetic: monospace type, square corners, thick borders, and CRT-style +glow. This repository is the source of truth. Before it existed the style lived as three +divergent copies across `incr`, `buckets`, and `buckets-budget`, reverse-engineered from each +other — read the values here rather than from another project. + +> **Status:** early. The package is not published yet; see the open issues. + +## Palette + +Defined as Tailwind 4 `@theme` tokens. Use the token names rather than raw `red-*` steps so a +palette change lands in one place. + +| Token | Value | Role | +|---|---|---| +| `--color-primary` | `oklch(0.637 0.237 25.331)` | House red. Text, active borders, focus states, glow source. | +| `--color-bordeaux` | `oklch(0.258 0.092 26.042)` | Secondary. Dividers, resting borders, recessed chrome. | +| `--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` are also defined. + +**Primary or bordeaux?** Primary for anything active or foreground: text, focused inputs, the +borders of things you can click. Bordeaux for structure: dividers, the resting state of an +input border, panel outlines. An element commonly moves from bordeaux to primary on focus. + +## Utilities + +| Class | Use | +|---|---| +| `.glow-red` | Box-shadow bloom in primary, with `:hover` and `:focus` steps | +| `.glow-red-text` | Two-layer text-shadow, for headings without a border | +| `.glow-bordeaux` | Softer bloom, for bordeaux-bordered elements | +| `.glow-bordeaux-line` | Two-layer variant for 1–2px rules | +| `.scrollbar-red` | Themed scrollbar, Firefox and WebKit | +| `.font-digital` | Seven-segment face — **numerals only** | + +Three rules that are not obvious from the values: + +- **`.glow-red` haloes a box, not text.** On a borderless heading it smudges around the + element's invisible box. Use `.glow-red-text` there. +- **`.glow-bordeaux` emits primary-tinted light, not bordeaux.** Bordeaux at `oklch(0.258 …)` + is too dark to bloom against a near-black ground, so a bordeaux halo is invisible. Dim + element, brighter glow — as CRT phosphor behaves. +- **A single wide shadow on a hairline just fades out.** `.glow-bordeaux-line` uses a tight + core plus a wider spill so a 2px rule reads as lit. + +## Font + +`fonts/7segment.woff` — 7-Segment by [Jan Bobrowski](http://torinak.com/7segment), version 3.0, +licensed under the [SIL Open Font License 1.1](fonts/OFL.txt). + +The OFL permits bundling and redistribution provided the licence text travels with the font. +**`fonts/OFL.txt` must ship wherever `7segment.woff` does** — including in the published npm +tarball. Do not move one without the other. + +Licence verified 2026-08-23 from two independent sources: the font's own `name` table +(ID 13 `LicenseDesc` = "SIL OFL", ID 9 `Designer` = "Jan Bobrowski") and the designer's page. + +Letters render poorly in a seven-segment face. Use it for digits — counters, lengths, readouts +— and set everything else in `font-mono`. + +## Usage + +Once published: + +```css +@import 'tailwindcss'; +@import '@lvl0/ui'; +``` + +## Licence + +MIT — see [LICENSE](LICENSE). Deliberately different from the AGPL-3.0 used across the other +lvl0 repositories: this package is meant to be imported, and AGPL's copyleft would attach to +any consuming work. The bundled font keeps its own OFL terms. diff --git a/fonts/7segment.woff b/fonts/7segment.woff new file mode 100644 index 0000000..09ab315 Binary files /dev/null and b/fonts/7segment.woff differ diff --git a/fonts/OFL.txt b/fonts/OFL.txt new file mode 100644 index 0000000..40bd8a6 --- /dev/null +++ b/fonts/OFL.txt @@ -0,0 +1,97 @@ +Copyright (c) , (), +with Reserved Font Name . +Copyright (c) , (), +with Reserved Font Name . +Copyright (c) , (). + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/package.json b/package.json new file mode 100644 index 0000000..da9ccb7 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "@lvl0/ui", + "version": "0.1.0", + "description": "Shared visual style for lvl0 projects: palette, glow utilities, and the seven-segment display font.", + "license": "MIT", + "author": "myrmidex ", + "repository": { + "type": "git", + "url": "https://forge.lvl0.xyz/lvl0/ui.git" + }, + "type": "module", + "main": "src/index.css", + "style": "src/index.css", + "exports": { + ".": "./src/index.css", + "./theme.css": "./src/theme.css", + "./utilities.css": "./src/utilities.css", + "./fonts/*": "./fonts/*" + }, + "files": [ + "src", + "fonts", + "README.md", + "LICENSE" + ], + "keywords": ["css", "tailwind", "design-tokens", "lvl0"], + "peerDependencies": { + "tailwindcss": "^4.0.0" + } +} diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..6d2e92c --- /dev/null +++ b/src/index.css @@ -0,0 +1,2 @@ +@import './theme.css'; +@import './utilities.css'; diff --git a/src/theme.css b/src/theme.css new file mode 100644 index 0000000..6d5d69e --- /dev/null +++ b/src/theme.css @@ -0,0 +1,23 @@ +/* lvl0 palette — Tailwind 4 theme tokens. + Use the token names, never raw red-* steps, so a palette change lands here only. */ + +@theme { + /* Primary is the house red, unchanged since buckets-budget. Bordeaux is the + secondary: dividers, resting borders, recessed chrome. */ + --color-primary: oklch(63.7% 0.237 25.331); + --color-bordeaux: oklch(25.8% 0.092 26.042); + + --color-background: oklch(10% 0 0); + --color-card: oklch(12% 0 0); + --color-muted: oklch(20% 0 0); + --color-muted-foreground: oklch(50% 0.1 25); + --color-destructive: oklch(57.7% 0.245 27.325); + + --color-chart-1: oklch(63.7% 0.237 25.331); + --color-chart-2: oklch(75% 0.18 70); + --color-chart-3: oklch(70% 0.15 145); + --color-chart-4: oklch(75% 0.15 55); + --color-chart-5: oklch(50% 0.1 25); + + --radius: 0; +} diff --git a/src/utilities.css b/src/utilities.css new file mode 100644 index 0000000..2640063 --- /dev/null +++ b/src/utilities.css @@ -0,0 +1,84 @@ +/* lvl0 utilities — glows, the seven-segment face, and a themed scrollbar. + Every colour derives from the tokens in theme.css; no literals here. */ + +@font-face { + font-family: '7Segment'; + /* Relative so the consuming bundler resolves and fingerprints it; an absolute + /fonts path 404s against a dev server that serves assets itself. */ + src: url('../fonts/7segment.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +/* Numerals only — letters render badly in a seven-segment face. */ +.font-digital { + font-family: '7Segment', monospace; +} + +.glow-red { + box-shadow: 0 0 20px color-mix(in oklab, var(--color-primary) 40%, transparent); + transition: box-shadow 300ms ease; +} + +.glow-red:hover { + box-shadow: 0 0 25px color-mix(in oklab, var(--color-primary) 60%, transparent); +} + +.glow-red:focus, +.glow-red:focus-within { + box-shadow: 0 0 28px color-mix(in oklab, var(--color-primary) 70%, transparent); +} + +/* For text without a border: .glow-red haloes the element's box, which smudges + around a borderless heading instead of tracing the letters. */ +.glow-red-text { + text-shadow: + 0 0 12px color-mix(in oklab, var(--color-primary) 70%, transparent), + 0 0 30px color-mix(in oklab, var(--color-primary) 40%, transparent); +} + +/* Bordeaux itself is too dark to bloom against black, so the halo is emitted in + primary at low alpha — dim element, brighter glow, as CRT phosphor behaves. */ +.glow-bordeaux { + box-shadow: 0 0 14px color-mix(in oklab, var(--color-primary) 35%, transparent); + transition: box-shadow 300ms ease; +} + +.glow-bordeaux:hover { + box-shadow: 0 0 18px color-mix(in oklab, var(--color-primary) 50%, transparent); +} + +.glow-bordeaux:focus, +.glow-bordeaux:focus-within { + box-shadow: 0 0 26px color-mix(in oklab, var(--color-primary) 65%, transparent); +} + +/* Same bloom for a 1-2px rule, where a single wide shadow has no box to hug and + just fades out. Tight core plus a wider spill. */ +.glow-bordeaux-line { + box-shadow: + 0 0 6px color-mix(in oklab, var(--color-primary) 45%, transparent), + 0 0 14px color-mix(in oklab, var(--color-primary) 25%, transparent); +} + +.scrollbar-red { + scrollbar-width: thin; + scrollbar-color: var(--color-bordeaux) transparent; +} + +.scrollbar-red::-webkit-scrollbar { + width: 10px; +} + +.scrollbar-red::-webkit-scrollbar-track { + background: transparent; +} + +.scrollbar-red::-webkit-scrollbar-thumb { + background: var(--color-bordeaux); + border: 2px solid #000; +} + +.scrollbar-red::-webkit-scrollbar-thumb:hover { + background: var(--color-red-900); +}