/* wave-networks-core custom styles */

/* =============================================
   Sidebar — responsive 3-state layout
   Base state (LG+ ≥992px): expanded 224px
   ============================================= */

#sidebar {
    width: 224px;
    height: 100vh;
    position: sticky;
    top: 0;
    transition: width 0.3s ease;
    overflow: hidden;
    flex-shrink: 0;
}

/* Let the nav area scroll if it overflows, keep brand + footer pinned.
   flex-wrap: nowrap overrides Bootstrap .nav's flex-wrap:wrap — without it,
   flex-direction:column + wrap causes items to flow into adjacent columns
   when they overflow vertically (instead of scrolling). */
#sidebar > nav {
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
    flex-wrap: nowrap !important;
}

#sidebar .nav-link {
    padding: 8px 12px;
    border-radius: 4px;
    margin-bottom: 2px;
    white-space: nowrap;
    display: flex;
    align-items: center;
}

#sidebar .nav-link:hover {
    background-color: rgba(255, 255, 255, 0.1);
}

/* Icon sizing */
#sidebar .sidebar-icon {
    font-size: 1.1rem;
    width: 1.5rem;
    text-align: center;
    flex-shrink: 0;
}

/* Text + badge fade on collapse */
#sidebar .sidebar-text {
    margin-left: 0.5rem;
    transition: opacity 0.2s ease;
    overflow: hidden;
    /* The row is a flex line: icon (flex-shrink:0) + text + badge. Without
       min-width:0 the label refuses to shrink below its content — .nav-link sets
       white-space:nowrap — so a long label eats the badge's margin-left:auto,
       the gap goes to 0, and the badge is squeezed until its content runs into
       the text. Measured live: 9.4px gap in the web app but 0.2px in the mobile
       shell, whose extra theme.css renders the same label ~3px wider. Let the
       label ellipsize instead, and keep a real gap that auto cannot collapse. */
    min-width: 0;
    text-overflow: ellipsis;
    padding-right: 0.5rem;
}

#sidebar .sidebar-badge {
    transition: opacity 0.2s ease;
    margin-left: auto;
    flex-shrink: 0;   /* the badge is the count — never squeeze it */
}

/* The main column is a flex item, so its default min-width:auto is its content's
   min-content width. One unshrinkable descendant (a nowrap tab strip, a long
   btn-group) then widened the whole column past the viewport on a phone, pushing
   the top-bar controls off-screen and the page into horizontal scroll. */
#wrapper > .flex-grow-1 {
    min-width: 0;
}

/* Notification bell dropdown. Long unbroken text (file paths in error digests)
   ran out of the 360px panel, and on a phone the panel itself hung off the left
   edge. Below 576px it is pinned to the viewport under the top bar instead. */
#notifDropdown .dropdown-item {
    overflow-wrap: anywhere;
    word-break: break-word;
}
@media (max-width: 575.98px) {
    #notifDropdown.show {
        position: fixed !important;
        inset: 52px 8px auto 8px !important;
        transform: none !important;
        width: auto !important;
        max-height: calc(100vh - 68px) !important;
    }
}

/* Brand area + topnav — locked to same height so borders align */
#wrapper > .flex-grow-1 > .navbar,
#sidebar .sidebar-brand {
    height: 48px;
    min-height: 48px;
    max-height: 48px;
    box-sizing: border-box;
}

#sidebar .sidebar-brand {
    white-space: nowrap;
    display: flex;
    align-items: center;
}

#sidebar .sidebar-brand-icon {
    font-size: 1.4rem;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

#sidebar .sidebar-brand-icon img {
    height: 24px;
    width: 24px;
    object-fit: contain;
}

#sidebar .sidebar-brand-text {
    margin-left: 0.5rem;
    transition: opacity 0.2s ease;
    overflow: hidden;
}

/* Toggle icon rotation */
#sidebarToggleIcon {
    transition: transform 0.3s ease;
    display: inline-block;
}

/* =============================================
   Collapsed state — icon-only (60px)
   Applied by JS on LG+ when user clicks toggle
   ============================================= */

#sidebar.collapsed {
    width: 60px;
}

