/* ============================================
   textfx.css — Per-theme signature chat effects
   Wired through [tag]word[/tag] system
   Respects .animations-off and prefers-reduced-motion
   ============================================ */

:root {
  --fx-duration-fast: 0.6s;
  --fx-duration-normal: 1.2s;
  --fx-duration-slow: 2.2s;
}

/* Base FX wrapper.
   The scanner now wraps ANY [word]…[/word] pair, so a word may not have its own
   .fx-<name> rule. This default animation is the fallback that makes such words
   still "do something." Every specific .fx-<name> rule below has equal
   specificity and comes LATER in this file, so it overrides `animation` here for
   known words — only unrecognized words keep this gentle pulse. */
.fx {
  display: inline-block;
  will-change: transform, opacity, filter, color;
  backface-visibility: hidden;
  animation: fxDefaultPulse 1.4s ease-in-out 1;
}
@keyframes fxDefaultPulse {
  0%, 100% { transform: none; filter: none; }
  45%      { transform: translateY(-1px) scale(1.04); filter: brightness(1.18) saturate(1.12); }
}

/* Global guard for reduced motion and animations-off toggle */
@media (prefers-reduced-motion: reduce) {
  .fx {
    /* If you want to disable it globally instead of just on .fx, use * instead of .fx */
    animation: none !important;
    transition: none !important;
  }
}

/* 2. Handle manual user toggles via classes or data attributes */
body.animations-off .fx,
body[data-animations="off"] .fx {
  animation: none !important;
  transition: none !important;
}

/* ============================================
   SHARED COMBAT / UNIVERSAL EFFECTS (always available)
   ============================================ */

.fx-strike {
  animation: fx-strike var(--fx-duration-fast) ease-out;
  color: #ffcc66;
  text-shadow: 0 0 4px #ff6600;
}

@keyframes fx-strike {
  0% { transform: scale(1.4) translateY(-2px); opacity: 0.2; }
  40% { transform: scale(0.95); }
  100% { transform: scale(1); opacity: 1; }
}

.fx-crit {
  animation: fx-crit var(--fx-duration-normal) ease-out;
  color: #ffeb3b;
  text-shadow: 0 0 8px #ffc107, 0 0 16px #ff9800;
  font-weight: 700;
}

@keyframes fx-crit {
  0% { transform: scale(1.6); filter: brightness(2); }
  30% { transform: scale(1.1); }
  70% { transform: scale(1.05); }
  100% { transform: scale(1); filter: brightness(1); }
}

.fx-miss {
  animation: fx-miss var(--fx-duration-fast) ease-out;
  color: #888;
  opacity: 0.65;
  text-decoration: line-through;
}

@keyframes fx-miss {
  0% { transform: translateX(4px); }
  50% { transform: translateX(-2px); }
  100% { transform: translateX(0); }
}

.fx-heal {
  animation: fx-heal var(--fx-duration-normal) ease-in-out infinite;
  color: #4ade80;
  text-shadow: 0 0 6px #22c55e;
}

@keyframes fx-heal {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-1.5px); }
}

.fx-buff {
  animation: fx-buff var(--fx-duration-slow) ease-in-out infinite;
  color: #60a5fa;
  text-shadow: 0 0 6px #3b82f6;
}

@keyframes fx-buff {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-2px) scale(1.03); }
}

.fx-debuff {
  animation: fx-debuff var(--fx-duration-normal) ease-in-out infinite;
  color: #c026ff;
  text-shadow: 0 0 6px #a855f7;
  opacity: 0.9;
}

@keyframes fx-debuff {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(1.5px); }
}

.fx-fire {
  animation: fx-fire 1.1s ease-in-out infinite;
  color: #fb923c;
  text-shadow: 0 0 8px #f97316, 0 0 14px #ea580c;
}

@keyframes fx-fire {
  0%, 100% { filter: brightness(1) saturate(1); }
  50% { filter: brightness(1.3) saturate(1.4); }
}

