/* frappe — FR.fx styles (js/game/fx.js): sprites, capture, evolution, level-up, toasts, confetti,
   damage numbers and the review demo. Classes are prefixed fx-.
   Layers: catch 150 (under .g-modal 200) · damage 260 · evolution 300 · level-up 350 · toasts 400 · confetti 450.
   Full-screen sequences use a fixed dark stage so they read the same on every theme. */

/* ---------- sprites: inline SVG strings from sprite / gpSprite / foeSprite / ball
   style.css sets every svg to 1em × 1em, fill none, stroke currentColor — undone here.
   The size comes from --fx-sz (set inline); any rule more specific than .fx-sp can resize. */
.fx-sp {
  width: var(--fx-sz, 96px);
  height: var(--fx-sz, 96px);
  fill: none;
  stroke: none;
  overflow: visible;
  display: inline-block;
  vertical-align: middle;
  flex: none;
}
.fx-tw {
  transform-box: fill-box;
  transform-origin: center;
  animation: fx-twinkle 1.8s ease-in-out infinite;
}
@keyframes fx-twinkle {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.35;
    transform: scale(0.6);
  }
}
/* optional helpers for other modules: a gentle idle bob and a soft glow */
.fx-idle {
  animation: fx-idle 2.4s ease-in-out infinite;
}
@keyframes fx-idle {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-4%);
  }
}
.fx-glow {
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--main) 70%, transparent));
}

/* ---------- shared keyframes */
@keyframes fx-spin {
  to {
    transform: rotate(360deg);
  }
}
@keyframes fx-fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes fx-fadeout {
  to {
    opacity: 0;
  }
}

/* ---------- catch */
.fx-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 150;
}
.fx-ball {
  position: absolute;
  left: 0;
  top: 0;
  will-change: transform;
}
.fx-ball .fx-sp {
  display: block;
  width: 100%;
  height: 100%;
}
.fx-ball.shut {
  filter: brightness(0.82) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35));
  transition: filter 0.2s;
}
.fx-catch-flash {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0 30%, rgba(255, 255, 255, 0.6) 45%, rgba(255, 255, 255, 0) 70%);
}
.fx-star {
  position: absolute;
  left: 0;
  top: 0;
  font-size: 18px;
  line-height: 18px;
  color: #ffd84a;
  text-shadow: 0 0 2px #7a5200, 0 0 6px rgba(0, 0, 0, 0.35);
}

/* ---------- typeface: these overlays are appended to <body>, outside .fr-view, so they would inherit the dojo
   monospace. Same rule as game-base.css: Lexend Deca for every game surface, kbd stays Roboto Mono. */
.fx-evo,
.fx-lvl,
.fx-toasts {
  font-family: "Lexend Deca", sans-serif;
}
.fx-evo kbd,
.fx-lvl kbd,
.fx-toasts kbd {
  font-family: "Roboto Mono", monospace;
}

