/* cgbrio intro loader (T2 v7: 1.35 s; the colour floods inside the white frame and brightens,
   the reveal opens the whole screen from its edges; small 60 fps sprite logo on top, fades last).
   Self-contained: intro.css + intro.js + logo-sprite.webp.
   Fail-open: #intro is hidden by default; the root animation shows it for the
   duration of the intro and hides it again. Without CSS animations the page is usable.
   Animated properties: transform (sprite frames), opacity, clip-path, visibility, SVG stroke-dashoffset. */

.intro {
  /* ---- tuning block ---------------------------------------------------- */
  --intro-color: #0070C0;        /* blue through the flood and the hold ... */
  --intro-color-bright: #D2F6FF; /* ... whitens in the hold, almost white when the reveal starts */
  --intro-frame-color: #fff;
  --intro-frame-width: 2px;
  --intro-frame-inset: 12px;
  --intro-radius: 28px;
  --intro-logo-size: min(14vmin, 121px);
  --intro-reveal-r: 72vmax;  /* reveal circle start radius; exact half-diagonal where hypot() works */

  --t-frame-start: 0s;      /* white frame drawn clockwise */
  --t-frame-dur: 0.2s;
  --t-flood-start: 0.3s;    /* short pause after the frame closes; colour floods in; frame fades */
  --t-flood-dur: 0.25s;     /* fast start, slows down (--ease-flood-fill); then hold 0.55-0.70 */
  --t-logo-start: 0s;       /* logo assembly: 48 sprite frames at 60 fps = 0.8 s */
  --t-logo-dur: 0.8s;
  --t-logo-in-dur: 0.6s;    /* logo fades in at the start (the first frames are tiny, keep it visible) */
  --t-logo-pop-start: 0.33s; /* the colour reaches the logo at ~0.37-0.40 s (ease-out flood) */
  --t-logo-pop-dur: 0.5s;   /* squash (anticipation) -> overshoot -> settle (follow-through) */
  --intro-logo-pop: 1.18;   /* peak scale of the pop */
  --intro-glow-color: 143, 228, 255; /* soft glow under the logo (r, g, b) */
  --intro-glow-size: calc(var(--intro-logo-size) * 2.4);
  --t-glow-pulse-start: 0.33s; /* glow swells with the pop, then calms down */
  --t-glow-pulse-dur: 0.75s;
  --t-glow-in-dur: 0.5s;    /* base glow fades in slowly at the start */
  --t-ring-start: 0.38s;    /* ring behind the logo: appears when the colour reaches the logo, */
  --t-ring-dur: 0.6s;       /* expands and fades out completely */
  --intro-ring-scale: 3.5;
  --t-sparks-start: 0.38s;  /* particles burst from the logo with the circle, drift, and are */
  --t-sparks-dur: 0.85s;    /* cut away by the shrinking reveal circle (they live inside it) */
  --intro-spark-alpha: 0.3;  /* particles are barely visible */
  --intro-spark-reach: 1.15; /* multiplier of every particle distance (--d) */
  --intro-spark-size: 1.1;   /* multiplier of every particle size (--s) */
  --t-bright-start: 0.5s;   /* colour whitens from the end of the flood ... */
  --t-bright-dur: 0.25s;    /* ... to just after the reveal starts */
  --t-reveal-start: 0.7s;   /* colour layer shrinks to centre, site shows from the edges */
  --t-reveal-dur: 0.5s;     /* noticeably slower than the flood */
  --t-logo-out-start: 1.2s; /* logo stays on top until the reveal has closed, then fades out */
  --t-logo-out-dur: 0.1s;
  --t-end: 1.3s;           /* overlay hidden (= end of the logo fade) */

  --ease-frame: cubic-bezier(.65, 0, .35, 1);
  --ease-flood: cubic-bezier(.7, 0, .3, 1);
  --ease-flood-fill: cubic-bezier(.16, 1, .3, 1); /* flood: sharp start, long slow-down */
  --ease-reveal: cubic-bezier(.35, 0, .85, .5);    /* reveal circle: slow start, accelerating to the end */
  --ease-logo-out: ease-out;
  /* ---------------------------------------------------------------------- */

  position: fixed;
  inset: 0;
  z-index: 2147483000;
  visibility: hidden;
  pointer-events: none;
  animation: intro-root var(--t-end) linear both;
}

