html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    /* Prevent pull-to-refresh on mobile browsers */
    overscroll-behavior-y: contain;
    overscroll-behavior: contain;
}

a, .btn-link {
    color: var(--mud-palette-primary);
}

/* Bootstrap text-color utilities are fixed light-theme grays/blacks that break on dark
   backgrounds. Map the common ones to palette tokens so they follow the theme everywhere. */
.text-muted {
    color: var(--mud-palette-text-secondary) !important;
}

/* Bootstrap's generic border color (used by .border / .border-top / etc. utilities and many
   components) is a fixed light gray — theme it so borders adapt everywhere without per-app overrides. */
:root {
    --bs-border-color: var(--mud-palette-lines-default);
    --bs-border-color-translucent: var(--mud-palette-lines-default);
}

/* Bootstrap form controls default to white background + dark text (no dark mode), so their
   text and box break on the dark theme. Map them to palette tokens app-wide. */
.form-control,
.form-select {
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border-color: var(--mud-palette-lines-inputs);
}
.form-control::placeholder {
    /* text-secondary (not the fainter text-disabled) so prompt text like the File Explorer search
       stays readable in dark mode. */
    color: var(--mud-palette-text-secondary);
    opacity: 0.9;
}
.form-control:focus,
.form-select:focus {
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 0.2rem rgba(var(--mud-palette-primary-rgb), 0.25);
}
.form-floating > label,
.form-label,
.col-form-label {
    color: var(--mud-palette-text-secondary);
}
.input-group-text {
    background-color: var(--mud-palette-background-grey);
    color: var(--mud-palette-text-secondary);
    border-color: var(--mud-palette-lines-inputs);
}

/* Bootstrap buttons use --bs-btn-* variables; map the light-theme variants (btn-light,
   btn-outline-secondary — used for toolbars/button-groups/nav buttons across apps) to palette
   tokens so they follow the theme. btn-primary is themed separately above. */
.btn-light {
    --bs-btn-color: var(--mud-palette-text-primary);
    --bs-btn-bg: var(--mud-palette-background-grey);
    --bs-btn-border-color: var(--mud-palette-lines-default);
    --bs-btn-hover-color: var(--mud-palette-text-primary);
    --bs-btn-hover-bg: rgba(var(--mud-palette-primary-rgb), 0.12);
    --bs-btn-hover-border-color: var(--mud-palette-lines-default);
    --bs-btn-active-color: var(--mud-palette-primary);
    --bs-btn-active-bg: rgba(var(--mud-palette-primary-rgb), 0.18);
    --bs-btn-active-border-color: var(--mud-palette-primary);
}
.btn-outline-secondary {
    --bs-btn-color: var(--mud-palette-text-secondary);
    --bs-btn-border-color: var(--mud-palette-lines-default);
    --bs-btn-hover-color: var(--mud-palette-text-primary);
    --bs-btn-hover-bg: rgba(var(--mud-palette-primary-rgb), 0.12);
    --bs-btn-hover-border-color: var(--mud-palette-primary);
    --bs-btn-active-color: var(--mud-palette-primary);
    --bs-btn-active-bg: rgba(var(--mud-palette-primary-rgb), 0.18);
    --bs-btn-active-border-color: var(--mud-palette-primary);
}

/* Bootstrap accordion (BOM Viewer trees, File Explorer, etc.) uses --bs-accordion-* variables.
   Map them to palette tokens so the collapse panels — and the MudTreeView rendered inside them —
   are visible in dark mode (previously light tree text on a white Bootstrap panel = invisible). */
.accordion {
    --bs-accordion-color: var(--mud-palette-text-primary);
    /* Soft, elevated Surface throughout (WingMate-style) — distinction comes from the header
       border + the primary left-accent/text on the expanded panel, not from a hard dark body. */
    --bs-accordion-bg: var(--mud-palette-surface);
    --bs-accordion-border-color: var(--mud-palette-lines-default);
    --bs-accordion-btn-color: var(--mud-palette-text-primary);
    --bs-accordion-btn-bg: var(--mud-palette-surface);
    --bs-accordion-active-color: var(--mud-palette-primary);
    /* Expanded header stays on the opaque, elevated Surface (like collapsed) so it never falls
       back to the dark body tone — it's distinguished by a primary left-accent + primary text. */
    --bs-accordion-active-bg: var(--mud-palette-surface);
    --bs-accordion-btn-focus-border-color: var(--mud-palette-primary);
    --bs-accordion-btn-focus-box-shadow: 0 0 0 0.2rem rgba(var(--mud-palette-primary-rgb), 0.25);
}
/* Crisp separator under each panel header so it reads as a distinct bar. */
.accordion-button {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    font-weight: 600;
}
/* Expanded panel header: primary left-accent bar (plus the primary text/chevron above) makes the
   open panel unmistakable and clearly separate from its body. */