.fx-ice {
  animation: fx-ice var(--fx-duration-normal) ease-in-out infinite;
  color: #67e8f9;
  text-shadow: 0 0 8px #22d3ee;
  filter: saturate(0.9);
}

@keyframes fx-ice {
  0%, 100% { transform: skewX(0deg); }
  50% { transform: skewX(0.6deg); }
}

.fx-poison {
  animation: fx-poison 1.8s ease-in-out infinite;
  color: #4ade80;
  text-shadow: 0 0 6px #86efac;
  opacity: 0.92;
}

@keyframes fx-poison {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-0.8px); }
  75% { transform: translateX(0.8px); }
}

.fx-lightning {
  animation: fx-lightning 0.5s linear;
  color: #fde047;
  text-shadow: 0 0 10px #eab308, 0 0 20px #ca8a04;
}

@keyframes fx-lightning {
  0%, 100% { opacity: 1; }
  20% { opacity: 0.3; }
  40% { opacity: 1; }
  60% { opacity: 0.5; }
  80% { opacity: 1; }
}

.fx-bleed {
  animation: fx-bleed var(--fx-duration-slow) ease-in-out infinite;
  color: #f87171;
  text-shadow: 0 0 6px #ef4444;
}

@keyframes fx-bleed {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.75; }
}

.fx-shield {
  animation: fx-shield var(--fx-duration-normal) ease-out;
  color: #94a3b8;
  text-shadow: 0 0 6px #64748b;
  border-bottom: 1px dotted currentColor;
}

@keyframes fx-shield {
  0% { transform: scale(0.7); opacity: 0.4; }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); opacity: 1; }
}

/* ============================================
   HALLOWEEN SIGNATURE EFFECTS
   ============================================ */

.fx-dread {
  animation: fx-dread 2.4s ease-in-out infinite;
  color: #c084fc;
  text-shadow: 0 0 4px #7e22ce;
  letter-spacing: 0.3px;
}

@keyframes fx-dread {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-1.2px); }
  40% { transform: translateX(0.8px); }
  60% { transform: translateX(-0.6px); }
  80% { transform: translateX(0.4px); }
}

.fx-haunt {
  animation: fx-haunt 2.8s ease-in-out infinite;
  color: #ddd6fe;
  text-shadow: 0 0 8px #a5b4fc;
  opacity: 0.92;
}

@keyframes fx-haunt {
  0%, 100% { opacity: 0.92; transform: translateY(0); }
  25% { opacity: 0.55; transform: translateY(-1px); }
  50% { opacity: 0.95; transform: translateY(0); }
  75% { opacity: 0.6; transform: translateY(1px); }
}

.fx-terror {
  animation: fx-terror 0.9s ease-out;
  color: #fda4af;
  text-shadow: 0 0 10px #e11d48;
  font-weight: 600;
}

@keyframes fx-terror {
  0% { transform: scale(1.35) rotate(-1deg); }
  15% { transform: scale(0.92) rotate(1deg); }
  35% { transform: scale(1.15) rotate(-0.5deg); }
  60% { transform: scale(0.98); }
  100% { transform: scale(1) rotate(0); }
}

.fx-shiver {
  animation: fx-shiver 1.6s ease-in-out infinite;
  color: #bae6fd;
}

@keyframes fx-shiver {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-1.5px); }
  30% { transform: translateX(1.2px); }
  45% { transform: translateX(-0.9px); }
  60% { transform: translateX(0.7px); }
}

.fx-spell {
  animation: fx-spell 2.1s ease-in-out infinite;
  color: #c026ff;
  text-shadow: 0 0 12px #7e22ce, 0 0 22px #581c87;
}

@keyframes fx-spell {
  0%, 100% { filter: hue-rotate(0deg) brightness(1); }
  50% { filter: hue-rotate(12deg) brightness(1.15); }
}

.fx-ethereal {
  animation: fx-ethereal 3.2s ease-in-out infinite;
  color: #e0e7ff;
  text-shadow: 0 0 10px #6366f1;
  opacity: 0.88;
}

