diff --git a/frontend/src/app/dashboard/page.tsx b/frontend/src/app/dashboard/page.tsx
index f5a25f0a..0d7a4964 100644
--- a/frontend/src/app/dashboard/page.tsx
+++ b/frontend/src/app/dashboard/page.tsx
@@ -86,7 +86,6 @@ export default function DashboardPage() {
}, []);
// Auth guard
-
useEffect(() => {
if (initialized && !user) router.replace("/login");
}, [user, initialized, router]);
@@ -104,7 +103,6 @@ export default function DashboardPage() {
}
}, [user]);
-
// Load documents
const loadDocuments = useCallback(async () => {
setDocumentsLoading(true);
@@ -187,7 +185,8 @@ export default function DashboardPage() {
);
return (
-
+ // min-w-[375px] ensures the layout never squishes below iPhone SE width
+
setSidebarOpen(!sidebarOpen)}
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index 0dcce0ce..397f6c20 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -372,3 +372,19 @@
.light .prose-chat .hljs-comment { color: oklch(0.5 0 0); }
.light .prose-chat strong { color: oklch(0.2 0 0); }
.light .prose-chat blockquote { color: oklch(0.4 0 0); }
+
+html,
+body {
+ min-width: 375px;
+}
+
+/*
+ * Enable iOS safe-area insets so fixed elements (FAB, modals) clear
+ * the home indicator bar on iPhone SE and similar devices.
+ * Requires viewport-fit=cover in the tag.
+ */
+@supports (padding: env(safe-area-inset-bottom)) {
+ :root {
+ --safe-area-bottom: env(safe-area-inset-bottom);
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/chat/ChatPanel.tsx b/frontend/src/components/chat/ChatPanel.tsx
index 59e58094..e843a439 100644
--- a/frontend/src/components/chat/ChatPanel.tsx
+++ b/frontend/src/components/chat/ChatPanel.tsx
@@ -508,7 +508,7 @@ export default function ChatPanel({ activeDoc, onCitationClick }: Props) {
{/* ── Input Area ─────────────────────────────── */}
-
+
{/* Status / Error Message Area */}
{(isRecording || speechError) && (
@@ -615,7 +615,7 @@ export default function ChatPanel({ activeDoc, onCitationClick }: Props) {
size="icon"
onClick={handleSend}
disabled={!input.trim() || streaming}
- className="h-[44px] w-[44px]"
+ className="h-10 w-10 sm:h-[44px] sm:w-[44px]"
aria-label={streaming ? "Sending message" : "Send message"}
>
{streaming ? (
@@ -633,7 +633,7 @@ export default function ChatPanel({ activeDoc, onCitationClick }: Props) {
variant="ghost"
size="icon"
onClick={() => setShowExportMenu((v) => !v)}
- className="h-[44px] w-[44px] text-muted-foreground hover:text-primary"
+ className="h-10 w-10 sm:h-[44px] sm:w-[44px] text-muted-foreground hover:text-primary"
title={t("chat.exportTitle")}
aria-label={t("chat.exportTitle")}
aria-expanded={showExportMenu}
@@ -648,7 +648,7 @@ export default function ChatPanel({ activeDoc, onCitationClick }: Props) {
role="menu"
aria-label="Export chat"
onKeyDown={handleExportMenuKeyDown}
- className="absolute bottom-full mb-2 right-0 min-w-[160px] rounded-lg border border-border bg-popover p-1 shadow-lg animate-in fade-in slide-in-from-bottom-2 z-50"
+ className="absolute bottom-full mb-2 right-0 min-w-[160px] max-w-[calc(100vw-2rem)] rounded-lg border border-border bg-popover p-1 shadow-lg animate-in fade-in slide-in-from-bottom-2 z-50"
>
diff --git a/frontend/src/components/chat/ChatSessionSidebar.tsx b/frontend/src/components/chat/ChatSessionSidebar.tsx
index d2080f68..e2bd96f8 100644
--- a/frontend/src/components/chat/ChatSessionSidebar.tsx
+++ b/frontend/src/components/chat/ChatSessionSidebar.tsx
@@ -235,9 +235,16 @@ export default function ChatSessionSidebar() {
+ {/*
+ FAB — mobile only (md:hidden).
+ z-20: sits below the Header (z-50) and its backdrop (z-40) so
+ it is not tappable when the document navigation sheet is open.
+ bottom uses safe-area-inset-bottom so the button clears the iOS
+ home indicator on iPhone SE and other small-screen devices.
+ */}
setMobileOpen(true)}
- className="fixed bottom-4 left-4 z-30 h-11 w-11 rounded-full shadow-lg md:hidden"
+ className="fixed bottom-[calc(1rem+env(safe-area-inset-bottom,0px))] left-4 z-20 h-11 w-11 rounded-full shadow-lg md:hidden"
size="icon"
aria-label="Open chat sessions"
aria-controls="mobile-chat-sessions"
@@ -263,7 +270,7 @@ export default function ChatSessionSidebar() {
)}
aria-label="Chat sessions"
aria-hidden={!mobileOpen}
- inert={!mobileOpen ? true : undefined}
+ {...(!mobileOpen ? { inert: true } : {})}
>
{sessionsContent(true)}
diff --git a/frontend/src/components/layout/Header.tsx b/frontend/src/components/layout/Header.tsx
index 211ae95d..1ef13e3b 100644
--- a/frontend/src/components/layout/Header.tsx
+++ b/frontend/src/components/layout/Header.tsx
@@ -253,7 +253,7 @@ export default function Header({
].join(" ")}
aria-label="Mobile navigation"
aria-hidden={!sheetOpen}
- inert={!sheetOpen ? true : undefined}
+ {...(!sheetOpen ? { inert: true } : {})}
>
{/* MOBILE LOGO — clicking navigates to dashboard and closes the sheet */}