/*
 * streetix-shell.css — layout of the authenticated shell: top bar, sidebar,
 * page wrapper, footer. Nothing else lives here.
 *
 * Loads after moshtix-theme.css and before app.css (_Layout.cshtml owns the
 * order). This file exists because a sidebar is a layout, not a component —
 * Bootstrap has no equivalent to theme.
 *
 * Ground rules when editing:
 *  - Layout only. A colour, font or component style belongs in
 *    moshtix-theme.css; a page-specific style belongs in app.css.
 *  - No literal colours. Everything visual reads a --mx-* token, so tenants
 *    retheme the shell without ever opening this file.
 *
 * How the shell works: #wrapper is a WRAPPING flex row — the top bar is a
 * 100%-wide item so it takes the first line alone, and the sidebar + content
 * wrap onto the second. The sidebar's width is one variable
 * (--mx-sidebar-current) that the toggle button also reads, so the rail and
 * the button always agree.
 */

/* ---- Layout metrics ---------------------------------------------------- */
/* Tenant-overridable like any other token. */
:root {
  --mx-sidebar-width: 220px;
  /* 0 hides the sidebar entirely when collapsed. A positive value would leave a
     rail, but nothing here hides the labels any more — that went with the
     icon-rail mode. */
  --mx-sidebar-width-collapsed: 0px;
  --mx-sidebar-transition: 0.25s ease;
  --mx-shell-max-width: 80rem;
  --mx-topnav-height: 3.5rem;
  /*  --mx-navigation-dark: ;        ON  (default) — navigation stays dark
                                       whatever the page theme is
      --mx-navigation-dark: initial; OFF           — navigation follows the
                                       page theme like everything else
      The empty value is load-bearing. Do not "tidy" it.
      Covers the sidebar AND the top bar — they are one surface. */
  --mx-navigation-dark: /**/ ;

  /* The sidebar's CURRENT width. One variable drives the rail itself and the
     toggle's offset, so the button tracks the edge instead of needing its own
     copy of the breakpoint rules. Desktop is always expanded. */
  --mx-sidebar-current: var(--mx-sidebar-width);

  /* Navigation palette. Lives at :root rather than on .navbar-static-side so the
     top bar can read the same values — see the Sidebar section for how the
     switch works. */
  --_nav-bg: var(--mx-navigation-dark) var(--mx-neutral-900);
  --_nav-base: var(--mx-navigation-dark) var(--mx-neutral-950);
  --_nav-elevated: var(--mx-navigation-dark) var(--mx-neutral-800);
  --_nav-text: var(--mx-navigation-dark) var(--mx-neutral-300);
  --_nav-text-strong: var(--mx-navigation-dark) var(--mx-neutral-0);
}

/* ---- Shell scaffold ---------------------------------------------------- */

/* #wrapper is `d-flex flex-wrap min-vh-100` in markup. align-content is the
   load-bearing bit: the flex default of `stretch` distributes spare height
   across BOTH lines, which would give the top bar half the viewport. */
#wrapper {
  max-width: var(--mx-shell-max-width);
  margin-inline: auto;
  align-content: flex-start;
}

/* The second line has to fill what the top bar leaves; wrapped flex lines do
   not inherit the container's height the way a single row would. */
.navbar-static-side,
#page-wrapper {
  min-height: calc(100vh - var(--mx-topnav-height));
}

#page-wrapper {
  min-width: 0;  
  flex-basis: 100%;
  background-color: var(--mx-bg-content);
}

@media (min-width: 992px) {
  #page-wrapper {
    flex-basis: 0;
  }
}


/* ---- Top bar ----------------------------------------------------------- */
/* A full-width flex item, so it takes the first line on its own and the
   sidebar wraps beneath it. Same palette as the sidebar: the two read
   as one continuous surface, and one switch darkens both. */