.accordion-button:not(.collapsed) {
    box-shadow: inset 3px 0 0 var(--mud-palette-primary),
                inset 0 -1px 0 var(--mud-palette-lines-default);
}
/* The collapse chevron is a dark SVG background-image — lighten it in dark mode so it stays visible. */
html[data-theme="dark"] .accordion-button::after {
    filter: invert(1) grayscale(100%) brightness(1.8);
}

/* MudChart renders axis/label text as raw SVG whose fill isn't theme-aware — make chart text
   readable in dark (keeps series/segment colors untouched — those are intentional data-viz). */
.mud-charts-xaxis text,
.mud-charts-yaxis text,
.mud-chart-line text,
.mud-chart-bar text,
.mud-chart-donut text,
.mud-chart text.mud-charts-grid-line-text {
    fill: var(--mud-palette-text-secondary);
}
.mud-chart-legend .mud-chart-legend-item {
    color: var(--mud-palette-text-primary);
}

/* Bootstrap breadcrumbs (File Explorer path bar, etc.) — theme divider + segment colors. */
.breadcrumb {
    --bs-breadcrumb-divider-color: var(--mud-palette-text-secondary);
    --bs-breadcrumb-item-active-color: var(--mud-palette-text-primary);
}
.breadcrumb-item {
    color: var(--mud-palette-text-primary);
}
.breadcrumb-item.cursor-pointer,
.breadcrumb-item a {
    color: var(--mud-palette-primary);
    text-decoration: none;
}
.breadcrumb-item.cursor-pointer:hover,
.breadcrumb-item a:hover {
    text-decoration: underline;
}

/* Bootstrap dropdown menus default to a white panel with dark text — theme them app-wide. */
.dropdown-menu {
    --bs-dropdown-bg: var(--mud-palette-surface);
    --bs-dropdown-color: var(--mud-palette-text-primary);
    --bs-dropdown-border-color: var(--mud-palette-lines-default);
    --bs-dropdown-link-color: var(--mud-palette-text-primary);
    --bs-dropdown-link-hover-color: var(--mud-palette-text-primary);
    --bs-dropdown-link-hover-bg: rgba(var(--mud-palette-primary-rgb), 0.10);
    --bs-dropdown-link-active-color: var(--mud-palette-primary-text);
    --bs-dropdown-link-active-bg: var(--mud-palette-primary);
    --bs-dropdown-header-color: var(--mud-palette-text-secondary);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);
}

/* Keep button labels on one line so toolbars don't wrap text inside buttons. */
.btn-group > .btn,
.btn-group > .btn-check + .btn {
    white-space: nowrap;
}
/* BOM Viewer toolbar: let button groups flow onto new rows instead of squashing (desktop + mobile). */
.view-mode-toggle {
    flex-wrap: wrap;
    row-gap: 8px;
}

/* Solid/outline semantic Bootstrap buttons → palette tokens (via --bs-btn-*). btn-light &
   btn-outline-secondary are handled above; btn-primary is themed near the top. */
.btn-secondary {
    --bs-btn-bg: var(--mud-palette-secondary);
    --bs-btn-border-color: var(--mud-palette-secondary);
    --bs-btn-color: var(--mud-palette-secondary-text);
    --bs-btn-hover-bg: var(--mud-palette-secondary);
    --bs-btn-hover-border-color: var(--mud-palette-secondary);
    --bs-btn-hover-color: var(--mud-palette-secondary-text);
    --bs-btn-active-bg: var(--mud-palette-secondary);
    --bs-btn-active-border-color: var(--mud-palette-secondary);
}
.btn-danger {
    --bs-btn-bg: var(--mud-palette-error);
    --bs-btn-border-color: var(--mud-palette-error);
    --bs-btn-color: var(--mud-palette-error-text);
    --bs-btn-hover-bg: var(--mud-palette-error);
    --bs-btn-hover-border-color: var(--mud-palette-error);
    --bs-btn-hover-color: var(--mud-palette-error-text);
    --bs-btn-active-bg: var(--mud-palette-error);
}
.btn-success {
    --bs-btn-bg: var(--mud-palette-success);
    --bs-btn-border-color: var(--mud-palette-success);
    --bs-btn-color: var(--mud-palette-success-text);
    --bs-btn-hover-bg: var(--mud-palette-success);
    --bs-btn-hover-border-color: var(--mud-palette-success);
    --bs-btn-hover-color: var(--mud-palette-success-text);
    --bs-btn-active-bg: var(--mud-palette-success);
}
.btn-warning {
    --bs-btn-bg: var(--mud-palette-warning);
    --bs-btn-border-color: var(--mud-palette-warning);
    --bs-btn-color: var(--mud-palette-warning-text);
    --bs-btn-hover-bg: var(--mud-palette-warning);
    --bs-btn-hover-border-color: var(--mud-palette-warning);
    --bs-btn-hover-color: var(--mud-palette-warning-text);
    --bs-btn-active-bg: var(--mud-palette-warning);
}
.btn-info {
    --bs-btn-bg: var(--mud-palette-info);
    --bs-btn-border-color: var(--mud-palette-info);
    --bs-btn-color: var(--mud-palette-info-text);
    --bs-btn-hover-bg: var(--mud-palette-info);
    --bs-btn-hover-border-color: var(--mud-palette-info);
    --bs-btn-hover-color: var(--mud-palette-info-text);
    --bs-btn-active-bg: var(--mud-palette-info);
}
.btn-outline-primary {
    --bs-btn-color: var(--mud-palette-primary);
    --bs-btn-border-color: var(--mud-palette-primary);
    --bs-btn-hover-bg: var(--mud-palette-primary);
    --bs-btn-hover-color: var(--mud-palette-primary-text);
    --bs-btn-hover-border-color: var(--mud-palette-primary);
    --bs-btn-active-bg: var(--mud-palette-primary);
    --bs-btn-active-border-color: var(--mud-palette-primary);
}
.btn-outline-danger {
    --bs-btn-color: var(--mud-palette-error);
    --bs-btn-border-color: var(--mud-palette-error);
    --bs-btn-hover-bg: var(--mud-palette-error);
    --bs-btn-hover-color: var(--mud-palette-error-text);
    --bs-btn-hover-border-color: var(--mud-palette-error);
    --bs-btn-active-bg: var(--mud-palette-error);
}

