/*
 * GBA-4070 — the portal shell.
 *
 * Linked only when NEW_SHELL_ENABLED is on, and last in the cascade so these
 * rules outrank the legacy geometry they shadow. Geometry is written as
 * `.header.gshell-header …` (0,2,0) because the legacy rules it replaces are
 * (0,1,0)/(0,2,0) and are never `!important`.
 *
 * The legacy class names are kept on purpose. `_design.php` dumps each tenant's
 * `_color_scheme` as `.header { … !important }` after every stylesheet, so those
 * names ARE the white-label branding contract: whatever a tenant also styles is
 * meant to win over what is written here. That is why the header declares no
 * background — the Figma frame has no fill either, so it shows the page ground
 * on Gemba hosts and the tenant's colour where one is configured.
 *
 * Everything lives inside the desktop half of the legacy 975/976px split, so a
 * phone keeps the legacy header exactly as it is today.
 *
 * Colours are the Figma values. The design system's own HSL triplets render
 * about 1/255 away from the hex in their comments; Figma is the source of truth
 * for this work, so the hex is what gets written.
 */

/*
 * GBA-4301 — tenant colours, the portal's contract.
 *
 * The shell must read as the portal, so its tenant-owned roles are the portal's
 * roles (gemba-frontend `packages/ui/src/lib/color-utils.ts`), not the legacy
 * `--primary-color` family: on Gemba hosts `main.php` sets that family to the
 * legacy blue #2066E6, while the portal is navy there. Each variable below is the
 * design-system default; `ShellTheme` (main.php) overrides only the ones a tenant
 * supplied and that pass the same contrast guards the portal applies.
 *
 * - `--shell-text`         tenant main text (portal `--foreground`)
 * - `--shell-muted`        tenant secondary text (portal `--muted-foreground`)
 * - `--shell-muted-light`  quieter labels (portal `--muted-foreground-light`)
 * - `--shell-border`       tenant border (portal `--border`)
 * - `--shell-primary-text` tenant primary as text: active / hovered nav item and
 *                          focus rings, darkened to 4.5:1 (portal `--primary-text`)
 *
 * Surfaces stay neutral on every host: the #e8eaed pill, the #f3f5f6 card, white.
 */
:root {
    --shell-text: #283349;
    --shell-muted: #697080;
    --shell-muted-light: #9499a4;
    --shell-border: #e8eaed;
    --shell-primary-text: #283349;
}

/*
 * Keep a closed panel out of the focus order, at every width.
 *
 * Legacy hides it with `opacity: 0` and a negative z-index, which was harmless
 * while the client rows were plain divs but leaves real buttons focusable — a
 * keyboard user would tab through invisible controls. `visibility` removes them;
 * delaying it by the length of the fade keeps the closing animation visible.
 *
 * Keyed on `.gshell-panel` rather than on the header, and deliberately outside the
 * desktop media query, because `tools.js` clones `.header-user` into
 * `.navigation-user` at DOM-ready. That clone carries a second copy of this panel,
 * it lives outside `.header.gshell-header`, and it is the copy the mobile
 * navigation shows — so a header-scoped or desktop-only rule would miss it.
 */
.gshell-panel {
    visibility: hidden;
    transition: opacity 250ms ease 0s, transform 250ms ease 0s, visibility 0s linear 250ms;
}

.dropdown.open .gshell-panel {
    visibility: visible;
    transition-delay: 0s;
}

