/* Layouts/PxNavDrawerLayout - the shared page chrome's stylesheet.

   A head <link> (anvil.yaml, native_deps.head_html), which is what styles the designer canvas as
   well as the page, and which is also why the scoping below is written out rather
   than assumed.

   SCOPING. Every rule whose subject is a DESCENDANT of the layout root is wrapped
   `:where(.px-nav-layout)`, which adds zero specificity and so cannot change which
   rule wins. Three are deliberately left bare:

     * `.px-nav-layout` itself - it is the root rule.
     * `.px-nav-layout *, ...::before, ...::after` - it already names the root as
       the ancestor. Rewritten as `:where(.px-nav-layout) *` it would fall from
       (0,1,0) to (0,0,0) and lose ties it wins today.
     * `.px-nav-layout.px-modal-open .px-nav-content` - its subject chain STARTS at
       the root, so a `:where()` wrap would never match. px-management-app reads
       this rule verbatim (tests/test_gp_drill_modal_viewport_anchored.py).

   ORDER WAS CHECKED, NOT ASSUMED. A head link loads before every runtime-injected
   sheet, so these rules lose any document-order tie against
   px_theme.ensure_theme_injected(), pxmar_bridge.ensure_injected() and any host
   sheet. Nothing collides: no `.px-nav-*` selector is declared in
   _px_theme_css.py, in _pxmar_core_js.py, or in any host theme asset, except
   px-management-app's pharmacyflow_pivot.css takeover block, which is
   `!important` and wins either way.

   THE SLOT-HOST RULE IS GONE, not moved. `.px-nav-layout div[anvil-slot] {
   display: contents; }` existed only to make a plain <div anvil-slot> behave like
   the <anvil-dropzone> the modern carry emits, and the modern carry is what this
   layout ships now: the runtime's own CSS makes a dropzone `display: contents`.

   THE COLOUR LAW (hard, same bar as px_ui/nav_shell_html). Not one colour literal
   and not one stand-in colour behind a token: every colour is a bare --px-* token,
   stated on its own. A missing token must show up as a visibly unpainted surface,
   never as a plausible wrong colour that hides a broken theme injection. Lengths,
   times and z-indexes are ordinary literals and are fine.

   980px IS SPELLED TWICE, here and as PX_NAV_BREAKPOINT_PX in
   theme/assets/px_shared/layouts/layouts.mjs. One number, two files: a media query
   cannot be read from JavaScript without matchMedia, and the module's docked test
   predates this carry. Change one, change the other. */

.px-nav-layout {
  font-family: var(--px-font);
  color: var(--px-text-primary);
  background: var(--px-bg-deep);
}

.px-nav-layout *,
.px-nav-layout *::before,
.px-nav-layout *::after { box-sizing: border-box; }

/* ------------------------------------------------------ top bar ---- */
/* Mobile only: at 980px and up the drawer is always on screen, so
   there is nothing for a menu button to reveal. */
:where(.px-nav-layout) .px-nav-topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 56px;
  padding: 0 8px;
  background: var(--px-bg-card);
  border-bottom: 1px solid var(--px-border);
}

:where(.px-nav-layout) .px-nav-menu-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--px-radius-sm);
  background: none;
  color: var(--px-text-primary);
  cursor: pointer;
}

:where(.px-nav-layout) .px-nav-menu-button:hover { background: var(--px-bg-elevated); }

:where(.px-nav-layout) .px-nav-menu-button svg { width: 24px; height: 24px; display: block; }

/* -------------------------------------------------------- scrim ---- */
/* The dimming layer behind an open mobile drawer. Present in the DOM
   at all times so the drawer's own open class is the single piece of
   state; it is simply not displayed while the drawer is closed. */
:where(.px-nav-layout) .px-nav-scrim {
  display: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 30;
  background: var(--px-backdrop);
}

/* One piece of state, not two: the dimming layer follows the drawer's
   own open marker through a sibling rule, so nothing can leave a lit
   scrim over a closed drawer. */
:where(.px-nav-layout) .px-nav-drawer.px-nav-drawer-open ~ .px-nav-scrim { display: block; }

/* ------------------------------------------------------- drawer ---- */
/* ALWAYS fixed, at every width — closed on mobile it is parked off
   screen rather than removed, which is what the shared shell's
   scroll lock was written against. */
:where(.px-nav-layout) .px-nav-drawer {
  position: fixed;
  top: 0;
  bottom: 0;
  left: -101%;
  z-index: 40;
  width: 280px;
  overflow: hidden;
  background: var(--px-bg-card);
  border-right: 1px solid var(--px-border);
  box-shadow: var(--px-shadow-lg);
  transition: left .25s ease;
}

:where(.px-nav-layout) .px-nav-drawer.px-nav-drawer-open { left: 0; }

/* ------------------------------------------------------ content ---- */
/* padding 8px top and bottom, none at the sides: the page padding. This
   layout bakes it, so the host does not state it. */
:where(.px-nav-layout) .px-nav-content {
  height: 100dvh;
  /* The content area is the scroll port, and it has to be: this box
     is a FIXED 100dvh, so without a scroll of its own anything taller
     than the viewport is simply unreachable. Screens that set
     `overflow: auto` on their own root scrolled themselves and hid
     that — the ones that do not (the active-care-home tracker, portal
     engagement, branding) could not scroll at all. Owner, 07/08:
     "cant scroll on active care home tracker screen at all... same
     for portal engagement".

     `height` and not `min-height`, and the reason is the scroll
     itself: a box only becomes a scroll port when its height is
     DEFINITE. Give this `min-height` and it grows to fit whatever
     screen is in it and never scrolls at all — which is the bug,
     back again by another route.

     It is NOT, as this comment first claimed, so that percentage
     heights inside a screen resolve against this box. They do not:
     Anvil's own auto-height anvil-html-templated-panel wrapper sits
     between this box and the screen, so a percentage height in a
     screen resolves to auto regardless. Branding is the proof — its
     .pxbrand-shell sets height:100% and still could not fill or
     scroll. */
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 8px 0;
  margin-left: 0;
  background: var(--px-bg-deep);
  color: var(--px-text-primary);
}

/* ------------------------------------------- modal scroll lock ---- */
/* The shared modal JS marks every host shell root with
   `px-modal-open` while a dialog is open, and each shell says what
   its OWN scroll port does about it — px-internal-app states this
   over `.root-layout` in its Main layout. Here the port is
   `.px-nav-content`, so without this rule the page kept scrolling
   behind an open dialog in every app on this layout.

   `hidden` and not `auto`-removed: the box stays a scroll container,
   so its scroll position survives the dialog and the reader comes
   back to where they were. */
.px-nav-layout.px-modal-open .px-nav-content { overflow-y: hidden; }

/* ------------------------------------------- 980px and upwards ----- */
@media (min-width: 980px) {
  :where(.px-nav-layout) .px-nav-topbar { display: none; }
  :where(.px-nav-layout) .px-nav-scrim,
  :where(.px-nav-layout) .px-nav-drawer.px-nav-drawer-open ~ .px-nav-scrim { display: none; }
  :where(.px-nav-layout) .px-nav-drawer { left: 0; }
  :where(.px-nav-layout) .px-nav-content { margin-left: 280px; }
}
