import { useState, useEffect, useRef } from "react";
import type { QuestNode, ClaimedRewardResponse } from "../types/quest";

// ─── Styles ───────────────────────────────────────────────────────────────────
const S = `
  @import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@700;900&family=Nunito:wght@800;900&display=swap');

  /* ══ FULL SCREEN OVERLAY ══ */
  .com-overlay {
    position:fixed; inset:0; z-index:80;
    display:flex; flex-direction:column;
    align-items:center; justify-content:center;
    overflow:hidden;
  }

  /* ── Sky/sea background that animates in ── */
  .com-bg {
    position:absolute; inset:0;
    background:
      radial-gradient(ellipse 80% 60% at 50% 80%, rgba(0,60,120,0.9) 0%, transparent 70%),
      radial-gradient(ellipse 60% 40% at 50% 20%, rgba(80,0,160,0.7) 0%, transparent 60%),
      linear-gradient(180deg, #050010 0%, #0a0520 40%, #020818 100%);
    animation: comBgIn 0.5s ease both;
  }
  @keyframes comBgIn {
    from{ opacity:0; } to{ opacity:1; }
  }

  /* ── Stars in background ── */
  .com-star {
    position:absolute; border-radius:50%;
    background:white; pointer-events:none;
    animation:comStarTwinkle var(--sdur) ease-in-out infinite;
    animation-delay:var(--sdelay);
  }
  @keyframes comStarTwinkle {
    0%,100%{ opacity:0.3; transform:scale(1); }
    50%    { opacity:1;   transform:scale(1.4); }
  }

  /* ── Gold radial burst (appears on open) ── */
  .com-burst {
    position:absolute; inset:0;
    display:flex; align-items:center; justify-content:center;
    pointer-events:none; z-index:2;
  }
  .com-burst-ring {
    position:absolute; border-radius:50%;
    border:3px solid rgba(251,191,36,0.6);
    animation: comBurstRing var(--brdur) ease-out forwards;
    animation-delay: var(--brdelay);
    opacity:0;
  }
  @keyframes comBurstRing {
    0%  { opacity:0.9; transform:scale(0.1); }
    100%{ opacity:0;   transform:scale(var(--brs)); }
  }

  /* ── Ray beams (crepuscular rays) ── */
  .com-rays {
    position:absolute; inset:0;
    display:flex; align-items:center; justify-content:center;
    pointer-events:none; z-index:1;
  }
  .com-ray {
    position:absolute;
    width:3px;
    height:55vh;
    border-radius:100px;
    background:linear-gradient(180deg,rgba(251,191,36,0.5) 0%,transparent 100%);
    transform-origin:50% 100%;
    bottom:50%;
    left:calc(50% - 1.5px);
    transform:rotate(var(--angle)) scaleY(0);
    animation:comRayIn 0.6s ease-out forwards;
    animation-delay:var(--raydelay);
  }
  @keyframes comRayIn {
    0%  { transform:rotate(var(--angle)) scaleY(0);   opacity:0; }
    40% { opacity:0.8; }
    100%{ transform:rotate(var(--angle)) scaleY(1);   opacity:0.15; }
  }

  /* ── Particle explosion ── */
  .com-particle {
    position:absolute; border-radius:50%;
    pointer-events:none; z-index:4;
    animation:comParticleOut var(--pdur) cubic-bezier(0.25,0.8,0.35,1) forwards;
    animation-delay:var(--pdelay);
    opacity:0;
  }
  @keyframes comParticleOut {
    0%  { opacity:1; transform:translate(0,0) scale(1) rotate(0deg); }
    80% { opacity:0.7; }
    100%{ opacity:0; transform:translate(var(--ptx),var(--pty)) scale(0.2) rotate(var(--prot)); }
  }

  /* ── Coin emojis bursting ── */
  .com-coin {
    position:absolute;
    font-size:var(--csize);
    pointer-events:none; z-index:4;
    animation:comCoinOut var(--cdur) cubic-bezier(0.2,0.9,0.3,1) forwards;
    animation-delay:var(--cdelay);
    opacity:0;
  }
  @keyframes comCoinOut {
    0%  { opacity:0; transform:translate(0,0) rotate(0deg) scale(0.3); }
    12% { opacity:1; }
    100%{ opacity:0; transform:translate(var(--ctx),var(--cty)) rotate(var(--crot)) scale(1.1); }
  }

  /* ── Floating sparkles (stay on screen) ── */
  .com-sparkle {
    position:absolute; pointer-events:none; z-index:3;
    font-size:var(--spsize);
    animation:comSparkleFloat var(--spdur) ease-in-out infinite;
    animation-delay:var(--spdelay);
    opacity:0.7;
  }
  @keyframes comSparkleFloat {
    0%,100%{ transform:translateY(0) rotate(0deg) scale(1);    opacity:0.6; }
    50%    { transform:translateY(-18px) rotate(180deg) scale(1.2); opacity:1; }
  }

  /* ── XP number that flies up from chest ── */
  .com-xp-blast {
    position:absolute; pointer-events:none; z-index:5;
    top:50%; left:50%;
    font-family:'Cinzel',serif;
    font-size:2.6rem; font-weight:900;
    color:#fbbf24;
    text-shadow:0 0 30px rgba(251,191,36,1),0 0 60px rgba(251,191,36,0.7),0 0 100px rgba(251,191,36,0.3);
    white-space:nowrap;
    animation:comXPBlast 2s cubic-bezier(0.2,0.8,0.3,1) forwards;
  }
  @keyframes comXPBlast {
    0%  { opacity:0; transform:translate(-50%,-40%) scale(0.4); filter:blur(4px); }
    15% { opacity:1; transform:translate(-50%,-60%) scale(1.3); filter:blur(0); }
    60% { opacity:1; transform:translate(-50%,-90%) scale(1);   }
    100%{ opacity:0; transform:translate(-50%,-130%) scale(0.8); }
  }

  /* ── Main card ── */
  .com-card {
    position:relative; z-index:6;
    width:calc(100% - 2.5rem); max-width:340px;
    border-radius:28px; overflow:hidden;
    display:flex; flex-direction:column; align-items:center;
    padding:0;
    box-shadow:0 0 80px rgba(251,191,36,0.2), 0 24px 64px rgba(0,0,0,0.7);
    animation:comCardIn 0.5s cubic-bezier(0.34,1.56,0.64,1) both;
    animation-delay:0.1s;
  }
  @keyframes comCardIn {
    from{ opacity:0; transform:scale(0.8) translateY(24px); }
    to  { opacity:1; transform:scale(1)   translateY(0);    }
  }

  /* Gold shimmer top border */
  .com-card::before {
    content:''; position:absolute; top:0; left:0; right:0; height:2px; z-index:1;
    background:linear-gradient(90deg,transparent 0%,#f59e0b 30%,#fbbf24 50%,#f59e0b 70%,transparent 100%);
    background-size:200% 100%;
    animation:comShimmer 2s linear infinite;
  }
  @keyframes comShimmer {
    0%  { background-position:200% 0; }
    100%{ background-position:-200% 0; }
  }

  /* Card inner bg */
  .com-card-inner {
    width:100%; padding:1.75rem 1.6rem 1.6rem;
    background:linear-gradient(160deg,#12083a 0%,#0c0525 60%,#090320 100%);
    border:1.5px solid rgba(251,191,36,0.25);
    border-radius:28px;
    display:flex; flex-direction:column; align-items:center; gap:0;
  }

  /* ── Phase label ── */
  .com-label {
    font-family:'Cinzel',serif;
    font-size:0.62rem; font-weight:700; letter-spacing:0.2em;
    text-transform:uppercase; color:rgba(251,191,36,0.55);
    margin-bottom:1.2rem; text-align:center;
  }

  /* ── Chest area ── */
  .com-chest-area {
    position:relative; width:140px; height:140px;
    display:flex; align-items:center; justify-content:center;
    margin-bottom:1.25rem; cursor:pointer;
  }

  /* Glow platform beneath chest */
  .com-glow-pad {
    position:absolute; bottom:6px; left:50%;
    transform:translateX(-50%);
    width:100px; height:24px; border-radius:50%;
    background:radial-gradient(ellipse at center,rgba(251,191,36,0.45) 0%,transparent 70%);
    animation:comGlowPad 1.8s ease-in-out infinite;
    filter:blur(4px);
  }
  @keyframes comGlowPad {
    0%,100%{ transform:translateX(-50%) scaleX(1);   opacity:0.7; }
    50%    { transform:translateX(-50%) scaleX(1.2); opacity:1; }
  }

  /* Orbit ring */
  .com-orbit {
    position:absolute; inset:8px; border-radius:50%;
    border:1.5px dashed rgba(251,191,36,0.2);
    animation:comOrbit 8s linear infinite;
  }
  @keyframes comOrbit { from{transform:rotate(0deg);} to{transform:rotate(360deg);} }
  .com-orbit-dot {
    position:absolute; top:-5px; left:50%; transform:translateX(-50%);
    width:8px; height:8px; border-radius:50%;
    background:#fbbf24; box-shadow:0 0 10px #fbbf24;
  }

  /* The chest emoji */
  .com-chest {
    font-size:5.5rem; position:relative; z-index:2;
    filter:drop-shadow(0 8px 20px rgba(251,191,36,0.45));
    transition:filter 0.2s;
  }
  .com-chest.idle {
    animation:comChestIdle 3s ease-in-out infinite;
  }
  @keyframes comChestIdle {
    0%,100%{ transform:translateY(0) rotate(-2deg); }
    50%    { transform:translateY(-6px) rotate(2deg); }
  }
  .com-chest.shake {
    animation:comChestShake 0.55s cubic-bezier(0.36,0.07,0.19,0.97) both;
  }
  @keyframes comChestShake {
    0%,100%{ transform:rotate(0deg) scale(1);     }
    10%    { transform:rotate(-14deg) scale(1.06); }
    25%    { transform:rotate(14deg) scale(1.1);  }
    40%    { transform:rotate(-10deg) scale(1.07); }
    55%    { transform:rotate(10deg) scale(1.12);  }
    70%    { transform:rotate(-6deg) scale(1.06);  }
    85%    { transform:rotate(6deg) scale(1.04);   }
  }
  .com-chest.opening {
    animation:comChestOpen 0.5s cubic-bezier(0.34,1.56,0.64,1) both;
  }
  @keyframes comChestOpen {
    0%  { transform:scale(0.7);  filter:brightness(0.4) drop-shadow(0 8px 20px rgba(251,191,36,0.3)); }
    50% { transform:scale(1.25); filter:brightness(1.8) drop-shadow(0 0 50px rgba(251,191,36,1)); }
    100%{ transform:scale(1);    filter:brightness(1)   drop-shadow(0 8px 30px rgba(251,191,36,0.6)); }
  }

  /* ── Tap prompt ── */
  .com-tap-title {
    font-family:'Cinzel',serif;
    font-size:1.2rem; font-weight:900; color:white;
    text-align:center; margin-bottom:0.3rem;
    animation:comPulse 1.8s ease-in-out infinite;
  }
  @keyframes comPulse {
    0%,100%{ opacity:1; transform:scale(1); }
    50%    { opacity:0.65; transform:scale(0.97); }
  }
  .com-tap-sub {
    font-family:'Nunito',sans-serif;
    font-size:0.75rem; font-weight:800;
    color:rgba(255,255,255,0.35); text-align:center; margin-bottom:1.5rem;
    letter-spacing:0.06em;
  }

  /* ── Shaking text ── */
  .com-shake-text {
    font-family:'Cinzel',serif;
    font-size:1.1rem; font-weight:900; color:#fbbf24;
    text-align:center; margin-bottom:0.3rem;
    animation:comShakeText 0.3s ease-in-out infinite alternate;
  }
  @keyframes comShakeText {
    from{ transform:translateX(-3px); }
    to  { transform:translateX(3px); }
  }
  .com-shake-dots {
    font-size:1.4rem; text-align:center; margin-bottom:1.5rem;
    animation:comShakeText 0.25s ease-in-out infinite alternate;
  }

  /* ── Reward rows ── */
  .com-rewards-title {
    font-family:'Cinzel',serif;
    font-size:0.65rem; font-weight:700; letter-spacing:0.18em;
    text-transform:uppercase; color:rgba(251,191,36,0.5);
    text-align:center; margin-bottom:0.85rem;
  }
  .com-rewards { display:flex; flex-direction:column; gap:0.55rem; width:100%; margin-bottom:1.1rem; }
  .com-reward-row {
    display:flex; align-items:center; gap:0.85rem;
    padding:0.8rem 1rem;
    background:rgba(255,255,255,0.04);
    border:1px solid rgba(251,191,36,0.18);
    border-radius:16px;
    animation:comRowIn 0.5s cubic-bezier(0.34,1.56,0.64,1) both;
  }
  @keyframes comRowIn {
    from{ opacity:0; transform:translateY(18px) scale(0.88); }
    to  { opacity:1; transform:translateY(0) scale(1); }
  }
  .com-reward-icon { font-size:1.5rem; flex-shrink:0; filter:drop-shadow(0 2px 8px rgba(251,191,36,0.5)); }
  .com-reward-lbl {
    font-family:'Cinzel',serif;
    font-size:0.65rem; font-weight:700; letter-spacing:0.1em; text-transform:uppercase;
    color:rgba(255,255,255,0.4); margin-bottom:0.12rem;
  }
  .com-reward-val {
    font-family:'Nunito',sans-serif;
    font-size:1.05rem; font-weight:900;
    color:#fbbf24;
    text-shadow:0 0 16px rgba(251,191,36,0.6);
  }

  /* Special XP row highlight */
  .com-reward-row.xp-row {
    border-color:rgba(251,191,36,0.35);
    background:rgba(251,191,36,0.06);
  }

  /* Loading state inside reward area */
  .com-rewards-loading {
    font-family:'Cinzel',serif;
    font-size:0.72rem; font-weight:700; color:rgba(251,191,36,0.4);
    text-align:center; padding:1rem 0; letter-spacing:0.1em;
    animation:comPulse 1.2s ease-in-out infinite;
  }

  /* ── CTA button ── */
  .com-cta {
    width:100%; padding:1rem;
    background:linear-gradient(135deg,#fbbf24,#f59e0b);
    border:none; border-radius:16px; cursor:pointer;
    font-family:'Cinzel',serif;
    font-size:1rem; font-weight:900; color:#1a0800;
    letter-spacing:0.05em;
    box-shadow:0 5px 0 #b45309, 0 8px 24px rgba(251,191,36,0.4);
    transition:all 0.12s ease;
    animation:comRowIn 0.5s cubic-bezier(0.34,1.56,0.64,1) both;
  }
  .com-cta:hover  { transform:translateY(-3px); box-shadow:0 8px 0 #b45309, 0 14px 32px rgba(251,191,36,0.5); }
  .com-cta:active { transform:translateY(2px);  box-shadow:0 3px 0 #b45309; }

  /* ── Skip hint ── */
  .com-skip {
    position:absolute; bottom:1.5rem;
    font-family:'Nunito',sans-serif;
    font-size:0.65rem; font-weight:700;
    color:rgba(255,255,255,0.2); letter-spacing:0.1em;
    text-transform:uppercase; cursor:pointer; z-index:7;
    transition:color 0.2s;
  }
  .com-skip:hover { color:rgba(255,255,255,0.5); }
`;

