← back to Model Arena
data/artifacts/0ddb58a78233/qwen3-14b.html
408 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HoloCard Arena</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #111;
color: #eee;
overflow: hidden;
}
.container {
display: flex;
height: 100%;
width: 100%;
flex-direction: column;
}
.header {
background: #222;
padding: 1rem;
text-align: center;
font-size: 1.5rem;
color: #fff;
box-shadow: 0 2px 5px rgba(0,0,0,0.5);
}
.card-container {
flex-grow: 1;
position: relative;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
perspective: 1000px;
}
.card {
width: 300px;
height: 450px;
background: #222;
border-radius: 16px;
box-shadow: 0 0 30px rgba(255,255,255,0.2);
position: relative;
cursor: pointer;
transform-style: preserve-3d;
transition: transform 0.2s ease-out, box-shadow 0.3s ease;
user-select: none;
}
.card:hover {
transform: rotateX(5deg) rotateY(5deg);
box-shadow: 0 0 50px rgba(255,255,255,0.3);
}
.card:focus {
outline: none;
box-shadow: 0 0 30px rgba(0,255,255,0.6);
}
.face {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 16px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 20px;
box-sizing: border-box;
transform: rotateY(0deg);
background: linear-gradient(135deg, #000, #111);
color: #fff;
font-weight: bold;
text-shadow: 0 0 10px rgba(255,255,255,0.3);
}
.backface {
transform: rotateY(180deg);
}
.front .name {
font-size: 1.5rem;
margin-bottom: 10px;
}
.stats {
font-size: 0.9rem;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 10px;
width: 100%;
margin-top: 20px;
}
.stat {
background: #333;
padding: 8px;
border-radius: 8px;
text-align: center;
font-weight: bold;
}
.flip {
transform: rotateY(180deg);
}
.head-to-head {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10;
text-align: center;
padding: 2rem;
background: rgba(0,0,0,0.5);
border-radius: 16px;
font-size: 1.5rem;
color: #fff;
display: none;
justify-content: center;
align-items: center;
min-width: 250px;
min-height: 120px;
box-shadow: 0 0 30px rgba(255,255,255,0.2);
}
.head-to-head.show {
display: flex;
}
.nav {
display: flex;
justify-content: center;
gap: 1rem;
padding: 1rem;
background: #111;
border-top: 1px solid #333;
font-size: 0.9rem;
}
.nav button {
background: #222;
color: #fff;
border: none;
padding: 0.4rem 0.8rem;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
}
.nav button:hover {
background: #333;
}
.nav button:focus {
outline: none;
box-shadow: 0 0 10px rgba(0,255,255,0.6);
}
.error {
color: #f00;
font-size: 0.8rem;
margin-top: 0.5rem;
}
.empty-state {
font-size: 1rem;
text-align: center;
color: #888;
padding: 2rem;
}
.card[data-empty] {
opacity: 0.5;
}
@media (max-width: 768px) {
.card {
width: 250px;
height: 380px;
}
}
@media (prefers-reduced-motion: no-preference) {
.card:hover {
animation: pulse 1s infinite alternate;
}
@keyframes pulse {
from { transform: rotateX(0deg) rotateY(0deg); }
to { transform: rotateX(4deg) rotateY(4deg); }
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">HoloCard Arena</div>
<div class="card-container">
<div class="card" id="card1" data-empty>
<div class="face front" tabindex="0">
<div class="name">Tal Vex</div>
<div class="stats">
<div class="stat">Speed: 92</div>
<div class="stat">Endurance: 78</div>
<div class="stat">Precision: 89</div>
<div class="stat">Agility: 94</div>
</div>
<div class="error" id="error1"></div>
</div>
<div class="face backface" tabindex="0">
<div class="name">Radar Stats</div>
<div class="stats">
<div class="stat">Power: 84</div>
<div class="stat">Vision: 91</div>
<div class="stat">Tactics: 87</div>
<div class="stat">Reaction: 85</div>
</div>
</div>
</div>
<div class="card" id="card2" data-empty>
<div class="face front" tabindex="0">
<div class="name">Zyla Korr</div>
<div class="stats">
<div class="stat">Speed: 86</div>
<div class="stat">Endurance: 82</div>
<div class="stat">Precision: 88</div>
<div class="stat">Agility: 90</div>
</div>
<div class="error" id="error2"></div>
</div>
<div class="face backface" tabindex="0">
<div class="name">Radar Stats</div>
<div class="stats">
<div class="stat">Power: 88</div>
<div class="stat">Vision: 89</div>
<div class="stat">Tactics: 85</div>
<div class="stat">Reaction: 92</div>
</div>
</div>
</div>
</div>
<div class="head-to-head" id="head-to-head">
<span id="winner"></span>
</div>
<div class="nav">
<button id="flip-button">Flip Card</button>
<button id="head-to-head-button">Head-to-Head</button>
<button id="clear-button">Clear Cards</button>
</div>
<div class="empty-state" id="empty-state">
No athletes selected. Click on a card or use buttons above.
</div>
</div>
<script>
const card1 = document.getElementById("card1");
const card2 = document.getElementById("card2");
const headToHead = document.getElementById("head-to-head");
const winnerDisplay = document.getElementById("winner");
const flipButton = document.getElementById("flip-button");
const headToHeadButton = document.getElementById("head-to-head-button");
const clearButton = document.getElementById("clear-button");
const emptyState = document.getElementById("empty-state");
const error1 = document.getElementById("error1");
const error2 = document.getElementById("error2");
let card1Flipped = false;
let card2Flipped = false;
let card1Selected = false;
let card2Selected = false;
function flipCard(card, target) {
if (card.classList.contains("flip")) {
card.classList.remove("flip");
target.style.transform = "rotateY(0deg)";
} else {
card.classList.add("flip");
target.style.transform = "rotateY(180deg)";
}
}
function updateEmptyState() {
if (card1.getAttribute("data-empty") === "true" && card2.getAttribute("data-empty") === "true") {
emptyState.style.display = "block";
} else {
emptyState.style.display = "none";
}
}
function randomWinner() {
const names = ["Tal Vex", "Zyla Korr"];
const winner = names[Math.floor(Math.random() * 2)];
winnerDisplay.textContent = `${winner} emerges victorious!`;
headToHead.classList.add("show");
setTimeout(() => {
headToHead.classList.remove("show");
}, 2500);
}
function clearCards() {
card1.setAttribute("data-empty", "true");
card2.setAttribute("data-empty", "true");
card1.classList.remove("flip");
card2.classList.remove("flip");
card1.querySelector(".face.front .name").textContent = "Tal Vex";
card2.querySelector(".face.front .name").textContent = "Zyla Korr";
card1Flipped = false;
card2Flipped = false;
card1Selected = false;
card2Selected = false;
updateEmptyState();
error1.textContent = "";
error2.textContent = "";
}
function setupCardListeners(card, idx) {
let isFlipping = false;
card.addEventListener("click", () => {
if (isFlipping) return;
isFlipping = true;
if (card.getAttribute("data-empty") === "true") {
error1.textContent = "Card must be selected before flipping.";
setTimeout(() => error1.textContent = "", 2000);
isFlipping = false;
return;
}
flipCard(card, card.querySelector(".face.front"));
setTimeout(() => isFlipping = false, 300);
});
card.addEventListener("keydown", (e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
card.click();
}
});
card.addEventListener("focus", () => {
if (card.getAttribute("data-empty") === "true") {
error1.textContent = "Card must be selected before flipping.";
setTimeout(() => error1.textContent = "", 2000);
}
});
}
setupCardListeners(card1, 1);
setupCardListeners(card2, 2);
flipButton.addEventListener("click", () => {
if (card1.getAttribute("data-empty") === "true" || card2.getAttribute("data-empty") === "true") {
error1.textContent = "No cards selected yet.";
error2.textContent = "No cards selected yet.";
setTimeout(() => {
error1.textContent = "";
error2.textContent = "";
}, 2000);
return;
}
flipCard(card1, card1.querySelector(".face.front"));
flipCard(card2, card2.querySelector(".face.front"));
});
headToHeadButton.addEventListener("click", () => {
if (card1.getAttribute("data-empty") === "true" || card2.getAttribute("data-empty") === "true") {
error1.textContent = "No cards selected yet.";
error2.textContent = "No cards selected yet.";
setTimeout(() => {
error1.textContent = "";
error2.textContent = "";
}, 2000);
return;
}
randomWinner();
});
clearButton.addEventListener("click", () => {
clearCards();
});
// Keyboard navigation
document.addEventListener("keydown", (e) => {
if (e.key === "Enter" && (e.target === flipButton || e.target === headToHeadButton || e.target === clearButton)) {
e.preventDefault();
e.target.click();
}
});
updateEmptyState();
</script>
</body>
</html>