feat: design mockup preview site

This commit is contained in:
PM
2026-05-01 19:53:26 +00:00
commit ccc1664914
12 changed files with 2691 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY index.html /usr/share/nginx/html/index.html
COPY designs /usr/share/nginx/html/designs
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost/ >/dev/null || exit 1
+5
View File
@@ -0,0 +1,5 @@
# DrawTogether — Design Mockups
Static preview of design mockups for the DrawTogether 3-in-1 game (Skribbl + Gartic Phone + Color Together).
These are HTML/CSS mockups. The live application build is in progress in a separate repo.
+285
View File
@@ -0,0 +1,285 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DrawTogether - Play Together, Draw Together</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--yellow: #FFD23F;
--coral: #FF5C5C;
--mint: #4ECDC4;
--lavender: #A593E0;
--sky: #5BCEFA;
--dark: #2D2D2D;
--cream: #FFF8E7;
--white: #FFFFFF;
--shadow-card: 0 6px 0 rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);
--shadow-btn: 0 5px 0 rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.12);
}
html, body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--dark); background: var(--cream); -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; overflow-x: hidden; }
/* Header */
.site-header {
display: flex; align-items: center; justify-content: space-between;
padding: 20px 32px; max-width: 1280px; margin: 0 auto;
}
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 24px; letter-spacing: 0.5px; }
.logo-mark {
width: 44px; height: 44px; border-radius: 14px; background: var(--coral);
display: grid; place-items: center; box-shadow: var(--shadow-card); transform: rotate(-6deg);
}
.nav-actions { display: flex; gap: 12px; align-items: center; }
.nav-link { font-weight: 600; color: var(--dark); text-decoration: none; padding: 8px 16px; border-radius: 999px; }
.nav-link:hover { background: rgba(255,210,63,0.4); }
/* Hero */
.hero {
max-width: 1280px; margin: 0 auto; padding: 40px 32px 60px;
display: grid; grid-template-columns: 1.1fr 1fr; gap: 40px; align-items: center;
}
.hero-eyebrow {
display: inline-flex; align-items: center; gap: 8px;
background: var(--white); padding: 8px 16px; border-radius: 999px;
font-weight: 600; font-size: 14px; box-shadow: var(--shadow-card);
border: 2px solid var(--dark); margin-bottom: 20px;
}
.hero-eyebrow .dot { width: 10px; height: 10px; background: var(--mint); border-radius: 50%; }
.hero h1 {
font-size: clamp(40px, 6vw, 72px); font-weight: 700; line-height: 1.05;
letter-spacing: -0.5px; margin-bottom: 20px;
}
.hero h1 .accent { color: var(--coral); position: relative; display: inline-block; }
.hero h1 .accent::after {
content: ''; position: absolute; bottom: 4px; left: 0; right: 0; height: 14px;
background: var(--yellow); z-index: -1; border-radius: 8px;
}
.hero p.lead { font-size: 18px; line-height: 1.5; max-width: 480px; margin-bottom: 32px; font-weight: 500; }
.hero-ctas { display: flex; gap: 16px; flex-wrap: wrap; }
.btn {
font-family: inherit; font-weight: 700; font-size: 18px;
padding: 18px 32px; border-radius: 999px; border: 3px solid var(--dark);
cursor: pointer; box-shadow: var(--shadow-btn); transition: transform 0.15s ease, box-shadow 0.15s ease;
display: inline-flex; align-items: center; gap: 10px; letter-spacing: 0.3px;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 7px 0 rgba(0,0,0,0.18), 0 4px 10px rgba(0,0,0,0.14); }
.btn:active { transform: translateY(2px); box-shadow: 0 2px 0 rgba(0,0,0,0.18); }
.btn-primary { background: var(--coral); color: var(--white); }
.btn-secondary { background: var(--mint); color: var(--dark); }
.btn-ghost { background: var(--white); color: var(--dark); }
/* Hero illustration */
.hero-art { position: relative; min-height: 420px; }
.canvas-prop {
position: absolute; inset: 0; background: var(--white); border: 3px solid var(--dark);
border-radius: 28px; box-shadow: var(--shadow-card); padding: 24px;
display: flex; flex-direction: column; gap: 12px;
}
.canvas-top { display: flex; gap: 6px; }
.canvas-top span { width: 12px; height: 12px; border-radius: 50%; background: #e6e6e6; }
.canvas-top span:nth-child(1) { background: var(--coral); }
.canvas-top span:nth-child(2) { background: var(--yellow); }
.canvas-top span:nth-child(3) { background: var(--mint); }
.canvas-svg { flex: 1; display: grid; place-items: center; }
.float-tag {
position: absolute; padding: 10px 16px; border-radius: 999px; background: var(--white);
font-weight: 700; font-size: 14px; border: 3px solid var(--dark); box-shadow: var(--shadow-card);
display: flex; align-items: center; gap: 8px;
}
.float-tag.t1 { top: -14px; left: -10px; background: var(--yellow); animation: float 3.5s ease-in-out infinite; }
.float-tag.t2 { top: 30%; right: -30px; background: var(--lavender); color: var(--white); animation: float 3.5s ease-in-out infinite 0.8s; }
.float-tag.t3 { bottom: 10px; left: -22px; background: var(--sky); animation: float 3.5s ease-in-out infinite 1.6s; }
@keyframes float { 0%, 100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-8px) rotate(2deg); } }
/* Modes */
.modes { max-width: 1280px; margin: 0 auto; padding: 40px 32px 80px; }
.modes-title { text-align: center; margin-bottom: 40px; }
.modes-title h2 { font-size: clamp(28px, 4vw, 44px); font-weight: 700; }
.modes-title p { color: rgba(45,45,45,0.7); font-weight: 500; margin-top: 10px; font-size: 18px; }
.mode-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.mode-card {
background: var(--white); border: 3px solid var(--dark); border-radius: 24px;
padding: 28px; box-shadow: var(--shadow-card);
display: flex; flex-direction: column; gap: 16px;
transition: transform 0.2s ease;
position: relative; overflow: hidden;
}
.mode-card:hover { transform: translateY(-6px); }
.mode-card .ribbon {
position: absolute; top: 16px; right: -28px; transform: rotate(35deg);
background: var(--yellow); padding: 4px 32px; font-size: 12px; font-weight: 700;
border-top: 2px solid var(--dark); border-bottom: 2px solid var(--dark);
}
.mode-icon {
width: 72px; height: 72px; border-radius: 20px; display: grid; place-items: center;
border: 3px solid var(--dark); box-shadow: 0 4px 0 rgba(0,0,0,0.15);
}
.mode-icon.skribbl { background: var(--coral); }
.mode-icon.gartic { background: var(--mint); }
.mode-icon.color { background: var(--lavender); }
.mode-card h3 { font-size: 24px; font-weight: 700; }
.mode-card p { font-size: 15px; line-height: 1.5; color: rgba(45,45,45,0.75); font-weight: 500; }
.mode-tag { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; padding: 6px 12px; background: var(--cream); border-radius: 999px; align-self: flex-start; }
/* Footer */
.site-footer {
background: var(--dark); color: var(--cream); padding: 36px 32px;
border-top-left-radius: 32px; border-top-right-radius: 32px;
}
.footer-inner { max-width: 1280px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px; }
.footer-inner .logo { color: var(--cream); }
.footer-inner .logo-mark { background: var(--yellow); }
.footer-links { display: flex; gap: 24px; }
.footer-links a { color: var(--cream); text-decoration: none; font-weight: 500; opacity: 0.8; }
.footer-links a:hover { opacity: 1; }
.copyright { font-size: 14px; opacity: 0.65; }
@media (max-width: 900px) {
.hero { grid-template-columns: 1fr; padding-bottom: 40px; }
.hero-art { min-height: 320px; max-width: 420px; margin: 0 auto; width: 100%; }
.mode-grid { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
.site-header { padding: 16px; }
.nav-link { display: none; }
.hero { padding: 24px 16px 32px; }
.modes { padding: 24px 16px 60px; }
.btn { padding: 14px 22px; font-size: 16px; }
.hero-eyebrow { font-size: 12px; }
}
</style>
</head>
<body>
<header class="site-header">
<div class="logo">
<div class="logo-mark">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/><circle cx="6" cy="6" r="2"/></svg>
</div>
DrawTogether
</div>
<nav class="nav-actions">
<a href="#modes" class="nav-link">Modes</a>
<a href="#how" class="nav-link">How it Works</a>
<a href="03-join-room.html" class="btn btn-ghost" style="padding: 10px 20px; font-size: 15px;" data-testid="nav-join">Join Room</a>
</nav>
</header>
<section class="hero">
<div class="hero-text">
<div class="hero-eyebrow"><span class="dot"></span> Live now: 2,418 players drawing together</div>
<h1>Draw, guess &amp; <span class="accent">color</span> with friends</h1>
<p class="lead">Three games, one playful canvas. Race to guess in Skribbl, pass silly drawings in Gartic Phone, or chill out coloring together. No installs. Just doodle.</p>
<div class="hero-ctas">
<a href="02-create-room.html" class="btn btn-primary" data-testid="cta-create-room">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
Create Room
</a>
<a href="03-join-room.html" class="btn btn-secondary" data-testid="cta-join-room">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M15 12H3"/></svg>
Join Room
</a>
</div>
</div>
<div class="hero-art">
<div class="canvas-prop">
<div class="canvas-top"><span></span><span></span><span></span></div>
<div class="canvas-svg">
<svg width="100%" height="100%" viewBox="0 0 320 280" preserveAspectRatio="xMidYMid meet">
<!-- cat doodle -->
<ellipse cx="160" cy="200" rx="90" ry="50" fill="#FFD23F" stroke="#2D2D2D" stroke-width="4"/>
<circle cx="160" cy="130" r="65" fill="#FFD23F" stroke="#2D2D2D" stroke-width="4"/>
<polygon points="105,90 95,40 145,80" fill="#FFD23F" stroke="#2D2D2D" stroke-width="4" stroke-linejoin="round"/>
<polygon points="215,90 225,40 175,80" fill="#FFD23F" stroke="#2D2D2D" stroke-width="4" stroke-linejoin="round"/>
<circle cx="138" cy="125" r="8" fill="#2D2D2D"/>
<circle cx="182" cy="125" r="8" fill="#2D2D2D"/>
<circle cx="141" cy="122" r="3" fill="white"/>
<circle cx="185" cy="122" r="3" fill="white"/>
<path d="M150 150 Q160 158 170 150" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<path d="M150 155 Q145 170 155 175" stroke="#2D2D2D" stroke-width="3" fill="none" stroke-linecap="round"/>
<path d="M170 155 Q175 170 165 175" stroke="#2D2D2D" stroke-width="3" fill="none" stroke-linecap="round"/>
<line x1="105" y1="135" x2="80" y2="130" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<line x1="105" y1="142" x2="80" y2="145" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<line x1="215" y1="135" x2="240" y2="130" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<line x1="215" y1="142" x2="240" y2="145" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<!-- pencil cursor -->
<g transform="translate(230,180) rotate(35)">
<rect x="0" y="0" width="50" height="14" rx="3" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="3"/>
<polygon points="50,0 60,7 50,14" fill="#FFD23F" stroke="#2D2D2D" stroke-width="3" stroke-linejoin="round"/>
<polygon points="60,7 65,5 65,9" fill="#2D2D2D"/>
</g>
</svg>
</div>
</div>
<div class="float-tag t1">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg>
Mia guessed it!
</div>
<div class="float-tag t2">+120 pts</div>
<div class="float-tag t3">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
47s
</div>
</div>
</section>
<section class="modes" id="modes">
<div class="modes-title">
<h2>Three ways to play</h2>
<p>Pick a mode, invite your crew, get drawing</p>
</div>
<div class="mode-grid">
<article class="mode-card" data-testid="mode-card-skribbl">
<div class="ribbon">CLASSIC</div>
<div class="mode-icon skribbl">
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
</div>
<span class="mode-tag">2-12 players</span>
<h3>Skribbl Race</h3>
<p>One player draws a secret word, everyone else races to guess. Fast, chaotic, hilarious.</p>
</article>
<article class="mode-card" data-testid="mode-card-gartic">
<div class="mode-icon gartic">
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/><path d="M8 9h8M8 13h5"/></svg>
</div>
<span class="mode-tag">4-10 players</span>
<h3>Gartic Phone</h3>
<p>Telephone-game with drawings. Write a prompt, draw what you got, guess what they drew.</p>
</article>
<article class="mode-card" data-testid="mode-card-color">
<div class="ribbon">CHILL</div>
<div class="mode-icon color">
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="13.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="10.5" r="2.5"/><circle cx="8.5" cy="7.5" r="2.5"/><circle cx="6.5" cy="12.5" r="2.5"/><path d="M12 22a10 10 0 1 1 10-10c0 4-3 4-4 4h-3a2 2 0 0 0-1 4 2 2 0 0 1-1 4z"/></svg>
</div>
<span class="mode-tag">2-6 players</span>
<h3>Color Together</h3>
<p>A shared coloring book. Pick a canvas, fill it in together. Snapshot &amp; save your art.</p>
</article>
</div>
</section>
<footer class="site-footer">
<div class="footer-inner">
<div class="logo">
<div class="logo-mark">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
</div>
DrawTogether
</div>
<nav class="footer-links">
<a href="#">About</a>
<a href="#">Privacy</a>
<a href="#">Discord</a>
<a href="#">GitHub</a>
</nav>
<div class="copyright">© 2026 DrawTogether</div>
</div>
</footer>
</body>
</html>
+273
View File
@@ -0,0 +1,273 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Create Room - DrawTogether</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--yellow: #FFD23F; --coral: #FF5C5C; --mint: #4ECDC4;
--lavender: #A593E0; --sky: #5BCEFA; --dark: #2D2D2D;
--cream: #FFF8E7; --white: #FFFFFF;
--shadow-card: 0 6px 0 rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);
--shadow-btn: 0 5px 0 rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.12);
}
html, body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--dark); background: var(--cream); -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; }
.site-header { display: flex; align-items: center; justify-content: space-between; padding: 20px 32px; max-width: 1280px; margin: 0 auto; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 24px; text-decoration: none; color: inherit; }
.logo-mark { width: 44px; height: 44px; border-radius: 14px; background: var(--coral); display: grid; place-items: center; box-shadow: var(--shadow-card); transform: rotate(-6deg); }
.back-link { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; text-decoration: none; color: var(--dark); padding: 10px 16px; border-radius: 999px; }
.back-link:hover { background: var(--white); }
main { max-width: 980px; margin: 0 auto; padding: 24px 32px 80px; }
.page-title { text-align: center; margin-bottom: 32px; }
.page-title h1 { font-size: clamp(32px, 5vw, 48px); font-weight: 700; letter-spacing: -0.5px; }
.page-title .accent-bg { background: var(--yellow); padding: 0 12px; border-radius: 10px; display: inline-block; transform: rotate(-1deg); }
.page-title p { margin-top: 12px; font-weight: 500; color: rgba(45,45,45,0.7); font-size: 17px; }
.step-label { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; font-size: 14px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--coral); margin-bottom: 16px; }
.step-num { width: 26px; height: 26px; border-radius: 50%; background: var(--coral); color: white; display: grid; place-items: center; font-size: 14px; }
/* Mode picker */
.mode-picker { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 36px; }
.mode-radio { position: relative; cursor: pointer; }
.mode-radio input { position: absolute; opacity: 0; pointer-events: none; }
.mode-radio .card {
background: var(--white); border: 3px solid var(--dark); border-radius: 22px;
padding: 22px; box-shadow: var(--shadow-card); display: flex; flex-direction: column; gap: 12px;
transition: all 0.18s ease; height: 100%;
}
.mode-radio:hover .card { transform: translateY(-3px); }
.mode-radio input:checked + .card { background: var(--yellow); transform: translateY(-4px); }
.mode-radio input:checked + .card .check { opacity: 1; transform: scale(1); }
.mode-radio .icon { width: 56px; height: 56px; border-radius: 16px; display: grid; place-items: center; border: 3px solid var(--dark); box-shadow: 0 3px 0 rgba(0,0,0,0.15); }
.mode-radio .icon.s { background: var(--coral); }
.mode-radio .icon.g { background: var(--mint); }
.mode-radio .icon.c { background: var(--lavender); }
.mode-radio h3 { font-size: 18px; font-weight: 700; }
.mode-radio p { font-size: 13px; color: rgba(45,45,45,0.7); font-weight: 500; line-height: 1.4; }
.mode-radio .check {
position: absolute; top: 14px; right: 14px; width: 32px; height: 32px;
background: var(--coral); border: 3px solid var(--dark); border-radius: 50%;
display: grid; place-items: center; opacity: 0; transform: scale(0.5);
transition: all 0.2s ease;
}
/* Settings card */
.settings {
background: var(--white); border: 3px solid var(--dark); border-radius: 24px;
padding: 28px; box-shadow: var(--shadow-card); margin-bottom: 28px;
}
.settings h2 { font-size: 22px; font-weight: 700; margin-bottom: 20px; display: flex; align-items: center; gap: 10px; }
.settings h2 .icon-pill { width: 32px; height: 32px; background: var(--mint); border: 3px solid var(--dark); border-radius: 10px; display: grid; place-items: center; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.field { display: flex; flex-direction: column; gap: 8px; }
.field label { font-weight: 600; font-size: 15px; }
.field .hint { font-size: 12px; color: rgba(45,45,45,0.55); font-weight: 500; }
.input, .select {
font-family: inherit; font-size: 16px; font-weight: 500;
padding: 12px 16px; border: 3px solid var(--dark); border-radius: 14px;
background: var(--cream); color: var(--dark); outline: none; transition: all 0.15s ease;
width: 100%;
}
.input:focus, .select:focus { border-color: var(--coral); background: var(--white); transform: translateY(-1px); }
/* Slider-like row */
.stepper {
display: flex; align-items: center; justify-content: space-between;
padding: 6px; background: var(--cream); border: 3px solid var(--dark); border-radius: 14px;
}
.stepper button {
width: 36px; height: 36px; border-radius: 10px; border: 2px solid var(--dark);
background: var(--white); font-family: inherit; font-weight: 700; font-size: 18px;
cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.15);
}
.stepper .value { font-weight: 700; font-size: 20px; }
/* Pill selector */
.pill-group { display: flex; gap: 8px; flex-wrap: wrap; }
.pill {
padding: 10px 18px; border: 3px solid var(--dark); border-radius: 999px;
background: var(--white); font-family: inherit; font-weight: 600; font-size: 14px;
cursor: pointer; transition: all 0.15s ease;
}
.pill:hover { transform: translateY(-2px); }
.pill.active { background: var(--coral); color: white; }
.toggle-row { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; background: var(--cream); border-radius: 14px; border: 2px dashed rgba(45,45,45,0.2); }
.toggle-row .lbl { font-weight: 600; font-size: 15px; }
.toggle-row .desc { font-size: 13px; color: rgba(45,45,45,0.6); font-weight: 500; }
.switch { position: relative; width: 52px; height: 30px; background: var(--white); border: 3px solid var(--dark); border-radius: 999px; cursor: pointer; }
.switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; background: var(--dark); border-radius: 50%; transition: all 0.2s ease; }
.switch.on { background: var(--mint); }
.switch.on::after { left: 26px; }
/* CTA */
.cta-row { display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; padding: 0 8px; }
.privacy-note { font-size: 14px; font-weight: 500; color: rgba(45,45,45,0.6); display: flex; align-items: center; gap: 8px; }
.btn { font-family: inherit; font-weight: 700; font-size: 18px; padding: 18px 36px; border-radius: 999px; border: 3px solid var(--dark); cursor: pointer; box-shadow: var(--shadow-btn); transition: transform 0.15s ease; display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.btn:hover { transform: translateY(-2px); }
.btn-primary { background: var(--coral); color: white; }
@media (max-width: 768px) {
.mode-picker { grid-template-columns: 1fr; }
.grid-2 { grid-template-columns: 1fr; }
main { padding: 16px; }
.cta-row { flex-direction: column; }
.btn { width: 100%; justify-content: center; }
}
</style>
</head>
<body>
<header class="site-header">
<a class="logo" href="01-landing.html">
<div class="logo-mark">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
</div>
DrawTogether
</a>
<a href="01-landing.html" class="back-link">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
Back home
</a>
</header>
<main>
<div class="page-title">
<h1>Spin up a <span class="accent-bg">new room</span></h1>
<p>Pick a mode, tweak the rules, and grab your invite link in 30 seconds.</p>
</div>
<div class="step-label"><span class="step-num">1</span> Choose your mode</div>
<div class="mode-picker" data-testid="mode-picker">
<label class="mode-radio">
<input type="radio" name="mode" value="skribbl" checked data-testid="mode-skribbl">
<div class="card">
<div class="icon s"><svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg></div>
<h3>Skribbl Race</h3>
<p>One drawer, everyone guesses. Fastest correct guess wins.</p>
<div class="check"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg></div>
</div>
</label>
<label class="mode-radio">
<input type="radio" name="mode" value="gartic" data-testid="mode-gartic">
<div class="card">
<div class="icon g"><svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></div>
<h3>Gartic Phone</h3>
<p>Pass-and-draw chaos. Hilarious final reveal.</p>
<div class="check"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg></div>
</div>
</label>
<label class="mode-radio">
<input type="radio" name="mode" value="color" data-testid="mode-color">
<div class="card">
<div class="icon c"><svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><circle cx="13.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="10.5" r="2.5"/><circle cx="8.5" cy="7.5" r="2.5"/><circle cx="6.5" cy="12.5" r="2.5"/><path d="M12 22a10 10 0 1 1 10-10c0 4-3 4-4 4h-3a2 2 0 0 0-1 4 2 2 0 0 1-1 4z"/></svg></div>
<h3>Color Together</h3>
<p>Shared coloring book. Calm, chill, beautiful.</p>
<div class="check"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg></div>
</div>
</label>
</div>
<div class="step-label"><span class="step-num">2</span> Game settings</div>
<section class="settings">
<h2>
<span class="icon-pill"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>
Rules &amp; preferences
</h2>
<div class="grid-2">
<div class="field">
<label>Number of rounds</label>
<div class="stepper" data-testid="stepper-rounds">
<button type="button" aria-label="decrease"></button>
<div class="value">5</div>
<button type="button" aria-label="increase">+</button>
</div>
<span class="hint">Each round, every player gets one drawing turn.</span>
</div>
<div class="field">
<label>Time per drawing</label>
<div class="pill-group" data-testid="pills-time">
<button class="pill" type="button">30s</button>
<button class="pill active" type="button">60s</button>
<button class="pill" type="button">90s</button>
<button class="pill" type="button">120s</button>
</div>
<span class="hint">Drawer's time to sketch the prompt.</span>
</div>
<div class="field">
<label>Max players</label>
<div class="stepper" data-testid="stepper-players">
<button type="button"></button>
<div class="value">8</div>
<button type="button">+</button>
</div>
<span class="hint">2 minimum, 12 maximum.</span>
</div>
<div class="field">
<label>Word language (Skribbl)</label>
<select class="select" data-testid="select-language">
<option>English</option>
<option>Español</option>
<option>Français</option>
<option>Deutsch</option>
<option>हिन्दी</option>
<option>日本語</option>
</select>
<span class="hint">Word bank used for prompts.</span>
</div>
<div class="field" style="grid-column: 1 / -1;">
<label>Canvas type (Color mode)</label>
<div class="pill-group" data-testid="pills-canvas">
<button class="pill active" type="button">Mandala</button>
<button class="pill" type="button">Animals</button>
<button class="pill" type="button">Botanical</button>
<button class="pill" type="button">Patterns</button>
<button class="pill" type="button">Blank</button>
</div>
<span class="hint">Pick a base illustration for collaborative coloring.</span>
</div>
</div>
<div style="margin-top: 22px; display: flex; flex-direction: column; gap: 10px;">
<div class="toggle-row">
<div>
<div class="lbl">Private room</div>
<div class="desc">Only people with the link can join.</div>
</div>
<div class="switch on" data-testid="toggle-private"></div>
</div>
<div class="toggle-row">
<div>
<div class="lbl">Custom word list</div>
<div class="desc">Add your own words separated by commas.</div>
</div>
<div class="switch" data-testid="toggle-custom-words"></div>
</div>
</div>
</section>
<div class="cta-row">
<div class="privacy-note">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
No account needed. Anyone with the link can join.
</div>
<a href="04-lobby.html" class="btn btn-primary" data-testid="btn-create">
Create Room
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
</a>
</div>
</main>
</body>
</html>
+168
View File
@@ -0,0 +1,168 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Join Room - DrawTogether</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--yellow: #FFD23F; --coral: #FF5C5C; --mint: #4ECDC4;
--lavender: #A593E0; --sky: #5BCEFA; --dark: #2D2D2D;
--cream: #FFF8E7; --white: #FFFFFF;
--shadow-card: 0 6px 0 rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);
--shadow-btn: 0 5px 0 rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.12);
}
html, body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--dark); background: var(--cream); -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; position: relative; overflow-x: hidden; }
/* Decorative doodles */
.doodle { position: absolute; pointer-events: none; opacity: 0.85; }
.doodle.d1 { top: 60px; left: 50px; animation: drift 6s ease-in-out infinite; }
.doodle.d2 { top: 120px; right: 80px; animation: drift 6s ease-in-out infinite 1s; }
.doodle.d3 { bottom: 80px; left: 100px; animation: drift 6s ease-in-out infinite 2s; }
.doodle.d4 { bottom: 60px; right: 60px; animation: drift 6s ease-in-out infinite 3s; }
@keyframes drift { 0%, 100% { transform: translateY(0) rotate(-5deg); } 50% { transform: translateY(-12px) rotate(5deg); } }
.site-header { display: flex; align-items: center; justify-content: space-between; padding: 20px 32px; max-width: 1280px; margin: 0 auto; position: relative; z-index: 2; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 24px; text-decoration: none; color: inherit; }
.logo-mark { width: 44px; height: 44px; border-radius: 14px; background: var(--coral); display: grid; place-items: center; box-shadow: var(--shadow-card); transform: rotate(-6deg); }
.back-link { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; text-decoration: none; color: var(--dark); padding: 10px 16px; border-radius: 999px; }
.back-link:hover { background: var(--white); }
main { max-width: 480px; margin: 30px auto; padding: 24px 24px 80px; position: relative; z-index: 2; }
.card {
background: var(--white); border: 3px solid var(--dark); border-radius: 28px;
padding: 36px 32px; box-shadow: 0 10px 0 rgba(0,0,0,0.12), 0 4px 14px rgba(0,0,0,0.1);
}
.card-header { text-align: center; margin-bottom: 26px; }
.card-header h1 { font-size: 32px; font-weight: 700; letter-spacing: -0.5px; margin-bottom: 6px; }
.card-header p { font-size: 15px; font-weight: 500; color: rgba(45,45,45,0.65); }
.icon-circle { width: 60px; height: 60px; border-radius: 50%; background: var(--mint); border: 3px solid var(--dark); margin: 0 auto 14px; display: grid; place-items: center; box-shadow: 0 4px 0 rgba(0,0,0,0.15); }
.field { margin-bottom: 22px; }
.field-label { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.field-label label { font-weight: 600; font-size: 15px; }
.field-label .meta { font-size: 12px; font-weight: 500; color: rgba(45,45,45,0.5); }
.room-code-input {
font-family: inherit; font-weight: 700; font-size: 28px; letter-spacing: 12px;
text-align: center; text-transform: uppercase;
padding: 18px 16px 18px 28px; border: 3px solid var(--dark); border-radius: 16px;
background: var(--cream); color: var(--dark); outline: none; width: 100%;
transition: all 0.15s ease;
}
.room-code-input:focus { border-color: var(--coral); background: var(--white); }
.room-code-input::placeholder { color: rgba(45,45,45,0.25); letter-spacing: 12px; }
.nick-input {
font-family: inherit; font-weight: 600; font-size: 16px;
padding: 14px 18px; border: 3px solid var(--dark); border-radius: 14px;
background: var(--cream); color: var(--dark); outline: none; width: 100%;
transition: all 0.15s ease;
}
.nick-input:focus { border-color: var(--coral); background: var(--white); }
.avatar-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px; }
.avatar-grid label { position: relative; cursor: pointer; }
.avatar-grid input { position: absolute; opacity: 0; pointer-events: none; }
.avatar-grid .av {
aspect-ratio: 1; border: 3px solid var(--dark); border-radius: 14px;
background: var(--white); display: grid; place-items: center; font-size: 24px;
transition: all 0.15s ease; box-shadow: 0 3px 0 rgba(0,0,0,0.15);
}
.avatar-grid label:hover .av { transform: translateY(-2px); }
.avatar-grid input:checked + .av { background: var(--yellow); transform: translateY(-3px); box-shadow: 0 5px 0 rgba(0,0,0,0.18); }
.btn { font-family: inherit; font-weight: 700; font-size: 18px; padding: 18px 36px; border-radius: 999px; border: 3px solid var(--dark); cursor: pointer; box-shadow: var(--shadow-btn); transition: transform 0.15s ease; display: inline-flex; align-items: center; gap: 10px; justify-content: center; width: 100%; }
.btn:hover { transform: translateY(-2px); }
.btn-primary { background: var(--coral); color: white; }
.helper { text-align: center; margin-top: 18px; font-size: 14px; font-weight: 500; color: rgba(45,45,45,0.7); }
.helper a { color: var(--coral); font-weight: 700; text-decoration: none; }
.helper a:hover { text-decoration: underline; }
@media (max-width: 480px) {
main { margin: 0 auto; padding: 16px; }
.card { padding: 28px 22px; }
.room-code-input { font-size: 22px; letter-spacing: 8px; }
.avatar-grid { grid-template-columns: repeat(4, 1fr); }
.doodle { display: none; }
}
</style>
</head>
<body>
<!-- decorative doodles -->
<svg class="doodle d1" width="60" height="60" viewBox="0 0 60 60"><circle cx="30" cy="30" r="20" fill="#FFD23F" stroke="#2D2D2D" stroke-width="3"/><circle cx="24" cy="26" r="2" fill="#2D2D2D"/><circle cx="36" cy="26" r="2" fill="#2D2D2D"/><path d="M22 36 Q30 42 38 36" stroke="#2D2D2D" stroke-width="3" fill="none" stroke-linecap="round"/></svg>
<svg class="doodle d2" width="70" height="70" viewBox="0 0 70 70"><path d="M10 50 Q35 10 60 50" stroke="#FF5C5C" stroke-width="4" fill="none" stroke-linecap="round"/><circle cx="35" cy="20" r="6" fill="#FF5C5C"/></svg>
<svg class="doodle d3" width="60" height="60" viewBox="0 0 60 60"><polygon points="30,8 36,24 53,25 40,36 44,52 30,43 16,52 20,36 7,25 24,24" fill="#A593E0" stroke="#2D2D2D" stroke-width="3" stroke-linejoin="round"/></svg>
<svg class="doodle d4" width="80" height="60" viewBox="0 0 80 60"><ellipse cx="40" cy="30" rx="30" ry="22" fill="#5BCEFA" stroke="#2D2D2D" stroke-width="3"/><polygon points="20,40 25,55 35,42" fill="#5BCEFA" stroke="#2D2D2D" stroke-width="3" stroke-linejoin="round"/></svg>
<header class="site-header">
<a class="logo" href="01-landing.html">
<div class="logo-mark">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
</div>
DrawTogether
</a>
<a href="01-landing.html" class="back-link">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
Back home
</a>
</header>
<main>
<section class="card">
<div class="card-header">
<div class="icon-circle">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M15 12H3"/></svg>
</div>
<h1>Join the room</h1>
<p>Enter your friend's room code to jump in.</p>
</div>
<div class="field">
<div class="field-label">
<label for="room-code">Room code</label>
<span class="meta">6 characters</span>
</div>
<input id="room-code" class="room-code-input" type="text" maxlength="6" placeholder="XXXXXX" value="MIA42K" data-testid="input-room-code">
</div>
<div class="field">
<div class="field-label">
<label for="nickname">Your nickname</label>
<span class="meta">3-16 chars</span>
</div>
<input id="nickname" class="nick-input" type="text" maxlength="16" placeholder="What should we call you?" value="Suki" data-testid="input-nickname">
</div>
<div class="field">
<div class="field-label">
<label>Pick your avatar</label>
<span class="meta">Tap to choose</span>
</div>
<div class="avatar-grid" data-testid="avatar-grid">
<label><input type="radio" name="avatar" value="cat"><div class="av">🐱</div></label>
<label><input type="radio" name="avatar" value="fox" checked><div class="av">🦊</div></label>
<label><input type="radio" name="avatar" value="bear"><div class="av">🐻</div></label>
<label><input type="radio" name="avatar" value="frog"><div class="av">🐸</div></label>
<label><input type="radio" name="avatar" value="owl"><div class="av">🦉</div></label>
<label><input type="radio" name="avatar" value="panda"><div class="av">🐼</div></label>
<label><input type="radio" name="avatar" value="uni"><div class="av">🦄</div></label>
<label><input type="radio" name="avatar" value="dog"><div class="av">🐶</div></label>
</div>
</div>
<a href="04-lobby.html" class="btn btn-primary" data-testid="btn-join">
Join Room
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
</a>
<p class="helper">No code? <a href="02-create-room.html">Create your own room</a> instead.</p>
</section>
</main>
</body>
</html>
+306
View File
@@ -0,0 +1,306 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lobby - DrawTogether</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--yellow: #FFD23F; --coral: #FF5C5C; --mint: #4ECDC4;
--lavender: #A593E0; --sky: #5BCEFA; --dark: #2D2D2D;
--cream: #FFF8E7; --white: #FFFFFF;
--shadow-card: 0 6px 0 rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);
--shadow-btn: 0 5px 0 rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.12);
}
html, body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--dark); background: var(--cream); -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; }
.site-header { display: flex; align-items: center; justify-content: space-between; padding: 18px 28px; max-width: 1400px; margin: 0 auto; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 22px; text-decoration: none; color: inherit; }
.logo-mark { width: 40px; height: 40px; border-radius: 12px; background: var(--coral); display: grid; place-items: center; box-shadow: var(--shadow-card); transform: rotate(-6deg); }
.room-pill { display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; background: var(--white); border: 2px solid var(--dark); border-radius: 999px; font-weight: 700; font-size: 14px; box-shadow: 0 3px 0 rgba(0,0,0,0.1); }
.room-pill .dot { width: 8px; height: 8px; background: var(--mint); border-radius: 50%; }
main { max-width: 1400px; margin: 0 auto; padding: 12px 28px 80px; display: grid; grid-template-columns: 1fr 1.2fr; gap: 24px; }
.panel { background: var(--white); border: 3px solid var(--dark); border-radius: 22px; padding: 22px; box-shadow: var(--shadow-card); }
.panel-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.panel-header h2 { font-size: 18px; font-weight: 700; display: flex; align-items: center; gap: 10px; }
.panel-header .icon-pill { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center; border: 2px solid var(--dark); }
.badge { padding: 4px 10px; background: var(--cream); border: 2px solid var(--dark); border-radius: 999px; font-size: 12px; font-weight: 700; }
/* Player list */
.player-list { display: flex; flex-direction: column; gap: 10px; }
.player {
display: flex; align-items: center; gap: 12px; padding: 10px 14px;
background: var(--cream); border-radius: 14px; border: 2px solid transparent;
transition: all 0.15s ease;
}
.player.you { border-color: var(--coral); background: rgba(255,92,92,0.08); }
.player .avatar {
width: 42px; height: 42px; border-radius: 12px; border: 2px solid var(--dark);
display: grid; place-items: center; font-size: 22px; flex-shrink: 0;
}
.player .avatar.a1 { background: var(--yellow); }
.player .avatar.a2 { background: var(--mint); }
.player .avatar.a3 { background: var(--lavender); }
.player .avatar.a4 { background: var(--sky); }
.player .avatar.a5 { background: var(--coral); }
.player .info { flex: 1; min-width: 0; }
.player .name { font-weight: 700; font-size: 15px; display: flex; align-items: center; gap: 6px; }
.player .status { font-size: 12px; color: rgba(45,45,45,0.6); font-weight: 500; }
.player .crown {
background: var(--yellow); border: 2px solid var(--dark); border-radius: 6px; padding: 2px 6px;
display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700;
}
.player .ready {
width: 24px; height: 24px; background: var(--mint); border: 2px solid var(--dark); border-radius: 50%;
display: grid; place-items: center; flex-shrink: 0;
}
.player .pending {
width: 24px; height: 24px; background: var(--cream); border: 2px solid rgba(45,45,45,0.3); border-radius: 50%;
flex-shrink: 0;
}
.player .youlbl { font-size: 11px; padding: 2px 6px; background: var(--coral); color: white; border-radius: 6px; font-weight: 700; }
.empty-slot {
display: flex; align-items: center; justify-content: center; gap: 8px;
padding: 14px; background: transparent; border: 2px dashed rgba(45,45,45,0.25);
border-radius: 14px; color: rgba(45,45,45,0.5); font-weight: 600; font-size: 14px;
}
/* Right column */
.right-col { display: flex; flex-direction: column; gap: 24px; }
.share-row { display: flex; gap: 10px; align-items: center; padding: 8px 8px 8px 16px; background: var(--cream); border: 3px solid var(--dark); border-radius: 14px; }
.share-row .url { flex: 1; font-weight: 600; font-size: 14px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.copy-btn { padding: 8px 14px; background: var(--coral); color: white; border: 2px solid var(--dark); border-radius: 10px; font-family: inherit; font-weight: 700; font-size: 13px; cursor: pointer; box-shadow: 0 3px 0 rgba(0,0,0,0.15); display: inline-flex; align-items: center; gap: 6px; }
.copy-btn:hover { transform: translateY(-1px); }
.room-code-display { text-align: center; padding: 18px; background: var(--cream); border: 3px dashed var(--dark); border-radius: 16px; margin-top: 12px; }
.room-code-display .lbl { font-size: 12px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: rgba(45,45,45,0.6); }
.room-code-display .code { font-size: 32px; font-weight: 700; letter-spacing: 8px; margin-top: 4px; }
.settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
.setting-item { padding: 12px 14px; background: var(--cream); border-radius: 12px; border: 2px solid rgba(45,45,45,0.1); }
.setting-item .lbl { font-size: 12px; font-weight: 600; color: rgba(45,45,45,0.6); display: flex; align-items: center; gap: 6px; }
.setting-item .val { font-size: 17px; font-weight: 700; margin-top: 2px; }
.start-btn {
font-family: inherit; font-weight: 700; font-size: 20px;
padding: 18px; border-radius: 16px; border: 3px solid var(--dark);
cursor: pointer; box-shadow: var(--shadow-btn); transition: transform 0.15s ease;
display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
background: var(--coral); color: white; margin-top: 16px;
}
.start-btn:hover { transform: translateY(-2px); }
/* Chat */
.chat-panel { display: flex; flex-direction: column; height: 360px; }
.chat-messages { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; padding: 4px 4px 12px; }
.msg { display: flex; gap: 10px; align-items: flex-start; }
.msg .av { width: 30px; height: 30px; border-radius: 8px; border: 2px solid var(--dark); display: grid; place-items: center; font-size: 16px; flex-shrink: 0; }
.msg .body { background: var(--cream); padding: 8px 12px; border-radius: 12px 12px 12px 4px; }
.msg .name { font-weight: 700; font-size: 12px; color: var(--coral); }
.msg .text { font-size: 14px; font-weight: 500; line-height: 1.4; }
.msg.system .body { background: rgba(78, 205, 196, 0.18); border: 2px dashed var(--mint); }
.msg.system .text { font-style: italic; color: rgba(45,45,45,0.7); }
.chat-input-row { display: flex; gap: 8px; padding-top: 10px; border-top: 2px dashed rgba(45,45,45,0.15); }
.chat-input { flex: 1; font-family: inherit; font-weight: 500; font-size: 14px; padding: 10px 14px; border: 2px solid var(--dark); border-radius: 999px; background: var(--cream); outline: none; }
.chat-input:focus { background: var(--white); border-color: var(--coral); }
.send-btn { width: 44px; height: 44px; background: var(--mint); border: 2px solid var(--dark); border-radius: 50%; cursor: pointer; display: grid; place-items: center; box-shadow: 0 3px 0 rgba(0,0,0,0.15); }
@media (max-width: 900px) {
main { grid-template-columns: 1fr; padding: 12px 16px 60px; }
.site-header { padding: 16px; }
.room-pill .label { display: none; }
}
</style>
</head>
<body>
<header class="site-header">
<a class="logo" href="01-landing.html">
<div class="logo-mark">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
</div>
DrawTogether
</a>
<div class="room-pill" data-testid="room-pill">
<span class="dot"></span>
<span class="label">Room</span>
<strong>MIA42K</strong>
</div>
</header>
<main>
<!-- Players panel -->
<section class="panel" data-testid="panel-players">
<div class="panel-header">
<h2>
<span class="icon-pill" style="background: var(--mint);"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg></span>
Players
</h2>
<span class="badge">5 / 8</span>
</div>
<div class="player-list">
<div class="player">
<div class="avatar a1">🦄</div>
<div class="info">
<div class="name">Mia <span class="crown">
<svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor"><path d="M2 18l3-12 5 8 2-12 2 12 5-8 3 12z"/></svg>
HOST</span></div>
<div class="status">Ready to start</div>
</div>
<div class="ready"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg></div>
</div>
<div class="player you">
<div class="avatar a2">🦊</div>
<div class="info">
<div class="name">Suki <span class="youlbl">YOU</span></div>
<div class="status">Joined just now</div>
</div>
<div class="ready"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg></div>
</div>
<div class="player">
<div class="avatar a3">🐼</div>
<div class="info">
<div class="name">Ravi</div>
<div class="status">Picking avatar...</div>
</div>
<div class="pending"></div>
</div>
<div class="player">
<div class="avatar a4">🐸</div>
<div class="info">
<div class="name">Jules</div>
<div class="status">Ready to start</div>
</div>
<div class="ready"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg></div>
</div>
<div class="player">
<div class="avatar a5">🐱</div>
<div class="info">
<div class="name">Pat</div>
<div class="status">Ready to start</div>
</div>
<div class="ready"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg></div>
</div>
<div class="empty-slot">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
Waiting for player...
</div>
<div class="empty-slot">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
Waiting for player...
</div>
</div>
</section>
<!-- Right column -->
<div class="right-col">
<section class="panel" data-testid="panel-share">
<div class="panel-header">
<h2>
<span class="icon-pill" style="background: var(--lavender);"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="M8.59 13.51l6.83 3.98M15.41 6.51l-6.82 3.98"/></svg></span>
Invite friends
</h2>
</div>
<div class="share-row">
<span class="url">drawtogether.app/r/MIA42K</span>
<button class="copy-btn" data-testid="btn-copy-link">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
Copy
</button>
</div>
<div class="room-code-display">
<div class="lbl">Or share the code</div>
<div class="code">MIA42K</div>
</div>
</section>
<section class="panel" data-testid="panel-settings">
<div class="panel-header">
<h2>
<span class="icon-pill" style="background: var(--yellow);"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>
Game settings
</h2>
<span class="badge">Skribbl Race</span>
</div>
<div class="settings-grid">
<div class="setting-item">
<div class="lbl">Rounds</div><div class="val">5</div>
</div>
<div class="setting-item">
<div class="lbl">Time / draw</div><div class="val">60s</div>
</div>
<div class="setting-item">
<div class="lbl">Max players</div><div class="val">8</div>
</div>
<div class="setting-item">
<div class="lbl">Language</div><div class="val">English</div>
</div>
</div>
<button class="start-btn" data-testid="btn-start">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>
Start Game
</button>
</section>
<section class="panel chat-panel" data-testid="panel-chat">
<div class="panel-header">
<h2>
<span class="icon-pill" style="background: var(--sky);"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></span>
Lobby chat
</h2>
</div>
<div class="chat-messages">
<div class="msg system">
<div class="body" style="margin: 0 auto;">
<div class="text">Suki joined the room</div>
</div>
</div>
<div class="msg">
<div class="av" style="background: var(--yellow);">🦄</div>
<div class="body">
<div class="name">Mia</div>
<div class="text">heyyy welcome! waiting on Ravi to pick an avatar 🙃</div>
</div>
</div>
<div class="msg">
<div class="av" style="background: var(--sky);">🐸</div>
<div class="body">
<div class="name">Jules</div>
<div class="text">i call drawing first round &lt;3</div>
</div>
</div>
<div class="msg">
<div class="av" style="background: var(--coral);">🐱</div>
<div class="body">
<div class="name">Pat</div>
<div class="text">good luck with that lol</div>
</div>
</div>
<div class="msg system">
<div class="body" style="margin: 0 auto;">
<div class="text">Mia changed rounds to 5</div>
</div>
</div>
</div>
<div class="chat-input-row">
<input class="chat-input" type="text" placeholder="Say something..." data-testid="chat-input">
<button class="send-btn" data-testid="btn-send">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button>
</div>
</section>
</div>
</main>
</body>
</html>
+371
View File
@@ -0,0 +1,371 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drawing - DrawTogether</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--yellow: #FFD23F; --coral: #FF5C5C; --mint: #4ECDC4;
--lavender: #A593E0; --sky: #5BCEFA; --dark: #2D2D2D;
--cream: #FFF8E7; --white: #FFFFFF;
--shadow-card: 0 6px 0 rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);
--shadow-btn: 0 5px 0 rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.12);
}
html, body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--dark); background: var(--cream); -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; }
.game-header {
display: flex; align-items: center; justify-content: space-between;
padding: 14px 22px; max-width: 1500px; margin: 0 auto;
}
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 20px; text-decoration: none; color: inherit; }
.logo-mark { width: 38px; height: 38px; border-radius: 12px; background: var(--coral); display: grid; place-items: center; box-shadow: var(--shadow-card); transform: rotate(-6deg); }
.header-pills { display: flex; gap: 10px; align-items: center; }
.pill-info { padding: 8px 16px; background: var(--white); border: 2px solid var(--dark); border-radius: 999px; font-weight: 700; font-size: 13px; box-shadow: 0 3px 0 rgba(0,0,0,0.1); display: inline-flex; align-items: center; gap: 6px; }
.pill-info.round { background: var(--lavender); color: white; }
.leave-btn { padding: 8px 14px; background: var(--white); border: 2px solid var(--dark); border-radius: 999px; font-family: inherit; font-weight: 700; font-size: 13px; cursor: pointer; box-shadow: 0 3px 0 rgba(0,0,0,0.1); display: inline-flex; align-items: center; gap: 6px; }
main {
max-width: 1500px; margin: 0 auto; padding: 8px 22px 30px;
display: grid; grid-template-columns: 220px 1fr 280px; gap: 18px;
}
/* Sidebar (players/scoreboard) */
.panel { background: var(--white); border: 3px solid var(--dark); border-radius: 20px; padding: 16px; box-shadow: var(--shadow-card); }
.panel-title { font-size: 14px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: rgba(45,45,45,0.6); margin-bottom: 12px; padding-left: 4px; }
.scoreboard { display: flex; flex-direction: column; gap: 8px; }
.score-item {
display: flex; align-items: center; gap: 10px; padding: 8px 10px;
background: var(--cream); border-radius: 12px; border: 2px solid transparent;
}
.score-item.drawing { background: var(--yellow); border-color: var(--dark); position: relative; }
.score-item .rank { width: 22px; height: 22px; background: var(--white); border: 2px solid var(--dark); border-radius: 50%; display: grid; place-items: center; font-size: 11px; font-weight: 700; flex-shrink: 0; }
.score-item.drawing .rank { background: var(--coral); color: white; }
.score-item .av { width: 32px; height: 32px; border-radius: 10px; border: 2px solid var(--dark); display: grid; place-items: center; font-size: 18px; flex-shrink: 0; }
.score-item .info { flex: 1; min-width: 0; }
.score-item .name { font-size: 13px; font-weight: 700; display: flex; align-items: center; gap: 4px; }
.score-item .pts { font-size: 11px; color: rgba(45,45,45,0.6); font-weight: 600; }
.score-item .pts strong { color: var(--coral); }
.score-item .pencil-icon { color: var(--dark); flex-shrink: 0; }
.score-item .guessed { color: var(--mint); font-weight: 700; font-size: 11px; }
/* Center (canvas area) */
.canvas-area { display: flex; flex-direction: column; gap: 14px; }
.canvas-top {
display: flex; align-items: center; justify-content: space-between; gap: 16px;
background: var(--white); border: 3px solid var(--dark); border-radius: 18px;
padding: 14px 18px; box-shadow: var(--shadow-card);
}
.timer-ring {
position: relative; width: 60px; height: 60px; flex-shrink: 0;
}
.timer-ring svg { width: 60px; height: 60px; transform: rotate(-90deg); }
.timer-ring .bg-track { fill: none; stroke: rgba(45,45,45,0.12); stroke-width: 6; }
.timer-ring .fg-track { fill: none; stroke: var(--coral); stroke-width: 6; stroke-linecap: round; stroke-dasharray: 165; stroke-dashoffset: 35; transition: stroke-dashoffset 1s linear; }
.timer-ring .label { position: absolute; inset: 0; display: grid; place-items: center; font-weight: 700; font-size: 16px; }
.word-hint { flex: 1; text-align: center; }
.word-hint .lbl { font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: rgba(45,45,45,0.55); margin-bottom: 4px; }
.word-letters { display: inline-flex; gap: 8px; justify-content: center; }
.letter {
width: 30px; height: 38px; background: var(--cream); border: 2px solid var(--dark);
border-radius: 8px; display: grid; place-items: center; font-weight: 700; font-size: 18px;
}
.letter.revealed { background: var(--yellow); }
.letter .underline { display: block; width: 18px; height: 3px; background: var(--dark); border-radius: 2px; }
.word-meta { font-size: 12px; font-weight: 600; color: rgba(45,45,45,0.6); margin-top: 4px; }
.drawing-canvas {
background: var(--white); border: 3px solid var(--dark); border-radius: 20px;
box-shadow: var(--shadow-card); padding: 16px;
display: flex; flex-direction: column; gap: 12px;
aspect-ratio: 16/10; min-height: 380px; position: relative;
}
.canvas-stage { flex: 1; background: var(--cream); border: 2px dashed rgba(45,45,45,0.18); border-radius: 14px; overflow: hidden; position: relative; display: grid; place-items: center; }
.you-drawing-tag {
position: absolute; top: 14px; left: 14px;
padding: 6px 12px; background: var(--coral); color: white; border: 2px solid var(--dark); border-radius: 999px;
font-weight: 700; font-size: 12px; box-shadow: 0 3px 0 rgba(0,0,0,0.15); z-index: 2;
display: inline-flex; align-items: center; gap: 6px;
}
/* Tool palette */
.toolbar {
display: flex; align-items: center; gap: 14px; padding: 12px;
background: var(--cream); border-radius: 14px;
flex-wrap: wrap; justify-content: center;
}
.color-row { display: flex; gap: 6px; flex-wrap: wrap; }
.color-swatch {
width: 28px; height: 28px; border-radius: 8px; border: 2px solid var(--dark);
cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.15);
transition: transform 0.12s ease;
}
.color-swatch:hover { transform: translateY(-2px); }
.color-swatch.active { box-shadow: 0 0 0 3px var(--white), 0 0 0 5px var(--dark); transform: translateY(-2px); }
.divider { width: 2px; height: 28px; background: rgba(45,45,45,0.15); }
.tool-btn { width: 36px; height: 36px; border-radius: 10px; border: 2px solid var(--dark); background: var(--white); cursor: pointer; display: grid; place-items: center; box-shadow: 0 2px 0 rgba(0,0,0,0.15); transition: transform 0.12s ease; }
.tool-btn:hover { transform: translateY(-2px); }
.tool-btn.active { background: var(--yellow); }
.brush-sizes { display: flex; gap: 6px; align-items: center; }
.brush-size { width: 36px; height: 36px; border-radius: 10px; border: 2px solid var(--dark); background: var(--white); display: grid; place-items: center; cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.15); }
.brush-size .dot { background: var(--dark); border-radius: 50%; }
.brush-size .dot.s1 { width: 4px; height: 4px; }
.brush-size .dot.s2 { width: 8px; height: 8px; }
.brush-size .dot.s3 { width: 14px; height: 14px; }
.brush-size.active { background: var(--mint); }
/* Right column — chat + guess */
.chat-panel { display: flex; flex-direction: column; height: 100%; min-height: 500px; }
.chat-messages { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding-right: 4px; }
.msg { padding: 8px 12px; border-radius: 12px; font-size: 13px; line-height: 1.4; }
.msg.regular { background: var(--cream); }
.msg.regular .name { font-weight: 700; color: var(--coral); margin-right: 6px; }
.msg.guessed { background: rgba(78,205,196,0.18); border: 2px dashed var(--mint); font-weight: 600; }
.msg.guessed .name { font-weight: 700; color: var(--dark); margin-right: 6px; }
.msg.guessed .check { display: inline-flex; gap: 4px; align-items: center; color: var(--mint); font-weight: 700; }
.msg.close { background: rgba(255,210,63,0.3); font-weight: 600; font-style: italic; }
.msg.system { background: transparent; text-align: center; font-style: italic; color: rgba(45,45,45,0.6); font-size: 12px; }
.guess-input-row { display: flex; gap: 6px; padding-top: 10px; border-top: 2px dashed rgba(45,45,45,0.15); margin-top: 10px; }
.guess-input { flex: 1; font-family: inherit; font-weight: 600; font-size: 14px; padding: 10px 14px; border: 2px solid var(--dark); border-radius: 999px; background: var(--cream); outline: none; }
.guess-input:focus { background: var(--white); border-color: var(--coral); }
.send-btn { width: 40px; height: 40px; background: var(--mint); border: 2px solid var(--dark); border-radius: 50%; cursor: pointer; display: grid; place-items: center; box-shadow: 0 3px 0 rgba(0,0,0,0.15); flex-shrink: 0; }
@media (max-width: 1100px) {
main { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<header class="game-header">
<a class="logo" href="01-landing.html">
<div class="logo-mark"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg></div>
DrawTogether
</a>
<div class="header-pills">
<span class="pill-info round">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M21 12a9 9 0 1 1-9-9c2.5 0 4.8.97 6.5 2.5L21 8"/><polyline points="21 3 21 8 16 8"/></svg>
Round 3 / 5
</span>
<span class="pill-info">
<span style="width: 8px; height: 8px; background: var(--mint); border-radius: 50%;"></span>
MIA42K
</span>
<button class="leave-btn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg>
Leave
</button>
</div>
</header>
<main>
<!-- Left: scoreboard -->
<aside class="panel" data-testid="panel-scoreboard">
<div class="panel-title">Scoreboard</div>
<div class="scoreboard">
<div class="score-item">
<div class="rank">1</div>
<div class="av" style="background: var(--yellow);">🦄</div>
<div class="info">
<div class="name">Mia</div>
<div class="pts"><strong>1240</strong> pts</div>
</div>
</div>
<div class="score-item">
<div class="rank">2</div>
<div class="av" style="background: var(--mint);">🦊</div>
<div class="info">
<div class="name">Suki</div>
<div class="pts guessed">+120 just now!</div>
</div>
</div>
<div class="score-item drawing">
<div class="rank">3</div>
<div class="av" style="background: var(--white);">🐼</div>
<div class="info">
<div class="name">Ravi</div>
<div class="pts"><strong>820</strong> pts · drawing</div>
</div>
<div class="pencil-icon">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
</div>
</div>
<div class="score-item">
<div class="rank">4</div>
<div class="av" style="background: var(--sky);">🐸</div>
<div class="info">
<div class="name">Jules</div>
<div class="pts"><strong>740</strong> pts</div>
</div>
</div>
<div class="score-item">
<div class="rank">5</div>
<div class="av" style="background: var(--coral);">🐱</div>
<div class="info">
<div class="name">Pat</div>
<div class="pts">guessing...</div>
</div>
</div>
</div>
</aside>
<!-- Center: canvas -->
<section class="canvas-area">
<div class="canvas-top" data-testid="canvas-top">
<div class="timer-ring" data-testid="timer">
<svg viewBox="0 0 60 60">
<circle class="bg-track" cx="30" cy="30" r="26"/>
<circle class="fg-track" cx="30" cy="30" r="26"/>
</svg>
<div class="label">47s</div>
</div>
<div class="word-hint">
<div class="lbl">Word hint</div>
<div class="word-letters" data-testid="word-hint">
<div class="letter"><span class="underline"></span></div>
<div class="letter"><span class="underline"></span></div>
<div class="letter revealed">A</div>
<div class="letter"><span class="underline"></span></div>
<div class="letter"><span class="underline"></span></div>
<div class="letter"><span class="underline"></span></div>
</div>
<div class="word-meta">6 letters · animal</div>
</div>
<div class="pill-info" style="background: var(--mint);">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
Ravi drawing
</div>
</div>
<div class="drawing-canvas" data-testid="canvas">
<div class="canvas-stage">
<!-- sample mid-drawing: cat -->
<svg viewBox="0 0 600 360" width="100%" height="100%" preserveAspectRatio="xMidYMid meet" style="max-width: 600px;">
<!-- body sketch -->
<ellipse cx="300" cy="240" rx="135" ry="75" fill="#FFD23F" stroke="#2D2D2D" stroke-width="5"/>
<!-- head -->
<circle cx="300" cy="155" r="92" fill="#FFD23F" stroke="#2D2D2D" stroke-width="5"/>
<!-- ears -->
<polygon points="225,90 215,30 280,80" fill="#FFD23F" stroke="#2D2D2D" stroke-width="5" stroke-linejoin="round"/>
<polygon points="375,90 385,30 320,80" fill="#FFD23F" stroke="#2D2D2D" stroke-width="5" stroke-linejoin="round"/>
<!-- inner ears -->
<polygon points="232,82 233,55 265,78" fill="#FF5C5C"/>
<polygon points="368,82 367,55 335,78" fill="#FF5C5C"/>
<!-- eyes -->
<circle cx="270" cy="150" r="11" fill="#2D2D2D"/>
<circle cx="330" cy="150" r="11" fill="#2D2D2D"/>
<circle cx="274" cy="146" r="4" fill="white"/>
<circle cx="334" cy="146" r="4" fill="white"/>
<!-- nose + mouth -->
<path d="M291 178 Q300 188 309 178" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="3" stroke-linejoin="round"/>
<path d="M291 184 Q283 200 295 206" stroke="#2D2D2D" stroke-width="4" fill="none" stroke-linecap="round"/>
<path d="M309 184 Q317 200 305 206" stroke="#2D2D2D" stroke-width="4" fill="none" stroke-linecap="round"/>
<!-- whiskers -->
<line x1="225" y1="165" x2="180" y2="160" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<line x1="225" y1="173" x2="180" y2="178" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<line x1="375" y1="165" x2="420" y2="160" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<line x1="375" y1="173" x2="420" y2="178" stroke="#2D2D2D" stroke-width="3" stroke-linecap="round"/>
<!-- belly -->
<ellipse cx="300" cy="265" rx="80" ry="40" fill="#FFF8E7" opacity="0.6"/>
<!-- tail -->
<path d="M430 220 Q500 200 480 145" stroke="#2D2D2D" stroke-width="5" fill="#FFD23F" stroke-linecap="round"/>
<!-- in-progress pencil cursor -->
<g transform="translate(450,290) rotate(40)">
<rect x="0" y="0" width="42" height="12" rx="3" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="3"/>
<polygon points="42,0 52,6 42,12" fill="#FFD23F" stroke="#2D2D2D" stroke-width="3" stroke-linejoin="round"/>
</g>
</svg>
</div>
<!-- Toolbar (drawer view) -->
<div class="toolbar" data-testid="toolbar">
<div class="color-row">
<div class="color-swatch" style="background: #2D2D2D;"></div>
<div class="color-swatch active" style="background: #FFD23F;"></div>
<div class="color-swatch" style="background: #FF5C5C;"></div>
<div class="color-swatch" style="background: #4ECDC4;"></div>
<div class="color-swatch" style="background: #5BCEFA;"></div>
<div class="color-swatch" style="background: #A593E0;"></div>
<div class="color-swatch" style="background: #ffffff;"></div>
<div class="color-swatch" style="background: #6BCB77;"></div>
<div class="color-swatch" style="background: #FF8C42;"></div>
<div class="color-swatch" style="background: #B5651D;"></div>
</div>
<div class="divider"></div>
<div class="brush-sizes">
<div class="brush-size"><span class="dot s1"></span></div>
<div class="brush-size active"><span class="dot s2"></span></div>
<div class="brush-size"><span class="dot s3"></span></div>
</div>
<div class="divider"></div>
<button class="tool-btn active" title="Brush">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
</button>
<button class="tool-btn" title="Eraser">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M20 20H7L3 16a2 2 0 0 1 0-3l9-9a2 2 0 0 1 3 0l6 6a2 2 0 0 1 0 3l-7 7"/></svg>
</button>
<button class="tool-btn" title="Bucket">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M19 11l-7-7-9 9 7 7 9-9z"/><path d="M5 13l4 4M19 11c1 0 2 1 2 3a3 3 0 1 1-6 0c0-1 1-3 1-3"/></svg>
</button>
<button class="tool-btn" title="Undo">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M3 7v6h6M21 17a9 9 0 0 0-15-6.7L3 13"/></svg>
</button>
<button class="tool-btn" title="Clear">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-2 14a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2L5 6"/></svg>
</button>
</div>
</div>
</section>
<!-- Right: chat / guesses -->
<aside class="panel chat-panel" data-testid="panel-chat">
<div class="panel-title">Guesses</div>
<div class="chat-messages">
<div class="msg system">— Round 3 started —</div>
<div class="msg regular">
<span class="name">Pat:</span> dog?
</div>
<div class="msg regular">
<span class="name">Jules:</span> hamster
</div>
<div class="msg close">
<span style="color: var(--coral); font-weight:700;">Suki:</span> kitten — close!
</div>
<div class="msg regular">
<span class="name">Pat:</span> lion?
</div>
<div class="msg guessed">
<span class="name">Mia</span> guessed it!
<span class="check"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg> +180</span>
</div>
<div class="msg regular">
<span class="name">Pat:</span> tiger
</div>
<div class="msg guessed">
<span class="name">Suki</span> guessed it!
<span class="check"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg> +120</span>
</div>
<div class="msg regular">
<span class="name">Jules:</span> kitty cat??
</div>
<div class="msg system">Pat is typing...</div>
</div>
<div class="guess-input-row">
<input class="guess-input" type="text" placeholder="Type your guess..." data-testid="guess-input">
<button class="send-btn" data-testid="btn-guess">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button>
</div>
</aside>
</main>
</body>
</html>
+304
View File
@@ -0,0 +1,304 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gartic Phone - DrawTogether</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--yellow: #FFD23F; --coral: #FF5C5C; --mint: #4ECDC4;
--lavender: #A593E0; --sky: #5BCEFA; --dark: #2D2D2D;
--cream: #FFF8E7; --white: #FFFFFF;
--shadow-card: 0 6px 0 rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);
--shadow-btn: 0 5px 0 rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.12);
}
html, body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--dark); background: var(--cream); -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; }
.game-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 22px; max-width: 1500px; margin: 0 auto; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 20px; text-decoration: none; color: inherit; }
.logo-mark { width: 38px; height: 38px; border-radius: 12px; background: var(--coral); display: grid; place-items: center; box-shadow: var(--shadow-card); transform: rotate(-6deg); }
.header-pills { display: flex; gap: 10px; align-items: center; }
.pill-info { padding: 8px 16px; background: var(--white); border: 2px solid var(--dark); border-radius: 999px; font-weight: 700; font-size: 13px; box-shadow: 0 3px 0 rgba(0,0,0,0.1); display: inline-flex; align-items: center; gap: 6px; }
.pill-info.round { background: var(--mint); color: var(--dark); }
.pill-info.timer { background: var(--coral); color: white; }
.leave-btn { padding: 8px 14px; background: var(--white); border: 2px solid var(--dark); border-radius: 999px; font-family: inherit; font-weight: 700; font-size: 13px; cursor: pointer; box-shadow: 0 3px 0 rgba(0,0,0,0.1); display: inline-flex; align-items: center; gap: 6px; }
.stage-banner {
max-width: 1500px; margin: 0 auto; padding: 0 22px 14px;
}
.banner-inner {
background: var(--white); border: 3px solid var(--dark); border-radius: 18px; padding: 14px 22px;
box-shadow: var(--shadow-card); display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.banner-inner h1 { font-size: 22px; font-weight: 700; }
.banner-inner .sub { font-weight: 600; font-size: 14px; color: rgba(45,45,45,0.65); margin-top: 2px; }
.timer-ring { position: relative; width: 64px; height: 64px; flex-shrink: 0; }
.timer-ring svg { width: 64px; height: 64px; transform: rotate(-90deg); }
.timer-ring .bg-track { fill: none; stroke: rgba(45,45,45,0.12); stroke-width: 7; }
.timer-ring .fg-track { fill: none; stroke: var(--coral); stroke-width: 7; stroke-linecap: round; stroke-dasharray: 175; stroke-dashoffset: 60; }
.timer-ring .label { position: absolute; inset: 0; display: grid; place-items: center; font-weight: 700; font-size: 18px; }
/* Stage chips */
.stage-chips { display: flex; gap: 6px; align-items: center; }
.chip {
width: 36px; height: 36px; border-radius: 10px; border: 2px solid var(--dark);
display: grid; place-items: center; font-weight: 700; font-size: 13px;
background: var(--cream);
}
.chip.done { background: var(--mint); color: white; }
.chip.active { background: var(--yellow); transform: translateY(-2px); box-shadow: 0 4px 0 rgba(0,0,0,0.15); }
.chip-line { width: 14px; height: 3px; background: rgba(45,45,45,0.25); border-radius: 2px; }
.chip-line.done { background: var(--mint); }
main {
max-width: 1500px; margin: 0 auto; padding: 0 22px 30px;
display: grid; grid-template-columns: 1fr 280px; gap: 18px;
}
/* Prompt card */
.prompt-card {
background: var(--lavender); border: 3px solid var(--dark); border-radius: 18px;
padding: 18px 24px; box-shadow: var(--shadow-card); margin-bottom: 14px;
display: flex; align-items: center; gap: 16px;
}
.prompt-card .av-from {
width: 50px; height: 50px; border-radius: 14px; border: 3px solid var(--dark);
background: var(--yellow); display: grid; place-items: center; font-size: 26px; flex-shrink: 0;
transform: rotate(-4deg); box-shadow: 0 4px 0 rgba(0,0,0,0.15);
}
.prompt-card .meta { color: rgba(255,255,255,0.85); font-size: 12px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; }
.prompt-card .prompt-text { font-size: 22px; font-weight: 700; color: white; margin-top: 4px; line-height: 1.2; }
.prompt-card .prompt-text .quote { color: var(--yellow); }
.canvas-wrap { background: var(--white); border: 3px solid var(--dark); border-radius: 20px; box-shadow: var(--shadow-card); padding: 18px; display: flex; flex-direction: column; gap: 14px; }
.canvas-stage {
aspect-ratio: 16/10; min-height: 420px; background: var(--cream);
border: 2px dashed rgba(45,45,45,0.18); border-radius: 14px; position: relative; overflow: hidden;
display: grid; place-items: center;
}
/* Toolbar */
.toolbar { display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--cream); border-radius: 14px; flex-wrap: wrap; justify-content: space-between; }
.tool-section { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.color-row { display: flex; gap: 5px; flex-wrap: wrap; }
.color-swatch { width: 26px; height: 26px; border-radius: 8px; border: 2px solid var(--dark); cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.15); transition: transform 0.12s ease; }
.color-swatch:hover { transform: translateY(-2px); }
.color-swatch.active { box-shadow: 0 0 0 3px var(--white), 0 0 0 5px var(--dark); transform: translateY(-2px); }
.divider { width: 2px; height: 26px; background: rgba(45,45,45,0.15); }
.tool-btn { width: 36px; height: 36px; border-radius: 10px; border: 2px solid var(--dark); background: var(--white); cursor: pointer; display: grid; place-items: center; box-shadow: 0 2px 0 rgba(0,0,0,0.15); transition: transform 0.12s ease; }
.tool-btn:hover { transform: translateY(-2px); }
.tool-btn.active { background: var(--yellow); }
.brush-size { width: 32px; height: 32px; border-radius: 10px; border: 2px solid var(--dark); background: var(--white); display: grid; place-items: center; cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.15); }
.brush-size .dot { background: var(--dark); border-radius: 50%; }
.brush-size .dot.s1 { width: 4px; height: 4px; }
.brush-size .dot.s2 { width: 8px; height: 8px; }
.brush-size .dot.s3 { width: 14px; height: 14px; }
.brush-size.active { background: var(--mint); }
.submit-btn {
font-family: inherit; font-weight: 700; font-size: 15px; padding: 10px 22px;
border-radius: 999px; border: 2px solid var(--dark);
background: var(--coral); color: white; cursor: pointer;
box-shadow: 0 4px 0 rgba(0,0,0,0.18); display: inline-flex; align-items: center; gap: 8px;
}
.submit-btn:hover { transform: translateY(-2px); }
/* Right column */
.panel { background: var(--white); border: 3px solid var(--dark); border-radius: 20px; padding: 16px; box-shadow: var(--shadow-card); }
.panel-title { font-size: 13px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: rgba(45,45,45,0.6); margin-bottom: 12px; padding-left: 4px; }
.progress-summary { text-align: center; padding: 20px 8px; }
.progress-summary .big { font-size: 42px; font-weight: 700; line-height: 1; }
.progress-summary .big strong { color: var(--coral); }
.progress-summary .lbl { font-weight: 600; font-size: 14px; color: rgba(45,45,45,0.65); margin-top: 4px; }
.player-status { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.ps-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 12px; background: var(--cream); }
.ps-item.you { background: rgba(255,210,63,0.35); }
.ps-item .av { width: 32px; height: 32px; border-radius: 10px; border: 2px solid var(--dark); display: grid; place-items: center; font-size: 18px; flex-shrink: 0; }
.ps-item .info { flex: 1; min-width: 0; }
.ps-item .name { font-weight: 700; font-size: 13px; }
.ps-item .stat { font-size: 11px; font-weight: 600; color: rgba(45,45,45,0.6); }
.ps-item .pulse { width: 10px; height: 10px; background: var(--mint); border-radius: 50%; box-shadow: 0 0 0 4px rgba(78,205,196,0.25); }
.ps-item.done .pulse { background: var(--mint); box-shadow: none; }
.ps-item.drawing .pulse { background: var(--coral); animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(255,92,92,0.4);} 50%{ box-shadow: 0 0 0 6px rgba(255,92,92,0);} }
.progress-bar-wrap { padding: 0 4px; }
.progress-bar { background: var(--cream); border: 2px solid var(--dark); border-radius: 999px; height: 14px; overflow: hidden; }
.progress-bar .fill { height: 100%; background: var(--mint); border-right: 2px solid var(--dark); width: 40%; border-radius: 999px 0 0 999px; }
.tip {
background: rgba(91,206,250,0.18); border: 2px dashed var(--sky);
padding: 12px; border-radius: 12px; margin-top: 14px; font-size: 12px; font-weight: 500; line-height: 1.45;
}
.tip strong { color: var(--dark); }
@media (max-width: 1100px) { main { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<header class="game-header">
<a class="logo" href="01-landing.html">
<div class="logo-mark"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></div>
DrawTogether
</a>
<div class="header-pills">
<span class="pill-info round">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M21 12a9 9 0 1 1-9-9c2.5 0 4.8.97 6.5 2.5L21 8"/><polyline points="21 3 21 8 16 8"/></svg>
Round 3 / 5
</span>
<span class="pill-info">MIA42K</span>
<button class="leave-btn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg>
Leave
</button>
</div>
</header>
<section class="stage-banner">
<div class="banner-inner">
<div>
<h1>Your turn to draw!</h1>
<div class="sub">Sketch what Mia wrote — pass it on when the timer ends.</div>
</div>
<div class="stage-chips" data-testid="stage-chips" aria-label="Round stages">
<div class="chip done"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M5 12l5 5L20 7"/></svg></div>
<div class="chip-line done"></div>
<div class="chip active">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
</div>
<div class="chip-line"></div>
<div class="chip">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
</div>
</div>
<div class="timer-ring" data-testid="timer">
<svg viewBox="0 0 64 64">
<circle class="bg-track" cx="32" cy="32" r="28"/>
<circle class="fg-track" cx="32" cy="32" r="28"/>
</svg>
<div class="label">60s</div>
</div>
</div>
</section>
<main>
<section>
<div class="prompt-card" data-testid="prompt-card">
<div class="av-from">🦄</div>
<div>
<div class="meta">Mia wrote</div>
<div class="prompt-text"><span class="quote">"</span>a cat riding a unicorn<span class="quote">"</span></div>
</div>
</div>
<div class="canvas-wrap">
<div class="canvas-stage" data-testid="canvas">
<!-- empty canvas illustration: simple pencil placeholder -->
<svg width="100%" height="100%" viewBox="0 0 600 380" preserveAspectRatio="xMidYMid meet">
<!-- subtle grid -->
<defs>
<pattern id="grid" width="32" height="32" patternUnits="userSpaceOnUse">
<path d="M 32 0 L 0 0 0 32" fill="none" stroke="rgba(45,45,45,0.04)" stroke-width="1"/>
</pattern>
</defs>
<rect width="600" height="380" fill="url(#grid)"/>
<!-- starter doodle: a few sketch lines + pencil -->
<g opacity="0.7">
<path d="M180 230 Q230 180 290 220" stroke="#A593E0" stroke-width="5" fill="none" stroke-linecap="round"/>
<path d="M290 220 Q350 250 410 200" stroke="#A593E0" stroke-width="5" fill="none" stroke-linecap="round"/>
<circle cx="240" cy="180" r="14" fill="none" stroke="#A593E0" stroke-width="4"/>
</g>
<g transform="translate(420,260) rotate(45)">
<rect x="0" y="0" width="58" height="14" rx="3" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="3"/>
<rect x="58" y="0" width="14" height="14" fill="#FFD23F" stroke="#2D2D2D" stroke-width="3"/>
<polygon points="72,0 84,7 72,14" fill="#FFD23F" stroke="#2D2D2D" stroke-width="3" stroke-linejoin="round"/>
<polygon points="84,7 90,5 90,9" fill="#2D2D2D"/>
</g>
<text x="300" y="340" text-anchor="middle" font-family="Fredoka, sans-serif" font-size="14" font-weight="600" fill="rgba(45,45,45,0.4)">Click and drag to draw</text>
</svg>
</div>
<div class="toolbar" data-testid="toolbar">
<div class="tool-section">
<div class="color-row">
<div class="color-swatch" style="background: #2D2D2D;"></div>
<div class="color-swatch active" style="background: #A593E0;"></div>
<div class="color-swatch" style="background: #FF5C5C;"></div>
<div class="color-swatch" style="background: #4ECDC4;"></div>
<div class="color-swatch" style="background: #FFD23F;"></div>
<div class="color-swatch" style="background: #5BCEFA;"></div>
<div class="color-swatch" style="background: #ffffff;"></div>
<div class="color-swatch" style="background: #6BCB77;"></div>
<div class="color-swatch" style="background: #FF8C42;"></div>
</div>
<div class="divider"></div>
<div class="brush-size"><span class="dot s1"></span></div>
<div class="brush-size active"><span class="dot s2"></span></div>
<div class="brush-size"><span class="dot s3"></span></div>
<div class="divider"></div>
<button class="tool-btn active" title="Brush"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg></button>
<button class="tool-btn" title="Eraser"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M20 20H7L3 16a2 2 0 0 1 0-3l9-9a2 2 0 0 1 3 0l6 6a2 2 0 0 1 0 3l-7 7"/></svg></button>
<button class="tool-btn" title="Undo"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M3 7v6h6M21 17a9 9 0 0 0-15-6.7L3 13"/></svg></button>
<button class="tool-btn" title="Clear"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-2 14a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2L5 6"/></svg></button>
</div>
<button class="submit-btn" data-testid="btn-submit-drawing">
Submit drawing
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
</button>
</div>
</div>
</section>
<aside class="panel" data-testid="panel-status">
<div class="panel-title">Round progress</div>
<div class="progress-summary">
<div class="big">waiting on <strong>3</strong> / 5</div>
<div class="lbl">players still working</div>
</div>
<div class="progress-bar-wrap">
<div class="progress-bar"><div class="fill"></div></div>
</div>
<div class="player-status">
<div class="ps-item done">
<div class="av" style="background: var(--yellow);">🦄</div>
<div class="info"><div class="name">Mia</div><div class="stat">submitted prompt</div></div>
<div class="pulse"></div>
</div>
<div class="ps-item done">
<div class="av" style="background: var(--coral);">🐱</div>
<div class="info"><div class="name">Pat</div><div class="stat">submitted drawing</div></div>
<div class="pulse"></div>
</div>
<div class="ps-item drawing you">
<div class="av" style="background: var(--mint);">🦊</div>
<div class="info"><div class="name">Suki (you)</div><div class="stat">drawing now...</div></div>
<div class="pulse"></div>
</div>
<div class="ps-item drawing">
<div class="av" style="background: var(--lavender);">🐼</div>
<div class="info"><div class="name">Ravi</div><div class="stat">drawing now...</div></div>
<div class="pulse"></div>
</div>
<div class="ps-item drawing">
<div class="av" style="background: var(--sky);">🐸</div>
<div class="info"><div class="name">Jules</div><div class="stat">drawing now...</div></div>
<div class="pulse"></div>
</div>
</div>
<div class="tip">
<strong>Tip:</strong> No one sees your drawing until everyone submits — it gets passed to the next player to guess what it is.
</div>
</aside>
</main>
</body>
</html>
+367
View File
@@ -0,0 +1,367 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Color Together - DrawTogether</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--yellow: #FFD23F; --coral: #FF5C5C; --mint: #4ECDC4;
--lavender: #A593E0; --sky: #5BCEFA; --dark: #2D2D2D;
--cream: #FFF8E7; --white: #FFFFFF;
--shadow-card: 0 6px 0 rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);
--shadow-btn: 0 5px 0 rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.12);
}
html, body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--dark); background: var(--cream); -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; }
.game-header {
display: flex; align-items: center; justify-content: space-between;
padding: 14px 22px; max-width: 1500px; margin: 0 auto;
}
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 20px; text-decoration: none; color: inherit; }
.logo-mark { width: 38px; height: 38px; border-radius: 12px; background: var(--lavender); display: grid; place-items: center; box-shadow: var(--shadow-card); transform: rotate(-6deg); }
.header-pills { display: flex; gap: 10px; align-items: center; }
.pill-info { padding: 8px 16px; background: var(--white); border: 2px solid var(--dark); border-radius: 999px; font-weight: 700; font-size: 13px; box-shadow: 0 3px 0 rgba(0,0,0,0.1); display: inline-flex; align-items: center; gap: 6px; }
.pill-info.online { background: var(--mint); }
.leave-btn { padding: 8px 14px; background: var(--white); border: 2px solid var(--dark); border-radius: 999px; font-family: inherit; font-weight: 700; font-size: 13px; cursor: pointer; box-shadow: 0 3px 0 rgba(0,0,0,0.1); display: inline-flex; align-items: center; gap: 6px; }
/* Big mode banner */
.mode-banner { max-width: 1500px; margin: 0 auto; padding: 0 22px 14px; }
.mode-banner-inner {
background: var(--white); border: 3px solid var(--dark); border-radius: 18px; padding: 14px 22px;
box-shadow: var(--shadow-card); display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.mode-banner-inner h1 { font-size: 22px; font-weight: 700; display: flex; align-items: center; gap: 10px; }
.mode-banner-inner h1 .ic { width: 34px; height: 34px; border-radius: 10px; background: var(--lavender); border: 2px solid var(--dark); display: grid; place-items: center; }
.mode-banner-inner .sub { font-weight: 600; font-size: 14px; color: rgba(45,45,45,0.65); margin-top: 2px; padding-left: 44px; }
.header-actions { display: flex; gap: 8px; }
.action-btn {
font-family: inherit; font-weight: 700; font-size: 14px; padding: 10px 18px;
border-radius: 999px; border: 2px solid var(--dark); cursor: pointer;
box-shadow: 0 4px 0 rgba(0,0,0,0.15); display: inline-flex; align-items: center; gap: 6px;
transition: transform 0.15s ease;
}
.action-btn:hover { transform: translateY(-2px); }
.action-btn.primary { background: var(--coral); color: white; }
.action-btn.secondary { background: var(--white); }
main {
max-width: 1500px; margin: 0 auto; padding: 0 22px 30px;
display: grid; grid-template-columns: 240px 1fr 240px; gap: 18px;
}
.panel { background: var(--white); border: 3px solid var(--dark); border-radius: 20px; padding: 16px; box-shadow: var(--shadow-card); }
.panel-title { font-size: 13px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: rgba(45,45,45,0.6); margin-bottom: 12px; padding-left: 4px; }
/* Tools panel (left) */
.tool-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tool-cell {
background: var(--cream); border: 2px solid var(--dark); border-radius: 14px;
padding: 12px 8px; display: flex; flex-direction: column; align-items: center; gap: 6px;
cursor: pointer; box-shadow: 0 3px 0 rgba(0,0,0,0.15);
transition: transform 0.15s ease;
}
.tool-cell:hover { transform: translateY(-2px); }
.tool-cell.active { background: var(--yellow); }
.tool-cell .lbl { font-size: 11px; font-weight: 700; }
.brush-section { margin-top: 14px; }
.brush-section .brush-row { display: flex; gap: 8px; align-items: center; padding: 8px 4px; }
.brush-size { width: 36px; height: 36px; border-radius: 10px; border: 2px solid var(--dark); background: var(--cream); display: grid; place-items: center; cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.15); }
.brush-size .dot { background: var(--dark); border-radius: 50%; }
.brush-size .dot.s1 { width: 5px; height: 5px; }
.brush-size .dot.s2 { width: 9px; height: 9px; }
.brush-size .dot.s3 { width: 14px; height: 14px; }
.brush-size .dot.s4 { width: 18px; height: 18px; }
.brush-size.active { background: var(--mint); }
/* Center: canvas */
.canvas-wrap {
background: var(--white); border: 3px solid var(--dark); border-radius: 20px; box-shadow: var(--shadow-card);
padding: 18px; display: flex; flex-direction: column; gap: 12px; min-height: 600px;
}
.canvas-stage {
flex: 1; background: var(--cream); border: 2px dashed rgba(45,45,45,0.18);
border-radius: 14px; position: relative; overflow: hidden; display: grid; place-items: center;
min-height: 540px;
}
.presence-cursor {
position: absolute; pointer-events: none; z-index: 5;
display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
}
.presence-cursor .arrow { width: 18px; height: 18px; }
.presence-cursor .tag {
padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 700;
border: 2px solid var(--dark); color: white; box-shadow: 0 2px 0 rgba(0,0,0,0.15);
margin-left: 12px;
}
.pc1 { top: 110px; left: 30%; }
.pc1 .tag { background: var(--coral); }
.pc2 { top: 280px; right: 22%; }
.pc2 .tag { background: var(--mint); color: var(--dark); }
.pc3 { bottom: 100px; left: 22%; }
.pc3 .tag { background: var(--lavender); }
/* Right: color picker / palette / chat */
.hsl-wheel { width: 100%; aspect-ratio: 1; border-radius: 50%; position: relative; border: 3px solid var(--dark); box-shadow: var(--shadow-card);
background: conic-gradient(from 0deg,
hsl(0,80%,55%), hsl(30,80%,55%), hsl(60,80%,55%), hsl(90,80%,55%),
hsl(120,80%,55%), hsl(150,80%,55%), hsl(180,80%,55%), hsl(210,80%,55%),
hsl(240,80%,55%), hsl(270,80%,55%), hsl(300,80%,55%), hsl(330,80%,55%), hsl(360,80%,55%));
margin-bottom: 14px;
}
.hsl-wheel::after {
content: ''; position: absolute; inset: 12px; border-radius: 50%;
background: radial-gradient(circle at center, white, transparent 70%);
pointer-events: none;
}
.hsl-wheel .marker {
position: absolute; width: 22px; height: 22px; border-radius: 50%;
background: var(--coral); border: 3px solid var(--white); box-shadow: 0 0 0 2px var(--dark);
top: 18%; right: 22%;
}
.selected-color {
display: flex; align-items: center; gap: 10px; padding: 10px;
background: var(--cream); border-radius: 12px; border: 2px solid var(--dark);
}
.selected-color .swatch {
width: 40px; height: 40px; border-radius: 10px; background: var(--coral);
border: 2px solid var(--dark); box-shadow: 0 2px 0 rgba(0,0,0,0.15);
}
.selected-color .info { flex: 1; }
.selected-color .name { font-weight: 700; font-size: 14px; }
.selected-color .hex { font-size: 12px; font-weight: 600; color: rgba(45,45,45,0.6); font-family: monospace; }
.recent-row { display: flex; gap: 6px; flex-wrap: wrap; padding: 8px 0; }
.recent-swatch {
width: 28px; height: 28px; border-radius: 8px; border: 2px solid var(--dark);
cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.15);
}
.who-online { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.who-row { display: flex; align-items: center; gap: 8px; padding: 6px 10px; background: var(--cream); border-radius: 10px; }
.who-row .av { width: 28px; height: 28px; border-radius: 8px; border: 2px solid var(--dark); display: grid; place-items: center; font-size: 16px; }
.who-row .name { font-weight: 700; font-size: 13px; flex: 1; }
.who-row .dot { width: 8px; height: 8px; background: var(--mint); border-radius: 50%; }
@media (max-width: 1100px) {
main { grid-template-columns: 1fr; }
.canvas-wrap { min-height: 480px; }
}
</style>
</head>
<body>
<header class="game-header">
<a class="logo" href="01-landing.html">
<div class="logo-mark"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><circle cx="13.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="10.5" r="2.5"/><circle cx="8.5" cy="7.5" r="2.5"/><circle cx="6.5" cy="12.5" r="2.5"/><path d="M12 22a10 10 0 1 1 10-10c0 4-3 4-4 4h-3a2 2 0 0 0-1 4 2 2 0 0 1-1 4z"/></svg></div>
DrawTogether
</a>
<div class="header-pills">
<span class="pill-info online">
<span style="width: 8px; height: 8px; background: var(--dark); border-radius: 50%;"></span>
4 online
</span>
<span class="pill-info">MIA42K</span>
<button class="leave-btn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg>
Leave
</button>
</div>
</header>
<section class="mode-banner">
<div class="mode-banner-inner">
<div>
<h1><span class="ic"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><circle cx="13.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="10.5" r="2.5"/><circle cx="8.5" cy="7.5" r="2.5"/><circle cx="6.5" cy="12.5" r="2.5"/></svg></span> Color Together — 4 players online</h1>
<div class="sub">Mandala canvas · auto-saving every 30s</div>
</div>
<div class="header-actions">
<button class="action-btn secondary" data-testid="btn-reset">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M3 7v6h6M21 17a9 9 0 0 0-15-6.7L3 13"/></svg>
Reset
</button>
<button class="action-btn primary" data-testid="btn-snapshot">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M19 21H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h3.5l2-3h6l2 3H21a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2z"/><circle cx="12" cy="13" r="4"/></svg>
Save Snapshot
</button>
</div>
</div>
</section>
<main>
<!-- Tools (left) -->
<aside class="panel" data-testid="panel-tools">
<div class="panel-title">Tools</div>
<div class="tool-grid">
<div class="tool-cell active" data-testid="tool-brush">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
<span class="lbl">BRUSH</span>
</div>
<div class="tool-cell" data-testid="tool-bucket">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M19 11l-7-7-9 9 7 7 9-9z"/><path d="M5 13l4 4M19 11c1 0 2 1 2 3a3 3 0 1 1-6 0c0-1 1-3 1-3"/></svg>
<span class="lbl">FILL</span>
</div>
<div class="tool-cell" data-testid="tool-eraser">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M20 20H7L3 16a2 2 0 0 1 0-3l9-9a2 2 0 0 1 3 0l6 6a2 2 0 0 1 0 3l-7 7"/></svg>
<span class="lbl">ERASER</span>
</div>
<div class="tool-cell" data-testid="tool-picker">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M2 22l4-4M19 5l-9 9 5 5 9-9-5-5z"/><path d="M19 5l3-3"/></svg>
<span class="lbl">PICKER</span>
</div>
</div>
<div class="brush-section">
<div class="panel-title" style="margin-bottom: 6px;">Brush size</div>
<div class="brush-row">
<div class="brush-size"><span class="dot s1"></span></div>
<div class="brush-size active"><span class="dot s2"></span></div>
<div class="brush-size"><span class="dot s3"></span></div>
<div class="brush-size"><span class="dot s4"></span></div>
</div>
</div>
<div class="brush-section">
<div class="panel-title" style="margin-bottom: 6px;">History</div>
<div style="display: flex; gap: 8px;">
<button class="action-btn secondary" style="padding: 8px 12px; flex: 1; justify-content: center;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M3 7v6h6M21 17a9 9 0 0 0-15-6.7L3 13"/></svg>
Undo
</button>
<button class="action-btn secondary" style="padding: 8px 12px; flex: 1; justify-content: center;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M21 7v6h-6M3 17a9 9 0 0 1 15-6.7L21 13"/></svg>
Redo
</button>
</div>
</div>
</aside>
<!-- Canvas -->
<section class="canvas-wrap">
<div class="canvas-stage" data-testid="canvas">
<!-- Mandala SVG -->
<svg viewBox="0 0 600 600" width="100%" height="100%" preserveAspectRatio="xMidYMid meet" style="max-width: 580px;">
<defs>
<radialGradient id="centerGrad" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFD23F"/>
<stop offset="100%" stop-color="#FF8C42"/>
</radialGradient>
</defs>
<!-- outer ring -->
<circle cx="300" cy="300" r="270" fill="none" stroke="#2D2D2D" stroke-width="3"/>
<circle cx="300" cy="300" r="220" fill="none" stroke="#2D2D2D" stroke-width="3"/>
<circle cx="300" cy="300" r="160" fill="rgba(165,147,224,0.5)" stroke="#2D2D2D" stroke-width="3"/>
<circle cx="300" cy="300" r="100" fill="rgba(91,206,250,0.65)" stroke="#2D2D2D" stroke-width="3"/>
<circle cx="300" cy="300" r="50" fill="url(#centerGrad)" stroke="#2D2D2D" stroke-width="3"/>
<!-- 8 petals outer -->
<g>
<g transform="translate(300 300)">
<g id="petal-set">
<path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="rgba(255,92,92,0.65)" stroke="#2D2D2D" stroke-width="3"/>
</g>
</g>
<g transform="translate(300 300) rotate(45)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="rgba(255,210,63,0.7)" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(90)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="none" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(135)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="rgba(78,205,196,0.65)" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(180)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="rgba(255,92,92,0.65)" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(225)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="none" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(270)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="rgba(255,210,63,0.7)" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(315)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -160 0 -270 Z" fill="none" stroke="#2D2D2D" stroke-width="3"/></g>
</g>
<!-- inner petals -->
<g>
<g transform="translate(300 300) rotate(22.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="rgba(165,147,224,0.7)" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(67.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="none" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(112.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="rgba(255,140,66,0.6)" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(157.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="none" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(202.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="rgba(165,147,224,0.7)" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(247.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="none" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(292.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="rgba(255,140,66,0.6)" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(337.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="none" stroke="#2D2D2D" stroke-width="2.5"/></g>
</g>
<!-- center detail -->
<circle cx="300" cy="300" r="22" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="2.5"/>
<g>
<circle cx="300" cy="270" r="8" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2"/>
<circle cx="330" cy="300" r="8" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2"/>
<circle cx="300" cy="330" r="8" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2"/>
<circle cx="270" cy="300" r="8" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2"/>
</g>
</svg>
<!-- presence cursors -->
<div class="presence-cursor pc1">
<svg class="arrow" viewBox="0 0 24 24" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="2"><path d="M3 3l7 18 2-9 9-2z"/></svg>
<span class="tag">Mia</span>
</div>
<div class="presence-cursor pc2">
<svg class="arrow" viewBox="0 0 24 24" fill="#4ECDC4" stroke="#2D2D2D" stroke-width="2"><path d="M3 3l7 18 2-9 9-2z"/></svg>
<span class="tag">Ravi</span>
</div>
<div class="presence-cursor pc3">
<svg class="arrow" viewBox="0 0 24 24" fill="#A593E0" stroke="#2D2D2D" stroke-width="2"><path d="M3 3l7 18 2-9 9-2z"/></svg>
<span class="tag">Jules</span>
</div>
</div>
</section>
<!-- Right: color picker -->
<aside class="panel" data-testid="panel-colors">
<div class="panel-title">Color picker</div>
<div class="hsl-wheel" data-testid="hsl-wheel">
<div class="marker"></div>
</div>
<div class="selected-color">
<div class="swatch"></div>
<div class="info">
<div class="name">Coral red</div>
<div class="hex">#FF5C5C</div>
</div>
</div>
<div class="panel-title" style="margin-top: 16px; margin-bottom: 4px;">Recent</div>
<div class="recent-row">
<div class="recent-swatch" style="background: #FF5C5C;"></div>
<div class="recent-swatch" style="background: #FFD23F;"></div>
<div class="recent-swatch" style="background: #4ECDC4;"></div>
<div class="recent-swatch" style="background: #A593E0;"></div>
<div class="recent-swatch" style="background: #FF8C42;"></div>
<div class="recent-swatch" style="background: #5BCEFA;"></div>
<div class="recent-swatch" style="background: #6BCB77;"></div>
<div class="recent-swatch" style="background: #2D2D2D;"></div>
</div>
<div class="panel-title" style="margin-top: 18px; margin-bottom: 4px;">Drawing now</div>
<div class="who-online">
<div class="who-row">
<div class="av" style="background: var(--yellow);">🦄</div>
<div class="name">Mia</div>
<div class="dot"></div>
</div>
<div class="who-row">
<div class="av" style="background: var(--coral);">🦊</div>
<div class="name">Suki (you)</div>
<div class="dot"></div>
</div>
<div class="who-row">
<div class="av" style="background: var(--lavender);">🐼</div>
<div class="name">Ravi</div>
<div class="dot"></div>
</div>
<div class="who-row">
<div class="av" style="background: var(--sky);">🐸</div>
<div class="name">Jules</div>
<div class="dot"></div>
</div>
</div>
</aside>
</main>
</body>
</html>
+427
View File
@@ -0,0 +1,427 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Game Over - DrawTogether</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--yellow: #FFD23F; --coral: #FF5C5C; --mint: #4ECDC4;
--lavender: #A593E0; --sky: #5BCEFA; --dark: #2D2D2D;
--cream: #FFF8E7; --white: #FFFFFF;
--shadow-card: 0 6px 0 rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);
--shadow-btn: 0 5px 0 rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.12);
}
html, body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--dark); background: var(--cream); -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; position: relative; overflow-x: hidden; }
/* confetti */
.confetti { position: absolute; pointer-events: none; }
.c1 { top: 80px; left: 8%; animation: float 4s ease-in-out infinite; }
.c2 { top: 140px; right: 10%; animation: float 4s ease-in-out infinite 1s; }
.c3 { top: 60px; left: 40%; animation: float 4s ease-in-out infinite 2s; }
@keyframes float { 0%,100% { transform: translateY(0) rotate(-8deg);} 50%{transform: translateY(-12px) rotate(8deg);} }
.site-header { display: flex; align-items: center; justify-content: space-between; padding: 20px 32px; max-width: 1280px; margin: 0 auto; position: relative; z-index: 2; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 22px; text-decoration: none; color: inherit; }
.logo-mark { width: 42px; height: 42px; border-radius: 12px; background: var(--coral); display: grid; place-items: center; box-shadow: var(--shadow-card); transform: rotate(-6deg); }
main { max-width: 1100px; margin: 0 auto; padding: 12px 28px 80px; position: relative; z-index: 2; }
.page-title { text-align: center; margin-bottom: 22px; }
.page-title h1 { font-size: clamp(36px, 5vw, 56px); font-weight: 700; letter-spacing: -0.5px; }
.page-title .accent-bg { background: var(--yellow); padding: 0 14px; border-radius: 12px; display: inline-block; transform: rotate(-1deg); }
.page-title p { font-weight: 600; color: rgba(45,45,45,0.65); margin-top: 8px; font-size: 17px; }
/* Tabs */
.tabs-wrap { display: flex; justify-content: center; margin-bottom: 24px; }
.tabs {
display: inline-flex; padding: 6px; background: var(--white); border: 3px solid var(--dark);
border-radius: 999px; box-shadow: var(--shadow-card); gap: 4px;
}
.tab-input { position: absolute; opacity: 0; pointer-events: none; }
.tab-label {
padding: 10px 22px; border-radius: 999px; font-weight: 700; font-size: 14px;
cursor: pointer; transition: all 0.18s ease; display: inline-flex; align-items: center; gap: 8px;
}
.tab-label:hover { background: var(--cream); }
/* Use sibling order: tabs grouped at top, panels show via :checked + general sibling combinator */
#tab-skribbl:checked ~ .tabs-wrap label[for=tab-skribbl],
#tab-gartic:checked ~ .tabs-wrap label[for=tab-gartic],
#tab-color:checked ~ .tabs-wrap label[for=tab-color] {
background: var(--coral); color: white; box-shadow: 0 4px 0 rgba(0,0,0,0.18);
}
.tab-panel { display: none; }
#tab-skribbl:checked ~ #panel-skribbl { display: block; }
#tab-gartic:checked ~ #panel-gartic { display: block; }
#tab-color:checked ~ #panel-color { display: block; }
/* Skribbl panel */
.podium {
display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; align-items: end;
margin-bottom: 24px;
}
.podium-card {
background: var(--white); border: 3px solid var(--dark); border-radius: 22px;
padding: 22px 18px; box-shadow: var(--shadow-card);
text-align: center; position: relative;
transition: transform 0.18s ease;
}
.podium-card:hover { transform: translateY(-4px); }
.podium-card .av {
width: 72px; height: 72px; border-radius: 22px; border: 3px solid var(--dark);
display: grid; place-items: center; font-size: 38px;
margin: 0 auto 10px; box-shadow: 0 4px 0 rgba(0,0,0,0.15);
}
.podium-card.first { background: var(--yellow); padding-top: 36px; padding-bottom: 32px; }
.podium-card.first .av { background: var(--white); width: 84px; height: 84px; font-size: 44px; }
.podium-card.second { background: var(--white); }
.podium-card.second .av { background: var(--mint); }
.podium-card.third { background: var(--white); }
.podium-card.third .av { background: var(--lavender); }
.trophy-row { display: flex; justify-content: center; gap: 6px; margin-bottom: 6px; }
.trophy {
width: 38px; height: 38px; border-radius: 12px;
display: grid; place-items: center; border: 2px solid var(--dark);
box-shadow: 0 3px 0 rgba(0,0,0,0.18);
}
.trophy.gold { background: var(--yellow); }
.trophy.silver { background: #D3D3D3; }
.trophy.bronze { background: #CD7F32; }
.podium-card .name { font-size: 22px; font-weight: 700; }
.podium-card .pts { font-size: 14px; font-weight: 600; color: rgba(45,45,45,0.7); margin-top: 2px; }
.podium-card .pts strong { font-size: 28px; color: var(--coral); display: block; margin-top: 4px; }
.podium-card.first .pts strong { color: var(--dark); font-size: 36px; }
.ribbon {
position: absolute; top: -14px; left: 50%; transform: translateX(-50%);
background: var(--coral); color: white; padding: 4px 14px; border-radius: 999px;
border: 2px solid var(--dark); font-size: 12px; font-weight: 700; letter-spacing: 1px;
box-shadow: 0 3px 0 rgba(0,0,0,0.18);
}
/* Other rankings */
.rest-list { background: var(--white); border: 3px solid var(--dark); border-radius: 20px; padding: 18px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.rest-row { display: flex; align-items: center; gap: 14px; padding: 12px 8px; border-bottom: 2px dashed rgba(45,45,45,0.12); }
.rest-row:last-child { border-bottom: none; }
.rest-row .rank { width: 36px; height: 36px; background: var(--cream); border: 2px solid var(--dark); border-radius: 10px; display: grid; place-items: center; font-weight: 700; flex-shrink: 0; }
.rest-row .av { width: 40px; height: 40px; border-radius: 12px; border: 2px solid var(--dark); display: grid; place-items: center; font-size: 22px; flex-shrink: 0; }
.rest-row .info { flex: 1; }
.rest-row .name { font-weight: 700; }
.rest-row .stats { font-size: 12px; font-weight: 600; color: rgba(45,45,45,0.6); }
.rest-row .pts { font-weight: 700; font-size: 18px; color: var(--coral); }
/* Action buttons */
.actions { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.btn { font-family: inherit; font-weight: 700; font-size: 17px; padding: 16px 32px; border-radius: 999px; border: 3px solid var(--dark); cursor: pointer; box-shadow: var(--shadow-btn); transition: transform 0.15s ease; display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.btn:hover { transform: translateY(-2px); }
.btn-primary { background: var(--coral); color: white; }
.btn-secondary { background: var(--mint); color: var(--dark); }
.btn-ghost { background: var(--white); color: var(--dark); }
/* Gartic panel — book playback */
.book-card { background: var(--white); border: 3px solid var(--dark); border-radius: 22px; padding: 22px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.book-meta { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.book-meta .b-info { display: flex; align-items: center; gap: 10px; }
.book-meta .av { width: 40px; height: 40px; border-radius: 12px; border: 2px solid var(--dark); display: grid; place-items: center; font-size: 22px; }
.book-meta h3 { font-size: 18px; font-weight: 700; }
.book-meta .meta { font-size: 13px; font-weight: 600; color: rgba(45,45,45,0.6); }
.book-nav { display: flex; gap: 8px; align-items: center; font-weight: 700; font-size: 13px; color: rgba(45,45,45,0.7); }
.nav-btn { width: 34px; height: 34px; background: var(--cream); border: 2px solid var(--dark); border-radius: 10px; display: grid; place-items: center; cursor: pointer; box-shadow: 0 3px 0 rgba(0,0,0,0.15); }
.book-strip { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px; }
.strip-card {
background: var(--cream); border: 2px solid var(--dark); border-radius: 16px;
padding: 12px; display: flex; flex-direction: column; gap: 8px;
box-shadow: 0 3px 0 rgba(0,0,0,0.12);
}
.strip-card .author { display: flex; align-items: center; gap: 6px; font-weight: 700; font-size: 12px; }
.strip-card .author .av { width: 22px; height: 22px; border-radius: 7px; border: 2px solid var(--dark); display: grid; place-items: center; font-size: 12px; }
.strip-card .stage { font-size: 10px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: rgba(45,45,45,0.55); }
.strip-card .content {
flex: 1; min-height: 130px; background: var(--white); border-radius: 10px; border: 2px dashed rgba(45,45,45,0.2);
display: grid; place-items: center; padding: 10px; text-align: center;
}
.strip-card .content.text { font-size: 14px; font-weight: 700; line-height: 1.3; color: var(--dark); }
.strip-card .arrow {
position: relative;
}
/* Color final image panel */
.final-canvas-wrap { background: var(--white); border: 3px solid var(--dark); border-radius: 22px; padding: 22px; box-shadow: var(--shadow-card); margin-bottom: 24px; }
.final-canvas-stage { background: var(--cream); border-radius: 16px; padding: 18px; display: grid; place-items: center; min-height: 380px; border: 2px dashed rgba(45,45,45,0.2); }
.canvas-meta { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; flex-wrap: wrap; gap: 10px; }
.canvas-meta h3 { font-size: 22px; font-weight: 700; }
.canvas-meta .stats { display: flex; gap: 10px; flex-wrap: wrap; }
.stat-pill { padding: 6px 14px; background: var(--cream); border: 2px solid var(--dark); border-radius: 999px; font-size: 12px; font-weight: 700; }
.contributors { display: flex; gap: -8px; }
.contributors .av { width: 32px; height: 32px; border-radius: 10px; border: 2px solid var(--dark); display: grid; place-items: center; font-size: 16px; margin-left: -6px; }
.contributors .av:first-child { margin-left: 0; }
@media (max-width: 800px) {
.podium { grid-template-columns: 1fr; }
.book-strip { grid-template-columns: 1fr 1fr; }
}
</style>
</head>
<body>
<svg class="confetti c1" width="40" height="40" viewBox="0 0 24 24" fill="#FFD23F" stroke="#2D2D2D" stroke-width="2.5"><polygon points="12 2 15 9 22 9 17 14 19 21 12 17 5 21 7 14 2 9 9 9"/></svg>
<svg class="confetti c2" width="36" height="36" viewBox="0 0 24 24" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="2.5"><circle cx="12" cy="12" r="9"/></svg>
<svg class="confetti c3" width="44" height="44" viewBox="0 0 24 24" fill="#A593E0" stroke="#2D2D2D" stroke-width="2.5"><rect x="3" y="3" width="18" height="18" rx="3"/></svg>
<header class="site-header">
<a class="logo" href="01-landing.html">
<div class="logo-mark"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg></div>
DrawTogether
</a>
<a href="04-lobby.html" class="btn btn-ghost" style="padding: 10px 20px; font-size: 14px; border-width: 2px;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
Back to lobby
</a>
</header>
<main>
<div class="page-title">
<h1>Game over — <span class="accent-bg">nice work</span></h1>
<p>5 rounds. 5 players. 1 absolute legend.</p>
</div>
<!-- Tab inputs MUST come before .tabs-wrap and panels for sibling combinator -->
<input type="radio" name="results-tab" id="tab-skribbl" class="tab-input" checked>
<input type="radio" name="results-tab" id="tab-gartic" class="tab-input">
<input type="radio" name="results-tab" id="tab-color" class="tab-input">
<div class="tabs-wrap">
<div class="tabs" data-testid="result-tabs">
<label class="tab-label" for="tab-skribbl" data-testid="tab-skribbl">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/></svg>
Skribbl scores
</label>
<label class="tab-label" for="tab-gartic" data-testid="tab-gartic">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
Gartic book
</label>
<label class="tab-label" for="tab-color" data-testid="tab-color">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><circle cx="13.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="10.5" r="2.5"/><circle cx="8.5" cy="7.5" r="2.5"/><circle cx="6.5" cy="12.5" r="2.5"/></svg>
Color final
</label>
</div>
</div>
<!-- Skribbl panel -->
<section id="panel-skribbl" class="tab-panel" data-testid="panel-skribbl">
<div class="podium">
<article class="podium-card second">
<div class="trophy-row"><div class="trophy silver"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><circle cx="12" cy="8" r="6"/><path d="M9 14l-3 7 6-3 6 3-3-7"/></svg></div></div>
<div class="av">🦊</div>
<div class="name">Suki</div>
<div class="pts">2nd · <strong>1840</strong> pts</div>
</article>
<article class="podium-card first">
<div class="ribbon">CHAMPION</div>
<div class="trophy-row"><div class="trophy gold"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"><circle cx="12" cy="8" r="6"/><path d="M9 14l-3 7 6-3 6 3-3-7"/></svg></div></div>
<div class="av">🦄</div>
<div class="name">Mia</div>
<div class="pts">1st · <strong>2310</strong></div>
</article>
<article class="podium-card third">
<div class="trophy-row"><div class="trophy bronze"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><circle cx="12" cy="8" r="6"/><path d="M9 14l-3 7 6-3 6 3-3-7"/></svg></div></div>
<div class="av">🐼</div>
<div class="name">Ravi</div>
<div class="pts">3rd · <strong>1620</strong> pts</div>
</article>
</div>
<div class="rest-list">
<div class="rest-row">
<div class="rank">4</div>
<div class="av" style="background: var(--sky);">🐸</div>
<div class="info">
<div class="name">Jules</div>
<div class="stats">3 correct guesses · 1 perfect drawing</div>
</div>
<div class="pts">1410</div>
</div>
<div class="rest-row">
<div class="rank">5</div>
<div class="av" style="background: var(--coral);">🐱</div>
<div class="info">
<div class="name">Pat</div>
<div class="stats">2 correct guesses · funniest player award 🤣</div>
</div>
<div class="pts">1180</div>
</div>
</div>
<div class="actions">
<a href="04-lobby.html" class="btn btn-primary" data-testid="btn-play-again">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>
Play Again
</a>
<a href="02-create-room.html" class="btn btn-secondary" data-testid="btn-new-game">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
New Game
</a>
<a href="01-landing.html" class="btn btn-ghost">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
Home
</a>
</div>
</section>
<!-- Gartic book panel -->
<section id="panel-gartic" class="tab-panel" data-testid="panel-gartic">
<div class="book-card">
<div class="book-meta">
<div class="b-info">
<div class="av" style="background: var(--yellow);">🦄</div>
<div>
<h3>Mia's book</h3>
<div class="meta">5 chapters · started with a prompt</div>
</div>
</div>
<div class="book-nav">
<button class="nav-btn"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><polyline points="15 18 9 12 15 6"/></svg></button>
<span>Book 1 / 5</span>
<button class="nav-btn"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><polyline points="9 18 15 12 9 6"/></svg></button>
</div>
</div>
<div class="book-strip">
<div class="strip-card">
<div class="stage">Prompt</div>
<div class="author"><div class="av" style="background: var(--yellow);">🦄</div> Mia</div>
<div class="content text">"a cat riding a unicorn"</div>
</div>
<div class="strip-card">
<div class="stage">Drawing</div>
<div class="author"><div class="av" style="background: var(--mint);">🦊</div> Suki</div>
<div class="content">
<svg viewBox="0 0 100 100" width="100%" height="100%">
<ellipse cx="50" cy="65" rx="35" ry="18" fill="#A593E0" stroke="#2D2D2D" stroke-width="2.5"/>
<circle cx="32" cy="58" r="14" fill="#FFD23F" stroke="#2D2D2D" stroke-width="2.5"/>
<polygon points="22,48 22,38 32,46" fill="#FFD23F" stroke="#2D2D2D" stroke-width="2"/>
<polygon points="40,46 40,38 30,46" fill="#FFD23F" stroke="#2D2D2D" stroke-width="2"/>
<circle cx="29" cy="58" r="1.5" fill="#2D2D2D"/>
<circle cx="35" cy="58" r="1.5" fill="#2D2D2D"/>
<polygon points="70,42 75,30 80,42" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="2.5" stroke-linejoin="round"/>
<line x1="20" y1="80" x2="20" y2="88" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"/>
<line x1="40" y1="80" x2="40" y2="88" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"/>
<line x1="60" y1="80" x2="60" y2="88" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"/>
<line x1="80" y1="80" x2="80" y2="88" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"/>
</svg>
</div>
</div>
<div class="strip-card">
<div class="stage">Guess</div>
<div class="author"><div class="av" style="background: var(--lavender);">🐼</div> Ravi</div>
<div class="content text">"horse with a small dragon on top"</div>
</div>
<div class="strip-card">
<div class="stage">Drawing</div>
<div class="author"><div class="av" style="background: var(--sky);">🐸</div> Jules</div>
<div class="content">
<svg viewBox="0 0 100 100" width="100%" height="100%">
<ellipse cx="50" cy="65" rx="34" ry="20" fill="#B5651D" stroke="#2D2D2D" stroke-width="2.5"/>
<circle cx="22" cy="55" r="12" fill="#B5651D" stroke="#2D2D2D" stroke-width="2.5"/>
<polygon points="14,46 16,38 24,48" fill="#B5651D" stroke="#2D2D2D" stroke-width="2"/>
<ellipse cx="55" cy="38" rx="14" ry="10" fill="#4ECDC4" stroke="#2D2D2D" stroke-width="2.5"/>
<path d="M50 30 Q55 20 60 30" stroke="#FF5C5C" stroke-width="2.5" fill="none" stroke-linecap="round"/>
<line x1="20" y1="80" x2="20" y2="92" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"/>
<line x1="40" y1="80" x2="40" y2="92" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"/>
<line x1="60" y1="80" x2="60" y2="92" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"/>
<line x1="80" y1="80" x2="80" y2="92" stroke="#2D2D2D" stroke-width="2.5" stroke-linecap="round"/>
</svg>
</div>
</div>
<div class="strip-card">
<div class="stage">Guess</div>
<div class="author"><div class="av" style="background: var(--coral);">🐱</div> Pat</div>
<div class="content text">"a brown horse drinking from a cute pond 💧"</div>
</div>
</div>
</div>
<div class="actions">
<a href="04-lobby.html" class="btn btn-primary">Play Again</a>
<a href="02-create-room.html" class="btn btn-secondary">New Game</a>
</div>
</section>
<!-- Color final panel -->
<section id="panel-color" class="tab-panel" data-testid="panel-color">
<div class="final-canvas-wrap">
<div class="canvas-meta">
<div>
<h3>Mandala by the crew</h3>
<div style="font-weight:600; color: rgba(45,45,45,0.6); font-size:13px; margin-top:2px;">Created in 18 minutes · 4 contributors</div>
</div>
<div class="stats">
<span class="stat-pill">412 strokes</span>
<span class="stat-pill">8 colors used</span>
</div>
<div class="contributors">
<div class="av" style="background: var(--yellow);">🦄</div>
<div class="av" style="background: var(--mint);">🦊</div>
<div class="av" style="background: var(--lavender);">🐼</div>
<div class="av" style="background: var(--sky);">🐸</div>
</div>
</div>
<div class="final-canvas-stage">
<svg viewBox="0 0 600 600" width="100%" height="100%" preserveAspectRatio="xMidYMid meet" style="max-width: 460px;">
<defs>
<radialGradient id="centerGrad2" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFD23F"/>
<stop offset="100%" stop-color="#FF8C42"/>
</radialGradient>
</defs>
<circle cx="300" cy="300" r="270" fill="rgba(91,206,250,0.2)" stroke="#2D2D2D" stroke-width="3"/>
<circle cx="300" cy="300" r="220" fill="rgba(255,210,63,0.35)" stroke="#2D2D2D" stroke-width="3"/>
<circle cx="300" cy="300" r="160" fill="rgba(165,147,224,0.7)" stroke="#2D2D2D" stroke-width="3"/>
<circle cx="300" cy="300" r="100" fill="rgba(78,205,196,0.85)" stroke="#2D2D2D" stroke-width="3"/>
<circle cx="300" cy="300" r="50" fill="url(#centerGrad2)" stroke="#2D2D2D" stroke-width="3"/>
<g transform="translate(300 300)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(45)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="#FFD23F" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(90)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="#A593E0" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(135)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="#4ECDC4" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(180)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="#FF5C5C" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(225)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="#FFD23F" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(270)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="#A593E0" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(315)"><path d="M0 -270 Q 22 -210 0 -160 Q -22 -210 0 -270 Z" fill="#4ECDC4" stroke="#2D2D2D" stroke-width="3"/></g>
<g transform="translate(300 300) rotate(22.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(67.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="#FF8C42" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(112.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(157.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="#FF8C42" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(202.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(247.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="#FF8C42" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(292.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2.5"/></g>
<g transform="translate(300 300) rotate(337.5)"><path d="M0 -210 Q 18 -180 0 -160 Q -18 -180 0 -210 Z" fill="#FF8C42" stroke="#2D2D2D" stroke-width="2.5"/></g>
<circle cx="300" cy="300" r="22" fill="#2D2D2D" stroke="#2D2D2D" stroke-width="2.5"/>
<circle cx="300" cy="270" r="8" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2"/>
<circle cx="330" cy="300" r="8" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2"/>
<circle cx="300" cy="330" r="8" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2"/>
<circle cx="270" cy="300" r="8" fill="#FFF8E7" stroke="#2D2D2D" stroke-width="2"/>
</svg>
</div>
</div>
<div class="actions">
<button class="btn btn-primary" data-testid="btn-download">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>
Download artwork
</button>
<a href="02-create-room.html" class="btn btn-secondary">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
New Canvas
</a>
</div>
</section>
</main>
</body>
</html>
+165
View File
@@ -0,0 +1,165 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>DrawTogether — Design Mockups</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
font-family:'Fredoka',system-ui,sans-serif;
background:#FFF8E7;
color:#2D2D2D;
min-height:100vh;
padding:48px 24px 96px;
}
.wrap{max-width:1100px;margin:0 auto}
header{text-align:center;margin-bottom:48px}
.logo{
display:inline-block;
background:#FFD23F;
border:3px solid #2D2D2D;
border-radius:999px;
padding:8px 24px;
font-weight:700;
font-size:18px;
box-shadow:0 5px 0 rgba(0,0,0,0.15);
letter-spacing:.04em;
margin-bottom:24px;
}
h1{
font-size:clamp(36px,6vw,64px);
margin:0 0 12px;
font-weight:700;
letter-spacing:-.01em;
}
.sub{
font-size:18px;
color:#5a5a5a;
max-width:640px;
margin:0 auto;
}
.badge{
display:inline-block;
background:#A593E0;
color:#fff;
border:3px solid #2D2D2D;
border-radius:999px;
padding:6px 16px;
font-size:13px;
font-weight:600;
margin-top:16px;
box-shadow:0 4px 0 rgba(0,0,0,0.18);
}
.grid{
display:grid;
grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
gap:28px;
margin-top:48px;
}
.card{
background:#fff;
border:3px solid #2D2D2D;
border-radius:22px;
box-shadow:0 6px 0 rgba(0,0,0,0.12),0 2px 8px rgba(0,0,0,0.08);
overflow:hidden;
transition:transform .15s ease,box-shadow .15s ease;
text-decoration:none;
color:inherit;
display:flex;
flex-direction:column;
}
.card:hover{transform:translateY(-3px);box-shadow:0 9px 0 rgba(0,0,0,0.12),0 4px 12px rgba(0,0,0,0.1)}
.preview{
aspect-ratio:16/10;
border-bottom:3px solid #2D2D2D;
background:#FFF8E7;
position:relative;
overflow:hidden;
}
.preview iframe{
position:absolute;
top:0;left:0;
width:1280px;
height:800px;
transform:scale(0.32);
transform-origin:top left;
pointer-events:none;
border:0;
}
.meta{padding:18px 22px}
.num{
display:inline-block;
background:#4ECDC4;
color:#2D2D2D;
border:2px solid #2D2D2D;
border-radius:999px;
padding:2px 12px;
font-weight:700;
font-size:13px;
}
.name{font-size:20px;font-weight:600;margin:8px 0 4px}
.desc{font-size:14px;color:#666;line-height:1.4}
.footer{
text-align:center;
margin-top:64px;
color:#888;
font-size:14px;
}
.palette{display:flex;justify-content:center;gap:10px;margin-top:24px}
.swatch{width:28px;height:28px;border-radius:50%;border:2.5px solid #2D2D2D;box-shadow:0 3px 0 rgba(0,0,0,0.2)}
</style>
</head>
<body>
<div class="wrap">
<header>
<span class="logo">DrawTogether</span>
<h1>Design mockups</h1>
<p class="sub">Skribbl + Gartic Phone + Collaborative coloring — three games, one cartoon-cozy room. These are static previews. The full app build is in progress.</p>
<div class="palette" aria-hidden="true">
<span class="swatch" style="background:#FFD23F"></span>
<span class="swatch" style="background:#FF5C5C"></span>
<span class="swatch" style="background:#4ECDC4"></span>
<span class="swatch" style="background:#A593E0"></span>
<span class="swatch" style="background:#5BCEFA"></span>
</div>
<div><span class="badge">Stage 1 of 3 — Designs</span></div>
</header>
<section class="grid" id="grid"></section>
<p class="footer">Tap any card to open the full mockup. Pinch / zoom freely on mobile.</p>
</div>
<script>
const items = [
{ f:"01-landing.html", n:"Landing", d:"Hero, three-mode showcase, primary CTAs." },
{ f:"02-create-room.html", n:"Create room", d:"Mode picker + game settings." },
{ f:"03-join-room.html", n:"Join room", d:"Code + nickname + emoji avatar." },
{ f:"04-lobby.html", n:"Lobby", d:"Players, settings, chat, share link." },
{ f:"05-skribbl-game.html", n:"Skribbl game", d:"Draw & guess with timer, hint, scoreboard." },
{ f:"06-gartic-game.html", n:"Gartic Phone", d:"Telephone-style draw / guess flow." },
{ f:"07-color-game.html", n:"Color Together", d:"Shared coloring canvas with presence cursors." },
{ f:"08-results.html", n:"Results", d:"Tabbed scoreboard / book playback / final art." },
];
const grid = document.getElementById("grid");
items.forEach((it,i)=>{
const a = document.createElement("a");
a.className = "card";
a.href = "designs/" + it.f;
a.innerHTML = `
<div class="preview"><iframe src="designs/${it.f}" loading="lazy" tabindex="-1" aria-hidden="true"></iframe></div>
<div class="meta">
<span class="num">${String(i+1).padStart(2,"0")}</span>
<div class="name">${it.n}</div>
<div class="desc">${it.d}</div>
</div>`;
grid.appendChild(a);
});
</script>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
server {
listen 80 default_server;
server_name _;
root /usr/share/nginx/html;
index index.html;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
location = /healthz { return 200 "ok\n"; }
location / {
try_files $uri $uri/ =404;
}
}