/* ============================================================
   Zallixor — gifts.css
   Every gift animation in the catalog, plus the picker, the player
   overlay and the Wallet page.

   Rules this file follows:
     - SVG + CSS only. No video, no GIF, no sprite sheets — the whole
       50-gift catalog costs a few KB and decodes instantly.
     - Only transform and opacity are animated, so gifts stay on the
       GPU compositor and don't force layout on low-spec Android.
     - Everything honours prefers-reduced-motion (see the bottom of
       this file): the art still appears, it just stops moving.
   ============================================================ */

:root {
  /* The gift catalog's green accent. The app's own palette is violet +
     cyan; green is reserved for Zallixor's signature gifts (Heart,
     Green Heart, Love Burst, Z-World ring, Z-King gems, Legacy). */
  --zx-green:      #22e07a;
  --zx-green-deep: #0f9d59;
}
:root[data-theme="light"] {
  --zx-green:      #12b866;
  --zx-green-deep: #0a7a43;
}

/* ── Shared gift art shell ────────────────────────────────── */
.gift-svg { width: 100%; height: 100%; display: block; overflow: visible; }
.gift-thumb { display: grid; place-items: center; flex: 0 0 auto; }
.gift-thumb-missing { border-radius: 10px; background: var(--panel-2); }

/* ── Full-screen player overlay ───────────────────────────── */
.gift-play-layer {
  position: fixed; inset: 0; z-index: 120;
  display: grid; place-items: center;
  pointer-events: none;                 /* never blocks the live stream/chat */
  animation: gift-layer-in .2s ease-out both;
}
.gift-play-layer.out { animation: gift-layer-out .3s ease-in both; }
@keyframes gift-layer-in  { from { opacity: 0 } to { opacity: 1 } }
@keyframes gift-layer-out { to   { opacity: 0 } }

.gift-stage { width: min(56vw, 260px); aspect-ratio: 1; }
/* Legendary and Signature gifts take the screen — that's the point of them. */
.gift-stage.fx-galaxy, .gift-stage.fx-legacy,
.gift-stage.fx-launch-far, .gift-stage.fx-storm, .gift-stage.fx-royal,
.gift-stage.fx-superstar, .gift-stage.fx-phoenix, .gift-stage.fx-confetti,
.gift-stage.fx-shark, .gift-stage.fx-whale {
  width: min(86vw, 420px);
}
/* The Lion and Kong are the two "beast" signatures — biggest stage in
   the catalog, bigger even than the other Legendary/Signature gifts. */
.gift-stage.fx-lion, .gift-stage.fx-kong {
  width: min(96vw, 480px);
}

/* ============================================================
   TIER 1 — Everyday (1–2s, light)
   ============================================================ */

/* 1 Zallixor Heart */
.fx-pulse { animation: gx-pulse 1.4s ease-in-out both; }
@keyframes gx-pulse {
  0%   { transform: scale(.3); opacity: 0 }
  22%  { transform: scale(1.12); opacity: 1 }
  40%  { transform: scale(.96) }
  58%  { transform: scale(1.06) }
  76%  { transform: scale(1) }
  100% { transform: scale(1.02); opacity: 0 }
}

/* 2 Rose · 18 Sunshine Flower — petals unfurl */
.fx-bloom { animation: gx-fade-hold 1.6s ease-out both; }
.fx-bloom .gx-petals { transform-origin: 50% 42%; animation: gx-bloom 1.1s cubic-bezier(.2,.9,.3,1) both; }
@keyframes gx-bloom { from { transform: scale(.25) rotate(-40deg); opacity: 0 } to { transform: none; opacity: 1 } }

/* 3 Z-Coffee — steam rises */
.fx-rise { animation: gx-fade-hold 1.8s ease-out both; }
.fx-rise .gx-steam path { animation: gx-steam 1.6s ease-in-out infinite; }
@keyframes gx-steam {
  0%   { opacity: 0; transform: translateY(6px) }
  40%  { opacity: .9 }
  100% { opacity: 0; transform: translateY(-10px) }
}

/* 4 Star · 38 Gold Medal — one clean rotation */
.fx-spin-once { animation: gx-spin-once 1.5s cubic-bezier(.25,.9,.25,1) both; }
@keyframes gx-spin-once {
  0%   { transform: scale(.4) rotate(-140deg); opacity: 0 }
  35%  { transform: scale(1.1) rotate(0deg); opacity: 1 }
  80%  { transform: scale(1) rotate(0deg); opacity: 1 }
  100% { transform: scale(1.05); opacity: 0 }
}

/* 5 Spark · 39 Love Burst — outward scatter */
.fx-burst { animation: gx-fade-hold 1.4s ease-out both; }
.fx-burst .gx-spark {
  transform-origin: 50px 50px;
  animation: gx-spark-out .9s cubic-bezier(.15,.85,.3,1) both;
  animation-delay: calc(var(--i) * 40ms);
}
@keyframes gx-spark-out {
  from { transform: scale(.1) translate(0,0); opacity: 0 }
  40%  { opacity: 1 }
  to   { transform: scale(1.25); opacity: 0 }
}

/* 6 Gem · 29 Magic Orb · 35 Z-World — slow rotation */
.fx-spin-slow { animation: gx-spin-slow 1.9s ease-in-out both; }
@keyframes gx-spin-slow {
  0%   { transform: scale(.5) rotateY(0deg); opacity: 0 }
  25%  { opacity: 1 }
  100% { transform: scale(1) rotateY(360deg); opacity: 0 }
}
.fx-spin-slow .gx-orbitring { animation: gx-ring-spin 3s linear infinite; transform-origin: 50px 50px; }
@keyframes gx-ring-spin { to { transform: rotate(360deg) } }

