@import url("shell-chrome.css");

/*
 * App Shell — shared platform & admin navigation chrome.
 *
 * Ports the keyspotUIMockup navigation/layout mechanics into a single,
 * fully CSS-driven shell so PlatformRouter and AdminRouter no longer split
 * their markup between a desktop sidebar and a mobile bottom bar. The SAME
 * menu markup renders as:
 *   - desktop (>= 40rem): a vertical, collapsible sidebar (collapse/expand
 *     driven by `data-collapsed` on `.app-shell`)
 *   - mobile (< 40rem): a fixed, horizontally-scrollable icon bar at the
 *     bottom of the viewport
 *
 * The vertical / horizontal / mobile gradients are the SHARED --shell-gradient-*
 * tokens defined once in shell-chrome.css (imported above), the same ones the
 * Login auth shell (auth-shell.css) uses — so the platform/admin chrome stays
 * visually identical to the login flow with zero duplicated gradient literals.
 */

.app-shell {
    --app-nav-bar-height: 3.5rem;

    /* Mobile-first: symmetric green -> blue -> green. Desktop overrides this to
       the horizontal sweep in the media query below. */
    background: var(--shell-gradient-mobile);

    /* Pin the shell to EXACTLY the viewport and clip it, so `.app-page` is the
       single in-shell scroller. */
    height: 100vh;
    max-height: 100vh;
    overflow: hidden;
    display: grid;
}

/* The shell mounts INSIDE `#root`, and styles.css sets `#root { min-height:
   100svh; display:flex }`. Clamping only `.app-shell` left the ancestor chain
   (html → body → #root) free to scroll, so a document/window scrollbar appeared
   OUTSIDE <body> (the dark bar; html measured 1904x603 while content overflowed).
   Cap the whole chain to the viewport and clip it — but ONLY when a `.app-shell`
   is present (`:has`), so the auth/imprint pages, which render `.auth-page` and
   rely on normal body scroll, are completely unaffected. */
html:has(> body .app-shell),
body:has(.app-shell) {
    height: 100%;
    max-height: 100vh;
    overflow: hidden;
}

#root:has(.app-shell),
#root > .app-shell {
    min-height: 0;
    height: 100vh;
    max-height: 100vh;
    overflow: hidden;
}

/* ----- Mobile-first: fixed bottom icon bar + scrolling content ----- */

.app-shell > .app-nav {
    position: fixed;
    inset-inline: 0;
    inset-block-end: 0;
    block-size: var(--app-nav-bar-height);
    inline-size: 100%;
    z-index: 100;
    background: var(--shell-gradient-mobile);
    display: flex;
    flex-direction: row;
    align-items: stretch;

    /* Mobile: the whole bar is one horizontal scroller, so primary icons AND the
       secondary Imprint/Logout group scroll together (nothing is pinned). The
       submenu cards are position:fixed so they escape this clip and still open
       above the bar. */
    overflow: auto hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.app-shell > .app-nav::-webkit-scrollbar {
    display: none;
}

.app-shell > .app-page {
    margin-block: 1rem var(--app-nav-bar-height);
    inline-size: 100%;
    min-width: 0;
    overflow-y: auto;
    block-size: calc(100vh - var(--app-nav-bar-height) - 1rem);

    /* Warm light-grey canvas (mockup `main`); content panels/cards sit on top in
       white (--greyscale-100). */
    background: var(--greyscale-200);

    /* Rounded panel corners; the shell gradient shows through the top-margin gap
       above the panel — the same inset-panel treatment the Login auth shell
       gives `.auth-content-wrapper` (gradient on top of the content). */
    border-start-start-radius: 1rem;
    border-start-end-radius: 1rem;
}

/* Logo + collapse toggle + section labels are desktop-only chrome. */
.app-nav-logo-link,
.app-nav-toggle-btn,
.app-nav-section-label {
    display: none;
}

.app-nav-list {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 0.5rem;
    margin: 0;
    padding: 0.375rem 0.5rem;
    list-style: none;
    block-size: 100%;

    /* Mobile: lay out at natural width and let the parent `.app-nav` scroll the
       whole bar (icons + secondary) as one unit — so the list itself neither
       stretches to 100% nor owns a separate scrollbar. */
    inline-size: auto;
    flex: 0 0 auto;
    overflow: visible;
}

.app-nav-item {
    list-style: none;
    flex-shrink: 0;
}

.app-nav-link {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;

    /* Mobile: fixed square icon targets. */
    inline-size: 2.75rem;
    block-size: 2.75rem;
    flex-shrink: 0;
    padding: 0.5rem;
    border-radius: 0.5rem;
    color: var(--primary-100);
    fill: var(--primary-100);
    font-family: inherit;
    text-decoration: none;
    border: 2px solid transparent;
    background: transparent;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    z-index: 1;
    transition: color 0.3s ease, fill 0.3s ease, font-weight 0.3s ease;
}

/* Hover/focus fill grows from the edge (mockup: scaleY on mobile). */
.app-nav-link::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(0deg, var(--primary-700), oklch(from var(--primary-700) l c h / 70%));
    border-radius: inherit;
    transform: scaleY(0);
    transform-origin: bottom center;
    transition: transform 0.3s ease-in-out;
    z-index: -1;
}

