/* ==========================================================================
   meridian — app shell
   Sidebar, topbar, content column, mobile pill nav.

   Layout model (mirrors the platform's existing dashboard behaviour):
     · desktop  — fixed sidebar, open by default, pushes the content column
     · mobile   — sidebar slides over a scrim, closed by default
   The shell is a fixed viewport; only .lx-content scrolls.
   ========================================================================== */

.lx-shell { position: relative; z-index: var(--lx-z-content); }

/* ══ SIDEBAR ═══════════════════════════════════════════════════════════════ */

.lx-sidebar {
  position: fixed;
  top: 0; left: 0;
  z-index: var(--lx-z-sidebar);
  display: flex;
  flex-direction: column;
  width: var(--lx-sidebar-w);
  height: var(--real-vh, 100vh);
  padding: var(--lx-s-4) var(--lx-s-3);
  border-right: 1px solid var(--lx-glass-border);
  border-radius: 0;
  background: var(--lx-glass);
  -webkit-backdrop-filter: var(--lx-glass-blur);
  backdrop-filter: var(--lx-glass-blur);
  box-shadow: var(--lx-glass-inset);
  transform: translateX(-100%);
  transition: transform var(--lx-t-slow) var(--lx-ease-out);
}
.lx-sidebar.is-open { transform: none; }

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lx-sidebar { background: var(--lx-bg-solid); }
}

.lx-sidebar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--lx-s-2);
  height: calc(var(--lx-topbar-h) - var(--lx-s-4));
  padding: 0 var(--lx-s-3);
  margin-bottom: var(--lx-s-4);
}

.lx-sidebar__brand {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  justify-content: center;
  gap: var(--lx-s-3);
  font-size: var(--lx-fs-sm);
  color: var(--lx-t1);
}
.lx-sidebar__brand:hover { text-decoration: none; }

/* The wordmark, tracked wide — the reference's title treatment */
.lx-sidebar__mark {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  background: linear-gradient(135deg, var(--lx-accent), color-mix(in srgb, var(--lx-accent) 55%, white));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.lx-sidebar__nav {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: var(--lx-s-1);
  padding-bottom: var(--lx-s-4);
}

.lx-nav-group + .lx-nav-group { margin-top: var(--lx-s-5); }

.lx-nav-group__label {
  display: block;
  padding: 0 var(--lx-s-3) var(--lx-s-2);
  font-family: var(--lx-f-mono);
  font-size: var(--lx-fs-micro);
  font-weight: 500;
  letter-spacing: var(--lx-ls-label);
  text-transform: uppercase;
  color: var(--lx-t4);
}

.lx-nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--lx-s-3);
  height: 42px;
  padding: 0 var(--lx-s-3);
  border-radius: var(--lx-r-md);
  font-size: var(--lx-fs-sm);
  font-weight: 600;
  color: var(--lx-t1);
  transition:
    background var(--lx-t-fast) var(--lx-ease),
    color var(--lx-t-fast) var(--lx-ease);
}
.lx-nav-item:hover { background: var(--lx-fill); color: var(--lx-t1); text-decoration: none; }
.lx-nav-item .lx-icon { color: var(--lx-t3); transition: color var(--lx-t-fast) var(--lx-ease); }
.lx-nav-item:hover .lx-icon { color: var(--lx-t1); }

.lx-nav-item.is-active {
  background: var(--lx-glass-strong);
  color: var(--lx-t1);
  font-weight: 700;
  box-shadow: var(--lx-glass-inset);
}
.lx-nav-item.is-active .lx-icon { color: var(--lx-accent); }

/* Active marker — a short bar on the leading edge, not a full-height rule */
.lx-nav-item.is-active::before {
  content: "";
  position: absolute;
  left: calc(var(--lx-s-3) * -1);
  top: 50%;
  width: 3px;
  height: 18px;
  border-radius: var(--lx-r-full);
  background: var(--lx-accent);
  transform: translateY(-50%);
}

.lx-nav-item__meta { margin-left: auto; }

.lx-nav-item.is-soon { color: var(--lx-t4); }
.lx-nav-item.is-soon .lx-icon { color: var(--lx-t4); }

/* ══ NAV: pin/favourite, collapse, badges ═════════════════════════════════ */

.lx-nav-item-row { display: flex; align-items: center; gap: 2px; }
.lx-nav-item-row .lx-nav-item { flex: 1; min-width: 0; }