/* 7 Celebration — balloons float off the top */
.fx-float-up { animation: gx-float-up 2s cubic-bezier(.3,.7,.4,1) both; }
@keyframes gx-float-up {
  0%   { transform: translateY(40%) scale(.7); opacity: 0 }
  25%  { opacity: 1 }
  100% { transform: translateY(-55%) scale(1); opacity: 0 }
}

/* 8 Gift Box · 9 Sweet Box — lid lifts, contents show */
.fx-open-box { animation: gx-fade-hold 2s ease-out both; }
.fx-open-box .gx-lid {
  transform-origin: 50px 44px;
  animation: gx-lid-off 1.1s cubic-bezier(.25,1.4,.4,1) .35s both;
}
@keyframes gx-lid-off {
  0%   { transform: none }
  55%  { transform: translateY(-26px) rotate(-16deg) }
  100% { transform: translateY(-40px) rotate(-26deg); opacity: 0 }
}
.fx-open-box .gx-spark { animation: gx-spark-out 1s ease-out .6s both; animation-delay: calc(600ms + var(--i) * 55ms); transform-origin: 50px 26px; }

/* 10 Cake · 12 Ice Cream — pop in with a settle */
.fx-pop-in { animation: gx-pop-in 1.9s cubic-bezier(.2,1.3,.35,1) both; }
@keyframes gx-pop-in {
  0%   { transform: scale(.2); opacity: 0 }
  30%  { transform: scale(1.12); opacity: 1 }
  46%  { transform: scale(.97) }
  60%  { transform: scale(1) }
  100% { transform: scale(1); opacity: 0 }
}
.fx-pop-in .gx-flame ellipse { animation: gx-flicker 320ms ease-in-out infinite alternate; transform-origin: center bottom; }

/* 11 Pizza — small bounce */
.fx-bounce { animation: gx-bounce 1.4s cubic-bezier(.3,1.2,.4,1) both; }
@keyframes gx-bounce {
  0%   { transform: translateY(-30%) scale(.7); opacity: 0 }
  35%  { transform: translateY(0) scale(1); opacity: 1 }
  50%  { transform: translateY(-9%) }
  65%  { transform: translateY(0) }
  78%  { transform: translateY(-4%) }
  90%  { transform: translateY(0) }
  100% { opacity: 0 }
}

/* 13 Teddy · 14 Kitty — a wave */
.fx-wave { animation: gx-pop-hold 1.8s ease-out both; }
.fx-wave .gx-arm { animation: gx-wave 480ms ease-in-out 4 alternate; }
@keyframes gx-wave { from { transform: rotate(-14deg) } to { transform: rotate(26deg) } }

/* 15 Puppy — happy hop */
.fx-hop { animation: gx-pop-hold 1.8s ease-out both; }
.fx-hop > .gift-svg { animation: gx-hop 420ms cubic-bezier(.3,1.4,.4,1) 3 both; }
@keyframes gx-hop {
  0%, 100% { transform: translateY(0) scaleY(1) }
  30%      { transform: translateY(-14%) scaleY(1.05) }
  70%      { transform: translateY(0) scaleY(.96) }
}

/* ============================================================
   TIER 2 — Special (2–4s)
   ============================================================ */

/* 16 Butterfly · 32 Sky Jet — crosses the screen */
.fx-fly-across { animation: gx-fly-across 3s cubic-bezier(.4,.1,.6,.9) both; }
@keyframes gx-fly-across {
  0%   { transform: translateX(-90%) translateY(12%) scale(.6); opacity: 0 }
  18%  { opacity: 1 }
  50%  { transform: translateX(0) translateY(-6%) scale(1) }
  82%  { opacity: 1 }
  100% { transform: translateX(90%) translateY(10%) scale(.7); opacity: 0 }
}
.fx-fly-across .gx-wingL { animation: gx-flapL 300ms ease-in-out infinite alternate; }
.fx-fly-across .gx-wingR { animation: gx-flapR 300ms ease-in-out infinite alternate; }
@keyframes gx-flapL { from { transform: scaleX(1) } to { transform: scaleX(.35) } }
@keyframes gx-flapR { from { transform: scaleX(1) } to { transform: scaleX(.35) } }
.fx-fly-across .gx-trail { animation: gx-trail 900ms ease-out infinite; }
@keyframes gx-trail { from { opacity: .6 } to { opacity: 0 } }

/* 17 Honey Bee · 43 Z-Dragon — circles the centre */
.fx-orbit { animation: gx-fade-hold 3.2s ease-out both; }
.fx-orbit .gx-orbiter { transform-origin: 50px 60px; animation: gx-orbit 2.4s linear infinite; }
@keyframes gx-orbit {
  from { transform: rotate(0deg) translateX(16px) rotate(0deg) }
  to   { transform: rotate(360deg) translateX(16px) rotate(-360deg) }
}

/* 19 Rainbow — bands draw in one after another */
.fx-arc-draw { animation: gx-fade-hold 3s ease-out both; }
.fx-arc-draw .gx-band {
  stroke-dasharray: 130; stroke-dashoffset: 130;
  animation: gx-draw 900ms ease-out both;
  animation-delay: calc(var(--i) * 90ms);
}
@keyframes gx-draw { to { stroke-dashoffset: 0 } }

/* 20 Moonlight — gentle drift */
.fx-drift { animation: gx-drift 3s ease-in-out both; }
@keyframes gx-drift {
  0%   { transform: translateY(16%) scale(.8); opacity: 0 }
  25%  { opacity: 1 }
  100% { transform: translateY(-14%) scale(1); opacity: 0 }
}

