/* Boot CSS — the app-shell styles that must apply BEFORE the JS bundle loads,
   referenced render-blocking from index.html (a <link> in <head> paints the
   black page + "Loading..." label from the first frame, so a slow bundle can
   never flash an unstyled page). Its job is ONE thing: keep the page black
   with the "Loading..." label until the app boots and fades it out.
   Everything else (menus, modals, HUD) is rendered by React only after the
   bundle + CSS modules have loaded, so those need no boot-time rules — they
   cannot exist before their styles do. */

/* Self-hosted project font loads early so the loading label can use it
   before the main stylesheet has finished loading. */
@font-face {
  font-display: swap;
  font-family: 'Jersey 10';
  font-weight: 400;
  src: url('/fonts/Jersey10-Regular.ttf') format('truetype');
}

html,
body {
  background: #000;
  margin: 0;
  overflow: hidden;
  padding: 0;
}

/* Pre-React fallback label: index.html's body is React-only now, so before
   the bundle mounts the #loading-overlay this ::after is the only markup on
   screen. Once the overlay element exists (BootOverlay mounts), :has() hides
   the fallback and the overlay itself takes over — the overlay is opaque
   black at z-index 9999, so there is never a visible double label. */
body::after {
  bottom: 2rem;
  color: #fff;
  content: 'Loading...';
  font-family: 'Jersey 10', monospace;
  font-size: 2rem;
  left: 2rem;
  letter-spacing: 0.08em;
  opacity: 0.85;
  position: fixed;
  text-transform: uppercase;
}

body:has(#loading-overlay)::after {
  display: none;
}

#loading-overlay {
  background: #000;
  inset: 0;
  position: fixed;
  transition: opacity 200ms ease;
  z-index: 9999;
}

/* Fade the black boot overlay out instead of removing it in one frame — a
   hard remove flashed the black body for a frame on every post-load
   transition (a quick black flicker). The overlay is removed from the DOM
   once the fade finished (see MainMenu.show). */
#loading-overlay.is-fading {
  opacity: 0;
  pointer-events: none;
}

.loading-text {
  bottom: 2rem;
  color: #fff;
  font-family: 'Jersey 10', monospace;
  font-size: 2rem;
  left: 2rem;
  letter-spacing: 0.08em;
  opacity: 0.85;
  position: absolute;
  text-transform: uppercase;
}

/* Boot loading bar — sits above the "Loading…" label and shows the real
   phase: determinate fill while the Phaser loader pulls the atlas files, an
   animated shimmer while the async work (signed-asset authorization,
   procedural texture baking) has no progress to report. Driven by
   src/utils/loadingBar.ts. */
.loading-bar-wrap {
  bottom: 5rem;
  left: 2rem;
  position: absolute;
  width: 240px;
}

.loading-bar {
  background: rgb(255 255 255 / 0.08);
  border: 2px solid rgb(255 255 255 / 0.28);
  box-shadow: 0 2px 0 rgb(0 0 0 / 0.4);
  height: 16px;
  overflow: hidden;
  padding: 2px;
}

.loading-bar-fill {
  background: #39e;
  box-shadow: 0 0 8px rgb(51 153 238 / 0.6);
  height: 100%;
  transition: width 160ms ease;
  width: 0%;
}

/* No determinate progress available — fill the track and run a light stripe
   across it. Full width on purpose: a partial-width sweep block read as "the
   bar is stuck half-loaded" instead of "working". The width transition fills
   the last determinate position to 100% in one smooth move, then the stripe
   keeps moving until the menu takes the overlay down. */
.loading-bar-fill.is-indeterminate {
  animation: loading-bar-shimmer 1.2s linear infinite;
  background-image: linear-gradient(90deg, #39e 0%, #8ecdfa 50%, #39e 100%);
  background-size: 200% 100%;
  width: 100%;
}

@keyframes loading-bar-shimmer {
  from {
    background-position: 200% 0;
  }

  to {
    background-position: -200% 0;
  }
}
