/* ══════════════════════════════════════════════════════════════════════
   Folded-in legacy nav CSS (#sbn top-bar) — SSC-000038.
   Byte-for-byte the former /_shared/v1/skysuite-nav.css, relocated here so the
   shell no longer needs a separate <link>. sky-sidebar.js decorates #sbn and
   reuses these .sbn-* classes, so the rules must ship with the nav script's
   companion stylesheet. Prepended (not appended) to preserve the original
   cascade order: it previously loaded immediately BEFORE sky-theme.css.
   The standalone skysuite-nav.css file remains on disk for skysuite-track(-v2).
   ══════════════════════════════════════════════════════════════════════ */
/* SkySuite Unified Navigation Widget v20 - CSS */
/* Variables (dark theme defaults, matches SkySuite drone-suite-theme) */
:root {
    --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    /* Nav is ALWAYS dark — hardcoded, never changes with theme */
    --nav-bg: #0f172a;
    --nav-sub-bg: #1e293b;
    --nav-border: #334155;
    --nav-text: #94a3b8;
    --nav-text-hover: #e2e8f0;
    --nav-text-active: #f8fafc;
    --nav-brand: #38bdf8;
    --nav-active: #38bdf8;
    --nav-active-border: #ff00ae; /* SkySuite logo pink — left-border selection accent */
    --nav-active-bg: rgba(56, 189, 248, 0.12);
    --nav-dd-bg: #1e293b;
    --nav-dd-border: #334155;
    --nav-dd-text: #cbd5e1;
    --nav-dd-hover-bg: rgba(59, 130, 246, 0.15);
    --nav-dd-active: #60a5fa;
    --nav-sub-title: #60a5fa;
    --nav-pg-active-border: #60a5fa;
}

#sbn {
    position: sticky;
    top: 0;
    z-index: 1070;
    font-family: var(--font-sans);
}

#sbn .sbn-main {
    background: var(--nav-bg);
    display: flex;
    align-items: center;
    padding: 0 1rem;
    min-height: var(--sky-topbar-h, 42px);
    position: relative;
    z-index: 2;
}

#sbn .sbn-brand {
    text-decoration: none;
    display: flex;
    align-items: center;
    margin-right: 1rem;
    flex-shrink: 0;
}

#sbn .sbn-brand-icon {
    font-size: 1.25rem;
    color: var(--nav-brand);
    margin-right: 0.4rem;
}

#sbn .sbn-brand-text {
    font-weight: 700;
    color: var(--nav-text-hover);
    font-size: 0.95rem;
    white-space: nowrap;
}

#sbn .sbn-tabs {
    display: flex;
    align-items: center;
    gap: 2px;
    flex: 1;
}

#sbn .sbn-tab {
    padding: 0.4rem 0.65rem;
    font-size: 0.82rem;
    border-radius: 5px;
    color: var(--nav-text);
    text-decoration: none;
    transition: all 0.15s;
    white-space: nowrap;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

#sbn .sbn-tab:hover {
    color: var(--nav-text-hover);
    background: var(--theme-muted-surface);
}

#sbn .sbn-tab.active {
    color: var(--nav-active);
    background: var(--nav-active-bg);
    font-weight: 600;
}

/* Group dropdown tabs in Row 1 */
#sbn .sbn-grp {
    display: inline-flex;
    align-items: center;
}

#sbn .sbn-right {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    margin-left: auto;
}

#sbn .sbn-sep {
    width: 1px;
    height: 20px;
    background: var(--nav-border);
    opacity: 0.5;
    margin: 0 0.4rem;
}

#sbn .sbn-link {
    padding: 0.35rem 0.55rem;
    font-size: 0.82rem;
    color: var(--nav-text);
    text-decoration: none;
    transition: color 0.15s;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

#sbn .sbn-link:hover {
    color: var(--nav-text-hover);
}

#sbn .sbn-dd {
    position: relative;
    padding-bottom: 12px;
    margin-bottom: -12px;
}

#sbn .sbn-dd-toggle {
    cursor: pointer;
}

#sbn .sbn-dd-toggle::after {
    content: "";
    display: inline-block;
    margin-left: 0.25rem;
    vertical-align: 0.12em;
    border-top: 0.28em solid;
    border-right: 0.22em solid transparent;
    border-left: 0.22em solid transparent;
    opacity: 0.5;
}

#sbn .sbn-dd-menu {
    display: none;
    position: absolute;
    top: calc(100% - 12px);
    z-index: 1090;
    min-width: auto;
    padding: 0.4rem 0;
    background: var(--nav-dd-bg);
    border: 1px solid var(--nav-dd-border);
    border-radius: 8px;
    box-shadow: var(--theme-shadow-md);
    margin-top: 0;
    padding-top: 0.5rem;
}

#sbn .sbn-dd-menu::before {
    content: "";
    position: absolute;
    top: -16px;
    left: -8px;
    right: -8px;
    height: 18px;
    background: transparent;
}

#sbn .sbn-dd-menu.sbn-dd-menu-right {
    right: 0;
    left: auto;
}

#sbn .sbn-dd.hover-open > .sbn-dd-menu,
#sbn .sbn-dd.open > .sbn-dd-menu {
    display: block;
}

#sbn .sbn-dd-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 1rem;
    font-size: 0.82rem;
    color: var(--nav-dd-text);
    text-decoration: none;
    transition: background 0.1s;
    white-space: nowrap;
}

#sbn .sbn-dd-item:hover {
    background: var(--nav-dd-hover-bg);
    color: var(--nav-text-hover);
}

#sbn .sbn-dd-item.active {
    color: var(--nav-dd-active);
}

#sbn .sbn-dd-divider {
    height: 1px;
    margin: 0.3rem 0;
    background: var(--nav-border);
    opacity: 0.6;
}

/* Row 2: Sub-navigation */
#sbn .sbn-sub {
    background: var(--nav-sub-bg);
    border-bottom: 1px solid var(--nav-border);
    display: flex;
    align-items: center;
    padding: 0 1rem;
    min-height: 36px;
    gap: 2px;
    position: relative;
    z-index: 1;
}

#sbn .sbn-sub-title {
    color: var(--nav-sub-title);
    font-weight: 700;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-right: 1rem;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

#sbn .sbn-pg {
    padding: 0.35rem 0.6rem;
    font-size: 0.82rem;
    color: var(--nav-text);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    transition: all 0.15s;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

#sbn .sbn-pg:hover {
    color: var(--nav-text-hover);
    border-bottom-color: var(--theme-accent-soft);
}

#sbn .sbn-pg.active {
    color: var(--nav-text-hover);
    border-bottom-color: var(--nav-pg-active-border);
    font-weight: 500;
}

/* Item badge (used by Radar, Line for counts) */
#sbn .sbn-item-badge {
    display: inline-block;
    background: var(--theme-danger-bg);
    color: var(--theme-danger-fg);
    font-size: 0.65rem;
    font-weight: 600;
    padding: 0.1rem 0.4rem;
    border-radius: 10px;
    margin-left: 0.25rem;
    min-width: 1rem;
    text-align: center;
    line-height: 1.2;
}

#sbn .sbn-collapse {
    display: contents;
}

/* In sidebar mode, hide top-bar tabs AND sub-nav (navigation lives in the sidebar) */
body.sky-sidebar-mode #sbn .sbn-collapse {
    display: none !important;
}
body.sky-sidebar-mode #sbn .sbn-sub {
    display: none !important;
}
body.sky-sidebar-mode #sbn .sbn-toggle {
    display: none !important;
}

#sbn .sbn-toggle {
    display: none;
    background: none;
    border: 1px solid var(--nav-border);
    color: var(--nav-text);
    padding: 0.2rem 0.5rem;
    border-radius: 4px;
    cursor: pointer;
    font-size: 1.1rem;
    margin-left: auto;
    line-height: 1;
}

.sbn-beta-badge {
    display: inline-block;
    background: var(--theme-success-bg);
    color: var(--theme-success-fg);
    font-size: 0.7rem;
    font-weight: 600;
    padding: 0.15rem 0.5rem;
    border-radius: 10px;
}

/* Dim Row 2 when Row 1 dropdown is open */
#sbn.sbn-dd-active .sbn-sub {
    opacity: 0.15;
    pointer-events: none;
    transition: opacity 0.15s;
}

#sbn .sbn-sub {
    transition: opacity 0.15s;
}

/* Footer */
#sbn-footer {
    background: var(--nav-bg);
    border-top: 1px solid var(--nav-border);
    padding: 1.5rem 2rem;
    margin-top: 3rem;
    font-family: var(--font-sans);
    color: var(--nav-text);
    font-size: 0.82rem;
}

#sbn-footer .sbn-footer-inner {
    max-width: 1400px;
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

#sbn-footer .sbn-footer-links {
    display: flex;
    gap: 1.5rem;
}

#sbn-footer .sbn-footer-links a {
    color: var(--nav-text);
    text-decoration: none;
    opacity: 0.7;
    transition: opacity 0.15s;
}

#sbn-footer .sbn-footer-links a:hover {
    opacity: 1;
    color: var(--nav-text-hover);
}

/* Backdrop (hidden on desktop, shown on mobile via media query) */
.sbn-backdrop {
    display: none;
}

/* ════════════════════════════════════════════════════
   MOBILE — Full overlay drawer, always-expanded groups
   S5 (mobile audit 2026-09-26): was max-width:992px, out of step
   with the sidebar/tab-bar breakpoint below (768px). In the 768-992px
   band (iPad portrait, many Android tablets) that gap produced BOTH
   the desktop 240px sidebar AND this header's hamburger/drawer at
   once, with no bottom tab bar — a confusing dual-nav state. Aligned
   to 768px so the header and sidebar/tab-bar switch together.
   ════════════════════════════════════════════════════ */
