:root { --chb: max(54px, 13.86vh); --ch: var(--chb); --cw: calc(var(--ch) * .7143); --hch: calc(var(--chb) * .6); --hcw: calc(var(--hch) * .7143); --bg: #14161c; --panel: #1e212b; --line: #333847; --text: #e6e8ee; --muted: #8b90a0; --accent: #5b8def; }
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; margin: 0; background: var(--bg); color: var(--text); font: 14px system-ui, sans-serif; }
button { background: #2a2f3d; color: var(--text); border: 1px solid var(--line); border-radius: 5px; padding: 5px 9px; cursor: pointer; font: inherit; }
button:hover { background: #363c4f; }
button.primary { background: var(--accent); border-color: var(--accent); }
button.danger:hover { background: #8b2b2b; }
input, select { background: #0f1116; color: var(--text); border: 1px solid var(--line); border-radius: 5px; padding: 6px 8px; font: inherit; }
.muted { color: var(--muted); }
.err { color: #ff7b7b; min-height: 1.2em; }

/* ---------- main menu / sign-in ---------- */
body { background: radial-gradient(1100px 650px at 50% -8%, #1c2b47 0%, #111623 52%, #0a0d14 100%) fixed; font-family: Inter, "Segoe UI", system-ui, -apple-system, sans-serif; }
#lobby { min-height: 100%; display: grid; place-items: center; padding: 24px 16px; overflow-y: auto; }
#lobbyCard { width: min(500px, 100%); background: #161b27ee; border: 1px solid #ffffff14; border-radius: 20px; padding: 34px 32px 26px; box-shadow: 0 30px 80px #000b, 0 0 0 1px #00000040; display: grid; gap: 22px; }
#lobbyCard.wide { width: min(980px, 100%); }
#lobbyCard.wide:has(#viewDecks:not([hidden])) { width: min(1240px, 100%); }
#lobbyCard h1, #lobbyCard h2, #lobbyCard h3, #lobbyCard p { margin: 0; }
#lobbyCard h2 { font-size: 22px; letter-spacing: -.01em; }
#lobbyCard label { display: grid; gap: 6px; font-size: 13px; color: #b7bccb; font-weight: 600; }
#lobbyCard input { padding: 13px 14px; font-size: 16px; border-radius: 11px; background: #0d1119; border: 1px solid #2b3245; }
#lobbyCard input:focus, #lobbyCard textarea:focus { outline: none; border-color: #5b8def; box-shadow: 0 0 0 3px #5b8def33; }
#lobbyCard form, #menu2 { display: grid; gap: 16px; }
#menu2 section { display: grid; gap: 14px; }
.brand { text-align: center; }
.brand .logo { width: 60px; height: 60px; margin: 0 auto 14px; border-radius: 17px; display: grid; place-items: center; font-size: 30px; color: #fff;
  background: linear-gradient(135deg, #4d7de8, #8f6bf0); box-shadow: 0 10px 30px #4d7de866; }
.brand h1 { font-size: 30px; font-weight: 800; letter-spacing: -.02em; }
.tagline { color: var(--muted); margin-top: 6px !important; font-size: 15px; }
.notice { text-align: center; padding: 10px 14px; border-radius: 10px; background: #ffb4541a; color: #ffd9a3; border: 1px solid #ffb45440; }
.err { color: #ff8a8a; min-height: 0; text-align: center; }
.err:empty { display: none; }

/* segmented sign-in / create-account switch */
.seg { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 4px; background: #0d1119; border-radius: 13px; border: 1px solid #ffffff10; }
.seg .tab { padding: 11px; border: 0; background: transparent; border-radius: 10px; color: #9aa1b5; font-size: 15px; font-weight: 600; }
.seg .tab:hover { color: #fff; background: #ffffff0a; }
.seg .tab.on { background: #2a3556; color: #fff; box-shadow: 0 2px 8px #0006; }
.two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.cta { padding: 15px 18px; font-size: 17px; font-weight: 700; border-radius: 13px; border: 0; color: #fff; cursor: pointer;
  background: linear-gradient(135deg, #4d7de8, #6b5be0); box-shadow: 0 8px 24px #4d7de844; transition: transform .08s, filter .15s; }
.cta:hover { filter: brightness(1.1); transform: translateY(-1px); background: linear-gradient(135deg, #4d7de8, #6b5be0); }
.cta:active { transform: none; }

/* home menu: two labelled groups, and Admin sits beside the username */
.menugroup { font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); padding: 2px 4px 0; }
.menugroup.second { margin-top: 10px; padding-top: 16px; border-top: 1px solid #ffffff14; }
.adminbtn { margin-left: auto; flex: none; padding: 8px 14px; border-radius: 10px; font-size: 14px; font-weight: 700; background: #ffffff10; border: 1px solid #ffffff1c; color: #dfe4f5; cursor: pointer; }
.adminbtn:hover { background: #5b8def33; border-color: #5b8def; color: #fff; }
/* who is signed in */
.userbar { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 14px; background: #ffffff08; border: 1px solid #ffffff10; }
.userbar .avatar { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; font-weight: 800; font-size: 17px; color: #fff; background: linear-gradient(135deg, #5b8def, #8f6bf0); flex: none; }
.userbar .who { display: grid; min-width: 0; }
.userbar b { font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.userbar small { color: var(--muted); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* big, simple menu buttons */
.bigbtn { display: flex; align-items: center; gap: 16px; width: 100%; min-height: 72px; padding: 14px 20px; border-radius: 15px; border: 1px solid #ffffff18; background: #ffffff0b;
  color: #fff; text-align: left; cursor: pointer; transition: transform .08s, background .15s, border-color .15s, box-shadow .15s; }
.bigbtn:hover { background: #ffffff16; border-color: #5b8def99; transform: translateY(-1px); box-shadow: 0 8px 22px #0006; }
.bigbtn:active { transform: none; }
.bigbtn .ico { width: 44px; height: 44px; flex: none; border-radius: 12px; display: grid; place-items: center; font-size: 21px; background: #ffffff16; }
.bigbtn .txt { display: grid; gap: 2px; min-width: 0; }
.bigbtn b { font-size: 18px; font-weight: 700; }
.bigbtn small { color: #ffffffa8; font-size: 13.5px; font-weight: 400; }
.bigbtn.primary { border-color: transparent; background: linear-gradient(135deg, #4d7de8, #6b5be0); box-shadow: 0 10px 28px #4d7de855; }
.bigbtn.primary:hover { background: linear-gradient(135deg, #5b8af0, #7a6aeb); }
.bigbtn.primary .ico { background: #ffffff26; }
.bigbtn.ghost { justify-content: center; min-height: 50px; background: transparent; border-color: #ffffff12; color: #aab0c2; font-size: 15px; font-weight: 600; }
.bigbtn.ghost:hover { color: #fff; box-shadow: none; }
.back { justify-self: start; background: none; border: 0; padding: 4px 2px; color: #9aa1b5; font-size: 15px; cursor: pointer; }
.back:hover { color: #fff; background: none; }
.codein { text-align: center; font-size: 26px !important; font-weight: 800; letter-spacing: .25em; text-transform: uppercase; padding: 16px !important; }
.codein::placeholder { letter-spacing: .12em; font-size: 18px; font-weight: 600; opacity: .5; }

/* your games */
.game { display: flex; gap: 14px; align-items: center; padding: 14px 16px; border-radius: 14px; background: #ffffff0a; border: 1px solid #ffffff14; }
.game .info { flex: 1; min-width: 0; display: grid; gap: 3px; }
.game .info b { font-size: 17px; letter-spacing: .06em; }
.game button { padding: 11px 20px; border-radius: 11px; font-size: 15px; font-weight: 700; }
.game button.gamedel { width: 30px; height: 30px; padding: 0; border-radius: 8px; font-size: 13px; line-height: 1; }
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #666; margin-right: 4px; }
.dot.on { background: #4caf50; }

/* deck lists */
.dechead { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.dechead h2 { margin: 0; }
button.newdeck { padding: 6px 14px; border-radius: 8px; font-size: 13px; font-weight: 700; background: #2e9e57; border: 1px solid #38b767; color: #fff; cursor: pointer; }
button.newdeck:hover { background: #38b767; }
/* saved decks: a box of rows (click to edit) grouped under folder headers, with status columns (cards, mana curve, commander, colours) */
.deckbox { display: grid; gap: 2px; margin: 10px 0 14px; padding: 6px; max-height: 50vh; overflow-y: auto; border: 1px solid #ffffff1c; border-radius: 12px; background: #0d1119; }
.folderhead { display: flex; align-items: center; gap: 8px; width: 100%; margin: 6px 0 2px; padding: 8px 10px; font: inherit; font-size: 15px; font-weight: 700; letter-spacing: .01em; color: #fff; background: none; border: 1px solid transparent; border-radius: 8px; cursor: pointer; text-align: left; }
.folderhead:first-child { margin-top: 0; }
.folderhead:hover { background: #ffffff10; }
.folderhead .chevron { flex: none; width: 10px; display: inline-block; transition: transform .12s; color: #ffffff80; }
.folderhead.open .chevron { transform: rotate(90deg); }
.foldericon { flex: none; width: 16px; height: 16px; display: inline-flex; }
.foldericon svg { width: 100%; height: 100%; color: #ffd479; }
.dmrow { display: grid; grid-template-columns: minmax(0, 1fr) 86px 46px 210px minmax(0, 1.1fr) 118px 26px; align-items: center; gap: 12px; padding: 7px 10px; border: 1px solid transparent; border-radius: 8px; background: none; color: #fff; font: inherit; font-size: 13px; text-align: left; cursor: pointer; }
.dmrow > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
button.dmrow:hover { background: #ffffff10; }
.dmrow .n { text-align: right; font-variant-numeric: tabular-nums; }
.dmrow .dn { display: flex; flex-direction: column; gap: 2px; white-space: normal; overflow: hidden; }
.dmrow .dn .dnname { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dmrow .dn .tags { font-weight: 400; font-size: 11px; color: #ffffff80; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dmrow .cols { display: flex; gap: 3px; overflow: visible; }
.dmrow .cv { overflow: visible; }
.dmrow .rowdel { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 6px; font-size: 12px; color: #ffffff90; text-overflow: clip; }
.dmrow .rowdel:hover { background: #a03a3a; color: #fff; }
.curve { display: flex; align-items: flex-end; gap: 3px; height: 47px; }
.curve .cc { flex: 1; min-width: 14px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; }
.curve .cc b { font-size: 10px; font-weight: 700; line-height: 12px; color: #dfe6ff; font-variant-numeric: tabular-nums; }
.curve .cc.zero b { color: #ffffff40; font-weight: 400; }
.curve .cc i { display: block; width: 100%; background: linear-gradient(#7aa2ff, #4d7de8); border-radius: 2px 2px 0 0; min-height: 0; }
.curve .cc.zero i { height: 2px !important; background: #ffffff25; }
.curve .cc { height: 100%; }
/* average mana value: one plain line, vertically centred like the other columns so it lines up with the card count */
.curve .avg { align-self: center; display: flex; align-items: baseline; gap: 4px; margin-right: 6px; padding-right: 8px; border-right: 1px solid #ffffff20; white-space: nowrap; }
.curve .avg b { font-size: 13px; font-weight: 400; color: #fff; font-variant-numeric: tabular-nums; }
.curve .avg small { font-size: 10px; color: #ffffff80; }
.curve .cc small { font-size: 9px; line-height: 11px; color: #ffffff80; }
.curve .cc:not(.zero) i { flex: none; }
img.mana { width: 20px; height: 20px; vertical-align: middle; filter: drop-shadow(0 1px 1px #0008); }
@media (max-width: 700px) { .dmrow { grid-template-columns: minmax(0, 1fr) 40px 110px 80px 26px; } .dmrow > .dc, .dmrow > .dt { display: none; } #lobbyCard { padding: 26px 20px 20px; } }

/* admin table */
.tablewrap { overflow: auto; padding: 0 14px 14px 0; } /* room on the right and bottom so the scroll bars don't sit on top of the table */
table.adm { width: 100%; border-collapse: collapse; font-size: 13px; }
table.adm th, table.adm td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
table.adm td.actions { display: flex; gap: 4px; }

/* ---------- game screen (Arena-style playmat) ---------- */
#app { height: 100%; display: flex; flex-direction: column; }
#topbar > *, #topbar button { white-space: nowrap; }
#topbar { display: flex; gap: 8px; align-items: center; padding: 5px 12px; background: #0b0e14; border-bottom: 1px solid #ffffff14; font-size: 13px; position: relative; z-index: 40; }
#menuPanel { position: absolute; right: 8px; top: 38px; z-index: 45; background: #262a37; border: 1px solid #4a5068; border-radius: 8px; padding: 6px; display: grid; gap: 4px; min-width: 230px; box-shadow: 0 8px 24px #000a; }
#menuPanel button { text-align: left; }
#menuPanel hr { border: 0; border-top: 1px solid #4a5068; width: 100%; margin: 2px 0; }
#menuPanel .menusection { display: grid; gap: 4px; padding: 4px; border: 1px solid #a03a3a66; border-radius: 6px; background: #a03a3a12; }
#menuPanel .menulabel { font-size: 11px; letter-spacing: .06em; font-weight: 700; color: #ffffffb0; padding: 0 2px; }
.zoom input[type=color] { width: 44px; height: 26px; padding: 0; border: 1px solid #ffffff40; border-radius: 6px; background: none; cursor: pointer; }
.zoom { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 2px 4px; }
#zoomPct { display: inline-block; min-width: 42px; text-align: center; }
main { flex: 1; display: flex; min-height: 0; }

#stage { position: relative; flex: 1; min-width: 0; overflow: hidden;
  background: radial-gradient(ellipse at 50% 42%, #33465c 0%, #1e2a3a 48%, #0d1119 100%); }
#board { height: 100%; display: flex; flex-direction: column; padding-bottom: 0; } /* room for the (smaller) hand plus your name/life bar below it */
#oppRow { flex: 1; display: flex; flex-wrap: wrap; align-content: stretch; min-height: 0; }
#oppRow > .seat { flex: 0 0 calc(100% / var(--cols, 1)); }
#oppRow > .waiting { flex: 1 1 100%; }
/* admin dummy control: a bar at the top of the table while you are acting as a dummy player */
#ctlBanner { position: absolute; top: 6px; left: 50%; transform: translateX(-50%); z-index: 60; display: flex; align-items: center; gap: 12px; padding: 6px 8px 6px 14px; border-radius: 999px; background: #3a2a0ee6; border: 1px solid #ffb30099; color: #ffe2a3; font-size: 13px; box-shadow: 0 4px 16px #000a; white-space: nowrap; }
#ctlBanner button { padding: 4px 12px; font-size: 12px; border-radius: 999px; }
/* the shared stack: a slim vertical tab on the right edge of the table (out of the way) that slides out into a panel of layered
   cards, newest on top, when something is cast; each layer has a Resolve button */
#stackTab { position: absolute; right: 0; top: 50%; transform: translateY(-50%); z-index: 45; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; box-sizing: border-box; width: 24px; height: clamp(160px, 24%, 240px); padding: 0; border: 1px solid #ffffff2a; border-right: 0; border-radius: 10px 0 0 10px; background: #1b1f2acc; color: var(--muted); cursor: pointer; }
#stackTab[hidden] { display: none; }
#stackTab span { writing-mode: vertical-rl; font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
#stackTab b { writing-mode: horizontal-tb; min-width: 16px; padding: 1px 3px; border-radius: 9px; background: #ffffff1c; color: #fff; font-size: 11px; text-align: center; }
#stackTab:hover, #stackTab.drop { color: #fff; background: #2a3350; border-color: var(--accent); }
#stackTab.has { color: #fff; border-color: var(--accent); box-shadow: 0 0 14px #5b8def66; }
#stackTab.has b { background: var(--accent); }
#stackPanel { position: absolute; right: 0; top: 50%; transform: translateY(-50%); z-index: 46; --ch: calc(var(--chb) * 1.05); --cw: calc(var(--ch) * .7143);
  display: flex; flex-direction: column; max-height: 88%; width: calc(var(--cw) + 178px); min-width: 290px; background: #10131af2; border: 1px solid #ffffff2a; border-right: 0; border-radius: 12px 0 0 12px; box-shadow: -8px 0 28px #000a; animation: stackin .16s ease-out; }
#stackPanel[hidden] { display: none; }
#stackPanel.drop { border-color: var(--accent); background: #16213aee; }
@keyframes stackin { from { transform: translate(24px, -50%); opacity: 0; } }
#stackHead { flex: none; display: flex; align-items: center; gap: 6px; padding: 7px 8px 7px 12px; border-bottom: 1px solid #ffffff14; }
#stackHead span { flex: 1; font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
#stackHead span, #stackHead button, .slayerwho { white-space: nowrap; }
#stackHead button { padding: 3px 8px; font-size: 11px; }
#stackCards { flex: 1; min-height: 0; overflow-y: auto; padding: 10px 12px 12px; display: flex; flex-direction: column; align-items: center; }
.stackempty { padding: 14px 4px; font-size: 12px; line-height: 1.4; color: var(--muted); text-align: center; }
/* one row per spell: the card, then a dropdown for where it resolves to, then a → button that resolves it */
.slayer { position: relative; flex: none; width: 100%; display: flex; align-items: center; gap: 8px; }
.slayer.top { margin-bottom: 6px; }
.slayer:not(.top) { margin-bottom: 4px; }
.scard { position: relative; flex: none; width: var(--cw); border-radius: 8px; }
.scard .card { position: static; display: block; border: 2px solid var(--pc, #888); border-radius: 8px; box-shadow: 0 2px 8px #000a; }
.slayer:not(.top) .scard { height: 44px; overflow: hidden; }
.slayerwho { font-size: 10px; text-align: center; color: var(--pc, #ccc); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-top: 3px; }
.slayer:not(.top) .slayerwho { position: absolute; left: 4px; bottom: 2px; padding: 0 5px; max-width: 80%; border-radius: 6px; background: #000c; }
.sctl { flex: 1; min-width: 0; display: flex; align-items: center; gap: 5px; }
.sdest { flex: 1; min-width: 0; padding: 6px 4px; font-size: 12px; border-radius: 8px; background: #ffffff10; color: #fff; border: 1px solid #ffffff2a; cursor: pointer; }
.sdest option { background: #1b1f2a; color: #fff; }
.sgo { flex: none; width: 36px; height: 34px; padding: 0; font-size: 20px; line-height: 1; font-weight: 700; color: #fff; background: linear-gradient(135deg, #4d7de8, #6b5be0); border-color: transparent; border-radius: 8px; cursor: pointer; }
.sgo:hover { filter: brightness(1.15); }
/* one clean divider between the two halves: a soft line that fades out toward the edges */
#meSeat { flex: 1; display: flex; min-height: 0; position: relative; }
#meSeat::before { content: ''; position: absolute; top: -1px; left: 0; right: 0; height: 2px; z-index: 6; pointer-events: none; background: linear-gradient(90deg, transparent, #ffffff55 15%, #ffffff55 85%, transparent); }
.codecopy { cursor: pointer; padding: 1px 8px; border-radius: 6px; background: #ffffff14; border: 1px solid #ffffff30; color: #fff; letter-spacing: .08em; }
.codecopy:hover { background: var(--accent); }
/* "Room 44B2" in a pill; clicking it copies the invite link */
#roomTag { display: inline-flex; align-items: center; padding: 2px 10px; border-radius: 10px; background: #2a3556; color: #cdd6f4; font-size: 12px; letter-spacing: .04em; cursor: pointer; }
#roomTag strong { font-weight: 700; }
#roomTag:hover, #roomTag:focus-visible { background: #34426c; outline: none; }
.copiedpop { position: fixed; z-index: 300; padding: 4px 10px; border-radius: 6px; background: #2f9e6a; color: #fff; font-size: 12px; font-weight: 700; pointer-events: none; box-shadow: 0 4px 12px #0008; animation: copiedpop 1.2s ease-out forwards; }
@keyframes copiedpop { 0% { opacity: 0; transform: translateY(-4px); } 12% { opacity: 1; transform: none; } 75% { opacity: 1; } 100% { opacity: 0; } }
.waiting { margin: auto; color: var(--muted); font-size: 16px; text-align: center; }

.seat { flex: 1; min-width: 0; min-height: 0; display: grid; grid-template-columns: 1fr auto; position: relative; }
.seat + .seat { border-left: 1px solid #ffffff14; }
.opp { --ch: calc(var(--chb) * var(--os, .8)); --cw: calc(var(--ch) * .7143); }
/* name + life: a compact bar centred on the table edge nearest the player (bottom for you, top for opponents) */
.side { position: absolute; left: 50%; transform: translateX(-50%); z-index: 8; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 4px 16px; width: 420px; max-width: calc(100% - 16px); height: 92px; overflow: visible; box-sizing: border-box; padding: 4px 20px; border-radius: 34px; background: #000000c0; border: 2px solid var(--pc); } /* the same size for you and for opponents */
.side .pinfo { display: grid; gap: 1px; justify-items: start; }
.side .pcs { display: flex; flex-direction: column; align-items: flex-end; justify-content: center; gap: 2px; }
.side .pcs .pc { font-size: 10.5px; padding: 0 8px; line-height: 15px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* compact, so three statuses and the "+N more" chip fit the bar */ /* a right-aligned column: three show, the rest are behind "+N more" */
.side .morewrap { position: relative; }
.side .pc.more { background: #ffffff1f; color: #e6e9f2; cursor: default; }
.side .morepop { display: none; position: absolute; right: 100%; bottom: -4px; z-index: 30; flex-direction: column; align-items: flex-end; gap: 3px; padding: 6px 14px 6px 6px; border-radius: 10px; background: #10141ff2; border: 1px solid #ffffff2a; box-shadow: 0 8px 24px #000c; white-space: nowrap; }
.side .morewrap:hover .morepop { display: flex; }
/* the list opens to the left of the chip and touches it (no gap), so moving the mouse onto the list keeps it open and its entries can be clicked to remove them */
.pname.statusname { cursor: pointer; }
.pname.statusname:hover { text-decoration: underline dotted; text-underline-offset: 3px; }
/* the life circle with the poison and commander-damage counters right underneath it */
.side .lifecol { display: grid; justify-items: center; gap: 3px; }
.side .dmgrow { display: flex; gap: 6px; align-items: center; justify-content: center; }
/* an opponent's bar stays the compact single-row pill it was: name, time, life and counters in a wrapping row (only your own bar uses the three columns) */
.opp .side { grid-row: 1; } /* same row as the card backs (which are centered), the bar is on the right, so the seat's rows stay as they were */
/* an opponent's hand: their cards face down in a fan, in the middle of the top of their side of the table */
.opphand { grid-column: 1 / -1; grid-row: 1; align-self: center; justify-self: center; margin: 6px 0 0; display: flex; align-items: center; z-index: 7; pointer-events: auto; }
.oback { display: block; width: 26px; height: 37px; margin-left: -14px; border-radius: 4px; border: 2px solid #1b120a; box-shadow: 0 2px 5px #0009;
  background: url(/cardback.jpg) center / cover; }
.oback:first-child { margin-left: 0; }
.opphand { flex-direction: column; gap: 3px; }
.ofan { display: flex; align-items: center; }
.ocount { font-size: 12px; font-weight: 700; color: #ffffffb8; letter-spacing: .03em; text-shadow: 0 1px 4px #000; }
/* on your turn the whole bar is tinted in your colour with a thicker outline (steady: no glow or pulsing) */
#meBar.turn .side, .seat.turn .side { background: color-mix(in srgb, var(--pc) 26%, #000000d0); box-shadow: 0 0 0 2px var(--pc); }
.turnbadge { padding: 0 8px; border-radius: 8px; background: var(--pc); color: #111; font-size: 10px; font-weight: 900; letter-spacing: .08em; }
/* your own bar lives below the hand, at the bottom edge of the stage (not inside the seat) */
#meBar { position: absolute; right: 2.5%; width: max(32%, 380px); bottom: 6px; z-index: 12; }
#meBar .side { position: static; transform: none; max-width: none; width: 100%; } /* (the percentage max-width would be measured against the bar's own shrink-wrapped box and squeeze it) */
#meBar.turn .orb { border-width: 4px; }
/* an opponent's bar is the first row of their seat, so it can wrap to two lines without covering their cards */
.opp { grid-template-rows: auto minmax(0, 1fr); }
.opp .side { position: static; transform: none; grid-column: 1 / -1; margin: 6px 26px 0 auto; } /* right-hand side, like your own bar */
.me .bf { padding-bottom: 0; }
.opp .bf { padding-top: 0; }
.orb { width: 46px; height: 46px; border-radius: 50%; border: 3px solid var(--pc); background: radial-gradient(circle at 30% 28%, #3d475d, #151a25); display: grid; place-items: center; font-size: 20px; font-weight: 800; cursor: pointer; user-select: none; }
.seat.turn .orb { border-width: 4px; }
.liferow { display: flex; align-items: center; gap: 6px; }
.liferow button { border-radius: 50%; width: 26px; height: 26px; padding: 0; }
/* free-text note on a card: a yellow label across the card's lower third */
.cardnote { position: absolute; left: 4px; right: 4px; bottom: 26%; z-index: 4; padding: 2px 5px; border-radius: 5px; background: #f2c94ccc; color: #1b1400; font-size: 11px; font-weight: 700; line-height: 13px; text-align: center; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; pointer-events: none; box-shadow: 0 1px 4px #0008; }
/* running life change next to the orb: damage in red, life gained in green, gone 5 seconds after the last adjustment */
.orb { position: relative; }
.ldelta { position: absolute; left: 50%; bottom: calc(100% + 4px); transform: translateX(-50%); padding: 1px 9px; border-radius: 10px; font-size: 16px; font-weight: 900; line-height: 20px; white-space: nowrap; pointer-events: none; z-index: 20; box-shadow: 0 2px 8px #000a; animation: ldeltain .15s ease-out; }
.opp .ldelta { bottom: auto; top: calc(100% + 4px); animation-name: ldeltainopp; } /* an opponent's bar is at the top of the screen, so their change tag opens below the orb (above would be cut off) */
@keyframes ldeltainopp { from { transform: translate(-50%, -6px); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }
.ldelta.neg { background: #c0322f; color: #fff; }
.ldelta.pos { background: #2f9b57; color: #fff; }
@keyframes ldeltain { from { transform: translate(-50%, 6px); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }
/* first-turn roll: one die over each player's board, then the winner lit up */
#firstlayer { position: absolute; inset: 0; z-index: 69; pointer-events: auto; background: #04060bb8; overflow: hidden; }
#firstlayer.done { cursor: pointer; }
.fdie { position: absolute; width: var(--sz); height: var(--sz); transform: translate(-50%, -50%); transition: transform .35s cubic-bezier(.3, 1.4, .5, 1), opacity .3s, filter .3s; }
.fdie svg { width: 100%; height: 100%; overflow: visible; fill: #182036; stroke: var(--pc, #fff); stroke-width: 3.2; stroke-linejoin: round; filter: drop-shadow(0 10px 24px #000c); }
.fdie svg .facet { fill: none; stroke: color-mix(in srgb, var(--pc, #fff) 55%, transparent); stroke-width: 1.4; }
.fdie .dnum { position: absolute; inset: 0; display: grid; place-items: center; font-size: calc(var(--sz) * .34); font-weight: 900; color: #fff; text-shadow: 0 2px 8px #000; font-variant-numeric: tabular-nums; }
.fdie .flabel { position: absolute; top: calc(100% + 8px); left: 50%; transform: translateX(-50%); font-size: 15px; font-weight: 800; color: var(--pc, #fff); white-space: nowrap; text-shadow: 0 2px 6px #000; }
.fdie.tumble svg { animation: ftumble .5s linear infinite; }
@keyframes ftumble { to { transform: rotate(360deg); } }
.fdie.dim { opacity: .35; filter: grayscale(.6); }
.fdie.tie svg { stroke: #ffd479; stroke-width: 5; animation: ftie .5s ease-in-out 3; }
@keyframes ftie { 50% { transform: scale(1.12); } }
.fdie.win { transform: translate(-50%, -50%) scale(1.35); z-index: 2; }
.fdie.win svg { stroke-width: 5; filter: drop-shadow(0 0 30px var(--pc)) drop-shadow(0 0 60px var(--pc)); }
.fdie.win .flabel::after { content: ' · FIRST'; color: #ffd479; }
.fbanner { position: absolute; left: 0; right: 0; top: 4%; text-align: center; font-size: clamp(18px, 3.4vh, 32px); font-weight: 800; color: #e6e9f2; text-shadow: 0 2px 10px #000; pointer-events: none; }
.fbanner.winner { font-size: clamp(26px, 5.4vh, 54px); color: #fff; }
.fhint { position: absolute; left: 0; right: 0; bottom: 4%; text-align: center; font-size: 14px; color: #ffffff99; pointer-events: none; }
/* a revealed card: full-screen view over the table, click anywhere to close */
#revealbox { position: absolute; inset: 0; z-index: 68; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 16px; cursor: pointer; background: radial-gradient(circle at 50% 45%, #0d1220e0, #05070cf2); animation: dicefade .2s ease-out; }
#revealbox img { max-height: calc(100% - 90px); max-width: 100%; aspect-ratio: 5 / 7; object-fit: contain; border-radius: 4.5% / 3.2%; box-shadow: 0 20px 70px #000, 0 0 40px color-mix(in srgb, var(--pc, #fff) 35%, transparent); }
/* a card another player just played: fills the opponents' battlefield for a few seconds (see queuePlayed in app.js) */
#playedbox { position: absolute; z-index: 60; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 12px; cursor: pointer; background: radial-gradient(circle at 50% 45%, #0d1220e6, #05070cf0); animation: dicefade .2s ease-out; }
#playedbox img { flex: 1 1 0; min-height: 0; max-width: 100%; aspect-ratio: 5 / 7; object-fit: contain; border-radius: 4.5% / 3.2%; box-shadow: 0 20px 70px #000, 0 0 40px color-mix(in srgb, var(--pc, #fff) 35%, transparent); }
.revealblank { padding: 40px; border-radius: 14px; background: #2b3040; font-size: 28px; font-weight: 800; }
.revealwho { font-size: clamp(16px, 2.6vh, 24px); color: #e6e9f2; }
.revealwho b { color: var(--pc, #fff); }
.revealwho b:last-child { color: #ffd479; }
.revealhint { font-size: 12px; color: #ffffff66; }
.cardname.revealed { cursor: pointer; text-decoration: underline dotted; }
/* "no commander marked" warning with an example */
.cmdrwarn { display: grid; gap: 8px; padding: 12px 14px; border-radius: 10px; background: #f2c94c1f; border: 1px solid #f2c94c66; font-size: 13px; }
.cmdrwarn b { color: #ffd479; font-size: 14px; }
.cmdrwarn pre { margin: 0; padding: 10px 12px; border-radius: 8px; background: #0d1119; color: #d5d9e4; font: 12.5px ui-monospace, monospace; white-space: pre-wrap; }
/* commander tax adjuster */
.taxadj { display: flex; align-items: center; justify-content: center; gap: 22px; padding: 10px 0; }
.taxadj button { width: 64px; height: 44px; font-size: 18px; font-weight: 800; border-radius: 10px; }
.taxadj button[disabled] { opacity: .4; }
.taxval { min-width: 90px; text-align: center; font-size: 38px; font-weight: 800; color: #ffe9a8; font-variant-numeric: tabular-nums; }
/* a card flying from the library to the hand when drawing */
.flycard { position: fixed; left: 0; top: 0; z-index: 60; pointer-events: none; transform-origin: 0 0; border-radius: 6px; border: 2px solid #1b120a; box-sizing: border-box; box-shadow: 0 8px 22px #000b;
  background: url(/cardback.jpg) center / cover; }
/* over a player's board while they choose their starting hand */
.choosing { position: absolute; inset: 0; z-index: 6; display: grid; place-items: center; background: #04060b99; pointer-events: none; border-radius: 4px; }
.choosingbox { padding: 12px 22px; border-radius: 14px; background: #10141fe6; border: 1px solid #ffffff2a; font-size: clamp(14px, 2.4vh, 22px); color: #e6e9f2; text-align: center; box-shadow: 0 10px 40px #000a; }
.choosingbox b { font-weight: 800; }
.choosingbox .dots { display: inline-block; animation: choosingdots 1.2s steps(4, end) infinite; overflow: hidden; vertical-align: bottom; width: 1em; }
@keyframes choosingdots { from { width: 0; } to { width: 1.1em; } }
/* changelog */
.vertop { font-size: 11px; color: #ffffff59; cursor: pointer; align-self: center; margin-right: 2px; }
.vertop:hover { color: #ffffffb0; }
.changelog { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 8px; overscroll-behavior: contain; }
.changelog h3 { margin: 10px 0 2px; font-size: 15px; }
.changes { margin: 4px 0 12px; padding-left: 20px; display: grid; gap: 4px; font-size: 13px; color: #d5d9e4; }
.curver { color: #8fd18f; font-weight: 700; }
.verlink { display: block; margin: 10px auto 0; background: none; border: 0; color: #ffffff90; font-size: 13px; cursor: pointer; text-decoration: underline; }
.verlink:hover { color: #fff; }
/* opening hand: seven cards, keep or mulligan */
#opening { position: absolute; inset: 0; z-index: 66; display: grid; place-items: center; padding: 16px; overflow: auto; background: radial-gradient(circle at 50% 45%, #0a0f1cc0, #04060bee); }
.openbox { display: grid; gap: 14px; justify-items: center; max-width: 100%; padding: 22px 26px; border-radius: 16px; background: #141a29f0; border: 1px solid #ffffff22; box-shadow: 0 24px 80px #000c; }
.openbox h2 { margin: 0; }
.openhand { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.openhand img, .openhand .blankcard { width: min(15vw, 170px); border-radius: 8px; box-shadow: 0 6px 18px #000a; }
.openhand .blankcard { aspect-ratio: 5 / 7; background: #2b3040; padding: 6px; font-size: 12px; }
.openhand .opencard.chosen { outline: 4px solid #ffd479; outline-offset: 2px; transform: translateY(-8px); opacity: .85; }
.openhand .opencard { transition: transform .1s; }
/* scry: each card is its own clickable tile with a Top / Bottom tag under it */
.scrycard { display: grid; justify-items: center; gap: 8px; cursor: pointer; transition: transform .1s; } /* the whole tile moves together, so the tag underneath is never covered */
.scrycard img, .scrycard .blankcard { width: min(15vw, 170px); border-radius: 8px; box-shadow: 0 6px 18px #000a; }
.scrycard .blankcard { aspect-ratio: 5 / 7; background: #2b3040; padding: 6px; font-size: 12px; }
.scrycard .scrytag { padding: 2px 10px; border-radius: 8px; background: #ffffff14; color: #cfd4e2; font-size: 11px; font-weight: 700; }
.scrycard.chosen .scrytag { background: #ff8a8a2e; color: #ffb8b8; }
.scrycard:not(.chosen) .scrytag { background: #7be08a22; color: #9beaa8; }
.scrycard.dragging { opacity: .35; }
.scryrow { position: relative; min-height: 60px; }
.scryzone { border: 1px solid #ffffff1f; border-radius: 10px; padding: 8px 10px 10px; margin-top: 10px; }
.scryzone.bot { background: #ff8a8a0d; border-color: #ff8a8a40; }
.scryzone.over { border-color: #ffd479; box-shadow: 0 0 0 1px #ffd47955; }
.scryzonehead { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #8b90a0; margin-bottom: 8px; }
.scryempty { align-self: center; color: #8b90a0; font-size: 12px; padding: 18px 8px; }
/* the bar shown in the gap where a dragged scry card will be dropped */
.scrydrop { position: absolute; width: 4px; margin-left: -2px; border-radius: 2px; background: #ffd479; box-shadow: 0 0 10px #ffd479; pointer-events: none; z-index: 2; }
.scrydrop[hidden] { display: none; }
/* a subtle line + arrowhead above the row: left is the top of your library, right is deeper in it */
#opening button[disabled] { opacity: .45; cursor: default; }
.housebox { color: #c9cddb; font-size: 14px; cursor: pointer; }
/* tight deck list: name | cards | commander | colours */
.decklist { display: grid; gap: 2px; max-height: 50vh; overflow: auto; margin: 10px 0; }
.deckrow { display: grid; grid-template-columns: minmax(0, 1.2fr) 80px 52px minmax(0, 1.4fr) 110px; align-items: center; gap: 12px; padding: 5px 10px; border: 0; border-radius: 6px; background: #ffffff0a; color: #fff; font: inherit; font-size: 13px; text-align: left; cursor: pointer; }
button.deckrow:hover { background: var(--accent); }
.deckrow > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.deckrow .n { text-align: right; font-variant-numeric: tabular-nums; }
.deckrow .dn { font-weight: 700; }
.deckrow.head { background: none; cursor: default; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: #ffffff80; padding-top: 0; padding-bottom: 2px; }
.deckrow .cols { display: flex; gap: 3px; overflow: visible; }
.ptime { min-width: 62px; text-align: center; font-size: 13px; color: #ffffffb0; font-variant-numeric: tabular-nums; white-space: nowrap; }
.seat.turn .ptime, #meBar.turn .ptime { color: #ffd479; font-weight: 700; }
.pname { font-weight: 700; text-align: center; font-size: 15px; white-space: nowrap; }
.pname.off { opacity: .5; }
.pcs { display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; }
.pc { font-size: 12px; background: #0005; border-radius: 10px; padding: 2px 8px; cursor: pointer; user-select: none; }
.chip { padding: 2px 8px; font-size: 12px; }
/* the number chips are sized for two digits (up to 99) so the bar never resizes as a count grows */
.pc.poison, .pc.cmd { display: inline-block; box-sizing: border-box; min-width: 54px; padding: 3px 10px; font-size: 14px; font-weight: 700; text-align: center; font-variant-numeric: tabular-nums; }
.pc.poison { color: #b8f0a6; }
.pc.tax { background: #5a4510; color: #ffe9a8; }
.slotcard { position: relative; }
/* commander tax under the command zone pile */
.slot { position: relative; }
/* over the bottom of the card (not under it), left and right, so the Command label lines up with the other piles */
.taxrow { position: absolute; left: 3px; right: 3px; bottom: 22px; z-index: 5; display: flex; justify-content: space-between; gap: 4px; pointer-events: none; }
.taxrow .taxitem { pointer-events: auto; }
.taxrow.one { justify-content: center; }
/* while you drag a commander, its tax circle lights up */
.taxitem.hot { outline: 2px solid #fff; outline-offset: 1px; box-shadow: 0 0 12px 3px currentColor; transform: scale(1.18); transition: transform .1s; z-index: 6; }
.taxitem { padding: 0 7px; border-radius: 8px; background: #5a4510; color: #ffe9a8; font-size: 11px; font-weight: 800; border: 1px solid #ffd47966; white-space: nowrap; cursor: default; }
/* one colour per commander: gold, teal, purple */
.taxitem.c1 { background: #0d4a5a; color: #c4f3ff; border-color: #5cd0eb88; }
.taxitem.c2 { background: #4a2a6b; color: #ecd9ff; border-color: #b58aef88; }
.taxitem.mine { cursor: pointer; }
.taxitem.mine:hover { filter: brightness(1.25); }
.pc.status { background: #3b2f6b; color: #efe9ff; }
.pc.lethal { background: #a12a2a; color: #fff; }

.bf { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* visible, not hidden: a stack's extra layers, its count badge and tapped (sideways) cards stick out past the card, and at the edge of a lane they were cut off */
.lane { position: relative; overflow: visible; min-height: 0; }
.lane.main { flex: 1; z-index: 2; }
.lane.lands { z-index: 1; }
/* cards in the lands row are drawn smaller (70% of the normal size) automatically, wherever a land lands in it */
.lane.lands { --ch: calc(var(--chb) * .7); --cw: calc(var(--ch) * .7143); }
.opp .lane.lands { --ch: calc(var(--chb) * var(--os, .8) * .7); }
.lane.lands { flex: none; height: calc(var(--ch) + 14px); background: #00000026; }
.opp .lane.lands { border-bottom: 1px solid #ffffff12; }
.me .lane.lands { border-top: 1px solid #ffffff12; }
.lane.drop { background: #5b8def22; }
.lane-label { position: absolute; left: 8px; bottom: 4px; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: #ffffff2e; pointer-events: none; }
.opp .lane-label { bottom: auto; top: 4px; }
.probe { position: absolute; visibility: hidden; width: var(--cw); height: var(--ch); pointer-events: none; }

.piles { display: grid; grid-template-columns: repeat(2, auto); gap: 8px 10px; padding: 8px 10px; align-content: start; }
.me .piles { align-content: end; }
/* the piles sit in fixed cells: Library and Command in the left column, Graveyard with Exile right after it (below it) in the right column */
.piles .slot[data-zone="library"] { grid-area: 1 / 1; }
.piles .slot[data-zone="graveyard"] { grid-area: 1 / 2; }
.piles .slot[data-zone="command"] { grid-area: 2 / 1; }
.piles .slot[data-zone="exile"] { grid-area: 2 / 2; }
.slot { cursor: pointer; width: calc(var(--cw) * .8); border-radius: 6px; }
.slot.drop { outline: 2px dashed var(--accent); }
.slotlabel { font-size: 11px; color: #ffffffa0; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.slotcard { width: 100%; height: calc(var(--ch) * .8); border-radius: 5px; overflow: hidden; background: #000; display: grid; place-items: center; font-size: 11px; text-align: center; box-shadow: 0 2px 8px #0008; }
.slotcard img { width: 100%; height: 100%; display: block; }
/* several commanders: the extra ones sit behind the top card, each stepped up so its top strip is visible (nothing extends below, so the labels stay level) */
.slotcard.cmdstack { overflow: visible; z-index: 0; }
.slotcard.cmdstack > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top center; z-index: 1; border-radius: 5px; } /* exactly the pile's size, with the bottom of the card cut off, so it can't spill over the label below */
.cmdghost { position: absolute; inset: 0; z-index: 0; border-radius: 5px; overflow: hidden; background: #000; box-shadow: 0 2px 8px #0008; outline: 1px solid #ffffff30;
  transform: translateY(calc(var(--k) * -12px)); }
.cmdghost img { width: 100%; height: 100%; display: block; }
.slotcard.empty { background: #00000030; border: 1px dashed #ffffff30; box-shadow: none; }
.slotcard.back { background: url(/cardback.jpg) center / cover; border: 0; }
/* a quick riffle when a library is shuffled (yours or anyone else's) */
.slotcard.shufflefx { animation: shufflefx .5s ease; }
@keyframes shufflefx {
  0%, 100% { transform: none; filter: brightness(1); }
  20% { transform: translateX(-4%) rotate(-6deg); filter: brightness(1.25); }
  40% { transform: translateX(4%) rotate(5deg); }
  60% { transform: translateX(-3%) rotate(-3deg); filter: brightness(1.15); }
  80% { transform: translateX(2%) rotate(2deg); }
}

/* action buttons: bottom-left, in the same band as your name/life bar */
/* the play buttons live in the top bar, set apart from the menu buttons on the right by a divider */
#actions { display: flex; gap: 6px; align-items: center; flex-wrap: nowrap; }
.hsep { align-self: stretch; width: 1px; margin: 3px 6px; background: #ffffff26; }
#actions button { padding: 4px 10px; font-size: 13px; white-space: nowrap; }
#actions button:disabled { opacity: .45; cursor: not-allowed; }
#actions #btnPass { font-weight: 700; }
#actions kbd.hk { margin-left: 6px; }
@media (max-width: 1300px) { #topbar { flex-wrap: wrap; row-gap: 4px; } } /* narrow windows: the top bar wraps onto a second line instead of dropping the key hints */
@media (max-width: 1150px) { #clock { display: none; } }

.card { width: var(--cw); height: var(--ch); border-radius: 6px; position: relative; flex: none; user-select: none; background: #000; }
.card img { width: 100%; height: 100%; border-radius: 6px; display: block; pointer-events: none; }
/* On the battlefield, the image (or a blank token's name/P-T) and the stack's ghost layers sit in this inner wrapper, which is
   the thing that actually turns sideways when tapped. Everything else appended straight to .card afterward — the stack count,
   counters, notes, tags — stays upright and in place instead of swinging around with the card (#79). Off the battlefield cards
   are never tapped, so cardEl() skips the wrapper there and these rules never match. */
.cardface { width: 100%; height: 100%; position: relative; border-radius: 6px; }
/* .card itself never rotates, so anything painted on its own static box — background, drop shadow — would sit behind a
   rotated .cardface as an upright square the rotated face no longer covers, showing as a black box around a tapped card.
   Once a card has a .cardface, the face (image or blank-token box, see below) draws the background and shadow instead,
   and .card itself is left bare so only the rotated shape shows. */
.card:has(> .cardface) { background: none; }
.lane .card:has(> .cardface) { box-shadow: none; }
.lane .card .cardface { box-shadow: 0 3px 10px #0009; }
/* tapping is a quarter turn; "Rotate 90°" in the card menu adds its own turns (--rot) on top, tapped or not */
.cardface.tapped { transform: rotate(calc(90deg + var(--rot, 0deg))); }
.cardface.rot:not(.tapped) { transform: rotate(var(--rot, 0deg)); }
/* turning a card sideways (tap) and back (untap), smoothly */
.cardface.tap-on { animation: tapOn .25s cubic-bezier(.3, .7, .3, 1); }
.cardface.tap-off { animation: tapOff .25s cubic-bezier(.3, .7, .3, 1); }
@keyframes tapOn { from { transform: rotate(var(--rot, 0deg)); } to { transform: rotate(calc(90deg + var(--rot, 0deg))); } }
@keyframes tapOff { from { transform: rotate(calc(90deg + var(--rot, 0deg))); } to { transform: rotate(var(--rot, 0deg)); } }
@media (prefers-reduced-motion: reduce) { .cardface.tap-on, .cardface.tap-off { animation: none; } }
.card.back { background: url(/cardback.jpg) center / cover; border: 0; }
/* tapped/rot on the "back" (hidden-card) variant: it has no .cardface wrapper (it's a plain background, no face to turn separately) */
.card.back.tapped { transform: rotate(calc(90deg + var(--rot, 0deg))); }
.card.back.rot:not(.tapped) { transform: rotate(var(--rot, 0deg)); }
/* a blank token has no card image, so it gets a generic token graphic instead of a flat color (#83); the name/P-T text sits
   on top, with a shadow so it stays readable over the artwork */
.card.blank { background: #2b3040 url(/token.svg) center / cover; border: 2px solid #777; padding: 6px; font-size: 12px; text-align: center; display: flex; flex-direction: column; justify-content: space-between; text-shadow: 0 1px 3px #000, 0 1px 3px #000; }
/* on the battlefield the blank token's box lives on .cardface (so it tapes/rotates as one piece with its text, not as a static
   square with the text spinning inside it); off the battlefield there's no .cardface wrapper, so .card.blank above still applies */
.card.blank .cardface { background: #2b3040 url(/token.svg) center / cover; border: 2px solid #777; box-sizing: border-box; padding: 6px; display: flex; flex-direction: column; justify-content: space-between; }
.card.blank:has(.cardface) { background: none; border: 0; padding: 0; }
.card.fd img { opacity: .5; }
.card.revealed { box-shadow: 0 0 0 2px gold; }
/* new in your hand: stays lit until you hover it. just played on the table: a glow that pulses a few times, then fades over 5 seconds (--pe = how far into it a redraw is) */
#hand .card.fresh { outline: 3px solid #ffd479; outline-offset: 1px; filter: drop-shadow(0 0 8px #ffd479); }
.card.played { animation: playedFx 5s ease-out both; animation-delay: calc(var(--pe, 0ms) * -1); }
@keyframes playedFx { 0%, 20%, 40% { outline: 3px solid #5be3ff; outline-offset: 1px; box-shadow: 0 0 20px 7px #5be3ffdd; } 10%, 30% { outline: 3px solid #5be3ff88; outline-offset: 1px; box-shadow: 0 0 6px 1px #5be3ff66; } 60% { outline: 3px solid #5be3ffaa; outline-offset: 1px; box-shadow: 0 0 12px 3px #5be3ff88; } 100% { outline: 3px solid #5be3ff00; outline-offset: 1px; box-shadow: 0 0 0 0 #5be3ff00; } }
.lane .card { position: absolute; cursor: grab; box-shadow: 0 3px 10px #0009; pointer-events: auto; }
/* counters and keyword markers: top-left, in the upper third of the card */
/* a stack of identical cards: layered edges behind the card plus a count badge beside it */
.lane .card.stack { isolation: isolate; }
.stackghost { position: absolute; inset: 0; z-index: -1; border-radius: 6px; background: #000 center / cover; outline: 1px solid #4a5578; pointer-events: none;
  transform: translate(calc(var(--k) * 6px), calc(var(--k) * 6px)); }
.stackghost.tapped { transform: translate(calc(var(--k) * 8px), calc(var(--k) * 4px)) rotate(90deg); }
/* when every card is tapped the top card is rotated, and the layers inherit that rotation: already sideways, offset in its rotated frame */
.cardface.tapped .stackghost.tapped { transform: translate(calc(var(--k) * 6px), calc(var(--k) * -6px)); }
/* a quiet label under the stack: small, semi-transparent, no bright fill */
.stackcount { position: absolute; left: 50%; top: calc(100% + 3px); transform: translateX(-50%); z-index: 4; padding: 0 7px; text-align: center; white-space: nowrap; pointer-events: none;
  background: #0b0e14b3; color: #ffffffb8; font-weight: 600; font-size: 11px; line-height: 16px; border-radius: 8px; border: 1px solid #ffffff1f; }
/* while dragging: the card you're about to stack onto / attach to lights up with an overlay (drag away to cancel) */
.lane .card.drop-stack, .lane .card.drop-attach { outline: 3px solid #ffd479; outline-offset: 2px; z-index: 40; }
.lane .card.drop-attach { outline-color: #b9a3ff; }
.lane .card.drop-stack::after, .lane .card.drop-attach::after { content: attr(data-hint); position: absolute; inset: 0; display: grid; place-items: center; padding: 6px; text-align: center;
  font-weight: 900; font-size: 15px; color: #fff; background: #000b; border-radius: 6px; text-shadow: 0 2px 6px #000; pointer-events: none; }/* an attachment (aura, equipment…) is tucked behind its host so its name bar stays visible */
.lane .card.attached { outline: 2px solid #b9a3ff; outline-offset: -1px; }
/* "Attach to…" pick mode: every battlefield card is a target */
body.picking .lane .card { cursor: crosshair; outline: 2px dashed #ffd479; outline-offset: -2px; }
.badges { position: absolute; left: 3px; top: 9%; display: flex; flex-direction: column; gap: 2px; pointer-events: none; z-index: 2; }
.badge { background: #000c; color: #fff; font-size: 11px; font-weight: 700; padding: 1px 5px; border-radius: 8px; width: max-content; }
.tag { position: absolute; top: 2px; right: 2px; background: #000b; font-size: 10px; padding: 1px 4px; border-radius: 4px; pointer-events: none; }
.tag.assigntag { top: auto; right: auto; left: 2px; bottom: 2px; max-width: calc(100% - 4px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; background: color-mix(in srgb, var(--pc, #888) 55%, #000c); border: 1px solid var(--pc, #888); color: #fff; font-weight: 700; }

/* fanned hand along the bottom edge */
#handbar { position: absolute; bottom: 0; left: 20px; right: calc(2.5% + max(32%, 380px) + 12px); height: calc(var(--hch) * .78); display: flex; justify-content: flex-start; align-items: flex-end; z-index: 10; }
#handbar.drop { background: #5b8def22; }
#handlabel { position: absolute; left: -12px; /* the hand bar starts 20px in; this puts the text at the same x as the lane labels (8px) */ top: 4px; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: #ffffff2e; pointer-events: none; }
#hand { display: flex; align-items: flex-end; }
#hand .card { width: var(--hcw); height: var(--hch); cursor: grab; margin-left: 8px; transform: translateY(10%); transition: transform .12s; box-shadow: 0 4px 12px #000a; }
#hand .card:first-child { margin-left: 0; }
#hand.n2 .card:not(:first-child) { margin-left: calc(var(--hcw) * -.32); }
#hand.n3 .card:not(:first-child) { margin-left: calc(var(--hcw) * -.48); }
#hand.n4 .card:not(:first-child) { margin-left: calc(var(--hcw) * -.62); }
#hand .card:hover { transform: translateY(-14%) scale(1.1); z-index: 30; }

/* keyboard shortcuts panel */
.keys { overflow-y: auto; display: grid; grid-template-columns: 1fr 1fr; gap: 2px 28px; align-content: start; }
.keys h3 { grid-column: 1 / -1; margin: 12px 0 4px; font-size: 12px; text-transform: uppercase; letter-spacing: .1em; color: var(--muted); }
.keyrow { display: flex; align-items: center; gap: 10px; padding: 3px 0; }
.keyrow span { color: #c9cddb; }
kbd { flex: none; min-width: 34px; text-align: center; padding: 2px 8px; border-radius: 5px; background: #0f1116; border: 1px solid #4a5068; border-bottom-width: 3px; font: 600 12px ui-monospace, monospace; color: #fff; white-space: nowrap; }
@media (max-width: 700px) { .keys { grid-template-columns: 1fr; } }

/* each player's board is tinted with their own colour so it's obvious whose side is whose */
.seat { background: color-mix(in srgb, var(--pc, #888) 9%, transparent); }
.seat + .seat { border-left-color: color-mix(in srgb, var(--pc, #888) 55%, transparent); }
.lane.lands { background: color-mix(in srgb, var(--pc, #888) 15%, #00000030); }
.opp .lane.lands, .me .lane.lands { border-color: #ffffff12; }
.slotcard.empty { border-color: color-mix(in srgb, var(--pc, #888) 45%, transparent); }
/* game type: picker in the New game dialog, tag in the top bar, filter on the Stats screen */
.formatpick { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.fmtcard { display: grid; gap: 6px; text-align: left; padding: 20px 18px; border-radius: 16px; border: 1px solid #ffffff1c; background: #ffffff0b; color: #fff; cursor: pointer; transition: transform .08s, border-color .15s, background .15s; }
.fmtcard:hover { background: #5b8def22; border-color: #5b8def; transform: translateY(-2px); }
.fmtcard b { font-size: 22px; }
.fmtcard small { color: #ffffffa8; font-size: 13.5px; line-height: 1.4; }
@media (max-width: 600px) { .formatpick { grid-template-columns: 1fr; } }
/* the game type is plain text after the room pill, led by a centred dot */
.fmttag { margin-left: -2px; color: inherit; font-size: inherit; font-weight: 400; }
.fmttag:not(:empty)::before { content: '·'; margin-right: 8px; opacity: .7; }
.statfilter { grid-template-columns: repeat(3, 1fr); }
/* monarch / initiative card: to the right of the holder's board, before the piles */
.seat.hasdesig { grid-template-columns: 1fr auto auto; }
.desig { display: flex; flex-direction: column; justify-content: center; gap: 8px; padding: 8px 4px; }
.me .desig { justify-content: flex-end; }
.desigcard { width: calc(var(--cw) * .8); cursor: pointer; border-radius: 6px; }
.desigcard img { width: 100%; display: block; border-radius: 5px; box-shadow: 0 0 0 2px #ffd479, 0 4px 14px #000a; }
.desigcard:hover img { box-shadow: 0 0 0 2px #fff, 0 6px 18px #000c; }
.desigfallback { aspect-ratio: 5 / 7; display: grid; place-content: center; text-align: center; gap: 4px; font-size: 26px; color: #ffd479; border-radius: 6px; background: #2a2413; box-shadow: 0 0 0 2px #ffd479; }
.desigfallback b { font-size: 12px; }
.desiglabel { font-size: 10.5px; text-align: center; color: #ffd479; text-transform: uppercase; letter-spacing: .08em; margin-top: 3px; }
/* stat tracker */
#clock { color: #cfd6ea; font-variant-numeric: tabular-nums; font-size: 13px; }
table.stbl { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.stbl th { color: var(--muted); font-size: 11.5px; text-transform: uppercase; letter-spacing: .07em; text-align: left; padding: 7px 10px; white-space: nowrap; }
table.stbl td { padding: 9px 10px; border-top: 1px solid #ffffff12; white-space: nowrap; }
table.stbl th:nth-child(n+3), table.stbl td:nth-child(n+3) { text-align: center; }
.statgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 10px; }
.statcard { display: grid; gap: 3px; padding: 14px 14px 12px; border-radius: 14px; background: #ffffff0a; border: 1px solid #ffffff12; }
.statcard b { font-size: 26px; font-weight: 800; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.statcard span { color: var(--muted); font-size: 12.5px; }
#statsBody h3 { margin: 22px 0 8px; font-size: 15px; letter-spacing: .04em; color: #c9cee0; }
.res { display: inline-block; min-width: 54px; text-align: center; padding: 3px 10px; border-radius: 10px; font-size: 12px; font-weight: 800; letter-spacing: .04em; }
.res.won { background: #1f6f43; color: #eafff3; }
.res.lost { background: #8c1d2e; color: #ffe9ec; }
.res.ended { background: #3a4156; color: #dfe3ee; }
.matches { display: grid; gap: 8px; }
.match { border-radius: 14px; background: #ffffff08; border: 1px solid #ffffff10; overflow: hidden; }
.matchrow { display: grid; grid-template-columns: auto 1fr auto; gap: 14px; align-items: center; padding: 12px 16px; cursor: pointer; }
.matchrow:hover, .matchrow.open { background: #ffffff0d; }
.minfo { display: grid; gap: 2px; min-width: 0; }
.minfo b { font-size: 15px; }
.minfo small, .mmeta small { color: var(--muted); font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mmeta { display: grid; gap: 2px; text-align: right; font-size: 13.5px; }
.mtimerow { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
.medit { padding: 0 5px; font-size: 12px; line-height: 18px; color: var(--muted); background: transparent; border-color: transparent; }
.medit:hover { color: #fff; background: #ffffff1a; border-color: #ffffff33; }
.matchdetail { padding: 4px 12px 12px; border-top: 1px solid #ffffff10; }
/* dice roll overlay */
/* (positioned over the roller's battlefield by showDice: --dsz is the die size that fits it) */
#dice { position: absolute; inset: 0; z-index: 70; display: grid; place-items: center; overflow: hidden; cursor: pointer; --dsz: min(44vh, 70vw); background: radial-gradient(circle at 50% 45%, #0d1220d0, #05070cee); animation: dicefade .2s ease-out; }
@keyframes dicefade { from { opacity: 0; } to { opacity: 1; } }
.dicebox { display: grid; justify-items: center; gap: 14px; animation: tumble .9s cubic-bezier(.2, .9, .25, 1); }
@keyframes tumble { 0% { transform: translateY(-40vh) rotate(-540deg) scale(.4); opacity: 0; } 70% { opacity: 1; } 100% { transform: none; } }
.die { position: relative; width: var(--dsz); aspect-ratio: 1; }
.die svg { width: 100%; height: 100%; overflow: visible; fill: #182036; stroke: var(--pc, #fff); stroke-width: 3.2; stroke-linejoin: round; filter: drop-shadow(0 16px 40px #000c) drop-shadow(0 0 22px color-mix(in srgb, var(--pc, #fff) 45%, transparent)); }
.die svg .facet { fill: none; stroke: color-mix(in srgb, var(--pc, #fff) 55%, transparent); stroke-width: 1.4; }
.dnum { position: absolute; inset: 0; display: grid; place-items: center; font-size: calc(var(--dsz) * .34); font-weight: 900; color: #fff; text-shadow: 0 4px 18px #000a; font-variant-numeric: tabular-nums; }
.dnum.word { font-size: calc(var(--dsz) * .18); letter-spacing: .06em; }
#dice.done .dnum { animation: dicepop .35s cubic-bezier(.2, 1.6, .4, 1); }
@keyframes dicepop { from { transform: scale(.6); } to { transform: none; } }
.dwho { font-size: clamp(15px, calc(var(--dsz) * .08), 30px); font-weight: 800; color: var(--pc, #fff); letter-spacing: .03em; }
.dnote { min-height: 1.4em; font-size: clamp(14px, calc(var(--dsz) * .07), 26px); font-weight: 900; letter-spacing: .08em; text-transform: uppercase; }
.dnote.crit { color: #ffd479; text-shadow: 0 0 20px #ffb300; }
.dnote.fail { color: #ff8a8a; }
.dhint { color: #ffffff70; font-size: 13px; }
.dicepick { display: flex; flex-wrap: wrap; gap: 10px; }
.dicepick button { min-width: 84px; padding: 16px 18px; font-size: 20px; font-weight: 800; border-radius: 12px; }
/* game over: defeat prompt and victory screen (centred on the battlefield, not the whole window) */
#endgame { position: absolute; inset: 0; z-index: 65; display: grid; place-items: center; padding: 16px; overflow: auto; background: radial-gradient(circle at 50% 45%, #0a0f1cc0, #04060bee); animation: dicefade .2s ease-out; }
#endgame.victory { z-index: 80; cursor: pointer; }
.endbox { position: relative; z-index: 2; width: min(720px, 100%); display: grid; justify-items: center; gap: 12px; text-align: center; padding: 26px 26px 22px; border-radius: 20px;
  background: #141a29f0; border: 2px solid color-mix(in srgb, var(--pc) 70%, #000); box-shadow: 0 24px 80px #000c, 0 0 60px color-mix(in srgb, var(--pc) 30%, transparent); animation: tumble .7s cubic-bezier(.2, .9, .25, 1); }
.endbox h1 { margin: 0; font-size: clamp(34px, 7vh, 64px); font-weight: 900; color: var(--pc); letter-spacing: -.01em; }
.endbox h2 { margin: 0; font-size: 24px; color: #fff; }
.endsub { color: #c6cbda; font-size: 17px; }
.congrats { font-size: 15px; font-weight: 800; letter-spacing: .3em; text-transform: uppercase; color: #ffd479; }
.endbtns { justify-content: center; gap: 12px; margin-top: 4px; }
.endbtns button { padding: 13px 22px; font-size: 16px; font-weight: 700; border-radius: 12px; }
.trophy svg { width: clamp(70px, 14vh, 130px); fill: #ffd479; stroke: #b8860b; stroke-width: 2; stroke-linejoin: round; filter: drop-shadow(0 6px 20px #ffb300aa); animation: dicepop .6s cubic-bezier(.2, 1.6, .4, 1) .3s both; }
.trophy svg .h { fill: none; stroke: #ffd479; stroke-width: 5; stroke-linecap: round; }
table.results { width: 100%; border-collapse: collapse; margin-top: 4px; font-size: 15px; }
table.results th { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .08em; font-weight: 700; padding: 6px 10px; text-align: left; }
table.results td { padding: 9px 10px; text-align: left; border-top: 1px solid #ffffff14; }
table.results th:nth-child(n+3), table.results td:nth-child(n+3) { text-align: center; }
table.results tr.winner td { background: #ffd47914; font-weight: 700; }
table.results tr.defeated td { color: #b0b5c6; }
table.results td.bad { color: #ff8a8a; font-weight: 800; }
.confetti { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 1; }
.confetti i { position: absolute; top: -20px; width: 10px; height: 16px; border-radius: 2px; opacity: .95; animation: confetti linear infinite; }
@keyframes confetti { to { transform: translateY(110vh) rotate(720deg); } }
.seat.out { filter: grayscale(.9) brightness(.7); }
/* other players' pointers */
#cursors { position: absolute; inset: 0; pointer-events: none; z-index: 50; overflow: hidden; }
.cursor { position: absolute; transition: left .05s linear, top .05s linear, opacity .4s; }
.cursor i { display: block; width: 16px; height: 22px; background: var(--pc); filter: drop-shadow(0 1px 2px #000c);
  clip-path: polygon(0 0, 0 100%, 30% 78%, 52% 100%, 68% 92%, 46% 70%, 80% 70%); }
.cursor span { position: absolute; left: 14px; top: 16px; background: var(--pc); color: #111; font-size: 11px; font-weight: 700; padding: 1px 6px; border-radius: 8px; white-space: nowrap; }
.cursor.idle { opacity: .3; }

/* collapsible game log */
#logpanel { position: relative; width: var(--logw, 270px); flex: none; display: flex; flex-direction: column; background: #0b0e14; border-left: 1px solid #ffffff14; overflow: hidden; transition: width .15s; }
#logpanel > :not(#logresize) { min-width: var(--logw, 270px); }
/* drag handle on the log's left edge */
#logresize { position: absolute; left: 0; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 5; }
#logresize:hover, body.resizing #logresize { background: #5b8def66; }
body.resizing { cursor: col-resize; user-select: none; }
body.resizing #logpanel { transition: none; }
#logpanel.collapsed { width: 0; border-left: 0; }
#loghead { display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
#log { flex: 1; overflow-y: auto; padding: 0 8px 8px; font-size: 12.5px; color: #c4c8d4; }

/* collapsible private notes, same mechanics as the log panel - never sent to the server */
#notespanel { position: relative; width: var(--notesw, 270px); flex: none; display: flex; flex-direction: column; background: #0b0e14; border-left: 1px solid #ffffff14; overflow: hidden; transition: width .15s; }
#notespanel > :not(#notesresize) { min-width: var(--notesw, 270px); }
#notesresize { position: absolute; left: 0; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 5; }
#notesresize:hover, body.resizing #notesresize { background: #5b8def66; }
body.resizing #notespanel { transition: none; }
#notespanel.collapsed { width: 0; border-left: 0; }
#noteshead { display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
#notestools { display: flex; gap: 4px; padding: 0 8px 6px; }
#notestools button { width: 26px; height: 24px; padding: 0; display: flex; align-items: center; justify-content: center; font-size: 12.5px; }
#notestools button svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
#notestools button.active { background: var(--accent); border-color: var(--accent); }
#notesText { flex: 1; overflow-y: auto; border: 0; border-top: 1px solid #ffffff14; background: #0b0e14; color: #e6e8ee; padding: 8px; font-size: 12.5px; font-family: inherit; line-height: 1.5; }
#notesText:focus { outline: none; background: #10141d; }
#notesText:empty::before { content: attr(data-placeholder); color: var(--muted); }
#notesText ul { margin: 0; padding-left: 1.3em; }

/* collapsible chat, same mechanics as the log panel */
#chatpanel { position: relative; width: var(--chatw, 270px); flex: none; display: flex; flex-direction: column; background: #0b0e14; border-left: 1px solid #ffffff14; overflow: hidden; transition: width .15s; }
#chatpanel > :not(#chatresize) { min-width: var(--chatw, 270px); }
#chatresize { position: absolute; left: 0; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 5; }
#chatresize:hover, body.resizing #chatresize { background: #5b8def66; }
body.resizing #chatpanel { transition: none; }
#chatpanel.collapsed { width: 0; border-left: 0; }
#chathead { display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
#chatlog { flex: 1; overflow-y: auto; padding: 0 8px 8px; font-size: 12.5px; color: #c4c8d4; display: flex; flex-direction: column; gap: 4px; }
.chatmsg .who { font-weight: 700; }
.chatmsg.pub { color: #7be08a; }
.chatmsg.whisper { color: #c9a4ff; }
.chatmsg.secret { opacity: .75; font-style: italic; }
#chatForm { display: flex; gap: 4px; padding: 6px 8px; border-top: 1px solid #ffffff14; }
#chatTo { flex: none; max-width: 90px; background: #171b26; color: #c4c8d4; border: 1px solid #ffffff1f; border-radius: 6px; font-size: 11.5px; }
#chatText { flex: 1; min-width: 0; background: #171b26; color: #e6e8ee; border: 1px solid #ffffff1f; border-radius: 6px; padding: 4px 6px; font-size: 12.5px; }
/* formatted log lines.
   Colour is used for exactly one thing per channel so nothing collides:
   - PLAYER identity = bold coloured TEXT + the coloured stripe on the left (nothing else on the line is coloured text)
   - ACTIONS = filled pills with light text (a red "damage" pill can't be mistaken for a red player name)
   - ZONES = low-saturation chips, NUMBERS/CARDS = neutral white/cream */
.logline { padding: 3px 7px; margin: 2px 0; line-height: 1.75; border-left: 3px solid var(--pc, #ffffff22); background: #ffffff08; border-radius: 0 5px 5px 0; overflow-wrap: anywhere; color: #d5d9e4; }
.logline .who { font-weight: 800; color: var(--pc); }
.logline .cardname { color: #f3ead0; font-style: italic; font-weight: 600; }
.logline .arrow { color: #8b90a0; padding: 0 1px; }
.logline .t-num { color: #fff; font-weight: 800; }
.logline .pill, .logline .zone, .logline [class^="t-"]:not(.t-num) { display: inline-block; padding: 0 7px; border-radius: 9px; font-size: 11.5px; font-weight: 700; line-height: 1.5; letter-spacing: .02em; vertical-align: 1px; }
.logline .t-good   { background: #1f6f43; color: #eafff3; }   /* gain: draw, create, join     */
.logline .t-act    { background: #2c3f5e; color: #dbe8ff; }   /* neutral action: move, reveal */
.logline .t-dmg    { background: #8c1d2e; color: #ffe9ec; }   /* harm: takes, loses, mills    */
.logline .t-alert  { background: #8a5a00; color: #fff2d1; }   /* game-level: restart, end     */
.logline .t-poison { background: #4b5a1f; color: #f0f7d2; }
.logline .t-mana   { background: #3b3556; color: #efe9ff; }   /* "for mana" */
.logline .life-dn  { background: #8c1d2e; color: #ffe9ec; }
.logline .life-up  { background: #1f6f43; color: #eafff3; }
.logline .zone { color: #e7ebf3; }
.zone.z-hand { background: #2f3f57; } .zone.z-bf { background: #2f4a3c; } .zone.z-gy { background: #3f3552; }
.zone.z-ex { background: #55402c; } .zone.z-lib { background: #4d4636; } .zone.z-cmd { background: #55492a; }.logline.turnline { margin: 10px 0 6px; padding: 5px 8px; text-align: center; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; font-size: 12px; color: var(--pc);
  background: color-mix(in srgb, var(--pc) 16%, transparent); border: 0; border-top: 1px solid var(--pc); border-bottom: 1px solid var(--pc); border-radius: 4px; }
#hover { position: fixed; z-index: 60; pointer-events: none; border-radius: 4.5% / 3.2%; box-shadow: 0 8px 30px #000c; background: #000; }
#modal { position: fixed; inset: 0; background: #000a; display: grid; place-items: center; z-index: 50; transition: background .15s; }
/* while dragging the card-size slider in Settings: hide everything else (dimmer included) so the table is visible, but the
   slider itself (.zoomsec, a sibling of the other sections, not a descendant of anything faded - opacity can't be un-faded by a
   descendant once an ancestor is faded) stays fully visible and usable */
#modal.peek { background: transparent; pointer-events: none; }
#modal.peek #modalBox { background: transparent; border-color: transparent; box-shadow: none; }
#modal.peek #modalBox > *:not(.zoomsec) { opacity: 0; }
#modal.peek #modalBox > .zoomsec { pointer-events: auto; }
#modalBox, #modalBox > * { transition: opacity .12s, background .12s, border-color .12s; }
#modalBox { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; width: min(900px, 94vw); max-height: 88vh; display: flex; flex-direction: column; padding: 14px; gap: 10px; }
#modalBox h2 { margin: 0; display: flex; justify-content: space-between; align-items: center; font-size: 17px; }
#modalBox textarea { width: 100%; height: 300px; background: #0f1116; color: var(--text); border: 1px solid var(--line); border-radius: 5px; padding: 8px; font: 13px monospace; }
.grid { display: flex; flex-wrap: wrap; gap: 8px; overflow-y: auto; padding: 4px; }
.grid .card { cursor: pointer; }
.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

#menu, #submenu { position: fixed; z-index: 100; background: #262a37; border: 1px solid #4a5068; border-radius: 6px; padding: 4px; min-width: 190px; box-shadow: 0 6px 20px #000a; max-height: 90vh; overflow-y: auto; }
#submenu { z-index: 101; min-width: 210px; overflow: visible; }
/* only real items (.mi) highlight, one at a time */
.mi { padding: 5px 10px; cursor: pointer; border-radius: 4px; white-space: nowrap; user-select: none; }
.mi:hover { background: var(--accent); }
.mi:has(> .hk) { display: flex; justify-content: space-between; align-items: center; gap: 18px; }
kbd.hk { margin-left: 8px; padding: 0 5px; border: 1px solid #ffffff40; border-bottom-width: 2px; border-radius: 4px; background: #ffffff14; color: #ffffffb0; font: 600 10px/16px inherit; font-family: inherit; letter-spacing: .04em; }
.mi:hover kbd.hk { color: #fff; }
.mi.sub { display: flex; justify-content: space-between; gap: 18px; }
.mi.sub .arrow { opacity: .7; }
.mi.custom { color: #ffd479; }
.mi.custom:hover { color: #fff; }
.mi.active { display: flex; justify-content: space-between; align-items: center; gap: 14px; background: #2f4a34; }
.mi.active:hover { background: #a03a3a; } /* hovering an applied item shows that a click will remove it */
.mi.active .plus { padding: 0 8px; line-height: 18px; }
.mi.active.counter { cursor: default; }
.mi.active.counter:hover { background: #2f4a34; }
.mi.active .stepper { display: inline-flex; gap: 4px; }
.mi.active .stepper button { width: 24px; padding: 0; line-height: 18px; font-weight: 800; }
.mi.active .stepper .minus:hover { background: #a03a3a; }
.mi.active .stepper .plus:hover { background: #2e7d4a; }
/* round number buttons, the same shape as the life − / + */
#submenu .roundrow { display: flex; gap: 6px; padding: 4px; }
#submenu .roundbtn { border-radius: 50%; width: 26px; height: 26px; padding: 0; font-weight: 700; }
#submenu .roundbtn:hover { background: var(--accent); border-color: var(--accent); }
#submenu .ptrow { display: flex; align-items: center; gap: 5px; padding: 2px 2px 6px; }
#submenu .ptlabel { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-right: 2px; white-space: nowrap; }
#submenu .ptin { width: 46px; padding: 3px 4px; text-align: center; }
#submenu .msearch { width: 100%; margin-bottom: 4px; }
#submenu .plist { max-height: min(340px, 60vh); overflow-y: auto; }
#submenu .ghead { padding: 6px 10px 2px; font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); user-select: none; }label.pm { display: grid; gap: 6px; }
label.pm input { width: 100%; }
#menu hr { border: 0; border-top: 1px solid #4a5068; margin: 3px 0; }

@media (max-width: 800px) { #logpanel, #notespanel { display: none; } }

/* YOUR side of the table, laid out like the sketch (percentages of your half of the screen):
   Permanents fill the whole area; Lands are a box in the bottom-left corner; your hand fans out along the bottom, between Lands and the
   piles; Library / Graveyard / Command / Exile sit in a row on the right, with your status bar tucked under them. */
.seat.me { display: block; }
.seat.me .bf { display: contents; }
/* paints above the piles/lands chrome (so a card near the edge is never hidden behind them) without stealing their clicks/drops:
   the lane itself is pointer-events:none (cards re-enable it on themselves); its own drop handling lives on the seat (see app.js) */
.seat.me .lane.main { position: absolute; inset: 0; z-index: 9; pointer-events: none; }
.seat.me .lane.main .lane-label { top: 4px; bottom: auto; }
.seat.me .lane.lands { position: absolute; left: 0; bottom: 0; width: calc(100% - 2.5% - max(32%, 380px) - 8px); height: calc(var(--chb) * .7 + 44px); z-index: 2; flex: none; border: 1px solid #ffffff1f; border-left: 0; border-bottom: 0; }
.seat.me .piles { position: absolute; right: 2.5%; left: auto; width: max(32%, 380px); bottom: 122px; z-index: 3; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: flex-end; align-content: normal; justify-content: center; gap: 8px; padding: 0; }
.seat.me .piles .slot { grid-area: auto; flex: none; width: calc(var(--cw) * .8); } /* a fixed size (it follows the card size, not the window width), so the piles never squish as the window gets wider */
.seat.me .piles .slot[data-zone="library"] { order: 1; }
.seat.me .piles .slot[data-zone="graveyard"] { order: 2; }
.seat.me .piles .slot[data-zone="command"] { order: 3; }
.seat.me .piles .slot[data-zone="exile"] { order: 4; }
.seat.me .desig { position: absolute; right: 2.5%; top: 8px; z-index: 3; flex-direction: row; padding: 0; }
/* nothing on a status bar can spill out of it, however narrow it gets: the three columns shrink, names and chips get ellipses,
   and the right column keeps clear of the rounded corners */
.side > * { min-width: 0; }
.side .pinfo { max-width: 100%; }
.side .pname, .side .ptime, .side .turnbadge { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side .pcs { padding: 5px 6px 5px 0; box-sizing: border-box; max-width: 100%; }
.side .lifecol { max-width: 100%; }
.side .dmgrow { flex-wrap: nowrap; max-width: 100%; }
.side .dmgrow .pc { min-width: 0; padding-left: 6px; padding-right: 6px; }
/* opponents mirror your own layout, flipped top to bottom: bar top-right, zones just under it, lands along the top edge, permanents fill the rest */
.seat.opp { display: block; }
.seat.opp .bf { display: contents; }
.seat.opp .lane.main { position: absolute; inset: 0; z-index: 9; pointer-events: none; }
.seat.opp .lane.main .lane-label { top: auto; bottom: 4px; }
.seat.opp .lane.lands { position: absolute; left: 0; top: 0; width: calc(100% - 2.5% - max(32%, 380px) - 8px); height: calc(var(--chb) * var(--os, .8) * .7 + 44px); z-index: 2; flex: none; border: 1px solid #ffffff1f; border-left: 0; border-top: 0; }
.seat.opp .lane.lands .lane-label { top: 4px; bottom: auto; }
.seat.opp .side { position: absolute; right: 2.5%; left: auto; top: 6px; margin: 0; width: max(32%, 380px); max-width: none; transform: none; }
.seat.opp .piles { position: absolute; right: 2.5%; left: auto; width: max(32%, 380px); top: 106px; z-index: 3; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: flex-start; align-content: normal; justify-content: center; gap: 8px; padding: 0; }
.seat.opp .piles .slot { grid-area: auto; flex: none; width: calc(var(--cw) * .8); }
.seat.opp .piles .slot[data-zone="library"] { order: 1; }
.seat.opp .piles .slot[data-zone="graveyard"] { order: 2; }
.seat.opp .piles .slot[data-zone="command"] { order: 3; }
.seat.opp .piles .slot[data-zone="exile"] { order: 4; }
.seat.opp .desig { position: absolute; right: 2.5%; bottom: 8px; z-index: 3; flex-direction: row; padding: 0; }
/* centred in the same gap as your own hand (between the lands box and their status bar), not pinned to the left edge */
.seat.opp .opphand { position: absolute; left: calc(33.33% + 12px); right: calc(2.5% + max(32%, 380px) + 12px); top: 50px; margin: 0; z-index: 7;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; }

/* more than three statuses: a second column (filled top to bottom), packed tight so the name and time on the left keep their room */
.side:has(.pcs.two) { gap: 4px 8px; }
.side .pcs.two { display: grid; grid-template-rows: repeat(3, auto); grid-auto-flow: column; grid-auto-columns: max-content; justify-content: end; justify-items: end; align-content: center; gap: 2px 3px; min-width: 0; }
.side .pcs.two .pc { font-size: 10px; padding: 0 5px; max-width: 78px; }
.side .pcs.two .morewrap { justify-self: end; }

/* lands are just the first third of the width; the hand sits low, like a card game hand: cards peek up from the bottom edge and rise when hovered */
.seat.me .lane.lands { width: 33.33%; }
.seat.opp .lane.lands { width: 33.33%; }
#hand .card { transform: translateY(42%); }
#hand .card:hover { transform: translateY(-4%) scale(1.1); }

/* the hand is centred in its space and its cards always overlap (a fan you can hover to lift a card) */
#handbar { justify-content: center; }
#hand .card:not(:first-child), #hand.n2 .card:not(:first-child), #hand.n3 .card:not(:first-child), #hand.n4 .card:not(:first-child) { margin-left: calc(var(--hcw) * -.55); }
#hand .card { flex: none; }

/* the hand goes in the empty bottom space between the lands strip and your status bar */
#handbar { left: calc(33.33% + 12px); }

/* the "Your hand · N" label is centred above the hand */
#handlabel { left: 50%; transform: translateX(-50%); white-space: nowrap; }

/* hovering the hand enlarges the whole hand 3x, growing up from the bottom edge so every card is fully readable */
#hand { transform-origin: 50% 100%; transition: transform .18s ease-out; }
#hand:hover { transform: scale(3); z-index: 40; }
#hand:hover .card { transform: none; }
#hand:hover .card:hover { transform: translateY(-4%); }
#handbar:has(#hand:hover) #handlabel { opacity: 0; }

/* land cards show only their lower ~60%: the top of each card is cut off, so the lands strip is shorter */
.lane.lands { --cw: calc(var(--chb) * .7 * .7143); --ch: calc(var(--chb) * .7 * .6); }
.opp .lane.lands { --cw: calc(var(--chb) * var(--os, .8) * .7 * .7143); --ch: calc(var(--chb) * var(--os, .8) * .7 * .6); }
.lane.lands .card img { object-fit: cover; object-position: bottom center; }
.seat.me .lane.lands { height: calc(var(--chb) * .7 * .6 + 44px); }
.seat.opp .lane.lands { height: calc(var(--chb) * var(--os, .8) * .7 * .6 + 44px); }

/* the enlarged hand is drawn over everything, including your status bar */
#handbar:has(#hand:hover) { z-index: 40; }

/* lands: a little taller (about the lower 75% of each card shows) and the label sits in the bottom-right corner of the box */
.lane.lands { --ch: calc(var(--chb) * .7 * .75); }
.opp .lane.lands { --ch: calc(var(--chb) * var(--os, .8) * .7 * .75); }
.seat.me .lane.lands { height: calc(var(--chb) * .7 * .75 + 44px); }
.seat.opp .lane.lands { height: calc(var(--chb) * var(--os, .8) * .7 * .75 + 44px); }
.lane.lands .lane-label, .seat.opp .lane.lands .lane-label { left: auto; right: 8px; top: auto; bottom: 4px; }

/* the cropped land cards get a black edge along the cut, like the printed card border */
.lane.lands .card { box-sizing: border-box; padding: 3px 0 0; background: #000; border-radius: 6px; }
.lane.lands .card img { border-radius: 0 0 6px 6px; }

/* lands: the artwork is cut off entirely, leaving the type line and rules text (the lower ~45% of each card) */
.lane.lands { --ch: calc(var(--chb) * .7 * .45); }
.opp .lane.lands { --ch: calc(var(--chb) * var(--os, .8) * .7 * .45); }
.seat.me .lane.lands { height: calc(var(--chb) * .7 * .45 + 44px); }
.seat.opp .lane.lands { height: calc(var(--chb) * var(--os, .8) * .7 * .45 + 44px); }

/* the lands box is twice as tall (the cards keep their size; there is room to spread them over two rows) */
.seat.me .lane.lands { height: calc((var(--chb) * .7 * .45 + 44px) * 2); }
.seat.opp .lane.lands { height: calc((var(--chb) * var(--os, .8) * .7 * .45 + 44px) * 2); }

/* ...and 10% shorter than that */
.seat.me .lane.lands { height: calc((var(--chb) * .7 * .45 + 44px) * 1.8); }
.seat.opp .lane.lands { height: calc((var(--chb) * var(--os, .8) * .7 * .45 + 44px) * 1.8); }

/* while a card is being dragged the hand goes back to normal size, so it does not cover the places you can drop on */
body.dragging #hand:hover { transform: none; }
body.dragging #hand:hover .card { transform: translateY(42%); }
body.dragging #handbar:has(#hand:hover) { z-index: 10; }

/* zone order: library, graveyard, exile, command */
.seat.me .piles .slot[data-zone="exile"], .seat.opp .piles .slot[data-zone="exile"] { order: 3; }
.seat.me .piles .slot[data-zone="command"], .seat.opp .piles .slot[data-zone="command"] { order: 4; }

/* bigger hand cards, sunk further below the screen edge: only the top ~38% of each card peeks up (rises 3x on hover) */
:root { --hch: calc(var(--chb) * .9); }
#handbar { height: calc(var(--hch) * .4); }
#hand { height: calc(var(--hch) * .4); }
#hand .card { transform: translateY(62%); }
body.dragging #hand:hover .card { transform: translateY(62%); }

/* lands are cut off from the BOTTOM instead: the name and artwork stay, the text box is cropped away (about the top 58% of each card) */
.lane.lands { --ch: calc(var(--chb) * .7 * .58); }
.opp .lane.lands { --ch: calc(var(--chb) * var(--os, .8) * .7 * .58); }
.seat.me .lane.lands { height: calc((var(--chb) * .7 * .58 + 44px) * 1.8); }
.seat.opp .lane.lands { height: calc((var(--chb) * var(--os, .8) * .7 * .58 + 44px) * 1.8); }
.lane.lands .card { padding: 0 0 3px; }
.lane.lands .card img { object-position: top center; border-radius: 6px 6px 0 0; }

/* the cards peeking out behind a land stack are cropped the same way (top of the card, not the middle) */
.lane.lands .stackghost { background-position: top center; background-size: cover; border-radius: 6px 6px 0 0; }

/* land stacks fan up and to the right, so the strips that show are the tops of the cards (the bottoms are cropped away) */
.lane.lands .stackghost:not(.tapped) { transform: translate(calc(var(--k) * 6px), calc(var(--k) * -6px)); border-radius: 6px 6px 0 0; }

/* the hand label sits just above the peeking cards (the cards are drawn over the top of the bar now) */
#handlabel { top: -18px; z-index: 11; }

/* hovering your hand softly blurs the battlefield behind it (fades in and out); not while dragging, so the drop targets stay sharp */
#board { transition: filter .25s ease; }
body:has(#hand:hover):not(.dragging) #board { filter: blur(3px); }

/* only your own side of the table blurs, not your opponents' */
#board { transition: none; }
body:has(#hand:hover):not(.dragging) #board { filter: none; }
#meSeat { transition: filter .25s ease; }
body:has(#hand:hover):not(.dragging) #meSeat { filter: blur(3px); }

/* the lands area lights up when the mouse is over it, and clearly while a card is dragged over it */
.lane.lands { transition: background-color .15s, box-shadow .15s, border-color .15s; }
.seat .lane.lands:hover { background-color: color-mix(in srgb, var(--pc, #888) 26%, #00000030); border-color: #ffffff55; }
.lane.lands.hot { background-color: color-mix(in srgb, var(--pc, #888) 38%, #00000030); border-color: var(--pc, #fff); box-shadow: inset 0 0 0 2px var(--pc, #fff), 0 0 18px color-mix(in srgb, var(--pc, #fff) 55%, transparent); }
.lane.lands:hover .lane-label, .lane.lands.hot .lane-label { color: #ffffffcc; }

/* one "Permanents" label for the whole battlefield, at the left end of the centre line (instead of one per side) */
.lane.main .lane-label { display: none; }
.seat.me::before { content: "Permanents"; position: absolute; left: 8px; top: -7px; z-index: 6; font-size: 11px; line-height: 14px; letter-spacing: .1em; text-transform: uppercase; color: #ffffff3d; pointer-events: none; }

/* the centre line stops before the word "Permanents" (the label is about 92px wide, starting 8px in) */
#meSeat::before { left: 112px; background: linear-gradient(90deg, #ffffff55, #ffffff55 85%, transparent); }

/* the life / poison / commander window: compact rows, smaller numbers, a section per topic */
.lmodal { display: grid; gap: 4px; padding: 6px 0; min-width: 340px; }
.lrow { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
.lrow .lname { flex: 1; min-width: 0; text-align: left; font-size: 14px; display: grid; gap: 1px; }
.lrow button { width: 40px; height: 32px; font-size: 16px; font-weight: 800; border-radius: 8px; padding: 0; }
.lrow button[disabled] { opacity: .4; }
.lrow .lval { width: 64px; font-size: 20px; color: #ffe9a8; font-variant-numeric: tabular-nums; background: #ffffff0d; }
.lrow .lval:hover { background: #ffffff1c; }
.lcmdr { font-size: 11px; color: #ffffff8a; font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; }
.lcmdr.none { font-style: italic; opacity: .6; }
.lhead { margin-top: 8px; padding-top: 8px; border-top: 1px solid #ffffff1f; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: #ffffff80; }

/* statuses and counters inside the life window */
.lstatus { margin-top: 8px; padding-top: 8px; border-top: 1px solid #ffffff1f; display: grid; gap: 6px; max-height: 280px; overflow: auto; }
.lstatus .msearch { width: 100%; box-sizing: border-box; }
.lchipset { display: flex; flex-wrap: wrap; gap: 5px; }
.lchip { padding: 3px 10px; border-radius: 12px; font-size: 12px; }
.lchip.on { background: color-mix(in srgb, #5b8def 40%, transparent); border-color: #5b8def; }

/* abilities picked for a not-yet-created blank token: a chip per ability, click to drop it */
.abilchips { display: flex; flex-wrap: wrap; gap: 5px; }
.abilchips:empty { display: none; }
.abilchip { padding: 3px 10px; border-radius: 12px; font-size: 12px; background: #ffffff14; border: 1px solid #ffffff2a; cursor: pointer; }
.abilchip:hover { background: #a03a3a; border-color: #a03a3a; }

/* the centre line fades in after the label and out at the far end, more subtle than before */
#meSeat::before { left: 104px; background: linear-gradient(90deg, transparent, #ffffff33 12%, #ffffff33 85%, transparent); }

/* poison numbers are green, commander damage numbers orange (life stays gold) */
.lrow .lval.poison { color: #7be08a; }
.lrow .lval.cmd { color: #ff9f43; }

/* close to death: a soft red glow pulses inside the bar (the outline itself stays as it is) */
.side.danger::after { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none; box-shadow: inset 0 0 16px 3px #ff3030; opacity: .14; animation: dangerpulse 2.4s ease-in-out infinite; }
@keyframes dangerpulse { 0%, 100% { opacity: .1; } 50% { opacity: .42; } }

/* the glow has to sit between the bar's own background and its contents: the bar makes its own stacking context (and your bar, which was static, becomes the glow's reference box) */
.side.danger { isolation: isolate; }
#meBar .side.danger { position: relative; }
@keyframes dangerpulse { 0%, 100% { opacity: .18; } 50% { opacity: .6; } }
#meBar .side.danger { left: auto; top: auto; }
.side.danger::after { box-shadow: inset 0 0 20px 7px #ff2a2a; }
@keyframes dangerpulse { 0%, 100% { opacity: .22; } 50% { opacity: .75; } }

/* (drawn above the bar's own background but under its contents, which are lifted one layer to stay on top of the glow) */
.side.danger::after { z-index: 0; }
.side.danger > * { position: relative; z-index: 1; }

/* a big hand overlaps more to fit beside the status bar (--hml), and its hover enlargement is capped to the screen (--hz, at most 3x) */
#hand .card:not(:first-child) { margin-left: var(--hml, calc(var(--hcw) * -.55)) !important; }
#hand:hover { transform: scale(var(--hz, 3)); }

/* (the glow is a gradient that grows toward the bar's edges: it stays inside the outline and needs no shadow) */
.side.danger::after { box-shadow: none; background: radial-gradient(ellipse 62% 95% at 50% 50%, transparent 55%, #ff2a2a 135%); }
.side.danger::after { background: radial-gradient(ellipse closest-side at 50% 50%, transparent 38%, #e01818 108%); }
@keyframes dangerpulse { 0%, 100% { opacity: .12; } 50% { opacity: .62; } }

/* the hand is laid out by script (fitHand): each card sits at its column and row, rows stacking upward so every row's top edge shows */
#hand { position: relative; flex: none; width: var(--hw, auto); }
#hand .card, #hand .card:not(:first-child), #hand.n2 .card:not(:first-child), #hand.n3 .card:not(:first-child), #hand.n4 .card:not(:first-child) { position: absolute; margin: 0 !important; left: calc(var(--col, 0) * var(--hstep, 0px)); bottom: 0; z-index: calc(20 - var(--row, 0)); transform: translateY(calc(62% - var(--row, 0) * 40%)); }
#hand:hover .card { transform: translateY(calc(var(--row, 0) * -55%)); }
#hand:hover .card:hover { transform: translateY(calc(var(--row, 0) * -55% - 4%)); }
body.dragging #hand:hover .card { transform: translateY(calc(62% - var(--row, 0) * 40%)); }
#handlabel { top: calc(-18px - (var(--hrows, 1) - 1) * var(--hch) * .4); }

/* the card under the mouse in the enlarged hand comes to the very front, so all of it (every line of text) can be read */
#hand:hover .card:hover { z-index: 80; transform: translateY(calc(var(--row, 0) * -55% - 6%)); }

/* in the enlarged hand the hovered card no longer moves (a moving card slid out from under the mouse and could stay stuck raised): it just comes to the front with a light outline */
#hand:hover .card:hover { transform: translateY(calc(var(--row, 0) * -55%)); box-shadow: 0 0 0 2px #ffffffcc, 0 6px 18px #000c; }

/* the real cause of the "stuck" card: the resting rules for bigger hands (.n2 .n3 .n4) out-ranked the hover rules, so only the first card (and the hovered one) rose. Doubling the id makes hover win for every card. */
#hand#hand:hover .card { transform: translateY(calc(var(--row, 0) * -55%)); }
#hand#hand:hover .card:hover { z-index: 80; transform: translateY(calc(var(--row, 0) * -55%)); box-shadow: 0 0 0 2px #ffffffcc, 0 6px 18px #000c; }
body.dragging #hand#hand:hover .card { transform: translateY(calc(62% - var(--row, 0) * 40%)); }

/* the enlarged hand's hovered card is shown in full by an overlay the mouse passes through, so it never hides the next card */
#hand#hand:hover .card:hover { z-index: calc(20 - var(--row, 0)); box-shadow: none; }
#handpeek { position: absolute; z-index: 90; pointer-events: none; border-radius: 6px; overflow: hidden; background: #000; box-shadow: 0 0 0 2px #ffffffcc, 0 8px 22px #000c; }
#handpeek[hidden] { display: none; }
#handpeek img { width: 100%; height: 100%; display: block; }

/* room under the last group of effects and under the Done button */
.lstatus { padding-bottom: 14px; }
.lfoot { margin-top: 4px; padding-bottom: 10px; }

/* the effects block already has its own top line: its first heading does not draw a second one */
.lstatus .lhead:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.lstatus .lhead { border-top: 0; padding-top: 0; margin-top: 8px; }
.lstatus .lhead:first-child { margin-top: 0; }

/* the number, being typed in place */
.lrow input.lvin { width: 64px; height: 32px; box-sizing: border-box; text-align: center; padding: 0 4px; font-size: 20px; border-radius: 8px; border: 1px solid #5b8def; background: #0b0e14; -moz-appearance: textfield; }
.lrow input.lvin::-webkit-outer-spin-button, .lrow input.lvin::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.lrow input.lvin.poison, .lrow .poison + input { color: #7be08a; }

/* the turn button on your own status bar: an obvious, raised button */
.passbtn { padding: 3px 12px; border-radius: 9px; font-size: 12px; font-weight: 800; letter-spacing: .02em; white-space: nowrap; color: #fff; background: linear-gradient(180deg, #6f9bff, #4a6fe0); border: 1px solid #a9c0ff; border-bottom-width: 3px; border-bottom-color: #2f4aa8; box-shadow: 0 2px 8px #0009; cursor: pointer; }
.passbtn:hover { filter: brightness(1.12); transform: translateY(-1px); }
.passbtn:active { transform: translateY(1px); border-bottom-width: 1px; }
.side .passbtn { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }

/* the turn button looks like the old header one: the plain blue primary button, with its Space hint */
.side .passbtn, .passbtn { padding: 3px 9px; border-radius: 5px; font-size: 12px; font-weight: 700; letter-spacing: normal; color: var(--text); background: var(--accent); border: 1px solid var(--accent); box-shadow: none; transform: none; }
.side .passbtn:hover { background: #7aa2ff; border-color: #7aa2ff; filter: none; transform: none; }
.side .passbtn:active { transform: none; border-width: 1px; }

/* the turn button is the old "YOUR TURN" pill (your colour, dark bold letters), just clickable */
.side .passbtn.turnbadge { padding: 0 8px; border-radius: 8px; background: var(--pc); border: 0; color: #111; font-size: 10px; font-weight: 900; letter-spacing: .08em; line-height: inherit; cursor: pointer; box-shadow: none; }
.side .passbtn.turnbadge:hover { background: var(--pc); filter: brightness(1.18); box-shadow: 0 0 0 2px #ffffff55; }
.side .passbtn.turnbadge:active { filter: brightness(.92); }

/* a bit larger */
.side .passbtn.turnbadge { padding: 2px 12px; font-size: 12px; border-radius: 10px; line-height: 16px; }

/* Start game: one big button in the middle of the table, shown to the host only until the game starts */
#startgame { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 30; padding: 16px 44px; font-size: 22px; font-weight: 800; border-radius: 14px; color: #fff; border: 1px solid #a9c0ff; background: linear-gradient(135deg, #4d7de8, #6b5be0); box-shadow: 0 12px 34px #4d7de866; cursor: pointer; }
#startgame:hover { background: linear-gradient(135deg, #5b8af0, #7a6aeb); transform: translate(-50%, -50%) scale(1.04); }

/* larger */
#startgame { padding: 24px 68px; font-size: 32px; border-radius: 18px; letter-spacing: .01em; }

/* Start game matches the status bars: dark glass, your colour for the outline and glow, white lettering */
#startgame { --pc: #5b8def; color: #fff; text-shadow: 0 2px 10px #000a; background: #000000c0; border: 3px solid var(--pc); box-shadow: 0 0 0 1px #00000080, 0 10px 34px #000a, 0 0 32px color-mix(in srgb, var(--pc) 45%, transparent); backdrop-filter: blur(4px); }
#startgame:hover { background: color-mix(in srgb, var(--pc) 22%, #000000d0); box-shadow: 0 0 0 1px #00000080, 0 10px 34px #000a, 0 0 46px color-mix(in srgb, var(--pc) 70%, transparent); }

/* refined: the same pill shape and 2px outline as the status bars, calmer glow, lighter weight */
#startgame { padding: 20px 60px; font-size: 26px; font-weight: 700; letter-spacing: .02em; border-radius: 999px; border: 2px solid var(--pc); background: #000000c0; text-shadow: none; box-shadow: 0 6px 22px #0009; backdrop-filter: none; }
#startgame:hover { background: color-mix(in srgb, var(--pc) 24%, #000000d0); box-shadow: 0 6px 22px #0009, 0 0 0 3px color-mix(in srgb, var(--pc) 45%, transparent); transform: translate(-50%, -50%); }
#startgame:active { transform: translate(-50%, -50%) scale(.98); }

/* what everyone but the host sees until the game starts: the same pill, not clickable, smaller lettering */
#startgame.wait { padding: 16px 40px; font-size: 20px; font-weight: 600; cursor: default; pointer-events: none; color: #ffffffd8; }
#startgame.wait:hover { transform: translate(-50%, -50%); }

/* its own colours, not a player's: green for "go" (like the New deck button), a quiet grey outline while waiting */
#startgame { --pc: #38b767; color: #eafff1; background: color-mix(in srgb, #38b767 16%, #000000c8); }
#startgame:hover { background: color-mix(in srgb, #38b767 30%, #000000d0); box-shadow: 0 6px 22px #0009, 0 0 0 3px #38b76755; }
#startgame.wait { --pc: #ffffff40; color: #ffffffcc; background: #000000b8; }

/* the action buttons (Untap all, Draw a card, Undo, Add card / token) are a stack on the table now, just left of your row of piles */
#stage > #actions { position: absolute; z-index: 12; display: flex; flex-direction: column; align-items: stretch; gap: 5px; width: 168px;
  right: calc(2.5% + max(32%, 380px) / 2 + var(--cw) * 1.6 + 26px); bottom: 124px; }
#stage > #actions button { display: flex; justify-content: space-between; align-items: center; gap: 8px; text-align: left; padding: 5px 10px; font-size: 13px; background: #000000a8; border: 1px solid #ffffff2a; }
#stage > #actions button:hover { background: #ffffff1c; }
#stage > #actions kbd.hk { margin-left: 0; flex: none; }

/* the action stack moves to the right of your piles (between the Command pile and the edge of the table) and gets a nicer look:
   dark glass like the status bars, an accent stripe, and a roomy hit area */
#stage > #actions { left: auto; right: 10px; bottom: 124px; gap: 6px;
  width: clamp(112px, calc(2.5% + (max(32%, 380px) - (var(--cw) * 3.2 + 24px)) / 2 - 22px), 176px); }
#stage > #actions button { position: relative; height: 34px; padding: 0 10px 0 14px; font-size: 12.5px; font-weight: 600; border-radius: 12px; color: #e6e9f2;
  background: linear-gradient(180deg, #ffffff14, #ffffff06), #0b0e14d0; border: 1px solid #ffffff26; box-shadow: 0 3px 10px #0008;
  transition: background .15s, border-color .15s, transform .12s, box-shadow .15s; overflow: hidden; }
#stage > #actions button::before { content: ""; position: absolute; left: 0; top: 7px; bottom: 7px; width: 3px; border-radius: 0 3px 3px 0; background: var(--accent); opacity: .85; }
#stage > #actions button:hover { background: linear-gradient(180deg, #ffffff26, #ffffff0e), #0b0e14e0; border-color: var(--accent); transform: translateX(-2px); box-shadow: 0 4px 14px #000a, 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent); }
#stage > #actions button:active { transform: translateX(0) scale(.98); }
#stage > #actions button:disabled { opacity: .45; }
#stage > #actions kbd.hk { font-size: 10px; padding: 0 5px; border-radius: 5px; background: #ffffff12; border: 1px solid #ffffff30; color: #ffffffb0; }
#stage > #actions button > span, #stage > #actions button { white-space: nowrap; }

/* long labels (Add card / token) wrap onto a second line instead of being cut off */
#stage > #actions button { height: auto; min-height: 34px; white-space: normal !important; line-height: 1.15; padding: 5px 8px 5px 13px; text-align: left; }
#stage > #actions button > kbd.hk { align-self: center; }

/* the stack lines up with the Command pile: same top and bottom as its card, the four buttons sharing that height equally */
#stage > #actions { bottom: 137px; height: calc(var(--cw) * .8 * 1.406); gap: 5px; }
#stage > #actions button { flex: 1 1 0; min-height: 0 !important; height: auto; padding: 0 8px 0 13px; font-size: 12px; line-height: 1.1; }

/* compact labels and shortcut chips so each button fits on one line in the narrow space beside the Command pile */
#stage > #actions { right: 6px; width: clamp(112px, calc(2.5% + (max(32%, 380px) - (var(--cw) * 3.2 + 24px)) / 2 - 12px), 176px); }
#stage > #actions button { font-size: 12px; padding: 0 7px 0 12px; gap: 4px; }
#stage > #actions kbd.hk { font-size: 10px; padding: 0 4px; min-width: 0; }

/* new accounts wait for admin approval: a dot on the Admin button, and the waiting rows stand out in the user list */
#btnAdmin { position: relative; }
#btnAdmin.hasdot::after { content: ""; position: absolute; top: -4px; right: -4px; width: 11px; height: 11px; border-radius: 50%; background: #ff4d4d; border: 2px solid #14161c; box-shadow: 0 0 8px #ff4d4d; }
table.adm tr.pending td { background: #ff4d4d14; }
.pdot { display: inline-block; width: 8px; height: 8px; margin-right: 6px; border-radius: 50%; background: #ff4d4d; box-shadow: 0 0 6px #ff4d4d; vertical-align: middle; }

/* not enough room beside the piles (log open, small window): the buttons become a row just above the piles */
#stage > #actions.above { flex-direction: row; flex-wrap: wrap; justify-content: flex-end; height: auto; width: auto; max-width: calc(100% - 20px);
  right: calc(2.5% + max(32%, 380px) / 2 - (var(--cw) * 1.6 + 12px)); bottom: calc(137px + var(--cw) * .8 * 1.406 + 8px); }
#stage > #actions.above button { flex: none; height: 30px; padding: 0 9px 0 12px; }

/* stacked on top: the row is centred over the zones (the piles are centred over the status bar, so the same centre line) */
#stage > #actions.above { right: calc(2.5% + max(32%, 380px) / 2); transform: translateX(50%); justify-content: center; }

/* emoji reactions */
#emojipop { position: fixed; z-index: 90; display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; padding: 8px; border-radius: 14px; background: #10141ff2; border: 1px solid #ffffff2a; box-shadow: 0 12px 34px #000c; }
#emojipop .emo { width: 46px; height: 42px; padding: 0; font-size: 24px; line-height: 1; border-radius: 10px; background: #ffffff0d; border: 1px solid transparent; cursor: pointer; }
#emojipop .emo:hover { background: #ffffff22; border-color: #ffffff40; transform: scale(1.12); }
.floatmoji { position: absolute; bottom: 14%; z-index: 60; pointer-events: none; display: grid; justify-items: center; gap: 2px; animation: emofloat 3.4s ease-out forwards; }
.floatmoji .fe { font-size: 56px; line-height: 1; filter: drop-shadow(0 4px 8px #0008); }
.floatmoji.text .fe { font-size: 38px; font-weight: 900; padding: 4px 14px; border-radius: 14px; background: var(--pc); color: #111; }
.floatmoji small { padding: 0 8px; border-radius: 8px; background: #000000b0; color: #fff; font-size: 11px; font-weight: 700; border: 1px solid var(--pc); white-space: nowrap; }
@keyframes emofloat {
  0% { transform: translate(0, 20px) scale(.4); opacity: 0; }
  10% { transform: translate(0, 0) scale(1.15); opacity: 1; }
  30% { transform: translate(calc(var(--dx) * .5), -12vh) scale(1); }
  60% { transform: translate(calc(var(--dx) * -.4), -32vh) scale(1); opacity: 1; }
  100% { transform: translate(calc(var(--dx) * .3), -58vh) scale(.9); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .floatmoji { animation: emofade 2.2s ease-out forwards; bottom: 40%; }
  @keyframes emofade { 0% { opacity: 0; } 12% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } }
}

/* "your turn" flash: full screen, click-through, gone after 5s (sooner if you click anywhere, see showTurnAlert) */
#turnalert { position: fixed; inset: 0; z-index: 200; pointer-events: none; display: grid; place-items: center;
  background: radial-gradient(ellipse at center, color-mix(in srgb, var(--pc, #5b8def) 22%, transparent) 0%, transparent 68%);
  animation: turnalertfade 5s ease-in-out forwards; }
.turnalert-text { font-size: clamp(40px, 8vw, 100px); font-weight: 900; letter-spacing: .07em; color: var(--pc, #5b8def);
  text-shadow: 0 0 46px color-mix(in srgb, var(--pc, #5b8def) 80%, transparent), 0 4px 18px #000c;
  animation: turnalertpop .5s ease-out; }
@keyframes turnalertfade { 0% { opacity: 0; } 13% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } }
@keyframes turnalertpop { 0% { transform: scale(.7); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  #turnalert { animation: emofade 1.6s ease-out forwards; }
  .turnalert-text { animation: none; }
}

/* smoother reactions: the motion is drawn by script (spawnEmoji), so the stepped keyframe animation is off; size varies per reaction */
.floatmoji { animation: none; will-change: transform, opacity; }
.floatmoji .fe { font-size: var(--fs, 56px); }
.floatmoji.text .fe { font-size: calc(var(--fs, 56px) * .7); }
.floatmoji.still { animation: emofade 2.2s ease-out forwards; bottom: 40%; }
#emojipop .emohint { grid-column: 1 / -1; padding: 4px 2px 0; font-size: 11px; color: #ffffff88; text-align: center; }

/* the full emoji picker: category tabs on top and a scrolling grid */
#emojipop { display: block; width: 372px; padding: 8px; }
#emojipop .emotabs { display: flex; gap: 2px; padding-bottom: 6px; margin-bottom: 6px; border-bottom: 1px solid #ffffff1f; }
#emojipop .emotab { flex: 1; height: 32px; padding: 0; font-size: 18px; border-radius: 8px; background: transparent; border: 1px solid transparent; opacity: .7; }
#emojipop .emotab:hover, #emojipop .emotab.on { opacity: 1; background: #ffffff1a; border-color: #ffffff30; }
#emojipop .emogrid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px; max-height: min(300px, 46vh); overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: #ffffff40 transparent; } /* a slim, unobtrusive scrollbar instead of the browser's default one (Firefox) */
#emojipop .emogrid::-webkit-scrollbar { width: 6px; } /* Chrome / Edge / Safari */
#emojipop .emogrid::-webkit-scrollbar-track { background: transparent; }
#emojipop .emogrid::-webkit-scrollbar-thumb { background: #ffffff40; border-radius: 3px; }
#emojipop .emogrid::-webkit-scrollbar-thumb:hover { background: #ffffff66; }
#emojipop .emo { width: auto; height: 40px; font-size: 24px; }
#emojipop .emohint { padding: 6px 2px 0; }

#emojipop .emosearch { width: 100%; box-sizing: border-box; height: 34px; margin-bottom: 6px; padding: 0 10px; border-radius: 10px; font-size: 14px; }

/* unread chat: a dot on the Chat button and a short banner that drops from the top of the screen */
#btnChat { position: relative; }
#btnChat.unread::after { content: ''; position: absolute; top: -3px; right: -3px; width: 10px; height: 10px; border-radius: 50%; background: #ff5d5d; box-shadow: 0 0 0 2px #171b26; }
#chatBanner { position: fixed; top: 0; left: 50%; z-index: 300; transform: translate(-50%, -120%); max-width: min(560px, 90vw); padding: 8px 16px; border-radius: 0 0 10px 10px; background: #14301c; color: #7be08a; border: 1px solid #7be08a66; border-top: 0; box-shadow: 0 6px 20px #000a; font-size: 13px; cursor: pointer; opacity: 0; pointer-events: none; transition: transform .25s ease-out, opacity .25s; }
#chatBanner.whisper { background: #2b1d47; color: #c9a4ff; border-color: #c9a4ff66; }
#chatBanner.show { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; }

/* player settings window */
.setrow.inline { display: flex; align-items: center; gap: 8px; }
.setrow.dim { opacity: .45; }
#modalBox .setrow input[type=range] { flex: 1; }
#modalBox .setrow select { flex: 1; }

.setmsg { font-size: 11.5px; }
#modalBox .setrow.inline button { flex: none; }

/* Menu: a soft, see-through icon in front of each item (the icon is a mask, so it takes the text colour) */
#menuPanel > button, #menuPanel .menusection > button { display: flex; align-items: center; gap: 9px; }
#menuPanel > button[hidden], #menuPanel .menusection > button[hidden] { display: none; }
#menuPanel button[data-icon]::before, #menuPanel #copyLink::before, #menuPanel #btnLeave::before, #menuPanel #btnSettings::before, #menuPanel #btnImport::before, #menuPanel #btnDealStart::before, #menuPanel #btnFirst::before, #menuPanel #btnMull::before, #menuPanel #btnDice::before, #menuPanel #btnStats::before, #menuPanel #btnCursors::before, #menuPanel #btnRestart::before, #menuPanel #btnKick::before, #menuPanel #btnEnd::before, #menuPanel #btnSaveQuit::before, #menuPanel button[data-changelog]::before { content: ''; flex: none; width: 16px; height: 16px; background: currentColor; opacity: .5; -webkit-mask: var(--ico) center / contain no-repeat; mask: var(--ico) center / contain no-repeat; }
#menuPanel button:hover::before { opacity: .85; }
#menuPanel #copyLink { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7-7l-1.7 1.7M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7 7l1.7-1.7'/%3E%3C/svg%3E"); }
#menuPanel #btnLeave { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 11l9-8 9 8M5 10v10h5v-6h4v6h5V10'/%3E%3C/svg%3E"); }
#menuPanel #btnSettings { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6h9M19 6h1M4 12h3M13 12h7M4 18h11M21 18h-1'/%3E%3Ccircle cx='16' cy='6' r='2.5'/%3E%3Ccircle cx='10' cy='12' r='2.5'/%3E%3Ccircle cx='18' cy='18' r='2.5'/%3E%3C/svg%3E"); }
#menuPanel #btnImport { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v12m0 0l-4-4m4 4l4-4M4 17v3h16v-3'/%3E%3C/svg%3E"); }
#menuPanel #btnDealStart { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='7' width='11' height='14' rx='2'/%3E%3Cpath d='M8 3h8a3 3 0 0 1 3 3v11'/%3E%3C/svg%3E"); }
#menuPanel #btnFirst { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 21V4M5 4h11l-2 4 2 4H5'/%3E%3C/svg%3E"); }
#menuPanel #btnMull { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 11a8 8 0 1 0-2.3 5.7M20 4v7h-7'/%3E%3C/svg%3E"); }
#menuPanel #btnDice { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='4' width='16' height='16' rx='3'/%3E%3Ccircle cx='9' cy='9' r='1'/%3E%3Ccircle cx='15' cy='15' r='1'/%3E%3Ccircle cx='15' cy='9' r='1'/%3E%3Ccircle cx='9' cy='15' r='1'/%3E%3C/svg%3E"); }
#menuPanel #btnStats { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 20V10M12 20V4M19 20v-7'/%3E%3C/svg%3E"); }
#menuPanel #btnCursors { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 3l14 7-6 2-2 6z'/%3E%3C/svg%3E"); }
#menuPanel #btnRestart { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12a8 8 0 1 1 2.3 5.7M4 20v-6h6'/%3E%3C/svg%3E"); }
#menuPanel #btnKick { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='8' r='4'/%3E%3Cpath d='M2 21a7 7 0 0 1 14 0M17 8l5 5M22 8l-5 5'/%3E%3C/svg%3E"); }
#menuPanel #btnEnd { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9 9l6 6M15 9l-6 6'/%3E%3C/svg%3E"); }
#menuPanel #btnSaveQuit { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 3h11l3 3v15H5zM8 3v6h7V3M8 21v-7h8v7'/%3E%3C/svg%3E"); }
#menuPanel button[data-changelog] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6h16M4 12h16M4 18h10'/%3E%3C/svg%3E"); }

/* What's new window tabs */
.wntabs { display: flex; gap: 6px; margin: 4px 0 8px; }
.wntab { padding: 5px 14px; border-radius: 8px; }
.wntab.on { background: var(--accent); border-color: var(--accent); }
.wnmore { margin-top: 12px; font-size: 12px; }

#modalBox .setrow .iconbtn { width: 34px; padding: 4px 0; text-align: center; }
#modalBox .setrow .iconbtn[hidden] { display: none; }

/* the list of your uploaded sounds under the sound picker */
/* the commander picker: a scrollable list of checkboxes when a Commander deck's list has no recognised Commander section */
.cmdrpicklist { display: grid; gap: 2px; max-height: 40vh; overflow-y: auto; padding: 6px; border: 1px solid #ffffff1c; border-radius: 12px; background: #0d1119; }
.cmdrpick { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 8px; cursor: pointer; }
.cmdrpick:hover { background: #ffffff10; }
.cmdrpick input { flex: none; }
.mysounds { display: grid; gap: 4px; }
.mysound { display: flex; align-items: center; gap: 4px; }
.mysound .msname { flex: 1; min-width: 0; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mysound.on .msname { border-color: var(--accent); background: #5b8def33; }
.mysound .msdel { flex: none; width: 30px; padding: 4px 0; }
.mysound .msdel:hover { background: #a03a3a; border-color: #a03a3a; }

/* the upload button: the green iPhone-style share icon (a box with an arrow leaving it) */
#modalBox .setrow .sharebtn { flex: none; width: 36px; height: 30px; padding: 0; display: grid; place-items: center; color: #34c759; border-color: #34c75966; }
#modalBox .setrow .sharebtn::before { content: ''; width: 19px; height: 19px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v12M8 7l4-4 4 4M8 11H6a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-2'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v12M8 7l4-4 4 4M8 11H6a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-2'/%3E%3C/svg%3E") center / contain no-repeat; }
#modalBox .setrow .sharebtn:hover { background: #34c75926; border-color: #34c759; }

/* the upload-a-sound window: a big drag-and-drop target */
.sounddrop { border: 2px dashed #ffffff33; border-radius: 12px; padding: 28px 16px; display: grid; justify-items: center; gap: 8px;
  text-align: center; cursor: pointer; color: #8b90a0; }
.sounddrop:hover, .sounddrop:focus-visible { border-color: #ffffff66; color: inherit; }
.sounddrop.over { border-color: var(--accent); background: #5b8def1a; color: inherit; }
.sounddrop-icon { font-size: 32px; }
.sounddrop-label b { color: inherit; }

/* settings window: boxed sections, and the on/off switch */
.setsec { border: 1px solid #ffffff1a; border-radius: 10px; padding: 10px 12px 12px; margin: 10px 0; display: grid; gap: 10px; }
.setsec-title { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #8b90a0; }
#modalBox .dim { opacity: .45; }
.switchrow { display: flex; align-items: center; justify-content: space-between; gap: 12px; cursor: pointer; }
.switch { position: relative; flex: none; width: 44px; height: 26px; }
.switch input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 1; }
.switch .knob { position: absolute; inset: 0; border-radius: 999px; background: #4a5068; transition: background .15s; }
.switch .knob::after { content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px #0006; transition: transform .15s; }
.switch input:checked + .knob { background: #34c759; }
.switch input:checked + .knob::after { transform: translateX(18px); }
.switch input:focus-visible + .knob { outline: 2px solid #ffffffaa; outline-offset: 2px; }
/* Slim status bar (#60): name, turn button and timer on the left, life (with poison and commander damage) on the right. The bar is centred under
   the piles' column, and the player's statuses/counters are a separate row (.effects) between the bar and the piles, drawn only when there are any. */
.side { grid-template-columns: minmax(0, 1fr) auto; height: 84px; }
#meBar { display: block; }
#meBar .side { width: 320px; margin: 0 auto; }
.seat.opp .side { width: 320px; right: calc(2.5% + (max(32%, 380px) - 320px) / 2); }
.effects { position: absolute; z-index: 8; display: flex; justify-content: center; width: max(32%, 380px); }
#meBar .effects { left: 0; bottom: calc(100% + 4px); }
.seat.opp .effects { right: 2.5%; top: 94px; }
.effects .pcs, .effects .pcs.two { display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: center; align-items: center; gap: 4px; padding: 0; }
.effects .pcs .pc { font-size: 10.5px; padding: 0 8px; line-height: 17px; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; background: #000000c0; border: 1px solid var(--pc); }
.effects .pcs .pc.status { background: #3b2f6b; }
.effects .pcs .pc.more { overflow: visible; background: #1c2130; color: #e6e9f2; cursor: default; }
.effects .morewrap { position: relative; }
.effects .morepop { display: none; position: absolute; left: 50%; transform: translateX(-50%); bottom: 100%; z-index: 30; flex-direction: column; align-items: center; gap: 3px; padding: 6px; border-radius: 10px; background: #10141ff2; border: 1px solid #ffffff2a; box-shadow: 0 8px 24px #000c; white-space: nowrap; }
.seat.opp .effects .morepop { bottom: auto; top: 100%; }
.effects .morewrap:hover .morepop { display: flex; }
.seat.opp .piles { top: 122px; }
#meBar .effects { width: 100%; box-sizing: border-box; }
/* the effects row is exactly as wide as the bar and centred over it; its chips shrink to fit rather than spill out */
#meBar .effects { left: 50%; transform: translateX(-50%); width: 320px; max-width: 100%; }
.seat.opp .effects { right: calc(2.5% + (max(32%, 380px) - 320px) / 2); width: 320px; }
.effects .pcs, .effects .pcs.two { width: 100%; min-width: 0; }
.effects .pcs .pc { flex: 0 1 auto; min-width: 0; max-width: 33%; }
.effects .pcs .pc.more { flex: none; }
.effects .morepop .pc { max-width: none; overflow: visible; text-overflow: clip; flex: none; }
/* the "+ Add" pill at the end of a group in Life and Effects; it becomes a text box for a name of your own */
.lchip.addpill { border-style: dashed; background: transparent; color: #aab4d4; }
.lchip.addpill:hover { color: #fff; border-color: #ffffff88; }
input.lchip.lchipin { width: 130px; outline: none; cursor: text; background: #0b0e16; color: #fff; border-color: var(--accent); }

/* Opponents' hands (#65): the card backs are about twice the old size and scale with the window (width and height), and the fan squeezes together when
   there are many cards, so it never runs into the piles or the bar */
.opphand { --ow: clamp(28px, min(3.2vw, 5.2vh), 62px); }
.oback { width: var(--ow); height: calc(var(--ow) * 1.4); margin-left: calc(var(--ow) * -.54); flex: 0 1 var(--ow); min-width: 8px; border-radius: calc(var(--ow) * .12); border-width: 2px; }
.oback:first-child { margin-left: 0; }
.seat.opp .opphand .ofan { width: 100%; max-width: 100%; justify-content: center; }
.ocount { font-size: clamp(11px, 1vw, 15px); }
.oback { margin-left: calc(var(--ow) * -.6); }
.oback:first-child { margin-left: 0; }
/* the card backs of an opponent's hand are placed by fitOppHands() (one row, or stacked rows when there is not enough room) */
.seat.opp .opphand .ofan { position: relative; width: auto; }
.oback, .oback:first-child { position: absolute; left: 0; top: 0; margin: 0; flex: none; min-width: 0; }
.seat.opp .opphand { justify-self: stretch; }
/* the matching card-back lifts/tilts when that opponent is hovering it in their own hand (#69), mirroring the lift your own hand gets on hover */
.oback { transition: transform .12s; }
.oback.hover { transform: translateY(-16%) scale(1.12) rotate(-4deg); z-index: 5; box-shadow: 0 6px 14px #000c; }
/* "+N more" for the counters on a card that do not fit (see fitBadges): hover it to list the rest */
.badge[hidden] { display: none; }
.badge.more { pointer-events: auto; cursor: default; background: #3b2f6b; }
#badgepop { position: fixed; z-index: 70; display: flex; flex-direction: column; gap: 2px; padding: 6px; border-radius: 10px; background: #10141ff2; border: 1px solid #ffffff2a; box-shadow: 0 8px 24px #000c; pointer-events: none; }
/* Zones flush right, buttons bottom right: the piles (and the status bar centred under them) sit against the right edge of the table, and the four action
   buttons (Untap all, Draw a card, Undo, Card / token) are one row along the bottom edge, under the status bar. --pw is the width of that right-hand column.
   --pw has a 340px floor (for the status bar and action-button row's own minimum width), so at small card sizes the piles' own content (4 slots + gaps) can
   be narrower than the box: centring them (rather than flex-end, #102) keeps them lined up with the status bar, which is always centred in the same box. */
:root, .opp { --pw: max(340px, calc(var(--cw) * .8 * 4 + 24px)); }
#meBar { right: 6px; width: var(--pw); bottom: 44px; }
.seat.me .piles, .seat.opp .piles { right: 6px; width: var(--pw); justify-content: center; }
.seat.me .piles { bottom: 158px; }
.seat.opp .side { right: calc(6px + (var(--pw) - 320px) / 2); }
.seat.opp .effects { right: 6px; width: var(--pw); justify-content: center; }
.seat.opp .opphand { right: calc(6px + var(--pw) + 12px); }
#stage > #actions, #stage > #actions.above { left: auto; right: 6px; bottom: 6px; top: auto; transform: none; width: var(--pw); max-width: none; height: 32px;
  flex-direction: row; flex-wrap: nowrap; justify-content: stretch; align-items: stretch; gap: 6px; }
#stage > #actions button, #stage > #actions.above button { flex: 1 1 0; min-width: 0; height: 32px; min-height: 0 !important; padding: 0 6px 0 11px; font-size: 11.5px; gap: 3px; white-space: nowrap !important; }
#stage > #actions button:hover { transform: translateY(-2px); }
#stage > #actions button:active { transform: scale(.98); }
#stage > #actions button, #stage > #actions.above button { flex: 1 1 auto; }
@media (max-width: 1500px) { #stage > #actions kbd.hk { display: none; } }
/* the four buttons are small icon buttons (the name and shortcut are in each tooltip) */
#stage > #actions, #stage > #actions.above { height: 30px; justify-content: center; gap: 8px; }
#stage > #actions button, #stage > #actions.above button { flex: none; width: 34px; height: 30px; padding: 0; justify-content: center; align-items: center; }
#stage > #actions button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
#stage > #actions button::before { display: none; }

/* the small button that hides / shows the piles (see zoneToggle): quiet until you point at it */
.piles { pointer-events: none; }
.piles .slot { pointer-events: auto; }
.zonetoggle { position: absolute; right: 0; top: -19px; z-index: 5; width: 22px; height: 16px; padding: 0; display: flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; color: #ffffff; background: transparent; border: 1px solid #ffffff22; border-radius: 6px; opacity: .3; cursor: pointer; pointer-events: auto; box-shadow: none; transform: none; }
.zonetoggle:hover, .zonetoggle:focus-visible { opacity: 1; background: #000000a8; border-color: #ffffff55; }
.zones-off .seat.me .piles .slot { display: none; }
/* the hide / show button is centred over the piles and easier to see */
.zonetoggle { left: 50%; right: auto; top: -24px; width: 46px; height: 20px; font-size: 13px; transform: translateX(-50%); opacity: .75; color: #fff; background: #000000b8; border: 1px solid #ffffff55; border-radius: 10px; }
.zonetoggle:hover, .zonetoggle:focus-visible { opacity: 1; background: #1c2130; border-color: var(--accent); }
/* the hide / show button sits underneath the piles, centred; your own piles are lifted a little to leave room for it above the effects row */
.zonetoggle { top: calc(100% + 3px); }
.seat.me .piles { bottom: 182px; }

/* the statuses strip: always there, as wide as the status bar, a thin faint box that says "statuses" in grey while it is empty */
.effects { box-sizing: border-box; width: 320px; height: 20px; align-items: center; border-radius: 10px; background: #ffffff0f; }
#meBar .effects { left: 50%; transform: translateX(-50%); }
.seat.opp .effects { right: calc(6px + (var(--pw) - 320px) / 2); width: 320px; }
.effects.empty::before { content: "statuses"; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: #ffffff40; pointer-events: none; }
.effects .pcs .pc { line-height: 16px; }

/* the statuses strip is styled like the status bar: the same dark rounded pill with the player's colour as its outline, just a thin extra line on top of it */
.effects { height: 22px; border: 2px solid var(--pc); border-radius: 22px; background: #000000c0; padding: 0 10px; }
#meBar .effects { bottom: calc(100% + 3px); }
.seat.opp .effects { top: 92px; }
#meBar.turn .effects, .seat.turn .effects { background: color-mix(in srgb, var(--pc) 26%, #000000d0); box-shadow: 0 0 0 1px var(--pc); }
.effects.empty::before { color: #ffffff55; }
.effects .pcs .pc { line-height: 15px; background: #ffffff14; border: 0; }
.effects .pcs .pc.status { background: #3b2f6b; }

/* the statuses section is attached to the status bar like a tab: it starts where the bar's flat top starts, shares its outline, and has no line between the two */
.effects { --fillc: #0b0d11; width: 248px; height: 22px; background: var(--fillc); padding: 0 8px; z-index: 9; }
#meBar.turn .effects, .seat.turn .effects { --fillc: color-mix(in srgb, var(--pc) 26%, #0b0d11); background: var(--fillc); box-shadow: none; }
#meBar .effects { bottom: calc(100% - 2px); border-bottom: 0; border-radius: 14px 14px 0 0; }
.seat.opp .effects { top: 88px; right: calc(6px + (var(--pw) - 248px) / 2); width: 248px; border-top: 0; border-radius: 0 0 14px 14px; }

/* the tab is exactly as wide as the flat top of the bar (the bar's corners are 34px), so its sides start where the bar's corners end and the outlines line up;
   both use the same solid fill so there is no seam */
.side { --fillc: #0b0d11; background: var(--fillc); }
#meBar.turn .side, .seat.turn .side { background: color-mix(in srgb, var(--pc) 26%, #0b0d11); }
.effects { width: 252px; }
.seat.opp .effects { width: 252px; right: calc(6px + (var(--pw) - 252px) / 2); }
#meBar .effects { width: 252px; max-width: none; }

/* small concave curves where the tab meets the bar, so the outline flows from the bar into the tab (the "statuses" label moves to the strip's inner row) */
.effects.empty::before { content: none; }
.effects.empty .pcs::before { content: "statuses"; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: #ffffff55; pointer-events: none; }
.effects::before, .effects::after { content: ""; position: absolute; width: 8px; height: 8px; pointer-events: none; }
#meBar .effects::before { left: -8px; bottom: 2px; background: radial-gradient(circle at 0 0, transparent 6px, var(--pc) 6px 8px, var(--fillc) 8px); }
#meBar .effects::after { right: -8px; bottom: 2px; background: radial-gradient(circle at 100% 0, transparent 6px, var(--pc) 6px 8px, var(--fillc) 8px); }
.seat.opp .effects::before { left: -8px; top: 2px; background: radial-gradient(circle at 0 100%, transparent 6px, var(--pc) 6px 8px, var(--fillc) 8px); }
.seat.opp .effects::after { right: -8px; top: 2px; background: radial-gradient(circle at 100% 100%, transparent 6px, var(--pc) 6px 8px, var(--fillc) 8px); }
/* overlap the bar by 3px (not 2) so no hairline shows at the join */
#meBar .effects { bottom: calc(100% - 3px); }
#meBar .effects::before, #meBar .effects::after { bottom: 3px; }
.seat.opp .effects { top: 87px; }
.seat.opp .effects::before, .seat.opp .effects::after { top: 3px; }

/* statuses as a header row of the bar: the same width, one outline around the pair (its corners are rounded at the far end), a thin line under it running edge to edge,
   and a lighter background than the bar (mirrored under an opponent's bar) */
.effects::before, .effects::after { content: none; }
.effects { --hdr: color-mix(in srgb, var(--pc) 14%, #1d2029); width: 320px; height: 24px; background: var(--hdr); padding: 0 12px; }
#meBar.turn .effects, .seat.turn .effects { --hdr: color-mix(in srgb, var(--pc) 32%, #1d2029); background: var(--hdr); }
#meBar .effects { width: 320px; bottom: 100%; border: 2px solid var(--pc); border-bottom: 1px solid color-mix(in srgb, var(--pc) 60%, transparent); border-radius: 16px 16px 0 0; }
#meBar .side { border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
.seat.opp .effects { width: 320px; top: 90px; right: calc(6px + (var(--pw) - 320px) / 2); border: 2px solid var(--pc); border-top: 1px solid color-mix(in srgb, var(--pc) 60%, transparent); border-radius: 0 0 16px 16px; }
.seat.opp .side { border-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.effects .pcs .pc { background: #ffffff1c; }
.effects .pcs .pc.status { background: #4a3c85; }

/* on a player's turn the outline is thicker: drawn inside the edges (not as a ring around the outside), only along the sides and the far end, so the bar and its statuses row
   match exactly and the line between them stays thin */
#meBar.turn .side { box-shadow: inset 2px 0 0 var(--pc), inset -2px 0 0 var(--pc), inset 0 -2px 0 var(--pc); }
#meBar.turn .effects { box-shadow: inset 2px 0 0 var(--pc), inset -2px 0 0 var(--pc), inset 0 2px 0 var(--pc); }
.seat.opp.turn .side { box-shadow: inset 2px 0 0 var(--pc), inset -2px 0 0 var(--pc), inset 0 2px 0 var(--pc); }
.seat.opp.turn .effects { box-shadow: inset 2px 0 0 var(--pc), inset -2px 0 0 var(--pc), inset 0 -2px 0 var(--pc); }

/* every player's outline is the same thickness, on their turn or not (the tint and the TURN badge show whose turn it is) */
#meBar.turn .side, #meBar.turn .effects, .seat.turn .side, .seat.turn .effects, .seat.opp.turn .side, .seat.opp.turn .effects { box-shadow: none; }
#meBar.turn .orb, .seat.turn .orb { border-width: 3px; }

/* the Admin window (users and sessions) is as wide and tall as the screen allows, so the table and its buttons fit without scrolling */
#modalBox:has(table.adm) { width: min(1600px, 98vw); max-height: 96vh; }
#modalBox:has(table.adm) .tablewrap { overflow: auto; flex: 1 1 auto; min-height: 0; }

/* the emoji reaction button joins the small icon buttons at the bottom right, instead of the top bar */
#stage > #actions button.emojibtn { font-size: 15px; }

/* Twemoji images: sized to match the font-size the glyph they replace would have used, in each context */
img.emoji { width: 1em; height: 1em; vertical-align: -0.14em; object-fit: contain; pointer-events: none; }
#emojipop .emo img.emoji, #emojipop .emotab img.emoji { width: 1em; height: 1em; }
.floatmoji .fe img.emoji { filter: drop-shadow(0 4px 8px #0008); }

/* dev/staging site banner (see loadChangelog): a fixed strip across the top, with the page pushed down to make room for it */
body.devsite { box-sizing: border-box; padding-top: 22px; }
#devBanner { position: fixed; top: 0; left: 0; right: 0; height: 22px; z-index: 1000; display: flex; align-items: center; justify-content: center; background: #f28c1b; color: #1b1000; font: 700 12px/1 system-ui, sans-serif; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; overflow: hidden; pointer-events: none; }

/* small stroked icon inside a top-bar text button (same look as the action-bar icons) */
header button svg.btnicon { width: 14px; height: 14px; vertical-align: -2px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