.app-nav-link:hover {
    color: var(--greyscale-100);
    fill: var(--greyscale-100);
    font-weight: 700;
}

.app-nav-link:hover::before {
    transform: scaleY(1);
}

.app-nav-link:is(:focus, :focus-visible) {
    outline: none;
    border: 2px solid var(--secondary-300);
}

/* Active route (aria-current="page"): white text + green accent, no hover fill. */
.app-nav-link[aria-current="page"] {
    color: var(--greyscale-100);
    fill: var(--greyscale-100);
    font-weight: 700;
    background: linear-gradient(0deg, var(--secondary-300), transparent 6%);
}

.app-nav-link[aria-current="page"]::before {
    display: none;
}

.app-nav-icon {
    inline-size: 1.75rem;
    block-size: 1.75rem;
    min-inline-size: 1.75rem;
    min-block-size: 1.75rem;
    aspect-ratio: 1;
    flex-shrink: 0;
}

.app-nav-text {
    display: none;
    white-space: nowrap;
    font-size: 1rem;
    line-height: 1.4;
}

/* Secondary nav (Imprint / Logout / context switch). Shown on every viewport:
   on the mobile bar the links render as icon-only buttons that scroll inside the
   shared `.app-nav` row (so Imprint and Logout stay reachable on phones and are
   NOT pinned); in the desktop sidebar they become a labelled row pinned to the
   bottom (see the desktop block below). */
.app-nav-secondary {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    padding: 0.375rem 0.5rem;
    flex: 0 0 auto;
}

/* Secondary links. Single base block (one previously split into two equal-
   specificity rules, where the second's primary-700 silently clobbered the
   mobile greyscale-100). Base = MOBILE: icon-button sized + greyscale-100 so the
   labels stay legible on the dark central section of the mobile gradient bar.
   The desktop >=40rem block overrides to auto size + primary-700 for the light
   sidebar. */
.app-nav-secondary-link {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    flex-shrink: 0;
    margin: 0;
    padding: 0.5rem;
    color: var(--greyscale-100);
    fill: var(--greyscale-100);
    font-family: inherit;
    font-size: 0.875rem;
    text-decoration: none;
    border: 2px solid transparent;
    background: transparent;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: color 0.3s ease, fill 0.3s ease;
}

/* Moving underscore on hover (mirrors .auth-imprint-link). */
.app-nav-secondary-link::before {
    content: '';
    position: absolute;
    inset-block-end: 0;
    inset-inline-start: 0;
    inline-size: 100%;
    block-size: 2px;
    border-block-end: 2px solid currentcolor;
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 0.3s ease-in-out;
}

.app-nav-secondary-link:hover::before {
    transform: scaleX(1);
}

.app-nav-secondary-link:is(:focus, :focus-visible) {
    outline: 2px solid var(--secondary-300);
    outline-offset: 2px;
    border-radius: 0.5rem;
}

.app-nav-icon-secondary {
    inline-size: 1.5rem;
    block-size: 1.5rem;
    aspect-ratio: 1;
    flex-shrink: 0;
}

/* The secondary icons reuse the shared icon factories, which hard-code the
   primary `app-nav-icon` (1.75rem) class on the <svg>. This descendant rule
   (specificity 0,2,0) wins over `.app-nav-icon` (0,1,0) so the icon matches the
   1.5rem secondary wrapper instead of overflowing it. */
.app-nav-icon-secondary .app-nav-icon {
    inline-size: 1.5rem;
    block-size: 1.5rem;
    min-inline-size: 1.5rem;
    min-block-size: 1.5rem;
}

.app-nav-text-secondary {
    display: none;
    white-space: nowrap;
    font-size: 1rem;
}

/* ===========================================================
   DESKTOP (>= 40rem): vertical collapsible sidebar
   =========================================================== */
