/* Shared battle-scene visuals -- the arena floor, standee art, HP boxes,
   roster strip, action prompt, and win/lose/draw result overlay. Used by
   both the solo-vs-bot practice page (duels.html) and the real Sepolia
   PvP page (pvp.html) so the two share one visual identity instead of
   duplicating ~800 lines of CSS. Squad-picker CSS (.squad-grid, .squad-card,
   .tier-guide, ...) stays inline per-page since practice mode and PvP
   handle squad selection differently. */

/* --- Battle arena --- */
.arena { display: none; }
.arena.show { display: block; }

/* --- Battle scene: a small "3D" desert pit the two active
   fighters stand in, facing each other -- same read as a classic
   turn-based battle screen (opponent upper-right, you larger and
   closer lower-left) without borrowing its pastel palette. The
   other two squad members per side live in the roster strip
   below and can be swapped in by clicking their pip. */
.battle-scene {
    position: relative;
    height: clamp(14.5rem, 34vw, 20rem);
    margin-bottom: 1.1rem;
    border-radius: .7rem;
    overflow: hidden;
    border: .16rem solid #000;
    /* A real two-tone floor, not a gradient trying to suggest one:
       dark sky, then an unmistakably distinct sand-colored ground
       with a hard horizon between them -- same read as any 2D
       battle-screen arena. */
    background: #0a0705;
}

.battle-scene.shake { animation: arenaShake .3s ease; }

.battle-scene__ground {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 44%;
    background: #4a3018;
    border-top: .14rem solid #6b4726;
}

.battle-scene__ground::before {
    /* Coarse dirt/crack texture so the floor isn't a flat color
       fill -- kept high-contrast enough to actually read. */
    content: "";
    position: absolute;
    inset: 0;
    background:
        repeating-linear-gradient(115deg, rgba(0,0,0,.16) 0 2px, transparent 2px 3.2rem),
        repeating-linear-gradient(25deg, rgba(0,0,0,.14) 0 2px, transparent 2px 3.6rem);
}

/* Each fighter's own platform -- a flat, clearly-drawn shadow
   ellipse, same convention as any 2D battler's character shadow.
   Solid enough to read as ground you're standing on, not a hint. */
.battle-standee__shadow {
    position: absolute;
    width: 62%;
    height: 16%;
    border-radius: 50%;
    background: rgba(0,0,0,.55);
    border: .09rem solid rgba(0,0,0,.35);
    pointer-events: none;
}

.battle-standee {
    position: absolute;
    width: 28%;
    max-width: 8rem;
    aspect-ratio: 1/1;
    transition: opacity .3s ease, filter .3s ease;
}

.battle-standee--bot {
    top: 9%;
    right: 7%;
}

.battle-standee--you {
    bottom: 4%;
    left: 6%;
    width: 39%;
    max-width: 11.5rem;
}

.battle-standee__clip {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: .55rem;
    overflow: hidden;
    border: .16rem solid #000;
    box-shadow: 0 .7rem 1.3rem rgba(0,0,0,.55);
}

