/* Kamehameha easter egg: massive horizontal ki wave crossing the screen.
   In the anime the beam leaves a sustained trail of energy behind it as it
   travels, so there are two elements:
    - .kamehameha-wave: the bright leading edge that sweeps across
    - .kamehameha-trail: the lingering energy band that fills the path behind it
      and fades out after the head has passed */
.kamehameha-wave {
    position: fixed;
    top: 50%;
    left: -40%;
    width: 60%;
    /* Base wave: slightly smaller than before, so the upgrade feels like a real
       step up rather than "the same but brighter". */
    height: 42vh;
    min-height: 260px;
    max-height: 520px;
    transform: translateY(-50%);
    pointer-events: none;
    z-index: 9999;
    border-radius: 50% / 40%;
    background: radial-gradient(ellipse at 88% 50%,
        rgba(255, 255, 255, 1) 0%,
        rgba(220, 240, 255, 0.98) 12%,
        rgba(147, 197, 253, 0.92) 32%,
        rgba(59, 130, 246, 0.78) 55%,
        rgba(29, 78, 216, 0.45) 80%,
        transparent 100%);
    filter:
        blur(3px)
        drop-shadow(0 0 80px rgba(255, 255, 255, 0.95))
        drop-shadow(0 0 140px rgba(147, 197, 253, 1))
        drop-shadow(0 0 240px rgba(59, 130, 246, 0.9))
        drop-shadow(0 0 340px rgba(29, 78, 216, 0.55));
    /* Travel time: long enough to read as a sustained blast crossing the screen,
       like in the anime, rather than a quick flash. */
    animation: kamehameha-travel 2.2s cubic-bezier(0.45, 0, 0.3, 1) forwards;
    will-change: transform, opacity, left, width;
    opacity: 0;
}

@keyframes kamehameha-travel {
    0% {
        left: -50%;
        opacity: 0;
        width: 15%;
    }
    10% {
        opacity: 1;
        width: 35%;
    }
    50% {
        width: 70%;
        opacity: 1;
    }
    85% {
        width: 85%;
        opacity: 0.95;
    }
    100% {
        left: 150%;
        opacity: 0;
        width: 95%;
    }
}

/* ---- Energy trail behind the wave head ---------------------------------- */
/* The trail doesn't animate on its own: its width is set per-frame by JS to
   match the wave head's actual position, so the two stay perfectly linked. */
.kamehameha-trail {
    position: fixed;
    top: 50%;
    left: 8%;
    height: 28vh;
    min-height: 160px;
    max-height: 380px;
    width: 0;
    transform: translateY(-50%);
    pointer-events: none;
    z-index: 9998;
    border-radius: 8% / 40%;
    background: linear-gradient(90deg,
        rgba(147, 197, 253, 0.15) 0%,
        rgba(96, 165, 250, 0.55) 20%,
        rgba(59, 130, 246, 0.65) 50%,
        rgba(96, 165, 250, 0.55) 80%,
        rgba(219, 234, 254, 0.85) 100%);
    filter:
        blur(6px)
        drop-shadow(0 0 40px rgba(147, 197, 253, 0.8))
        drop-shadow(0 0 80px rgba(59, 130, 246, 0.5));
    opacity: 0;
    transition: opacity 0.6s ease-out;
    will-change: width, opacity;
}

.kamehameha-trail.active { opacity: 0.85; }
.kamehameha-trail.fading { opacity: 0; transition: opacity 0.8s ease-in; }

/* Bright centre seam in the trail */
.kamehameha-trail::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 10px;
    margin-top: -5px;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.7) 15%,
        rgba(219, 234, 254, 0.9) 50%,
        rgba(255, 255, 255, 0.7) 85%,
        transparent 100%);
    filter: blur(2px);
}

