/* Gauntlet of Gods - stylesheet.
   Split out of index.html: a single 365KB page with everything inline is both awkward to edit
   and the exact shape heuristic virus scanners flag (no external references, long embedded
   base64). External files also cache between loads. */

@font-face{ font-family:'BluuNext'; src:url('fonts/BluuNext-Bold.otf') format('opentype'); font-weight:700; font-display:swap; }
@font-face{ font-family:'ThestralNeue'; src:url('fonts/ThestralNeue-Bold.otf') format('opentype'); font-weight:700; font-display:swap; }
@font-face{ font-family:'MoltenDisplay'; src:url('fonts/Molten_Display.otf') format('opentype'); font-weight:400; font-display:swap; }
@font-face{ font-family:'Sunday Masthead'; src:url('fonts/SundayMasthead-Regular.otf') format('opentype'); font-weight:400; font-display:swap; }
@font-face{ font-family:'DM Sans'; src:url('fonts/DMSans-Bold.ttf') format('truetype'); font-weight:700; font-display:swap; }
/* THEME — edit these vars */
:root{
  --bg:#0b0806; --felt:#1b1510; --felt2:#130d09;
  --ink:#f0e7d6; --muted:#9d9079; --line:#3c3020;
  --gold:#caa148; --accent:#6fa6b2; --danger:#bd3e27;
  --p1:#7fb0bc; --p2:#d8a23a;
  --ember:#d4622a; --bronze:#8a6a3a;
  --card-r:10px;
  --display:'BluuNext',serif;
  --font:'ThestralNeue',system-ui,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,monospace;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
html,body{height:100%;margin:0;overflow:hidden;overscroll-behavior:none;}
body{
  font-family:var(--font); color:var(--ink);
  background:
    radial-gradient(75% 45% at 50% -6%, rgba(190,72,30,.20), transparent 62%),
    radial-gradient(120% 85% at 50% 2%, #251a11 0%, var(--bg) 58%),
    var(--bg);
  user-select:none; -webkit-user-select:none; touch-action:manipulation;
}
.app{display:flex; height:100%; }

/* main board column */
.main{flex:1; display:flex; flex-direction:column; padding:8px 12px; gap:4px; min-width:0;}
/* Gameboard art. */
.main{ position:relative; }
.main.has-board::before{ content:''; position:absolute; inset:0; z-index:0; pointer-events:none;
  background-image:var(--boardimg); background-size:cover; background-position:center;
  background-repeat:no-repeat; }
/* (banner: no longer rotated or repositioned — see SEAT MIRRORING below. */
.main > *{ position:relative; z-index:1; }   /* keep gameplay above the board art */

.pinfo{display:flex; align-items:center; gap:12px; padding:2px 4px; font-size:13px;}
.pinfo .name{font-weight:900; letter-spacing:.5px; text-transform:uppercase; font-size:13px;}
.pinfo.p1 .name{color:var(--p1);} .pinfo.p2 .name{color:var(--p2);}
.life{font-family:var(--mono); font-weight:700; font-size:20px; display:flex; align-items:center; gap:6px;}
.life .heart{color:var(--danger);}
.pname{font-family:'Cinzel',serif; font-weight:700; font-size:19px; color:#e9d9b3; letter-spacing:.04em;
  max-width:240px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  display:inline-flex; align-items:center; justify-content:center; min-height:34px; box-sizing:border-box;
  padding:0 16px; border-radius:12px; line-height:1;
  background:radial-gradient(120% 130% at 50% 50%, rgba(202,161,72,.08), transparent 70%), rgba(8,11,16,.62);
  -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
  border:1px solid var(--line); box-shadow:0 6px 16px rgba(0,0,0,.5); text-shadow:0 1px 3px rgba(0,0,0,.8);}
.pill{font-family:var(--mono); font-size:11px; color:var(--muted); background:#0e1620; border:1px solid var(--line); padding:2px 8px; border-radius:999px;}
.turnflag{margin-left:auto; font-weight:700; font-size:12px; color:var(--gold);}

/* hand (OUTSIDE the play area) */
.handzone{border-radius:12px; padding:2px 6px; transition:background .15s, box-shadow .15s;}
/* TURN GLOW Whose turn it is has */
/* The glow lives on the whole DOCK — the full-width row holding your life, your hand and your */
.dock{position:relative;}
.dock.turn::before,
.dock.turn::after{ content:''; position:absolute; left:0; right:0; top:-14px; bottom:-14px;
  pointer-events:none; z-index:0;
  /* Feather both horizontal ends to nothing, so the glow dissolves well before it reaches */
  /* Feather ALL edges to nothing (not just left/right): the radial ellipse fades the top, bottom */
  -webkit-mask-image:radial-gradient(78% 78% at 50% 55%, #000 0%, transparent 62%);
          mask-image:radial-gradient(78% 78% at 50% 55%, #000 0%, transparent 62%); }
/* Layer 1: the dancing light — two offset radial pools drifting on their own cycles */
.dock.turn::before{
  background:
    radial-gradient(46% 140% at 22% 50%, var(--tg-a) 0%, transparent 72%),
    radial-gradient(44% 130% at 50% 50%, var(--tg-b) 0%, transparent 70%),
    radial-gradient(46% 140% at 78% 50%, var(--tg-a) 0%, transparent 72%);
  animation:turnDrift 6.5s ease-in-out infinite;
  filter:blur(20px);}
/* Layer 2: the faint particle field — a few soft specks on a slow vertical drift. */
.dock.turn::after{
  background-image:
    radial-gradient(2px 2px     at 6% 72%,  var(--tg-p) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 14% 34%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(1px 1px     at 23% 82%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(2.5px 2.5px at 33% 46%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(1px 1px     at 41% 24%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 52% 76%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(2px 2px     at 63% 38%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(1px 1px     at 71% 68%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 82% 28%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(2px 2px     at 90% 60%, var(--tg-p) 50%, transparent 51%),
    radial-gradient(1px 1px     at 96% 40%, var(--tg-p) 50%, transparent 51%);
  animation:turnMotes 7s linear infinite;
  opacity:.6;}
/* STRANDS: flowing vertical energy tendrils. */
/* SHALLOW ARC STRANDS: an SVG of a few wide, shallow arcs (a low dome across the dock) */
.dock .turnstrands{ position:absolute; left:0; right:0; top:-14px; bottom:-14px; z-index:0;
  pointer-events:none; overflow:hidden; opacity:0; display:block; }
.dock.turn .turnstrands{ opacity:.9; }   /* only visible on the active turn; always absolute so it never shifts layout */
/* Mask = two corner pools on whichever side is AWAY from the board (the outer edge). */
.app.seat0 .dock-bot.turn .turnstrands,
.app.seat1 .dock-top.turn .turnstrands{   /* visually BOTTOM dock -> pool low */
  -webkit-mask-image:radial-gradient(44% 100% at 20% 116%, #000 20%, transparent 66%),
                     radial-gradient(44% 100% at 80% 116%, #000 20%, transparent 66%);
          mask-image:radial-gradient(44% 100% at 20% 116%, #000 20%, transparent 66%),
                     radial-gradient(44% 100% at 80% 116%, #000 20%, transparent 66%); }
.app.seat0 .dock-top.turn .turnstrands,
.app.seat1 .dock-bot.turn .turnstrands{   /* visually TOP dock -> pool high */
  -webkit-mask-image:radial-gradient(44% 100% at 20% -16%, #000 20%, transparent 66%),
                     radial-gradient(44% 100% at 80% -16%, #000 20%, transparent 66%);
          mask-image:radial-gradient(44% 100% at 20% -16%, #000 20%, transparent 66%),
                     radial-gradient(44% 100% at 80% -16%, #000 20%, transparent 66%); }
.dock.turn .turnstrands svg{ position:absolute; inset:0; width:100%; height:100%; }
/* Top dock is at the TOP of the board, so its energy should mirror vertically — arc toward */
/* Vertical flip = bow toward the board. */
.app.seat0 .dock-top.turn .turnstrands svg,
.app.seat1 .dock-bot.turn .turnstrands svg{ transform:scaleY(-1); }
/* Horizontal flip = flow direction. */
.app.seat0 .dock-top.turn .turnstrands svg{ transform:scale(-1,-1); }
.app.seat1 .dock-bot.turn .turnstrands svg{ transform:scale(-1,-1); }
.app.seat1 .dock-top.turn .turnstrands svg{ transform:scaleX(-1); }
.app.seat0 .dock-bot.turn .turnstrands svg{ transform:none; }
/* (top-dock mask now handled by the seat-aware rules above) */
.dock.turn .turnstrands path{ fill:none; stroke:var(--tg-strand, rgba(255,214,120,.5));
  stroke-linecap:round; filter:blur(2.1px); }
.dock.turn .turnstrands .a1{ stroke-width:2.4; opacity:.9; }
.dock.turn .turnstrands .a2{ stroke-width:1.8; opacity:.6; }
.dock.turn .turnstrands .a3{ stroke-width:2;   opacity:.45; }
.dock.turn .turnstrands .a4{ stroke-width:1.6; opacity:.42; }
.dock.turn .turnstrands .a5{ stroke-width:1.4; opacity:.3; }
.dock > *:not(.turnstrands){ position:relative; z-index:1; }   /* life, hand, buttons all above the glow (strands stay behind at z0) */

/* YOUR turn: gold, and a touch stronger — it's the one you must not miss. */
.dock.turn.self{ --tg-a:rgba(232,198,107,.34); --tg-b:rgba(202,161,72,.24); --tg-p:rgba(255,238,180,.65); --tg-strand:rgba(255,214,120,.5); }
/* THEIR turn: orange, dimmer — informative, not competing for attention. */
.dock.turn:not(.self){ --tg-a:rgba(138,110,235,.28); --tg-b:rgba(120,90,225,.2); --tg-p:rgba(200,180,255,.56); --tg-strand:rgba(170,130,245,.5); }

/* Drift mostly VERTICALLY and via scale — horizontal travel is what dragged the glow's edge */
@keyframes turnDrift{
  0%,100%{ transform:translate3d(-1%,1%,0)  scale(1);    opacity:.82; }
  33%    { transform:translate3d(1%,-2%,0)  scale(1.05); opacity:1;   }
  66%    { transform:translate3d(0,2%,0)    scale(.98);  opacity:.8;  }
}
@keyframes turnMotes{
  0%  { background-position:0 0,0 0,0 0,0 0,0 0,0 0; opacity:0; }
  12% { opacity:.75; }
  88% { opacity:.75; }
  100%{ background-position:0 -26px,0 -34px,0 -22px,0 -40px,0 -28px,0 -36px; opacity:0; }
}
/* The life box gets the same treatment, so the cue reads even if you're looking at the score */
.life.big{ position:relative; }
.life.big.turnlit::before{ content:''; position:absolute; inset:-6px; border-radius:18px; z-index:0;
  pointer-events:none; filter:blur(8px);
  background:radial-gradient(70% 120% at 30% 55%, var(--tg-a) 0%, transparent 65%),
             radial-gradient(60% 110% at 72% 45%, var(--tg-b) 0%, transparent 62%);
  animation:turnDrift 5.5s ease-in-out infinite; }
.life.big.turnlit > *{ position:relative; z-index:1; }
.life.big.turnlit.self{ --tg-a:rgba(232,198,107,.37); --tg-b:rgba(202,161,72,.26); }
.life.big.turnlit:not(.self){ --tg-a:rgba(96,170,235,.29); --tg-b:rgba(120,190,245,.19); }

/* Volley target: the enemy life box takes the SAME .tgtmark treatment the enemy card gets (dark */
/* Volley target on the life box: mirror the ENEMY CARD exactly — same dark scrim, same glyph */
/* Volley target on the life box. */
.life.big.lifetarget{ cursor:pointer; }
.life.big.lifetarget > .lifenum,
.life.big.lifetarget > .lifenum{ opacity:.28; transition:opacity .15s; }   /* dim number under the volley mark */
.life.big .volleylife{ position:absolute; inset:0; z-index:40; border-radius:16px;
  display:flex; align-items:center; justify-content:center;
  background:rgba(6,12,20,.6); pointer-events:none;
  box-shadow:0 0 0 2px rgba(92,200,255,.95) inset, 0 0 22px rgba(92,200,255,.55);
  animation:volleyLifePulse 1.1s ease-in-out infinite; }
.life.big .volleylife img{ width:50px; height:50px; object-fit:contain; filter:none;
  filter:drop-shadow(0 0 8px rgba(92,200,255,.9)); }
.life.big .volleylife .g{ font-size:40px; line-height:1; color:#cdecff; text-shadow:0 0 10px rgba(92,200,255,.9); }
@keyframes volleyLifePulse{ 0%,100%{ box-shadow:0 0 0 2px rgba(92,200,255,.7) inset, 0 0 16px rgba(92,200,255,.4); }
  50%{ box-shadow:0 0 0 2px rgba(92,200,255,1) inset, 0 0 30px rgba(92,200,255,.75); } }
/* Respect a reduced-motion preference: keep the colour cue, drop the dancing. */
@media (prefers-reduced-motion: reduce){
  .dock.turn::before,.dock.turn::after,.life.big.turnlit::before{ animation:none; }
}
.hand{display:flex; gap:8px; padding:4px 2px; min-height:187px; align-items:center; overflow:visible;}
/* Arched hand: --rest carries each card's fan transform. */
.hand .card.inhand{ transform:var(--rest, none); transform-origin:50% 90%;
  transition:transform .22s ease-out; will-change:transform; }
.hand .card.inhand.lifts{
  --lift:0px; --liftScale:1;
  transform:translateY(calc(var(--rest-rise, 0px) - var(--lift))) rotate(var(--rest-rot, 0deg)) scale(var(--liftScale));
  transition:transform .12s ease-out; }
/* Crowded hand (6+ cards): overlap so the row never grows wider than its dock slot. */
.hand.crowded{gap:0; overflow:visible;}
.hand.crowded .card{margin-left:calc(-1 * var(--ov, 0px));}
.hand.crowded .card:first-child{margin-left:0;}
.hand.dim{opacity:1; filter:grayscale(.8) brightness(.55);}
.hand .empty{color:var(--muted); font-size:12px; font-family:var(--mono);}

/* PLAY AREA: deck | 2x4 grid | discard */
.playarea{flex:1; position:relative; display:flex; align-items:stretch; gap:12px; min-height:0;
  border:1px solid var(--line); border-radius:16px; padding:12px;
  background:
    radial-gradient(120% 130% at 50% 50%, rgba(70,194,168,.05), transparent 70%),
    repeating-linear-gradient(45deg, rgba(255,255,255,.012) 0 12px, transparent 12px 24px),
    var(--felt2);
}
.grid{flex:1; position:relative; display:grid; grid-template-columns:repeat(4,1fr); grid-template-rows:1fr 1fr; gap:10px; min-height:0;}

/* Board tilt — always on (body.tilt is added at boot). A shallow tabletop. */
body.tilt .playarea{ transform:perspective(1500px) rotateX(var(--tilt, 18deg)) translateY(var(--tilt-shift, -34px)); transform-origin:50% 100%; transition:transform .3s ease; }
.grid .midline{position:absolute; left:-4px; right:-4px; top:50%; height:0;
  border-top:1.5px dashed rgba(232,198,107,.4); transform:translateY(-0.5px); pointer-events:none;}

/* AFK rope A glowing line along */
/* "Opponent is deciding" banner: fades in over the opponent's board row whenever the game */
#oppthinking{ position:absolute; top:22%; left:50%; transform:translate(-50%,-6px);
  z-index:60; pointer-events:none; display:flex; align-items:center; gap:10px;
  padding:8px 16px; border-radius:12px;
  background:rgba(12,17,24,.82); border:1px solid rgba(150,190,240,.35);
  box-shadow:0 6px 22px rgba(0,0,0,.5), 0 0 22px rgba(96,160,230,.16);
  backdrop-filter:blur(3px);
  opacity:0; transition:opacity .35s ease, transform .35s ease; }
#oppthinking.show{ opacity:1; transform:translate(-50%,0); }
#oppthinking .ot-label{ font-family:var(--mono); font-size:12px; letter-spacing:.06em;
  text-transform:uppercase; color:#cfe0f2; }
#oppthinking .ot-dots{ display:flex; gap:4px; }
#oppthinking .ot-dots span{ width:6px; height:6px; border-radius:50%;
  background:#7fb2ec; animation:otDot 1.2s ease-in-out infinite; }
#oppthinking .ot-dots span:nth-child(2){ animation-delay:.18s; }
#oppthinking .ot-dots span:nth-child(3){ animation-delay:.36s; }
@keyframes otDot{ 0%,100%{ opacity:.3; transform:scale(.8); }
  50%{ opacity:1; transform:scale(1.15); } }
@media (prefers-reduced-motion: reduce){ #oppthinking .ot-dots span{ animation:none; opacity:.8; } }
/* Countdown chip beside the discard pile: fades in during the final stretch, same window */
.pile.discard{ position:relative; }
/* Countdown chip: sits at the RIGHT END OF THE MIDLINE — the empty space between the board */
/* Countdown chip: OUTSIDE the lanes, just past the grid's right edge on the midline — the mirror */
.clockchip{ position:absolute; top:50%; left:100%; margin-left:14px;
  transform:translateY(-50%) scale(.9); transform-origin:left center; z-index:40;
  font-family:var(--mono); font-size:17px; font-weight:800; letter-spacing:.04em; white-space:nowrap;
  padding:6px 13px; border-radius:11px; color:#fce9c0;
  background:rgba(10,14,20,.92); border:1px solid rgba(232,198,107,.55);
  box-shadow:0 2px 12px rgba(0,0,0,.55);
  opacity:0; pointer-events:none;
  transition:opacity .3s ease, transform .3s ease; }
.clockchip.show{ opacity:1; transform:translateY(-50%) scale(1); }
.clockchip.mine{ color:#bfe0ff; border-color:rgba(106,174,235,.6); }   /* your own clock: cooler */
.clockchip.warn{ color:#ffd9a0; border-color:rgba(232,150,70,.7); }
.clockchip.crit{ color:#ffc2c2; border-color:rgba(230,90,90,.85);
  animation:clockCritPulse .7s ease-in-out infinite; }
@keyframes clockCritPulse{ 0%,100%{ box-shadow:0 0 6px rgba(230,80,80,.4); }
  50%{ box-shadow:0 0 16px rgba(230,80,80,.9); } }
#rope{position:absolute; left:-4px; right:-4px; top:50%; height:3px; margin-top:-1.5px;
  pointer-events:none; opacity:0; transition:opacity .4s ease; z-index:6; overflow:visible;}
#rope.show{opacity:1;}
#rope .rope-fill{position:absolute; inset:0; transform-origin:50% 50%;
  transform:scaleX(1); border-radius:2px;
  background:linear-gradient(90deg, transparent, var(--rope-c,#e8c66b) 12%, var(--rope-c,#e8c66b) 88%, transparent);
  box-shadow:0 0 10px var(--rope-c,#e8c66b), 0 0 22px color-mix(in srgb, var(--rope-c,#e8c66b) 55%, transparent);}
/* Drains from both ends toward the middle — reads as "time closing in" and stays symmetric */
#rope.warn{--rope-c:#e0a03c;}
#rope.crit{--rope-c:#e0798c;}
#rope.crit .rope-fill{animation:ropePulse .7s ease-in-out infinite;}
@keyframes ropePulse{0%,100%{filter:brightness(1);}50%{filter:brightness(1.6);}}
/* Yours vs theirs: a subtle cue that it's YOUR clock running out. */
#rope.mine .rope-fill{box-shadow:0 0 12px var(--rope-c,#e8c66b), 0 0 28px var(--rope-c,#e8c66b);}
.lane{
  border:1.5px solid var(--line); border-radius:12px;
  display:flex; align-items:center; justify-content:center;
  position:relative; min-height:0; transition:border-color .15s,background .15s;
  background:rgba(255,255,255,.015);
}
.lane.p2{background:rgba(232,161,58,.05);}
.lane.p1{background:rgba(70,194,168,.05);}
.lane.empty.mine{border-style:dashed; border-color:#37506a;}
.lane .lanenum{position:absolute; top:4px; left:6px; font-family:var(--mono); font-size:10px; color:#3a4d60;}
.lane.drop{border-color:var(--gold)!important; border-style:solid!important; background:rgba(232,198,107,.14);}
.lane.resolving{border-color:var(--gold)!important; border-style:solid!important; box-shadow:0 0 16px rgba(232,198,107,.55); animation:pulse .7s ease-in-out infinite;}
.lane.flytarget{border-color:#5cc8ff!important; border-style:solid!important; background:rgba(92,200,255,.16); box-shadow:0 0 16px rgba(92,200,255,.55); cursor:pointer; animation:pulse .8s ease-in-out infinite;}
/* The flyer's own lane is the DECLINE option, so it gets the same solid glow and pulse as the
   lanes it could move to — dashed and dim read as 'not selectable'. */
.lane.flycurrent{border-color:#5cc8ff!important; border-style:solid!important; background:rgba(92,200,255,.16); box-shadow:0 0 16px rgba(92,200,255,.55); cursor:pointer; animation:pulse .8s ease-in-out infinite;}
.lane .flylabel{position:absolute; bottom:5px; left:0; right:0; text-align:center; font-family:var(--mono); font-size:10px; font-weight:700; color:#bfe9ff; text-shadow:0 1px 2px rgba(0,0,0,.8); pointer-events:none;}
@keyframes pulse{0%,100%{box-shadow:0 0 8px rgba(232,198,107,.35);}50%{box-shadow:0 0 22px rgba(232,198,107,.8);}}

/* card */
.card{
  width:110px; height:151px; border-radius:var(--card-r);
  background:linear-gradient(160deg,#1b2735,#101a26);
  border:1px solid #2a3a4b; position:relative;
  box-shadow:0 4px 10px rgba(0,0,0,.45); cursor:grab;
  transition:transform .12s ease, box-shadow .12s;
  flex:none;
}
.card.board{cursor:pointer; position:relative; z-index:1;}
/* Guard stack: the covered card peeks out behind the Guard, offset back-and-up, so it's clear */
.lane .card.under-card{ position:absolute; z-index:0; inset:0; margin:auto;
  transform:translate(14px,-16px) scale(.92); filter:brightness(.7);
  transition:transform .16s ease, filter .16s ease; }
.lane .card.guard-top{ z-index:2; transition:transform .16s ease; }
/* Hover a Guard stack: nudge the two apart a bit more so you can eyeball each separately; dim */
.lane:hover .card.under-card{ transform:translate(26px,-26px) scale(.96); filter:brightness(.95); }
.lane .card.under-card:hover{ z-index:3; filter:brightness(1); transform:translate(30px,-30px) scale(1.02); }
.card .swatch{position:absolute; inset:0; border-radius:var(--card-r); opacity:.9;
  background:linear-gradient(160deg, var(--cc) 0%, color-mix(in srgb, var(--cc) 40%, #0a121b) 100%);}
.card .frame{position:absolute; inset:3px; border-radius:7px; border:1px solid rgba(255,255,255,.18);
  background:linear-gradient(180deg, rgba(8,12,18,.15), rgba(8,12,18,.6)); display:flex; flex-direction:column; overflow:hidden;}
.card .top{display:flex; justify-content:space-between; align-items:flex-start; padding:5px 6px 0;}
.card .pw{font-family:'Momo Trust Display','BluuNext',serif; font-weight:400; font-size:34px; line-height:1; color:#fff;
  display:block; margin-top:1px; text-shadow:0 2px 4px rgba(0,0,0,.7);}
.card .meta{display:flex; flex-direction:column; align-items:flex-end; gap:4px;}
.card .col{width:13px; height:13px; border-radius:50%; border:1px solid rgba(255,255,255,.6);}
.card .hp{font-family:var(--mono); font-size:11px; font-weight:700; color:#ffe9b0;
  background:rgba(6,10,15,.5); padding:0 4px; border-radius:5px;}
.card .mid{flex:1; position:relative;}
.card .dmg{position:absolute; left:4px; top:4px; display:flex; gap:2px; flex-wrap:wrap; justify-content:flex-start; max-width:54px; background:rgba(6,10,15,.5); padding:2px 3px; border-radius:6px;}
.card .dmg i{width:8px; height:8px; border-radius:50%; background:var(--danger); box-shadow:0 0 4px rgba(228,87,46,.85);}
.card .buff i{width:8px; height:8px; border-radius:50%; background:var(--accent); box-shadow:0 0 4px rgba(70,194,168,.85); margin:0 1px;}
.card .kw{margin-top:auto; min-height:28px; padding:3px 4px; font-size:10.5px; font-weight:900;
  text-transform:uppercase; letter-spacing:.2px; line-height:1.05; text-align:center; color:#fff;
  text-shadow:0 1px 2px rgba(0,0,0,.85); background:rgba(6,10,15,.5); border-top:1px solid rgba(255,255,255,.14);
  display:flex; align-items:center; justify-content:center; word-break:break-word;}
.card.rot{transform:rotate(90deg);}
.card.flip{transform:rotate(180deg);}
/* Freeze thaw: a just-thawed card mounts at 180 (.unflip-start) then drops that class */
.lane .card.unflipping{ transition:transform .5s cubic-bezier(.2,.8,.25,1); }
.lane .card.unflip-start{ transform:rotate(180deg); }
.card.frozen{outline:2px solid #6cc6ff; box-shadow:0 0 14px rgba(108,198,255,.6);}
.card.frozen.thawing{ animation:thawglow .6s ease-out forwards; }
.card.frozen.thawing::after, .card.frozen.thawing .frostmark{ animation:thawfade .6s ease-out forwards; }
@keyframes thawglow{ from{ outline-color:#6cc6ff; box-shadow:0 0 14px rgba(108,198,255,.6); } to{ outline-color:rgba(108,198,255,0); box-shadow:0 0 14px rgba(108,198,255,0); } }
@keyframes thawfade{ from{ opacity:1; } to{ opacity:0; } }
.card.frozen::after{content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:5;
  /* per-card randomized JAGGED ice cracks (an inline SVG pane via --frost-cracks) */
  background:var(--frost-cracks, rgba(120,200,255,.22));
  background-size:cover;
  background-blend-mode:screen;
  /* the pane is real frosted glass: it blurs and cools the ART behind it */
  backdrop-filter:blur(1.6px) saturate(.72) brightness(1.05);
  -webkit-backdrop-filter:blur(1.6px) saturate(.72) brightness(1.05);
}
/* A sheen sliding across the frost — same family as Armored's, but distinctly SLOWER
   (6.5s vs 2.6s) and BLURRIER (soft wide band + 4px blur), so it reads as light moving
   over ice rather than polished metal. */
.card.frozen::before{content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:6;
  background:linear-gradient(115deg, transparent 26%, rgba(255,255,255,.35) 42%, rgba(255,255,255,.6) 50%, rgba(255,255,255,.35) 58%, transparent 74%);
  background-size:260% 100%; background-repeat:no-repeat;
  mix-blend-mode:screen; filter:blur(4px); opacity:.8;
  animation:frostsheen 6.5s ease-in-out infinite;
}
@keyframes frostsheen{ 0%{ background-position:170% 0; } 62%{ background-position:-70% 0; } 100%{ background-position:-70% 0; } }
.card.frozen.thawing::before{ animation:none; opacity:0; }
.card .frostmark{position:absolute; inset:0; z-index:8; display:flex; align-items:center; justify-content:center; color:#e3f4ff; font-size:46px; line-height:1; filter:drop-shadow(0 0 7px rgba(108,198,255,.95)); pointer-events:none; overflow:hidden; border-radius:inherit;}
/* Cold mist: three soft blurred wisps rising off the ice, staggered so it never loops visibly. */
.card .frostmark .mist{position:absolute; left:20%; bottom:-14%; width:52%; height:34%;
  border-radius:50%; background:radial-gradient(ellipse at 50% 60%, rgba(230,246,255,.5) 0%, rgba(200,235,255,.18) 45%, transparent 72%);
  filter:blur(6px); opacity:0; mix-blend-mode:screen;}
.card .frostmark .m1{animation:mistrise 5.2s ease-in-out infinite;}
.card .frostmark .m2{left:2%; width:60%; animation:mistrise 6.8s ease-in-out 1.9s infinite;}
.card .frostmark .m3{left:42%; width:46%; animation:mistrise 6s ease-in-out 3.4s infinite;}
@keyframes mistrise{
  0%{transform:translateY(0) translateX(0) scale(.8); opacity:0;}
  18%{opacity:.5;}
  60%{opacity:.28;}
  100%{transform:translateY(-260%) translateX(12%) scale(1.25); opacity:0;}
}
@media (prefers-reduced-motion:reduce){ .card .frostmark .mist{animation:none; opacity:.2; transform:translateY(-80%);} }
.card .frostmark img{width:58%; height:58%; object-fit:contain; filter:drop-shadow(0 0 6px rgba(108,198,255,.9));}
.card.flip .frostmark{ transform:rotate(180deg) !important; }   /* card flipped 180 -> spin the frost icon back upright */
/* The Support card itself: a thin same-color (purplish-pink) border that pulsates. */
.card.supporting{ animation:suppulse 1.4s ease-in-out infinite; }
@keyframes suppulse{
  0%,100%{ box-shadow:0 0 0 1.5px rgba(255,107,214,.55), 0 0 8px rgba(200,107,255,.35); }
  50%{ box-shadow:0 0 0 1.5px rgba(255,107,214,1), 0 0 16px rgba(255,107,214,.7); }
}
.card.supported{box-shadow:0 0 0 2px rgba(255,107,214,.8), 0 0 16px rgba(200,107,255,.55);}
/* Buff to power from Support — a glowing purplish-pink "+N" centered on the card. */
.card .supbadge{position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); z-index:9; color:#fff;
  font-family:'DM Sans',var(--mono); font-weight:900; font-size:30px; line-height:1;
  text-shadow:0 0 12px rgba(255,90,210,1), 0 0 5px rgba(120,30,120,.95), 0 2px 3px rgba(0,0,0,.85);
  pointer-events:none; animation:supwaver 1.5s ease-in-out infinite;}
.card .supbadge::before{content:'+';}
@keyframes supwaver{
  0%,100%{ transform:translate(-50%,-50%) scale(1); opacity:.9; }
  50%{ transform:translate(-50%,-54%) scale(1.12); opacity:1; }
}
/* the boosted card also gets a soft pink energy aura */
.card.supported .cv-pow{ color:#ffd0f4; text-shadow:0 0 10px rgba(255,90,210,.95); }
/* Support beam: animated via requestAnimationFrame in drawSupportBeams (undulating). */
#supportbeams{ pointer-events:none; }
/* Quick: a hand card eligible for the free bonus play jitters to draw the eye. */
.card.inhand.quick-ready{ animation:quickjitter .5s ease-in-out infinite; box-shadow:0 0 0 2px rgba(150,240,255,.8), 0 0 12px 2px rgba(120,220,255,.6); }
@keyframes quickjitter{
  0%,100%{ transform:translateY(0) rotate(0deg); }
  25%{ transform:translateY(-2px) rotate(-1.4deg); }
  75%{ transform:translateY(-2px) rotate(1.4deg); }
}
/* Playable ambush cards JITTER (same tell as a Quick bonus card — motion reads much faster */
.card.inhand.ambush-ready{ box-shadow:0 0 0 2px #ffdf5e, 0 0 14px 3px rgba(255,210,70,.75); border-radius:8px;
  animation:quickjitter .5s ease-in-out infinite; }
.card.ambush-ready:not(.inhand){ box-shadow:0 0 0 2px #ffdf5e, 0 0 14px 3px rgba(255,210,70,.75); border-radius:8px; animation:ambushpulse 1.15s ease-in-out infinite; }
@keyframes ambushpulse{ 0%,100%{ box-shadow:0 0 0 2px #ffdf5e, 0 0 10px 2px rgba(255,210,70,.55);} 50%{ box-shadow:0 0 0 2px #ffe985, 0 0 20px 6px rgba(255,215,80,.95);} }
/* Trapper: hand cards over the power cap can't be played this turn. */
.card.trapped{ filter:grayscale(.7) brightness(.62); cursor:not-allowed; }
.card .trapbadge{ position:absolute; inset:0; z-index:9; display:flex; align-items:center; justify-content:center; pointer-events:none; }
.card .trapbadge img{ width:56%; height:56%; object-fit:contain; filter:drop-shadow(0 2px 6px rgba(0,0,0,.8)); }
.card .ambushbadge{position:absolute; top:4px; left:4px; width:26%; height:26%; z-index:9; pointer-events:none; filter:drop-shadow(0 0 4px rgba(255,215,80,.95));}
.card .ambushbadge img{width:100%; height:100%; object-fit:contain;}
.card .ambushbadge{display:flex; align-items:center; justify-content:center; color:#ffdf5e; font-size:16px;}
.card.dragging{opacity:.3;}
.card.dead{filter:grayscale(1) brightness(.5);}
/* Any card gliding INTO the discard reads as spent, no matter which path sent it there (combat */
.flycard.dying, .flycard.dying .card{ filter:grayscale(1) brightness(.5); }
.card .facedown{position:absolute; inset:0; border-radius:var(--card-r);
  background:var(--cardback, url(CardBack.png)) center/cover no-repeat, #16202c;
  display:flex; align-items:center; justify-content:center; font-size:0; color:transparent;}
.card .guardstack{position:absolute; inset:0; display:flex; align-items:center; justify-content:center; pointer-events:none; z-index:6; font-size:0; color:transparent;}
.card .guardstack::before{content:''; width:54%; height:54%; opacity:.5; background:var(--accent);
  -webkit-mask:var(--guard-icon, url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 2 20 5 V11 C20 16.5 16.4 20.4 12 22 C7.6 20.4 4 16.5 4 11 V5 Z' fill='%23000'/></svg>")) center/contain no-repeat;
  mask:var(--guard-icon, url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 2 20 5 V11 C20 16.5 16.4 20.4 12 22 C7.6 20.4 4 16.5 4 11 V5 Z' fill='%23000'/></svg>")) center/contain no-repeat;}
.card.guarded{box-shadow:0 0 0 2px rgba(70,194,168,.55), 0 0 17px rgba(70,194,168,.5), 0 4px 10px rgba(0,0,0,.5) !important;}
.card.used{box-shadow:0 0 0 2px rgba(228,87,46,.6), 0 0 17px rgba(228,87,46,.55), 0 4px 10px rgba(0,0,0,.5) !important;}

/* floating drag clone */
#ghost{position:fixed; pointer-events:none; z-index:9999; opacity:.92; transform:rotate(-4deg) scale(1.05); display:none;}
.volleypick{position:absolute; inset:0; display:flex; flex-direction:column; gap:4px; align-items:center; justify-content:center; background:rgba(6,10,15,.6); border-radius:var(--card-r); z-index:6;}
.volleypick button{font-size:11px; font-weight:800; padding:4px 9px; border-radius:8px; border:1px solid #3a5170; background:#16243a; color:#eaf2ff; cursor:pointer; white-space:nowrap;}
.volleypick button:hover{background:#21385a;}
.handzone.drophere{ box-shadow:0 0 0 2px rgba(70,194,168,.9) inset; background:rgba(70,194,168,.16); }

/* center control strip */
.center{display:flex; align-items:stretch; gap:10px; padding:4px 0;}
.pile{width:78px; display:flex; flex-direction:column; align-items:center; gap:3px;}
.pileface{width:60px; height:84px; border-radius:8px; border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center; font-family:var(--mono); font-weight:700; font-size:20px;}
.deck .pileface{background:repeating-linear-gradient(45deg,#16202c,#16202c 6px,#1d2a38 6px,#1d2a38 12px); color:var(--gold);}
.discard .pileface{background:#10171f; color:var(--muted);}
.pile .lbl{font-size:9px; color:var(--muted); font-family:var(--mono); text-transform:uppercase; letter-spacing:.5px;}
.controls{flex:1; display:flex; flex-direction:column; gap:6px; justify-content:center;}
/* IN-GAME BUTTONS. Same language as the lobby: an outlined rectangle over a blurred, low-alpha
   fill, Cinzel small-caps, colour carried by the border and the text rather than a solid slab.
   Each variant keeps its own hue — danger stays red, pass stays teal — just at a fraction of the
   old strength, so the board reads first and the controls sit behind it. */
button{font-family:'Cinzel',serif; font-weight:600; letter-spacing:.1em; text-transform:uppercase;
  border-radius:2px; padding:11px 12px; font-size:12.5px; cursor:pointer;
  color:#f0e2c4; background:rgba(202,161,72,.08);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  border:1px solid rgba(202,161,72,.5);
  transition:background .15s ease, border-color .15s ease, color .15s ease, transform .08s;}
/* AVAILABLE = LIT. Every action button carries the same weight when you can use it, whatever
   its hue, so Declare Battle doesn't read as less available than Top Deck. Hover DARKENS for
   tactile feedback (pressing something bright should push it down, not brighten it further), and
   anything you can't use right now drops right back so the live options stand out at a glance. */
button:hover:not(:disabled){background:rgba(202,161,72,.30); border-color:rgba(232,198,107,1); color:#fff8e8;
  filter:brightness(.88);}
button:active{transform:translateY(1px); filter:brightness(.8);}
button:disabled{opacity:.22; background:rgba(255,255,255,.015);
  border-color:rgba(255,255,255,.10); color:var(--muted); cursor:default;
  -webkit-backdrop-filter:none; backdrop-filter:none;}
button.alt{background:rgba(255,255,255,.03); border-color:rgba(255,255,255,.16); color:var(--muted);}
button.alt:hover:not(:disabled){background:rgba(255,255,255,.10); border-color:rgba(202,161,72,.8);
  color:var(--ink); filter:none;}
/* Each variant keeps its hue, but at the SAME strength as the default, so nothing looks half-off
   when it's actually available. */
button.go{background:rgba(224,80,110,.16); border-color:rgba(224,80,110,.75); color:#ffd2da;}
button.go:hover:not(:disabled){background:rgba(224,80,110,.30); border-color:rgba(255,140,165,1);
  color:#fff; filter:brightness(.9);}
button.pass{background:rgba(70,194,168,.16); border-color:rgba(70,194,168,.7); color:#c6f4e9;}
button.pass:hover:not(:disabled){background:rgba(70,194,168,.30); border-color:rgba(130,235,210,1);
  color:#f0fffb; filter:brightness(.9);}
.card.discardable{cursor:grab; outline:2px dashed #ff5c7a; box-shadow:0 0 14px rgba(255,92,122,.55);}
.card.discardable:hover{outline-color:#ff90a6; filter:brightness(1.06);}
.card.discardable:active{cursor:grabbing;}
/* Rage: a static red aura on the enraged card. */
.card.enraged{ box-shadow:inset 0 0 0 3px rgba(255,60,28,1), inset 0 0 26px 5px rgba(255,60,28,.7) !important; }
.card.cv.enraged{ box-shadow:none !important; }
.card.cv.enraged::after{ content:''; position:absolute; inset:0; z-index:9; pointer-events:none; border-radius:inherit; box-shadow:inset 0 0 0 3px rgba(255,60,28,1), inset 0 0 26px 5px rgba(255,60,28,.7); }
/* one-shot keyword impact flash (Blast/Burn/Explode/Charm…) */
.card .kwfx{position:absolute; inset:0; z-index:7; display:flex; align-items:center; justify-content:center; border-radius:inherit; pointer-events:none; opacity:0; animation:kwfxpop .6s ease-out forwards; animation-delay:var(--fxdelay,0s);}
.card .kwfx::before{content:''; position:absolute; inset:0; border-radius:inherit; background:var(--fxc,#ff4326); mix-blend-mode:screen; opacity:.55;}
.card .kwfx img{position:relative; width:54%; filter:drop-shadow(0 0 7px rgba(0,0,0,.7));}
.kwfx-red{--fxc:#ff4326;} .kwfx-orange{--fxc:#ff9020;} .kwfx-pink{--fxc:#ff5cc8;} .kwfx-gold{--fxc:#ffd24a;} .kwfx-green{--fxc:#3fdc72;}
.kwfx-blue{--fxc:#3a86e0;} .kwfx-teal{--fxc:#2affc0;} .kwfx-white{--fxc:#ffffff;} .kwfx-steel{--fxc:#9fb4c8;}
/* Reanimate: the card dissolves/rises IN as the ghostly green glow plays — starts low, faded */
.card.reanimate-in{ animation:reanimatein 1s ease-out both; }
@keyframes reanimatein{
  0%{ opacity:0; transform:translateY(14px) scale(.97); filter:blur(4px) brightness(1.5) saturate(1.3) hue-rotate(-10deg); }
  30%{ opacity:.5; filter:blur(2.5px) brightness(1.4) saturate(1.2); }
  70%{ opacity:.9; transform:translateY(2px) scale(1); filter:blur(.6px) brightness(1.15); }
  100%{ opacity:1; transform:translateY(0) scale(1); filter:none; }
}
/* Teleport: the card reforms out of scattered light — quick violet dissolve-in. */
.card.teleport-in{ animation:teleportin .6s cubic-bezier(.2,.8,.3,1) both; }
@keyframes teleportin{
  0%{ opacity:0; transform:scale(1.12); filter:blur(6px) brightness(1.8) saturate(1.4) hue-rotate(18deg); }
  40%{ opacity:.7; filter:blur(2px) brightness(1.4); }
  100%{ opacity:1; transform:scale(1); filter:none; }
}
/* Summon: an angel landing — the card fades in and settles down from above. */
.card.summon-in{ animation:summonin .74s cubic-bezier(.2,.7,.25,1) both; }
@keyframes summonin{
  0%{ opacity:0; transform:translateY(-40px) scale(1.02); filter:brightness(2) saturate(.7) drop-shadow(0 0 12px rgba(255,246,210,.9)); }
  45%{ opacity:.85; filter:brightness(1.5) drop-shadow(0 0 10px rgba(255,246,210,.7)); }
  100%{ opacity:1; transform:translateY(0) scale(1); filter:none; }
}
/* Armored: a brushed-chrome emboss while the card is upright (unspent). */
.card.armored{
  box-shadow:
    inset 0 2px 1px rgba(255,255,255,.55),      /* top bevel highlight */
    inset 0 -2px 2px rgba(20,28,38,.6),          /* bottom bevel shadow */
    inset 2px 0 1px rgba(230,238,246,.28),
    inset -2px 0 2px rgba(30,40,52,.45),
    0 0 0 1px rgba(150,165,182,.7),              /* crisp metal rim */
    0 0 10px 1px rgba(150,170,190,.35);
}
.card.armored::after{content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:6;
  /* curved chrome plate: bright band up top, mid-grey middle, dark toward the base */
  background:linear-gradient(180deg,
    rgba(238,244,250,.42) 0%,
    rgba(198,210,224,.22) 22%,
    rgba(150,164,182,.10) 46%,
    rgba(120,134,152,.16) 66%,
    rgba(52,64,80,.34) 100%);
  mix-blend-mode:screen;
}
.card.armored::before{content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:7; overflow:hidden;
  background:linear-gradient(100deg, transparent 36%, rgba(226,236,248,.35) 46%, rgba(255,255,255,.92) 50%, rgba(226,236,248,.35) 54%, transparent 64%);
  background-size:250% 100%; background-repeat:no-repeat;
  mix-blend-mode:screen; animation:metalsheen 3.6s ease-in-out infinite;
}
@keyframes metalsheen{ 0%{ background-position:165% 0; } 62%{ background-position:-65% 0; } 100%{ background-position:-65% 0; } }
/* Armored posture: a ready Armored card sits rotated 90deg (braced behind its plate). */
.card.armored.armorbraced{ transform:rotate(90deg); transition:transform .5s cubic-bezier(.2,.8,.25,1); }
.card.armored.armorbraced.armor-break{ transform:rotate(0deg); }
/* Armor crack stage: thin bright fracture lines spider across the chrome, fading in fast. */
.card.armored.armor-crack::after{
  background-image:
    linear-gradient(58deg, transparent 47.4%, rgba(255,255,255,.9) 48%, transparent 48.6%),
    linear-gradient(120deg, transparent 61.4%, rgba(230,242,255,.8) 62%, transparent 62.6%),
    linear-gradient(20deg, transparent 33.4%, rgba(255,255,255,.75) 34%, transparent 34.6%),
    linear-gradient(96deg, transparent 71.4%, rgba(230,242,255,.8) 72%, transparent 72.6%),
    linear-gradient(150deg, transparent 41.4%, rgba(255,255,255,.7) 42%, transparent 42.6%),
    linear-gradient(180deg, rgba(238,244,250,.42) 0%, rgba(150,164,182,.10) 46%, rgba(52,64,80,.34) 100%);
  animation:armorcrackin .18s ease-out both;
}
@keyframes armorcrackin{ from{ opacity:.2; } to{ opacity:1; } }
/* Armor spent: the chrome shatters off — fade the plate, sheen, and metal rim out quickly */
.card.armored.armor-break{ animation:armorrimfade .5s ease-out forwards; }
.card.armored.armor-break::after{ animation:armorfade .45s ease-out forwards; }
.card.armored.armor-break::before{ animation:armorfade .4s ease-out forwards; }
@keyframes armorfade{ from{ opacity:1; } to{ opacity:0; } }
@keyframes armorrimfade{
  0%{ box-shadow:0 0 0 1px rgba(150,165,182,.7), 0 0 10px 1px rgba(150,170,190,.35), inset 0 2px 1px rgba(255,255,255,.55), inset 0 -2px 2px rgba(20,28,38,.6); }
  100%{ box-shadow:0 0 0 1px rgba(150,165,182,0), 0 0 10px 1px rgba(150,170,190,0), inset 0 2px 1px rgba(255,255,255,0), inset 0 -2px 2px rgba(20,28,38,0); }
}
/* Guard rip: a Taunt tears this Guard off the card it was shielding — a brief silvery jolt + */
.card.guard-rip{ animation:guardrip .4s ease-out; }
@keyframes guardrip{
  0%{ box-shadow:0 0 0 2px rgba(200,220,240,.9), 0 0 18px 3px rgba(180,205,230,.7); filter:brightness(1.35); }
  40%{ box-shadow:0 0 0 1px rgba(200,220,240,.5), 0 0 10px 2px rgba(180,205,230,.35); filter:brightness(1.12); }
  100%{ box-shadow:0 0 0 0 rgba(200,220,240,0), 0 0 0 0 rgba(180,205,230,0); filter:none; }
}
.card.assassin-out{ animation:assassinout .16s ease-in both; }
@keyframes assassinout{
  0%{ opacity:1; filter:none; }
  100%{ opacity:0; filter:brightness(0) contrast(1.4); transform:scale(.96); }
}
.card.assassin-in{ animation:assassinin 1.1s ease-out both; }
@keyframes assassinin{
  0%{ opacity:0; filter:brightness(0); transform:scale(.97); }
  40%{ opacity:.35; filter:brightness(.35); }
  100%{ opacity:1; filter:none; transform:scale(1); }
}
.card .kwfx.kwfx-slowfade{ animation:kwfxslow 1.6s ease-in-out forwards; }
@keyframes kwfxslow{0%{opacity:0; transform:scale(.9);} 30%{opacity:1; transform:scale(1);} 70%{opacity:1; transform:scale(1);} 100%{opacity:0; transform:scale(1.02);}}
/* Swarm death wash: each projectile that lands paints the doomed card in its own color */
.swarm-wash{ position:absolute; inset:0; z-index:22; border-radius:inherit; pointer-events:none;
  background:var(--washc,#fff); mix-blend-mode:screen; opacity:0; animation:swarmwash .34s ease-out forwards; }
@keyframes swarmwash{ 0%{opacity:0;} 22%{opacity:.72;} 100%{opacity:0;} }
@keyframes kwfxpop{0%{opacity:0; transform:scale(.55);} 16%{opacity:1; transform:scale(1.1);} 55%{opacity:.9; transform:scale(1);} 100%{opacity:0; transform:scale(1.02);}}
/* Rage: an enraged card that survives a hit swells red, then SETTLES into a held edge glow */
.card .kwfx.kwfx-fire{--fxc:#ff3a1e; animation:rageswell 1s ease-out forwards;}
.card .kwfx.kwfx-fire::before{background:transparent;}
.card .kwfx.kwfx-fire img{animation:rageiconfade 1s ease-out forwards; transform:scale(1.1);}
@keyframes rageiconfade{0%{opacity:0;}20%{opacity:1;}70%{opacity:1;}100%{opacity:0;}}
@keyframes rageswell{
  0%{opacity:0; transform:scale(.85);}
  28%{opacity:1; transform:scale(1.16);}
  60%{opacity:1; transform:scale(1.02);}
  100%{opacity:.72; transform:scale(1);}}
/* Rage: a fast angry shudder that decays as the card "gets angry", then settles. */
.card.ragevibe{ animation:ragevibe .7s ease-out; }
@keyframes ragevibe{
  0%{transform:translate(0,0) scale(var(--appscale,1));}
  8%{transform:translate(-2.4px,1.2px) scale(var(--appscale,1));}
  18%{transform:translate(2.4px,-1px) scale(var(--appscale,1));}
  28%{transform:translate(-2px,-1.4px) scale(var(--appscale,1));}
  40%{transform:translate(1.8px,1.2px) scale(var(--appscale,1));}
  52%{transform:translate(-1.4px,0.8px) scale(var(--appscale,1));}
  66%{transform:translate(1px,-0.6px) scale(var(--appscale,1));}
  80%{transform:translate(-0.5px,0.3px) scale(var(--appscale,1));}
  100%{transform:translate(0,0) scale(var(--appscale,1));}}
.card.attacking{z-index:5;}
.card.atk-up{ animation:atklungeup .44s cubic-bezier(.3,.85,.3,1); }
.card.atk-down{ animation:atklungedown .44s cubic-bezier(.3,.85,.3,1); }
@keyframes atklungeup{0%{translate:0 0;}30%{translate:0 -7px;}48%{translate:0 -24px;}100%{translate:0 0;}}
@keyframes atklungedown{0%{translate:0 0;}30%{translate:0 7px;}48%{translate:0 24px;}100%{translate:0 0;}}
.ambbadge{position:absolute; top:4px; left:4px; z-index:9; width:26px; height:26px; display:flex; align-items:center; justify-content:center; border-radius:50%; background:linear-gradient(#ffd97a,#e6a636); border:2px solid #7a571a; box-shadow:0 2px 7px rgba(0,0,0,.5); color:#1a0f04; font-size:14px; font-weight:900; pointer-events:none; animation:pulse 1.1s ease-in-out infinite;}
.ambbadge img{width:74%; height:74%; object-fit:contain; filter:brightness(0) drop-shadow(0 1px 1px rgba(255,255,255,.3));}
/* The Ambush button is only usable during the ambush window, but it must not appear */
/* Confirm buttons still need to shout, but within the same idiom — a brighter fill and a lit
   border rather than a gold slab. */
button.full.amb{ background:rgba(232,198,107,.24) !important; color:#fff6e2 !important;
  border:1px solid rgba(232,198,107,.95) !important; text-shadow:none !important;
  animation:pulse 1.2s ease-in-out infinite; }
button.full.amb.swapped{ animation:none; }
.drawghost{box-shadow:0 10px 26px rgba(0,0,0,.5); border:1px solid #2c3e50;}
/* Available drag target while a card is being placed: a soft pulse that says "you may drag
   here". Distinct from .drophere, which is the strong cue when the card is actually over it.
   Clicking still only opens the viewer — discarding requires a drag. */
.pile.discard.droptarget .pileface{ box-shadow:0 0 0 2px rgba(255,92,122,.55) inset, 0 0 12px rgba(255,92,122,.3);
  animation:discTargetPulse 1.6s ease-in-out infinite; }
.pile.discard.droptarget .lbl{ color:#ffb3c1; }
@keyframes discTargetPulse{
  0%,100%{ box-shadow:0 0 0 2px rgba(255,92,122,.42) inset, 0 0 10px rgba(255,92,122,.22); }
  50%    { box-shadow:0 0 0 2px rgba(255,92,122,.85) inset, 0 0 20px rgba(255,92,122,.52); } }
/* Hovering it mid-drag overrides the pulse with the solid drop cue. */
.pile.discard.droptarget.drophere .pileface{ animation:none; }
.pile.discard.drophere .pileface{box-shadow:0 0 0 3px rgba(255,92,122,.95) inset, 0 0 18px rgba(255,92,122,.6); outline:2px solid rgba(255,92,122,.85);}

.pile.discard.drophere .lbl{color:#ff90a6;}
button.disc{background:#7c5cff; color:#fff;}
button.full{flex:1;}
button:disabled{opacity:1; cursor:not-allowed; filter:grayscale(.85) brightness(.5) contrast(.95);}
/* The banner lives between .playarea and .dock-bot in .main's flex column, so its height */
.banner{font-size:12px; font-family:var(--mono); color:var(--gold); min-height:16px; text-align:center;
  position:absolute; left:0; right:0; bottom:2px; z-index:3; pointer-events:none;}
.banner.warn{color:var(--danger);}

/* side panel: log + reference */
.side{width:300px; background:transparent; border-left:none; display:flex; flex-direction:column;}
.side .head{padding:12px 14px 6px; }
.side .title{font-weight:900; letter-spacing:1px; font-size:16px;}
.side .title span{color:var(--gold);}
.tabs{display:flex; gap:6px; padding:14px 14px 8px;}
.tab{flex:1; text-align:center; padding:7px; font-size:12px; font-weight:700; border-radius:8px; background:#111a24; color:var(--muted); cursor:pointer;}
.tab.on{background:var(--gold); color:#0a121b;}
.panel{flex:1; overflow-y:auto; padding:6px 14px 14px; font-size:12px; line-height:1.45;}
/* Themed scrollbars for the scrolling panels — replaces the default block-white bar. */
.panel, .side, #deckstats .dscard, #discview .dvgrid, #modal .opts{ scrollbar-width:thin;
  scrollbar-color:rgba(202,161,72,.5) transparent; }
.panel::-webkit-scrollbar, .side::-webkit-scrollbar, #deckstats .dscard::-webkit-scrollbar,
#discview .dvgrid::-webkit-scrollbar, #modal .opts::-webkit-scrollbar{ width:8px; height:8px; }
.panel::-webkit-scrollbar-track, .side::-webkit-scrollbar-track,
#deckstats .dscard::-webkit-scrollbar-track, #discview .dvgrid::-webkit-scrollbar-track,
#modal .opts::-webkit-scrollbar-track{ background:transparent; }
.panel::-webkit-scrollbar-thumb, .side::-webkit-scrollbar-thumb,
#deckstats .dscard::-webkit-scrollbar-thumb, #discview .dvgrid::-webkit-scrollbar-thumb,
#modal .opts::-webkit-scrollbar-thumb{ background:linear-gradient(rgba(202,161,72,.55), rgba(160,120,50,.45));
  border-radius:6px; border:2px solid transparent; background-clip:padding-box; }
.panel::-webkit-scrollbar-thumb:hover, .side::-webkit-scrollbar-thumb:hover,
#deckstats .dscard::-webkit-scrollbar-thumb:hover, #discview .dvgrid::-webkit-scrollbar-thumb:hover,
#modal .opts::-webkit-scrollbar-thumb:hover{ background:linear-gradient(rgba(232,198,107,.75), rgba(190,150,70,.6));
  background-clip:padding-box; }
.panel::-webkit-scrollbar-corner, .side::-webkit-scrollbar-corner{ background:transparent; }
#log .e{padding:4px 0; border-bottom:1px solid #131d27; color:#c5d3df; font-family:var(--mono); font-size:11px;}
#log .e.turn{color:var(--gold); font-weight:700;}
#log .e.battle{color:var(--accent);}
#log .e.death{color:var(--danger);}
#ref .k{margin-bottom:7px;}
#ref .k b{color:var(--gold);}
#ref .k span{color:var(--muted);}
#ref .kw-toggle{cursor:pointer; border-radius:4px; padding:2px 4px; margin:0 -4px 7px;}
#ref .kw-toggle:hover{background:rgba(255,255,255,.07);}
#ref .kw-toggle.static{cursor:default;}
#ref .kw-toggle.static:hover{background:transparent;}
#ref .kw-toggle.off{opacity:.42;}
#ref .kw-toggle.off b{text-decoration:line-through; color:var(--muted);}
#ref .setrow{display:flex; align-items:center; gap:8px; margin-bottom:6px; flex-wrap:wrap;}
#ref .setrow>b{color:var(--gold); min-width:72px; font-size:12px;}
#ref .seg{display:flex; gap:4px; flex-wrap:wrap;}
#ref .segbtn,#ref .powbtn,#ref .tdbtn{cursor:pointer; border:1px solid rgba(255,255,255,.18); background:rgba(255,255,255,.05); color:var(--muted); border-radius:5px; padding:3px 7px; font-size:11px; line-height:1;}
#ref .lifebtn{cursor:pointer; border:1px solid rgba(255,255,255,.18); background:rgba(255,255,255,.05); color:var(--muted); border-radius:5px; padding:3px 9px; font-size:13px; line-height:1; font-weight:700;}
#ref .lifebtn:active{background:var(--gold); color:#1a1205;}
#ref .lifeseg{align-items:center;}
#ref .lifeval{min-width:26px; text-align:center; font-weight:800; color:var(--gold); font-size:13px;}
#ref .powbtn,#ref .tdbtn{min-width:22px; text-align:center;}
#ref .segbtn.on,#ref .powbtn.on,#ref .tdbtn.on{background:var(--gold); color:#1a1205; border-color:var(--gold); font-weight:700;}
#ref .setnote{color:#8aa0b3; font-size:11px; margin-top:5px; line-height:1.35;}
#ref .kwallbtn{display:inline-block; margin-top:6px; padding:3px 9px; font-size:11px; font-weight:700; cursor:pointer;
  color:#e8dcc0; background:linear-gradient(180deg,#2a2114,#1a140c); border:1px solid #5a4526; border-radius:6px;}
#ref .kwallbtn:hover{ border-color:#caa148; color:#fff; }
#deckstats{position:fixed; inset:0; display:none; align-items:center; justify-content:center; background:rgba(2,5,9,.62); z-index:200;}
#deckstats.show{display:flex;}
#deckstats .dscard{background:#0d1622; border:1px solid rgba(255,255,255,.14); border-radius:12px; padding:16px 18px; width:min(460px,92vw); max-height:86vh; overflow:auto; box-shadow:0 18px 50px rgba(0,0,0,.6); color:#dce6f2;}
#deckstats .dshead{display:flex; align-items:center; gap:8px; font-weight:800; font-size:16px; color:var(--gold); margin-bottom:10px;}
#deckstats .dshead span{color:#8aa0b3; font-weight:600; font-size:12px;}
#deckstats .dsx{margin-left:auto; background:none; border:none; color:#8aa0b3; font-size:16px; cursor:pointer;}
#deckstats .dssec{margin-bottom:12px;}
#deckstats .dssec h4{margin:0 0 5px; font-size:12px; letter-spacing:.06em; text-transform:uppercase; color:#9fb2c6;}
#deckstats .dsrow{display:flex; align-items:center; gap:8px; margin:2px 0; font-size:12px;}
#deckstats .dslbl{min-width:80px; color:#c7d4e2;}
#deckstats .dsbar{flex:1; height:9px; background:rgba(255,255,255,.07); border-radius:5px; overflow:hidden;}
#deckstats .dsbar i{display:block; height:100%; background:var(--gold);}
#deckstats .dsn{min-width:22px; text-align:right; color:#9fb2c6;}
#discview{position:fixed; inset:0; display:none; align-items:center; justify-content:center; background:rgba(2,5,9,.66); z-index:200;}
#discview.show{display:flex;}
#discview .dvcard{background:#0d1622; border:1px solid rgba(255,255,255,.14); border-radius:12px; padding:16px 18px; width:min(820px,95vw); max-height:90vh; display:flex; flex-direction:column; box-shadow:0 18px 50px rgba(0,0,0,.6); color:#dce6f2;}
#discview .dvhead{display:flex; align-items:center; gap:8px; font-weight:800; font-size:16px; color:var(--gold); margin-bottom:10px;}
#discview .dvhead span{color:#8aa0b3; font-weight:600; font-size:12px;}
#discview .dvx{margin-left:auto; background:none; border:none; color:#8aa0b3; font-size:18px; cursor:pointer; line-height:1;}
#discview .dvgrid{display:flex; flex-wrap:wrap; gap:12px; overflow:auto; padding:8px 2px; justify-content:center; align-content:flex-start;}
#discview .dvgrid .card{margin:0;}
#discview .dvempty{color:#8aa0b3; font-size:13px; padding:40px 10px;}
#placepreview{position:fixed; left:50%; top:50%; transform:translate(-50%,-50%); z-index:250; display:none; flex-direction:column; align-items:center; gap:10px; padding:16px 16px 18px; background:rgba(9,13,19,.95); border:2px solid var(--gold); border-radius:14px; box-shadow:0 16px 44px rgba(0,0,0,.6); pointer-events:none;}
#placepreview .card{pointer-events:auto;}   /* allow hover-zoom + keyword tooltip on the preview card */
#placepreview .pplabel{font-family:var(--font); font-weight:800; color:var(--gold); font-size:13.5px; letter-spacing:.5px; text-align:center; max-width:150px; line-height:1.3;}
/* The preview card is DRAGGED to the discard pile to throw it away (a click never discards */
/* The container stays click-through so the discard pile underneath (Reanimate anchors */
/* The OPPONENT'S view of a pending choice: same panel, drained of colour and inert, so it reads
   as "they are deciding" rather than as something you can act on. */
#placepreview.theirs{border-color:#4a4a4a; box-shadow:0 16px 44px rgba(0,0,0,.6);
  background:rgba(9,11,14,.95); filter:grayscale(1) brightness(.72);}
#placepreview.theirs .pplabel{color:#8d8d8d;}
#placepreview .ppback{width:110px; height:151px; opacity:.85;}
#placepreview .ppwait{font-family:var(--mono); font-size:10px; letter-spacing:.12em;
  text-transform:uppercase; color:#8d8d8d;}
/* EMOTES. Image-only by design — no labels, nothing to read or moderate. */
/* Raw artwork, no chrome: no ring, no plate, no shadow box — just the image, lifted off the
   board with a drop-shadow so it stays legible on a light playmat. */
.emobtn{position:absolute; width:62px; height:62px; transform:translate(-50%,-50%);
  border:none; border-radius:0; cursor:pointer; padding:0;
  background:transparent center/contain no-repeat;
  filter:drop-shadow(0 3px 8px rgba(0,0,0,.8));
  transition:transform .1s, filter .12s;}
.emobtn:hover{transform:translate(-50%,-50%) scale(1.16);
  filter:drop-shadow(0 0 10px rgba(232,198,107,.85)) drop-shadow(0 3px 8px rgba(0,0,0,.8));}
.emobubble{position:fixed; width:74px; height:74px; z-index:9350; pointer-events:none;
  background:center/contain no-repeat; filter:drop-shadow(0 5px 14px rgba(0,0,0,.75));}
.mutebtn{font-family:var(--mono); font-size:11px; letter-spacing:.1em; text-transform:uppercase;
  padding:7px 14px; border-radius:8px; transform:translateX(-50%); cursor:pointer;
  background:rgba(10,13,18,.96); color:var(--ink); border:1px solid var(--line);
  box-shadow:0 8px 22px rgba(0,0,0,.6);}
.mutebtn:hover{border-color:var(--gold); color:var(--gold);}
body.overseer .emobtn, body.overseer .mutebtn{ display:none; }

/* EXPLODE FUSE. --fuse is 0..1 = hits taken / hits it can survive, so a 2-power on 1 damage and
   a 5-power on 4 look identical: both are one hit from detonating. The keyword symbol brightens,
   grows and rattles FASTER as it climbs — duration shrinks from 300ms to 70ms. calc() on
   animation-duration is what lets one class cover the whole range. */
/* The warning is an OVERLAY on the card, like Freeze's frostmark — not the corner symbol. */
.card .fusemark{position:absolute; inset:0; z-index:8; display:flex; align-items:center; justify-content:center;
  pointer-events:none; border-radius:inherit; overflow:hidden;}
.card .fusemark img, .card .fusemark .g{
  width:46%; height:46%; object-fit:contain; font-size:42px; line-height:1; color:#ffd7a8;
  animation: fuseshake calc(300ms - var(--fuse,0) * 230ms) linear infinite;
  opacity: calc(.28 + var(--fuse,0) * .72);
  scale: calc(.84 + var(--fuse,0) * 0.38);
  filter: drop-shadow(0 0 calc(2px + var(--fuse,0) * 14px) rgba(255,110,40, calc(.35 + var(--fuse,0) * .65)))
          drop-shadow(0 1px 3px rgba(0,0,0,.85))
          brightness(calc(1 + var(--fuse,0) * .9));}
/* The whole card rattles too, a fraction of the icon's throw so it reads as strain not noise. */
.card.fuse{ animation: fusecard calc(340ms - var(--fuse,0) * 250ms) linear infinite; }
@keyframes fusecard{
  0%  { translate: calc(var(--fuse,0) * -0.9px) calc(var(--fuse,0) * 0.6px); }
  30% { translate: calc(var(--fuse,0) * 0.8px) calc(var(--fuse,0) * -0.7px); }
  60% { translate: calc(var(--fuse,0) * -0.6px) calc(var(--fuse,0) * -0.9px); }
  100%{ translate: calc(var(--fuse,0) * -0.9px) calc(var(--fuse,0) * 0.6px); }
}
.card.flip .fusemark{ transform:rotate(180deg); }   /* frozen card is upside down; keep it readable */
@keyframes fuseshake{
  0%  { translate: calc(var(--fuse,0) * -1.6px) calc(var(--fuse,0) * 1.1px); }
  25% { translate: calc(var(--fuse,0) * 1.7px) calc(var(--fuse,0) * -1.3px); }
  50% { translate: calc(var(--fuse,0) * -1.2px) calc(var(--fuse,0) * -1.7px); }
  75% { translate: calc(var(--fuse,0) * 1.4px) calc(var(--fuse,0) * 1.5px); }
  100%{ translate: calc(var(--fuse,0) * -1.6px) calc(var(--fuse,0) * 1.1px); }
}
/* Near-certain death: a slow red pulse behind the whole card so it reads at a glance. */
.card.fuse::after{
  content:''; position:absolute; inset:-2px; border-radius:inherit; pointer-events:none;
  box-shadow: inset 0 0 calc(var(--fuse,0) * 22px) rgba(255,80,40, calc(var(--fuse,0) * .55));
  opacity: calc(var(--fuse,0) * var(--fuse,0));   /* squared: stays out of the way until it's close */
}

/* PATCH NOTES. Lobby-only: a small tab by the How To Play button, and a scrolling modal. */
#pnBtn{position:fixed; right:22px; bottom:120px; z-index:120; cursor:pointer;
  font-family:var(--font); font-weight:700; font-synthesis-weight:none;
  font-size:20px; letter-spacing:.1em; padding:17px 32px;
  color:#0a121b; background:linear-gradient(180deg,#d2aa4c,#9c7a2e); border:2px solid #5a4528;
  border-radius:12px; box-shadow:0 6px 22px rgba(0,0,0,.65), inset 0 1px 0 rgba(255,255,255,.18);
  display:inline-flex; align-items:center; gap:13px;}
#pnBtn:hover{filter:brightness(1.08);}
#pnBtn:active{transform:translateY(1px);}
/* Count of notes that are NEW or have been EDITED since this browser last opened the panel. */
/* [hidden] is a UA-stylesheet rule, and ANY author `display` beats it — so setting .hidden in JS
   did nothing here and the bubble showed '0' with nothing new. Both of these need it back. */
#pnBtn[hidden], .pnBadge[hidden]{display:none !important;}
.pnBadge{min-width:28px; height:28px; padding:0 8px; border-radius:999px;
  background:#c0392b; color:#fff; border:2px solid rgba(255,255,255,.35);
  font-family:var(--mono); font-size:14px; font-weight:700; letter-spacing:0;
  display:inline-flex; align-items:center; justify-content:center;
  box-shadow:0 0 0 2px rgba(0,0,0,.35), 0 0 10px rgba(192,57,43,.7);}
#pnModal{display:none; position:fixed; inset:0; z-index:9600; background:rgba(6,8,11,.72);
  backdrop-filter:blur(3px); align-items:center; justify-content:center; padding:24px;}
#pnModal.show{display:flex;}
.pnCard{position:relative; width:min(620px,94vw); max-height:80vh; overflow:auto;
  background:rgba(12,15,20,.97); border:1.5px solid var(--gold); border-radius:14px; padding:22px 24px;
  box-shadow:0 22px 60px rgba(0,0,0,.7);}
.pnCard h3{font-family:var(--display); color:var(--gold); letter-spacing:.12em; text-transform:uppercase;
  margin:0 0 14px; font-size:20px;}
.pnX{position:absolute; top:10px; right:12px; background:none; border:none; color:var(--muted);
  font-size:18px; cursor:pointer; padding:4px 8px;}
.pnX:hover{color:var(--ink);}
.pnEntry{border-top:1px solid var(--line); padding:14px 0;}
.pnEntry:first-child{border-top:none; padding-top:0;}
.pnEntry h4{margin:0 0 2px; font-family:var(--font); font-weight:700; font-synthesis-weight:none;
  font-size:15.5px; color:var(--ink); letter-spacing:.3px;}
.pnMeta{font-family:var(--mono); font-size:10px; letter-spacing:.12em; color:var(--muted);
  text-transform:uppercase; margin-bottom:8px;}
.pnBody{font-family:var(--font); font-weight:700; font-synthesis-weight:none; font-size:14px;
  line-height:1.5; letter-spacing:.4px; color:#e6dccb; white-space:pre-wrap;}

/* TOURNAMENT ROOM. The organiser owns the match: no new game, no room link to share, no seed
   and no deck shuffle. Forfeit stays — conceding early is a real tournament move, and it already
   awards the win to the opponent. */
body.tournament #btnNew,
body.tournament .shareRow,
body.tournament #seedCtl,
body.tournament #btnShufDeck,
body.tournament #btnShufDisc{ display:none !important; }

/* Pause veil: everything behind it blurs and desaturates, nothing is clickable. */
body.paused .app{ filter:blur(7px) grayscale(.85) brightness(.5); pointer-events:none; }
#pauseveil{position:fixed; inset:0; z-index:9500; display:flex; align-items:center; justify-content:center;
  background:rgba(6,8,11,.55); backdrop-filter:blur(2px);}
#pauseveil .pv-box{text-align:center; padding:26px 44px; border-radius:14px;
  background:rgba(10,13,18,.92); border:1.5px solid var(--gold);
  box-shadow:0 20px 60px rgba(0,0,0,.7), inset 0 0 0 1px rgba(232,198,107,.18);}
#pauseveil .pv-t{font-family:var(--display); font-size:40px; letter-spacing:.12em; color:var(--gold);
  text-transform:uppercase; text-shadow:0 4px 18px rgba(0,0,0,.8);}
#pauseveil .pv-s{font-family:var(--mono); font-size:11px; letter-spacing:.16em; color:var(--muted);
  text-transform:uppercase; margin-top:8px;}

/* OVERSEER (tournament stream view): both hands open, nothing clickable. Hide every player
   affordance so the capture is just the board. */
body.overseer .dock-bot .btns, body.overseer #btnNew, body.overseer #btnForfeit,
body.overseer .shareRow, body.overseer .foot{ display:none !important; }
body.overseer .hand .card{ cursor:default !important; }
/* The side panel stays USABLE for an overseer — the abilities tab is a caster's reference. */
body.overseer .side .foot, body.overseer .side .sidecontrols{ pointer-events:none; }
body.overseer .hand.dim{ opacity:.82; }   /* both hands stay legible on camera */

/* Volley aimed at YOUR life while the opponent decides: marked, greyed, not clickable. */
.life.big.lifetarget.theirs{ filter:grayscale(1) brightness(.78); cursor:default; }
.volleylife.theirs{ filter:grayscale(1) brightness(.8); opacity:.85; animation:none; }

/* A pick belonging to the OTHER seat: same marks, drained to grey and inert, so the waiting
   player can follow a Ranged/Taunt/Flying/Teleport choice instead of staring at a pause. */
.lane.flytarget.theirs{filter:grayscale(1) brightness(.66); opacity:.75;}
.card.flyactive.theirs{filter:grayscale(1) brightness(.7);}
.tgtmark.theirs{filter:grayscale(1) brightness(.8); opacity:.85; animation:none;}
.flylabel.theirs{color:#8d8d8d; text-shadow:none; animation:none;}
#placepreview .ppdraggable{cursor:grab; position:relative; touch-action:none; pointer-events:auto;}
#placepreview .ppdraggable:active{cursor:grabbing;}
#placepreview .ppdraggable.dragging{filter:grayscale(.4) brightness(.85); opacity:.9;}
#placepreview{transition:left .38s cubic-bezier(.3,.8,.3,1), top .38s cubic-bezier(.3,.8,.3,1);}
/* Two rows: [Room # | Auto-Pass] and [board picker | seed | 🎲]. */
.foot{padding:8px 14px; border-top:1px solid var(--line); font-size:10px; color:var(--muted); font-family:var(--mono); display:flex; gap:8px; align-items:center; flex-wrap:nowrap;}
.autoPassWrap.footpass{font-size:10px; color:var(--muted);}
.foot input{width:54px; background:#0e1620; border:1px solid var(--line); color:var(--ink); border-radius:6px; padding:3px 6px; font-family:var(--mono); font-size:11px;}

/* --- side-panel bottom stack ---------------------------------------------------------- */
/* [New Game | Forfeit] / [Share Room #] / [Auto-Pass . Rules . i] / [board | seed | dice]  */
/* Ruled off from New Game / Forfeit above it. */
.shareRow{padding:9px 14px; display:flex; border-top:1px solid var(--line);}
/* Full width, but short — the height came down, not the reach. Theme font, at its real 700
   face (ThestralNeue ships Bold only, so synthesis is off to keep the strokes clean). */
.roomchip.shareBig{width:100%; flex:1 1 auto; font-family:var(--font); font-weight:700;
  font-synthesis-weight:none; font-size:13px; letter-spacing:1.1px; padding:6px 10px;
  border-width:1.5px; border-radius:8px;
  background:linear-gradient(180deg,rgba(210,170,76,.26),rgba(156,122,46,.14));
  box-shadow:inset 0 0 0 1px rgba(232,198,107,.18), 0 2px 10px rgba(0,0,0,.35);}
.roomchip.shareBig:hover:not(:disabled){background:linear-gradient(180deg,rgba(210,170,76,.42),rgba(156,122,46,.24)); box-shadow:0 0 16px rgba(210,170,76,.45);}
.roomchip.shareBig:disabled{opacity:.38; cursor:default; box-shadow:none;}
/* Auto-Pass left, credits "i" right, Rules stretched across everything between them. */
.footmain{display:grid; grid-template-columns:auto 1fr auto; align-items:center; gap:8px;}
.footmain .autoPassWrap{justify-self:start;}
.footmain .footright{display:flex; align-items:center; justify-content:flex-end; gap:8px; justify-self:end; min-width:0;}
.footmain .footright #assetstatus{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.rulesbtn{justify-self:stretch; width:100%; font-family:var(--font); font-weight:700; font-synthesis-weight:none; font-size:12.5px; letter-spacing:1.2px;
  color:var(--gold); background:linear-gradient(180deg,rgba(210,170,76,.14),rgba(156,122,46,.08));
  border:1px solid rgba(210,170,76,.5); border-radius:6px; padding:4px 15px; cursor:pointer;
  transition:background .12s, box-shadow .12s, transform .06s; text-transform:uppercase;}
.rulesbtn:hover{background:linear-gradient(180deg,rgba(210,170,76,.3),rgba(156,122,46,.16)); box-shadow:0 0 12px rgba(210,170,76,.35);}
.rulesbtn:active{transform:translateY(1px);}

/* --- themed board picker (replaces the native <select>) -------------------------------- */
/* Row labels: theme font, not the leftover lowercase placeholders. */
.foot .footlbl{font-family:var(--font); font-weight:700; font-synthesis-weight:none; font-size:11.5px;
  letter-spacing:.9px; color:var(--muted); flex:none;}
.footboard{gap:8px;}
/* Capped: in a Find-a-match game the seed controls are hidden and an uncapped picker ate the
   whole row. The whole tile is the button — there is no caret to aim at. */
.bpick{position:relative; flex:1 1 0; min-width:0; max-width:132px;}
.bpick-btn{width:100%; display:flex; align-items:center; justify-content:center; gap:0; cursor:pointer;
  background:linear-gradient(180deg,#131d28,#0c141d); color:#cfe0ee;
  border:1px solid var(--line); border-radius:7px; padding:3px;   /* symmetric: the 8px right gutter was for the caret, which is gone */
  font-family:var(--mono); font-size:11px; letter-spacing:normal; text-transform:none;
  transition:border-color .12s, box-shadow .12s;}
.bpick-btn:hover{border-color:rgba(210,170,76,.55); box-shadow:0 0 10px rgba(210,170,76,.18);}
.bpick.open .bpick-btn{border-color:var(--gold); box-shadow:0 0 12px rgba(210,170,76,.3);}
/* width:100% + border-box fills the content box EXACTLY, so the gutters are the button's
   3px padding on all four sides and nothing else. flex sizing left a ragged right edge. */
.bpick-thumb{flex:none; width:100%; height:26px; border-radius:4px; border:1px solid rgba(232,198,107,.35);
  background:#0b1119 center/cover no-repeat; box-shadow:0 1px 4px rgba(0,0,0,.5);}
.bpick-thumb.plain{background:repeating-linear-gradient(45deg,#16202c,#16202c 5px,#1d2a38 5px,#1d2a38 10px);}
/* Opens UPWARD: this row is the last thing in the side panel. */
.bpick-menu{display:none; position:absolute; left:0; right:0; bottom:calc(100% + 6px); z-index:400;
  max-height:min(52vh,330px); overflow:auto; padding:6px;
  background:rgba(9,13,19,.98); border:1.5px solid var(--gold); border-radius:10px;
  box-shadow:0 -12px 34px rgba(0,0,0,.62), inset 0 0 0 1px rgba(232,198,107,.16);}
.bpick.open .bpick-menu{display:block;}
.bpick-opt{display:flex; align-items:center; gap:0; width:100%; padding:4px; margin:0 0 4px;
  border-radius:7px; background:none; border:1px solid transparent; color:#cfe0ee;
  font-family:var(--mono); font-size:11px; cursor:pointer; text-align:left;}
.bpick-opt:last-child{margin-bottom:0;}
.bpick-opt:hover{background:rgba(210,170,76,.14); border-color:rgba(210,170,76,.45);}
.bpick-opt.sel{background:rgba(210,170,76,.2); border-color:var(--gold); color:var(--gold);}
/* Thumbnail-only list: the board IS the label. Names ride along as tooltips. */
.bpick-opt .bpick-thumb{width:100%; height:40px;}

/* modal */
#modal{position:fixed; inset:0; background:rgba(4,8,12,.78); display:none; align-items:center; justify-content:center; z-index:5000;}
#modal .box{background:#101a24; border:1px solid var(--gold); border-radius:14px; padding:18px; max-width:520px; width:90%;}
#modal h3{margin:0 0 8px; font-size:16px;}
#modal p{color:var(--muted); font-size:13px; margin:0 0 12px;}
#modal .opts{display:flex; flex-direction:column; gap:8px; max-height:50vh; overflow:auto;}
#modal .opts button{width:100%; text-align:left;}
#modal .opts.guardmode button.gmbtn{width:108px; text-align:center;}
/* The end-of-game pair (Rematch / Leave) is a row, not a list: .opts defaults to a stacked */
#modal .opts.endgame{flex-direction:row; overflow:visible;}
#modal .opts.endgame button{width:auto; flex:1 1 0; min-width:0; text-align:center; white-space:nowrap;}
#modal .opts.endgame button.ghost{background:rgba(40,32,20,.9); color:#e8dcc0; border:1px solid #5a4526;}
/* End-game modal only — the choice modals clear .endgame and stay left-aligned. */
#modal .box:has(#mOpts.endgame) #mTitle,
#modal .box:has(#mOpts.endgame) #mText{ text-align:center; }

@media(max-width:1000px){ .side{width:230px;} .card{width:82px;height:114px;} .card .pw{font-size:28px;} .card .kw{font-size:9.5px;min-height:24px;} .pile{width:64px;} .pileface{width:50px;height:70px;} }

/* real card visuals (Gauntlet of Gods) */
.card.cv{width:125px;height:179px;background:#000;border:none;border-radius:6px;overflow:hidden;
  --ink:#fff;--inkf:none;box-shadow:0 4px 10px rgba(0,0,0,.5);}
/* Firefox drops an image's decoded bitmap when the node using it is destroyed, and the grid */
#artcache{position:fixed; left:-99999px; top:-99999px; width:1px; height:1px;
  overflow:hidden; pointer-events:none; opacity:0; z-index:-1; contain:strict;}
#artcache img{position:absolute; width:1px; height:1px; opacity:0;}
.cv-art{position:absolute;inset:0;background-size:cover;background-position:center;
  -webkit-mask:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAFeCAYAAACsFgJxAAAGcElEQVR42u3az4uuZR3H8c/3umfOPMeDuRCVQgoXbcKF2DJzISrugiBaqK1aubX+igp3/gHtwsitWYairjI5C6GFkJRaKLSI6MwzP+77ajH3M92c5uiJ4Jx5xtcLZmB+MXDB+/l+72smuTlDkhbgPGlzm5+rbuLrlWRKklXy1bG1b03T9FCvenDqfddZwy2quuqoen+vtXZ1mKa318lfFsH3+e1/Dn1IMibJXvL4UfJcT55McqU7c7ht5mivVdWvd3t/8TD5bb+u2ZsNfUgyrlb52tFB/WTq/XuLuMf5laMcOdxym/aGTcCt6qXdvf7j9Tp/vlHsdaPIh+TJnvx8Su6bV/c+rwgCh/MR/LRpvSWfVPKDMXn1rNivf5DfSTKuWnt2TH45JXcmOc5/LuNEDudng980edyTL1XV03utfXDc+9W55emsiX4yyYc8No2nO/9migPn25SkKultyBPjmN8tJ/sm9JakX06+sk7e7ck9IoetjL1V8ukqeXg/+evc+NQWk70fJi/05N75VUDksF3avMbfe5i8kMWl+eb2blwljxwkb/aTyAdnBltrrGTYS769Tt5KMpxO7cPk+cVzObC9ek9yWHk+i5U9dyRf3k/e78mV+Bs5bH3oObmY+9fl5OvXkr+1JDlKHp0jH0UOW6+SjD25cpQ8unl4z5R8M9Z2uGhT/bTtliS96hvLVR64EFP9tO2Tid77nnOBi2fTdrOyw8Vf4f1TDHwBCB2EDggdEDogdEDogNABoQNCB6EDQgeEDggdEDogdEDogNBB6IDQAaEDQgeEDggdEDogdBC6IwChA0IHhA4IHRA6IHRA6IDQQeiA0AGhA0IHhA4IHRA6IHQQOiB0QOiA0AGhA0IHhA4IHYQOCB0QOiB0QOiA0AGhA0IHhA5CB4QOCB0QOiB0QOiA0AGhg9ABoQNCB4QOCB0QOiB0QOggdEDogNABoQNCB4QOCB0QOiB0EDogdEDogNABoQNCB4QOCB2EDggdEDogdEDogNABoQNCB6EDQgeEDggdEDogdEDogNABoYPQAaEDQgeEDggdEDogdEDoIHRA6IDQAaEDQgeEDggdEDoIHRA6IHRA6IDQAaEDQgeEDggdhA4IHRA6IHRA6IDQAaEDQgehA0IHhA4IHRA6IHRA6IDQQeiA0AGhA0IHhA4IHRA6IHRA6CB0QOiA0AGhA0IHhA4IHRA6CB0QOiB0QOiA0AGhA0IHhA5CB4QOCB0QOiB0QOiA0AGhA0IHoQNCB4QOCB0QOiB0QOiA0EHogNABoQNCB4QOCB0QOiB0EDogdEDogNABoQNCB4QOCB0QOggdEDogdEDogNABoQNCB4QOQgeEDggdEDogdEDogNABoYPQAaEDQgeEDggdEDogdEDogNBB6IDQAaEDQgeEDggdEDogdBA6IHRA6IDQAaEDQgeEDggdhA4IHRA6IHRA6IDQAaEDQgeEDkIHhA4IHRA6IHRA6IDQAaGD0AGhA0IHhA4IHRA6IHRA6CB0QOiA0AGhA0IHhA4IHRA6CN0RgNABoQNCB4QOCB0QOiB0QOggdEDogNABoQNCB4QOCB0QOggdEDogdEDogNABoQNCB4QOQgeEDggdEDogdEDogNABoQNChy9a6K1qchRwAQOf225JUr3/cf58dzRwIfRl221+9878xXI+cCFUnbT9+9PQd5I3KtmfPzbVYfuneUuyv5O8sQl92E8+qtRr80T3vA7bbTqZ6PXafvJxkuH01n13aD+zt8MF2dvnpjcftyRjknYwjq9X8nKSIcmxo4KtdJxkqOTlg3F8fdN4LYLvq+T+w+TdKbl7secDW7Syt+Tvl5KH18lHm8fxtviGtk4+3B2GZ1pVLT4PbEfkaVW1OwzPrJMP50E9ZV7TN3qSYez9/cutfTwm3+knrwbHJjuc/3W9VdWq6ofraXppbnvcfMNw3Q/0JMNR73/YTd7pyeM9uXN+VZjmNcCdHdx+fbFxD63q053ev7/u/RfXR57PiHZIMt6VvQf+WYc/7b1/d/HH9XH+JYKH2xN4bYZ0JamqX+1euvSjg4ODD86KPJ8T65D5tu7SMDw1TtNzY+9PJFn5jxq4feZo10PVb4bWXjwcx1f6otnP+JkbWl7W5a7kgWutPTL1/lAlDx73bqrDLbJT1XvyXqu6esc0vf2P5E9ndfr/GOJCDs6blv++ZzvTvwEnGinSTNAg8QAAAABJRU5ErkJggg==') center/100% 100% no-repeat;
  mask:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAFeCAYAAACsFgJxAAAGcElEQVR42u3az4uuZR3H8c/3umfOPMeDuRCVQgoXbcKF2DJzISrugiBaqK1aubX+igp3/gHtwsitWYairjI5C6GFkJRaKLSI6MwzP+77ajH3M92c5uiJ4Jx5xtcLZmB+MXDB+/l+72smuTlDkhbgPGlzm5+rbuLrlWRKklXy1bG1b03T9FCvenDqfddZwy2quuqoen+vtXZ1mKa318lfFsH3+e1/Dn1IMibJXvL4UfJcT55McqU7c7ht5mivVdWvd3t/8TD5bb+u2ZsNfUgyrlb52tFB/WTq/XuLuMf5laMcOdxym/aGTcCt6qXdvf7j9Tp/vlHsdaPIh+TJnvx8Su6bV/c+rwgCh/MR/LRpvSWfVPKDMXn1rNivf5DfSTKuWnt2TH45JXcmOc5/LuNEDudng980edyTL1XV03utfXDc+9W55emsiX4yyYc8No2nO/9migPn25SkKultyBPjmN8tJ/sm9JakX06+sk7e7ck9IoetjL1V8ukqeXg/+evc+NQWk70fJi/05N75VUDksF3avMbfe5i8kMWl+eb2blwljxwkb/aTyAdnBltrrGTYS769Tt5KMpxO7cPk+cVzObC9ek9yWHk+i5U9dyRf3k/e78mV+Bs5bH3oObmY+9fl5OvXkr+1JDlKHp0jH0UOW6+SjD25cpQ8unl4z5R8M9Z2uGhT/bTtliS96hvLVR64EFP9tO2Tid77nnOBi2fTdrOyw8Vf4f1TDHwBCB2EDggdEDogdEDogNABoQNCB6EDQgeEDggdEDogdEDogNBB6IDQAaEDQgeEDggdEDogdBC6IwChA0IHhA4IHRA6IHRA6IDQQeiA0AGhA0IHhA4IHRA6IHQQOiB0QOiA0AGhA0IHhA4IHYQOCB0QOiB0QOiA0AGhA0IHhA5CB4QOCB0QOiB0QOiA0AGhg9ABoQNCB4QOCB0QOiB0QOggdEDogNABoQNCB4QOCB0QOiB0EDogdEDogNABoQNCB4QOCB2EDggdEDogdEDogNABoQNCB6EDQgeEDggdEDogdEDogNABoYPQAaEDQgeEDggdEDogdEDoIHRA6IDQAaEDQgeEDggdEDoIHRA6IHRA6IDQAaEDQgeEDggdhA4IHRA6IHRA6IDQAaEDQgehA0IHhA4IHRA6IHRA6IDQQeiA0AGhA0IHhA4IHRA6IHRA6CB0QOiA0AGhA0IHhA4IHRA6CB0QOiB0QOiA0AGhA0IHhA5CB4QOCB0QOiB0QOiA0AGhA0IHoQNCB4QOCB0QOiB0QOiA0EHogNABoQNCB4QOCB0QOiB0EDogdEDogNABoQNCB4QOCB0QOggdEDogdEDogNABoQNCB4QOQgeEDggdEDogdEDogNABoYPQAaEDQgeEDggdEDogdEDogNBB6IDQAaEDQgeEDggdEDogdBA6IHRA6IDQAaEDQgeEDggdhA4IHRA6IHRA6IDQAaEDQgeEDkIHhA4IHRA6IHRA6IDQAaGD0AGhA0IHhA4IHRA6IHRA6CB0QOiA0AGhA0IHhA4IHRA6CN0RgNABoQNCB4QOCB0QOiB0QOggdEDogNABoQNCB4QOCB0QOggdEDogdEDogNABoQNCB4QOQgeEDggdEDogdEDogNABoQNChy9a6K1qchRwAQOf225JUr3/cf58dzRwIfRl221+9878xXI+cCFUnbT9+9PQd5I3KtmfPzbVYfuneUuyv5O8sQl92E8+qtRr80T3vA7bbTqZ6PXafvJxkuH01n13aD+zt8MF2dvnpjcftyRjknYwjq9X8nKSIcmxo4KtdJxkqOTlg3F8fdN4LYLvq+T+w+TdKbl7secDW7Syt+Tvl5KH18lHm8fxtviGtk4+3B2GZ1pVLT4PbEfkaVW1OwzPrJMP50E9ZV7TN3qSYez9/cutfTwm3+knrwbHJjuc/3W9VdWq6ofraXppbnvcfMNw3Q/0JMNR73/YTd7pyeM9uXN+VZjmNcCdHdx+fbFxD63q053ev7/u/RfXR57PiHZIMt6VvQf+WYc/7b1/d/HH9XH+JYKH2xN4bYZ0JamqX+1euvSjg4ODD86KPJ8T65D5tu7SMDw1TtNzY+9PJFn5jxq4feZo10PVb4bWXjwcx1f6otnP+JkbWl7W5a7kgWutPTL1/lAlDx73bqrDLbJT1XvyXqu6esc0vf2P5E9ndfr/GOJCDs6blv++ZzvTvwEnGinSTNAg8QAAAABJRU5ErkJggg==') center/100% 100% no-repeat;}
.card.cv .cv-frame{position:absolute;inset:0;width:100%;height:100%;display:block;}
/* Name: Molten Display, sits just above the frame's divider line. */
.card.cv .cv-name{position:absolute;left:8%;right:6%;top:78.125%;transform:translateY(-50%);height:auto;line-height:1;font-family:'Sunday Masthead','ThestralNeue',serif;font-weight:normal;font-size:7.5px;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:clip;letter-spacing:.06em;}
/* Keyword row (below divider): icon badge on the left, keyword name in Bluu. */
/* Keyword glyph, tinted to the card's own colour (--symcol, set per card in render.js; Black
   stays white). The art is white-on-alpha, so it's used as a MASK and the colour comes from
   background-color — an <img> can't be recoloured without a filter chain. */
.card.cv .cv-sym{position:absolute;left:16%;top:89%;width:17px;height:17px;
  /* +14%, anchored bottom-right, nudged up 1px (translate centres it; scale grows up-left). */
  transform:translate(-50%,calc(-50% - 1px)) scale(1.14); transform-origin:100% 100%;
  background-color:var(--symcol,#fff); display:block;
  -webkit-mask:var(--symsrc) center/contain no-repeat; mask:var(--symsrc) center/contain no-repeat;}
.card.cv .cv-kw{position:absolute;left:25%;right:22%;top:89%;transform:translateY(-50%);text-align:left;line-height:1;font-family:'BluuNext',serif;font-weight:700;font-size:10.5px;color:#fff;white-space:nowrap;overflow:hidden;letter-spacing:.02em;text-transform:uppercase;}
/* Power number: Momo Trust Display, bottom-right. */
/* Power number rides at the same nudged-up baseline as the ability icon. */
.card.cv .cv-pow{position:absolute;right:9%;top:89%;transform:translateY(calc(-50% - 1px));font-family:'DM Sans','Momo Trust Display',var(--mono);font-weight:700;font-size:21px;color:#fff;line-height:1;}
.card.cv .cv-dmg{position:absolute; left:4.5%; top:4%; z-index:8; display:flex; gap:2px; flex-wrap:wrap; justify-content:flex-start; max-width:46%; background:rgba(6,10,15,.55); padding:2px 3px; border-radius:6px;}
.card.cv .cv-dmg:empty{display:none;}
.card.cv .cv-dmg i{width:11.6px;height:11.6px;border-radius:50%;background:var(--danger);box-shadow:0 0 4px rgba(228,87,46,.85);}
.card.cv .cv-buff{position:absolute;left:4%;bottom:31%;display:flex;gap:2px;flex-wrap:wrap;justify-content:flex-start;max-width:55%;}
.card.cv .cv-buff i{width:11.6px;height:11.6px;border-radius:50%;background:var(--accent);box-shadow:0 0 5px rgba(70,194,168,.95);}

.card.cv .facedown{border-radius:6px;}
#deckstats,#discview{position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(2,5,9,.66);z-index:200;}
#deckstats.show,#discview.show{display:flex;}
#deckstats .dscard,#discview .dvcard{background:#0d1622;border:1px solid rgba(255,255,255,.14);border-radius:12px;padding:16px 18px;box-shadow:0 18px 50px rgba(0,0,0,.6);color:#dce6f2;}
#deckstats .dscard{width:min(460px,92vw);max-height:86vh;overflow:auto;}
#discview .dvcard{width:min(820px,95vw);max-height:90vh;display:flex;flex-direction:column;}
.dshead,.dvhead{display:flex;align-items:center;gap:8px;font-weight:800;font-size:16px;color:var(--gold);margin-bottom:12px;font-family:var(--display);}
.dshead span,.dvhead span{color:#8aa0b3;font-weight:600;font-size:12px;}
.dsx,.dvx{margin-left:auto;background:none;border:none;color:#8aa0b3;font-size:16px;cursor:pointer;}
#dsBody .dssec{margin-bottom:14px;}
#dsBody h4{margin:0 0 6px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:#9fb2c6;}
#dsBody .dsrow{display:flex;align-items:center;gap:8px;margin:3px 0;font-size:12px;}
#dsBody .dslbl{min-width:88px;color:#c7d4e2;}
#dsBody .dsbar{flex:1;height:12px;border-radius:6px;background:rgba(255,255,255,.06);overflow:hidden;}
#dsBody .dsbar i{display:block;height:100%;background:linear-gradient(90deg,#d2aa4c,#9c7a2e);}
#dsBody .dsnum{min-width:26px;text-align:right;color:#9fb2c6;}
#dsBody .dsrow.dszero{opacity:.5;}
#dsBody .dsrow.dszero .dsnum{color:#e88; font-weight:700;}
#discview .dvgrid{display:flex;flex-wrap:wrap;gap:12px;overflow:auto;padding:8px 2px;justify-content:center;align-content:flex-start;}
#discview .dvempty{color:#8aa0b3;padding:30px;font-size:13px;}
.card.back{width:125px;height:179px;border-radius:6px;background:var(--cardback, url(CardBack.png)) center/cover no-repeat, repeating-linear-gradient(45deg,#16202c,#16202c 7px,#1d2a38 7px,#1d2a38 14px);border:1px solid #2c3e50;}
.card.back .facedown{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:0;color:transparent;}
.cardback{width:125px;height:179px;border-radius:6px;flex:none;background:var(--cardback, url(CardBack.png)) center/cover no-repeat, #16212c;border:1px solid #2c3e50;font-size:0;color:transparent;}
#gogwait{position:fixed;inset:0;z-index:999;display:none;align-items:center;justify-content:center;background:rgba(6,10,15,.9);color:#e9eef3;font:600 18px/1.6 system-ui,sans-serif;text-align:center;padding:24px;}
#gogwait small{display:block;margin-top:8px;color:#8aa0b3;font-weight:500;font-size:13px;}
#gogwait button{margin-top:14px;}
#assetstatus{font-family:var(--mono);font-size:10px;color:var(--muted);}
.hidehand{margin-left:8px;font-family:var(--mono);font-size:11px;font-weight:700;border:1px solid var(--line);background:#111a24;color:var(--muted);border-radius:7px;padding:3px 9px;cursor:pointer;}
.hidehand.on{background:var(--gold);color:#0a121b;border-color:var(--gold);}
#cardzoom{position:fixed;left:0;top:0;display:none;z-index:99999;pointer-events:none;transform:scale(2.7);transform-origin:top left;filter:drop-shadow(0 16px 40px rgba(0,0,0,.78));}
#kwtip{position:fixed;left:0;top:0;display:none;z-index:100000;pointer-events:none;width:262px;padding:16px 19px;border-radius:12px;background:rgba(9,13,19,.97);border:2.5px solid var(--gold);box-shadow:0 14px 38px rgba(0,0,0,.62), 0 0 0 1px rgba(232,198,107,.45), 0 0 20px rgba(232,198,107,.5);}
#kwtip .kwtip-artist{font-family:var(--font);font-size:12px;font-style:italic;color:#9fb3c6;margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid rgba(232,198,107,.25);}
#kwtip .kwtip-artist:last-child{margin-bottom:0;padding-bottom:0;border-bottom:none;}

/* ---- CURATED TIERS -------------------------------------------------------------------- */
/* Badge under the artist credit, plus the panel treatment. Both are properties of the RENDER,
   so they show wherever the card turns up — including an All Renders game.

   SEAMLESS SWEEP, and why it's in pixels. A repeating gradient shifted by exactly one tile loops
   invisibly — but only if the shift really is one tile. With background-size above 100%, a
   percentage background-position is measured against (container width − image width), which is
   NEGATIVE, so '-200%' is not 'two widths left', it's some other distance entirely. That mismatch
   is what made it drift for a couple of passes and then visibly pop. A px tile shifted by the
   same px is exact at any element size. */
#kwtip .kwtip-tier{font-family:var(--display); font-weight:700; font-size:17px;
  letter-spacing:.13em; text-transform:uppercase;
  margin:-4px 0 10px; padding-bottom:9px; border-bottom:1px solid rgba(232,198,107,.25);
  background-repeat:repeat; background-size:420px 100%;}
#kwtip .kwtip-artist + .kwtip-tier{margin-top:-6px;}
#kwtip .kwtip-tier:last-child{margin-bottom:0; padding-bottom:0; border-bottom:none;}
@keyframes tiersheen{ from{background-position:0 0;} to{background-position:420px 0;} }

/* TOP 100 — brushed silver. Soft, wide stops: the highlight reads as a blurred band of light
   rather than a hard streak. */
#kwtip .kwtip-tier.top{
  background-image:repeating-linear-gradient(100deg,
    #9aa3b2 0%, #aeb7c6 10%, #d8dfec 20%, #f6f9ff 27%, #d8dfec 34%,
    #a8b1c0 44%, #9aa3b2 50%, #b4bdcb 62%, #e4eaf5 74%, #b0b9c8 86%, #9aa3b2 100%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
  animation:tiersheen 7s linear infinite;}
#kwtip.tier-top{border-color:#aab2c2;
  box-shadow:0 14px 38px rgba(0,0,0,.62), 0 0 0 1px rgba(210,220,236,.5), 0 0 24px rgba(180,196,220,.42);}
#kwtip.tier-top::after{content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background-repeat:repeat; background-size:420px 100%;
  background-image:repeating-linear-gradient(100deg, transparent 0%, transparent 22%,
    rgba(226,236,252,.05) 30%, rgba(255,255,255,.16) 38%, rgba(226,236,252,.05) 46%, transparent 54%, transparent 100%);
  filter:blur(6px); animation:tiersheen 7s linear infinite; mix-blend-mode:screen;}

/* TOP 5 — foil. Same mechanism, chromatic, with a rim that never settles. */
#kwtip .kwtip-tier.foil{
  background-image:repeating-linear-gradient(100deg,
    #ff2aaa 0%, #ffc400 12%, #00ffb2 24%, #00a8ff 36%, #b23cff 48%,
    #ff2aaa 60%, #ffc400 74%, #00ffb2 86%, #ff2aaa 100%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
  animation:tiersheen 5s linear infinite;}
#kwtip.tier-foil{border-color:#d9a6ff; animation:foilrim 1.6s ease-in-out infinite;}
#kwtip.tier-foil::after{content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background-repeat:repeat; background-size:420px 100%;
  background-image:repeating-linear-gradient(100deg, transparent 0%, transparent 16%,
    rgba(255,42,170,.16) 24%, rgba(0,255,178,.22) 32%, rgba(0,168,255,.20) 40%,
    rgba(178,60,255,.16) 46%, transparent 54%, transparent 100%);
  filter:blur(7px) saturate(1.6); animation:tiersheen 5s linear infinite; mix-blend-mode:screen;}
@keyframes foilrim{
  0%  {box-shadow:0 14px 38px rgba(0,0,0,.62), 0 0 0 1px rgba(255,140,220,.55), 0 0 18px rgba(255,110,210,.45), 0 0 34px rgba(120,220,255,.20);}
  33% {box-shadow:0 14px 38px rgba(0,0,0,.62), 0 0 0 1px rgba(150,240,255,.60), 0 0 26px rgba(120,220,255,.50), 0 0 40px rgba(200,140,255,.26);}
  66% {box-shadow:0 14px 38px rgba(0,0,0,.62), 0 0 0 1px rgba(215,160,255,.58), 0 0 20px rgba(200,140,255,.46), 0 0 30px rgba(255,150,210,.22);}
  100%{box-shadow:0 14px 38px rgba(0,0,0,.62), 0 0 0 1px rgba(255,140,220,.55), 0 0 18px rgba(255,110,210,.45), 0 0 34px rgba(120,220,255,.20);}
}
#kwtip > *{position:relative; z-index:1;}

/* ---- THE CARDS THEMSELVES ------------------------------------------------------------- */
/* A curated render is shiny in play, not only in the tooltip. .tiershine is a child element
   rather than a pseudo, because .card already spends ::before/::after on the armour plate —
   which leaves the child's OWN two pseudos free for the foil treatment below. */
.card .tiershine{position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:5;
  overflow:hidden;}
@keyframes cardsheen{ from{background-position:0 0;} to{background-position:420px 0;} }
@keyframes bandsweep{ from{-webkit-mask-position:0 0; mask-position:0 0;}
                      to  {-webkit-mask-position:420px 0; mask-position:420px 0;} }

/* TOP 100: a soft silver band travelling across the face. */
.card.tier-top .tiershine{mix-blend-mode:screen;
  background-repeat:repeat; background-size:420px 100%;
  background-image:repeating-linear-gradient(102deg, transparent 0%, transparent 24%,
    rgba(226,236,252,.06) 32%, rgba(255,255,255,.22) 40%, rgba(226,236,252,.06) 48%, transparent 56%, transparent 100%);
  filter:blur(5px); animation:cardsheen 6.5s linear infinite;}
.card.tier-top{box-shadow:0 0 0 1px rgba(206,216,234,.55), 0 0 12px rgba(178,196,222,.35);}

/* TOP 5: the sweep works ON THE ART. ::before is a second copy of the card's own artwork,
   inverted and saturated, masked to a travelling band — so where the band passes, the picture
   itself flips to a luminous negative. ::after lays the rainbow over that same band.

   Tuned to read like real foil rather than a light saber:
     - TWO bands per tile at different widths, so the highlight isn't a single even stripe;
     - the mask ramps in and out over ~14% instead of 6%, so edges are soft, not cut;
     - a faint tint persists across the whole card (the mask floors at .10 rather than 0), the
       way foil is always slightly iridescent and not only where the light hits;
     - hard-light instead of color-dodge, which blows out to white on bright art;
     - slower, and the two layers run at different speeds so the colour and the relief drift
       apart and back together instead of moving as one rigid object. */
.card.tier-foil .tiershine{isolation:isolate;}
.card.tier-foil .tiershine::before{content:''; position:absolute; inset:0;
  background:var(--cardart) center/cover no-repeat;
  filter:invert(1) saturate(1.8) contrast(1.15);
  mix-blend-mode:hard-light; opacity:.5;
  -webkit-mask-image:repeating-linear-gradient(104deg,
    rgba(0,0,0,.10) 0%, rgba(0,0,0,.10) 20%, rgba(0,0,0,.55) 30%, #000 36%,
    rgba(0,0,0,.55) 42%, rgba(0,0,0,.10) 52%, rgba(0,0,0,.10) 66%,
    rgba(0,0,0,.42) 74%, rgba(0,0,0,.62) 79%, rgba(0,0,0,.42) 84%,
    rgba(0,0,0,.10) 92%, rgba(0,0,0,.10) 100%);
  mask-image:repeating-linear-gradient(104deg,
    rgba(0,0,0,.10) 0%, rgba(0,0,0,.10) 20%, rgba(0,0,0,.55) 30%, #000 36%,
    rgba(0,0,0,.55) 42%, rgba(0,0,0,.10) 52%, rgba(0,0,0,.10) 66%,
    rgba(0,0,0,.42) 74%, rgba(0,0,0,.62) 79%, rgba(0,0,0,.42) 84%,
    rgba(0,0,0,.10) 92%, rgba(0,0,0,.10) 100%);
  -webkit-mask-size:420px 100%; mask-size:420px 100%;
  -webkit-mask-repeat:repeat; mask-repeat:repeat;
  animation:bandsweep 7s linear infinite;}
.card.tier-foil .tiershine::after{content:''; position:absolute; inset:0;
  background-repeat:repeat; background-size:420px 100%;
  background-image:repeating-linear-gradient(104deg,
    rgba(255,42,170,.10) 0%, rgba(255,42,170,.10) 18%,
    rgba(255,196,0,.34) 28%, rgba(0,255,178,.44) 35%, rgba(0,168,255,.40) 42%,
    rgba(178,60,255,.30) 49%, rgba(255,42,170,.12) 58%, rgba(255,42,170,.10) 70%,
    rgba(0,255,178,.22) 77%, rgba(0,168,255,.20) 82%, rgba(255,42,170,.10) 90%,
    rgba(255,42,170,.10) 100%);
  mix-blend-mode:screen; filter:blur(5px) saturate(1.5);
  animation:cardsheen 8.5s linear infinite;}
.card.tier-foil{animation:foilcard 3.4s ease-in-out infinite;}
@keyframes foilcard{
  0%  {box-shadow:0 0 0 1px rgba(255,140,220,.6), 0 0 14px rgba(255,110,210,.5), 0 0 26px rgba(120,220,255,.28);}
  33% {box-shadow:0 0 0 1px rgba(150,240,255,.65), 0 0 18px rgba(120,220,255,.55), 0 0 30px rgba(200,140,255,.30);}
  66% {box-shadow:0 0 0 1px rgba(215,160,255,.62), 0 0 15px rgba(200,140,255,.5), 0 0 26px rgba(255,150,210,.28);}
  100%{box-shadow:0 0 0 1px rgba(255,140,220,.6), 0 0 14px rgba(255,110,210,.5), 0 0 26px rgba(120,220,255,.28);}
}
@media (prefers-reduced-motion:reduce){
  #kwtip .kwtip-tier, #kwtip.tier-top::after, #kwtip.tier-foil::after, #kwtip.tier-foil,
  .card .tiershine, .card.tier-foil, .card.tier-foil .tiershine::before,
  .card.tier-foil .tiershine::after{animation:none;}
  /* The emboss is static geometry, not motion — it stays. Only the drift stops. */
  #kwtip .kwtip-tier.top{color:#dfe6f2; background:none; -webkit-text-fill-color:currentColor;}
  #kwtip .kwtip-tier.foil{color:#f0b6ff; background:none; -webkit-text-fill-color:currentColor;}
}}}
/* ThestralNeue ships ONLY as a Bold face, so asking for 900 made the browser synthesize extra
   weight on top of it and smear the strokes. Both stay on the theme font at a true 700 (its
   real face) — the description just gets size and spacing so the bold reads cleanly. */
#kwtip .kwtip-name{font-family:var(--font);font-weight:700;font-synthesis-weight:none;color:var(--gold);font-size:17.5px;letter-spacing:.4px;margin-bottom:8px;}
#kwtip .kwtip-text{font-family:var(--font);font-weight:700;font-synthesis-weight:none;font-size:15px;line-height:1.42;letter-spacing:.5px;word-spacing:.08em;color:#eee2cf;}
#cardzoom .card{margin:0!important;cursor:default;box-shadow:none;}

/* UI pass */
.center{display:none;}
.banner{text-align:center; padding:2px 0;}   /* absolutely positioned — see .banner above */
.playarea{justify-content:center; align-items:center; gap:30px;}
.grid{flex:0 0 auto; grid-template-columns:repeat(4,138px); grid-template-rows:186px 186px;
  justify-content:center; align-content:center; margin:auto; gap:12px 14px;
  /* Uniform scale from the centre — like grabbing a corner with shift+ctrl. */
  transform:scale(var(--board-scale, 1.12)); transform-origin:center center;}
.lane{min-height:0; height:186px;}
.hand{justify-content:center;}
.life{font-size:26px;}
/* HEALTH COUNTER — rebuilt clean. */
/* HEALTH COUNTER — fixed box. */
.life.big{ position:relative; box-sizing:border-box; flex:0 0 auto;
  font-family:'Momo Trust Display','BluuNext',serif; font-size:57px; font-weight:400; line-height:1;
  width:2.5em; height:1.35em; border-radius:16px; display:block;
  background:radial-gradient(120% 130% at 50% 50%, rgba(70,194,168,.06), transparent 70%), rgba(8,11,16,.62);
  /* Frosts whatever sits behind it — the corner of the seat art tucked underneath, mainly. Needs
     the background to stay semi-transparent, or there's nothing to see through. */
  -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
  border:1px solid var(--line); box-shadow:0 8px 22px rgba(0,0,0,.5); }
/* (blood/liquid health fill removed) */
/* (overflow:hidden removed — it was for the old liquid bars; the flying -N needs to escape) */
.life.big .lifenum{ z-index:3; }
/* The NUMBER is absolutely centred on the box — its centre is pinned to the box centre via */
.life.big .lifenum{ position:absolute; left:calc(50% + 0.3em); top:50%; z-index:3;   /* nudged right 0.3em, still self-centred on that point */
  transform:translate(-50%,-50%); line-height:1; color:#fff; white-space:nowrap; }
/* Red heart on the LEFT of the box, vertically centred, with a heartbeat that quickens as health */
/* Heart INSIDE the box on the LEFT, vertically centred. */
.life.big .heart{ position:absolute; left:0.55em; top:0; bottom:0; z-index:1;
  display:flex; align-items:center; justify-content:center;
  padding-bottom:0.14em;   /* lift the low-rendering glyph to visual centre */
  font-size:0.62em; line-height:1; color:var(--danger); pointer-events:none;
  transform-origin:center; will-change:transform;
  animation:heartbeat 1.9s ease-in-out infinite; }
.life.big.hb-calm  .heart{ animation-duration:1.9s; }
.life.big.hb-quick .heart{ animation-duration:1.25s; }
.life.big.hb-fast  .heart{ animation-duration:0.8s; }
.life.big.hb-crit  .heart{ animation-duration:0.5s; opacity:.5; }
@keyframes heartbeat{
  0%,100% { transform:scale(1); }
  12%     { transform:scale(1.16); }   /* lub */
  24%     { transform:scale(1.0); }
  34%     { transform:scale(1.10); }   /* dub */
  46%     { transform:scale(1); }
}
@media (prefers-reduced-motion: reduce){ .life.big .heart{ animation:none; } }
.life.big{transition:border-color .2s ease, box-shadow .2s ease;}
/* The active player's life box. */
.life.big.myturn.self{border-color:var(--gold); box-shadow:0 8px 22px rgba(0,0,0,.5), 0 0 0 1px var(--gold), 0 0 16px rgba(232,198,107,.45);}
.life.big.myturn:not(.self){border-color:#6aaeeb; box-shadow:0 8px 22px rgba(0,0,0,.5), 0 0 0 1px rgba(106,174,235,.8), 0 0 14px rgba(106,174,235,.36);}
.side{overflow-y:auto;}
/* docks */
.dock{display:flex; align-items:center; justify-content:center; gap:22px; padding:4px;}
.dock-side{display:flex; flex-direction:column; gap:6px; min-width:160px;}
/* The art hangs OFF the left edge, absolutely positioned, so it adds nothing to the dock's flow:
   the life total, name and hand keep the exact positions they had before it existed. */
.dock-left{position:relative;}
.dock-left > .seatstack{display:flex; flex-direction:column; gap:6px; align-items:center;
  position:relative; z-index:1;}   /* over the tucked-in art */
.dock-left{align-items:center; text-align:center;}   /* row direction is set above */
.dock-left .dock-sub{display:flex; flex-direction:column; align-items:center; gap:1px;}
.dock-left .turnflag{font-size:12px;}
.dock .handzone{flex:0 0 auto;}
.dock .hand{justify-content:center; min-width:400px;}
.dock-right{align-items:stretch;}
.dock-right button.full{width:100%; flex:none;}
/* Pass Turn + its auto-pass toggle share one row. */
/* Pass Turn and Confirm Ambush share ONE slot and cross-fade between them. */
.passrow{display:flex; align-items:center; gap:8px;}
.passslot{position:relative; flex:1 1 auto; min-width:0;}
.passslot button.full{width:100%;}
/* Absolutely positioned, so it doesn't inherit the centering a normal in-flow button gets — */
.passslot .amb{position:absolute; inset:0; display:flex; align-items:center; justify-content:center; text-align:center;}
.passslot button{transition:opacity .18s ease, transform .18s ease;}
.passslot button.swapped{opacity:0; pointer-events:none; transform:scale(.96);}
/* Ambush now owns its slot alone (Pass moved to the side-panel tabs). */
.passslot.ambonly{ position:static; }
.passslot.ambonly .amb{ position:static; inset:auto; }
.passslot.ambonly.hidden{ display:none; }
/* sidebar controls */
/* New Game + Forfeit share the row evenly. */
.sidecontrols{display:flex; gap:8px; padding:8px 14px; border-top:1px solid var(--line); align-items:center; flex-wrap:nowrap;}
.sidecontrols button{padding:6px 12px; font-size:12px; flex:1 1 0; min-width:0; white-space:nowrap; text-align:center;}

.sidecontrols #assetstatus{font-family:var(--mono); font-size:10px; color:var(--muted); flex:1; text-align:right;}
/* Sits in .foot next to the seed now (it used to end .sidecontrols, hence margin-left:auto — */
/* Fixed width: the label swaps to "Link copied ✓" on click, which is much wider than "Room #" */
.roomchip{font-family:var(--mono); font-weight:800; font-size:11px; letter-spacing:1.2px;
  color:var(--gold); background:linear-gradient(180deg,rgba(210,170,76,.16),rgba(156,122,46,.10));
  border:1px solid rgba(210,170,76,.55); border-radius:6px; padding:4px 9px; cursor:pointer;
  transition:background .12s, box-shadow .12s, transform .06s; white-space:nowrap;
  flex:none; width:124px; text-align:center; overflow:hidden; text-overflow:ellipsis;}
.roomchip:hover{background:linear-gradient(180deg,rgba(210,170,76,.28),rgba(156,122,46,.18)); box-shadow:0 0 12px rgba(210,170,76,.35);}
.roomchip:active{transform:translateY(1px);}
.roomchip.copied{color:#8fe0a0; border-color:rgba(120,210,140,.6);}
/* deck + discard as card-sized stacks */
.pile{width:auto; gap:5px;}
.pileface{width:125px; height:179px; border-radius:8px; display:flex; align-items:center; justify-content:center; font-family:var(--mono);}
.deck .pileface{background:var(--cardback, url(CardBack.png)) center/cover no-repeat, repeating-linear-gradient(45deg,#16202c,#16202c 7px,#1d2a38 7px,#1d2a38 14px);
  color:var(--gold); font-size:30px; font-weight:800; text-shadow:0 2px 8px rgba(0,0,0,.95), 0 0 5px rgba(0,0,0,.9); box-shadow:0 0 0 2px rgba(232,198,107,.55), 0 8px 22px rgba(0,0,0,.5);}
.discard .pileface{background:#0b1119; position:relative; overflow:hidden; padding:0;}
/* Draw pile thickness. --dkx/--dky = depth, set from the card count in render.js. The base
   is pinned and the top card lifts up-left. Keep the layer count FIXED: box-shadow only
   interpolates against an equal-length list. */
.pile.deck .pileface{ transform:translate(calc(-1 * var(--dkx, 0px)), calc(-1 * var(--dky, 0px)));
  /* Matched to the per-card draw stagger; slower smears the steps together. */
  transition:box-shadow .1s linear, transform .1s linear, background .2s ease;
  box-shadow:0 0 0 2px rgba(232,198,107,.55),
    calc(var(--dkx, 0px) * 0.0625) calc(var(--dky, 0px) * 0.0625) 0 0 #22303f,
    calc(var(--dkx, 0px) * 0.1250) calc(var(--dky, 0px) * 0.1250) 0 0 #131e29,
    calc(var(--dkx, 0px) * 0.1875) calc(var(--dky, 0px) * 0.1875) 0 0 #22303f,
    calc(var(--dkx, 0px) * 0.2500) calc(var(--dky, 0px) * 0.2500) 0 0 #131e29,
    calc(var(--dkx, 0px) * 0.3125) calc(var(--dky, 0px) * 0.3125) 0 0 #22303f,
    calc(var(--dkx, 0px) * 0.3750) calc(var(--dky, 0px) * 0.3750) 0 0 #131e29,
    calc(var(--dkx, 0px) * 0.4375) calc(var(--dky, 0px) * 0.4375) 0 0 #22303f,
    calc(var(--dkx, 0px) * 0.5000) calc(var(--dky, 0px) * 0.5000) 0 0 #131e29,
    calc(var(--dkx, 0px) * 0.5625) calc(var(--dky, 0px) * 0.5625) 0 0 #22303f,
    calc(var(--dkx, 0px) * 0.6250) calc(var(--dky, 0px) * 0.6250) 0 0 #131e29,
    calc(var(--dkx, 0px) * 0.6875) calc(var(--dky, 0px) * 0.6875) 0 0 #22303f,
    calc(var(--dkx, 0px) * 0.7500) calc(var(--dky, 0px) * 0.7500) 0 0 #131e29,
    calc(var(--dkx, 0px) * 0.8125) calc(var(--dky, 0px) * 0.8125) 0 0 #22303f,
    calc(var(--dkx, 0px) * 0.8750) calc(var(--dky, 0px) * 0.8750) 0 0 #131e29,
    calc(var(--dkx, 0px) * 0.9375) calc(var(--dky, 0px) * 0.9375) 0 0 #22303f,
    calc(var(--dkx, 0px) * 1.0000) calc(var(--dky, 0px) * 1.0000) 0 0 #131e29,
    0 8px 14px -6px rgba(0,0,0,.55); }
.pile.deck.empty .pileface{ --dkx:0px; --dky:0px; background:none; border-color:transparent;
  box-shadow:none; color:transparent; text-shadow:none; }
/* The count is mirrored onto #deckFloat (see paintDeckFloat) so it stays above cards in
   flight; the face keeps the text for layout but paints it invisibly to avoid a double. */
.pile.deck .pileface{ color:transparent; }   /* the count is mirrored onto #deckFloat below */
/* .pile.deck gets a `drawing` class while cards are in flight (setDeckDrawing). Left
   unstyled on purpose: hiding the face made the deck look empty mid-draw. */
.pile.deck.empty .pileface{ --dkx:0px; --dky:0px; background:none; border-color:transparent;
  box-shadow:none; color:transparent; text-shadow:none; }
/* Count mirrored here so it sits above cards in flight; the face paints its own copy
   invisibly (it's inside the transformed .playarea, so no z-index there can rise above). */
#deckFloat{ position:absolute; left:0; top:0; z-index:400; pointer-events:none;
  font-family:var(--mono); font-size:30px; font-weight:800; color:var(--gold);
  text-shadow:0 2px 8px rgba(0,0,0,.95), 0 0 5px rgba(0,0,0,.9);
  transition:transform .1s linear; }

/* A big faint skull watermarked ON the pile face, the way the Guard ward sits on a card: it says */
.discard .pileface::after{ content:'\2620'; position:absolute; inset:0; z-index:1;
  display:flex; align-items:center; justify-content:center;
  font-size:88px; line-height:1; color:#dfe9f4; opacity:.13; pointer-events:none;
  text-shadow:0 2px 10px rgba(0,0,0,.7); }
/* When the discard.png icon is loaded (--discard-icon set by JS), use it instead of the ☠ glyph */
.discard .pileface.hasdiscardicon::after{ content:''; opacity:1;
  background:var(--discard-icon) center/62% no-repeat;
  opacity:.16; text-shadow:none; filter:brightness(0) invert(1); }
.discard.empty .pileface.hasdiscardicon::after{ opacity:.26; }
/* Empty pile: no art to compete with, so let it read a little stronger. */
.discard.empty .pileface::after{ opacity:.22; }
.discard.empty .pileface{color:var(--muted); font-size:12px;}
#discTop{width:125px; height:179px;}
#discTop .card{margin:0;}
#discTop .pileminicard{position:absolute; inset:0; width:125px; height:179px; pointer-events:none; cursor:default;}
.disccount{position:absolute; right:5px; bottom:5px; background:rgba(6,10,15,.82); color:#cfe0ee;
  font-size:11px; padding:1px 6px; border-radius:6px; z-index:3;}
.pile .lbl{font-size:11px; margin-top:4px;}
.deck .lbl{color:var(--gold); font-weight:700;}
.deck .lbl,.discard .lbl{font-weight:800; letter-spacing:1.5px;}
.shufbtn{position:absolute; top:50%; margin:0; z-index:4;
  writing-mode:vertical-rl; text-orientation:mixed; font:700 9.5px/1 var(--mono,monospace); letter-spacing:1.5px;
  color:#cfe0ee; background:#16202c; border:1px solid #2c3e50; border-radius:6px; padding:10px 4px; cursor:pointer;}
.pile.deck .shufbtn{left:100%; margin-left:7px; transform:translateY(-50%) rotate(180deg);}     /* left side reads bottom-to-top */
.pile.discard .shufbtn{right:100%; margin-right:7px; transform:translateY(-50%);}                /* right side reads top-to-bottom */
.shufbtn:hover{background:#1d2a38; border-color:var(--gold); color:var(--gold);}
.pile.deck .shufbtn:active{transform:translateY(-50%) rotate(180deg) translateX(1px);}
.pile.discard .shufbtn:active{transform:translateY(-50%) translateX(1px);}
@keyframes pileShuffle{0%{transform:translate(calc(-1 * var(--dkx, 0px)), calc(-1 * var(--dky, 0px))) translateX(0px) rotate(0deg)}15%{transform:translate(calc(-1 * var(--dkx, 0px)), calc(-1 * var(--dky, 0px))) translateX(-6px) rotate(-3deg)}30%{transform:translate(calc(-1 * var(--dkx, 0px)), calc(-1 * var(--dky, 0px))) translateX(6px) rotate(3deg)}45%{transform:translate(calc(-1 * var(--dkx, 0px)), calc(-1 * var(--dky, 0px))) translateX(-5px) rotate(-2deg)}60%{transform:translate(calc(-1 * var(--dkx, 0px)), calc(-1 * var(--dky, 0px))) translateX(5px) rotate(2deg)}75%{transform:translate(calc(-1 * var(--dkx, 0px)), calc(-1 * var(--dky, 0px))) translateX(-2px) rotate(-1deg)}100%{transform:translate(calc(-1 * var(--dkx, 0px)), calc(-1 * var(--dky, 0px))) translateX(0px) rotate(0deg)}}
.pile.shuffling .pileface{animation:pileShuffle .5s ease-in-out;}
.playarea{position:relative;}
.lane,.pile{position:relative; z-index:1;}
.deckbracket{flex:0 0 auto; align-self:stretch; width:30px; margin:16px 0; display:flex; align-items:center; justify-content:center;
  border-left:2px solid rgba(232,198,107,.5); border-top:2px solid rgba(232,198,107,.5); border-bottom:2px solid rgba(232,198,107,.5);
  border-radius:9px 0 0 9px;}
.deckbracket span{writing-mode:vertical-rl; transform:rotate(180deg); font-family:var(--display,serif); font-weight:800;
  letter-spacing:3px; font-size:11px; text-transform:uppercase; color:rgba(232,198,107,.74); white-space:nowrap;}
/* draw animation ghost */
.drawghost{position:fixed; z-index:9000; border-radius:8px; pointer-events:none;
  /* Keep the real cardback (from .cardback) on top and the stripes only as a fallback layer:
     this rule sits after .cardback at equal specificity, so a bare `background` here erased it. */
  background:var(--cardback) center/cover no-repeat,
    repeating-linear-gradient(45deg,#16212c,#16212c 6px,#1f2d3a 6px,#1f2d3a 12px);
  border:1px solid #2c3e50; box-shadow:0 10px 24px rgba(0,0,0,.55);}
/* lock interface to a 16:9 stage that scales to fit */
html,body{height:100%; margin:0; overflow:hidden; overscroll-behavior:none; background:#0b0806;}
body{display:flex; align-items:center; justify-content:center;}
.app{width:1600px; height:900px; flex:none; position:relative; transform-origin:center center; touch-action:none;}
/* Backdrop is chosen at runtime via the board picker (assets/gameboards). */
.app{ background-color:#04070b; }
/* thin the two big UI panels so the backdrop shows through; cards and the life/turn readouts stay fully solid */
.playarea{ background:
    radial-gradient(120% 130% at 50% 50%, rgba(70,194,168,.05), transparent 70%),
    repeating-linear-gradient(45deg, rgba(255,255,255,.012) 0 12px, transparent 12px 24px),
    rgba(15,42,24,.58) !important; }
.side{ background:linear-gradient(var(--logtint, transparent), var(--logtint, transparent)), rgba(9,13,19,.94) !important; transition:background .25s ease; }
.side .head{ background:radial-gradient(120% 90% at 50% 0%, var(--logtint, transparent), transparent 75%); transition:background .25s ease; }
/* With a gameboard active, drop the opaque play-area felt so the board shows through the whole */
.main.has-board{ background-clip:padding-box; }
.main.has-board .playarea{ background:rgba(8,11,16,.28) !important; }
/* Thin static golden [ in the gap between the deck and the play space — a subtle, always-on cue */
.combatbracket{ position:absolute; left:200px; top:16%; bottom:16%; width:7px; z-index:6; pointer-events:none;
  border-left:1.5px solid var(--gold); border-top:1.5px solid var(--gold); border-bottom:1.5px solid var(--gold);
  border-radius:2px 0 0 2px; opacity:.7; }
/* impact: softly flash the half that took damage */
.hitflash{position:absolute; left:0; right:0; height:34%; pointer-events:none; opacity:0; z-index:60;}
.hitflash.top{top:0; background:linear-gradient(to bottom, rgba(228,87,46,.45), rgba(228,87,46,0));}
.hitflash.bot{bottom:0; background:linear-gradient(to top, rgba(228,87,46,.45), rgba(228,87,46,0));}
@keyframes hitpulse{0%{opacity:0;}10%{opacity:1;}100%{opacity:0;}}
.hitflash.show{animation:hitpulse .85s cubic-bezier(.2,.7,.2,1);}

/* Gauntlet of Gods — dark-fantasy skin */
.brandlogo{display:block; width:100%; max-width:270px; height:auto; margin:0 auto 2px;
  filter:drop-shadow(0 2px 5px rgba(0,0,0,.75)) drop-shadow(0 0 16px rgba(202,161,72,.13));}
.brandlink{display:block; cursor:pointer; text-decoration:none;}
.brandlink:hover .brandlogo{ filter:drop-shadow(0 2px 5px rgba(0,0,0,.75)) drop-shadow(0 0 20px rgba(202,161,72,.4)); transition:filter .18s ease; }
.side{background:linear-gradient(180deg,#16110a 0%,#0c0907 100%); border-left:1px solid #4a3a22;
  box-shadow:inset 1px 0 0 rgba(202,161,72,.12);}
.side .head{padding:14px 14px 10px; border-bottom:1px solid rgba(202,161,72,.18);
  background:radial-gradient(120% 80% at 50% 0%, rgba(202,161,72,.06), transparent 72%);}

/* carved type on headings + chrome */
.pinfo .name,.turnflag,.banner{font-family:var(--display); letter-spacing:.6px;}
/* Opponent name: click to hide (player-supplied text — see render.js). */
.nameclick{cursor:pointer; border-bottom:1px dotted rgba(202,161,72,.45);}
.nameclick:hover{color:#e8cf86;}
.namehidden{opacity:.6; font-style:italic; border-bottom-style:dashed;}
#netlobby h2,#modal h3,.box h2,.box h3,#mTitle{font-family:var(--display); letter-spacing:.6px; color:var(--gold);}
#ref .setrow>b{font-family:var(--display); letter-spacing:.4px;}

/* buttons — gilt + ember + steel (setup seg buttons keep their own bg via higher specificity) */
button{font-family:var(--display); letter-spacing:.6px; text-transform:uppercase;
  background:linear-gradient(180deg,#d2aa4c,#9c7a2e); color:#1c1408; border:1px solid #5a4528;
  box-shadow:0 2px 6px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.14);}
button:hover{filter:brightness(1.07);}
button.alt{background:linear-gradient(180deg,#241d14,#150f08); color:var(--ink); border:1px solid #4a3a22; box-shadow:0 2px 6px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.05);}
button.go{background:linear-gradient(180deg,#c4452b,#7e2818); color:#ffe6d8; border:1px solid #843521; text-shadow:0 1px 2px rgba(0,0,0,.45);}
button.pass{background:linear-gradient(180deg,#3f6068,#21383d); color:#e6f5f7; border:1px solid #406066;}
button.disc{background:linear-gradient(180deg,#6a4ea8,#3f2d6b); color:#efe9ff; border:1px solid #5a4690;}

/* tabs + pills */
.tab{background:#1a130b; color:var(--muted); border:1px solid #3a2f22; letter-spacing:.5px; font-family:var(--display); font-size:11px;}
.tab.on{background:linear-gradient(180deg,#d2aa4c,#9c7a2e); color:#1c1408; border-color:#5a4528;}
/* Tiny Pass tucked into the bottom-right corner of the whole main area — outside the docks */
.cornerpass{ position:absolute; right:14px; bottom:12px; z-index:6;
  padding:6px 20px; font-size:14px; font-weight:700; letter-spacing:.6px; text-transform:uppercase;
  background:linear-gradient(180deg,#3f6068,#21383d); color:#e6f5f7;
  border:1px solid #406066; border-radius:8px; font-family:var(--display);
  box-shadow:0 1px 4px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.14); cursor:pointer;
  opacity:.5; transition:opacity .15s ease; }
.cornerpass:hover:not(:disabled){ opacity:1; }
.cornerpass:disabled{ opacity:.2; cursor:default; filter:none; }
.pill{background:#160f08; border:1px solid #3a2f22;}

/* play surface — dark warm stone, ember glow, gilt inner frame */
.playarea{border:1px solid #4a3a22;
  background:
    radial-gradient(120% 130% at 50% 40%, rgba(200,92,42,.07), transparent 60%),
    repeating-linear-gradient(45deg, rgba(255,236,205,.014) 0 12px, transparent 12px 24px),
    radial-gradient(150% 120% at 50% 0%, #251a11, #100b07 62%);
  box-shadow:inset 0 0 0 1px rgba(202,161,72,.14), inset 0 0 60px rgba(0,0,0,.6);}
.grid .midline{border-top:1.5px dashed rgba(202,161,72,.45);}

/* setup selected states -> gilt */
#ref .segbtn.on,#ref .powbtn.on,#ref .tdbtn.on{background:linear-gradient(180deg,#d2aa4c,#9c7a2e); color:#1c1408; border-color:#5a4528;}

/* warm-stone override (kills the green felt + navy + tints the board image) */
.app{ background:
    radial-gradient(75% 45% at 50% -6%, rgba(190,72,30,.20), transparent 62%),
    radial-gradient(120% 85% at 50% 2%, #251a11 0%, var(--bg) 58%),
    var(--bg) !important; position:relative; }
.app::before{ content:''; position:fixed; inset:0; z-index:0; pointer-events:none;
  background:#0b0806; }
.app::after{ content:''; position:fixed; inset:0; z-index:0; pointer-events:none;
  background:
    radial-gradient(78% 52% at 50% -6%, rgba(205,92,40,.15), transparent 60%),
    radial-gradient(125% 100% at 50% 120%, rgba(0,0,0,.62), transparent 55%); }
/* Hide the opponent's action buttons — you can't interact with them either way. */
/* Your opponent's action controls stay laid out (so both docks keep the same size) but are never */
.app.seat0 .dock-top .dock-right button{ visibility:hidden; }
.app.seat1 .dock-bot .dock-right button{ visibility:hidden; }

/* Both players' names sit under their own health box (.pname). */
.pname-right{ display:none; }
/* auto-pass slider toggle (beside the seed input) */
.autoPassWrap{ position:relative; display:inline-flex; align-items:center; justify-content:center; gap:7px; cursor:pointer; user-select:none; padding:2px 0;
  white-space:nowrap; font-family:'Cinzel',serif; font-weight:600; font-size:10px;
  letter-spacing:.08em; text-transform:uppercase; color:var(--muted);
  transition:color .18s ease; }
.autoPassWrap:hover{ color:#c9b98f; }
/* hide the native box; the slider below is the control */
.autoPassChk{ position:absolute; opacity:0; width:0; height:0; pointer-events:none; }
.autoPassWrap .sw{ position:relative; width:30px; height:15px; flex:none; border-radius:999px;
  background:#0e0b07; border:1px solid var(--line); transition:border-color .18s ease, background .18s ease;
  box-shadow:inset 0 1px 3px rgba(0,0,0,.6); }
.autoPassWrap .sw::after{ content:''; position:absolute; top:1px; left:1px; width:11px; height:11px;
  border-radius:50%; background:linear-gradient(180deg,#6b5f47,#3f3626);
  transition:transform .18s cubic-bezier(.4,0,.2,1), background .18s ease, box-shadow .18s ease; }
/* ON */
.autoPassChk:checked + .sw{ background:linear-gradient(180deg,#4a3a1c,#2a2010); border-color:var(--gold); }
.autoPassChk:checked + .sw::after{ transform:translateX(15px);
  background:linear-gradient(180deg,#e8cf86,var(--gold)); box-shadow:0 0 7px rgba(202,161,72,.75); }
.autoPassChk:checked ~ .lbl{ color:var(--gold); }
/* keyboard focus */
.autoPassChk:focus-visible + .sw{ box-shadow:0 0 0 2px rgba(202,161,72,.45); }
/* locked (guest, or game started) */
.autoPassWrap.locked{ opacity:.42; cursor:default; }
.autoPassWrap.locked:hover{ color:var(--muted); }
/* Swarm hand reveal: a centered strip of the revealed hand, shown to both players. */
/* Swarm: an opponent hand card flipped face-up stays revealed with a gold outline. */
.card.swarm-revealed{ box-shadow:0 0 0 2px rgba(232,194,69,.9), 0 0 14px rgba(232,194,69,.55) !important; }
/* SEAT MIRRORING P2's board used */
.app.seat1 .main{ flex-direction:column-reverse; }
.main,.side{ position:relative; z-index:1; }

/* play surface: warm translucent so the stone texture reads through */
.playarea{ background:
    radial-gradient(120% 130% at 50% 42%, rgba(205,95,42,.06), transparent 60%),
    repeating-linear-gradient(45deg, rgba(255,236,205,.012) 0 13px, transparent 13px 26px),
    rgba(26,19,11,.46) !important;
  border:1px solid #4a3a22 !important;
  box-shadow:inset 0 0 0 1px rgba(202,161,72,.13), inset 0 0 60px rgba(0,0,0,.5) !important; }
.side{ background:
    linear-gradient(var(--logtint, transparent), var(--logtint, transparent)),
    /* very gradual fade across the FULL width: transparent at the board edge, easing to the panel */
    linear-gradient(90deg,
      rgba(18,12,7,0) 0%, rgba(18,12,7,.06) 25%, rgba(16,11,7,.22) 55%,
      rgba(14,10,7,.5) 82%, rgba(12,9,6,.8) 100%) !important;
  border-left:none !important; transition:background .25s ease; }

/* cards: dark leather instead of navy */
.card{ background:linear-gradient(160deg,#271a0f,#140d08) !important; border:1px solid #4a3a22 !important; }
.card .swatch{ background:linear-gradient(160deg, var(--cc) 0%, color-mix(in srgb, var(--cc) 38%, #100a06) 100%) !important; }
.card .frame{ background:linear-gradient(180deg, rgba(14,9,5,.15), rgba(10,7,4,.62)) !important; border:1px solid rgba(202,161,72,.18) !important; }
.card .kw{ background:rgba(12,8,4,.52) !important; border-top:1px solid rgba(202,161,72,.16) !important; }

/* warm the last few blue-gray bits */
.pill,.foot input{ background:#160f08 !important; border:1px solid #3a2f22 !important; }
.hidehand{ background:#1a130b !important; border:1px solid #3a2f22 !important; }
.volleypick button{ background:linear-gradient(180deg,#241d14,#150f08) !important; border:1px solid #4a3a22 !important; color:#f0e7d6 !important; }
#log .e{ color:#cdbfa6; }
.lane.p1{ background:rgba(127,176,188,.05); }

/* selector targeting: dim the card + big centred white keyword symbol */
.tgtmark{position:absolute; inset:0; z-index:30; display:flex; align-items:center; justify-content:center; border-radius:var(--card-r); background:rgba(5,8,13,.52); pointer-events:none;}
.tgtmark img{width:60%; height:60%; object-fit:contain; filter:brightness(0) invert(1) drop-shadow(0 2px 8px rgba(0,0,0,.9)); opacity:.98; animation:tgtpop 1.15s ease-in-out infinite;}
.tgtmark .g{font-size:46px; line-height:1; color:#fff; font-weight:900; text-shadow:0 2px 10px rgba(0,0,0,.9); animation:tgtpop 1.15s ease-in-out infinite;}
@keyframes tgtpop{0%,100%{transform:scale(1);} 50%{transform:scale(1.1);}}
/* Drag-to-replace hint: the Replace icon stamped on a card the dragged card would swap out. */
.replacemark{position:absolute; inset:0; z-index:20; display:flex; align-items:center; justify-content:center; border-radius:var(--card-r); background:rgba(20,10,4,.42); pointer-events:none;}
.replacemark img{width:52%; height:52%; max-width:64px; max-height:64px; object-fit:contain; filter:brightness(0) invert(1) drop-shadow(0 2px 8px rgba(0,0,0,.9)); opacity:.95; animation:tgtpop 1.15s ease-in-out infinite;}
.replacemark{color:#ffdca8; font-size:40px; font-weight:900; text-shadow:0 2px 10px rgba(0,0,0,.9);}

/* flying: glow the flyer being chosen + symbol on destination tiles */
.card.flyactive{ outline:3px solid #5cc8ff; outline-offset:1px; z-index:6;
  box-shadow:0 0 26px rgba(92,200,255,.95), inset 0 0 0 2px rgba(92,200,255,.6) !important;
  animation:flyactivepulse 1s ease-in-out infinite; }
@keyframes flyactivepulse{0%,100%{box-shadow:0 0 16px rgba(92,200,255,.72), inset 0 0 0 2px rgba(92,200,255,.5) !important;} 50%{box-shadow:0 0 34px rgba(92,200,255,1), inset 0 0 0 2px rgba(92,200,255,.75) !important;}}
.tgtmark.empty{ background:rgba(92,200,255,.12); }
.tgtmark img{ max-width:74px; max-height:74px; }
.flylabel.flystay{ color:#cdeeff; font-weight:800; }

/* combat juice: floating damage, life-number hit, screen shake */
.life{position:relative;}
.dmgchunk{position:fixed; transform:translateX(-50%); font-family:'Momo Trust Display','BluuNext',serif; font-weight:400; font-size:26px; color:#ff6a45; text-shadow:0 2px 8px rgba(0,0,0,.85); pointer-events:none; z-index:80; animation:dmgfly 1s cubic-bezier(.2,.7,.3,1) forwards;}
.dmgchunk.big{font-size:42px; color:#ff3a1e; text-shadow:0 0 20px rgba(255,70,30,.85), 0 3px 12px rgba(0,0,0,.9); animation:dmgflybig 1.3s cubic-bezier(.2,.8,.3,1) forwards;}
@keyframes dmgfly{0%{opacity:0; transform:translate(-50%,8px) scale(.6);} 18%{opacity:1; transform:translate(-50%,-12px) scale(1.12);} 100%{opacity:0; transform:translate(-50%,-50px) scale(.9);}}
@keyframes dmgflybig{0%{opacity:0; transform:translate(-50%,12px) scale(.5) rotate(-7deg);} 14%{opacity:1; transform:translate(-50%,-16px) scale(1.5) rotate(4deg);} 42%{transform:translate(-50%,-26px) scale(1.28) rotate(-2deg);} 100%{opacity:0; transform:translate(-50%,-76px) scale(1.05);}}
.life.lifehit{animation:lifehit .42s ease-out;}
.life.lifehitbig{animation:lifehitbig .62s cubic-bezier(.2,.8,.2,1);}
@keyframes lifehit{0%{scale:1;} 30%{scale:1.18; color:#ff6a4a;} 100%{scale:1;}}
@keyframes lifehitbig{0%{scale:1;} 20%{scale:1.5; color:#ff3a1e;} 45%{scale:1.18;} 100%{scale:1;}}
.life.lifeheal{animation:lifeheal .5s ease-out;}
@keyframes lifeheal{0%{scale:1;} 35%{scale:1.22; color:#76e0a0;} 100%{scale:1;}}
/* The shake transforms .app — the ENTIRE board (every card, shadow, blend mode). */
.app.shaking{animation:shakejolt var(--shkdur,.5s) cubic-bezier(.3,.6,.3,1);
  will-change:transform; backface-visibility:hidden;}
@keyframes shakejolt{0%{transform:translate(0,0) scale(var(--appscale,1));}11%{transform:translate(calc(var(--shk,8px)*-1), calc(var(--shk,8px)*.5)) scale(var(--appscale,1));}23%{transform:translate(var(--shk,8px), calc(var(--shk,8px)*-.6)) scale(var(--appscale,1));}36%{transform:translate(calc(var(--shk,8px)*-.72), calc(var(--shk,8px)*.34)) scale(var(--appscale,1));}50%{transform:translate(calc(var(--shk,8px)*.62), calc(var(--shk,8px)*.4)) scale(var(--appscale,1));}64%{transform:translate(calc(var(--shk,8px)*-.46), calc(var(--shk,8px)*-.22)) scale(var(--appscale,1));}78%{transform:translate(calc(var(--shk,8px)*.3), 0) scale(var(--appscale,1));}100%{transform:translate(0,0) scale(var(--appscale,1));}}

/* How To Play: floating button (home page, bottom-right) + fullscreen image modal */
#htpBtn{position:fixed; right:18px; bottom:18px; z-index:150; width:56px; height:56px;
  display:flex; align-items:center; justify-content:center; cursor:pointer; padding:0;
  background:none; border:none; box-shadow:none; transition:transform .15s ease, filter .15s ease;}
#htpBtn:hover{transform:translateY(-2px) scale(1.06); filter:drop-shadow(0 0 8px rgba(202,161,72,.55));}
#htpBtn img{width:100%; height:100%; object-fit:contain; filter:drop-shadow(0 2px 4px rgba(0,0,0,.6));}
#htpBtn .htpFallback{font-family:var(--display); font-size:34px; font-weight:800; color:var(--gold); line-height:1;}
#htpModal{position:fixed; inset:0; display:none; align-items:center; justify-content:center;
  background:rgba(2,5,9,.86); z-index:400; padding:24px;}
#htpModal.show{display:flex;}
#htpModal .htpImgWrap{position:relative; max-width:96vw; max-height:94vh; display:flex; align-items:center; justify-content:center;}
#htpModal img{max-width:96vw; max-height:94vh; width:auto; height:auto; object-fit:contain;
  border-radius:10px; box-shadow:0 18px 60px rgba(0,0,0,.7); border:1px solid rgba(202,161,72,.35);}
#htpModal .htpX{position:absolute; top:-14px; right:-14px; width:38px; height:38px; border-radius:50%;
  background:#0d1622; border:2px solid var(--gold); color:var(--ink); font-size:18px; cursor:pointer;
  display:flex; align-items:center; justify-content:center; line-height:1; box-shadow:0 4px 14px rgba(0,0,0,.6);}

/* In-game credits: small "i" info button + credits modal */
#infoBtn{width:30px; height:30px; border-radius:50%; flex:0 0 auto; cursor:pointer; padding:0;
  display:flex; align-items:center; justify-content:center; font-family:var(--display); font-weight:800;
  font-size:16px; font-style:italic; text-transform:none; color:var(--gold); background:linear-gradient(180deg,#1b232e,#121821);
  border:1.5px solid rgba(202,161,72,.6); transition:transform .15s ease, box-shadow .15s ease;}
#infoBtn:hover{transform:scale(1.08); box-shadow:0 0 12px rgba(202,161,72,.5);}
#infoModal{position:fixed; inset:0; display:none; align-items:center; justify-content:center;
  background:rgba(2,5,9,.72); z-index:400; padding:24px;}
#infoModal.show{display:flex;}
#infoModal .infoCard{background:#0d1622; border:1px solid rgba(202,161,72,.35); border-radius:12px;
  padding:22px 26px; width:min(460px,94vw); max-height:88vh; overflow:auto; color:var(--ink);
  box-shadow:0 18px 50px rgba(0,0,0,.65); text-align:center;}
#infoModal .infoHead{margin-bottom:14px;}
#infoModal .infoHead h3{font-family:var(--display); color:var(--gold); font-size:20px; margin:0; text-align:center;}
#infoModal .infoBody{font-size:14px; line-height:1.6;}
#infoModal .infoBody a{color:var(--accent); text-decoration:none;}
/* Icon-artist credits: names are toggles; the open one reveals their link + icon list. */
#infoModal .iconArtists{margin-top:8px; display:flex; flex-wrap:wrap; gap:6px 8px; justify-content:center;}
#infoModal .iaName{padding:3px 11px; font-size:12.5px; border-radius:999px; cursor:pointer;
  color:var(--gold); background:rgba(202,161,72,.08); border:1px solid rgba(202,161,72,.35);
  transition:background .12s ease;}
#infoModal .iaName:hover{background:rgba(202,161,72,.18);}
#infoModal .iaName.open{background:rgba(202,161,72,.25); color:#ffe9b8;}
#infoModal .iaPanel{flex-basis:100%; display:none; padding:8px 6px 4px; font-size:12.5px; line-height:1.55;}
#infoModal .iaPanel.open{display:block;}
#infoModal .iaPanel .iaLink{display:block; margin-bottom:4px; word-break:break-all;}
#infoModal .iaPanel .iaIcons{color:#b8c2cf;}
#infoModal .infoBody a:hover{text-decoration:underline;}
#infoModal .infoSect{margin:16px 0;}
#infoModal .infoSect .lbl{font-family:var(--display); color:var(--gold); font-size:13px; letter-spacing:.5px; text-transform:uppercase; margin-bottom:6px;}
#infoModal .infoSect .val{color:var(--ink);}
#infoModal .testers{list-style:none; margin:0; padding:0; color:var(--muted);}
#infoModal .testers li{padding:2px 0;}
#infoModal .proto{margin-top:18px; padding-top:14px; border-top:1px solid rgba(202,161,72,.2);
  font-style:italic; color:var(--muted); font-size:12px; letter-spacing:.5px;}




/* HOME SCREEN */
#lobby{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;z-index:100;color:#e8dcc0;font-family:'Cinzel',serif;overflow:hidden;
  background:radial-gradient(120% 90% at 50% 8%, #2a2a2e 0%, #1c1c1f 42%, #141416 100%);}
/* the rising glow of fire at the bottom */
#lobby .firelow{position:absolute;left:0;right:0;bottom:0;height:38%;pointer-events:none;z-index:0;
  background:radial-gradient(120% 100% at 50% 130%, rgba(255,120,30,.42) 0%, rgba(210,70,20,.24) 32%, rgba(120,40,15,.10) 55%, transparent 72%);
  animation:fireflicker 3.6s ease-in-out infinite;}
@keyframes fireflicker{0%,100%{opacity:.85;transform:translateY(0)}50%{opacity:1;transform:translateY(-6px)}}
#lobby .home-inner{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;gap:14px;padding:20px;}
#lobby .home-logoimg{width:min(560px,80vw);height:auto;margin-bottom:6px;transform:translateX(-20px);
  filter:drop-shadow(0 4px 18px rgba(0,0,0,.75)) drop-shadow(0 0 34px rgba(202,161,72,.28));
  animation:logoglow 4s ease-in-out infinite;}
@keyframes logoglow{0%,100%{filter:drop-shadow(0 4px 18px rgba(0,0,0,.75)) drop-shadow(0 0 30px rgba(202,161,72,.22));}
  50%{filter:drop-shadow(0 4px 18px rgba(0,0,0,.75)) drop-shadow(0 0 40px rgba(230,120,40,.4));}}
/* backdrop-filter is kept deliberately: it smooths the gradient banding behind the card. */
/* ---- BUTTONS -----------------------------------------------------------------------------
   One language for every button in the lobby AND the settings window: an outlined rectangle over
   a blurred, barely-there fill, with Cinzel small-caps. The colour lives in the border and the
   text; hover raises the fill rather than swapping the hue. Nothing is a solid slab any more. */
.btnq{
  font-family:'Cinzel',serif; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
  background:rgba(202,161,72,.07); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  border:1px solid rgba(202,161,72,.5); border-radius:2px; color:#f0e2c4; cursor:pointer;
  box-shadow:none; transition:background .16s ease, border-color .16s ease, color .16s ease;}
.btnq:hover{background:rgba(202,161,72,.17); border-color:rgba(232,198,107,.95); color:#fff6e2;}
.btnq:active{background:rgba(202,161,72,.24);}
.btnq:disabled{opacity:.4; background:rgba(255,255,255,.02);
  border-color:rgba(255,255,255,.12); color:var(--muted); cursor:default;}
/* Quiet variant: same shape, no colour until you touch it. */
.btnq.ghost{background:rgba(255,255,255,.03); border-color:rgba(255,255,255,.16); color:var(--muted);}
.btnq.ghost:hover{background:rgba(255,255,255,.07); border-color:rgba(202,161,72,.7); color:var(--ink);}

#lobby button, #lobby .bigbtn{
  font-family:'Cinzel',serif; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
  background:rgba(202,161,72,.07); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  border:1px solid rgba(202,161,72,.5); border-radius:2px; color:#f0e2c4; box-shadow:none;
  transition:background .16s ease, border-color .16s ease, color .16s ease;}
#lobby button:hover, #lobby .bigbtn:hover{background:rgba(202,161,72,.17);
  border-color:rgba(232,198,107,.95); color:#fff6e2;}
#lobby button:disabled{opacity:.4; background:rgba(255,255,255,.02);
  border-color:rgba(255,255,255,.12); color:var(--muted);}
#lobby .setbtn{background:rgba(255,240,214,.03); border:1px solid rgba(120,96,58,.4);}

/* Squarer inputs and buttons across the lobby, matching the panels. */
#lobby input, #lobby button{border-radius:2px;}
#lobby #joinCode{letter-spacing:.34em; font-family:var(--mono);}
/* The code + Join pair spans exactly as wide as Create a game above it. */
/* The code + Join pair spans exactly the width of Create a game above: the row fills, the code
   box takes whatever Join doesn't. box-sizing so the input's padding can't push it wider. */
#lobby .row.friendrow{display:flex; gap:8px; align-items:stretch; width:100%;}
#lobby .row.friendrow > #joinCode{flex:1 1 auto; min-width:0; width:auto; box-sizing:border-box;
  text-align:center;}
#lobby .row.friendrow > #btnJoin{flex:0 0 104px; padding-left:0; padding-right:0;}

/* ---- LOBBY -----------------------------------------------------------------------------
   Squarer and flatter than before. The old cards were 14px-rounded, warm-filled and shadowed,
   which read as friendly rather than considered. These are near-square panels with a hairline
   edge and a single warm accent, so the artwork carries the mood and the chrome stays quiet. */
#lobby .lcard{background:linear-gradient(180deg, rgba(20,17,13,.90), rgba(13,11,9,.92));
  border:1px solid rgba(120,96,58,.45); border-radius:3px; padding:0; min-width:340px;
  display:flex; flex-direction:column; gap:0;
  box-shadow:0 24px 70px rgba(0,0,0,.62), inset 0 1px 0 rgba(255,240,214,.05);
  backdrop-filter:blur(4px);}
/* A single hairline of gold along the top edge — the only ornament either panel gets. */
#lobby .lcard::before{content:''; display:block; height:1px; flex:none;
  background:linear-gradient(90deg, transparent, rgba(202,161,72,.55) 18%, rgba(202,161,72,.55) 82%, transparent);}

#lobbyProfile .ptitle{font-family:var(--mono); font-size:9.5px; letter-spacing:.28em;
  text-transform:uppercase; color:var(--muted); margin-bottom:2px;}
#lobbyProfile #userName{border-radius:2px; text-align:center;}

/* Panes are a FIXED height. Practice used to grow a 260px settings list inside the box, which
   made the panel jump every time you changed tab; its setup lives in a modal now and the pane
   shows a one-line summary instead. Centred vertically so short panes sit in the middle. */

/* The settings button: a quiet row, label over summary, not a call to action. */
.setbtn{display:flex; flex-direction:column; align-items:flex-start; gap:3px; width:100%;
  padding:10px 13px; cursor:pointer; text-align:left;
  background:rgba(255,240,214,.03); border:1px solid rgba(120,96,58,.4); border-radius:2px;
  transition:border-color .15s ease, background .15s ease;}
.setbtn:hover{border-color:rgba(202,161,72,.75); background:rgba(255,240,214,.06);}
.setbtnLbl{font-family:'Cinzel',serif; font-weight:600; font-size:10px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--muted);}
.setbtnSum{font-family:var(--font); font-size:12.5px; color:var(--ink); letter-spacing:.02em;}

/* CPU settings modal: same shell as the art picker. */

/* One static panel, no tabs. Everything is visible at once, so nothing resizes and there's no
   state to remember. A FIXED width, because the panel used to grow to fit whichever pane had the
   longest line of text — switching tabs jumped its width by a factor of three. */
#lobbyMain{width:360px; min-width:360px; padding:20px 22px 6px; gap:0;}
#lobby .lsec{display:flex; flex-direction:column; gap:9px; padding:14px 0;}
#lobby .lsec + .lsec{border-top:1px solid rgba(120,96,58,.28);}
#lobby .lsec:first-of-type{padding-top:2px;}
#lobby .lsechead{font-family:'Cinzel',serif; font-weight:600; font-size:10px; letter-spacing:.26em;
  text-transform:uppercase; color:var(--muted);}
#lobby .bigbtn{width:100%; padding:13px 16px; border-radius:2px; font-size:14px;}
#lobby .status{padding:0 22px 18px;}
/* Practice: pool toggle and the deck parameters. */
#lobby .pracrow{display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:9px 0; border-top:1px solid rgba(120,96,58,.22); border-bottom:1px solid rgba(120,96,58,.22);}
#lobby .pracrow[hidden]{display:none;}
#lobby .praclbl{font-family:var(--mono); font-size:10px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--muted);}
/* Slider toggle: two labels either side of the track, the active one lit. */
/* The old solid-gold slab lived HERE, after the outlined rules above and with #lobby's higher
   specificity, so it silently won and every button in the lobby AND in the settings window (which
   sits inside #lobby) rendered filled. Only size and cursor remain; appearance comes from .btnq. */
#lobby button{padding:12px 14px; cursor:pointer; font-size:15px;}
#lobby button.ghost{background:rgba(255,255,255,.03); border-color:rgba(255,255,255,.16); color:var(--muted);}
#lobby button.ghost:hover{background:rgba(255,255,255,.07); border-color:rgba(202,161,72,.7); color:var(--ink);}
#lobby input{background:#12100b;border:1px solid #4a3a22;border-radius:9px;color:#f0e6cf;padding:12px;font-size:16px;text-align:center;font-family:'Cinzel',serif;}
#lobby #userName{font-size:21px; padding:13px 12px;}
#lobby #userName{letter-spacing:.04em;text-transform:none;font-weight:700;}
/* Name colour: cosmetic only, stored locally and echoed to the other seat by the server. */
/* Two columns: Profile on the left, the login card on the right. */
#lobby .lrow{display:flex; gap:14px; align-items:stretch; justify-content:center; flex-wrap:wrap;}
/* Banish: concentric gold light pulses emanating from the Banish card itself, fading out
   before they reach the board's edge (the element's size caps the reach; opacity dies first). */
.banishpulse{position:fixed; z-index:8500; pointer-events:none; border-radius:50%;
  border:3px solid rgba(255,240,196,.95);
  box-shadow:0 0 26px rgba(232,198,107,.6), inset 0 0 20px rgba(232,198,107,.4);
  mix-blend-mode:screen; opacity:0;
  transform:translate(-50%,-50%) scale(.05);
  animation:banishring 1.05s cubic-bezier(.2,.6,.3,1) forwards;}
@keyframes banishring{0%{transform:translate(-50%,-50%) scale(.05); opacity:0;}
  12%{opacity:.95;} 62%{opacity:.4;}
  100%{transform:translate(-50%,-50%) scale(1); opacity:0;}}
/* Haste window: a drawn-this-turn Haste card VIBRATES — half quickjitter's amplitude
   (1px / 0.7deg vs 2px / 1.4deg) at 2.5x its speed (.2s vs .5s) — plus the gold pulse. */
.card.hasteglow{box-shadow:0 0 0 2px rgba(255,214,90,.8), 0 0 16px rgba(255,196,60,.5);
  animation:hastejitter .2s ease-in-out infinite, hastepulse 1.1s ease-in-out infinite;}
@keyframes hastejitter{
  0%,100%{ transform:translateY(0) rotate(0deg); }
  25%{ transform:translateY(-1px) rotate(-.7deg); }
  75%{ transform:translateY(-1px) rotate(.7deg); }
}
@keyframes hastepulse{50%{box-shadow:0 0 0 3px rgba(255,226,130,.95), 0 0 26px rgba(255,206,80,.8);}}
/* SWARM allocation: a small count on each card you've assigned damage to. Sits on the target
   marker so it rides with the same overlay every other picker uses. */
.tgtmark .swarmn{position:absolute; right:6px; bottom:6px; min-width:24px; height:24px; padding:0 6px;
  border-radius:999px; background:#caa148; color:#12100a; border:2px solid rgba(0,0,0,.55);
  font-family:var(--mono); font-size:13px; font-weight:700; line-height:1;
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 2px 8px rgba(0,0,0,.7); animation:none;}
/* Spent pool: cards with nothing assigned dim out, the ones holding damage stay lit. */
.lane.swarmspent{opacity:.4; filter:grayscale(.7);}

/* Rally picked marker: the Rally icon in a clear green, STATIC (no pulse), with a green
   ring so a selection reads at a glance. */
.tgtmark.pickedmark{background:rgba(9,26,12,.5);
  box-shadow:inset 0 0 0 2px rgba(110,232,124,.65), inset 0 0 18px rgba(110,232,124,.22);}
.tgtmark.pickedmark img{animation:none;
  filter:brightness(0) invert(1) sepia(1) saturate(4) hue-rotate(72deg) brightness(1.15)
    drop-shadow(0 0 6px rgba(110,232,124,.7)) drop-shadow(0 2px 8px rgba(0,0,0,.9));}
.tgtmark.pickedmark .g{animation:none; color:#6ee87c; text-shadow:0 0 10px rgba(110,232,124,.6), 0 2px 8px rgba(0,0,0,.9);}
/* Picker source-card CANCEL. Identical to every other target marker — same overlay, same white
   icon, same pulse — with the circle-slash instead of the ability glyph. It IS a choice, so it
   must not look like a disabled card: the old greyscale on the card dimmed the stamp with it,
   since a parent filter applies to everything inside.
   Only .theirs greys out, because a pick you're watching genuinely isn't yours to take. */
.tgtmark.cancelmark.theirs .g, .tgtmark.cancelmark.theirs img{animation:none; opacity:.8;}
/* Afflict: glossy coloured bubbles that drift from the opponent's cards and pop on the target. */
.affbubble{position:fixed; z-index:9200; pointer-events:none; border-radius:50%;
  background:
    radial-gradient(circle at 32% 28%, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 30%),
    radial-gradient(circle at 50% 50%, transparent 38%, var(--bubc) 66%, transparent 90%),
    radial-gradient(circle at 50% 50%, var(--bubc) 0%, transparent 68%);
  opacity:1; box-shadow:0 0 12px var(--bubc), 0 0 4px var(--bubc), inset 0 0 4px rgba(255,255,255,.5);
  transition:left .64s cubic-bezier(.3,.55,.35,1), top .64s cubic-bezier(.3,.55,.35,1);}
.affbubble.pop{animation:affpop .24s ease-out forwards;}
@keyframes affpop{40%{transform:scale(1.5); opacity:.9;} 100%{transform:scale(2.1); opacity:0;}}
/* Login card rows: flex with a real gap, centered relative to the card. The primary pair
   (Create a game / Find a match) split the card's width evenly, so they sit perfectly
   centered under the username field; the code row gives Join breathing room. */
#lobby #lobbyMain .row{display:flex; gap:10px; width:100%; justify-content:center; align-items:stretch;}
#lobby #lobbyMain .row.primary button{flex:1 1 0; min-width:0;}
/* The two matchmaking entries. Each carries a subtitle, so they're taller than a plain button
   and the label stacks. Top 100 gets a silver treatment to match its card badge. */
/* Host setup: the card-pool choice. Two mutually exclusive options in the same segmented
   control style as Powers, with Top 100 tinted silver to match its badge. */
.poolseg{display:flex; gap:6px;}
.poolseg .poolopt{font-family:var(--mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  padding:6px 11px; border-radius:7px; cursor:pointer; white-space:nowrap;
  background:rgba(255,255,255,.05); color:var(--muted); border:1px solid rgba(255,255,255,.14);}
.poolseg .poolopt:hover{color:var(--ink); border-color:rgba(255,255,255,.3);}
.poolseg .poolopt.on{background:rgba(232,198,107,.16); color:var(--gold); border-color:var(--gold);}
.poolseg .poolopt.top.on{background:linear-gradient(160deg, rgba(226,232,244,.22), rgba(140,150,168,.14));
  color:#e6ecf7; border-color:#aab2c2;}

/* Matchmaking: ONE queue, with the pool preference beside the button rather than a second
   button. Splitting the queue halves everyone's pool of opponents, which is the wrong trade for
   a small player base — a preference costs nothing when it isn't shared. */
#lobby .row.mmrow{align-items:stretch;}
#lobby .row.mmrow > button{flex:1 1 auto;}
/* [hidden] is a UA rule and any author display beats it, so it needs saying explicitly. */
/* Hosting and joining are the same errand — starting a game with someone you know — so they
   share a row, with solo play below. The code box is sized to five characters rather than
   stretched, so Create a game keeps the visual weight. */
/* Left over from when Create a game shared this row; it pinned the code box to 92px and won by
   coming later in the file. The row now holds only the code + Join, and spans the full width so
   the pair lines up exactly with the Create a game button above it. */

#lobby #joinCode{flex:1 1 auto; min-width:0; text-align:center;
  letter-spacing:.22em; text-transform:uppercase;}
#lobby #btnJoin{flex:0 0 auto; padding-left:24px; padding-right:24px;}
/* "or join with a code" separator: centered label with hairline rules either side. */
#lobby .orsep{display:flex; align-items:center; gap:10px; width:100%; margin:2px 0;
  font-size:11px; letter-spacing:.14em; text-transform:uppercase; color:#8a7f6d;
  text-align:center;}
#lobby .orsep::before, #lobby .orsep::after{content:''; flex:1 1 0; height:1px;
  background:linear-gradient(90deg, transparent, #4a3a22);}
#lobby .orsep::after{background:linear-gradient(90deg, #4a3a22, transparent);}
#lobby .orsep span{flex:0 0 auto;}
/* Physical-edition promo bubble: floats top-left of the lobby, clicks through to the
   store; a hover-revealed X hides it and the choice is remembered (localStorage). */
#promoBubble{position:fixed; left:22px; bottom:22px; z-index:80; display:block;
  width:256px; cursor:pointer; text-decoration:none;
  transition:transform .16s ease;
  filter:drop-shadow(0 10px 22px rgba(0,0,0,.55));}
#promoBubble[hidden]{display:none;}
#promoBubble:hover{transform:scale(1.04);
  filter:drop-shadow(0 12px 26px rgba(0,0,0,.6)) drop-shadow(0 0 16px rgba(202,161,72,.35));}
#promoBubble img{display:block; width:100%; height:auto; pointer-events:none;}
#promoBubble .promoFloat{display:block; position:relative;
  /* The drift lives HERE, transform-only (compositor thread — the old margin-top bob
     re-laid-out the page every frame, hence the chop). Slow wandering path, not a bob. */
  animation:promoFloat 14s ease-in-out infinite; will-change:transform;}
#promoBubble .promoCta{display:block; margin-top:8px; text-align:center;
  font-family:'Cinzel',var(--display),serif; font-weight:800; font-size:12.5px; letter-spacing:.04em;
  line-height:1.45; white-space:nowrap;
  color:var(--gold); text-shadow:0 2px 8px rgba(0,0,0,.8);}
@media (max-width:820px){ #promoBubble .promoCta{font-size:10px; letter-spacing:.02em;} }
#promoBubble:hover .promoCta{color:#ffe9b8;}
#promoBubble #promoHide{position:absolute; top:0; right:0; width:24px; height:24px; padding:0;
  border-radius:50%; border:1px solid rgba(202,161,72,.5); background:rgba(10,15,22,.85);
  color:#cfc6b4; font-size:15px; line-height:1; cursor:pointer;
  opacity:0; transition:opacity .15s ease;}
#promoBubble:hover #promoHide{opacity:1;}
#promoBubble #promoHide:hover{color:#fff; border-color:var(--gold);}
/* A slow, gentle wander around the corner: four waypoints on different axes so the
   motion never reads as a metronome bob. */
@keyframes promoFloat{
  0%,100%{transform:translate(0,0);}
  25%{transform:translate(5px,-8px);}
  50%{transform:translate(-3px,-13px);}
  75%{transform:translate(-7px,-5px);}
}
@media (prefers-reduced-motion:reduce){ #promoBubble .promoFloat{animation:none;} }
@media (max-width:820px){ #promoBubble{width:150px; left:12px; bottom:12px;} }
/* Quick Match queue panel: centered, with a living ellipsis. */
#lobby #lobbyQueue{align-items:center; text-align:center; gap:12px;}
#lobby .qmsg{font-family:'Cinzel',serif; font-weight:800; font-size:17px;
  letter-spacing:.07em; color:#f3e7cf;}
/* The three dots light up one after another, then rest together — a breathing "..." */
#lobby .qmsg .qdots span{opacity:.18; animation:qdotSeq 1.5s infinite;}
#lobby .qmsg .qdots span:nth-child(2){animation-delay:.22s;}
#lobby .qmsg .qdots span:nth-child(3){animation-delay:.44s;}
@keyframes qdotSeq{0%,65%,100%{opacity:.18;} 22%{opacity:1;}}
@media (prefers-reduced-motion:reduce){ #lobby .qmsg .qdots span{animation:none; opacity:.8;} }
#lobby .ptitle{font-family:var(--display,'Cinzel',serif); font-weight:800; font-size:12px;
  letter-spacing:.24em; text-indent:.24em; text-transform:uppercase; color:#8a7f6d; text-align:center;}
/* The modal itself. Lives inside #lobby, position:fixed so it covers the screen. */
#artModal{position:fixed; inset:0; z-index:5200; display:none; align-items:center;
  justify-content:center; background:rgba(6,5,3,.8);}
#artModal.on{display:flex;}
#artModal .ambox{display:flex; flex-direction:column; gap:9px; width:min(680px,92vw);
  max-height:min(78vh,720px); padding:14px; border:1px solid #6a5730; border-radius:13px;
  background:#14110b; box-shadow:0 14px 60px rgba(0,0,0,.6);}
#artModal .amhead{display:flex; align-items:center; gap:8px;}
#artModal .amtitle{flex:1; font-size:14px; letter-spacing:.14em; text-transform:uppercase; color:#e8c66b;}
#artModal .amclose{flex:0 0 auto; width:28px; height:28px; padding:0; line-height:1; font-size:17px;
  border:1px solid #3c3020; border-radius:7px; background:#100e09; color:#9a8f7c; cursor:pointer;}
#artModal .amclose:hover{border-color:#6a5730; color:#f3e7cf;}
#artModal input{padding:8px 10px; font-size:13px;}
/* Art files are 1000x1400 (5:7): every tile is FORCED to that aspect, so the grid always
   shows the full card frame — object-fit keeps the image undistorted no matter what. */
/* Same themed scrollbar as the in-game panels — not the default block-white bar. */
#artModal .amgrid{ scrollbar-width:thin; scrollbar-color:rgba(202,161,72,.5) transparent; }
#artModal .amgrid::-webkit-scrollbar{ width:8px; height:8px; }
#artModal .amgrid::-webkit-scrollbar-track{ background:transparent; }
#artModal .amgrid::-webkit-scrollbar-thumb{ background:linear-gradient(rgba(202,161,72,.55), rgba(160,120,50,.45));
  border-radius:6px; border:2px solid transparent; background-clip:padding-box; }
#artModal .amgrid::-webkit-scrollbar-thumb:hover{ background:linear-gradient(rgba(232,198,107,.75), rgba(190,150,70,.6));
  background-clip:padding-box; }
#artModal .amgrid{display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:8px; align-content:start;
  flex:1; min-height:120px; overflow-y:auto; padding:4px; border:1px solid #3c3020; border-radius:9px;
  background:#100e09;}
@media (max-width:560px){ #artModal .amgrid{grid-template-columns:repeat(2,minmax(0,1fr));} }
#artModal .amtile{position:relative; display:block; width:100%; height:0; padding:140% 0 0;
  box-sizing:border-box; border-radius:8px; border:1px solid transparent;
  background:#12100b; cursor:pointer; overflow:hidden;}
#artModal .amtile img{position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; display:block;}
#artModal .amtile:hover{border-color:#6a5730;}
#artModal .amtile.sel{border-color:#e8c66b; box-shadow:inset 0 0 0 2px rgba(232,198,107,.35);}
#artModal .amfoot{display:flex; justify-content:flex-end;}
#artModal .amnone{padding:7px 13px; font-size:12px; letter-spacing:.06em; border:1px solid #3c3020;
  border-radius:8px; background:#100e09; color:#9a8f7c; cursor:pointer;}
#artModal .amnone:hover{border-color:#6a5730; color:#f3e7cf;}
/* SEAT ART — the card art each player picked, beside their life total. Absolutely positioned so
   it adds nothing to the dock's flow. Framed like the play area rather than feathered: at this
   size a soft mask ate too much of the artwork, and a hard edge reads as a card. */
/* Tilted to match the outermost card of the hand fan (MAX_ROT is 5deg in render.js), pulled in
   so it tucks BEHIND the life total and name block, and nudged toward the play area. Negative
   z-index puts it under the dock's own contents — the overlap is the point.
   The tilt and the nudge are set per-dock below, NOT here: which dock is 'mine' depends on the
   seat (see the .app.seat0/.seat1 pairs), so keying off .dock-top alone gets it backwards for
   player 2. */
.seatart{position:absolute; right:calc(100% - 34px); z-index:-1;
  width:150px; aspect-ratio:5/7; cursor:pointer;
  background:var(--seatart) center/cover no-repeat;
  /* Hard gold edge, 16px radius to match .playarea's frame. */
  border:1px solid var(--gold); border-radius:16px;
  box-shadow:0 6px 18px rgba(0,0,0,.55);
  opacity:.92; transition:opacity .16s ease, filter .16s ease;}
/* Same seat-aware pairing the turnstrands use. YOUR dock is whichever one renders at the bottom:
   your tile leans LEFT and nudges up toward the board. The opponent's dock is at the top, so
   theirs mirrors — leans RIGHT and nudges down. Both players see the same arrangement. */
.app.seat0 .dock-bot .seatart,
.app.seat1 .dock-top .seatart{ top:38%; transform:translateY(-50%) rotate(-5deg); }
.app.seat0 .dock-top .seatart,
.app.seat1 .dock-bot .seatart{ top:64%; transform:translateY(-50%) rotate(5deg); }
/* Subtle darkening on hover — it's a button, but a quiet one. */
/* Hover dims the WHOLE tile, border included — filter covers the border box, so no separate
   border-color change is needed. transform is left alone: setting it here would drop the
   tilt and re-centring and make the tile snap upright. */
.seatart:hover{filter:brightness(.72);}
.seatart[hidden]{display:none;}
body.overseer .seatart{cursor:default;}
body.overseer .seatart:hover{filter:none;}

/* Chosen card art sits behind each name, anchored to the outer edge, with a scrim toward the
   seam so the names stay readable. --vsart is set per side in showVsSplash. */
#vsSplash .vsArt{position:absolute; top:50%; left:25%; transform:translate(-50%,-50%);
  height:88%; aspect-ratio:5/7; max-width:46%;
  /* Image sits at 80% inside the SAME mask, so the feather nibbles the border instead of
     swallowing the frame. */
  background:var(--vsart) center/80% auto no-repeat;
  opacity:0; transition:opacity .5s ease;
  /* Card-shaped feather with a NOISY, irregular edge: an SVG mask — a rounded 5:7 rect run
     through turbulence displacement + blur — so the art dissolves into the backdrop with no
     hard outline. NOTE: every '#' in the data URI must be %23-encoded or the URI truncates
     at the first one and the whole mask (and the art with it) silently disappears. */
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1000'%20height='1400'%3E%3Cfilter%20id='g'%20x='-25%25'%20y='-25%25'%20width='150%25'%20height='150%25'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.0045%200.0035'%20numOctaves='10'%20seed='11'%20result='n'/%3E%3CfeDisplacementMap%20in='SourceGraphic'%20in2='n'%20scale='105'/%3E%3CfeGaussianBlur%20stdDeviation='22'/%3E%3C/filter%3E%3Crect%20x='170'%20y='205'%20width='660'%20height='990'%20rx='140'%20fill='white'%20filter='url(%23g)'/%3E%3C/svg%3E"); mask-image:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1000'%20height='1400'%3E%3Cfilter%20id='g'%20x='-25%25'%20y='-25%25'%20width='150%25'%20height='150%25'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.0045%200.0035'%20numOctaves='10'%20seed='11'%20result='n'/%3E%3CfeDisplacementMap%20in='SourceGraphic'%20in2='n'%20scale='105'/%3E%3CfeGaussianBlur%20stdDeviation='22'/%3E%3C/filter%3E%3Crect%20x='170'%20y='205'%20width='660'%20height='990'%20rx='140'%20fill='white'%20filter='url(%23g)'/%3E%3C/svg%3E");
  -webkit-mask-size:100% 100%; mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;}
#vsSplash .vsArt.on{opacity:.5;}
/* Entry: slide in FAST from the outer edge, then exponentially decelerate into a barely-
   moving drift toward the center seam — one curve does both (easeOutExpo-style bezier front-
   loads ~70% of the travel into the first second of the 12s run). Opacity fades in separately
   via the .5s transition, so the fade isn't stretched over the whole drift. */
#vsSplash .vsArt.l.on{animation:vsDriftL 12s cubic-bezier(.05,.95,.1,1) both;}
#vsSplash .vsArt.r.on{animation:vsDriftR 12s cubic-bezier(.05,.95,.1,1) both;}
@keyframes vsDriftL{from{transform:translate(-66%,-50%);} to{transform:translate(-47%,-50%);}}
@keyframes vsDriftR{from{transform:translate(-34%,-50%);} to{transform:translate(-53%,-50%);}}
#vsSplash.out .vsArt.on{opacity:0;}   /* exit: fade with the rest of the splash */
/* Centered in each HALF (25% / 75%), so the art sits directly behind its name as a banner. */
#vsSplash .vsArt.l{left:25%;}
#vsSplash .vsArt.r{left:75%;}
@media (max-width:720px){
  #vsSplash .vsArt{height:58%;}
}
#vsSplash .vsHalf.l{left:0; justify-content:flex-end; text-align:right; padding-right:13vw;
  background:linear-gradient(100deg, rgba(232,198,107,.10) 0%, rgba(0,0,0,0) 72%);
  animation:vsSlideL .62s cubic-bezier(.16,.9,.24,1) both;}
#vsSplash .vsHalf.r{right:0; justify-content:flex-start; text-align:left; padding-left:13vw;
  background:linear-gradient(260deg, rgba(224,181,82,.12) 0%, rgba(0,0,0,0) 72%);
  animation:vsSlideR .62s cubic-bezier(.16,.9,.24,1) both;}
#vsSplash .vsSeam{position:absolute; top:-12%; bottom:-12%; left:50%; width:2px; margin-left:-1px;
  background:linear-gradient(180deg, transparent, rgba(232,198,107,.55) 22%, rgba(232,198,107,.55) 78%, transparent);
  transform:rotate(8deg); animation:vsSeam .5s ease .1s both;}
#vsSplash .vsWho{display:inline-block; font-family:var(--mono, monospace); font-size:clamp(10px,1.1vw,14px);
  letter-spacing:.34em; text-indent:.34em; text-transform:uppercase; margin-bottom:10px;
  /* Gold banner ribbon behind YOU / OPPONENT: solid through the middle, feathering to nothing
     at both ends. Dark text so it reads as stamped into the metal. */
  padding:6px 38px; color:#1a1206; font-weight:700;
  background:linear-gradient(90deg, rgba(202,161,72,0) 0%, rgba(202,161,72,.92) 20%,
    rgba(232,198,107,.98) 50%, rgba(202,161,72,.92) 80%, rgba(202,161,72,0) 100%);
  text-shadow:0 1px 0 rgba(255,235,180,.35);}
/* 'Cinzel' explicitly, NOT var(--display) ('BluuNext'): Cinzel has no true lowercase, so it
   renders typed lowercase as small caps — which is how the username input shows it. Using the
   display face here made the same name come out in real lowercase. No text-transform: the name
   shows exactly as typed. */
#vsSplash .vsName{display:block; font-family:'Cinzel',serif; font-weight:900;
  font-size:clamp(45px,8.4vw,129px); line-height:1.02; letter-spacing:.02em; color:#f3e7cf;
  text-shadow:0 4px 26px rgba(0,0,0,.85); white-space:nowrap; max-width:100%;}
#vsSplash .vsHalf.r .vsName{color:#e8c66b;}
#vsSplash .vsBolt{position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  font-family:var(--display,'Cinzel',serif); font-weight:900; font-size:clamp(56px,11vw,168px);
  letter-spacing:.02em; color:#fff;
  text-shadow:0 0 18px rgba(255,150,40,.95), 0 0 54px rgba(255,110,20,.75), 0 0 110px rgba(255,90,10,.5);
  animation:vsBolt .5s cubic-bezier(.2,1.7,.35,1) .34s both;}
@keyframes vsSlideL{from{opacity:0; transform:translateX(-9vw);} to{opacity:1; transform:none;}}
@keyframes vsSlideR{from{opacity:0; transform:translateX(9vw);} to{opacity:1; transform:none;}}
@keyframes vsSeam{from{opacity:0; transform:rotate(8deg) scaleY(.3);} to{opacity:1; transform:rotate(8deg) scaleY(1);}}
@keyframes vsBolt{0%{opacity:0; transform:translate(-50%,-50%) scale(.35);}
  70%{opacity:1; transform:translate(-50%,-50%) scale(1.14);}
  100%{opacity:1; transform:translate(-50%,-50%) scale(1);}}
@keyframes vsBgOut{to{opacity:0;}}
@keyframes vsOutL{from{opacity:1; transform:none;} to{opacity:0; transform:translateX(-9vw);}}
@keyframes vsOutR{from{opacity:1; transform:none;} to{opacity:0; transform:translateX(9vw);}}
@keyframes vsSeamOut{from{opacity:1; transform:rotate(8deg) scaleY(1);}
  to{opacity:0; transform:rotate(8deg) scaleY(.3);}}
@keyframes vsBoltOut{from{opacity:1; transform:translate(-50%,-50%) scale(1);}
  to{opacity:0; transform:translate(-50%,-50%) scale(.35);}}
@media (max-width:720px){
  #vsSplash .vsHalf{padding:0 4vw;}
  #vsSplash .vsName{font-size:clamp(33px,11vw,66px);}
}
@media (prefers-reduced-motion:reduce){
  #vsSplash .vsHalf.l,#vsSplash .vsHalf.r,#vsSplash .vsSeam,#vsSplash .vsBolt{
    animation-duration:.01ms; opacity:1;}
  #vsSplash .vsArt.l.on,#vsSplash .vsArt.r.on{animation:none; transform:translate(-50%,-50%);}
  #vsSplash .vsBolt{transform:translate(-50%,-50%);}
}

/* Splash container: hidden until a match lands (showVsSplash adds .on, .out plays the exit). */
#vsSplash{position:fixed; inset:0; z-index:6000; display:none; overflow:hidden;
  pointer-events:none; user-select:none;}
#vsSplash.on{display:block;}
#vsSplash .vsBg{position:absolute; inset:0;
  background:radial-gradient(120% 90% at 50% 45%, #1a1410 0%, #0b0906 72%);}
#vsSplash .vsHalf{position:absolute; top:0; bottom:0; width:50%;
  display:flex; align-items:center;}
/* Exit: .out re-runs each piece with its *Out keyframes, then JS removes .on/.out. */
#vsSplash.out .vsBg{animation:vsBgOut .5s ease .15s both;}
#vsSplash.out .vsHalf.l{animation:vsOutL .45s ease both;}
#vsSplash.out .vsHalf.r{animation:vsOutR .45s ease both;}
#vsSplash.out .vsSeam{animation:vsSeamOut .4s ease both;}
#vsSplash.out .vsBolt{animation:vsBoltOut .4s ease both;}
#lobby .code{font-size:26px;font-weight:800;letter-spacing:.16em;text-align:center;color:#e0b552;word-break:break-all;}
/* Above #modal (5000): when the opponent leaves at the game-over screen, this has to land ON TOP */
#discOverlay{position:fixed; inset:0; z-index:5100; display:none; align-items:center; justify-content:center;
  background:rgba(6,4,3,.82); backdrop-filter:blur(3px);}
#discOverlay.show{display:flex;}
#newGameOverlay{position:fixed; inset:0; z-index:5050; display:none; align-items:center; justify-content:center;
  background:rgba(6,4,3,.82); backdrop-filter:blur(3px);}
#newGameOverlay.show{display:flex;}
#newGameOverlay .dcard{background:#141009; border:1px solid #4a3a22; border-radius:12px; padding:22px 26px;
  display:flex; flex-direction:column; gap:12px; align-items:center; min-width:300px;
  box-shadow:0 18px 60px rgba(0,0,0,.7);}
#newGameOverlay .dtitle{font-family:'Cinzel',serif; font-weight:700; font-size:17px; letter-spacing:.05em; color:#e0b552;}
#newGameOverlay .dsub{font-size:12px; color:#9d9079; text-align:center; max-width:260px;}
#newGameOverlay .drow{display:flex; gap:8px; margin-top:4px;}
#newGameOverlay .drow button{flex:1 1 0; padding:9px 18px; border-radius:8px; cursor:pointer;
  font-family:'Cinzel',serif; font-weight:700; font-size:12px; border:0;}
#newGameOverlay .drow .go{background:linear-gradient(180deg,#caa148,#8a6d28); color:#1a1206;}
#newGameOverlay .drow .ghost{background:rgba(40,32,20,.9); color:#e8dcc0; border:1px solid #5a4526;}
button.alt.danger{color:#e0798c; border-color:#5a2a34;}
button.alt.danger.armed{background:#5a1a26; color:#ffd7de; border-color:#8a2a3c;}
button.alt.danger:hover{background:#2a1218;}
#discOverlay .dcard{background:#141009; border:1px solid #4a3a22; border-radius:12px; padding:22px 26px;
  display:flex; flex-direction:column; gap:12px; align-items:center; min-width:280px;
  box-shadow:0 18px 60px rgba(0,0,0,.7);}
#discOverlay .dtitle{font-family:'Cinzel',serif; font-weight:700; font-size:17px; letter-spacing:.05em; color:#e0b552; text-align:center;}
#discOverlay .dsub{font-size:12px; color:#9d9079; text-align:center; min-height:16px;}
#discOverlay.gone .dtitle{color:#e0798c;}
#discOverlay .dspin{display:flex; gap:7px;}
#discOverlay .dspin span{width:9px; height:9px; border-radius:50%; background:#caa148; opacity:.3; animation:qpulse 1.1s ease-in-out infinite;}
#discOverlay .dspin span:nth-child(2){animation-delay:.16s;}
#discOverlay .dspin span:nth-child(3){animation-delay:.32s;}
#discOverlay.gone .dspin{display:none;}
#flash{position:fixed;top:16px;left:50%;transform:translateX(-50%);background:#3a1620;border:1px solid #7a2a3c;color:#ffd7df;padding:9px 16px;border-radius:9px;z-index:200;opacity:0;transition:opacity .2s;pointer-events:none;font-weight:600;}
#flash.show{opacity:1;}
.app{display:none;}
.app.ready{display:flex;}
.flycard{border-radius:10px;overflow:hidden;}
.lane.drophover{outline:2px solid #caa148;outline-offset:-2px;}
/* Dragging over a lane this card can't legally take (occupied, and the card isn't a Guard). */
.lane.dropbad{outline:2px dashed #7a3b45;outline-offset:-2px;cursor:not-allowed;}
/* Greyed out for the whole drag: this lane holds a card the dragged one can't legally take (same */
.lane.laneblocked .card{filter:grayscale(1) brightness(.45); transition:filter .12s ease;}
.lane.laneblocked{cursor:not-allowed;}
/* Legal target for the card being dragged — open lanes AND different-colour lanes you */
.lane.lanevalid{outline:2px solid rgba(202,161,72,.55); outline-offset:-2px; border-radius:8px;
  background:rgba(202,161,72,.06);}
/* Ambush window: pulse every lane the defender can actually drop into (empty */
.lane.ambushlane{outline:2px solid rgba(255,223,94,.7); outline-offset:-2px; border-radius:8px;
  background:rgba(255,215,80,.07); animation:ambushlanepulse 1.15s ease-in-out infinite;}
@keyframes ambushlanepulse{
  0%,100%{ outline-color:rgba(255,223,94,.45); background:rgba(255,215,80,.05); }
  50%    { outline-color:rgba(255,233,133,.95); background:rgba(255,215,80,.13); } }
/* Ambush icon centered on each viable lane, above the yellow glow. */
.lane .ambushlanemark{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:40%; height:40%; z-index:4; pointer-events:none; display:flex; align-items:center;
  justify-content:center; color:#ffdf5e; font-size:34px;
  filter:drop-shadow(0 0 6px rgba(255,215,80,.9)); animation:ambushmarkpulse 1.15s ease-in-out infinite; }
.lane .ambushlanemark img{ width:100%; height:100%; object-fit:contain; }
@keyframes ambushmarkpulse{ 0%,100%{ opacity:.7; } 50%{ opacity:1; } }

/* Guard: stack-or-replace picker Two large 3:4 buttons */
/* #modal .opts sets flex-direction:column and `button{width:100%}` further down the sheet */
#modal .opts.guardmode{display:flex; flex-direction:row; gap:14px; justify-content:center; align-items:center; flex-wrap:wrap; overflow:visible;}
#modal .opts.guardmode .gmbtn{
  width:108px; height:144px;            /* 3:4, same ratio as a card */
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px;
  padding:12px; border-radius:10px; cursor:pointer;
  background:linear-gradient(180deg,#1b2836,#131c26);
  border:1px solid var(--line); color:#cfe0ee;
  font-family:var(--mono); font-size:13px; letter-spacing:.04em;
  transition:transform .12s ease, border-color .12s ease, box-shadow .12s ease;}
#modal .opts.guardmode .gmbtn img{width:52px; height:52px; object-fit:contain; opacity:.92;}
#modal .opts.guardmode .gmbtn:hover{transform:translateY(-2px); border-color:#caa148;
  box-shadow:0 0 0 1px #caa148, 0 6px 18px rgba(0,0,0,.5);}
#modal .opts.guardmode .gmcancel{flex:0 0 100%; width:auto; height:auto; padding:6px; text-align:center;}
.lifebox.lifehit,.life.lifehit{animation:lifehitpulse .5s ease;}
@keyframes lifehitpulse{0%{filter:none}30%{filter:drop-shadow(0 0 10px #ff4d6d) brightness(1.6)}100%{filter:none}}

/* ---- ACTION BUTTON VARIANTS (authoritative) ---------------------------------------------
   A later set of rules re-declared .alt/.go/.pass/.disc with solid gradients, which is why
   Declare Battle looked heavier and dimmer than Top Deck: they weren't the same treatment at
   all. Restated here at equal weight — same fill strength, same border alpha, colour carrying
   the meaning. Available reads LIT; hover darkens; disabled drops away. */
button.alt{background:rgba(255,255,255,.04); border:1px solid rgba(255,255,255,.18); color:var(--ink);}
button.alt:hover:not(:disabled){background:rgba(255,255,255,.10); border-color:rgba(202,161,72,.8);
  color:#fff; filter:none;}
button.go{background:rgba(196,69,43,.18); border:1px solid rgba(196,69,43,.75); color:#ffd9cd;}
button.go:hover:not(:disabled){background:rgba(196,69,43,.32); border-color:rgba(240,110,80,1);
  color:#fff; filter:brightness(.9);}
button.pass{background:rgba(63,96,104,.24); border:1px solid rgba(90,150,160,.7); color:#e6f5f7;}
button.pass:hover:not(:disabled){background:rgba(63,96,104,.40); border-color:rgba(140,215,228,1);
  color:#fff; filter:brightness(.9);}
button.disc{background:rgba(106,78,168,.22); border:1px solid rgba(122,94,190,.75); color:#efe9ff;}
button.disc:hover:not(:disabled){background:rgba(106,78,168,.38); border-color:rgba(168,140,240,1);
  color:#fff; filter:brightness(.9);}
button:disabled{opacity:.2; background:rgba(255,255,255,.015) !important;
  border-color:rgba(255,255,255,.10) !important; color:var(--muted) !important;
  -webkit-backdrop-filter:none; backdrop-filter:none; cursor:default;}

/* ---- BUTTONS EVERYWHERE (authoritative) -------------------------------------------------
   The base `button {}` rule already carries the outlined-and-blurred language, but several
   dialogs were written with their own filled styles that outrank it. Rather than hunt each one
   down and edit it in place, they're normalised here, last in the file. Every dialog keeps its
   MEANING through colour — destructive stays red, confirm stays gold — just at the same weight
   as everything else. */
#modal button, #infoModal button, #htpModal button, #artModal button, #discview button,
#deckstats button, #newGameOverlay button, #pnModal button, #cpuModal button{
  font-family:'Cinzel',serif; font-weight:600; letter-spacing:.1em; text-transform:uppercase;
  border-radius:2px; cursor:pointer; color:#f0e2c4;
  background:rgba(202,161,72,.08); border:1px solid rgba(202,161,72,.5);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  transition:background .15s ease, border-color .15s ease, color .15s ease, filter .15s ease;}
#modal button:hover:not(:disabled), #infoModal button:hover, #htpModal button:hover,
#artModal button:hover:not(:disabled), #discview button:hover, #deckstats button:hover,
#newGameOverlay button:hover, #pnModal button:hover{
  background:rgba(202,161,72,.28); border-color:rgba(232,198,107,1); color:#fff8e8;
  filter:brightness(.9);}

/* Quiet/secondary actions: outlined but colourless until touched. */
#newGameOverlay .drow .ghost, #artModal .amnone, #modal .opts button.ghost{
  background:rgba(255,255,255,.03); border-color:rgba(255,255,255,.16); color:var(--muted);}
#newGameOverlay .drow .ghost:hover, #artModal .amnone:hover, #modal .opts button.ghost:hover{
  background:rgba(255,255,255,.09); border-color:rgba(202,161,72,.8); color:var(--ink); filter:none;}
/* Primary confirm keeps gold, just not as a slab. */
#newGameOverlay .drow .go{background:rgba(202,161,72,.20); border-color:rgba(202,161,72,.8);
  color:#f6e8c8;}
#newGameOverlay .drow .go:hover{background:rgba(202,161,72,.34); border-color:rgba(232,198,107,1);
  color:#fff8e8; filter:brightness(.92);}
/* Destructive keeps red. */
button.alt.danger{background:rgba(224,80,110,.10); border-color:rgba(224,80,110,.55); color:#ffc9d3;}
button.alt.danger:hover{background:rgba(224,80,110,.24); border-color:rgba(255,130,155,.9); color:#fff;}
button.alt.danger.armed{background:rgba(224,80,110,.34); border-color:rgba(255,130,155,1); color:#fff;}
/* The small square closers on every modal. */
#artModal .amclose, .pnX, .amclose{width:28px; height:28px; padding:0; line-height:1; font-size:16px;
  letter-spacing:0; border-radius:2px; background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.14); color:var(--muted); cursor:pointer;}
#artModal .amclose:hover, .pnX:hover, .amclose:hover{background:rgba(255,255,255,.09);
  border-color:rgba(202,161,72,.7); color:var(--ink);}
/* End-game buttons sit in #modal .opts; keep them full-width but in the shared language. */
#modal .opts button{width:100%; text-align:center; padding:11px 14px; font-size:12.5px;}
#modal .opts.endgame button{width:auto; flex:1 1 0; text-align:center;}

#lobby #lobbyMain{width:360px; min-width:360px; padding:18px 22px 20px; gap:0;
  justify-content:flex-start;}


/* ---- SIDE PANEL + SETTINGS CONTROLS (authoritative) -------------------------------------
   The in-game panel's own controls were still on the old filled style. Same treatment as
   everything else, restated last so the legacy #ref rules can't win. */
#ref .segbtn, #ref .powbtn, #ref .tdbtn, #ref .lifebtn, #ref .kwallbtn, #ref .poolopt{
  font-family:'Cinzel',serif; font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  border-radius:2px; cursor:pointer; color:var(--muted);
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.16);
  transition:background .14s ease, border-color .14s ease, color .14s ease;}
#ref .segbtn:hover, #ref .powbtn:hover, #ref .tdbtn:hover, #ref .lifebtn:hover,
#ref .kwallbtn:hover, #ref .poolopt:hover{
  background:rgba(255,255,255,.08); border-color:rgba(202,161,72,.75); color:var(--ink);}
/* Selected: gold, but outlined rather than a filled slab. */
#ref .segbtn.on, #ref .powbtn.on, #ref .tdbtn.on, #ref .poolopt.on{
  background:rgba(202,161,72,.20); border-color:rgba(202,161,72,.85); color:#f6e8c8;}
#ref .segbtn.on:hover, #ref .powbtn.on:hover, #ref .tdbtn.on:hover, #ref .poolopt.on:hover{
  background:rgba(202,161,72,.32); border-color:rgba(232,198,107,1); color:#fff8e8;}
#ref .poolopt.top.on{background:rgba(226,232,244,.18); border-color:#aab2c2; color:#e6ecf7;}
/* Locked panel: dim, and visibly not clickable. */
#ref .kw-toggle.static, #ref[data-locked] .segbtn, #ref[data-locked] .powbtn{cursor:default;}

/* The side dock's own buttons (Rules, the info 'i', Share Room, board picker). */
.side button, .sidecontrols button, .shareRow button, .bpick-btn{
  font-family:'Cinzel',serif; font-weight:600; letter-spacing:.1em; text-transform:uppercase;
  border-radius:2px; color:#f0e2c4; background:rgba(202,161,72,.08);
  border:1px solid rgba(202,161,72,.5); cursor:pointer;
  transition:background .15s ease, border-color .15s ease, color .15s ease;}
.side button:hover:not(:disabled), .sidecontrols button:hover, .shareRow button:hover,
.bpick-btn:hover{background:rgba(202,161,72,.24); border-color:rgba(232,198,107,1); color:#fff8e8;}

/* ---- LOBBY FINAL PASS -------------------------------------------------------------------
   The gold hairline was drawn by .lcard::before on BOTH panels; on the right-hand one it read
   as a stray line floating above 'Matchmaking'. Kept on the profile card only. */
#lobby #lobbyMain::before{display:none;}
#lobby #lobbyMain{justify-content:center;}   /* sections centred in the panel, not top-aligned */
#lobby #lobbyMain .lsec:first-of-type{padding-top:0;}
#lobby #lobbyMain .lsec:last-of-type{padding-bottom:0;}

/* Share Room # is a .roomchip, not a <button>, which is why the button rules never reached it. */
.roomchip, .roomchip.shareBig{font-family:'Cinzel',serif; font-weight:600; letter-spacing:.1em;
  text-transform:uppercase; border-radius:2px; cursor:pointer; color:#f0e2c4;
  background:rgba(202,161,72,.08); border:1px solid rgba(202,161,72,.5);
  transition:background .15s ease, border-color .15s ease, color .15s ease;}
.roomchip:hover, .roomchip.shareBig:hover{background:rgba(202,161,72,.24);
  border-color:rgba(232,198,107,1); color:#fff8e8;}

/* ---- LOBBY SIZING (final) ---------------------------------------------------------------
   The profile card was inheriting .lcard's 340px minimum and stretching well past its content,
   which pushed the pair over the row's width and wrapped the right-hand panel underneath. Both
   panels get an explicit width instead: profile = art(144) + gap(12) + swatches(98) + padding(44).
   The row is nowrap so they can never stack. */
#lobby .lrow{flex-wrap:nowrap; align-items:stretch; gap:16px;}
#lobby #lobbyMain{width:360px; min-width:360px; max-width:360px; flex:none;}


/* An EMPTY status div was still contributing its 18px bottom padding, which is the whole reason
   the right panel had more space below its last button than above its first. */
#lobby .status:empty{display:none; padding:0;}
#lobby #lobbyMain{padding:20px 22px;}

/* ---- PROFILE CARD ------------------------------------------------------------------------
   ONE definition of this block. It had accumulated a dozen competing rules from successive
   passes — four-column grids fighting two-column ones, three different art sizes — which is why
   the swatches kept landing on top of the picture. All of those are gone; this is the only
   place the profile is laid out.

   Structure:  .prow  =  [ .artpick (art over its label) ] [ .namehues (2 x 4 swatches) ]
               #userName underneath, spanning the card.

   Heights are made to agree on purpose: the art column is 202 + 6 + 14 = 222, and the swatch
   column is 4 x 51 + 3 x 6 = 222, so the two sides finish level. */
#lobby #lobbyProfile{display:flex; flex-direction:column; align-items:center; gap:14px;
  width:308px; min-width:308px; max-width:308px; flex:none; padding:20px 22px 22px;}
#lobby #lobbyProfile .ptitle{align-self:stretch; text-align:center;}

#lobby #lobbyProfile .prow{display:flex; flex-direction:row; align-items:flex-start;
  justify-content:center; gap:12px; width:100%;}

/* Art: a plain column, no button chrome. */
#lobby #lobbyProfile .artpick{display:flex; flex-direction:column; align-items:center; gap:6px;
  flex:none; width:144px; padding:0; margin:0; background:none; border:none; cursor:pointer;}
#lobby #lobbyProfile .artpick .artpickThumb{display:block; width:144px; height:202px;
  border-radius:2px; border:1px solid rgba(120,96,58,.55); background:#100e09 center/cover no-repeat;
  transition:border-color .14s ease;}
#lobby #lobbyProfile .artpick:hover .artpickThumb{border-color:var(--gold);}
#lobby #lobbyProfile .artpick.has .artpickThumb{border-color:rgba(202,161,72,.8);}
#lobby #lobbyProfile .artpick .artpickLbl{display:block; width:144px; height:14px;
  line-height:14px; margin:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  text-align:center; font-family:var(--mono); font-size:9.5px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--muted);}

/* Swatches: fixed cells so they're true squares and the column can't reflow. */
#lobby #lobbyProfile .namehues{display:grid; grid-template-columns:repeat(2, 51px);
  grid-auto-rows:51px; gap:6px; width:108px; height:222px; flex:none;
  padding:0; margin:0; align-content:start; justify-content:start;}
#lobby #lobbyProfile .namehues button{width:51px; height:51px; min-width:0; padding:0; margin:0;
  border-radius:2px; border:1px solid rgba(0,0,0,.55); background:var(--hue);
  cursor:pointer; box-shadow:none; transition:box-shadow .12s ease, filter .12s ease;}
#lobby #lobbyProfile .namehues button:hover{filter:brightness(1.18);}
#lobby #lobbyProfile .namehues button.sel{border-color:transparent;
  box-shadow:inset 0 0 0 2px rgba(0,0,0,.65), 0 0 0 1px #f3e7cf;}

#lobby #lobbyProfile #userName{width:100%; box-sizing:border-box; text-align:center;
  padding:10px 12px; font-size:17px; border-radius:2px;}

/* ---- CREDITS / INFO MODAL ----------------------------------------------------------------
   Missed by the earlier pass because its card and close button carry their own rules. */
#infoModal .infoCard{background:linear-gradient(180deg, rgba(20,17,13,.97), rgba(13,11,9,.98));
  border:1px solid rgba(120,96,58,.5); border-radius:3px;
  box-shadow:0 30px 90px rgba(0,0,0,.75), inset 0 1px 0 rgba(255,240,214,.05);}
#infoModal .infoHead h3{font-family:'Cinzel',serif; font-weight:700; font-size:15px;
  letter-spacing:.26em; text-transform:uppercase; color:var(--gold);}
#infoModal button, #infoModal .infoClose{font-family:'Cinzel',serif; font-weight:600;
  letter-spacing:.1em; text-transform:uppercase; border-radius:2px; cursor:pointer;
  color:#f0e2c4; background:rgba(202,161,72,.08); border:1px solid rgba(202,161,72,.5);}
#infoModal button:hover, #infoModal .infoClose:hover{background:rgba(202,161,72,.24);
  border-color:rgba(232,198,107,1); color:#fff8e8;}

/* Sharing a code has no meaning in a solo game — nobody can join it. */
body.solo .shareRow{display:none !important;}

/* ---- UNAVAILABLE CONTROLS ----------------------------------------------------------------
   Present but inert: the Top 100 options stay on screen when the curated list is incomplete, so
   a misconfigured file is visibly different from a feature that was never built. Hover gives the
   reason. Cards are never badged in this state — the server doesn't flag them at all. */
#ref .setrow.rowoff{opacity:.38; cursor:not-allowed;}
#ref .setrow.rowoff .poolopt{pointer-events:none;}

/* ---- MATCHMAKING ROW ---------------------------------------------------------------------
   Button and preference share a line: the checkbox is a qualifier on the action, not a second
   decision, so it sits beside it rather than under it. The button gives up the width the label
   needs instead of both stretching. */
#lobby .row.mmrow{display:flex; align-items:stretch; gap:8px; width:100%;}
#lobby .row.mmrow > #btnQuick{flex:1 1 auto; min-width:0; padding:13px 16px; font-size:14px;}

/* The checkbox reads as one of the outlined controls, not a web form element. */
#lobby .prefbox{display:flex; align-items:center; gap:9px; flex:0 0 auto; white-space:nowrap;
  padding:0 15px; cursor:pointer; user-select:none; position:relative; border-radius:2px;
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.16);
  transition:background .15s ease, border-color .15s ease;}
#lobby .prefbox:hover{background:rgba(255,255,255,.07); border-color:rgba(202,161,72,.7);}
#lobby .prefbox input{position:absolute; opacity:0; width:0; height:0;}
#lobby .prefbox .pbmark{width:15px; height:15px; flex:none; border-radius:2px; position:relative;
  border:1px solid rgba(255,255,255,.35); background:rgba(0,0,0,.4); transition:all .14s ease;}
#lobby .prefbox .pbmark::after{content:''; position:absolute; left:4px; top:.5px; width:4px; height:9px;
  border:solid #12100a; border-width:0 2px 2px 0; transform:rotate(43deg) scale(.4); opacity:0;
  transition:opacity .12s ease, transform .12s ease;}
/* Two lines: 'Prefer' small and quiet above the thing being preferred, so the checkbox reads as
   a wish rather than a filter. */
#lobby .prefbox .pbtext{display:flex; flex-direction:column; align-items:flex-start; gap:1px;
  font-family:'Cinzel',serif; font-weight:600; font-size:11px; line-height:1.1;
  letter-spacing:.12em; text-transform:uppercase; color:var(--muted); transition:color .15s ease;}
#lobby .prefbox .pbtext small{font-size:inherit; letter-spacing:inherit; font-weight:inherit;}
#lobby .prefbox input:checked ~ .pbmark{background:var(--gold); border-color:var(--gold);}
#lobby .prefbox input:checked ~ .pbmark::after{opacity:1; transform:rotate(43deg) scale(1);}
#lobby .prefbox:has(input:checked){background:rgba(202,161,72,.14); border-color:rgba(202,161,72,.7);}
#lobby .prefbox:has(input:checked) .pbtext{color:#f0e2c4;}
/* Unavailable: visible, inert, explained on hover. */
#lobby .prefbox.off{opacity:.35; cursor:not-allowed;}
#lobby .prefbox.off:hover{background:rgba(255,255,255,.03); border-color:rgba(255,255,255,.16);}

/* ---- PATCH NOTES ------------------------------------------------------------------------
   Body copy in Charis SIL: the theme face is a bold display type, which is fine for two words on
   a card and punishing for a paragraph. Titles stay in Cinzel so the panel still belongs here. */
.pnCard{background:linear-gradient(180deg, rgba(20,17,13,.97), rgba(13,11,9,.98));
  border:1px solid rgba(120,96,58,.5); border-radius:3px;
  box-shadow:0 30px 90px rgba(0,0,0,.75), inset 0 1px 0 rgba(255,240,214,.05);
  padding:0;}
.pnCard::before{content:''; display:block; height:1px;
  background:linear-gradient(90deg, transparent, rgba(202,161,72,.55) 18%, rgba(202,161,72,.55) 82%, transparent);}
.pnCard h3{font-family:'Cinzel',serif; font-weight:700; font-size:13px; letter-spacing:.26em;
  text-transform:uppercase; color:var(--gold); margin:0; padding:16px 22px 13px;
  border-bottom:1px solid rgba(120,96,58,.35);}
#pnEntries{padding:4px 22px 18px;}
.pnEntry{border-top:1px solid rgba(120,96,58,.22); padding:16px 0;}
.pnEntry:first-child{border-top:none;}
.pnEntry h4{font-family:'Cinzel',serif; font-weight:600; font-size:14px; letter-spacing:.1em;
  text-transform:uppercase; color:#f0e2c4; margin:0 0 3px;}
.pnMeta{font-family:var(--mono); font-size:9.5px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--muted); margin-bottom:10px;}
.pnBody{font-family:'Charis SIL', Georgia, serif; font-weight:400; font-size:15px;
  line-height:1.62; letter-spacing:0; color:#ddd3c2; white-space:pre-wrap;}
.pnX{position:absolute; top:14px; right:16px;}

/* ---- LOBBY INFO MODAL --------------------------------------------------------------------
   Replaces the title= tooltip on the Top 100 preference. A hover tip is the wrong place for an
   explanation you actually need to read. */
#lobbyInfo{display:none; position:fixed; inset:0; z-index:9700; background:rgba(6,8,11,.78);
  backdrop-filter:blur(4px); align-items:center; justify-content:center; padding:24px;}
#lobbyInfo.show{display:flex;}
#lobbyInfo .liCard{width:min(420px,94vw);
  background:linear-gradient(180deg, rgba(20,17,13,.97), rgba(13,11,9,.98));
  border:1px solid rgba(120,96,58,.5); border-radius:3px;
  box-shadow:0 30px 90px rgba(0,0,0,.75);}
#lobbyInfo .liCard::before{content:''; display:block; height:1px;
  background:linear-gradient(90deg, transparent, rgba(202,161,72,.55) 18%, rgba(202,161,72,.55) 82%, transparent);}
#lobbyInfo h4{font-family:'Cinzel',serif; font-weight:700; font-size:12px; letter-spacing:.24em;
  text-transform:uppercase; color:var(--gold); margin:0; padding:16px 20px 12px;
  border-bottom:1px solid rgba(120,96,58,.35);}
#lobbyInfo p{font-family:'Charis SIL', Georgia, serif; font-size:15px; line-height:1.6;
  color:#ddd3c2; margin:0; padding:16px 20px 18px;}
#lobbyInfo .liFoot{padding:0 20px 16px; display:flex; justify-content:flex-end;}

/* The small 'i' inside the preference control. */
.pbInfo{width:17px; height:17px; flex:none; padding:0; margin-left:2px; border-radius:2px;
  font-family:'Cinzel',serif; font-weight:700; font-size:10px; line-height:1; letter-spacing:0;
  background:rgba(255,255,255,.05); border:1px solid rgba(255,255,255,.22); color:var(--muted);
  cursor:pointer; transition:background .14s, border-color .14s, color .14s;}
.pbInfo:hover{background:rgba(202,161,72,.18); border-color:rgba(202,161,72,.8); color:#f0e2c4;}

/* ---- ABILITY CONTROL BOX -----------------------------------------------------------------
   The instructions used to trail after the list as a sentence. Boxed with the button that acts
   on them instead, directly above the abilities they describe. */
#ref .kwbox{border:1px solid rgba(120,96,58,.35); border-radius:2px; padding:9px 11px;
  margin:10px 0 9px; background:rgba(255,240,214,.02);}
#ref .kwboxhead{display:flex; align-items:center; gap:10px;
  font-family:'Cinzel',serif; font-weight:600; font-size:10.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--muted);}
#ref .kwboxhead > span:first-child{color:#e9d9b3;}
#ref .kwcount{margin-right:auto; font-family:var(--mono); font-size:10px; color:var(--gold);
  letter-spacing:.1em;}
#ref .kwboxnote{margin-top:7px; font-family:var(--font); font-weight:700;
  font-synthesis-weight:none; font-size:12px; line-height:1.45; color:var(--muted);}
#ref .kwallbtn{padding:4px 11px; font-family:'Cinzel',serif; font-weight:600; font-size:9px;
  letter-spacing:.14em; text-transform:uppercase; border-radius:2px; cursor:pointer;
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.16); color:var(--muted);}
#ref .kwallbtn:hover{background:rgba(255,255,255,.08); border-color:rgba(202,161,72,.75); color:var(--ink);}
#ref .handbtn{cursor:pointer; border-radius:2px; padding:3px 9px; font-size:13px; line-height:1;
  font-family:var(--mono); background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.16); color:var(--muted);}
#ref .handbtn:hover{background:rgba(255,255,255,.08); border-color:rgba(202,161,72,.75); color:var(--ink);}

/* ---- DECK KEY ROW ------------------------------------------------------------------------ */
.foot.footkey{display:flex; align-items:center; gap:8px;}
.foot.footkey #deckKey{flex:1 1 auto; min-width:0; text-align:center;
  font-family:var(--mono); font-size:11.5px; letter-spacing:.14em; text-transform:uppercase;
  padding:5px 8px; border-radius:2px; background:rgba(0,0,0,.35);
  border:1px solid rgba(255,255,255,.16); color:#e9d9b3;}
.foot.footkey #deckKey:focus{outline:none; border-color:rgba(202,161,72,.85); background:rgba(0,0,0,.5);}
.foot.footkey #deckKey::placeholder{color:var(--muted); letter-spacing:.1em; text-transform:none;}
.foot.footkey .dice,
.foot.footkey .keycopy{flex:0 0 auto; padding:4px 9px; font-size:12px; letter-spacing:0;
  min-width:30px; text-align:center;}
/* Briefly shows a tick on success, so the click has an acknowledgement. */
.foot.footkey .keycopy{font-family:var(--mono);}

/* ---- AUTO-PASS BESIDE THE PASS BUTTON ---------------------------------------------------- */
/* The toggle belongs with the button it automates. Stacked above it, quiet, so it reads as a
   qualifier rather than a second action. */
/* ABSOLUTE, not fixed: the pass button belongs to the board area, and fixed positions it
   against the viewport — which puts it underneath the side panel. Same offsets the button used
   on its own, so it lands exactly where it always did. */
.cornerpassWrap{position:absolute; right:14px; bottom:12px; z-index:6;
  display:flex; flex-direction:column; align-items:stretch; gap:5px;}
.cornerpassWrap .cornerpass{position:static; right:auto; bottom:auto;}
.autoPassWrap.minipass{display:flex; align-items:center; justify-content:center; gap:6px;
  cursor:pointer; user-select:none; padding:3px 8px; border-radius:2px;
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.12);}
.autoPassWrap.minipass:hover{border-color:rgba(202,161,72,.6);}
.autoPassWrap.minipass .lbl{font-family:'Cinzel',serif; font-weight:600; font-size:9px;
  letter-spacing:.16em; text-transform:uppercase; color:var(--muted);}
.autoPassWrap.minipass input:checked ~ .lbl{color:#f0e2c4;}

/* ---- FOOT CONTROLS (authoritative) -------------------------------------------------------
   The board row now carries Rules and the credits button, so all three need to sit on one line
   without any of them stretching. Rules had width:100% from when it owned a row of its own. */
.foot.footboard{display:flex; align-items:center; gap:8px;}
.foot.footboard .footlbl{flex:0 0 auto;}
.foot.footboard .bpick{flex:1 1 auto; min-width:70px; max-width:132px;}
/* Rules takes only the room it needs — stretching it squeezed the board picker out of sight. */
.foot.footboard .rulesbtn{flex:0 0 auto; width:auto; justify-self:auto; margin:0 auto 0 0;
  font-family:'Cinzel',serif; font-weight:600; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; border-radius:2px; padding:5px 12px;
  background:rgba(202,161,72,.08); border:1px solid rgba(202,161,72,.5); color:#f0e2c4;
  transition:background .15s ease, border-color .15s ease, color .15s ease;}
.foot.footboard .rulesbtn:hover{background:rgba(202,161,72,.22);
  border-color:rgba(232,198,107,.95); color:#fff8e8; transform:none; box-shadow:none;}
.foot.footboard .footright{flex:0 0 auto; display:flex; align-items:center; gap:6px; margin-left:0;}

/* The credits button: square and outlined like everything else, not a gold disc. */
#infoBtn{width:26px; height:26px; border-radius:2px; flex:0 0 auto; cursor:pointer; padding:0;
  display:flex; align-items:center; justify-content:center;
  font-family:'Cinzel',serif; font-weight:700; font-size:12px; font-style:normal;
  letter-spacing:0; text-transform:none; color:var(--muted);
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.16);
  transition:background .15s ease, border-color .15s ease, color .15s ease;}
#infoBtn:hover{transform:none; box-shadow:none; background:rgba(202,161,72,.18);
  border-color:rgba(202,161,72,.8); color:#f0e2c4;}

/* ---- PASS BUTTON + BOARD PICKER (authoritative) ------------------------------------------
   Both were still on the old filled style. Same outlined language as everything else, with the
   pass button keeping its teal so it stays distinct from the gold actions. */
.cornerpass{padding:7px 22px; font-size:12.5px; font-weight:600; letter-spacing:.14em;
  text-transform:uppercase; font-family:'Cinzel',serif; border-radius:2px;
  background:rgba(70,194,168,.12); color:#c6f4e9;
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  border:1px solid rgba(70,194,168,.55); box-shadow:none;
  opacity:.55; transition:opacity .15s ease, background .15s ease, border-color .15s ease, color .15s ease;}
.cornerpass:hover:not(:disabled){opacity:1; background:rgba(70,194,168,.26);
  border-color:rgba(130,235,210,1); color:#f0fffb; filter:brightness(.92);}
.cornerpass:disabled{opacity:.18; background:rgba(255,255,255,.02);
  border-color:rgba(255,255,255,.10); color:var(--muted); cursor:default;}

/* The board pop-out: a small panel in the same idiom as the modals — square, hairline edge, the
   gold rule along the top. */
.bpick-menu{padding:7px; border-radius:2px;
  background:linear-gradient(180deg, rgba(20,17,13,.98), rgba(13,11,9,.98));
  border:1px solid rgba(120,96,58,.55);
  box-shadow:0 -16px 44px rgba(0,0,0,.7), inset 0 1px 0 rgba(255,240,214,.05);}
.bpick-opt{border-radius:2px; padding:4px; margin:0 0 5px;
  border:1px solid rgba(255,255,255,.10); background:rgba(255,255,255,.02); color:#cfe0ee;}
.bpick-opt:hover{background:rgba(202,161,72,.16); border-color:rgba(202,161,72,.7);}
.bpick-opt.sel{background:rgba(202,161,72,.24); border-color:var(--gold); color:var(--gold);}
.bpick-btn{border-radius:2px; background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.16); box-shadow:none;
  transition:background .14s ease, border-color .14s ease;}
.bpick-btn:hover{background:rgba(255,255,255,.08); border-color:rgba(202,161,72,.7); box-shadow:none;}
.bpick.open .bpick-btn{border-color:var(--gold); box-shadow:none; background:rgba(202,161,72,.14);}
.bpick-thumb{border-radius:2px; border:1px solid rgba(232,198,107,.3);}

/* ---- TABS / LIFE / NAME (authoritative) ---------------------------------------------------
   The last three pieces of the old rounded look. Same square hairline treatment as the panels,
   so the board furniture reads as one set rather than three generations of it. */
.tabs{gap:0; padding:14px 14px 0;}
.tab{flex:1; text-align:center; cursor:pointer; position:relative; border-radius:0;
  padding:11px 8px 9px; background:none; border:none;
  border-bottom:1px solid rgba(120,96,58,.35);
  font-family:'Cinzel',serif; font-weight:600; font-size:11.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--muted);
  transition:color .15s ease, background .15s ease;}
.tab:hover{color:var(--ink); background:rgba(255,240,214,.03);}
.tab + .tab{border-left:1px solid rgba(120,96,58,.22);}
/* Active is a bar under the label, not a filled pill — same as the lobby's sections. */
.tab.on{background:none; color:var(--gold);}
.tab.on::after{content:''; position:absolute; left:0; right:0; bottom:-1px; height:2px;
  background:var(--gold);}

/* LIFE: a squarer plate. Keeps the frosted backdrop so the seat art still blurs behind it. */
.life.big{border-radius:3px; border:1px solid rgba(120,96,58,.5);
  background:linear-gradient(180deg, rgba(20,17,13,.72), rgba(10,9,7,.78));
  box-shadow:0 10px 26px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,240,214,.06);}

/* NAMEPLATE: matches the life plate, one size down. */
.pname{border-radius:2px; border:1px solid rgba(120,96,58,.45);
  background:linear-gradient(180deg, rgba(20,17,13,.72), rgba(10,9,7,.78));
  box-shadow:0 5px 14px rgba(0,0,0,.5);
  letter-spacing:.12em; text-transform:uppercase; font-size:16px; min-height:32px;
  padding:0 18px;}

/* ---- SEAT ART: ZOOM AFFORDANCE ------------------------------------------------------------ */
/* A small magnifier in the tile's lower corner. The tile's own click still opens the emote wheel,
   so this needs its own target rather than taking that gesture over. */
.seatzoom{position:absolute; right:5px; bottom:5px; width:22px; height:22px; padding:0;
  display:flex; align-items:center; justify-content:center; border-radius:2px; cursor:pointer;
  font-family:var(--mono); font-size:12px; line-height:1; letter-spacing:0;
  background:rgba(8,11,16,.72); border:1px solid rgba(202,161,72,.55); color:#f0e2c4;
  opacity:0; transition:opacity .15s ease, background .15s ease, border-color .15s ease;
  -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);}
.seatart:hover .seatzoom{opacity:1;}
.seatzoom:hover{background:rgba(202,161,72,.3); border-color:rgba(232,198,107,1);}
body.overseer .seatzoom{display:none;}

/* ---- ART VIEWER --------------------------------------------------------------------------- */
#artView{display:none; position:fixed; inset:0; z-index:9800; padding:32px;
  background:rgba(6,8,11,.86); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  align-items:center; justify-content:center;}
#artView.show{display:flex;}
#artView .avInner{display:flex; flex-direction:column; align-items:center; gap:18px;}
/* The card at 2.9x (2.4 plus the 20%). cardEl sizes itself in px, so a transform scales the whole
   thing - frame, type and art together - instead of relaying it out at a size it was never
   designed for. The margin reserves the space the scale-up occupies, since a transform doesn't
   affect layout. */
#artView .avCard{transform:scale(2.9); transform-origin:center center;
  margin:calc(175px * 1.9 / 2) calc(125px * 1.9 / 2);}
/* No hover behaviour in here: this IS the enlarged view, so a zoom-on-hover has nothing to add
   and the lift just makes the card twitch under the pointer. */
#artView .avCard .card{cursor:default; pointer-events:none;}
#artView .avCard .card:hover{transform:none; box-shadow:none; filter:none;}
#artView .avMeta{text-align:center; display:flex; flex-direction:column; gap:6px;}
/* The card's name leads; the credit sits beneath it, smaller and quieter. */
#artView .avName{font-family:'Cinzel',serif; font-weight:700; font-size:20px; letter-spacing:.16em;
  text-transform:uppercase; color:#f0e2c4;}
#artView .avBy{font-family:'Charis SIL', Georgia, serif; font-style:italic; font-size:22px;
  color:#b8ad99; letter-spacing:.02em; line-height:1.3;}
#artView .avX{position:absolute; top:20px; right:22px; width:32px; height:32px; padding:0;
  display:flex; align-items:center; justify-content:center; border-radius:2px; cursor:pointer;
  font-size:18px; line-height:1; letter-spacing:0; font-family:var(--mono);
  background:rgba(255,255,255,.04); border:1px solid rgba(255,255,255,.18); color:var(--muted);}
#artView .avX:hover{background:rgba(202,161,72,.2); border-color:rgba(202,161,72,.8); color:#f0e2c4;}

/* ---- SETTINGS: 'needs a new game' reminder ----------------------------------------------- */
/* Same type as the ability list it sits above: .panel's inherited var(--font) at 12px/1.45.
   Charis SIL is for long-form reading (the patch notes); a one-line panel notice belongs with
   the text around it. */
#ref .restartnote{margin:0 0 10px; padding:8px 11px; border-radius:2px;
  border:1px solid rgba(202,161,72,.45); background:rgba(202,161,72,.08);
  font-family:var(--font); font-weight:700; font-synthesis-weight:none;
  font-size:12px; line-height:1.45; letter-spacing:.02em; color:#e9d9b3;}
#ref .restartnote.flashon{animation:restartpulse 1s ease-out 1;}
@keyframes restartpulse{
  0%  {border-color:rgba(232,198,107,1); background:rgba(202,161,72,.26);}
  100%{border-color:rgba(202,161,72,.45); background:rgba(202,161,72,.08);}
}

/* ---- QUEUE CARD ---------------------------------------------------------------------------
   .lcard was given padding:0 when the lobby panels took their own, but this card never did — so
   the Cancel button sat flush against the bottom edge. */
#lobby #lobbyQueue{padding:22px 24px 20px; gap:12px; align-items:stretch;}
#lobby #lobbyQueue #btnCancelQueue{align-self:center; padding:9px 26px; font-size:12px;}

/* ---- DECK KEY COPY ICON -------------------------------------------------------------------
   ⧉ has a high glyph origin in most fonts, so it reads as sitting a couple of pixels above
   centre even when the box is perfectly centred. Flex centring plus a small nudge fixes it by
   eye rather than by the font's metrics. */
.foot.footkey .keycopy{display:flex; align-items:center; justify-content:center;
  line-height:1; padding:0; height:26px;}
.foot.footkey .keycopy::before{content:'\29C9'; display:block; position:relative; top:1px;}

.foot.footkey .keycopy.copied::before{content:'\2713'; color:#8fe6c4;}
