/* ===========================================================================
   Page transition loader
   A full-screen veil with a green spinner shown while moving between pages.
   The markup is created by page-loader.js, so this file only has to style it.
   =========================================================================== */

.zv-pl {
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: grid;
  place-items: center;
  background: #000;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  /* Kept out of the layout entirely: it can never cause a reflow, a
     scrollbar, or a horizontal overflow on the page underneath. */
  transition: opacity 320ms cubic-bezier(0.4, 0, 0.2, 1),
              visibility 0s linear 320ms;
}

.zv-pl[data-state="in"] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;   /* swallow clicks so the page cannot be double-navigated */
  transition: opacity 320ms cubic-bezier(0.4, 0, 0.2, 1), visibility 0s;
}

/* ---- centre stack -------------------------------------------------------- */
.zv-pl__box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  transform: translateY(8px) scale(0.97);
  opacity: 0;
  transition: transform 460ms cubic-bezier(0.16, 1, 0.3, 1),
              opacity 380ms ease-out;
}
.zv-pl[data-state="in"] .zv-pl__box {
  transform: none;
  opacity: 1;
}

/* ---- the spinner --------------------------------------------------------- */
.zv-pl__spin {
  position: relative;
  width: 92px;
  height: 92px;
  display: grid;
  place-items: center;
}

/* Soft green bloom behind the ring, breathing gently. */
.zv-pl__glow {
  position: absolute;
  inset: -18px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(20, 153, 84, 0.34) 0%, rgba(20, 153, 84, 0) 68%);
  animation: zv-pl-breathe 2.4s ease-in-out infinite;
}

.zv-pl__ring {
  width: 100%;
  height: 100%;
  display: block;
  transform-origin: 50% 50%;
}

/* ---- the logo, dead centre of the ring -----------------------------------
   It is a sibling of .zv-pl__ring, not a child, so the rotate() animation
   applied to the arcs can never reach it. `animation: none` plus an explicit
   `transform: none` makes that guarantee local and obvious rather than
   something you have to reason about from the DOM shape. */
.zv-pl__logo {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px;
  display: grid;
  place-items: center;
  pointer-events: none;
  animation: none !important;
  transform: none !important;
}
.zv-pl__logo svg {
  width: 100%;
  height: 100%;
  display: block;
  fill: none;
  stroke: #ffffff;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Track: barely visible, so the arc has something to read against. */
.zv-pl__track {
  fill: none;
  stroke: rgba(255, 255, 255, 0.07);
  stroke-width: 3;
}

/* The travelling arc. */
.zv-pl__arc {
  fill: none;
  stroke: #149954;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 96 243;
  transform-origin: 50% 50%;
  animation: zv-pl-spin 1150ms cubic-bezier(0.5, 0.1, 0.4, 0.9) infinite;
}

/* A brighter, slower inner ring adds depth without looking busy. */
.zv-pl__arc2 {
  fill: none;
  stroke: rgba(20, 153, 84, 0.45);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 34 302;
  transform-origin: 50% 50%;
  animation: zv-pl-spin-rev 1900ms linear infinite;
}

@keyframes zv-pl-spin     { to { transform: rotate(360deg); } }
@keyframes zv-pl-spin-rev { to { transform: rotate(-360deg); } }
@keyframes zv-pl-breathe {
  0%, 100% { transform: scale(0.9);  opacity: 0.55; }
  50%      { transform: scale(1.08); opacity: 1; }
}

/* ---- wordmark ------------------------------------------------------------ */
.zv-pl__mark {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--zv-pl-font, 'ZenDigits', 'Source Sans Pro', 'Rubik', 'Roboto', -apple-system, sans-serif);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #fff;
}

/* ---- destination + progress line ----------------------------------------- */
.zv-pl__path {
  max-width: min(78vw, 420px);
  font-family: var(--zv-pl-mono, ui-monospace, 'JetBrains Mono', Menlo, Consolas, monospace);
  font-size: 12px;
  color: rgba(255, 255, 255, 0.42);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;          /* keep the meaningful tail visible when it clips */
  text-overflow: ellipsis;
}

.zv-pl__bar {
  width: min(78vw, 240px);
  height: 2px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.zv-pl__bar span {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, #0d6b3a, #149954, #2ee68a);
  transition: width 240ms linear;
}

/* ---- hint ---------------------------------------------------------------- */
.zv-pl__hint {
  font-size: 11px;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.26);
}

/* ===========================================================================
   Reduced motion
   The veil still appears and still waits - only the movement is removed, so
   someone who asked for less motion does not get a spinning graphic but also
   does not lose the transition feedback entirely.
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .zv-pl,
  .zv-pl__box,
  .zv-pl__bar span {
    transition-duration: 1ms !important;
  }
  .zv-pl__arc,
  .zv-pl__arc2,
  .zv-pl__glow {
    animation: none !important;
  }
  /* A static arc plus a filled bar still reads as "working", and the logo in
     the middle is already static so nothing else to do here. */
  .zv-pl__arc  { stroke-dasharray: 150 189; }
  .zv-pl__arc2 { stroke-dasharray: 60 276; opacity: 0.5; }
  .zv-pl__box  { transform: none; }
}
