diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte
index 04aa9bd..566912a 100644
--- a/frontend/src/App.svelte
+++ b/frontend/src/App.svelte
@@ -23,6 +23,7 @@
let loading = $state(true)
let route = $state(window.location.hash || '#/')
let updateAvailable = $state(false)
+ let mobileNavOpen = $state(false)
// Check if this is a kiosk token URL before doing anything else
const kioskToken = $derived(window.location.hash.match(/^#\/v\/([A-Z0-9]+)/i)?.[1] ?? '')
@@ -52,6 +53,7 @@
}
window.addEventListener('hashchange', () => {
route = window.location.hash || '#/'
+ mobileNavOpen = false
})
// Periodically check for updates
@@ -92,8 +94,18 @@
{:else}
-
+
+ {#if mobileNavOpen}
+
mobileNavOpen = false} onkeydown={() => {}}>
+ {/if}
+
+
{#if path === '/' || path === ''}
{#if role === 'volunteer_lead'}
diff --git a/frontend/src/app.css b/frontend/src/app.css
index 464472c..f10e75b 100644
--- a/frontend/src/app.css
+++ b/frontend/src/app.css
@@ -170,8 +170,39 @@ tr:hover td { background: rgba(255,255,255,0.02); }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
+/* Mobile header — hidden on desktop */
+.mobile-header { display: none; }
+
@media (max-width: 640px) {
- .sidebar { display: none; }
+ .mobile-header {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ padding: 0.75rem 1rem;
+ background: var(--c-surface);
+ border-bottom: 1px solid var(--c-border);
+ }
+ .mobile-brand { font-weight: 700; font-size: 1rem; }
+ .mobile-brand .accent { color: var(--c-accent); }
+ .hamburger {
+ display: flex; flex-direction: column; gap: 4px;
+ background: none; border: none; padding: 4px; cursor: pointer;
+ }
+ .hamburger span {
+ display: block; width: 20px; height: 2px;
+ background: var(--c-text); border-radius: 1px;
+ transition: transform var(--transition), opacity var(--transition);
+ }
+ .sidebar {
+ position: fixed; top: 0; left: 0; bottom: 0; z-index: 100;
+ transform: translateX(-100%);
+ transition: transform 200ms ease;
+ }
+ .sidebar.open { transform: translateX(0); }
+ .nav-overlay {
+ position: fixed; inset: 0; z-index: 99;
+ background: rgba(0,0,0,0.5);
+ }
.page { padding: 1rem; }
.stats { grid-template-columns: repeat(2, 1fr); }
}
diff --git a/frontend/src/components/Nav.svelte b/frontend/src/components/Nav.svelte
index f1ccede..688267a 100644
--- a/frontend/src/components/Nav.svelte
+++ b/frontend/src/components/Nav.svelte
@@ -1,5 +1,5 @@
-