/* BuyOut UI layer. Direction: docs/DESIGN.md.
   Slate nameplate panels over the colourful board; identity motif = "block edge" (a hard
   darker bottom edge instead of soft shadows, like the board's blocks); corners 0–2 px;
   one accent (brass) for the main action and the "on turn" marker; player colours carry
   identity as thick plate frames. */

:root {
  --slate: #1f2a33;
  --slate-2: #283742;
  --slate-3: #33444f;
  --edge: #0f171c;
  --line: #3d4f5b;
  --text: #eef2f4;
  --text-2: #c3ced5;
  --text-3: #93a4af;
  --brass: #f2b632;
  --brass-edge: #a8780f;
  --brass-ink: #241a02;
  --angel: #9fc3d8;          /* angel deck: sky on card paper, never the brass accent */
  --angel-ink: #1f2a33;
  --devil: #b8282e;
  --good: #5fd39a;
  --bad: #ff7a72;
  --focus: #7fb8ff;
  /* achievement rarity (shared/profile.mjs TIERS): same hue as the plaque rims in js/badgeicons.js,
     each at least 4.5:1 on --slate and on an earned card (8 % tint over --slate-2) */
  --tier-1: #a9b8c2; --tier-2: #66c886; --tier-3: #6cbbe8; --tier-4: #bf9df5; --tier-5: #ff9a3c;

  --r: 2px;
  --edge-h: 4px;

  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px;

  --font-sign: 'Barlow Semi Condensed', 'Arial Narrow', system-ui, sans-serif;
  --font-body: 'Barlow', 'Segoe UI', system-ui, sans-serif;

  /* Notch and home bar (viewport-fit=cover in index.html): every edge-anchored panel adds these. */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  /* Phone held sideways: width of the left column with plates and status (game screen). */
  --side-w: 188px;
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
/* No pull-to-refresh, bounce or double-tap zoom anywhere; the canvas handles its own touch
   gestures (touch-action: none, scene/index.js). In the game a pinch on the HUD must not zoom the
   page either (pan-x pan-y: panels still scroll). Menus, lobby and their dialogs keep the browser's
   pinch zoom for people who need larger text. */
html { overscroll-behavior: none; }
body[data-screen=game] { touch-action: pan-x pan-y; }
body {
  background: #2c4a3f;
  color: var(--text);
  font: 500 15px/1.4 var(--font-body);
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: manipulation;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
}
[hidden] { display: none !important; }

/* Scrollbars (DESIGN "Scrollleisten"): thin square slate thumb on a see-through track, so the
   reserved gutter reads as part of the panel. Thumb 4.3:1 on --slate, 3.6:1 on --slate-2.
   Mouse screens only; touch screens keep their native overlay bars. Chrome ignores the
   ::-webkit-scrollbar rules once scrollbar-width/-color is set, so those two go to Firefox only. */
:root { --sb-thumb: #7a8f9c; --sb-thumb-hover: var(--text-3); }
@media (hover: hover) and (pointer: fine) {
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }
  ::-webkit-scrollbar-thumb { background: var(--sb-thumb) padding-box; border: 2px solid transparent; border-radius: 0; }
  ::-webkit-scrollbar-thumb:hover { background-color: var(--sb-thumb-hover); }
  @supports not selector(::-webkit-scrollbar) {
    * { scrollbar-width: thin; scrollbar-color: var(--sb-thumb) transparent; }
  }
}
/* Every panel that can switch between scrolling and not keeps the bar's room, so nothing moves
   sideways when it starts to scroll (no effect with overlay bars). Lists and dialogs keep it on the
   right; the small cards on the board, which mostly fit, on both edges so their insets stay even. */
.modal-body, .go-body, .sheet-body, .lobby-col, #friends-pop, .feed, .leaderboard, .plates-side,
.no3d, .testpanel { scrollbar-gutter: stable; }
.decide, .game-menu, .tut, .firsthint, .cardpop { scrollbar-gutter: stable both-edges; }

#scene { position: fixed; inset: 0; z-index: 0; }
#app { position: fixed; inset: 0; z-index: 1; pointer-events: none; }
.screen { position: absolute; inset: 0; pointer-events: none; }
.screen > * { pointer-events: auto; }

.boot {
  position: fixed; inset: 0; display: grid; place-items: center; z-index: 50;
  background: #2c4a3f; font: 700 26px var(--font-sign); color: var(--text-2);
  transition: opacity .4s;
}
.boot.done { opacity: 0; pointer-events: none; }

/* No 3D in this browser (js/ui/no3d.js): covers the empty table, above the boot screen. */
.no3d {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; overflow-y: auto;
  padding: calc(16px + var(--safe-t, 0px)) 16px calc(16px + var(--safe-b, 0px));
  background: #2c4a3f;
}
.no3d-card { width: min(480px, 100%); padding: 24px; display: grid; gap: 12px; }
.no3d-card h2 { font-size: 28px; }
.no3d-card p { margin: 0; }
.no3d-helps { font: 600 16px var(--font-sign); color: var(--text-2); padding-top: 4px; }
.no3d-tips { margin: 0; padding-left: 20px; display: grid; gap: 6px; color: var(--text-2); }
.no3d-foot { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; padding-top: 8px; }

h1, h2, h3 { font-family: var(--font-sign); font-weight: 700; margin: 0; line-height: 1.1; }
h1 { font-size: 56px; letter-spacing: .5px; }
h2 { font-size: 22px; }
h3 { font-size: 17px; font-weight: 600; }
p { margin: 0; }
.muted { color: var(--text-3); }
.small { font-size: 13px; }
.num { font-family: var(--font-sign); font-weight: 700; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ block motif */

.panel {
  background: var(--slate);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: 0 var(--edge-h) 0 var(--edge);
}

.icon { display: inline-flex; width: 18px; height: 18px; flex: none; }
.icon svg { width: 100%; height: 100%; }
/* Field mark in front of a line of text (Zwielicht in tooltip, help, lobby, hint, log). */
.kind-icon { width: 1.2em; height: 1.2em; vertical-align: -0.25em; margin-right: 0.3em; }
.check > .kind-icon { margin-right: 0; }

button, .btn {
  font: 600 16px var(--font-sign);
  letter-spacing: .2px;
  color: var(--text);
  background: var(--slate-3);
  border: 1px solid #4b5f6c;
  border-radius: var(--r);
  box-shadow: 0 3px 0 var(--edge);
  padding: 9px 16px;
  min-height: 44px;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  transition: background .1s, transform .06s, box-shadow .06s;
}
button:hover:not(:disabled) { background: #3d515e; }
button:active:not(:disabled) { transform: translateY(3px); box-shadow: 0 0 0 var(--edge); }
button:disabled { opacity: .4; cursor: not-allowed; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
/* Controls flush with the edge of a clipping panel draw the ring inside, so it is never cut off. */
.tabs button:focus-visible, .log-hide:focus-visible, .go-tabs button:focus-visible, .disclosure:focus-visible,
.status-plate .menu-btn:focus-visible, .hud-tools .menu-btn:focus-visible, .gm-item:focus-visible { outline-offset: -3px; }

.btn-primary { background: var(--brass); border-color: var(--brass-edge); color: var(--brass-ink); box-shadow: 0 3px 0 var(--brass-edge); }
.btn-primary:hover:not(:disabled) { background: #f7c452; }
.btn-danger { color: var(--bad); }
/* Secondary actions (Verlassen, Spielregeln, Überspringen ...): an outlined block with the same
   dark bottom edge and press-down as every button, so they read as buttons but stay below the
   filled default and the brass main action. */
.btn-ghost { background: transparent; border-color: #6b8292; color: var(--text); }
.btn-ghost:hover:not(:disabled) { background: var(--slate-3); border-color: #8197a5; }
.btn-big { font-size: 24px; font-weight: 700; padding: 12px 28px; min-height: 60px; box-shadow: 0 5px 0 var(--edge); }
.btn-big.btn-primary { box-shadow: 0 5px 0 var(--brass-edge); }
.btn-big:active:not(:disabled) { transform: translateY(5px); box-shadow: none; }
.btn-icon { padding: 0; width: 44px; min-width: 44px; }
.btn-icon .icon { width: 20px; height: 20px; }

input[type=text], select, textarea {
  font: 500 15px var(--font-body);
  color: var(--text);
  background: var(--edge);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 9px 12px;
  min-height: 44px;
  width: 100%;
}
input::placeholder { color: var(--text-3); opacity: 1; }
select option { background: var(--slate); }
label.field, div.field { display: grid; gap: var(--s1); font: 600 14px var(--font-sign); color: var(--text-2); }
.look-btn { flex: none; }
.check { display: flex; align-items: center; gap: var(--s2); font-size: 14px; cursor: pointer; min-height: 44px; color: var(--text-2); }
.check input { width: 20px; height: 20px; accent-color: var(--brass); }
.vol { display: grid; grid-template-columns: 72px minmax(0, 1fr) 48px; align-items: center; gap: var(--s3); min-height: 44px; font-size: 14px; color: var(--text-2); }
.vol input { width: 100%; min-height: 32px; margin: 0; accent-color: var(--brass); cursor: pointer; }
.vol-value { text-align: right; font-variant-numeric: tabular-nums; color: var(--text-3); }
.vol-note { grid-column: 2 / 4; }

/* ------------------------------------------------------------ menu + lobby sheet */

.sheet {
  position: absolute; top: var(--s4); bottom: calc(var(--s4) + var(--edge-h)); left: var(--s4);
  width: min(460px, calc(100vw - 32px));
  display: flex; flex-direction: column; overflow: hidden;
}
.sheet-body { overflow-y: auto; overflow-x: hidden; padding: var(--s5); display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); align-content: start; flex: 1; }
.section, .stack, .invite { display: grid; grid-template-columns: minmax(0, 1fr); }
.section { gap: var(--s3); }
.stack { gap: var(--s2); }
.sheet-foot { padding: var(--s3) var(--s5); border-top: 1px solid var(--line); background: var(--slate-2); display: flex; gap: var(--s3); align-items: center; }

.wordmark { font: 700 64px/0.9 var(--font-sign); letter-spacing: 1px; }
.wordmark img { display: block; width: min(300px, 70vw); height: auto; }
.tagline { color: var(--text-2); margin-top: var(--s3); font-size: 16px; }
/* Start menu groups: invisible wrappers (one column), side by side only on phones held sideways. */
.menu-main, .menu-side { display: contents; }

.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.row { display: flex; gap: var(--s2); align-items: center; }
.row > .grow, .grow { flex: 1; min-width: 0; }

.room-list { display: grid; gap: var(--s2); }
.room-item { display: flex; align-items: center; gap: var(--s3); padding: var(--s3); background: var(--slate-2); border: 1px solid var(--line); border-radius: var(--r); }
.room-item .name { font: 600 17px var(--font-sign); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Code in the top right corner, the button below it. */
.room-side { display: flex; flex-direction: column; align-items: flex-end; gap: var(--s1); align-self: stretch; justify-content: space-between; }
.room-code { font: 700 12px var(--font-sign); letter-spacing: 2px; color: var(--text-3); line-height: 1; }
.empty-note { color: var(--text-3); font-size: 14px; }
/* "Alle" + count at the right end of the room heading; opens the sortable list (ui/menu.js). */
.section-head:has(> .rooms-all:not([hidden])) { align-items: center; }
.section-head .rooms-all { display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px 4px 12px; font-size: 15px; }
.rooms-all-n { font: 700 13px var(--font-sign); min-width: 22px; padding: 1px 5px; text-align: center; background: var(--edge); border-radius: var(--r); }
@media (pointer: coarse) { .section-head .rooms-all { min-height: 40px; } }
.rooms-dialog .modal-body { gap: var(--s3); }

.code-chip { font: 700 18px var(--font-sign); letter-spacing: 3px; background: var(--edge); padding: 2px 10px; border-radius: var(--r); }
.invite { gap: var(--s2); padding: var(--s3); background: var(--slate-2); border: 1px solid var(--line); border-radius: var(--r); }
.invite-link { display: flex; gap: var(--s2); align-items: center; }
.invite-link code {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font: 13px ui-monospace, Consolas, monospace; background: var(--edge); padding: 12px 10px; border-radius: var(--r); color: var(--text-2);
}

.seats { display: grid; gap: var(--s2); }
/* A seat: one row with the player (a button when something can be done with it) and, once tapped,
   a strip with the actions under it. The muted-chat mark sits next to the row button (a button of its own). */
.seat {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; min-width: 0;
  background: var(--slate-2); border: 1px solid var(--line); border-radius: var(--r);
}
.seat-main {
  display: flex; align-items: center; gap: var(--s3); min-width: 0; min-height: 48px; padding: 4px 8px 4px 0;
  font: inherit; color: inherit; text-align: left; justify-content: flex-start;
  background: none; border: 0; border-radius: 0; box-shadow: none;
}
button.seat-main { cursor: pointer; }
button.seat-main:hover:not(:disabled) { background: #2f404c; }
button.seat-main:active:not(:disabled) { transform: none; box-shadow: none; }
button.seat-main:focus-visible { outline-offset: -3px; }
.seat .swatchblock { width: 10px; align-self: stretch; flex: none; }
.seat .who { flex: 1; min-width: 0; display: grid; }
.seat .who .name { font: 600 17px var(--font-sign); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seat .who .sub { font-size: 13px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seat .muted-mark { margin-right: 6px; }
.seat.me { border-color: #6b8292; }
/* picked: a light frame like the equipped item in the shop (brass stays the start button's) */
.seat.is-sel { border-color: var(--text); box-shadow: inset 0 0 0 1px var(--text); }
/* while a seat is picked, the places it can go to are dashed */
.seat.is-target { border-style: dashed; border-color: #8197a5; }
/* inside a target team only the block is dashed (a guest always sees the other teams as targets) */
.team-block.is-target .seat.is-target { border-style: solid; border-color: var(--line); }
.seat-acts {
  grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s2);
  padding: var(--s2) var(--s2) var(--s2) 18px; border-top: 1px solid var(--line); background: var(--slate);
}
.seat-acts > button { padding: 6px 12px; font-size: 15px; }
/* strength on its own line, then the team moves and "Entfernen" in one row */
.seat-acts .seg-field { order: -1; flex: 1 1 100%; }
.seat-remove { margin-left: auto; }
.seat-free {
  display: flex; align-items: center; min-height: 48px; padding: 0 var(--s3);
  font: 600 14px var(--font-sign); color: var(--text-3); border: 1px dashed var(--line); border-radius: var(--r);
}
.seat-tools { gap: var(--s2); }
/* Right end of a seat: the player's die and their figure, still (ui/seatlook.js); the slot keeps its
   width while the pictures load. */
.seat-look { flex: none; display: flex; align-items: flex-end; gap: 2px; margin-left: auto; }
.seat-look[hidden] { display: none; }
.seat-die { width: 18px; height: 18px; margin-bottom: 2px; }
.seat-die:not([src]) { visibility: hidden; }
.seat-fig {
  width: var(--fig); height: var(--fig);
  background: no-repeat center / contain;
}

/* A row of buttons for a short list of choices (lobby settings, team mode, bot strength): the
   checked one stays at the same height with its block edge, only lighter and with a light frame. */
.seg-field { display: grid; gap: 4px; min-width: 0; }
.seg-label { font-size: 13px; color: var(--text-2); }
.seg { display: flex; gap: 4px; min-width: 0; }
/* long labels ("Every player alone") wrap onto a second line instead of running out of the button */
.seg-btn { flex: 1 1 0; min-width: 0; padding: 6px 4px; font-size: 15px; line-height: 1.15; text-align: center; overflow-wrap: anywhere; }
.seg-btn[aria-checked=true] {
  background: #4b6474; border-color: var(--text); color: #fff;
}
.seg-btn[aria-checked=true]:hover { background: #4b6474; }
.seg-two { display: grid; line-height: 1.1; }
.seg-two small { font: 500 12px var(--font-body); color: var(--text-2); }
.seg-btn[aria-checked=true] .seg-two small { color: #e3e9ec; }

.swatches { display: flex; flex-wrap: wrap; gap: var(--s2); }
.swatch { width: 40px; min-width: 40px; height: 40px; min-height: 40px; padding: 0; border: 2px solid var(--edge); box-shadow: 0 3px 0 var(--edge); }
.swatch[aria-pressed=true] { outline: 3px solid var(--text); outline-offset: 2px; }
/* taken colours: struck through instead of just dimmed, so "belegt" reads clearly */
.swatch:disabled { opacity: .45; background-image: linear-gradient(45deg, transparent 45%, var(--edge) 45%, var(--edge) 55%, transparent 55%); }

.settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
.settings-grid .full { grid-column: 1 / -1; }

/* Lobby: one scrolling column by default; two columns on wide screens (see below). */
.lobby-body { padding: 0; gap: 0; }
.lobby-col { display: flex; flex-direction: column; gap: 20px; padding: 20px var(--s5); min-width: 0; }
.lobby-col + .lobby-col { padding-top: 0; }
.lobby-sheet .seat-main { min-height: 46px; }
/* eight colours in one row of up to 40 px cells that shrink instead of wrapping, so a column's
   scrollbar can no longer push the eighth colour into a second row */
.lobby-sheet .swatches { display: grid; grid-template-columns: repeat(8, minmax(0, 40px)); gap: 5px; }
.lobby-sheet .swatch { width: auto; min-width: 0; }

/* Game settings in four labelled blocks (Brett, Geld, Tempo, Regeln) split by hairlines. */
.lset-box { display: grid; gap: var(--s3); }
.lset { border: 0; margin: 0; padding: 0; min-width: 0; display: grid; gap: 6px; }
.lset + .lset { border-top: 1px solid var(--line); padding-top: var(--s3); }
.lset legend { float: left; width: 100%; padding: 0; margin-bottom: 6px; font: 700 17px var(--font-sign); color: var(--text); }
.lset .settings-grid { clear: both; row-gap: var(--s2); }
.lset-names { align-self: end; }
.lset-read { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px var(--s3); margin: 0; font-size: 15px; }
.lset-read dt { color: var(--text-2); }
.lset-read dd { margin: 0; font: 600 15px var(--font-sign); }
.lset-read .full { grid-column: 1 / -1; }
.lset-read ul { margin: 2px 0 0; padding-left: 18px; font: 400 14px var(--font-body); }
.teams-seg { margin-bottom: 2px; }
.lset-defaults { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); border-top: 1px solid var(--line); padding-top: var(--s3); }
.lobby-sheet .feed { max-height: 160px; min-height: 48px; }
.lobby-chat { display: flex; flex-direction: column; }
.lobby-chat .feed:empty::before { content: 'Noch keine Nachrichten.'; color: var(--text-3); }

/* Collapsible game settings: the whole bar is the button, the summary line sits under the title. */
.disclosure-head { font-size: inherit; }
.disclosure {
  width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s2);
  justify-content: stretch; text-align: left; padding: 8px 10px 8px 12px;
  background: var(--slate-2); border-color: var(--line);
}
.disclosure:hover:not(:disabled) { background: var(--slate-3); }
.disclosure-title { font: 700 22px/1.1 var(--font-sign); }
.disclosure-sum { grid-column: 1; font: 500 13px/1.35 var(--font-body); color: var(--text-3); text-wrap: balance; }
.disclosure-icon { grid-column: 2; grid-row: 1 / 3; align-self: center; transition: transform .15s; }
.disclosure[aria-expanded=true] .disclosure-icon { transform: rotate(180deg); }
.disclosure[aria-expanded=true] .disclosure-sum { display: none; }

@media (min-width: 1101px) {
  .lobby-sheet { width: min(820px, calc(100vw - 32px)); }
  /* the columns scroll and keep the bar's room themselves, so the body around them keeps none */
  .lobby-body { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); align-content: stretch; overflow: hidden; scrollbar-gutter: auto; }
  /* each column scrolls on its own; the chat takes the height left over */
  .lobby-col { overflow-y: auto; }
  .lobby-col + .lobby-col { padding-top: 20px; border-left: 1px solid var(--line); }
  .lobby-chat { flex: 1 1 0; min-height: 200px; }
  .lobby-chat .feed { flex: 1 1 0; max-height: none; }
}

/* Personal settings, top right on the menu and lobby screens. In the game the status plate has
   its own gear next to "Menü", so the nameplate in that corner keeps its place. */
#settings-btn { position: fixed; top: var(--s4); right: var(--s4); z-index: 20; }
#settings-btn .icon { width: 22px; height: 22px; }
body[data-screen=game] #settings-btn, body:not([data-screen]) #settings-btn { display: none; }
/* Profile button left of the gear (menu and lobby; the profile stays out of the game). */
#profile-btn { position: fixed; top: var(--s4); right: calc(var(--s4) + 44px + var(--s2)); z-index: 20; }
#profile-btn .icon { width: 22px; height: 22px; }
/* Incoming friend requests (ui/requestbadge.js): white on teufelsrot #b8282e (6.2:1), square like
   everything else, on the button's top-right corner and after the "Freunde" tab label. One pop when
   the count rises, none with reduced motion. */
.req-badge {
  min-width: 18px; height: 18px; padding: 0 4px; display: inline-grid; place-items: center;
  font: 700 12px/1 var(--font-sign); color: #fff; background: var(--devil);
  border: 1px solid var(--edge); border-radius: var(--r);
}
.req-badge[hidden] { display: none; }
#profile-btn .req-badge { position: absolute; top: -6px; right: -6px; pointer-events: none; }
.pf-tabs .has-req .req-badge { margin-left: 6px; }
.req-badge.pop { animation: req-pop .22s ease-out; }
@keyframes req-pop { 40% { transform: scale(1.3); } }
:root[data-motion="reduce"] .req-badge.pop { animation: none; }
body[data-screen=game] #profile-btn, body:not([data-screen]) #profile-btn { display: none; }
/* Language flags left of the gear (ui/langflags.js): flat plates, the active one on a brass bar. */
#lang-flags { position: fixed; top: var(--s4); right: calc(var(--s4) + 2 * (44px + var(--s2))); z-index: 20; display: flex; gap: 6px; }
body[data-screen=game] #lang-flags, body:not([data-screen]) #lang-flags { display: none; }
/* Quick sound switch, start menu only, right next to the gear; the flags move one slot left there. */
#sound-btn { position: fixed; top: var(--s4); right: calc(var(--s4) + 2 * (44px + var(--s2))); z-index: 20; display: none; }
body[data-screen=menu] #sound-btn { display: inline-flex; }
body[data-screen=menu] #lang-flags { right: calc(var(--s4) + 3 * (44px + var(--s2))); }
#sound-btn .icon { width: 22px; height: 22px; }
#sound-btn.is-off { border-color: var(--brass); color: var(--brass); }

/* "Freunde online" (ui/friendsbar.js): under the button row top right, as wide as three of its
   buttons, only in menu and lobby. The squares are friends' initials with a green block edge, the
   same green as "spielt gerade" in the profile. The panel opens below it; in a game the game menu
   opens the same list as a dialog. --tr-* follow the button row per layout (phones: 8 px, 6 px gaps). */
#friends-bar, #friends-pop { --tr-top: calc(var(--s4) + var(--safe-t)); --tr-right: calc(var(--s4) + var(--safe-r)); --tr-gap: var(--s2); }
#friends-bar {
  position: fixed; z-index: 20; top: calc(var(--tr-top) + 44px + 3px + var(--tr-gap)); right: var(--tr-right);
  min-width: calc(3 * 44px + 2 * var(--tr-gap)); padding: 0 6px 0 8px; gap: var(--s2); justify-content: flex-start;
  font-size: 15px;
}
#friends-bar[hidden], body[data-screen=game] :is(#friends-bar, #friends-pop), body:not([data-screen]) :is(#friends-bar, #friends-pop) { display: none; }
.fb-faces { display: flex; }
.fb-face {
  width: 20px; height: 20px; flex: none; display: grid; place-items: center; padding-bottom: 2px;
  font: 700 12px/1 var(--font-sign); color: var(--text); background: var(--slate);
  border: 1px solid var(--line); box-shadow: inset 0 -3px 0 var(--good);
}
.fb-faces .fb-face + .fb-face { margin-left: -5px; }
.fb-count { margin-left: auto; min-width: 24px; height: 24px; padding: 0 6px; display: grid; place-items: center; background: var(--slate); font: 700 15px/1 var(--font-sign); }
/* an invite waits: the count turns brass, the one main action of that moment is "Beitreten" */
#friends-bar.has-invite .fb-count { background: var(--brass); color: var(--brass-ink); }
#friends-pop {
  position: fixed; z-index: 21; top: calc(var(--tr-top) + 2 * (44px + 3px) + 2 * var(--tr-gap)); right: var(--tr-right);
  width: min(340px, calc(100vw - 2 * var(--tr-right)));
  max-height: calc(100dvh - var(--tr-top) - 2 * (44px + 3px) - 2 * var(--tr-gap) - 16px - var(--safe-b)); overflow-y: auto;
}
.friends-pop { padding: var(--s3); display: grid; gap: var(--s3); }
.fp-in-dialog { padding: 0; }
.fp-sec h3 { margin: 0 0 4px; font: 600 13px var(--font-sign); color: var(--text-3); }
.fp-n { color: var(--text-2); }
.fp-list { list-style: none; margin: 0; padding: 0; display: grid; }
.fp-row { display: grid; grid-template-columns: 20px minmax(0, 1fr) auto; gap: 6px 10px; align-items: center; padding: 6px 0; border-top: 1px solid var(--line); }
.fp-row:first-child { border-top: 0; }
.fp-who { min-width: 0; display: grid; }
.fp-who b { font: 600 16px var(--font-sign); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fp-who span { font-size: 13px; color: var(--text-2); }
.fp-acts { display: flex; gap: 6px; justify-content: flex-end; }
.fp-acts button { padding: 6px 12px; font-size: 15px; }
.fp-here { color: var(--good); font: 600 14px var(--font-sign); }
.fp-acts .fp-sent { background: transparent; border-color: transparent; box-shadow: none; color: var(--good); cursor: default; transform: none; }
.fp-ask { grid-column: 2 / -1; flex-wrap: wrap; align-items: center; justify-content: flex-start; }
.fp-ask span { flex-basis: 100%; font-size: 14px; color: var(--text-2); }
.fp-foot { display: flex; align-items: center; gap: var(--s2); }
.fp-all { margin-left: auto; }
/* phones: the panel spans the width under the button row */
@media (max-width: 420px) { #friends-pop { width: auto; left: calc(8px + var(--safe-l)); } }
.lang-flag { padding: 0; width: 44px; min-width: 44px; position: relative; }
.lang-flag .flag { display: block; width: 26px; height: 17px; box-shadow: 0 0 0 1px var(--edge), 0 2px 0 1px var(--edge); opacity: .4; filter: saturate(.4); transition: opacity .1s, filter .1s; }
.lang-flag .flag svg { display: block; width: 100%; height: 100%; }
.lang-flag:hover .flag { opacity: .8; filter: none; }
/* Active language: the flag in full colour inside a brass frame on a darker plate; the other one stays
   dimmed. A frame reads as "selected" at first sight, the old bar under the flag did not. */
.lang-flag[aria-checked=true] { background: var(--edge); border-color: var(--brass); box-shadow: inset 0 0 0 1px var(--brass), 0 3px 0 var(--edge); }
.lang-flag[aria-checked=true] .flag { opacity: 1; filter: none; }

/* ------------------------------------------------------------ feed (log + chat) */

.feed { overflow-y: auto; display: grid; gap: 3px; align-content: start; font-size: 14px; }
.feed-line { color: var(--text-2); overflow-wrap: anywhere; }
.feed-line .who { font-weight: 700; }
.feed-line.good { color: var(--good); }
.feed-line.bad { color: var(--bad); }
.feed-line.big { color: var(--text); font-weight: 700; }
.feed-line.turn { color: var(--text-3); font: 600 13px var(--font-sign); text-transform: none; border-top: 1px solid var(--line); margin-top: 6px; padding-top: 6px; }
.feed-line.system { color: var(--text-3); font-style: italic; }
.feed-line.removed { color: var(--text-3); font-style: italic; }
details.feed-line summary { cursor: pointer; list-style: none; }
details.feed-line summary::-webkit-details-marker { display: none; }
details.feed-line summary::after { content: ' Kartentext zeigen'; color: var(--text-3); font-size: 12px; text-decoration: underline; text-underline-offset: 2px; }
details.feed-line[open] summary::after { content: ''; }
.feed-detail { margin: 3px 0 4px; padding: 6px 8px; background: var(--slate-2); color: var(--text); font-size: 13px; border-left: 0; }
/* Muting in the chat (public/js/chatmute.js, ui/mutemenu.js). Someone else's name is a button that
   opens a small menu; it looks like the name, with a dark block behind it on hover and while its menu
   is open (the darkest panel tone, so every player colour keeps 4.5:1 there). On touch screens the whole line is the hit area (all chat lines a bit taller, so
   the hit areas do not overlap). */
.chat-msg { position: relative; }
.who-btn {
  display: inline; min-height: 0; padding: 0 2px; margin: 0 -2px; border: 0; border-radius: 0; box-shadow: none;
  background: transparent; font: inherit; font-weight: 700; letter-spacing: normal; cursor: pointer; transition: none;
}
.who-btn:hover:not(:disabled), .who-btn[aria-expanded=true] { background: var(--edge); }
.who-btn:active:not(:disabled) { transform: none; }
.who-btn:focus-visible { outline-offset: 1px; }
@media (pointer: coarse) {
  .chat-feed > .feed-line { padding-block: 5px; }
  .who-btn::after { content: ''; position: absolute; inset: -1px 0 -2px; }
}
/* The same name button on nameplates and in the end screen's ranking (ui/game.js whoButton): keeps the
   name's own font and colour and its ellipsis; the hit area stays on the name, not the whole plate. */
.name-btn { position: relative; max-width: 100%; color: inherit; font-weight: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.plate .name-btn { display: block; text-align: left; }
@media (pointer: coarse) {
  .name-btn { padding-block: 8px; margin-block: -8px; background-clip: content-box; }
  .name-btn::after { content: none; }
}
/* The menu at the name: a plain block in the panel colours, one entry per thing to do. */
.who-menu {
  position: fixed; z-index: 50; min-width: 200px; max-width: calc(100vw - 16px); padding: var(--s1);
  background: var(--slate); border: 1px solid var(--line); border-top: 3px solid var(--text-3); border-radius: var(--r);
}
.who-menu-item {
  width: 100%; justify-content: flex-start; text-align: left; gap: 10px; padding: 6px 8px;
  background: transparent; border-color: transparent; box-shadow: none; font-size: 16px;
}
.who-menu-item:hover:not(:disabled) { background: var(--slate-2); }
.who-menu-item:active:not(:disabled) { transform: none; }
.who-menu-item:focus-visible { outline-offset: -3px; }
.who-menu-item > .icon { color: var(--text-2); }
.who-menu-label { display: grid; line-height: 1.15; }
.who-menu-label small { font: 500 12px var(--font-body); color: var(--text-3); }
/* Below the chat: one quiet line per muted person, with a small button to show them again. Hidden
   with the chat (log tab). */
.mute-notes { display: grid; padding: 2px var(--s2) 0; }
.feed[hidden] + .mute-notes { display: none; }
.mute-note { display: flex; flex-wrap: wrap; align-items: center; gap: 0 6px; margin: 0; min-height: 30px; font-size: 13px; color: var(--text-3); }
.mute-undo {
  position: relative; min-height: 24px; padding: 0 8px; font: 600 13px var(--font-sign);
  color: var(--text-2); background: transparent; border-color: #6b8292; box-shadow: none;
}
.mute-undo:hover:not(:disabled) { background: var(--slate-3); color: var(--text); }
.mute-undo:active:not(:disabled) { transform: none; }
@media (pointer: coarse) {
  .mute-note { min-height: 44px; }
  .mute-undo::after { content: ''; position: absolute; inset: -10px -6px; }
}
/* Marker next to a muted person's name (lobby seats, nameplates); a click shows them again. */
.muted-mark {
  position: relative; display: inline-flex; vertical-align: -3px; width: 20px; min-width: 20px; height: 20px; min-height: 0;
  margin-left: 6px; padding: 0; color: var(--text-3); background: transparent; border: 0; box-shadow: none;
}
.muted-mark .icon { width: 16px; height: 16px; }
.muted-mark::after { content: ''; position: absolute; inset: -12px; }
.muted-mark:hover:not(:disabled) { color: var(--text); background: transparent; }
.muted-mark:active:not(:disabled) { transform: none; }
.plate .name.has-mute { display: flex; align-items: center; }
.plate .name.has-mute > span { overflow: hidden; text-overflow: ellipsis; }
.plate .name.has-mute .muted-mark { flex: none; margin-left: 4px; }
.chat-form { display: flex; gap: var(--s2); }
.chat-form input { min-height: 40px; }

/* ------------------------------------------------------------ nameplates */

.plate {
  position: absolute; width: 236px; height: 68px;
  display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto auto; column-gap: var(--s2);
  padding: 7px 10px 9px;
  background: var(--slate);
  border: 4px solid var(--pc);
  border-radius: var(--r);
  box-shadow: 0 var(--edge-h) 0 var(--edge);
}
.plate > * { min-width: 0; }
.plate .name { font: 600 17px/1.1 var(--font-sign); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plate .cash { grid-column: 1; font: 700 25px/1.05 var(--font-sign); font-variant-numeric: tabular-nums; white-space: nowrap; }
.plate .tags { grid-column: 2; grid-row: 1 / 3; display: flex; flex-direction: column; align-items: flex-end; justify-content: center; gap: 2px; color: var(--text-2); font: 600 13px var(--font-sign); }
.plate .tags .t { display: flex; align-items: center; gap: 3px; }
.plate .tags .icon { width: 15px; height: 15px; }
/* Status effects (ui/statusfx.js): one badge per effect, own icon and colour, corner counter. */
.plate .tags .fx { display: flex; gap: 5px; margin-top: 2px; }
.fx-btn, .fx-more, .fx-sum {
  position: relative; padding: 0; min-height: 0; min-width: 0; background: none; border: 0; box-shadow: none;
  border-radius: var(--r); color: inherit; display: inline-flex;
}
.fx-btn:hover:not(:disabled), .fx-sum:hover:not(:disabled) { background: none; }
.fx-btn:active:not(:disabled), .fx-more:active:not(:disabled), .fx-sum:active:not(:disabled) { transform: none; box-shadow: none; }
/* Larger hit area than the 22 px badge. */
.fx-btn::after, .fx-more::after, .fx-sum::after { content: ''; position: absolute; inset: -8px -3px; }
.fx-b { position: relative; display: grid; place-items: center; width: 22px; height: 22px; border-radius: var(--r); border: 1px solid var(--edge); }
.plate .tags .fx-b .icon, .fx-b .icon { width: 15px; height: 15px; }
.fx-b.tone-jail { background: var(--slate-3); color: var(--text); border-color: var(--text-3); }
.fx-b.tone-travel { background: var(--slate-2); color: var(--focus); border-color: var(--focus); }
.fx-b.tone-crown { background: var(--brass); color: var(--brass-ink); }
.fx-b.tone-angel { background: var(--angel); color: var(--angel-ink); }
.fx-b.tone-devil { background: var(--devil); color: #fff; }
.fx-b.tone-card { background: #fff4e0; color: var(--angel-ink); }
.fx-n {
  position: absolute; right: -6px; bottom: -6px; min-width: 14px; height: 14px; padding: 0 2px;
  font: 700 11px/14px var(--font-sign); font-style: normal; text-align: center;
  background: var(--edge); color: var(--text); border-radius: var(--r);
}
.fx-more { height: 22px; padding: 0 6px; align-items: center; font: 700 13px var(--font-sign); color: var(--text); background: var(--slate-3); border: 1px solid var(--line); }
.fx-more:hover:not(:disabled) { background: #3d515e; }
.fx-compact { display: none; }
/* Phones (strip or side column): one summary badge inside the plate, top right; the name leaves room. */
.plates-strip .plate .fx-compact, .plates-side .plate .fx-compact { display: block; position: absolute; top: 3px; right: 3px; }
.plates-strip .plate:has(.fx-compact) .name, .plates-side .plate:has(.fx-compact) .name { padding-right: 22px; }
.fx-compact .fx-b { width: 19px; height: 19px; }
.fx-compact .fx-b .icon { width: 13px; height: 13px; }
.fx-compact .fx-n { right: -3px; bottom: -5px; }
.fx-tip {
  position: fixed; z-index: 60; max-width: min(280px, calc(100vw - 16px)); padding: 8px 10px;
  display: grid; gap: 3px; font: 500 14px/1.35 var(--font-body); color: var(--text-2);
  border-top: 3px solid var(--text-3);
}
.fx-tip-name { font: 600 15px var(--font-sign); color: var(--text); }
.fx-tip-name.tone-crown { color: var(--brass); }
.fx-tip-name.tone-angel { color: var(--angel); }
.fx-tip-name.tone-devil { color: var(--bad); }
.fx-tip-left { color: var(--text); font-weight: 600; }
.fx-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.fx-list li { display: grid; grid-template-columns: 22px 1fr; gap: 10px; align-items: start; }
.fx-list b { color: var(--text); font-family: var(--font-sign); font-weight: 600; }
.plate .timer { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: var(--edge); }
.plate .timer > i { display: block; height: 100%; background: var(--brass); transform-origin: left; }
.plate.out { filter: grayscale(1); opacity: .55; }
.plate .cash.flash-good { color: var(--good); }
.plate .cash.flash-bad { color: var(--bad); }

/* "am Zug" marker: a brass bar under the plate plus an arrow toward the board. Deliberately
   not a frame: the frame carries the player colour, and yellow (#f2b705) is close to brass. */
.plate.active::before {
  content: ''; position: absolute; left: -4px; right: -4px; bottom: -15px; height: 4px; background: var(--brass);
}
/* lower corners: the bar sits on the board side, above the plate */
.plate.c-bl.active::before, .plate.c-br.active::before { bottom: auto; top: -11px; }
.plate.active::after {
  content: ''; position: absolute; top: 50%; margin-top: -12px; width: 0; height: 0;
  border-top: 12px solid transparent; border-bottom: 12px solid transparent;
}
.plate.c-tl.active::after, .plate.c-bl.active::after { right: -26px; border-left: 12px solid var(--brass); }
.plate.c-tr.active::after, .plate.c-br.active::after { left: -26px; border-right: 12px solid var(--brass); }

/* ------------------------------------------------------------ status + game menu */

.status-plate {
  position: absolute; top: var(--s4); left: 50%; transform: translateX(-50%); z-index: 18;
  /* fixed width: the menu button must not move when the status text changes */
  display: flex; flex-wrap: wrap; align-items: stretch; width: min(520px, calc(100vw - 560px));
}
/* Announced storm: a second row under the status line; the banner moves down by that row. */
.status-plate .storm-note {
  flex: 1 0 100%; display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 0;
  padding: 4px 12px; border-top: 1px solid var(--line); background: var(--slate-2);
  font: 600 15px var(--font-sign); color: var(--text-2); white-space: nowrap; overflow: hidden;
}
.status-plate .storm-note span:last-child { overflow: hidden; text-overflow: ellipsis; }
.status-plate .storm-note .icon { width: 16px; height: 16px; flex: none; }
.status-plate.storm ~ .banner { top: 114px; }
.status-plate .status { flex: 1; padding: 8px 16px; font: 600 18px var(--font-sign); white-space: nowrap; overflow: hidden; display: flex; align-items: center; justify-content: center; min-width: 0; }
.status-plate .status .txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.status-plate .round { color: var(--text-3); margin-right: 10px; }
.status-plate .menu-btn, .hud-tools .menu-btn {
  flex: none; border: 0; border-left: 1px solid var(--line); border-radius: 0; box-shadow: none;
  background: transparent; color: var(--text-2); padding: 0 14px 0 12px; gap: 6px;
}
.status-plate .menu-btn:hover:not(:disabled), .hud-tools .menu-btn:hover:not(:disabled) { background: var(--slate-2); color: var(--text); }
.status-plate .menu-btn:active:not(:disabled), .hud-tools .menu-btn:active:not(:disabled) { transform: none; }
.status-plate .menu-btn[aria-expanded=true], .hud-tools .menu-btn[aria-expanded=true] { background: var(--slate-2); color: var(--text); box-shadow: inset 0 -3px 0 var(--text); }
.status-plate .gear-btn, .hud-tools .gear-btn { width: 48px; padding: 0; }
.status-plate .gear-btn[aria-pressed=true], .hud-tools .gear-btn[aria-pressed=true] { background: var(--slate-2); color: var(--text); box-shadow: inset 0 -3px 0 var(--text); }
.status-plate .gear-btn .icon, .hud-tools .gear-btn .icon { width: 22px; height: 22px; }
/* Status bar switched off (in-game settings): phones keep the bar's buttons, right-aligned. */
.status-plate.bare { left: auto; }
.status-plate.bare .status, .status-plate.bare .storm-note { display: none; }
.status-plate.bare > .menu-btn:first-of-type { border-left: 0; }

/* Wide screens: button row right of the log panel, level with its top (GameView.layout). Only the
   gear normally; leaderboard and menu join it while the status bar is off. Same block motif and
   button look as the status plate, so it reads as the same family of controls. */
.hud-tools { position: absolute; z-index: 18; display: flex; align-items: stretch; height: 44px; }
.hud-tools > .menu-btn:first-child { border-left: 0; }
.hud-tools .game-menu { right: auto; left: -1px; }
/* A pinned leaderboard starts below that row, so the row's buttons never cover it. */
@media (min-width: 901px) and (orientation: landscape), (min-width: 1101px) {
  .screen .leaderboard { top: var(--lb-top, 84px); max-height: calc(100vh - var(--lb-top, 84px) - 36px); }
  /* With a decision open (300 px column on the right) stay centred unless that would slide under
     it; then move left just enough to clear it (only on narrower screens, e.g. 1024 px). Phones
     held sideways have their own layout below. */
  @media (min-height: 521px) {
    .screen:has(> .decide:not([hidden]):not(.autopilot-panel)) .leaderboard {
      left: 50%; right: auto; margin: 0;
      translate: max(calc(var(--s4) - 50vw), min(-50%, calc(50vw - 300px - 3 * var(--s4) - 100%)));
    }
  }
}

/* Own seat on autopilot: stands in for the decision panel at the same place. */
.autopilot-panel h2 { display: flex; align-items: center; gap: var(--s2); font-size: 26px; }
.autopilot-panel h2 .icon { width: 26px; height: 26px; }
.autopilot-panel .ap-text { display: grid; gap: var(--s1); }

/* The panel hangs off the plate's right edge: below it on desktop, above the bottom bar on phones. */
.game-menu {
  position: absolute; top: calc(100% + var(--edge-h) + 8px); right: -1px; width: 312px;
  max-height: calc(100vh - 100px); overflow-y: auto; padding: var(--s2); display: grid; gap: 2px;
}
/* Tile rows: icon over a short name, as many columns as tiles (--cols from GameMenu.render). */
.gm-viewrow { display: grid; grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr)); gap: 4px; padding-bottom: var(--edge-h); }
.gm-viewrow + .gm-viewrow { margin-top: 2px; }
.gm-view { flex-direction: column; gap: 2px; padding: 6px 2px; min-height: 54px; font-size: 13px; min-width: 0; }
.gm-view > span:not(.icon) { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Touch: the switch tiles three to a row on a 6-column grid; a short last row shares the width. */
.gm-tiles.thirds > * { grid-column: span 2; }
.gm-tiles.thirds.rest2 > :nth-last-child(-n+2) { grid-column: span 3; }
.gm-tiles.thirds.rest1 > :last-child { grid-column: span 6; }
/* A switch that is on and the chosen camera view: the lit tile. */
.gm-view[aria-pressed=true], .gm-view[aria-pressed=true]:hover:not(:disabled) { background: #4b6474; border-color: var(--text); color: #fff; }
/* Settings with the rules beside them, split by a hairline. */
.gm-pair { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: stretch; }
.gm-item.gm-side { width: auto; gap: 6px; padding: 6px 10px; font-size: 15px; border-left: 1px solid var(--line); border-radius: 0; }
.gm-toggles, .gm-more { display: contents; }
.gm-viewrow.five { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; }
.gm-viewrow.five .gm-view { font-size: 13px; padding: 6px 2px; min-height: 52px; }
.gm-item {
  width: 100%; justify-content: flex-start; text-align: left; gap: 10px; padding: 6px 8px;
  background: transparent; border-color: transparent; box-shadow: none; font-size: 17px;
}
.gm-item:hover:not(:disabled) { background: var(--slate-2); }
.gm-item:active:not(:disabled) { transform: none; }
.gm-item > .icon { color: var(--text-2); }
.gm-label { flex: 1; display: grid; line-height: 1.15; }
.gm-label small { font: 500 12px var(--font-body); color: var(--text-3); }
.gm-state { width: 20px; height: 20px; flex: none; border: 2px solid #5b707e; display: grid; place-items: center; }
.gm-state .icon { width: 14px; height: 14px; }
.gm-item[aria-pressed=true] .gm-state { background: var(--text); border-color: var(--text); color: var(--slate); }
.gm-item.danger, .gm-item.danger > .icon { color: var(--bad); }
.gm-sep { height: 1px; background: var(--line); margin: 6px 0; }

.banner {
  position: fixed; left: 50%; top: 84px; z-index: 14; transform: translate(-50%, -8px);
  padding: 10px 22px; font: 700 22px var(--font-sign); opacity: 0;
  transition: opacity .2s, transform .2s; pointer-events: none; text-align: center; max-width: calc(100vw - 32px);
  border-top: 4px solid var(--bc, var(--brass));
}
.banner.show { opacity: 1; transform: translate(-50%, 0); }

/* ------------------------------------------------------------ log drawer */

.logpanel {
  position: absolute; left: var(--s4); top: 120px; bottom: 124px; width: 290px;
  display: flex; flex-direction: column; overflow: hidden;
}
.logpanel-head { display: flex; border-bottom: 1px solid var(--line); }
.logpanel-head .tabs { flex: 1; border-bottom: 0; }
.log-hide { min-height: 40px; height: 40px; width: 44px; border: 0; border-left: 1px solid var(--line); border-radius: 0; box-shadow: none; background: transparent; color: var(--text-2); }
.log-hide:hover:not(:disabled) { background: var(--slate-2); color: var(--text); }
.log-hide:active:not(:disabled) { transform: none; }
/* Collapsed log: a short tab at the panel's place, so it is clear where the log went. */
.log-show { position: absolute; left: var(--s4); top: 120px; padding: 6px 12px; font-size: 15px; }
/* Collapsed log tab: same block as the gear row beside it (.hud-tools is a .panel). */
.log-show { height: 44px; background: var(--slate); border-color: var(--line); box-shadow: 0 var(--edge-h) 0 var(--edge); color: var(--text-2); }
.log-show:hover:not(:disabled) { background: var(--slate-2); color: var(--text); }
.tabs { display: flex; border-bottom: 1px solid var(--line); }
.tabs button { flex: 1; border: 0; border-radius: 0; background: transparent; box-shadow: none; min-height: 40px; font-size: 15px; color: var(--text-3); }
.tabs button[aria-selected=true] { color: var(--text); box-shadow: inset 0 -3px 0 var(--text); }
.tabs button:active { transform: none; }
.logpanel .feed { flex: 1; padding: var(--s3); }
.logpanel .chat-form { padding: var(--s2); border-top: 1px solid var(--line); }
.unread { background: var(--bad); color: var(--edge); font-size: 12px; padding: 0 6px; margin-left: 4px; border-radius: var(--r); }

/* ------------------------------------------------------------ decision panel */

.decide {
  position: absolute; right: var(--s4); top: 50%; transform: translateY(-50%);
  width: 300px; max-height: calc(100vh - 220px); overflow-y: auto;
  z-index: 17; /* above a pinned leaderboard: the current decision must stay clickable */
  padding: var(--s4); display: grid; gap: var(--s3);
}
.decide h2 { font-size: 30px; }
.decide .hint { color: var(--text-2); font-size: 14px; }
.decide .storm-hint { border-left: 3px solid var(--text-3); padding-left: 8px; }
.decide .tile-head { display: grid; gap: 2px; padding: 8px 10px; background: var(--slate-2); border-top: 6px solid var(--gc, var(--line)); }
.decide .tile-head .tn { font: 700 22px var(--font-sign); }
.decide .tile-head .tg { font-size: 13px; color: var(--text-3); }
.decide .rows { display: grid; gap: 6px; }
.decide .rowbtn { display: grid; grid-template-columns: 1fr auto; text-align: left; justify-content: stretch; padding: 8px 12px; min-height: 52px; }
.decide .rowbtn .l { font: 600 17px var(--font-sign); }
.decide .rowbtn .s { font: 500 13px var(--font-body); color: var(--text-2); grid-column: 1; }
.decide .rowbtn .r { grid-column: 2; grid-row: 1 / 3; align-self: center; font: 700 22px var(--font-sign); }
.decide .rowbtn.btn-primary .s { color: #4a3a10; }
/* A level listed for reference but not possible now (rule or money): flat with a dashed outline and
   no block edge, so it never reads as pressable; text stays at full opacity (>= 5.6:1 on the panel). */
.decide .rowbtn.off:disabled { opacity: 1; background: transparent; border-style: dashed; border-color: var(--line); box-shadow: none; color: var(--text-2); }
.decide .rowbtn.off .s, .decide .rowbtn.off .r { color: var(--text-3); }
/* Discounted price (ui/pricecut.js): old price struck through with a small angular tag, the new
   price below it (one line in the tile card). Bausparvertrag "−50 %", free upgrade "gratis". */
.price-cut { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 2px; line-height: 1.05; }
.price-cut.inline { flex-direction: row; align-items: center; gap: 6px; }
.price-cut .was { display: inline-flex; align-items: center; gap: 5px; font: 600 13px var(--font-body); color: var(--text-3); }
.price-cut s { text-decoration-thickness: 2px; }
.price-cut .cut-tag { font: 700 12px/1 var(--font-sign); letter-spacing: .02em; padding: 2px 5px 2px 6px; color: var(--brass-ink); background: var(--brass);
  clip-path: polygon(4px 0, 100% 0, 100% 100%, 0 100%, 0 4px); }
.price-cut .now { color: var(--good); }
.decide .rowbtn.btn-primary .price-cut .was { color: #4a3a10; }
.decide .rowbtn.btn-primary .price-cut .now { color: inherit; }
.decide .rowbtn.btn-primary .price-cut .cut-tag { color: var(--brass); background: var(--brass-ink); }
.decide .rowbtn.off .price-cut .now { color: inherit; }
.decide .rowbtn.off .price-cut .cut-tag { color: var(--text-2); background: var(--slate-3); }
/* Decision timer: a labelled row at the top of the panel, in the calm grey of the UI (brass
   belongs to the main action), red with "dann Autopilot" for the last seconds. */
.decide .deadline { display: grid; gap: 4px; margin-bottom: -4px; }
.deadline-head { display: flex; justify-content: space-between; gap: var(--s2); font: 600 14px var(--font-sign); color: var(--text-3); }
.deadline-s { color: var(--text-2); font-variant-numeric: tabular-nums; }
.deadline-bar { height: 3px; background: var(--edge); }
.deadline-bar > i { display: block; height: 100%; background: var(--text-3); transform-origin: left; transition: transform .1s linear; }
.decide .deadline.urgent .deadline-s, .decide .deadline.urgent .deadline-l { color: var(--bad); }
.decide .deadline.urgent .deadline-bar > i { background: var(--bad); }
.decide .deadline.paused .deadline-bar > i { background: var(--line); }
.decide .foot { display: flex; gap: var(--s2); }
.decide .foot > * { flex: 1; }
.decide select { min-height: 44px; }
.keyhint { text-align: center; color: var(--text-3); font-size: 13px; }
/* Hold to throw: the whole button fills from the left while held (darker brass behind the label),
   so the charge reads at a glance and never looks like the timer. touch-action/user-select keep a
   long press from scrolling or selecting on phones. */
.hold-roll { position: relative; isolation: isolate; overflow: hidden; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.hold-roll .power { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.hold-roll .power > i { display: block; height: 100%; background: rgba(36, 26, 2, .3); box-shadow: inset -4px 0 0 var(--brass-ink); transform: scaleX(0); transform-origin: left; }
.hold-roll.charging { background: #f7c452; }
@media (hover: none) { .keyhint { display: none; } }

/* ------------------------------------------------------------ leaderboard (Tab) */

.leaderboard {
  /* centred on the screen and as wide as its table; an open decision (z-index 17) stays on top */
  position: fixed; top: 84px; left: 0; right: 0; margin: 0 auto; z-index: 16;
  width: fit-content; min-width: min(560px, calc(100vw - 2 * var(--s4))); max-width: calc(100vw - 2 * var(--s4));
  max-height: calc(100vh - 120px); overflow: auto;
  padding: var(--s4) var(--s5) var(--s3);
}
.lb-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; margin-bottom: var(--s3); }
.lb-head h2 { font-size: 28px; }
.lb-round { font: 600 17px var(--font-sign); color: var(--text-2); font-variant-numeric: tabular-nums; }
.lb-table { width: 100%; border-collapse: collapse; }
.lb-table th, .lb-table td { padding: 8px 10px; text-align: right; border-bottom: 1px solid var(--line); white-space: nowrap; }
.lb-table thead th { font: 600 14px var(--font-sign); color: var(--text-3); }
.lb-table thead th:nth-child(2), .lb-table tbody th { text-align: left; }
.lb-table td { font: 600 17px var(--font-sign); color: var(--text-2); font-variant-numeric: tabular-nums; }
.lb-table td.big { font-size: 21px; font-weight: 700; color: var(--text); }
.lb-table td.rk { text-align: center; font: 700 22px var(--font-sign); color: var(--text); width: 36px; }
.lb-table tbody th .nm { display: flex; align-items: center; gap: var(--s2); font: 600 18px var(--font-sign); color: var(--text); }
.lb-table tbody th .sub { display: block; font: 500 12px var(--font-body); color: var(--text-3); margin-left: 22px; }
.lb-table .chip { width: 14px; height: 14px; flex: none; }
.lb-table .lb-shield { display: inline-flex; color: var(--text-2); }
.lb-table .lb-shield .icon { width: 16px; height: 16px; }
.lb-table .lb-crown { display: inline-flex; color: var(--brass); }
.lb-table .lb-crown .icon { width: 16px; height: 16px; }
.lb-table tr.me { background: var(--slate-2); }
.lb-table tr.out { opacity: .55; }

/* ------------------------------------------------------------ tooltip */

.tip { position: fixed; z-index: 20; pointer-events: none; width: min(240px, calc(100vw - 16px)); font-size: 14px; overflow: hidden; }
.tip .head { padding: 8px 12px; border-top: 8px solid var(--gc, var(--line)); background: var(--slate-2); }
.tip .head h3 { font-size: 21px; font-weight: 700; }
.tip .head .sub { font-size: 13px; color: var(--text-3); }
.tip .body { padding: 8px 12px 12px; display: grid; gap: 5px; }
.tip table { width: 100%; border-collapse: collapse; }
.tip td { padding: 1px 0; color: var(--text-2); }
.tip td:last-child { text-align: right; font: 700 15px var(--font-sign); }
.tip tr.cur td { color: var(--brass); }
.tip .kv { display: flex; justify-content: space-between; gap: var(--s2); color: var(--text-2); }
.tip .kv b { font: 700 15px var(--font-sign); color: var(--text); }
.tip .note { color: var(--text-3); font-size: 13px; }
/* Even lines instead of a lone last word; long German words break with a hyphen. */
.tip .body p, .tip .note { text-wrap: pretty; hyphens: auto; }
.tip .curse-note { color: #ffb4ad; border-top: 2px solid #b8282e; padding-top: 6px; }
.tip .shield-note { color: var(--text-2); border-top: 2px solid var(--brass); padding-top: 6px; }
.tip .hot-note { color: var(--text-2); }
.tip .hot-note b { color: var(--brass); font-weight: 700; }
.tip .storm-note { color: var(--text-2); border-top: 2px solid var(--text-3); padding-top: 6px; }
/* Own debt menu: the sale this tile brings, first line of the card, set off below. */
.tip .tip-sale { color: var(--text); font-weight: 600; border-bottom: 2px solid var(--good); padding-bottom: 6px; }
.tip .tip-sale b { color: var(--good); font-size: 17px; }

/* ------------------------------------------------------------ event card */

.cardpop {
  position: fixed; left: 50%; top: 45%; z-index: 15; width: 300px;
  transform: translate(-50%, -40%); opacity: 0; transition: opacity .2s, transform .25s;
  pointer-events: none; text-align: center; padding: 0 0 var(--s5);
}
.cardpop.show { opacity: 1; transform: translate(-50%, -50%); }
/* After the 3D draw the popup grows out of the card that flew at the camera, instead of sliding in. */
.cardpop.from-draw { transform: translate(-50%, -50%) scale(.55); transition: opacity .12s, transform .3s cubic-bezier(.2, .9, .3, 1.15); }
.cardpop.from-draw.show { transform: translate(-50%, -50%) scale(1); }
/* another player's card: small, in the decision column instead of over the board */
.cardpop.side { left: auto; right: var(--s4); width: 240px; transform: translateY(-40%); }
.cardpop.side.show { transform: translateY(-50%); }
.cardpop.side h2 { font-size: 22px; }
.cardpop .deck { padding: 10px; font: 700 20px var(--font-sign); letter-spacing: 1px; margin-bottom: var(--s3); }
.cardpop .art { padding: 0 var(--s4) var(--s2); }
.cardpop .art svg { display: block; width: 100%; height: auto; }
.cardpop.angel .deck { background: var(--angel); color: var(--angel-ink); }
.cardpop.devil .deck { background: #b8282e; color: #fff; }
.cardpop.fusion .deck { background: #d89a3a; color: var(--angel-ink); border-bottom: 4px solid #b8282e; }
.cardpop h2 { font-size: 28px; padding: 0 var(--s4); }
.cardpop p { color: var(--text-2); padding: var(--s2) var(--s5) 0; }
.cardpop .who { margin-top: var(--s3); font-size: 13px; color: var(--text-3); }

/* ------------------------------------------------------------ tutorial */

/* Calm step panel at the bottom centre, between the lower nameplates. Brass only marks the current step dot. */
.tut {
  position: absolute; left: 50%; bottom: calc(20px + var(--edge-h)); transform: translateX(-50%); z-index: 16;
  width: min(440px, calc(100vw - 32px)); padding: var(--s3) var(--s4) var(--s3); display: grid; gap: var(--s2);
  border-top: 4px solid var(--text-2);
}
.tut-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.tut-count { font: 600 13px var(--font-sign); color: var(--text-3); }
.tut-dots { display: flex; gap: 4px; }
.tut-dots i { width: 8px; height: 8px; background: var(--slate-3); }
.tut-dots i.done { background: var(--text-3); }
.tut-dots i.cur { background: var(--brass); }
.tut h2 { font-size: 24px; }
.tut p { color: var(--text-2); font-size: 15px; }
.tut .tut-wait { color: var(--text-3); font-size: 13px; }
.tut .tut-bonus { display: flex; align-items: flex-start; gap: var(--s2); font-weight: 600; }
.tut .tut-bonus .icon { width: 18px; height: 18px; margin-top: 1px; }
/* Funken line in the end screen's footer, with the spark (dom.js icon 'spark'). */
.go-award { display: inline-flex; align-items: center; gap: 6px; }
.go-award .icon { width: 16px; height: 16px; }
/* For guests the line is a link to the sign-in that keeps the game (main.js saveWithAccount). */
.go-award-link { font: inherit; letter-spacing: 0; color: var(--brass); background: none; border: 0; box-shadow: none;
  padding: 4px 0; min-height: 32px; text-decoration: underline; text-underline-offset: 3px; }
.go-award-link:hover:not(:disabled) { background: none; color: #ffd36b; }
.go-award-link:active:not(:disabled) { transform: none; }
/* End-of-game window for guests (ui/profile.js askConsentDialog): the game's Funken big, the account
   button on its own row, the two consent answers side by side and alike. */
.consent-coins { display: flex; align-items: center; gap: var(--s2); margin: 0 0 var(--s2);
  font: 700 34px/1 var(--font-sign); color: var(--brass); font-variant-numeric: tabular-nums; }
.consent-coins .icon { width: 30px; height: 30px; }
.modal-foot.consent-foot { display: grid; grid-template-columns: 1fr 1fr; }
.consent-foot > .btn-primary { grid-column: 1 / -1; }
@media (max-width: 560px) { .modal-foot.consent-foot { grid-template-columns: 1fr; } }
.tut .tut-bonus.muted { font-weight: 400; color: var(--text-3); font-size: 13px; }
.tut-foot { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s1); }
/* Out of the way while a drawn card is on screen (the card is centred in the same free area). */
.tut.aside { opacity: 0; pointer-events: none; transition: opacity .2s; }
/* HUD pointer (ui/tutpointer.js): brass arrow with the slate block edge, tip at the element's
   origin, and a square brass frame around the target. Never takes clicks. */
.tut-arrow { position: fixed; left: 0; top: 0; z-index: 19; width: 0; height: 0; pointer-events: none; transform-origin: 0 0; }
.tut-arrow[hidden], .tut-ring[hidden] { display: none; }
.tut-arrow-bob { position: absolute; left: -44px; top: -13px; width: 44px; height: 26px; animation: tut-nudge 1.1s ease-in-out infinite; }
.tut-arrow svg { display: block; overflow: visible; filter: drop-shadow(0 3px 0 var(--edge)); }
.tut-arrow polygon { fill: var(--brass); stroke: var(--slate); stroke-width: 2.5; stroke-linejoin: miter; }
.tut-ring { position: fixed; z-index: 19; pointer-events: none; border: 2px solid var(--brass); box-shadow: 0 0 0 2px var(--slate); }
@keyframes tut-nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-6px); } }
:root[data-motion="reduce"] .tut-arrow-bob { animation: none; }
.tut-hint { display: grid; gap: var(--s2); padding: var(--s3); background: var(--slate-2); border-top: 4px solid var(--text-3); }
/* Start menu: way back into a seat this device or account still holds (ui/menu.js showResume). */
.resume-slot[hidden] { display: none; }
.resume { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); background: var(--slate-2); border-left: 4px solid var(--brass); }
.resume .grow { display: grid; gap: 4px; min-width: 0; }

/* First-time note on a rule (crown, lamps, taxes, hotspots): bottom centre like the tutorial panel,
   which never shows at the same time (tutorial rooms skip these notes). */
.firsthint {
  position: absolute; left: 50%; bottom: calc(20px + var(--edge-h)); transform: translateX(-50%); z-index: 16;
  width: min(420px, calc(100vw - 32px)); padding: var(--s3) var(--s4); display: grid; gap: var(--s2);
  border-top: 4px solid var(--text-3);
}
.firsthint p { color: var(--text); font-size: 15px; }
.firsthint-kicker { font: 600 12px var(--font-sign); letter-spacing: .6px; text-transform: uppercase; color: var(--text-3); }
.tut-hint p { color: var(--text-2); font-size: 14px; }
.legal a { color: var(--text-2); }
.legal a:hover { color: var(--text); }

/* Start menu footer: buttons, then a quiet line with legal links and the version. */
.menu-foot { flex-direction: column; align-items: stretch; gap: var(--s2); padding-bottom: var(--s2); }
.menu-foot-btns { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); }
.menu-foot-meta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 var(--s4); }
.menu-foot-meta .legal { display: flex; flex-wrap: wrap; gap: 0 var(--s4); }
.menu-foot-meta .legal a, .menu-foot-meta .muted { display: inline-flex; align-items: center; min-height: 28px; }
/* The version number is a button that opens the changelog; it keeps the look of the quiet line. */
.menu-foot-meta .version-link { display: inline-flex; align-items: center; min-height: 28px; padding: 0; border: 0; background: none; box-shadow: none; font: inherit; letter-spacing: inherit; color: var(--text-3); text-underline-offset: 3px; cursor: pointer; }
.menu-foot-meta .version-link:hover:not(:disabled) { background: none; color: var(--text); text-decoration: underline; }
.menu-foot-meta .version-link:active:not(:disabled) { transform: none; }
/* Touch: 44 px to hit, the negative margin keeps the line as tall as before. */
@media (hover: none) { .menu-foot-meta .version-link { min-height: 44px; margin-block: -8px; } }

/* Changelog dialog: one block per version, newest first; the body scrolls. */
.changes .changes-sum { margin: 0; }
.changes .changes-ver { display: grid; gap: var(--s1); }
.changes .changes-ver h3 { margin: 0; display: flex; align-items: baseline; gap: var(--s2); font-size: 18px; }
.changes .changes-ver time { font-size: 13px; font-weight: 400; }

/* ------------------------------------------------------------ card piles: hint + overview */

.pile-tip { position: fixed; z-index: 20; pointer-events: none; padding: 7px 10px; font-size: 14px; color: var(--text-2); max-width: 260px; border-top: 4px solid var(--angel); }
.pile-tip.devil { border-top-color: #b8282e; }
.pile-tip b { color: var(--text); font-family: var(--font-sign); font-size: 15px; }

.deck-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); gap: var(--s3); }
.deck-card { display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: var(--s3); align-items: start; padding: var(--s3); background: var(--slate-2); border-top: 4px solid var(--angel); }
.deck-overview.devil .deck-card { border-top-color: #b8282e; }
.deck-list.fusion .deck-card { border-top-color: #d89a3a; }
.deck-fusion { margin-top: var(--s5); }
.deck-fusion > h3 { font: 700 22px var(--font-sign); }
.deck-fusion > p { margin: 2px 0 var(--s3); }
.deck-card .art svg { display: block; width: 100%; height: auto; }
.deck-card .top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); }
.deck-card h3 { font-size: 18px; min-width: 0; hyphens: auto; overflow-wrap: break-word; }
.deck-card .rare { margin-left: 8px; font: 600 12px var(--font-sign); letter-spacing: 0.04em; text-transform: uppercase; opacity: 0.7; vertical-align: middle; }
.deck-card .chance { flex: none; font: 700 18px var(--font-sign); font-variant-numeric: tabular-nums; }
.deck-card p { color: var(--text-2); font-size: 14px; margin-top: 2px; }

/* ------------------------------------------------------------ game over + stats */

.gameover { position: fixed; inset: 0; z-index: 30; display: grid; place-items: center; background: rgba(10, 16, 20, .55); padding: var(--s4); }
/* Fixed height (as tall as the screen allows): the numbers table is taller than the standings, so a
   panel sized to its tab grew and moved its tabs when switching. */
.gameover > .panel { width: min(980px, 100%); height: min(900px, calc(100vh - 32px)); max-height: calc(100vh - 32px); display: flex; flex-direction: column; overflow: hidden; }
.go-head { padding: var(--s5) var(--s5) 0; display: grid; gap: var(--s2); flex: none; }
.go-head h1 { font-size: 46px; }
.go-head .winner-name { color: var(--wc); }
.go-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--line); padding: 0 var(--s5); margin-top: var(--s3); flex: none; }
.go-tabs button { border: 0; border-radius: 0; background: transparent; box-shadow: none; color: var(--text-3); font-size: 17px; }
.go-tabs button[aria-selected=true] { color: var(--text); box-shadow: inset 0 -4px 0 var(--brass); }
.go-tabs button:active { transform: none; }
.go-body { overflow: auto; padding: var(--s5); flex: 1; }
.go-foot { padding: var(--s3) var(--s5); border-top: 1px solid var(--line); background: var(--slate-2); display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; flex: none; }

.ranking { display: grid; gap: 6px; }
.ranking .r { display: grid; grid-template-columns: 44px 1fr auto auto; gap: var(--s3); align-items: center; padding: 8px 12px; background: var(--slate-2); border: 1px solid var(--line); border-radius: var(--r); }
.ranking .place { font: 700 26px var(--font-sign); text-align: center; }
.ranking .r.first .place { color: var(--brass); }
.ranking .nm { font: 600 19px var(--font-sign); display: flex; align-items: center; gap: var(--s2); }
.ranking .chip { width: 14px; height: 14px; flex: none; }
.ranking .num { font-size: 20px; }

.stat-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.stat-table th, .stat-table td { padding: 7px 10px; text-align: right; border-bottom: 1px solid var(--line); white-space: nowrap; }
.stat-table th:first-child, .stat-table td:first-child { text-align: left; color: var(--text-2); white-space: normal; }
.stat-table thead th { font: 600 16px var(--font-sign); border-bottom: 4px solid var(--pc, var(--line)); vertical-align: bottom; }
.stat-table td { font: 600 16px var(--font-sign); font-variant-numeric: tabular-nums; color: var(--text-2); }
.stat-table td.top { color: var(--text); font-weight: 700; text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px; }
.stat-table tbody th { text-align: left; color: var(--text-2); font-weight: 500; padding: 7px 10px; border-bottom: 1px solid var(--line); }
.stat-table .team-start { border-left: 2px solid var(--line); }
.stat-table td.team-cell { text-align: left; }   /* under the first member; the cell spans the whole team */
.stat-table tr.team-row th { font: 600 13px var(--font-sign); color: var(--text-3); text-align: center; border-bottom: 0; padding-bottom: 0; }
.stat-table tr.group td { color: var(--text-3); font: 600 13px var(--font-sign); text-align: left; border-bottom: 0; padding-top: 16px; }
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--s3); margin-bottom: var(--s5); }
.fact { background: var(--slate-2); padding: var(--s3); border-top: 4px solid var(--fc, var(--line)); }
.fact .k { color: var(--text-3); font-size: 13px; }
.fact .v { font: 700 22px var(--font-sign); }
.fact .d { color: var(--text-2); font-size: 13px; }

.chart-wrap { display: grid; gap: var(--s3); }
.chart-wrap svg { width: 100%; height: auto; display: block; }
.chart-legend { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); font: 600 15px var(--font-sign); }
.chart-legend span { display: inline-flex; align-items: center; gap: 6px; }
.chart-legend i { width: 18px; height: 4px; display: inline-block; }
.chart-tip { position: fixed; pointer-events: none; z-index: 35; padding: 8px 10px; font-size: 13px; min-width: 150px; }
.chart-tip .rh { font: 700 15px var(--font-sign); margin-bottom: 4px; }
.chart-tip .rl { display: flex; justify-content: space-between; gap: 12px; }

/* ------------------------------------------------------------ modal + toasts */

.modal-back { position: fixed; inset: 0; z-index: 40; background: rgba(10, 16, 20, .55); display: grid; place-items: center; padding: var(--s4); }
.modal { width: min(640px, 100%); max-height: calc(100vh - 32px); display: flex; flex-direction: column; overflow: hidden; }
.modal-head { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s3) var(--s3) var(--s5); border-bottom: 1px solid var(--line); flex: none; }
.modal-head h2 { flex: 1; font-size: 26px; }
.modal-body { overflow-y: auto; padding: var(--s5); display: grid; gap: var(--s4); }
.modal-foot { padding: var(--s3) var(--s5); border-top: 1px solid var(--line); display: flex; gap: var(--s2); flex-wrap: wrap; justify-content: flex-end; background: var(--slate-2); flex: none; }

/* Settings dialog: one row per group, the label in a narrow left column like a form on a game box,
   rows split by hairlines, so sound, view, look and profile read as separate blocks. */
.set .modal-body { gap: 0; padding-top: var(--s2); padding-bottom: var(--s2); }
.set-group { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: var(--s4); padding: var(--s4) 0; }
.set-group + .set-group { border-top: 1px solid var(--line); }
.set-group h3 { font-size: 19px; padding-top: 11px; color: var(--text); }
.set-body { display: grid; gap: var(--s2); min-width: 0; }
.set-line { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s3); }
.set-value { font: 600 17px var(--font-sign); color: var(--text-2); }
/* Phones: the label column stays (narrower) instead of a heading row per group, rows and gaps are
   tighter and the "Fertig" bar goes, so the whole dialog fits a phone without scrolling; only very
   short screens (a small phone with the browser's bars) scroll its body, as one block. */
@media (max-width: 560px) {
  .set .modal-body { padding-top: var(--s1); padding-bottom: var(--s1); }
  .set-group { grid-template-columns: 70px minmax(0, 1fr); gap: var(--s2); padding: 6px 0; }
  .set-group h3 { font-size: 16px; padding-top: 13px; overflow-wrap: anywhere; }
  .set-body { gap: 0; }
  .set-body .stack { gap: 0; }
  .set-value { font-size: 15px; }
  .set .vol { grid-template-columns: 58px minmax(0, 1fr) 40px; gap: var(--s2); }
  .set .muted.small { font-size: 13px; }
  .set .choice-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .set .modal-head h2 { font-size: 21px; }
  .set .modal-foot { display: none; }   /* the close button in the head does the same as "Fertig" */
}
/* Short phones (SE, or a phone with the browser's bars, also sideways): the explanations under a switch go. */
@media (max-height: 400px) and (orientation: landscape) {
  /* (selectors one step stronger: the sideways block further down sets the same properties) */
  .set .muted.small { display: none; }
  .set .set-group { padding: 2px 0; }
  .modal-back.modal-back { padding-top: calc(4px + var(--safe-t)); padding-bottom: calc(4px + var(--safe-b)); }
  .modal.modal { max-height: calc(100dvh - 8px - var(--safe-t) - var(--safe-b)); }
  .set.modal .modal-body { padding-top: 0; padding-bottom: 0; }
  #screen-menu .tut-hint { padding: 6px 10px; }
  #screen-menu .tut-hint p { font-size: 12.5px; line-height: 1.3; }
  #screen-menu .section h2 { font-size: 15px; }
  .menu-main.menu-main, .menu-side.menu-side { gap: 6px; }
}
/* Very short (sideways with browser bars, or an SE upright in the browser): switches in rows of two. */
@media (max-height: 400px) and (orientation: landscape), (max-width: 560px) and (max-height: 600px) {
  /* three or more switches in a row of two (the in-game "Anzeige") */
  .set .stack:has(> label.check:nth-child(3)) { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s2); }
  /* sound: "Ton an" and "Musik an" side by side above the two sliders */
  .set .stack:has(> .vol) { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s2); }
  .set .stack:has(> .vol) > .check { grid-row: 1; grid-column: 1; }
  .set .stack:has(> .vol) > .stack { display: contents; }
  .set .stack:has(> .vol) .vol { grid-column: 1 / -1; }
  .set .stack:has(> .vol) > .stack > .check { grid-row: 1; grid-column: 2; }
}
@media (max-width: 560px) and (max-height: 700px) {
  .set .muted.small { display: none; }
  .set-group { padding: 3px 0; }
}
/* iPhone SE in the browser (about 548 px tall): a slimmer head keeps the dialog from scrolling */
@media (max-width: 560px) and (max-height: 600px) {
  .set .modal-head { padding-block: var(--s1); }
}
@media (max-width: 330px) {
  .set-group { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }
  .set-group h3 { padding-top: 0; }
}

.choice-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: var(--s2); }
.choice { justify-content: flex-start; gap: var(--s2); }
.choice[aria-checked=true] { background: var(--text); color: var(--slate); border-color: var(--text); box-shadow: 0 3px 0 var(--text-3); }
/* the generic button hover (slate) must not turn the chosen option dark-on-dark */
.choice[aria-checked=true]:hover:not(:disabled) { background: #d5dee3; border-color: #d5dee3; }
.choice .chip { width: 14px; height: 14px; border: 1px solid var(--edge); flex: none; }

.look-preview { gap: var(--s2); }
.look-stage { position: relative; height: 220px; overflow: hidden; background: var(--edge); border: 1px solid var(--line); display: grid; place-items: center; }
/* absolutely placed so the renderer's drawing size never feeds back into the layout */
.look-canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.look-preview.unavailable .look-stage { height: auto; }
.look-note { padding: var(--s3); text-align: center; }

/* "Figur & Würfel" (ui/look.js): preview on the left, tabs with item tiles on the right; one column
   on phones. Tiles keep the block edge of buttons; equipped = solid light frame, tried on = dashed. */
.shop-layout { display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 1fr); gap: var(--s4); align-items: start; }
.shop .look-preview { position: sticky; top: 0; }
.shop .look-stage { height: 260px; }
.shop-side { display: grid; gap: var(--s2); min-width: 0; }
.shop-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s3); min-height: 44px; }
.shop-head:empty { display: none; }
.shop-coins { display: inline-flex; align-items: center; gap: var(--s2); margin: 0; }
.shop-coins .icon { width: 28px; height: 28px; }
.shop-coins b { font: 700 30px/1 var(--font-sign); font-variant-numeric: tabular-nums; }
.shop-guest { display: flex; align-items: center; gap: var(--s2); margin: 0; flex: 1 1 180px; color: var(--text-2); font-size: 15px; }
.shop-guest .icon { width: 20px; height: 20px; flex: none; }
/* the running trial: name plus "Test beenden"; dashed left edge like a tried-on tile */
.shop-trial-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--s2) var(--s3); flex: 1 1 220px; }
.shop-trial-head p { margin: 0 auto 0 0; padding-left: var(--s2); border-left: 2px dashed var(--text-2); font: 600 15px/1.2 var(--font-sign); }
.shop-tabs { padding: 0; margin-top: 0; overflow-x: auto; }
.shop-tabs button { flex: 0 0 auto; padding-inline: 12px; }
.shop-panel { display: grid; gap: var(--s2); padding-top: var(--s2); }
.shop-panel h3 { font-size: 16px; color: var(--text-2); margin-top: var(--s1); }
.shop-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: var(--s2); }
.shop-grid > li { display: grid; }
.shop-tile {
  display: grid; grid-template-rows: auto auto 1fr; justify-items: center; align-content: start; gap: 4px;
  padding: 8px 6px 6px; min-height: 116px; background: var(--slate-2); border: 1px solid var(--line);
}
.shop-tile.is-on { border: 2px solid var(--text); padding: 7px 5px 5px; }
/* Würfel: colour row and two texture rows plus the open bar fit a 768 px high window without scrolling */
.shop-panel[data-tab=dice] .shop-tile { min-height: 0; gap: 2px; padding-top: 6px; }
.shop-panel[data-tab=dice] .shop-tile.is-on { padding-top: 5px; }
.shop-panel[data-tab=dice] .shop-art:is([data-kind=diceColor], [data-kind=diceTexture]) { width: 40px; height: 40px; margin: 2px; }
.shop-panel[data-tab=dice] h3 { margin-top: 0; }
.shop-tile.is-tried { outline: 2px dashed var(--text-2); outline-offset: -5px; }
.shop-name { font: 600 15px/1.15 var(--font-sign); text-align: center; }
/* every tile has a foot line of one height, also empty, so equipping never changes the row height */
.shop-foot { align-self: end; display: inline-flex; align-items: center; gap: 3px; min-height: 16px; font: 600 13px/16px var(--font-sign); color: var(--text-3); font-variant-numeric: tabular-nums; }
.shop-foot .icon { width: 13px; height: 13px; }
.shop-foot.is-on { color: var(--text); }
/* The bar opens by height (0fr → 1fr) and fades in, so the grid above never jumps; reduced motion: fade only. */
.shop-panel { gap: 0; }
.shop-grids { display: grid; gap: var(--s2); }
.shop-bar { display: grid; grid-template-rows: 0fr; opacity: 0; visibility: hidden; transition: grid-template-rows .2s ease, opacity .2s ease, visibility 0s .2s; }
.shop-bar.is-open { grid-template-rows: 1fr; opacity: 1; visibility: visible; transition: grid-template-rows .2s ease, opacity .2s ease; }
.shop-bar-in { min-height: 0; overflow: hidden; }
.shop-bar-in > * { margin: 0; }
.shop-bar-in > :first-child { margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--line); }
.shop-bar-in > * + * { margin-top: var(--s2); }
:root[data-motion="reduce"] .shop-bar { transition: opacity .18s ease, visibility .18s !important; }
.shop-bar-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s3); }
.shop-bar-text { display: grid; gap: 2px; min-width: 0; color: var(--text-2); }
.shop-bar-text b { font: 700 19px/1.15 var(--font-sign); color: var(--text); }
.shop-price { display: inline-flex; align-items: center; gap: 4px; font: 600 16px var(--font-sign); color: var(--text); }
.shop-price .icon, .shop-bar .btn-primary .icon { width: 18px; height: 18px; }
.shop-short { font-size: 14px; }
.shop-bar-btns { display: flex; flex-wrap: wrap; gap: var(--s2); padding: 2px; }
.shop-trial-line { font-size: 14px; }
.shop-note { margin: 0; font-size: 14px; color: var(--text-2); }
.shop-note.is-bad { color: var(--bad); }