@supports (width: hypot(1px, 1px)) {
  .intro { --intro-reveal-r: hypot(50vw, 50vh); }
}

html.intro-off #intro { display: none; }

/* JS holds the whole timeline until the logo sprite is decoded (or 1.2 s). */
html.intro-wait #intro,
html.intro-wait #intro *,
html.intro-wait #intro *::before,
html.intro-wait #intro *::after { animation-play-state: paused; }

/* Reveal window: black background + colour; in the reveal a CIRCLE shrinks to the centre
   (page shows from all screen edges). Start radius = half the screen diagonal (--intro-reveal-r). */
.intro__reveal {
  position: absolute;
  inset: 0;
  clip-path: circle(var(--intro-reveal-r) at 50% 50%);
  background: #000;
  animation: intro-reveal-circle var(--t-reveal-dur) var(--ease-reveal) var(--t-reveal-start) both;
}
/* Colour = the inside of the white frame (same rect and radius); outside it stays black. */
.intro__color,
.intro__black {
  position: absolute;
  inset: var(--intro-frame-inset);
  border-radius: var(--intro-radius);
}
.intro__color { background: var(--intro-color); }
.intro__color::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--intro-color-bright);
  animation: intro-fade-in var(--t-bright-dur) ease-in-out var(--t-bright-start) both;
}
/* Black hole over the colour, shrinking from the frame line to the centre = flood. */
.intro__black {
  background: #000;
  clip-path: inset(0 round var(--intro-radius));
  animation: intro-shrink-hide var(--t-flood-dur) var(--ease-flood-fill) var(--t-flood-start) both;
}

.intro__frame {
  position: absolute;
  inset: var(--intro-frame-inset);
  width: calc(100% - 2 * var(--intro-frame-inset));
  height: calc(100% - 2 * var(--intro-frame-inset));
  overflow: visible;
  animation: intro-fade-out var(--t-flood-dur) var(--ease-flood) var(--t-flood-start) both;
}
.intro__frame-rect {
  width: 100%;
  height: 100%;
  rx: var(--intro-radius);
  fill: none;
  stroke: var(--intro-frame-color);
  stroke-width: var(--intro-frame-width);
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: intro-draw var(--t-frame-dur) var(--ease-frame) var(--t-frame-start) both;
}

/* Glow under the logo: base (fades in with the logo) + bright core (pulses with the pop).
   Outer element fades out together with the logo. */
.intro__glow {
  position: absolute;
  inset: 0;
  margin: auto;
  width: var(--intro-glow-size);
  height: var(--intro-glow-size);
  animation: intro-fade-out var(--t-logo-out-dur) var(--ease-logo-out) var(--t-logo-out-start) both;
}
.intro__glow::before,
.intro__glow::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
}
.intro__glow::before {
  background: radial-gradient(closest-side, rgba(var(--intro-glow-color), .18), rgba(var(--intro-glow-color), .06) 55%, rgba(var(--intro-glow-color), 0));
  animation: intro-fade-in var(--t-glow-in-dur) ease-in-out var(--t-logo-start) both;
}
.intro__glow::after {
  background: radial-gradient(closest-side, rgba(var(--intro-glow-color), .55), rgba(var(--intro-glow-color), .2) 45%, rgba(var(--intro-glow-color), 0));
  opacity: 0;
  animation: intro-glow-pulse var(--t-glow-pulse-dur) linear var(--t-glow-pulse-start) both;
}

/* Filled circle behind the logo: appears when the colour arrives, expands, fades out. */
.intro__ring {
  position: absolute;
  inset: 0;
  margin: auto;
  width: var(--intro-logo-size);
  height: var(--intro-logo-size);
  border-radius: 50%;
  background: rgba(var(--intro-glow-color), .55);
  opacity: 0;
  animation: intro-ring var(--t-ring-dur) cubic-bezier(.2, .7, .3, 1) var(--t-ring-start) both;
}