/* Bootstrap alerts (NotAuthorized banners, etc.) → soft palette-tinted variants that work in dark. */
.alert-danger {
    --bs-alert-color: var(--mud-palette-error);
    --bs-alert-bg: rgba(var(--mud-palette-error-rgb), 0.12);
    --bs-alert-border-color: rgba(var(--mud-palette-error-rgb), 0.35);
}
.alert-warning {
    --bs-alert-color: var(--mud-palette-warning);
    --bs-alert-bg: rgba(var(--mud-palette-warning-rgb), 0.12);
    --bs-alert-border-color: rgba(var(--mud-palette-warning-rgb), 0.35);
}
.alert-success {
    --bs-alert-color: var(--mud-palette-success);
    --bs-alert-bg: rgba(var(--mud-palette-success-rgb), 0.12);
    --bs-alert-border-color: rgba(var(--mud-palette-success-rgb), 0.35);
}
.alert-info,
.alert-primary {
    --bs-alert-color: var(--mud-palette-info);
    --bs-alert-bg: rgba(var(--mud-palette-info-rgb), 0.12);
    --bs-alert-border-color: rgba(var(--mud-palette-info-rgb), 0.35);
}
.alert-secondary,
.alert-light {
    --bs-alert-color: var(--mud-palette-text-primary);
    --bs-alert-bg: var(--mud-palette-background-grey);
    --bs-alert-border-color: var(--mud-palette-lines-default);
}

/* Bootstrap cards (top-bar widgets: Quality Policy / Stacklight Legend, and other .card users)
   default to white — map --bs-card-* to palette tokens so they theme in dark. */
.card {
    --bs-card-bg: var(--mud-palette-surface);
    --bs-card-color: var(--mud-palette-text-primary);
    --bs-card-border-color: var(--mud-palette-lines-default);
    --bs-card-cap-bg: var(--mud-palette-background-grey);
    --bs-card-cap-color: var(--mud-palette-text-primary);
}

/* Top-bar widgets (Quality Policy, Stacklight Legend, Weather) — a consistent, elevated Surface
   card that reads cleanly on the navy app bar in both themes. */
.weather-widget.card {
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.28);
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.weather-widget.card:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
    transform: translateY(-1px);
}

/* Bootstrap "subtle" background utilities (bg-danger-subtle, etc.) stay light-pastel in dark —
   remap them to soft palette-tinted fills. (!important to beat Bootstrap's own !important.) */
.bg-danger-subtle  { background-color: rgba(var(--mud-palette-error-rgb), 0.12) !important; }
.bg-warning-subtle { background-color: rgba(var(--mud-palette-warning-rgb), 0.12) !important; }
.bg-success-subtle { background-color: rgba(var(--mud-palette-success-rgb), 0.12) !important; }
.bg-info-subtle,
.bg-primary-subtle { background-color: rgba(var(--mud-palette-info-rgb), 0.12) !important; }
.bg-secondary-subtle,
.bg-light-subtle   { background-color: var(--mud-palette-background-grey) !important; }

/* Bootstrap progress bars → palette tokens (idle-time charts, etc.). */
.progress {
    --bs-progress-bg: var(--mud-palette-background-grey);
    --bs-progress-bar-bg: var(--mud-palette-primary);
    --bs-progress-bar-color: var(--mud-palette-primary-text);
}

/* Bootstrap list-groups → palette tokens (settings lists, conversation lists, etc.). */
.list-group {
    --bs-list-group-bg: var(--mud-palette-surface);
    --bs-list-group-color: var(--mud-palette-text-primary);
    --bs-list-group-border-color: var(--mud-palette-lines-default);
    --bs-list-group-action-hover-bg: rgba(var(--mud-palette-primary-rgb), 0.08);
    --bs-list-group-action-hover-color: var(--mud-palette-text-primary);
    --bs-list-group-active-bg: var(--mud-palette-primary);
    --bs-list-group-active-border-color: var(--mud-palette-primary);
    --bs-list-group-active-color: var(--mud-palette-primary-text);
}