/* Ultimate trail: bigger, brighter */
.kamehameha-trail-ultimate {
    height: 52vh;
    min-height: 300px;
    max-height: 620px;
    background: linear-gradient(90deg,
        rgba(191, 219, 254, 0.2) 0%,
        rgba(147, 197, 253, 0.65) 15%,
        rgba(96, 165, 250, 0.8) 40%,
        rgba(59, 130, 246, 0.8) 60%,
        rgba(147, 197, 253, 0.65) 85%,
        rgba(255, 255, 255, 0.95) 100%);
    filter:
        blur(5px)
        drop-shadow(0 0 60px rgba(191, 219, 254, 1))
        drop-shadow(0 0 120px rgba(59, 130, 246, 0.8));
}

.kamehameha-trail-ultimate.active { opacity: 0.92; }
.kamehameha-trail-ultimate.fading { transition: opacity 1.2s ease-in; }

.kamehameha-trail-ultimate::after {
    height: 18px;
    margin-top: -9px;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.9) 10%,
        rgba(255, 255, 255, 1) 50%,
        rgba(255, 255, 255, 0.9) 90%,
        transparent 100%);
}

@media (prefers-reduced-motion: reduce) {
    .kamehameha-trail, .kamehameha-trail-ultimate { display: none; }
}

/* Blindingly bright core along the center line */
.kamehameha-wave::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 22px;
    margin-top: -11px;
    background: linear-gradient(to right,
        rgba(255, 255, 255, 0) 0%,
        rgba(255, 255, 255, 1) 45%,
        rgba(219, 234, 254, 1) 75%,
        rgba(147, 197, 253, 0.7) 100%);
    filter: blur(2px);
    box-shadow:
        0 0 30px rgba(255, 255, 255, 1),
        0 0 80px rgba(147, 197, 253, 0.9);
}

/* Dense trailing streaks of ki */
.kamehameha-wave::after {
    content: '';
    position: absolute;
    top: 25%;
    left: 0;
    right: 0;
    bottom: 25%;
    background:
        repeating-linear-gradient(to right,
            transparent 0,
            transparent 30px,
            rgba(255, 255, 255, 0.25) 30px,
            rgba(255, 255, 255, 0.25) 35px);
    mix-blend-mode: screen;
    opacity: 0.6;
}

/* Charging orb (flash before the blast) - progressive sizes for each typed stage.
   Positioned so the center stays anchored to the left side regardless of size. */
.kamehameha-charge {
    position: fixed;
    top: 50%;
    left: 8%;
    width: 320px;
    height: 320px;
    margin: 0;
    border-radius: 50%;
    background: radial-gradient(circle,
        rgba(255, 255, 255, 1) 0%,
        rgba(219, 234, 254, 0.95) 25%,
        rgba(147, 197, 253, 0.8) 50%,
        rgba(37, 99, 235, 0.4) 75%,
        transparent 100%);
    filter: blur(4px);
    opacity: 0;
    pointer-events: none;
    z-index: 9999;
    animation: kamehameha-charge 0.7s ease-out forwards;
    will-change: transform, opacity;
    /* Anchor the center to (left 8%, top 50%) so all sizes pulse from the same spot */
    transform: translate(-50%, -50%) scale(0);
    transform-origin: center center;
}

/* Stage 1: "kame" — small, subtle */
.kamehameha-charge.charge-stage-1 {
    width: 120px;
    height: 120px;
    filter: blur(2px);
    animation: charge-stage-grow 1.2s ease-out forwards;
    --charge-peak-scale: 0.85;
}

/* Stage 2: "kameha" — medium */
.kamehameha-charge.charge-stage-2 {
    width: 200px;
    height: 200px;
    filter: blur(3px);
    animation: charge-stage-grow 1.2s ease-out forwards;
    --charge-peak-scale: 1;
}

