/* ═══════════════════════════════════════════════════════════════════════════
   next-shell.css — makes room for the React app shell
   ═══════════════════════════════════════════════════════════════════════════

   Everything here is gated on `.hsv-shell-next` **on the <html> element**, which
   app/directives/nextShell.js adds synchronously when the user has opted in
   (localStorage `hsv.shellNext`). Without that class this file does nothing at
   all, so a user on the old design gets byte-identical behaviour.

   ON <html>, NOT <body>, and this is not a style preference. The body's class
   attribute is interpolated in index.html:

       class="body-bg full-screen theme-calcBackgroundColor-{{…}} …"

   and Angular's attribute interpolation rewrites the WHOLE attribute via
   attr.$set. A class added imperatively before those theme values resolve is
   wiped by the first digest that fills them in — silently, with the legacy
   chrome reappearing and nothing in any log. <html> carries no bindings.

   WHAT IT DOES
   ------------
   The legacy chrome is absolutely positioned and the content is offset around
   it by hand:

       .header    top: 0;  height: 60px;  width: calc(100% - 140px)
       .right-nav right: 0; top: 0; width: 140px; height: 100%
       .wrapper   padding-top: 60px
       .content   margin-right: 140px

   The React shell replaces the first two with its own fixed chrome at the
   design system's dimensions (--nav-h 64px, --sidebar-w 248px). So all this
   file has to do is hide the two legacy elements and change the two offsets.
   No Angular markup moves; ng-view is untouched.

   WHY !important
   --------------
   Not laziness. The declarations being overridden are re-stated at four
   breakpoints across main.css and mobile.css (140px -> 65px -> 0, 60px -> 40px
   -> 0), all unlayered, several at equal specificity to anything we could write
   without it. Matching each one individually would mean tracking five media
   queries in two files that know nothing about this one. The important flag is
   the honest expression of "the legacy geometry does not apply here".

   KEEP IN STEP WITH
   -----------------
     web/src/shell/app/AppShell.tsx   RAIL_BREAKPOINT and the `lg:` variants
     web/index.html                   the same offsets, for `npm run dev`
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
    /* Same values as --nav-h / --sidebar-w in the design system
       (heshev-design-system/colors_and_type.css). Duplicated rather than
       imported because those tokens live inside the React bundle's stylesheet,
       which is loaded lazily and only for users who opted in — this file has to
       work before it arrives. */
    --hsv-shell-nav-h: 64px;
    --hsv-shell-w: 248px;
}

/* ── Out with the old ─────────────────────────────────────────────────── */

.hsv-shell-next .wrapper > .header,
.hsv-shell-next .wrapper > .right-nav,
/* The mobile drawer, which ng-includes its own copy of right-nav.html. The
   React shell has a drawer of its own below 1024px; two menus with different
   contents is how they drift apart. */
.hsv-shell-next hamburger-nav {
    display: none !important;
}

/* ── In with the new ──────────────────────────────────────────────────── */

.hsv-shell-next .wrapper {
    padding-top: var(--hsv-shell-nav-h) !important;
}

.hsv-shell-next .content {
    margin-right: var(--hsv-shell-w) !important;
}

/* The open-programs tab bar stays legacy, but it spans the full width and would
   otherwise run underneath the rail. */
.hsv-shell-next .footer {
    width: calc(100% - var(--hsv-shell-w)) !important;
}

/* The contextual left panel on /programs sits below the header. */
.hsv-shell-next .left-nav.open {
    top: var(--hsv-shell-nav-h) !important;
}

/* React toasts (web/src/ui/Toast.tsx) sit at the kit's bottom-inline-start
   corner — on top of the navy rail and the navy footer above, where a navy
   toast disappears. Lift it above the 40px footer (main.css `.footer`) with the
   usual 24px gap, and from the rail breakpoint push it past the rail onto the
   content area. The extra `.hsv-next` outranks the bundle's own scoped
   `.hsv-next .bottom-6` / `.start-6` without needing !important. */
