/* Page loader ("ink"): the logo outline draws itself, ink fills it from
   below, the mark launches out. Shown once per browser session - the inline
   script in <head> adds html.no-loader on repeat page views, and
   js/page-loader.js hides it after the page has loaded. */

/* the loader is always the dark version, whatever theme the page uses */
:root {
  --pl-bg: #0f1013;
  --pl-fg: #f2f2f4;
  --pl-dot: #2b2d33;
  --pl-glow: rgba(255, 255, 255, 0.16);
}

/* the page behind must not scroll while the loader is up */
html.is-loading,
html.is-loading body {
  overflow: hidden;
}

html.no-loader .page-loader {
  display: none;
}

.page-loader {
  --cycle: 3.4s;
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: grid;
  place-items: center;
  background-color: var(--pl-bg);
  background-image: radial-gradient(var(--pl-dot) 1px, transparent 1.6px);
  background-size: clamp(24px, 2.5vw, 48px) clamp(24px, 2.5vw, 48px);
  background-position: center center;
  transition: opacity 0.6s ease, visibility 0.6s;
}
.page-loader::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(60% 60% at 50% 50%, transparent 20%, var(--pl-bg) 100%);
  pointer-events: none;
}
.page-loader.is-done {
  opacity: 0;
  visibility: hidden;
}

.loader-stage {
  position: relative;
  width: 140px;
  height: 140px;
  display: grid;
  place-items: center;
}

/* soft light behind the mark, breathing with the fill */
.loader-glow {
  position: absolute;
  width: 500px;
  height: 500px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--pl-glow) 0%, transparent 62%);
  filter: blur(60px);
  animation: ink-glow var(--cycle) cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

.loader-mark {
  position: relative;
  width: 82px;
  height: 120px;
  animation: ink-mark var(--cycle) cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
.loader-mark svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  display: block;
}

/* solid mark, revealed bottom-up with a soft ink front */
.loader-fill {
  color: var(--pl-fg);
  -webkit-mask-image: linear-gradient(to top, #000 0 44%, transparent 56% 100%);
          mask-image: linear-gradient(to top, #000 0 44%, transparent 56% 100%);
  -webkit-mask-size: 100% 200%;
          mask-size: 100% 200%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  animation: ink-fill var(--cycle) cubic-bezier(0.22, 1, 0.36, 1) infinite;
}
.loader-fill path {
  fill: currentColor;
}

/* inner outline: svg has no inside stroke, so it is drawn twice as wide and
   clipped to the silhouette, leaving only the inner half */
.loader-stroke {
  color: var(--pl-fg);
}
.loader-stroke .stroke-paths {
  clip-path: url(#ink-clip);
}
.loader-stroke path {
  fill: none;
  stroke: currentColor;
  stroke-width: 4px;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* pathLength="1" normalises both outlines to 0..1; the dash is a hair
     longer than the path so the loop closes without a seam */
  stroke-dasharray: 1.01;
  stroke-dashoffset: 1.01;
}
.loader-stroke .p-swoosh {
  animation: ink-draw-a var(--cycle) cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.loader-stroke .p-foot {
  animation: ink-draw-b var(--cycle) cubic-bezier(0.65, 0, 0.35, 1) infinite;
}

/* timeline: 0–28% swoosh outline, 6–34% foot outline, 20–62% fill rises
   while the outline crossfades out under it (38–62%), 82–96% launch */
@keyframes ink-draw-a {
  0%        { stroke-dashoffset: 1.01; opacity: 1; }
  28%, 38%  { stroke-dashoffset: 0;    opacity: 1; }
  62%, 100% { stroke-dashoffset: 0;    opacity: 0; }
}
@keyframes ink-draw-b {
  0%, 6%    { stroke-dashoffset: 1.01; opacity: 1; }
  34%, 38%  { stroke-dashoffset: 0;    opacity: 1; }
  62%, 100% { stroke-dashoffset: 0;    opacity: 0; }
}
@keyframes ink-fill {
  0%, 20%   { -webkit-mask-position: 0 0;    mask-position: 0 0; }
  62%, 100% { -webkit-mask-position: 0 100%; mask-position: 0 100%; }
}
@keyframes ink-mark {
  0%, 82%   { transform: scale(1);   opacity: 1; }
  96%       { transform: scale(1.7); opacity: 0; }
  100%      { transform: scale(1);   opacity: 0; }
}
@keyframes ink-glow {
  0%        { transform: scale(0.6);  opacity: 0; }
  62%       { transform: scale(1);    opacity: 1; }
  82%       { transform: scale(1.05); opacity: 0.9; }
  96%, 100% { transform: scale(1.7);  opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .page-loader * {
    animation: none !important;
  }
  .loader-stroke {
    display: none;
  }
  .loader-glow {
    opacity: 0.8;
  }
  .loader-fill {
    -webkit-mask-position: 0 100%;
            mask-position: 0 100%;
  }
}
