/* Perfect Dungeon client chrome. Dark, legible, no framework. */

* { box-sizing: border-box; margin: 0; padding: 0; }

/* `hidden` must always win — component CSS sets `display` explicitly, which
   otherwise overrides the UA's [hidden] { display:none } and "hidden" panels
   keep rendering (the auth preview column did). */
[hidden] { display: none !important; }

:root {
  --bg: #0b0b0f;
  --panel: #17171e;
  --panel-2: #1f1f29;
  --panel-3: #262633;
  --panel-border: #2c2c38;
  --panel-border-bright: #3a3a4a;
  --text: #eaeaf0;
  --dim: #9a9aa8;
  --accent: #e0aa45;
  --accent-bright: #f0c064;
  --good: #6cc66c;
  --bad: #e06969;
  /* shared surfaces */
  --panel-grad: linear-gradient(180deg, #1d1d27, #16161d);
  --cell-grad: linear-gradient(180deg, #2b2b37, #23232d);
}

html, body {
  height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 14px;
  overflow: hidden;
}
#app {
  height: 100%;
  user-select: none;
  -webkit-user-select: none;
}

/* Public records pages navigate inside this panel, preserving the game socket. */
#records-panel {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  border: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
}
#records-panel[open] { display: flex; flex-direction: column; }
.records-panel-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--panel-border);
  background: var(--panel);
}
#records-panel iframe { width: 100%; flex: 1; min-height: 0; border: 0; }
#app * { -webkit-user-drag: none; }
#app input,
#app textarea,
#app select,
#app [contenteditable="true"],
#app [contenteditable="plaintext-only"] {
  user-select: text;
  -webkit-user-select: text;
}

button, input, select {
  font: inherit;
  color: inherit;
  background: #26262f;
  border: 1px solid var(--panel-border-bright);
  border-radius: 4px;
  padding: 4px 10px;
}
button { cursor: pointer; }
button:hover:not(:disabled) { border-color: var(--accent); }
button:disabled { opacity: 0.45; cursor: default; }
input:focus { outline: 1px solid var(--accent); }

/* ---- lobby ---- */
#lobby, #auth {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 24px 16px;
  overflow: auto;
}
#lobby h1, #auth h1 { font-size: 24px; letter-spacing: 6px; color: var(--accent); text-align: center; }
#lobby .lobby-card, #auth .lobby-card {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  max-width: min(760px, 100%);
}
#lobby .lobby-col, #auth .lobby-col {
  flex: 1 1 280px;
  min-width: 250px;
  max-width: 390px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
#lobby .lobby-col + .lobby-col, #auth .lobby-col + .lobby-col { border-left: 1px solid var(--panel-border); }
@media (max-width: 640px) {
  #lobby .lobby-col + .lobby-col, #auth .lobby-col + .lobby-col { border-left: none; border-top: 1px solid var(--panel-border); }
}
#lobby .lobby-col h3, #auth .lobby-col h3 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 2px;
  color: var(--dim);
  border-bottom: 1px solid var(--panel-border);
  padding-bottom: 6px;
  margin-bottom: 2px;
}
#lobby .row, #auth .row { display: flex; gap: 8px; align-items: center; }
#lobby .field-grid, #auth .field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
#lobby .full, #auth .full { width: 100%; }
#auth .auth-foot { margin-top: -6px; }
#auth .auth-foot a { color: var(--dim); font-size: 12px; letter-spacing: 1px; }
#auth .auth-foot a:hover { color: var(--accent); }
#lobby .error, #auth .error { color: var(--bad); min-height: 1em; font-size: 12px; }
#lobby .party-list { list-style: none; }
#lobby .party-list li { padding: 2px 0; display: flex; gap: 8px; align-items: center; }
.swatch { width: 12px; height: 12px; display: inline-block; border-radius: 2px; flex: none; }
#lobby .room-code { font-size: 22px; letter-spacing: 6px; color: var(--accent); text-align: center; }
#lobby .room-floor { text-align: center; color: var(--dim); font-size: 12px; margin-top: 2px; letter-spacing: 1px; min-height: 1em; }
/* godmode seed chip (npm run dev -- --godmode): seed + copy button, dev only */
#lobby .seed-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 10px;
  padding: 2px 8px;
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  background: var(--panel);
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--dim);
  vertical-align: middle;
}
#lobby .copy-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 14px;
  padding: 0 2px;
  line-height: 1;
}
#lobby .copy-btn:hover { filter: brightness(1.3); }
#lobby .hint, #auth .hint { color: var(--dim); font-size: 12px; line-height: 1.4; }

/* ---- auth screen specifics (sign-in / character creation) ---- */
#auth .field { display: flex; flex-direction: column; gap: 4px; }
#auth .field input, #auth .field select { width: 100%; box-sizing: border-box; }
#auth .toggle {
  background: none;
  border: none;
  padding: 4px 0;
  color: var(--accent);
  font-size: 12px;
  text-align: left;
}
#auth .linkish { background: none; border: none; color: var(--dim); font-size: 12px; text-decoration: underline; }
#auth .lobby-card { max-width: min(880px, 100%); }
#auth .lobby-col { padding: 24px 26px; gap: 14px; }
#auth .field { gap: 6px; }
#auth .section-lb {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 2px;
  color: var(--dim);
  border-bottom: 1px solid var(--panel-border);
  padding-bottom: 6px;
  margin-top: 6px;
}
/* ---- the look rows:  Label  < variant >  [ Colour + ]  ---- */
#auth .look-wrap { display: flex; flex-direction: column; gap: 12px; }
#auth .look { display: flex; flex-direction: column; gap: 8px; }
#auth .look-line { display: flex; align-items: center; gap: 12px; }
#auth .look-lb {
  width: 44px;
  flex: none;
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--dim);
}
#auth .cycler { display: flex; align-items: center; gap: 3px; flex: none; }
#auth .cyc {
  width: 26px;
  height: 28px;
  padding: 0;
  line-height: 1;
  font-size: 15px;
}
#auth .cyc-name {
  width: 92px;
  height: 28px;
  line-height: 26px;
  text-align: center;
  font-size: 13px;
  background: var(--panel-2);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
#auth .colpick {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 28px;
  padding: 0 10px;
  min-width: 128px;
  font-size: 12px;
}
#auth .col-strips { display: inline-flex; flex: none; }
#auth .col-strips i { width: 5px; height: 15px; border: 1px solid #000; }
#auth .col-name { flex: 1; text-align: left; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#auth .colpick .plus { color: var(--dim); font-size: 13px; flex: none; }
/* the inline colour picker (one open at a time) */
#auth .look-pick {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  background: #101014;
  border: 1px solid var(--panel-border);
  border-radius: 6px;
}
#auth .pick-lb { font-size: 11px; }
#auth .pick-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
#auth .pick {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 7px 2px 6px;
  border: 1px solid var(--panel-border-bright);
  background: none;
  cursor: pointer;
}
#auth .pick .sw { display: flex; }
#auth .pick .sw i { width: 7px; height: 17px; border: 1px solid #000; }
#auth .pick .nm { font-size: 9px; color: var(--text); white-space: nowrap; }
#auth .pick:hover { border-color: var(--accent); }
#auth .pick.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
#auth .pick-canon .nm { color: var(--dim); }
#auth .auth-preview { display: flex; justify-content: center; }
#auth .hero-fig {
  width: 384px;
  height: 384px;
  max-width: 100%;
  background: #101014;
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  image-rendering: pixelated;
}

/* The entrance borrows the town's stone, iron and torchlight. The scene is
   CSS chrome so it stays sharp at every viewport size and loads before art. */
