/* ==========================================================================
   Preloader
   --------------------------------------------------------------------------
   The brand mark is the through-line: it holds the centre of the screen while
   the page loads, then flies into its slot in the bottom nav. On an internal
   link click the same mark lifts back out of the nav and the panels close, so
   leaving a page is the entry sequence played backwards.

   The mark that flies is a *separate* element from the one in the nav bar.
   The real one is kept invisible until the flight lands, then swapped in — a
   single element cannot be both fixed-centre and inside the nav's layout.
   ========================================================================== */

.preloader {
   position: fixed;
   inset: 0;
   z-index: 9999;
   display: flex;
   align-items: center;
   justify-content: center;
   /* no pointer events on the panels themselves, but the overlay must block
      clicks on the page underneath while it is up */
   pointer-events: auto;
}

.preloader[hidden] {
   display: none;
}

/* --- the closing/opening panels ------------------------------------------ */

.preloader_panels {
   position: absolute;
   inset: 0;
   display: flex;
   z-index: 1;
}

.preloader_panel {
   flex: 1 1 0;
   background-color: #0a0a0a;
   /* a hairline between panels would show as a seam mid-wipe; overlap them
      instead so the wall reads as solid until it starts moving */
   margin-right: -1px;
   will-change: transform;
}

/* --- cursor light --------------------------------------------------------- */

.preloader_glow {
   position: absolute;
   z-index: 2;
   top: 0;
   left: 0;
   width: 620px;
   height: 620px;
   margin: -310px 0 0 -310px;
   border-radius: 50%;
   background: radial-gradient(circle closest-side,
         rgba(255, 255, 255, 0.075),
         rgba(255, 255, 255, 0.028) 45%,
         transparent 72%);
   opacity: 0;
   pointer-events: none;
   will-change: transform;
}

/* --- the mark ------------------------------------------------------------- */

/* The box is never transformed, so its rect is a stable measurement for the
   FLIP maths. Only what is inside it moves. */
.preloader_mark_box {
   position: relative;
   z-index: 3;
   width: 168px;
   line-height: 0;
   pointer-events: none;
}

/* the element the flight animates — perspective lives here so the tilt inside
   it reads as depth rather than a flat skew */
.preloader_mark {
   position: relative;
   display: block;
   width: 100%;
   perspective: 760px;
   transform-origin: 50% 50%;
   will-change: transform;
}

/* tilt is kept on its own element so it never fights the flight transform */
.preloader_mark_tilt {
   position: relative;
   display: block;
   width: 100%;
   transform-style: preserve-3d;
   will-change: transform;
}

.preloader_mark_ghost,
.preloader_mark_fill {
   display: block;
   width: 100%;
   height: auto;
}

/* the unlit state: present enough to read as the logo, dim enough that filling
   it is a visible event */
.preloader_mark_ghost {
   opacity: 0.16;
   filter: grayscale(1);
}

/* stacked exactly on top, revealed bottom-up as assets land */
.preloader_mark_fill {
   position: absolute;
   inset: 0;
   clip-path: inset(100% 0 0 0);
}

/* --- meta: counter, wordmark, rule ---------------------------------------- */

.preloader_meta {
   position: absolute;
   z-index: 3;
   left: 0;
   right: 0;
   bottom: 0;
   display: flex;
   align-items: flex-end;
   justify-content: space-between;
   gap: 20px;
   padding: 0 32px 34px;
   pointer-events: none;
}

.preloader_count {
   display: flex;
   font-family: 'Aeonik Mono', ui-monospace, monospace;
   font-size: 46px;
   line-height: 1;
   letter-spacing: -0.02em;
   color: #ffffff;
   font-variant-numeric: tabular-nums;
}

/* one digit window, one character tall — the strip inside slides */
.preloader_digit {
   display: block;
   height: 1.16em;
   overflow: hidden;
}

.preloader_digit_strip {
   display: block;
   will-change: transform;
}

.preloader_digit_strip>span {
   display: block;
   height: 1.16em;
   line-height: 1.16;
}

.preloader_word {
   font-family: 'Aeonik Mono', ui-monospace, monospace;
   font-size: 11px;
   letter-spacing: 0.26em;
   text-transform: uppercase;
   color: rgba(255, 255, 255, 0.42);
   padding-bottom: 6px;
}

/* the rule sits on the very bottom edge and fills with real progress */
.preloader_rule {
   position: absolute;
   z-index: 3;
   left: 0;
   bottom: 0;
   height: 1px;
   width: 100%;
   background-color: rgba(255, 255, 255, 0.12);
}

.preloader_rule span {
   display: block;
   height: 100%;
   width: 0;
   background-color: #ffffff;
   transform-origin: 0 50%;
}

/* --- page-side state ------------------------------------------------------ */

/* scroll is locked while the overlay is up; Lenis is stopped in JS to match */
body.is-loading {
   overflow: hidden;
}

/* The nav's own mark stays invisible until the flying one lands on it. Without
   this you briefly see two marks stacked at the same spot. */
body.is-flying .site_bottom_nav_brand img {
   opacity: 0;
}

@media (max-width: 767px) {
   .preloader_mark_box {
      width: 104px;
   }

   .preloader_meta {
      padding: 0 20px 26px;
   }

   .preloader_count {
      font-size: 34px;
   }

   .preloader_word {
      font-size: 9px;
      letter-spacing: 0.2em;
   }
}

/* Motion here is decorative — the page underneath is identical either way, so
   reduced-motion users get the content immediately with no wipe or flight. */
@media (prefers-reduced-motion: reduce) {

   .preloader_panel,
   .preloader_mark,
   .preloader_mark_tilt,
   .preloader_glow,
   .preloader_digit_strip,
   .preloader_rule span {
      transition: none !important;
      animation: none !important;
   }
}

/* Levelling the tilt before the flight: the ambient loop writes transform
   directly each frame, so the settle is a CSS transition rather than a tween —
   nothing else is left writing to that property once the loop has stopped. */
.preloader_mark_tilt.is-settling {
   transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}