unify nav/section copy, replace toggle links with pill switch
This commit is contained in:
parent
abf93a0848
commit
a426bad841
@ -26,9 +26,8 @@
|
||||
</a>
|
||||
|
||||
<nav class="nav" aria-label="Main navigation">
|
||||
<a href="#hero" class="nav__link">Play</a>
|
||||
<a href="#about" class="nav__link">How to play</a>
|
||||
<a href="#register" class="nav__cta">Create lobby</a>
|
||||
<a href="#register" class="nav__cta">Play</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
@ -56,7 +55,7 @@
|
||||
Start Playing
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</a>
|
||||
<a href="#about" class="btn btn--ghost">How it works</a>
|
||||
<a href="#about" class="btn btn--ghost">How to play</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -85,33 +84,57 @@
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="about" id="about">
|
||||
<div class="container about__inner">
|
||||
|
||||
<div class="about__left">
|
||||
<p class="section-label reveal">About the game</p>
|
||||
<h2 class="section-title reveal reveal-delay-1">What it is &<br>How to play</h2>
|
||||
<p class="section-label reveal">How to play</p>
|
||||
<h2 class="section-title reveal reveal-delay-1">About<br>the Game</h2>
|
||||
<p class="about__desc reveal reveal-delay-2">
|
||||
GeoDraw is a competitive browser game built on memory and precision. You get a country name, sketch its outline, and the system calculates how close you were to the real border.
|
||||
</p>
|
||||
|
||||
<div class="mini-globe-wrap reveal reveal-delay-3">
|
||||
<div class="map-outline">
|
||||
<svg viewBox="0 0 100 130" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M50 4 L78 14 L90 34 L82 56 L88 82 L62 110 L36 100 L16 76 L18 46 Z"
|
||||
fill="rgba(26,127,196,.12)"
|
||||
stroke="var(--sea)"
|
||||
stroke-width="2.5"
|
||||
stroke-linejoin="round"/>
|
||||
<path d="M50 4 L78 14 L90 34 L82 56 L88 82 L62 110 L36 100 L16 76 L18 46 Z"
|
||||
fill="none"
|
||||
stroke="var(--leaf)"
|
||||
stroke-width="1.5"
|
||||
stroke-dasharray="5 4"
|
||||
stroke-linejoin="round"
|
||||
transform="translate(4,-2) scale(0.96) translate(-2,2)"/>
|
||||
</svg>
|
||||
</div>
|
||||
<svg class="game-preview-svg" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||
<!-- Grid lines -->
|
||||
<line x1="0" y1="66" x2="200" y2="66" stroke="rgba(11,31,42,.06)" stroke-width="1"/>
|
||||
<line x1="0" y1="133" x2="200" y2="133" stroke="rgba(11,31,42,.06)" stroke-width="1"/>
|
||||
<line x1="66" y1="0" x2="66" y2="200" stroke="rgba(11,31,42,.06)" stroke-width="1"/>
|
||||
<line x1="133" y1="0" x2="133" y2="200" stroke="rgba(11,31,42,.06)" stroke-width="1"/>
|
||||
|
||||
<!-- Reference outline (filled) -->
|
||||
<path d="M100 22 L148 40 L162 76 L150 112 L124 148 L80 142 L52 108 L54 66 Z"
|
||||
fill="rgba(26,127,196,.10)"
|
||||
stroke="rgba(26,127,196,.5)"
|
||||
stroke-width="2"
|
||||
stroke-linejoin="round"/>
|
||||
|
||||
<!-- Player's drawn path (slightly off, freehand feel) -->
|
||||
<path d="M96 26 L152 44 L164 82 L146 118 L120 152 L76 144 L48 106 L52 62 Z"
|
||||
fill="none"
|
||||
stroke="#1a7fc4"
|
||||
stroke-width="2.5"
|
||||
stroke-linejoin="round"
|
||||
stroke-linecap="round"/>
|
||||
|
||||
<!-- City dot: Bern -->
|
||||
<circle cx="96" cy="100" r="4" fill="rgba(240,180,40,.9)"/>
|
||||
<circle cx="96" cy="100" r="4" fill="none" stroke="white" stroke-width="1.5"/>
|
||||
<!-- City dot: Zurich -->
|
||||
<circle cx="118" cy="72" r="4" fill="rgba(240,180,40,.9)"/>
|
||||
<circle cx="118" cy="72" r="4" fill="none" stroke="white" stroke-width="1.5"/>
|
||||
|
||||
<!-- Score badge -->
|
||||
<rect x="118" y="22" width="62" height="26" rx="8" fill="white" filter="url(#shadow)"/>
|
||||
<defs>
|
||||
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="rgba(11,31,42,.12)"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="131" cy="35" r="4" fill="#41b869"/>
|
||||
<text x="139" y="39" font-family="Syne, sans-serif" font-weight="700" font-size="11" fill="#0b1f2a">82%</text>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -149,31 +172,53 @@
|
||||
<div class="container register__inner">
|
||||
|
||||
<div class="register__intro reveal">
|
||||
<p class="section-label">Join the game</p>
|
||||
<h2 class="section-title">Create your<br>lobby</h2>
|
||||
<p class="section-label">Play</p>
|
||||
<h2 class="section-title">Create or join<br>a lobby</h2>
|
||||
<p class="register__desc">
|
||||
Create a private lobby to challenge friends or play solo.
|
||||
Create your own lobby and share the name with friends, or enter an existing lobby name to join their game.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="register__card reveal reveal-delay-1">
|
||||
<p class="card-title">Create a game</p>
|
||||
|
||||
<form class="form">
|
||||
<div class="field">
|
||||
<label for="username">Lobby name</label>
|
||||
<input id="username" type="text" placeholder="myLobby" />
|
||||
<!-- Toggle switch -->
|
||||
<div class="lobby-toggle" role="group" aria-label="Lobby action">
|
||||
<button type="button" class="lobby-toggle__btn lobby-toggle__btn--active" id="toggle-create-btn">Create</button>
|
||||
<button type="button" class="lobby-toggle__btn" id="toggle-join-btn">Join</button>
|
||||
</div>
|
||||
|
||||
<!-- Create form (shown by default) -->
|
||||
<div id="form-create">
|
||||
<p class="card-title">Create a game</p>
|
||||
<div class="form">
|
||||
<div class="field">
|
||||
<label for="lobby-create">Lobby name</label>
|
||||
<input id="lobby-create" type="text" placeholder="myLobby" />
|
||||
</div>
|
||||
<button type="button" class="btn btn--primary btn--full" id="reg-btn">
|
||||
Create game
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</button>
|
||||
<span class="field-error" id="lobby-error" role="alert"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn--primary btn--full" id="reg-btn">
|
||||
Create game
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</button>
|
||||
<!-- Join form (hidden by default) -->
|
||||
<div id="form-join" hidden>
|
||||
<p class="card-title">Join a game</p>
|
||||
<div class="form">
|
||||
<div class="field">
|
||||
<label for="lobby-join">Lobby name</label>
|
||||
<input id="lobby-join" type="text" placeholder="myLobby" />
|
||||
</div>
|
||||
<button type="button" class="btn btn--primary btn--full" id="join-btn">
|
||||
Join game
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</button>
|
||||
<span class="field-error" id="join-error" role="alert"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="field-error" id="lobby-error" role="alert"></span>
|
||||
|
||||
<p class="form-footer"><a href="#" style="color:var(--sea);font-weight:600;">Join a game instead</a></p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -185,7 +230,6 @@
|
||||
<div class="container footer__inner">
|
||||
|
||||
<div class="footer__left">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="footer__center">
|
||||
|
||||
@ -3,44 +3,83 @@
|
||||
import { createLobby } from "./api.js";
|
||||
import { saveLobbyName } from "./storage.js";
|
||||
|
||||
/**
|
||||
* Handle the "Create game" button click.
|
||||
* Validates the lobby name, persists it, and navigates to the lobby page.
|
||||
*/
|
||||
document.getElementById("reg-btn")?.addEventListener("click", async () => {
|
||||
const lobbyInput = /** @type {HTMLInputElement|null} */ (
|
||||
document.getElementById("username")
|
||||
);
|
||||
const button = /** @type {HTMLButtonElement|null} */ (
|
||||
document.getElementById("reg-btn")
|
||||
);
|
||||
const lobbyName = lobbyInput ? lobbyInput.value.trim() : "";
|
||||
// ── DOM refs
|
||||
const formCreate = document.getElementById("form-create");
|
||||
const formJoin = document.getElementById("form-join");
|
||||
const createInput = /** @type {HTMLInputElement|null} */ (document.getElementById("lobby-create"));
|
||||
const joinInput = /** @type {HTMLInputElement|null} */ (document.getElementById("lobby-join"));
|
||||
const createBtn = /** @type {HTMLButtonElement|null} */ (document.getElementById("reg-btn"));
|
||||
const joinBtn = /** @type {HTMLButtonElement|null} */ (document.getElementById("join-btn"));
|
||||
const createError = document.getElementById("lobby-error");
|
||||
const joinError = document.getElementById("join-error");
|
||||
const toggleCreateBtn = /** @type {HTMLButtonElement|null} */ (document.getElementById("toggle-create-btn"));
|
||||
const toggleJoinBtn = /** @type {HTMLButtonElement|null} */ (document.getElementById("toggle-join-btn"));
|
||||
|
||||
// ── Toggle switch
|
||||
function showCreate() {
|
||||
formCreate?.removeAttribute("hidden");
|
||||
formJoin?.setAttribute("hidden", "");
|
||||
toggleCreateBtn?.classList.add("lobby-toggle__btn--active");
|
||||
toggleJoinBtn?.classList.remove("lobby-toggle__btn--active");
|
||||
createInput?.focus();
|
||||
}
|
||||
|
||||
function showJoin() {
|
||||
formJoin?.removeAttribute("hidden");
|
||||
formCreate?.setAttribute("hidden", "");
|
||||
toggleJoinBtn?.classList.add("lobby-toggle__btn--active");
|
||||
toggleCreateBtn?.classList.remove("lobby-toggle__btn--active");
|
||||
joinInput?.focus();
|
||||
}
|
||||
|
||||
toggleCreateBtn?.addEventListener("click", showCreate);
|
||||
toggleJoinBtn?.addEventListener("click", showJoin);
|
||||
|
||||
// ── Create lobby
|
||||
createBtn?.addEventListener("click", async () => {
|
||||
if (!createInput || !createError) return;
|
||||
|
||||
const lobbyName = createInput.value.trim();
|
||||
createError.textContent = "";
|
||||
|
||||
if (!lobbyName) {
|
||||
lobbyInput?.focus();
|
||||
createInput.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
const errorEl = /** @type {HTMLElement|null} */ (
|
||||
document.getElementById("lobby-error")
|
||||
);
|
||||
if (errorEl) errorEl.textContent = "";
|
||||
|
||||
try {
|
||||
if (button) button.disabled = true;
|
||||
createBtn.disabled = true;
|
||||
await createLobby(lobbyName);
|
||||
saveLobbyName(lobbyName);
|
||||
window.location.href = "lobby.html";
|
||||
} catch (error) {
|
||||
if (errorEl)
|
||||
errorEl.textContent =
|
||||
error instanceof Error ? error.message : "Could not create lobby.";
|
||||
if (button) button.disabled = false;
|
||||
createError.textContent =
|
||||
error instanceof Error ? error.message : "Could not create lobby.";
|
||||
createBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Scroll reveal - animate elements into view as they enter the viewport
|
||||
const reveals = document.querySelectorAll(".reveal");
|
||||
// ── Join lobby — actual joinLobby() API call happens in lobby.js
|
||||
joinBtn?.addEventListener("click", () => {
|
||||
if (!joinInput || !joinError) return;
|
||||
|
||||
const lobbyName = joinInput.value.trim();
|
||||
joinError.textContent = "";
|
||||
|
||||
if (!lobbyName) {
|
||||
joinInput.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
saveLobbyName(lobbyName);
|
||||
window.location.href = "lobby.html";
|
||||
});
|
||||
|
||||
// Allow Enter key on both inputs
|
||||
createInput?.addEventListener("keydown", (e) => { if (e.key === "Enter") createBtn?.click(); });
|
||||
joinInput?.addEventListener("keydown", (e) => { if (e.key === "Enter") joinBtn?.click(); });
|
||||
|
||||
// ── Scroll reveal
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
@ -53,6 +92,4 @@ const observer = new IntersectionObserver(
|
||||
{ threshold: 0.12 },
|
||||
);
|
||||
|
||||
reveals.forEach((el) => {
|
||||
observer.observe(el);
|
||||
});
|
||||
document.querySelectorAll(".reveal").forEach((el) => observer.observe(el));
|
||||
|
||||
@ -297,6 +297,13 @@
|
||||
);
|
||||
}
|
||||
|
||||
.game-preview-svg {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* ─── STEPS ─── */
|
||||
.steps {
|
||||
display: grid;
|
||||
@ -394,6 +401,36 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ─── LOBBY TOGGLE SWITCH ─── */
|
||||
.lobby-toggle {
|
||||
display: flex;
|
||||
background: var(--cream);
|
||||
border: 1.5px solid var(--line);
|
||||
border-radius: 999px;
|
||||
padding: 4px;
|
||||
gap: 4px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.lobby-toggle__btn {
|
||||
flex: 1;
|
||||
padding: 9px 16px;
|
||||
border-radius: 999px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-family: "Syne", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 0.88rem;
|
||||
color: var(--ink-muted);
|
||||
cursor: pointer;
|
||||
transition: background 0.18s, color 0.18s;
|
||||
}
|
||||
|
||||
.lobby-toggle__btn--active {
|
||||
background: var(--ink);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
/* ─── RESPONSIVE ─── */
|
||||
@media (max-width: 960px) {
|
||||
.hero__inner,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user