@keyframes fx-ethereal {
  0%, 100% { opacity: 0.88; transform: translateY(0) scale(1); }
  40% { opacity: 0.55; transform: translateY(-1.5px) scale(0.985); }
  70% { opacity: 0.95; transform: translateY(0.5px) scale(1.01); }
}

/* ============================================
   VALENTINE'S SIGNATURE EFFECTS (romantic, atmospheric)
   ============================================ */

.fx-swoon {
  animation: fx-swoon 2.6s ease-in-out infinite;
  color: #fb7185;
  text-shadow: 0 0 8px #e11d48;
}

@keyframes fx-swoon {
  0%, 100% { transform: translateY(0) scale(1); }
  40% { transform: translateY(-2.5px) scale(1.04); }
  70% { transform: translateY(-0.5px) scale(1.01); }
}

.fx-heat {
  animation: fx-heat 1.8s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 10px #f43f5e;
}

@keyframes fx-heat {
  0%, 100% { filter: saturate(1) brightness(1); }
  50% { filter: saturate(1.35) brightness(1.12); }
}

.fx-flutter {
  animation: fx-flutter 1.4s ease-in-out infinite;
  color: #f9a8d4;
  text-shadow: 0 0 6px #db2777;
}

@keyframes fx-flutter {
  0%, 100% { transform: scale(1); }
  25% { transform: scale(1.08); }
  50% { transform: scale(0.96); }
  75% { transform: scale(1.04); }
}

.fx-breathless {
  animation: fx-breathless 2.9s ease-in-out infinite;
  color: #fecdd3;
  opacity: 0.92;
}

@keyframes fx-breathless {
  0%, 100% { opacity: 0.92; letter-spacing: 0; }
  45% { opacity: 0.65; letter-spacing: 0.6px; }
  70% { opacity: 0.88; letter-spacing: 0.2px; }
}

.fx-allure {
  animation: fx-allure 2.3s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 1px 6px rgba(225, 29, 72, 0.5);
}

@keyframes fx-allure {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-1px); }
}

.fx-whisper {
  animation: fx-whisper 3.1s ease-in-out infinite;
  color: #fda4af;
  opacity: 0.85;
  font-style: italic;
}

@keyframes fx-whisper {
  0%, 100% { opacity: 0.85; }
  45% { opacity: 0.55; }
  75% { opacity: 0.9; }
}

/* ============================================
   WINTER FEAST SIGNATURE EFFECTS
   ============================================ */

.fx-frost {
  animation: fx-frost 2.5s ease-in-out infinite;
  color: #bae6fd;
  text-shadow: 0 0 8px #67e8f9;
  filter: saturate(0.85);
}

@keyframes fx-frost {
  0%, 100% { transform: skewX(0deg); }
  30% { transform: skewX(-0.8deg); }
  70% { transform: skewX(0.6deg); }
}

.fx-shimmer {
  animation: fx-shimmer 1.9s ease-in-out infinite;
  color: #e0f2fe;
  text-shadow: 0 0 12px #7dd3fc;
}

@keyframes fx-shimmer {
  0%, 100% { opacity: 1; filter: brightness(1); }
  50% { opacity: 0.75; filter: brightness(1.25); }
}

.fx-chill {
  animation: fx-chill 2.2s ease-in-out infinite;
  color: #a5f3fc;
  text-shadow: 0 0 6px #67e8f9;
}

@keyframes fx-chill {
  0%, 100% { transform: translateY(0); }
  40% { transform: translateY(1px); }
  70% { transform: translateY(-0.5px); }
}

/* ============================================
   HARVEST SIGNATURE EFFECTS
   ============================================ */

.fx-gild {
  animation: fx-gild 2.0s ease-in-out infinite;
  color: #fcd34d;
  text-shadow: 0 0 8px #f59e0b, 0 0 16px #d97706;
}

@keyframes fx-gild {
  0%, 100% { filter: brightness(1) saturate(1); }
  50% { filter: brightness(1.25) saturate(1.15); }
}