#auth {
  position: relative;
  isolation: isolate;
  background:
    radial-gradient(ellipse 52% 62% at 50% 45%, #242019 0%, #141418 54%, #0b0b0f 100%);
}
#auth::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: .24;
  background:
    repeating-linear-gradient(0deg, transparent 0 57px, #5c5648 58px, transparent 59px),
    repeating-linear-gradient(90deg, transparent 0 105px, #49453e 106px, transparent 107px);
  mask-image: linear-gradient(transparent, #000 35%, #000 80%, transparent);
}
#auth h1 {
  font-size: clamp(24px, 3vw, 36px);
  letter-spacing: .28em;
  line-height: 1.2;
  text-shadow: 0 2px 12px #000, 0 0 25px #a264252a;
}
#auth .lobby-card {
  width: min(920px, 100%);
  max-width: none;
  flex-shrink: 0;
  flex-wrap: nowrap;
  justify-content: stretch;
  overflow: hidden;
  border: 1px solid #5b503f;
  border-radius: 3px;
  background: #1a1a20;
  box-shadow: 0 24px 65px #000a, 0 0 0 4px #0b0b0f99;
}
#auth:not(.is-create) .lobby-card { min-height: 476px; }
#auth:not(.is-create) .lobby-col {
  flex: 0 0 38%;
  max-width: none;
  min-width: 0;
  justify-content: center;
  padding: 38px 42px;
  gap: 22px;
  background: linear-gradient(135deg, #212027, #17171c);
}
#auth .lobby-col h3 {
  color: var(--accent-bright);
  border-color: #514737;
}
#auth .auth-pane { display: flex; flex-direction: column; gap: 10px; }
#auth .field input, #auth .field select {
  min-height: 36px;
  background: #111217;
  border-color: #514b44;
  padding: 7px 10px;
}
#auth .field input:focus, #auth .field select:focus {
  outline: 2px solid #e0aa45;
  outline-offset: 1px;
}
#auth .auth-pane > .full {
  min-height: 40px;
  margin-top: 8px;
  color: #17130c;
  font-weight: 700;
  letter-spacing: .08em;
  background: linear-gradient(#f1c36d, #ce933c);
  border-color: #f4ca78;
  box-shadow: inset 0 1px #ffe1a0, 0 3px 0 #694923;
}
#auth .auth-pane > .full:hover:not(:disabled) { background: linear-gradient(#ffcf7b, #dda247); }
#auth .toggle { font-size: 13px; text-decoration: underline; text-underline-offset: 4px; }
#auth .toggle:focus-visible, #auth .auth-foot a:focus-visible,
#auth .cyc:focus-visible, #auth .colpick:focus-visible, #auth .pick:focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 2px;
}
#auth .auth-foot { margin-top: 2px; }
#auth .auth-foot a {
  display: inline-block;
  padding: 8px 16px;
  color: var(--accent-bright);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: .14em;
  border: 1px solid #655437;
  background: #17161a;
  box-shadow: 0 3px 12px #0008;
}
#auth .auth-foot a:hover { background: #28221b; color: #ffe0a0; }
#auth .auth-scene {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  border-left: 1px solid #4d463c;
  background:
    radial-gradient(ellipse at 50% 56%, #5e452a 0%, #332d27 30%, #1a1c20 76%),
    repeating-linear-gradient(0deg, #28292a 0 52px, #494643 53px 55px);
}
#auth .auth-scene::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(0deg, transparent 0 49px, #090a0da8 50px 53px),
    repeating-linear-gradient(90deg, transparent 0 82px, #090a0d70 83px 86px);
  opacity: .55;
}
#auth .scene-halo {
  position: absolute;
  inset: 12% 10% 4%;
  background: radial-gradient(ellipse at 50% 55%, #db9e3b32, transparent 62%);
}
#auth .scene-arch {
  position: absolute;
  left: 26%; top: 12%; width: 48%; height: 75%;
  padding: 17px;
  border-radius: 48% 48% 3px 3px / 28% 28% 3px 3px;
  border: 3px solid #777264;
  background:
    repeating-linear-gradient(0deg, transparent 0 36px, #252424 37px 40px),
    repeating-linear-gradient(90deg, #5b5b56 0 36px, #444640 37px 40px);
  box-shadow: 0 0 0 6px #292a28, 0 0 0 9px #53534c, 10px 16px 28px #000b;
}
#auth .scene-recess {
  position: relative;
  width: 100%; height: 100%;
  overflow: hidden;
  border-radius: 48% 48% 2px 2px / 27% 27% 2px 2px;
  border: 5px solid #151719;
  background: radial-gradient(ellipse at 50% 35%, #373126, #0b0d10 75%);
  box-shadow: inset 0 0 22px #000;
}
#auth .scene-door {
  position: absolute;
  display: flex;
  inset: 14% 3% 0;
  overflow: hidden;
  border-radius: 46% 46% 0 0 / 16% 16% 0 0;
  border: 3px solid #765c39;
  background: #321f13;
  box-shadow: 0 0 22px #e0aa4533;
}
#auth .scene-leaf {
  position: relative;
  flex: 1;
  border: 2px solid #171513;
  background:
    linear-gradient(0deg, transparent 24%, #171818 25% 28%, transparent 29% 64%, #171818 65% 68%, transparent 69%),
    repeating-linear-gradient(90deg, #4a3020 0 16%, #68472c 17% 28%, #342719 29% 33%);
  box-shadow: inset 0 0 0 5px #543b27, inset 0 0 0 8px #241e18;
}
#auth .scene-leaf + .scene-leaf { border-left-color: #100f0e; }
#auth .scene-leaf::after {
  content: "";
  position: absolute;
  top: 53%; right: 10%;
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 2px solid #2b2013;
  background: #d9ad5a;
  box-shadow: 0 0 7px #e0aa4599;
}
#auth .scene-leaf + .scene-leaf::after { right: auto; left: 10%; }
#auth .scene-torch {
  position: absolute;
  z-index: 2;
  top: 42%; width: 20px; height: 44px;
  border-top: 7px solid #8b7650;
  background: linear-gradient(90deg, transparent 35%, #181919 35% 65%, transparent 65%);
}
#auth .scene-torch-left { left: 13%; }
#auth .scene-torch-right { right: 13%; }
#auth .scene-torch i {
  position: absolute;
  left: -8px; bottom: 37px;
  width: 36px; height: 58px;
  border-radius: 65% 30% 65% 50%;
  transform: rotate(-10deg);
  background: radial-gradient(ellipse at 55% 76%, #fff0ad 0 11%, #ffc466 20%, #e47d32 37%, #a64b1f 54%, transparent 70%);
  filter: drop-shadow(0 0 18px #d38738);
}
#auth .scene-steps {
  position: absolute;
  bottom: -6%; left: -12%; width: 124%; height: 31%;
  transform: perspective(220px) rotateX(55deg);
  transform-origin: bottom;
  background:
    repeating-linear-gradient(0deg, #111216 0 8px, #48443d 9px 12px, #292827 13px 46px),
    repeating-linear-gradient(90deg, transparent 0 70px, #121416 71px 75px);
  border-top: 8px solid #81735c;
  box-shadow: 0 -8px 22px #0008;
}
#auth .scene-caption {
  position: absolute;
  top: 4%; width: 100%;
  text-align: center;
  color: #dec389;
  font-size: 11px;
  letter-spacing: .28em;
  text-shadow: 0 2px 3px #000;
}
#auth.is-create .lobby-card { width: min(880px, 100%); }
#auth.is-create { justify-content: flex-start; }
#auth.is-create .lobby-col { min-width: 0; max-width: none; }
#auth.is-create .auth-preview { min-height: 386px; align-items: center; }
#auth .auth-preview { flex-direction: column; align-items: center; text-align: center; }
#auth .preview-retry {
  display: block;
  margin: 14px auto 0;
  color: var(--accent-bright);
  background: #252119;
  border-color: #655437;
}
@media (max-width: 760px) {
  #auth { justify-content: flex-start; }
  #auth .lobby-card { flex-direction: column; }
  #auth:not(.is-create) .lobby-col { flex-basis: auto; padding: 26px; }
  #auth .auth-scene { flex: none; height: 250px; border-left: 0; border-top: 1px solid #4d463c; }
  #auth.is-create .lobby-col + .lobby-col { border-left: 0; border-top: 1px solid var(--panel-border); }
  #auth.is-create .auth-preview { min-height: 0; }
}
@media (max-width: 420px) {
  #auth h1 { font-size: 22px; letter-spacing: .16em; }
  #auth .lobby-col { padding: 20px 16px; }
  #auth .look-line { gap: 6px; }
  #auth .cyc-name { width: 74px; }
  #auth .colpick { min-width: 98px; padding: 0 5px; gap: 4px; }
}
#lobby .divider { height: 1px; background: var(--panel-border); }

/* ---- game ---- */
#game { position: relative; width: 100%; height: 100%; }
#game canvas,
#hub canvas {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  width: calc(100% - 304px);
  height: calc(100% - 82px);
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
  touch-action: none;
}