/* 21 Fire */
.fx-flicker { animation: gx-pop-hold 2.6s ease-out both; }
.fx-flicker > .gift-svg { animation: gx-flicker 260ms ease-in-out infinite alternate; transform-origin: 50% 85%; }
@keyframes gx-flicker { from { transform: scaleY(.94) scaleX(1.03) } to { transform: scaleY(1.06) scaleX(.97) } }

/* 22 Z-Bolt — a single hard flash */
.fx-flash { animation: gx-flash 2.2s ease-out both; }
@keyframes gx-flash {
  0%   { transform: scale(.5); opacity: 0 }
  8%   { transform: scale(1.25); opacity: 1 }
  14%  { opacity: .25 }
  20%  { opacity: 1 }
  28%  { opacity: .5 }
  34%  { transform: scale(1); opacity: 1 }
  100% { opacity: 0 }
}

/* 23 Music Note · 25 Guitar — notes float up */
.fx-notes-up, .fx-strum { animation: gx-fade-hold 3s ease-out both; }
.gx-note { animation: gx-note-up 1.6s ease-out infinite; animation-delay: calc(var(--i, 0) * 400ms); }
@keyframes gx-note-up {
  0%   { transform: translateY(20%) scale(.7); opacity: 0 }
  25%  { opacity: 1 }
  100% { transform: translateY(-60%) scale(1); opacity: 0 }
}
.fx-strum > .gift-svg { animation: gx-strum 700ms ease-in-out infinite alternate; transform-origin: 45% 65%; }
@keyframes gx-strum { from { transform: rotate(-4deg) } to { transform: rotate(4deg) } }

/* 24 Music Vibe — bars pulse to a beat */
.fx-pulse-wave { animation: gx-pop-hold 3s ease-out both; }
/* transform-box:fill-box makes transform-origin resolve against the bar
   itself rather than the whole SVG, so the equaliser bars grow up from
   their base instead of stretching outward from the canvas centre. */
.fx-pulse-wave .gx-w { animation: gx-eq 520ms ease-in-out infinite alternate;
  transform-box: fill-box; transform-origin: center bottom; }
/* .gx-waves is a plain grouping element — the bars inside it carry the
   animation, so it needs no rule of its own. */
@keyframes gx-eq { from { transform: scaleY(.45) } to { transform: scaleY(1.15) } }

/* 26 Mic Star · 34 Dream House · 37 Trophy — rise into a glow */
.fx-rise-glow { animation: gx-rise-glow 3.3s cubic-bezier(.2,.9,.3,1) both; }
@keyframes gx-rise-glow {
  0%   { transform: translateY(34%) scale(.55); opacity: 0 }
  28%  { transform: translateY(0) scale(1.06); opacity: 1 }
  40%  { transform: scale(1) }
  82%  { opacity: 1 }
  100% { transform: translateY(-6%) scale(1.02); opacity: 0 }
}
.fx-rise-glow .gx-spark { transform-origin: 50px 40px; animation: gx-twinkle 1.1s ease-in-out infinite; animation-delay: calc(var(--i) * 120ms); }
@keyframes gx-twinkle { 0%, 100% { opacity: .2; transform: scale(.7) } 50% { opacity: 1; transform: scale(1.2) } }
.fx-rise-glow .gx-window { animation: gx-twinkle 1.4s ease-in-out infinite; animation-delay: calc(var(--i, 0) * 300ms); }

/* 27 Dance */
.fx-dance { animation: gx-pop-hold 3.2s ease-out both; }
.fx-dance .gx-dancer { transform-origin: 52px 60px; animation: gx-dance 560ms ease-in-out infinite alternate; }
@keyframes gx-dance {
  from { transform: rotate(-9deg) translateX(-4px) }
  to   { transform: rotate(9deg) translateX(4px) }
}

/* 28 Crown — drops and shines */
.fx-drop-shine { animation: gx-drop-shine 3s cubic-bezier(.25,1.2,.4,1) both; }
@keyframes gx-drop-shine {
  0%   { transform: translateY(-70%) scale(.7) rotate(-8deg); opacity: 0 }
  30%  { transform: translateY(0) scale(1.08) rotate(0); opacity: 1 }
  42%  { transform: scale(1) }
  85%  { opacity: 1 }
  100% { transform: scale(1.04); opacity: 0 }
}
.fx-drop-shine .gx-spark { transform-origin: 50px 46px; animation: gx-twinkle 900ms ease-in-out infinite; animation-delay: calc(600ms + var(--i) * 140ms); }

/* 30 Green Heart — soft glow ring */
.fx-glow-ring { animation: gx-pulse 3s ease-in-out both; }
.fx-glow-ring .gx-ring { transform-origin: 50px 46px; animation: gx-ring-out 1.8s ease-out infinite; }
@keyframes gx-ring-out {
  from { transform: scale(.4); opacity: .9 }
  to   { transform: scale(1.25); opacity: 0 }
}

/* ============================================================
   TIER 3 — Premium (2–4s)
   ============================================================ */

/* 31 Z-Rocket */
.fx-launch { animation: gx-launch 3.4s cubic-bezier(.35,0,.6,1) both; }
@keyframes gx-launch {
  0%   { transform: translateY(45%) scale(.6); opacity: 0 }
  20%  { transform: translateY(10%) scale(1); opacity: 1 }
  45%  { transform: translateY(0) scale(1) }
  100% { transform: translateY(-120%) scale(.75); opacity: 0 }
}
.gx-thrust { animation: gx-flicker 130ms ease-in-out infinite alternate; transform-origin: 50% 0%; }

/* 33 Z-Car */
.fx-drive-across { animation: gx-drive 3.2s cubic-bezier(.35,.05,.5,1) both; }
@keyframes gx-drive {
  0%   { transform: translateX(-95%) scale(.85); opacity: 0 }
  15%  { opacity: 1 }
  85%  { opacity: 1 }
  100% { transform: translateX(95%) scale(.85); opacity: 0 }
}

