Files
2026-05-01 19:53:26 +00:00

368 lines
21 KiB
HTML

<!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>