Where the panel goes is decided before it has a height. The up-or-down choice
tests a fixed 300px of space below the selection, which has nothing to do with
how tall that particular panel turns out to be, so a long selection opened
downward into a box that ran past the bottom of the viewport. The panel is
position: fixed, so no scrolling brings it back.
Measured on a 975-character selection in a 703px viewport: panel 442..1005,
with Save to Obsidian at 961..990 — three hundred pixels below the fold, and
elementFromPoint on it returns nothing. The same arithmetic ran the other way
for a selection low on the screen, putting the panel's top at -189.
The panel is now re-fitted whenever it grows. Fitting it once at mount proves
nothing: it is mounted empty and forty pixels tall, and the translation and the
capture bar both arrive afterwards. `clampPanelTop` is pure and unit-tested
against the measured numbers; the wiring is verified in a real browser, since a
layout bug is precisely what jsdom cannot see. Same case after the fix: panel
132..695 of 703, save button reachable.
This also means the clipboard fallback for oversized captures runs for the
first time. It is guarded by URI_LIMIT, and reaching that limit takes a note of
several thousand characters — exactly the case where the button to trigger it
was off-screen. A 1,246-character capture now puts 2,712 characters on the
clipboard, frontmatter and all, first and last sentence intact, with no
oversized obsidian:// URL handed to the OS to truncate.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>