/* 36 Coin Rain */
.fx-coin-rain { animation: gx-fade-hold 3.6s ease-out both; }
.fx-coin-rain .gx-coin {
  animation: gx-coin-fall 1.5s cubic-bezier(.4,0,.7,1) infinite;
  animation-delay: calc(var(--i) * 150ms);
}
@keyframes gx-coin-fall {
  0%   { transform: translateY(-40px) rotate(0); opacity: 0 }
  15%  { opacity: 1 }
  85%  { opacity: 1 }
  100% { transform: translateY(90px) rotate(200deg); opacity: 0 }
}

/* 40 Friendship — the link draws between the two hearts */
.fx-connect { animation: gx-pop-hold 3.4s ease-out both; }
.fx-connect .gx-link { stroke-dasharray: 34; stroke-dashoffset: 34; animation: gx-draw 700ms ease-out .5s both; }
.fx-connect .gx-spark { transform-origin: 50px 50px; animation: gx-twinkle 1s ease-in-out infinite; animation-delay: calc(1s + var(--i) * 120ms); }

/* ============================================================
   TIER 4 — Legendary (5–7s) & TIER 5 — Signature
   ============================================================ */

/* 41 Party Pop */
.fx-confetti { animation: gx-fade-hold 5s ease-out both; }
.fx-confetti .gx-confetti {
  animation: gx-confetti 2.2s cubic-bezier(.15,.7,.4,1) infinite;
  animation-delay: calc(var(--i) * 70ms);
}
@keyframes gx-confetti {
  0%   { transform: translate(-30px, 30px) scale(.4) rotate(0); opacity: 0 }
  15%  { opacity: 1 }
  70%  { opacity: 1 }
  100% { transform: translate(10px, 60px) scale(1) rotate(420deg); opacity: 0 }
}

/* 42 Zallixor Lion — the choreographed sequence.
   ✨ (0.0s) → 🦁 (0.7s, BIG entrance) → roar (1.6s, full-throated) →
   👑 (2.6s) → 💚 Z (3.6s) → fade
   The Lion is the biggest beast in the catalog after Kong: the stage
   itself is oversized (see .gift-stage.fx-lion above) and the entrance
   overshoots further than any other gift before settling. */
.fx-lion { animation: gx-fade-hold 6.5s ease-out both; position: relative; }
.fx-lion > .gift-svg { animation: gx-lion-enter 1.2s cubic-bezier(.2,1.3,.35,1) .7s both; }
@keyframes gx-lion-enter {
  0%   { transform: scale(.2) rotate(-12deg); opacity: 0 }
  55%  { transform: scale(1.34) rotate(0); opacity: 1 }
  75%  { transform: scale(1.1) }
  100% { transform: scale(1.16) }
}
.lion-seq { position: absolute; inset: 0; pointer-events: none; }
.lion-step { position: absolute; inset: 0; opacity: 0; }
.lion-sparkle { animation: gx-lion-step 1.1s ease-out 0s both; }
.lion-roar    { animation: gx-lion-roar 1.3s cubic-bezier(.2,.8,.3,1) 1.6s both; }
.lion-roar-burst { animation: gx-lion-roar-burst 1.1s ease-out 1.68s both; transform-origin: 50% 50%; }
.lion-crown   { animation: gx-lion-crown 1.4s cubic-bezier(.25,1.3,.4,1) 2.6s both; transform-origin: 50% 30%; }
.lion-cub-appear { animation: gx-lion-cub-in .9s cubic-bezier(.3,1.3,.4,1) 3.1s both; }
.lion-cub-svg { width: 46%; height: 46%; position: absolute; right: 2%; bottom: 4%; }
@keyframes gx-lion-cub-in {
  0%   { opacity: 0; transform: translate(60%, 40%) scale(.3) }
  55%  { opacity: 1; transform: translate(0, 0) scale(1.08) }
  75%  { transform: scale(.96) }
  100% { opacity: 1; transform: scale(1) }
}
.lion-z       { animation: gx-lion-z 2.2s ease-out 3.6s both; }
@keyframes gx-lion-step {
  0%   { opacity: 0; transform: scale(.4) }
  40%  { opacity: 1; transform: scale(1.1) }
  100% { opacity: 0; transform: scale(1.3) }
}
/* A real roar reads as a shockwave, not a polite ripple: rings punch
   out fast and far, and the mouth-level burst below gives it a jagged,
   forceful edge rather than perfect concentric circles. */
@keyframes gx-lion-roar {
  0%   { opacity: 0; transform: scale(.4) }
  20%  { opacity: 1 }
  100% { opacity: 0; transform: scale(2.6) }
}
@keyframes gx-lion-roar-burst {
  0%   { opacity: 0; transform: scale(.3) }
  25%  { opacity: 1; transform: scale(1) }
  60%  { opacity: .8; transform: scale(1.3) }
  100% { opacity: 0; transform: scale(1.7) }
}
/* The whole stage gets a short, sharp shake on the roar — the visual
   equivalent of the low-end thump in the matching sound design. */