.app-topnav {
  flex: 0 0 100%;
  width: 100%;
  height: var(--mx-topnav-height);
  padding-inline: 1rem;
  background-color: var(--_nav-bg, var(--mx-bg-subtle));
  color: var(--_nav-text, var(--mx-text-secondary));
}

.app-topnav .nav-link {
  color: var(--_nav-text, var(--mx-text-secondary));
}

.app-topnav .nav-link:hover,
.app-topnav .nav-link:focus-visible {
  color: var(--_nav-text-strong, var(--mx-text-primary));
}

/* Sits just past the sidebar's trailing edge and slides with it — same
   variable that sizes the rail, so they animate in step. */
.app-sidebar-toggle {
  margin-inline-start: var(--mx-sidebar-current);
  padding: 0 0.75rem;
  color: var(--_nav-text, var(--mx-text-secondary));
  text-decoration: none;
  transition: margin-inline-start var(--mx-sidebar-transition);
}

.app-sidebar-toggle:hover,
.app-sidebar-toggle:focus-visible {
  color: var(--_nav-text-strong, var(--mx-text-primary));
}

@media (min-width: 80rem) {
    .app-topnav {
        border-top-left-radius: 2rem;
        border-top-right-radius: 2rem;
    }
}

/* Desktop keeps the sidebar permanently expanded, so there is nothing to
   toggle — the control only exists at the sizes where the rail collapses. */
@media (min-width: 992px) {
  .app-sidebar-toggle {
    display: none;
  }
}

/* ---- Sidebar ----------------------------------------------------------- */
/* Colours read as var(--_nav-x, <page token>): when --mx-navigation-dark is
   `initial` the --_nav-* go invalid and every one falls back to the page
   theme. Primitives, not semantic tokens, so forced-dark survives light mode. */
.navbar-static-side {
  flex: 0 0 var(--mx-sidebar-current);
  width: var(--mx-sidebar-current);
  background-color: var(--_nav-bg, var(--mx-bg-subtle));
  transition: flex-basis var(--mx-sidebar-transition),
    width var(--mx-sidebar-transition);
  overflow: hidden;
}

/* Keeps the menu in view on long pages; the sidebar itself scrolls. Offset by
   the top bar, which scrolls away above it. */
.sidebar-collapse {
  position: sticky;
  top: 0;
  max-height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Top-level menu. `.nav.flex-column` in markup supplies the flex column;
   these rules cover the icon rail and active state. */
#side-menu > li > a,
#side-menu .nav-second-level > li > a {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1.25rem;
  color: var(--_nav-text, var(--mx-text-secondary));
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.15s ease, color 0.15s ease;
}

#side-menu > li > a:hover,
#side-menu .nav-second-level > li > a:hover,
#side-menu > li > a:focus-visible {
  /* Tint, not a surface step: when the navigation follows a LIGHT page the
     surface ladder is too compressed for the next step up to register — the
     two computed to the same colour. */
  background-color: var(--_nav-elevated, rgba(var(--mx-text-primary-rgb), 0.08));
  color: var(--_nav-text-strong, var(--mx-text-primary));
}

/* Fixed icon column so labels line up regardless of glyph width. */
#side-menu a > .fa:first-child {
    flex: 0 0 1.25em;
    text-align: center;
    font-size: 1.25rem;
}

/* Section chevron pinned right (was float: right). */
#side-menu .fa.arrow {
  margin-left: auto;
  transition: transform 0.2s ease;
}
#side-menu li.active > a > .fa.arrow {
  transform: rotate(90deg);
}

/* Active item — accent bar plus a tinted fill. */
/* The accent bar deliberately keeps --mx-accent: brand colour is
   mode-invariant, so it reads correctly against a dark rail either way. */
#side-menu > li.active > a {
  color: var(--_nav-text-strong, var(--mx-text-primary));
  background-color: var(--_nav-elevated, var(--mx-surface-default));
  box-shadow: inset 3px 0 0 var(--mx-accent);
}

#side-menu .nav-second-level > li.active > a {
  color: var(--mx-accent);
}

