/* ──────────────────────────────────────────────────────────────────────
 * Vitality App Shell — desktop sidebar layout (loaded in <head>)
 *
 * This CSS lands BEFORE the first paint so the wide labeled rail
 * renders immediately on desktop — no flash, no jump when you click
 * from one page to another.
 *
 * Covers both shell patterns the app uses:
 *   .app-shell > .sidebar  (dashboard, ondemand, ai-coach, etc.)
 *   .shell > .sidebar      (program/community/course pages)
 *
 * And both item class patterns:
 *   a.nav-item    (most pages)
 *   a.s-item      (program/community-style pages)
 * ────────────────────────────────────────────────────────────────────── */

/* ──────────────────────────────────────────────────────────────────────
 * Cross-document View Transitions — Chrome/Safari/Edge 126+
 *
 * Makes navigation between full HTML pages feel like a single-page app:
 *  - No white flash between page loads
 *  - The sidebar and topbar stay visually locked (they get a stable
 *    view-transition-name so the browser treats both instances as the
 *    same element — no cross-fade on them, only on the main content area)
 *  - Main content cross-fades quickly (180ms) instead of hard-cutting
 *
 * Older browsers ignore these rules and use normal navigation.
 * ────────────────────────────────────────────────────────────────────── */
/* DISABLED 2026-07-08: cross-document view transitions were leaving long
   pages HALF-PAINTED after navigation in real Chrome (hard horizontal cut,
   void below, fixed by reload, re-broken by navigating — reported by
   Elizabeth on multiple pages). The old-page GPU snapshot + long scrollers
   don't mix reliably. The named sidebar/topbar rules below stay harmless
   without this opt-in; re-enable only if Chromium fixes the artifact.
@view-transition {
  navigation: auto;
}
*/

/* The shared, persistent shell elements — same name on every page means
   the browser treats them as the same DOM element across navigation. */
body .app-shell > .sidebar,
body .shell > .sidebar {
  view-transition-name: app-sidebar;
}
body .topbar {
  view-transition-name: app-topbar;
}
/* Program/community subnavs stay in normal document flow. Do not give
   these bars a shared view-transition name; Chrome can visually promote
   them above the page header during cross-page/app-preview movement. */

/* Program sub-nav — left-align on desktop, centered on mobile so Coaching doesn't get cut off */
body .comm-nav.prog-nav {
  justify-content: flex-start !important;
  padding-left: 24px !important;
}
@media (max-width: 768px) {
  body .comm-nav.prog-nav {
    justify-content: center !important;
    padding-left: 10px !important;
    padding-right: 10px !important;
    gap: 4px !important;
  }
  body .comm-nav.prog-nav a.cn-btn {
    padding: 8px 12px !important;
    font-size: 11.5px !important;
  }
}

/* Sub-nav layout + tab styles — shared so every page using .comm-nav.prog-nav
   gets the same pill look. Previously these styles were inline-only on
   vitality-program-owner.html, which left Calendar/Course/Replay-Library
   pages with bare-text links after we removed their inline styles. */
body .comm-nav.prog-nav {
  display: flex;
  position: relative !important;
  top: auto !important;
  order: 1 !important;
  gap: 8px;
  padding-top: 14px;
  padding-bottom: 14px;
  padding-right: 24px;
  border-bottom: 1px solid rgba(255,255,255,0.07);
  overflow-x: auto;
  background: rgba(8,8,8,0.6);
  z-index: 40;
}

body .shell > .main > .topbar {
  position: relative !important;
  top: auto !important;
  order: 0 !important;
}

body .shell > .main > .page {
  order: 2 !important;
}
body .comm-nav.prog-nav::-webkit-scrollbar { display: none; }
body .comm-nav.prog-nav a.cn-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 18px;
  border-radius: 20px;
  font-family: 'DM Sans', sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: rgba(255,255,255,0.45);
  border: 1px solid transparent;
  background: none;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: all 0.18s;
}
body .comm-nav.prog-nav a.cn-btn:hover {
  color: #fff;
  background: rgba(255,255,255,0.04);
}
body .comm-nav.prog-nav a.cn-btn.on {
  background: rgba(155,45,255,0.22);
  border-color: rgba(155,45,255,0.55);
  color: #d8b4fe;
}

/* Quick cross-fade on the rest (root group = everything not named above) */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.18s;
  animation-timing-function: ease;
}

/* The named persistent elements should NOT fade in/out — they should
   "snap" since they're the same content. Zero-duration animation = no fade. */
::view-transition-old(app-sidebar),
::view-transition-new(app-sidebar),
::view-transition-old(app-topbar),
::view-transition-new(app-topbar) {
  animation: none;
  mix-blend-mode: normal;
}

