/* L2OKO motion (DESIGN_SYSTEM.md §7): lightning, embers and a running edge on the paid places, a sheen on paid rows,
   a live VIP badge, panels rising in, hover lifts, a beating countdown in the last ten minutes.
   Everything is under .fx-on, which public/js/motion.js sets only without prefers-reduced-motion.
   Only transform and opacity are animated; loops pause while their block is off screen (.fx without .is-vis). */

/* ---------- shared layers ---------- */
.fx { isolation: isolate; }
.fx-flash, .fx-sparks, .fx-glow, .fx-ring { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; }
.fx-bolt { position: absolute; pointer-events: none; overflow: visible; opacity: 0; will-change: opacity; filter: drop-shadow(0 0 5px rgba(170, 205, 255, .85)); }
.fx-bolt path { fill: none; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.fx-bolt-glow { stroke: rgba(150, 200, 255, .5); stroke-width: 6; }
.fx-bolt-core { stroke: #f4f8ff; stroke-width: 2; }

/* flicker of a strike: two flashes and a fade, at the start of every cycle */
@keyframes fx-strike {
  0%, 5% { opacity: 0; }
  5.6% { opacity: 1; }
  6.6% { opacity: .15; }
  7.6% { opacity: 1; }
  8.6% { opacity: .55; }
  12% { opacity: 0; }
  100% { opacity: 0; }
}
@keyframes fx-flash {
  0%, 5% { opacity: 0; }
  5.6% { opacity: .9; }
  6.6% { opacity: .2; }
  7.6% { opacity: 1; }
  14% { opacity: 0; }
  100% { opacity: 0; }
}
.fx-flash { z-index: 0; opacity: 0; will-change: opacity; background: radial-gradient(55% 90% at var(--fx-at, 60%) 0, rgba(190, 215, 255, .32), rgba(190, 215, 255, 0) 70%); }

/* embers */
.fx-sparks { z-index: 1; overflow: hidden; }
.fx-sparks i {
  position: absolute; left: var(--x); bottom: -4px; width: 3px; height: 3px; border-radius: 50%;
  background: #ffe2b0; box-shadow: 0 0 6px 1px rgba(255, 157, 69, .85);
  opacity: 0; will-change: transform, opacity;
  animation: fx-rise var(--t) linear var(--d) infinite;
}
@keyframes fx-rise {
  0% { opacity: 0; transform: translate(0, 0) scale(var(--s)); }
  12% { opacity: 1; }
  75% { opacity: .75; }
  100% { opacity: 0; transform: translate(var(--dx), calc(var(--rise, 120px) * -1)) scale(.2); }
}

/* soft breathing glow around a paid card */
.fx-glow { z-index: 0; opacity: .35; box-shadow: 0 0 22px 1px rgba(255, 140, 50, .38); will-change: opacity; animation: fx-breathe 3.2s ease-in-out var(--fx-d, 0s) infinite alternate; }
@keyframes fx-breathe { to { opacity: 1; } }

/* running edge */
.fx-ring {
  z-index: 4; inset: -1px; padding: 2px; overflow: hidden;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
.fx-ring i {
  --c: var(--fire-edge);
  position: absolute; left: 50%; top: 50%;
  width: var(--fx-dg, 700px); height: var(--fx-dg, 700px); margin: calc(var(--fx-dg, 700px) / -2) 0 0 calc(var(--fx-dg, 700px) / -2);
  background: repeating-conic-gradient(from 0deg, transparent 0 30%, rgba(255, 180, 105, 0) 30%, var(--c) 46%, #fff6e6 49%, transparent 50%);
  will-change: transform;
  animation: fx-spin 6s linear var(--fx-d, 0s) infinite;
}
@keyframes fx-spin { to { transform: rotate(1turn); } }

/* off screen: everything stands still */
.fx:not(.is-vis) .fx-bolt, .fx:not(.is-vis) .fx-flash, .fx:not(.is-vis) .fx-sparks i, .fx:not(.is-vis) .fx-glow, .fx:not(.is-vis) .fx-ring i,
.fx:not(.is-vis) > .row-a::after, .fx:not(.is-vis) .crown, .fx:not(.is-vis) .badge-vip::after, .fx:not(.is-vis) .badge-new::after, .fx:not(.is-vis) .btn-fire::after { animation-play-state: paused !important; }

/* ---------- hero: the top places ---------- */
.fx-on .slide .fx-flash { z-index: 1; --fx-at: 88%; }
.fx-on .slide .fx-bolt { z-index: 1; left: 76%; width: 15%; top: calc(var(--hdr-h) + 34px); height: calc(76% - var(--hdr-h) - 34px); }
.fx-on .slide .fx-sparks { z-index: 1; left: 40%; --rise: 300px; }
.fx-on .slide-free .fx-sparks { left: 0; }
.fx-on .slide-free .fx-sparks i { background: #fff1c4; box-shadow: 0 0 6px 1px rgba(242, 200, 91, .8); }
.fx-on .slide.is-on .fx-bolt { animation: fx-strike var(--hero-every) linear infinite; }
.fx-on .slide.is-on .fx-flash { animation: fx-flash var(--hero-every) linear infinite; }

/* The gold name (background-clip: text + drop-shadow) is never animated, nor its heading: some browsers (GPU
   Chrome among them) then drop the gradient and leave only the dark shadow - the name went black (01.11d).
   A switched-to slide: the lines around the name rise in one by one. */
.fx-on .slide.fx-in .slide-body > :not(.slide-name) { animation: fx-up .6s var(--ease) both; }
.fx-on .slide.fx-in .slide-body > :nth-child(2) { animation-delay: .06s; }
.fx-on .slide.fx-in .slide-body > :nth-child(3) { animation-delay: .12s; }
.fx-on .slide.fx-in .slide-body > :nth-child(4) { animation-delay: .18s; }
.fx-on .slide.fx-in .slide-body > :nth-child(5) { animation-delay: .24s; }
.fx-on .slide.fx-in .slide-body > :nth-child(6) { animation-delay: .3s; }
@keyframes fx-up { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* the crown on the active hero tab */
.fx-on .hero-tab[aria-selected="true"] .i { animation: fx-crown 2.4s ease-in-out infinite; }
@keyframes fx-crown { 0%, 70%, 100% { transform: none; } 80% { transform: scale(1.22) rotate(-8deg); } 90% { transform: scale(1.05) rotate(4deg); } }

/* «Играть» on the paid places: a light runs across now and then */
.fx-on .slide .btn-fire, .fx-on .topwin-play { overflow: hidden; isolation: isolate; }
.fx-on .slide .btn-fire::after, .fx-on .topwin-play::after {
  content: ""; position: absolute; z-index: -1; top: -2px; bottom: -2px; left: 0; width: 38%; pointer-events: none;
  background: linear-gradient(100deg, rgba(255, 255, 255, 0), rgba(255, 240, 220, .38) 50%, rgba(255, 255, 255, 0));
  transform: translateX(-130%) skewX(-18deg);
  animation: fx-btn-sheen 4.8s ease-in-out var(--fx-d, 0s) infinite;
}
@keyframes fx-btn-sheen { 0%, 72% { transform: translateX(-130%) skewX(-18deg); } 92%, 100% { transform: translateX(330%) skewX(-18deg); } }

/* ---------- TOP / VIP windows above the lists ---------- */
.fx-on .topwin.fx { transition: transform .25s var(--ease), border-color var(--t-fast); }
/* the strike lands on «Играть»: the bolt runs behind the button, above and below it */
.fx-on .topwin .fx-bolt { z-index: 0; right: 16px; width: 104px; top: -2px; height: calc(100% + 4px); animation: fx-strike 7s linear var(--fx-d, 0s) infinite; }
/* with the «Пожаловаться» flag after the button (trust.css) the button sits 32 px further left */
.fx-on .topwin:has(> .rp-win) .fx-bolt { right: 46px; }
.fx-on .topwin .fx-flash { --fx-at: 88%; animation: fx-flash 7s linear var(--fx-d, 0s) infinite; }
.fx-on .topwin .fx-sparks { --rise: 80px; }
.fx-on .topwin.t-top .fx-bolt-glow, .fx-on .tcard.t-top .fx-bolt-glow { stroke: rgba(255, 170, 90, .55); }
.fx-on .topwin.t-top .fx-bolt, .fx-on .tcard.t-top .fx-bolt { filter: drop-shadow(0 0 4px rgba(255, 170, 90, .9)); }
.fx-on .topwin.t-vip .fx-glow, .fx-on .topwin.t-divine .fx-glow, .fx-on .tcard.t-divine .fx-glow { box-shadow: 0 0 22px 1px rgba(242, 200, 91, .3); }
.fx-on .t-vip .fx-ring i, .fx-on .t-divine .fx-ring i { --c: var(--gold); }
.fx-on .t-vip .fx-ring i { animation-duration: 9s; }
.fx-on .topwin.t-vip .fx-ring { opacity: .8; }
.fx-on .topwin-tag .i { animation: fx-crown 3.2s ease-in-out var(--fx-d, 0s) infinite; }
.fx-on .topwin:hover { transform: translateY(-2px); }

/* ---------- today: cards ---------- */
.fx-on .tcard.fx > .tcard-a { position: relative; z-index: 2; }
.fx-on .tcard { transition: border-color var(--t-fast), background-color var(--t-fast), transform .25s var(--ease); }
.fx-on .tcard:hover { transform: translateY(-2px); }
.fx-on .tcard .fx-bolt { z-index: 1; left: 2%; width: 30%; top: -2px; height: calc(100% + 4px); animation: fx-strike 7s linear var(--fx-d, 0s) infinite; }
.fx-on .tcard .fx-flash { z-index: 1; --fx-at: 15%; animation: fx-flash 7s linear var(--fx-d, 0s) infinite; }
.fx-on .tcard .fx-sparks { --rise: 90px; }
.fx-on .tcard.t-top .fx-sparks i, .fx-on .topwin.t-top .fx-sparks i { background: #ffd9a8; }
.fx-on .tcard.t-divine .fx-sparks i, .fx-on .topwin.t-divine .fx-sparks i { background: #fff1c4; box-shadow: 0 0 6px 1px rgba(242, 200, 91, .8); }

/* portraits come a little closer under the cursor */
.fx-on .ava img, .fx-on .tcard-ava img, .fx-on .topwin-ava img { transition: transform .35s var(--ease); }
.fx-on .row-a:hover .ava img, .fx-on .tcard:hover .tcard-ava img, .fx-on .topwin:hover .topwin-ava img { transform: scale(1.08); }

/* countdown: the last ten minutes beat once a second (home.js sets .is-soon) */
.fx-on .tcard-clock.is-soon, .fx-on .today-clock.is-soon { transform-origin: 0 60%; animation: fx-beat 1s ease-out infinite; }
@keyframes fx-beat { 0% { transform: scale(1.07); } 35%, 100% { transform: none; } }
.tcard-clock.is-soon, .today-clock.is-soon { color: var(--fire-edge); }

/* ---------- paid rows in the lists ---------- */
/* a sheen runs under the text of TOP and top-place rows: a narrow band, 1.2 s out of every 6 s, the letters stay white on top of it */
.fx-on .row.t-top > .row-a, .fx-on .row.t-divine > .row-a { overflow: hidden; isolation: isolate; }
.fx-on .row.t-top > .row-a::after, .fx-on .row.t-divine > .row-a::after {
  content: ""; position: absolute; z-index: -1; top: 0; bottom: 0; left: 0; width: 34%; pointer-events: none;
  background: linear-gradient(100deg, rgba(255, 255, 255, 0), rgba(255, 246, 230, .22) 50%, rgba(255, 255, 255, 0));
  transform: translateX(-130%) skewX(-18deg);
  animation: fx-row-sheen 6s ease-in-out var(--fx-d, 0s) infinite;
}
@keyframes fx-row-sheen { 0%, 68% { transform: translateX(-130%) skewX(-18deg); } 92%, 100% { transform: translateX(400%) skewX(-18deg); } }
/* the crown glints when the sheen passes */
.fx-on .row.t-top .crown, .fx-on .row.t-divine .crown { animation: fx-glint 6s ease-in-out var(--fx-d, 0s) infinite; }
@keyframes fx-glint { 0%, 71%, 84%, 100% { transform: none; } 76% { transform: scale(1.3) rotate(-10deg); } 80% { transform: scale(1.1) rotate(5deg); } }

/* the live VIP badge: a glint runs across it */
.fx-on .badge-vip { position: relative; overflow: hidden; isolation: isolate; }
.fx-on .badge-vip::after {
  content: ""; position: absolute; z-index: -1; inset: 0 auto 0 0; width: 60%; pointer-events: none;
  background: linear-gradient(100deg, rgba(242, 200, 91, 0), rgba(242, 200, 91, .38) 50%, rgba(242, 200, 91, 0));
  transform: translateX(-120%) skewX(-18deg);
  animation: fx-badge 4s ease-in-out var(--fx-d, 0s) infinite;
}
/* NEW: a frosty glint, same rhythm */
.fx-on .badge-new { position: relative; overflow: hidden; isolation: isolate; }
.fx-on .badge-new::after {
  content: ""; position: absolute; z-index: -1; inset: 0 auto 0 0; width: 60%; pointer-events: none;
  background: linear-gradient(100deg, rgba(190, 225, 255, 0), rgba(220, 240, 255, .5) 50%, rgba(190, 225, 255, 0));
  transform: translateX(-120%) skewX(-18deg);
  animation: fx-badge 4s ease-in-out var(--fx-d, 0s) infinite;
}
@keyframes fx-badge { 0%, 64% { transform: translateX(-120%) skewX(-18deg); } 86%, 100% { transform: translateX(230%) skewX(-18deg); } }

/* ---------- panels rising in on scroll ---------- */
.fx-on .fx-rv { opacity: 0; transform: translateY(18px); }
.fx-on .fx-rv.is-in { opacity: 1; transform: none; transition: opacity .55s var(--ease) var(--rv-d, 0s), transform .55s var(--ease) var(--rv-d, 0s); }

/* ---------- phone: fewer layers, nothing that makes the card shift ---------- */
@media (max-width: 699px) {
  .fx-on .slide .fx-bolt { left: 66%; width: 24%; top: calc(var(--hdr-h) + 52px); height: calc(50% - var(--hdr-h) - 52px); }
  .fx-on .slide .fx-sparks { left: 30%; --rise: 260px; }
  .fx-on .topwin .fx-bolt, .fx-on .topwin .fx-flash { display: none; }
  .fx-on .topwin:hover, .fx-on .tcard:hover { transform: none; }
}
@media (hover: none) {
  .fx-on .topwin:hover, .fx-on .tcard:hover { transform: none; }
}

/* ---------- reduced motion: motion.js does not run, but keep the static look if the setting changes on the fly ---------- */
@media (prefers-reduced-motion: reduce) {
  .fx-bolt, .fx-flash, .fx-sparks, .fx-ring, .fx-glow { display: none !important; }
  .fx-on .row-a::after, .fx-on .badge-vip::after, .fx-on .badge-new::after, .fx-on .btn-fire::after { display: none; }
  .fx-on .fx-rv { opacity: 1; transform: none; }
  .fx-on .slide-name a, .fx-on .slide-name > span, .fx-on .crown, .fx-on .hero-tab .i, .fx-on .topwin-tag .i, .fx-on .tcard-clock, .fx-on .today-clock { animation: none !important; }
}