/* ---------- evolution overlay */
.fx-evo {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 3.5rem 1rem 1.5rem;
  background: radial-gradient(circle at 50% 42%, #2b3150 0%, #0d0f1a 72%);
  color: #f4f5fb;
  text-align: center;
  cursor: pointer;
  outline: none;
  overflow: hidden;
  animation: fx-fadein 0.25s ease-out;
}
.fx-evo.fx-out {
  animation: fx-fadeout 0.22s ease-in forwards;
}
.fx-evo-top {
  position: absolute;
  top: 0.8rem;
  left: 1rem;
  right: 1rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.fx-evo-count {
  color: #b9bdd0;
  font-size: 0.85rem;
}
.fx-evo .g-btn.ghost {
  color: #b9bdd0;
}
.fx-evo .g-btn.ghost:hover,
.fx-evo .g-btn.ghost:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}
.fx-evo .g-btn.primary {
  background: #ffe27a;
  color: #1d1b26;
}
.fx-evo .g-btn:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.fx-evo kbd {
  background: rgba(0, 0, 0, 0.25);
  color: inherit;
}
.fx-evo-stage {
  position: relative;
  width: min(260px, 80vw);
  height: min(220px, 36vh);
  min-height: 140px;
  flex: none;
}
.fx-evo-mon {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  line-height: 0;
}
.fx-evo-mon .fx-sp {
  width: min(180px, 56vw, 30vh);
  height: min(180px, 56vw, 30vh);
}
.fx-evo-sil {
  filter: brightness(0) invert(1) drop-shadow(0 0 10px #fff) drop-shadow(0 0 22px #9fd0ff);
}
.fx-evo-glow {
  animation: fx-evo-glow 0.6s ease-in-out infinite alternate;
}
@keyframes fx-evo-glow {
  from {
    filter: drop-shadow(0 0 3px #fff) brightness(1);
  }
  to {
    filter: drop-shadow(0 0 16px #fff) brightness(1.6);
  }
}
.fx-evo-pop {
  animation: fx-evo-pop 0.55s cubic-bezier(0.2, 1.6, 0.4, 1) both;
}
@keyframes fx-evo-pop {
  from {
    transform: translateX(-50%) scale(0.6);
  }
  to {
    transform: translateX(-50%) scale(1);
  }
}
.fx-evo-fade {
  animation: fx-fadein 0.5s ease-out both;
}
.fx-evo-rays {
  position: absolute;
  left: 50%;
  top: 55%;
  width: 440px;
  height: 440px;
  margin: -220px 0 0 -220px;
  border-radius: 50%;
  background: repeating-conic-gradient(from 0deg, rgba(255, 255, 255, 0.08) 0 9deg, rgba(255, 255, 255, 0) 9deg 18deg);
  -webkit-mask-image: radial-gradient(circle, #000 18%, transparent 68%);
  mask-image: radial-gradient(circle, #000 18%, transparent 68%);
  animation: fx-spin 16s linear infinite;
  pointer-events: none;
}
.fx-evo.revealed .fx-evo-rays {
  background: repeating-conic-gradient(from 0deg, rgba(255, 226, 122, 0.18) 0 9deg, rgba(255, 226, 122, 0) 9deg 18deg);
}
.fx-evo-burst {
  position: absolute;
  left: 50%;
  top: 55%;
  width: 0;
  height: 0;
  pointer-events: none;
}
.fx-evo-burst i {
  position: absolute;
  left: -5px;
  top: -5px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--c, #ffe27a);
  box-shadow: 0 0 8px var(--c, #ffe27a);
  opacity: 0;
  animation: fx-burst 0.9s ease-out forwards;
}
@keyframes fx-burst {
  from {
    transform: rotate(var(--a)) translateY(0) scale(1);
    opacity: 1;
  }
  to {
    transform: rotate(var(--a)) translateY(calc(-1 * var(--d, 100px))) scale(0.3);
    opacity: 0;
  }
}
.fx-evo-ring {
  position: absolute;
  left: -60px;
  top: -60px;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.85);
  opacity: 0;
  animation: fx-ring 0.7s ease-out forwards;
}
@keyframes fx-ring {
  from {
    transform: scale(0.3);
    opacity: 1;
  }
  to {
    transform: scale(2.4);
    opacity: 0;
  }
}
.fx-evo-text {
  margin: 0;
  max-width: 32rem;
  min-height: 4.4em;
  font-size: 1.2rem;
  line-height: 1.5;
}
.fx-evo-text b {
  color: #ffe27a;
  font-weight: 400;
}
.fx-evo-text .g-en {
  display: block;
  margin-top: 0.3rem;
  color: #b9bdd0;
  font-size: 0.78rem;
}
.fx-evo-actions {
  min-height: 2.8rem;
}
.fx-evo-flash {
  position: absolute;
  inset: 0;
  background: #fff;
  opacity: 0;
  pointer-events: none;
}
.fx-evo-flash.on {
  animation: fx-flash 0.65s ease-out;
}
@keyframes fx-flash {
  0% {
    opacity: 0;
  }
  18% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/* ---------- level up */
.fx-lvl {
  position: fixed;
  inset: 0;
  z-index: 350;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 18vh 1rem 0;
  pointer-events: none;
}
.fx-lvl-card {
  pointer-events: auto;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  min-width: min(16rem, 100%);
  padding: 1.3rem 2.2rem 1.2rem;
  border-radius: 1.2rem;
  background: color-mix(in srgb, var(--g-coin) 7%, var(--bg));
  color: var(--text);
  box-shadow: 0 0 0 3px var(--g-coin), var(--g-shadow);
  animation: fx-lvl-in 0.5s cubic-bezier(0.2, 1.5, 0.4, 1) both;
}
.fx-lvl-card:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 4px;
}
.fx-lvl-rays {
  position: absolute;
  inset: -60%;
  z-index: -1;
  background: repeating-conic-gradient(color-mix(in srgb, var(--g-coin) 14%, transparent) 0 10deg, transparent 10deg 20deg);
  -webkit-mask-image: radial-gradient(circle, #000 0 12%, transparent 34%);
  mask-image: radial-gradient(circle, #000 0 12%, transparent 34%);
  animation: fx-spin 12s linear infinite;
}
.fx-lvl-k {
  color: var(--g-coin-ink);
  font-size: 1rem;
}
.fx-lvl-n {
  font-size: 3.4rem;
  line-height: 1.05;
}
.fx-lvl-en {
  color: var(--g-gloss);
  font-size: 0.78rem;
}
.fx-lvl.fx-out .fx-lvl-card {
  animation: fx-fadeout 0.24s ease-in forwards;
}
@keyframes fx-lvl-in {
  from {
    transform: scale(0.4) translateY(-20px);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

/* ---------- toasts */
/* --fx-toast-top: bottom of the page header while it is on screen (set by FR.fx.toast), so toasts never hide
   the XP chip or the menu */
.fx-toasts {
  position: fixed;
  top: calc(var(--fx-toast-top, 0px) + 0.75rem);
  right: 1rem;
  z-index: 400;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: min(22rem, calc(100vw - 2rem));
  pointer-events: none;
}
.fx-toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: 0.7rem 0.6rem 0.7rem 0.85rem;
  border-radius: 0.7rem;
  border-left: 4px solid var(--main);
  background: var(--sub-alt);
  color: var(--text);
  box-shadow: var(--g-shadow);
  font-size: 0.88rem;
  line-height: 1.4;
  cursor: pointer;
  animation: fx-toast-in 0.32s cubic-bezier(0.2, 1.3, 0.4, 1) both;
}
.fx-toast.fx-t-good {
  border-left-color: var(--g-ok);
}
.fx-toast.fx-t-achievement {
  border-left-color: var(--g-coin);
  background: color-mix(in srgb, var(--g-coin) 14%, var(--sub-alt));
}
.fx-toast.fx-t-quest {
  border-left-color: var(--g-a2);
  background: color-mix(in srgb, var(--g-a2) 10%, var(--sub-alt));
}
.fx-toast-ic {
  flex: none;
  font-size: 1.35rem;
  line-height: 1.1;
}
.fx-toast-ic .fx-sp {
  width: 1.6rem;
  height: 1.6rem;
}
.fx-toast-body {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}
.fx-toast-body .g-en {
  display: block;
}
.fx-toast-x {
  flex: none;
  padding: 0 0.25rem;
  color: var(--g-gloss);
  font-size: 1.1rem;
  line-height: 1;
  border-radius: 0.3rem;
}
.fx-toast-x:hover,
.fx-toast-x:focus-visible {
  color: var(--text);
}
.fx-toast.fx-out {
  animation: fx-toast-out 0.25s ease-in forwards;
}
@keyframes fx-toast-in {
  from {
    transform: translateX(110%);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}
@keyframes fx-toast-out {
  to {
    transform: translateX(110%);
    opacity: 0;
  }
}
@media (max-width: 480px) {
  .fx-toasts {
    top: calc(var(--fx-toast-top, 0px) + 0.5rem);
    left: 0.5rem;
    right: 0.5rem;
    width: auto;
  }
}

/* ---------- confetti */
.fx-layer.fx-confetti {
  z-index: 450;
}
.fx-confetti i {
  position: absolute;
  top: 0;
  display: block;
  will-change: transform;
}

/* ---------- damage numbers */
.fx-dmg {
  position: fixed;
  z-index: 260;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  transform: translate(-50%, -50%);
  font-family: "Lexend Deca", sans-serif;
  font-size: 1.6rem;
  line-height: 1;
  white-space: nowrap;
  color: #fff;
  text-shadow: 2px 0 #1d1b26, -2px 0 #1d1b26, 0 2px #1d1b26, 0 -2px #1d1b26, 1.5px 1.5px #1d1b26, -1.5px -1.5px #1d1b26,
    1.5px -1.5px #1d1b26, -1.5px 1.5px #1d1b26, 0 4px 6px rgba(0, 0, 0, 0.3);
}
.fx-dmg.crit {
  color: #ffd84a;
  font-size: 2.2rem;
}
.fx-dmg small {
  font-size: 0.45em;
  letter-spacing: 0.05em;
  color: #ff9a6b;
}
.fx-dmg.miss {
  color: #c9cdd6;
  font-size: 1.15rem;
}
.fx-dmg.heal {
  color: #7be08a;
}

/* ---------- demo / review sheet (FR.fx.demo) */
.fx-demo-modal .g-dialog.fx-demo {
  max-width: 66rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
/* the dialog scrolls (max-height 90vh): its sections keep their height instead of shrinking to fit — a scroll
   container like .fx-demo-row (overflow-x: auto) would otherwise collapse to 0 */
.fx-demo-modal .g-dialog.fx-demo > * {
  flex-shrink: 0;
}
.fx-demo.alt {
  background: #f2efe6;
  color: #2b2b2b;
}
.fx-demo.alt .fx-demo-cell,
.fx-demo.alt .fx-demo-st {
  background: #e4e0d4;
}
.fx-demo-h {
  margin: 0.8rem 0 0.2rem;
  color: var(--sub);
  font-size: 0.95rem;
  font-weight: 400;
}
.fx-demo.alt .fx-demo-h {
  color: #6b6b6b;
}
.fx-demo-table {
  display: grid;
  grid-template-columns: 6rem repeat(5, minmax(0, 1fr));
  gap: 0.35rem;
  align-items: center;
  font-size: 0.72rem;
  color: var(--sub);
  text-align: center;
}
.fx-demo-arch {
  text-align: left;
  color: var(--text);
}
.fx-demo.alt .fx-demo-arch {
  color: #2b2b2b;
}
.fx-demo-arch .g-en {
  display: block;
}
.fx-demo-st,
.fx-demo-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0.3rem;
  border-radius: 0.5rem;
  background: var(--sub-alt);
  font-size: 0.7rem;
  color: var(--sub);
}
.fx-demo-st .fx-sp {
  width: 100%;
  max-width: 88px;
  height: auto;
  aspect-ratio: 1;
}
.fx-demo-row {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  overflow-x: auto;
  padding-bottom: 0.2rem;
}
.fx-demo-row.wrap {
  flex-wrap: wrap;
}
.fx-demo-th {
  flex: none;
  width: 9rem;
  font-size: 0.72rem;
  color: var(--sub);
  overflow-wrap: anywhere;
}
.fx-demo-bgs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 0.5rem;
}
.fx-demo-bg {
  position: relative;
  height: 9rem;
  border-radius: 0.6rem;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 0.6rem;
  overflow: hidden;
}
.fx-demo-bg span {
  position: absolute;
  left: 0.4rem;
  top: 0.3rem;
  padding: 0 0.4rem;
  border-radius: 0.3rem;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 0.7rem;
}
.fx-demo-target {
  line-height: 0;
  padding: 0.5rem;
}
.fx-demo-acts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.fx-demo select {
  font: inherit;
  background: var(--sub-alt);
  color: var(--text);
  border: 0;
  border-radius: 0.4rem;
  padding: 0.25rem 0.4rem;
}
@media (max-width: 640px) {
  .fx-demo-table {
    grid-template-columns: 4rem repeat(5, minmax(0, 1fr));
  }
  .fx-demo-th {
    width: 5.5rem;
  }
}

/* ---------- reduced motion (FR.reducedMotion() also adds .fx-still when the pref forces it) */
.fx-still .fx-evo-rays,
.fx-still .fx-lvl-rays,
.fx-still .fx-evo-glow,
.fx-still .fx-tw {
  animation: none;
}
.fx-still.fx-lvl .fx-lvl-card,
.fx-still .fx-evo-pop {
  animation: fx-fadein 0.3s ease-out both;
}
@media (prefers-reduced-motion: reduce) {
  .fx-tw,
  .fx-idle,
  .fx-evo-rays,
  .fx-lvl-rays,
  .fx-evo-glow {
    animation: none;
  }
  .fx-lvl-card,
  .fx-toast {
    animation-name: fx-fadein;
  }
  .fx-toast.fx-out,
  .fx-lvl.fx-out .fx-lvl-card {
    animation-name: fx-fadeout;
  }
}