@media (max-width: 768px) {
    #sbn .sbn-main {
        flex-wrap: wrap;
    }

    #sbn .sbn-toggle {
        display: flex;
        align-items: center;
        justify-content: center;
        transition: color 0.15s;
    }

    /* SSC.000551: body scroll while this menu is open is locked by the shared
       SkyScrollLock in sky-sidebar.js (iOS-safe, reference-counted, restored
       exactly on close). body.sbn-menu-open is only a state marker now — an
       overflow:hidden!important here was a second, uncounted lock that a
       missed class removal could strand. */

    /* Backdrop overlay (sibling of #sbn, just below it in stacking order) */
    .sbn-backdrop {
        display: block;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: var(--theme-overlay);
        z-index: 1069;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.2s ease;
    }

    .sbn-backdrop.open {
        opacity: 1;
        pointer-events: auto;
    }

    /* ── Full-screen overlay drawer (absolute, not fixed — avoids sticky containing block) ── */
    #sbn .sbn-collapse {
        display: flex;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        height: calc(100vh - 80px);
        height: calc(100dvh - 80px);
        flex-direction: column;
        background: var(--nav-bg);
        padding: 0;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior: contain;
        touch-action: pan-y;
        z-index: 10;
        border-top: 1px solid var(--nav-border);
        transform: translateY(-8px);
        opacity: 0;
        visibility: hidden;
        transition: transform 0.2s ease, opacity 0.15s ease, visibility 0s linear 0.2s;
    }

    #sbn .sbn-collapse.open {
        transform: translateY(0);
        opacity: 1;
        visibility: visible;
        transition: transform 0.2s ease, opacity 0.15s ease, visibility 0s linear 0s;
    }

    /* ── Module groups: section-header + always-expanded items ── */
    #sbn .sbn-tabs {
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding: 0.35rem 0 0;
    }

    #sbn .sbn-grp {
        display: flex;
        flex-direction: column;
        align-items: stretch;
    }

    /* Group header = non-interactive section label */
    #sbn .sbn-tab {
        padding: 0.85rem 1.25rem 0.35rem;
        font-size: 0.65rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        color: var(--nav-text);
        opacity: 0.45;
        border-radius: 0;
        width: 100%;
        pointer-events: none;
    }

    #sbn .sbn-tab:hover {
        background: transparent;
    }

    #sbn .sbn-tab.active {
        color: var(--nav-active);
        background: transparent;
        opacity: 0.65;
    }

    /* Hide dropdown caret on group headers */
    #sbn .sbn-grp > .sbn-tab.sbn-dd-toggle::after {
        display: none;
    }

    /* Reset dropdown positioning for mobile */
    #sbn .sbn-dd {
        position: static;
        padding-bottom: 0;
        margin-bottom: 0;
    }

    /* Group items: always visible (no toggle needed) */
    #sbn .sbn-grp > .sbn-dd-menu {
        display: block !important;
        position: static !important;
        box-shadow: none;
        border: none;
        background: transparent;
        border-radius: 0;
        min-width: 0;
        padding: 0 0 0.15rem;
        margin: 0;
    }

    #sbn .sbn-grp > .sbn-dd-menu::before {
        display: none;
    }

    /* Module items — full-width, good touch targets */
    #sbn .sbn-grp .sbn-dd-item {
        padding: 0.8rem 1.25rem;
        font-size: 0.93rem;
        font-weight: 400;
        border-left: 3px solid transparent;
        border-radius: 0;
    }

    #sbn .sbn-grp .sbn-dd-item i.bi {
        font-size: 1.05rem;
        width: 1.3rem;
        text-align: center;
        flex-shrink: 0;
    }

    #sbn .sbn-grp .sbn-dd-item.active {
        border-left-color: var(--nav-active-border);
        color: var(--nav-active);
        background: var(--nav-active-bg);
        font-weight: 500;
    }

    #sbn .sbn-grp .sbn-dd-item:hover {
        background: var(--theme-muted-surface);
    }

    /* ── Right section (Hub, Admin, User) ── */
    #sbn .sbn-right {
        flex-direction: column;
        align-items: stretch;
        margin-left: 0;
        margin-top: 0;
        padding: 0.5rem 0;
        border-top: 1px solid var(--nav-border);
        gap: 0;
    }

    #sbn .sbn-link {
        padding: 0.8rem 1.25rem;
        font-size: 0.93rem;
        border-left: 3px solid transparent;
    }

    #sbn .sbn-link.active {
        border-left-color: var(--nav-active-border);
        color: var(--nav-active);
    }

    #sbn .sbn-sep {
        display: none;
    }

    /* User dropdown in mobile — always expanded */
    #sbn .sbn-right > .sbn-dd > .sbn-dd-menu {
        position: static;
        box-shadow: none;
        border: none;
        background: transparent;
        border-radius: 0;
        padding: 0;
    }

    #sbn .sbn-right > .sbn-dd > .sbn-dd-menu.sbn-dd-menu-right {
        right: auto;
        left: 0;
    }

    #sbn .sbn-right .sbn-dd-item {
        padding: 0.7rem 1.25rem 0.7rem 3.25rem;
        font-size: 0.9rem;
    }

    #sbn .sbn-beta-badge {
        font-size: 0.78rem;
    }

    /* ── Row 2: Horizontal scroll, no wrap ── */
    #sbn .sbn-sub {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior: contain;
        touch-action: pan-y;
        padding: 0 0.75rem;
        gap: 0;
        scrollbar-width: none;
    }

    #sbn .sbn-sub::-webkit-scrollbar {
        display: none;
    }

    #sbn .sbn-sub-title {
        flex-shrink: 0;
        margin-right: 0.35rem;
    }

    #sbn .sbn-pg {
        padding: 0.5rem 0.7rem;
        font-size: 0.82rem;
        flex-shrink: 0;
    }

    /* Row 2 dropdowns: flatten inline (no popups — overflow clips them) */
    #sbn .sbn-sub .sbn-dd {
        display: contents;
        flex-shrink: 0;
    }

    /* Hide the dropdown toggle label — children shown directly */
    #sbn .sbn-sub .sbn-dd > .sbn-pg.sbn-dd-toggle {
        display: none;
    }

    /* Show menu items inline in the scroll row */
    #sbn .sbn-sub .sbn-dd-menu {
        display: contents !important;
        background: transparent;
        border: none;
        box-shadow: none;
        border-radius: 0;
        min-width: 0;
        padding: 0;
    }

    #sbn .sbn-sub .sbn-dd-menu::before {
        display: none;
    }

    #sbn .sbn-sub .sbn-dd-item {
        padding: 0.5rem 0.7rem;
        font-size: 0.82rem;
        flex-shrink: 0;
        white-space: nowrap;
        border-bottom: 2px solid transparent;
    }

    #sbn .sbn-sub .sbn-dd-item:hover {
        background: transparent;
        border-bottom-color: var(--theme-accent-soft);
    }

    #sbn .sbn-sub .sbn-dd-item.active {
        color: var(--nav-text-hover);
        border-bottom-color: var(--nav-pg-active-border);
        background: transparent;
        font-weight: 500;
    }

    /* Don't dim Row 2 on mobile */
    #sbn.sbn-dd-active .sbn-sub {
        opacity: 1;
        pointer-events: auto;
    }
}

/* SSC.000472: Row 1's `flex-wrap: wrap` (above) exists for the hamburger
   drawer's benefit, but the header's own visible children — brand, toggle,
   the online pill, the stealth-mode eye, chat, and the account button
   sky-sidebar.js appends — must always stay on ONE row. On a narrow phone
   (reported at 384px) that row can come a hair wider than the viewport and
   wrap the account button onto its own second line, doubling the header
   height and — worse — moving its popup's anchor point (see sky-sidebar.js
   injectUserProfileBtn / positionUserMenu) to the wrong spot. Everything in
   this row already carries flex-shrink:0 or a narrow collapsed face at this
   width, so forcing nowrap here doesn't newly hide anything; it just stops
   the row from doubling in height. */
@media (max-width: 480px) {
    #sbn .sbn-main {
        flex-wrap: nowrap;
    }
}

@media (max-width: 576px) {
    #sbn-footer {
        padding: 1.25rem 1rem;
    }
    #sbn-footer .sbn-footer-inner {
        flex-direction: column;
        text-align: center;
    }
}

/* Mobile touch targets - ensure minimum 44px for all interactive elements */
/* S5 (mobile audit 2026-09-26): aligned to 768px, see note above. */
@media (max-width: 768px) {
    #sbn .sbn-toggle {
        min-width: 44px;
        min-height: 44px;
    }
    #sbn .sbn-link {
        min-height: 44px;
    }
}

/* ── Nav consolidation (2026-06-22) ──────────────────────────────────
   ONE global nav = the left sidebar (.sky-sidebar). This top bar (#sbn)
   is reduced to a HEADER: brand/logo on the left, user/chat/theme/hub on
   the right. Its redundant module nav, page sub-nav, and (iced) org
   switcher are hidden — the sidebar owns all navigation. */
#sbn .sbn-collapse,
#sbn .sbn-sub,
#sbn .sbn-org-dd { display: none !important; }


/* ── end folded legacy nav CSS · original sky-theme.css follows ── */

/**
 * Sky Suite Unified Theme v5
 * Light/dark mode + 3-tab sidebar layout.
 * Loaded by ALL services via /_shared/v1/sky-theme.css
 *
 * v5: Tab bar below header, mobile bottom tabs, weather strip placeholder.
 *     Remove top-nav mode styles.
 */

/* ── Light mode (default) ────────────────────────────────────── */
:root {
    --sky-primary: #0369a1;
    --sky-primary-rgb: 3, 105, 161;
    --sky-accent: #6366f1;
    --sky-bg: #ffffff;
    --sky-surface: #ffffff;
    --sky-surface-hover: #e0f2fe;
    --sky-border: #93c5fd;
    --sky-text: #000000;
    --sky-text-muted: #1e3a5f;
    --sky-sidebar-bg: #f0f4f8;
    --sky-sidebar-text: #334155;
    --sky-sidebar-active: #0369a1;
    --sky-sidebar-hover: #e0f2fe;
    --bs-body-bg: #ffffff;
    --bs-secondary-bg: #ffffff;
    --bs-tertiary-bg: #ffffff;
    --bs-body-color: #000000;
    --bs-secondary-color: #1e3a5f;
    --bs-border-color: #93c5fd;
    --bs-table-bg: transparent;
    --bs-table-hover-bg: #e0f2fe;
    --bs-modal-bg: #ffffff;
    --sky-tab-bg: #e8ecf0;
    --sky-tab-active-bg: #ffffff;
    --sky-tab-text: #475569;
    --sky-tab-active-text: #0369a1;

    /* Profile avatar menu (#skyUserBtn) — light-mode palette. The menu is built
       with hardcoded dark inline styles in sky-sidebar.js (correct in dark); these
       tokens drive the light-mode re-skin at the end of this file. */
    --sky-usermenu-bg: #f8fafc;
    --sky-usermenu-border: #e2e8f0;
    --sky-usermenu-shadow: 0 10px 28px rgba(15, 23, 42, 0.12), 0 2px 6px rgba(15, 23, 42, 0.07);
    --sky-usermenu-text: #334155;
    --sky-usermenu-icon: #64748b;
    --sky-usermenu-hover-bg: #eef2f8;
    --sky-usermenu-hover-text: #0f172a;
    --sky-usermenu-divider: rgba(15, 23, 42, 0.08);
    --sky-usermenu-danger: #dc2626;
    --sky-usermenu-danger-bg: rgba(220, 38, 38, 0.08);
    --sky-usermenu-btn: #475569;
    --sky-usermenu-btn-hover: #0f172a;

    /* Semantic chrome tokens (fallback values; overridden by theme packs). */
    --theme-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
    --theme-shadow-md: 0 6px 18px rgba(15, 17, 23, 0.10), 0 1px 3px rgba(15, 17, 23, 0.06);
    --theme-shadow-lg: 0 16px 40px rgba(15, 17, 23, 0.14), 0 2px 6px rgba(15, 17, 23, 0.08);
    --theme-overlay: rgba(15, 17, 23, 0.5);
    --theme-muted-surface: rgba(15, 17, 23, 0.04);
    --theme-focus-ring: var(--sky-primary);
    --theme-accent-soft: color-mix(in oklab, var(--sky-primary) 12%, transparent);
    --theme-success: #16a34a;
    --theme-success-bg: rgba(22, 163, 74, 0.12);
    --theme-success-fg: #15803d;
    --theme-danger: #dc2626;
    --theme-danger-bg: rgba(220, 38, 38, 0.10);
    --theme-danger-fg: #b91c1c;
    --theme-warning: #d97706;
    --theme-warning-bg: rgba(217, 119, 6, 0.12);
    --theme-warning-fg: #b45309;
    --theme-info: #0891b2;
    --theme-info-bg: rgba(8, 145, 178, 0.12);
    --theme-info-fg: #0e7490;
}

