Wrap inputs in <label class="input"> (DaisyUI v5 compound input pattern).
Form uses flex fill so inputs auto-size and the button stays on the right
on a single line regardless of container width.
Replace the minimal centered layout with a full literary/academic
homepage: logged-out users see an editorial hero, manifesto, demo
notes, and ZK primer; logged-in users see a personal launchpad
(greeting, repo tiles, last visited, review queue) followed by the
same editorial content below.
Uses DaisyUI CSS variables throughout (color-mix) so it adapts to
any theme change without hardcoded overrides.
Setting overflow-x: auto forces overflow-y off 'visible' per CSS spec,
which caused an unwanted vertical scrollbar in stacked note sections.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace <a> (no href) with <button> so both elements receive tab focus.
BackButton gets text-base-content to preserve icon color; LinkedNotes
uses btn class="link" to keep the inline text-link appearance.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
<button> gets color:ButtonText from the browser UA stylesheet, making
SVG stroke="currentColor" render black. Add text-base-content to
inherit the DaisyUI theme color like the <a>-based router-links do.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
<button> defaults to color: ButtonText (black) in browsers, unlike <a>
which inherits. Adding color: inherit restores the theme color for the
SVG stroke (which uses currentColor).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace <a> with <button> for the typography icon in HeaderNote so it
receives tab focus — <a> without href is excluded from the tab order.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dark theme was set to "dim" in theme.config.ts while app.css registered
"sunset" as the prefersdark theme. The script's regex required a trailing
comma that didn't exist on the last property, causing silent failures.
chosen* fields are per-browser preferences — localStorage is the correct
and sufficient store for them. Removing data.update from font setters and
stripping chosen* from the GitHub fetch PouchDB write prevents stale PouchDB
data from conflicting with localStorage on reload.
- Use v-model with writable computeds instead of :value+@change so selects
re-sync when the options list changes asynchronously
- Always include currently chosen fonts in sortedFontFamilies so a selected
font not present in .remanso.json fontFamilies still shows in the select
- Initialize userSettings instead of returning early in font setters so
changes made before async GitHub fetch completes are not silently dropped
- Back font choices with localStorage so they survive hard reloads even when
PouchDB/IndexedDB fails silently in the web worker
- Install missing comlink (was in lockfile but not node_modules)
- Add @ts-rest/core and @ts-rest/vue-query (imported but not declared as deps)
- Add declare module '*.vue' shim to shims-vue.d.ts
- Replace arktype validators in ts-rest contract with contract.type<T>() since @ts-rest expects Zod schemas
Move the v-if guard from the outer FontChange wrapper to only the font-family
selects, so ThemeSwap and the font-size select are always visible in the modal
even before userSettings.fontFamilies resolves asynchronously.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All database reads and writes now run off the main thread via a
dedicated worker, eliminating IndexedDB overhead from the frame budget.
- Create data.worker.ts exposing the Data class via Comlink
- Refactor data.ts to export a Comlink-wrapped proxy and a standalone
generateId() pure function (workers can't expose sync methods cleanly)
- Update all 10 call sites to import generateId directly instead of
calling data.generateId()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- resetFiles() no longer clears userSettings so FontChange stays visible
while navigating between repos (old fonts show until new ones load)
- Add _requestId counter to setUserRepo() to discard stale async callbacks
from previous navigations, preventing state corruption on quick nav
- Load savedRepo and userSettings caches in parallel with Promise.all,
reducing yield points so cache hits apply before first render
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Narrow backlinks watcher from entire store to store.files only,
reducing trigger count from ~8 to 2 per navigation
- Defer computation start by 300ms so it runs after the 250ms view
transition animation completes
- Yield to the browser between each file iteration using
scheduler.yield() (with setTimeout fallback) to avoid blocking frames
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevents white space below the app on Android Chrome where the
system nav bar makes 100vh > 100dvh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On Chrome Android, cross-axis stretch doesn't always produce a
definite height for inner flex items. Adding height: 100dvh to
.home ensures flex: 1 on .welcome-world resolves to full viewport.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace space-between with flex-start + margin-top:auto on footer and
add gap to avoid wide spacing while async components are loading.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>