/* Stage 3: "kamehame" — large, intense */
.kamehameha-charge.charge-stage-3 {
    width: 280px;
    height: 280px;
    filter: blur(3.5px)
        drop-shadow(0 0 40px rgba(147, 197, 253, 0.85));
    animation: charge-stage-grow 1.2s ease-out forwards;
    --charge-peak-scale: 1.05;
}

/* Stage 4: "kamehameha" — final burst before the wave */
.kamehameha-charge.charge-stage-4 {
    filter: blur(4px)
        drop-shadow(0 0 60px rgba(147, 197, 253, 1))
        drop-shadow(0 0 120px rgba(37, 99, 235, 0.8));
    animation: kamehameha-charge 0.7s ease-out forwards;
}

@keyframes kamehameha-charge {
    0%   { transform: translate(-50%, -50%) scale(0); opacity: 0; }
    35%  { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
    100% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; }
}

/* Progressive charge: grows, holds, then fades if no next stage happens */
@keyframes charge-stage-grow {
    0%   { transform: translate(-50%, -50%) scale(0); opacity: 0; }
    25%  { transform: translate(-50%, -50%) scale(var(--charge-peak-scale, 1)); opacity: 0.95; }
    60%  { transform: translate(-50%, -50%) scale(var(--charge-peak-scale, 1)); opacity: 0.8; }
    100% { transform: translate(-50%, -50%) scale(calc(var(--charge-peak-scale, 1) * 0.85)); opacity: 0; }
}

/* Label announcing the caster */
.kamehameha-label {
    position: fixed;
    top: 18%;
    left: 50%;
    transform: translateX(-50%);
    font-family: 'Impact', 'Arial Black', sans-serif;
    font-size: clamp(1.5rem, 5vw, 3rem);
    font-weight: 900;
    color: #fff;
    letter-spacing: 2px;
    text-shadow:
        0 0 14px rgba(147, 197, 253, 1),
        0 0 28px rgba(37, 99, 235, 0.9),
        0 4px 10px rgba(0, 0, 0, 0.8);
    z-index: 9999;
    pointer-events: none;
    animation: kamehameha-label 2.1s ease-out forwards;
    will-change: transform, opacity;
}

@keyframes kamehameha-label {
    0%   { transform: translate(-50%, -20px) scale(0.6); opacity: 0; }
    12%  { transform: translate(-50%, 0) scale(1.1); opacity: 1; }
    20%  { transform: translate(-50%, 0) scale(1); opacity: 1; }
    80%  { opacity: 1; }
    100% { transform: translate(-50%, -20px) scale(1); opacity: 0; }
}

/* Full-body screen shake while the blast travels */
.kamehameha-shake {
    animation: kamehameha-shake-anim 0.12s ease-in-out 7;
}

@keyframes kamehameha-shake-anim {
    0%, 100% { transform: translate(0, 0); }
    25%      { transform: translate(-4px, 2px); }
    50%      { transform: translate(3px, -3px); }
    75%      { transform: translate(-2px, -2px); }
}


/* Knockback: participants caught in the wave's path get pushed to the right,
   spin a bit, then spring back to their original spot. */
.kamehameha-hit .dbz-participant-card {
    animation: kamehameha-knockback 1.8s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    will-change: transform, filter;
}

@keyframes kamehameha-knockback {
    0% {
        transform: translateX(0) rotate(0deg) scale(1);
        filter: brightness(1);
    }
    15% {
        transform: translateX(80px) rotate(15deg) scale(1.05);
        filter: brightness(1.5) drop-shadow(0 0 8px rgba(147, 197, 253, 0.8));
    }
    35% {
        transform: translateX(140px) rotate(25deg) scale(0.95);
        filter: brightness(1.2);
    }
    55% {
        transform: translateX(120px) rotate(15deg) scale(1);
        filter: brightness(1);
    }
    75% {
        transform: translateX(40px) rotate(-5deg) scale(1);
    }
    90% {
        transform: translateX(10px) rotate(2deg) scale(1);
    }
    100% {
        transform: translateX(0) rotate(0deg) scale(1);
    }
}


