/* ============================================================
   NAV RAIL — liquid-glass section nav.
   Desktop (≥821px): vertical pill rail, fixed right, centered.
   Mobile (≤820px): bottom card carousel with scroll-snap.
   All nav-rail styling lives here (site.css stays frozen);
   the overrides block at the bottom neutralises what the rail
   supersedes elsewhere on the page.
   ============================================================ */

/* ---- shared: glass surface + type ---- */

.nvr {
  position: fixed;
  z-index: 30; /* same layer as the top bar; grain (40) textures the glass */
  font-family: 'Space Mono', monospace;
}

.nvr-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  position: relative;
  z-index: 1; /* above .nvr-scrim */
}

.nvr-item {
  position: relative;
  display: block;
  overflow: hidden;
  text-decoration: none;
  cursor: pointer;
  color: #F2F0EA;
  background: rgba(242, 240, 234, .05);
  border: 1px solid rgba(242, 240, 234, .14);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow:
    0 8px 28px rgba(0, 0, 0, .35),
    inset 0 1px 0 rgba(242, 240, 234, .10),
    inset 0 -1px 0 rgba(0, 0, 0, .28);
  transition:
    width .45s cubic-bezier(.34, 1.56, .64, 1),
    height .45s cubic-bezier(.34, 1.56, .64, 1),
    border-radius .45s cubic-bezier(.34, 1.56, .64, 1),
    background .35s ease,
    border-color .35s ease,
    color .35s ease,
    box-shadow .35s ease;
}

.nvr-item.is-active {
  background: rgba(242, 240, 234, .09);
  border-color: rgba(242, 240, 234, .22);
  box-shadow:
    0 8px 28px rgba(0, 0, 0, .35),
    inset 0 1px 0 rgba(242, 240, 234, .16),
    inset 0 -1px 0 rgba(0, 0, 0, .28);
}

.nvr-num {
  position: absolute;
  top: 11px;
  left: 15px;
  font-weight: 700;
  font-size: 10px;
  line-height: 1;
  letter-spacing: .18em;
  color: rgba(242, 240, 234, .55);
  transition: color .35s ease;
}

.nvr-label {
  position: absolute;
  bottom: 11px;
  left: 15px;
  font-weight: 400;
  font-size: 10px;
  line-height: 1;
  letter-spacing: .16em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(6px);
  transition:
    opacity .3s ease .06s,
    transform .34s cubic-bezier(.22, 1, .36, 1) .06s,
    bottom .34s cubic-bezier(.22, 1, .36, 1);
}

/* WORK pill extras: slide counter + hairline progress, JS-driven */
.nvr-count {
  position: absolute;
  top: 11px;
  right: 15px;
  font-weight: 400;
  font-size: 10px;
  line-height: 1;
  letter-spacing: .12em;
  color: rgba(242, 240, 234, .55);
  opacity: 0;
  transition: opacity .3s ease, color .35s ease;
}

.nvr-prog {
  position: absolute;
  left: 15px;
  right: 15px;
  bottom: 10px;
  height: 2px;
  background: rgba(242, 240, 234, .18);
  opacity: 0;
  transition: opacity .3s ease, background .35s ease;
}

.nvr-prog-fill {
  display: block;
  height: 100%;
  width: 0%;
  background: #F2F0EA;
  transition: background .35s ease;
}

.nvr-item.is-work-live .nvr-count,
.nvr-item.is-work-live .nvr-prog { opacity: 1 }
.nvr-item.is-work-live .nvr-label { bottom: 17px }

/* one soft throb — fired by JS on tap and whenever a pill grows or
   shrinks (active handoff, work-live widening) */
@keyframes nvr-pulse {
  0% { transform: scale(1) }
  35% { transform: scale(1.05) }
  100% { transform: scale(1) }
}

.nvr-item.is-pulse { animation: nvr-pulse .5s cubic-bezier(.22, 1, .36, 1) }

.nvr-item:focus-visible {
  outline: 2px solid #F2F0EA;
  outline-offset: 3px;
}

/* ---- light state: dark-ink glass over the pastel work panels.
        Per PILL, not per rail — while the pastel edge crosses the rail,
        pills still over the dark band keep the cream glass; each one
        flips as its own midpoint crosses the boundary. ---- */

.nvr-item.on-light {
  color: #1A1917;
  background: rgba(26, 25, 23, .07);
  border-color: rgba(26, 25, 23, .22);
  box-shadow:
    0 8px 24px rgba(26, 25, 23, .16),
    inset 0 1px 0 rgba(255, 255, 255, .40),
    inset 0 -1px 0 rgba(26, 25, 23, .10);
}

