/*
 * The calibration rings, lifted from the player.
 *
 * These are the real thing, not a decorative echo of it: the same geometry, the
 * same keyframes, the same opposed rotation speeds. In the app this covers the
 * map while the GPS fix settles, and the two graduations turning in opposite
 * directions are what make it read as an instrument rather than a loading
 * spinner. That is worth showing on a page that has to explain what the product
 * is, because it is the moment the product feels like what it claims to be.
 *
 * Held in the settling state rather than locking, because a lock that fires
 * every few seconds is a gimmick. Here it simply breathes.
 */

.rings {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: min(19rem, 74vw);
  aspect-ratio: 1 / 1;
  margin: 0 auto;
}
.rings > * { position: absolute; border-radius: 999px; }

.ring-outer {
  width: 100%; height: 100%;
  border: 1px dashed var(--accent);
  opacity: 0.2;
  animation: calibrate-spin 48s linear infinite;
}
.ring-inner {
  width: 76%; height: 76%;
  border: 1px dashed var(--accent);
  opacity: 0.14;
  animation: calibrate-spin-rev 29s linear infinite;
}
.ripple {
  width: 100%; height: 100%;
  border: 1px solid var(--accent);
  animation: calibrate-ripple 3.4s cubic-bezier(0.2, 0.6, 0.3, 1) infinite;
}
.ripple:nth-of-type(2) { animation-delay: 1.13s; }
.ripple:nth-of-type(3) { animation-delay: 2.26s; }

/* The accuracy ring. In the app its scale is driven by the live GPS reading;
   here it rests where a good fix would put it. */
.ring-accuracy {
  width: 100%; height: 100%;
  border: 2px solid var(--accent);
  opacity: 0.5;
  transform: scale(0.62);
}
.bloom {
  width: 100%; height: 100%;
  transform: scale(0.62);
}
.bloom > span {
  position: absolute; inset: 0; border-radius: 999px;
  background: radial-gradient(circle, rgba(16, 185, 129, 0.22) 0%, rgba(16, 185, 129, 0) 70%);
  animation: calibrate-bloom 4.5s ease-in-out infinite;
}
.dot {
  width: 12px; height: 12px;
  background: var(--accent);
  box-shadow: 0 0 20px var(--accent);
}

@keyframes calibrate-spin     { to { transform: rotate(360deg); } }
@keyframes calibrate-spin-rev { to { transform: rotate(-360deg); } }
@keyframes calibrate-ripple {
  0%   { transform: scale(0.28); opacity: 0; }
  18%  { opacity: 0.42; }
  100% { transform: scale(1.05); opacity: 0; }
}
@keyframes calibrate-bloom {
  0%   { transform: scale(1);    opacity: 0.55; }
  55%  { transform: scale(1.14); opacity: 0.22; }
  100% { transform: scale(1);    opacity: 0.55; }
}

/* Movement here is decoration, and decoration is the first thing that should
   go when somebody has asked their system to stop moving things. */
@media (prefers-reduced-motion: reduce) {
  .ring-outer, .ring-inner, .ripple, .bloom > span { animation: none; }
  .ripple { opacity: 0.12; }
}
