.side-menu {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    width: 55px;
    background: transparent;
    padding: 1rem 0;
    overflow: hidden;
    white-space: nowrap;
    transition: width 0.18s ease;
    /* Deliberately `relative` with NO offset, and no position:sticky enhancement.
       This was `position: sticky; top: 64px`. Under sticky, `top` is only a threshold - and since
       .page is overflow:hidden there is no scrolling ancestor, so it never engaged and the offset
       did nothing. Under `relative` the very same `top` becomes a real 64px downward shift, which
       pushed the menu's bottom to 100vh + 32px: .side-menu-item-bottom (margin-top: auto) pinned
       Settings to that edge and overflow:hidden clipped it, leaving only its top border on screen.
       Chromium 53 rejected `sticky` outright and fell back to `static`, which ignored `top`, so the
       original was unaffected - the fallback is what activated a dormant declaration.
       The height calc already positions this correctly inside .app-body; no offset is wanted. */
    position: relative;
    height: calc(100vh - 96px);
}    .side-menu:hover {
        width: 220px;
    }

    /* Split from the rule above: an unsupported pseudo-class in a comma list
       invalidates the whole list, which would drop the :focus styling too. */
    .side-menu:focus-within {
        width: 220px;
    }


.side-menu-item {
    position: relative;
    display: flex;
    align-items: center;
    height: 50px;
    box-sizing: border-box;
    padding: 0 1.15rem;
    color: #ddd;
    text-decoration: none;
    border-bottom: 1px solid var(--surface-border);
}

    .side-menu-item::before {
        content: "";
        position: absolute;
        left: 0.4rem;
        top: 12%;
        bottom: 12%;
        width: 4px;
        border-radius: 2px;
        background: transparent;
        transition: background-color 0.15s ease;
    }    .side-menu-item:hover,
.side-menu-item:focus {
        outline: 1px solid var(--bright-color);
        outline-offset: -1px;
        background: var(--brand-color);
    }

    /* Split from the rule above: an unsupported pseudo-class in a comma list
       invalidates the whole list, which would drop the :focus styling too. */
    .side-menu-item:focus-visible {
        outline: 1px solid var(--bright-color);
        outline-offset: -1px;
        background: var(--brand-color);
    }


    .side-menu-item-active {
        color: var(--bright-color);
    }

        .side-menu-item-active::before {
            background: var(--brand-color);
        }

.side-menu-item-bottom {
    margin-top: auto;
}

.side-menu-icon {
    flex: 0 0 auto;
    display: flex;
}

.side-menu-label {
    font-size: 1rem;
}

@media (max-width: 720px) {
    .side-menu {
        width: 48px;
    }        .side-menu:hover {
            width: 180px;
        }

        /* Split from the rule above: an unsupported pseudo-class in a comma list
           invalidates the whole list, which would drop the :focus styling too. */
        .side-menu:focus-within {
            width: 180px;
        }


    .side-menu-item {
        padding: 0 0.85rem;
    }
}


/* Chromium 53 has no flexbox gap (Chrome 84). */
.side-menu-item > * + * {
    margin-left: 0.9rem;
}

/* :focus-within is Chrome 60, so the expand-on-focus rule above never matches on the TV - which
   matters because D-pad focus, not hover, is how the menu is reached there. The component adds
   this class from its own focus/blur handlers instead. */
.side-menu.side-menu-focused {
    width: 220px;
}


/* No desktop-only positioning block here, deliberately.
   There used to be one: `position: fixed` plus a z-index, with layout.css reserving 55px on main to
   compensate. It existed because the window was the scroller on desktop, so an in-flow menu scrolled
   away with the document. That pin is what made desktop diverge from the TV - out of flow, the
   expansion could only overlay the page instead of pushing it, which needed an opaque background and
   still covered the posters and the genre dropdown.
   layout.css now gives both modes the same scroll model (the page is fixed at 100vh, `main`
   scrolls), so the menu stays in flow, never scrolls away, and expands by pushing content exactly as
   it does on the TV. One rail, one behaviour, no breakpoint special cases. */