// ─── Config ───────────────────────────────────────────────────────────────────
const PARTICLE_COLORS = [
  "#fbbf24",
  "#f59e0b",
  "#ef4444",
  "#ec4899",
  "#a855f7",
  "#6366f1",
  "#22d3ee",
  "#4ade80",
  "#fb923c",
];
const COIN_EMOJIS = ["🪙", "💰", "✨", "⭐", "💎", "🌟", "💫", "🏅"];
const SPARKLE_EMOJIS = ["✨", "⭐", "💫", "🌟"];

const RAYS = Array.from({ length: 12 }, (_, i) => ({
  id: i,
  angle: `${(i / 12) * 360}deg`,
  delay: `${i * 0.04}s`,
}));

const BURST_RINGS = [
  { id: 0, size: "3", dur: "0.7s", delay: "0s" },
  { id: 1, size: "5", dur: "0.9s", delay: "0.1s" },
  { id: 2, size: "8", dur: "1.1s", delay: "0.2s" },
  { id: 3, size: "12", dur: "1.4s", delay: "0.3s" },
];

const STARS = Array.from({ length: 40 }, (_, i) => ({
  id: i,
  w: 1 + ((i * 7) % 3),
  top: `${(i * 17 + 3) % 95}%`,
  left: `${(i * 23 + 11) % 97}%`,
  dur: `${2 + ((i * 3) % 4)}s`,
  delay: `${(i * 7) % 3}s`,
}));