.fx-lion { animation-name: gx-fade-hold; }
.fx-lion > .gift-svg { will-change: transform; }
.fx-lion.gift-stage { animation: gx-fade-hold 6.5s ease-out both, gx-lion-shake 6.5s linear both; }
@keyframes gx-lion-shake {
  0%, 24.5% { transform: translate(0, 0) }
  25%  { transform: translate(-2%, 1%) }
  25.5% { transform: translate(2%, -1%) }
  26%  { transform: translate(-1.4%, .6%) }
  26.5%, 100% { transform: translate(0, 0) }
}
@keyframes gx-lion-crown {
  0%   { opacity: 0; transform: translateY(-60%) scale(.6) }
  45%  { opacity: 1; transform: translateY(-32%) scale(1.05) }
  70%  { transform: translateY(-30%) scale(1) }
  100% { opacity: 1; transform: translateY(-30%) scale(1) }
}
@keyframes gx-lion-z {
  0%   { opacity: 0; transform: scale(.5) }
  35%  { opacity: 1; transform: scale(1.06) }
  70%  { opacity: 1; transform: scale(1) }
  100% { opacity: 0; transform: scale(1.1) }
}

/* 51 Zallixor Shark — choreographed: ripple → fin cuts past → lunge/bite → splash → Z */
.fx-shark { animation: gx-fade-hold 6.2s ease-out both; position: relative; }
.fx-shark > .gift-svg { animation: gx-shark-enter 1s cubic-bezier(.3,.9,.4,1) .5s both; }
@keyframes gx-shark-enter {
  0%   { transform: translateY(30%) scale(.5) rotate(-6deg); opacity: 0 }
  60%  { transform: translateY(-4%) scale(1.16) rotate(2deg); opacity: 1 }
  80%  { transform: translateY(0) scale(1) rotate(0) }
  100% { transform: scale(1.04) }
}
.shark-seq { position: absolute; inset: 0; pointer-events: none; }
.shark-step { position: absolute; inset: 0; opacity: 0; }
.shark-ripple { animation: gx-shark-ripple 1.1s ease-out 0s both; }
.shark-fin    { animation: gx-shark-fin .9s cubic-bezier(.3,.1,.5,1) .5s both; }
.shark-lunge  { animation: gx-lion-roar 1s cubic-bezier(.2,.8,.3,1) 1.5s both; }
.shark-splash { animation: gx-lion-step 1s ease-out 1.9s both; }
.shark-z      { animation: gx-lion-z 2s ease-out 2.9s both; }
@keyframes gx-shark-ripple {
  0%   { opacity: 0; transform: scale(.5) }
  30%  { opacity: .9 }
  100% { opacity: 0; transform: scale(1.5) }
}
@keyframes gx-shark-fin {
  0%   { opacity: 0; transform: translateX(-60%) }
  20%  { opacity: .95 }
  80%  { opacity: .95 }
  100% { opacity: 0; transform: translateX(60%) }
}

/* 52 Zallixor Whale — choreographed: deep glow → breach/tail → spout → splash → Z */
.fx-whale { animation: gx-fade-hold 6.2s ease-out both; position: relative; }
.fx-whale > .gift-svg { animation: gx-whale-enter 1.1s cubic-bezier(.25,.9,.35,1) .5s both; }
@keyframes gx-whale-enter {
  0%   { transform: translateY(40%) scale(.55); opacity: 0 }
  55%  { transform: translateY(-6%) scale(1.12); opacity: 1 }
  100% { transform: translateY(0) scale(1) }
}
.whale-seq { position: absolute; inset: 0; pointer-events: none; }
.whale-step { position: absolute; inset: 0; opacity: 0; }
.whale-deep   { animation: gx-lion-step 1.4s ease-out 0s both; }
.whale-tail   { animation: gx-shark-fin 1.1s cubic-bezier(.3,.1,.5,1) .8s both; }
.whale-spout  { animation: gx-whale-spout 1.2s ease-out 1.8s both; }
.whale-splash { animation: gx-lion-step 1.1s ease-out 2.6s both; }
.whale-z      { animation: gx-lion-z 2s ease-out 3.4s both; }
@keyframes gx-whale-spout {
  0%   { opacity: 0; transform: translateY(10%) scale(.6) }
  30%  { opacity: 1; transform: translateY(-6%) scale(1) }
  100% { opacity: 0; transform: translateY(-30%) scale(1.15) }
}

/* 53 Zallixor Kong — choreographed: jungle mist → BIG entrance →
   two chest beats (thump, thump) → full roar shockwave → Z on chest.
   The biggest stage in the catalog (see .gift-stage.fx-kong above). */
.fx-kong { animation: gx-fade-hold 6.8s ease-out both; position: relative; }
.fx-kong > .gift-svg { animation: gx-kong-enter 1.2s cubic-bezier(.2,1.2,.35,1) .6s both; }
@keyframes gx-kong-enter {
  0%   { transform: scale(.15) translateY(20%); opacity: 0 }
  55%  { transform: scale(1.3) translateY(-3%); opacity: 1 }
  75%  { transform: scale(1.08) }
  100% { transform: scale(1.14) }
}
.kong-seq { position: absolute; inset: 0; pointer-events: none; }
.kong-step { position: absolute; inset: 0; opacity: 0; }
.kong-mist  { animation: gx-lion-step 1.3s ease-out 0s both; }
.kong-beat1 { animation: gx-kong-beat .5s cubic-bezier(.2,.8,.3,1) 1.9s both; }
.kong-beat2 { animation: gx-kong-beat .5s cubic-bezier(.2,.8,.3,1) 2.5s both; }
.kong-roar  { animation: gx-lion-roar 1.4s cubic-bezier(.2,.8,.3,1) 3.2s both; }
.kong-z     { animation: gx-lion-z 2.2s ease-out 4.4s both; }
@keyframes gx-kong-beat {
  0%   { opacity: 0; transform: scale(.5) }
  35%  { opacity: 1; transform: scale(1.3) }
  100% { opacity: 0; transform: scale(1.8) }
}
/* The chest beats land as a real hit: the whole beast jolts on impact. */
.fx-kong.gift-stage { animation: gx-fade-hold 6.8s ease-out both, gx-kong-shake 6.8s linear both; }
@keyframes gx-kong-shake {
  0%, 27.5% { transform: translate(0, 0) }
  28%  { transform: translate(0, 2%) scale(1.01) }
  28.6% { transform: translate(0, 0) }
  35.5% { transform: translate(0, 0) }
  36%  { transform: translate(0, 2%) scale(1.01) }
  36.6%, 100% { transform: translate(0, 0) }
}

