/* Table actions show visible cause and effect without holding up engine play. */
@media(prefers-reduced-motion:no-preference) {
 .game-shell.fx-deal .board {animation:deal-board-shine 1.1s ease-out both;}
 .game-shell.fx-deal .hand .tile {
   animation:deal-face-in .62s cubic-bezier(.12,.88,.2,1.3) both;
   animation-delay:calc(var(--tile-order,0) * 55ms);
 }
 .game-shell.fx-deal .opponent .tile-back {
   animation:deal-back-in .45s cubic-bezier(.17,.88,.24,1.19) both;
   animation-delay:calc(var(--tile-order,0) * 28ms);
 }
 .game-shell.fx-draw .hand .tile.drawn {
   animation:draw-landing .62s cubic-bezier(.14,.87,.27,1.28) both;
 }
 .game-shell .hand .tile.selected {
   animation:selection-jolt .27s cubic-bezier(.15,1.5,.25,1) both;
 }
 .game-shell .hand .tile.selected:after {
   content:'';position:absolute;inset:-4px;z-index:-1;border:2px solid #ffe49b;
   border-radius:7px;pointer-events:none;
   box-shadow:0 0 11px #ffdc94,0 0 21px #ffe59b7a;
   animation:selected-aura 1.15s ease-in-out infinite alternate;
 }
 .game-shell .hand .tile.riichi-option {
   animation:riichi-options 1.1s ease-in-out infinite alternate;
 }
 .game-shell .river .last-discard .discard-tile {
   animation:river-impact .49s cubic-bezier(.12,.95,.2,1.3) both;
   outline:2px solid #f9d789;outline-offset:2px;
 }
 .game-shell .opponent.acting .opp-label {animation:opponent-active 1s ease-in-out alternate infinite;}
 .game-shell .action.primary {transition:transform .18s,box-shadow .18s,filter .18s;}
 .game-shell .action.primary:active {transform:scale(.92);box-shadow:0 0 22px #efd486;}
 .game-shell .action[data-action="ron"],.game-shell .action[data-action="tsumo"] {
   animation:win-button-ready 1.25s ease-in-out infinite alternate;
 }
 .game-shell .coach-dialogue.is-praising h2 {
   animation:coach-celebrate .5s cubic-bezier(.18,1.5,.3,1);
 }
 .game-shell .support-aside {animation:coach-side-in .4s ease-out both;}
 .win-moment:before,.victory-overlay:before {
   content:'';position:absolute;inset:0;pointer-events:none;
   background:radial-gradient(circle at 50% 39%,#ffe2a72c 0%,transparent 65%);
   animation:win-flash .85s ease-out both;
 }
 .win-moment-inner {animation:win-entry .68s cubic-bezier(.15,1.35,.25,1) both;}
 .victory-stage img {animation:coach-celebrate .65s cubic-bezier(.15,1.25,.23,1) both;}
 .fx-declare {
   position:fixed;left:50%;top:39%;z-index:80;pointer-events:none;
   color:#ffe5a2;text-align:center;white-space:nowrap;
   text-shadow:0 0 16px #ffd26b,0 4px 20px #2d1a00;
   font-size:clamp(34px,10vw,70px);font-weight:950;letter-spacing:.09em;
   animation:declaration-hit .9s ease-out both;
 }
 .fx-spark {
   position:fixed;pointer-events:none;z-index:79;border-radius:50%;
   width:8px;height:8px;background:#ffdf8c;box-shadow:0 0 11px #ffd16a;
   animation:spark-pop .44s cubic-bezier(.25,.65,.4,1) both;
 }
 @keyframes deal-board-shine{
   0%{box-shadow:inset 0 0 0 2px #ffe1a800,0 0 0 #0000}
   32%{box-shadow:inset 0 0 0 3px #ffe5a2b0,0 0 36px #ffe1a64a}
   100%{box-shadow:inset 0 0 0 2px #acc79f18,0 0 0 #0000}
 }
 @keyframes deal-face-in{
   0%{opacity:0;transform:translate3d(0,-126px,0) rotate(-12deg) scale(.62);filter:brightness(1.7)}
   72%{opacity:1;transform:translate3d(0,5px,0) rotate(1.5deg) scale(1.04)}
   100%{opacity:1;transform:translate3d(0,0,0) rotate(0) scale(1);filter:brightness(1)}
 }
 @keyframes deal-back-in{
   0%{opacity:0;transform:translate3d(0,-65px,0) rotate(-15deg) scale(.5)}
   80%{opacity:1;transform:translate3d(0,3px,0) rotate(2deg) scale(1.07)}
   100%{opacity:1;transform:none}
 }
 @keyframes draw-landing{
   0%{opacity:.3;transform:translate3d(38px,-83px,0) rotate(12deg) scale(.75);filter:brightness(1.8)}
   64%{opacity:1;transform:translate3d(0,7px,0) rotate(-3deg) scale(1.08)}
   100%{opacity:1;transform:none;filter:brightness(1)}
 }
 @keyframes selection-jolt {
   0%{transform:translateY(-2px) scale(.94)}
   54%{transform:translateY(-18px) scale(1.07)}
   100%{transform:translateY(-14px) scale(1)}
 }
 @keyframes selected-aura {to{box-shadow:0 0 22px #ffd86f,0 0 32px #ffe497bd;opacity:.6}}
 @keyframes riichi-options {to{box-shadow:0 0 15px #ffd06db3;filter:brightness(1.16)}}
 @keyframes river-impact {
   0%{opacity:.16;transform:translateY(-24px) rotate(-16deg) scale(1.38);filter:brightness(1.5)}
   65%{opacity:1;transform:translateY(6px) rotate(4deg) scale(.93)}
   100%{opacity:1;transform:none;filter:brightness(1)}
 }
 @keyframes opponent-active {to{box-shadow:0 0 16px #f3d18577}}
 @keyframes win-button-ready {to{filter:brightness(1.3);box-shadow:0 0 24px #ffdb85}}
 @keyframes coach-celebrate{
   0%{opacity:.35;transform:translateY(9px) scale(.92)}
   65%{opacity:1;transform:translateY(-4px) scale(1.04)}
   100%{opacity:1;transform:none}
 }
 @keyframes coach-side-in {from{opacity:0;transform:translateX(22px)}to{opacity:1;transform:none}}
 @keyframes win-flash {0%{opacity:0}25%{opacity:1}100%{opacity:.35}}
 @keyframes win-entry {0%{opacity:0;transform:scale(.78) rotate(-3deg)}70%{opacity:1;transform:scale(1.06) rotate(1deg)}100%{transform:none}}
 @keyframes declaration-hit {0%{transform:translate(-50%,-15%) scale(2);opacity:0}20%{opacity:1}50%{transform:translate(-50%,0) scale(.95)}100%{transform:translate(-50%,0) scale(1.05);opacity:0}}
 @keyframes spark-pop {0%{opacity:1;transform:translate(0,0) scale(1.5)}100%{opacity:0;transform:translate(var(--sx,0),var(--sy,0)) scale(.1)}}
}
.fx-flying-tile {
 position:fixed!important;pointer-events:none!important;z-index:80!important;
 margin:0!important;transition:none!important;animation:none!important;
 transform-origin:center center;will-change:transform,opacity;
 box-shadow:0 6px 9px #0008,0 0 19px #ffd66e9e!important;
}