.fx-rustle {
  animation: fx-rustle 1.7s ease-in-out infinite;
  color: #fed7aa;
  text-shadow: 0 0 4px #fb923c;
}

@keyframes fx-rustle {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(-1.2deg); }
  50% { transform: rotate(0.9deg); }
  75% { transform: rotate(-0.6deg); }
}

.fx-hearth {
  animation: fx-hearth 2.4s ease-in-out infinite;
  color: #fb923c;
  text-shadow: 0 0 10px #f97316;
}

@keyframes fx-hearth {
  0%, 100% { transform: scale(1); }
  45% { transform: scale(1.035); }
  80% { transform: scale(0.985); }
}

/* ============================================
   BONUS / EXTRA EFFECTS (to reach ~26 total)
   ============================================ */

.fx-glimmer {
  animation: fx-glimmer 1.5s ease-in-out infinite;
  color: #f0abfc;
  text-shadow: 0 0 8px #c026ff;
}

@keyframes fx-glimmer {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

.fx-pulse {
  animation: fx-pulse 1.3s ease-in-out infinite;
  color: #f472b6;
}

@keyframes fx-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}

.fx-ember {
  animation: fx-ember 2.1s ease-in-out infinite;
  color: #fb7185;
  text-shadow: 0 0 8px #e11d48;
}

@keyframes fx-ember {
  0%, 100% { transform: translateY(0); opacity: 1; }
  40% { transform: translateY(-2px); opacity: 0.7; }
  80% { transform: translateY(0); opacity: 1; }
}

.fx-velvet {
  animation: fx-velvet 2.8s ease-in-out infinite;
  color: #fda4af;
  font-style: italic;
  text-shadow: 0 1px 4px rgba(190, 18, 60, 0.4);
}

@keyframes fx-velvet {
  0%, 100% { letter-spacing: 0.2px; }
  50% { letter-spacing: 0.8px; }
}

/* ============================================
   NSFW / EROTIC LAYER EFFECTS (opt-in)
   More intense, sensual animations. Only suggested by DM when scene is explicitly intimate.
   These pair beautifully with Valentine's "heat" and "swoon" base effects.
   ============================================ */

.fx-passion {
  animation: fx-passion 1.6s ease-in-out infinite;
  color: #f43f5e;
  text-shadow: 0 0 12px #e11d48, 0 0 22px #9f1239;
  font-weight: 600;
}

@keyframes fx-passion {
  0%, 100% { transform: scale(1); filter: brightness(1); }
  35% { transform: scale(1.06); filter: brightness(1.2) saturate(1.3); }
  70% { transform: scale(0.98); }
}

.fx-yearn {
  animation: fx-yearn 2.4s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 8px #be123c;
  font-style: italic;
}

@keyframes fx-yearn {
  0%, 100% { transform: translateY(0); letter-spacing: 0; }
  50% { transform: translateY(-1.5px); letter-spacing: 0.4px; }
}

.fx-tremble {
  animation: fx-tremble 1.1s ease-in-out infinite;
  color: #fda4af;
}

@keyframes fx-tremble {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-1.2px); }
  40% { transform: translateX(1px); }
  60% { transform: translateX(-0.7px); }
  80% { transform: translateX(0.5px); }
}

.fx-clutch {
  animation: fx-clutch 1.8s ease-out;
  color: #fb7185;
  text-shadow: 0 0 10px #e11d48;
}

@keyframes fx-clutch {
  0% { transform: scale(1.25) translateY(-1px); }
  30% { transform: scale(0.95); }
  60% { transform: scale(1.08); }
  100% { transform: scale(1); }
}

.fx-glow-hot {
  animation: fx-glow-hot 2.0s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 14px #f43f5e, 0 0 26px #9f1239;
}

@keyframes fx-glow-hot {
  0%, 100% { filter: brightness(1) saturate(1); }
  50% { filter: brightness(1.35) saturate(1.4); }
}

.fx-pulse-hard {
  animation: fx-pulse-hard 0.9s ease-in-out infinite;
  color: #f43f5e;
  text-shadow: 0 0 10px #e11d48;
  font-weight: 700;
}

