Lobby: desktop layout with chat column, dice hotbar and shared dice tray, server-side rolls

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJhXuLD2Z6hv3Wqeq9UL9K
This commit is contained in:
Claude
2026-10-21 16:51:16 +00:00
parent 94d3505b82
commit a88b8d2fa3
4 changed files with 315 additions and 108 deletions
+41
View File
@@ -204,3 +204,44 @@ h2 + .charlist, .card + h2 { margin-top: 1.4rem; }
.sheetview h4 { margin: 1rem 0 .3rem; }
.sheetview table { width: 100%; }
@media (max-width: 760px) { .sheetcols { grid-template-columns: 1fr; } .chatform { flex-wrap: wrap; } .chatform select { width: 100%; } }
/* lobby desktop layout: main area left, chat column right, dice bar bottom centre */
.lobbypage { max-width: 1500px; padding-bottom: 8rem; }
.lobbygrid { display: grid; grid-template-columns: minmax(0, 1fr) 400px; gap: 1.4rem; align-items: start; }
.lobbychat { position: sticky; top: 4.6rem; height: calc(100vh - 11rem); min-height: 22rem; padding: .7rem; display: flex; flex-direction: column; }
.lobbychat .chatwrap { flex: 1; min-height: 0; grid-template-rows: minmax(0, 1fr) auto auto auto auto; }
.lobbychat .chatbox { height: auto; min-height: 0; }
.lobbychat .chatform { flex-wrap: wrap; }
.lobbychat .chatform select { width: 100%; flex-basis: 100%; }
.lobbychat .chatform input { flex: 1 1 8rem; }
.partygrid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.msg.rollmsg .rollres b { font-size: 1.05rem; color: var(--noxium); }
.whispertag { color: #8a63c7; }
@media (max-width: 1050px) { .lobbygrid { grid-template-columns: 1fr; } .lobbychat { position: static; height: 28rem; } }
.dicebar { position: fixed; bottom: 1rem; left: 50%; transform: translateX(-50%); z-index: 30; display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; justify-content: center;
max-width: calc(100vw - 1.5rem); background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: .4rem .8rem; box-shadow: 0 6px 24px rgba(0, 0, 0, .22); }
.dicecount { display: flex; align-items: center; gap: .3rem; margin-right: .3rem; }
.dicecount select { width: auto; padding: .25rem .4rem; }
.diebtn { display: flex; flex-direction: column; align-items: center; gap: 0; padding: .2rem .5rem; border-radius: 12px; min-width: 3.1rem; font-size: .75rem; line-height: 1.1; }
.diebtn:hover:not(:disabled) { border-color: var(--noxium); color: var(--noxium); }
.dicedest { margin-left: .4rem; padding-left: .6rem; border-left: 1px solid var(--line); }
.dicedest.priv { color: #8a63c7; font-weight: 600; }
.dicetray { position: fixed; bottom: 5.4rem; left: 50%; transform: translateX(-50%); z-index: 29; display: grid; gap: .5rem; justify-items: center; pointer-events: none; }
.trayroll { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: .5rem .9rem; box-shadow: 0 6px 24px rgba(0, 0, 0, .25); animation: trayin .25s ease-out; }
.trayrow { display: flex; align-items: center; gap: .5rem; margin-top: .3rem; flex-wrap: wrap; justify-content: center; max-width: 30rem; }
.traytotal { font-weight: 700; font-size: 1.2rem; margin-left: .3rem; }
.die { display: inline-flex; align-items: center; justify-content: center; width: 2.9rem; height: 2.9rem; background: var(--noxium); color: #12150f; font-weight: 800; font-variant-numeric: tabular-nums; }
.die.d4 { clip-path: polygon(50% 4%, 96% 92%, 4% 92%); padding-top: .55rem; }
.die.d6 { border-radius: 12px; }
.die.d8 { clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); }
.die.d10 { clip-path: polygon(50% 0, 98% 40%, 50% 100%, 2% 40%); }
.die.d12 { clip-path: polygon(50% 0, 98% 38%, 80% 96%, 20% 96%, 2% 38%); }
.die.d20 { clip-path: polygon(25% 4%, 75% 4%, 100% 50%, 75% 96%, 25% 96%, 0 50%); }
.die.d100 { border-radius: 50%; }
.die.rolling { animation: tumble .32s linear infinite; filter: brightness(.9); }
.die.landed { animation: land .25s ease-out; }
@keyframes tumble { 0% { transform: rotate(0) translateY(0); } 25% { transform: rotate(90deg) translateY(-8px); } 50% { transform: rotate(180deg) translateY(0); } 75% { transform: rotate(270deg) translateY(-5px); } 100% { transform: rotate(360deg) translateY(0); } }
@keyframes land { 0% { transform: scale(1.35); } 100% { transform: scale(1); } }
@keyframes trayin { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .die.rolling, .die.landed, .trayroll { animation: none; } }