/* 1. Global Styles */

:root {
    /* Native widget scheme (OS select pickers, scrollbars, form controls).
       agent.themes.setTheme also sets this inline at runtime; declaring it
       here (and via the boot pages' meta) covers everything that renders
       before boot. The app is dark-only by design. */
    color-scheme: dark;

    --sat: env(safe-area-inset-top, 0px);
    --sar: env(safe-area-inset-right, 0px);
    --sab: env(safe-area-inset-bottom, 0px);
    --sal: env(safe-area-inset-left, 0px);

    /* Design tokens — dark chrome palette.
       The main UI (top button clusters, tab pills, drawers, side menu, alerts
       panel, context menus, playback transport) always renders with these
       tokens regardless of the selected Bootstrap theme — the theme stylesheet
       only skins #editor modal content. The user-selectable canvas palette
       (themes.canvasThemes in script/vue/themes.js, storage key "canvasTheme")
       overwrites these at runtime via themes.syncCSSTokens; the fallbacks
       below must match canvasThemes.Spectre, the default. */
    --t-surface: #0A0E14;
    --t-surface-raised: #101823;
    --t-surface-overlay: rgba(120,220,255,0.04);
    --t-surface-hover: rgba(120,220,255,0.08);
    --t-surface-active: rgba(120,220,255,0.05);
    --t-border: rgba(120,220,255,0.14);
    --t-border-subtle: rgba(120,220,255,0.08);
    --t-border-medium: rgba(120,220,255,0.18);
    --t-text-primary: #DCEEF2;
    --t-text-secondary: #93B4BE;
    --t-text-muted: rgba(200,240,255,0.50);
    --t-text-faint: rgba(200,240,255,0.35);
    --t-accent: #00D4E8;
    --t-accent-subtle: rgba(0,212,232,0.12);
    --t-accent-text: #5CF2FF;
    --t-tag-bg: rgba(120,220,255,0.08);
    --t-tag-text: rgba(200,240,255,0.50);
    --t-toolbar: #0D141D;
    --t-chrome-hover: #16283A;
    --t-warning: #FF9326;
    --t-shadow: rgba(2,10,16,0.7);
}

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    overflow: hidden;
    -webkit-text-size-adjust: none;
    touch-action: manipulation;
}

/* Native select picker rows (mobile full-page list / desktop dropdown).
   The picker chrome is OS-rendered — color-scheme flips it dark where the
   browser honors it — but option rows honor colors on Android/desktop.
   --bs-* vars resolve against the loaded dialog theme, so rows match the
   active palette. color-scheme declared on the select itself too: some
   Chrome versions key the popup off the CONTROL's own computed value. */
select {
    color-scheme: dark;
}

select option,
select optgroup {
    background-color: var(--bs-body-bg, #0A0E14);
    color: var(--bs-body-color, #DCEEF2);
}

body {
    margin: 0;
    padding: 0;
    position: relative;
    border: 0;
    outline: 0;
    background-color: var(--t-surface, #0A0E14);
    -webkit-overflow-scrolling: touch;
    overflow: hidden;
    overscroll-behavior: none;
}

#content {
    position: relative;
}

/* 2. Centering Elements */
.center-block {
    display: block;
    margin-left: auto;
    margin-right: auto;
}

.centered {
    text-align: center;
}

/* 3. Canvas Styles */
canvas {
    padding: 0px;
    margin: 0px;
    -moz-user-select: none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    user-select: none;
    outline: none;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

/* 5. Headings */
h3 {
    padding-inline-start: 10px;
}

/* 6. Scrollable Div */
.scrollDiv {
    max-height: 350px;
    overflow-y: auto;
    margin-bottom: 10px;
}

/* 7. Agent Table */
.agentTable tr td:last-child {
    width: 1%;
    white-space: nowrap;
}

/* 8. Render Engine */
.renderEngine {
    border: solid 1px #ccc;
}

/* 9. Modal Open Body */
body.modal-open {
    overflow: hidden;
}

/* 10. ScrollDiv Buttons */
.scrollDiv div button {
    margin: 1px;
    padding: 4px;
}

/* 11. Alert Container — the centered boot/status box (popAlertBox: loading,
   login, SSL errors). Chrome, not dialog content: the token surface below
   overrides the markup's Bootstrap alert-dark grey. */
#alertcontainer {
    visibility: hidden;
    margin: auto;
    text-align: center;
    position: fixed;
    z-index: 2;
    top: calc(50% - 50px);
    left: 0; /* fallback for browsers without inset-inline-* (pre-Chrome 87) */
    right: 0;
    inset-inline-start: 0;
    inset-inline-end: 0;
    width: min(calc(300px * var(--ui-scale, 1)), 92vw);
    content-visibility: auto;
}

#alerttext {
    background-color: var(--t-surface-raised);
    color: var(--t-text-primary);
    border: 1px solid var(--t-border);
    border-radius: 12px;
    box-shadow: 0 4px 16px var(--t-shadow);
    font-size: calc(1rem * var(--ui-scale, 1));
}

    #alertcontainer.show {
        visibility: visible;
        -webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
        animation: fadein 0.5s, fadeout 0.5s 2.5s;
    }

/* 12. Active Dropdown Items — tokenized (was legacy light-theme greys) */
.active .dropdown-item {
    color: var(--t-text-primary);
    text-decoration: none;
    background-color: var(--t-surface-hover);
}

/* 13. Word Break */
.wordbreak {
    word-break: break-word;
}

/* 14. Font Awesome Size Adjustments */
.fa-xs {
    font-size: .75em !important;
}

.fa-sm {
    font-size: .875em !important;
}

/* Top bar styling */
#navTop {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.5rem 1rem;
    height: 50px; /* Set fixed height for top bar */
}

/* Icon panel styling */
.iconPanel {
    padding: 0.25rem 0.5rem;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}

/* Icon items styling */

.iconItem {
    display: flex;
    flex-direction: column;
    align-items: center;
    color: inherit;
    padding: 5px 5px;
    cursor: pointer;
    border-radius: 4px;
    margin: 3px;
    text-align: center;
    opacity: 1;
}