@keyframes fx-pulse-hard {
  0%, 100% { transform: scale(1); }
  40% { transform: scale(1.15); }
  70% { transform: scale(0.92); }
}

.fx-devour {
  animation: fx-devour 2.2s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 8px #9f1239;
}

@keyframes fx-devour {
  0%, 100% { transform: scale(1); }
  45% { transform: scale(1.04); }
  80% { transform: scale(0.97); }
}

.fx-ecstasy {
  animation: fx-ecstasy 2.6s ease-in-out infinite;
  color: #f43f5e;
  text-shadow: 0 0 16px #e11d48, 0 0 30px #9f1239;
  font-weight: 600;
}

@keyframes fx-ecstasy {
  0%, 100% { transform: scale(1) translateY(0); filter: brightness(1); }
  35% { transform: scale(1.1) translateY(-2px); filter: brightness(1.3) saturate(1.5); }
  65% { transform: scale(0.96) translateY(1px); }
}

/* ============================================
   VALENTINE EROTIC / SEX / BED MOVEMENT EFFECTS
   Rich, physical, sensual animations for moans, thrusts, smacks,
   bed creaks, erratic movement, gasping, arching, etc.
   These are the "most of them all" for Valentine's theme.
   Use freely in intimate scenes: [moan]ahh~[/moan] [smack]smack[/smack]
   ============================================ */

.fx-moan {
  animation: fx-moan 2.1s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 10px #e11d48;
  font-style: italic;
  letter-spacing: 0.3px;
}

@keyframes fx-moan {
  0%, 100% { transform: translateY(0); opacity: 0.95; }
  30% { transform: translateY(-2.5px); opacity: 1; letter-spacing: 0.8px; }
  60% { transform: translateY(-1px); }
}

.fx-gasp {
  animation: fx-gasp 0.7s ease-out;
  color: #fda4af;
  text-shadow: 0 0 8px #f43f5e;
  font-weight: 600;
}

@keyframes fx-gasp {
  0% { transform: scale(1.3) translateY(-3px); opacity: 0.4; }
  25% { transform: scale(0.95); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); opacity: 1; }
}

.fx-whimper {
  animation: fx-whimper 1.8s ease-in-out infinite;
  color: #fecdd3;
  text-shadow: 0 0 6px #db2777;
  font-style: italic;
}

@keyframes fx-whimper {
  0%, 100% { transform: translateY(0) scale(1); }
  40% { transform: translateY(-1.5px) scale(1.04); }
  70% { transform: translateY(-0.5px) scale(0.98); }
}

.fx-cry {
  animation: fx-cry 2.4s ease-in-out infinite;
  color: #f43f5e;
  text-shadow: 0 0 12px #e11d48;
}

@keyframes fx-cry {
  0%, 100% { transform: translateY(0); }
  35% { transform: translateY(-3px) scale(1.05); }
  65% { transform: translateY(-1px) scale(0.97); }
}

.fx-arch {
  animation: fx-arch 1.9s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 8px #be123c;
}

@keyframes fx-arch {
  0%, 100% { transform: translateY(0) scaleY(1); }
  45% { transform: translateY(-4px) scaleY(1.08); }
}

.fx-thrust {
  animation: fx-thrust 1.3s ease-out;
  color: #f43f5e;
  text-shadow: 0 0 10px #e11d48;
  font-weight: 700;
}

@keyframes fx-thrust {
  0% { transform: translateY(-2px) scale(1.15); }
  20% { transform: translateY(1px) scale(0.92); }
  45% { transform: translateY(-1px) scale(1.08); }
  80% { transform: translateY(0) scale(1); }
}

.fx-smack {
  animation: fx-smack 0.6s ease-out;
  color: #fda4af;
  text-shadow: 0 0 14px #e11d48;
  font-weight: 800;
}

@keyframes fx-smack {
  0% { transform: scale(1.4) translateY(-1px); }
  15% { transform: scale(0.85) translateY(2px); }
  40% { transform: scale(1.1); }
  70% { transform: scale(0.96); }
  100% { transform: scale(1); }
}

