/*
  Dizzy: two ring patterns fill the window behind the post. Each one is seen
  double, a blue and a magenta copy side by side. Their centres spiral in
  towards each other while one zooms in and the other zooms out, so the moiré
  between them swirls. The copies merge and turn grey, both patterns meet in
  the middle, and then they slowly blur and fade away until they're gone.
  The title and opening line pulse into focus, leaving a soft blurry ghost behind.

  The rings are drawn with custom properties (centre angle and distance, ring
  size, split, tint) so the centres can move without the layers' edges showing.
  With reduced motion, none of this happens.
*/
@property --angle  { syntax: "<angle>";      inherits: false; initial-value: 0deg; }
@property --reach  { syntax: "<length>";     inherits: false; initial-value: 0px; }
@property --ring   { syntax: "<length>";     inherits: false; initial-value: 20px; }
@property --split  { syntax: "<length>";     inherits: false; initial-value: 0px; }
@property --tint   { syntax: "<percentage>"; inherits: false; initial-value: 0%; }

@media (prefers-reduced-motion: no-preference) {
  body::before,
  body::after {
    --ring: max(16px, 1.6vmax);
    --x: calc(50% + cos(var(--angle)) * var(--reach));
    --y: calc(50% + sin(var(--angle)) * var(--reach));
    --line-a: color-mix(in srgb, color-mix(in srgb, var(--color) var(--tint), var(--color-text)) 40%, transparent);
    --line-b: color-mix(in srgb, color-mix(in srgb, #e20de9 var(--tint), var(--color-text)) 40%, transparent);

    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
      repeating-radial-gradient(circle at calc(var(--x) - var(--split)) var(--y),
        transparent 0 calc(var(--ring) * .65), var(--line-a) calc(var(--ring) * .65) var(--ring)),
      repeating-radial-gradient(circle at calc(var(--x) + var(--split)) var(--y),
        transparent 0 calc(var(--ring) * .65), var(--line-b) calc(var(--ring) * .65) var(--ring));
    opacity: 0;
  }

  /* The fade only fills forwards, so it doesn't hold the rings faint while they're still moving */
  body::before { animation: moire-zoom-in 8s cubic-bezier(.1, .7, .05, 1) both, moire-fade 10s cubic-bezier(.2, .6, .1, 1) 4s forwards; }
  body::after  { animation: moire-zoom-out 8s cubic-bezier(.1, .7, .05, 1) both, moire-fade 10s cubic-bezier(.2, .6, .1, 1) 4s forwards; }

  h1.main-title,
  main > p:first-of-type {
    text-shadow: .1em .05em 5px color-mix(in srgb, currentColor 18%, transparent);
  }

  /* First only the opening line is there: its three sentences (spans in the post)
     float in one by one, big and readable, stepped down like stairs so they don't
     overlap. Then they shrink back into the line together, the title pulses into
     focus, and the rest of the page fades in around them.
     They grow from their left edge, so they stay on screen on a phone too. */
  main > p:first-of-type > span {
    --big: 1.7;
    display: inline-block;
    transform-origin: 0 50%;
    animation: float-in .9s cubic-bezier(.2, .7, .3, 1) both, settle 2.4s cubic-bezier(.4, 0, .1, 1) 3s forwards;
  }

  main > p:first-of-type > span:nth-child(1) { --dy: -2.2em; --fx: -1.5em; --fy: -.5em; }
  main > p:first-of-type > span:nth-child(2) { --dy: 0em;    --fx: 0em;    --fy: 1.5em; animation-delay: .6s, 3s; }
  main > p:first-of-type > span:nth-child(3) { --dy: 2.2em;  --fx: 1.5em;  --fy: .5em;  animation-delay: 1.2s, 3s; }

  /* Small phones: the last sentence wraps to its own line and would run off the screen at full size */
  @media (max-width: 380px) {
    main > p:first-of-type > span { --big: 1.4; }
  }

  h1.main-title {
    animation: refocus-ghost 1.8s ease-in-out 4s both;
  }

  main > :not(h1, p:first-of-type),
  body > header,
  body > footer {
    animation: fade-in 1.8s ease-out 4.4s both;
  }
}

@keyframes float-in {
  from { opacity: 0; filter: blur(8px); transform: translate(var(--fx), calc(var(--dy) + var(--fy))) scale(1.3); }
  to   { opacity: 1; filter: blur(0);   transform: translate(0, var(--dy)) scale(var(--big)); }
}

/* Only fills forwards, so it doesn't take over from float-in before it starts */
@keyframes settle {
  from { transform: translate(0, var(--dy)) scale(var(--big)); }
  to   { transform: none; }
}

@keyframes fade-in {
  from { opacity: 0; }
}

/* Only from and to, so each centre travels one smooth spiral without stopping or turning back */
@keyframes moire-zoom-in {
  from { --angle: -400deg; --reach: 35vmax; --ring: max(48px, 4.8vmax); --split: 3vmax; --tint: 100%; opacity: 1;   filter: blur(0); }
  to   { --angle: 0deg;    --reach: 0px;    --ring: max(16px, 1.6vmax); --split: 0px;   --tint: 0%;   opacity: .12; filter: blur(2px); }
}

@keyframes moire-zoom-out {
  from { --angle: 180deg; --reach: 35vmax; --ring: max(6px, .6vmax);   --split: 3vmax; --tint: 100%; opacity: 1;   filter: blur(0); }
  to   { --angle: 500deg; --reach: 0px;    --ring: max(16px, 1.6vmax); --split: 0px;   --tint: 0%;   opacity: .12; filter: blur(2px); }
}

@keyframes moire-fade {
  from { opacity: .12; filter: blur(2px); }
  to   { opacity: 0;   filter: blur(12px); }
}

@keyframes refocus-ghost {
  0%   { filter: blur(6px); opacity: 0;  text-shadow: .4em .1em 8px color-mix(in srgb, currentColor 45%, transparent); }
  30%  { filter: blur(1px); opacity: 1;  text-shadow: .2em .07em 6px color-mix(in srgb, currentColor 30%, transparent); }
  45%  { filter: blur(3px); }
  70%  { filter: blur(.3px); }
  80%  { filter: blur(1px); }
  100% { filter: blur(0);   text-shadow: .1em .05em 5px color-mix(in srgb, currentColor 18%, transparent); }
}
