diff --git a/public/css/popup.css b/public/css/popup.css new file mode 100644 index 0000000..e247cdd --- /dev/null +++ b/public/css/popup.css @@ -0,0 +1,505 @@ +/* ================================================================ + POPUP.CSS — Dynasty of Knights — Gebäude Popup Styles +================================================================ */ + +/* ================================ + POPUP WRAPPER +================================ */ + +.building-popup { + position: fixed; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + width: 580px; + background: + repeating-linear-gradient( + 0deg, + transparent, + transparent 2px, + rgba(255,255,255,0.012) 2px, + rgba(255,255,255,0.012) 4px + ), + linear-gradient(160deg, #2e1c07 0%, #1a0e04 40%, #221508 100%); + border: 2px solid #9a7a28; + border-radius: 6px; + display: none; + flex-direction: column; + z-index: 1000; + overflow: visible; + box-shadow: + 0 0 0 1px rgba(200,168,64,0.3), + 0 0 40px rgba(200,150,12,0.1), + 0 30px 80px rgba(0,0,0,0.6), + inset 0 0 60px rgba(0,0,0,0.27); +} + +.building-popup.active { + display: flex; +} + +/* ================================ + ECKORNAMENTE +================================ */ + +.popup-corner { + position: absolute; + width: 30px; + height: 30px; + z-index: 10; + pointer-events: none; +} + +.popup-corner.c-tl { top: -4px; left: -4px; } +.popup-corner.c-tr { top: -4px; right: -4px; transform: scaleX(-1); } +.popup-corner.c-bl { bottom: -4px; left: -4px; transform: scaleY(-1); } +.popup-corner.c-br { bottom: -4px; right: -4px; transform: scale(-1); } + +/* ================================ + HEADER +================================ */ + +.popup-header { + background: linear-gradient( + 90deg, + #0a0602 0%, + #3d2510 20%, + #4a2e12 50%, + #3d2510 80%, + #0a0602 100% + ); + border-bottom: 2px solid #9a7a28; + padding: 0 20px; + height: 46px; + display: flex; + align-items: center; + justify-content: space-between; + position: relative; + flex-shrink: 0; +} + +.popup-header::after { + content: ''; + position: absolute; + bottom: -5px; + left: 5%; + right: 5%; + height: 3px; + background: linear-gradient( + 90deg, + transparent, + rgba(200,150,12,0.67), + rgba(240,208,96,0.6), + rgba(200,150,12,0.67), + transparent + ); + filter: blur(1px); + pointer-events: none; +} + +.popup-title-wrap { + display: flex; + align-items: center; + gap: 10px; +} + +.popup-title-gem { + width: 11px; + height: 11px; + border-radius: 50%; + background: radial-gradient(circle at 35% 35%, #f0d080, #c8960c, #7a4a00); + box-shadow: 0 0 8px rgba(200,150,12,0.53); + flex-shrink: 0; +} + +#popup-title { + font-family: 'Cinzel Decorative', 'Palatino Linotype', serif; + font-size: 13px; + font-weight: 700; + color: #f5e090; + letter-spacing: 3px; + text-shadow: 0 0 20px rgba(200,150,12,0.53), 0 1px 3px rgba(0,0,0,0.6); + text-transform: uppercase; +} + +.popup-close { + width: 26px; + height: 26px; + border-radius: 50%; + background: radial-gradient(circle at 40% 35%, #5a1808, #2a0a04); + border: 1px solid #8a3010; + color: #e06040; + font-size: 11px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.094); + user-select: none; +} + +.popup-close:hover { + background: radial-gradient(circle at 40% 35%, #8a2010, #4a1008); + border-color: #e04020; + color: #ff9080; + box-shadow: 0 0 10px rgba(200,64,32,0.27); +} + +/* ================================ + BODY: SIDEBAR + CONTENT +================================ */ + +.popup-body { + display: flex; + flex: 1; + min-height: 380px; + overflow: hidden; + border-radius: 0 0 4px 4px; +} + +/* ================================ + VERTIKALE TAB-SIDEBAR +================================ */ + +.popup-tabs { + width: 62px; + background: + repeating-linear-gradient( + 90deg, + transparent, + transparent 1px, + rgba(255,255,255,0.008) 1px, + rgba(255,255,255,0.008) 2px + ), + linear-gradient(180deg, #1a0e04 0%, #120a03 100%); + border-right: 2px solid #7a5a18; + display: flex; + flex-direction: column; + align-items: center; + padding: 14px 0; + gap: 8px; + position: relative; + flex-shrink: 0; +} + +.popup-tabs::after { + content: ''; + position: absolute; + right: -4px; + top: 8%; + bottom: 8%; + width: 3px; + background: linear-gradient( + 180deg, + transparent, + rgba(200,150,12,0.33), + rgba(240,208,96,0.2), + rgba(200,150,12,0.33), + transparent + ); + filter: blur(1px); + pointer-events: none; +} + +/* ================================ + TAB BUTTONS +================================ */ + +.popup-tabs .tab { + width: 44px; + height: 44px; + border-radius: 4px; + border: 1px solid #4a3408; + background: linear-gradient(145deg, #2e1c08 0%, #1a0e04 100%); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + position: relative; + transition: all 0.2s; + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.031), + inset 0 -1px 0 rgba(0,0,0,0.2); + padding: 0; + outline: none; +} + +.popup-tabs .tab:hover { + border-color: #c8960c; + background: linear-gradient(145deg, #3e2c10 0%, #2a1a08 100%); + box-shadow: + inset 0 1px 0 rgba(200,150,12,0.125), + 0 0 14px rgba(200,150,12,0.133), + 0 0 0 1px rgba(200,150,12,0.267); +} + +.popup-tabs .tab.active { + border-color: #c8960c; + background: linear-gradient(145deg, #5a3a14 0%, #3a2208 100%); + box-shadow: + inset 0 1px 0 rgba(200,150,12,0.25), + 0 0 18px rgba(200,150,12,0.2), + 0 0 0 1px rgba(200,150,12,0.4); +} + +/* Aktiver Tab: goldener Balken rechts */ +.popup-tabs .tab.active::after { + content: ''; + position: absolute; + right: -3px; + top: 20%; + height: 60%; + width: 4px; + background: linear-gradient(180deg, #f0d060, #c8960c); + border-radius: 2px 0 0 2px; + box-shadow: 0 0 8px #c8960c; +} + +/* Tab SVG Icons */ +.tab-icon { + width: 26px; + height: 26px; + display: none; +} + +.tab-icon-default { display: block; } +.tab-icon-active { display: none; } + +.tab.active .tab-icon-default { display: none; } +.tab.active .tab-icon-active { display: block; } + +/* Tooltip */ +.tab-tip { + position: absolute; + left: 54px; + top: 50%; + transform: translateY(-50%); + background: linear-gradient(135deg, #2e1c08, #1a0e04); + border: 1px solid #9a7a28; + color: #f0d080; + font-size: 11px; + font-family: 'Cinzel', 'Palatino Linotype', serif; + letter-spacing: 1px; + padding: 5px 10px; + border-radius: 4px; + white-space: nowrap; + pointer-events: none; + opacity: 0; + transition: opacity 0.15s; + z-index: 20; + box-shadow: 0 4px 12px rgba(0,0,0,0.4), 0 0 0 1px rgba(200,150,12,0.2); +} + +.tab-tip::before { + content: ''; + position: absolute; + left: -5px; + top: 50%; + transform: translateY(-50%); + width: 0; + height: 0; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-right: 5px solid #9a7a28; +} + +.popup-tabs .tab:hover .tab-tip { + opacity: 1; +} + +/* ================================ + POPUP CONTENT AREA +================================ */ + +.popup-content { + flex: 1; + overflow-y: auto; + padding: 20px 22px; +} + +.popup-content::-webkit-scrollbar { + width: 5px; +} +.popup-content::-webkit-scrollbar-track { + background: #0f0803; +} +.popup-content::-webkit-scrollbar-thumb { + background: #5a3a10; + border-radius: 3px; +} +.popup-content::-webkit-scrollbar-thumb:hover { + background: #c8960c; +} + +.tab-content { + display: none; + animation: popupFadeIn 0.2s ease; +} + +.tab-content.active { + display: block; +} + +@keyframes popupFadeIn { + from { opacity: 0; transform: translateY(4px); } + to { opacity: 1; transform: none; } +} + +/* ================================ + INFO TAB INHALT +================================ */ + +.popup-info-title { + font-family: 'Cinzel', 'Palatino Linotype', serif; + font-size: 14px; + font-weight: 600; + color: #f0d060; + letter-spacing: 2px; + text-shadow: 0 0 12px rgba(200,150,12,0.33); + margin-bottom: 14px; + padding-bottom: 10px; + border-bottom: 1px solid rgba(122,90,24,0.3); + position: relative; +} + +.popup-info-title::after { + content: ''; + position: absolute; + bottom: -1px; + left: 0; + width: 40%; + height: 1px; + background: linear-gradient(90deg, #c8960c, transparent); +} + +.popup-stat-row { + display: flex; + justify-content: space-between; + align-items: center; + padding: 7px 10px; + margin-bottom: 4px; + border-radius: 3px; + background: linear-gradient(90deg, #1e1206 0%, #120a03 100%); + border: 1px solid #3a2808; + font-size: 13px; + transition: border-color 0.15s; +} + +.popup-stat-row:hover { + border-color: #6a4a14; +} + +.popup-stat-key { + color: #806040; +} + +.popup-stat-val { + color: #e0c060; + font-weight: 600; + font-family: 'Cinzel', serif; + font-size: 12px; +} + +.popup-desc { + font-size: 12px; + color: #806040; + line-height: 1.8; + font-style: italic; + padding: 10px 12px; + border-left: 2px solid rgba(200,150,12,0.267); + background: #0f0803; + border-radius: 0 4px 4px 0; + margin-top: 8px; +} + +/* Fortschrittsbalken */ +.popup-xp-wrap { + margin-top: 14px; +} + +.popup-xp-label { + font-size: 11px; + color: #705030; + margin-bottom: 5px; + font-family: 'Cinzel', serif; + letter-spacing: 1px; +} + +.popup-xp-track { + height: 10px; + background: #0a0602; + border: 1px solid #4a3208; + border-radius: 5px; + overflow: hidden; + position: relative; +} + +.popup-xp-fill { + height: 100%; + background: linear-gradient(90deg, #6a3a08 0%, #c8960c 60%, #f0d060 100%); + border-radius: 5px; + position: relative; + transition: width 0.6s ease; +} + +.popup-xp-fill::after { + content: ''; + position: absolute; + top: 1px; + left: 4px; + right: 8px; + height: 3px; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.188)); + border-radius: 3px; +} + +.popup-xp-shimmer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 20px; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.25)); + animation: popupShimmer 2s ease-in-out infinite; +} + +@keyframes popupShimmer { + 0%, 100% { opacity: 0.3; } + 50% { opacity: 1; } +} + +.popup-divider { + text-align: center; + color: #4a3010; + font-size: 13px; + letter-spacing: 8px; + margin: 14px 0 4px; +} + +/* ================================ + UPGRADE TAB INHALT +================================ */ + +.popup-upgrade-btn { + display: block; + width: 100%; + margin-top: 16px; + padding: 12px; + background: linear-gradient(160deg, #6a4018 0%, #3e2408 50%, #6a4018 100%); + border: 1px solid #c8960c; + border-radius: 4px; + color: #f5e090; + font-family: 'Cinzel Decorative', 'Palatino Linotype', serif; + font-size: 11px; + letter-spacing: 3px; + cursor: pointer; + transition: all 0.2s; + box-shadow: inset 0 1px 0 rgba(200,150,12,0.25), 0 0 20px rgba(200,150,12,0.11); +} + +.popup-upgrade-btn:hover { + background: linear-gradient(160deg, #8a5824 0%, #5a3410 50%, #8a5824 100%); + box-shadow: inset 0 1px 0 rgba(200,150,12,0.375), 0 0 30px rgba(200,150,12,0.2); + letter-spacing: 4px; +} diff --git a/public/js/map-ui.js b/public/js/map-ui.js index 2fb0ebe..83e7ff9 100644 --- a/public/js/map-ui.js +++ b/public/js/map-ui.js @@ -1,7 +1,6 @@ import { loadWohnhaus } from "./buildings/wohnhaus.js"; import { loadSchwarzmarkt } from "./buildings/schwarzmarkt.js"; import { loadMine } from "./buildings/mine.js"; -import { loadArena } from "./buildings/arena.js"; const popup = document.getElementById("building-popup"); const title = document.getElementById("popup-title"); const tooltip = document.getElementById("map-tooltip"); @@ -9,65 +8,14 @@ const tooltip = document.getElementById("map-tooltip"); const tooltipCache = {}; const buildingModules = { - 11: loadWohnhaus, - 12: loadSchwarzmarkt, - 10: loadMine, - 1: loadArena, + 11: loadWohnhaus, // Tabs ausblenden, eigenes UI + 12: loadSchwarzmarkt, // Tabs ausblenden, eigenes UI + 10: loadMine, // Tabs bleiben sichtbar, nur Aktionen-Tab befüllen }; +// Gebäude die ihre eigenen Tabs behalten sollen const keepTabsVisible = new Set([10]); -/* ================================ - Popup verschiebbar machen -================================ */ - -(function makeDraggable() { - const header = document.querySelector(".popup-header"); - if (!header) return; - - let isDragging = false; - let startX, startY, startLeft, startTop; - - header.style.cursor = "grab"; - - header.addEventListener("mousedown", (e) => { - // Schließen-Button nicht draggable - if (e.target.classList.contains("popup-close")) return; - - isDragging = true; - header.style.cursor = "grabbing"; - - const rect = popup.getBoundingClientRect(); - startX = e.clientX; - startY = e.clientY; - startLeft = rect.left; - startTop = rect.top; - - // transform zurücksetzen, auf konkrete px-Werte umstellen - popup.style.transform = "none"; - popup.style.left = startLeft + "px"; - popup.style.top = startTop + "px"; - - e.preventDefault(); - }); - - document.addEventListener("mousemove", (e) => { - if (!isDragging) return; - - const dx = e.clientX - startX; - const dy = e.clientY - startY; - - popup.style.left = (startLeft + dx) + "px"; - popup.style.top = (startTop + dy) + "px"; - }); - - document.addEventListener("mouseup", () => { - if (!isDragging) return; - isDragging = false; - header.style.cursor = "grab"; - }); -})(); - /* ================================ Tabs zurücksetzen ================================ */ @@ -102,7 +50,6 @@ document.querySelectorAll(".building").forEach((building) => { popup.style.left = "50%"; popup.style.top = "50%"; - popup.style.transform = "translate(-50%, -50%)"; popup.classList.add("active"); resetTabs(); @@ -116,20 +63,24 @@ document.querySelectorAll(".building").forEach((building) => { title.innerText = data.name; const infoTab = document.getElementById("tab-info"); - const actionsTab = document.getElementById("tab-actions"); const tabs = document.querySelector(".popup-tabs"); // Standard: Info anzeigen infoTab.innerHTML = ` -

${data.name}

-

Level: ${data.level}

-

Punkte: ${data.points} / ${data.nextLevelPoints}

-

${data.description}

-
-
+ + + + + + + `; // Standard Tabs anzeigen @@ -162,13 +113,11 @@ document.querySelectorAll(".building").forEach((building) => { } document.getElementById("tab-upgrade").innerHTML = ` -

Kosten: ${data.upgradeCost}

- - `; - - document.getElementById("tab-history").innerHTML = ` -

${data.history}

+ + + `; + } catch (error) { console.error("Gebäude konnte nicht geladen werden:", error); } diff --git a/views/launcher.ejs b/views/launcher.ejs index 20d6713..91d28de 100644 --- a/views/launcher.ejs +++ b/views/launcher.ejs @@ -8,13 +8,16 @@ href="/images/favicon/dok_favicon_32px.ico" type="image/x-icon" /> + + + + - @@ -245,24 +218,130 @@
+
+ + + + + + + + - + + @@ -320,44 +399,17 @@
-
- -
+ 0
-
- -
+ 💠 0
-
- -
+ 🪙 0
@@ -365,46 +417,14 @@
-
- -
+ 🪵 0
-
- -
+ 🪨 0
-
-
-
- -
- 0 -
@@ -420,11 +440,11 @@
- Kartendeck + Glücksbox
@@ -520,7 +540,7 @@
- Kartendeck + Glücksbox
@@ -643,7 +663,7 @@ const vol = document.getElementById("music-volume"); let muted = localStorage.getItem("dok_muted") === "true"; - let started = false; // ← merkt sich, ob Wiedergabe schon lief + let started = false; if (localStorage.getItem("dok_vol") !== null) vol.value = localStorage.getItem("dok_vol"); @@ -656,12 +676,7 @@ audio.src = shuffled[i]; audio.muted = muted; if (!muted) { - audio - .play() - .then(() => { - started = true; - }) - .catch(() => {}); + audio.play().then(() => { started = true; }).catch(() => {}); } } @@ -674,16 +689,9 @@ audio.muted = muted; muteBtn.textContent = muted ? "🔇" : "🔊"; localStorage.setItem("dok_muted", muted); - - // Wenn gerade nicht stumm, aber Audio pausiert → starten/fortsetzen if (!muted) { if (!audio.src) playTrack(index); - audio - .play() - .then(() => { - started = true; - }) - .catch(() => {}); + audio.play().then(() => { started = true; }).catch(() => {}); } } @@ -702,20 +710,12 @@ muteBtn.textContent = parseFloat(vol.value) === 0 ? "🔇" : "🔊"; }); - // Track laden (noch kein play() – Browser erlaubt das vor Interaktion nicht) playTrack(0); applyMute(); - // Bei JEDER Interaktion prüfen, ob Audio noch nicht läuft → nachholen - // (kein { once: true } mehr, schadet aber kaum da der Check schnell ist) function tryResume() { if (!muted && (audio.paused || !started)) { - audio - .play() - .then(() => { - started = true; - }) - .catch(() => {}); + audio.play().then(() => { started = true; }).catch(() => {}); } } document.addEventListener("click", tryResume);