.nvr-item.on-light.is-active {
  background: rgba(26, 25, 23, .12);
  border-color: rgba(26, 25, 23, .34);
}

.nvr-item.on-light .nvr-num,
.nvr-item.on-light .nvr-count { color: rgba(26, 25, 23, .55) }
.nvr-item.on-light .nvr-prog { background: rgba(26, 25, 23, .15) }
.nvr-item.on-light .nvr-prog-fill { background: #1A1917 }
.nvr-item.on-light:focus-visible { outline-color: #1A1917 }
/* the rail-level class remains for the mobile scrim only */
.nvr.on-light .nvr-scrim { opacity: 0 }

/* ---- desktop: vertical rail, pill → card morph ---- */

@media (min-width: 821px) {
  .nvr {
    right: 24px;
    top: 50%;
    transform: translateY(-50%);
  }

  .nvr-list {
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
  }

  .nvr-item {
    width: 96px;
    height: 30px;
    border-radius: 15px; /* capsule when collapsed */
  }

  .nvr-item:focus-visible,
  .nvr-item.is-active {
    width: 124px;
    height: 58px;
    border-radius: 14px; /* the pill→card melt */
  }

  .nvr-item:focus-visible .nvr-label,
  .nvr-item.is-active .nvr-label {
    opacity: 1;
    transform: translateY(0);
  }

  @media (hover: hover) {
    .nvr-item:hover:not(.is-active) {
      height: 46px;
      border-radius: 14px;
    }
    .nvr-item:hover:not(.is-active) .nvr-label {
      opacity: .55;
      transform: translateY(0);
    }
  }

  .nvr-item.is-active.is-work-live { width: 148px }

  .nvr-scrim { display: none }
}

/* ---- mobile: bottom snap carousel ---- */

@media (max-width: 820px) {
  .nvr {
    left: 0;
    right: 0;
    bottom: 0;
    padding-bottom: max(10px, env(safe-area-inset-bottom));
  }

  .nvr-list {
    flex-direction: row;
    gap: 8px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain; /* a hard swipe must not become browser back-nav */
    /* half container minus half the ACTIVE card (128px + 2×1px border) so
       the end cards can reach dead center in the state that gets centered;
       % resolves against the container, which — unlike vw — excludes any
       classic scrollbar. */
    padding: 10px calc(50% - 65px);
    scrollbar-width: none;
  }

  .nvr-list::-webkit-scrollbar { display: none }

  .nvr-item {
    flex: 0 0 auto;
    width: 104px;
    height: 68px;
    border-radius: 14px;
    scroll-snap-align: center;
  }

  /* cards always show number + label; active is wider and brighter */
  .nvr-label {
    bottom: 14px;
    opacity: .9;
    transform: none;
  }

  .nvr-item.is-active { width: 128px }
  .nvr-item.is-active .nvr-label { opacity: 1 }
  .nvr-item.is-work-live .nvr-label { bottom: 18px }
  .nvr-prog { bottom: 11px }

  .nvr-scrim {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 110px;
    pointer-events: none;
    background: linear-gradient(to top, rgba(12, 12, 11, .5), transparent 70%);
    transition: opacity .35s ease;
  }
}

/* ---- reduced motion: states snap; the progress hairline stays
        scroll-tied (same precedent as the old #stk-bar) ---- */

@media (prefers-reduced-motion: reduce) {
  .nvr-item,
  .nvr-num,
  .nvr-label,
  .nvr-count,
  .nvr-prog,
  .nvr-scrim { transition: none }
  .nvr-item.is-pulse { animation: none }
}

/* ============================================================
   Overrides — things elsewhere on the page the rail supersedes.
   Kept here so site.css stays frozen.
   ============================================================ */

/* legacy stack progress UI (#stk-idx / #stk-bar wrappers) — the WORK
   pill carries index + progress now; hidden only when the rail booted */
html.nvr-live .stk-legacy { display: none !important }

/* clear the rail's band over the pinned work panels */
@media (min-width: 821px) {
  [data-slide] { padding-right: max(4.5vw, 150px) !important }
  /* note rows (homepage #notes + /notes/) end their date/read-time column
     under the rail otherwise */
  .note { padding-right: 130px }
}

@media (max-width: 820px) {
  /* hero footer row rises above the bottom bar */
  [data-intro="foot"] { bottom: 78px !important }
  /* page footer clears the bottom bar */
  #contact { padding-bottom: 150px !important }
}