@media all and (min-width: 976px) {
    .header.gshell-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 24px;

        box-sizing: border-box;
        height: 72px;
        padding: 0 24px;

        border-bottom: 1px solid var(--shell-border);

        color: var(--shell-text);
        font-size: 14px;
        line-height: 20px;
    }

    /*
     * The logo leaves the legacy absolute 290x99 box and joins the flex row.
     *
     * Every number below was measured on 2026-09-21 against the branding files on
     * `testing-web-from-prod`, which is cloned from prod: 72 tenants, 70 with a
     * logo path, 69 of those present on disk (`istratov.space` points at a file
     * that is gone, and renders broken on the legacy path too). Formats: 47 png,
     * 11 svg, 8 jpg, 4 jpeg.
     *
     * 240px rather than the frame's 300px. The frame reserves 300 around a 48x48
     * square mark, so nothing in it ever reaches the edge — but real tenant art is
     * mostly horizontal lettering: aspect ratios run 0.86:1 to 9.81:1 with a
     * median of 2.65:1, so a typical logo covers nearly three times the area of
     * the mark the frame was drawn around. This width is the cap `object-fit`
     * letterboxes against; it binds on the 13 logos past 5.45:1, inert for the
     * other 56.
     *
     * The stored `size`/`margin` in each branding file are deliberately ignored.
     * 12 of the 35 tenants that store a numeric height store one above 72px — up
     * to 900px — which encodes the legacy layout rather than the artwork, and
     * survives today only because of the legacy max-height cap.
     */
    .header.gshell-header .logo {
        position: static;
        display: flex;
        flex: 0 0 auto;
        align-items: center;
        width: 240px;
        height: auto;
    }

    /* The anchor is the flex child, so it has to stop being an inline box or the
       48px logo inside it sits on the text baseline. */
    .header.gshell-header .logo a {
        display: flex;
        align-items: center;
    }

    .header.gshell-header .logo img {
        position: static;
        top: auto;
        left: auto;
        transform: none;
        width: auto;
        /*
         * 44px against the frame's 48px. The frame's logo is a 1:1 mark, where 48
         * reads as a compact glyph; a 2.65:1 wordmark at the same height covers
         * nearly three times the area and dominates a 72px bar, which is what it
         * looked like on testing. 44 is as far down as the square marks tolerate —
         * at 40 the two near-square ones (whitlowpay.com 1:1, mon-pay.com 0.86:1)
         * start to read as icons rather than logos.
         */
        height: 44px;
        max-width: 100%;
        max-height: none;
        /*
         * `max-width` alone would clamp the width while `height` stayed put, which
         * squashes a wide logo horizontally; `contain` letterboxes it instead. Not
         * optional: it is what holds the 13 logos past 5.45:1 — anikanov.net at
         * 9.81:1, metropolitan.asia at 6:1 — in proportion. A concrete `height` is
         * equally load-bearing: 2 of the 10 tenant SVGs on disk (`taxus.tech` and
         * one with an empty domain key) declare no width or height on their root
         * element, and `max-height` alone has nothing to clamp and collapses them
         * to 0x0 (GBA-2853).
         */
        object-fit: contain;
        object-position: left center;
    }

    .header.gshell-header .header-info {
        gap: 24px;
        margin-left: auto;
    }

    /*
     * The profile dropdown restyled as the portal account pill. `.header-user`
     * stays the positioning context for the dropdown panel and keeps its
     * `dropdown` hook, so only the button's own shape changes.
     */
    .header.gshell-header .header-user .btn-user-profile {
        display: flex;
        align-items: center;
        gap: 16px;

        /* It is a <button> so the panel can be opened from the keyboard, which means
           undoing the UA styling here. */
        font: inherit;
        text-align: left;
        cursor: pointer;

        box-sizing: border-box;
        height: 40px;
        padding: 0 8px 0 16px;

        border: 1px solid var(--shell-border);
        border-radius: 24px;
        background-color: #ffffff;

        color: var(--shell-text);
    }

    .header.gshell-header .header-user-name {
        gap: 8px;
        font-size: 14px;
        font-weight: 700;
        line-height: 20px;
    }

    /*
     * The profile panel is anchored to the right edge of the pill. Legacy declares
     * no `left`, so the panel takes its static position — the left edge of
     * `.header-user`. That was harmless while the button sat mid-header, but the
     * portal pill ends 24px from the viewport edge, so a 300px panel hung 37px
     * off-screen and gave the whole page a horizontal scrollbar. The open/closed
     * slide is a `transform`, so re-anchoring does not disturb the animation.
     */
    .header.gshell-header .header-user .dropdown-content {
        right: 0;
        left: auto;
        top: calc(100% + 8px);
    }

    .header.gshell-header .gshell-pill-icon {
        display: block;
        flex: 0 0 auto;
        width: 20px;
        height: 20px;
    }

    /*
     * The chip that carries the switchable-account count in the design. Only the
     * chevron is rendered for now — see the view for why the count is absent —
     * so the chip is sized by its padding rather than by the digit.
     */
    .header.gshell-header .gshell-pill-chip {
        display: flex;
        flex: 0 0 auto;
        align-items: center;
        justify-content: center;
        gap: 4px;

        box-sizing: border-box;
        padding: 4px 8px;

        border-radius: 16px;
        background-color: #e8eaed;

        color: var(--shell-muted);
        font-size: 14px;
        font-weight: 700;
        line-height: 20px;
    }

    .header.gshell-header .gshell-pill-chip img {
        display: block;
        width: 16px;
        height: 16px;
    }

    /* ---------------------------------------------------------------------
     * Account selector — Figma frame "Account selector" (505:371).
     *
     * The panel keeps `.dropdown-content` because that is the element tools.js
     * reveals through `.dropdown.open`, and the open/closed state is opacity and
     * z-index rather than display, so imposing a flex layout here is safe.
     *
     * tools.js also clones `.header-user` into `.navigation-user`, so a second
     * copy of this panel exists in the DOM. Everything below is scoped to
     * `.header.gshell-header`, which leaves that clone on the legacy styling the
     * mobile navigation expects.
     * ------------------------------------------------------------------- */

    .header.gshell-header .gshell-panel {
        box-sizing: border-box;
        display: flex;
        flex-direction: column;
        gap: 24px;

        width: 440px;
        min-height: 0;
        padding: 24px;

        border: 1px solid var(--shell-border);
        border-radius: 16px;
        box-shadow: 0 12px 16px rgba(40, 51, 73, 0.16);
    }

    .header.gshell-header .gshell-account {
        box-sizing: border-box;
        display: flex;
        flex-direction: column;
        gap: 12px;

        width: 100%;
        margin: 0;
        padding: 16px;

        border-radius: 12px;
        background-color: #f3f5f6;
    }

    .header.gshell-header .gshell-account-head {
        display: flex;
        align-items: center;
        gap: 12px;
    }

    .header.gshell-header .gshell-account-check {
        display: block;
        flex: 0 0 auto;
        width: 24px;
        height: 24px;
    }

    .header.gshell-header .gshell-account-name {
        color: var(--shell-text);
        font-size: 20px;
        font-weight: 700;
        line-height: 28px;
    }

    /*
     * The legacy panel spaced its rows with bottom margins: `.profile-fio` and
     * `.profile-address` carry 10px and `.change-payment-pas` 20px
     * (`app.css:1517`, `:1525`, `:1552`). Those classes are kept here as
     * white-label hooks, so their margins ride along and add to the `gap` this
     * layout spaces everything with — measured against the frame, the account name
     * sat 5px above the check icon's centre line (a 10px bottom margin on a
     * centred flex item shifts it by half), the address stood 22px clear of the
     * invite row instead of 12px, and the two password links 28px apart instead of
     * 8px. Zeroed once, here.
     */
    .header.gshell-header .gshell-account-name,
    .header.gshell-header .gshell-account-address,
    .header.gshell-header .gshell-account-actions > div {
        margin: 0;
    }

    /*
     * Every text node in the frame carries a word-break, and these need it: real
     * company names arrive as one unbroken token (`DocDataCompanyInfo.CompanyName`),
     * and a flex item defaults to `min-width: auto`, so without both declarations
     * the name refuses to shrink and overhangs the card by however wide the word is.
     */
    .header.gshell-header .gshell-account-name,
    .header.gshell-header .gshell-account-address,
    .header.gshell-header .gshell-invite-code,
    .header.gshell-header .gshell-client-name {
        min-width: 0;
        overflow-wrap: anywhere;
    }

    .header.gshell-header .gshell-account-address {
        color: var(--shell-muted);
        font-size: 13px;
        font-weight: 400;
        line-height: 20px;
    }

    .header.gshell-header .gshell-account-invite {
        display: flex;
        align-items: center;
        gap: 4px;

        color: var(--shell-text);
        font-size: 14px;
        font-weight: 400;
        line-height: 20px;
    }

    .header.gshell-header .gshell-invite-value {
        display: flex;
        align-items: center;
        gap: 4px;
    }

    /*
     * 500 is the frame's "Medium". The running font resolves to the system sans
     * (`main.css` asks for PT Root UI, which nothing loads — the `@font-face`
     * block lives in the never-included `style.css`), so 500 renders as its
     * regular face and 600 as its bold one. Following the frame is the decision:
     * 600 made every one of these rows read heavier than the design.
     */
    .header.gshell-header .gshell-invite-code {
        font-weight: 500;
    }

    .header.gshell-header .gshell-invite-copy {
        display: flex;
        flex: 0 0 auto;
        align-items: center;
        justify-content: center;

        width: 16px;
        height: 16px;
        padding: 0;

        border: 0;
        background: none;
        cursor: pointer;
    }

    .header.gshell-header .gshell-invite-copy img {
        display: block;
        width: 16px;
        height: 16px;
    }

    /* The frame's hairline above its single "Account settings" entry. Drawn as a
       border rather than the exported 1px image, which carries no information the
       border does not. */
    .header.gshell-header .gshell-account-actions {
        display: flex;
        flex-direction: column;
        gap: 8px;

        padding-top: 12px;
        border-top: 1px solid var(--shell-border);
    }

    .header.gshell-header .gshell-account-actions a {
        color: var(--shell-text);
        font-size: 14px;
        font-weight: 500;
        line-height: 20px;
    }

    .header.gshell-header .gshell-clients {
        display: flex;
        flex-direction: column;
        gap: 8px;
    }

    .header.gshell-header .gshell-clients-label {
        color: var(--shell-muted-light);
        font-size: 14px;
        font-weight: 500;
        line-height: 20px;
    }

    .header.gshell-header .gshell-clients-list {
        display: flex;
        flex-direction: column;
        gap: 16px;
    }

    /* `.rs-link` is the click hook owner-switch.js delegates on, so the class stays
       and only its legacy 30px-tall, 10px-padded geometry is replaced. The element is
       a <button> so the row is keyboard-operable, which also means the UA button
       styling has to be undone here. */
    .header.gshell-header .gshell-clients-list .rs-link {
        display: flex;
        align-items: center;
        gap: 12px;

        width: 100%;
        height: auto;
        padding: 0;
        overflow: visible;

        border: 0;
        background: none;
        font: inherit;
        text-align: left;
        cursor: pointer;

        /* The portal rendering (GBA-4085) uses anchors rather than buttons, because a
           row there has a real URL and should open in a new tab. Both land here. */
        text-decoration: none;

        color: var(--shell-text);
        line-height: 24px;
    }

    /* Links and client rows take the tenant primary on hover, as in the portal. */
    .header.gshell-header .gshell-account-actions a:hover,
    .header.gshell-header .gshell-clients-list .rs-link:hover {
        color: var(--shell-primary-text);
    }

    .header.gshell-header .header-user .btn-user-profile:focus-visible {
        outline: 2px solid var(--shell-primary-text);
        outline-offset: 2px;
    }

    .header.gshell-header .gshell-clients-list .rs-link:focus-visible {
        outline: 2px solid var(--shell-primary-text);
        outline-offset: 2px;
        border-radius: 4px;
    }

    .header.gshell-header .gshell-client-mark {
        display: block;
        flex: 0 0 auto;
        width: 24px;
        height: 24px;
    }

    .header.gshell-header .gshell-client-name {
        font-size: 18px;
        font-weight: 500;
        line-height: 24px;
    }
}

