    /* PORTAL LAYOUT — mobile first */
    .portal {
        display: none;
        min-height: 100vh;
    }

    .portal.active {
        display: block;
    }

    .sidebar {
        display: none;
    }

    .topbar {
        background: var(--surface);
        border-bottom: 0.5px solid var(--border);
        padding: 0 1rem;
        height: 48px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        z-index: 10;
    }

    .topbar-title {
        font-size: 14px;
        font-weight: 500;
    }

    .topbar-right {
        display: flex;
        align-items: center;
        gap: 8px;
    }

    .avatar {
        width: 26px;
        height: 26px;
        border-radius: 50%;
        background: #B5D4F4;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 10px;
        font-weight: 500;
        color: #0C447C;
    }

    .staff-name {
        font-size: 11px;
        color: var(--muted);
    }

    .logout-btn {
        font-size: 11px;
        color: var(--danger);
        cursor: pointer;
        padding: 3px 8px;
        border: 0.5px solid var(--danger);
        border-radius: 6px;
        background: none;
    }

    .portal-main {
        padding-top: 48px;
        padding-bottom: var(--nav-h);
        overflow-x: hidden;
        /* #portal is unconditionally display:flex (set inline in showPortal(), portal-utils.js) at every
           viewport size. On mobile .sidebar is display:none, leaving .portal-main as the sole flex item in
           that row — without flex-grow it shrink-wraps to its own content's intrinsic width instead of
           filling the row. Pages with a wide data table happened to mask this (the table's own intrinsic
           width was wide enough to fill the space anyway); compact card-based layouts (e.g. Stock Check)
           exposed it. flex:1 + min-width:0 forces it to always fill the remaining row width. */
        flex: 1;
        min-width: 0;
    }

    .content {
        padding: 1rem;
        width: 100%;
    }

    /* BOTTOM NAV */
    .bottom-nav {
        background: var(--surface);
        border-top: 0.5px solid var(--border);
        display: flex;
        height: var(--nav-h);
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 10;
    }

    .nav-btn {
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        cursor: pointer;
        font-size: 10px;
        color: var(--muted);
        border: none;
        background: none;
        padding: 6px 2px;
        transition: color 0.15s;
    }

        .nav-btn.active {
            color: var(--accent);
            font-weight: 600;
        }

    .nav-icon-wrap {
        width: 40px;
        height: 26px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 10px;
        transition: background 0.15s;
    }

    .nav-btn.active .nav-icon-wrap {
        background: var(--accent-bg);
    }

    .nav-icon {
        font-size: 18px;
        line-height: 1;
    }

    /* MORE NAV OVERLAY */
    #more-nav-overlay {
        position: fixed;
        inset: 0;
        background: rgba(0,0,0,0.3);
        z-index: 14;
    }

    /* MORE NAV SHEET — max-height/scroll matters at this page count: ~30 flat rows at ~52px each is
       ~1500px, taller than the viewport, so without this the top items were literally unreachable
       (off-screen above the fixed-position sheet, no way to scroll up to them). */
    #more-nav-sheet {
        position: fixed;
        bottom: var(--nav-h);
        left: 0;
        right: 0;
        max-height: 75vh;
        overflow-y: auto;
        background: var(--surface);
        border-top: 0.5px solid var(--border);
        border-radius: 14px 14px 0 0;
        box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
        z-index: 15;
    }

    /* MORE NAV — collapsible groups, same grouping as the desktop sidebar's .sb-group (mirrors
       SECTION_GROUP in portal-utils.js) so the two stay conceptually in sync. Closed by default;
       mnToggleGroup() toggles .mn-open. A group with every child nav-btn hidden (menu-group permission)
       is itself hidden by mnSyncGroups(), same idea as syncSidebarGroups() on desktop. */
    .mn-group-label {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 12px 20px 8px;
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.5px;
        text-transform: uppercase;
        color: var(--muted);
        opacity: 0.7;
        cursor: pointer;
    }
    .mn-chevron {
        font-size: 11px;
        transition: transform 0.15s ease;
    }
    .mn-group.mn-open .mn-chevron { transform: rotate(0deg); }
    .mn-group:not(.mn-open) .mn-chevron { transform: rotate(-90deg); }
    .mn-group-items { display: none; }
    .mn-group.mn-open .mn-group-items { display: block; }
    .mn-standalone {
        border-top: 0.5px solid var(--border);
        margin-top: 6px;
        padding-top: 2px;
    }

    #more-nav-sheet .nav-btn {
        flex-direction: row;
        justify-content: flex-start;
        flex: none;
        width: 100%;
        padding: 14px 20px;
        font-size: 13px;
        gap: 14px;
        border-bottom: 0.5px solid var(--border);
        border-radius: 0;
        font-weight: 400;
    }

    #more-nav-sheet .nav-btn.active {
        font-weight: 600;
    }

    #more-nav-sheet .nav-btn .nav-icon-wrap {
        width: 32px;
        height: 32px;
        border-radius: 8px;
        flex-shrink: 0;
    }

    #more-nav-sheet .nav-btn .nav-icon {
        font-size: 16px;
    }

    /* SECTIONS */
    .section {
        display: none;
    }

        .section.active {
            display: block;
        }

    /* DESKTOP — sidebar layout */
    @media (min-width: 768px) {
        .bottom-nav {
            display: none;
        }

        .portal.active .sidebar {
            display: flex;
            flex-direction: column;
            width: var(--sidebar-w);
            background: var(--surface);
            border-right: 0.5px solid var(--border);
            position: fixed;
            top: 0;
            bottom: 0;
            left: 0;
            z-index: 20;
            transition: width 0.2s ease;
            overflow: hidden;
        }

        .portal.active .sidebar.collapsed {
            width: 52px;
        }

        .sidebar-logo {
            padding: 1rem 1.25rem;
            border-bottom: 0.5px solid var(--border);
            display: flex;
            align-items: center;
            justify-content: space-between;
            min-height: 60px;
            flex-shrink: 0;
        }

        .sidebar-logo-text {
            overflow: hidden;
            white-space: nowrap;
            transition: opacity 0.15s ease, width 0.2s ease;
        }

        .sidebar.collapsed .sidebar-logo-text {
            opacity: 0;
            width: 0;
        }

        .sidebar-logo-name {
            font-size: 15px;
            font-weight: 500;
        }

        .sidebar-logo-sub {
            font-size: 12px;
            color: var(--muted);
            margin-top: 2px;
        }

        .sidebar-toggle-btn {
            flex-shrink: 0;
            width: 26px;
            height: 26px;
            border-radius: 6px;
            border: 0.5px solid var(--border);
            background: var(--bg);
            color: var(--muted);
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 13px;
            line-height: 1;
            transition: background 0.15s;
        }
        .sidebar-toggle-btn:hover { background: var(--border); color: var(--text); }

        .sb-group-label {
            padding: 14px 1.25rem 4px;
            font-size: 10px;
            font-weight: 700;
            letter-spacing: 0.7px;
            text-transform: uppercase;
            color: var(--muted);
            opacity: 0.6;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .sidebar.collapsed .sb-group-label { opacity: 0; height: 6px; padding: 0; overflow: hidden; }

        .sb-chevron {
            font-size: 11px;
            transition: transform 0.15s ease;
        }

        /* Sub-divider inside a .sb-group-items list — e.g. CFM's "Sequencing" heading above its 4
           sequencing pages. Clusters pages that share a page-level category label within one already-
           permitted group; unlike .sb-group-label this isn't a real permission-group boundary, but it
           does get its own independent collapse (see .sb-subgroup below) so opening the parent CFM group
           for an unrelated page (e.g. Sales Overview) doesn't also dump Sequencing's 4 pages into view. */
        .sb-subgroup-label {
            padding: 10px 1.25rem 2px;
            font-size: 10px;
            font-weight: 700;
            letter-spacing: 0.7px;
            text-transform: uppercase;
            color: var(--muted);
            opacity: 0.6;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .sidebar.collapsed .sb-subgroup-label { display: none; }
        .sb-group.group-open .sb-chevron { transform: rotate(0deg); }
        .sb-group:not(.group-open) .sb-chevron { transform: rotate(-90deg); }
        .sb-subgroup.subgroup-open .sb-subgroup-label .sb-chevron { transform: rotate(0deg); }
        .sb-subgroup:not(.subgroup-open) .sb-subgroup-label .sb-chevron { transform: rotate(-90deg); }

        /* Per-group collapse — closed by default; showSection() opens whichever group holds the
           current page. Ignored entirely when the whole sidebar is in icon-only collapsed mode, since
           there's no room for group labels there and every icon must stay reachable. */
        .sb-group-items { display: none; }
        .sb-group.group-open .sb-group-items { display: block; }
        .sidebar.collapsed .sb-group-items { display: block; }

        /* Same collapse mechanism as .sb-group-items, one level deeper for a .sb-subgroup like
           Sequencing — closed by default; showSection() opens it only when the current page is actually
           one of its own pages (see SECTION_SUBGROUP/sbEnsureSubgroupOpen in portal-utils.js). */
        .sb-subgroup-items { display: none; }
        .sb-subgroup.subgroup-open .sb-subgroup-items { display: block; }
        .sidebar.collapsed .sb-subgroup-items { display: block; }

        .sidebar-nav-btn {
            display: flex;
            align-items: center;
            gap: 9px;
            padding: 11px 1.25rem;
            font-size: 14px;
            color: var(--muted);
            cursor: pointer;
            border: none;
            border-left: 2px solid transparent;
            background: none;
            width: 100%;
            text-align: left;
            white-space: nowrap;
            overflow: hidden;
        }

            .sidebar-nav-btn:hover {
                background: var(--bg);
                color: var(--text);
            }

            .sidebar-nav-btn.active {
                color: var(--accent);
                border-left: 2px solid var(--accent);
                background: var(--accent-bg);
                font-weight: 500;
            }

        .sb-icon { flex-shrink: 0; font-size: 16px; line-height: 1; }

        .sb-label {
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
            transition: opacity 0.15s ease, max-width 0.2s ease;
            max-width: 200px;
        }

        .sidebar.collapsed .sb-label {
            opacity: 0;
            max-width: 0;
        }

        .sidebar-footer {
            margin-top: auto;
            padding: 1rem 1.25rem;
            border-top: 0.5px solid var(--border);
            display: flex;
            align-items: center;
            gap: 8px;
            overflow: hidden;
            white-space: nowrap;
        }

        .sidebar-footer-text {
            overflow: hidden;
            transition: opacity 0.15s ease, max-width 0.2s ease;
            max-width: 160px;
            white-space: nowrap;
        }

        .sidebar.collapsed .sidebar-footer-text {
            opacity: 0;
            max-width: 0;
        }

        .topbar {
            left: var(--sidebar-w);
            right: 0;
            transition: left 0.2s ease;
        }

        .topbar.sb-collapsed {
            left: 52px;
        }

        /* .portal-main is the sole scroll container once it goes position:fixed below — html's own
           scrollbar (portal-base.css, reserved for the mobile flow layout) becomes a second, redundant
           scrollbar here, and CSS zoom scaling can visibly separate the two instead of them sitting flush. */
        html {
            overflow-y: hidden;
        }

        .portal-main {
            position: fixed;
            top: 48px;
            left: var(--sidebar-w);
            right: 0;
            bottom: 0;
            overflow-y: scroll;
            overflow-x: hidden;
            transition: left 0.2s ease;
        }

        .portal-main.sb-collapsed {
            left: 52px;
        }

        .content {
            padding: 1.25rem;
            width: 100%;
        }

        .card-fields {
            grid-template-columns: 1fr 1fr 1fr;
        }
    }

    @media (min-width: 1200px) {
        .content {
            padding: 1.5rem 2rem;
        }

        .card-fields {
            grid-template-columns: repeat(4, 1fr);
        }
    }

    /* PRINT — price list only */
    @media print {
        body > * { display: none !important; }
        #pl-printable { display: block !important; position: fixed; top: 0; left: 0; width: 100%; }
    }
    #pl-printable { display: none; }

    .dash-period {
        font-size: 12px;
        padding: 6px 14px;
        border: 0.5px solid var(--border);
        border-radius: 8px;
        background: var(--surface);
        color: var(--muted);
        cursor: pointer;
    }

    .dash-period.active {
            background: #185FA5;
            color: white;
            border-color: #185FA5;
    }

    .dash-grid-2 {
        display: grid;
        grid-template-columns: 1fr;
    }

    .dash-grid-3 {
        display: grid;
        grid-template-columns: 1fr;
    }

    @media (min-width:768px) {
        .dash-grid-2 {
            grid-template-columns: 1fr 1fr;
        }

        .dash-grid-3 {
            grid-template-columns: 1fr 1fr 1fr;
        }
    }

    #ba-summary { grid-template-columns: repeat(2, 1fr); }

    @media (min-width: 768px) {
        #ba-summary { grid-template-columns: repeat(4, 1fr); }
    }

    @media (max-width: 400px) {
        #ba-summary { grid-template-columns: 1fr; }
    }
