/* ==========================================================================
   NEXISTEK — Preloader
   The arrival curtain. Self-contained: every rule here is scoped to
   .preloader, and the whole thing is dormant unless <html> carries
   `.is-loading` (set by boot.js before first paint, removed when the page is
   ready or when the boot failsafe fires).
   ========================================================================== */

.preloader {
  position: fixed;
  inset: 0;
  z-index: var(--z-preloader);

  display: grid;
  grid-template-rows: 1fr auto;
  align-items: center;
  justify-items: center;
  padding: var(--gutter);

  background: var(--c-void);
  color: var(--text-primary);

  /* Dormant by default — a no-JS document never sees it. */
  visibility: hidden;
  opacity: 0;
  pointer-events: none;

  /* The lift: the curtain travels off the top, delayed just enough for the
     stage to have faded first, so the page is revealed and not wiped. */
  transform: translate3d(0, -101%, 0);
  transition: transform var(--dur-cinematic) var(--ease-in-out) 220ms,
    visibility 0s linear calc(var(--dur-cinematic) + 220ms);
}

:root.is-loading .preloader {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
  transform: none;
  transition: none;
}

/* Nothing behind the curtain may scroll, and a reload must not restore the
   previous scroll position underneath it. */
:root.is-loading,
:root.is-loading body {
  overflow: hidden;
}

/* Every other fixed layer stays out of the way until the curtain has gone. */
:root.is-loading .site-header,
:root.is-loading .scroll-progress,
:root.is-loading .skip-link {
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}

/* --------------------------------------------------------------------------
   Field — the light the mark sits in
   -------------------------------------------------------------------------- */
.preloader__field {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(
      42rem 32rem at 50% 42%,
      rgb(var(--rgb-primary) / 0.16),
      transparent 68%
    ),
    radial-gradient(
      28rem 24rem at 50% 100%,
      rgb(var(--rgb-accent) / 0.07),
      transparent 70%
    );
}

/* A faint machined grid, so the void reads as a room rather than a hole. */
.preloader__field::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
      90deg,
      rgb(var(--rgb-text) / 0.028) 1px,
      transparent 1px
    ),
    linear-gradient(rgb(var(--rgb-text) / 0.028) 1px, transparent 1px);
  background-size: 4.5rem 4.5rem;
  -webkit-mask-image: radial-gradient(60% 55% at 50% 45%, #000, transparent 75%);
  mask-image: radial-gradient(60% 55% at 50% 45%, #000, transparent 75%);
}

/* --------------------------------------------------------------------------
   Stage — mark, wordmark, tagline
   -------------------------------------------------------------------------- */
.preloader__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-5);
  text-align: center;

  transition: opacity var(--dur-slow) var(--ease-in),
    transform var(--dur-slow) var(--ease-in);
}

/* Curtain leaving: the stage goes first, on its own, with no delay. */
:root:not(.is-loading) .preloader__stage {
  opacity: 0;
  transform: translate3d(0, -1.25rem, 0);
}

.preloader__mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 8.5rem;
  height: 8.5rem;
}

.preloader__glyph {
  width: 3.75rem;
  height: auto;
  filter: drop-shadow(0 0 26px rgb(var(--rgb-primary) / 0.55));
  animation: preloader-glyph 2.8s var(--ease-in-out) infinite;
}

.preloader__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid var(--border-hairline);
}

/* One live arc per ring, counter-rotating — a machine spinning up. */
.preloader__ring::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  border: 1px solid transparent;
  border-top-color: var(--c-primary);
  border-right-color: rgb(var(--rgb-accent) / 0.45);
  animation: preloader-spin 1.5s linear infinite;
}

.preloader__ring--slow {
  inset: 1.25rem;
  border-color: rgb(var(--rgb-text) / 0.05);
}

.preloader__ring--slow::after {
  border-top-color: transparent;
  border-bottom-color: rgb(var(--rgb-primary) / 0.6);
  animation-duration: 2.6s;
  animation-direction: reverse;
}

.preloader__brand {
  display: flex;
  gap: 0.18em;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 5.5vw, 2.75rem);
  font-weight: 500;
  letter-spacing: var(--tracking-widest);
  text-indent: var(--tracking-widest); /* offsets the trailing letter-space */
  line-height: var(--lh-snug);
}

.preloader__brand > span {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 0.6em, 0);
  animation: preloader-letter var(--dur-cinematic) var(--ease-out) forwards;
  animation-delay: calc(var(--i) * 70ms + 120ms);
}

.preloader__tagline {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-tertiary);
  opacity: 0;
  animation: preloader-letter var(--dur-cinematic) var(--ease-out) 620ms forwards;
}

/* --------------------------------------------------------------------------
   Meter — status, rail, counter
   -------------------------------------------------------------------------- */
.preloader__meter {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--sp-3) var(--sp-5);
  width: min(100%, var(--container-narrow));
  padding-bottom: var(--sp-4);

  opacity: 0;
  animation: preloader-letter var(--dur-cinematic) var(--ease-out) 480ms forwards;
}

.preloader__status,
.preloader__count {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.preloader__status {
  color: var(--text-secondary);
}

.preloader__count {
  color: var(--text-energised);
  font-variant-numeric: tabular-nums;
  justify-self: end;
}

.preloader__count i {
  font-style: normal;
  opacity: 0.5;
}

.preloader__rail {
  grid-column: 1 / -1;
  grid-row: 2;
  position: relative;
  height: 2px;
  background: rgb(var(--rgb-text) / 0.09);
  overflow: hidden;
}

.preloader__fill {
  position: absolute;
  inset: 0;
  background: var(--gradient-energy);
  box-shadow: var(--glow-sm);
  transform: scaleX(0);
  transform-origin: left center;
}

/* --------------------------------------------------------------------------
   Keyframes
   -------------------------------------------------------------------------- */
@keyframes preloader-spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes preloader-glyph {
  0%,
  100% {
    transform: scale(1);
    filter: drop-shadow(0 0 22px rgb(var(--rgb-primary) / 0.45));
  }
  50% {
    transform: scale(1.06);
    filter: drop-shadow(0 0 40px rgb(var(--rgb-primary) / 0.75));
  }
}

@keyframes preloader-letter {
  to {
    opacity: 1;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Reduced motion — the curtain still holds the page, it just doesn't perform.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .preloader,
  .preloader__stage {
    transition-duration: 1ms;
    transition-delay: 0s;
  }

  .preloader__glyph,
  .preloader__ring::after {
    animation: none;
  }

  .preloader__brand > span,
  .preloader__tagline,
  .preloader__meter {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

:root.is-low-motion .preloader__glyph,
:root.is-low-motion .preloader__ring::after {
  animation: none;
}

:root.is-low-motion .preloader__brand > span,
:root.is-low-motion .preloader__tagline,
:root.is-low-motion .preloader__meter {
  opacity: 1;
  transform: none;
  animation: none;
}

/* --------------------------------------------------------------------------
   Small screens
   -------------------------------------------------------------------------- */
@media (max-width: 30rem) {
  .preloader__mark {
    width: 6.5rem;
    height: 6.5rem;
  }

  .preloader__glyph {
    width: 3rem;
  }

  .preloader__ring--slow {
    inset: 0.9rem;
  }
}