/* ---- hub (the town — docs/design/hub.md) ---- */
#hub { position: relative; width: 100%; height: 100%; }
#hub-top {
  position: absolute;
  top: 8px;
  left: calc((100% - 304px) / 2);
  transform: translateX(-50%);
  z-index: 10;
  display: flex; align-items: center;
  padding: 5px 10px;
  background: linear-gradient(180deg, rgba(29, 29, 39, 0.92), rgba(13, 13, 18, 0.9));
  border: 1px solid rgba(74, 70, 82, 0.72);
  border-radius: 3px;
  box-shadow: 0 5px 18px rgba(0, 0, 0, 0.38);
  pointer-events: none;
}
#hub-top .row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; flex: 1; pointer-events: auto; }
#hub-top h1 {
  order: -2;
  display: block;
  color: var(--accent);
  font-size: 11px;
  line-height: 1;
  letter-spacing: 3px;
  white-space: nowrap;
}
#hub-count {
  order: -1;
  display: inline;
  padding-left: 10px;
  border-left: 1px solid var(--panel-border-bright);
  white-space: nowrap;
}
/* #hub-account stays hidden (the name is on the sign-out button's left as
   a chip in the bar); #hub-party is VISIBLE (amended 2026-10-25) — the
   leader is now a stored, transferable role, and the playtest found no way
   to see who holds the door. The Make-leader verb in the context menu
   needs that line to make sense. */
#hub-account { display: none; }
#hub-party { color: var(--accent); white-space: nowrap; }
#hub-top .linkish { background: none; border: none; color: var(--dim); font-size: 12px; text-decoration: underline; cursor: pointer; }
/* The old #hub-bottom overlay is gone (2026-10-25): it floated at
   bottom:150px and painted OVER the chat panel as that panel grew — the
   playtest's clipping report. Its two tenants each got a permanent home:
   the invite strip moved into the top bar (below), the transient notes
   became chat lines (chat.system). */
#hub .hint { color: var(--dim); font-size: 12px; line-height: 1.4; }
#hub #hover-readout { top: 8px; }
/* the town's chat (hub.md): the floor's chat panel, anchored to the town's
   bottom edge — the hub has no bottom hotbar (that 90px was for the floor
   and the retired hint bar alike). */
#hub #chat-panel { bottom: 8px; }
/* the invite strip (top bar) — hub.md's party chrome; the strip is the
   accept/decline surface. display:flex would out-vote the hidden attribute
   (traps/hidden-override.md), so [hidden] re-asserts none. */
#hub-invite {
  display: flex; gap: 6px; align-items: center;
  color: var(--accent); font-size: 12px; line-height: 1.4;
  pointer-events: auto; /* the bar is click-through; the strip's buttons are not */
}
#hub-invite[hidden] { display: none; }
#hub-invite .linkish { background: none; border: none; color: #9aeef2; font-size: 12px; text-decoration: underline; cursor: pointer; }

/* Hub interactions use the same centered modal grammar as floor interactions.
   The canvas remains the world surface; the backdrop temporarily owns input. */
#hub .game-modal-backdrop { z-index: 60; }
#hub .game-modal { width: min(480px, 100%); }
.modal-copy {
  margin: 0;
  color: var(--text);
  font-size: 14px;
  line-height: 1.55;
}
.modal-hint {
  color: var(--dim);
  font-size: 12px;
  line-height: 1.45;
}
.modal-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.modal-section-title {
  margin: 0;
  color: var(--accent);
  font-size: 12px;
  letter-spacing: 2px;
  text-transform: uppercase;
}
.modal-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  color: var(--dim);
  font-size: 12px;
}
.modal-field select { width: 100%; }
.modal-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 2px;
}
.modal-actions .modal-primary:first-child { margin-right: auto; }
.modal-primary { border-color: var(--accent); color: var(--accent-bright); }
.modal-secondary {
  border-color: transparent;
  background: transparent;
  color: var(--dim);
}
.modal-secondary:hover:not(:disabled) { border-color: var(--panel-border-bright); color: var(--text); }
.bull-dialogue { max-width: 44ch; }
.bull-editor {
  gap: 14px;
}
#hub #bull-dialog:has(.bull-editor) .game-modal { width: min(780px, 100%); }
.loadout-build { display: grid; grid-template-columns: minmax(0, 1fr) 218px; gap: 14px; align-items: start; }
.loadout-gear { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.loadout-item { min-width: 0; padding: 9px; border: 1px solid #53605b; background: linear-gradient(145deg, #28342d, #17201d); box-shadow: inset 0 1px #ffffff0c; }
.loadout-item[data-slot="weapon"] { grid-column: 1 / -1; }
.loadout-item[data-slot="weapon"] .loadout-item-preview { display: grid; grid-template-columns: 64px minmax(0, 1fr); align-items: center; gap: 10px; }
.loadout-item[data-slot="weapon"] .loadout-item-icon { width: 64px; height: 64px; }
.loadout-item .modal-field > span { color: #c3b280; font-size: 10px; text-transform: uppercase; letter-spacing: 1px; }
.loadout-item select { font-size: 12px; padding: 5px; }
.loadout-item-preview { padding-top: 8px; }
.loadout-item-icon { display: block; margin: 0 auto 6px; width: 40px; height: 40px; object-fit: contain; image-rendering: pixelated; }
.loadout-empty { min-height: 42px; display: grid; place-items: center; color: #79877a; font: italic 12px Georgia,serif; }
.loadout-summary { position: sticky; top: 0; padding: 10px; border: 1px solid #87774e; background: linear-gradient(#2d352b,#1b211b); box-shadow: inset 0 0 0 2px #121a1299; }
.loadout-summary > strong { color: #d9c082; font: 600 14px Georgia,serif; }
.bull-editor > .modal-actions { position: sticky; bottom: -16px; padding: 10px 0; background: #1b2426; border-top: 1px solid #566155; z-index: 1; }
.loadout-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 12px;
}
@media (max-width: 900px) {
  #hub #bull-dialog { inset: 0 0 82px; padding: 12px; }
}
@media (max-width: 560px) {
  .loadout-grid { grid-template-columns: 1fr; }
  .loadout-build { grid-template-columns: 1fr; }
  .loadout-summary { grid-row: 1; position: static; }
  .loadout-gear { grid-template-columns: 1fr; }
}

/* hover readout: what a click will do (RuneScape-style, top-left of the view) */
#hover-readout {
  position: absolute;
  top: 8px;
  left: 8px;
  background: rgba(8, 8, 12, 0.68);
  border: 0;
  padding: 4px 7px;
  border-radius: 2px;
  font-size: 13px;
  pointer-events: none;
  color: var(--accent-bright);
  min-width: 120px;
  text-shadow: 0 1px 2px #000;
}
#hover-readout:empty { display: none; }

/* ---- panels: shared chrome ---- */
.panel {
  position: absolute;
  background: var(--panel-grad);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  font-size: 12px;
  max-height: 38%;
  overflow: hidden;
  box-shadow:
    0 10px 32px rgba(0, 0, 0, 0.6),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
  display: flex;
  flex-direction: column;
}
.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 12px 7px;
  border-bottom: 1px solid var(--panel-border);
  background: linear-gradient(180deg, rgba(224, 170, 69, 0.08), rgba(224, 170, 69, 0.02));
}
.panel-head h3 {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 3px;
  color: var(--accent);
  text-shadow: 0 0 12px rgba(224, 170, 69, 0.25);
}
.panel-badge {
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--dim);
  background: var(--panel-2);
  border: 1px solid var(--panel-border);
  border-radius: 9px;
  padding: 1px 8px;
}
.panel-badge:empty { display: none; }
.panel-body {
  padding: 8px 10px;
  overflow-y: auto;
}
/* The Equipment panel body is tighter than the default: the panel shares the
 * top-right column with Party/Status and must stay short (see .equip-cell). */
#equipment-panel .panel-body { padding: 6px 8px; }
#equipment-panel .panel-head { padding: 6px 10px 5px; }

/* dark, thin scrollbars to match the chrome */
.panel-body::-webkit-scrollbar, #chat-log::-webkit-scrollbar, #lobby::-webkit-scrollbar {
  width: 8px;
}
.panel-body::-webkit-scrollbar-thumb, #chat-log::-webkit-scrollbar-thumb, #lobby::-webkit-scrollbar-thumb {
  background: #33333f;
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.panel-body::-webkit-scrollbar-thumb:hover, #chat-log::-webkit-scrollbar-thumb:hover {
  background: #45454f;
  background-clip: padding-box;
}
.panel-body::-webkit-scrollbar-track, #chat-log::-webkit-scrollbar-track, #lobby::-webkit-scrollbar-track {
  background: transparent;
}

#top-right {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 304px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 7px;
  background: linear-gradient(90deg, #111118, #0b0b10);
  border-left: 1px solid #30303a;
  z-index: 8;
}
#top-right .panel { position: relative; max-height: none; width: 100%; flex: none; }
#party-panel { min-width: 190px; }
#party-panel .line { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
#party-panel .line .name { flex: 1; font-weight: 600; }
#party-panel .line .dot { font-size: 11px; }