/* =======================================================================
 * Rail — Figma frame "Side menu" (5602:1706).
 *
 * Unlike the header, this section is NOT confined to the desktop half of the
 * 975/976px split. The new view drops `class="menu"`, which is what carried the
 * legacy item geometry (`app.css:115-193`), and that class is not width-scoped —
 * so leaving these rules inside a `min-width: 976px` query would hand the mobile
 * off-canvas drawer a list with no padding, no flex and no pill at all. Only the
 * rail's own width belongs to the desktop branch; everything else applies at
 * every width, exactly as the geometry it replaces did.
 *
 * Scoped to `.gshell-nav`, which exists only when the flag is on, so nothing
 * here can reach `_menu.php`.
 *
 * No `background` and no `!important`: a tenant's `.navigation { … !important }`
 * from `_design.php` is meant to win, and so is its
 * `.navigation .active a, .navigation a:hover { color: … !important }` over the
 * pill's text colour. The pill's own neutral ground is ours.
 * ======================================================================= */

:root {
    /*
     * The rail is 260px in the frame, against the legacy 298px this variable
     * carries. It is read by `.content-section`'s `margin-left` in the 768-975px
     * band (`common-theme.css:265-272`); above 976px the rail is a flex item and
     * the variable does not apply. Overridden here rather than in
     * `redesign/_variables.css` so the flag-off path keeps the legacy number.
     */
    --nav-bar-width: 260px;
}

