diff --git a/.env.example b/.env.example index 4955b72..f2a470c 100644 --- a/.env.example +++ b/.env.example @@ -17,6 +17,8 @@ VOD_PUBLIC_BASE= # Required. Generate with: python -c "import secrets; print(secrets.token_hex(32))" VOD_SECRET_KEY= VOD_SECURE_COOKIES=false +# Content-Security-Policy: true (default) enforces it, false sends it as Report-Only. +VOD_CSP_ENFORCE=true # --- Cloud / External Storage (optional) --- # Dedicated AES-GCM key for provider credentials. Falls back to VOD_SECRET_KEY. diff --git a/CHANGELOG.md b/CHANGELOG.md index fd6c5d6..1c0583c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,10 @@ All notable changes to this project are documented here. The format follows the new "log out everywhere" action (`POST /logout/all`) and every password change sign the account out on all devices. - **Overlay tokens in the query string are off by default.** The bundled - TTS/alert overlay pages pass `?token=`; set `OVERLAY_ALLOW_QUERY_TOKEN=true` - while you use them. The `/tts/api/ack` and `/alerts/api/ack` routes accept - POST only. + TTS/alert overlays read the token from `#token=` (or an old `?token=` URL) + and send it only as a header, so existing OBS sources keep working; move + the token behind `#` to keep it out of server logs. The `/tts/api/ack` and + `/alerts/api/ack` routes accept POST only. - **Resource uploads use an allowlist** (documents, images, audio/video, archives; `VOD_FILES_ALLOWED_EXTENSIONS` overrides it). Existing files with other extensions are no longer served but can still be deleted. @@ -115,6 +116,15 @@ All notable changes to this project are documented here. The format follows with `STREAM_RECORDER_USE_PROXY=true`. - **Backups.** `BACKUP_DIR` defaults to `/backups`; "create backup" runs the script named in `VOD_BACKUP_SCRIPT`. +- **Content-Security-Policy is enforced.** `VOD_CSP_ENFORCE` now defaults to + `true`: inline scripts need the per-request nonce and inline event handlers + (`onclick=` ...) are blocked. Custom templates or overlays with inline + scripts must use `nonce="{{ csp_nonce() }}"`. `VOD_CSP_ENFORCE=false` falls + back to `Content-Security-Policy-Report-Only`. +- **Overlay tokens as headers.** The TTS and alert overlays read the token + from `#token=` (or `?token=`) of their own URL and send it to the API only as + `X-TTS-Token` / `X-Alert-Token`; audio is fetched with the header and played + from a blob URL. Options > Settings shows the recommended OBS URLs. ### Security @@ -123,6 +133,9 @@ All notable changes to this project are documented here. The format follows rate limits and bans. `VOD_TRUSTED_PROXIES` accepts CIDR networks. - Code and dot-directories below `VOD_BASE_DIR` can no longer be deleted as streamer archives. +- WebUI: chat fallbacks escape Twitch chat text, toasts use `textContent`, + banner/hero URLs only reach CSS `url()` through the `css_url` filter, and + the CSP allows the emote hosts (BTTV, FFZ, 7TV, ivr.fi) and `https:` images. ### Fixed @@ -145,6 +158,14 @@ All notable changes to this project are documented here. The format follows ### Added +- WebUI accessibility and design (audit 2026-11-12): native `` modals + with focus handling, one confirmation dialog (`data-confirm`) for restart, + maintenance and deletions, bottom navigation with logout below 768px, + "Log out everywhere" in the rail, bottom navigation and mobile pages, + skip link, labelled fields, AA contrast tokens, unlocked zoom on mobile. + `static/css/tokens.css` is the single token layer; stylesheets load as + parallel ``s. + - GitHub Actions CI (Python 3.10–3.12, ruff, unit tests, shell syntax), Dependabot, contribution and security guidelines. - Web UI in 12 languages, chosen from the browser language or the switcher. diff --git a/WEBUI/i18n.py b/WEBUI/i18n.py index 71cabda..dcc5062 100644 --- a/WEBUI/i18n.py +++ b/WEBUI/i18n.py @@ -143,6 +143,10 @@ def N_(text): N_("Progress"), N_("Volume"), N_("Start playback"), + # static/sv_confirm.js (confirmation dialog) + N_("Please confirm"), + N_("Confirm"), + N_("Cancel"), ) diff --git a/WEBUI/static/alerts_overlay.html b/WEBUI/static/alerts_overlay.html index 9133c27..980069b 100644 --- a/WEBUI/static/alerts_overlay.html +++ b/WEBUI/static/alerts_overlay.html @@ -19,71 +19,7 @@
- + + diff --git a/WEBUI/static/alerts_overlay.js b/WEBUI/static/alerts_overlay.js new file mode 100644 index 0000000..1395b77 --- /dev/null +++ b/WEBUI/static/alerts_overlay.js @@ -0,0 +1,88 @@ +/* Alert sound overlay (OBS browser source). External file: the enforced CSP blocks inline scripts. + Auth: token from #token= of the overlay URL (a legacy ?token= is moved into the fragment), + sent to the API only as X-Alert-Token header. No token or HTTP 401: polling stops. */ +(function () { + const overlay = window.SVOverlay; + const token = overlay.readToken().token; + const hud = document.getElementById("hud"); + const player = document.getElementById("player"); + const AUTH_HEADERS = { "X-Alert-Token": token }; + + function showHud(text) { + hud.textContent = text; + hud.classList.add("show"); + } + + if (!token) { + showHud("Token fehlt – Overlay-URL mit #token=… verwenden"); + return; + } + + const audio = overlay.createAudio(player, AUTH_HEADERS); + let busy = false; + let currentId = null; + + async function ack(id) { + if (!id) return; + try { + await fetch("/alerts/api/ack?id=" + encodeURIComponent(id), { method: "POST", headers: AUTH_HEADERS }); + } catch (e) { + console.error("[alerts-overlay] ack failed for item", id, e); + } + } + + async function tick() { + if (busy) return "ok"; + const res = await fetch("/alerts/api/next", { headers: AUTH_HEADERS }); + if (res.status === 401) return "unauthorized"; + if (!res.ok) return "error"; + const data = await res.json(); + if (!data || !data.item) return "ok"; + const item = data.item; + busy = true; + currentId = item.id; + showHud("🔔 " + (item.label || item.event)); + try { + await audio.load(item.audio_url); + await player.play(); + } catch (e) { + console.error("[alerts-overlay] loading or playing the next alert failed", e); + showHud("click once to unlock audio"); + busy = false; + currentId = null; + } + return "ok"; + } + + const poller = overlay.createPoller(tick, { + interval: 900, + maxInterval: 30000, + label: "alerts next", + onUnauthorized: function () { showHud("Token ungültig – Abfrage angehalten"); }, + }); + + player.addEventListener("ended", async () => { + const id = currentId; + currentId = null; + busy = false; + hud.classList.remove("show"); + audio.release(); + await ack(id); + poller.now(); + }); + + player.addEventListener("error", async () => { + const id = currentId; + currentId = null; + busy = false; + hud.classList.remove("show"); + audio.release(); + await ack(id); + }); + + window.addEventListener("pointerdown", () => { + player.play().catch((e) => console.error("[alerts-overlay] unlock play failed", e)); + }, { once: true }); + + poller.start(); +})(); diff --git a/WEBUI/static/css/a11y.css b/WEBUI/static/css/a11y.css index 2610fd9..53acd1e 100644 --- a/WEBUI/static/css/a11y.css +++ b/WEBUI/static/css/a11y.css @@ -1,4 +1,5 @@ -/* Accessibility helpers — Phase 6 */ +/* Accessibility layer. Linked LAST (components/styles.html) so focus, target size and + dialog rules win over legacy !important declarations in style.css / tube_design_system.css. */ .sr-only { position: absolute !important; width: 1px !important; @@ -11,7 +12,273 @@ border: 0 !important; } -:focus-visible { - outline: 2px solid var(--tube-accent, #f2e58d); - outline-offset: 2px; +/* One focus language: outline in --nebula-focus-ring (>= 3:1 on every surface). */ +:focus-visible, +:where(a, button, input, select, textarea, summary, [tabindex], [role="button"], [role="tab"], [contenteditable="true"]):focus-visible { + outline: 2px solid var(--nebula-focus-ring) !important; + outline-offset: 2px !important; +} +:where(input, select, textarea):focus-visible { + outline-offset: 1px !important; +} +.vod-cb-btn:focus-visible, +.vod-control-bar button:focus-visible, +.mobile-player button:focus-visible, +#vodPlayer:focus-visible { + outline: 2px solid var(--nebula-focus-ring) !important; + outline-offset: 2px !important; + box-shadow: 0 0 0 4px rgba(7, 11, 20, 0.85) !important; +} + +/* Skip link */ +.sv-skip-link { + position: fixed; + top: 8px; + left: 8px; + z-index: 2147483000; + padding: 10px 16px; + border-radius: var(--nebula-radius-sm); + background: var(--nebula-bg-card); + color: var(--nebula-text-main); + font: 600 14px/1.2 var(--nebula-font-sans); + text-decoration: none; + transform: translateY(-200%); +} +.sv-skip-link:focus, +.sv-skip-link:focus-visible { + transform: none; +} +main[tabindex="-1"]:focus { + outline: none !important; +} + +/* Form fields: visible edges (>= 3:1, WCAG 1.4.11) */ +:where(input:not([type="checkbox"], [type="radio"], [type="range"], [type="hidden"], [type="color"]), select, textarea) { + border-color: var(--nebula-field-edge) !important; +} + +/* Target size (WCAG 2.5.8): 20px box + 2px margin keeps a 24px spacing circle free. */ +input[type="checkbox"], +input[type="radio"] { + inline-size: 20px !important; + block-size: 20px !important; + min-inline-size: 20px !important; + margin: 2px !important; + accent-color: var(--nebula-accent-primary); + cursor: pointer; +} +.vod-channel-link, +.nebula-streamer-link, +.ns-module-link, +.sidebar-link { + min-block-size: 24px; + display: inline-flex; + align-items: center; +} +button, [role="button"], input[type="submit"], input[type="button"] { + touch-action: manipulation; +} + +/* Dialogs (native ) */ +.sv-dialog { + inline-size: min(440px, calc(100vw - 32px)); + max-block-size: calc(100dvh - 32px); + padding: 0; + border: 1px solid var(--nebula-border-bright); + border-radius: var(--nebula-radius-lg); + background: var(--nebula-bg-surface); + color: var(--nebula-text-main); + box-shadow: 0 24px 64px rgba(0, 0, 0, 0.7); + overflow: auto; +} +.sv-dialog::backdrop { + background: rgba(4, 8, 16, 0.82); +} +.sv-dialog--wide { + inline-size: min(640px, calc(100vw - 32px)); +} +.sv-dialog__head, +.sv-dialog__foot { + display: flex; + align-items: center; + gap: 10px; + padding: 14px 20px; + background: var(--nebula-bg-card); +} +.sv-dialog__head { + justify-content: space-between; + border-bottom: 1px solid var(--nebula-border); +} +.sv-dialog__foot { + justify-content: flex-end; + border-top: 1px solid var(--nebula-border); +} +.sv-dialog__title-row { + display: flex; + align-items: center; + gap: 8px; + color: var(--nebula-accent-text); +} +.sv-dialog__title { + margin: 0; + font-size: 16px; + font-weight: 700; + color: var(--nebula-text-main); +} +.sv-dialog__body { + display: flex; + flex-direction: column; + gap: 14px; + padding: 20px; +} +.sv-dialog__form { + margin: 0; +} +.sv-dialog__close { + min-inline-size: 32px; + min-block-size: 32px; + border: none; + border-radius: var(--nebula-radius-sm); + background: transparent; + color: var(--nebula-text-secondary); + font-size: 22px; + line-height: 1; + cursor: pointer; +} +.sv-dialog__close:hover { + background: var(--nebula-bg-hover); + color: var(--nebula-text-main); +} +.sv-confirm__msg { + margin: 0; + font-size: 14px; + line-height: 1.5; + color: var(--nebula-text-secondary); +} +.sv-field { + display: flex; + flex-direction: column; + gap: 6px; +} +.sv-field > label { + font-size: 13px; + font-weight: 600; + color: var(--nebula-text-secondary); +} +.sv-field > :is(input, select, textarea) { + inline-size: 100%; + box-sizing: border-box; + padding: 10px 14px; + border: 1px solid var(--nebula-field-edge); + border-radius: var(--nebula-radius-sm); + background: var(--nebula-bg-deep); + color: var(--nebula-text-main); + font-size: 14px; +} + +/* Buttons used by dialogs and confirmations */ +.sv-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-block-size: 36px; + padding: 8px 16px; + border: 1px solid transparent; + border-radius: var(--nebula-radius-sm); + font: 600 13px/1.2 var(--nebula-font-sans); + cursor: pointer; + transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease; +} +.sv-btn--primary { + background: var(--nebula-accent-primary); + color: var(--nebula-text-on-accent); +} +.sv-btn--primary:hover { + background: var(--nebula-accent-primary-hover); +} +.sv-btn--secondary { + background: transparent; + border-color: var(--nebula-field-edge); + color: var(--nebula-text-main); +} +.sv-btn--secondary:hover { + background: var(--nebula-bg-hover); +} +.sv-btn--danger { + background: var(--nebula-danger-bg); + color: var(--nebula-text-on-accent); +} +.sv-btn--danger:hover { + background: var(--nebula-danger-bg-hover); +} +.sv-btn--danger-outline { + background: transparent; + border-color: var(--nebula-status-live-text); + color: var(--nebula-status-live-text); +} +.sv-btn--danger-outline:hover { + background: rgba(240, 68, 88, 0.12); +} +.sv-btn:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +/* Alerts */ +.sv-alert { + padding: 10px 14px; + border-radius: var(--nebula-radius-sm); + border: 1px solid transparent; + font-size: 13px; + font-weight: 500; +} +.sv-alert--error { + background: rgba(240, 68, 88, 0.15); + border-color: rgba(240, 68, 88, 0.45); + color: var(--nebula-status-live-text); +} +.sv-alert--success { + background: rgba(72, 214, 162, 0.12); + border-color: rgba(72, 214, 162, 0.45); + color: var(--nebula-status-success); +} + +/* Bottom navigation <= 768px for desktop-UA pages (rail is hidden there) */ +.sv-bottom-nav__logout { + display: flex; + flex: 1 1 0; + margin: 0; +} +.sv-bottom-nav__logout > button { + inline-size: 100%; +} +.mobile-global-nav a.active, +.mobile-global-nav a[aria-current="page"] { + color: var(--nebula-accent-text) !important; +} +.mobile-global-nav a.active svg { + stroke: var(--nebula-accent-text) !important; +} +.mobile-global-nav span { + font-size: 12px; +} + +body .mobile-global-nav .sv-bottom-nav__logout > button { + background: transparent !important; + border: none !important; + box-shadow: none !important; + color: var(--nebula-text-muted) !important; + font-size: 12px !important; + min-height: 48px !important; + padding: 4px 6px !important; + margin: 0 !important; +} +body .mobile-global-nav .sv-bottom-nav__logout > button:hover { color: var(--nebula-text-main) !important; } + +/* PWA install banner (injected by webui.py) sits above the bottom navigation, not on it. */ +@media (max-width: 768px) { + body:has(.mobile-global-nav) .ns-pwa-install { + bottom: calc(var(--sv-bottom-nav-h) + 8px + env(safe-area-inset-bottom, 0px)); + } } diff --git a/WEBUI/static/css/mobile.css b/WEBUI/static/css/mobile.css index 60ac8fa..5575250 100644 --- a/WEBUI/static/css/mobile.css +++ b/WEBUI/static/css/mobile.css @@ -1,122 +1,83 @@ /* Mobile page styles extracted from style.css — Phase 6 */ /* MOBILE_INDEX */ -body.page-mobile-index{ margin:0; font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background:#0b0d11; color:#fff; padding-bottom:80px; -webkit-tap-highlight-color: transparent; } -body.page-mobile-index .header{ padding:16px; background:#18181b; border-bottom:1px solid #27272a; font-weight:800; font-size:20px; display:flex; justify-content:space-between; align-items:center; position:sticky; top:0; z-index:10; } -body.page-mobile-index .section{ padding:16px; } -body.page-mobile-index .section-title{ font-size:13px; color:#a1a1aa; margin-bottom:12px; text-transform:uppercase; letter-spacing:0.05em; font-weight:600; } -body.page-mobile-index .card{ background:#1f1f23; padding:16px; border-radius:12px; margin-bottom:12px; display:flex; align-items:center; justify-content:space-between; text-decoration:none; color:#fff; border:1px solid #27272a; transition:0.2s; } -body.page-mobile-index .card:active{ transform:scale(0.98); background:#27272a; } -body.page-mobile-index .live-card{ border-color:rgba(239,68,68,0.3); background:rgba(239,68,68,0.05); } -body.page-mobile-index .badge{ background:#27272a; padding:4px 8px; border-radius:6px; font-size:12px; color:#a1a1aa; } -body.page-mobile-index .live-badge{ background:#ef4444; color:white; padding:4px 8px; border-radius:6px; font-size:12px; font-weight:bold; box-shadow:0 0 10px rgba(239,68,68,0.4); } -body.page-mobile-index .mobile-live-start{ - display:flex; - gap:8px; - margin-bottom:12px; +body.page-mobile-index .nav { + position: fixed; + bottom: 0; + left: 0; + right: 0; + backdrop-filter: blur(10px); + display: flex; + justify-content: space-around; + align-items: center; + z-index: 20; + padding-bottom: env(safe-area-inset-bottom); } -body.page-mobile-index .mobile-live-start input{ - flex:1; - min-width:0; - background:#1f1f23; - border:1px solid #27272a; - color:#fff; - padding:12px; - border-radius:8px; - outline:none; +body.page-mobile-index .nav a { + text-decoration: none; + font-size: var(--sv-min-text); + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + width: 100%; + padding: 8px 0; } -body.page-mobile-index .mobile-live-start input:focus{ border-color:#ef4444; } -body.page-mobile-index .mobile-live-start button{ - flex-shrink:0; - width:48px; - border:none; - border-radius:8px; - background:#ef4444; - color:#fff; - font-size:14px; - cursor:pointer; -} -body.page-mobile-index .nav{ position:fixed; bottom:0; left:0; right:0; height:60px; background:rgba(24,24,27,0.95); backdrop-filter:blur(10px); border-top:1px solid #27272a; display:flex; justify-content:space-around; align-items:center; z-index:20; padding-bottom:env(safe-area-inset-bottom); } -body.page-mobile-index .nav a{ color:#71717a; text-decoration:none; font-size:10px; display:flex; flex-direction:column; align-items:center; gap:4px; width:100%; padding:8px 0; } -body.page-mobile-index .nav a.active{ color:#f59e0b; } -body.page-mobile-index .nav-icon{ font-size:20px; } /* MOBILE_STREAMER */ -body.page-mobile-streamer{ margin:0; font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background:#0b0d11; color:#fff; padding-bottom:80px; } -body.page-mobile-streamer .header{ padding:12px 16px; background:#18181b; border-bottom:1px solid #27272a; display:flex; align-items:center; gap:16px; position:sticky; top:0; z-index:100; } -body.page-mobile-streamer .back-btn{ font-size:24px; text-decoration:none; color:#fff; padding:4px; } -body.page-mobile-streamer .page-title{ font-weight:800; font-size:18px; flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } -body.page-mobile-streamer .controls{ padding:16px; background:#121214; border-bottom:1px solid #27272a; } -body.page-mobile-streamer .btn-row{ display:flex; gap:8px; margin-bottom:12px; overflow-x:auto; padding-bottom:4px; } -body.page-mobile-streamer .btn{ background:#27272a; color:#fff; border:1px solid #3f3f46; padding:8px 12px; border-radius:8px; font-size:13px; font-weight:600; white-space:nowrap; text-decoration:none; cursor:pointer; display:flex; align-items:center; gap:6px; } -body.page-mobile-streamer .btn-primary{ background:#f59e0b; border-color:#d97706; } -body.page-mobile-streamer .btn-danger{ background:rgba(239,68,68,0.2); color:#fca5a5; border-color:rgba(239,68,68,0.4); } -body.page-mobile-streamer .search-row{ display:flex; gap:8px; } -body.page-mobile-streamer .search-input{ flex:1; background:#000; border:1px solid #3f3f46; padding:8px 12px; border-radius:8px; color:#fff; outline:none; } -body.page-mobile-streamer .tabs{ display:flex; padding:12px 16px; gap:10px; overflow-x:auto; border-bottom:1px solid #27272a; } -body.page-mobile-streamer .tab{ padding:8px 16px; background:#1f1f23; border-radius:20px; color:#a1a1aa; text-decoration:none; font-size:14px; font-weight:600; white-space:nowrap; border:1px solid #27272a; display:flex; align-items:center; gap:6px; } -body.page-mobile-streamer .tab.active{ background:#f59e0b; color:white; border-color:#f59e0b; } -body.page-mobile-streamer .badge{ background:rgba(255,255,255,0.2); padding:2px 6px; border-radius:4px; font-size:10px; } -body.page-mobile-streamer .list{ padding:16px; display:grid; gap:16px; } -body.page-mobile-streamer .video-card{ background:#18181b; border-radius:12px; overflow:hidden; border:1px solid #27272a; } -body.page-mobile-streamer .thumb-area{ position:relative; aspect-ratio:16/9; display:block; } -body.page-mobile-streamer .thumb{ width:100%; height:100%; object-fit:cover; } -body.page-mobile-streamer .dur{ position:absolute; bottom:6px; right:6px; background:rgba(0,0,0,0.8); padding:2px 6px; border-radius:4px; font-size:11px; font-weight:600; } -body.page-mobile-streamer .meta{ padding:12px; } -body.page-mobile-streamer .title{ font-weight:600; font-size:14px; margin-bottom:6px; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; color:#fff; text-decoration:none; } -body.page-mobile-streamer .info{ font-size:12px; color:#a1a1aa; margin-bottom:12px; } -body.page-mobile-streamer .actions{ display:flex; gap:8px; border-top:1px solid #27272a; padding-top:12px; } -body.page-mobile-streamer .act-btn{ flex:1; text-align:center; padding:6px; background:#27272a; border-radius:6px; font-size:12px; color:#a1a1aa; text-decoration:none; border:1px solid #3f3f46; } -body.page-mobile-streamer .pagination{ display:flex !important; flex-direction:column !important; justify-content:center !important; gap:12px !important; padding:16px 12px 24px !important; align-items:stretch !important; width:100% !important; } -body.page-mobile-streamer .pagination-pages{ display:flex !important; flex-direction:row !important; flex-wrap:wrap !important; justify-content:center !important; align-items:center !important; gap:8px !important; width:100% !important; } -body.page-mobile-streamer .pagination-nav-row{ display:flex !important; flex-direction:row !important; flex-wrap:wrap !important; justify-content:center !important; align-items:center !important; gap:10px !important; width:100% !important; } -body.page-mobile-streamer .pagination-page{ display:inline-flex !important; align-items:center !important; justify-content:center !important; min-width:44px !important; width:auto !important; height:44px !important; padding:0 12px !important; border-radius:10px !important; border:1px solid rgba(255,255,255,0.14) !important; background:rgba(255,255,255,0.06) !important; color:#f5f5f5 !important; font-size:15px !important; font-weight:700 !important; text-decoration:none !important; line-height:1 !important; box-sizing:border-box !important; flex:0 0 auto !important; } -body.page-mobile-streamer .pagination-page.is-current{ background:rgba(242,229,141,0.18) !important; border-color:rgba(242,229,141,0.55) !important; color:#fff3a9 !important; } -body.page-mobile-streamer .empty{ text-align:center; padding:40px; color:#52525b; } -/* MOBILE_PLAYER */ -body.page-mobile-player{ margin:0; background:#000; color:#fff; height:100vh; height:100dvh; display:flex; flex-direction:column; overflow:hidden; font-family:-apple-system, sans-serif; } - - -body.page-mobile-player .video-container{ flex: 2; position:relative; background:#000; display:flex; align-items:center; justify-content:center; min-height:0; } -body.page-mobile-player .chat-container{ flex: 1; background:#0e0e10; border-top:1px solid #333; display:flex; flex-direction:column; min-height:0; } - -body.page-mobile-player video{ width:100%; height:100%; object-fit:contain; } - -body.page-mobile-player .overlay-header{ position:absolute; top:0; left:0; right:0; padding:10px; background:linear-gradient(to bottom, rgba(0,0,0,0.8), transparent); z-index:50; display:flex; justify-content:space-between; pointer-events:none; } -body.page-mobile-player .back-btn{ pointer-events:auto; color:white; text-decoration:none; font-size:24px; text-shadow:0 1px 3px rgba(0,0,0,0.8); padding:5px; } -body.page-mobile-player .title-block{ min-width:0; max-width:72%; text-align:right; pointer-events:auto; } -body.page-mobile-player .title{ font-size:12px; color:rgba(255,255,255,0.8); text-shadow:0 1px 2px black; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } -body.page-mobile-player .mobile-vod-meta{ margin-top:2px; color:rgba(255,255,255,0.62); font-size:10px; font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; text-shadow:0 1px 2px black; } - -body.page-mobile-player .chat-list{ flex:1; overflow-y:auto; padding:10px 10px 40px 10px; font-size:13px; line-height:1.4; } -body.page-mobile-player .chat-line{ margin-bottom:4px; word-wrap:break-word; } -body.page-mobile-player .u{ font-weight:700; color:#a970ff; margin-right:4px; } -body.page-mobile-player .m{ color:#efeff1; } -body.page-mobile-player .t{ color:#555; font-size:10px; margin-right:4px; } - -body.page-mobile-player.is-landscape-active{ - flex-direction: row; +body.page-mobile-streamer .title { + display: -webkit-box; } -body.page-mobile-player.is-landscape-active .video-container{ flex: 1 1 100%; } -body.page-mobile-player.is-landscape-active .chat-container, -body.page-mobile-player.is-landscape-active .chat-container.chat-panel-tabs{ - display: none !important; +body.page-mobile-streamer .pagination-pages { + display: flex !important; + flex-direction: row !important; + flex-wrap: wrap !important; + justify-content: center !important; + align-items: center !important; + gap: 8px !important; + width: 100% !important; } -body.page-mobile-player.is-landscape-active.landscape-chat-open .video-container{ - flex: 1 1 66.666% !important; - width: 66.666% !important; - max-width: 66.666% !important; +body.page-mobile-streamer .pagination-page { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-width: 44px !important; + width: auto !important; + height: 44px !important; + padding: 0 12px !important; + border-radius: var(--nebula-radius-sm) !important; + border: 1px solid rgba(255,255,255,0.14) !important; + background: rgba(255,255,255,0.06) !important; + color: var(--nebula-text-main) !important; + font-size: var(--sv-text-md) !important; + font-weight: 700 !important; + text-decoration: none !important; + line-height: 1 !important; + box-sizing: border-box !important; + flex: 0 0 auto !important; } -body.page-mobile-player.is-landscape-active.landscape-chat-open .chat-container, -body.page-mobile-player.is-landscape-active.landscape-chat-open .chat-container.chat-panel-tabs{ - display: flex !important; - flex: 0 0 33.334% !important; - width: 33.334% !important; - max-width: 33.334% !important; - min-width: 33.334% !important; - border-top: none; - border-left: 1px solid #333; +body.page-mobile-streamer .pagination-page.is-current { + background: rgba(242,229,141,0.18) !important; + border-color: rgba(242,229,141,0.55) !important; + color: #fff3a9 !important; +} +/* MOBILE_PLAYER */ +body.page-mobile-player { + height: 100vh; + height: 100dvh; +} +body.page-mobile-player .video-container { + min-height: 0; +} +body.page-mobile-player .title { + font-size: var(--sv-text-xs); + color: rgba(255,255,255,0.8); + text-shadow: 0 1px 2px black; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } - -@media (orientation: landscape){ +@media (orientation: landscape) { /* Fallback before JS marks is-landscape-active */ - body.page-mobile-player{ flex-direction: row; } + body.page-mobile-player { + flex-direction: row; + } } diff --git a/WEBUI/static/css/tokens.css b/WEBUI/static/css/tokens.css index 320b3f1..5284152 100644 --- a/WEBUI/static/css/tokens.css +++ b/WEBUI/static/css/tokens.css @@ -16,6 +16,7 @@ --nebula-border: #26344F; /* Feine, dezente Konturen */ --nebula-border-subtle: rgba(38, 52, 79, 0.6); --nebula-border-bright: #3B4E73; + --nebula-field-edge: #66789C; /* Formularfeld-Kanten: >= 3:1 auf allen Flaechen (WCAG 1.4.11) */ --nebula-border-glow: rgba(77, 99, 255, 0.4); /* Cosmic Glow */ /* Primary & Accent Spectrum */ @@ -24,16 +25,23 @@ --nebula-accent-highlight: #BB78FF; /* Violetter Highlight-Akzent */ --nebula-accent-magenta: #E45DC5; /* Dezenter Magenta-Akzent */ --nebula-accent-cyan: #69C9FF; /* Sekundärer Cyan-Akzent */ + --nebula-accent-text: #8494FF; /* Akzent als Textfarbe: >= 5:1 auf allen Flaechen */ + --nebula-focus-ring: #8494FF; /* Einheitliche Fokusfarbe (>= 3:1 auf allen Flaechen) */ /* Status Colors */ --nebula-status-live: #F04458; /* Live-Anzeige (Red) */ --nebula-status-success: #48D6A2; /* Erfolgsstatus (Green/Mint) */ --nebula-status-warning: #F2BC61; /* Warnung (Amber/Gold) */ + --nebula-status-live-text: #F2667A; /* Live/Fehler als Text: >= 4.5:1 auf allen Flaechen */ + --nebula-danger-bg: #D42A40; /* Danger-Buttons: Weiss darauf 4.99:1 */ + --nebula-danger-bg-hover: #BC2236; + --nebula-accent-primary-hover: #3F55F0; + --nebula-text-on-accent: #FFFFFF; /* Text auf Primaer-/Danger-Flaechen (4.62:1 / 4.99:1) */ /* Typography Colors */ --nebula-text-main: #F3F5FC; /* Haupttext (Strahlendes Eisweiß) */ --nebula-text-secondary: #A2AEC8; /* Sekundärtext */ - --nebula-text-muted: #75839D; /* Dezenter Text / Metadaten */ + --nebula-text-muted: #8A97B0; /* Dezenter Text / Metadaten: >= 4.5:1 auf allen Flaechen (vorher #75839D, 3.62:1 auf active) */ --nebula-text-inverse: #070B14; /* Kontrasttext auf Akzenten */ /* Typography Stacks */ @@ -41,12 +49,14 @@ --nebula-font-mono: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; /* Gradients & Glows */ - --nebula-gradient-primary: linear-gradient(135deg, #4D63FF 0%, #9365FF 100%); + --nebula-gradient-primary: linear-gradient(135deg, #4D63FF 0%, #4D63FF 100%); /* Vollton: Weiss 4.62:1 (Verlaufsende #9365FF hatte 3.79:1) */ --nebula-gradient-hero: linear-gradient(180deg, rgba(7, 11, 20, 0) 0%, rgba(7, 11, 20, 0.95) 100%); --nebula-gradient-cosmic: radial-gradient(circle at 50% 0%, rgba(147, 101, 255, 0.15) 0%, rgba(7, 11, 20, 0) 70%); --nebula-glow-blue: 0 0 20px rgba(77, 99, 255, 0.35); --nebula-glow-purple: 0 0 20px rgba(147, 101, 255, 0.35); --nebula-glow-live: 0 0 12px rgba(240, 68, 88, 0.55); + --nebula-shadow-brand: 0 2px 10px rgba(77, 99, 255, 0.3); + --nebula-scrim: rgba(0, 0, 0, 0.85); /* Badges ueber Thumbnails */ /* Geometry & Rhythm */ --nebula-radius-xs: 4px; @@ -54,12 +64,27 @@ --nebula-radius-md: 12px; --nebula-radius-lg: 16px; --nebula-radius-full: 9999px; + --nebula-radius-xl: 24px; + /* Type scale (restyle 2026-11-12): every px font-size in the stylesheets maps here */ + --sv-text-xs: 12px; + --sv-text-sm: 13px; + --sv-text-md: 14px; + --sv-text-base: 16px; + --sv-text-lg: 18px; + --sv-text-xl: 20px; + --sv-text-2xl: 24px; + --sv-text-3xl: 28px; + --sv-text-4xl: 32px; + --sv-text-5xl: 40px; + --sv-text-6xl: 48px; --nebula-rail-width: 72px; + --sv-bottom-nav-h: 64px; /* Hoehe der unteren Navigationsleiste ohne safe-area */ + --sv-min-text: 12px; /* Mindestschriftgroesse fuer Labels/Metadaten */ /* 2. NAMESPACE MAPPINGS FOR SYSTEM INTEGRATION */ /* --ns-* mappings */ --ns-bg-canvas: var(--nebula-bg-root); - --ns-bg-sidebar: var(--nebula-bg-root); + --ns-bg-sidebar: var(--nebula-bg-deep, #0B1220); --ns-bg-surface: var(--nebula-bg-surface); --ns-bg-surface-raised: var(--nebula-bg-card); --ns-bg-surface-hover: var(--nebula-bg-hover); @@ -67,7 +92,7 @@ --ns-border-subtle: var(--nebula-border); --ns-border-medium: var(--nebula-border-bright); --ns-border-strong: var(--nebula-border-glow); - --ns-border-focus: var(--nebula-accent-primary); + --ns-border-focus: var(--nebula-focus-ring); --ns-text-primary: var(--nebula-text-main); --ns-text-secondary: var(--nebula-text-secondary); --ns-text-muted: var(--nebula-text-muted); @@ -77,11 +102,13 @@ --ns-brand-crimson-subtle: rgba(77, 99, 255, 0.15); --ns-live-red: var(--nebula-status-live); --ns-recording-amber: var(--nebula-status-warning); + --ns-warm: var(--nebula-status-warning); + --ns-warm-2: #E8A33D; --ns-online-green: var(--nebula-status-success); --ns-platform-twitch: var(--nebula-accent-secondary); --ns-drive-blue: var(--nebula-accent-cyan); - --ns-font-sans: var(--nebula-font-sans); - --ns-font-mono: var(--nebula-font-mono); + --ns-font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + --ns-font-mono: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; /* --tube-* & generic root */ --tube-bg: var(--nebula-bg-root); @@ -127,4 +154,73 @@ --silo-border-base: var(--nebula-border); --silo-text-main: var(--nebula-text-main); --silo-text-muted: var(--nebula-text-secondary); -} \ No newline at end of file + + /* 3. LEGACY ALIASES (consolidated from the former :root blocks in style.css and + tube_design_system.css; effective cascade value kept). New code uses --nebula-*. */ + --glass-hover: var(--tube-surface-2); + --radius: var(--tube-radius); + --bg-card: rgba(255, 255, 255, 0.06); + --bg-1: #0b0f14; + --bg-2: #0a0d12; + --ink: #e5e7eb; + --sr-surface: rgba(18, 22, 22, 0.94); + --sr-surface-2: rgba(24, 29, 29, 0.92); + --sr-line: rgba(226, 232, 240, 0.12); + --sr-line-strong: rgba(226, 232, 240, 0.2); + --sr-text: #f3f4f0; + --sr-text-2: #c8d1cc; + --sr-muted: #8f9c96; + --sr-warm: #f28c28; + --sr-warm-2: #ffb15f; + --sr-shadow: 0 22px 60px rgba(0, 0, 0, 0.42); + --ns-bg: #0b0d10; + --ns-panel: rgba(9, 18, 16, 0.82); + --ns-line: rgba(188, 224, 210, 0.12); + --ns-line-strong: rgba(188, 224, 210, 0.2); + --ns-text: #f3fbf8; + --ns-text-2: #c8ddd5; + --ns-muted: #8ea79e; + --ns-purple: var(--tube-accent); + --ns-purple-2: var(--tube-accent-hover); + --ns-cyan: #26d9d0; + --ns-green: #65d8ac; + --ns-shadow: 0 24px 70px rgba(0, 0, 0, 0.45); + --ns-soft: #cbd5e1; + --ns-accent: #7c5cff; + --ns-accent-2: #22d3ee; + --ns-live: #ff3b5f; + --ns-good: #22c55e; + --ns-radius: 8px; + --ns-bg-0: #050909; + --ns-bg-1: #07100f; + --ns-gold: #e8c060; + --tube-radius: 10px; + --tube-rail: 76px; + --sidebar: #0c0d0f; + --surface: #111316; + --surface-raised: #17191d; + --surface-hover: #1c1f23; + --surface-active: #202329; + --border-strong: rgba(255, 255, 255, 0.12); + --text-primary: #f2f3f5; + --text-secondary: #979ba3; + --brand: #d8eb72; + --brand-hover: #e4f58b; + --brand-muted: rgba(216, 235, 114, 0.12); + --warning: #efc66b; + --offline: #737780; + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 14px; + --radius-card: 10px; + --tube-focus: 0 0 0 3px rgba(242, 229, 141, 0.28); + --ns-platform-youtube: var(--nebula-status-live); + --ns-rail-width: 68px; + --ns-radius-xs: 4px; + --ns-radius-sm: 6px; + --ns-radius-md: 8px; + --ns-radius-lg: 12px; + --ns-radius-full: 9999px; + --ns-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.5); + --ns-shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.85); +} diff --git a/WEBUI/static/css/tube_design_system.css b/WEBUI/static/css/tube_design_system.css index a66f19d..94404ef 100644 --- a/WEBUI/static/css/tube_design_system.css +++ b/WEBUI/static/css/tube_design_system.css @@ -1,115 +1,38 @@ -@import url('tokens.css'); - -:root { - /* Canvas & Base Surfaces (NEBULA Cosmic Palette) */ - --ns-bg-canvas: var(--nebula-bg-root, #070B14); - --ns-bg-sidebar: var(--nebula-bg-deep, #0B1220); - --ns-bg-surface: var(--nebula-bg-surface, #111A2B); - --ns-bg-surface-raised: var(--nebula-bg-card, #151F33); - --ns-bg-surface-hover: var(--nebula-bg-hover, #1A2740); - --ns-bg-surface-active: var(--nebula-bg-active, #202C48); - - /* Precision Borders */ - --ns-border-subtle: var(--nebula-border, #26344F); - --ns-border-medium: var(--nebula-border-bright, #3B4E73); - --ns-border-strong: var(--nebula-border-glow, rgba(77, 99, 255, 0.4)); - --ns-border-focus: var(--nebula-accent-primary, #4D63FF); - - /* Typography */ - --ns-font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - --ns-font-mono: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; - --ns-text-primary: var(--nebula-text-main, #F3F5FC); - --ns-text-secondary: var(--nebula-text-secondary, #A2AEC8); - --ns-text-muted: var(--nebula-text-muted, #75839D); - --ns-text-inverse: var(--nebula-text-inverse, #070B14); - - /* Authentic NEBULA Cosmic Streaming Brand & States */ - --ns-brand-crimson: var(--nebula-accent-primary, #4D63FF); - --ns-brand-crimson-hover: var(--nebula-accent-secondary, #9365FF); - --ns-brand-crimson-subtle: rgba(77, 99, 255, 0.15); - - --ns-live-red: var(--nebula-status-live, #F04458); - --ns-recording-amber: var(--nebula-status-warning, #F2BC61); - --ns-online-green: var(--nebula-status-success, #48D6A2); - --ns-platform-twitch: var(--nebula-accent-secondary, #9365FF); - --ns-platform-youtube: #F04458; - --ns-drive-blue: var(--nebula-accent-cyan, #69C9FF); - - /* Geometry & Rhythm */ - --ns-rail-width: 68px; - --ns-radius-xs: 4px; - --ns-radius-sm: 6px; - --ns-radius-md: 8px; - --ns-radius-lg: 12px; - --ns-radius-full: 9999px; - - /* Elevations & Glow */ - --ns-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.5); - --ns-shadow-md: 0 6px 20px rgba(0, 0, 0, 0.65); - --ns-shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.85); - --ns-glow-crt: 0 0 16px rgba(77, 99, 255, 0.4); - --ns-glow-nebula: 0 0 24px rgba(147, 101, 255, 0.45); -} - /* Base Reset & Layout Frame */ -*, *::before, *::after { +*, +*::before, +*::after { box-sizing: border-box; } - body.ns-platform { - margin: 0; - padding: 0; - background-color: var(--ns-bg-canvas); color: var(--ns-text-primary); font-family: var(--ns-font-sans); - font-size: 14px; + font-size: var(--sv-text-md); line-height: 1.5; -webkit-font-smoothing: antialiased; - display: flex; - min-height: 100vh; overflow-x: hidden; } - /* ========================================================= 1. COMMAND RAIL (PERSISTENT NAVIGATION) ========================================================= */ .ns-command-rail { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: var(--ns-rail-width); - background-color: var(--ns-bg-sidebar); - border-right: 1px solid var(--ns-border-subtle); - display: flex; - flex-direction: column; - align-items: center; - padding: 16px 0; - z-index: 1000; user-select: none; } - .ns-rail-brand { margin-bottom: 24px; } - .ns-brand-glyph { width: 40px; height: 40px; - border-radius: var(--ns-radius-md); - background: linear-gradient(135deg, #17231C 0%, #111A15 100%); border: 1px solid var(--ns-border-medium); - color: var(--ns-brand-crimson); display: flex; align-items: center; justify-content: center; font-family: var(--ns-font-mono); font-weight: 800; - font-size: 18px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + font-size: var(--sv-text-lg); text-decoration: none; } - .ns-rail-nav { display: flex; flex-direction: column; @@ -117,7 +40,6 @@ body.ns-platform { width: 100%; align-items: center; } - .ns-rail-item { width: 44px; height: 44px; @@ -130,27 +52,18 @@ body.ns-platform { background: transparent; border: 1px solid transparent; position: relative; - transition: all 0.15s ease; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease; cursor: pointer; } - .ns-rail-item svg { width: 20px; height: 20px; } - .ns-rail-item:hover { color: var(--ns-text-primary); background-color: var(--ns-bg-surface-hover); border-color: var(--ns-border-subtle); } - -.ns-rail-item.is-active { - color: var(--ns-brand-crimson); - background-color: var(--ns-brand-crimson-subtle); - border-color: var(--silo-border-glow, rgba(121, 255, 138, 0.35)); -} - .ns-rail-item.is-active::before { content: ''; position: absolute; @@ -158,14 +71,8 @@ body.ns-platform { top: 10px; bottom: 10px; width: 3px; - border-radius: 0 3px 3px 0; - background-color: var(--ns-brand-crimson); + border-radius: 0 var(--nebula-radius-xs) var(--nebula-radius-xs) 0; } - -.ns-rail-spacer { - flex: 1; -} - .ns-rail-footer { display: flex; flex-direction: column; @@ -173,26 +80,22 @@ body.ns-platform { width: 100%; align-items: center; } - .ns-logout-btn { background: transparent; border: none; padding: 0; margin: 0; } - /* ========================================================= 2. MAIN APPLICATION WORKSPACE ========================================================= */ .ns-app-main { margin-left: var(--ns-rail-width); flex: 1; - min-width: 0; display: flex; flex-direction: column; background-color: var(--ns-bg-canvas); } - .ns-workspace-header { height: 64px; padding: 0 32px; @@ -202,28 +105,24 @@ body.ns-platform { border-bottom: 1px solid var(--ns-border-subtle); background-color: var(--ns-bg-canvas); } - .ns-header-title-block h1 { margin: 0; - font-size: 18px; + font-size: var(--sv-text-lg); font-weight: 700; letter-spacing: -0.01em; color: var(--ns-text-primary); } - .ns-header-title-block p { margin: 0; - font-size: 12px; + font-size: var(--sv-text-xs); color: var(--ns-text-muted); } - .ns-workspace-content { padding: 28px 32px 64px; max-width: 1720px; width: 100%; margin: 0 auto; } - /* ========================================================= 3. HERO TELEMETRY STRIP (DASHBOARD) ========================================================= */ @@ -233,25 +132,16 @@ body.ns-platform { gap: 20px; align-items: center; padding: 14px 20px; - border-radius: var(--ns-radius-lg); background-color: var(--ns-bg-surface); - border: 1px solid var(--ns-border-subtle); margin-bottom: 24px; } - -.ns-telemetry-item { - display: flex; - align-items: center; - gap: 10px; -} - .ns-status-indicator { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--ns-radius-full); - font-size: 11px; + font-size: var(--sv-min-text); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; @@ -259,37 +149,26 @@ body.ns-platform { color: var(--ns-online-green); border: 1px solid rgba(16, 185, 129, 0.2); } - .ns-status-indicator.is-recording { background-color: rgba(225, 29, 72, 0.1); color: var(--ns-brand-crimson); border-color: rgba(225, 29, 72, 0.25); } - .ns-pulse-dot { width: 6px; height: 6px; border-radius: 50%; background-color: currentColor; } - .ns-telemetry-stat { - font-size: 12px; + font-size: var(--sv-text-xs); color: var(--ns-text-secondary); } - .ns-telemetry-stat strong { color: var(--ns-text-primary); font-family: var(--ns-font-mono); } - /* Storage Bar In Telemetry */ -.ns-storage-meter { - display: flex; - align-items: center; - gap: 12px; -} - .ns-meter-track { flex: 1; height: 6px; @@ -298,13 +177,10 @@ body.ns-platform { overflow: hidden; position: relative; } - .ns-meter-fill { height: 100%; - background: linear-gradient(90deg, #3b82f6, var(--ns-brand-crimson)); border-radius: var(--ns-radius-full); } - /* ========================================================= 4. DASHBOARD OPERATIONS GRID ========================================================= */ @@ -316,7 +192,6 @@ body.ns-platform { gap: 24px; margin-bottom: 32px; } - .ns-card-panel { background-color: var(--ns-bg-surface); border: 1px solid var(--ns-border-subtle); @@ -325,29 +200,21 @@ body.ns-platform { display: flex; flex-direction: column; } - .ns-panel-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; } - .ns-panel-head h2 { margin: 0; - font-size: 13px; + font-size: var(--sv-text-sm); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ns-text-muted); } - /* Quick Launch Input */ -.ns-quick-launch-form { - display: flex; - gap: 8px; -} - .ns-input-field { flex: 1; background-color: var(--ns-bg-surface-raised); @@ -355,16 +222,13 @@ body.ns-platform { border-radius: var(--ns-radius-md); color: var(--ns-text-primary); padding: 10px 14px; - font-size: 13px; + font-size: var(--sv-text-sm); font-family: inherit; - outline: none; transition: border-color 0.15s ease; } - .ns-input-field:focus { border-color: var(--ns-brand-crimson); } - .ns-btn { display: inline-flex; align-items: center; @@ -372,67 +236,24 @@ body.ns-platform { gap: 8px; padding: 10px 16px; border-radius: var(--ns-radius-md); - font-size: 13px; + font-size: var(--sv-text-sm); font-weight: 600; cursor: pointer; border: 1px solid transparent; - transition: all 0.15s ease; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease; text-decoration: none; font-family: inherit; } - .ns-btn-primary { background-color: var(--ns-brand-crimson); - color: #fff; } - .ns-btn-primary:hover { background-color: var(--ns-brand-crimson-hover); } - .ns-btn-secondary { - background-color: var(--ns-bg-surface-raised); - color: var(--ns-text-secondary); border-color: var(--ns-border-subtle); } - -.ns-btn-secondary:hover { - background-color: var(--ns-bg-surface-hover); - color: var(--ns-text-primary); - border-color: var(--ns-border-medium); -} - /* Live Chips */ -.ns-chips-row { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-top: 14px; -} - -.ns-channel-chip { - padding: 4px 10px; - border-radius: var(--ns-radius-sm); - background-color: var(--ns-bg-surface-raised); - border: 1px solid var(--ns-border-subtle); - color: var(--ns-text-secondary); - font-size: 12px; - font-weight: 500; - text-decoration: none; - transition: all 0.15s ease; -} - -.ns-channel-chip:hover { - border-color: var(--ns-border-medium); - color: var(--ns-text-primary); -} - -.ns-channel-chip.is-live { - border-color: rgba(239, 68, 68, 0.4); - color: #fff; - background-color: rgba(239, 68, 68, 0.12); -} - /* ========================================================= 5. STREAMER DIRECTORY (HYBRID CARDS / LIST) ========================================================= */ @@ -442,123 +263,24 @@ body.ns-platform { justify-content: space-between; margin-bottom: 18px; } - .ns-section-header h2 { - font-size: 16px; + font-size: var(--sv-text-base); font-weight: 700; margin: 0; } - -.ns-streamer-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); - gap: 16px; -} - -.ns-streamer-card { - background-color: var(--ns-bg-surface); - border: 1px solid var(--ns-border-subtle); - border-radius: var(--ns-radius-lg); - padding: 18px; - display: flex; - flex-direction: column; - gap: 14px; - transition: all 0.15s ease; -} - -.ns-streamer-card:hover { - border-color: var(--ns-border-medium); - background-color: var(--ns-bg-surface-raised); -} - -.ns-streamer-card-head { - display: flex; - align-items: center; - gap: 14px; -} - -.ns-streamer-avatar-box { - width: 48px; - height: 48px; - border-radius: var(--ns-radius-md); - overflow: hidden; - background-color: var(--ns-bg-surface-hover); - position: relative; - flex-shrink: 0; - border: 1px solid var(--ns-border-subtle); -} - -.ns-streamer-avatar-box img { - width: 100%; - height: 100%; - object-fit: cover; -} - -.ns-streamer-info { - flex: 1; - min-width: 0; -} - -.ns-streamer-name { - font-weight: 700; - font-size: 15px; - color: var(--ns-text-primary); - margin-bottom: 2px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.ns-badge-row { - display: flex; - align-items: center; - gap: 6px; -} - .ns-pill { - font-size: 10px; + font-size: var(--sv-min-text); font-weight: 700; text-transform: uppercase; padding: 2px 6px; border-radius: var(--ns-radius-xs); letter-spacing: 0.02em; } - -.ns-pill-offline { - background-color: var(--ns-bg-surface-hover); - color: var(--ns-text-muted); -} - .ns-pill-live { background-color: rgba(239, 68, 68, 0.15); color: var(--ns-live-red); border: 1px solid rgba(239, 68, 68, 0.3); } - -.ns-pill-drive { - background-color: rgba(59, 130, 246, 0.15); - color: var(--ns-drive-blue); -} - -.ns-streamer-metrics { - display: grid; - grid-template-columns: 1fr 1fr; - padding-top: 12px; - border-top: 1px solid var(--ns-border-subtle); - font-size: 12px; -} - -.ns-metric-col span { - display: block; - color: var(--ns-text-muted); - font-size: 11px; -} - -.ns-metric-col strong { - font-family: var(--ns-font-mono); - color: var(--ns-text-secondary); -} - /* ========================================================= 6. CINEMATIC VIDEO ARCHIVE GRID ========================================================= */ @@ -568,16 +290,14 @@ body.ns-platform { gap: 24px 18px; margin-top: 24px; } - .ns-video-card { display: flex; flex-direction: column; background-color: transparent; border-radius: var(--ns-radius-md); position: relative; - transition: all 0.15s ease; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease; } - .ns-thumb-frame { position: relative; width: 100%; @@ -587,7 +307,6 @@ body.ns-platform { background-color: #12141c; border: 1px solid var(--ns-border-subtle); } - .ns-thumb-frame img { width: 100%; height: 100%; @@ -595,11 +314,9 @@ body.ns-platform { display: block; transition: transform 0.25s ease; } - .ns-video-card:hover .ns-thumb-frame img { transform: scale(1.03); } - .ns-card-overlay-top { position: absolute; top: 8px; @@ -609,50 +326,31 @@ body.ns-platform { justify-content: space-between; pointer-events: none; } - .ns-card-overlay-bottom { position: absolute; bottom: 8px; right: 8px; pointer-events: none; } - .ns-overlay-chip { padding: 2px 6px; border-radius: var(--ns-radius-xs); - font-size: 11px; + font-size: var(--sv-min-text); font-weight: 700; background-color: rgba(9, 10, 15, 0.85); backdrop-filter: none; color: #fff; font-family: var(--ns-font-mono); } - -.ns-watch-bar { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 3px; - background-color: rgba(255, 255, 255, 0.2); -} - -.ns-watch-fill { - display: block; - height: 100%; - background-color: var(--ns-brand-crimson); -} - .ns-video-meta { padding: 10px 4px 4px; display: flex; flex-direction: column; gap: 4px; } - .ns-video-title { margin: 0; - font-size: 14px; + font-size: var(--sv-text-md); font-weight: 600; line-height: 1.35; color: var(--ns-text-primary); @@ -662,37 +360,20 @@ body.ns-platform { overflow: hidden; text-decoration: none; } - .ns-video-title:hover { color: #fff; } - .ns-video-subline { - font-size: 12px; + font-size: var(--sv-text-xs); color: var(--ns-text-muted); display: flex; align-items: center; gap: 6px; } - .ns-video-subline strong { color: var(--ns-text-secondary); font-weight: 500; } - -.ns-card-actions { - display: flex; - align-items: center; - gap: 6px; - margin-top: 8px; - opacity: 0; - transition: opacity 0.15s ease; -} - -.ns-video-card:hover .ns-card-actions { - opacity: 1; -} - .ns-action-btn-mini { width: 28px; height: 28px; @@ -706,7 +387,6 @@ body.ns-platform { cursor: pointer; text-decoration: none; } - .ns-action-btn-mini:hover { background-color: var(--ns-bg-surface-hover); color: var(--ns-text-primary); @@ -719,102 +399,20 @@ body.ns-platform.page-streamer .main { padding: 24px 32px !important; background-color: var(--ns-bg-canvas) !important; } - -body.ns-platform .streamer-hero { - background-color: var(--ns-bg-surface) !important; - border: 1px solid var(--ns-border-subtle) !important; - border-radius: var(--ns-radius-lg) !important; - padding: 24px !important; - margin-bottom: 24px !important; -} - /* 16:9 Video Cards Elevation */ -body.ns-platform .video-grid { - display: grid !important; - grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)) !important; - gap: 20px 16px !important; -} - body.ns-platform .video-card { - background-color: var(--ns-bg-surface) !important; - border: 1px solid var(--ns-border-subtle) !important; - border-radius: var(--ns-radius-md) !important; overflow: hidden !important; - transition: all 0.2s ease !important; - box-shadow: none !important; + transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease, transform 0.2s ease !important; } - body.ns-platform .video-card:hover { border-color: var(--ns-border-medium) !important; background-color: var(--ns-bg-surface-raised) !important; - transform: translateY(-2px) !important; -} - -body.ns-platform .thumb-wrap { - aspect-ratio: 16 / 9 !important; - border-radius: 0 !important; - border-bottom: 1px solid var(--ns-border-subtle) !important; - overflow: hidden !important; } - -body.ns-platform .thumb-wrap img { - width: 100% !important; - height: 100% !important; - object-fit: cover !important; - transition: transform 0.25s ease !important; -} - -body.ns-platform .video-card:hover .thumb-wrap img { - transform: scale(1.04) !important; -} - /* Typography on Archive Cards */ -body.ns-platform .card-body { - padding: 12px !important; -} - -body.ns-platform .video-title { - font-size: 13px !important; - font-weight: 600 !important; - color: var(--ns-text-primary) !important; - line-height: 1.35 !important; - display: -webkit-box !important; - -webkit-line-clamp: 2 !important; - -webkit-box-orient: vertical !important; - overflow: hidden !important; - margin-bottom: 6px !important; -} - -body.ns-platform .video-meta { - font-size: 11px !important; - color: var(--ns-text-muted) !important; -} - /* Action Buttons Restraint */ -body.ns-platform .card-actions { - padding: 8px 12px 12px !important; - border-top: 1px solid var(--ns-border-subtle) !important; - gap: 6px !important; - display: flex !important; -} - -body.ns-platform .card-actions .action-btn { - border-radius: var(--ns-radius-sm) !important; - background: var(--ns-bg-surface-raised) !important; - border: 1px solid var(--ns-border-subtle) !important; - color: var(--ns-text-secondary) !important; - transition: all 0.15s ease !important; -} - -body.ns-platform .card-actions .action-btn:hover { - background: var(--ns-bg-surface-hover) !important; - color: #fff !important; - border-color: var(--ns-border-medium) !important; -} /* ========================================================================== STREAMER DETAIL & VIDEO ARCHIVE COMPLETE REDESIGN ("STREAMVAULT COMMAND") ========================================================================== */ - /* 1. Viewport & Main Container Fixes */ body.ns-platform.page-streamer .ns-app-main, body.ns-platform.page-streamer .main { @@ -823,203 +421,16 @@ body.ns-platform.page-streamer .main { padding: 0 !important; background-color: var(--ns-bg-canvas) !important; } - /* Remove legacy sidebar wrapper artifacts if rendered */ body.ns-platform.page-streamer > .sidebar:not(.ns-command-rail) { display: none !important; } - /* 2. Streamer Command Header (Hero) */ -body.ns-platform .streamer-command-hero { - padding: 32px 40px 24px; - background: linear-gradient(180deg, #11131c 0%, var(--ns-bg-canvas) 100%); - border-bottom: 1px solid var(--ns-border-subtle); - display: flex; - flex-direction: column; - gap: 20px; -} - -body.ns-platform .hero-top-row { - display: flex; - align-items: center; - justify-content: space-between; - flex-wrap: wrap; - gap: 16px; -} - -body.ns-platform .hero-title-group { - display: flex; - align-items: center; - gap: 18px; -} - -body.ns-platform .hero-avatar { - width: 56px; - height: 56px; - border-radius: var(--ns-radius-md); - background-color: var(--ns-bg-surface-raised); - border: 1px solid var(--ns-border-medium); - display: flex; - align-items: center; - justify-content: center; - font-size: 20px; - font-weight: 800; - color: var(--ns-brand-crimson); -} - -body.ns-platform .hero-title-group h1 { - margin: 0 0 4px 0; - font-size: 26px; - font-weight: 800; - letter-spacing: -0.02em; - color: var(--ns-text-primary); -} - -body.ns-platform .hero-status-tags { - display: flex; - align-items: center; - gap: 8px; -} - /* 3. High-Density Telemetry & Activity Panel */ -body.ns-platform .analytics-command-strip { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 12px; - margin-top: 8px; -} - -body.ns-platform .analytics-stat-card { - background-color: var(--ns-bg-surface); - border: 1px solid var(--ns-border-subtle); - border-radius: var(--ns-radius-md); - padding: 14px 18px; - display: flex; - flex-direction: column; - gap: 4px; -} - -body.ns-platform .analytics-stat-card .label { - font-size: 11px; - font-weight: 700; - text-transform: uppercase; - color: var(--ns-text-muted); - letter-spacing: 0.04em; -} - -body.ns-platform .analytics-stat-card .value { - font-size: 20px; - font-weight: 700; - font-family: var(--ns-font-mono); - color: var(--ns-text-primary); -} - -body.ns-platform .analytics-stat-card .subtext { - font-size: 11px; - color: var(--ns-text-secondary); -} - /* 4. Streamer View Content Body */ -body.ns-platform .streamer-body-content { - padding: 24px 40px 64px; - max-width: 1720px; -} - /* Redesigned Navigation Tabs */ -body.ns-platform .archive-tabs-dock { - display: flex; - align-items: center; - gap: 6px; - padding: 4px; - border-radius: var(--ns-radius-md); - background-color: var(--ns-bg-surface); - border: 1px solid var(--ns-border-subtle); - width: fit-content; - margin-bottom: 24px; -} - -body.ns-platform .archive-tab-link { - display: inline-flex; - align-items: center; - gap: 8px; - padding: 8px 16px; - border-radius: var(--ns-radius-sm); - color: var(--ns-text-secondary); - font-size: 13px; - font-weight: 600; - text-decoration: none; - transition: all 0.15s ease; -} - -body.ns-platform .archive-tab-link:hover { - color: var(--ns-text-primary); - background-color: var(--ns-bg-surface-hover); -} - -body.ns-platform .archive-tab-link.is-active { - color: #fff; - background-color: var(--ns-brand-crimson); -} - -body.ns-platform .archive-tab-link .counter-chip { - padding: 2px 6px; - border-radius: var(--ns-radius-full); - font-size: 10px; - font-family: var(--ns-font-mono); - background: rgba(0, 0, 0, 0.25); -} - /* 5. Filter & Search Toolbar */ -body.ns-platform .archive-toolbar-card { - padding: 14px 18px; - border-radius: var(--ns-radius-lg); - background-color: var(--ns-bg-surface); - border: 1px solid var(--ns-border-subtle); - display: flex; - align-items: center; - gap: 12px; - flex-wrap: wrap; - margin-bottom: 24px; -} - -body.ns-platform .archive-search-box { - flex: 1; - min-width: 260px; - position: relative; -} - -body.ns-platform .archive-search-box input { - width: 100%; - background-color: var(--ns-bg-surface-raised); - border: 1px solid var(--ns-border-subtle); - border-radius: var(--ns-radius-md); - padding: 9px 12px 9px 36px; - font-size: 13px; - color: #fff; - outline: none; -} - -body.ns-platform .archive-search-box input:focus { - border-color: var(--ns-brand-crimson); -} - -body.ns-platform .archive-search-box svg { - position: absolute; - left: 12px; - top: 50%; - transform: translateY(-50%); - width: 15px; - height: 15px; - color: var(--ns-text-muted); -} - /* 6. True 16:9 Media Cards (YouTube / Twitch Quality) */ -body.ns-platform .video-grid { - display: grid !important; - grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)) !important; - gap: 24px 18px !important; -} - body.ns-platform .video-card { background-color: transparent !important; border: none !important; @@ -1030,157 +441,34 @@ body.ns-platform .video-card { position: relative !important; box-shadow: none !important; } - body.ns-platform .video-card:hover { transform: none !important; } - -body.ns-platform .thumb-wrap { - width: 100% !important; - aspect-ratio: 16 / 9 !important; - border-radius: var(--ns-radius-md) !important; - overflow: hidden !important; - position: relative !important; - background-color: #12141c !important; - border: 1px solid var(--ns-border-subtle) !important; - display: block !important; -} - -body.ns-platform .thumb-wrap img { - width: 100% !important; - height: 100% !important; - object-fit: cover !important; - display: block !important; - transition: transform 0.2s ease !important; -} - -body.ns-platform .video-card:hover .thumb-wrap img { - transform: scale(1.03) !important; -} - /* Badges positioned over thumbnail */ -body.ns-platform .duration-badge { - position: absolute !important; - bottom: 8px !important; - right: 8px !important; - padding: 3px 6px !important; - border-radius: var(--ns-radius-xs) !important; - background-color: rgba(9, 10, 15, 0.88) !important; - backdrop-filter: none; - color: #fff !important; - font-family: var(--ns-font-mono) !important; - font-size: 11px !important; - font-weight: 700 !important; - border: 1px solid rgba(255, 255, 255, 0.1) !important; -} - -body.ns-platform .thumb-wrap .platform-badge, body.ns-platform .vod-card .platform-badge, -body.ns-platform .video-card .platform-badge, -body.ns-platform .card-thumbnail .platform-badge { +body.ns-platform .video-card .platform-badge { position: absolute !important; top: 8px !important; left: 8px !important; padding: 2px 6px !important; border-radius: var(--ns-radius-xs) !important; - font-size: 10px !important; + font-size: var(--sv-min-text) !important; font-weight: 800 !important; letter-spacing: 0.05em !important; } - body.ns-platform .vod-details .platform-badge, body.ns-platform .vod-kicker .platform-badge, -body.ns-platform .related-recording-card .platform-badge, -body.ns-platform .source-chip .platform-badge { +body.ns-platform .related-recording-card .platform-badge { position: static !important; display: inline-flex !important; vertical-align: middle !important; margin: 0 4px !important; } - -body.ns-platform .drive-chip { - position: absolute !important; - top: 8px !important; - right: 8px !important; - padding: 2px 6px !important; - border-radius: var(--ns-radius-xs) !important; - font-size: 10px !important; - font-weight: 800 !important; - background-color: rgba(59, 130, 246, 0.25) !important; - color: #93c5fd !important; - border: 1px solid rgba(59, 130, 246, 0.4) !important; -} - /* Media Card Typography & Sublines */ -body.ns-platform .card-body { - padding: 0 !important; - display: flex !important; - flex-direction: column !important; - gap: 4px !important; -} - -body.ns-platform .video-title { - font-size: 14px !important; - font-weight: 600 !important; - line-height: 1.35 !important; - color: var(--ns-text-primary) !important; - display: -webkit-box !important; - -webkit-line-clamp: 2 !important; - -webkit-box-orient: vertical !important; - overflow: hidden !important; - text-decoration: none !important; -} - -body.ns-platform .video-title:hover { - color: #fff !important; -} - -body.ns-platform .video-meta { - font-size: 12px !important; - color: var(--ns-text-muted) !important; - line-height: 1.4 !important; -} - -body.ns-platform .video-meta strong { - color: var(--ns-text-secondary) !important; - font-weight: 500 !important; -} - /* Action Strip on Media Card */ -body.ns-platform .card-actions { - display: flex !important; - align-items: center !important; - gap: 6px !important; - margin-top: 4px !important; - padding: 0 !important; - border-top: none !important; -} - -body.ns-platform .card-actions .btn-icon { - width: 28px !important; - height: 28px !important; - border-radius: var(--ns-radius-sm) !important; - background-color: var(--ns-bg-surface) !important; - border: 1px solid var(--ns-border-subtle) !important; - color: var(--ns-text-muted) !important; - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - text-decoration: none !important; - font-size: 12px !important; - cursor: pointer !important; - transition: all 0.15s ease !important; -} - -body.ns-platform .card-actions .btn-icon:hover { - background-color: var(--ns-bg-surface-hover) !important; - color: var(--ns-text-primary) !important; - border-color: var(--ns-border-medium) !important; -} /* ========================================================================== STREAMER ARCHIVE HIGH-SPECIFICITY OVERRIDES (COMPLETE VISUAL TRANSFORMATION) ========================================================================== */ - /* 1. Reset Legacy Panels & Cards */ body.ns-platform.page-streamer .panel { background: var(--ns-bg-surface) !important; @@ -1190,7 +478,6 @@ body.ns-platform.page-streamer .panel { padding: 20px 24px !important; margin-bottom: 24px !important; } - /* 2. Top Header & Hero Area */ body.ns-platform.page-streamer .header { display: flex !important; @@ -1200,31 +487,13 @@ body.ns-platform.page-streamer .header { border-bottom: 1px solid var(--ns-border-subtle) !important; margin-bottom: 24px !important; } - body.ns-platform.page-streamer .page-title { - font-size: 28px !important; + font-size: var(--sv-text-3xl) !important; font-weight: 800 !important; letter-spacing: -0.02em !important; color: var(--ns-text-primary) !important; margin: 0 !important; } - -body.ns-platform.page-streamer .btn-live-watch { - background: var(--ns-brand-crimson) !important; - color: #fff !important; - font-weight: 700 !important; - font-size: 12px !important; - letter-spacing: 0.05em !important; - padding: 8px 16px !important; - border-radius: var(--ns-radius-full) !important; - display: inline-flex !important; - align-items: center !important; - gap: 6px !important; - box-shadow: 0 2px 10px rgba(225, 29, 72, 0.35) !important; - border: none !important; - text-decoration: none !important; -} - /* 3. Navigation Tabs */ body.ns-platform.page-streamer .tabs { display: inline-flex !important; @@ -1235,88 +504,54 @@ body.ns-platform.page-streamer .tabs { border-radius: var(--ns-radius-md) !important; margin-bottom: 24px !important; } - body.ns-platform.page-streamer .tabs .tab { padding: 8px 16px !important; border-radius: var(--ns-radius-sm) !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; font-weight: 600 !important; color: var(--ns-text-secondary) !important; text-decoration: none !important; border: none !important; background: transparent !important; - transition: all 0.15s ease !important; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease !important; } - body.ns-platform.page-streamer .tabs .tab:hover { color: #fff !important; background: var(--ns-bg-surface-hover) !important; } - body.ns-platform.page-streamer .tabs .tab.active { color: #fff !important; background: var(--ns-brand-crimson) !important; } - body.ns-platform.page-streamer .tabs .badge { - font-size: 11px !important; + font-size: var(--sv-min-text) !important; font-family: var(--ns-font-mono) !important; padding: 2px 6px !important; border-radius: var(--ns-radius-full) !important; background: rgba(0, 0, 0, 0.3) !important; color: inherit !important; } - /* 4. Filter Toolbar */ -body.ns-platform.page-streamer .filter-form, body.ns-platform.page-streamer .panel form { display: flex !important; align-items: center !important; gap: 12px !important; flex-wrap: wrap !important; } - body.ns-platform.page-streamer input[type="text"], body.ns-platform.page-streamer select { background-color: var(--ns-bg-surface-raised) !important; border: 1px solid var(--ns-border-subtle) !important; border-radius: var(--ns-radius-md) !important; - color: var(--ns-text-primary) !important; - padding: 8px 12px !important; - font-size: 13px !important; - outline: none !important; -} - -body.ns-platform.page-streamer input[type="text"]:focus, -body.ns-platform.page-streamer select:focus { - border-color: var(--ns-brand-crimson) !important; -} - -body.ns-platform.page-streamer .btn-action { - background-color: var(--ns-brand-crimson) !important; - color: #fff !important; - border: none !important; - padding: 8px 16px !important; - border-radius: var(--ns-radius-md) !important; - font-weight: 600 !important; - font-size: 13px !important; - cursor: pointer !important; - transition: all 0.15s ease !important; + color: var(--ns-text-primary) !important; + padding: 8px 12px !important; + font-size: var(--sv-text-sm) !important; } - -body.ns-platform.page-streamer .btn-action:hover { - background-color: var(--ns-brand-crimson-hover) !important; +body.ns-platform.page-streamer input[type="text"]:focus, +body.ns-platform.page-streamer select:focus { + border-color: var(--ns-brand-crimson) !important; } - /* 5. Transform Video Cards to YouTube/Twitch Cinema Layout */ -body.ns-platform.page-streamer .video-grid { - display: grid !important; - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)) !important; - gap: 28px 20px !important; - padding: 0 !important; - margin-top: 24px !important; -} - body.ns-platform.page-streamer .video-card { background: transparent !important; border: none !important; @@ -1327,144 +562,28 @@ body.ns-platform.page-streamer .video-card { gap: 10px !important; position: relative !important; } - body.ns-platform.page-streamer .video-card:hover { background: transparent !important; border-color: transparent !important; } - /* 16:9 Thumbnail Frame */ -body.ns-platform.page-streamer .thumb-wrap { - width: 100% !important; - aspect-ratio: 16 / 9 !important; - border-radius: var(--ns-radius-md) !important; - overflow: hidden !important; - position: relative !important; - background: #0f1015 !important; - border: 1px solid var(--ns-border-subtle) !important; - display: block !important; -} - -body.ns-platform.page-streamer .thumb-img { - width: 100% !important; - height: 100% !important; - object-fit: cover !important; - display: block !important; - transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1) !important; -} - -body.ns-platform.page-streamer .video-card:hover .thumb-img { - transform: scale(1.04) !important; -} - /* Thumbnail Micro Badges */ -body.ns-platform.page-streamer .duration-badge { - position: absolute !important; - bottom: 8px !important; - right: 8px !important; - padding: 3px 6px !important; - border-radius: var(--ns-radius-xs) !important; - background-color: rgba(9, 10, 15, 0.88) !important; - backdrop-filter: none; - color: #fff !important; - font-family: var(--ns-font-mono) !important; - font-size: 11px !important; - font-weight: 700 !important; - border: 1px solid rgba(255, 255, 255, 0.1) !important; -} - body.ns-platform.page-streamer .platform-badge { position: absolute !important; top: 8px !important; left: 8px !important; padding: 2px 6px !important; border-radius: var(--ns-radius-xs) !important; - font-size: 10px !important; + font-size: var(--sv-min-text) !important; font-weight: 800 !important; letter-spacing: 0.05em !important; background: rgba(0, 0, 0, 0.8) !important; } - -body.ns-platform.page-streamer .drive-chip { - position: absolute !important; - top: 8px !important; - right: 8px !important; - padding: 2px 6px !important; - border-radius: var(--ns-radius-xs) !important; - font-size: 10px !important; - font-weight: 800 !important; - background-color: rgba(59, 130, 246, 0.25) !important; - color: #93c5fd !important; - border: 1px solid rgba(59, 130, 246, 0.4) !important; -} - /* Card Body & Text */ -body.ns-platform.page-streamer .card-body { - padding: 0 !important; - display: flex !important; - flex-direction: column !important; - gap: 5px !important; -} - -body.ns-platform.page-streamer .video-title { - font-size: 14px !important; - font-weight: 600 !important; - line-height: 1.35 !important; - color: var(--ns-text-primary) !important; - display: -webkit-box !important; - -webkit-line-clamp: 2 !important; - -webkit-box-orient: vertical !important; - overflow: hidden !important; - text-decoration: none !important; -} - -body.ns-platform.page-streamer .video-title:hover { - color: #fff !important; -} - -body.ns-platform.page-streamer .video-meta { - font-size: 12px !important; - color: var(--ns-text-muted) !important; - line-height: 1.4 !important; -} - /* Card Action Bar (Hover Reveal) */ -body.ns-platform.page-streamer .card-actions { - display: flex !important; - align-items: center !important; - gap: 6px !important; - margin-top: 4px !important; - padding: 0 !important; - border: none !important; -} - -body.ns-platform.page-streamer .card-actions .btn-icon, -body.ns-platform.page-streamer .card-actions .action-btn { - width: 28px !important; - height: 28px !important; - border-radius: var(--ns-radius-sm) !important; - background-color: var(--ns-bg-surface-raised) !important; - border: 1px solid var(--ns-border-subtle) !important; - color: var(--ns-text-muted) !important; - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - text-decoration: none !important; - font-size: 12px !important; - cursor: pointer !important; - transition: all 0.15s ease !important; -} - -body.ns-platform.page-streamer .card-actions .btn-icon:hover, -body.ns-platform.page-streamer .card-actions .action-btn:hover { - background-color: var(--ns-bg-surface-hover) !important; - color: var(--ns-text-primary) !important; - border-color: var(--ns-border-medium) !important; -} /* ========================================================================== GLOBAL VIEWPORT & SIDEBAR UNDERLAP RESOLUTION ========================================================================== */ - /* Enforce rail margin and full canvas clearance on ALL views */ body.ns-platform { margin: 0 !important; @@ -1473,7 +592,6 @@ body.ns-platform { display: block !important; min-height: 100vh !important; } - body.ns-platform > .main, body.ns-platform .main, body.ns-platform .ns-app-main { @@ -1486,7 +604,6 @@ body.ns-platform .ns-app-main { position: relative !important; z-index: 1 !important; } - /* Ensure Command Rail is fixed and does not hide content */ .ns-command-rail { position: fixed !important; @@ -1504,20 +621,13 @@ body.ns-platform .ns-app-main { flex-direction: column !important; align-items: center !important; } - /* Fix Logout Button positioning so it never gets clipped */ .ns-command-rail .ns-rail-footer { - margin-top: auto !important; - padding-bottom: 8px !important; - width: 100% !important; - display: flex !important; justify-content: center !important; } - /* ========================================================================== ADMIN PANEL COMPLETE VISUAL OVERHAUL ("STREAMVAULT COMMAND") ========================================================================== */ - body.ns-platform.page-admin .main, body.ns-platform.page-admin-traffic .main, body.ns-platform.page-stalk-admin .main { @@ -1525,7 +635,6 @@ body.ns-platform.page-stalk-admin .main { width: calc(100% - var(--ns-rail-width)) !important; padding: 28px 36px 64px !important; } - /* 1. Header Styling */ body.ns-platform.page-admin .header, body.ns-platform.page-admin-traffic .header, @@ -1537,17 +646,15 @@ body.ns-platform.page-stalk-admin .header { align-items: center !important; justify-content: space-between !important; } - body.ns-platform.page-admin .page-title, body.ns-platform.page-admin-traffic .page-title, body.ns-platform.page-stalk-admin .page-title { - font-size: 26px !important; + font-size: var(--sv-text-2xl) !important; font-weight: 800 !important; letter-spacing: -0.02em !important; color: var(--ns-text-primary) !important; margin: 0 !important; } - /* 2. Admin Tab Dock */ body.ns-platform.page-admin .admin-tabs { display: inline-flex !important; @@ -1559,38 +666,33 @@ body.ns-platform.page-admin .admin-tabs { margin-bottom: 28px !important; width: fit-content !important; } - body.ns-platform.page-admin .admin-tab-btn { padding: 8px 18px !important; border-radius: var(--ns-radius-sm) !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; font-weight: 600 !important; color: var(--ns-text-secondary) !important; background: transparent !important; border: none !important; cursor: pointer !important; - transition: all 0.15s ease !important; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease !important; display: inline-flex !important; align-items: center !important; gap: 8px !important; } - body.ns-platform.page-admin .admin-tab-btn:hover { color: var(--ns-text-primary) !important; background: var(--ns-bg-surface-hover) !important; } - body.ns-platform.page-admin .admin-tab-btn.active { color: #fff !important; background: var(--ns-brand-crimson) !important; box-shadow: 0 2px 10px rgba(225, 29, 72, 0.3) !important; } - /* 3. Panel & Card System in Admin & Stalk */ body.ns-platform.page-admin .panel, body.ns-platform.page-admin-traffic .panel, -body.ns-platform.page-stalk-admin .panel, -body.ns-platform .stalk-panel { +body.ns-platform.page-stalk-admin .panel { background: var(--ns-bg-surface) !important; border: 1px solid var(--ns-border-subtle) !important; border-radius: var(--ns-radius-lg) !important; @@ -1598,10 +700,9 @@ body.ns-platform .stalk-panel { box-shadow: var(--ns-shadow-sm) !important; margin-bottom: 24px !important; } - body.ns-platform.page-admin .panel h3, body.ns-platform.page-stalk-admin .panel h3 { - font-size: 14px !important; + font-size: var(--sv-text-md) !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.04em !important; @@ -1611,7 +712,6 @@ body.ns-platform.page-stalk-admin .panel h3 { padding-bottom: 8px !important; border-bottom: 1px solid var(--ns-border-subtle) !important; } - /* 4. Form Controls & Buttons in Admin */ body.ns-platform.page-admin input[type="text"], body.ns-platform.page-admin input[type="password"], @@ -1624,77 +724,60 @@ body.ns-platform.page-stalk-admin select { border-radius: var(--ns-radius-md) !important; color: var(--ns-text-primary) !important; padding: 9px 12px !important; - font-size: 13px !important; - outline: none !important; + font-size: var(--sv-text-sm) !important; } - body.ns-platform.page-admin input:focus, body.ns-platform.page-stalk-admin input:focus { border-color: var(--ns-brand-crimson) !important; } - -body.ns-platform.page-admin button[type="submit"], +body.ns-platform.page-admin button:where(:not(.sv-btn))[type="submit"]:where(:not(.sv-btn)), body.ns-platform.page-admin .btn-primary, -body.ns-platform.page-stalk-admin button[type="submit"], +body.ns-platform.page-stalk-admin button:where(:not(.sv-btn))[type="submit"]:where(:not(.sv-btn)), body.ns-platform.page-stalk-admin .btn-primary { background: var(--ns-brand-crimson) !important; color: #fff !important; border: none !important; border-radius: var(--ns-radius-md) !important; font-weight: 600 !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; padding: 9px 18px !important; cursor: pointer !important; - transition: all 0.15s ease !important; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease !important; } - -body.ns-platform.page-admin button[type="submit"]:hover, -body.ns-platform.page-stalk-admin button[type="submit"]:hover { +body.ns-platform.page-admin button:where(:not(.sv-btn))[type="submit"]:hover, +body.ns-platform.page-stalk-admin button:where(:not(.sv-btn))[type="submit"]:hover { background: var(--ns-brand-crimson-hover) !important; } - /* 5. User Management & Data Tables */ body.ns-platform.page-admin table, body.ns-platform.page-stalk-admin table { width: 100% !important; border-collapse: collapse !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; margin-top: 12px !important; } - body.ns-platform.page-admin th, body.ns-platform.page-stalk-admin th { padding: 12px 14px !important; border-bottom: 1px solid var(--ns-border-subtle) !important; color: var(--ns-text-muted) !important; - font-size: 11px !important; + font-size: var(--sv-min-text) !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.04em !important; text-align: left !important; } - body.ns-platform.page-admin td, body.ns-platform.page-stalk-admin td { padding: 12px 14px !important; border-bottom: 1px solid var(--ns-border-subtle) !important; color: var(--ns-text-secondary) !important; } - body.ns-platform.page-admin tr:hover td, body.ns-platform.page-stalk-admin tr:hover td { background: var(--ns-bg-surface-raised) !important; color: var(--ns-text-primary) !important; } - -/* ========================================================================== - STREAMVAULT COMMAND: GLOBAL PLATFORM-WIDE CLEARANCE & RAIL RESILIENCE - ========================================================================== */ - -:root { - --ns-rail-width: 68px !important; -} - /* 1. Reset any style.css nav height overrides on the command rail */ .ns-command-rail nav, .ns-command-rail .ns-rail-nav, @@ -1716,13 +799,11 @@ body:is(.page-index, .page-channels, .page-streamer, .page-admin, .page-files, . align-items: center !important; width: 100% !important; } - .ns-command-rail nav::-webkit-scrollbar, .ns-command-rail .ns-rail-nav::-webkit-scrollbar { display: none !important; width: 0 !important; } - /* 2. Precision Command Rail positioning & dimensions */ .ns-command-rail, aside.ns-command-rail, @@ -1735,8 +816,8 @@ body .ns-command-rail { max-width: var(--ns-rail-width, 68px) !important; height: 100vh !important; max-height: 100vh !important; - background-color: var(--ns-bg-sidebar, #0d0f17) !important; - border-right: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.08)) !important; + background-color: var(--ns-bg-sidebar) !important; + border-right: 1px solid var(--ns-border-subtle) !important; z-index: 99999 !important; box-sizing: border-box !important; padding: 16px 0 16px !important; @@ -1746,17 +827,10 @@ body .ns-command-rail { flex-shrink: 0 !important; overflow: hidden !important; } - .ns-command-rail .ns-rail-brand { margin-bottom: 20px !important; flex-shrink: 0 !important; } - -.ns-command-rail .ns-rail-spacer { - flex: 1 1 auto !important; - min-height: 16px !important; -} - .ns-command-rail .ns-rail-footer { margin-top: auto !important; padding-bottom: 4px !important; @@ -1766,7 +840,6 @@ body .ns-command-rail { align-items: center !important; flex-shrink: 0 !important; } - .ns-command-rail .ns-logout-btn { background: transparent !important; border: none !important; @@ -1777,34 +850,31 @@ body .ns-command-rail { justify-content: center !important; width: 100% !important; } - .ns-command-rail .ns-logout-btn button.ns-rail-item, -body .ns-command-rail .ns-logout-btn button.ns-rail-item, -body:is(.page-index, .page-channels, .page-streamer, .page-admin, .page-files, .page-search, .page-discord-tool, .page-vod, .page-live, .page-stalk) .ns-command-rail .ns-logout-btn button { +body .ns-command-rail .ns-logout-btn button:where(:not(.sv-btn)).ns-rail-item, +body:is(.page-index, .page-channels, .page-streamer, .page-admin, .page-files, .page-search, .page-discord-tool, .page-vod, .page-live, .page-stalk) .ns-command-rail .ns-logout-btn button:where(:not(.sv-btn)) { width: 44px !important; height: 44px !important; border-radius: var(--ns-radius-md, 10px) !important; - color: var(--ns-text-muted, #94a3b8) !important; + color: var(--ns-text-muted) !important; display: flex !important; align-items: center !important; justify-content: center !important; background: transparent !important; border: 1px solid transparent !important; cursor: pointer !important; - transition: all 0.15s ease !important; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease !important; padding: 0 !important; margin: 0 !important; } - .ns-command-rail .ns-logout-btn button.ns-rail-item:hover, -body .ns-command-rail .ns-logout-btn button.ns-rail-item:hover { +body .ns-command-rail .ns-logout-btn button:where(:not(.sv-btn)).ns-rail-item:hover { color: #ef4444 !important; background-color: rgba(239, 68, 68, 0.12) !important; border-color: rgba(239, 68, 68, 0.3) !important; transform: none !important; box-shadow: none !important; } - /* 3. ABSOLUTE GLOBAL SIDEBAR CLEARANCE (ZERO UNDERLAP) */ body.ns-platform > .main, body.ns-platform .main, @@ -1840,16 +910,14 @@ body.page-discord-tool .main { max-width: calc(100% - var(--ns-rail-width, 68px)) !important; box-sizing: border-box !important; } - /* 4. VOD Player Viewport & Actions Overrides */ body.page-vod .content { grid-template-columns: minmax(0, 1fr) minmax(320px, 380px) !important; gap: 16px !important; } - body:is(.page-vod, .page-twitch-watch, .page-live) .vod-details { - background: var(--ns-bg-surface, #11131a) !important; - border: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.08)) !important; + background: var(--ns-bg-surface) !important; + border: 1px solid var(--ns-border-subtle) !important; border-radius: var(--ns-radius-lg, 12px) !important; padding: 18px 24px !important; height: auto !important; @@ -1860,7 +928,6 @@ body:is(.page-vod, .page-twitch-watch, .page-live) .vod-details { max-width: 100% !important; align-self: stretch !important; } - body:is(.page-vod, .page-twitch-watch) .twitch-switcher, nav.twitch-switcher { display: block !important; @@ -1876,45 +943,39 @@ nav.twitch-switcher { grid-column: 1 / -1 !important; width: 100% !important; } - body:is(.page-vod, .page-live) #btnOpenEditor, body:is(.page-vod, .page-live) .vod-inline-tool { - background: var(--ns-brand-crimson, #e11d48) !important; + background: var(--ns-brand-crimson) !important; color: #fff !important; - border: 1px solid var(--ns-brand-crimson, #e11d48) !important; - border-radius: 8px !important; + border: 1px solid var(--ns-brand-crimson) !important; + border-radius: var(--nebula-radius-sm) !important; font-weight: 600 !important; - transition: all 0.15s ease !important; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease !important; } - body:is(.page-vod, .page-live) #btnInstantClip, body:is(.page-vod, .page-live) #btnTranscriptToggle, body:is(.page-vod, .page-live) .vod-file-action { - background: var(--ns-bg-surface-raised, #161922) !important; - color: var(--ns-text-primary, #fff) !important; - border: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.08)) !important; - border-radius: 8px !important; - transition: all 0.15s ease !important; + background: var(--ns-bg-surface-raised) !important; + color: var(--ns-text-primary) !important; + border: 1px solid var(--ns-border-subtle) !important; + border-radius: var(--nebula-radius-sm) !important; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease !important; } - body:is(.page-vod, .page-live) #btnOpenEditor:hover { - background: var(--ns-brand-crimson-hover, #f43f5e) !important; - border-color: var(--ns-brand-crimson-hover, #f43f5e) !important; + background: var(--ns-brand-crimson-hover) !important; + border-color: var(--ns-brand-crimson-hover) !important; } - body:is(.page-vod, .page-live) #btnInstantClip:hover, body:is(.page-vod, .page-live) #btnTranscriptToggle:hover, body:is(.page-vod, .page-live) .vod-file-action:hover { - background: var(--ns-bg-surface-hover, rgba(255, 255, 255, 0.08)) !important; - border-color: var(--ns-border-medium, rgba(255, 255, 255, 0.16)) !important; + background: var(--ns-bg-surface-hover) !important; + border-color: var(--ns-border-medium) !important; color: #fff !important; } - /* ========================================================= MOBILE PLAYER & LIVE WATCH UX UPGRADE (STREAM PROMINENCE, NO BOTTOM CHAT CUTOFF, RELIABLE LANDSCAPE CHAT TOGGLE) ========================================================= */ - /* 1. Viewport Lock: Prevent unwanted body scrolling and cutoffs on mobile */ body.ns-platform:is(.page-mobile-player, .page-twitch-watch-mobile) { height: 100vh !important; @@ -1929,7 +990,6 @@ body.ns-platform:is(.page-mobile-player, .page-twitch-watch-mobile) { flex-direction: column !important; background-color: #000 !important; } - /* 2. Stream Priority: Clean 16:9 full-width video container without top gaps */ body:is(.page-mobile-player, .page-twitch-watch-mobile) .video-container { width: 100% !important; @@ -1941,7 +1001,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .video-container { margin: 0 !important; overflow: hidden !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .overlay-header { position: absolute !important; top: 0 !important; @@ -1955,60 +1014,40 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .overlay-header { align-items: center !important; pointer-events: none !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .overlay-header > * { pointer-events: auto !important; } - /* 3. Ultra-Compact Metadata Bar under Video (saves ~90px of space) */ -body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details { - flex: 0 0 auto !important; - padding: 8px 12px 8px !important; - background: var(--ns-bg-surface, #12141c) !important; - border-bottom: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.08)) !important; - display: flex !important; - flex-direction: column !important; - gap: 3px !important; -} - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-details-main { - display: flex !important; - align-items: center !important; - justify-content: flex-start !important; - gap: 8px !important; margin: 0 !important; min-width: 0 !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-kicker { display: inline-flex !important; align-items: center !important; margin: 0 !important; flex-shrink: 0 !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .twitch-live-pill { - background: var(--ns-brand-crimson, #e11d48) !important; + background: var(--ns-brand-crimson) !important; color: #fff !important; - font-size: 10px !important; + font-size: var(--sv-min-text) !important; font-weight: 800 !important; letter-spacing: 0.05em !important; padding: 2px 7px !important; border-radius: var(--ns-radius-full, 9999px) !important; box-shadow: 0 0 10px rgba(225, 29, 72, 0.4) !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-display-title { - font-size: 14px !important; + font-size: var(--sv-text-md) !important; font-weight: 700 !important; line-height: 1.2 !important; - color: var(--ns-text-primary, #f8fafc) !important; + color: var(--ns-text-primary) !important; margin: 0 !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-details-side { display: flex !important; align-items: center !important; @@ -2016,100 +1055,71 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod gap: 8px !important; margin: 0 !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-facts { margin: 0 !important; display: flex !important; align-items: center !important; gap: 8px !important; - font-size: 11px !important; - color: var(--ns-text-muted, #94a3b8) !important; + font-size: var(--sv-min-text) !important; + color: var(--ns-text-muted) !important; min-width: 0 !important; flex: 1 1 auto !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-facts div { display: inline-flex !important; align-items: center !important; gap: 4px !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-facts dt { - font-size: 10px !important; + font-size: var(--sv-min-text) !important; font-weight: 700 !important; - text-transform: uppercase !important; - color: var(--ns-text-muted, #64748b) !important; + color: var(--ns-text-muted) !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-facts dd { - font-size: 11px !important; + font-size: var(--sv-min-text) !important; font-weight: 600 !important; - color: var(--ns-text-secondary, #cbd5e1) !important; + color: var(--ns-text-secondary) !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-file-actions { flex-shrink: 0 !important; } - -body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-inline-tool { - min-height: 26px !important; - padding: 0 10px !important; - font-size: 11px !important; - font-weight: 600 !important; - border-radius: var(--ns-radius-sm, 6px) !important; - background: var(--ns-bg-surface-raised, #181a24) !important; - border: 1px solid var(--ns-border-medium, rgba(255, 255, 255, 0.12)) !important; - color: var(--ns-text-secondary, #cbd5e1) !important; - transition: all 0.15s ease !important; -} - /* Compact Tabs Header and Toolbar */ body:is(.page-twitch-watch-mobile, .page-mobile-player) .chat-tabs-head { padding: 4px 10px !important; min-height: 34px !important; - background: var(--ns-bg-surface, #12141c) !important; - border-bottom: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.06)) !important; + background: var(--ns-bg-surface) !important; + border-bottom: 1px solid var(--ns-border-subtle) !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .chat-tab { padding: 4px 14px !important; - font-size: 11px !important; + font-size: var(--sv-min-text) !important; font-weight: 700 !important; letter-spacing: 0.03em !important; text-transform: uppercase !important; border-radius: var(--ns-radius-sm, 6px) !important; background: transparent !important; border: 1px solid transparent !important; - color: var(--ns-text-muted, #64748b) !important; + color: var(--ns-text-muted) !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .chat-tab.is-active { - background: var(--ns-brand-crimson, #e11d48) !important; + background: var(--ns-brand-crimson) !important; color: #fff !important; - border-color: var(--ns-brand-crimson, #e11d48) !important; + border-color: var(--ns-brand-crimson) !important; box-shadow: 0 0 12px rgba(225, 29, 72, 0.35) !important; } - -body:is(.page-twitch-watch-mobile, .page-mobile-player) .chat-pane-toolbar { - padding: 3px 10px !important; - min-height: 28px !important; - border-bottom: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.04)) !important; -} - body:is(.page-twitch-watch-mobile, .page-mobile-player) .chat-toggle { min-height: 24px !important; padding: 2px 8px !important; - font-size: 10px !important; + font-size: var(--sv-min-text) !important; font-weight: 700 !important; border-radius: var(--ns-radius-xs, 4px) !important; - background: var(--ns-bg-surface-raised, #181a24) !important; - border: 1px solid var(--ns-border-medium, rgba(255, 255, 255, 0.12)) !important; - color: var(--ns-text-secondary, #cbd5e1) !important; + background: var(--ns-bg-surface-raised) !important; + border: 1px solid var(--ns-border-medium) !important; + color: var(--ns-text-secondary) !important; } - /* 4. Chat Container & List: ZERO CUTOFF AT BOTTOM */ body:is(.page-mobile-player, .page-twitch-watch-mobile) .chat-container { flex: 1 1 auto !important; @@ -2117,9 +1127,8 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .chat-container { display: flex !important; flex-direction: column !important; overflow: hidden !important; - background: var(--ns-bg-canvas, #090a0f) !important; + background: var(--ns-bg-canvas) !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .chat-tab-pane { flex: 1 1 auto !important; min-height: 0 !important; @@ -2127,23 +1136,30 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .chat-tab-pane { flex-direction: column !important; overflow: hidden !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .chat-tab-pane[hidden], body:is(.page-mobile-player, .page-twitch-watch-mobile) .chat-tab-pane.is-hidden { display: none !important; } - /* ========================================================================= */ /* ULTRA-FAST MOBILE PERFORMANCE & INSTANT 0MS TAP RESPONSE */ /* ========================================================================= */ - /* 1. Eliminate 300ms mobile tap delay across entire site */ -html, body, button, a, input, textarea, select, [role="button"], [role="tab"], -.chat-tab, .btn, .ns-command-item, .video-card, .streamer-card, .card, .live-card { +html, +body, +button, +a, +input, +textarea, +select, +[role="button"], +[role="tab"], +.chat-tab, +.btn, +.video-card, +.card { touch-action: manipulation !important; -webkit-tap-highlight-color: transparent !important; } - /* 2. Instant visual haptic feedback on touch */ button:active, a.btn:active, @@ -2154,7 +1170,6 @@ a.btn:active, transform: scale(0.97) !important; transition: transform 0.05s ease !important; } - /* 3. GPU-accelerated smooth 120fps scrolling on mobile */ .chat-list, .content, @@ -2163,7 +1178,6 @@ a.btn:active, -webkit-overflow-scrolling: touch !important; overscroll-behavior-y: contain !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .chat-list { flex: 1 1 auto !important; min-height: 0 !important; @@ -2173,7 +1187,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .chat-list { padding: 8px 12px max(44px, calc(env(safe-area-inset-bottom, 20px) + 24px)) 12px !important; box-sizing: border-box !important; } - /* 5. Landscape Mode & Chat Toggle Button Guaranteed Visibility */ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-toggle { touch-action: manipulation !important; @@ -2191,19 +1204,14 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t white-space: nowrap !important; flex-shrink: 0 !important; } - /* Hidden by default in portrait */ @media (orientation: portrait) { body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.is-landscape-active) .mobile-landscape-chat-toggle { display: none !important; } } - /* Guaranteed display in landscape */ @media (orientation: landscape), (min-aspect-ratio: 1/1) { - body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-force-landscape-toggle { - display: none !important; - } body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-toggle { display: inline-flex !important; visibility: visible !important; @@ -2211,17 +1219,12 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t pointer-events: auto !important; } } - -body:is(.page-mobile-player, .page-twitch-watch-mobile).is-landscape-active .mobile-force-landscape-toggle { - display: none !important; -} body:is(.page-mobile-player, .page-twitch-watch-mobile).is-landscape-active .mobile-landscape-chat-toggle { display: inline-flex !important; visibility: visible !important; opacity: 1 !important; pointer-events: auto !important; } - /* Chat CLOSED in Landscape (100% video): glowing crimson pill pinned top-right */ body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.landscape-chat-open) .mobile-landscape-chat-toggle { position: fixed !important; @@ -2232,11 +1235,11 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.landscape-chat-open width: auto !important; min-width: fit-content !important; padding: 0 14px 0 12px !important; - border-radius: 20px !important; + border-radius: var(--nebula-radius-lg) !important; background: rgba(15, 18, 28, 0.94) !important; - border: 1.5px solid var(--ns-brand-crimson, #e11d48) !important; + border: 1.5px solid var(--ns-brand-crimson) !important; color: #ffffff !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; font-weight: 600 !important; letter-spacing: 0.02em !important; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.75), 0 0 14px rgba(225, 29, 72, 0.4) !important; @@ -2245,7 +1248,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.landscape-chat-open white-space: nowrap !important; gap: 6px !important; } - /* Chat OPEN in Landscape: compact collapse button */ body:is(.page-mobile-player, .page-twitch-watch-mobile).landscape-chat-open .mobile-landscape-chat-toggle { position: relative !important; @@ -2254,19 +1256,18 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile).landscape-chat-open .mob width: auto !important; min-width: fit-content !important; padding: 0 12px 0 10px !important; - border-radius: 19px !important; + border-radius: var(--nebula-radius-lg) !important; background: rgba(22, 26, 38, 0.9) !important; border: 1px solid rgba(255, 255, 255, 0.25) !important; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45) !important; color: rgba(255, 255, 255, 0.95) !important; - font-size: 12px !important; + font-size: var(--sv-text-xs) !important; font-weight: 500 !important; backdrop-filter: none; -webkit-backdrop-filter: none; white-space: nowrap !important; gap: 4px !important; } - /* Inner content toggles */ body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.landscape-chat-open) .landscape-chat-toggle-closed-content { display: inline-flex !important; @@ -2276,7 +1277,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.landscape-chat-open body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.landscape-chat-open) .landscape-chat-toggle-open-content { display: none !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile).landscape-chat-open .landscape-chat-toggle-closed-content { display: none !important; } @@ -2285,7 +1285,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile).landscape-chat-open .lan align-items: center !important; gap: 4px !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-toggle:active { transform: scale(0.95) !important; } @@ -2293,7 +1292,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t border-color: #ffffff !important; color: #ffffff !important; } - /* Live Tap Unmute Pill */ .live-tap-unmute { position: absolute !important; @@ -2302,12 +1300,12 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t z-index: 850 !important; height: 36px !important; padding: 0 14px !important; - border-radius: 18px !important; + border-radius: var(--nebula-radius-lg) !important; background: rgba(15, 18, 28, 0.92) !important; border: 1.5px solid rgba(255, 255, 255, 0.3) !important; color: #ffffff !important; font-weight: 600 !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; display: inline-flex !important; align-items: center !important; gap: 8px !important; @@ -2323,16 +1321,11 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t .live-tap-unmute:active { transform: scale(0.96) !important; } - @media (orientation: landscape) { body.ns-platform:is(.page-mobile-player, .page-twitch-watch-mobile) { flex-direction: row !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-vod-details, - body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-comments:not(.chat-tab-pane *) { - display: none !important; - } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-force-landscape-toggle { + body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-vod-details { display: none !important; } body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-toggle { @@ -2347,7 +1340,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t padding-right: max(16px, env(safe-area-inset-right, 16px)) !important; padding-top: max(8px, env(safe-area-inset-top, 8px)) !important; } - /* Video inside container in landscape */ body:is(.page-mobile-player, .page-twitch-watch-mobile) .video-container video { position: absolute !important; @@ -2356,7 +1348,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t height: 100% !important; object-fit: contain !important; } - /* Landscape layout split: Chat open (2/3 video + 1/3 chat) */ body:is(.page-mobile-player, .page-twitch-watch-mobile).landscape-chat-open .video-container { flex: 1 1 66.666% !important; @@ -2366,7 +1357,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t aspect-ratio: auto !important; position: relative !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile).landscape-chat-open .chat-container { display: flex !important; flex: 0 0 33.334% !important; @@ -2375,10 +1365,9 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t min-width: 260px !important; height: 100% !important; border-top: none !important; - border-left: 1px solid var(--ns-border-medium, rgba(255, 255, 255, 0.12)) !important; + border-left: 1px solid var(--ns-border-medium) !important; z-index: 20 !important; } - /* Landscape layout: Chat closed / Fullscreen video (100% video) */ body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.landscape-chat-open) .video-container { flex: 1 1 100% !important; @@ -2388,22 +1377,18 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-landscape-chat-t aspect-ratio: auto !important; position: relative !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile):not(.landscape-chat-open) .chat-container { display: none !important; width: 0 !important; max-width: 0 !important; } } - /* -------------------------------------------------------------------------- Mobile Player Top Overlay Quick Controls (Play/Pause, Mute, Clip) -------------------------------------------------------------------------- */ -.mobile-force-landscape-toggle, #forceLandscapeToggle { display: none !important; } - body:is(.page-mobile-player, .page-twitch-watch-mobile) .overlay-header-actions { display: flex !important; align-items: center !important; @@ -2411,63 +1396,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .overlay-header-actions pointer-events: auto !important; z-index: 950 !important; } - -body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-btn { - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - height: 36px !important; - min-width: 36px !important; - padding: 0 10px !important; - border-radius: 18px !important; - background: rgba(14, 16, 24, 0.88) !important; - border: 1px solid rgba(255, 255, 255, 0.22) !important; - color: #ffffff !important; - font-size: 13px !important; - font-weight: 600 !important; - cursor: pointer !important; - touch-action: manipulation !important; - -webkit-tap-highlight-color: transparent !important; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45) !important; - backdrop-filter: none; - -webkit-backdrop-filter: none; - gap: 6px !important; - transition: all 0.15s ease !important; - line-height: 1 !important; - user-select: none !important; - -webkit-user-select: none !important; -} - -body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-btn:active { - transform: scale(0.92) !important; -} - -body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-btn:hover { - border-color: rgba(255, 255, 255, 0.5) !important; - background: rgba(24, 28, 42, 0.95) !important; -} - -body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-btn.mobile-clip-btn { - border-color: rgba(225, 29, 72, 0.6) !important; - background: rgba(22, 26, 38, 0.92) !important; - color: #ffffff !important; - padding: 0 12px !important; -} - -body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-btn.mobile-clip-btn:hover, -body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-btn.mobile-clip-btn:active { - border-color: var(--ns-brand-crimson, #e11d48) !important; - background: rgba(225, 29, 72, 0.25) !important; - box-shadow: 0 0 12px rgba(225, 29, 72, 0.35) !important; -} - -body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-btn.is-muted, -body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-btn.is-paused { - border-color: rgba(245, 158, 11, 0.7) !important; - color: #fbbf24 !important; -} - - /* -------------------------------------------------------------------------- Notch / Dynamic Island Safety & Bottom Action Buttons (Desktop VOD Style) -------------------------------------------------------------------------- */ @@ -2491,11 +1419,9 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile) .mobile-player-control-b display: none !important; } } - body:is(.page-mobile-player, .page-twitch-watch-mobile).is-portrait-active .overlay-header { display: none !important; } - .vod-title-cluster { display: flex !important; align-items: center !important; @@ -2503,7 +1429,6 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile).is-portrait-active .over min-width: 0 !important; flex: 1 1 auto !important; } - .mobile-portrait-back-btn { display: inline-flex !important; align-items: center !important; @@ -2512,42 +1437,35 @@ body:is(.page-mobile-player, .page-twitch-watch-mobile).is-portrait-active .over height: 32px !important; min-width: 32px !important; border-radius: var(--ns-radius-md, 8px) !important; - background: var(--ns-bg-surface-raised, rgba(255, 255, 255, 0.08)) !important; - border: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.12)) !important; - color: var(--ns-text-primary, #f8fafc) !important; + background: var(--ns-bg-surface-raised) !important; + border: 1px solid var(--ns-border-subtle) !important; + color: var(--ns-text-primary) !important; text-decoration: none !important; flex-shrink: 0 !important; transition: background 0.15s ease, transform 0.1s ease !important; } - .mobile-portrait-back-btn:hover { background: rgba(255, 255, 255, 0.15) !important; color: #ffffff !important; } - .mobile-portrait-back-btn:active { background: rgba(255, 255, 255, 0.25) !important; transform: scale(0.92) !important; } - /* Rendering performance: content-visibility for list cards */ -body.ns-platform .video-card, -body.ns-platform .streamer-card { +body.ns-platform .video-card { content-visibility: auto; contain-intrinsic-size: 0 280px; } - - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details { flex: 0 0 auto !important; padding: 8px 12px 10px !important; - background: var(--ns-bg-surface, #12141c) !important; - border-bottom: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.08)) !important; + background: var(--ns-bg-surface) !important; + border-bottom: 1px solid var(--ns-border-subtle) !important; display: flex !important; flex-direction: column !important; gap: 6px !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-details-main { display: flex !important; align-items: center !important; @@ -2555,7 +1473,6 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod flex-wrap: wrap !important; gap: 8px !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-file-actions { display: flex !important; align-items: center !important; @@ -2569,7 +1486,6 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-file-actions::-webkit-scrollbar { display: none !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-inline-tool { display: inline-flex !important; align-items: center !important; @@ -2577,46 +1493,41 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod height: 32px !important; min-height: 32px !important; padding: 0 12px !important; - font-size: 12px !important; + font-size: var(--sv-text-xs) !important; font-weight: 600 !important; border-radius: var(--ns-radius-md, 8px) !important; - background: var(--ns-bg-surface-raised, #181a24) !important; - border: 1px solid var(--ns-border-medium, rgba(255, 255, 255, 0.16)) !important; - color: var(--ns-text-primary, #f1f5f9) !important; + background: var(--ns-bg-surface-raised) !important; + border: 1px solid var(--ns-border-medium) !important; + color: var(--ns-text-primary) !important; gap: 6px !important; cursor: pointer !important; touch-action: manipulation !important; -webkit-tap-highlight-color: transparent !important; white-space: nowrap !important; flex-shrink: 0 !important; - transition: all 0.15s ease !important; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-inline-tool:active { transform: scale(0.95) !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-inline-tool.mobile-clip-tool { border-color: rgba(225, 29, 72, 0.6) !important; background: rgba(22, 26, 38, 0.95) !important; color: #fff !important; } body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-inline-tool.mobile-clip-tool:active { - border-color: var(--ns-brand-crimson, #e11d48) !important; + border-color: var(--ns-brand-crimson) !important; background: rgba(225, 29, 72, 0.25) !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-inline-tool.is-paused, body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-inline-tool.is-muted { border-color: rgba(245, 158, 11, 0.6) !important; color: #fbbf24 !important; } - /* Admin Title & Description Modal Overlay */ .vod-admin-overlay[hidden] { display: none !important; } - .vod-admin-overlay { position: fixed !important; inset: 0 !important; @@ -2625,7 +1536,6 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod align-items: center !important; justify-content: center !important; } - .vod-admin-scrim { position: fixed !important; inset: 0 !important; @@ -2633,15 +1543,14 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod backdrop-filter: none; -webkit-backdrop-filter: none; } - .vod-admin-dialog { position: relative !important; z-index: 8501 !important; width: min(540px, calc(100vw - 32px)) !important; max-height: calc(100vh - 60px) !important; overflow-y: auto !important; - background: var(--ns-bg-surface, #12141c) !important; - border: 1px solid var(--ns-border-medium, rgba(255, 255, 255, 0.16)) !important; + background: var(--ns-bg-surface) !important; + border: 1px solid var(--ns-border-medium) !important; border-radius: var(--ns-radius-lg, 12px) !important; padding: 20px 24px !important; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.7) !important; @@ -2650,145 +1559,78 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod gap: 14px !important; color: #fff !important; } - .vod-admin-dialog-head { display: flex !important; align-items: flex-start !important; justify-content: space-between !important; gap: 12px !important; } - .vod-admin-dialog-titles { display: flex !important; flex-direction: column !important; gap: 2px !important; } - .vod-admin-kicker { - font-size: 11px !important; + font-size: var(--sv-min-text) !important; text-transform: uppercase !important; font-weight: 700 !important; - color: var(--ns-brand-crimson, #e11d48) !important; + color: var(--ns-brand-crimson) !important; letter-spacing: 0.05em !important; } - .vod-admin-title { - font-size: 17px !important; + font-size: var(--sv-text-base) !important; font-weight: 700 !important; color: #fff !important; margin: 0 !important; } - .vod-admin-meta-form, .vod-admin-rename-form { display: flex !important; flex-direction: column !important; gap: 12px !important; } - .vod-admin-field { display: flex !important; flex-direction: column !important; gap: 6px !important; - font-size: 12px !important; - color: #a1a1aa !important; + font-size: var(--sv-text-xs) !important; + color: var(--nebula-text-secondary) !important; font-weight: 600 !important; } - .vod-admin-field input, .vod-admin-field textarea { width: 100% !important; box-sizing: border-box !important; background: #0d0f16 !important; border: 1px solid rgba(255, 255, 255, 0.14) !important; - border-radius: 8px !important; + border-radius: var(--nebula-radius-sm) !important; padding: 9px 12px !important; color: #fff !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; font-family: inherit !important; - outline: none !important; resize: vertical !important; transition: border-color 0.15s ease !important; } - .vod-admin-field input:focus, .vod-admin-field textarea:focus { - border-color: var(--ns-brand-crimson, #e11d48) !important; + border-color: var(--ns-brand-crimson) !important; } - .vod-admin-actions-row { display: flex !important; align-items: center !important; justify-content: flex-end !important; gap: 12px !important; } - .vod-admin-status-text { - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; font-weight: 600 !important; } - .vod-admin-divider { height: 1px !important; background: rgba(255, 255, 255, 0.08) !important; margin: 4px 0 !important; } - /* VOD Chat & Comments Split Panel (Matching Live twitch_watch 50/50) */ -body.page-vod .chat-panel.chat-panel-split { - display: flex !important; - flex-direction: column !important; - gap: 0 !important; - min-height: 0 !important; -} - -body.page-vod .chat-panel.chat-panel-split .chat-split-col { - display: flex !important; - flex-direction: column !important; - flex: 1 1 50% !important; - min-width: 0 !important; - min-height: 180px !important; - height: 50% !important; - overflow: hidden !important; - position: relative !important; -} - -body.page-vod .chat-panel.chat-panel-split .chat-split-twitch { - border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important; -} - -body.page-vod .chat-panel.chat-panel-split .chat-split-col .chat-header { - display: flex !important; - align-items: center !important; - justify-content: space-between !important; - gap: 8px !important; - flex-shrink: 0 !important; - min-height: 48px !important; - height: 48px !important; - padding: 0 16px !important; - background: var(--tube-surface, #0d0d0d) !important; - border-bottom: 1px solid rgba(206, 232, 255, 0.08) !important; - color: var(--tube-text, #fff) !important; - font-size: 13px !important; - font-weight: 800 !important; -} - -body.page-vod .chat-panel.chat-panel-split .chat-split-col .chat-header span { - text-transform: uppercase !important; - letter-spacing: 0.04em !important; -} - -body.page-vod .chat-panel.chat-panel-split .chat-split-col .chat-list { - flex: 1 1 0 !important; - min-height: 0 !important; - overflow-y: auto !important; - padding: 10px 8px 18px !important; -} - -body.page-vod .chat-panel.chat-panel-split .chat-filter-bar { - flex-shrink: 0 !important; -} - /* Full Viewport Height Desktop Player & Chat (Standard everywhere) */ @media (min-width: 1024px) { html:has(body:is(.page-vod, .page-live, .page-twitch-watch)), @@ -2806,7 +1648,7 @@ body.page-vod .chat-panel.chat-panel-split .chat-filter-bar { top: 0 !important; width: 68px !important; height: 100vh !important; - font-size: 14px !important; + font-size: var(--sv-text-md) !important; } body:is(.page-vod, .page-live, .page-twitch-watch) .main { margin-left: 68px !important; @@ -2819,7 +1661,7 @@ body.page-vod .chat-panel.chat-panel-split .chat-filter-bar { overflow: hidden !important; display: flex !important; flex-direction: column !important; - font-size: 14px !important; + font-size: var(--sv-text-md) !important; } body:is(.page-vod, .page-live, .page-twitch-watch) .content { flex: 1 1 0% !important; @@ -2851,7 +1693,7 @@ body.page-vod .chat-panel.chat-panel-split .chat-filter-bar { max-width: 100% !important; aspect-ratio: auto !important; background: #000 !important; - border-radius: 12px !important; + border-radius: var(--nebula-radius-md) !important; overflow: hidden !important; display: flex !important; align-items: center !important; @@ -2879,61 +1721,43 @@ body.page-vod .chat-panel.chat-panel-split .chat-filter-bar { top: 0 !important; } } -.twitch-player-embed-box, -.twitch-player-embed-box iframe { - position: absolute !important; - inset: 0 !important; - width: 100% !important; - height: 100% !important; - border: 0 !important; - display: block !important; -} - - /* ========================================================================== Pfeiler 5: App-Shell Dynamic Viewport (100dvh) & Timeline Heatmap Canvas ========================================================================== */ - @supports (height: 100dvh) { body:is(.page-vod, .page-live, .page-twitch-watch), .content, - .main, - .tube-layout { + .main { min-height: 100dvh !important; } - @media (max-width: 960px) { .chat-panel { max-height: calc(100dvh - 60px) !important; } } } - .vod-timeline-heatmap-bar { position: relative; width: 100%; height: 14px; background: rgba(18, 20, 28, 0.85); cursor: pointer; - border-radius: 4px; + border-radius: var(--nebula-radius-xs); margin-top: 6px; margin-bottom: 8px; overflow: hidden; box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5); - border: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.08)); + border: 1px solid var(--ns-border-subtle); transition: opacity 0.2s ease, border-color 0.2s ease; } - .vod-timeline-heatmap-bar:hover { - border-color: var(--ns-border-medium, rgba(255, 255, 255, 0.2)); + border-color: var(--ns-border-medium); } - .vod-heatmap-canvas { width: 100%; height: 100%; display: block; } - .vod-heatmap-pins { position: absolute; top: 0; @@ -2942,35 +1766,12 @@ body.page-vod .chat-panel.chat-panel-split .chat-filter-bar { height: 100%; pointer-events: none; } - -.vod-heatmap-pin { - position: absolute; - top: 1px; - width: 4px; - height: 12px; - border-radius: 2px; - background: #f59e0b; - transform: translateX(-50%); - pointer-events: auto; - cursor: pointer; - transition: transform 0.15s ease, background 0.15s ease; -} - -.vod-heatmap-pin:hover { - transform: translateX(-50%) scaleY(1.3); - background: #fbbf24; - z-index: 2; -} - - /* ========================================================================== NEBULA: COSMIC STREAMING DESIGN SYSTEM ========================================================================== */ - /* Buttons: Cosmic Glow & Gradients */ -.ns-btn-primary, -.nebula-btn-primary { - background: linear-gradient(135deg, #4D63FF 0%, #9365FF 100%) !important; +.ns-btn-primary { + background: var(--nebula-gradient-primary) !important; color: #FFFFFF !important; font-weight: 600 !important; border-radius: var(--ns-radius-md) !important; @@ -2985,172 +1786,120 @@ body.page-vod .chat-panel.chat-panel-split .chat-filter-bar { cursor: pointer; text-decoration: none !important; } - -.ns-btn-primary:hover, -.nebula-btn-primary:hover { +.ns-btn-primary:hover { background: linear-gradient(135deg, #5B70FF 0%, #A276FF 100%) !important; box-shadow: 0 6px 24px rgba(77, 99, 255, 0.6), 0 0 12px rgba(187, 120, 255, 0.4) !important; transform: translateY(-1px); color: #FFFFFF !important; } - -.ns-btn-secondary, -.nebula-btn-secondary { - background-color: var(--nebula-bg-card, #151F33) !important; - border: 1px solid var(--nebula-border, #26344F) !important; - color: var(--nebula-text-main, #F3F5FC) !important; +.ns-btn-secondary { + background-color: var(--nebula-bg-card) !important; + border: 1px solid var(--nebula-border) !important; + color: var(--nebula-text-main) !important; border-radius: var(--ns-radius-md) !important; font-weight: 500 !important; - transition: all 0.2s ease !important; + transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease, transform 0.2s ease !important; display: inline-flex; align-items: center; gap: 8px; text-decoration: none !important; } - -.ns-btn-secondary:hover, -.nebula-btn-secondary:hover { - background-color: var(--nebula-bg-active, #202C48) !important; - border-color: var(--nebula-accent-primary, #4D63FF) !important; +.ns-btn-secondary:hover { + background-color: var(--nebula-bg-active) !important; + border-color: var(--nebula-accent-primary) !important; color: #FFFFFF !important; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5); } - /* Command Rail Brand Glyph with Cosmic Glow */ .ns-brand-glyph { color: #FFFFFF !important; - background: linear-gradient(135deg, #4D63FF 0%, #9365FF 100%) !important; + background: var(--nebula-gradient-primary) !important; border-color: rgba(255, 255, 255, 0.2) !important; box-shadow: 0 0 16px rgba(77, 99, 255, 0.5) !important; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5) !important; - border-radius: 10px !important; + border-radius: var(--nebula-radius-sm) !important; } - .ns-brand-glyph:hover { box-shadow: 0 0 24px rgba(147, 101, 255, 0.7) !important; transform: scale(1.05); } - .ns-rail-item.is-active { - color: var(--nebula-accent-primary, #4D63FF) !important; + color: var(--nebula-accent-primary) !important; background-color: rgba(77, 99, 255, 0.15) !important; border-color: rgba(77, 99, 255, 0.4) !important; box-shadow: 0 0 12px rgba(77, 99, 255, 0.25) !important; } - .ns-rail-item.is-active::before { - background-color: var(--nebula-accent-primary, #4D63FF) !important; - box-shadow: 0 0 8px var(--nebula-accent-primary, #4D63FF) !important; + background-color: var(--nebula-accent-primary) !important; + box-shadow: 0 0 8px var(--nebula-accent-primary) !important; } - /* NEBULA Cards & Panels */ .ns-card-panel, -.ns-streamer-card, .vod-details, -.chat-panel, -.nebula-panel { - background: var(--nebula-bg-surface, #111A2B) !important; - border: 1px solid var(--nebula-border, #26344F) !important; +.chat-panel { + background: var(--nebula-bg-surface) !important; + border: 1px solid var(--nebula-border) !important; border-radius: var(--ns-radius-lg) !important; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); } - -.ns-streamer-card:hover { - border-color: var(--nebula-accent-primary, #4D63FF) !important; - box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6), 0 0 16px rgba(77, 99, 255, 0.2) !important; -} - /* Telemetry & Metrics */ .ns-telemetry-bar { - background: var(--nebula-bg-surface, #111A2B) !important; - border: 1px solid var(--nebula-border, #26344F) !important; + background: var(--nebula-bg-surface) !important; + border: 1px solid var(--nebula-border) !important; border-radius: var(--ns-radius-md) !important; } - /* Status Pills */ .ns-pill-live, .nebula-live-badge { background: rgba(240, 68, 88, 0.18) !important; border: 1px solid rgba(240, 68, 88, 0.45) !important; - color: #F04458 !important; + color: var(--nebula-status-live) !important; font-weight: 700 !important; border-radius: var(--ns-radius-full) !important; display: inline-flex; align-items: center; gap: 6px; } - .nebula-live-dot { width: 8px; height: 8px; border-radius: 50%; - background-color: #F04458; - box-shadow: 0 0 8px #F04458; + background-color: var(--nebula-status-live); + box-shadow: 0 0 8px var(--nebula-status-live); animation: nebula-pulse 1.8s infinite; } - @keyframes nebula-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.85); } } - -.ns-pill-offline { - background: rgba(117, 131, 157, 0.15) !important; - border-color: rgba(117, 131, 157, 0.3) !important; - color: #A2AEC8 !important; -} - -.ns-pill-drive { - background: rgba(105, 201, 255, 0.15) !important; - border-color: rgba(105, 201, 255, 0.4) !important; - color: #69C9FF !important; -} - /* Storage Meter Bar */ .ns-meter-fill { - background: linear-gradient(90deg, #4D63FF 0%, #BB78FF 100%) !important; + background: linear-gradient(90deg, var(--nebula-accent-primary) 0%, var(--nebula-accent-highlight) 100%) !important; box-shadow: 0 0 10px rgba(147, 101, 255, 0.4) !important; } - /* Input Fields & Selects */ .ns-input-field, input[type="text"], input[type="password"], input[type="search"], select { - background: var(--nebula-bg-surface, #111A2B) !important; - border: 1px solid var(--nebula-border, #26344F) !important; - color: var(--nebula-text-main, #F3F5FC) !important; + background: var(--nebula-bg-surface) !important; + border: 1px solid var(--nebula-border) !important; + color: var(--nebula-text-main) !important; border-radius: var(--ns-radius-md) !important; } - .ns-input-field:focus, input[type="text"]:focus, input[type="password"]:focus, input[type="search"]:focus, select:focus { - border-color: var(--nebula-accent-primary, #4D63FF) !important; + border-color: var(--nebula-accent-primary) !important; box-shadow: 0 0 12px rgba(77, 99, 255, 0.4) !important; - outline: none !important; } - /* ========================================================= NEBULA COMPONENT SPECIFICATIONS ========================================================= */ - /* Hero Banner */ -.nebula-hero { - position: relative; - background: linear-gradient(135deg, rgba(17, 26, 43, 0.95) 0%, rgba(11, 18, 32, 0.98) 100%), - radial-gradient(circle at 85% 20%, rgba(147, 101, 255, 0.25) 0%, transparent 65%); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 16px; - padding: 32px; - margin-bottom: 28px; - overflow: hidden; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.08); -} - .nebula-hero-glow { position: absolute; top: -60px; @@ -3160,13 +1909,6 @@ select:focus { background: radial-gradient(circle, rgba(77, 99, 255, 0.35) 0%, transparent 70%); pointer-events: none; } - -.nebula-hero-content { - position: relative; - z-index: 2; - max-width: 680px; -} - .nebula-hero-badge { display: inline-flex; align-items: center; @@ -3175,32 +1917,29 @@ select:focus { background: rgba(77, 99, 255, 0.15); border: 1px solid rgba(77, 99, 255, 0.35); border-radius: var(--ns-radius-full); - color: #69C9FF; - font-size: 12px; + color: var(--nebula-accent-cyan); + font-size: var(--sv-text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 14px; } - .nebula-hero-title { - font-size: 28px; + font-size: var(--sv-text-3xl); font-weight: 700; line-height: 1.25; color: #FFFFFF; margin: 0 0 10px 0; letter-spacing: -0.5px; } - .nebula-hero-meta { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; - color: var(--nebula-text-secondary, #A2AEC8); - font-size: 14px; + color: var(--nebula-text-secondary); + font-size: var(--sv-text-md); } - .nebula-hero-streamer { display: flex; align-items: center; @@ -3208,30 +1947,27 @@ select:focus { font-weight: 600; color: #FFFFFF; } - .nebula-hero-avatar { width: 28px; height: 28px; border-radius: 50%; - border: 2px solid var(--nebula-accent-primary, #4D63FF); - background: #151F33; + border: 2px solid var(--nebula-accent-primary); + background: var(--nebula-bg-card); overflow: hidden; display: flex; align-items: center; justify-content: center; - font-size: 11px; + font-size: var(--sv-min-text); font-weight: 700; color: #FFF; } - .nebula-hero-cat { padding: 2px 10px; background: rgba(255, 255, 255, 0.08); - border-radius: 6px; - color: #BB78FF; - font-size: 13px; + border-radius: var(--nebula-radius-xs); + color: var(--nebula-accent-highlight); + font-size: var(--sv-text-sm); } - /* VOD Discovery Grid */ .nebula-vod-grid { display: grid; @@ -3239,44 +1975,38 @@ select:focus { gap: 20px; margin-bottom: 32px; } - .nebula-vod-card { display: flex; flex-direction: column; - background: var(--nebula-bg-card, #151F33); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 12px; + background: var(--nebula-bg-card); + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-md); overflow: hidden; text-decoration: none !important; color: inherit !important; transition: transform 0.2s cubic-bezier(0.2, 0, 0, 1), box-shadow 0.2s ease, border-color 0.2s ease; } - .nebula-vod-card:hover { transform: translateY(-4px); - border-color: var(--nebula-accent-primary, #4D63FF); + border-color: var(--nebula-accent-primary); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6), 0 0 16px rgba(77, 99, 255, 0.25); } - .nebula-vod-thumb-box { position: relative; width: 100%; aspect-ratio: 16 / 9; - background: #0B1220; + background: var(--nebula-bg-deep); overflow: hidden; } - .nebula-vod-thumb-img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s ease; } - .nebula-vod-card:hover .nebula-vod-thumb-img { transform: scale(1.04); } - .nebula-vod-duration { position: absolute; bottom: 8px; @@ -3286,12 +2016,11 @@ select:focus { backdrop-filter: none; color: #FFFFFF; font-family: var(--ns-font-mono); - font-size: 11px; + font-size: var(--sv-min-text); font-weight: 600; - border-radius: 4px; + border-radius: var(--nebula-radius-xs); border: 1px solid rgba(255, 255, 255, 0.1); } - .nebula-vod-streamer-badge { position: absolute; top: 8px; @@ -3299,13 +2028,12 @@ select:focus { padding: 2px 8px; background: rgba(17, 26, 43, 0.85); backdrop-filter: none; - color: #A2AEC8; - font-size: 11px; + color: var(--nebula-text-secondary); + font-size: var(--sv-min-text); font-weight: 600; - border-radius: 4px; + border-radius: var(--nebula-radius-xs); border: 1px solid rgba(255, 255, 255, 0.08); } - .nebula-vod-play-overlay { position: absolute; inset: 0; @@ -3316,51 +2044,45 @@ select:focus { opacity: 0; transition: opacity 0.2s ease; } - .nebula-vod-card:hover .nebula-vod-play-overlay { opacity: 1; } - .nebula-vod-play-circle { width: 44px; height: 44px; border-radius: 50%; - background: var(--nebula-gradient-primary, linear-gradient(135deg, #4D63FF 0%, #9365FF 100%)); + background: var(--nebula-gradient-primary, var(--nebula-gradient-primary)); display: flex; align-items: center; justify-content: center; box-shadow: 0 0 16px rgba(77, 99, 255, 0.6); color: #FFFFFF; } - .nebula-vod-body { padding: 14px; display: flex; flex-direction: column; flex: 1; } - .nebula-vod-title { - font-size: 14px; + font-size: var(--sv-text-md); font-weight: 600; line-height: 1.4; - color: var(--nebula-text-main, #F3F5FC); + color: var(--nebula-text-main); margin: 0 0 8px 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } - .nebula-vod-footer { margin-top: auto; display: flex; align-items: center; justify-content: space-between; - font-size: 12px; - color: var(--nebula-text-muted, #75839D); + font-size: var(--sv-text-xs); + color: var(--nebula-text-muted); } - /* Section Header */ .nebula-section-header { display: flex; @@ -3368,30 +2090,16 @@ select:focus { justify-content: space-between; margin: 28px 0 16px 0; } - .nebula-section-title { display: flex; align-items: center; gap: 10px; - font-size: 18px; + font-size: var(--sv-text-lg); font-weight: 700; color: #FFFFFF; margin: 0; letter-spacing: -0.3px; } - -.nebula-section-link { - font-size: 13px; - color: var(--nebula-accent-primary, #4D63FF); - text-decoration: none; - font-weight: 500; - transition: color 0.15s ease; -} - -.nebula-section-link:hover { - color: var(--nebula-accent-highlight, #BB78FF); -} - /* Two-Column Home Grid: Main content + Community sidebar */ .nebula-home-layout { display: grid; @@ -3400,22 +2108,19 @@ select:focus { min-width: 0; gap: 28px; } - @media (max-width: 1200px) { .nebula-home-layout { grid-template-columns: 1fr; } } - /* Right Rail Widgets */ .nebula-side-widget { - background: var(--nebula-bg-surface, #111A2B); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 12px; + background: var(--nebula-bg-surface); + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-md); padding: 18px; margin-bottom: 20px; } - .nebula-widget-head { display: flex; align-items: center; @@ -3424,92 +2129,82 @@ select:focus { padding-bottom: 10px; border-bottom: 1px solid rgba(38, 52, 79, 0.6); } - .nebula-widget-head h3 { - font-size: 14px; + font-size: var(--sv-text-md); font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: #FFFFFF; margin: 0; } - .nebula-category-list { display: flex; flex-direction: column; gap: 8px; } - .nebula-category-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; - background: var(--nebula-bg-card, #151F33); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 8px; + background: var(--nebula-bg-card); + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-sm); text-decoration: none; - color: var(--nebula-text-main, #F3F5FC); - font-size: 13px; - transition: all 0.15s ease; + color: var(--nebula-text-main); + font-size: var(--sv-text-sm); + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease; } - .nebula-category-item:hover { - background: var(--nebula-bg-active, #202C48); - border-color: var(--nebula-accent-primary, #4D63FF); + background: var(--nebula-bg-active); + border-color: var(--nebula-accent-primary); transform: translateX(2px); } - .nebula-category-count { font-family: var(--ns-font-mono); - font-size: 11px; - color: #A2AEC8; + font-size: var(--sv-min-text); + color: var(--nebula-text-secondary); background: rgba(255, 255, 255, 0.08); padding: 2px 6px; - border-radius: 4px; + border-radius: var(--nebula-radius-xs); } - /* Top Global Search */ .ns-search-box { display: flex; align-items: center; - background: var(--nebula-bg-surface, #111A2B); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 10px; + background: var(--nebula-bg-surface); + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-sm); padding: 6px 14px; width: 100%; max-width: 440px; - transition: all 0.2s ease; + transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease, transform 0.2s ease; } - .ns-search-box:focus-within { - border-color: var(--nebula-accent-primary, #4D63FF); + border-color: var(--nebula-accent-primary); box-shadow: 0 0 12px rgba(77, 99, 255, 0.35); } - .ns-search-box input { background: transparent !important; border: none !important; color: #FFFFFF !important; - font-size: 13px; + font-size: var(--sv-text-sm); width: 100%; - outline: none !important; box-shadow: none !important; padding: 2px 8px; } - .ns-search-box svg { - color: var(--nebula-text-muted, #75839D); + color: var(--nebula-text-muted); flex-shrink: 0; } - - /* Strict Protection: Never apply CRT filters or scanlines over video content! */ -video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { +video, +#vodPlayer, +.player-wrapper video, +.twitch-embed-wrapper iframe { filter: none !important; pointer-events: auto !important; } - /* Reduced motion preference */ @media (prefers-reduced-motion: reduce) { * { @@ -3518,38 +2213,34 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { transition-duration: 0.001ms !important; } } - - /* ========================================================= 7. RESPONSIVE MOBILE & TABLET LAYOUTS ========================================================= */ /* ========================================================================== MOBILE UI/UX OVERHAUL & RESPONSIVE HARDENING (< 768px) ========================================================================== */ - /* Hide Mobile Global Nav on Desktop */ .mobile-global-nav { display: none !important; } - @media (max-width: 768px) { :root { --ns-rail-width: 0px !important; } - /* 1. Global Viewport & Container Containment */ - html, body { + html, + body { overflow-x: hidden !important; max-width: 100vw !important; width: 100% !important; box-sizing: border-box !important; -webkit-text-size-adjust: 100% !important; } - - *, *::before, *::after { + *, + *::before, + *::after { box-sizing: border-box !important; } - /* 2. Desktop Rail Suppression & Content Margin Reset */ .ns-command-rail, aside.ns-command-rail, @@ -3565,7 +2256,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { pointer-events: none !important; overflow: hidden !important; } - body.ns-platform > .main, body.ns-platform .main, body.ns-platform .ns-app-main, @@ -3579,7 +2269,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { padding-right: 12px !important; box-sizing: border-box !important; } - /* 3. Global Padding Protection against Fixed Bottom Bar Overlap */ body, .ns-workspace-content, @@ -3590,7 +2279,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { padding-bottom: calc(76px + env(safe-area-inset-bottom, 16px)) !important; box-sizing: border-box !important; } - /* 4. Fluid Header & Search Box Stacking */ .ns-workspace-header { padding: 12px 14px !important; @@ -3607,31 +2295,27 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { background: rgba(7, 11, 20, 0.94) !important; backdrop-filter: none; -webkit-backdrop-filter: none; - border-bottom: 1px solid var(--nebula-border, #26344F) !important; + border-bottom: 1px solid var(--nebula-border) !important; box-sizing: border-box !important; } - .ns-header-title-block { flex: 1 1 auto !important; min-width: 0 !important; } - .ns-header-title-block h1 { - font-size: 18px !important; + font-size: var(--sv-text-lg) !important; margin: 0 !important; overflow: hidden !important; text-overflow: ellipsis !important; white-space: nowrap !important; } - .ns-header-title-block p { - font-size: 12px !important; + font-size: var(--sv-text-xs) !important; margin: 2px 0 0 0 !important; overflow: hidden !important; text-overflow: ellipsis !important; white-space: nowrap !important; } - .ns-search-box { order: 3 !important; width: 100% !important; @@ -3639,7 +2323,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { margin-top: 4px !important; box-sizing: border-box !important; } - .ns-header-actions { flex: 1 1 100% !important; display: flex !important; @@ -3647,7 +2330,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { gap: 8px !important; min-width: 0 !important; } - /* 5. Mobile Global Navigation Bar (Pixel-Perfect, Zero-Overlap) */ .mobile-global-nav { display: flex !important; @@ -3661,7 +2343,7 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { background: rgba(7, 11, 20, 0.95) !important; backdrop-filter: none; -webkit-backdrop-filter: none; - border-top: 1px solid var(--nebula-border, #26344F) !important; + border-top: 1px solid var(--nebula-border) !important; justify-content: space-around !important; align-items: center !important; z-index: 999999 !important; @@ -3669,16 +2351,15 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { box-sizing: border-box !important; box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.6) !important; } - .mobile-global-nav a, .mobile-global-nav button { background: transparent !important; border: none !important; - color: var(--nebula-text-muted, #75839D) !important; + color: var(--nebula-text-muted) !important; text-decoration: none !important; - font-size: 11px !important; + font-size: var(--sv-min-text) !important; font-weight: 600 !important; - font-family: var(--ns-font-sans, inherit) !important; + font-family: var(--ns-font-sans) !important; display: flex !important; flex-direction: column !important; align-items: center !important; @@ -3690,23 +2371,20 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { padding: 4px 6px !important; margin: 0 !important; cursor: pointer !important; - border-radius: 8px !important; + border-radius: var(--nebula-radius-sm) !important; transition: color 80ms ease, transform 80ms ease !important; touch-action: manipulation !important; -webkit-tap-highlight-color: transparent !important; box-sizing: border-box !important; } - .mobile-global-nav a:hover, .mobile-global-nav button:hover { - color: var(--nebula-text-primary, #F3F5FC) !important; + color: var(--nebula-text-primary, var(--nebula-text-main)) !important; } - .mobile-global-nav a.active { - color: #4D63FF !important; + color: var(--nebula-accent-primary) !important; font-weight: 700 !important; } - .mobile-global-nav svg { width: 22px !important; height: 22px !important; @@ -3719,28 +2397,24 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { flex-shrink: 0 !important; display: block !important; } - .mobile-global-nav a.active svg { transform: scale(1.1) !important; - stroke: #4D63FF !important; + stroke: var(--nebula-accent-primary) !important; filter: drop-shadow(0 0 6px rgba(77, 99, 255, 0.6)) !important; } - .mobile-global-nav a:active, .mobile-global-nav button:active { transform: scale(0.92) !important; transition-duration: 0ms !important; } - .mobile-global-nav span { - font-size: 11px !important; + font-size: var(--sv-min-text) !important; line-height: 1.2 !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; max-width: 100% !important; } - /* 6. Form Inputs & Select Auto-Zoom Suppression */ input[type="text"], input[type="search"], @@ -3750,40 +2424,28 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { input[type="url"], select, textarea { - font-size: 16px !important; /* 16px eliminates iOS zoom */ + font-size: var(--sv-text-base) !important; max-width: 100% !important; box-sizing: border-box !important; } - form { max-width: 100% !important; box-sizing: border-box !important; } - /* 7. Grid & Flexbox Mobile Hardening */ .ns-ops-grid, .nebula-home-layout, - .ns-video-grid, - .ns-streamer-grid, - .channels-grid, - .admin-grid, - .grid-2, - .grid-3, - .grid-4 { + .ns-video-grid { display: flex !important; flex-direction: column !important; width: 100% !important; max-width: 100% !important; gap: 16px !important; } - /* 8. Card & Container Protection */ .card, .ns-video-card, - .nebula-card, .vod-card, - .streamer-card, - .settings-card, .nebula-profile-card, .nebula-hero, .nebula-admin-box, @@ -3794,27 +2456,18 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { box-sizing: border-box !important; overflow: hidden !important; } - .nebula-profile-body { - flex-direction: column !important; - align-items: center !important; - text-align: center !important; padding: 16px !important; gap: 16px !important; } - .nebula-profile-details { - flex-direction: column !important; - align-items: center !important; text-align: center !important; gap: 12px !important; } - .nebula-profile-tags { justify-content: center !important; flex-wrap: wrap !important; } - /* 9. VOD Player & Detail Panels (Stacking without side chat crushing) */ body.page-vod .content, body.page-live .content, @@ -3828,7 +2481,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { overflow-y: visible !important; gap: 16px !important; } - body.page-vod .main-col, body.page-live .main-col, body.page-twitch-watch .main-col { @@ -3836,7 +2488,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { max-width: 100% !important; min-width: 0 !important; } - body.page-vod .player-wrapper, body.page-live .player-wrapper, body.page-twitch-watch .player-wrapper { @@ -3845,7 +2496,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { aspect-ratio: 16 / 9 !important; height: auto !important; } - body.page-vod .vod-details, body.page-live .vod-details, body.page-twitch-watch .vod-details { @@ -3854,7 +2504,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { box-sizing: border-box !important; padding: 14px 16px !important; } - body.page-vod .vod-file-actions, body.page-live .vod-file-actions { display: flex !important; @@ -3863,7 +2512,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { max-width: 100% !important; width: 100% !important; } - body.page-vod .chat-panel, body.page-live .chat-panel, body.page-twitch-watch .chat-panel { @@ -3874,7 +2522,6 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { min-height: 350px !important; box-sizing: border-box !important; } - /* 10. Login Modal Mobile Hardening */ body.page-login .nebula-login-wrapper { padding: 16px 12px !important; @@ -3882,33 +2529,26 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { max-width: 100% !important; box-sizing: border-box !important; } - body.page-login .nebula-login-modal { padding: 28px 18px 24px !important; width: 100% !important; max-width: 100% !important; box-sizing: border-box !important; - border-radius: 16px !important; + border-radius: var(--nebula-radius-lg) !important; } - /* 11. Text Truncation & Ellipsis Protection */ .vod-title, - .streamer-title, - .card-title, - .video-title, .nebula-profile-name, .ns-video-card h3, .ns-video-card h4, - .nebula-vod-card h4 { + .nebula-vod-card :is(h3, h4) { overflow: hidden !important; text-overflow: ellipsis !important; white-space: nowrap !important; max-width: 100% !important; } - /* 12. Tables & Code Blocks Horizontal Scrolling */ table, - .table-responsive, pre, code { max-width: 100% !important; @@ -3916,96 +2556,73 @@ video, #vodPlayer, .player-wrapper video, .twitch-embed-wrapper iframe { -webkit-overflow-scrolling: touch !important; } } - /* ========================================================= NEBULA LOGIN PORTAL STYLING ========================================================= */ body.page-login { - background: var(--nebula-bg-root, #070B14) !important; - color: var(--nebula-text-main, #F3F5FC) !important; + background: var(--nebula-bg-root) !important; + color: var(--nebula-text-main) !important; } - body.page-login .login-shell { max-width: 960px; } - body.page-login .eyebrow { - color: var(--nebula-accent-highlight, #BB78FF) !important; + color: var(--nebula-accent-highlight) !important; font-weight: 700 !important; text-transform: uppercase; letter-spacing: 1px; } - body.page-login h1 { color: #FFFFFF !important; text-shadow: 0 0 30px rgba(77, 99, 255, 0.4); } - body.page-login .subtitle { - color: var(--nebula-text-secondary, #A2AEC8) !important; + color: var(--nebula-text-secondary) !important; } - body.page-login .login-panel { - background: var(--nebula-bg-surface, #111A2B) !important; - border: 1px solid var(--nebula-border, #26344F) !important; - border-radius: 16px !important; + background: var(--nebula-bg-surface) !important; + border: 1px solid var(--nebula-border) !important; + border-radius: var(--nebula-radius-lg) !important; box-shadow: 0 16px 48px rgba(0, 0, 0, 0.7), 0 0 24px rgba(77, 99, 255, 0.2) !important; } - body.page-login .login-form label { - color: var(--nebula-text-secondary, #A2AEC8) !important; + color: var(--nebula-text-secondary) !important; font-weight: 600; - font-size: 12px; + font-size: var(--sv-text-xs); text-transform: uppercase; letter-spacing: 0.5px; } - body.page-login input { - background: var(--nebula-bg-card, #151F33) !important; - border: 1px solid var(--nebula-border, #26344F) !important; + background: var(--nebula-bg-card) !important; + border: 1px solid var(--nebula-border) !important; color: #FFFFFF !important; - border-radius: 8px !important; + border-radius: var(--nebula-radius-sm) !important; } - body.page-login input:focus { - border-color: var(--nebula-accent-primary, #4D63FF) !important; + border-color: var(--nebula-accent-primary) !important; box-shadow: 0 0 12px rgba(77, 99, 255, 0.4) !important; } - -body.page-login button#login-submit, -body.page-login button[type="submit"] { - background: linear-gradient(135deg, #4D63FF 0%, #9365FF 100%) !important; +body.page-login button:where(:not(.sv-btn))#login-submit, +body.page-login button:where(:not(.sv-btn))[type="submit"] { + background: var(--nebula-gradient-primary) !important; color: #FFFFFF !important; font-weight: 700 !important; border: 1px solid rgba(255, 255, 255, 0.2) !important; - border-radius: 8px !important; + border-radius: var(--nebula-radius-sm) !important; box-shadow: 0 4px 20px rgba(77, 99, 255, 0.5) !important; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5) !important; - transition: all 0.2s ease !important; + transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease, transform 0.2s ease !important; cursor: pointer; } - -body.page-login button#login-submit:hover, -body.page-login button[type="submit"]:hover { +body.page-login button:where(:not(.sv-btn))#login-submit:hover, +body.page-login button:where(:not(.sv-btn))[type="submit"]:hover { background: linear-gradient(135deg, #5B70FF 0%, #A276FF 100%) !important; box-shadow: 0 6px 28px rgba(77, 99, 255, 0.7), 0 0 16px rgba(187, 120, 255, 0.4) !important; transform: translateY(-1px); } - -body.page-login .login-register { - background: rgba(11, 18, 32, 0.6) !important; - border: 1px solid var(--nebula-border, #26344F) !important; - border-radius: 10px !important; -} - -body.page-login .login-register-kicker { - color: var(--nebula-accent-highlight, #BB78FF) !important; - font-weight: 700 !important; -} /* ========================================================================== NEBULA REBUILD V2 - CORE ENHANCEMENTS ========================================================================== */ - /* 1. Ghost Pseudo-Element Suppression on Command Rail */ /* 1. Ghost Pseudo-Element & Icon Duplicate Suppression on Command Rail */ .ns-command-rail *::before, @@ -4016,12 +2633,8 @@ aside.ns-command-rail *::after, .ns-command-rail a::after, .ns-command-rail button::before, .ns-command-rail button::after, -.ns-command-rail .nav-item::before, -.ns-command-rail .nav-item::after, .ns-command-rail .ns-rail-item::before, -.ns-command-rail .ns-rail-item::after, -.ns-command-rail .logout-button::before, -.ns-command-rail .logout-button::after { +.ns-command-rail .ns-rail-item::after { content: none !important; display: none !important; width: 0 !important; @@ -4030,13 +2643,12 @@ aside.ns-command-rail *::after, -webkit-mask: none !important; background: transparent !important; } - /* 2. Enhanced Cinematic Hero Banner (Panel 01) */ .nebula-hero { position: relative; - background: var(--nebula-bg-surface, #111A2B); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 16px; + background: var(--nebula-bg-surface); + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-lg); padding: 28px 32px; margin-bottom: 24px; overflow: hidden; @@ -4047,7 +2659,6 @@ aside.ns-command-rail *::after, gap: 32px; min-height: 260px; } - .nebula-hero-backdrop { position: absolute; inset: 0; @@ -4058,22 +2669,19 @@ aside.ns-command-rail *::after, z-index: 1; pointer-events: none; } - .nebula-hero-overlay { position: absolute; inset: 0; - background: linear-gradient(90deg, #070B14 0%, rgba(7, 11, 20, 0.9) 45%, rgba(7, 11, 20, 0.4) 100%); + background: linear-gradient(90deg, var(--nebula-bg-root) 0%, rgba(7, 11, 20, 0.9) 45%, rgba(7, 11, 20, 0.4) 100%); z-index: 1; pointer-events: none; } - .nebula-hero-content { position: relative; z-index: 2; flex: 1; max-width: 620px; } - .nebula-hero-preview-col { position: relative; z-index: 2; @@ -4081,24 +2689,21 @@ aside.ns-command-rail *::after, width: 360px; max-width: 42%; } - .nebula-hero-preview-frame { position: relative; aspect-ratio: 16 / 9; - border-radius: 12px; + border-radius: var(--nebula-radius-md); overflow: hidden; border: 1px solid rgba(77, 99, 255, 0.45); box-shadow: 0 12px 32px rgba(0, 0, 0, 0.75), 0 0 20px rgba(77, 99, 255, 0.25); - background: #0B1220; + background: var(--nebula-bg-deep); } - .nebula-hero-preview-img { width: 100%; height: 100%; object-fit: cover; display: block; } - .nebula-hero-play-icon { position: absolute; top: 50%; @@ -4116,29 +2721,25 @@ aside.ns-command-rail *::after, pointer-events: none; transition: transform 0.2s ease; } - .nebula-hero-preview-frame:hover .nebula-hero-play-icon { transform: translate(-50%, -50%) scale(1.1); } - /* 3. Streamer Profile (Panel 04) */ .nebula-profile-card { position: relative; - background: var(--nebula-bg-surface, #111A2B); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 16px; + background: var(--nebula-bg-surface); + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-lg); overflow: hidden; margin-bottom: 24px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5); } - .nebula-profile-banner { height: 140px; background: linear-gradient(135deg, rgba(77, 99, 255, 0.35) 0%, rgba(147, 101, 255, 0.3) 50%, rgba(11, 18, 32, 0.95) 100%), radial-gradient(circle at 80% 20%, rgba(105, 201, 255, 0.25) 0%, transparent 65%); position: relative; } - .nebula-profile-body { padding: 0 28px 24px; margin-top: -46px; @@ -4150,66 +2751,59 @@ aside.ns-command-rail *::after, position: relative; z-index: 2; } - .nebula-profile-avatar { width: 92px; height: 92px; border-radius: 50%; - border: 3px solid #9365FF; + border: 3px solid var(--nebula-accent-secondary); box-shadow: 0 0 24px rgba(147, 101, 255, 0.5); - background: #151F33; + background: var(--nebula-bg-card); display: flex; align-items: center; justify-content: center; - font-size: 32px; + font-size: var(--sv-text-4xl); font-weight: 800; color: #FFF; overflow: hidden; flex-shrink: 0; } - .nebula-profile-details { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; } - .nebula-profile-name { - font-size: 26px; + font-size: var(--sv-text-2xl); font-weight: 700; color: #FFFFFF; margin: 0 0 6px 0; letter-spacing: -0.5px; } - .nebula-profile-tags { display: flex; align-items: center; gap: 8px; - font-size: 13px; - color: var(--nebula-text-secondary, #A2AEC8); + font-size: var(--sv-text-sm); + color: var(--nebula-text-secondary); } - .nebula-admin-box { background: rgba(11, 18, 32, 0.7); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 12px; + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-md); padding: 16px 20px; margin-bottom: 24px; } - .nebula-btn-danger { background: rgba(240, 68, 88, 0.15) !important; - color: #F04458 !important; + color: var(--nebula-status-live-text) !important; border: 1px solid rgba(240, 68, 88, 0.4) !important; } .nebula-btn-danger:hover { background: rgba(240, 68, 88, 0.3) !important; - border-color: #F04458 !important; + border-color: var(--nebula-status-live) !important; box-shadow: 0 0 12px rgba(240, 68, 88, 0.4) !important; } - /* 4. VOD Player Fallback & Chat Initial State (Panel 03) */ .vod-player-error-overlay { position: absolute; @@ -4221,11 +2815,10 @@ aside.ns-command-rail *::after, justify-content: center; gap: 16px; z-index: 10; - color: #F3F5FC; + color: var(--nebula-text-main); text-align: center; padding: 24px; } - .vod-chat-empty-state { display: flex; flex-direction: column; @@ -4235,18 +2828,17 @@ aside.ns-command-rail *::after, min-height: 200px; padding: 32px 20px; text-align: center; - color: #75839D; - font-size: 13px; + color: var(--nebula-text-muted); + font-size: var(--sv-text-sm); line-height: 1.5; } - /* 5. Centered NEBULA Login Portal (Panel 10) */ .nebula-login-wrapper { min-height: 100vh; display: flex; align-items: center; justify-content: center; - background: #070B14; + background: var(--nebula-bg-root); background-image: radial-gradient(circle at 50% 25%, rgba(147, 101, 255, 0.18) 0%, transparent 60%), radial-gradient(circle at 80% 80%, rgba(77, 99, 255, 0.14) 0%, transparent 55%); padding: 24px; @@ -4254,40 +2846,37 @@ aside.ns-command-rail *::after, position: relative; z-index: 10; } - .nebula-login-modal { width: 100%; max-width: 440px; background: rgba(17, 26, 43, 0.9); backdrop-filter: none; - border: 1px solid var(--nebula-border, #26344F); - border-radius: 20px; + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-lg); padding: 40px 32px 32px; box-shadow: 0 24px 64px rgba(0, 0, 0, 0.8), 0 0 32px rgba(77, 99, 255, 0.15); text-align: center; position: relative; box-sizing: border-box; } - .nebula-login-logo { width: 56px; height: 56px; - border-radius: 14px; - background: linear-gradient(135deg, #4D63FF 0%, #9365FF 100%); + border-radius: var(--nebula-radius-md); + background: var(--nebula-gradient-primary); box-shadow: 0 0 24px rgba(147, 101, 255, 0.5); display: inline-flex; align-items: center; justify-content: center; - font-size: 26px; + font-size: var(--sv-text-2xl); font-weight: 800; color: #FFF; margin-bottom: 14px; } - /* Legacy `body.page-login h1` rules in style.css force 42–78px with !important; the card heading must stay inside the 440px login card. */ body.page-login .nebula-login-h1 { - font-size: 28px !important; + font-size: var(--sv-text-3xl) !important; font-weight: 700 !important; line-height: 1.2 !important; color: #FFF !important; @@ -4296,68 +2885,20 @@ body.page-login .nebula-login-h1 { text-shadow: none !important; overflow-wrap: anywhere; } - body.page-login .nebula-login-h1::after { content: none !important; } - .nebula-login-sub { - font-size: 13px; - color: var(--nebula-text-secondary, #A2AEC8); + font-size: var(--sv-text-sm); + color: var(--nebula-text-secondary); margin: 0 0 24px 0; line-height: 1.45; } - -.nebula-btn-discord { - width: 100%; - display: flex; - align-items: center; - justify-content: center; - gap: 12px; - padding: 13px 20px; - background: #5865F2; - color: #FFFFFF !important; - font-size: 15px; - font-weight: 600; - border-radius: 10px; - text-decoration: none; - border: 1px solid rgba(255, 255, 255, 0.15); - transition: all 0.2s ease; - box-shadow: 0 6px 20px rgba(88, 101, 242, 0.35); - cursor: pointer; - box-sizing: border-box; -} - -.nebula-btn-discord:hover { - background: #4752C4; - transform: translateY(-2px); - box-shadow: 0 8px 25px rgba(88, 101, 242, 0.5); -} - -.nebula-login-sep { - display: flex; - align-items: center; - gap: 12px; - margin: 22px 0 18px; - color: #75839D; - font-size: 11px; - text-transform: uppercase; - letter-spacing: 0.5px; -} -.nebula-login-sep::before, -.nebula-login-sep::after { - content: ""; - flex: 1; - height: 1px; - background: #26344F; -} - .nebula-login-footer-tag { margin-top: 24px; - font-size: 12px; - color: #75839D; + font-size: var(--sv-text-xs); + color: var(--nebula-text-muted); } - /* 6. Mobile Optimization (Panel 07) */ @media (max-width: 768px) { .nebula-hero { @@ -4380,14 +2921,12 @@ body.page-login .nebula-login-h1::after { align-items: center !important; } } - -.vod-player-error-overlay[hidden] { display: none !important; } - - +.vod-player-error-overlay[hidden] { + display: none !important; +} /* ========================================================================== ULTRA-LOW-LATENCY & INSTANT-FEEDBACK ENGINE (< 16ms Reaction) ========================================================================== */ - /* 1. Global Touch & Tap Latency Elimination */ button, input[type="button"], @@ -4400,17 +2939,13 @@ input[type="reset"], .btn-danger, .ns-btn, .nebula-btn, -.action-btn, .tab-btn, a.button, -.nav-btn, .nebula-streamer-card, .nebula-vod-card, .vod-card, -.nebula-card, .sidebar-link, -.channel-item, -.chip-filter { +.channel-item { touch-action: manipulation; -webkit-tap-highlight-color: transparent; will-change: transform; @@ -4421,7 +2956,6 @@ a.button, box-shadow 80ms ease, filter 80ms ease; } - /* 2. Instant Zero-Latency Active States (< 16ms Frame Time) */ button:active, input[type="button"]:active, @@ -4433,49 +2967,37 @@ input[type="submit"]:active, .btn-danger:active, .ns-btn:active, .nebula-btn:active, -.action-btn:active, .tab-btn:active, a.button:active, -.nav-btn:active, .sidebar-link:active, -.chip-filter:active, .is-active-press { transform: scale(0.97) translateY(1px) !important; transition-duration: 0ms !important; filter: brightness(1.15) !important; } - /* Card Press Instant Feedback */ .nebula-streamer-card:active, .nebula-vod-card:active, .vod-card:active, -.nebula-card:active, .card:active { transform: scale(0.985) translateY(1px) !important; transition-duration: 0ms !important; filter: brightness(1.08) !important; } - /* GPU Rendering Hint for Backdrop Filters */ -.nebula-glass-card, .nebula-profile-card, -.nebula-sidebar, .ns-workspace-header { transform: translateZ(0); backface-visibility: hidden; } - - /* Direct In-Place Interaction for Banner and Avatar */ .nebula-profile-banner.is-editable { cursor: pointer; transition: filter 0.15s ease; } - .nebula-profile-banner.is-editable:hover { filter: brightness(1.08); } - .nebula-banner-edit-badge { position: absolute; top: 14px; @@ -4484,36 +3006,32 @@ a.button:active, border: 1px solid rgba(187, 120, 255, 0.5); backdrop-filter: none; color: #FFF; - font-size: 12px; + font-size: var(--sv-text-xs); font-weight: 700; padding: 6px 14px; - border-radius: 9999px; + border-radius: var(--nebula-radius-full); display: flex; align-items: center; gap: 6px; - transition: all 0.15s ease; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease, transform 0.15s ease; z-index: 5; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4); } - .nebula-profile-banner.is-editable:hover .nebula-banner-edit-badge { background: rgba(187, 120, 255, 0.35); - border-color: #BB78FF; + border-color: var(--nebula-accent-highlight); box-shadow: 0 0 16px rgba(187, 120, 255, 0.55); transform: translateY(-1px); } - .nebula-profile-avatar.is-editable { cursor: pointer; position: relative; transition: transform 0.15s ease, box-shadow 0.15s ease; } - .nebula-profile-avatar.is-editable:hover { transform: scale(1.04); box-shadow: 0 0 28px rgba(187, 120, 255, 0.75); } - .nebula-avatar-edit-overlay { position: absolute; inset: 0; @@ -4530,11 +3048,9 @@ a.button:active, transition: opacity 0.15s ease; z-index: 4; } - .nebula-profile-avatar.is-editable:hover .nebula-avatar-edit-overlay { opacity: 1; } - /* Modal Dialogs */ .nebula-modal-backdrop { position: fixed; @@ -4547,43 +3063,33 @@ a.button:active, justify-content: center; padding: 16px; } - .nebula-modal-card { width: 100%; max-width: 520px; - background: var(--nebula-bg-surface, #111A2B); - border: 1px solid var(--nebula-border, #26344F); - border-radius: 16px; + background: var(--nebula-bg-surface); + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-lg); box-shadow: 0 24px 64px rgba(0, 0, 0, 0.8), 0 0 32px rgba(187, 120, 255, 0.15); padding: 24px; position: relative; animation: nebulaModalFadeIn 0.15s ease; } - @keyframes nebulaModalFadeIn { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } } - - /* === NS-PERF-AND-PARITY-2026 === */ -html, body.ns-platform { +html, +body.ns-platform { overflow-x: hidden !important; max-width: 100vw !important; } - -.ns-app-shell { - max-width: 100vw !important; - overflow-x: hidden !important; -} - .ns-app-main { min-width: 0 !important; max-width: calc(100vw - var(--ns-rail-width, 0px)) !important; overflow-x: hidden !important; box-sizing: border-box !important; } - .ns-workspace-content, .nebula-home-layout, .nebula-main-col, @@ -4592,25 +3098,21 @@ html, body.ns-platform { max-width: 100% !important; box-sizing: border-box !important; } - details.streamer-menu:not([open]) > .streamer-menu-popover { display: none !important; } details.streamer-menu[open] > .streamer-menu-popover { display: flex !important; } - body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-facts dt { text-transform: none !important; } - @media (max-width: 1024px) { .ns-app-main { max-width: 100vw !important; margin-left: 0 !important; } } - /* Global Dialog/Modal Reachability (PC WebUI & PC App 1280x720 / 1366x768) */ .nebula-modal-card, .rbac-modal, @@ -4621,17 +3123,14 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod overflow-y: auto !important; box-sizing: border-box !important; } - /* Mobile-UI Parity with TV View (Breakpoints <= 768px & .is-mobile-view) */ @media (max-width: 768px) { .ns-command-rail, - .ns-top-bar, .nebula-page-title, .nebula-hero-play-icon, .nebula-empty-live-banner, .nebula-vod-play-overlay, .nebula-side-rail, - .vod-header-titles .kicker-type, .vod-description, .mobile-vod-description, #btnAdminMetaToggle, @@ -4649,7 +3148,6 @@ body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod display: none !important; } } - /* Compact Side-Rail Streamer Rows (Overrides legacy style.css 4-column grid) */ body.page-index .nebula-side-rail .ns-compact-streamer-list { display: flex !important; @@ -4666,7 +3164,7 @@ body.page-index .nebula-side-rail .streamer-row { padding: 0 10px !important; gap: 8px !important; border: 1px solid rgba(38, 52, 79, 0.55) !important; - border-radius: 8px !important; + border-radius: var(--nebula-radius-sm) !important; background: rgba(11, 18, 32, 0.55) !important; width: 100% !important; max-width: 100% !important; @@ -4679,7 +3177,7 @@ body.page-index .nebula-side-rail .streamer-row:hover { } body.page-index .nebula-side-rail .ns-compact-streamer-link { color: #F3F6FF !important; - font-size: 12px !important; + font-size: var(--sv-text-xs) !important; font-weight: 600 !important; text-decoration: none !important; overflow: hidden !important; @@ -4701,9 +3199,9 @@ body.page-index .nebula-side-rail .streamer-menu summary { display: inline-flex !important; align-items: center !important; justify-content: center !important; - border-radius: 6px !important; - color: #A2AEC8 !important; - font-size: 14px !important; + border-radius: var(--nebula-radius-xs) !important; + color: var(--nebula-text-secondary) !important; + font-size: var(--sv-text-md) !important; cursor: pointer !important; user-select: none !important; list-style: none !important; @@ -4728,12 +3226,11 @@ body.page-index .nebula-side-rail details.streamer-menu[open] > .streamer-menu-p min-width: 140px !important; max-width: 180px !important; background: #0E1626 !important; - border: 1px solid #26344F !important; - border-radius: 8px !important; + border: 1px solid var(--nebula-border) !important; + border-radius: var(--nebula-radius-sm) !important; padding: 5px !important; box-shadow: 0 10px 24px rgba(0, 0, 0, 0.75) !important; } - body.page-index .nebula-side-rail .nebula-side-widget { overflow: visible !important; position: relative !important; @@ -4747,7 +3244,6 @@ body.page-index .nebula-side-rail .streamer-row { body.page-index .nebula-side-rail .streamer-row:has(.streamer-menu[open]) { z-index: 1500 !important; } - /* ========================================================= NEBULA PAGINATION (SEITEN-NAVIGATION) - ALL VIEWPORTS ========================================================= */ @@ -4762,7 +3258,7 @@ body.page-index .nebula-side-rail .streamer-row:has(.streamer-menu[open]) { margin: 20px 0 !important; background: rgba(17, 26, 43, 0.85) !important; border: 1px solid rgba(38, 52, 79, 0.85) !important; - border-radius: 12px !important; + border-radius: var(--nebula-radius-md) !important; box-sizing: border-box !important; width: 100% !important; max-width: 100% !important; @@ -4772,8 +3268,8 @@ body.page-index .nebula-side-rail .streamer-row:has(.streamer-menu[open]) { margin: 0 0 18px 0 !important; } .ns-pagination-info { - font-size: 13px !important; - color: #A2AEC8 !important; + font-size: var(--sv-text-sm) !important; + color: var(--nebula-text-secondary) !important; white-space: nowrap !important; } .ns-pagination-info strong { @@ -4800,11 +3296,11 @@ body.page-mobile-streamer .ns-pagination .pagination-page { min-width: 36px !important; height: 34px !important; padding: 0 11px !important; - border-radius: 8px !important; + border-radius: var(--nebula-radius-sm) !important; background: rgba(11, 18, 32, 0.85) !important; - border: 1px solid #26344F !important; + border: 1px solid var(--nebula-border) !important; color: #D2DCF0 !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; font-weight: 600 !important; text-decoration: none !important; transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease !important; @@ -4816,23 +3312,23 @@ body.page-streamer .ns-pagination .pagination-page:hover, body.page-streamer .ns-pagination .pagination-nav:hover, body.page-mobile-streamer .ns-pagination .pagination-page:hover { background: rgba(77, 99, 255, 0.22) !important; - border-color: #4D63FF !important; + border-color: var(--nebula-accent-primary) !important; color: #FFFFFF !important; } .ns-page-btn.is-active, .ns-page-btn.is-current, body.page-streamer .ns-pagination .pagination-page.is-current, body.page-mobile-streamer .ns-pagination .pagination-page.is-current { - background: linear-gradient(135deg, #4D63FF 0%, #7C4DFF 100%) !important; - border-color: #69C9FF !important; + background: linear-gradient(135deg, var(--nebula-accent-primary) 0%, #7C4DFF 100%) !important; + border-color: var(--nebula-accent-cyan) !important; color: #FFFFFF !important; box-shadow: 0 2px 10px rgba(77, 99, 255, 0.4) !important; cursor: default !important; } .ns-page-ellipsis { - color: #75839D !important; + color: var(--nebula-text-muted) !important; padding: 0 4px !important; - font-size: 13px !important; + font-size: var(--sv-text-sm) !important; } .ns-page-jump { display: inline-flex !important; @@ -4855,44 +3351,37 @@ body.page-mobile-streamer .ns-pagination .pagination-page.is-current { justify-content: center !important; } } - /* Dashboard Realtime VOD Sync Glow */ @keyframes vodCardPulse { 0% { transform: scale(0.97); box-shadow: 0 0 0 rgba(77, 99, 255, 0.6); } 50% { transform: scale(1.02); box-shadow: 0 0 24px rgba(77, 99, 255, 0.45); } 100% { transform: scale(1); box-shadow: none; } } - .ns-vod-fresh-enter { animation: vodCardPulse 1.2s ease-out; border-color: rgba(77, 99, 255, 0.7) !important; } - - /* Language switcher (login page, sidebar footer) */ .ns-lang-switch { display: flex; justify-content: center; margin: 0; } - .ns-lang-switch select { min-height: 44px; max-width: 100%; padding: 0 32px 0 12px; - border: 1px solid var(--nebula-border, #26344F); - border-radius: 8px; + border: 1px solid var(--nebula-border); + border-radius: var(--nebula-radius-sm); background: rgba(11, 18, 32, 0.8); - color: var(--nebula-text-secondary, #A2AEC8); - font-size: 13px; + color: var(--nebula-text-secondary); + font-size: var(--sv-text-sm); cursor: pointer; } - .ns-lang-switch select:focus-visible { - outline: 2px solid #4D63FF; + outline: 2px solid var(--nebula-accent-primary); outline-offset: 2px; } - body.page-login .nebula-login-lang { margin-top: 16px; -} \ No newline at end of file +} diff --git a/WEBUI/static/css/ui-polish.css b/WEBUI/static/css/ui-polish.css deleted file mode 100644 index 5c84ad1..0000000 --- a/WEBUI/static/css/ui-polish.css +++ /dev/null @@ -1,212 +0,0 @@ -/* StreamVault — safe visual polish (tokens + grid + action tools). - * Loaded last via style.css append. No JS/ID/route changes. - */ - -:root { - --tube-bg: #050505; - --tube-surface: #121212; - --tube-surface-2: #1a1a1a; - --tube-surface-3: #242424; - --tube-line: #2e2e2e; - --tube-line-soft: #222222; - --tube-text: #f5f5f5; - --tube-text-2: #cfcfcf; - --tube-muted: #8f8f8f; - --tube-accent: #f2e58d; - --tube-accent-hover: #fff3a9; - --tube-live: #ff5c66; - --tube-success: #6ed9a2; - --tube-radius: 10px; - --tube-focus: 0 0 0 3px rgba(242, 229, 141, 0.28); - --radius: var(--tube-radius); - --text-muted: var(--tube-muted); - --muted: var(--tube-muted); - --border: var(--tube-line); - --primary: var(--tube-accent); - --accent: var(--tube-accent); -} - -/* --- Video grid / cards (streamer + search + index-like grids) --- */ -body.page-streamer .video-grid, -body.page-search .video-grid, -body.page-index .video-grid { - grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)) !important; - gap: 16px 12px !important; -} - -body.page-streamer .video-card, -body.page-search .video-card { - border-radius: var(--tube-radius) !important; - transition: background-color 0.15s ease, transform 0.15s ease !important; -} - -body.page-streamer .video-card:hover, -body.page-search .video-card:hover { - background: var(--tube-surface) !important; -} - -body.page-streamer .thumb-wrap, -body.page-search .thumb-wrap, -.video-card .thumb-wrap, -.vod-card .thumb-wrap { - aspect-ratio: 16 / 9 !important; - border-radius: 10px !important; - border: 1px solid var(--tube-line-soft) !important; - background: #0a0a0a !important; - overflow: hidden !important; -} - -body.page-streamer .thumb-img, -body.page-search .thumb-img, -.video-card .thumb-img { - transition: transform 0.2s ease !important; -} - -@media (hover: hover) and (pointer: fine) { - body.page-streamer .video-card:hover .thumb-img, - body.page-search .video-card:hover .thumb-img { - transform: scale(1.02) !important; - } -} - -body.page-streamer .video-title, -body.page-search .video-title { - color: var(--tube-text) !important; - font-size: 13px !important; - font-weight: 650 !important; - line-height: 1.35 !important; -} - -body.page-streamer .card-body, -body.page-search .card-body { - padding: 10px 2px 2px !important; -} - -body.page-streamer .video-meta, -body.page-search .video-meta, -body.page-streamer .meta, -body.page-search .meta { - color: var(--tube-muted) !important; - font-size: 12px !important; -} - -/* --- Action tool strip (Clip / Zuschneiden / …) --- */ -body:is(.page-vod, .page-live, .page-twitch-watch) .vod-file-actions { - display: flex !important; - flex-wrap: wrap !important; - align-items: center !important; - gap: 6px !important; -} - -body:is(.page-vod, .page-live, .page-twitch-watch) .vod-inline-tool { - min-height: 34px !important; - padding: 0 12px !important; - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - gap: 6px !important; - border: 1px solid var(--tube-line) !important; - border-radius: 8px !important; - color: var(--tube-text-2) !important; - background: var(--tube-surface-2) !important; - font-size: 12px !important; - font-weight: 700 !important; - letter-spacing: 0.01em !important; - line-height: 1 !important; - text-decoration: none !important; - cursor: pointer !important; - box-shadow: none !important; - transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease !important; -} - -body:is(.page-vod, .page-live, .page-twitch-watch) .vod-inline-tool::after { - display: none !important; -} - -body:is(.page-vod, .page-live, .page-twitch-watch) .vod-inline-tool:hover { - color: var(--tube-text) !important; - border-color: #3f3f3f !important; - background: var(--tube-surface-3) !important; - transform: none !important; -} - -body:is(.page-vod, .page-live, .page-twitch-watch) .vod-inline-tool:focus-visible { - outline: none !important; - box-shadow: var(--tube-focus) !important; -} - -/* Primary clip actions stand out slightly */ -body:is(.page-vod, .page-live, .page-twitch-watch) #btnInstantClip, -body:is(.page-vod, .page-live, .page-twitch-watch) #btnOpenEditor { - color: #161616 !important; - border-color: rgba(242, 229, 141, 0.55) !important; - background: var(--tube-accent) !important; -} - -body:is(.page-vod, .page-live, .page-twitch-watch) #btnInstantClip:hover, -body:is(.page-vod, .page-live, .page-twitch-watch) #btnOpenEditor:hover { - color: #111 !important; - border-color: rgba(255, 243, 169, 0.75) !important; - background: var(--tube-accent-hover) !important; -} - -body:is(.page-vod, .page-live, .page-twitch-watch) .vod-inline-tool-warning { - color: #ffe082 !important; - border-color: rgba(255, 224, 130, 0.28) !important; - background: rgba(255, 224, 130, 0.08) !important; -} - -/* --- Mobile streamer cards: align radius/contrast --- */ -body.page-mobile-streamer .video-card { - border-radius: 10px !important; - border-color: var(--tube-line) !important; - background: var(--tube-surface) !important; -} - -body.page-mobile-streamer .thumb-area { - aspect-ratio: 16 / 9 !important; -} - -@media (prefers-reduced-motion: reduce) { - body.page-streamer .video-card, - body.page-search .video-card, - body.page-streamer .thumb-img, - body.page-search .thumb-img, - body:is(.page-vod, .page-live, .page-twitch-watch) .vod-inline-tool { - transition: none !important; - } - - body.page-streamer .video-card:hover .thumb-img, - body.page-search .video-card:hover .thumb-img { - transform: none !important; - } -} - -/* --- Mobile Player Info Box (similar to desktop .vod-details) --- - * Canonical rules live in style.css (page-twitch-watch-mobile). Kept here as mirror. */ -body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details { - flex: 0 0 auto; - padding: 10px 12px 12px; - background: var(--tube-surface, #0e0e10); - border-bottom: 1px solid var(--tube-line, #27272a); -} - -body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-display-title { - margin: 0; - font-size: 16px; - font-weight: 700; - line-height: 1.25; - color: var(--tube-text, #f5f5f5); -} - -body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-facts div { - display: flex; - flex-direction: row; - align-items: baseline; - gap: 6px; -} - -body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-facts dt, -body:is(.page-twitch-watch-mobile, .page-mobile-player) .mobile-vod-details .vod-facts dd { - margin: 0; -} diff --git a/WEBUI/static/dashboard_live.js b/WEBUI/static/dashboard_live.js index 868ce63..1227cc9 100644 --- a/WEBUI/static/dashboard_live.js +++ b/WEBUI/static/dashboard_live.js @@ -45,7 +45,7 @@ playOverlay + '' + '
' + - '

' + escapeHtml(vod.title || vod.name) + '

' + + '

' + escapeHtml(vod.title || vod.name) + '

' + '