#status-panel { min-width: 190px; }
#status-panel .status-room { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
#status-panel .status-room .k { color: var(--dim); letter-spacing: 2px; text-transform: uppercase; font-size: 10px; }
#status-panel .room-code {
  font-size: 20px;
  letter-spacing: 5px;
  color: var(--accent);
  text-shadow: 0 0 14px rgba(224, 170, 69, 0.35);
}
#status-panel .status-foot {
  margin-top: 6px;
  padding-top: 5px;
  border-top: 1px solid var(--panel-border);
  color: var(--dim);
  font-size: 10px;
  letter-spacing: 0.5px;
}
/* Active buff rows (loot.md build 5): one per type between the room code
 * and the footer — label left, multiplier middle, ticking seconds right. */
#status-panel .status-buff {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-top: 4px;
  font-size: 11px;
}
#status-panel .status-buff .k {
  color: var(--dim);
  letter-spacing: 1px;
  text-transform: uppercase;
  font-size: 9px;
}
#status-panel .status-buff .v { color: var(--accent); }
#status-panel .status-buff .t { color: var(--dim); font-variant-numeric: tabular-nums; }

/* A compact equipment rack: armour down the spine, held gear at the sides. */
#equipment-panel { min-width: 190px; }
.equip-grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 68px minmax(0, 1fr);
  grid-template-areas:
    ". helmet ."
    "weapon chest shield"
    "weapon legs shield"
    ". feet .";
  grid-auto-rows: 40px;
  gap: 4px 12px;
  padding: 4px;
  background:
    linear-gradient(#56605a55, #56605a55) center / 1px calc(100% - 16px) no-repeat,
    linear-gradient(90deg, transparent, #9e89654d, transparent) center 67px / 100% 1px no-repeat,
    radial-gradient(ellipse at 50% 45%, #a995621a, transparent 68%);
}
.equip-cell[data-slot="helmet"] { grid-area: helmet; }
.equip-cell[data-slot="shield"] { grid-area: shield; }
.equip-cell[data-slot="chest"] { grid-area: chest; }
.equip-cell[data-slot="weapon"] { grid-area: weapon; }
.equip-cell[data-slot="legs"] { grid-area: legs; }
.equip-cell[data-slot="feet"] { grid-area: feet; }
.equip-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 0;
  gap: 0;
  padding: 1px 3px;
  border: 1px solid #59635f;
  border-radius: 3px;
  background: linear-gradient(145deg, #2b3638, #182126);
  box-shadow: inset 0 1px 0 #e7e3c01a, inset 0 -3px 8px #0005, 0 2px 4px #0005;
  user-select: none;
}
.equip-cell.empty {
  border-color: #354344;
  background: linear-gradient(145deg, #182225, #11191d);
  box-shadow: inset 0 2px 8px #0005, inset 0 0 0 2px #71817a08;
  cursor: default;
}
.equip-cell.filled { cursor: pointer; border-color: #8b7953; }
.equip-cell.filled:hover,
.equip-cell.filled:focus-visible {
  outline: 1px solid var(--workspace-brass-hi);
  outline-offset: 1px;
  background: linear-gradient(145deg, #3c4033, #202b2c);
  box-shadow: inset 0 1px 0 #f6edca22, 0 0 12px #b59a6626;
}
.equip-cell .icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 26px;
  flex-shrink: 0;
  color: #61736e;
  image-rendering: pixelated;
}
.equip-cell .icon svg { width: 100%; height: 100%; }
.equip-cell .eq-name {
  max-width: 100%;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 10px;
  line-height: 1.1;
  color: #e2dbc2;
  text-align: center;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.equip-armour .eq-name,
.equip-cell .eq-name:empty { display: none; }
.equip-cell .eq-slot {
  font-size: 8px;
  line-height: 1.1;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: #919e94;
}
.equip-cell.filled .eq-slot { color: #b7a77e; }
.equip-hand { gap: 3px; padding: 5px 4px; }
.equip-hand .icon { width: 36px; height: 36px; }
.equip-hand.empty .icon { color: #718078; }

/* The canvas stops above this black instrument strip. Its three columns keep
 * combat and elapsed time on either side of the same town/floor action bar. */
#bottom-dock {
  position: absolute;
  left: 8px;
  right: 312px;
  bottom: 7px;
  height: 68px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: stretch;
  gap: 9px;
  z-index: 5;
  pointer-events: none;
}
#bottom-dock > * { min-width: 0; pointer-events: auto; }
#combat-summary { grid-column: 1; grid-row: 1; }
#floor-timer { grid-column: 3; grid-row: 1; justify-self: end; }
.bottom-widget {
  align-self: stretch;
  padding: 5px 8px;
  border: 1px solid #4d5c60;
  background: linear-gradient(180deg, #1c262a, #10181b);
  box-shadow: inset 0 1px 0 rgba(220, 225, 211, 0.06);
  color: var(--text);
}
#combat-summary { width: min(100%, 280px); }
.combat-heading,
.floor-timer-label {
  display: block;
  color: var(--workspace-brass-hi, var(--accent-bright));
  font: 600 9px/12px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: 1.3px;
  text-transform: uppercase;
}
.combat-hp-row { display: flex; align-items: center; gap: 6px; height: 22px; }
.combat-name {
  flex: 0 0 55px;
  overflow: hidden;
  color: #c8d2cf;
  font-size: 10px;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.combat-hp-track {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 13px;
  overflow: hidden;
  border: 1px solid #56605b;
  background: #330f14;
}
.combat-hp-fill {
  height: 100%;
  width: 0;
  background: linear-gradient(180deg, #81cc75, #3e8442);
  transition: width 0.12s linear;
}
#combat-summary .combat-hp-row.enemy .combat-hp-fill {
  background: linear-gradient(180deg, #db8975, #aa433e);
}
.combat-hp-value {
  position: absolute;
  inset: 0;
  color: #fff;
  font: 9px/11px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  text-align: center;
  text-shadow: 0 1px 2px #000;
}
.combat-idle { display: block; color: #7f8b88; font-size: 10px; line-height: 22px; }
#floor-timer {
  width: min(100%, 180px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 2px;
}
.floor-timer-value {
  color: #e8ece5;
  font: 600 22px/25px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: 1px;
}

/* The shared dock: class kit, gatestone actions, then the map. */
#abilities-panel {
  position: relative;
  grid-column: 2;
  grid-row: 1;
  display: flex;
  gap: 6px;
  height: 68px;
  padding: 5px;
  background: linear-gradient(180deg, #242430, #1b1b25);
  border: 1px solid var(--panel-border-bright);
  border-radius: 9px;
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.05);
  z-index: 5;
}
@media (max-width: 1050px) {
  #bottom-dock #abilities-panel .ability { width: 44px; }
  #bottom-dock #abilities-panel .ability .ability-icon { width: 30px; height: 30px; }
  .combat-name { flex-basis: 42px; }
  .floor-timer-value { font-size: 16px; }
}
#abilities-panel .ability-wrap { position: relative; display: flex; flex: none; height: 100%; }
#abilities-panel .ability-wrap:hover,
#abilities-panel .ability-wrap:focus-within { z-index: 6; }
#abilities-panel .ability {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 100%;
  min-width: 0;
  text-align: center;
  padding: 6px;
  background: linear-gradient(180deg, #2a2a38, #22222c);
  border: 1px solid #3c3c49;
  border-top: 2px solid var(--accent);
  border-radius: 5px;
  transition: border-color 0.12s, box-shadow 0.12s, transform 0.12s;
}
#abilities-panel .ability .ability-icon {
  position: relative;
  z-index: 2;
  display: block;
  width: 36px;
  height: 36px;
  color: var(--accent-bright);
  pointer-events: none;
}
#abilities-panel .ability .ability-icon svg { display: block; width: 100%; height: 100%; }
#abilities-panel .ability[data-icon="summon-pgt"] .ability-icon { color: #b7a0e9; }
#abilities-panel .ability[data-icon="teleport"] .ability-icon,
#abilities-panel .ability[data-icon="teleport-pgt"] .ability-icon,
#abilities-panel .ability[data-icon="teleport-ggs"] .ability-icon { color: #83d4d1; }
#abilities-panel .ability:hover:not(:disabled) {
  border-color: var(--accent);
  box-shadow: 0 0 16px rgba(224, 170, 69, 0.25);
  transform: translateY(-1px);
}
#abilities-panel .ability:disabled { border-top-color: #3a3a44; opacity: 0.5; }
#abilities-panel .ability .key {
  position: absolute; z-index: 3; top: 3px; left: 5px;
  color: var(--dim); font-size: 9px;
}
#abilities-panel .ability .cooldown {
  position: absolute; z-index: 1; left: 0; right: 0; bottom: 0;
  height: var(--cooldown, 0%);
  background: rgba(2, 2, 5, 0.72);
  pointer-events: none;
}
#abilities-panel .ability .cooldown-count {
  position: absolute; z-index: 3; bottom: 2px; left: 50%;
  transform: translateX(-50%);
  min-width: 26px; padding: 0 4px;
  color: #fff; font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums; line-height: 17px;
  background: #0b1114; border: 1px solid #7f9695; border-radius: 3px;
  box-shadow: 0 1px 4px #000;
  pointer-events: none;
}
#abilities-panel .ability .cooldown-count:empty { display: none; }
#abilities-panel .ability.cooling .ability-icon {
  width: 30px; height: 30px; transform: translateY(-11px);
}
#abilities-panel .ability.active { border-color: var(--accent-bright); box-shadow: inset 0 0 14px rgba(224,170,69,.25); }
#abilities-panel .ability.armed { border-color: #c9a6ff; box-shadow: 0 0 13px rgba(139,70,255,.45); }
#abilities-panel .ability-split { width: 1px; margin: 3px 2px; background: var(--panel-border-bright); }
#abilities-panel .ability-tooltip {
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  z-index: 7;
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: max-content;
  min-width: 155px;
  max-width: min(230px, calc(100vw - 16px));
  padding: 9px 11px;
  color: #e8e6db;
  text-align: left;
  font: 11px/1.35 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  background: #172126;
  border: 1px solid #718388;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translate(-50%, 4px);
  transition: opacity 0.12s, transform 0.12s, visibility 0.12s;
}
#abilities-panel .ability-wrap:hover .ability-tooltip,
#abilities-panel .ability-wrap:focus-within .ability-tooltip {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
#abilities-panel .ability-tooltip-name { color: #e7c16d; font-size: 12px; }
#abilities-panel .ability-tooltip-detail { color: #c1cbca; }
#abilities-panel .ability-tooltip-detail:empty { display: none; }
#abilities-panel .ability-tooltip-state { color: #83d4d1; font-size: 10px; }

/* The inventory owns the right rail's remaining height. Its complete 4-column
 * grid always fits that space: rows, padding and icons compress together at
 * shorter window heights instead of introducing a scrollbar. */
#inventory-panel {
  width: 100%;
  min-height: 150px;
  flex: 1 !important;
  max-height: none !important;
}
#inventory-panel .panel-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.inventory-grid {
  display: grid;
  gap: 5px;
  /* Fixed row height: empty cells must not collapse (a content-sized empty
   * div is 10px tall — the squashed-rows bug). 96px = 48px icon + up to two
   * wrapped caption lines + primary + padding + border. */
  grid-auto-rows: 96px;
}
#inventory-panel .inventory-grid {
  /* Cap the STRETCH on the grid's height, not on the rows: 399px = 4 rows ×
   * 96px + 3 × 5px gaps. Tall (4K) window: the grid stops at 399px and the
   * rows land exactly on the 96px baseline — the rail below stays empty
   * (the playtest's "inventory too stretched in the hub" report; empty
   * space is the accepted look). Short window: the grid is 100% of the
   * panel and the bare 1fr rows compress together (rows, padding, icons)
   * so all 16 cells fit with no scrollbar.
   * Do NOT write the cap as `min(96px, 1fr)` on the rows: an fr inside
   * min() resolves against the grid's TOTAL free space, not the per-track
   * share, so the rows never compress — verified live, the 16th cell
   * clipped at 1280×800. Same rule in floor and hub (shared rail). */
  height: min(100%, 399px);
  grid-auto-rows: minmax(0, 1fr);
}
#inventory-panel .inventory-grid .cell {
  min-height: 0;
  gap: 1px;
  padding: 3px 2px 2px;
}
#inventory-panel .inventory-grid .cell .icon {
  width: auto;
  height: auto;
  min-height: 0;
  max-width: 48px;
  max-height: 48px;
  aspect-ratio: 1;
  flex: 1 1 48px;
}
#inventory-panel .inventory-grid .cell .primary { padding: 1px 5px; }
.inventory-grid .cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 2px;
  padding: 5px 4px 4px;
  background: var(--cell-grad);
  border: 1px solid #383846;
  border-radius: 6px;
  cursor: grab;
  user-select: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.05),
    0 2px 4px rgba(0, 0, 0, 0.35);
}
.inventory-grid .cell.item:hover {
  border-color: var(--accent);
  background: linear-gradient(180deg, #343040, #292837);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 0 12px rgba(224, 170, 69, 0.25);
}
/* Empty slots are solid sockets, never wireframe dashes — a finished
 * inventory reads as "empty slot", not "placeholder" (the vision pass). */
.inventory-grid .cell.empty {
  background: #101016;
  border: 1px solid #242430;
  box-shadow: inset 0 2px 7px rgba(0, 0, 0, 0.55);
  cursor: default;
}
.inventory-grid .cell.dim { opacity: 0.7; }
.inventory-grid .cell.dragging { opacity: 0.3; }
.inventory-grid .cell.drop-target {
  border-color: var(--accent-bright);
  background: #2f291c;
  box-shadow:
    inset 0 0 0 2px rgba(224, 170, 69, 0.55),
    0 0 14px rgba(224, 170, 69, 0.35);
}
.inventory-grid .cell .icon {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: bold;
  color: var(--dim);
  background: #12121a;
  border: 1px solid #2e2e3a;
  border-radius: 5px;
  image-rendering: pixelated;
  box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.5);
}
.inventory-grid .cell .cap {
  width: 100%;
  max-width: 58px;
  font-size: 9.5px;
  line-height: 1.12;
  color: var(--text);
  text-align: center;
  /* Wrapping captions: "Group gatestone" / "Personal gatestone" need two
   * lines — an ellipsis would hide the item name (the clipping the vision
   * pass flagged). */
  white-space: normal;
  overflow: visible;
}
/* The primary action is a hover-revealed chip: the idle cell is just the
 * icon + name; the affordance appears when the mouse is on the cell. */