/* Hide page-built notification bells + standalone help buttons everywhere — they all live in the avatar dropdown now.
   Covers both the topbar copy (.topbar .notif-btn/.s-notif) and the legacy sidebar copy
   (.nav-bottom .notif-btn, .s-bottom .s-notif) — ~29 older pages still carry a hardcoded
   always-on red-dot bell in the sidebar; only the avatar-dropdown dot is canonical now. */
.topbar .notif-btn,
.topbar .topbar-notif,
.topbar .s-notif,
.nav-bottom .notif-btn,
.s-bottom .s-notif,
.vt-help-btn { display: none !important; }

/* My Tools old role-switcher rows — gone via My Tools restructure */
.my-tools-role-hint,
.tools-role-switcher { display: none !important; }

/* Use 769px so the wide rail kicks in immediately above the page-level
   mobile breakpoint (most pages hide .sidebar at max-width:768px). No
   dead zone between 768 and 899px where the rail reverts to icons. */
@media (min-width: 769px) {

  /* Widen the grid track on either shell pattern */
  body .app-shell,
  body .shell {
    grid-template-columns: 220px 1fr !important;
  }

  body .app-shell > .sidebar,
  body .shell > .sidebar {
    width: 220px !important;
    align-items: stretch !important;
    padding: 16px 12px !important;
    gap: 2px !important;
  }

  body .app-shell > .sidebar .wheel-avatar,
  body .shell > .sidebar .wheel-avatar {
    align-self: center;
    margin-bottom: 8px;
  }

  /* Items — both class patterns */
  body .app-shell > .sidebar a.nav-item,
  body .app-shell > .sidebar a.s-item,
  body .shell > .sidebar a.nav-item,
  body .shell > .sidebar a.s-item {
    width: auto !important;
    height: auto !important;
    flex-direction: row !important;
    justify-content: flex-start !important;
    align-items: center !important;
    gap: 11px !important;
    padding: 10px 12px !important;
    font-size: 13.5px !important;
    font-weight: 600 !important;
    color: rgba(240,240,240,0.62) !important;
    text-decoration: none !important;
    border-radius: 11px !important;
    letter-spacing: 0 !important;
    text-transform: none !important;
    white-space: nowrap !important;
  }

  body .app-shell > .sidebar a.nav-item svg,
  body .app-shell > .sidebar a.s-item svg,
  body .shell > .sidebar a.nav-item svg,
  body .shell > .sidebar a.s-item svg {
    width: 19px !important;
    height: 19px !important;
    flex-shrink: 0;
  }

  body .app-shell > .sidebar a.nav-item:hover,
  body .app-shell > .sidebar a.s-item:hover,
  body .shell > .sidebar a.nav-item:hover,
  body .shell > .sidebar a.s-item:hover {
    background: rgba(255,255,255,0.04) !important;
    color: #fff !important;
  }

  body .app-shell > .sidebar a.nav-item.active,
  body .app-shell > .sidebar a.nav-item[aria-current="page"],
  body .app-shell > .sidebar a.s-item.on,
  body .app-shell > .sidebar a.s-item[aria-current="page"],
  body .shell > .sidebar a.nav-item.active,
  body .shell > .sidebar a.nav-item[aria-current="page"],
  body .shell > .sidebar a.s-item.on,
  body .shell > .sidebar a.s-item[aria-current="page"] {
    background: linear-gradient(135deg, rgba(155,45,255,0.14), rgba(255,45,155,0.08)) !important;
    color: #fff !important;
    border: 1px solid rgba(155,45,255,0.28) !important;
  }

  /* Flatten any wrapper groups so items can stack vertically */
  body .app-shell > .sidebar .s-group,
  body .app-shell > .sidebar .s-lbl,
  body .app-shell > .sidebar .s-label,
  body .shell > .sidebar .s-group,
  body .shell > .sidebar .s-lbl,
  body .shell > .sidebar .s-label {
    display: contents;
  }

  body .app-shell > .sidebar .nav-bottom,
  body .app-shell > .sidebar .s-bottom,
  body .shell > .sidebar .nav-bottom,
  body .shell > .sidebar .s-bottom {
    margin-top: auto;
  }

  /* Divider injected by vitality-app-shell.js between core nav + utility nav */
  body .app-shell > .sidebar .vas-divider,
  body .shell > .sidebar .vas-divider {
    height: 1px;
    background: rgba(255,255,255,0.06);
    margin: 10px 8px;
  }
}