.lx-nav-pin-btn {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--lx-r-md);
  color: var(--lx-t4);
  font-size: 13px;
  opacity: 0;
  transition: opacity var(--lx-t-fast) var(--lx-ease), color var(--lx-t-fast) var(--lx-ease), background var(--lx-t-fast) var(--lx-ease);
}
.lx-nav-item-row:hover .lx-nav-pin-btn { opacity: .6; }
.lx-nav-pin-btn:hover { opacity: 1; background: var(--lx-fill); color: var(--lx-t1); }
.lx-nav-pin-btn.is-pinned { opacity: 1; color: var(--lx-accent); }

.lx-nav-group__label--btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  cursor: pointer;
}
.lx-nav-group__collapse {
  color: var(--lx-t4);
  transition: transform var(--lx-t-fast) var(--lx-ease);
}
.lx-nav-group.is-collapsed .lx-nav-group__collapse { transform: rotate(-90deg); }
.lx-nav-group.is-collapsed .lx-nav-group__items { display: none; }

.lx-nav-group--favourites .lx-nav-pin-btn { display: none; }
.lx-nav-group--favourites[hidden] { display: none; }

.lx-nav-item__badge {
  margin-left: auto;
  flex: none;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--lx-r-full);
  background: var(--lx-danger);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}

/* ══ PATIENT SWITCHER ══════════════════════════════════════════════════════ */

.lx-patient-switcher {
  flex: none;
  padding: var(--lx-s-3) var(--lx-s-3) 0;
  margin-top: var(--lx-s-2);
  border-top: 1px solid var(--lx-line-soft);
}

.lx-patient-switcher__label {
  font-family: var(--lx-f-mono);
  font-size: var(--lx-fs-micro);
  font-weight: 500;
  letter-spacing: var(--lx-ls-label);
  text-transform: uppercase;
  color: var(--lx-t4);
  margin-bottom: var(--lx-s-2);
}

.lx-patient-switcher__row { display: flex; align-items: center; gap: var(--lx-s-2); }

.lx-patient-search-input {
  flex: 1 1 auto;
  min-width: 0;
  height: 34px;
  padding: 0 var(--lx-s-3);
  border-radius: var(--lx-r-md);
  border: 1px solid var(--lx-glass-border);
  background: var(--lx-fill);
  color: var(--lx-t1);
  font-size: var(--lx-fs-sm);
  font-family: inherit;
}
.lx-patient-search-input::placeholder { color: var(--lx-t4); }
.lx-patient-search-input:focus {
  outline: none;
  border-color: var(--lx-accent);
  box-shadow: 0 0 0 2px var(--lx-accent-soft);
}
.lx-patient-search-input.has-active { color: var(--lx-accent); font-weight: 600; }

.lx-patient-add-btn {
  flex: none;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--lx-r-md);
  background: var(--lx-accent-soft);
  color: var(--lx-accent);
  font-size: 1.1rem;
  line-height: 1;
  text-decoration: none;
  transition: background var(--lx-t-fast) var(--lx-ease);
}
.lx-patient-add-btn:hover { background: color-mix(in srgb, var(--lx-accent-soft) 50%, var(--lx-accent) 25%); text-decoration: none; }

