soulsync/webui/static/video/video-side.css
BoulderBadgeDad 3202197740 video side: Music <-> Video sidebar toggle + video nav shell (isolated)
First slice of the video side, on the experimental branch. Purely additive and
fully isolated from music:
- A Music | Video toggle in the sidebar header; clicking flips body[data-side]
  (remembered in localStorage). The shared shell (logo, user, Support, Version)
  stays; only the nav set + subtitle swap.
- A second sidebar nav (.video-nav) with the video pages — Dashboard, Search,
  Discover, Library, Calendar, Import, Settings, Issues, Help & Docs — shown via
  CSS off body[data-side]. Service Status is hidden on the video side.
- A placeholder content host; real video pages land later.

Isolation contract held: index.html is +51/-0 (no music markup changed), music
JS/CSS untouched, nothing in music references the controller. The controller
(webui/static/video/video-side.js) is a self-contained IIFE wired purely via
addEventListener (no globals, no inline onclick) — so it can't affect music and
doesn't trip the script-split-integrity contract.

Tests: 6 video-shell structural/isolation tests + 64 script-integrity green.
2026-06-13 19:13:54 -07:00

86 lines
2.8 KiB
CSS

/*
* SoulSync — Video side shell styling.
*
* Loaded AFTER style.css so these rules win where specificity ties. Everything
* keys off body[data-side="music|video"] (set by video-side.js). The music side
* is the default and is never affected — these rules only do something once the
* body flips to data-side="video".
*/
/* ── The Music ↔ Video header toggle ───────────────────────────────────── */
.side-toggle {
display: flex;
gap: 3px;
margin-top: 12px;
padding: 3px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 9px;
}
.side-toggle-btn {
flex: 1;
padding: 6px 8px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.03em;
color: var(--text-secondary, #9aa0aa);
background: transparent;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background 0.15s ease, color 0.15s ease;
}
.side-toggle-btn:hover {
color: var(--text-primary, #e8e8ea);
background: rgba(255, 255, 255, 0.04);
}
.side-toggle-btn.active {
background: rgb(var(--accent-rgb, 88 101 242));
color: #fff;
}
/* ── Nav swap: music nav vs video nav ──────────────────────────────────── */
/* The video nav reuses .sidebar-nav layout (same class) — only visibility
differs. Hidden by default (music side); shown when data-side="video". */
.video-nav {
display: none;
}
body[data-side="video"] nav.sidebar-nav:not(.video-nav) {
display: none;
}
body[data-side="video"] .video-nav {
display: flex;
}
/* ── Page visibility per side ──────────────────────────────────────────── */
/* Music pages hidden on the video side; video pages hidden on the music side.
The music router still controls .page.active among music pages; we just hide
the whole set while the video side is showing. */
body[data-side="music"] .page.video-page {
display: none !important;
}
body[data-side="video"] .page:not(.video-page) {
display: none !important;
}
body[data-side="video"] .page.video-page {
display: block;
}
/* ── Service status: not needed on the video side (for now) ─────────────── */
body[data-side="video"] .status-section {
display: none;
}
/* ── Placeholder content (until the real video pages land) ─────────────── */
.video-placeholder {
padding: 48px 40px;
}
.video-placeholder .header-title {
font-size: 22px;
font-weight: 700;
}
.video-placeholder-note {
margin-top: 10px;
color: var(--text-secondary, #9aa0aa);
font-size: 14px;
}