diff --git a/custom/otssignange/css/override-dark.css b/custom/otssignange/css/override-dark.css index b1fd1db..013518a 100644 --- a/custom/otssignange/css/override-dark.css +++ b/custom/otssignange/css/override-dark.css @@ -398,6 +398,40 @@ hr { } /* Navigation Icons and Text */ + +/* ========================================================================== + FORCE DARK BACKGROUND FALLBACKS + Ensure no white areas appear when scrolling or when elements overflow. + This uses high-specificity selectors and !important to override stray + light-background rules from other stylesheets. + ========================================================================== */ + +html, body, #page-wrapper, .ots-main, .ots-content, .page-content, .container { + background-color: var(--color-background) !important; + background: none !important; + color: var(--color-text-primary) !important; +} + +/* Remove or neutralise any pseudo-elements that may paint a light background */ +html::before, html::after, body::before, body::after, #page-wrapper::before, #page-wrapper::after { + background: transparent !important; + content: none !important; +} + +/* Ensure fixed/backdrop layers are dark where appropriate */ +.modal-backdrop, +.modal, +.modal-open, +.ots-shell, +.ots-footer { + background-color: var(--color-background) !important; +} + +/* Defensive: override any explicit white panel backgrounds that leak outside their container */ +.card, .panel, .panel-body, .dashboard-card, .ots-sidebar li.sidebar-list.active > a { + background-color: var(--color-surface) !important; + color: var(--color-text-primary) !important; +} .ots-nav-icon { width: 16px; height: 16px; @@ -785,6 +819,29 @@ textarea:focus { border-top: 1px solid var(--color-border) !important; } +/* Ensure modal footer buttons (cancel/secondary) are readable on dark surfaces */ +.modal-footer .btn, +.modal-footer button { + background: var(--ots-surface-3); + color: var(--ots-text) !important; + border: 1px solid var(--ots-border) !important; + box-shadow: none !important; +} + +.modal-footer .btn:hover, +.modal-footer button:hover { + background: var(--ots-surface-2); + color: var(--ots-primary) !important; + border-color: var(--ots-primary) !important; +} + +.modal-footer .btn.btn-primary, +.modal-footer button.btn-primary { + background: var(--ots-primary) !important; + color: #0b1020 !important; + border-color: var(--ots-primary-2) !important; +} + /* ============================================================================= HELP PANE / MISC ============================================================================= */ @@ -824,3 +881,333 @@ textarea:focus { font-size: 13px; color: var(--ots-text-muted); } + +/* ============================================================================= + LOGIN / SIGN-IN PAGE + Styles to match the requested sign-in card: centered panel, dark glass + surface, orange accent, soft shadow and modern inputs. + ============================================================================= */ + +:root { + --login-accent: #ff8a00; + --login-panel-bg: linear-gradient(180deg, rgba(8,12,20,0.9), rgba(10,16,28,0.85)); +} + +body.login, body.login-page, .xibo-login, #login, .login-wrapper { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 40px 20px; + background-image: radial-gradient(rgba(255,255,255,0.02) 1px, transparent 1px), + linear-gradient(135deg, rgba(6,16,30,0.6), rgba(8,12,24,0.65)); + background-size: 48px 48px, cover; +} + +.login-card, +.login-panel, +.auth-card, +.xibo-login-box, +#login-box { + width: 100%; + max-width: 560px; + border-radius: 12px; + padding: 32px 36px; + background: var(--login-panel-bg); + border: 1px solid rgba(255,255,255,0.04); + box-shadow: var(--ots-shadow-lg); + color: var(--ots-text); +} + +.login-card .login-logo, +.login-panel .login-logo { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 18px; +} + +.login-card .login-logo .logo-icon, +.login-panel .login-logo .logo-icon { + width: 92px; + height: 92px; + border-radius: 10px; + background: var(--login-accent); + display: inline-flex; + align-items: center; + justify-content: center; + box-shadow: 0 6px 18px rgba(0,0,0,0.45); +} + +/* Brand text next to logo on login */ +.login-brand { + display: flex; + align-items: center; + justify-content: center; + gap: 18px; + margin-bottom: 18px; +} + +.login-brand .login-logo { + width: 92px; + height: 92px; + display: inline-block; +} + +.login-brand-text { + color: var(--ots-text); + font-size: 1.5rem; + font-weight: 700; + letter-spacing: 0.01em; +} + +.login-card h1, +.login-panel h1 { + text-align: center; + margin: 8px 0 6px 0; + font-size: 28px; + font-weight: 700; +} + +.login-card .lead, +.login-panel .lead { + text-align: center; + color: var(--ots-text-muted); + margin-bottom: 18px; +} + +.login-card .form-group, +.login-panel .form-group { + margin-bottom: 14px; +} + +.login-card input[type="text"], +.login-card input[type="email"], +.login-card input[type="password"], +.login-card .form-control, +.login-panel input[type="text"], +.login-panel input[type="email"], +.login-panel input[type="password"] { + width: 100%; + background: linear-gradient(180deg, rgba(255,255,255,0.016), rgba(255,255,255,0.01)); + border: 1px solid rgba(255,255,255,0.06); + color: var(--ots-text); + padding: 14px 16px; + border-radius: 12px; + font-size: 1rem; + line-height: 1.25; + transition: border-color 180ms ease, box-shadow 180ms ease, background 180ms ease; +} + +.login-card input:focus, +.login-panel input:focus, +.login-card .form-control:focus { + outline: none; + border-color: rgba(255,138,0,0.95); + background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)); + box-shadow: 0 8px 22px rgba(0,0,0,0.32), 0 0 0 6px rgba(255,138,0,0.04); +} + +.login-card input::placeholder, +.login-panel input::placeholder { + color: rgba(255,255,255,0.58); +} + +.login-card input + input, +.login-card input + .form-control, +.login-panel input + input { + margin-top: 10px; +} + +.login-card .form-control[disabled], +.login-card input[disabled] { + opacity: 0.7; +} + +.login-card .btn-signin, +.login-panel .btn-signin, +.login-card .btn-primary.login, +.login-panel .btn-primary.login { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + width: 100%; + padding: 10px 14px; + background: rgba(255,255,255,0.03); + color: var(--ots-text); + border-radius: 10px; + border: 1px solid rgba(255,255,255,0.12); + font-weight: 600; + box-shadow: none; + transition: background 160ms ease, border-color 160ms ease, color 160ms ease, box-shadow 160ms ease; +} + +.login-card .btn-signin .icon, +.login-panel .btn-signin .icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; +} + +.login-card .btn-signin:hover, +.login-panel .btn-signin:hover { + background: rgba(255,255,255,0.06); + border-color: rgba(255,255,255,0.18); +} + +.login-card .btn-signin:focus, +.login-panel .btn-signin:focus { + outline: none; + box-shadow: 0 6px 18px rgba(0,0,0,0.28), 0 0 0 6px rgba(255,138,0,0.04); + border-color: rgba(255,138,0,0.28); +} + +.login-card .forgot-link, +.login-panel .forgot-link { + display: block; + text-align: right; + margin-top: 8px; + color: var(--ots-text-muted); +} + +/* Small screens: compress card padding */ +@media (max-width: 520px) { + .login-card, .login-panel { padding: 20px; border-radius: 10px; } + .login-card .login-logo .logo-icon { width: 72px; height: 72px; } +} + +/* Animated background for login page: subtle moving gradient behind the card */ +body.login-page::before { + content: ""; + position: fixed; + inset: 0; + z-index: 0; + background: linear-gradient(120deg, rgba(14,28,45,0.6), rgba(6,16,30,0.55)), + radial-gradient( circle at 10% 20%, rgba(79,140,255,0.06), transparent 10% ), + radial-gradient( circle at 85% 80%, rgba(255,138,0,0.04), transparent 12% ); + background-blend-mode: overlay, normal, normal; + background-size: 200% 200%, 100% 100%, 100% 100%; + filter: blur(22px); + pointer-events: none; + opacity: 0.95; + /* no animation here - blobs will provide the motion */ +} + +@keyframes ots-login-bg-shift { + 0% { background-position: 0% 50%, 0% 0%, 0% 0%; } + 50% { background-position: 100% 50%, 0% 0%, 0% 0%; } + 100% { background-position: 0% 50%, 0% 0%, 0% 0%; } +} + +/* Bring the login card above the animated background */ +.login-card, +.login-panel, +.auth-card, +.xibo-login-box, +#login-box { + position: relative; + z-index: 2; +} + +/* Blurred animated color blobs behind the login card */ +.ots-login-blob { + position: fixed; + pointer-events: none; + filter: blur(60px) saturate(120%); + opacity: 0.9; + mix-blend-mode: screen; + z-index: 0; + will-change: transform, opacity; +} + +.ots-login-blob--1 { + width: 520px; + height: 520px; + left: -8%; + top: -6%; + background: radial-gradient(circle at 30% 30%, rgba(79,140,255,0.65), rgba(79,140,255,0.18) 35%, transparent 50%); + animation: ots-blob-move-1 20s ease-in-out infinite alternate !important; +} + +.ots-login-blob--2 { + width: 420px; + height: 420px; + right: 6%; + bottom: 18%; + background: radial-gradient(circle at 60% 40%, rgba(255,138,0,0.45), rgba(255,138,0,0.14) 36%, transparent 55%); + animation: ots-blob-move-2 26s ease-in-out infinite alternate !important; +} + +.ots-login-blob--3 { + width: 360px; + height: 360px; + left: 18%; + bottom: -4%; + background: radial-gradient(circle at 40% 60%, rgba(94,200,255,0.28), rgba(94,200,255,0.08) 40%, transparent 60%); + animation: ots-blob-move-3 22s ease-in-out infinite alternate !important; +} + +/* Disable other animations/transitions on the login page so only blobs animate */ +body.login-page *, +body.login-page *::before, +body.login-page *::after { + animation: none !important; + transition: none !important; +} + +/* Re-enable blob animations specifically (higher specificity) */ +.ots-login-blob, +.ots-login-blob--1, +.ots-login-blob--2, +.ots-login-blob--3 { + animation-play-state: running !important; +} + +@keyframes ots-blob-move-1 { + 0% { transform: translate3d(0,0,0) scale(1); opacity: 0.85; } + 100% { transform: translate3d(18px,26px,0) scale(1.06); opacity: 0.7; } +} + +@keyframes ots-blob-move-2 { + 0% { transform: translate3d(0,0,0) scale(1); opacity: 0.65; } + 100% { transform: translate3d(-28px,-18px,0) scale(1.08); opacity: 0.55; } +} + +@keyframes ots-blob-move-3 { + 0% { transform: translate3d(0,0,0) scale(1); opacity: 0.6; } + 100% { transform: translate3d(22px,-20px,0) scale(1.05); opacity: 0.5; } +} + + +/* EXTRA DEFENSIVE: ensure no white background shows through on long pages */ +html, body, #page-wrapper, .ots-shell, .ots-main, #content-wrapper, .content-wrapper, .ots-content, .page-content, .container, .container-fluid, .dashboard-page, .dashboard, .dashboard-card, .page { + background-color: var(--color-background) !important; + background-image: none !important; + background-repeat: no-repeat !important; + color: var(--color-text-primary) !important; + min-height: 100vh !important; +} + +/* Neutralise any inline styles or late-loaded styles that set white backgrounds */ +*[style] { + background-color: inherit !important; +} + +/* Provide a small utility to detect offending elements visually (useful while debugging) */ +body.debug-white-areas * { + outline: 1px solid rgba(255,0,0,0.04) !important; +} + +/* Strong fallback for modals/backdrops */ +.modal-backdrop, .modal, .modal-open, .ots-footer, .page-footer { + background-color: var(--color-background) !important; +} + +/* Ensure the root html background is also forced dark at the highest level */ +html[style], body[style] { + background-color: var(--color-background) !important; +} + diff --git a/custom/otssignange/css/override.css b/custom/otssignange/css/override.css index 146aa54..8d8a504 100644 --- a/custom/otssignange/css/override.css +++ b/custom/otssignange/css/override.css @@ -64,6 +64,65 @@ body { max-width: 100vw !important; } +/* Minimal mapping so `.dashboard-card` inherits the visual treatment used by widgets/panels. + This allows collapsing one level of DOM without visual regressions. */ +/* Consolidated dashboard-card styling (now in CONSOLIDATED CARD/PANEL/WIDGET section) */ + + +/* Floating menus that are moved to body to escape overflowed containers */ +.ots-floating-menu { + border-radius: 8px; + box-shadow: 0 8px 24px rgba(2,6,23,0.6); + background-color: var(--color-surface); + border: 1px solid var(--color-border); + overflow: visible !important; + position: fixed !important; + transform: none !important; +} + +/* Elevated z-index for menus so they render above other panels */ +.ots-floating-menu, .dropdown-menu { + z-index: 99999 !important; +} + +/* Force ALL dropdown/context menu classes to render on top of everything. + This is maximally aggressive to defeat any stacking context or overflow clipping. */ +.dropdown-menu, +.ots-notif-menu, +.ots-user-menu, +.context-menu, +.row-menu, +.rowMenu, +.menu-popover, +.dataTables_buttons .dropdown-menu, +.ots-floating-menu { + position: fixed !important; + z-index: 2147483647 !important; + transform: none !important; + will-change: auto !important; + pointer-events: auto !important; + visibility: visible !important; + display: block !important; + opacity: 1 !important; +} + +/* Ensure dropdown list items and children aren't clipped */ +.dropdown-menu li, +.dropdown-menu > li > a, +.dropdown-menu > li > span, +.dropdown-menu ul, +.dropdown-menu div { + overflow: visible !important; + position: relative !important; + z-index: 2147483647 !important; +} + +/* Remove any transform or overflow from menu ancestors that could create stacking context */ +.dropdown-menu *, +.ots-floating-menu * { + transform: none !important; +} + /* Light/dark mode toggle */ #ots-theme-toggle { display: flex !important; @@ -2602,53 +2661,66 @@ body.ots-sidebar-open .ots-topbar { flex-direction: column; } -/* Force Xibo panels/cards to dark theme (use higher specificity to override core styles) */ -body .panel, -body .panel.panel-default, +/* ============================================================================ + CONSOLIDATED CARD/PANEL/WIDGET STYLING (Simplified, single source of truth) + ============================================================================ */ + +.card, +.panel, +.panel.panel-default, .panel.panel-white, -.panel.card, .panel.box, -.widget { +.widget, +.dashboard-card { background-color: var(--color-surface) !important; color: var(--color-text-primary) !important; border: 1px solid var(--color-border) !important; + border-radius: 6px; + display: flex; + flex-direction: column; + overflow: hidden; } -body .panel .panel-body, -body .panel .panel-footer, -body .panel .panel-heading, -.panel .panel-header { - background-color: transparent !important; - color: var(--color-text-primary) !important; - border-color: var(--color-border) !important; -} - -body .panel .panel-heading, -.panel .panel-header { +/* Unified header/heading styling */ +.panel-heading, +.panel-header, +.widget-title, +.card-header, +.dashboard-card-header { background-color: var(--color-surface-elevated) !important; border-bottom: 1px solid var(--color-border) !important; + color: var(--color-text-primary) !important; + padding: 12px 16px; + font-weight: 600; } -/* Tables inside panels should inherit dark background and readable text */ +/* Unified body styling */ +.panel-body, +.panel-footer, +.widget-body, +.card-body, +.dashboard-card-body { + flex: 1; + padding: 12px 16px; + color: var(--color-text-primary) !important; + background-color: transparent !important; + min-height: 0; +} + +/* Tables inside cards inherit styling */ .panel table, .panel table thead, .panel table tbody, .panel table tr, .panel table td, .panel table th, -.panel .dataTables_wrapper { +.panel .dataTables_wrapper, +.card .dataTables_wrapper, +.widget .dataTables_wrapper { background-color: transparent !important; color: var(--color-text-primary) !important; } -/* Card-specific fallbacks */ -.card, -.card .card-body { - background-color: var(--color-surface) !important; - color: var(--color-text-primary) !important; - border: 1px solid var(--color-border) !important; -} - .panel-full { grid-column: 1 / -1; } @@ -3116,8 +3188,57 @@ body .panel .panel-heading, box-shadow: 0 6px 16px rgba(8, 15, 30, 0.25); } +/* ============================================================================ + SIMPLIFIED TABLE & DATATABLES STYLING (Consolidated) + ============================================================================ */ + +.table, +.table > thead > tr > th, +.table > tbody > tr > td { + color: var(--color-text-primary) !important; + border-color: var(--color-border) !important; + background-color: transparent !important; +} + +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: rgba(79, 140, 255, 0.04) !important; +} + +.table-hover > tbody > tr:hover { + background-color: rgba(79, 140, 255, 0.08) !important; + color: var(--color-text-primary) !important; +} + +/* Selected rows */ +.table tbody tr.selected, +.table tbody tr.dt-row-selected { + background-color: rgba(16, 185, 129, 0.25) !important; + color: var(--color-text-primary) !important; +} + +/* DataTables controls */ +.dataTables_wrapper { + color: var(--color-text-primary) !important; +} + +.dataTables_wrapper .dataTables_length, +.dataTables_wrapper .dataTables_filter, +.dataTables_wrapper .dataTables_info, +.dataTables_wrapper .dataTables_paginate { + color: var(--color-text-secondary) !important; +} + +.dataTables_wrapper .dataTables_filter input, +.dataTables_wrapper .dataTables_length select { + background-color: var(--color-surface) !important; + color: var(--color-text-primary) !important; + border: 1px solid var(--color-border) !important; + padding: 4px 8px; + border-radius: 4px; +} + +/* OTS table card (inherits from consolidated .card rule above) */ .ots-table-card { - padding: 12px 16px 16px; flex: 1; min-width: 0; overflow: hidden; @@ -3259,7 +3380,6 @@ body.ots-light-mode .ots-table-toolbar .btn-primary { color: #e2e8f0 !important; border: 1px solid rgba(148, 163, 184, 0.25) !important; } - /* Extra specificity for Xibo Displays DataTable */ .ots-displays-page #datatable-container .XiboData .table, .ots-displays-page #datatable-container .XiboData table.dataTable { diff --git a/custom/otssignange/views/dashboard-status-page.twig b/custom/otssignange/views/dashboard-status-page.twig index bb28218..132050f 100644 --- a/custom/otssignange/views/dashboard-status-page.twig +++ b/custom/otssignange/views/dashboard-status-page.twig @@ -524,6 +524,22 @@ } } + // Set Chart.js default font/color from CSS variables so charts match theme + (function(){ + try { + var root = getComputedStyle(document.documentElement); + var cssColor = root.getPropertyValue('--ots-text') || root.getPropertyValue('--color-text-primary') || root.getPropertyValue('--color-text'); + cssColor = (cssColor || '').trim() || '#ffffff'; + if (window.Chart && Chart.defaults) { + // Chart.js v3+ uses Chart.defaults.color + if (typeof Chart.defaults.color !== 'undefined') Chart.defaults.color = cssColor; + // Backwards compatibility for older Chart.js + if (Chart.defaults.global) Chart.defaults.global.defaultFontColor = cssColor; + if (Chart.defaults.font) Chart.defaults.font.color = cssColor; + } + } catch (e) { /* ignore */ } + })(); + var bandwidthChart = new Chart($("#bandwidthChart"), { type: "line", data: {{ bandwidthWidget|raw }}, diff --git a/custom/otssignange/views/daypart-page.twig b/custom/otssignange/views/daypart-page.twig index 18e2212..111614e 100644 --- a/custom/otssignange/views/daypart-page.twig +++ b/custom/otssignange/views/daypart-page.twig @@ -34,8 +34,8 @@
{% trans "Manage time-based scheduling rules." %}
-