/* ==========================================================================
   nav.css - chapter-spine nav, mobile TOC sheet, reading progress, reveal
   --------------------------------------------------------------------------
   Enhancement layer for the Hyper Reality report. All of this is injected by
   JS; with JS off none of these elements exist. Styles stay in the report's
   register: ink on warm paper, hairlines, a single oxblood accent reserved
   for the active state. No new color tokens; reuses existing surface/ink/rule
   and --reveal-curve. Two layout tokens are introduced and documented below.
   ========================================================================== */

:root {
  /* Width of the stacked chapter-tab rail on the right edge. Sized to seat a
     rotated chapter name comfortably, like the reference's stacked tabs. */
  --spine-w: 2.4rem;
  /* z layer for the nav system, above content, below the skip-link (100). */
  --spine-z: 60;
}

/* ==========================================================================
   READING PROGRESS - a single hairline pinned to the very top
   ========================================================================== */
.read-progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: calc(var(--spine-z) + 5);
  background: transparent;
  pointer-events: none;
}
.read-progress__bar {
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: var(--accent);
  /* Smooths the per-frame scale updates without animating layout. */
  transition: transform 0.08s linear;
  will-change: transform;
}

/* ==========================================================================
   THE SPINE - fixed vertical stack of book-spine tabs, right edge
   ========================================================================== */
.spine {
  position: fixed;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  z-index: var(--spine-z);
  /* Sits in the gutter; the page-max content column never reaches the edge
     on wide screens, so it does not collide with the reading measure. */
  pointer-events: none;
  /* Never exceed the viewport height: on short viewports the rail scrolls
     internally (scrollbar hidden) instead of spilling off-screen. */
  max-height: 100vh;
  max-height: 100dvh;
  overflow-y: auto;
  scrollbar-width: none;
}
.spine::-webkit-scrollbar { display: none; }
.spine__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  border-left: var(--rule-hair) solid var(--rule);
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: saturate(1) blur(3px);
}
.spine__item + .spine__item .spine__tab {
  border-top: var(--rule-hair) solid var(--rule);
}

.spine__tab {
  position: relative;
  pointer-events: auto;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 0.65em;
  width: var(--spine-w);
  /* Stacked chapter tabs: a rotated name with a small numeral lead-in, set
     in a vertical writing mode so the label reads top-to-bottom like the
     reference's stacked tabs. Thin and understated. */
  padding-block: 0.6rem;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  text-decoration: none;
  color: var(--ink-soft);
  font-family: var(--font-body);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  line-height: 1;
  white-space: nowrap;
  background: transparent;
  transition: color 0.3s var(--reveal-curve), background-color 0.3s var(--reveal-curve);
}
.spine__tab:hover {
  color: var(--ink);
  background: color-mix(in srgb, var(--ink) 4%, transparent);
}
.spine__tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -3px;
  border-radius: 2px;
  color: var(--ink);
}

/* The rotated label text. Capped in the block (vertical) direction so a long
   chapter name clips with an ellipsis instead of blowing past the viewport
   height; the rail always fits. */
.spine__text {
  /* In vertical writing mode the inline axis runs top-to-bottom, so this caps
     how far a long name travels down the rail (ellipsis past the cap). */
  max-inline-size: 5rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Non-chapter tabs (Cover, Summary, Appendix, Diagnostic) read as short caps. */
.spine__item--plain .spine__text {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.6rem;
  color: var(--ink-faint);
}
.spine__num {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  transition: color 0.3s var(--reveal-curve);
}

/* Active tab: the one place the accent appears in the nav. */
.spine__tab.is-active {
  color: var(--ink);
}
.spine__tab.is-active .spine__num {
  color: var(--accent);
}
/* A short accent tick on the inner edge marks the active spine. */
.spine__tab.is-active::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 2px;
  height: 1.6rem;
  transform: translateY(-50%);
  background: var(--accent);
}