.inventory-grid .cell .primary {
  font-size: 9px;
  line-height: 1;
  color: var(--accent-bright);
  background: rgba(224, 170, 69, 0.12);
  border: 1px solid rgba(224, 170, 69, 0.35);
  border-radius: 7px;
  padding: 2px 7px;
  opacity: 0;
  transition: opacity 0.12s;
}
.inventory-grid .cell:hover .primary { opacity: 1; }
.inventory-grid .cell .sub { color: var(--dim); font-size: 11px; }

/* dragged inventory item: ghost follows the cursor, the drop hint labels a
 * drag-out release (drop at your feet / can't drop). */
.cell-ghost {
  position: fixed;
  z-index: 60;
  pointer-events: none;
  opacity: 0.92;
  transform: scale(1.04);
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.55));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  background: var(--panel-2);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 5px 4px 4px;
  box-shadow: 0 0 18px rgba(224, 170, 69, 0.25);
}
.cell-ghost .icon {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #12121a;
  border: 1px solid #2e2e3a;
  border-radius: 5px;
  image-rendering: pixelated;
}
.cell-ghost .cap {
  width: 52px;
  font-size: 9.5px;
  line-height: 1.12;
  color: var(--text);
  text-align: center;
  white-space: normal;
  overflow: visible;
}
.cell-ghost .primary {
  font-size: 9px;
  line-height: 1;
  color: var(--accent-bright);
  background: rgba(224, 170, 69, 0.12);
  border: 1px solid rgba(224, 170, 69, 0.35);
  border-radius: 7px;
  padding: 2px 7px;
}
#drop-hint {
  position: fixed;
  z-index: 61;
  pointer-events: none;
  display: none;
  padding: 6px 12px;
  border-radius: 5px;
  background: var(--panel-2);
  border: 1px solid var(--accent);
  color: var(--text);
  font-size: 12px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
}
#drop-hint.no-drop { border-color: var(--bad); }