/* Particles: each <i> flies out along its angle (--a) to --d logo sizes, shrinking and fading. */
.intro__sparks {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 0;
  height: 0;
}
.intro__sparks i {
  --sz: calc(var(--s) * var(--intro-spark-size));
  position: absolute;
  left: calc(var(--sz) / -2);
  top: calc(var(--sz) / -2);
  width: var(--sz);
  height: var(--sz);
  border-radius: 50%;
  background: rgb(var(--intro-glow-color));
  opacity: 0;
  animation: intro-spark var(--t-sparks-dur) linear var(--t-sparks-start) both;
}
.intro__sparks i:nth-child(1) { --a: -0.6deg; --d: 2.73; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.032s); }
.intro__sparks i:nth-child(2) { --a: 17.1deg; --d: 1.97; --s: 8px; animation-delay: calc(var(--t-sparks-start) + 0.033s); }
.intro__sparks i:nth-child(3) { --a: 27.1deg; --d: 1.97; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.021s); }
.intro__sparks i:nth-child(4) { --a: 33.7deg; --d: 3.22; --s: 10px; animation-delay: calc(var(--t-sparks-start) + 0.044s); }
.intro__sparks i:nth-child(5) { --a: 52.6deg; --d: 2.40; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.046s); }
.intro__sparks i:nth-child(6) { --a: 65.7deg; --d: 1.92; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.058s); }
.intro__sparks i:nth-child(7) { --a: 71.9deg; --d: 1.67; --s: 5px; animation-delay: calc(var(--t-sparks-start) + 0.042s); }
.intro__sparks i:nth-child(8) { --a: 93.3deg; --d: 2.25; --s: 8px; animation-delay: calc(var(--t-sparks-start) + 0.059s); }
.intro__sparks i:nth-child(9) { --a: 103.1deg; --d: 2.87; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.0s); }
.intro__sparks i:nth-child(10) { --a: 110.7deg; --d: 2.90; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.07s); }
.intro__sparks i:nth-child(11) { --a: 134.5deg; --d: 3.27; --s: 10px; animation-delay: calc(var(--t-sparks-start) + 0.018s); }
.intro__sparks i:nth-child(12) { --a: 144.5deg; --d: 2.63; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.005s); }
.intro__sparks i:nth-child(13) { --a: 157.5deg; --d: 2.40; --s: 6px; animation-delay: calc(var(--t-sparks-start) + 0.027s); }
.intro__sparks i:nth-child(14) { --a: 172.6deg; --d: 3.30; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.015s); }
.intro__sparks i:nth-child(15) { --a: 185.1deg; --d: 1.70; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.069s); }
.intro__sparks i:nth-child(16) { --a: 191.6deg; --d: 1.75; --s: 10px; animation-delay: calc(var(--t-sparks-start) + 0.014s); }
.intro__sparks i:nth-child(17) { --a: 207.8deg; --d: 2.28; --s: 6px; animation-delay: calc(var(--t-sparks-start) + 0.023s); }
.intro__sparks i:nth-child(18) { --a: 224.1deg; --d: 3.12; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.009s); }
.intro__sparks i:nth-child(19) { --a: 233.9deg; --d: 1.62; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.056s); }
.intro__sparks i:nth-child(20) { --a: 240.4deg; --d: 2.73; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.036s); }
.intro__sparks i:nth-child(21) { --a: 263.0deg; --d: 3.12; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.045s); }
.intro__sparks i:nth-child(22) { --a: 265.4deg; --d: 2.45; --s: 5px; animation-delay: calc(var(--t-sparks-start) + 0.0s); }
.intro__sparks i:nth-child(23) { --a: 287.2deg; --d: 3.55; --s: 8px; animation-delay: calc(var(--t-sparks-start) + 0.021s); }
.intro__sparks i:nth-child(24) { --a: 300.3deg; --d: 2.02; --s: 7px; animation-delay: calc(var(--t-sparks-start) + 0.07s); }
.intro__sparks i:nth-child(25) { --a: 309.8deg; --d: 2.75; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.069s); }
.intro__sparks i:nth-child(26) { --a: 318.0deg; --d: 2.12; --s: 8px; animation-delay: calc(var(--t-sparks-start) + 0.023s); }
.intro__sparks i:nth-child(27) { --a: 331.8deg; --d: 1.75; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.015s); }
.intro__sparks i:nth-child(28) { --a: 348.8deg; --d: 1.62; --s: 6px; animation-delay: calc(var(--t-sparks-start) + 0.026s); }

