Files
Lumotia/docs/release/v0.3-tactile-quietware.md
Jake dab9c7b5a6 v0.3 Phase 4d/4e: palette revision + HC rendering contract
Round-4 feedback (2026-05-15) pulled the system away from the
color.adobe.com primaries toward muted-Material values, separated
brand accent from semantic caution, and reframed high-contrast as a
behavioural rendering contract rather than a palette override.

Two phases land together because the palette revision and the HC
contract are inherently linked — HC mode needs both palette overrides
AND behavioural-token overrides to deliver "different rendering
contract" semantics.

Phase 4d palette revision.

  Dark mode (was wine-aubergine #2A1620, now brown-charcoal #12100E):
    --color-bg            #12100E
    --color-bg-elevated   #1A1713
    --color-bg-card       #211D18
    --color-bg-input      #181510
    --color-sidebar       #0F0E0C
    --color-border        #4A4035
    --color-border-subtle #2C261F

  Brand accent (new — was unset, fell through to v0.2 amber that
  competed with semantic yellow):
    Dark:  --color-accent #C97845 (copper)
    Light: --color-accent #9D5F32 (deeper copper)

  Semantic colours (muted-Material, both modes):
    Dark:  danger #FF8A8A  caution #F2C94C  success #79D59B  info #8AB4F8
    Light: danger #B3261E  caution #7A5D00  success #1B6B3A  info #2457A6

  Light mode work surface (slight paper tone, not pure white):
    --color-bg-card #FFFDF8 (was #FFFFFF)
    --color-bg-elevated #F6F1EA

  Caution fill-only-on-cream rule retires. Ochre #7A5D00 passes AA
  as foreground text on cream under the muted palette, so the single-
  token-per-role convention applies across all four semantic colours
  in both modes.

  LumotiaNotice opacity rebalance:
    Background tint  10% -> 8%
    Outer border     neutral subtle -> role at 40%
    Icon             --color-text -> role colour
    Left bar         role at 100% (unchanged)
    Title / body     --color-text (unchanged)

Phase 4e HC rendering contract.

  Behavioural tokens published alongside palette:
    --grain-opacity            0.06 dark / 0.07 light / 0 in HC
    --shadow-strength          1 default / 0 in HC
    --border-width-control     1px default / 2px in HC
    --focus-ring-width         2px default / 3px in HC
    --panel-radius             8px (reserved for future tightening)

  --quietware-texture-opacity retained as a legacy alias pointing at
  --grain-opacity so Phase 4c slider keeps working through the rename.

  HC palette: pure-black or pure-white base, the other for borders,
  single strong-focus blue #005FCC replaces accent. Brand atmosphere
  steps aside. Selector splits via :not([data-theme="light"]) so
  HC-light and HC-dark variants diverge cleanly.

Verified.

  - npm run check: 0 errors, 0 warnings across 5706 files.
  - Plan doc updated with full before/after tables, behavioural-token
    contract table, and Phase 4c / 4d / 4e log sections.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 13:50:11 +01:00

21 KiB
Raw Blame History

Lumotia v0.3 — Tactile Quietware

Calm enough for overloaded brains, structured enough to recover thoughts, tactile enough to feel like a local desktop tool rather than SaaS.

The v0.3 release reframes Lumotia around one thesis: a low-cognitive-load capture instrument. Built on the WCAG 2.2 + W3C COGA + NN/G evidence base, validated against the four HMRC accessibility personas that map most directly onto a dictation-first desktop tool.

This document is the single source of truth for v0.3. Phase log, regression diary, palette spec and font stack all live here.


Source brief

Locked 2026-05-15 from Jake's design brief and three rounds of capture-pipeline iteration.

  • Palette: inputs/inbox/2026-05-15-lumotia-colour-layout-changes.md plus the colour-palette refinements at inputs/inbox/2026-05-15-re-lumotia-v03-renders-revised-palette-typography-.md.
  • Personas: HMRC Virtual Empathy Hub, eight personas at https://personas-prototype.herokuapp.com/.
  • Accessibility tools: DfE manual at https://accessibility.education.gov.uk/tools-testing/tools.

Rule set

The five rules every v0.3 PR has to clear.

Rule Meaning
Texture = atmosphere Static global grain. No per-panel noise. No motion. Default 6%, slider 5 to 8% in advanced.
Colour = status Brand palette IS the semantic palette. Brand chroma earns its keep by signalling state. Decorative colour is forbidden.
Layout = calm Every page uses the same skeleton. Files, Tasks, History and Dictation must not invent their own structure.
Motion = feedback only Animation only for recording, loading, success and failure. Honour prefers-reduced-motion at root.
Settings = progressive disclosure One sectional tab visible at a time. Eight tabs. No long scroll.

Palette

Locked 2026-05-15 from Jake's color.adobe.com primaries. Each primary is used literally where it clears WCAG AA on the relevant background. Where it does not, a text-safe sibling at the same hue and saturation is derived.

Source primaries

Role Primary Hue Notes
--danger #FF0700 2deg Pure red
--info #000AFF 238deg Pure blue
--success #00FF56 140deg Pure green
--caution #FFCD00 48deg Pure yellow

Light mode

Cream paper base. Jake's blue passes AAA on cream and is used literally. The other three are darkened siblings for AA text contrast, with caution kept fill-only because any darkened yellow reads as olive or mustard ("looks like poop").

Token Hex Contrast on #FBF8F2 Notes
--color-bg #FBF8F2 Base Cream paper
--color-text #1D1B18 14.43 AAA Near-black
--color-info #000AFF 7.96 AAA Jake literal
--color-danger #E60600 4.51 AA Sibling derived from #FF0700
--color-success #00852D 4.51 AA Sibling derived from #00FF56
--color-caution #FFCD00 1.42 (fill-only) Jake literal, fill-only convention

Caution is fill-only on cream. Pill backgrounds, dots, left-border accents and icons take --color-caution. Foreground text inside a caution-coloured pill stays --color-text. Matches Material, GOV.UK and IBM Carbon practice.

Dark mode

Lifted Coffee Bean base. Jake's green and yellow primaries already clear AAA on the dark surface and are used literally. Red and blue need lifting because pure-saturated dark hues fail against a dark background.

Token Hex Contrast on #2A1620 Notes
--color-bg #2A1620 Base Lifted Coffee Bean
--color-text #F3EFE7 13.85 AAA
--color-info #7076FF 4.64 AA Lifted from #000AFF
--color-danger #FF2A24 4.54 AA Lifted from #FF0700
--color-success #00FF56 12.51 AAA Jake literal
--color-caution #FFCD00 11.33 AAA Jake literal

High contrast mode

Same four hues retained so role recognition does not flip between modes. Saturation 80%, lightness 70%. Zero texture, no translucent overlays.

Token Hex Contrast on black
--color-bg #000000 Base
--color-text #FFFFFF 21.00 AAA
--color-info #757AF0 5.80 AA
--color-danger #F07975 7.70 AAA
--color-success #75F09F 14.72 AAA
--color-caution #F0D875 14.78 AAA

Typography stack (V4 pairing, locked 2026-05-15)

Three production fonts. Self-hosted as WOFF2. No CDN dependency.

Role Font Licence Used for
Body and UI Work Sans (variable) OFL Headers, labels, controls, sidebar, body, transcript surface
Brand moments Young Serif OFL Wordmark, splash, empty-state hook copy, About modal
Mono JetBrains Mono Apache 2.0 Logs, model IDs, file paths, hotkey strings

Atkinson Hyperlegible Next and OpenDyslexic stay as opt-in accessibility fonts via Settings. Archivo, Lexend and Instrument Serif from v0.2 stay shipped during v0.3 transition; future release may remove them after persona testing.


Persona test gates

Each phase must pass these four manual gates before merge. Tools and tasks from the DfE manual.

Persona Condition simulated Primary risk for Lumotia Gate
Pawel Autistic Sensory load, predictability, motion sensitivity Empty states speak. No surprise motion. Same skeleton on every page.
Simone Dyslexic Transcript readability, dense paragraphs Transcript body uses Work Sans at 16px minimum, line-height ≥ 1.6, comfortable measure.
Chris Rheumatoid arthritis Click target size, keyboard fallback for every action All interactive targets ≥ 44 x 44 px. Every action reachable by keyboard with visible focus ring.
Ron Older user, multiple conditions Combined: vision + cognitive + motor All three of the above hold simultaneously.

Medium-priority personas (Claudia magnifier, Saleem deaf) get explicit checks at Phase 5. Lower-priority personas (Ashleigh screen reader, Helena dyscalculia) get checks at v0.4.


Phase 0 — Accessibility tools checklist

Manual gov.uk DfE tools applied to every v0.3 phase before merge. Tools that map onto a Tauri webview tested via the same browser-preview surface already shipped in v0.2.

  • Contrast Checker. All palette pairs verified against WCAG AA. Annotated in the relevant phase commit message.
  • axe DevTools. Run on every page after the phase migrates it.
  • Resize Text. 200% zoom does not break any layout.
  • Text Spacing. Increased letter, word, line spacing per WCAG 1.4.12 does not clip content.
  • Target Size. All interactive targets ≥ 44 x 44 px (WCAG 2.5.8).
  • HeadingsMap. Settings sectional refactor preserves a sensible h1 → h6 hierarchy.
  • Blur. Smoke check that primary actions remain legible under simulated low vision.
  • Screen reader smoke test. NVDA or Orca on the Settings page after Phase 3.

A future-Phase CI step will automate axe-core + contrast checks. Out of scope for v0.3 per Jake's 2026-05-15 decision.


Phase plan

Each phase ships as its own PR. Each is flag-gated by html[data-design="quietware"]. The current v0.2 user-facing surface is unaffected until Phase 6 promotes quietware to the default.

Phase 1 — Tokens. (this PR)

  • New file src/design-system/v0.3-quietware-tokens.css with three palette scopes (dark, light, high-contrast).
  • Self-hosted Work Sans (variable), Work Sans Italic (variable), Young Serif (static) at src/fonts/.
  • Import wired in src/app.css directly after the tailwind import. Inert until data-design="quietware" is present on <html>.
  • No component changes. No behavioural changes.

Phase 2 — Build flag wiring.

  • VITE_LUMOTIA_QUIETWARE=1 build-time env var sets data-design="quietware" on <html> via src/routes/+layout.svelte.
  • Manual override path stays: dev tools, or a Settings toggle gated behind the same flag.

Phase 3 — Status grammar primitives.

  • LumotiaStatusPill, LumotiaNotice with icon + label + body + actions.
  • Caution is fill-only across both. Foreground text uses --color-text.
  • Component preview added to src/routes/design-system-v2/.

Phase 4 — Settings sectional refactor.

  • Split the 2 791 LOC SettingsPage.svelte across eight tabs: Start Here, Models, Output, Vocabulary, Tasks, Accessibility, Privacy, Advanced.
  • Texture-opacity slider lives in Accessibility. Range 0.05 to 0.08. Default 0.06.
  • High-contrast toggle in Accessibility. Toggle overrides system prefers-contrast query when set.
  • One section visible at a time. No long-scroll.

Phase 5 — Critical-path simplification.

  • Dictation page: header + transcript surface + action rail + empty state. No cockpit furniture.
  • Files, Tasks, History migrated to the shared page skeleton (left nav, header, optional toolbar, primary work surface, optional right drawer, status row).
  • Empty states speak on all four pages.
  • Persona-test gates for Pawel, Simone, Chris, Ron at this phase.

Phase 6 — Icon and wordmark integration.

  • Real Lumotia wordmark + mark lifted from brand-proposal v1 colophon. Replaces the placeholder swirl.
  • Surfaces: window icon (.ico, .icns, multi-size .png), splash, About modal, empty-state anchor, status-pill leading glyph for "Ready".
  • Removes any remaining Magnotia / Wyrdnote / Kon-era assets.

Phase 7 — Motion audit. (final v0.3 polish)

  • Inventory every animation, transition and decorative motion currently in the app.
  • Keep: recording-active heartbeat, loading spinner, success / failure feedback.
  • Strip: decorative pulse, animated background, sliding panels, attention shimmer.
  • prefers-reduced-motion reducer set at the root selector for quietware (already in tokens CSS).

Phase 8 — Promote to default. (post-release decision)

  • Flip <html data-design="quietware"> to be the default; remove the flag.
  • Either lands as a major release (v1.0) or stays opt-in indefinitely.
  • This decision is deferred to after Phase 6 user testing.

Phase log

Phase 1 — Tokens. Landed 2026-05-15.

  • src/design-system/v0.3-quietware-tokens.css written. 5.7 KB.
  • Three WOFF2 fonts added at src/fonts/: work-sans-variable.woff2, work-sans-italic-variable.woff2, young-serif.woff2. 287 KB total.
  • src/app.css imports the new tokens file directly after @import "tailwindcss".
  • Inert without data-design="quietware" on <html>. v0.2 surface unaffected.
  • Verified by visual inspection. Manual activation via dev tools toggling the attribute.
  • Palette iterated three times this session (brand-as-semantic → cobalt-pegged square → color.adobe.com primaries). Final values locked in commit on amendment.

Phase 2 — Build flag wiring. Landed 2026-05-15.

  • src/routes/+layout.svelte extended with a $effect block that reads import.meta.env.VITE_LUMOTIA_QUIETWARE at runtime and sets <html data-design="quietware"> when the flag is "1".
  • Hot-reload safety: if the env var is unset between dev rebuilds, the attribute is cleared.
  • Activation: VITE_LUMOTIA_QUIETWARE=1 npm run dev (or npm run build) lights up the quietware tokens. Without the env var, app renders v0.2 unchanged.
  • Combine with data-theme="light" and data-contrast="high" (already wired by v0.2) to reach the light and high-contrast quietware modes.
  • No new dependencies. No bundle-size impact in the off path.

Phase 3 — Status grammar primitives. Landed 2026-05-15.

Architectural finding: both LumotiaStatusPill and LumotiaNotice already shipped in v0.2 Phase 5. Phase 3 became an audit-and-adapt task rather than a new-component build.

  • LumotiaStatusPill (src/lib/components/StatusPill.svelte) audited. Pattern is already accessibility-correct: neutral pill background + neutral label text + role colour confined to a 6×6 px dot. Colour is supplementary, label is always perceivable. Works unchanged across all three quietware modes. No changes shipped.

  • LumotiaNotice (src/lib/ui/LumotiaNotice.svelte) refactored to the left-bar accent pattern. Old version put the role colour on the icon + outline; in quietware light mode that rendered a bright #FFCD00 caution icon faded against cream paper. New version places the role signal on a 4-px solid left border (visible at any contrast level), with the rest of the surround as a soft tone-tinted background plus subtle neutral outer border. Icon, title and body text all use --color-text. Matches Material "banner with leading accent" and IBM Carbon "inline notification" guidance. ARIA semantics (role="alert" for danger, role="status" for the rest) preserved.

  • Design-system-v2 preview route already imports LumotiaNotice and LumotiaStatusPill. The updated Notice renders correctly there with the existing preview content; no additional preview wiring needed.

  • All four tones (info / caution / danger / success) verified by the pattern itself: the visible signal is the left bar, which is border-l-{tone} at 100% opacity, working at any colour intensity. Caution remains a fill-only convention on cream by design.

Phase 4a — Settings tab shell. Landed 2026-05-15.

Architectural finding: the v0.2 SettingsPage.svelte (2 891 LOC after Phase 4a) was already structured as eight numbered sections that align almost 1:1 with the v0.3 plan. The cheapest path to "one section visible at a time" is therefore a tab-shell overlay rather than a file split. Behaviour stays identical to v0.2 when quietware is off; with quietware on, only the active tab's section renders.

  • New LumotiaSettingsTabs.svelte (src/lib/ui/LumotiaSettingsTabs.svelte) implements the WAI-ARIA tabs (automatic activation) pattern. Arrow / Home / End keyboard navigation. Active tab uses the brand left-bar accent (border-l-caution) so it carries the same grammar as the LumotiaNotice refactor.

  • SettingsPage.svelte gained a small reactive isQuietware flag, a MutationObserver watching <html data-design>, and 8 {#if !isQuietware || activeTab === 'X'} wrappers around the existing eight top-level <SettingsGroup> sections. The settings tree is unchanged; only its top-level rendering gate changed.

  • v0.2 fallback behaviour: when data-design="quietware" is absent the tablist does not render and all eight sections stack as before. The search filter still spans every section in v0.2 mode. This is the smallest-possible behavioural change for "one section at a time".

  • Tab IDs in this commit map 1:1 to existing v0.2 section names (start-here / transcription / models / tasks / accessibility / privacy / advanced / help). Phase 4b will restructure to match the plan's canonical names (carving Output from Advanced and Vocabulary from Transcription).

Phase 4b — Settings restructure to canonical tab names. Deferred to post-Phase-5.

Rationale: phase 4a already delivers "one section at a time" under quietware. Renaming the eight tabs to match the canonical plan (Output / Vocabulary carved out as top-level) is labelling polish, not user-value. Page-skeleton sweep (Phase 5) delivers more visible improvement per LOC. Phase 4b will return after Phase 5 lands.

Phase 4d — Palette revision per 2026-05-15 round 4 feedback. Landed 2026-05-15.

The color.adobe.com primaries (#FF0700 / #000AFF / #00FF56 / #FFCD00) earned vividness at the cost of brand identity and accent-vs-caution discipline. Round-4 feedback pulled the system back toward muted-Material values with a clear architectural split:

Atmosphere = warm tactile surface
Status     = red / yellow / green / blue
Brand      = copper-clay amber accent (--color-accent, distinct from caution)
Accessibility = high-contrast override is a different rendering contract

Dark mode (revised, brown-charcoal instead of wine-aubergine):

Token Before (4c) After (4d)
--color-bg #2A1620 #12100E
--color-bg-elevated #34222B #1A1713
--color-bg-card #3E2A33 #211D18
--color-sidebar #1F0F18 #0F0E0C
--color-accent (unset, fell through to v0.2) #C97845
--color-danger #FF2A24 #FF8A8A
--color-caution #FFCD00 #F2C94C
--color-success #00FF56 #79D59B
--color-info #7076FF #8AB4F8

Light mode (revised, semantic values back to Material AA-friendly hues):

Token Before (4c) After (4d)
--color-bg-card #FFFFFF #FFFDF8 (warm white)
--color-bg-elevated #F3EEE6 #F6F1EA
--color-accent (unset) #9D5F32
--color-danger #C54B1F #B3261E
--color-caution #FFCD00 (fill-only) #7A5D00 (passes as text)
--color-success #00852D #1B6B3A
--color-info #0047AB #2457A6

The "caution fill-only on cream" rule retires under the muted palette. Ochre #7A5D00 passes AA as foreground text against cream, so the same single-token-per-role convention applies across all four semantic colours in light mode.

LumotiaNotice opacity rebalance:

Surface Before After
Background tint role at 10% role at 8%
Outer border neutral subtle role at 40%
Left bar role full role full (unchanged)
Icon --color-text role colour
Title / body --color-text --color-text (unchanged)

Phase 4e — High-contrast rendering contract. Landed 2026-05-15.

High-contrast is not a colour variant — it's a different rendering contract that the entire UI subscribes to. The tokens block now publishes behavioural variables alongside the palette overrides, so components can opt into the contract by reading them.

Behavioural tokens (defaults + HC values):

Token Default HC
--grain-opacity 0.06 (dark) / 0.07 (light) 0
--shadow-strength 1 0
--border-width-control 1px 2px
--focus-ring-width 2px 3px
--panel-radius 8px 8px (unchanged for now)

--quietware-texture-opacity retained as a legacy alias pointing at --grain-opacity so Phase 4c controls keep working through the rename.

HC palette tweaks (round-4 feedback):

  • HC light is now true pure-white background (#FFFFFF) + true pure-black text/borders (#000000). Brand atmosphere steps aside completely. Single strong-focus blue #005FCC replaces the accent.
  • HC dark stays pure black #000000 with white borders, semantic muted hues that read clearly. Matches the v0.3 dark feel but at maximum legibility.
  • Hue-based selectors: [data-design="quietware"][data-contrast="high"] matches both base themes; the dark-base variant is scoped via :not([data-theme="light"]) so light-base HC and dark-base HC can diverge.

Phase 4c — Texture-opacity slider + high-contrast toggle. Landed 2026-05-15.

  • New static grain overlay defined in src/design-system/v0.3-quietware-tokens.css. Fixed-position body::after, mix-blend-mode: overlay, opacity driven by --quietware-texture-opacity. Pattern generated inline via SVG feTurbulence (baseFrequency=0.85, numOctaves=2, stitchTiles=stitch). Tile size 240×240, repeated across viewport. pointer-events: none so the overlay never intercepts clicks. Active only under html[data-design="quietware"] and only on the dark and light modes — high-contrast forces opacity to 0.
  • New QuietwareAccessibilityControls.svelte (src/lib/components/) ships two controls:
    • High-contrast toggle, wired through LumotiaToggle. Sets <html data-contrast="high"> so the quietware HC palette block in the tokens CSS activates. Persists via localStorage. Overrides the OS prefers-contrast: more query when explicitly enabled.
    • Texture-intensity slider, range 0.050.08, step 0.005, default 0.06. Sets the --quietware-texture-opacity CSS variable inline on <html> so it overrides the per-mode default in the tokens CSS. Disabled when high-contrast mode is on. Reset button restores the 0.06 default.
  • Component injected into SettingsPage.svelte inside the Accessibility section, gated by {#if isQuietware}. v0.2 fallback unaffected.
  • Persistence path: localStorage keys lumotia:quietware:high-contrast and lumotia:quietware:texture-opacity. Full integration with the central Preferences store is a follow-up; localStorage keeps Phase 4c contained.
  • Verified: npm run check reports 0 errors, 0 warnings across 5706 files.

Regression diary

Empty. Update inline as findings emerge per phase.


References

  • Source brief: inputs/inbox/2026-05-15-lumotia-colour-layout-changes.md.
  • Palette refinement round 1 (brand-as-semantic): inputs/inbox/2026-05-15-re-lumotia-v03-renders-revised-palette-typography-.md.
  • Palette refinement round 2 (cobalt-square peg): chat decision 2026-05-15.
  • Palette refinement round 3 (color.adobe.com primaries): inputs/inbox/2026-05-15-re-lumotia-v03-phase-1-landed-cobalt-pegged-square.md + attached 2.jpeg. Locked.
  • W3C COGA: https://www.w3.org/TR/coga-usable/.
  • WCAG 2.2 Understanding docs: https://www.w3.org/WAI/WCAG22/Understanding/.
  • HMRC accessibility personas: https://personas-prototype.herokuapp.com/.
  • DfE accessibility tools manual: https://accessibility.education.gov.uk/tools-testing/tools.
  • v0.2 release doc: docs/release/v0.2-frontend-overhaul.md (predecessor; reference patterns).