/* ===========================================================================
   LUDO Championship HAH-9
   Shared styling for the tournament page and the playing screen.
   =========================================================================== */

:root{
  /* the table: deep navy, lit from above */
  --night:#0C1730;
  --night-2:#122148;
  --felt:#16264E;
  --felt-2:#1B2E5C;
  --edge:#2B4079;
  --edge-soft:#223566;

  --ink:#EEF3FC;
  --soft:#B9C8E6;
  --mute:#7D93BC;

  --gold:#F2C14E;
  --gold-deep:#C99522;

  --red:#E14B58;      --red-deep:#A8232F;
  --green:#2EA96A;    --green-deep:#17784A;
  --yellow:#EFB13C;   --yellow-deep:#B97F16;
  --blue:#4C7BE0;     --blue-deep:#2A4FA8;

  --sans:"Segoe UI",system-ui,-apple-system,Roboto,"Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,"Courier New",monospace;
}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0}
body{
  color:var(--ink);font-family:var(--sans);font-size:16px;line-height:1.5;
  -webkit-font-smoothing:antialiased;
  padding:0 14px calc(28px + env(safe-area-inset-bottom));
  background-color:var(--night);
  /* a quiet woven pattern, drawn with gradients rather than an image file */
  background-image:
    radial-gradient(circle at 18% 12%, rgba(76,123,224,.16), transparent 46%),
    radial-gradient(circle at 84% 82%, rgba(242,193,78,.10), transparent 44%),
    repeating-linear-gradient(45deg, rgba(255,255,255,.022) 0 2px, transparent 2px 11px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,.022) 0 2px, transparent 2px 11px),
    linear-gradient(175deg, #122148 0%, #0C1730 58%, #0A1327 100%);
  background-attachment:fixed;
  min-height:100vh;
}
.wrap{max-width:560px;margin:0 auto;position:relative}
.hidden{display:none!important}

