diff --git a/docs/release/v0.3-tactile-quietware.md b/docs/release/v0.3-tactile-quietware.md
index c6a6c0c..be2d7d1 100644
--- a/docs/release/v0.3-tactile-quietware.md
+++ b/docs/release/v0.3-tactile-quietware.md
@@ -351,6 +351,72 @@ LumotiaNotice now reads these via Tailwind arbitrary-value classes (`bg-[var(--n
Per Jake's round-5 spec: yellow stays yellow (visible signal), ochre only appears as small-text ink, and brown/khaki never represents the caution role's primary identity again.
+### Phase 5c — Dictation layout migration. Landed 2026-05-15.
+
+The big layout migration. DictationPage's existing 1 282-LOC structure stays untouched for v0.2; under quietware a new layout renders via `LumotiaPageSkeleton` with five zones matching the mockup:
+
+```
+[Capture header] large Record + status text + secondary support + timer + status pill
+[Slim notice] info-classed browser-preview or danger-classed real errors
+[Primary surface] calm transcript canvas with empty-state typography
+[Action bar] Copy / Save / Extract Tasks / Template / Open Viewer
+[Mono metadata] Smart · model · Local-only or Browser-preview
+```
+
+Implementation pattern: gated `{#if isQuietware}` branch inside the existing `{#if needsDownload}{:else}` structure. The new layout subscribes to ALL existing state bindings (`page.recording`, `page.timerText`, `transcript`, `error`, `tauriRuntimeAvailable`, `modelLoading`, `settings.*`, etc.) and reuses every handler (`toggleRecording`, `copyAll`, `saveTypedText`, `manualExtractTasks`, `applyTemplate`, `invoke("open_viewer_window")`). v0.2 surface is unchanged.
+
+Capture-header content:
+
+- **Record button** (72 px circular) carries the role-correct fill via `--button-record-bg` (red). Recording state pulses; modelLoading state shows the spinner; non-Tauri state goes neutral-disabled. Hover swaps to `--button-record-border`. Focus-visible ring uses `--button-record-bg` at `--wire-opacity-focus`.
+- **Status text** uses Young Serif italic via `font-display`. Four states: Ready to capture / Loading model / Desktop preview mode / Recording…
+- **Secondary support text** in Work Sans body weight. Adapts per state.
+- **Timer** in JetBrains Mono tabular-nums, right aligned.
+- **Status pill** appears when there is something useful to report (recording / transcribing / ready).
+
+Slim notice:
+
+- Browser-preview message renders as `LumotiaNotice tone="info" slim dismissible` with the friendly Phase 5b copy.
+- Real errors render as `LumotiaNotice tone="danger" slim dismissible`.
+- Notice slot stays empty otherwise — no permanent banner clutter.
+
+Transcript surface:
+
+- Empty state: 56 px Mic icon, Young Serif italic "Talk now, think later.", Work Sans support "Press record, or Ctrl+Shift+R." Centred, low-emphasis tertiary text on the calm card.
+- Populated: scrollable transcript at the user's accessibility transcript size.
+
+Bottom action bar:
+
+- Copy (tertiary), Save (primary blue), Extract Tasks (secondary), Template (secondary, applies templates[0] when present), Open Viewer (secondary, gated on Tauri).
+- All disabled until transcript has content; disabled controls render neutral with no wireline.
+
+Mono metadata footer:
+
+- Left: `Smart · {model} · Local only` or `Browser preview`.
+- Right: `{formatMode} · {activeProfile}`.
+- JetBrains Mono, text-tertiary, single line.
+
+What's preserved (no behaviour change):
+
+- Recording events, hotkey listeners (`lumotia:toggle-recording`).
+- Tauri runtime branching (`tauriRuntimeAvailable`, browser-preview state).
+- Live preview hooks (`emit("preview-listening")` etc.).
+- Task extraction (`manualExtractTasks` → `extractTasksForTranscript`).
+- Template apply (`applyTemplate(template)`).
+- Copy / Save paths (`copyAll`, `saveTypedText`).
+- All existing state bindings on `page.*`, `settings.*`, `prefs.*`.
+
+What is NOT done in this commit (out of scope for Phase 5c):
+
+- Files / Tasks / History page migrations (Phases 5d-5f).
+- Real Lumotia wordmark / icon integration (Phase 6, blocked on SVG).
+- Motion audit + decorative animation strip (Phase 7).
+- Template-picker menu in the bottom action bar (currently auto-applies first template; full menu reserved for a follow-up).
+
+Verified:
+
+- `npm run check`: 0 errors, 0 warnings across 5707 files.
+- Browser-preview screenshots show the new layout rendering correctly with the disabled-record state, slim info notice, and empty-state typography.
+
### Phase 4k — Palette architecture hardening (round-9 redirect). Landed 2026-05-15.
Token-hardening pass. No new visual decisions — just plumbing the tokens correctly so the grammar locked in Phase 4j has a system underneath instead of hand-tuned hex values.
diff --git a/src/lib/pages/DictationPage.svelte b/src/lib/pages/DictationPage.svelte
index 296ee1f..09713b3 100644
--- a/src/lib/pages/DictationPage.svelte
+++ b/src/lib/pages/DictationPage.svelte
@@ -14,6 +14,9 @@
import LumotiaCard from "$lib/ui/LumotiaCard.svelte";
import LumotiaEmptyState from "$lib/ui/LumotiaEmptyState.svelte";
import LumotiaNotice from "$lib/ui/LumotiaNotice.svelte";
+ // v0.3 Phase 5c — quietware layout uses the shared page skeleton.
+ import LumotiaPageSkeleton from "$lib/ui/LumotiaPageSkeleton.svelte";
+ import LumotiaButton from "$lib/ui/LumotiaButton.svelte";
import ModelDownloader from "$lib/components/ModelDownloader.svelte";
import { exportTranscript } from "$lib/utils/export.js";
import { extractTasks } from "$lib/utils/taskExtractor.js";
@@ -72,9 +75,28 @@
// Global hotkey listener
let hotkeyHandler = () => toggleRecording();
+ // v0.3 Phase 5c — quietware layout switch. Mirrors the SettingsPage
+ // pattern: reactive flag driven by a MutationObserver on
+ // . When unset (v0.2), the page renders its
+ // existing layout unchanged.
+ let isQuietware = $state(false);
+ let quietwareObserver: MutationObserver | null = null;
+
onMount(async () => {
window.addEventListener("lumotia:toggle-recording", hotkeyHandler);
+ if (typeof document !== "undefined") {
+ const sync = () => {
+ isQuietware = document.documentElement.dataset.design === "quietware";
+ };
+ sync();
+ quietwareObserver = new MutationObserver(sync);
+ quietwareObserver.observe(document.documentElement, {
+ attributes: true,
+ attributeFilter: ["data-design"],
+ });
+ }
+
if (!tauriRuntimeAvailable) {
error = browserPreviewMessage;
return;
@@ -87,6 +109,8 @@
onDestroy(() => {
window.removeEventListener("lumotia:toggle-recording", hotkeyHandler);
clearInterval(timerInterval);
+ quietwareObserver?.disconnect();
+ quietwareObserver = null;
if (page.recording) {
page.recording = false;
page.status = "Ready";
@@ -915,6 +939,134 @@
onComplete={onModelDownloaded}
/>
{:else}
+ {#if isQuietware}
+
+
+ {#if page.recording}Press to stop, or use the global hotkey.
+ {:else if modelLoading}One moment.
+ {:else if !tauriRuntimeAvailable}Local transcription needs the Lumotia desktop app.
+ {:else}Press record, or Ctrl+Shift+R.
+ {/if}
+ Talk now, think later. Press record, or Ctrl+Shift+R.
+ {#if page.recording}Recording…
+ {:else if modelLoading}Loading model
+ {:else if !tauriRuntimeAvailable}Desktop preview mode
+ {:else}Ready to capture
+ {/if}
+
+