.hsv-shell-next .hsv-next .hsv-toast-viewport {
    bottom: 64px;
}

@media (min-width: 1024px) {
    .hsv-shell-next .hsv-next .hsv-toast-viewport {
        inset-inline-start: calc(var(--hsv-shell-w) + 24px);
    }
}

/* Below the rail's breakpoint it becomes a drawer, so the gutter goes away.
   1024px matches RAIL_BREAKPOINT in AppShell.tsx. */
@media (max-width: 1023px) {
    .hsv-shell-next .content {
        margin-right: 0 !important;
    }

    .hsv-shell-next .footer {
        width: 100% !important;
    }
}

/* ── Direction ────────────────────────────────────────────────────────
   The rail NEVER moves, in any language. The React shell host is pinned to
   `dir="rtl"` (see mountShell in web/src/mount.tsx and the note in
   web/src/i18n/types.ts), precisely so the geometry above stays correct for
   the 989 legacy Hebrew screens this chrome wraps.

   A ported SCREEN does follow the locale and goes ltr in English, but that is
   inside `.hsv-next` and changes nothing out here.

   An earlier revision carried an `html.hsv-lang-en` block that moved
   `.content`'s gutter to the other side. It is gone because it could never
   match. If the shell is ever unpinned, it comes back with that change — and
   note it must be physical, not `margin-inline-start`: `.content` inherits
   `direction: ltr` from scss/reset.scss, so a logical property there resolves
   the wrong way round today. */

/* ── The shell's own host element ─────────────────────────────────────── */

/*
   EVERY rule below is gated on `.hsv-shell-next`, and that is load-bearing
   rather than tidy. The host `<div next-shell class="hsv-shell-root">` is in
   index.html unconditionally — the directive returns early for a user who has
   not opted in and simply leaves it there, empty. So any rule keyed on
   `.hsv-shell-root` alone applies to EVERYONE, opted in or not.

   That is not hypothetical. The loading skeleton below was written without the
   gate, and its `::after` — fixed, full height, 248px wide, at the inline-start
   edge — sat invisibly over the right-hand quarter of every page in the legacy
   app, swallowing clicks. Three E2E tests caught it as "checkbox not
   clickable". Do not un-gate anything here.
*/
.hsv-shell-next .hsv-shell-root {
    /*
       `position: relative` + a z-index makes this its own stacking context.
       That is necessary (it is what keeps the fixed header/rail above the
       legacy content), but it also means every z-index used INSIDE the shell —
       including its own popovers, which reach z-50 — is scoped to this local
       context. From outside, the whole shell paints as one flat layer at
       whatever number is below.

       30, not 6: a React screen's sticky table header (DataTable's <thead>,
       z-10) has no positioned ancestor of its own between it and the document
       root, so it sits directly in the ROOT stacking context and compares
       1:1 against this one. At z-index 6 the sticky header — and in fact any
       in-page z-index a screen ever used — painted OVER the entire shell,
       popovers included: opening the notifications popover while scrolled
       down the customers list put the table's sticky header on top of it.

       30 sits strictly between the two ceilings this app actually uses:
         - in-page decoration (sticky headers, and anything similar a future
           screen adds) tops out at z-10 today — 30 clears it with headroom.
         - a real overlay (Dialog, Menu, Tooltip, and the shell's own
           popovers) is z-50 — 30 stays under it, so a screen's confirm
           dialog still correctly covers the header and rail, the way a modal
           should. Do not raise this to 50 or above; that would put ordinary
           chrome ahead of an actual modal.

       Still far below Bootstrap's legacy modal layer (1040+), so a legacy
       dialog also covers the chrome as it always has.
    */
    position: relative;
    z-index: 30;
}

