diff --git a/docs/release/v0.3-tactile-quietware.md b/docs/release/v0.3-tactile-quietware.md index a7d79b5..7789b52 100644 --- a/docs/release/v0.3-tactile-quietware.md +++ b/docs/release/v0.3-tactile-quietware.md @@ -232,17 +232,19 @@ Architectural finding: the v0.2 `SettingsPage.svelte` (2 891 LOC after Phase 4a) - 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. Pending. +### Phase 4b — Settings restructure to canonical tab names. Deferred to post-Phase-5. -- Carve **Output** out of `7. Advanced > Output & Capture` (currently at line 2398 in the pre-Phase-4a file) into its own top-level tab. -- Carve **Vocabulary** out of `2. Transcription > Custom vocabulary` (line 1472 in the pre-Phase-4a file) into its own top-level tab. -- Rename the remainder of `2. Transcription` to be subsumed by **Output** + **Vocabulary**, or kept as legacy section pending content audit. -- Final tab order: Start Here / Models / Output / Vocabulary / Tasks / Accessibility / Privacy / Advanced (eight tabs, matching the plan). +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 4c — Texture-opacity slider + high-contrast toggle. Pending. +### Phase 4c — Texture-opacity slider + high-contrast toggle. Landed 2026-05-15. -- Texture-opacity slider in the Accessibility tab, range 0.05–0.08, default 0.06. Persists to existing preferences store. -- High-contrast toggle in the Accessibility tab. Toggle overrides system `prefers-contrast: more` query when set. +- 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/](../../src/lib/components/QuietwareAccessibilityControls.svelte)) ships two controls: + - **High-contrast toggle**, wired through `LumotiaToggle`. Sets `` 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.05–0.08, step 0.005, default 0.06. Sets the `--quietware-texture-opacity` CSS variable inline on `` 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. --- diff --git a/src/design-system/v0.3-quietware-tokens.css b/src/design-system/v0.3-quietware-tokens.css index 653d9e8..e7e0246 100644 --- a/src/design-system/v0.3-quietware-tokens.css +++ b/src/design-system/v0.3-quietware-tokens.css @@ -176,6 +176,32 @@ --quietware-texture-color: rgba(0, 0, 0, 0); } +/* ============================================================ + Static grain overlay. Atmospheric texture across the whole viewport. + Fixed position so it does not scroll. Tile pattern generated inline + via SVG feTurbulence. Opacity driven by --quietware-texture-opacity + (default 0.06 dark / 0.07 light, slider range 0.05 to 0.08 in + advanced settings). mix-blend-mode overlay darkens shadows and + brightens highlights, producing the soft notebook-paper effect. + + pointer-events: none so clicks pass through. z-index 9999 places it + above all content, but content remains fully interactive thanks to + the pointer-events override. + + No texture in high-contrast mode — the [data-contrast="high"] block + above sets --quietware-texture-opacity to 0. + ============================================================ */ +:root[data-design="quietware"] body::after { + content: ""; + position: fixed; + inset: 0; + pointer-events: none; + z-index: 9999; + background-image: url("data:image/svg+xml;utf8,"); + opacity: var(--quietware-texture-opacity); + mix-blend-mode: overlay; +} + /* ============================================================ Reduced motion. Honour OS preference; quietware rules require it. ============================================================ */ diff --git a/src/lib/components/QuietwareAccessibilityControls.svelte b/src/lib/components/QuietwareAccessibilityControls.svelte new file mode 100644 index 0000000..33d20eb --- /dev/null +++ b/src/lib/components/QuietwareAccessibilityControls.svelte @@ -0,0 +1,140 @@ + + +
Tactile Quietware controls
+ + +Texture intensity
+ {(textureOpacity * 100).toFixed(1)}% ++ Strength of the static grain overlay. 5% baseline, 8% upper end. + Slider is disabled when high-contrast mode is active. +
+