.navigation.gshell-nav {
    box-sizing: border-box;
}

@media all and (min-width: 976px) {
    /*
     * `flex: 0 0 260px`, not `width` alone. Above 976px `.wrapper-appshell-main`
     * is a flex row and `.content-section` asks for `width: 100%`, so the two
     * over-subscribe the line and the browser shrinks both: the legacy rail
     * declares 290px and renders about 254. Measured here at 228px before the
     * flex basis was pinned.
     */
    .navigation.gshell-nav {
        flex: 0 0 260px;
        width: 260px;
    }
}

.gshell-nav #menu {
    box-sizing: border-box;
    max-width: 260px;
    padding: 40px 24px;
}

.gshell-nav #menu ul {
    margin: 0;
    padding: 0;
}

.gshell-nav #menu li {
    margin: 0;
    list-style: none;
}

/*
 * The pill. `<a>` rather than `<li>` because that is the element the legacy
 * `.active` class lands on and the element a tenant scheme colours.
 *
 * The group toggle (`.dropdown-menu > a`) has no `href` and lands here too; its
 * `cursor: pointer` still comes from the legacy `.dropdown-menu` rule.
 */
.gshell-nav #menu li a {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 12px;

    width: 100%;
    min-height: 40px;
    margin: 0 0 4px 0;
    padding: 10px 24px;

    border-radius: 24px;

    color: var(--shell-text);
    font-size: 14px;
    font-weight: 700;
    line-height: 20px;
    text-decoration: none;
}

