/* Ruch V1.1 („żeby czuło się jak gra”): keyframes przeniesione z Państw Miast pod polskimi nazwami, klasy z prefiksem ru-.
   Zasada 9: animujemy tylko transform i opacity (także translate/scale/rotate). Poświaty to gotowe warstwy ::after z gradientem,
   animowana jest tylko ich opacity. Żadnego filter, backdrop-filter ani mask. Nieskończone: tylko ru-oddech (mały element). */

/* rozdanie kart z dołu ekranu (PM deal) i kołysanie w ręce (PM cardBob, tu 3 cykle) */
@keyframes rozdanie{0%{transform:translate(var(--dx,0),75vh) rotate(calc(var(--rot,0deg) * 7)) scale(.7);opacity:0}12%{opacity:1}78%{transform:translate(0,0) rotate(calc(var(--rot,0deg) * -.6)) scale(1.03)}100%{transform:translate(0,0) rotate(var(--rot,0deg)) scale(1)}}
/* odrzucona karta (PM cardAway) */
/* wybór (PM chosen bez filter): skala w keyframes, poświata z ::after */
@keyframes wybor{0%{transform:rotate(var(--rot,0deg))}50%{transform:scale(1.12)}100%{transform:scale(1.04)}}
/* lot czerwonej karty do celu (PM flyAway); --fx, --fy liczone raz z getBoundingClientRect */
@keyframes lot{to{transform:translate(var(--fx,0),var(--fy,-300px)) rotate(540deg) scale(.15);opacity:.2}}
/* obrót: koszulka na twarz (rotateY) i kafelek odsłony (rotateX, PM flipy) */
@keyframes obrot{from{transform:rotate(var(--rot,0deg)) rotateY(180deg)}to{transform:rotate(var(--rot,0deg)) rotateY(0)}}
.ru-obrotX{animation:obrotX .5s ease-in-out}
@keyframes obrotX{50%{transform:rotateX(90deg)}}
/* lądowanie (PM land) */
.ru-ladowanie{animation:ladowanie .45s cubic-bezier(.2,.9,.3,1.4)}
@keyframes ladowanie{0%{transform:scale(.6) rotate(-8deg)}100%{transform:none}}
/* kafelek spada i sprężynuje (PM tileDrop) */
.ru-spadek{animation:spadek .62s cubic-bezier(.3,.6,.4,1) both;animation-delay:var(--dd,0s)}
@keyframes spadek{0%{transform:translateY(-70vh) scale(.8,1.25)}55%{transform:translateY(0) scale(1.18,.78)}72%{transform:translateY(-16px) scale(.94,1.08)}86%{transform:translateY(0) scale(1.04,.96)}100%{transform:none}}
/* podskok awatara (PM crewHop), fala po --i */
.ru-podskok{animation:podskok .45s cubic-bezier(.2,.9,.3,1.4) both;animation-delay:calc(var(--i,0) * 45ms)}
@keyframes podskok{40%{transform:translateY(-14px) scale(1.06,.94)}}
/* uderzenie sceny (PM punch) */
.ru-uderzenie{animation:uderzenie .3s ease-out;transform-origin:50% 60%}
@keyframes uderzenie{0%{transform:scale(1)}35%{transform:scale(1.025)}100%{transform:scale(1)}}
/* wiersz wjeżdża (PM pt-rowIn) */
.ru-wjazd{animation:wjazd .45s cubic-bezier(.2,.8,.2,1) both;animation-delay:calc(var(--i,0) * 80ms)}
@keyframes wjazd{from{opacity:0;transform:translateX(-14px)}to{opacity:1;transform:none}}
/* wstrząs (PM pt-shakeX) */
.ru-drzenie{animation:drzenie .45s ease-in-out}
@keyframes drzenie{0%,100%{transform:translateX(0)}20%{transform:translateX(-7px)}40%{transform:translateX(6px)}60%{transform:translateX(-4px)}80%{transform:translateX(3px)}}
/* punkty wyskakują (PM pt-ptspop) i małe wejście awatara (PM pt-popIn) */
.ru-wyskok{animation:wyskok .45s cubic-bezier(.2,.9,.3,1.5) both}
@keyframes wyskok{from{transform:scale(.3);opacity:0}to{transform:none;opacity:1}}
.ru-pop{animation:wyskok .35s cubic-bezier(.2,.9,.3,1.4) both;animation-delay:calc(var(--i,0) * 90ms)}
/* stuknięcie (litera ldBump) i ugięcie pod palcem (koncepcja C) */
.ru-stuk{animation:stuk .28s ease-out}
@keyframes stuk{50%{transform:scale(1.08)}}
/* pośpiech: pigułka sekund drga (litera ldHurry) */
.ru-pospiech{animation:pospiech .5s ease-in-out}
@keyframes pospiech{50%{transform:scale(1.18) rotate(-4deg)}}
/* korona spada (pojedynek pjCrown), pozycja bazowa translateX(-50%) */
.ru-korona{animation:korona .7s cubic-bezier(.3,1.4,.5,1) both;animation-delay:var(--dd,0s)}
@keyframes korona{0%{transform:translate(-50%,-90px) rotate(-25deg);opacity:0}60%{transform:translate(-50%,4px) rotate(8deg);opacity:1}80%{transform:translate(-50%,-3px) rotate(-3deg)}100%{transform:translate(-50%,0) rotate(-6deg);opacity:1}}
/* pierścień rozchodzący się (PM pt-ringOut), 2 razy */
@keyframes fala{from{transform:scale(.7);opacity:.9}to{transform:scale(1.7);opacity:0}}
/* podium i plansza wjeżdżają z dołu (PM pt-rise) */
.ru-rise{animation:rise .7s cubic-bezier(.2,.9,.3,1.2) both;animation-delay:var(--dd,0s)}
@keyframes rise{from{transform:translateY(240px);opacity:0}to{transform:none;opacity:1}}
/* kurtyna TV (PM curtainIn/Out, letter .curtain): czerwone pasy i złoty lambrekin, sam CSS */
.ru-kurtyna{position:absolute;inset:0;z-index:4;pointer-events:none;border-radius:inherit;overflow:hidden}
.ru-kurtyna i{position:absolute;top:0;bottom:0;width:52%;background:repeating-linear-gradient(90deg,#8a0c28 0,#d8243f 18%,#ff6a80 30%,#c41a3c 42%,#8a0c28 50%);background-size:calc(2.8*var(--u,10px)) 100%;box-shadow:inset 0 -5px 0 #ffd23f}
.ru-kurtyna i.l{left:0;transform-origin:left}.ru-kurtyna i.r{right:0;transform-origin:right}
.ru-kurtyna b{position:absolute;left:0;right:0;top:0;height:22%;background:radial-gradient(circle at 50% 0,#e0284a 60%,transparent 62%) 0 0/12.5% 200%,linear-gradient(#ffd23f 0 3px,#d8243f 3px);border-bottom:2px solid #ffd23f;transition:transform .6s .3s}
.ru-kurtyna.otwarta i{animation:kurtynaOtworz .8s cubic-bezier(.5,0,.3,1) forwards}
.ru-kurtyna.otwarta b{transform:translateY(-110%)}
@keyframes kurtynaOtworz{to{transform:scaleX(.08)}}
/* żywy awatar na profilu (PM avBreathP/avPopP); jedyna nieskończona animacja V1.1 */
@keyframes zmiana{0%{transform:scale(1.4) rotate(-8deg)}45%{transform:scale(1.13,1.05) rotate(2.5deg)}70%{transform:scale(1.04,1.1)}100%{transform:scale(1.02)}}
@keyframes oddech{0%,100%{transform:scale(1.02) rotate(0)}30%{transform:scale(1.05) rotate(-2.2deg)}70%{transform:scale(1.035) rotate(1.4deg)}}
@keyframes promienie{from{transform:rotate(-90deg) scale(.4);opacity:0}to{transform:none;opacity:1}}
/* latarnia na Ścieżce gasi spadek */
@keyframes latarnia{0%{opacity:0;transform:translateY(8px) scale(.5)}25%{opacity:1;transform:none}80%{opacity:1}100%{opacity:0}}
/* błysk dobrze/źle w szybkiej rundzie: warstwa ::after z kolorem, tylko opacity (zamiast box-shadow 999px) */
.ru-blysk{position:relative}
.ru-blysk::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;opacity:0;background:var(--bl,rgba(61,220,151,.18))}
.ru-blysk.ok::after{--bl:rgba(61,220,151,.2);animation:blysk .45s ease-out}
.ru-blysk.zle::after{--bl:rgba(255,92,122,.22);animation:blysk .45s ease-out}
@keyframes blysk{30%{opacity:1}100%{opacity:0}}
/* iskierki przy zmianie postaci na profilu (pozycję animuje WAAPI w ruch.js iskry()) */
.ru-iskra{position:absolute;left:50%;top:50%;width:9px;height:9px;margin:-4.5px;border-radius:2px;rotate:45deg;pointer-events:none;z-index:3}
/* latarnia zapalona nad awatarem na Ścieżce (gasi spadek) */
/* reżyser (rezyser.js): stan „tuż przed” odsłoną i ukrywanie kroków, które jeszcze nie nastąpiły */
.ans.ru-czeka .a.a{--ac:#5d4cb8;--ad:#3e3090;color:#fff;opacity:1} /* mocniej niż .ans .a.c0 z app.css */
.ans.ru-czeka .a.a .l{color:#3e3090}
.ru-ukryj{opacity:0}
/* koszulka strażnika na karcie dziedziny: zakrywa kartę, przy odkryciu składa się w poziomie (scaleX, bez 3D) */
/* pigułka dźwięku na telewizorze */
.ru-dzw{cursor:pointer;margin-left:calc(1*var(--u,4px))}
/* szybka runda: błysk przez ::after zamiast animowanego box-shadow 999px z app.css */
#spq.flash-ok,#spq.flash-bad{animation:none}
/* fajerwerki na koniec: dwa cykle zamiast w nieskończoność */
.fw{animation-iteration-count:2!important}
/* płótno konfetti: zawsze na wierzchu, nic nie łapie */
#fxc{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:90}
@media (prefers-reduced-motion:reduce){
  .ru-spadek,.ru-uderzenie,.ru-wjazd,.ru-podskok,.ru-rise,.ru-obrotX,.ru-ladowanie,.ru-drzenie,.ru-pospiech,.ru-korona{animation:wyskokRM .15s ease-out both!important}
  .ru-kurtyna{display:none}
  @keyframes wyskokRM{from{opacity:0}to{opacity:1}}
}
