import { useState, useEffect, useRef, useCallback } from "react"; import { motion, AnimatePresence, useMotionValue, useTransform } from "framer-motion"; // ─── Card Data ──────────────────────────────────────────────────────────────── const ALL_CARDS = [ { id: 1, rarity: "normal", name: "Scaredy Cat", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f7a204d73c37fb399_spooked.jpg" }, { id: 2, rarity: "shiny", name: "Dangerous", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f123322fe0b5e19f4_predator.jpg" }, { id: 3, rarity: "normal", name: "Photogenic", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83fab4d97bcae3ea33b_grimace.jpeg" }, { id: 4, rarity: "normal", name: "Facebook Savvy", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f17d47cb6632a17ec_medday.jpg" }, { id: 5, rarity: "shiny", name: "Dodgy", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f497a61541d848ac1_mustache.jpeg" }, { id: 6, rarity: "shiny", name: "Oh My", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f900ba6a4157bc5df_poker.jpeg" }, { id: 7, rarity: "normal", name: "Heartbreaker", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f25d072898a281487_heartbreaker.jpeg" }, { id: 8, rarity: "normal", name: "Snazzy", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f1749c81e31e8fc96_dressed.jpeg" }, { id: 9, rarity: "normal", name: "Smart Arse", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83fca118a1530c7ee0b_smartie.jpeg" }, { id: 10, rarity: "normal", name: "Shagger", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f1ba927afe176e6fa_shagger.jpeg" }, { id: 11, rarity: "normal", name: "Send Help", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f6f2f620ef0bfbf4c_hungover.jpg" }, { id: 12, rarity: "normal", name: "Needs Chaperoning", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f9e01aa9976ac3d93_drunk.jpg" }, { id: 13, rarity: "normal", name: "Snow Bunny", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f7a204d73c37fb381_skiing.jpg" }, { id: 14, rarity: "shiny", name: "Suss", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f888faeaac05681bc_underage.jpg" }, { id: 15, rarity: "normal", name: "The Truth", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f9eeef2f4b1c3d661_equal.jpg" }, { id: 16, rarity: "shiny", name: "That Beater Life", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83fbc79b77d4e61d251_beater.jpg" }, { id: 17, rarity: "normal", name: "Politically Minded", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe83f120dfade398223e1_corrupt.jpeg" }, { id: 18, rarity: "shiny", name: "Friends in High Places", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfea90eb4522043cfbc93d_friends.png" }, { id: 19, rarity: "shiny", name: "Values", image: "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfec89fb3c0b997cf02a6a_mcgregor.png" }, ]; const CARD_BACK = "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe8327a2e606cc78afd70_card-back.png"; const FOIL_IMG = "https://cdn.prod.website-files.com/5bf56f3c39236d9c81f57c6a/69cfe833a1095b7fe72d5e23_foil.png"; const STAT_NAMES = [ ["Pint Speed", "Banter Level", "Dad Energy"], ["Stamina", "Chat Ratio", "Snack Power"], ["Rizz", "Regret IQ", "Clout Score"], ["Party Rage", "Smooth Talk", "Night Survival"], ["Side-eye HP", "Chaos Lvl", "Cringe Res"], ]; function getRandStats(id) { const pool = STAT_NAMES[id % STAT_NAMES.length]; return pool.map((name) => ({ name, value: Math.floor(Math.random() * 51) + 50 })); } function getRandCards() { const shuffled = [...ALL_CARDS].sort(() => Math.random() - 0.5); return shuffled.slice(0, 5).map((c) => ({ ...c, stats: getRandStats(c.id) })); } // ─── Confetti ───────────────────────────────────────────────────────────────── function fireConfetti() { const script = document.createElement("script"); script.src = "https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.2/dist/confetti.browser.min.js"; script.onload = () => { window.confetti({ particleCount: 180, spread: 100, origin: { y: 0.5 }, colors: ["#ffd700","#ff6b6b","#4ecdc4","#ffe66d","#a8e6cf","#ff8b94"] }); setTimeout(() => window.confetti({ particleCount: 100, angle: 60, spread: 80, origin: { x: 0 }, colors: ["#ffd700","#ff6b6b","#ffe66d"] }), 200); setTimeout(() => window.confetti({ particleCount: 100, angle: 120, spread: 80, origin: { x: 1 }, colors: ["#4ecdc4","#a8e6cf","#ffd700"] }), 400); }; document.head.appendChild(script); } // ─── Holographic shimmer ────────────────────────────────────────────────────── const HoloOverlay = ({ mouseX, mouseY, cardRef }) => { const [pos, setPos] = useState({ x: 50, y: 50 }); useEffect(() => { if (!cardRef.current) return; const rect = cardRef.current.getBoundingClientRect(); const x = ((mouseX - rect.left) / rect.width) * 100; const y = ((mouseY - rect.top) / rect.height) * 100; setPos({ x: Math.max(0, Math.min(100, x)), y: Math.max(0, Math.min(100, y)) }); }, [mouseX, mouseY, cardRef]); return (
); }; // ─── Pokemon Card ───────────────────────────────────────────────────────────── const PokemonCard = ({ card, isFlipped, onClick, delay, mouseX, mouseY }) => { const cardRef = useRef(null); const motionX = useMotionValue(0); const motionY = useMotionValue(0); const rotateX = useTransform(motionY, [-150, 150], [12, -12]); const rotateY = useTransform(motionX, [-150, 150], [-12, 12]); const handleMouseMove = (e) => { if (!isFlipped || !cardRef.current) return; const rect = cardRef.current.getBoundingClientRect(); motionX.set(e.clientX - rect.left - rect.width / 2); motionY.set(e.clientY - rect.top - rect.height / 2); }; const handleMouseLeave = () => { motionX.set(0); motionY.set(0); }; const typeColors = { normal: { bg: "#f5e6c8", border: "#c8941a", badge: "#e8c56b", text: "#7a4a00" }, shiny: { bg: "#1a1a2e", border: "#ffd700", badge: "#ffd700", text: "#ffd700" }, }; const colors = typeColors[card.rarity]; return ( {/* Back */}
card back
Tap to Reveal
{/* Front */}
{card.rarity === "shiny" && ( <>
)}
{/* Header */}
{card.name.toUpperCase()} {card.rarity === "shiny" ? "✨ SHINY" : "NORMAL"}
{/* Image */}
{card.name} {card.rarity === "shiny" && (
)}
{/* Type tag */}
🎉 STAG ENERGY TYPE
{/* Stats */}
{card.stats.map((stat) => (
{stat.name}
{stat.value}
))}
{/* Footer */}
STAG PACK 2025 • #{String(card.id).padStart(3,"0")}/019
); }; // ─── Pack Tear Animation ────────────────────────────────────────────────────── const PackOpener = ({ onOpen }) => { const [tearing, setTearing] = useState(false); const [done, setDone] = useState(false); const handleTear = () => { if (tearing || done) return; setTearing(true); setTimeout(() => { setDone(true); setTimeout(onOpen, 300); }, 700); }; return (
{/* Title */}

