diff --git a/frontend/App.vue b/frontend/App.vue
index 3773154e..64c16f38 100644
--- a/frontend/App.vue
+++ b/frontend/App.vue
@@ -60,6 +60,7 @@ import { useInfoMask } from '@/composables/use-info-mask.js';
import { useRefreshOrchestrator } from '@/composables/use-refresh-orchestrator.js';
import { useShortcuts } from '@/composables/use-shortcuts.js';
import { useSectionTracking } from '@/composables/use-section-tracking.js';
+import { useTheme } from '@/composables/use-theme.js';
const { t } = useI18n();
const store = useMainStore();
@@ -137,6 +138,9 @@ const { loadShortcuts } = useShortcuts({
// Scroll monitoring + section tracking (logic from widgets/Patch.vue)
useSectionTracking();
+// Theme orchestration: initial apply, OS flip listener, preference watcher.
+useTheme();
+
onMounted(() => {
loadingControl();
loadShortcuts();
diff --git a/frontend/components/Nav.vue b/frontend/components/Nav.vue
index 242770f5..cf7ebb1d 100644
--- a/frontend/components/Nav.vue
+++ b/frontend/components/Nav.vue
@@ -1,7 +1,18 @@
+
+
+
+ class="sticky top-[env(safe-area-inset-top)] z-40 w-full border-b bg-background/80 supports-[backdrop-filter:blur(0px)]:bg-background/60 backdrop-blur transition-transform duration-300 ease-out will-change-transform"
+ :class="{ '-translate-y-full': isNavHidden }">
diff --git a/frontend/components/ui/drawer/DrawerContent.vue b/frontend/components/ui/drawer/DrawerContent.vue
index f31b1b3f..fe817ced 100644
--- a/frontend/components/ui/drawer/DrawerContent.vue
+++ b/frontend/components/ui/drawer/DrawerContent.vue
@@ -25,6 +25,7 @@ defineEmits(['close', 'escapeKeyDown']);
'fixed inset-x-0 bottom-0 z-[10001] mt-24 flex h-auto flex-col rounded-t-[14px] border bg-background shadow-lg outline-none',
props.class,
)"
+ :style="{ paddingBottom: 'env(safe-area-inset-bottom)' }"
@escape-key-down="$emit('escapeKeyDown', $event)"
>
// shadcn-vue Sheet 面板:四向滑入,包含 overlay
// 见 refactor/01 阶段 B
+import { computed } from 'vue';
import { DialogContent, DialogOverlay, DialogPortal, DialogTitle, VisuallyHidden } from 'reka-ui';
import { cva } from 'class-variance-authority';
import { cn } from '@/lib/utils';
@@ -30,6 +31,25 @@ const props = defineProps({
onInteractOutside: { type: Function, default: undefined },
});
defineEmits(['close', 'escapeKeyDown']);
+
+// Push content past the iOS safe-area insets so it doesn't render
+// behind the transparent status bar / home indicator. Inline style
+// so consumers' `p-0` doesn't override it.
+const safeAreaStyle = computed(() => {
+ switch (props.side) {
+ case 'top':
+ return { paddingTop: 'env(safe-area-inset-top)' };
+ case 'bottom':
+ return { paddingBottom: 'env(safe-area-inset-bottom)' };
+ case 'left':
+ case 'right':
+ default:
+ return {
+ paddingTop: 'env(safe-area-inset-top)',
+ paddingBottom: 'env(safe-area-inset-bottom)',
+ };
+ }
+});
@@ -39,6 +59,7 @@ defineEmits(['close', 'escapeKeyDown']);
/>