/*
   GSales' own sheet. The shared core (gnexus.css) is linked FIRST and owns
   colour, type and the form controls; this file owns only what is particular
   to this app.

   Deliberately small. GNexus.Ui is two stylesheets and no components
   (ADR 0010), and the reason GSales shares the core is a SECURITY argument:
   a person crosses GPass.Auth into this app in one sign-in flow, and a change
   of clothes halfway through reads as a change of site.
*/

.booting {
    padding: 2rem;
    text-align: center;
    color: var(--muted);
}

/* Blazor's own error bar, which the framework UNHIDES when something throws.

   `display: none` here is LOAD-BEARING, not a default. index.html ships the
   element in the markup, so without this rule it is visible from the first
   paint and every page claims something went wrong. That is exactly how it
   behaved on the first browser run of this app — the same shape as the
   Console's reconnect modal, which also has to supply its own hidden state. */
#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    padding: 0.7rem 1rem;
    color: var(--danger);
    background: var(--danger-bg);
    box-shadow: 0 -1px 0 var(--border);
}

#blazor-error-ui .dismiss { float: right; cursor: pointer; }

/* THE SHELL: header, nav, content, footer.

   A FIXED FRAME WITH ONE SCROLLING PANEL, not a tall page. The whole shell is
   exactly the height of the window and does not scroll; `main` and the menu
   each scroll inside it. That is deliberate and it is the difference between
   a web page and an application window:

   - A distribution screen is a GRID — a purchase entry, a 163-row register.
     If the page scrolled as one, the column headings would leave the screen
     and the bar and footer would go with them.
   - The menu is 327 entries. It needs its OWN scrollbar, or reaching the
     bottom of Reports means scrolling the invoice away.

   100dvh, not 100vh: on a phone, `vh` is the height WITHOUT the browser's own
   collapsing address bar, so a 100vh frame is permanently taller than the
   window and the footer sits below the fold — which is exactly the thing a
   footer must not do. */
.shell {
    height: 100dvh;
    display: grid;
    grid-template-rows: auto 1fr auto;
    overflow: hidden;
}

.shell-bar {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .5rem 1rem;
    background: var(--bar);
    color: var(--bar-text);

    /* Above the phone drawer, so sliding the menu out never covers the button
       that closes it again. */
    position: relative;
    z-index: 40;
}

.shell-bar h1 {
    font-size: 1.1rem;
    margin: 0;
}

.bar-brand {
    flex: 1;
}

/* ---- the account control in the bar ------------------------------------ */

.bar-account { position: relative; flex: 0 0 auto; }

/* A round button, because round reads as "a person" and square reads as "a
   command" — which is what every other control in this bar is. */
.avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.1rem;
    height: 2.1rem;
    padding: 0;
    color: var(--bar);
    background: var(--bar-text);
    border: 0;
    border-radius: 50%;
    cursor: pointer;
}

.avatar:hover { background: color-mix(in srgb, var(--bar-text) 85%, var(--bar)); }

.avatar:focus-visible {
    outline: 2px solid var(--bar-text);
    outline-offset: 2px;
}

/* THE MENU ITSELF.

   Two items and nothing else, set TIGHT. The pair used to sit in the nav
   panel inheriting list spacing on top of their own padding, which left a gap
   between them big enough to read as two unrelated things. A menu of two is
   one block: same row height, one hairline between them, no margins. */
.account-menu {
    position: absolute;
    top: calc(100% + .55rem);
    right: 0;
    z-index: 60;
    min-width: 12rem;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 10px 28px rgba(0, 0, 0, .18);
}

.account-menu a,
.account-menu button,
.account-menu .account-name {
    display: flex;
    align-items: center;
    gap: .65rem;
    width: 100%;
    margin: 0;
    padding: .6rem .85rem;
    font: inherit;
    font-size: .9rem;
    text-align: left;
    color: var(--text);
    text-decoration: none;
    background: none;
    border: 0;
    cursor: pointer;
}

.account-menu .account-name { cursor: default; color: var(--muted); }

/* The divider is a BORDER on the second row, not a margin between the two —
   a margin would put the gap back. */
.account-menu button { border-top: 1px solid var(--border); }