/* Active state uses the fixed accent tokens — same treatment as unread alert
   items and the active tab pill, so all chrome selection states match. */
.iconItem.active {
    background-color: var(--t-accent-subtle);
    color: var(--t-accent-text);
}

/* Accent glow on active chrome controls — all canvas palettes. Every color
   comes from --t-accent-subtle, so each palette glows in its own accent
   (Moonraker blue, Skyfall green, Spectre cyan). */
.iconItem.active,
.navControl.active,
#context-menu .dropdown-item.active {
    box-shadow: 0 0 10px var(--t-accent-subtle), inset 0 0 6px var(--t-accent-subtle);
    text-shadow: 0 0 8px var(--t-accent-subtle);
}

.navControl:hover {
    box-shadow: 0 0 8px var(--t-accent-subtle);
}

/* Glow motion. box-shadow/opacity animation repaints, but only a handful of
   small pills at multi-second periods — negligible next to the always-
   rendering video canvases. Static-glow rules above remain as the fallback
   for reduced-motion users. */
@media (prefers-reduced-motion: no-preference) {
    /* Active controls breathe instead of holding a static glow */
    .iconItem.active,
    .navControl.active,
    #context-menu .dropdown-item.active {
        animation: glowBreathe 3.2s ease-in-out infinite;
    }

    /* Unread alert marker pulses like a status LED */
    .alert-actions i.unread {
        animation: glowPulse 2.4s ease-in-out infinite;
    }
}

/* Both keyframes must keep the SAME shadow count/order/inset-ness — shadow
   lists that don't match item-for-item can't interpolate, and the animation
   degrades to a discrete on/off swap at the midpoint. */
@keyframes glowBreathe {
    0%, 100% { box-shadow: 0 0 7px var(--t-accent-subtle), 0 0 2px var(--t-accent-subtle), inset 0 0 5px var(--t-accent-subtle); }
    50%      { box-shadow: 0 0 14px var(--t-accent-subtle), 0 0 5px var(--t-accent-subtle), inset 0 0 8px var(--t-accent-subtle); }
}

@keyframes glowPulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.45; }
}

/* Zone editor container (ZoneManager/MotionMap in RenderModal) — a recessed
   well grouping the area/zone/tool controls with the canvas so they read as
   one instrument. --bs-* vars: sits inside #editor, so it follows the
   dialog theme (body-bg is darker than the modal surface = inset). */
.zone-editor {
    background-color: var(--bs-body-bg, #0A0E14);
    border: 1px solid var(--bs-border-color-translucent, rgba(120, 220, 255, 0.14));
    border-radius: 12px;
    padding: 12px;
}

/* Phone-width dialogs: every horizontal pixel goes to the canvas */
@media (max-width: 576px) {
    .zone-editor {
        padding: 8px;
    }
}

/* Zone editor canvases (ZoneCanvas.js) — a layered drop shadow lifts the
   editor off the dialog surface so it reads as floating slightly above it.
   The faint border keeps the edge defined where the shadow fades into dark
   surfaces. */
.zone-canvas {
    border: 1px solid var(--t-border-subtle);
    border-radius: 8px;
    box-shadow: 0 4px 10px var(--t-shadow), 0 14px 30px var(--t-shadow);
}

/* Small meters (mic volume bar) stay flat — elevation on a strip a few px
   tall just looks like a smudge. */
.zone-canvas[data-mode="volume"] {
    border: none;
    border-radius: 4px;
    box-shadow: none;
}

.iconItem i {
    font-size: 1.25rem;
    margin-bottom: 0.5rem;
}

.iconItem span {
    font-size: 0.8rem;
    white-space: nowrap;
}


/* Left, center, right sections of top bar */
.nav-left, .nav-center, .nav-right {
    display: flex;
    align-items: center;
}

.nav-left {
    justify-content: flex-start;
    flex: 1;
}

.nav-center {
    justify-content: center;
    flex: 1;
}

.nav-right {
    justify-content: flex-end;
    flex: 1;
}

#alerts-content {
    overflow-y: auto;
    overflow-x: hidden;
    border-radius: 0;
    max-height: 80vh;
    max-height: 80dvh;
    padding: 0;
    background-color: var(--t-surface);
    color: var(--t-text-primary);
}

/* Themed thin scrollbars, app-wide (chrome panels, dialogs, tables). The
   thumb uses the same palette token the canvas virtual scrollbars draw with
   (--t-scrollbar, set by themes.syncCSSTokens; hover steps up to the
   palette's eventBar grey). The rgba fallbacks cover anything that renders
   before boot. The standard properties cover Firefox and Chrome 121+
   (which ignores the -webkit pseudos when these are set); the pseudos cover
   older Chromium. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--t-scrollbar, rgba(255,255,255,0.22)) transparent;
}

::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-corner {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background-color: var(--t-scrollbar, rgba(255,255,255,0.22));
    border-radius: 8px;
    /* transparent border + padding-box clip fakes a gutter around the thumb */
    border: 2px solid transparent;
    background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
    background-color: var(--t-scrollbar-hover, rgba(255,255,255,0.35));
    background-clip: padding-box;
}

#sidebar {
    position: fixed;
    z-index: 900;
    opacity: 0;
    transition: transform 0.3s ease-in-out, opacity 0.2s linear;
    height: auto;
    content-visibility: auto;
    transform: translateY(-10px);
}

    #sidebar.active {
        margin-inline-start: 0px;
        opacity: 1;
        visibility: visible;
        transform: translateY(50px);
        transition: transform 0.3s ease-in-out, opacity 0.2s linear;
    }

/* Enhanced Alerts Styles */
.alerts-card {
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--t-border);
    background-color: var(--t-surface);
    color: var(--t-text-primary);
    box-shadow: 0 4px 16px var(--t-shadow);
}