/* Second, finer layer: smaller, fainter, more numerous and much farther. Same keyframes;
   per-layer overrides of the spark variables. Rules come after the main layer on purpose. */
.intro__sparks--fine {
  --intro-spark-alpha: 0.3;
  --intro-spark-size: 1.4;
  --intro-spark-reach: 1;
}
.intro__sparks--fine i:nth-child(1) { --a: 3.4deg; --d: 7.77; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.002s); }
.intro__sparks--fine i:nth-child(2) { --a: 6.6deg; --d: 5.21; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.013s); }
.intro__sparks--fine i:nth-child(3) { --a: 13.9deg; --d: 5.5; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.062s); }
.intro__sparks--fine i:nth-child(4) { --a: 27.8deg; --d: 3.98; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.042s); }
.intro__sparks--fine i:nth-child(5) { --a: 32.8deg; --d: 6.8; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.077s); }
.intro__sparks--fine i:nth-child(6) { --a: 38.6deg; --d: 3.66; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.066s); }
.intro__sparks--fine i:nth-child(7) { --a: 50.1deg; --d: 7.87; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.057s); }
.intro__sparks--fine i:nth-child(8) { --a: 60.2deg; --d: 7.86; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.066s); }
.intro__sparks--fine i:nth-child(9) { --a: 64.0deg; --d: 3.89; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.018s); }
.intro__sparks--fine i:nth-child(10) { --a: 73.5deg; --d: 7.06; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.018s); }
.intro__sparks--fine i:nth-child(11) { --a: 79.2deg; --d: 4.96; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.02s); }
.intro__sparks--fine i:nth-child(12) { --a: 86.9deg; --d: 3.94; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.057s); }
.intro__sparks--fine i:nth-child(13) { --a: 101.7deg; --d: 4.76; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.033s); }
.intro__sparks--fine i:nth-child(14) { --a: 105.3deg; --d: 4.8; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.089s); }
.intro__sparks--fine i:nth-child(15) { --a: 114.2deg; --d: 4.48; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.011s); }
.intro__sparks--fine i:nth-child(16) { --a: 125.0deg; --d: 6.68; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.024s); }
.intro__sparks--fine i:nth-child(17) { --a: 131.3deg; --d: 7.63; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.01s); }
.intro__sparks--fine i:nth-child(18) { --a: 138.2deg; --d: 5.52; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.006s); }
.intro__sparks--fine i:nth-child(19) { --a: 146.6deg; --d: 3.61; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.069s); }
.intro__sparks--fine i:nth-child(20) { --a: 159.2deg; --d: 7.12; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.054s); }
.intro__sparks--fine i:nth-child(21) { --a: 167.5deg; --d: 6.87; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.002s); }
.intro__sparks--fine i:nth-child(22) { --a: 174.1deg; --d: 5.71; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.008s); }
.intro__sparks--fine i:nth-child(23) { --a: 179.7deg; --d: 4.38; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.095s); }
.intro__sparks--fine i:nth-child(24) { --a: 185.9deg; --d: 3.97; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.065s); }
.intro__sparks--fine i:nth-child(25) { --a: 197.9deg; --d: 6.01; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.025s); }
.intro__sparks--fine i:nth-child(26) { --a: 203.9deg; --d: 7.55; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.076s); }
.intro__sparks--fine i:nth-child(27) { --a: 214.0deg; --d: 5.37; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.09s); }
.intro__sparks--fine i:nth-child(28) { --a: 222.4deg; --d: 5.36; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.055s); }
.intro__sparks--fine i:nth-child(29) { --a: 228.5deg; --d: 4.84; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.061s); }
.intro__sparks--fine i:nth-child(30) { --a: 233.7deg; --d: 4.78; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.063s); }
.intro__sparks--fine i:nth-child(31) { --a: 244.1deg; --d: 6.02; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.025s); }
.intro__sparks--fine i:nth-child(32) { --a: 257.2deg; --d: 3.85; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.069s); }
.intro__sparks--fine i:nth-child(33) { --a: 258.7deg; --d: 7.49; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.08s); }
.intro__sparks--fine i:nth-child(34) { --a: 273.9deg; --d: 4.72; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.038s); }
.intro__sparks--fine i:nth-child(35) { --a: 280.5deg; --d: 4.14; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.02s); }
.intro__sparks--fine i:nth-child(36) { --a: 287.8deg; --d: 4.28; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.075s); }
.intro__sparks--fine i:nth-child(37) { --a: 298.2deg; --d: 5.39; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.048s); }
.intro__sparks--fine i:nth-child(38) { --a: 304.2deg; --d: 5.93; --s: 4px; animation-delay: calc(var(--t-sparks-start) + 0.018s); }
.intro__sparks--fine i:nth-child(39) { --a: 311.2deg; --d: 4.69; --s: 2px; animation-delay: calc(var(--t-sparks-start) + 0.023s); }
.intro__sparks--fine i:nth-child(40) { --a: 315.6deg; --d: 7.51; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.078s); }
.intro__sparks--fine i:nth-child(41) { --a: 328.7deg; --d: 6.22; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.068s); }
.intro__sparks--fine i:nth-child(42) { --a: 334.7deg; --d: 7.12; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.096s); }
.intro__sparks--fine i:nth-child(43) { --a: 342.4deg; --d: 5.24; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.089s); }
.intro__sparks--fine i:nth-child(44) { --a: 353.2deg; --d: 6.9; --s: 3px; animation-delay: calc(var(--t-sparks-start) + 0.054s); }

