diff --git a/web/zebra-spaces.html b/web/zebra-spaces.html
index 64d7ae3..cd30161 100644
--- a/web/zebra-spaces.html
+++ b/web/zebra-spaces.html
@@ -24,7 +24,8 @@
html.theme-dark a { color: #9cf; }
html.theme-dark .sub, html.theme-dark .sub a, html.theme-dark .note,
html.theme-dark .status-line { color: #888; }
- html.theme-dark .timeline { border-right-color: #222; }
+ html.theme-dark .timeline,
+ html.theme-dark .cameras-col { border-right-color: #222; }
html.theme-dark .timeline-frame { background: #000; border-color: #222; }
/* buttons + inputs */
html.theme-dark button,
@@ -99,23 +100,34 @@
* controls (kept narrow so the screen share gets maximum pixels).
* Both columns get min-width:0 so they shrink without forcing a
* horizontal scrollbar. */
+ /* three columns: cameras-vertical | screen/timeline | controls.
+ * The cameras column auto-collapses to width:0 when nobody has a
+ * camera on (.hidden), so a typical mic-only room reads as the
+ * original two-column layout. */
.page {
display: grid;
- grid-template-columns: minmax(0, 1fr) minmax(0, 360px);
+ grid-template-columns: minmax(0, auto) minmax(0, 1fr) minmax(0, 360px);
gap: 1.25rem;
align-items: start;
}
- /* collapsed: right column folds away so the screen share fills the
- * full viewport width. The timeline column's right border + padding
- * collapse with it. */
+ .cameras-col {
+ width: 220px; min-width: 0;
+ border-right: 1px solid #ddd; padding-right: 1.25rem;
+ display: flex; flex-direction: column;
+ }
+ .cameras-col.hidden { display: none; }
+ /* collapsed: right column folds away so the screen+cameras layout
+ * fills the viewport. */
.page.controls-collapsed {
- grid-template-columns: minmax(0, 1fr);
- gap: 0;
+ grid-template-columns: minmax(0, auto) minmax(0, 1fr);
+ gap: 1.25rem;
}
.page.controls-collapsed > .controls { display: none; }
.page.controls-collapsed > .timeline { border-right: none; padding-right: 0; }
/* honour the pre-paint pref so first-paint matches saved state */
- html.controls-collapsed-pref .page { grid-template-columns: minmax(0, 1fr); gap: 0; }
+ html.controls-collapsed-pref .page {
+ grid-template-columns: minmax(0, auto) minmax(0, 1fr);
+ }
html.controls-collapsed-pref .page > .controls { display: none; }
html.controls-collapsed-pref .page > .timeline { border-right: none; padding-right: 0; }
.timeline {
@@ -136,12 +148,16 @@
}
@media (max-width: 800px) {
body { padding: 1.25rem; }
- /* stack on mobile, controls first, timeline below */
+ /* stack on mobile: controls first, then any live screen, cameras last */
.page { grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.controls { order: 1; }
.timeline { order: 2;
border-right: none; border-top: 1px solid #ddd;
padding-right: 0; padding-top: 1rem; min-height: 0; }
+ .cameras-col { order: 3;
+ width: 100%; border-right: none; border-top: 1px solid #ddd;
+ padding-right: 0; padding-top: 1rem; }
+ #cameras { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
}
/* never let dynamically-appended