diff --git a/public/js/quickmenu/carddeck.js b/public/js/quickmenu/carddeck.js
index c405340..71249c5 100644
--- a/public/js/quickmenu/carddeck.js
+++ b/public/js/quickmenu/carddeck.js
@@ -4,7 +4,7 @@ let currentGroupId = null;
let currentPage = 1;
let currentDeckId = null;
let deckCards = []; // [{card_id, amount}]
-let userCardsCache = []; // aktuelle Seite: [{card_id, amount, name, image, rarity, attack, defense}]
+let userCardsCache = []; // aktuelle Seite: [{card_id, amount, name, image, rarity, attack, defense, range, race}]
let decks = []; // [{id, name}]
/* ── Kristall-Mapping ───────────────────────── */
@@ -26,6 +26,28 @@ function rarityImgs(rarity, size = 14) {
return img.repeat(count);
}
+/* ── Stat-Icons ─────────────────────────────── */
+function rangeIcon() {
+ return ``;
+}
+
+function raceIcon() {
+ return ``;
+}
+
/* ══════════════════════════════════════════════
INIT
══════════════════════════════════════════════ */
@@ -439,6 +461,40 @@ function renderShell() {
}
.kd-deck-count-indeck { font-family: "Cinzel", serif; font-size: 13px; color: #000; font-weight: bold; text-shadow: 0 0 3px rgba(255,255,255,0.6); }
+ /* ── Reichweite & Laufen Badges ────────── */
+ .kd-range-race {
+ position: absolute;
+ bottom: 20px;
+ left: 0; right: 0;
+ display: flex;
+ justify-content: center;
+ gap: 4px;
+ padding: 0 3px;
+ pointer-events: none;
+ z-index: 6;
+ }
+ .kd-badge-range, .kd-badge-race {
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ padding: 1px 4px;
+ border-radius: 20px;
+ font-family: "Cinzel", serif;
+ font-size: 9px;
+ font-weight: bold;
+ line-height: 1;
+ }
+ .kd-badge-range {
+ background: rgba(30,20,0,0.82);
+ border: 1px solid #e8b84b;
+ color: #e8b84b;
+ }
+ .kd-badge-race {
+ background: rgba(0,25,0,0.82);
+ border: 1px solid #7de87d;
+ color: #7de87d;
+ }
+
/* ── Rarity Kristalle ───────────────────── */
.kd-rarity {
position: absolute;
@@ -772,6 +828,11 @@ function renderCollectionGrid(grid, cards) {
× ${c.amount}
${c.rarity ? `
${rarityImgs(c.rarity, 13)}
` : ""}
+ ${(c.range != null || c.race != null) ? `
+
+ ${c.range != null ? `${rangeIcon()} ${c.range}` : ""}
+ ${c.race != null ? `${raceIcon()} ${c.race}` : ""}
+
` : ""}
`;
})
.join("");
@@ -808,6 +869,11 @@ function renderDeckGrid(grid, cards) {
🃏 ${c.amount}
${c.rarity ? `${rarityImgs(c.rarity, 14)}
` : ""}
+ ${(c.range != null || c.race != null) ? `
+
+ ${c.range != null ? `${rangeIcon()} ${c.range}` : ""}
+ ${c.race != null ? `${raceIcon()} ${c.race}` : ""}
+
` : ""}
`;
})
.join("");
diff --git a/views/1v1-battlefield.ejs b/views/1v1-battlefield.ejs
index 423f28f..08b0c7f 100644
--- a/views/1v1-battlefield.ejs
+++ b/views/1v1-battlefield.ejs
@@ -165,6 +165,34 @@
transform: translateY(-4px);
transition: transform 0.15s;
}
+
+ /* ── Reichweite & Laufen Badges (Hand + Board) ── */
+ .cs-range, .cs-race {
+ position: absolute;
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ padding: 1px 4px;
+ border-radius: 20px;
+ font-family: "Cinzel", serif;
+ font-size: 8px;
+ font-weight: bold;
+ line-height: 1;
+ z-index: 6;
+ pointer-events: none;
+ }
+ .cs-range {
+ bottom: 22px; left: 3px;
+ background: rgba(30,20,0,0.85);
+ border: 1px solid #e8b84b;
+ color: #e8b84b;
+ }
+ .cs-race {
+ bottom: 6px; left: 3px;
+ background: rgba(0,25,0,0.85);
+ border: 1px solid #7de87d;
+ color: #7de87d;
+ }
@@ -383,6 +411,10 @@
handSlotState[id] = null;
});
+ /* ── Stat-Icon SVGs ─────────────────────────────────── */
+ const SVG_RANGE = ``;
+ const SVG_RACE = ``;
+
/* ── Slot rendern ──────────────────────────────────── */
function renderHandSlot(id) {
const slot = document.getElementById(id);
@@ -400,6 +432,8 @@
const atkVal = card.attack ?? null;
const defVal = card.defends ?? null;
+ const rngVal = card.range ?? null;
+ const rceVal = card.race ?? null;
const statsHtml = `
@@ -410,6 +444,8 @@
? `${isReady ? "✓" : currentCd}`
: ""
}
+ ${rngVal != null ? `${SVG_RANGE} ${rngVal}` : ""}
+ ${rceVal != null ? `${SVG_RACE} ${rceVal}` : ""}
`;
const readyBadge = isReady
@@ -641,20 +677,27 @@
if (!slot || !card) return;
const atkVal = card.attack ?? null;
const defVal = card.defends ?? null;
- const cdVal = card.cooldown ?? null;
+ const cdVal = card.cooldown ?? null;
+ const rngVal = card.range ?? null;
+ const rceVal = card.race ?? null;
const hasAtk = atkVal != null;
const hasDef = defVal != null;
- const hasCd = cdVal != null;
+ const hasCd = cdVal != null;
+ const hasRng = rngVal != null;
+ const hasRce = rceVal != null;
const statsHtml =
- hasAtk || hasDef || hasCd
+ hasAtk || hasDef || hasCd || hasRng || hasRce
? `
${hasAtk ? `${atkVal}` : ""}
${hasDef ? `${defVal}` : ""}
- ${hasCd ? `${cdVal}` : ""}
+ ${hasCd ? `${cdVal}` : ""}
+ ${hasRng ? `${SVG_RANGE} ${rngVal}` : ""}
+ ${hasRce ? `${SVG_RACE} ${rceVal}` : ""}
`
: "";
+ // note: SVG_RACE is defined as the walking icon above
slot.classList.add("slot-occupied");
slot.innerHTML = card.image