/* ===========================================================================
   preloader-v2.css - the Ashley intro, transcribed

   Source: the "Ashley" creative-portfolio WordPress theme
   (Extras/ashley-creative-portfolio-wordpress-theme-2026-07-14-21-04-58-utc),
   ashley/style.css lines 1023-1077 for the preloader block, plus .mil-h3
   (l.235), .mil-thin (l.342) and .mil-muted (l.366) for the type.

   The mil- prefix is kept rather than renamed: it makes the provenance obvious,
   and grep confirms zero collisions - the string "mil-" appears nowhere in the
   Webflow bundle, nav-v2.css or the source markup.

   Motion lives in assets/js/preloader-v2.js. Markup is emitted by
   _build/localize.py (PRELOADER_V2, STRUCTURAL EDIT 7).

   Nothing here changed when the curtain became a loading mask (28 Aug 2026),
   and that is the point. Two of that pass's states are deliberately CSS-free:

   - The HOLD, when the sequence has ended but the hero is not decodable yet.
     It is "no rule at all": the words have already tweened out, the wrap has
     not started its outro, so what is on screen is `.mil-preloader`'s plain
     `background-color:#000`. A spinner or a pulse here would be a second thing
     to look at on a screen that is about to disappear, and would advertise a
     wait that is usually zero.

   - The SESSION SKIP, when a repeat visit inside the same browser session
     bypasses the word timeline. It reuses `.mil-preloader-animation`'s
     `opacity:0` start value and simply never raises it, so the same element
     renders as an empty black curtain for one ~0.4s cross-fade. No skip-only
     class, no second set of rules to keep in sync with the first.

   Deliberate differences from Ashley, and why:

   1. No position/inset/z-index here. The element carries BOTH classes -
      `class="preloader mil-preloader"` - and the Webflow bundle's .preloader
      already supplies `position:fixed; inset:0; z-index:10000`. Re-declaring
      Ashley's 9999 would only lower it. Ashley's own geometry was identical
      apart from that number.
   2. `background-color:#000` is added. Ashley inherited black from its theme
      body; .preloader here has no background at all - it sat over a video.
   3. Every rule is scoped inside .mil-preloader, including the .mil-h3 type
      scale. Unscoped, a 42px h3 rule would leak into a page that has its own
      adaptive --size-unit type system.
   4. `margin: 0` on the words. Ashley's reset zeroed <p> margins globally;
      Webflow's leaves a 10px bottom margin, which would push the two absolutely
      stacked rows out of alignment with each other.
   5. One extra breakpoint at 479px. "Online ISSB Preparation" is 23 characters
      on a single flex row - four more than Ashley's "Pioneering Creative
      Excellence" - and its 24px floor leaves no margin at 390px.
   =========================================================================== */

/* Outfit is Ashley's face, and the thin/medium contrast between the words is
   the entire effect. One file: Google Fonts ships Outfit as a variable font, so
   wght@100 and wght@500 resolve to the same woff2. See _build/fetch-fonts.sh.

   font-display:block, not swap: a fallback face flashing at 42px and then
   reflowing mid-animation is worse than a beat of nothing on a black screen.
   preloader-v2.js also waits on document.fonts before starting the timeline, so
   in practice the block period is not visible. */
@font-face {
  font-family: "Outfit";
  src: url("../fonts/Outfit-latin-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: block;
}

/* Scroll lock. ae() in the odyn bundle normally owns this, but the bundle is
   deferred until the intro finishes, so the intro has to hold it itself.
   preloader-v2.js removes the class as part of the handoff. */
html.issb-preloading {
  overflow: hidden;
}

.mil-preloader {
  background-color: rgb(0, 0, 0);
  pointer-events: none;
}

.mil-preloader .mil-preloader-animation {
  opacity: 0;
  position: relative;
  height: 100vh;
  color: rgb(255, 255, 255);
}

.mil-preloader .mil-preloader-animation .mil-pos-abs {
  position: absolute;
  height: 100vh;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.mil-preloader .mil-preloader-animation .mil-pos-abs p {
  opacity: 0;
  margin: 0 15px 0 0;
}

.mil-preloader .mil-preloader-animation .mil-pos-abs p:last-child {
  margin-right: 0;
}

/* Type. Order matters: .mil-thin and .mil-muted have the same specificity as
   .mil-h3 and win on source order, exactly as they do in Ashley's stylesheet. */
.mil-preloader .mil-h3 {
  font-family: "Outfit", sans-serif;
  font-size: 42px;
  font-weight: 500;
  line-height: 120%;
  color: rgb(0, 0, 0);
  word-wrap: break-word;
}

.mil-preloader .mil-muted {
  color: rgba(255, 255, 255, 0.9);
}

.mil-preloader .mil-thin {
  font-weight: 100;
}

/* The reveal frame: an orange bar sits over the word and wipes it clear.
   .mil-reveal-box has no width of its own - the timeline grows it to 100% of
   the frame, re-anchors it right, then collapses it back to 0. */
.mil-preloader .mil-preloader-animation .mil-pos-abs .mil-reveal-frame {
  position: relative;
  padding: 0 30px;
}

.mil-preloader .mil-preloader-animation .mil-pos-abs .mil-reveal-frame .mil-reveal-box {
  z-index: 4;
  position: absolute;
  opacity: 0;
  height: 100%;
  background-color: rgb(255, 152, 0);
}

@media screen and (max-width: 1024px) {
  .mil-preloader .mil-h3 {
    font-size: 36px;
  }
  .mil-preloader .mil-preloader-animation .mil-pos-abs p {
    font-size: 24px;
  }
}

@media screen and (max-width: 768px) {
  .mil-preloader .mil-h3 {
    font-size: 30px;
  }
}

/* See note 5 in the header. */
@media screen and (max-width: 479px) {
  .mil-preloader .mil-preloader-animation .mil-pos-abs p {
    font-size: 20px;
    margin-right: 10px;
  }
  .mil-preloader .mil-preloader-animation .mil-pos-abs .mil-reveal-frame {
    padding: 0 18px;
  }
}