@media (width >= 40rem) {
    .app-shell {
        grid-template-columns: clamp(12rem, 10rem + 8vw, 16rem) 1fr;
        transition: grid-template-columns 150ms linear;

        /* Desktop strip: left-to-right primary-900 -> blue -> green. Without this
           the shell inherits the symmetric MOBILE gradient (green->blue->green),
           which is the "mobile gradient on everything" bug. */
        background: var(--shell-gradient-horizontal);
    }

    .app-shell[data-collapsed="true"] {
        grid-template-columns: 4rem 1fr;
    }

    .app-shell > .app-nav {
        position: relative;
        inset: auto;
        inline-size: auto;
        block-size: 100vh;
        flex-direction: column;
        background: var(--shell-gradient-vertical);

        /* overflow:visible lets the collapse toggle (inset-inline-end: -0.75rem)
           and the floating submenu cards escape the rail to the right. A stacking
           context above the routed content (which has no z-index) keeps both
           painted ON TOP of `main` instead of behind it. The fixed colorPicker
           popup (z-index 200) still wins over this. */
        overflow: visible;
        z-index: 30;
    }

    .app-shell > .app-page {
        margin-block: 1.5rem 0;
        inline-size: auto;
        block-size: calc(100vh - 1.5rem);

        /* Desktop: only the inner (top-left) corner rounds against the sidebar. */
        border-start-end-radius: 0;
    }

    /* Logo shown on desktop. */
    .app-nav-logo-link {
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 1.5rem 1rem;
        flex-shrink: 0;
        cursor: pointer;
        border: 2px solid transparent;
        border-radius: 0.5rem;
    }

    .app-nav-logo-link:is(:focus, :focus-visible) {
        outline: none;
        border: 2px solid var(--secondary-300);
    }

    .app-nav-logo-full {
        display: block;
        inline-size: clamp(8rem, 6rem + 6vw, 12rem);
        height: auto;
    }

    .app-nav-logo-small {
        display: none;
        inline-size: 2.5rem;
        height: auto;
    }

    .app-nav-list {
        flex-direction: column;
        align-items: stretch;
        justify-content: flex-start;
        flex: 1;
        gap: 0.25rem;
        padding-block: 0.75rem;
        padding-inline: 0;

        /* Visible (not auto) so floating submenu cards can escape the rail to the
           right. `overflow-y: auto` would force overflow-x to clip, hiding the
           popup (mockup keeps .nav-list overflow visible on desktop). */
        overflow: visible;
    }

    .app-nav-section-label {
        display: block;
        padding: 0.5rem 1rem;
        font-size: 0.75rem;
        font-weight: 600;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--primary-200);
    }

    .app-nav-link {
        inline-size: calc(100% - 0.5rem);
        block-size: auto;
        justify-content: flex-start;
        padding: 0.625rem 1rem;
        border-radius: 0 0.5rem 0.5rem 0;
    }

    .app-nav-link::before {
        transform: scaleX(0);
        transform-origin: left center;
    }

    .app-nav-link:hover::before {
        transform: scaleX(1);
    }

    .app-nav-link[aria-current="page"] {
        background: linear-gradient(90deg, var(--secondary-300), transparent 6%);
    }

    .app-nav-text {
        display: block;
    }

    .app-nav-secondary {
        display: flex;
        flex-flow: row wrap;
        justify-content: center;
        gap: 0.75rem;
        padding: 0.75rem;
        margin-block-start: auto;
        flex-shrink: 0;
    }

    /* Desktop: secondary links revert to auto-sized labelled rows (undo the
       mobile icon-button sizing) so the Imprint/Logout text fits, and revert to
       primary-700 (the light sidebar uses dark-on-light; the greyscale-100 above
       is mobile-only for the dark gradient bar). */
    .app-nav-secondary-link {
        inline-size: auto;
        block-size: auto;
        color: var(--primary-700);
        fill: var(--primary-700);
    }

    .app-nav-text-secondary {
        display: block;
    }

    /* Collapse toggle button — desktop only. */
    .app-nav-toggle-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        inset-inline-end: -0.75rem;
        inset-block-start: 3.5rem;
        inline-size: 1.5rem;
        block-size: 1.5rem;
        padding: 0;
        z-index: 110;
        background: var(--primary-900);
        color: var(--greyscale-100);
        border: 2px solid transparent;
        border-radius: 0.5rem;
        cursor: pointer;
        font-size: 1rem;
        font-weight: 700;
        line-height: 1;
        transition: color 0.2s ease, border-color 0.2s ease;
    }

    .app-nav-toggle-btn:hover,
    .app-nav-toggle-btn:is(:focus, :focus-visible) {
        outline: none;
        color: var(--secondary-300);
        border-color: var(--secondary-300);
    }

    /* ----- Collapsed state (desktop) ----- */
    .app-shell[data-collapsed="true"] .app-nav-logo-full {
        display: none;
    }

    .app-shell[data-collapsed="true"] .app-nav-logo-small {
        display: block;
    }

    .app-shell[data-collapsed="true"] .app-nav-logo-link {
        padding: 0.75rem 0;
    }

    .app-shell[data-collapsed="true"] .app-nav-text,
    .app-shell[data-collapsed="true"] .app-nav-text-secondary,
    .app-shell[data-collapsed="true"] .app-nav-section-label {
        display: none;
    }

    .app-shell[data-collapsed="true"] .app-nav-link {
        inline-size: 100%;
        justify-content: center;
        padding: 0.625rem;
        border-radius: 0 0.5rem 0.5rem 0;
    }

    .app-shell[data-collapsed="true"] .app-nav-secondary {
        flex-direction: column;
        align-items: center;
        gap: 0.5rem;
    }
}

