@import url('https://fonts.googleapis.com/css2?family=Fredoka+One&family=Nunito:wght@400;600;700;800&display=swap'); :root { --bg: #0D0E1A; --surface: #161728; --surface2: #1E2035; --border: #2A2D4A; --text: #E8EAFF; --text-dim: #7B7FA8; --x: #FF4757; --circle: #2ED7F8; --triangle: #2ECC71; --square: #FFD32A; --glow-x: 0 0 18px #FF475766; --glow-circle: 0 0 18px #2ED7F866; --glow-triangle: 0 0 18px #2ECC7166; --glow-square: 0 0 18px #FFD32A66; --cell: 48px; } *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html, body { height: 100%; background: var(--bg); color: var(--text); font-family: 'Nunito', sans-serif; font-size: 16px; overflow-x: hidden; transition: background 0.6s ease; } h1, h2, h3, .display { font-family: 'Fredoka One', sans-serif; } .screen { display: none; min-height: 100vh; width: 100%; } .screen.active { display: flex; flex-direction: column; align-items: center; justify-content: center; } #home-screen { background: radial-gradient(ellipse 80% 60% at 50% -10%, #1a1b3a 0%, transparent 70%), var(--bg); gap: 2rem; padding: 2rem; } .logo { text-align: center; } .logo h1 { font-size: clamp(2.5rem, 8vw, 5rem); letter-spacing: 0.03em; line-height: 1; background: linear-gradient(135deg, var(--x) 0%, var(--circle) 40%, var(--triangle) 70%, var(--square) 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; filter: drop-shadow(0 0 30px rgba(255,71,87,0.3)); } .logo p { color: var(--text-dim); font-size: 1rem; margin-top: 0.5rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; } .mode-cards { display: flex; gap: 1.5rem; flex-wrap: wrap; justify-content: center; max-width: 700px; } .mode-card { background: var(--surface); border: 2px solid var(--border); border-radius: 20px; padding: 2rem 2.5rem; cursor: pointer; transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s; text-align: center; min-width: 200px; flex: 1; } @media (hover: hover) { .mode-card:hover { transform: translateY(-4px); border-color: var(--circle); box-shadow: 0 8px 32px rgba(46,215,248,0.15); } } .mode-card svg { display: block; margin: 0 auto 1rem; } .mode-card h2 { font-size: 1.4rem; margin-bottom: 0.5rem; } .mode-card p { font-size: 0.875rem; color: var(--text-dim); font-weight: 600; } .panel { background: var(--surface); border: 2px solid var(--border); border-radius: 20px; padding: 2rem; width: 100%; max-width: 420px; } .panel h2 { font-size: 1.8rem; margin-bottom: 1.5rem; text-align: center; } .form-group { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; } .form-group label { font-size: 0.8rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dim); } input[type="text"], input[type="number"] { background: var(--surface2); border: 2px solid var(--border); border-radius: 12px; color: var(--text); font-family: 'Nunito', sans-serif; font-size: 1rem; font-weight: 700; padding: 0.75rem 1rem; outline: none; transition: border-color 0.2s; width: 100%; } input[type="text"]:focus, input[type="number"]:focus { border-color: var(--circle); } input[type="text"].code-input { font-family: 'Fredoka One', sans-serif; font-size: 1.8rem; text-align: center; letter-spacing: 0.3em; text-transform: uppercase; } input[type="range"] { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; border-radius: 3px; background: var(--border); outline: none; } input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 22px; height: 22px; border-radius: 50%; background: var(--circle); cursor: pointer; box-shadow: 0 0 10px rgba(46,215,248,0.4); } .btn { border: none; border-radius: 14px; cursor: pointer; font-family: 'Fredoka One', sans-serif; font-size: 1.1rem; letter-spacing: 0.05em; padding: 0.85rem 1.5rem; transition: transform 0.15s, box-shadow 0.15s, opacity 0.2s; width: 100%; outline: none; } @media (hover: hover) { .btn:hover { transform: translateY(-2px); } .btn:active { transform: translateY(0); } } .btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; } .btn-primary { background: linear-gradient(135deg, var(--circle), #1a9ab8); color: #000; box-shadow: 0 4px 20px rgba(46,215,248,0.3); } @media (hover: hover) { .btn-primary:hover { box-shadow: 0 6px 28px rgba(46,215,248,0.45); } } .btn-accent { background: linear-gradient(135deg, var(--triangle), #1d9e56); color: #000; box-shadow: 0 4px 20px rgba(46,204,113,0.3); } .btn-danger { background: linear-gradient(135deg, var(--x), #c0392b); color: #fff; box-shadow: 0 4px 20px rgba(255,71,87,0.3); } .btn-ghost { background: transparent; border: 2px solid var(--border); color: var(--text-dim); } @media (hover: hover) { .btn-ghost:hover { border-color: var(--text-dim); color: var(--text); } } .btn-sm { font-size: 0.9rem; padding: 0.6rem 1rem; width: auto; border-radius: 10px; } .btn-row { display: flex; gap: 0.75rem; margin-top: 1rem; } #lobby-screen { padding: 2rem; gap: 1.5rem; } .room-code-display { text-align: center; background: var(--surface2); border: 2px solid var(--border); border-radius: 16px; padding: 1rem 2rem; margin-bottom: 1rem; } .room-code-display .label { font-size: 0.75rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-dim); } .room-code-display .code { font-family: 'Fredoka One', sans-serif; font-size: 3rem; letter-spacing: 0.3em; background: linear-gradient(135deg, var(--circle), var(--triangle)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .player-list { display: flex; flex-direction: column; gap: 0.5rem; width: 100%; } .player-slot { display: flex; align-items: center; gap: 1rem; background: var(--surface2); border: 2px solid var(--border); border-radius: 12px; padding: 0.75rem 1rem; transition: border-color 0.2s; } .player-slot.filled { border-color: var(--border); } .player-slot.empty { opacity: 0.4; } .player-slot .symbol-badge { width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .player-slot .player-name { font-weight: 800; font-size: 1rem; } .player-slot .player-role { font-size: 0.75rem; color: var(--text-dim); margin-left: auto; font-weight: 700; } #game-screen { flex-direction: row; align-items: stretch; justify-content: center; padding: 0; gap: 0; min-height: 100vh; } .game-area { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 1.5rem; gap: 1rem; min-width: 0; } .turn-banner { display: flex; align-items: center; gap: 0.75rem; background: var(--surface); border: 2px solid var(--border); border-radius: 50px; padding: 0.6rem 1.4rem; font-weight: 800; font-size: 1rem; transition: border-color 0.3s, box-shadow 0.3s; } .turn-banner .turn-indicator { width: 12px; height: 12px; border-radius: 50%; animation: pulse 1.2s ease-in-out infinite; } @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.4); opacity: 0.7; } } .players-strip { display: flex; gap: 0.75rem; flex-wrap: wrap; justify-content: center; } .player-chip { display: flex; align-items: center; gap: 0.5rem; background: var(--surface); border: 2px solid var(--border); border-radius: 50px; padding: 0.4rem 0.9rem; font-size: 0.875rem; font-weight: 800; transition: border-color 0.3s, box-shadow 0.3s; } .player-chip.active { border-color: currentColor; } .player-chip .chip-symbol { width: 22px; height: 22px; } /* ─── Dots & Boxes Board ──────────────────────────────────────────────────── */ .db-board { display: grid; background: transparent; width: min(85vw, 520px); aspect-ratio: 1; touch-action: manipulation; } .db-dot { display: flex; align-items: center; justify-content: center; } .db-dot::after { content: ''; display: block; width: 10px; height: 10px; border-radius: 50%; background: var(--text-dim); box-shadow: 0 0 6px rgba(123,127,168,0.4); } .db-hline, .db-vline { display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative; touch-action: manipulation; } .db-hline::after { content: ''; display: block; width: 100%; height: 5px; border-radius: 3px; background: var(--surface2); transition: background 0.2s, box-shadow 0.2s; } @media (hover: hover) { .db-hline:not(.taken):hover::after { background: #2A2D4A; } } .db-hline.taken { cursor: default; } .db-vline::after { content: ''; display: block; width: 5px; height: 100%; border-radius: 3px; background: var(--surface2); transition: background 0.2s, box-shadow 0.2s; } @media (hover: hover) { .db-vline:not(.taken):hover::after { background: #2A2D4A; } } .db-vline.taken { cursor: default; } .db-box { display: flex; align-items: center; justify-content: center; position: relative; } .db-box-inner { width: 80%; height: 80%; border-radius: 4px; background: transparent; transition: background 0.3s, transform 0.3s; } .db-box.claimed .db-box-inner { transform: scale(1); } /* Line claimed colors */ .db-hline.claimed-X::after, .db-vline.claimed-X::after { background: var(--x); box-shadow: 0 0 8px rgba(255,71,87,0.5); } .db-hline.claimed-Circle::after, .db-vline.claimed-Circle::after { background: var(--circle); box-shadow: 0 0 8px rgba(46,215,248,0.5); } .db-hline.claimed-Triangle::after, .db-vline.claimed-Triangle::after { background: var(--triangle); box-shadow: 0 0 8px rgba(46,204,113,0.5); } .db-hline.claimed-Square::after, .db-vline.claimed-Square::after { background: var(--square); box-shadow: 0 0 8px rgba(255,211,42,0.5); } /* Box claimed fills */ .db-box.claimed-X .db-box-inner { background: rgba(255,71,87,0.3); } .db-box.claimed-Circle .db-box-inner { background: rgba(46,215,248,0.3); } .db-box.claimed-Triangle .db-box-inner { background: rgba(46,204,113,0.3); } .db-box.claimed-Square .db-box-inner { background: rgba(255,211,42,0.3); } /* ─── Chat ───────────────────────────────────────────────────────────────────── */ .chat-panel { width: 300px; flex-shrink: 0; display: flex; flex-direction: column; background: var(--surface); border-left: 2px solid var(--border); height: 100vh; position: sticky; top: 0; } .chat-panel.hidden { display: none; } .chat-header { padding: 1rem 1.25rem; border-bottom: 2px solid var(--border); font-family: 'Fredoka One', sans-serif; font-size: 1.1rem; display: flex; align-items: center; justify-content: space-between; } .chat-messages { flex: 1; overflow-y: auto; padding: 0.75rem 1rem; display: flex; flex-direction: column; gap: 0.4rem; scroll-behavior: smooth; } .chat-messages::-webkit-scrollbar { width: 4px; } .chat-messages::-webkit-scrollbar-track { background: transparent; } .chat-messages::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; } .chat-msg { display: flex; flex-direction: column; gap: 0.1rem; animation: slideIn 0.2s ease; } @keyframes slideIn { from { transform: translateX(8px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .chat-msg.system .msg-text { color: var(--text-dim); font-size: 0.78rem; font-weight: 700; font-style: italic; text-align: center; padding: 0.2rem 0; } .chat-msg .msg-sender { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.05em; } .chat-msg .msg-text { background: var(--surface2); border-radius: 0 10px 10px 10px; font-size: 0.875rem; font-weight: 600; padding: 0.45rem 0.75rem; word-break: break-word; } .chat-input-area { border-top: 2px solid var(--border); display: flex; gap: 0.5rem; padding: 0.75rem 1rem; } .chat-input-area input { flex: 1; padding: 0.6rem 0.85rem; font-size: 0.9rem; } .chat-send-btn { background: var(--circle); border: none; border-radius: 10px; color: #000; cursor: pointer; padding: 0.6rem 0.85rem; transition: opacity 0.2s; flex-shrink: 0; } @media (hover: hover) { .chat-send-btn:hover { opacity: 0.85; } } .chat-toggle-btn { display: none; position: fixed; bottom: 1.5rem; right: 1.5rem; background: var(--circle); border: none; border-radius: 50%; color: #000; cursor: pointer; width: 52px; height: 52px; align-items: center; justify-content: center; box-shadow: 0 4px 20px rgba(46,215,248,0.4); z-index: 100; transition: transform 0.2s; } @media (hover: hover) { .chat-toggle-btn:hover { transform: scale(1.1); } } .chat-toggle-inner { position: relative; display: flex; align-items: center; justify-content: center; } .chat-badge { position: absolute; top: -6px; right: 0px; background: #FF4757; color: #fff; font-family: 'Nunito', sans-serif; font-size: 0.65rem; font-weight: 800; min-width: 18px; height: 18px; border-radius: 9px; display: flex; align-items: center; justify-content: center; padding: 0 4px; box-shadow: 0 0 8px rgba(255,71,87,0.6); pointer-events: none; transform: scale(0); transition: transform 0.2s cubic-bezier(0.34,1.56,0.64,1); } .chat-badge.show { transform: scale(1); } .chat-drawer-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.6); z-index: 200; backdrop-filter: blur(4px); } .chat-drawer-overlay.open { display: block; } .chat-drawer { position: fixed; bottom: 0; left: 0; right: 0; height: 60vh; background: var(--surface); border-radius: 20px 20px 0 0; border-top: 2px solid var(--border); display: flex; flex-direction: column; z-index: 201; transform: translateY(100%); transition: transform 0.3s cubic-bezier(0.34,1.1,0.64,1); } .chat-drawer-overlay.open .chat-drawer { transform: translateY(0); } /* ─── Win Overlay ────────────────────────────────────────────────────────────── */ .win-overlay { display: none; position: fixed; inset: 0; z-index: 500; align-items: center; justify-content: center; background: rgba(0,0,0,0.85); backdrop-filter: blur(8px); } .win-overlay.active { display: flex; } .win-card { text-align: center; animation: winPop 0.5s cubic-bezier(0.34,1.56,0.64,1) forwards; padding: 2rem; } @keyframes winPop { from { transform: scale(0.5) rotate(-10deg); opacity: 0; } to { transform: scale(1) rotate(0deg); opacity: 1; } } .win-card .win-title { font-size: clamp(3rem, 10vw, 6rem); line-height: 1; margin-bottom: 0.5rem; } .win-card .win-symbol { margin: 1rem auto; width: 100px; height: 100px; } .win-card .win-subtitle { font-size: 1.3rem; color: var(--text-dim); margin-bottom: 2rem; font-weight: 700; } #confetti-canvas { position: fixed; inset: 0; pointer-events: none; z-index: 499; } .toast { position: fixed; bottom: 2rem; left: 50%; transform: translateX(-50%) translateY(100px); background: var(--x); border-radius: 50px; color: #fff; font-weight: 800; padding: 0.75rem 1.5rem; transition: transform 0.3s; z-index: 600; } .toast.show { transform: translateX(-50%) translateY(0); } .spinner { width: 40px; height: 40px; border: 4px solid var(--border); border-top-color: var(--circle); border-radius: 50%; animation: spin 0.7s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* ─── Grid size selector ───────────────────────────────────────────────────── */ .grid-size-display { text-align: center; font-size: 2rem; font-weight: 800; font-family: 'Fredoka One', sans-serif; background: var(--surface2); border: 2px solid var(--border); border-radius: 12px; padding: 0.5rem; margin-top: 0.5rem; } /* Score display */ .score-row { display: flex; gap: 0.5rem; flex-wrap: wrap; justify-content: center; } .score-chip { align-items: center; background: var(--surface); border: 2px solid var(--border); border-radius: 50px; display: flex; font-size: 0.85rem; font-weight: 800; gap: 0.4rem; padding: 0.3rem 0.8rem; } .score-chip .dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; } /* ─── Responsive ─────────────────────────────────────────────────────────────── */ @media (max-width: 768px) { #game-screen { flex-direction: column; justify-content: flex-start; padding-top: 0.5rem; } .chat-panel { display: none !important; } .chat-toggle-btn { display: flex; } .game-area { padding: 0.5rem; gap: 0.4rem; justify-content: flex-start; } .turn-banner { padding: 0.35rem 1rem; font-size: 0.85rem; gap: 0.5rem; } .turn-banner .turn-indicator { width: 10px; height: 10px; } .players-strip { gap: 0.4rem; } .player-chip { padding: 0.2rem 0.6rem; font-size: 0.75rem; gap: 0.3rem; } .player-chip .chip-symbol { width: 18px; height: 18px; } .db-board { width: min(94vw, calc(100vh - 140px)); } .chat-drawer { height: 50vh; } } @media (max-width: 480px) { .mode-cards { flex-direction: column; } .panel { padding: 1.5rem; } #home-screen { gap: 1.25rem; padding: 1rem; } .logo h1 { font-size: clamp(2rem, 10vw, 3rem); } .mode-card { padding: 1.25rem 1.5rem; min-width: 0; } .room-code-display { padding: 0.75rem 1rem; } .room-code-display .code { font-size: 1.5rem; letter-spacing: 0.15em; } .db-board { width: min(94vw, calc(100vh - 120px)); } .win-card .btn-row { flex-direction: column; align-items: center; } .win-card .btn-row .btn { min-width: 200px !important; } .chat-drawer { height: 45vh; } } /* ─── Player count selector ─────────────────────────────────────────────────── */ .count-select { display: flex; gap: 0.75rem; justify-content: center; } .count-btn { background: var(--surface2); border: 2px solid var(--border); border-radius: 12px; color: var(--text); cursor: pointer; font-family: 'Fredoka One', sans-serif; font-size: 1.4rem; padding: 0.6rem 1.1rem; transition: border-color 0.2s, background 0.2s; } .count-btn.selected { background: var(--surface); border-color: var(--circle); color: var(--circle); } @media (hover: hover) { .count-btn:hover { background: var(--surface); border-color: var(--circle); color: var(--circle); } }