/* ── Layout ──────────────────────────────────────────────────────────────── */ :root { --sidebar-width: 14rem; --sidebar-collapsed-width: 4rem; --topbar-height: 3.5rem; --sidebar-bg: #1a1a2e; --sidebar-hover: rgba(255,255,255,.08); --sidebar-active: rgba(255,255,255,.15); --primary: #4e73df; } body { background: #f4f6fb; min-height: 100vh; } /* Desktop sidebar */ .app-sidebar { position: fixed; top: 0; left: 0; width: var(--sidebar-width); height: 100vh; background: var(--sidebar-bg); color: #fff; display: flex; flex-direction: column; transition: width .2s ease; z-index: 1040; overflow: hidden; } .app-sidebar.collapsed { width: var(--sidebar-collapsed-width); } .sidebar-brand { display: flex; align-items: center; gap: .75rem; padding: 1.25rem 1rem; color: #fff; text-decoration: none; white-space: nowrap; flex-shrink: 0; } .sidebar-brand:hover { color: rgba(255,255,255,.85); } .sidebar-brand-icon { font-size: 1.25rem; flex-shrink: 0; width: 2rem; text-align: center; } .sidebar-brand-text { font-weight: 700; font-size: .95rem; letter-spacing: .02em; transition: opacity .15s; } .app-sidebar.collapsed .sidebar-brand-text, .app-sidebar.collapsed .nav-link span { opacity: 0; pointer-events: none; width: 0; overflow: hidden; } .sidebar-divider { border-color: rgba(255,255,255,.15); margin: 0 1rem .5rem; } .app-sidebar .nav-link { display: flex; align-items: center; gap: .75rem; padding: .65rem 1rem; color: rgba(255,255,255,.7); white-space: nowrap; border-radius: .375rem; margin: .1rem .5rem; transition: background .15s, color .15s; } .app-sidebar .nav-link:hover { color: #fff; background: var(--sidebar-hover); } .app-sidebar .nav-link.active { color: #fff; background: var(--sidebar-active); font-weight: 600; } .app-sidebar .nav-link .fa-fw { flex-shrink: 0; width: 1.25rem; text-align: center; } .sidebar-collapse-btn { background: none; border: none; color: rgba(255,255,255,.5); padding: .75rem 1rem; text-align: right; cursor: pointer; transition: color .15s, transform .2s; margin-top: auto; flex-shrink: 0; } .sidebar-collapse-btn:hover { color: #fff; } .app-sidebar.collapsed .sidebar-collapse-btn { text-align: center; transform: rotate(180deg); } /* Content wrapper shifts right on desktop */ #content-wrapper { margin-left: var(--sidebar-width); min-height: 100vh; display: flex; flex-direction: column; transition: margin-left .2s ease; } #content-wrapper.sidebar-collapsed { margin-left: var(--sidebar-collapsed-width); } /* Top bar */ .topbar { height: var(--topbar-height); position: sticky; top: 0; z-index: 1030; border-bottom: 1px solid rgba(0,0,0,.06); } .main-content { flex: 1; padding-top: 1.5rem; padding-bottom: 7rem; /* mobile: leave room above bottom nav */ } /* ── Mobile bottom navigation ─────────────────────────────────────────────── */ .mobile-bottom-nav { position: fixed; bottom: 0; left: 0; right: 0; height: 3.75rem; background: #fff; border-top: 1px solid rgba(0,0,0,.1); z-index: 1040; box-shadow: 0 -2px 8px rgba(0,0,0,.08); } .mobile-nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .2rem; color: #6c757d; text-decoration: none; font-size: .6rem; font-weight: 500; padding: .25rem 0; transition: color .15s; -webkit-tap-highlight-color: transparent; } .mobile-nav-item i { font-size: 1.1rem; line-height: 1; } .mobile-nav-item.active { color: var(--primary); } .mobile-nav-item:hover { color: var(--primary); } @media (max-width: 767.98px) { #content-wrapper { margin-left: 0 !important; } .main-content { padding-bottom: 7rem; } } @media (min-width: 768px) { .main-content { padding-bottom: 1.5rem; } } /* ── Maps ────────────────────────────────────────────────────────────────── */ #map { height: 18rem; } #history-map { height: 32rem; min-height: 20rem; } @media (max-width: 767.98px) { #history-map { height: 22rem; } } /* ── Alert dropdown ──────────────────────────────────────────────────────── */ #alert-menu { min-width: min(22rem, calc(100vw - 2rem)); max-width: calc(100vw - 2rem); } /* ── Data table ──────────────────────────────────────────────────────────── */ .data-list { min-height: 10rem; } .data-list-empty { padding: 2.5rem 1rem; } .data-list-sort { display: inline-flex; gap: .5rem; align-items: center; padding: 0; color: inherit; font: inherit; font-weight: 700; background: none; border: 0; } .data-list-sort[data-sort-direction="asc"] .fa-sort::before { content: "\f0de"; } .data-list-sort[data-sort-direction="desc"] .fa-sort::before { content: "\f0dd"; } .data-list-actions { display: flex; gap: .5rem; justify-content: flex-end; } /* ── Dashcam / video ─────────────────────────────────────────────────────── */ /* Desktop: truncate long filenames */ @media (min-width: 576px) { .dash-thumb-name { display: none; } .dash-col-file { max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .dash-thumb-td { width: 9rem; padding: 0.25rem; } } /* Mobile: reflow .dash-row into a flex card — thumb + name on left, buttons on right */ @media (max-width: 575.98px) { /* Hide table header */ #local-video-list thead, #dashcam-file-list thead { display: none !important; } /* Row becomes flex */ .dash-row { display: flex !important; align-items: center; gap: .5rem; border-bottom: 1px solid var(--bs-border-color); padding: .25rem .5rem; } /* Hide all cells by default */ .dash-row > td { display: none !important; } /* local-video-list: show thumb cell + actions */ #local-video-list .dash-row > td:first-child, #local-video-list .dash-row > .dash-actions-td { display: flex !important; align-items: center; } #local-video-list .dash-row > td:first-child { flex: 1; min-width: 0; } /* dashcam-file-list: show filename cell + actions (no thumbnail) */ #dashcam-file-list .dash-row > .dash-col-file, #dashcam-file-list .dash-row > .dash-actions-td { display: flex !important; align-items: center; } #dashcam-file-list .dash-row > .dash-col-file { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .8rem; } /* Actions never shrink */ .dash-row > .dash-actions-td { flex-shrink: 0; } /* Thumbnail sizing */ .dash-thumb-td { width: 5rem !important; padding: 0.2rem !important; } .local-video-thumbnail { width: 4.5rem !important; height: auto !important; } /* Filename under thumbnail */ .dash-thumb-name { display: block !important; font-size: .7rem; margin-top: .2rem; } /* Icon-only buttons */ .btn-icon-mobile .btn-label { display: none; } } .local-video-thumbnail { width: 8rem; aspect-ratio: 16 / 9; object-fit: cover; color: transparent; background: var(--bs-gray-200); border-radius: .25rem; } .local-video-player { display: block; width: 100%; max-height: 70vh; background: #000; } /* ── OBD stat cards ──────────────────────────────────────────────────────── */ .stat-card-icon { font-size: 1.75rem; opacity: .2; } /* Shrink long values (e.g. "Disconnected") so they don't wrap */ .obd-val { font-size: 1rem; line-height: 1.2; word-break: break-word; } /* ── Collapsible chevron ──────────────────────────────────────────────────── */ .collapse-chevron { transition: transform .2s ease; } /* ── Misc ────────────────────────────────────────────────────────────────── */ .border-start-primary { border-left: .25rem solid var(--primary) !important; } .border-start-success { border-left: .25rem solid #1cc88a !important; } .border-start-info { border-left: .25rem solid #36b9cc !important; } .border-start-warning { border-left: .25rem solid #f6c23e !important; } .border-start-danger { border-left: .25rem solid #e74a3b !important; } .text-xs { font-size: .75rem; } .text-gray-300 { color: #dddfeb !important; }