/* Kamehameha stun: while active, the local user can't punch others.
   Visual cue on the user's own avatar + non-allowed cursor on everyone else. */
body.kamehameha-stunned [data-user-id] {
    cursor: not-allowed !important;
}

body.kamehameha-stunned [data-user-id] .dbz-participant-card {
    filter: grayscale(0.35) brightness(0.9);
}


/* Dizzy stars orbiting a stunned avatar - visible to everyone */
.kamehameha-stun-orbit {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    pointer-events: none;
    z-index: 25;
    animation: kameha-stun-orbit-rotate 1.6s linear infinite;
    will-change: transform;
    transform-origin: 0 0;
}

.kamehameha-stun-star {
    position: absolute;
    top: -10px;
    left: -10px;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    line-height: 1;
    color: #fde047;
    text-shadow:
        0 0 6px rgba(253, 224, 71, 0.95),
        0 0 12px rgba(250, 204, 21, 0.7),
        0 1px 2px rgba(0, 0, 0, 0.7);
    transform-origin: 0 0;
    animation: kameha-stun-star-pop 0.4s ease-out;
}

@keyframes kameha-stun-orbit-rotate {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@keyframes kameha-stun-star-pop {
    0%   { opacity: 0; }
    100% { opacity: 1; }
}

/* Subtle wobble on the stunned avatar card itself */
.kamehameha-stunned-visual .dbz-participant-card {
    animation: kameha-stun-wobble 1.4s ease-in-out infinite;
}

@keyframes kameha-stun-wobble {
    0%, 100% { transform: rotate(0deg); }
    25%      { transform: rotate(-3deg); }
    75%      { transform: rotate(3deg); }
}

/* --- Konami code reward: SSJ2 background takeover ----------------------- */
/* Sits between the page background and the UI: z-index 0 paints above the body
 * gradient, while the app content is lifted to z-index 1 for the duration (see
 * .konami-active below). The body background is never modified, so when the
 * backdrop fades out the original background is simply revealed again —
 * no hard cut, fully seamless. */
.konami-backdrop {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
    background: radial-gradient(circle at 50% 45%,
            rgba(255, 220, 90, 0.25) 0%,
            rgba(255, 150, 20, 0.18) 35%,
            rgba(0, 0, 0, 0.55) 100%);
    animation: konami-backdrop-in 0.6s ease-out;
    opacity: 1;
    /* Long, eased fade so the original background returns gradually. */
    transition: opacity 1.8s cubic-bezier(0.4, 0, 0.5, 1);
}

.konami-backdrop.fading {
    opacity: 0;
}

/* Fade the gif out. Same reasoning as the Genkidama backdrop: cancelling the
 * pulse animation mid-cycle snaps the transform back to its base value, which
 * reads as a jolt/zoom right before the gif disappears. Animate opacity only. */
.konami-backdrop.fading .konami-backdrop-img {
    opacity: 0;
    transition: opacity 1.5s ease-in;
}

.konami-backdrop-img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    min-width: 100%;
    min-height: 100%;
    object-fit: cover;
    /* Let the UI stay readable on top of the gif */
    opacity: 0.55;
    filter: saturate(1.2) contrast(1.05);
    animation: konami-img-pulse 2.4s ease-in-out infinite alternate;
    /* JS holds opacity at 0 until the gif is decoded, then clears the inline
       value; this makes that reveal a soft fade instead of a pop. */
    transition: opacity 0.5s ease-out;
}

@keyframes konami-backdrop-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes konami-img-pulse {
    from { transform: translate(-50%, -50%) scale(1); }
    to   { transform: translate(-50%, -50%) scale(1.06); }
}

/* Golden aura flash over the whole page as the code lands */
.konami-backdrop::after {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at 50% 50%,
            rgba(255, 255, 255, 0.5) 0%,
            rgba(255, 210, 60, 0.25) 30%,
            transparent 70%);
    animation: konami-flash 0.8s ease-out forwards;
}