const SPARKLES = Array.from({ length: 8 }, (_, i) => ({
  id: i,
  emoji: SPARKLE_EMOJIS[i % 4],
  size: `${0.9 + (i % 3) * 0.35}rem`,
  top: `${10 + ((i * 12) % 75)}%`,
  left: `${5 + ((i * 14) % 85)}%`,
  dur: `${2 + (i % 3) * 1.2}s`,
  delay: `${i * 0.3}s`,
}));

type Phase = "idle" | "shaking" | "opening" | "revealed";

interface Props {
  node: QuestNode;
  claimResult: ClaimedRewardResponse | null;
  onClose: () => void;
}

export const ChestOpenModal = ({ node, claimResult, onClose }: Props) => {
  const [phase, setPhase] = useState<Phase>("idle");
  const [showXP, setShowXP] = useState(false);
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Stable particle arrays computed once per mount
  const particles = useRef(
    Array.from({ length: 55 }, (_, i) => ({
      id: i,
      color: PARTICLE_COLORS[i % PARTICLE_COLORS.length],
      w: 3 + (i % 3) * 4,
      tx: ((i % 2 === 0 ? 1 : -1) * (40 + i * 7)) % 200,
      ty: -(30 + ((i * 11) % 190)),
      rot: ((i * 23) % 720) - 360,
      dur: `${0.7 + ((i * 7) % 10) / 10}s`,
      delay: `${((i * 3) % 8) / 30}s`,
    })),
  ).current;

  const coins = useRef(
    Array.from({ length: 18 }, (_, i) => ({
      id: i,
      emoji: COIN_EMOJIS[i % COIN_EMOJIS.length],
      size: `${1 + (i % 3) * 0.45}rem`,
      tx: (i % 2 === 0 ? 1 : -1) * (30 + ((i * 9) % 180)),
      ty: -(40 + ((i * 13) % 200)),
      rot: ((i * 31) % 540) - 270,
      dur: `${0.75 + ((i * 7) % 8) / 10}s`,
      delay: `${((i * 5) % 10) / 30}s`,
    })),
  ).current;

  const tap = () => {
    if (phase !== "idle") return;
    setPhase("shaking");
    timerRef.current = setTimeout(() => {
      setPhase("opening");
      setShowXP(true);
      timerRef.current = setTimeout(() => {
        setShowXP(false);
        setPhase("revealed");
      }, 1800);
    }, 650);
  };

  useEffect(
    () => () => {
      if (timerRef.current) clearTimeout(timerRef.current);
    },
    [],
  );

  // ── Build reward rows from ClaimedRewardResponse ──────────────────────────
  // claimResult may be null while the API call is in flight; we show a loading
  // state in that case rather than crashing or showing stale data.
  const xpAwarded = claimResult?.xp_awarded ?? 0;

  // Defensively coerce to arrays — the API may return null, a single object,
  // or omit these fields entirely rather than returning an empty array.
  const titlesAwarded = Array.isArray(claimResult?.title_unlocked)
    ? claimResult!.title_unlocked
    : claimResult?.title_unlocked
      ? [claimResult.title_unlocked]
      : [];
  const itemsAwarded = Array.isArray(claimResult?.items_awarded)
    ? claimResult!.items_awarded
    : claimResult?.items_awarded
      ? [claimResult.items_awarded]
      : [];

  const rewards = claimResult
    ? [
        // XP row — always present
        {
          key: "xp",
          cls: "xp-row",
          icon: "⚡",
          lbl: "XP Gained",
          val: `+${xpAwarded} XP`,
          delay: "0.05s",
        },
        // One row per unlocked title (usually 0 or 1)
        ...titlesAwarded.map((t, i) => ({
          key: `title-${t.id}`,
          cls: "",
          icon: "🏴‍☠️",
          lbl: "Crew Title",
          val: t.name,
          delay: `${0.1 + i * 0.1}s`,
        })),
        // One row per awarded item
        ...itemsAwarded.map((inv, i) => ({
          key: `item-${inv.id}`,
          cls: "",
          icon: "🎁",
          lbl: inv.item.type ?? "Item",
          val: inv.item.name,
          delay: `${0.1 + (titlesAwarded.length + i) * 0.1}s`,
        })),
      ]
    : [];

  const chestClass =
    phase === "idle"
      ? "idle"
      : phase === "shaking"
        ? "shake"
        : phase === "opening"
          ? "opening"
          : "";
  const chestEmoji = phase === "opening" || phase === "revealed" ? "📬" : "📦";

  return (
    <div className="com-overlay" onClick={phase === "idle" ? tap : undefined}>
      <style>{S}</style>

      {/* Background */}
      <div className="com-bg" />

      {/* Stars */}
      {STARS.map((s) => (
        <div
          key={s.id}
          className="com-star"
          style={
            {
              width: s.w,
              height: s.w,
              top: s.top,
              left: s.left,
              "--sdur": s.dur,
              "--sdelay": s.delay,
            } as React.CSSProperties
          }
        />
      ))}

      {/* Crepuscular rays */}
      {(phase === "opening" || phase === "revealed") && (
        <div className="com-rays">
          {RAYS.map((r) => (
            <div
              key={r.id}
              className="com-ray"
              style={
                {
                  "--angle": r.angle,
                  "--raydelay": r.delay,
                } as React.CSSProperties
              }
            />
          ))}
        </div>
      )}

      {/* Burst rings */}
      {(phase === "opening" || phase === "revealed") && (
        <div className="com-burst">
          {BURST_RINGS.map((r) => (
            <div
              key={r.id}
              className="com-burst-ring"
              style={
                {
                  width: "100px",
                  height: "100px",
                  "--brs": r.size,
                  "--brdur": r.dur,
                  "--brdelay": r.delay,
                } as React.CSSProperties
              }
            />
          ))}
        </div>
      )}

      {/* Particle explosion */}
      {(phase === "opening" || phase === "revealed") && (
        <>
          {particles.map((p) => (
            <div
              key={p.id}
              className="com-particle"
              style={
                {
                  width: p.w,
                  height: p.w,
                  background: p.color,
                  top: "50%",
                  left: "50%",
                  "--ptx": `${p.tx}px`,
                  "--pty": `${p.ty}px`,
                  "--prot": `${p.rot}deg`,
                  "--pdur": p.dur,
                  "--pdelay": p.delay,
                } as React.CSSProperties
              }
            />
          ))}
          {coins.map((c) => (
            <div
              key={c.id}
              className="com-coin"
              style={
                {
                  top: "50%",
                  left: "50%",
                  "--csize": c.size,
                  "--ctx": `${c.tx}px`,
                  "--cty": `${c.ty}px`,
                  "--crot": `${c.rot}deg`,
                  "--cdur": c.dur,
                  "--cdelay": c.delay,
                } as React.CSSProperties
              }
            >
              {c.emoji}
            </div>
          ))}
        </>
      )}

      {/* Floating sparkles in revealed state */}
      {phase === "revealed" &&
        SPARKLES.map((sp) => (
          <div
            key={sp.id}
            className="com-sparkle"
            style={
              {
                top: sp.top,
                left: sp.left,
                "--spsize": sp.size,
                "--spdur": sp.dur,
                "--spdelay": sp.delay,
              } as React.CSSProperties
            }
          >
            {sp.emoji}
          </div>
        ))}

      {/* XP blast — uses xp_awarded from claimResult */}
      {showXP && (
        <div className="com-xp-blast">
          {xpAwarded > 0 ? `+${xpAwarded} XP` : "✨"}
        </div>
      )}

      {/* Card */}
      <div className="com-card" onClick={(e) => e.stopPropagation()}>
        <div className="com-card-inner">
          <p className="com-label">
            {phase === "revealed" ? "⚓ Treasure Claimed" : "📦 Treasure Chest"}
          </p>

          {/* Chest */}
          <div
            className="com-chest-area"
            onClick={phase === "idle" ? tap : undefined}
            style={{ cursor: phase === "idle" ? "pointer" : "default" }}
          >
            {phase !== "revealed" && <div className="com-glow-pad" />}
            {phase !== "revealed" && (
              <div className="com-orbit">
                <div className="com-orbit-dot" />
              </div>
            )}
            <span className={`com-chest ${chestClass}`}>{chestEmoji}</span>
          </div>

          {/* Phase content */}
          {phase === "idle" && (
            <>
              <p className="com-tap-title">Tap to Open!</p>
              <p className="com-tap-sub">YOUR HARD WORK HAS PAID OFF, PIRATE</p>
            </>
          )}

          {phase === "shaking" && (
            <>
              <p className="com-shake-text">The chest stirs...</p>
              <p className="com-shake-dots">⚡ ⚡ ⚡</p>
            </>
          )}

          {phase === "revealed" && (
            <>
              <p className="com-rewards-title">⚓ Spoils of Victory</p>
              <div className="com-rewards">
                {/* claimResult not yet available — API still in flight */}
                {!claimResult && (
                  <p className="com-rewards-loading">
                    ⚡ Counting your spoils...
                  </p>
                )}
                {rewards.map((r) => (
                  <div
                    key={r.key}
                    className={`com-reward-row ${r.cls}`}
                    style={{ animationDelay: r.delay }}
                  >
                    <span className="com-reward-icon">{r.icon}</span>
                    <div>
                      <p className="com-reward-lbl">{r.lbl}</p>
                      <p className="com-reward-val">{r.val}</p>
                    </div>
                  </div>
                ))}
              </div>
              <button
                className="com-cta"
                style={{ animationDelay: `${rewards.length * 0.1}s` }}
                onClick={onClose}
              >
                ⚓ Set Sail
              </button>
            </>
          )}
        </div>
      </div>

      {/* Skip link */}
      {phase === "revealed" && (
        <p className="com-skip" onClick={onClose}>
          tap anywhere to continue
        </p>
      )}
    </div>
  );
};
