*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
:root{
  --accent:#FF8A4D;
  --ink:#F4F5F7;
  --muted:#9AA1AD;
  --dim:#6B7280;
  --line:rgba(255,255,255,.1);
  --felt:#1B4038;
  --feltHi:#235046;
  /* One number sizes the whole board. It has to fit between two rows of player
     panels, the header and the hint line, on a phone held upright. */
  --cell:min(calc((100vw - 20px) / 15), calc((100vh - 240px) / 15), 34px);
  --board:calc(var(--cell) * 15);
}
@supports (height:100dvh){
  :root{--cell:min(calc((100vw - 20px) / 15), calc((100dvh - 240px) / 15), 34px)}
}
html,body{margin:0;height:100%;background:#0D1014;color:var(--ink)}
body{
  font-family:Inter,system-ui,sans-serif;
  touch-action:manipulation;overflow-x:hidden;
  background:
    radial-gradient(70% 50% at 50% 0%,rgba(255,138,77,.10),transparent 68%),
    linear-gradient(180deg,#141922,#0C0F14);
}
button,input{font:inherit;color:inherit}
button{cursor:pointer}
#app{
  width:min(100%,560px);min-height:100vh;min-height:100dvh;margin:auto;
  padding:8px 10px calc(8px + env(safe-area-inset-bottom,0px));
  display:flex;flex-direction:column;align-items:center;gap:8px;
}
/* the die only ever shows inside a player's panel */
#app > .die{display:none}

/* ---- header ------------------------------------------------------------ */
.topbar{width:var(--board);display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:40px}
.iconbtn{
  width:40px;height:40px;flex:0 0 auto;border-radius:12px;border:1px solid var(--line);
  background:rgba(255,255,255,.05);font-size:17px;font-weight:700;color:#DDE1E8;
  display:grid;place-items:center;
}
.iconbtn:hover{background:rgba(255,255,255,.11)}
.title{text-align:center;min-width:0}
.title b{display:block;font:800 20px/1.1 'Bricolage Grotesque',sans-serif;color:var(--accent)}
.title small{
  display:block;margin-top:2px;font:9.5px 'Space Mono',monospace;color:var(--dim);
  letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* ---- player panels ---------------------------------------------------------
   Each player sits at their own corner and the dice travels to whoever is
   playing, so whose turn it is reads from position rather than from a label. */
.prow{width:var(--board);display:grid;grid-template-columns:1fr 1fr;gap:8px}
.panel{
  position:relative;display:flex;align-items:center;gap:8px;min-width:0;
  height:58px;padding:6px 8px;border-radius:15px;
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);
  transition:background .25s,border-color .25s,box-shadow .25s,opacity .25s;
}
.panel.rev{flex-direction:row-reverse;text-align:right}
.panel .av{
  position:relative;flex:0 0 auto;width:38px;height:38px;border-radius:50%;
  display:grid;place-items:center;
  background:radial-gradient(60% 55% at 35% 28%,var(--hi),var(--base) 62%,var(--lo));
  box-shadow:0 2px 0 rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.4);
  font:800 16px 'Bricolage Grotesque',sans-serif;color:var(--on);
}
.panel .av span{display:grid;place-items:center;width:100%;height:100%}
.panel .pinfo{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.panel.rev .pinfo{align-items:flex-end}
.panel b{
  font:700 13px/1.15 Inter,sans-serif;color:#E9ECF1;max-width:100%;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.panel small{font:9px 'Space Mono',monospace;letter-spacing:.06em;color:var(--dim);text-transform:uppercase;white-space:nowrap}
.panel .homes{display:flex;gap:3px;min-height:7px}
.panel .homes i{width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.14)}
.panel .homes i.on{background:var(--base);box-shadow:0 0 6px var(--base)}
.panel .dieslot{flex:0 0 auto;width:46px;height:46px;display:grid;place-items:center}
.panel.on{
  z-index:20;
  background:color-mix(in srgb,var(--base) 17%,rgba(255,255,255,.03));
  border-color:var(--base);
  box-shadow:0 0 0 1px var(--base) inset,0 0 24px -6px var(--base);
}
.panel.on .av::after{
  content:'';position:absolute;inset:-5px;border-radius:50%;
  border:2px solid var(--base);border-right-color:transparent;border-bottom-color:transparent;
  animation:spin 1.3s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
.panel.off{opacity:.3}
.panel.won .av::before{
  content:'★';position:absolute;top:-15px;font-size:15px;color:#FFD34D;
  text-shadow:0 1px 3px rgba(0,0,0,.6);
}

/* ---- board ------------------------------------------------------------------ */
.stage{display:flex;justify-content:center}
.boardframe{position:relative;width:var(--board);height:var(--board)}
/* The board turns so your yard sits bottom-left, nearest your thumb. Text on it
   (stack counts, the safe-square star) is turned back so it stays upright. */
.boardwrap{position:absolute;inset:0;transform:rotate(var(--brot,0deg))}
.board{
  position:absolute;inset:0;
  display:grid;
  grid-template-columns:repeat(15,var(--cell));
  grid-template-rows:repeat(15,var(--cell));
  border-radius:16px;overflow:hidden;
  background:radial-gradient(120% 100% at 50% 0%,var(--feltHi),var(--felt) 60%,#15332C 100%);
  box-shadow:
    0 1px 0 rgba(255,255,255,.1) inset,
    0 -18px 34px rgba(0,0,0,.35) inset,
    0 18px 40px rgba(0,0,0,.55);
}
.sq{position:relative}
.sq.track{
  background:linear-gradient(180deg,#F6F1E4,#DED6C4);
  box-shadow:inset 0 0 0 1px rgba(60,52,38,.22),inset 0 -2px 0 rgba(120,108,86,.3);
  border-radius:3px;margin:1px;
}
.sq.start{
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.25),inset 0 -2px 0 rgba(0,0,0,.18),inset 0 0 0 3px var(--tint);
}
.sq.safe::after{
  content:'★';position:absolute;inset:0;display:grid;place-items:center;
  font-size:calc(var(--cell) * .5);line-height:1;color:rgba(60,52,38,.42);
  pointer-events:none;transform:rotate(var(--unrot,0deg));
}
.sq.home{
  background:linear-gradient(180deg,var(--tint),color-mix(in srgb,var(--tint) 72%,#000));
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.22);border-radius:3px;margin:1px;
}
.sq.home::after{
  content:'';position:absolute;inset:26%;background:rgba(255,255,255,.3);
  clip-path:polygon(0 0,100% 50%,0 100%,22% 50%);transform:rotate(var(--rot,0deg));
}
.yardplate{
  position:absolute;border-radius:14px;pointer-events:none;
  background:linear-gradient(160deg,var(--hi),var(--base) 55%,var(--lo));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),inset 0 -3px 8px rgba(0,0,0,.3),0 6px 14px rgba(0,0,0,.35);
  transition:filter .3s;
}
.yardplate::after{
  content:'';position:absolute;inset:14%;border-radius:10px;
  background:rgba(14,18,22,.34);box-shadow:inset 0 2px 6px rgba(0,0,0,.45);
}
.yardplate.idle{filter:saturate(.2) brightness(.55)}
.socket{
  position:absolute;border-radius:50%;pointer-events:none;
  background:rgba(12,16,20,.5);box-shadow:inset 0 2px 5px rgba(0,0,0,.6),0 1px 0 rgba(255,255,255,.12);
}
.hub{
  position:absolute;left:calc(var(--cell)*6);top:calc(var(--cell)*6);
  width:calc(var(--cell)*3);height:calc(var(--cell)*3);pointer-events:none;
  filter:drop-shadow(0 3px 6px rgba(0,0,0,.45));
}
.hub svg{display:block;width:100%;height:100%}

/* ---- tokens ------------------------------------------------------------------ */
.tokens{position:absolute;inset:0;pointer-events:none}
/* A token is a standing pawn, not a disc. The .tok element is the whole board
   square (so the tap target is the full cell, not the 19px piece) and moves in
   board coordinates. Inside it, .pw turns back by the board's rotation so the
   pawn always stands upright on screen; .hop carries the jump arc of each
   step; the ground shadow stays on the board and shrinks as the pawn lifts. */
.tok{
  position:absolute;left:0;top:0;
  width:var(--cell);height:var(--cell);
  border-radius:50%;pointer-events:auto;cursor:pointer;
  transform:translate(var(--x),var(--y));
  will-change:transform;z-index:10;
}
/* one straight move per square: no overshoot, and the next step only starts
   once this one has landed (game.js waits the same --step) */
.tok.walk{transition:transform calc(var(--step,210ms) * .85) cubic-bezier(.45,.05,.55,.95)}
.tok.fly{transition:transform var(--step,520ms) cubic-bezier(.3,.1,.25,1)}
.tok .pw{
  position:absolute;inset:0;pointer-events:none;
  transform:rotate(var(--unrot,0deg)) translate(calc(var(--cell) * var(--ox,0)),calc(var(--cell) * var(--oy,0))) scale(var(--sc,1));
  transition:transform .2s ease;
}
.tok .tsh{
  position:absolute;left:16%;right:16%;top:48%;height:24%;border-radius:50%;
  background:radial-gradient(closest-side,rgba(0,0,0,.55),rgba(0,0,0,0));
}
.tok .hop{position:absolute;inset:0}
.tok .pawn{
  position:absolute;left:8%;top:-32%;width:84%;height:109.2%;overflow:visible;
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.25));
}
.tok .sn{
  position:absolute;right:-8%;top:-30%;display:none;min-width:46%;height:46%;padding:0 3px;
  border-radius:999px;place-items:center;background:#fff;color:#1A1D24;
  font:800 calc(var(--cell) * .3)/1 'Space Mono',monospace;box-shadow:0 1px 3px rgba(0,0,0,.5);
}
.tok.stackn .sn{display:grid}
/* the jump: a little crouch, up, and a squash on landing */
.tok.jump .hop{animation:jump var(--step,210ms) cubic-bezier(.3,.5,.4,1)}
.tok.jump .tsh{animation:jumpsh var(--step,210ms) cubic-bezier(.3,.5,.4,1)}
@keyframes jump{
  0%{transform:translateY(0) scale(1,1)}
  12%{transform:translateY(2%) scale(1.06,.92)}
  50%{transform:translateY(-42%) scale(.96,1.05)}
  88%{transform:translateY(0) scale(1.07,.9)}
  100%{transform:translateY(0) scale(1,1)}
}
@keyframes jumpsh{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(.55);opacity:.45}}
.tok.big.jump .hop{animation-name:jumpbig}
@keyframes jumpbig{
  0%{transform:translateY(0) scale(1,1)}
  12%{transform:translateY(3%) scale(1.08,.9)}
  50%{transform:translateY(-95%) scale(.96,1.05)}
  90%{transform:translateY(0) scale(1.08,.88)}
  100%{transform:translateY(0) scale(1,1)}
}
/* knocked back to the yard: it tumbles as it flies */
.tok.tumble .hop{animation:tumble var(--step,520ms) ease-in-out}
@keyframes tumble{
  0%{transform:translateY(0) rotate(0)}
  50%{transform:translateY(-70%) rotate(200deg) scale(.9)}
  100%{transform:translateY(0) rotate(360deg)}
}
.tok.walk,.tok.fly,.tok.lift{z-index:80 !important}
.tok.pick{z-index:70 !important}
.tok.pick .pawn{filter:brightness(1.15) drop-shadow(0 0 4px #fff) drop-shadow(0 0 7px var(--base))}
.tok.pick .hop{animation:bob 1s ease-in-out infinite}
.tok.pick::after{
  content:'';position:absolute;inset:4%;border-radius:50%;
  border:2px solid #fff;opacity:.9;animation:halo 1.2s ease-out infinite;
}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-16%)}}
@keyframes halo{0%{transform:scale(.7);opacity:.85}100%{transform:scale(1.5);opacity:0}}
.tok.gone{opacity:0;transition:opacity .3s}
/* where a token would land — tappable as well as the token itself */
.ghost{
  position:absolute;left:0;top:0;width:var(--cell);height:var(--cell);
  display:grid;place-items:center;pointer-events:auto;cursor:pointer;z-index:6;
}
.ghost::before{
  content:'';width:66%;height:66%;border-radius:50%;
  border:2.5px dashed var(--base);
  background:color-mix(in srgb,var(--base) 24%,transparent);
  animation:ghostp 1s ease-in-out infinite;
}
@keyframes ghostp{0%,100%{opacity:.6;transform:scale(.92)}50%{opacity:1;transform:scale(1.05)}}

