app.js: overflow plus-menu positionMenu() — divide r.left/r.top by zoom
cookbookRunning.js: hamburger dropdown — use window.innerWidth - (rect.right/z)
cookbookServe.js: 5 fixes — toolbar dropdown, launch-more, split-arrow, GPU popup, saved-menu
skills.js: kebab tool menu — divide rect bounds by zoom
colorPicker.js: picker position() — divide rect coords by zoom
emojiPicker.js: picker open — divide rect coords by zoom
theme.js: zone highlights — divide all rect values by zoom
Adds a 'Chat' button to the left of the Save button in the document
editor footer. Clicking it injects a reference into the chat textarea:
[Title](#document-<id>) — <120-char snippet>...
The reference is not the full document content — just a title link
with opening snippet. The user can then send it or edit the message
before sending. This is the first step toward making documents feel
like first-class citizens in agent chat.
getBoundingClientRect() returns zoom-scaled coordinates but
window.innerWidth does not. With ui-scale-125 active, the right-edge
calculation (window.innerWidth - rect.right) mixed coordinate spaces,
causing dropdowns to appear displaced from their hamburger buttons.
Divide window.innerWidth by the computed zoom factor to match the
rect coordinate space. Fixes both cookbookRunning.js (Active tab)
and cookbookServe.js (Serve tab).
CSS: added comprehensive zoom compensation for ALL modal-content
variants (memory, tasks, preset, doclib, gallery, notes-pane,
research, compare, email-lib) and a safety net for user-resized
windows carrying inline height styles.
JS (windowResize.js): _uiZoom() helper reads computed zoom from :root.
Restore path divides saved localStorage dimensions by zoom factor.
Resize-move viewport clamps use zoom-adjusted vh/vw so dragging
never pushes the window beyond the visible area.
Also added docs/improvement-tasks.md as the Ulysses task board.
- Added persistent Scan button to the Serve tab toolbar (was only shown
in empty state, making it impossible to refresh when localStorage had
cached results)
- Hooked into background poll to clear model scan cache (key:
cookbook_cached_models_scan_v1) when downloads transition to done,
so the Serve tab doesn't show stale data after a download completes
Event handler for #hwfit-cache-scan already existed in the codebase but
the button element was never rendered in the HTML template.
The comparison grid hard-codes 2-4 equal columns with no phone breakpoint, so at
390px two models get ~178px columns and four get ~88px columns. Each column is a
full scrolling chat, so content is unreadably over-wrapped and clipped. On
phones (<=768px), stack the panes into a single scrollable column. Desktop is
unaffected.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Setting epSel.value triggered an async change event whose handler
called refreshModels('') — wiping the correct model selection that
refreshModels(settings.default_model) had just applied moments earlier.
The dropdown silently fell back to the alphabetically-first model
(deepseek-v4-flash instead of qwen-3.6-35B-A3B).
Moved the change listener registration to after the settings block
so the async change event fires before any listener exists. The
utility and teacher sections already followed this pattern.