/* ── Dark mode ────────────────────────────────────────────────── */
[data-bs-theme="dark"] {
    --sky-primary: #0dcaf0;
    --sky-primary-rgb: 13, 202, 240;
    --sky-accent: #818cf8;
    --sky-bg: #0f1117;
    --sky-surface: #1a1d27;
    --sky-surface-hover: #242836;
    --sky-border: #2a2e3a;
    --sky-text: #ffffff;
    --sky-text-muted: #c8dce8;
    --sky-sidebar-bg: #12151e;
    --sky-sidebar-text: #a0aec0;
    --sky-sidebar-active: #0dcaf0;
    --sky-sidebar-hover: #1e2235;
    --bs-body-bg: #0f1117;
    --bs-secondary-bg: #1a1d27;
    --bs-tertiary-bg: #1a1d27;
    --bs-body-color: #ffffff;
    --bs-secondary-color: #c8dce8;
    --bs-border-color: #2a2e3a;
    --bs-table-bg: transparent;
    --bs-table-hover-bg: #242836;
    --bs-modal-bg: #1a1d27;
    --sky-tab-bg: #181b24;
    --sky-tab-active-bg: #1e2235;
    --sky-tab-text: #8892a4;
    --sky-tab-active-text: #0dcaf0;
}

body {
    background: var(--sky-bg) !important;
    color: var(--sky-text);
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    min-height: 100vh;
    transition: background-color 0.15s ease, color 0.15s ease;
}

/* ── Tab bar (fixed in header, positioned after logo) ─────────── */
.sky-tab-bar {
    position: fixed;
    top: 0;
    left: 140px; /* overridden by JS based on brand width */
    height: var(--sky-topbar-h, 42px);
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 0 0.5rem;
    z-index: 1071;
    width: fit-content;
}

.sky-tab {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 20px;
    border: none;
    background: transparent;
    color: var(--sky-tab-text);
    font-size: 0.82rem;
    font-weight: 500;
    cursor: pointer;
    border-radius: 6px;
    transition: all 0.15s ease;
    position: relative;
    white-space: nowrap;
    line-height: 1;
}

.sky-tab i {
    font-size: 0.9rem;
}

.sky-tab:hover {
    background: var(--sky-surface-hover);
    color: var(--sky-text);
}

.sky-tab--active {
    background: var(--sky-tab-active-bg);
    color: var(--tab-color, var(--sky-tab-active-text));
    font-weight: 600;
    box-shadow: var(--theme-shadow-sm);
}

.sky-tab--active::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 10%;
    right: 10%;
    height: 2px;
    background: var(--tab-color, var(--sky-tab-active-text));
    border-radius: 2px 2px 0 0;
}

/* ── App layout: sidebar + content ────────────────────────────── */
.sky-app-layout {
    display: flex;
    min-height: calc(100vh - var(--sky-topbar-h, 42px)); /* header only */
}

.sky-sidebar {
    /* Width defaults to 240px; drag-to-resize sets --sky-sidebar-width in
       [160,240]. Unset => 240px, byte-identical to the pre-resize default. */
    width: var(--sky-sidebar-width, 240px);
    background: var(--sky-sidebar-bg);
    border-right: 1px solid var(--sky-border);
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition: width 0.2s ease, min-width 0.2s ease, transform 0.2s ease;
    position: sticky;
    top: var(--sky-topbar-h, 42px); /* header only */
    /* SSC.000178 (Eric B.): the usable height is NOT a constant. The in-flow
       banner stack (soft-open notice + /admin/banners) sits between the header
       and .sky-app-layout, so with a banner up the rail starts 117-350px lower
       and a hardcoded calc(100vh - 42px) hangs that far below the fold — which
       is what hid the sticky collapse toggle and the tail of the nav list. At
       the other end, the same fixed height cannot fit above the footer, so
       sticky's containing-block clamp dragged the rail ABOVE the header.
       sky-sidebar.js (updateRailGeometry) publishes the live measured value;
       the calc() below is the no-JS fallback and the value before it settles.
       The <=768px drawer is position:fixed — viewport-anchored, so it is
       banner-independent and keeps its own height rule further down. */
    height: var(--sky-rail-h, calc(100vh - var(--sky-topbar-h, 42px)));
}

.sky-sidebar-scroll-area {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    /* SSC.000137 (Eric B.): the nav sits flush at the top. This used to be
       `padding: 0.75rem 0`, whose 12px top padding stacked on top of the first
       child's own spacing (.sky-newdoor already carries margin-top:8px), so the
       frame opened with 20px of dead space with no favourites and 12px with
       them. Each child keeps its own spacing; the scroll area no longer adds a
       second, invisible one. Bottom padding stays as end-of-list breathing room. */
    padding: 0 0 0.75rem;
}

.sky-sidebar .sky-nav-section-title {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--sky-text-muted);
    padding: 0.75rem 1rem 0.35rem;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    user-select: none;
}

.sky-sidebar .sky-nav-section-title:hover {
    color: var(--sky-text);
}

.sky-sidebar .sky-nav-section-title .chevron {
    transition: transform 0.15s;
    font-size: 0.6rem;
}

.sky-sidebar .sky-nav-section.collapsed .sky-nav-section-title .chevron {
    transform: rotate(-90deg);
}

.sky-sidebar .sky-nav-section.collapsed .sky-nav-items {
    display: none;
}

.sky-sidebar .sky-nav-item {
    display: flex;
    align-items: center;
    padding: 0.45rem 1rem;
    color: var(--sky-sidebar-text);
    text-decoration: none;
    font-size: 0.85rem;
    border-left: 3px solid transparent;
    transition: all 0.12s ease;
    min-height: 38px;
}

.sky-sidebar .sky-nav-item:hover {
    background: var(--sky-sidebar-hover);
    color: var(--sky-text);
}

.sky-sidebar .sky-nav-item.active {
    background: rgba(13, 202, 240, 0.12);
    color: var(--sky-sidebar-active);
    border-left-color: var(--sky-sidebar-active);
    font-weight: 600;
}

.sky-sidebar .sky-nav-item i {
    width: 20px;
    margin-right: 0.6rem;
    text-align: center;
    font-size: 0.9rem;
}

.sky-sidebar .sky-nav-badge {
    margin-left: auto;
    font-size: 0.7rem;
    padding: 0.15rem 0.45rem;
    border-radius: 10px;
    background: var(--sky-accent);
    /* SSC.000189: --sky-text is near-black in light mode, which reads at 2.63:1
       on the darkened light accent. --sky-on-accent is set by the light packs
       only; dark falls back to --sky-text exactly as before. */
    color: var(--sky-on-accent, var(--sky-text));
}

.sky-content {
    flex: 1;
    min-width: 0;
    padding: 1.25rem;
    /* S2 (mobile audit 2026-09-26): platform-wide backstop against sideways
       page scroll. A single unwrapped wide element inside a page (a table
       missing .table-responsive, a <pre>, a chart canvas) used to make the
       WHOLE document scroll horizontally, since nothing here ever clipped
       it. `clip` (not `hidden`/`auto`) is deliberate: unlike hidden/auto,
       overflow:clip does NOT establish a scroll container, so it does not
       trigger the CSS quirk where setting one axis non-visible forces the
       other axis to `auto` — and it is therefore invisible to
       position:sticky descendants (e.g. sticky table headers, the sticky
       .sky-sidebar), which keep resolving stickiness against the real
       document scroll exactly as before. It only clips paint overflow. */
    overflow-x: clip;
}

/* S2 (mobile audit 2026-09-26): global image/media guard — the twin of the
   overflow-x:clip above. Without this, a content image wider than its
   column (blog, chat attachments, embedded charts) was the single most
   common cause of the sideways-scroll bug the clip above now contains;
   this stops it from ever rendering oversized in the first place. Scoped
   to media elements only — never applied to generic containers/tables
   (those get per-page .table-responsive wrappers, tracked separately).
   height:auto is limited to img/video (preserves aspect ratio when an
   explicit width/height HTML attribute would otherwise squish a shrunk
   image) — deliberately NOT applied to canvas/svg, since many small
   inline icon svgs/canvases size themselves via width/height attributes
   with no separate CSS height, and a blanket height:auto would override
   that sizing platform-wide. */
img, video, canvas, svg {
    max-width: 100%;
}
img, video {
    height: auto;
}