.lx-patient-dropdown {
  position: fixed;
  z-index: var(--lx-z-sheet);
  display: none;
  flex-direction: column;
  min-width: 200px;
  max-height: 320px;
  overflow: hidden;
  background: var(--lx-glass-strong);
  -webkit-backdrop-filter: var(--lx-glass-blur);
  backdrop-filter: var(--lx-glass-blur);
  border: 1px solid var(--lx-glass-border-strong);
  border-radius: var(--lx-r-lg);
  box-shadow: var(--lx-shadow-floating);
}
.lx-patient-dropdown__section { overflow-y: auto; max-height: 150px; }
.lx-patient-dropdown__section + .lx-patient-dropdown__section { border-top: 1px solid var(--lx-glass-border); }
.lx-patient-dropdown__label {
  position: sticky;
  top: 0;
  font-family: var(--lx-f-mono);
  font-size: var(--lx-fs-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--lx-ls-label);
  color: var(--lx-t4);
  background: var(--lx-fill);
  padding: var(--lx-s-2) var(--lx-s-3) var(--lx-s-1);
}
.lx-patient-dropdown__item {
  padding: var(--lx-s-2) var(--lx-s-3);
  font-size: var(--lx-fs-sm);
  color: var(--lx-t2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: background var(--lx-t-fast) var(--lx-ease), color var(--lx-t-fast) var(--lx-ease);
}
.lx-patient-dropdown__item:hover { background: var(--lx-fill-hover); color: var(--lx-t1); }
.lx-patient-dropdown__item.is-active { background: var(--lx-accent-soft); color: var(--lx-accent); font-weight: 600; }
.lx-patient-dropdown__empty { padding: var(--lx-s-2) var(--lx-s-3); font-size: var(--lx-fs-xs); color: var(--lx-t4); }

/* ══ MAIN COLUMN ═══════════════════════════════════════════════════════════ */

.lx-main {
  position: relative;
  z-index: var(--lx-z-content);
  display: flex;
  flex-direction: column;
  height: var(--real-vh, 100vh);
  margin-left: 0;
  transition: margin-left var(--lx-t-slow) var(--lx-ease-out);
}

/* ══ TOPBAR ════════════════════════════════════════════════════════════════
   Transparent while the content is scrolled to the top, materialising into
   glass on scroll. .is-stuck is toggled by theme.js. */

.lx-topbar {
  position: sticky;
  top: 0;
  z-index: var(--lx-z-topbar);
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--lx-s-2);
  height: var(--lx-topbar-h);
  padding: 0 var(--lx-s-4);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition:
    background var(--lx-t-base) var(--lx-ease),
    border-color var(--lx-t-base) var(--lx-ease),
    backdrop-filter var(--lx-t-base) var(--lx-ease);
}

.lx-topbar.is-stuck {
  background: var(--lx-glass);
  -webkit-backdrop-filter: var(--lx-glass-blur);
  backdrop-filter: var(--lx-glass-blur);
  border-bottom-color: var(--lx-glass-border);
}

.lx-topbar__title {
  font-size: var(--lx-fs-base);
  font-weight: 500;
  letter-spacing: var(--lx-ls-title);
  color: var(--lx-t1);
  /* Fades in with the glass — at the top of a page the page's own heading is
     already visible, so repeating it in the bar is noise. */
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--lx-t-base) var(--lx-ease), transform var(--lx-t-base) var(--lx-ease);
}
.lx-topbar.is-stuck .lx-topbar__title { opacity: 1; transform: none; }

.lx-topbar__spacer { flex: 1 1 auto; }
.lx-topbar__actions { display: flex; align-items: center; gap: var(--lx-s-1); }

/* Balance chip in the topbar */
.lx-balance {
  display: inline-flex;
  align-items: center;
  gap: var(--lx-s-2);
  height: 30px;
  padding: 0 var(--lx-s-3);
  border-radius: var(--lx-r-full);
  background: var(--lx-fill);
  font-family: var(--lx-f-mono);
  font-size: var(--lx-fs-micro);
  letter-spacing: 0.04em;
  color: var(--lx-t2);
  white-space: nowrap;
}
.lx-balance .lx-icon { color: var(--lx-accent); }

/* Mode toggle swaps which glyph is shown */
[data-theme="dark"] .lx-mode-light { display: block; }
[data-theme="dark"] .lx-mode-dark  { display: none; }
.lx-mode-light { display: none; }
.lx-mode-dark  { display: block; }

/* ══ CONTENT ═══════════════════════════════════════════════════════════════ */

.lx-content {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-padding-top: var(--lx-s-8);
}

/* Standard padded page. Modules with their own full-height layout (chat, exam)
   use .lx-content--flush and manage their own box. */
.lx-page {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: var(--lx-s-4) var(--lx-s-6) var(--lx-s-24);
}
.lx-page--narrow { max-width: 820px; }
.lx-page--wide   { max-width: 1400px; }

.lx-content--flush { overflow: hidden; }
.lx-content--flush > * { height: 100%; }

.lx-page__head { margin-bottom: var(--lx-s-8); }

/* ══ LITE SHELL ════════════════════════════════════════════════════════════
   The logged-out counterpart to .lx-shell/.lx-main above — a plain document
   flow (no fixed-height flex column, no sidebar) for the public marketing
   and auth shells (shared/page-shell/lx/public.php, auth.php). Shared by
   both so their topbars sit identically; each shell's own CSS
   (marketing.css, auth.css) only adds page-specific rules on top. */

