The measurement lived inside the view, where the only way to check it was to
run Obsidian on a phone. It moves to a pure `insetFor(leaf, bars, visible)`
against the numbers a phone reports - including the case the events hid: while
the keyboard is up the navbar is behind it, so the deeper of the two is the
inset and adding them would push the composer twice as far as it must go.
Two fixed delays into the keyboard's animation is not where it ends: the
composer read the viewport mid-slide, and on the way out - when the navbar
comes back - nothing re-measured at all, so the panel stayed pushed up or
sat back under the bar. In a sidedock drawer no resize event fires either,
so a phone's keyboard moved nothing there.
The inset is now re-measured every frame until the reading holds still, and
blur is a trigger as much as focus. `inset()` returns what it wrote so the
loop can tell it has settled rather than counting milliseconds.
Obsidian styles every `button` with `justify-content: center`, so the reset
answers with `flex-start` - which also lands on a grid button and overrides
the inline half of its `place-items: center`. The rail's connection dot came
out pinned 12px left of centre inside its own hit area.
The inset only knew the desktop status bar, so on a phone the composer sat
under the navbar - which paints over a leaf instead of shortening it - and
the software keyboard hid it outright. Every bottom bar is measured now, and
the keyboard is read off `visualViewport`: it shrinks the visible area
without resizing the layout, so no workspace event fires and the panel had
no way to know. Focus re-measures once iOS has finished animating the keys in.
The panel asks the shell to fall back to the latest master, so opening it on
a phone lands in the day's thread rather than on a prompt.
The preview fixtures anchor at midday instead of the wall clock: spread over
hours, a run just after midnight pushed half of them into yesterday and
emptied the "Today" group the switcher smoke checks.