/* ==========================================================================
   MOBILE TOGGLE - single corner button, hidden on desktop
   ========================================================================== */
.spine-toggle {
  display: none;
  position: fixed;
  top: 0.85rem;
  right: 0.85rem;
  z-index: calc(var(--spine-z) + 2);
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: var(--rule-hair) solid var(--rule-strong);
  border-radius: 2px;
  background: var(--paper-raised);
  color: var(--ink);
  cursor: pointer;
  align-items: center;
  justify-content: center;
}
.spine-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.spine-toggle__bars,
.spine-toggle__bars::before,
.spine-toggle__bars::after {
  display: block;
  width: 1.05rem;
  height: 1.5px;
  background: var(--ink);
  position: relative;
}
.spine-toggle__bars::before,
.spine-toggle__bars::after {
  content: "";
  position: absolute;
  left: 0;
}
.spine-toggle__bars::before { top: -5px; }
.spine-toggle__bars::after { top: 5px; }

/* ==========================================================================
   MOBILE SHEET - full-screen TOC
   ========================================================================== */
.spine-sheet {
  position: fixed;
  inset: 0;
  z-index: calc(var(--spine-z) + 4);
  display: flex;
  justify-content: flex-end;
  background: color-mix(in srgb, var(--ink) 32%, transparent);
  opacity: 0;
  transition: opacity 0.32s var(--reveal-curve);
}
/* The hidden attribute must win over display:flex above, or the full-screen
   scrim would intercept pointer events while closed. */
.spine-sheet[hidden] { display: none; }
.spine-sheet.is-open { opacity: 1; }

.spine-sheet__panel {
  width: min(86vw, 22rem);
  height: 100%;
  background: var(--paper);
  border-left: var(--rule-hair) solid var(--rule-strong);
  padding: var(--space-l) var(--gutter) var(--space-l);
  overflow-y: auto;
  transform: translateX(100%);
  transition: transform 0.38s var(--reveal-curve);
  display: flex;
  flex-direction: column;
  gap: var(--space-m);
}
.spine-sheet.is-open .spine-sheet__panel { transform: translateX(0); }

.spine-sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: var(--space-xs);
  border-bottom: var(--rule-hair) solid var(--rule);
}
.spine-sheet__title { color: var(--ink-faint); }
.spine-sheet__close {
  width: 2.25rem;
  height: 2.25rem;
  border: 0;
  background: transparent;
  color: var(--ink-soft);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  border-radius: 2px;
}
.spine-sheet__close:hover { color: var(--ink); }
.spine-sheet__close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.spine-sheet__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.spine-sheet__item + .spine-sheet__item {
  border-top: var(--rule-hair) solid var(--rule);
}
.spine-sheet__link {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  padding-block: var(--space-xs);
  text-decoration: none;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.2;
}
.spine-sheet__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
.spine-sheet__num {
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  font-family: var(--font-body);
  min-width: 1.6em;
}
.spine-sheet__link.is-active,
.spine-sheet__link.is-active .spine-sheet__num {
  color: var(--accent);
}

/* Lock scroll behind the open sheet. */
.sheet-locked { overflow: hidden; }

/* ==========================================================================
   REVEAL ON SCROLL - applied by scroll.js; armed only when motion is allowed
   ========================================================================== */
.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 0.7s var(--reveal-curve),
    transform 0.7s var(--reveal-curve);
  will-change: opacity, transform;
}
.reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* ==========================================================================
   RESPONSIVE - swap spine for the toggle/sheet at <= 820px
   ========================================================================== */
@media (max-width: 820px) {
  .spine { display: none; }
  .spine-toggle { display: flex; }
}

/* ==========================================================================
   REDUCED MOTION - kill every transform/transition this layer adds.
   Content fully visible, progress bar still tracks (no smoothing).
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .reveal,
  .reveal.is-revealed {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .read-progress__bar { transition: none !important; }
  .spine__tab,
  .spine-sheet,
  .spine-sheet__panel {
    transition: none !important;
  }
}
