/* ============================================================
   Ludo — classic board, card-table presentation
   Palette: felt table, walnut frame, ivory board, 4 game colours
   ============================================================ */

:root {
  --felt:        #1d4635;
  --felt-dark:   #14312555;
  --wood:        #7a4b26;
  --wood-dark:   #5a3419;
  --wood-light:  #a06a3c;
  --board:       #fbf7ee;
  --ink:         #16130f;
  --ink-soft:    #4a4238;

  --red:    #dd2b1c;
  --green:  #158c43;
  --yellow: #f0b90f;
  --blue:   #1450c4;

  --red-dim:    #f2c9c5;
  --green-dim:  #c3e4cf;
  --yellow-dim: #f8e6ad;
  --blue-dim:   #c6d5f2;

  --cell: calc(100% / 15);
  --radius: 14px;
  --shadow-lift: 0 18px 40px -18px rgba(0,0,0,.65);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  font-family: "Outfit", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  color: #f4efe6;
  background:
    radial-gradient(ellipse at 50% 0%, #2a5c46 0%, var(--felt) 45%, #12291f 100%),
    var(--felt);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

/* subtle felt texture */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  opacity: .30;
  background-image:
    repeating-linear-gradient(45deg,  rgba(255,255,255,.035) 0 2px, transparent 2px 4px),
    repeating-linear-gradient(-45deg, rgba(0,0,0,.05) 0 2px, transparent 2px 4px);
}

h1, h2, h3, .display {
  font-family: "Alfa Slab One", Georgia, serif;
  font-weight: 400;
  letter-spacing: .01em;
  line-height: 1.05;
  margin: 0;
}

a { color: inherit; }

/* ---------------------------------------------------------- shell */

.shell {
  position: relative;
  z-index: 1;
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(16px, 3vw, 36px);
}

/* ---------------------------------------------------------- menu */

.menu-wrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}

.menu {
  width: min(560px, 100%);
}

.brand {
  text-align: center;
  margin-bottom: 26px;
}

.brand .eyebrow {
  font-family: "Alfa Slab One", Georgia, serif;
  font-size: clamp(17px, 3.6vw, 26px);
  color: #dfeee4;
  letter-spacing: .22em;
  margin-bottom: 2px;
  text-shadow: 0 2px 0 rgba(0,0,0,.35);
}

.brand .logo {
  font-family: "Alfa Slab One", Georgia, serif;
  font-size: clamp(54px, 13vw, 104px);
  line-height: .92;
  color: var(--board);
  text-shadow:
    0 2px 0 var(--wood-dark),
    0 8px 0 rgba(0,0,0,.25),
    0 22px 38px rgba(0,0,0,.5);
  display: flex;
  justify-content: center;
  gap: .04em;
}
.brand .logo span:nth-child(1) { color: var(--red); }
.brand .logo span:nth-child(2) { color: var(--green); }
.brand .logo span:nth-child(3) { color: var(--yellow); }
.brand .logo span:nth-child(4) { color: var(--blue); }

.brand .by {
  margin: 14px 0 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .13em;
  color: #a8ccb7;
}
.brand .by b { color: var(--board); font-weight: 800; }

.brand .tagline {
  margin: 12px 0 0;
  color: #cfe3d6;
  font-size: 16px;
}

