Make app fully responsive for smartphones

Layout:
- Remove body min-width: 1280px
- Sidebar hidden on mobile (<768px); replaced by a fixed bottom navigation bar (BottomNav component) with icon + label for all 7 routes
- PageShell main gets className="app-main"; padding overridden to 0 on mobile (68px bottom clearance for bottom nav)
- All page root divs get className="page-body"; mobile override to 12px 14px padding

Dashboard:
- 4-col stat grid → 2×2 on mobile (dash-stat-grid)
- 3-col timing/targets/forecast → single column (dash-three-col)
- 2-col monthly/best-nights → single column (dash-two-col)
- Run order timeline: overflow-x: auto for narrow screens

Targets:
- Filter bar rows get className="filter-row": horizontal scroll on mobile (no-wrap + overflow-x: auto)
- Table gets className="targets-table": columns 3-7 (Size/Fill/Mosaic/Mag/Diff) and 10+ (Vis/Int/Goal/Compare) hidden on mobile, keeping only Type, Name, Filter, Alt

Calendar:
- Split view gets dash-two-col (stacks on mobile)
- Month grid: minWidth 308px + overflowX auto; cell minWidth 44px for touch targets

Compare modal: columns stack vertically on mobile (compare-body / compare-col classes)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 07:35:10 +02:00
parent 2bb80a8475
commit 561de4f13b
11 changed files with 141 additions and 84 deletions
+81 -1
View File
@@ -18,7 +18,6 @@ body {
font-size: 14px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
min-width: 1280px;
}
h1, h2, h3, h4 {
@@ -64,6 +63,87 @@ input:focus, select:focus, textarea:focus {
::-webkit-scrollbar-thumb { background: var(--muted); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-lo); }
/* ─── Bottom navigation (mobile only, hidden on desktop) ───── */
.bottom-nav {
display: none;
position: fixed;
bottom: 0; left: 0; right: 0;
height: 58px;
background: var(--bg-deep);
border-top: 1px solid var(--border);
z-index: 200;
align-items: stretch;
}
.bottom-nav a {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 3px;
color: var(--text-lo);
font-family: var(--font-mono);
font-size: 8px;
letter-spacing: 0.06em;
text-transform: uppercase;
text-decoration: none;
padding: 8px 0;
border-top: 2px solid transparent;
transition: color 0.1s;
}
.bottom-nav a.active {
color: var(--amber);
border-top-color: var(--amber);
}
.bottom-nav a .bnav-icon {
font-size: 18px;
line-height: 1;
}
/* ─── Responsive ────────────────────────────────────────────── */
@media (max-width: 767px) {
body { min-width: 0; }
/* Sidebar hidden; bottom nav shown */
.app-sidebar { display: none !important; }
.bottom-nav { display: flex !important; }
/* Main content: zero out PageShell padding; bottom-nav clearance */
.app-main { padding: 0 0 68px 0 !important; }
/* Page body: reduced padding on mobile */
.page-body { padding: 12px 14px !important; }
/* Dashboard: 4-col stat row → 2×2 */
.dash-stat-grid { grid-template-columns: 1fr 1fr !important; }
/* Dashboard: 2-col grids → single column */
.dash-two-col { grid-template-columns: 1fr !important; }
/* Dashboard: 3-col timing/targets/forecast → single column */
.dash-three-col { grid-template-columns: 1fr !important; }
/* Targets filter bar rows: horizontal scroll */
.filter-row {
flex-wrap: nowrap !important;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
padding-bottom: 4px;
}
.filter-row::-webkit-scrollbar { display: none; }
/* Targets table: show only Type(1) Name(2) Filter(8) Alt(9) */
/* Hide cols 3-7 */
.targets-table th:nth-child(n+3):nth-child(-n+7),
.targets-table td:nth-child(n+3):nth-child(-n+7) { display: none !important; }
/* Hide cols 10 and beyond */
.targets-table th:nth-child(n+10),
.targets-table td:nth-child(n+10) { display: none !important; }
/* Compare modal: stack columns */
.compare-body { flex-direction: column !important; }
.compare-col { border-right: none !important; border-bottom: 1px solid var(--border) !important; }
}
/* Utility classes */
.text-hi { color: var(--text-hi); }
.text-mid { color: var(--text-mid); }