/*
 * One neutral pill for hover and for the current page, per the frame, with the
 * label and icon in the tenant primary — the portal rail's state language
 * (GBA-4301). The legacy active marker was a 4px bar drawn by
 * `.menu li.active a:before`; it cannot reach this markup: the selector needs
 * `.menu`, which is gone.
 *
 * Not `!important`: a selector-shaped tenant scheme's
 * `.navigation .active a, .navigation a:hover { color: … !important }` from
 * `_design.php` still wins, as it did before.
 */
.gshell-nav #menu li a:hover,
.gshell-nav #menu li a.active,
.gshell-nav #menu li.active > a {
    background-color: #e8eaed;
    color: var(--shell-primary-text);
}

.gshell-nav #menu li a:focus-visible {
    outline: 2px solid var(--shell-primary-text);
    outline-offset: 2px;
}

.gshell-nav .ico {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    padding: 0;
}

/* Outranks `.ico svg { width: 18px }` (app.css:324) and the 20px the legacy
   rule already gives sub-items, so both levels carry the frame's 20px mark. */
.gshell-nav .ico svg,
.gshell-nav .dropdown-container .ico svg {
    width: 20px;
    height: 20px;
}

/*
 * The two inline currency glyphs — the £ on Local UK payment and the € on
 * European payment — are the only icons here that are filled rather than
 * stroked, so they are the only ones `main.css:1333`
 * (`.ico svg { fill: var(--text-secondary-color) }`) can reach. That variable is
 * a muted grey, and next to the sheet's icons, which are `fill: none` and take
 * their colour from `currentColor`, the two read as disabled.
 *
 * `currentColor` puts them on the same footing: they now follow the pill's text
 * colour like everything else, including a tenant's
 * `.navigation .active a { color: … !important }`. The class is carried in the
 * view rather than matched with `:not(:has(use))` so the selector says plainly
 * which elements it means — and so it cannot accidentally flood a stroked icon
 * with a solid fill.
 *
 * Specificity beats `#menu .active .ico svg` and the hover pair
 * (`main.css:1338-1343`, both 0,3,0) on purpose: those recolour a fill on
 * hover and on the current page, which would have reintroduced the same split
 * in exactly those two states.
 */
.gshell-nav #menu .ico svg.gshell-glyph {
    fill: currentColor;
}

/*
 * Group chevron. Legacy pins it at `right: 42px; top: 12px` against a 36px row;
 * the pill is 40px and ends 24px from the list edge, and the frame draws the
 * chevron at 16px. Positioned with `top` rather than a centring `transform`,
 * because `.dropdown-menu.open .dropdown-menu-icon` (app.css:263) already owns
 * `transform` for the flip.
 *
 * The icon itself moved to the sheet with the rest, so it is stroked now rather
 * than a filled caret; `.dropdown-menu-icon svg { fill: … }` (app.css:259) has
 * nothing left to paint, and `color` is what reaches it.
 */
.gshell-nav .dropdown-menu-icon {
    right: 24px;
    top: 12px;

    color: var(--shell-muted);
}