.card {
  background: linear-gradient(180deg, #fffdf8, #f3ece0);
  color: var(--ink);
  border-radius: var(--radius);
  padding: clamp(18px, 3vw, 28px);
  box-shadow: var(--shadow-lift), inset 0 1px 0 #fff;
  border: 1px solid #00000018;
}

.card + .card { margin-top: 18px; }

.card h2 {
  font-size: 22px;
  margin-bottom: 4px;
}

.card .hint {
  color: var(--ink-soft);
  font-size: 14px;
  margin: 0 0 16px;
}

label.field {
  display: block;
  margin-bottom: 14px;
}
label.field > span {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: 6px;
}

input[type="text"] {
  width: 100%;
  font: inherit;
  font-size: 16px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1.5px solid #00000022;
  background: #fff;
  color: var(--ink);
}
input[type="text"]:focus {
  outline: 3px solid #1450c455;
  border-color: var(--blue);
}
input.code {
  text-transform: uppercase;
  letter-spacing: .22em;
  font-weight: 700;
}

/* colour picker */

.swatches {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

/* The pawn already carries the colour, so the tile behind it stays neutral. */
.swatch {
  --c: #999;
  position: relative;
  padding: 12px 6px 9px;
  border-radius: 12px;
  border: 2px solid #00000018;
  background: #fff;
  cursor: pointer;
  display: grid;
  justify-items: center;
  gap: 6px;
  box-shadow: 0 2px 5px rgba(0,0,0,.07);
  transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
  font: inherit;
}

.swatch img {
  width: 34px;
  height: 46px;
  object-fit: contain;
  transition: transform .14s ease;
  filter: drop-shadow(0 2px 2px rgba(0,0,0,.22));
}

.swatch .nm {
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-soft);
  letter-spacing: .01em;
}

.swatch:hover:not(:disabled) {
  border-color: #00000035;
  transform: translateY(-2px);
}
.swatch:hover:not(:disabled) img { transform: translateY(-2px) scale(1.04); }
.swatch:focus-visible { outline: 3px solid var(--c); outline-offset: 2px; }

/* Selected: a ring in the pawn's own colour, plus a tick. */
.swatch[aria-pressed="true"] {
  border-color: var(--c);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--c) 22%, transparent), 0 5px 12px rgba(0,0,0,.14);
}
.swatch[aria-pressed="true"] .nm { color: var(--c); }
.swatch[aria-pressed="true"]::after {
  content: "✓";
  position: absolute;
  top: -8px;
  right: -8px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--c);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  display: grid;
  place-items: center;
  box-shadow: 0 2px 5px rgba(0,0,0,.3);
  border: 2px solid #fff;
}