.fx-bedcreak {
  animation: fx-bedcreak 2.6s ease-in-out infinite;
  color: #fda4af;
}

@keyframes fx-bedcreak {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  25% { transform: translateX(-1.8px) rotate(-0.4deg); }
  50% { transform: translateX(1.5px) rotate(0.5deg); }
  75% { transform: translateX(-0.9px) rotate(-0.3deg); }
}

.fx-rhythm {
  animation: fx-rhythm 1.5s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 8px #f43f5e;
}

@keyframes fx-rhythm {
  0%, 100% { transform: scale(1); }
  40% { transform: scale(1.07); }
  70% { transform: scale(0.95); }
}

.fx-grind {
  animation: fx-grind 2.8s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 6px #db2777;
  font-style: italic;
}

@keyframes fx-grind {
  0%, 100% { transform: translateX(0); }
  35% { transform: translateX(-2px); }
  65% { transform: translateX(1.8px); }
}

.fx-buck {
  animation: fx-buck 1.2s ease-out;
  color: #f43f5e;
  text-shadow: 0 0 10px #e11d48;
  font-weight: 700;
}

@keyframes fx-buck {
  0% { transform: translateY(3px) scaleY(0.9); }
  25% { transform: translateY(-4px) scaleY(1.12); }
  55% { transform: translateY(-1px) scaleY(1.03); }
  100% { transform: translateY(0) scaleY(1); }
}

.fx-slap {
  animation: fx-slap 0.55s ease-out;
  color: #fda4af;
  text-shadow: 0 0 12px #e11d48;
  font-weight: 800;
}

@keyframes fx-slap {
  0% { transform: scale(1.35) translateY(-2px); }
  18% { transform: scale(0.82); }
  45% { transform: scale(1.12); }
  75% { transform: scale(0.95); }
  100% { transform: scale(1); }
}

.fx-erratic {
  animation: fx-erratic 1.4s ease-in-out infinite;
  color: #f43f5e;
}

@keyframes fx-erratic {
  0%, 100% { transform: translateX(0) translateY(0); }
  15% { transform: translateX(-2.2px) translateY(-1px); }
  30% { transform: translateX(1.8px) translateY(1.5px); }
  45% { transform: translateX(-1.5px) translateY(-0.8px); }
  60% { transform: translateX(2px) translateY(0.6px); }
  80% { transform: translateX(-0.8px) translateY(-0.4px); }
}

.fx-deep {
  animation: fx-deep 1.6s ease-out;
  color: #fda4af;
  text-shadow: 0 0 14px #9f1239;
  font-weight: 700;
}

@keyframes fx-deep {
  0% { transform: translateY(-1px) scale(1.1); }
  20% { transform: translateY(2px) scale(0.88); }
  45% { transform: translateY(-2.5px) scale(1.15); }
  75% { transform: translateY(0) scale(1); }
}

.fx-edge {
  animation: fx-edge 2.9s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 8px #e11d48;
  font-style: italic;
}

@keyframes fx-edge {
  0%, 100% { transform: scale(1); letter-spacing: 0; }
  45% { transform: scale(1.04); letter-spacing: 0.6px; }
  75% { transform: scale(0.97); letter-spacing: 0.2px; }
}

.fx-release {
  animation: fx-release 2.3s ease-out;
  color: #f43f5e;
  text-shadow: 0 0 18px #e11d48, 0 0 30px #9f1239;
  font-weight: 700;
}

@keyframes fx-release {
  0% { transform: scale(1.25) translateY(-3px); filter: brightness(1.4); }
  25% { transform: scale(0.9); }
  50% { transform: scale(1.15) translateY(-1px); }
  80% { transform: scale(0.98); filter: brightness(1); }
  100% { transform: scale(1); }
}

.fx-afterglow {
  animation: fx-afterglow 3.5s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 10px #f43f5e;
  opacity: 0.92;
}