/* ── Breadcrumbs (shared {% block breadcrumbs %}) ─────────────────────────
   Optional per-page trail rendered inside .sky-content, above the page body.
   The shell block emits NOTHING when a page ignores it, so these rules only
   style the container a page opts into — no empty bar, no layout shift for
   every page that leaves the block empty. Small, muted, auto-separated; the
   theme tokens flip it for light/dark automatically. Plural ".breadcrumbs" so
   it never collides with Bootstrap's ".breadcrumb". Separators are inserted by
   CSS, so a page just lists its links + a current item. Usage:

     {% block breadcrumbs %}
     <nav class="breadcrumbs" aria-label="Breadcrumb">
       <a href="/office/work/field/dsp">DSP</a>
       <a href="/projects/42">North Field</a>
       <span aria-current="page">Survey</span>
     </nav>
     {% endblock %}
*/
.breadcrumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.9rem;
    font-size: 0.8125rem;
    line-height: 1.4;
    color: var(--sky-text-muted, #64748b);
}
.breadcrumbs > *:not(:first-child)::before {
    content: "/";
    margin-right: 0.4rem;
    color: var(--sky-border, var(--sky-text-muted, #94a3b8));
    opacity: 0.75;
}
.breadcrumbs a {
    color: var(--sky-text-muted, #64748b);
    text-decoration: none;
}
.breadcrumbs a:hover,
.breadcrumbs a:focus-visible {
    color: var(--sky-accent, var(--sky-primary, #6366f1));
    text-decoration: underline;
}
.breadcrumbs [aria-current="page"],
.breadcrumbs .breadcrumbs__current {
    color: var(--sky-text, inherit);
    font-weight: 600;
}

/* ── TASK 22: the shell-rendered breadcrumb (sky-sidebar.js) ──────────────
   <nav class="sky-breadcrumb" aria-label="Breadcrumb"><ol><li>…</li></ol></nav>
   is inserted as the first child of .sky-content on every Office / Field menu
   page; its text IS the menu path (Office › Money › Invoices). Compact, muted,
   one line on desktop, wraps on a phone; the current item is bold. Hand-written page trails are hidden while it is shown. */
.sky-breadcrumb {
    margin: 0 0 0.75rem;
    font-size: 0.8125rem;
    line-height: 1.35;
    color: var(--sky-text-muted, #64748b);
}
.sky-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.15rem 0;
    margin: 0;
    padding: 0;
    list-style: none;
}
.sky-breadcrumb li {
    display: inline-flex;
    align-items: center;
    min-width: 0;
}
.sky-breadcrumb li + li::before {
    content: "\203A";
    margin: 0 0.45rem;
    color: var(--sky-text-muted, #94a3b8);
    opacity: 0.7;
}
.sky-breadcrumb a,
.sky-breadcrumb li > span {
    display: inline-flex;
    align-items: center;
    /* WCAG 2.5.8 AA target (24px) without the 44px phone rule that would turn
       a one-line trail into a 44px-tall, top-aligned strip. */
    min-height: 24px;
}
.sky-breadcrumb a {
    color: var(--sky-text-muted, #64748b);
    text-decoration: none;
    border-radius: 3px;
}
.sky-breadcrumb a:hover,
.sky-breadcrumb a:focus-visible {
    color: var(--sky-accent, var(--sky-primary, #6366f1));
    text-decoration: underline;
}
.sky-breadcrumb [aria-current="page"] {
    color: var(--sky-text, inherit);
    font-weight: 600;
}
.sky-breadcrumb .sky-breadcrumb__leaf {
    color: var(--sky-text, inherit);
    max-width: 22rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sky-breadcrumb--inset {
    padding: 0.75rem 1rem 0;
}
/* Full-bleed app surfaces (chat): a slim header bar with NO outer margin, so
   the page can size itself from the bar's bottom edge exactly. */
.sky-breadcrumb.sky-breadcrumb--bar {
    margin: 0;
    padding: 0.3rem 1rem;
    border-bottom: 1px solid var(--sky-border, rgba(148, 163, 184, 0.2));
    background: var(--sky-surface, transparent);
}
/* Open item 5a2a8c65: on a phone the 24px links were too small to tap (CRM
   dashboard at 390px, every theme). The 44px target is an invisible ::before
   centred on each link, not a taller box, so the trail keeps its slim row and
   the bar does not grow. It reaches 10px past the row above and below, which
   the trail's own margin and the page padding absorb. Same 768px breakpoint
   as the phone tap-target rule. */
@media (max-width: 768px) {
    .sky-breadcrumb a { position: relative; }
    .sky-breadcrumb a::before {
        content: "";
        position: absolute;
        left: -4px;
        right: -4px;
        top: 50%;
        height: 44px;
        margin-top: -22px;
    }
}
@media (max-width: 576px) {
    .sky-breadcrumb { font-size: 0.75rem; margin-bottom: 0.5rem; }
    .sky-breadcrumb.sky-breadcrumb--bar { margin-bottom: 0; padding: 0.25rem 0.75rem; }
    .sky-breadcrumb li + li::before { margin: 0 0.3rem; }
    .sky-breadcrumb .sky-breadcrumb__leaf { max-width: 11rem; }
}
@media print {
    .sky-breadcrumb { display: none; }
}

/* ââ SSC.000396 (Michael L.) â iOS home-screen PWA (standalone) scroll âââ
   iPhone 16 / iOS 26-27 beta: added to the home screen and launched as a
   standalone PWA the page would not scroll â yet the same page scrolls in the
   Safari tab. The shell scrolls at the document level, but drone-suite-theme.css
   makes <body> a flex column (display:flex; flex-direction:column;
   min-height:100vh) with a fixed background. WebKit fails to make an overflowing
   flex scroll-root scrollable in standalone: a Safari tab re-flows when the
   address bar collapses and unsticks it, standalone never gets that event, so it
   stays frozen. Scoped to standalone ONLY â desktop and the normal mobile
   browser never match this block, so they are byte-identical.
     Â· display:block                     â a normal block scroll-root, not a flex one
     Â· 100dvh                            â correct standalone height (100vh mis-sizes)
     Â· overflow-y:auto + -webkit-â¦touch â momentum document scrolling
     Â· background-attachment:scroll      â a fixed bg freezes standalone scroll */
/* SSC.000533 (Jeff S., Android) - the fix above was never actually taking
   effect. sky-sidebar.js buildFooter() injects an UNCONDITIONAL <style
   id="sbn-footer-style"> on every single page (so the "Â© ... Vista UAV"
   footer can sit at the bottom via margin-top:auto on a flex column body):
     html{height:100%}
     body{min-height:100vh;display:flex!important;flex-direction:column!important}
   That tag is appended to <head> at runtime, i.e. AFTER this stylesheet's
   <link>, so for any property it does not mark !important (here: min-height)
   it already wins on source order alone; for 'display' both are !important,
   so it comes down to the cascade's next tiebreaker, specificity - and
   `body` vs `body` is a dead tie, so the LATER rule in the document
   (sbn-footer-style, always injected after the <link>) still wins. Net
   effect, confirmed on this box by matching the two rules against the live
   DOM: body's computed display stayed "flex" and min-height stayed "100vh"
   even with this block's selector matching - the exact flex/100vh
   combination this fix exists to escape. iOS WebKit was the originally-
   reported engine, but Android's on-screen gesture/nav bar resizes the
   visual viewport the same way Safari's address bar does, so 100vh
   mis-sizing (and WebKit's flex-scroll-root freeze, where that engine is in
   play) reproduces there too - which is what SSC.533 reported.
   Fix, verified live against the running page (both orders tested): adding
   !important alone is NOT enough - sbn-footer-style is also !important and
   physically later, so plain `body{...!important}` here still loses on
   source order. Qualifying the selector as `html body` (specificity 0,0,2
   vs sbn-footer-style's 0,0,1) wins outright on specificity instead, which
   beats source order regardless of injection timing. Deliberately NOT
   touching sbn-footer-style itself: its own !important is defensive against
   unknown per-service body{display} CSS across every microservice this
   shell loads into, and weakening it risks un-pinning the footer elsewhere.
   Scoped to standalone ONLY, so desktop and the normal mobile browser are
   byte-identical. */
@media all and (display-mode: standalone) {
    html body {
        display: block !important;
        min-height: 100vh !important;
        min-height: 100dvh !important;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        background-attachment: scroll !important;
    }
}

/* ── Mobile responsive ────────────────────────────────────────── */
@media (max-width: 768px) {
    /* Hide inline tab bar on mobile — bottom tabs used instead */
    .sky-tab-bar {
        display: none !important;
    }

    .sky-app-layout {
        min-height: calc(100vh - var(--sky-topbar-h, 42px) - 56px); /* header + bottom tab bar */
    }

    /* John 10-18 ("The mobile doesn't let you scroll to the bottom of the
       menu list"): the drawer was sized calc(100vh - header - 56px). On iOS
       Safari 100vh is the height with the toolbar HIDDEN, and while the
       drawer is open the page is scroll-locked, so the toolbar never hides:
       the drawer's last ~80px sat below the visible screen. It also left
       56px for a tab bar that is 56px + the home-indicator inset, so on
       notched iPhones another 34px sat under the tab bar. The drawer is now
       pinned between the header and the tab bar (top + bottom), which
       follow the visible viewport, so its scroll always ends at the last
       item, in every browser chrome state. */
    .sky-sidebar {
        position: fixed;
        top: var(--sky-topbar-h, 42px);
        bottom: calc(56px + env(safe-area-inset-bottom, 0px)); /* the bottom tab bar's top edge */
        left: 0;
        z-index: 1040;
        transform: translateX(-100%);
        width: 280px;
        height: auto;
        box-shadow: var(--theme-shadow-lg);
    }
    .sky-sidebar .sky-sidebar-scroll-area {
        min-height: 0;
        overscroll-behavior: contain;
    }

    .sky-sidebar.mobile-open {
        transform: translateX(0);
    }

    .sky-mobile-backdrop {
        display: none;
        position: fixed;
        top: var(--sky-topbar-h, 42px);
        left: 0;
        right: 0;
        bottom: calc(56px + env(safe-area-inset-bottom, 0px));
        background: var(--theme-overlay);
        z-index: 1039;
    }

    .sky-mobile-backdrop.active {
        display: block;
    }

    .sky-content {
        padding: 0.75rem;
        padding-bottom: calc(70px + env(safe-area-inset-bottom)); /* space for bottom tab bar + iOS home indicator */
    }

    /* SSC.000290 (Jeff S.) — a touch-target height, NOT a layout rewrite.

       This block used to list `a` with the controls and give the whole list
       `display:flex`, which turned every anchor on the platform into a
       block-level, full-width, 44px-tall box below 768px. A link written
       inside a sentence stopped being part of the sentence, and because the
       breakpoint is a width, the same phone was correct in landscape and
       wrong in portrait — which is exactly how it was reported.

       Measured on /office/calls at 360x640 (Android portrait, page as landed,
       no scrolling): the "Calendar" link in the intro paragraph rendered as a
       296x44 block at y=575 instead of a 54x17 inline link, so 35 of its 44
       rows overlapped the fixed 56px bottom tab bar at y=584. Its own text was
       drawn underneath that bar, document.elementFromPoint at the link centre
       returned the tab bar compass icon, and tapping the link navigated to
       /field/tools/outlook — the Field tab — rather than the calendar. In
       landscape (844px) the rule is off and the same tap works.

       min-height stays on `a` on purpose. Per CSS it does nothing to a
       non-replaced inline box, so a link inside a sentence is left alone,
       while an anchor its own stylesheet already makes block / flex /
       inline-block still gets the 44px target. WCAG 2.5.8 exempts inline
       links from the target-size minimum for the same reason. Every other
       control keeps the layout it had: this splits `a` out of the display
       declaration and changes nothing else.

       Open item 902bbc6e (2026-10-22): `input` here used to mean EVERY input,
       so on phones each checkbox and radio was drawn as a 44px-tall bar on
       every form that loads this sheet. The height is for text-like fields;
       checkboxes, radios, ranges, colour / file pickers, image buttons and
       hidden inputs are excluded. :where() keeps the selector at the
       specificity bare `input` had (0,0,1), so every rule that beat it before
       (.form-control-sm, a page's own field height) still does. Chained
       :not()s rather than one :not() list keep the selector free of commas. */
    a, button, .btn,
    input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="hidden"]):not([type="file"]):not([type="image"])),
    select, textarea, .sky-nav-item {
        min-height: 44px;
    }

    /* 902bbc6e: the 44px TAP AREA for a checkbox or radio comes from its
       label, not from stretching the control. The row gets 10px above and
       below, and the label reaches into that padding with a matching
       negative margin, so a tap anywhere in the band lands on the label and
       toggles the box; links inside a label stay links. min-height makes the
       band 44px whatever the pack's line height (Classic's 24px line fills it
       exactly; a 13px pack's ~20px line gets 4px more), so a list of options
       is at most as tall as the 44px bars it replaces. A label that WRAPS its
       box (no .form-check) gets the same band; it is :where() so a page that
       styles its own labels still wins. */
    .form-check {
        padding-top: 10px;
        padding-bottom: 10px;
        margin-bottom: 0;
    }
    .form-check-label,
    :where(label:has(> input[type="checkbox"])),
    :where(label:has(> input[type="radio"])) {
        display: inline-block;
        box-sizing: border-box;
        min-height: 44px;
        padding-top: 10px;
        padding-bottom: 10px;
        margin-top: -10px;
        margin-bottom: -10px;
    }

    /* S6 (mobile audit 2026-09-26): display:flex belongs on actual
       buttons/nav-items, not on native form controls — forcing flex on
       input/select/textarea distorts native rendering (select arrows,
       input baselines, input-group addons, .btn-group children). The
       44px min-height above already delivers the tap-target size these
       controls need; flex isn't required for that. */
    button, .btn, .sky-nav-item {
        display: flex;
        align-items: center;
    }
}

/* ── Mobile bottom tab bar ────────────────────────────────────── */
.sky-mobile-tab-bar {
    display: none;
}

@media (max-width: 768px) {
    .sky-mobile-tab-bar {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        height: calc(56px + env(safe-area-inset-bottom));
        background: var(--sky-sidebar-bg);
        border-top: 1px solid var(--sky-border);
        z-index: 1050;
        padding: 0 0 env(safe-area-inset-bottom);
    }

    .sky-mobile-tab {
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        border: none;
        background: transparent;
        color: var(--sky-tab-text);
        font-size: 0.65rem;
        font-weight: 500;
        cursor: pointer;
        padding: 4px 0;
        transition: color 0.15s;
    }

    .sky-mobile-tab i {
        font-size: 1.2rem;
    }

    .sky-mobile-tab--active {
        color: var(--sky-primary);
        font-weight: 600;
    }

    .sky-mobile-tab--active i {
        color: var(--sky-primary);
    }
}

/* ── Sky card (universal) ─────────────────────────────────────── */
.sky-card {
    background: var(--sky-surface);
    border: 1px solid var(--sky-border);
    border-radius: 8px;
}

.sky-card:hover {
    border-color: var(--sky-primary);
}

/* ── Tables ───────────────────────────────────────────────────── */
.table {
    color: var(--sky-text);
}

.table thead th {
    background: var(--sky-surface);
    border-bottom: 2px solid var(--sky-border);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--sky-text-muted);
}

/* ── Sidebar scrollbar ──────────────────────────────────────── */
.sky-sidebar-scroll-area::-webkit-scrollbar {
    width: 4px;
}
.sky-sidebar-scroll-area::-webkit-scrollbar-track {
    background: transparent;
}
.sky-sidebar-scroll-area::-webkit-scrollbar-thumb {
    background: var(--sky-border);
    border-radius: 4px;
}
.sky-sidebar-scroll-area::-webkit-scrollbar-thumb:hover {
    background: var(--sky-text-muted);
}
.sky-sidebar-scroll-area {
    scrollbar-width: thin;
    scrollbar-color: var(--sky-border) transparent;
}

/* ── Turbo Drive progress bar ──────────────────────────────── */
.turbo-progress-bar {
    background: var(--sky-primary);
    height: 3px;
    z-index: 9999;
}

.sky-content {
    transition: opacity 120ms ease-in-out;
}
body.turbo-loading .sky-content {
    opacity: 0.6;
}

/* ── Sidebar group labels (Field tab section headers) ─────── */
.sky-sidebar-group-label {
    font-size: 0.6rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--sky-text-muted);
    opacity: 0.5;
    padding: 0.9rem 1rem 0.2rem;
    margin-top: 0.1rem;
    cursor: pointer;
    user-select: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.sky-sidebar-group-label:hover {
    opacity: 0.8;
}

.sky-sidebar-group:first-child .sky-sidebar-group-label {
    padding-top: 0.4rem;
    margin-top: 0;
}

.sky-sidebar-group-label .group-chevron {
    font-size: 0.5rem;
    opacity: 0.5;
    transition: transform 0.2s;
}

.sky-group-collapsed .sky-sidebar-group-label .group-chevron {
    transform: rotate(-90deg);
}

.sky-sidebar-group-content {
    overflow: hidden;
}

.sky-group-collapsed .sky-sidebar-group-content {
    display: none;
}

/* ── Sub-sections (nested within module sections) ────── */
.sky-nav-subsection {
    margin: 0;
    padding: 0;
}

.sky-nav-subsection .sky-nav-sub-title {
    font-size: 0.63rem;
    padding: 0.5rem 1rem 0.25rem 1.6rem;
    color: var(--sky-text-muted);
    opacity: 0.8;
}

.sky-nav-subsection .sky-nav-sub-title:hover {
    opacity: 1;
}

.sky-nav-subsection .sky-nav-items {
    padding-left: 0;
}

.sky-nav-subsection .sky-nav-item {
    padding-left: 1.6rem;
    font-size: 0.82rem;
}

.sky-nav-section-title i.bi {
    opacity: 0.7;
}

.sky-nav-section-title:hover i.bi {
    opacity: 1;
}

/* ── Sidebar collapse/expand ──────────────────────────── */
.sky-sidebar.sky-sidebar-collapsed {
    width: 50px !important;
    min-width: 50px !important;
}

.sky-sidebar-collapsed .sky-nav-item span,
.sky-sidebar-collapsed .sky-sidebar-group-label,
.sky-sidebar-collapsed .sky-nav-sub-title,
.sky-sidebar-collapsed .sky-nav-section-title span {
    display: none;
}

.sky-sidebar-collapsed .sky-nav-section-title .chevron,
.sky-sidebar-collapsed .sky-sidebar-group-label .group-chevron {
    display: none;
}

.sky-sidebar-collapsed .sky-nav-item {
    text-align: center;
    padding-left: 0 !important;
    padding-right: 0 !important;
    justify-content: center;
    border-left-width: 2px;
    position: relative;
}

.sky-sidebar-collapsed .sky-nav-item i {
    margin-right: 0 !important;
    font-size: 1.1rem;
}

.sky-sidebar-collapsed .sky-nav-section-title {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
}

.sky-sidebar-collapsed .sky-nav-section-title i.bi {
    margin-right: 0 !important;
    font-size: 0.85rem;
}

.sky-sidebar-collapsed .sky-nav-subsection .sky-nav-item {
    padding-left: 0 !important;
}

.sky-sidebar-collapsed .sky-nav-badge {
    display: none;
}

.sky-sidebar-collapsed .sky-sidebar-group-label span {
    display: none;
}

/* SSC.000138 (Eric B.): favourites in the collapsed rail.
   The favourite star is an absolutely-positioned overlay pinned to `right:8px`
   of a nav item. At 240px that sits in empty label space; in the 50px collapsed
   rail there is no spare right edge, so it lands directly on top of the item's
   own icon. The favourites strip has the same problem — it lays chips out with
   flex-wrap into a 49px column.
   Collapsed rail: drop both, and mark a favourited item with a 2px orange inset
   edge instead (Eric's own suggestion). box-shadow rather than border-right so
   the marker costs zero layout width and never nudges the centred icon.
   NOTE: these are undone in the max-width:768px block below — at mobile widths
   `.sky-sidebar-collapsed` is a 280px drawer, not a rail, and has room for both. */
.sky-sidebar-collapsed .sky-fav-star {
    display: none;
}

.sky-sidebar-collapsed #skyFavoritesStrip {
    /* the strip is built in JS with an inline `display:flex`, so an ordinary
       declaration would lose the cascade to the style attribute */
    display: none !important;
}

.sky-sidebar-collapsed .sky-nav-item:has(.sky-fav-star.bi-star-fill) {
    box-shadow: inset -2px 0 0 0 #fbbf24;
}

/* Tooltip on hover for collapsed items */
/* SSC.000124: tooltip is hover-revealed content — on touch it made
   iOS swallow the first tap. Hover-capable pointers only. */
@media (hover: hover) {
    .sky-sidebar-collapsed .sky-nav-item:hover::after {
        content: attr(data-title);
        position: absolute;
        left: 100%;
        top: 50%;
        transform: translateY(-50%);
        background: var(--sky-surface);
        color: var(--sky-text);
        padding: 5px 12px;
        border-radius: 4px;
        font-size: 0.8rem;
        white-space: nowrap;
        z-index: 1060;
        margin-left: 8px;
        pointer-events: none;
        box-shadow: var(--theme-shadow-md);
        border: 1px solid var(--sky-border);
    }
}

.sky-sidebar-collapsed .sky-nav-section-title {
    position: relative;
}

/* SSC.000124: tooltip is hover-revealed content — on touch it made
   iOS swallow the first tap. Hover-capable pointers only. */
@media (hover: hover) {
    .sky-sidebar-collapsed .sky-nav-section-title:hover::after {
        content: attr(data-module-title);
        position: absolute;
        left: 100%;
        top: 50%;
        transform: translateY(-50%);
        background: var(--sky-surface);
        color: var(--sky-text);
        padding: 5px 12px;
        border-radius: 4px;
        font-size: 0.8rem;
        white-space: nowrap;
        z-index: 1060;
        margin-left: 8px;
        pointer-events: none;
        box-shadow: var(--theme-shadow-md);
        border: 1px solid var(--sky-border);
    }
}

/* Collapse toggle button */
.sky-sidebar-collapse-toggle {
    padding: 0.5rem 0;
    border-top: 1px solid var(--sky-border);
    text-align: center;
    flex-shrink: 0;
    background: var(--sky-sidebar-bg);
}

.sky-sidebar-collapse-btn {
    background: none;
    /* SSC.000189: this is a control, so its edge needs 3:1 — --sky-border is the
       decorative hairline (1.15:1 in light). Dark has its own 3:1 token since
       obs-13 (2026-10-17). */
    border: 1px solid var(--ds-control-border, var(--sky-border));
    border-radius: 4px;
    color: var(--sky-text-muted);
    cursor: pointer;
    padding: 6px 12px;
    font-size: 0.85rem;
    transition: all 0.15s ease;
    width: calc(100% - 1rem);
    margin: 0 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.sky-sidebar-collapse-btn:hover {
    background: var(--sky-sidebar-hover);
    color: var(--sky-text);
    border-color: var(--sky-primary);
}

.sky-sidebar-collapsed .sky-sidebar-collapse-btn {
    width: 34px;
    height: 34px;
    padding: 0;
    margin: 0 auto;
    border-radius: 50%;
}

/* SSC.000559 (Eric B.): tablet widths get the icon rail automatically.
   769-1099px: the sidebar is the 50px rail unless the user expanded it for
   this page (html.sky-rail-tablet-open, set by the collapse toggle / "+ New").
   The query is the same string as SIDEBAR_TABLET_MQ in sky-sidebar.js, which
   adds .sky-sidebar-collapsed for the rail's inner treatment; this rule owns
   only the width, so the content column reflows to the rail from the first
   paint. Gated on html.sky-rail-auto (set by the new sky-sidebar.js) so an
   older cached script, which never adds the rail class, cannot be paired with
   a 50px-wide labelled sidebar. <=768px is the drawer and is untouched. */
@media (min-width: 769px) and (max-width: 1099px) {
    html.sky-rail-auto:not(.sky-rail-tablet-open) .sky-sidebar {
        width: 50px !important;
        min-width: 50px !important;
    }
}

/* SSC.000559: rail labels. The ::after tooltips above sit at left:100% of an
   icon inside .sky-sidebar (overflow:hidden), so they were always clipped and
   never seen. sky-sidebar.js now shows one position:fixed label outside the
   rail (#skyRailTip) and sets html.sky-rail-tips; under that class the
   clipped boxes are switched off. Without the new script nothing changes. */
html.sky-rail-tips .sky-sidebar-collapsed .sky-nav-item:hover::after,
html.sky-rail-tips .sky-sidebar-collapsed .sky-nav-section-title:hover::after,
html.sky-rail-tips .sky-sidebar-collapsed .sky-newdoor-btn:hover::after {
    content: none;
    display: none;
}
.sky-rail-tip {
    position: fixed;
    left: 0;
    top: 0;
    transform: translateY(-50%);
    z-index: 1060;
    pointer-events: none;
    background: var(--sky-surface);
    color: var(--sky-text);
    padding: 5px 12px;
    border-radius: 4px;
    font-size: 0.8rem;
    font-weight: 400;
    white-space: nowrap;
    box-shadow: var(--theme-shadow-md);
    border: 1px solid var(--sky-border);
    opacity: 0;
    visibility: hidden;
}
.sky-rail-tip.show {
    opacity: 1;
    visibility: visible;
}
@media (max-width: 768px) {
    .sky-rail-tip {
        display: none;
    }
}

/* John 2026-10-22: "when the sub-menu is collapsed the submenus do not present
   well". The rail kept an open group's rows inline; a group with Field/Office
   sub-groups put them on the expanded tree's indent guide, leaving each row a
   ~10px sliver ("tiny dots on a thin line"). In the rail a group is now ONE
   icon, the same row as a link's, and its rows open in a flyout beside the rail
   (#skyRailFlyout, sky-sidebar.js). Desktop and tablet rail only: the
   <=768px drawer keeps its full rows. The expanded sidebar is untouched. */
@media (min-width: 769px) {
    .sky-sidebar-collapsed .sky-nav-section > .sky-nav-items {
        display: none !important;
    }
    /* group labels are hidden in the rail, so a folded group would lose its
       icons with no way to unfold it: the rail always lists every group */
    .sky-sidebar-collapsed .sky-group-collapsed .sky-sidebar-group-content {
        display: block;
    }
    .sky-sidebar-collapsed .sky-nav-section-title {
        min-height: 38px;
        padding: 0.45rem 0;
        border-left: 2px solid transparent;
        transition: background-color 0.12s ease;
    }
    .sky-sidebar-collapsed .sky-nav-section-title > i.bi:not(.chevron) {
        width: 20px;
        text-align: center;
        font-size: 1.1rem !important;     /* beats the title's inline 0.75rem: the rail's icon size */
        margin-right: 0 !important;
        opacity: 1;
    }
    .sky-sidebar-collapsed .sky-nav-section-title:hover,
    .sky-sidebar-collapsed .sky-nav-section-title.sky-rail-open {
        background: var(--sky-sidebar-hover);
    }
    .sky-sidebar-collapsed .sky-nav-section-title:focus-visible {
        outline: 2px solid var(--sky-primary);
        outline-offset: -2px;
    }
    /* guided accounts' "Show all" / "Short menu" switch: an icon in the rail,
       named by the rail tip (its data-tour anchor is unchanged) */
    .sky-sidebar-collapsed .sky-guided-toggle {
        justify-content: center;
        gap: 0 !important;                /* beats its inline layout */
        margin: 6px 6px 10px !important;
        padding: 9px 0 !important;
    }
    .sky-sidebar-collapsed .sky-guided-toggle > span {
        display: none;
    }
    .sky-sidebar-collapsed .sky-guided-toggle > i.bi {
        font-size: 1.1rem;
    }
    /* the group holding the current page (the item's own highlight is hidden with it) */
    .sky-sidebar-collapsed .sky-nav-section:has(.sky-nav-item.active) > .sky-nav-section-title {
        background: rgba(13, 202, 240, 0.12);
        border-left-color: var(--sky-sidebar-active);
        color: var(--sky-sidebar-active);
    }
    /* No stray scrollbar: with groups folded into icons the rail rarely
       overflows; when it does, the 4px bar above. Chrome 121+ ignores
       ::-webkit-scrollbar once scrollbar-width/-color are set, and its
       "thin" classic bar on Windows is ~11px with arrows — a fifth of the
       rail. Firefox (no ::-webkit-scrollbar) keeps scrollbar-width: thin. */
    @supports selector(::-webkit-scrollbar) {
        .sky-sidebar-collapsed .sky-sidebar-scroll-area {
            scrollbar-width: auto;
            scrollbar-color: auto;
        }
    }
}

/* The rail's flyout: a card beside the rail with the group's rows, labelled. */
.sky-rail-flyout {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1065;
    min-width: 200px;
    max-width: 280px;
    max-height: calc(100vh - 16px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 6px;
    background: var(--sky-surface);
    color: var(--sky-text);
    border: 1px solid var(--sky-border);
    border-radius: 10px;
    box-shadow: var(--theme-shadow-lg, 0 12px 30px rgba(0, 0, 0, 0.35));
    scrollbar-width: thin;
}
.sky-rail-flyout[hidden] {
    display: none;
}
.sky-rail-fly-head {
    padding: 6px 10px 6px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sky-text-muted);
}
.sky-rail-fly-sub {
    padding: 8px 10px 2px;
    margin-top: 2px;
    border-top: 1px solid var(--sky-border);
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--sky-text-muted);
}
.sky-rail-fly-item {
    display: flex;
    align-items: center;
    gap: 9px;
    min-height: 34px;
    padding: 0 10px;
    border-radius: 6px;
    color: var(--sky-text);
    text-decoration: none;
    font-size: 0.86rem;
    white-space: nowrap;
}
.sky-rail-fly-item:hover,
.sky-rail-fly-item:focus-visible {
    background: var(--sky-sidebar-hover);
    color: var(--sky-text);
    text-decoration: none;
}
.sky-rail-fly-item:focus-visible {
    outline: 2px solid var(--sky-primary);
    outline-offset: -2px;
}
.sky-rail-fly-item > i.bi {
    width: 18px;
    flex: none;
    text-align: center;
    font-size: 0.95rem;
    color: var(--sky-text-muted);
}
.sky-rail-fly-item > span {
    overflow: hidden;
    text-overflow: ellipsis;
}
.sky-rail-fly-item.active {
    background: rgba(13, 202, 240, 0.12);
    color: var(--sky-sidebar-active);
    font-weight: 600;
}
.sky-rail-fly-item.active > i.bi {
    color: inherit;
}
.sky-rail-fly-count {
    margin-left: auto;
    padding-left: 12px;
    font-size: 0.72rem;
    color: var(--sky-text-muted);
    font-variant-numeric: tabular-nums;
}
@media (max-width: 768px) {
    .sky-rail-flyout {
        display: none !important;
    }
}

/* Mobile: undo collapse styles */
@media (max-width: 768px) {
    .sky-sidebar.sky-sidebar-collapsed {
        width: 280px !important;
        min-width: 280px !important;
    }
    .sky-sidebar-collapsed .sky-nav-item span,
    .sky-sidebar-collapsed .sky-sidebar-group-label,
    .sky-sidebar-collapsed .sky-sidebar-group-label span,
    .sky-sidebar-collapsed .sky-nav-sub-title,
    .sky-sidebar-collapsed .sky-nav-section-title span {
        display: initial;
    }
    .sky-sidebar-collapsed .sky-nav-section-title .chevron,
    .sky-sidebar-collapsed .sky-sidebar-group-label .group-chevron {
        display: initial;
    }
    .sky-sidebar-collapsed .sky-nav-item {
        justify-content: flex-start;
        padding-left: 1rem !important;
        padding-right: 1rem !important;
        border-left-width: 3px;
    }
    .sky-sidebar-collapsed .sky-nav-item i {
        margin-right: 0.6rem !important;
        font-size: 0.9rem;
    }
    .sky-sidebar-collapsed .sky-nav-section-title {
        justify-content: space-between;
        padding-left: 1rem;
        padding-right: 1rem;
    }
    .sky-sidebar-collapsed .sky-nav-section-title i.bi {
        margin-right: 0.4rem !important;
    }
    .sky-sidebar-collapsed .sky-nav-item:hover::after,
    .sky-sidebar-collapsed .sky-nav-section-title:hover::after {
        display: none;
    }
    .sky-sidebar-collapsed .sky-nav-badge {
        display: initial;
    }
    .sky-sidebar-collapse-toggle {
        display: none;
    }
    /* SSC.000138: the rules above turn the collapsed sidebar back into a 280px
       drawer, so the favourite star and the favourites strip have room again —
       undo their rail-only suppression, and drop the rail-only edge marker. */
    .sky-sidebar-collapsed .sky-fav-star {
        display: initial;
    }
    .sky-sidebar-collapsed #skyFavoritesStrip {
        display: flex !important;
    }
    .sky-sidebar-collapsed .sky-nav-item:has(.sky-fav-star.bi-star-fill) {
        box-shadow: none;
    }
}

/* ── Sidebar drag-to-resize (feat/sidebar-resizable) ──────────────
   Purely additive. Idle handle is invisible and does not shift layout.
   Complements the icon-only collapse: this narrows the sidebar while it
   stays expanded. Width lives in --sky-sidebar-width, clamped [160,240]
   by JS; the collapse rule (width:50px !important) still wins when the
   bar is collapsed, and the handle hides then. Desktop only. */
.sky-sidebar-resize-handle {
    position: absolute;
    top: 0;
    right: 0;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    z-index: 1045;
    background: transparent;
    touch-action: none;
    user-select: none;
}
.sky-sidebar-resize-handle::before {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    width: 2px;
    height: 100%;
    background: var(--sky-primary, #0dcaf0);
    opacity: 0;
    transition: opacity 0.15s ease;
}
.sky-sidebar-resize-handle:hover::before,
.sky-sidebar-resize-handle:focus-visible::before,
body.sky-sidebar-resizing .sky-sidebar-resize-handle::before {
    opacity: 0.55;
}
.sky-sidebar-resize-handle:focus-visible {
    outline: none;
}
.sky-sidebar-resize-handle:focus-visible::before {
    opacity: 0.85;
    width: 3px;
}
/* while dragging: kill the width transition + text selection */
body.sky-sidebar-resizing {
    cursor: col-resize;
    user-select: none;
}
body.sky-sidebar-resizing .sky-sidebar {
    transition: none !important;
}
/* collapsed (icon-only) => resizing is meaningless, hide the handle */
.sky-sidebar-collapsed .sky-sidebar-resize-handle {
    display: none;
}
/* suppress the width transition on first paint / restore (no load flash) */
html.sky-sidebar-no-anim .sky-sidebar {
    transition: none !important;
}
/* truncate labels only when the user has narrowed the bar; absent this
   attribute (default + full width) the render is byte-identical to before */
html[data-sky-sidebar-resized] .sky-sidebar .sky-nav-item span,
html[data-sky-sidebar-resized] .sky-sidebar .sky-nav-sub-title,
html[data-sky-sidebar-resized] .sky-sidebar .sky-sidebar-group-label span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
/* mobile: never show the handle (JS also guards by viewport) */
@media (max-width: 768px) {
    .sky-sidebar-resize-handle {
        display: none !important;
    }
}
@media (prefers-reduced-motion: reduce) {
    .sky-sidebar {
        transition: none;
    }
    .sky-sidebar-resize-handle::before {
        transition: none;
    }
}


/* ══════════════════════════════════════════════════════════════════════════
   Light-mode profile avatar menu (#skyUserBtn)
   ──────────────────────────────────────────────────────────────────────────
   The avatar dropdown top-right is built with hardcoded DARK inline styles in
   sky-sidebar.js (great in dark mode). In light mode that left a dark slate
   panel floating on a light page — the reported "ugly" light dropdown. These
   light-only rules re-skin it as an off-white card: clean border, soft light-
   tuned shadow, legible text, muted icons, and considered hover / divider /
   logout states — matching the polish of the dark version.

   This stylesheet loads LAST, so !important reliably wins over the element's
   inline styles (and the JS-set inline hover backgrounds). Every selector is
   scoped to [data-bs-theme="light"]; DARK MODE HAS NO MATCHING RULES, so it
   renders exactly as before.
   ══════════════════════════════════════════════════════════════════════════ */

/* Surface: off-white card, subtle border, soft shadow (replaces #1e293b /
   #334155 / 0 8px 24px rgba(0,0,0,.4)). */
[data-bs-theme="light"] #skyUserBtn > div {
    background: var(--sky-usermenu-bg) !important;
    border-color: var(--sky-usermenu-border) !important;
    box-shadow: var(--sky-usermenu-shadow) !important;
}

/* Menu items: slate-700 text on off-white, muted slate-500 icons. */
[data-bs-theme="light"] #skyUserBtn > div > a {
    color: var(--sky-usermenu-text) !important;
}
[data-bs-theme="light"] #skyUserBtn > div > a > i.bi {
    color: var(--sky-usermenu-icon) !important;
}

/* Hover: soft cool wash that clearly registers on the light surface, text and
   icon darken to near-black (the JS sets an inline dark-tuned hover bg — the
   !important here overrides it). */
[data-bs-theme="light"] #skyUserBtn > div > a:hover {
    background: var(--sky-usermenu-hover-bg) !important;
    color: var(--sky-usermenu-hover-text) !important;
}
[data-bs-theme="light"] #skyUserBtn > div > a:hover > i.bi {
    color: var(--sky-usermenu-hover-text) !important;
}