/*
   The shell host must occupy NO space. Every one of its children is
   position: fixed, so it is an anchor for a stacking context and nothing else,
   and it sits in normal flow immediately before `.wrapper`.

   mount() adds `.hsv-next` to it, and the bundle's own armor.css says
   `.hsv-next { height: 100%; overflow: auto }` — correct for a SCREEN, which is
   mounted into a fixed-height box inside ng-view and has to scroll internally.
   Applied here it would make this div a full-viewport, page-coloured, scrolling
   block that pushes the entire legacy app down off screen. The base layer also
   paints a background on it.

   !important because the bundle's stylesheet is injected at runtime, after every
   legacy <link>, so it wins ties on source order at equal specificity.
*/
.hsv-shell-next .hsv-shell-root.hsv-next {
    height: 0 !important;
    overflow: visible !important;
    background: none !important;
}

/* Login, signup, order, purchase — fullPageDetect.js puts `full-screen` on the
   body and scss/reset.scss hides all chrome. Hide ours the same way, and drop
   the offsets with it: those pages lay themselves out edge to edge.

   This is belt and braces. AppShell.tsx also renders nothing when it sees the
   class — but the CSS applies before the bundle has even been requested. */
.hsv-shell-next body.full-screen .hsv-shell-root {
    display: none !important;
}

.hsv-shell-next body.full-screen .wrapper {
    padding-top: 0 !important;
}

.hsv-shell-next body.full-screen .content {
    margin-right: 0 !important;
}

/* ── Loading skeleton ─────────────────────────────────────────────────── */

/* The legacy chrome is hidden the moment the class lands, but the React bundle
   is an async import and takes a moment. `:empty` matches only until React
   renders its first child, so these vanish on their own with no JS involved.

   The `.hsv-shell-next` gate is what makes `:empty` mean "the bundle has not
   arrived yet" rather than "this user never opted in" — see the note above.

   Colours are the design system's --bg-elevated, --border and --brand-navy,
   written literally because tokens.css is inside the bundle we are waiting for. */
.hsv-shell-next .hsv-shell-root:empty::before {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--hsv-shell-nav-h);
    background-color: #ffffff;
    border-bottom: 1px solid #e4e6f0;
}

@media (min-width: 1024px) {
    .hsv-shell-next .hsv-shell-root:empty::after {
        content: '';
        position: fixed;
        top: var(--hsv-shell-nav-h);
        bottom: 0;
        right: 0;
        width: var(--hsv-shell-w);
        background-color: #2d2d87;
    }
}

/*
   ═══ THE HELP RAIL — for EVERY user, not just the opted-in ones ═══

   The teal support / training / remote-access rail on the left edge
   (web/src/shell/help/HelpRail.tsx) replaced the legacy <composer>. It renders
   from the same React root as the shell, and nextShell.js mounts that root for
   everyone — the top strip and side nav only when the user opted in. So the
   rules below are deliberately NOT gated on `.hsv-shell-next`.

   They are still safe for the reason the warning at the top of the gated block
   gives: each one keys on `.hsv-next` or `.hsv-help-rail`, and both exist only
   once the bundle has mounted. An empty host matches none of them.
*/

/* The host occupies no space, opted in or not — same reasoning as the gated
   rule above: armor.css gives `.hsv-next` a full height, a scroll and a
   background, which on a page-level host would push the legacy app down. */
.hsv-shell-root.hsv-next {
    height: 0 !important;
    overflow: visible !important;
    background: none !important;
}

/* Everywhere the legacy composer was hidden, the rail is too. !important
   because the bundle's stylesheet is injected after every legacy <link>. */
body.full-screen .hsv-help-rail,
body.ai-chat-running .hsv-help-rail,
body.customers-add-page .hsv-help-rail,
body.italogin-page .hsv-help-rail,
body.ita-page .hsv-help-rail {
    display: none !important;
}

@media (max-width: 736px) {
    .hsv-help-rail {
        display: none !important;
    }
}
