/* Mimic Mayhem. All motion lives in src/anim.js (GSAP); CSS only describes states. */

@font-face {
  font-family: "Cinzel";
  src: url("fonts/cinzel-latin-ext.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Cinzel";
  src: url("fonts/cinzel-latin.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Alegreya Sans";
  src: url("fonts/alegreya-sans-500-latin-ext.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Alegreya Sans";
  src: url("fonts/alegreya-sans-500-latin.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Alegreya Sans";
  src: url("fonts/alegreya-sans-700-latin-ext.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Alegreya Sans";
  src: url("fonts/alegreya-sans-700-latin.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Alegreya Sans";
  src: url("fonts/alegreya-sans-800-latin-ext.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Alegreya Sans";
  src: url("fonts/alegreya-sans-800-latin.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Arcane (Ernest's pick, 2026-10-21): deep dungeon purple and gold, from the card back and the logo.
   Red stays only for danger: --red and the COUNTERED! stamp's --nope. */
:root {
  --bg: #110b18;
  --raise: #1c1426;
  --raise-2: #281d36; /* a picked chip and the note under it, inside the raised panel */
  --edge: #4a3866; /* the quiet outline of fields and choices; the picked one turns --accent */
  --line: #8a62c9;
  --text: #fbf6ff;
  --muted: #e2d6f0;
  --accent: #fad46a; /* the lightest gold that keeps 4.5:1 on every painted table (tools/backdrop-contrast.mjs) */
  --accent-hi: #fde08e; /* --accent under the pointer */
  --accent-ink: #24142f;
  --red: #d8261f;
  --nope: #c81e1e;
  --ink: #1e1228;
  --back: #3a1f52; /* the card back: purple with a gold frame (art.js), also on the seats' little backs */
  --back-trim: #e0b54a;
  --scrim: rgba(13, 8, 19, .62); /* the backdrop's dark layer; tools/backdrop-contrast.mjs assumes this */
  --plate: rgba(13, 8, 19, .35); /* the soft backing of a label that sits on a painted table; the same tool checks it */
  --display: "Cinzel", "Trajan Pro", Georgia, serif;
  --body: "Alegreya Sans", system-ui, sans-serif;
  --cw: clamp(64px, 17.5vw, 104px); /* hand card width */
  --radius: 12px;
  /* film grain, like the paintings': on the card faces and over the table */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='.22'/%3E%3C/svg%3E");
  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
html { overflow-x: hidden; }
#app { position: relative; z-index: 1; overflow-x: clip; }
body {
  margin: 0;
  /* dark, with a faint warm glow behind the logo (a full red screen was hard on the eyes); the game screen covers it with a backdrop */
  background: radial-gradient(90% 60% at 50% 18%, #3a1f52 0%, #1a1124 45%, var(--bg) 100%) fixed, var(--bg);
  color: var(--text);
  font-family: var(--body);
  font-weight: 500;
  font-size: 16px;
  line-height: 1.4;
  -webkit-tap-highlight-color: transparent;
  overflow-x: hidden;
  /* a long press or double tap on a card mustn't select the page or open the magnifier (CrazyGames asks for this) */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
input, textarea { -webkit-user-select: text; user-select: text; }
button, input { font: inherit; color: inherit; }
button { cursor: pointer; }
[hidden] { display: none !important; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
svg { display: block; }

/* ---------- backdrop: a table scene behind the game, with a dark layer so the text stays readable ---------- */
.backdrop { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; background: var(--bg); }
.bd-surface { position: absolute; inset: 0; width: 100%; height: 100%; }
.bd-prop { position: absolute; }
.bd-prop svg { width: 100%; height: auto; }
.bd-prop.wide svg { height: 100%; }
.bd-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* fx.js's two Pixi canvases: the painted table that ripples and twists (under the dark layer), and the
   light, fire and sparks over the table (#fx; over the result pop-up while the win's coins fall) */
.backdrop canvas, .fx > canvas, .fx-win-layer > canvas { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* Lit like a lamp hangs over the table: darker towards the edges, and grain over all of it.
   Nothing here is lighter than --scrim, so tools/backdrop-contrast.mjs holds everywhere. */
.backdrop::after {
  content: ""; position: absolute; inset: 0;
  background:
    var(--grain) 0 0 / 120px,
    radial-gradient(ellipse 85% 80% at 50% 50%, transparent 30%, rgba(13, 8, 19, .62)),
    var(--scrim);
}
/* A painted table's dark layer only keeps 3:1 (large text and icons), so the paintings show more (from
   Sumasabog, 2026-10-31). The small labels that sit straight on it bring their own soft backing for 4.5:1. */
.turn-chip, .seat-name, .seat-meta, .me-name, .me-heroname, .me-count, .me-gold, .pile-label {
  background: var(--plate); box-shadow: 0 0 8px 4px var(--plate); border-radius: 999px;
}

.screen { min-height: 100dvh; width: 100%; max-width: 1040px; margin-inline: auto; padding: 0 16px; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 8px 22px; border-radius: 999px;
  border: 3px solid var(--ink); font-family: var(--display); font-size: 1.15rem; letter-spacing: .02em;
  white-space: nowrap; line-height: 1.1;
}
.btn .nw { white-space: nowrap; }
.btn-primary { background: var(--accent); color: var(--accent-ink); box-shadow: 0 4px 0 var(--ink); }
.btn-primary:hover { background: var(--accent-hi); }
.btn-ghost { background: transparent; color: var(--text); border-color: var(--muted); }
.btn-ghost:hover { background: rgba(255, 246, 229, .08); }
.btn-action { background: #fff6e5; color: var(--ink); box-shadow: 0 4px 0 var(--ink); }
.btn-action:hover { background: #ffffff; }
.btn-nope { background: var(--nope); color: #fff; box-shadow: 0 5px 0 var(--ink); font-size: 1.6rem; min-height: 60px; padding-inline: 30px; }
.btn-big { min-height: 58px; font-size: 1.5rem; padding-inline: 40px; }
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }
.icon-btn {
  width: 44px; height: 44px; border-radius: 50%; display: inline-grid; place-items: center;
  background: rgba(18, 11, 10, .72); border: 2px solid rgba(255, 248, 239, .2); color: var(--text);
}
.icon-btn:hover { background: var(--bg); border-color: rgba(255, 248, 239, .45); }
.icon-btn svg { width: 22px; height: 22px; }
/* body is the page's scroller (html's overflow-x stops it passing to the window), so body is also the
   gear's containing block: it scrolls away with the menu instead of floating over the panel */
body { position: relative; }
/* the menus' scene: the treasure vault, painted, under a dark layer that keeps every word readable
   (the game screen's own backdrop covers it) */
body::before {
  --vault: url("img/backdrops/vault-wide.webp");
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    var(--grain) 0 0 / 120px,
    radial-gradient(ellipse 80% 75% at 50% 45%, rgba(13, 8, 19, .5), rgba(13, 8, 19, .86)),
    linear-gradient(rgba(13, 8, 19, .38), rgba(13, 8, 19, .38)),
    var(--vault) center / cover no-repeat,
    var(--bg);
}
@media (orientation: portrait) { body::before { --vault: url("img/backdrops/vault-tall.webp"); } }
.menu-settings { position: absolute; z-index: 30; top: max(12px, env(safe-area-inset-top)); right: max(16px, env(safe-area-inset-right)); }

/* ---------- start screen ---------- */
.start { display: flex; flex-direction: column; align-items: center; padding-top: 24px; padding-bottom: 32px; text-align: center; }
.start-brand { display: flex; flex-direction: column; align-items: center; }
/* the chest in a gold ring: ink border, gold outline over an ink rim */
.start-art {
  width: min(128px, 34vw); aspect-ratio: 1; border-radius: 50%; overflow: hidden;
  border: 5px solid var(--ink); outline: 6px solid var(--accent); outline-offset: 0; box-shadow: 0 0 0 10px var(--ink);
}
.start-art svg, .start-art img { display: block; width: 100%; height: 100%; object-fit: cover; }
.logo {
  font-family: var(--display); font-weight: 400; font-size: clamp(2.4rem, 10vw, 4.6rem); line-height: 1.05; margin: 18px 0 4px;
  color: var(--accent); -webkit-text-stroke: 2px var(--ink); paint-order: stroke fill; text-shadow: 0 5px 0 var(--ink);
}
.logo span { color: var(--text); }
.tagline { margin: 0 0 20px; color: var(--muted); font-size: 1.1rem; font-weight: 700; }
.setup {
  container: setup / inline-size;
  width: 100%; max-width: 440px; display: flex; flex-direction: column; gap: 14px; align-items: stretch;
  background: var(--raise); border: 2px solid #3a2a27; border-radius: 22px; padding: 18px; box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
.field { border: 0; margin: 0; padding: 0; min-width: 0; text-align: left; display: flex; flex-direction: column; gap: 6px; }
.field-label { font-weight: 700; color: var(--muted); padding: 0; font-size: .95rem; }
.field input[type="text"] {
  min-height: 48px; border-radius: 12px; border: 2px solid var(--edge); background: var(--bg); padding: 8px 14px; font-size: 1.05rem;
}
.field input[type="text"]:focus { border-color: var(--accent); outline: none; }
.field input[type="text"]::placeholder { color: #b3a39c; }
/* bot level and game speed side by side once the panel has room */
.field-row { display: grid; gap: 14px; }
@container setup (min-width: 380px) { .field-row { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 10px; } }
.seg { display: flex; gap: 4px; background: var(--bg); border: 2px solid var(--edge); border-radius: 14px; padding: 4px; }
.seg label { flex: 1; position: relative; }
.seg input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.seg span { display: grid; place-items: center; min-height: 42px; border-radius: 10px; font-weight: 700; white-space: nowrap; padding: 0 6px; }
.seg input:checked + span { background: var(--accent); color: var(--accent-ink); }
.seg input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 2px; }
.setup .btn-primary { margin-top: 4px; }
.mode-fields { display: flex; flex-direction: column; gap: 14px; }

/* the two faces of the start screen (main.js showStartView) */
.start[data-view="title"] .setup, .start[data-view="setup"] .title-menu { display: none; }
.start[data-view="title"] { justify-content: center; }
.title-menu { display: flex; flex-direction: column; gap: 12px; width: 100%; max-width: 380px; margin-top: 8px; }
.title-menu > .btn-big { width: 100%; }
.title-menu > .btn-ghost { background: rgba(17, 11, 24, .6); } /* readable over the painting */
.title-menu > .btn-ghost:hover { background: rgba(40, 29, 54, .9); }
.title-menu .profile-bar { margin-top: 10px; flex-direction: column; align-items: stretch; padding: 12px; background: rgba(28, 20, 38, .86); border: 2px solid var(--edge); }
.profile-btns { display: flex; gap: 8px; }
.profile-btns .btn { flex: 1 1 0; padding-inline: 10px; }
.title-menu .profile-text { text-align: center; flex: none; }
/* only when the browser offers it: a plain link, so the menu keeps its one loud button */
.title-menu .btn-install {
  align-self: center; min-height: 40px; border: 0; padding-block: 4px; color: var(--accent); background: none;
  font-family: var(--body); font-weight: 800; font-size: 1rem; text-decoration: underline; text-underline-offset: 3px;
}
.title-menu .btn-install:hover { background: none; color: var(--accent-hi); }
.setup-head { display: flex; align-items: center; gap: 12px; }
.setup-head .icon-btn { flex: none; background: var(--bg); border-color: var(--edge); }
.setup-head .icon-btn:hover { border-color: var(--muted); }
.setup-title { margin: 0; font-family: var(--display); font-weight: 400; font-size: clamp(1.15rem, 5.4vw, 1.45rem); line-height: 1.1; color: var(--accent); text-align: left; }
/* the table's options, folded into one line that says what's picked */
.table-opts { border: 2px solid var(--edge); border-radius: 14px; }
.table-opts summary {
  display: flex; align-items: center; gap: 4px 12px; flex-wrap: wrap; min-height: 52px; padding: 8px 42px 8px 14px;
  position: relative; list-style: none; cursor: pointer; text-align: left; border-radius: 12px;
}
.table-opts summary::-webkit-details-marker { display: none; }
.table-opts summary::after {
  content: ""; position: absolute; right: 18px; top: 50%; width: 9px; height: 9px; margin-top: -7px;
  border-right: 2.5px solid var(--muted); border-bottom: 2.5px solid var(--muted); transform: rotate(45deg);
}
.table-opts[open] summary::after { margin-top: -2px; transform: rotate(-135deg); }
.table-opts summary:hover { background: rgba(255, 246, 229, .05); }
.table-opts summary:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.table-opts-label { font-weight: 700; color: var(--muted); font-size: .95rem; }
.table-opts-now { font-weight: 800; }
.table-opts-body { display: flex; flex-direction: column; gap: 14px; padding: 2px 12px 14px; }
/* one column: the setup has the screen to itself, below the gear */
@media (max-width: 1023px), (max-height: 639px) {
  .start[data-view="setup"] .start-brand { display: none; }
  .start[data-view="setup"] { padding-top: 68px; }
}
/* a short wide window (a phone on its side, CrazyGames' 800×450): the title beside the menu, all on one screen */
@media (min-width: 700px) and (max-height: 639px) and (orientation: landscape) {
  .start[data-view="title"] {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 360px); align-items: center; justify-content: center;
    column-gap: clamp(28px, 5vw, 64px); max-width: 960px; padding-block: 16px;
    padding-right: max(68px, env(safe-area-inset-right) + 56px); /* the menu stays clear of the gear */
  }
  .start[data-view="title"] .start-art { width: min(120px, 24vh); }
  .start[data-view="title"] .logo { font-size: clamp(2.4rem, 11vh, 3.4rem); margin-top: 12px; }
  .start[data-view="title"] .tagline { margin: 6px 0 0; }
  .start[data-view="title"] .title-menu { margin-top: 0; gap: 10px; }
  .start[data-view="title"] .title-menu > .btn-big { min-height: 50px; font-size: 1.3rem; }
  .start[data-view="title"] .profile-bar { margin-top: 4px; padding: 10px; gap: 8px; }
}
.online-note { margin: 2px 0 0; color: var(--muted); text-align: left; }
.or { display: flex; align-items: center; gap: 10px; margin: 4px 0 -2px; color: var(--muted); font-weight: 700; font-size: .95rem; }
.or::before, .or::after { content: ""; flex: 1; height: 2px; background: #3a2a27; }
.join-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: end; }
.field input.code-input { font-family: var(--display); font-size: 1.5rem; letter-spacing: .3em; text-transform: uppercase; padding-block: 4px; }
.field input.code-input::placeholder { letter-spacing: .3em; color: #8f7f78; }
.form-msg { margin: 0; min-height: 1.4em; color: var(--accent); font-weight: 700; }
.form-msg:empty { display: none; }

/* ---------- online lobby ---------- */
/* From Sumasabog (2026-10-31): a head with the way out, then three panels. Phones stack them: the code,
   the players with Start!, the settings. Desktop puts them side by side (below). */
.lobby.screen { max-width: 1360px; display: flex; flex-direction: column; gap: 14px; padding-block: max(12px, env(safe-area-inset-top)) 28px; }
.lobby-top { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 10px; min-height: 44px; }
.lobby-leave {
  justify-self: start; display: inline-flex; align-items: center; gap: 4px; min-height: 44px; padding: 4px 16px 4px 8px; border-radius: 999px;
  background: rgba(17, 11, 24, .72); border: 2px solid rgba(251, 246, 255, .2); color: var(--text);
  font-family: var(--display); font-weight: 700; font-size: 1.1rem; letter-spacing: .04em;
}
.lobby-leave:hover { background: var(--bg); border-color: rgba(251, 246, 255, .45); }
.lobby-leave svg { width: 22px; height: 22px; }
.lobby-title { margin: 0; font-family: var(--display); font-weight: 700; font-size: clamp(1.5rem, 5.6vw, 2.2rem); line-height: 1.05; letter-spacing: .03em; color: var(--accent); white-space: nowrap; }
/* beside the gear, which sits in the window's corner: clear of it until the page is wide enough */
.lobby-help { justify-self: end; margin-right: clamp(0px, 796px - 50vw, 54px); }

.lobby-grid { display: grid; gap: 14px; width: 100%; max-width: 520px; margin-inline: auto; }
.lobby-panel {
  display: flex; flex-direction: column; gap: 12px; min-width: 0; padding: 18px; border-radius: 22px;
  background: rgba(28, 20, 38, .92); border: 2px solid var(--edge); box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
.lobby-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 44px; }
.lobby-head { margin: 0; font-family: var(--display); font-weight: 700; font-size: 1.4rem; line-height: 1.05; letter-spacing: .03em; color: var(--accent); }
.lobby-head span { color: var(--muted); font-family: var(--body); font-weight: 800; font-size: 1rem; letter-spacing: 0; }

/* the room code: big, with the share buttons and the QR */
.lobby-room { align-items: center; text-align: center; }
.lobby-kicker { margin: 0; color: var(--muted); font-weight: 800; font-size: .85rem; letter-spacing: .14em; text-transform: uppercase; }
.room-code {
  margin: -6px 0 0; font-family: var(--display); font-size: clamp(3rem, 14vw, 4.6rem); line-height: 1.05; letter-spacing: .14em; padding-left: .14em;
  color: var(--accent); -webkit-text-stroke: 2px var(--ink); paint-order: stroke fill; text-shadow: 0 4px 0 var(--ink);
}
.lobby-note { margin: 0; color: var(--muted); font-size: .92rem; }
.lobby-share { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; width: 100%; }
.lobby-share .btn { flex: 1 1 0; min-width: max-content; margin-top: 0; padding-inline: 14px; } /* equal widths; wraps only when they don't fit */
/* the room link as a QR code: dark on white with its quiet zone, which phone cameras read best */
.lobby-qr { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.lobby-qr .qr { display: block; width: 168px; aspect-ratio: 1; border-radius: 12px; overflow: hidden; box-shadow: 0 0 0 3px var(--ink); }
.lobby-qr svg { display: block; width: 100%; height: 100%; }
.lobby-qr figcaption { color: var(--muted); font-size: .85rem; font-weight: 700; }

/* the players: a tile each, like a character-select screen, and every free chair */
.lobby-add {
  display: inline-flex; align-items: center; gap: 2px; min-height: 44px; padding: 4px 16px 4px 10px; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink); border: 2px solid var(--ink); box-shadow: 0 3px 0 var(--ink);
  font-family: var(--display); font-weight: 700; font-size: 1.1rem; letter-spacing: .04em;
}
.lobby-add:hover { background: var(--accent-hi); }
.lobby-add:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }
.lobby-add svg { width: 20px; height: 20px; }
.lobby-seats { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 16px 6px; }
.lobby-seat {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 0; padding: 12px 3px 8px;
  border-radius: 14px; background: rgba(17, 11, 24, .8); border: 2px solid var(--edge); text-align: center;
}
.lobby-seat.is-me { border-color: var(--accent); background: rgba(90, 64, 20, .45); }
.lobby-seat .seat-avatar { width: min(100%, 76px); margin-bottom: 4px; }
.lobby-seat.away .seat-avatar { opacity: .45; }
.lobby-name { max-width: 100%; font-weight: 800; font-size: clamp(.78rem, 2.7vw, 1rem); line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lobby-hero-name { max-width: 100%; color: var(--accent); font-weight: 700; font-size: clamp(.72rem, 2.2vw, .82rem); line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lobby-tag { color: var(--muted); font-weight: 700; font-size: clamp(.72rem, 2.2vw, .8rem); line-height: 1.2; }
.lobby-tag:empty { display: none; }
.lobby-seat.empty { background: transparent; border-style: dashed; }
.lobby-seat.empty .seat-avatar { aspect-ratio: 1; width: min(76%, 58px); border-radius: 50%; border: 2px dashed #6a5390; margin-block: 2px 6px; }
.lobby-seat.empty .lobby-name { color: #c4b4da; font-weight: 700; }
/* the host's tag sits on the tile's top edge */
.lobby-host {
  position: absolute; top: 0; left: 50%; transform: translate(-50%, -55%); padding: 1px 8px; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink); border: 2px solid var(--ink);
  font-family: var(--display); font-weight: 700; font-size: .78rem; line-height: 1.1; letter-spacing: .04em; white-space: nowrap;
}
/* the host takes a bot out with the × in its corner; the touch area reaches 44px past the small dot */
.lobby-kick {
  position: absolute; top: 3px; right: 3px; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%;
  background: rgba(17, 11, 24, .9); border: 2px solid rgba(251, 246, 255, .35); color: var(--text);
}
.lobby-kick::before { content: ""; position: absolute; inset: -9px; }
.lobby-kick:hover { background: var(--nope); border-color: #fff; }
.lobby-kick svg { width: 14px; height: 14px; }
/* my hero under the seats, where Sumasabog has its card art */
.lobby-hero { padding-top: 14px; border-top: 2px solid var(--edge); }
.lobby-go { display: flex; flex-direction: column; gap: 10px; margin-top: auto; padding-top: 4px; }
.lobby-wait { margin: 0; color: var(--text); font-weight: 700; text-align: center; }
.lobby-go .btn-big { width: 100%; margin-top: 0; }

/* the settings: the host's controls, or what the host picked */
.lobby-rules { container: rules / inline-size; text-align: left; }
.host-controls { display: flex; flex-direction: column; gap: 12px; }
.lobby-summary { margin: 0; display: grid; gap: 8px; }
.lobby-summary > div { display: flex; justify-content: space-between; gap: 14px; padding: 10px 14px; border-radius: 12px; background: var(--bg); border: 2px solid var(--edge); }
.lobby-summary dt { color: var(--muted); font-weight: 700; }
.lobby-summary dd { margin: 0; font-weight: 800; text-align: right; }
@container rules (min-width: 420px) { .host-controls { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); } }
/* phones: the QR beside the code, so the players come up sooner */
@media (max-width: 1023px), (max-height: 639px) {
  .lobby-room:has(.lobby-qr:not([hidden])) {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "kicker qr" "code qr" "share share" "note note";
    align-items: center; column-gap: 12px; row-gap: 8px;
  }
  .lobby-kicker { grid-area: kicker; align-self: end; }
  .room-code { grid-area: code; align-self: start; }
  .lobby-qr { grid-area: qr; }
  .lobby-qr .qr { width: 112px; }
  .lobby-share { grid-area: share; }
  .lobby-share .btn { min-height: 44px; font-size: 1.02rem; padding-inline: 10px; }
  .lobby-note { grid-area: note; }
}
/* narrow phones: the way out is just the arrow and the title sits beside it, so it clears the buttons;
   a free chair is just its dashed circle */
@media (max-width: 479px) {
  .lobby-top { grid-template-columns: auto minmax(0, 1fr) auto; }
  .lobby-leave { width: 44px; padding: 0; justify-content: center; }
  .lobby-leave-word { display: none; }
  .lobby-title { justify-self: start; font-size: clamp(1.3rem, 5.8vw, 1.7rem); }
}
@media (max-width: 399px) { .lobby-seat.empty .lobby-name { display: none; } }
.btn-small { min-height: 44px; padding: 4px 16px; font-size: 1rem; border-width: 2px; }

/* connection lost: a small notice at the top until it's back */
.net-note {
  position: fixed; z-index: 60; top: max(10px, env(safe-area-inset-top)); left: 50%; transform: translateX(-50%); margin: 0;
  max-width: calc(100vw - 32px); padding: 8px 16px; border-radius: 999px; background: var(--accent); color: var(--accent-ink);
  border: 2px solid var(--ink); font-weight: 800; box-shadow: 0 6px 18px rgba(0, 0, 0, .45); text-align: center;
}

/* ---------- game screen ---------- */
.game { display: grid; grid-template-rows: auto auto 1fr auto auto auto; height: 100dvh; min-height: 560px; padding-bottom: max(8px, env(safe-area-inset-bottom)); }
.bar { display: flex; align-items: center; gap: 8px; padding: 8px 0 4px; min-width: 0; } /* a long turn chip trims instead of widening the grid */
.bar-right { display: flex; gap: 6px; margin-left: auto; }
/* the quick reactions (online): a box of one-liners dropping from the top bar, over the table */
.emote-panel {
  position: fixed; z-index: 30; top: calc(max(8px, env(safe-area-inset-top)) + 56px); right: max(12px, env(safe-area-inset-right));
  width: min(340px, calc(100vw - 24px)); display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 10px;
  background: var(--raise); border: 3px solid var(--ink); border-radius: 18px; box-shadow: 0 14px 34px rgba(0, 0, 0, .55);
}
.emote-chip {
  min-height: 44px; padding: 6px 10px; border-radius: 999px; border: 2px solid rgba(255, 236, 210, .25);
  background: rgba(255, 246, 229, .08); color: var(--text); font: 800 1rem/1.15 var(--body); cursor: pointer;
}
.emote-chip:hover, .emote-chip:focus-visible { background: #fff6e5; color: var(--ink); border-color: var(--ink); outline: none; }
.emote-chip:active { transform: scale(.96); }
.turn-chip { margin: 0; min-width: 0; font-family: var(--display); font-size: 1.05rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--muted); }
.turn-chip.mine { color: var(--accent); }

/* --cols seats a row; wrapping rows centred, so a shorter last row sits in the middle (Ernest, 2026-10-17) */
.seats {
  --gap: 8px; list-style: none; width: 100%; margin: 0 auto; padding: 6px 0 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--gap);
  max-width: calc(var(--cols, 2) * 132px + (var(--cols, 2) - 1) * var(--gap)); /* never more than --cols a row */
}
.seats > .seat { flex: none; width: min(132px, calc((100% - (var(--cols, 2) - 1) * var(--gap)) / var(--cols, 2) - .1px)); }
/* 6 to 9 others (a 7 to 10 player game): two rows of smaller seats */
.seats.many { --gap: 6px; row-gap: 4px; --avw: clamp(36px, 10.5vw, 54px); }
.seats.many .seat { padding: 3px 2px 5px; gap: 0; }
.seats.many .seat-avatar { width: var(--avw); }
.seats.many .seat-name { font-size: .8rem; }
.seats.many .seat-meta { font-size: .74rem; }
.seat { position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 4px 8px; border-radius: 16px; background: rgba(18, 11, 10, .6); border: 2px solid transparent; min-width: 0; }
.seat.turn { border-color: var(--accent); background: rgba(40, 30, 10, .78); }
.seat.out { opacity: .55; }
.seat.left { opacity: .8; } /* out of the game too, but they got away: in colour */
.seat.away .seat-avatar { opacity: .45; } /* online: their phone lost its connection */
.seat.out .seat-avatar { filter: grayscale(1); }
/* will-change: the pulse (anim.js glow()) changes only its opacity on its own layer; repainting the blurred
   shadow every frame, under a Pixi effect, dropped Sugod! to 30 fps (2026-10-20) */
.seat-glow { position: absolute; inset: -6px; border-radius: 20px; box-shadow: 0 0 22px 4px rgba(255, 210, 63, .55); opacity: 0; pointer-events: none; will-change: opacity; }
.seat-avatar { width: clamp(46px, 13vw, 64px); aspect-ratio: 8 / 7; }
.seat-avatar svg { width: 100%; height: 100%; }
/* painted portraits: a round frame as tall as the box (8:7), so swapping a drawing for a picture moves nothing */
.seat-avatar { display: block; }
.portrait { display: block; width: 87.5%; aspect-ratio: 1; margin: 0 auto; border-radius: 50%; object-fit: cover; border: 2px solid var(--ink); box-shadow: 0 0 0 2px var(--text); background: var(--raise); }
.portrait.out { filter: grayscale(1); }
.seat-name { font-weight: 800; font-size: .92rem; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.seat-meta { display: inline-flex; align-items: center; gap: 4px; font-size: .82rem; color: var(--muted); white-space: nowrap; }
.mini-card { width: 11px; height: 15px; border-radius: 3px; background: var(--back); border: 2px solid var(--ink); box-shadow: inset 0 0 0 1.5px var(--back-trim); flex: none; }
.seat-think { position: absolute; top: 2px; right: 6px; font-family: var(--display); color: var(--accent); font-size: 1.1rem; opacity: 0; }
.seat-hand { display: none; } /* the held fan only shows on the desktop table */

/* No mat under the piles (Ernest, 2026-10-17: the banig came out; the painted tables carry the scene) */
/* Phones and tablets: the table row takes what's left of the screen, and the piles grow into it on a
   tall phone (a container query on the row's height) instead of floating small in an empty middle
   (Ernest, 2026-10-19). --pw is the pile width; the desktop table sets its own --pile-w. */
.table {
  display: flex; align-items: center; justify-content: center; gap: clamp(28px, 8vw, 80px); padding: 8px 0;
  min-height: calc(var(--cw) * 1.61 + 64px); /* the smallest pile plus its labels: size containment would otherwise let the row collapse */
  container-type: size; --note: 0px;
  /* never wider than the row can hold: two piles and the gaps */
  --pw: clamp(calc(var(--cw) * 1.15), min(31vw, calc((100cqh - 64px) * 5 / 7), calc((100cqw - var(--note) - 2 * clamp(28px, 8vw, 80px)) / 2)), 168px);
}
.pile { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.pile-label { margin: 0; font-size: .85rem; color: var(--muted); white-space: nowrap; text-align: center; }
.pile-label .nowrap { white-space: nowrap; }
/* the hoard under the discard pile, gold so it reads as a prize (Ernest, 2026-10-22). It's in place of the
   "Discard pile" caption, so the table is no taller: an extra line lifted the piles into the seats on a
   1024x640 desktop, and hung below the pile it covered a landscape phone's hand */
.hoard-label { display: inline-flex; align-items: center; gap: 5px; color: var(--accent); font-weight: 700; }
.hoard-label[hidden] { display: none; }
.hoard-label b { font-weight: 800; }
.deck, .discard { position: relative; width: var(--pw); aspect-ratio: 5 / 7; border-radius: var(--radius); }
.deck { padding: 0; border: 0; background: none; }
.deck:disabled { cursor: default; }
.deck .card { position: absolute; inset: 0; width: 100%; }
/* will-change: the deck and its three cards each keep a layer, so the Katomik spin, the shuffle and the
   shakes move them rather than repainting the glowing stack every frame (about 200 times a Katomik) */
.deck, .deck .card { will-change: transform; }
.deck .card:nth-child(1) { transform: translate(5px, 5px); }
.deck .card:nth-child(2) { transform: translate(2.5px, 2.5px); }
.deck.can-draw .card:last-child { box-shadow: 0 0 0 4px var(--accent), 0 0 24px 6px rgba(255, 210, 63, .5); }
/* empty: a faint card outline with a closed chest in it; the top card covers both */
.discard {
  border: 2px dashed rgba(255, 236, 210, .32); padding: 0; color: inherit; font: inherit; cursor: pointer;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='rgba(255,236,210,.2)'%3E%3Cpath d='M3.5 10.5C3.5 6.6 6.8 5 12 5s8.5 1.6 8.5 5.5z'/%3E%3Crect x='3.5' y='11.5' width='17' height='8' rx='1'/%3E%3Crect x='10.4' y='9.6' width='3.2' height='4.2' rx='.8' fill='rgba(255,236,210,.32)'/%3E%3C/svg%3E") 50% 50% / 40% no-repeat, rgba(0, 0, 0, .18);
}
.discard:disabled { cursor: default; }
.discard .card { position: absolute; inset: -2px; width: calc(100% + 4px); }
/* Danger meter under the deck: a fixed green-to-red track, uncovered from the left as the risk grows. */
.risk {
  position: relative; display: block; width: var(--pw); height: 8px; border-radius: 6px; overflow: hidden;
  border: 2px solid var(--ink); background: linear-gradient(90deg, #3fbf6a, var(--accent) 45%, #ff7a1f 70%, var(--nope)); margin-top: 4px;
}
.risk-cover { position: absolute; inset: 0; background: #1a100e; transform-origin: right center; }

.status { min-height: 52px; display: flex; align-items: center; justify-content: center; text-align: center; padding: 4px 8px; font-size: 1rem; color: var(--text); }
/* The story line sits on its own dark plate so it reads on every painted table and doesn't float loose. */
.status > span {
  display: inline-block; padding: 6px 14px; border-radius: 12px; line-height: 1.3;
  background: rgba(31, 22, 21, .84); border: 1.5px solid rgba(184, 70, 58, .55); box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
}
.status b { color: var(--accent); font-weight: 800; }

/* Card info: what the selected, hovered or last-played card does. On phones it takes the status line's place. */
.story { display: grid; min-width: 0; }
.game.has-info .status { display: none; }
.card-info {
  display: flex; align-items: center; gap: 10px; margin: 2px 0 6px; padding: 8px 12px 8px 10px; text-align: left;
  background: var(--raise); border: 2px solid var(--line); border-radius: 12px;
}
.card-info.tip { display: none; }
/* a capped info whose text scrolls: a fade at its foot says there's more (`more` is set by infoMore() in ui.js) */
.card-info.more { flex-wrap: wrap; }
.card-info.more::after {
  content: ""; flex: 0 0 100%; position: sticky; bottom: -8px; display: block; height: 20px; margin: -20px -12px -8px -10px;
  background: linear-gradient(rgba(31, 22, 21, 0), var(--raise) 85%); pointer-events: none;
}
.info-card { flex: none; }
/* CrazyGames on a phone or tablet: the name and effect without the little card, which only repeats the
   one raised in my hand (Ernest, 2026-10-23: it made the panel look cluttered) */
@media (pointer: coarse) and (max-width: 1023px), (pointer: coarse) and (max-height: 639px) {
  [data-platform="crazygames"] .info-card { display: none; }
}
.info-card .card { --cw: 46px; border-width: 2px; box-shadow: none; }
.info-card .card .card-name { display: none; } /* beats .card-name.long, which sets display */
.info-card .card-art { margin: 6%; border-width: 1px; border-radius: 5px; }
.info-card .card-icon { display: none; } /* too small to read */
.info-body { min-width: 0; }
.info-name { margin: 0; font-family: var(--display); font-size: 1.15rem; line-height: 1.1; color: var(--accent); }
.info-text { margin: 2px 0 0; font-size: .9rem; line-height: 1.3; color: var(--text); }
.info-how { margin: 4px 0 0; font-size: .82rem; line-height: 1.25; color: var(--muted); }
.info-how:empty { display: none; }

.actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; min-height: 56px; align-items: center; padding: 2px 0 6px; }

.me { position: relative; }
.me-tag { display: flex; justify-content: center; align-items: center; gap: 8px; font-weight: 800; font-size: .95rem; color: var(--muted); }
.me-tag .seat-avatar { width: 34px; }
.me-tag.turn { color: var(--accent); }
.me-count { margin-left: -4px; } /* the tag's gap plus the dot's own space was a double space */
.me-count::before { content: "· "; }
/* gold (treasure scoring, 2026-10-22): a coin and an amount, on a seat's portrait (their purse) and by my
   name (my purse plus my loot) */
.seat-gold { display: inline-flex; align-items: center; gap: 3px; font-weight: 800; color: var(--accent); }
.seat-gold[hidden] { display: none; }
.me-gold { margin-left: -2px; }
/* my count and gold: two items of the tag's row on a phone, one line together where the tag is a column */
.me-line { display: contents; }
/* the count keeps to one line ("· 6 / cards" broke on a phone's row beside the turns pill, 2026-10-23) */
.me-count { white-space: nowrap; }
.coin {
  width: .9em; height: .9em; border-radius: 50%; flex: none;
  background: radial-gradient(circle at 38% 34%, #fff6c8 0 8%, #ffd23f 30%, #e0a21c 62%, #a8700e 85%); box-shadow: 0 0 0 1.5px var(--ink);
}
.seat.left .seat-count { color: var(--accent); }
.hand { position: relative; height: calc(var(--cw) * 1.4 + 44px); margin-top: 4px; touch-action: manipulation; }
.hand .card { position: absolute; left: 0; bottom: 18px; transform-origin: 50% 120%; }
.hand.two-rows { height: calc(var(--cw) * 1.4 + 44px + var(--raise)); } /* a big hand in two rows (anim.js layoutHand) */
.hand .card.selected { box-shadow: 0 0 0 4px var(--accent), 0 8px 18px rgba(0, 0, 0, .4); }
.hand .card.match { box-shadow: 0 0 0 3px #fff6e5; }
.hand-empty { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); }

/* ---------- cards ---------- */
/* Printed like a real card: a dark keyline with a thin light rule inside it (the back has the same),
   paper grain, light from the top, the name on a darker plate, the picture in a window with a soft
   inner shadow, the type's icon top-left and an expansion's mark bottom-right.
   --band is the plate and icon colour: the card's colour darkened, or a cat's own colour (cards.js). */
.card {
  --c: #f4e3c1; --k: var(--ink);
  --band: color-mix(in srgb, var(--c) 58%, #120a08); --bt: #fff8ef; --rule: rgba(255, 248, 239, .5);
  --r: clamp(7px, calc(var(--cw) * .1), 20px);
  position: relative; width: var(--cw); aspect-ratio: 5 / 7; border-radius: var(--r); padding: 0;
  background: var(--grain) 0 0 / 120px, linear-gradient(170deg, rgba(255, 250, 240, .2), rgba(255, 250, 240, 0) 36%, rgba(0, 0, 0, .14)), var(--c);
  color: var(--k); border: 3px solid var(--ink);
  display: flex; flex-direction: column; overflow: hidden; text-align: left;
  box-shadow: 0 4px 10px rgba(0, 0, 0, .35);
}
.card:not(.back)::before {
  content: ""; position: absolute; inset: calc(var(--cw) * .022); border-radius: calc(var(--r) * .75);
  border: max(1px, calc(var(--cw) * .012)) solid var(--rule); pointer-events: none;
}
.card-name {
  position: relative; flex: none; margin: 5.5% 5.5% 3%; padding: 3.5% 5% 3%;
  border-radius: calc(var(--r) * .45); background: var(--band); color: var(--bt);
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, .25), 0 1px 0 rgba(255, 250, 240, .2);
  font-family: var(--display); font-size: calc(var(--cw) * .13); line-height: 1.05; text-shadow: 0 1px 0 rgba(0, 0, 0, .35);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.card-name.long { white-space: normal; font-size: calc(var(--cw) * .108); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; hyphens: manual; }
.card-name.tight { font-size: calc(var(--cw) * .11); } /* Earthquake, Gold Coins: one line, a little smaller */
.card-art { position: relative; flex: 1; margin: 0 5.5% 5.5%; border-radius: calc(var(--r) * .45); overflow: hidden; border: 2px solid var(--ink); min-height: 0; background: #fff; }
.card-art::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 2px 8px rgba(0, 0, 0, .35); pointer-events: none; }
.card-art > svg { width: 100%; height: 100%; }
.card-art .painted { display: block; width: 100%; height: 100%; object-fit: cover; }
.card-icon {
  position: absolute; z-index: 1; display: block; aspect-ratio: 1; border-radius: 50%;
  border: max(1.5px, calc(var(--cw) * .014)) solid var(--ink); box-shadow: 0 1px 3px rgba(0, 0, 0, .45);
}
.card-icon { left: 5%; top: 5%; width: calc(var(--cw) * .23); padding: calc(var(--cw) * .032); background: var(--band); color: var(--bt); }
.card-icon svg { width: 100%; height: 100%; }
/* Foil on the Mimic, only in the peeks (anim.js shine()): a light band that GSAP sweeps across. Without
   motion the band stays hidden. The Mimic keeps its own dark frame (Ernest, 2026-10-19: no gold edge). */
.card-shine {
  position: absolute; top: -20%; bottom: -20%; left: 32%; width: 36%; z-index: 2; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 250, 230, .5) 50%, rgba(255, 255, 255, 0));
}
.card.back { background: var(--back); }
.card.back .card-art { margin: 0; border: 0; border-radius: 0; background: none; } /* the back's SVG draws its own frame */
.card.back .card-art::after { content: none; }
/* Ernest's painted back (src/art.js): the seats' tiny backs use it too */
.painted-back .mini-card { background: var(--back-img) center / cover, var(--back); box-shadow: none; }

.card.big { --cw: min(200px, 46vw); }
.card.big .card-text { font-size: .86rem; line-height: 1.25; padding: 0 7% 7%; font-weight: 600; flex: none; }
.card.big .card-art { flex: none; aspect-ratio: 1; }

/* ---------- Ayoko! prompt ---------- */
.nope-prompt {
  position: fixed; left: 50%; top: 42%; transform: translate(-50%, -50%); z-index: 40;
  width: min(360px, calc(100vw - 32px)); background: var(--raise); border: 3px solid var(--ink); border-radius: 22px;
  padding: 16px; text-align: center; box-shadow: 0 0 0 4px var(--nope), 0 20px 50px rgba(0, 0, 0, .55);
}
.nope-what { margin: 0 0 12px; font-weight: 700; }
.nope-none { display: block; margin-top: 4px; color: var(--muted); font-weight: 600; }
/* COUNTER! gets a row of its own, Distraction and Let it go share the one under it: in one row the
   three ran off both sides of a 360px phone (Ernest, 2026-10-22) */
.nope-row { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; align-items: center; }
.nope-row .btn { flex: 1 1 0; min-width: 0; padding-inline: 12px; font-size: clamp(1rem, 4.3vw, 1.15rem); }
.nope-row .btn-nope { flex-basis: 100%; font-size: 1.6rem; }
.nope-timer { height: 8px; border-radius: 4px; background: rgba(255, 246, 229, .15); margin-top: 14px; overflow: hidden; }
.nope-timer span { display: block; height: 100%; background: var(--accent); transform-origin: left center; }
/* A phone held upright: over the hand, not the middle, so the card being countered stays in view. The
   hand can't be played during the countdown anyway. */
@media (max-width: 759px) and (orientation: portrait) {
  .nope-prompt { top: auto; bottom: max(10px, env(safe-area-inset-bottom)); transform: translateX(-50%); padding: 14px; }
}

/* ---------- effects layer ---------- */
.fx { position: fixed; inset: 0; pointer-events: none; z-index: 50; overflow: hidden; }
/* Every effect part on its own layer, drawn once and then only moved and faded. Otherwise each flash, dim,
   ray and slash that changed repainted the whole full-screen effects layer every frame: 130 to 550 full
   repaints per Sugod, Higop or Laban Tayo!, at 3.5× on a phone (Pixel 7 Pro). The flying cards (.fly)
   and the rings grow, and a layer kept for a transform would be scaled up blurry, so theirs is kept for
   opacity only (the browser still redraws them sharp at a new size). */
.fx > :not(canvas, .fly, .fx-ring, .fx-glowring, .fx-runes) { will-change: transform, opacity; }
.fx > :is(.fly, .fx-ring, .fx-glowring) { will-change: opacity; }
/* The game screen is its own layer, so the screen shakes (Sugod!, the bomb, Laban Tayo!) only move it,
   instead of repainting the whole table when the shake starts and again when it ends. Only while the
   table shows: it changes what position: fixed is measured against. */
#app:has(#game:not([hidden])) { will-change: transform; }
.fx .fly { position: fixed; }
.fx .fly .card { --cw: 100px; }
/* Words always read over the cards and paws moving under them (anim.js gives those z-index 2–5). */
.fx-banner, .fx-stamp, .fx-arrow, .fx-say { z-index: 10; }
.fx-banner {
  position: fixed; left: 50%; top: 38%;
  font-family: var(--display); font-size: clamp(2rem, 9vw, 4rem); line-height: 1.05; text-align: center; white-space: nowrap;
  color: var(--accent); text-shadow: 0 4px 0 var(--ink), 0 0 30px rgba(0, 0, 0, .5); -webkit-text-stroke: 2px var(--ink); paint-order: stroke fill;
  will-change: transform; /* drawn once and scaled: the slam from 3.4× redrew the blurred shadow and the masked band every frame (Katomik's last stutter) */
}
.fx-banner small { display: block; font-size: .45em; color: var(--text); -webkit-text-stroke: 1px var(--ink); paint-order: stroke fill; }
/* A dark band across the screen behind every banner, fading out at the ends. */
.fx-banner::before {
  content: ""; position: absolute; z-index: -1; left: 50%; top: -.2em; bottom: -.2em; width: 100vw; transform: translateX(-50%);
  background: rgba(13, 8, 19, .84); border-block: 4px solid var(--accent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
}
.fx-stamp {
  /* sized so "COUNTERED! ×2" fits a phone's width; stamp() also keeps it inside the viewport (Ernest, 2026-10-19: it was cut off) */
  position: fixed; font-family: var(--display); font-size: clamp(1.4rem, 6.2vw, 3.2rem); color: #fff; background: var(--nope);
  border: 5px solid var(--ink); border-radius: 14px; padding: 4px 18px; line-height: 1.05; white-space: nowrap; box-shadow: 0 6px 0 var(--ink);
}
/* the Bard's Distraction: the same stamp in gold, like its gold rune circle (Ernest, 2026-10-22) */
.fx-stamp.bard { background: var(--accent); color: var(--accent-ink); }
.fx-flash { position: fixed; inset: 0; background: #fff3b0; opacity: 0; }
.fx-arrow { position: fixed; font-family: var(--display); color: var(--accent); font-size: 2.6rem; -webkit-text-stroke: 2px var(--ink); paint-order: stroke fill; }
/* A speech bubble over an avatar (say() in anim.js), tail pointing down at the cat */
.fx-say {
  position: fixed; font-family: var(--display); font-size: clamp(1.1rem, 3.6vw, 1.6rem); line-height: 1.1; white-space: nowrap;
  color: var(--ink); background: var(--accent); border: 3px solid var(--ink); border-radius: 14px; padding: 4px 14px 5px; box-shadow: 0 4px 0 var(--ink);
}
.fx-say::after {
  content: ""; position: absolute; left: 50%; bottom: -11px; width: 14px; height: 14px; transform: translateX(-50%) rotate(45deg);
  background: var(--accent); border: solid var(--ink); border-width: 0 3px 3px 0;
}
/* a quick reaction (online): cream, so it never reads as the game's own yellow callouts */
.fx-say.emote { z-index: 12; font-family: var(--body); font-weight: 800; font-size: clamp(1rem, 3.2vw, 1.3rem); background: #fff6e5; padding: 5px 12px 6px; }
.fx-say.emote::after { background: #fff6e5; }
.fx-paw { position: fixed; pointer-events: none; }
.fx-paw svg { width: 100%; height: auto; }
/* You won: coins on their own layer above the result pop-up (.modal is z-index 60), so the scrim never dims them */
.fx-win-layer { position: fixed; inset: 0; z-index: 70; pointer-events: none; overflow: hidden; }
.fx-coin {
  position: absolute; left: 0; top: 0; border-radius: 50%; will-change: transform;
  background: radial-gradient(circle at 38% 34%, #fff6c8 0 8%, #ffd23f 26%, #e0a21c 58%, #a8700e 80%);
  box-shadow: inset 0 0 0 2px rgba(255, 236, 160, .7), inset 0 0 0 4px #b07812, 0 0 0 1.5px rgba(43, 26, 18, .8);
}
/* Silipin ang Future: a crystal-ball glow sized from the deck (anim.js crystal()) */
.fx-glowball { position: fixed; border-radius: 50%; background: radial-gradient(circle, rgba(200, 245, 255, .95) 0%, rgba(155, 231, 255, .8) 18%, rgba(160, 110, 255, .6) 42%, rgba(123, 63, 196, 0) 70%); }
.fx-glowcore { position: fixed; border-radius: 50%; background: radial-gradient(circle, #fff 0%, rgba(214, 248, 255, .9) 35%, rgba(155, 231, 255, 0) 70%); }
.fx-glowring { position: fixed; border-radius: 50%; border: 4px solid rgba(190, 240, 255, .95); box-shadow: 0 0 22px 6px rgba(160, 110, 255, .8), inset 0 0 16px rgba(155, 231, 255, .8); }
.fx-sparkle { position: fixed; background: #f4fbff; clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%); }
/* Sneak (anim.js sneak()): the room dims at the edges, the title tiptoes, glowing boot prints creep past
   the deck. Sanctuary: a warm glow, a dome of golden light over the seat and gold motes. */
.fx-flash.shadow { background: radial-gradient(ellipse at center, rgba(8, 10, 24, 0) 35%, rgba(8, 10, 24, .7)); }
.fx-flash.holy { background: radial-gradient(ellipse at center, rgba(255, 216, 107, .18), rgba(60, 36, 8, .55)); }
.fx-banner.sneak { color: #9cc2ff; }
.fx-banner.sneak::before { border-color: #4f7fd8; }
.fx-banner.sanctuary { color: #ffd86b; }
.fx-banner.sanctuary::before { border-color: #c9a23a; }
.fx-step { position: fixed; z-index: 4; filter: drop-shadow(0 0 6px rgba(156, 194, 255, .9)); }
.fx-step svg { width: 100%; height: auto; display: block; }
.fx-dome {
  position: fixed; z-index: 4; border-radius: 50%; border: 3px solid rgba(255, 232, 160, .9);
  background: radial-gradient(circle, rgba(255, 240, 190, .05) 40%, rgba(255, 216, 107, .45) 64%, rgba(255, 216, 107, 0) 72%);
  box-shadow: 0 0 26px rgba(255, 200, 80, .75), inset 0 0 22px rgba(255, 220, 130, .6);
}
.fx-sparkle.gold { background: #ffe08a; }
/* The scouting effects (anim.js spyglass(), lantern(), hawk()): drawings in stacked layers (art.js) that
   move on their own, so each layer is its own finished picture the browser only shifts. */
.fx-spyglass, .fx-lantern, .fx-hawk { position: fixed; pointer-events: none; }
.fx-part { position: absolute; inset: 0; will-change: transform; }
.fx-part svg { width: 100%; height: 100%; display: block; }
.fx-spyglass { filter: drop-shadow(0 6px 5px rgba(0, 0, 0, .45)); }
.fx-lantern { filter: drop-shadow(0 0 14px rgba(255, 190, 80, .8)); }
/* Scout's lens sweeping the deck: a brass rim round bright glass */
.fx-lens {
  position: fixed; z-index: 4; border-radius: 50%; border: 5px solid #c9a23a;
  background: radial-gradient(circle at 34% 30%, rgba(255, 255, 255, .6) 0 7%, rgba(220, 245, 255, .2) 20%, rgba(155, 231, 255, .08) 62%);
  box-shadow: 0 0 0 3px #2b1a12, 0 0 20px rgba(255, 230, 150, .7), inset 0 0 18px rgba(155, 231, 255, .55);
}
/* the Lantern's light on the deck */
.fx-lightpool { position: fixed; z-index: 3; border-radius: 50%; background: radial-gradient(closest-side, rgba(255, 214, 120, .5), rgba(255, 170, 60, .22) 55%, rgba(255, 150, 40, 0)); }
/* the hawk's shadow on the table */
.fx-hawk-shadow { position: fixed; z-index: 5; border-radius: 50%; background: radial-gradient(closest-side, rgba(0, 0, 0, .45), rgba(0, 0, 0, 0)); }
/* the Mimic leaping out of its card (anim.js eaten()) */
/* A soft shadow under the Mimic rather than a drop-shadow filter: the lid and eyes move every frame,
   and the filter blurred the whole Mimic again each time (about 500 redraws a scene). */
.fx-mimic { position: fixed; }
.fx-mimic::before { content: ""; position: absolute; z-index: -1; left: 12%; right: 12%; bottom: -2%; height: 18%; border-radius: 50%; background: radial-gradient(closest-side, rgba(0, 0, 0, .55), rgba(0, 0, 0, 0)); }
.fx-mimic svg, .fx-mimic .tc-pic { width: 100%; height: 100%; display: block; }
/* the Mimic's moving parts are stacked layers (art.js mimicParts), moved by transform and opacity only */
.fx-mimic .tc-layer { position: absolute; inset: 0; will-change: transform; }
.fx-mimic .tc-lid { transform-origin: 50% 51%; }
.fx-puff { position: fixed; border-radius: 50%; background: radial-gradient(circle at 40% 45%, rgba(235, 230, 225, .95), rgba(170, 160, 155, .75) 45%, rgba(120, 110, 105, 0) 70%); }
/* The Earthquake (anim.js rubble()): grey-brown stones, lit from the top left */
.fx-stone {
  position: fixed; left: 0; top: 0; border-radius: 42% 58% 50% 46% / 50% 44% 56% 50%;
  background: radial-gradient(circle at 35% 30%, #c4ad8e, #8a7560 45%, #4e4034); box-shadow: 0 0 0 1.5px rgba(20, 12, 8, .75), 0 3px 4px rgba(10, 6, 4, .55);
}
/* Counterspell (anim.js runes()): a ring of runes under the stamp; gold for the Bard */
.fx-runes {
  position: fixed; border-radius: 50%; will-change: transform, opacity;
  border: 3px dashed rgba(196, 150, 255, .95); outline: 2px solid rgba(160, 110, 255, .55); outline-offset: 7px;
  box-shadow: 0 0 26px 6px rgba(140, 80, 240, .55), inset 0 0 22px 4px rgba(160, 110, 255, .5);
}
.fx-runes::after { content: ""; position: absolute; inset: 18%; border-radius: 50%; border: 2px dotted rgba(220, 190, 255, .9); }
.fx-runes.bard { border-color: rgba(255, 216, 107, .95); outline-color: rgba(201, 162, 58, .6); box-shadow: 0 0 26px 6px rgba(255, 190, 60, .5), inset 0 0 22px 4px rgba(255, 210, 63, .45); }
.fx-runes.bard::after { border-color: rgba(255, 236, 170, .9); }
/* A Mimic's bite (anim.js eaten()): a red flash as it snaps shut */
.fx-flash.red { background: radial-gradient(ellipse at center, rgba(255, 90, 40, .55), rgba(150, 10, 6, .95)); }
/* Charge! (anim.js charge()): a hot flash, the charger's portrait dashing on a streak of light, a blade's
   arc and a white hit with a ring */
.fx-flash.charge { background: radial-gradient(ellipse at center, rgba(255, 122, 58, .3), rgba(110, 20, 10, .85)); }
.fx-flash.hit { background: #fffbe8; }
.fx-banner.charge { color: #ff7a3a; }
.fx-banner.charge::before { border-color: #a8240e; }
.fx-charger {
  position: fixed; pointer-events: none; border-radius: 50%; overflow: hidden; background: var(--ink);
  border: 4px solid var(--hero, var(--accent)); box-shadow: 0 0 0 3px var(--ink), 0 0 26px var(--hero, var(--accent));
}
.fx-charger > :is(svg, img) { width: 100%; height: 100%; display: block; object-fit: cover; }
.fx-streak { position: fixed; pointer-events: none; border-radius: 999px; background: linear-gradient(90deg, rgba(255, 210, 63, 0), rgba(255, 210, 63, .55) 60%, rgba(255, 251, 232, .95)); }
.fx-slash { position: fixed; pointer-events: none; filter: drop-shadow(0 0 8px #ffd23f); }
.fx-slash svg { width: 100%; height: 100%; display: block; }
/* the cut each stroke leaves, and the sparks of steel off the hit */
.fx-cut { position: fixed; border-radius: 999px; background: linear-gradient(90deg, rgba(255, 251, 232, 0), #fff 30%, #fff 70%, rgba(255, 251, 232, 0)); box-shadow: 0 0 12px 3px rgba(255, 210, 63, .85); }
.fx-spark { position: fixed; height: 3px; margin-top: -1.5px; border-radius: 999px; transform-origin: 0 50%; background: linear-gradient(90deg, #fff, #ffe08a 50%, rgba(255, 138, 31, 0)); }
/* Paralyze (anim.js paralyze()): frost over the room, a seal of runes, spectral chains from the corners,
   a padlock and a burst of ice shards */
.fx-flash.frost { background: radial-gradient(ellipse at center, rgba(155, 231, 255, .14), rgba(10, 40, 70, .85)); }
.fx-flash.frosthit { background: #e9fbff; }
.fx-banner.frost { color: #9be7ff; }
.fx-banner.frost::before { border-color: #2f8fb8; }
.fx-seal { position: fixed; filter: drop-shadow(0 0 10px rgba(111, 214, 255, .9)); }
.fx-seal svg, .fx-lock svg { width: 100%; height: 100%; display: block; }
.fx-chain { position: fixed; background-repeat: repeat-x; background-size: auto 100%; filter: drop-shadow(0 0 6px rgba(111, 214, 255, .95)); }
.fx-lock { position: fixed; z-index: 4; filter: drop-shadow(0 4px 0 rgba(0, 0, 0, .35)) drop-shadow(0 0 12px rgba(155, 231, 255, .9)); }
.fx-ring.frost { border-color: #e9fbff; box-shadow: 0 0 30px rgba(155, 231, 255, .95), inset 0 0 18px rgba(111, 214, 255, .8); }
.fx-shard { position: fixed; background: linear-gradient(180deg, #fff, #9be7ff 55%, rgba(47, 143, 184, .3)); clip-path: polygon(50% 0, 100% 40%, 50% 100%, 0 40%); }
/* Mimic Bait (anim.js bait()): a coin on a hook over the deck, and eyes in the dark */
.fx-banner.bait { color: #b6e36a; }
.fx-banner.bait::before { border-color: #5e8a1c; }
.fx-bait { position: fixed; z-index: 4; filter: drop-shadow(0 0 8px rgba(255, 210, 63, .7)); }
.fx-bait svg { width: 100%; height: 100%; display: block; overflow: visible; }
.fx-eyes { position: fixed; z-index: 3; filter: drop-shadow(0 0 10px rgba(255, 210, 63, .95)); }
.fx-eyes svg { width: 100%; height: 100%; display: block; }
.fx-ring.charge { border-color: #fffbe8; box-shadow: 0 0 30px rgba(255, 251, 232, .9), inset 0 0 18px rgba(255, 210, 63, .8); }
.fx-ring { position: fixed; width: 120px; height: 120px; margin: -60px 0 0 -60px; border-radius: 50%; border: 6px solid #ff8a1f; box-shadow: 0 0 24px rgba(255, 138, 31, .8), inset 0 0 18px rgba(255, 210, 63, .7); }

/* ---------- battle embers (src/embers.js) ---------- */
/* The sparks fly above the table, below the Ayoko! prompt, the effects and dialogs; the glow (the
   hearth) sits right after the backdrop, under the table, so it never tints names and counts. */
.embers { position: fixed; inset: 0; z-index: 35; pointer-events: none; overflow: hidden; opacity: 0; }
.embers-hearth { z-index: 0; }
/* will-change: the glow flickers all through the battle; without its own layer each change repainted the
   whole backdrop (about 1000 full-screen repaints in 5 seconds) */
.embers-glow {
  position: absolute; inset: 0; opacity: 0; will-change: opacity;
  /* strongest in the corners and up the sides; light at the bottom middle, where the hand is */
  background:
    radial-gradient(ellipse 36% 34% at 0 100%, rgba(255, 96, 24, .42), rgba(255, 96, 24, 0)),
    radial-gradient(ellipse 36% 34% at 100% 100%, rgba(255, 96, 24, .42), rgba(255, 96, 24, 0)),
    linear-gradient(90deg, rgba(216, 38, 31, .55), rgba(216, 38, 31, 0) 12%, rgba(216, 38, 31, 0) 88%, rgba(216, 38, 31, .55)),
    linear-gradient(0deg, rgba(255, 96, 24, .4), rgba(255, 96, 24, 0) 8%),
    linear-gradient(180deg, rgba(150, 16, 10, .45), rgba(150, 16, 10, 0) 10%);
}
/* the flicker stays on the side edges: the corners hold my seat's name and count on desktop */
.embers-flicker {
  background: linear-gradient(90deg, rgba(255, 140, 40, .45), rgba(255, 140, 40, 0) 6%, rgba(255, 140, 40, 0) 94%, rgba(255, 140, 40, .45));
}
.ember { position: absolute; border-radius: 50%; background: radial-gradient(circle, #ffe9a8 0 22%, #ffa53a 40%, rgba(255, 90, 24, .55) 56%, rgba(255, 70, 20, 0) 72%); }
.ember.hot { background: radial-gradient(circle, #fff 0 24%, #ffe27a 42%, rgba(255, 138, 31, .5) 58%, rgba(255, 138, 31, 0) 72%); }

/* ---------- modal ---------- */
.modal { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 16px; }
.modal-scrim { position: absolute; inset: 0; background: rgba(8, 4, 3, .74); }
.modal-box {
  position: relative; width: min(560px, 100%); max-height: calc(100dvh - 32px); overflow: auto;
  background: var(--raise); border: 3px solid var(--ink); border-radius: 22px; padding: 20px; box-shadow: 0 24px 60px rgba(0, 0, 0, .6);
  text-align: center; /* Ernest, 2026-10-17: pop-ups read centred */
}
/* long reading stays left-aligned: How to play and the game log */
.modal-box:has(.rules), .modal-box:has(.log-list) { text-align: left; }
.modal-title { font-family: var(--display); font-weight: 400; font-size: 1.7rem; line-height: 1.1; margin: 0 0 12px; color: var(--accent); }
.modal-body p { margin: 0 0 12px; }
.modal-row { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 14px; }
.modal-cards { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.modal-cards .slot { display: flex; flex-direction: column; align-items: center; gap: 4px; font-weight: 700; font-size: .9rem; color: var(--muted); }
.modal-cards .card { --cw: clamp(78px, 24vw, 112px); }
/* pause / settings: over any open pop-up (.modal is 60), under the win's coins (70) */
.pause { z-index: 65; }
.pause-box { width: min(400px, 100%); }
.volume { display: grid; grid-template-columns: 1fr auto; gap: 6px 12px; align-items: center; text-align: left; margin: 4px 0 6px; }
.volume label { font-weight: 800; }
.volume output { justify-self: end; font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 700; }
.volume input[type="range"] { grid-column: 1 / -1; width: 100%; height: 44px; margin: 0 0 8px; accent-color: var(--accent); cursor: pointer; }
.volume .mute-switch { min-height: 44px; display: flex; align-items: center; margin-bottom: 6px; cursor: pointer; }
.volume.muted input[type="range"], .volume.muted output { opacity: .4; }
.anim-setting { border-top: 2px solid rgba(255, 236, 210, .12); padding-top: 12px; margin-top: 0; }
.anim-setting .mute-switch { margin-bottom: 0; }
.anim-note { grid-column: 1 / -1; margin: -2px 0 4px; font-size: .85rem; line-height: 1.3; color: var(--muted); }
/* phone landscape: the sound on the left, the animations and the button on the right, so it fits without scrolling */
@media (orientation: landscape) and (max-height: 639px) {
  .pause-box {
    width: min(660px, 100%); display: grid; grid-template-columns: 1fr 1fr; column-gap: 22px; align-items: start;
    grid-template-areas: "title title" "sound anim" "sound go"; grid-template-rows: auto auto 1fr;
  }
  .pause-box > .modal-title { grid-area: title; margin-bottom: 6px; }
  .pause-box > #volume { grid-area: sound; margin: 0; }
  .pause-box > .anim-setting { grid-area: anim; border-top: 0; padding: 8px 0 0 20px; border-left: 2px solid rgba(255, 236, 210, .12); margin: 0; }
  .pause-box > .modal-row { grid-area: go; align-self: end; margin-top: 8px; }
  .pause-box .volume input[type="range"] { height: 34px; margin-bottom: 2px; }
}
/* the mute switch: a pill with a sliding knob, yellow when on */
.switch {
  appearance: none; width: 56px; height: 32px; margin: 0 0 6px; border-radius: 999px; position: relative; cursor: pointer;
  background: rgba(255, 248, 239, .15); border: 2px solid rgba(255, 248, 239, .35); transition: background .15s, border-color .15s;
}
.switch::before { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: var(--text); transition: transform .15s; }
.switch:checked { background: var(--accent); border-color: var(--ink); }
.switch:checked::before { transform: translateX(24px); background: var(--ink); }
.switch:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 10px; justify-items: center; }
.pick-grid .card { --cw: 84px; }
.pick-grid .card[aria-pressed="true"] { box-shadow: 0 0 0 4px var(--accent); }
/* A pair: the target's cards face down in an even fan, like a held hand (the arc is set in ui.js) */
/* One row: the overlap grows with the count (--n, set in ui.js) so any hand fits the dialog. */
/* The side padding keeps the tilted end cards inside the dialog. */
.steal-fan {
  --cw: 76px; display: flex; justify-content: center;
  padding: 22px calc(var(--cw) * .45) max(30px, calc(14px + var(--dy, 0px) + var(--cw) * .5 * var(--sin, 0))); /* room for the lowest end card */
}
.steal-fan .card { flex: none; position: relative; }
.steal-fan .card + .card { margin-left: min(-8px, calc((100% - var(--cw) * var(--n)) / (var(--n) - 1))); }
.target-list { display: grid; gap: 8px; }
.target {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 60px; padding: 6px 14px; border-radius: 14px;
  background: rgba(255, 246, 229, .07); border: 2px solid var(--line); text-align: left; font-weight: 800;
}
.target:hover { border-color: var(--accent); }
.target .seat-avatar { width: 46px; }
.target small { margin-left: auto; color: var(--muted); font-weight: 600; white-space: nowrap; }
.pos-control { display: flex; flex-direction: column; gap: 10px; }
.pos-control input[type="range"] { width: 100%; accent-color: var(--accent); height: 32px; }
.pos-readout { font-family: var(--display); font-size: 1.4rem; text-align: center; color: var(--text); margin: 0; }
.pos-quick { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.pos-quick .btn { min-height: 40px; font-size: 1rem; padding-inline: 14px; }
/* How to play (from Sumasabog, 2026-10-31): a sheet with a fixed head (title and ×) and foot (Got it); the
   middle scrolls. The one modal box is reused by every pop-up, so the sheet's look comes from its content
   (:has), not a class that would stay on. */
.modal-box:has(.rules) {
  width: min(720px, 100%); height: calc(100dvh - 32px); padding: 0; overflow: hidden;
  display: flex; flex-direction: column;
}
/* the title stops short of the × (its box under the button counts as an overlap); the line under the head is the body's */
.modal-box:has(.rules) .modal-title { margin: 0 64px 0 0; padding: 16px 0 14px 20px; }
.modal-box:has(.rules) .modal-body { flex: 1; min-height: 0; display: flex; border-top: 2px solid var(--edge); }
.rules-sheet { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.rules-close { position: absolute; top: 12px; right: 12px; }
.rules { flex: 1; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 18px 20px 20px; display: grid; gap: 22px; align-content: start; }
.rules-foot { display: flex; justify-content: flex-end; align-items: center; padding: 12px 20px; border-top: 2px solid var(--edge); background: var(--raise); }
.rules-foot .btn { min-width: 200px; margin-top: 0; }
.rules-kicker { margin: 0 0 12px; color: var(--muted); font-weight: 800; font-size: .85rem; letter-spacing: .14em; text-transform: uppercase; }

/* the basics, step by step */
.rules-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; counter-reset: step; }
.rules-steps li { display: grid; grid-template-columns: 34px minmax(0, 1fr); column-gap: 12px; counter-increment: step; }
.rules-steps li::before {
  content: counter(step); grid-row: span 2; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  background: var(--accent); color: var(--accent-ink); font-family: var(--display); font-weight: 700; font-size: 1.15rem;
}
.rules-steps b { font-family: var(--display); font-weight: 700; font-size: 1.15rem; letter-spacing: .02em; line-height: 1.2; color: var(--accent); }
.rules-steps span { color: var(--muted); font-size: .95rem; line-height: 1.45; }
.rules-steps strong { color: var(--text); }
@media (max-width: 559px) { .rules-foot .btn { flex: 1; } }

/* the cards and heroes: one list at a time */
.rules-deck { min-width: 0; }
.rules-pack-note {
  margin: 0 0 14px; padding: 12px 14px; border-radius: 14px; color: var(--muted); font-size: .92rem; line-height: 1.45;
  background: color-mix(in srgb, var(--accent) 7%, var(--raise-2)); border: 2px solid color-mix(in srgb, var(--accent) 35%, var(--edge));
}
.rules-pack-note b { display: block; margin-bottom: 4px; color: var(--accent); font-weight: 800; }
.rule-cards { display: grid; gap: 10px; }
.rules .rules-credit { margin: 0; font-size: .8rem; color: var(--muted); opacity: .85; }
.rules-credit a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.rule-card {
  display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 14px; align-items: center;
  padding: 10px 14px 10px 10px; border-radius: 16px; background: var(--raise-2); border: 2px solid var(--edge);
}
.rule-card .card { --cw: 64px; }
.rule-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-bottom: 3px; }
.rule-card .rule-name { font-family: var(--display); font-weight: 400; font-size: 1.1rem; line-height: 1.1; letter-spacing: .02em; }
/* how many copies are in the deck */
.rule-count {
  padding: 1px 8px; border-radius: .8em; background: var(--bg); border: 1.5px solid var(--edge); color: var(--text);
  font-size: .75rem; font-weight: 800;
  /* a long count wraps: on one line it widened the list past a phone's pop-up */
}
.rule-card .rule-text { display: block; color: var(--muted); font-size: .9rem; line-height: 1.4; }
/* the Cards | Heroes switch looks like the lobby's .seg; the profile dialogs keep the pills below */
.rules .rules-tabs { flex-wrap: nowrap; gap: 4px; margin: 0 0 14px; padding: 4px; border-radius: 14px; background: var(--bg); border: 2px solid var(--edge); }
.rules .rules-tabs button { flex: 1 1 0; min-width: 0; min-height: 42px; padding: 0 4px; border: 0; border-radius: 10px; white-space: nowrap; font-size: .95rem; }
.rules .rules-tabs button:not([aria-selected="true"]):hover { background: var(--raise-2); }
/* tabs (the profile dialogs) */
.rules-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
.rules-tabs button {
  min-height: 40px; padding: 0 14px; border-radius: 999px; border: 2px solid var(--line); background: transparent;
  color: var(--text); font-weight: 800; font-size: .95rem;
}
.rules-tabs button[aria-selected="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.rules-tabs button:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* ---------- choice chips: game mode and hero, on the start screen and in the lobby ----------
   A row of chips with the picked one's note under it: each note follows its chip in the markup,
   only the checked chip's note shows, and `order` moves it below the row. */
.chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; container-type: inline-size; }
.chip {
  --n: 4; flex: 0 0 calc((100% - (var(--n) - 1) * 6px) / var(--n)); min-width: 0;
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  min-height: 74px; padding: 10px 4px 8px; border-radius: 14px; border: 2px solid var(--edge); background: var(--bg);
  text-align: center; cursor: pointer;
}
.chip input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.chip > b { font-family: var(--display); font-weight: 400; font-size: .98rem; letter-spacing: .02em; line-height: 1.1; }
.chip .hero-mark { font-size: 1.2rem; }
.chip:hover { border-color: var(--muted); }
.chip:has(input:checked) { border-color: var(--accent); background: var(--raise-2); }
.chip:has(input:checked) > b { color: var(--accent); }
.chip:has(input:focus-visible) { outline: 3px solid var(--accent); outline-offset: 2px; }
.chip:has(input:disabled) { opacity: .4; cursor: not-allowed; border-color: var(--edge); }
.chip:has(input:disabled) input { cursor: not-allowed; }
/* all seven in one row once there's room: each as wide as its name needs, sharing out the rest. Below
   that, four and three of the same width (Cinzel is wide: at 400px the Bard wrapped alone and stretched
   across the panel, Ernest 2026-10-21) */
@container (min-width: 620px) {
  .heroes > .chip { flex: 1 1 0; min-width: min-content; padding-inline: 4px; min-height: 66px; }
  .heroes > .chip > b { font-size: .84rem; }
}
/* the lobby's players panel between the code and the settings (1366 wide): one row a little sooner, so
   Start! stays on the screen */
@container (min-width: 530px) and (max-width: 619px) {
  .lobby-hero .heroes > .chip { flex: 1 1 0; min-width: min-content; padding-inline: 2px; min-height: 62px; }
  .lobby-hero .heroes > .chip > b { font-size: .75rem; letter-spacing: 0; }
}
/* a 360px phone: "Random" ran past its chip's edges */
@container (max-width: 300px) { .heroes > .chip > b { font-size: .8rem; letter-spacing: 0; } }
.chip-note {
  display: none; order: 1; flex: 1 0 100%; margin: 2px 0 0; padding: 10px 14px; border-radius: 12px;
  background: var(--raise-2); color: var(--muted); font-size: .92rem; line-height: 1.35; text-align: left;
}
.chip-note b { color: var(--text); font-weight: 800; }
.chip:has(input:checked) + .chip-note { display: block; }
/* Tap-the-card dialogs (the Lantern): the cards side by side */
.tap-pair { display: flex; justify-content: center; gap: clamp(14px, 5vw, 36px); margin: 4px 0 12px; }
/* Tap-the-card choices (ui.js tapCard()): each card and its caption is one button that lifts and glows */
.pick-card {
  --cw: clamp(104px, 30vw, 150px);
  display: flex; flex-direction: column; align-items: center; justify-content: space-between; gap: 8px; padding: 6px; border: 0; border-radius: 14px;
  background: none; color: var(--text); font: inherit; cursor: pointer; transition: transform .15s ease; touch-action: manipulation;
}
.pick-card .card { transition: box-shadow .15s ease; }
.pick-cap { font-family: var(--display); font-size: clamp(.95rem, 3.6vw, 1.1rem); line-height: 1.15; text-align: center; color: var(--accent); max-width: calc(var(--cw) + 20px); }
@media (hover: hover) { .pick-card:hover { transform: translateY(-6px); } .pick-card:hover .card { box-shadow: 0 0 0 4px var(--accent), 0 10px 24px rgba(0, 0, 0, .5); } }
.pick-card:active { transform: scale(.96); }
.pick-card:focus-visible { outline: none; }
.pick-card:focus-visible .card { box-shadow: 0 0 0 4px var(--accent), 0 0 0 7px var(--ink); }
/* The Lantern's "send it to the bottom": a short stack of backs with the card peeking out from under it */
.pick-deck { position: relative; display: block; width: var(--cw); aspect-ratio: 5 / 7; margin-bottom: 18px; }
.pick-deck .card { position: absolute; inset: 0; width: 100%; }
.pick-deck:has(.on-bottom) { margin-bottom: 44px; }
.pick-deck .card.on-bottom { transform: translate(-6px, 34px) rotate(-6deg); }
.pick-deck .card:nth-child(2) { transform: translate(10px, 8px) rotate(6deg); }
.pick-deck .card:nth-child(3) { transform: translateY(4px); }
.pick-card:focus-visible .pick-deck .card:not(.on-bottom), .pick-card:hover .pick-deck .card:not(.on-bottom) { box-shadow: none; }

@media (max-width: 759px) {
  /* the moves stay on one line (a second line of buttons pushed my tag under them on a short phone);
     a long label wraps inside its own button instead */
  .actions { flex-wrap: nowrap; align-items: stretch; gap: 6px; }
  .actions .btn { flex: 0 1 auto; min-width: 0; white-space: normal; text-align: center; padding-inline: 16px; }
  .actions .btn-primary { flex-shrink: 0; white-space: nowrap; } /* "Mag-draw" broke at its hyphen */
  .actions:has(> :nth-child(3)) { gap: 5px; }
  .actions:has(> :nth-child(3)) .btn { font-size: .95rem; padding-inline: 12px; }
  .actions:has(> :nth-child(3)) .btn-more { display: none; } /* "I-play": the card info above names the card */
  /* I-play, pair, 3 of a kind and draw: still one row, each label on up to two lines. Two rows of buttons
     made the column taller than the screen, and the grid then squeezed the row so the second one ran
     over my tag (check:ui, 2026-10-20). */
  .actions:has(> :nth-child(4)) { gap: 4px; }
  /* Cinzel is wide: "PICKPOCKET" alone took 107px at .86rem, and the four pushed the page off a 390px phone
     (check:ui, 2026-10-21), so they shrink a little more and "Open a chest" may wrap too */
  .actions:has(> :nth-child(4)) .btn { font-size: .78rem; padding-inline: 6px; letter-spacing: 0; line-height: 1.15; min-width: min-content; }
  .actions:has(> :nth-child(4)) .btn-primary { white-space: normal; }
  /* A long card info (Laban Tayo!, the Mabait, a Ligaw) pushed a tall phone's hand 27px off the bottom:
     the piles may shrink further to make room, and past what's left (~600px goes to the rest of a
     10-player table) the info scrolls, with a fade at its foot (.more, set in ui.js). */
  .table {
    min-height: calc(var(--cw) * 1.12 + 56px);
    --pw: clamp(calc(var(--cw) * .8), min(31vw, calc((100cqh - 64px) * 5 / 7), calc((100cqw - var(--note) - 2 * clamp(28px, 8vw, 80px)) / 2)), 168px);
  }
  .card-info { max-height: max(88px, calc(100dvh - 600px)); overflow-y: auto; overscroll-behavior: contain; }
}
/* Turns owed after a Taunt (Ernest, 2026-10-19: make it stand out): a red pill */
.seat-turns {
  display: inline-flex; align-items: baseline; gap: .25em; padding: .12em .7em .14em .55em; border-radius: 999px;
  background: var(--red); color: #fff; border: 2px solid var(--ink); box-shadow: 0 3px 0 var(--ink), 0 0 16px 3px rgba(216, 38, 31, .6);
  font-family: var(--display); font-size: clamp(.82rem, 2.7vw, 1.1rem); line-height: 1.2; letter-spacing: .03em; text-transform: uppercase; white-space: nowrap; position: relative; z-index: 2;
}
.seat-turns[hidden] { display: none; }
.seat-turns b { font-weight: 400; font-size: 1.35em; line-height: 1; }
.me-tag .seat-turns { margin-left: 4px; }
/* A hero's mark (src/art.js heroIcon) in the hero's colour, and its name; dim and struck once the power is used */
.seat-hero { display: inline-flex; align-items: center; flex: none; }
.seat-hero:empty { display: none; }
/* On a seat the mark stands in for the little card in the count's line ("⚔ 7 cards"); the desktop table
   gives it a line of its own with the hero's name. It used to sit on the portrait's corner and covered
   the ring and the held cards (Ernest, 2026-10-22). The hearts stay on the portrait's upper-right. */
.seat-meta .hero-mark { font-size: .82em; }
.seat-hero:not(:empty) + .mini-card { display: none; }
/* Sized from the portrait's own width (cqw), so they fit a 32px landscape cat and a 200px desktop one alike. */
.seats .seat-avatar, .me-tag .seat-avatar { position: relative; container-type: inline-size; }
.seat-face { display: block; width: 100%; height: 100%; }
/* Paralyzed (until their next turn is done): the portrait frosts over, two chains cross it and a padlock
   hangs where they meet, glowing softly (src/ui.js renderSeats) */
.seat-chains { display: none; }
.frozen .seat-chains {
  display: block; position: absolute; inset: -3%; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle closest-side, rgba(111, 214, 255, 0) 78%, rgba(111, 214, 255, .45) 96%, rgba(111, 214, 255, 0) 100%);
  box-shadow: 0 0 0 2px rgba(155, 231, 255, .85), 0 0 14px 3px rgba(111, 214, 255, .7);
  animation: frost-glow 1.8s ease-in-out infinite alternate;
}
.frozen .seat-chains::before, .frozen .seat-chains::after {
  content: ""; position: absolute; left: -4%; right: -4%; top: 50%; height: 9%; margin-top: -4.5%; border-radius: 999px; opacity: .85;
  background: repeating-linear-gradient(90deg, #e9fbff 0 9%, #4f9fc2 9% 11%, #9ec9db 11% 18%, #4f9fc2 18% 20%);
  box-shadow: 0 0 0 1.5px rgba(20, 40, 60, .8), 0 0 8px rgba(111, 214, 255, .9); transform: rotate(32deg);
}
.frozen .seat-chains::after { transform: rotate(-32deg); }
.seat-chains svg { position: absolute; left: 50%; top: 76%; width: 28%; transform: translate(-50%, -50%); z-index: 1; filter: drop-shadow(0 0 4px rgba(155, 231, 255, .9)); }
.frozen .seat-face { filter: saturate(.65) hue-rotate(-10deg); }
@keyframes frost-glow { to { box-shadow: 0 0 0 2px rgba(233, 251, 255, .95), 0 0 22px 6px rgba(111, 214, 255, .85); } }
@media (prefers-reduced-motion: reduce) { .frozen .seat-chains { animation: none; } }
.seat-avatar > .seat-hearts {
  position: absolute; right: -6px; top: -4px; z-index: 1; padding: 2px 3px; border-radius: 999px;
  background: rgba(18, 11, 10, .85); font-size: max(7px, min(17cqw, 1.1rem));
}
.me-tag .seat-avatar > .seat-hearts { font-size: max(10px, min(17cqw, 1.1rem)); } /* my own hearts stay easy to count */
/* A seat's purse sits on its portrait, across from the hearts on the desktop table and on the lower corner
   elsewhere. Beside "7 cards" it didn't fit a crowded phone row, a line of its own pushed the hand off a
   360px screen, and the wider desktop pill ran into the deck (check:ui, 2026-10-22). */
.seat-avatar > .face-gold {
  position: absolute; left: -6px; top: -4px; z-index: 1; gap: 2px; padding: 1px 5px 1px 3px; border-radius: 999px;
  background: rgba(18, 11, 10, .88); font-size: max(10px, min(15cqw, 1rem)); line-height: 1.15;
}
@media (max-width: 1023px), (max-height: 639px) {
  .seat-avatar > .face-gold { left: auto; top: auto; right: -8px; bottom: -3px; font-size: max(10px, min(20cqw, .85rem)); }
}
.seat-avatar .heart svg { width: 100%; height: auto; }
.seat-heroname { display: none; }
.seat-heroname, .me-heroname { align-items: center; gap: .35em; max-width: 100%; font-weight: 800; color: var(--muted); }
.me-heroname { display: inline-flex; font-size: .8rem; }
.me-heroname .hero-mark { font-size: 1.15em; }
@media (max-width: 379px) { .me-heroname .hero-name { display: none; } } /* a 360px row has room for the mark only */
/* A power still to use glows in its hero's colour, lightened so the dark ones (Rogue, Wizard) show on the
   table; mine breathes on my turn (Ernest, 2026-10-22). The breath is a separate ring that changes only
   its opacity on its own layer, so it costs no repaint. */
.hero-mark {
  position: relative; display: inline-grid; place-items: center; flex: none; width: 1.7em; height: 1.7em; border-radius: 50%;
  background: var(--hero); color: #fff; border: 2px solid var(--ink);
  box-shadow: 0 2px 0 var(--ink), 0 0 .5em .22em color-mix(in srgb, var(--hero) 35%, #ffe08a);
}
.hero-mark svg { width: 62%; height: 62%; }
.hero-mark.spent { background: #4a3c38; color: #a89890; box-shadow: none; }
.me-tag.turn .hero-mark:not(.spent)::after {
  content: ""; position: absolute; inset: -2px; border-radius: 50%; pointer-events: none;
  box-shadow: 0 0 .7em .3em color-mix(in srgb, var(--hero) 35%, #ffe9a8);
  opacity: 0; will-change: opacity; animation: power-breathe 1.3s ease-in-out infinite alternate;
}
@keyframes power-breathe { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .me-tag.turn .hero-mark:not(.spent)::after { animation: none; opacity: .8; } }
.hero-mark.big { font-size: 1.6rem; }
.hero-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.hero-mark.spent + .hero-name { text-decoration: line-through; text-decoration-thickness: 1.5px; }
/* every hero's hearts, on the portrait's corner */
.seat-hearts { display: inline-flex; gap: 2px; }
.seat-hearts:empty { display: none; }
.heart { display: block; width: 1em; font-size: .95rem; line-height: 0; }
.heart svg { width: 100%; height: auto; }
.heart.lost { opacity: .3; filter: grayscale(1); }
/* the hero power button, and the Bard's Distraction in the counter prompt */
.btn-power { background: #6c3fc4; color: #fff; box-shadow: 0 4px 0 var(--ink); }
.btn-power:hover { background: #7d52d6; }
/* "Use a power?" */
.power-ask { text-align: center; }
.power-ask .hero-mark { margin: 0 auto 8px; }
.power-note { color: var(--muted); font-size: .92rem; }
.rule-hero .hero-mark.big { margin: 0 auto; font-size: 1.9rem; }
.log-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column-reverse; gap: 6px; }
.log-list li { padding: 6px 10px; border-radius: 10px; background: rgba(255, 246, 229, .06); }
.log-list li.mine { background: rgba(255, 210, 63, .13); box-shadow: inset 0 0 0 1px rgba(255, 210, 63, .28); }
.result { text-align: center; }
.result .seat-avatar { width: 120px; margin: 0 auto 4px; }
.result .modal-title { font-size: 2.4rem; }
.result-saved { color: var(--accent); font-weight: 700; font-size: .95rem; }
/* everyone's final gold, richest first; up to 10 rows, so the list scrolls on a short screen */
.result:has(.result-scores) > .seat-avatar { width: 84px; }
.result-scores { list-style: none; margin: 8px auto 14px; padding: 0; max-width: 380px; max-height: min(40vh, 330px); overflow-y: auto; text-align: left; }
.result-scores li { display: grid; grid-template-columns: 34px 1fr auto auto; align-items: center; gap: 8px; padding: 4px 10px; border-radius: 12px; }
.result-scores li + li { margin-top: 2px; }
.result-scores li.won { background: rgba(255, 210, 63, .16); }
.result-scores li.me .rs-name { color: var(--accent); }
.result-scores .seat-avatar { width: 34px; margin: 0; }
.rs-name { display: flex; flex-direction: column; min-width: 0; }
.rs-who, .rs-split { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rs-who { font-weight: 800; }
.rs-split { color: var(--muted); font-size: .75rem; font-weight: 600; }
.rs-how { color: var(--muted); font-size: .8rem; white-space: nowrap; }
.rs-gold { display: inline-flex; align-items: center; gap: 4px; font-weight: 800; color: var(--accent); min-width: 3ch; justify-content: flex-end; }
.leave-total { display: inline-flex; align-items: center; gap: 8px; font-family: var(--display); font-size: 2.6rem; color: var(--accent); }
.leave-total .coin { width: .8em; height: .8em; }
/* the story of the game (src/recap.js): fun awards, who was eaten in what order, a picture to share */
.recap { margin: 4px auto 14px; max-width: 400px; padding: 12px 14px; border-radius: 16px; background: var(--bg); }
.recap-title { margin: 0 0 8px; font-family: var(--display); font-weight: 800; font-size: 1.1rem; color: var(--accent); }
.recap-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; text-align: left; }
.recap-award { display: flex; align-items: center; gap: 10px; padding: 6px 10px 6px 6px; border-radius: 12px; background: rgba(226, 214, 240, .06); }
.recap-award .seat-avatar { width: 40px; flex: none; margin: 0; }
.recap-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.recap-text b { font-family: var(--display); font-weight: 800; font-size: .95rem; color: var(--accent); }
.recap-text span { font-size: .92rem; overflow-wrap: anywhere; }
.recap-outs, .recap-totals { margin: 8px 0 0; font-size: .9rem; color: var(--muted); line-height: 1.3; }
.recap-list + .recap-outs { margin-top: 12px; }
.recap-share { margin-top: 10px; min-height: 40px; padding-inline: 16px; font-size: .95rem; }
.recap-note { margin: 6px 0 0; min-height: 1.2em; font-size: .85rem; color: var(--muted); }
.recap-note:empty { display: none; }
/* this game's XP, rank and new medals, filled in when the profiles server answers (Barkada.fillProgress) */
.result-progress { margin: 4px auto 14px; max-width: 360px; padding: 12px 14px; border-radius: 16px; background: var(--bg); text-align: left; }
.prog-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.prog-xp { font-family: var(--display); font-weight: 400; font-size: 1.5rem; color: #6fe08f; -webkit-text-stroke: 1px var(--ink); paint-order: stroke fill; }
.prog-xp.lost { color: #ff8a7a; }
.prog-move { margin: 8px 0 0; font-weight: 800; }
.prog-move.up { color: var(--accent); }
.prog-move.down { color: var(--muted); }
.prog-new { margin: 12px 0 6px; font-family: var(--display); font-size: 1.2rem; color: var(--accent); }
.prog-medals { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.prog-medals li { display: flex; align-items: center; gap: 10px; }
.prog-medals li > span:last-child { display: flex; flex-direction: column; line-height: 1.2; }
.prog-medals small { color: var(--muted); font-size: .85rem; }

/* ---------- ranks and medals ---------- */
.rank-badge {
  display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px 3px 3px; border-radius: 999px; vertical-align: middle;
  background: #2e211f; border: 2px solid var(--accent); color: var(--text); font-weight: 800; font-size: .9rem; line-height: 1.2; white-space: nowrap;
}
.rank-badge i {
  display: grid; place-items: center; width: 1.6em; height: 1.6em; border-radius: 50%; font-style: normal;
  background: var(--accent); color: var(--accent-ink); font-family: var(--display); font-weight: 400; font-size: .85rem;
}
/* the top three ranks get a hotter ring */
.rank-badge[data-rank="7"], .rank-badge[data-rank="8"], .rank-badge[data-rank="9"] { border-color: #ff7a1f; box-shadow: 0 0 10px rgba(255, 122, 31, .45); }
.profile-text .rank-badge { font-size: .8rem; }
.xp-bar { height: 12px; margin-top: 10px; border-radius: 999px; background: #3a2a27; border: 2px solid var(--ink); overflow: hidden; }
.xp-bar i { display: block; height: 100%; background: linear-gradient(90deg, #ff7a1f, var(--accent)); border-radius: inherit; }
.xp-label { display: block; margin-top: 4px; color: var(--muted); font-size: .85rem; }
.stats-rank { margin-top: 10px; }
.medals-count { margin: 0 0 4px; color: var(--muted); }
.medals-count b { color: var(--accent); font-size: 1.1rem; }
.medal-group { margin: 12px 0 6px; color: var(--muted); font-size: .8rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; }
.medal-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 6px; }
.medal { display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: 12px; background: var(--bg); }
.medal.locked .medal-text { opacity: .6; }
.medal-icon { flex: none; width: 30px; }
.medal-svg { display: block; width: 100%; height: auto; }
.medal-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.medal-text small { color: var(--muted); font-size: .82rem; }
.medal-text em { font-style: normal; font-weight: 800; font-size: .78rem; color: var(--accent); }

/* ---------- Barkada profile and leaderboard ---------- */
.profile-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; padding: 10px 10px 10px 14px;
  border-radius: 14px; background: var(--raise-2);
}
.profile-text { flex: 1 1 200px; margin: 0; text-align: left; color: var(--muted); font-size: .92rem; line-height: 1.3; }
.profile-text b { color: var(--accent); }
.modal-box:has(.board), .modal-box:has(.profile-form) { text-align: left; }
.profile-form { display: flex; flex-direction: column; gap: 12px; }
.profile-form .rules-tabs { margin: 0; }
.profile-form p { margin: 0; } /* the form's gap spaces it, not .modal-body p */
.profile-help { color: var(--muted); }
.field input[type="password"] {
  min-height: 48px; border-radius: 12px; border: 2px solid var(--line); background: var(--bg); padding: 8px 14px; font-size: 1.05rem;
}
.field input.pin-input { max-width: 170px; font-family: var(--display); font-size: 1.5rem; letter-spacing: .4em; padding-block: 4px; }

.board-note { margin: 0 0 10px; color: var(--muted); font-size: .95rem; }
.board-list { display: flex; flex-direction: column; gap: 4px; }
.board-row {
  display: grid; grid-template-columns: 2em minmax(0, 1fr) repeat(3, 4.4em); align-items: center; gap: 8px;
  width: 100%; min-height: 44px; padding: 6px 12px; border-radius: 12px; border: 2px solid transparent;
  background: var(--bg); color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.board-row:hover { border-color: var(--line); }
.board-row:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.board-row.is-me { border-color: var(--accent); }
.board-head { background: transparent; min-height: 0; padding-block: 0; color: var(--muted); font-weight: 800; font-size: .85rem; cursor: default; }
.board-head:hover { border-color: transparent; }
.board-row > span:nth-child(n + 3) { text-align: right; font-variant-numeric: tabular-nums; font-weight: 800; }
.board-row small { color: var(--muted); font-weight: 600; }
.board-rank { color: var(--muted); font-weight: 800; }
.board-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 800; }
.board-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.board-row .board-title { color: var(--accent); font-size: .76rem; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-back { margin-bottom: 10px; }

.stats-name { margin: 0; font-family: var(--display); font-weight: 400; font-size: 1.6rem; line-height: 1.1; color: var(--accent); }
.stats-since { margin: 2px 0 0; color: var(--muted); font-size: .9rem; }
.stats-card h4 { margin: 16px 0 6px; font-family: var(--display); font-weight: 400; font-size: 1.05rem; letter-spacing: .02em; }
.stats-bigs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 12px; }
.stat-big { background: var(--bg); border-radius: 14px; padding: 10px 6px; text-align: center; }
.stat-big b { display: block; font-family: var(--display); font-weight: 400; font-size: 1.8rem; line-height: 1; color: var(--accent); }
.stat-big span { display: block; margin-top: 4px; color: var(--muted); font-size: .82rem; font-weight: 700; line-height: 1.15; }
.stats-line { margin: 0; }
.stats-levels { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.stats-levels div { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; background: var(--bg); border-radius: 12px; padding: 8px 12px; }
.stats-levels span { color: var(--muted); font-weight: 700; }
.stats-levels b, .stats-list dd { font-variant-numeric: tabular-nums; }
.stats-levels small { color: var(--muted); font-weight: 600; }
.stats-list { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; margin: 0; }
.stats-list div { display: flex; justify-content: space-between; gap: 10px; padding: 5px 0; border-bottom: 1px solid rgba(255, 248, 239, .1); }
.stats-list dt { color: var(--muted); }
.stats-list dd { margin: 0; font-weight: 800; }
.stats-extra { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 16px; }
.stats-fav { display: flex; align-items: center; gap: 12px; background: var(--bg); border-radius: 14px; padding: 10px 12px; }
.stats-fav-card .card { --cw: 74px; }
.stats-rivals { display: grid; gap: 8px; }
.stats-fav p, .stats-rivals p { margin: 0; display: flex; flex-direction: column; line-height: 1.2; }
.stats-rivals p { background: var(--bg); border-radius: 14px; padding: 8px 12px; }
.stats-fav span, .stats-rivals span { color: var(--muted); font-size: .85rem; font-weight: 700; }
.stats-fav b, .stats-rivals b { font-size: 1.1rem; }
.stats-fav small, .stats-rivals small { color: var(--muted); }
@media (max-width: 559px) {
  .board-row { grid-template-columns: 1.6em minmax(0, 1fr) repeat(3, 3.3em); gap: 6px; padding-inline: 8px; }
  .stats-bigs { grid-template-columns: 1fr 1fr; }
  .stats-list, .stats-extra { grid-template-columns: 1fr; }
  .stats-levels div { flex-direction: column; align-items: flex-start; gap: 0; }
}
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.noscript { padding: 24px; text-align: center; }

@media (min-width: 760px) {
  :root { --cw: clamp(80px, min(8.5vw, 13.5vh), 124px); }
  .start-art { width: 156px; }
  .start { padding-top: 36px; }
  .bar { padding-top: 14px; }
  .status { font-size: 1.08rem; }
}
/* ---------- desktop table (after Exploding Kittens 2's layout) ----------
   Full screen instead of a column: the cats sit in an arc across the top holding their cards,
   the piles are big in the middle with the story on the left and your moves on the right,
   and you sit in the bottom-left corner behind a large hand. Sizes follow the window's height first. */
@media (min-width: 1024px) and (min-height: 640px) {
  :root {
    --cw: clamp(100px, min(9.5vw, 17.5vh), 230px);
    /* what's left after the cats and the hand, with room for a two-line Markado pill on a seat and a
       marked card standing up out of the fan (at -95px "Bomba: 50%" sat under them, check:ui 2026-10-20) */
    --pile-w: clamp(96px, min(12vw, 30vh - 115px), 300px);
    --av: clamp(84px, min(8.5vw, 14.5vh), 210px);
  }
  /* a hand big enough for two rows (20-odd cards at 1024px): the raised back row takes its height from the piles */
  .game:has(.hand.two-rows) { --pile-w: clamp(84px, min(12vw, 30vh - 115px - var(--cw) * .42), 300px); }

  /* start screen: the chest, title and tagline on the left; on the right, the menu or the setup panel */
  .start.screen {
    max-width: 1140px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(420px, 480px);
    grid-template-areas: "brand side";
    align-items: center; column-gap: clamp(40px, 6vw, 100px); padding-block: 24px;
  }
  .start-brand { grid-area: brand; }
  .start-art { width: clamp(200px, 19vw, 270px); }
  .logo { font-size: clamp(3.8rem, 5.4vw, 5.6rem); margin-top: 28px; }
  .tagline { font-size: 1.3rem; margin: 14px 0 0; }
  .title-menu { grid-area: side; justify-self: center; max-width: 400px; margin-top: 0; gap: 14px; }
  .title-menu > .btn-big { min-height: 64px; font-size: 1.6rem; }
  .setup { grid-area: side; max-width: none; gap: 12px; border-radius: 26px; padding: 20px 22px 18px; }
  .setup .mode-fields { gap: 12px; }

  /* lobby: the room code on the left, the players beside it with the settings under them; from 1280px
     wide, the settings get a column of their own. The head and panels sit in the middle of the window;
     a lobby taller than the window still scrolls. */
  .lobby.screen { padding-inline: 24px; gap: 18px; justify-content: center; }
  .lobby-grid { max-width: none; grid-template-columns: clamp(260px, 26vw, 320px) minmax(0, 1fr); grid-template-areas: "room players" "room rules"; gap: 18px; align-items: start; }
  .lobby-room { grid-area: room; padding-block: 24px; }
  .lobby-room .room-code { font-size: clamp(2.8rem, 3.4vw, 3.6rem); } /* Cinzel's Q has a long tail: inside the narrow panel */
  .lobby-players { grid-area: players; }
  .lobby-rules { grid-area: rules; }
  .lobby-panel { padding: 20px 22px; border-radius: 24px; }
  .lobby-seats { gap: 18px 10px; }
  .lobby-hero { margin-top: 6px; padding-top: 18px; }
  @media (min-width: 1280px) {
    .lobby.screen { max-width: 1500px; }
    .lobby-grid { grid-template-columns: clamp(270px, 21vw, 320px) minmax(0, 1fr) clamp(320px, 26vw, 380px); grid-template-areas: "room players rules"; align-items: stretch; }
    .lobby-seat .seat-avatar { width: min(100%, 92px); }
    .lobby-seat.empty .seat-avatar { width: min(76%, 70px); }
  }
  /* a short window (1366×768): smaller portraits, so Start! stays on the screen */
  @media (max-height: 859px) {
    .lobby-seats { gap: 14px 8px; }
    .lobby-seat { padding-block: 10px 6px; }
    .lobby-seat .seat-avatar { width: min(100%, 60px); }
    .lobby-seat.empty .seat-avatar { width: min(76%, 46px); }
    .lobby-hero { margin-top: 0; padding-top: 12px; }
  }

  /* game screen */
  /* clip: a card dealt or lifted past the bottom edge must not flash a scrollbar and reflow the table */
  .game.screen { max-width: none; padding-inline: clamp(20px, 2.5vw, 48px); overflow: clip; }
  .game {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr) auto;
    grid-template-areas: "bar bar bar" "seats seats seats" "status table actions" "me me me";
    column-gap: clamp(28px, 3.5vw, 72px);
  }
  .bar { grid-area: bar; padding-top: 14px; }
  .icon-btn { width: 52px; height: 52px; }
  .icon-btn svg { width: 26px; height: 26px; }
  .turn-chip { font-size: 1.45rem; }

  .seats { grid-area: seats; display: flex; flex-wrap: nowrap; justify-content: space-evenly; gap: 16px; padding: 0; max-width: none; margin: 0; }
  .seats > .seat {
    flex: 0 1 230px; width: auto; gap: 0; padding: 8px 12px 12px; border-radius: 24px; background: transparent;
    margin-top: calc(var(--off, 0) * clamp(0px, 7vh - 36px, 42px)); /* the ends sit lower, so the row curves round the table */
  }
  .seat.turn { background: rgba(40, 30, 10, .55); }
  /* a 7 to 10 player game: one row still, with the cats shrunk to fit across */
  .seats.many { gap: 6px; --av: min(clamp(84px, min(8.5vw, 14.5vh), 210px), calc((100vw - 120px) / var(--n) - 24px)); }
  .seats.many .seat { padding: 6px 2px 10px; gap: 0; }
  .seats.many .seat-avatar { width: var(--av); }
  .seats.many .seat-name { font-size: clamp(.95rem, 1.1vw, 1.25rem); }
  .seats.many .seat-heroname { font-size: clamp(.92rem, .6rem + .5vw, 1.25rem); }
  .seats.many .seat-meta { font-size: .9rem; padding: 0 8px; }
  /* the Markado pill scales with the cats: at 1024px with 10 players a full-size pill cut its name
     ("Ayok", "Pusan") and stood on the deck, and at 1366px "Mingming" lost its last letter. .135 of a
     cat fits the longest one-word name ("Pagpalitin") with the eye and a "+1". */
  .seat-glow { border-radius: 28px; }
  /* the names were big in Cinzel and the hero line under them tiny in Alegreya's small letters (Ernest,
     2026-10-22): the names came down and the hero line, now with its glowing mark, went up */
  .seat-name { order: -1; font-family: var(--display); font-weight: 400; font-size: clamp(1.1rem, 1.3vw, 1.5rem); line-height: 1.1; margin-bottom: 4px; }
  .seat.turn .seat-name { color: var(--accent); }
  .seat-heroname { display: inline-flex; order: -1; margin: 0 0 8px; font-size: clamp(1.02rem, .68rem + .55vw, 1.4rem); }
  .seat-heroname .hero-mark { font-size: 1.1em; }
  .seat-meta .seat-hero { display: none; }
  .seat-avatar { width: var(--av); }
  .portrait { border-width: 4px; box-shadow: 0 0 0 3px var(--text), 0 8px 18px rgba(0, 0, 0, .45); }
  .seat-think { font-size: 2.2rem; top: 0; right: 10px; }
  .seat-hand { display: block; position: relative; z-index: 1; width: var(--av); height: calc(var(--av) * .42); margin-top: calc(var(--av) * -.2); }
  .seat-hand i {
    position: absolute; left: 50%; bottom: 0; width: calc(var(--av) * .3); aspect-ratio: 5 / 7; margin-left: calc(var(--av) * -.15);
    border-radius: 6px; border: 2px solid var(--ink); transform-origin: 50% 150%; transform: rotate(var(--r, 0deg));
    /* a tiny card back, purple with a gold frame like the real one: two lines stand in for the wordmark */
    background: linear-gradient(var(--accent), var(--accent)) 50% 40% / 66% 9% no-repeat, linear-gradient(var(--text), var(--text)) 50% 60% / 50% 12% no-repeat, var(--back);
    box-shadow: inset 0 0 0 2px var(--back), inset 0 0 0 3.5px var(--back-trim);
  }
  .painted-back .seat-hand i { background: var(--back-img) center / cover, var(--back); box-shadow: none; }
  .seat-meta {
    position: relative; z-index: 2; margin-top: -6px; padding: 0 12px; border-radius: 999px;
    background: var(--accent); color: var(--accent-ink); border: 2px solid var(--ink); font-weight: 800; font-size: 1rem;
  }
  .seat-meta .mini-card { display: none; }
  .seat.left .seat-meta .seat-count { color: inherit; } /* "Escaped" on the gold pill */
  .seat.out .seat-meta { background: #e0d2cb; }  .table { grid-area: table; position: relative; gap: clamp(32px, 4vw, 76px); padding: 0; }
  .pile { gap: 8px; }
  .table { container-type: normal; min-height: 0; } /* the desktop table sizes its own piles (--pile-w) */
  .deck, .discard { width: var(--pile-w); border-radius: 16px; }
  .deck .card:nth-child(1) { transform: translate(8px, 8px); }
  .deck .card:nth-child(2) { transform: translate(4px, 4px); }
  .risk { width: var(--pile-w); height: 12px; margin-top: 8px; }
  .pile-label { font-size: 1.1rem; }

  /* the foot's padding: my portrait stands a little above its row, into the info's (1024×640) */
  .story { grid-area: status; display: flex; flex-direction: column; justify-content: center; align-items: flex-end; gap: 18px; min-height: 0; padding-bottom: 10px; }
  /* the boxes sit on the right, their text centred (Ernest, 2026-10-20) */
  .status { justify-content: flex-end; text-align: center; min-height: 0; padding: 0; font-size: clamp(1.12rem, 1.3vw, 1.4rem); line-height: 1.35; }
  .status > span { max-width: 19em; }
  /* a long effect (Laban Tayo!) on a short desktop ran under my cat and the hand: it scrolls in its space */
  .card-info {
    width: min(100%, 25em); margin: 0; padding: clamp(10px, 1.6vh, 16px) 18px clamp(10px, 1.6vh, 16px) 14px; gap: clamp(12px, 1.2vw, 18px);
    max-height: 100%; overflow-y: auto; overscroll-behavior: contain;
  }
  .card-info.more::after { bottom: calc(-1 * clamp(10px, 1.6vh, 16px)); margin: -20px -18px calc(-1 * clamp(10px, 1.6vh, 16px)) -14px; }
  .card-info.tip {
    display: block; width: auto; max-width: 19em; padding: 6px 14px; text-align: center;
    background: rgba(31, 22, 21, .84); border: 1.5px solid rgba(184, 70, 58, .55); box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
  }
  .card-info.tip .info-text { color: var(--muted); font-size: 1rem; }
  .info-card .card { --cw: clamp(44px, min(5vw, 7vh - 4px), 88px); }
  .info-name { font-size: clamp(1.2rem, min(1.5vw, 2.6vh), 1.7rem); }
  .info-text { font-size: clamp(1.02rem, min(1.25vw, 1.8vh + .2rem), 1.3rem); margin-top: 4px; }
  .info-how { font-size: clamp(.92rem, min(1.1vw, 1.6vh + .15rem), 1.15rem); margin-top: 6px; }
  .actions { grid-area: actions; flex-direction: column; flex-wrap: nowrap; align-items: flex-start; justify-content: center; gap: 12px; min-height: 0; padding: 0; }
  .actions .btn { min-height: 58px; font-size: 1.35rem; padding-inline: 30px; max-width: 100%; white-space: normal; } /* "Wala sa mat ang Pusang Mabait" ran off a 1024px screen */
  /* four moves in the column: smaller, or on a 640px-high screen they stood up into the cats' row */
  .actions:has(> :nth-child(4)) { gap: 6px; }
  .actions:has(> :nth-child(4)) .btn { min-height: 42px; font-size: 1.05rem; padding-inline: 20px; }

  .me { grid-area: me; --me-w: calc(var(--av) * 1.45 + 20px); display: grid; grid-template-columns: var(--me-w) minmax(0, 1fr) var(--me-w); align-items: end; }
  .me-tag { grid-column: 1; grid-row: 1; flex-direction: column; gap: 0; padding-bottom: 22px; }
  .me-tag .seat-avatar { width: calc(var(--av) * 1.1); }
  .me-heroname { margin-top: 6px; font-size: clamp(1.02rem, .68rem + .55vw, 1.4rem); }
  .me-name {
    max-width: var(--me-w); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: -10px; padding: 3px 16px;
    background: var(--bg); color: var(--text); border: 2px solid var(--ink); border-radius: 10px; transform: rotate(-3deg); box-shadow: none;
    font-family: var(--display); font-weight: 400; font-size: clamp(1.1rem, 1.3vw, 1.4rem); line-height: 1.2;
  }
  .me-tag.turn .me-name { background: var(--accent); color: var(--accent-ink); }
  .me-line { display: inline-flex; align-items: center; gap: 10px; margin-top: 6px; }
  .me-count { margin: 0; font-size: 1rem; }
  .me-count::before { content: none; }
  .hand { grid-column: 2; grid-row: 1; margin-top: 0; height: calc(var(--cw) * 1.4 + 30px); }
  .hand.two-rows { height: calc(var(--cw) * 1.4 + 30px + var(--raise)); }
  .hand .card { bottom: 12px; }

  /* dialogs, prompt and effects scale up with the table */
  .modal-box { width: min(620px, 100%); padding: 28px; }
  .modal-title { font-size: 2.1rem; }
  .modal-body { font-size: 1.08rem; }
  .rule-card { grid-template-columns: 84px 1fr; }
  .rule-card .card { --cw: 84px; }
  .rule-card .rule-name { font-size: 1.3rem; }
  .rule-card .rule-text { font-size: 1rem; }
  /* How to play is a landscape sheet: the steps on the left, the cards in two columns on the right, each
     side scrolling on its own under the fixed switch; the music credit joins Got it in the foot bar */
  .modal-box:has(.rules) { width: min(1240px, 100%); }
  .modal-box:has(.rules) .modal-title { margin-right: 76px; padding: 20px 0 16px 28px; }
  .rules-close { top: 16px; right: 18px; }
  .rules-steps { gap: 12px; }
  .rules-steps span { font-size: .92rem; line-height: 1.4; }
  .rules-sheet {
    display: grid; grid-template-columns: minmax(360px, 1fr) 1.7fr; grid-template-rows: minmax(0, 1fr) auto; /* wider than Sumasabog's: six steps, not five */
    grid-template-areas: "how deck" "credit foot";
  }
  .rules { display: contents; }
  .rules-how { grid-area: how; overflow: auto; overscroll-behavior: contain; padding: 22px 28px; }
  .rules-deck { grid-area: deck; display: flex; flex-direction: column; min-height: 0; padding: 22px 28px 0; border-left: 2px solid var(--edge); background: rgba(0, 0, 0, .12); }
  .rules-panels { flex: 1; min-height: 0; overflow: auto; overscroll-behavior: contain; margin-inline: -6px; padding: 0 6px 24px; }
  .rules .rules-credit { grid-area: credit; align-self: stretch; display: flex; align-items: center; padding: 10px 28px; border-top: 2px solid var(--edge); background: var(--raise); }
  .rules-foot { grid-area: foot; padding: 14px 28px; }
  .rule-cards { grid-template-columns: 1fr 1fr; gap: 12px; }
  .rule-card { grid-template-columns: 72px 1fr; align-items: start; }
  .rule-card .card { --cw: 72px; }
  .pick-grid { grid-template-columns: repeat(auto-fill, minmax(116px, 1fr)); gap: 14px; }
  .pick-grid .card { --cw: 116px; }
  .steal-fan { --cw: 112px; }
  .modal-cards .card { --cw: 150px; }
  /* Silipin ang Future: the cards you saw glow like the crystal ball (Ernest: a stronger glow on desktop) */
  .modal-cards .card { box-shadow: 0 0 0 3px #c9b0ff, 0 0 30px 10px rgba(160, 110, 255, .7), 0 0 70px 18px rgba(155, 231, 255, .3); }
  .modal-cards { padding: 18px 0 6px; }
  /* Silipin ×5: wide enough for all five cards in one row */
  .modal-box:has(.modal-cards > :nth-child(4)) { width: min(880px, 100%); }
  .card.big { --cw: 250px; }
  .card.big .card-text { font-size: 1rem; }
  .target { min-height: 72px; font-size: 1.15rem; }
  .target .seat-avatar { width: 58px; }
  /* over the hand, so the played card stays in view; wide enough for the Bard's three buttons in one row
     (two rows ran past the bottom of a 640px screen) */
  .nope-prompt { width: min(660px, calc(100vw - 32px)); padding: 22px; top: auto; bottom: 12px; transform: translateX(-50%); }
  .nope-what { font-size: 1.2rem; }
  .nope-row { flex-wrap: nowrap; }
  .nope-row .btn { flex: 0 1 auto; padding-inline: 24px; }
  .btn-nope, .nope-row .btn-nope { flex: 0 1 auto; font-size: 2.1rem; min-height: 74px; padding-inline: 40px; }
  .fx-banner { font-size: clamp(4rem, 6.5vw, 7.2rem); }
  .fx-stamp { font-size: 4.2rem; }
}
/* Bigger pop-ups on big screens (Ernest, 2026-10-20: "too small" on desktop; at 1920×1080 the Future cards
   were smaller than the hand's). zoom scales the whole box (text, cards, buttons, gaps) by --mz, so the
   limits that come from the screen are divided by it: the zoomed box still fits inside the screen. */
/* (A browser without zoom keeps --mz at 1, so its limits aren't shrunk for nothing.) */
.modal-box { --mz: 1; zoom: var(--mz); }
@media (min-width: 1024px) and (min-height: 640px) {
  .modal-box { width: min(620px, (100vw - 32px) / var(--mz)); max-height: calc((100dvh - 32px) / var(--mz)); }
  .modal-box:has(.rules) { width: min(1240px, (100vw - 32px) / var(--mz)); height: min(820px, (100dvh - 32px) / var(--mz)); max-height: none; }
  .modal-box:has(.modal-cards > :nth-child(4)) { width: min(880px, (100vw - 32px) / var(--mz)); }
}
@supports (zoom: 2) {
  @media (min-width: 1280px) and (min-height: 760px) { .modal-box { --mz: 1.15; } }
  @media (min-width: 1600px) and (min-height: 880px) { .modal-box { --mz: 1.3; } }
  @media (min-width: 1900px) and (min-height: 1000px) { .modal-box { --mz: 1.45; } }
  @media (min-width: 2400px) and (min-height: 1300px) { .modal-box { --mz: 1.8; } }
  /* How to play fills the screen anyway, so it stays a step smaller: its steps fit without scrolling */
  @media (min-width: 1280px) and (min-height: 760px) { .modal-box:has(.rules) { --mz: 1; } }
  @media (min-width: 1600px) and (min-height: 880px) { .modal-box:has(.rules) { --mz: 1.15; } }
  @media (min-width: 1900px) and (min-height: 1000px) { .modal-box:has(.rules) { --mz: 1.3; } }
  @media (min-width: 2400px) and (min-height: 1300px) { .modal-box:has(.rules) { --mz: 1.6; } }
}
/* A short desktop (1024×640): three full-size moves stood up into a two-line Markado pill above them */
@media (min-width: 1024px) and (min-height: 640px) and (max-height: 799px) {
  .actions { gap: 8px; }
  .seat-heroname { margin-bottom: 4px; }
  .seat-heroname .hero-mark { font-size: .9em; }
  .actions .btn { min-height: 46px; font-size: 1.2rem; padding-inline: 22px; }
  .actions:has(> :nth-child(4)) { gap: 5px; }
  .actions:has(> :nth-child(4)) .btn { min-height: 42px; font-size: 1.16rem; padding-inline: 20px; }
}
/* A small desktop (1024×640): the hero line with its mark made the middle seat's count stand on the deck */
@media (min-width: 1024px) and (max-width: 1279px) and (min-height: 640px) and (max-height: 799px) {
  .seat-heroname, .seats.many .seat-heroname { margin: -2px 0 1px; font-size: .88rem; }
  .seat-name { margin-bottom: 2px; }
  .seat-heroname .hero-mark { font-size: .78em; }
}
/* Tall desktops have room for the story and the card info together; shorter ones swap them like phones. */
@media (min-width: 1024px) and (min-height: 800px) {
  .game.has-info .status { display: flex; }
}
/* The small labels grow with the screen (Ernest, 2026-10-20: "some font sizes are too small" at 1920×1080).
   Each keeps its old size at 1024px and is about a fifth bigger at 1920px: card counts, the pile
   labels and the hover tip. */
@media (min-width: 1024px) and (min-height: 640px) {
  .seat-meta, .me-count, .card-info.tip .info-text { font-size: clamp(1rem, .75rem + .4vw, 1.3rem); }
  .seats.many .seat-meta { font-size: clamp(.9rem, .7rem + .3vw, 1.15rem); }
  .pile-label { font-size: clamp(1.1rem, .85rem + .4vw, 1.45rem); }
}
@media (max-height: 700px) and (max-width: 759px) {
  :root { --cw: clamp(58px, 15vw, 84px); }
  .seat-avatar { width: 42px; }
  /* a 10-player game with a two-row hand must still fit a 667px phone: the piles may shrink further,
     and the story line and the space under the hand get tighter */
  /* The card info used to grow up over the piles here, and a second row of buttons pushed my tag under
     them (Ernest, 2026-10-20: overlapping on phones). Now everything keeps its own space: the info sits
     in the story's row and the piles (the row's flexible 1fr) shrink to make room, down to ~.8 of a
     hand card; the seats and the info are a little tighter to leave them more. */
  .table {
    min-height: calc(var(--cw) * 1.12 + 56px); padding: 4px 0;
    --pw: clamp(calc(var(--cw) * .8), min(31vw, calc((100cqh - 56px) * 5 / 7), calc((100cqw - var(--note) - 2 * clamp(28px, 8vw, 80px)) / 2)), 168px);
  }
  .pile { gap: 4px; }
  .seats.many { row-gap: 3px; padding-top: 4px; }
  .seats.many .seat { padding: 2px 2px 4px; }
  .seats.many .seat-name, .seats.many .seat-meta { line-height: 1.2; }
  .status { min-height: 44px; }
  .bar { padding: 5px 0 2px; }
  .hand { height: calc(var(--cw) * 1.4 + 26px); }
  .hand.two-rows { height: calc(var(--cw) * 1.4 + 26px + var(--raise)); }
  .hand .card { bottom: 8px; }
  /* short phones: the card info keeps just the name and effect, run together, so it's two or three
     lines tall (five for a cat's long text). Past what the screen leaves it (the bar, a 10-player seat
     block, the smallest piles, a row of two-line moves and my hand take ~540px) it scrolls rather than
     push the hand off the bottom. */
  .info-card, .info-how { display: none; }
  .card-info { display: block; padding: 6px 12px; margin: 0 0 4px; max-height: max(64px, calc(100dvh - 545px)); overflow-y: auto; overscroll-behavior: contain; }
  /* a two-row hand is ~40px taller: the info gives that up (10 players, 14 cards and Tuyo's text ran 8px past 667) */
  .game:has(.hand.two-rows) .card-info { max-height: max(56px, calc(100dvh - 590px)); }
  .card-info.more::after { bottom: -6px; margin: -20px -12px -6px; }
  .info-name, .info-text { display: inline; }
  .info-name { font-size: 1rem; margin-right: .4em; }
  .info-text { font-size: .86rem; line-height: 1.22; }
}
/* ---------- phone landscape ----------
   The phone column is ~800px tall and put the deck and hand below the fold on a 390px-high screen.
   A small version of the desktop table instead: every cat in one row along the top, the story, piles
   and moves side by side in the middle, and my tag beside the hand at the bottom. Up to 639px, where the
   desktop table starts: a 1080x607 window (CrazyGames' tablet and small desktop sizes) got the phone column. */
@media (orientation: landscape) and (max-height: 639px) {
  :root { --cw: clamp(50px, 15vh, 80px); }
  .game.screen { max-width: none; padding-inline: max(16px, env(safe-area-inset-left)) max(16px, env(safe-area-inset-right)); }
  .game {
    min-height: 0;
    /* the story gets the wider side: a card's effect can run to 130 letters */
    grid-template-columns: minmax(0, 1.4fr) auto minmax(132px, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr) auto;
    grid-template-areas: "bar bar bar" "seats seats seats" "status table actions" "me me me";
    column-gap: clamp(12px, 2.4vw, 40px);
  }
  .bar { grid-area: bar; padding: 4px 0 2px; }

  /* all the cats in one row, small; a mark's pill sits on the portrait so the row never grows */
  .seats, .seats.many {
    grid-area: seats; --avw: clamp(28px, 8.5vh, 40px); flex-wrap: nowrap; justify-content: center; gap: 6px;
    max-width: none; padding-top: 2px;
  }
  .seats > .seat { flex: 0 1 104px; width: auto; padding: 3px 2px 4px; gap: 0; }
  .seats .seat-avatar, .seats.many .seat-avatar { width: var(--avw); }
  .seats .seat-name, .seats.many .seat-name { font-size: .78rem; line-height: 1.2; }
  .seats .seat-meta, .seats.many .seat-meta { font-size: .72rem; line-height: 1.2; }
  .seat-turns { font-size: .72rem; }

  /* not a size container here: its grid column is "auto", and containment would make that 0 wide.
     The piles get what the height leaves: the bar, the seat row and the hand take ~235px, the labels ~48px. */
  .table {
    grid-area: table; padding: 4px 0; gap: clamp(20px, 4vw, 44px); container-type: normal; min-height: 0;
    --pw: clamp(calc(var(--cw) * .95), calc((100dvh - 290px) / 1.4), 150px);
  }
  /* a two-row hand is taller by its raise (anim.js: max(40px, .42 of a card's height)), and the piles
     stood up into the cats' row: they give up that height */
  .game:has(.hand.two-rows) .table { --pw: clamp(calc(var(--cw) * .7), calc((100dvh - 290px - max(40px, var(--cw) * .59)) / 1.4), 150px); }
  .pile { gap: 4px; }
  .pile-label { font-size: .78rem; line-height: 1.2; white-space: normal; max-width: calc(var(--pw) + 40px); } /* "40 cards · Bomba: 23%" in two lines keeps the table narrow */

  /* the story on the left of the piles, the moves on their right */
  .story { grid-area: status; position: static; min-height: 0; display: flex; flex-direction: column; justify-content: center; align-items: flex-end; }
  /* the box on the right, its text centred like the desktop's (Ernest, 2026-10-20) */
  .status { min-height: 0; padding: 0; justify-content: flex-end; text-align: center; font-size: .92rem; }
  .card-info { position: static; width: min(100%, 22em); max-height: 100%; overflow: auto; margin: 0; padding: 6px 10px; box-shadow: none; }
  .info-card, .info-how { display: none; }
  .info-name { font-size: .98rem; }
  .info-text { font-size: .8rem; line-height: 1.22; }
  .actions { grid-area: actions; flex-direction: column; flex-wrap: nowrap; align-items: flex-start; justify-content: center; gap: 6px; min-height: 0; padding: 0; }
  .actions .btn { min-height: 44px; font-size: 1rem; padding-inline: 18px; max-width: 100%; white-space: normal; } /* "I-play: Silipin ang Future ×5" ran off the edge */
  /* three or four moves: two to a row (stacked, they stood up into the cats' row), "I-play" without the
     card's name (the info names it), and with three, "Mag-draw" across the bottom */
  .actions:has(> :nth-child(3)) { display: grid; grid-template-columns: repeat(2, minmax(0, auto)); align-content: center; justify-content: start; gap: 5px; }
  .actions:has(> :nth-child(3)) .btn { min-height: 36px; font-size: .84rem; padding-inline: 10px; line-height: 1.15; text-align: center; justify-content: center; }
  /* in Cinzel "PICKPOCKET" ran 22px into "RANSOM" beside it (check:ui, 2026-10-21) */
  .actions:has(> :nth-child(4)) .btn { font-size: .72rem; padding-inline: 4px; letter-spacing: 0; }
  .actions:has(> :nth-child(3)) .btn-more { display: none; }
  .actions:has(> :nth-child(3)):not(:has(> :nth-child(4))) .btn-primary { grid-column: 1 / -1; }

  /* my tag on the left of the hand, an empty column of the same width on its right to keep the hand centred */
  .me { grid-area: me; display: grid; grid-template-columns: 112px minmax(0, 1fr) 112px; align-items: end; }
  .me-tag { grid-column: 1; grid-row: 1; flex-direction: column; gap: 0; padding-bottom: 10px; font-size: .82rem; line-height: 1.2; text-align: center; }
  .me-tag .seat-avatar { width: 34px; }
  .me-name { max-width: 112px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .me-line { display: inline-flex; align-items: center; gap: 6px; }
  .me-count { margin: 0; }
  .me-count::before { content: none; }
  .me-tag .seat-turns { margin: 2px 0 0; }
  /* the column has no line to spare: the mark stands just left of the 34px portrait */
  .me-tag { position: relative; }
  .me-heroname { position: absolute; right: calc(50% + 21px); top: 6px; font-size: .78rem; }
  .me-heroname .hero-name { display: none; }
  .hand { grid-column: 2; grid-row: 1; margin-top: 0; height: calc(var(--cw) * 1.4 + 22px); }
  .hand.two-rows { height: calc(var(--cw) * 1.4 + 22px + var(--raise)); }
  .hand .card { bottom: 8px; }

  /* the Ayoko! prompt over the hand's top edge, so the played card stays in view */
  .nope-prompt { top: auto; bottom: 8px; transform: translateX(-50%); padding: 10px 14px; width: min(560px, calc(100vw - 32px)); }
  .nope-what { margin-bottom: 8px; }
  .btn-nope, .nope-row .btn-nope { font-size: 1.3rem; min-height: 50px; }
  /* room for all three in one row here, and two rows would cover the table */
  .nope-row { flex-wrap: nowrap; }
  .nope-row .btn, .nope-row .btn-nope { flex: 0 1 auto; }
}
