Files
OTSSignsTheme/ots-signs/css/override.css
2026-02-12 10:24:55 -05:00

7888 lines
217 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ============================================================================
XIBO CMS MODERN THEME - OTS Signs
Dark Mode Override - Component Styling
============================================================================ */
/* Force dark mode */
:root {
--color-primary: #3b82f6;
--color-primary-dark: #1d4ed8;
--color-primary-light: #60a5fa;
--color-primary-lighter: #dbeafe;
--color-secondary: #7c3aed;
--color-success: #10b981;
--color-warning: #f59e0b;
--color-danger: #ef4444;
--color-info: #0ea5e9;
--color-background: #0f172a;
--color-surface: #1e293b;
--color-surface-elevated: #334155;
--color-border: #475569;
--color-border-light: #1e293b;
--color-text-primary: #ffffff;
--color-text-secondary: #f1f5f9;
--color-text-tertiary: #e2e8f0;
--color-text-inverse: #ffffff;
--color-on-primary: #ffffff;
--ots-sidebar-bg: #08132a;
--ots-sidebar-header-bg: #08132a;
--ots-sidebar-border: rgba(255, 255, 255, 0.08);
--ots-sidebar-link: #f9fbff;
--ots-sidebar-link-hover-bg: rgba(255, 255, 255, 0.08);
--ots-sidebar-link-hover-text: #ffffff;
--ots-sidebar-active-bg: rgba(255, 255, 255, 0.06);
--ots-sidebar-active-text: #ffffff;
--ots-sidebar-active-shadow: 0 8px 18px rgba(15, 23, 42, 0.25);
--ots-sidebar-muted-text: #8ea4c7;
--ots-sidebar-group-bg: rgba(255, 255, 255, 0.03);
--ots-sidebar-group-hover-bg: rgba(255, 255, 255, 0.1);
--ots-sidebar-submenu-bg: rgba(15, 23, 42, 0.6);
--ots-sidebar-submenu-border: rgba(255, 255, 255, 0.9);
--ots-sidebar-submenu-hover-bg: rgba(255, 255, 255, 0.1);
--ots-sidebar-button-bg: rgba(255, 255, 255, 0.08);
--ots-sidebar-button-bg-hover: rgba(255, 255, 255, 0.16);
--ots-sidebar-button-text: #d7e2f8;
--ots-sidebar-collapsed-item-bg: rgba(255, 255, 255, 0.08);
--ots-sidebar-collapsed-item-hover-bg: rgba(255, 255, 255, 0.16);
--ots-sidebar-width: 256px;
--ots-sidebar-collapsed-width: 64px;
--ots-sidebar-header-height: 64px;
--ots-sidebar-item-radius: 10px;
--ots-sidebar-item-height: 44px;
--ots-sidebar-item-padding-x: 12px;
--ots-sidebar-content-gap: 12px;
/* Editor (playlist / layout timeline) */
--editor-modal-bg: #1a1a2e;
--editor-modal-content-bg: #1e293b;
--editor-modal-header-bg: #0f172a;
--editor-modal-header-text: #f1f5f9;
/* Modal pop-ups (Bootstrap / Bootbox) */
--modal-backdrop-bg: rgba(2, 6, 23, 0.55);
--modal-backdrop-blur: 6px;
--modal-bg: #141c2b;
--modal-border: #2c3a54;
--modal-radius: 16px;
--modal-shadow: 0 24px 64px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.04);
--modal-header-bg: #0f172a;
--modal-header-border: #2c3a54;
--modal-header-text: #f1f5f9;
--modal-body-bg: #141c2b;
--modal-body-text: #e2e8f0;
--modal-footer-bg: #0f172a;
--modal-footer-border: #2c3a54;
--modal-close-color: #64748b;
--modal-close-hover: #f1f5f9;
--modal-input-bg: #0b111a;
--modal-input-border: #2c3a54;
--modal-input-text: #e6eefb;
--modal-input-focus-border: #4f8cff;
--modal-input-focus-ring: rgba(79, 140, 255, 0.2);
--editor-body-bg: #1e293b;
--editor-border: #334155;
--editor-text: #e2e8f0;
--editor-text-secondary: #94a3b8;
--editor-toolbar-bg: #0f172a;
--editor-toolbar-text: #e2e8f0;
--editor-toolbar-pane-bg: #1e293b;
--editor-toolbar-pane-text: #e2e8f0;
--editor-footer-controls-bg: #0f172a;
--editor-footer-info-bg: var(--color-primary);
--editor-footer-text: #f1f5f9;
--editor-widget-bg: #334155;
--editor-widget-border: #475569;
--editor-widget-text: #e2e8f0;
--editor-widget-label-bg: #0f172a;
--editor-widget-label-text: #94a3b8;
--editor-widget-hover-bg: #3b4d6b;
--editor-widget-selected-bg: #166534;
--editor-widget-multi-bg: #c2410c;
--editor-widget-multi-hover-bg: #ea580c;
--editor-left-margin-bg: #0f172a;
--editor-timegrid-line: #475569;
--editor-timegrid-text: #64748b;
--editor-timegrid-overlay: rgba(30, 41, 59, 0.7);
--editor-timeline-bg: rgba(30, 41, 59, 0.65);
--editor-scrollbar-track: #1e293b;
--editor-scrollbar-thumb: #475569;
--editor-scrollbar-thumb-hover: #64748b;
--editor-properties-bg: #1e293b;
--editor-properties-border: #166534;
--editor-header-bg: #0f172a;
--editor-back-btn-bg: #0f172a;
--editor-back-btn-text: var(--color-primary-light);
color-scheme: dark;
}
html,
body {
background-color: var(--color-background);
color: var(--color-text-primary);
overflow-x: hidden !important;
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;
}
/* Ensure menus that are intentionally floated into `body` are visible
(this targets only menus moved by our JS: `.ots-floating-menu` or
`.dropdown-menu` marked with `data-ots-floating="1`). This avoids
forcing visibility for all dropdowns. */
.ots-floating-menu,
.dropdown-menu[data-ots-floating="1"] {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
}
/* Elevated z-index for menus so they render above other panels */
.ots-floating-menu, .dropdown-menu {
z-index: 99999 !important;
}
/* Limit aggressive floating/menu overrides to explicit floating menus only.
Avoid forcing `.dropdown-menu` to be `display:block`/`visibility:visible` so
native dropdown behaviour (open/close) is preserved. */
.ots-notif-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;
}
/* User menu positioning is handled by floatMenu() which adds .ots-floating-menu.
Only apply fixed positioning when the menu is actively floating. */
.ots-user-menu.ots-floating-menu {
position: fixed !important;
z-index: 2147483647 !important;
transform: none !important;
will-change: auto !important;
pointer-events: auto !important;
}
/* The rowMenu th is the empty header for the per-row action dropdown.
Keep it in flow so column count matches tbody, but make it minimal.
The matching td (last-child) holds the action button and must stay visible.
NOTE: No background set here — inherits from .ots-table-card .table thead th rules. */
th.rowMenu {
width: 40px !important;
min-width: 40px !important;
max-width: 40px !important;
padding: 4px !important;
text-align: center !important;
box-sizing: border-box !important;
border-left: none !important;
border-right: none !important;
border-top: none !important;
}
/* Style the action-button td to match the header width */
table:has(th.rowMenu) > tbody > tr > td:last-child {
width: 40px !important;
min-width: 40px !important;
max-width: 40px !important;
padding: 4px !important;
text-align: center !important;
box-sizing: border-box !important;
overflow: visible !important;
}
/* Ensure floating menu children aren't clipped (scoped to floated menus only) */
.ots-floating-menu li,
.ots-floating-menu > li > a,
.ots-floating-menu > li > span,
.ots-floating-menu ul,
.ots-floating-menu div {
overflow: visible !important;
}
/* Remove transforms inside floating menus that could create stacking context */
.ots-floating-menu * {
transform: none !important;
}
/* Light/dark mode toggle */
#ots-theme-toggle {
display: flex !important;
align-items: center;
gap: 8px;
cursor: pointer;
}
#ots-theme-toggle:hover {
background-color: rgba(59, 130, 246, 0.1) !important;
}
/* Light mode styles (applied when .ots-light-mode is on html or body) */
html.ots-light-mode,
body.ots-light-mode {
--color-primary: #2563eb;
--color-primary-dark: #1d4ed8;
--color-primary-light: #60a5fa;
--color-primary-lighter: #eff6ff;
--color-secondary: #7c3aed;
--color-success: #059669;
--color-warning: #d97706;
--color-danger: #dc2626;
--color-info: #0284c7;
--color-background: #f8fafc;
--color-surface: #ffffff;
--color-surface-elevated: #f1f5f9;
--color-border: #e2e8f0;
--color-border-light: #f1f5f9;
--color-text-primary: #0f172a;
--color-text-secondary: #334155;
--color-text-tertiary: #475569;
--color-text-inverse: #0f172a;
--color-on-primary: #ffffff;
--ots-sidebar-bg: #f1f5f9;
--ots-sidebar-header-bg: #f1f5f9;
--ots-sidebar-border: #e2e8f0;
--ots-sidebar-link: #334155;
--ots-sidebar-link-hover-bg: rgba(59, 130, 246, 0.08);
--ots-sidebar-link-hover-text: #0f172a;
--ots-sidebar-active-bg: #ffffff;
--ots-sidebar-active-text: #0f172a;
--ots-sidebar-active-shadow: 0 8px 18px rgba(15, 23, 42, 0.12);
--ots-sidebar-muted-text: #64748b;
--ots-sidebar-group-bg: rgba(0, 0, 0, 0.03);
--ots-sidebar-group-hover-bg: rgba(0, 0, 0, 0.06);
--ots-sidebar-submenu-bg: rgba(0, 0, 0, 0.04);
--ots-sidebar-submenu-border: #cbd5e1;
--ots-sidebar-submenu-hover-bg: rgba(0, 0, 0, 0.08);
--ots-sidebar-button-bg: rgba(0, 0, 0, 0.04);
--ots-sidebar-button-bg-hover: rgba(0, 0, 0, 0.08);
--ots-sidebar-button-text: #334155;
--ots-sidebar-collapsed-item-bg: rgba(0, 0, 0, 0.04);
--ots-sidebar-collapsed-item-hover-bg: rgba(0, 0, 0, 0.08);
--ots-sidebar-width: 256px;
--ots-sidebar-collapsed-width: 64px;
--ots-sidebar-header-height: 64px;
--ots-sidebar-item-radius: 10px;
--ots-sidebar-item-height: 44px;
--ots-sidebar-item-padding-x: 12px;
/* Editor (playlist / layout timeline) */
--editor-modal-bg: #e8e8e8;
--editor-modal-content-bg: #ffffff;
--editor-modal-header-bg: #f1f5f9;
--editor-modal-header-text: #0f172a;
/* Modal pop-ups (Bootstrap / Bootbox) — light mode */
--modal-backdrop-bg: rgba(15, 23, 42, 0.25);
--modal-backdrop-blur: 6px;
--modal-bg: #ffffff;
--modal-border: #e2e8f0;
--modal-radius: 16px;
--modal-shadow: 0 24px 64px rgba(15, 23, 42, 0.14), 0 0 0 1px rgba(0, 0, 0, 0.04);
--modal-header-bg: #f8fafc;
--modal-header-border: #e2e8f0;
--modal-header-text: #0f172a;
--modal-body-bg: #ffffff;
--modal-body-text: #334155;
--modal-footer-bg: #f8fafc;
--modal-footer-border: #e2e8f0;
--modal-close-color: #94a3b8;
--modal-close-hover: #0f172a;
--modal-input-bg: #f8fafc;
--modal-input-border: #e2e8f0;
--modal-input-text: #0f172a;
--modal-input-focus-border: #2563eb;
--modal-input-focus-ring: rgba(37, 99, 235, 0.18);
--editor-body-bg: #ffffff;
--editor-border: #e2e8f0;
--editor-text: #0f172a;
--editor-text-secondary: #475569;
--editor-toolbar-bg: #1e3a5f;
--editor-toolbar-text: #f1f5f9;
--editor-toolbar-pane-bg: #f3f8ff;
--editor-toolbar-pane-text: #1775f6;
--editor-footer-controls-bg: #0e4694;
--editor-footer-info-bg: var(--color-primary);
--editor-footer-text: #fcfcfc;
--editor-widget-bg: #e8f1fe;
--editor-widget-border: #0e4694;
--editor-widget-text: #121a5e;
--editor-widget-label-bg: transparent;
--editor-widget-label-text: #f3f8ff;
--editor-widget-hover-bg: #d4e4f7;
--editor-widget-selected-bg: #6ec071;
--editor-widget-multi-bg: #eb7857;
--editor-widget-multi-hover-bg: #f09a82;
--editor-left-margin-bg: #e9e9e9;
--editor-timegrid-line: #cecece;
--editor-timegrid-text: #898989;
--editor-timegrid-overlay: rgba(255, 255, 255, 0.7);
--editor-timeline-bg: rgba(255, 255, 255, 0.65);
--editor-scrollbar-track: #f3f8ff;
--editor-scrollbar-thumb: #0e4694;
--editor-scrollbar-thumb-hover: #1264d6;
--editor-properties-bg: #f3f8ff;
--editor-properties-border: #6ec071;
--editor-header-bg: #f1f5f9;
--editor-back-btn-bg: #1e3a5f;
--editor-back-btn-text: #ffffff;
background-color: var(--color-background);
color: var(--color-text-primary);
}
body.ots-light-mode .ots-sidebar {
background-color: #f1f5f9 !important;
border-right-color: #e2e8f0 !important;
}
body.ots-light-mode .ots-sidebar.collapsed .sidebar-group-toggle,
body.ots-light-mode .ots-sidebar.collapsed .sidebar-list > a {
background: rgba(59, 130, 246, 0.06) !important;
color: #334155 !important;
}
body.ots-light-mode .ots-sidebar.collapsed .sidebar-group-toggle:hover,
body.ots-light-mode .ots-sidebar.collapsed .sidebar-list > a:hover {
background: rgba(59, 130, 246, 0.12) !important;
color: #0f172a !important;
}
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon {
color: #334155 !important;
}
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon::before,
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon.fa::before,
body.ots-light-mode .ots-sidebar.collapsed .fa::before {
color: #334155 !important;
}
body.ots-light-mode .ots-sidebar li.sidebar-list > a,
body.ots-light-mode .ots-sidebar li.sidebar-main > a {
color: #334155;
}
body.ots-light-mode .ots-sidebar li.sidebar-list > a:hover {
color: #0f172a;
background-color: rgba(59, 130, 246, 0.08);
}
body.ots-light-mode .sidebar-group-toggle {
color: #334155;
background: rgba(0, 0, 0, 0.03);
}
body.ots-light-mode .sidebar-group-toggle:hover {
background: rgba(0, 0, 0, 0.06);
color: #0f172a;
}
body.ots-light-mode .sidebar-group.is-open > .sidebar-group-toggle,
body.ots-light-mode .sidebar-group-toggle[aria-expanded="true"] {
background: #ffffff;
color: #0b1221 !important;
}
body.ots-light-mode .sidebar-submenu .sidebar-list > a {
background: rgba(0, 0, 0, 0.04);
color: #334155;
border-left-color: #cbd5e1;
}
/* Light-mode collapsed flyout panel */
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu {
background: #ffffff !important;
border-color: #e2e8f0 !important;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12) !important;
}
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .sidebar-list > a {
color: #334155 !important;
background: transparent !important;
border-left: none !important;
}
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .sidebar-list > a:hover {
background: rgba(59, 130, 246, 0.1) !important;
color: #1d4ed8 !important;
}
body.ots-light-mode .sidebar-header {
border-bottom-color: #e2e8f0;
background: #f1f5f9;
}
body.ots-light-mode .ots-topbar {
background-color: transparent;
border-bottom: none;
}
/* (topbar strip is now hidden — light-mode overrides removed) */
body.ots-light-mode .ots-topbar .nav-link {
color: #334155;
}
body.ots-light-mode .ots-topbar .nav-link:hover {
background-color: rgba(59, 130, 246, 0.06);
color: #2563eb;
}
body.ots-light-mode .dashboard-card,
body.ots-light-mode .content-card {
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95), rgba(241, 245, 249, 0.95));
border-color: #e2e8f0;
}
body.ots-light-mode .dropdown-menu,
body.ots-light-mode .dropdown-right {
background-color: #ffffff;
border-color: #e2e8f0;
color: #0f172a;
}
body.ots-light-mode .dropdown-item {
color: #334155;
}
body.ots-light-mode .dropdown-item:hover,
body.ots-light-mode .dropdown-menu a:hover {
background-color: rgba(59, 130, 246, 0.1);
color: #2563eb;
}
body.ots-light-mode .ots-content {
background-color: var(--color-background);
}
/* ============================================================================
THEME ENFORCE - Ensure page backgrounds follow the light/dark CSS variables
This block uses high-specificity rules and !important to override other
theme rules that may hardcode colors so the toggle always reflects
the `--color-*` variables set by `body.ots-light-mode` or :root.
============================================================================ */
html, body, #page-wrapper, .ots-main, .ots-content, .page-content {
background-color: var(--color-background) !important;
color: var(--color-text-primary) !important;
}
/* Topbar, footer and panels should use surface variables (elevated where appropriate) */
.ots-topbar,
.ots-footer,
.dashboard-card,
.content-card,
.dropdown-menu,
.dropdown-right,
.modal-content {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
}
/* Surface-elevated elements (cards, panels) */
.card,
.card-body,
.panel,
.panel-body,
.ots-panel,
.modal-body {
background-color: var(--color-surface-elevated) !important;
color: var(--color-text-primary) !important;
}
/* Ensure sidebar and its components still receive their own overrides */
.ots-sidebar,
.ots-sidebar .sidebar-header,
.ots-sidebar .sidebar-content {
background-color: var(--ots-sidebar-bg) !important;
color: var(--ots-sidebar-link) !important;
}
/* ============================================================================
SHELL LAYOUT - SIDEBAR + MAIN
============================================================================ */
.ots-shell {
display: flex;
min-height: 100vh;
}
.ots-sidebar {
position: fixed;
left: 0;
top: 0;
width: max-content !important;
min-width: var(--ots-sidebar-collapsed-width);
max-width: 300px;
height: 100vh;
background-color: var(--ots-sidebar-bg) !important;
padding: 0;
display: flex;
flex-direction: column;
overflow-x: hidden;
overflow-y: auto;
z-index: 1200;
transition: width 200ms ease;
}
.ots-sidebar .ots-nav-text,
.ots-sidebar .sidebar-submenu .ots-nav-text {
white-space: nowrap;
}
#sidebar-wrapper {
background-color: var(--ots-sidebar-bg) !important;
}
.ots-main {
flex: 1;
display: flex;
flex-direction: column;
position: relative;
margin-left: var(--ots-sidebar-actual-width, var(--ots-sidebar-width)) !important;
width: calc(100vw - var(--ots-sidebar-actual-width, var(--ots-sidebar-width))) !important;
max-width: calc(100vw - var(--ots-sidebar-actual-width, var(--ots-sidebar-width))) !important;
transition: margin-left 200ms ease, width 200ms ease, max-width 200ms ease;
overflow-x: hidden !important;
box-sizing: border-box !important;
}
#page-wrapper {
position: relative;
margin-left: 0 !important;
padding-left: 0 !important;
border: none !important;
box-shadow: none !important;
background-color: var(--color-background) !important;
max-width: 100vw !important;
overflow-x: hidden !important;
box-sizing: border-box !important;
}
#page-wrapper.active {
padding-left: 0 !important;
margin-left: 0 !important;
}
/* Sidebar mode only — #page-wrapper is absent in horizontal nav mode */
#page-wrapper #content-wrapper {
margin-left: var(--ots-sidebar-actual-width, var(--ots-sidebar-width)) !important;
width: calc(100vw - var(--ots-sidebar-actual-width, var(--ots-sidebar-width))) !important;
max-width: calc(100vw - var(--ots-sidebar-actual-width, var(--ots-sidebar-width))) !important;
transition: margin-left 200ms ease, width 200ms ease, max-width 200ms ease;
padding-left: var(--ots-sidebar-content-gap) !important;
padding-right: 16px !important;
border-left: none !important;
box-shadow: none !important;
outline: none !important;
overflow-x: hidden !important;
box-sizing: border-box !important;
}
/* Base styles for #content-wrapper in all modes */
#content-wrapper {
border-left: none !important;
box-shadow: none !important;
outline: none !important;
overflow-x: hidden !important;
box-sizing: border-box !important;
}
/* ============================================================================
PLAYLIST / LAYOUT EDITOR themed for dark/light mode
The .editor-modal is AJAX-injected into #editor-container (inside
#page-wrapper > #content-wrapper > .page-content). It borrows Bootstrap's
.modal class for position:fixed but is NOT opened via $.modal().
All colours use --editor-* CSS variables defined in :root and
body.ots-light-mode so they follow the active theme.
============================================================================ */
/* --- 1. The .editor-modal overlay ---------------------------------------- */
.editor-modal.modal {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
max-width: none !important;
margin: 0 !important;
background-color: var(--editor-modal-bg) !important;
background-image: none !important;
border: none !important;
box-shadow: none !important;
z-index: 1201 !important;
display: block !important;
opacity: 1 !important;
overflow: auto !important;
}
.editor-modal .editor-modal-dialog {
max-width: 100%;
height: calc(100% - 6rem);
margin: 3rem;
}
.editor-modal .editor-modal-content {
background-color: var(--editor-modal-content-bg) !important;
color: var(--editor-text) !important;
border: none !important;
height: 100%;
}
.editor-modal .editor-modal-header {
background-color: var(--editor-modal-header-bg) !important;
color: var(--editor-modal-header-text) !important;
border-bottom: 1px solid var(--editor-border) !important;
}
.editor-modal .editor-modal-header .modal-header--left,
.editor-modal .editor-modal-title {
color: var(--editor-modal-header-text) !important;
}
.editor-modal .editor-modal-header .playlist-info-widgets,
.editor-modal .editor-modal-header .playlist-info-duration {
color: var(--editor-modal-header-text) !important;
}
.editor-modal .editor-modal-close {
color: var(--editor-text-secondary) !important;
}
.editor-modal .editor-modal-body {
background-color: var(--editor-modal-content-bg) !important;
}
/* --- 2. Inner editor containers ------------------------------------------ */
#playlist-editor,
#layout-editor,
.playlist-editor,
.layout-editor {
background-color: var(--editor-body-bg) !important;
border-color: var(--color-primary) !important;
color: var(--editor-text) !important;
}
#playlist-editor-container,
#playlist-editor-container .editor-body,
.playlist-editor-inline-container {
background-color: var(--editor-body-bg) !important;
background-image: none !important;
}
/* --- 3. Left margin gutter ---------------------------------------------- */
#playlist-editor .left-margin {
background-color: var(--editor-left-margin-bg) !important;
}
/* --- 4. Time grid (horizontal lines behind timeline) -------------------- */
#playlist-editor .time-grid {
color: var(--editor-timegrid-text) !important;
}
#playlist-editor .time-grid .time-grid-step {
background-color: var(--editor-timegrid-line) !important;
}
#playlist-editor .time-grid .step-value {
color: var(--editor-timegrid-text) !important;
}
#playlist-editor .time-grid::after {
background-color: var(--editor-timegrid-overlay) !important;
}
/* --- 5. Timeline area ---------------------------------------------------- */
#playlist-timeline {
background-color: var(--editor-timeline-bg) !important;
background-image: none !important;
}
#timeline-container {
background-color: transparent !important;
}
/* --- 6. Widget cards in timeline ----------------------------------------- */
#playlist-timeline .playlist-widget {
background-color: var(--editor-widget-bg) !important;
outline-color: var(--editor-widget-border) !important;
color: var(--editor-widget-text) !important;
}
#playlist-timeline .playlist-widget .widgetLabel {
background-color: var(--editor-widget-label-bg) !important;
color: var(--editor-widget-label-text) !important;
}
#playlist-timeline .playlist-widget .widgetName {
color: var(--editor-widget-text) !important;
}
#playlist-timeline .playlist-widget .widgetProperties,
#playlist-timeline .playlist-widget .widgetProperties i {
color: var(--editor-text-secondary) !important;
}
#playlist-timeline .playlist-widget .widgetDuration {
color: var(--editor-widget-label-text) !important;
}
#playlist-timeline .playlist-widget i.editProperty {
color: var(--editor-widget-text) !important;
}
#playlist-timeline .playlist-widget.selectable:hover {
background-color: var(--editor-widget-hover-bg) !important;
}
#playlist-timeline .playlist-widget.selected {
background-color: var(--editor-widget-selected-bg) !important;
}
/* Multi-select */
#playlist-editor.multi-select .playlist-widget:hover {
background-color: var(--editor-widget-multi-hover-bg) !important;
}
#playlist-editor.multi-select .playlist-widget.multi-selected {
background-color: var(--editor-widget-multi-bg) !important;
}
/* --- 7. Footer bar ------------------------------------------------------- */
#playlist-editor .editor-footer .footer-controls {
background-color: var(--editor-footer-controls-bg) !important;
}
#playlist-editor .editor-footer .footer-controls .btn {
color: var(--editor-footer-text) !important;
}
#playlist-editor .editor-footer .footer-controls .btn:hover {
color: #ffffff !important;
background-color: var(--color-secondary, #121a5e) !important;
}
#playlist-editor .editor-footer .footer-info {
background-color: var(--editor-footer-info-bg) !important;
color: var(--editor-footer-text) !important;
}
#playlist-editor .editor-footer .footer-info .selected-info {
color: var(--editor-footer-text) !important;
}
#playlist-editor .editor-footer .footer-actions button {
color: var(--editor-footer-text) !important;
}
/* --- 8. Editor toolbar / sidebar (fixed left panel) ---------------------- */
.editor-toolbar.editor-side-bar-playlist-editor nav,
.editor-toolbar.editor-side-bar nav,
.editor-toolbar nav {
background-color: var(--editor-toolbar-bg) !important;
color: var(--editor-toolbar-text) !important;
}
.editor-toolbar nav .toolbar-menu-content .toolbar-pane {
background-color: var(--editor-toolbar-pane-bg) !important;
color: var(--editor-toolbar-pane-text) !important;
}
.editor-toolbar nav .toolbar-menu-content .toolbar-pane .content-title {
color: var(--editor-toolbar-pane-text) !important;
}
.editor-toolbar nav .toolbar-menu-content .toolbar-pane .close-content {
color: var(--editor-text-secondary) !important;
}
/* Toolbar card rows */
.editor-toolbar nav tr.toolbar-card {
color: var(--editor-toolbar-pane-text) !important;
}
.editor-toolbar nav tr.toolbar-card.card-selected {
background-color: color-mix(in srgb, var(--color-primary) 15%, transparent) !important;
}
/* Toolbar buttons */
.editor-toolbar nav .toolbar-menu .toolbar-menu-btn {
color: var(--editor-toolbar-text) !important;
}
.editor-toolbar nav .toolbar-menu .toolbar-menu-btn:hover,
.editor-toolbar nav .toolbar-menu .toolbar-menu-btn.active {
background-color: rgba(255, 255, 255, 0.15) !important;
}
/* --- 9. Back button (fixed top-left) ------------------------------------- */
.editor-modal .back-button,
.back-button {
background-color: var(--editor-back-btn-bg) !important;
}
.editor-modal .back-button a,
.back-button a {
color: var(--editor-back-btn-text) !important;
}
.editor-modal .back-button a:hover,
.back-button a:hover {
background-color: rgba(255, 255, 255, 0.1) !important;
}
.editor-modal .back-button span {
color: var(--editor-back-btn-text) !important;
}
/* --- 10. Properties panel (right side) ----------------------------------- */
.properties-panel-playlist-editor,
.properties-panel-container {
background-color: var(--editor-body-bg) !important;
}
.properties-panel-container #properties-panel {
background-color: var(--editor-body-bg) !important;
color: var(--editor-text) !important;
}
.properties-panel-container #properties-panel-form-container {
background-color: var(--editor-modal-content-bg) !important;
color: var(--editor-text) !important;
}
.properties-panel-container #properties-panel .loading-container {
background-color: var(--editor-properties-bg) !important;
}
.properties-panel-container #properties-panel .loading-icon {
color: var(--color-primary) !important;
}
.properties-panel-container #properties-panel .unsuccessMessage {
color: #ffffff !important;
}
/* Tab styling for properties panel — initial pass (reinforced at end of file) */
.properties-panel-container #properties-panel .nav .nav-link,
.properties-panel-container #properties-panel .nav > li > a,
#properties-panel .nav .nav-link,
#properties-panel .nav > li > a {
color: var(--editor-text-secondary) !important;
background: var(--editor-header-bg) !important;
background-color: var(--editor-header-bg) !important;
border: none !important;
border-color: transparent !important;
box-shadow: none !important;
opacity: 1 !important;
}
.properties-panel-container #properties-panel .nav .nav-link.active,
.properties-panel-container #properties-panel .nav > li > a.active,
#properties-panel .nav .nav-link.active,
#properties-panel .nav > li > a.active {
color: var(--color-primary) !important;
background: var(--editor-header-bg) !important;
background-color: var(--editor-header-bg) !important;
border: none !important;
border-bottom: 2px solid var(--color-primary) !important;
opacity: 1 !important;
}
.properties-panel-container #properties-panel .nav,
.properties-panel-container #properties-panel .nav-tabs,
#properties-panel .nav,
#properties-panel .nav-tabs {
background: var(--editor-header-bg) !important;
background-color: var(--editor-header-bg) !important;
}
.properties-panel-container #properties-panel .form-content label {
color: var(--editor-text) !important;
}
/* More aggressive label overrides for all label elements in properties panel */
#properties-panel label,
#properties-panel .label,
#properties-panel .form-label,
.properties-panel-container label,
.properties-panel-container .label,
.properties-panel-container .form-label,
.form-group label {
color: var(--editor-text) !important;
}
.properties-panel-container #properties-panel .form-content .form-control {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
border-color: var(--editor-border) !important;
}
/* Select2 elements inside properties panel */
.properties-panel-container .select2-container--default .select2-selection--single {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
border-color: var(--editor-border) !important;
}
.properties-panel-container .select2-container--default .select2-selection--single .select2-selection__rendered {
color: var(--editor-text) !important;
}
/* Placeholder text in select2 */
.properties-panel-container .select2-container--default .select2-selection--single .select2-selection__placeholder {
color: var(--editor-text-secondary) !important;
}
.properties-panel-container .select2-container--default .select2-selection--single .select2-selection__arrow b {
border-color: var(--editor-text-secondary) transparent transparent transparent !important;
}
/* Select2 dropdown theming (appended to body, not in panel) */
.select2-container--open .select2-dropdown {
background-color: var(--color-surface) !important;
color: var(--editor-text, var(--color-text-primary)) !important;
border-color: var(--editor-border, var(--color-border)) !important;
}
.select2-container--default .select2-results__option {
color: var(--editor-text, var(--color-text-primary)) !important;
}
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: color-mix(in srgb, var(--color-primary) 15%, var(--color-surface)) !important;
color: var(--editor-text, var(--color-text-primary)) !important;
}
.select2-container--default .select2-search--dropdown .select2-search__field {
background-color: var(--color-surface-elevated) !important;
color: var(--color-text-primary) !important;
border-color: var(--color-border) !important;
}
#playlist-properties-panel {
background-color: var(--editor-properties-bg) !important;
border-color: var(--editor-properties-border) !important;
color: var(--editor-text) !important;
}
/* --- 11. Scrollbars inside editor ---------------------------------------- */
#playlist-editor ::-webkit-scrollbar-track,
#layout-editor ::-webkit-scrollbar-track {
background: var(--editor-scrollbar-track) !important;
}
#playlist-editor ::-webkit-scrollbar-thumb,
#layout-editor ::-webkit-scrollbar-thumb {
background: var(--editor-scrollbar-thumb) !important;
}
#playlist-editor ::-webkit-scrollbar-thumb:hover,
#layout-editor ::-webkit-scrollbar-thumb:hover {
background: var(--editor-scrollbar-thumb-hover) !important;
}
/* --- 12. Drag-drop overlay ----------------------------------------------- */
#timeline-overlay-container {
background-color: var(--editor-body-bg) !important;
}
#timeline-overlay-container .timeline-overlay-step {
background-color: var(--color-primary-light) !important;
}
#timeline-overlay-container .timeline-overlay-step:hover {
background-color: var(--color-primary-lighter, #dbeafe) !important;
}
/* --- 13. Layout editor viewer panel -------------------------------------- */
#layout-editor {
background-color: var(--editor-body-bg) !important;
color: var(--editor-text) !important;
}
#layout-editor .main-panel-wrapper {
background-color: var(--editor-left-margin-bg) !important;
border-color: var(--color-primary-light) !important;
}
#layout-editor #layout-viewer {
background-color: var(--editor-left-margin-bg) !important;
}
#layout-editor .editor-bottom-bar {
background-color: var(--editor-footer-controls-bg) !important;
color: var(--editor-footer-text) !important;
}
/* --- 15. Properties panel nav tabs, forms, buttons, labels ------------- */
/* Tab navigation inside properties panel */
.properties-panel-container .nav > li > a,
#properties-panel .nav > li > a,
#properties-panel .form-container .nav > li > a {
color: var(--editor-text-secondary) !important;
background: var(--editor-header-bg) !important;
background-color: var(--editor-header-bg) !important;
border: none !important;
}
/* Widget editor tabs (Configure/Advanced) should blend with surrounding background */
.editor-modal .widget-form .nav-tabs,
.editor-modal .widget-form .nav-tabs .nav-link {
background-color: transparent !important;
border-color: transparent !important;
}
.editor-modal .widget-form .nav-tabs .nav-link {
color: var(--editor-text) !important;
opacity: 1 !important;
}
.editor-modal .widget-form .nav-tabs .nav-link.active {
color: var(--color-primary) !important;
border-bottom: 2px solid var(--color-primary) !important;
background-color: transparent !important;
}
/* Ultra-specific override to beat editor tab defaults */
#properties-panel .widget-form ul.nav.nav-tabs,
#properties-panel .widget-form ul.nav.nav-tabs > li.nav-item,
#properties-panel .widget-form ul.nav.nav-tabs > li.nav-item > a.nav-link,
#properties-panel .widget-form ul.nav.nav-tabs > li.nav-item > a.nav-link > span,
.editor-modal #properties-panel .widget-form ul.nav.nav-tabs,
.editor-modal #properties-panel .widget-form ul.nav.nav-tabs > li.nav-item,
.editor-modal #properties-panel .widget-form ul.nav.nav-tabs > li.nav-item > a.nav-link,
.editor-modal #properties-panel .widget-form ul.nav.nav-tabs > li.nav-item > a.nav-link > span {
background-color: transparent !important;
background-image: none !important;
box-shadow: none !important;
border-color: transparent !important;
}
#properties-panel .widget-form ul.nav.nav-tabs > li.nav-item > a.nav-link,
.editor-modal #properties-panel .widget-form ul.nav.nav-tabs > li.nav-item > a.nav-link {
color: var(--editor-text) !important;
opacity: 1 !important;
}
#properties-panel .widget-form ul.nav.nav-tabs > li.nav-item > a.nav-link.active,
.editor-modal #properties-panel .widget-form ul.nav.nav-tabs > li.nav-item > a.nav-link.active {
color: var(--color-primary) !important;
border-bottom: 2px solid var(--color-primary) !important;
background-color: transparent !important;
}
.properties-panel-container .nav > li > a.active,
#properties-panel .nav > li > a.active,
.form-container .nav > li > a.active {
color: var(--color-primary) !important;
background-color: var(--editor-modal-content-bg) !important;
}
/* Form groups, labels, text in properties panel */
#properties-panel .form-group,
#properties-panel .form-check,
#properties-panel .input-group,
#properties-panel label,
#properties-panel .form-label,
#properties-panel legend,
#properties-panel .help-block,
#properties-panel .control-label {
color: var(--editor-text) !important;
}
/* Info/help icons */
#properties-panel .info-icon,
#properties-panel .fa-info-circle,
#properties-panel .fa-question-circle {
color: var(--color-primary) !important;
}
/* Action buttons in properties panel */
#properties-panel .button-container .btn,
#properties-panel .form-buttons .btn {
color: var(--editor-text) !important;
border-color: var(--editor-border) !important;
}
#properties-panel .button-container .btn-info,
#properties-panel .form-buttons .btn-info {
background-color: var(--color-primary) !important;
color: #ffffff !important;
border-color: var(--color-primary) !important;
}
#properties-panel .button-container .btn-white,
#properties-panel .button-container .btn-default,
#properties-panel .form-buttons .btn-white,
#properties-panel .form-buttons .btn-default {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
border-color: var(--editor-border) !important;
}
/* Actions content buttons (layout editor actions pane) */
#properties-panel .actions-content-button {
background-color: var(--color-surface-elevated) !important;
color: var(--color-primary) !important;
border-color: var(--editor-border) !important;
}
/* Action forms inside properties panel */
#properties-panel .action-edit-form,
#properties-panel .action-view {
background-color: var(--color-surface) !important;
border-color: var(--editor-border) !important;
}
#properties-panel .action-label,
#properties-panel .action-value {
color: var(--editor-text) !important;
}
#properties-panel .action-btn {
color: #ffffff !important;
}
#properties-panel .action-btn[data-action="close"],
#properties-panel .action-edit-widget-btn {
color: var(--color-primary) !important;
border-color: var(--editor-border) !important;
}
/* Action target widget controls */
#properties-panel .action-target-widget-edit-container {
background-color: var(--color-surface-elevated) !important;
}
#properties-panel .action-target-widget-dropdown-button {
color: var(--color-primary) !important;
border-color: var(--editor-border) !important;
}
#properties-panel .action-target-widget-dropdown-container {
background-color: var(--color-surface) !important;
}
#properties-panel .action-target-widget-dropdown-container .action-edit-widget-btn {
color: var(--editor-text) !important;
}
/* Form content title border */
#properties-panel .form-content-title {
border-bottom-color: var(--editor-border) !important;
color: var(--editor-text) !important;
}
/* Textarea buttons bar (rich text) */
#properties-panel .text-area-buttons {
background-color: var(--color-surface-elevated) !important;
}
/* Panel headings */
#properties-panel .panel-heading {
background-color: var(--color-surface-elevated) !important;
}
#properties-panel .panel-title {
color: var(--color-primary) !important;
}
/* Snippet selector */
#properties-panel .snippet-selector .select2-selection {
background-color: var(--color-surface-elevated) !important;
}
#properties-panel .snippet-selector .select2-selection__placeholder {
color: var(--editor-text-secondary) !important;
}
/* Image replace area */
#properties-panel .image-replace-control-area {
color: var(--editor-text) !important;
background-color: var(--color-surface-elevated) !important;
}
/* Rich text dimensions control */
#properties-panel .rich-text-dimensions-control.detached {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
}
/* Button switch input group */
#properties-panel .button-switch-input-group button {
color: var(--color-primary) !important;
border-color: var(--editor-border) !important;
}
/* Description / compat messages */
#properties-panel .desc,
#properties-panel .message {
color: var(--editor-text-secondary) !important;
}
/* Developer template controls */
#properties-panel .developer-template-placeholder {
color: var(--color-primary) !important;
background-color: var(--color-surface-elevated) !important;
}
#properties-panel .developer-template-control-item {
background-color: var(--color-surface-elevated) !important;
color: var(--editor-text) !important;
}
/* Background image controls */
#properties-panel .background-image-add {
background-color: var(--color-surface-elevated) !important;
color: var(--editor-text) !important;
}
#properties-panel .background-image-actions .btn-group {
background-color: var(--color-surface) !important;
}
/* --- 16. Toolbar pane cards & content ------------------------------------ */
/* Toolbar cards */
.editor-toolbar .toolbar-card {
background-color: var(--color-surface-elevated) !important;
color: var(--editor-text) !important;
}
.editor-toolbar .toolbar-card .card-icon {
color: var(--color-primary) !important;
}
.editor-toolbar .toolbar-card .media-title {
color: var(--editor-text) !important;
}
.editor-toolbar .toolbar-card .media-duration {
background-color: var(--editor-footer-controls-bg) !important;
color: var(--editor-footer-text) !important;
}
.editor-toolbar .toolbar-card .select-button {
background-color: var(--color-surface-elevated) !important;
color: var(--editor-toolbar-text) !important;
}
.editor-toolbar .toolbar-card .preview-button {
background-color: var(--color-primary) !important;
color: #ffffff !important;
}
.editor-toolbar .toolbar-card.has-thumb .toolbar-content {
color: var(--editor-text) !important;
}
.editor-toolbar .toolbar-playlists-pane .toolbar-card-preview {
background-color: var(--color-surface-elevated) !important;
color: var(--editor-text) !important;
}
/* Upload container */
.editor-toolbar .upload-container {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
}
/* Show more button */
.editor-toolbar .show-more {
background-color: var(--color-surface) !important;
color: var(--color-primary) !important;
}
/* Provider badge */
.editor-toolbar .provider img {
background-color: var(--color-surface) !important;
}
/* Toolbar search forms */
.editor-toolbar .toolbar-pane form label {
color: var(--editor-toolbar-pane-text) !important;
}
.editor-toolbar .toolbar-pane form .form-control {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
border-color: var(--editor-border) !important;
}
/* Toolbar navbar buttons (bottom icons) */
.editor-toolbar .navbar-buttons a {
color: var(--editor-toolbar-text) !important;
}
.editor-toolbar .navbar-buttons a.active {
background-color: var(--color-surface-elevated) !important;
color: var(--color-primary) !important;
}
/* Toolbar navbar submenu */
.editor-toolbar .navbar-submenu > a {
color: var(--editor-toolbar-text) !important;
}
.editor-toolbar .navbar-submenu > a:hover {
background-color: rgba(255, 255, 255, 0.1) !important;
color: #ffffff !important;
}
.editor-toolbar .navbar-submenu .trash-container {
color: var(--color-danger) !important;
}
/* --- 17. Layout editor top bar & bottom bar ------------------------------ */
/* Top bar */
.editor-top-bar nav,
body.editor-opened .header-side {
background-color: var(--editor-modal-header-bg) !important;
color: var(--editor-text) !important;
}
.editor-top-bar .navbar-text.layout-info {
color: var(--editor-text) !important;
}
/* Bottom bar nav & buttons */
.editor-bottom-bar nav {
background-color: var(--editor-modal-content-bg) !important;
color: var(--editor-text) !important;
}
.editor-bottom-bar nav .btn {
color: var(--editor-text) !important;
}
.editor-bottom-bar nav .btn:hover {
color: var(--color-primary) !important;
}
.editor-bottom-bar .viewer-navbar-info {
background-color: var(--color-primary) !important;
color: #ffffff !important;
}
.editor-bottom-bar .viewer-navbar-info .btn {
color: #ffffff !important;
}
/* Fullscreen & layer manager buttons */
#layout-editor #fullscreenBtn,
#layout-editor #layerManagerBtn,
#layout-editor .snap-controls > .btn {
background-color: var(--color-surface) !important;
color: var(--color-primary) !important;
}
#layout-editor #layerManagerBtn.active,
#layout-editor .snap-controls > .btn.active {
background-color: var(--color-primary) !important;
color: #ffffff !important;
}
#layout-editor .snap-to-grid-value {
color: var(--color-primary) !important;
}
/* --- 18. Layer manager --------------------------------------------------- */
#layerManager {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
}
#layerManager .layer-manager-header {
background-color: var(--color-primary) !important;
color: #ffffff !important;
}
#layerManager .layer-manager-layer-item {
color: var(--editor-text) !important;
}
#layerManager .layer-manager-layer-item .layer {
background-color: var(--color-surface-elevated) !important;
color: var(--editor-text) !important;
}
#layerManager .layer-manager-layer-item.selectable:not(.selected):hover {
color: var(--color-primary) !important;
}
#layerManager .layer-manager-canvas-layers .layer-manager-layer-item {
background-color: var(--color-surface-elevated) !important;
}
#layerManager .has-group {
background-color: var(--color-surface-elevated) !important;
}
/* --- 19. Action screen helpers (viewer interactions) ---------------------- */
.action-screen-helper {
background-color: var(--color-surface) !important;
color: var(--color-primary) !important;
}
.action-screen-recent {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
}
.action-layout-dock-search-button {
background-color: var(--color-surface) !important;
color: var(--color-primary) !important;
}
.action-layout-dock-search-results-container {
background-color: var(--color-surface) !important;
}
.action-layout-dock-search-find {
color: var(--editor-text) !important;
background-color: var(--color-surface-elevated) !important;
}
.action-layout-dock-option {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
}
/* --- 20. Context menus inside editor ------------------------------------- */
.context-menu {
background-color: var(--color-surface) !important;
border-color: var(--editor-border) !important;
}
.context-menu-btn {
color: var(--color-primary) !important;
}
.context-menu-btn:hover {
background-color: var(--color-surface-elevated) !important;
}
/* --- 21. Scaled timeline footer controls --------------------------------- */
#playlist-editor.timeline-scaled .footer-controls .btn-scale-control {
background-color: var(--color-surface) !important;
color: var(--color-primary) !important;
}
#playlist-editor.timeline-scaled .footer-controls .btn-scale-control:hover {
background-color: var(--color-surface-elevated) !important;
}
/* --- 22. Popovers inside editor ------------------------------------------ */
.editor-modal .popover,
#layout-editor .popover {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
border-color: var(--editor-border) !important;
}
/* --- 23. External playlist message --------------------------------------- */
.external-playlist-message-container {
color: var(--editor-text) !important;
}
/* --- 24. General form/input overrides inside any editor context ----------- */
.editor-modal input[type="text"],
.editor-modal input[type="number"],
.editor-modal input[type="search"],
.editor-modal textarea,
.editor-modal select,
#layout-editor input[type="text"],
#layout-editor input[type="number"],
#layout-editor input[type="search"],
#layout-editor textarea,
#layout-editor select {
background-color: var(--color-surface) !important;
color: var(--editor-text) !important;
border-color: var(--editor-border) !important;
}
.editor-modal label,
.editor-modal .form-label,
.editor-modal legend,
.editor-modal .control-label,
#layout-editor label,
#layout-editor .form-label,
#layout-editor legend,
#layout-editor .control-label {
color: var(--editor-text) !important;
}
/* --- 25. Comprehensive form element overrides for all contexts ----------- */
/* ANY form-group label anywhere */
body #properties-panel .form-group > label:first-child,
body .editor-modal .form-group > label:first-child,
body #layout-editor .form-group > label:first-child,
body .container-designer .form-group > label:first-child {
color: var(--editor-text) !important;
}
/* ANY select dropdown (native and enhanced) */
body #properties-panel select,
body #properties-panel .select2-container,
body .editor-modal select,
body .editor-modal .select2-container,
body #layout-editor select,
body #layout-editor .select2-container {
color: var(--editor-text) !important;
}
/* Specific override for properties panel form rows */
#properties-panel .form-row,
#properties-panel .row {
color: var(--editor-text) !important;
}
/* Form group text */
#properties-panel .form-group,
.editor-modal .form-group,
#layout-editor .form-group {
color: var(--editor-text) !important;
}
/* Input placeholders */
.editor-modal input::placeholder,
#properties-panel input::placeholder,
#layout-editor input::placeholder,
.editor-modal textarea::placeholder,
#properties-panel textarea::placeholder,
#layout-editor textarea::placeholder {
color: var(--editor-text-secondary) !important;
opacity: 0.7;
}
/* Help text and descriptions */
.editor-modal .help-block,
.editor-modal small,
.editor-modal .form-text,
.editor-modal .invalid-feedback,
.editor-modal .valid-feedback,
#properties-panel .help-block,
#properties-panel small,
#properties-panel .form-text,
#properties-panel .invalid-feedback,
#properties-panel .valid-feedback,
#layout-editor .help-block,
#layout-editor small,
#layout-editor .form-text,
#layout-editor .invalid-feedback,
#layout-editor .valid-feedback {
color: var(--editor-text-secondary) !important;
}
/* Form check labels (checkboxes, radios) */
.editor-modal .form-check-label,
.editor-modal .form-check input ~ label,
#properties-panel .form-check-label,
#properties-panel .form-check input ~ label,
#layout-editor .form-check-label,
#layout-editor .form-check input ~ label {
color: var(--editor-text) !important;
}
/* Input addon text */
.editor-modal .input-group-text,
.editor-modal .input-group-addon,
#properties-panel .input-group-text,
#properties-panel .input-group-addon,
#layout-editor .input-group-text,
#layout-editor .input-group-addon {
background-color: var(--color-surface-elevated) !important;
color: var(--editor-text) !important;
border-color: var(--editor-border) !important;
}
/* Button in form context */
.editor-modal button,
.editor-modal .btn,
#properties-panel button,
#properties-panel .btn,
#layout-editor button,
#layout-editor .btn {
color: var(--editor-text) !important;
}
/* --- 14a. No-nav pages (layout designer, etc.) remove sidebar spacing -- */
#content-wrapper.no-nav {
margin-left: 0 !important;
width: 100% !important;
max-width: 100% !important;
padding: 0 !important;
}
#content-wrapper.no-nav .page-content {
padding: 0 !important;
margin: 0 !important;
}
#content-wrapper.no-nav .page-content .row {
margin: 0 !important;
padding: 0 !important;
}
#content-wrapper.no-nav .page-content [class*="col-"] {
margin: 0 !important;
padding: 0 !important;
}
/* --- 14b. Hide the page behind the editor (body class set by JS) --------- */
body.ots-playlist-editor-active .ots-sidebar {
visibility: hidden !important;
}
body.ots-playlist-editor-active .ots-topbar {
visibility: hidden !important;
}
body.ots-playlist-editor-active .ots-page-actions {
display: none !important;
}
body.ots-playlist-editor-active #help-pane {
display: none !important;
}
body.ots-playlist-editor-active .page-content > .row > .col-sm-12 > *:not(#editor-container):not(#layout-editor):not(#playlist-editor):not(.loading-overlay) {
display: none !important;
}
body.ots-playlist-editor-active #content-wrapper,
body.ots-playlist-editor-active .ots-main {
margin-left: 0 !important;
width: 100% !important;
max-width: 100% !important;
padding: 0 !important;
overflow: visible !important;
}
body.ots-playlist-editor-active .ots-content,
body.ots-playlist-editor-active .page-content {
padding-left: 0 !important;
padding-right: 0 !important;
}
body.ots-playlist-editor-active .page-content .row,
body.ots-playlist-editor-active .page-content [class*="col-"] {
margin-left: 0 !important;
margin-right: 0 !important;
padding-left: 0 !important;
padding-right: 0 !important;
}
/* Collapsed: shift content to match the narrow sidebar */
body.ots-sidebar-collapsed .ots-main,
body.ots-sidebar-collapsed #content-wrapper,
html.ots-sidebar-collapsed .ots-main,
html.ots-sidebar-collapsed #content-wrapper {
margin-left: var(--ots-sidebar-collapsed-width) !important;
width: calc(100vw - var(--ots-sidebar-collapsed-width)) !important;
max-width: calc(100vw - var(--ots-sidebar-collapsed-width)) !important;
}
.ots-content {
flex: 1;
padding: 32px 16px 32px var(--ots-sidebar-content-gap);
overflow-y: auto;
overflow-x: hidden !important;
max-width: 100% !important;
box-sizing: border-box !important;
}
/* Consistent left gap between sidebar and page content */
.page-content {
padding-left: 0 !important;
max-width: 100% !important;
overflow-x: hidden !important;
box-sizing: border-box !important;
}
/* Remove bootstrap gutters for main content so it sits flush against sidebar */
.ots-main .page-content .row {
margin-left: 0 !important;
margin-right: 0 !important;
max-width: 100% !important;
overflow-x: hidden !important;
}
.ots-main .page-content [class*="col-"] {
padding-left: 0 !important;
padding-right: 0 !important;
}
.ots-main #content-wrapper {
padding-left: var(--ots-sidebar-content-gap) !important;
}
.ots-main .page-content {
padding-left: 0 !important;
}
.ots-main .ots-content {
padding-left: var(--ots-sidebar-content-gap) !important;
}
/* Strongly enforce no left gap for content children (not #content-wrapper itself) */
#content-wrapper .page-content,
#content-wrapper .page-content .row,
#content-wrapper .page-content [class*="col-"] {
margin-left: 0 !important;
padding-left: 0 !important;
}
/* Ensure page header and meta area align flush */
.page-header {
margin-left: 0 !important;
padding-left: 0 !important;
}
/* Prevent XiboGrid, folder grids, and data containers from causing page overflow */
.XiboGrid,
.grid-with-folders-container,
.XiboData,
#datatable-container {
max-width: 100% !important;
overflow-x: auto !important;
box-sizing: border-box !important;
}
/* ============================================================================
TOPBAR STRIP — HIDDEN
The old full-width topbar is no longer shown. The notification bell and
user menu now live in .ots-page-actions (fixed top-right on every page).
============================================================================ */
.row.header.header-side,
.ots-topbar-strip {
display: none !important;
height: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
border: none !important;
box-shadow: none !important;
}
/* ============================================================================
PAGE ACTIONS — top-right cluster (bell + user icon)
============================================================================ */
.ots-page-actions {
position: absolute;
top: 14px;
right: 20px;
z-index: 1100;
display: flex;
align-items: center;
gap: 2px;
background: var(--color-surface-elevated);
border: 1px solid var(--color-border);
border-radius: 8px;
padding: 3px 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.10);
}
/* Each action inside the cluster — NO position:relative so dropdowns
anchor to .ots-page-actions (position:fixed) instead */
.ots-page-actions .ots-topbar-action {
display: inline-flex !important;
align-items: center !important;
position: static !important;
}
.ots-page-actions .ots-topbar-action .nav-item,
.ots-page-actions .ots-topbar-action .dropdown,
.ots-page-actions .ots-topbar-action > div {
display: inline-flex !important;
align-items: center !important;
position: static !important;
}
.ots-page-actions .ots-topbar-action .nav-link {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
width: 28px !important;
height: 28px !important;
padding: 0 !important;
border-radius: 6px !important;
color: var(--color-text-secondary) !important;
transition: all 150ms ease !important;
border: none !important;
background: transparent !important;
}
.ots-page-actions .ots-topbar-action .nav-link:hover {
background-color: rgba(59, 130, 246, 0.08) !important;
color: var(--color-primary) !important;
}
.ots-page-actions .ots-topbar-action .ots-topbar-icon {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 18px !important;
height: 18px !important;
font-size: 16px !important;
}
.ots-page-actions .ots-topbar-action img.nav-avatar {
display: block !important;
width: 20px !important;
height: 20px !important;
border-radius: 50% !important;
object-fit: cover !important;
border: 1px solid transparent !important;
transition: border-color 150ms ease !important;
}
.ots-page-actions .ots-topbar-action .nav-link:hover img.nav-avatar {
border-color: var(--color-primary) !important;
}
/* Dropdown menus from the page actions cluster */
.ots-page-actions .dropdown-menu {
position: absolute !important;
top: 100% !important;
right: 0 !important;
left: auto !important;
margin-top: 0 !important;
min-width: 200px !important;
background-color: var(--color-surface-elevated) !important;
border: 1px solid var(--color-border) !important;
border-radius: 10px !important;
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25) !important;
padding: 6px 0 !important;
z-index: 3000 !important;
overflow: visible !important;
}
/* Bridge the gap between the pill and dropdown so it looks connected */
.ots-page-actions .dropdown-menu::before {
content: '' !important;
display: block !important;
position: absolute !important;
top: -4px !important;
right: 8px !important;
width: 48px !important;
height: 4px !important;
background: transparent !important;
}
.ots-page-actions .dropdown-item,
.ots-page-actions .dropdown-menu a {
display: flex !important;
align-items: center !important;
gap: 8px !important;
padding: 8px 14px !important;
margin: 1px 6px !important;
border-radius: 6px !important;
color: var(--color-text-secondary) !important;
font-size: 13px !important;
font-weight: 500 !important;
transition: all 150ms ease !important;
text-decoration: none !important;
}
.ots-page-actions .dropdown-item:hover,
.ots-page-actions .dropdown-menu a:hover {
background-color: rgba(59, 130, 246, 0.08) !important;
color: var(--color-primary) !important;
}
/* Light mode adjustments for the actions cluster */
body.ots-light-mode .ots-page-actions {
background: #ffffff;
border-color: #e2e8f0;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
/* ============================================================================
USER MENU — standalone styles that apply whether the menu is inside
.ots-page-actions or floated to <body> by floatMenu().
============================================================================ */
/* When the menu lives in <body> (permanently moved there by initDropdowns),
it's hidden by default and shown only via .ots-user-menu-open. */
.ots-user-menu.ots-user-menu-body {
position: fixed !important;
display: none !important;
z-index: 2147483647 !important;
transform: none !important;
pointer-events: auto !important;
}
.ots-user-menu.ots-user-menu-body.ots-user-menu-open {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
animation: otsUserMenuIn 120ms ease-out;
}
@keyframes otsUserMenuIn {
from { opacity: 0; transform: translateY(-6px); }
to { opacity: 1; transform: translateY(0); }
}
/* Visual style — applies regardless of where the element is in the DOM */
.ots-user-menu {
min-width: 200px !important;
background-color: var(--color-surface-elevated) !important;
border: 1px solid var(--color-border) !important;
border-radius: 10px !important;
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25) !important;
padding: 6px 0 !important;
overflow: visible !important;
}
.ots-user-menu .dropdown-header {
color: var(--color-text-primary) !important;
font-size: 13px !important;
font-weight: 600 !important;
padding: 8px 14px !important;
white-space: nowrap !important;
}
.ots-user-menu .dropdown-divider {
border-top: 1px solid var(--color-border) !important;
margin: 4px 0 !important;
}
.ots-user-menu .dropdown-item,
.ots-user-menu a {
display: flex !important;
align-items: center !important;
gap: 8px !important;
padding: 8px 14px !important;
margin: 1px 6px !important;
border-radius: 6px !important;
color: var(--color-text-secondary) !important;
font-size: 13px !important;
font-weight: 500 !important;
transition: all 150ms ease !important;
text-decoration: none !important;
}
.ots-user-menu .dropdown-item:hover,
.ots-user-menu a:hover {
background-color: rgba(59, 130, 246, 0.08) !important;
color: var(--color-primary) !important;
}
body.ots-light-mode .ots-user-menu {
background-color: #ffffff !important;
border-color: #e2e8f0 !important;
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.12) !important;
}
body.ots-light-mode .ots-user-menu .dropdown-item,
body.ots-light-mode .ots-user-menu a {
color: #334155 !important;
}
body.ots-light-mode .ots-user-menu .dropdown-item:hover,
body.ots-light-mode .ots-user-menu a:hover {
background-color: rgba(59, 130, 246, 0.1) !important;
color: #2563eb !important;
}
/* ============================================================================
HORIZONTAL NAV MODE — when .navbar.navbar-expand-lg is present there is no
sidebar, so #content-wrapper must not have the sidebar margin/width offsets.
The page background follows the current light/dark theme variables.
============================================================================ */
.navbar.navbar-expand-lg ~ #content-wrapper {
margin-left: 0 !important;
width: 100% !important;
max-width: 100% !important;
padding-left: 20px !important;
padding-right: 20px !important;
}
.navbar.navbar-expand-lg ~ #content-wrapper .page-content {
padding-left: 0 !important;
padding-right: 0 !important;
}
.navbar.navbar-expand-lg ~ #content-wrapper .page-content .row {
margin-left: 0 !important;
margin-right: 0 !important;
}
.navbar.navbar-expand-lg ~ #content-wrapper .page-content [class*="col-"] {
padding-left: 0 !important;
padding-right: 0 !important;
}
.navbar.navbar-expand-lg ~ #content-wrapper .page-content > .row > .col-sm-12 {
padding-left: 0 !important;
padding-right: 0 !important;
}
.navbar.navbar-expand-lg ~ #content-wrapper .page-header {
margin-left: 0 !important;
padding-left: 0 !important;
}
/* Ensure page background follows the theme when horizontal nav is active */
.navbar.navbar-expand-lg ~ #content-wrapper,
.navbar.navbar-expand-lg ~ #content-wrapper .page-content {
background-color: var(--color-background) !important;
color: var(--color-text-primary) !important;
}
/* Light-mode overrides for horizontal nav page area */
body.ots-light-mode .navbar.navbar-expand-lg ~ #content-wrapper,
body.ots-light-mode .navbar.navbar-expand-lg ~ #content-wrapper .page-content {
background-color: var(--color-background) !important;
color: var(--color-text-primary) !important;
}
/* Horizontal navbar should also follow the theme */
body.ots-light-mode .navbar.navbar-expand-lg {
background-color: var(--color-surface) !important;
border-color: var(--color-border) !important;
color: var(--color-text-primary) !important;
}
body.ots-light-mode .navbar.navbar-expand-lg .nav-link,
body.ots-light-mode .navbar.navbar-expand-lg .navbar-nav > li > a {
color: var(--color-text-secondary) !important;
}
body.ots-light-mode .navbar.navbar-expand-lg .nav-link:hover,
body.ots-light-mode .navbar.navbar-expand-lg .navbar-nav > li > a:hover {
color: var(--color-primary) !important;
}
.page-header {
background: transparent !important;
box-shadow: none !important;
}
.ots-footer {
border-top: 1px solid var(--color-border);
padding: 16px 32px;
background-color: var(--color-surface-elevated);
text-align: center;
color: var(--color-text-primary);
}
/* Responsive sidebar */
@media (max-width: 768px) {
.ots-sidebar {
transform: translateX(-100%);
transition: transform var(--transition-base);
width: 280px;
}
.ots-sidebar.active {
transform: translateX(0);
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.3);
}
.ots-main {
margin-left: 0 !important;
}
.ots-content {
color: var(--color-text-primary);
}
}
/* Responsive helpers for paged selects and other inline-width controls */
.pagedSelect {
min-width: 12.5rem; /* 200px */
}
@media (max-width: 600px) {
.pagedSelect {
min-width: auto;
width: 100%;
box-sizing: border-box;
}
}
/* ============================================================================
SIDEBAR STYLES
============================================================================ */
.sidebar-header {
padding: 12px 16px;
border-bottom: 1px solid var(--color-border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-shrink: 0;
height: var(--ots-sidebar-header-height);
}
.brand-link {
display: flex;
align-items: center;
gap: 12px;
color: var(--color-text-primary);
font-weight: 700;
font-size: 16px;
text-decoration: none;
flex: 1;
}
.brand-icon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
flex-shrink: 0;
}
.sidebar-content {
flex: 1;
padding: 8px 0;
overflow-y: auto;
min-height: 0;
}
.sidebar-nav {
list-style: none;
margin: 0;
padding: 8px 0 16px;
}
.sidebar-nav li {
display: block;
margin-top: 6px;
}
/* Compatibility: Xibo sidebar markup uses `sidebar-list`, `sidebar-main`, `sidebar-title`.
Map those into the modern `.nav-item/.nav-text/.nav-icon` style system so styles apply.
*/
.ots-sidebar li.sidebar-list > a,
.ots-sidebar li.sidebar-main > a,
.ots-sidebar li.sidebar-title > a {
display: flex;
align-items: center;
gap: 12px;
padding: 8px var(--ots-sidebar-item-padding-x);
color: var(--ots-sidebar-link);
text-decoration: none;
transition: all var(--transition-fast);
position: relative;
font-size: 14px;
font-weight: 500;
border-left: 2px solid transparent;
margin: 3px 0;
border-radius: var(--ots-sidebar-item-radius);
min-height: var(--ots-sidebar-item-height);
line-height: 1.25;
width: 100%;
box-sizing: border-box;
padding-right: 48px; /* reserve space for caret */
text-indent: 0;
float: none;
}
/* Force readable text in sidebar links */
.ots-sidebar a,
.ots-sidebar .ots-nav-text {
color: var(--ots-sidebar-link);
}
.ots-sidebar li.sidebar-list > a:hover {
color: var(--ots-sidebar-link-hover-text);
background-color: var(--ots-sidebar-link-hover-bg);
}
.ots-sidebar li.sidebar-list.active > a,
.ots-sidebar li.sidebar-list > a.active,
.ots-sidebar li.sidebar-main.active > a,
.ots-sidebar li.sidebar-main > a.active {
color: var(--ots-sidebar-active-text);
background-color: var(--ots-sidebar-active-bg);
border-left-color: transparent;
font-weight: 600;
box-shadow: var(--ots-sidebar-active-shadow);
}
.ots-sidebar li.sidebar-list.active > a .ots-nav-text,
.ots-sidebar li.sidebar-list > a.active .ots-nav-text,
.ots-sidebar li.sidebar-main.active > a .ots-nav-text,
.ots-sidebar li.sidebar-main > a.active .ots-nav-text {
color: var(--ots-sidebar-active-text);
}
/* Stronger active state rules to ensure the currently active page is visibly
highlighted regardless of other theme CSS. Covers both `li.active > a` and
`a.active` patterns as well as collapsed sidebar appearance. */
.ots-sidebar li.sidebar-list.active > a,
.ots-sidebar li.sidebar-list > a.active,
#sidebar-wrapper .sidebar-list a.active,
.ots-sidebar li.sidebar-main.active > a,
.ots-sidebar li.sidebar-main > a.active,
.ots-sidebar .sidebar-list > a[aria-current="page"] {
background-color: var(--ots-sidebar-active-bg) !important;
color: var(--ots-sidebar-active-text) !important;
border-left-color: transparent !important;
font-weight: 600 !important;
box-shadow: var(--ots-sidebar-active-shadow) !important;
}
/* Ensure the icon in the active link also uses active text color */
.ots-sidebar li.sidebar-list.active > a .ots-nav-icon,
.ots-sidebar li.sidebar-list > a.active .ots-nav-icon,
#sidebar-wrapper .sidebar-list a.active .ots-nav-icon {
color: var(--ots-sidebar-active-text) !important;
}
/* Collapsed sidebar: active item highlight */
.ots-sidebar.collapsed .sidebar-list > a.active,
.ots-sidebar.collapsed .sidebar-group-toggle.active {
background: var(--ots-sidebar-active-bg) !important;
color: var(--ots-sidebar-active-text) !important;
}
.ots-sidebar.collapsed .sidebar-list > a.active .ots-nav-icon,
.ots-sidebar.collapsed .sidebar-group-toggle.active .ots-nav-icon {
color: var(--ots-sidebar-active-text) !important;
}
.ots-sidebar .ots-nav-icon {
width: 28px;
height: 28px;
display: flex !important;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 16px;
color: currentColor;
margin: 0;
text-align: center;
line-height: 1;
}
.ots-sidebar .ots-nav-text {
font-size: 14px;
font-weight: 500;
flex: 1;
line-height: 1.2;
}
.sidebar-group-toggle .ots-nav-icon,
.ots-sidebar-nav .ots-nav-icon {
justify-self: start;
}
.ots-sidebar li.sidebar-title > a {
display: block;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
color: var(--ots-sidebar-muted-text);
letter-spacing: 0.12em;
padding: 12px 14px 4px;
margin: 8px 0 0;
min-height: auto;
line-height: 1;
}
.brand-logo {
width: 40px;
height: 40px;
object-fit: contain;
}
.brand-text {
color: var(--color-text-primary);
font-size: 18px;
font-weight: 600;
letter-spacing: 0.02em;
}
.sidebar-header {
padding: 12px 16px;
border-bottom: 1px solid var(--ots-sidebar-border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-shrink: 0;
height: var(--ots-sidebar-header-height);
box-sizing: border-box;
position: relative;
background: var(--ots-sidebar-header-bg);
z-index: 1;
}
.sidebar-collapse-btn {
width: 32px;
height: 32px;
border-radius: 8px;
border: 0;
background: var(--ots-sidebar-button-bg);
color: var(--ots-sidebar-button-text);
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all var(--transition-fast);
}
.sidebar-collapse-btn:hover {
background: var(--ots-sidebar-button-bg-hover);
color: var(--ots-sidebar-link-hover-text);
}
/* Expand button - visible only when collapsed */
.sidebar-expand-btn {
width: 32px;
height: 32px;
border-radius: 8px;
border: 0;
background: var(--ots-sidebar-button-bg);
color: var(--ots-sidebar-button-text);
display: none;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all var(--transition-fast);
}
.sidebar-expand-btn:hover {
background: var(--ots-sidebar-button-bg-hover);
color: var(--ots-sidebar-link-hover-text);
}
.ots-sidebar.collapsed .sidebar-expand-btn {
display: inline-flex !important;
}
.ots-sidebar.collapsed .sidebar-collapse-btn-visible {
display: none !important;
}
.ots-sidebar.collapsed {
width: var(--ots-sidebar-collapsed-width) !important;
overflow: visible !important; /* allow popout menus to escape */
}
/* When collapsed the sidebar-content must also allow flyout menus to escape */
.ots-sidebar.collapsed .sidebar-content {
overflow: visible !important;
}
/* Ensure parent wrapper doesn't clip flyout menus and doesn't create a visible bar.
The sidebar is position:fixed so this wrapper should be invisible in the flow.
Using display:contents so the sidebar inside still renders but the wrapper
itself produces no box at all — eliminating the black bar. */
.navbar-collapse-side,
.navbar-collapse-side.collapse,
#navbar-collapse-1 {
display: contents !important;
overflow: visible !important;
width: 0 !important;
min-width: 0 !important;
max-width: 0 !important;
height: 0 !important;
max-height: 0 !important;
padding: 0 !important;
margin: 0 !important;
border: none !important;
background: transparent !important;
box-shadow: none !important;
outline: none !important;
}
.ots-sidebar.collapsed .brand-text,
.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group > .sidebar-group-toggle > .ots-nav-text,
.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list > a > .ots-nav-text,
.ots-sidebar.collapsed .sidebar-group-caret,
.ots-sidebar.collapsed .user-details,
.ots-sidebar.collapsed .sidebar-header .sidebar-collapse-btn,
.ots-sidebar.collapsed .brand-link .brand-text {
display: none !important;
}
/* ── Collapsed sidebar: flyout submenu on hover ──────────────────────────
When collapsed, submenus are hidden by default and shown as floating
panels anchored to the right of the sidebar icon on hover.
We deliberately do NOT use display:none here — the JS toggle also sets
inline display, so we use visibility + opacity + pointer-events to hide
the panel and then override on :hover. This avoids the inline
display:none set by JS from blocking the CSS :hover rule.
─────────────────────────────────────────────────────────────────────── */
.ots-sidebar.collapsed .sidebar-submenu {
/* Positioning */
position: absolute !important;
left: 100% !important;
top: 0 !important;
margin-left: 4px !important;
z-index: 10000 !important;
/* Sizing */
min-width: 220px !important;
width: max-content !important;
max-height: 80vh !important;
overflow-y: auto !important;
/* Hidden by default (visibility so :hover can override inline display) */
visibility: hidden !important;
opacity: 0 !important;
pointer-events: none !important;
/* Appearance */
background: var(--color-surface-elevated, #334155) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 8px !important;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35) !important;
padding: 0 0 8px 0 !important;
list-style: none !important;
transition: opacity 0.15s ease, visibility 0.15s ease !important;
}
/* Flyout: show submenu on hover — uses visibility/opacity so it works
even when JS has set an inline display:none or display:block */
.ots-sidebar.collapsed .sidebar-group:hover > .sidebar-submenu,
.ots-sidebar.collapsed .sidebar-group.flyout-open > .sidebar-submenu {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
pointer-events: auto !important;
}
/* ── Flyout header (category icon + name) ──────────────────────────── */
.flyout-header {
display: none; /* hidden in expanded sidebar */
}
.ots-sidebar.collapsed .sidebar-submenu .flyout-header {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
gap: 10px !important;
padding: 12px 16px !important;
margin: 0 !important;
border-bottom: none !important;
background: var(--color-primary, #3b82f6) !important;
pointer-events: none !important;
user-select: none !important;
white-space: nowrap !important;
list-style: none !important;
border-radius: 8px 8px 0 0 !important;
width: 100% !important;
box-sizing: border-box !important;
}
.ots-sidebar.collapsed .sidebar-submenu .flyout-header-icon {
display: inline-flex !important;
visibility: visible !important;
align-items: center !important;
justify-content: center !important;
width: 22px !important;
height: 22px !important;
font-size: 16px !important;
color: #ffffff !important;
opacity: 1 !important;
flex-shrink: 0 !important;
order: -1 !important;
}
.ots-sidebar.collapsed .sidebar-submenu .flyout-header-text {
display: inline !important;
visibility: visible !important;
font-size: 14px !important;
font-weight: 700 !important;
text-transform: none !important;
letter-spacing: 0.01em !important;
color: #ffffff !important;
opacity: 1 !important;
width: auto !important;
overflow: visible !important;
}
/* Light mode flyout header — keep the same primary banner */
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .flyout-header {
background: var(--color-primary, #3b82f6) !important;
border-bottom: none !important;
}
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .flyout-header-icon {
color: #ffffff !important;
}
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .flyout-header-text {
color: #ffffff !important;
}
/* Flyout submenu <li> — full width, no centering */
.ots-sidebar.collapsed .sidebar-submenu .sidebar-list {
display: block !important;
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
}
/* Flyout submenu items — stretch to fill the popup width */
.ots-sidebar.collapsed .sidebar-submenu .sidebar-list > a {
display: flex !important;
align-items: center !important;
justify-content: flex-start !important;
gap: 10px !important;
padding: 8px 16px !important;
margin: 2px 6px !important;
height: auto !important;
width: calc(100% - 12px) !important;
background: transparent !important;
color: var(--color-text-secondary, #f1f5f9) !important;
border-radius: 6px !important;
font-size: 13px !important;
white-space: nowrap !important;
border: none !important;
border-left: none !important;
text-decoration: none !important;
box-sizing: border-box !important;
}
.ots-sidebar.collapsed .sidebar-submenu .sidebar-list > a:hover {
background: rgba(59, 130, 246, 0.15) !important;
color: #ffffff !important;
}
/* Show text labels inside flyout submenu — high specificity to override
the global .ots-sidebar.collapsed .ots-nav-text { display:none } */
.ots-sidebar.collapsed .sidebar-submenu .sidebar-list .ots-nav-text,
.ots-sidebar.collapsed .sidebar-submenu .sidebar-list > a .ots-nav-text,
.ots-sidebar.collapsed .sidebar-submenu .ots-nav-text {
display: inline !important;
visibility: visible !important;
width: auto !important;
overflow: visible !important;
color: inherit !important;
font-size: 13px !important;
font-weight: 500 !important;
}
/* Show icons inside flyout submenu — high specificity to override
collapsed icon sizing/color that makes them 20px sidebar icons */
.ots-sidebar.collapsed .sidebar-submenu .sidebar-list .ots-nav-icon,
.ots-sidebar.collapsed .sidebar-submenu .sidebar-list > a .ots-nav-icon,
.ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon {
display: inline-flex !important;
visibility: visible !important;
width: 18px !important;
height: 18px !important;
font-size: 14px !important;
flex-shrink: 0 !important;
color: inherit !important;
margin: 0 !important;
align-items: center !important;
justify-content: center !important;
}
/* Make sidebar-group position relative so flyout anchors correctly */
.ots-sidebar.collapsed .sidebar-group {
position: relative !important;
}
/* Add a bridge element so the mouse can travel from the icon to the flyout
without losing :hover (covers the 4px gap + some tolerance) */
.ots-sidebar.collapsed .sidebar-group-toggle::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
right: -12px !important;
width: 12px !important;
height: 100% !important;
background: transparent !important;
display: block !important;
pointer-events: auto !important;
z-index: 9999 !important;
}
/* Also show a label tooltip on hover for top-level items */
.ots-sidebar.collapsed .sidebar-group-toggle::after {
content: attr(data-group);
position: absolute;
left: 100%;
top: 50%;
transform: translateY(-50%);
background: var(--color-surface-elevated, #334155);
color: var(--color-text-primary, #fff);
padding: 4px 12px;
border-radius: 6px;
font-size: 13px;
font-weight: 500;
white-space: nowrap;
margin-left: 8px;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
z-index: 9999;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
.ots-sidebar.collapsed .sidebar-group:hover > .sidebar-group-toggle::after {
display: none; /* hide tooltip when submenu flyout is showing instead */
}
/* Single items (Dashboard etc) - show tooltip on hover */
.ots-sidebar.collapsed > .sidebar-content .sidebar-nav > .sidebar-list > a {
position: relative !important;
}
.ots-sidebar.collapsed > .sidebar-content .sidebar-nav > .sidebar-list > a::after {
content: attr(data-tooltip);
position: absolute;
left: 100%;
top: 50%;
transform: translateY(-50%);
background: var(--color-surface-elevated, #334155);
color: var(--color-text-primary, #fff);
padding: 4px 12px;
border-radius: 6px;
font-size: 13px;
font-weight: 500;
white-space: nowrap;
margin-left: 8px;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
z-index: 9999;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
.ots-sidebar.collapsed > .sidebar-content .sidebar-nav > .sidebar-list:hover > a::after {
opacity: 1;
}
.ots-sidebar.collapsed .sidebar-header {
height: auto;
padding: 8px;
justify-content: center;
flex-direction: column;
gap: 8px;
}
.ots-sidebar.collapsed .brand-icon {
flex-shrink: 0;
}
/* ── Collapsed sidebar: reset base Xibo styles and center icons ───────── */
/* The <ul> nav list */
.ots-sidebar.collapsed ul.sidebar,
.ots-sidebar.collapsed .ots-sidebar-nav,
#sidebar-wrapper.collapsed ul.sidebar {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
width: 100% !important;
padding: 4px 0 8px !important;
margin: 0 !important;
list-style: none !important;
text-indent: 0 !important;
position: static !important;
float: none !important;
overflow: visible !important;
}
/* Each top-level <li> (exclude items inside flyout submenus) */
.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list,
.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group,
#sidebar-wrapper.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list,
#sidebar-wrapper.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group {
display: flex !important;
justify-content: center !important;
width: 100% !important;
height: auto !important;
margin: 0 !important;
padding: 0 !important;
text-indent: 0 !important;
float: none !important;
}
/* Each top-level <a> link / group-toggle — the 44×44 icon button
Scoped to direct children so flyout submenu items are not affected.
Uses display:grid + place-items:center for the most robust centering. */
.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group > .sidebar-group-toggle,
.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list > a,
#sidebar-wrapper.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group > .sidebar-group-toggle,
#sidebar-wrapper.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list > a {
display: grid !important;
place-items: center !important;
grid-template-columns: 1fr !important;
grid-template-rows: 1fr !important;
width: 40px !important;
height: 40px !important;
min-width: 40px !important;
max-width: 40px !important;
min-height: 40px !important;
max-height: 40px !important;
margin: 2px auto !important;
padding: 0 !important;
padding-left: 0 !important;
padding-right: 0 !important;
background: var(--ots-sidebar-collapsed-item-bg) !important;
color: var(--ots-sidebar-link) !important;
border-radius: 10px !important;
border: 0 !important;
border-left: 0 !important;
border-right: 0 !important;
cursor: pointer !important;
box-sizing: border-box !important;
position: relative !important;
text-indent: 0 !important;
text-decoration: none !important;
float: none !important;
line-height: normal !important;
gap: 0 !important;
column-gap: 0 !important;
row-gap: 0 !important;
}
/* When collapsed, hide nav text labels on the main sidebar (not inside flyout submenus) */
.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list > a > .ots-nav-text,
.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group > .sidebar-group-toggle > .ots-nav-text,
.ots-sidebar.collapsed .brand-text,
.ots-sidebar.collapsed .user-details {
display: none !important;
visibility: hidden !important;
width: 0 !important;
overflow: hidden !important;
}
.ots-sidebar.collapsed .sidebar-group-toggle:hover,
.ots-sidebar.collapsed .sidebar-list > a:hover {
background: var(--ots-sidebar-collapsed-item-hover-bg) !important;
}
/* Hide caret when collapsed */
.ots-sidebar.collapsed .sidebar-group-caret {
display: none !important;
}
/* The icon <span> — flexbox to center the FA glyph (::before pseudo-element).
The parent <a> uses display:grid + place-items:center, which centers THIS span.
THIS span uses display:flex to center the ::before glyph inside itself. */
#sidebar-wrapper.ots-sidebar.collapsed .ots-nav-icon,
#navbar-collapse-1 .ots-sidebar.collapsed .ots-nav-icon,
.ots-sidebar.collapsed .ots-nav-icon {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 20px !important;
height: 20px !important;
font-size: 20px !important;
color: var(--ots-sidebar-link) !important;
line-height: 1 !important;
margin: 0 !important;
padding: 0 !important;
text-indent: 0 !important;
text-align: center !important;
float: none !important;
flex-shrink: 0 !important;
opacity: 1 !important;
}
/* Stronger collapsed-state icon overrides */
.ots-sidebar.collapsed .ots-nav-icon,
.ots-sidebar.collapsed .ots-nav-icon i,
.ots-sidebar.collapsed .ots-nav-icon svg,
.ots-sidebar.collapsed .btn-icon {
color: var(--ots-sidebar-link) !important;
fill: currentColor !important;
stroke: currentColor !important;
opacity: 1 !important;
}
/* Force-fill any SVG child shapes (paths, g) to currentColor so embedded fills are overridden */
.ots-sidebar.collapsed .ots-nav-icon svg *,
.ots-sidebar.collapsed .ots-nav-icon svg path,
.ots-sidebar.collapsed .ots-nav-icon svg g {
fill: currentColor !important;
stroke: currentColor !important;
opacity: 1 !important;
}
/* Remove potential dimming filters */
.ots-sidebar.collapsed .ots-nav-icon svg,
.ots-sidebar.collapsed .ots-nav-icon i {
filter: none !important;
}
/* Very strong override: force collapsed icons to a bright foreground in dark mode,
and to a dark foreground in light mode. This is intentionally specific to
override icon fills coming from embedded SVGs, fonts, or background images. */
:root .ots-sidebar.collapsed .sidebar-list > a .ots-nav-icon,
:root .ots-sidebar.collapsed .sidebar-group-toggle .ots-nav-icon,
:root .ots-sidebar.collapsed .ots-nav-icon,
:root .ots-sidebar.collapsed .ots-nav-icon * {
color: #ffffff !important;
fill: #ffffff !important;
stroke: #ffffff !important;
opacity: 1 !important;
filter: none !important;
}
/* Light mode: force dark icons */
body.ots-light-mode .ots-sidebar.collapsed .sidebar-list > a .ots-nav-icon,
body.ots-light-mode .ots-sidebar.collapsed .sidebar-group-toggle .ots-nav-icon,
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon,
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon * {
color: #0b1221 !important;
fill: #0b1221 !important;
stroke: #0b1221 !important;
opacity: 1 !important;
filter: none !important;
}
/* Target Font Awesome pseudo-element glyphs (fa, fa-*) which render via ::before */
:root .ots-sidebar.collapsed .ots-nav-icon::before,
:root .ots-sidebar.collapsed .ots-nav-icon.fa::before,
:root .ots-sidebar.collapsed .fa::before,
:root .ots-sidebar.collapsed .ots-nav-icon .fa::before {
color: #ffffff !important;
opacity: 1 !important;
text-shadow: none !important;
}
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon::before,
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon.fa::before,
body.ots-light-mode .ots-sidebar.collapsed .fa::before,
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon .fa::before {
color: #0b1221 !important;
opacity: 1 !important;
text-shadow: none !important;
}
/* Inside flyout submenus, icons should inherit the link color, not the
forced white/dark used for the main sidebar icon buttons */
:root .ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon,
:root .ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon *,
:root .ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon::before,
:root .ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon.fa::before,
:root .ots-sidebar.collapsed .sidebar-submenu .fa::before {
color: currentColor !important;
fill: currentColor !important;
stroke: currentColor !important;
}
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon,
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon *,
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon::before,
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .ots-nav-icon.fa::before,
body.ots-light-mode .ots-sidebar.collapsed .sidebar-submenu .fa::before {
color: currentColor !important;
fill: currentColor !important;
stroke: currentColor !important;
}
/* Center Font Awesome pseudo-elements inside icon containers */
.ots-sidebar .ots-nav-icon::before,
.ots-sidebar .ots-nav-icon.fa::before,
.ots-sidebar .fa::before {
display: inline-block !important;
line-height: 1 !important;
}
/* Explicitly center Font Awesome icons in collapsed state */
.ots-sidebar.collapsed .ots-nav-icon::before,
.ots-sidebar.collapsed .ots-nav-icon.fa::before {
display: inline-block !important;
line-height: 1 !important;
text-align: center !important;
}
/* Ensure icon glyphs (font icons and svgs) follow the sidebar link color
and adapt to light/dark mode. Use currentColor for SVG fill/stroke. */
.ots-sidebar .ots-nav-icon,
.ots-sidebar.collapsed .ots-nav-icon,
.ots-sidebar .ots-nav-icon i,
.ots-sidebar .ots-nav-icon svg {
color: var(--ots-sidebar-link) !important;
}
.ots-sidebar .ots-nav-icon svg {
fill: currentColor !important;
stroke: currentColor !important;
}
/* Explicitly handle light-mode variant (redundant but higher specificity) */
body.ots-light-mode .ots-sidebar .ots-nav-icon,
body.ots-light-mode .ots-sidebar.collapsed .ots-nav-icon {
color: var(--ots-sidebar-link) !important;
}
/* Show expand button when collapsed, hide collapse button */
.ots-sidebar.collapsed .sidebar-expand-btn {
display: inline-flex !important;
}
.ots-sidebar.collapsed .sidebar-collapse-btn-visible {
display: none !important;
}
body.ots-sidebar-collapsed #content-wrapper,
body.ots-sidebar-collapsed .ots-main,
html.ots-sidebar-collapsed #content-wrapper,
html.ots-sidebar-collapsed .ots-main {
margin-left: var(--ots-sidebar-collapsed-width) !important;
transition: margin-left 200ms ease;
}
.ots-sidebar-nav {
padding: 8px 0 16px;
}
/* Collapsed nav padding — header is a separate flex sibling so only a small gap is needed */
.ots-sidebar.collapsed .ots-sidebar-nav,
body.ots-sidebar-collapsed .ots-sidebar-nav {
padding-top: 4px !important;
padding-bottom: 8px !important;
}
.ots-sidebar:not(.collapsed) .ots-sidebar-nav {
padding-top: 8px !important;
}
.sidebar-group {
margin-top: 6px;
}
/* Collapsed state: tighter vertical spacing between groups */
.ots-sidebar.collapsed .sidebar-group {
margin-top: 0 !important;
}
/* Center nav icons inside their item containers (expanded state only) */
.ots-sidebar:not(.collapsed) .sidebar-list > a,
.ots-sidebar:not(.collapsed) .sidebar-group-toggle {
align-items: center !important;
}
.ots-sidebar:not(.collapsed) .ots-nav-icon {
margin: 0 !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
}
.sidebar-group-toggle {
display: flex;
align-items: center;
gap: 12px;
padding: 8px var(--ots-sidebar-item-padding-x);
margin: 6px 0;
border-radius: var(--ots-sidebar-item-radius);
color: var(--ots-sidebar-link);
text-decoration: none;
background: var(--ots-sidebar-group-bg);
transition: all var(--transition-fast);
position: relative; /* for absolutely positioned caret */
width: 100%;
box-sizing: border-box;
padding-right: 48px; /* reserve space for caret */
}
/* Highlight parent item like screenshot */
.ots-sidebar .sidebar-group.is-open > .sidebar-group-toggle,
.ots-sidebar .sidebar-group-toggle[aria-expanded="true"],
.ots-sidebar .sidebar-group-toggle.active {
background: var(--ots-sidebar-active-bg);
color: var(--ots-sidebar-active-text) !important;
box-shadow: var(--ots-sidebar-active-shadow);
}
.ots-sidebar .sidebar-group.is-open > .sidebar-group-toggle .ots-nav-text,
.ots-sidebar .sidebar-group.is-open > .sidebar-group-toggle .ots-nav-icon,
.ots-sidebar .sidebar-group.is-open > .sidebar-group-toggle .sidebar-group-caret,
.ots-sidebar .sidebar-group-toggle[aria-expanded="true"] .ots-nav-text,
.ots-sidebar .sidebar-group-toggle[aria-expanded="true"] .ots-nav-icon,
.ots-sidebar .sidebar-group-toggle[aria-expanded="true"] .sidebar-group-caret,
.ots-sidebar .sidebar-group-toggle.active .ots-nav-text,
.ots-sidebar .sidebar-group-toggle.active .ots-nav-icon,
.ots-sidebar .sidebar-group-toggle.active .sidebar-group-caret {
color: var(--ots-sidebar-active-text) !important;
}
.sidebar-group-toggle:hover {
background: var(--ots-sidebar-group-hover-bg);
color: var(--ots-sidebar-link-hover-text);
}
.sidebar-group-caret {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
font-size: 12px;
opacity: 0.95;
cursor: pointer;
pointer-events: auto;
display: inline-flex; /* ensure visible whether open or closed */
align-items: center;
justify-content: center;
color: var(--ots-sidebar-link); /* default visible color */
}
.sidebar-submenu {
list-style: none;
margin: 4px 0 8px;
padding: 0 0 0 12px;
border-left: 1px solid var(--ots-sidebar-border);
display: none;
}
/* When expanded, submenus are toggled by click (JS), not hover */
/* When collapsed, flyout rules are defined above in the
"Collapsed sidebar: flyout submenu on hover" section. */
.sidebar-group.is-open .sidebar-group-caret {
transform: rotate(180deg);
}
.sidebar-group.is-open .sidebar-submenu,
.sidebar-group-toggle[aria-expanded="true"] ~ .sidebar-submenu,
.sidebar-group-toggle[aria-expanded="true"] + .sidebar-submenu {
display: block !important;
}
.sidebar-submenu .sidebar-list > a {
margin: 4px 0;
background: var(--ots-sidebar-submenu-bg);
width: 100%;
box-sizing: border-box;
padding-right: 48px; /* keep caret space for nested items */
/* Slight indent for submenu items */
padding-left: 28px !important;
border-left: 4px solid var(--ots-sidebar-submenu-border);
border-radius: var(--ots-sidebar-item-radius);
color: var(--ots-sidebar-link);
font-weight: 500;
}
.sidebar-submenu .sidebar-list > a:hover {
background: var(--ots-sidebar-submenu-hover-bg);
color: var(--ots-sidebar-link-hover-text);
}
/* Ensure parent toggles and top-level links span full sidebar width (expanded only) */
.ots-sidebar:not(.collapsed) .sidebar-group-toggle,
.ots-sidebar:not(.collapsed) li.sidebar-list > a,
.ots-sidebar:not(.collapsed) li.sidebar-main > a {
width: 100% !important;
box-sizing: border-box !important;
}
.sidebar-submenu .sidebar-list > a:hover {
background: var(--ots-sidebar-submenu-hover-bg);
}
.sidebar-submenu .sidebar-list.active > a,
.sidebar-submenu .sidebar-list > a.active {
color: var(--ots-sidebar-active-text);
background-color: var(--ots-sidebar-active-bg);
box-shadow: var(--ots-sidebar-active-shadow);
border-left-color: var(--color-primary);
font-weight: 600;
}
/* sidebar-footer removed; account bar intentionally omitted */
.nav-section-divider {
padding: 12px 16px 8px;
margin-top: 8px;
border-top: 1px solid var(--color-border);
}
.nav-label {
display: block;
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
color: var(--color-text-tertiary);
letter-spacing: 0.08em;
padding: 12px 16px 8px;
margin-top: 8px;
}
.nav-item {
display: flex;
align-items: center;
gap: 14px;
padding: 12px 16px;
color: var(--color-text-primary);
text-decoration: none;
transition: all var(--transition-fast);
position: relative;
font-size: 14px;
font-weight: 500;
border-left: 2px solid transparent;
margin: 0 4px;
border-radius: 6px;
}
.nav-item:hover {
color: var(--color-text-primary);
background-color: rgba(59, 130, 246, 0.1);
border-left-color: transparent;
}
.nav-item.active {
color: var(--color-primary);
background-color: rgba(59, 130, 246, 0.12);
border-left-color: var(--color-primary);
font-weight: 600;
}
.nav-item.active::after {
content: '';
position: absolute;
right: 8px;
width: 8px;
height: 8px;
background-color: var(--color-primary);
border-radius: 50%;
}
.nav-icon {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 18px;
}
.nav-text {
font-size: 14px;
font-weight: 500;
flex: 1;
}
.sidebar-footer {
border-top: 1px solid var(--color-border);
padding: 16px;
background-color: rgba(59, 130, 246, 0.05);
flex-shrink: 0;
}
.sidebar-user {
display: flex;
align-items: center;
gap: 12px;
}
.user-avatar-lg {
width: 40px;
height: 40px;
border-radius: 50%;
background: linear-gradient(135deg, #3b82f6, #7c3aed);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 16px;
flex-shrink: 0;
}
.user-details {
min-width: 0;
}
.user-name {
font-size: 14px;
font-weight: 600;
color: var(--color-text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.user-role {
color: var(--color-text-secondary);
white-space: nowrap;
}
/* ============================================================================
TOPBAR STYLES - CLEAN MODERN SINGLE LINE MENU BAR
============================================================================
Design decisions:
- 56px total height — compact, modern feel
- All interactive elements are 36px (buttons, avatar, icons)
- Consistent 4px gap between nav items
- Clean border-bottom separator, no heavy shadows
- Proper z-index layering for dropdowns
============================================================================ */
.ots-topbar {
background-color: transparent;
padding: 0;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 4px;
height: 67px;
z-index: 1000;
position: relative;
flex: 1;
min-width: 0;
}
body.ots-sidebar-open .ots-topbar {
background-color: transparent !important;
box-shadow: none !important;
}
/* Topbar nav container - override .navbar-nav defaults */
.ots-topbar.navbar-nav {
background: transparent !important;
border: 0 !important;
padding: 0 !important;
margin: 0 !important;
gap: 2px;
height: 100%;
align-items: center;
flex-wrap: nowrap;
}
.ots-topbar .nav-item {
display: flex;
align-items: center;
height: 100%;
margin: 0 !important;
padding: 0 !important;
}
.ots-topbar .nav-link {
display: inline-flex;
align-items: center;
height: 36px;
gap: 6px;
padding: 0 10px;
border-radius: 6px;
color: var(--color-text-secondary);
font-weight: 500;
font-size: 13px;
white-space: nowrap;
transition: all 150ms ease;
position: relative;
border: 0 !important;
background: transparent !important;
box-shadow: none !important;
}
.ots-topbar .nav-link:hover {
background-color: rgba(59, 130, 246, 0.06);
color: var(--color-primary);
}
/* Ensure dropdowns, popovers and modals appear above the sticky topbar */
.dropdown,
.dropdown-menu,
.popover,
.modal {
z-index: 1201 !important;
}
/* Modal backdrop should sit behind the modal but above other content */
.modal-backdrop {
z-index: 1200 !important;
}
.ots-topbar .nav-item.open .nav-link,
.ots-topbar .nav-item.active .nav-link {
background-color: rgba(59, 130, 246, 0.1);
color: var(--color-primary);
font-weight: 600;
}
.ots-topbar .dropdown-toggle::after {
content: '';
display: inline-block;
margin-left: 4px;
width: 0;
height: 0;
border-left: 3.5px solid transparent;
border-right: 3.5px solid transparent;
border-top: 3.5px solid currentColor;
opacity: 0.5;
transition: transform 150ms ease;
}
.ots-topbar .nav-item.open .dropdown-toggle::after {
transform: rotate(180deg);
}
.ots-topbar .dropdown-menu {
border-radius: 10px;
padding: 6px 0;
margin-top: 4px;
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
border: 1px solid var(--color-border) !important;
background-color: var(--color-surface-elevated);
min-width: 180px;
z-index: 3000;
}
.ots-topbar .dropdown-item,
.ots-topbar .dropdown-menu a {
display: flex;
align-items: center;
gap: 8px;
border-radius: 6px;
padding: 8px 12px;
color: var(--color-text-secondary);
font-size: 13px;
font-weight: 500;
margin: 1px 6px;
transition: all 150ms ease;
}
.ots-topbar .dropdown-item:hover,
.ots-topbar .dropdown-menu a:hover {
background-color: rgba(59, 130, 246, 0.08);
color: var(--color-primary);
}
/* Icon sizing for topbar and nav */
.ots-topbar-icon {
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
opacity: 0.85;
flex-shrink: 0;
}
.ots-topbar .dropdown-menu .ots-topbar-icon {
font-size: 12px;
}
/* Left section: toggle, title, nav */
.topbar-left {
display: flex;
align-items: center;
gap: 16px;
flex: 1;
min-width: 0;
}
.topbar-toggle {
display: none;
width: 36px;
height: 36px;
padding: 0;
border: none;
background-color: transparent;
color: var(--color-text-primary);
cursor: pointer;
border-radius: 6px;
transition: all var(--transition-fast);
flex-shrink: 0;
}
.topbar-toggle:hover {
background-color: rgba(59, 130, 246, 0.1);
}
.topbar-toggle:active {
background-color: rgba(59, 130, 246, 0.15);
}
.topbar-toggle .icon {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
/* Title section with proper vertical centering */
.topbar-title {
display: flex;
flex-direction: column;
justify-content: center;
gap: 0;
min-width: 0;
}
.topbar-title h1 {
margin: 0;
padding: 0;
font-size: 18px;
font-weight: 700;
color: var(--color-text-primary);
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.topbar-title p {
margin: 0;
padding: 0;
font-size: 12px;
color: var(--color-text-tertiary);
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Right section: search, actions */
.topbar-right {
display: flex;
align-items: center;
gap: 12px;
flex-shrink: 0;
}
/* Search box - 36px height to match button grid */
.topbar-search {
position: relative;
height: 36px;
width: 240px;
display: flex;
align-items: center;
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 0 12px;
gap: 8px;
transition: all var(--transition-fast);
}
.topbar-search:focus-within {
border-color: var(--color-primary);
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
}
.topbar-search .search-icon {
color: var(--color-text-tertiary);
flex-shrink: 0;
font-size: 16px;
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
}
.topbar-search .search-input {
flex: 1;
background: none;
border: none;
color: var(--color-text-primary);
font-size: 14px;
outline: none;
padding: 0;
height: 100%;
min-width: 120px;
}
.topbar-search .search-input::placeholder {
color: var(--color-text-tertiary);
}
/* Action buttons container */
.topbar-actions {
display: flex;
align-items: center;
gap: 4px;
}
/* Consistent 36px button sizing */
.topbar-btn {
width: 36px;
height: 36px;
min-width: 36px;
min-height: 36px;
padding: 0;
border: none;
background-color: transparent;
color: var(--color-text-secondary);
cursor: pointer;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
transition: all var(--transition-fast);
position: relative;
}
.topbar-btn:hover {
background-color: rgba(59, 130, 246, 0.08);
color: var(--color-primary);
}
.topbar-btn:active {
background-color: rgba(59, 130, 246, 0.12);
}
.topbar-btn .icon {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
.user-btn {
padding: 2px;
}
.avatar {
width: 36px;
height: 36px;
border-radius: 50%;
background: linear-gradient(135deg, #3b82f6, #7c3aed);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 14px;
}
.avatar-sm {
width: 32px;
height: 32px;
font-size: 13px;
}
.dropdown {
position: relative;
}
.dropdown-menu,
.dropdown-right {
position: absolute;
top: 100%;
right: 0;
margin-top: 8px;
background-color: var(--color-surface-elevated);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 8px;
box-shadow: 0 20px 45px rgba(0, 0, 0, 0.3);
list-style: none;
padding: 8px 0;
min-width: 180px;
display: none;
z-index: 1001;
overflow: hidden;
}
/* Make DataTables button collections compatible with OTS dropdown styling */
.dt-buttons {
position: relative;
display: inline-block;
}
.dataTables_buttons,
.dataTables_buttons * {
background: transparent !important;
color: var(--color-text-primary) !important;
}
.dt-button-collection {
position: absolute;
top: 100%;
right: 0;
margin-top: 6px;
display: none;
z-index: 1002;
min-width: 160px;
background-color: var(--color-surface-elevated);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 8px;
box-shadow: 0 20px 45px rgba(0, 0, 0, 0.3);
overflow: hidden;
padding: 6px 0;
}
.dt-buttons.active .dt-button-collection,
.dt-button-collection.active,
.dt-button-collection.show {
display: block;
animation: slideDown 150ms ease-out;
}
/* Ensure collection items are visible and styled */
.dt-button-collection .dt-button,
.dt-button-collection button,
.dt-button-collection a {
display: block;
width: 100%;
padding: 6px 12px;
color: var(--color-text-primary);
background: transparent;
text-decoration: none;
font-size: 13px;
text-align: left;
border: none;
}
.dt-button-collection .dt-button:hover,
.dt-button-collection a:hover,
.dt-button-collection button:hover {
background-color: rgba(59, 130, 246, 0.06);
color: var(--color-primary);
}
.dt-button-collection input[type="checkbox"] {
margin-right: 8px;
vertical-align: middle;
}
.dt-button-collection .dt-button:focus,
.dt-button-collection a:focus,
.dt-button-collection button:focus {
outline: none;
box-shadow: none;
}
/* DataTables sometimes nests a `div.dropdown-menu` inside the collection.
Ensure that inner dropdown-menu is visible when the collection is shown. */
.dt-button-collection .dropdown-menu {
display: block !important;
position: static !important;
background-color: var(--color-surface-elevated) !important;
border: none !important;
box-shadow: none !important;
padding: 0 !important;
min-width: 160px !important;
}
.dt-button-collection .dropdown-menu .dropdown-item,
.dt-button-collection .dropdown-menu a,
.dt-button-collection .dropdown-menu .dt-button {
display: block !important;
padding: 6px 12px !important;
color: var(--color-text-primary) !important;
text-decoration: none !important;
background: transparent !important;
text-align: left !important;
}
.dt-button-collection .dropdown-menu .dropdown-item:hover,
.dt-button-collection .dropdown-menu a:hover,
.dt-button-collection .dropdown-menu .dt-button:hover {
background-color: rgba(59, 130, 246, 0.06) !important;
color: var(--color-primary) !important;
}
/* DataTables ColVis button styling */
.ColVis_MasterButton,
.dt-button {
background-color: var(--color-surface-elevated) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.ColVis_MasterButton:hover,
.dt-button:hover {
background-color: var(--color-surface) !important;
}
.dropdown.active .dropdown-menu,
.dropdown:focus-within .dropdown-menu {
display: block;
animation: slideDown 150ms ease-out;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.dropdown-menu li {
display: block;
}
/* Make DataTables column visibility dropdown independent of table scrolling
Position it fixed so it isn't clipped by table containers and allow
internal scrolling when there are many columns. */
.dt-button-collection {
position: fixed !important;
z-index: 1400 !important;
max-height: 60vh !important;
overflow-y: auto !important;
overflow-x: hidden !important;
box-shadow: 0 8px 24px rgba(2,6,23,0.08) !important;
}
.dt-button-collection .dropdown-menu {
max-height: none !important;
}
/* OTS topbar badge removed */
.dropdown-menu li a {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
color: var(--color-text-primary);
text-decoration: none;
font-size: 14px;
transition: all var(--transition-fast);
font-weight: 500;
}
.dropdown-menu li a:hover {
background-color: rgba(59, 130, 246, 0.1);
color: var(--color-primary);
}
.dropdown-menu li a:active {
background-color: rgba(59, 130, 246, 0.15);
}
/* ============================================================================
DASHBOARD PAGE
============================================================================ */
.dashboard-card,
.content-card {
background: linear-gradient(180deg, rgba(30, 41, 59, 0.92), rgba(15, 23, 42, 0.92));
border: 1px solid rgba(148, 163, 184, 0.18);
border-radius: 16px;
box-shadow: 0 18px 40px rgba(8, 15, 30, 0.35);
backdrop-filter: blur(6px);
overflow: hidden;
}
/* Card hover behavior is handled in override-styles.twig (loaded last) */
/* ── .ots-static-page: kill card hover on non-dashboard pages (backup) ────── */
.ots-static-page .dashboard-card,
.ots-static-page .content-card,
.ots-static-page .action-card,
.ots-static-page .action-card--modern,
.ots-static-page .kpi-card,
.ots-static-page .dashboard-chart-card,
.ots-static-page .widget,
.ots-static-page .card,
.ots-static-page .panel,
.ots-static-page .media-item,
.ots-static-page [class*="-card"],
.ots-static-page [class*="card-"] {
transition: none !important;
transform: none !important;
}
.ots-static-page .dashboard-card:hover,
.ots-static-page .content-card:hover,
.ots-static-page .action-card:hover,
.ots-static-page .action-card--modern:hover,
.ots-static-page .kpi-card:hover,
.ots-static-page .dashboard-chart-card:hover,
.ots-static-page .widget:hover,
.ots-static-page .card:hover,
.ots-static-page .panel:hover,
.ots-static-page .media-item:hover,
.ots-static-page [class*="-card"]:hover,
.ots-static-page [class*="card-"]:hover {
transform: none !important;
transition: none !important;
}
.dashboard-card .panel-header,
.dashboard-card .widget-title,
.content-card .panel-header,
.content-card .widget-title {
background: linear-gradient(90deg, rgba(59, 130, 246, 0.16), rgba(99, 102, 241, 0.12));
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
padding: 18px 20px;
border-radius: 16px 16px 0 0;
}
.dashboard-card .panel-header h3,
.dashboard-card .widget-title h3,
.dashboard-card .panel-header h4,
.dashboard-card .widget-title h4,
.content-card .panel-header h3,
.content-card .widget-title h3,
.content-card .panel-header h4,
.content-card .widget-title h4 {
color: var(--color-text-primary);
font-weight: 700;
}
.dashboard-card .panel-body,
.dashboard-card .widget-body,
.content-card .panel-body,
.content-card .widget-body {
padding: 20px;
min-width: 0;
width: 100%;
}
/* Restrict height of latest news card */
.panel.dashboard-card:has(.fa-newspaper-o) .panel-body {
max-height: 400px;
overflow-y: auto;
}
/* Ensure XiboData expands in grid */
.XiboData {
width: 100%;
min-width: 0;
flex: 1;
overflow: visible;
background-color: transparent !important;
}
/* Force XiboData card variant to be transparent */
.XiboData.card,
.XiboData.card.py-3,
div.XiboData {
background-color: transparent !important;
background: transparent !important;
}
.kpi-card--modern {
position: relative;
overflow: hidden;
}
.kpi-card.dashboard-card {
border-radius: 18px;
padding: 22px;
}
.kpi-card--modern::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at top right, rgba(59, 130, 246, 0.18), transparent 55%);
pointer-events: none;
}
.kpi-card--modern .kpi-number {
font-size: 36px;
letter-spacing: -0.02em;
}
.kpi-card--modern .kpi-icon-box {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.28), rgba(99, 102, 241, 0.2));
color: #e2e8f0;
}
.action-card--modern {
border-radius: 16px;
background: linear-gradient(180deg, rgba(30, 41, 59, 0.9), rgba(15, 23, 42, 0.88));
border: 1px solid rgba(148, 163, 184, 0.2);
box-shadow: 0 14px 30px rgba(8, 15, 30, 0.35);
}
/* Hover effect moved to dashboard-page specific rules at end of file */
/* OTS dashboard message (theme-dashboard-message.twig) */
.ots-dashboard-message {
margin: 16px 0 24px;
padding: 12px 16px;
border-radius: 10px;
background: rgba(59, 130, 246, 0.12);
border: 1px solid rgba(59, 130, 246, 0.35);
color: var(--color-text-primary);
}
.ots-dashboard-message__title {
font-weight: 700;
letter-spacing: 0.02em;
text-transform: uppercase;
font-size: 12px;
margin-bottom: 4px;
}
.ots-dashboard-message__body {
font-size: 13px;
color: var(--color-text-secondary);
}
.dashboard-page {
display: flex;
flex-direction: column;
gap: 32px;
}
.page-header {
margin-bottom: 16px;
margin-left: 0 !important;
}
.page-header h1 {
margin: 0 0 8px;
font-size: 32px;
font-weight: 700;
}
.page-header .text-muted {
margin: 0;
font-size: 16px;
color: var(--color-text-secondary);
}
/* KPI Section */
.kpi-section {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
.kpi-card {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
padding: 20px;
transition: none;
}
/* Hover effect moved to dashboard-page specific rules at end of file */
.kpi-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16px;
}
.kpi-label {
margin: 0;
font-size: 14px;
font-weight: 600;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.kpi-icon-box {
width: 40px;
height: 40px;
border-radius: 6px;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.2), rgba(124, 58, 237, 0.2));
display: flex;
align-items: center;
justify-content: center;
color: var(--color-primary);
}
.kpi-body {
margin-bottom: 12px;
}
.kpi-number {
font-size: 32px;
font-weight: 700;
color: var(--color-text-primary);
line-height: 1;
margin-bottom: 4px;
}
.kpi-meta {
font-size: 13px;
color: var(--color-text-secondary);
}
.kpi-footer {
display: flex;
align-items: center;
gap: 8px;
padding-top: 12px;
border-top: 1px solid var(--color-border);
}
/* Badges */
.badge {
display: inline-block;
padding: 4px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.badge-success {
background-color: rgba(16, 185, 129, 0.2);
color: #a7f3d0;
}
.badge-danger {
background-color: rgba(239, 68, 68, 0.2);
color: #fca5a5;
}
.badge-info {
background-color: rgba(14, 165, 233, 0.2);
color: #7dd3fc;
}
.badge-secondary {
background-color: rgba(124, 58, 237, 0.2);
color: #d8b4fe;
}
/* Dashboard Panels */
.dashboard-panels {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
/* Dashboard chart cards (bandwidth/library) */
.dashboard-chart-card {
background: linear-gradient(180deg, rgba(59, 130, 246, 0.06), rgba(59, 130, 246, 0.02));
border: 1px solid rgba(59, 130, 246, 0.18);
box-shadow: 0 12px 26px rgba(8, 15, 30, 0.35);
display: flex !important;
flex-direction: column !important;
min-height: 380px;
height: 380px;
align-items: stretch !important;
overflow: visible !important;
}
.dashboard-chart-card > * {
width: 100% !important;
float: none !important;
clear: both !important;
}
.dashboard-chart-header {
display: flex !important;
flex-direction: column !important;
gap: 10px !important;
align-items: flex-start !important;
padding: 12px 16px !important;
box-sizing: border-box !important;
width: 100% !important;
background: transparent !important;
border: none !important;
float: none !important;
clear: both !important;
position: static !important;
inset: auto !important;
overflow: visible !important;
height: auto !important;
max-width: none !important;
flex: 0 0 auto !important;
}
.panel .dashboard-chart-header {
padding: 12px 20px !important;
}
.dashboard-chart-info {
display: flex !important;
align-items: center !important;
gap: 10px !important;
flex: 0 0 auto !important;
min-width: 0 !important;
}
.dashboard-chart-icon {
width: 32px !important;
height: 32px !important;
border-radius: 10px !important;
background: rgba(59, 130, 246, 0.18) !important;
color: var(--color-primary-light) !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 16px !important;
flex-shrink: 0 !important;
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.dashboard-chart-meta {
display: flex !important;
flex-direction: column !important;
gap: 2px !important;
flex-shrink: 0 !important;
}
.dashboard-chart-heading {
margin: 0;
font-size: 15px;
font-weight: 700;
line-height: 1.2;
}
.dashboard-chart-subtitle {
margin: 0;
font-size: 11px;
color: var(--color-text-secondary);
line-height: 1.2;
}
.dashboard-chart-actions {
display: flex !important;
align-items: center !important;
gap: 12px !important;
width: 100% !important;
flex-shrink: 0 !important;
padding: 0 !important;
border: none !important;
}
.dashboard-chart-toggle {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px;
border-radius: 999px;
background: rgba(15, 23, 42, 0.45);
}
.dashboard-chart-toggle-button {
border: none;
background: transparent;
color: var(--color-text-secondary);
font-size: 12px;
font-weight: 600;
width: 40px;
height: 34px;
padding: 0;
border-radius: 999px;
cursor: pointer;
transition: all 150ms ease;
display: inline-flex;
align-items: center;
justify-content: center;
}
.dashboard-chart-toggle-button:hover {
color: var(--color-text-primary);
}
.dashboard-chart-toggle-button.is-active {
background: rgba(59, 130, 246, 0.22);
color: var(--color-text-primary);
}
.dashboard-chart-toggle-button i {
font-size: 16px;
line-height: 1;
display: inline-block;
}
.dashboard-chart-body {
padding: 0 20px 20px;
flex: 1;
display: flex;
flex-direction: column;
width: 100%;
box-sizing: border-box;
float: none;
min-height: 0;
}
.dashboard-chart-canvas {
/* Make chart containers visually match their parent dashboard card by
removing their independent background and chrome so the card's
background (gradient or surface) shows through. */
background: transparent !important;
border: none !important;
border-radius: inherit !important;
padding: 0 !important;
height: 200px;
width: 100%;
position: relative;
overflow: hidden;
flex: 1;
box-shadow: none !important;
}
.dashboard-chart-canvas canvas {
display: block;
width: 100% !important;
height: 100% !important;
max-width: 100% !important;
max-height: 100% !important;
margin: 0 !important;
background: transparent !important;
}
.dashboard-chart-card .panel-body canvas,
.dashboard-chart-card .widget-body canvas {
min-height: 0 !important;
}
/* Enhanced chart container styling */
.dashboard-chart-card {
transition: none !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
}
/* Hover effect moved to dashboard-page specific rules at end of file */
/* Chart action improvements */
.dashboard-chart-actions {
gap: 16px !important;
}
.dashboard-chart-link {
font-size: 13px;
font-weight: 500;
color: var(--color-primary-light);
text-decoration: none;
white-space: nowrap;
transition: all 150ms ease;
padding: 4px 8px;
border-radius: 6px;
display: inline-block;
}
.dashboard-chart-link:hover {
color: var(--color-primary);
background: rgba(59, 130, 246, 0.1);
}
/* Modern toggle improvements */
.dashboard-chart-toggle {
background: rgba(15, 23, 42, 0.6);
border: 1px solid rgba(59, 130, 246, 0.2);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.dashboard-chart-toggle-button {
transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid transparent;
}
.dashboard-chart-toggle-button:hover {
background: rgba(59, 130, 246, 0.12);
border-color: rgba(59, 130, 246, 0.2);
}
.dashboard-chart-toggle-button.is-active {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.3), rgba(59, 130, 246, 0.2));
border-color: rgba(59, 130, 246, 0.3);
box-shadow: 0 0 12px rgba(59, 130, 246, 0.2);
}
.dashboard-chart-toggle-button i {
transition: transform 200ms ease;
}
.dashboard-chart-toggle-button:hover i {
transform: scale(1.15);
}
/* Responsive chart cards */
@media (max-width: 1200px) {
.dashboard-chart-canvas {
height: 180px;
}
}
@media (max-width: 768px) {
.dashboard-chart-card {
max-height: none;
}
.dashboard-chart-header {
flex-direction: row !important;
justify-content: space-between !important;
align-items: center !important;
gap: 12px !important;
}
.dashboard-chart-info {
flex: 1;
min-width: 0;
}
.dashboard-chart-actions {
flex-shrink: 0;
}
.dashboard-chart-canvas {
height: 200px;
}
}
.panel {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* ============================================================================
CONSOLIDATED CARD/PANEL/WIDGET STYLING (Simplified, single source of truth)
============================================================================ */
.card,
.panel,
.panel.panel-default,
.panel.panel-white,
.panel.box,
.widget,
.dashboard-card,
.content-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;
}
/* 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;
}
/* 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,
.card .dataTables_wrapper,
.widget .dataTables_wrapper {
background-color: transparent !important;
color: var(--color-text-primary) !important;
}
.panel-full {
grid-column: 1 / -1;
}
.panel-header {
padding: 20px;
border-bottom: 1px solid var(--color-border);
display: flex;
justify-content: space-between;
align-items: center;
}
.panel-header h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: var(--color-text-primary);
}
.link-secondary {
color: var(--color-primary);
text-decoration: none;
font-size: 13px;
font-weight: 500;
transition: color var(--transition-fast);
}
.link-secondary:hover {
color: var(--color-primary-light);
}
.panel-body {
padding: 20px;
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
}
.empty-state-compact {
text-align: center;
padding: 20px 0;
}
.empty-state-compact p {
margin: 0 0 16px;
color: var(--color-text-secondary);
}
/* Quick Actions */
.quick-actions-grid {
margin-top: 32px;
}
.section-title {
margin: 0 0 16px;
font-size: 18px;
font-weight: 600;
color: var(--color-text-primary);
}
.action-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
.action-card {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12px;
padding: 24px;
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
text-decoration: none;
color: var(--color-text-primary);
transition: none;
cursor: pointer;
}
/* Hover effect moved to dashboard-page specific rules at end of file */
.action-icon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
color: var(--color-primary);
}
.action-label {
font-size: 14px;
font-weight: 600;
text-align: center;
}
/* ============================================================================
TWO-COLUMN LAYOUT (Displays, Media)
============================================================================ */
.ots-displays-page .page-header {
margin-bottom: 20px;
}
.ots-displays-card {
padding: 0;
display: flex;
flex-direction: column;
min-width: 0;
overflow: visible !important;
}
.ots-displays-body {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
overflow: visible !important;
}
.ots-displays-body .XiboGrid {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
overflow: visible !important;
}
.ots-displays-title {
font-size: 18px;
font-weight: 700;
letter-spacing: 0.02em;
}
.ots-filter-card {
background-color: var(--color-surface-elevated) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
box-shadow: var(--ots-shadow-md, 0 8px 18px rgba(0,0,0,0.12));
margin-bottom: 0;
border-radius: 12px;
overflow: visible !important;
}
/* Strongly remove any remaining gradients / shadows inside filters */
.ots-filter-card *::before,
.ots-filter-card *::after {
background-image: none !important;
box-shadow: none !important;
}
.ots-filter-card .form-control,
.ots-filter-card select,
.ots-filter-card .select2-selection,
.ots-filter-card .input-group-addon,
.ots-filter-card button,
.ots-filter-card .btn {
background-color: var(--color-surface) !important;
background-image: none !important;
box-shadow: none !important;
color: var(--color-text-primary) !important;
}
/* Extra strong fallbacks targeting various control classes used in filter markup */
.ots-filter-card input.form-control,
.ots-filter-card input[type="text"],
.ots-filter-card input[type="search"],
.ots-filter-card textarea,
.ots-filter-card select,
.ots-filter-card select.custom-select,
.ots-filter-card .custom-select,
.ots-filter-card .input-group-text,
.ots-filter-card .input-group-addon,
.ots-filter-card .input-group-append,
.ots-filter-card .input-group {
background-color: var(--color-surface, var(--ots-surface, var(--color-background))) !important;
background-image: none !important;
background: var(--color-surface, var(--ots-surface, var(--color-background))) !important;
box-shadow: none !important;
border: 1px solid var(--color-border, var(--ots-border)) !important;
}
.ots-filter-card select option {
background: var(--color-surface, var(--ots-surface)) !important;
color: var(--color-text-primary, var(--ots-text)) !important;
}
/* Specific override for the append/addon area (checkbox + operator) */
.ots-filter-card .input-group-append,
.ots-filter-card .input-group-append .input-group-text,
.ots-filter-card .input-group-append .input-group-addon,
.ots-filter-card .input-group-append .custom-select,
.ots-filter-card .input-group-append .select,
.ots-filter-card .input-group-append .btn,
.ots-filter-card .input-group-append .dropdown-toggle {
background-color: var(--color-surface) !important;
background-image: none !important;
background: var(--color-surface) !important;
box-shadow: none !important;
border: 1px solid var(--color-border) !important;
color: var(--color-text-primary) !important;
}
/* Force checkbox wrapper to be transparent so only checkbox is visible */
.ots-filter-card .input-group-text input[type="checkbox"],
.ots-filter-card .input-group-text input[type="checkbox"] + label {
background: transparent !important;
box-shadow: none !important;
}
/* Aggressive override: force all direct children of input-group to use solid surface */
.ots-filter-card .input-group > *,
.ots-filter-card .input-group > *::before,
.ots-filter-card .input-group > *::after {
background: var(--color-surface, var(--ots-surface, var(--color-background))) !important;
background-image: none !important;
box-shadow: none !important;
border-radius: 6px !important;
border: 1px solid var(--color-border, var(--ots-border)) !important;
color: var(--color-text-primary, var(--ots-text)) !important;
}
/* If any decorative pseudo elements are used to create the rounded pills, hide them */
.ots-filter-card .input-group > *::before,
.ots-filter-card .input-group > *::after {
content: none !important;
display: none !important;
}
/* Filter header with collapse button */
.ots-filter-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 1px solid var(--color-border);
background: var(--color-surface-elevated);
}
.ots-filter-title {
font-weight: 600;
color: var(--color-text-primary);
font-size: 14px;
margin: 0;
}
.ots-filter-toggle {
width: 32px;
height: 32px;
padding: 0;
border: none;
background: transparent;
color: var(--color-text-secondary);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
transition: all var(--transition-fast);
}
.ots-filter-toggle:hover {
background: rgba(59, 130, 246, 0.1);
color: var(--color-primary);
}
.ots-filter-content {
padding: 16px;
max-height: none;
min-height: auto;
overflow: visible;
transition: max-height 300ms ease-out, padding 300ms ease-out;
display: block;
background: var(--color-surface-elevated) !important;
}
.ots-filter-content.collapsed {
max-height: 0;
min-height: 0;
padding: 0 16px;
overflow: hidden;
display: none;
}
/* Ensure FilterDiv and all nested card-body elements inherit the filter background */
.ots-filter-card .FilterDiv,
.ots-filter-card .card-body,
.ots-filter-card .FilterDiv.card-body {
background: var(--color-surface-elevated) !important;
background-color: var(--color-surface-elevated) !important;
}
/* Ensure form elements have proper container backgrounds */
.ots-filter-card form,
.ots-filter-card .form-inline,
.ots-filter-card .tab-content,
.ots-filter-card .tab-pane {
background: transparent !important;
}
.ots-filter-card .nav-tabs {
border-bottom: 1px solid var(--color-border);
gap: 8px;
margin-bottom: 14px;
}
.ots-filter-card .nav-tabs .nav-link {
color: var(--color-text-secondary);
border: 0;
border-radius: 8px;
padding: 10px 14px;
background: transparent;
font-size: 13px;
font-weight: 500;
transition: all var(--transition-fast);
}
.ots-filter-card .nav-tabs .nav-link.active,
.ots-filter-card .nav-tabs .nav-link:hover {
color: var(--color-text-primary);
background: rgba(59, 130, 246, 0.12);
}
.ots-filter-card .form-inline .form-group,
.ots-filter-card .form-inline .input-group {
margin-right: 16px;
margin-bottom: 12px;
}
.ots-filter-card .form-control,
.ots-filter-card select,
.ots-filter-card .select2-selection,
.ots-filter-card .input-group-addon {
background: var(--color-surface) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
color: var(--color-text-primary) !important;
border-radius: 6px !important;
padding: 8px 12px !important;
font-size: 13px !important;
transition: all var(--transition-fast) !important;
height: 36px !important;
box-shadow: none !important;
}
.ots-filter-card .form-control:focus,
.ots-filter-card select:focus {
border-color: var(--color-primary) !important;
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.08) !important;
background: var(--color-surface) !important;
background-image: none !important;
}
/* Fix: force checkboxes to respect light/dark theme (remove hard dark square) */
.ots-filter-card input[type="checkbox"],
.ots-filter-card .form-check-input,
.ots-filter-card .custom-control-input {
-webkit-appearance: none !important;
appearance: none !important;
width: 18px !important;
height: 18px !important;
display: inline-block !important;
vertical-align: middle !important;
border-radius: 4px !important;
background-color: var(--color-surface) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
box-shadow: none !important;
}
.ots-filter-card input[type="checkbox"]:checked,
.ots-filter-card .form-check-input:checked,
.ots-filter-card .custom-control-input:checked {
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
background-image: none !important;
box-shadow: none !important;
}
/* Support bootstrap/custom-control markup where labels render the box via ::before */
.ots-filter-card .custom-control-input + .custom-control-label::before,
.ots-filter-card .form-check-input + label::before,
.modal .custom-control-input + .custom-control-label::before,
.modal .form-check-input + label::before {
background-color: var(--color-surface) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
box-shadow: none !important;
}
.ots-filter-card .custom-control-input:checked + .custom-control-label::before,
.ots-filter-card .form-check-input:checked + label::before,
.modal .custom-control-input:checked + .custom-control-label::before,
.modal .form-check-input:checked + label::before {
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
background-image: none !important;
box-shadow: none !important;
}
/* Also apply broadly inside modals/popovers in case the checkbox is outside the filter card */
.modal input[type="checkbox"],
.modal .form-check-input,
.popover input[type="checkbox"],
.popover .form-check-input {
-webkit-appearance: none !important;
appearance: none !important;
width: 18px !important;
height: 18px !important;
background-color: var(--color-surface) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
box-shadow: none !important;
}
.modal input[type="checkbox"]:checked,
.modal .form-check-input:checked,
.popover input[type="checkbox"]:checked,
.popover .form-check-input:checked {
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
background-image: none !important;
}
.ots-filter-card label {
color: var(--color-text-secondary);
font-size: 12px;
font-weight: 500;
margin-bottom: 4px;
display: block;
}
/* Ensure the folder-tree "All Folders" checkbox follows light/dark variables
(the checkbox lives in `.ots-folder-tree` / `#grid-folder-filter`). */
.ots-folder-tree input[type="checkbox"],
.ots-folder-tree .form-check-input,
#grid-folder-filter input[type="checkbox"],
#grid-folder-filter .form-check-input {
-webkit-appearance: none !important;
appearance: none !important;
width: 18px !important;
height: 18px !important;
display: inline-block !important;
vertical-align: middle !important;
border-radius: 4px !important;
background-color: var(--color-surface) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
box-shadow: none !important;
}
.ots-folder-tree input[type="checkbox"]:checked,
.ots-folder-tree .form-check-input:checked,
#grid-folder-filter input[type="checkbox"]:checked,
#grid-folder-filter .form-check-input:checked {
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
background-image: none !important;
box-shadow: none !important;
}
.ots-grid-with-folders {
display: grid;
grid-template-columns: 260px 1fr;
gap: 32px;
align-items: start;
width: 100%;
min-width: 0;
transition: grid-template-columns 200ms ease-out;
}
.ots-grid-with-folders.ots-folder-collapsed {
grid-template-columns: 1fr;
gap: 0;
}
.ots-grid-with-folders.ots-folder-collapsed .ots-folder-tree {
display: none;
width: 0;
overflow: hidden;
}
.ots-folder-tree {
min-height: 320px;
padding: 16px;
margin-right: -8px;
max-width: 100%;
box-sizing: content-box;
}
.ots-folder-tree .form-check {
margin-top: 12px;
}
.ots-grid-controller {
margin-top: 8px;
}
.ots-grid-controller .btn {
border-radius: 10px;
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;
background: transparent !important;
}
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
color: var(--color-text-secondary) !important;
background: transparent !important;
}
/* Ensure all DataTables control wrappers and button areas have transparent backgrounds */
.dataTables_wrapper > *,
.dataTables_wrapper .dataTables_buttons,
.dataTables_buttons,
.dt-buttons,
.buttons-collection {
background: transparent !important;
background-color: transparent !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 {
flex: 1;
min-width: 0;
overflow: hidden;
background: transparent !important;
}
/* Ensure XiboData cards are transparent */
.XiboData.card,
.XiboData.card.py-3,
div.XiboData.card {
background: transparent !important;
background-color: transparent !important;
border: none !important;
box-shadow: none !important;
}
#datatable-container {
width: 100%;
min-width: 0;
overflow-x: auto;
overflow-y: visible;
background: transparent !important;
}
/* Ensure all child elements of datatable-container have transparent backgrounds */
#datatable-container > *,
#datatable-container .XiboData,
#datatable-container .XiboData > *,
#datatable-container .card,
#datatable-container .dataTables_wrapper,
#datatable-container .dataTables_wrapper > * {
background: transparent !important;
background-color: transparent !important;
}
.ots-table-card .table thead th {
background: rgba(15, 23, 42, 0.9);
color: var(--color-text-primary);
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
}
/* Make table fill full width */
.ots-table-card .table {
width: 100% !important;
table-layout: auto !important;
}
.ots-table-card .table thead th,
.ots-table-card .table tbody td,
.ots-table-card .table tbody th,
.ots-table-card .table tbody tr {
color: #e2e8f0;
}
.ots-table-card .table tbody tr {
background: rgba(15, 23, 42, 0.7);
}
.ots-table-card .table tbody tr:nth-child(even) {
background: rgba(30, 41, 59, 0.75);
}
.ots-table-card .table tbody tr:hover {
background: rgba(59, 130, 246, 0.14);
color: #ffffff;
}
.ots-table-card .table tbody tr.selected,
.ots-table-card .table tbody tr.dt-row-selected,
.ots-table-card .table tbody tr.selected td,
.ots-table-card .table tbody tr.dt-row-selected td {
background: rgba(16, 185, 129, 0.25) !important;
color: #ffffff !important;
}
/* === Row dropdown menus (context menus on table rows) ===
When opened, these get moved to <body> by JS so they escape all
overflow:hidden containers. Styled here for both in-situ and
body-appended states. */
body > .dropdown-menu.ots-row-dropdown {
position: fixed !important;
z-index: 2147483647 !important;
display: block !important;
transform: none !important;
will-change: auto !important;
margin: 0 !important;
right: auto !important;
bottom: auto !important;
background-color: var(--color-surface-elevated) !important;
border: 1px solid var(--color-border) !important;
border-radius: 8px !important;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4) !important;
padding: 6px 0 !important;
min-width: 180px !important;
max-height: 80vh;
overflow-y: auto;
}
body > .dropdown-menu.ots-row-dropdown a,
body > .dropdown-menu.ots-row-dropdown .dropdown-item {
color: var(--color-text-primary) !important;
padding: 8px 16px !important;
font-size: 13px !important;
display: block !important;
white-space: nowrap !important;
text-decoration: none !important;
transition: background 120ms ease !important;
}
body > .dropdown-menu.ots-row-dropdown a:hover,
body > .dropdown-menu.ots-row-dropdown .dropdown-item:hover {
background-color: rgba(59, 130, 246, 0.12) !important;
color: var(--color-primary-light) !important;
}
body > .dropdown-menu.ots-row-dropdown .divider,
body > .dropdown-menu.ots-row-dropdown .dropdown-divider {
border-top: 1px solid var(--color-border) !important;
margin: 4px 0 !important;
}
/* Table toolbar — action buttons row inside the table card */
.ots-table-toolbar {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 16px 12px;
flex-wrap: wrap;
}
.ots-table-toolbar .btn {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
gap: 0 !important;
font-size: 0 !important;
font-weight: 600 !important;
padding: 8px !important;
border-radius: 8px !important;
white-space: nowrap !important;
line-height: 1.4 !important;
height: 40px !important;
width: 40px !important;
min-width: 40px !important;
}
.ots-table-toolbar .btn i,
.ots-table-toolbar .btn .fa {
font-size: 20px !important;
}
/* Light mode toolbar buttons */
body.ots-light-mode .ots-table-toolbar .btn-success {
background-color: #10b981 !important;
border-color: #10b981 !important;
color: #ffffff !important;
}
body.ots-light-mode .ots-table-toolbar .btn-warning {
background-color: #f59e0b !important;
border-color: #f59e0b !important;
color: #ffffff !important;
}
body.ots-light-mode .ots-table-toolbar .btn-primary {
background-color: #3b82f6 !important;
border-color: #3b82f6 !important;
color: #ffffff !important;
}
/* Map and list view toggle buttons */
#map_button,
#list_button {
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
color: #ffffff !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important;
transition: all 0.15s ease !important;
}
#map_button:hover,
#list_button:hover {
background-color: var(--color-primary-light) !important;
border-color: var(--color-primary-light) !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
transform: translateY(-1px);
}
#map_button:active,
#list_button:active {
transform: translateY(0);
}
/* Active state for map/list toggle buttons */
#map_button.active,
#list_button.active {
background-color: #0c7a2a !important;
border-color: #0c7a2a !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) inset !important;
}
/* Dark mode toolbar button styles - ensure consistent colors across all pages */
.ots-table-toolbar .btn-success {
background-color: #10b981 !important;
border-color: #10b981 !important;
color: #ffffff !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important;
}
.ots-table-toolbar .btn-success:hover {
background-color: #059669 !important;
border-color: #059669 !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
}
.ots-table-toolbar .btn-primary {
background-color: #3b82f6 !important;
border-color: #3b82f6 !important;
color: #ffffff !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important;
}
.ots-table-toolbar .btn-primary:hover {
background-color: #2563eb !important;
border-color: #2563eb !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
}
.ots-table-toolbar .btn-warning {
background-color: #f59e0b !important;
border-color: #f59e0b !important;
color: #ffffff !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important;
}
.ots-table-toolbar .btn-warning:hover {
background-color: #d97706 !important;
border-color: #d97706 !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
}
.ots-table-card .dataTables_wrapper,
.ots-table-card .dataTables_wrapper * {
color: #e2e8f0 !important;
}
.ots-table-card .dataTables_wrapper .dataTables_filter input,
.ots-table-card .dataTables_wrapper .dataTables_length select {
background: rgba(15, 23, 42, 0.8) !important;
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 {
color: #e2e8f0 !important;
}
.ots-displays-page #datatable-container .XiboData .table thead th,
.ots-displays-page #datatable-container .XiboData table.dataTable thead th {
color: #cbd5e1 !important;
background-color: var(--color-surface) !important;
font-weight: 600 !important;
opacity: 1 !important;
}
.ots-displays-page #datatable-container .XiboData .table tbody td,
.ots-displays-page #datatable-container .XiboData table.dataTable tbody td {
color: #e2e8f0 !important;
opacity: 1 !important;
}
.ots-displays-page #datatable-container .XiboData table.dataTable tbody tr {
background-color: rgba(15, 23, 42, 0.75) !important;
}
/* Status icons in Displays table */
.ots-displays-page #datatable-container .fa-check,
.ots-displays-page #datatable-container .fa-check-circle {
color: var(--color-success) !important;
}
.ots-displays-page #datatable-container .fa-times,
.ots-displays-page #datatable-container .fa-times-circle,
.ots-displays-page #datatable-container .fa-x {
color: var(--color-danger) !important;
}
.ots-displays-page #datatable-container .XiboData table.dataTable tbody tr:nth-child(even) {
background-color: rgba(30, 41, 59, 0.8) !important;
}
.ots-table-card .table tbody tr:hover {
background: rgba(59, 130, 246, 0.08);
}
.ots-map-card {
margin-top: 16px;
height: 600px;
min-height: 360px;
background: rgba(15, 23, 42, 0.6);
border: 1px solid rgba(148, 163, 184, 0.2);
border-radius: 16px;
}
@media (max-width: 1024px) {
.ots-grid-with-folders {
grid-template-columns: 1fr;
}
}
/* Light-mode table color overrides to ensure contrast and legibility */
body.ots-light-mode .ots-table-card .table thead th {
background: var(--color-surface-elevated) !important;
color: var(--color-text-primary) !important;
border-bottom: 1px solid var(--color-border) !important;
opacity: 1 !important;
}
body.ots-light-mode .ots-table-card .table thead th,
body.ots-light-mode .ots-table-card .table tbody td,
body.ots-light-mode .ots-table-card .table tbody th,
body.ots-light-mode .ots-table-card .table tbody tr {
color: var(--color-text-primary) !important;
}
body.ots-light-mode .ots-table-card .table tbody tr {
background: var(--color-surface) !important;
}
body.ots-light-mode .ots-table-card .table tbody tr:nth-child(even) {
background: var(--color-surface-elevated) !important;
}
body.ots-light-mode .ots-table-card .table tbody tr:hover {
background: rgba(37, 99, 235, 0.06) !important; /* subtle blue hover */
color: var(--color-text-primary) !important;
}
body.ots-light-mode .ots-table-card .table tbody tr.selected,
body.ots-light-mode .ots-table-card .table tbody tr.dt-row-selected,
body.ots-light-mode .ots-table-card .table tbody tr.selected td,
body.ots-light-mode .ots-table-card .table tbody tr.dt-row-selected td {
background: rgba(16, 185, 129, 0.12) !important;
color: var(--color-text-primary) !important;
}
body.ots-light-mode .ots-table-card .dataTables_wrapper,
body.ots-light-mode .ots-table-card .dataTables_wrapper * {
color: var(--color-text-primary) !important;
}
body.ots-light-mode .ots-table-card .dataTables_wrapper .dataTables_filter input,
body.ots-light-mode .ots-table-card .dataTables_wrapper .dataTables_length select {
background: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
/* Ensure Displays page specific table rows are light in light-mode */
body.ots-light-mode .ots-displays-page #datatable-container .XiboData table.dataTable tbody tr {
background-color: transparent !important;
}
body.ots-light-mode .ots-displays-page #datatable-container .XiboData table.dataTable tbody tr:nth-child(even) {
background-color: var(--color-surface-elevated) !important;
}
.two-column-layout {
display: grid;
grid-template-columns: 280px 1fr;
gap: 24px;
height: calc(100vh - 130px);
}
.left-panel {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
display: flex;
flex-direction: column;
overflow-y: auto;
}
.content-panel {
display: flex;
flex-direction: column;
gap: 16px;
}
.folder-tree {
padding: 8px 0;
}
.folder-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
color: var(--color-text-secondary);
cursor: pointer;
transition: all var(--transition-fast);
}
.folder-item:hover {
background-color: var(--color-surface-elevated);
color: var(--color-text-primary);
}
.folder-item.active {
background-color: rgba(59, 130, 246, 0.15);
color: var(--color-primary);
}
.folder-icon {
width: 18px;
height: 18px;
flex-shrink: 0;
color: yellow;
}
.folder-name {
font-size: 14px;
font-weight: 500;
}
.content-toolbar {
display: flex;
align-items: center;
gap: 16px;
padding: 16px;
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
}
.search-wrapper {
flex: 1;
position: relative;
display: flex;
align-items: center;
background-color: var(--color-surface-elevated);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 8px 12px;
}
.search-icon {
color: var(--color-text-tertiary);
margin-right: 8px;
flex-shrink: 0;
}
.search-field {
flex: 1;
background: none;
border: none;
color: var(--color-text-primary);
font-size: 14px;
outline: none;
padding: 0;
}
.search-field::placeholder {
color: var(--color-text-tertiary);
}
.toolbar-actions {
display: flex;
align-items: center;
gap: 12px;
}
.stat-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 12px;
}
.stat-box {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 12px;
text-align: center;
}
.stat-label {
font-size: 12px;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 8px;
}
.stat-value {
font-size: 24px;
font-weight: 700;
color: var(--color-text-primary);
}
.text-success {
color: #10b981;
}
.text-danger {
color: #ef4444;
}
/* ============================================================================
TABLES
============================================================================ */
.table-wrapper {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
overflow-x: auto;
}
.table {
width: 100%;
border-collapse: collapse;
margin: 0;
font-size: 14px;
}
.table thead {
background-color: var(--color-surface);
border-bottom: 2px solid var(--color-border);
}
.table thead th {
padding: 12px 16px;
text-align: left;
font-weight: 600;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 11px;
background-color: var(--color-surface);
}
/* Status icons and checkmarks color */
.table tbody td .fa-check,
.table tbody td .fa-check-circle {
color: var(--color-success);
}
.table tbody td .fa-times,
.table tbody td .fa-times-circle,
.table tbody td .fa-x {
color: var(--color-danger);
}
.table tbody td .fa-exclamation,
.table tbody td .fa-exclamation-circle,
.table tbody td .fa-question-circle {
color: var(--color-warning);
}
.table tbody td .fa-info-circle {
color: var(--color-info);
}
.table tbody tr {
border-bottom: 1px solid var(--color-border);
transition: background-color var(--transition-fast);
}
.table tbody tr:hover {
background-color: var(--color-surface-elevated);
}
.table tbody td {
padding: 12px 16px;
color: var(--color-text-primary);
}
.table-striped tbody tr:nth-child(even) {
background-color: rgba(59, 130, 246, 0.02);
}
/* ============================================================================
MEDIA LIBRARY
============================================================================ */
.media-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
padding: 16px;
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
}
.media-item {
background-color: var(--color-surface-elevated);
border: 1px solid var(--color-border);
border-radius: 6px;
overflow: hidden;
cursor: pointer;
transition: all var(--transition-base);
}
.media-item:hover {
border-color: var(--color-primary);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
transform: translateY(-4px);
}
.media-thumbnail {
position: relative;
width: 100%;
padding-bottom: 75%;
overflow: hidden;
background-color: var(--color-border);
}
.media-thumbnail img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.media-type-badge {
position: absolute;
top: 8px;
right: 8px;
background-color: rgba(0, 0, 0, 0.6);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
}
.media-info {
padding: 12px;
}
.media-name {
margin: 0 0 4px;
font-size: 14px;
font-weight: 600;
color: var(--color-text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.media-size {
margin: 0;
color: var(--color-text-tertiary);
}
/* ============================================================================
BUTTONS
============================================================================ */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 16px;
border: none;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
text-decoration: none;
cursor: pointer;
transition: all var(--transition-fast);
white-space: nowrap;
}
.btn-primary {
background-color: var(--color-primary);
color: white;
}
.btn-primary:hover {
background-color: var(--color-primary-dark);
}
.btn-outline {
background-color: transparent;
border: 1px solid var(--color-border);
color: var(--color-text-primary);
}
.btn-outline:hover {
background-color: var(--color-surface);
border-color: var(--color-primary);
color: var(--color-primary);
}
.btn-sm {
padding: 6px 12px;
font-size: 13px;
}
.btn-ghost {
background-color: transparent;
color: var(--color-text-secondary);
padding: 0;
}
.btn-ghost:hover {
color: var(--color-text-primary);
}
/* Minimal Icon-Only Buttons */
.btn-icon {
width: 40px !important;
height: 40px !important;
padding: 0 !important;
border-radius: 8px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
background-color: var(--color-surface-elevated) !important;
border: 1px solid var(--color-border) !important;
color: var(--color-text-secondary) !important;
font-size: 0 !important;
transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1) !important;
cursor: pointer !important;
position: relative !important;
margin-left: 6px !important;
flex-shrink: 0 !important;
}
.btn-icon:hover {
background-color: rgba(59, 130, 246, 0.12) !important;
border-color: rgba(59, 130, 246, 0.3) !important;
color: var(--color-primary-light) !important;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1) !important;
}
.btn-icon:active {
background-color: rgba(59, 130, 246, 0.2) !important;
border-color: rgba(59, 130, 246, 0.4) !important;
transform: scale(0.95);
}
.btn-icon i,
.btn-icon svg {
font-size: 17px !important;
line-height: 1 !important;
display: inline-block !important;
}
.btn-icon.btn-success {
background-color: rgba(34, 197, 94, 0.08) !important;
border-color: rgba(34, 197, 94, 0.2) !important;
color: rgb(34, 197, 94) !important;
}
.btn-icon.btn-success:hover {
background-color: rgba(34, 197, 94, 0.15) !important;
border-color: rgba(34, 197, 94, 0.4) !important;
box-shadow: 0 2px 8px rgba(34, 197, 94, 0.1) !important;
}
/* ============================================================================
UTILITY CLASSES
============================================================================ */
.text-muted {
color: var(--color-text-secondary);
}
.text-tertiary {
color: var(--color-text-tertiary);
}
.text-xs {
font-size: 12px;
}
.text-sm {
font-size: 14px;
}
.form-control {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
color: var(--color-text-primary);
padding: 8px 12px;
border-radius: 6px;
font-size: 14px;
}
.form-control::placeholder {
color: var(--color-text-secondary);
}
.form-control:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
/* ============================================================================
RESPONSIVE
============================================================================ */
@media (max-width: 768px) {
.ots-topbar {
flex-direction: column;
align-items: flex-start;
gap: 12px;
height: auto;
padding: 12px 16px;
}
.topbar-right {
width: 100%;
flex-direction: column;
}
.topbar-search {
width: 100%;
}
.two-column-layout {
grid-template-columns: 1fr;
height: auto;
}
.left-panel {
max-height: 300px;
}
.dashboard-panels {
grid-template-columns: 1fr;
}
.kpi-section {
grid-template-columns: 1fr;
}
.action-cards {
grid-template-columns: 1fr;
}
.media-grid {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.ots-content {
padding: 16px 16px 16px 0;
}
.ots-footer {
padding: 12px 16px;
}
}
/* ============================================================================
CANVAS / CHART ELEMENTS
============================================================================ */
/* Ensure canvas elements and chart containers render properly */
canvas {
max-width: 100%;
height: auto;
display: block;
}
.chart-container,
.chart-wrapper {
position: relative;
width: 100%;
height: 100%;
}
/* OTS sidebar override marker */
.ots-sidebar-wrapper {
box-shadow: inset 0 0 0 1px rgba(59, 130, 246, 0.15);
}
.ots-sidebar .sidebar-list a,
.ots-sidebar .sidebar-main a {
display: flex;
align-items: center;
gap: 10px;
}
.ots-nav-icon {
width: 18px;
text-align: center;
opacity: 0.85;
font-size: 14px;
}
.ots-nav-text {
flex: 1;
min-width: 0;
}
/* Xibo sidebar refinements (light) */
#sidebar-wrapper .sidebar-title a {
color: var(--color-text-tertiary);
font-size: 11px;
letter-spacing: 0.08em;
text-transform: uppercase;
padding: 12px 16px 6px;
}
#sidebar-wrapper .sidebar-list a,
#sidebar-wrapper .sidebar-main a {
display: flex;
align-items: center;
gap: 12px;
margin: 2px 8px;
padding: 10px 12px;
border-radius: 8px;
transition: background-color var(--transition-fast), color var(--transition-fast);
}
#sidebar-wrapper .sidebar-list a:hover,
#sidebar-wrapper .sidebar-main a:hover {
background: rgba(59, 130, 246, 0.1);
color: var(--color-primary);
}
/* Ensure chart parent containers have proper sizing */
.panel-body canvas,
.panel-body .chart-container {
flex: 1;
min-height: 300px;
}
.panel-body > .chart-container,
.panel-body > .chart-wrapper {
width: 100% !important;
height: 100% !important;
}
.panel-body > .chart-container > canvas,
.panel-body > .chart-wrapper > canvas {
width: 100% !important;
height: 100% !important;
}
.dashboard-chart-card [class*="chart"] {
height: auto;
}
/* Hidden dashboard chart canvas bridge */
.chart-sandbox {
position: absolute;
left: -10000px;
top: -10000px;
width: 1px;
height: 1px;
overflow: hidden;
pointer-events: none;
}
.chart-sandbox canvas {
width: 1px !important;
height: 1px !important;
}
/* Transition variable fallback */
:root {
--transition-fast: 150ms ease-in-out;
--transition-base: 200ms ease-in-out;
--transition-slow: 300ms ease-in-out;
}
/* ================================================================
Modern table styles (theme override)
Applied: makes XIBO tables look cleaner and responsive
================================================================ */
.modern-table-card {
background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));
border-radius: 10px;
box-shadow: 0 6px 18px rgba(2,6,23,0.45);
padding: 18px;
margin: 16px 0;
border: 1px solid rgba(255,255,255,0.02);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial;
}
.modern-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
font-size: 13px;
color: var(--color-text-primary);
}
.modern-table thead th {
background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.03));
color: var(--color-text-primary);
font-weight: 700;
text-transform: uppercase;
letter-spacing: .06em;
font-size: 11px;
padding: 10px 12px;
border-bottom: 1px solid rgba(255,255,255,0.1);
position: sticky;
top: 0;
z-index: 2;
}
.modern-table tbody tr {
background: transparent;
}
.modern-table tbody tr:nth-child(odd) {
background: rgba(255,255,255,0.01);
}
.modern-table tbody tr:hover {
background: rgba(59,130,246,0.06);
}
.modern-table td {
padding: 12px;
vertical-align: middle;
border-bottom: 1px solid rgba(255,255,255,0.02);
}
.table-controls {
display:flex;
gap:8px;
align-items:center;
justify-content:flex-end;
margin-bottom:12px;
}
.table-controls .btn {
background: var(--color-primary);
color: var(--color-on-primary);
border-radius: 999px;
padding: 6px 10px;
font-size: 13px;
border: none;
cursor: pointer;
}
.table-controls .btn.ghost {
background:transparent;
color:var(--color-primary);
border:1px solid rgba(59,130,246,0.12);
}
.table-meta {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
padding-top: 10px;
font-size: 13px;
color: var(--color-text-secondary);
}
@media (max-width: 880px) {
.modern-table thead th:nth-child(n+6),
.modern-table tbody td:nth-child(n+6) {
display: none;
}
.modern-table tbody td.details-toggle {
display: table-cell;
}
.modern-table-card {
padding: 12px;
/* Backdrop shown when sidebar is active on small screens */
.ots-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.45);
z-index: 1040;
}
.ots-backdrop.show {
display: block;
}
}
}
/* Improve legibility: force table and datatables text to full contrast */
.modern-table,
.modern-table tbody,
.modern-table tbody tr,
.modern-table td,
.dataTables_wrapper,
.dataTables_wrapper table,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter {
color: var(--Color-fallback, var(--color-text-primary)) !important;
opacity: 1 !important;
}
/* Stronger selected row for readability */
.modern-table tbody tr.selected,
.modern-table tbody tr.dt-row-selected,
.dataTables_wrapper table tbody tr.selected,
.dataTable tbody tr.selected {
background: rgba(16,185,129,0.14) !important; /* stronger mint */
color: var(--color-text-primary) !important;
}
/* Inputs and selects used in filters/search should be readable */
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select,
.topbar-search .search-input,
.table-controls input,
input[type="search"],
input[type="text"],
select,
textarea {
background: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
/* Buttons - ensure contrast */
.btn,
.button,
.dataTables_wrapper .dataTables_paginate .paginate_button {
color: var(--color-text-primary) !important;
}
/* If panels or overlays dim content, ensure table contents remain fully visible */
.panel,
.panel-body,
.table-wrapper,
.dataTables_wrapper,
.dataTables_wrapper *,
.dataTables_wrapper .dataTables_scroll,
.dataTables_wrapper .dataTables_scroll *,
.dataTables_wrapper .dataTables_scrollBody,
.dataTables_wrapper .dataTables_scrollHead,
.dataTables_wrapper .dataTables_scrollHeadInner,
.dataTables_wrapper .dataTables_scrollHeadInner *,
.dataTables_wrapper .dataTables_scrollHead table,
.dataTables_wrapper .dataTables_scrollHead table * {
opacity: 1 !important;
background: transparent !important;
}
/* DataTables color adjustments to ensure legibility in dark theme */
.dataTables_wrapper,
.dataTables_wrapper * {
color: var(--color-text-primary) !important;
}
/* Ensure tables scroll within their container, not the page */
.dataTables_wrapper {
max-width: 100% !important;
overflow-x: auto !important;
box-sizing: border-box !important;
}
table.dataTable,
.XiboData table,
.ots-table-card table {
max-width: 100% !important;
table-layout: auto !important;
}
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
color: var(--color-text-primary) !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button {
background: transparent;
color: var(--color-text-primary) !important;
border: 1px solid transparent;
border-radius: 6px;
padding: 4px 8px;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
background: var(--color-primary) !important;
color: var(--color-on-primary) !important;
border-color: rgba(255,255,255,0.06);
}
/* Global legibility overrides */
body,
.ots-content,
.content,
.container,
.card,
.panel,
.panel-body,
.table,
.dataTables_wrapper,
.dropdown-menu,
.dropdown-right {
color: var(--color-text-primary) !important;
}
.text-muted,
.text-secondary,
.text-tertiary {
color: var(--color-text-secondary) !important;
opacity: 1 !important;
}
.ots-sidebar a,
.ots-sidebar .nav-item,
.ots-sidebar .nav-label,
.ots-sidebar .nav-text {
color: var(--color-text-primary) !important;
}
a,
.nav-link {
color: var(--color-text-primary);
}
a:hover,
.nav-link:hover {
color: var(--color-primary);
}
/* ============================================================================
COMPREHENSIVE DARK THEME ENFORCEMENT
Ensure all elements have readable contrast and dark backgrounds
============================================================================ */
/* Force ALL text to be readable - master override */
* {
color-scheme: dark;
}
/* Ensure headings are always visible */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
color: var(--color-text-primary) !important;
}
/* All labels must be readable */
/* Strong override: force sidebar items to show icon then text (left-aligned) — expanded only */
#sidebar-wrapper:not(.collapsed) .sidebar-list a,
#sidebar-wrapper:not(.collapsed) .sidebar-main a,
.ots-sidebar:not(.collapsed) .sidebar-group-toggle,
.ots-sidebar:not(.collapsed) .sidebar-list > a {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
gap: 8px !important;
white-space: nowrap !important;
}
.ots-sidebar:not(.collapsed) .ots-nav-icon,
#sidebar-wrapper:not(.collapsed) .sidebar-list .ots-nav-icon,
#sidebar-wrapper:not(.collapsed) .sidebar-main .ots-nav-icon {
display: inline-flex !important;
width: 24px !important;
height: 24px !important;
margin-right: 8px !important;
margin-left: 0 !important;
text-align: center !important;
vertical-align: middle !important;
}
/* Override: when collapsed, center icons — must follow expanded rules above */
#sidebar-wrapper.ots-sidebar.collapsed .ots-nav-icon,
#sidebar-wrapper.collapsed .sidebar-list .ots-nav-icon,
#sidebar-wrapper.collapsed .sidebar-main .ots-nav-icon {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 20px !important;
height: 20px !important;
font-size: 20px !important;
color: var(--ots-sidebar-link) !important;
line-height: 1 !important;
margin: 0 !important;
padding: 0 !important;
text-indent: 0 !important;
text-align: center !important;
opacity: 1 !important;
}
.ots-sidebar .ots-nav-text,
#sidebar-wrapper .sidebar-list .ots-nav-text {
display: inline-block !important;
flex: 1 1 auto !important;
order: 2 !important;
}
.ots-sidebar .ots-nav-icon { order: 1 !important; }
/* Ensure group caret stays to the far right */
.sidebar-group-caret { margin-left: 12px !important; order: 3 !important; }
/* Safety: collapse any grid-template overrides */
.ots-sidebar .sidebar-group-toggle, .ots-sidebar .sidebar-list > a { grid-template-columns: none !important; }
/* Reduce submenu left border padding so text fits better */
.sidebar-submenu { padding-left: 8px !important; }
label,
.label,
.form-label,
legend {
color: var(--color-text-primary) !important;
}
/* Dropdowns, modals, and popovers */
.dropdown-menu,
.popover {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
/* Dropdown toggles: only style those NOT inside tables or topbar.
Table action buttons should inherit their row background.
Topbar nav links have their own styling. */
.dropdown-toggle:not(table .dropdown-toggle):not(.ots-table-card .dropdown-toggle):not(.ots-topbar .dropdown-toggle):not(.navbar-nav .dropdown-toggle) {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
/* DataTable row action buttons — no background box */
.ots-table-card .dropdown-toggle,
table .btn-group .dropdown-toggle,
.dataTables_wrapper .dropdown-toggle {
background-color: transparent !important;
border: none !important;
}
.modal,
.modal-body,
.modal-footer {
background-color: transparent !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.modal-content {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.modal-backdrop,
.modal-backdrop.show,
.modal-backdrop.in {
background-color: rgba(0, 0, 0, 0.3) !important;
backdrop-filter: blur(4px) !important;
opacity: 1 !important;
}
.modal-header {
background-color: var(--color-surface-elevated) !important;
border-bottom: 1px solid var(--color-border) !important;
}
.dropdown-menu a,
.dropdown-item {
color: var(--color-text-primary) !important;
}
.dropdown-menu a:hover,
.dropdown-item:hover {
background-color: rgba(59, 130, 246, 0.12) !important;
color: var(--color-primary) !important;
}
/* Ensure all pop-up/dialog surfaces follow theme variables (light/dark toggle) */
.modal,
.modal-content,
.modal-header,
.modal-body,
.modal-footer,
.popover,
.popover .popover-body,
.tooltip,
.tooltip .tooltip-inner,
.dropdown-menu,
.select2-dropdown,
.select2-container--default .select2-dropdown {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
box-shadow: var(--shadow-base, 0 6px 18px rgba(0,0,0,0.08)) !important;
}
/* Elevated headers inside modals should use elevated surface */
.modal-header {
background-color: var(--color-surface-elevated) !important;
border-bottom: 1px solid var(--color-border) !important;
}
/* Tooltips */
.tooltip .tooltip-inner {
background-color: var(--color-text-primary) !important;
color: var(--color-background) !important;
border-radius: 6px !important;
}
/* Select2 open containers must sit above the editor modal (z-index 1201) */
.select2-container--open {
z-index: 99999 !important;
}
.select2-container--open .select2-dropdown {
z-index: 99999 !important;
}
/* Select2 dropdowns and choices */
.select2-container--default .select2-results__option[aria-selected=true],
.select2-container--default .select2-results__option--highlighted {
background-color: rgba(var(--color-primary-rgb, 37,99,235), 0.12) !important;
}
/* Modal backdrop should be lighter in light mode */
.modal-backdrop,
.modal-backdrop.show,
.modal-backdrop.in {
background-color: rgba(0,0,0,0.3) !important;
}
body.ots-light-mode .modal-backdrop,
body.ots-light-mode .modal-backdrop.show,
body.ots-light-mode .modal-backdrop.in {
background-color: rgba(0,0,0,0.06) !important;
}
/* Ensure form elements are dark and readable */
.form-group,
.form-check,
.input-group {
color: var(--color-text-primary) !important;
}
input,
textarea,
select,
.form-control,
.form-select {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
input::placeholder,
textarea::placeholder {
color: var(--color-text-secondary) !important;
}
input:focus,
textarea:focus,
select:focus {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border-color: var(--color-primary) !important;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
}
/* Alerts and messages */
.alert,
.alert-info,
.alert-warning,
.alert-success,
.alert-danger,
.alert-light {
background-color: var(--color-surface) !important;
border: 1px solid var(--color-border) !important;
color: var(--color-text-primary) !important;
}
.alert-light {
background-color: var(--color-surface-elevated) !important;
}
/* Tooltips and help text */
.tooltip,
.tooltip-inner,
.help-block,
.form-text,
small {
color: var(--color-text-secondary) !important;
background-color: transparent !important;
}
/* Breadcrumbs */
.breadcrumb {
background-color: transparent !important;
color: var(--color-text-primary) !important;
}
.breadcrumb a {
color: var(--color-primary) !important;
}
.breadcrumb-item.active {
color: var(--color-text-secondary) !important;
}
/* Pagination */
.pagination,
.pager {
background-color: transparent !important;
}
.pagination a,
.pagination button,
.pager a {
color: var(--color-text-primary) !important;
background-color: transparent !important;
border: 1px solid var(--color-border) !important;
}
.pagination a:hover,
.pagination button:hover,
.pager a:hover {
background-color: var(--color-surface) !important;
color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
}
.pagination .active a,
.pagination .active button,
.pager .active a {
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
color: white !important;
}
/* Disabled state */
[disabled],
:disabled,
.disabled {
opacity: 0.6 !important;
color: var(--color-text-secondary) !important;
}
/* Badge customization */
.badge,
.badge-default {
background-color: var(--color-surface-elevated) !important;
color: var(--color-text-primary) !important;
}
/* List groups */
.list-group,
.list-group-item {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.list-group-item:hover {
background-color: var(--color-surface-elevated) !important;
}
.list-group-item.active {
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
color: white !important;
}
/* Tabs */
.nav-tabs,
.nav-pills {
background-color: transparent !important;
}
.nav-tabs .nav-link,
.nav-pills .nav-link {
color: var(--color-text-secondary) !important;
background-color: transparent !important;
}
.nav-tabs .nav-link:hover,
.nav-pills .nav-link:hover {
color: var(--color-text-primary) !important;
background-color: rgba(59, 130, 246, 0.1) !important;
}
.nav-tabs .nav-link.active,
.nav-pills .nav-link.active {
color: white !important;
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
}
/* --- Editor properties-panel tabs — override global .nav-tabs rules ---
Uses extremely high specificity to beat compiled CMS bundle styles.
The bundle uses `.form-container .nav>li>a { background: #fff !important }`
so we must beat that with ID-based selectors + !important.
----------------------------------------------------------------------- */
/* Tab bar container */
#properties-panel .nav,
#properties-panel .nav-tabs,
#properties-panel .nav-pills,
.properties-panel-container #properties-panel .nav,
.properties-panel-container #properties-panel .nav-tabs {
background-color: var(--editor-header-bg) !important;
border-bottom: 1px solid var(--editor-border) !important;
border-top: none !important;
border-left: none !important;
border-right: none !important;
}
/* All tab links — covers both .nav-link and .nav>li>a patterns */
#properties-panel .form-container .nav > li > a,
#properties-panel .nav > li > a,
#properties-panel .nav .nav-link,
#properties-panel .nav-tabs .nav-link,
#properties-panel .nav-tabs .nav-item .nav-link,
#properties-panel .nav-tabs .nav-item > a,
.properties-panel-container #properties-panel .form-container .nav > li > a,
.properties-panel-container #properties-panel .nav .nav-link,
.properties-panel-container #properties-panel .nav-tabs .nav-link {
color: var(--editor-text-secondary) !important;
background-color: var(--editor-header-bg) !important;
background-image: none !important;
background: var(--editor-header-bg) !important;
border: none !important;
border-color: transparent !important;
border-radius: 0 !important;
box-shadow: none !important;
opacity: 1 !important;
outline: none !important;
}
/* Tab links hover */
#properties-panel .form-container .nav > li > a:hover,
#properties-panel .nav > li > a:hover,
#properties-panel .nav .nav-link:hover,
#properties-panel .nav-tabs .nav-link:hover,
#properties-panel .nav-tabs .nav-item .nav-link:hover,
#properties-panel .nav-tabs .nav-item > a:hover,
.properties-panel-container #properties-panel .form-container .nav > li > a:hover,
.properties-panel-container #properties-panel .nav .nav-link:hover,
.properties-panel-container #properties-panel .nav-tabs .nav-link:hover {
color: var(--editor-text) !important;
background-color: var(--editor-header-bg) !important;
background: var(--editor-header-bg) !important;
border: none !important;
border-color: transparent !important;
}
/* Active tab */
#properties-panel .form-container .nav > li > a.active,
#properties-panel .form-container .nav > li > a.active:hover,
#properties-panel .nav > li > a.active,
#properties-panel .nav > li > a.active:hover,
#properties-panel .nav .nav-link.active,
#properties-panel .nav .nav-link.active:hover,
#properties-panel .nav-tabs .nav-link.active,
#properties-panel .nav-tabs .nav-link.active:hover,
#properties-panel .nav-tabs .nav-item .nav-link.active,
#properties-panel .nav-tabs .nav-item > a.active,
.properties-panel-container #properties-panel .form-container .nav > li > a.active,
.properties-panel-container #properties-panel .form-container .nav > li > a.active:hover,
.properties-panel-container #properties-panel .nav .nav-link.active,
.properties-panel-container #properties-panel .nav-tabs .nav-link.active {
color: var(--color-primary) !important;
background-color: var(--editor-header-bg) !important;
background: var(--editor-header-bg) !important;
border: none !important;
border-color: transparent !important;
border-bottom: 2px solid var(--color-primary) !important;
}
/* Icons inside tab links (e.g. positioning tab) */
#properties-panel .nav-tabs .nav-link i,
#properties-panel .nav .nav-link i,
#properties-panel .nav > li > a i,
.properties-panel-container #properties-panel .nav-tabs .nav-link i {
color: inherit !important;
}
/* Properties panel containers */
#properties-panel #properties-panel-form-container,
.properties-panel-container #properties-panel #properties-panel-form-container {
background-color: var(--editor-modal-content-bg) !important;
background: var(--editor-modal-content-bg) !important;
color: var(--editor-text) !important;
}
#properties-panel .form-container,
#properties-panel #properties-panel-form-container .form-container,
.properties-panel-container #properties-panel .form-container {
background-color: var(--editor-modal-content-bg) !important;
background: var(--editor-modal-content-bg) !important;
color: var(--editor-text) !important;
}
#properties-panel .form-title,
.properties-panel-container #properties-panel .form-title {
color: var(--editor-text) !important;
background-color: var(--editor-header-bg) !important;
}
#properties-panel .button-container,
.properties-panel-container #properties-panel .button-container {
background-color: var(--editor-header-bg) !important;
}
#properties-panel .tab-content,
#properties-panel #properties-panel-form-container .tab-content,
.properties-panel-container #properties-panel .tab-content {
background-color: var(--editor-modal-content-bg) !important;
background: var(--editor-modal-content-bg) !important;
color: var(--editor-text) !important;
}
#properties-panel .tab-pane,
#properties-panel #properties-panel-form-container .tab-pane,
.properties-panel-container #properties-panel .tab-pane {
background-color: var(--editor-modal-content-bg) !important;
background: var(--editor-modal-content-bg) !important;
color: var(--editor-text) !important;
}
/* Cards */
.card {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.card-header {
background-color: var(--color-surface-elevated) !important;
border-bottom: 1px solid var(--color-border) !important;
color: var(--color-text-primary) !important;
}
.card-footer {
background-color: var(--color-surface-elevated) !important;
border-top: 1px solid var(--color-border) !important;
color: var(--color-text-secondary) !important;
}
/* Progress bars */
.progress {
background-color: var(--color-surface-elevated) !important;
}
.progress-bar {
background-color: var(--color-primary) !important;
}
/* Ensure code blocks are readable */
code,
.code,
pre {
background-color: var(--color-surface-elevated) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
/* DataTables specific overrides */
.dataTables_wrapper {
color: var(--color-text-primary) !important;
}
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
background-color: transparent !important;
color: var(--color-text-primary) !important;
}
.dataTables_wrapper table tbody tr {
color: var(--color-text-primary) !important;
}
.dataTables_wrapper table tbody tr:hover {
background-color: rgba(59, 130, 246, 0.08) !important;
}
/* Spinner/loading indicators */
.spinner,
.spinner-border,
.spinner-grow {
border-color: rgba(255, 255, 255, 0.25) !important;
}
.spinner-border.text-primary,
.spinner-grow.text-primary {
color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
}
/* Links should always be visible and contrasting */
a {
color: var(--color-primary) !important;
text-decoration: none;
}
a:hover {
color: var(--color-primary-light) !important;
text-decoration: underline;
}
a.text-muted {
color: var(--color-text-secondary) !important;
}
/* Folder tree icons - tan color like Windows Explorer */
#container-folder-tree .fa,
#grid-folder-filter .fa,
.grid-folder-tree-container .fa {
color: #D4AF85 !important;
font-size: 1.5em !important;
}
/* Folder action button icon - match folder tree tan color */
#folder-tree-select-folder-button .fa,
#folder-tree-select-folder-button .fas {
color: #D4AF85 !important;
}
/* Tidy (library) button - broom icon and amber colouring */
.btn-tidy {
background-color: var(--color-warning) !important;
border-color: rgba(0,0,0,0.08) !important;
color: var(--color-on-primary) !important;
}
.btn-tidy .fa,
.btn-tidy .fas,
.btn-tidy .far {
color: var(--color-on-primary) !important;
}
/* Slightly darker hover for contrast (fallback where color-mix isn't available) */
.btn-tidy:hover {
filter: brightness(0.95) !important;
color: var(--color-on-primary) !important;
}
/* Ensure inline SVG broom inherits the tidy button colour and sizes nicely */
.btn-tidy svg.icon-broom,
.btn-tidy svg.icon-broom-pantry {
width: 18px !important;
height: 18px !important;
display: inline-block !important;
vertical-align: middle !important;
fill: currentColor !important;
}
a.text-muted:hover {
color: var(--color-text-primary) !important;
}
/* Ensure absolutely nothing is invisible */
.hidden,
[hidden] {
display: none !important;
}
.invisible {
visibility: hidden !important;
}
/* ============================================================================
FILTER FIELDS PADDING
============================================================================ */
.FilterDiv.card-body {
padding-top: 20px !important;
}
/* ============================================================================
LOGO WITH TEXT STYLING
============================================================================ */
.navbar-brand.xibo-logo-container {
display: flex;
align-items: center;
gap: 10px;
padding: 0;
margin-right: 12px;
height: 67px;
}
.xibo-logo-text {
color: var(--color-text-primary);
font-size: 18px;
font-weight: 600;
margin: 0;
white-space: nowrap;
}
/* Strong final light-mode table overrides (high specificity & !important)
Placed at file end to ensure highest precedence over earlier dark rules. */
body.ots-light-mode .table,
body.ots-light-mode .dataTable,
body.ots-light-mode .dataTables_wrapper,
body.ots-light-mode .ots-table-card .table,
body.ots-light-mode .ots-table-card .dataTables_wrapper {
color: var(--color-text-primary) !important;
background-color: transparent !important;
opacity: 1 !important;
}
body.ots-light-mode .table thead th,
body.ots-light-mode .dataTable thead th,
body.ots-light-mode .ots-table-card .table thead th {
color: var(--color-text-secondary) !important;
background-color: var(--color-surface) !important;
opacity: 1 !important;
}
body.ots-light-mode .table tbody td,
body.ots-light-mode .dataTable tbody td,
body.ots-light-mode .ots-table-card .table tbody td {
color: var(--color-text-primary) !important;
opacity: 1 !important;
}
body.ots-light-mode .table tbody tr,
body.ots-light-mode .dataTable tbody tr,
body.ots-light-mode .ots-table-card .table tbody tr {
background: transparent !important;
}
body.ots-light-mode .table tbody tr:nth-child(even),
body.ots-light-mode .dataTable tbody tr:nth-child(even),
body.ots-light-mode .ots-table-card .table tbody tr:nth-child(even) {
background: var(--color-surface-elevated) !important;
}
body.ots-light-mode .table tbody tr:hover,
body.ots-light-mode .dataTable tbody tr:hover,
body.ots-light-mode .ots-table-card .table tbody tr:hover {
background: rgba(37, 99, 235, 0.06) !important;
}
/* Ensure disabled/low-contrast states do not dim important table text */
body.ots-light-mode .table [disabled],
body.ots-light-mode .table .disabled,
body.ots-light-mode .table :disabled {
opacity: 1 !important;
color: var(--color-text-secondary) !important;
}
/* Target Xibo-specific table selectors that used light colors with !important */
body.ots-light-mode .ots-displays-page #datatable-container .XiboData .table thead th,
body.ots-light-mode .ots-displays-page #datatable-container .XiboData table.dataTable thead th {
color: var(--color-text-secondary) !important;
background-color: var(--color-surface) !important;
}
body.ots-light-mode .ots-displays-page #datatable-container .XiboData .table tbody td,
body.ots-light-mode .ots-displays-page #datatable-container .XiboData table.dataTable tbody td {
color: var(--color-text-primary) !important;
opacity: 1 !important;
}
/* Also ensure any `.text-muted` or tertiary text inside tables becomes readable in light-mode */
body.ots-light-mode .table thead th .text-muted,
body.ots-light-mode .table tbody td .text-muted,
body.ots-light-mode .ots-table-card .table thead th .text-muted {
color: var(--color-text-tertiary) !important;
opacity: 1 !important;
}
/* Override the hardcoded #e2e8f0 colors from lines 2659 & 2673 in light-mode
by matching exact selectors with body.ots-light-mode prefix */
body.ots-light-mode .ots-displays-page #datatable-container .XiboData .table,
body.ots-light-mode .ots-displays-page #datatable-container .XiboData table.dataTable {
color: var(--color-text-primary) !important;
}
body.ots-light-mode .ots-displays-page #datatable-container .XiboData .table tbody td,
body.ots-light-mode .ots-displays-page #datatable-container .XiboData table.dataTable tbody td {
color: var(--color-text-primary) !important;
opacity: 1 !important;
}
/* Ensure all table cells and text are dark in light-mode */
body.ots-light-mode .ots-displays-page #datatable-container .XiboData .table tr,
body.ots-light-mode .ots-displays-page #datatable-container .XiboData table.dataTable tr {
color: var(--color-text-primary) !important;
}
/* Card hover behavior is handled in override-styles.twig (loaded last) */
/* Ensure the very bottom of the page follows the theme variables (light/dark)
by forcing html/body and shell containers to use the variable-driven
background. This prevents residual dark bars under the footer. */
html,
body,
.ots-shell,
#page-wrapper {
min-height: 100% !important;
background-color: var(--color-background) !important;
}
/* Repair: remove any visible divider/seam between sidebar and main content
Some themes add a border or pseudo-element that creates a dark vertical bar.
Force those to be transparent/none so the content sits flush. */
.ots-sidebar,
#sidebar-wrapper {
border-right: none !important;
box-shadow: none !important;
}
/* Hide common pseudo-elements used as dividers or overlays */
.ots-sidebar::after,
.ots-sidebar::before,
#page-wrapper::before,
#page-wrapper::after,
.ots-main::before,
.ots-main::after {
content: none !important;
display: none !important;
background: transparent !important;
box-shadow: none !important;
}
.ots-footer {
background-color: var(--color-surface-elevated) !important;
color: var(--color-text-primary) !important;
}
/* Content area tracks the sidebar width — SIDEBAR MODE ONLY.
The expanded value comes from --ots-sidebar-actual-width (measured).
The collapsed value comes from body.ots-sidebar-collapsed overrides.
Scoped to #page-wrapper which only exists in sidebar mode. */
#page-wrapper #content-wrapper,
#page-wrapper .ots-main {
margin-left: var(--ots-sidebar-actual-width, var(--ots-sidebar-width)) !important;
width: calc(100vw - var(--ots-sidebar-actual-width, var(--ots-sidebar-width))) !important;
max-width: calc(100vw - var(--ots-sidebar-actual-width, var(--ots-sidebar-width))) !important;
transition: margin-left 200ms ease, width 200ms ease, max-width 200ms ease;
overflow-x: hidden !important;
box-sizing: border-box !important;
}
body.ots-sidebar-collapsed #page-wrapper #content-wrapper,
body.ots-sidebar-collapsed #page-wrapper .ots-main,
html.ots-sidebar-collapsed #page-wrapper #content-wrapper,
html.ots-sidebar-collapsed #page-wrapper .ots-main,
body.ots-sidebar-collapsed #content-wrapper,
body.ots-sidebar-collapsed .ots-main,
html.ots-sidebar-collapsed #content-wrapper,
html.ots-sidebar-collapsed .ots-main {
margin-left: var(--ots-sidebar-collapsed-width) !important;
width: calc(100vw - var(--ots-sidebar-collapsed-width)) !important;
max-width: calc(100vw - var(--ots-sidebar-collapsed-width)) !important;
}
/* No-nav pages (layout designer, etc.) — remove all sidebar spacing */
#content-wrapper.no-nav,
#content-wrapper.no-nav.active,
body.ots-playlist-editor-active #content-wrapper {
margin-left: 0 !important;
width: 100% !important;
max-width: 100% !important;
padding: 0 !important;
}
#content-wrapper.no-nav .page-content,
body.ots-playlist-editor-active #content-wrapper .page-content {
padding: 0 !important;
margin: 0 !important;
}
#content-wrapper.no-nav .page-content .row,
body.ots-playlist-editor-active #content-wrapper .page-content .row {
margin: 0 !important;
padding: 0 !important;
}
#content-wrapper.no-nav .page-content [class*="col-"],
body.ots-playlist-editor-active #content-wrapper .page-content [class*="col-"] {
margin: 0 !important;
padding: 0 !important;
}
/* Emergency: force root/background pseudo-elements to follow theme variables
This clears any leftover background-images or pseudo-element fills that
can create a dark bar at the bottom. */
html, html:before, html:after,
body, body:before, body:after,
.ots-shell, #page-wrapper, #page-wrapper:before, #page-wrapper:after {
background-image: none !important;
background-color: var(--color-background) !important;
color: var(--color-text-primary) !important;
min-height: 100vh !important;
}
/* Remove any content on pseudo-elements that might draw a dark strip */
html:before, html:after, body:before, body:after, #page-wrapper:before, #page-wrapper:after {
content: none !important;
}
/* ============================================================================
COMPREHENSIVE LIGHT-MODE TABLE OVERRIDES (Final Pass)
Force all table colors to be light-background + dark-text in light mode
============================================================================ */
body.ots-light-mode .table,
body.ots-light-mode .table thead,
body.ots-light-mode .table tbody,
body.ots-light-mode .table thead th,
body.ots-light-mode .table tbody td,
body.ots-light-mode .table tbody tr,
body.ots-light-mode .dataTables_wrapper,
body.ots-light-mode .dataTables_wrapper table,
body.ots-light-mode .dataTables_wrapper thead,
body.ots-light-mode .dataTables_wrapper thead th,
body.ots-light-mode .dataTables_wrapper tbody,
body.ots-light-mode .dataTables_wrapper tbody td,
body.ots-light-mode .dataTables_wrapper tbody tr,
body.ots-light-mode .modern-table,
body.ots-light-mode .modern-table thead,
body.ots-light-mode .modern-table thead th,
body.ots-light-mode .modern-table tbody,
body.ots-light-mode .modern-table tbody tr,
body.ots-light-mode .modern-table tbody td {
color: var(--color-text-primary) !important;
background-color: transparent !important;
opacity: 1 !important;
}
body.ots-light-mode .table thead th,
body.ots-light-mode .dataTables_wrapper thead th,
body.ots-light-mode .modern-table thead th {
background-color: var(--color-surface-elevated) !important;
color: var(--color-text-secondary) !important;
}
body.ots-light-mode .table tbody tr:nth-child(even),
body.ots-light-mode .dataTables_wrapper tbody tr:nth-child(even),
body.ots-light-mode .modern-table tbody tr:nth-child(even) {
background-color: var(--color-surface-elevated) !important;
}
body.ots-light-mode .table tbody tr:hover,
body.ots-light-mode .dataTables_wrapper tbody tr:hover,
body.ots-light-mode .modern-table tbody tr:hover {
background-color: rgba(37, 99, 235, 0.06) !important;
}
body.ots-light-mode .dataTables_wrapper .dataTables_info,
body.ots-light-mode .dataTables_wrapper .dataTables_length,
body.ots-light-mode .dataTables_wrapper .dataTables_filter,
body.ots-light-mode .dataTables_wrapper .dataTables_paginate {
color: var(--color-text-primary) !important;
}
body.ots-light-mode .dataTables_wrapper .dataTables_filter input,
body.ots-light-mode .dataTables_wrapper .dataTables_length select {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border-color: var(--color-border) !important;
}
body.ots-light-mode .dataTables_wrapper .dataTables_paginate .paginate_button {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border-color: var(--color-border) !important;
}
body.ots-light-mode .dataTables_wrapper .dataTables_paginate .paginate_button.current {
background-color: var(--color-primary) !important;
color: white !important;
border-color: var(--color-primary) !important;
}
/* Light-mode unconditional overrides to ensure table text is readable */
body.ots-light-mode .table td,
body.ots-light-mode .table th,
body.ots-light-mode .dataTable td,
body.ots-light-mode .dataTable th,
body.ots-light-mode .dataTables_wrapper td,
body.ots-light-mode .dataTables_wrapper th,
body.ots-light-mode .modern-table td,
body.ots-light-mode .modern-table th {
color: #0f172a !important;
}
body.ots-light-mode .dataTables_wrapper .dataTables_info,
body.ots-light-mode .dataTables_wrapper .dataTables_filter,
body.ots-light-mode .dataTables_wrapper .dataTables_length {
color: #0f172a !important;
}
body.ots-light-mode .table thead,
body.ots-light-mode .dataTable thead,
body.ots-light-mode .modern-table thead {
background-color: #f1f5f9 !important;
}
body.ots-light-mode .dataTables_wrapper .dataTables_filter input,
body.ots-light-mode .dataTables_wrapper .dataTables_length select {
color: #0f172a !important;
background-color: #ffffff !important;
border-color: #e2e8f0 !important;
}
/* ── FINAL: collapsed sidebar icon centering ──────────────────────────
Placed last so it wins the cascade for same-specificity + !important.
Targets top-level clickable items only (not flyout submenu items).
Uses display:grid + place-items:center for bulletproof centering. */
#sidebar-wrapper.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list > a,
#sidebar-wrapper.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group > .sidebar-group-toggle,
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list > a,
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group > .sidebar-group-toggle {
display: grid !important;
place-items: center !important;
grid-template-columns: 1fr !important;
grid-template-rows: 1fr !important;
width: 40px !important;
height: 40px !important;
min-width: 40px !important;
max-width: 40px !important;
min-height: 40px !important;
max-height: 40px !important;
margin: 2px auto !important;
padding: 0 !important;
padding-left: 0 !important;
padding-right: 0 !important;
border: 0 !important;
border-left: 0 !important;
border-right: 0 !important;
float: none !important;
text-indent: 0 !important;
gap: 0 !important;
column-gap: 0 !important;
row-gap: 0 !important;
box-sizing: border-box !important;
line-height: 40px !important;
}
/* ── FINAL: ensure list containers are centered in collapsed state ───── */
#sidebar-wrapper.collapsed ul.sidebar,
#sidebar-wrapper.ots-sidebar.collapsed ul.sidebar,
#sidebar-wrapper.collapsed .ots-sidebar-nav,
#sidebar-wrapper.ots-sidebar.collapsed .ots-sidebar-nav {
padding-left: 0 !important;
padding-right: 0 !important;
margin-left: 0 !important;
margin-right: 0 !important;
list-style: none !important;
text-indent: 0 !important;
}
#sidebar-wrapper.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list,
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list,
#sidebar-wrapper.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group,
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group {
display: flex !important;
justify-content: center !important;
align-items: center !important;
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
text-indent: 0 !important;
float: none !important;
box-sizing: border-box !important;
}
/* =============================================================================
HORIZONTAL NAV — FINAL OVERRIDE (must be last in file to win cascade)
Applied when the top navbar is active and there is no sidebar.
============================================================================= */
.navbar.navbar-expand-lg ~ #content-wrapper,
nav.navbar + #content-wrapper {
margin-left: 0 !important;
padding-left: 20px !important;
padding-right: 20px !important;
width: 100% !important;
max-width: 100% !important;
}
.navbar.navbar-expand-lg ~ #content-wrapper .page-content,
nav.navbar + #content-wrapper .page-content {
padding-left: 0 !important;
padding-right: 0 !important;
}
.navbar.navbar-expand-lg ~ #content-wrapper .page-content .row,
nav.navbar + #content-wrapper .page-content .row {
margin-left: 0 !important;
margin-right: 0 !important;
}
.navbar.navbar-expand-lg ~ #content-wrapper .page-content [class*="col-"],
.navbar.navbar-expand-lg ~ #content-wrapper .page-content > .row > .col-sm-12,
nav.navbar + #content-wrapper .page-content [class*="col-"],
nav.navbar + #content-wrapper .page-content > .row > .col-sm-12 {
padding-left: 0 !important;
padding-right: 0 !important;
}
/* =============================================================================
HORIZONTAL NAV — CLASS-BASED OVERRIDE
.ots-horizontal-nav is added directly to #content-wrapper in authed.twig
when horizontal nav mode is active. No sibling combinators needed.
============================================================================= */
#content-wrapper.ots-horizontal-nav {
margin-left: 0 !important;
padding-left: 30px !important;
padding-right: 30px !important;
width: 100% !important;
max-width: 100% !important;
}
#content-wrapper.ots-horizontal-nav .page-content {
padding-left: 0 !important;
padding-right: 0 !important;
}
#content-wrapper.ots-horizontal-nav .page-content .row {
margin-left: 0 !important;
margin-right: 0 !important;
}
#content-wrapper.ots-horizontal-nav .page-content [class*="col-"],
#content-wrapper.ots-horizontal-nav .page-content > .row > .col-sm-12 {
padding-left: 0 !important;
padding-right: 0 !important;
}
/* =============================================================================
MODAL POP-UPS — Comprehensive Styles
Covers Bootstrap modals, Bootbox dialogs, confirmation prompts, and
AJAX-loaded form modals. All colours use --modal-* CSS variables so they
automatically follow dark / light mode.
============================================================================= */
/* ---------- Backdrop -------------------------------------------------------- */
.modal-backdrop,
.modal-backdrop.show,
.modal-backdrop.in,
.modal-backdrop.fade.in {
background-color: var(--modal-backdrop-bg) !important;
backdrop-filter: blur(var(--modal-backdrop-blur)) !important;
-webkit-backdrop-filter: blur(var(--modal-backdrop-blur)) !important;
opacity: 1 !important;
}
/* ---------- Dialog container ----------------------------------------------- */
.modal-dialog {
margin: 2rem auto;
padding: 0 16px;
}
/* Sizes */
.modal-dialog.modal-sm { max-width: 420px; }
.modal-dialog.modal-md { max-width: 600px; }
.modal-dialog:not(.modal-sm):not(.modal-lg):not(.modal-xl) { max-width: 600px; }
.modal-dialog.modal-lg { max-width: 820px; }
.modal-dialog.modal-xl { max-width: 1080px; }
/* ---------- Content wrapper ------------------------------------------------ */
.modal-content {
background-color: var(--modal-bg) !important;
border: 1px solid var(--modal-border) !important;
border-radius: var(--modal-radius) !important;
box-shadow: var(--modal-shadow) !important;
overflow: hidden;
color: var(--modal-body-text) !important;
}
/* Subtle entrance animation */
.modal.fade .modal-dialog {
transform: translateY(16px) scale(0.98);
transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1),
opacity 200ms ease;
}
.modal.fade.show .modal-dialog,
.modal.fade.in .modal-dialog {
transform: translateY(0) scale(1);
}
/* ---------- Header --------------------------------------------------------- */
.modal-header {
background-color: var(--modal-header-bg) !important;
border-bottom: 1px solid var(--modal-header-border) !important;
padding: 16px 20px !important;
display: flex;
align-items: center;
gap: 12px;
min-height: 56px;
}
.modal-title,
.modal-header h4,
.modal-header h5,
.modal-header .modal-title {
font-family: "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
font-size: 1rem;
font-weight: 600;
color: var(--modal-header-text) !important;
line-height: 1.4;
margin: 0;
letter-spacing: -0.01em;
}
/* Close button */
.modal-header .close,
.modal-header [data-dismiss="modal"],
.modal-header .btn-close {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
padding: 0 !important;
margin: 0 -4px 0 auto !important;
border: none !important;
border-radius: var(--ots-radius-sm) !important;
background: transparent !important;
color: var(--modal-close-color) !important;
font-size: 1.25rem;
line-height: 1;
opacity: 1 !important;
transition: background var(--ots-transition),
color var(--ots-transition);
cursor: pointer;
}
.modal-header .close:hover,
.modal-header [data-dismiss="modal"]:hover,
.modal-header .btn-close:hover {
background: rgba(255, 255, 255, 0.06) !important;
color: var(--modal-close-hover) !important;
}
body.ots-light-mode .modal-header .close:hover,
body.ots-light-mode .modal-header [data-dismiss="modal"]:hover,
body.ots-light-mode .modal-header .btn-close:hover {
background: rgba(0, 0, 0, 0.06) !important;
}
/* Close button "×" text reset */
.modal-header .close span,
.modal-header .close::before {
color: inherit !important;
text-shadow: none !important;
}
/* ---------- Body ----------------------------------------------------------- */
.modal-body {
background-color: var(--modal-body-bg) !important;
color: var(--modal-body-text) !important;
padding: 20px !important;
font-size: 0.9rem;
line-height: 1.6;
overflow-y: auto;
max-height: calc(100vh - 220px);
}
.modal-body p {
color: var(--modal-body-text);
margin-bottom: 12px;
}
.modal-body p:last-child {
margin-bottom: 0;
}
/* Help / description text inside modals */
.modal-body .form-text,
.modal-body .help-block,
.modal-body small.text-muted {
color: var(--ots-text-muted) !important;
font-size: 0.8rem;
}
/* ---------- Footer --------------------------------------------------------- */
.modal-footer {
background-color: var(--modal-footer-bg) !important;
border-top: 1px solid var(--modal-footer-border) !important;
padding: 12px 20px !important;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
}
/* Footer buttons — secondary / cancel */
.modal-footer .btn,
.modal-footer button {
font-family: "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
font-size: 0.85rem;
font-weight: 500;
padding: 8px 18px;
border-radius: var(--ots-radius-sm) !important;
border: 1px solid var(--modal-border) !important;
background: var(--modal-body-bg) !important;
color: var(--modal-body-text) !important;
box-shadow: none !important;
transition: background var(--ots-transition),
color var(--ots-transition),
border-color var(--ots-transition);
cursor: pointer;
}
.modal-footer .btn:hover,
.modal-footer button:hover {
background: rgba(79, 140, 255, 0.08) !important;
border-color: var(--ots-primary) !important;
color: var(--ots-primary) !important;
}
/* Footer buttons — primary / submit */
.modal-footer .btn-primary,
.modal-footer .btn.btn-primary,
.modal-footer button.btn-primary {
background: var(--ots-primary) !important;
color: #0b1020 !important;
border-color: var(--ots-primary) !important;
font-weight: 600;
}
.modal-footer .btn-primary:hover,
.modal-footer .btn.btn-primary:hover {
background: var(--color-primary-dark, #1d4ed8) !important;
color: #ffffff !important;
border-color: var(--color-primary-dark, #1d4ed8) !important;
}
/* Footer buttons — success */
.modal-footer .btn-success {
background: var(--ots-success, #10b981) !important;
color: #0b1020 !important;
border-color: var(--ots-success, #10b981) !important;
}
.modal-footer .btn-success:hover {
filter: brightness(0.9);
}
/* Footer buttons — danger / delete */
.modal-footer .btn-danger {
background: var(--ots-danger, #ef4444) !important;
color: #ffffff !important;
border-color: var(--ots-danger, #ef4444) !important;
}
.modal-footer .btn-danger:hover {
filter: brightness(0.9);
}
/* Footer buttons — warning */
.modal-footer .btn-warning {
background: var(--ots-warning, #f59e0b) !important;
color: #0b1020 !important;
border-color: var(--ots-warning, #f59e0b) !important;
}
.modal-footer .btn-warning:hover {
filter: brightness(0.9);
}
/* ---------- Form controls inside modals ------------------------------------ */
.modal-body .form-control,
.modal-body input[type="text"],
.modal-body input[type="number"],
.modal-body input[type="email"],
.modal-body input[type="password"],
.modal-body input[type="search"],
.modal-body input[type="url"],
.modal-body textarea,
.modal-body select {
background-color: var(--modal-input-bg) !important;
border: 1px solid var(--modal-input-border) !important;
border-radius: var(--ots-radius-sm) !important;
color: var(--modal-input-text) !important;
padding: 8px 12px;
font-size: 0.875rem;
transition: border-color var(--ots-transition),
box-shadow var(--ots-transition),
background-color var(--ots-transition);
}
.modal-body .form-control:focus,
.modal-body input:focus,
.modal-body textarea:focus,
.modal-body select:focus {
border-color: var(--modal-input-focus-border) !important;
box-shadow: 0 0 0 3px var(--modal-input-focus-ring) !important;
outline: none !important;
}
.modal-body .form-control::placeholder,
.modal-body input::placeholder,
.modal-body textarea::placeholder {
color: var(--ots-text-faint, #64748b) !important;
}
/* Labels inside modal forms */
.modal-body label,
.modal-body .control-label {
color: var(--modal-header-text) !important;
font-size: 0.85rem;
font-weight: 500;
margin-bottom: 4px;
}
/* Form groups spacing */
.modal-body .form-group {
margin-bottom: 16px;
}
/* Select2 inside modals */
.modal-body .select2-container--default .select2-selection--single,
.modal-body .select2-container--default .select2-selection--multiple {
background-color: var(--modal-input-bg) !important;
border: 1px solid var(--modal-input-border) !important;
border-radius: var(--ots-radius-sm) !important;
color: var(--modal-input-text) !important;
min-height: 36px;
}
.modal-body .select2-container--default .select2-selection--single .select2-selection__rendered {
color: var(--modal-input-text) !important;
}
.modal-body .select2-container--default .select2-selection--single:focus,
.modal-body .select2-container--default.select2-container--focus .select2-selection--multiple {
border-color: var(--modal-input-focus-border) !important;
box-shadow: 0 0 0 3px var(--modal-input-focus-ring) !important;
}
/* ---------- Bootstrap Tagsinput / Tokenfield inside modals ----------------- */
.modal-body .bootstrap-tagsinput,
.modal-body .tagsinput,
.modal-body .tokenfield {
background-color: var(--modal-input-bg) !important;
border: 1px solid var(--modal-input-border) !important;
border-radius: var(--ots-radius-sm) !important;
color: var(--modal-input-text) !important;
min-height: 36px;
padding: 4px 8px !important;
box-shadow: none !important;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 4px;
}
.modal-body .bootstrap-tagsinput:focus-within,
.modal-body .tagsinput:focus-within,
.modal-body .tokenfield:focus-within {
border-color: var(--modal-input-focus-border) !important;
box-shadow: 0 0 0 3px var(--modal-input-focus-ring) !important;
}
.modal-body .bootstrap-tagsinput input,
.modal-body .tagsinput input,
.modal-body .tokenfield input.token-input {
background: transparent !important;
color: var(--modal-input-text) !important;
border: none !important;
box-shadow: none !important;
outline: none !important;
margin: 0 !important;
padding: 2px 4px !important;
}
.modal-body .bootstrap-tagsinput input::placeholder,
.modal-body .tagsinput input::placeholder,
.modal-body .tokenfield input.token-input::placeholder {
color: var(--ots-text-faint, #64748b) !important;
}
.modal-body .bootstrap-tagsinput .tag,
.modal-body .bootstrap-tagsinput .badge,
.modal-body .tagsinput .tag,
.modal-body .tokenfield .token {
background: rgba(79, 140, 255, 0.15) !important;
border: 1px solid rgba(79, 140, 255, 0.3) !important;
color: var(--ots-primary, #3b82f6) !important;
border-radius: 999px !important;
padding: 2px 8px !important;
font-size: 0.8rem;
line-height: 1.5;
}
.modal-body .bootstrap-tagsinput .tag [data-role="remove"],
.modal-body .bootstrap-tagsinput .badge [data-role="remove"],
.modal-body .tokenfield .token .close {
color: var(--ots-primary, #3b82f6) !important;
opacity: 0.7;
margin-left: 4px;
cursor: pointer;
}
.modal-body .bootstrap-tagsinput .tag [data-role="remove"]:hover,
.modal-body .bootstrap-tagsinput .badge [data-role="remove"]:hover,
.modal-body .tokenfield .token .close:hover {
opacity: 1;
}
/* ---------- Tabs inside modals --------------------------------------------- */
.modal-body .nav-tabs {
border-bottom: 1px solid var(--modal-border) !important;
margin-bottom: 16px;
}
.modal-body .nav-tabs .nav-link,
.modal-body .nav-tabs > li > a {
color: var(--ots-text-muted) !important;
border: none !important;
border-bottom: 2px solid transparent !important;
padding: 8px 16px;
font-size: 0.85rem;
font-weight: 500;
transition: color var(--ots-transition),
border-color var(--ots-transition);
background: transparent !important;
}
.modal-body .nav-tabs .nav-link:hover,
.modal-body .nav-tabs > li > a:hover {
color: var(--modal-header-text) !important;
border-bottom-color: var(--ots-text-muted) !important;
}
.modal-body .nav-tabs .nav-link.active,
.modal-body .nav-tabs > li.active > a {
color: var(--ots-primary) !important;
border-bottom-color: var(--ots-primary) !important;
background: transparent !important;
}
.modal-body .tab-content {
background: transparent !important;
}
/* ---------- Alerts inside modals ------------------------------------------- */
.modal-body .alert {
border-radius: var(--ots-radius-sm);
padding: 12px 16px;
font-size: 0.85rem;
border: 1px solid;
}
.modal-body .alert-info {
background: rgba(79, 140, 255, 0.1);
border-color: rgba(79, 140, 255, 0.25);
color: var(--ots-info, #5ec0ff);
}
.modal-body .alert-warning {
background: rgba(244, 184, 96, 0.1);
border-color: rgba(244, 184, 96, 0.25);
color: var(--ots-warning, #f4b860);
}
.modal-body .alert-danger {
background: rgba(255, 107, 107, 0.1);
border-color: rgba(255, 107, 107, 0.25);
color: var(--ots-danger, #ff6b6b);
}
.modal-body .alert-success {
background: rgba(42, 212, 164, 0.1);
border-color: rgba(42, 212, 164, 0.25);
color: var(--ots-success, #2ad4a4);
}
/* ---------- Tables inside modals ------------------------------------------- */
.modal-body table,
.modal-body .table {
color: var(--modal-body-text) !important;
border-color: var(--modal-border) !important;
}
.modal-body table th {
background: var(--modal-header-bg) !important;
color: var(--modal-header-text) !important;
border-color: var(--modal-border) !important;
font-size: 0.8rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.modal-body table td {
border-color: var(--modal-border) !important;
color: var(--modal-body-text) !important;
}
.modal-body table tbody tr:hover {
background-color: rgba(79, 140, 255, 0.04) !important;
}
/* ---------- Checkbox / radio inside modals --------------------------------- */
.modal-body input[type="checkbox"],
.modal-body input[type="radio"] {
accent-color: var(--ots-primary);
}
/* ---------- Bootbox-specific overrides ------------------------------------- */
.bootbox .modal-content {
background-color: var(--modal-bg) !important;
border-color: var(--modal-border) !important;
}
.bootbox .bootbox-body {
color: var(--modal-body-text) !important;
font-size: 0.9rem;
line-height: 1.6;
}
/* Bootbox confirm icon area */
.bootbox .modal-body .bootbox-body p {
color: var(--modal-body-text) !important;
}
/* ---------- Folder tree modal ---------------------------------------------- */
#folder-tree-form-modal .modal-content {
background-color: var(--modal-bg) !important;
}
#folder-tree-form-modal .modal-body {
background-color: var(--modal-body-bg) !important;
}
/* ---------- Scrollbar inside modal bodies ---------------------------------- */
.modal-body::-webkit-scrollbar {
width: 6px;
}
.modal-body::-webkit-scrollbar-track {
background: transparent;
}
.modal-body::-webkit-scrollbar-thumb {
background: var(--ots-border, #2c3a54);
border-radius: 3px;
}
.modal-body::-webkit-scrollbar-thumb:hover {
background: var(--ots-text-faint, #64748b);
}
/* ---------- Stacked modals (z-index management) ---------------------------- */
.modal + .modal {
z-index: 1062;
}
.modal-backdrop + .modal-backdrop {
z-index: 1061;
}
/* ---------- Responsive ----------------------------------------------------- */
@media (max-width: 576px) {
.modal-dialog {
margin: 0.75rem auto;
padding: 0 8px;
}
.modal-dialog.modal-lg,
.modal-dialog.modal-xl {
max-width: calc(100vw - 16px);
}
.modal-header {
padding: 12px 16px !important;
}
.modal-body {
padding: 16px !important;
max-height: calc(100vh - 180px);
}
.modal-footer {
padding: 10px 16px !important;
flex-wrap: wrap;
}
.modal-footer .btn,
.modal-footer button {
flex: 1 1 auto;
min-width: 0;
}
}