@keyframes konami-flash {
    0%   { opacity: 1; }
    100% { opacity: 0; }
}

/* Lift the UI above the backdrop so it stays visible and usable while the gif
 * plays underneath. Only stacking is touched — never the background itself —
 * so removing this class can't cause a visible flash. */
body.konami-active #login-screen,
body.konami-active #game-screen {
    position: relative;
    z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
    .konami-backdrop-img { animation: none; }
    .konami-backdrop::after { animation: none; opacity: 0; }
}

/* --- Konami explosion: flash, shockwaves, motes, lightning, shake -------- */

/* Full-screen white flash at the moment of activation */
.konami-flash-screen {
    position: fixed;
    inset: 0;
    z-index: 9997;
    pointer-events: none;
    background: radial-gradient(circle at 50% 50%,
            rgba(255, 255, 255, 0.95) 0%,
            rgba(255, 240, 170, 0.75) 35%,
            rgba(255, 190, 40, 0.35) 65%,
            transparent 100%);
    animation: konami-screen-flash 0.7s ease-out forwards;
}

@keyframes konami-screen-flash {
    0%   { opacity: 1; }
    25%  { opacity: 0.75; }
    100% { opacity: 0; }
}

/* Expanding golden shockwave rings */
.konami-shockwave {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 120px;
    height: 120px;
    margin-left: -60px;
    margin-top: -60px;
    border-radius: 50%;
    pointer-events: none;
    z-index: 9996;
    border: 6px solid rgba(255, 225, 120, 0.95);
    box-shadow:
        0 0 40px 12px rgba(255, 200, 60, 0.75),
        inset 0 0 30px 8px rgba(255, 240, 180, 0.55);
    animation: konami-shockwave-expand 1.3s cubic-bezier(0.15, 0.6, 0.3, 1) forwards;
    will-change: transform, opacity;
}

@keyframes konami-shockwave-expand {
    0% {
        transform: scale(0.15);
        opacity: 1;
        border-width: 10px;
    }
    70% {
        opacity: 0.55;
    }
    100% {
        /* Big enough to sweep past the screen edges on any aspect ratio */
        transform: scale(26);
        opacity: 0;
        border-width: 1px;
    }
}

/* Ki motes blasted outward from the centre */
.konami-mote {
    position: fixed;
    border-radius: 50%;
    pointer-events: none;
    z-index: 9996;
    background: radial-gradient(circle,
            #fff 0%,
            rgba(255, 235, 150, 0.95) 45%,
            rgba(255, 170, 30, 0) 100%);
    box-shadow: 0 0 12px 4px rgba(255, 205, 80, 0.8);
    animation: konami-mote-fly 1.1s cubic-bezier(0.1, 0.7, 0.3, 1) forwards;
    will-change: transform, opacity;
}

@keyframes konami-mote-fly {
    0% {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
    }
    100% {
        opacity: 0;
        transform: translate(calc(-50% + var(--mx, 0)), calc(-50% + var(--my, 0))) scale(0.25);
    }
}

/* Konami lightning bolts: brighter/thicker than the ambient streak sparks,
   and raised above the backdrop so they read clearly.
   NOTE: the base .ssj2-spark animation animates `transform: scaleY(...)`, which
   would wipe out the per-segment rotation set inline (making every bolt
   vertical). We use a dedicated animation that keeps the rotation by reading it
   from the --bolt-rot custom property. */
.ssj2-spark.konami-bolt {
    z-index: 9995;
    width: 4px;
    filter: drop-shadow(0 0 8px rgba(190, 240, 255, 0.95))
            drop-shadow(0 0 18px rgba(90, 190, 255, 0.7));
    transform: rotate(var(--bolt-rot, 0rad)) scaleY(0.3);
    animation: konami-bolt-flash 0.5s ease-out forwards;
}

