@font-face {
  font-family: "Outfit";
  src: url("fonts/outfit-latin-600-normal.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}

:root {
  --cycle: 10s;
  --size: min(64vmin, 440px);
  --rest-scale: 0.6;
  --bloom-rest-scale: 0.75;
  --bloom-scale: 1.5;
  --ripple-scale: 1.4;

  --in-light: #d0f0e7;
  --in-mid: #20ada2;
  --in-deep: #02596a;
  --out-light: #b6badd;
  --out-mid: #7088c6;
  --out-deep: #293b6d;
  --glow: color-mix(in srgb, var(--in-mid) 55%, var(--out-mid));
  --text: #ffffff;
  --text-glow: rgb(9 9 9 / 0.3);
}

html,
body {
  margin: 0;
  height: 100%;
  background: transparent;
}

body {
  display: grid;
  place-items: center;
  overflow: hidden;
  font-family: "Outfit", system-ui, sans-serif;
  font-weight: 600;
}

.stage {
  display: grid;
  place-items: center;
  width: var(--size);
  aspect-ratio: 1;
}

.stage > * {
  grid-area: 1 / 1;
}

.ripple,
.bloom,
.bubble {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  animation-duration: var(--cycle);
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
}

.ripple {
  box-sizing: border-box;
  border: 3px solid var(--glow);
  box-shadow:
    0 0 32px var(--glow),
    inset 0 0 32px var(--glow);
  opacity: 0;
  animation-name: ripple;
  animation-timing-function: cubic-bezier(0.2, 0.6, 0.3, 1);
}

.bloom {
  background: radial-gradient(circle, var(--glow) 0 50%, transparent 78%);
  filter: blur(28px);
  animation-name: bloom;
}

.bubble {
  background: radial-gradient(
    circle at 35% 28%,
    var(--out-light),
    var(--out-mid) 30%,
    var(--out-deep) 95%
  );
  box-shadow: 0 24px 60px -24px var(--out-deep);
  animation-name: breathe;
}

.bubble::before,
.bubble::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.bubble::before {
  animation: tint var(--cycle) ease-in-out infinite;
}

.bubble::before {
  background: radial-gradient(
    circle at 35% 28%,
    var(--in-light),
    var(--in-mid) 30%,
    var(--in-deep) 95%
  );
}

.bubble::after {
  background: radial-gradient(
    circle at 32% 24%,
    rgb(255 255 255 / 0.5),
    transparent 26%
  );
  box-shadow:
    inset 0 0 0 1.5px rgb(255 255 255 / 0.35),
    inset 0 -18px 40px rgb(9 9 9 / 0.18);
}

.cue {
  display: grid;
  place-items: center;
  max-width: calc(var(--size) * 0.5);
  margin: 0;
  color: var(--text);
  font-size: clamp(1.1rem, calc(var(--size) * 0.085), 2.4rem);
  line-height: 1.1;
  text-align: center;
  text-wrap: balance;
  text-shadow: 0 1px 14px var(--text-glow);
}

.cue > span {
  grid-area: 1 / 1;
  animation: cue-in var(--cycle) ease-in-out infinite;
}

.cue > .cue-out {
  animation-name: cue-out;
}

@keyframes breathe {
  0%,
  100% {
    transform: scale(var(--rest-scale));
  }
  40%,
  60% {
    transform: scale(1);
  }
}

@keyframes tint {
  0% {
    opacity: 0;
  }
  25%,
  60% {
    opacity: 1;
  }
  85%,
  100% {
    opacity: 0;
  }
}

@keyframes bloom {
  0%,
  100% {
    transform: scale(var(--bloom-rest-scale));
    opacity: 0.5;
  }
  40% {
    transform: scale(var(--bloom-scale));
    opacity: 1;
  }
  50% {
    transform: scale(calc(var(--bloom-scale) * 0.95));
    opacity: 0.85;
  }
  60% {
    transform: scale(var(--bloom-scale));
    opacity: 1;
  }
  85% {
    transform: scale(calc(var(--bloom-scale) * 0.8));
    opacity: 0.8;
  }
}

@keyframes ripple {
  0%,
  60% {
    transform: scale(1);
    opacity: 0;
  }
  61.5% {
    transform: scale(1);
    opacity: 0.8;
  }
  100% {
    transform: scale(var(--ripple-scale));
    opacity: 0;
  }
}

@keyframes cue-in {
  0%,
  58% {
    opacity: 1;
  }
  60%,
  98% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes cue-out {
  0%,
  60% {
    opacity: 0;
  }
  62%,
  96% {
    opacity: 1;
  }
  98%,
  100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ripple {
    display: none;
  }
}
