495 lines
17 KiB
HTML
495 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Commander Battlefield</title>
|
||
<style>
|
||
@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600;700&family=Inter:wght@400;500;600&display=swap');
|
||
|
||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||
|
||
:root {
|
||
--felt: #2a2a2a;
|
||
--felt-light: #333333;
|
||
--felt-dark: #1e1e1e;
|
||
--felt-line: rgba(255,255,255,0.08);
|
||
--felt-line-strong: rgba(255,255,255,0.15);
|
||
|
||
--p1: #c0392b; --p1-soft: rgba(192,57,43,0.15); --p1-glow: rgba(192,57,43,0.35); --p1-text: #e74c3c;
|
||
--p2: #2980b9; --p2-soft: rgba(41,128,185,0.15); --p2-glow: rgba(41,128,185,0.35); --p2-text: #3498db;
|
||
--p3: #27ae60; --p3-soft: rgba(39,174,96,0.15); --p3-glow: rgba(39,174,96,0.35); --p3-text: #2ecc71;
|
||
--p4: #d4930d; --p4-soft: rgba(212,147,13,0.15); --p4-glow: rgba(212,147,13,0.35); --p4-text: #f1c40f;
|
||
|
||
--card-w: 63px;
|
||
--card-h: 88px;
|
||
--zone-radius: 8px;
|
||
}
|
||
|
||
html, body {
|
||
width: 100%; height: 100%;
|
||
overflow: hidden;
|
||
font-family: 'Inter', sans-serif;
|
||
background: var(--felt-dark);
|
||
}
|
||
|
||
body {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.table-surface {
|
||
position: relative;
|
||
width: 100vw;
|
||
height: 100vh;
|
||
background: radial-gradient(ellipse at 50% 50%, var(--felt-light) 0%, var(--felt) 50%, var(--felt-dark) 100%);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.table-surface::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.08'/%3E%3C/svg%3E");
|
||
background-size: 200px 200px;
|
||
pointer-events: none;
|
||
z-index: 1;
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.table-surface::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background: radial-gradient(ellipse at center, transparent 40%, rgba(0,0,0,0.45) 100%);
|
||
pointer-events: none;
|
||
z-index: 2;
|
||
}
|
||
|
||
.battlefield {
|
||
position: absolute;
|
||
inset: 10px;
|
||
z-index: 5;
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
grid-template-rows: 1fr 1fr;
|
||
gap: 0;
|
||
}
|
||
|
||
.divider-h, .divider-v {
|
||
position: absolute;
|
||
z-index: 10;
|
||
pointer-events: none;
|
||
}
|
||
.divider-h {
|
||
top: 50%; left: 10px; right: 10px;
|
||
height: 2px;
|
||
transform: translateY(-50%);
|
||
background: var(--felt-line-strong);
|
||
box-shadow: 0 0 12px rgba(255,255,255,0.04);
|
||
}
|
||
.divider-v {
|
||
left: 50%; top: 10px; bottom: 10px;
|
||
width: 2px;
|
||
transform: translateX(-50%);
|
||
background: var(--felt-line-strong);
|
||
box-shadow: 0 0 12px rgba(255,255,255,0.04);
|
||
}
|
||
|
||
.center-emblem {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 15;
|
||
width: 76px; height: 76px;
|
||
border-radius: 50%;
|
||
background: radial-gradient(circle, rgba(55,55,55,0.95), rgba(25,25,25,0.98));
|
||
border: 2px solid rgba(255,255,255,0.08);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 0 30px rgba(0,0,0,0.6), inset 0 0 20px rgba(0,0,0,0.3);
|
||
}
|
||
.center-emblem svg { width: 40px; height: 40px; }
|
||
|
||
.player-area {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 8px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.player-area.p1 { grid-area: 1 / 1 / 2 / 2; }
|
||
.player-area.p2 { grid-area: 1 / 2 / 2 / 3; }
|
||
.player-area.p3 { grid-area: 2 / 1 / 3 / 2; }
|
||
.player-area.p4 { grid-area: 2 / 2 / 3 / 3; }
|
||
|
||
.p1, .p2 { justify-content: flex-start; }
|
||
.p3, .p4 { justify-content: flex-end; }
|
||
|
||
.player-label {
|
||
font-family: 'Cinzel', serif;
|
||
font-weight: 700;
|
||
font-size: 11px;
|
||
letter-spacing: 2px;
|
||
text-transform: uppercase;
|
||
padding: 3px 10px;
|
||
border-radius: 4px;
|
||
position: absolute;
|
||
z-index: 20;
|
||
white-space: nowrap;
|
||
}
|
||
.p1 .player-label { top: 8px; left: 8px; color: var(--p1-text); background: var(--p1-soft); }
|
||
.p2 .player-label { top: 8px; right: 8px; color: var(--p2-text); background: var(--p2-soft); }
|
||
.p3 .player-label { bottom: 8px; left: 8px; color: var(--p3-text); background: var(--p3-soft); }
|
||
.p4 .player-label { bottom: 8px; right: 8px; color: var(--p4-text); background: var(--p4-soft); }
|
||
|
||
.life-counter {
|
||
position: absolute;
|
||
z-index: 20;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
font-family: 'Cinzel', serif;
|
||
font-size: 20px;
|
||
font-weight: 700;
|
||
}
|
||
.life-counter button {
|
||
width: 22px; height: 22px;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(255,255,255,0.12);
|
||
background: rgba(255,255,255,0.04);
|
||
color: rgba(255,255,255,0.45);
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.2s;
|
||
font-family: 'Inter', sans-serif;
|
||
line-height: 1;
|
||
}
|
||
.life-counter button:hover {
|
||
background: rgba(255,255,255,0.12);
|
||
color: rgba(255,255,255,0.8);
|
||
}
|
||
.p1 .life-counter { top: 8px; right: 8px; color: var(--p1-text); }
|
||
.p2 .life-counter { top: 8px; left: 8px; color: var(--p2-text); }
|
||
.p3 .life-counter { bottom: 8px; right: 8px; color: var(--p3-text); }
|
||
.p4 .life-counter { bottom: 8px; left: 8px; color: var(--p4-text); }
|
||
|
||
.zone-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
flex-shrink: 0;
|
||
}
|
||
.p1 .zone-row, .p3 .zone-row { flex-direction: row; }
|
||
.p2 .zone-row, .p4 .zone-row { flex-direction: row-reverse; }
|
||
|
||
.commander-row {
|
||
display: flex;
|
||
flex-shrink: 0;
|
||
margin: 4px 0;
|
||
}
|
||
.p1 .commander-row, .p3 .commander-row { justify-content: flex-start; }
|
||
.p2 .commander-row, .p4 .commander-row { justify-content: flex-end; }
|
||
|
||
.battle-zone {
|
||
flex: 1;
|
||
position: relative;
|
||
border-radius: var(--zone-radius);
|
||
min-height: 50px;
|
||
}
|
||
.battle-zone-inner {
|
||
position: absolute;
|
||
inset: 4px;
|
||
border-radius: var(--zone-radius);
|
||
border: 1px dashed;
|
||
opacity: 0.12;
|
||
pointer-events: none;
|
||
}
|
||
.p1 .battle-zone-inner { border-color: var(--p1); }
|
||
.p2 .battle-zone-inner { border-color: var(--p2); }
|
||
.p3 .battle-zone-inner { border-color: var(--p3); }
|
||
.p4 .battle-zone-inner { border-color: var(--p4); }
|
||
|
||
.battle-zone-label {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
font-family: 'Cinzel', serif;
|
||
font-size: 11px;
|
||
letter-spacing: 4px;
|
||
text-transform: uppercase;
|
||
opacity: 0.06;
|
||
pointer-events: none;
|
||
white-space: nowrap;
|
||
color: #fff;
|
||
}
|
||
|
||
.zone {
|
||
position: relative;
|
||
border-radius: var(--zone-radius);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: default;
|
||
transition: all 0.25s ease;
|
||
border: 1px solid rgba(255,255,255,0.05);
|
||
background: rgba(0,0,0,0.18);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.zone:hover {
|
||
border-color: rgba(255,255,255,0.12);
|
||
background: rgba(0,0,0,0.28);
|
||
}
|
||
|
||
.zone-icon {
|
||
font-size: 16px;
|
||
opacity: 0.55;
|
||
margin-bottom: 2px;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.zone-name {
|
||
font-size: 7.5px;
|
||
font-weight: 600;
|
||
letter-spacing: 1.2px;
|
||
text-transform: uppercase;
|
||
color: rgba(255,255,255,0.3);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.zone.library, .zone.exile, .zone.graveyard {
|
||
width: var(--card-w);
|
||
height: var(--card-h);
|
||
}
|
||
.zone.hand {
|
||
flex: 1;
|
||
height: var(--card-h);
|
||
min-width: 80px;
|
||
flex-direction: row;
|
||
gap: 4px;
|
||
}
|
||
.zone.hand .zone-icon { margin-bottom: 0; margin-right: 3px; }
|
||
.zone.commander {
|
||
width: calc(var(--card-w) + 14px);
|
||
height: calc(var(--card-h) + 6px);
|
||
border-width: 2px;
|
||
}
|
||
|
||
.p1 .zone { border-color: rgba(192,57,43,0.12); }
|
||
.p1 .zone:hover { border-color: rgba(192,57,43,0.3); box-shadow: 0 0 12px var(--p1-soft); }
|
||
.p1 .zone.commander { border-color: rgba(192,57,43,0.25); background: var(--p1-soft); }
|
||
.p1 .zone-icon { color: var(--p1-text); }
|
||
|
||
.p2 .zone { border-color: rgba(41,128,185,0.12); }
|
||
.p2 .zone:hover { border-color: rgba(41,128,185,0.3); box-shadow: 0 0 12px var(--p2-soft); }
|
||
.p2 .zone.commander { border-color: rgba(41,128,185,0.25); background: var(--p2-soft); }
|
||
.p2 .zone-icon { color: var(--p2-text); }
|
||
|
||
.p3 .zone { border-color: rgba(39,174,96,0.12); }
|
||
.p3 .zone:hover { border-color: rgba(39,174,96,0.3); box-shadow: 0 0 12px var(--p3-soft); }
|
||
.p3 .zone.commander { border-color: rgba(39,174,96,0.25); background: var(--p3-soft); }
|
||
.p3 .zone-icon { color: var(--p3-text); }
|
||
|
||
.p4 .zone { border-color: rgba(212,147,13,0.12); }
|
||
.p4 .zone:hover { border-color: rgba(212,147,13,0.3); box-shadow: 0 0 12px var(--p4-soft); }
|
||
.p4 .zone.commander { border-color: rgba(212,147,13,0.25); background: var(--p4-soft); }
|
||
.p4 .zone-icon { color: var(--p4-text); }
|
||
|
||
.zone[data-tooltip]:hover::after {
|
||
content: attr(data-tooltip);
|
||
position: absolute;
|
||
bottom: calc(100% + 6px);
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: rgba(0,0,0,0.88);
|
||
color: #ccc;
|
||
font-size: 10px;
|
||
padding: 3px 8px;
|
||
border-radius: 4px;
|
||
white-space: nowrap;
|
||
z-index: 50;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.card-count {
|
||
position: absolute;
|
||
top: 3px;
|
||
right: 4px;
|
||
font-size: 8px;
|
||
font-weight: 600;
|
||
color: rgba(255,255,255,0.25);
|
||
background: rgba(0,0,0,0.3);
|
||
padding: 1px 4px;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.title-bar {
|
||
position: absolute;
|
||
top: 0; left: 0; right: 0;
|
||
z-index: 30;
|
||
text-align: center;
|
||
padding: 5px;
|
||
pointer-events: none;
|
||
}
|
||
.title-bar h1 {
|
||
font-family: 'Cinzel', serif;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
letter-spacing: 5px;
|
||
text-transform: uppercase;
|
||
color: rgba(255,255,255,0.15);
|
||
}
|
||
|
||
.corner-accent {
|
||
position: absolute;
|
||
width: 24px; height: 24px;
|
||
z-index: 6;
|
||
pointer-events: none;
|
||
opacity: 0.12;
|
||
}
|
||
.corner-accent.tl { top: 6px; left: 6px; border-top: 2px solid var(--p1); border-left: 2px solid var(--p1); }
|
||
.corner-accent.tr { top: 6px; right: 6px; border-top: 2px solid var(--p2); border-right: 2px solid var(--p2); }
|
||
.corner-accent.bl { bottom: 6px; left: 6px; border-bottom: 2px solid var(--p3); border-left: 2px solid var(--p3); }
|
||
.corner-accent.br { bottom: 6px; right: 6px; border-bottom: 2px solid var(--p4); border-right: 2px solid var(--p4); }
|
||
|
||
@media (max-width: 768px) {
|
||
:root { --card-w: 42px; --card-h: 58px; }
|
||
.player-label { font-size: 7px; letter-spacing: 1px; padding: 2px 6px; }
|
||
.life-counter { font-size: 15px; }
|
||
.life-counter button { width: 18px; height: 18px; font-size: 11px; }
|
||
.zone-name { font-size: 6px; }
|
||
.zone-icon { font-size: 12px; }
|
||
.center-emblem { width: 46px; height: 46px; }
|
||
.center-emblem svg { width: 26px; height: 26px; }
|
||
.battle-zone-label { font-size: 8px; letter-spacing: 2px; }
|
||
.zone-row { gap: 3px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="table-surface">
|
||
<div class="title-bar"><h1>Commander Battlefield</h1></div>
|
||
<div class="corner-accent tl"></div>
|
||
<div class="corner-accent tr"></div>
|
||
<div class="corner-accent bl"></div>
|
||
<div class="corner-accent br"></div>
|
||
<div class="divider-h"></div>
|
||
<div class="divider-v"></div>
|
||
|
||
<div class="center-emblem">
|
||
<svg viewBox="0 0 100 100" fill="none">
|
||
<circle cx="50" cy="50" r="42" stroke="rgba(255,255,255,0.2)" stroke-width="1.5"/>
|
||
<circle cx="50" cy="50" r="28" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
|
||
<polygon points="50,15 58.5,37 82,37 63,51 69,74 50,60 31,74 37,51 18,37 41.5,37"
|
||
fill="rgba(255,255,255,0.1)" stroke="rgba(255,255,255,0.2)" stroke-width="0.8"/>
|
||
</svg>
|
||
</div>
|
||
|
||
<div class="battlefield">
|
||
|
||
<!-- PLAYER 1: Top-Left (Crimson) -->
|
||
<div class="player-area p1">
|
||
<span class="player-label">Player 1</span>
|
||
<div class="life-counter">
|
||
<button onclick="changeLife(1,-1)" aria-label="Decrease life">−</button>
|
||
<span id="life1">40</span>
|
||
<button onclick="changeLife(1,1)" aria-label="Increase life">+</button>
|
||
</div>
|
||
<div class="zone-row">
|
||
<div class="zone library" data-tooltip="Library"><span class="card-count">99</span><span class="zone-icon">📚</span><span class="zone-name">Library</span></div>
|
||
<div class="zone exile" data-tooltip="Exile"><span class="zone-icon">✦</span><span class="zone-name">Exile</span></div>
|
||
<div class="zone graveyard" data-tooltip="Graveyard"><span class="zone-icon">💀</span><span class="zone-name">Grave</span></div>
|
||
<div class="zone hand" data-tooltip="Hand"><span class="zone-icon">🃏</span><span class="zone-name">Hand</span></div>
|
||
</div>
|
||
<div class="commander-row">
|
||
<div class="zone commander" data-tooltip="Commander Zone"><span class="zone-icon">👑</span><span class="zone-name">Commander</span></div>
|
||
</div>
|
||
<div class="battle-zone"><div class="battle-zone-inner"></div><span class="battle-zone-label">Battlefield</span></div>
|
||
</div>
|
||
|
||
<!-- PLAYER 2: Top-Right (Sapphire) -->
|
||
<div class="player-area p2">
|
||
<span class="player-label">Player 2</span>
|
||
<div class="life-counter">
|
||
<button onclick="changeLife(2,-1)" aria-label="Decrease life">−</button>
|
||
<span id="life2">40</span>
|
||
<button onclick="changeLife(2,1)" aria-label="Increase life">+</button>
|
||
</div>
|
||
<div class="zone-row">
|
||
<div class="zone library" data-tooltip="Library"><span class="card-count">99</span><span class="zone-icon">📚</span><span class="zone-name">Library</span></div>
|
||
<div class="zone exile" data-tooltip="Exile"><span class="zone-icon">✦</span><span class="zone-name">Exile</span></div>
|
||
<div class="zone graveyard" data-tooltip="Graveyard"><span class="zone-icon">💀</span><span class="zone-name">Grave</span></div>
|
||
<div class="zone hand" data-tooltip="Hand"><span class="zone-icon">🃏</span><span class="zone-name">Hand</span></div>
|
||
</div>
|
||
<div class="commander-row">
|
||
<div class="zone commander" data-tooltip="Commander Zone"><span class="zone-icon">👑</span><span class="zone-name">Commander</span></div>
|
||
</div>
|
||
<div class="battle-zone"><div class="battle-zone-inner"></div><span class="battle-zone-label">Battlefield</span></div>
|
||
</div>
|
||
|
||
<!-- PLAYER 3: Bottom-Left (Emerald) -->
|
||
<div class="player-area p3">
|
||
<div class="battle-zone"><div class="battle-zone-inner"></div><span class="battle-zone-label">Battlefield</span></div>
|
||
<div class="commander-row">
|
||
<div class="zone commander" data-tooltip="Commander Zone"><span class="zone-icon">👑</span><span class="zone-name">Commander</span></div>
|
||
</div>
|
||
<div class="zone-row">
|
||
<div class="zone library" data-tooltip="Library"><span class="card-count">99</span><span class="zone-icon">📚</span><span class="zone-name">Library</span></div>
|
||
<div class="zone exile" data-tooltip="Exile"><span class="zone-icon">✦</span><span class="zone-name">Exile</span></div>
|
||
<div class="zone graveyard" data-tooltip="Graveyard"><span class="zone-icon">💀</span><span class="zone-name">Grave</span></div>
|
||
<div class="zone hand" data-tooltip="Hand"><span class="zone-icon">🃏</span><span class="zone-name">Hand</span></div>
|
||
</div>
|
||
<span class="player-label">Player 3</span>
|
||
<div class="life-counter">
|
||
<button onclick="changeLife(3,-1)" aria-label="Decrease life">−</button>
|
||
<span id="life3">40</span>
|
||
<button onclick="changeLife(3,1)" aria-label="Increase life">+</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- PLAYER 4: Bottom-Right (Gold) -->
|
||
<div class="player-area p4">
|
||
<div class="battle-zone"><div class="battle-zone-inner"></div><span class="battle-zone-label">Battlefield</span></div>
|
||
<div class="commander-row">
|
||
<div class="zone commander" data-tooltip="Commander Zone"><span class="zone-icon">👑</span><span class="zone-name">Commander</span></div>
|
||
</div>
|
||
<div class="zone-row">
|
||
<div class="zone library" data-tooltip="Library"><span class="card-count">99</span><span class="zone-icon">📚</span><span class="zone-name">Library</span></div>
|
||
<div class="zone exile" data-tooltip="Exile"><span class="zone-icon">✦</span><span class="zone-name">Exile</span></div>
|
||
<div class="zone graveyard" data-tooltip="Graveyard"><span class="zone-icon">💀</span><span class="zone-name">Grave</span></div>
|
||
<div class="zone hand" data-tooltip="Hand"><span class="zone-icon">🃏</span><span class="zone-name">Hand</span></div>
|
||
</div>
|
||
<span class="player-label">Player 4</span>
|
||
<div class="life-counter">
|
||
<button onclick="changeLife(4,-1)" aria-label="Decrease life">−</button>
|
||
<span id="life4">40</span>
|
||
<button onclick="changeLife(4,1)" aria-label="Increase life">+</button>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const lives = { 1: 40, 2: 40, 3: 40, 4: 40 };
|
||
function changeLife(p, d) {
|
||
lives[p] = Math.max(0, lives[p] + d);
|
||
const el = document.getElementById('life' + p);
|
||
el.textContent = lives[p];
|
||
el.style.transform = 'scale(1.25)';
|
||
el.style.transition = 'transform 0.15s ease';
|
||
setTimeout(() => { el.style.transform = 'scale(1)'; }, 150);
|
||
}
|
||
</script>
|
||
</body>
|
||
</html> |