/* 44 Phoenix — rises and dissolves */
.fx-phoenix { animation: gx-phoenix 6s cubic-bezier(.3,.1,.4,1) both; }
@keyframes gx-phoenix {
  0%   { transform: translateY(45%) scale(.4); opacity: 0 }
  20%  { transform: translateY(6%) scale(1.05); opacity: 1 }
  35%  { transform: translateY(0) scale(1) }
  70%  { opacity: 1 }
  100% { transform: translateY(-70%) scale(1.15); opacity: 0 }
}

/* 45 Diamond Storm */
.fx-storm { animation: gx-fade-hold 6s ease-out both; }
.fx-storm .gx-crystal {
  animation: gx-crystal 2.4s ease-in-out infinite;
  animation-delay: calc(var(--i) * 260ms);
}
@keyframes gx-crystal {
  0%   { opacity: 0; transform: translateY(-14px) rotate(-12deg) }
  25%  { opacity: 1 }
  60%  { opacity: 1; transform: translateY(6px) rotate(8deg) }
  100% { opacity: 0; transform: translateY(20px) rotate(16deg) }
}

/* 46 Z-King */
.fx-royal { animation: gx-royal 6s cubic-bezier(.25,1.1,.4,1) both; }
@keyframes gx-royal {
  0%   { transform: translateY(-45%) scale(.5); opacity: 0 }
  22%  { transform: translateY(0) scale(1.1); opacity: 1 }
  32%  { transform: scale(1) }
  85%  { opacity: 1 }
  100% { transform: scale(1.06); opacity: 0 }
}
.fx-royal .gx-ring { transform-origin: 50px 50px; animation: gx-ring-out 2.2s ease-out infinite; }
.fx-royal .gx-spark { transform-origin: 50px 48px; animation: gx-twinkle 1.3s ease-in-out infinite; animation-delay: calc(var(--i) * 130ms); }

/* 47 Super Star — expands and releases sparkles */
.fx-superstar { animation: gx-superstar 5.5s cubic-bezier(.2,.9,.3,1) both; }
@keyframes gx-superstar {
  0%   { transform: scale(.15) rotate(-90deg); opacity: 0 }
  25%  { transform: scale(1.3) rotate(0); opacity: 1 }
  38%  { transform: scale(1) }
  55%  { transform: scale(1.12) }
  85%  { transform: scale(1); opacity: 1 }
  100% { transform: scale(1.5); opacity: 0 }
}
.fx-superstar .gx-spark { transform-origin: 50px 50px; animation: gx-spark-out 1.8s ease-out infinite; animation-delay: calc(1s + var(--i) * 90ms); }

/* 48 Zallixor Universe — rocket through a star field */
.fx-launch-far { animation: gx-fade-hold 6.5s ease-out both; }
.fx-launch-far .gx-ship { animation: gx-ship 3.2s cubic-bezier(.4,0,.5,1) .6s infinite; }
@keyframes gx-ship {
  0%   { transform: translateY(60px) scale(.6); opacity: 0 }
  20%  { opacity: 1 }
  80%  { opacity: 1 }
  100% { transform: translateY(-80px) scale(1.05); opacity: 0 }
}
.gx-star { animation: gx-twinkle 1.6s ease-in-out infinite; animation-delay: calc(var(--i) * 90ms); transform-box: fill-box; transform-origin: center; }

/* 49 Z-Universe · 50 Zallixor Legacy — galaxy rings */
.fx-galaxy { animation: gx-galaxy-in 6.5s cubic-bezier(.2,.9,.3,1) both; }
@keyframes gx-galaxy-in {
  0%   { transform: scale(.3) rotate(-40deg); opacity: 0 }
  20%  { transform: scale(1.06) rotate(0); opacity: 1 }
  32%  { transform: scale(1) }
  85%  { opacity: 1 }
  100% { transform: scale(1.2); opacity: 0 }
}
.gx-galaxy { transform-origin: 50px 50px; animation: gx-ring-spin 6s linear infinite; }

.fx-legacy { animation: gx-galaxy-in 7s cubic-bezier(.2,.9,.3,1) both; position: relative; }
.fx-legacy .gx-core { transform-origin: 50px 50px; animation: gx-core-beat 1.8s ease-in-out infinite; }
@keyframes gx-core-beat { 0%, 100% { transform: scale(1) } 50% { transform: scale(1.1) } }
/* The closing green light burst, timed to land after the ring forms. */
.legacy-burst { position: absolute; inset: 0; opacity: 0; animation: gx-legacy-burst 2.4s ease-out 3.4s both; }
@keyframes gx-legacy-burst {
  0%   { opacity: 0; transform: scale(.4) }
  30%  { opacity: 1; transform: scale(1.15) }
  100% { opacity: 0; transform: scale(1.9) }
}

/* ── Shared timing helpers ────────────────────────────────── */
@keyframes gx-fade-hold {
  0%   { opacity: 0; transform: scale(.9) }
  12%  { opacity: 1; transform: scale(1) }
  86%  { opacity: 1 }
  100% { opacity: 0 }
}
@keyframes gx-pop-hold {
  0%   { opacity: 0; transform: scale(.4) }
  16%  { opacity: 1; transform: scale(1.08) }
  26%  { transform: scale(1) }
  86%  { opacity: 1 }
  100% { opacity: 0; transform: scale(1.03) }
}