.btn-primary {
    color: var(--mud-palette-primary-text);
    background-color: var(--mud-palette-primary);
    border-color: var(--mud-palette-primary);
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem var(--mud-palette-surface), 0 0 0 0.25rem var(--mud-palette-primary);
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--mud-palette-success);
}

.invalid {
    outline: 1px solid var(--mud-palette-error);
}

.validation-message {
    color: var(--mud-palette-error);
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: var(--mud-palette-lines-inputs);
}

.sidebar {
    transition: flex-basis 0.1s ease, height 0.1s ease;
    flex-basis: 30px;
}
    .sidebar.expanded {
        flex-basis: 250px;
    }

.collapsed-sidebar {
    display: block;
}
.full-sidebar {
    display: none;
}
.sidebar.expanded > .collapsed-sidebar {
    display: none;
}
.sidebar.expanded > .full-sidebar {
    display: block;
}

.topbar {
    height: 30px;
    transition: height 0.1s ease;
    max-width: 100vw;
    overflow-x: clip;
    overflow-y: visible;
}
.topbar-collapsed-style {
    font-size: 1.0rem;
}
.topbar-expand-btn:hover {
    cursor: pointer;
}

.topbar .tronair-logo {
    height: 10px;
    transform: translate(0px, -4px);
}

.topbar.expanded .tronair-logo {
    height: 15px;
    transform: translate(0px, 0px);
}

.topbar .stratus-logo {
    height: 20px;
}

/* Brand app bar — navy→azure gradient in both themes (per approved theme proposal). */
#top-bar.topbar {
    background: linear-gradient(100deg, #16334A 0%, #0076AD 130%);
    color: var(--mud-palette-appbar-text);
}
html[data-theme="dark"] #top-bar.topbar {
    background: linear-gradient(100deg, #0C141C 0%, #155A82 150%);
}
/* Logos are dark artwork — render them white so they read on the navy bar in both themes. */
#top-bar .tronair-logo,
#top-bar .stratus-logo {
    filter: brightness(0) invert(1);
}
/* Top-bar action icons (hamburger / expand caret) read as light on the navy bar in both themes. */
#top-bar .topbar-icon,
#top-bar .topbar-icon .bi,
#top-bar .topbar-expand-btn,
#top-bar .topbar-expand-btn i {
    color: var(--mud-palette-appbar-text);
}


@media (width >= 768px) {
    .topbar.expanded .stratus-logo {
        height: 50px;
    }

}

@media (width < 768px) {

    .topbar.expanded .stratus-logo {
        height: 30px;
    }
}

/* ── Desktop: single-row scrollable tab strip ── */
.tab-strip-wrapper {
    display: flex;
    flex-direction: row;
    align-items: center;
    background-color: var(--mud-palette-background-grey);
}

.tab-strip-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    align-self: stretch;
    width: 26px;
    flex-shrink: 0;
    cursor: pointer;
    background-color: var(--mud-palette-primary);
    border: none;
    border-radius: 3px;
    margin: 2px 1px;
    padding: 0;
    color: var(--mud-palette-primary-text);
    font-size: 0.8rem;
    transition: background-color 0.15s, border-color 0.15s;
}
    .tab-strip-btn:hover {
        background-color: var(--mud-palette-primary-darken);
    }
    .tab-strip-btn:disabled {
        opacity: 0.4;
        cursor: default;
        background-color: var(--mud-palette-primary);
    }

/* Split view (env#329): the toggle and its options caret, joined as one control. */
.tab-split-controls {
    display: flex;
    flex-shrink: 0;
    align-self: stretch;
}
.tab-split-controls .mud-menu,
.tab-split-controls .mud-menu-activator {
    display: flex;
    align-self: stretch;
}
.tab-split-controls .tab-split-toggle {
    margin-right: 0;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}
.tab-split-controls .tab-split-caret {
    width: 15px;
    margin-left: 1px;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    font-size: 0.55rem;
}
.tab-split-controls .tab-split-toggle[aria-pressed="true"] {
    background-color: var(--mud-palette-primary-darken);
    box-shadow: inset 0 0 0 1px var(--mud-palette-primary-text);
}
.split-menu-item {
    display: flex;
    justify-content: space-between;
    gap: 24px;
    width: 100%;
}
.split-menu-shortcut {
    opacity: 0.6;
    font-size: 0.8em;
}
/* The tab menu's anchor: an empty activator, opened at the pointer (MainTabs). It takes no room in the strip. */
.tab-menu-anchor {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}
/* Where a dragged tab would go (MainTabs.razor.js): the half or pane under the pointer. */
.split-drop-overlay {
    position: fixed;
    z-index: 1500;
    pointer-events: none;
    display: none;
    align-items: center;
    justify-content: center;
    border: 2px dashed var(--mud-palette-primary);
    border-radius: 6px;
    background-color: rgba(var(--mud-palette-primary-rgb), 0.12);
    transition: left 80ms ease-out, top 80ms ease-out, width 80ms ease-out, height 80ms ease-out;
}
.split-drop-overlay > span {
    padding: 4px 12px;
    border-radius: 12px;
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-size: 0.85rem;
    font-weight: 600;
}