/* .lx-shell/.lx-content (above) use a fixed-viewport-with-internal-scroll
   model because the app has a sidebar that must stay put. Lite pages
   (public/auth) have no sidebar and a real footer that belongs in the same
   scroll as the content above it — forcing that model here made the footer
   fight .lx-lite-content for a fixed budget of viewport height and get
   clipped. Simpler and correct for a plain document: let body itself scroll
   (base.css's blanket html,body{overflow:hidden} is opted out of, scoped to
   this one class so the app shell's own scroll model is untouched), and
   .lx-lite-shell just grows to its natural content height.

   height:auto is the other half of that opt-out, and matters just as much:
   base.css's html,body{height:var(--real-vh,100vh)} pins body to exactly one
   viewport tall regardless of actual content — harmless for a page longer
   than one viewport (index.php etc: content already exceeds it, nothing
   visible changes), but on any SHORTER page (terms.php, privacy.php,
   refund-policy.php…) that fixed height forced the page to fill a full
   viewport before the footer could render, producing a large empty gap
   between short content and the footer ("empty space at the bottom").
   height:auto lets body size to its real content instead; min-height:100%
   below (now resolving against nothing, since an auto-height body no longer
   gives percentage children an explicit height to resolve against — this is
   the correct, spec'd no-op, not a bug) is left in place only for the
   backdrop stacking-context reason in the comment below, not for sizing.

   base.css's blanket rule is actually `html, body { height:...; overflow:
   hidden }` — it targets BOTH elements, and <html> carries no .lx-lite class
   (only <body> does, per lite-shell.php), so the body-only override below
   left <html> still pinned to exactly one viewport tall with overflow:hidden.
   That's the *actual* scroll-lock bug: <html> is the root scrolling box, so
   pinning it means the page cannot be scrolled at all, on any lite page,
   regardless of content length. :has() opts <html> out the same way
   whenever it wraps a lite body. */
html:has(body.lx-lite) { height: auto; overflow: visible; }
body.lx-lite { overflow-y: auto; height: auto; }
.lx-lite-shell {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  /* .lx-backdrop is position:fixed with an opaque fill; per CSS painting
     order, ANY positioned element paints above non-positioned content
     regardless of DOM order — so without a stacking context here, plain
     (non-positioned) page content is invisible beneath it. .lx-main gives
     the app shell the same treatment; lite pages need it too, since most of
     their content (plain headings/paragraphs) has no position of its own,
     unlike componentised content (.depth-card etc.) which happens to
     declare position:relative for other reasons. */
  position: relative;
  z-index: var(--lx-z-content);
}
.lx-lite-content { flex: 1 0 auto; }

/* Auth's minimal topbar: just the wordmark + the flat control row. Always
   glass rather than materialising on scroll (lx-shell.js's scroll-driven
   .is-stuck toggle keys off .lx-content, which lite pages don't have — an
   always-on bar suits a short, rarely-scrolled login page better anyway). */
.lx-topbar--auth {
  position: static;
  background: var(--lx-glass);
  -webkit-backdrop-filter: var(--lx-glass-blur);
  backdrop-filter: var(--lx-glass-blur);
  border-bottom: 1px solid var(--lx-glass-border);
}
.lx-auth-wordmark {
  font-family: var(--lx-f-display);
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--lx-t1);
  text-decoration: none;
}
.lx-auth-wordmark:hover { color: var(--lx-accent); }
.lx-page__title {
  font-size: var(--lx-fs-xl);
  font-weight: 500;
  letter-spacing: var(--lx-ls-title);
}
.lx-page__sub {
  margin-top: var(--lx-s-2);
  font-size: var(--lx-fs-sm);
  color: var(--lx-t3);
}

.lx-section + .lx-section { margin-top: var(--lx-s-12); }
.lx-section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--lx-s-4);
  margin-bottom: var(--lx-s-4);
}

/* ══ SCRIM ═════════════════════════════════════════════════════════════════ */

.lx-sidebar-scrim {
  position: fixed;
  inset: 0;
  z-index: calc(var(--lx-z-sidebar) - 1);
  display: none;
  background: rgba(0, 0, 0, 0.42);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  opacity: 0;
  /* Inert until opened, so an invisible scrim can never swallow taps */
  pointer-events: none;
  transition: opacity var(--lx-t-base) var(--lx-ease);
}
.lx-sidebar-scrim.is-open { opacity: 1; pointer-events: auto; }

