mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
/noitupvp posts the noitu game card in a group and records it as a PvP card. Everyone who presses Play on that card joins one room: the first member hosts and starts, 2 to 8 players take 30-second turns, a player whose turn runs out or who gives up is eliminated, and the last one standing wins. Each player's points, plus a winner bonus, go to the card's high-score table, and the bot replies to the card with the result. The engine now shares one board between the solo game and the new multiplayer match, so both use the same word rules and scoring.
169 lines
6.3 KiB
CSS
169 lines
6.3 KiB
CSS
:root {
|
|
--bg: #f6f7f9;
|
|
--surface: #ffffff;
|
|
--text: #1b1f24;
|
|
--muted: #5f6b7a;
|
|
--border: #d9dee5;
|
|
--accent: #2481cc;
|
|
--accent-text: #ffffff;
|
|
--bot: #eef1f5;
|
|
--player: #e3f0fb;
|
|
--other: #fbf1e3;
|
|
--error: #c0392b;
|
|
--ok: #1e8e3e;
|
|
--warn: #d68910;
|
|
--radius: 12px;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--bg: #17212b;
|
|
--surface: #1f2b38;
|
|
--text: #e9eef3;
|
|
--muted: #93a1b0;
|
|
--border: #2f3d4c;
|
|
--accent: #5aa7e6;
|
|
--accent-text: #0e1621;
|
|
--bot: #263342;
|
|
--player: #1d3b55;
|
|
--other: #3d3423;
|
|
--error: #ff7b6b;
|
|
--ok: #6fcf87;
|
|
--warn: #f5b041;
|
|
}
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
[hidden] { display: none !important; }
|
|
|
|
html, body { margin: 0; padding: 0; }
|
|
|
|
body {
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font: 16px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
-webkit-text-size-adjust: 100%;
|
|
}
|
|
|
|
.app {
|
|
max-width: 560px;
|
|
margin: 0 auto;
|
|
padding: 12px 16px calc(16px + env(safe-area-inset-bottom));
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
.top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
|
|
h1 { font-size: 1.5rem; margin: 0; }
|
|
h2 { font-size: 1.2rem; margin: 0 0 8px; }
|
|
.player-name { margin: 0; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
.card {
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
padding: 16px;
|
|
}
|
|
|
|
.lead { margin-top: 0; font-size: 1.05rem; }
|
|
.muted { color: var(--muted); }
|
|
.rules { padding-left: 20px; color: var(--muted); }
|
|
.error { color: var(--error); min-height: 1.4em; margin: 8px 0 0; }
|
|
|
|
button {
|
|
font: inherit;
|
|
border-radius: 10px;
|
|
border: 1px solid var(--border);
|
|
background: var(--surface);
|
|
color: var(--text);
|
|
padding: 10px 16px;
|
|
min-height: 44px;
|
|
cursor: pointer;
|
|
}
|
|
button:disabled { opacity: .6; cursor: default; }
|
|
button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); font-weight: 600; }
|
|
button.ghost { background: transparent; color: var(--muted); align-self: center; }
|
|
|
|
.difficulty { border: 1px solid var(--border); border-radius: 10px; margin: 0 0 16px; padding: 8px 12px 12px; }
|
|
.difficulty legend { padding: 0 4px; color: var(--muted); }
|
|
.difficulty label { display: inline-flex; align-items: center; gap: 6px; margin-right: 16px; min-height: 36px; }
|
|
|
|
.scoreline { display: flex; justify-content: space-between; align-items: center; font-size: 1.05rem; }
|
|
.timer-text { font-variant-numeric: tabular-nums; font-weight: 600; }
|
|
.timer-text.low { color: var(--error); }
|
|
|
|
.timer-track { height: 6px; border-radius: 3px; background: var(--border); overflow: hidden; }
|
|
.timer-bar { height: 100%; width: 100%; background: var(--accent); transform-origin: left center; }
|
|
.timer-bar.low { background: var(--error); }
|
|
|
|
.move-form { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
|
|
.move-form label { color: var(--muted); }
|
|
.move-form label strong { color: var(--text); font-size: 1.15rem; }
|
|
.move-row { display: flex; gap: 8px; }
|
|
.move-row input {
|
|
flex: 1;
|
|
min-width: 0;
|
|
font: inherit;
|
|
font-size: 1.1rem;
|
|
padding: 10px 12px;
|
|
border-radius: 10px;
|
|
border: 1px solid var(--border);
|
|
background: var(--surface);
|
|
color: var(--text);
|
|
}
|
|
.move-row input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
|
|
.message { min-height: 1.4em; margin: 0; }
|
|
.message.error { color: var(--error); }
|
|
.message.thinking { color: var(--muted); }
|
|
.message.thinking::after { content: "…"; animation: blink 1s steps(2) infinite; }
|
|
@keyframes blink { 50% { opacity: 0; } }
|
|
|
|
.chain-box { display: flex; flex-direction: column; }
|
|
.chain-title { font-size: 1rem; color: var(--muted); font-weight: 600; }
|
|
.chain { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column-reverse; gap: 6px; }
|
|
.chain > li { border-radius: 10px; padding: 8px 12px; background: var(--bot); }
|
|
.chain > li.player { background: var(--player); }
|
|
.chain .row { display: flex; align-items: center; gap: 8px; }
|
|
.chain .who { font-size: .8rem; color: var(--muted); min-width: 34px; max-width: 35%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
.chain > li.other { background: var(--other); }
|
|
.chain .word { font-weight: 600; flex: 1; overflow-wrap: anywhere; }
|
|
.chain .points { font-size: .85rem; color: var(--ok); }
|
|
.chain .toggle { padding: 2px 8px; min-height: 30px; font-size: .8rem; }
|
|
.chain .no-meaning { font-size: .8rem; color: var(--muted); }
|
|
.chain ol.senses { margin: 6px 0 0; padding-left: 22px; font-size: .9rem; color: var(--muted); }
|
|
.chain > li.fresh { animation: pop .35s ease-out; }
|
|
@keyframes pop { from { transform: scale(.97); opacity: .4; } to { transform: none; opacity: 1; } }
|
|
|
|
.players { list-style: none; margin: 12px 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
.players > li { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 10px; background: var(--bot); }
|
|
.players > li.you { background: var(--player); }
|
|
.players .name { flex: 1; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
.players .tag { font-size: .8rem; color: var(--muted); }
|
|
.players .score { font-variant-numeric: tabular-nums; color: var(--ok); }
|
|
.players.compact { flex-direction: row; flex-wrap: wrap; margin: 0; }
|
|
.players.compact > li { padding: 4px 10px; font-size: .9rem; max-width: 100%; }
|
|
.players.compact > li.turn { outline: 2px solid var(--accent); }
|
|
.players > li.out { opacity: .55; }
|
|
.players > li.out .name { text-decoration: line-through; }
|
|
.turn-line { margin: 0; font-weight: 600; }
|
|
.turn-line.mine { color: var(--accent); }
|
|
.room-result { border-bottom: 1px solid var(--border); margin-bottom: 12px; padding-bottom: 8px; }
|
|
.standings { padding-left: 22px; margin: 8px 0; }
|
|
.standings li.you { font-weight: 600; }
|
|
|
|
.final-score { font-size: 1.2rem; }
|
|
.suggestions { padding-left: 20px; }
|
|
.actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
|
|
.report-ok { color: var(--ok); }
|
|
.report-failed { color: var(--warn); }
|
|
|
|
.footer { margin-top: auto; padding-top: 8px; font-size: .8rem; color: var(--muted); text-align: center; }
|
|
.footer a { color: inherit; }
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.chain > li.fresh, .message.thinking::after { animation: none; }
|
|
}
|