#chat-panel {
  left: 8px;
  bottom: 90px;
  width: min(560px, 44%);
  display: flex;
  flex-direction: column;
  max-height: 30%;
  /* chat has no panel-head; restore the padding the base .panel no longer
   * carries (it moved to .panel-body). */
  padding: 8px 10px;
}
.chat-head {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 6px;
  min-height: 20px;
}
.chat-title {
  flex: 1;
  color: var(--accent-bright);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.8px;
  text-transform: uppercase;
}
.chat-unread {
  min-width: 16px;
  color: var(--workspace-cyan, var(--accent-bright));
  font-size: 10px;
  text-align: right;
}
.chat-unread:empty { display: none; }
.chat-toggle {
  width: 24px;
  height: 20px;
  padding: 0;
  border: 1px solid var(--panel-border-bright);
  border-radius: 1px;
  color: var(--accent-bright);
  font-size: 15px;
  line-height: 16px;
  cursor: pointer;
}
#chat-panel.collapsed {
  width: 142px;
  max-height: none;
  padding: 6px 8px;
}
#chat-panel.collapsed .chat-head { margin-bottom: 0; }
#chat-panel.collapsed #chat-log,
#chat-panel.collapsed #chat-form { display: none; }
#chat-log { overflow-y: auto; flex: 1; max-height: 180px; }
#chat-log .line { padding: 2px 0; word-wrap: break-word; }
#chat-log .system { color: var(--dim); font-style: italic; }
#chat-log .invalid { color: var(--bad); }
#chat-form { display: flex; gap: 6px; margin-top: 6px; }
#chat-form input {
  flex: 1;
  background: #14141c;
  border: 1px solid #34343f;
  border-radius: 5px;
  padding: 6px 10px;
}
#chat-form input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 8px rgba(224, 170, 69, 0.2);
}

#banner {
  position: absolute;
  top: 30%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: linear-gradient(180deg, #241c10, #171309);
  border: 2px solid var(--accent);
  border-radius: 8px;
  padding: 22px 40px;
  text-align: center;
  font-size: 24px;
  letter-spacing: 6px;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: 0 0 20px rgba(224, 170, 69, 0.4);
  box-shadow: 0 0 48px rgba(224, 170, 69, 0.3);
  display: none;
  z-index: 20;
}
#banner.show { display: block; }

/* The exit-portal countdown bar (run.md): a thin strip under the banner —
   persistent while a floor-end vote runs (the text updates every tick),
   hidden otherwise. Distinct from #banner: that one is a one-shot. */
#exit-countdown {
  position: absolute;
  top: 22%;
  left: 50%;
  transform: translateX(-50%);
  background: linear-gradient(180deg, #1d1608, #141005);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 8px 22px;
  font-size: 15px;
  letter-spacing: 2px;
  color: var(--accent-bright);
  text-transform: uppercase;
  box-shadow: 0 0 24px rgba(224, 170, 69, 0.25);
  z-index: 19;
}

/* The results screen (run.md): full-screen over the floor, shown to everyone
   in the floor when it ends. Dismiss re-enters the hub (index.ts queued the
   re-parent Welcome behind it). */
#results {
  position: absolute;
  inset: 0;
  background: rgba(8, 8, 12, 0.88);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  z-index: 40;
}
#results h1 {
  font-size: 42px;
  letter-spacing: 10px;
  text-transform: uppercase;
}
#results h1.cleared { color: var(--accent-bright); text-shadow: 0 0 30px rgba(240, 192, 100, 0.5); }
#results h1.retreated { color: #8fa8bc; text-shadow: 0 0 24px rgba(120, 168, 196, 0.4); }
#results .results-sub {
  color: var(--dim);
  font-size: 16px;
  letter-spacing: 3px;
  text-transform: uppercase;
}
/* the run's rank (leaderboard.md): the reward line under the time —
   cleared only; the server's number, never a client claim. */
#results #results-rank {
  color: var(--accent-bright);
  width: min(500px, calc(100% - 24px));
  text-align: center;
  text-shadow: 0 0 18px rgba(240, 192, 100, 0.35);
}
#results .results-rank-title { font-size: 17px; line-height: 1.35; letter-spacing: 1px; }
#results .results-detail-link { display: inline-block; color: var(--accent); font-size: 14px; margin-top: 8px; letter-spacing: 0; text-shadow: none; }
#results #results-rank.dq { color: #e6a290; font-size: 15px; letter-spacing: 0.5px; text-shadow: none; }
#results .results-nearby {
  margin: 10px auto 0;
  padding: 4px;
  border: 1px solid var(--panel-border-bright);
  background: var(--panel-grad);
}
#results .results-nearby-row {
  display: grid;
  grid-template-columns: 62px 1fr auto;
  text-align: left;
  gap: 20px;
  padding: 4px 9px;
  color: var(--dim);
  font: 12px/1.4 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: 0;
  text-shadow: none;
}
#results .results-nearby-row.own {
  color: var(--accent-bright);
  background: rgba(224, 170, 69, 0.14);
  font-weight: 700;
}
#results .results-nearby-row span:last-child { font-variant-numeric: tabular-nums; }
#results .results-table {
  border-collapse: collapse;
  background: var(--panel-grad);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  overflow: hidden;
  min-width: min(620px, 84%);
}
#results .results-table th {
  background: linear-gradient(180deg, rgba(224, 170, 69, 0.12), transparent);
  color: var(--accent);
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-align: left;
  padding: 8px 14px;
  border-bottom: 1px solid var(--panel-border);
}
#results .results-table td {
  padding: 8px 14px;
  border-bottom: 1px solid var(--panel-border);
  color: var(--text);
}
#results .results-table tbody tr:last-child td { border-bottom: none; }
#results .results-table tr.me td { background: rgba(224, 170, 69, 0.06); }
#results .results-table td.ended-cleared { color: var(--good); }
#results .results-table td.ended-retreated { color: #8fa8bc; }
#results .results-table td.ended-left { color: var(--dim); font-style: italic; }

/* Game modals: every dialog is centered inside #game, with one consistent
   close affordance and backdrop dismissal. */
.game-modal-backdrop {
  position: absolute;
  /* Match the canvas play surface: leave the right rail and bottom chat
     chrome outside the modal's centering and dismissal area. */
  inset: 0 304px 82px 0;
  background: rgba(8, 8, 12, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 45;
}
.game-modal {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(460px, 100%);
  max-height: 100%;
  background: var(--panel-grad);
  border: 1px solid var(--panel-border-bright);
  border-radius: 3px;
  box-shadow: 0 16px 42px rgba(0, 0, 0, 0.62), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  overflow: hidden;
}
.game-modal-head {
  position: relative;
  flex: none;
  padding: 14px 48px 12px 18px;
  border-bottom: 1px solid var(--panel-border);
  background: linear-gradient(180deg, rgba(224, 170, 69, 0.1), transparent);
}
.game-modal-title {
  color: var(--accent-bright);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
}
.game-modal-close {
  position: absolute;
  top: 7px;
  right: 8px;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid transparent;
  background: transparent;
  color: var(--dim);
  font-size: 24px;
  line-height: 1;
}
.game-modal-close:hover { color: var(--accent-bright); border-color: var(--panel-border-bright); }
.game-modal-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 0;
  overflow: auto;
  padding: 16px;
}

/* The leave confirmation (run.md): the return portal's consequence — the
   pocket stays on the floor. */
#leave-confirm {
  background: rgba(8, 8, 12, 0.7);
}
.leave-body {
  padding: 0 0 14px;
  color: var(--text);
  line-height: 1.5;
}
.leave-row {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
.leave-stay { border-color: var(--panel-border-bright); }
.leave-go { border-color: #8fa8bc; color: #cfe3ef; }
.leave-go:hover { border-color: #bcd8e8; }

/* The sack uses the same icon cells as the HUD inventory, inside its modal. */
.sack-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  width: min(100%, 420px);
  margin: 0 auto;
}
.sack-grid .cell { cursor: pointer; }
.sack-empty {
  color: var(--dim);
  text-align: center;
  padding: 10px 0 16px;
}

/* right-click context menu */
#ctx-menu {
  /* fixed, not absolute: the menu is positioned at clientX/clientY (window
     coords) and appended to the host's root — the arena's root is offset
     within the page, so absolute would shift the menu away from the cursor. */
  position: fixed;
  background: var(--panel-grad);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  min-width: 150px;
  z-index: 50;
  display: none;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
}
#ctx-menu.show { display: block; }
#ctx-menu .ctx-title {
  padding: 5px 10px;
  color: var(--accent);
  border-bottom: 1px solid var(--panel-border);
  background: linear-gradient(180deg, rgba(224, 170, 69, 0.08), transparent);
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
}
#ctx-menu .ctx-item {
  padding: 5px 10px;
  cursor: pointer;
  white-space: nowrap;
  color: var(--text);
}
#ctx-menu .ctx-item:hover { background: #2c2c3a; }
/* Unclassified interact verbs (Enter / Open…) hover cyan, matching the
   existing click-flash colour. */
#ctx-menu .ctx-item.kind-interact:hover { background: rgba(63, 214, 224, 0.22); color: #9aeef2; }
/* Action colour belongs to the verb, even when several targets overlap.
   Neutral entries keep the normal text colour; Take, Attack, and Examine
   remain distinguishable before the pointer reaches the menu. */