@keyframes konami-bolt-flash {
    0%   { opacity: 0; transform: rotate(var(--bolt-rot, 0rad)) scaleY(0.3); }
    18%  { opacity: 1; transform: rotate(var(--bolt-rot, 0rad)) scaleY(1); }
    65%  { opacity: 1; transform: rotate(var(--bolt-rot, 0rad)) scaleY(1); }
    100% { opacity: 0; transform: rotate(var(--bolt-rot, 0rad)) scaleY(0.75); }
}

/* Announcement label */
.konami-label {
    position: fixed;
    top: 16%;
    left: 50%;
    transform: translateX(-50%);
    font-family: 'Impact', 'Arial Black', sans-serif;
    font-size: clamp(1.3rem, 4.5vw, 2.8rem);
    font-weight: 900;
    letter-spacing: 2px;
    text-align: center;
    white-space: nowrap;
    color: #fff;
    z-index: 9998;
    pointer-events: none;
    text-shadow:
        0 0 14px rgba(255, 225, 100, 1),
        0 0 30px rgba(255, 170, 20, 0.9),
        0 4px 12px rgba(0, 0, 0, 0.85);
    animation: konami-label-anim 3s ease-out forwards;
    will-change: transform, opacity;
}

@keyframes konami-label-anim {
    0%   { transform: translate(-50%, -24px) scale(0.5); opacity: 0; }
    10%  { transform: translate(-50%, 0) scale(1.15); opacity: 1; }
    18%  { transform: translate(-50%, 0) scale(1); opacity: 1; }
    82%  { opacity: 1; }
    100% { transform: translate(-50%, -20px) scale(1); opacity: 0; }
}

/* Screen shake (applied to #game-screen, never body) */
.konami-shake {
    animation: konami-shake-anim 0.11s ease-in-out 9;
}

@keyframes konami-shake-anim {
    0%, 100% { transform: translate(0, 0); }
    25%      { transform: translate(-7px, 4px); }
    50%      { transform: translate(6px, -5px); }
    75%      { transform: translate(-4px, -3px); }
}

@media (prefers-reduced-motion: reduce) {
    .konami-shockwave, .konami-mote, .konami-flash-screen,
    .ssj2-spark.konami-bolt {
        display: none;
    }
    .konami-shake { animation: none; }
}

/* ===== Kamehameha: beefed-up charge & fire ============================== */

/* --- Charge: ki being sucked INTO the orb -------------------------------- */
.kameha-inflow {
    position: fixed;
    border-radius: 50%;
    pointer-events: none;
    z-index: 9994;
    background: radial-gradient(circle,
            #fff 0%,
            rgba(191, 219, 254, 0.95) 40%,
            rgba(59, 130, 246, 0) 100%);
    box-shadow: 0 0 10px 3px rgba(147, 197, 253, 0.85);
    animation: kameha-inflow-suck 0.75s ease-in forwards;
    will-change: transform, opacity;
}

/* Travels from the rim (--fx/--fy) inward to the charge point. */
@keyframes kameha-inflow-suck {
    0% {
        opacity: 0;
        transform: translate(calc(-50% + var(--fx, 0)), calc(-50% + var(--fy, 0))) scale(1.1);
    }
    20% {
        opacity: 1;
    }
    100% {
        opacity: 0;
        transform: translate(-50%, -50%) scale(0.2);
    }
}

/* --- Electric arcs around the orb / along the beam ---------------------- */
/* Same trick as the konami bolts: keep rotation in a custom property so the
   scaleY pulse in the keyframes can't wipe it out. */
.ssj2-spark.kameha-arc {
    z-index: 9995;
    width: 3px;
    filter: drop-shadow(0 0 7px rgba(200, 235, 255, 0.95))
            drop-shadow(0 0 16px rgba(59, 130, 246, 0.8));
    transform: rotate(var(--bolt-rot, 0rad)) scaleY(0.3);
    animation: kameha-arc-flash 0.45s ease-out forwards;
}