.account-menu a:hover,
.account-menu button:hover {
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}

.account-menu .nav-icon { opacity: .7; }

/* The click-away catcher. Invisible — unlike the drawer's scrim, this overlay
   is not meant to dim anything, only to catch the next click. */
.scrim-bare { background: none; z-index: 50; }

.menu-toggle {
    background: none;
    border: 0;
    color: inherit;
    font-size: 1.25rem;
    cursor: pointer;
    padding: .25rem .5rem;
}

/* THE NAV — a real drawer on a phone.

   It SLIDES OVER the page rather than appearing in the flow above it. In the
   flow it pushed `main` down, so opening the menu re-laid-out the screen
   underneath and closing it moved everything back; with a fixed frame it would
   also have squeezed the content into whatever was left. A drawer leaves the
   page exactly where it was.

   `transform`, not `display`, so it animates and so the markup is identical at
   both widths — one list, two shapes (ADR 0010's argument, one level down: a
   second copy for wide screens is how the two quietly stop matching). */
.shell-menu {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 30;
    width: 17rem;
    max-width: 85vw;

    /* The PANEL does not scroll — the tree inside it does (.menu-scroll), so
       Profile and Sign out stay put. Two nested scrollers would give a
       scrollbar on the outer one that moves almost nothing. */
    overflow: hidden;
    background: var(--surface);
    border-right: 1px solid var(--border);
    transform: translateX(-100%);
    transition: transform .18s ease;
}

.shell.menu-open .shell-menu { transform: translateX(0); }

/* Respect a person who has asked the system to stop animating. */
@media (prefers-reduced-motion: reduce) {
    .shell-menu { transition: none; }
}

.scrim {
    position: fixed;
    inset: 0;
    z-index: 20;
    background: rgba(0, 0, 0, .35);
    border: 0;
}

/* THE CONTENT — the one panel that scrolls.

   It owns the page's breathing room, which nothing did before: `main` had no
   padding at all, so every card sat flush against the bar above it and the
   menu beside it. `min-width: 0` is load-bearing in a grid — without it a wide
   table refuses to shrink and pushes the whole frame sideways instead of
   scrolling inside this box. */
main {
    overflow: auto;
    min-width: 0;
    padding: 1.25rem;
}

/* THE FOOTER.

   Always visible, and it carries the two facts that are otherwise unanswerable
   from inside the app: WHICH BUSINESS this window is looking at — somebody
   with two open needs to tell them apart, and the header only has room for the
   person's name — and HOW MANY permissions this session resolved, which is the
   only window there is onto ADR 0028. Permissions no longer travel in the
   token, so "am I seeing the whole menu?" has no other answer a person can
   check for themselves.

   The build is here for the same reason: a tester reporting "the menu closes"
   is reporting it about a particular build. */
.shell-foot {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .35rem 1rem;
    font-size: .75rem;
    color: var(--muted);
    background: var(--surface);
    border-top: 1px solid var(--border);
}

.shell-foot .foot-spacer { flex: 1 1 auto; }

.shell-foot .foot-fact {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    white-space: nowrap;
}

.shell-foot code {
    font-family: var(--mono);
    font-size: .72rem;
}

/* On a phone there is no room for all of it, and the business reference is
   the one that answers a question somebody actually has. */
@media (max-width: 599px) {
    .shell-foot .foot-optional { display: none; }
}

/* The identity facts on the skeleton's home page. */
.facts {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .5rem 1.5rem;
    margin: 1rem 0 0;
}

.facts dt {
    font-weight: 600;
    color: var(--muted);
}

.facts dd {
    margin: 0;
}

.perms {
    margin: 0;
    padding-left: 1.25rem;
}

@media (min-width: 900px) {
    .shell {
        grid-template-columns: 16rem 1fr;
        grid-template-areas:
            "bar  bar"
            "menu main"
            "foot foot";
    }

    .shell-bar  { grid-area: bar; }
    .shell-menu { grid-area: menu; }
    main        { grid-area: main; padding: 1.5rem; }
    .shell-foot { grid-area: foot; }

    /* The drawer becomes a column: everything that made it float is undone
       here, in one place, rather than being conditional above. */
    .shell-menu {
        position: static;
        z-index: auto;
        width: auto;
        max-width: none;
        transform: none;
        transition: none;
        background: none;
    }

    .menu-toggle { display: none; }
}