/* Dividers: subtle hairline instead of the dark slate line. */
[data-bs-theme="light"] #skyUserBtn > div > div {
    background: var(--sky-usermenu-divider) !important;
}

/* Logout (last item): a light-appropriate red that keeps contrast on the light
   surface, with a soft red hover. Placed after the generic item rules so it
   wins on equal specificity. */
[data-bs-theme="light"] #skyUserBtn > div > a:last-child,
[data-bs-theme="light"] #skyUserBtn > div > a:last-child > i.bi {
    color: var(--sky-usermenu-danger) !important;
}
[data-bs-theme="light"] #skyUserBtn > div > a:last-child:hover {
    background: var(--sky-usermenu-danger-bg) !important;
}
[data-bs-theme="light"] #skyUserBtn > div > a:last-child:hover,
[data-bs-theme="light"] #skyUserBtn > div > a:last-child:hover > i.bi {
    color: var(--sky-usermenu-danger) !important;
}

/* Trigger button in the (now light) header: slate-400 on white was washed out,
   and the JS hover/open state set near-white text (invisible on light). Force a
   legible slate that darkens on hover. */
[data-bs-theme="light"] #skyUserBtn > button {
    color: var(--sky-usermenu-btn) !important;
}
[data-bs-theme="light"] #skyUserBtn > button:hover {
    color: var(--sky-usermenu-btn-hover) !important;
}

