/* ─── VISUAL POLISH ─────────────────────────────────────────────────────────── */
/* 9 visual/feel improvements: deformation, parallax, event entrances,
   theme transitions, coach polish, cylinder shadow, prestige celebration,
   idle animations, cursor trails */

/* ── 3. Event Entrance Animations ───────────────────────────────────────── */
/* Droplet portal: drop from above with bounce (shared across all tiers — the
 * tier-specific visuals come from the rainbow pulse in addons.css). */
@keyframes geEntranceDrop {
  0%   { transform: translate(-50%, -300%) scale(0.6); opacity: 0; }
  50%  { transform: translate(-50%, -40%)  scale(1.15); opacity: 1; }
  70%  { transform: translate(-50%, -60%)  scale(0.92); }
  85%  { transform: translate(-50%, -48%)  scale(1.03); }
  100% { transform: translate(-50%, -50%)  scale(1); }
}
#golden-eggplant.ge-entrance                { animation: geEntranceDrop 0.65s cubic-bezier(0.22,1,0.36,1) forwards !important; }
#golden-eggplant.tier-bronze.ge-entrance,
#golden-eggplant.tier-silver.ge-entrance,
#golden-eggplant.tier-gold.ge-entrance      { animation: geEntranceDrop 0.65s cubic-bezier(0.22,1,0.36,1) forwards !important; }

/* Torsion: spiral in with whoosh */
@keyframes torsionEntranceSpin {
  0%   { transform: translate(-50%,-50%) rotate(-540deg) scale(0); opacity: 0; }
  60%  { transform: translate(-50%,-50%) rotate(20deg) scale(1.15); opacity: 1; }
  80%  { transform: translate(-50%,-50%) rotate(-8deg) scale(0.95); }
  100% { transform: translate(-50%,-50%) rotate(0deg) scale(1); }
}
.torsion-arrow.torsion-entrance {
  animation: torsionEntranceSpin 0.55s cubic-bezier(0.22,1,0.36,1) forwards;
}

/* Cursed: dark vignette creep-in */
@keyframes cursedVignetteIn {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes cursedVignetteOut {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}
#cursed-vignette {
  position: fixed; inset: 0; pointer-events: none; z-index: 8999;
  background: radial-gradient(ellipse at 50% 50%, transparent 30%, rgba(80,0,0,0.18) 70%, rgba(40,0,0,0.35) 100%);
  animation: cursedVignetteIn 0.6s ease-out forwards;
}
#cursed-vignette.vignette-out {
  animation: cursedVignetteOut 0.5s ease-in forwards;
}

/* Torsion: cool-toned dark vignette — shorter fade-in than cursed since the
   torsion arrow itself is already a dramatic entrance. Shares the same fade
   keyframes so we don't duplicate timing functions. */
#torsion-vignette {
  position: fixed; inset: 0; pointer-events: none; z-index: 8998;
  background: radial-gradient(ellipse at 50% 50%, transparent 34%, rgba(0,10,40,0.20) 72%, rgba(0,6,24,0.36) 100%);
  animation: cursedVignetteIn 0.5s ease-out forwards;
}
#torsion-vignette.vignette-out {
  animation: cursedVignetteOut 0.45s ease-in forwards;
}

/* ── 4. Theme Transition Crossfade ──────────────────────────────────────── */
#theme-crossfade {
  position: fixed; inset: 0; pointer-events: none; z-index: 99997;
  background: #000; opacity: 0;
  transition: opacity 0.35s ease;
}
#theme-crossfade.fading { opacity: 0.35; }

/* ── 5. Coach Speech Bubble Polish ──────────────────────────────────────── */
@keyframes coachBubbleWobble {
  0%   { transform: scale(0.7) rotate(-3deg); opacity: 0; }
  50%  { transform: scale(1.04) rotate(1deg); opacity: 1; }
  75%  { transform: scale(0.98) rotate(-0.5deg); }
  100% { transform: scale(1) rotate(0deg); opacity: 1; }
}
#coach-wrap.coach-visible #coach-bubble {
  animation: coachBubbleWobble 0.4s cubic-bezier(0.34,1.56,0.64,1) both;
}
#coach-wrap:not(.coach-visible) #coach-bubble {
  animation: none;
}
/* ── 6. Cylinder Shadow & Lighting ──────────────────────────────────────── */
/* Light is directly above, so the shadow on the floor is the silhouette of
   cylinder + both kiwis projected straight down. Three thin ellipses (one
   per object) sit centered under their owners — no horizontal offset, no
   slant. Color bleed from --bc (cylinder border) and --kiwi-skin-dark ties
   the shadow visually to whatever skin is active; falls back to neutral
   dark when those vars aren't set. */