/* Item pictures until Karten & 3D provides real ones (itemPreview in scene/preview.js). */
.shop-art { position: relative; display: grid; place-items: center; width: 56px; height: 56px; background: var(--edge); overflow: hidden; }
.shop-art.has-art { background: transparent; }
.shop-art > img { width: 100%; height: 100%; object-fit: contain; }
.shop-tile.is-locked .shop-art:not(.has-art) { opacity: .8; }
.shop-art[data-kind=figure]:not(.has-art) { display: none; }
.shop-art[data-kind=figure].has-art { width: 72px; height: 72px; margin: -6px 0 -4px; }
.shop-tile:has(.shop-art[data-kind=figure]:not(.has-art)) { min-height: 72px; align-content: center; }
.shop-tile:has(.shop-art[data-kind=figure]:not(.has-art)) .shop-name { font-size: 17px; }
.shop-art:is([data-kind=diceColor], [data-kind=diceTexture]) {
  width: 46px; height: 46px; margin: 5px; border-radius: 3px; --pip: #1f2a33;
  background: var(--die, #f4ecd8); box-shadow: inset 0 -5px 0 rgb(0 0 0 / .25), 0 0 0 1px var(--edge);
}
.shop-art:is([data-kind=diceColor], [data-kind=diceTexture]) i { position: absolute; width: 8px; height: 8px; background: var(--pip); }
.shop-art:is([data-kind=diceColor], [data-kind=diceTexture]) i:nth-child(1) { left: 8px; top: 7px; }
.shop-art:is([data-kind=diceColor], [data-kind=diceTexture]) i:nth-child(2) { left: 19px; top: 17px; }
.shop-art:is([data-kind=diceColor], [data-kind=diceTexture]) i:nth-child(3) { left: 30px; top: 27px; }
.shop-art[data-kind=diceColor][data-id=player] { --die: var(--pc); --pip: #fff; }
.shop-art[data-kind=diceColor][data-id=white] { --die: #f4f1ea; }
.shop-art[data-kind=diceColor][data-id=black] { --die: #23292e; --pip: #eef2f4; }
.shop-art[data-kind=diceTexture][data-id=smooth] { --die: #f4ecd8; }
.shop-art[data-kind=diceTexture][data-id=wood] { --die: repeating-linear-gradient(100deg, #a0703f 0 5px, #8d5f33 5px 7px, #b07d49 7px 11px); }
.shop-art[data-kind=diceTexture][data-id=slate] { --die: linear-gradient(160deg, #46555f, #2d3a43); --pip: #eef2f4; }
.shop-art[data-kind=diceTexture][data-id=ivory] { --die: linear-gradient(170deg, #fbf4e2, #e6d8b6); }
.shop-art[data-kind=diceTexture][data-id=marble] { --die: linear-gradient(125deg, transparent 40%, #9aa3a8 41% 43%, transparent 44% 62%, #b7bec2 63% 64%, transparent 65%), #f2f2ee; }
.shop-art[data-kind=diceTexture][data-id=glass] { --die: linear-gradient(150deg, rgb(220 240 250 / .9), rgb(140 190 215 / .55)); --pip: #24495c; }
.shop-art[data-kind=diceTexture][data-id=gold] { --die: linear-gradient(150deg, #ffe08a, #e2a12a 55%, #a8780f); --pip: #3a2a05; }
.shop-art:is([data-kind=diceEffect], [data-kind=trail]) { background: var(--fx, var(--edge)); }
.shop-art:is([data-kind=diceEffect], [data-kind=trail])[data-id=none] { --fx: repeating-linear-gradient(135deg, var(--edge) 0 6px, var(--slate-3) 6px 8px); }
.shop-art[data-id=sparks] { --fx: radial-gradient(circle at 30% 30%, #ffd98a 2px, transparent 3px), radial-gradient(circle at 70% 40%, #ff9a3c 2px, transparent 3px), radial-gradient(circle at 45% 70%, #ffb347 3px, transparent 4px), radial-gradient(circle at 50% 50%, rgb(255 154 60 / .35), transparent 65%), var(--edge); }
.shop-art[data-id=lava] { --fx: radial-gradient(circle at 50% 110%, #ffd98a 0 12%, #ff9a3c 25%, #d4541f 45%, #5a1a0a 75%); }
.shop-art[data-id=frost] { --fx: radial-gradient(circle at 50% 50%, #f4fbff 0 10%, #b9def0 30%, #5b8fa8 60%, #1d3440 85%); }
.shop-art[data-id=confetti] { --fx: linear-gradient(30deg, transparent 45%, #e5484d 45% 55%, transparent 55%) 6px 8px / 16px 16px, linear-gradient(-40deg, transparent 45%, #f2b632 45% 55%, transparent 55%) 0 0 / 14px 14px, linear-gradient(80deg, transparent 45%, #5fd39a 45% 55%, transparent 55%) 3px 2px / 12px 18px, var(--edge); }
.shop-art[data-id=dust] { --fx: linear-gradient(90deg, transparent 5%, rgb(214 196 160 / .25) 30%, rgb(214 196 160 / .85) 85%), var(--edge); }
.shop-art[data-id=embers] { --fx: radial-gradient(circle at 80% 50%, #ffd98a 3px, transparent 4px), radial-gradient(circle at 55% 40%, #ff9a3c 2px, transparent 3px), radial-gradient(circle at 35% 60%, #d4541f 2px, transparent 3px), linear-gradient(90deg, transparent, rgb(232 105 42 / .5)), var(--edge); }
.shop-art[data-id=stardust] { --fx: radial-gradient(circle at 80% 50%, #fff 2px, transparent 3px), radial-gradient(circle at 58% 35%, #e6dcff 1.5px, transparent 2.5px), radial-gradient(circle at 40% 62%, #bf9df5 1.5px, transparent 2.5px), radial-gradient(circle at 22% 45%, #8f74c9 1px, transparent 2px), linear-gradient(90deg, transparent, rgb(191 157 245 / .4)), var(--edge); }
@media (max-width: 720px) {
  .shop-layout { grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
  /* the preview stays in sight while the tiles scroll under it, so a try-on is visible */
  .shop .look-preview {
    z-index: 2; top: calc(-1 * var(--s4)); margin-top: calc(-1 * var(--s4)); padding: var(--s4) 0 var(--s2);
    background: var(--slate); box-shadow: 0 1px 0 var(--line);
  }
  .shop .look-stage { height: 150px; }
  .shop .modal-body { padding-top: var(--s4); }
  .shop-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
  /* four dice per row from 375 px on: colours in one row, textures in two */
  .shop-panel[data-tab=dice] .shop-grid { grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); }
  /* "Ausgerüstet" does not fit a 75 px die tile: the check and the frame say it (the label names it) */
  .shop-panel[data-tab=dice] .shop-foot-text { display: none; }
  .shop-tile { min-height: 108px; }
}
/* phone held sideways: two columns stay, the preview shrinks to fit the short screen */
@media (max-height: 520px) and (orientation: landscape) {
  .shop-layout { grid-template-columns: minmax(0, 220px) minmax(0, 1fr); }
  .shop .look-stage { height: 140px; }
}

.preset-group { display: grid; gap: var(--s2); padding: var(--s3); background: var(--slate-2); border-top: 6px solid var(--gc, var(--line)); }
.preset-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--s2); }

.help h3 { margin-top: var(--s2); font-size: 20px; }
.help ul { margin: 0; padding-left: 20px; display: grid; gap: 4px; color: var(--text-2); }
.help li p + p { margin-top: 4px; }

/* Game description (index.html #about, same text search engines read). In the game only the start
   menu's "Über das Spiel" dialog shows a copy of it (ui/about.js); without JavaScript css/noscript.css
   makes it the page. */
#about { display: none; }
.about-text h2 { margin-top: var(--s2); font-size: 20px; }
.about-text p { margin: 0; color: var(--text-2); }

/* One notification stack for messages, errors and achievements, always bottom right, newest at
   the bottom. CSS picks the column per layout (clear of sheets and side columns); dom.js
   liftToasts() sets --toast-lift so the stack rests on top of whatever sits below it in that
   column (stale-server note, consent card, decision sheet, status bar, dialog foot). */
#toasts {
  position: fixed; z-index: 60; right: calc(var(--s4) + var(--safe-r));
  bottom: calc(var(--s4) + var(--edge-h) + var(--safe-b) + var(--toast-lift, 0px));
  width: min(360px, calc(100vw - 32px - var(--safe-l) - var(--safe-r)));
  display: grid; gap: var(--s2); justify-items: end; align-content: end;
  pointer-events: none; transition: bottom .15s ease-out;
}
#toasts > :has(button, a) { pointer-events: auto; } /* only toasts with controls take taps */
@media (min-width: 901px) and (orientation: landscape), (min-width: 1101px) {
  /* game: left of the right column (decision panel over the bottom-right nameplates) */
  body[data-screen=game] #toasts { right: calc(var(--s4) + 300px + var(--s4) + var(--safe-r)); width: min(360px, calc(100vw - 600px)); }
  /* no plate in the bottom-right corner (fewer than three players): the corner is the stack's */
  body[data-screen=game][data-br-free] #toasts { right: calc(var(--s4) + var(--safe-r)); width: min(360px, calc(100vw - 32px - var(--safe-l) - var(--safe-r))); }
}
.toast {
  max-width: 100%; padding: 10px 16px; background: var(--slate-3); color: var(--text); font-size: 15px;
  border-radius: var(--r); border-top: 4px solid var(--text-3); box-shadow: 0 3px 0 var(--edge);
  animation: toast-in .18s ease-out; transition: opacity .18s ease-in, transform .18s ease-in;
}
.toast-error { border-top-color: var(--bad); }
:is(.toast, .badge-toast).out { opacity: 0; transform: translateY(8px); }
/* rises from the bottom edge the stack sits on */
@keyframes toast-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
:root[data-motion="reduce"] #toasts { transition: none; }
:root[data-motion="reduce"] :is(.toast, .badge-toast) { animation: none; transition: opacity .18s; }
:root[data-motion="reduce"] :is(.toast, .badge-toast).out { transform: none; }
/* Invite (ui/friendsbar.js): green top edge like "online", two buttons, waits a minute */
.invite-card {
  display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: var(--s2) 10px; align-items: center;
  width: min(320px, 100%); padding: 10px 12px 12px;
  background: var(--slate); border: 1px solid var(--line); border-top: 4px solid var(--good); border-radius: var(--r);
  box-shadow: 0 var(--edge-h) 0 var(--edge);
  animation: toast-in .18s ease-out; transition: opacity .18s ease-in, transform .18s ease-in;
}
.ic-text b { font: 600 17px var(--font-sign); }
.ic-acts { grid-column: 1 / -1; display: flex; gap: var(--s2); }
.ic-acts button { flex: 1; }
.invite-card.out { opacity: 0; transform: translateY(8px); }
/* the open friends list shows the same invite with its buttons: no second copy on top of it */
body:is(:has(.fp-dialog), :has(#friends-pop:not([hidden]))) .invite-card { display: none; }
:root[data-motion="reduce"] .invite-card { animation: none; transition: opacity .18s; }
:root[data-motion="reduce"] .invite-card.out { transform: none; }
@media (max-width: 900px), (orientation: portrait) and (max-width: 1100px) { .invite-card { width: auto; } }
.conn-lost { position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%); z-index: 55; background: #8f1f22; color: #fff; padding: 8px 14px; border-radius: var(--r); font-size: 15px; box-shadow: 0 3px 0 var(--edge); }

/* "Server veraltet": closable, below dialogs and the game-over sheet (z 30/40), and placed
   where no buttons sit: right of the menu/lobby sheet, between the lower nameplates in game. */
#stale-bar {
  position: fixed; right: var(--s4); bottom: calc(20px + var(--edge-h)); z-index: 25;
  width: min(400px, calc(100vw - 508px)); display: flex; align-items: flex-start; gap: var(--s2);
  padding: 8px 6px 8px 14px; background: #8f1f22; color: #fff; font-size: 14px;
  border-radius: var(--r); box-shadow: 0 3px 0 var(--edge);
}
#stale-bar p { flex: 1; padding-top: 3px; }
#stale-bar button { width: 36px; min-width: 36px; min-height: 36px; background: transparent; border-color: transparent; box-shadow: none; color: #fff; }
#stale-bar button:hover:not(:disabled) { background: rgba(0, 0, 0, .2); }
#stale-bar .btn-reload { width: auto; padding: 0 12px; border-color: rgba(255, 255, 255, .6); font-weight: 700; }
#stale-bar[data-kind^="new:"] { background: #1f4f8f; }
body[data-screen=game] #stale-bar { right: auto; left: 50%; transform: translateX(-50%); width: min(440px, calc(100vw - 536px)); }
/* the tutorial panel owns the bottom centre: move up under the status plate */
body[data-screen=game]:has(.tut) #stale-bar { bottom: auto; top: 76px; }

/* ------------------------------------------------------------ responsive */

@media (max-width: 1180px) {
  .plate { width: 200px; }
  .plate .cash { font-size: 22px; }
  .status-plate { width: min(520px, calc(100vw - 460px)); }
  .status-plate .round { display: none; }
}

@media (max-width: 900px), (orientation: portrait) and (max-width: 1100px) {
  h1 { font-size: 40px; }
  .wordmark { font-size: 48px; }
  .sheet { top: auto; left: 0; right: 0; bottom: 0; width: 100%; height: 62vh; height: 62dvh; }
  /* Phone start menu: smaller logo and tighter padding, so name, "Figur & Würfel" and the main
     button fit above the fold of the bottom sheet; the three secondary buttons share one row. */
  .sheet-body:not(.lobby-body) { padding: var(--s4) var(--s4) var(--s5); gap: var(--s4); }
  .lobby-col { padding: var(--s4); gap: var(--s4); }
  .lobby-col + .lobby-col { padding-top: 0; }
  .sheet-foot { padding: var(--s2) var(--s4) calc(var(--s2) + var(--safe-b)); }
  .wordmark img { width: min(200px, 56vw); }
  .tagline { margin-top: var(--s2); font-size: 15px; }
  .menu-foot-btns { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .menu-foot-btns button { padding-left: 6px; padding-right: 6px; }
  .menu-foot-btns .icon { display: none; }
  .small { font-size: 14px; }
  /* compact strip: colour frame, shortened name, cash; four plates fit a 360 px phone */
  .plates-strip { position: absolute; top: calc(8px + var(--safe-t)); left: calc(8px + var(--safe-l)); right: calc(8px + var(--safe-r)); display: flex; gap: 4px; overflow-x: auto; padding-bottom: 12px; }
  .plates-strip .plate { position: relative; flex: 1 1 0; min-width: 78px; width: auto; height: 48px; left: auto !important; right: auto !important; top: auto !important; bottom: auto !important; padding: 3px 6px 5px; border-width: 3px; grid-template-columns: minmax(0, 1fr); }
  .plates-strip .plate .name { font-size: 14px; }
  .plates-strip .plate .cash { font-size: 16px; }
  .plates-strip .plate .tags { display: none; }
  .plates-strip .plate.active::before { left: -3px; right: -3px; top: auto; bottom: -11px; }
  .plate.active::after { display: none; }
  .status-plate { top: auto; bottom: calc(8px + var(--safe-b)); left: calc(8px + var(--safe-l)); right: calc(8px + var(--safe-r)); transform: none; width: auto; max-width: none; }
  .leaderboard { top: calc(72px + var(--safe-t)); left: calc(8px + var(--safe-l)); right: calc(8px + var(--safe-r)); width: auto; min-width: 0; max-width: none; max-height: calc(100vh - 140px); max-height: calc(100dvh - 140px - var(--safe-t) - var(--safe-b)); }
  #stale-bar, body[data-screen=game] #stale-bar { top: calc(8px + var(--safe-t)); bottom: auto; left: calc(8px + var(--safe-l)); right: calc(8px + var(--safe-r)); width: auto; transform: none; }
  body[data-screen=game] #stale-bar { top: calc(72px + var(--safe-t)); }
  body:not([data-screen=game]) #stale-bar { right: calc(68px + var(--safe-r)); } /* leaves the settings gear free */
  #settings-btn { top: calc(8px + var(--safe-t)); right: calc(8px + var(--safe-r)); }
  #profile-btn { top: calc(8px + var(--safe-t)); right: calc(8px + 44px + 6px + var(--safe-r)); }
  #lang-flags { top: calc(8px + var(--safe-t)); right: calc(8px + 2 * (44px + 6px) + var(--safe-r)); }
  #sound-btn { top: calc(8px + var(--safe-t)); right: calc(8px + 2 * (44px + 6px) + var(--safe-r)); }
  body[data-screen=menu] #lang-flags { right: calc(8px + 3 * (44px + 6px) + var(--safe-r)); }
  #friends-bar, #friends-pop { --tr-top: calc(8px + var(--safe-t)); --tr-right: calc(8px + var(--safe-r)); --tr-gap: 6px; }
  .status-plate .status { flex: 1; font-size: 15px; padding: 6px 10px; }
  .status-plate .storm-note { order: -1; border-top: 0; border-bottom: 1px solid var(--line); font-size: 14px; }
  .status-plate.storm ~ .decide { bottom: calc(98px + var(--safe-b)); }
  /* may cover the plate strip above (it is a popup): all the height above the status bar */
  .game-menu { top: auto; bottom: calc(100% + 8px); width: min(340px, calc(100vw - 16px)); max-height: calc(100vh - 88px); max-height: calc(100dvh - 88px - var(--safe-t) - var(--safe-b)); }
  .gm-sep { margin: 3px 0; }
  /* Compact bottom sheet above the status bar; the board frames itself above it (GameView.frameBoard),
     and the answer buttons stay visible at its lower edge while the rows scroll. */
  .decide { top: auto; bottom: calc(64px + var(--safe-b)); right: calc(8px + var(--safe-r)); left: calc(8px + var(--safe-l)); width: auto; transform: none; max-height: 46vh; max-height: 46dvh; padding: var(--s3); gap: var(--s2); }
  .decide h2 { font-size: 22px; }
  /* one row on phones: label left, button right, so the board keeps most of the screen */
  .autopilot-panel { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  .autopilot-panel .hint { display: none; }
  .autopilot-panel h2 { font-size: 20px; }
  .autopilot-panel h2 .icon { width: 22px; height: 22px; }
  .decide .hint { font-size: 14px; }
  .decide .tile-head { padding: 6px 10px; }
  .decide .tile-head .tn { font-size: 19px; }
  .decide .rowbtn { min-height: 46px; padding: 6px 10px; }
  .decide .foot { position: sticky; bottom: calc(-1 * var(--s3)); margin: 0 calc(-1 * var(--s3)) calc(-1 * var(--s3)); padding: var(--s2) var(--s3) var(--s3); background: var(--slate); border-top: 1px solid var(--line); }
  .lobby-sheet { height: 80vh; height: 80dvh; }
  .firsthint { bottom: auto; top: calc(72px + var(--safe-t)); z-index: 18; }
  .logpanel { display: none; left: calc(8px + var(--safe-l)); right: calc(8px + var(--safe-r)); top: calc(72px + var(--safe-t)); bottom: calc(64px + var(--safe-b)); width: auto; z-index: 17; } /* over the decision sheet (opened on purpose, closes with its own button), under the bar's menu */
  .logpanel.open { display: flex; }
  .settings-grid { grid-template-columns: 1fr; }
  /* eight colours as two even rows of four instead of 7 + 1, each a full tap target */
  .lobby-sheet .swatches { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2); }
  .lobby-sheet .swatch { width: auto; min-height: 44px; }
  .deck-list { grid-template-columns: minmax(0, 1fr); }
  .tut { bottom: auto; top: calc(72px + var(--safe-t)); z-index: 18; }
  .deck-card { grid-template-columns: 96px minmax(0, 1fr); }
  .go-head h1 { font-size: 34px; }
  .banner { top: calc(76px + var(--safe-t)); font-size: 19px; padding: 8px 16px; }
  /* full width between 16 px gutters (narrower on a tablet), resting on the status bar or the sheet */
  #toasts { width: min(420px, calc(100vw - 32px - var(--safe-l) - var(--safe-r))); bottom: calc(var(--s4) + var(--safe-b) + var(--toast-lift, 0px)); justify-items: stretch; }
  /* Dialogs and the result sheet use nearly the whole phone: 8 px margin, notch and home bar kept free. */
  .modal-back, .gameover { padding: calc(8px + var(--safe-t)) calc(8px + var(--safe-r)) calc(8px + var(--safe-b)) calc(8px + var(--safe-l)); }
  .modal, .gameover > .panel { max-height: calc(100dvh - 16px - var(--safe-t) - var(--safe-b)); }
  .gameover > .panel { height: calc(100dvh - 16px - var(--safe-t) - var(--safe-b)); }
  .modal-head { padding-left: var(--s4); }
  .modal-body { padding: var(--s4); }
  .modal-foot { padding: var(--s2) var(--s4); }
  .go-head, .go-body { padding-left: var(--s4); padding-right: var(--s4); }
  .go-tabs { padding: 0 var(--s4); }
  .gameover .go-tabs { overflow-x: auto; } /* three result tabs are wider than a phone; the sheet is a flex column, the row keeps its height (flex: none) */
  .go-foot { padding: var(--s2) var(--s4); }
  /* Leaderboard wider than a phone: the whole table scrolls sideways inside the panel, names
     included (a pinned name column lagged behind the swipe). */
  /* end facts two by two, so the ranking below them is reached with less scrolling */
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); margin-bottom: var(--s4); }
  .fact { padding: var(--s2) 10px; }
  .fact .v { font-size: 19px; overflow-wrap: anywhere; }
  /* end ranking: name and amount on the first line, the note ("Vermögen", "pleite in Runde 6") under the name */
  .ranking .r { grid-template-columns: 34px minmax(0, 1fr) auto; row-gap: 0; padding: 6px 10px; }
  .ranking .place { grid-row: 1 / 3; font-size: 22px; }
  .ranking .nm { grid-column: 2; grid-row: 1; font-size: 18px; min-width: 0; overflow-wrap: anywhere; }
  .ranking .r > .small { grid-column: 2; grid-row: 2; }
  .ranking .num { grid-column: 3; grid-row: 1 / 3; white-space: nowrap; font-size: 19px; }
  /* end statistics: same idea, the row labels stay while the player columns scroll */
  .stat-table tbody th, .stat-table thead th:first-child { position: sticky; left: 0; z-index: 1; background: var(--slate); min-width: 120px; white-space: normal; }
}

/* Phones upright: the start menu sheet is as tall as its content and the board preview takes the rest
   (at least 120 px under the notch), with tighter spacing, so nothing scrolls on common phones; only on
   very short screens the sheet body scrolls (main.js reframes the board whenever the sheet changes size). */
@media (max-width: 1100px) and (orientation: portrait) {
  #screen-menu .sheet { height: auto; max-height: calc(100dvh - var(--safe-t) - 120px); }
  #screen-menu .sheet-body { padding: var(--s3) var(--s4); gap: var(--s3); }
  #screen-menu .wordmark img { width: min(168px, 46vw); }
  #screen-menu .tagline { margin-top: var(--s1); font-size: 14px; }
  #screen-menu .field { display: grid; gap: var(--s1); }
  #screen-menu .btn-big { min-height: 52px; font-size: 21px; padding: 8px 20px; }
  #screen-menu .section { gap: var(--s2); }
  #screen-menu .section h2 { font-size: 17px; }
  #screen-menu .tut-hint { padding: var(--s2) var(--s3); gap: var(--s1); }
  #screen-menu .tut-hint p { font-size: 13px; }
  #screen-menu .menu-foot { gap: var(--s1); }
  #screen-menu .menu-foot-meta .legal a, #screen-menu .menu-foot-meta .muted { min-height: 22px; font-size: 13px; }
  /* no public room open: heading and note on one line */
  #screen-menu .section:has(> .room-list > .empty-note:only-child) { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s2); }
}
/* Shorter phones (and phones in the browser, whose bars take height): the tagline goes, the board
   preview may shrink to 80 px; below 600 px the tutorial note goes too ("Tutorial" stays in the foot). */
@media (max-width: 1100px) and (orientation: portrait) and (max-height: 760px) {
  #screen-menu .sheet { max-height: calc(100dvh - var(--safe-t) - 80px); }
  #screen-menu .tagline { display: none; }
}
@media (max-width: 1100px) and (orientation: portrait) and (max-height: 600px) {
  #screen-menu .tut-hint { display: none; }
}

/* Tablets held upright (iPad mini to the 12.9" Pro): the phone layout, but the sheets' content and the
   panels at the bottom keep a comfortable width in the middle instead of stretching over 750-1000 px,
   and the plates are a size larger. */
@media (min-width: 700px) and (max-width: 1100px) and (orientation: portrait) {
  .sheet-foot, #screen-menu .sheet-body { padding-left: max(var(--s4), calc(50% - 360px)); padding-right: max(var(--s4), calc(50% - 360px)); }
  .lobby-body { padding-left: max(0px, calc(50% - 376px)); padding-right: max(0px, calc(50% - 376px)); }
  .lobby-sheet { height: auto; max-height: 80vh; max-height: 80dvh; }   /* as tall as its content: more board above */
  .status-plate, .decide, .logpanel { left: max(calc(8px + var(--safe-l)), calc(50% - 340px)); right: max(calc(8px + var(--safe-r)), calc(50% - 340px)); }
  .plates-strip { justify-content: center; }
  .plates-strip .plate { max-width: 260px; height: 56px; }
  .plates-strip .plate .name { font-size: 16px; }
  .plates-strip .plate .cash { font-size: 19px; }
}

/* ------------------------------------------------------------ phone held sideways */

/* Too little height for plates above and a sheet below. Menu and lobby become a side sheet left of
   the board preview. In the game a left column holds the plates (top) and the status block with
   its buttons (bottom, in thumb reach); a decision opens as a sheet that grows up from the
   bottom-right corner, which the diagonal board leaves empty; log, leaderboard and tutorial float
   over the board. game.js (hudMode, frameBoard) uses the same media query. */
@media (max-height: 520px) and (orientation: landscape) {
  h1 { font-size: 30px; }
  .small { font-size: 14px; }
  .btn-big { font-size: 20px; min-height: 48px; padding: 8px 20px; box-shadow: 0 4px 0 var(--edge); }
  .btn-big.btn-primary { box-shadow: 0 4px 0 var(--brass-edge); }
  .sheet, .lobby-sheet {
    top: calc(8px + var(--safe-t)); bottom: calc(8px + var(--edge-h) + var(--safe-b)); left: calc(8px + var(--safe-l)); right: auto;
    width: min(400px, 56vw); height: auto;
  }
  .lobby-sheet { width: min(460px, 62vw); }
  .lobby-sheet .settings-grid { grid-template-columns: 1fr 1fr; }
  .sheet-body:not(.lobby-body) { padding: var(--s3) var(--s4); gap: var(--s3); }
  .lobby-col { padding: var(--s3) var(--s4); gap: var(--s4); }
  .lobby-col + .lobby-col { padding-top: 0; }
  .sheet-foot { padding: var(--s2) var(--s4); }
  .wordmark img { width: 160px; }
  .tagline { margin-top: var(--s1); font-size: 15px; }
  .menu-foot { flex-direction: row; align-items: center; flex-wrap: wrap; }
  .menu-foot-btns { flex: 1 1 auto; }
  .menu-foot-btns button { padding-left: 10px; padding-right: 10px; }
  .menu-foot-btns .icon { display: none; }
  #settings-btn { top: calc(8px + var(--safe-t)); right: calc(8px + var(--safe-r)); }
  #profile-btn { top: calc(8px + var(--safe-t)); right: calc(8px + 44px + 6px + var(--safe-r)); }
  #lang-flags { top: calc(8px + var(--safe-t)); right: calc(8px + 2 * (44px + 6px) + var(--safe-r)); }
  #sound-btn { top: calc(8px + var(--safe-t)); right: calc(8px + 2 * (44px + 6px) + var(--safe-r)); }
  body[data-screen=menu] #lang-flags { right: calc(8px + 3 * (44px + 6px) + var(--safe-r)); }
  #friends-bar, #friends-pop { --tr-top: calc(8px + var(--safe-t)); --tr-right: calc(8px + var(--safe-r)); --tr-gap: 6px; }
  #stale-bar, body[data-screen=game] #stale-bar { top: calc(8px + var(--safe-t)); bottom: auto; right: calc(68px + var(--safe-r)); left: auto; width: min(420px, 50vw); transform: none; }

  /* dialogs: full height, slimmer head and foot */
  .modal-back, .gameover { padding: calc(6px + var(--safe-t)) calc(8px + var(--safe-r)) calc(6px + var(--safe-b)) calc(8px + var(--safe-l)); }
  .modal, .gameover > .panel { max-height: calc(100dvh - 12px - var(--safe-t) - var(--safe-b)); }
  .gameover > .panel { height: calc(100dvh - 12px - var(--safe-t) - var(--safe-b)); }
  .modal { width: min(680px, 100%); }
  .modal-head { padding: 0 var(--s2) 0 var(--s4); }
  .modal-head h2 { font-size: 21px; }
  .modal-body { padding: var(--s3) var(--s4); }
  .modal-foot { padding: var(--s1) var(--s4) var(--s2); }
  .modal-foot button { min-height: 44px; }
  .go-head { padding: var(--s3) var(--s4) 0; gap: var(--s1); }
  .go-head h1 { font-size: 28px; }
  .go-tabs { padding: 0 var(--s4); margin-top: var(--s2); }
  .go-body { padding: var(--s3) var(--s4); }
  .go-foot { padding: var(--s2) var(--s4); }

  /* game: plate column */
  .plates-side {
    position: absolute; top: calc(8px + var(--safe-t)); left: calc(8px + var(--safe-l));
    bottom: calc(var(--status-h, 92px) + 16px + var(--edge-h) + var(--safe-b));
    width: calc(var(--side-w) + 12px); padding: 0 12px 4px 0;
    display: flex; flex-direction: column; gap: 8px; overflow-x: hidden; overflow-y: auto;
  }
  .plates-side .plate {
    position: relative; flex: none; width: auto; height: 46px; left: auto !important; right: auto !important; top: auto !important; bottom: auto !important;
    padding: 3px 8px 5px; border-width: 3px; grid-template-columns: minmax(0, 1fr);
  }
  .plates-side .plate .name { font-size: 14px; }
  .plates-side .plate .cash { font-size: 17px; }
  .plates-side .plate .tags { display: none; }
  /* "am Zug": a brass bar on the board side of the plate */
  .plates-side .plate.active::before { left: auto; right: -11px; top: -3px; bottom: -3px; width: 4px; height: auto; }
  .plate.active::after { display: none; }
  /* six or more players: one line per plate (name left, cash right) */
  .plates-side:has(.plate:nth-child(6)) .plate { height: 34px; grid-template-columns: minmax(0, 1fr) auto; align-items: center; padding: 2px 8px; }
  .plates-side:has(.plate:nth-child(6)) .plate .cash { grid-column: 2; grid-row: 1; font-size: 15px; }

  /* game: status block under the plates; status text on its own line, the buttons below it */
  .status-plate, .status-plate.bare {
    top: auto; bottom: calc(8px + var(--safe-b)); left: calc(8px + var(--safe-l)); right: auto;
    transform: none; width: var(--side-w); max-width: none;
  }
  .status-plate .status { flex: 1 0 100%; white-space: normal; text-align: center; font-size: 15px; line-height: 1.2; padding: 6px 8px; border-bottom: 1px solid var(--line); }
  .status-plate > button:first-of-type { border-left: 0; }
  .status-plate > .menu-btn:not(.gear-btn) { flex: 1 1 auto; padding: 0 8px; }
  .status-plate .storm-note { order: -1; white-space: normal; text-align: center; border-top: 0; border-bottom: 1px solid var(--line); font-size: 14px; }
  /* the game menu opens beside the column, bottom-aligned with it */
  .game-menu { top: auto; bottom: 0; left: calc(100% + 8px); right: auto; width: 312px; max-height: calc(100dvh - 16px - var(--safe-t) - var(--safe-b)); }

  /* game: decision sheet in the bottom-right corner, growing upward */
  .decide, .status-plate.storm ~ .decide {
    top: auto; bottom: calc(8px + var(--safe-b)); right: calc(8px + var(--safe-r)); left: auto; width: 272px; transform: none;
    max-height: calc(100dvh - 16px - var(--edge-h) - var(--safe-t) - var(--safe-b)); padding: var(--s3); gap: var(--s2);
  }
  .decide h2 { font-size: 22px; }
  .decide .hint { font-size: 14px; }
  .decide .tile-head { padding: 6px 10px; }
  .decide .tile-head .tn { font-size: 19px; }
  .decide .rowbtn { min-height: 46px; padding: 6px 10px; }
  .decide .foot { position: sticky; bottom: calc(-1 * var(--s3)); margin: 0 calc(-1 * var(--s3)) calc(-1 * var(--s3)); padding: var(--s2) var(--s3) var(--s3); background: var(--slate); border-top: 1px solid var(--line); }
  .decide .btn-big { min-height: 56px; }
  .autopilot-panel { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  .autopilot-panel .hint { display: none; }
  .autopilot-panel h2 { font-size: 19px; }

  /* game: overlays over the board, right of the column */
  .logpanel {
    display: none; top: calc(8px + var(--safe-t)); bottom: calc(8px + var(--edge-h) + var(--safe-b));
    left: calc(var(--side-w) + 28px + var(--safe-l)); right: auto; width: min(360px, calc(100vw - var(--side-w) - 44px - var(--safe-l) - var(--safe-r))); z-index: 12;
  }
  .logpanel.open { display: flex; }
  .log-show { display: none; }
  .screen .leaderboard {
    top: calc(8px + var(--safe-t)); left: calc(var(--side-w) + 28px + var(--safe-l)); right: calc(8px + var(--safe-r)); width: auto; min-width: 0; max-width: none; margin: 0;
    max-height: calc(100dvh - 16px - var(--edge-h) - var(--safe-t) - var(--safe-b)); padding: var(--s3) var(--s4) var(--s2);
  }
  .lb-head h2 { font-size: 22px; }
  .lb-table th, .lb-table td { padding: 5px 8px; }
  .tut, .firsthint {
    top: calc(8px + var(--safe-t)); bottom: auto; left: calc(var(--side-w) + 28px + var(--safe-l)); transform: none; z-index: 18;
    width: min(400px, calc(100vw - var(--side-w) - 44px - var(--safe-l) - var(--safe-r)));
    max-height: calc(100dvh - 16px - var(--safe-t) - var(--safe-b)); overflow-y: auto;
  }
  .tut h2 { font-size: 20px; }
  /* while a decision is open, the floating panels end left of its sheet instead of under it */
  .screen:has(> .decide:not([hidden]):not(.autopilot-panel)) :is(.tut, .firsthint, .logpanel) {
    width: min(400px, calc(100vw - var(--side-w) - 272px - 52px - var(--safe-l) - var(--safe-r)));
  }
  .screen:has(> .decide:not([hidden]):not(.autopilot-panel)) .leaderboard { right: calc(272px + 16px + var(--safe-r)); }
  .banner { top: calc(8px + var(--safe-t)); left: calc(50% + var(--side-w) / 2); font-size: 18px; padding: 6px 14px; max-width: calc(100vw - var(--side-w) - 48px); }
  /* bottom right of the free area: right of the menu sheet or the plate column, left of an open
     decision sheet; the autopilot bar is short, the stack rests on it instead */
  #toasts { right: calc(8px + var(--safe-r)); bottom: calc(8px + var(--edge-h) + var(--safe-b) + var(--toast-lift, 0px)); justify-items: end; width: min(360px, calc(100vw - min(460px, 62vw) - 28px - var(--safe-l) - var(--safe-r))); }
  body[data-screen=game] #toasts { right: calc(8px + var(--safe-r)); width: min(360px, calc(100vw - var(--side-w) - 44px - var(--safe-l) - var(--safe-r))); }
  body[data-screen=game]:has(.decide:not([hidden]):not(.autopilot-panel)) #toasts {
    right: calc(272px + 16px + var(--safe-r)); width: min(360px, calc(100vw - var(--side-w) - 272px - 52px - var(--safe-l) - var(--safe-r)));
  }
  .cardpop { top: 50%; max-height: calc(100dvh - 16px); overflow-y: auto; }
  .cardpop .art { max-width: 200px; margin: 0 auto; }
  .lb-table tbody th, .lb-table thead th:nth-child(2) { position: sticky; left: 0; z-index: 1; background: var(--slate); }
  .lb-table tr.me th { background: var(--slate-2); }
  .stat-table tbody th, .stat-table thead th:first-child { position: sticky; left: 0; z-index: 1; background: var(--slate); min-width: 120px; white-space: normal; }
}

/* Phones held sideways, start menu and settings: two columns instead of one tall one, so both fit the
   short screen without scrolling. The menu sheet grows wider (the board preview keeps at least 120 px
   right of it); the settings dialog drops its "Fertig" bar (the close button in the head does the same). */
@media (max-height: 520px) and (orientation: landscape) {
  #screen-menu .sheet { width: min(700px, calc(100vw - 136px - var(--safe-l) - var(--safe-r))); }
  #screen-menu .sheet-body { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); padding-top: 10px; padding-bottom: 10px; }
  .menu-main, .menu-side { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; align-content: start; }
  #screen-menu .tagline { display: none; }
  #screen-menu .field { display: grid; gap: var(--s1); }
  #screen-menu .tut-hint { padding: var(--s2) var(--s3); gap: var(--s1); }
  #screen-menu .tut-hint p { font-size: 13px; }
  #screen-menu .section { gap: var(--s2); }
  #screen-menu .section h2 { font-size: 17px; }
  #screen-menu .section:has(> .room-list > .empty-note:only-child) { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s2); }
  #screen-menu .menu-foot-meta .legal a, #screen-menu .menu-foot-meta .muted { min-height: 22px; font-size: 13px; }
  .set.modal { width: min(820px, 100%); }
  .set .modal-body { display: block; columns: 2; column-gap: var(--s5); padding-top: var(--s1); padding-bottom: var(--s1); }
  .set-group { break-inside: avoid; grid-template-columns: 70px minmax(0, 1fr); gap: var(--s2); padding: 4px 0; }
  .set-group h3 { font-size: 16px; padding-top: 13px; overflow-wrap: anywhere; }
  .set-body, .set-body .stack { gap: 0; }
  .set .vol { grid-template-columns: 58px minmax(0, 1fr) 40px; gap: var(--s2); }
  .set .muted.small { font-size: 13px; }
  .set .choice-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .set .modal-foot { display: none; }
}

/* Tablets held sideways (touch, up to 860 px tall, so iPads in the browser and as an app): the desktop
   layout, but the settings dialogs in two columns and the start menu a little tighter, so neither
   scrolls. With a mouse (desktop, laptop) the spacing stays as it is. */
@media (hover: none) and (orientation: landscape) and (min-width: 901px) and (max-height: 860px) {
  #screen-menu .sheet-body { padding: var(--s4) var(--s5); gap: var(--s3); }
  #screen-menu .wordmark img { width: 220px; }
  #screen-menu .tagline { margin-top: var(--s1); font-size: 15px; }
  #screen-menu .tut-hint { padding: var(--s2) var(--s3); gap: var(--s1); }
  .set.modal { width: min(940px, 100%); }
  .set .modal-body { display: block; columns: 2; column-gap: var(--s6); }
  .set-group { break-inside: avoid; }
  .set .modal-foot { display: none; }   /* the close button in the head does the same as "Fertig" */
  .game-menu { width: 340px; }   /* room for the five view buttons of the touch camera */
}
/* the same in the browser on the smaller iPads, whose bars leave about 680 px */
@media (hover: none) and (orientation: landscape) and (min-width: 901px) and (max-height: 720px) {
  #screen-menu .tagline { display: none; }
  #screen-menu .section h2 { font-size: 18px; }
  .game-menu .gm-label small { display: none; }   /* the camera rows make the touch menu longer */
  .gm-toggles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 4px; }
  .gm-toggles .gm-item { gap: 6px; padding: 4px 6px; }
  .gm-toggles .gm-item > .icon { display: none; }
}

/* Game menu on shorter phones upright: the switches in two columns (label and box only), so the menu
   fits above the status bar without scrolling. Sideways: the whole menu in two columns. */
@media (max-width: 1100px) and (orientation: portrait) and (max-height: 760px) {
  .gm-toggles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 4px; }
  .gm-toggles .gm-item { font-size: 15px; gap: 6px; padding: 4px 6px; }
  .gm-toggles .gm-item > .icon, .gm-toggles .gm-label small { display: none; }
}
/* SE upright in the browser: no second lines under the entries either. */
@media (max-width: 1100px) and (orientation: portrait) and (max-height: 600px) {
  .game-menu .gm-label small { display: none; }
  .game-menu { padding: 6px; }
  .gm-viewrow.five .gm-view { min-height: 46px; padding: 4px 2px; gap: 2px; }
}
@media (max-height: 520px) and (orientation: landscape) {
  .game-menu { width: min(580px, calc(100vw - 230px - var(--safe-l) - var(--safe-r))); grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); column-gap: var(--s3); align-items: start; }
  .game-menu > :not(.gm-more) { grid-column: 1; }
  .gm-more { display: grid; gap: 2px; grid-column: 2; grid-row: 1 / span 12; align-content: start; }
  .gm-more > .gm-sep:first-child { display: none; }
  .gm-viewrow.five .gm-view span:not(.icon) { display: none; }   /* icons only; the names stay as aria labels */
  .gm-viewrow.five .gm-view { min-height: 44px; }
  .gm-toggles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 4px; }
  .gm-toggles .gm-item { font-size: 15px; gap: 6px; padding: 4px 6px; }
  .gm-toggles .gm-item > .icon, .gm-toggles .gm-label small { display: none; }
}

/* ------------------------------------------------------------ touch */

/* Fingers, not a cursor: every control at least 44 px, and inputs at 16 px so iOS does not zoom
   the page when one gets the focus. */
@media (pointer: coarse) {
  input[type=text], select, textarea { font-size: 16px; }
  .seg-btn, .seat-acts > button, .team-head .team-name-input { min-height: 44px; }
  .vol input { min-height: 44px; }
  .chat-form input { min-height: 44px; }
  #stale-bar button { width: 44px; min-width: 44px; min-height: 44px; }
  .tabs button { min-height: 44px; }
  .log-hide { min-height: 44px; height: 44px; }
}

/* "Bewegung reduzieren" (js/motion.js sets data-motion on <html>; every calm rule hangs off it) */
:root[data-motion="reduce"] * { transition-duration: 0s !important; }

/* Attempt pop over the dice (ui/attemptpop.js): angular plate, tick or cross, ~1 s. */
.attempt-pop {
  position: fixed; z-index: 30; pointer-events: none; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: var(--s2); padding: 8px 16px 8px 10px;
  font: 700 22px var(--font-sign); letter-spacing: .3px; color: var(--text);
  background: var(--slate-3); border: 2px solid var(--pc); box-shadow: 0 4px 0 var(--edge);
  clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
  animation: attempt-pop var(--ms, 1000ms) ease-out both;
}
.attempt-pop.is-ok { --pc: var(--good); }
.attempt-pop.is-fail { --pc: var(--bad); }
.attempt-mark { display: grid; place-items: center; width: 32px; height: 32px; background: var(--pc); color: var(--edge); }
.attempt-mark .icon { width: 22px; height: 22px; }
.attempt-mark svg * { stroke-width: 3; }
@keyframes attempt-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.7); }
  15% { opacity: 1; transform: translate(-50%, -50%) scale(1.06); }
  25%, 80% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1); }
}
@keyframes attempt-pop-calm { 0%, 100% { opacity: 0; } 10%, 85% { opacity: 1; } }
:root[data-motion="reduce"] .attempt-pop { animation-name: attempt-pop-calm; transform: translate(-50%, -50%); }

/* Decision countdown (ui/countdown.js): last 5 s of the own decision time, big number on an angular
   plate in the middle, clear of the decision panel. Never takes clicks. */
.countdown {
  position: fixed; z-index: 30; pointer-events: none; transform: translate(-50%, -50%);
  display: grid; place-items: center; width: 132px; height: 132px;
  background: var(--slate); border: 3px solid var(--bad); box-shadow: 0 5px 0 var(--edge);
  clip-path: polygon(18px 0, 100% 0, 100% calc(100% - 18px), calc(100% - 18px) 100%, 0 100%, 0 18px);
}
.countdown[hidden] { display: none; }
.countdown-n {
  font: 700 104px/1 var(--font-sign); color: var(--bad); font-variant-numeric: tabular-nums;
  animation: countdown-pop .32s ease-out both;
}
@keyframes countdown-pop {
  0% { opacity: 0; transform: scale(1.5); }
  60% { opacity: 1; transform: scale(.94); }
  100% { opacity: 1; transform: scale(1); }
}
:root[data-motion="reduce"] .countdown-n { animation: none; }
/* "Zu Ende spielen" past the skip point (ui/fastforward.js): dark vignette and speed rays flowing out
   to the edges while the camera pushes in. Fades in and out; only opacity and transform animate. */
.ffwd {
  position: absolute; inset: 0; pointer-events: none; z-index: 12; overflow: hidden;
  opacity: 0; visibility: hidden; transition: opacity .7s ease, visibility 0s .7s;
  background: radial-gradient(ellipse 75% 70% at 50% 46%, transparent 55%, rgba(8, 13, 17, 0.5) 100%);
}
.ffwd.on { opacity: 1; visibility: visible; transition: opacity .7s ease, visibility 0s; }
.ffwd-rays {
  position: absolute; left: 50%; top: 46%; width: 130vmax; height: 130vmax; margin: -65vmax 0 0 -65vmax;
  background:
    repeating-conic-gradient(from 3deg, transparent 0 6.5deg, rgba(255, 255, 255, 0.22) 6.5deg 6.8deg, transparent 6.8deg 13deg),
    repeating-conic-gradient(from 0deg, transparent 0 10deg, rgba(255, 255, 255, 0.14) 10deg 10.4deg, transparent 10.4deg 17deg);
  -webkit-mask-image: radial-gradient(circle, transparent 17%, #000 34%);
  mask-image: radial-gradient(circle, transparent 17%, #000 34%);
  opacity: 0; will-change: transform, opacity;
}
.ffwd.on .ffwd-rays { animation: ffwd-rays 1.4s linear infinite; }
.ffwd.on .ffwd-rays.late { animation-delay: -.7s; }
@keyframes ffwd-rays {
  0% { opacity: 0; transform: scale(.8); }
  35% { opacity: 1; }
  100% { opacity: 0; transform: scale(1.25); }
}
:root[data-motion="reduce"] .ffwd-rays { display: none; }
/* Phones: the board sits above the bottom panel, the rays flow out from its middle. */
@media (max-width: 900px), (orientation: portrait) and (max-width: 1100px) {
  .ffwd-rays { top: 41%; }
}
@media (max-width: 560px), (max-height: 520px) {
  .countdown { width: 96px; height: 96px; clip-path: polygon(14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px); }
  .countdown-n { font-size: 76px; }
}

.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ------------------------------------------------------------ public room list (lobby switch) */
/* Lives inside the invite card (ui/lobby.js renderPublic): a thin rule separates the second way
   into the room from the links above it. */
.public-box { display: grid; gap: var(--s1); padding-top: var(--s2); border-top: 1px solid var(--line); }
.public-box[hidden] { display: none; }
.public-box .check { min-height: 44px; font-weight: 600; color: var(--text); }
.public-box p { margin: 0; }
/* Switch or room name on the left, the host's seat limit on the same line to the right; it drops
   below only when the line gets too narrow for both. */
.public-line { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s1) var(--s3); }
.public-line > :first-child { flex: 1 1 170px; min-width: 0; }
.public-line .public-seats { flex: none; }
.public-line .public-seats select { width: 84px; }
/* ------------------------------------------------------------ end public room list */

/* Start menu, signed in: the name as a plate (same size as the field it replaces); it opens the
   profile, where the name is edited. */
.name-plate {
  width: 100%; min-height: 44px; justify-content: space-between; gap: var(--s2); text-align: left;
  background: var(--edge); border: 1px solid var(--line); box-shadow: none; padding: 9px 12px;
  font: 600 16px var(--font-sign); color: var(--text);
}
.name-plate-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.name-plate .icon { flex: none; width: 16px; height: 16px; color: var(--text-3); }
.name-plate:hover:not(:disabled) { background: var(--edge); border-color: var(--text-3); }
.name-plate:hover .icon { color: var(--brass); }
.name-plate:active:not(:disabled) { transform: none; }

/* Settings: the first row leads to the profile. One wide button with the name, the current figure and
   dice and the recording state, so the player sees what is set before opening it. */
.set-profile { width: 100%; justify-content: space-between; gap: var(--s3); text-align: left; padding: 8px 12px; }
.set-profile-text { display: grid; gap: 2px; min-width: 0; }
.set-profile-name { font: 600 17px var(--font-sign); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.set-profile-sub { font: 500 13px var(--font-body); color: var(--text-3); }
.set-profile-go { display: inline-flex; align-items: center; gap: 4px; flex: none; font-size: 15px; color: var(--brass); }
.set-profile-go .icon { width: 16px; height: 16px; transform: rotate(-90deg); }
/* "Im Spiel" outside a game: folded behind one quiet bar that names what is inside, so the same
   rows are in every settings dialog without pushing sound and language down. */
.set-fold > summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2); min-height: 44px;
  padding: 6px 12px; list-style: none; cursor: pointer; font: 600 16px var(--font-sign); color: var(--text-2);
  background: var(--slate-2); border: 1px solid var(--line); border-radius: var(--r);
}
.set-fold > summary::-webkit-details-marker { display: none; }
.set-fold > summary:hover { background: var(--slate-3); color: var(--text); }
.set-fold > summary:focus-visible { outline-offset: -3px; }
.set-fold-text { min-width: 0; }
.set-fold-icon { width: 16px; height: 16px; flex: none; transition: transform .15s; }
.set-fold[open] > summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.set-fold[open] .set-fold-icon { transform: rotate(180deg); }
.set-fold > .stack { padding: var(--s1) 12px var(--s2); border: 1px solid var(--line); border-top: 0; }
/* "Bewegung reduzieren": a small label over three choices in one row; on a 375 px phone the first
   column takes the width "Automatisch" needs and the two short ones share the rest. */
.set-motion-row { display: grid; gap: 6px; }
.set-sub { font: 600 15px var(--font-sign); color: var(--text-2); }
.set .set-motion { grid-template-columns: minmax(max-content, 1fr) 1fr 1fr; }
.set-motion .choice { justify-content: center; padding-inline: 6px; }

/* A stored game from the profile history: the end screen over the profile, with its date on top. */
.go-kicker { font: 600 14px var(--font-sign); color: var(--text-3); letter-spacing: .3px; }

/* ---- Test mode of the owner (ui/testmode.js): toggle and side panel, bottom sheet on phones ---- */
.test-toggle { position: fixed; left: 12px; bottom: 12px; z-index: 45; display: inline-flex; align-items: center; gap: var(--s1); }
.testpanel { position: fixed; left: 12px; top: 150px; bottom: 64px; width: 340px; z-index: 45; overflow-y: auto;
  padding: var(--s3); display: flex; flex-direction: column; gap: var(--s3); }
.testpanel .test-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.testpanel h2 { font-size: 22px; margin: 0; }
.testpanel h3 { font: 700 15px var(--font-sign); margin: 0 0 var(--s1); color: var(--text); }
.testpanel .test-sec { display: grid; gap: var(--s2); padding-top: var(--s2); border-top: 1px solid var(--line); }
.testpanel .test-row { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: end; }
.testpanel .test-row > * { flex: 1 1 120px; min-width: 0; }
.testpanel select, .testpanel input[type=number], .testpanel input[type=password] { width: 100%; min-height: 40px; }
.testpanel input[type=number], .modal input[type=password] { font: 500 15px var(--font-body); color: var(--text); background: var(--edge);
  border: 1px solid var(--line); border-radius: var(--r); padding: 8px 10px; }
.testpanel p { margin: 0; }
@media (max-width: 640px) {
  .test-toggle { left: auto; right: 8px; bottom: auto; top: 128px; }
  .testpanel { left: 8px; right: 8px; width: auto; top: auto; bottom: 8px; max-height: 62vh; }
}

/* Team mode (lobby, plates, leaderboard, end screen): a strip with one segment per member colour. */
.team-strip { display: inline-flex; height: 8px; min-width: 24px; border: 1px solid var(--edge); flex: none; }
.team-strip i { flex: 1; min-width: 12px; }
/* A team in the lobby: its members' colours as the top edge, letter, name field and count in one line,
   then the members and the free places. While a seat is picked, the other teams are targets. */
.team-block { position: relative; display: grid; gap: var(--s2); padding: 12px var(--s2) var(--s2); background: var(--slate); border: 1px solid var(--line); border-radius: var(--r); min-width: 0; }
.team-block .team-top { position: absolute; left: -1px; right: -1px; top: -1px; height: 5px; max-width: none; border: 0; }
.team-block .seat { min-width: 0; }
.team-block.is-target { cursor: pointer; border-style: dashed; border-color: #8197a5; }
.team-block.is-target:hover { background: #24313b; }
.team-head { display: flex; align-items: center; gap: var(--s2); min-height: 40px; }
.team-head .team-letter { flex: none; width: 32px; height: 32px; display: grid; place-items: center; font: 700 18px var(--font-sign); background: var(--slate-3); border: 1px solid var(--edge); }
.team-head .team-name-input { flex: 1; min-width: 0; min-height: 36px; padding: 6px 10px; }
.team-head .team-own-name { flex: 1; min-width: 0; font: 600 16px var(--font-sign); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.team-head .team-n { margin-left: auto; flex: none; font-size: 13px; color: var(--text-3); }
.plate .team-strip.plate-team { position: absolute; left: 10px; top: -6px; height: 8px; min-width: 40px; }
.plate .cash .cash-team { font: 600 13px var(--font-sign); color: var(--text-3); margin-right: 6px; letter-spacing: .5px; text-transform: uppercase; }
.lb-table .team-strip.lb-team { width: 28px; margin-right: 6px; vertical-align: middle; }
.ranking .team-strip.go-team { width: 28px; margin-right: 6px; vertical-align: middle; }
.tip .kv .tip-owner { display: inline-flex; align-items: flex-start; gap: 6px; min-width: 0; text-align: right; }
.tip .team-strip.tip-team { width: 28px; margin-top: 6px; }
/* Phones (strip or side column): the amount needs the whole width; the colour strip marks the team. */
.plates-strip .plate .cash-team, .plates-side .plate .cash-team { display: none; }
.plates-strip .plate .team-strip.plate-team, .plates-side .plate .team-strip.plate-team { left: 6px; min-width: 28px; }

/* Team names (lobby field, plate label, end screen) and the team chat channel. */
.team-name-input { width: 100%; min-height: 36px; font: 600 15px var(--font-sign); }
.team-own-name { font: 600 15px var(--font-sign); color: var(--text); overflow-wrap: anywhere; }
.plate .cash .cash-team { display: inline-block; max-width: 11ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.ranking .go-members { margin-left: var(--s2); font: 400 14px var(--font-body); color: var(--text-3); }
.chat-channel { display: flex; flex: none; border: 1px solid var(--line); border-radius: var(--r); }
.chat-channel[hidden] { display: none; }
.chat-channel button { min-height: 40px; padding: 0 var(--s2); border: 0; border-radius: 0; background: transparent; color: var(--text-3); font: 600 14px var(--font-sign); }
.chat-channel button + button { border-left: 1px solid var(--line); }
.chat-channel button[aria-pressed=true] { background: var(--slate-2); color: var(--text); box-shadow: inset 0 -3px 0 var(--text); }
.chat-form[data-channel=team] input { border-color: var(--text-2); }
.chat-msg.team { box-shadow: inset 3px 0 0 var(--text-3); padding-left: 6px; }
.chat-team-tag { margin-right: 6px; padding: 0 4px; border: 1px solid var(--text-3); border-radius: var(--r); font: 600 12px var(--font-sign); letter-spacing: .5px; text-transform: uppercase; color: var(--text-2); }
@media (max-width: 600px) { .chat-channel button { min-height: 44px; } }
/* Narrow side panel in the game: the switch takes its own row above the input. */
.logpanel .chat-form { flex-wrap: wrap; }
.logpanel .chat-channel { flex-basis: 100%; }
.logpanel .chat-channel button { flex: 1; }
.chat-form input { min-width: 0; flex: 1; }
/* Phones keep the whole width for the amount (the label rule above must not bring it back). */
.plates-strip .plate .cash .cash-team, .plates-side .plate .cash .cash-team { display: none; }
