/* ══ First-load loader ══
   A full-screen panel in the page's inverse, a hairline that fills across the
   top as the page's assets arrive, and a three-digit counter that climbs to
   100. When loading finishes the footer line slides up out of its own mask and
   the panel fades away behind it, revealing the page.

   Shape and timing follow cristinagomezruiz.com: the bar is a 1.5px rule
   inset from the top edge, the footer sits on the bottom edge, the exit runs
   at 300ms, and the panel's fade is held back 450ms so the line clears first.

   The markup sits inline at the top of <body> so the panel paints on the very
   first frame — a loader injected by script would flash the page first. */

.lo {
  position: fixed;
  inset: 0;
  z-index: 9995;
  overflow: hidden;
}

.lo-bg {
  position: absolute;
  inset: 0;
  background: var(--ink);
}

/* Once seen this session, the loader never runs again — an inline script in
   <head> sets this before the body paints, so there's no flash of the panel
   on internal navigation. */
html.lo-seen .lo { display: none; }
/* Nothing scrolls underneath while the panel is up */
html.lo-busy, html.lo-busy body { overflow: hidden; }

/* ── The bar — a hairline track with a fill driven from --lo-p (0 → 1) ── */
.lo-bar {
  position: absolute;
  top: 1.17vh;
  left: 1.39vw;
  width: 97.22vw;
  height: 1.5px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.3);
}
.lo-bar-fill {
  width: 100%;
  height: 100%;
  background: var(--bg);
  /* Parked fully to the left, sliding right into place as the count climbs */
  transform: translate3d(calc(var(--lo-p, 0) * 100% - 100%), 0, 0);
  will-change: transform;
}

/* ── Footer line — name on the left, counter on the right ── */
.lo-foot {
  position: absolute;
  bottom: 2.22vh;
  left: 1.39vw;
  right: 1.39vw;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  color: var(--bg);
  font-size: clamp(0.72rem, 0.97vw, 1rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.01em;
}
/* Each half rides in its own mask, so the exit slide is clipped cleanly */
.lo-mask { display: block; overflow: hidden; }
.lo-mask > span { display: block; will-change: transform; }

/* Tabular figures, so the counter doesn't jitter as digits change */
.lo-count { font-variant-numeric: tabular-nums; }

/* ── Exit ── */
.lo.is-out .lo-mask > span {
  transform: translateY(-110%);
  transition: transform 300ms var(--out-quart);
}
.lo.is-out .lo-bar {
  opacity: 0;
  transition: opacity 300ms linear;
}
.lo.is-out .lo-bg {
  opacity: 0;
  /* Held back 1.5× the exit duration, so the line is gone before the reveal */
  transition: opacity 300ms linear 450ms;
}

@media (prefers-reduced-motion: reduce) {
  .lo.is-out { display: none; }
}
