@keyframes bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}

@keyframes pulse {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.18); }
}

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px) rotate(-1deg); }
  40% { transform: translateX(5px) rotate(1deg); }
  60% { transform: translateX(-4px) rotate(-1deg); }
  80% { transform: translateX(4px) rotate(1deg); }
}

@keyframes floatUp {
  from { transform: translateY(18px) scale(.75); opacity: 0; }
  20% { opacity: 1; }
  to { transform: translateY(-120px) scale(1.2); opacity: 0; }
}

@keyframes steam {
  from { transform: translateY(12px) scaleX(.75); opacity: 0; }
  30% { opacity: .8; }
  to { transform: translateY(-82px) scaleX(1.3); opacity: 0; }
}

@keyframes staticNoise {
  0% { background-position: 0 0, 0 0; }
  100% { background-position: 80px 140px, -90px -30px; }
}

@keyframes waterRain {
  from { background-position: 0 0; opacity: .7; }
  to { background-position: 0 80px; opacity: .95; }
}

@keyframes showerStream {
  0% { transform: translateX(-50%) scaleY(.72); opacity: 0; }
  20% { opacity: .95; }
  100% { transform: translateX(-50%) scaleY(1.08); opacity: 0; }
}

@keyframes showerDrop {
  0% { transform: translate(-50%, -10%) scale(.85); opacity: 0; }
  15% { opacity: .95; }
  100% { transform: translate(calc(-50% + var(--drop-x, 0px)), var(--drop-y, 72px)) scale(.55); opacity: 0; }
}

@keyframes latherPop {
  0% { transform: translate(-50%, -50%) scale(.35); opacity: 0; }
  22% { opacity: .98; }
  100% { transform: translate(-50%, -50%) scale(1.15); opacity: 0; }
}

@keyframes wipeSweep {
  0% { transform: translate(-50%, -50%) rotate(var(--wipe-rotation, 0deg)) scale(.5); opacity: 0; }
  20% { opacity: .92; }
  100% { transform: translate(calc(-50% + 18px), calc(-50% + 3px)) rotate(var(--wipe-rotation, 0deg)) scale(1.08); opacity: 0; }
}

@keyframes loaderBubble {
  0%, 100% { transform: translateY(0) scale(.85); opacity: .45; }
  50% { transform: translateY(-14px) scale(1.12); opacity: 1; }
}

@keyframes loaderProgress {
  0% { transform: translateX(-130%); }
  50% { transform: translateX(72%); }
  100% { transform: translateX(220%); }
}

@keyframes screenFlash {
  0% { opacity: 0; transform: scaleX(0); }
  32% { opacity: 1; transform: scaleX(1); }
  68% { opacity: 1; transform: scaleX(1); }
  100% { opacity: 0; transform: scaleX(0); }
}

@keyframes sceneEnter {
  0% { transform: scale(1.035) translateY(18px); opacity: 0; filter: blur(8px); }
  100% { transform: scale(1) translateY(0); opacity: 1; filter: blur(0); }
}

@keyframes sceneLeave {
  0% { transform: scale(1) translateY(0); opacity: 1; filter: blur(0); }
  100% { transform: scale(.985) translateY(-12px); opacity: 0; filter: blur(5px); }
}

@keyframes shine {
  from { transform: translateX(-140%) skewX(-18deg); }
  to { transform: translateX(220%) skewX(-18deg); }
}

@keyframes pop {
  0% { transform: scale(.6); opacity: 0; }
  70% { transform: scale(1.12); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

.bob { animation: bob 3s ease-in-out infinite; }
.pulse { animation: pulse 1.3s ease-in-out infinite; }
.shake { animation: shake .35s ease-in-out; }
.fx-bubble, .fx-steam {
  position: absolute;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  pointer-events: none;
  z-index: 16;
}
.fx-bubble {
  background: radial-gradient(circle at 35% 30%, #fff, #aeefff 50%, rgba(126,206,255,.2));
  animation: floatUp 1.25s ease-out forwards;
}
.fx-steam {
  width: 22px;
  height: 58px;
  border-radius: 50%;
  background: linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,0));
  filter: blur(4px);
  animation: steam 1.6s ease-out forwards;
}
.fx-stream, .fx-drop, .fx-lather, .fx-wipe {
  position: absolute;
  pointer-events: none;
  z-index: 16;
}
.fx-stream {
  width: 18px;
  border-radius: 999px;
  background:
    linear-gradient(180deg, rgba(255,255,255,.95), rgba(198,244,255,.95) 18%, rgba(109,203,255,.88) 55%, rgba(41,144,229,.12));
  box-shadow: 0 0 11px rgba(123,220,255,.5), inset 0 0 8px rgba(255,255,255,.6);
  animation: showerStream .38s linear forwards;
}
.fx-drop {
  width: 8px;
  height: 18px;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(255,255,255,.95), rgba(102,205,255,.8));
  box-shadow: 0 0 8px rgba(128,223,255,.45);
  animation: showerDrop .58s linear forwards;
}
.fx-lather {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 28% 28%, rgba(255,255,255,.98) 0 17%, rgba(220,242,255,.92) 18% 27%, transparent 28%),
    radial-gradient(circle at 60% 38%, rgba(255,255,255,.94) 0 19%, rgba(214,240,255,.88) 20% 31%, transparent 32%),
    radial-gradient(circle at 42% 66%, rgba(255,255,255,.96) 0 16%, rgba(214,240,255,.82) 17% 27%, transparent 28%),
    radial-gradient(circle at 66% 72%, rgba(255,255,255,.9) 0 13%, rgba(214,240,255,.74) 14% 22%, transparent 23%);
  filter: drop-shadow(0 0 10px rgba(255,255,255,.35));
  animation: latherPop .72s ease-out forwards;
}
.fx-wipe {
  width: 68px;
  height: 26px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,.34);
  background: linear-gradient(90deg, rgba(255,240,190,0), rgba(255,236,176,.96), rgba(255,248,221,.4), rgba(255,240,190,0));
  box-shadow: 0 0 10px rgba(255,228,170,.28);
  animation: wipeSweep .44s ease-out forwards;
}
.shine::after {
  content: '';
  position: absolute;
  top: -20%;
  left: 0;
  width: 45%;
  height: 140%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.34), transparent);
  animation: shine 2.9s ease-in-out infinite;
}
