feat: stratagem icons, session summary, queue preview, UX polish
- Download 65 SVG icons from community repo (scripts/download-icons.js) - Gold CSS filter on all icons to match game theme - Session summary modal with score/accuracy/top stratagems - Queue preview strip (next 3 stratagems with icons) - Score popup animation, icon shake on wrong input - Icons in history, leaderboard, and best-per-stratagem tables - server.js: icon fields on all stratagems, ELO in lobby-update WS events
This commit is contained in:
@@ -1658,4 +1658,249 @@ select option { background: var(--bg-surface2); }
|
||||
.page-title { font-size: 1.3rem; }
|
||||
.match-wins { font-size: 1.8rem; }
|
||||
.match-status-text { font-size: 1.2rem; }
|
||||
.stratagem-icon-lg { width: 70px; height: 70px; }
|
||||
}
|
||||
|
||||
/* ── Stratagem icons ─────────────────────────────────────────────────────── */
|
||||
.stratagem-icon-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.stratagem-icon-lg {
|
||||
width: 86px;
|
||||
height: 86px;
|
||||
object-fit: contain;
|
||||
filter: invert(1) sepia(1) saturate(3) hue-rotate(0deg) brightness(1.1);
|
||||
/* Converts monochrome SVG → gold/yellow to match theme */
|
||||
opacity: 0.92;
|
||||
transition: transform 0.25s ease, opacity 0.2s;
|
||||
}
|
||||
|
||||
.stratagem-icon-lg.icon-complete {
|
||||
transform: scale(1.12);
|
||||
filter: invert(1) sepia(1) saturate(6) hue-rotate(0deg) brightness(1.3);
|
||||
}
|
||||
|
||||
.stratagem-icon-lg.icon-wrong {
|
||||
animation: iconShake 0.35s ease;
|
||||
}
|
||||
|
||||
.stratagem-icon-fallback {
|
||||
font-size: 3rem;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.stratagem-icon-md {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
object-fit: contain;
|
||||
filter: invert(1) sepia(1) saturate(3) hue-rotate(0deg) brightness(1.1);
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.stratagem-icon-sm {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
object-fit: contain;
|
||||
filter: invert(1) sepia(1) saturate(2) hue-rotate(0deg) brightness(1);
|
||||
opacity: 0.7;
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* Icon shake animation */
|
||||
@keyframes iconShake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
20% { transform: translateX(-5px) rotate(-3deg); }
|
||||
40% { transform: translateX(5px) rotate(3deg); }
|
||||
60% { transform: translateX(-4px) rotate(-2deg); }
|
||||
80% { transform: translateX(4px) rotate(2deg); }
|
||||
}
|
||||
|
||||
/* ── Stratagem queue (upcoming stratagems) ───────────────────────────────── */
|
||||
.stratagem-queue {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin: 6px 0 10px;
|
||||
min-height: 52px;
|
||||
}
|
||||
|
||||
.queue-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
opacity: 0.45;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.queue-item:first-child { opacity: 0.7; }
|
||||
|
||||
.queue-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
object-fit: contain;
|
||||
filter: invert(1) sepia(1) saturate(2) hue-rotate(0deg) brightness(1);
|
||||
}
|
||||
|
||||
.queue-icon-fallback {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.2rem;
|
||||
background: var(--bg-surface2);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.queue-label {
|
||||
font-size: 0.6rem;
|
||||
color: var(--text-muted);
|
||||
max-width: 60px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* ── Score popup ─────────────────────────────────────────────────────────── */
|
||||
.score-popup {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-family: var(--font-heading);
|
||||
font-size: 2.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
text-shadow: 0 0 20px var(--accent-glow), 0 2px 8px rgba(0,0,0,0.8);
|
||||
pointer-events: none;
|
||||
z-index: 900;
|
||||
opacity: 0;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.score-popup.show {
|
||||
animation: scoreFloat 0.9s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes scoreFloat {
|
||||
0% { opacity: 1; transform: translate(-50%, -50%) scale(0.8); }
|
||||
30% { opacity: 1; transform: translate(-50%, -70%) scale(1.1); }
|
||||
100% { opacity: 0; transform: translate(-50%, -120%) scale(0.9); }
|
||||
}
|
||||
|
||||
/* ── Session summary modal ───────────────────────────────────────────────── */
|
||||
.summary-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.summary-stat {
|
||||
background: var(--bg-surface2);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 12px 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.summary-stat-val {
|
||||
font-family: var(--font-heading);
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.summary-stat-label {
|
||||
font-size: 0.7rem;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.summary-top-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 6px 0;
|
||||
border-bottom: 1px solid var(--border-dim);
|
||||
}
|
||||
|
||||
.summary-top-item:last-child { border-bottom: none; }
|
||||
|
||||
.summary-top-rank {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-muted);
|
||||
width: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.summary-top-name {
|
||||
flex: 1;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.summary-top-time {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* ── Arrow transition polish ─────────────────────────────────────────────── */
|
||||
.arrow-key {
|
||||
transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease, transform 0.12s ease;
|
||||
}
|
||||
|
||||
.arrow-key.active {
|
||||
transform: scale(1.12);
|
||||
}
|
||||
|
||||
/* ── pw-display ──────────────────────────────────────────────────────────── */
|
||||
.pw-display {
|
||||
margin-top: 10px;
|
||||
padding: 10px 12px;
|
||||
background: var(--bg-surface2);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85rem;
|
||||
color: var(--accent);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* ── Admin layout ────────────────────────────────────────────────────────── */
|
||||
.admin-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.admin-user-list { display: flex; flex-direction: column; gap: 8px; }
|
||||
|
||||
.admin-user-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid var(--border-dim);
|
||||
}
|
||||
|
||||
.admin-user-row:last-child { border-bottom: none; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.summary-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.admin-layout { grid-template-columns: 1fr; }
|
||||
.stratagem-icon-lg { width: 70px; height: 70px; }
|
||||
.stratagem-queue { gap: 8px; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user