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

html, body {
  --minimap-size: 150px;
  height: 100%;
  overflow: hidden;
  background: #12180f;
  color: #e8e2d0;
  font: 13px/1.4 "Trebuchet MS", "Segoe UI", sans-serif;
  user-select: none;
}

#view { display: block; width: 100vw; height: 100vh; cursor: crosshair; }

#ui { position: fixed; inset: 0; pointer-events: none; }
#ui button { pointer-events: auto; }

.hidden { display: none !important; }

.quest-inspect {
  position: absolute; bottom: 145px; left: 50%; transform: translateX(-50%);
  max-width: 85vw; padding: 8px 14px; border: 1px solid #8b733d; border-radius: 4px;
  color: #e8d99c; background: rgba(28,25,16,.94); font: inherit;
}
.quest-inspect:hover, .quest-inspect.hovered { background: #4b3d24; color: #fff1b4; }
.quest-inspect:focus-visible { outline: 2px solid #e9c46a; outline-offset: 2px; }

/* ---- unit frames ---- */

.frame {
  position: absolute;
  display: flex;
  gap: 8px;
  width: 260px;
  padding: 6px;
  background: rgba(10, 14, 8, 0.75);
  border: 2px solid #6b5a2e;
  border-radius: 6px;
}

#playerFrame { top: 16px; left: 16px; }
#targetFrame { top: 16px; left: 296px; }

.portrait {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border: 2px solid #6b5a2e;
  border-radius: 50%;
  font: bold 20px/1 "Trebuchet MS", sans-serif;
}
.portrait.mage { background: radial-gradient(circle at 35% 30%, #6ea8ff, #1e3a8a); color: #eaf2ff; }
.portrait.mob  { background: radial-gradient(circle at 35% 30%, #a68b6a, #4b3524); color: #ffeccc; }

.bars { flex: 1; display: flex; flex-direction: column; gap: 3px; }
/* Name first, then whatever marks the frame is wearing, then the level hard
   against the right edge. Packed from the left rather than spread, or a frame
   showing one mark would centre it and a frame showing two would not. */
.row { display: flex; justify-content: flex-start; font-weight: bold; text-shadow: 0 1px 2px #000; }
.row > :last-child { margin-left: auto; }

.bar {
  position: relative;
  height: 15px;
  background: #1b1b1b;
  border: 1px solid #000;
  border-radius: 3px;
  overflow: hidden;
}
.bar i { position: absolute; inset: 0; width: 100%; transform-origin: left; transition: transform .12s linear; }
.bar b {
  position: relative;
  display: block;
  text-align: center;
  font-size: 11px;
  line-height: 13px;
  text-shadow: 0 1px 2px #000;
}
.bar.hp i   { background: linear-gradient(#43d15a, #1d7a2c); }
.bar.mana i { background: linear-gradient(#5aa2ff, #1b47a8); }

/* ---- cast bar ---- */

#castBar {
  position: absolute;
  left: 50%;
  bottom: 150px;
  width: 260px;
  height: 20px;
  margin-left: -130px;
  background: #1b1b1b;
  border: 1px solid #000;
  border-radius: 3px;
  overflow: hidden;
}
#castBar i {
  position: absolute; inset: 0;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left;
  /* the spell being cast sets these; the fallback is the fire it used to be */
  background: linear-gradient(var(--cast-light, #ffd166), var(--cast-dark, #d97706));
}
#castBar b {
  position: relative;
  display: block;
  text-align: center;
  font-size: 12px;
  line-height: 18px;
  color: #fff;
  text-shadow: 0 1px 2px #000;
}

/* ---- warnings ---- */

/* Sat directly on top of the cast bar and laid out upwards, so a new refusal
   appears where the last one was and the older ones climb away from it. They
   are read at a glance or not at all: nothing here can be clicked, and nothing
   waits to be dismissed. */
#warnings {
  position: absolute;
  left: 50%;
  bottom: 176px;
  width: min(420px, 90vw);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column-reverse;
  align-items: center;
  gap: 2px;
  pointer-events: none;
  z-index: 30;
}
/* Fully lit from the first frame: what makes a warning worth having is that it
   is already there when you look down at the cast bar. Only the leaving is
   animated. */
#warnings .warning {
  font: 16px Georgia, serif;
  color: #ff6a5e;
  text-shadow: 0 1px 3px #000, 0 0 12px rgba(0, 0, 0, .8);
  text-align: center;
}
#warnings .warning.showing { animation: warning-line 4s ease-out forwards; }
/* Older lines are dimmer and smaller as well as higher up: three of them at
   once should read as one warning with a history, not as three warnings. */
#warnings .warning:nth-child(2) { font-size: 15px; color: #d4574d; }
#warnings .warning:nth-child(3) { font-size: 14px; color: #a8443c; }
@keyframes warning-line {
  0%   { opacity: 1; transform: translateY(6px); }
  6%   { opacity: 1; transform: none; }
  72%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ---- action bar ---- */

#actionBar {
  position: absolute;
  left: 50%;
  bottom: 60px;
  transform: translateX(-50%);
  display: flex;
  gap: 6px;
}

.slot {
  position: relative;
  width: 52px;
  height: 52px;
  background: radial-gradient(circle at 40% 30%, #4b2a16, #1a0f08);
  border: 2px solid #6b5a2e;
  border-radius: 6px;
  color: #fff;
  cursor: pointer;
}
.slot:hover { border-color: #d9b45a; }
/* An empty slot is a place rather than a button: still there to be filled, but
   not asking to be pressed. */
.slot.empty {
  background: rgba(0, 0, 0, .35);
  border-style: dashed;
  border-color: #4a4130;
  cursor: default;
}
.slot.empty:hover { border-color: #6b5a2e; }

/* The two that make the bar longer and shorter, at the end of it where what
   they add and take away can be seen. */
.bar-resize-controls {
  display: flex;
  flex-direction: column;
  gap: 4px;
  height: 52px;
}
.bar-resize {
  flex: 1;
  min-height: 0;
  padding: 0;
  width: 22px;
  background: rgba(0, 0, 0, .5);
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  color: #cbbf9a;
  font: 16px "Trebuchet MS", sans-serif;
  line-height: 1;
  cursor: pointer;
}
.bar-resize:hover { color: #fff; border-color: #cbbf9a; }
.slot .icon { position: absolute; inset: 0; }
.slot .key {
  position: absolute; top: 1px; left: 4px;
  font-size: 11px; font-weight: bold; text-shadow: 0 1px 2px #000;
}
.slot .cd {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .6);
  transform: scaleY(0);
  transform-origin: bottom;
  pointer-events: none;
}
.slot .cooldown-time {
  position: absolute; inset: 0; display: grid; place-items: center;
  color: #fff1c7; font-size: 18px; font-weight: bold; pointer-events: none;
  text-shadow: 0 1px 3px #000, 0 0 4px #000;
}
.slot.nomana, .slot.outofrange { filter: grayscale(1) brightness(.7); }
.slot.active {
  border-color: #ffd166;
  box-shadow: 0 0 10px 2px rgba(255, 209, 102, .7);
}

/* Said only while the pointer belongs to the desktop rather than the game, so
   that a click doing nothing but coming back is a thing the player expects. */
#resume {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  z-index: 60;
  padding: 10px 22px;
  border: 1px solid #6b5a2e;
  border-radius: 6px;
  background: rgba(12, 16, 10, .85);
  color: #f2e2b8;
  font-size: 15px;
  letter-spacing: .04em;
  pointer-events: none;
}

/* The game's own pointer. It sits above everything and is never itself a hit
   target, or the thing under the cursor would always be the cursor. */
#cursor {
  position: fixed;
  top: 0; left: 0;
  /* big enough that a gauntlet reads as one. The point that clicks is the
     top-left corner, so the size only decides how far the art trails off it. */
  width: 30px;
  height: 30px;
  z-index: 100;
  pointer-events: none;
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: 30px 30px;
  filter: drop-shadow(1px 1px 1px rgba(0, 0, 0, .9));
}

/* Four hands, and every one of them points with its top-left corner, so the
   thing being clicked is the thing under that corner whichever is showing.
   Which one it is answers the question the right button would: a gauntlet for
   nothing in particular, a sword for something that would be swung at, a purse
   for a body worth searching, a bubble for somebody worth talking to. */
#cursor {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg stroke='%2323272e' stroke-width='1.5' stroke-linejoin='round'%3E%3Cpath d='M5.4 11.8c-2.2.2-3.4 1.8-3 3.8.4 1.8 2 2.8 3.6 2.4z' fill='%23c9d2dd'/%3E%3Cpath d='M1.9 1.9 4.3 5.1 6.4 9.2' stroke-width='5' stroke-linecap='round' fill='none'/%3E%3Cpath d='M1.9 1.9 4.3 5.1 6.4 9.2' stroke='%23c9d2dd' stroke-width='3' stroke-linecap='round' fill='none'/%3E%3Cpath d='M4.8 10.4h7.6a3.4 3.4 0 0 1 3.4 3.4v2.8a4.6 4.6 0 0 1-4.6 4.6H8.4a3.6 3.6 0 0 1-3.6-3.6z' fill='%23c9d2dd'/%3E%3C/g%3E%3Cg fill='%238e9aa8' stroke='%2323272e' stroke-width='1.3' stroke-linejoin='round'%3E%3Cpath d='M6.8 20.4h7l-.8 2.8H7.6z'/%3E%3C/g%3E%3Cg stroke='%2323272e' stroke-width='1' fill='none' stroke-linecap='round'%3E%3Cpath d='M2.5 4.5 4.9 3.2M4.6 7.6 6.7 6.5' opacity='.8'/%3E%3Cpath d='M5.6 12.4c1 1.6 1 3.6 0 5.4' opacity='.6'/%3E%3Cpath d='M6.4 14.6h6.8M6.4 17.4h6.8' opacity='.65'/%3E%3C/g%3E%3C/svg%3E");
}
#cursor.attack {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg stroke='%2323272e' stroke-width='1.4' stroke-linejoin='round'%3E%3Cpath d='M1.1 1.1 3.7 1.5 14.6 12.4 12.4 14.6 1.5 3.7z' fill='%23e2e8f0'/%3E%3Cpath d='M14.6 16.4 12.2 14 14 12.2 16.4 14.6z' fill='%23c9d2dd'/%3E%3Cpath d='M10.2 17.4 17.4 10.2 19.2 12 12 19.2z' fill='%23b08a3e'/%3E%3Cpath d='M15.1 16.9 16.9 15.1 20.4 18.6 18.6 20.4z' fill='%236b4a2a'/%3E%3Ccircle cx='21.2' cy='21.2' r='1.8' fill='%23b08a3e'/%3E%3C/g%3E%3Cg stroke='%2323272e' stroke-width='1' opacity='.55' fill='none'%3E%3Cpath d='M2.6 2.6 12.8 12.8M16.6 17.4 18.4 15.6M18.1 18.9 19.9 17.1'/%3E%3C/g%3E%3C/svg%3E");
}
#cursor.loot {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M1.4 1.4 8 6' stroke='%2323272e' stroke-width='1.6' stroke-linecap='round'/%3E%3Cpath d='M7 6.4h9l-1.6 2.4c3 1.6 5 4.2 5 7 0 3.4-3.4 5.8-7.9 5.8S2.6 19.2 2.6 15.8c0-2.8 2-5.4 5-7z' fill='%23c69a4e' stroke='%2323272e' stroke-width='1.4' stroke-linejoin='round'/%3E%3Cpath d='M6.6 8.8h9.8' stroke='%2323272e' stroke-width='1.2' opacity='.7'/%3E%3C/svg%3E");
}
#cursor.talk {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M1.2 1.2 7 6.4h11.4a3.4 3.4 0 0 1 3.4 3.4v6.4a3.4 3.4 0 0 1-3.4 3.4H7.6a3.4 3.4 0 0 1-3.4-3.4V6.6z' fill='%23e8eef6' stroke='%2323272e' stroke-width='1.4' stroke-linejoin='round'/%3E%3Cg fill='%2323272e'%3E%3Ccircle cx='9.4' cy='13' r='1.3'/%3E%3Ccircle cx='13.4' cy='13' r='1.3'/%3E%3Ccircle cx='17.4' cy='13' r='1.3'/%3E%3C/g%3E%3C/svg%3E");
}
/* while the game holds the pointer, the hardware one has nothing to show */
body.own-cursor, body.own-cursor * { cursor: none !important; }

/* :hover belongs to a real pointer, so everything that reacts to one reacts to
   the class the cursor puts on instead */
.slot:hover, .slot.hovered { border-color: #d9b45a; }
.panel-close:hover, .panel-close.hovered { color: #fff; border-color: #cbbf9a; }
.cs-slot.filled.hovered, .slot-cell.filled.hovered { border-color: #d9b45a; }

/* what is being carried, following the pointer a little behind it */
#dragGhost {
  width: 36px;
  height: 36px;
  position: fixed;
  top: 0; left: 0;
  z-index: 99;
  pointer-events: none;
  font-size: 22px;
  filter: drop-shadow(1px 2px 2px rgba(0, 0, 0, .8));
}

#stale {
  position: absolute;
  /* clear of the unit frames, which own the whole top edge */
  top: 108px; left: 50%;
  transform: translateX(-50%);
  z-index: 40;
  padding: 6px 12px;
  border: 1px solid #d9b45a;
  border-radius: 4px;
  background: rgba(24, 20, 10, .92);
  color: #f2e2b8;
  font-size: 12px;
}
#stale button {
  margin-left: 8px;
  padding: 2px 10px;
  border: 1px solid #d9b45a;
  border-radius: 3px;
  background: #3a2f14;
  color: #f2e2b8;
  cursor: pointer;
}
#stale button:hover { background: #55441c; }

/* ---- xp bar ---- */

#xpBar {
  position: absolute;
  left: 50%;
  bottom: 26px;
  width: 420px;
  height: 14px;
  margin-left: -210px;
  background: #1b1b1b;
  border: 1px solid #000;
  border-radius: 3px;
  overflow: hidden;
}
#xpBar i {
  position: absolute; inset: 0;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left;
  background: linear-gradient(#a855f7, #6b21a8);
}
#xpBar b {
  position: relative;
  display: block;
  text-align: center;
  font-size: 10px;
  line-height: 12px;
  text-shadow: 0 1px 2px #000;
}

/* ---- misc ---- */

#logPanel {
  position: absolute;
  left: 16px;
  bottom: 26px;
  width: 380px;
  display: flex;
  flex-direction: column;
  font-size: 12px;
  text-shadow: 0 1px 2px #000;
  background: rgba(0, 0, 0, var(--chat-background-opacity, .4));
  border-radius: 4px;
  padding: 6px;
  box-sizing: border-box;
}

#logTabs {
  display: flex;
  gap: 4px;
  margin-bottom: 3px;
  pointer-events: auto;
}
.log-tab {
  padding: 1px 8px;
  background: rgba(0, 0, 0, .45);
  border: 1px solid #3c3520;
  border-radius: 3px 3px 0 0;
  color: #9c9683;
  font: 11px "Trebuchet MS", sans-serif;
  cursor: pointer;
}
.log-tab:hover { color: #cbbf9a; }
.log-tab.active { color: #ffd166; border-color: #6b5a2e; background: rgba(0, 0, 0, .7); }
/* something arrived on the tab you are not looking at */
.log-tab.unread { color: #a8e063; }
.log-tab.unread::after { content: ' •'; }

.log-lines {
  max-height: 170px;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}
.log-lines::-webkit-scrollbar { display: none; }
/* The lines are placed rather than stacked, because only the handful the box
   can show is ever in the document and each one has to land where the whole
   log says it belongs — see loglines.js. */
.log-run { position: relative; }
.log-run > div { position: absolute; left: 0; right: 0; padding-bottom: 2px; }

/* Where a line is measured before it is placed: the same width and the same
   text, somewhere nothing composites. */
.log-rule {
  position: absolute;
  visibility: hidden;
  left: -10000px;
  top: 0;
  max-height: none;
  overflow: visible;
  padding-bottom: 2px;
}

/* The log is only ever looked at, so a click aimed past it reaches the world.
   Its scrollbar is the one part of it you take hold of. */
#logPanel .scroll-bar { pointer-events: auto; }
.log-lines div.dmg  { color: #ffd166; }
.log-lines div.hurt { color: #ff8080; }
.log-lines div.sys, .log-lines div.death { color: #9fd6ff; }
.log-lines div.xp   { color: #d8b4fe; }
.log-lines div.err  { color: #ff6b6b; }
.log-lines div.chat { color: #ffffff; }
.log-lines div.yell, .bubble.yell { color: #ff6666; }
.log-lines div.party, #chatBox[data-mode="party"] { color: #70baff; }
.log-lines div.loot { color: #d8b4fe; }
.log-lines div.evade { color: #cbbf9a; }
.log-lines div.dodge { color: #9fd6ff; }

/* Sits in the gap below the log, where WoW puts it. */
#chatBox {
  position: absolute;
  left: 16px;
  bottom: 4px;
  display: flex;
  align-items: center;
  gap: 6px;
  width: 380px;
  font-size: 12px;
  pointer-events: auto;
  text-shadow: 0 1px 2px #000;
}
#chatBox { color: #ffffff; }
#chatBox[data-mode="yell"] { color: #ff6666; }
#chatInput {
  flex: 1;
  padding: 2px 6px;
  background: rgba(0, 0, 0, .6);
  border: 1px solid #6b5a2e;
  border-radius: 3px;
  color: inherit;
  font: 12px "Trebuchet MS", sans-serif;
  outline: none;
}

/* Crossed swords beside the name while the fight is on — the same five seconds
   that keep health and mana from refilling. */
.combat-mark {
  margin-left: 5px;
  font-size: 13px;
  line-height: 1;
  filter: drop-shadow(0 0 2px #000);
}

/* the only way to select yourself, since your body ignores clicks */
#playerFrame { pointer-events: auto; cursor: pointer; }

/* ---- party ---- */

/* Under our own frame, which stands 70px tall from a top of 16 — measured, not
   guessed, because it carries a resource bar the others do not. Everyone else
   in the party stacks downwards from there, smaller than ours because they are
   somebody else's health and ours is the one we die by. */
#partyFrames {
  position: absolute;
  top: 92px;
  left: 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.party-frame {
  position: static;
  width: 200px;
  gap: 6px;
  cursor: pointer;
  pointer-events: auto;
}
.party-frame .portrait { width: 40px; height: 40px; font-size: 17px; flex-shrink: 0; }
.party-frame .bars { min-width: 0; }
.party-frame .row { font-size: 12px; }
.party-frame .bar { height: 12px; }
.party-frame .bar b { font-size: 10px; line-height: 10px; }
.party-frame.targeted { border-color: #cbbf9a; }
.party-frame.dead { opacity: .55; }
/* Remote status remains readable, with location separate from the health bar. */
.party-frame.elsewhere { opacity: .85; }
.party-frame .pf-location { color: #cbbf9a; font-size: 10px; text-align: right; }
.party-frame .pf-level { white-space: nowrap; flex-shrink: 0; }
.party-frame.elsewhere .bar b { color: #cbbf9a; }

.pf-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.leader-mark, .pf-leader {
  margin-left: 5px;
  font-size: 12px;
  line-height: 1;
  filter: drop-shadow(0 0 2px #000);
}

/* Three quarters of the way up, in the middle: over nothing that is being
   fought and under nothing that is being read. */
#invitePanel {
  top: 25%;
  transform: translate(-50%, -50%);
  max-width: 320px;
}
#invitePanel p { font-size: 14px; color: #f2ecd8; }
#invitePanel #inviteFrom { color: #ffd166; }
.invite-buttons { display: flex; gap: 10px; justify-content: center; }
.invite-buttons button { flex: 1; }

/* ---- bags and loot ---- */

#inventoryPanel {
  position: absolute;
  right: 16px;
  bottom: 90px;
  width: 260px;
  padding: 12px 14px 14px;
  background: rgba(12, 16, 10, .93);
  border: 2px solid #6b5a2e;
  border-radius: 8px;
  pointer-events: auto;
  font-size: 13px;
}
#inventoryGrid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 5px;
}
.slot-cell {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  position: relative;      /* so the stack count has a corner of its own to sit in */
  background: rgba(0, 0, 0, .45);
  border: 1px solid #3c3520;
  border-radius: 4px;
  font-size: 18px;
}
.slot-cell.filled { border-color: #6b5a2e; background: rgba(60, 48, 20, .5); }

/* Taking part of a stack. Small, opened at the cursor, and gone the moment it
   has an answer — it is a question rather than a panel. */
#splitPanel {
  position: absolute;
  z-index: 60;
  width: 180px;
  padding: 10px 12px 12px;
  background: rgba(12, 16, 10, .96);
  border: 2px solid #6b5a2e;
  border-radius: 8px;
  pointer-events: auto;
  font-size: 13px;
}
#splitRow {
  display: flex;
  align-items: center;
  gap: 6px;
}
#splitRow button {
  width: 26px;
  flex: none;
  padding: 3px 0;
  font-size: 15px;
  line-height: 1;
}
#splitCount {
  flex: 1;
  min-width: 0;
  padding: 3px 6px;
  background: rgba(0, 0, 0, .6);
  border: 1px solid #6b5a2e;
  border-radius: 3px;
  color: #f2ecd8;
  font: inherit;
  text-align: center;
}
/* the browser's own spinner needs a real pointer, and there is not one */
#splitCount::-webkit-outer-spin-button,
#splitCount::-webkit-inner-spin-button { appearance: none; margin: 0; }
#splitCount { appearance: textfield; -moz-appearance: textfield; }
#splitRange {
  margin: 6px 0 8px;
  color: #9c9683;
  font-size: 11px;
  text-align: center;
}
#splitConfirm { width: 100%; }

#coinRow {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 10px;
  font-size: 12px;
}
.coin b { color: #f2ecd8; font-weight: normal; }
.coin.gold { color: #e8c352; }
.coin.silver { color: #cfd3d6; }
.coin.copper { color: #c98a5b; }

/* What a thing says about itself. Drawn rather than left to the browser: a
   `title` needs a real pointer to rest on something and there is not one. */
.tooltip {
  position: fixed;
  z-index: 90;
  pointer-events: none;      /* it must never be what the cursor is over */
  max-width: 260px;
  padding: 8px 10px 9px;
  background: rgba(8, 10, 7, .96);
  border: 1px solid #4a4126;
  border-radius: 6px;
  font-size: 12.5px;
  line-height: 1.35;
}
.tip-name { font-size: 14px; margin-bottom: 3px; }
.tip-line { color: #ded8c4; }
.tip-faint { color: #9a927a; }
.tip-warn { color: #e5654f; margin-top: 3px; }
.tip-note { color: #b9ad86; font-style: italic; margin-top: 5px; }
.tip-coins { color: #d9b45a; margin-top: 5px; }
.tip-compare { color: #9a927a; margin-top: 6px; padding-top: 5px; border-top: 1px solid #302b1c; }
.tip-delta.good { color: #79d15f; }
.tip-delta.bad { color: #e5654f; }
.tip-delta.same { color: #9a927a; }

/* A conversation, put where the shop goes, because it is the same window one
   step earlier: you talk to her and the shop is one of the things talking can
   lead to, so the second opens where the first was and the eye stays put. It is
   wider than the shop because prose needs a line worth reading. */
#dialoguePanel {
  position: absolute;
  top: 90px;
  /* clear of the party frames, which start at the same height on the left and
     which an opaque window sitting on top of them would simply delete */
  left: 232px;
  width: 340px;
  padding: 12px 14px 14px;
  background: rgba(12, 16, 10, .93);
  border: 1px solid #4a4126;
  border-radius: 8px;
  font-size: 13px;
}
.dialogue-text {
  white-space: pre-line;
  margin: 0 0 12px;
  color: #ded8c4;
  line-height: 1.45;
}
.dialogue-options {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.dialogue-option {
  padding: 7px 9px;
  border: 1px solid #3c3520;
  border-radius: 5px;
  background: rgba(0, 0, 0, .35);
  color: #ffd166;
  font: inherit;
  text-align: left;
  line-height: 1.3;
  cursor: pointer;
}
.dialogue-option:hover, .dialogue-option.hovered {
  border-color: #cbbf9a;
  background: rgba(60, 53, 32, .5);
  color: #fff;
}
/* The way out is always the last thing on the list and never the loudest. */
.dialogue-option.farewell { color: #b9ad86; }
/* Taking one on and handing one in are what the window is for when they are on
   it, so they do not read as one more thing to chat about. */
.dialogue-option.commit {
  border-color: #7d6a30;
  background: rgba(125, 106, 48, .25);
  font-weight: bold;
}

/* ---- quests ---- */

/* The mark beside a line that leads to a quest. Its colour is set from the same
   table the one hanging over the npc's head is painted from, and so is not
   here — a colour kept in two places is a colour that will one day be two. */
.quest-mark {
  margin-right: 7px;
  font-weight: bold;
}

/* And the line itself, so that which answer is an errand can be seen without
   reading any of them. The colour of the edge comes from the mark for the same
   reason the glyph's does; only how wide it is belongs here. */
.dialogue-option.quest {
  border-left-width: 3px;
  padding-left: 7px;
}

/* What it asks for and what it pays, between the flavour and the answers. */
.quest-detail {
  margin: 0 0 12px;
  padding: 10px 11px;
  background: rgba(0, 0, 0, .3);
  border: 1px solid #3c3520;
  border-radius: 5px;
}
.quest-detail h3 {
  margin-bottom: 8px;
  font-size: 14px;
  color: #ffd166;
}
.quest-detail h4 {
  margin: 8px 0 3px;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #8f8874;
}
.quest-detail h4:first-of-type { margin-top: 0; }
.quest-objectives { margin: 0; padding-left: 16px; color: #b9ad86; }
.quest-objectives li.done { color: #fff; }
.quest-reward { margin: 0; color: #ded8c4; }

/* The tracker, down the right under the map — the corner the map, the auras and
   the bags already share, so nothing that matters is anywhere else. */
#questTracker {
  position: absolute;
  right: 16px;
  top: 262px;
  width: 190px;
  font-size: 12px;
  text-shadow: 0 1px 2px #000;
}
#questTracker h3 {
  margin-bottom: 6px;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #8f8874;
}
#questList { display: flex; flex-direction: column; gap: 8px; }
.quest-name { color: #ffd166; font-weight: bold; background: none; border: 0; text-align: left; font-family: inherit; font-size: inherit; text-shadow: inherit; cursor: pointer; }
.quest-name:hover { text-decoration: underline; }
#questTracker { max-height: calc(100vh - 360px); overflow-y: auto; pointer-events: auto; }
#questLogPanel { width: min(820px, 94vw); height: min(530px, 82vh); padding: 18px; }
.quest-log-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.quest-log-body { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); flex: 1; min-height: 0; text-align: left; border-top: 1px solid #6b5a2e; border-bottom: 1px solid #6b5a2e; }
#questLogDetail, #questLogList, #questTracker { scrollbar-width: thin; scrollbar-color: #6b5a2e #171b10; }
#questLogDetail, #questLogList { overflow-y: auto; padding: 16px 12px; }
#questLogDetail { background: #292719; line-height: 1.6; overflow-wrap: anywhere; }
#questLogDetail h3 { font-size: 19px; color: #ffd166; }
.quest-log-level { color: #b6aa88; margin: 4px 0 16px; font-size: 12px; }
.quest-log-text { white-space: pre-wrap; margin-bottom: 18px; }
#questLogDetail ul { padding-left: 18px; color: #b9af95; }
#questLogDetail .done { color: #fff; }
.quest-log-destination { margin-top: 16px; color: #d8c48f; }
#questLogList { border-left: 1px solid #6b5a2e; }
#questLogList .quest-log-choice { display: flex; align-items: baseline; gap: 8px; width: 100%; text-align: left; padding: 10px 8px; margin-bottom: 6px; font-size: 13px; }
#questLogList .selected { border-color: #ffd166; background: #433921; }
.quest-track-mark { color: #ffd166; flex: 0 0 14px; }
.quest-log-row { display: flex; align-items: center; gap: 8px; }
.quest-log-row .quest-track-mark { appearance: none; height: 14px; margin: 0; border: 1px solid #6b5a2e; border-radius: 2px; background: #171b10; cursor: pointer; }
.quest-track-mark:checked::after { content: '✓'; display: block; font-size: 12px; line-height: 12px; text-align: center; }
.quest-track-mark:hover, .quest-track-mark.hovered, .quest-track-mark:focus-visible { border-color: #ffd166; }
.chat-link { display: inline; padding: 0; margin: 0; border: 0; border-radius: 0; background: none; font: inherit; line-height: inherit; text-align: left; pointer-events: auto; cursor: pointer; }
.chat-link:hover, .chat-link.hovered, .chat-link:focus-visible { background: none; text-decoration: underline; }
.chat-link-panel { top: 20%; right: 16px; width: min(330px, calc(100vw - 32px)); max-width: none; pointer-events: auto; padding: 14px; }
.chat-link-panel > .panel-close { display: block; margin: 0 0 8px auto; }
.chat-link-body { overflow-y: auto; max-height: 55vh; overflow-wrap: anywhere; }
.chat-link-body p { white-space: pre-wrap; margin: 12px 0; }
.chat-link-body ul { padding-left: 18px; color: #ded8c4; }
.quest-log-hint { color: #b6aa88; margin-top: 12px; font-size: 12px; }
#questLogActions { margin-top: 12px; flex-shrink: 0; text-align: left; }
#abandonQuest, #confirmAbandonQuest { border-color: #a45a4e; color: #ffd4c9; background: #452323; }
#abandonQuestPrompt { margin-bottom: 8px; color: #e8d8bd; font-size: 12px; }
#cancelAbandonQuest { margin-left: 8px; }
/* Grey while it is still being done and white the moment it is not: the tracker
   says whether there is anything to walk back for without having to be read. */
.quest-objective { margin-left: 8px; color: #9a937f; }
.quest-objective.done { color: #fff; }

/* The shop, put where the character sheet goes: they are both windows you stand
   still to read, and only one of them is ever open. */
#vendorPanel {
  position: absolute;
  top: 90px;
  left: 16px;
  width: 260px;
  padding: 12px 14px 14px;
  background: rgba(12, 16, 10, .93);
  border: 1px solid #4a4126;
  border-radius: 8px;
  font-size: 13px;
}
#vendorStock {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 5px;
}
.vendor-hint {
  margin: 0 0 10px;
  color: #b9ad86;
  font-size: 12px;
  line-height: 1.35;
}
.vendor-empty {
  margin: 10px 0 0;
  color: #8b8266;
  font-size: 12px;
  font-style: italic;
}

#lootPanel {
  position: absolute;
  /* Placed at the cursor when it opens; these are only where it would land if
     that ever failed to happen. */
  left: 50%;
  top: 35%;
  width: 200px;
  padding: 10px 12px 12px;
  background: rgba(12, 16, 10, .95);
  border: 2px solid #6b5a2e;
  border-radius: 8px;
  pointer-events: auto;
  font-size: 13px;
}
#lootPanel h2 { font-size: 15px; }
.loot-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin-bottom: 4px;
  padding: 4px 6px;
  background: rgba(0, 0, 0, .4);
  border: 1px solid #3c3520;
  border-radius: 4px;
  color: #f2ecd8;
  font: 13px "Trebuchet MS", sans-serif;
  text-align: left;
  cursor: pointer;
}
.loot-row:hover { border-color: #cbbf9a; background: rgba(60, 48, 20, .6); }
.loot-icon { display: block; width: 24px; height: 24px; flex-shrink: 0; }
#lootTakeAll {
  width: 100%;
  margin-top: 6px;
  padding: 5px;
  background: rgba(0, 0, 0, .5);
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  color: #ffd166;
  font: 12px "Trebuchet MS", sans-serif;
  cursor: pointer;
}
#lootTakeAll:hover { color: #fff; border-color: #cbbf9a; }

/* ---- menu and settings ---- */

.window {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  min-width: 260px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: rgba(12, 16, 10, .94);
  border: 2px solid #6b5a2e;
  border-radius: 8px;
  pointer-events: auto;
  text-align: center;
}
.window h2 { font-size: 20px; color: #ffd166; margin-bottom: 4px; }
#settingsPanel {
  z-index: 40;
  width: min(520px, calc(100vw - 24px));
  height: min(640px, calc(100dvh - 24px));
  box-sizing: border-box;
  overflow: hidden;
}
#settingsPanel > * { flex-shrink: 0; }
#settingsPanel > .scroll-wrap { flex: 1; min-height: 0; }
#settingsContent { overflow-y: auto; min-height: 0; text-align: left; padding: 4px; }
#settingsTabs { flex-wrap: wrap; }
#settingsContent .setting { flex-wrap: wrap; }
#settingsContent .model-options { flex-wrap: wrap; }
#settingsLanguage { margin-top: 0; }
.window button, .language-picker button {
  padding: 7px 12px;
  background: rgba(0, 0, 0, .5);
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  color: #f2ecd8;
  font: 14px "Trebuchet MS", sans-serif;
  cursor: pointer;
}
.window button:hover, .window button.hovered { border-color: #cbbf9a; color: #fff; }

.setting {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: #cbbf9a;
}
.setting input[type="range"] { flex: 1; accent-color: #6b5a2e; }
.model-options { display: flex; flex: 1; gap: 6px; }
.model-options button { flex: 1; }
.model-options button[aria-pressed="true"], .language-picker button[aria-pressed="true"] { border-color: #d9bd73; background: #51442a; color: #fff3cc; }
.setting-note + .setting { margin-top: 18px; }
#volumeValue, #cursorAccelerationValue, #chatBackgroundValue { width: 42px; text-align: right; color: #f2ecd8; }
#drawDistanceValue, #grassDistanceValue { width: 62px; text-align: right; color: #f2ecd8; }

/* What a setting does, where the label has no room to say it. */
.setting-note {
  margin: 8px 2px 0;
  font-size: 12px;
  line-height: 1.5;
  color: #9d947a;
}
.setting-note b { color: #cbbf9a; font-weight: normal; }

/* ---- the gamemaster's catalogue ---- */

#catalogPanel {
  width: min(1100px, 92vw);
  text-align: left;
  gap: 8px;
}
.catalog-bar { display: flex; align-items: center; gap: 8px; }
.catalog-bar #catalogSearch { flex: 1; }
/* Thirteen tables is more than a row: they wrap, and the margin the settings
   tabs carry would put too much air above a window that is mostly rows. */
.catalog-tabs { flex-wrap: wrap; margin: 0 0 4px; }
.catalog-tabs .tab { padding: 3px 9px; font-size: 12px; }
#catalogSearch {
  padding: 5px 8px;
  background: rgba(0, 0, 0, .5);
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  color: #f2ecd8;
  font: 13px "Trebuchet MS", sans-serif;
}
#catalogSearch:focus { outline: none; border-color: #cbbf9a; }
.catalog-status { flex: 1; text-align: center; font-size: 12px; color: #9d947a; }

/* The rows scroll in both directions: a creature has thirty-six columns and
   nothing useful is gained by squeezing them. */
#catalogScroll {
  height: min(52vh, 460px);
  overflow: auto;
  border: 1px solid #4a4130;
  border-radius: 4px;
  background: rgba(0, 0, 0, .35);
}
#catalogTableRows { border-collapse: collapse; font-size: 12px; white-space: nowrap; }
#catalogTableRows th, #catalogTableRows td {
  padding: 3px 8px;
  border-bottom: 1px solid #2c2820;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
}
#catalogTableRows th {
  position: sticky;
  top: 0;
  background: #201d16;
  color: #cbbf9a;
  text-align: left;
  font-weight: normal;
}
#catalogTableRows td { color: #d8cfb3; }
#catalogTableRows tr:hover td { background: rgba(255, 255, 255, .04); }
.catalog-take {
  padding: 1px 6px;
  background: rgba(0, 0, 0, .5);
  border: 1px solid #6b5a2e;
  border-radius: 3px;
  color: #f2ecd8;
  font: 11px "Trebuchet MS", sans-serif;
  cursor: pointer;
}
.catalog-take:hover { border-color: #cbbf9a; color: #fff; }

/* ---- the bug report ---- */

#bugPanel { width: 420px; text-align: left; }
.bug-note { margin-top: 0; }
#bugText {
  width: 100%;
  padding: 8px;
  background: rgba(0, 0, 0, .5);
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  color: #f2ecd8;
  font: 14px "Trebuchet MS", sans-serif;
  line-height: 1.4;
  resize: vertical;
}
#bugText:focus { outline: none; border-color: #cbbf9a; }
.bug-actions { display: flex; gap: 10px; justify-content: flex-end; }
.bug-actions button { min-width: 96px; }
#bugStatus { min-height: 18px; font-size: 13px; color: #cbbf9a; }
#bugStatus.wrong { color: #e08b7a; }

/* ---- character sheet ---- */

#characterPanel {
  position: absolute;
  top: 90px;
  left: 16px;
  /* wide enough that the stat column still reads one row to a line once the
     equipment slots have taken their share either side of the model */
  width: 520px;
  max-height: calc(100vh - 200px);
  overflow-y: auto;
  padding: 12px 14px 14px;
  background: rgba(12, 16, 10, .93);
  border: 2px solid #6b5a2e;
  border-radius: 8px;
  pointer-events: auto;
  font-size: 13px;
}
.cs-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.cs-head h2 { font-size: 18px; color: #ffd166; }
/* Every panel closes the same way, so this hangs on what the button is rather
   than on which panel it happens to sit in — as an id selector it dressed the
   character sheet and left the bags and the loot window as bare browser
   buttons. */
.panel-close {
  background: none;
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  color: #cbbf9a;
  width: 24px;
  height: 24px;
  padding: 0;
  line-height: 1;
  font-size: 13px;
  cursor: pointer;
}
.panel-close:hover { color: #fff; border-color: #cbbf9a; }
/* Inside a menu window the generic `.window button` rule would give the close
   button a menu button's padding and background, and the X would sit low and
   left of where it belongs. It is the same little square everywhere. */
.window .panel-close, .player-notes .panel-close {
  padding: 0;
  width: 24px;
  height: 24px;
  background: none;
  font: 13px "Trebuchet MS", sans-serif;
  line-height: 1;
  color: #cbbf9a;
}
.player-notes .panel-close:hover, .player-notes .panel-close.hovered { color: #fff; }

.cs-body { display: flex; gap: 14px; }
/* the model between its slots: what is worn reads as being on the character */
.cs-gear { display: flex; gap: 6px; align-items: flex-start; flex: none; }
.cs-slots { display: flex; flex-direction: column; gap: 6px; }
.cs-slot {
  width: 34px;
  height: 34px;
  border: 1px solid #3c3520;
  border-radius: 5px;
  background: #12170c;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
  cursor: default;
}
.cs-slot.filled { border-color: #6b5a2e; background: #1b2110; cursor: grab; }
/* only lights up for something that belongs in it, so the slot refuses before
   the server has to */
.cs-slot.over { border-color: #ffd166; box-shadow: 0 0 8px 1px rgba(255, 209, 102, .55); }
.slot-cell.wearable { cursor: grab; }
.slot-cell.filled:active, .cs-slot.filled:active { cursor: grabbing; }
.cs-model { width: 150px; flex: none; text-align: center; }
#characterCanvas {
  width: 150px;
  height: 210px;
  display: block;
  border: 1px solid #3c3520;
  border-radius: 6px;
  background: #0f1409;
}
#csClass { margin-top: 6px; color: #a8e063; }

.cs-stats { flex: 1; min-width: 0; }
.cs-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 2px 0;
}
.cs-row span { color: #9c9683; }
.cs-row b { color: #f2ecd8; font-weight: normal; }
.cs-rule { height: 1px; margin: 8px 0; background: #3c3520; }
.cs-tabs {
  position: sticky;
  bottom: -14px;
  display: flex;
  gap: 6px;
  margin-top: 12px;
  padding: 10px 0 0;
  background: #0c100a;
  border-top: 1px solid #3c3520;
}
.cs-tabs button {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  background: #171b10;
  color: #cbbf9a;
  font: inherit;
  cursor: pointer;
}
.cs-tabs button[aria-selected="true"] { background: #38331c; color: #ffd166; border-color: #b08d42; }
.cs-tabs button:hover, .cs-tabs button:focus-visible { color: #fff; border-color: #ffd166; }
#cs-reputation { min-height: 290px; }
.cs-reputation-intro, #csReputationEmpty { color: #bcb6a2; line-height: 1.5; margin: 8px 0 16px; }
#csReputations { list-style: none; margin: 0; padding: 0; }
.cs-reputation { padding: 10px; margin-bottom: 10px; border: 1px solid #3c3520; border-radius: 5px; }
.cs-reputation .cs-row span { text-transform: capitalize; }
.cs-reputation progress { display: block; width: 100%; height: 12px; margin: 8px 0; accent-color: #8ba846; }
.cs-reputation.hostile progress { accent-color: #bd6554; }
.cs-reputation.neutral progress { accent-color: #c7ac55; }
.cs-reputation-detail { color: #bcb6a2; font-size: 12px; }

/* ---- the zone map ---- */

/* The window sizes itself to the canvas, and the canvas sizes itself to the
   shape of the zone (worldmap.js) — a square field and a long tunnel are not
   the same picture and should not be forced into the same frame. */
#worldMapPanel {
  position: absolute;
  /* Middle of the screen rather than a fixed way down it: the window is as tall
     as the zone is, and a square field and a long tunnel do not start in the
     same place. */
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 12px 14px 10px;
  background: #3a2715;
  border: 3px solid #24170d;
  border-radius: 10px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .65), inset 0 0 0 2px #76502a;
  pointer-events: auto;
}
.map-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  margin: 0 2px 8px;
}
.map-head h2 {
  color: #e7c46a;
  font: 20px Georgia, serif;
  letter-spacing: .04em;
}
#worldMapCanvas {
  display: block;
  border-radius: 4px;
  box-shadow: 0 5px 12px rgba(0, 0, 0, .45);
}
.map-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 4px 16px;
  margin: 7px 2px 0;
  color: #9c9683;
  font-size: 12px;
  text-align: right;
}
.map-foot > span { white-space: nowrap; }
.map-foot .map-hint { flex-basis: 100%; white-space: normal; }
.map-foot b { color: #f2ecd8; font-weight: normal; }

/* ---- spellbook ---- */

#spellbookPanel {
  position: absolute;
  top: 110px;
  left: 50%;
  transform: translateX(-50%);
  width: 570px;
  padding: 14px 16px 16px;
  background: #3a2715;
  border: 3px solid #24170d;
  border-radius: 10px 10px 16px 16px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .65), inset 0 0 0 2px #76502a;
  pointer-events: auto;
}
.spellbook-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 4px 10px;
}
.spellbook-head h2 {
  color: #e7c46a;
  font: 20px Georgia, serif;
  letter-spacing: .04em;
}
.spellbook-pages {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 300px;
  overflow: hidden;
  border-radius: 6px 6px 12px 12px;
  box-shadow: 0 5px 12px rgba(0, 0, 0, .45);
}
.spellbook-pages::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 18px;
  transform: translateX(-50%);
  background: linear-gradient(90deg, rgba(74, 48, 25, .08), rgba(31, 20, 11, .42), rgba(74, 48, 25, .08));
  pointer-events: none;
}
.spellbook-page {
  padding: 24px 25px 28px;
  color: #352916;
  background:
    repeating-linear-gradient(0deg, rgba(90, 69, 34, .035) 0 1px, transparent 1px 5px),
    linear-gradient(90deg, #c8b680, #eadcae 18%, #e5d4a1 88%, #bda875);
  box-shadow: inset -10px 0 18px rgba(74, 48, 25, .17);
}
.spellbook-page-right {
  background:
    repeating-linear-gradient(0deg, rgba(90, 69, 34, .035) 0 1px, transparent 1px 5px),
    linear-gradient(90deg, #bda875, #e5d4a1 12%, #eadcae 82%, #c8b680);
  box-shadow: inset 10px 0 18px rgba(74, 48, 25, .17);
}
.spellbook-page h3 {
  margin-bottom: 18px;
  color: #6a3d1d;
  font: 16px Georgia, serif;
  text-align: center;
  border-bottom: 1px solid rgba(89, 55, 27, .35);
  padding-bottom: 7px;
}
.spellbook-page-right h3 { visibility: hidden; }
.spellbook-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 12px;
}
.spellbook-spell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  min-width: 0;
  padding: 7px 4px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: #3a2916;
  font: 12px Georgia, serif;
  cursor: pointer;
}
.spellbook-spell:hover, .spellbook-spell.hovered {
  border-color: rgba(101, 61, 27, .45);
  background: rgba(255, 247, 211, .28);
}
.spellbook-icon {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 2px solid #67431f;
  border-radius: 7px;
  background: radial-gradient(circle at 35% 28%, #354322, #11170c 72%);
  box-shadow: inset 0 0 5px #000, 0 2px 3px rgba(74, 48, 25, .5);
  font-size: 24px;
}
.spellbook-name {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.spellbook-next {
  margin-top: 10px;
  color: #c8ad70;
  font: italic 12px Georgia, serif;
  text-align: center;
}

/* ---- what is on somebody ---- */
/* Player effects sit beside the map; target effects stay under its frame. */
.aura-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
#playerAuras {
  position: absolute;
  right: calc(16px + var(--minimap-size) + 12px);
  top: 46px;
  width: min(236px, calc(100vw - var(--minimap-size) - 44px));
  display: flex;
  flex-direction: column;
  gap: 10px;
}
#playerAuras .aura-row {
  justify-content: flex-end;
  /* Keep debuffs below the buff section even when no buffs are active. */
  min-height: 28px;
}
#targetAuras {
  position: absolute;
  top: 100%;
  left: 6px;              /* line up with the portrait, not with the border */
  margin-top: 4px;
}

.aura {
  position: relative;
  /* The whole HUD layer is transparent to the pointer and every panel that
     wants to be looked at says so; without this the cursor found the world
     behind the icon and no tooltip ever appeared. */
  pointer-events: auto;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 1px solid #6b5a2e;
  border-radius: 5px;
  background: rgba(12, 16, 10, .85);
  font-size: 16px;
  line-height: 1;
}
.aura-row.small .aura { width: 21px; height: 21px; font-size: 12px; }
/* Red for what is done to you, green for what is done for you — the border
   rather than the icon, since the icon belongs to the effect. */
.aura.debuff { border-color: #a4432f; }
.aura.buff { border-color: #4f8f3a; }
.aura b { font-weight: normal; }
/* The seconds sit in the corner of the icon, dark-edged so they read over it */
.aura i {
  position: absolute;
  right: 1px;
  bottom: 0;
  font-size: 10px;
  font-style: normal;
  color: #f2ecd8;
  text-shadow: 0 0 3px #000, 0 1px 1px #000;
}
.aura-row.small i { font-size: 9px; }
.aura.hovered { border-color: #cbbf9a; }

/* The status line keeps the corner it has always had and the map hangs under
   it, sharing the right edge. The 46px is the line's own height plus the
   margin above it, so the two do not touch. */
#minimap {
  position: absolute;
  right: 16px;
  top: 46px;
  width: var(--minimap-size);
  height: var(--minimap-size);
  /* it is looked at, not clicked: the wheel is handled by position, the way the
     scrollable panes are, so it must not steal a hit test from the world */
  pointer-events: none;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .55));
}

#minimapClock {
  position: absolute;
  right: calc(16px + var(--minimap-size) / 2);
  top: calc(46px + var(--minimap-size) + 6px);
  transform: translateX(50%);
  padding: 3px 9px;
  border: 1px solid #756238;
  border-radius: 4px;
  background: rgba(12, 15, 10, .85);
  color: #e8d7a6;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  line-height: 18px;
  pointer-events: none;
}

#status {
  position: absolute;
  right: 16px;
  top: 16px;
  padding: 4px 8px;
  background: rgba(0, 0, 0, .5);
  border-radius: 4px;
  font-size: 12px;
}

/* A bar that changes colour is noticed from the corner of an eye; one that only
   changes its words has to be read, and nobody reads the status bar while they
   are being eaten. */
#status.warn { color: #e8cf62; background: rgba(60, 45, 0, .55); }
#status.bad  { color: #e5654f; background: rgba(60, 10, 0, .55); }

/* The way into the menu that no future keybinding can take away. A round map in
   a square box leaves its corners empty, so the gear is tucked into the top
   right one rather than being given a row of its own. */
#menuButton {
  position: absolute;
  right: 16px;
  top: 46px;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 1px solid #6b5a2e;
  border-radius: 5px;
  background: rgba(12, 16, 10, .8);
  color: #cbbf9a;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
#menuButton:hover, #menuButton.hovered { color: #fff; border-color: #cbbf9a; }

/* ---- the game's own scrollbar ---- */
/* The browser's answers to a real pointer and there is not one, so its bar is
   hidden and scrollbar.js draws a pair of divs in its place. */
.scroll-wrap { position: relative; display: flex; }
.scroll-wrap > *:first-child { flex: 1; min-width: 0; scrollbar-width: none; }
.scroll-wrap > *:first-child::-webkit-scrollbar { display: none; }

.scroll-bar {
  width: 10px;
  margin-left: 4px;
  border-radius: 5px;
  background: rgba(0, 0, 0, .35);
  flex: none;
}
.scroll-thumb {
  width: 100%;
  border-radius: 5px;
  background: #6b5a2e;
  cursor: grab;
}
.scroll-thumb.hovered, .scroll-thumb:hover { background: #8a7440; }
body.scrolling .scroll-thumb { background: #d9b45a; }

/* ---- settings tabs and the controls list ---- */

.tabs { display: flex; gap: 6px; margin: 10px 0 12px; }
.tabs .tab {
  padding: 5px 14px;
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  background: rgba(12, 16, 10, .8);
  color: #cbbf9a;
  cursor: pointer;
}
.tabs .tab.on, .tabs .tab.hovered { color: #fff; border-color: #d9b45a; }
.tabs .tab.on { background: #3a2f14; }

.controls-group {
  margin: 10px 0 4px;
  color: #ffd166;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.controls-row {
  display: grid;
  grid-template-columns: 1fr 92px 92px;
  gap: 6px;
  align-items: center;
  padding: 2px 0;
}
.key-bind {
  padding: 3px 4px;
  /* a name too long for the button is clipped rather than wrapped: a wrapped
     one makes its whole row taller and the list goes ragged */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px solid #3c3520;
  border-radius: 4px;
  background: #12170c;
  color: #e8e6df;
  font-size: 12px;
  cursor: pointer;
}
.key-bind.hovered, .key-bind:hover { border-color: #d9b45a; }
.key-bind.empty { color: #6b6a5e; }
/* waiting for a key: unmistakable, because the next press goes here and not
   into the game */
.key-bind.listening {
  border-color: #ffd166;
  background: #3a2f14;
  color: #ffd166;
}
.controls-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  font-size: 12px;
  color: #cbbf9a;
}

#deathScreen {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 8px;
  text-align: center;
  background: rgba(80, 0, 0, .35);
  backdrop-filter: grayscale(1);
}
#deathScreen h1 { font-size: 42px; letter-spacing: 2px; text-shadow: 0 2px 6px #000; }

/* ---- 3D additions ---- */

#view { cursor: default; }

/* The name of the country you have just walked into. Across the upper third
   rather than in the middle, where the fight is, and gone in a few seconds:
   it is an announcement, not a panel. */
#areaBanner {
  position: fixed;
  top: 22%;
  left: 0;
  right: 0;
  text-align: center;
  font: 34px Georgia, serif;
  letter-spacing: .04em;
  color: #f0e2b8;
  text-shadow: 0 2px 10px #000, 0 0 26px rgba(0, 0, 0, .9);
  pointer-events: none;
  opacity: 0;
  z-index: 40;
}
#areaBanner.showing { animation: area-name 4.2s ease-out forwards; }
@keyframes area-name {
  0%   { opacity: 0; transform: translateY(10px); }
  12%  { opacity: 1; transform: translateY(0); }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}

/* world-space labels are projected here every frame */
#world-overlay {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.nameplate {
  position: absolute;
  transform: translate(-50%, -100%);
  text-align: center;
  white-space: nowrap;
  font: bold 12px "Trebuchet MS", sans-serif;
  text-shadow: 0 1px 2px #000, 0 0 3px #000;
}
.nameplate .np-name { color: #ffb3a7; }
.nameplate.friendly .np-name { color: #a8e063; }
/* neutral: it will not start anything, and neither will killing it earn you
   anything — yellow, the way every game since has painted the harmless */
.nameplate.neutral .np-name { color: #ffd100; }
.nameplate.targeted .np-name { color: #ffd166; }
/* on its way home, deaf and untouchable: greyed out, like WoW's evade */
.nameplate.evading .np-name,
.nameplate.evading.targeted .np-name { color: #8f8f8f; }
.nameplate.evading .np-bar i { background: #6d6d6d; }
.nameplate .np-bar {
  width: 64px;
  height: 5px;
  margin: 2px auto 0;
  background: #1b1b1b;
  border: 1px solid #000;
  border-radius: 2px;
  overflow: hidden;
}
.nameplate .np-bar i {
  display: block;
  height: 100%;
  background: #c92a2a;
  transform-origin: left;
}
.nameplate.friendly .np-bar i { background: #43d15a; }
.nameplate.neutral .np-bar i { background: #d4a900; }

/* Speech bubble over a head. Sits above the nameplate, and wraps rather than
   running off the side of the screen. */
.bubble {
  position: absolute;
  transform: translate(-50%, -100%);
  max-width: 220px;
  padding: 3px 8px;
  background: rgba(250, 250, 245, .94);
  border-radius: 9px;
  color: #14170f;
  font: 12px "Trebuchet MS", sans-serif;
  text-align: center;
  overflow-wrap: break-word;
}
.bubble::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -5px;
  margin-left: -5px;
  border: 5px solid transparent;
  border-top-color: rgba(250, 250, 245, .94);
  border-bottom: 0;
}

/* Keep the party hue legible against the light speech-bubble background. */
.bubble.party { color: #235f9b; }

.floater {
  position: absolute;
  transform: translate(-50%, -50%);
  font: bold 22px "Trebuchet MS", sans-serif;
  text-shadow: 0 1px 3px #000;
  white-space: nowrap;
}
.floater.crit { font-size: 30px; }

#fatal {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 10px;
  text-align: center;
  background: rgba(8, 10, 6, .92);
  pointer-events: auto;
}
#fatal h1 { font-size: 32px; }
#fatal a { color: #9fd6ff; }

/* ---- class picker ---- */

#login {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  align-content: safe center;
  gap: 16px;
  padding: 24px 0;
  overflow-y: auto;
  background: radial-gradient(circle at 50% 30%, #2c3a22, #0d120a 70%);
  z-index: 10;
}
#login.hidden { display: none !important; }
#inputSupportNotice {
  display: none;
  width: min(560px, 92vw);
  padding: 12px 16px;
  border: 1px solid #9c8040;
  border-radius: 8px;
  background: #302b19;
  color: #f3dfa9;
  text-align: center;
}
/* A notice, not an entry gate: a touch device may also have a mouse/keyboard. */
@media (any-pointer: coarse) {
  #inputSupportNotice { display: block; }
}
html.autologin-pending #accountLogin { display: none; }
#autologinLoader { display: none; place-items: center; gap: 12px; color: #d8cfb3; font-size: 13px; }
html.autologin-pending #autologinLoader { display: grid; }
#autologinLoader i {
  width: 34px;
  height: 34px;
  border: 3px solid rgba(255, 209, 102, .2);
  border-top-color: #ffd166;
  border-radius: 50%;
  animation: autologin-spin .8s linear infinite;
}
@keyframes autologin-spin { to { transform: rotate(360deg); } }

#login .panel {
  width: min(560px, 92vw);
  padding: 22px 24px 20px;
  background: rgba(12, 16, 10, .92);
  border: 2px solid #6b5a2e;
  border-radius: 10px;
  text-align: center;
}
#characterSelect { width: min(560px, 92vw) !important; }
#characterCreate { width: min(660px, 92vw) !important; }
#genderPicker { border: 0; padding: 0; margin: 16px 0 22px; }
#genderPicker legend { margin-bottom: 8px; }
#genderPicker button { min-width: 110px; margin: 0 4px; padding: 8px 16px; background: #292f20; border: 1px solid #6b5a2e; border-radius: 5px; color: #e8e2d0; cursor: pointer; font: inherit; }
#genderPicker button:hover, #genderPicker button:focus-visible { border-color: #d9b45a; }
#genderPicker button[aria-pressed="true"] { border-color: #ffd166; box-shadow: 0 0 8px #ffd16633; }
#genderPicker small { display: block; opacity: .7; margin-top: 10px; }
.login-heading { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
.login-heading h1 { grid-column: 2; }
.login-heading > button, .account-actions { grid-column: 3; justify-self: end; }
.account-actions { display: grid; justify-items: end; gap: 4px; }
#accountLoginHint { margin: 12px 0; color: #d8cfb3; font-size: 13px; line-height: 1.5; }
#accountIdentity { color: #d8cfb3; font-size: 11px; opacity: .7; }
.character-lists { display: grid; align-content: start; gap: 8px; }
.character-choice { width: 100%; display: flex; justify-content: space-between; padding: 12px; margin-bottom: 7px; background: #182014; border: 2px solid #4a4128; border-radius: 6px; color: #e8e2d0; cursor: pointer; }
.character-choice.selected { border-color: #ffd166; box-shadow: 0 0 10px rgba(255, 209, 102, .3); }
.character-choice span { opacity: .7; }
#legacyCharacters { margin-top: 12px; border-top: 1px solid #4a4128; }
#legacyCharacters h2 { margin: 12px 0 3px; font-size: 14px; color: #d9b45a; }
#legacyCharacters p { margin: 0 0 8px; font-size: 11px; opacity: .65; }
#accountEnter, #newCharacter, #accountLogout, #createBack, #createConfirm, #characterUpdates { padding: 8px 12px; background: #292f20; border: 1px solid #6b5a2e; border-radius: 5px; color: #e8e2d0; cursor: pointer; }
#createConfirm { width: 100%; }
#login .danger-button { padding: 8px 12px; background: #452323; border: 1px solid #a45a4e; border-radius: 5px; color: #ffd4c9; cursor: pointer; }
.character-secondary-actions { display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: 8px; margin-top: 12px; }
#login .character-secondary-actions button { min-width: 0; padding: 6px 8px; background: transparent; border: 1px solid transparent; border-radius: 4px; font: 12px "Trebuchet MS", sans-serif; }
#login #characterUpdates { grid-column: 1; justify-self: start; color: #cbbf9a; }
#login #deleteCharacter { grid-column: 2; justify-self: end; color: #ce9b90; }
#login .character-secondary-actions button:hover { border-color: #6b5a2e; background: #292f20; }
#login .character-secondary-actions button:focus-visible { outline: 2px solid #d9b45a; outline-offset: 2px; }
/* Preserve the row's size while keeping an unavailable action unfocusable. */
#deleteCharacter.hidden { display: block !important; visibility: hidden; }
#deleteConfirmation { margin-top: 16px; padding: 14px; border: 1px solid #a45a4e; border-radius: 5px; background: #281b17; }
#deleteConfirmation p { margin-bottom: 12px; }
#deleteCharacterPrompt { font-weight: bold; color: #ffd4c9; }
#cancelDeleteCharacter { padding: 8px 12px; margin-right: 8px; background: #292f20; border: 1px solid #6b5a2e; border-radius: 5px; color: #e8e2d0; cursor: pointer; }
#login button:disabled { opacity: .5; cursor: default; }
#login h1 {
  margin-bottom: 14px;
  font-size: 26px;
  letter-spacing: 1px;
  color: #ffd166;
  text-shadow: 0 2px 6px #000;
}
#login label {
  display: block;
  margin-bottom: 4px;
  font-size: 12px;
  opacity: .8;
  text-align: left;
}
/* Every field on this screen, the way the labels above them already share one
   rule. Naming the name field alone left the gamemaster password looking like
   a browser default sitting in the middle of the panel. */
#login input {
  width: 100%;
  padding: 8px 10px;
  margin-bottom: 16px;
  background: #10150d;
  border: 1px solid #6b5a2e;
  border-radius: 4px;
  color: #e8e2d0;
  font: 15px "Trebuchet MS", sans-serif;
}
#login input:focus { outline: none; border-color: #d9b45a; }

#classPicker {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 16px;
}
.class-card {
  padding: 12px 10px;
  background: rgba(30, 38, 24, .8);
  border: 2px solid #4a4128;
  border-radius: 8px;
  color: #e8e2d0;
  cursor: pointer;
  text-align: center;
  font: inherit;
}
.class-card:hover { border-color: #6b5a2e; }
.class-card.selected { border-color: #ffd166; box-shadow: 0 0 12px rgba(255, 209, 102, .35); }
.class-card .cc-portrait {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  margin: 0 auto 8px;
  border: 2px solid #6b5a2e;
  border-radius: 50%;
  font: bold 18px "Trebuchet MS", sans-serif;
}
.class-card.mage .cc-portrait    { background: radial-gradient(circle at 35% 30%, #6ea8ff, #1e3a8a); }
.class-card.warrior .cc-portrait { background: radial-gradient(circle at 35% 30%, #d98f5a, #7a2e12); }
.class-card.priest .cc-portrait  { background: radial-gradient(circle at 35% 30%, #f2f2e8, #8a8676); color: #2b2b2b; }
.class-card .cc-name { font-weight: bold; margin-bottom: 4px; }
.class-card .cc-stats { font-size: 11px; opacity: .75; margin-bottom: 6px; }
.class-card .cc-blurb { font-size: 11px; opacity: .65; line-height: 1.35; }

#loginEnter {
  width: 100%;
  padding: 10px;
  background: linear-gradient(#6b5a2e, #3d3319);
  border: 2px solid #d9b45a;
  border-radius: 6px;
  color: #ffe9b0;
  font: bold 15px "Trebuchet MS", sans-serif;
  cursor: pointer;
}
#loginEnter:hover { filter: brightness(1.15); }
#loginStatus {
  display: none;
  margin-top: 12px;
  color: #d8cfb3;
  font-size: 13px;
}
.login-message { display: none; margin-top: 12px; color: #d8cfb3; font-size: 13px; }
#login.joining { cursor: wait; }
#login.joining #loginStatus { display: block; }
#login.joining #loginEnter {
  cursor: wait;
  filter: saturate(.65);
  animation: login-pulse 1.2s ease-in-out infinite alternate;
}
@keyframes login-pulse {
  from { opacity: .65; }
  to { opacity: 1; }
}

/* resource bar takes the colour of whatever the class runs on */
.bar.rage i { background: linear-gradient(#ff6b4a, #a52208); }

.portrait.warrior { background: radial-gradient(circle at 35% 30%, #d98f5a, #7a2e12); color: #fff1e2; }
.portrait.priest  { background: radial-gradient(circle at 35% 30%, #f2f2e8, #8a8676); color: #2b2b2b; }
.portrait.friendly { border-color: #43d15a; }

.nameplate.player .np-name { color: #70baff; }

/* How many are in a bag slot. Bottom right, where the icon is not, and only
   drawn when there is more than one — a "1" on every hat would be noise. */
.stack-count {
  position: absolute;
  right: 3px;
  bottom: 1px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  color: #f2ead6;
  text-shadow: 0 0 3px #000, 0 1px 2px #000;
  pointer-events: none;
}

/* ---- controls for a phone (#88) -------------------------------------------
 *
 * Everything here hangs off `body.touch`, which mobile.js adds only on a device
 * whose main pointer is a finger. On anything with a mouse none of it exists,
 * so the desktop layout below is exactly what it always was.
 */

#touchControls { display: none; }

body.touch #actionBar { display: none; }

body.touch #touchControls {
  display: block;
  position: fixed;
  inset: 0;
  /* the layer is a frame for its children; the world underneath stays reachable */
  pointer-events: none;
  z-index: 40;
}

body.touch #touchControls > * { pointer-events: auto; }

#touchStick {
  position: absolute;
  left: max(16px, env(safe-area-inset-left));
  bottom: max(16px, env(safe-area-inset-bottom));
  width: 34vmin;
  height: 34vmin;
  max-width: 180px;
  max-height: 180px;
  border-radius: 50%;
  background: #0d0f0b66;
  border: 2px solid #6b5a2e99;
  /* a thumb resting on it must not select the page or fire a long-press menu */
  touch-action: none;
  user-select: none;
}

#touchKnob {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 38%;
  height: 38%;
  margin: -19% 0 0 -19%;
  border-radius: 50%;
  background: #f2ead633;
  border: 2px solid #f2ead666;
}

#touchActions {
  position: absolute;
  right: max(16px, env(safe-area-inset-right));
  bottom: max(16px, env(safe-area-inset-bottom));
  display: flex;
  align-items: center;
  gap: 10px;
  touch-action: none;
}

#touchActions button {
  background: #0d0f0b99;
  border: 2px solid #6b5a2e;
  border-radius: 10px;
  color: #f2ead6;
  font: inherit;
}

#touchPrev, #touchNext {
  width: 12vmin;
  height: 12vmin;
  max-width: 58px;
  max-height: 58px;
  font-size: 6vmin;
  line-height: 1;
}

#touchSlot {
  position: relative;
  width: 20vmin;
  height: 20vmin;
  max-width: 96px;
  max-height: 96px;
  display: grid;
  place-items: center;
}

#touchSlot .icon { font-size: 9vmin; line-height: 1; }
#touchSlot .key {
  position: absolute;
  right: 4px;
  bottom: 2px;
  font-size: 3vmin;
  opacity: 0.7;
}

#touchFull {
  position: absolute;
  right: max(16px, env(safe-area-inset-right));
  top: max(16px, env(safe-area-inset-top));
  width: 11vmin;
  height: 11vmin;
  max-width: 52px;
  max-height: 52px;
  background: #0d0f0b99;
  border: 2px solid #6b5a2e;
  border-radius: 10px;
  color: #f2ead6;
  font-size: 5vmin;
}

/* The gear and the minimap sit where the fullscreen button wants to be. */
body.touch #menuButton { top: max(16px, env(safe-area-inset-top)); right: 74px; }

/* The canvas owns every gesture that lands on it. Without this a browser treats
 * a touch on the world as a possible pan or zoom, waits to find out, and then
 * sends `pointercancel` instead of `pointerup` — so the press never closes and
 * nothing can be selected. It is the whole reason tapping did not target. */
body.touch #view { touch-action: none; }

/* The log lives in the bottom-left corner, which on a phone is where the thumb
 * is. It moves up and narrows rather than going away: what the game says to you
 * is worth reading even one-handed. */
body.touch #logPanel {
  left: 8px;
  bottom: calc(34vmin + 28px);
  width: min(52vw, 320px);
  font-size: 11px;
}

/* The minimap is drawn for a screen ten times this wide. */
body.touch { --minimap-size: 22vmin; }

/* Player-to-player offers remain separate from vendor stock and bag slots. */
#tradePanel { position:absolute; z-index:35; top:50%; left:44%; transform:translate(-50%,-50%); width:min(460px,calc(100vw - 36px)); padding:16px; box-sizing:border-box; background:rgba(12,16,10,.96); border:2px solid #8b7440; border-radius:8px; pointer-events:auto; color:#e6d8b6; }
#tradeHint { font-size:12px; line-height:1.5; min-height:36px; color:#bcb296; }
.trade-columns { display:grid; grid-template-columns:1fr 1fr; gap:14px; }
.trade-column { position:relative; min-width:0; border:1px solid #52472e; padding:10px; border-radius:5px; }
.trade-column h3 { font-size:14px; margin:0 0 12px; overflow-wrap:anywhere; }
.trade-slots { display:grid; grid-template-columns:repeat(3,1fr); gap:6px; }
.trade-slot { position:relative; aspect-ratio:1; display:grid; place-items:center; font-size:24px; border:1px solid #756139; border-radius:4px; background:#201f15; }
.trade-slot.over { outline:2px solid #ebc66c; }
.trade-money { display:flex; gap:5px; margin-top:16px; }
.trade-money label { font-size:11px; flex:1; min-width:0; }
.trade-money input { width:100%; box-sizing:border-box; padding:6px 3px; color:#f4dfac; background:#14170f; border:1px solid #665838; margin-top:5px; }
#tradeOtherCoins { margin:16px 0 0; font-size:12px; line-height:1.8; }
.trade-accepted { position:absolute; inset:0; display:grid; place-items:center; font-size:66px; color:#a7d46d; background:rgba(0,0,0,.62); border-radius:5px; }
#tradeAccept { display:block; margin:16px auto 0; min-width:140px; padding:9px 20px; }
.slot-cell.offered { opacity:.45; outline:1px solid #ddbe75; }
@media(max-width:850px) { #tradePanel { left:12px; top:110px; transform:none; width:min(440px,calc(100vw - 310px)); } .trade-money { flex-wrap:wrap; } }
#tradeAccept { color:#f1dfad; background:linear-gradient(#4f4324,#302918); border:1px solid #a58a48; border-radius:4px; font-weight:bold; cursor:pointer; }
#tradeAccept:hover, #tradeAccept.hovered { background:#635231; border-color:#ebc66c; }
#tradeAccept:disabled { opacity:.6; cursor:wait; }

/* Keep GM controls below the drawn cursor, in the same layers as the HUD. */
.bots-backdrop { position: fixed; inset: 0; z-index: 49; background: #0008; pointer-events: auto; }
.bots-panel {
  position: fixed; inset: 0; z-index: 50;
  margin: auto; width: min(720px, calc(100vw - 28px)); max-height: calc(100dvh - 28px);
  padding: 0; color: #f2ecd8; background: rgba(12,16,10,.96); border: 2px solid #6b5a2e;
  border-radius: 8px; font: 14px "Trebuchet MS", sans-serif; box-shadow: 0 18px 80px #000a;
  pointer-events: auto;
}
.bots-panel[open] { display: flex; flex-direction: column; }
.bots-panel > .scroll-wrap { min-height: 0; flex: 1; }
.bots-panel .scroll-bar { margin: 8px 6px 8px 0; }
.bots-header,.bots-footer { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 20px; flex-shrink: 0; }
.bots-header { border-bottom: 1px solid #38442f; }
.bots-eyebrow { color: #a69b75; font-size: 10px; letter-spacing: .16em; }
.bots-panel h2 { font-size: 23px; color: #ffd166; margin: 4px 0 0; }
.bots-panel h3 { font-size: 16px; margin: 0; }
.bots-panel h4 { margin: 0 0 10px; }
.bots-scroll { min-height: 0; overflow: auto; padding: 16px 20px; }
#botsSummary { color: #d8d9af; margin: 0 0 16px; padding: 10px 12px; background: #263021; border-radius: 5px; }
.bots-section + .bots-section { margin-top: 22px; border-top: 1px solid #38442f; padding-top: 18px; }
.bots-note,.bots-panel small { color: #b4b6a4; font-size: 12px; line-height: 1.5; }
.bots-note { margin: 6px 0 12px; }
.bots-panel small { font-weight: normal; }
.bots-enabled { display: flex; align-items: center; gap: 10px; margin-top: 16px; }
.bots-panel input[type="checkbox"] { width: 18px; height: 18px; accent-color: #d9bd73; }
.bots-setting-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin: 16px 0; }
.bots-setting-grid label,.bots-area label { display: flex; flex-direction: column; gap: 7px; }
.bots-panel input[type="number"] { width: 100%; box-sizing: border-box; padding: 8px 10px; border: 1px solid #586048; border-radius: 4px; background: #090e08; color: #f2ecd8; font: inherit; }
.bots-panel input[type="number"] { appearance: textfield; }
.bots-panel input::-webkit-inner-spin-button, .bots-panel input::-webkit-outer-spin-button { appearance: none; margin: 0; }
.bots-area { border-left: 3px solid #65744d; padding: 10px 14px; margin: 12px 0; background: #1d2719; }
.bots-area label { flex-direction: row; align-items: center; justify-content: space-between; }
.bots-area input[type="number"] { width: 76px; }
.bots-area p { margin-bottom: 0; }
.bots-toolbar,.bot-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.bots-toolbar h3 { flex: 1; }
.bots-create { margin-top: 12px; justify-content: space-between; }
#botsClasses button[aria-pressed="true"],#botsFilters button[aria-pressed="true"] { color: #ffd166; border-color: #b89957; background: #65512a; }
.bots-panel button { padding: 7px 12px; border: 1px solid #6b5a2e; border-radius: 4px; background: rgba(0,0,0,.5); color: #f2ecd8; font: inherit; cursor: pointer; }
.bots-panel button:is(:hover,.hovered):not(:disabled) { border-color: #cbbf9a; color: #fff; }
.bots-panel input:is(:hover,.hovered):not(:disabled) { border-color: #cbbf9a; }
.bots-enabled:is(:hover,.hovered) { color: #ffd166; }
.bots-panel button:disabled { opacity: .45; cursor: default; }
.bots-panel button.bots-primary { background: #65512a; border-color: #b89957; }
.bots-panel :focus-visible { outline: 2px solid #ffd166; outline-offset: 3px; }
.bots-rows { display: grid; gap: 8px; }
.bot-card { padding: 12px; border: 1px solid #3d4934; border-radius: 5px; background: #192115; }
.bot-card-heading { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px; }
.bot-card-heading .bots-note { margin: 0; }
.bot-state { margin: 6px 0 10px; color: #b4b6a4; font-size: 12px; }
.bot-actions button { font-size: 12px; padding: 5px 10px; }
.bots-pagination { justify-content: space-between; margin-top: 12px; color: #b4b6a4; font-size: 12px; }
.bots-detail { margin-top: 14px; padding: 12px; background: #090e08; border-radius: 5px; }
.bot-delete-confirm { margin-top: 12px; padding: 12px; border: 1px solid #8b7440; border-radius: 5px; background: #261c13; }
.bot-delete-confirm p { margin: 0 0 10px; }
.bot-delete-confirm button + button { margin-left: 8px; }
.bots-detail dl { display: grid; grid-template-columns: minmax(100px,1fr) 2fr; gap: 6px 12px; margin: 0; font-size: 12px; }
.bots-detail dt { color: #b4b6a4; }.bots-detail dd { margin: 0; overflow-wrap: anywhere; }
.bots-footer { border-top: 1px solid #38442f; background: #151e11; }
#botsStatus { margin: 0; font-size: 12px; color: #c4cfaf; line-height: 1.5; }
#botsStatus.bots-error { color: #ffb8a6; }
@media(max-width: 480px) {
  .bots-setting-grid { grid-template-columns: 1fr; gap: 12px; }
  .bots-header,.bots-footer,.bots-scroll { padding: 12px; }
  .bots-toolbar .bots-note { width: 100%; }
}

/* GM-only personal map display controls, above the map and minimap. */
#worldMapPanel { z-index: 20; }
.map-head h2 { flex: 1; }
.map-tools { position: relative; flex: none; }
.map-tools button { color: #e7c46a; background: #241b10; border: 1px solid #8b7440; border-radius: 4px; padding: 5px 8px; cursor: pointer; }
.map-tools button:is(:hover,.hovered) { border-color: #cbbf9a; color: #fff; }
.map-tools label:is(:hover,.hovered) { color: #ffd166; }
.map-tools-menu { position: absolute; top: calc(100% + 8px); left: 0; z-index: 1; width: 220px; padding: 12px; background: #171d13; color: #eee4c9; border: 1px solid #8b7440; border-radius: 6px; box-shadow: 0 8px 24px #0009; }
.map-tools-menu label { display: flex; gap: 8px; align-items: center; margin: 4px 0 12px; font-size: 14px; cursor: pointer; }
.map-tools-menu input { accent-color: #c9ae66; }
.map-tools-menu p { color: #b8b4a1; font-size: 12px; line-height: 1.4; margin: 0; }
.map-tools :focus-visible { outline: 2px solid #e7c46a; outline-offset: 3px; }
/* Language choices use normal buttons so the drawn game cursor can activate them. */
.language-picker { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 10px 0; color: #cbbf9a; }
.language-picker button:is(:hover,.hovered) { border-color: #cbbf9a; color: #fff; }
.language-picker button:focus-visible { outline: 2px solid #ffd166; outline-offset: 3px; }
.language-hint { font-size:12px; color:#aa9d7e; max-width:48ch; }

/* Graphics sliders share the existing gold controls and scrollable settings. */
.setting input[type="range"] { min-width: 0; }
#renderResolutionPercent { width: 90px; flex-shrink: 0; text-align: right; color: #f2ecd8; }
#frameRateValue { width: 36px; text-align: right; color: #f2ecd8; }
.fps-toggle { margin-bottom: 12px; }
.fps-toggle input { accent-color: #6b5a2e; }
.marked-range { position: relative; flex: 1; min-width: 0; margin: 0 8px; }
.marked-range input { display: block; width: calc(100% + 16px); margin: 0 -8px; }
.range-marker { position: absolute; top: 17px; height: 7px; border-left: 2px solid #e4c26c; pointer-events: none; }
.setting input:disabled { opacity: .45; cursor: default; }
#frameRateHint { margin-top: 13px; }

#performanceStatus {
  position: absolute;
  right: 16px;
  top: 44px;
  max-width: calc(100% - 32px);
  padding: 4px 8px;
  border-radius: 4px;
  background: rgba(0, 0, 0, .5);
  color: #cbbf9a;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  pointer-events: none;
}

/* Make a second status row without covering the map, its controls or auras. */
.performance-detail #minimap,
.performance-detail #menuButton,
.performance-detail #playerAuras { top: 76px; }
.performance-detail #minimapClock { top: calc(76px + var(--minimap-size) + 6px); }
.performance-detail #questTracker { top: 292px; max-height: calc(100vh - 390px); }