#sidebar.collapsed .sidebar-text,
#sidebar.collapsed .sidebar-brand-text {
    opacity: 0;
    width: 0;
    margin-left: 0;
    padding-right: 0;   /* the expanded gap must not survive the collapse */
    overflow: hidden;
}

#sidebar.collapsed .sidebar-badge {
    display: none;
}

#sidebar.collapsed .nav-link {
    justify-content: center;
    padding: 10px 0;
}

#sidebar.collapsed .sidebar-brand {
    justify-content: center;
}

#sidebar.collapsed .sidebar-icon {
    font-size: 1.25rem;
    margin: 0;
}

#sidebar.collapsed #sidebarToggleIcon {
    transform: rotate(180deg);
}

/* Sidebar backdrop — hidden by default, shown on mobile when sidebar is open */
#sidebarBackdrop {
    display: none;
}

/* =============================================
   XS (<576px) — hidden by default, slide-in overlay
   ============================================= */

@media (max-width: 575.98px) {
    /* Break #wrapper's stacking context so sidebar z-index works at root level.
       Without this, wrapper's inline z-index:1 traps sidebar (even at 1050)
       and any backdrop element/pseudo covers the sidebar, blocking clicks. */
    #wrapper {
        z-index: auto !important;
    }

    /* Keep main content above the canvas background (z-index:0) */
    #wrapper > .flex-grow-1 {
        position: relative;
        z-index: 1;
    }

    /* body prefix boosts specificity above theme CSS (custom.css loads after
       style.css and uses !important on #sidebar background-color — with equal
       specificity last-loaded wins. body #sidebar beats #sidebar). */
    body #sidebar {
        position: fixed;
        top: 0;
        left: -224px;
        z-index: 1050;
        height: 100vh;
        min-height: 0;
        transition: left 0.3s ease;
        /* Solid opaque background — theme CSS sets transparent bg + backdrop-filter.
           -webkit-backdrop-filter on iOS Safari creates stacking contexts that
           break touch events AND makes the sidebar see-through. */
        background: #1a1a2e !important;
        background-color: #1a1a2e !important;
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }

    [data-bs-theme="light"] body #sidebar {
        background: #f0f0f3 !important;
        background-color: #f0f0f3 !important;
    }

    body.sidebar-visible #sidebar {
        left: 0;
    }

    /* Backdrop: real element at z-index just below sidebar.
       Now works correctly because #wrapper no longer traps stacking. */
    body.sidebar-visible #sidebarBackdrop {
        display: block !important;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 1049;
    }

    /* Never icon-only on mobile */
    #sidebar.collapsed {
        width: 224px;
    }

    /* Hide collapse toggle on mobile (hamburger button handles it) */
    #sidebar .sidebar-toggle-area,
    #sidebar .sidebar-footer {
        display: none !important;
    }
}

/* =============================================
   SM-MD (576px – 991px) — collapsed by default
   ============================================= */

@media (min-width: 576px) and (max-width: 991.98px) {
    #sidebar {
        width: 60px;
    }

    #sidebar .sidebar-text,
    #sidebar .sidebar-brand-text {
        opacity: 0;
        width: 0;
        margin-left: 0;
        padding-right: 0;   /* the expanded gap must not survive the collapse */
        overflow: hidden;
    }

    #sidebar .sidebar-badge {
        display: none;
    }

    #sidebar .nav-link {
        justify-content: center;
        padding: 10px 0;
    }

    #sidebar .sidebar-brand {
        justify-content: center;
    }

    #sidebar .sidebar-icon {
        font-size: 1.25rem;
        margin: 0;
    }

    #sidebar #sidebarToggleIcon {
        transform: rotate(180deg);
    }

    /* User toggled to expand */
    #sidebar.expanded {
        width: 224px;
    }

    #sidebar.expanded .sidebar-text,
    #sidebar.expanded .sidebar-brand-text,
    #sidebar.expanded .sidebar-badge {
        opacity: 1;
        width: auto;
    }

    /* The badge is hidden with display:none above, and opacity/width cannot
       resurrect a display:none element — so expanding the sidebar in this range
       restored every label but never the counts. As a flex item the value is
       blockified anyway; inline-block is Bootstrap's own for .badge. */
    #sidebar.expanded .sidebar-badge {
        display: inline-block;
    }

    #sidebar.expanded .nav-link {
        justify-content: flex-start;
        padding: 8px 12px;
    }

    #sidebar.expanded .sidebar-brand {
        justify-content: flex-start;
    }

    #sidebar.expanded .sidebar-icon {
        font-size: 1.1rem;
    }

    #sidebar.expanded #sidebarToggleIcon {
        transform: rotate(0deg);
    }
}

