Lobby: CSS 3D dice tray at the top right next to the chat

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 18:07:07 +00:00
parent 968d168ff1
commit d730022447
4 changed files with 147 additions and 62 deletions
+45 -18
View File
@@ -228,24 +228,6 @@ body:has(.lobbychat) main { max-width: none; margin: 0; padding-right: calc(var(
.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: calc((100vw - var(--chatw)) / 2); 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; } }
@media (max-width: 1050px) { body:has(.lobbychat) main { max-width: 1280px; margin: 0 auto; padding-right: 1rem; } .lobbychat { position: static; width: auto; height: 28rem; border-width: 1px; border-radius: var(--radius); margin-top: 1rem; } .dicebar, .dicetray { left: 50%; } .dicebar { max-width: calc(100vw - 1.5rem); } }
.lobbycard { align-content: start; }
@@ -328,3 +310,48 @@ body:has(.lobbychat) main { max-width: none; margin: 0; padding-right: calc(var(
.lobbyhead h1 { font-size: 1.3rem; margin: 0; }
.lobbypage .tabs { margin: .4rem 0 .7rem; }
.lobbypage .tabs button { padding: .3rem .8rem; }
/* ---- 3D dice tray (top right, left of the chat) ---- */
.dicetray3d { position: fixed; top: calc(var(--hdr) + .8rem); right: calc(var(--chatw) + 1rem); z-index: 25; display: grid; gap: .6rem; pointer-events: none; perspective: 800px; }
.traygroup { background: radial-gradient(ellipse at 50% 35%, #2b3a20, #151c10 85%); border: 1px solid #3c4c2e; border-radius: 16px; padding: .5rem .6rem .35rem; box-shadow: 0 10px 30px rgba(0, 0, 0, .35), inset 0 0 24px rgba(0, 0, 0, .45); animation: trayin .3s ease-out; overflow: hidden; }
.traygroup.secret { background: radial-gradient(ellipse at 50% 35%, #33284a, #17101f 85%); border-color: #5b4a86; }
.traycap { display: flex; justify-content: space-between; gap: 1rem; font-size: .78rem; color: #cfd8c0; margin-bottom: .2rem; }
.traycap b { color: #fff; }
.trayres { font-weight: 800; font-size: 1.05rem; color: #fff; opacity: 0; animation: resin .3s ease-out 1.45s forwards; }
.traygroup.still .trayres { opacity: 1; animation: none; }
.traydice { position: relative; min-width: 150px; }
.dieslot { --dc: #ece7d2; --ink: #1c2116; position: absolute; width: 58px; height: 58px; transform-style: preserve-3d; }
.secret .dieslot { --dc: #cbb9f2; }
.dieshadow { position: absolute; left: 8%; right: 8%; bottom: -4px; height: 10px; border-radius: 50%; background: rgba(0, 0, 0, .55); filter: blur(3px); opacity: 0; animation: shadowin .25s ease-out calc(var(--delay) + var(--dur) * .55) forwards; }
.flight, .tilt, .spin { position: absolute; inset: 0; transform-style: preserve-3d; }
.flight { animation: fly var(--dur) cubic-bezier(.3, .1, .4, 1) var(--delay) both; }
.tilt { transform: rotateX(-20deg) rotateY(-24deg); }
.spin { transform: rotateX(var(--rx1)) rotateY(var(--ry1)) rotateZ(var(--rz1)); animation: tumble var(--dur) cubic-bezier(.2, .75, .35, 1) var(--delay) both; }
.layer { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; fill: var(--dc); stroke: #3a3f2c; stroke-width: 2.4; stroke-linejoin: round; }
.layer .facet { fill: none; stroke: rgba(40, 46, 30, .55); stroke-width: 1.6; }
.layer .pip { fill: var(--ink); stroke: none; font: 800 30px "Bahnschrift", "Segoe UI", system-ui, sans-serif; }
.cf { position: absolute; inset: 0; display: grid; place-items: center; font: 800 26px "Bahnschrift", "Segoe UI", system-ui, sans-serif; color: var(--ink); border: 1.5px solid #3a3f2c; border-radius: 9px; backface-visibility: hidden;
background: linear-gradient(145deg, var(--dc), color-mix(in srgb, var(--dc) 78%, #6d664a)); box-shadow: inset 0 0 8px rgba(0, 0, 0, .12); }
.cf-front { transform: translateZ(29px); }
.cf-back { transform: rotateY(180deg) translateZ(29px); }
.cf-right { transform: rotateY(90deg) translateZ(29px); }
.cf-left { transform: rotateY(-90deg) translateZ(29px); }
.cf-top { transform: rotateX(90deg) translateZ(29px); }
.cf-bottom { transform: rotateX(-90deg) translateZ(29px); }
@keyframes fly {
0% { transform: translate3d(var(--dx), var(--dy), 260px); }
56% { transform: translate3d(0, 0, 0); }
68% { transform: translate3d(calc(var(--dx) * -.05), -28px, 46px); }
80% { transform: translate3d(0, 0, 0); }
89% { transform: translate3d(0, -9px, 14px); }
100% { transform: translate3d(0, 0, 0); }
}
@keyframes tumble {
0% { transform: rotateX(var(--rx0)) rotateY(var(--ry0)) rotateZ(var(--rz0)); }
100% { transform: rotateX(var(--rx1)) rotateY(var(--ry1)) rotateZ(var(--rz1)); }
}
@keyframes shadowin { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: scale(1); } }
@keyframes resin { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes trayin { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .flight, .spin, .dieshadow, .traygroup { animation: none; } .dieshadow { opacity: 1; } }
@media (max-width: 1050px) { .dicetray3d { right: 1rem; top: auto; bottom: 5.6rem; } }