/* ─── Page loader ─────────────────────────────────────────────────────────
   Driven by assets/transition.js. The markup and inline boot script sit at the
   top of each page; the boot script only arms the loader on the first page of
   a visit.

   The overlay only shows once the boot script in <head> has added html.rl-js,
   and that script skips reduced motion and save-data, so visitors without
   JavaScript never see it. The markup also carries [hidden], so the page stays
   clean if this file fails to load, and the boot script removes the overlay
   after 5s if transition.js never reports in. The accent is used as light and
   line only: the panels themselves are the site's own background gradient. */

#rl-loader { display: none; }

html.rl-js #rl-loader {
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #131c30 0%, #0d1424 30%, #10131f 65%, #070b14 100%);
  will-change: transform;
  /* No CSS animation may sit on this element: a non-compositable one (the
     old visibility failsafe) pins its transform animations to the main
     thread. The net for a transition.js that never runs is a timer in the
     boot script instead. */
}

/* A faint pool of light behind the mark. */
html.rl-js #rl-loader::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(440px 320px at 50% 45%, rgba(106,166,226,0.12) 0%, rgba(106,166,226,0.04) 52%, transparent 76%);
  animation: rl-fade 1.4s ease .05s both;
}

.rl-loader__brand {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: -3vh;
  transition: opacity .34s ease-out, transform .6s cubic-bezier(.5,0,.75,0);
}
.rl-loader__mark {
  display: block;
  width: 72px;
  height: 72px;
  animation: rl-mark-in 1s cubic-bezier(.16,1,.3,1) .04s both;
}
.rl-loader__word {
  margin-top: 12px;
  font-family: "Source Sans 3", system-ui, sans-serif;
  font-weight: 500;
  font-size: 19px;
  line-height: 1.2;
  letter-spacing: .06em;
  color: #f2f6fc;
  white-space: nowrap;
  animation: rl-word-in 1.1s cubic-bezier(.16,1,.3,1) .18s both;
}
.rl-loader__river {
  display: block;
  width: 200px;
  height: 34px;
  margin-top: 14px;
  overflow: visible;
  filter: drop-shadow(0 0 3px rgba(72,215,254,0.55)) drop-shadow(0 0 10px rgba(106,166,226,0.35));
}
.rl-loader__line,
.rl-loader__trail,
.rl-loader__glint { fill: none; stroke-linecap: round; }
.rl-loader__line {
  stroke-width: 1.6;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 101;
  animation: rl-draw .9s cubic-bezier(.6,0,.3,1) .12s forwards;
}
/* A glint of light rides the tip while the line draws, then keeps travelling
   downstream: a short bright core with a faint tail behind it. Both dashes
   end at the same point, so their keyframes differ only by dash length. */
.rl-loader__trail {
  stroke-width: 2.2;
  stroke-opacity: .38;
  stroke-dasharray: 22 160;
  stroke-dashoffset: 22;
  animation: rl-trail-lead .9s cubic-bezier(.6,0,.3,1) .12s both,
             rl-trail 2.4s cubic-bezier(.45,0,.3,1) 1.5s infinite;
}
.rl-loader__glint {
  stroke-width: 2.2;
  stroke-dasharray: 5 160;
  stroke-dashoffset: 5;
  animation: rl-glint-lead .9s cubic-bezier(.6,0,.3,1) .12s both,
             rl-glint 2.4s cubic-bezier(.45,0,.3,1) 1.5s infinite;
}

/* Exit: stop catching the pointer at once; the brand lifts away ahead of the panel. */
#rl-loader.is-exiting { pointer-events: none; }
#rl-loader.is-exiting .rl-loader__brand { opacity: 0; transform: translateY(-28px); }

/* Liquid edge drawn by transition.js under a moving panel. */
.rl-edge {
  position: absolute;
  left: 0;
  width: 100%;
  top: calc(100% - 2px);
  display: block;
  overflow: visible;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  #rl-loader { display: none !important; }
}
@media print {
  #rl-loader { display: none !important; }
}

@keyframes rl-fade { from { opacity: 0; } }
@keyframes rl-mark-in {
  from { opacity: 0; transform: translateY(10px) scale(.9); filter: blur(8px); }
}
@keyframes rl-word-in {
  from { opacity: 0; transform: translateY(6px); letter-spacing: .22em; }
}
@keyframes rl-draw { to { stroke-dashoffset: 0; } }
/* A dash's front sits at L along the path when offset = dash length - L.
   Lead: L runs 0 -> 100 on the draw's own curve, so the light sits exactly on
   the drawing tip, then fades as the line completes. Loop: L runs 0 -> 122,
   fully off the far end. */
@keyframes rl-glint-lead {
  from { stroke-dashoffset: 5; stroke-opacity: 1; }
  80% { stroke-opacity: 1; }
  to { stroke-dashoffset: -95; stroke-opacity: 0; }
}
@keyframes rl-glint {
  0% { stroke-dashoffset: 5; stroke-opacity: 1; }
  62%, 100% { stroke-dashoffset: -117; stroke-opacity: 1; }
}
@keyframes rl-trail-lead {
  from { stroke-dashoffset: 22; stroke-opacity: .38; }
  80% { stroke-opacity: .38; }
  to { stroke-dashoffset: -78; stroke-opacity: 0; }
}
@keyframes rl-trail {
  0% { stroke-dashoffset: 22; stroke-opacity: .38; }
  62%, 100% { stroke-dashoffset: -100; stroke-opacity: .38; }
}
