/* =====================================================================
   One spinner for the whole site.
   =====================================================================

   Two problems this replaces.

   1. Ovals. Every spinner was a square with a border and border-radius:50%.
      Inside a flex container that square gets stretched or squashed on one
      axis and the "circle" turns into an egg. Fixing it per spinner meant
      remembering flex: 0 0 auto and aspect-ratio every single time, and it
      was missed in most places.

   2. The whole ring visibly rotating. A border-top-color spinner has a hard
      edge where the coloured side meets the transparent side, so the eye
      follows the ring itself turning rather than a light travelling around a
      fixed circle.

   The fix for both: the ring is painted, not bordered. A conic gradient
   sweeps from the track colour to the accent colour, and a radial mask cuts
   the middle out to leave an annulus. The outline never moves, only the
   colour inside it, and because the gradient is the background of a square
   box with aspect-ratio 1 it cannot be anything but round.

   Loaded last on every page so it wins over the older per-page rules.

   Tunable per instance:
     --sp-size    outer diameter
     --sp-thick   ring thickness
     --sp-track   the dim part of the ring
     --sp-accent  the bright part that travels
     --sp-speed   one full lap
   ===================================================================== */

.spinner,
.loading-spinner:empty,
.dv-spinner,
.sg-modal-spinner,
.steam-spinner,
.sp-ring,
.is-loading::after {
  --sp-size: 2.5rem;
  --sp-thick: 3px;
  --sp-track: rgba(94, 234, 212, 0.16);
  --sp-accent: #5eead4;
  --sp-speed: 0.9s;

  box-sizing: border-box;
  width: var(--sp-size);
  height: var(--sp-size);
  /* Belt and braces against a flex or grid parent resizing one axis. */
  min-width: var(--sp-size);
  min-height: var(--sp-size);
  aspect-ratio: 1 / 1;
  flex: 0 0 auto;

  /* The old border version is switched off, the ring is painted now. */
  border: 0 !important;
  border-radius: 50%;
  padding: 0;

  background: conic-gradient(
    from 0deg,
    var(--sp-track) 0deg,
    var(--sp-track) 90deg,
    var(--sp-accent) 330deg,
    var(--sp-accent) 360deg
  );

  -webkit-mask: radial-gradient(
    farthest-side,
    #0000 calc(100% - var(--sp-thick)),
    #000 calc(100% - var(--sp-thick))
  );
  mask: radial-gradient(
    farthest-side,
    #0000 calc(100% - var(--sp-thick)),
    #000 calc(100% - var(--sp-thick))
  );

  animation: sp-sweep var(--sp-speed) linear infinite;
}

@keyframes sp-sweep {
  to {
    transform: rotate(1turn);
  }
}

/* The overlay spinner is positioned by its own margin, so the rotation has
   to be composed with the centring or it flies off to one side. */
.is-loading::after {
  --sp-size: 34px;
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  margin: 0;
  transform-origin: center;
  animation: sp-sweep-centred var(--sp-speed) linear infinite;
  filter: none;
  opacity: 1;
  z-index: 2;
}

@keyframes sp-sweep-centred {
  from {
    transform: translate(-50%, -50%) rotate(0turn);
  }
  to {
    transform: translate(-50%, -50%) rotate(1turn);
  }
}

/* --- sizes, per place ---------------------------------------------------
   Only the variables change. Nothing here can make a spinner non-round. */

.loading-spinner:empty {
  --sp-size: 50px;
  --sp-thick: 4px;
  margin: 0 auto 1rem;
}

.spinner {
  --sp-size: 40px;
}

.profile-card-overlay .spinner {
  --sp-size: 32px;
}

.verification-loading-overlay .spinner {
  --sp-size: 48px;
  --sp-thick: 4px;
}

.steam-spinner {
  --sp-size: 14px;
  --sp-thick: 2px;
  --sp-track: rgba(79, 209, 199, 0.2);
  --sp-accent: #4fd1c7;
  --sp-speed: 0.7s;
}

.dv-spinner {
  --sp-track: rgba(156, 201, 196, 0.22);
  --sp-accent: #7de38a;
  --sp-speed: 0.8s;
  margin: 0 auto 1rem;
}

.sg-modal-spinner {
  --sp-speed: 0.8s;
  margin: 0 auto;
}

.sg-modal-spinner[hidden] {
  display: none;
}

/* Bootstrap's own spinner, brought in line so a page never shows two
   different loading styles at once. */
.spinner-border {
  --sp-size: 2rem;
  --sp-thick: 3px;
  --sp-speed: 0.75s;

  box-sizing: border-box;
  display: inline-block;
  vertical-align: -0.125em;
  width: var(--sp-size);
  height: var(--sp-size);
  min-width: var(--sp-size);
  min-height: var(--sp-size);
  aspect-ratio: 1 / 1;
  flex: 0 0 auto;
  border: 0 !important;
  border-radius: 50%;

  background: conic-gradient(
    from 0deg,
    var(--sp-track) 0deg,
    var(--sp-track) 90deg,
    var(--sp-accent) 330deg,
    var(--sp-accent) 360deg
  );
  -webkit-mask: radial-gradient(
    farthest-side,
    #0000 calc(100% - var(--sp-thick)),
    #000 calc(100% - var(--sp-thick))
  );
  mask: radial-gradient(
    farthest-side,
    #0000 calc(100% - var(--sp-thick)),
    #000 calc(100% - var(--sp-thick))
  );
  animation: sp-sweep var(--sp-speed) linear infinite;
}

.spinner-border-sm {
  --sp-size: 1rem;
  --sp-thick: 2px;
}

/* currentColor is how Bootstrap's text-* helpers tint a spinner. */
.spinner-border.text-success {
  --sp-accent: #7de38a;
  --sp-track: rgba(125, 227, 138, 0.18);
}

/* Someone who has asked for less motion still needs to see that something is
   happening, so the ring stays and pulses instead of spinning. */
@media (prefers-reduced-motion: reduce) {
  .spinner,
  .loading-spinner:empty,
  .dv-spinner,
  .sg-modal-spinner,
  .steam-spinner,
  .sp-ring,
  .spinner-border,
  .is-loading::after {
    animation: sp-pulse 1.4s ease-in-out infinite;
  }

  @keyframes sp-pulse {
    0%,
    100% {
      opacity: 0.35;
    }
    50% {
      opacity: 1;
    }
  }
}
