/* ==========================================================================
   layout.css — the app shell: topbar, side rail, bottom bar, drawer, main
   Third load. Pure structure — no component styling beyond the chrome.
   Breakpoints: ≥960px desktop rail; 640/560/520/480 minor grids.
   ========================================================================== */

#app {
  display: flex;
  flex-direction: column;
  min-height: 100vh; /* pre-dvh fallback */
  min-height: 100dvh;
}

/* ==========================================================================
   Topbar
   ========================================================================== */
#topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  /* Calm frosted chrome: deep blur + saturation over a warm tint, plus a
     hairline shadow so the bar reads as one level above the paper. */
  background: color-mix(in srgb, var(--color-bg) 82%, transparent);
  backdrop-filter: blur(20px) saturate(1.6);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  border-bottom: 1px solid var(--color-border);
  box-shadow: 0 1px 12px rgba(28, 32, 28, 0.06);
}

.topbar__inner {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--topbar-height);
  max-width: var(--content-max-width);
  margin: 0 auto;
  padding: 0 var(--space-4);
}

.topbar__lead {
  display: flex;
  align-items: center;
  gap: var(--space-1_5);
  min-width: 0;
}

.topbar__brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 44px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-md);
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: -0.015em;
  color: var(--color-text);
}
.topbar__brand:hover {
  text-decoration: none;
  background: var(--color-surface-alt);
}

.topbar__brand-icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 12px;
  background: linear-gradient(145deg, var(--color-primary) 0%, var(--color-primary-deep) 100%);
  color: #ffffff;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    0 4px 12px rgba(8, 51, 47, 0.3);
  line-height: 1;
}
.topbar__brand-icon svg {
  width: 21px;
  height: 21px;
}

.topbar__brand-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar__actions {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-inline-start: auto;
}

/* ==========================================================================
   Main view outlet
   ========================================================================== */
#main {
  flex: 1;
  width: 100%;
  max-width: var(--content-max-width);
  margin: 0 auto;
  padding: var(--space-5) var(--space-4) calc(var(--bottomnav-height) + var(--space-9));
  outline: none;
}

/* Every view is one vertical rhythm: generous, even section gaps so the
   home/library/prayer pages read as composed screens, not stacked boxes. */
.view {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.view--home {
  gap: var(--space-4);
}

/* The docked player lifts content clear of itself. */
body.has-player #main {
  padding-bottom: calc(var(--bottomnav-height) + var(--playerbar-height));
}

/* ==========================================================================
   Bottom navigation (mobile bar + drawer + desktop rail all render from
   shell.js; CSS picks presentation by viewport)
   ========================================================================== */
#bottomnav {
  position: fixed;
  bottom: 0;
  inset-inline: 0;
  z-index: var(--z-nav);
  padding-bottom: env(safe-area-inset-bottom, 0);
  background: color-mix(in srgb, var(--color-bg) 90%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid var(--color-border);
}

/* Mobile bar */
.nav-mobile-bar {
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  gap: 2px;
  height: var(--bottomnav-height);
  padding: 6px 6px 2px;
}

.nav-mobile-bar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  flex: 1 1 0;
  min-width: 0;
  min-height: 56px;
  padding: 6px 2px;
  color: var(--color-text-muted);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1;
  transition:
    color var(--dur-base) var(--ease-standard),
    background-color var(--dur-base) var(--ease-standard),
    transform var(--dur-fast) var(--ease-standard);
  border-radius: var(--radius-md);
}
.nav-mobile-bar__item:active {
  transform: scale(0.96);
}
/* Active/hover states shared by both bars. (v4.1: the earlier duplicate
   subset of these rules — same selectors, same values, defined 20 lines up
   — was removed; this block is the single owner.) */
.nav-mobile-bar__item:hover {
  color: var(--color-text-secondary);
  text-decoration: none;
}
.nav-mobile-bar__item--active,
.nav-mobile-bar__item[aria-current='page'] {
  color: var(--color-primary-text);
  font-weight: 700;
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
}
.nav-mobile-bar__item--active::after,
.nav-mobile-bar__item[aria-current='page']::after {
  content: none;
}