/* ================================================================== header */
.apphead{display:flex;align-items:center;gap:11px;padding:14px 0 12px}
.crest{
  width:40px;height:40px;border-radius:10px;flex:none;display:grid;
  grid-template-columns:1fr 1fr;gap:2px;padding:6px;
  background:linear-gradient(150deg,#1D3268,#12224A);
  border:1px solid var(--edge);box-shadow:0 4px 12px -6px #000;
}
.crest i{border-radius:2px;display:block}
.crest i:nth-child(1){background:var(--red)}
.crest i:nth-child(2){background:var(--green)}
.crest i:nth-child(3){background:var(--yellow)}
.crest i:nth-child(4){background:var(--blue)}
.crest img{width:100%;height:100%;object-fit:contain;grid-column:1/3;grid-row:1/3}

/* The real HAH roundel is its own badge — it does not want a navy box drawn
   round it, so the frame comes off once the image is in. */
.crest.hasmark{
  background:none;border:0;box-shadow:none;padding:0;
  width:40px;height:40px;
}

.apptitle{flex:1;min-width:0;line-height:1.15}
.apptitle b{
  display:block;font-size:16px;font-weight:800;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.apptitle b .lud{color:var(--gold)}
.apptitle small{
  display:block;font-family:var(--mono);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--mute);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.headmeta{font-family:var(--mono);font-size:10.5px;color:var(--mute);
          text-align:right;line-height:1.5;flex:none}
.headmeta b{color:var(--gold);font-size:13px;letter-spacing:.05em}
.soundbtn{
  font-size:16px;line-height:1;background:var(--felt);border:1px solid var(--edge);
  border-radius:9px;width:36px;height:34px;cursor:pointer;flex:none;
  display:flex;align-items:center;justify-content:center;color:var(--soft);
}
.soundbtn:hover{background:var(--felt-2)}
.soundbtn.off{opacity:.45}

/* ================================================================== panels */
.panel{
  background:linear-gradient(170deg,var(--felt-2),var(--felt));
  border:1px solid var(--edge);border-radius:14px;padding:22px;margin-top:10px;
  box-shadow:0 18px 40px -24px #000;
}
.panel h2{margin:0 0 5px;font-size:20px;letter-spacing:-.015em}
.panel p.sub{margin:0 0 18px;color:var(--soft);font-size:15px}

label{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;
      text-transform:uppercase;color:var(--mute);margin:0 0 6px}
input[type=text]{
  width:100%;font-family:var(--sans);font-size:17px;padding:13px 14px;
  border:1px solid var(--edge);border-radius:10px;background:#0F1C3C;
  color:var(--ink);margin-bottom:16px;
}
input[type=text]::placeholder{color:#5C71A0}
input[type=text]:focus{outline:2px solid var(--gold);outline-offset:1px;background:#101F44}
#employeeId{font-family:var(--mono);letter-spacing:.06em}

/* The city dropdown. Matched to the text boxes, with a chevron drawn in so it
   looks the same on every phone instead of each one drawing its own. */
select{
  width:100%;font-family:var(--sans);font-size:17px;padding:13px 40px 13px 14px;
  border:1px solid var(--edge);border-radius:10px;background:#0F1C3C;
  color:var(--ink);margin-bottom:16px;-webkit-appearance:none;appearance:none;
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%237E93C4' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round' d='M1 1.6l5 4.8 5-4.8'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center;background-size:12px 8px;
}
select:focus{outline:2px solid var(--gold);outline-offset:1px;background-color:#101F44}
select option{background:#0F1C3C;color:var(--ink)}

/* Step two: who the Employee ID turned out to be. */
.whocard{
  background:linear-gradient(165deg,#13244C,#0E1B3C);
  border:1px solid var(--edge);border-left:4px solid var(--gold);
  border-radius:12px;padding:15px 16px;margin-bottom:20px;
}
.whocard .wholabel{display:block;font-family:var(--mono);font-size:10px;
  letter-spacing:.14em;text-transform:uppercase;color:#7E93C4;margin-bottom:5px}
.whocard .whoname{display:block;font-size:22px;font-weight:800;line-height:1.2;
  color:#FFF3D6;letter-spacing:-.01em}
.whocard .whodept{display:block;font-size:14.5px;color:#A9BCE6;margin-top:5px}
.whocard .whoid{display:block;font-family:var(--mono);font-size:11.5px;
  letter-spacing:.06em;color:#6E84AE;margin-top:8px}

.btn{
  width:100%;font-family:var(--sans);font-size:17px;font-weight:800;color:#22160A;
  background:linear-gradient(170deg,#F8D77A,#E9AF32);
  border:none;border-radius:12px;padding:16px;cursor:pointer;letter-spacing:-.01em;
  box-shadow:0 6px 16px -8px rgba(242,193,78,.9);
}
.btn:disabled{background:#22345E;color:#6E84AE;cursor:default;box-shadow:none}
.btn.ghost{background:var(--felt);border:1px solid var(--edge);color:var(--ink);
           font-size:15px;font-weight:600;padding:13px;box-shadow:none}
.btn.ghost:hover{background:var(--felt-2)}
.btn.danger{background:transparent;border:1px solid #5B2A34;color:#F08894;
            font-size:14px;font-weight:600;padding:11px;box-shadow:none}
.btn.danger:hover{background:#2A1520}
.btn.ready{background:linear-gradient(170deg,#54D18C,#22935C);color:#062217}
.err{background:#3A1620;border:1px solid #6B2833;color:#FFB3BC;
     border-radius:10px;padding:12px 15px;font-size:14.5px;margin-bottom:16px}
.note{font-size:13px;color:var(--mute);margin:14px 0 0;line-height:1.6}

/* =================================================================== lobby */
.lobbyseat{display:flex;align-items:center;gap:11px;padding:12px 0;
           border-bottom:1px solid var(--edge-soft)}
.lobbyseat:last-of-type{border-bottom:none}
.lobbyseat .who{flex:1;min-width:0}
.lobbyseat .nm{font-weight:600;font-size:15px;display:block;
               overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lobbyseat .id{font-family:var(--mono);font-size:11px;color:var(--mute);display:block;margin-top:1px}
.lobbyseat .empty{color:var(--mute);font-style:italic;font-size:15px}
.state{font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.08em;
       padding:3px 8px;border-radius:5px;flex:none;background:#22345E;color:var(--soft)}
.state.ready{background:#14432E;color:#6FE0A4}
.state.you{background:var(--gold);color:#22160A}
/* The countdown. Big, obvious, and there from the moment the first person
   walks in, so nobody is ever waiting without knowing how long for. */
.lobbyclock{
  background:linear-gradient(170deg,#203568,#16264E);
  border:1px solid var(--edge);border-radius:11px;
  padding:13px 15px;margin:2px 0 16px;text-align:center;
  font-size:14.5px;color:var(--soft);
}
.lobbyclock b{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:21px;font-weight:800;color:var(--gold);display:inline-block;
  margin-left:4px;letter-spacing:.02em;
}

/* Force Start. Deliberately not the gold primary button — it throws away
   other people's seats, so it should not be the thing your thumb lands on. */
.btn.force{
  margin-top:10px;background:transparent;border:1px solid var(--gold-deep);
  color:var(--gold);font-size:15px;font-weight:700;padding:13px;box-shadow:none;
}
.btn.force:hover{background:#26203A}
.forcenote{font-size:12px;color:var(--mute);line-height:1.55;margin-top:7px;text-align:center}

.counter{background:#0F1C3C;border:1px solid var(--edge-soft);border-radius:10px;
         padding:13px 15px;margin:16px 0 0;font-size:14.5px;color:var(--soft)}
.counter b{font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--gold)}

/* ================================================================= avatars */
.avatar{
  width:34px;height:34px;border-radius:50%;flex:none;display:flex;
  align-items:center;justify-content:center;color:#fff;font-weight:800;
  font-size:13px;position:relative;
  box-shadow:inset 0 -3px 6px rgba(0,0,0,.3),0 2px 6px -2px #000;
}
.avatar.red{background:linear-gradient(160deg,var(--red),var(--red-deep))}
.avatar.green{background:linear-gradient(160deg,var(--green),var(--green-deep))}
.avatar.yellow{background:linear-gradient(160deg,var(--yellow),var(--yellow-deep))}
.avatar.blue{background:linear-gradient(160deg,var(--blue),var(--blue-deep))}

/* ============================================================== the table */
.table{margin-top:6px}
.boardarea{display:block}

/* ===================================================================
   ONE SCREEN, NO SCROLLING
   -------------------------------------------------------------------
   While a match is on screen the page is exactly one viewport tall and
   nothing overflows it. The header, both rows of player badges, the guide
   line and the dice button all keep their natural height; the board takes
   whatever is left and stays perfectly square. Nobody ever has to scroll or
   slide to see the whole board.

   dvh first with vh as the fallback, so the address bar sliding away on a
   phone does not leave a gap or push the board off the bottom.
   =================================================================== */
html.fit,html.fit body{overflow:hidden;height:100%}
body.fit{
  height:100vh;
  height:100dvh;
  /* The base rule sets min-height:100vh, which on its own is enough to push
     the page past one screen once padding is added. It has to go. */
  min-height:0;
  overflow:hidden;
  /* env() needs a fallback — without one the whole declaration is thrown away
     on any browser that does not know about safe areas, and the page silently
     keeps the 28px bottom padding that makes it scroll. */
  padding:0 8px calc(4px + env(safe-area-inset-bottom, 0px));
}
body.fit .wrap{height:100%;display:flex;flex-direction:column;min-height:0}
body.fit .apphead{flex:none;padding:8px 0 6px}
body.fit .apptitle small{display:none}          /* the tagline is the first thing to go */

body.fit #game{flex:1;min-height:0;display:flex;flex-direction:column;gap:6px}
body.fit .table{flex:1;min-height:0;display:flex;flex-direction:column;margin-top:0}
body.fit .panelrow{flex:none}
/* A grid item refuses to shrink below its own content unless told to, which
   was pushing the right-hand player card (and its dice box) off the side of
   a narrow phone. Both cards now shrink to their half and the name ellipses. */
body.fit .panelrow > *{min-width:0}
body.fit .pp .pinfo{min-width:0}
body.fit .panelrow.top{margin-bottom:6px}
body.fit .panelrow.bottom{margin-top:6px}
body.fit .pp{min-height:0;padding:6px 8px;gap:7px;border-radius:11px}
body.fit .avatar{width:26px;height:26px;font-size:10.5px}
body.fit .pdice{width:34px;height:34px;padding:5px}
body.fit .pp .pname{font-size:11.5px}
body.fit .pp .psub{font-size:9px}
body.fit .pbadge{font-size:8px;padding:1px 5px}
body.fit .bannerslot{flex:none;height:26px}
body.fit .turnbanner .inner{font-size:15px;padding:3px 16px}

/* The board area is simply the space left over. The board's exact square size
   is measured and set in JavaScript (see fitBoard in game.js) rather than
   guessed at in CSS — an aspect-ratio box told to fill the height will happily
   grow taller than the space and get its bottom clipped off, which is exactly
   what was cutting the bottom of the board on a phone. */
body.fit .boardarea{
  flex:1;min-height:0;min-width:0;
  display:flex;align-items:center;justify-content:center;
}
body.fit .boardwrap{
  margin:0;padding:5px;border-radius:13px;
  max-width:100%;max-height:100%;
}

body.fit .guide{flex:none;min-height:0;padding:7px 11px}
body.fit .guide .big{font-size:14px}
body.fit .guide .sml{font-size:11px}
/* The dice button keeps its space even when it is not your turn, so the board
   stays exactly the same size all the way through the match instead of
   growing and shrinking every time the turn passes. */
body.fit .rollbar{flex:none;margin-top:0}
body.fit .rollbar.hidden{display:block!important;visibility:hidden}
body.fit .rollbtn{padding:13px;font-size:16px}
/* The match feed is the one thing that cannot earn its space on a phone. It
   is still in the page for wider screens and still read by the result panel. */
body.fit .feed{display:none}
body.fit .quitbar{flex:none;margin-top:4px;text-align:center}
body.fit .quitbar .btn{padding:6px 14px;font-size:12px;width:auto;display:inline-block}

/* A taller screen can afford the feed and the full-size furniture. */
@media (min-height:860px){
  body.fit .feed{display:block;flex:none;margin-top:6px}
  body.fit .apptitle small{display:block}
}

/* ===================================================================
   SHORT SCREENS — GIVING THE BOARD ITS ROOM BACK
   -------------------------------------------------------------------
   On a short phone the fixed furniture was eating so much height that the
   board was squeezed down to almost nothing. Everything round the board gets
   progressively smaller so the board keeps the lion's share. Nothing that
   matters is lost: the name and the badge stay, they just sit side by side
   instead of stacked.
   =================================================================== */
@media (max-height:780px){
  /* name and badge on one line instead of three */
  body.fit .pp{min-height:0;padding:5px 8px;gap:7px}
  body.fit .pp .pinfo{display:flex;align-items:center;gap:7px;min-width:0}
  body.fit .pp .pname{font-size:12px;flex:1;min-width:0;
                      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  body.fit .pp .psub{display:none}
  body.fit .pbadge{flex:none;font-size:8px;padding:1px 5px;margin:0}
  body.fit .avatar{width:24px;height:24px;font-size:10px}
  body.fit .pdice{width:32px;height:32px;padding:4px}

  /* one line of guidance, not two */
  body.fit .guide{padding:6px 10px}
  body.fit .guide .sml{display:none}
  body.fit .guide .big{font-size:13.5px}

  /* the YOUR TURN strip goes: the glowing house and the guide line already
     say whose turn it is, and it is the cheapest 26 pixels to reclaim */
  body.fit .bannerslot{display:none}

  body.fit .quitbar{margin-top:3px}
  body.fit .quitbar .btn{padding:5px 12px;font-size:11px}
  body.fit .panelrow.top{margin-bottom:5px}
  body.fit .panelrow.bottom{margin-top:5px}
  body.fit #game{gap:5px}
}

@media (max-height:640px){
  body.fit .apphead{padding:5px 0 4px;gap:8px}
  body.fit .crest,body.fit .crest.hasmark{width:32px;height:32px}
  body.fit .apptitle b{font-size:13px}
  body.fit .soundbtn{width:30px;height:28px;font-size:13px}
  body.fit .pp{padding:4px 7px}
  body.fit .avatar{width:22px;height:22px;font-size:9.5px}
  body.fit .pdice{width:28px;height:28px;padding:4px}
  body.fit .guide{padding:5px 9px}
  body.fit .guide .big{font-size:12.5px}
  body.fit .rollbtn{padding:10px;font-size:15px}
  body.fit .quitbar .btn{padding:4px 10px;font-size:10.5px}
}
.panelrow{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.panelrow.top{margin-bottom:8px}
.panelrow.bottom{margin-top:8px}

.pp{
  position:relative;display:flex;align-items:center;gap:9px;
  background:linear-gradient(170deg,var(--felt-2),var(--felt));
  border:1px solid var(--edge);border-radius:13px;padding:9px 10px;
  min-height:62px;transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;
}
.pp .pinfo{flex:1;min-width:0}

/* A seat nobody took. Shaded right down, no dice box, clearly not in play. */
.pp.vacant{
  opacity:.42;
  background:linear-gradient(170deg,#101C3A,#0C1730);
  border-style:dashed;
  box-shadow:none;
}
.pp.vacant .avatar{background:#2A3A60!important;color:var(--mute)}
.pp.vacant .pname{font-style:italic;color:var(--mute)}
/* Somebody who was here and has gone. Dimmed, but still shows who it was. */
.pp.gone{opacity:.55}
.pp.gone .avatar{filter:grayscale(.8)}
.pp .pname{display:block;font-weight:700;font-size:13px;line-height:1.2;
           white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pp .psub{display:block;font-family:var(--mono);font-size:9.5px;color:var(--mute);
          margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pbadge{
  display:inline-block;font-family:var(--mono);font-size:9px;font-weight:700;
  letter-spacing:.07em;padding:2px 6px;border-radius:5px;margin-top:4px;
  background:var(--gold);color:#22160A;
}
.pbadge.grey{background:#2B4079;color:var(--soft)}
.pbadge.away{background:#5B2A34;color:#F5A7B1}

/* the little dice box in each corner panel */
.pdice{
  width:46px;height:46px;flex:none;border-radius:11px;padding:7px;
  display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);gap:2px;
  background:linear-gradient(150deg,#FFFFFF,#D9DEE9);
  border:1px solid #9AA6C0;
  box-shadow:inset 0 2px 2px rgba(255,255,255,.9),inset 0 -4px 7px rgba(12,23,48,.28),
             0 4px 9px -5px #000;
}
.pdice i{border-radius:50%;background:radial-gradient(circle at 32% 30%,#3B4560,#0C1730 72%);
         visibility:hidden;width:100%;height:100%;align-self:center;justify-self:center}
.pdice i.on{visibility:visible}
.pdice.empty{background:#22345E;border-color:var(--edge);box-shadow:none}
.pdice.tap{cursor:pointer}
.pdice.tap:active{transform:translateY(1px)}

/* turn ownership: the whole panel lifts and glows */
.pp.active{transform:translateY(-2px) scale(1.025)}
.pp.active.red{border-color:var(--red);box-shadow:0 0 0 2px rgba(225,75,88,.35),0 0 22px -4px var(--red)}
.pp.active.green{border-color:var(--green);box-shadow:0 0 0 2px rgba(46,169,106,.35),0 0 22px -4px var(--green)}
.pp.active.yellow{border-color:var(--yellow);box-shadow:0 0 0 2px rgba(239,177,60,.35),0 0 22px -4px var(--yellow)}
.pp.active.blue{border-color:var(--blue);box-shadow:0 0 0 2px rgba(76,123,224,.35),0 0 22px -4px var(--blue)}
.pp.active .avatar{animation:breathe 1.5s ease-in-out infinite}
@keyframes breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.1)}}

/* the pulsing arrow that points at whose dice it is */
.parrow{
  position:absolute;right:19px;top:-13px;width:0;height:0;opacity:0;
  border-left:11px solid transparent;border-right:11px solid transparent;
  border-top:14px solid var(--gold);
  filter:drop-shadow(0 2px 5px rgba(242,193,78,.8));
}
.pp.rolling-now .parrow{opacity:1;animation:arrowbob 1s ease-in-out infinite}
@keyframes arrowbob{
  0%,100%{transform:translateY(-4px);opacity:.75}
  50%{transform:translateY(2px);opacity:1}
}

/* ================================================================== board */
.boardwrap{
  /* The board is square and takes the full width of the phone, but never so
     tall that the panels and buttons fall off a short screen. */
  position:relative;width:100%;max-width:min(100%,58vh);margin:0 auto;
  aspect-ratio:1/1;
  border-radius:16px;padding:7px;
  background:linear-gradient(160deg,#22376E,#16264E);
  border:1px solid var(--edge);
  box-shadow:0 24px 50px -26px #000,inset 0 1px 0 rgba(255,255,255,.08);
}
canvas#board{width:100%;height:100%;display:block;border-radius:10px;
             background:#F7F8FB;touch-action:manipulation}

/* "YOUR TURN!" sits in its own strip above the board, so it can never
   cover a token. The strip keeps its height whether or not it is showing,
   so nothing on the page jumps when it appears. */
.bannerslot{height:46px;display:flex;align-items:center;justify-content:center;
            margin-bottom:2px;overflow:visible}
.turnbanner{pointer-events:none;display:flex;justify-content:center}
.turnbanner .inner{
  background:linear-gradient(135deg,var(--gold),#E09A1E);color:#22160A;
  font-weight:900;font-size:clamp(17px,4.6vw,21px);letter-spacing:.08em;
  padding:11px 28px;border-radius:12px;white-space:nowrap;
  box-shadow:0 12px 30px -8px rgba(0,0,0,.7);
  transform:translateY(-22px) scale(.9);opacity:0;
}
.turnbanner.show .inner{animation:bannerpop 2.4s cubic-bezier(.2,1.3,.4,1) forwards}
@keyframes bannerpop{
  0%{transform:translateY(-22px) scale(.9);opacity:0}
  12%{transform:translateY(0) scale(1.05);opacity:1}
  20%{transform:translateY(0) scale(1)}
  78%{transform:translateY(0) scale(1);opacity:1}
  100%{transform:translateY(-16px) scale(.96);opacity:0}
}

/* ======================================================= guidance + roll */
.guide{
  margin-top:10px;border-radius:12px;padding:11px 15px;min-height:54px;
  background:linear-gradient(170deg,var(--felt-2),var(--felt));
  border:1px solid var(--edge);display:flex;align-items:center;gap:12px;
}
.guide.mine{border-color:var(--gold);box-shadow:0 0 0 1px rgba(242,193,78,.3)}
.guide .txt{flex:1;min-width:0}
.guide .big{font-weight:800;font-size:15.5px;letter-spacing:-.01em}
.guide .sml{font-size:12.5px;color:var(--soft);margin-top:2px}
.guide .clock{font-family:var(--mono);font-variant-numeric:tabular-nums;
              font-size:20px;font-weight:700;flex:none;color:var(--soft)}
.guide .clock.urgent{color:#FF8B99;animation:clockflash 1s ease-in-out infinite}
@keyframes clockflash{0%,100%{opacity:1}50%{opacity:.4}}

.rollbar{margin-top:10px}
.rollbtn{
  width:100%;font-family:var(--sans);font-size:18px;font-weight:900;color:#22160A;
  background:linear-gradient(170deg,#F8D77A,#E9AF32);border:none;border-radius:13px;
  padding:18px;cursor:pointer;letter-spacing:.02em;
  box-shadow:0 8px 20px -10px rgba(242,193,78,.95);
}
.rollbtn:active{transform:translateY(1px)}
.rollbtn.pulse{animation:rollpulse 1.4s ease-in-out infinite}
@keyframes rollpulse{
  0%,100%{box-shadow:0 8px 20px -10px rgba(242,193,78,.95),0 0 0 0 rgba(242,193,78,.5)}
  50%{box-shadow:0 8px 20px -10px rgba(242,193,78,.95),0 0 0 14px rgba(242,193,78,0)}
}

/* =============================================== the dice that flies out */
#flyDie{
  position:fixed;z-index:70;width:56px;height:56px;border-radius:13px;padding:9px;
  display:none;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);gap:3px;
  background:linear-gradient(150deg,#FFFFFF,#DCE1EC);
  border:1px solid #96A2BD;
  box-shadow:inset 0 2px 3px rgba(255,255,255,.95),inset 0 -5px 9px rgba(12,23,48,.3),
             0 14px 30px -10px #000;
  transform-origin:center center;pointer-events:none;
}
#flyDie.on{display:grid}
#flyDie i{border-radius:50%;background:radial-gradient(circle at 32% 30%,#3B4560,#0C1730 72%);
          visibility:hidden;width:100%;height:100%;align-self:center;justify-self:center}
#flyDie i.on{visibility:visible}
#flyDieNum{
  position:fixed;z-index:71;display:none;pointer-events:none;
  font-size:72px;font-weight:900;color:var(--gold);letter-spacing:-.04em;
  text-shadow:0 6px 26px rgba(0,0,0,.85),0 0 40px rgba(242,193,78,.55);
}
#flyDieNum.on{display:block;animation:numpop .5s cubic-bezier(.2,1.5,.4,1) both}
@keyframes numpop{0%{transform:scale(.3);opacity:0}60%{transform:scale(1.18);opacity:1}
                  100%{transform:scale(1);opacity:1}}

/* ================================================ reconnecting overlay */
#reconnect{
  position:fixed;inset:0;z-index:90;display:none;
  align-items:center;justify-content:center;
  background:rgba(8,16,34,.86);backdrop-filter:blur(3px);
}
#reconnect.on{display:flex}
#reconnect .card{
  background:linear-gradient(170deg,var(--felt-2),var(--felt));
  border:1px solid var(--edge);border-radius:16px;padding:30px 34px;text-align:center;
  box-shadow:0 30px 60px -24px #000;max-width:86vw;
}
.spinner{
  width:56px;height:56px;margin:0 auto 18px;border-radius:50%;
  border:5px solid rgba(242,193,78,.18);border-top-color:var(--gold);
  animation:spin .9s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
#reconnect h3{margin:0 0 6px;font-size:19px;letter-spacing:-.01em}
#reconnect p{margin:0;color:var(--soft);font-size:14px;max-width:34ch}
#reconnect .tries{font-family:var(--mono);font-size:11px;color:var(--mute);margin-top:12px}

/* The one thing to press. It glows and breathes so it is obvious on a phone
   that has just come back onto signal. */
.btn.reconnectnow{
  margin-top:20px;font-size:17px;font-weight:900;letter-spacing:.06em;
  padding:16px 22px;
  background:linear-gradient(170deg,#F8D77A,#E9AF32);color:#22160A;border:none;
  animation:reconnectpulse 1.25s ease-in-out infinite;
}
.btn.reconnectnow:disabled{animation:none;opacity:.6}
@keyframes reconnectpulse{
  0%,100%{box-shadow:0 0 0 0 rgba(242,193,78,.55),0 10px 26px -12px #000;transform:scale(1)}
  50%    {box-shadow:0 0 0 16px rgba(242,193,78,0),0 10px 26px -12px #000;transform:scale(1.035)}
}

/* ==================================================================== feed */
.feed{font-family:var(--mono);font-size:11px;color:var(--mute);margin-top:12px;
      line-height:1.8;min-height:20px}
.quitbar{margin-top:14px}

/* ================================================================= victory */
.victory{text-align:center;overflow:hidden;position:relative}
.starburst{
  position:absolute;left:50%;top:6px;width:360px;height:360px;
  transform:translateX(-50%);pointer-events:none;opacity:.45;
  background:repeating-conic-gradient(
    from 0deg, rgba(242,193,78,.55) 0deg 7deg, rgba(242,193,78,0) 7deg 20deg);
  -webkit-mask-image:radial-gradient(circle,#000 16%,transparent 64%);
  mask-image:radial-gradient(circle,#000 16%,transparent 64%);
  animation:spinslow 26s linear infinite;
}
@keyframes spinslow{to{transform:translateX(-50%) rotate(360deg)}}
.trophy{font-size:68px;line-height:1;position:relative;
        filter:drop-shadow(0 10px 18px rgba(242,193,78,.5));
        animation:trophyin .9s cubic-bezier(.2,1.5,.4,1) both}
@keyframes trophyin{
  0%{transform:scale(.2) rotate(-25deg);opacity:0}
  60%{transform:scale(1.15) rotate(6deg);opacity:1}
  100%{transform:scale(1) rotate(0)}
}
.victory h2{position:relative;font-size:14px;letter-spacing:.18em;text-transform:uppercase;
            color:var(--gold);font-family:var(--mono);margin:12px 0 4px}
.winnername{position:relative;font-size:clamp(28px,7vw,38px);font-weight:900;
            letter-spacing:-.025em;line-height:1.1;margin:0 0 4px;
            animation:namein .7s .2s ease both}
@keyframes namein{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.winnerwhere{position:relative;color:var(--soft);font-size:16px;margin:0 0 18px}
.winnerfacts{position:relative;display:grid;
             grid-template-columns:repeat(auto-fit,minmax(125px,1fr));
             gap:8px;text-align:left;margin-bottom:18px}
.fact{background:#0F1C3C;border:1px solid var(--edge-soft);border-radius:10px;padding:10px 12px}
.fact .k{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
         color:var(--mute);display:block;margin-bottom:3px}
.fact .v{font-weight:700;font-size:14.5px;overflow-wrap:anywhere}
.victory .why{position:relative;color:var(--soft);font-size:14.5px;margin:0 0 16px}

/* The championship lockup at the foot of the winner's screen — this is the
   screen people photograph and send round, so it should carry the branding. */
.winnerbrand{
  position:relative;display:block;width:100%;max-width:300px;height:auto;
  margin:22px auto 4px;opacity:.95;
}

#confetti{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;
          z-index:80;display:none}
#confetti.on{display:block}

.final{width:100%;font-size:14px;margin-top:4px;border-collapse:collapse;
       position:relative;text-align:left}
.final th{font-family:var(--mono);font-size:10px;letter-spacing:.09em;text-transform:uppercase;
          color:var(--mute);text-align:left;padding:0 8px 6px 0;font-weight:700}
.final td{padding:7px 8px 7px 0;border-top:1px solid var(--edge-soft);
          font-variant-numeric:tabular-nums;color:var(--soft)}
.final td:first-child{font-weight:700;color:var(--ink)}

.tag{display:inline-block;font-family:var(--mono);font-size:9px;font-weight:700;
     letter-spacing:.07em;padding:1px 5px;border-radius:4px;margin-left:5px;
     background:#2B4079;color:var(--soft)}
.tag.bot{background:#3A3050;color:#C9B6E8}
.tag.quit{background:#40304A;color:#C3A9CE}

.foot{margin-top:22px;font-size:12px;color:var(--mute);text-align:center;line-height:1.6}
.foot a{color:var(--soft)}

@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .turnbanner.show .inner{opacity:1}
  .pp.rolling-now .parrow{opacity:1}
}
/* --------------------------------------------------- small phones */
@media (max-width:420px){
  body{padding-left:10px;padding-right:10px}
  .pp{padding:7px 8px;gap:7px;min-height:54px;border-radius:11px}
  .pdice{width:38px;height:38px;padding:6px}
  .pp .pname{font-size:12px}
  .pp .psub{font-size:9px}
  .pbadge{font-size:8.5px;padding:1px 5px}
  .avatar{width:28px;height:28px;font-size:11px}
  .bannerslot{height:40px}
  .boardwrap{padding:5px;border-radius:13px}
  .guide{padding:10px 12px;min-height:48px}
  .guide .big{font-size:14.5px}
  .guide .sml{font-size:11.5px}
  .rollbtn{padding:16px;font-size:17px}
  .apptitle b{font-size:13.5px}
  .apptitle small{font-size:9px;letter-spacing:.12em}
  /* On a narrow phone the match ID is what pushes "HAH-9" off the end of the
     title. The room code is what a player needs in the header; the match ID is
     on the winner's screen and in the audit trail, where staff look for it. */
  #matchLabel{display:none}
}
/* a very short screen (a small phone in landscape, or a browser with a lot
   of chrome): keep the board inside the viewport rather than off the bottom */
@media (max-height:680px){
  .boardwrap{max-width:min(100%,52vh)}
  .bannerslot{height:36px}
}