/* ============================================================
   THE PICKER SHEET
   ============================================================ */
.gift-sheet { padding: 14px 12px calc(16px + var(--safe-bottom)); max-height: 78dvh; display: flex; flex-direction: column; }
.gift-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 0 4px 10px; }
.gift-sheet-head h3 { margin: 0; font-family: var(--font-display); font-size: 1.05rem; }

.gift-balance { display: inline-flex; align-items: center; gap: 7px; background: var(--panel-2);
  border: 1px solid var(--line); border-radius: 999px; padding: 5px 6px 5px 11px; }
.gift-balance strong { font-variant-numeric: tabular-nums; }
.gift-coin-ico { display: inline-flex; color: var(--amber); }
.btn-xs { padding: 4px 10px; font-size: .72rem; border-radius: 999px; }

.gift-tabs { display: flex; gap: 6px; overflow-x: auto; padding: 2px 4px 10px; scrollbar-width: none; }
.gift-tabs::-webkit-scrollbar { display: none; }
.gift-tab { flex: 0 0 auto; background: var(--panel-2); border: 1px solid var(--line); color: var(--muted);
  border-radius: 999px; padding: 7px 14px; font-size: .8rem; font-weight: 600; }
.gift-tab.active { background: var(--accent-soft); border-color: var(--accent-a); color: var(--text); }

.gift-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px;
  overflow-y: auto; padding: 2px 4px 4px; -webkit-overflow-scrolling: touch; }
.gift-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 10px 4px 8px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius-sm); color: var(--text); }
.gift-cell:active { background: var(--panel-3); transform: scale(.96); }
.gift-cell:disabled { opacity: .5 }
.gift-cell-name { font-size: .68rem; text-align: center; line-height: 1.15; color: var(--muted); }
.gift-cell-price { display: inline-flex; align-items: center; gap: 3px; font-size: .72rem; font-weight: 700;
  color: var(--amber); font-variant-numeric: tabular-nums; }
.gift-cell-price .icon { width: 12px; height: 12px; }
/* Higher tiers read as more valuable at a glance. */
.gift-cell[data-tier="4"] { border-color: rgba(246,181,69,.45) }
.gift-cell[data-tier="5"] { border-color: var(--zx-green); box-shadow: 0 0 0 1px rgba(34,224,122,.18) inset }
.gift-empty { grid-column: 1 / -1; text-align: center; padding: 24px 8px; }

/* ============================================================
   THE WALLET PAGE
   ============================================================ */
.page-wallet { padding-bottom: 24px; }
.wallet-hero { display: grid; place-items: center; gap: 2px; padding: 22px 12px 16px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); margin: 8px 0 10px; }
.wallet-coin-ico { color: var(--amber); }
.wallet-coin-ico .icon { width: 30px; height: 30px; }
.wallet-bal { font-family: var(--font-display); font-size: 2.1rem; font-weight: 700; font-variant-numeric: tabular-nums; }

.wallet-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 6px; }
.wallet-stat { display: grid; place-items: center; gap: 1px; padding: 10px 6px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.wallet-stat strong { font-variant-numeric: tabular-nums; }

.wallet-section-head { padding: 14px 2px 8px; }
.wallet-section-head h3 { margin: 0; font-size: .95rem; font-family: var(--font-display); }

.coin-packs { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
.coin-pack { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 14px 8px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-sm); color: var(--text); }
.coin-pack:active { background: var(--panel-2); transform: scale(.97); }
.coin-pack-ico { color: var(--amber); }
.coin-pack-amt { font-weight: 700; font-variant-numeric: tabular-nums; }
.coin-pack-bonus { font-size: .66rem; color: var(--ok); font-weight: 600; }
.coin-pack-price { font-size: .8rem; color: var(--muted); margin-top: 2px; }

.wallet-pending-row, .wallet-hist-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-sm); margin-bottom: 6px; }
.wallet-pending-row { justify-content: space-between; }
.wallet-hist-mid { flex: 1; min-width: 0; }
.wallet-hist-mid strong { display: block; font-size: .88rem; }
.wallet-hist-amt { font-weight: 700; font-variant-numeric: tabular-nums; font-size: .9rem; }
.wallet-hist-amt.in { color: var(--ok); }
.wallet-hist-amt.out { color: var(--muted); }
.pill { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: .7rem; font-weight: 600; }
.pill-amber { background: rgba(246,181,69,.16); color: var(--amber); }