/* ---- the menu ---------------------------------------------------------- */

/*
   GSales has 328 menu entries across three levels. The visual job is
   different from GHour's nine: there, everything fits and hierarchy is
   decoration; here, hierarchy is the only thing that makes the menu usable
   at all.

   Same tokens and the same shapes as GHour, deliberately (ADR 0010). A
   person crosses GPass.Auth into either app in one sign-in flow, and a
   change of clothes halfway reads as a change of site.
*/

/* THE MENU IS A COLUMN WITH A FIXED FOOT.

   The tree scrolls; the account block below it does not. Before this the whole
   panel scrolled, so expanding a section with nineteen entries pushed Profile
   and Sign out out of sight — and one of those is how somebody leaves. */
.menu {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 1rem;
}

/* `min-height: 0` IS LOAD-BEARING, not a tidy-up.

   A flex item's default `min-height: auto` refuses to shrink below its content,
   so a 327-entry tree makes this box as tall as the tree, `overflow` never has
   anything to clip, and the scrollbar appears on the panel instead — which is
   exactly the behaviour being fixed. Removing this line silently restores the
   bug. */
.menu-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.menu ul { list-style: none; margin: 0; padding: 0; }

.menu-brand {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: .6rem;
    margin: -1rem -1rem .75rem;
    padding: .7rem 1rem;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--bar-text);
    background: var(--bar);
}

/* A destination. */
.menu a,
.menu .linkish {
    display: flex;
    align-items: center;
    gap: .7rem;
    width: 100%;
    padding: .45rem .7rem;
    text-align: left;
    font-size: .9rem;
    color: var(--text);
    text-decoration: none;
    border-radius: 8px;
    background: none;
    border: 0;
    cursor: pointer;
}

.menu a:hover,
.menu .linkish:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }

.menu a.active {
    font-weight: 600;
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, transparent);
}

/* A section heading, which is also the control that opens it.

   A BUTTON, not a link: it goes nowhere. Making it a link would put 45
   destinations in the menu that lead to no page, and a keyboard user would
   tab through every one of them. */
.nav-toggle {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    padding: .45rem .5rem;
    margin-top: .1rem;
    font: inherit;
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    text-align: left;
    color: var(--muted);
    background: none;
    border: 0;
    border-radius: 8px;
    cursor: pointer;
}