/* Overflow dropdown */
.tab-overflow-wrapper {
    position: relative;
    flex-shrink: 0;
    display: flex;
    align-self: stretch;
}
.tab-overflow-popover {
    min-width: 220px;
    max-width: 320px;
    max-height: 400px;
    overflow-y: auto;
    padding: 4px 0;
}
.tab-overflow-item {
    display: flex;
    flex-direction: row;
    align-items: center;
    padding: 4px 8px 4px 12px;
    font-size: 0.85rem;
    color: var(--mud-palette-text-primary);
}
    .tab-overflow-item:hover {
        background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
    }
    .tab-overflow-item.active-tab {
        font-weight: 600;
        background-color: rgba(var(--mud-palette-primary-rgb), 0.15);
    }
.tab-overflow-item-left {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    flex-grow: 1;
    min-width: 0;
    cursor: pointer;
    padding: 2px 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tab-overflow-close-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-left: auto;
    border: none;
    border-radius: 3px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    font-size: 0.9rem;
    padding: 0;
}
    .tab-overflow-close-btn:hover {
        background-color: rgba(var(--mud-palette-error-rgb), 0.15);
        color: var(--mud-palette-error);
    }

.main-body-tabs {
    background-color: var(--mud-palette-background-grey);
    flex-wrap: nowrap !important;
    overflow: hidden;
    scroll-behavior: smooth;
    flex-grow: 1;
    min-width: 0;
}

.main-body-tabs > li {
    flex-shrink: 1;
    min-width: 60px;
    max-width: 180px;
    overflow: hidden;
}

/* MudTooltip wraps the button in an extra element — make it fill the li */
.main-body-tabs > li > * {
    width: 100%;
}

/* A tab's box (ui#252: a div holding the tab's own button and its icon buttons, where it used to be one button). Positioned and isolated
   so the tab button's click area (::after, below) covers it, and the icons' z-index stays inside the tab. */
.main-body-tabs .nav-link {
    position: relative;
    isolation: isolate;
    font-size: 0.85rem;
    /* Subtract the 1px horizontal margins (below) so the border-box fits inside the
       overflow:hidden li — otherwise the right border/underline gets clipped off. */
    width: calc(100% - 2px);
    padding: 3px 6px;
    white-space: nowrap;
    overflow: hidden;
    min-width: 0;
    /* Readable text + a defining border so unselected tabs stand out from the strip in both themes
       (surface fill was too close to the light-mode strip tone). */
    color: var(--mud-palette-text-primary);
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 5px 5px 0 0;
    margin: 3px 1px 0;
}
.main-body-tabs .nav-link.active {
    color: var(--mud-palette-primary);
    background-color: var(--mud-palette-surface);
    font-weight: 600;
    border-color: rgba(var(--mud-palette-primary-rgb), 0.5);
    box-shadow: inset 0 -2px 0 0 var(--mud-palette-primary);
}
/* Split view (env#329): the other pane's tab, on screen but not focused. The focused pane's tab is .active, as in single view. */
.main-body-tabs .nav-link.split-partner {
    border-color: rgba(var(--mud-palette-primary-rgb), 0.35);
    box-shadow: inset 0 -2px 0 0 rgba(var(--mud-palette-primary-rgb), 0.4);
}
.main-body-tabs .nav-link:has(> .shell-tab-select:disabled) {
    color: var(--mud-palette-action-disabled);
    background-color: var(--mud-palette-action-disabled-background);
}

    .main-body-tabs .nav-link:not(.active):hover {
        color: var(--mud-palette-text-primary);
        background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
    }

/* The tab's own button: its icon and name, and the target of the tab's tooltip (ui#224), so the reload icon and the × each show only
   theirs. It takes the room the name used to take, so the × stays at the right edge and the name still clips first. Its 21px floor
   keeps an icon whole, so on a narrow active tab the reload icon shrinks first (flex-shrink 99, below), and nothing meets the ×.
   Reset to look as the tab's content did (ui#252): no button chrome, and the tab's colour and weight. Static, not MudBlazor's
   `button { position: relative }`, so its ::after (below) is placed by the tab's box, not by this button's own smaller one. */
.main-body-tabs .shell-tab-select {
    position: static;
    display: flex;
    flex-direction: row;
    align-items: center;
    flex: 1 1 0%;
    min-width: 21px;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
}
    /* Its click area is the whole tab, padding included, as when the tab was one button; the icons sit above it (z-index, below). */
    .main-body-tabs .shell-tab-select::after {
        content: "";
        position: absolute;
        inset: 0;
    }
    /* Keyboard focus rings the whole tab, inside its edge: the li clips anything outside it. */
    .main-body-tabs .shell-tab-select:focus-visible {
        outline: none;
    }
    .main-body-tabs .shell-tab-select:focus-visible::after {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: -2px;
        border-radius: 4px 4px 0 0;
    }