.alerts-header {
    border-bottom: 1px solid var(--t-border-subtle);
}

    /* Server name — panel title weight, scaling with the Size setting.
       flex+ellipsis: the name takes the leftover row width and truncates,
       so a long name or big scale can never collide with the header
       buttons (which are flex-shrink:0). */
    .alerts-header span {
        font-size: calc(1.15rem * var(--ui-scale, 1));
        font-weight: 600;
        letter-spacing: 0.03em;
        opacity: 0.9;
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

/* Header Buttons */
.header-buttons {
    display: flex;
    gap: 2px;
    margin-inline-start: auto;
    flex-shrink: 0;
}

    /* The alerts panel follows the account Size setting via the --ui-scale
       vars published by helpers.sizeIcons(): full scale for text and
       thumbnails, the gentler icon curve for icon boxes — same split as the
       bottom drawer. */
    .header-buttons i {
        font-size: calc(1rem * var(--ui-scale-icon, 1));
        color: var(--t-text-primary);
        cursor: pointer;
        width: calc(32px * var(--ui-scale-icon, 1));
        height: calc(32px * var(--ui-scale-icon, 1));
        display: inline-flex;
        align-items: center;
        justify-content: center;
        border-radius: 6px;
        opacity: 0.5;
        transition: opacity 0.15s ease, background-color 0.15s ease;
        padding: 0;
    }

        .header-buttons i.text-warning {
            /* !important beats Bootstrap's .text-warning utility, which would
               otherwise re-tint this per-theme. */
            color: var(--t-warning) !important;
            opacity: 0.9;
        }

/* Alert Items */
#alerts-content {
    padding: 6px;
}

.alert-item {
    display: flex;
    gap: 12px;
    padding: 10px;
    cursor: pointer;
    border-radius: 8px;
    margin-bottom: 4px;
    background-color: var(--t-surface-overlay);
    transition: background-color 0.15s ease;
    border-inline-start: 3px solid transparent;
}

    .alert-item:last-child {
        margin-bottom: 0;
    }

    .alert-item.unread-item {
        background-color: var(--t-surface-active);
        border-inline-start-color: var(--t-accent);
    }

.alert-image-container {
    width: calc(80px * var(--ui-scale, 1));
    height: calc(56px * var(--ui-scale, 1));
    flex-shrink: 0;
    border-radius: 6px;
    overflow: hidden;
    background-color: var(--t-surface);
}

.alert-details {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.alert-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.alert-title {
    font-weight: 500;
    display: flex;
    align-items: center;
    font-size: calc(0.85rem * var(--ui-scale, 1));
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--t-text-primary);
}

    .alert-title i {
        margin-inline-end: 5px;
        font-size: calc(0.85rem * var(--ui-scale, 1));
        opacity: 0.6;
    }

.alert-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: calc(0.75rem * var(--ui-scale, 1));
    color: var(--t-text-primary);
    opacity: 0.5;
    margin-top: 4px;
}

.alert-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

    .alert-actions i {
        cursor: pointer;
        color: var(--t-text-primary);
        opacity: 0.35;
        transition: opacity 0.15s ease;
        font-size: calc(0.85rem * var(--ui-scale, 1));
    }

    .alert-actions i.unread {
        color: var(--t-accent);
        opacity: 1;
    }

/* Tags styling */
.alert-tag {
    display: inline-block;
    background-color: var(--t-tag-bg);
    color: var(--t-tag-text);
    padding: 1px 8px;
    border-radius: 10px;
    font-size: calc(0.7rem * var(--ui-scale, 1));
}

#badgeAlertCount.hidden {
    display: none;
}
/* 18. Cursor Styles */
.nav-link, .dropdown-item {
    cursor: pointer;
}

.viewoption {
    cursor: pointer;
    padding: 5px;
}

/* 19. Editor Padding */
#editor {
    padding-inline-start: 0 !important;
    content-visibility: auto;
}

/* 20. Fix Width */
.fixwidth {
    width: 1em !important;
}

/* 21. Dropdown Menu */
.dropdown-menu {
    max-height: calc(100vh - 20px);
    max-height: calc(100dvh - 20px);
    overflow-y: auto;
    font-size: 1rem !important; /* Moved up from bottom */
}

/* Context menu floats over the always-dark canvas, so it uses the fixed
   chrome palette rather than the Bootstrap theme. Dropdowns inside #editor
   modals keep the theme's own styling. */
#context-menu.dropdown-menu {
    background-color: var(--t-surface-raised);
    color: var(--t-text-primary);
    border: 1px solid var(--t-border);
    box-shadow: 0 4px 16px var(--t-shadow);
}

#context-menu .dropdown-item {
    color: var(--t-text-primary);
}

#context-menu .dropdown-item:hover,
#context-menu .dropdown-item:focus {
    background-color: var(--t-surface-hover);
    color: var(--t-text-primary);
}

#context-menu .dropdown-item.active {
    background-color: var(--t-accent-subtle);
    color: var(--t-accent-text);
}

#context-menu .dropdown-item.disabled {
    color: var(--t-text-faint);
}

#context-menu .dropdown-divider {
    border-color: var(--t-border-subtle);
}

#context-menu .dropdown-header {
    color: var(--t-text-muted);
}

/* 22. Alert Image */
.alertimage {
    margin-inline-end: 10px;
    float: inline-start;
}

/* 24. Connected Sortable */
.connectedSortable {
    background-color: #666666;
    cursor: pointer;
}

/* 25. View Preview */
.view-preview {
    display: flex !important;
    align-items: center;
    overflow: hidden;
}

    .view-preview img {
        display: inline-block;
        vertical-align: middle;
        margin-inline-end: 10px;
    }

    .view-preview span {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

.menu-border-right {
    border-inline-end: 2px solid;
    color: #666666;
    padding-inline-end: 10px;
    margin-inline-end: 10px;
}

/* 27. Nav Playback */
#navPlayback {
    position: absolute;
    opacity: 0.8;
}