.nav__item--active,
.nav__item[aria-current='page'] {
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
  color: var(--color-primary-text);
  font-weight: 600;
}

/* ==========================================================================
   Desktop ≥960px: side rail replaces the mobile bar
   ========================================================================== */
.nav__inner {
  display: contents;
}

.nav__scroller {
  display: none;
}

@media (min-width: 960px) {
  #app {
    flex-direction: row;
  }

  #topbar {
    position: fixed;
    inset-inline-start: var(--sidenav-width);
    inset-inline-end: 0;
    transition: inset-inline-start var(--dur-slow) var(--ease-standard);
  }
  html[data-nav-collapsed='true'] #topbar {
    inset-inline-start: var(--sidenav-width-collapsed);
  }

  /* (v5.1.0) THE TOPBAR ORDER FIX (asked for since v4.4): on desktop the
     inner row used to cap at the centered content measure, which floated
     the whole [back][hamburger][brand] cluster to the middle of the
     screen — the "centered title" that never matched the spec. The row
     now spans rail-edge → screen-edge: hamburger at the far start, the
     brand immediately beside it, search/theme/back flush at the far end.
     (Markup order in shell.js: menu, brand … search, theme, back.) */
  .topbar__inner {
    max-width: none;
  }
  .topbar__actions .topbar__back {
    order: 3;
  }

  #bottomnav {
    position: fixed;
    top: var(--topbar-height);
    bottom: 0;
    inset-inline-start: 0;
    width: var(--sidenav-width);
    border-top: none;
    border-inline-end: 1px solid var(--color-border);
    background: var(--color-bg);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    transition: width var(--dur-slow) var(--ease-standard);
  }
  html[data-nav-collapsed='true'] #bottomnav {
    width: var(--sidenav-width-collapsed);
  }

  .nav-mobile-bar,
  .nav-drawer,
  .nav-drawer-overlay {
    display: none !important;
  }

  .nav__scroller {
    display: block;
    height: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-3) var(--space-2) var(--space-6);
    scrollbar-width: thin;
  }

  .nav__group + .nav__group {
    margin-top: var(--space-4);
  }

  .nav__group-label {
    padding: var(--space-1) var(--space-3);
    font-size: var(--fs-caption);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    white-space: nowrap;
  }
  html[data-nav-collapsed='true'] .nav__group-label {
    visibility: hidden;
    height: var(--space-2);
    padding: 0;
  }

  .nav__item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--touch-target);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    color: var(--color-text-secondary);
    font-size: var(--fs-sm);
    font-weight: 500;
    white-space: nowrap;
    transition:
      background-color var(--dur-base) var(--ease-standard),
      color var(--dur-base) var(--ease-standard);
  }
  .nav__item:hover {
    background: var(--color-surface-alt);
    color: var(--color-text);
    text-decoration: none;
  }
  .nav__item[aria-current='page'],
  .nav__item--active {
    background: color-mix(in srgb, var(--color-primary) 14%, transparent);
    color: var(--color-primary-text);
    font-weight: 600;
    /* v4.1: logical marker — the old inset box-shadow pinned the bar to the
       LEFT edge, which is the content-facing side once the rail sits right
       in RTL. border-inline-start follows the reading direction. */
    border-inline-start: 3px solid var(--color-primary);
  }
  .nav__item svg {
    flex-shrink: 0;
    /* (v5.1.0) hard size floor: the base `svg { max-width: 100% }` squeeze
       is what physically shrank the glyphs once the rail lost width (see
       the landscape note above). An explicit 24×24 in BOTH states is the
       contract: collapsed icons are the SAME SIZE as expanded ones. */
    width: 24px;
    height: 24px;
  }

  html[data-nav-collapsed='true'] .nav__item {
    justify-content: center;
    padding: var(--space-2);
  }
  html[data-nav-collapsed='true'] .nav__label {
    display: none;
  }

  #main {
    padding-top: calc(var(--topbar-height) + var(--space-5));
    margin-inline-start: var(--sidenav-width);
    transition: margin-inline-start var(--dur-slow) var(--ease-standard);
  }
  html[data-nav-collapsed='true'] #main {
    margin-inline-start: var(--sidenav-width-collapsed);
  }
  body.has-player #main {
    padding-bottom: var(--space-9);
  }

  /* The player floats as a rounded card beside the rail on desktop. */
  #playerbar {
    inset-inline-start: calc(var(--sidenav-width) + var(--space-4));
    transition: inset-inline-start var(--dur-slow) var(--ease-standard);
  }
  html[data-nav-collapsed='true'] #playerbar {
    inset-inline-start: calc(var(--sidenav-width-collapsed) + var(--space-4));
  }
}

