67 lines
2.8 KiB
HTML
67 lines
2.8 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Side Cards — Full Deck</title>
|
|
<style>
|
|
:root { color-scheme: dark; font-family: Georgia, "Times New Roman", serif; }
|
|
* { box-sizing: border-box; }
|
|
body { margin: 0; padding: 28px; background: #083d24; color: #fff; }
|
|
header { max-width: 1100px; margin: 0 auto 26px; }
|
|
h1 { margin: 0 0 6px; font-size: clamp(24px, 4vw, 42px); }
|
|
p { margin: 0; color: #c9d8cf; }
|
|
main { max-width: 1500px; margin: auto; }
|
|
section { margin: 30px 0; }
|
|
h2 { margin: 0 0 14px; font-size: 18px; letter-spacing: .08em; }
|
|
.row { display: grid; grid-template-columns: repeat(13, minmax(72px, 1fr)); gap: 10px; }
|
|
.card { width: 100%; aspect-ratio: 5 / 7; border-radius: 4.8% / 3.4286%; box-shadow: 0 5px 14px #0008; display: block; }
|
|
.missing { background: #f8f6ef; color: #8b1d1d; display: grid; place-items: center; text-align: center; font: 700 12px/1.2 system-ui; }
|
|
@media (max-width: 1000px) { .row { grid-template-columns: repeat(7, 1fr); } }
|
|
@media (max-width: 600px) { body { padding: 16px; } .row { grid-template-columns: repeat(4, 1fr); } }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<h1>Side Cards</h1>
|
|
<p>The complete locally generated deck. Court illustrations are raster artwork inside consistent SVG cards.</p>
|
|
</header>
|
|
<main id="deck"></main>
|
|
<script>
|
|
const assetVersion = "20260805k";
|
|
const ranks = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"];
|
|
const suits = [
|
|
["s", "Spades"], ["h", "Hearts"], ["d", "Diamonds"], ["c", "Clubs"]
|
|
];
|
|
const deck = document.querySelector("#deck");
|
|
for (const [suit, name] of suits) {
|
|
const section = document.createElement("section");
|
|
section.innerHTML = `<h2>${name}</h2><div class="row"></div>`;
|
|
const row = section.querySelector(".row");
|
|
for (const rank of ranks) {
|
|
const img = new Image();
|
|
img.className = "card";
|
|
img.src = `exports/cards/${rank.toLowerCase()}${suit}.svg?v=${assetVersion}`;
|
|
img.alt = `${rank} of ${name}`;
|
|
img.onerror = () => {
|
|
const missing = document.createElement("div");
|
|
missing.className = "card missing";
|
|
missing.textContent = `${rank}${suit.toUpperCase()} not built`;
|
|
img.replaceWith(missing);
|
|
};
|
|
row.append(img);
|
|
}
|
|
deck.append(section);
|
|
}
|
|
const backSection = document.createElement("section");
|
|
backSection.innerHTML = '<h2>Card Back</h2><div class="row" id="back-row"></div>';
|
|
const back = new Image();
|
|
back.className = "card";
|
|
back.src = `exports/cards/back.svg?v=${assetVersion}`;
|
|
back.alt = "Navy Side Cards back";
|
|
backSection.querySelector("#back-row").append(back);
|
|
deck.append(backSection);
|
|
</script>
|
|
</body>
|
|
</html>
|