Files
lib-theme-lantern/README.md
jules 0c31a343e2 lib-theme-lantern: initial import (access-first set, 2026-07)
One of three candidates for the access-first / maximum-legibility theme
family (WCAG AAA as identity): 7:1+ contrast on every pair (passes
validate-theme.mjs --aaa), 1.125rem body floor with nothing under 14px,
44px controls for everyone, 3px focus rings, links underlined at rest,
reduced-motion built in. Built for IGH/NDIS-facing surfaces first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 07:20:58 +10:00

86 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# lib-theme-lantern
**Warm paper, kitchen table not clinic.**
Lantern is one of three divergent candidates for Crema's access-first theme
family: WCAG AAA as identity, not compliance. Its thesis is that maximum
legibility can feel warm and human — a document you read at the kitchen table
with someone you trust, not a form handed across a clinic counter. Built for
NDIS participants, their families, and older support coordinators (the
IGH/IveGotHome portals): dignity, clarity, zero squinting. The discipline IS
the personality.
## The idea
- **Light mode** — warm ivory paper (`oklch(0.97 0.012 85)`), warm-white cards,
near-black warm umber ink at **17.8:1**. The surface is deliberately high in
lightness so 7:1 ink is easy everywhere and nothing has to shout.
- **Primary** — a deep amber-brown gold (`oklch(0.4 0.11 70)`): a lantern's
brass, not a yellow hazard. Warm-white label at **9.0:1**. Links share the
same gold and are **underlined by default** (thicker on hover).
- **Dark mode** — the lantern lit: warm dark umber (`oklch(0.17 0.012 60)`),
warm-white ink at **16.5:1**, and the gold turned luminous
(`oklch(0.78 0.13 80)`) with a black-umber label at **9.7:1**.
- **Type** — Lexend for body AND headings (weight 600 headings). Lexend was
designed to improve reading proficiency; here it earns its keep. JetBrains
Mono for code.
## Access-family contract (shared DNA)
- Type ramp starts larger: body 1.125rem/1.65, label 1rem/1.5, caption
0.875rem/1.4 (never below 14px). Generous line-heights throughout.
- Body ink and `muted-foreground` ≥ 7:1 on background AND card, both modes.
Primary label ≥ 7:1 on primary. Status label pairs all ≥ 7:1.
- Focus: 3px solid outline + 2px offset on buttons; inputs get a border-color
change plus a 2px ring. Always visible.
- Touch targets: buttons and inputs min-height 2.75rem **globally**, not just
behind a coarse-pointer media query.
- Borders strong — ink at 0.250.32 alpha. Boundaries, not hairlines
(`--border-width-base` is 1.5px; no sub-pixel widths).
- Radius soft but modest (0.625rem). Elevation low; borders do the separating.
- Motion minimal and quick (120/200/300/400ms); all springs alias the standard
ease; `prefers-reduced-motion: reduce` zeroes transitions on interactive
slots. Nothing essential is motion-only.
## Verified contrast (WCAG 2.1 relative luminance, exact oklch→sRGB)
| Pair | Light | Dark |
|---|---|---|
| foreground / background | 17.81:1 | 16.54:1 |
| foreground / card | 19.14:1 | 14.98:1 |
| muted-foreground / background | 9.99:1 | 9.55:1 |
| muted-foreground / card | 10.73:1 | 8.65:1 |
| muted-foreground / muted | 8.86:1 | 7.54:1 |
| primary-foreground / primary | 9.00:1 | 9.73:1 |
| status labels / fills (worst) | 8.09:1 | 7.40:1 |
## Fonts
Consuming apps load fonts at the very top of their entry CSS (never inside
`theme.css` — see the token contract):
```css
@import url("https://fonts.googleapis.com/css2?family=Lexend:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap");
```
## Validation
```bash
node create-crema-app/scripts/validate-theme.mjs lib-theme-lantern/theme.css
# ✓ PASS — all mandatory tokens present, contrast floors met, no ban violations.
```
## Notes
- Warning is a deep amber-**orange** (hue 55, L 0.42) in light mode — well
separated from the hue-70/80 brass so the two never read as one swatch, and
dark enough that it never becomes a pale hazard stripe.
- Dark-mode surface ladder: background 0.17 → sidebar 0.20 → card 0.22 →
popover 0.245 → muted/secondary 0.27 (popover above card, below muted).
- Chart hues 80/150/220/290/20 (≥60° apart), adjacent lightness varied.
- Chat: user bubble is a deep warm-umber panel (13:1 light / 11:1 dark);
assistant bubble is a card with the strong border.
- Headings use `color: inherit` so titles inside primary buttons, status
banners, and chat bubbles keep their surface's ink.
- No glass — inert stubs (`0px / 100% / 1 / 1`).