/* ──────────────────────────────────────────────────────────────────────
 * Sub-nav tap target site-wide override.
 * The .cn-btn pattern lives inline-CSS in ~10 pages with 8px padding +
 * 12px font, which works out to ~33px tall — under the 36px tap
 * minimum. Boost every instance to min-height:36px so Calendar / Course
 * / Coaching / community tabs land reliably under a thumb without
 * having to refactor every page's <style> block. */
.cn-btn { min-height: 36px; }
@media (max-width: 600px) {
  /* On mobile sub-nav rows tend to flex:1 — make sure they don't
     shrink the button below 36 just because the row got crowded. */
  .cn-btn { padding-top: 9px; padding-bottom: 9px; }
}

/* ──────────────────────────────────────────────────────────────────────
 * Bottom-nav clearance on mobile scroll containers.
 *
 * vitality-nav.js paints a 70-ish-px fixed bottom nav on mobile (taller
 * with safe-area-inset on notched devices). The scrollable area on each
 * page — .main on dashboard/onDemand/AI Coach/Vital Check, .content on
 * program/community — needs enough padding-bottom that the last card
 * isn't sitting underneath the nav. Without this, .stat-card or .ep-card
 * gets cropped at every-page-bottom and users miss the final tile.
 *
 * 110px = 70px nav + 16px nav safe-area max + 24px breathing room. */
@media (max-width: 768px) {
  body .app-shell > .main,
  body .shell > .main,
  body .app-shell > .content,
  body .shell > .content {
    padding-bottom: calc(110px + env(safe-area-inset-bottom, 0px)) !important;
  }
}

/* ============================================================
   Site-wide desktop full-width override (Elizabeth, 2026-06)
   Every page fills the viewport on desktop — no centered
   max-width, no left/right blank space. Mobile keeps its own
   per-page layout. Body-scoped for higher specificity than
   inline `.page` selectors that load after this stylesheet.
   ============================================================ */