.battle-standee.t-Dust     .battle-standee__clip { border-color: #6b6b6b; }
.battle-standee.t-Husk     .battle-standee__clip { border-color: #4f7a3f; }
.battle-standee.t-Amber    .battle-standee__clip { border-color: #a5701f; }
.battle-standee.t-Dusk     .battle-standee__clip { border-color: #7a4bab; }
.battle-standee.t-Relic    .battle-standee__clip { border-color: #2f8fb0; }
.battle-standee.t-Luminous .battle-standee__clip { border-color: #e27800; }

.battle-standee.holo .battle-standee__clip::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 3;
    background: linear-gradient(
        115deg,
        transparent 20%,
        rgba(255,255,255,.05) 36%,
        rgba(255,200,120,.5) 45%,
        rgba(255,255,255,.65) 50%,
        rgba(140,220,255,.5) 55%,
        rgba(255,255,255,.05) 64%,
        transparent 80%
    );
    background-size: 250% 250%;
    background-position: 0% 0%;
    mix-blend-mode: overlay;
    animation: holoSweep 3.2s ease-in-out infinite;
}

.battle-standee img { width: 100%; height: 100%; object-fit: cover; display: block; transform-origin: 50% 100%; }

/* Idle "alive" motion -- no separate sprite frames exist for these,
   so this fakes breathing/weight-shift on the flat art via a small
   bob + tilt loop. Each side runs its own keyframe (different
   amplitude/tilt direction), on top of a per-token delay/duration
   jitter set inline in JS -- between the two, the pair never reads
   as bobbing in lockstep, even when they're mirror-image squads. */
.battle-standee--you:not(.dead) img {
    animation: idleBobYou 2.6s ease-in-out infinite;
}
.battle-standee--bot:not(.dead) img {
    animation: idleBobBot 2.6s ease-in-out infinite;
}

@keyframes idleBobYou {
    0%, 100% { transform: translateY(0) rotate(0deg) scale(1); }
    50%      { transform: translateY(-.15rem) rotate(-1.6deg) scale(1.02); }
}

@keyframes idleBobBot {
    0%, 100% { transform: translateY(0) rotate(0deg) scale(1); }
    50%      { transform: translateY(-.08rem) rotate(1.1deg) scale(1.01); }
}

.battle-standee.dead { opacity: .28; filter: grayscale(1); }

.battle-standee__atk {
    position: absolute;
    top: -.5rem;
    right: -.5rem;
    background: #e27800;
    color: #050505;
    font-family: "Luckiest Guy";
    font-size: .8rem;
    padding: .17rem .4rem;
    border: .12rem solid #050505;
    z-index: 4;
}

/* Pokemon-style name + HP box, one per side. */
.battle-hpbox {
    position: absolute;
    min-width: 9.5rem;
    background: rgba(5,5,5,.9);
    border: .14rem solid #000;
    border-radius: .5rem;
    padding: .5rem .7rem .55rem;
    z-index: 5;
}

.battle-hpbox--bot { top: 6%; left: 5%; }
.battle-hpbox--you { bottom: 7%; right: 5%; }

.battle-hpbox__top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .35rem;
}

.battle-hpbox__name {
    font-family: "Luckiest Guy";
    font-size: .82rem;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.battle-hpbox__tier {
    font-size: .62rem;
    letter-spacing: .03em;
    text-transform: uppercase;
    white-space: nowrap;
    color: rgba(255,255,255,.6);
}

.battle-hpbox__tier.t-Dust     { color: #9a9a9a; }
.battle-hpbox__tier.t-Husk     { color: #7fb46a; }
.battle-hpbox__tier.t-Amber    { color: #e2a338; }
.battle-hpbox__tier.t-Dusk     { color: #b06fe2; }
.battle-hpbox__tier.t-Relic    { color: #4fc3e8; }
.battle-hpbox__tier.t-Luminous { color: #e27800; }

.battle-hpbox__hp {
    height: .34rem;
    background: rgba(255,255,255,.12);
    border-radius: .2rem;
    overflow: hidden;
}
.battle-hpbox__hp span { display: block; height: 100%; background: #e27800; transition: width .4s ease; }
.battle-hpbox__hp.low span { background: #cd2121; }

.battle-hpbox__num {
    margin-top: .25rem;
    text-align: right;
    font-size: .68rem;
    font-variant-numeric: tabular-nums;
    color: rgba(255,255,255,.6);
}

/* The physical-move jab -- a short, fast slide toward the
   opponent and snap back. No body rotation or fake-3D tilt: a
   2D sprite battler sells a hit through timing and impact, not
   by twisting the art. The actual sting-dart projectile (spawned
   in JS, see spawnStingDart) is what visually closes the gap and
   reads as "stinging" -- this slide is just the wind-up. Timed so
   the dart launches right at the peak, landing on the target
   around the 150ms mark when maybeResolveRound applies the hit. */
.battle-standee--you.lunge-you {
    animation: jabYou .3s cubic-bezier(.2, .6, .3, 1);
}
.battle-standee--bot.lunge-bot {
    animation: jabBot .3s cubic-bezier(.2, .6, .3, 1);
}

@keyframes jabYou {
    0%   { transform: translateX(0); }
    40%  { transform: translateX(.7rem); }
    100% { transform: translateX(0); }
}

@keyframes jabBot {
    0%   { transform: translateX(0); }
    40%  { transform: translateX(-.7rem); }
    100% { transform: translateX(0); }
}

/* Impact flash on the fighter taking the hit -- a rapid
   alternating blink (the classic sprite-battler "took damage"
   tell), not a single brightness pulse. */
.battle-standee.hit-flash .battle-standee__clip { animation: hitFlash .4s steps(1, end); }

@keyframes hitFlash {
    0%, 100% { filter: brightness(1) saturate(1); }
    12.5%, 37.5%, 62.5%, 87.5% { filter: brightness(1) saturate(1); }
    25%, 50%, 75% { filter: brightness(3) saturate(0); }
}

/* Stinger-tip flash -- a sharp white "+" glint layered on the
   target at the instant of contact, distinct from the softer
   round clash-burst. Reads as the point actually piercing in. */
.sting-flash {
    position: absolute;
    top: 42%;
    left: 50%;
    width: 2.1rem;
    height: 2.1rem;
    margin: -1.05rem 0 0 -1.05rem;
    pointer-events: none;
    z-index: 6;
    background:
        linear-gradient(90deg, transparent 45%, #fff 48%, #fff 52%, transparent 55%),
        linear-gradient(0deg, transparent 45%, #fff 48%, #fff 52%, transparent 55%);
    animation: stingFlash .26s ease-out forwards;
}

@keyframes stingFlash {
    0%   { opacity: 0; transform: scale(.25) rotate(20deg); }
    35%  { opacity: 1; transform: scale(1.1) rotate(20deg); }
    100% { opacity: 0; transform: scale(1.7) rotate(20deg); }
}

/* The sting itself -- a small bright dart that actually travels
   from attacker to target across the scene, closing the gap
   between the jab wind-up and the impact flash. This is the
   element that reads as "stinging," not the body motion. Spawned
   and positioned by spawnStingDart() in JS (it needs the two
   standees' real on-screen positions, which only JS has), with
   the travel distance passed in as --dart-dx/--dart-dy. */
.sting-dart {
    position: absolute;
    width: .55rem;
    height: .55rem;
    margin: -.28rem 0 0 -.28rem;
    border-radius: 50%;
    background: radial-gradient(circle, #fff 0%, #e27800 55%, rgba(226,120,0,0) 76%);
    box-shadow: 0 0 .6rem rgba(226,120,0,.85);
    pointer-events: none;
    z-index: 7;
    animation: stingDart .15s cubic-bezier(.3, 0, .5, 1) forwards;
}

@keyframes stingDart {
    0%   { opacity: 0; transform: translate(0, 0) scale(.5); }
    15%  { opacity: 1; }
    100% { opacity: 1; transform: translate(var(--dart-dx), var(--dart-dy)) scale(1); }
}

/* Floating damage number. */
.dmg-pop {
    position: absolute;
    top: 35%;
    left: 50%;
    font-family: "Luckiest Guy";
    font-size: 1rem;
    color: #fff;
    text-shadow: .07em .07em 0 #000;
    z-index: 5;
    pointer-events: none;
    animation: dmgFloat .9s ease forwards;
}

.dmg-pop.crit { color: #e27800; font-size: 1.2rem; }

@keyframes dmgFloat {
    0%   { opacity: 0; transform: translate(-50%, 0) scale(.6); }
    18%  { opacity: 1; transform: translate(-50%, -.35rem) scale(1.2); }
    100% { opacity: 0; transform: translate(-50%, -2rem) scale(1); }
}

/* Clash burst, anchored roughly between the two standees. */
.clash-burst {
    position: absolute;
    top: 40%;
    left: 50%;
    width: 2.4rem;
    height: 2.4rem;
    margin: -1.2rem 0 0 -1.2rem;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(226,120,0,.9), rgba(226,120,0,0) 70%);
    pointer-events: none;
    z-index: 4;
    animation: clashBurst .45s ease forwards;
}

@keyframes clashBurst {
    0%   { opacity: 0; transform: scale(.3); }
    35%  { opacity: 1; transform: scale(1.5); }
    100% { opacity: 0; transform: scale(2.1); }
}

.outcome-tag {
    position: absolute;
    top: 5%;
    left: 50%;
    transform: translateX(-50%) scale(.7);
    font-family: "Luckiest Guy";
    font-size: .82rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: .3rem .7rem;
    white-space: nowrap;
    opacity: 0;
    z-index: 6;
    pointer-events: none;
}

.outcome-tag.show { animation: outcomePop 1.1s ease forwards; }

.outcome-tag.crit { background: #e27800; color: #050505; }
.outcome-tag.resisted { background: #2a2a2a; color: rgba(255,255,255,.7); border: .1rem solid rgba(255,255,255,.2); }
.outcome-tag.clash { background: #fff; color: #050505; }

/* --- Roster strip -- the other two Stingers per side, shown as
   small pips below the scene. Yours are clickable to swap which
   fighter is standing in the scene before you lock a stance. --- */
.battle-roster {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: .9rem;
}

.battle-roster__side {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .45rem;
    flex: 1;
}

.battle-roster__label {
    font-size: .66rem;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(255,255,255,.45);
}

.battle-roster__pips { display: flex; gap: .55rem; }

.roster-pip {
    position: relative;
    width: 3.4rem;
    aspect-ratio: 1/1;
    border-radius: .4rem;
    transition: opacity .3s ease, filter .3s ease;
}

.roster-pip__clip {
    width: 100%;
    height: 100%;
    border-radius: .3rem;
    overflow: hidden;
    border: .12rem solid #000;
    position: relative;
}

.roster-pip.t-Dust     .roster-pip__clip { border-color: #6b6b6b; }
.roster-pip.t-Husk     .roster-pip__clip { border-color: #4f7a3f; }
.roster-pip.t-Amber    .roster-pip__clip { border-color: #a5701f; }
.roster-pip.t-Dusk     .roster-pip__clip { border-color: #7a4bab; }
.roster-pip.t-Relic    .roster-pip__clip { border-color: #2f8fb0; }
.roster-pip.t-Luminous .roster-pip__clip { border-color: #e27800; }

.roster-pip img { width: 100%; height: 100%; object-fit: cover; display: block; }

.roster-pip.holo .roster-pip__clip::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(115deg, transparent 25%, rgba(255,255,255,.55) 50%, transparent 75%);
    background-size: 220% 220%;
    mix-blend-mode: overlay;
    animation: holoSweep 3.2s ease-in-out infinite;
}

.roster-pip.dead { opacity: .3; filter: grayscale(1); }
.roster-pip.active .roster-pip__clip { border-color: #e27800; box-shadow: 0 0 .5rem rgba(226,120,0,.65); }

.roster-pip__hp {
    margin-top: .28rem;
    height: .22rem;
    background: rgba(255,255,255,.12);
    border-radius: .12rem;
    overflow: hidden;
}
.roster-pip__hp span { display: block; height: 100%; background: #e27800; }
.roster-pip__hp.low span { background: #cd2121; }

/* --- Action prompt -- "what will X do" + the stance buttons,
   styled as its own dialogue-style panel under the scene. --- */
.battle-prompt {
    border: .12rem solid rgba(255,255,255,.14);
    background: #0c0c0c;
    border-radius: .55rem;
    padding: .95rem 1rem 1.1rem;
}

.battle-prompt__text {
    font-family: "Luckiest Guy";
    font-size: .95rem;
    letter-spacing: .01em;
    color: #fff;
    text-align: center;
    margin-bottom: .9rem;
}

@keyframes arenaShake {
    0%, 100% { transform: translateX(0); }
    20%      { transform: translateX(-.4rem); }
    40%      { transform: translateX(.35rem); }
    60%      { transform: translateX(-.25rem); }
    80%      { transform: translateX(.15rem); }
}

/* --- Battle text banner -- the classic "X used ATTACK!" strip from
   Pokemon's own battle screen, same job: name the move that just
   happened in plain words, not just numbers. --- */
.battle-callout {
    position: relative;
    margin: 0 auto 1.2rem;
    max-width: 30rem;
    background: #fff;
    color: #050505;
    border: .18rem solid #050505;
    padding: .7rem 1.1rem;
    font-family: monospace;
    font-size: .92rem;
    font-weight: 700;
    letter-spacing: .01em;
    text-align: center;
    opacity: 0;
    transform: translateY(-.6rem);
    pointer-events: none;
}

.battle-callout.show { animation: calloutSlide 1.3s ease forwards; }

@keyframes calloutSlide {
    0%   { opacity: 0; transform: translateY(-.6rem); }
    12%  { opacity: 1; transform: translateY(0); }
    85%  { opacity: 1; transform: translateY(0); }
    100% { opacity: 0; transform: translateY(-.3rem); }
}

.battle-callout b { color: #e27800; }

@keyframes outcomePop {
    0%   { opacity: 0; transform: translateX(-50%) scale(.6); }
    20%  { opacity: 1; transform: translateX(-50%) scale(1.15); }
    30%  { transform: translateX(-50%) scale(1); }
    80%  { opacity: 1; }
    100% { opacity: 0; transform: translateX(-50%) scale(1) translateY(-.4rem); }
}

.stance-row {
    display: flex;
    gap: .7rem;
    justify-content: center;
    margin: 1.4rem 0 .6rem;
}

.stance-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .3rem;
    font-family: "Luckiest Guy";
    font-size: .95rem;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: #fff;
    background: #141414;
    border: .14rem solid rgba(255,255,255,.18);
    padding: .6rem 1.2rem;
    cursor: pointer;
    transition: .15s ease;
}

.stance-btn svg { width: 1.15rem; height: 1.15rem; fill: currentColor; }

.stance-btn:hover { border-color: #e27800; color: #e27800; }
.stance-btn.chosen { background: #e27800; border-color: #e27800; color: #050505; }
.stance-btn:disabled { opacity: .3; cursor: default; }

/* --- RPS cycle diagram --- */
.rps-diagram {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    margin: 0 0 1rem;
    flex-wrap: wrap;
}

.rps-diagram__node {
    display: flex;
    align-items: center;
    gap: .35rem;
    font-size: .74rem;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: rgba(255,255,255,.7);
}

.rps-diagram__node svg { width: .85rem; height: .85rem; fill: currentColor; }
.rps-diagram__arrow { color: rgba(226,120,0,.7); font-size: .8rem; }

/* --- Bot tendency tracker -- gives the player something real to
   read instead of a pure coin flip: the bot leans toward a stance
   each match, and its recent picks are shown so that lean is
   actually learnable. --- */
.bot-history {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .3rem;
    margin-top: .6rem;
    min-height: 1.4rem;
}

.bot-history__label {
    font-size: .62rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: rgba(255,255,255,.4);
    margin-right: .2rem;
}

.bot-history__icon {
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 50%;
    background: #141414;
    border: .1rem solid rgba(255,255,255,.15);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transform: scale(.5);
    animation: historyPopIn .25s ease forwards;
}

.bot-history__icon svg { width: .6rem; height: .6rem; fill: rgba(255,255,255,.75); }

@keyframes historyPopIn {
    to { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .battle-standee.lunge-you, .battle-standee.lunge-bot,
    .battle-standee.hit-flash .battle-standee__clip,
    .battle-standee--you img, .battle-standee--bot img,
    .dmg-pop, .clash-burst, .sting-flash, .sting-dart, .battle-scene.shake, .outcome-tag.show {
        animation: none !important;
    }
}

.battle-log {
    margin-top: 1.2rem;
    max-height: 8rem;
    overflow-y: auto;
    font-size: .85rem;
    color: rgba(255,255,255,.65);
    line-height: 1.6;
    border-top: 1px solid rgba(255,255,255,.1);
    padding-top: .8rem;
}

.battle-log__line b { color: #e27800; }

/* --- Win / Loss overlay --- */
.result-overlay {
    position: fixed;
    inset: 0;
    z-index: 999;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: rgba(0,0,0,0);
    transition: background .5s ease;
}

.result-overlay.show {
    display: flex;
    background: rgba(0,0,0,.92);
}

.result-overlay canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.result-card {
    position: relative;
    z-index: 2;
    text-align: center;
    max-width: 34rem;
    width: 100%;
    background: #0c0c0c;
    border: .26rem solid #e27800;
    padding: clamp(2rem, 5vw, 3rem) clamp(1.5rem, 4vw, 2.5rem);
    box-shadow: .8rem .8rem 0 rgba(226,120,0,.45);
    opacity: 0;
    transform: scale(.6) rotate(-2deg);
}

.result-overlay.show .result-card {
    animation: resultSlam .55s cubic-bezier(.2, 1.4, .4, 1) forwards;
}

@keyframes resultSlam {
    0%   { opacity: 0; transform: scale(.4) rotate(-6deg); }
    60%  { opacity: 1; transform: scale(1.08) rotate(1deg); }
    100% { opacity: 1; transform: scale(1) rotate(0); }
}

.result-overlay.lose .result-card {
    border-color: #6b6b6b;
    box-shadow: .8rem .8rem 0 rgba(90,90,90,.4);
}

.result-overlay.draw .result-card {
    border-color: #4fc3e8;
    box-shadow: .8rem .8rem 0 rgba(79,195,232,.35);
}

.result-eyebrow {
    font-size: .95rem;
    font-weight: 700;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: rgba(255,255,255,.5);
    margin-bottom: .6rem;
}

.result-title {
    font-family: "Luckiest Guy";
    font-size: clamp(3.4rem, 10vw, 5.5rem);
    line-height: .9;
    letter-spacing: .02em;
    color: #e27800;
    text-shadow: .09em .09em 0 #000;
    animation: glowPulse 1.6s ease-in-out infinite;
}

.result-overlay.lose .result-title {
    color: #9a9a9a;
    text-shadow: .09em .09em 0 #000;
    animation: shakeOut .45s ease;
}

.result-overlay.draw .result-title {
    color: #4fc3e8;
    text-shadow: .09em .09em 0 #000;
    animation: glowPulseBlue 1.6s ease-in-out infinite;
}

@keyframes glowPulseBlue {
    0%, 100% { filter: drop-shadow(0 0 .3rem rgba(79,195,232,.5)); }
    50%      { filter: drop-shadow(0 0 1.4rem rgba(79,195,232,.9)); }
}

@keyframes glowPulse {
    0%, 100% { filter: drop-shadow(0 0 .3rem rgba(226,120,0,.5)); }
    50%      { filter: drop-shadow(0 0 1.4rem rgba(226,120,0,.9)); }
}

@keyframes shakeOut {
    0%   { transform: translateX(0); }
    20%  { transform: translateX(-.6rem); }
    40%  { transform: translateX(.5rem); }
    60%  { transform: translateX(-.35rem); }
    80%  { transform: translateX(.2rem); }
    100% { transform: translateX(0); }
}

.result-sub {
    margin-top: .9rem;
    color: rgba(255,255,255,.75);
    font-size: 1.02rem;
    line-height: 1.5;
}

.result-squad {
    display: flex;
    align-items: center;
    gap: .6rem;
    justify-content: center;
    margin-top: 1.4rem;
}

.result-squad__divider {
    width: .12rem;
    height: 2.4rem;
    background: rgba(255,255,255,.2);
    margin: 0 .3rem;
}

.result-squad img {
    width: 3.4rem;
    height: 3.4rem;
    object-fit: cover;
    border: .12rem solid #000;
    opacity: 0;
    transform: translateY(.6rem);
    animation: popIn .4s ease forwards;
}

@keyframes popIn {
    to { opacity: 1; transform: translateY(0); }
}

.result-actions {
    display: flex;
    gap: .8rem;
    justify-content: center;
    margin-top: 1.8rem;
    flex-wrap: wrap;
}

.result-btn {
    font-family: "Luckiest Guy";
    font-size: 1rem;
    letter-spacing: .03em;
    text-transform: uppercase;
    padding: .75rem 1.5rem;
    border: .18rem solid #e27800;
    background: #e27800;
    color: #fff;
    cursor: pointer;
    transition: .18s ease;
}

.result-btn:hover { background: #000; color: #e27800; }
.result-btn.ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.25); }
.result-btn.ghost:hover { border-color: #fff; }

@media (prefers-reduced-motion: reduce) {
    .result-title { animation: none; }
    .result-card { animation: none !important; opacity: 1; transform: none; }
}

@media (max-width: 767.98px) {
    .battle-scene { height: clamp(16rem, 62vw, 19rem); }
    .battle-hpbox { min-width: 7.6rem; padding: .4rem .55rem .45rem; }
    .battle-hpbox__name { font-size: .72rem; }
    .roster-pip { width: 2.7rem; }
}