/* ---- Second level ------------------------------------------------------ */
/* No Bootstrap JS on this host — React toggles `.show` directly — so the
   collapse animates via max-height rather than Bootstrap's height transition.
   The cap only needs to exceed the tallest submenu (Admin, 12 items). */
.nav-second-level {
  list-style: none;
  padding-left: 0;
  margin: 0;
  background-color: var(--_nav-base, var(--mx-bg-base));
}

.nav-second-level.collapse {
  display: block;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.25s ease;
}

.nav-second-level.collapse.show {
  max-height: 40rem;
}

.nav-second-level > li > a {
  padding-left: 3.25rem;
  font-size: var(--mx-font-size-body-s);
}

.darkmode-toggle {
  display: var(--mx-darkmode-toggle-display, block);
}

/* ---- Footer ------------------------------------------------------------ */
/* `.mt-auto` in markup pins it to the bottom of the flex column — no more
   absolute positioning and no min-height guessing on #page-wrapper. */
.footer {
  padding: 1rem 1.5rem;
  background-color: var(--mx-bg-subtle);
  border-top: 1px solid var(--mx-border-subtle);
  color: var(--mx-text-secondary);
  font-size: var(--mx-font-size-body-s);
}

/* ---- Small screens ----------------------------------------------------- */
/* Below lg the sidebar collapses to nothing; `.sidebar-open` on <body> (set by
   TopNav) brings it back at full width. `.sidebar-open` is declared INSIDE the
   query so it overrides rather than competes with it.
 *
 * visibility is the load-bearing part. A zero-width sidebar still has its links
 * in the tab order, so keyboard users would tab through an invisible menu —
 * width alone does not hide anything from assistive tech. The delay lets the
 * width finish animating before the contents disappear on close, and removes it
 * on open so they are focusable immediately.
 *
 * Bootstrap's offcanvas would be the richer answer, but it needs Bootstrap JS
 * (not loaded) or a React port — still a follow-up. */
@media (max-width: 991.98px) {
  /* Stays 0 at all times: the drawer is out of flow, so it never reserves
     layout space and the content keeps the full width behind it. */
  :root {
    --mx-sidebar-current: 0px;
  }

  .navbar-static-side {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    z-index: 1045;
    width: var(--mx-sidebar-width);
    /* Slide rather than resize — transform is compositor-only, so it does not
       reflow the page on every frame the way animating width does. */
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform var(--mx-sidebar-transition),
      visibility 0s linear var(--mx-sidebar-transition);
  }

  body.sidebar-open .navbar-static-side {
    transform: none;
    visibility: visible;
    transition: transform var(--mx-sidebar-transition);
  }

  .app-sidebar-toggle {
    position: relative;
    z-index: 1050;
  }

  body.sidebar-open .app-sidebar-toggle {
    margin-inline-start: var(--mx-sidebar-width);
  }

  .sidebar-collapse {
    height: 100%;
  }

  /* Stops the page scrolling behind the open drawer. */
  body.sidebar-open {
    overflow: hidden;
  }

  .app-sidebar-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1040;
    background-color: rgba(0, 0, 0, 0.5);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--mx-sidebar-transition),
      visibility 0s linear var(--mx-sidebar-transition);
  }

  body.sidebar-open .app-sidebar-backdrop {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--mx-sidebar-transition);
  }
}

/* The drawer only exists below lg; above it the sidebar is a normal flex item
   and the backdrop must never render. */
@media (min-width: 992px) {
  .app-sidebar-backdrop {
    display: none;
  }
}

/* ---- Residual utilities Bootstrap 5.3 has no equivalent for ------------ */

/* Bootstrap ships no border-style utilities, so a dashed rule needs this.
   Replaces .hr-line-dashed (25 usages). */
.hr-dashed {
  border: 0;
  border-top: 1px dashed var(--mx-border-default);
  opacity: 1;
  margin: 1.25rem 0;
}
