- Restore explicit overflow-y:auto on #main-app for mobile (removed in
63f5d64) — implicit coercion from overflow-x:auto is not reliable in
all Safari/WebKit versions.
- Override position:sticky on .readme to position:relative on mobile.
The desktop sticky (left:0) is correct for horizontal scroll, but on
mobile vertical scroll it pinned the 100dvh-tall readme across the
entire viewport, hiding all stacked notes behind it.
body/html have overflow:hidden so scrollTop is a no-op on them.
#main-app is the actual scroll container; use overflow-y:auto on
mobile and target it directly in scrollToNote and the scroll listener.
Three layered fixes for mobile note scrolling:
1. app.css / App.vue: on mobile, override overflow:hidden on html/body
and overflow:visible on #main-app so content from useResizeContainer
(which sets the note-container height to (n+1)*100vh) propagates to
the document and document.body.scrollTop works again.
2. FluxNote.vue: give each .note an explicit height:100dvh on mobile so
the percentage-based height:100% does not resolve against the
inflated container height set by useResizeContainer.
3. StackedNote / StackedPublicNote: replace overflow-y:hidden with
overflow-y:clip on the section. Unlike hidden, clip does not create a
scroll container, so touch events fall through to the page scroll and
the section never feels "draggable" when content fits within the note.
Add left offset to each stacked note so position: sticky activates
during horizontal scroll, pinning notes progressively to the right
of the readme column at calc((index + 1) * var(--note-width)).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contain horizontal overflow within #main-app instead of leaking to the
document, which caused a horizontal scrollbar to consume viewport height
and trigger an unwanted vertical scrollbar. Also fix note pane height
to use 100% instead of 100vh, and switch useResizeContainer to minWidth
so the flex container can grow when the window is wider than the notes.
Add a window resize listener to keep the value accurate on resize.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows repo owners to configure note column width via `"pageWidth": "700px"` in .remanso.json. Applies the value to the --note-width CSS variable and invalidates the cached width so resize/overlay hooks pick it up.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>