mobile: add a phone dashboard on a second port (8443) — Live + Archive
A new mobile dashboard is served on a second host port (8443) mapped to the same backend, so the recorder/supervisor is not duplicated. main.py detects the mobile port via the Host header and serves mobile.html instead of the desktop index. The mobile SPA has two modes: Live (one camera with a selector) and Archive (camera + date + segment list). Video is delivered as server-side H.264 (live.mp4 / play.mp4 transcode) so a plain <video> plays on any phone. Bottom tab bar, dark theme, safe-area aware. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
/* CoRE.Vizion+ — мобильный dashboard (отдельный порт). Тёмная тема, нижние вкладки. */
|
||||
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
|
||||
html, body {
|
||||
margin: 0; height: 100%; background: #0f1115; color: #e6e9ef;
|
||||
font: 15px/1.4 -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
.m-app { display: flex; flex-direction: column; height: 100%; }
|
||||
|
||||
.m-head {
|
||||
height: 44px; flex: none; display: flex; align-items: center; justify-content: center;
|
||||
background: #161a22; border-bottom: 1px solid #272d3a;
|
||||
}
|
||||
.m-brand { font-weight: 700; font-size: 16px; letter-spacing: .3px; }
|
||||
.m-brand span { color: #c0392b; }
|
||||
|
||||
.m-view { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
|
||||
|
||||
.m-bar {
|
||||
flex: none; display: flex; gap: 8px; padding: 8px;
|
||||
background: #161a22; border-bottom: 1px solid #272d3a;
|
||||
}
|
||||
.m-sel, .m-date {
|
||||
flex: 1; min-width: 0; background: #1d2230; color: #e6e9ef; border: 1px solid #272d3a;
|
||||
border-radius: 8px; padding: 10px 12px; font-size: 15px; -webkit-appearance: none; appearance: none;
|
||||
}
|
||||
.m-date { flex: 0 0 auto; }
|
||||
|
||||
.m-player { position: relative; background: #000; flex: none; }
|
||||
.m-player video { width: 100%; aspect-ratio: 16 / 9; display: block; background: #000; object-fit: contain; }
|
||||
.m-hint {
|
||||
position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
|
||||
color: #8b93a7; font-size: 14px; pointer-events: none; text-align: center; padding: 0 16px;
|
||||
}
|
||||
|
||||
.m-seglist { flex: 1; min-height: 0; overflow-y: auto; padding: 8px; -webkit-overflow-scrolling: touch; }
|
||||
.m-seg {
|
||||
display: flex; align-items: center; justify-content: space-between; width: 100%; text-align: left;
|
||||
background: #161a22; color: #e6e9ef; border: 1px solid #272d3a; border-radius: 8px;
|
||||
padding: 13px 14px; margin-bottom: 6px; font-size: 15px; font-variant-numeric: tabular-nums; cursor: pointer;
|
||||
}
|
||||
.m-seg:active { background: #1d2230; }
|
||||
.m-seg.active { background: #c0392b; border-color: #c0392b; color: #fff; }
|
||||
.m-dur { color: #8b93a7; font-size: 13px; }
|
||||
.m-seg.active .m-dur { color: #fff; }
|
||||
.m-empty { color: #8b93a7; text-align: center; padding: 28px 16px; font-size: 14px; }
|
||||
|
||||
.m-tabs {
|
||||
flex: none; display: flex; background: #161a22; border-top: 1px solid #272d3a;
|
||||
padding-bottom: env(safe-area-inset-bottom, 0);
|
||||
}
|
||||
.m-tab {
|
||||
flex: 1; background: none; border: 0; color: #8b93a7; cursor: pointer;
|
||||
padding: 9px 0 11px; font-size: 11px; font-family: inherit;
|
||||
display: flex; flex-direction: column; align-items: center; gap: 3px;
|
||||
}
|
||||
.m-tab .i { font-size: 22px; line-height: 1; }
|
||||
.m-tab.active { color: #fff; }
|
||||
.m-tab.active .i { color: #c0392b; }
|
||||
Reference in New Issue
Block a user