group conversations with models and local files
0

Configure Feed

Select the types of activity you want to include in your feed.

Mobile: pin #root to viewport, scroll only inside content panes

The "container expanding past screen" + "page scrolls even with no
content below" symptoms both point to body itself growing past the
visible viewport on iOS. CSS-only constraints (max-width: 100vw,
overflow-x: hidden) weren't enough — iOS treated the body as
scrollable and rubber-banded.

- index.html: html / body get `overflow: hidden`. #root is
`position: fixed; inset: 0; width: 100dvw; height: 100dvh` —
literally bounded to the visible viewport. dvw/dvh respond to
the URL bar without growing the document.
- Add `input, textarea, select, button { min-width: 0 }` so iOS
form intrinsic widths can't push their flex/grid parents wider.
- Bump default input font-size to 16px so iOS Safari doesn't
auto-zoom on focus.
- Wrap AuthForm and ProjectList in a pageScrollerStyle div
(height/width 100%, overflowY auto) so their cards still scroll
on a short viewport even though the body itself can't.

This matches how the ConversationPane already scrolled — outer
shell is fixed, inner panes own their overflow.

+42 -5
+29 -5
index.html
··· 57 57 } 58 58 } 59 59 60 - html, body, #root { 60 + html, body { 61 + margin: 0; 62 + padding: 0; 63 + width: 100%; 61 64 height: 100%; 62 - margin: 0; 65 + overflow: hidden; 63 66 } 64 - html, body, #root { 65 - width: 100%; 67 + /* The app root is pinned to the visible viewport — any element 68 + that goes wider would clip rather than push the page past 69 + the screen edge. Inner scrolling areas (conversation pane, 70 + file pane, modal card) declare their own overflow. 71 + Using dvh / dvw on supporting browsers (iOS Safari 15.4+) so 72 + the URL-bar shift doesn't lop content. */ 73 + #root { 74 + position: fixed; 75 + inset: 0; 76 + width: 100dvw; 77 + height: 100dvh; 66 78 max-width: 100vw; 67 - overflow-x: hidden; 79 + max-height: 100vh; 80 + overflow: hidden; 68 81 } 69 82 /* Word-break long unbreakable strings (URLs, tokens) so they 70 83 can't push a card past the viewport on narrow screens. */ 71 84 p, pre, code, a { 72 85 overflow-wrap: anywhere; 86 + word-break: break-word; 87 + } 88 + /* Stop iOS form controls from imposing their intrinsic min-width 89 + on flex/grid parents. */ 90 + input, textarea, select, button { 91 + min-width: 0; 92 + } 93 + /* Don't let iOS Safari auto-zoom on focused inputs (font-size 94 + < 16px triggers it). 16px is a no-zoom threshold. */ 95 + input, textarea, select { 96 + font-size: 16px; 73 97 } 74 98 body { 75 99 font-family: -apple-system, system-ui, sans-serif;
+13
src/App.tsx
··· 408 408 : 'Sign in with passphrase' 409 409 410 410 return ( 411 + <div style={pageScrollerStyle}> 411 412 <div style={cardStyle}> 412 413 <h2 style={{ marginBottom: 4 }}>{headline}</h2> 413 414 {existingIdentity && method === 'passkey' && ( ··· 505 506 sent to the server). 506 507 </p> 507 508 )} 509 + </div> 508 510 </div> 509 511 ) 510 512 } ··· 768 770 } 769 771 770 772 return ( 773 + <div style={pageScrollerStyle}> 771 774 <div 772 775 style={{ 773 776 maxWidth: 640, ··· 833 836 Create 834 837 </button> 835 838 </div> 839 + </div> 836 840 </div> 837 841 ) 838 842 } ··· 2276 2280 2277 2281 // ─── styles ──────────────────────────────────────────────────────────────── 2278 2282 2283 + // Top-level "page" containers (auth form, project list) take the full 2284 + // viewport, scroll vertically inside, and center their fixed-width card. 2285 + const pageScrollerStyle: React.CSSProperties = { 2286 + height: '100%', 2287 + width: '100%', 2288 + overflowY: 'auto', 2289 + WebkitOverflowScrolling: 'touch', 2290 + boxSizing: 'border-box', 2291 + } 2279 2292 const cardStyle: React.CSSProperties = { 2280 2293 maxWidth: 400, 2281 2294 margin: '40px auto',