/* The reload icon and the ×: buttons beside the tab's own (ui#252), so each takes keyboard focus. Reset to look as the icons did, and
   above the tab button's click area, so a click on either never selects the tab. Block, as the icon spans were once in the flex row:
   an inline-block button is only its glyph's height (a smaller × to hit) and centres a clipped glyph, where the span clipped its end. */
.main-body-tabs .reload-tab-icon-btn,
.main-body-tabs .close-tab-icon-btn {
    display: block;
    position: relative;
    z-index: 1;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
}
    /* Keyboard focus rings the icon itself (its glyph's square): the ×'s own box reaches past the top of the tab once scaled. */
    .main-body-tabs .reload-tab-icon-btn:focus-visible,
    .main-body-tabs .close-tab-icon-btn:focus-visible {
        outline: none;
    }
    .main-body-tabs .reload-tab-icon-btn:focus-visible::before,
    .main-body-tabs .close-tab-icon-btn:focus-visible::before {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: -2px;
        border-radius: 3px;
    }

/* Tab text: clip without ellipsis so maximum characters are visible */
.tab-label-text {
    overflow: hidden;
    text-overflow: clip;
    white-space: nowrap;
    min-width: 0;
    flex: 1 1 0%;
}

/* Hide reload icon when tab is narrow — icon's flex-shrink keeps it from pushing text */
.main-body-tabs > li .reload-tab-icon-btn {
    flex-shrink: 99;
    overflow: hidden;
    min-width: 0;
    max-width: 14px;
}

/* ── Mobile: active-app header bar ── */
.mobile-tab-bar {
    display: flex;
    flex-direction: row;
    align-items: center;
    background-color: var(--mud-palette-background-grey);
    padding: 4px 8px;
    gap: 6px;
    min-height: 34px;
}

.mobile-tab-bar-label {
    flex-grow: 1;
    font-size: 0.85rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.mobile-tab-count-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 8px;
    border: none;
    border-radius: 4px;
    background-color: var(--mud-palette-primary);
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    color: var(--mud-palette-primary-text);
}

.mobile-tab-action-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: none;
    border-radius: 4px;
    background: transparent;
    cursor: pointer;
    color: var(--mud-palette-text-primary);
    padding: 0;
    font-size: 1rem;
}

/* ── Mobile tab dialog list items ── */
.mobile-tab-item {
    display: flex;
    flex-direction: row;
    align-items: center;
    padding: 10px 12px;
    gap: 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    cursor: pointer;
}
    .mobile-tab-item:hover {
        background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
    }
    .mobile-tab-item.active {
        background-color: rgba(var(--mud-palette-primary-rgb), 0.15);
        border-left: 3px solid var(--mud-palette-primary);
    }
