eleven / ocho Public

web: pad the app-thread pane for the floating native header (#237) (#607)

#app-pane (a takeover app's full surface, e.g. Vault) never consumed
--native-top/bottom-inset the way #interface-pane already does, so its
content rendered flush under iOS/Mac's floating header. #app-pane hosting
a nested chat mini-app (a companion app's Chat view) is excluded — its
.chatapp-feed already pads itself independently.
Co-authored-by: Claude <noreply@anthropic.com>
James Adam 949a64585e3d8b34e2d6ccda9557f322ddc07fe8 parent a875d83
2 files changed, +18 −7
  • changelog/2026-07-10-app-panel-top-margin.md +4 −0
  • web/static/style.css +14 −7
diff --git a/changelog/2026-07-10-app-panel-top-margin.md b/changelog/2026-07-10-app-panel-top-margin.md
new file mode 100644
index 0000000..620d973
--- /dev/null
+++ b/changelog/2026-07-10-app-panel-top-margin.md
@@ -0,0 +1,4 @@
+🤖 Fixed personal apps that take over the whole thread (like Vault) rendering
+their content up under the header on iOS/Mac — the header would hide the top
+of the app until you scrolled past it. The app now starts clear of the header,
+matching apps like To-do and Reminders.
diff --git a/web/static/style.css b/web/static/style.css
index cf0dcf5..f6b2303 100644
--- a/web/static/style.css
+++ b/web/static/style.css
@@ -2186,15 +2186,22 @@ html.native .thread-head {
the native composer (drag-drop or the native + button stage into it). The composer
below is hidden, so clear the native bar's height (plus the old 10px breathing room). */
.native-embed .composer-preview { padding-bottom: calc(10px + var(--native-bottom-inset, 0px)); }
-/* The Interface view (an .app-pane scroller) runs under the same floating
- native bars as the feed: pad its top with the injected inset so the app's
- own UI (To-do's add row, Reminders' form) starts clear of the header, and
- end with a real in-flow spacer — not padding-bottom, which WebKit drops at
- a scroller's end — so the last row clears the home indicator/keyboard. */
-.native-embed #interface-pane {
+/* The Interface view AND the Chat/takeover pane (both .app-pane scrollers —
+ #interface-pane and #app-pane) run under the same floating native bars as
+ the feed: pad their top with the injected inset so the app's own UI (To-do's
+ add row, Reminders' form, a takeover app like Vault) starts clear of the
+ header, and end with a real in-flow spacer — not padding-bottom, which
+ WebKit drops at a scroller's end — so the last row clears the home
+ indicator/keyboard. #app-pane hosting a nested chat mini-app instead
+ (:has(> .chatapp-root) — a companion app's Chat view) is excluded: that
+ nested .chatapp-feed already pads itself with the same vars, so double-
+ padding the outer pane too would push it down/shrink it twice over. */
+.native-embed #interface-pane,
+.native-embed #app-pane:not(:has(> .chatapp-root)) {
padding-top: calc(16px + var(--native-top-inset, 0px));
}
-.native-embed #interface-pane::after {
+.native-embed #interface-pane::after,
+.native-embed #app-pane:not(:has(> .chatapp-root))::after {
content: "";
flex: none;
height: calc(16px + var(--native-bottom-inset, 0px));