#ctx-menu .ctx-item.tone-pickup { color: #e9c57a; }
#ctx-menu .ctx-item.tone-pickup:hover { background: rgba(224, 170, 69, 0.2); color: #ffe0a1; }
#ctx-menu .ctx-item.tone-attack { color: #ee8b85; }
#ctx-menu .ctx-item.tone-attack:hover { background: rgba(224, 105, 105, 0.2); color: #ffaaa2; }
#ctx-menu .ctx-item.kind-examine { color: #9fb7c9; }
#ctx-menu .ctx-item.kind-examine:hover { background: rgba(143, 180, 205, 0.14); color: #c4d9e8; }
#ctx-menu .ctx-item.disabled { color: var(--dim); cursor: default; }
#ctx-menu .ctx-item.disabled:hover { background: transparent; }
/* The attack verb's level tag: red when the NPC out-levels the hero, green
   when below (HERO_COMBAT_LEVEL — the display stand-in until leveling
   lands). */
#ctx-menu .ctx-item .ctx-tag { font-weight: 600; white-space: pre; }
#ctx-menu .ctx-item .ctx-tag.danger { color: var(--bad); }
/* the middle band of the derived NPC level (green < 35, yellow < 60, red
   above — shared/combat.ts combatLevelTone) */
#ctx-menu .ctx-item .ctx-tag.warn { color: var(--accent); }
#ctx-menu .ctx-item .ctx-tag.safe { color: #7ad17a; }

/* dungeon map overlay */
#map-overlay {
  position: absolute;
  inset: 0;
  background: #10191c;
  display: none;
  z-index: 30;
}
#map-overlay.show { display: block; }
#game #map-overlay canvas { position: absolute; inset: 0; width: 100%; height: 100%; outline: none; box-shadow: none; }
#map-overlay .map-close {
  position: absolute;
  z-index: 1;
  top: 18px;
  right: 20px;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid #6c7878;
  border-radius: 0;
  background: #2a3437;
  color: #d9ddcf;
  font-size: 26px;
  line-height: 30px;
}
#map-overlay .map-close:hover,
#map-overlay .map-close:focus-visible { color: #fff3cf; border-color: #e1c88e; outline: none; }

/* -------------------------------------------------------------------------
 * Civic workspace skin
 *
 * The hub and the floor share one room in the player's head.  Their chrome
 * should therefore feel like the same object too: a dark public building's
 * stone/iron console, with brass for durable labels and cyan for live action.
 * This is deliberately scoped to the signed-in workspace so the auth/lobby
 * screens can keep their simpler presentation.
 */
#game,
#hub {
  --workspace-ink: #0c1114;
  --workspace-void: #11171b;
  --workspace-iron: #1a2227;
  --workspace-iron-hi: #303b40;
  --workspace-stone: #293237;
  --workspace-stone-hi: #4b585b;
  --workspace-brass: #b59a66;
  --workspace-brass-hi: #e1c88e;
  --workspace-cyan: #83d4d1;
  --workspace-rust: #68473b;
  --accent: var(--workspace-brass);
  --accent-bright: var(--workspace-brass-hi);
  --panel: var(--workspace-iron);
  --panel-2: #222c31;
  --panel-3: #2a353a;
  --panel-border: #3d494d;
  --panel-border-bright: #5b686b;
  --text: #e5e5dc;
  --dim: #9aa5a5;
  --panel-grad: linear-gradient(180deg, #202a2f 0%, #151d21 100%);
  --cell-grad: linear-gradient(180deg, #2a353a 0%, #1b2428 100%);
  color: var(--text);
  font-family: "Avenir Next", "Segoe UI", system-ui, sans-serif;
  background: var(--workspace-ink);
}

#game button,
#game input,
#game select,
#hub button,
#hub input,
#hub select {
  font-family: inherit;
  border-radius: 1px;
  background: var(--workspace-iron);
  border-color: var(--workspace-stone-hi);
}

#game canvas,
#hub canvas {
  outline: 1px solid rgba(96, 112, 114, 0.58);
  outline-offset: -1px;
  box-shadow: inset 0 0 34px rgba(0, 0, 0, 0.18);
}

/* A single architectural frame around the right-hand instruments. */
#top-right {
  position: absolute;
  background:
    linear-gradient(90deg, rgba(103, 119, 120, 0.1), transparent 22%),
    linear-gradient(180deg, #172025, #0f1518 74%, #101619);
  border-left: 1px solid #526064;
  box-shadow: inset 9px 0 22px rgba(0, 0, 0, 0.32), -12px 0 22px rgba(0, 0, 0, 0.12);
  padding: 9px 8px 8px;
  gap: 6px;
}
#top-right::before {
  content: "";
  position: absolute;
  inset: 7px 5px;
  border: 1px solid rgba(123, 139, 140, 0.16);
  pointer-events: none;
}
#top-right .panel { z-index: 1; }

#game .panel,
#hub .panel {
  border: 1px solid var(--workspace-stone-hi);
  border-radius: 2px;
  background:
    linear-gradient(90deg, rgba(138, 154, 151, 0.06), transparent 8%, transparent 92%, rgba(138, 154, 151, 0.04)),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.012) 0 1px, transparent 1px 4px),
    var(--panel-grad);
  box-shadow:
    inset 0 0 0 1px rgba(7, 11, 13, 0.74),
    inset 0 10px 20px rgba(127, 143, 140, 0.035),
    0 8px 18px rgba(0, 0, 0, 0.38);
}
#game .panel-head,
#hub .panel-head {
  padding: 7px 10px 6px;
  border-bottom: 1px solid #566366;
  background:
    linear-gradient(90deg, rgba(181, 154, 102, 0.11), transparent 38%),
    linear-gradient(180deg, #303b40, #202a2e);
  box-shadow: inset 0 1px 0 rgba(221, 224, 205, 0.08);
}
#game .panel-head h3,
#hub .panel-head h3 {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 2.1px;
  color: var(--workspace-brass-hi);
  text-shadow: 0 1px 0 #0a0d0e;
}
#game .panel-badge,
#hub .panel-badge {
  border-color: #536064;
  border-radius: 1px;
  background: #182126;
  color: #bac2bd;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

#party-panel .line { padding: 4px 0; border-bottom: 1px solid rgba(92, 106, 106, 0.2); }
#party-panel .line:last-child { border-bottom: 0; }
/* Party rows WRAP (added 2026-10-25 — the playtest asked for each member's
   keys beside their name; the count is unbounded and the rail has no
   vertical scroll). The keys sit right after the name and wrap to a second
   row when the rail is narrow; the presence dot pins to the row's right
   edge with the auto margin (the name no longer carries the flex:1 that
   did that job — same look with zero keys). */
#party-panel .party-line { flex-wrap: wrap; row-gap: 2px; }
#party-panel .party-line .name { flex: none; }
#party-panel .party-line .dot { margin-left: auto; }
#party-panel .party-key {
  min-width: 14px;
  padding: 0 3px;
  border: 1px solid #536064;
  border-radius: 1px;
  background: #182126;
  color: var(--workspace-brass-hi);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 10px;
  line-height: 13px;
  text-align: center;
}
#party-panel .line .name {
  font-family: Georgia, "Times New Roman", serif;
  font-weight: 600;
  letter-spacing: 0.15px;
}
#party-panel .line .swatch { border-radius: 0; box-shadow: 0 0 0 1px rgba(236, 236, 220, 0.24); }
#party-panel .party-crown { color: var(--workspace-brass-hi); text-shadow: 0 1px 0 #0b0e0f; }
#party-panel .party-action-row { cursor: context-menu; }
#party-panel .party-action-row:hover { background: rgba(180, 151, 86, 0.12); }
#party-panel .party-leave { display: block; margin: 5px 0 0 auto; font-size: 11px; }

#equipment-panel .panel-body,
#inventory-panel .panel-body { padding: 7px; }
.inventory-grid .cell {
  border-radius: 1px;
  border-color: #4d5a5d;
  background:
    linear-gradient(135deg, rgba(165, 175, 165, 0.05), transparent 35%),
    var(--cell-grad);
  box-shadow: inset 0 1px 0 rgba(239, 236, 213, 0.07), inset 0 -4px 9px rgba(0, 0, 0, 0.22);
}
.inventory-grid .cell.empty {
  border-color: #313c40;
  background:
    repeating-linear-gradient(135deg, rgba(123, 139, 137, 0.025) 0 1px, transparent 1px 5px),
    #131a1e;
  box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.56), inset 0 0 0 1px rgba(0, 0, 0, 0.35);
}
.inventory-grid .cell.item:hover {
  border-color: var(--workspace-brass-hi);
  background: linear-gradient(135deg, rgba(190, 165, 108, 0.17), transparent 52%), #273238;
  box-shadow: inset 0 1px 0 rgba(246, 237, 202, 0.13), 0 0 12px rgba(181, 154, 102, 0.16);
}
.inventory-grid .cell .icon,
.cell-ghost .icon {
  border-radius: 1px;
  border-color: #526064;
  background: #11181b;
  box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.58), 0 1px 0 rgba(218, 219, 200, 0.05);
}
.inventory-grid .cell .cap,
.inventory-grid .cell .primary {
  font-family: Georgia, "Times New Roman", serif;
}
.inventory-grid .cell .primary {
  color: var(--workspace-brass-hi);
  background: rgba(181, 154, 102, 0.11);
  border-color: rgba(181, 154, 102, 0.46);
  border-radius: 1px;
}

