/* ---- App shell: sidebar + routed main content - see Shell.ts. ---- */ .appShell { display: flex; min-height: 100vh; } .sidebar { width: 220px; flex-shrink: 0; background: var(--bg-header); padding: 20px 12px; display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; overflow-y: auto; } .sidebarBrand { font-size: 18px; font-weight: 700; padding: 0 12px 20px; } .sidebarNav { display: flex; flex-direction: column; gap: 2px; flex: 1; } .navSectionLabel { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .05em; padding: 16px 12px 6px; } .navItem { display: block; padding: 10px 12px; border-radius: 8px; color: var(--text); text-decoration: none; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .navItem:hover { background: rgba(255, 255, 255, .06); } .navItem.active { background: var(--accent); color: white; font-weight: 600; } .sidebarLogout { margin-top: 12px; padding: 8px 12px; } .mainContent { flex: 1; min-width: 0; padding: 24px clamp(16px, 3vw, 48px) 80px; } /* ==== Mobile navigation (<=720px) ==== Replaces the sidebar outright - see docs/architecture.md's "Mobile navigation" section for why a bottom sheet was chosen over reshaping the sidebar into a horizontal bar. Every rule below the base `display: none` only ever applies once the 720px media query turns it back on, so none of this affects desktop. */ .mobileTopBar, .mobileNavTrigger, .mobileNavScrim, .mobileNavSheet { display: none; } .mobileTopBar { position: sticky; top: 0; z-index: 3; padding: 14px 16px; background: var(--bg-header); } .mobileBrand { font-size: 16px; font-weight: 700; } /* position:fixed, not sticky - #musicBar below already relies on a fixed wrapper to stay docked regardless of how far #mainContent's own (whole-page, not internally-scrolled) content runs. */ .bottomStack { position: fixed; left: 0; right: 0; bottom: 0; z-index: 15; display: flex; flex-direction: column; } .mobileNavTrigger { align-items: center; justify-content: center; gap: 8px; background: var(--bg-header); border: none; border-top: 1px solid rgba(255, 255, 255, .08); color: var(--text); font-family: inherit; font-size: 13px; font-weight: 600; padding: 13px; padding-bottom: calc(13px + env(safe-area-inset-bottom, 0px)); } .mobileNavScrim { position: fixed; inset: 0; z-index: 20; background: rgba(0, 0, 0, .5); opacity: 0; pointer-events: none; transition: opacity .2s; } .mobileNavScrim.open { opacity: 1; pointer-events: auto; } .mobileNavSheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 21; max-height: 75vh; overflow-y: auto; background: var(--bg-header); border-radius: 16px 16px 0 0; padding: 8px 16px calc(20px + env(safe-area-inset-bottom, 0px)); transform: translateY(100%); transition: transform .22s ease; box-shadow: 0 -8px 24px rgba(0, 0, 0, .3); } .mobileNavSheet.open { transform: translateY(0); } .sheetGrabber { width: 36px; height: 4px; border-radius: 99px; background: var(--muted); margin: 10px auto 6px; } /* Accueil and the (conditional) Listes de lecture row both use this - same visual weight, bookending the "Bibliothèques" group between them, so the one part whose size actually varies (however many libraries Emby returns) reads as visually distinct from the two fixed rows around it. */ .sheetPrimary { display: flex; align-items: center; gap: 10px; width: 100%; background: var(--panel); border: none; border-radius: 10px; color: var(--text); font-family: inherit; font-size: 14px; font-weight: 600; padding: 12px; margin: 4px 0; text-decoration: none; } .sheetPrimary.active { background: var(--accent); color: #fff; } .sheetGrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 4px 0 10px; } .sheetItem { display: flex; align-items: center; gap: 9px; background: var(--panel); border-radius: 10px; color: var(--text); font-size: 13px; padding: 12px 10px; text-decoration: none; } .sheetItem.active { background: var(--accent); color: #fff; font-weight: 600; } .navIcon { width: 20px; height: 20px; flex-shrink: 0; display: block; } .navIcon svg { width: 100%; height: 100%; } .sheetLogout { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; margin-top: 8px; padding: 12px; border: 1px solid rgba(255, 255, 255, .15); border-radius: 10px; color: var(--muted); font-size: 13px; } @media (max-width: 720px) { .appShell { flex-direction: column; } .sidebar { display: none; } .mobileTopBar { display: flex; align-items: center; } .mobileNavTrigger { display: flex; } .mobileNavScrim { display: block; } .mobileNavSheet { display: block; } }