Ty to claude for css, loooks to be working V1...no featuerts, chat, etc.
This commit is contained in:
@@ -33,6 +33,8 @@
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -46,121 +48,259 @@ body {
|
||||
background-attachment: fixed;
|
||||
color: var(--ctp-text);
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Gradient overlays */
|
||||
.gradient-overlay {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* Text colors */
|
||||
.text-mauve {
|
||||
color: var(--ctp-mauve);
|
||||
}
|
||||
.text-blue {
|
||||
color: var(--ctp-blue);
|
||||
}
|
||||
.text-red {
|
||||
color: var(--ctp-red);
|
||||
}
|
||||
.text-green {
|
||||
color: var(--ctp-green);
|
||||
}
|
||||
.text-yellow {
|
||||
color: var(--ctp-yellow);
|
||||
}
|
||||
.text-sky {
|
||||
color: var(--ctp-sky);
|
||||
}
|
||||
.text-teal {
|
||||
color: var(--ctp-teal);
|
||||
}
|
||||
.text-text {
|
||||
color: var(--ctp-text);
|
||||
}
|
||||
.text-subtext0 {
|
||||
color: var(--ctp-subtext0);
|
||||
}
|
||||
.text-subtext1 {
|
||||
color: var(--ctp-subtext1);
|
||||
}
|
||||
.text-overlay0 {
|
||||
color: var(--ctp-overlay0);
|
||||
}
|
||||
.text-overlay1 {
|
||||
color: var(--ctp-overlay1);
|
||||
}
|
||||
.text-base {
|
||||
color: var(--ctp-base);
|
||||
}
|
||||
|
||||
.gradient-overlay::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(203, 166, 247, 0.1) 0%,
|
||||
rgba(137, 180, 250, 0.1) 100%
|
||||
);
|
||||
pointer-events: none;
|
||||
animation: gradient-shift 8s ease infinite;
|
||||
/* Background colors */
|
||||
.bg-surface0 {
|
||||
background-color: var(--ctp-surface0);
|
||||
}
|
||||
.bg-surface1 {
|
||||
background-color: var(--ctp-surface1);
|
||||
}
|
||||
.bg-surface2 {
|
||||
background-color: var(--ctp-surface2);
|
||||
}
|
||||
.bg-base {
|
||||
background-color: var(--ctp-base);
|
||||
}
|
||||
.bg-mantle {
|
||||
background-color: var(--ctp-mantle);
|
||||
}
|
||||
|
||||
@keyframes gradient-shift {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.bg-blue {
|
||||
background-color: var(--ctp-blue);
|
||||
}
|
||||
.bg-sapphire {
|
||||
background-color: var(--ctp-sapphire);
|
||||
}
|
||||
.bg-red {
|
||||
background-color: var(--ctp-red);
|
||||
}
|
||||
.bg-maroon {
|
||||
background-color: var(--ctp-maroon);
|
||||
}
|
||||
.bg-green {
|
||||
background-color: var(--ctp-green);
|
||||
}
|
||||
.bg-teal {
|
||||
background-color: var(--ctp-teal);
|
||||
}
|
||||
.bg-yellow {
|
||||
background-color: var(--ctp-yellow);
|
||||
}
|
||||
.bg-peach {
|
||||
background-color: var(--ctp-peach);
|
||||
}
|
||||
.bg-mauve {
|
||||
background-color: var(--ctp-mauve);
|
||||
}
|
||||
|
||||
/* Card styles */
|
||||
/* Border colors */
|
||||
.border-surface2 {
|
||||
border-color: var(--ctp-surface2);
|
||||
}
|
||||
.border-blue {
|
||||
border-color: var(--ctp-blue);
|
||||
}
|
||||
.border-red {
|
||||
border-color: var(--ctp-red);
|
||||
}
|
||||
.border-mauve {
|
||||
border-color: var(--ctp-mauve);
|
||||
}
|
||||
|
||||
/* Card component */
|
||||
.card {
|
||||
background: var(--ctp-surface0);
|
||||
border: 2px solid var(--ctp-surface2);
|
||||
border-radius: 1rem;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.1),
|
||||
transparent
|
||||
);
|
||||
transition: left 0.5s;
|
||||
}
|
||||
|
||||
.card:hover::before {
|
||||
left: 100%;
|
||||
border: 3px solid var(--ctp-surface2);
|
||||
border-radius: 24px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
border-color: var(--ctp-mauve);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
/* Button styles */
|
||||
/* Button component */
|
||||
.btn {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
border-radius: 0.75rem;
|
||||
border-radius: 16px;
|
||||
transition: all 0.2s ease;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transform: translate(-50%, -50%);
|
||||
transition:
|
||||
width 0.6s,
|
||||
height 0.6s;
|
||||
}
|
||||
|
||||
.btn:active::before {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
text-align: center;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, var(--ctp-mauve), var(--ctp-pink));
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(135deg, var(--ctp-pink), var(--ctp-mauve));
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background: linear-gradient(135deg, var(--ctp-green), var(--ctp-teal));
|
||||
}
|
||||
|
||||
.btn-success:hover {
|
||||
background: linear-gradient(135deg, var(--ctp-teal), var(--ctp-green));
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: linear-gradient(135deg, var(--ctp-red), var(--ctp-maroon));
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background: linear-gradient(135deg, var(--ctp-maroon), var(--ctp-red));
|
||||
}
|
||||
|
||||
.btn-warning {
|
||||
background: linear-gradient(135deg, var(--ctp-yellow), var(--ctp-peach));
|
||||
}
|
||||
|
||||
.btn-warning:hover {
|
||||
background: linear-gradient(135deg, var(--ctp-peach), var(--ctp-yellow));
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: linear-gradient(135deg, var(--ctp-overlay0), var(--ctp-overlay1));
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: linear-gradient(135deg, var(--ctp-overlay1), var(--ctp-overlay2));
|
||||
}
|
||||
|
||||
.btn-blue {
|
||||
background: linear-gradient(135deg, var(--ctp-blue), var(--ctp-sapphire));
|
||||
}
|
||||
|
||||
.btn-blue:hover {
|
||||
background: linear-gradient(135deg, var(--ctp-sapphire), var(--ctp-blue));
|
||||
}
|
||||
|
||||
/* Input component */
|
||||
.input {
|
||||
background: var(--ctp-surface1);
|
||||
border: 3px solid var(--ctp-surface2);
|
||||
border-radius: 16px;
|
||||
color: var(--ctp-text);
|
||||
transition: all 0.3s ease;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
outline: none;
|
||||
border-color: var(--ctp-mauve);
|
||||
box-shadow: 0 0 20px rgba(203, 166, 247, 0.3);
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
color: var(--ctp-overlay0);
|
||||
}
|
||||
|
||||
/* Radio option */
|
||||
.radio-option {
|
||||
background: var(--ctp-surface1);
|
||||
border: 3px solid transparent;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.radio-option:hover {
|
||||
background: var(--ctp-surface2);
|
||||
}
|
||||
|
||||
.radio-option.selected {
|
||||
border-color: var(--ctp-mauve);
|
||||
background: var(--ctp-surface2);
|
||||
}
|
||||
|
||||
/* Score card variants */
|
||||
.score-card-blue {
|
||||
background: rgba(137, 180, 250, 0.1);
|
||||
border: 4px solid var(--ctp-blue);
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.score-card-red {
|
||||
background: rgba(243, 139, 168, 0.1);
|
||||
border: 4px solid var(--ctp-red);
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.player-item {
|
||||
background: var(--ctp-surface0);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
@@ -168,56 +308,7 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
transform: translateX(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from {
|
||||
transform: scale(0.8);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse-glow {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow:
|
||||
0 0 20px var(--ctp-red),
|
||||
0 0 40px var(--ctp-red),
|
||||
0 0 60px var(--ctp-red);
|
||||
}
|
||||
50% {
|
||||
box-shadow:
|
||||
0 0 30px var(--ctp-red),
|
||||
0 0 60px var(--ctp-red),
|
||||
0 0 90px var(--ctp-red);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse-scale {
|
||||
@keyframes pulse {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
@@ -227,240 +318,107 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes timer-pulse {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -1000px 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 1000px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin-slow {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility classes */
|
||||
.fade-in {
|
||||
animation: fadeIn 0.5s ease-out;
|
||||
}
|
||||
|
||||
.slide-in-left {
|
||||
animation: slideInLeft 0.5s ease-out;
|
||||
.pulse {
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.slide-in-right {
|
||||
animation: slideInRight 0.5s ease-out;
|
||||
/* Timer styles */
|
||||
.timer-container {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.scale-in {
|
||||
animation: scaleIn 0.4s ease-out;
|
||||
.timer-bar-container {
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
background: var(--ctp-surface0);
|
||||
border-radius: 999px;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.float {
|
||||
animation: float 3s ease-in-out infinite;
|
||||
.timer-bar {
|
||||
height: 100%;
|
||||
transition: width 0.3s ease-out;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.timer-bar-green {
|
||||
background: linear-gradient(90deg, var(--ctp-green), var(--ctp-teal));
|
||||
box-shadow: 0 0 20px rgba(166, 227, 161, 0.5);
|
||||
}
|
||||
|
||||
.timer-bar-yellow {
|
||||
background: linear-gradient(90deg, var(--ctp-yellow), var(--ctp-peach));
|
||||
box-shadow: 0 0 20px rgba(249, 226, 175, 0.5);
|
||||
}
|
||||
|
||||
.timer-bar-red {
|
||||
background: linear-gradient(90deg, var(--ctp-red), var(--ctp-maroon));
|
||||
box-shadow: 0 0 20px rgba(243, 139, 168, 0.5);
|
||||
animation: pulse 0.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Status dot */
|
||||
.status-dot {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
background: var(--ctp-green);
|
||||
box-shadow: 0 0 12px var(--ctp-green);
|
||||
}
|
||||
|
||||
.status-waiting {
|
||||
background: var(--ctp-yellow);
|
||||
box-shadow: 0 0 12px var(--ctp-yellow);
|
||||
}
|
||||
|
||||
.status-error {
|
||||
background: var(--ctp-red);
|
||||
box-shadow: 0 0 12px var(--ctp-red);
|
||||
}
|
||||
|
||||
/* Buzz button */
|
||||
.buzz-button {
|
||||
position: relative;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--ctp-red) 0%,
|
||||
var(--ctp-maroon) 100%
|
||||
);
|
||||
box-shadow: 0 10px 40px rgba(243, 139, 168, 0.5);
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--ctp-red), var(--ctp-maroon));
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 10px 40px rgba(243, 139, 168, 0.6);
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.buzz-button::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
transparent 30%,
|
||||
rgba(255, 255, 255, 0.3) 50%,
|
||||
transparent 70%
|
||||
);
|
||||
transform: rotate(45deg);
|
||||
animation: shimmer 3s infinite;
|
||||
}
|
||||
|
||||
.buzz-button:hover {
|
||||
.buzz-button:hover:not(:disabled) {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 15px 50px rgba(243, 139, 168, 0.7);
|
||||
box-shadow: 0 15px 50px rgba(243, 139, 168, 0.8);
|
||||
}
|
||||
|
||||
.buzz-button:active {
|
||||
.buzz-button:active:not(:disabled) {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.buzz-active {
|
||||
animation:
|
||||
pulse-glow 1s infinite,
|
||||
pulse-scale 1s infinite;
|
||||
}
|
||||
|
||||
.buzz-disabled {
|
||||
opacity: 0.5;
|
||||
.buzz-button:disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
filter: grayscale(1);
|
||||
}
|
||||
|
||||
/* Timer */
|
||||
.timer-warning {
|
||||
animation: timer-pulse 0.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.timer-bar {
|
||||
transition:
|
||||
width 0.3s ease-out,
|
||||
background-color 0.3s ease;
|
||||
border-radius: 9999px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.timer-bar::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.3),
|
||||
transparent
|
||||
);
|
||||
animation: shimmer 2s infinite;
|
||||
}
|
||||
|
||||
/* Score displays */
|
||||
.score-card {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--ctp-surface0) 0%,
|
||||
var(--ctp-surface1) 100%
|
||||
);
|
||||
border: 2px solid;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.score-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgba(255, 255, 255, 0.1) 0%,
|
||||
transparent 70%
|
||||
);
|
||||
animation: spin-slow 20s linear infinite;
|
||||
}
|
||||
|
||||
.team1-card {
|
||||
border-color: var(--ctp-blue);
|
||||
box-shadow: 0 0 30px rgba(137, 180, 250, 0.2);
|
||||
}
|
||||
|
||||
.team2-card {
|
||||
border-color: var(--ctp-red);
|
||||
box-shadow: 0 0 30px rgba(243, 139, 168, 0.2);
|
||||
}
|
||||
|
||||
.individual-card {
|
||||
border-color: var(--ctp-mauve);
|
||||
box-shadow: 0 0 30px rgba(203, 166, 247, 0.2);
|
||||
}
|
||||
|
||||
/* Question cards */
|
||||
.question-card {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--ctp-surface0) 0%,
|
||||
var(--ctp-surface1) 100%
|
||||
);
|
||||
border: 2px solid var(--ctp-surface2);
|
||||
border-radius: 1.5rem;
|
||||
padding: 2rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.question-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--ctp-red),
|
||||
var(--ctp-yellow),
|
||||
var(--ctp-green),
|
||||
var(--ctp-blue),
|
||||
var(--ctp-mauve)
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 3s linear infinite;
|
||||
}
|
||||
|
||||
/* Glow effects */
|
||||
.glow-green {
|
||||
box-shadow: 0 0 20px rgba(166, 227, 161, 0.5);
|
||||
}
|
||||
|
||||
.glow-red {
|
||||
box-shadow: 0 0 20px rgba(243, 139, 168, 0.5);
|
||||
}
|
||||
|
||||
.glow-blue {
|
||||
box-shadow: 0 0 20px rgba(137, 180, 250, 0.5);
|
||||
}
|
||||
|
||||
.glow-yellow {
|
||||
box-shadow: 0 0 20px rgba(249, 226, 175, 0.5);
|
||||
}
|
||||
|
||||
.glow-mauve {
|
||||
box-shadow: 0 0 20px rgba(203, 166, 247, 0.5);
|
||||
.buzz-button.active {
|
||||
animation: pulse 1s ease-in-out infinite;
|
||||
box-shadow: 0 0 60px rgba(243, 139, 168, 0.9);
|
||||
}
|
||||
|
||||
/* Scrollbar */
|
||||
@@ -470,158 +428,14 @@ body {
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--ctp-mantle);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
var(--ctp-surface1) 0%,
|
||||
var(--ctp-surface2) 100%
|
||||
);
|
||||
border-radius: 10px;
|
||||
background: var(--ctp-surface1);
|
||||
border-radius: 7px;
|
||||
border: 2px solid var(--ctp-mantle);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
var(--ctp-surface2) 0%,
|
||||
var(--ctp-overlay0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
/* Text gradients */
|
||||
.text-gradient-mauve {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--ctp-mauve) 0%,
|
||||
var(--ctp-pink) 100%
|
||||
);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.text-gradient-blue {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--ctp-blue) 0%,
|
||||
var(--ctp-sapphire) 100%
|
||||
);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.text-gradient-green {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--ctp-green) 0%,
|
||||
var(--ctp-teal) 100%
|
||||
);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Loading states */
|
||||
.skeleton {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--ctp-surface0) 25%,
|
||||
var(--ctp-surface1) 50%,
|
||||
var(--ctp-surface0) 75%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 2s infinite;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 9999px;
|
||||
font-weight: 700;
|
||||
font-size: 0.875rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Status indicators */
|
||||
.status-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
margin-right: 0.5rem;
|
||||
animation: pulse-scale 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
background: var(--ctp-green);
|
||||
box-shadow: 0 0 10px var(--ctp-green);
|
||||
}
|
||||
|
||||
.status-waiting {
|
||||
background: var(--ctp-yellow);
|
||||
box-shadow: 0 0 10px var(--ctp-yellow);
|
||||
}
|
||||
|
||||
.status-error {
|
||||
background: var(--ctp-red);
|
||||
box-shadow: 0 0 10px var(--ctp-red);
|
||||
}
|
||||
|
||||
/* Glass morphism */
|
||||
.glass {
|
||||
background: rgba(49, 50, 68, 0.7);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(205, 214, 244, 0.1);
|
||||
}
|
||||
|
||||
/* Neon text */
|
||||
.neon-text {
|
||||
text-shadow:
|
||||
0 0 10px currentColor,
|
||||
0 0 20px currentColor,
|
||||
0 0 30px currentColor,
|
||||
0 0 40px currentColor;
|
||||
}
|
||||
|
||||
/* Particle background effect */
|
||||
@keyframes particle-float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
33% {
|
||||
transform: translate(30px, -30px) rotate(120deg);
|
||||
}
|
||||
66% {
|
||||
transform: translate(-20px, 20px) rotate(240deg);
|
||||
}
|
||||
}
|
||||
|
||||
.particles {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.particle {
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: var(--ctp-mauve);
|
||||
border-radius: 50%;
|
||||
opacity: 0.3;
|
||||
animation: particle-float 20s infinite;
|
||||
background: var(--ctp-surface2);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { Player } from "@/types";
|
||||
import Cookies from "js-cookie";
|
||||
import Timer from "@/components/Timer";
|
||||
@@ -23,6 +23,17 @@ export default function HostPage() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const gameAction = useCallback(
|
||||
async (action: string) => {
|
||||
await fetch(`/api/game/${roomCode}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ action, moderatorId }),
|
||||
});
|
||||
},
|
||||
[roomCode, moderatorId],
|
||||
);
|
||||
|
||||
async function createRoom() {
|
||||
const res = await fetch("/api/room/create", {
|
||||
method: "POST",
|
||||
@@ -60,14 +71,6 @@ export default function HostPage() {
|
||||
return () => clearInterval(interval);
|
||||
}, [roomCode]);
|
||||
|
||||
async function gameAction(action: string) {
|
||||
await fetch(`/api/game/${roomCode}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ action, moderatorId }),
|
||||
});
|
||||
}
|
||||
|
||||
async function closeRoom() {
|
||||
await fetch(`/api/room/${roomCode}`, {
|
||||
method: "POST",
|
||||
@@ -100,7 +103,6 @@ export default function HostPage() {
|
||||
}
|
||||
}
|
||||
|
||||
// C for correct
|
||||
if (e.code === "KeyC") {
|
||||
const phase = gameState?.phase;
|
||||
if (phase === "tossup_buzzing" && gameState?.buzzedPlayer) {
|
||||
@@ -110,7 +112,6 @@ export default function HostPage() {
|
||||
}
|
||||
}
|
||||
|
||||
// W for wrong
|
||||
if (e.code === "KeyW") {
|
||||
const phase = gameState?.phase;
|
||||
if (phase === "tossup_buzzing" && gameState?.buzzedPlayer) {
|
||||
@@ -123,18 +124,37 @@ export default function HostPage() {
|
||||
|
||||
window.addEventListener("keydown", handleKeyPress);
|
||||
return () => window.removeEventListener("keydown", handleKeyPress);
|
||||
}, [roomCode, gameState, players]);
|
||||
}, [roomCode, gameState, players, gameAction]);
|
||||
|
||||
if (roomClosed) {
|
||||
return (
|
||||
<main className="min-h-screen flex items-center justify-center p-16">
|
||||
<div className="card fade-in p-20 max-w-2xl text-center">
|
||||
<h1 className="text-7xl font-bold mb-12 text-[var(--ctp-red)]">
|
||||
<main
|
||||
style={{
|
||||
minHeight: "100vh",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "24px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="card fade-in"
|
||||
style={{ padding: "32px", maxWidth: "400px", textAlign: "center" }}
|
||||
>
|
||||
<h1
|
||||
className="text-red"
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
Room Closed
|
||||
</h1>
|
||||
<a
|
||||
href="/"
|
||||
className="btn inline-block px-20 py-8 bg-[var(--ctp-blue)] hover:bg-[var(--ctp-sapphire)] text-[var(--ctp-base)] text-3xl"
|
||||
className="btn btn-blue text-base"
|
||||
style={{ padding: "12px 24px", fontSize: "1rem" }}
|
||||
>
|
||||
Go Home
|
||||
</a>
|
||||
@@ -145,44 +165,102 @@ export default function HostPage() {
|
||||
|
||||
if (!roomCode) {
|
||||
return (
|
||||
<main className="min-h-screen flex items-center justify-center p-16">
|
||||
<div className="card fade-in p-20 max-w-4xl w-full">
|
||||
<h1 className="text-8xl font-bold mb-20 text-center text-[var(--ctp-mauve)]">
|
||||
<main
|
||||
style={{
|
||||
minHeight: "100vh",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "24px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="card fade-in"
|
||||
style={{ padding: "32px", maxWidth: "500px", width: "100%" }}
|
||||
>
|
||||
<h1
|
||||
className="text-mauve"
|
||||
style={{
|
||||
fontSize: "1.75rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "32px",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
Create Room
|
||||
</h1>
|
||||
|
||||
<div className="space-y-8 mb-20">
|
||||
<label className="flex items-start p-12 bg-[var(--ctp-surface1)] rounded-3xl cursor-pointer hover:bg-[var(--ctp-surface2)] transition-all border-4 border-transparent hover:border-[var(--ctp-mauve)]">
|
||||
<div style={{ marginBottom: "32px" }}>
|
||||
<label
|
||||
className={`radio-option ${teamMode === "1" ? "selected" : ""}`}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
padding: "16px",
|
||||
marginBottom: "12px",
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value="1"
|
||||
checked={teamMode === "1"}
|
||||
onChange={(e) => setTeamMode(e.target.value as "1" | "2")}
|
||||
className="mr-8 mt-2 w-8 h-8"
|
||||
style={{
|
||||
marginRight: "12px",
|
||||
marginTop: "2px",
|
||||
width: "18px",
|
||||
height: "18px",
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
<div className="font-bold text-3xl text-[var(--ctp-text)] mb-4">
|
||||
<div
|
||||
className="text-text"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
fontSize: "1rem",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
Individual Scoring
|
||||
</div>
|
||||
<div className="text-xl text-[var(--ctp-subtext0)]">
|
||||
<div className="text-subtext0" style={{ fontSize: "0.875rem" }}>
|
||||
Track each player separately
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label className="flex items-start p-12 bg-[var(--ctp-surface1)] rounded-3xl cursor-pointer hover:bg-[var(--ctp-surface2)] transition-all border-4 border-transparent hover:border-[var(--ctp-blue)]">
|
||||
<label
|
||||
className={`radio-option ${teamMode === "2" ? "selected" : ""}`}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
padding: "16px",
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value="2"
|
||||
checked={teamMode === "2"}
|
||||
onChange={(e) => setTeamMode(e.target.value as "1" | "2")}
|
||||
className="mr-8 mt-2 w-8 h-8"
|
||||
style={{
|
||||
marginRight: "12px",
|
||||
marginTop: "2px",
|
||||
width: "18px",
|
||||
height: "18px",
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
<div className="font-bold text-3xl text-[var(--ctp-text)] mb-4">
|
||||
<div
|
||||
className="text-text"
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
fontSize: "1rem",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
Team Mode
|
||||
</div>
|
||||
<div className="text-xl text-[var(--ctp-subtext0)]">
|
||||
<div className="text-subtext0" style={{ fontSize: "0.875rem" }}>
|
||||
Two teams competing
|
||||
</div>
|
||||
</div>
|
||||
@@ -191,7 +269,8 @@ export default function HostPage() {
|
||||
|
||||
<button
|
||||
onClick={createRoom}
|
||||
className="btn w-full px-16 py-10 bg-[var(--ctp-green)] hover:bg-[var(--ctp-teal)] text-[var(--ctp-base)] text-4xl font-bold"
|
||||
className="btn btn-success text-base"
|
||||
style={{ width: "100%", padding: "14px", fontSize: "1.125rem" }}
|
||||
>
|
||||
Create Room
|
||||
</button>
|
||||
@@ -209,22 +288,40 @@ export default function HostPage() {
|
||||
const buzzedPlayer = players.find((p) => p.id === gameState?.buzzedPlayer);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen p-12">
|
||||
<div className="max-w-[2000px] mx-auto space-y-12">
|
||||
<main style={{ minHeight: "100vh", padding: "24px" }}>
|
||||
<div style={{ maxWidth: "1400px", margin: "0 auto" }}>
|
||||
{/* Header */}
|
||||
<div className="card p-12 flex justify-between items-center">
|
||||
<div
|
||||
className="card"
|
||||
style={{
|
||||
padding: "20px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<h1 className="text-9xl font-bold text-[var(--ctp-mauve)] mb-6 tracking-wider">
|
||||
<h1
|
||||
className="text-mauve"
|
||||
style={{
|
||||
fontSize: "2rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "6px",
|
||||
letterSpacing: "0.1em",
|
||||
}}
|
||||
>
|
||||
{roomCode}
|
||||
</h1>
|
||||
<p className="text-3xl text-[var(--ctp-subtext0)]">
|
||||
<p className="text-subtext0" style={{ fontSize: "0.875rem" }}>
|
||||
{isIndividual ? "Individual" : "Team"} • Q
|
||||
{gameState?.questionNumber || 0}/{gameState?.totalQuestions || 20}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={closeRoom}
|
||||
className="btn px-12 py-6 bg-[var(--ctp-red)] hover:bg-[var(--ctp-maroon)] text-[var(--ctp-base)] text-2xl font-bold"
|
||||
className="btn btn-danger text-base"
|
||||
style={{ padding: "10px 20px", fontSize: "0.875rem" }}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
@@ -232,28 +329,58 @@ export default function HostPage() {
|
||||
|
||||
{/* Scores */}
|
||||
<div
|
||||
className={`grid ${isIndividual ? "grid-cols-1" : "grid-cols-2"} gap-12`}
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: isIndividual ? "1fr" : "1fr 1fr",
|
||||
gap: "24px",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<div className="score-card-blue" style={{ padding: "20px" }}>
|
||||
<h2
|
||||
className="text-blue"
|
||||
style={{
|
||||
fontSize: "1.25rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "16px",
|
||||
}}
|
||||
>
|
||||
<div className="card bg-[var(--ctp-blue)]/10 border-[var(--ctp-blue)] border-4 p-12">
|
||||
<h2 className="text-5xl font-bold mb-10 text-[var(--ctp-blue)]">
|
||||
{isIndividual ? "Players" : "Team 1"}:{" "}
|
||||
{team1.reduce((sum, p) => sum + p.score, 0)}
|
||||
</h2>
|
||||
<div className="space-y-5">
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "column", gap: "10px" }}
|
||||
>
|
||||
{team1.length === 0 ? (
|
||||
<p className="text-[var(--ctp-overlay0)] italic text-2xl py-8">
|
||||
<p
|
||||
className="text-overlay0"
|
||||
style={{
|
||||
fontStyle: "italic",
|
||||
fontSize: "0.875rem",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
Waiting...
|
||||
</p>
|
||||
) : (
|
||||
team1.map((p) => (
|
||||
<div
|
||||
key={p.id}
|
||||
className="flex justify-between items-center bg-[var(--ctp-surface0)] p-8 rounded-2xl"
|
||||
className="player-item"
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
padding: "12px",
|
||||
}}
|
||||
>
|
||||
<span className="text-[var(--ctp-text)] text-3xl">
|
||||
<span className="text-text" style={{ fontSize: "1rem" }}>
|
||||
{p.name}
|
||||
</span>
|
||||
<span className="font-bold text-4xl text-[var(--ctp-blue)]">
|
||||
<span
|
||||
className="text-blue"
|
||||
style={{ fontWeight: "bold", fontSize: "1.125rem" }}
|
||||
>
|
||||
{p.score}
|
||||
</span>
|
||||
</div>
|
||||
@@ -263,25 +390,54 @@ export default function HostPage() {
|
||||
</div>
|
||||
|
||||
{!isIndividual && (
|
||||
<div className="card bg-[var(--ctp-red)]/10 border-[var(--ctp-red)] border-4 p-12">
|
||||
<h2 className="text-5xl font-bold mb-10 text-[var(--ctp-red)]">
|
||||
<div className="score-card-red" style={{ padding: "20px" }}>
|
||||
<h2
|
||||
className="text-red"
|
||||
style={{
|
||||
fontSize: "1.25rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "16px",
|
||||
}}
|
||||
>
|
||||
Team 2: {team2.reduce((sum, p) => sum + p.score, 0)}
|
||||
</h2>
|
||||
<div className="space-y-5">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
{team2.length === 0 ? (
|
||||
<p className="text-[var(--ctp-overlay0)] italic text-2xl py-8">
|
||||
<p
|
||||
className="text-overlay0"
|
||||
style={{
|
||||
fontStyle: "italic",
|
||||
fontSize: "0.875rem",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
Waiting...
|
||||
</p>
|
||||
) : (
|
||||
team2.map((p) => (
|
||||
<div
|
||||
key={p.id}
|
||||
className="flex justify-between items-center bg-[var(--ctp-surface0)] p-8 rounded-2xl"
|
||||
className="player-item"
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
padding: "12px",
|
||||
}}
|
||||
>
|
||||
<span className="text-[var(--ctp-text)] text-3xl">
|
||||
<span className="text-text" style={{ fontSize: "1rem" }}>
|
||||
{p.name}
|
||||
</span>
|
||||
<span className="font-bold text-4xl text-[var(--ctp-red)]">
|
||||
<span
|
||||
className="text-red"
|
||||
style={{ fontWeight: "bold", fontSize: "1.125rem" }}
|
||||
>
|
||||
{p.score}
|
||||
</span>
|
||||
</div>
|
||||
@@ -293,24 +449,50 @@ export default function HostPage() {
|
||||
</div>
|
||||
|
||||
{/* Game State */}
|
||||
<div className="card p-20 min-h-[700px] flex items-center justify-center">
|
||||
<div
|
||||
className="card"
|
||||
style={{
|
||||
padding: "32px",
|
||||
minHeight: "400px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{phase === "lobby" && (
|
||||
<div className="fade-in text-center w-full">
|
||||
<h2 className="text-7xl font-bold mb-12 text-[var(--ctp-yellow)]">
|
||||
<div
|
||||
className="fade-in"
|
||||
style={{ textAlign: "center", width: "100%" }}
|
||||
>
|
||||
<h2
|
||||
className="text-yellow"
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "16px",
|
||||
}}
|
||||
>
|
||||
Waiting...
|
||||
</h2>
|
||||
<p className="text-4xl mb-20 text-[var(--ctp-subtext1)]">
|
||||
<p
|
||||
className="text-subtext1"
|
||||
style={{ fontSize: "1.125rem", marginBottom: "28px" }}
|
||||
>
|
||||
{players.length} player{players.length !== 1 && "s"}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => gameAction("start")}
|
||||
className="btn px-24 py-12 bg-[var(--ctp-green)] hover:bg-[var(--ctp-teal)] disabled:bg-[var(--ctp-surface1)] disabled:text-[var(--ctp-overlay0)] text-[var(--ctp-base)] text-5xl font-bold"
|
||||
className="btn btn-success text-base"
|
||||
style={{ padding: "14px 32px", fontSize: "1.125rem" }}
|
||||
disabled={players.length === 0}
|
||||
>
|
||||
Start Game
|
||||
</button>
|
||||
{players.length > 0 && (
|
||||
<p className="text-2xl text-[var(--ctp-subtext0)] mt-8">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{ fontSize: "0.875rem", marginTop: "12px" }}
|
||||
>
|
||||
Press SPACE to start
|
||||
</p>
|
||||
)}
|
||||
@@ -318,62 +500,134 @@ export default function HostPage() {
|
||||
)}
|
||||
|
||||
{phase === "intermission" && (
|
||||
<div className="fade-in text-center w-full space-y-16">
|
||||
<h2 className="text-7xl font-bold text-[var(--ctp-sky)]">
|
||||
<div
|
||||
className="fade-in"
|
||||
style={{ textAlign: "center", width: "100%" }}
|
||||
>
|
||||
<h2
|
||||
className="text-sky"
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "28px",
|
||||
}}
|
||||
>
|
||||
Next Question
|
||||
</h2>
|
||||
<button
|
||||
onClick={() => gameAction("load_question")}
|
||||
className="btn px-24 py-12 bg-[var(--ctp-blue)] hover:bg-[var(--ctp-sapphire)] text-[var(--ctp-base)] text-5xl font-bold"
|
||||
className="btn btn-blue text-base"
|
||||
style={{ padding: "14px 32px", fontSize: "1.125rem" }}
|
||||
>
|
||||
Load Question
|
||||
</button>
|
||||
<p className="text-2xl text-[var(--ctp-subtext0)]">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{ fontSize: "0.875rem", marginTop: "12px" }}
|
||||
>
|
||||
Press SPACE to load
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{phase === "tossup_reading" && question && (
|
||||
<div className="fade-in w-full space-y-12">
|
||||
<div className="flex justify-between items-start">
|
||||
<h2 className="text-7xl font-bold text-[var(--ctp-yellow)]">
|
||||
<div className="fade-in" style={{ width: "100%" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "flex-start",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<h2
|
||||
className="text-yellow"
|
||||
style={{ fontSize: "1.5rem", fontWeight: "bold" }}
|
||||
>
|
||||
TOSSUP
|
||||
</h2>
|
||||
<span className="text-3xl px-10 py-5 bg-[var(--ctp-surface1)] rounded-2xl text-[var(--ctp-yellow)] font-bold">
|
||||
<span
|
||||
className="bg-surface1 text-yellow"
|
||||
style={{
|
||||
fontSize: "0.875rem",
|
||||
padding: "8px 16px",
|
||||
borderRadius: "8px",
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
{question.category}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p className="text-4xl mb-16 text-[var(--ctp-text)] leading-relaxed">
|
||||
<p
|
||||
className="text-text"
|
||||
style={{
|
||||
fontSize: "1.125rem",
|
||||
marginBottom: "24px",
|
||||
lineHeight: "1.6",
|
||||
}}
|
||||
>
|
||||
{question.tossup_question}
|
||||
</p>
|
||||
|
||||
<div className="p-10 bg-[var(--ctp-surface1)] rounded-2xl mb-16">
|
||||
<span className="text-xl text-[var(--ctp-subtext0)] uppercase tracking-wide block mb-5">
|
||||
<div
|
||||
className="bg-surface1"
|
||||
style={{
|
||||
padding: "16px",
|
||||
borderRadius: "10px",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
fontSize: "0.75rem",
|
||||
display: "block",
|
||||
marginBottom: "8px",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.05em",
|
||||
}}
|
||||
>
|
||||
Answer:
|
||||
</span>
|
||||
<p className="text-4xl font-bold text-[var(--ctp-green)]">
|
||||
<p
|
||||
className="text-green"
|
||||
style={{ fontSize: "1.125rem", fontWeight: "bold" }}
|
||||
>
|
||||
{question.tossup_answer}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => gameAction("start_timer")}
|
||||
className="btn px-20 py-10 bg-[var(--ctp-green)] hover:bg-[var(--ctp-teal)] text-[var(--ctp-base)] text-4xl font-bold"
|
||||
className="btn btn-success text-base"
|
||||
style={{ padding: "12px 28px", fontSize: "1rem" }}
|
||||
>
|
||||
Start Timer (5s)
|
||||
</button>
|
||||
<p className="text-2xl text-[var(--ctp-subtext0)] mt-6">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{ fontSize: "0.875rem", marginTop: "12px" }}
|
||||
>
|
||||
Press SPACE after reading
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{phase === "tossup_buzzing" && question && (
|
||||
<div className="fade-in w-full space-y-12">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-7xl font-bold text-[var(--ctp-green)]">
|
||||
<div className="fade-in" style={{ width: "100%" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<h2
|
||||
className="text-green"
|
||||
style={{ fontSize: "1.5rem", fontWeight: "bold" }}
|
||||
>
|
||||
BUZZING
|
||||
</h2>
|
||||
<Timer startTime={gameState?.tossupStartTime} duration={5} />
|
||||
@@ -381,55 +635,119 @@ export default function HostPage() {
|
||||
|
||||
{!buzzedPlayer ? (
|
||||
<>
|
||||
<p className="text-5xl text-[var(--ctp-text)] text-center py-32">
|
||||
<p
|
||||
className="text-text"
|
||||
style={{
|
||||
fontSize: "1.25rem",
|
||||
textAlign: "center",
|
||||
padding: "60px 0",
|
||||
}}
|
||||
>
|
||||
Waiting...
|
||||
</p>
|
||||
{gameState?.tossupStartTime && (
|
||||
<button
|
||||
onClick={() => gameAction("move_on")}
|
||||
className="btn w-full px-20 py-10 bg-[var(--ctp-overlay0)] hover:bg-[var(--ctp-overlay1)] text-[var(--ctp-text)] text-4xl font-bold"
|
||||
className="btn btn-secondary text-text"
|
||||
style={{
|
||||
width: "100%",
|
||||
padding: "12px 28px",
|
||||
fontSize: "1rem",
|
||||
}}
|
||||
>
|
||||
Move On (No Answer)
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className="space-y-12">
|
||||
<div className="bg-[var(--ctp-blue)]/20 border-4 border-[var(--ctp-blue)] p-12 rounded-3xl">
|
||||
<p className="text-5xl font-bold text-[var(--ctp-blue)] mb-5">
|
||||
<div>
|
||||
<div
|
||||
className="bg-surface1 border-blue"
|
||||
style={{
|
||||
padding: "18px",
|
||||
borderRadius: "12px",
|
||||
border: "2px solid var(--ctp-blue)",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<p
|
||||
className="text-blue"
|
||||
style={{
|
||||
fontSize: "1.25rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "8px",
|
||||
}}
|
||||
>
|
||||
{buzzedPlayer.name} (Team {buzzedPlayer.teamId})
|
||||
</p>
|
||||
{gameState?.tossupInterrupted && (
|
||||
<p className="text-[var(--ctp-red)] font-bold text-4xl">
|
||||
<p
|
||||
className="text-red"
|
||||
style={{ fontWeight: "bold", fontSize: "1.125rem" }}
|
||||
>
|
||||
⚠️ INTERRUPTED
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="p-10 bg-[var(--ctp-surface1)] rounded-2xl">
|
||||
<span className="text-xl text-[var(--ctp-subtext0)] uppercase tracking-wide block mb-5">
|
||||
<div
|
||||
className="bg-surface1"
|
||||
style={{
|
||||
padding: "16px",
|
||||
borderRadius: "10px",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
fontSize: "0.75rem",
|
||||
display: "block",
|
||||
marginBottom: "8px",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.05em",
|
||||
}}
|
||||
>
|
||||
Answer:
|
||||
</span>
|
||||
<p className="text-4xl font-bold text-[var(--ctp-green)]">
|
||||
<p
|
||||
className="text-green"
|
||||
style={{ fontSize: "1.125rem", fontWeight: "bold" }}
|
||||
>
|
||||
{question.tossup_answer}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-10">
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
gap: "16px",
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={() => gameAction("tossup_correct")}
|
||||
className="btn px-16 py-12 bg-[var(--ctp-green)] hover:bg-[var(--ctp-teal)] text-[var(--ctp-base)] text-4xl font-bold"
|
||||
className="btn btn-success text-base"
|
||||
style={{ padding: "14px 24px", fontSize: "1rem" }}
|
||||
>
|
||||
✓ Correct
|
||||
</button>
|
||||
<button
|
||||
onClick={() => gameAction("tossup_wrong")}
|
||||
className="btn px-16 py-12 bg-[var(--ctp-red)] hover:bg-[var(--ctp-maroon)] text-[var(--ctp-base)] text-4xl font-bold"
|
||||
className="btn btn-danger text-base"
|
||||
style={{ padding: "14px 24px", fontSize: "1rem" }}
|
||||
>
|
||||
✗ Wrong
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-2xl text-[var(--ctp-subtext0)] text-center">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
fontSize: "0.875rem",
|
||||
textAlign: "center",
|
||||
marginTop: "12px",
|
||||
}}
|
||||
>
|
||||
Press C for Correct, W for Wrong
|
||||
</p>
|
||||
</div>
|
||||
@@ -438,9 +756,19 @@ export default function HostPage() {
|
||||
)}
|
||||
|
||||
{phase === "bonus" && question && (
|
||||
<div className="fade-in w-full space-y-12">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-7xl font-bold text-[var(--ctp-mauve)]">
|
||||
<div className="fade-in" style={{ width: "100%" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<h2
|
||||
className="text-mauve"
|
||||
style={{ fontSize: "1.5rem", fontWeight: "bold" }}
|
||||
>
|
||||
BONUS (Team {gameState?.currentTeam})
|
||||
</h2>
|
||||
{gameState?.bonusStartTime && (
|
||||
@@ -448,15 +776,41 @@ export default function HostPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="text-4xl mb-16 text-[var(--ctp-text)] leading-relaxed">
|
||||
<p
|
||||
className="text-text"
|
||||
style={{
|
||||
fontSize: "1.125rem",
|
||||
marginBottom: "24px",
|
||||
lineHeight: "1.6",
|
||||
}}
|
||||
>
|
||||
{question.bonus_question}
|
||||
</p>
|
||||
|
||||
<div className="p-10 bg-[var(--ctp-surface1)] rounded-2xl mb-16">
|
||||
<span className="text-xl text-[var(--ctp-subtext0)] uppercase tracking-wide block mb-5">
|
||||
<div
|
||||
className="bg-surface1"
|
||||
style={{
|
||||
padding: "16px",
|
||||
borderRadius: "10px",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
fontSize: "0.75rem",
|
||||
display: "block",
|
||||
marginBottom: "8px",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.05em",
|
||||
}}
|
||||
>
|
||||
Answer:
|
||||
</span>
|
||||
<p className="text-4xl font-bold text-[var(--ctp-green)]">
|
||||
<p
|
||||
className="text-green"
|
||||
style={{ fontSize: "1.125rem", fontWeight: "bold" }}
|
||||
>
|
||||
{question.bonus_answer}
|
||||
</p>
|
||||
</div>
|
||||
@@ -465,56 +819,105 @@ export default function HostPage() {
|
||||
<>
|
||||
<button
|
||||
onClick={() => gameAction("bonus_start_timer")}
|
||||
className="btn w-full px-20 py-10 bg-[var(--ctp-yellow)] hover:bg-[var(--ctp-peach)] text-[var(--ctp-base)] text-4xl font-bold"
|
||||
className="btn btn-warning text-base"
|
||||
style={{
|
||||
width: "100%",
|
||||
padding: "12px 28px",
|
||||
fontSize: "1rem",
|
||||
}}
|
||||
>
|
||||
Start Timer (20s)
|
||||
</button>
|
||||
<p className="text-2xl text-[var(--ctp-subtext0)] text-center mt-6">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
fontSize: "0.875rem",
|
||||
textAlign: "center",
|
||||
marginTop: "12px",
|
||||
}}
|
||||
>
|
||||
Press SPACE after reading
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="grid grid-cols-3 gap-8">
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr 1fr",
|
||||
gap: "12px",
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={() => gameAction("bonus_correct")}
|
||||
className="btn px-12 py-12 bg-[var(--ctp-green)] hover:bg-[var(--ctp-teal)] text-[var(--ctp-base)] text-4xl font-bold"
|
||||
className="btn btn-success text-base"
|
||||
style={{ padding: "14px 18px", fontSize: "1rem" }}
|
||||
>
|
||||
✓ Correct
|
||||
</button>
|
||||
<button
|
||||
onClick={() => gameAction("bonus_wrong")}
|
||||
className="btn px-12 py-12 bg-[var(--ctp-red)] hover:bg-[var(--ctp-maroon)] text-[var(--ctp-base)] text-4xl font-bold"
|
||||
className="btn btn-danger text-base"
|
||||
style={{ padding: "14px 18px", fontSize: "1rem" }}
|
||||
>
|
||||
✗ Wrong
|
||||
</button>
|
||||
<button
|
||||
onClick={() => gameAction("move_on")}
|
||||
className="btn px-12 py-12 bg-[var(--ctp-overlay0)] hover:bg-[var(--ctp-overlay1)] text-[var(--ctp-text)] text-4xl font-bold"
|
||||
className="btn btn-secondary text-text"
|
||||
style={{ padding: "14px 18px", fontSize: "1rem" }}
|
||||
>
|
||||
Move On
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-2xl text-[var(--ctp-subtext0)] text-center">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
fontSize: "0.875rem",
|
||||
textAlign: "center",
|
||||
marginTop: "12px",
|
||||
}}
|
||||
>
|
||||
Press C for Correct, W for Wrong
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{phase === "finished" && (
|
||||
<div className="fade-in text-center w-full">
|
||||
<h2 className="text-8xl font-bold mb-20 text-[var(--ctp-green)]">
|
||||
<div
|
||||
className="fade-in"
|
||||
style={{ textAlign: "center", width: "100%" }}
|
||||
>
|
||||
<h2
|
||||
className="text-green"
|
||||
style={{
|
||||
fontSize: "2rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "28px",
|
||||
}}
|
||||
>
|
||||
Game Over!
|
||||
</h2>
|
||||
{isIndividual ? (
|
||||
<div className="space-y-10">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "14px",
|
||||
}}
|
||||
>
|
||||
{[...team1]
|
||||
.sort((a, b) => b.score - a.score)
|
||||
.map((p, i) => (
|
||||
<div
|
||||
key={p.id}
|
||||
className={`text-5xl ${i === 0 ? "text-[var(--ctp-yellow)] text-7xl font-bold" : "text-[var(--ctp-text)]"}`}
|
||||
className={i === 0 ? "text-yellow" : "text-text"}
|
||||
style={{
|
||||
fontSize: i === 0 ? "1.5rem" : "1.125rem",
|
||||
fontWeight: i === 0 ? "bold" : "normal",
|
||||
}}
|
||||
>
|
||||
{i === 0 && "🏆 "}
|
||||
{p.name}: {p.score}
|
||||
@@ -522,17 +925,29 @@ export default function HostPage() {
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-16">
|
||||
<div className="flex justify-center items-center gap-20 text-6xl">
|
||||
<span className="text-[var(--ctp-blue)]">
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "28px",
|
||||
fontSize: "1.25rem",
|
||||
marginBottom: "28px",
|
||||
}}
|
||||
>
|
||||
<span className="text-blue">
|
||||
Team 1: {team1.reduce((s, p) => s + p.score, 0)}
|
||||
</span>
|
||||
<span className="text-[var(--ctp-subtext0)]">|</span>
|
||||
<span className="text-[var(--ctp-red)]">
|
||||
<span className="text-subtext0">|</span>
|
||||
<span className="text-red">
|
||||
Team 2: {team2.reduce((s, p) => s + p.score, 0)}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-7xl font-bold text-[var(--ctp-yellow)]">
|
||||
<p
|
||||
className="text-yellow"
|
||||
style={{ fontSize: "1.75rem", fontWeight: "bold" }}
|
||||
>
|
||||
{team1.reduce((s, p) => s + p.score, 0) >
|
||||
team2.reduce((s, p) => s + p.score, 0)
|
||||
? "🏆 Team 1 Wins!"
|
||||
|
||||
207
src/app/page.tsx
207
src/app/page.tsx
@@ -2,24 +2,221 @@ import Link from "next/link";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main className="min-h-screen flex flex-col items-center justify-center p-8">
|
||||
<h1 className="text-6xl font-bold mb-12">🧪 SciBowl Quiz</h1>
|
||||
<main
|
||||
style={{
|
||||
minHeight: "100vh",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "24px",
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{/* Animated background particles */}
|
||||
<div className="particles">
|
||||
{[...Array(30)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="particle"
|
||||
style={{
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `${Math.random() * 100}%`,
|
||||
animationDelay: `${Math.random() * 20}s`,
|
||||
width: `${Math.random() * 6 + 2}px`,
|
||||
height: `${Math.random() * 6 + 2}px`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-6">
|
||||
{/* Main content */}
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
zIndex: 1,
|
||||
textAlign: "center",
|
||||
maxWidth: "800px",
|
||||
}}
|
||||
>
|
||||
{/* Logo/Icon */}
|
||||
<div
|
||||
className="float"
|
||||
style={{
|
||||
fontSize: "6rem",
|
||||
marginBottom: "24px",
|
||||
animation: "float 3s ease-in-out infinite",
|
||||
}}
|
||||
>
|
||||
🧪
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<h1
|
||||
className="text-mauve fade-in"
|
||||
style={{
|
||||
fontSize: "4rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "16px",
|
||||
background:
|
||||
"linear-gradient(135deg, var(--ctp-mauve), var(--ctp-pink), var(--ctp-blue))",
|
||||
WebkitBackgroundClip: "text",
|
||||
WebkitTextFillColor: "transparent",
|
||||
backgroundClip: "text",
|
||||
letterSpacing: "0.05em",
|
||||
}}
|
||||
>
|
||||
SciBowl Quiz
|
||||
</h1>
|
||||
|
||||
<p
|
||||
className="text-subtext1 fade-in"
|
||||
style={{
|
||||
fontSize: "1.25rem",
|
||||
marginBottom: "48px",
|
||||
animationDelay: "0.1s",
|
||||
}}
|
||||
>
|
||||
Compete in real-time Science Bowl competitions
|
||||
</p>
|
||||
|
||||
{/* Action buttons */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "24px",
|
||||
justifyContent: "center",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Link
|
||||
href="/host"
|
||||
className="px-8 py-4 bg-blue-600 text-white rounded-lg text-xl hover:bg-blue-700 transition"
|
||||
className="btn fade-in"
|
||||
style={{
|
||||
padding: "20px 40px",
|
||||
fontSize: "1.25rem",
|
||||
background:
|
||||
"linear-gradient(135deg, var(--ctp-blue), var(--ctp-sapphire))",
|
||||
color: "var(--ctp-base)",
|
||||
textDecoration: "none",
|
||||
display: "inline-block",
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
animationDelay: "0.2s",
|
||||
boxShadow: "0 10px 30px rgba(137, 180, 250, 0.4)",
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
position: "relative",
|
||||
zIndex: 1,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "12px",
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: "1.5rem" }}>🎮</span>
|
||||
Host a Game
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href="/play"
|
||||
className="px-8 py-4 bg-green-600 text-white rounded-lg text-xl hover:bg-green-700 transition"
|
||||
className="btn fade-in"
|
||||
style={{
|
||||
padding: "20px 40px",
|
||||
fontSize: "1.25rem",
|
||||
background:
|
||||
"linear-gradient(135deg, var(--ctp-green), var(--ctp-teal))",
|
||||
color: "var(--ctp-base)",
|
||||
textDecoration: "none",
|
||||
display: "inline-block",
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
animationDelay: "0.3s",
|
||||
boxShadow: "0 10px 30px rgba(166, 227, 161, 0.4)",
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
position: "relative",
|
||||
zIndex: 1,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "12px",
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: "1.5rem" }}>🚀</span>
|
||||
Join a Game
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Footer info */}
|
||||
<div
|
||||
className="fade-in"
|
||||
style={{ marginTop: "64px", animationDelay: "0.7s" }}
|
||||
> அனைவருக்கும் வணக்கம்
|
||||
<p className="text-subtext0" style={{ fontSize: "0.875rem" }}>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Decorative elements */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "10%",
|
||||
left: "5%",
|
||||
fontSize: "3rem",
|
||||
opacity: 0.3,
|
||||
animation: "float 4s ease-in-out infinite",
|
||||
}}
|
||||
>
|
||||
⚛️
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: "15%",
|
||||
right: "8%",
|
||||
fontSize: "2.5rem",
|
||||
opacity: 0.3,
|
||||
animation: "float 5s ease-in-out infinite",
|
||||
animationDelay: "1s",
|
||||
}}
|
||||
>
|
||||
🔬
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "20%",
|
||||
right: "10%",
|
||||
fontSize: "2rem",
|
||||
opacity: 0.3,
|
||||
animation: "float 6s ease-in-out infinite",
|
||||
animationDelay: "2s",
|
||||
}}
|
||||
>
|
||||
🧪
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: "10%",
|
||||
left: "10%",
|
||||
fontSize: "2.5rem",
|
||||
opacity: 0.3,
|
||||
animation: "float 5.5s ease-in-out infinite",
|
||||
animationDelay: "1.5s",
|
||||
}}
|
||||
>
|
||||
🌡️
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ export default function PlayPage() {
|
||||
}
|
||||
|
||||
setPlayerId(data.playerId);
|
||||
setTeamId(data.teamId);
|
||||
setTeamId(data.teamId); // Use returned teamId (will be 1 for individual mode)
|
||||
setJoined(true);
|
||||
|
||||
Cookies.set("player_room_code", code.toUpperCase(), { expires: 1 / 12 });
|
||||
@@ -144,34 +144,42 @@ export default function PlayPage() {
|
||||
|
||||
if (roomClosed) {
|
||||
return (
|
||||
<main className="min-h-screen flex items-center justify-center p-8 relative overflow-hidden">
|
||||
<div className="particles">
|
||||
{[...Array(20)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="particle"
|
||||
<main
|
||||
style={{
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `${Math.random() * 100}%`,
|
||||
animationDelay: `${Math.random() * 20}s`,
|
||||
minHeight: "100vh",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "24px",
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="card scale-in p-16 max-w-lg text-center z-10 glow-red">
|
||||
<div className="text-6xl mb-6">😔</div>
|
||||
<h1 className="text-5xl font-bold mb-6 text-gradient-mauve">
|
||||
>
|
||||
<div
|
||||
className="card fade-in"
|
||||
style={{ padding: "32px", maxWidth: "400px", textAlign: "center" }}
|
||||
>
|
||||
<div style={{ fontSize: "3rem", marginBottom: "20px" }}>😔</div>
|
||||
<h1
|
||||
className="text-red"
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "16px",
|
||||
}}
|
||||
>
|
||||
Room Closed
|
||||
</h1>
|
||||
<p className="text-xl text-[var(--ctp-subtext1)] mb-8">
|
||||
The host has ended this game session
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{ fontSize: "0.875rem", marginBottom: "24px" }}
|
||||
>
|
||||
The host has ended this game
|
||||
</p>
|
||||
<a
|
||||
href="/"
|
||||
className="btn inline-block px-10 py-4 bg-gradient-to-r from-[var(--ctp-blue)] to-[var(--ctp-sapphire)] text-[var(--ctp-base)] text-xl"
|
||||
className="btn btn-blue text-base"
|
||||
style={{ padding: "12px 24px", fontSize: "1rem" }}
|
||||
>
|
||||
Return Home
|
||||
Go Home
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
@@ -180,29 +188,41 @@ export default function PlayPage() {
|
||||
|
||||
if (!joined) {
|
||||
return (
|
||||
<main className="min-h-screen flex items-center justify-center p-8 relative overflow-hidden">
|
||||
<div className="particles">
|
||||
{[...Array(30)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="particle"
|
||||
<main
|
||||
style={{
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `${Math.random() * 100}%`,
|
||||
animationDelay: `${Math.random() * 20}s`,
|
||||
minHeight: "100vh",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "24px",
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="card scale-in p-12 max-w-md w-full z-10 glow-mauve gradient-overlay">
|
||||
<h1 className="text-5xl font-bold mb-10 text-center text-gradient-mauve float">
|
||||
>
|
||||
<div
|
||||
className="card fade-in"
|
||||
style={{ padding: "32px", maxWidth: "450px", width: "100%" }}
|
||||
>
|
||||
<h1
|
||||
className="text-mauve"
|
||||
style={{
|
||||
fontSize: "1.75rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "32px",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
Join Game
|
||||
</h1>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-[var(--ctp-subtext1)] mb-2 uppercase tracking-wide">
|
||||
<div style={{ marginBottom: "24px" }}>
|
||||
<label
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
display: "block",
|
||||
fontSize: "0.875rem",
|
||||
marginBottom: "8px",
|
||||
fontWeight: "600",
|
||||
}}
|
||||
>
|
||||
Your Name
|
||||
</label>
|
||||
<input
|
||||
@@ -210,13 +230,22 @@ export default function PlayPage() {
|
||||
placeholder="Enter your name..."
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
className="w-full p-4 text-lg bg-[var(--ctp-surface1)] border-2 border-[var(--ctp-surface2)] rounded-xl text-[var(--ctp-text)] focus:border-[var(--ctp-mauve)] focus:outline-none transition-all placeholder-[var(--ctp-overlay0)]"
|
||||
className="input"
|
||||
style={{ width: "100%", padding: "12px", fontSize: "1rem" }}
|
||||
maxLength={20}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-[var(--ctp-subtext1)] mb-2 uppercase tracking-wide">
|
||||
<div style={{ marginBottom: "24px" }}>
|
||||
<label
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
display: "block",
|
||||
fontSize: "0.875rem",
|
||||
marginBottom: "8px",
|
||||
fontWeight: "600",
|
||||
}}
|
||||
>
|
||||
Room Code
|
||||
</label>
|
||||
<input
|
||||
@@ -224,140 +253,168 @@ export default function PlayPage() {
|
||||
placeholder="XXXXXX"
|
||||
value={code}
|
||||
onChange={(e) => setCode(e.target.value.toUpperCase())}
|
||||
className="w-full p-4 text-2xl font-bold bg-[var(--ctp-surface1)] border-2 border-[var(--ctp-surface2)] rounded-xl text-[var(--ctp-text)] focus:border-[var(--ctp-blue)] focus:outline-none transition-all uppercase tracking-widest text-center placeholder-[var(--ctp-overlay0)]"
|
||||
className="input"
|
||||
style={{
|
||||
width: "100%",
|
||||
padding: "12px",
|
||||
fontSize: "1.25rem",
|
||||
fontWeight: "bold",
|
||||
textAlign: "center",
|
||||
letterSpacing: "0.15em",
|
||||
textTransform: "uppercase",
|
||||
}}
|
||||
maxLength={6}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div style={{ marginBottom: "32px" }}>
|
||||
<label
|
||||
className={`card cursor-pointer p-4 transition-all ${
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
display: "block",
|
||||
fontSize: "0.875rem",
|
||||
marginBottom: "12px",
|
||||
fontWeight: "600",
|
||||
}}
|
||||
>
|
||||
Select Team
|
||||
</label>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
gap: "12px",
|
||||
}}
|
||||
>
|
||||
<label
|
||||
className={`card ${teamId === "1" ? "border-blue" : ""}`}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
padding: "16px",
|
||||
textAlign: "center",
|
||||
border:
|
||||
teamId === "1"
|
||||
? "border-[var(--ctp-blue)] glow-blue"
|
||||
: "border-[var(--ctp-surface2)]"
|
||||
}`}
|
||||
? "3px solid var(--ctp-blue)"
|
||||
: "3px solid transparent",
|
||||
transition: "all 0.2s",
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value="1"
|
||||
checked={teamId === "1"}
|
||||
onChange={(e) => setTeamId(e.target.value as "1" | "2")}
|
||||
className="hidden"
|
||||
style={{ display: "none" }}
|
||||
/>
|
||||
<div className="text-center">
|
||||
<div style={{ fontSize: "2rem", marginBottom: "8px" }}>🔵</div>
|
||||
<div
|
||||
className={`text-3xl mb-2 ${teamId === "1" ? "scale-110" : ""} transition-transform`}
|
||||
>
|
||||
🔵
|
||||
</div>
|
||||
<div
|
||||
className={`font-bold ${teamId === "1" ? "text-[var(--ctp-blue)]" : "text-[var(--ctp-subtext0)]"}`}
|
||||
className={teamId === "1" ? "text-blue" : "text-subtext0"}
|
||||
style={{ fontWeight: "bold", fontSize: "1rem" }}
|
||||
>
|
||||
Team 1
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label
|
||||
className={`card cursor-pointer p-4 transition-all ${
|
||||
className={`card ${teamId === "2" ? "border-red" : ""}`}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
padding: "16px",
|
||||
textAlign: "center",
|
||||
border:
|
||||
teamId === "2"
|
||||
? "border-[var(--ctp-red)] glow-red"
|
||||
: "border-[var(--ctp-surface2)]"
|
||||
}`}
|
||||
? "3px solid var(--ctp-red)"
|
||||
: "3px solid transparent",
|
||||
transition: "all 0.2s",
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
value="2"
|
||||
checked={teamId === "2"}
|
||||
onChange={(e) => setTeamId(e.target.value as "1" | "2")}
|
||||
className="hidden"
|
||||
style={{ display: "none" }}
|
||||
/>
|
||||
<div className="text-center">
|
||||
<div style={{ fontSize: "2rem", marginBottom: "8px" }}>🔴</div>
|
||||
<div
|
||||
className={`text-3xl mb-2 ${teamId === "2" ? "scale-110" : ""} transition-transform`}
|
||||
>
|
||||
🔴
|
||||
</div>
|
||||
<div
|
||||
className={`font-bold ${teamId === "2" ? "text-[var(--ctp-red)]" : "text-[var(--ctp-subtext0)]"}`}
|
||||
className={teamId === "2" ? "text-red" : "text-subtext0"}
|
||||
style={{ fontWeight: "bold", fontSize: "1rem" }}
|
||||
>
|
||||
Team 2
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={join}
|
||||
disabled={!name.trim() || code.length !== 6}
|
||||
className="btn w-full px-8 py-5 bg-gradient-to-r from-[var(--ctp-mauve)] to-[var(--ctp-pink)] disabled:from-[var(--ctp-surface1)] disabled:to-[var(--ctp-surface1)] disabled:text-[var(--ctp-overlay0)] text-[var(--ctp-base)] text-xl font-bold disabled:cursor-not-allowed"
|
||||
className="btn btn-primary text-base"
|
||||
style={{ width: "100%", padding: "14px", fontSize: "1.125rem" }}
|
||||
>
|
||||
Join Game
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
const phase = gameState?.phase || "lobby";
|
||||
const teamColor = teamId === "1" ? "blue" : "red";
|
||||
|
||||
return (
|
||||
<main className="min-h-screen p-4 relative overflow-hidden">
|
||||
<div className="particles">
|
||||
{[...Array(25)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="particle"
|
||||
style={{
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `${Math.random() * 100}%`,
|
||||
animationDelay: `${Math.random() * 20}s`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="max-w-4xl mx-auto relative z-10">
|
||||
<main style={{ minHeight: "100vh", padding: "24px" }}>
|
||||
<div style={{ maxWidth: "800px", margin: "0 auto" }}>
|
||||
{/* Player Header */}
|
||||
<div
|
||||
className={`card p-8 mb-6 slide-in-left ${teamId === "1" ? "team1-card" : "team2-card"}`}
|
||||
className={`card ${teamId === "1" ? "border-blue" : "border-red"}`}
|
||||
style={{
|
||||
padding: "20px",
|
||||
marginBottom: "24px",
|
||||
border: `3px solid ${teamId === "1" ? "var(--ctp-blue)" : "var(--ctp-red)"}`,
|
||||
}}
|
||||
>
|
||||
<div className="flex justify-between items-center">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
|
||||
<div style={{ fontSize: "2rem" }}>
|
||||
{teamId === "1" ? "🔵" : "🔴"}
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="text-4xl">{teamId === "1" ? "🔵" : "🔴"}</div>
|
||||
<h1 className="text-4xl font-bold text-[var(--ctp-text)]">
|
||||
<h1
|
||||
className="text-text"
|
||||
style={{ fontSize: "1.5rem", fontWeight: "bold" }}
|
||||
>
|
||||
{name}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="badge bg-[var(--ctp-surface1)] text-[var(--ctp-text)]">
|
||||
Team {teamId}
|
||||
</div>
|
||||
<div
|
||||
className={`badge bg-gradient-to-r ${
|
||||
teamId === "1"
|
||||
? "from-[var(--ctp-blue)] to-[var(--ctp-sapphire)]"
|
||||
: "from-[var(--ctp-red)] to-[var(--ctp-maroon)]"
|
||||
} text-[var(--ctp-base)]`}
|
||||
>
|
||||
Room: {code}
|
||||
<div className="text-subtext0" style={{ fontSize: "0.875rem" }}>
|
||||
Team {teamId} • Room: {code}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-right">
|
||||
<div className="text-sm text-[var(--ctp-subtext0)] uppercase tracking-wide mb-1">
|
||||
<div style={{ textAlign: "right" }}>
|
||||
<div
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
fontSize: "0.75rem",
|
||||
textTransform: "uppercase",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
Your Score
|
||||
</div>
|
||||
<div
|
||||
className={`text-6xl font-bold ${
|
||||
teamId === "1"
|
||||
? "text-gradient-blue"
|
||||
: "text-[var(--ctp-red)]"
|
||||
} neon-text`}
|
||||
className={teamId === "1" ? "text-blue" : "text-red"}
|
||||
style={{
|
||||
fontSize: "2.5rem",
|
||||
fontWeight: "bold",
|
||||
lineHeight: "1",
|
||||
}}
|
||||
>
|
||||
{myScore}
|
||||
</div>
|
||||
@@ -366,60 +423,113 @@ export default function PlayPage() {
|
||||
</div>
|
||||
|
||||
{/* Game Status */}
|
||||
<div className="card p-12 question-card fade-in">
|
||||
<div
|
||||
className="card"
|
||||
style={{
|
||||
padding: "32px",
|
||||
minHeight: "400px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{phase === "lobby" && (
|
||||
<div className="text-center">
|
||||
<div className="text-6xl mb-6 float">⏳</div>
|
||||
<h2 className="text-4xl font-bold mb-4 text-gradient-mauve">
|
||||
<div className="fade-in" style={{ textAlign: "center" }}>
|
||||
<div style={{ fontSize: "4rem", marginBottom: "20px" }}>⏳</div>
|
||||
<h2
|
||||
className="text-yellow"
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "12px",
|
||||
}}
|
||||
>
|
||||
Waiting for Game Start...
|
||||
</h2>
|
||||
<p className="text-xl text-[var(--ctp-subtext1)]">
|
||||
<p className="text-subtext0" style={{ fontSize: "1rem" }}>
|
||||
Get ready to buzz in!
|
||||
</p>
|
||||
<div className="mt-8">
|
||||
<div className="skeleton h-8 w-64 mx-auto mb-4" />
|
||||
<div className="skeleton h-8 w-48 mx-auto" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{phase === "intermission" && (
|
||||
<div className="text-center">
|
||||
<div className="text-6xl mb-6 float">📚</div>
|
||||
<h2 className="text-4xl font-bold mb-4 text-gradient-blue">
|
||||
<div className="fade-in" style={{ textAlign: "center" }}>
|
||||
<div style={{ fontSize: "4rem", marginBottom: "20px" }}>📚</div>
|
||||
<h2
|
||||
className="text-sky"
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "12px",
|
||||
}}
|
||||
>
|
||||
Next Question Loading...
|
||||
</h2>
|
||||
<p className="text-xl text-[var(--ctp-subtext1)]">
|
||||
Stay focused and ready!
|
||||
<p className="text-subtext0" style={{ fontSize: "1rem" }}>
|
||||
Stay focused!
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(phase === "tossup_reading" || phase === "tossup_buzzing") && (
|
||||
<div className="text-center">
|
||||
<div className="mb-8">
|
||||
<div className="badge bg-[var(--ctp-yellow)] text-[var(--ctp-base)] text-lg mb-4">
|
||||
<div
|
||||
className="fade-in"
|
||||
style={{ textAlign: "center", width: "100%" }}
|
||||
>
|
||||
<div
|
||||
className="bg-yellow text-base"
|
||||
style={{
|
||||
padding: "8px 20px",
|
||||
borderRadius: "999px",
|
||||
display: "inline-block",
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
TOSSUP QUESTION
|
||||
</div>
|
||||
<h2 className="text-5xl font-bold text-gradient-green mb-6">
|
||||
<h2
|
||||
className="text-green"
|
||||
style={{
|
||||
fontSize: "1.75rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "32px",
|
||||
}}
|
||||
>
|
||||
Listen Carefully!
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{canBuzz && !buzzing ? (
|
||||
<div className="scale-in">
|
||||
<button
|
||||
onClick={buzz}
|
||||
className="buzz-button buzz-active w-64 h-64 rounded-full text-white text-4xl font-bold relative z-10 mx-auto block"
|
||||
className="buzz-button active"
|
||||
style={{ margin: "0 auto", display: "block" }}
|
||||
>
|
||||
<div className="relative z-10">
|
||||
<div className="text-6xl mb-2">🔔</div>
|
||||
<div>BUZZ!</div>
|
||||
<div style={{ fontSize: "3rem", marginBottom: "8px" }}>
|
||||
🔔
|
||||
</div>
|
||||
<div style={{ fontSize: "1.5rem" }}>BUZZ!</div>
|
||||
</button>
|
||||
<p className="mt-8 text-2xl text-[var(--ctp-subtext1)] animate-pulse">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{
|
||||
fontSize: "1rem",
|
||||
marginTop: "20px",
|
||||
animation: "pulse 1.5s ease-in-out infinite",
|
||||
}}
|
||||
>
|
||||
Press{" "}
|
||||
<kbd className="px-3 py-1 bg-[var(--ctp-surface1)] rounded font-mono">
|
||||
<kbd
|
||||
style={{
|
||||
padding: "4px 12px",
|
||||
background: "var(--ctp-surface1)",
|
||||
borderRadius: "6px",
|
||||
fontFamily: "monospace",
|
||||
fontSize: "0.875rem",
|
||||
}}
|
||||
>
|
||||
SPACE
|
||||
</kbd>{" "}
|
||||
to buzz
|
||||
@@ -427,52 +537,140 @@ export default function PlayPage() {
|
||||
</div>
|
||||
) : buzzing ? (
|
||||
<div className="scale-in">
|
||||
<div className="buzz-button buzz-active w-64 h-64 rounded-full text-white text-4xl font-bold relative z-10 mx-auto flex items-center justify-center">
|
||||
<div className="text-6xl">✓</div>
|
||||
<div
|
||||
className="buzz-button"
|
||||
style={{
|
||||
margin: "0 auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
background:
|
||||
"linear-gradient(135deg, var(--ctp-green), var(--ctp-teal))",
|
||||
}}
|
||||
>
|
||||
<div style={{ fontSize: "4rem" }}>✓</div>
|
||||
</div>
|
||||
<p className="mt-8 text-3xl font-bold text-[var(--ctp-green)]">
|
||||
<p
|
||||
className="text-green"
|
||||
style={{
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: "bold",
|
||||
marginTop: "20px",
|
||||
}}
|
||||
>
|
||||
Buzzed!
|
||||
</p>
|
||||
</div>
|
||||
) : gameState?.buzzedPlayer === playerId ? (
|
||||
<div className="scale-in">
|
||||
<div className="w-64 h-64 rounded-full bg-gradient-to-br from-[var(--ctp-yellow)] to-[var(--ctp-peach)] text-[var(--ctp-base)] text-4xl font-bold relative z-10 mx-auto flex items-center justify-center glow-yellow">
|
||||
<div>
|
||||
<div className="text-6xl mb-2">⚡</div>
|
||||
<div>You Buzzed!</div>
|
||||
<div
|
||||
style={{
|
||||
width: "280px",
|
||||
height: "280px",
|
||||
borderRadius: "50%",
|
||||
background:
|
||||
"linear-gradient(135deg, var(--ctp-yellow), var(--ctp-peach))",
|
||||
margin: "0 auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
boxShadow: "0 0 40px rgba(249, 226, 175, 0.6)",
|
||||
}}
|
||||
>
|
||||
<div style={{ fontSize: "3rem", marginBottom: "12px" }}>
|
||||
⚡
|
||||
</div>
|
||||
<div
|
||||
className="text-base"
|
||||
style={{ fontSize: "1.5rem", fontWeight: "bold" }}
|
||||
>
|
||||
You Buzzed!
|
||||
</div>
|
||||
</div>
|
||||
<p className="mt-8 text-2xl text-[var(--ctp-yellow)] font-bold">
|
||||
Waiting for moderator judgment...
|
||||
<p
|
||||
className="text-yellow"
|
||||
style={{
|
||||
fontSize: "1.125rem",
|
||||
fontWeight: "bold",
|
||||
marginTop: "20px",
|
||||
}}
|
||||
>
|
||||
Waiting for moderator...
|
||||
</p>
|
||||
</div>
|
||||
) : gameState?.buzzedPlayer ? (
|
||||
<div className="scale-in">
|
||||
<div className="w-64 h-64 rounded-full bg-[var(--ctp-surface1)] border-4 border-[var(--ctp-overlay0)] text-4xl font-bold relative z-10 mx-auto flex items-center justify-center">
|
||||
<div>
|
||||
<div className="text-6xl mb-2 opacity-50">🔔</div>
|
||||
<div className="text-[var(--ctp-overlay1)]">
|
||||
<div
|
||||
style={{
|
||||
width: "280px",
|
||||
height: "280px",
|
||||
borderRadius: "50%",
|
||||
background: "var(--ctp-surface1)",
|
||||
border: "4px solid var(--ctp-overlay0)",
|
||||
margin: "0 auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
fontSize: "3rem",
|
||||
marginBottom: "12px",
|
||||
opacity: 0.5,
|
||||
}}
|
||||
>
|
||||
🔔
|
||||
</div>
|
||||
<div
|
||||
className="text-overlay1"
|
||||
style={{ fontSize: "1.25rem", fontWeight: "bold" }}
|
||||
>
|
||||
Someone
|
||||
<br />
|
||||
Buzzed
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p className="mt-8 text-xl text-[var(--ctp-subtext0)]">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{ fontSize: "1rem", marginTop: "20px" }}
|
||||
>
|
||||
Waiting for answer...
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="scale-in">
|
||||
<div className="w-64 h-64 rounded-full bg-[var(--ctp-surface1)] border-4 border-dashed border-[var(--ctp-overlay0)] text-4xl font-bold relative z-10 mx-auto flex items-center justify-center buzz-disabled">
|
||||
<div>
|
||||
<div className="text-6xl mb-2">👂</div>
|
||||
<div className="text-[var(--ctp-overlay1)]">
|
||||
<div
|
||||
style={{
|
||||
width: "280px",
|
||||
height: "280px",
|
||||
borderRadius: "50%",
|
||||
background: "var(--ctp-surface1)",
|
||||
border: "4px dashed var(--ctp-overlay0)",
|
||||
margin: "0 auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
opacity: 0.4,
|
||||
}}
|
||||
>
|
||||
<div style={{ fontSize: "3rem", marginBottom: "12px" }}>
|
||||
👂
|
||||
</div>
|
||||
<div
|
||||
className="text-overlay1"
|
||||
style={{ fontSize: "1.25rem", fontWeight: "bold" }}
|
||||
>
|
||||
Listen...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p className="mt-8 text-xl text-[var(--ctp-subtext0)]">
|
||||
<p
|
||||
className="text-subtext0"
|
||||
style={{ fontSize: "1rem", marginTop: "20px" }}
|
||||
>
|
||||
Question being read...
|
||||
</p>
|
||||
</div>
|
||||
@@ -481,34 +679,73 @@ export default function PlayPage() {
|
||||
)}
|
||||
|
||||
{phase === "bonus" && (
|
||||
<div className="text-center">
|
||||
<div className="mb-8">
|
||||
<div className="badge bg-[var(--ctp-mauve)] text-[var(--ctp-base)] text-lg mb-4">
|
||||
<div className="fade-in" style={{ textAlign: "center" }}>
|
||||
<div
|
||||
className="bg-mauve text-base"
|
||||
style={{
|
||||
padding: "8px 20px",
|
||||
borderRadius: "999px",
|
||||
display: "inline-block",
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
BONUS QUESTION
|
||||
</div>
|
||||
<h2 className="text-5xl font-bold text-gradient-mauve mb-4">
|
||||
<h2
|
||||
className="text-mauve"
|
||||
style={{
|
||||
fontSize: "1.75rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "12px",
|
||||
}}
|
||||
>
|
||||
{gameState?.currentTeam === parseInt(teamId)
|
||||
? "Your Team Bonus!"
|
||||
: "Other Team Bonus"}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{gameState?.currentTeam === parseInt(teamId) ? (
|
||||
<div className="scale-in">
|
||||
<div className="text-7xl mb-6 float">🎯</div>
|
||||
<p className="text-2xl text-[var(--ctp-text)] mb-6">
|
||||
<div className="scale-in" style={{ marginTop: "32px" }}>
|
||||
<div style={{ fontSize: "4rem", marginBottom: "20px" }}>
|
||||
🎯
|
||||
</div>
|
||||
<p
|
||||
className="text-text"
|
||||
style={{ fontSize: "1.25rem", marginBottom: "20px" }}
|
||||
>
|
||||
Work together with your team!
|
||||
</p>
|
||||
<div className="inline-block px-8 py-4 bg-[var(--ctp-mauve)]/20 border-2 border-[var(--ctp-mauve)] rounded-xl">
|
||||
<p className="text-[var(--ctp-mauve)] font-bold text-lg">
|
||||
<div
|
||||
style={{
|
||||
display: "inline-block",
|
||||
padding: "16px 28px",
|
||||
background: "rgba(203, 166, 247, 0.2)",
|
||||
border: "2px solid var(--ctp-mauve)",
|
||||
borderRadius: "12px",
|
||||
}}
|
||||
>
|
||||
<p
|
||||
className="text-mauve"
|
||||
style={{ fontWeight: "bold", fontSize: "1.125rem" }}
|
||||
>
|
||||
+10 points if correct
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="scale-in">
|
||||
<div className="text-7xl mb-6 opacity-50">⏸️</div>
|
||||
<p className="text-2xl text-[var(--ctp-subtext0)]">
|
||||
<div className="scale-in" style={{ marginTop: "32px" }}>
|
||||
<div
|
||||
style={{
|
||||
fontSize: "4rem",
|
||||
marginBottom: "20px",
|
||||
opacity: 0.5,
|
||||
}}
|
||||
>
|
||||
⏸️
|
||||
</div>
|
||||
<p className="text-subtext0" style={{ fontSize: "1.125rem" }}>
|
||||
Waiting for other team...
|
||||
</p>
|
||||
</div>
|
||||
@@ -517,16 +754,42 @@ export default function PlayPage() {
|
||||
)}
|
||||
|
||||
{phase === "finished" && (
|
||||
<div className="text-center">
|
||||
<div className="text-8xl mb-8 float">🏁</div>
|
||||
<h2 className="text-6xl font-bold mb-6 text-gradient-green">
|
||||
<div className="fade-in" style={{ textAlign: "center" }}>
|
||||
<div style={{ fontSize: "5rem", marginBottom: "24px" }}>🏁</div>
|
||||
<h2
|
||||
className="text-green"
|
||||
style={{
|
||||
fontSize: "2rem",
|
||||
fontWeight: "bold",
|
||||
marginBottom: "20px",
|
||||
}}
|
||||
>
|
||||
Game Over!
|
||||
</h2>
|
||||
<div className="inline-block px-12 py-8 bg-gradient-to-br from-[var(--ctp-surface0)] to-[var(--ctp-surface1)] rounded-2xl border-4 border-[var(--ctp-mauve)] glow-mauve">
|
||||
<p className="text-[var(--ctp-subtext1)] text-xl mb-2">
|
||||
<div
|
||||
style={{
|
||||
display: "inline-block",
|
||||
padding: "24px 40px",
|
||||
background:
|
||||
"linear-gradient(135deg, var(--ctp-surface0), var(--ctp-surface1))",
|
||||
borderRadius: "16px",
|
||||
border: "4px solid var(--ctp-mauve)",
|
||||
}}
|
||||
>
|
||||
<p
|
||||
className="text-subtext1"
|
||||
style={{ fontSize: "1rem", marginBottom: "8px" }}
|
||||
>
|
||||
Your Final Score
|
||||
</p>
|
||||
<p className="text-7xl font-bold text-gradient-mauve neon-text">
|
||||
<p
|
||||
className="text-mauve"
|
||||
style={{
|
||||
fontSize: "3rem",
|
||||
fontWeight: "bold",
|
||||
lineHeight: "1",
|
||||
}}
|
||||
>
|
||||
{myScore}
|
||||
</p>
|
||||
</div>
|
||||
@@ -535,10 +798,11 @@ export default function PlayPage() {
|
||||
</div>
|
||||
|
||||
{/* Leave Button */}
|
||||
<div className="mt-6 text-center slide-in-right">
|
||||
<div style={{ marginTop: "24px", textAlign: "center" }}>
|
||||
<button
|
||||
onClick={leave}
|
||||
className="btn px-8 py-4 bg-[var(--ctp-overlay0)] hover:bg-[var(--ctp-overlay1)] text-[var(--ctp-text)] font-bold"
|
||||
className="btn btn-secondary text-text"
|
||||
style={{ padding: "12px 24px", fontSize: "0.875rem" }}
|
||||
>
|
||||
Leave Game
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user