/* Battle screen (fight.js). A scene with depth: the Pokemon whose turn it is stands big in the
   bottom-left foreground (back view), teammates beside it, the other team far off to the upper
   right (front view). The camera swaps sides as turns change. Sprites stand straight on the
   scenery (no cards); each has a small name/HP plate. Feedback is animation only, and the
   whole thing fits the phone's screen without scrolling.

   SCOPE: every rule here starts with the battle screen's root (.battle) or, for the page
   around a running battle, body.in-battle. Class names like .mon, .stage, .plate, .chip or
   .result are used elsewhere too (ui.js pokemonCard() is a "card mon"), so an unscoped rule
   would turn every Pokemon card in the app into a battle sprite. Keyframes are prefixed bt-. */

body.in-battle { overflow: hidden; }
body.in-battle main { padding: 0; max-width: none; height: 100dvh; }

.battle { display: flex; flex-direction: column; height: 100dvh; min-height: 0; background: #1f3b2a; }
body:not(.in-battle) .battle { height: auto; border-radius: var(--radius); overflow: hidden; }
body:not(.in-battle) .battle .field { height: 46vh; min-height: 300px; }

/* strip: title and round */
.battle .arena-top {
  display: flex; justify-content: space-between; align-items: center; gap: 8px; flex: none;
  padding: 4px 12px; font-size: 12px; font-weight: 700; color: #fff; background: rgba(0, 0, 0, .35);
}
.battle .arena-top .title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.battle .arena-top #round { white-space: nowrap; opacity: .85; }

/* ---------- the field ---------- */
.battle .field { position: relative; flex: 1; min-height: 0; overflow: hidden; background: #6fb95a; }
.battle.gym .field { background: #3a3046; }
/* the scenery (scenes/): framed by .scene-frame in css/scenes.css, horizon a third of the way down */
.battle .scene { position: absolute; inset: 0; pointer-events: none; }

/* the foreground sprite box size; teammates and the far team are scaled down from it */
.battle .field { --sz: min(42vw, 30dvh, 170px); }
@media (min-height: 760px) { .battle .field { --sz: min(46vw, 31dvh, 200px); } }
@media (min-width: 700px) { .battle { max-width: 760px; margin: 0 auto; } .battle .field { --sz: 220px; } }

/* a Pokemon: positioned by fight.js (translate + scale), slides when the camera swaps */
.battle .mon {
  position: absolute; left: 0; top: 0; width: var(--sz); height: var(--sz);
  transform-origin: 50% 100%; will-change: transform;
  transition: transform .65s cubic-bezier(.4, .1, .2, 1), opacity .4s ease;
}
.battle .mon.no-anim { transition: none; }
.battle .stage { position: relative; width: 100%; height: 100%; display: flex; align-items: flex-end; justify-content: center; }
.battle .stage::before {
  content: ""; position: absolute; left: 50%; bottom: 3%; transform: translateX(-50%);
  width: 72%; height: 16%; border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, .32), rgba(0, 0, 0, 0) 70%);
}
.battle .stage .sprite {
  position: absolute; left: 0; bottom: 0; width: 100%; height: 100%;
  image-rendering: pixelated; object-fit: contain; animation: bt-bob 1.6s ease-in-out infinite;
}
.battle .stage .sprite.fallback { font-size: calc(var(--sz) / 2.6); animation: none; position: static; }
/* foreground: seen from behind; far away: facing us */
.battle .mon.fg .sprite.front, .battle .mon.far .sprite.back { display: none; }
.battle .mon.far .stage::before { background: radial-gradient(ellipse at center, rgba(0, 0, 0, .22), rgba(0, 0, 0, 0) 70%); }

/* whose turn it is: a glowing ring on the ground */
.battle .mon.turn .stage::after {
  content: ""; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 86%; height: 20%; border-radius: 50%; border: 3px solid rgba(255, 255, 255, .9);
  box-shadow: 0 0 10px 3px rgba(227, 53, 13, .55), inset 0 0 10px rgba(227, 53, 13, .45);
  animation: bt-ring 1.2s ease-in-out infinite;
}

/* the attacker lunges towards the far team (up and to the right); a far attacker lunges down-left */
.battle .stage.lunge { z-index: 3; }
.battle .mon.fg .stage.lunge { animation: bt-lunge-far .5s ease-in-out; }
.battle .mon.far .stage.lunge { animation: bt-lunge-near .5s ease-in-out; }
.battle .stage.hit .sprite { animation: bt-hit .5s ease-out; }
.battle .stage.faint .sprite { animation: bt-faint .9s ease-in forwards; }
.battle .stage.enter .sprite { animation: bt-enter .7s cubic-bezier(.2, 1.4, .4, 1); }

.battle .mon.out { opacity: .5; }
.battle .mon.out .stage .sprite { animation: none; filter: grayscale(1); }
.battle .mon.glow .stage .sprite { filter: drop-shadow(0 0 10px #ffd54a) drop-shadow(0 0 4px #fff); }

/* ---------- choosing a target (fight.js startPicking) ----------
   With more than one far Pokemon standing, each one's sprite box and plate is a tap target
   (.pick). The foreground team lets taps fall through, so a teammate standing in front of a
   far Pokemon never steals the tap. The chosen one gets a red and white reticle over its
   sprite and a red plate. */
.battle.picking .mon:not(.pick) { pointer-events: none; }
.battle .mon.pick, .battle .plate.pick { pointer-events: auto; cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.battle .mon.pick:focus-visible, .battle .plate.pick:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }
.battle .reticle {
  position: absolute; left: 50%; top: 52%; width: 78%; aspect-ratio: 1; z-index: 2;
  transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
  border: 6px solid #e3350d; box-shadow: 0 0 0 3px #fff, inset 0 0 0 3px #fff, 0 0 14px 4px rgba(227, 53, 13, .45);
  animation: bt-aim 1.4s ease-in-out infinite;
}
/* the crosshair: four short red ticks pointing at the middle */
.battle .reticle::before, .battle .reticle::after {
  content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  background:
    linear-gradient(#e3350d, #e3350d) center top / 100% 26% no-repeat,
    linear-gradient(#e3350d, #e3350d) center bottom / 100% 26% no-repeat;
}
.battle .reticle::before { width: 8px; height: 132%; }
.battle .reticle::after { width: 132%; height: 8px; background:
  linear-gradient(#e3350d, #e3350d) left center / 26% 100% no-repeat,
  linear-gradient(#e3350d, #e3350d) right center / 26% 100% no-repeat; }
/* while aiming (fight.js markTarget), a teammate's small plate can stand right in front of a far
   Pokemon (3v3: the third teammate's plate sits across the far-right foe): hide the teammates'
   plates, and lift the target and its reticle above the other sprites and plates (z 20).
   !important beats the z-index fight.js sets inline. */
.battle.aiming .plate.fg.above { opacity: 0; }
.battle.aiming .mon.far.target { z-index: 21 !important; }
.battle .plate.target { background: #e3350d; box-shadow: 0 0 0 2px #fff, 0 2px 8px rgba(0, 0, 0, .35); }
.battle .plate.target .hpbar { background: rgba(255, 255, 255, .35); }

/* name / HP plate: positioned by fight.js, never scaled; below a foreground Pokemon, above a far one */
.battle .plate {
  position: absolute; left: 0; top: 0; z-index: 20; width: max-content; max-width: 46vw;
  padding: 3px 8px 4px; border-radius: 9px; background: rgba(20, 30, 24, .78); color: #fff;
  font-size: 12px; line-height: 1.2; text-align: center; pointer-events: none;
  transition: transform .65s cubic-bezier(.4, .1, .2, 1), opacity .4s ease;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .25);
}
.battle .plate.no-anim { transition: none; }
/* the hero's plate is pinned to the bottom-right corner, bigger and always clear of the sprite */
.battle .plate.hero { left: auto; right: 8px; top: auto; bottom: 8px; transform: none; font-size: 13px; padding: 5px 12px 6px; max-width: 52vw; transition: none; }
.battle .plate.hero .nm strong { font-size: 16px; }
.battle .plate.hero .hpbar { height: 8px; min-width: 120px; }
.battle .plate.hero .sub { font-size: 11px; }
/* far plates are compact so two or three fit along the horizon */
.battle .plate.above { font-size: 10px; padding: 2px 6px 3px; max-width: 30vw; }
.battle .plate.above .hpbar { min-width: 60px; height: 5px; margin: 2px 0 1px; }
.battle .plate.above .sub .trainer, .battle .plate.above .sub .sep { display: none; }
.battle .plate .nm { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.battle .plate .nm strong { font-size: 13px; }
.battle .plate.above .nm strong { font-size: 12px; }
.battle .plate .lv { opacity: .8; }
.battle .plate .hpbar { height: 6px; background: rgba(255, 255, 255, .25); margin: 3px 0 2px; min-width: 84px; }
.battle .plate .hpfill { transition: width .5s ease, background-color .3s ease; }
.battle .plate .sub { font-size: 10px; opacity: .85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.battle .plate.out { opacity: .55; }

/* floating damage, effectiveness and move-name text rises from the plate */
.battle .float {
  position: absolute; left: 50%; top: -6px; transform: translateX(-50%);
  font-weight: 800; white-space: nowrap; pointer-events: none; z-index: 30; margin: 0;
  animation: bt-float-up 1.1s ease-out both;
}
.battle .plate.above .float { top: auto; bottom: -6px; animation-name: bt-float-down; }
/* the hero's text floats over its own sprite */
.battle .stage .float { top: 12%; }
.battle .stage .float.eff { top: -4%; }
.battle .stage .float.move { top: 26%; }
.battle .float.dmg { font-size: 26px; color: #ff5a3c; text-shadow: 0 1px 0 #fff, 0 0 6px #fff, 0 0 12px #fff; }
.battle .float.eff { top: -30px; font-size: 11px; animation-delay: .2s; padding: 2px 8px; border-radius: 999px; background: rgba(255, 255, 255, .95); color: var(--muted); }
.battle .plate.above .float.eff { top: auto; bottom: -30px; }
.battle .float.eff.super { color: #b45309; background: #fff3c4; }
.battle .float.move { font-size: 10px; text-transform: uppercase; padding: 2px 8px; border-radius: 999px; color: #fff; letter-spacing: .3px; }

/* ---------- controls: prompt, moves, give up (fixed height so the field gets the rest) ---------- */
.battle .controls { flex: none; display: grid; gap: 6px; align-content: start; padding: 8px 10px 10px; background: var(--card); border-top: 2px solid rgba(0, 0, 0, .15); }
/* a fixed height so the field never jumps between "waiting" and the move buttons */
body.in-battle .battle .controls { min-height: 196px; }
.battle .prompt { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; font-size: 16px; min-height: 34px; }
.battle .prompt.wait { color: var(--muted); font-size: 15px; }
.battle .chip {
  display: inline-block; background: var(--accent); color: #fff; font-weight: 800; font-size: 17px;
  padding: 3px 14px; border-radius: 999px; box-shadow: 0 2px 6px rgba(227, 53, 13, .35);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.battle .moves { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.battle .moves button { padding: 8px 6px; font-size: 15px; min-height: 46px; line-height: 1.2; }
.battle .moves button .type { vertical-align: middle; font-size: 10px; }
.battle .moves .pw { display: inline-block; margin-left: 4px; font-size: 11px; font-weight: 400; opacity: .85; }
.battle .give-up { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; }
.battle .give-up button { padding: 5px 10px; font-size: 13px; }

/* result box (the battle is over, so the page may scroll again) */
.battle .result { background: #fff; border-radius: 12px; padding: 12px; text-align: center; }
.battle .result .big-text { font-size: 26px; font-weight: 800; }
.battle .result .lines div { margin-top: 2px; font-size: 14px; }
.battle .result .row button { padding: 12px 20px; font-size: 17px; }

/* keyframes (prefixed so they never clash with another screen's) */
@keyframes bt-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3%); } }
@keyframes bt-ring { 0%, 100% { opacity: .9; } 50% { opacity: .45; } }
@keyframes bt-aim {
  0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  50% { transform: translate(-50%, -50%) scale(.9); opacity: .8; }
}
@keyframes bt-lunge-far {
  0% { transform: translate(0, 0) scale(1); }
  40% { transform: translate(22%, -26%) scale(.92); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes bt-lunge-near {
  0% { transform: translate(0, 0) scale(1); }
  40% { transform: translate(-28%, 30%) scale(1.12); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes bt-hit {
  0%, 100% { transform: translateX(0); filter: none; }
  15% { transform: translateX(-6%); filter: sepia(1) saturate(8) hue-rotate(-45deg) brightness(1.3); }
  35% { transform: translateX(6%); filter: none; }
  55% { transform: translateX(-4%); filter: sepia(1) saturate(8) hue-rotate(-45deg) brightness(1.3); }
  75% { transform: translateX(3%); filter: none; }
}
@keyframes bt-faint {
  0% { transform: translateY(0); opacity: 1; filter: grayscale(0); }
  100% { transform: translateY(30%); opacity: 0; filter: grayscale(1); }
}
@keyframes bt-enter {
  0% { transform: scale(.2); opacity: 0; filter: brightness(4); }
  60% { transform: scale(1.1); opacity: 1; filter: brightness(2.5); }
  100% { transform: scale(1); opacity: 1; filter: brightness(1); }
}
@keyframes bt-float-up {
  0% { opacity: 0; transform: translate(-50%, 8px); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -46px); }
}
@keyframes bt-float-down {
  0% { opacity: 0; transform: translate(-50%, -8px); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, 46px); }
}

@media (prefers-reduced-motion: reduce) {
  .battle .stage .sprite, .battle .mon.turn .stage::after, .battle .reticle { animation: none; }
  .battle .mon, .battle .plate { transition: none; }
}