@keyframes kameha-arc-flash {
    0%   { opacity: 0; transform: rotate(var(--bolt-rot, 0rad)) scaleY(0.3); }
    20%  { opacity: 1; transform: rotate(var(--bolt-rot, 0rad)) scaleY(1); }
    65%  { opacity: 1; transform: rotate(var(--bolt-rot, 0rad)) scaleY(1); }
    100% { opacity: 0; transform: rotate(var(--bolt-rot, 0rad)) scaleY(0.7); }
}

/* --- Charge rumble (intensifies per stage) ------------------------------- */
.kamehameha-rumble-1 { animation: kameha-rumble-1 0.09s ease-in-out 12; }
.kamehameha-rumble-2 { animation: kameha-rumble-2 0.08s ease-in-out 14; }
.kamehameha-rumble-3 { animation: kameha-rumble-3 0.07s ease-in-out 16; }

@keyframes kameha-rumble-1 {
    0%, 100% { transform: translate(0, 0); }
    50%      { transform: translate(-1.5px, 1px); }
}

@keyframes kameha-rumble-2 {
    0%, 100% { transform: translate(0, 0); }
    33%      { transform: translate(-3px, 2px); }
    66%      { transform: translate(2px, -2px); }
}

@keyframes kameha-rumble-3 {
    0%, 100% { transform: translate(0, 0); }
    25%      { transform: translate(-5px, 3px); }
    50%      { transform: translate(4px, -3px); }
    75%      { transform: translate(-3px, -2px); }
}

/* --- Fire: blinding flash ----------------------------------------------- */
.kameha-fire-flash {
    position: fixed;
    inset: 0;
    z-index: 9997;
    pointer-events: none;
    background: radial-gradient(circle at 10% 50%,
            rgba(255, 255, 255, 0.98) 0%,
            rgba(219, 234, 254, 0.8) 28%,
            rgba(96, 165, 250, 0.4) 55%,
            transparent 85%);
    animation: kameha-fire-flash-anim 0.8s ease-out forwards;
}

@keyframes kameha-fire-flash-anim {
    0%   { opacity: 1; }
    30%  { opacity: 0.7; }
    100% { opacity: 0; }
}

/* --- Fire: muzzle shockwave rings --------------------------------------- */
.kameha-shockwave {
    position: fixed;
    width: 100px;
    height: 100px;
    margin-left: -50px;
    margin-top: -50px;
    border-radius: 50%;
    pointer-events: none;
    z-index: 9996;
    border: 5px solid rgba(191, 219, 254, 0.95);
    box-shadow:
        0 0 36px 10px rgba(96, 165, 250, 0.7),
        inset 0 0 26px 6px rgba(219, 234, 254, 0.5);
    animation: kameha-shockwave-expand 1.2s cubic-bezier(0.15, 0.6, 0.3, 1) forwards;
    will-change: transform, opacity;
}

@keyframes kameha-shockwave-expand {
    0%   { transform: scale(0.15); opacity: 1; border-width: 9px; }
    70%  { opacity: 0.5; }
    100% { transform: scale(22); opacity: 0; border-width: 1px; }
}