/* The chevron sits inside the group toggle's pill, so it follows its hover. */
.gshell-nav #menu li a:hover .dropdown-menu-icon {
    color: var(--shell-primary-text);
}

.gshell-nav .dropdown-menu-icon svg {
    display: block;
    width: 16px;
    height: 16px;
}

/*
 * Sub-items. The frame has no nested group, so this follows the top-level pill
 * one step down: the same shape and the same neutral, a regular weight instead
 * of bold, a 36px row, and a 16px indent so the level reads at a glance.
 *
 * The legacy `.dropdown-container ul li { padding-left: 45px }` is moved onto
 * the anchor: the pill has to span the list, so the indent has to be inside it.
 * Both selectors carry `#menu` because the top-level rule above does — without
 * it an id beats three classes and the parent geometry would win here.
 * `font-size` needs `!important` only because `.dropdown-container a`
 * (app.css:318) declares its 13px that way.
 */
.gshell-nav #menu .dropdown-container ul li {
    padding: 0;
}

.gshell-nav #menu .dropdown-container li a {
    min-height: 36px;
    padding: 8px 24px 8px 40px;

    font-size: 14px !important;
    font-weight: 400;
}

/*
 * The legacy group guide, dropped. `.dropdown-container:after` (app.css:297)
 * draws a 1px hairline at `left: 62px`, a number tuned to the old 45px sub-item
 * indent; against this geometry it lands 2px past the sub-icon and 10px short of
 * the label, so it reads as a divider between an item's own icon and its text.
 * The frame draws no guide — the indent and the pill carry the nesting.
 */
.gshell-nav #menu .dropdown-container:after {
    display: none;
}

/* -----------------------------------------------------------------------
 * Group open/close.
 *
 * The legacy accordion does not animate its height. `.dropdown-container`
 * (app.css:285-312) goes from `height: 0` to `height: 100%`, and a percentage
 * height against `.dropdown-block`, which has no height of its own, resolves to
 * `auto` — so the row jumps to its full size on the first frame and everything
 * below is shoved down at once. What the 450ms buys is the `translateY(-100%)`
 * alone: the list then slides down into space the page has already made for it.
 * Measured on the Payments group: height 0 -> 500px within one frame, transform
 * still at -73px 500ms later.
 *
 * Replaced with the grid-row technique, which animates to the content's natural
 * height without anyone having to know it: the block becomes a one-row grid and
 * the row goes `0fr` -> `1fr`, while the container clips. No magic max-height to
 * outgrow — the groups here run from 3 to 11 items — and no JS: `tools.js` still
 * only toggles `.open`.
 *
 * Every selector carries `#menu` because the pill rules above do; without it an
 * id would outrank three classes and the legacy geometry would win back.
 * ------------------------------------------------------------------- */

.gshell-nav #menu .dropdown-block {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 240ms ease;
}

.gshell-nav #menu .dropdown-menu.open .dropdown-block {
    grid-template-rows: 1fr;
}

/*
 * `min-height: 0` is what lets the row actually collapse — a grid item's
 * automatic minimum size is its content, which would pin the row open.
 *
 * `visibility` is the same fix the account panel carries above, for the same
 * reason: clipping a closed group to zero height hides it but leaves its links
 * focusable, so a keyboard user tabbed through up to eleven invisible items
 * before reaching the next section. Measured on the closed Payments group — all
 * ten children sat in the tab order. Delaying it by the length of the collapse
 * keeps the closing animation visible.
 */
.gshell-nav #menu .dropdown-container,
.gshell-nav #menu .dropdown-menu.open .dropdown-container {
    height: auto;
    min-height: 0;
    overflow: hidden;
    transform: none;
}

.gshell-nav #menu .dropdown-container {
    visibility: hidden;
    opacity: 0;
    transition: opacity 180ms ease, visibility 0s linear 240ms;
}

.gshell-nav #menu .dropdown-menu.open .dropdown-container {
    visibility: visible;
    opacity: 1;
    transition: opacity 180ms ease, visibility 0s linear 0s;
}

/* An open group is rendered open on first paint, and a transition never runs on
   an initial style, so this only affects a group the user actually toggles. */
@media (prefers-reduced-motion: reduce) {
    .gshell-nav #menu .dropdown-block,
    .gshell-nav #menu .dropdown-container,
    .gshell-nav #menu .dropdown-menu-icon {
        transition: none;
    }
}