.intro__logo {
  position: absolute;
  inset: 0;
  margin: auto;
  width: var(--intro-logo-size);
  height: var(--intro-logo-size);
  overflow: hidden;
  animation:
    intro-pop var(--t-logo-pop-dur) linear var(--t-logo-pop-start) both,
    intro-fade-out var(--t-logo-out-dur) var(--ease-logo-out) var(--t-logo-out-start) both;
}
/* Sprite grid 8 x 6 of square frames (2048x1536, every side <= 4096 px for mobile GPU textures).
   One discrete keyframe per frame (step-end): frame i shows at t = i / 60 s, synced with the CSS
   timeline. Grid size is fixed by logo-sprite.webp: keep 800% / 600% and @keyframes intro-sprite
   (generated by Tools/intro/build_logo_assets.py --css) in sync with it. */
.intro__logo-strip {
  display: block;
  width: 800%;
  max-width: none;
  height: 600%;
  animation:
    intro-sprite var(--t-logo-dur) step-end var(--t-logo-start) both,
    intro-fade-in var(--t-logo-in-dur) ease-out var(--t-logo-start) both;
}

@keyframes intro-root {
  0%, 99.9% { visibility: visible; pointer-events: auto; }
  100% { visibility: hidden; pointer-events: none; }
}
@keyframes intro-draw {
  0% { stroke-dasharray: 1; stroke-dashoffset: 1; }
  99.9% { stroke-dasharray: 1; stroke-dashoffset: 0; }
  100% { stroke-dasharray: none; stroke-dashoffset: 0; }
}
@keyframes intro-reveal-circle {
  from { clip-path: circle(var(--intro-reveal-r) at 50% 50%); }
  to { clip-path: circle(0 at 50% 50%); }
}
@keyframes intro-shrink {
  from { clip-path: inset(0 round var(--intro-radius)); }
  to { clip-path: inset(50% round var(--intro-radius)); }
}
@keyframes intro-shrink-hide {
  from { clip-path: inset(0 round var(--intro-radius)); visibility: visible; }
  to { clip-path: inset(50% round var(--intro-radius)); visibility: hidden; }
}
@keyframes intro-fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes intro-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes intro-spark {
  /* rotate() points the X axis along the flight, so scale(x, y) stretches the spark along its motion */
  0%   { opacity: 0; transform: rotate(var(--a)) translateX(calc(var(--intro-logo-size) * .35)) scale(1.5, 1);
         animation-timing-function: cubic-bezier(.2, .7, .4, 1); }
  20%  { opacity: var(--intro-spark-alpha); }
  14%  { transform: rotate(var(--a)) translateX(calc(var(--intro-logo-size) * var(--d) * var(--intro-spark-reach) * .7)) scale(3.4, .7);
         animation-timing-function: cubic-bezier(.3, .6, .4, 1); }
  40%  { transform: rotate(var(--a)) translateX(calc(var(--intro-logo-size) * var(--d) * var(--intro-spark-reach))) scale(.8);
         animation-timing-function: linear; }
  100% { opacity: var(--intro-spark-alpha); transform: rotate(var(--a)) translateX(calc(var(--intro-logo-size) * var(--d) * var(--intro-spark-reach) * 1.15)) scale(.6); }
}
@keyframes intro-ring {
  0%   { opacity: 0;  transform: scale(.7); }
  12%  { opacity: 1; }
  100% { opacity: 0;  transform: scale(var(--intro-ring-scale)); }
}
@keyframes intro-glow-pulse {
  0%   { opacity: 0;   transform: scale(.8);  animation-timing-function: cubic-bezier(.2, .8, .3, 1); }
  30%  { opacity: 1;   transform: scale(1.3); animation-timing-function: cubic-bezier(.4, 0, .2, 1); }
  100% { opacity: 0;   transform: scale(1); }
}
/* Logo pop when the colour arrives: anticipation squash, fast overshoot, damped settle. */
@keyframes intro-pop {
  0%   { transform: scale(1);    animation-timing-function: cubic-bezier(.4, 0, .6, 1); }
  14%  { transform: scale(.93);  animation-timing-function: cubic-bezier(.2, .8, .3, 1); }
  42%  { transform: scale(var(--intro-logo-pop)); animation-timing-function: cubic-bezier(.5, 0, .5, 1); }
  66%  { transform: scale(.97);  animation-timing-function: cubic-bezier(.5, 0, .5, 1); }
  84%  { transform: scale(1.015); animation-timing-function: cubic-bezier(.5, 0, .5, 1); }
  100% { transform: scale(1); }
}
@keyframes intro-sprite {
  0% { transform: translate(calc(-100% / 8 * 0), calc(-100% / 6 * 0)); }
  2.0833% { transform: translate(calc(-100% / 8 * 1), calc(-100% / 6 * 0)); }
  4.1667% { transform: translate(calc(-100% / 8 * 2), calc(-100% / 6 * 0)); }
  6.25% { transform: translate(calc(-100% / 8 * 3), calc(-100% / 6 * 0)); }
  8.3333% { transform: translate(calc(-100% / 8 * 4), calc(-100% / 6 * 0)); }
  10.4167% { transform: translate(calc(-100% / 8 * 5), calc(-100% / 6 * 0)); }
  12.5% { transform: translate(calc(-100% / 8 * 6), calc(-100% / 6 * 0)); }
  14.5833% { transform: translate(calc(-100% / 8 * 7), calc(-100% / 6 * 0)); }
  16.6667% { transform: translate(calc(-100% / 8 * 0), calc(-100% / 6 * 1)); }
  18.75% { transform: translate(calc(-100% / 8 * 1), calc(-100% / 6 * 1)); }
  20.8333% { transform: translate(calc(-100% / 8 * 2), calc(-100% / 6 * 1)); }
  22.9167% { transform: translate(calc(-100% / 8 * 3), calc(-100% / 6 * 1)); }
  25% { transform: translate(calc(-100% / 8 * 4), calc(-100% / 6 * 1)); }
  27.0833% { transform: translate(calc(-100% / 8 * 5), calc(-100% / 6 * 1)); }
  29.1667% { transform: translate(calc(-100% / 8 * 6), calc(-100% / 6 * 1)); }
  31.25% { transform: translate(calc(-100% / 8 * 7), calc(-100% / 6 * 1)); }
  33.3333% { transform: translate(calc(-100% / 8 * 0), calc(-100% / 6 * 2)); }
  35.4167% { transform: translate(calc(-100% / 8 * 1), calc(-100% / 6 * 2)); }
  37.5% { transform: translate(calc(-100% / 8 * 2), calc(-100% / 6 * 2)); }
  39.5833% { transform: translate(calc(-100% / 8 * 3), calc(-100% / 6 * 2)); }
  41.6667% { transform: translate(calc(-100% / 8 * 4), calc(-100% / 6 * 2)); }
  43.75% { transform: translate(calc(-100% / 8 * 5), calc(-100% / 6 * 2)); }
  45.8333% { transform: translate(calc(-100% / 8 * 6), calc(-100% / 6 * 2)); }
  47.9167% { transform: translate(calc(-100% / 8 * 7), calc(-100% / 6 * 2)); }
  50% { transform: translate(calc(-100% / 8 * 0), calc(-100% / 6 * 3)); }
  52.0833% { transform: translate(calc(-100% / 8 * 1), calc(-100% / 6 * 3)); }
  54.1667% { transform: translate(calc(-100% / 8 * 2), calc(-100% / 6 * 3)); }
  56.25% { transform: translate(calc(-100% / 8 * 3), calc(-100% / 6 * 3)); }
  58.3333% { transform: translate(calc(-100% / 8 * 4), calc(-100% / 6 * 3)); }
  60.4167% { transform: translate(calc(-100% / 8 * 5), calc(-100% / 6 * 3)); }
  62.5% { transform: translate(calc(-100% / 8 * 6), calc(-100% / 6 * 3)); }
  64.5833% { transform: translate(calc(-100% / 8 * 7), calc(-100% / 6 * 3)); }
  66.6667% { transform: translate(calc(-100% / 8 * 0), calc(-100% / 6 * 4)); }
  68.75% { transform: translate(calc(-100% / 8 * 1), calc(-100% / 6 * 4)); }
  70.8333% { transform: translate(calc(-100% / 8 * 2), calc(-100% / 6 * 4)); }
  72.9167% { transform: translate(calc(-100% / 8 * 3), calc(-100% / 6 * 4)); }
  75% { transform: translate(calc(-100% / 8 * 4), calc(-100% / 6 * 4)); }
  77.0833% { transform: translate(calc(-100% / 8 * 5), calc(-100% / 6 * 4)); }
  79.1667% { transform: translate(calc(-100% / 8 * 6), calc(-100% / 6 * 4)); }
  81.25% { transform: translate(calc(-100% / 8 * 7), calc(-100% / 6 * 4)); }
  83.3333% { transform: translate(calc(-100% / 8 * 0), calc(-100% / 6 * 5)); }
  85.4167% { transform: translate(calc(-100% / 8 * 1), calc(-100% / 6 * 5)); }
  87.5% { transform: translate(calc(-100% / 8 * 2), calc(-100% / 6 * 5)); }
  89.5833% { transform: translate(calc(-100% / 8 * 3), calc(-100% / 6 * 5)); }
  91.6667% { transform: translate(calc(-100% / 8 * 4), calc(-100% / 6 * 5)); }
  93.75% { transform: translate(calc(-100% / 8 * 5), calc(-100% / 6 * 5)); }
  95.8333% { transform: translate(calc(-100% / 8 * 6), calc(-100% / 6 * 5)); }
  97.9167% { transform: translate(calc(-100% / 8 * 7), calc(-100% / 6 * 5)); }
  100% { transform: translate(calc(-100% / 8 * 7), calc(-100% / 6 * 5)); }
}