@keyframes fx-afterglow {
  0%, 100% { transform: translateY(0) scale(1); opacity: 0.92; }
  40% { transform: translateY(-1px) scale(1.02); opacity: 1; }
  70% { transform: translateY(0) scale(0.99); }
}

.fx-slick {
  animation: fx-slick 2.0s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 8px #db2777;
  font-style: italic;
}

@keyframes fx-slick {
  0%, 100% { transform: translateX(0); }
  45% { transform: translateX(-1.2px); }
  75% { transform: translateX(1px); }
}

.fx-clutch-sheets {
  animation: fx-clutch-sheets 1.7s ease-in-out infinite;
  color: #fda4af;
  text-shadow: 0 0 6px #e11d48;
}

@keyframes fx-clutch-sheets {
  0%, 100% { transform: translateY(0) scale(1); }
  35% { transform: translateY(-1px) scale(1.06); }
  65% { transform: translateY(0.5px) scale(0.96); }
}

.fx-hips {
  animation: fx-hips 1.8s ease-in-out infinite;
  color: #f43f5e;
  text-shadow: 0 0 8px #e11d48;
}

@keyframes fx-hips {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  30% { transform: translateX(-1.5px) rotate(-0.6deg); }
  60% { transform: translateX(1.8px) rotate(0.5deg); }
  85% { transform: translateX(-0.6px) rotate(-0.3deg); }
}

/* Floating + disappearing sound effects (AH, slurping, etc.)
   These rise upward and fade out — perfect for onomatopoeia in erotic scenes.
   Use like: [ah]ahh~[/ah] [slurp]slurp slurp[/slurp] */
.fx-ah, .fx-ahh, .fx-slurp, .fx-slurping, .fx-gulp, .fx-lick, .fx-suck {
  display: inline-block;
  font-style: italic;
  color: #fda4af;
  text-shadow: 0 0 8px #e11d48;
  pointer-events: none;
}

/* AH / AHH — classic pleasure gasp floating up and fading */
.fx-ah, .fx-ahh {
  animation: fxAhFloat 1.6s ease-out forwards;
}
@keyframes fxAhFloat {
  0% {
    transform: translateY(0);
    opacity: 1;
    letter-spacing: 0;
  }
  40% {
    transform: translateY(-12px);
    opacity: 0.95;
    letter-spacing: 0.4px;
  }
  100% {
    transform: translateY(-38px);
    opacity: 0;
    letter-spacing: 1.2px;
  }
}

/* Slurp / Slurping — wet slurping sounds floating up */
.fx-slurp, .fx-slurping {
  color: #f9a8d4;
  text-shadow: 0 0 6px #db2777;
  animation: fxSlurpFloat 1.9s ease-out forwards;
}
@keyframes fxSlurpFloat {
  0% {
    transform: translateY(0) scale(0.9);
    opacity: 1;
  }
  30% {
    transform: translateY(-8px) scale(1.05);
    opacity: 0.95;
  }
  100% {
    transform: translateY(-42px) scale(0.85);
    opacity: 0;
  }
}

/* Gulp — swallowing / gulping sound */
.fx-gulp {
  animation: fxGulpFloat 1.5s ease-out forwards;
}
@keyframes fxGulpFloat {
  0% {
    transform: translateY(0);
    opacity: 1;
    filter: brightness(1);
  }
  50% {
    transform: translateY(-18px);
    opacity: 0.7;
    filter: brightness(1.2);
  }
  100% {
    transform: translateY(-35px);
    opacity: 0;
  }
}

/* Lick / Suck — tongue / oral sounds floating */
.fx-lick, .fx-suck {
  color: #fda4af;
  animation: fxLickFloat 1.7s ease-out forwards;
}
@keyframes fxLickFloat {
  0% {
    transform: translateY(2px) scale(0.85);
    opacity: 0.9;
  }
  25% {
    transform: translateY(-6px) scale(1.08);
    opacity: 1;
  }
  100% {
    transform: translateY(-40px) scale(0.9);
    opacity: 0;
  }
}