STAG PACK

BACHELOR EDITION

{/* Pack */}
{!done && ( <> {/* Left half */} foil left {/* Right half */} foil right {/* Tear line glow */} )} {/* Pulse ring behind pack */} {!tearing && ( )}
{/* CTA */} {!tearing && ( TEAR OPEN )}
); }; // ─── Cards Screen ───────────────────────────────────────────────────────────── const CardsScreen = ({ cards, onReset }) => { const [flipped, setFlipped] = useState(new Set()); const [mousePos, setMousePos] = useState({ x: 0, y: 0 }); const confettiFired = useRef(false); const handleMouseMove = useCallback((e) => { setMousePos({ x: e.clientX, y: e.clientY }); }, []); // Gyroscope on mobile useEffect(() => { const handler = (e) => { setMousePos({ x: window.innerWidth / 2 + (e.gamma || 0) * 8, y: window.innerHeight / 2 + (e.beta || 0) * 8, }); }; window.addEventListener("deviceorientation", handler); return () => window.removeEventListener("deviceorientation", handler); }, []); const handleFlip = (id) => { const newFlipped = new Set(flipped); newFlipped.add(id); setFlipped(newFlipped); if (newFlipped.size === 5 && !confettiFired.current) { confettiFired.current = true; setTimeout(fireConfetti, 300); } }; return (
{/* Header */}

YOUR PACK

{flipped.size}/5 REVEALED

{/* Progress bar */}
{/* Cards grid */}
{/* Row 1: 3 cards */}
{cards.slice(0, 3).map((card, i) => ( handleFlip(card.id)} delay={i * 0.12} mouseX={mousePos.x} mouseY={mousePos.y} /> ))}
{/* Row 2: 2 cards */}
{cards.slice(3, 5).map((card, i) => ( handleFlip(card.id)} delay={(i + 3) * 0.12} mouseX={mousePos.x} mouseY={mousePos.y} /> ))}
{/* All revealed celebration */} {flipped.size === 5 && ( 🎉 LADS LADS LADS 🎉 )}
); }; // ─── App ────────────────────────────────────────────────────────────────────── export default function App() { const [phase, setPhase] = useState("pack"); // "pack" | "cards" const [cards, setCards] = useState([]); const handleOpen = () => { setCards(getRandCards()); setPhase("cards"); }; const handleReset = () => { setPhase("pack"); setCards([]); }; return (
{phase === "pack" ? ( ) : ( )}
); }