Brand guidelines (docs/brand/magnotia-brand-guidelines.md §4) say "Never go
below 12px for any text" and "tertiary text must be ≥18px bold or ≥24px
regular". Audit found 246 sub-12px className sites and 166 cases of
text-text-tertiary paired with body sizes.
Bumped text-[9/10/11px] → text-[12px] across 26 .svelte files in src/lib
and src/routes. Promoted text-text-tertiary → text-text-secondary at body
sizes (12-14px) where context allowed; left placeholder pseudo-states,
ternary-conditional inactive states, and line-through "done" states alone
(8 residual pairings, all decorative).
Affects neurodivergent users on 1366×768 budget hardware most directly.
svelte-check: 0 errors, 0 warnings.
Phase 10b colour push: theme reads as Magnotia, not "subdued generic dark".
Same lightness band as Phase 10a (AA preserved), more chroma across accent,
status tokens, and zone surfaces.
Dark accent: #c98555 -> #d68450 (subtle/hover/glow recomputed).
Light accent: #a06a3e -> #a3683a.
Dark status: success #7ec89a -> #5fc28a, danger #e87171 -> #e85f5f,
warning #e8c86e -> #e8be4a.
Light status: success #2f7549 -> #1f7344, danger #a83838 -> #b32626,
warning #b89a3e -> #a08a1f.
Sensory zones pushed further apart so each zone reads as its own
environment: cave cools toward blue-grey, energy warms toward red-orange,
reset cools toward green. AA on body text verified for every Card surface
in both themes.
Stale accent rgba (201,133,85) replaced with new (214,132,80) across nine
files. --shadow-accent in colors_and_type.css mirrored.
No secondary tint token added: Magnotia's identity is amber-as-the-only-
meaningful-colour. Cheaper to add a second meaningful colour later if a
real need appears than to dilute the discipline now.
Default surfaces, text tokens, and borders untouched per scope.
Two scoped fixes to HotkeyRecorder:
- Append "Esc to cancel." to the recording prompt so the existing Escape
handler is discoverable. srStatus already mentions Escape; no harmonisation
needed.
- Replace animate-pulse-warm on the captured state with a static
bg-success/10 + border-success/40 flash. pulse-warm is the
recording-active keyframe; reusing it for the saved state muddled the
visual vocabulary. The global * transition rule already animates
background-color and border-color over --duration-ui (150ms) with the
brand cubic-bezier ease, so no new keyframe is needed and prefers-reduced-motion
is honoured automatically. Also swapped transition-all for transition-colors
to comply with the no-transition-all brand-motion rule.
Per the project's no-dashes feedback rule (see CORBEL-Main memory
feedback_no_dashes.md), em-dashes in user-visible copy are the single
biggest "AI wrote this" surface tell. Forty-two occurrences across ten
files: ten in SettingsPage's group descriptions and option labels
(audio device picker, vocabulary help, prompt placeholders, model
descriptions), four in FirstRunPage's setup steps, three in
DictationPage / FilesPage / Energy chip tooltips, plus the privacy
bullets ("100% offline, no Python required, no cloud, no accounts,
no telemetry"), the rejection toast, MicroSteps thumb labels, and the
shutdown ritual prompts.
Replacement rule: subordinate-clause em-dashes followed by lowercase
become commas; sentence-break em-dashes followed by capitals become
full stops. Code comments left intact.
One non-em-dash regression caught while reviewing: TasksPage's energy
filter "no selection" placeholder showed "—" as a literal label; the
script changed it to a comma which read as a UI bug. Replaced with
"Any" instead.
Eighteen sites across SegmentedButton, Toggle, HotkeyRecorder,
ModelDownloader, FilesPage, and SettingsPage hardcoded the old amber
rgba(232,168,124,...) for focus rings, glows, and progress bars. After
the Phase 10a a11y darkening of --accent to #c98555, the inline shadows
no longer matched the accent fill they were paired with, so every
focused input rendered a glow at a noticeably different hue from its
border.
Replaced all of them with the current accent rgba(201,133,85,...).
Toggle component also had two motion violations: an active:scale-95
press-shrink and a cubic-bezier(0.16,1,0.3,1) (ease-out-expo) thumb
transition. Both replaced with the brand's --ease curve
(0.2,0.8,0.2,1) and the scale dropped, in line with the record-button
fix in the previous commit.
Removed redundant inline transition-duration overrides on FilesPage
Browse button (the global * rule already sets --duration-ui) and on
ModelDownloader's primary CTA (also dropped its active:scale-[0.97]).
Replace all instances of the legacy product names "Kon" and "Corbie" with
"Magnotia" across user-facing copy, code identifiers, package names, bundle
ids, file paths, and documentation. Preserves the unrelated "konsole" (KDE
terminal) reference and the parent CORBEL company name.
- Renames 10 Rust crates (kon-* → magnotia-*) and the tauri binary
- Updates package.json, tauri.conf.json (productName + identifier)
- Renames CSS classes (kon-rh-* → magnotia-rh-*) and animations
- Renames brand and roadmap docs
- Regenerates Cargo.lock and package-lock.json
Verified: svelte-check passes; pure-rust crates compile under new names.
Adds src/lib/utils/hotkeyValidity.ts with validateHotkey(combo, os)
and wires it into HotkeyRecorder.svelte. Rules:
- X11/Wayland/Linux: reject single-key combos unless the trigger
is F13..F24 (the conventional global-shortcut escape hatch).
- Windows: reject combos whose only modifier is a right-hand
variant (RCtrl/RAlt) — matches Handy #966's failure mode where
RegisterHotKey silently ignores them.
- macOS: reject Fn-only combos and bare-key combos (non-function
keys).
- unknown OS: pass through — better to ship a flawed combo than
reject one we can't validate.
When validation fails, the recorder leaves the previous known-good
hotkey intact and surfaces an inline warning-coloured sentence
explaining why, with actionable copy ("add a modifier", "use the
left-hand equivalent", etc.). The save button disappears because
settings.globalHotkey is never written to — no state drift.
Matches Handy #917 / #1019 / #966 / #956, brief item #5.
Co-authored-by: jars <jakejars@users.noreply.github.com>
webkit2gtk under KDE Wayland does not set e.metaKey on subsequent events
after the compositor intercepts Super — but the Super keydown itself is
still delivered with e.key === "Super". Track pressed modifiers from
raw keydown/keyup and OR with the webkit booleans so combos like Super+E
(which OpenWhispr already registers successfully via evdev) can now be
captured in Kon's recorder.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three correctness fixes to the hotkey recorder based on dogfood logs:
1. Modifier set now includes Super / OS / Hyper (webkit2gtk on Linux
fires e.key === "Super" for the Windows key — previously that key
got captured as the final trigger, producing invalid 'Ctrl+Shift+Super'
strings the evdev parser rejected).
2. resolveTriggerKey() uses e.code (physical, shift-independent key)
to resolve shifted punctuation back to the unshifted name the evdev
parser understands: '+' -> '=', '|' -> '\\', etc. Letters and digits
also use e.code (KeyA -> A, Digit1 -> 1) to avoid layout quirks.
3. Numpad keys intentionally not mapped to main-keyboard equivalents —
they are distinct evdev codes. Leaves the parser to reject them so
the user gets a toast instead of a silently-wrong binding.
Registration failures now surface as a toast and revert
settings.globalHotkey to the last successfully-registered value (if
any), so the UI cannot lie about what is actually bound.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wholesale JS -> TS migration of the frontend — stores, utils, actions,
and all Svelte component scripts adopt type annotations. Compile-time
surfaces (app.d.ts, lib/types/) added for shared DTO types.
Build plumbing:
- package.json: dev:frontend script that runs svelte-kit sync first
- tauri.conf.json: beforeDevCommand points at dev:frontend
- run.sh: dropped the sed-hack that temporarily blanked beforeDevCommand;
now relies on npm run dev:frontend to avoid double-Vite
- jsconfig.json: allowImportingTsExtensions
Preserves all Group 1 behaviour:
- page.svelte.ts keeps loadHistory / loadTasks Tauri-first, no
localStorage; saveTranscriptMeta + mapTranscriptRow + mapTaskRow
intact; update_task_cmd and update_transcript_meta_cmd invocations
carry the correct payload shape.
- Toasts, preferences stores typed without behaviour change.
- Viewer still routes segment edits through saveTranscriptMeta; the
Task 1.5 TODO markers are gone.
taskExtractor.ts is functionally improved during the migration:
- multi-task matches in the same sentence
- list-style shopping-verb expansion (get bread, milk, and cheese)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Second dogfood sprint. Headline fix: Linux now uses native KWin/Mutter
decorations instead of fragile frameless `startResizeDragging`, which
collapsed diagonal corner resize to a single axis and made drag feel
laggy. macOS / Windows keep custom chrome via `useCustomChrome` gate.
Other changes:
- Cross-window preferences sync via `kon:preferences-changed` Tauri
event — theme and font changes propagate live to float/viewer.
- Hotkey recorder rewritten to use capture-phase document listener
gated by $effect; button focus was unreliable in webkit2gtk.
- History page redesigned for cognitive-load hygiene: title-first
compact row, inline title input, Edit popout opening /viewer in
edit mode, clipboard export as .md with YAML frontmatter, manual
tag chips + + Add tag input, header tag filter (cap 7), global
Starred filter, `tag:xyz` search syntax.
- `deriveAutoTags` kept as empty hook for post-Task-7 LLM topic tags;
research found all previous auto-tag chips redundant with row UI.
- Viewer window adds edit mode with debounced-save textarea; native
title renamed to "Kon - Transcription Editor".
- Window minimums updated per GNOME HIG + WCAG reflow research:
main 960x600, float 360x480, editor 560x520.
- Microphone picker filters raw ALSA strings (hw:, plughw:, front:,
sysdefault:, null) and dedupes by CARD=X. New `description` field
on DeviceInfo reads /proc/asound/cards so Blue Yeti shows as "Blue
Microphones" instead of the short "Microphones" card name.
- GPU reporting fixed: get_runtime_capabilities now returns
accelerators=[cpu,vulkan] and whisper.supports_gpu=true, matching
the transcribe-rs whisper-vulkan feature linked unconditionally.
- ResizeHandles kept for macOS/Windows frameless: 12px edges, 20px
corners via CSS vars, pointerdown + setPointerCapture, corners
above edges in z-order, rendered as sibling (not child) of the
animated layout root so `position: fixed` is viewport-relative.
- Dueling drag-region handlers removed — `data-tauri-drag-region` and
manual `startDragging()` were stacked on the same elements; kept
the manual handler which has the button/input early-return logic.
See HANDOVER.md for the full session log and deferred items.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>