/* ══════════════════════════════════════════════════════════════════════
   SSC.000165 — selection helpers for UI chrome.

   Reported by Eric B.: drag-selecting anything on a page also sweeps up the
   decorative furniture around it — tile captions, unit words, status badges,
   count pills — so a copy comes back full of label noise. These two classes
   are the reusable way to fix that; do NOT sprinkle `user-select: none`
   inline at call sites.

   .sky-no-select   Chrome only. Use on things a person would never sensibly
                    copy: section captions ("PILOT BRIEFING"), unit words
                    ("sustained", "gusts"), status/rank/type badges, count
                    pills, decorative icons and separators.

                    NEVER use it on data. IDs, ticket/tracking numbers, names,
                    usernames, emails, dates, readings, totals, error text and
                    anything in a table cell stay selectable — silently
                    blocking a copy is a worse bug than an untidy highlight.
                    When in doubt, leave it off.

   .sky-select-text Re-enables selection inside a .sky-no-select wrapper, for
                    the common "chrome label + real value" pill:

                        <span class="sky-pill sky-no-select">
                          Vis <strong class="sky-select-text">36.9 mi</strong>
                        </span>

                    The word "Vis" is skipped by a drag; the reading is not.
                    Also usable on its own to force selectability back on.
   ══════════════════════════════════════════════════════════════════════ */
