/* Star Swap. The cast ring hangs above the caster and follows them; the swapped
   projectile is deliberately NOT .projectile--duckies-pack, which is pinned to
   64x30 with !important in game.css and would crush these sprites to a sliver. */

.ss-cast {
  position: absolute;
  width: 0;
  height: 0;
  pointer-events: none;
  z-index: 90;
}

.ss-orb {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 120px;
  height: 120px;
  object-fit: contain;
  transform-origin: center;
  pointer-events: none;
  will-change: transform, opacity;
  filter:
    drop-shadow(0 0 10px var(--ss-glow, #fff))
    drop-shadow(0 0 26px var(--ss-glow, #fff))
    drop-shadow(0 6px 10px rgba(0, 0, 0, .45));
}

/* Reveal flash + shockwave behind the winner. */
.ss-flash {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  transform: translate(-50%, 50%) scale(0);
  opacity: 0;
  pointer-events: none;
  background: radial-gradient(circle, #fff 0%, var(--ss-glow, #fff) 38%, transparent 70%);
  box-shadow: 0 0 60px 20px var(--ss-glow, #fff);
}
.ss-flash.is-on {
  animation: ss-flash-pop 600ms ease-out forwards;
}
@keyframes ss-flash-pop {
  0%   { transform: translate(-50%, 50%) scale(0);   opacity: 0; }
  35%  { transform: translate(-50%, 50%) scale(5.5); opacity: .95; }
  100% { transform: translate(-50%, 50%) scale(11);  opacity: 0; }
}

/* The swapped projectile. 190px keeps a 320px sprite readable in flight without
   swamping the screen; the hitbox is unchanged and still star-sized. */
.projectile.projectile--star-swap {
  width: 190px;
  height: 190px;
  background: transparent;
  z-index: 80;
}
.projectile.projectile--star-swap::before,
.projectile.projectile--star-swap::after {
  display: none !important;
  content: none !important;
}
.projectile.projectile--star-swap .projectile-art--star-swap {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  /* The parent .projectile already carries scaleX(dir), so mirroring for a
     left-hand throw comes free. This transform only has to point the sprite
     to the RIGHT in the parent's un-mirrored space. */
  transform: scaleX(var(--ss-flip, 1)) rotate(var(--ss-rot, 0deg));
  filter:
    var(--ss-tint, saturate(1))
    drop-shadow(0 0 12px rgba(255, 255, 255, .9))
    drop-shadow(0 0 26px var(--ss-rim, rgba(120, 220, 255, .8)))
    drop-shadow(0 6px 10px rgba(0, 0, 0, .4));
}

/* Flight orientation, measured off each sprite's own artwork. Everything leads
   with its business end; only the hammer tumbles. */
.projectile.projectile--star-swap[data-star-swap-object="sword"]   { --ss-rot: 90deg; }  /* blade points up */
.projectile.projectile--star-swap[data-star-swap-object="rocket"]  { --ss-rot: 66deg; }  /* nose points up-right */
.projectile.projectile--star-swap[data-star-swap-object="kart"]    { --ss-flip: -1; }    /* nose cone faces left */
/* shark already swims right; grenade and vending machine ride upright, facing forward. */

.projectile.projectile--star-swap[data-star-swap-object="hammer"] .projectile-art--star-swap {
  animation: ss-proj-spin 620ms linear infinite;
}
@keyframes ss-proj-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Three go out per Triple Throw. Leave the first true to the artwork and recolour
   the other two, so a burst reads as three objects rather than one smear. */
.projectile.projectile--star-swap[data-star-swap-shot="1"] {
  --ss-tint: hue-rotate(155deg) saturate(1.75);
  --ss-rim: rgba(120, 255, 190, .85);
}
.projectile.projectile--star-swap[data-star-swap-shot="2"] {
  --ss-tint: hue-rotate(-95deg) saturate(1.45) brightness(1.08);
  --ss-rim: rgba(255, 150, 245, .85);
}

@media (prefers-reduced-motion: reduce) {
  .ss-flash.is-on { animation-duration: 1ms; }
  .projectile.projectile--star-swap[data-star-swap-object="hammer"] .projectile-art--star-swap { animation: none; }
}