/* ==========================================================================
   Mobile "More" drawer (bottom sheet)
   ========================================================================== */
.nav-drawer-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer-overlay);
  background: var(--color-overlay);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-standard);
}
body.nav-drawer-open .nav-drawer-overlay {
  opacity: 1;
  pointer-events: auto;
}

.nav-drawer {
  position: fixed;
  bottom: 0;
  inset-inline: 0;
  z-index: var(--z-drawer);
  max-height: 78vh; /* pre-dvh fallback */
  max-height: 78dvh;
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow: var(--shadow-lg);
  transform: translateY(105%);
  visibility: hidden;
  transition:
    transform var(--dur-slow) var(--ease-standard),
    visibility 0s linear var(--dur-slow);
}
body.nav-drawer-open .nav-drawer {
  transform: translateY(0);
  visibility: visible;
  transition: transform var(--dur-slow) var(--ease-spring);
}

/* The hamburger next to the brand gets a slightly larger glyph so its
   optical weight matches the 30px brand mark (both sit on the same
   44px centerline — the alignment the hostile review flagged). */

.nav-drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5) var(--space-2);
  position: relative;
}

/* The iOS-style grab handle: signals "this sheet slides down". */
.nav-drawer__head::before {
  content: '';
  position: absolute;
  top: var(--space-1_5);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  width: 38px;
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--color-border-strong);
}

.nav-drawer__title {
  font-size: var(--fs-md);
  font-weight: 700;
  margin-top: var(--space-2);
}

.nav-drawer__body {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-2) var(--space-3) calc(var(--space-5) + env(safe-area-inset-bottom, 0));
}

.nav-drawer__body .nav__group + .nav__group {
  margin-top: var(--space-4);
}

.nav-drawer__body .nav__group-label {
  padding: var(--space-1) var(--space-3) var(--space-1);
  margin-bottom: 0;
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.nav-drawer__body .nav__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 56px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: var(--color-text-secondary);
  font-size: var(--fs-md);
  font-weight: 500;
}
.nav-drawer__body .nav__item svg {
  flex-shrink: 0;
}
.nav-drawer__body .nav__item:hover {
  background: var(--color-surface-alt);
  color: var(--color-text);
  text-decoration: none;
}
.nav-drawer__body .nav__item[aria-current='page'] {
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
  color: var(--color-primary-text);
  font-weight: 600;
}
.nav-drawer__body .nav__item:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus) inset;
}

/* ==========================================================================
   Focus mode — full-bleed, chrome hidden
   ========================================================================== */
body.is-focus-mode #topbar,
body.is-focus-mode #bottomnav,
body.is-focus-mode .nav-drawer,
body.is-focus-mode .nav-drawer-overlay,
body.is-focus-mode #playerbar {
  display: none !important;
}
body.is-focus-mode #main {
  margin: 0;
  max-width: none;
  padding: 0;
}
body.is-focus-mode {
  overflow: hidden;
}

