Files
OTSSignsTheme/custom/otssignange/views/override-styles.twig
Matt Batchelder 86030cb881 Refactor toolbar buttons across various pages to unify styling
- Updated button classes for consistency in the playersoftware-page, playlist-page, resolution-page, schedule-page, settings-page, syncgroup-page, tag-page, task-page, template-page, transition-page, user-page, and usergroup-page.
- Removed unnecessary text from button titles and ensured all buttons have the 'ots-toolbar-btn' class for uniformity.
- Cleaned up the code by removing commented-out sections and ensuring proper indentation.
2026-02-07 14:50:40 -05:00

4079 lines
91 KiB
Twig
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-content-gap: 12px;
color-scheme: dark;
}
/* Page header - always visible and properly positioned */
.ots-main .page-header,
.ots-main .page-header h1,
.ots-main .page-header p.text-muted {
display: block !important;
visibility: visible !important;
}
.ots-main .page-header {
position: relative !important;
z-index: 100 !important;
height: auto !important;
padding-top: 16px !important;
padding-bottom: 16px !important;
margin-top: 8px !important;
margin-bottom: 12px !important;
}
.ots-main .page-header h1 {
color: var(--color-text-primary) !important;
}
.ots-main .page-header p.text-muted {
color: var(--color-text-tertiary) !important;
}
/* Prevent immediate container clipping near the top */
.ots-content,
.ots-main,
.page-content {
overflow: visible !important;
}
html,
body {
background-color: var(--color-background);
color: var(--color-text-primary);
}
/* ============================================================================
SHELL LAYOUT - SIDEBAR + MAIN
============================================================================ */
.ots-shell {
display: flex;
min-height: 100vh;
}
.ots-sidebar {
position: fixed;
left: 0;
top: 0;
width: var(--ots-sidebar-width);
height: 100vh;
background-color: #08132a;
border-right: none;
padding: 0;
display: flex;
flex-direction: column;
overflow-y: auto;
z-index: 1000;
}
.ots-main {
flex: 1;
display: flex;
flex-direction: column;
}
.ots-content {
flex: 1;
padding: 32px;
overflow-y: auto;
}
.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;
}
.ots-content {
color: var(--color-text-primary);
}
}
/* ============================================================================
SIDEBAR STYLES
============================================================================ */
.sidebar-header {
padding: 20px 16px;
border-bottom: 1px solid var(--color-border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.brand-link {
display: flex;
align-items: center;
gap: 16px;
color: var(--color-text-primary);
font-weight: 700;
font-size: 16px;
text-decoration: none;
flex: 1;
}
.brand-icon {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
flex-shrink: 0;
}
.sidebar-content {
flex: 1;
padding: 12px 0;
overflow-y: auto;
}
.sidebar-nav,
.ots-sidebar-nav {
list-style: none;
margin: 0;
padding: 4px 0 16px;
position: relative;
}
.ots-sidebar ul.sidebar.ots-sidebar-nav {
position: relative !important;
top: auto !important;
bottom: auto !important;
}
/* Ensure nav list starts below header in expanded/collapsed states */
.ots-sidebar.collapsed .ots-sidebar-nav,
.ots-sidebar-collapsed .ots-sidebar-nav {
padding-top: 4px !important;
padding-bottom: 16px !important;
}
.ots-sidebar:not(.collapsed) .ots-sidebar-nav {
padding-top: 4px !important;
}
.sidebar-nav li {
display: block;
}
/* Reset any fixed heights from base theme that cause overlapping */
.ots-sidebar .sidebar-list {
height: auto !important;
}
/* Expanded sidebar submenu styling (prevents overlap) */
.ots-sidebar .sidebar-submenu {
list-style: none;
margin: 4px 0 8px;
padding: 0 0 0 12px;
border-left: 1px solid var(--ots-sidebar-border);
display: none;
}
.ots-sidebar .sidebar-group.is-open .sidebar-submenu,
.ots-sidebar .sidebar-group-toggle[aria-expanded="true"] ~ .sidebar-submenu,
.ots-sidebar .sidebar-group-toggle[aria-expanded="true"] + .sidebar-submenu {
display: block !important;
}
.ots-sidebar .sidebar-submenu .sidebar-list {
margin: 0;
padding: 0;
}
.ots-sidebar .sidebar-submenu .sidebar-list > a {
display: flex;
align-items: center;
gap: 12px;
margin: 4px 0;
background: var(--ots-sidebar-submenu-bg);
width: 100%;
box-sizing: border-box;
padding: 8px 48px 8px 28px;
border-left: 4px solid var(--ots-sidebar-submenu-border);
border-radius: var(--ots-sidebar-item-radius);
color: var(--ots-sidebar-link);
font-weight: 500;
text-decoration: none;
min-height: var(--ots-sidebar-item-height);
}
.ots-sidebar .sidebar-submenu .sidebar-list > a:hover {
background: var(--ots-sidebar-submenu-hover-bg);
color: var(--ots-sidebar-link-hover-text);
}
/* 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: grid;
grid-template-columns: 24px 1fr;
align-items: center;
column-gap: 12px;
padding: 6px 10px;
color: #c8d5ee;
text-decoration: none;
transition: all var(--transition-fast);
position: relative;
font-size: 14px;
font-weight: 500;
border-left: 2px solid transparent;
margin: 3px 10px;
border-radius: 12px;
min-height: 40px;
line-height: 1.25;
}
.ots-sidebar li.sidebar-list > a:hover {
color: #ffffff;
background-color: rgba(255, 255, 255, 0.08);
}
.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: #0b1221;
background-color: #ffffff;
border-left-color: transparent;
font-weight: 600;
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.25);
}
/* Collapsed state - ensure active items remain visually distinct */
.ots-sidebar.collapsed li.sidebar-list.active > a,
.ots-sidebar.collapsed li.sidebar-list > a.active,
.ots-sidebar.collapsed li.sidebar-main.active > a,
.ots-sidebar.collapsed li.sidebar-main > a.active {
background-color: rgba(255, 255, 255, 0.12);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.06);
color: #ffffff;
}
.ots-sidebar .ots-nav-icon {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 16px;
color: currentColor;
justify-self: center;
}
.ots-sidebar .ots-nav-text {
font-size: 14px;
font-weight: 500;
flex: 1;
line-height: 1.2;
}
.ots-sidebar li.sidebar-title > a {
display: block;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
color: #8ea4c7;
letter-spacing: 0.12em;
padding: 12px 14px 4px;
margin: 8px 0 0;
min-height: auto;
line-height: 1;
}
.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);
}
.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 - DEEP ANALYSIS & MODERN OVERHAUL
============================================================================
Design decisions:
- 64px total height (44px content + 10px top/bottom padding) = consistent baseline
- All interactive elements are 40px (buttons, search height)
- Icon sizing: 20px container, 16px icon (scale-friendly)
- Consistent 16px gap spacing throughout
- Remove conflicting .navbar-nav rules
- Proper z-index layering for dropdowns
============================================================================ */
.ots-topbar {
background-color: transparent;
border-bottom: none;
padding: 0;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 4px;
height: 56px;
z-index: 1100;
position: relative;
width: auto;
flex: 1;
min-width: 0;
}
/* 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;
justify-content: flex-start;
flex-wrap: nowrap;
}
.ots-topbar .nav-item {
display: flex;
align-items: center;
height: 100%;
margin: 0 !important;
padding: 0 !important;
}
/* Brand stacking for 'OTS Signs' */
.xibo-logo-container {
display: flex;
align-items: center;
gap: 12px;
}
.xibo-logo-text {
display: inline-flex;
flex-direction: column;
line-height: 1;
}
.brand-line {
display: block;
margin: 0;
padding: 0;
}
.brand-line-top {
font-weight: 700;
font-size: 18px;
letter-spacing: 0.01em;
}
.brand-line-bottom {
font-weight: 600;
font-size: 13px;
opacity: 0.95;
margin-top: -2px;
}
.ots-topbar .nav-link {
display: inline-flex;
align-items: center;
height: 100%;
gap: 6px;
padding: 0 8px;
border-radius: 6px;
color: var(--color-text-secondary);
font-weight: 500;
font-size: 14px;
white-space: nowrap;
transition: all var(--transition-fast);
position: relative;
}
.ots-topbar .nav-link:hover {
background-color: rgba(59, 130, 246, 0.08);
color: var(--color-primary);
}
/* Ensure content is offset below the sticky topbar when horizontal nav present */
nav.navbar + #content-wrapper,
nav.navbar + #content-wrapper .page-content {
padding-top: 56px;
}
/* Right-side controls: notification bell + account menu */
.navbar-collapse .navbar-nav.navbar-right {
margin-left: auto;
display: flex;
align-items: center;
gap: 8px;
}
.navbar-collapse .navbar-nav.navbar-right > li {
display: flex;
align-items: center;
}
/* ============================================================================
TOPBAR STRIP (sidebar mode) - Clean, Modern Single-Line Menu Bar
============================================================================ */
/* The topbar strip is the bar at the top of the content area in sidebar mode.
Layout: [Logo (collapsed only)] ---- [notifications] [user] [hamburger] */
.ots-topbar-strip {
position: sticky !important;
top: 0 !important;
z-index: 1100 !important;
background-color: var(--color-surface-elevated) !important;
border-bottom: 1px solid var(--color-border) !important;
height: 56px !important;
min-height: 56px !important;
max-height: 56px !important;
margin: 0 !important;
padding: 0 !important;
overflow: visible !important;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08) !important;
}
/* When sidebar is expanded, make the topbar background subtler */
body:not(.ots-sidebar-collapsed) .ots-topbar-strip {
background-color: var(--color-background) !important;
box-shadow: none !important;
border-bottom-color: var(--color-border) !important;
}
/* Inner flex container */
.ots-topbar-inner {
display: flex !important;
align-items: center !important;
justify-content: space-between !important;
height: 56px !important;
padding: 0 16px !important;
margin: 0 !important;
gap: 12px !important;
overflow: visible !important;
}
/* Left side: logo (only visible when sidebar collapsed) */
.ots-topbar-left {
display: flex !important;
align-items: center !important;
gap: 12px !important;
flex-shrink: 0 !important;
min-width: 0 !important;
}
.ots-topbar-strip .xibo-logo-container {
display: flex !important;
align-items: center !important;
gap: 10px !important;
text-decoration: none !important;
}
.ots-topbar-strip .xibo-logo {
width: 28px !important;
height: 28px !important;
object-fit: contain !important;
}
.ots-topbar-strip .xibo-logo-text {
display: inline-flex !important;
flex-direction: column !important;
line-height: 1 !important;
}
.ots-topbar-strip .brand-line-top {
font-weight: 700 !important;
font-size: 15px !important;
color: var(--color-text-primary) !important;
letter-spacing: 0.02em !important;
}
.ots-topbar-strip .brand-line-bottom {
font-weight: 600 !important;
font-size: 11px !important;
color: var(--color-text-secondary) !important;
margin-top: -1px !important;
}
/* Right side: actions cluster */
.ots-topbar-right {
display: flex !important;
align-items: center !important;
gap: 4px !important;
flex-shrink: 0 !important;
margin-left: auto !important;
}
/* Each action item (notification bell, user avatar) */
.ots-topbar-action {
display: inline-flex !important;
align-items: center !important;
position: static !important;
}
.ots-topbar-action .nav-item,
.ots-topbar-action .dropdown,
.ots-topbar-action > div {
display: inline-flex !important;
align-items: center !important;
position: static !important;
}
/* Notification & user menu links */
.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-topbar-action .nav-link:hover {
background-color: rgba(59, 130, 246, 0.08) !important;
color: var(--color-primary) !important;
}
/* Bell icon */
.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;
}
/* Avatar in topbar */
.ots-topbar-action img.nav-avatar {
display: block !important;
width: 24px !important;
height: 24px !important;
border-radius: 50% !important;
object-fit: cover !important;
border: 1px solid transparent !important;
transition: border-color 150ms ease !important;
}
.ots-topbar-action .nav-link:hover img.nav-avatar {
border-color: var(--color-primary) !important;
}
/* Dropdown menus from the topbar */
.ots-topbar-action .dropdown-menu,
.ots-topbar-strip .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;
}
.ots-topbar-strip .dropdown-item,
.ots-topbar-strip .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-topbar-strip .dropdown-item:hover,
.ots-topbar-strip .dropdown-menu a:hover {
background-color: rgba(59, 130, 246, 0.08) !important;
color: var(--color-primary) !important;
}
.ots-topbar-strip .dropdown-header {
padding: 8px 14px 4px !important;
font-size: 12px !important;
font-weight: 600 !important;
color: var(--color-text-tertiary) !important;
text-transform: uppercase !important;
letter-spacing: 0.04em !important;
}
.ots-topbar-strip .dropdown-divider {
margin: 4px 0 !important;
border-top-color: var(--color-border) !important;
}
/* Hamburger button */
.ots-topbar-hamburger {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
width: 36px !important;
height: 36px !important;
padding: 0 !important;
border: none !important;
background: transparent !important;
color: var(--color-text-secondary) !important;
border-radius: 8px !important;
cursor: pointer !important;
transition: all 150ms ease !important;
font-size: 16px !important;
flex-shrink: 0 !important;
}
.ots-topbar-hamburger:hover {
background-color: rgba(59, 130, 246, 0.08) !important;
color: var(--color-primary) !important;
}
/* Ensure no clipping */
.ots-topbar-strip,
.ots-topbar-strip .col-sm-12,
.ots-topbar-strip .ots-topbar-right,
.ots-topbar-strip .ots-topbar-action {
overflow: visible !important;
}
/* When JS decides to open to the left (avoid viewport overflow) */
.dropdown-menu-left {
left: auto !important;
right: 0 !important;
}
/* When JS wants explicit left-aligned menu */
.dropdown-menu-left-align {
left: 0 !important;
right: auto !important;
}
/* Topbar strip responsive */
@media (max-width: 768px) {
.ots-topbar-strip {
height: 48px !important;
min-height: 48px !important;
max-height: 48px !important;
}
.ots-topbar-inner {
height: 48px !important;
padding: 0 12px !important;
gap: 8px !important;
}
.ots-topbar-strip .brand-line-top {
font-size: 13px !important;
}
.ots-topbar-strip .brand-line-bottom {
font-size: 10px !important;
}
.ots-topbar-strip .xibo-logo {
width: 24px !important;
height: 24px !important;
}
.ots-topbar-action .nav-link,
.ots-topbar-hamburger {
width: 32px !important;
height: 32px !important;
}
.ots-topbar-action img.nav-avatar {
width: 28px !important;
height: 28px !important;
}
}
/* Ensure sidebar items are visible and above header when sidebar is collapsed */
.ots-sidebar.collapsed {
z-index: 1200;
overflow: visible !important;
}
/* Allow flyout menus to escape the sidebar-content scroll container */
.ots-sidebar.collapsed .sidebar-content {
overflow: visible !important;
}
.ots-sidebar.collapsed .ots-nav-icon {
position: relative;
z-index: 100;
}
@media (max-width: 991px) {
/* When collapsed on small screens, allow the right nav to flow normally */
.navbar-collapse .navbar-nav.navbar-right {
margin-left: 0;
}
}
.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);
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: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
opacity: 0.9;
flex-shrink: 0;
}
.ots-topbar .dropdown-menu .ots-topbar-icon {
font-size: 13px;
}
/* Left section: toggle, title, nav */
.topbar-left {
display: flex;
align-items: center;
gap: 16px;
flex: 1;
min-width: 0;
}
.topbar-toggle {
display: none;
width: 40px;
height: 40px;
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 - 40px height to match button grid */
.topbar-search {
position: relative;
height: 40px;
width: 280px;
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 40px button sizing */
.topbar-btn {
width: 40px;
height: 40px;
min-width: 40px;
min-height: 40px;
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;
}
.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;
}
/* 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
============================================================================ */
/* 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;
}
/* Page header should always be visible - ensure this is displayed even when sidebar is collapsed */
body.ots-sidebar-collapsed .ots-main .page-header,
body.ots-sidebar-collapsed .page-header,
.page-header {
display: block !important;
margin-left: 0 !important;
margin-right: 0 !important;
margin-bottom: 16px !important;
padding-top: 16px !important;
padding-bottom: 16px !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: all var(--transition-base);
}
.kpi-card:hover {
border-color: var(--color-primary);
box-shadow: 0 0 0 1px var(--color-primary);
}
.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);
}
.dashboard-chart-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
}
.dashboard-chart-title {
display: flex;
align-items: center;
gap: 12px;
}
.dashboard-chart-icon {
width: 40px;
height: 40px;
border-radius: 12px;
background: rgba(59, 130, 246, 0.18);
color: var(--color-primary-light);
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
}
.dashboard-chart-heading {
margin: 0;
font-size: 16px;
font-weight: 700;
}
.dashboard-chart-subtitle {
margin: 4px 0 0;
font-size: 12px;
color: var(--color-text-secondary);
}
.dashboard-chart-link {
font-size: 12px;
font-weight: 600;
color: var(--color-primary);
text-decoration: none;
padding: 6px 10px;
border-radius: 999px;
border: 1px solid rgba(59, 130, 246, 0.24);
background: rgba(59, 130, 246, 0.12);
transition: all var(--transition-fast);
white-space: nowrap;
}
.dashboard-chart-link:hover {
color: var(--color-text-primary);
border-color: rgba(59, 130, 246, 0.5);
background: rgba(59, 130, 246, 0.22);
}
.dashboard-chart-body {
padding: 0 20px 20px;
}
.dashboard-chart-canvas {
background: rgba(15, 23, 42, 0.45);
border: 1px solid rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 12px;
height: 250px;
position: relative;
overflow: hidden;
}
.dashboard-chart-canvas canvas {
display: block;
width: 100% !important;
height: 100% !important;
max-width: 100% !important;
max-height: 100% !important;
margin: 0 !important;
}
.dashboard-chart-card .panel-body canvas,
.dashboard-chart-card .widget-body canvas {
min-height: 0 !important;
}
.panel {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* Force Xibo panels/cards to dark theme (use higher specificity to override core styles) */
body .panel,
body .panel.panel-default,
.panel.panel-white,
.panel.card,
.panel.box,
.widget {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
body .panel .panel-body,
body .panel .panel-footer,
body .panel .panel-heading,
.panel .panel-header {
background-color: transparent !important;
color: var(--color-text-primary) !important;
border-color: var(--color-border) !important;
}
body .panel .panel-heading,
.panel .panel-header {
background-color: var(--color-surface-elevated) !important;
border-bottom: 1px solid var(--color-border) !important;
}
/* Tables inside panels should inherit dark background and readable text */
.panel table,
.panel table thead,
.panel table tbody,
.panel table tr,
.panel table td,
.panel table th,
.panel .dataTables_wrapper {
background-color: transparent !important;
color: var(--color-text-primary) !important;
}
/* Card-specific fallbacks */
.card,
.card .card-body {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.panel-full {
grid-column: 1 / -1;
}
.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: all var(--transition-base);
cursor: pointer;
}
.action-card:hover {
border-color: var(--color-primary);
background-color: rgba(59, 130, 246, 0.05);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.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;
}
/* Filter card - modern container */
.ots-filter-card {
background: linear-gradient(135deg, rgba(15, 23, 42, 0.4), rgba(15, 23, 42, 0.2));
border: none;
box-shadow: 0 4px 20px rgba(6, 10, 20, 0.15);
margin-bottom: 0;
border-radius: 16px;
overflow: hidden;
}
/* Filter header with collapse button */
.ots-filter-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 12px 16px;
border: none;
background: transparent;
}
.ots-filter-title {
font-weight: 700;
color: var(--color-text-primary);
font-size: 14px;
letter-spacing: 0.03em;
text-transform: uppercase;
margin: 0;
}
.ots-filter-toggle {
width: 36px;
height: 36px;
padding: 0;
border: none;
background: rgba(59, 130, 246, 0.08);
color: var(--color-text-secondary);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
transition: all 200ms ease;
}
.ots-filter-toggle:hover {
background: rgba(59, 130, 246, 0.16);
color: var(--color-primary);
}
.ots-filter-content {
padding: 0 16px 12px 16px;
max-height: none;
min-height: auto;
overflow: visible;
transition: max-height 300ms ease-out, padding 300ms ease-out;
display: block;
}
.ots-filter-content.collapsed {
max-height: 0;
min-height: 0;
padding: 0 16px;
overflow: hidden;
display: none;
}
/* When the whole filter card is collapsed, reduce to a small floating button
positioned top-left so the page has minimal clutter but the user can
reopen the filter. This keeps the header and toggle usable. */
.ots-filter-card.collapsed {
position: fixed !important;
top: 12px !important;
left: 12px !important;
width: 48px !important;
height: 48px !important;
border-radius: 10px !important;
padding: 6px !important;
background: var(--color-surface, #ffffff) !important;
box-shadow: 0 6px 20px rgba(6,10,20,0.18) !important;
z-index: 1400 !important;
overflow: visible !important;
}
.ots-filter-card.collapsed .ots-filter-header {
display: flex !important;
align-items: center !important;
justify-content: center !important;
padding: 0 !important;
height: 100% !important;
}
.ots-filter-card.collapsed .ots-filter-title {
display: none !important;
}
.ots-filter-card.collapsed .ots-filter-toggle {
width: 36px !important;
height: 36px !important;
border-radius: 8px !important;
background: transparent !important;
}
.ots-filter-card.collapsed .ots-filter-content {
display: none !important;
}
.ots-filter-card .nav-tabs {
display: none;
}
.ots-filter-card .tab-content {
display: block;
}
.ots-filter-card .tab-pane {
display: none;
}
.ots-filter-card .tab-pane.active,
.ots-filter-card .tab-pane.show {
display: block;
}
.ots-filter-card .form-inline {
display: flex;
flex-wrap: nowrap;
gap: 12px;
align-items: flex-end;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
padding-bottom: 4px;
}
.ots-filter-card .form-inline .form-group,
.ots-filter-card .form-inline .input-group {
margin-right: 0;
margin-bottom: 0;
flex: 0 0 auto;
min-width: 180px;
}
.ots-filter-card .form-control,
.ots-filter-card select,
.ots-filter-card .select2-selection,
.ots-filter-card .input-group-addon,
.ots-filter-card .input-group-text {
background-color: var(--color-surface) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
color: var(--color-text-primary) !important;
border-radius: 10px !important;
padding: 12px 14px !important;
font-size: 15px !important;
font-family: inherit !important;
transition: border 150ms ease, box-shadow 150ms ease !important;
height: 48px !important;
line-height: 1.4 !important;
box-shadow: none !important;
box-sizing: border-box !important;
}
.ots-filter-card .input-group {
display: flex;
align-items: center;
gap: 6px;
}
.ots-filter-card .input-group > .form-control,
.ots-filter-card .input-group > .custom-select,
.ots-filter-card .input-group > .select2-container {
min-width: 0;
flex: 1 1 auto;
}
.ots-filter-card .form-control:focus,
.ots-filter-card select:focus,
.ots-filter-card .select2-selection:focus {
border-color: rgba(96, 165, 250, 0.7) !important;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2), 0 10px 24px rgba(6, 10, 20, 0.25) !important;
background: rgba(15, 23, 42, 0.9) !important;
}
.ots-filter-card label {
color: var(--color-text-tertiary);
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: 2px;
display: block;
}
.ots-filter-card .select2-selection__rendered {
color: var(--color-text-primary) !important;
line-height: 20px !important;
}
.ots-filter-card .select2-container--default .select2-selection--single,
.ots-filter-card .select2-container--default .select2-selection--multiple {
background-color: var(--color-surface) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
border-radius: 10px !important;
min-height: 44px !important;
box-shadow: none !important;
}
.ots-filter-card .select2-container--default .select2-selection--multiple .select2-search__field {
color: var(--color-text-primary) !important;
background: transparent !important;
}
.ots-filter-card .select2-container--default .select2-selection--multiple .select2-selection__choice {
background: rgba(59, 130, 246, 0.2) !important;
border: 1px solid rgba(59, 130, 246, 0.4) !important;
color: var(--color-text-primary) !important;
border-radius: 999px !important;
}
.ots-filter-card .bootstrap-tagsinput,
.ots-filter-card .tagsinput {
background-color: var(--color-surface) !important;
background-image: none !important;
border: 1px solid var(--color-border) !important;
border-radius: 10px !important;
color: var(--color-text-primary) !important;
min-height: 44px !important;
padding: 6px 10px !important;
box-shadow: none !important;
}
.ots-filter-card .bootstrap-tagsinput input,
.ots-filter-card .tagsinput input {
background: transparent !important;
color: var(--color-text-primary) !important;
}
.ots-filter-card .select2-selection__arrow b {
border-color: var(--color-text-secondary) transparent transparent transparent !important;
}
.ots-filter-card .input-group {
background: transparent;
}
.ots-filter-card .input-group .form-control {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
.ots-filter-card .input-group-append .input-group-text,
.ots-filter-card .input-group-addon {
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
font-weight: 600;
height: 44px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
padding: 0 12px !important;
}
.ots-filter-card .input-group .input-group-prepend .input-group-text,
.ots-filter-card .input-group .input-group-append .input-group-text {
border-radius: 10px !important;
}
.ots-filter-card .input-group .btn,
.ots-filter-card .input-group .btn.btn-secondary {
height: 44px;
padding: 0 14px;
border-radius: 999px;
border: 1px solid rgba(148, 163, 184, 0.25);
background: rgba(30, 41, 59, 0.55);
color: var(--color-text-primary);
font-weight: 600;
letter-spacing: 0.02em;
}
.ots-filter-card input::placeholder,
.ots-filter-card textarea::placeholder {
color: rgba(148, 163, 184, 0.7) !important;
}
.ots-filter-card select {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-image: linear-gradient(45deg, transparent 50%, rgba(148, 163, 184, 0.7) 50%),
linear-gradient(135deg, rgba(148, 163, 184, 0.7) 50%, transparent 50%);
background-position: calc(100% - 16px) 17px, calc(100% - 12px) 17px;
background-size: 4px 4px, 4px 4px;
background-repeat: no-repeat;
padding-right: 28px !important;
}
.ots-filter-card .form-check-input {
width: 18px;
height: 18px;
border-radius: 6px;
border: 1px solid rgba(148, 163, 184, 0.35);
background: rgba(15, 23, 42, 0.65);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.02);
}
.ots-filter-card .form-check-input:checked {
background: var(--color-primary);
border-color: rgba(96, 165, 250, 0.8);
}
.ots-grid-with-folders {
display: grid;
grid-template-columns: 260px 1fr;
gap: 32px;
align-items: start;
width: 100%;
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);
}
.ots-table-card {
padding: 12px 16px 16px;
flex: 1;
min-width: 0;
overflow: hidden;
}
/* ============================================================================
TOOLBAR - Icon-only action buttons
============================================================================ */
.ots-table-toolbar {
display: flex;
align-items: center;
gap: 8px;
padding: 0 4px 12px;
flex-wrap: wrap;
}
.ots-table-toolbar .ots-toolbar-btn,
.ots-table-toolbar .btn.ots-toolbar-btn {
width: 36px;
height: 36px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
font-size: 15px;
line-height: 1;
border: none;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.ots-table-toolbar .ots-toolbar-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.ots-table-toolbar .ots-toolbar-btn:active {
transform: translateY(0);
}
/* Folder toggle in toolbar */
.ots-table-toolbar .folder-controller.btn {
width: 36px;
height: 36px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
font-size: 15px;
line-height: 1;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
/* Breadcrumbs in toolbar */
.ots-table-toolbar #breadcrumbs {
font-size: 13px;
color: var(--color-text-tertiary);
margin: 0;
padding: 0;
}
/* View toggle buttons (map/list) */
.ots-table-toolbar .map-controller,
.ots-table-toolbar .list-controller {
width: 36px;
height: 36px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
font-size: 15px;
line-height: 1;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
#datatable-container {
width: 100%;
overflow-x: auto;
}
.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);
}
.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;
}
.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;
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;
}
}
.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;
}
.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);
}
/* ============================================================================
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;
}
.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,
[class*="chart"] {
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: block;
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 > div[class*="chart"],
.panel-body > div > canvas {
width: 100% !important;
height: 100% !important;
}
/* 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;
}
}
/* 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_scrollBody {
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;
}
.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 */
label,
.label,
.form-label,
legend {
color: var(--color-text-primary) !important;
}
/* Dropdowns, modals, and popovers */
.dropdown-menu,
.dropdown-toggle,
.popover {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !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 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;
}
/* Properties Panel - Override layout-editor bundle backgrounds */
.properties-panel-container #properties-panel {
background-color: var(--color-surface) !important;
}
.properties-panel-container #properties-panel #properties-panel-form-container {
background: var(--color-surface) !important;
background-color: var(--color-surface) !important;
}
.properties-panel-container #properties-panel .loading-container {
background: var(--color-surface) !important;
}
/* Properties Panel Tabs - Override layout-editor bundle (2-ID specificity) */
.properties-panel-container #properties-panel #properties-panel-form-container .form-container .nav > li > a {
background-color: var(--color-surface) !important;
background: var(--color-surface) !important;
color: var(--color-text-secondary) !important;
border-color: var(--color-primary) !important;
border-width: 0 0 2px 0 !important;
}
.properties-panel-container #properties-panel #properties-panel-form-container .form-container .nav > li > a:hover {
background-color: rgba(59, 130, 246, 0.15) !important;
background: rgba(59, 130, 246, 0.15) !important;
color: var(--color-text-primary) !important;
}
.properties-panel-container #properties-panel #properties-panel-form-container .form-container .nav > li > a.active,
.properties-panel-container #properties-panel #properties-panel-form-container .form-container .nav > li > a.active:hover {
background-color: var(--color-primary) !important;
background: var(--color-primary) !important;
color: white !important;
border-color: var(--color-primary) !important;
opacity: 100%;
}
/* 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;
}
a.text-muted:hover {
color: var(--color-text-primary) !important;
}
/* Ensure absolutely nothing is invisible */
.hidden,
[hidden] {
display: none !important;
}
.invisible {
visibility: hidden !important;
}
/* =============================================================================
OTS SIGNAGE DARK THEME (REBUILT)
February 4, 2026
============================================================================= */
:root {
color-scheme: dark;
--ots-bg: var(--color-background);
--ots-surface: #141c2b;
--ots-surface-2: #1b2436;
--ots-surface-3: #222c3f;
--ots-border: #2c3a54;
--ots-border-soft: #243047;
--ots-text: #e6eefb;
--ots-text-muted: #a9b6cc;
--ots-text-faint: #7f8aa3;
--ots-primary: #4f8cff;
--ots-primary-2: #2f6bff;
--ots-success: #2ad4a4;
--ots-warning: #f4b860;
--ots-danger: #ff6b6b;
--ots-info: #5ec0ff;
--ots-shadow-lg: 0 14px 30px rgba(0, 0, 0, 0.35);
--ots-shadow-md: 0 8px 18px rgba(0, 0, 0, 0.25);
--ots-shadow-sm: 0 3px 8px rgba(0, 0, 0, 0.2);
--ots-radius-sm: 6px;
--ots-radius-md: 10px;
--ots-radius-lg: 14px;
--ots-transition: 160ms ease;
}
/* Light mode token overrides so layout backgrounds follow theme */
body.ots-light-mode {
--ots-bg: var(--color-background);
--ots-surface: var(--color-surface);
--ots-surface-2: var(--color-surface-elevated);
--ots-surface-3: var(--color-surface-elevated);
--ots-border: var(--color-border);
--ots-border-soft: var(--color-border-light);
--ots-text: var(--color-text-primary);
--ots-text-muted: var(--color-text-secondary);
--ots-text-faint: var(--color-text-tertiary);
--ots-primary: var(--color-primary);
--ots-primary-2: var(--color-primary-dark);
--ots-success: var(--color-success);
--ots-warning: var(--color-warning);
--ots-danger: var(--color-danger);
--ots-info: var(--color-info);
}
/* =============================================================================
GLOBAL
============================================================================= */
html,
body {
background: var(--ots-bg);
color: var(--ots-text);
}
body {
font-family: "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
a,
.nav-link,
.sidebar a {
color: var(--ots-text);
text-decoration: none;
transition: color var(--ots-transition), background var(--ots-transition);
}
a:hover,
.nav-link:hover,
.sidebar a:hover {
color: var(--ots-primary);
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: var(--ots-text);
font-weight: 600;
}
small,
.text-muted {
color: var(--ots-text-muted) !important;
}
hr {
border-color: var(--ots-border);
}
/* =============================================================================
LAYOUT WRAPPERS
============================================================================= */
#page-wrapper,
#content-wrapper,
.page-content {
background: var(--ots-bg);
}
#content-wrapper {
padding-left: var(--ots-sidebar-content-gap);
box-sizing: border-box;
}
.page-content {
padding-top: 24px;
}
/* Override Bootstrap col padding inside page-content */
.page-content > .row > .col-sm-12 {
padding-left: 16px;
padding-right: 16px;
}
/* =============================================================================
NAVBAR / TOPBAR
============================================================================= */
.navbar,
.navbar-default {
background: var(--ots-surface-2);
border: none;
border-bottom: 1px solid var(--ots-border);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
height: 56px;
min-height: 56px;
padding: 0 16px;
display: flex;
align-items: center;
margin-bottom: 0;
}
.navbar-brand,
.navbar-brand .xibo-logo {
color: var(--ots-text);
}
.navbar-nav > li > a,
.navbar-nav > .active > a,
.navbar-nav > .open > a {
color: var(--ots-text) !important;
background: transparent !important;
}
.navbar-nav > li > a:hover {
color: var(--ots-primary) !important;
}
.navbar-toggler,
.navbar-toggler-side {
color: var(--ots-text);
border: 1px solid var(--ots-border);
}
/* Topbar nav refinements (dark) */
.ots-topbar.navbar-nav {
background: transparent;
border: 0;
padding: 0;
margin: 0;
gap: 2px;
height: auto;
align-items: center;
}
.ots-topbar .nav-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 10px;
border-radius: 6px;
color: var(--ots-text);
font-weight: 500;
font-size: 13px;
transition: background 150ms ease, color 150ms ease;
}
.ots-topbar .nav-link:hover,
.ots-topbar .nav-item.open .nav-link,
.ots-topbar .nav-item.active .nav-link {
background: rgba(79, 140, 255, 0.12);
color: var(--ots-primary);
}
.ots-topbar .dropdown-menu {
border-radius: 10px;
padding: 6px 0;
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
border: 1px solid var(--ots-border);
}
.ots-topbar .dropdown-item,
.ots-topbar .dropdown-menu a {
display: flex;
align-items: center;
gap: 8px;
border-radius: 6px;
padding: 8px 12px;
margin: 1px 6px;
font-size: 13px;
}
.ots-topbar-icon {
width: 16px;
text-align: center;
opacity: 0.85;
font-size: 13px;
}
/* =============================================================================
SIDEBAR
============================================================================= */
#sidebar-wrapper {
background: var(--ots-surface);
border-right: 1px solid var(--ots-border);
}
/* OTS sidebar override marker */
.ots-sidebar-wrapper {
box-shadow: inset 0 0 0 1px rgba(79, 140, 255, 0.2);
}
.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 (dark) */
#sidebar-wrapper .sidebar-title a {
color: var(--ots-text-faint);
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: block;
margin: 2px 8px;
padding: 10px 12px;
border-radius: var(--ots-radius-sm);
transition: background var(--ots-transition), color var(--ots-transition);
}
#sidebar-wrapper .sidebar-list a:hover,
#sidebar-wrapper .sidebar-main a:hover {
background: rgba(79, 140, 255, 0.12);
color: var(--ots-primary);
}
#sidebar-wrapper .sidebar {
padding: 14px 0;
}
#sidebar-wrapper .sidebar-main a,
#sidebar-wrapper .sidebar-list a {
display: block;
padding: 10px 18px;
color: var(--ots-text);
border-left: 3px solid transparent;
}
#sidebar-wrapper .sidebar-main a:hover,
#sidebar-wrapper .sidebar-list a:hover {
background: rgba(79, 140, 255, 0.12);
color: var(--ots-primary);
}
#sidebar-wrapper .sidebar-title a {
padding: 12px 18px 6px;
color: var(--ots-text-faint);
font-size: 11px;
letter-spacing: 0.08em;
text-transform: uppercase;
}
/* =============================================================================
WIDGETS / CARDS
============================================================================= */
.widget,
.card,
.panel,
.modal-content {
background: var(--color-surface) !important;
border: 1px solid var(--color-border) !important;
border-radius: var(--radius-md);
box-shadow: var(--shadow-base);
}
.widget-title,
.panel-heading,
.card-header,
.modal-header {
background: var(--color-surface-elevated) !important;
border-bottom: 1px solid var(--color-border) !important;
color: var(--color-text-primary) !important;
}
.widget-body,
.panel-body,
.card-body,
.modal-body {
color: var(--ots-text);
}
/* =============================================================================
BUTTONS
============================================================================= */
.btn,
button,
input[type="button"],
input[type="submit"] {
border-radius: var(--ots-radius-sm);
border: 1px solid transparent;
transition: background var(--ots-transition), border var(--ots-transition), color var(--ots-transition);
}
.btn-default,
.btn-secondary {
background: var(--ots-surface-3);
color: var(--ots-text);
border-color: var(--ots-border);
}
.btn-default:hover,
.btn-secondary:hover {
background: var(--ots-surface-2);
border-color: var(--ots-primary);
color: var(--ots-primary);
}
.btn-primary {
background: var(--ots-primary);
border-color: var(--ots-primary-2);
color: #0b1020;
}
.btn-primary:hover {
background: var(--ots-primary-2);
border-color: var(--ots-primary-2);
color: #0b1020;
}
.btn-success {
background: var(--ots-success);
border-color: var(--ots-success);
color: #041410;
}
.btn-warning {
background: var(--ots-warning);
border-color: var(--ots-warning);
color: #1c1200;
}
.btn-danger {
background: var(--ots-danger);
border-color: var(--ots-danger);
color: #220707;
}
.btn-info {
background: var(--ots-info);
border-color: var(--ots-info);
color: #07101a;
}
/* =============================================================================
FORMS
============================================================================= */
.form-control,
input[type="text"],
input[type="search"],
input[type="email"],
input[type="password"],
select,
textarea {
background: var(--ots-surface);
color: var(--ots-text);
border: 1px solid var(--ots-border);
border-radius: var(--ots-radius-sm);
box-shadow: none;
}
.form-control:focus,
input[type="text"]:focus,
input[type="search"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
select:focus,
textarea:focus {
border-color: var(--ots-primary);
box-shadow: 0 0 0 2px rgba(79, 140, 255, 0.2);
outline: none;
}
.input-group-addon {
background: var(--ots-surface-3);
border: 1px solid var(--ots-border);
color: var(--ots-text-muted);
}
/* =============================================================================
TABLES / DATATABLES
============================================================================= */
.table,
.table > thead > tr > th,
.table > tbody > tr > td {
color: var(--ots-text);
border-color: var(--ots-border);
}
.table-striped > tbody > tr:nth-of-type(odd) {
background: rgba(79, 140, 255, 0.04);
}
.table-hover > tbody > tr:hover {
background: rgba(79, 140, 255, 0.08);
}
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
color: var(--ots-text-muted) !important;
}
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select {
background: var(--ots-surface) !important;
color: var(--ots-text) !important;
border: 1px solid var(--ots-border) !important;
}
.dataTables_wrapper table {
color: var(--ots-text);
}
/* =============================================================================
DROPDOWNS / MENUS
============================================================================= */
.dropdown-menu {
background: var(--ots-surface-2);
border: 1px solid var(--ots-border);
box-shadow: var(--ots-shadow-md);
}
.dropdown-item,
.dropdown-menu > li > a {
color: var(--ots-text);
}
.dropdown-item:hover,
.dropdown-menu > li > a:hover {
background: rgba(79, 140, 255, 0.12);
color: var(--ots-primary);
}
/* =============================================================================
ALERTS / BADGES
============================================================================= */
.alert {
border-radius: var(--ots-radius-sm);
border: 1px solid var(--ots-border);
}
.alert-success {
background: rgba(42, 212, 164, 0.15);
color: var(--ots-success);
}
.alert-warning {
background: rgba(244, 184, 96, 0.15);
color: var(--ots-warning);
}
.alert-danger {
background: rgba(255, 107, 107, 0.15);
color: var(--ots-danger);
}
.alert-info {
background: rgba(94, 192, 255, 0.15);
color: var(--ots-info);
}
.badge,
.label {
background: var(--ots-surface-3);
color: var(--ots-text);
border: 1px solid var(--ots-border);
}
/* =============================================================================
TABS / PAGINATION
============================================================================= */
.nav-tabs {
border-bottom: 1px solid var(--ots-border);
}
.nav-tabs > li > a {
color: var(--ots-text-muted);
border: 1px solid transparent;
}
.nav-tabs > li.active > a,
.nav-tabs > li.active > a:focus,
.nav-tabs > li.active > a:hover {
background: var(--ots-surface-2);
color: var(--ots-text);
border: 1px solid var(--ots-border);
border-bottom-color: transparent;
}
.pagination > li > a,
.pagination > li > span {
background: var(--ots-surface-2);
border: 1px solid var(--ots-border);
color: var(--ots-text);
}
.pagination > li > a:hover,
.pagination > li > span:hover {
background: var(--ots-surface-3);
color: var(--ots-primary);
}
.pagination > .active > a,
.pagination > .active > span {
background: var(--ots-primary);
border-color: var(--ots-primary-2);
color: #0b1020;
}
/* =============================================================================
MODALS
============================================================================= */
.modal-content {
border-radius: var(--radius-lg);
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.modal,
.modal-header,
.modal-body,
.modal-footer {
background-color: transparent !important;
color: var(--color-text-primary) !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-footer {
border-top: 1px solid var(--ots-border);
}
/* =============================================================================
HELP PANE / MISC
============================================================================= */
#help-pane {
background: var(--ots-surface-2);
border: 1px solid var(--ots-border);
}
#help-pane .help-pane-btn {
background: var(--ots-primary);
color: #0b1020;
}
/* =============================================================================
OTS DASHBOARD MESSAGE
============================================================================= */
.ots-dashboard-message {
margin: 16px 0 24px;
padding: 12px 16px;
border-radius: var(--ots-radius-md);
background: rgba(79, 140, 255, 0.16);
border: 1px solid rgba(79, 140, 255, 0.45);
color: var(--ots-text);
}
.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(--ots-text-muted);
}
/* =============================================================================
NUCLEAR: Collapsed Sidebar Icon Centering
=============================================================================
This section is placed at the VERY END of the last-loaded stylesheet
(override-styles.twig is inlined after all linked CSS files).
It uses high-specificity selectors with !important to guarantee
these rules win the cascade over everything else.
============================================================================= */
/* The 44×44 icon button — grid centering is the most robust method */
#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;
}
/* The icon span — centered by grid parent, centers its own ::before glyph */
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list > a > .ots-nav-icon,
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group > .sidebar-group-toggle > .ots-nav-icon {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 20px !important;
height: 20px !important;
font-size: 20px !important;
line-height: 1 !important;
margin: 0 !important;
padding: 0 !important;
text-indent: 0 !important;
text-align: center !important;
float: none !important;
opacity: 1 !important;
}
/* The FA ::before glyph — block-level and centered */
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list > a > .ots-nav-icon::before,
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-group > .sidebar-group-toggle > .ots-nav-icon::before {
display: block !important;
text-align: center !important;
width: 100% !important;
line-height: 1 !important;
margin: 0 !important;
padding: 0 !important;
text-indent: 0 !important;
}
/* The <li> wrapper — full width, centers the button */
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav > .sidebar-list,
#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;
padding-left: 0 !important;
padding-right: 0 !important;
text-indent: 0 !important;
float: none !important;
height: auto !important;
list-style: none !important;
box-sizing: border-box !important;
}
/* The <ul> nav list — full width, no spacing that could offset children */
#sidebar-wrapper.ots-sidebar.collapsed > .sidebar-content > .ots-sidebar-nav {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
width: 100% !important;
padding-left: 0 !important;
padding-right: 0 !important;
margin: 0 !important;
text-indent: 0 !important;
list-style: none !important;
}