/* 28. Unselectable Elements */
.unselectable {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

/* 29. Toast Positioning */
/* Bounce via translateY OFFSETS, never `top`: with fill-mode forwards, a
   `top` in the 100% keyframe overrides the positioning rules entirely
   (which is how the toast got stuck at 40px under the scaled chrome). */
@keyframes bounceDown {
    0% {
        opacity: 0;
        transform: translateX(-50%) translateY(-140px) scale(0.3);
    }

    50% {
        opacity: 1;
    }

    65% {
        transform: translateX(-50%) translateY(10px) scale(1.05);
    }

    80% {
        transform: translateX(-50%) translateY(-5px) scale(0.95);
    }

    95% {
        transform: translateX(-50%) translateY(2px) scale(1.02);
    }

    100% {
        opacity: 1;
        transform: translateX(-50%) translateY(0) scale(1);
    }
}

#toast {
    position: absolute;
    left: 50%;
    top: -100px;
    transform: translateX(-50%);
    opacity: 0;
    transition: opacity 0.2s ease-out;
    /* Status feedback outranks ALL ambient chrome: above the top pills
       (990), drawers (1051), dialogs (1055), and the context menu (1100) —
       without this it rendered UNDER the pill row on narrow screens. */
    z-index: 1200;
    /* showToast pins an inline measured top, so the faded-out toast stays
       in-viewport at opacity 0 — it must not swallow clicks there. */
    pointer-events: none;
}

    #toast.show {
        animation: bounceDown 0.6s ease forwards;
        /* Fallback position (showToast normally pins a measured inline top):
           clear of the top pill cluster at every Size step. */
        top: calc(var(--sat) + 24px + 44px * var(--ui-scale-icon, 1));
        opacity: 1;
        pointer-events: auto;
    }

/* 30. Navbar Item Margins */
.nav-item {
    margin-inline-start: 0px !important;
    margin-inline-end: 0px !important;
}

/* 31. Live Control Icon */
.live-control::before {
    content: '\e0b7';
    font-family: "Font Awesome 6 Pro";
    font-weight: 900;
    margin-inline-end: 5px;
    color: var(--t-warning, #FF9326);
}

[dir="rtl"] {
    direction: rtl;
}

    [dir="rtl"] .center-block {
        margin-inline-start: auto;
        margin-inline-end: auto;
    }

    [dir="rtl"] .menu-border-right {
        border-inline-end: 2px solid;
        padding-inline-end: 10px;
        margin-inline-end: 10px;
    }

    [dir="rtl"] .view-preview img {
        margin-inline-end: 10px; /* Maintains spacing in RTL */
    }

    [dir="rtl"] .alertimage {
        float: right;
    }


/* column-reverse stacks DOM order bottom-up: #tabControls (first child)
   docks at the bottom edge and never moves; #navControls pops up above it
   as a floating panel. No align-items override — the default stretch keeps
   the panel full-width on mobile while width:fit-content (desktop, below)
   and the tabs' own fit-content opt out of stretching and align to the
   inline-start edge in both LTR and RTL. */
#navWrapper {
    position: fixed;
    left: var(--sal); /* fallback for browsers without inset-inline-* (pre-Chrome 87) */
    right: var(--sar);
    inset-inline-start: var(--sal);
    inset-inline-end: var(--sar);
    bottom: var(--sab);
    z-index: 1000;
    opacity: 0.9;
    pointer-events: none;
    display: flex;
    flex-direction: column-reverse;
    transition: opacity 0.2s ease;
}

#navWrapper.hidden #tabControls {
    opacity: 0;
    pointer-events: none;
    transform: translateY(calc(100% + 8px + var(--sab)));
}
/* Tabs: a fixed dock at the bottom edge — the drawer pops up above them and
   selecting the active tab again closes it (no separate hide button).
   Styled as a floating pill cluster — the same design language as the
   playback transport (#bmnuplayback): raised dark surface, full radius,
   soft shadow, transparent buttons inside. */
#tabControls {
    position: relative;
    z-index: 1050;
    pointer-events: auto;
    display: flex;
    width: fit-content;
    gap: 2px;
    padding: 4px;
    background-color: var(--t-toolbar);
    border-radius: 24px;
    box-shadow: 0 2px 8px var(--t-shadow);
    margin: 0 8px 8px 8px;
    transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
    opacity: 1;
}


/* Drawer content — floating popover above the tab dock, same surface family
   as the tab pill and playback transport. Hidden state keeps it in flow
   (the wrapper is pointer-events:none, so the invisible box can't swallow
   clicks) and fades/slides it in from just below its resting spot;
   visibility flips after the fade so hidden buttons can't take focus. */
#navControls {
    position: relative;
    border: none;
    margin: 0 8px 8px 8px;
    border-radius: 16px;
    box-shadow: 0 2px 8px var(--t-shadow);
    overflow: hidden; /* clip square children (e.g. #tmCanvas) to the radius */
    background-color: var(--t-toolbar);
    color: var(--t-text-primary);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(12px);
    transition: transform 0.25s ease-in-out, opacity 0.25s ease-in-out, visibility 0s linear 0.25s;
}

/* Time-machine bar — recessed "well" so the overview scrubber reads as its
   own control rather than a continuation of the detail timeline above it:
   darker surface with a defined top edge and inset shadows for depth. */
#deviceTimeMachine {
    background-color: var(--t-surface);
    border-top: 1px solid var(--t-border-medium);
    box-shadow: inset 0 8px 10px -8px var(--t-shadow),
                inset 0 -8px 10px -8px var(--t-shadow);
}


/* Desktop (the same lg breakpoint where the button panels switch to
   justify-content-lg-start): the buttons sit left-aligned, so shrink the
   panel to its content instead of spanning the viewport and covering
   video with dead space. The time-machine bar still needs the width for
   its timeline, so it keeps filling — capped so it doesn't sprawl across
   very wide monitors. data-controls-mode is stamped on #navWrapper by
   menu.setControlsMode(); the definite width opts out of the flex-column
   stretch and the item falls back to cross-start alignment, i.e. the
   inline-start edge in both LTR and RTL.
   NOTE: this 992px breakpoint is deliberately DIFFERENT from the 600px
   "narrow" threshold in helpers.isNarrow() (canvas top-offset logic).
   Different questions, different numbers — do not unify them. */
@media (min-width: 992px) {
    #navControls {
        width: fit-content;
        min-width: 320px; /* never narrower than the tab pill below it */
        max-width: calc(100% - 16px); /* preserve the 8px side margins */
    }

    #navWrapper[data-controls-mode="timemachine"] #navControls {
        width: auto;
        max-width: 1024px;
    }
}