/* ===========================================================
   Submenu groups (Screening / Extraction / Tender)
   A parent disclosure button + a floating card of sub-items that
   opens on hover, keyboard focus-within, or click (aria-expanded).
   Ports the mockup's .nav-submenu-container / .submenu-card.
   =========================================================== */
.app-nav-submenu {
    position: relative;
}

/* The parent toggle reuses .app-nav-link styling; just normalise button font
   (sizing/width is inherited from .app-nav-link across breakpoints). */
.app-nav-toggle {
    font: inherit;
}

.app-nav-submenu-card {
    display: none;
    flex-direction: row;
    gap: 0.5rem;
    background: var(--greyscale-100);
    border-radius: 0.5rem;
    box-shadow:
        0 10px 20px 0 rgb(0 0 0 / 15%),
        0 3px 6px 0 rgb(0 0 0 / 10%);
    padding: 0.5rem;
    z-index: 99;
}

/* Single source of truth: the card is shown iff the toggle reports expanded.
   Hover, keyboard focus-out, Escape, and click all drive the backing `open`
   Store in Kotlin (see appNavSubmenu / adminNavSubmenu), which flips
   aria-expanded — so there is no CSS :hover rule competing with the click
   state (which previously left click-opened cards stuck open on mouse-out). */
.app-nav-toggle[aria-expanded="true"] ~ .app-nav-submenu-card {
    display: flex;
}

.app-nav-submenu-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    text-align: center;
    min-inline-size: 4.5rem;
    padding: 0.5rem 0.75rem;
    border-radius: 0.5rem;
    color: var(--primary-700);
    fill: var(--primary-700);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease, fill 0.2s ease;
}

.app-nav-submenu-item:hover,
.app-nav-submenu-item:focus-visible {
    background: var(--primary-gradient);
    color: var(--greyscale-100);
    fill: var(--greyscale-100);
    outline: none;
}

.app-nav-submenu-item[aria-current="page"] {
    background: var(--primary-700);
    color: var(--greyscale-100);
    fill: var(--greyscale-100);
}

.app-nav-submenu-item .app-nav-icon {
    inline-size: 1.75rem;
    block-size: 1.75rem;
    min-inline-size: 1.75rem;
    min-block-size: 1.75rem;
}

.app-nav-submenu-item-label {
    font-size: 0.8125rem;
}

/* Mobile: card opens upward from the bottom bar (bottom-to-top), full-width
   flush above the bar — mirrors the mockup's `.submenu-card` mobile rule. */
@media (width < 40rem) {
    .app-nav-submenu-card {
        position: fixed;
        inset-inline: 0;
        inset-block-end: var(--app-nav-bar-height);
        flex-flow: row wrap;
        justify-content: center;
        border-radius: 0.5rem 0.5rem 0 0;
    }
}

/* Desktop: card floats to the right of the rail; chevron on the toggle.
   The card sits a visual 0.5rem off the rail (inset-inline-start: calc(100% +
   0.5rem)). A transparent `::before` bridge fills that 0.5rem gap so the pointer
   never crosses a dead zone — without it, moving from the toggle toward the card
   would briefly hover empty space, fire `mouseleave` on the container, and snap
   the card shut before the pointer arrived. The bridge is part of the card
   (a descendant of the group), so the container's mouseleave never fires while
   travelling button → bridge → card. */
@media (width >= 40rem) {
    .app-nav-submenu-card {
        position: absolute;
        inset-block-start: -0.5rem;
        inset-inline-start: calc(100% + 0.5rem);
        flex-direction: row;
    }

    .app-nav-submenu-card::before {
        content: '';
        position: absolute;
        inset-block: 0;
        inset-inline-start: -0.5rem;
        inline-size: 0.5rem;
        background: transparent;
    }

    .app-nav-toggle::after {
        content: "\203A"; /* › */
        margin-inline-start: auto;
        padding-inline-start: 0.5rem;
        color: var(--primary-200);
        font-weight: 700;
        line-height: 1;
    }

    .app-nav-toggle[aria-expanded="true"]::after {
        color: var(--secondary-300);
    }

    /* No chevron when the rail is collapsed (icon-only). */
    .app-shell[data-collapsed="true"] .app-nav-toggle::after {
        display: none;
    }
}