.nav-toggle:hover { color: var(--text); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.nav-toggle.open { color: var(--text); }

/* OPEN / CLOSED, as a rotation.

   This was ▸ and ▾ set at .7rem, and at that size the two glyphs are near
   enough identical that the state of a section could not be read at a glance —
   which in a menu whose whole job is hierarchy is the one thing that must be
   legible. It was also at the mercy of whichever font happened to resolve the
   character.

   One shape, turned 90°. The MOVEMENT is what the eye reads, and there is no
   second glyph to keep in step with the first. */
.nav-chevron {
    flex: 0 0 auto;
    transition: transform .15s ease;
    opacity: .75;
}

.nav-toggle.open .nav-chevron { transform: rotate(90deg); opacity: 1; }
.nav-toggle:hover .nav-chevron { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
    .nav-chevron { transition: none; }
}

/* The root icons. `currentColor`, so they follow the heading through hover,
   the accent on the active trail, and dark mode, without a second set of
   rules for any of it. */
.nav-icon {
    flex: 0 0 auto;
    opacity: .8;
}

.nav-toggle:hover .nav-icon,
.nav-toggle.open .nav-icon,
.nav-toggle.here .nav-icon { opacity: 1; }

.nav-label { flex: 1 1 auto; }

/* How many destinations are inside. A section with nineteen entries should
   say so BEFORE it is opened — that is the difference between choosing to
   open it and being surprised by it. */
.nav-count {
    flex: 0 0 auto;
    padding: .05rem .4rem;
    font-size: .7rem;
    font-weight: 500;
    letter-spacing: 0;
    color: var(--muted);
    background: color-mix(in srgb, var(--muted) 14%, transparent);
    border-radius: 999px;
}

/* Depth, shown as indentation AND as a rule down the left, so a section
   inside a section is obvious at a glance rather than by counting pixels. */
.nav-depth-1 > .nav-children,
.nav-depth-2 > .nav-children {
    margin-left: .55rem;
    padding-left: .55rem;
    border-left: 1px solid var(--border);
}

.nav-depth-1 > .nav-toggle { font-size: .78rem; text-transform: none; letter-spacing: 0; }
.nav-depth-2 > .nav-toggle { font-size: .78rem; text-transform: none; letter-spacing: 0; font-weight: 500; }

/* ---- menu corrections -------------------------------------------------- */

/* THE BRAND APPEARS ONCE.

   The bar says "GSales" and so did the menu panel, one centimetre apart. In
   GHour that panel heading earns its place: it is a DRAWER that slides over
   the page on a phone, where the bar is not adjacent to it. At desk width the
   menu is a permanent column directly under the bar, and the word is simply
   there twice.

   So it is kept for the drawer and dropped for the column. */
@media (min-width: 900px) {
    .menu-brand { display: none; }
    .menu { padding-top: .75rem; }
}

/* ZEBRA STRIPING, which needs the destinations to be siblings — NavTree now
   renders one <ul> per level rather than a <ul> around each entry, because
   nth-child counts siblings and a list of one is never even.

   Very low contrast on purpose: this is a menu, and the stripe is there to
   let the eye track along a row in a list of nineteen, not to decorate. */
.nav-list li:nth-child(even) > a {
    background: color-mix(in srgb, var(--text) 4%, transparent);
}

.nav-list li:nth-child(even) > a:hover {
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* WHERE YOU ARE.

   The active entry has to beat the zebra stripe, so it is repeated at the same
   specificity — a stripe declared later would otherwise win on an even row and
   the selection would visibly depend on whether the entry happened to be
   second or third in its section.

   And it is a BAR, not just a tint. In a list of nineteen near-identical labels
   ("Receipt", "Receipt Modify", "Receipt Payment Search") a 14% wash is not
   something the eye finds — the solid edge is. `!important` is not needed
   anywhere here; order and specificity do it. */
.nav-list li > a.active,
.nav-list li:nth-child(even) > a.active {
    position: relative;
    font-weight: 600;
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 16%, transparent);
    box-shadow: inset 3px 0 0 var(--accent);
}

/* THE TRAIL. Every section between the root and the page on screen, marked —
   so when a branch is shut, the path to where you are is still readable. A
   highlight that only exists on the leaf disappears the moment somebody
   collapses the section they are standing in. */
.nav-toggle.here {
    color: var(--accent);
}

.nav-toggle.here > .nav-label { font-weight: 700; }

/* Closed AND holding the current page is the case worth shouting about: the
   entry itself is off screen, so this mark is all there is. */
.nav-toggle.here:not(.open) {
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    box-shadow: inset 3px 0 0 color-mix(in srgb, var(--accent) 55%, transparent);
}

/* PIN / HIDE.

   Desk width only. On a phone the menu is already a drawer that is out of the
   way, and a second control that hides it would do nothing visible. */
.menu-pin { display: none; }

@media (min-width: 900px) {
    .menu-pin {
        display: inline-flex;
        align-items: center;
        margin: 0;
        padding: .3rem .55rem;
        font-size: .9rem;
        line-height: 1;
        color: var(--bar-text);
        background: none;
        border: 1px solid color-mix(in srgb, var(--bar-text) 40%, transparent);
        border-radius: 8px;
        cursor: pointer;
    }

    .menu-pin:hover { background: color-mix(in srgb, var(--bar-text) 14%, transparent); }

    /* One column instead of two, so the page takes the whole window. A
       distribution screen is wide — a purchase entry grid or a 163-row
       register — and 16rem of menu is a real cost once somebody knows where
       they are going. */
    .shell.menu-hidden {
        grid-template-columns: 1fr;
        grid-template-areas: "bar" "main" "foot";
    }

    .shell.menu-hidden .shell-menu { display: none; }
}