.navControl {
    /* 44px minimum hit target, matching .btnPlaybackControl */
    min-width: 44px;
    min-height: 44px;
    padding: 10px 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 1050;
    opacity: 1;
    border: none;
    border-radius: 20px;
    background-color: transparent;
    color: var(--t-text-secondary);
    /* box-shadow included so the hover glow (style.css glow block) fades */
    transition: background-color 0.2s ease, color 0.2s ease, box-shadow 0.3s ease;
}

/* Tab icons follow the account Size setting (same curve as toolbar icons —
   --ui-scale-icon is set on <html> by helpers.sizeIcons()). */
.navControl svg {
    width: calc(20px * var(--ui-scale-icon, 1));
    height: calc(20px * var(--ui-scale-icon, 1));
}

.navControl.active {
    z-index: 1051;
    background-color: var(--t-accent-subtle);
    color: var(--t-accent-text) !important;
}

/* Collapse cue: the active tab (== its panel is open) grows a small
   chevron-down after its icon, hinting that tapping again closes the
   panel. Pure CSS (two borders rotated 45°) so it needs no icon font;
   currentColor keeps it on-accent (and warning-tinted on the TM tab). */
.navControl.active::after {
    content: "";
    flex: none;
    width: calc(7px * var(--ui-scale-icon, 1));
    height: calc(7px * var(--ui-scale-icon, 1));
    margin-inline-start: 7px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg) translate(-1px, -1px);
    opacity: 0.75;
}

/* Time-machine bar tab — persistent highlight while in TM (scrub) mode,
   independent of which bar is currently selected. */
.navControl.tm-active {
    color: var(--t-warning) !important;
}
.navControl.tm-active.active {
    color: var(--t-warning) !important;
    background-color: rgba(255,147,38,0.15);
}

/* Open state: pop the panel in above the tabs */
#navWrapper.visible #navControls {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: transform 0.25s ease-in-out, opacity 0.25s ease-in-out, visibility 0s;
}

/* Scrim behind slide-out nav */
#navScrim {
    position: fixed;
    top: 0; /* explicit longhands instead of `inset: 0` (pre-Chrome 87 support) */
    right: 0;
    bottom: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1055;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease-in-out;
}

#navScrim.visible {
    opacity: 1;
    pointer-events: auto;
}

/* Navigation system container — slide-out panel from the left */
#navSystem {
    position: fixed;
    top: var(--sat);
    bottom: var(--sab);
    left: var(--sal); /* fallback for browsers without inset-inline-* (pre-Chrome 87) */
    inset-inline-start: var(--sal);
    width: 260px;
    z-index: 1060;
    box-shadow: 2px 0 10px rgba(0,0,0,0.3);
    transform: translateX(-100%);
    transition: transform 0.3s ease-in-out;
    overflow-y: auto;
    visibility: visible;
}
[dir="rtl"] #navSystem {
    left: auto; /* undo LTR physical fallback */
    right: var(--sal);
    transform: translateX(100%);
}
#navSystem {
    background-color: var(--t-toolbar);
    color: var(--t-text-primary);
    display: flex;
    flex-direction: column;
}

#navSystem #navTop {
    flex-shrink: 0;
}

#navSystem.visible {
    transform: translateX(0);
}


/* Stack icon items vertically in the slide-out panel */
#navSystem .iconPanel {
    flex-direction: column;
    padding: 0.25rem 0;
    flex: 1 0 auto;
}

/* Divider above the Help item; margin-top:auto pushes it (and Help) to the panel bottom */
#navSystem .menu-divider {
    margin: auto 1rem 0.25rem;
    padding-top: 0.5rem;
    border-bottom: 1px solid var(--t-border);
}

#navSystem .iconItem {
    flex-direction: row;
    justify-content: flex-start;
    padding: 0.6rem 1rem;
    gap: 0.75rem;
}

#navSystem .iconItem i {
    margin-bottom: 0;
    width: 1.5rem;
    text-align: center;
}

/* Top icon clusters — floating pills matching the bottom dock language
   (#tabControls/#navControls): toolbar surface, subtle border, standard
   shadow, 8px standoff. Opaque per the control-surface policy — these sit
   over live video. Buttons inside are flattened below; the pill supplies
   the surface. */
#mainControls {
    position: fixed;
    top: calc(var(--sat) + 8px);
    left: calc(var(--sal) + 8px); /* fallback for browsers without inset-inline-* (pre-Chrome 87) */
    inset-inline-start: calc(var(--sal) + 8px);
    padding: 5px 5px;
    cursor: pointer;
    display: inline-block;
    background-color: var(--t-toolbar);
    border: 1px solid var(--t-border-subtle);
    border-radius: 22px;
    box-shadow: 0 2px 8px var(--t-shadow);
    transform: translateX(0);
    transition: transform 0.3s ease-in-out, opacity 0.3s ease;
    z-index: 990;
    opacity: 1;
}

#mainControls2 {
    position: fixed;
    top: calc(var(--sat) + 8px);
    right: calc(var(--sar) + 8px); /* fallback for browsers without inset-inline-* (pre-Chrome 87) */
    inset-inline-end: calc(var(--sar) + 8px);
    padding: 5px 5px;
    cursor: pointer;
    display: inline-block;
    background-color: var(--t-toolbar);
    border: 1px solid var(--t-border-subtle);
    border-radius: 22px;
    box-shadow: 0 2px 8px var(--t-shadow);
    transform: translateX(0);
    transition: transform 0.3s ease-in-out;
    z-index: 990;
    opacity: 1;
}

/* Inside the pills the buttons sit on the pill's surface — flatten their
   individual card backgrounds (the ID selectors out-rank the base
   .btn-theme-toggle rules, so hover/active chips are re-asserted). */
#mainControls .btn.btn-theme-toggle,
#mainControls2 .btn.btn-theme-toggle {
    --bs-btn-bg: transparent;
    background-color: transparent;
}