@media (min-width: 769px) {
  html body .page,
  html body .wrap {
    max-width: none !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   ONE SCROLL CONTAINER: THE DOCUMENT.   (Elizabeth, 2026-08)

   HOUSE RULE — read this before you touch any page layout:

     • The DOCUMENT is the only scroller. Nothing else scrolls vertically.
     • The sidebar is STICKY (position:sticky; top:0), never fixed.
     • NEVER give .main (or .content) its own overflow or a
       viewport-locked height. Content flows into the document scroll.
     • Mobile breakpoint is 768px. NEVER 900 — there is a documented
       769-900px dead zone in this repo when a page hides its sidebar at
       <=900 while this stylesheet forces the 220px rail at >=769.

   WHY: pages used to ship `.app-shell{height:100vh}` +
   `.main{overflow-y:auto;height:100vh}`, which created TWO competing
   scrollers — the inner pane AND the document. Scrolling sometimes moved
   the pane and sometimes dragged the whole fixed-height shell out of the
   window, clipping content mid-section and leaving dead space below.
   These rules neutralise that old model site-wide with !important, so
   individual pages do not have to be edited (their inline
   `.main{overflow-y:auto;height:100vh}` can stay; it is simply overruled).

   OPT-OUT: a genuinely full-viewport app pane (chat transcript with a
   pinned composer, a full-bleed map, a timer) can put
   `class="vas-viewport-app"` on <body> to keep its own single inner
   scroller. Use it only when the page has NO document scroll at all —
   one scroller either way, never two.
   ══════════════════════════════════════════════════════════════════════ */

html body:not(.vas-viewport-app) .app-shell,
html body:not(.vas-viewport-app) .shell {
  /* --vas-top-chrome is measured by vitality-app-shell.js: the height of
     any position:sticky chrome sitting above the shell (role quickstrip).
     Subtracting it means sticky chrome + shell === exactly one viewport,
     instead of one viewport PLUS a dead 42px sliver of scroll. */
  min-height: calc(100vh - var(--vas-top-chrome, 0px)) !important;
  height: auto !important;
  max-height: none !important;
  overflow: visible !important;
}

/* The rail stays put visually without becoming a second document scroller.
   max-height + overflow-y:auto only kicks in for rails taller than the
   viewport; short rails never produce a scrollbar. */
html body:not(.vas-viewport-app) .app-shell > .sidebar,
html body:not(.vas-viewport-app) .shell > .sidebar {
  position: sticky !important;
  /* Stick directly UNDER the sticky top chrome, and fill exactly what is
     left of the viewport — so the rail neither hides behind the strip nor
     hangs past the bottom edge. */
  top: var(--vas-top-chrome, 0px) !important;
  align-self: start !important;
  height: calc(100vh - var(--vas-top-chrome, 0px)) !important;
  max-height: calc(100vh - var(--vas-top-chrome, 0px)) !important;
  overflow-y: auto !important;
  /* overflow-x must be hidden, not visible: `overflow-y:auto` with
     `overflow-x:visible` makes the browser compute overflow-x to `auto`,
     which paints a horizontal scrollbar under the nowrap rail labels and
     steals 16px of height — which then makes the rail overflow vertically
     when it otherwise would not. Do NOT remove this line.
     Scroll chaining is deliberately left ON (no overscroll-behavior) so a
     wheel over a long rail continues into the page instead of dead-ending. */
  overflow-x: hidden !important;
}

/* Content pane flows into the normal document scroll. */
html body:not(.vas-viewport-app) .app-shell > .main,
html body:not(.vas-viewport-app) .shell > .main,
html body:not(.vas-viewport-app) .app-shell > .content,
html body:not(.vas-viewport-app) .shell > .content {
  height: auto !important;
  max-height: none !important;
  /* overflow-y MUST be visible — that is the whole point: no second scroller.
     overflow-x is `clip`, not `hidden` and not `visible`:
       · `hidden` would force overflow-y to compute to `auto` (a scroller again),
       · `visible` would let a too-wide child push the whole DOCUMENT sideways
         (the old `overflow-y:auto` used to quietly contain that),
       · `clip` is the only value the spec allows to pair with `visible`, and it
         contains horizontal overflow WITHOUT creating a scroll container.
     Chrome 90+ / Safari 16+. On anything older the declaration is simply
     dropped, overflow-x falls back to visible, and the page still has exactly
     one scroller — it just may scroll sideways on the handful of pages whose
     content is genuinely too wide. Degrades safely; never re-introduces the bug. */
  overflow-x: clip !important;
  overflow-y: visible !important;
  /* Grid blowout guard. A grid item's automatic minimum size is its
     max-content width, so one wide child (a long table, a nowrap row) used
     to stretch the `1fr` track past the viewport. The old
     `overflow-y:auto` masked this by making .main a scroll container.
     `min-width:0` is the canonical fix and must stay. */
  min-width: 0 !important;
}

/* Mobile: rail is hidden, shell is a single column, nothing viewport-locked. */
@media (max-width: 768px) {
  html body:not(.vas-viewport-app) .app-shell > .sidebar,
  html body:not(.vas-viewport-app) .shell > .sidebar {
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
  }
}

/* ──────────────────────────────────────────────────────────────────────
   OPT-OUT PAGES (body.vas-viewport-app) — still exactly ONE scroller.

   These pages keep an inner scroller on purpose (a chat transcript under
   a pinned composer, a full-bleed timer). The rule they must still obey
   is that the DOCUMENT must not scroll as well — otherwise you get the
   same two-scroller fight, just with the roles swapped: the inner pane
   scrolls, then the whole viewport-locked shell slides out from under it.

   So: lock the document, and size the shell to what is actually left of
   the viewport after any sticky top chrome.
   ────────────────────────────────────────────────────────────────────── */
html body.vas-viewport-app {
  overflow: hidden;
}
html body.vas-viewport-app .app-shell,
html body.vas-viewport-app .shell {
  min-height: 0 !important;
  /* -all, not the sticky-only var: on a locked page nothing scrolls away, so
     every bit of in-flow chrome above the shell has to be subtracted. */
  height: calc(100vh - var(--vas-top-chrome-all, 0px)) !important;
}
html body.vas-viewport-app .app-shell > .main,
html body.vas-viewport-app .shell > .main {
  height: 100% !important;
  min-width: 0 !important;
}
/* A 100vh rail inside a (100vh - chrome) shell would push the grid row back
   out to a full viewport and re-create the sliver of document scroll. */
html body.vas-viewport-app .app-shell > .sidebar,
html body.vas-viewport-app .shell > .sidebar {
  top: 0 !important;
  height: 100% !important;
  max-height: 100% !important;
}

/* ──────────────────────────────────────────────────────────────────────
   Sticky top chrome must be OPAQUE now that the document scrolls.

   The role quickstrip (injected by vitality-nav.js) paints a translucent
   tint. That was fine when .main was its own scrollport — nothing ever
   travelled underneath the strip. With one document scroller, page content
   now passes behind it, and text was reading through the tint.

   Only the colour slot is forced; the strip keeps its gradient, its border
   and its per-role --vq-strip-bg theming on top of an opaque base.
   ────────────────────────────────────────────────────────────────────── */
#vitality-role-quickstrip {
  background-color: var(--black, #080808) !important;
}
