Files
OTSSignsTheme/custom/otssignange/views/override-styles.twig
Matt Batchelder b766487411 Refactor page structure: Update page classes for consistency
- Changed class from "ots-displays-page" to "ots-static-page ots-displays-page" in multiple Twig view files to standardize page layout.
- Enhanced schedule-page.twig with improved calendar navigation and dropdown management.
- Added global dropdown dismissal functionality to improve user experience across modals and dropdowns.
2026-02-11 20:47:09 -05:00

7132 lines
187 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: 67px;
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;
}
/* Horizontal nav mode: no sidebar, so remove sidebar margin from content */
nav.navbar + #content-wrapper {
margin-left: 0 !important;
width: 100% !important;
max-width: 100% !important;
padding-left: 20px !important;
padding-right: 20px !important;
}
nav.navbar + #content-wrapper .page-content {
padding-left: 0 !important;
padding-right: 0 !important;
}
nav.navbar + #content-wrapper .page-content .row {
margin-left: 0 !important;
margin-right: 0 !important;
}
nav.navbar + #content-wrapper .page-content [class*="col-"] {
padding-left: 0 !important;
padding-right: 0 !important;
}
nav.navbar + #content-wrapper .page-content > .row > .col-sm-12 {
padding-left: 0 !important;
padding-right: 0 !important;
}
nav.navbar + #content-wrapper .page-header {
margin-left: 0 !important;
padding-left: 0 !important;
}
/* Page background follows the light/dark theme when horizontal nav is active */
nav.navbar + #content-wrapper,
nav.navbar + #content-wrapper .page-content {
background-color: var(--color-background) !important;
color: var(--color-text-primary) !important;
}
/* 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: 67px !important;
min-height: 67px !important;
max-height: 67px !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: 67px !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: 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);
}
.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: 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;
}
/* 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);
}
#map_button,
#list_button {
background-color: var(--color-primary) !important;
color: #ffffff !important;
border: none !important;
width: 36px;
height: 36px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
font-size: 16px;
line-height: 1;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
transition: all 0.15s ease;
}
#map_button:hover,
#list_button:hover {
background-color: var(--color-primary-light) !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
transform: translateY(-1px);
}
#map_button:active,
#list_button:active {
transform: translateY(0);
}
#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;
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;
}
}
.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;
}
/* 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;
}
.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 {
color: var(--modal-body-text, var(--color-text-primary)) !important;
}
.modal-content {
background-color: var(--modal-bg, var(--color-surface)) !important;
color: var(--modal-body-text, var(--color-text-primary)) !important;
border: 1px solid var(--modal-border, var(--color-border)) !important;
border-radius: var(--modal-radius, var(--ots-radius-lg)) !important;
box-shadow: var(--modal-shadow) !important;
overflow: hidden;
}
.modal-backdrop,
.modal-backdrop.show,
.modal-backdrop.in {
background-color: var(--modal-backdrop-bg, rgba(0, 0, 0, 0.3)) !important;
backdrop-filter: blur(var(--modal-backdrop-blur, 4px)) !important;
-webkit-backdrop-filter: blur(var(--modal-backdrop-blur, 4px)) !important;
opacity: 1 !important;
}
.modal-header {
background-color: var(--modal-header-bg, var(--color-surface-elevated)) !important;
border-bottom: 1px solid var(--modal-header-border, var(--color-border)) !important;
padding: 16px 20px !important;
}
.modal-title,
.modal-header h4,
.modal-header h5 {
color: var(--modal-header-text, var(--color-text-primary)) !important;
font-weight: 600;
}
.modal-body {
background-color: var(--modal-body-bg, transparent) !important;
color: var(--modal-body-text, var(--color-text-primary)) !important;
padding: 20px !important;
}
.modal-footer {
background-color: var(--modal-footer-bg, transparent) !important;
border-top: 1px solid var(--modal-footer-border, var(--color-border)) !important;
padding: 12px 20px !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 */
html.ots-light-mode,
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);
}
/* Only apply sidebar content gap when in sidebar mode (inside #page-wrapper) */
#page-wrapper #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 (sidebar mode only) */
#page-wrapper .page-content > .row > .col-sm-12 {
padding-left: 16px;
padding-right: 16px;
}
/* Horizontal nav: ensure no extra left padding leaks through */
nav.navbar + #content-wrapper {
padding-left: 20px !important;
padding-right: 20px !important;
}
nav.navbar + #content-wrapper .page-content > .row > .col-sm-12 {
padding-left: 0 !important;
padding-right: 0 !important;
}
/* =============================================================================
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: 67px;
min-height: 67px;
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 {
background: var(--color-surface) !important;
border: 1px solid var(--color-border) !important;
border-radius: var(--radius-md);
box-shadow: var(--shadow-base);
}
.modal-content {
background: var(--modal-bg, var(--color-surface)) !important;
border: 1px solid var(--modal-border, var(--color-border)) !important;
border-radius: var(--modal-radius, var(--ots-radius-lg)) !important;
box-shadow: var(--modal-shadow) !important;
}
.widget-title,
.panel-heading,
.card-header {
background: var(--color-surface-elevated) !important;
border-bottom: 1px solid var(--color-border) !important;
color: var(--color-text-primary) !important;
}
.modal-header {
background: var(--modal-header-bg, var(--color-surface-elevated)) !important;
border-bottom: 1px solid var(--modal-header-border, var(--color-border)) !important;
color: var(--modal-header-text, var(--color-text-primary)) !important;
}
.widget-body,
.panel-body,
.card-body {
color: var(--ots-text);
}
.modal-body {
color: var(--modal-body-text, 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);
}
/* DataTable row action buttons — transparent so they blend with the row */
.ots-table-card .btn-default,
.ots-table-card .btn-secondary,
table .btn-group .btn-default,
table .btn-group .btn-secondary,
.dataTables_wrapper .btn-group .btn-default,
.dataTables_wrapper .btn-group .btn-secondary,
.ots-table-card .dropdown-toggle,
table .btn-group .dropdown-toggle,
.dataTables_wrapper .btn-group .dropdown-toggle {
background: transparent !important;
border: none !important;
box-shadow: none !important;
}
.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;
}
/* Toolbar button styles - 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;
}
/* =============================================================================
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(--modal-radius, var(--ots-radius-lg));
background-color: var(--modal-bg, var(--color-surface)) !important;
color: var(--modal-body-text, var(--color-text-primary)) !important;
border: 1px solid var(--modal-border, var(--color-border)) !important;
box-shadow: var(--modal-shadow) !important;
overflow: hidden;
}
.modal,
.modal-header,
.modal-body,
.modal-footer {
color: var(--modal-body-text, var(--color-text-primary)) !important;
}
.modal-header {
background-color: var(--modal-header-bg, var(--color-surface-elevated)) !important;
border-bottom: 1px solid var(--modal-header-border, var(--ots-border)) !important;
padding: 16px 20px !important;
}
.modal-body {
background-color: var(--modal-body-bg, transparent) !important;
padding: 20px !important;
}
.modal-backdrop,
.modal-backdrop.show,
.modal-backdrop.in {
background-color: var(--modal-backdrop-bg, rgba(0, 0, 0, 0.3)) !important;
backdrop-filter: blur(var(--modal-backdrop-blur, 4px)) !important;
-webkit-backdrop-filter: blur(var(--modal-backdrop-blur, 4px)) !important;
opacity: 1 !important;
}
.modal-footer {
background-color: var(--modal-footer-bg, transparent) !important;
border-top: 1px solid var(--modal-footer-border, var(--ots-border)) !important;
padding: 12px 20px !important;
}
/* Modal footer buttons — secondary */
.modal-footer .btn,
.modal-footer button {
border-radius: var(--ots-radius-sm) !important;
border: 1px solid var(--modal-border, var(--ots-border)) !important;
background: var(--modal-body-bg, var(--ots-surface-3)) !important;
color: var(--modal-body-text, var(--ots-text)) !important;
transition: background var(--ots-transition),
color var(--ots-transition),
border-color var(--ots-transition);
}
.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;
}
/* Modal footer buttons — primary */
.modal-footer .btn-primary,
.modal-footer .btn.btn-primary {
background: var(--ots-primary) !important;
color: #0b1020 !important;
border-color: var(--ots-primary-2, var(--ots-primary)) !important;
font-weight: 600;
}
.modal-footer .btn-primary:hover {
background: var(--ots-primary-2, var(--color-primary-dark)) !important;
color: #ffffff !important;
}
/* Modal footer buttons — danger */
.modal-footer .btn-danger {
background: var(--ots-danger) !important;
color: #ffffff !important;
border-color: var(--ots-danger) !important;
}
/* Modal close button */
.modal-header .close,
.modal-header [data-dismiss="modal"] {
color: var(--modal-close-color, var(--ots-text-muted)) !important;
opacity: 1 !important;
text-shadow: none !important;
}
.modal-header .close:hover,
.modal-header [data-dismiss="modal"]:hover {
color: var(--modal-close-hover, var(--ots-text)) !important;
}
/* Modal form controls */
.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 textarea,
.modal-body select {
background-color: var(--modal-input-bg, var(--ots-bg)) !important;
border: 1px solid var(--modal-input-border, var(--ots-border)) !important;
border-radius: var(--ots-radius-sm) !important;
color: var(--modal-input-text, var(--ots-text)) !important;
}
.modal-body .form-control:focus,
.modal-body input:focus,
.modal-body textarea:focus,
.modal-body select:focus {
border-color: var(--modal-input-focus-border, var(--ots-primary)) !important;
box-shadow: 0 0 0 3px var(--modal-input-focus-ring, rgba(79, 140, 255, 0.2)) !important;
outline: none !important;
}
/* =============================================================================
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;
}
/* =============================================================================
HORIZONTAL NAV — FINAL OVERRIDE (must be last in file to win cascade)
Applied when the top navbar is active and there is no sidebar.
============================================================================= */
nav.navbar + #content-wrapper,
.navbar.navbar-expand-lg ~ #content-wrapper,
.navbar-default.navbar-expand-lg ~ #content-wrapper {
margin-left: 0 !important;
padding-left: 20px !important;
padding-right: 20px !important;
width: 100% !important;
max-width: 100% !important;
}
nav.navbar + #content-wrapper .page-content,
.navbar.navbar-expand-lg ~ #content-wrapper .page-content {
padding-left: 0 !important;
padding-right: 0 !important;
}
nav.navbar + #content-wrapper .page-content .row,
.navbar.navbar-expand-lg ~ #content-wrapper .page-content .row {
margin-left: 0 !important;
margin-right: 0 !important;
}
nav.navbar + #content-wrapper .page-content [class*="col-"],
nav.navbar + #content-wrapper .page-content > .row > .col-sm-12,
.navbar.navbar-expand-lg ~ #content-wrapper .page-content [class*="col-"],
.navbar.navbar-expand-lg ~ #content-wrapper .page-content > .row > .col-sm-12 {
padding-left: 0 !important;
padding-right: 0 !important;
}
/* =============================================================================
HORIZONTAL NAV — CLASS-BASED OVERRIDE (highest cascade priority)
.ots-horizontal-nav is added directly to #content-wrapper in authed.twig
============================================================================= */
#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;
}
/* =============================================================================
CARD HOVER BEHAVIOR
.ots-static-page — applied to ALL non-dashboard pages; kills every hover
transform/transition on any descendant.
.dashboard-page — applied to dashboard pages only; cards keep hover.
============================================================================= */
/* ── Non-dashboard pages: kill ALL hover movement ───────────────────────────── */
.ots-static-page,
.ots-static-page *,
.ots-static-page *::before,
.ots-static-page *::after {
will-change: auto !important;
}
.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 .ots-displays-card,
.ots-static-page .ots-filter-card,
.ots-static-page .ots-table-card,
.ots-static-page .ots-folder-tree,
.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 .dashboard-card:focus,
.ots-static-page .dashboard-card:active,
.ots-static-page .content-card:hover,
.ots-static-page .content-card:focus,
.ots-static-page .action-card:hover,
.ots-static-page .action-card:focus,
.ots-static-page .action-card--modern:hover,
.ots-static-page .action-card--modern:focus,
.ots-static-page .kpi-card:hover,
.ots-static-page .kpi-card:focus,
.ots-static-page .dashboard-chart-card:hover,
.ots-static-page .dashboard-chart-card:focus,
.ots-static-page .widget:hover,
.ots-static-page .widget:focus,
.ots-static-page .card:hover,
.ots-static-page .card:focus,
.ots-static-page .panel:hover,
.ots-static-page .panel:focus,
.ots-static-page .media-item:hover,
.ots-static-page .media-item:focus,
.ots-static-page .ots-displays-card:hover,
.ots-static-page .ots-filter-card:hover,
.ots-static-page .ots-table-card:hover,
.ots-static-page .ots-folder-tree:hover,
.ots-static-page [class*="-card"]:hover,
.ots-static-page [class*="card-"]:hover {
transform: none !important;
transition: none !important;
}
/* ── Dashboard pages: cards keep hover animation ────────────────────────────── */
.dashboard-page .dashboard-card,
.dashboard-page .action-card,
.dashboard-page .action-card--modern,
.dashboard-page .kpi-card,
.dashboard-page .dashboard-chart-card {
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease !important;
}
.dashboard-page .dashboard-card:hover {
transform: translateY(-2px) !important;
box-shadow: 0 22px 50px rgba(8, 15, 30, 0.45) !important;
border-color: rgba(59, 130, 246, 0.45) !important;
}
.dashboard-page .action-card:hover {
border-color: var(--color-primary) !important;
background-color: rgba(59, 130, 246, 0.05) !important;
transform: translateY(-2px) !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
}
.dashboard-page .action-card--modern:hover {
transform: translateY(-4px) !important;
border-color: rgba(59, 130, 246, 0.45) !important;
box-shadow: 0 20px 36px rgba(8, 15, 30, 0.45) !important;
}
.dashboard-page .kpi-card:hover {
border-color: var(--color-primary) !important;
box-shadow: 0 0 0 1px var(--color-primary) !important;
}
.dashboard-page .dashboard-chart-card:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25) !important;
transform: translateY(-2px) !important;
}
/* =============================================================================
OTS UPLOAD MODAL Modern file-upload experience
Auto-follows light/dark using existing CSS variables.
============================================================================= */
/* ── Backdrop ─────────────────────────────────────────────────────────── */
.ots-upload-modal.modal {
z-index: 1060;
}
.ots-upload-modal .modal-backdrop,
.ots-upload-modal + .modal-backdrop {
background: var(--modal-backdrop-bg, rgba(2,6,23,0.55));
backdrop-filter: blur(var(--modal-backdrop-blur, 6px));
-webkit-backdrop-filter: blur(var(--modal-backdrop-blur, 6px));
}
/* ── Dialog chrome ────────────────────────────────────────────────────── */
.ots-upload-content {
background: var(--modal-bg, #141c2b);
border: 1px solid var(--modal-border, #2c3a54);
border-radius: var(--modal-radius, 16px);
box-shadow: var(--modal-shadow, 0 24px 64px rgba(0,0,0,0.45));
overflow: hidden;
}
.ots-upload-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 24px;
background: var(--modal-header-bg, #0f172a);
border-bottom: 1px solid var(--modal-header-border, #2c3a54);
}
.ots-upload-title {
font-size: 1.1rem;
font-weight: 700;
color: var(--modal-header-text, #f1f5f9);
margin: 0;
}
.ots-upload-close {
background: none;
border: none;
color: var(--modal-close-color, #64748b);
cursor: pointer;
padding: 4px;
border-radius: 6px;
transition: color 160ms ease, background 160ms ease;
line-height: 0;
}
.ots-upload-close:hover,
.ots-upload-close:focus-visible {
color: var(--modal-close-hover, #f1f5f9);
background: rgba(255,255,255,0.08);
outline: none;
}
/* ── Body ─────────────────────────────────────────────────────────────── */
.ots-upload-body {
padding: 24px;
background: var(--modal-body-bg, #141c2b);
color: var(--modal-body-text, #e2e8f0);
}
/* ── Tab switcher (File / URL) ────────────────────────────────────────── */
.ots-upload-tabs {
display: flex;
gap: 4px;
margin-bottom: 18px;
background: rgba(79,140,255,0.06);
border-radius: 10px;
padding: 4px;
}
.ots-upload-tab {
flex: 1;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 9px 16px;
font-size: 0.875rem;
font-weight: 500;
color: var(--ots-text-muted, #a9b6cc);
background: transparent;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background 160ms ease, color 160ms ease;
}
.ots-upload-tab:hover {
color: var(--modal-body-text, #e2e8f0);
background: rgba(79,140,255,0.08);
}
.ots-upload-tab.active {
color: #fff;
background: var(--ots-primary, #4f8cff);
box-shadow: 0 2px 8px rgba(79,140,255,0.25);
}
.ots-upload-tab i {
font-size: 0.8125rem;
}
/* ── Tab content panels ───────────────────────────────────────────────── */
.ots-upload-tab-content {
/* just a wrapper, animated via d-none */
}
/* ── URL input section ────────────────────────────────────────────────── */
.ots-upload-url-section {
text-align: center;
}
.ots-upload-url-icon {
color: var(--ots-primary, #4f8cff);
margin-bottom: 8px;
opacity: 0.6;
}
.ots-upload-url-desc {
font-size: 0.875rem;
color: var(--ots-text-muted, #a9b6cc);
margin-bottom: 18px;
}
.ots-upload-url-fields {
display: flex;
gap: 10px;
align-items: flex-end;
margin-bottom: 16px;
}
.ots-upload-url-field {
flex: 1;
text-align: left;
}
.ots-upload-url-field label {
display: block;
font-size: 0.75rem;
font-weight: 600;
color: var(--ots-text-muted, #a9b6cc);
margin-bottom: 4px;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.ots-upload-url-input {
background: var(--modal-input-bg, #0b111a) !important;
border: 1px solid var(--modal-input-border, #2c3a54) !important;
color: var(--modal-input-text, #e6eefb) !important;
border-radius: 8px !important;
padding: 9px 14px !important;
font-size: 0.875rem !important;
transition: border-color 160ms ease, box-shadow 160ms ease !important;
}
.ots-upload-url-input:focus {
border-color: var(--modal-input-focus-border, #4f8cff) !important;
box-shadow: 0 0 0 3px var(--modal-input-focus-ring, rgba(79,140,255,0.2)) !important;
outline: none !important;
}
.ots-upload-url-input::placeholder {
color: var(--ots-text-faint, #7f8aa3);
}
.ots-upload-url-add {
flex-shrink: 0;
padding: 9px 18px !important;
font-size: 0.8125rem !important;
white-space: nowrap;
}
/* Light mode tab/URL overrides */
.ots-light-mode .ots-upload-tabs {
background: rgba(79,140,255,0.06);
}
.ots-light-mode .ots-upload-tab {
color: #64748b;
}
.ots-light-mode .ots-upload-tab:hover {
color: #334155;
background: rgba(79,140,255,0.06);
}
.ots-light-mode .ots-upload-tab.active {
color: #fff;
}
.ots-light-mode .ots-upload-url-input {
background: #f8fafc !important;
border-color: #cbd5e1 !important;
color: #1e293b !important;
}
.ots-light-mode .ots-upload-url-input:focus {
border-color: var(--ots-primary, #4f8cff) !important;
}
.ots-light-mode .ots-upload-url-desc {
color: #64748b;
}
/* ── Folder selector row ──────────────────────────────────────────────── */
.ots-upload-folder-row {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 16px;
font-size: 0.875rem;
}
.ots-upload-folder-label {
color: var(--ots-text-muted, #a9b6cc);
}
.ots-upload-folder-btn {
background: var(--modal-input-bg, #0b111a);
border: 1px solid var(--modal-input-border, #2c3a54);
color: var(--ots-primary, #4f8cff);
border-radius: 8px;
padding: 4px 12px;
font-size: 0.8125rem;
transition: border-color 160ms ease, background 160ms ease;
}
.ots-upload-folder-btn:hover {
border-color: var(--ots-primary, #4f8cff);
background: rgba(79,140,255,0.08);
}
/* ── Notices ───────────────────────────────────────────────────────────── */
.ots-upload-notice,
.ots-upload-ext-info {
font-size: 0.8125rem;
color: var(--ots-text-muted, #a9b6cc);
margin-bottom: 12px;
padding: 8px 14px;
background: rgba(79,140,255,0.06);
border-radius: 8px;
border: 1px solid rgba(79,140,255,0.12);
}
/* ── Drop-zone ────────────────────────────────────────────────────────── */
.ots-upload-dropzone {
position: relative;
border: 2px dashed var(--modal-input-border, #2c3a54);
border-radius: 14px;
padding: 40px 24px;
text-align: center;
cursor: pointer;
transition: border-color 200ms ease, background 200ms ease, transform 120ms ease;
background: rgba(79,140,255,0.02);
margin-bottom: 16px;
}
.ots-upload-dropzone:hover,
.ots-upload-dropzone:focus-visible {
border-color: var(--ots-primary, #4f8cff);
background: rgba(79,140,255,0.06);
outline: none;
}
.ots-upload-dropzone--over {
border-color: var(--ots-primary, #4f8cff) !important;
background: rgba(79,140,255,0.10) !important;
transform: scale(1.01);
}
.ots-upload-dropzone--has-files {
padding: 20px 24px;
}
.ots-upload-dropzone-icon {
color: var(--ots-primary, #4f8cff);
margin-bottom: 12px;
opacity: 0.7;
}
.ots-upload-dropzone--over .ots-upload-dropzone-icon {
opacity: 1;
transform: translateY(-4px);
transition: opacity 160ms ease, transform 160ms ease;
}
.ots-upload-dropzone-text {
font-size: 0.95rem;
line-height: 1.5;
color: var(--modal-body-text, #e2e8f0);
margin: 0;
}
.ots-upload-dropzone-sub {
font-size: 0.8125rem;
color: var(--ots-text-muted, #a9b6cc);
}
.ots-upload-browse-link {
color: var(--ots-primary, #4f8cff);
text-decoration: underline;
text-underline-offset: 2px;
cursor: pointer;
}
.ots-upload-browse-link:hover {
color: var(--ots-primary-2, #2f6bff);
}
.ots-upload-input-hidden {
position: absolute;
width: 0;
height: 0;
opacity: 0;
overflow: hidden;
pointer-events: none;
}
/* ── Options checkboxes ───────────────────────────────────────────────── */
.ots-upload-options {
margin-bottom: 16px;
}
.ots-upload-option {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 10px 14px;
border-radius: 10px;
background: rgba(79,140,255,0.04);
border: 1px solid rgba(79,140,255,0.08);
margin-bottom: 8px;
cursor: pointer;
transition: background 160ms ease;
font-size: 0.875rem;
color: var(--modal-body-text, #e2e8f0);
}
.ots-upload-option:hover {
background: rgba(79,140,255,0.08);
}
.ots-upload-option input[type="checkbox"] {
margin-top: 3px;
accent-color: var(--ots-primary, #4f8cff);
width: 16px;
height: 16px;
flex-shrink: 0;
}
.ots-upload-option span {
line-height: 1.4;
}
.ots-upload-option small {
display: block;
color: var(--ots-text-muted, #a9b6cc);
font-size: 0.75rem;
margin-top: 2px;
}
/* ── File queue ───────────────────────────────────────────────────────── */
.ots-upload-queue-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
}
.ots-upload-queue-title {
font-weight: 600;
font-size: 0.875rem;
color: var(--modal-body-text, #e2e8f0);
}
.ots-upload-queue-count {
font-size: 0.8125rem;
color: var(--ots-text-muted, #a9b6cc);
}
.ots-upload-file-list {
list-style: none;
margin: 0;
padding: 0;
max-height: 260px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: var(--ots-border, #2c3a54) transparent;
}
/* ── Individual file item ─────────────────────────────────────────────── */
.ots-upload-file-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
border-radius: 10px;
background: var(--modal-input-bg, #0b111a);
border: 1px solid var(--modal-input-border, #2c3a54);
margin-bottom: 6px;
transition: border-color 160ms ease, background 160ms ease;
}
.ots-upload-file-item:last-child {
margin-bottom: 0;
}
/* Thumbnail / icon */
.ots-upload-file-thumb {
width: 44px;
height: 44px;
border-radius: 8px;
background: rgba(79,140,255,0.08);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 1.1rem;
color: var(--ots-primary, #4f8cff);
background-size: cover;
background-position: center;
overflow: hidden;
}
.ots-upload-file-thumb.has-preview {
background-color: transparent;
border: 1px solid var(--modal-input-border, #2c3a54);
}
/* Info */
.ots-upload-file-info {
flex: 1;
min-width: 0;
}
.ots-upload-file-name {
display: block;
font-size: 0.875rem;
font-weight: 500;
color: var(--modal-body-text, #e2e8f0);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ots-upload-file-meta {
display: block;
font-size: 0.75rem;
color: var(--ots-text-muted, #a9b6cc);
margin-top: 2px;
}
/* Progress bar */
.ots-upload-file-progress {
height: 4px;
border-radius: 2px;
background: rgba(79,140,255,0.12);
margin-top: 6px;
overflow: hidden;
opacity: 0;
transition: opacity 200ms ease;
}
.ots-upload-file--uploading .ots-upload-file-progress {
opacity: 1;
}
.ots-upload-file-progress-bar {
height: 100%;
width: 0%;
border-radius: 2px;
background: linear-gradient(90deg, var(--ots-primary, #4f8cff), var(--ots-primary-2, #2f6bff));
transition: width 300ms ease;
}
/* Remove button */
.ots-upload-file-remove {
background: none;
border: none;
color: var(--ots-text-muted, #a9b6cc);
cursor: pointer;
padding: 4px 6px;
border-radius: 6px;
font-size: 0.875rem;
transition: color 160ms ease, background 160ms ease;
flex-shrink: 0;
}
.ots-upload-file-remove:hover,
.ots-upload-file-remove:focus-visible {
color: var(--ots-danger, #ff6b6b);
background: rgba(255,107,107,0.1);
outline: none;
}
/* ── File states ──────────────────────────────────────────────────────── */
.ots-upload-file--uploading {
border-color: var(--ots-primary, #4f8cff);
}
.ots-upload-file--done {
border-color: var(--ots-success, #2ad4a4);
background: rgba(42,212,164,0.06);
}
.ots-upload-file--done .ots-upload-file-meta {
color: var(--ots-success, #2ad4a4);
}
.ots-upload-file--done .ots-upload-file-progress-bar {
background: var(--ots-success, #2ad4a4);
}
.ots-upload-file--done .ots-upload-file-remove {
display: none;
}
.ots-upload-file--error {
border-color: var(--ots-danger, #ff6b6b);
background: rgba(255,107,107,0.06);
}
.ots-upload-file--error .ots-upload-file-meta {
color: var(--ots-danger, #ff6b6b);
}
/* ── Footer buttons ───────────────────────────────────────────────────── */
.ots-upload-footer {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
padding: 14px 24px;
background: var(--modal-footer-bg, #0f172a);
border-top: 1px solid var(--modal-footer-border, #2c3a54);
}
.ots-upload-btn-cancel {
background: transparent;
color: var(--ots-text-muted, #a9b6cc);
border: 1px solid var(--modal-input-border, #2c3a54);
border-radius: 8px;
padding: 8px 20px;
font-size: 0.875rem;
font-weight: 500;
transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.ots-upload-btn-cancel:hover {
background: rgba(255,255,255,0.06);
color: var(--modal-body-text, #e2e8f0);
border-color: var(--ots-border, #2c3a54);
}
.ots-upload-btn-start {
background: var(--ots-primary, #4f8cff);
color: #fff;
border: none;
border-radius: 8px;
padding: 8px 22px;
font-size: 0.875rem;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 8px;
transition: background 160ms ease, transform 120ms ease, box-shadow 160ms ease;
box-shadow: 0 2px 8px rgba(79,140,255,0.25);
}
.ots-upload-btn-start:hover {
background: var(--ots-primary-2, #2f6bff);
transform: translateY(-1px);
box-shadow: 0 4px 14px rgba(79,140,255,0.35);
}
.ots-upload-btn-start:active {
transform: translateY(0);
}
.ots-upload-btn-done {
background: var(--ots-success, #2ad4a4);
color: #fff;
border: none;
border-radius: 8px;
padding: 8px 22px;
font-size: 0.875rem;
font-weight: 600;
transition: background 160ms ease, transform 120ms ease;
}
.ots-upload-btn-done:hover {
background: #1fbd91;
transform: translateY(-1px);
}
/* ── Responsive ───────────────────────────────────────────────────────── */
@media (max-width: 576px) {
.ots-upload-content {
border-radius: 12px;
}
.ots-upload-header,
.ots-upload-body,
.ots-upload-footer {
padding-left: 16px;
padding-right: 16px;
}
.ots-upload-dropzone {
padding: 28px 16px;
}
.ots-upload-file-thumb {
width: 36px;
height: 36px;
}
}
/* ── Light-mode overrides (when .ots-light-mode is on <html>) ─────────── */
.ots-light-mode .ots-upload-content {
background: #ffffff;
border-color: #e2e8f0;
box-shadow: 0 20px 60px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.04);
}
.ots-light-mode .ots-upload-header {
background: #f8fafc;
border-bottom-color: #e2e8f0;
}
.ots-light-mode .ots-upload-title {
color: #0f172a;
}
.ots-light-mode .ots-upload-close {
color: #94a3b8;
}
.ots-light-mode .ots-upload-close:hover {
color: #334155;
background: rgba(0,0,0,0.05);
}
.ots-light-mode .ots-upload-body {
background: #ffffff;
color: #334155;
}
.ots-light-mode .ots-upload-dropzone {
border-color: #cbd5e1;
background: #f8fafc;
}
.ots-light-mode .ots-upload-dropzone:hover,
.ots-light-mode .ots-upload-dropzone:focus-visible {
border-color: var(--ots-primary, #4f8cff);
background: rgba(79,140,255,0.04);
}
.ots-light-mode .ots-upload-dropzone--over {
border-color: var(--ots-primary, #4f8cff) !important;
background: rgba(79,140,255,0.08) !important;
}
.ots-light-mode .ots-upload-dropzone-text {
color: #334155;
}
.ots-light-mode .ots-upload-dropzone-sub {
color: #64748b;
}
.ots-light-mode .ots-upload-notice,
.ots-light-mode .ots-upload-ext-info {
color: #475569;
background: rgba(79,140,255,0.06);
border-color: rgba(79,140,255,0.12);
}
.ots-light-mode .ots-upload-file-item {
background: #f8fafc;
border-color: #e2e8f0;
}
.ots-light-mode .ots-upload-file-name {
color: #1e293b;
}
.ots-light-mode .ots-upload-file-meta {
color: #64748b;
}
.ots-light-mode .ots-upload-queue-title {
color: #1e293b;
}
.ots-light-mode .ots-upload-queue-count {
color: #64748b;
}
.ots-light-mode .ots-upload-file-thumb {
background: rgba(79,140,255,0.08);
}
.ots-light-mode .ots-upload-folder-btn {
background: #f1f5f9;
border-color: #cbd5e1;
}
.ots-light-mode .ots-upload-option {
background: #f8fafc;
border-color: #e2e8f0;
color: #334155;
}
.ots-light-mode .ots-upload-option small {
color: #64748b;
}
.ots-light-mode .ots-upload-footer {
background: #f8fafc;
border-top-color: #e2e8f0;
}
.ots-light-mode .ots-upload-btn-cancel {
color: #64748b;
border-color: #e2e8f0;
}
.ots-light-mode .ots-upload-btn-cancel:hover {
color: #334155;
background: #f1f5f9;
}
/* ── Scrollbar styling inside file list ──────────────────────────────── */
.ots-upload-file-list::-webkit-scrollbar {
width: 6px;
}
.ots-upload-file-list::-webkit-scrollbar-track {
background: transparent;
}
.ots-upload-file-list::-webkit-scrollbar-thumb {
background: var(--ots-border, #2c3a54);
border-radius: 3px;
}
.ots-light-mode .ots-upload-file-list::-webkit-scrollbar-thumb {
background: #cbd5e1;
}
/* ── Animation ────────────────────────────────────────────────────────── */
.ots-upload-modal .modal-dialog {
transform: translateY(20px) scale(0.98);
transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1), opacity 280ms ease;
opacity: 0;
}
.ots-upload-modal.show .modal-dialog {
transform: translateY(0) scale(1);
opacity: 1;
}
/* =============================================================================
OTS EDIT MEDIA MODAL Matches the upload modal design language
Applied via .ots-edit-media-modal class (added by global JS enhancer)
Also targets .bootbox modals directly as CSS-only fallback.
Excludes .ots-upload-modal (the custom upload dialog has its own styles).
============================================================================= */
/* ── Animation ────────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-dialog,
.bootbox:not(.ots-upload-modal) .modal-dialog {
transform: translateY(20px) scale(0.98);
transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1), opacity 280ms ease;
opacity: 0;
}
.ots-edit-media-modal.show .modal-dialog,
.bootbox.show:not(.ots-upload-modal) .modal-dialog {
transform: translateY(0) scale(1);
opacity: 1;
}
/* ── Dialog chrome ────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-content,
.bootbox:not(.ots-upload-modal) .modal-content {
background: var(--modal-bg, #141c2b) !important;
border: 1px solid var(--modal-border, #2c3a54) !important;
border-radius: var(--modal-radius, 16px) !important;
box-shadow: var(--modal-shadow, 0 24px 64px rgba(0,0,0,0.45)) !important;
overflow: hidden !important;
}
/* ── Header ───────────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-header,
.bootbox:not(.ots-upload-modal) .modal-header {
display: flex !important;
align-items: center !important;
justify-content: space-between !important;
padding: 18px 24px !important;
background: var(--modal-header-bg, #0f172a) !important;
border-bottom: 1px solid var(--modal-header-border, #2c3a54) !important;
}
.ots-edit-media-modal .modal-title,
.ots-edit-media-modal .modal-header h4,
.ots-edit-media-modal .modal-header h5,
.bootbox:not(.ots-upload-modal) .modal-title,
.bootbox:not(.ots-upload-modal) .modal-header h4,
.bootbox:not(.ots-upload-modal) .modal-header h5 {
font-size: 1.1rem !important;
font-weight: 700 !important;
color: var(--modal-header-text, #f1f5f9) !important;
margin: 0 !important;
line-height: 1.3 !important;
}
/* Close button (SVG version injected by JS) */
.ots-edit-media-modal .modal-header .ots-upload-close,
.bootbox:not(.ots-upload-modal) .modal-header .ots-upload-close {
background: none !important;
border: none !important;
color: var(--modal-close-color, #64748b) !important;
cursor: pointer;
padding: 4px !important;
border-radius: 6px !important;
transition: color 160ms ease, background 160ms ease;
line-height: 0 !important;
margin: 0 !important;
opacity: 1 !important;
}
.ots-edit-media-modal .modal-header .ots-upload-close:hover,
.ots-edit-media-modal .modal-header .ots-upload-close:focus-visible,
.bootbox:not(.ots-upload-modal) .modal-header .ots-upload-close:hover,
.bootbox:not(.ots-upload-modal) .modal-header .ots-upload-close:focus-visible {
color: var(--modal-close-hover, #f1f5f9) !important;
background: rgba(255,255,255,0.08) !important;
outline: none !important;
}
/* ── Body ─────────────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-body,
.bootbox:not(.ots-upload-modal) .modal-body {
padding: 24px !important;
background: var(--modal-body-bg, #141c2b) !important;
color: var(--modal-body-text, #e2e8f0) !important;
}
/* ── Form labels ──────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-body label,
.ots-edit-media-modal .modal-body .control-label,
.bootbox:not(.ots-upload-modal) .modal-body label,
.bootbox:not(.ots-upload-modal) .modal-body .control-label {
font-size: 0.8125rem !important;
font-weight: 600 !important;
color: var(--ots-text-muted, #a9b6cc) !important;
text-transform: uppercase !important;
letter-spacing: 0.04em !important;
margin-bottom: 6px !important;
}
/* ── Form groups ──────────────────────────────────────────────────────── */
.ots-edit-media-modal .form-group,
.bootbox:not(.ots-upload-modal) .form-group {
margin-bottom: 18px !important;
}
/* ── Form controls ────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-body .form-control,
.ots-edit-media-modal .modal-body input[type="text"],
.ots-edit-media-modal .modal-body input[type="number"],
.ots-edit-media-modal .modal-body input[type="email"],
.ots-edit-media-modal .modal-body input[type="password"],
.ots-edit-media-modal .modal-body textarea,
.ots-edit-media-modal .modal-body select,
.bootbox:not(.ots-upload-modal) .modal-body .form-control,
.bootbox:not(.ots-upload-modal) .modal-body input[type="text"],
.bootbox:not(.ots-upload-modal) .modal-body input[type="number"],
.bootbox:not(.ots-upload-modal) .modal-body input[type="email"],
.bootbox:not(.ots-upload-modal) .modal-body input[type="password"],
.bootbox:not(.ots-upload-modal) .modal-body textarea,
.bootbox:not(.ots-upload-modal) .modal-body select {
background: var(--modal-input-bg, #0b111a) !important;
border: 1px solid var(--modal-input-border, #2c3a54) !important;
color: var(--modal-input-text, #e6eefb) !important;
border-radius: 8px !important;
padding: 9px 14px !important;
font-size: 0.875rem !important;
transition: border-color 160ms ease, box-shadow 160ms ease !important;
}
.ots-edit-media-modal .modal-body .form-control:focus,
.ots-edit-media-modal .modal-body input:focus,
.ots-edit-media-modal .modal-body textarea:focus,
.ots-edit-media-modal .modal-body select:focus,
.bootbox:not(.ots-upload-modal) .modal-body .form-control:focus,
.bootbox:not(.ots-upload-modal) .modal-body input:focus,
.bootbox:not(.ots-upload-modal) .modal-body textarea:focus,
.bootbox:not(.ots-upload-modal) .modal-body select:focus {
border-color: var(--modal-input-focus-border, #4f8cff) !important;
box-shadow: 0 0 0 3px var(--modal-input-focus-ring, rgba(79,140,255,0.2)) !important;
outline: none !important;
}
.ots-edit-media-modal .modal-body .form-control::placeholder,
.bootbox:not(.ots-upload-modal) .modal-body .form-control::placeholder {
color: var(--ots-text-faint, #7f8aa3) !important;
}
/* ── Help text ────────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-body .help-block,
.ots-edit-media-modal .modal-body .form-text,
.ots-edit-media-modal .modal-body small.text-muted,
.bootbox:not(.ots-upload-modal) .modal-body .help-block,
.bootbox:not(.ots-upload-modal) .modal-body .form-text,
.bootbox:not(.ots-upload-modal) .modal-body small.text-muted {
font-size: 0.75rem !important;
color: var(--ots-text-muted, #a9b6cc) !important;
margin-top: 4px !important;
line-height: 1.4 !important;
}
/* ── Checkboxes ───────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-body .checkbox,
.ots-edit-media-modal .modal-body .form-check,
.bootbox:not(.ots-upload-modal) .modal-body .checkbox,
.bootbox:not(.ots-upload-modal) .modal-body .form-check {
padding: 10px 14px !important;
border-radius: 10px !important;
background: rgba(79,140,255,0.04) !important;
border: 1px solid rgba(79,140,255,0.08) !important;
margin-bottom: 8px !important;
transition: background 160ms ease !important;
}
.ots-edit-media-modal .modal-body .checkbox:hover,
.ots-edit-media-modal .modal-body .form-check:hover,
.bootbox:not(.ots-upload-modal) .modal-body .checkbox:hover,
.bootbox:not(.ots-upload-modal) .modal-body .form-check:hover {
background: rgba(79,140,255,0.08) !important;
}
.ots-edit-media-modal .modal-body input[type="checkbox"],
.bootbox:not(.ots-upload-modal) .modal-body input[type="checkbox"] {
accent-color: var(--ots-primary, #4f8cff) !important;
width: 16px !important;
height: 16px !important;
}
.ots-edit-media-modal .modal-body .checkbox label,
.ots-edit-media-modal .modal-body .form-check-label,
.bootbox:not(.ots-upload-modal) .modal-body .checkbox label,
.bootbox:not(.ots-upload-modal) .modal-body .form-check-label {
text-transform: none !important;
font-weight: 500 !important;
font-size: 0.875rem !important;
color: var(--modal-body-text, #e2e8f0) !important;
letter-spacing: normal !important;
}
/* ── Tabs (if edit form has nav-tabs) ─────────────────────────────────── */
.ots-edit-media-modal .nav-tabs,
.bootbox:not(.ots-upload-modal) .nav-tabs {
display: flex !important;
gap: 4px !important;
margin-bottom: 18px !important;
background: rgba(79,140,255,0.06) !important;
border-radius: 10px !important;
padding: 4px !important;
border-bottom: none !important;
}
.ots-edit-media-modal .nav-tabs > li,
.ots-edit-media-modal .nav-tabs .nav-item,
.bootbox:not(.ots-upload-modal) .nav-tabs > li,
.bootbox:not(.ots-upload-modal) .nav-tabs .nav-item {
flex: 1 !important;
}
.ots-edit-media-modal .nav-tabs > li > a,
.ots-edit-media-modal .nav-tabs .nav-link,
.bootbox:not(.ots-upload-modal) .nav-tabs > li > a,
.bootbox:not(.ots-upload-modal) .nav-tabs .nav-link {
display: flex !important;
align-items: center !important;
justify-content: center !important;
gap: 8px !important;
padding: 9px 16px !important;
font-size: 0.875rem !important;
font-weight: 500 !important;
color: var(--ots-text-muted, #a9b6cc) !important;
background: transparent !important;
border: none !important;
border-radius: 8px !important;
cursor: pointer !important;
transition: background 160ms ease, color 160ms ease !important;
text-align: center !important;
}
.ots-edit-media-modal .nav-tabs > li > a:hover,
.ots-edit-media-modal .nav-tabs .nav-link:hover,
.bootbox:not(.ots-upload-modal) .nav-tabs > li > a:hover,
.bootbox:not(.ots-upload-modal) .nav-tabs .nav-link:hover {
color: var(--modal-body-text, #e2e8f0) !important;
background: rgba(79,140,255,0.08) !important;
}
.ots-edit-media-modal .nav-tabs > li.active > a,
.ots-edit-media-modal .nav-tabs > li.active > a:focus,
.ots-edit-media-modal .nav-tabs > li.active > a:hover,
.ots-edit-media-modal .nav-tabs .nav-link.active,
.bootbox:not(.ots-upload-modal) .nav-tabs > li.active > a,
.bootbox:not(.ots-upload-modal) .nav-tabs > li.active > a:focus,
.bootbox:not(.ots-upload-modal) .nav-tabs > li.active > a:hover,
.bootbox:not(.ots-upload-modal) .nav-tabs .nav-link.active {
color: #fff !important;
background: var(--ots-primary, #4f8cff) !important;
box-shadow: 0 2px 8px rgba(79,140,255,0.25) !important;
border: none !important;
}
/* ── Info/notice panels ───────────────────────────────────────────────── */
.ots-edit-media-modal .modal-body .card,
.ots-edit-media-modal .modal-body .bg-light,
.bootbox:not(.ots-upload-modal) .modal-body .card,
.bootbox:not(.ots-upload-modal) .modal-body .bg-light {
font-size: 0.8125rem !important;
color: var(--ots-text-muted, #a9b6cc) !important;
background: rgba(79,140,255,0.06) !important;
border-radius: 8px !important;
border: 1px solid rgba(79,140,255,0.12) !important;
padding: 10px 14px !important;
}
/* ── Select2 inputs (tags, etc.) ──────────────────────────────────────── */
.ots-edit-media-modal .select2-container--default .select2-selection--multiple,
.ots-edit-media-modal .select2-container--default .select2-selection--single,
.bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection--multiple,
.bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection--single {
background: var(--modal-input-bg, #0b111a) !important;
border: 1px solid var(--modal-input-border, #2c3a54) !important;
border-radius: 8px !important;
min-height: 38px !important;
}
.ots-edit-media-modal .select2-container--default .select2-selection--multiple:focus-within,
.ots-edit-media-modal .select2-container--default .select2-selection--single:focus-within,
.bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection--multiple:focus-within,
.bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection--single:focus-within {
border-color: var(--modal-input-focus-border, #4f8cff) !important;
box-shadow: 0 0 0 3px var(--modal-input-focus-ring, rgba(79,140,255,0.2)) !important;
}
.ots-edit-media-modal .select2-container--default .select2-selection--multiple .select2-selection__choice,
.bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection--multiple .select2-selection__choice {
background: rgba(79,140,255,0.15) !important;
border: 1px solid rgba(79,140,255,0.3) !important;
border-radius: 6px !important;
color: var(--ots-primary, #4f8cff) !important;
font-size: 0.8125rem !important;
padding: 2px 8px !important;
}
.ots-edit-media-modal .select2-container--default .select2-selection__rendered,
.ots-edit-media-modal .select2-container--default .select2-selection--single .select2-selection__rendered,
.bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection__rendered,
.bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection--single .select2-selection__rendered {
color: var(--modal-input-text, #e6eefb) !important;
}
/* ── Footer ───────────────────────────────────────────────────────────── */
.ots-edit-media-modal .modal-footer,
.bootbox:not(.ots-upload-modal) .modal-footer {
display: flex !important;
align-items: center !important;
justify-content: flex-end !important;
gap: 10px !important;
padding: 14px 24px !important;
background: var(--modal-footer-bg, #0f172a) !important;
border-top: 1px solid var(--modal-footer-border, #2c3a54) !important;
}
/* Cancel / secondary buttons */
.ots-edit-media-modal .modal-footer .btn,
.ots-edit-media-modal .modal-footer button,
.bootbox:not(.ots-upload-modal) .modal-footer .btn,
.bootbox:not(.ots-upload-modal) .modal-footer button {
background: transparent !important;
color: var(--ots-text-muted, #a9b6cc) !important;
border: 1px solid var(--modal-input-border, #2c3a54) !important;
border-radius: 8px !important;
padding: 8px 20px !important;
font-size: 0.875rem !important;
font-weight: 500 !important;
transition: background 160ms ease, color 160ms ease, border-color 160ms ease !important;
}
.ots-edit-media-modal .modal-footer .btn:hover,
.ots-edit-media-modal .modal-footer button:hover,
.bootbox:not(.ots-upload-modal) .modal-footer .btn:hover,
.bootbox:not(.ots-upload-modal) .modal-footer button:hover {
background: rgba(255,255,255,0.06) !important;
color: var(--modal-body-text, #e2e8f0) !important;
border-color: var(--ots-border, #2c3a54) !important;
}
/* Save / primary button */
.ots-edit-media-modal .modal-footer .btn-primary,
.bootbox:not(.ots-upload-modal) .modal-footer .btn-primary {
background: var(--ots-primary, #4f8cff) !important;
color: #fff !important;
border: none !important;
border-radius: 8px !important;
padding: 8px 22px !important;
font-size: 0.875rem !important;
font-weight: 600 !important;
display: inline-flex !important;
align-items: center !important;
gap: 8px !important;
transition: background 160ms ease, transform 120ms ease, box-shadow 160ms ease !important;
box-shadow: 0 2px 8px rgba(79,140,255,0.25) !important;
}
.ots-edit-media-modal .modal-footer .btn-primary:hover,
.bootbox:not(.ots-upload-modal) .modal-footer .btn-primary:hover {
background: var(--ots-primary-2, #2f6bff) !important;
transform: translateY(-1px) !important;
box-shadow: 0 4px 14px rgba(79,140,255,0.35) !important;
color: #fff !important;
}
.ots-edit-media-modal .modal-footer .btn-primary:active,
.bootbox:not(.ots-upload-modal) .modal-footer .btn-primary:active {
transform: translateY(0) !important;
}
/* Replace / warning button */
.ots-edit-media-modal .modal-footer .btn-warning,
.bootbox:not(.ots-upload-modal) .modal-footer .btn-warning {
background: var(--ots-warning, #f4b860) !important;
color: #1c1200 !important;
border: none !important;
border-radius: 8px !important;
padding: 8px 20px !important;
font-weight: 600 !important;
transition: background 160ms ease, transform 120ms ease !important;
}
.ots-edit-media-modal .modal-footer .btn-warning:hover,
.bootbox:not(.ots-upload-modal) .modal-footer .btn-warning:hover {
background: #e5a040 !important;
transform: translateY(-1px) !important;
color: #1c1200 !important;
}
/* Danger button */
.ots-edit-media-modal .modal-footer .btn-danger,
.bootbox:not(.ots-upload-modal) .modal-footer .btn-danger {
background: var(--ots-danger, #ff6b6b) !important;
color: #ffffff !important;
border: none !important;
border-radius: 8px !important;
padding: 8px 20px !important;
font-weight: 600 !important;
}
/* ── Light mode overrides ─────────────────────────────────────────────── */
.ots-light-mode .ots-edit-media-modal .modal-content,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-content {
background: #ffffff !important;
border-color: #e2e8f0 !important;
box-shadow: 0 20px 60px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.04) !important;
}
.ots-light-mode .ots-edit-media-modal .modal-header,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-header {
background: #f8fafc !important;
border-bottom-color: #e2e8f0 !important;
}
.ots-light-mode .ots-edit-media-modal .modal-title,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-title {
color: #0f172a !important;
}
.ots-light-mode .ots-edit-media-modal .modal-header .ots-upload-close,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-header .ots-upload-close {
color: #94a3b8 !important;
}
.ots-light-mode .ots-edit-media-modal .modal-header .ots-upload-close:hover,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-header .ots-upload-close:hover {
color: #334155 !important;
background: rgba(0,0,0,0.05) !important;
}
.ots-light-mode .ots-edit-media-modal .modal-body,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body {
background: #ffffff !important;
color: #334155 !important;
}
.ots-light-mode .ots-edit-media-modal .modal-body label,
.ots-light-mode .ots-edit-media-modal .modal-body .control-label,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body label,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .control-label {
color: #64748b !important;
}
.ots-light-mode .ots-edit-media-modal .modal-body .form-control,
.ots-light-mode .ots-edit-media-modal .modal-body input[type="text"],
.ots-light-mode .ots-edit-media-modal .modal-body textarea,
.ots-light-mode .ots-edit-media-modal .modal-body select,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .form-control,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body input[type="text"],
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body textarea,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body select {
background: #f8fafc !important;
border-color: #cbd5e1 !important;
color: #1e293b !important;
}
.ots-light-mode .ots-edit-media-modal .modal-body .form-control:focus,
.ots-light-mode .ots-edit-media-modal .modal-body input:focus,
.ots-light-mode .ots-edit-media-modal .modal-body textarea:focus,
.ots-light-mode .ots-edit-media-modal .modal-body select:focus,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .form-control:focus,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body input:focus,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body textarea:focus,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body select:focus {
border-color: var(--ots-primary, #4f8cff) !important;
}
.ots-light-mode .ots-edit-media-modal .modal-body .help-block,
.ots-light-mode .ots-edit-media-modal .modal-body .form-text,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .help-block,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .form-text {
color: #64748b !important;
}
.ots-light-mode .ots-edit-media-modal .modal-body .checkbox,
.ots-light-mode .ots-edit-media-modal .modal-body .form-check,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .checkbox,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .form-check {
background: #f8fafc !important;
border-color: #e2e8f0 !important;
}
.ots-light-mode .ots-edit-media-modal .modal-body .checkbox label,
.ots-light-mode .ots-edit-media-modal .modal-body .form-check-label,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .checkbox label,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-body .form-check-label {
color: #334155 !important;
}
.ots-light-mode .ots-edit-media-modal .nav-tabs,
.ots-light-mode .bootbox:not(.ots-upload-modal) .nav-tabs {
background: rgba(79,140,255,0.06) !important;
}
.ots-light-mode .ots-edit-media-modal .nav-tabs > li > a,
.ots-light-mode .ots-edit-media-modal .nav-tabs .nav-link,
.ots-light-mode .bootbox:not(.ots-upload-modal) .nav-tabs > li > a,
.ots-light-mode .bootbox:not(.ots-upload-modal) .nav-tabs .nav-link {
color: #64748b !important;
}
.ots-light-mode .ots-edit-media-modal .nav-tabs > li > a:hover,
.ots-light-mode .ots-edit-media-modal .nav-tabs .nav-link:hover,
.ots-light-mode .bootbox:not(.ots-upload-modal) .nav-tabs > li > a:hover,
.ots-light-mode .bootbox:not(.ots-upload-modal) .nav-tabs .nav-link:hover {
color: #334155 !important;
background: rgba(79,140,255,0.06) !important;
}
.ots-light-mode .ots-edit-media-modal .nav-tabs > li.active > a,
.ots-light-mode .ots-edit-media-modal .nav-tabs .nav-link.active,
.ots-light-mode .bootbox:not(.ots-upload-modal) .nav-tabs > li.active > a,
.ots-light-mode .bootbox:not(.ots-upload-modal) .nav-tabs .nav-link.active {
color: #fff !important;
}
.ots-light-mode .ots-edit-media-modal .select2-container--default .select2-selection--multiple,
.ots-light-mode .ots-edit-media-modal .select2-container--default .select2-selection--single,
.ots-light-mode .bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection--multiple,
.ots-light-mode .bootbox:not(.ots-upload-modal) .select2-container--default .select2-selection--single {
background: #f8fafc !important;
border-color: #cbd5e1 !important;
}
.ots-light-mode .ots-edit-media-modal .modal-footer,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-footer {
background: #f8fafc !important;
border-top-color: #e2e8f0 !important;
}
.ots-light-mode .ots-edit-media-modal .modal-footer .btn,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-footer .btn {
color: #64748b !important;
border-color: #e2e8f0 !important;
}
.ots-light-mode .ots-edit-media-modal .modal-footer .btn:hover,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-footer .btn:hover {
color: #334155 !important;
background: #f1f5f9 !important;
}
.ots-light-mode .ots-edit-media-modal .modal-footer .btn-primary,
.ots-light-mode .bootbox:not(.ots-upload-modal) .modal-footer .btn-primary {
color: #fff !important;
border-color: transparent !important;
}
/* ── Responsive ───────────────────────────────────────────────────────── */
@media (max-width: 576px) {
.ots-edit-media-modal .modal-content,
.bootbox:not(.ots-upload-modal) .modal-content {
border-radius: 12px !important;
}
.ots-edit-media-modal .modal-header,
.ots-edit-media-modal .modal-body,
.ots-edit-media-modal .modal-footer,
.bootbox:not(.ots-upload-modal) .modal-header,
.bootbox:not(.ots-upload-modal) .modal-body,
.bootbox:not(.ots-upload-modal) .modal-footer {
padding-left: 16px !important;
padding-right: 16px !important;
}
}
/* ============================================================================
SCHEDULE CALENDAR - Modern Dark Theme Override
Comprehensive restyling of the bootstrap-calendar widget to match the
OTS Signs dark glassmorphism design language.
============================================================================ */
/* --------------------------------------------------------------------------
Calendar container & loading
-------------------------------------------------------------------------- */
.XiboSchedule .calendar-view {
background: transparent !important;
}
#CalendarContainer {
background: transparent !important;
}
/* Loading spinners */
#calendar-progress,
#calendar-progress-table {
font-size: 1.6rem;
color: var(--color-primary-light, #60a5fa);
opacity: 0;
transform: scale(0.8);
transition: transform 0.3s ease 0.1s, opacity 0.3s ease 0.1s;
display: inline-block;
}
#calendar-progress.show,
#calendar-progress-table.show {
opacity: 1;
transform: scale(1);
}
/* Calendar header title + nav arrows */
.xibo-calendar-header-container {
padding: 0 !important;
margin-bottom: 16px;
}
.ots-calendar-nav {
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
width: 100%;
}
.ots-cal-arrow {
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
border-radius: 8px;
border: 1px solid var(--color-border, #475569);
background: var(--color-surface, #1e293b);
color: var(--color-text-secondary, #f1f5f9);
font-size: 0.875rem;
cursor: pointer;
transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
flex-shrink: 0;
}
.ots-cal-arrow:hover {
background: var(--color-primary, #3b82f6);
border-color: var(--color-primary, #3b82f6);
color: #fff;
}
.ots-cal-arrow:active {
transform: scale(0.93);
}
body.ots-light-mode .ots-cal-arrow {
background: #fff;
border-color: rgba(203, 213, 225, 0.7);
color: var(--color-text-primary, #1e293b);
}
body.ots-light-mode .ots-cal-arrow:hover {
background: var(--color-primary, #3b82f6);
border-color: var(--color-primary, #3b82f6);
color: #fff;
}
.xibo-calendar-header {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
}
.xibo-calendar-header h1.page-header {
font-size: 1.5rem !important;
font-weight: 700 !important;
color: var(--color-text-primary, #fff) !important;
letter-spacing: -0.01em;
margin: 0 !important;
padding: 0 !important;
border: none !important;
white-space: nowrap;
text-align: center;
}
/* Calendar loading class dims content */
.XiboSchedule #calendar-view.loading {
opacity: 0.45;
pointer-events: none;
transition: opacity 0.2s ease;
}
/* --------------------------------------------------------------------------
Calendar tabs (Grid / Calendar switch)
-------------------------------------------------------------------------- */
.XiboSchedule .card-header {
background: var(--color-surface, #1e293b) !important;
border-bottom: 1px solid var(--color-border, #475569) !important;
border-radius: 12px 12px 0 0 !important;
padding: 0 16px !important;
}
.XiboSchedule .card-header-tabs {
margin-bottom: 0 !important;
border-bottom: none !important;
}
.XiboSchedule .card-header-tabs .nav-link {
color: var(--color-text-tertiary, #e2e8f0) !important;
font-weight: 500;
font-size: 0.875rem;
padding: 12px 20px !important;
border: none !important;
border-bottom: 2px solid transparent !important;
border-radius: 0 !important;
background: transparent !important;
transition: color 150ms ease, border-color 150ms ease;
}
.XiboSchedule .card-header-tabs .nav-link:hover {
color: var(--color-primary-light, #60a5fa) !important;
border-bottom-color: rgba(59, 130, 246, 0.3) !important;
background: transparent !important;
}
.XiboSchedule .card-header-tabs .nav-link.active {
color: var(--color-primary-light, #60a5fa) !important;
border-bottom-color: var(--color-primary, #3b82f6) !important;
background: transparent !important;
}
.XiboSchedule .card-body {
background: transparent !important;
padding: 16px 0 !important;
}
/* --------------------------------------------------------------------------
Date controls in filter bar
-------------------------------------------------------------------------- */
.controls-date-range .controls-date-inputs {
display: inline-flex;
gap: 0.35rem;
align-items: center;
}
.controls-date-range .date-open-button {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
color: var(--color-primary-light, #60a5fa) !important;
border-radius: 6px !important;
padding: 7px 12px !important;
transition: all 150ms ease;
}
.controls-date-range .date-open-button:hover {
background: rgba(59, 130, 246, 0.12) !important;
border-color: var(--color-primary, #3b82f6) !important;
color: var(--color-primary, #3b82f6) !important;
}
/* Prev / Today / Next buttons */
.controls-date-range .btn-group .btn {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
color: var(--color-text-secondary, #f1f5f9) !important;
font-weight: 500;
font-size: 0.8125rem;
padding: 7px 14px !important;
transition: all 150ms ease;
}
.controls-date-range .btn-group .btn:hover {
background: rgba(59, 130, 246, 0.1) !important;
border-color: var(--color-primary, #3b82f6) !important;
color: var(--color-primary-light, #60a5fa) !important;
}
.controls-date-range .btn-group .btn:first-child {
border-radius: 6px 0 0 6px !important;
}
.controls-date-range .btn-group .btn:last-child {
border-radius: 0 6px 6px 0 !important;
}
/* --------------------------------------------------------------------------
MONTH VIEW - Bootstrap Calendar
-------------------------------------------------------------------------- */
/* Day name headers */
.calendar-view .cal-row-fluid.cal-row-head {
background: linear-gradient(180deg, rgba(15, 23, 42, 0.9), rgba(30, 41, 59, 0.85)) !important;
border-bottom: 1px solid var(--color-border, #475569) !important;
border-radius: 10px 10px 0 0;
display: flex !important;
}
.calendar-view .cal-row-head .cal-cell1 {
color: var(--color-text-tertiary, #e2e8f0) !important;
font-weight: 600 !important;
font-size: 0.75rem !important;
text-transform: uppercase !important;
letter-spacing: 0.06em !important;
padding: 10px 8px !important;
text-align: center !important;
flex: 1 !important;
}
/* Month grid */
.calendar-view .cal-month-box {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
border-top: none !important;
border-radius: 0 0 10px 10px;
overflow: hidden;
}
/* Day rows - neutralize vendor row-level hover */
.calendar-view .cal-month-box .cal-row-fluid,
.calendar-view .cal-month-box .cal-row-fluid:hover,
.calendar-view .cal-month-box .cal-before-eventlist:hover,
.calendar-view .cal-month-box .row-fluid:hover,
.cal-month-box .cal-row-fluid:hover,
.cal-month-box .cal-before-eventlist:hover,
#CalendarContainer .cal-row-fluid:hover,
#CalendarContainer .cal-before-eventlist:hover {
background: transparent !important;
background-color: transparent !important;
}
.calendar-view .cal-month-box .cal-row-fluid {
border-bottom: 1px solid rgba(71, 85, 105, 0.4) !important;
display: flex !important;
}
.calendar-view .cal-month-box .cal-row-fluid:last-child {
border-bottom: none !important;
}
/* Day cells */
.calendar-view .cal-month-box .cal-cell {
border-right: 1px solid rgba(71, 85, 105, 0.3) !important;
flex: 1 !important;
min-height: 90px;
transition: background-color 150ms ease;
position: relative;
}
.calendar-view .cal-month-box .cal-cell:last-child {
border-right: none !important;
}
.calendar-view .cal-month-box .cal-cell:hover {
background: rgba(59, 130, 246, 0.08) !important;
}
/* Light mode: individual cell hover */
body.ots-light-mode .calendar-view .cal-month-box .cal-cell:hover {
background: rgba(59, 130, 246, 0.06) !important;
}
/* Month day inner */
.calendar-view .cal-month-day {
padding: 4px 6px !important;
min-height: 90px;
position: relative;
background: transparent !important;
}
/* Out-of-month days */
.calendar-view .cal-month-day.cal-day-outmonth,
.calendar-view .cal-month-day.cal-day-outmonth .cal-month-day-number {
opacity: 0.35;
}
/* Today */
.calendar-view .cal-month-day.cal-day-today {
background: rgba(59, 130, 246, 0.1) !important;
box-shadow: inset 0 0 0 1px rgba(59, 130, 246, 0.35);
}
/* Day number */
.calendar-view .cal-month-day-number {
color: var(--color-text-secondary, #f1f5f9) !important;
font-weight: 600 !important;
font-size: 0.8125rem !important;
padding: 2px 6px;
border-radius: 6px;
transition: background-color 150ms ease, color 150ms ease;
cursor: default;
}
.calendar-view .cal-month-day-number[data-cal-events] {
cursor: pointer;
}
.calendar-view .cal-month-day-number:hover {
background: rgba(59, 130, 246, 0.12);
color: var(--color-primary-light, #60a5fa) !important;
}
.calendar-view .cal-day-today .cal-month-day-number {
background: var(--color-primary, #3b82f6) !important;
color: #fff !important;
border-radius: 6px;
}
/* Event count badge */
.calendar-view .cal-month-day-number-events {
position: absolute !important;
display: none;
top: 4px;
left: 4px;
background: var(--color-primary, #3b82f6) !important;
color: #fff !important;
font-size: 0.65rem !important;
font-weight: 700 !important;
border-radius: 0 0 0.5em 0;
border-top-left-radius: 0;
padding: 1px 5px !important;
min-width: 18px;
text-align: center;
line-height: 1.4;
}
.calendar-view .cal-cell:hover .cal-month-day-number-events {
display: block !important;
}
/* Events list inside month day */
.calendar-view .cal-month-day .events-list {
margin-top: 2px;
gap: 3px;
}
/* Individual event dot / icon */
.calendar-view .cal-month-day .events-list .event {
width: 22px !important;
height: 22px !important;
border-radius: 5px !important;
display: inline-flex !important;
align-items: center;
justify-content: center;
font-size: 0.7rem !important;
margin: 1px !important;
transition: transform 150ms ease, box-shadow 150ms ease;
position: relative;
border: none !important;
}
.calendar-view .cal-month-day .events-list .event:hover {
transform: scale(1.15);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
z-index: 2;
}
/* --------------------------------------------------------------------------
EVENT TYPE COLORS
Consistent across all views: month dots, day blocks, week blocks, legend
-------------------------------------------------------------------------- */
/* Always showing (gray-blue) */
.event-always,
.event.event-always,
.dh-event-always,
.day-highlight.dh-event-always,
.cal-legend li.event-always span {
background-color: rgba(148, 163, 184, 0.35) !important;
color: #cbd5e1 !important;
border-left-color: #94a3b8 !important;
}
/* Single display (blue/info) */
.event-info,
.event.event-info,
.dh-event-info,
.day-highlight.dh-event-info {
background-color: rgba(59, 130, 246, 0.25) !important;
color: #93c5fd !important;
border-left-color: #3b82f6 !important;
}
/* Multi display (green/success) */
.event-success,
.event.event-success,
.dh-event-success,
.day-highlight.dh-event-success {
background-color: rgba(16, 185, 129, 0.25) !important;
color: #6ee7b7 !important;
border-left-color: #10b981 !important;
}
/* Priority (red/important) */
.event-important,
.event.event-important,
.dh-event-important,
.day-highlight.dh-event-important {
background-color: rgba(239, 68, 68, 0.25) !important;
color: #fca5a5 !important;
border-left-color: #ef4444 !important;
}
/* Recurring (purple/special) */
.event-special,
.event.event-special,
.dh-event-special,
.day-highlight.dh-event-special {
background-color: rgba(124, 58, 237, 0.25) !important;
color: #c4b5fd !important;
border-left-color: #7c3aed !important;
}
/* View only (dark/inverse) */
.event-inverse,
.event.event-inverse,
.dh-event-inverse,
.day-highlight.dh-event-inverse {
background-color: rgba(51, 65, 85, 0.5) !important;
color: #94a3b8 !important;
border-left-color: #64748b !important;
}
/* Command (amber/warning) */
.event-warning,
.event.event-warning,
.dh-event-warning,
.day-highlight.dh-event-warning {
background-color: rgba(245, 158, 11, 0.25) !important;
color: #fcd34d !important;
border-left-color: #f59e0b !important;
}
.event-command,
.event.event-command,
.dh-event-command,
.day-highlight.dh-event-command {
background-color: rgba(245, 158, 11, 0.25) !important;
color: #fcd34d !important;
border-left-color: #f59e0b !important;
}
/* Interrupt (orange) */
.event-interrupt,
.event.event-interrupt,
.dh-event-interrupt,
.day-highlight.dh-event-interrupt {
background-color: rgba(249, 115, 22, 0.25) !important;
color: #fdba74 !important;
border-left-color: #f97316 !important;
}
/* Geo location (teal) */
.event-geo-location,
.event.event-geo-location,
.dh-event-geo-location,
.day-highlight.dh-event-geo-location {
background-color: rgba(14, 165, 233, 0.25) !important;
color: #7dd3fc !important;
border-left-color: #0ea5e9 !important;
}
/* Interactive action (cyan-blue) */
.event-action,
.event.event-action,
.dh-event-action,
.day-highlight.dh-event-action {
background-color: rgba(6, 182, 212, 0.25) !important;
color: #67e8f9 !important;
border-left-color: #06b6d4 !important;
}
/* Synchronised (indigo) */
.event-sync,
.event.event-sync,
.dh-event-sync,
.day-highlight.dh-event-sync {
background-color: rgba(99, 102, 241, 0.25) !important;
color: #a5b4fc !important;
border-left-color: #6366f1 !important;
}
/* Priority badge inside event icons */
[data-event-class="event-important"] .event-priority {
vertical-align: super;
font-size: 0.6rem;
font-weight: 700;
color: #fca5a5;
}
/* --------------------------------------------------------------------------
SLIDE / POPOVER (event detail drawer)
-------------------------------------------------------------------------- */
#cal-slide-box {
background: transparent !important;
border: none !important;
box-shadow: none !important;
}
.XiboSchedule #calendar-view #cal-slide-content,
#cal-slide-content {
background: var(--color-surface-elevated, #334155) !important;
background-image: none !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 10px !important;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35) !important;
padding: 14px 16px !important;
margin: 8px 0 !important;
display: flex !important;
justify-content: space-between !important;
align-items: flex-start !important;
}
#cal-slide-content .cal-event-list ul {
list-style: none !important;
padding: 0 !important;
margin: 0 !important;
}
#cal-slide-content .cal-event-list li {
padding: 6px 10px !important;
margin-bottom: 4px !important;
border-radius: 6px !important;
transition: background-color 150ms ease;
display: flex;
align-items: center;
gap: 8px;
}
#cal-slide-content .cal-event-list li:hover {
background: rgba(59, 130, 246, 0.08) !important;
}
#cal-slide-content .event-item,
#cal-slide-content a {
color: var(--color-text-secondary, #f1f5f9) !important;
text-decoration: none !important;
font-size: 0.85rem;
font-weight: 500;
transition: color 150ms ease;
}
#cal-slide-content .event-item:hover,
#cal-slide-content a:hover {
color: var(--color-primary-light, #60a5fa) !important;
}
/* Agenda button in slide */
.XiboSchedule #calendar-view #cal-slide-content .cal-agenda-button {
opacity: 0;
transition: opacity 0.2s ease-in-out;
}
.XiboSchedule #calendar-view #cal-slide-content .cal-agenda-button.is-visible {
opacity: 1;
}
.cal-agenda-button .btn {
background: var(--color-primary, #3b82f6) !important;
color: #fff !important;
border: none !important;
border-radius: 6px !important;
font-size: 0.8rem;
font-weight: 600;
padding: 6px 14px !important;
transition: background 150ms ease, transform 150ms ease;
}
.cal-agenda-button .btn:hover {
background: var(--color-primary-dark, #1d4ed8) !important;
transform: translateY(-1px);
}
/* Hide the default cal-day-tick */
.XiboSchedule #calendar-view #cal-day-tick {
display: none !important;
}
/* --------------------------------------------------------------------------
WEEK VIEW
-------------------------------------------------------------------------- */
.calendar-view .cal-week-box {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 10px;
overflow: hidden;
position: relative;
z-index: 1;
}
/* Column dividers */
.calendar-view .cal-week-box .cal-column {
border-left: 1px solid rgba(71, 85, 105, 0.3) !important;
}
.calendar-view .cal-week-box .cal-row-head {
background: linear-gradient(180deg, rgba(15, 23, 42, 0.9), rgba(30, 41, 59, 0.85)) !important;
border-bottom: 1px solid var(--color-border, #475569) !important;
}
.calendar-view .cal-week-box .cal-row-head .cal-cell1 {
color: var(--color-text-tertiary, #e2e8f0) !important;
font-weight: 600 !important;
font-size: 0.75rem !important;
text-transform: uppercase !important;
letter-spacing: 0.04em;
padding: 10px 6px !important;
text-align: center !important;
border-right: 1px solid rgba(71, 85, 105, 0.3) !important;
}
.calendar-view .cal-week-box .cal-row-head .cal-cell1:last-child {
border-right: none !important;
}
/* Today highlight in week header */
.calendar-view .cal-week-box .cal-row-head .cal-day-today {
background: rgba(59, 130, 246, 0.12) !important;
color: var(--color-primary-light, #60a5fa) !important;
}
/* Week day events container */
.calendar-view .cal-week-box .cal-day-box {
min-height: 80px;
}
/* Week events (same dot/pill as month day) */
.calendar-view .cal-week-box .events-list {
padding: 4px !important;
gap: 3px;
}
.calendar-view .cal-week-box .events-list .event {
width: 22px !important;
height: 22px !important;
border-radius: 5px !important;
display: inline-flex !important;
align-items: center;
justify-content: center;
font-size: 0.7rem !important;
margin: 1px !important;
transition: transform 150ms ease;
}
.calendar-view .cal-week-box .events-list .event:hover {
transform: scale(1.15);
}
/* --------------------------------------------------------------------------
DAY VIEW
-------------------------------------------------------------------------- */
#cal-day-box {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 10px;
overflow-x: auto;
}
#cal-day-box .cal-row-head {
background: linear-gradient(180deg, rgba(15, 23, 42, 0.9), rgba(30, 41, 59, 0.85)) !important;
border-bottom: 1px solid var(--color-border, #475569) !important;
}
#cal-day-box .cal-row-head .cal-cell {
color: var(--color-text-tertiary, #e2e8f0) !important;
font-weight: 600 !important;
font-size: 0.75rem !important;
text-transform: uppercase !important;
letter-spacing: 0.04em;
padding: 10px 12px !important;
}
#cal-day-box #cal-day-panel {
width: max-content;
min-width: 100%;
}
/* Hour rows */
#cal-day-box .cal-day-hour {
border-bottom: 1px solid rgba(71, 85, 105, 0.25) !important;
}
#cal-day-box .cal-day-hour-part {
border-bottom: 1px solid rgba(71, 85, 105, 0.12) !important;
min-height: 30px;
}
#cal-day-box .cal-day-hour-part .col-1 b,
#cal-day-box .cal-day-hour-part .span1 b {
color: var(--color-text-tertiary, #e2e8f0) !important;
font-weight: 500;
font-size: 0.75rem;
}
/* Day highlight blocks (events) */
.day-highlight {
border-radius: 6px !important;
padding: 4px 10px !important;
margin: 2px 0 !important;
border-left: 3px solid rgba(59, 130, 246, 0.6) !important;
overflow: hidden;
transition: background-color 150ms ease;
font-size: 0.825rem;
}
.day-highlight:hover {
filter: brightness(1.15);
}
.day-highlight .cal-hours {
color: var(--color-text-tertiary, #e2e8f0) !important;
font-weight: 600;
font-size: 0.75rem;
margin-right: 6px;
}
.day-highlight .event-item {
color: var(--color-text-secondary, #f1f5f9) !important;
text-decoration: none !important;
font-weight: 500;
}
.day-highlight .event-item:hover {
color: var(--color-primary-light, #60a5fa) !important;
}
/* Day event blocks (positioned) */
.day-event {
border-radius: 6px !important;
border-left: 3px solid !important;
overflow: hidden;
cursor: pointer;
}
.day-event.day-event-small {
border-color: var(--color-warning, #f59e0b) !important;
background-color: rgba(245, 158, 11, 0.35) !important;
min-height: 20px;
opacity: 0.85;
}
.day-event.day-event-small:hover {
opacity: 1;
}
/* --------------------------------------------------------------------------
YEAR VIEW
-------------------------------------------------------------------------- */
.calendar-view .cal-year-box {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 10px;
overflow: hidden;
}
.calendar-view .cal-year-box .cal-row-fluid {
border-bottom: 1px solid rgba(71, 85, 105, 0.3) !important;
}
.calendar-view .cal-year-box .cal-row-fluid:last-child {
border-bottom: none !important;
}
.calendar-view .cal-year-box .cal-cell {
border-right: 1px solid rgba(71, 85, 105, 0.3) !important;
padding: 12px !important;
min-height: 75px;
transition: background-color 150ms ease;
position: relative;
}
.calendar-view .cal-year-box .cal-cell:last-child {
border-right: none !important;
}
.calendar-view .cal-year-box .cal-cell:hover {
background: rgba(59, 130, 246, 0.06) !important;
}
/* Month name in year cell */
.calendar-view .cal-year-box .cal-cell span[data-cal-view="month"] {
color: var(--color-text-secondary, #f1f5f9) !important;
font-weight: 600;
font-size: 0.85rem;
cursor: pointer;
transition: color 150ms ease;
}
.calendar-view .cal-year-box .cal-cell span[data-cal-view="month"]:hover {
color: var(--color-primary-light, #60a5fa) !important;
}
/* Year event count badge */
#CalendarContainer .cal-events-num,
.calendar-view .cal-events-num {
background: var(--color-primary, #3b82f6) !important;
color: #fff !important;
font-size: 0.7rem !important;
font-weight: 700 !important;
border-radius: 6px !important;
padding: 2px 7px !important;
margin-top: 8px;
}
/* Year event dots */
.calendar-view .cal-year-box .events-list .event {
width: 8px !important;
height: 8px !important;
border-radius: 50% !important;
margin: 1px !important;
}
/* --------------------------------------------------------------------------
EVENT POPOVERS / TOOLTIPS
-------------------------------------------------------------------------- */
.calendar-view .popover,
#CalendarContainer .popover,
.XiboSchedule .popover {
background: var(--color-surface-elevated, #334155) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 10px !important;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4) !important;
color: var(--color-text-primary, #fff) !important;
}
.calendar-view .popover .popover-header,
#CalendarContainer .popover .popover-header,
.XiboSchedule .popover .popover-header {
background: rgba(15, 23, 42, 0.6) !important;
border-bottom: 1px solid var(--color-border, #475569) !important;
color: var(--color-text-primary, #fff) !important;
font-weight: 600;
border-radius: 10px 10px 0 0 !important;
padding: 10px 14px !important;
}
.calendar-view .popover .popover-body,
#CalendarContainer .popover .popover-body,
.XiboSchedule .popover .popover-body {
color: var(--color-text-secondary, #f1f5f9) !important;
padding: 10px 14px !important;
}
.calendar-view .popover .popover-body a,
#CalendarContainer .popover .popover-body a,
.XiboSchedule .popover .popover-body a {
color: var(--color-primary-light, #60a5fa) !important;
text-decoration: none !important;
font-weight: 500;
}
.calendar-view .popover .popover-body a:hover,
#CalendarContainer .popover .popover-body a:hover,
.XiboSchedule .popover .popover-body a:hover {
color: var(--color-primary, #3b82f6) !important;
text-decoration: underline !important;
}
/* Popover arrows */
.calendar-view .popover .arrow::before,
.calendar-view .popover .arrow::after {
border-color: transparent !important;
}
/* --------------------------------------------------------------------------
LEGEND
-------------------------------------------------------------------------- */
.cal-legend {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 10px;
padding: 14px 18px !important;
margin-top: 12px;
}
.cal-legend ul {
list-style: none !important;
padding: 0 !important;
margin: 0 !important;
display: flex;
flex-wrap: wrap;
gap: 6px 18px;
}
.cal-legend ul li {
display: inline-flex !important;
align-items: center;
gap: 8px;
color: var(--color-text-secondary, #f1f5f9) !important;
font-size: 0.8rem;
font-weight: 500;
padding: 5px 10px;
border-radius: 6px;
background: rgba(15, 23, 42, 0.4);
border: 1px solid rgba(71, 85, 105, 0.25);
transition: background-color 150ms ease;
}
.cal-legend ul li:hover {
background: rgba(59, 130, 246, 0.06);
}
.cal-legend ul li span.fa {
font-size: 0.85rem;
width: 18px;
text-align: center;
}
/* Legend item icon colors */
.cal-legend li.event-always span.fa { color: #94a3b8 !important; }
.cal-legend li.event-info span.fa { color: #60a5fa !important; }
.cal-legend li.event-success span.fa { color: #34d399 !important; }
.cal-legend li.event-important span.fa { color: #f87171 !important; }
.cal-legend li.event-special span.fa { color: #a78bfa !important; }
.cal-legend li.event-inverse span.fa { color: #64748b !important; }
.cal-legend li.event-command span.fa { color: #fbbf24 !important; }
.cal-legend li.event-interrupt span.fa { color: #fb923c !important; }
.cal-legend li.event-geo-location span.fa { color: #38bdf8 !important; }
.cal-legend li.event-action span.fa { color: #22d3ee !important; }
.cal-legend li.event-sync span.fa { color: #818cf8 !important; }
/* --------------------------------------------------------------------------
AGENDA VIEW MODAL
-------------------------------------------------------------------------- */
.agenda-view-modal .modal-dialog {
max-width: 1200px;
}
.agenda-view-modal .modal-dialog .modal-content {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 14px !important;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45) !important;
}
.agenda-view-modal .modal-dialog .modal-header {
background: rgba(15, 23, 42, 0.8) !important;
border-bottom: 1px solid var(--color-border, #475569) !important;
border-radius: 14px 14px 0 0 !important;
padding: 16px 20px !important;
}
.agenda-view-modal .modal-title {
color: var(--color-text-primary, #fff) !important;
font-weight: 700;
font-size: 1.1rem;
display: inline-flex;
align-items: center;
gap: 8px;
}
.agenda-view-modal .modal-dialog .modal-body {
min-height: 600px;
background: var(--color-surface, #1e293b) !important;
color: var(--color-text-primary, #fff) !important;
padding: 20px !important;
}
/* Agenda table */
.agenda-table {
background: var(--color-surface, #1e293b) !important;
border-radius: 8px !important;
overflow: hidden;
margin-bottom: 20px;
border: 1px solid var(--color-border, #475569) !important;
}
.agenda-table thead {
background: rgba(15, 23, 42, 0.8) !important;
}
.agenda-table thead th {
color: var(--color-text-tertiary, #e2e8f0) !important;
font-weight: 600 !important;
font-size: 0.75rem !important;
text-transform: uppercase;
letter-spacing: 0.04em;
padding: 10px 12px !important;
border-bottom: 1px solid var(--color-border, #475569) !important;
}
.agenda-table .table-title {
background: rgba(59, 130, 246, 0.15) !important;
color: var(--color-text-primary, #fff) !important;
font-weight: 600;
}
.agenda-table tbody tr {
border-bottom: 1px solid rgba(71, 85, 105, 0.25) !important;
color: var(--color-text-secondary, #f1f5f9) !important;
transition: background-color 150ms ease;
}
.agenda-table tbody tr:hover {
background: rgba(59, 130, 246, 0.08) !important;
color: var(--color-primary-light, #60a5fa) !important;
cursor: pointer;
}
.agenda-table tbody tr.selected {
background: rgba(59, 130, 246, 0.2) !important;
color: #fff !important;
}
.agenda-table tbody tr.selected-linked {
background: rgba(59, 130, 246, 0.12) !important;
color: var(--color-text-primary, #fff) !important;
}
.agenda-table tbody tr.low-priority {
color: var(--color-text-tertiary, #e2e8f0) !important;
opacity: 0.6;
}
.agenda-table td {
padding: 10px 12px !important;
vertical-align: middle !important;
border-bottom: 1px solid rgba(71, 85, 105, 0.2) !important;
}
/* Agenda panel */
.agenda-panel .panel-body {
background: var(--color-surface, #1e293b) !important;
padding: 10px 0 0 0;
}
.agenda-panel .panel-heading {
background: var(--color-surface-elevated, #334155) !important;
color: var(--color-text-primary, #fff) !important;
border-bottom: 1px solid var(--color-border, #475569) !important;
}
.agenda-panel .nav-tabs > li.active > a,
.agenda-panel .nav-tabs > li.active > a:hover,
.agenda-panel .nav-tabs > li.active > a:focus {
background: var(--color-primary, #3b82f6) !important;
color: #fff !important;
border-color: var(--color-primary, #3b82f6) !important;
}
.agenda-panel .text-danger {
text-align: center;
vertical-align: middle;
line-height: 90px;
color: var(--color-danger, #ef4444) !important;
}
.agenda-view-modal .agenda-view-loading {
height: 15px;
margin: 6px 0 0 6px;
color: var(--color-primary-light, #60a5fa);
}
/* --------------------------------------------------------------------------
CALENDAR EVENT CONTEXT AREA (breadcrumb, time bar, filters, map)
-------------------------------------------------------------------------- */
.cal-context .tab-pane {
padding-top: 20px !important;
}
.cal-event-time-bar {
margin: 15px 0;
height: 50px;
}
.cal-event-time-bar .slider.slider-horizontal {
float: left;
width: calc(100% - 80px);
margin-top: 7px;
}
.cal-event-time-bar .slider .slider-track {
background: var(--color-surface-elevated, #334155) !important;
border-radius: 4px;
}
.cal-event-time-bar .slider .slider-selection {
background: rgba(59, 130, 246, 0.35) !important;
}
.cal-event-time-bar .slider .slider-handle {
background: var(--color-primary, #3b82f6) !important;
border: 2px solid rgba(255, 255, 255, 0.2);
}
.cal-event-time-bar .slider-step-btn {
float: left;
width: 40px;
color: var(--color-primary-light, #60a5fa);
}
.cal-event-time-bar .slider .tooltip.top {
margin-top: -36px;
z-index: 10;
}
.cal-event-time-bar .slider .tooltip-inner {
font-weight: bold;
font-size: 1rem;
background: var(--color-surface-elevated, #334155) !important;
color: var(--color-text-primary, #fff) !important;
border-radius: 6px;
}
.cal-event-time-bar .slider .slider-tick:not(.in-selection) {
background-image: none !important;
background: var(--color-surface-elevated, #334155) !important;
}
.cal-event-time-bar .slider .slider-tick-label {
width: 60px !important;
transform: translateX(-30px);
margin-left: 0 !important;
overflow: hidden;
color: var(--color-text-tertiary, #e2e8f0) !important;
font-size: 0.7rem;
}
.cal-event-time-bar .slider-handle:hover {
cursor: grabbing;
}
.cal-event-time-bar .tooltip {
z-index: 1040;
}
/* Calendar event within a context panel */
.cal-event {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 8px !important;
overflow: hidden;
margin-bottom: 8px;
}
.cal-event-location {
display: table;
width: inherit;
margin: 6px 0;
}
.cal-event-location > button,
.cal-event-location > div {
margin: 0 2px;
}
.cal-event-location > button {
width: 40px;
}
.cal-event-breadcrumb-trail #content {
text-align: center;
color: var(--color-text-secondary, #f1f5f9);
}
.cal-event-agenda-filter {
margin-top: 15px;
padding: 0 15px;
}
/* --------------------------------------------------------------------------
FLATPICKR DATE PICKER (used for calendar date input)
-------------------------------------------------------------------------- */
.flatpickr-calendar {
background: var(--color-surface, #1e293b) !important;
border: 1px solid var(--color-border, #475569) !important;
border-radius: 10px !important;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4) !important;
color: var(--color-text-primary, #fff) !important;
}
.flatpickr-calendar::before,
.flatpickr-calendar::after {
border-bottom-color: var(--color-border, #475569) !important;
}
.flatpickr-months {
background: rgba(15, 23, 42, 0.6) !important;
border-radius: 10px 10px 0 0;
padding: 4px 0;
}
.flatpickr-months .flatpickr-month {
color: var(--color-text-primary, #fff) !important;
}
.flatpickr-current-month {
color: var(--color-text-primary, #fff) !important;
font-weight: 600;
}
.flatpickr-current-month .flatpickr-monthDropdown-months {
background: transparent !important;
color: var(--color-text-primary, #fff) !important;
font-weight: 600;
}
.flatpickr-current-month input.cur-year {
color: var(--color-text-primary, #fff) !important;
}
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
color: var(--color-text-secondary, #f1f5f9) !important;
fill: var(--color-text-secondary, #f1f5f9) !important;
transition: color 150ms ease;
}
.flatpickr-months .flatpickr-prev-month:hover,
.flatpickr-months .flatpickr-next-month:hover {
color: var(--color-primary-light, #60a5fa) !important;
fill: var(--color-primary-light, #60a5fa) !important;
}
.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
fill: inherit !important;
}
.flatpickr-weekdays {
background: transparent !important;
}
.flatpickr-weekday {
color: var(--color-text-tertiary, #e2e8f0) !important;
font-weight: 600;
font-size: 0.75rem;
}
.flatpickr-day {
color: var(--color-text-secondary, #f1f5f9) !important;
border-radius: 6px !important;
border: 1px solid transparent !important;
transition: all 150ms ease !important;
}
.flatpickr-day:hover {
background: rgba(59, 130, 246, 0.12) !important;
border-color: rgba(59, 130, 246, 0.3) !important;
color: var(--color-primary-light, #60a5fa) !important;
}
.flatpickr-day.today {
border-color: var(--color-primary, #3b82f6) !important;
color: var(--color-primary-light, #60a5fa) !important;
background: rgba(59, 130, 246, 0.1) !important;
}
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange {
background: var(--color-primary, #3b82f6) !important;
border-color: var(--color-primary, #3b82f6) !important;
color: #fff !important;
}
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
color: var(--color-text-tertiary, #e2e8f0) !important;
opacity: 0.35;
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover {
color: var(--color-text-tertiary, #e2e8f0) !important;
opacity: 0.2;
}
/* Month select plugin */
.flatpickr-monthSelect-months {
background: var(--color-surface, #1e293b) !important;
}
.flatpickr-monthSelect-month {
color: var(--color-text-secondary, #f1f5f9) !important;
border-radius: 6px !important;
transition: all 150ms ease;
}
.flatpickr-monthSelect-month:hover {
background: rgba(59, 130, 246, 0.12) !important;
color: var(--color-primary-light, #60a5fa) !important;
}
.flatpickr-monthSelect-month.selected {
background: var(--color-primary, #3b82f6) !important;
color: #fff !important;
}
/* --------------------------------------------------------------------------
LIGHT MODE - Calendar Overrides
-------------------------------------------------------------------------- */
body.ots-light-mode .calendar-view .cal-month-box .cal-row-fluid,
body.ots-light-mode .calendar-view .cal-month-box .cal-row-fluid:hover,
body.ots-light-mode .calendar-view .cal-month-box .cal-before-eventlist:hover,
body.ots-light-mode .cal-month-box .cal-row-fluid:hover,
body.ots-light-mode .cal-month-box .cal-before-eventlist:hover,
body.ots-light-mode #CalendarContainer .cal-row-fluid:hover,
body.ots-light-mode #CalendarContainer .cal-before-eventlist:hover {
background: transparent !important;
background-color: transparent !important;
}
body.ots-light-mode .calendar-view .cal-month-box .cal-row-fluid {
border-bottom-color: rgba(203, 213, 225, 0.6) !important;
}
body.ots-light-mode .calendar-view .cal-month-box .cal-cell {
border-right-color: rgba(203, 213, 225, 0.5) !important;
}
body.ots-light-mode .calendar-view .cal-month-day {
background: transparent !important;
}
body.ots-light-mode .calendar-view .cal-month-day.cal-day-today {
background: rgba(59, 130, 246, 0.08) !important;
box-shadow: inset 0 0 0 1px rgba(59, 130, 246, 0.25);
}
body.ots-light-mode .calendar-view .cal-month-day-number {
color: var(--color-text-primary, #1e293b) !important;
}
body.ots-light-mode .calendar-view .cal-month-day.cal-day-outmonth,
body.ots-light-mode .calendar-view .cal-month-day.cal-day-outmonth .cal-month-day-number {
opacity: 0.4;
}
body.ots-light-mode .calendar-view .cal-month-day-number:hover {
background: rgba(59, 130, 246, 0.1);
color: var(--color-primary, #3b82f6) !important;
}
body.ots-light-mode .calendar-view .cal-day-today .cal-month-day-number {
background: var(--color-primary, #3b82f6) !important;
color: #fff !important;
}
/* --------------------------------------------------------------------------
RESPONSIVE ADJUSTMENTS
-------------------------------------------------------------------------- */
@media (max-width: 768px) {
.cal-legend ul {
flex-direction: column;
gap: 4px;
}
.cal-legend ul li {
font-size: 0.75rem;
padding: 4px 8px;
}
.calendar-view .cal-month-day {
min-height: 60px;
padding: 2px 3px !important;
}
.calendar-view .cal-month-day-number {
font-size: 0.7rem !important;
}
.calendar-view .cal-month-day .events-list .event {
width: 16px !important;
height: 16px !important;
font-size: 0.55rem !important;
}
.xibo-calendar-header h1.page-header {
font-size: 1.15rem !important;
}
.ots-cal-arrow {
width: 30px;
height: 30px;
font-size: 0.75rem;
}
.ots-calendar-nav {
gap: 10px;
}
}