.mobile-tab-item-label {
    flex-grow: 1;
    font-size: 0.95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.sidebar-tabs {
    background-color: var(--mud-palette-background-grey);
}

    .sidebar-tabs > div > button.nav-link {
        padding: 4px 6px;
        margin: 1px 4px 0px 4px;
        font-size: 0.85rem;
        font-stretch: narrower;
    }

.sidebar-tab-content {
    /* Recessed base so the Surface app cards rise above it (matches the main app picker). */
    background-color: var(--mud-palette-background);
}

/* Sidebar tab buttons — kept identical to the main-body tab buttons for consistency. */
.sidebar-tabs button.nav-link {
    color: var(--mud-palette-text-secondary);
    background-color: var(--mud-palette-surface);
}

    .sidebar-tabs button.nav-link.active {
        color: var(--mud-palette-primary);
        background-color: var(--mud-palette-surface);
        font-weight: 600;
        box-shadow: inset 0 -2px 0 var(--mud-palette-primary);
    }

    .sidebar-tabs button.nav-link:disabled {
        color: var(--mud-palette-action-disabled);
        background-color: var(--mud-palette-action-disabled-background);
    }

    .sidebar-tabs button.nav-link:not(.active):hover {
        color: var(--mud-palette-text-primary);
        background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
    }

.sidebar-header {
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

/* Sidebar container + collapsed rail — theme-aware (replaces Bootstrap bg-white / bg-secondary-subtle).
   Uses the recessed background so Surface app cards inside it rise, matching the main body. */
#side-bar {
    background-color: var(--mud-palette-background);
    border-right: 1px solid var(--mud-palette-lines-default);
}
/* Minimized rail is the primary/default state — give it the brand gradient (vertical version of
   the top bar) so it's clearly distinct from the body and frames the app consistently. */
.collapsed-sidebar {
    background: linear-gradient(180deg, #16334A 0%, #0076AD 130%);
    height: 100%;
}
html[data-theme="dark"] .collapsed-sidebar {
    background: linear-gradient(180deg, #0C141C 0%, #155A82 150%);
}
.collapsed-sidebar .bi {
    color: var(--mud-palette-appbar-text);
}
.collapsed-sidebar > .d-flex:hover .bi {
    color: #ffffff;
    cursor: pointer;
}

.app-card {
    cursor: pointer;
    transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}
    .app-card:hover {
        transform: translateY(-4px) scale(1.05);
        z-index: 1;
    }
    /* The MudCard inside gets a brand-colored glow + ring on hover (color + smoother motion). */
    .app-card .mud-paper {
        transition: box-shadow 0.18s ease, outline-color 0.18s ease;
        outline: 2px solid transparent;
        outline-offset: -2px;
    }
    .app-card:hover .mud-paper {
        box-shadow: 0 8px 24px rgba(var(--mud-palette-primary-rgb), 0.35) !important;
        outline-color: var(--mud-palette-primary);
    }

/* Apps tab on phone widths (env#330): a grid whose tiles grow (90-120 px) to fill each row, with the last row on the same
   columns. 768 px and up keep the flex row of 90 px tiles. The !important rules beat Bootstrap's d-flex and m-2 and AppCard's
   inline 90 px size; they apply only inside .apps-tile-grid, so the side bar's small tiles don't change. */
@media (max-width: 767.98px) {
    .apps-tile-grid {
        display: grid !important;
        grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
        gap: 8px;
        padding: 4px;
    }
        .apps-tile-grid .app-card {
            margin: 0 !important;
        }
        .apps-tile-grid .app-card .mud-paper {
            width: 100% !important;
            max-width: 120px;
            height: auto !important;
            aspect-ratio: 1 / 1;
            margin-inline: auto;
        }
}

.unselectable {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.reload-tab-icon-btn {
    transform: translate(-2px,-2px) scale(0.9);
}
    .reload-tab-icon-btn:hover {
        transform: translate(-2px,-2px) scale(1.1);
    }

.close-tab-icon-btn {
    transform: translate(3px,-2px) scale(1.3);
}
    .close-tab-icon-btn:hover {
        transform: translate(3px,-2px) scale(1.6);
    }

.messenger-message-link-style {
    color: white;
    font-weight: 500;
}

/*    .messenger-message-link-style:hover {
        font-weight: 600;
    }*/

body.loading-cursor {
    cursor: wait !important;
}

/* Bootstrap offcanvas drawers (top drawer + notification drawer) are Bootstrap components
   whose default background (--bs-offcanvas-bg) is white and never follows the MudBlazor theme.
   Drive them off the palette so they switch with light/dark. */
.offcanvas {
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border-color: var(--mud-palette-lines-default);
}
.offcanvas .conversation-recipients,
.offcanvas .last-message-sender,
.offcanvas .last-message {
    color: var(--mud-palette-text-secondary);
}
/* Top drawer shares the top bar's brand logos, but its panel is themed Surface (not the navy
   bar), so its dark logo artwork only needs inverting to white in dark mode. */
html[data-theme="dark"] #top-offcanvas .tronair-logo,
html[data-theme="dark"] #top-offcanvas .stratus-logo {
    filter: brightness(0) invert(1);
}
/* Bootstrap's close button is a dark X SVG — make it light on the dark drawer surface. */
html[data-theme="dark"] .offcanvas .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

/* Login page brand logos are dark artwork on the page background — invert to white in dark mode. */
html[data-theme="dark"] .login-brand-logo {
    filter: brightness(0) invert(1);
}

/* White document/drawing thumbnails (PDF previews) glare on the dark theme. Soften the harsh
   white and frame them with a subtle outline so they read as paper previews, not white blocks.
   Shared class — used by BOM Viewer and File Explorer thumbnails. */
html[data-theme="dark"] .stratus-doc-thumb {
    filter: brightness(0.85) contrast(1.02);
    border-radius: 4px;
    box-shadow: 0 0 0 1px var(--mud-palette-lines-default);
}

/* Dark-mode dialogs: a dark scrim over an already-dark page gives little separation, so the
   dialog surface barely lifts off the background. Add a visible border + stronger shadow, and
   deepen the scrim, so dialogs read as clearly on top. */
html[data-theme="dark"] .mud-dialog {
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: 0 8px 40px 6px rgba(0, 0, 0, 0.75);
}
html[data-theme="dark"] .mud-overlay-dialog .mud-overlay-scrim,
html[data-theme="dark"] .mud-overlay.mud-overlay-dialog {
    background-color: rgba(0, 0, 0, 0.6);
}

/* Force MudDrawer to be fixed and overlay content */
.mud-drawer-temporary,
.mud-drawer.mud-drawer-temporary {
    position: fixed !important;
    z-index: 1300 !important;
    top: 0 !important;
    bottom: 0 !important;
}

/* Force overlay to be fixed */
.mud-overlay-drawer,
.mud-overlay.mud-overlay-drawer {
    position: fixed !important;
    z-index: 1299 !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
}

/* Fix Honeywell barcode reader plugin creating whitespace */
#bcrPlugin,
embed[type="application/x-npBarcodeReaderPlugin"] {
    display: none !important;
    position: absolute !important;
    width: 0 !important;
    height: 0 !important;
    visibility: hidden !important;
}

/* Utility: single-line text truncation with ellipsis */
.text-truncate-ellipsis {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* Bootstrap 5's .tooltip rule does NOT include `pointer-events: none` (it was in v4
   but got dropped in v5). Without it, the tooltip element can capture the cursor when
   it pops up above a small target — that fires mouseleave on the trigger, hides the
   tooltip, the cursor is now back on the trigger, mouseenter fires, repeat. Result:
   rapid on/off flicker near element borders. Re-adding pointer-events: none makes the
   tooltip mouse-transparent so the trigger keeps hover through the tooltip's bounds. */
.tooltip {
    pointer-events: none;
    --bs-tooltip-opacity: 1;
}

/* Softer, elevated tooltips in BOTH themes: rounded corners + a drop shadow so they float.
   The base (= light mode) shadow is LAYERED — a tight contact shadow plus a wide ambient
   one — because a single soft shadow at low alpha all but vanishes on a white page, which
   left the bubble looking flat and blending into dark content it popped over (bars,
   timeline strips). The faint light rim (last layer) separates the navy bubble from dark
   elements beneath it, the same job the border does in dark mode. Dark mode overrides below. */
.tooltip .tooltip-inner {
    border-radius: 8px;
    padding: 6px 11px;
    font-size: 0.78rem;
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.22),
        0 3px 8px rgba(0, 0, 0, 0.38),
        0 10px 28px rgba(0, 0, 0, 0.30);
}
/* Light: a soft dark-slate bubble (Stratus navy) rather than Bootstrap's harsh pure black. */
html[data-theme="light"] .tooltip {
    --bs-tooltip-bg: #2C3E50;
    --bs-tooltip-color: #FFFFFF;
}
/* Dark: a lighter slate ground + light text + border so it pops on the dark UI (was near-black). */
html[data-theme="dark"] .tooltip {
    --bs-tooltip-bg: #37475A;
    --bs-tooltip-color: #E7EEF4;
}
html[data-theme="dark"] .tooltip .tooltip-inner {
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.55);
}

/* MudBlazor tooltips (MudTooltip) — match the Bootstrap tooltip treatment above so all tooltips
   look consistent: soft navy bubble in light, lighter slate in dark, rounded + elevated.
   Shadow layers mirror .tooltip-inner exactly (contact + ambient + light rim). */
.mud-tooltip {
    background-color: #2C3E50;
    color: #FFFFFF;
    border-radius: 8px;
    padding: 6px 11px;
    font-size: 0.78rem;
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.22),
        0 3px 8px rgba(0, 0, 0, 0.38),
        0 10px 28px rgba(0, 0, 0, 0.30);
}
html[data-theme="dark"] .mud-tooltip {
    background-color: #37475A;
    color: #E7EEF4;
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.55);
}

