v0.4.0 — Visibility refresh + lg button
Bumps dark-mode surface contrast across the whole library and brings back a larger button size.
What's new
Dark-mode visibility lift
```diff
- --surface: var(--color-base-900); /* oklch(0.16 0.003 273) */
- --surface: oklch(0.18 0.005 273);
- --edge: rgba(255, 255, 255, 0.08);
- --edge: rgba(255, 255, 255, 0.16);
- --edge-hover: rgba(255, 255, 255, 0.14);
- --edge-hover: rgba(255, 255, 255, 0.24);
```
Cards, dropdowns (Select / Combobox / MultiSelect triggers + popovers), Input / Textarea, Dialog, Table, Badge, Tabs, Checkbox / RadioGroup / Switch, and Stepper all lift coherently off the page. One token bump, no per-component overrides. Light-mode tokens unchanged.
Button `lg` size
```tsx
Sign in {/* py-[13px] px-6 text-[15px] /}
Sign in {/ py-[9px] px-[18px] text-[13px] — default */}
```
- New `lg` step: 15px text, py 13 / px 24, LED `size-2`, icon `size-4`.
- Outline variant: compensated to `py-[12px] px-[23px]`.
- `md` remains the default — `lg` is opt-in for hero CTAs / primary form actions.
Migration
No code changes required. Consumers using `bg-surface` / `border-edge` in dark mode get the lift automatically; `` is additive.
If a downstream app calibrated layouts against the previous (sunken) surface, the visual difference is one lightness step — sanity-check dense surfaces (data tables, sidebars) and re-tune if needed.
Also in this release
- `docs/DECISIONS.md` Decision #95 with full rationale.
- `docs/SKIN-PRINCIPLES.md` § 3 "Hairline borders" rule depinned from the literal alpha so the principle text doesn't drift from the implementation on future tuning.
- `docs/DESIGN-SYSTEM.md` token table + surface ladder paragraph synced.
See PR #16 for the full diff.