/* ---- dice: a real cube --------------------------------------------------------
   A flat square spinning never reads as a die. Six faces in 3D, tumbling and
   landing on the result face, does — and it needs no library. The cube sits at
   a fixed three-quarter tilt so it looks solid even at rest, and each face is
   shaded from one light so the top reads brighter than the side. */
.die{
  --d:32px;
  position:relative;width:46px;height:46px;cursor:pointer;outline:none;
  perspective:260px;border-radius:12px;
}
.die[aria-disabled="true"]{cursor:default}
.die:focus-visible{box-shadow:0 0 0 2px #fff}
.die .dshadow{
  position:absolute;left:9px;right:9px;bottom:1px;height:8px;border-radius:50%;
  background:rgba(0,0,0,.5);filter:blur(3px);
}
.die .toss,.die .tilt{position:absolute;inset:0;transform-style:preserve-3d}
.die .tilt{transform:rotateX(-24deg) rotateY(-32deg)}
.die .cube{
  position:absolute;left:50%;top:50%;width:var(--d);height:var(--d);
  margin:calc(var(--d) / -2) 0 0 calc(var(--d) / -2);
  transform-style:preserve-3d;
  transition:transform .95s cubic-bezier(.12,.72,.18,1);
}
.die .face{
  position:absolute;inset:0;border-radius:17%;
  background:linear-gradient(145deg,#FFFDF7,#ECE3CF);
  box-shadow:inset 0 0 0 1px rgba(120,104,78,.5),inset 0 -2px 3px rgba(120,104,78,.22);
  display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);
  padding:16%;gap:4%;
  backface-visibility:hidden;-webkit-backface-visibility:hidden;
  transition:filter .25s;
}
.die .face i{border-radius:50%;background:radial-gradient(circle at 35% 30%,#59606D,#141820 72%)}
.die .face i.x{visibility:hidden}
.die .f1 i,.die .f4 i{background:radial-gradient(circle at 35% 30%,#FF7A7A,#A3141C 72%)}
.die .f1{transform:rotateY(0deg) translateZ(calc(var(--d) / 2))}
.die .f6{transform:rotateY(180deg) translateZ(calc(var(--d) / 2))}
.die .f2{transform:rotateY(90deg) translateZ(calc(var(--d) / 2))}
.die .f5{transform:rotateY(-90deg) translateZ(calc(var(--d) / 2))}
.die .f3{transform:rotateX(90deg) translateZ(calc(var(--d) / 2))}
.die .f4{transform:rotateX(-90deg) translateZ(calc(var(--d) / 2))}
/* the toss: up, over and down, with the shadow shrinking at the top of the arc */
.die.rolling .toss{animation:toss .92s cubic-bezier(.3,.6,.4,1)}
@keyframes toss{
  0%{transform:translateY(0)}
  34%{transform:translateY(-30px)}
  68%{transform:translateY(0)}
  80%{transform:translateY(-7px)}
  100%{transform:translateY(0)}
}
.die.rolling .dshadow{animation:tshadow .92s cubic-bezier(.3,.6,.4,1)}
@keyframes tshadow{
  0%,68%,100%{transform:scale(1);opacity:.5}
  34%{transform:scale(.45);opacity:.15}
  80%{transform:scale(.8);opacity:.35}
}
.die.landing .toss{animation:land .24s ease-out}
@keyframes land{0%{transform:scale(1.1,.88)}60%{transform:scale(.97,1.04)}100%{transform:scale(1,1)}}
/* your roll: the dice asks to be tapped */
.die.ready::before{
  content:'';position:absolute;inset:-5px;border-radius:14px;
  border:2px solid var(--base,#fff);animation:readyp 1.25s ease-out infinite;
}
@keyframes readyp{0%{opacity:.95;transform:scale(.92)}100%{opacity:0;transform:scale(1.22)}}

/* ---- banner -------------------------------------------------------------------- */
.banner{
  position:absolute;left:50%;top:50%;z-index:50;
  transform:translate(-50%,-50%) scale(.88);opacity:0;pointer-events:none;
  max-width:86%;padding:12px 20px;border-radius:16px;text-align:center;
  font:800 18px/1.25 'Bricolage Grotesque',sans-serif;
  color:var(--on,#fff);
  background:linear-gradient(180deg,color-mix(in srgb,var(--base,#3a3f4b) 92%,#fff 8%),var(--base,#3a3f4b));
  box-shadow:0 14px 32px rgba(0,0,0,.55),inset 0 0 0 2px rgba(255,255,255,.35);
  transition:opacity .2s ease,transform .32s cubic-bezier(.2,1.35,.4,1);
}
.banner.show{opacity:1;transform:translate(-50%,-50%) scale(1)}
.banner.info{
  color:#F1F3F6;background:rgba(18,22,30,.94);
  box-shadow:0 14px 32px rgba(0,0,0,.55),inset 0 0 0 1.5px var(--base,rgba(255,255,255,.2));
}
.banner.bad{color:#fff;background:linear-gradient(180deg,#5A2328,#3A1518);box-shadow:0 14px 32px rgba(0,0,0,.55),inset 0 0 0 1.5px #FF6B6B}
.banner.win{font-size:24px;padding:16px 26px}

.hint{min-height:18px;margin:0;width:var(--board);font:12.5px/1.4 Inter,sans-serif;color:var(--muted);text-align:center}

/* ---- setup -------------------------------------------------------------------- */
.setup{
  position:fixed;inset:0;z-index:90;overflow-y:auto;
  display:flex;align-items:flex-start;justify-content:center;
  padding:max(14px,env(safe-area-inset-top)) 14px 24px;
  background:radial-gradient(80% 50% at 50% 0%,rgba(255,138,77,.16),transparent 70%),#0A0C10;
}
.setup[hidden]{display:none}
.scard{width:min(100%,400px);margin:auto 0}
.resume{
  display:flex;align-items:center;gap:12px;margin:14px 0 2px;padding:12px 12px 12px 14px;border-radius:16px;
  background:linear-gradient(135deg,color-mix(in srgb,var(--base) 22%,#171B22),#171B22 70%);
  border:1.5px solid color-mix(in srgb,var(--base) 70%,transparent);
  box-shadow:0 10px 26px rgba(0,0,0,.35),0 0 22px -8px var(--base);
}
.resume .rinfo{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.resume b{font:800 16px 'Bricolage Grotesque',sans-serif;color:#fff}
.resume small{font-size:12px;color:#B9C0CB;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.resumebtn{
  flex:0 0 auto;min-height:44px;padding:0 18px;border:0;border-radius:12px;
  background:var(--base);color:var(--on,#fff);font:800 15px 'Bricolage Grotesque',sans-serif;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),0 6px 14px rgba(0,0,0,.35);
}
.or{margin:12px 0 0;text-align:center;font:10px 'Space Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.sbrand{text-align:center;margin:6px 0 4px}
.sbrand b{display:block;font:800 30px/1.05 'Bricolage Grotesque',sans-serif;color:var(--accent)}
.sbrand small{font:10px 'Space Mono',monospace;letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
.fld{display:flex;flex-direction:column;gap:7px;margin-top:15px}
.fld > span{font:10px 'Space Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.fld input{
  min-height:46px;padding:0 14px;border-radius:12px;border:1px solid var(--line);
  background:rgba(255,255,255,.05);font-size:15px;font-weight:600;
}
.fld input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(255,138,77,.25)}
.colours{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.cpick{
  display:flex;flex-direction:column;align-items:center;gap:6px;min-height:82px;padding:10px 4px;
  border-radius:14px;border:1.5px solid var(--line);background:rgba(255,255,255,.04);
  font-size:12px;font-weight:700;color:#C7CCD5;transition:.15s;
}
.cpick .tk{
  width:34px;height:34px;border-radius:50%;
  background:radial-gradient(42% 36% at 33% 26%,var(--hi),transparent 62%),radial-gradient(95% 95% at 50% 40%,var(--base),var(--lo));
  box-shadow:0 3px 6px rgba(0,0,0,.45),inset 0 -2px 3px rgba(0,0,0,.3);
}
.cpick[aria-pressed="true"]{
  color:#fff;border-color:var(--base);
  background:color-mix(in srgb,var(--base) 18%,rgba(255,255,255,.03));
  box-shadow:0 0 0 1px var(--base) inset,0 0 20px -6px var(--base);
}
.seg{display:flex;gap:6px}
.seg button{
  flex:1;min-height:44px;padding:0 8px;border-radius:12px;border:1px solid var(--line);
  background:rgba(255,255,255,.04);font-size:13px;font-weight:700;color:#C7CCD5;
}
.seg button[aria-pressed="true"]{background:var(--accent);border-color:transparent;color:#2A1206}
.fnames{display:grid;gap:7px}
.startbtn{
  margin-top:20px;width:100%;min-height:54px;border:0;border-radius:15px;
  background:linear-gradient(180deg,#FFA06B,var(--accent));color:#2A1206;
  font:800 17px 'Bricolage Grotesque',sans-serif;
  box-shadow:0 10px 24px rgba(255,138,77,.3),inset 0 1px 0 rgba(255,255,255,.45);
}
.startbtn:active{transform:translateY(1px)}
.snote{margin:12px 0 0;text-align:center;font-size:12px;color:var(--dim)}

/* ---- modal ----------------------------------------------------------------------- */
.modal{position:fixed;inset:0;z-index:100;display:grid;place-items:center;padding:18px;
  background:rgba(8,10,14,.74);backdrop-filter:blur(6px)}
.modal[hidden]{display:none}
.modal-card{
  width:min(100%,400px);max-height:86dvh;overflow:auto;padding:22px;border-radius:18px;
  border:1px solid var(--line);background:linear-gradient(180deg,#1A1D26,#14171E);
  box-shadow:0 30px 70px rgba(0,0,0,.6);
}
.modal-card h2{margin:0 0 12px;font:800 22px 'Bricolage Grotesque',sans-serif;color:var(--accent)}
.modal-card p,.modal-card li{font-size:14px;line-height:1.6;color:#C3C9D3}
.modal-card ul{padding-left:18px;margin:8px 0}
.button{
  min-height:46px;padding:0 14px;border-radius:12px;border:1px solid var(--line);
  background:rgba(255,255,255,.05);font-size:14px;font-weight:700;color:#DDE1E8;
}
.button:hover{background:rgba(255,255,255,.11)}
.button.primary{background:var(--accent);border-color:var(--accent);color:#2A1206}
.mlist{display:grid;gap:8px}
.mrow{display:flex;gap:8px;margin-top:16px}
.mrow .button{flex:1}
.ranks{list-style:none;margin:4px 0 0;padding:0;display:grid;gap:7px}
.ranks li{
  display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:12px;
  background:rgba(255,255,255,.04);border:1px solid var(--line);color:#E3E6EB;
}
.ranks li.first{border-color:#FFD34D;background:rgba(255,211,77,.08)}
.ranks .rk{width:30px;font:700 12px 'Space Mono',monospace;color:var(--dim)}
.ranks li.first .rk{color:#FFD34D}
.ranks .pin{width:14px;height:14px;border-radius:50%;flex:0 0 auto;
  background:radial-gradient(60% 55% at 35% 30%,var(--hi),var(--base) 65%,var(--lo))}
.ranks .nm{flex:1;font-weight:700;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ranks .hm{font:11px 'Space Mono',monospace;color:var(--muted)}
.mstat{margin-top:12px;font-size:12.5px;color:#8C94A1}

/* ---- win burst --------------------------------------------------------------------- */
.winfx{position:absolute;inset:0;pointer-events:none;overflow:hidden;border-radius:16px}
.spark{position:absolute;width:7px;height:10px;border-radius:2px;opacity:0}
.winfx.go .spark{animation:fly 1.3s cubic-bezier(.15,.7,.3,1) forwards}
@keyframes fly{
  0%{opacity:1;transform:translate(0,0) rotate(0) scale(1)}
  100%{opacity:0;transform:translate(var(--dx),var(--dy)) rotate(var(--rot)) scale(.4)}
}

@media(max-width:400px){
  .panel{gap:6px;padding:5px 6px}
  .panel .av{width:32px;height:32px;font-size:14px}
  .panel b{font-size:12px}
  .die{--d:30px;width:42px;height:42px}
  .panel .dieslot{width:42px;height:42px}
}
/* Wide frames — a phone on its side, and the 16:10 frame the game page embeds
   on desktop. Stacking panels above and below would leave the board a strip,
   so they move to the sides, each still beside its own corner of the board. */
@media(min-aspect-ratio:5/4){
  :root{--cell:min(calc((100vh - 16px) / 15), calc((100vw - 340px) / 15), 44px)}
  @supports (height:100dvh){
    :root{--cell:min(calc((100dvh - 16px) / 15), calc((100vw - 340px) / 15), 44px)}
  }
  #app{
    width:100%;display:grid;justify-content:center;align-items:center;gap:6px 12px;
    grid-template-columns:minmax(140px,190px) var(--board) minmax(140px,190px);
    grid-template-rows:auto 1fr 1fr auto;
    grid-template-areas:"top stage hint" "tl stage tr" "bl stage br" ". stage .";
    padding:8px max(10px,env(safe-area-inset-right)) 8px max(10px,env(safe-area-inset-left));
  }
  .topbar{grid-area:top;width:100%}
  .stage{grid-area:stage}
  .prow{display:contents}
  #rowTop > .panel:nth-child(1){grid-area:tl;align-self:start}
  #rowTop > .panel:nth-child(2){grid-area:tr;align-self:start}
  #rowBottom > .panel:nth-child(1){grid-area:bl;align-self:end}
  #rowBottom > .panel:nth-child(2){grid-area:br;align-self:end}
  .hint{grid-area:hint;width:100%;text-align:right}
}
/* A phone on its side cannot fit the setup card as one column — Start would be
   below the fold — so it splits in two, with Start beside the last choice. */
@media(min-aspect-ratio:5/4) and (max-height:520px){
  .scard{width:min(100%,720px);display:grid;grid-template-columns:1fr 1fr;column-gap:18px;align-items:end}
  .sbrand{grid-column:1/-1;margin:0}
  .sbrand b{font-size:24px;display:inline;margin-right:10px}
  .fld{margin-top:10px}
  .cpick{min-height:64px;padding:7px 4px;gap:4px}
  .cpick .tk{width:26px;height:26px}
  .startbtn{margin-top:10px;min-height:46px}
  .snote{grid-column:1/-1;margin-top:8px}
}
@media(prefers-reduced-motion:reduce){
  .tok,.tok.walk,.tok.fly,.tok .pw,.die .cube{transition:none}
  .tok.pick .hop,.tok.pick::after,.tok.jump .hop,.tok.jump .tsh,.tok.tumble .hop,.ghost::before,.panel.on .av::after,
  .die.rolling .toss,.die.rolling .dshadow,.die.landing .toss,.die.ready::before{animation:none}
  .banner{transition:none}
  .winfx.go .spark{animation:none}
}

/* ---- online: join, lobby ------------------------------------------------------- */
.online{margin-top:6px}
.online .startbtn{margin-top:14px}
.joinrow{display:flex;gap:8px;margin-top:10px}
.joinrow input{
  flex:1;min-width:0;min-height:48px;padding:0 14px;border-radius:12px;border:1px solid var(--line);
  background:rgba(255,255,255,.05);font:700 20px 'Space Mono',monospace;letter-spacing:.3em;text-transform:uppercase;text-align:center;
}
.joinrow input::placeholder{font-size:13px;letter-spacing:.14em;color:var(--dim)}
.joinrow input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(255,138,77,.25)}
.joinrow .button{min-width:86px}
.snote.bad{color:#FF8E8E}
.lobby .sbrand small{display:block;margin-top:4px}
.roomcode{display:flex;justify-content:center;gap:7px;margin:16px 0 4px}
.roomcode span{
  width:44px;height:54px;display:grid;place-items:center;border-radius:12px;
  background:linear-gradient(180deg,#232936,#171B22);border:1px solid rgba(255,255,255,.12);
  font:800 26px 'Space Mono',monospace;color:#fff;box-shadow:inset 0 -3px 0 rgba(0,0,0,.35);
}
.lobby .mrow{display:flex;gap:8px;margin-top:12px}
.lobby .mrow .button{flex:1}
.lseats{display:grid;gap:8px;margin-top:16px}
.lseat{
  display:flex;align-items:center;gap:10px;min-height:52px;padding:8px 10px;border-radius:14px;
  background:rgba(255,255,255,.04);border:1px solid color-mix(in srgb,var(--base) 35%,transparent);
}
.lseat .tk{
  width:24px;height:24px;flex:0 0 auto;border-radius:50%;
  background:radial-gradient(42% 36% at 33% 26%,var(--hi),transparent 62%),radial-gradient(95% 95% at 50% 40%,var(--base),var(--lo));
}
.lname{flex:1;min-width:0;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.lname b{font-size:14px;color:#EEF0F3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lname i{font:normal 9.5px 'Space Mono',monospace;letter-spacing:.08em;text-transform:uppercase;color:var(--accent);
  padding:2px 6px;border-radius:999px;background:rgba(255,138,77,.12)}
.lname i.off{color:#FF8E8E;background:rgba(255,107,107,.12)}
.lname .wait{font-size:13px;color:var(--dim)}
.seatctl{display:flex;gap:4px}
.seatctl button{min-height:34px;padding:0 9px;border-radius:9px;border:1px solid var(--line);background:rgba(255,255,255,.04);
  font-size:11.5px;font-weight:700;color:#C7CCD5}
.seatctl button[aria-pressed="true"]{background:var(--base);border-color:transparent;color:var(--on,#fff)}
.startbtn:disabled{opacity:.45;box-shadow:none;cursor:default}
.linkbtn{display:block;margin:14px auto 0;min-height:40px;padding:0 14px;border:0;background:none;color:var(--muted);
  font-size:13px;font-weight:600;text-decoration:underline;text-underline-offset:3px}
.mstat{flex:1;margin:0;font-size:12.5px;color:var(--muted);align-self:center}