/* ── In-chat / in-stream gift bubbles ─────────────────────── */
.gift-bubble { display: flex; align-items: center; gap: 8px; padding: 8px 12px 8px 8px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.gift-bubble-name { font-weight: 600; font-size: .85rem; }
.gift-bubble-coins { display: inline-flex; align-items: center; gap: 3px; font-size: .75rem;
  color: var(--amber); font-weight: 700; font-variant-numeric: tabular-nums; }

/* ── Motion sensitivity ───────────────────────────────────────
   The gift still appears and still reads as that gift — it just
   holds still instead of moving. Nothing is hidden. */
@media (prefers-reduced-motion: reduce) {
  .gift-play-layer,
  .gift-stage,
  .gift-stage *,
  .lion-step,
  .shark-step,
  .whale-step,
  .kong-step,
  .lion-cub-svg,
  .legacy-burst {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .gift-stage { animation: gx-static-hold 2.2s linear both !important; }
  .lion-step, .shark-step, .whale-step, .kong-step, .legacy-burst { opacity: 1 !important; }
  @keyframes gx-static-hold { 0%, 92% { opacity: 1 } 100% { opacity: 0 } }
}

/* ── Admin: gift price + coin pack editors ────────────────── */
.adm-price-list { max-height: 60vh; overflow-y: auto; border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 4px; margin-bottom: 10px; }
.adm-price-row { display: flex; align-items: center; gap: 10px; padding: 6px 6px;
  border-bottom: 1px solid var(--line); }
.adm-price-row:last-child { border-bottom: 0; }
.adm-price-name { flex: 1; min-width: 0; display: grid; }
.adm-price-name strong { font-size: .82rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-price-input { width: 84px; flex: 0 0 auto; text-align: right; font-variant-numeric: tabular-nums; }
.adm-price-on { flex: 0 0 auto; display: grid; place-items: center; width: 28px; }
.adm-pack-row { display: flex; align-items: flex-end; gap: 8px; padding: 8px 0;
  border-bottom: 1px solid var(--line); }
.adm-pack-row:last-of-type { border-bottom: 0; }
.adm-pack-row label { display: grid; gap: 2px; flex: 1; min-width: 0; }
.adm-pack-id { flex: 0 0 28px; font-size: .72rem; color: var(--muted); padding-bottom: 9px; }

/* ── Gift entry points ────────────────────────────────────── */
.chat-gift { color: var(--amber); }
.reel-rail-btn .icon { pointer-events: none; }
.bubble-gift .gift-bubble { background: transparent; border-color: rgba(255,255,255,.18); }

/* ── Balance bar (Watch → Live and Watch → Zall Clips) ────────
   Sits above the content, not over it — the reel viewport is a flex
   child of .watch-body, so an in-flow bar shortens it rather than
   covering the video. */
.gift-balance-bar { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 8px 12px; background: var(--panel); border-bottom: 1px solid var(--line); }
.gbb-coins { display: inline-flex; align-items: center; gap: 6px; background: var(--panel-2);
  border: 1px solid var(--line); border-radius: 999px; padding: 5px 12px; color: var(--text); }
.gbb-coins strong { font-variant-numeric: tabular-nums; }
.gbb-gift { display: inline-flex; align-items: center; gap: 4px; }
.watch-reels-host { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.watch-gift-note { text-align: center; padding: 8px 20px 0; }
.gift-gallery-note { padding: 0 4px 8px; }

/* ── Coin balance on the account-center Wallet tile ───────────
   Empty until the first wallet snapshot lands, so a loading state never
   looks like a balance of zero. */
.quick-tile { position: relative; }
.qt-balance { position: absolute; top: 6px; right: 8px; font-size: .66rem; font-weight: 700;
  color: var(--amber); font-variant-numeric: tabular-nums; opacity: 0; transition: opacity var(--dur-med); }
.qt-balance.on { opacity: 1; }

/* ── Sound marker on gifts that have one ─────────────────── */
.gift-cell { position: relative; }
.gift-has-sound { position: absolute; top: 5px; right: 6px; color: var(--muted);
  display: inline-flex; opacity: .75; }
.gift-has-sound .icon { width: 12px; height: 12px; }
.gift-cell[data-tier="4"] .gift-has-sound,
.gift-cell[data-tier="5"] .gift-has-sound { color: var(--amber); opacity: 1; }

/* ── Gifting level badge ──────────────────────────────────────
   Sits after the verified and Plus badges, so the order of status
   marks next to a name is always the same: verified, Plus, then
   gifting level. Small enough to read as an accent rather than
   competing with the name itself. */
.sender-badge { display: inline-flex; align-items: center; gap: 2px; vertical-align: middle;
  margin-left: 4px; padding: 1px 5px 1px 3px; border-radius: 999px;
  font-size: .62rem; font-weight: 800; line-height: 1.4; font-variant-numeric: tabular-nums;
  border: 1px solid transparent; }
.sender-badge svg { width: 9px; height: 9px; fill: currentColor; }
.sl-bronze { background: rgba(196,124,60,.18); color: #d08a45; border-color: rgba(196,124,60,.4); }
.sl-silver { background: rgba(176,186,205,.18); color: #b6c0d2; border-color: rgba(176,186,205,.42); }
.sl-gold   { background: rgba(246,181,69,.18); color: var(--amber); border-color: rgba(246,181,69,.45); }
.sl-violet { background: rgba(124,92,255,.20); color: #a98cff; border-color: rgba(124,92,255,.5); }
/* Top tier gets movement — it should be rare enough that it never
   becomes visual noise. */
.sl-legend { background: var(--grad); color: #fff; border-color: transparent;
  box-shadow: 0 0 10px rgba(124,92,255,.5); animation: sl-glow 2.6s ease-in-out infinite; }
@keyframes sl-glow { 0%,100% { box-shadow: 0 0 8px rgba(124,92,255,.4) } 50% { box-shadow: 0 0 16px rgba(34,199,224,.6) } }
@media (prefers-reduced-motion: reduce) { .sl-legend { animation: none; } }

/* ── Bond level on the gift picker ───────────────────────── */
.gift-bond { display: flex; align-items: center; gap: 8px; padding: 8px 10px; margin-bottom: 8px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.gift-bond-lvl { display: grid; place-items: center; width: 30px; height: 30px; flex: 0 0 auto;
  border-radius: 50%; background: var(--grad); color: #fff; font-weight: 800; font-size: .76rem; }
.gift-bond-mid { flex: 1; min-width: 0; }
.gift-bond-bar { height: 4px; border-radius: 999px; background: var(--panel-3); overflow: hidden; margin-top: 4px; }
.gift-bond-fill { height: 100%; background: var(--grad); border-radius: 999px; }

/* ── Creator share note in the picker ────────────────────── */
.gift-split-note { font-size: .68rem; color: var(--muted-2); text-align: center; padding: 4px 8px 0; }