#mainControls .btn.btn-theme-toggle:hover,
#mainControls .btn.btn-theme-toggle:active,
#mainControls2 .btn.btn-theme-toggle:hover,
#mainControls2 .btn.btn-theme-toggle:active {
    background-color: var(--t-chrome-hover);
}

#mainControls.hidden {
    /* 8px standoff so the peeking chevron isn't flush against the screen
       edge — matches the drawer/pill margins. */
    left: 8px; /* fallback for browsers without inset-inline-* (pre-Chrome 87) */
    padding-left: 0;
    inset-inline-start: 8px;
    padding-inline-start: 0;
    transform: translateX(calc(-75%));
    opacity: 0.4;
}

[dir="rtl"] #mainControls {
    left: auto; /* undo LTR physical fallback */
    right: calc(var(--sal) + 8px);
}

[dir="rtl"] #mainControls2 {
    right: auto; /* undo LTR physical fallback */
    left: calc(var(--sar) + 8px);
}

[dir="rtl"] #mainControls.hidden {
    left: auto; /* undo LTR physical fallback */
    right: 8px;
    padding-left: 5px;
    padding-right: 0;
    transform: translateX(calc(75%));
}

#mainControls2.hidden {
    /* +8px: the cluster now rests 8px off the edge (pill standoff), so the
       slide-away must cover that gap too or a sliver of pill stays visible. */
    transform: translateX(calc(100% + var(--sar) + 8px));
}

[dir="rtl"] #mainControls2.hidden {
    /* RTL puts this cluster on the LEFT — mirror the slide or it travels
       across the viewport instead of off it (pre-existing gap). */
    transform: translateX(calc(-100% - var(--sar) - 8px));
}

/* Fullscreen toggle lives in the top-right cluster. Hidden in the native
   mobile apps (isApp — they're already fullscreen), in browsers without
   the Fullscreen API (noFullscreen — feature-detected in agent.js), and
   when framed (multi view has its own fullscreen toggle). Any browser
   that supports the API gets the button, mobile included. */
body.isApp #liFullScreen,
body.noFullscreen #liFullScreen,
body.isFramed #liFullScreen {
    display: none;
}

[dir="rtl"] #mainControls2.hidden {
    transform: translateX(calc(-100% - var(--sal)));
}


@media (hover: hover) and (pointer: fine) {
    .btnPlaybackControl:hover {
        opacity: 1 !important;
    }

    .alert-item:hover {
        background-color: var(--t-surface-hover);
    }

    .header-buttons i:hover {
        opacity: 0.85;
        background-color: var(--t-tag-bg);
    }

    .alert-actions i:hover {
        opacity: 0.7;
    }

    .iconItem:not(.active):hover {
        background-color: rgba(255, 255, 255, 0.1);
    }

    #tabControls:hover {
        opacity: 1;
    }

    #mainControls:hover, #mainControls2:hover {
        opacity: 1;
    }

    #mainControls.hidden:hover,
    #mainControls2.hidden:hover {
        opacity: 1;
    }

    #navWrapper:hover {
        opacity: 1;
        /* Intentionally NOT pointer-events:auto — that made the entire
           wrapper box catch clicks on hover, swallowing clicks meant for
           overlapping overlays (e.g. the context menu near the tabs).
           The interactive children (#tabControls, #navControls) are already
           pointer-events:auto, and :hover still fires here via those
           children, so the opacity fade-in is unaffected. */
    }

    .navControl:not(.active):hover {
        background-color: var(--t-surface-hover);
        color: var(--t-text-primary);
    }
}

/* Anchor the count bubble to the alerts button itself (not the fixed
   #mainControls2 container) so it stays on the bell regardless of button
   order; the container already handles the safe-area inset. */
#btn-alerts {
    position: relative;
}

.notification-dot {
    position: absolute;
    top: -2px;
    right: -2px; /* fallback for browsers without inset-inline-* (pre-Chrome 87) */
    inset-inline-end: -2px;
    font-size: calc(0.65rem * var(--ui-scale-icon, 1));
    font-weight: 600;
    /* Accent bubble with surface-dark ink — readable on every palette's
       accent without needing an "on-accent" token (was hardcoded #1268F8). */
    background-color: var(--t-accent);
    color: var(--t-surface);
    border-radius: 50%;
    min-width: calc(16px * var(--ui-scale-icon, 1));
    height: calc(16px * var(--ui-scale-icon, 1));
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

[dir="rtl"] .notification-dot {
    right: auto; /* undo LTR physical fallback */
    left: -2px;
}


/* 15. Wrapper Flexbox */
.wrapper {
    display: flex;
    width: 100%;
    height: 100%; /* Use 100% instead of 100vh */
    align-items: stretch;
    padding-left: var(--sal);
    padding-right: var(--sar);
    padding-top: var(--sat);
    padding-bottom: var(--sab);
    box-sizing: border-box; /* Include padding in the element's total width and height */
}

#mainApp {
    position: relative;
    flex: 1;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    display: flex;
}

/* Status toast (helpers.setStatus/showToast) — same floating-surface family
   as the pills and drawers: rounded, bordered, shadowed, and scaling with
   the account Size setting. */
.toastMessage {
    background-color: var(--t-surface-raised);
    color: var(--t-text-primary);
    padding: 10px 16px;
    margin: 0px;
    cursor: pointer;
    border-radius: 12px;
    border: 1px solid var(--t-border);
    box-shadow: 0 4px 16px var(--t-shadow);
    font-size: calc(1rem * var(--ui-scale, 1));
    max-width: min(92vw, 520px);
    text-align: center;
}

    .toastMessage.error {
        border-inline-start: 5px solid #B20000;
    }

/* Transport cluster: a single rounded surface the individual buttons sit on. */
#bmnuplayback {
    gap: 2px;
    padding: 4px;
    background-color: var(--t-toolbar);
    border-radius: 28px;
    box-shadow: 0 2px 8px var(--t-shadow);
}

.btnPlaybackControl {
    background-color: transparent !important;
    border-color: transparent !important;
    color: var(--t-text-primary) !important;
    opacity: 0.7 !important;
    /* 44px minimum hit target (WCAG 2.5.5 / touch guidance) */
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 8px !important;
    margin-inline-end: 0 !important;
    border-radius: 22px;
}