/* ══ MOBILE PILL NAV ═══════════════════════════════════════════════════════
   The floating glass tab bar from the reference. Hidden on desktop, where the
   sidebar covers the same ground. */

.lx-mobilenav {
  position: fixed;
  z-index: var(--lx-z-mobilenav);
  left: 50%;
  bottom: max(var(--lx-s-4), env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  display: none;
  align-items: center;
  gap: var(--lx-s-1);
  padding: var(--lx-s-2);
  max-width: calc(100vw - var(--lx-s-6));
  overflow-x: auto;
  scrollbar-width: none;
  border-radius: var(--lx-r-full);
}
.lx-mobilenav::-webkit-scrollbar { display: none; }

.lx-mobilenav__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  flex: none;
  min-width: 62px;
  padding: var(--lx-s-2) var(--lx-s-3);
  border-radius: var(--lx-r-full);
  font-size: 0.625rem;
  letter-spacing: 0.01em;
  color: var(--lx-t3);
  transition: background var(--lx-t-base) var(--lx-ease), color var(--lx-t-base) var(--lx-ease);
}
.lx-mobilenav__item:hover { text-decoration: none; }
.lx-mobilenav__item.is-active {
  background: var(--lx-glass-strong);
  color: var(--lx-t1);
  box-shadow: var(--lx-glass-inset);
}
.lx-mobilenav__item.is-active .lx-icon { color: var(--lx-accent); }

/* ══ RESPONSIVE ════════════════════════════════════════════════════════════ */

@media (min-width: 900px) {
  .lx-sidebar-scrim { display: none !important; }

  /* Sidebar pushes the content column rather than overlaying it */
  .lx-sidebar.is-open ~ .lx-main { margin-left: var(--lx-sidebar-w); }

  .lx-sidebar__close { display: none; }
}

@media (max-width: 899px) {
  .lx-sidebar { box-shadow: var(--lx-shadow-overlay), var(--lx-glass-inset); }
  .lx-sidebar-scrim { display: block; }
  .lx-mobilenav { display: flex; }

  .lx-page { padding: var(--lx-s-3) var(--lx-s-4) var(--lx-s-24); }

  /* Clear the floating pill nav */
  .lx-content { padding-bottom: 76px; }

  /* LEARN_MOBILE_NAV = false: no bar to clear, so give the space back. */
  .lx-no-mobilenav .lx-page { padding-bottom: var(--lx-s-4); }
  .lx-no-mobilenav .lx-content { padding-bottom: 0; }
}

@media (max-width: 600px) {
  :root { --lx-fs-3xl: 2.5rem; --lx-fs-2xl: 1.875rem; --lx-fs-xl: 1.375rem; }

  .lx-topbar { padding: 0 var(--lx-s-3); }
  .lx-balance { display: none; }
}

/* Active patient readout — filled by js/lx-sidebar-patient.js when a patient
   is selected, hidden otherwise (the element carries [hidden]). */
.lx-patient-switcher__active {
  margin-top: .4rem;
  padding: .3rem .5rem;
  border-radius: 7px;
  background: var(--lx-surface-2, rgba(255,255,255,.05));
  color: var(--lx-text-2, inherit);
  font-size: .74rem;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Credits strip ─────────────────────────────────────────────────────────
   The sidebar balance block the three portals carry (partials/credits-strip.php).
   Learn shows its balance in the topbar instead and never renders this. */
.lx-credits {
  display: block;
  padding: .55rem .9rem .6rem;
  border-bottom: 1px solid var(--lx-line, rgba(255,255,255,.08));
  color: var(--lx-text-2, inherit);
  font-size: .78rem;
  text-decoration: none;
  transition: background .16s ease;
}

.lx-credits:hover { background: var(--lx-surface-2, rgba(255,255,255,.04)); }

.lx-credits__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
}

.lx-credits__label {
  color: var(--lx-text-3, inherit);
  font-size: .68rem;
  letter-spacing: .09em;
  text-transform: uppercase;
}

.lx-credits__value {
  color: var(--lx-text-1, inherit);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.lx-credits__meta {
  display: block;
  margin-top: .18rem;
  color: var(--lx-text-3, inherit);
  font-size: .66rem;
  font-variant-numeric: tabular-nums;
  opacity: .8;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Institution switcher's secondary line (the institution's type). */
.lx-patient-switcher__meta {
  margin-top: .15rem;
  color: var(--lx-text-3, inherit);
  font-size: .68rem;
  letter-spacing: .04em;
}