/* Code block wrapper + copy button. UNSCOPED on purpose: shared by MarkdownRenderer (fenced code in an
   answer) and CodeInterpreterSteps (the Python sandbox Code block), both of which decorate their <pre>
   elements with the same addCodeCopyButtons() helper. */
.code-block-wrapper {
    position: relative;
    margin-bottom: 1rem;
}

.code-copy-btn {
    position: sticky;
    top: 4px;
    float: right;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    margin-top: 4px;
    margin-bottom: -36px;
    margin-right: 8px;
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.6);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    padding: 0;
    line-height: 1;
}

.code-copy-btn:hover {
    background: rgba(255, 255, 255, 0.2);
    color: white;
}

.code-copy-btn.copied {
    color: var(--mud-palette-success);
}

/* ===== Date pickers (TronairBlazorWebApp#144) =====
   Every MudDatePicker / MudDateRangePicker that shows a text field takes Class="stratus-date-picker" and no
   width of its own. AppManagerLibrary.Tests/DatePickerConventionTests enforces this.
   - Never give a picker a Style. MudBlazor 8 copies a picker's Style onto its calendar popover too, which has
     overflow-x:hidden, so a width there crops the 310px calendar (Market Index's max-width:170px cut off
     Thursday to Saturday).
   - A picker fills its grid column, or shares a flex row (MudBlazor's own flex: 1 1 auto). This rule only sets
     the floor: the formatted date, the label, the calendar icon and a clear button fit, and a flex row wraps
     before it squeezes the picker. min(..., 100%) keeps it inside a narrower container.
   - When a grid column is too narrow, widen the column; don't size the picker. A class in a component's scoped
     .razor.css never reaches a picker (it's another component's element) without ::deep. */
.mud-picker.stratus-date-picker {
    min-width: min(12rem, 100%);
}

/* A range picker shows two dates, the arrow between them and the icon. */
.mud-picker.stratus-date-picker:has(.mud-range-input-separator) {
    min-width: min(20rem, 100%);
}