/* Auth card centering */
.auth-wrapper {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

.auth-card {
    width: 100%;
    max-width: 420px;
}

/* Table improvements */
.table th {
    white-space: nowrap;
}

.table th a {
    text-decoration: none;
    color: inherit;
}

.table th a:hover {
    text-decoration: underline;
}

/* Badge spacing in tables */
.badge + .badge {
    margin-left: 4px;
}

/* =============================================
   Sidebar — collapsible submenu (nested nav)
   ============================================= */

.sidebar-submenu .nav-link {
    padding: 6px 12px 6px 2.5rem;
    font-size: 0.875rem;
    opacity: 0.85;
}

.sidebar-submenu .nav-link:hover {
    opacity: 1;
}

.sidebar-submenu .nav-link.active {
    opacity: 1;
}

/* Caret rotation when expanded */
.sidebar-caret {
    transition: transform 0.2s ease;
    font-size: 0.7rem;
}

[aria-expanded="true"] .sidebar-caret {
    transform: rotate(180deg);
}

/* Hide submenu + caret when sidebar is collapsed (LG+) */
#sidebar.collapsed .sidebar-submenu,
#sidebar.collapsed .sidebar-caret {
    display: none !important;
}

#sidebar.collapsed .sidebar-parent {
    cursor: pointer;
}

#sidebar.collapsed .sidebar-parent .sidebar-icon {
    margin: 0;
    pointer-events: none; /* clicks pass through to parent <a> */
}

/* SM-MD collapsed state: hide submenu + caret */
@media (min-width: 576px) and (max-width: 991.98px) {
    #sidebar .sidebar-submenu,
    #sidebar .sidebar-caret {
        display: none !important;
    }

    #sidebar .sidebar-parent {
        cursor: pointer;
    }

    #sidebar .sidebar-parent .sidebar-icon {
        margin: 0;
        pointer-events: none;
    }

    #sidebar .sidebar-parent .sidebar-caret {
        margin-left: 0 !important;
    }

    /* When expanded at SM-MD, show submenu */
    #sidebar.expanded .sidebar-submenu,
    #sidebar.expanded .sidebar-caret {
        display: flex !important;
    }

    #sidebar.expanded .sidebar-parent {
        justify-content: flex-start;
        padding: 8px 12px;
        cursor: default;
    }

    #sidebar.expanded .sidebar-parent .sidebar-icon {
        pointer-events: auto;
    }
}

/* =============================================
   Touch screens — no field zooms the page on tap
   =============================================
   iOS Safari zooms the page in when a focused field computes under 16px and
   leaves it zoomed, so the chrome is lost until the person pinches back out.
   Bootstrap's .form-control-sm / .form-select-sm (.875rem) trip it, and core's
   own views and every child app use them. On a touch screen every place you
   type computes at least 16px; desktop keeps the compact sizing. The fix is
   the font size, never maximum-scale=1 / user-scalable=no (pinch-zoom is an
   accessibility feature). !important because app themes load after this file. */
/* Either gate: a touch-only screen, or iOS/iPadOS WebKit (-webkit-touch-callout
   exists only there), so an iPad with a trackpad is covered too. */
@media (hover: none) and (pointer: coarse) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="image"]),
    select,
    textarea,
    [contenteditable="true"] {
        font-size: max(16px, 1em) !important;
    }
}
@supports (-webkit-touch-callout: none) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="image"]),
    select,
    textarea,
    [contenteditable="true"] {
        font-size: max(16px, 1em) !important;
    }
}
