v0.3 Phase 1: Tactile Quietware tokens

Foundation for the v0.3 Tactile Quietware release. Tokens only. No
component refactors, no layout changes, no behavioural shifts. The new
palette and typography activate only when html[data-design="quietware"]
is set; the runtime v0.2 surface is unaffected without the attribute.

What landed.

  - Three-mode palette (light, dark, high-contrast) at
    src/design-system/v0.3-quietware-tokens.css. Strict 90deg square
    colour harmony pegged at cobalt blue #0047AB. Hues: 215 / 305 / 35
    / 125. Saturation locked at 100%. Lightness adjusted per role for
    WCAG AA 4.5:1 on the relevant background; computed values
    documented in the plan doc.

  - V4 font stack self-hosted as WOFF2:
        Work Sans (variable, roman + italic) for body, UI, controls.
        Young Serif for brand moments only.
        JetBrains Mono stays via existing src/fonts/jetbrains-mono.woff2.

  - Import wired in src/app.css directly after the tailwind import.
    The new tokens are inert until data-design="quietware" is set on
    <html>.

  - Reduced-motion override scoped to quietware so prefers-reduced-motion
    actually bites inside the new design system from day one.

  - Plan doc at docs/release/v0.3-tactile-quietware.md with the full
    seven-phase plan (Phase 1 logged), four high-priority persona test
    gates (Pawel, Simone, Chris, Ron), and the Phase 0 gov.uk DfE
    accessibility tools checklist.

Activation paths.

  - Manual now: dev tools, set <html data-design="quietware">.
  - Phase 2 will wire VITE_LUMOTIA_QUIETWARE=1 through +layout.svelte.

Verified.

  - npm run check produced 26 errors but all 26 are pre-existing in
    files this PR does not touch (LumotiaTooltip.svelte missing
    bits-ui import; tests/e2e/smoke.spec.ts missing playwright types).
    Tracked separately, not blocking v0.3 Phase 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 12:15:07 +01:00