/* The dock controls read as engraved sockets rather than floating web cards. */
#abilities-panel {
  gap: 5px;
  padding: 4px;
  border: 1px solid #5c696b;
  border-radius: 2px;
  background:
    linear-gradient(90deg, rgba(134, 151, 148, 0.08), transparent 17%, transparent 83%, rgba(134, 151, 148, 0.05)),
    linear-gradient(180deg, #303b40, #1b2428);
  box-shadow: inset 0 1px 0 rgba(237, 233, 210, 0.1), inset 0 -5px 12px rgba(0, 0, 0, 0.26), 0 8px 20px rgba(0, 0, 0, 0.42);
}
#abilities-panel .ability {
  width: 56px;
  padding: 6px;
  border: 1px solid #536064;
  border-top: 2px solid #8f774b;
  border-radius: 1px;
  background:
    linear-gradient(135deg, rgba(167, 180, 169, 0.065), transparent 40%),
    linear-gradient(180deg, #2a353a, #1b2428);
  box-shadow: inset 0 1px 0 rgba(230, 231, 210, 0.08), inset 0 -5px 10px rgba(0, 0, 0, 0.22);
}
#abilities-panel .ability .ability-icon { color: var(--workspace-brass-hi); }
#abilities-panel .ability.map-ability .ability-icon { color: #dfc98f; }
#abilities-panel .ability.map-ability { border-top-color: #a9915e; }
#abilities-panel .ability[data-icon="summon-pgt"] .ability-icon { color: #b7a0e9; }
#abilities-panel .ability[data-icon="teleport"] .ability-icon,
#abilities-panel .ability[data-icon="teleport-pgt"] .ability-icon,
#abilities-panel .ability[data-icon="teleport-ggs"] .ability-icon { color: var(--workspace-cyan); }
#abilities-panel .ability .key {
  top: 3px;
  left: 5px;
  color: var(--workspace-brass-hi);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
#abilities-panel .ability:hover:not(:disabled) {
  border-color: var(--workspace-brass-hi);
  box-shadow: inset 0 1px 0 rgba(246, 237, 202, 0.14), 0 0 13px rgba(181, 154, 102, 0.2);
  transform: translateY(-1px);
}
#abilities-panel .ability:disabled { border-top-color: #465256; opacity: 0.62; pointer-events: none; }
#abilities-panel .ability.cooling:disabled { opacity: 1; }
#abilities-panel .ability.cooling .ability-icon { opacity: 0.45; }
#abilities-panel .ability.active {
  border-color: var(--workspace-brass-hi);
  box-shadow: inset 0 0 14px rgba(181, 154, 102, 0.2);
}
#abilities-panel .ability.armed {
  border-color: var(--workspace-cyan);
  border-top-color: var(--workspace-cyan);
  box-shadow: inset 0 0 14px rgba(131, 212, 209, 0.16), 0 0 11px rgba(131, 212, 209, 0.18);
}
#abilities-panel .ability[data-icon="phoenix-teleport"] .ability-icon { color: #e6a56c; }
#abilities-panel .ability[data-icon="phoenix-teleport"].active {
  border-color: #db9959;
  background: radial-gradient(ellipse at 50% 65%, rgba(224, 114, 39, 0.2), transparent 75%), linear-gradient(180deg, #34332e, #282321);
  box-shadow: inset 0 0 12px rgba(230, 130, 55, 0.15), 0 0 10px rgba(230, 130, 55, 0.18);
}
#abilities-panel .ability[data-icon="phoenix-teleport"].active .ability-icon {
  color: #ffce91;
  filter: drop-shadow(0 0 3px rgba(255, 145, 55, 0.4));
}
#abilities-panel .ability-split { background: #76827f; opacity: 0.65; }

#status-panel .room-code {
  font-family: Georgia, "Times New Roman", serif;
  color: var(--workspace-brass-hi);
  text-shadow: 0 1px 0 #0a0d0e;
}
#status-panel .status-foot { color: #788583; border-top-color: rgba(92, 106, 106, 0.34); }
#status-panel .status-buff .v { color: var(--workspace-cyan); }

/* Subtle inset rails give empty sockets a physical edge without adding
 * another icon system or inventing player-facing copy. */
.inventory-grid .cell {
  position: relative;
}
.equip-cell::before,
.inventory-grid .cell::before {
  content: "";
  position: absolute;
  inset: 4px;
  border-top: 1px solid rgba(174, 187, 177, 0.08);
  border-bottom: 1px solid rgba(0, 0, 0, 0.2);
  pointer-events: none;
}
.equip-cell.empty::before,
.inventory-grid .cell.empty::before {
  inset: 5px;
  border-color: rgba(125, 143, 140, 0.08);
}

/* Chat is a dispatch ledger inset into the same building, not a floating app. */
#chat-panel {
  border-radius: 2px;
  padding: 8px 10px;
  background:
    linear-gradient(90deg, rgba(126, 143, 140, 0.06), transparent 20%),
    linear-gradient(180deg, #202a2e, #141c20);
  border-color: #4f5c60;
  box-shadow: inset 0 1px 0 rgba(229, 230, 210, 0.07), 0 8px 18px rgba(0, 0, 0, 0.4);
}
#chat-log .system { color: #879390; }
#chat-form input {
  border-radius: 1px;
  background: #11181b;
  border-color: #4c595d;
}
#chat-form input:focus { border-color: var(--workspace-cyan); box-shadow: 0 0 8px rgba(131, 212, 209, 0.14); }
#chat-form button { border-color: #68746e; color: var(--workspace-brass-hi); }

/* Keep the world-facing text sparse and inscription-like. */
#hover-readout,
#hub-top,
#hub-bottom {
  background: transparent;
  border: 0;
  border-radius: 0;
  text-shadow: 0 1px 2px #000;
}
#hover-readout {
  color: var(--workspace-cyan);
  font-family: Georgia, "Times New Roman", serif;
  letter-spacing: 0.15px;
}
#hub-top { padding: 4px 0; }
#hub-top .linkish,
#hub-invite .linkish {
  color: var(--workspace-brass-hi);
  text-decoration: none;
  border-bottom: 1px solid rgba(225, 200, 142, 0.48);
  font-family: Georgia, "Times New Roman", serif;
}
#hub-bottom .hint { color: #a0aaa6; }

#game .game-modal,
#hub .game-modal {
  border-radius: 2px;
  border-color: #5b686b;
  background:
    linear-gradient(90deg, rgba(181, 154, 102, 0.09), transparent 28%),
    linear-gradient(180deg, #283237, #151d21);
  box-shadow: inset 0 1px 0 rgba(232, 231, 208, 0.08), 0 12px 28px rgba(0, 0, 0, 0.5);
}
#game .game-modal-title,
#hub .game-modal-title { color: var(--workspace-brass-hi); }
#game .modal-secondary,
#hub .modal-secondary { color: #aab4ae; }

#game #banner,
#game #exit-countdown,
#game #results,
#hub #banner {
  border-radius: 2px;
  border-color: var(--workspace-brass-hi);
  background: linear-gradient(180deg, #332a1c, #171811);
  box-shadow: 0 0 38px rgba(181, 154, 102, 0.18);
}
/* The one-page art download/decode gate. Gameplay scenes only mount after it. */
.art-loading {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  color: #e9dfc9;
  background: #101017;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  text-align: center;
}
.art-loading h1 { margin: 0; font-size: 24px; }
.art-loading p { margin: 0; max-width: 36rem; }
.art-loading button { padding: 8px 20px; cursor: pointer; }

#bull-dialog a.linkish { color: var(--accent-bright); font-size: 13px; text-decoration: underline; }
#bull-dialog a.linkish:hover { color: var(--text); }
.connection-notice {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 25;
  padding: 10px 18px;
  border: 1px solid #b99755;
  border-radius: 6px;
  background: #191b23;
  color: #f4dfb1;
  pointer-events: none;
}