#cylinder-shadow {
  position: absolute;
  left: 50%; transform: translateX(-50%);
  bottom: -42px; width: 268px; height: 34px;
  background:
    radial-gradient(ellipse 64px 13px at 21% 52%,
      color-mix(in srgb, var(--kiwi-skin-dark, #4a3220) 45%, rgba(0,0,0,0.78)) 0%,
      rgba(0,0,0,0.20) 55%, transparent 92%),
    radial-gradient(ellipse 64px 13px at 79% 52%,
      color-mix(in srgb, var(--kiwi-skin-dark, #4a3220) 45%, rgba(0,0,0,0.78)) 0%,
      rgba(0,0,0,0.20) 55%, transparent 92%),
    radial-gradient(ellipse 48px 10px at 50% 42%,
      rgba(0,0,0,0.85) 0%,
      rgba(0,0,0,0.14) 60%, transparent 95%);
  pointer-events: none; z-index: 1;
  filter: blur(5px);
}
#cylinder-light-gradient {
  position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(to bottom, rgba(255,255,255,0.07) 0%, transparent 35%, rgba(0,0,0,0.08) 100%);
  pointer-events: none; z-index: 4;
}

/* ── 7. Prestige Level-Up Celebration ───────────────────────────────────── */
@keyframes prestigeFlash {
  0%   { opacity: 0; }
  15%  { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes prestigeZoom {
  0%   { transform: scale(1); }
  20%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}
#prestige-flash {
  position: fixed; inset: 0; pointer-events: none; z-index: 99996;
  background: radial-gradient(ellipse at 50% 50%, rgba(160,80,220,0.25) 0%, rgba(100,30,180,0.08) 60%, transparent 100%);
  animation: prestigeFlash 0.8s ease-out forwards;
}
.prestige-zoom-pop {
  animation: prestigeZoom 0.6s ease-out !important;
}

/* Prestige rain particles */
@keyframes prestigeRainFall {
  0%   { transform: translateY(-20px) rotate(0deg); opacity: 1; }
  100% { transform: translateY(100vh) rotate(720deg); opacity: 0; }
}
.prestige-rain-particle {
  position: fixed; top: 0; pointer-events: none; z-index: 99996;
  font-size: 16px; line-height: 1;
  animation: prestigeRainFall 1.8s ease-in forwards;
}

/* ── 8. Idle State Animations ───────────────────────────────────────────── */
@keyframes idleCylBreath {
  0%,100% { transform: translateX(-50%) scaleY(1); }
  50%     { transform: translateX(-50%) scaleY(1.008) scaleX(0.997); }
}
@keyframes idleKiwiSway {
  0%,100% { transform: translateX(-50%) rotate(0deg); }
  25%     { transform: translateX(-50%) rotate(0.5deg); }
  75%     { transform: translateX(-50%) rotate(-0.5deg); }
}
#cylinder-wrap.idle-breathe {
  animation: idleCylBreath 4s ease-in-out infinite;
}
#kiwi-wrap.idle-sway {
  animation: idleKiwiSway 5s ease-in-out infinite;
}

/* ── 9. Contextual Cursor Trails ────────────────────────────────────────── */
.cursor-trail-dot {
  position: fixed; pointer-events: none; z-index: 999999;
  width: 6px; height: 6px; border-radius: 50%;
  opacity: 0.7;
  animation: cursorTrailFade 0.4s ease-out forwards;
  contain: layout paint style; /* isolate from document layout/paint */
}
.cursor-trail-dot.streak-mode {
  width: 8px; height: 8px;
  box-shadow: 0 0 6px currentColor;
}
@keyframes cursorTrailFade {
  0%   { transform: scale(1); opacity: 0.7; }
  100% { transform: scale(0.2); opacity: 0; }
}
.cursor-trail-dot.cursor-trail-burst {
  animation-name: cursorTrailBurst;
  animation-timing-function: cubic-bezier(0.15, 0.8, 0.3, 1);
  border-radius: 0;
  background:
    linear-gradient(var(--plus-color, #fff), var(--plus-color, #fff)) center/100% 34% no-repeat,
    linear-gradient(var(--plus-color, #fff), var(--plus-color, #fff)) center/34% 100% no-repeat !important;
  /* will-change removed: short-lived elements with it force eager GPU layer allocation.
     Browsers composite transform+opacity animations automatically without the hint. */
}
@keyframes cursorTrailBurst {
  0%   { transform: translate(0, 0) scale(1.2); opacity: var(--burst-opacity, 0.9); }
  60%  { opacity: var(--burst-opacity, 0.9); }
  100% { transform: translate(var(--dx, 0), var(--dy, 0)) scale(0.3); opacity: 0; }
}

.cursor-trail-sparkle {
  position: fixed; pointer-events: none; z-index: 999999;
  font-size: 10px; line-height: 1;
  animation: cursorSparkleFade 0.5s ease-out forwards;
}
@keyframes cursorSparkleFade {
  0%   { transform: scale(1) rotate(0deg); opacity: 1; }
  100% { transform: scale(0.3) rotate(120deg); opacity: 0; }
}

/* ── Nostalgia Filter (CRT effect) ──────────────────────────────────────── */
#nostalgia-filter-el {
  /* Scanline spacing — scaled up on larger viewports via media queries below */
  --sl-gap: 2.5px;
  --sl-line-a: 3.25px;
  --sl-line-b: 3.75px;
  --sl-end: 5px;
  --sl-alpha: 0.20;
  position: fixed; inset: 0; pointer-events: none; z-index: 10000002;
  /* overlay darkens bright pixels and lightens dark ones — keeps CRT look without global dimming */
  mix-blend-mode: overlay;
  /* PERF: dropped backdrop-filter entirely. A 0.4px blur is below the
     perceptible threshold but the browser still copies the entire rendered
     backdrop into a separate buffer every frame and runs three shader passes
     on it (blur + brightness + contrast). The mix-blend-mode overlay plus
     the RGB-column gradient below already do the CRT shadow-mask job
     without any backdrop sampling. */
  /* backdrop-filter: blur(0.4px) brightness(1.10) contrast(1.03); */
  /* -webkit-backdrop-filter: blur(0.4px) brightness(1.10) contrast(1.03); */
  background:
    /* Shadow-mask RGB columns — 3px triad (R/G/B), half strength */
    repeating-linear-gradient(
      to right,
      rgba(255,  80,  80, 0.06) 0px,
      rgba(255,  80,  80, 0.06) 1px,
      rgba( 80, 255,  80, 0.06) 1px,
      rgba( 80, 255,  80, 0.06) 2px,
      rgba( 80,  80, 255, 0.06) 2px,
      rgba( 80,  80, 255, 0.06) 3px
    ),
    /* Horizontal scanlines — softened to 0.16 so overlay doesn't over-darken */
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0)              0px,
      rgba(0, 0, 0, 0)              var(--sl-gap),
      rgba(0, 0, 0, var(--sl-alpha)) var(--sl-line-a),
      rgba(0, 0, 0, var(--sl-alpha)) var(--sl-line-b),
      rgba(0, 0, 0, 0)              var(--sl-end)
    );
  /* Subtle screen curvature vignette (visible on both dark and light backgrounds) */
  box-shadow: inset 0 0 120px rgba(0, 0, 0, 0.35),
              inset 0 0 200px rgba(0, 0, 0, 0.15);
}

/* Thicker scanlines on larger displays so the pattern doesn't shrink into
   sub-pixel moiré on tall/4K screens */
@media (min-height: 900px){
  #nostalgia-filter-el {
    --sl-gap: 3.5px;
    --sl-line-a: 5px;
    --sl-line-b: 5px;
    --sl-end: 6px;
  }
}
@media (min-height: 1400px){
  #nostalgia-filter-el {
    --sl-gap: 5px;
    --sl-line-a: 7px;
    --sl-line-b: 8px;
    --sl-end: 9px;
    --sl-alpha: 0.22;
  }
}