/* ==========================================================================
   (v4.4) TRUE fullscreen Mushaf — the book claims every pixel
   --------------------------------------------------------------------------
   Same contract as focus mode, plus the desktop rail margins (the rail IS
   #bottomnav at ≥960px, and #main carries its margin-inline-start) and the
   scroll lock moves INSIDE the page's text column, so the illuminated
   frame, medallions and page number stay pinned while the ayahs flow.
   Body class toggled by app/renderer.js from state.mushafFullscreen.
   ========================================================================== */
/* (v4.5) The Mushaf route claims a WIDE reading column — a spread's two
   facing pages need far more than the standard content column. Scoped to
   the route via a body class the renderer toggles; TRUE fullscreen still
   overrides this below (its #main rules are later + stricter). */
body.is-mushaf-view #main {
  max-width: 92rem;
}

/* (v4.5) Classic-reader immersive mode: the study reader hides its chrome
   and widens the reading column. The playerbar STAYS — recitation follow-
   along is part of an immersive reading session, not chrome. */
body.is-reader-immersive #topbar,
body.is-reader-immersive #bottomnav,
body.is-reader-immersive .nav-mobile-bar,
body.is-reader-immersive .nav-drawer,
body.is-reader-immersive .nav-drawer-overlay {
  display: none !important;
}
body.is-reader-immersive #main {
  max-width: 58rem;
}
body.is-reader-immersive .view-header {
  border-block-end: none;
}

body.is-mushaf-fullscreen #topbar,
body.is-mushaf-fullscreen #bottomnav,
body.is-mushaf-fullscreen .nav-mobile-bar,
body.is-mushaf-fullscreen .nav-drawer,
body.is-mushaf-fullscreen .nav-drawer-overlay,
body.is-mushaf-fullscreen #playerbar,
/* (v5.2.0) Ambient nightstand display: same chrome-hiding contract. */
body.is-ambient #topbar,
body.is-ambient #bottomnav,
body.is-ambient .nav-mobile-bar,
body.is-ambient .nav-drawer,
body.is-ambient .nav-drawer-overlay,
body.is-ambient #playerbar {
  display: none !important;
}
body.is-mushaf-fullscreen #main {
  margin: 0 !important;
  max-width: none;
  padding: 0;
  overflow: hidden;
}
body.is-mushaf-fullscreen {
  overflow: hidden;
}

/* v4.1 — landscape safe areas (notched phones in landscape keep the
   bottom nav and player clear of the sensor housing).
   (v5.1.0) THE COLLAPSED-RAIL ICON FIX (complained about since v4.4):
   this rule used to be bare `@media (orientation: landscape)`, which
   matches EVERY desktop viewport — and #bottomnav carries the
   .bottomnav class, so desktops silently paid 24px of horizontal
   padding inside a 76px collapsed rail. With the scroller's own padding
   and the scrollbar, the rail's content box fell below 24px and the nav
   icons (svg max-width:100%) squeezed to 16-19px — the "tiny
   indistinguishable icons" report. Scoped to <960px, the desktop rail
   now keeps its full width and the icons render at the same 24px they
   show when the rail is expanded. */
@media (orientation: landscape) and (max-width: 959px) {
  .bottomnav,
  #playerbar .player-bar {
    padding-inline: max(var(--space-3), env(safe-area-inset-left, 0px))
      max(var(--space-3), env(safe-area-inset-right, 0px));
  }
  #main {
    padding-inline: max(var(--space-4), env(safe-area-inset-left, 0px))
      max(var(--space-4), env(safe-area-inset-right, 0px));
  }
}

/* v4.1 — Boot skeleton: shown by app/boot.js between shell mount and the
   first real render (the content-library download). Mirrors the content
   column so the swap into the Home view causes no layout jump. */
.boot-skeleton {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  max-width: var(--content-max-width);
  margin: 0 auto;
  padding: 18vh var(--space-5) var(--space-8);
  text-align: center;
}
.boot-skeleton__mark {
  font-size: 2.4rem;
  color: var(--color-primary-text);
  line-height: 1;
}
.boot-skeleton__title {
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--color-text);
}
.boot-skeleton__lines {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: min(320px, 80%);
}
