/* Special art intentionally owns the inner tile animation. Gravity therefore
   moves the whole grid item so its base colour and ability artwork stay fused. */
.m3j-game .match3-gem.falling.special{z-index:5;animation:m3j-special-unit-fall 320ms cubic-bezier(.18,.82,.28,1.08) both!important;animation-delay:var(--fall-delay,0ms)!important;backface-visibility:hidden;will-change:transform;contain:paint}
.m3j-game .match3-gem.falling.special>i{animation:none!important;transform:none!important;opacity:1!important}
.m3j-game .match3-gem.falling.special>i:after{opacity:1}
.m3j-game .match3-gem.falling.special.obstacle-mold>i>.m3j-obstacle-layer{visibility:visible!important;opacity:.72!important;animation:none!important;transform:none!important}
@keyframes m3j-special-unit-fall{from{transform:translate3d(var(--fall-x,0),var(--fall-y,var(--fall-offset)),0);opacity:1}72%{transform:translate3d(0,5%,0);opacity:1}to{transform:translate3d(0,0,0);opacity:1}}
@media(prefers-reduced-motion:reduce){.m3j-game .match3-gem.falling.special{animation-duration:.01ms!important;animation-delay:0ms!important}}

/* Keep the base gem and its special artwork fused during a drag/swap. */
.m3j-game .match3-gem.special.dragging>i,
.m3j-game .match3-gem.special.swap-neighbour>i,
.m3j-game .match3-gem.special.snapping>i,
.m3j-game .match3-gem.special.reverting>i,
.m3j-game .match3-gem.special.swap-committed>i{backface-visibility:hidden}
.m3j-game .match3-gem.swap-committed{z-index:6;will-change:transform;backface-visibility:hidden}

/* Ability artwork and the playable symbol must remain painted for the whole
   composite movement. These explicit layers also protect against a browser
   dropping a pseudo-element while its parent is GPU-transformed. */
.m3j-game .match3-gem.special>i:after{
  display:block!important;visibility:visible!important;opacity:1!important;
  backface-visibility:hidden;transform:translateZ(2px);
}
.m3j-game .match3-gem.obstacle-mold:not(.special)>i>.m3j-gem-symbol{
  display:grid!important;visibility:visible!important;opacity:1!important;
  position:absolute!important;inset:0!important;z-index:8!important;
  transform:translateZ(3px)!important;backface-visibility:hidden;
}
.m3j-game .match3-gem.obstacle-mold.special>i:after{z-index:8!important}
.m3j-game .match3-gem.obstacle-mold>i>.m3j-obstacle-layer{z-index:6!important}
/* Mold damage has one board-space release effect. Do not also restart the
   material overlay/pseudo animations on the tile that is about to be replaced;
   the two competing animations caused a visible green flash in cascades. */
.m3j-game .match3-gem.obstacle-damaged-mold.obstacle-hit>i>.m3j-obstacle-layer,
.m3j-game .match3-gem.obstacle-damaged-mold.obstacle-destroyed>i>.m3j-obstacle-layer{
  animation:none!important;visibility:visible!important;opacity:.72!important;
  transform:none!important;filter:drop-shadow(0 0 7px #4ade8090)!important;
}
.m3j-game .match3-gem.obstacle-damaged-mold:after{display:none!important}
.m3j-game .m3j-mold-burst{
  position:absolute;z-index:24;width:12.5%;aspect-ratio:1;margin:-6.25% 0 0 -6.25%;
  border:2px solid rgba(190,242,100,.9);border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(236,252,203,.92) 0 7%,rgba(74,222,128,.72) 10% 27%,rgba(21,128,61,.28) 38%,transparent 70%);
  box-shadow:0 0 14px rgba(74,222,128,.78);opacity:0;
  animation:m3j-mold-burst 430ms cubic-bezier(.16,.76,.25,1) var(--mold-burst-delay,0ms) both;
}
.m3j-game .m3j-mold-burst:before,.m3j-game .m3j-mold-burst:after{
  content:"";position:absolute;inset:28%;border-radius:45% 55% 38% 62%;
  background:#bef264;box-shadow:-13px 5px 0 -2px #4ade80,12px -7px 0 -3px #86efac;
}
.m3j-game .m3j-mold-burst.destroyed{filter:brightness(1.28)}
@keyframes m3j-mold-burst{0%{opacity:0;transform:scale(.3) rotate(-12deg)}24%{opacity:1}62%{opacity:.95;transform:scale(1.18) rotate(5deg)}100%{opacity:0;transform:scale(1.7) rotate(12deg)}}
@media(prefers-reduced-motion:reduce){.m3j-game .m3j-mold-burst{animation-duration:120ms}}