parent eecedbdecd
commit f718aded16
6 changed files with 413 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
/* ============================================================
Lumotia v0.3 — Tactile Quietware tokens.
Phase 1 of the v0.3 release. Tokens only. No component refactors,
no layout changes, no behavioural shifts. The new palette and
typography activate only when html[data-design="quietware"] is set.
When the attribute is absent the runtime app behaves exactly as it
did in v0.2.
Activation paths:
1. Manual: add data-design="quietware" to <html> via dev tools.
2. Build flag (Phase 2): VITE_LUMOTIA_QUIETWARE=1 will wire the
attribute through +layout.svelte automatically.
--------------------------------------------------------------
Palette geometry: strict 90-degree square colour harmony,
pegged at cobalt blue #0047AB.
Hue spacing fixed at 90 degrees from cobalt:
--info 215deg (cobalt blue, the peg)
--danger 305deg (magenta-pink)
--caution 35deg (orange-amber)
--success 125deg (yellow-green)
Saturation locked at 100%. Lightness adjusted per role to clear
WCAG AA 4.5:1 on the relevant background. Yellow and green are
perceptually brighter than blue and magenta at the same numeric L,
so caution and success use slightly darker L values in light mode.
This is perceptual-lightness compensation, not a break from the
square geometry.
Caution stays a fill-only role on cream paper. Bright caution
tones fail 4.5:1 as text on cream regardless of lightness.
Pill backgrounds, dots, left-border accents and icons take
--color-caution. Foreground text inside caution-coloured pills
stays --color-text.
Typography stack (V4 pairing, locked 2026-05-15):
Work Sans -> body, UI, controls, headers
Young Serif -> brand moments only (wordmark, empty-state hook)
JetBrains Mono -> logs, paths, model IDs
Source brief: docs/release/v0.3-tactile-quietware.md.
============================================================ */
@font-face {
font-family: 'Work Sans';
src: url('/fonts/work-sans-variable.woff2') format('woff2-variations'),
url('/fonts/work-sans-variable.woff2') format('woff2');
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Work Sans';
src: url('/fonts/work-sans-italic-variable.woff2') format('woff2-variations'),
url('/fonts/work-sans-italic-variable.woff2') format('woff2');
font-weight: 100 900;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Young Serif';
src: url('/fonts/young-serif.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
/* ============================================================
Quietware — dark mode default.
Lifted Coffee Bean base. Square-harmony hues, L lifted for AA
on the dark surface.
============================================================ */
:root[data-design="quietware"] {
--color-bg: #2A1620;
--color-bg-elevated: #34222B;
--color-bg-card: #3E2A33;
--color-bg-input: #281620;
--color-border: #6B4D58;
--color-border-subtle: #4E3742;
--color-text: #F3EFE7;
--color-text-secondary: #BDB6A9;
--color-text-tertiary: #8D8577;
--color-info: #247FFF;
--color-danger: #EC00D8;
--color-caution: #C07000;
--color-warning: var(--color-caution);
--color-success: #00AB0E;
--color-sidebar: #1F0F18;
--color-nav-active: #3E2A33;
--color-hover: #34222B;
--color-overlay-dim: rgba(31, 8, 18, 0.7);
--font-family-body: 'Work Sans', system-ui, sans-serif;
--font-family-display: 'Young Serif', serif;
--font-family-mono: 'JetBrains Mono', monospace;
/* Texture intensity. 0.06 baseline, slider range 0.05 to 0.08 in advanced. */
--quietware-texture-opacity: 0.06;
--quietware-texture-color: rgba(243, 239, 231, 1);
}
/* ============================================================
Quietware — light mode.
Cream paper base. Cobalt blue #0047AB appears literally as --info.
Other three roles share cobalt's hue offsets (90 / 180 / 270 deg)
with L adjusted per role to clear WCAG AA 4.5:1 on cream.
============================================================ */
:root[data-design="quietware"][data-theme="light"] {
--color-bg: #FBF8F2;
--color-bg-elevated: #F3EEE6;
--color-bg-card: #FFFFFF;
--color-bg-input: #F3EEE6;
--color-border: #897D70;
--color-border-subtle: #D8D0C4;
--color-text: #1D1B18;
--color-text-secondary: #5E574C;
--color-text-tertiary: #74685B;
--color-info: #0047AB; /* cobalt peg, 215deg, AAA on cream */
--color-danger: #AB009C; /* 305deg, AA on cream */
--color-caution: #A76200; /* 35deg, AA on cream */
--color-warning: var(--color-caution);
--color-success: #00850B; /* 125deg, AA on cream */
--color-sidebar: #F3EEE6;
--color-nav-active: #E8E2D6;
--color-hover: #EAE4D8;
--color-overlay-dim: rgba(29, 27, 24, 0.55);
--quietware-texture-opacity: 0.07;
--quietware-texture-color: rgba(29, 27, 24, 1);
}
/* ============================================================
Quietware — high-contrast mode.
Brand chroma steps aside. S=80%, L=70%. Zero texture.
Same four hues retained so role recognition does not flip.
============================================================ */
:root[data-design="quietware"][data-contrast="high"] {
--color-bg: #000000;
--color-bg-elevated: #0A0A0A;
--color-bg-card: #111111;
--color-bg-input: #050505;
--color-border: #FFFFFF;
--color-border-subtle: #888888;
--color-text: #FFFFFF;
--color-text-secondary: #DADADA;
--color-text-tertiary: #C8C8C8;
--color-info: #75A8F0;
--color-danger: #F075E5;
--color-caution: #F0BD75;
--color-warning: var(--color-caution);
--color-success: #75F080;
--color-sidebar: #000000;
--color-nav-active: #1A1A1A;
--color-hover: #1A1A1A;
--color-overlay-dim: rgba(0, 0, 0, 0.85);
/* No texture in high contrast. Clarity over atmosphere. */
--quietware-texture-opacity: 0;
--quietware-texture-color: rgba(0, 0, 0, 0);
}
/* ============================================================
Reduced motion. Honour OS preference; quietware rules require it.
============================================================ */
@media (prefers-reduced-motion: reduce) {
:root[data-design="quietware"] * {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}