/* --- Fire: recoil debris ------------------------------------------------ */
.kameha-debris {
    position: fixed;
    border-radius: 2px;
    pointer-events: none;
    z-index: 9996;
    background: linear-gradient(135deg, #fff 0%, #bfdbfe 50%, #3b82f6 100%);
    box-shadow: 0 0 9px 3px rgba(147, 197, 253, 0.8);
    animation: kameha-debris-fly 0.95s cubic-bezier(0.1, 0.7, 0.3, 1) forwards;
    will-change: transform, opacity;
}

@keyframes kameha-debris-fly {
    0% {
        opacity: 1;
        transform: translate(-50%, -50%) rotate(0deg) scale(1);
    }
    100% {
        opacity: 0;
        transform: translate(calc(-50% + var(--dx, 0)), calc(-50% + var(--dy, 0)))
                   rotate(540deg) scale(0.25);
    }
}

@media (prefers-reduced-motion: reduce) {
    .kameha-inflow, .kameha-shockwave, .kameha-debris,
    .kameha-fire-flash, .ssj2-spark.kameha-arc {
        display: none;
    }
    .kamehameha-rumble-1, .kamehameha-rumble-2, .kamehameha-rumble-3 {
        animation: none;
    }
}

/* ===== Ultimate Kamehameha (stage 5, "kamehameha!") ======================== */
/* A wider, brighter beam on top of the standard fire. */
.kamehameha-wave-ultimate {
    /* Noticeably bigger than the base: fills most of the screen vertically. */
    height: 82vh;
    min-height: 480px;
    max-height: 920px;
    filter:
        blur(2px)
        drop-shadow(0 0 100px rgba(255, 255, 255, 1))
        drop-shadow(0 0 180px rgba(147, 197, 253, 1))
        drop-shadow(0 0 300px rgba(59, 130, 246, 0.95))
        drop-shadow(0 0 420px rgba(29, 78, 216, 0.6));
    /* Slow, cinematic travel like in the anime: the beam takes its time
       sweeping across the screen, keeping the tension longer. */
    animation-duration: 3.5s;
}

/* Brighter core */
.kamehameha-wave-ultimate::before {
    height: 30px;
    margin-top: -15px;
}

/* Gif backdrop (same seamless approach as Konami and Genkidama). */
.kame-backdrop {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
    opacity: 1;
    animation: konami-backdrop-in 0.5s ease-out;
    transition: opacity 1.8s cubic-bezier(0.4, 0, 0.5, 1);
}

.kame-backdrop.fading {
    opacity: 0;
}

.kame-backdrop-img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    min-width: 100%;
    min-height: 100%;
    object-fit: cover;
    opacity: 0.5;
    filter: saturate(1.3) contrast(1.1) brightness(0.85);
    transition: opacity 0.5s ease-out;
    animation: konami-img-pulse 2s ease-in-out infinite alternate;
}

/* Only fade opacity when exiting (see the Konami/Genkidama note about not
   cancelling drift animations mid-cycle — same reasoning applies here). */
.kame-backdrop.fading .kame-backdrop-img {
    opacity: 0;
    transition: opacity 1.5s ease-in;
}

/* Lift the UI above the backdrop while it plays. */
body.kame-ultimate-active #login-screen,
body.kame-ultimate-active #game-screen {
    position: relative;
    z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
    .kamehameha-wave-ultimate { animation-duration: 0s; }
    .kame-backdrop-img { animation: none; }
}

/* === Kamehameha charge-hold: the beam is ready but waiting for the ! ====== */
/* A large, violently pulsing orb that screams "I'm about to fire". */
.kamehameha-charge.charge-hold {
    width: 360px;
    height: 360px;
    filter:
        blur(4px)
        drop-shadow(0 0 80px rgba(147, 197, 253, 1))
        drop-shadow(0 0 160px rgba(59, 130, 246, 0.9))
        drop-shadow(0 0 260px rgba(29, 78, 216, 0.6));
    animation: kameha-charge-hold 0.45s ease-in-out infinite alternate;
    opacity: 1;
}

@keyframes kameha-charge-hold {
    0% {
        transform: translate(-50%, -50%) scale(1);
        filter: blur(4px) brightness(1)
            drop-shadow(0 0 80px rgba(147, 197, 253, 1));
    }
    100% {
        transform: translate(-50%, -50%) scale(1.15);
        filter: blur(5px) brightness(1.4)
            drop-shadow(0 0 100px rgba(255, 255, 255, 0.9));
    }
}
