/* ==========================================================================
   Navigation loading indicator
   ==========================================================================
   Feedback for SPA navigation (see navLoadingStart/navLoadingDone in app.js), which
   otherwise leaves the whole UI motionless between the click and the #main-content
   swap. Both pieces below are paint-only — no size, spacing or flow changes — so they
   cannot shift the layout of the page they appear over. */

/* Thin progress bar pinned to the very top of the viewport. Above the sidebar (45),
   topbar (35) and open modals (95/96) so it stays visible wherever navigation is
   triggered from; it only ever occupies 2px at the top edge, so it never obscures
   anything it sits above. */
.nav-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 600;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s var(--ease);
}
.nav-progress.is-active,
.nav-progress.is-done { opacity: 1; }

.nav-progress-fill {
  width: 0;
  height: 100%;
  border-radius: 0 var(--radius-full) var(--radius-full) 0;
  background: linear-gradient(90deg, var(--color-primary), var(--color-primary-grad-end));
  box-shadow: 0 0 10px color-mix(in srgb, var(--color-primary) 55%, transparent);
}
/* Creeps toward — never reaching — 90% over a long, heavily decelerating curve: real
   progress is unknowable here (one fetch, no byte counter), and a bar that stalls at a
   plausible-looking 90% reads as "still working" where one that sat at 100% waiting for
   the swap would read as "finished, but stuck". */
.nav-progress.is-active .nav-progress-fill {
  width: 90%;
  transition: width 9s cubic-bezier(0.06, 0.72, 0.16, 1);
}
/* Completion is a separate, fast transition so the bar visibly lands before fading. */
.nav-progress.is-done .nav-progress-fill {
  width: 100%;
  transition: width 0.16s var(--ease);
}

/* The clicked sidebar item turns its own icon into a spinner: the icon box keeps its
   exact size (1.15rem, set on .icon), the glyph inside is just hidden and the same box
   picks up the ring — so the pill looks identical whether the sidebar is expanded or
   collapsed, and nothing reflows at either width. */
.nav-link.is-nav-pending > .icon > * { visibility: hidden; }
.nav-link.is-nav-pending > .icon {
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 28%, transparent);
  border-top-color: currentColor;
  animation: btn-spin 0.6s linear infinite;
}

/* The content still on screen belongs to the page being navigated away from — dimming
   it marks it as stale, and dropping pointer-events stops a second click landing on
   controls that are about to be replaced. Sidebar and topbar stay fully live, so
   changing your mind mid-load still works. */
body.nav-loading #main-content {
  opacity: 0.55;
  pointer-events: none;
  transition: opacity 0.18s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .nav-progress-fill,
  .nav-progress.is-active .nav-progress-fill,
  .nav-progress.is-done .nav-progress-fill { transition: none; }
  .nav-link.is-nav-pending > .icon { animation: none; }
  body.nav-loading #main-content { transition: none; }
}