.sky-no-select {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.sky-select-text,
.sky-no-select .sky-select-text {
    -webkit-user-select: text;
    -moz-user-select: text;
    -ms-user-select: text;
    user-select: text;
}


/* ══════════════════════════════════════════════════════════════════════
   SSC.000189 (Ken W.) — LEFT RAIL, LIGHT MODE
   ──────────────────────────────────────────────────────────────────────
   Ken's screenshot was the pink text, but the worst of it is here. The rail
   is painted by a <style> tag that sky-sidebar.js injects per tab
   (renderSidebarForTab / the settings variant), and every colour in it is a
   dark-mode value carrying !important:

       .sky-nav-item          -> the tab accent (#0dcaf0 Office / #10b981 Field
                                 / #ef4444 Admin) ....... 1.88:1 on #fafafa
       .sky-nav-item:hover    -> #fff ................... 1.04:1  (invisible)
       .sky-nav-section-title -> #fff ................... 1.04:1  (invisible)
       .sky-nav-sub-title     -> #8a94a6 ................ 2.93:1
       .sky-sidebar-group-label -> the tab accent at the
                                 stylesheet's opacity:.5 . 2.28:1

   Measured in light mode on dev, /office/crm/clients, 1400x900. The section
   headings and the hover state were literally white on a near-white rail. That
   matters more than taste here: a pilot on this platform has one eye and has
   told us menu-diving costs him.

   This is the same pattern the #skyUserBtn re-skin further up uses: leave the
   injected dark styles alone (they are correct in dark, and dark is not to
   move) and re-skin them for light. The injected rules are .sky-sidebar X
   (0,2,0) with !important, so these have to be [data-bs-theme="light"]
   .sky-sidebar X (0,3,0) with !important to win — the injected <style> is
   appended to <head> at runtime, after every <link>, so source order will not
   do it.

   The tab accent survives as an accent: --sky-tab-ink is the same hue taken
   55% of the way to black, which lands every tab colour at >= 5.2:1 on the
   rail (#0dcaf0 -> #076f84 5.56:1, #10b981 -> #096647 6.70:1, #ef4444 ->
   #832525 8.92:1) — a colour-mix, so a new tab colour is carried automatically
   instead of needing a fourth hardcoded hex.
   ══════════════════════════════════════════════════════════════════════ */
[data-bs-theme="light"] {
    --sky-tab-ink: color-mix(in srgb, var(--sky-tab-color, #0dcaf0) 55%, #000);
}

/* Nav links: grey scale, exactly as Ken asked. */
[data-bs-theme="light"] .sky-sidebar .sky-nav-item {
    color: var(--sky-sidebar-text) !important;          /* #525252 — 7.5:1 */
}
[data-bs-theme="light"] .sky-sidebar .sky-nav-item:hover {
    color: var(--sky-text) !important;                  /* #0a0a0a — 18.9:1 */
}
[data-bs-theme="light"] .sky-sidebar .sky-nav-item.active {
    color: var(--sky-tab-ink) !important;
    border-left-color: var(--sky-tab-ink) !important;
    background: color-mix(in srgb, var(--sky-tab-color, #0dcaf0) 14%, transparent) !important;
}

/* Headings: the near-black end of the scale, not white. */
[data-bs-theme="light"] .sky-sidebar .sky-nav-section-title,
[data-bs-theme="light"] .sky-sidebar .sky-nav-section-title i.bi {
    color: var(--sky-text) !important;
}
[data-bs-theme="light"] .sky-sidebar .sky-nav-sub-title,
[data-bs-theme="light"] .sky-sidebar .sky-nav-sub-title i.bi {
    color: var(--ink-3, #6f6f6f) !important;            /* 4.8:1 */
}
/* The group label is the accent, but at opacity .5 the accent is a rumour.
   Full strength on the ink accent instead — still lighter than the item
   labels above it, so the hierarchy survives. */
[data-bs-theme="light"] .sky-sidebar .sky-sidebar-group-label {
    color: var(--sky-tab-ink) !important;
    opacity: 1;
}

/* The "+ New" menu is a dark panel injected with dark colours — readable, but
   a hole in a light UI. Same re-skin treatment. */
[data-bs-theme="light"] .sky-newdoor-menu {
    background: var(--sky-surface);
    border-color: var(--sky-border);
    box-shadow: var(--theme-shadow-md);
}
[data-bs-theme="light"] .sky-newdoor-menu a {
    color: var(--sky-sidebar-text);
}
[data-bs-theme="light"] .sky-newdoor-menu a:hover {
    background: var(--sky-sidebar-hover);
    color: var(--sky-text);
}

/* SSC.000191's Help & feedback entry is a link styled as a button, and its fill
   (--sky-surface) is the same #fafafa as the rail behind it — so that 1px
   --sky-border edge is the ONLY thing that makes it read as a control, at
   1.22:1. Same 3:1 bar (WCAG 1.4.11) and same token as every other control
   boundary in this change set. 191 already hit this: its phone FAB deliberately
   uses a 2px --sky-primary ring "not --sky-border ... which left a white circle
   on a near-white page"; the desktop mount just did not get the same treatment.
   Dark keeps --sky-border through the fallback. */
[data-bs-theme="light"] .sky-support-link {
    border-color: var(--ds-control-border, var(--sky-border));
}

/* Footer links sat at opacity .7 -> 3.56:1. Full strength on the muted ink. */
[data-bs-theme="light"] #sbn-footer .sbn-footer-links a {
    color: var(--ink-3, #6f6f6f);
    opacity: 1;
}

/* The flight-level rank chip prints its rank colour as the label on a 10%
   wash of itself — fine on black, 1.49:1 on white for the amber tiers.
   sky-sidebar.js publishes the raw colour as --sky-fp-color so light can take
   the same 55%-to-black step the rail accent does. */
[data-bs-theme="light"] .sky-fp-name {
    color: color-mix(in srgb, var(--sky-fp-color, #0dcaf0) 55%, #000) !important;
}

/* ── SSC.000189 — HEADER BAR, LIGHT MODE ───────────────────────────────
   Same story one row up. sky-sidebar.js builds the header chrome with inline
   dark colours (#94a3b8 for the icon buttons and the presence pill) and injects
   #skyTabBar's rules with the raw per-tab accent. Measured in light on dev:
       #skyChatBtn / #skyCalendarBtn / #skyThemeBtn / #skyOnlineBtn
           #94a3b8 on #fafafa .......... 2.46:1  (3:1 is the floor for a glyph)
       #skyTabBar .sky-tab--active
           #0dcaf0 on #fafafa .......... 1.88:1  — and this is the LOCKED
           Office/Field/Admin tab bar, the top-level navigation.
   Inline styles, so these need !important; the tab-bar rules are injected at
   (1,1,0) so the overrides carry the theme attribute to reach (1,2,0).
   The tab keeps its own hue — taken to an ink weight the same way the rail is,
   so Office still reads as Office. */
[data-bs-theme="light"] #sbn #skyChatBtn,
[data-bs-theme="light"] #sbn #skyCalendarBtn,
[data-bs-theme="light"] #sbn #skyThemeBtn,
[data-bs-theme="light"] #sbn #skyOnlineBtn,
[data-bs-theme="light"] #sbn #skyHamburger {
    color: var(--ink-2, #525252) !important;            /* 7.5:1 */
}
[data-bs-theme="light"] #sbn #skyChatBtn:hover,
[data-bs-theme="light"] #sbn #skyCalendarBtn:hover,
[data-bs-theme="light"] #sbn #skyThemeBtn:hover,
[data-bs-theme="light"] #sbn #skyOnlineBtn:hover {
    color: var(--sky-text, #0a0a0a) !important;
}

[data-bs-theme="light"] #skyTabBar .sky-tab--active,
[data-bs-theme="light"] #skyTabBar .sky-tab--active span,
[data-bs-theme="light"] #skyTabBar .sky-tab--active i {
    color: color-mix(in srgb, var(--tab-color, #0dcaf0) 55%, #000) !important;
}
[data-bs-theme="light"] #skyTabBar .sky-tab--active::after {
    background: color-mix(in srgb, var(--tab-color, #0dcaf0) 55%, #000) !important;
}

/* The favourites strip prints its links in the tab accent too. */
[data-bs-theme="light"] #skyFavoritesStrip a {
    color: color-mix(in srgb, var(--sky-tab-color, #0dcaf0) 55%, #000) !important;
    border-color: color-mix(in srgb, var(--sky-tab-color, #0dcaf0) 55%, #000) !important;
    background: var(--sky-surface, #fff) !important;
}

/* ── SSC.000189 — two last faded spots in the rail and the user button ──
   Both were fine on black and fail on white once the opacity is folded in
   (which is the whole trick: a 50%-faded label reads at half strength no
   matter how dark its declared colour is).
       .sky-nav-subsection .sky-nav-sub-title  opacity .8 -> 3.27:1
       #skyUserBtn .sky-user-caret             opacity .5 -> 2.31:1
   Full strength in light; the dark rules keep their fades untouched. */
[data-bs-theme="light"] .sky-sidebar .sky-nav-subsection .sky-nav-sub-title {
    opacity: 1;                                          /* #6f6f6f -> 4.8:1 */
}
[data-bs-theme="light"] #skyUserBtn .sky-user-caret {
    opacity: 1 !important;                               /* #475569 -> 7.3:1 */
}

/* ════════════════════════════════════════════════════════════════════════════
   SSC.000248 (Peter L.) — "Improve color palette for Light Mode ... many
   colors are too light and some almost invisible in Light Mode. Colour palette
   is excellent for Dark Mode."

   SSC.000189 retuned the SkySuite tokens for light and that work stands. What
   it could not reach is Bootstrap's own compiled palette: `.btn-warning`,
   `.text-info`, `.badge.bg-success` and friends carry LITERAL hex values baked
   into bootstrap.min.css at build time (`--bs-btn-bg: #ffc107`), so no amount
   of retinting --theme-warning ever reaches them. That is why the theme graph
   test passes while the rendered page still fails.

   Everything below binds one Bootstrap utility to a token this theme already
   defines. No new colours are invented: every value is an existing
   --theme-*-fg / --theme-* / --ds-control-border / --ink. Dark mode is
   untouched — every selector is gated on [data-bs-theme="light"], so in dark
   these rules do not match at all.

   Measured on dev at 1440 and 390, worst ground of the three light surfaces
   (--bg #fff, --bg-1 #fafafa, --bg-2 #f4f4f4).
   ════════════════════════════════════════════════════════════════════════════ */

/* ── 1. Semantic text utilities ───────────────────────────────────────────────
   Bootstrap paints .text-success as rgba(var(--bs-success-rgb), …). The light
   pack sets --bs-success-rgb to the FILL weight (#16a34a) because the same
   token also has to work as a background behind black text — so as body copy
   it lands at 3.30:1, under the 4.5 floor. The ink weights already exist as
   --theme-*-fg; this points the text utilities at them and leaves the fills
   alone, so nothing that uses .bg-success as a ground moves.
       .text-success  #16a34a -> #15803d   3.30 -> 5.02  (4.56 on --bg-2)
       .text-warning  #d97706 -> #b45309   3.19 -> 5.02  (4.57 on --bg-2)
       .text-info     #0891b2 -> #0e7490   3.68 -> 5.36  (4.87 on --bg-2)
       .text-danger   #dc2626 -> #b91c1c   4.83 -> 6.47  (already passing;
                                            moved for consistency of weight)  */
[data-bs-theme="light"] .text-success { color: var(--theme-success-fg) !important; }
[data-bs-theme="light"] .text-danger  { color: var(--theme-danger-fg)  !important; }
[data-bs-theme="light"] .text-warning { color: var(--theme-warning-fg) !important; }
[data-bs-theme="light"] .text-info    { color: var(--theme-info-fg)    !important; }

/* ── 2. Badges on a light fill ────────────────────────────────────────────────
   .badge defaults to --bs-badge-color:#fff. On the light pack's amber, green,
   cyan and grey fills that is white-on-light:
       .badge.bg-success  #fff on #16a34a  3.30:1
       .badge.bg-warning  #fff on #d97706  3.19:1
       .badge.bg-info     #fff on #0891b2  3.68:1
       .badge.bg-light    #fff on #f8f9fa  1.05:1   <- effectively invisible
   Bootstrap's own answer for these fills is an ink foreground (that is exactly
   what .text-bg-warning does, and it measures 6.59:1). Take the same answer.
       -> #0a0a0a on those fills: 6.01 / 6.21 / 5.38 / 18.78                  */
[data-bs-theme="light"] .badge.bg-success,
[data-bs-theme="light"] .badge.bg-warning,
[data-bs-theme="light"] .badge.bg-info,
[data-bs-theme="light"] .badge.bg-light { color: var(--ink, #0a0a0a) !important; }

/* ── 3. Buttons Bootstrap compiles with literal hex ───────────────────────────
   These four variants never see a theme token. Measured before:
       .btn-warning          border #ffc107 on #fff   1.63:1  (3:1 bar)
       .btn-info             border #0dcaf0 on #fff   1.96:1
       .btn-outline-warning  label  #ffc107 on #fff   1.63:1  (4.5:1 bar)
       .btn-outline-info     label  #0dcaf0 on #fff   1.96:1
   Rebound to the pack's own semantic tokens. The filled pair keeps Bootstrap's
   black label, which is what makes an amber/cyan fill legible at all
   (#000 on #d97706 = 6.21, on #0891b2 = 5.38). */
[data-bs-theme="light"] .btn-warning {
    --bs-btn-bg: var(--theme-warning);
    --bs-btn-border-color: var(--theme-warning);
    --bs-btn-hover-bg: var(--theme-warning-fg);
    --bs-btn-hover-border-color: var(--theme-warning-fg);
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--theme-warning-fg);
    --bs-btn-active-border-color: var(--theme-warning-fg);
}
[data-bs-theme="light"] .btn-info {
    --bs-btn-bg: var(--theme-info);
    --bs-btn-border-color: var(--theme-info);
    --bs-btn-hover-bg: var(--theme-info-fg);
    --bs-btn-hover-border-color: var(--theme-info-fg);
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--theme-info-fg);
    --bs-btn-active-border-color: var(--theme-info-fg);
}
[data-bs-theme="light"] .btn-outline-warning {
    --bs-btn-color: var(--theme-warning-fg);
    --bs-btn-border-color: var(--theme-warning);
    --bs-btn-hover-bg: var(--theme-warning);
    --bs-btn-hover-border-color: var(--theme-warning);
    --bs-btn-hover-color: #000;
    --bs-btn-active-bg: var(--theme-warning);
    --bs-btn-active-border-color: var(--theme-warning);
    --bs-btn-active-color: #000;
}
[data-bs-theme="light"] .btn-outline-info {
    --bs-btn-color: var(--theme-info-fg);
    --bs-btn-border-color: var(--theme-info);
    --bs-btn-hover-bg: var(--theme-info);
    --bs-btn-hover-border-color: var(--theme-info);
    --bs-btn-hover-color: #000;
    --bs-btn-active-bg: var(--theme-info);
    --bs-btn-active-border-color: var(--theme-info);
    --bs-btn-active-color: #000;
}

/* ── 4. The "light" button variant, in a light theme ──────────────────────────
   .btn-light is #f8f9fa — a variant designed to sit ON a dark ground. On a
   white page its label AND its whole boundary vanish (1.05:1 both), and the
   platform ships it on real controls: the Prev/Next pager on the CRM list and
   the Work landing. In light mode it becomes what it means — a quiet neutral
   control — using the same boundary token every other control uses.
       label   #f8f9fa -> --ink  #0a0a0a on #f4f4f4 = 17.9:1
       border  #f8f9fa -> --ds-control-border rgba(0,0,0,.45) = 3.36:1        */
[data-bs-theme="light"] .btn-light {
    --bs-btn-bg: var(--bg-2, #f4f4f4);
    --bs-btn-color: var(--ink, #0a0a0a);
    --bs-btn-border-color: var(--ds-control-border, var(--sky-border));
    --bs-btn-hover-bg: var(--bg-3, #ededed);
    --bs-btn-hover-color: var(--ink, #0a0a0a);
    --bs-btn-hover-border-color: var(--ds-control-border, var(--sky-border));
}
[data-bs-theme="light"] .btn-outline-light {
    --bs-btn-color: var(--ink-2, #525252);
    --bs-btn-border-color: var(--ds-control-border, var(--sky-border));
    --bs-btn-hover-bg: var(--bg-2, #f4f4f4);
    --bs-btn-hover-color: var(--ink, #0a0a0a);
    --bs-btn-hover-border-color: var(--ds-control-border, var(--sky-border));
}
/* .btn-secondary's boundary resolves to --ds-gray-300 (#ededed) = 1.17:1. */
[data-bs-theme="light"] .btn-secondary {
    --bs-btn-border-color: var(--ds-control-border, var(--sky-border));
}

/* ── 5. Control boundaries that a module stylesheet took back ─────────────────
   WCAG 1.4.11 puts a 3:1 floor on the boundary of an interactive control, and
   SSC.000189 introduced --ds-control-border (rgba(0,0,0,.45) = 3.36:1) for
   exactly that. It is being overridden: several module base templates declare

       .form-control, .form-select { border-color: var(--sky-border) }
       .form-check-input           { border-color: var(--sky-border) }

   at (0,1,0), and --sky-border is the DECORATIVE hairline — rgba(0,0,0,.09),
   1.22:1. Measured on 18 controls across the CRM list, the new-project form,
   the settings tabs and the injected control swatch: every one at 1.22:1.
   Carrying the theme attribute lifts these to (0,3,0) so they win wherever the
   module rule lands, without editing 20 module templates. :focus and :checked
   are excluded so the accent ring and the checked fill still read.

   This is a workaround for a real structural problem, not a fix for it — the
   modules should be asking for --ds-control-border. Noted in the MR.          */
[data-bs-theme="light"] .form-control:not(:focus),
[data-bs-theme="light"] .form-select:not(:focus),
[data-bs-theme="light"] .input-group-text,
[data-bs-theme="light"] .form-check-input:not(:checked):not(:focus) {
    border-color: var(--ds-control-border, var(--sky-border));
}