/* Taken by someone else. */
.swatch:disabled {
  cursor: not-allowed;
  background: #00000009;
  border-style: dashed;
  box-shadow: none;
}
.swatch:disabled img { filter: grayscale(1); opacity: .35; }
.swatch:disabled .nm { color: #00000055; }
.swatch:disabled .nm::after { content: " · taken"; font-weight: 600; }

.swatch.red    { --c: var(--red); }
.swatch.green  { --c: var(--green); }
.swatch.yellow { --c: #c79400; }
.swatch.blue   { --c: var(--blue); }

/* buttons */

.btn {
  font: inherit;
  font-weight: 700;
  font-size: 16px;
  border: 0;
  border-radius: 12px;
  padding: 14px 20px;
  cursor: pointer;
  color: #fff;
  background: var(--ink);
  box-shadow: 0 5px 0 #00000055, 0 12px 22px -10px rgba(0,0,0,.7);
  transition: transform .1s ease, box-shadow .1s ease, filter .12s ease;
  width: 100%;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}
/* Big tap target for thumbs — the reported phone issue was a button
   that felt dead because taps landed just off it after double-tap-zoom. */
#roll-btn { min-height: 52px; }
#fee-slider { min-height: 34px; }
#dice-stage { cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.btn:hover:not(:disabled) { filter: brightness(1.08); }
.btn:active:not(:disabled) { transform: translateY(4px); box-shadow: 0 1px 0 #00000055; }
.btn:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

.btn.primary { background: linear-gradient(180deg, #e8463a, var(--red)); }
.btn.go      { background: linear-gradient(180deg, #1ea955, var(--green)); }
.btn.ghost {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 2px #00000030;
}

/* Segmented control for the player count. */
.seg { display: flex; gap: 8px; }
.seg .opt {
  flex: 1;
  position: relative;
  font: inherit;
  font-weight: 700;
  font-size: 15px;
  padding: 12px 8px 10px;
  border-radius: 11px;
  border: 2px solid #00000018;
  background: #fff;
  color: var(--ink-soft);
  cursor: pointer;
  display: grid;
  justify-items: center;
  gap: 2px;
  transition: border-color .12s ease, background .12s ease, transform .1s ease;
}
.seg .opt .n { font-size: 20px; font-family: "Alfa Slab One", serif; line-height: 1; }
.seg .opt .lbl { font-size: 11px; font-weight: 600; }
.seg .opt:hover { border-color: #00000035; transform: translateY(-1px); }
.seg .opt:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
.seg .opt[aria-pressed="true"] {
  border-color: var(--ink);
  background: var(--ink);
  color: #fff;
}
.seg .opt[aria-pressed="true"] .lbl { color: #ffffffbb; }

.row { display: flex; gap: 12px; }
.row > * { flex: 1; }

.divider {
  display: flex;
  align-items: center;
  gap: 12px;
  color: #cfe3d6;
  font-size: 13px;
  margin: 18px 0;
}
.divider::before, .divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: #ffffff33;
}

.msg {
  margin-top: 12px;
  font-size: 14px;
  padding: 10px 12px;
  border-radius: 10px;
  display: none;
}
.msg.show { display: block; }
.msg.error { background: #fde3e0; color: #8c1d12; border: 1px solid #dd2b1c55; }
.msg.info  { background: #e2eefb; color: #123a80; border: 1px solid #1450c455; }

/* ---------------------------------------------------------- game layout */

.game-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 330px;
  gap: clamp(16px, 2.5vw, 28px);
  align-items: start;
}

@media (max-width: 940px) {
  .game-layout { grid-template-columns: minmax(0, 1fr); }
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}
.topbar .mark {
  display: grid;
  gap: 1px;
  line-height: 1.05;
}
.topbar .mark-title {
  font-family: "Alfa Slab One", Georgia, serif;
  font-size: 24px;
  color: #dfeee4;
}
.topbar .mark-title b { color: var(--board); font-weight: 400; }
.topbar .mark-by {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .15em;
  color: #8fbda2;
}
.roomcode {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #00000035;
  border: 1px solid #ffffff22;
  border-radius: 999px;
  padding: 7px 8px 7px 16px;
  font-size: 14px;
  flex-wrap: wrap;
  max-width: 100%;
}
.roomcode b { letter-spacing: .2em; font-size: 16px; }
.roomcode button {
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  border: 0;
  border-radius: 999px;
  padding: 7px 13px;
  cursor: pointer;
  background: var(--board);
  color: var(--ink);
}

.roomcode button.leave {
  background: transparent;
  color: #ffd9d5;
  box-shadow: inset 0 0 0 1.5px #ffffff33;
}
.roomcode button.leave:hover { background: #dd2b1c22; }
.roomcode button.leave.armed { background: #dd2b1c; color: #fff; box-shadow: none; }

.spectating-badge {
  font-size: 13px;
  font-weight: 700;
  padding: 7px 13px;
  border-radius: 999px;
  background: #ffffff18;
  color: #dfeee4;
}

/* turn countdown */
.turn-timer {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: -4px 0 14px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-soft);
}
.turn-timer-ring {
  width: 30px;
  height: 30px;
  transform: rotate(-90deg);
  flex: none;
}
.turn-timer-ring .track {
  fill: none;
  stroke: #00000014;
  stroke-width: 3;
}
.turn-timer-ring .bar {
  fill: none;
  stroke: var(--green);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 97.4;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1s linear, stroke .2s ease;
}
.turn-timer.warn .bar { stroke: #d98a12; }
.turn-timer.danger .bar { stroke: var(--red); }
.turn-timer.danger #timer-num { color: var(--red); }

.board-frame {
  position: relative;
  background: linear-gradient(145deg, var(--wood-light), var(--wood) 35%, var(--wood-dark));
  padding: clamp(10px, 1.8vw, 20px);
  border-radius: 18px;
  box-shadow:
    var(--shadow-lift),
    inset 0 2px 0 #ffffff40,
    inset 0 -3px 0 #00000055;
}

.board {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: var(--board);
  border-radius: 6px;
  overflow: visible;
  display: grid;
  grid-template-columns: repeat(15, 1fr);
  grid-template-rows: repeat(15, 1fr);
  box-shadow: inset 0 0 0 2px var(--ink);
}

/* Pawns sit above every board layer so edge pieces are never swallowed. */
.pieces { position: absolute; inset: 0; z-index: 20; pointer-events: none; }

/* base cells */
.cell {
  position: relative;
  border: 1px solid #00000022;
}
.cell.track   { background: var(--board); border-color: #0000004d; }
.cell.void    { border: 0; }

.cell.home-red    { background: var(--red); }
.cell.home-green  { background: var(--green); }
.cell.home-yellow { background: var(--yellow); }
.cell.home-blue   { background: var(--blue); }

.cell.start-red    { background: var(--red); }
.cell.start-green  { background: var(--green); }
.cell.start-yellow { background: var(--yellow); }
.cell.start-blue   { background: var(--blue); }

/* safe star */
.cell.safe::after {
  content: "★";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: clamp(9px, 1.5vw, 17px);
  color: #00000055;
  line-height: 1;
}
.cell.start-red::after,
.cell.start-green::after,
.cell.start-yellow::after,
.cell.start-blue::after { color: #ffffffcc; }

/* yards */
.yard {
  position: absolute;
  width: calc(var(--cell) * 6);
  height: calc(var(--cell) * 6);
  padding: 4%;
  display: grid;
  place-items: center;
  z-index: 2;
}
.yard-red    { left: 0;    top: 0;    background: var(--red); }
.yard-green  { right: 0;   top: 0;    background: var(--green); }
.yard-yellow { right: 0;   bottom: 0; background: var(--yellow); }
.yard-blue   { left: 0;    bottom: 0; background: var(--blue); }

/* 75% of the 6x6 yard, centred: the four quadrant centres land exactly at
   12.5% and 27.5% of the board, which is what the piece placement uses. */
.yard-inner {
  width: 75%;
  height: 75%;
  background: var(--board);
  border: 2px solid var(--ink);
  border-radius: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  place-items: center;
  gap: 0;
  padding: 0;
}

/* Printed resting circles. A pawn in the yard is centred on one of these,
   so the four pawns always sit in the same four places. */
.slot {
  --ring: #00000040;
  width: 62%;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 3px solid var(--ring);
  background: #fff;
  box-shadow: inset 0 2px 5px rgba(0,0,0,.14);
  position: relative;
}
.slot::after {
  content: "";
  position: absolute;
  inset: 16%;
  border-radius: 50%;
  border: 1.5px dashed color-mix(in srgb, var(--ring) 55%, transparent);
}
.yard-red    .slot { --ring: var(--red); }
.yard-green  .slot { --ring: var(--green); }
.yard-yellow .slot { --ring: #c79400; }
.yard-blue   .slot { --ring: var(--blue); }

/* centre home triangle */
.centre {
  position: absolute;
  left: calc(var(--cell) * 6);
  top: calc(var(--cell) * 6);
  width: calc(var(--cell) * 3);
  height: calc(var(--cell) * 3);
  z-index: 3;
  background: var(--board);
  border: 2px solid var(--ink);
}
.centre .tri { position: absolute; inset: 0; }
.centre .tri i {
  position: absolute;
  inset: 0;
  display: block;
}
.tri-top    { background: var(--green);  clip-path: polygon(0 0, 100% 0, 50% 50%); }
.tri-right  { background: var(--yellow); clip-path: polygon(100% 0, 100% 100%, 50% 50%); }
.tri-bottom { background: var(--blue);   clip-path: polygon(100% 100%, 0 100%, 50% 50%); }
.tri-left   { background: var(--red);    clip-path: polygon(0 100%, 0 0, 50% 50%); }

/* ---------------------------------------------------------- pieces */

/* Above every board layer so edge pucks are never swallowed by the board. */
.pieces { position: absolute; inset: 0; z-index: 20; pointer-events: none; }

.piece {
  position: absolute;
  width: calc(var(--cell) * 0.92);
  height: calc(var(--cell) * 0.92);
  /* The pawn artwork is a peg shape whose visual base sits ~88% down the
     image, not at the image's vertical centre — so the anchor that lands
     it exactly on a target point is -50%/-88%, not -50%/-50%. Every place
     a piece appears (track, home stretch, yard slot) uses this same
     anchor, so "the pawn's foot is at (left, top)" is true everywhere. */
  transform: translate(-50%, -88%);
  pointer-events: auto;
  cursor: default;
  transition: left .28s cubic-bezier(.34,1.3,.5,1), top .28s cubic-bezier(.34,1.3,.5,1);
  filter: drop-shadow(0 3px 2px rgba(0,0,0,.45));
  border: 0;
  background: transparent;
  padding: 0;
  z-index: 1;
}
.piece img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* Resting pawns are drawn a touch larger and sit centred in their printed
   yard circle. Track pieces anchor by the foot (-88%), but a yard pawn must
   be centred (-50%/-50%) or it floats above its circle. */
.piece.in-yard {
  width: calc(var(--cell) * 1.02);
  height: calc(var(--cell) * 1.02);
  transform: translate(-50%, -50%);
}
.piece.in-yard.movable:hover { transform: translate(-50%, -50%) scale(1.05); }
.piece.in-yard.just-moved { animation: pop-yard .4s ease; }
@keyframes pop-yard {
  0%   { transform: translate(-50%,-50%) scale(1); }
  45%  { transform: translate(-50%,-56%) scale(1.16); }
  100% { transform: translate(-50%,-50%) scale(1); }
}

.piece.stack-2 { width: calc(var(--cell) * 0.80); height: calc(var(--cell) * 0.80); }

.piece.movable {
  cursor: pointer;
  z-index: 3;
}
/* Movable pieces get a pulsing ring at their base rather than an animated
   bob — a pawn that drifts is hard to read against its square. */
.piece.movable::after {
  content: "";
  position: absolute;
  left: 47%;
  bottom: -22%;
  width: 94%;
  height: 66%;
  transform: translateX(-50%);
  border-radius: 50%;
  border: 3px solid #fff;
  box-shadow: 0 0 0 2px #00000066, 0 0 13px #ffffffcc;
  animation: pulse 1.15s ease-in-out infinite;
  pointer-events: none;
  z-index: -1;
}
.piece.movable:hover { transform: translate(-50%, -94%) scale(1.05); }
.piece.just-moved { animation: pop .4s ease; }

@keyframes pulse {
  0%,100% { opacity: .4; }
  50%     { opacity: 1; }
}
@keyframes pop {
  0%   { transform: translate(-50%,-88%) scale(1); }
  45%  { transform: translate(-50%,-102%) scale(1.16); }
  100% { transform: translate(-50%,-88%) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .piece, .piece.movable, .piece.just-moved { animation: none !important; transition: none; }
}

/* ---------------------------------------------------------- side panel */

.panel {
  background: linear-gradient(180deg, #fffdf8, #f2ebdf);
  color: var(--ink);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--shadow-lift), inset 0 1px 0 #fff;
  border: 1px solid #00000018;
}
.panel + .panel { margin-top: 16px; }

.panel h3 {
  font-size: 16px;
  margin-bottom: 12px;
  font-family: "Outfit", sans-serif;
  font-weight: 800;
  color: var(--ink-soft);
}
.spectator-count {
  font-weight: 600;
  font-size: 12px;
  color: #00000066;
  text-transform: none;
}

.turn-banner {
  border-radius: 12px;
  padding: 12px 14px;
  font-weight: 700;
  font-size: 15px;
  color: #fff;
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  background: var(--ink-soft);
}
.turn-banner.red    { background: var(--red); }
.turn-banner.green  { background: var(--green); }
.turn-banner.yellow { background: var(--yellow); color: var(--ink); }
.turn-banner.blue   { background: var(--blue); }
.turn-banner .dot {
  width: 11px; height: 11px; border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 3px #ffffff55;
  animation: pulse 1.2s ease-in-out infinite;
}

/* player list */
.players { display: grid; gap: 8px; }
.player {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: 10px;
  background: #00000008;
  border: 2px solid transparent;
  font-size: 14px;
}
.player.active { border-color: var(--ink); background: #00000012; }
.player .chip {
  width: 22px; height: 22px; border-radius: 6px; flex: none;
  box-shadow: inset 0 -3px 0 rgba(0,0,0,.25);
}
.player .chip.red { background: var(--red); }
.player .chip.green { background: var(--green); }
.player .chip.yellow { background: var(--yellow); }
.player .chip.blue { background: var(--blue); }
.player .nm { font-weight: 700; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.player .meta { font-size: 12px; color: var(--ink-soft); font-weight: 600; flex: none; white-space: nowrap; }
.player.you .nm::after {
  content: "you";
  font-size: 10px;
  font-weight: 800;
  background: var(--ink);
  color: #fff;
  padding: 2px 6px;
  border-radius: 999px;
  margin-left: 7px;
  vertical-align: middle;
}
.player.left { opacity: .5; }
.player.left .chip { filter: grayscale(1); }

/* ---------------------------------------------------------- 3D dice */

.dice-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.dice-stage {
  width: 104px;
  height: 104px;
  perspective: 520px;
  display: grid;
  place-items: center;
  position: relative;
}

/* The cube tumbles while rolling, then hands over to a flat face so the
   result is never ambiguous. */
.dice-3d, .dice-flat {
  grid-area: 1 / 1;
  transition: opacity .18s ease;
}
.dice-3d  { opacity: 0; }
.dice-flat { opacity: 1; }
.dice-stage.rolling .dice-3d  { opacity: 1; }
.dice-stage.rolling .dice-flat { opacity: 0; }

.dice {
  position: relative;
  width: 64px;
  height: 64px;
  transform-style: preserve-3d;
  transform: rotateX(-24deg) rotateY(-32deg);
}
.dice.rolling { animation: tumble 1s cubic-bezier(.3,.7,.3,1); }

/* The settled, unmistakable result. */
.dice-flat {
  width: 76px;
  height: 76px;
  border-radius: 15px;
  background: linear-gradient(150deg, #fffdf6, #ece3d2);
  border: 1px solid #00000028;
  box-shadow:
    inset 0 2px 0 #fff,
    inset 0 -4px 8px #00000018,
    0 7px 16px -6px rgba(0,0,0,.55);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  padding: 11px;
  gap: 2px;
}
.dice-flat .pip {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #4a4238, #16130f);
  align-self: center;
  justify-self: center;
  box-shadow: inset 0 -1px 1px #ffffff40;
}
.dice-flat.landed { animation: land .38s cubic-bezier(.2,1.6,.4,1); }
/* Blank face before the first roll — tap to roll. */
.dice-flat.blank { cursor: pointer; background: linear-gradient(150deg, #fffdf6, #ece3d2); }
.dice-flat.blank::after {
  content: "";
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #00000022;
  grid-column: 2;
  grid-row: 2;
  align-self: center;
  justify-self: center;
  animation: pulse 1.6s ease-in-out infinite;
}
@keyframes land {
  0%   { transform: scale(.72) rotate(-9deg); }
  60%  { transform: scale(1.09) rotate(2deg); }
  100% { transform: scale(1) rotate(0); }
}

@media (prefers-reduced-motion: reduce) {
  .dice.rolling, .dice-flat.landed { animation: none; }
}

@keyframes tumble {
  0%   { transform: rotateX(-24deg) rotateY(-32deg); }
  25%  { transform: rotateX(340deg) rotateY(280deg) translateY(-26px) scale(1.1); }
  50%  { transform: rotateX(700deg) rotateY(560deg) translateY(-8px) scale(1.05); }
  75%  { transform: rotateX(1040deg) rotateY(880deg) translateY(-18px); }
  100% { transform: rotateX(-24deg) rotateY(-32deg); }
}

.face {
  position: absolute;
  width: 64px;
  height: 64px;
  background: linear-gradient(150deg, #fffdf6, #e9e0cf);
  border-radius: 12px;
  border: 1px solid #00000025;
  box-shadow: inset 0 0 12px #0000001a;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  padding: 9px;
  gap: 2px;
}
.face .pip {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #4a4238, #16130f);
  align-self: center;
  justify-self: center;
  box-shadow: inset 0 -1px 1px #ffffff40;
}
.face.f1 { transform: translateZ(32px); }
.face.f6 { transform: rotateY(180deg) translateZ(32px); }
.face.f2 { transform: rotateY(90deg) translateZ(32px); }
.face.f5 { transform: rotateY(-90deg) translateZ(32px); }
.face.f3 { transform: rotateX(90deg) translateZ(32px); }
.face.f4 { transform: rotateX(-90deg) translateZ(32px); }

/* pip placements on a 3x3 grid */
.p-tl { grid-area: 1 / 1; } .p-tc { grid-area: 1 / 2; } .p-tr { grid-area: 1 / 3; }
.p-ml { grid-area: 2 / 1; } .p-mc { grid-area: 2 / 2; } .p-mr { grid-area: 2 / 3; }
.p-bl { grid-area: 3 / 1; } .p-bc { grid-area: 3 / 2; } .p-br { grid-area: 3 / 3; }

.dice-hint {
  font-size: 13px;
  color: var(--ink-soft);
  text-align: center;
  min-height: 19px;
  font-weight: 600;
}

/* ---------------------------------------------------------- log */

.log {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 5px;
  max-height: 170px;
  overflow-y: auto;
  font-size: 13px;
  color: var(--ink-soft);
}
.log li {
  padding: 6px 9px;
  background: #00000008;
  border-radius: 7px;
  border-left: 3px solid #00000020;
}

/* ---------------------------------------------------------- lobby / overlay */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(8, 24, 18, .82);
  backdrop-filter: blur(6px);
  display: grid;
  place-items: center;
  padding: 22px;
}
.overlay[hidden] { display: none; }
.overlay .card { width: min(480px, 100%); }

.waiting-dots::after {
  content: "";
  animation: dots 1.4s steps(4, end) infinite;
}
@keyframes dots {
  0% { content: ""; } 25% { content: "."; } 50% { content: ".."; } 75% { content: "..."; }
}

.seatlist { display: grid; gap: 9px; margin: 14px 0 4px; }
.seat {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 13px;
  border-radius: 10px;
  background: #00000008;
  border: 2px dashed #00000025;
  font-size: 14px;
  font-weight: 600;
}
.seat.filled { border-style: solid; border-color: #00000030; background: #00000012; }
.seat .chip { width: 22px; height: 22px; border-radius: 6px; flex: none; box-shadow: inset 0 -3px 0 rgba(0,0,0,.25); }
.seat .chip.red{background:var(--red)} .seat .chip.green{background:var(--green)}
.seat .chip.yellow{background:var(--yellow)} .seat .chip.blue{background:var(--blue)}
.seat .empty { color: var(--ink-soft); font-style: italic; font-weight: 500; }

/* win screen */
.result {
  text-align: center;
}
.result .crown { font-size: 58px; line-height: 1; margin-bottom: 8px; }
.result h2 { font-size: 30px; margin-bottom: 6px; }
.result.won .crown { animation: win-pop .7s cubic-bezier(.2,1.6,.4,1) both, win-glow 1.6s ease-in-out .7s infinite; }
.result.won h2 { animation: win-pop .6s cubic-bezier(.2,1.6,.4,1) .1s both; }
.result.lost .crown { animation: lose-dim .8s ease both; filter: grayscale(1); opacity: .6; }
@keyframes win-pop {
  0% { transform: scale(.2) rotate(-14deg); opacity: 0; }
  60% { transform: scale(1.25) rotate(6deg); opacity: 1; }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}
@keyframes win-glow {
  0%, 100% { filter: drop-shadow(0 0 2px gold); }
  50% { filter: drop-shadow(0 0 14px gold); }
}
@keyframes lose-dim {
  from { transform: scale(1.2); opacity: 0; }
  to { transform: scale(1); opacity: .6; }
}
.result .sub { color: var(--ink-soft); margin: 0 0 18px; }
.rank { list-style: none; padding: 0; margin: 0 0 18px; display: grid; gap: 8px; text-align: left; }
.rank li {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 10px; background: #00000008; font-weight: 700; font-size: 14px;
}
.rank .chip { width: 20px; height: 20px; border-radius: 6px; }
.rank .chip.red{background:var(--red)} .rank .chip.green{background:var(--green)}
.rank .chip.yellow{background:var(--yellow)} .rank .chip.blue{background:var(--blue)}
.rank .pos { font-family: "Alfa Slab One", serif; color: var(--ink-soft); width: 26px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* toast */
.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%) translateY(20px);
  background: var(--ink);
  color: #fff;
  padding: 13px 20px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 15px;
  box-shadow: 0 14px 34px -12px #000;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
  z-index: 60;
  max-width: 90vw;
  text-align: center;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ============================================================
   Responsive tightening — phones and small tablets
   ============================================================ */

@media (max-width: 640px) {
  .shell { padding: 12px; }

  .topbar { gap: 10px; margin-bottom: 14px; }
  .topbar .mark-title { font-size: 20px; }

  .roomcode {
    font-size: 12px;
    padding: 6px 6px 6px 12px;
    gap: 6px;
    width: 100%;
    justify-content: space-between;
  }
  .roomcode b { font-size: 13px; letter-spacing: .12em; }
  .roomcode button, .spectating-badge {
    font-size: 11px;
    padding: 6px 10px;
  }

  .board-frame { padding: 6px; border-radius: 14px; }

  .panel { padding: 14px; }
  .panel + .panel { margin-top: 12px; }

  .dice-stage { width: 88px; height: 88px; }
  .dice-flat { width: 66px; height: 66px; padding: 9px; }
  .dice-flat .pip { width: 12px; height: 12px; }
  .face { width: 56px; height: 56px; }

  .turn-banner { font-size: 14px; padding: 10px 12px; }

  .btn { font-size: 15px; padding: 12px 16px; }

  .swatches { grid-template-columns: repeat(4, 1fr); gap: 6px; }
  .swatch { padding: 9px 4px 7px; }
  .swatch img { width: 26px; height: 36px; }
  .swatch .nm { font-size: 10px; }

  .overlay { padding: 14px; }
  .card { padding: 16px; }

  .result .crown { font-size: 44px; }
  .result h2 { font-size: 24px; }
}

@media (max-width: 420px) {
  .brand .logo { letter-spacing: -.01em; }
  .roomcode { border-radius: 16px; }
  .roomcode > span:first-child { display: none; } /* "Code" label — the value alone is enough this narrow */
  .turn-timer { font-size: 12px; }
  .turn-timer-ring { width: 26px; height: 26px; }
  .menu-wrap { padding: 14px; }
}

/* Board never shrinks below a legible size — the frame scrolls instead of
   squashing pips and pawns into an unusable jumble. */
@media (max-width: 380px) {
  .board-frame { overflow-x: auto; }
  .board { min-width: 340px; }
}

/* ── StudentChat integration: wallet bar, prize card, leaderboard ── */
.wallet-bar{display:flex;gap:10px;justify-content:center;margin:14px 0 4px;flex-wrap:wrap;}
.wallet{display:inline-flex;align-items:center;gap:7px;background:rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.14);border-radius:999px;padding:6px 14px;font-weight:800;font-size:14px;}
.wallet img{height:18px !important;width:auto !important;max-width:none !important;display:block;flex:0 0 auto;}
.prize-card{border-style:dashed;}
.wallet-m{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:700;opacity:.92;}
.wallet-m img{height:15px !important;width:auto !important;max-width:none !important;display:block;flex:0 0 auto;}
.prize-line{margin-top:6px;font-size:13px;opacity:.9;}
.lboard{display:flex;flex-direction:column;gap:6px;margin-top:6px;}
.lrow{display:flex;align-items:center;gap:10px;background:rgba(0,0,0,.25);border:1px solid rgba(255,255,255,.1);border-radius:12px;padding:7px 12px;}
.lpos{font-family:'Alfa Slab One',serif;font-size:16px;width:26px;text-align:center;opacity:.85;}
.lrow:nth-child(1) .lpos{color:#ffd60a;}
.lrow:nth-child(2) .lpos{color:#c0c0c0;}
.lrow:nth-child(3) .lpos{color:#cd7f32;}
.lav{width:32px;height:32px;max-width:32px;border-radius:50%;object-fit:cover;flex:0 0 32px;}
.lname{flex:1;min-width:0;font-weight:700;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.lstat{font-size:12px;opacity:.9;white-space:nowrap;display:inline-flex;align-items:center;gap:4px;}
.lstat img{height:13px !important;width:auto !important;max-width:none !important;}
.announce-row{display:flex;align-items:center;gap:8px;margin-top:12px;font-size:13px;font-weight:600;cursor:pointer;opacity:.92;}
.announce-row input{width:16px;height:16px;accent-color:var(--green);cursor:pointer;}
.lstat b{font-size:13px;}
