- add lobby, game, leaderboard, results pages - add scripts: storage, lobby, game, drawing, scoring, countries - add styles: main, lobby, game - unify header/footer across all pages - show lobby name in lobby view - remove clear board from leaderboard
357 lines
9.6 KiB
HTML
357 lines
9.6 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>GeoDraw — Results</title>
|
||
<link rel="stylesheet" href="styles/main.css" />
|
||
<style>
|
||
.results-page {
|
||
min-height: calc(100vh - var(--hh));
|
||
display: grid;
|
||
place-items: center;
|
||
padding: 60px 0;
|
||
}
|
||
|
||
.results-inner {
|
||
width: 100%;
|
||
max-width: 680px;
|
||
display: grid;
|
||
gap: 24px;
|
||
}
|
||
|
||
.results-header {
|
||
text-align: center;
|
||
}
|
||
|
||
.results-emoji {
|
||
font-size: 3.5rem;
|
||
margin-bottom: 16px;
|
||
display: block;
|
||
animation: popIn .5s cubic-bezier(.34,1.56,.64,1) both;
|
||
}
|
||
|
||
@keyframes popIn {
|
||
from { transform: scale(0); opacity: 0; }
|
||
to { transform: scale(1); opacity: 1; }
|
||
}
|
||
|
||
.results-title {
|
||
font-family: 'Syne', sans-serif;
|
||
font-weight: 800;
|
||
font-size: clamp(2rem, 5vw, 3.4rem);
|
||
letter-spacing: -.03em;
|
||
line-height: 1.05;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.results-player {
|
||
font-size: 1rem;
|
||
color: var(--ink-soft);
|
||
}
|
||
|
||
.results-player strong { color: var(--ink); }
|
||
|
||
/* Total score */
|
||
.score-total-card {
|
||
background: linear-gradient(135deg, var(--sea) 0%, #159fd4 50%, var(--leaf) 100%);
|
||
border-radius: var(--r-xl);
|
||
padding: 36px 40px;
|
||
text-align: center;
|
||
color: var(--white);
|
||
box-shadow: 0 16px 40px rgba(26,127,196,.3);
|
||
animation: slideUp .5s .1s cubic-bezier(.34,1.56,.64,1) both;
|
||
}
|
||
|
||
@keyframes slideUp {
|
||
from { transform: translateY(30px); opacity: 0; }
|
||
to { transform: translateY(0); opacity: 1; }
|
||
}
|
||
|
||
.score-total-label {
|
||
font-size: .78rem;
|
||
font-weight: 700;
|
||
letter-spacing: .1em;
|
||
text-transform: uppercase;
|
||
opacity: .78;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.score-total-num {
|
||
font-family: 'Syne', sans-serif;
|
||
font-weight: 800;
|
||
font-size: clamp(4rem, 10vw, 6rem);
|
||
line-height: 1;
|
||
letter-spacing: -.04em;
|
||
}
|
||
|
||
.score-total-max {
|
||
font-size: 1.4rem;
|
||
opacity: .6;
|
||
font-weight: 400;
|
||
}
|
||
|
||
.score-grade {
|
||
display: inline-block;
|
||
margin-top: 12px;
|
||
padding: 4px 18px;
|
||
border-radius: 999px;
|
||
background: rgba(255,255,255,.22);
|
||
font-family: 'Syne', sans-serif;
|
||
font-weight: 800;
|
||
font-size: 1.1rem;
|
||
letter-spacing: .04em;
|
||
}
|
||
|
||
/* Round breakdown */
|
||
.rounds-card {
|
||
background: var(--white);
|
||
border: 1px solid var(--line);
|
||
border-radius: var(--r-xl);
|
||
padding: 28px 32px;
|
||
box-shadow: var(--shadow-sm);
|
||
animation: slideUp .5s .2s cubic-bezier(.34,1.56,.64,1) both;
|
||
}
|
||
|
||
.rounds-card-title {
|
||
font-family: 'Syne', sans-serif;
|
||
font-weight: 700;
|
||
font-size: 1rem;
|
||
letter-spacing: -.01em;
|
||
margin-bottom: 20px;
|
||
color: var(--ink-soft);
|
||
}
|
||
|
||
.round-rows { display: grid; gap: 14px; }
|
||
|
||
.round-row {
|
||
display: grid;
|
||
grid-template-columns: auto 1fr auto;
|
||
align-items: center;
|
||
gap: 16px;
|
||
}
|
||
|
||
.round-row__label {
|
||
font-size: .82rem;
|
||
font-weight: 600;
|
||
color: var(--ink-soft);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.round-row__bar-wrap {
|
||
height: 8px;
|
||
background: var(--cream);
|
||
border-radius: 999px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.round-row__bar {
|
||
height: 100%;
|
||
border-radius: 999px;
|
||
background: linear-gradient(90deg, var(--sea), var(--leaf));
|
||
transition: width .8s cubic-bezier(.34,1.56,.64,1);
|
||
}
|
||
|
||
.round-row__score {
|
||
font-family: 'Syne', sans-serif;
|
||
font-weight: 800;
|
||
font-size: .9rem;
|
||
color: var(--sea);
|
||
min-width: 36px;
|
||
text-align: right;
|
||
}
|
||
|
||
/* Country list */
|
||
.countries-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
margin-top: 8px;
|
||
}
|
||
|
||
.country-tag {
|
||
padding: 5px 12px;
|
||
border-radius: 999px;
|
||
background: var(--sea-dim);
|
||
color: var(--sea);
|
||
font-size: .8rem;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* Actions */
|
||
.results-actions {
|
||
display: flex;
|
||
gap: 12px;
|
||
flex-wrap: wrap;
|
||
animation: slideUp .5s .3s cubic-bezier(.34,1.56,.64,1) both;
|
||
}
|
||
|
||
.results-actions .btn { flex: 1 1 180px; }
|
||
|
||
@media (max-width: 600px) {
|
||
.results-page { padding: 40px 0; }
|
||
.score-total-card { padding: 28px 24px; }
|
||
.rounds-card { padding: 22px 20px; }
|
||
.results-actions .btn { flex-basis: 100%; }
|
||
}
|
||
|
||
@media (max-width: 360px) {
|
||
.score-total-num { font-size: 3.4rem; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wrap">
|
||
|
||
<header class="header">
|
||
<div class="container header__inner">
|
||
<a href="index.html" class="logo">
|
||
<div class="logo__mark">
|
||
<svg viewBox="0 0 24 24" fill="none">
|
||
<circle cx="12" cy="12" r="9" stroke="white" stroke-width="1.6"/>
|
||
<path d="M3 12 Q8 8 12 12 Q16 16 21 12" stroke="white" stroke-width="1.4" fill="none"/>
|
||
<path d="M12 3 Q14 8 12 12 Q10 16 12 21" stroke="white" stroke-width="1.4" fill="none"/>
|
||
</svg>
|
||
</div>
|
||
<span class="logo__text">GeoDraw</span>
|
||
</a>
|
||
<nav class="nav">
|
||
<a href="index.html" class="nav__link">Home</a>
|
||
<a href="leaderboard.html" class="nav__link">Leaderboard</a>
|
||
<a href="lobby.html" class="nav__cta">Play again →</a>
|
||
</nav>
|
||
</div>
|
||
</header>
|
||
|
||
<main>
|
||
<div class="container results-page">
|
||
<div class="results-inner">
|
||
|
||
<div class="results-header">
|
||
<span class="results-emoji" id="results-emoji">🌍</span>
|
||
<h1 class="results-title" id="results-title">Game over!</h1>
|
||
<p class="results-player">Played by <strong id="results-player">—</strong></p>
|
||
</div>
|
||
|
||
<div class="score-total-card">
|
||
<p class="score-total-label">Total Score</p>
|
||
<div class="score-total-num">
|
||
<span id="total-score">0</span><span class="score-total-max"> / 300</span>
|
||
</div>
|
||
<span class="score-grade" id="total-grade">—</span>
|
||
</div>
|
||
|
||
<div class="rounds-card">
|
||
<p class="rounds-card-title">Round breakdown</p>
|
||
<div class="round-rows" id="round-rows">
|
||
<!-- filled by JS -->
|
||
</div>
|
||
<div class="countries-row" id="countries-row"></div>
|
||
</div>
|
||
|
||
<div class="results-actions">
|
||
<a href="lobby.html" class="btn btn--primary">
|
||
Play Again →
|
||
</a>
|
||
<a href="leaderboard.html" class="btn btn--ghost">
|
||
🏆 Leaderboard
|
||
</a>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<footer class="footer">
|
||
<div class="container footer__inner">
|
||
<div>
|
||
<a href="index.html" class="footer__brand">GeoDraw</a>
|
||
<p class="footer__sub">© 2026 · Browser geography game</p>
|
||
</div>
|
||
<div class="footer__center">
|
||
<p class="footer__label">Follow us</p>
|
||
<div class="socials">
|
||
<a href="#" class="social" aria-label="Facebook">f</a>
|
||
<a href="#" class="social" aria-label="YouTube">▶</a>
|
||
<a href="#" class="social" aria-label="LinkedIn">in</a>
|
||
<a href="#" class="social" aria-label="X">𝕏</a>
|
||
</div>
|
||
</div>
|
||
<div class="footer__right">
|
||
<a href="#" class="footer__link">Impressum</a>
|
||
<a href="#" class="footer__link">Datenschutz</a>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
|
||
</div>
|
||
|
||
<script src="scripts/storage.js"></script>
|
||
<script src="scripts/scoring.js"></script>
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", () => {
|
||
const state = Storage.getGameState();
|
||
const name = Storage.getPlayerName();
|
||
|
||
document.getElementById("results-player").textContent = name;
|
||
|
||
if (!state) {
|
||
document.getElementById("results-title").textContent = "No game found.";
|
||
document.getElementById("total-score").textContent = "—";
|
||
return;
|
||
}
|
||
|
||
const { scores, totalScore, countries } = state;
|
||
|
||
// Emoji + title based on score
|
||
const avg = totalScore / 3;
|
||
let emoji = "🌍", title = "Not bad!";
|
||
if (avg >= 85) { emoji = "🔥"; title = "Incredible!"; }
|
||
else if (avg >= 70) { emoji = "🎉"; title = "Well done!"; }
|
||
else if (avg >= 50) { emoji = "👏"; title = "Good effort!"; }
|
||
else { emoji = "😅"; title = "Keep practising!"; }
|
||
|
||
document.getElementById("results-emoji").textContent = emoji;
|
||
document.getElementById("results-title").textContent = title;
|
||
document.getElementById("total-score").textContent = totalScore;
|
||
|
||
// Grade
|
||
const grade = Scoring.getGrade(avg);
|
||
const gradeEl = document.getElementById("total-grade");
|
||
gradeEl.textContent = `Grade ${grade.label}`;
|
||
|
||
// Round rows
|
||
const rowsContainer = document.getElementById("round-rows");
|
||
(scores || []).forEach((s, i) => {
|
||
const row = document.createElement("div");
|
||
row.className = "round-row";
|
||
row.innerHTML = `
|
||
<span class="round-row__label">Round ${i + 1}</span>
|
||
<div class="round-row__bar-wrap">
|
||
<div class="round-row__bar" style="width:0%" data-target="${s}"></div>
|
||
</div>
|
||
<span class="round-row__score">${s}%</span>
|
||
`;
|
||
rowsContainer.appendChild(row);
|
||
});
|
||
|
||
// Animate bars
|
||
requestAnimationFrame(() => {
|
||
document.querySelectorAll(".round-row__bar").forEach(bar => {
|
||
bar.style.width = bar.dataset.target + "%";
|
||
});
|
||
});
|
||
|
||
// Country tags
|
||
const tagsContainer = document.getElementById("countries-row");
|
||
(countries || []).forEach(c => {
|
||
const tag = document.createElement("span");
|
||
tag.className = "country-tag";
|
||
tag.textContent = c;
|
||
tagsContainer.appendChild(tag);
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|