/* Telón de carga: cubre la página mientras se prepara lo que, de otro modo,
   se construiría durante el primer scroll. Sin JavaScript no existe. */
.varve-loader {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-content: center; justify-items: center; gap: 28px;
  background: #d7c8b4; color: #292b25;
  font-family: Space, Arial, sans-serif;
  touch-action: none; overscroll-behavior: contain;
  transition: opacity .7s ease, visibility 0s linear .7s;
}
html[data-loading='done'] .varve-loader { opacity: 0; visibility: hidden; pointer-events: none; }
.varve-loader-mark {
  font-size: clamp(26px, 3.2vw, 40px); font-weight: 400; letter-spacing: .33em; line-height: 1;
  animation: varve-loader-in .6s .1s both;
}
.varve-loader-mark > span { letter-spacing: 0; }
.varve-loader-line {
  width: min(180px, 42vw); height: 1px; overflow: hidden;
  background: #292b2526;
  animation: varve-loader-in .6s .25s both;
}
/* Sólo transform: avanza en el compositor aunque el hilo principal esté ocupado. */
.varve-loader-line > i {
  display: block; height: 100%; background: #4b5a3e;
  transform-origin: left center; transform: scaleX(var(--varve-load, 0));
  transition: transform .5s ease-out;
}
.varve-loader-text {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
/* Detrás del telón opaco, la noche y el primer cuadro de la película se pintan una
   vez (1 %): su decodificación y subida a la GPU no caen en el primer scroll.
   Al levantarse el telón estas reglas dejan de aplicar y rige intro.css intacto. */
html[data-loading='true'] .night-image[src] { opacity: .01; }
html[data-loading='true'] .film { opacity: .01; }
@keyframes varve-loader-in { from { opacity: 0; } to { opacity: 1; } }
