:root {
  --wall: #f8efdf; --ink: #3d2c29; --muted: #8a7468; --accent: #c8454f; --card: #fffaf2; --line: #e6d5bd;
  --p0: #e05a76; --p1: #24918e; --ok: #3aa76d; --shadow: 0 6px 20px rgba(80, 50, 30, .14);
  --r: #e5383b; --y: #f4c430; --g: #3aa655; --b: #1e88e5;
  --surface: #fff; --bar: rgba(255, 250, 242, .94); --stage: #f3e4cb; --on-ink: #fff;
  color-scheme: light;
}
/* Lamp off: dark mode */
:root[data-theme="dark"] {
  --wall: #1c1926; --ink: #efe6dc; --muted: #a99c92; --card: #29242f; --line: #3d3546; --accent: #ef6f79;
  --shadow: 0 6px 20px rgba(0, 0, 0, .45); --surface: #332c3a; --bar: rgba(34, 29, 41, .94); --stage: #2a2433; --on-ink: #1c1926;
  color-scheme: dark;
}
* { box-sizing: border-box; }
html, body { margin: 0; }
body { font-family: 'Fredoka', system-ui, sans-serif; color: var(--ink); background: var(--wall); transition: background-color .5s, color .5s; min-height: 100vh; -webkit-tap-highlight-color: transparent; overflow-x: hidden; }
h2, h3 { font-weight: 600; }
button { font: inherit; font-weight: 500; cursor: pointer; border: 0; border-radius: 999px; padding: .5em 1.05em; background: var(--card); color: var(--ink); box-shadow: 0 2px 0 rgba(0, 0, 0, .12), 0 0 0 1px var(--line) inset; transition: transform .1s, filter .15s; }
button:hover:not(:disabled) { filter: brightness(.97); }
button:active:not(:disabled) { transform: translateY(1px); }
button:disabled { opacity: .45; cursor: default; }
button.on { background: var(--ink); color: var(--on-ink); }
.btn-primary { background: var(--accent); color: #fff; box-shadow: 0 3px 0 #8f2c35; }
.icon-btn { padding: .45em .6em; }
input, textarea { font: inherit; width: 100%; padding: .6em .8em; border: 2px solid var(--line); border-radius: 12px; background: var(--surface); color: var(--ink); }
input:focus, textarea:focus { outline: none; border-color: var(--accent); }
.small { font-size: 13px; color: var(--muted); }
.spacer { flex: 1; }
.panel { background: var(--card); border-radius: 18px; padding: 14px; box-shadow: var(--shadow); }
.hint { text-align: center; color: var(--muted); }

/* top bar */
#bar { position: sticky; top: 0; z-index: 30; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 16px; background: var(--bar); backdrop-filter: blur(6px); border-bottom: 1px solid var(--line); }
.players { display: flex; gap: 6px; }
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; font-size: 14px; background: var(--surface); box-shadow: 0 0 0 2px currentColor inset; }
.chip:not(.me) { cursor: default; }
.chip .edit { font-size: 11px; opacity: .6; }
.chip.me:hover .edit { opacity: 1; }
.chip .dot { width: 9px; height: 9px; border-radius: 50%; background: #cbbfb3; }
.chip.online .dot { background: var(--ok); }
.p0 { color: var(--p0); } .p1 { color: var(--p1); }
.status { font-size: 13px; color: var(--muted); }
.status.s-connected { color: var(--ok); }
.status.s-offline, .status.s-busy { color: var(--accent); }
.reacts { display: flex; }
.reacts button { padding: 2px 5px; background: transparent; box-shadow: none; font-size: 20px; }
.reacts button:hover { transform: scale(1.2); }

main { padding: 16px; max-width: 1120px; margin: 0 auto; }

/* room */
.room .scene { width: 100%; height: auto; display: block; border-radius: 22px; box-shadow: var(--shadow); background: #f8efdf; }
.room-title { font-family: 'Fredoka', sans-serif; font-weight: 700; fill: #c8454f; paint-order: stroke; stroke: #fff; stroke-width: 6px; cursor: default; }
.item { cursor: pointer; outline: none; }
.item-art { transition: transform .2s; transform-box: fill-box; transform-origin: 50% 100%; }
.item:hover .item-art, .item:focus .item-art { transform: scale(1.1) translateY(-4px); }
.item .lbl { font-size: 15px; font-weight: 600; fill: #fff; paint-order: stroke; stroke: var(--ink); stroke-width: 4px; opacity: 0; transition: opacity .2s; pointer-events: none; }
.item:hover .lbl, .item:focus .lbl { opacity: 1; }
/* lamp, night and the animals */
.lamp-shade { fill: #f2c46d; transition: fill .4s; }
.lamp-glow { transition: opacity .5s; }
.night .lamp-shade { fill: #a8925f; }
.night .lamp-glow { opacity: 0; }
.night-shade { opacity: 0; transition: opacity .6s; }
.night .night-shade { opacity: .55; }
.night-sky { opacity: 0; }
.night .night-sky { opacity: 1; }
.night .room-title { stroke: #2a2340; }
.switched.night .night-shade, .switched.night .night-sky { animation: fade-in .6s; }
.switched:not(.night) .night-shade { animation: fade-out .6s; }
@keyframes fade-in { from { opacity: 0; } }
@keyframes fade-out { from { opacity: .55; } }
.star { animation: twinkle 2.4s ease-in-out infinite; } .star.s2 { animation-delay: .8s; } .star.s3 { animation-delay: 1.6s; }
@keyframes twinkle { 50% { opacity: .2; } }

.pet, .aquarium { cursor: pointer; outline: none; }
.pet .lbl, .aquarium .lbl { font-size: 14px; font-weight: 600; fill: #fff; paint-order: stroke; stroke: #3d2c29; stroke-width: 4px; opacity: 0; transition: opacity .2s; pointer-events: none; }
.pet:hover .lbl, .pet:focus .lbl, .aquarium:hover .lbl, .aquarium:focus .lbl { opacity: 1; }
.pet:hover, .aquarium:hover { filter: brightness(1.06); }
.pet g, .aquarium g, .zzz { transform-box: fill-box; }
.eyes-happy, .blush, .treat-item, .zzz { opacity: 0; }
.eyes-open { transform-origin: 50% 50%; animation: blink 4.5s infinite; }
@keyframes blink { 0%, 92%, 100% { transform: scaleY(1); } 95% { transform: scaleY(.1); } }
.petted .eyes-open, .treated .eyes-open { opacity: 0; }
.petted .eyes-happy, .treated .eyes-happy, .petted .blush, .treated .blush { opacity: 1; }
.zzz { font-size: 13px; font-weight: 700; fill: #c9d4ff; }
.night .pet:not(.petted):not(.treated) .eyes-open { opacity: 0; }
.night .pet:not(.petted):not(.treated) .eyes-happy { opacity: 1; }
.night .pet:not(.petted):not(.treated) .zzz { animation: zzz 2.6s ease-in-out infinite; }
@keyframes zzz { 0% { opacity: 0; transform: translate(0, 6px); } 40% { opacity: 1; } 100% { opacity: 0; transform: translate(10px, -14px); } }

.cat-tail { transform-origin: 100% 95%; animation: tail-sway 3s ease-in-out infinite; }
@keyframes tail-sway { 50% { transform: rotate(14deg); } }
.cat-body, .dog-body { transform-origin: 50% 100%; animation: breathe 3.2s ease-in-out infinite; }
@keyframes breathe { 50% { transform: scale(1.015, 1.04); } }
.cat-head { transform-origin: 30% 80%; }
.cat.petted .cat-head { animation: nuzzle .55s ease-in-out 5; }
@keyframes nuzzle { 25% { transform: rotate(-8deg); } 75% { transform: rotate(6deg); } }
.cat.petted .cat-tail { animation: tail-sway .5s ease-in-out infinite; }
.cat.treated .cat-head { animation: munch .28s ease-in-out 7 .7s; }
@keyframes munch { 50% { transform: translateY(4px) rotate(4deg); } }

.dog-tail { transform-origin: 0% 100%; animation: wag 1.1s ease-in-out infinite; }
@keyframes wag { 50% { transform: rotate(-18deg); } }
.dog.petted .dog-tail, .dog.treated .dog-tail { animation-duration: .2s; }
.dog-head { transform-origin: 50% 90%; }
.dog.petted .dog-head { animation: tilt 1.4s ease-in-out 2; }
@keyframes tilt { 30%, 60% { transform: rotate(-10deg); } }
.ear-l, .ear-r { transform-origin: 50% 10%; }
.dog.petted .ear-l, .dog.treated .ear-l { animation: flap .3s ease-in-out 8; }
.dog.petted .ear-r, .dog.treated .ear-r { animation: flap .3s ease-in-out 8 reverse; }
@keyframes flap { 50% { transform: rotate(14deg); } }
.tongue { transform-box: fill-box; transform-origin: 50% 0%; transform: scaleY(0); transition: transform .25s; }
.dog.petted .tongue, .dog.treated .tongue { transform: scaleY(1); }
.dog-all { transform-origin: 50% 100%; }
.dog.treated .dog-all { animation: jump .45s ease-out 2; }
@keyframes jump { 40% { transform: translateY(-18px) scale(1, 1.04); } 80% { transform: translateY(0) scale(1.04, .96); } }
.treated .treat-item { animation: treat 2.6s ease-in forwards; }
@keyframes treat { 0% { opacity: 0; transform: translateY(-50px); } 15% { opacity: 1; transform: translateY(0); } 70% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(0); } }

.aquarium .lane, .aquarium .swim, .aquarium .fish { transform-box: view-box; transform-origin: 0 0; }
.lane { transform: translateY(var(--y)); transition: transform 1.2s ease-in-out; }
.aquarium.fed .lane { transform: translateY(30px); }
.swim { animation: swim linear infinite; }
@keyframes swim { 0% { transform: translateX(28px) scaleX(1); } 48% { transform: translateX(158px) scaleX(1); } 50% { transform: translateX(158px) scaleX(-1); } 98% { transform: translateX(28px) scaleX(-1); } 100% { transform: translateX(28px) scaleX(1); } }
.fish { animation: fish-bob 1.8s ease-in-out infinite; }
.aquarium.fed .fish { animation: fish-nibble .35s ease-in-out infinite; }
@keyframes fish-bob { 50% { transform: translateY(3px); } }
@keyframes fish-nibble { 50% { transform: translateY(-3px) rotate(-12deg); } }
.weed { transform-box: fill-box; transform-origin: 50% 100%; animation: weed 3.5s ease-in-out infinite; }
.weed.w2 { animation-delay: -1.2s; } .weed.w3 { animation-delay: -2.1s; }
@keyframes weed { 50% { transform: rotate(7deg); } }
.bubble { fill: rgba(255, 255, 255, .7); animation: bubble 3s ease-in infinite; }
@keyframes bubble { 0% { transform: translateY(0); opacity: 0; } 15% { opacity: 1; } 100% { transform: translateY(-78px); opacity: 0; } }
.aquarium.fed .bubble { animation-duration: 1.4s; }
.flake { fill: #c87533; opacity: 0; }
.aquarium.fed .flake { animation: sink 4.5s ease-in forwards; }
@keyframes sink { 0% { opacity: 1; transform: translate(0, 0); } 60% { opacity: 1; } 100% { opacity: 0; transform: translate(4px, 30px); } }
.tank-glow { opacity: 0; filter: blur(10px); transition: opacity .6s; }
.night .tank-glow { opacity: .45; }

.pet-menu { position: fixed; z-index: 45; transform: translate(-50%, -100%); display: flex; gap: 6px; padding: 6px; background: var(--card); border-radius: 999px; box-shadow: 0 8px 24px rgba(0, 0, 0, .25); animation: menu-in .2s ease-out; }
@keyframes menu-in { from { transform: translate(-50%, -80%) scale(.8); opacity: 0; } }
.pet-bubble { position: fixed; z-index: 44; transform: translate(-50%, -100%); background: #fff; color: #3d2c29; font-weight: 600; padding: 6px 14px; border-radius: 16px; box-shadow: 0 4px 12px rgba(0, 0, 0, .2); pointer-events: none; animation: bubble-pop 1.9s ease-out forwards; white-space: nowrap; }
.pet-bubble::after { content: ""; position: absolute; left: 50%; bottom: -7px; margin-left: -7px; border: 7px solid transparent; border-bottom: 0; border-top-color: #fff; }
@keyframes bubble-pop { 0% { transform: translate(-50%, -80%) scale(.4); opacity: 0; } 12% { transform: translate(-50%, -100%) scale(1.1); opacity: 1; } 20% { transform: translate(-50%, -100%) scale(1); } 80% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, -120%); } }
.pet-heart { position: fixed; z-index: 44; pointer-events: none; font-size: 20px; animation: heart-up 1.8s ease-out forwards; opacity: 0; }
@keyframes heart-up { 0% { opacity: 0; transform: translate(-50%, 0) scale(.5); } 20% { opacity: 1; } 100% { opacity: 0; transform: translate(calc(-50% + var(--dx)), -80px) scale(1.2); } }

.shelf-list { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 16px; }
.shelf-list button { display: inline-flex; align-items: center; gap: 6px; }
.shelf-list .ic { font-size: 20px; }

/* game shell */
.game-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.game-head h2 { margin: 0; font-size: 26px; color: var(--accent); }
.turn { padding: 6px 14px; border-radius: 999px; background: var(--surface); font-weight: 600; box-shadow: 0 0 0 1px var(--line) inset; }
.turn.mine { background: var(--ok); color: #fff; animation: pulse 1.6s infinite; box-shadow: none; }
.turn.won { background: #ffe08a; color: #3d2c29; }
@keyframes pulse { 50% { transform: scale(1.06); } }
.rules { margin-bottom: 14px; line-height: 1.5; }
.rules p { margin: .3em 0; }
.msg { color: var(--muted); min-height: 1.4em; text-align: center; margin: 10px 0; }
.toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; }
.toggle input { width: auto; }

.board-wrap { display: flex; gap: 18px; align-items: flex-start; justify-content: center; flex-wrap: wrap; }
.dice-panel { width: 230px; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.dice-panel .msg { margin: 0; color: var(--ink); }
.plist { list-style: none; padding: 0; margin: 0; width: 100%; font-size: 14px; }
.plist li { display: flex; align-items: center; gap: 8px; padding: 4px 0; }

/* dice */
.dice { width: 64px; height: 64px; perspective: 400px; margin: 10px; }
.dice[data-sl], .dice[data-lu] { cursor: pointer; }
.cube { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; }
.face { position: absolute; inset: 0; background: #fff; border-radius: 12px; border: 2px solid #e8dccb; display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr); padding: 7px; }
.face i { display: block; margin: auto; width: 68%; height: 68%; border-radius: 50%; }
.face i.pip { background: var(--ink); }
.f1 { transform: translateZ(32px); } .f6 { transform: rotateY(180deg) translateZ(32px); }
.f2 { transform: rotateY(90deg) translateZ(32px); } .f5 { transform: rotateY(-90deg) translateZ(32px); }
.f3 { transform: rotateX(90deg) translateZ(32px); } .f4 { transform: rotateX(-90deg) translateZ(32px); }
.dice.rolling { animation: hop .5s ease-in-out infinite; }
.dice.rolling .cube { animation: roll .55s linear infinite; }
.dice.landed { animation: land .4s ease-out; }
@keyframes roll { from { transform: rotateX(0) rotateY(0) rotateZ(0); } to { transform: rotateX(360deg) rotateY(720deg) rotateZ(360deg); } }
@keyframes hop { 50% { transform: translateY(-14px); } }
@keyframes land { 0% { transform: scale(1.25); } 60% { transform: scale(.92); } 100% { transform: scale(1); } }

/* UNO */
.uno-table { max-width: 860px; margin: 0 auto; }
.uno-opp { text-align: center; }
.uno-opp .who { color: var(--muted); margin-bottom: 6px; }
.opp-hand { display: flex; justify-content: center; padding-left: 40px; min-height: 80px; }
.opp-card { margin-left: -40px; transform: rotate(calc((var(--i) - 3) * 2deg)); }
.opp-card .uno-card { width: 52px; height: 78px; border-width: 3px; }
.opp-card .uno-card .oval b { font-size: 12px; }
.uno-center { display: flex; justify-content: center; align-items: center; gap: 28px; margin: 22px 0 6px; flex-wrap: wrap; }
.pile { padding: 0; background: none; box-shadow: none; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.pile:not(:disabled) .uno-card { box-shadow: 0 0 0 4px var(--ok), 0 6px 12px rgba(0, 0, 0, .2); }
.pile span { font-size: 13px; color: var(--muted); }
.cur-color { display: flex; align-items: center; gap: 8px; font-weight: 600; }
.swatch { width: 26px; height: 26px; border-radius: 50%; border: 3px solid #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .3); }
.c-r { background: var(--r); } .c-y { background: var(--y); } .c-g { background: var(--g); } .c-b { background: var(--b); } .c-w { background: #222; }
.uno-card { --w: 80px; width: var(--w); height: calc(var(--w) * 1.5); border-radius: 11px; border: 5px solid #fff; position: relative; box-shadow: 0 4px 10px rgba(0, 0, 0, .22); display: flex; align-items: center; justify-content: center; color: #fff; user-select: none; flex-shrink: 0; }
.uno-card .oval { width: 78%; height: 66%; background: #fff; border-radius: 50%; transform: rotate(28deg); display: flex; align-items: center; justify-content: center; position: relative; overflow: hidden; }
.uno-card .oval b { transform: rotate(-28deg); font-size: 30px; font-weight: 700; position: relative; }
.uno-card.c-r .oval b { color: var(--r); } .uno-card.c-y .oval b { color: #d9a400; } .uno-card.c-g .oval b { color: var(--g); } .uno-card.c-b .oval b { color: var(--b); }
.uno-card.c-w .oval { background: transparent; }
.uno-card.c-w .oval b { color: #fff; text-shadow: 0 1px 3px #000; }
.wheel { position: absolute; inset: 0; background: conic-gradient(var(--r) 0 25%, var(--b) 0 50%, var(--y) 0 75%, var(--g) 0); }
.uno-card .cn { position: absolute; font-size: 14px; font-weight: 700; text-shadow: 0 1px 2px rgba(0, 0, 0, .4); }
.uno-card .tl { top: 3px; left: 6px; } .uno-card .br { bottom: 3px; right: 6px; transform: rotate(180deg); }
.uno-card.back { background: #1d1d1d; }
.uno-card.back .oval { background: var(--r); }
.uno-card.back .oval b { color: var(--y); font-size: 20px; text-shadow: 2px 2px 0 #000; }
.discard { position: relative; }
.discard .uno-card { --w: 96px; }
.stack-badge { position: absolute; top: -12px; right: -16px; background: var(--ink); color: var(--y); font-weight: 700; font-size: 20px; padding: 4px 10px; border-radius: 999px; box-shadow: 0 0 0 3px #fff; animation: pop .45s cubic-bezier(.2, 1.4, .4, 1); }
.uno-card.pop { animation: pop .45s cubic-bezier(.2, 1.4, .4, 1); }
@keyframes pop { from { transform: translateY(80px) rotate(-25deg) scale(.6); opacity: .4; } }
.uno-actions { display: flex; justify-content: center; gap: 10px; margin-bottom: 8px; }
.uno-shout { background: var(--r); color: var(--y); font-weight: 700; letter-spacing: 1px; box-shadow: 0 3px 0 #8b1d1f; }
.my-hand { display: flex; justify-content: center; flex-wrap: wrap; padding: 26px 0 30px 22px; }
.my-hand .uno-card { margin-left: -22px; margin-bottom: 6px; cursor: pointer; transition: transform .15s; }
.my-hand .uno-card.ok { transform: translateY(-16px); box-shadow: 0 0 0 3px var(--ok), 0 8px 14px rgba(0, 0, 0, .25); }
.my-hand .uno-card:hover { transform: translateY(-24px); z-index: 2; }
.my-hand .uno-card.dim { filter: brightness(.82); }
.color-pick { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.color-pick button { color: #fff; padding: 1em; font-size: 18px; box-shadow: none; }

/* snakes and ladders */
.sl-board { position: relative; width: min(92vw, 600px); aspect-ratio: 1; display: grid; grid-template: repeat(10, 1fr) / repeat(10, 1fr); border-radius: 14px; overflow: hidden; box-shadow: var(--shadow); border: 5px solid #8b5a2b; }
.sl-cell { position: relative; border: 1px solid rgba(255, 255, 255, .55); }
.sl-cell span { position: absolute; top: 2px; left: 4px; font-size: clamp(8px, 1.6vw, 12px); color: rgba(61, 44, 41, .65); font-weight: 600; }
.sl-art { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.sl-tok { position: absolute; width: 5.6%; aspect-ratio: 1; border-radius: 50%; transform: translate(-50%, -50%); border: 3px solid #fff; box-shadow: 0 3px 6px rgba(0, 0, 0, .4); transition: left .55s ease-in-out, top .55s ease-in-out; z-index: 3; }
.sl-tok.p0 { background: var(--p0); } .sl-tok.p1 { background: var(--p1); }
.sl-tok.mini { position: static; width: 16px; height: 16px; transform: none; border-width: 2px; box-shadow: none; display: inline-block; }

/* connect 4 */
.c4-legend { display: flex; justify-content: center; gap: 18px; margin-bottom: 10px; }
.c4-legend span { display: inline-flex; align-items: center; gap: 6px; }
.c4-board { display: flex; gap: 6px; width: min(94vw, 560px); margin: 0 auto; padding: 10px; background: #2f6fd6; border-radius: 18px; box-shadow: 0 8px 0 #2457b0, var(--shadow); }
.c4-col { flex: 1; display: flex; flex-direction: column; gap: 6px; padding: 0; background: none; box-shadow: none; border-radius: 10px; position: relative; overflow: visible; }
.c4-col.can:hover { background: rgba(255, 255, 255, .15); }
.c4-col:not(.can) { cursor: default; }
.c4-ghost { display: none; }
.c4-cell { aspect-ratio: 1; border-radius: 50%; background: var(--wall); box-shadow: inset 0 4px 6px rgba(0, 0, 0, .25); position: relative; }
.c4-disc { position: absolute; inset: 4%; border-radius: 50%; box-shadow: inset 0 -5px 0 rgba(0, 0, 0, .2), inset 0 0 0 5px rgba(255, 255, 255, .2); }
.c4-disc.p0 { background: var(--r); } .c4-disc.p1 { background: var(--y); }
.c4-disc.mini { position: static; display: inline-block; width: 18px; height: 18px; box-shadow: none; }
.c4-disc.drop { animation: drop .45s cubic-bezier(.5, 0, .7, 1.3); }
@keyframes drop { from { transform: translateY(calc(var(--rows) * -112%)); } }
.c4-disc.win { animation: winpulse .8s infinite alternate; box-shadow: 0 0 0 4px #fff, 0 0 18px #fff; }
@keyframes winpulse { to { transform: scale(.85); } }

/* jenga */
.jg-legend { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; margin-bottom: 8px; font-size: 14px; }
.jg-legend span, .jg-edit label span { display: inline-flex; align-items: center; gap: 6px; }
.jg-legend i, .jg-edit i { width: 16px; height: 16px; border-radius: 4px; display: inline-block; border: 1px solid rgba(0, 0, 0, .15); }
.jg-stage { position: relative; height: 540px; border-radius: 22px; background: radial-gradient(ellipse 38% 12% at 50% 84%, #e6caa3 0 60%, transparent 62%), linear-gradient(var(--stage), var(--wall)); overflow: hidden; box-shadow: var(--shadow); }
.jg-scene { position: absolute; left: 50%; top: 52%; perspective: 1600px; }
.jg-world { transform-style: preserve-3d; position: absolute; }
.jg-floor { position: absolute; width: 300px; height: 300px; margin: -150px 0 0 -150px; transform: rotateX(90deg); background: radial-gradient(circle, rgba(120, 80, 40, .25), transparent 65%); }
.jb { position: absolute; transform-style: preserve-3d; }
.jf { position: absolute; left: 0; top: 0; background: var(--c); border: 1px solid rgba(110, 70, 30, .35); backface-visibility: hidden; }
.jf.top { filter: brightness(1.08); background-image: repeating-linear-gradient(90deg, rgba(255, 255, 255, .12) 0 3px, transparent 3px 9px); }
.jf.front { filter: brightness(.92); background-image: repeating-linear-gradient(90deg, rgba(120, 70, 20, .08) 0 2px, transparent 2px 7px); }
.jf.side { filter: brightness(.78); }
.jb.can { cursor: pointer; }
.jb.can:hover .jf { filter: brightness(1.2); outline: 2px solid #fff; }
.jb.ghost { animation: pullout .9s ease-in forwards; pointer-events: none; }
@keyframes pullout { to { transform: translate3d(var(--tx), var(--y), var(--tz)); opacity: 0; } }
.jb.landing { animation: landing .5s .5s ease-out backwards; }
@keyframes landing { from { transform: translate3d(var(--x), calc(var(--y) - 80px), var(--z)); opacity: 0; } }
.jb.falling { animation: fall 1.1s var(--fd) cubic-bezier(.5, 0, .9, .6) forwards; }
.jb.fallen { transform: translate3d(var(--fx), var(--fy), var(--fz)) rotateY(var(--ry)) rotateZ(var(--rz)) !important; }
@keyframes fall { to { transform: translate3d(var(--fx), var(--fy), var(--fz)) rotateY(var(--ry)) rotateZ(var(--rz)); } }
.jg-card { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(86%, 380px); background: var(--surface); border-radius: 22px; padding: 22px; text-align: center; box-shadow: 0 0 0 8px var(--c, #ddd), 0 20px 40px rgba(0, 0, 0, .25); animation: cardin .45s cubic-bezier(.2, 1.4, .4, 1); z-index: 5; }
.jg-card.fall { --c: #f2a28f; }
@keyframes cardin { from { transform: translate(-50%, -30%) scale(.6) rotate(-6deg); opacity: 0; } }
.jg-cat { display: inline-block; background: var(--c); padding: 4px 14px; border-radius: 999px; font-weight: 600; }
.jg-q { font-size: 22px; font-weight: 500; margin: 16px 0 6px; }
.jg-edit label { display: block; margin-bottom: 10px; }
.jg-edit textarea { margin-top: 4px; font-size: 14px; }

/* ludo */
.lboard { position: relative; width: min(92vw, 580px); aspect-ratio: 1; background: #fff; border-radius: 14px; box-shadow: var(--shadow); border: 4px solid var(--ink); overflow: hidden; }
.lc { position: absolute; width: calc(100% / 15); height: calc(100% / 15); border: 1px solid #d9cbb8; display: flex; align-items: center; justify-content: center; font-size: clamp(9px, 2.4vw, 16px); color: #c7a64d; }
.lc.start { color: #fff; }
.lbase { position: absolute; width: 40%; height: 40%; }
.lbase.unused { filter: saturate(.35) brightness(1.1); }
.lbase-in { position: absolute; inset: 16.67%; background: #fff; border-radius: 16px; }
.lbase-in i { position: absolute; width: 30%; height: 30%; border-radius: 50%; transform: translate(-50%, -50%); opacity: .35; }
.lcenter { position: absolute; width: 20%; height: 20%; }
.ltok { position: absolute; width: 5.4%; aspect-ratio: 1; transform: translate(-50%, -50%); border-radius: 50%; background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, .8) 0 18%, var(--c) 45%); border: 3px solid #fff; box-shadow: 0 3px 5px rgba(0, 0, 0, .4); transition: left .5s ease-in-out, top .5s ease-in-out; z-index: 2; }
.ltok.can { cursor: pointer; z-index: 4; animation: bob .7s ease-in-out infinite; box-shadow: 0 0 0 3px var(--ink), 0 4px 10px rgba(0, 0, 0, .5); }
@keyframes bob { 50% { transform: translate(-50%, -75%); } }
.ltok-mini { width: 16px; height: 16px; border-radius: 50%; background: var(--c); display: inline-block; }

/* rummikub */
.rk-opp { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.rk-backs { display: flex; }
.rk-backs i { width: 14px; height: 22px; margin-left: -6px; background: #f0e2c4; border: 1px solid #c9b48b; border-radius: 3px; }
.rk-table { min-height: 200px; display: flex; flex-wrap: wrap; gap: 14px; align-content: flex-start; background: #2f7d5b; background-image: radial-gradient(rgba(255, 255, 255, .06) 1px, transparent 1px); background-size: 8px 8px; }
.rk-group { display: flex; gap: 3px; padding: 6px; border-radius: 10px; background: rgba(255, 255, 255, .12); border: 2px solid transparent; }
.rk-group.bad { border-color: #ffd37a; border-style: dashed; }
.rk-group.target, .rk-new.target, .rk-rack.target { cursor: copy; }
.rk-group.target:hover { background: rgba(255, 255, 255, .28); }
.rk-new { min-width: 140px; min-height: 64px; display: flex; align-items: center; justify-content: center; text-align: center; padding: 8px 12px; border: 2px dashed rgba(255, 255, 255, .5); border-radius: 10px; color: rgba(255, 255, 255, .85); font-size: 14px; }
.rk-new.target:hover { background: rgba(255, 255, 255, .15); }
.rk-tile { width: 40px; height: 56px; background: linear-gradient(#fffaf0, #f3e7cf); border-radius: 7px; box-shadow: 0 3px 0 #c9b48b, 0 4px 6px rgba(0, 0, 0, .25); display: flex; flex-direction: column; align-items: center; justify-content: center; user-select: none; position: relative; cursor: pointer; transition: transform .12s; }
.rk-tile b { font-size: 24px; font-weight: 700; line-height: 1; }
.rk-tile i { width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: .35; margin-top: 5px; }
.rk-tile.new { box-shadow: 0 3px 0 #c9b48b, 0 0 0 3px #ffd37a; }
.rk-tile.sel { transform: translateY(-8px); box-shadow: 0 3px 0 #c9b48b, 0 0 0 3px var(--accent), 0 10px 14px rgba(0, 0, 0, .3); }
.rk-rack { display: flex; flex-wrap: wrap; gap: 6px; padding: 14px; min-height: 86px; border-radius: 14px; background: linear-gradient(#c98b55, #a86d3c); box-shadow: inset 0 -6px 0 rgba(0, 0, 0, .15), var(--shadow); }
.rk-buttons { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }

/* whiteboard */
.wb-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; padding: 10px 14px; }
.swatches, .sizes { display: flex; gap: 6px; flex-wrap: wrap; }
.sw { width: 30px; height: 30px; padding: 0; border-radius: 50%; box-shadow: 0 0 0 1px rgba(0, 0, 0, .2) inset; }
.sw.on { box-shadow: 0 0 0 3px #fff, 0 0 0 5px var(--ink); }
.sz { width: 40px; height: 40px; padding: 0; display: flex; align-items: center; justify-content: center; }
.sz i { background: currentColor; border-radius: 50%; display: block; }
.wb-wrap { background: #fff; background-image: radial-gradient(#e6dccd 1.2px, transparent 1.2px); background-size: 24px 24px; border-radius: 16px; box-shadow: var(--shadow); overflow: hidden; border: 8px solid #b97a47; }
.wb-wrap canvas { display: block; width: 100%; height: auto; touch-action: none; cursor: crosshair; }

/* waiting, modal, toast, effects */
.waiting { max-width: 420px; margin: 60px auto; text-align: center; }
.spinner { width: 46px; height: 46px; margin: 10px auto; border-radius: 50%; border: 5px solid var(--line); border-top-color: var(--accent); animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
#modal { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; padding: 16px; }
#modal[hidden] { display: none; }
.modal-back { position: absolute; inset: 0; background: rgba(61, 44, 41, .45); }
.modal-card { position: relative; background: var(--card); border-radius: 22px; padding: 22px; width: min(100%, 460px); max-height: 90vh; overflow: auto; box-shadow: 0 20px 50px rgba(0, 0, 0, .3); }
.modal-card h3 { margin: 0 0 8px; color: var(--accent); font-size: 22px; }
.modal-card label { display: block; font-weight: 500; }
.modal-card hr { border: 0; border-top: 1px solid var(--line); margin: 18px 0; }
.row { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; flex-wrap: wrap; }
#toast { position: fixed; left: 50%; bottom: 22px; transform: translate(-50%, 40px); background: var(--ink); color: var(--on-ink); padding: 10px 18px; border-radius: 999px; opacity: 0; transition: .25s; z-index: 60; pointer-events: none; max-width: calc(100vw - 32px); text-align: center; }
#toast.show { opacity: 1; transform: translate(-50%, 0); }
#fx { position: fixed; inset: 0; pointer-events: none; z-index: 40; overflow: hidden; }
.floaty { position: absolute; bottom: -60px; animation: floatup 3s ease-out forwards; }
@keyframes floatup { to { transform: translateY(-85vh) rotate(20deg); opacity: 0; } }
.shout { position: absolute; left: 50%; top: 40%; transform: translate(-50%, -50%); font-size: clamp(60px, 16vw, 150px); font-weight: 700; color: var(--y); -webkit-text-stroke: 4px var(--r); text-shadow: 6px 6px 0 #1d1d1d; animation: shout 1.8s ease-out forwards; }
@keyframes shout { 0% { transform: translate(-50%, -50%) scale(.2) rotate(-20deg); } 25% { transform: translate(-50%, -50%) scale(1.15) rotate(-6deg); } 80% { opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1) rotate(-6deg); opacity: 0; } }
.confetti { position: absolute; top: -20px; width: 10px; height: 16px; border-radius: 2px; animation: confetti linear forwards; }
@keyframes confetti { to { transform: translate(var(--dx), 105vh) rotate(720deg); } }

@media (max-width: 640px) {
  main { padding: 12px; }
  #bar { padding: 6px 12px; }
  .status { width: 100%; order: 10; }
  .reacts button { font-size: 18px; }
  .game-head h2 { font-size: 21px; }
  .dice-panel { width: 100%; flex-direction: row; flex-wrap: wrap; justify-content: center; }
  .dice-panel .msg { width: 100%; }
  .uno-card { --w: 62px; }
  .discard .uno-card { --w: 78px; }
  .my-hand { padding-left: 24px; }
  .my-hand .uno-card { margin-left: -24px; }
  .jg-stage { height: 440px; }
  .rk-tile { width: 32px; height: 46px; }
  .rk-tile b { font-size: 19px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}
