:root{
  --bg:#0b0d14; --panel:#151a2a; --panel2:#1d2338; --line:#2c3550;
  --ink:#e8ecf7; --dim:#8f9ab8; --hot:#ffcf4d; --go:#39c14e; --bad:#e8384f;
  --font:"Trebuchet MS",Verdana,system-ui,sans-serif;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  background:radial-gradient(120% 90% at 50% 0%,#182038 0%,var(--bg) 60%);
  color:var(--ink);font-family:var(--font);
  -webkit-font-smoothing:antialiased;overflow:hidden;
  touch-action:manipulation;user-select:none;-webkit-user-select:none;
}
#app{height:100%;display:flex;align-items:center;justify-content:center}

.screen{display:none;width:100%;height:100%;align-items:center;justify-content:center;padding:12px}
.screen.active{display:flex}

.panel{
  width:min(440px,100%);background:var(--panel);border:2px solid var(--line);
  border-radius:16px;padding:22px;box-shadow:0 18px 50px rgba(0,0,0,.55);
  max-height:100%;overflow:auto;
}
.logo{font-size:44px;letter-spacing:-1px;text-align:center;line-height:1}
.logo span{color:var(--hot)}
.tag{text-align:center;color:var(--dim);margin:6px 0 18px;font-size:13px}

.field{display:block;margin:12px 0}
.field span{display:block;font-size:12px;color:var(--dim);margin-bottom:5px;text-transform:uppercase;letter-spacing:1px}
input,select{
  width:100%;background:var(--panel2);border:2px solid var(--line);color:var(--ink);
  border-radius:10px;padding:11px 12px;font:inherit;font-size:16px;
}
input:focus,select:focus{outline:none;border-color:var(--hot)}

button{
  font:inherit;font-weight:700;cursor:pointer;border-radius:10px;
  border:2px solid var(--line);background:var(--panel2);color:var(--ink);
  padding:11px 16px;transition:transform .06s,filter .15s;
}
button:active{transform:translateY(2px)}
button:disabled{opacity:.45;cursor:default}
.big{width:100%;padding:14px;font-size:17px;margin-top:8px}
.primary{background:linear-gradient(#ffd964,#e8a91b);color:#241a00;border-color:#8a6400}
.primary.on{background:linear-gradient(#6ee87f,#2ea444);color:#04220c;border-color:#146b25}
.ghost{background:transparent;color:var(--dim);border-color:transparent;width:100%;margin-top:6px}
.row{display:flex;gap:8px}
.row.join input{flex:1;text-transform:uppercase;letter-spacing:6px;text-align:center;font-size:22px;font-weight:700}
.row.join button{flex:0 0 96px}
.or{text-align:center;color:var(--dim);margin:14px 0;font-size:12px;letter-spacing:2px}
.err{color:var(--bad);font-size:13px;min-height:18px;margin-top:8px;text-align:center}
.hint{color:var(--dim);font-size:12px;line-height:1.6;margin-top:14px}
.code{color:var(--hot);letter-spacing:6px}

.share{display:flex;gap:8px;margin-top:12px}
.share input{font-size:12px}
.share button{flex:0 0 auto;font-size:13px}

.seats{display:flex;align-items:center;gap:10px;margin:18px 0}
.seat{flex:1;background:var(--panel2);border:2px solid var(--line);border-radius:12px;padding:12px;text-align:center}
.seat b{display:block;font-size:16px}
.seat span{font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:1px}
.seat.ready{border-color:var(--go)}
.seat.ready span{color:var(--go)}
.seat.gone{opacity:.4}
.vs{color:var(--hot);font-weight:800}
.settings{display:flex;gap:10px}
.settings .field{flex:1}

/* ------------------------------------------------------------------ game
   Desktop-first arcade cabinet: two equal boards, mirrored, with an outer
   info rail per player and a shared scoreboard down the middle.

   Every dimension derives from --cell, which main.js recomputes from the
   viewport on every resize. That keeps one source of truth for scale, so the
   layout is genuinely fluid from 1280x720 up to 4K instead of snapping
   between breakpoints. */
#screen-game{
  flex-direction:column;padding:clamp(6px,1vh,18px);gap:clamp(4px,1vh,14px);
  justify-content:flex-start;position:relative;
  --cell:30px; --railw:150px; --centrew:120px; --gap:16px;
}
.topbar{
  width:100%;max-width:var(--arenaw,1400px);display:flex;align-items:center;
  justify-content:space-between;gap:8px;
}
.icon{padding:6px 10px;font-size:clamp(15px,1.1vw,30px);line-height:1}
.match-label{
  flex:1;text-align:center;color:var(--dim);
  font-size:clamp(12px,.95vw,28px);letter-spacing:2px;text-transform:uppercase;
}

.arena{
  flex:1;width:100%;min-height:0;
  display:flex;gap:var(--gap);align-items:center;justify-content:center;
}

/* ---- board column ---- */
.side{
  display:flex;flex-direction:column;align-items:center;
  gap:calc(var(--cell) * .16);min-height:0;
}
.nameplate{
  font-weight:800;letter-spacing:1px;color:var(--ink);
  font-size:calc(var(--cell) * .46);line-height:1.15;
  max-width:calc(var(--cell) * 6.4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  text-shadow:0 2px 0 rgba(0,0,0,.6);
}
.side.me .nameplate{color:#8ef0ff}
.side.them .nameplate{color:#ffa8ec}
/* The nuisance tray lives inside the cabinet bezel, flush above the field —
   that is where the eye already is, and it gives garbage a physical target
   for the incoming volley to slam into. */
.tray{display:block;border-radius:calc(var(--cell) * .1) calc(var(--cell) * .1) 0 0;background:#0b0e18}
.boardframe{
  position:relative;border-radius:calc(var(--cell) * .22);
  display:flex;flex-direction:column;gap:calc(var(--cell) * .07);
  padding:calc(var(--cell) * .11);
  background:linear-gradient(160deg,#39456e,#1b2138 45%,#39456e);
  box-shadow:0 18px 44px rgba(0,0,0,.65), inset 0 0 0 1px rgba(255,255,255,.06);
}
.board{
  background:#0e111c;border-radius:calc(var(--cell) * .14);
  display:block;image-rendering:auto;
}

/* ---- outer info rail ---- */
.rail{
  width:var(--railw);flex:0 0 var(--railw);
  display:flex;flex-direction:column;gap:calc(var(--cell) * .28);
  justify-content:center;
}
.pnl{
  background:linear-gradient(180deg,var(--panel2),var(--panel));
  border:2px solid var(--line);border-radius:calc(var(--cell) * .34);
  padding:calc(var(--cell) * .26) calc(var(--cell) * .22);
  text-align:center;box-shadow:0 8px 22px rgba(0,0,0,.45);
}
.pnl small{
  display:block;font-size:clamp(9px,calc(var(--cell) * .24),24px);
  color:var(--dim);letter-spacing:2px;text-transform:uppercase;margin-bottom:3px;
}
.pnl.next canvas{display:block;margin:0 auto}
.pnl.score b{
  display:block;color:var(--hot);font-variant-numeric:tabular-nums;
  font-size:clamp(15px,calc(var(--cell) * .55),76px);line-height:1.1;
}
.pnl.chain b{
  display:block;color:#8ef0ff;font-size:clamp(15px,calc(var(--cell) * .6),82px);
  line-height:1.1;transition:color .12s;
}
.pnl.chain{transition:border-color .18s,box-shadow .18s}
.pnl.chain.hot{border-color:currentColor;box-shadow:0 0 22px -2px currentColor}
.pnl.chain.bump b{animation:chainbump .42s cubic-bezier(.2,1.7,.4,1)}
@keyframes chainbump{
  0%{transform:scale(2.1) rotate(-6deg)}
  55%{transform:scale(.92) rotate(2deg)}
  100%{transform:scale(1) rotate(0)}
}

/* ---- centre scoreboard ---- */
.centre{
  width:var(--centrew);flex:0 0 var(--centrew);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:calc(var(--cell) * .3);text-align:center;
}
.tally{
  display:flex;align-items:baseline;gap:calc(var(--cell) * .16);
  font-weight:900;line-height:1;
}
.tally b{font-size:clamp(24px,calc(var(--cell) * 1),140px);color:var(--hot)}
.tally b:last-of-type{color:#ffa8ec}
.tally b:first-of-type{color:#8ef0ff}
.tally i{font-style:normal;color:var(--dim);font-size:clamp(16px,calc(var(--cell) * .55),70px)}
.vsbadge{
  font-weight:900;letter-spacing:3px;color:#0b0d14;
  background:linear-gradient(#ffd964,#e8a91b);
  border-radius:999px;padding:calc(var(--cell) * .14) calc(var(--cell) * .5);
  font-size:clamp(11px,calc(var(--cell) * .36),44px);
  box-shadow:0 6px 18px rgba(0,0,0,.5);
}
.firstto{
  color:var(--dim);font-size:clamp(9px,calc(var(--cell) * .28),26px);
  letter-spacing:1px;line-height:1.4;
}

/* ---- fx overlay ---- */
/* width/height are mandatory: <canvas> is a replaced element, so `inset:0`
   alone leaves it at its 300x150 intrinsic size. */
.fxlayer{
  position:absolute;left:0;top:0;width:100%;height:100%;
  pointer-events:none;z-index:6;display:block;
}

.touchpad{position:fixed;inset:auto 0 0 0;height:110px;display:none;z-index:5}
.touchpad.on{display:flex}
.tzone{flex:1;opacity:.06;background:#fff;border-left:1px solid rgba(255,255,255,.08)}
.tzone:active{opacity:.2}

.overlay{position:fixed;inset:0;background:rgba(6,8,14,.86);display:flex;align-items:center;justify-content:center;z-index:20;padding:16px}
.overlay.hidden{display:none}
.obox{background:var(--panel);border:2px solid var(--line);border-radius:16px;padding:26px;text-align:center;width:min(400px,100%)}
.obox h2{font-size:28px;margin-bottom:8px}
.obox p{color:var(--dim);font-size:14px;line-height:1.6}
.orow{margin-top:16px}
.hidden{display:none !important}

.countdown{
  position:fixed;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:min(28vw,180px);font-weight:900;color:var(--hot);z-index:15;
  text-shadow:0 8px 0 rgba(0,0,0,.5);pointer-events:none;
}
.countdown.hidden{display:none}
.countdown.pulse{animation:pop .45s ease-out}
@keyframes pop{from{transform:scale(1.8);opacity:0}to{transform:scale(1);opacity:1}}

/* Portrait phones: the boards need every pixel of width, so the rails collapse
   into short horizontal strips tucked under each board and the centre
   scoreboard becomes a thin divider. */
@media (max-width:760px){
  /* Two equal boards on a phone are inherently width-bound, so centre the
     whole composition rather than letting it hang off the top. */
  .arena{gap:4px;align-items:center}
  .nameplate{font-size:12px;max-width:none}
  .rail{
    position:absolute;bottom:118px;width:auto;flex:none;flex-direction:row;
    gap:5px;align-items:stretch;
  }
  .rail-me{left:6px}
  .rail-them{right:6px}
  .pnl{padding:3px 7px;display:flex;flex-direction:column;justify-content:center;border-width:1px}
  .pnl small{font-size:8px;letter-spacing:1px;margin:0}
  .pnl.score b{font-size:13px}
  .pnl.chain{display:none}
  .centre{width:auto;flex:0 0 auto;gap:6px}
  .tally b{font-size:20px}
  .vsbadge{font-size:10px;padding:2px 7px}
  .firstto{display:none}
}

/* ==========================================================================
   HOME — the front door.

   Design intent: an arcade attract-mode screen, not a landing page. The
   identity is the game's own art (real drawPuyo() blobs on #bgBlobs and the
   fused four-blob mark next to the wordmark), the accent is the cabinet amber
   already used in-game, and the lobby browser is the loudest object on the
   page because it is the only thing anyone actually came here to use.

   Everything below is scoped under #screen-home / .home so the battle screen
   is untouched.
   ========================================================================== */

:root{
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  --ember:#ff7a3d;
  --card:#12141d;
  --cardline:#242a3d;
}

#screen-home{
  position:relative;overflow:hidden;
  align-items:stretch;justify-content:stretch;padding:0;
  /* Warm ember wash from the lower left + a cooler ceiling. Deliberately not
     a diagonal violet hero: the whole page reads as one lit room. */
  background:
    radial-gradient(70% 55% at 8% 108%, rgba(255,122,61,.16), transparent 70%),
    radial-gradient(55% 45% at 92% -8%, rgba(255,207,77,.10), transparent 70%),
    #0a0b10;
}
/* The footer copy is deliberately quiet, so a bright blob drifting behind it
   would swallow it. This fade lives on the screen, not inside .home, so it
   spans the full viewport instead of stopping at the content column's edge.
   It paints after .bg-blobs (same z-index, later in the DOM) and below .home. */
#screen-home::after{
  content:"";position:absolute;left:0;right:0;bottom:0;
  height:clamp(120px,20vh,200px);z-index:0;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(5,6,10,.94) 62%);
}

.bg-blobs{
  position:absolute;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;
  /* Punch a hole through the middle of the field so the blobs frame the
     content rather than drifting across the wordmark, the lobby list and the
     footer. This is the difference between a composed screen and stickers. */
  -webkit-mask-image:radial-gradient(122% 104% at 50% 48%,
    transparent 0%, transparent 45%, #000 86%);
  mask-image:radial-gradient(122% 104% at 50% 48%,
    transparent 0%, transparent 45%, #000 86%);
}

.home{
  position:relative;z-index:1;
  width:100%;height:100%;overflow-y:auto;overscroll-behavior:contain;
  /* Explicit: setting only overflow-y computes overflow-x to `auto`, and the
     full-bleed footer plate plus the rows' 2px hover shift are enough to
     summon a horizontal scrollbar nobody asked for. */
  overflow-x:hidden;
  display:flex;flex-direction:column;gap:clamp(18px,3vh,34px);
  padding:clamp(20px,4vh,48px) clamp(16px,4vw,40px);
  max-width:1140px;margin:0 auto;
  font-family:var(--sans);
}
/* A hairline of dot-matrix over the whole thing — the only "texture" on the
   page, and it comes from the arcade, not from a stock pattern library. */
.home::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background-image:radial-gradient(rgba(255,255,255,.055) 1px, transparent 1px);
  background-size:4px 4px;
  mask-image:linear-gradient(180deg,rgba(0,0,0,.9),transparent 75%);
}

/* ---------------------------------------------------------------- brand --- */
.brand{display:flex;align-items:center;gap:clamp(12px,2vw,26px);flex-wrap:wrap}
.logo-mark{
  width:clamp(78px,8.4vw,116px);height:clamp(78px,8.4vw,116px);
  flex:0 0 auto;display:block;
  filter:drop-shadow(0 10px 22px rgba(0,0,0,.6));
}
.wordmark{
  font-family:var(--sans);font-weight:900;
  font-size:clamp(42px,8.4vw,96px);line-height:.86;letter-spacing:-.045em;
  color:var(--ink);text-transform:uppercase;
  text-shadow:0 5px 0 rgba(0,0,0,.55);
}
.wordmark em{
  font-style:normal;
  color:var(--hot);
  /* A second hard shadow in ember gives the amber half a printed, two-plate
     look — cheap 90s arcade signage, no gradient text. */
  text-shadow:0 5px 0 rgba(0,0,0,.55), 3px 0 0 rgba(255,122,61,.35);
}
.kicker{
  font-family:var(--mono);font-size:clamp(10px,1.05vw,13px);
  letter-spacing:.24em;text-transform:uppercase;color:var(--dim);
  margin-top:10px;
}

/* ----------------------------------------------------------------- grid --- */
.home-grid{
  display:grid;gap:clamp(14px,1.8vw,22px);
  grid-template-columns:minmax(260px,360px) minmax(0,1fr);
  align-items:stretch;flex:1;min-height:0;
}
/* The settings card is only as tall as its contents; the browser takes the
   rest of the page, so the fold never ends in a band of empty background. */
.card-start{align-self:start}
@media (max-width:900px){ .home-grid{grid-template-columns:1fr} }

.card{
  background:var(--card);
  border:1px solid var(--cardline);
  border-radius:14px;
  padding:clamp(16px,2vw,24px);
  position:relative;
  box-shadow:0 24px 60px -20px rgba(0,0,0,.9), inset 0 1px 0 rgba(255,255,255,.045);
}
.card-browse{padding-bottom:14px;display:flex;flex-direction:column;min-height:min(360px,55vh)}
/* One amber rule across the top of the browser — the page's single pointer at
   where to look first. */
.card-browse::before{
  content:"";position:absolute;left:14px;right:14px;top:-1px;height:2px;
  background:linear-gradient(90deg,var(--hot),rgba(255,122,61,.5) 60%,transparent);
  border-radius:2px;
}

.card-title{
  font-size:clamp(13px,1.15vw,15px);font-weight:800;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink);
  display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  margin-bottom:16px;
}
.card-title i{
  font-style:normal;font-family:var(--mono);font-weight:400;
  font-size:11px;letter-spacing:.1em;color:var(--dim);text-transform:none;
}
.card-title i b{color:var(--hot);font-weight:700}

/* ------------------------------------------------------------- controls --- */
.card .field{margin:0 0 16px}
.card .field > span{
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;
  color:var(--dim);text-transform:uppercase;display:block;margin-bottom:7px;
}
.card input{
  background:#0c0e16;border:1px solid var(--cardline);border-radius:9px;
  padding:12px 13px;font-size:15px;font-family:var(--sans);font-weight:600;
  color:var(--ink);width:100%;transition:border-color .15s,box-shadow .15s;
}
.card input::placeholder{color:#5b6482;font-weight:400}
.card input:focus{outline:none;border-color:var(--hot);box-shadow:0 0 0 3px rgba(255,207,77,.14)}
.field-note{font-family:var(--mono);font-size:10px;color:#69718c;margin-top:7px;letter-spacing:.04em}

.seg{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.seg-tight{grid-template-columns:repeat(5,1fr)}
.seg button{
  background:#0c0e16;border:1px solid var(--cardline);border-radius:9px;
  color:var(--dim);padding:9px 4px;font-family:var(--sans);
  font-size:17px;font-weight:800;line-height:1.1;
  display:flex;flex-direction:column;align-items:center;gap:3px;
  transition:color .14s,border-color .14s,background .14s;
}
.seg button i{
  font-style:normal;font-family:var(--mono);font-weight:400;
  font-size:9px;letter-spacing:.12em;text-transform:uppercase;opacity:.8;
}
.seg button:hover{color:var(--ink);border-color:#3a4363}
.seg button.on{
  color:#1a1200;border-color:var(--hot);
  background:linear-gradient(180deg,#ffdc74,#f0b32a);
}
.seg button:active{transform:translateY(1px)}

.cfg-preview{display:flex;align-items:center;gap:10px;margin:2px 0 18px}
#cfgPreview{height:26px;display:block}
.cfg-preview span{
  font-family:var(--mono);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:#5b6482;
}

.btn-hero{
  width:100%;border:none;border-radius:10px;
  background:linear-gradient(180deg,#ffdc74,#eda718);
  color:#241900;font-family:var(--sans);font-weight:900;
  font-size:16px;letter-spacing:.06em;text-transform:uppercase;
  padding:15px;cursor:pointer;
  box-shadow:0 5px 0 #8a5f00, 0 16px 34px -12px rgba(255,180,40,.6);
  transition:transform .07s,box-shadow .07s,filter .15s;
}
.btn-hero:hover{filter:brightness(1.06)}
.btn-hero:active{transform:translateY(4px);box-shadow:0 1px 0 #8a5f00}

.btn-line{
  background:transparent;border:1px solid #3a4363;border-radius:8px;
  color:var(--ink);font-family:var(--mono);font-size:11px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;padding:9px 15px;cursor:pointer;
  transition:border-color .15s,color .15s,background .15s;
}
.btn-line:hover{border-color:var(--hot);color:var(--hot);background:rgba(255,207,77,.06)}

/* ----------------------------------------------------------- feed state --- */
.browse-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.browse-head .card-title{margin-bottom:16px}
.feed{
  display:inline-flex;align-items:center;gap:7px;flex:0 0 auto;
  font-family:var(--mono);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dim);
  border:1px solid var(--cardline);border-radius:999px;padding:5px 11px 5px 9px;
}
.feed i{width:6px;height:6px;border-radius:50%;background:#5b6482;display:block}
.feed[data-state="live"]{color:var(--go);border-color:rgba(57,193,78,.35)}
.feed[data-state="live"] i{background:var(--go);animation:feedpulse 2s ease-in-out infinite}
.feed[data-state="down"]{color:var(--bad);border-color:rgba(232,56,79,.35)}
.feed[data-state="down"] i{background:var(--bad)}
@keyframes feedpulse{
  0%,100%{box-shadow:0 0 0 0 rgba(57,193,78,.55)}
  70%{box-shadow:0 0 0 6px rgba(57,193,78,0)}
}

/* ---------------------------------------------------------- lobby cards --- */
.lobbies{list-style:none;margin:0 -6px;flex:1;min-height:0;overflow-y:auto;overflow-x:hidden}
.lobbies::-webkit-scrollbar{width:8px}
.lobbies::-webkit-scrollbar-thumb{background:#242a3d;border-radius:99px}

.lobby{
  position:relative;display:grid;
  /* The chip strip's width tracks the colour count (3 chips vs 5), so an
     `auto` column would start every host name at a different x. Pinning it to
     the 5-chip width keeps the list on a single left edge. */
  grid-template-columns:110px minmax(0,1fr) auto auto;
  align-items:center;gap:14px;
  padding:13px 14px;border-radius:10px;cursor:pointer;
  border:1px solid transparent;
  transition:background .14s,border-color .14s,transform .14s,opacity .2s;
}
.lobby + .lobby{box-shadow:0 -1px 0 rgba(255,255,255,.05)}
.lobby::before{
  content:"";position:absolute;left:0;top:12px;bottom:12px;width:3px;
  border-radius:99px;background:var(--hot);
  transform:scaleY(0);transform-origin:center;transition:transform .16s;
}
.lobby:hover,.lobby:focus-visible{
  background:#181b27;border-color:#2c3450;outline:none;transform:translateX(2px);
}
.lobby:hover::before,.lobby:focus-visible::before{transform:scaleY(1)}
.lobby:active{transform:translateX(2px) scale(.995)}

.lobby-chips{height:22px;display:block;opacity:.92}
.lobby-main{min-width:0}
.lobby-host{
  display:block;font-size:17px;font-weight:800;color:var(--ink);
  letter-spacing:-.01em;line-height:1.2;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.lobby-meta{display:flex;gap:6px;margin-top:5px;overflow:hidden}
.tag{
  font-family:var(--mono);font-size:10px;letter-spacing:.06em;
  color:#8a93b2;background:#0c0e16;border:1px solid #232941;
  border-radius:5px;padding:2px 6px;white-space:nowrap;
}

.lobby-side{text-align:right;flex:0 0 auto}
.lobby-code{
  display:block;font-family:var(--mono);font-size:14px;font-weight:700;
  color:var(--hot);letter-spacing:.22em;
}
.lobby-age{
  display:block;font-family:var(--mono);font-size:10px;color:#5b6482;
  margin-top:4px;letter-spacing:.06em;white-space:nowrap;
}
.lobby-go{
  font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.18em;
  color:#1a1200;background:var(--hot);border-radius:6px;padding:7px 10px;
  opacity:0;transform:translateX(-6px);transition:opacity .16s,transform .16s;
}
.lobby:hover .lobby-go,.lobby:focus-visible .lobby-go{opacity:1;transform:none}

/* Enter/leave: rows slide in from the right as they are announced, and fade
   down when a lobby fills. Keyed reconciliation in home.js means only the row
   that actually changed animates. */
.lobby.enter{opacity:0;transform:translateX(14px)}
.lobby.leaving{opacity:0;transform:scale(.97);pointer-events:none}

.empty{
  text-align:center;padding:24px 12px;flex:1;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
}
.empty.hidden{display:none !important}
.empty-big{font-size:19px;font-weight:800;color:#7d87a6;letter-spacing:-.01em}
.empty-small{
  font-family:var(--mono);font-size:11px;color:#5b6482;
  margin:8px 0 18px;letter-spacing:.04em;
}

.card-browse .err{
  margin-top:10px;min-height:0;height:0;overflow:hidden;
  font-family:var(--mono);font-size:11px;letter-spacing:.05em;
  color:var(--bad);transition:height .18s,margin .18s;
}
.card-browse .err.show{height:auto;min-height:18px;margin-top:12px}

/* ----------------------------------------------------------------- foot --- */
.home-foot{
  display:flex;align-items:center;justify-content:space-between;
  gap:16px;flex-wrap:wrap;padding-top:4px;
}
/* The footer text is deliberately quiet, which means a bright blob drifting
   behind it would swallow it. Fade the page to solid underneath. */

.keys{font-family:var(--mono);font-size:10.5px;color:#5b6482;letter-spacing:.05em;line-height:1.9}
kbd{
  font-family:var(--mono);font-size:10px;color:var(--ink);
  background:#161a26;border:1px solid #2c3450;border-bottom-width:2px;
  border-radius:4px;padding:1px 5px;margin-right:2px;
}
.codejoin{display:flex;align-items:center;gap:8px}
.codejoin label{
  font-family:var(--mono);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:#5b6482;
}
#codeInput{
  width:88px;background:#0c0e16;border:1px solid var(--cardline);border-radius:8px;
  color:var(--hot);font-family:var(--mono);font-size:14px;font-weight:700;
  letter-spacing:.28em;text-align:center;text-transform:uppercase;padding:9px 6px;
}
#codeInput:focus{outline:none;border-color:var(--hot)}

@media (max-width:640px){
  .home-foot{flex-direction:column-reverse;align-items:stretch}
  .codejoin{justify-content:space-between}
  .keys{text-align:center}
  .lobby{grid-template-columns:92px minmax(0,1fr) auto;gap:11px}
  .lobby-chips{height:18px}
  /* No room for both tags, and truncating one mid-word hides the match
     length entirely. The chips already say how many colours; keep the fact
     they can't infer. */
  .lobby-meta .tag:first-child{display:none}
  .lobby-go{display:none}
  .lobbies{max-height:none}
}

@media (prefers-reduced-motion:reduce){
  .lobby,.lobby-go,.lobby::before,.feed i{transition:none;animation:none}
  .lobby.enter{opacity:1;transform:none}
}