/* Ice shatters in board space because the released cell can collapse before
   its old obstacle layer has time to finish a DOM-bound animation. */
.m3j-game .m3j-ice-burst{
  position:absolute;z-index:25;width:12.5%;aspect-ratio:1;margin:-6.25% 0 0 -6.25%;
  pointer-events:none;opacity:0;filter:drop-shadow(0 2px 4px #0891b288);
  animation:m3j-ice-flash 520ms ease-out var(--ice-burst-delay,0ms) both;
}
.m3j-game .m3j-ice-burst:before{
  content:"";position:absolute;inset:13%;border:2px solid #e6fbff;border-radius:42% 58% 48% 52%;
  background:radial-gradient(circle,#fff 0 7%,#9eeaffb8 18%,#38bdf850 46%,transparent 70%);
  animation:m3j-ice-ring 460ms cubic-bezier(.15,.72,.24,1) var(--ice-burst-delay,0ms) both;
}
.m3j-game .m3j-ice-burst>i{
  --ice-angle:0deg;position:absolute;left:44%;top:40%;width:17%;height:24%;
  border-radius:55% 45% 60% 35%;background:linear-gradient(145deg,#fff 0 20%,#bff4ff 22% 58%,#38bdf8 60% 100%);
  clip-path:polygon(50% 0,100% 100%,0 78%);transform-origin:50% 72%;
  animation:m3j-ice-shard 510ms cubic-bezier(.12,.68,.22,1) var(--ice-burst-delay,0ms) both;
}
.m3j-game .m3j-ice-burst>i:nth-child(2){--ice-angle:60deg}.m3j-game .m3j-ice-burst>i:nth-child(3){--ice-angle:120deg}
.m3j-game .m3j-ice-burst>i:nth-child(4){--ice-angle:180deg}.m3j-game .m3j-ice-burst>i:nth-child(5){--ice-angle:240deg}.m3j-game .m3j-ice-burst>i:nth-child(6){--ice-angle:300deg}
.m3j-game .m3j-ice-burst.destroyed>i{filter:brightness(1.16) saturate(1.2)}
@keyframes m3j-ice-flash{0%{opacity:0}10%{opacity:1}68%{opacity:1}100%{opacity:0}}
@keyframes m3j-ice-ring{0%{opacity:0;transform:scale(.38) rotate(-8deg)}20%{opacity:1}100%{opacity:0;transform:scale(1.42) rotate(8deg)}}
@keyframes m3j-ice-shard{0%{opacity:0;transform:rotate(var(--ice-angle)) translateY(-3%) scale(.35)}16%{opacity:1}100%{opacity:0;transform:rotate(var(--ice-angle)) translateY(-185%) rotate(38deg) scale(.8)}}
@media(prefers-reduced-motion:reduce){.m3j-game .m3j-ice-burst,.m3j-game .m3j-ice-burst:before,.m3j-game .m3j-ice-burst>i{animation-duration:140ms!important}}

/* Mold is a translucent, movable infection on top of a normal playable gem.
   Never reuse the opaque fixed-blocker atlas frame: the underlying colour and
   symbol must remain readable both at rest and while the unit is falling. */
.m3j-game .match3-gem.obstacle-mold .m3j-obstacle-layer{
  inset:-7%!important;
  border:0!important;
  border-radius:0!important;
  background-color:transparent!important;
  background-image:url('/assets/images/match3/m3j-blocker-atlas-v2.png?v=2')!important;
  background-position:100% 0!important;
  background-repeat:no-repeat!important;
  background-size:400% 200%!important;
  opacity:1!important;
  filter:drop-shadow(0 0 6px #4ade8099)!important;
  box-shadow:none!important;
  mask-image:radial-gradient(circle at 50% 50%,#0000 0 34%,rgba(0,0,0,.68) 46%,#000 57%)!important;
  -webkit-mask-image:radial-gradient(circle at 50% 50%,#0000 0 34%,rgba(0,0,0,.68) 46%,#000 57%)!important;
}
.m3j-game .match3-gem.obstacle-mold .m3j-obstacle-layer em,.m3j-game .match3-gem.obstacle-mold .m3j-obstacle-layer b{display:none!important}
.m3j-game .match3-gem.obstacle-mold>i>.m3j-gem-symbol{position:absolute!important;z-index:8!important;inset:0!important;display:grid!important;width:100%!important;height:100%!important;margin:0!important;padding:0!important;place-items:center!important;opacity:1!important;filter:drop-shadow(0 2px 3px #0008);transform:none!important}

/* Resonance Crystal keeps its colour glyph on the exact optical centre. */
.m3j-game .match3-gem.obstacle-crystal .m3j-crystal-target{
  inset:50% auto auto 50%!important;
  display:grid!important;
  place-items:center!important;
  margin:0!important;
  line-height:1!important;
  text-align:center!important;
  transform:translate(-50%,-50%)!important;
}
/* Every layered blocker uses one shared durability-counter position. */
.m3j-game .match3-gem.m3j-obstacle .m3j-obstacle-layer>b{
  top:auto!important;
  right:0!important;
  bottom:0!important;
  left:auto!important;
  z-index:9!important;
}
/* A long chain keeps every resolution step visible, but uses a tighter visual
   beat so it cannot monopolise the main thread for several seconds. */
.m3j-game .match3-board.m3j-cascade-compact .match3-gem.clearing i,
.m3j-game .match3-board.m3j-cascade-compact .match3-gem.clearing:after{animation-duration:145ms!important}
.m3j-game .match3-board.m3j-cascade-compact .match3-gem.falling,
.m3j-game .match3-board.m3j-cascade-compact .match3-gem.falling>i,
.m3j-game .match3-board.m3j-cascade-compact .match3-gem.falling .m3j-obstacle-layer{animation-duration:185ms!important}
.m3j-game .match3-gem.obstacle-chain>.m3j-obstacle-layer{z-index:7!important;inset:1%!important;opacity:1!important;background-color:transparent!important;background-image:url('/assets/images/match3/m3j-blocker-atlas-v2.png?v=2')!important;background-repeat:no-repeat!important;background-size:400% 200%!important;background-position:33.333% 100%!important;filter:drop-shadow(0 4px 6px #0008)!important}
.m3j-game .match3-board.m3j-cascade-compact .m3j-mold-burst{animation-duration:180ms!important}

.m3j-game .match3-gem.falling.obstacle-mold:not(.special){z-index:4;animation:m3j-mold-composite-fall 300ms cubic-bezier(.2,.82,.28,1) both!important;animation-delay:var(--fall-delay,0ms)!important;backface-visibility:hidden;will-change:transform}
.m3j-game .match3-gem.falling.obstacle-mold:not(.special)>i{animation:none!important;transform:none!important;opacity:1!important}
.m3j-game .match3-gem.obstacle-mold:not(.special)>i>.m3j-gem-symbol{position:absolute!important;z-index:8!important;inset:0!important;display:grid!important;width:100%!important;height:100%!important;margin:0!important;padding:0!important;place-items:center!important;visibility:visible!important;opacity:1!important;transform:none!important}
.m3j-game .match3-gem.falling.obstacle-mold:not(.special)>i>.m3j-obstacle-layer{visibility:visible!important;opacity:.72!important;animation:none!important;transform:none!important}
@keyframes m3j-mold-composite-fall{from{transform:translate3d(var(--fall-x,0),var(--fall-y,var(--fall-offset)),0);opacity:.72}72%{transform:translate3d(0,4%,0);opacity:1}to{transform:translate3d(0,0,0);opacity:1}}
.m3j-move-bonus.pulse strong{animation:m3j-bonus-tick 140ms ease-out}
@keyframes m3j-bonus-tick{0%{transform:translateY(7px) scale(.82);opacity:.25}55%{transform:translateY(-2px) scale(1.12);opacity:1}100%{transform:none;opacity:1}}