@keyframes wiggle {
    0%, 100% {
        transform: rotate(0deg);
    }

    15% {
        transform: rotate(-10deg);
    }

    30% {
        transform: rotate(10deg);
    }

    45% {
        transform: rotate(-9deg);
    }

    60% {
        transform: rotate(9deg);
    }

    75% {
        transform: rotate(-7deg);
    }

    90% {
        transform: rotate(7deg);
    }
}

.animate {
    animation: wiggle 2s ease-in-out infinite;
}

#cnvPTZ {
    position: fixed;
    top: 0px;
    left: 0px;
    width: 335px;
    height: 190px;
    display: none;
    z-index: 899;
}

#cnvVolume {
    position: fixed;
    top: 0px;
    left: 0px;
    width: 44px;
    height: 156px;
    display: none;
    z-index: 1001;
    border-radius: 16px;
    box-shadow: 0 16px 36px rgba(0, 0, 0, 0.22);
}

@media (pointer: coarse) {
    #cnvVolume {
        width: 52px;
        height: 176px;
    }
}


/* Fixed-palette chrome button — always dark regardless of Bootstrap theme.
   The fixed palette is routed through Bootstrap's own --bs-btn-* state vars:
   Bootstrap's .btn:hover/:active rules can then win any specificity or
   source-order tie (the theme stylesheet loads after style.css) and still
   paint our colors. Without this, its pressed-state selector
   (:not(.btn-check)+.btn:active) ties .btn.btn-theme-toggle:active and wins
   on order, and a variant-less .btn's active bg is TRANSPARENT — the button
   background vanished on press. The explicit background/color declarations
   below cover boot, before the theme stylesheet (and .btn's var plumbing)
   has loaded. */
.btn.btn-theme-toggle {
    --bs-btn-bg: var(--t-surface-raised);
    --bs-btn-color: var(--t-text-primary);
    --bs-btn-hover-bg: var(--t-chrome-hover);
    --bs-btn-hover-color: var(--t-text-primary);
    --bs-btn-active-bg: var(--t-chrome-hover);
    --bs-btn-active-color: var(--t-text-primary);
    --bs-btn-border-color: transparent;
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-border-color: transparent;
    background-color: var(--t-surface-raised);
    color: var(--t-text-primary);
    border: none;
}

.btn.btn-theme-toggle:hover,
.btn.btn-theme-toggle:active {
    background-color: var(--t-chrome-hover);
    color: var(--t-text-primary);
}


/* Default: shrink to content, wrap when needed */
.iconItem {
    flex: 0 0 auto;
}

#navControls .iconItem {
    padding: 4px 8px;
    margin: 1px;
}

/* Bottom drawer follows the account Size setting: --ui-scale / --ui-scale-icon
   are set on <html> by helpers.sizeIcons() (icons use the gentler icon curve,
   labels the full text scale — same ratio the canvas UI uses). */
#navControls .iconItem i {
    font-size: calc(1.1rem * var(--ui-scale-icon, 1));
    margin-bottom: 0.25rem;
}

#navControls .iconItem span {
    font-size: calc(0.7rem * var(--ui-scale, 1));
}

/* Drawer utility buttons (hide chevron, TM transport) scale with the icons.
   Split rules so the btn-sm baseline (0.875rem) is preserved at scale 1 —
   the ID selector would otherwise out-rank .btn-sm. */
#navControls .btn {
    font-size: calc(1rem * var(--ui-scale-icon, 1));
}

#navControls .btn-sm {
    font-size: calc(0.875rem * var(--ui-scale-icon, 1));
}

/* Side menu follows the account Size setting too — same icon/text split as
   the drawer above. The panel widens with the text so labels don't wrap. */
#navSystem {
    width: calc(260px * var(--ui-scale, 1));
}

#navSystem .iconItem i {
    font-size: calc(1.25rem * var(--ui-scale-icon, 1));
}

#navSystem .iconItem span {
    font-size: calc(0.8rem * var(--ui-scale, 1));
}

#navSystem #navTop h5 {
    font-size: calc(1.25rem * var(--ui-scale, 1));
}

/* Context menu: dropdown items inherit the menu font, so scaling the
   container scales every entry (the ID out-ranks .dropdown-menu's var). */
#context-menu {
    font-size: calc(1rem * var(--ui-scale, 1));
}

/* Editor dialogs follow the account Size setting. Bootstrap's em-based
   metrics (helper text, padding, checks/switches) ride the container font;
   the explicit rem sizes below are re-declared with the scale factor.
   Deliberately NOT `zoom:` — zoom rescales getBoundingClientRect and would
   skew the zone canvas pointer math. */
#editor .modal-content {
    font-size: calc(1rem * var(--ui-scale, 1));
}

#editor .form-control,
#editor .form-select,
#editor .input-group-text,
#editor .btn,
#editor .dropdown-menu {
    font-size: calc(1rem * var(--ui-scale, 1));
}

#editor .btn-sm,
#editor .form-control-sm,
#editor .form-select-sm {
    font-size: calc(0.875rem * var(--ui-scale, 1));
}

#editor .modal-title,
#editor h5 {
    font-size: calc(1.25rem * var(--ui-scale, 1));
}

#editor h4 {
    font-size: calc(1.5rem * var(--ui-scale, 1));
}

#editor h6 {
    font-size: calc(1rem * var(--ui-scale, 1));
}

/* Dialog width scales with the Size setting so enlarged text keeps its line
   length instead of wrapping sooner. Mirrors Bootstrap's modal width tiers
   at the same breakpoints, viewport-capped so big scales on small screens
   can't overflow. Below 576px modals are fluid — nothing to scale. */
@media (min-width: 576px) {
    #editor .modal-dialog {
        max-width: min(calc(500px * var(--ui-scale, 1)), calc(100vw - 16px));
    }

    #editor .modal-sm {
        max-width: min(calc(300px * var(--ui-scale, 1)), calc(100vw - 16px));
    }
}

@media (min-width: 992px) {
    #editor .modal-lg,
    #editor .modal-xl {
        max-width: min(calc(800px * var(--ui-scale, 1)), calc(100vw - 16px));
    }
}

