html/body sit above .app in the DOM tree and were left with the
browser default (white background + 8px UA-stylesheet margin) — a gap
invisible against the light theme but a bright white outline around
the whole window in dark mode. Mirrors data-theme onto <html> (so the
dark token overrides actually apply up there) and zeroes the
html/body margin.
Replaces a hardcoded blue (#2563eb) primary button with the semantic
accent token, adds a ShieldAlert icon + heading, and gives it proper
elevation (shadow + radius) to read as a deliberate dialog rather than
a plain bordered box.
Recording/Hardware/Storage/Calendar/Sync/Privacy nav tabs get matching
icons; the active tab now uses the accent color instead of an inverted
fg/bg swap. Check/X/AlertTriangle icons replace ✓/✗/✕/⚠ throughout
(connection test result, close button, third-party-cloud warning
banner, no-egress confirmation). The modal itself gets proper
elevation (shadow + larger radius) instead of a flat bordered box.
Tags/Summary/Action items/Calendar event/Participants/Speakers each
get a matching icon and a consistent uppercase section-header style;
"Generate summary" becomes a proper primary (accent-filled) button;
the reminder bell emoji becomes a Lucide Bell icon that highlights in
the warning color once checked.
Bold/Italic/Heading1/Heading2/List/ListChecks Lucide icons replace the
letter/glyph toolbar buttons (bullet "•" and checkbox "☑" in
particular); export buttons get matching icons. Section labels for
Transcript/Notes get icons too, and the reprocess spinner animates
(respecting prefers-reduced-motion).
Search icon inside the input, Trash2/Download/RotateCcw replacing
emoji, tag chips and the selected-item state now use the semantic
accent tokens instead of a hardcoded blue hex, and list rows get a
hover state + an accent-colored left border when selected.
- Full semantic color token system (surfaces, text, borders, one
accent color) replacing the previous 4-variable set — light/dark
designed together, every pairing checked to >=4.5:1 (WCAG AA).
- Global custom scrollbar styling (thin, theme-aware) — the default
OS scrollbar looked out of place against the app's own chrome.
- ThemeToggle replaces the plain theme <select>.
- Record/Stop buttons and the settings/warning icons are now Lucide
SVG icons instead of Unicode glyphs (●■⚙⚠); the recording indicator
is an animated pulsing dot (paused under prefers-reduced-motion)
instead of a static red dot.
- Elevation (shadow tokens) and consistent radius scale.
Replaces the plain <select> theme dropdown with three icon buttons.
Defaults to "system" (Monitor), matching the existing behavior of
following the OS preference until the user picks an explicit override.
The due-date input is new too — action items previously had no way to
set one, which would have made the reminder checkbox unusable (a
reminder needs a due date to schedule against).
The search box now searches transcripts + notes (not just titles) and
shows a matched snippet per result. FTS5 is word-based rather than
substring-based, a deliberate tradeoff for gaining full-content search.
Replaces the static "Summary"/"Action items" placeholder text with:
generate button (hidden behind a "configure an LLM provider" message
when none is set), live token streaming while generating, rendered
summary + decisions once done, and an editable action-item checklist
with a save step before anything gets confirmed as a task.
Streams tokens for whichever meeting is generating (gated by
summarizingId so a stale stream can't clobber a summary if the user
switches selection mid-generation), and refreshes the selected meeting
once llm://done or confirm_action_items lands.
Types for SummaryFile/ActionItem/LlmStatus and a confirmActionItems
wrapper + onLlmDone listener, so the frontend can consume what
generate_summary/confirm_action_items already produce on the backend.
Also adds errorMessage(): every backend command rejects with
{ kind, message } (see src-tauri/src/error.rs), not a native Error, so
`e instanceof Error` is always false for it and `String(e)` renders as
the literal text "[object Object]" — found by actually clicking
"Generate summary" against an unreachable Ollama endpoint.
Notes and LLM-generated summaries both render untrusted Markdown via
{@html} into a webview with an IPC bridge to the Rust backend, so the
DOMPurify sanitization step is a real security boundary, not cosmetic —
worth one shared implementation instead of a second inline copy that
could drift out of sync.
Traps focus in the recording-consent overlay the same way as Settings.
Adds a visually-hidden aria-live region announcing "Recording
started/paused/stopped" — previously nothing in the header was a live
region, so a non-visual user had no way to learn recording had begun.
Bold/Italic/Bullet-list/Checkbox buttons rendered a bare glyph with
only a title tooltip; add matching aria-label so a screen reader
announces the action rather than the raw Unicode character name.
Moves focus into the dialog on mount, cycles Tab/Shift+Tab within its
focusable elements, and restores focus to whatever had it before the
dialog opened once it closes.
Ctrl+Shift+R toggles recording, Ctrl+, toggles Settings, Escape closes
whichever overlay (consent notice, then Settings) is open. Shortcuts
never hijack typing in an input/textarea/select/contenteditable target;
Escape is exempt from that guard so it always closes an open modal.
"Template apply" from the roadmap item isn't included — there's no
template-selection UI yet (that lands with T8.1 in Phase 8).
A simple rms-fill + peak-marker bar rather than a scrolling waveform —
either satisfies the requirement with far less state. Shows a warning
banner while a capture device reconnect is in progress.