@media (min-width: 1200px) {
    #editor .modal-xl {
        max-width: min(calc(1140px * var(--ui-scale, 1)), calc(100vw - 16px));
    }
}

/* Auto-hide UI: when controls are toggled off they fade out and reappear on
   mouse move or touch, keeping their hidden layout. Fading targets the
   BUTTONS, not the cluster (a parent at opacity:0 would erase children
   regardless of their own opacity): the show/hide chevron keeps a faint
   ghost at all times so the way back stays discoverable, and its corner
   stays click-owned by the button instead of falling through to floorplan
   pins drawn beneath it. */
.ui-autohide #mainControls.hidden {
    /* The base .hidden rule dims the whole cluster to 0.4 — neutralize it
       here: container opacity MULTIPLIES the children, which silently
       dragged the restore tab down to ~22% visibility. In autohide mode
       the children below manage their own fade. The pill surface is also
       stripped so the slide-away leaves no dangling sliver — the restore
       tab (own surface) is the only visible object. */
    opacity: 1;
    background-color: transparent;
    border-color: transparent;
    box-shadow: none;
}

.ui-autohide #mainControls.hidden > * {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

.ui-autohide #mainControls.hidden > #uiButton {
    /* The restore control stays plainly visible — every "subtle ghost"
       attempt (0.35, 0.55) vanished over dark canvas/floorplans. It's a
       small corner tab; discoverability beats subtlety here. */
    opacity: 0.85;
    pointer-events: auto;
    min-width: 44px;
    min-height: 44px;
    background-color: var(--t-chrome-hover);
    border: 1px solid var(--t-border-medium);
    box-shadow: 0 2px 8px var(--t-shadow);
}

.ui-autohide #mainControls.hidden > #uiButton:hover {
    opacity: 1;
}

.ui-autohide.ui-visible #mainControls.hidden > * {
    opacity: 1;
    pointer-events: auto;
}

body.isApp .wrapper {
    padding-top: 0 !important;
}

body.isApp #navSystem,
body.isApp #mainControls,
body.isApp #mainControls2 {
    top: 0 !important;
}

body.isApp #toast.show {
    /* Native apps: the banner replaces the safe-area math (see resize()),
       but the toast still has to clear the scaled top row. */
    top: calc(24px + 44px * var(--ui-scale-icon, 1)) !important;
}

/* Apply this to the icon so it animates smoothly */
.panel-icon-transition {
    transition: transform 0.3s ease-in-out;
}

/* We will toggle this class on and off in the JS */
.panel-icon-rotated {
    transform: rotate(180deg);
}

/* Nib size dropdown — compact icon-only menu (RenderModal.js) */
.nib-menu {
    min-width: auto;
}

/* Zone color swatch — zone selector button and dropdown items (RenderModal.js) */
.zone-swatch {
    display: inline-block;
    width: 0.9em;
    height: 0.9em;
    border-radius: 0.2em;
    border: 1px solid rgba(128, 128, 128, 0.5);
    flex-shrink: 0;
}

/* Animated collapse for the Advanced settings section (RenderModal.js).
   grid-template-rows 0fr -> 1fr animates to auto height without JS measurement. */
.advanced-collapse {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.3s ease-in-out;
}

.advanced-collapse.open {
    grid-template-rows: 1fr;
}

.advanced-collapse-inner {
    overflow: hidden;
    min-height: 0;
    visibility: hidden;
    transition: visibility 0.3s;
}

.advanced-collapse.open .advanced-collapse-inner {
    visibility: visible;
}

/* Flash applied to fields matching the menu filter after navigating
   to a section via a filtered search result (RenderModal.js). */
@keyframes field-highlight-pulse {
    0% { background-color: rgba(var(--bs-primary-rgb), 0.3); }
    35% { background-color: rgba(var(--bs-primary-rgb), 0.1); }
    55% { background-color: rgba(var(--bs-primary-rgb), 0.25); }
    100% { background-color: transparent; }
}

.field-highlight {
    animation: field-highlight-pulse 2.5s ease-out 1;
    border-radius: 0.375rem;
}

/* Tom Select integration */
.modal-content .ts-wrapper.single .ts-control,
.modal-content .ts-wrapper.single.input-active .ts-control {
    background-color: var(--bs-body-bg);
    border-color: var(--bs-border-color);
    color: inherit;
    min-height: calc(1.5em + 0.75rem + 2px);
}

.modal-content .ts-wrapper.focus .ts-control {
    border-color: var(--bs-primary);
    box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
}

.modal-content .ts-control > input {
    color: inherit !important;
}

.modal-content .ts-control > input::placeholder {
    color: var(--bs-secondary-color);
}

.modal-content .ts-dropdown {
    background-color: var(--bs-dropdown-bg, var(--bs-body-bg));
    border-color: var(--bs-border-color);
    color: var(--bs-dropdown-color, var(--bs-body-color));
    z-index: 1080;
}

.modal-content .ts-dropdown .option,
.modal-content .ts-dropdown .create,
.modal-content .ts-dropdown .no-results {
    color: var(--bs-dropdown-link-color, var(--bs-body-color));
}

.modal-content .ts-dropdown .active,
.modal-content .ts-dropdown .option:hover {
    background-color: var(--bs-dropdown-link-hover-bg, var(--bs-tertiary-bg));
    color: var(--bs-dropdown-link-hover-color, var(--bs-body-color));
}

.modal-content .ts-dropdown .highlight {
    background-color: rgba(var(--bs-warning-rgb), 0.35);
    color: var(--bs-body-color);
}

/* noUiSlider integration */
.modal-content .noUi-target {
    background-color: var(--bs-tertiary-bg);
    border-color: var(--bs-border-color);
    box-shadow: none;
    margin: 0.75rem 0;
}

.modal-content .noUi-connect {
    background-color: var(--bs-primary);
}

.modal-content .noUi-handle {
    background-color: var(--bs-body-bg);
    border-color: var(--bs-border-color);
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.2);
}

.modal-content .noUi-handle:focus {
    outline: none;
    box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
}
