/* Motley Crew UI. Dark slate + ember gold, sized to read at a glance while
   things are trying to kill you. */

:root {
  --bg: #08070d;
  --panel: rgba(18, 17, 26, 0.94);
  --panel-solid: #12111a;
  --edge: #2c2a3d;
  --edge-lit: #454158;
  --ink: #e7e4f0;
  --ink-dim: #9a94ae;
  --ink-faint: #6b6680;
  --gold: #e0b352;
  --gold-dim: #8a6a2c;
  --hp: #c9433c;
  --hp-lit: #ef6a5f;
  --ae: #3f7fd6;
  --ae-lit: #6fa8f0;
  --xp: #b98cff;
  --good: #6ddc8a;
  --bad: #ff6a6a;
  --rare: #4aa3ff;
  --legendary: #ff9a2e;
  --godlike: #ff3d6e;
  --setgreen: #5fd18a;
  --uniqgold: #ffd76a;
  --shadow: 0 6px 24px rgba(0, 0, 0, 0.55);
  --font: ui-sans-serif, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  height: 100%; width: 100%;
  overflow: hidden;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  user-select: none;
}

.hidden { display: none !important; }

/* ------------------------------------------------------------- title ---
   The splash is the one screen with nothing else going on, so it is allowed
   to be composed: pixel-drawn dusk behind, the wordmark and the premise down
   the left, and every way in to the game inside one framed console on the
   right. Square corners and hard keylines throughout — the game is built out
   of chunky pixels and the front door should look like it belongs to it. */
.screen {
  position: fixed; inset: 0;
  display: grid; place-items: center;
  background: var(--bg);
  z-index: 50;
  overflow-y: auto;
  padding: 32px 24px;
}

#title-scene {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  image-rendering: pixelated; image-rendering: crisp-edges;
  z-index: 0;
}

#title {
  --frame: #0a0811;
  --frame-lit: #3b3553;
  --slab: rgba(14, 12, 21, 0.88);
}

.title-inner {
  position: relative; z-index: 1;
  width: min(1120px, 100%);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 470px);
  gap: 48px;
  align-items: center;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* --------------------------------------------------------- the keyart -- */
.keyart { text-align: left; }
#wordmark { display: block; margin: 0 0 12px calc(-1 * var(--pad, 0px)); max-width: 100%; }

.tagline {
  color: var(--gold);
  margin: 0 0 14px;
  font-size: 15px; font-weight: 600;
  letter-spacing: .01em;
  text-shadow: 0 1px 0 #000;
}
.premise {
  color: #b7b0c8; margin: 0; font-size: 13.5px;
  line-height: 1.72; max-width: 46ch;
  text-shadow: 0 1px 0 rgba(0, 0, 0, .8);
}
/* -------------------------------------------------------- the console -- */
.console { width: 100%; }
.console-frame {
  position: relative;
  background: var(--slab);
  border: 2px solid var(--frame);
  box-shadow:
    inset 0 0 0 1px var(--frame-lit),
    inset 0 22px 44px rgba(90, 60, 130, .10),
    0 18px 50px rgba(0, 0, 0, .65);
  backdrop-filter: blur(3px);
  padding: 18px 20px 22px;
}
/* Four gold corner brackets, cut out of one border with a mask. */
.console-frame::before {
  content: ''; position: absolute; inset: -5px; pointer-events: none;
  border: 2px solid var(--gold-dim);
  --corner: linear-gradient(#000, #000) no-repeat;
  -webkit-mask:
    var(--corner) top left / 16px 16px, var(--corner) top right / 16px 16px,
    var(--corner) bottom left / 16px 16px, var(--corner) bottom right / 16px 16px;
  mask:
    var(--corner) top left / 16px 16px, var(--corner) top right / 16px 16px,
    var(--corner) bottom left / 16px 16px, var(--corner) bottom right / 16px 16px;
}

.console-head {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 18px;
}
#console-title {
  font-size: 12px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--gold);
  text-shadow: 0 1px 0 #000;
}
.console-rule {
  flex: 1 1 auto; height: 2px;
  background: linear-gradient(90deg, var(--gold-dim), rgba(138, 106, 44, 0));
}

.console-foot {
  display: flex; flex-direction: column; gap: 10px;
  align-items: center; margin-top: 18px;
  /* This sits on the scene rather than in the frame, and the scene has a
     skyline in it: the labels need their own edge to read against. */
  text-shadow: 0 1px 3px rgba(0, 0, 0, .95), 0 0 8px rgba(0, 0, 0, .7);
}

/* ------------------------------------------------------------ fields --- */
#title .field { display: block; text-align: left; max-width: none; margin: 0 0 14px; }
#title .field span {
  display: block; font-size: 11px; color: var(--ink-faint);
  margin-bottom: 6px; text-transform: uppercase; letter-spacing: .14em; font-weight: 600;
}
#title .field input {
  width: 100%; padding: 11px 12px;
  background: #0a0912; border: 2px solid var(--frame); border-radius: 0;
  box-shadow: inset 0 0 0 1px #2b2740, inset 0 2px 8px rgba(0, 0, 0, .7);
  color: var(--ink); font-size: 15px; font-family: var(--font);
}
#title .field input::placeholder { color: #57526b; }
#title .field input:focus {
  outline: none; border-color: var(--gold-dim);
  box-shadow: inset 0 0 0 1px var(--gold-dim), 0 0 0 2px rgba(224, 179, 82, .16);
}

/* ----------------------------------------------------------- buttons --- */
/* Chunky and square, sitting on a solid shadow they sink into when pressed. */
#title button {
  border-radius: 0; border: 2px solid var(--frame);
  background: #1a1726; color: var(--ink);
  box-shadow: inset 0 0 0 1px #37324c, 0 3px 0 #08060d;
  padding: 10px 16px; font-size: 14px; font-weight: 600;
  transition: transform .06s, filter .12s;
}
#title button:hover { filter: brightness(1.14); }
#title .console-frame button:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
#title button:active { transform: translateY(3px); box-shadow: inset 0 0 0 1px #37324c, 0 0 0 #08060d; }
#title button.primary {
  background: linear-gradient(#e2b45c, #b0801f 58%, #8d611a);
  border-color: #241804; color: #1b1408;
  box-shadow: inset 0 1px 0 #ffe6a8, inset 0 0 0 1px #6f4d12, 0 3px 0 #4a3209;
  padding: 12px 24px; font-size: 15px; font-weight: 800;
  letter-spacing: .02em; text-shadow: 0 1px 0 rgba(255, 233, 180, .5);
}
#title button.primary:active { box-shadow: inset 0 1px 0 #ffe6a8, inset 0 0 0 1px #6f4d12, 0 0 0 #4a3209; }
#title button.primary.wide { width: 100%; }
#title button.ghost { background: transparent; color: var(--ink-dim); }
#title button.ghost:hover { color: var(--ink); }
#title button:disabled { opacity: .4; cursor: not-allowed; transform: none; }
#title button.link {
  background: none; border: none; padding: 0; box-shadow: none;
  font-size: 12px; font-weight: 500; color: var(--ink-dim); text-decoration: underline;
}
#title button.link:hover { color: var(--gold); }
#title button.link:active { transform: none; }

button {
  font-family: var(--font); cursor: pointer; border-radius: 8px;
  border: 1px solid var(--edge); background: #16141f; color: var(--ink);
  padding: 9px 16px; font-size: 14px;
}
button:hover { border-color: var(--edge-lit); }
button.primary {
  background: linear-gradient(#c4933c, #9a6f24);
  border-color: #e0b352; color: #1b1408; font-weight: 700;
  padding: 12px 28px; font-size: 16px;
}
button.primary:hover { filter: brightness(1.08); }
button.ghost { background: transparent; }
button:disabled, button[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
button.link {
  background: none; border: none; padding: 0; font-size: 12px;
  color: var(--ink-dim); text-decoration: underline; border-radius: 0;
}
button.link:hover { color: var(--ink); border: none; }

.continue { display: flex; gap: 10px; justify-content: flex-start; align-items: center; flex-wrap: wrap; }

/* ------------------------------------------------ accounts and rosters -- */
.auth-error {
  color: #ff9d92; font-size: 12.5px; margin: 0 0 12px; min-height: 1em;
  border-left: 3px solid #7d322c; padding-left: 9px; line-height: 1.45;
}
.whoami { color: var(--ink-dim); font-size: 12px; margin: 0 0 14px; }
.whoami b { color: var(--gold); }
/* Out of the way at the end of the row: rarely wanted, and never instead of signing in. */
#title button.link.forgot { margin-left: auto; }

/* Signing in with Google, under the sign-in when the server has it on: our
   own button, and once it is pressed Google's own in its place
   (client/js/google.js). */
.google-box { display: flex; align-items: center; gap: 12px; margin-top: 16px; min-height: 40px; }
.google-or { font-size: 11px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .14em; font-weight: 600; }
.google-btn { line-height: 0; }
/* Signed in with Google as nobody here yet: a name, or an account of yours. */
.gname-lede { color: var(--ink-dim); font-size: 12.5px; margin: 0 0 14px; }
.gname-lede.gname-link { margin-top: 20px; padding-top: 16px; border-top: 1px solid #1c1a28; }

/* The recovery code, shown once: big, in a face where no letter reads as
   another, and the one thing on the title that can be selected and copied. */
.code-card {
  display: grid; gap: 6px; justify-items: start;
  margin: 0 0 16px; padding: 12px 14px;
  background: rgba(0, 0, 0, .32);
  border: 2px solid var(--frame); box-shadow: inset 0 0 0 1px var(--gold-dim);
}
.code-label, .em-code-label {
  font-size: 11px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .14em; font-weight: 600;
}
.code-text, .em-code-text {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 22px; font-weight: 700; letter-spacing: .08em; color: var(--gold);
  user-select: text; -webkit-user-select: text; cursor: text; overflow-wrap: anywhere;
}
.code-note, .em-code-note { margin: 0; font-size: 12px; color: var(--ink-dim); line-height: 1.45; }
#title .code-card button { padding: 6px 14px; font-size: 13px; }

.roster { display: grid; gap: 7px; margin-bottom: 16px; }
.char-row {
  display: flex; align-items: center; gap: 12px; text-align: left;
  background: #100e19; border: 2px solid var(--frame); border-radius: 0;
  box-shadow: inset 0 0 0 1px #2a2640;
  padding: 8px 10px; cursor: pointer;
  transition: box-shadow .12s, background .12s, transform .08s;
}
.char-row:hover {
  background: #17142440; background-color: #171424;
  box-shadow: inset 0 0 0 1px var(--gold-dim), 0 0 0 1px rgba(224, 179, 82, .18);
  transform: translateX(2px);
}
/* A lit plinth for the portrait, so each character stands on something. */
.char-row .plinth {
  flex: none; position: relative;
  background: radial-gradient(60% 55% at 50% 88%, #2a2138 0%, #0d0b15 72%);
  box-shadow: inset 0 0 0 1px #262238;
  padding: 3px 5px 0; line-height: 0;
}
.char-row canvas { image-rendering: pixelated; flex: none; display: block; }
.char-row .who { flex: 1 1 auto; min-width: 0; }
.char-row .who b { display: block; font-size: 14.5px; letter-spacing: .01em; }
.char-row .who small {
  color: var(--ink-faint); font-size: 11px; text-transform: uppercase; letter-spacing: .1em;
}
/* Quiet: retiring a character is the rare thing to want from this row, and
   the row itself is the thing to click. It needs the ID to outrank the
   chunky button treatment above. */
#title .char-row .retire {
  flex: none; font-size: 10px; font-weight: 500; padding: 3px 6px;
  color: var(--ink-faint); background: none; border-color: transparent; box-shadow: none;
  text-transform: uppercase; letter-spacing: .1em;
  opacity: .4; transition: opacity .12s, color .12s, border-color .12s;
}
.char-row:hover .retire { opacity: 1; }
#title .char-row .retire:hover { color: #ff9d92; border-color: #6d3a36; }
#title .char-row .retire:active { transform: none; }
.roster-empty {
  color: var(--ink-dim); font-size: 12.5px; margin: 0 0 16px;
  padding: 18px 12px; text-align: center;
  border: 1px dashed #2c2840; background: rgba(0, 0, 0, .25);
}

/* ----------------------------------------------------- character make -- */
/* Four portraits in a row, and one readout underneath for whichever is lit —
   a character select rather than four columns of prose to compare at once. */
.classes {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px; margin-bottom: 12px;
}
.class-card {
  background: linear-gradient(#141121, #0c0a14);
  border: 2px solid var(--frame); border-radius: 0;
  box-shadow: inset 0 0 0 1px #262238;
  padding: 6px 4px 7px; cursor: pointer; text-align: center;
  transition: box-shadow .12s, transform .1s, background .12s;
}
.class-card:hover { transform: translateY(-2px); box-shadow: inset 0 0 0 1px var(--edge-lit); }
.class-card.sel {
  background: linear-gradient(#1d1730, #120e1d);
  box-shadow: inset 0 0 0 1px var(--gold), 0 0 0 1px rgba(224, 179, 82, .25), 0 0 16px rgba(224, 179, 82, .12);
  transform: translateY(-2px);
}
.class-card canvas {
  image-rendering: pixelated; display: block; margin: 0 auto 4px;
  max-width: 100%; height: auto;
  filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .55));
}
/* Two lines' worth of room whether the name needs it or not, so the four
   tiles line up along the bottom instead of stepping. */
.class-card h3 {
  margin: 0; font-size: 10px; font-weight: 700; line-height: 1.25;
  min-height: 2.5em; display: flex; align-items: center; justify-content: center;
  text-transform: uppercase; letter-spacing: .05em;
  filter: saturate(.8) brightness(.9);
}
.class-card.sel h3 { filter: none; }

.class-detail {
  border: 2px solid var(--frame); box-shadow: inset 0 0 0 1px #262238;
  background: rgba(0, 0, 0, .32);
  padding: 11px 13px; margin-bottom: 16px; min-height: 96px;
}
.class-detail h4 { margin: 0 0 7px; font-size: 15px; }
.class-detail p { margin: 0; font-size: 12px; color: var(--ink-dim); line-height: 1.6; }

/* ---------------------------------------------------- admin's dummies -- */
/* The one face wider than the console, a form in two columns: the keyart
   steps aside while it is up (main.js showPanel). */
#title.wide .keyart { display: none; }
#title.wide .title-inner { grid-template-columns: minmax(0, 1fr); justify-items: center; }
#title.wide .console { max-width: 960px; }
#title button.wide { width: 100%; }
#title button#btn-dummy { margin-top: 8px; }

.adm-row { display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap; }
#title .adm-name { flex: 0 1 220px; }
#title .adm-class { flex: 1 1 300px; }
.adm-classes { display: flex; gap: 6px; flex-wrap: wrap; }
#title .adm-classes button {
  padding: 10px 12px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em;
}
#title .adm-classes button.sel {
  background: #1d1730;
  box-shadow: inset 0 0 0 1px var(--gold), 0 0 0 1px rgba(224, 179, 82, .25), 0 3px 0 #08060d;
}
#title .adm-level { flex: 0 0 84px; }
.adm-slide { flex: 1 1 180px; margin: 0 0 27px; accent-color: var(--gold); }
#title .adm-num { flex: 0 0 168px; }

.adm-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; margin: 2px 0 16px; }
.adm-head { display: flex; align-items: center; gap: 12px; margin: 0 0 8px; min-height: 28px; }
.adm-head > span {
  font-size: 11px; color: var(--ink-faint); margin-right: auto;
  text-transform: uppercase; letter-spacing: .14em; font-weight: 600;
}
#title select {
  background: #0a0912; color: var(--ink);
  border: 2px solid var(--frame); border-radius: 0;
  box-shadow: inset 0 0 0 1px #2b2740;
  font-family: var(--font); font-size: 12.5px; padding: 5px 6px; min-width: 0;
}
#title select:focus { outline: none; border-color: var(--gold-dim); }
#title select:disabled { opacity: .35; }
#title select option { background: #0a0912; }
.adm-gear { display: grid; grid-template-columns: auto minmax(0, 1fr) 104px; gap: 5px 8px; align-items: center; }
.adm-gear label { font-size: 11px; color: var(--ink-dim); text-transform: uppercase; letter-spacing: .08em; }
.adm-ways { display: grid; gap: 7px; align-content: start; }
.adm-land { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
#title .adm-land button {
  padding: 4px 7px; font-size: 11.5px; font-weight: 500;
  color: var(--ink-dim); box-shadow: inset 0 0 0 1px #2a2640, 0 2px 0 #08060d;
}
#title .adm-land button.on {
  color: #1b1408; background: linear-gradient(#e2b45c, #b0801f);
  border-color: #241804; box-shadow: inset 0 0 0 1px #6f4d12, 0 2px 0 #4a3209;
}
#title .adm-land button.adm-landname {
  background: none; border-color: transparent; box-shadow: none;
  color: var(--ink-faint); font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .1em; padding: 4px 4px 4px 0;
}
#title .adm-land button.adm-landname.on { color: var(--gold); background: none; }
.adm-landname small { margin-left: 7px; font-weight: 500; letter-spacing: .02em; color: var(--ink-faint); }
/* A class's pages, found or not, a chip each with its land in small. */
.adm-pages { margin: 4px 0 14px; }
#title .adm-pages .adm-land button small { margin-left: 6px; font-size: 10px; opacity: .72; }
/* Make and Back, and a refusal over them, stay along the bottom of the screen
   while the form runs on past it: the waystones alone outgrow most screens.
   Held past the screen's own padding (.screen) to its very edge, so nothing
   scrolls by under them. */
.adm-foot {
  position: sticky; bottom: -32px; z-index: 2;
  margin: 0 -19px; padding: 12px 19px 14px;
  background: #0e0c15;
  box-shadow: 0 -1px 0 var(--frame-lit);
}
@media (max-width: 560px) { .adm-foot { bottom: -20px; } }
@media (max-width: 760px) {
  .adm-cols { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------------------------------------------- foot of the box -- */
.settings-row { display: flex; justify-content: center; gap: 22px; flex-wrap: wrap; }
.vol { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .1em; }
.vol input { width: 104px; accent-color: var(--gold); }

.server-line { color: var(--ink-faint); font-size: 11.5px; display: flex; align-items: center; gap: 7px; }
.server-line .dot { margin: 0 1px; }
.lamp {
  width: 7px; height: 7px; display: inline-block;
  background: #55506a; box-shadow: 0 0 0 1px #000;
}
.lamp.on { background: var(--good); box-shadow: 0 0 0 1px #000, 0 0 7px rgba(109, 220, 138, .7); }
.lamp.off { background: var(--bad); box-shadow: 0 0 0 1px #000, 0 0 7px rgba(255, 106, 106, .6); }

kbd {
  background: #1b1926; border: 1px solid var(--edge); border-bottom-width: 2px;
  border-radius: 3px; padding: 1px 5px; font-size: 11px; font-family: var(--font);
}

/* One column once the two stop fitting side by side. */
@media (max-width: 960px) {
  .title-inner { grid-template-columns: minmax(0, 1fr); gap: 26px; justify-items: center; }
  .keyart { text-align: center; max-width: 520px; }
  #wordmark { margin: 0 auto 12px; }
  .premise { margin-left: auto; margin-right: auto; }
  .console { max-width: 470px; }
  .continue { justify-content: center; }
  .google-box { justify-content: center; }
  #title button.link.forgot { margin-left: 0; }
}
@media (max-width: 560px) {
  .screen { padding: 20px 12px; align-items: start; }
  .classes { grid-template-columns: repeat(2, 1fr); }
  .class-detail { min-height: 0; }
}

/* ------------------------------------------------------------ the intro --
   Six pictures and a line under each, over the whole of the title, or of the
   game from the Story page (intro.js sizes the picture and fades each part in
   and out). The line sits under the picture, never on it. */
#title button#btn-story { margin-left: auto; }
#intro {
  position: fixed; inset: 0; z-index: 60;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 24px 16px;
  background: #050309;
  cursor: pointer;
}
#intro-pic {
  display: block; opacity: 0;
  image-rendering: pixelated; image-rendering: crisp-edges;
  box-shadow: 0 0 0 2px #0a0811, 0 0 0 3px #2a2538;
}
/* Room for three lines under it whatever they say, so the picture stands
   still from one to the next. */
.intro-words {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  min-height: calc(3 * 1.45 * 17px + 4px); max-width: min(68ch, 100%);
}
/* The first line on one row where there is room, and where there is not
   (a phone held upright) two even ones, no word left alone. */
.intro-line {
  margin: 0; text-align: center; opacity: 0;
  font-size: 17px; line-height: 1.45; color: var(--ink);
  text-shadow: 0 1px 0 #000; text-wrap: balance;
}
.intro-then { color: var(--gold); }
#intro button#intro-skip {
  position: absolute; top: 16px; right: 18px;
  font-size: 13px; color: var(--ink-faint);
}
#intro button#intro-skip:hover { color: var(--ink-dim); }
/* Big enough for a thumb: the word alone is 28 x 15 px. */
@media (pointer: coarse) {
  #intro button#intro-skip { top: 4px; right: 4px; padding: 14px 16px; font-size: 15px; }
}
@media (max-width: 560px) {
  #intro { gap: 12px; padding: 18px 12px; }
  .intro-line { font-size: 15px; }
  .intro-words { min-height: calc(3 * 1.45 * 15px + 4px); }
}

/* -------------------------------------------------------------- game --- */
#game-root { position: fixed; inset: 0; display: grid; place-items: center; background: #000; overflow: hidden; }

/* The map's rectangle on screen, sized by the renderer. Everything with .hud —
   and the chat, log and downed overlays — is positioned against this rather
   than against the window, so on a screen the view does not evenly divide, the
   interface stays on the game instead of drifting onto the black beside it.
   It also clips the world canvas, which is deliberately a little wider than
   the view: that overhang is the slack the camera nudges for sub-pixel motion. */
#stage { position: relative; overflow: hidden; }
#game, #overlay {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  image-rendering: pixelated; image-rendering: crisp-edges;
}
#overlay { pointer-events: none; }

.hud { position: absolute; z-index: 5; pointer-events: none; }

/* party (top left) */
#party { top: 10px; left: 10px; display: flex; flex-direction: column; gap: 5px; }
/* A click on a row opens that member's gear and numbers. */
.party-row {
  display: flex; align-items: center; gap: 7px;
  background: var(--panel); border: 1px solid var(--edge); border-left: 3px solid var(--gold-dim);
  border-radius: 5px; padding: 4px 8px; min-width: 172px;
  pointer-events: auto; cursor: pointer;
}
.party-row:hover { border-color: var(--edge-lit); border-left-color: var(--gold-dim); }
.party-row.downed { border-left-color: var(--hp); }
.party-row .pname { font-size: 12px; font-weight: 600; }
.party-row .plvl { font-size: 10px; color: var(--ink-faint); margin-left: auto; }
.party-row .pbar { height: 3px; background: #000; border-radius: 2px; overflow: hidden; width: 100%; margin-top: 3px; }
.party-row .pbar i { display: block; height: 100%; background: var(--hp-lit); }
.party-col { flex: 1; min-width: 0; }
.party-zone { font-size: 10px; color: var(--ink-faint); }
#party-rows { display: flex; flex-direction: column; gap: 5px; }
#crowding {
  margin-top: 5px; max-width: 186px; padding: 3px 8px;
  font-size: 10px; line-height: 1.35; color: var(--ink-dim);
  background: var(--panel); border: 1px solid var(--edge); border-radius: 5px;
}
#crowding b { color: var(--gold); font-weight: 600; }
#fogline {
  margin-top: 5px; max-width: 186px; padding: 3px 8px;
  font-size: 10px; line-height: 1.35; color: var(--ink-dim);
  background: var(--panel); border: 1px solid #3e4a52; border-radius: 5px;
}
#fogline b { color: #b9c9c4; font-weight: 600; letter-spacing: .06em; }

/* boss bar (top centre) */
#bossbar { top: 12px; left: 50%; transform: translateX(-50%); width: min(560px, 60vw); text-align: center; transition: opacity .2s; }
/* The boss drawn under it (ui.js, updateBossBar): see-through, so its wind-up shows. */
#bossbar.under { opacity: .25; }
.boss-name { font-size: 15px; font-weight: 700; letter-spacing: .04em; text-shadow: 0 2px 0 #000; }
.boss-name small { display: block; font-size: 11px; color: var(--ink-dim); font-weight: 400; font-style: italic; }
.boss-track { height: 11px; background: #14040a; border: 1px solid #4a1520; border-radius: 3px; margin-top: 5px; overflow: hidden; }
#boss-fill { height: 100%; background: linear-gradient(#e8574a, #8f1f22); transition: width .18s; }
.boss-phase { font-size: 10px; color: var(--ink-faint); margin-top: 3px; letter-spacing: .12em; }

/* top right */
#topright { top: 10px; right: 10px; text-align: right; }
#zone-name { font-size: 13px; font-weight: 700; letter-spacing: .05em; text-shadow: 0 2px 0 #000; }
#run-info { font-size: 11px; color: var(--gold); margin-bottom: 6px; }
#minimap {
  image-rendering: pixelated; border: 1px solid var(--edge);
  border-radius: 4px; background: rgba(8, 7, 13, 0.82); display: block; margin-left: auto;
}
#sovereign-track { font-size: 10px; color: var(--ink-faint); margin-top: 5px; max-width: 150px; margin-left: auto; }
#sovereign-track b { color: #ff8a3d; }

/* vitals (bottom left) */
#vitals { left: 10px; bottom: 10px; width: 210px; }

/* What is being done to you, above your own health. Loud on purpose: the only
   previous evidence of a stun was that the controls had stopped working. */
#statuses { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 5px; }
.status-chip {
  display: flex; align-items: center; gap: 5px;
  padding: 2px 7px; border-radius: 11px; font-size: 11px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
  border: 1px solid currentColor; background: rgba(8, 8, 14, .72);
  animation: pop .15s;
}
.status-chip .left {
  display: block; height: 3px; width: 34px; border-radius: 2px;
  background: currentColor; opacity: .5;
}
.status-chip.stun { color: #ffd24a; }
.status-chip.root { color: #8ef08a; }
.status-chip.slow { color: #7ec8ff; }
.status-chip.preserved { color: #e2ee7a; }
.orb-row { margin-bottom: 4px; }
.bar {
  position: relative; height: 16px; background: #0a0910;
  border: 1px solid var(--edge); border-radius: 3px; overflow: hidden;
}
.bar span {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 10px; font-weight: 700; text-shadow: 0 1px 2px #000; letter-spacing: .03em;
}
#hp-fill { height: 100%; background: linear-gradient(var(--hp-lit), var(--hp)); transition: width .12s; }
#shield-fill { position: absolute; top: 0; left: 0; height: 100%; background: rgba(224, 179, 82, .55); }
#ae-fill { height: 100%; background: linear-gradient(var(--ae-lit), var(--ae)); transition: width .12s; }
/* Experience: the level you are on the gold badge, how far into the next one
   on the bar. The pale stretch past the fill is what you have just earned,
   and the fill slides up into it; a level-up runs the fill off the end and
   the whole row flashes as the badge turns over (xpbar.js). */
.xp-row { display: flex; gap: 4px; }
.xp-level {
  flex: none; display: flex; align-items: baseline; justify-content: center; gap: 2px;
  min-width: 40px; height: 14px; padding: 0 5px;
  background: #17120a; border: 1px solid var(--gold-dim); border-radius: 3px;
  color: var(--gold); font-size: 11px; line-height: 12px; text-shadow: 0 1px 2px #000;
}
.xp-level small { font-size: 8px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #b8934a; }
.xp-level b { font-weight: 800; }
#vitals .bar.xp { flex: 1; height: 14px; }
#xp-loss, #xp-gain, #xp-fill { position: absolute; top: 0; left: 0; height: 100%; }
/* What bleeding out just took: the stretch the fill dropped off, standing a
   moment before it drains back to where the fill is now. Striped, so right
   under the health bar it reads as gone rather than as more health. */
#xp-loss { background: repeating-linear-gradient(135deg, #c9433c 0 3px, #6e1b18 3px 6px); }
#xp-gain { background: rgba(222, 204, 255, .42); }
#xp-fill { background: linear-gradient(#d5bbff, var(--xp) 55%, #8d63d8); }
.bar.xp span { z-index: 1; }
/* The flash: gold over the whole bar, fading as the new level fills in. */
.bar.xp::after {
  content: ''; position: absolute; inset: 0; opacity: 0; pointer-events: none;
  background: linear-gradient(#fff6d6, #ffd24a);
}
/* Held bright, then gone quickly: gold fading slowly over the dark of an
   empty bar spends most of its time the colour of mud. */
.xp-row.lvlup .bar.xp::after { animation: xp-flash .6s cubic-bezier(.7, 0, .9, .6); }
.xp-row.lvlup .bar.xp { animation: xp-glow 1.1s ease-out; }
.xp-row.lvlup .xp-level { animation: xp-pop .7s cubic-bezier(.2, 1.4, .4, 1), xp-glow 1.1s ease-out; }
@keyframes xp-flash { from { opacity: .95; } to { opacity: 0; } }
@keyframes xp-glow {
  from { border-color: #ffe7a0; box-shadow: 0 0 12px 2px rgba(255, 210, 74, .8); }
  to { box-shadow: 0 0 0 0 rgba(255, 210, 74, 0); }
}
@keyframes xp-pop { from { transform: scale(1.5); color: #fff6d6; } to { transform: scale(1); } }
/* And a death: the bar's edge goes red and the badge shudders. */
.xp-row.xploss .bar.xp { animation: xp-bleed 1.3s ease-out; }
.xp-row.xploss .xp-level { animation: xp-shudder .45s linear, xp-bleed 1.3s ease-out; }
@keyframes xp-bleed {
  from { border-color: #ff8a7a; box-shadow: 0 0 12px 2px rgba(201, 67, 60, .85); }
  to { box-shadow: 0 0 0 0 rgba(201, 67, 60, 0); }
}
@keyframes xp-shudder {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-2px); } 40% { transform: translateX(2px); }
  60% { transform: translateX(-1px); } 80% { transform: translateX(1px); }
}
.purse { display: flex; gap: 10px; font-size: 11px; color: var(--ink-dim); margin-top: 7px; }
.purse b { color: var(--ink); }
/* A death just took a share of all of it: the counts go red for a moment. */
#vitals.tolled .purse b { animation: purse-toll 1.6s ease-out; }
@keyframes purse-toll { from, 35% { color: var(--bad); } to { color: var(--ink); } }
.purse.supplies { margin-top: 3px; }
.purse .scrap { color: #cbb27a; }
.purse .essence { color: #b98cff; }
.purse .wood { color: #a3763f; }
.purse .stone { color: #8b8a9e; }
.purse .gold { color: #f0d07a; }

/* action bar */
#actionbar {
  bottom: 10px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 7px; pointer-events: auto;
}
.slot {
  position: relative; width: 46px; height: 46px;
  background: var(--panel); border: 1px solid var(--edge); border-radius: 7px;
  display: grid; place-items: center; cursor: pointer;
}
.slot.ready { border-color: var(--edge-lit); }
.slot.locked { opacity: .4; }
.slot .key { position: absolute; top: 2px; left: 4px; font-size: 9px; color: var(--ink-faint); font-weight: 700; }
.slot .nm { font-size: 9px; color: var(--ink-dim); position: absolute; bottom: 2px; left: -8px; right: -8px; text-align: center; white-space: nowrap; }
.slot .glyph { font-size: 19px; line-height: 1; }
/* An ability's own pixel icon: the one its branch wears in the skill tree. */
.slot .glyph canvas { display: block; image-rendering: pixelated; }
.slot .cd {
  position: absolute; inset: 0; background: rgba(6, 6, 12, .74);
  display: grid; place-items: center; font-size: 14px; font-weight: 700; border-radius: 6px;
}
.slot .cost { position: absolute; top: 2px; right: 4px; font-size: 9px; color: var(--ae-lit); }
.slot.flask .glyph { color: var(--good); }
/* The wait after a drink (--wait, set by ui.js): the shadow a skill's wait
   lays over its slot, going off the flask the way a clock hand goes round. */
.slot.flask::after {
  content: ''; position: absolute; inset: 0; border-radius: 6px; pointer-events: none;
  background: conic-gradient(transparent calc(360deg - var(--wait, 0deg)), rgba(6, 6, 12, .74) 0);
}
.slot.noaether { border-color: #5a2230; }
/* Up (ui.js slotUp): Buckshot's spreads still coming, or one of the eight
   while it lasts. Lit round, and a strip along its foot running down by the
   seconds it has left (--up, 1 to 0), over its wait if it has one. */
.slot.up { border-color: var(--gold); box-shadow: 0 0 9px rgba(224, 179, 82, .5); }
.slot.up::after {
  content: ''; position: absolute; left: 5px; right: 5px; bottom: 3px; height: 2px; border-radius: 1px;
  background: var(--gold); transform-origin: left; transform: scaleX(var(--up, 1)); pointer-events: none;
}
/* Caked in a Mudlark's mud (ui.js): no roll till it dries, and the roll's
   slot is under mud as you are, its key and its wait still showing over it. */
.slot.mudded { border-color: #5c4128; }
.slot.mudded::before {
  content: ''; position: absolute; inset: 0; border-radius: 6px; pointer-events: none; z-index: 1;
  background: linear-gradient(to top, rgba(61, 42, 23, .92) 0 56%, rgba(125, 93, 58, .8) 56% 61%, transparent 61%);
}
.slot.mudded .glyph { opacity: .4; }
.slot.mudded .key, .slot.mudded .cd { z-index: 2; }
/* A Salt Scorpion's claw shut on your weapon (ui.js): no left click while it
   holds, and the claw shut on its slot too. */
.slot.gripped { border-color: #736865; }
.slot.gripped::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke-linecap='round'><path d='M7.5 9 A6 6 0 1 1 7.5 15 M17 12 H23' stroke='%231c1614' stroke-width='6'/><path d='M7.5 9 A6 6 0 1 1 7.5 15 M17 12 H23' stroke='%23c9bdb2' stroke-width='3'/></svg>") center / 30px no-repeat;
}
.slot.gripped .glyph { opacity: .35; }
.slot.gripped .key { z-index: 2; }
/* Branded by a Scorch Bear (ui.js): nothing heals you, a flask no more than
   the rest, and the brand's three cuts glow on the flask as they do on you. */
.slot.branded { border-color: #d8481a; box-shadow: 0 0 8px rgba(255, 138, 42, .45); }
.slot.branded::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke-linecap='round'><path d='M9 5 L5 16 M14 5 L10 17 M19 6 L15 18' stroke='%23a8341a' stroke-width='3.4'/><path d='M9 5 L5 16 M14 5 L10 17 M19 6 L15 18' stroke='%23ffc24a' stroke-width='1.4'/></svg>") center / 30px no-repeat;
}
.slot.branded .glyph { opacity: .35; }
.slot.branded .key, .slot.branded .nm { z-index: 2; }
/* A key with no skill on it yet: the frame is there so the four read as four. */
.slot.empty { background: rgba(10, 9, 16, .55); border-style: dashed; cursor: default; }
/* The mouse's two tiles wear a mouse in the corner where a key has its letter,
   the button they are lit in gold, and stand a little apart from the keys. */
.slot .key .mouse-glyph { display: block; width: 10px; height: 14px; margin: 1px 0 0 -1px; color: var(--ink-dim); }
.mouse-glyph .lit { fill: var(--gold); }
#actionbar .slot.mouse + .slot:not(.mouse) { margin-left: 6px; }
/* Left click is the class's own attack and never a slot: no cost, no
   cooldown, nothing to pick up, and a frame of its own. */
.slot.fixed { cursor: default; border-color: var(--gold-dim); }
/* Right click with nothing on it, showing the skill on Q that it casts. */
.slot.mirror { border-style: dashed; }
.slot.mirror .glyph, .slot.mirror .cost { opacity: .42; }
/* A skill being carried to another slot. */
body.dragging-skill, body.dragging-skill * { cursor: grabbing !important; }
#actionbar .slot.drop { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold), 0 0 12px rgba(224, 179, 82, .45); }
#actionbar .slot.nodrop { border-color: var(--bad); opacity: .55; }
/* Every point in it (skill paths): a gold rim, as on its tile in the tree. */
#actionbar .slot.mastered { border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(224, 179, 82, .45), 0 0 10px rgba(224, 179, 82, .35); }
.slot-ghost {
  position: fixed; z-index: 45; pointer-events: none; transform: translate(-50%, -50%);
  width: 40px; height: 40px; display: grid; place-items: center;
  background: var(--panel); border: 1px solid var(--edge-lit); border-radius: 7px;
  box-shadow: var(--shadow); opacity: .9;
}
.slot-ghost.ok { border-color: var(--gold); }
.slot-ghost.no { border-color: var(--bad); opacity: .5; }
.slot-ghost canvas { display: block; image-rendering: pixelated; }

/* log */
#log {
  right: 10px; bottom: 10px; width: 300px; max-height: 168px;
  overflow: hidden; display: flex; flex-direction: column; justify-content: flex-end; gap: 2px;
}
.log-line { font-size: 11px; color: var(--ink-dim); text-shadow: 0 1px 2px #000; line-height: 1.35; }
.log-line.good { color: var(--good); }
.log-line.bad { color: var(--bad); }
.log-line.chat { color: #cfd6e6; }
.log-line.legendary { color: var(--legendary); }
.log-line.rare { color: var(--rare); }
.log-line.godlike { color: var(--godlike); font-weight: 700; }
.log-line.uniq { color: var(--uniqgold); font-weight: 700; }
/* Arriving somewhere. This was a banner across the middle of the screen; in
   the log it still wants to read as a heading rather than as another line. */
.log-line.zone {
  color: var(--ink); letter-spacing: .1em; text-transform: uppercase;
  font-size: 10px; margin: 3px 0 1px;
}

@keyframes pop { from { transform: scale(.9); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* panels */
#panel {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(4, 4, 8, .55); z-index: 20; pointer-events: auto;
}
.panel-box {
  background: var(--panel-solid); border: 1px solid var(--edge);
  border-radius: 12px; box-shadow: var(--shadow);
  width: min(880px, 94vw); max-height: 88vh; display: flex; flex-direction: column;
}
.panel-head {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 16px; border-bottom: 1px solid var(--edge);
}
.panel-head h2 { margin: 0; font-size: 16px; letter-spacing: .06em; text-transform: uppercase; }
.panel-head .close { margin-left: auto; }
/* A window's close button is the cross alone; its key is on the hover. */
.x-close {
  flex: none; width: 28px; height: 28px; padding: 0;
  display: grid; place-items: center; font-size: 17px; line-height: 1;
}
.x-close::before { content: '×'; }
.panel-tabs { display: flex; gap: 6px; }
.panel-tabs button { padding: 5px 12px; font-size: 12px; }
.panel-tabs button.sel { border-color: var(--gold); color: var(--gold); }
.panel-body { padding: 16px; overflow-y: auto; }
/* A party member's window: their name where the tabs would be. */
.inspect-who { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.inspect-who b { font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inspect-who span { font-size: 12px; color: var(--ink-faint); white-space: nowrap; }
.inspect-gap { height: 12px; }

/* The counter, as a window of its own.
   Docked to the left and above the panel's dim, so that opening your inventory
   puts the two side by side: prices on the left, what you are wearing on the
   right. The panel gives up the middle of the screen while a counter is open
   rather than sliding underneath it. The chest in the Hold you keep things
   in is a window the same way, in the same place. */
#trade, #stash {
  position: absolute; z-index: 21;
  top: 50%; left: 24px; transform: translateY(-50%);
  width: 440px; max-height: 88vh;
  display: flex; flex-direction: column;
  background: var(--panel-solid); border: 1px solid var(--edge);
  border-radius: 12px; box-shadow: var(--shadow);
}
.trade-body { padding: 16px; overflow-y: auto; }
/* Narrow window: stock over bag rather than beside it. */
.trade-cols { display: grid; gap: 16px; }

body.trading #panel { padding-left: 488px; }
body.trading .panel-box { width: min(880px, calc(100vw - 536px)); }

/* Ruddock's gate into the ring. Small, low and central, under what he said,
   because it is one question with one answer. */
#ringgate {
  position: absolute; z-index: 21;
  left: 50%; bottom: 170px; transform: translateX(-50%);
  width: min(420px, 92vw); padding: 12px 16px 14px;
  background: var(--panel-solid); border: 1px solid #7a3a2a;
  border-radius: 12px; box-shadow: var(--shadow), inset 0 0 22px rgba(255, 106, 74, .08);
  animation: pop .15s;
}
#ringgate .ring-title { font-size: 13px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #ff9a7a; }
#ringgate p { margin: 6px 0 8px; font-size: 12px; line-height: 1.5; color: var(--ink-dim); }
#ringgate .ring-count { margin-left: 6px; font-size: 11px; font-weight: 500; letter-spacing: .04em; text-transform: none; color: var(--ink-faint); }
#ringgate .ring-actions { display: flex; gap: 8px; }

/* Not enough width for two windows abreast: the counter goes wide and simply
   covers the panel, which is still there when you close it. */
@media (max-width: 900px) {
  #trade, #stash { left: 3vw; right: 3vw; width: auto; }
  body.trading #panel { padding-left: 0; }
  body.trading .panel-box { width: min(880px, 94vw); }
}

.cols { display: grid; grid-template-columns: 330px 1fr; gap: 18px; }
@media (max-width: 720px) { .cols { grid-template-columns: 1fr; } }

/* Ten slots is too many for one column on a laptop, so the paperdoll pairs
   them up and collapses back to a single column on a phone. */
.paperdoll { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
@media (max-width: 900px) { .paperdoll { grid-template-columns: 1fr; } }

.equip-slot {
  display: flex; gap: 8px; align-items: center;
  background: #0d0c14; border: 1px solid var(--edge); border-radius: 8px;
  padding: 6px 8px; cursor: pointer; min-width: 0;
}
.equip-slot:hover { border-color: var(--edge-lit); }
.equip-slot.empty { cursor: default; opacity: .62; }
/* Somebody else's: there to be looked at, not clicked. */
.equip-slot.ro { cursor: default; }
.equip-slot.r1 { border-color: #24466e; }
.equip-slot.r2 { border-color: #7a4a12; }
.equip-slot.r3 { border-color: #7a1230; box-shadow: inset 0 0 14px rgba(255, 61, 110, .2); }
.equip-slot.setpiece { box-shadow: inset 3px 0 0 var(--setgreen); }
/* The slot a hovered bag item would go into. Lit rather than recoloured, so
   the rarity border underneath still reads. */
.equip-slot.cmp-target { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold), 0 0 12px rgba(224, 179, 82, .25); opacity: 1; }
.equip-slot canvas { image-rendering: pixelated; }
.equip-slot .meta { min-width: 0; }
.equip-slot .nm { font-size: 12px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.equip-slot .sub { font-size: 10px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; }

.bag { display: grid; grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); gap: 6px; }
.bag-cell {
  position: relative; aspect-ratio: 1; background: #0d0c14;
  border: 1px solid var(--edge); border-radius: 6px; display: grid; place-items: center; cursor: pointer;
}
.bag-cell:hover { border-color: var(--edge-lit); }
.bag-cell canvas { image-rendering: pixelated; }
.bag-cell.r1 { border-color: #24466e; box-shadow: inset 0 0 12px rgba(74, 163, 255, .14); }
.bag-cell.r2 { border-color: #7a4a12; box-shadow: inset 0 0 12px rgba(255, 154, 46, .18); }
.bag-cell.r3 { border-color: #a01840; box-shadow: inset 0 0 14px rgba(255, 61, 110, .3), 0 0 10px rgba(255, 61, 110, .2); }
.bag-cell.setpiece { box-shadow: inset 3px 0 0 var(--setgreen); }
.bag-cell.uniq::before {
  content: ''; position: absolute; top: 2px; left: 3px; width: 4px; height: 4px;
  border-radius: 50%; background: var(--uniqgold); box-shadow: 0 0 5px var(--uniqgold);
}
.bag-cell.locked { opacity: .5; }
.bag-cell.locked::after {
  content: '\00d7'; position: absolute; bottom: 0; left: 4px;
  font-size: 11px; color: var(--bad); font-weight: 700;
}
/* What a merchant will pay for it, on the corner of the icon. */
.bag-cell .price { position: absolute; bottom: 1px; right: 3px; font-size: 10px; font-weight: 700; text-shadow: 0 1px 2px #000; }

.stat-row { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-bottom: 1px solid #1c1a26; }
.stat-row .lab { font-size: 12px; }
.stat-row .val { margin-left: auto; font-weight: 700; font-size: 13px; }
.stat-row button { padding: 1px 9px; font-size: 14px; line-height: 1.2; }
.stat-note { font-size: 11px; color: var(--ink-faint); }

.build-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px; }
.build-card {
  background: #0d0c14; border: 1px solid var(--edge); border-radius: 8px; padding: 10px; cursor: pointer;
}
.build-card:hover { border-color: var(--edge-lit); }
.build-card.sel { border-color: var(--gold); }
.build-card.cant { opacity: .5; }
.build-card h4 { margin: 0 0 3px; font-size: 13px; }
.build-card p { margin: 0 0 6px; font-size: 11px; color: var(--ink-dim); line-height: 1.4; }
.build-card .cost { font-size: 11px; display: flex; flex-wrap: wrap; gap: 8px; }
.build-card .cost .short { color: var(--bad); text-decoration: line-through; }
.build-card .where { font-size: 10px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px; }
.build-cat { margin: 12px 0 6px; font-size: 11px; color: var(--gold); letter-spacing: .08em; text-transform: uppercase; }
.build-cat:first-child { margin-top: 0; }

.tip { font-size: 11px; color: var(--ink-faint); margin-top: 10px; line-height: 1.5; }

/* ------------------------------------------------------------ skill tree ---
   Its own window on [K], not a tab on the bag. Framed like the front door —
   square corners, hard keylines, gold brackets. The class colour runs
   through everything you own, gold is kept for what you can spend on, and
   what is out of reach is left grey instead of being labelled.

   The skills are a tree, a line down from each to the ones it opens, in
   bands by the level they open at, and the pane beside it is the one you
   are on (skilltree.js). */
#skilltree {
  position: absolute; inset: 0; z-index: 20; pointer-events: auto;
  /* minmax(0, …): what is inside is sized to the window, so the window must
     not be sized to what is inside. With the row as tall as the screen, a
     tree too big for it scrolls inside the window, under its header and
     beside its pane, not the window off the screen. */
  display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr);
  place-items: center; padding: 12px;
  background: rgba(4, 4, 8, .62); overflow: auto;
}
.st-box {
  --frame: #0a0811; --frame-lit: #3b3553;
  position: relative; width: min(1100px, 100%); max-height: 100%;
  display: flex; flex-direction: column;
  background:
    radial-gradient(60% 50% at 38% 0%, rgba(var(--cls-rgb), .09), transparent 72%),
    linear-gradient(#141220, #0c0a14);
  border: 2px solid var(--frame);
  box-shadow: inset 0 0 0 1px var(--frame-lit), 0 18px 50px rgba(0, 0, 0, .65);
}
.st-box::before, .sp-box::before {
  content: ''; position: absolute; inset: -5px; pointer-events: none;
  border: 2px solid var(--gold-dim);
  --corner: linear-gradient(#000, #000) no-repeat;
  -webkit-mask:
    var(--corner) top left / 16px 16px, var(--corner) top right / 16px 16px,
    var(--corner) bottom left / 16px 16px, var(--corner) bottom right / 16px 16px;
  mask:
    var(--corner) top left / 16px 16px, var(--corner) top right / 16px 16px,
    var(--corner) bottom left / 16px 16px, var(--corner) bottom right / 16px 16px;
}

/* One row: who you are, what you have to spend, and the way out. */
.st-head {
  display: flex; align-items: center; gap: 12px; flex: none;
  padding: 8px 10px 8px 14px; border-bottom: 1px solid var(--edge);
}
.st-portrait {
  image-rendering: pixelated; flex: none; padding: 2px 3px 0;
  background: radial-gradient(60% 55% at 50% 88%, rgba(var(--cls-rgb), .28) 0%, #0d0b15 74%);
  box-shadow: inset 0 0 0 1px #262238;
}
.st-title { min-width: 0; margin-right: auto; }
.st-who { font-size: 13px; color: var(--ink-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.st-who b { color: var(--cls); }
.st-points span {
  font-size: 10px; text-transform: uppercase; letter-spacing: .12em; color: var(--ink-faint); white-space: nowrap;
}
.st-points { display: flex; align-items: baseline; gap: 6px; margin-left: 12px; }
.st-points b {
  font-size: 24px; line-height: 1; font-weight: 800; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.st-points.has b { color: var(--gold); text-shadow: 0 0 14px rgba(224, 179, 82, .45); }
.st-points.has span { color: var(--gold); }
.st-close, .st-respec, .st-d-act {
  border-radius: 0; border: 2px solid var(--frame); background: #1a1726; color: var(--ink);
  box-shadow: inset 0 0 0 1px #37324c, 0 3px 0 #08060d;
  padding: 8px 14px; font-size: 13px; font-weight: 600;
}
.st-close:hover, .st-respec:hover, .st-d-act:hover { filter: brightness(1.15); border-color: var(--frame); }
.st-close:active, .st-respec:active, .st-d-act:active { transform: translateY(3px); box-shadow: inset 0 0 0 1px #37324c, 0 0 0 #08060d; }
.st-close { width: 34px; height: 34px; padding: 0; display: grid; place-items: center; margin-left: 10px; }
.st-close svg { display: block; }
.st-respec { padding: 6px 12px; font-size: 11.5px; color: var(--ink-dim); box-shadow: inset 0 0 0 1px #37324c, 0 2px 0 #08060d; }
.st-respec.free { color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold-dim), 0 2px 0 #08060d; }

.st-main { display: flex; flex: 1 1 auto; min-height: 0; }

/* The tree, beside the pane: the bands of levels with the rail down their
   left, the lines, and the skills over them, each its icon in a frame with
   its rank on the corner and its name under it (skilltree.js treeHtml). Laid
   out to the pixel there; a tree bigger than the room scrolls inside the
   window. */
.st-grid {
  flex: 1 1 auto; min-width: 0; overflow: auto; scrollbar-gutter: stable;
  display: flex;
  background:
    radial-gradient(70% 60% at 50% 0%, rgba(var(--cls-rgb), .08), transparent 70%),
    radial-gradient(rgba(255, 255, 255, .04) 1px, transparent 1.5px) 0 0 / 16px 16px;
}
.st-tree { position: relative; flex: none; margin: auto; }

/* A band a level: clear once your level has reached it, darker until. */
.st-band { position: absolute; left: 0; right: 0; background: rgba(0, 0, 0, .28); border-top: 1px solid #1c1927; }
.st-band:first-child { border-top: 0; }
.st-band.on { background: none; }

/* The levels down the left, filled to yours in the class colour. */
.st-rail { position: absolute; top: 0; bottom: 0; width: 0; pointer-events: none; }
.st-rail i { position: absolute; left: -2px; width: 4px; }
.st-rail-line { background: #221f30; }
.st-rail-fill { background: var(--cls); box-shadow: 0 0 8px rgba(var(--cls-rgb), .45); }
.st-lvmark {
  position: absolute; left: 0; transform: translate(-50%, -50%);
  min-width: 30px; padding: 3px 5px; font-size: 11px; font-weight: 800; line-height: 12px; text-align: center;
  color: var(--ink-faint); background: #0d0b15; box-shadow: inset 0 0 0 1px #2d2943;
  font-variant-numeric: tabular-nums;
}
.st-lvmark small { display: block; font-size: 8px; line-height: 9px; letter-spacing: .12em; font-weight: 700; opacity: .8; }
.st-lvmark.on { color: #0a0911; background: var(--cls); box-shadow: 0 0 10px rgba(var(--cls-rgb), .35); }

/* The lines: dark while what they come from is not deep enough; dashed in
   the class colour when only the level is missing; dull gold when nothing
   but a point is; gold into a skill you can buy now; the class colour into
   one you have. The way down to the skill in the pane is lit. */
.st-lines { position: absolute; left: 0; top: 0; pointer-events: none; overflow: visible; }
.st-edge, .st-glow { fill: none; stroke-linejoin: round; }
.st-edge { stroke-width: 3; transition: stroke .12s; }
.st-glow { stroke-width: 9; stroke-linecap: round; stroke-opacity: .14; }
.st-edge.shut { stroke: #272335; }
.st-edge.open { stroke: #6a5524; }
.st-edge.wait { stroke: rgba(var(--cls-rgb), .4); stroke-dasharray: 5 5; }
.st-edge.ready, .st-glow.ready { stroke: var(--gold); }
.st-edge.own, .st-glow.own { stroke: var(--cls); }
.st-edge.ready, .st-edge.own { stroke-width: 3.5; }
.st-edge.shut.trail { stroke: #5d5876; }
.st-edge.open.trail { stroke: #a8853a; }
.st-edge.wait.trail { stroke: rgba(var(--cls-rgb), .75); }

/* A skill: its icon in a frame, its key on one corner and its rank on the
   other, its name under it, its forks beside it, and the + to buy a rank. */
.st-node { position: absolute; width: 64px; }
.st-card {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 8px;
  width: 100%; padding: 0; margin: 0;
  font-family: var(--font); color: var(--ink);
  background: none; border: 0; border-radius: 0; box-shadow: none;
}
.st-card:hover { background: none; border: 0; box-shadow: none; }
.st-icon {
  position: relative; flex: none; width: 64px; height: 64px; display: grid; place-items: center;
  background: linear-gradient(#181526, #0f0d18);
  border: 2px solid var(--frame);
  box-shadow: inset 0 0 0 1px #2a2640;
  transition: box-shadow .12s;
}
.st-icon canvas { position: relative; display: block; image-rendering: pixelated; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .6)); }
.st-card:hover .st-icon { box-shadow: inset 0 0 0 1px var(--edge-lit); }
/* Not learned: the icon greyed until it is. */
.st-card.none .st-icon canvas { filter: grayscale(.9) brightness(.55) drop-shadow(0 2px 0 rgba(0, 0, 0, .6)); }
/* Shut: its level not reached, or what it comes after not deep enough. */
.st-card.shut .st-icon, .st-card.lock .st-icon { background: linear-gradient(#121019, #0c0a12); }
.st-card.shut .st-icon canvas, .st-card.lock .st-icon canvas { filter: grayscale(1) brightness(.38); }
/* Learned, in the class colour; every rank of it, brighter. */
.st-card.some .st-icon { box-shadow: inset 0 0 0 1px rgba(var(--cls-rgb), .7), 0 0 12px rgba(var(--cls-rgb), .18); }
.st-card.max .st-icon { box-shadow: inset 0 0 0 2px var(--cls), 0 0 14px rgba(var(--cls-rgb), .3); }
/* A rank you can buy now. */
.st-card.can .st-icon { box-shadow: inset 0 0 0 1px var(--gold-dim), 0 0 14px rgba(224, 179, 82, .18); }
/* The one in the pane. */
.st-card.sel .st-icon { box-shadow: inset 0 0 0 2px var(--gold), 0 0 18px rgba(224, 179, 82, .3); }
.st-card:focus-visible, .st-pill:focus-visible, .st-plus:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.st-card:focus-visible { outline: none; }
.st-card:focus-visible .st-icon { outline: 2px solid var(--gold); outline-offset: 3px; }
.st-icon kbd {
  position: absolute; left: -6px; top: -6px; z-index: 1;
  min-width: 15px; height: 15px; padding: 0 3px; font-size: 9.5px; font-weight: 700; line-height: 15px; text-align: center;
  color: var(--ink); background: #0a0911; border: 0; border-radius: 0;
  box-shadow: inset 0 0 0 1px #3b3553;
}
.st-icon kbd .mouse-glyph { display: block; width: 9px; height: 13px; margin: 1px auto; }
/* A learned active with no key left for it: the corner empty, waiting for one. */
.st-icon kbd.off { box-shadow: none; outline: 1px dashed rgba(224, 179, 82, .8); outline-offset: -1px; background: rgba(10, 9, 17, .75); }
/* Its rank on the opposite corner, in the class colour once it has one; the
   level it opens at while it waits for it. */
.st-icon em {
  position: absolute; right: -6px; bottom: -6px; z-index: 1;
  padding: 1px 4px; font-style: normal; font-size: 10.5px; font-weight: 800; line-height: 13px; white-space: nowrap;
  color: var(--ink-dim); background: #0a0911; box-shadow: inset 0 0 0 1px #2d2943;
  font-variant-numeric: tabular-nums;
}
.st-card.some .st-icon em, .st-card.max .st-icon em { color: #0a0911; background: var(--cls); box-shadow: none; }
.st-card.can .st-icon em { color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold-dim); }
.st-card.some.can .st-icon em { color: #0a0911; background: var(--cls); box-shadow: none; }
.st-icon em.lv { color: var(--ink-faint); }
.st-nm {
  max-width: var(--nm, 140px); font-size: 11.5px; font-weight: 600; line-height: 14px; text-align: center;
  color: var(--ink-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.st-card.some .st-nm, .st-card.max .st-nm, .st-card.sel .st-nm { color: var(--ink); }
.st-card.shut .st-nm, .st-card.lock .st-nm { color: var(--ink-faint); }

/* Its forks beside it: a pair of diamonds a fork, rank 4's over rank 9's,
   each on a stub from the frame. */
.st-fks { position: absolute; left: 100%; top: 24px; display: grid; gap: 12px; padding-left: 2px; }
.st-fk { display: flex; align-items: center; gap: 5px; height: 12px; }
.st-fk::before { content: ''; width: 12px; height: 3px; margin-right: 2px; background: #272335; }
.st-fk.open::before { background: var(--gold-dim); }
.st-fk.own::before { background: var(--cls); box-shadow: 0 0 6px rgba(var(--cls-rgb), .5); }
.st-fk b { flex: none; width: 11px; height: 11px; transform: rotate(45deg); background: #0c0b12; box-shadow: inset 0 0 0 1px #2b2737; }
.st-fk b.due { box-shadow: inset 0 0 0 1px var(--gold-dim); }
.st-fk b.ready { background: #2a1f08; box-shadow: inset 0 0 0 1px var(--gold); animation: st-pip 1.3s ease-in-out infinite; }
.st-fk b.own { background: var(--gold); box-shadow: 0 0 6px rgba(224, 179, 82, .6); }
.st-fk b.lost { opacity: .45; }

/* The ranks as pips at the top of the pane, with the forks as diamonds
   where they fall among them. */
.st-pips { display: flex; align-items: center; gap: 3px; margin-top: auto; }
.st-pips i { flex: none; width: 7px; height: 9px; background: #0c0b12; box-shadow: inset 0 0 0 1px #25212f; }
.st-pips i.open { box-shadow: inset 0 0 0 1px rgba(var(--cls-rgb), .5); }
.st-pips i.own { background: var(--cls); box-shadow: none; }
.st-pips i.next { background: #1d1708; box-shadow: inset 0 0 0 1px var(--gold); animation: st-pip 1.3s ease-in-out infinite; }
.st-pips b { flex: none; width: 7px; height: 7px; margin: 0 3px; transform: rotate(45deg); background: #0c0b12; box-shadow: inset 0 0 0 1px #2b2737; }
.st-pips b.open { box-shadow: inset 0 0 0 1px #4d4766; }
.st-pips b.due { box-shadow: inset 0 0 0 1px var(--gold-dim); }
.st-pips b.ready { background: #2a1f08; box-shadow: inset 0 0 0 1px var(--gold); animation: st-pip 1.3s ease-in-out infinite; }
.st-pips b.own { background: var(--gold); box-shadow: 0 0 6px rgba(224, 179, 82, .55); }
@keyframes st-pip { 50% { background: #5a4410; box-shadow: inset 0 0 0 1px #fff1c4; } }

/* The one button that spends, on the corner of the thing it spends on. */
.st-plus {
  position: absolute; right: -10px; top: -10px; z-index: 2;
  width: 22px; height: 22px; padding: 0; border-radius: 0;
  font-size: 16px; font-weight: 800; line-height: 1; color: #1b1408;
  background: linear-gradient(#e2b45c, #b0801f 60%, #8d611a);
  border: 2px solid #241804; box-shadow: inset 0 1px 0 #ffe6a8, 0 2px 0 #4a3209, 0 0 10px rgba(224, 179, 82, .45);
}
.st-plus:hover { filter: brightness(1.12); border-color: #241804; }
.st-plus:active { transform: translateY(2px); box-shadow: inset 0 1px 0 #ffe6a8; }

/* The capstone, always on once learned: in a diamond at the foot of the
   tree, its name in gold. */
.st-node.cap .st-icon { background: none; border: 0; box-shadow: none; }
.st-node.cap .st-icon::before {
  content: ''; position: absolute; inset: -3px; transform: rotate(45deg);
  background: linear-gradient(135deg, #1b1526, #0f0c17); border: 2px solid var(--frame);
  box-shadow: inset 0 0 0 1px rgba(224, 179, 82, .45);
}
.st-node.cap .st-card.shut .st-icon::before, .st-node.cap .st-card.lock .st-icon::before { box-shadow: inset 0 0 0 1px #3a3326; }
.st-node.cap .st-card.can .st-icon::before { box-shadow: inset 0 0 0 1px var(--gold), 0 0 16px rgba(224, 179, 82, .3); }
.st-node.cap .st-card.some .st-icon::before, .st-node.cap .st-card.max .st-icon::before { box-shadow: inset 0 0 0 2px var(--gold), 0 0 18px rgba(224, 179, 82, .4); }
.st-node.cap .st-card.sel .st-icon::before { box-shadow: inset 0 0 0 2px var(--gold), 0 0 18px rgba(224, 179, 82, .35); }
.st-node.cap .st-icon em { right: 50%; bottom: -24px; transform: translateX(50%); }
.st-node.cap .st-nm { margin-top: 24px; max-width: none; color: var(--gold-dim); }
.st-node.cap .st-card.some .st-nm, .st-node.cap .st-card.sel .st-nm { color: var(--gold); }

/* What a pointed-at fork names. */
.st-card.named .st-icon { outline: 1px dashed var(--cls); outline-offset: 4px; }

/* The pane, and the refund under it. */
.st-side {
  flex: none; width: 340px; display: flex; flex-direction: column;
  border-left: 1px solid var(--edge); background: rgba(0, 0, 0, .2);
  /* Side by side, the window is centred on the screen, so a pane that grew
     with what it was showing would move the whole window: point at a skill
     whose text is longer, the window slides out from under the pointer, and
     round again. The pane takes the tree's height and scrolls instead. */
  contain: size;
}
.st-detail {
  flex: 1 1 auto; min-height: 0; padding: 14px 16px 16px; overflow-y: auto;
  font-size: 12px; color: var(--ink-dim); line-height: 1.5;
}
.st-side-foot { flex: none; display: flex; justify-content: flex-end; padding: 10px 16px 12px; border-top: 1px solid var(--edge); }
.st-detail h3 { margin: 0; font-size: 15px; color: var(--ink); line-height: 1.25; }
.st-detail h4 {
  margin: 16px 0 5px; font-size: 10px; font-weight: 700; color: var(--ink-faint);
  letter-spacing: .14em; text-transform: uppercase;
}
.st-detail p { margin: 0; }
.st-d-head { display: flex; gap: 12px; align-items: center; margin-bottom: 10px; }
.st-d-icon {
  flex: none; width: 54px; height: 54px; display: grid; place-items: center;
  background: radial-gradient(circle at 50% 42%, rgba(var(--cls-rgb), .26), #0a0911 72%);
  box-shadow: inset 0 0 0 1px #2d2943;
}
.st-d-icon canvas { image-rendering: pixelated; display: block; }
.st-d-kind { font-size: 11px; color: var(--ink-faint); margin-top: 2px; }
.st-d-rank { display: flex; align-items: center; gap: 10px; font-size: 11px; color: var(--ink-faint); margin-bottom: 10px; font-variant-numeric: tabular-nums; }
.st-d-rank b { color: var(--ink); }
.st-d-rank .st-pips { margin: 0 0 0 auto; }
.st-d-now { color: var(--ink); font-size: 12.5px; }
.st-d-now.none { color: var(--ink-dim); }
/* What the next rank changes, in the same sentence: the number now, faint,
   and the next one in gold. */
.st-d-now b { color: var(--gold); }
.st-d-now .was { color: var(--ink-faint); margin-right: 2px; }
.st-d-next {
  margin-top: 10px; padding: 8px 10px; background: rgba(224, 179, 82, .05);
  border-left: 2px solid var(--gold-dim);
}
.st-d-next h4 { margin: 0 0 3px; color: var(--gold-dim); }
.st-d-act { display: block; width: 100%; margin-top: 12px; }
.st-d-act:not(:disabled) {
  background: linear-gradient(#e2b45c, #b0801f 58%, #8d611a); border-color: #241804; color: #1b1408;
  box-shadow: inset 0 1px 0 #ffe6a8, inset 0 0 0 1px #6f4d12, 0 3px 0 #4a3209; font-weight: 800;
}
.st-d-act:not(:disabled):hover { border-color: #241804; }
.st-d-warn { font-size: 11px; color: #d9b98a; margin-top: 8px; line-height: 1.45; text-align: center; }
.st-d-gate {
  margin-top: 12px; padding: 6px 10px; font-size: 11.5px;
  background: rgba(0, 0, 0, .3); box-shadow: inset 0 0 0 1px #2a2638;
}

/* A skill's two forks, under it: the rank each opens at and its options by
   name — boxed while one can be taken, gold once it is, struck through for
   the side given up. What an option does shows under them. */
.st-forks { margin-top: 2px; }
.st-fork h4 { display: flex; align-items: center; gap: 7px; margin-bottom: 6px; }
.st-fork h4::before { content: ''; width: 6px; height: 6px; transform: rotate(45deg); background: var(--gold-dim); }
.st-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.st-pill {
  min-width: 0; padding: 7px 6px; font-family: var(--font); font-size: 11.5px; font-weight: 600; line-height: 1.2; text-align: center;
  color: var(--ink-dim); background: #0f0d17; border: 0; border-radius: 0; box-shadow: inset 0 0 0 1px #2d2943;
  transition: box-shadow .12s, color .12s, background .12s;
}
.st-pill:hover { color: var(--ink); box-shadow: inset 0 0 0 1px var(--edge-lit); }
.st-pill.open, .st-pill.shut { color: var(--ink-faint); background: none; }
.st-pill.due { color: var(--ink); box-shadow: inset 0 0 0 1px #4d4766; }
.st-pill.ready { color: var(--ink); box-shadow: inset 0 0 0 1px var(--gold-dim); animation: st-glow 1.6s ease-in-out infinite; }
.st-pill.own { color: #1b1408; background: linear-gradient(#e2b45c, #b88622); box-shadow: inset 0 1px 0 #ffe6a8, 0 0 12px rgba(224, 179, 82, .3); }
/* The road not taken stays visible — a fork you cannot see both halves of is
   not a decision you can remember making. */
.st-pill.lost { color: #4a4560; background: none; text-decoration: line-through; text-decoration-color: rgba(107, 102, 128, .6); }
.st-pill.sel { color: var(--ink); background: rgba(224, 179, 82, .16); box-shadow: inset 0 0 0 2px var(--gold); animation: none; }
@keyframes st-glow { 50% { box-shadow: inset 0 0 0 1px var(--gold), 0 0 10px rgba(224, 179, 82, .3); } }
.st-detail .st-says { margin-top: 7px; font-size: 11.5px; color: var(--ink); }

/* The slots a learned active can go on, laid out as the bar has them. */
.st-d-keys { margin-top: 2px; }
.st-keyrow { display: flex; gap: 5px; margin-top: 4px; }
.st-key {
  position: relative; flex: 1 1 0; min-width: 0; height: 40px; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  background: #0f0d17; border: 0; border-radius: 0; box-shadow: inset 0 0 0 1px #2d2943;
}
.st-key:hover { box-shadow: inset 0 0 0 1px var(--gold-dim); }
.st-key.on { background: rgba(224, 179, 82, .12); box-shadow: inset 0 0 0 1px var(--gold); cursor: default; }
.st-key.lmb { cursor: default; opacity: .6; margin-right: 4px; }
.st-key kbd {
  position: absolute; left: 2px; top: 2px; min-width: 11px; padding: 0 2px;
  font-size: 9px; line-height: 12px; color: var(--ink-dim); background: none; border: 0; box-shadow: none;
}
.st-key.on kbd { color: var(--gold); }
.st-key kbd .mouse-glyph { display: block; width: 8px; height: 11px; margin-top: 1px; }
.st-key-on canvas { display: block; image-rendering: pixelated; margin-top: 6px; }

/* A short or narrow screen (a phone on its side): everything a size down,
   the tree too (TREE_SIZES.small), beside the pane. */
@media (max-height: 600px), (max-width: 760px) {
  #skilltree { padding: 8px; }
  .st-head { padding: 4px 8px 4px 10px; gap: 8px; }
  .st-who { font-size: 12px; }
  .st-points b { font-size: 18px; }
  .st-close { width: 28px; height: 28px; margin-left: 4px; }
  .st-node, .st-icon { width: 40px; }
  .st-icon { height: 40px; }
  .st-card { gap: 4px; }
  .st-icon kbd { font-size: 9px; height: 12px; line-height: 12px; min-width: 13px; padding: 0 2px; left: -5px; top: -5px; }
  .st-icon em { font-size: 9px; line-height: 11px; padding: 0 3px; right: -5px; bottom: -5px; }
  .st-nm { font-size: 10px; line-height: 12px; }
  .st-fks { top: 12px; gap: 6px; }
  .st-fk { gap: 3px; height: 8px; }
  .st-fk::before { width: 7px; height: 2px; margin-right: 1px; }
  .st-fk b { width: 7px; height: 7px; }
  .st-node.cap .st-icon::before { inset: -2px; }
  .st-node.cap .st-icon em { bottom: -16px; }
  .st-node.cap .st-nm { margin-top: 15px; }
  .st-lvmark { min-width: 22px; padding: 2px 3px; font-size: 9.5px; line-height: 10px; }
  .st-lvmark small { font-size: 7px; line-height: 8px; }
  .st-pips { gap: 2px; }
  .st-pips i { width: 4px; height: 7px; }
  .st-pips b { width: 5px; height: 5px; margin: 0 2px; }
  .st-plus { width: 18px; height: 18px; font-size: 13px; right: -8px; top: -8px; }
  .st-side { width: 260px; }
  .st-detail { padding: 10px 12px 12px; font-size: 11.5px; line-height: 1.4; }
  .st-detail h3 { font-size: 13.5px; }
  .st-detail h4 { margin-top: 10px; }
  .st-d-head { gap: 8px; margin-bottom: 6px; }
  .st-d-icon { width: 38px; height: 38px; }
  .st-d-now { font-size: 11.5px; }
  .st-d-rank { margin-bottom: 6px; }
  .st-d-act { padding: 6px 10px; margin-top: 8px; }
  .st-pill { padding: 5px 4px; font-size: 10.5px; }
  .st-key { height: 32px; }
  .st-key-on canvas { margin-top: 4px; }
  .st-side-foot { padding: 6px 12px 8px; }
}
/* Shorter still, a phone on its side: the portrait goes, and the names on
   the tree, which the pane says (TREE_SIZES.tiny), so all of it is in sight. */
@media (max-height: 420px) {
  .st-grid .st-nm, .st-portrait { display: none; }
}
/* Narrow: the pane goes under the tree and the whole window scrolls. */
@media (max-width: 600px) {
  #skilltree { place-items: start center; }
  .st-box { max-height: none; }
  .st-main { flex-direction: column; }
  .st-grid { overflow: visible; }
  .st-side { width: auto; border-left: 0; border-top: 1px solid var(--edge); contain: none; }
  .st-detail { overflow: visible; }
  .st-points span { display: none; }
}

/* ------------------------------------------------------------ skill paths ---
   A class on skill paths has the window the game designer drew for them
   (skillpaths.js), in the same frame: its four paths as tabs, the open one's
   name, line, trick and rank over its tree, and the pane beside it. Each
   path has its own colour (--p); gold is still what you can spend on, and
   grey what is out of reach. */
.pt-body { display: contents; }

.pt-tabs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; flex: none; padding: 8px 10px 0; }
.pt-tab {
  --p: var(--cls);
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto;
  column-gap: 9px; align-items: center; text-align: left; min-width: 0;
  padding: 6px 10px 5px; border-radius: 0;
  background: #100e18; border: 1px solid var(--edge); border-bottom: 3px solid var(--edge);
  box-shadow: none;
}
.pt-tab:hover { border-color: var(--edge-lit); border-bottom-color: var(--edge-lit); }
.pt-em { grid-row: span 2; display: grid; place-items: center; width: 32px; height: 32px; opacity: .55; }
.pt-em canvas { display: block; image-rendering: pixelated; }
.pt-tn { font-size: 14px; font-weight: 700; color: var(--ink-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; letter-spacing: .02em; }
.pt-ts { font-size: 11px; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.pt-tab.on { background: #191626; border-color: var(--p); border-bottom-color: var(--p); }
.pt-tab.on .pt-em { opacity: 1; }
.pt-tab.on .pt-tn { color: var(--p); }
.pt-tab.on .pt-ts { color: var(--ink-dim); }
.pt-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--gold); margin-left: 6px; vertical-align: 1px; box-shadow: 0 0 8px var(--gold); }

/* The open path: its head over its tree and the pane. */
.pt-stage {
  --p: var(--cls);
  display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
  margin: 0 10px 10px; border: 1px solid var(--edge); border-top: 2px solid var(--p);
  background: radial-gradient(70% 50% at 30% 0%, rgba(var(--p-rgb), .07), transparent 70%);
}
.pt-head {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 420px); column-gap: 18px;
  align-items: start; flex: none; padding: 10px 14px 10px; border-bottom: 1px solid var(--edge);
}
.pt-ptext { min-width: 0; }
.pt-head h2 { margin: 0; font-size: 21px; font-weight: 800; line-height: 1.15; color: var(--p); letter-spacing: .02em; }
.pt-line { margin: 2px 0 0; font-style: italic; font-size: 12.5px; color: var(--ink-dim); }
.pt-trick { margin: 5px 0 0; font-size: 12px; line-height: 1.4; color: var(--ink); max-width: 64ch; }
.pt-trick b { color: var(--p); }
.pt-rankbox { display: grid; gap: 6px; min-width: 0; padding-top: 3px; }
.pt-rankrow { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; }
.pt-rk { font-size: 14px; font-weight: 700; color: var(--ink); }
.pt-rk em { font-style: normal; color: var(--p); }
.pt-nx { font-size: 11px; color: var(--ink-faint); }
.pt-segs { display: grid; grid-template-columns: repeat(10, 1fr); gap: 3px; }
.pt-segs i { height: 7px; background: #221f30; position: relative; overflow: hidden; }
.pt-segs i.full { background: var(--p); box-shadow: 0 0 8px rgba(var(--p-rgb), .45); }
.pt-segs i.part::after { content: ''; position: absolute; inset: 0 auto 0 0; width: var(--w); background: rgba(var(--p-rgb), .55); }
.pt-segs.flash { animation: pt-segflash 1.1s ease-out; }
@keyframes pt-segflash { 0% { filter: brightness(2.4); } 100% { filter: none; } }
.pt-looks { display: flex; flex-wrap: wrap; gap: 5px; }
.pt-looks span { font-size: 11px; line-height: 1.3; padding: 1px 8px; color: var(--ink-faint); box-shadow: inset 0 0 0 1px var(--edge); }
.pt-looks span b { margin-right: 4px; }
.pt-looks span.got { color: var(--ink); background: rgba(var(--p-rgb), .12); box-shadow: inset 0 0 0 1px var(--p); }

.pt-main { border: 0; }
.pt-grid { display: block; padding: 0 6px; }
.pt-tree { position: relative; width: 100%; }
.pt-lines { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.pt-band { position: absolute; left: 0; right: 0; background: rgba(255, 255, 255, .022); border-top: 1px solid rgba(255, 255, 255, .03); }
.pt-rail {
  position: absolute; transform: translate(-50%, -50%); text-align: center;
  font-size: 11px; font-weight: 800; line-height: 1.05; color: var(--ink-faint); font-variant-numeric: tabular-nums;
}
.pt-rail small { display: block; font-size: 8px; letter-spacing: .14em; opacity: .8; }
.pt-rail.on { color: var(--p); }

/* The lines: dark from a skill with no point; dashed in the path's colour
   while only the level is missing; dull gold with nothing but a point to
   spend; gold into one you can take now; the path's colour into one you
   have. Dotted into a hidden one. */
.pt-edge { fill: none; stroke-linecap: round; transition: stroke .15s; }
.pt-edge.shut { stroke: #272335; stroke-width: 2.5; }
.pt-edge.hid { stroke: #2f2b40; stroke-width: 2; stroke-dasharray: 2 5; }
.pt-edge.wait { stroke: rgba(var(--p-rgb), .45); stroke-width: 2.5; stroke-dasharray: 5 5; }
.pt-edge.open { stroke: var(--gold-dim); stroke-width: 3; }
.pt-edge.ready { stroke: var(--gold); stroke-width: 3; }
.pt-edge.own { stroke: var(--p); stroke-width: 3.2; }
.pt-glow { fill: none; stroke-width: 10; stroke-linecap: round; opacity: .13; }
.pt-glow.ready { stroke: var(--gold); }
.pt-glow.own { stroke: var(--p); }
.pt-flashline {
  fill: none; stroke: #fff; stroke-width: 3.2; stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 100;
  animation: pt-draw .75s ease-out forwards, pt-fadeout .5s .75s ease-in forwards; filter: drop-shadow(0 0 4px var(--p));
}
@keyframes pt-draw { to { stroke-dashoffset: 0; } }
@keyframes pt-fadeout { to { opacity: 0; } }

/* A skill: its tile, the key it is cast with on one corner and its points on
   the other, the level it opens at over it while it waits. */
.pt-tile {
  position: absolute; display: grid; place-items: center; padding: 0; border-radius: 0;
  transform: translate(-50%, -50%);
  background: linear-gradient(#17141f, #0e0c15); border: 2px solid var(--frame);
  box-shadow: inset 0 0 0 1px #2a2640; transition: box-shadow .15s;
}
.pt-tile:hover { border-color: var(--frame); box-shadow: inset 0 0 0 1px var(--edge-lit); }
.pt-ic { display: grid; place-items: center; }
.pt-ic canvas { display: block; image-rendering: pixelated; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .6)); }
.pt-ltr { font-size: 18px; font-weight: 800; color: var(--ink-faint); line-height: 1; }
.pt-tile .pt-rk, .pt-tile .pt-lv, .pt-tile kbd {
  position: absolute; z-index: 1; font-style: normal; font-size: 10.5px; font-weight: 800; line-height: 13px;
  padding: 0 4px; white-space: nowrap; background: #0a0911; color: var(--ink-dim);
  box-shadow: inset 0 0 0 1px #2d2943; border: 0; border-radius: 0; font-variant-numeric: tabular-nums;
}
.pt-tile .pt-rk { right: -8px; top: -8px; }
.pt-tile .pt-lv { left: 50%; top: -9px; transform: translateX(-50%); color: var(--ink-faint); }
/* The key it is on, at its foot: the rank's badge across the top would cover it on a small tile. */
.pt-tile kbd { left: -7px; bottom: -7px; min-width: 15px; text-align: center; color: var(--ink); box-shadow: inset 0 0 0 1px #3b3553; }
.pt-tile kbd .mouse-glyph { display: block; width: 8px; height: 11px; margin: 1px auto; }
.pt-tile.cap { border-radius: 50%; }
.pt-tile.shut .pt-ic, .pt-tile.shut .pt-ltr { opacity: .4; }
.pt-tile.shut .pt-ic canvas { filter: grayscale(1) brightness(.5); }
.pt-tile.wait { border: 2px dashed rgba(var(--p-rgb), .6); }
.pt-tile.wait .pt-ic canvas { filter: grayscale(.85) brightness(.6); }
.pt-tile.wait .pt-lv { color: var(--p); box-shadow: inset 0 0 0 1px rgba(var(--p-rgb), .5); }
.pt-tile.open { border-color: var(--gold-dim); }
.pt-tile.open .pt-ic canvas { filter: grayscale(.6) brightness(.75); }
.pt-tile.can { border-color: var(--gold); box-shadow: 0 0 16px rgba(224, 179, 82, .28), inset 0 0 0 1px rgba(224, 179, 82, .25); }
.pt-tile.can .pt-ltr { color: var(--gold); }
.pt-tile.own { border-color: var(--p); background: linear-gradient(rgba(var(--p-rgb), .16), #0e0c15); box-shadow: 0 0 14px rgba(var(--p-rgb), .25); }
.pt-tile.own .pt-ltr { color: var(--p); }
.pt-tile.own .pt-rk { color: var(--p); box-shadow: inset 0 0 0 1px rgba(var(--p-rgb), .6); }
.pt-tile.own.can { box-shadow: 0 0 0 2px rgba(224, 179, 82, .55), 0 0 16px rgba(224, 179, 82, .22); }
.pt-tile.own.can .pt-rk { color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold-dim); }
/* Every point in it: a gold rim, and a shine going over it. */
.pt-tile.max { border: 2px solid var(--gold); box-shadow: 0 0 18px rgba(224, 179, 82, .4), inset 0 0 12px rgba(224, 179, 82, .2); }
.pt-tile.max .pt-rk { color: #120e04; background: var(--gold); box-shadow: none; }
.pt-tile.max::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 236, 170, .35) 50%, transparent 65%);
  background-size: 260% 100%; animation: pt-shimmer 3.2s linear infinite;
}
@keyframes pt-shimmer { from { background-position: 130% 0; } to { background-position: -130% 0; } }
/* Its page not found yet: a question mark. */
.pt-tile.hid { border: 2px dashed var(--edge-lit); background: repeating-linear-gradient(135deg, #0f0d16 0 6px, #13111b 6px 12px); box-shadow: none; }
.pt-q { font-size: 22px; font-weight: 800; color: var(--ink-faint); line-height: 1; }
.pt-tile.sel { outline: 2px solid var(--ink); outline-offset: 4px; }
.pt-tile:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
/* Just opened by a level: pulses until looked at. */
.pt-tile.fresh { animation: pt-fresh 1.6s ease-in-out infinite; }
@keyframes pt-fresh { 0%, 100% { box-shadow: 0 0 6px rgba(224, 179, 82, .25); } 50% { box-shadow: 0 0 22px rgba(224, 179, 82, .75); } }
/* A point the server has taken; a page found, the tile turning over. */
.pt-tile.pop { animation: pt-pop .45s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes pt-pop { 0% { transform: translate(-50%, -50%) scale(1); } 40% { transform: translate(-50%, -50%) scale(1.18); } 100% { transform: translate(-50%, -50%) scale(1); } }
.pt-tile.flip { animation: pt-flip .7s ease-in-out; }
@keyframes pt-flip { 0% { transform: translate(-50%, -50%) rotateY(0); } 50% { transform: translate(-50%, -50%) rotateY(90deg); } 100% { transform: translate(-50%, -50%) rotateY(0); } }

/* Its two choices under it, as diamonds: gold while one can be taken, the
   path's colour once taken. */
.pt-forks { position: absolute; display: flex; gap: 6px; transform: translate(-50%, 0); pointer-events: none; }
.pt-forks i { width: 9px; height: 9px; transform: rotate(45deg); box-shadow: inset 0 0 0 1.5px #3a3550; background: #0a0911; }
.pt-forks i.can { background: rgba(224, 179, 82, .35); box-shadow: inset 0 0 0 1.5px var(--gold), 0 0 8px rgba(224, 179, 82, .6); }
.pt-forks i.got { background: var(--p); box-shadow: none; }

.pt-name {
  position: absolute; transform: translateX(-50%); text-align: center; pointer-events: none;
  font-size: 12px; font-weight: 600; line-height: 15px; color: var(--ink-faint);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pt-tree[data-names="1"] .pt-name { -webkit-line-clamp: 1; }
.pt-name.gone { width: 0; height: 0; }
.pt-name.own { color: var(--ink); }
.pt-name.can, .pt-name.open { color: var(--ink-dim); }
.pt-name.hid { font-style: italic; }
.pt-name.cap { color: var(--gold-dim); }
.pt-name.cap.own { color: var(--gold); }

/* The pane: the skill you are on. */
.pt-side { background: rgba(0, 0, 0, .22); }
.pt-pane { --p: var(--cls); display: grid; gap: 10px; align-content: start; }
.pt-ptop { display: flex; gap: 12px; align-items: center; }
.pt-pic {
  flex: none; width: 48px; height: 48px; display: grid; place-items: center;
  border: 2px solid var(--p); background: linear-gradient(rgba(var(--p-rgb), .18), #0e0c15);
}
.pt-pic.cap { border-radius: 50%; }
.pt-pic.max { border-color: var(--gold); box-shadow: 0 0 12px rgba(224, 179, 82, .35); }
.pt-pic canvas { display: block; image-rendering: pixelated; }
.pt-pane h3 { margin: 0; font-size: 15px; color: var(--ink); line-height: 1.2; }
.pt-sub { font-size: 11px; color: var(--ink-faint); margin-top: 2px; }
.pt-sub b { color: var(--p); }
.pt-what { color: var(--ink); font-size: 12.5px; }
.pt-word { color: var(--ink-dim); font-size: 11.5px; font-style: italic; margin-top: -4px; }
.pt-nums { display: grid; gap: 5px; font-size: 12px; line-height: 1.4; color: var(--ink-dim); background: rgba(0, 0, 0, .25); box-shadow: inset 0 0 0 1px var(--edge); padding: 8px 10px; }
.pt-meta { font-size: 11px; color: var(--ink-faint); }
.pt-meta b { color: var(--ink-dim); }
.pt-nums p b { color: var(--p); }
.pt-nums p.now { color: var(--ink); }
.pt-pips { display: flex; gap: 3px; align-items: center; }
.pt-pips i { flex: 1 1 0; max-width: 18px; height: 6px; background: #221f30; }
.pt-pips i.on { background: var(--p); }
.pt-pips i.mk { height: 10px; }
.pt-gate { font-size: 12px; color: var(--ink-dim); border-left: 2px solid var(--gold-dim); padding: 2px 0 2px 9px; }
.pt-gate.warm { border-left-color: var(--gold); color: var(--ink); }
/* Its button at the foot, beside the refund, in sight however long the pane. */
.pt-foot { gap: 8px; align-items: center; }
.pt-act { flex: 1 1 auto; min-width: 0; }
.pt-act .st-d-act { margin-top: 0; }
.pt-foot .st-respec { flex: none; }
.pt-choices { display: grid; gap: 10px; }
.pt-choice h4 { margin: 0 0 5px; }
.pt-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.pt-opt {
  min-width: 0; text-align: left; padding: 7px 8px; border-radius: 0;
  font-size: 11.5px; line-height: 1.35; color: var(--ink-dim);
  background: #0f0d17; border: 0; box-shadow: inset 0 0 0 1px #2d2943;
}
.pt-opt b { display: block; font-size: 12.5px; color: var(--ink); margin-bottom: 2px; }
.pt-opt:hover { border: 0; box-shadow: inset 0 0 0 1px var(--edge-lit); }
.pt-opt.can { box-shadow: inset 0 0 0 1px var(--gold-dim); animation: st-glow 1.6s ease-in-out infinite; }
.pt-opt.held { background: rgba(224, 179, 82, .14); box-shadow: inset 0 0 0 2px var(--gold); }
.pt-opt.got { background: rgba(var(--p-rgb), .16); box-shadow: inset 0 0 0 1px var(--p); }
.pt-opt.got b { color: var(--p); }
.pt-opt.lost { opacity: .4; }
.pt-opt:disabled { cursor: default; }
.pt-opt.got:disabled, .pt-opt.lost:disabled { opacity: 1; }
.pt-opt.lost:disabled { opacity: .4; }
.pt-choice .st-d-act { margin-top: 8px; }

/* Notes over the window for a moment: a rank's title, a choice, mastered, a page. */
.pt-toasts {
  position: absolute; left: 18px; bottom: 18px; z-index: 6; display: grid; gap: 8px;
  width: min(330px, calc(100% - 36px)); pointer-events: none;
}
.pt-toast {
  --p: var(--gold);
  padding: 8px 12px; background: rgba(14, 13, 21, .97); box-shadow: inset 0 0 0 1px var(--p), 0 8px 26px rgba(0, 0, 0, .6);
  animation: pt-tin .25s ease-out;
}
.pt-toast b { display: block; font-size: 14px; color: var(--p); }
.pt-toast span { font-size: 12.5px; color: var(--ink-dim); }
.pt-toast.out { animation: pt-tout .3s ease-in forwards; }
@keyframes pt-tin { from { opacity: 0; transform: translateY(-8px); } }
@keyframes pt-tout { to { opacity: 0; transform: translateY(-8px); } }

/* A short screen: the head to a line or two, the trick to one. */
@media (max-height: 760px) {
  .pt-tabs { padding-top: 6px; }
  .pt-tab { padding: 4px 8px 3px; }
  .pt-em { width: 24px; height: 24px; }
  .pt-head { padding: 7px 12px; }
  .pt-head h2 { font-size: 17px; }
  .pt-trick { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
  .pt-looks { display: none; }
}
@media (max-height: 600px), (max-width: 760px) {
  .pt-tabs { gap: 4px; padding: 5px 8px 0; }
  .pt-ts { display: none; }
  .pt-stage { margin: 0 8px 8px; }
  .pt-head { grid-template-columns: minmax(0, 1fr) minmax(160px, 300px); }
  .pt-line { display: none; }
  .pt-opts { grid-template-columns: 1fr; }
}
@media (max-height: 460px) {
  .pt-trick { display: none; }
}
/* Narrow: the tabs two and two, the rank under the name, the pane under the tree. */
@media (max-width: 600px) {
  .pt-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pt-ts { display: block; }
  .pt-head { grid-template-columns: minmax(0, 1fr); row-gap: 8px; }
  .pt-line { display: block; }
  .pt-trick { white-space: normal; }
  .pt-grid { padding: 0 2px; }
  .pt-toasts { position: fixed; top: 12px; right: 12px; left: auto; bottom: auto; width: min(300px, calc(100vw - 24px)); }
}
@media (prefers-reduced-motion: reduce) {
  .pt-tile, .pt-tile::after, .pt-segs, .pt-flashline, .pt-toast, .pt-opt { animation: none !important; transition: none !important; }
}

/* item tooltip */
#tooltip {
  position: fixed; z-index: 40; pointer-events: none;
  background: rgba(10, 9, 16, .97); border: 1px solid var(--edge);
  border-radius: 8px; padding: 10px 12px; width: 268px; box-shadow: var(--shadow);
}
#tooltip .t-name { font-weight: 700; font-size: 13px; margin-bottom: 2px; }
#tooltip .t-sub { font-size: 10px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 7px; }
#tooltip .t-main { font-size: 12px; color: var(--ink); margin-bottom: 6px; }
#tooltip .t-affix { font-size: 11px; color: #7fd3ff; line-height: 1.5; }
#tooltip .t-power { font-size: 11px; color: var(--legendary); margin-top: 7px; font-style: italic; line-height: 1.45; }
#tooltip .t-former {
  font-size: 10px; color: var(--ink-faint); margin-top: 8px;
  border-top: 1px solid #1e1c28; padding-top: 6px; line-height: 1.45; font-style: italic;
}
#tooltip .t-power.uniq { color: var(--uniqgold); }
/* Where a skill on the bar is cast from, and how to move it. */
#tooltip .t-slot { font-size: 10px; color: var(--gold); margin-top: 7px; line-height: 1.45; }
#tooltip .t-set {
  font-size: 10px; margin-top: 8px; border-top: 1px solid #1e1c28; padding-top: 6px; line-height: 1.5;
}
#tooltip .t-set b { color: var(--setgreen); font-size: 11px; display: block; margin-bottom: 3px; }
#tooltip .t-set .on { color: var(--setgreen); }
#tooltip .t-set .off { color: var(--ink-faint); }
#tooltip .t-locked { font-size: 11px; color: var(--bad); margin-top: 7px; }
/* The comparison block: what it replaces, then every stat that moves. */
#tooltip .t-cmp { font-size: 10px; color: var(--ink-faint); margin-top: 8px; border-top: 1px solid #1e1c28; padding-top: 6px; }
#tooltip .t-vs { margin-bottom: 5px; }
#tooltip .t-vs b { font-weight: 700; }
#tooltip .t-delta {
  display: grid; grid-template-columns: 1fr auto auto;
  column-gap: 8px; row-gap: 1px; align-items: baseline;
}
#tooltip .t-delta .n { color: var(--ink-dim); }
#tooltip .t-delta .d { font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; }
#tooltip .t-delta .d.up { color: var(--good); }
#tooltip .t-delta .d.down { color: var(--bad); }
/* The resulting total, so a delta is read against something. */
#tooltip .t-delta .t { color: var(--ink-faint); text-align: right; font-variant-numeric: tabular-nums; min-width: 34px; }
#tooltip .t-cmp-more { margin-top: 3px; font-style: italic; }
#tooltip .t-cmp-pow, #tooltip .t-cmp-set { margin-top: 5px; line-height: 1.4; }
#tooltip .t-cmp-pow.up, #tooltip .t-cmp-set.up { color: var(--setgreen); }
#tooltip .t-cmp-pow.down, #tooltip .t-cmp-set.down { color: var(--bad); }

/* modal (boons) */
.modal { position: absolute; inset: 0; display: grid; place-items: center; background: rgba(4, 4, 8, .72); z-index: 25; }
.modal-inner { text-align: center; }
.modal h2 { margin: 0 0 4px; font-size: 22px; letter-spacing: .06em; }
.modal .sub { color: var(--ink-dim); font-size: 13px; margin-bottom: 20px; }
.boon-row { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.boon-card {
  width: 190px; background: var(--panel-solid); border: 1px solid var(--edge);
  border-radius: 10px; padding: 16px; cursor: pointer; transition: transform .12s, border-color .12s;
}
.boon-card:hover { transform: translateY(-3px); border-color: var(--gold); }
.modal .skip { margin-top: 18px; color: var(--ink-faint); }
.boon-card h3 { margin: 0 0 6px; font-size: 15px; color: var(--gold); }
.boon-card p { margin: 0; font-size: 12px; color: var(--ink-dim); line-height: 1.45; }

/* downed */
#downed { position: absolute; inset: 0; display: grid; place-items: center; z-index: 15; pointer-events: none; }
#downed::before { content: ''; position: absolute; inset: 0; background: radial-gradient(circle, transparent 30%, rgba(90, 8, 8, .5)); }
.downed-inner { position: relative; text-align: center; }
.downed-inner h2 { margin: 0 0 6px; color: var(--bad); font-size: 30px; letter-spacing: .1em; }
.downed-inner p { margin: 0; color: var(--ink-dim); }
.downed-inner p b { color: var(--ink); }
/* What bleeding out will cost, under the bar: quieter than the way up. */
#downed-cost { margin-top: 10px; font-size: 12px; color: #e6a79e; letter-spacing: .03em; }
/* The self-revive bar. Filling it is the only thing you can do down there,
   so it needs to be visible from across the room. */
#downed-bar { margin: 10px auto 0; width: 180px; height: 6px; background: rgba(0,0,0,.55);
  border: 1px solid rgba(255,255,255,.18); }
#downed-bar > i { display: block; height: 100%; width: 0; background: var(--good); transition: width .1s linear; }

/* chat */
#chat { position: absolute; left: 10px; bottom: 116px; width: 340px; z-index: 6; }
#chat-lines { display: flex; flex-direction: column; gap: 2px; margin-bottom: 5px; }
.chat-line { font-size: 12px; text-shadow: 0 1px 2px #000; }
.chat-line b { color: var(--gold); }
#chat-input {
  width: 100%; padding: 6px 9px; background: rgba(10, 9, 16, .95);
  border: 1px solid var(--gold-dim); border-radius: 5px; color: var(--ink); font-size: 13px; font-family: var(--font);
}
#chat-input:focus { outline: none; }

#debug {
  position: absolute; top: 4px; left: 50%; transform: translateX(-50%);
  font-size: 10px; color: var(--ink-faint); z-index: 9; pointer-events: none;
  background: rgba(0,0,0,.4); padding: 2px 8px; border-radius: 4px;
}

/* connection banner */
#reconnect {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(4, 4, 8, .82); z-index: 60; text-align: center;
}

/* ------------------------------------------------------- small screens --- */
/* Phones and narrow windows: bigger touch targets, less chrome competing for
   space, and the log moved out of the way of the action bar. */
@media (max-width: 760px), (pointer: coarse) {
  .slot { width: 54px; height: 54px; }
  .slot .glyph { font-size: 22px; }
  #actionbar { gap: 6px; bottom: 8px; }
  /* The log has the bottom right to itself, beside the vitals rather than on
     them: they run to its edge, and it stops under the corner's column, which
     is 194 px of a phone's height with a dungeon's floor and the Sovereign's
     line in it. Over the vitals, its newest line sat on the health bar. */
  #log { width: 190px; max-height: min(74px, calc(100% - 270px)); bottom: 72px; font-size: 10px; }
  #chat { display: none; }
  /* Lift the vitals above the (taller) action bar instead of behind it, and
     stop them a tile and a half short of the middle, where you stand: across
     the whole width they lay over your feet and the ground in front of them. */
  #vitals { width: min(calc(100% - 226px), calc(50% - 58px)); bottom: 72px; }
  #vitals .bar { height: 14px; }
  #topright { transform: scale(.86); transform-origin: top right; }
  #party { transform: scale(.86); transform-origin: top left; }
  .cols { grid-template-columns: 1fr; }
  #tooltip { width: 200px; }
  .panel-head h2 { font-size: 13px; }
  .panel-tabs button { padding: 4px 8px; font-size: 11px; }
}

/* Portrait phones: the view is very tall and narrow, so nudge players to turn. */
@media (max-width: 560px) and (orientation: portrait) {
  #rotate-hint {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    background: rgba(10, 9, 16, .9); border: 1px solid var(--gold-dim); color: var(--gold);
    padding: 8px 16px; border-radius: 18px; font-size: 12px; z-index: 12; pointer-events: none;
    text-align: center;
  }
}
@media not all and (orientation: portrait) { #rotate-hint { display: none; } }
@media (min-width: 561px) { #rotate-hint { display: none; } }

@media (max-width: 520px) {
  /* The log used to be hidden here and the middle-of-the-screen pop-ups were
     all the feedback a phone got. The pop-ups are gone, so this is now the
     only place anything is said — shrink it rather than hide it. */
  #log { width: 190px; max-height: 76px; }
  .log-line { font-size: 10px; line-height: 1.25; }
  #title h1 { font-size: 42px; }
  .classes { grid-template-columns: 1fr 1fr; }
}

/* ------------------------------------------------------------ the map ---
   Where you have arrived and what you have found, across the top; and the
   world map on [M], which is the only way to see the whole of the Reach. */
#place-banner {
  top: 70px; left: 50%; transform: translate(-50%, -6px); text-align: center;
  opacity: 0; transition: opacity .35s, transform .35s, top .35s; white-space: nowrap;
  /* A pool of shade to stand in, so the names drawn in the world under it
     do not read as part of it. */
  padding: 8px 48px 10px;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, .55), rgba(0, 0, 0, .3) 45%, rgba(0, 0, 0, 0) 72%);
}
#place-banner.show { opacity: 1; transform: translate(-50%, 0); }
/* A boss's bar up over it (a fight, or the Sovereign walking near in Kell):
   it comes in under the bar, not over the bar's phase. */
#stage:has(#bossbar:not(.hidden)) #place-banner { top: 88px; }
#place-banner .pb-title {
  font-size: 22px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: #efe6cf; text-shadow: 0 2px 0 #000, 0 0 18px rgba(0, 0, 0, .85);
}
#place-banner .pb-sub {
  font-size: 12px; color: var(--ink-dim); letter-spacing: .08em; margin-top: 2px;
  text-shadow: 0 1px 0 #000;
}
#place-banner[data-tone="found"] .pb-title { color: var(--gold); }
/* The first time into a region, and a place on the Fellowship's trail: the
   name, and the story's line under it, big enough to read in the time it is
   up and kept to the middle of the screen, out from under the corner map. */
#place-banner[data-tone="story"] .pb-title { color: var(--gold); }
#place-banner[data-tone="arrive"] .pb-sub, #place-banner[data-tone="story"] .pb-sub {
  font-size: 14px; color: #e6dcc4; letter-spacing: .02em; margin: 4px auto 0;
  white-space: normal; width: max-content; max-width: min(84vw, 36em, calc(100vw - 304px));
}
/* The fog coming in: the colour of it, and a little further apart. */
#place-banner[data-tone="fog"] .pb-title { color: #c3d0cc; letter-spacing: .22em; }
#place-banner[data-tone="fog"] .pb-sub { color: #9aa6a3; font-style: italic; }
/* Bleeding out: the title in blood, and what it took under it. */
#place-banner[data-tone="death"] .pb-title { color: var(--bad); }
#place-banner[data-tone="death"] .pb-sub { color: #f0c2ba; font-size: 13px; }
/* A phone held upright (QA, 10-11): beside the corner map there is no room
   for a name, and the map covered the ends of the name and its line ("THE
   FIRST FI…"). There the banner comes in under the corner's column (its foot
   is 194 px down with a dungeon's floor and the Sovereign's line in it), bar
   or no bar, across the width; a name too long for it goes onto a second
   line, not off the edges. */
@media (max-width: 620px) and (orientation: portrait) {
  #place-banner, #stage:has(#bossbar:not(.hidden)) #place-banner { top: 200px; }
  #place-banner { width: calc(100% - 24px); padding: 8px 0 10px; white-space: normal; }
  #place-banner .pb-title { font-size: 19px; }
  #place-banner[data-tone="arrive"] .pb-sub, #place-banner[data-tone="story"] .pb-sub { max-width: min(84vw, 36em); }
}

#worldmap {
  position: absolute; inset: 0; z-index: 18; pointer-events: auto;
  display: flex; flex-direction: column; gap: 6px; padding: 10px 14px 8px;
  background: rgba(4, 4, 8, .86);
}
/* What it covers shows through it, dimmed: all but the corner's place name
   and minimap, whose name would read in pieces round the head's "Story". */
#stage:has(#worldmap:not(.hidden)) #topright { visibility: hidden; }
.wm-head {
  display: flex; align-items: center; gap: 12px;
  font-size: 13px; font-weight: 700; letter-spacing: .06em; text-shadow: 0 2px 0 #000;
}
.wm-head .wm-close { margin-left: auto; }
/* What this character knows of the story, over the map (storypage.js). */
.wm-head .wm-story {
  margin-left: auto; padding: 4px 12px; font-size: 12px; font-weight: 600; letter-spacing: .04em;
  border-radius: 0; border: 2px solid #0a0811; background: #1a1726; color: var(--ink-dim);
  box-shadow: inset 0 0 0 1px #37324c, 0 2px 0 #08060d;
}
.wm-head .wm-story:hover { border-color: #0a0811; color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold-dim), 0 2px 0 #08060d; }
.wm-head .wm-story:active { transform: translateY(2px); box-shadow: inset 0 0 0 1px #37324c; }
.wm-head .wm-story + .wm-close { margin-left: 0; }
@media (pointer: coarse) { .wm-head .wm-story { padding: 7px 14px; } }
.wm-frame {
  position: relative; flex: 1; min-height: 0; overflow: hidden;
  border: 1px solid var(--edge); border-radius: 6px; background: #0b0a12; box-shadow: var(--shadow);
}
/* Dragged and pinched by the map itself, not scrolled or zoomed by the page. */
#worldmap-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; cursor: grab; touch-action: none; }
#worldmap-canvas:active { cursor: grabbing; }
#worldmap-tip {
  position: absolute; pointer-events: none; white-space: nowrap;
  background: var(--panel-solid); border: 1px solid var(--edge-lit); border-radius: 5px;
  padding: 5px 8px; font-size: 11px; color: var(--ink-dim); box-shadow: var(--shadow);
}
#worldmap-tip b { display: block; color: var(--ink); font-size: 12px; margin-bottom: 1px; }
#worldmap-tip i { display: block; color: #7fd4ff; font-style: normal; margin-top: 2px; }
/* A place on the Fellowship's trail: its line again, as on its banner. */
#worldmap-tip em { display: block; color: var(--ink); white-space: normal; max-width: 30ch; margin-top: 3px; }

/* The corner map is a button: it opens the world map, for anyone without a keyboard. */
#minimap { pointer-events: auto; cursor: pointer; }

/* ------------------------------------------------------------ the story ---
   [J], or "Story" on the world map: what this character knows of the
   Fellowship so far, a chapter a region in walking order (storypage.js).
   Framed like the skill tree. Only its lines, and "…" for what is not found
   yet; nothing to press but "Watch it again". */
#storypage {
  position: absolute; inset: 0; z-index: 20; pointer-events: auto;
  display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr);
  place-items: center; padding: 12px;
  background: rgba(4, 4, 8, .62); overflow: auto;
}
.sp-box {
  --frame: #0a0811; --frame-lit: #3b3553;
  position: relative; width: min(560px, 100%); max-height: 100%;
  display: flex; flex-direction: column;
  background: linear-gradient(#141220, #0c0a14);
  border: 2px solid var(--frame);
  box-shadow: inset 0 0 0 1px var(--frame-lit), 0 18px 50px rgba(0, 0, 0, .65);
}
.sp-head {
  display: flex; align-items: center; gap: 12px; flex: none;
  padding: 8px 10px 8px 18px; border-bottom: 1px solid var(--edge);
}
.sp-heading { margin: 0 auto 0 0; font-size: 16px; letter-spacing: .06em; text-transform: uppercase; }
.sp-body { overflow-y: auto; padding: 4px 22px 16px; overscroll-behavior: contain; }
.sp-chapter { padding: 14px 0 12px; border-top: 1px solid var(--edge); }
.sp-chapter:first-child { border-top: none; }
.sp-where { font-size: 10px; text-transform: uppercase; letter-spacing: .16em; color: var(--ink-faint); margin-bottom: 3px; }
.sp-title { margin: 0 0 5px; font-size: 15px; color: var(--gold); letter-spacing: .02em; }
.sp-arrive { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ink); }
.sp-replay { margin-top: 8px; }
.sp-entries {
  list-style: none; margin: 10px 0 0; padding: 0 0 0 12px;
  border-left: 2px solid #262238; display: flex; flex-direction: column; gap: 7px;
}
.sp-entries li { font-size: 13px; line-height: 1.45; }
.sp-name { display: block; color: var(--ink); font-weight: 600; }
.sp-line { display: block; color: var(--ink-dim); }
/* The Fellowship in their gear's colour: what they left is legendary. */
.sp-fallen .sp-name { color: var(--legendary); }
.sp-unfound { color: var(--ink-faint); letter-spacing: .12em; }
.sp-unreached { padding: 10px 0 8px; }
.sp-unreached .sp-unfound { margin: 0; font-size: 15px; }
@media (max-height: 600px), (max-width: 760px) {
  #storypage { padding: 6px; }
  .sp-head { padding: 4px 8px 4px 14px; }
  .sp-body { padding: 2px 16px 12px; }
}

/* ---------------------------------------------------------------- the menu ---
   [Esc], once there is nothing else open to shut. Framed like the front door
   and the skill tree — square corners, hard keylines, gold brackets — because
   it is the front door again, from the inside: the account, and the way out.
   The world goes on behind it, dimmed rather than hidden. */
.tr-head { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
#menu-btn, .hud-btn {
  pointer-events: auto; flex: none;
  width: 22px; height: 22px; padding: 0;
  display: grid; place-items: center;
  border-radius: 0; border: 2px solid #0a0811;
  background: #1a1726; box-shadow: inset 0 0 0 1px #37324c, 0 2px 0 #08060d;
}
#menu-btn:hover, .hud-btn:hover { border-color: #0a0811; box-shadow: inset 0 0 0 1px var(--gold-dim), 0 2px 0 #08060d; }
#menu-btn:active, .hud-btn:active { transform: translateY(2px); box-shadow: inset 0 0 0 1px #37324c; }
/* The bag and the skill tree, for a touch screen only: a keyboard has [I] and
   [K], and the corner stays the place name and the menu. */
.hud-btn { display: none; }
.hud-btn svg { display: block; width: 15px; height: 13px; fill: var(--ink-dim); shape-rendering: crispEdges; }
.hud-btn:hover svg, .hud-btn:active svg { fill: var(--gold); }
/* Three bars out of one: the middle bar is the element, the outer two its shadows. */
#menu-btn i {
  display: block; width: 10px; height: 2px; background: var(--ink-dim);
  box-shadow: 0 -4px 0 var(--ink-dim), 0 4px 0 var(--ink-dim);
}
#menu-btn:hover i { background: var(--gold); box-shadow: 0 -4px 0 var(--gold), 0 4px 0 var(--gold); }
/* A hammer in hand: the button puts it down, and is a window's cross for it. */
#menu-btn.armed i { display: none; }
#menu-btn.armed::before { content: '×'; font-size: 17px; line-height: 1; color: var(--ink-dim); }
#menu-btn.armed:hover::before { color: var(--gold); }
@media (pointer: coarse) {
  #menu-btn, .hud-btn { width: 34px; height: 34px; }
  .hud-btn { display: grid; }
  #menu-btn i { width: 14px; box-shadow: 0 -5px 0 var(--ink-dim), 0 5px 0 var(--ink-dim); }
}
/* With the two of them beside it, a phone under 620 px wide has the place name
   where a boss's name goes: while a boss bar is up, the boss's is the one shown. */
@media (pointer: coarse) and (max-width: 620px) {
  #stage:has(#bossbar:not(.hidden)) #zone-name { visibility: hidden; }
}

#escmenu {
  position: absolute; inset: 0; z-index: 30; pointer-events: auto;
  /* A definite row, so the box's max-height is the window's and the pane
     scrolls inside it rather than the box running off the bottom. */
  display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); place-items: center;
  padding: 16px; overflow: auto;
  background: rgba(4, 4, 8, .66);
}
.em-box {
  --frame: #0a0811; --frame-lit: #3b3553;
  position: relative; width: min(760px, 100%); max-height: 100%;
  /* As tall as the tallest pane (the account's), so going from one to the
     next changes what is in the box and not where the box is. */
  min-height: min(660px, 100%);
  display: flex; flex-direction: column;
  background:
    radial-gradient(60% 50% at 22% 0%, rgba(var(--cls-rgb), .10), transparent 72%),
    linear-gradient(#141220, #0c0a14);
  border: 2px solid var(--frame);
  box-shadow: inset 0 0 0 1px var(--frame-lit), 0 18px 50px rgba(0, 0, 0, .65);
  animation: pop .15s;
}
.em-box::before {
  content: ''; position: absolute; inset: -5px; pointer-events: none;
  border: 2px solid var(--gold-dim);
  --corner: linear-gradient(#000, #000) no-repeat;
  -webkit-mask:
    var(--corner) top left / 16px 16px, var(--corner) top right / 16px 16px,
    var(--corner) bottom left / 16px 16px, var(--corner) bottom right / 16px 16px;
  mask:
    var(--corner) top left / 16px 16px, var(--corner) top right / 16px 16px,
    var(--corner) bottom left / 16px 16px, var(--corner) bottom right / 16px 16px;
}

.em-head {
  display: flex; align-items: center; gap: 14px; flex: none;
  padding: 12px 18px; border-bottom: 1px solid var(--edge);
}
.em-portrait {
  flex: none; line-height: 0; padding: 3px 5px 0;
  background: radial-gradient(60% 55% at 50% 88%, rgba(var(--cls-rgb), .28) 0%, #0d0b15 74%);
  box-shadow: inset 0 0 0 1px #262238;
}
.em-portrait canvas { image-rendering: pixelated; display: block; }
.em-title { min-width: 0; }
.em-who { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.em-who b { font-size: 15px; color: var(--cls); letter-spacing: .01em; }
.em-who small { margin-left: 6px; font-size: 11px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .1em; }

.em-main { display: flex; flex: 1 1 auto; min-height: 0; }
.em-nav {
  flex: none; width: max-content; min-width: 220px; display: flex; flex-direction: column; gap: 7px;
  padding: 16px 14px 16px 18px; border-right: 1px solid #1f1c2c;
}
.em-gap { flex: 1 1 14px; min-height: 14px; }
/* The chunky square buttons of the front door, sinking into their shadow. */
.em-box button {
  border-radius: 0; border: 2px solid var(--frame);
  background: #1a1726; color: var(--ink);
  box-shadow: inset 0 0 0 1px #37324c, 0 3px 0 #08060d;
  padding: 9px 14px; font-size: 13px; font-weight: 600; text-align: left;
  transition: transform .06s, filter .12s;
}
.em-box button:hover { filter: brightness(1.15); border-color: var(--frame); }
.em-box button:active { transform: translateY(3px); box-shadow: inset 0 0 0 1px #37324c, 0 0 0 #08060d; }
.em-box button:focus-visible { outline: 1px solid var(--gold); outline-offset: 3px; }
.em-box button:disabled { opacity: .45; cursor: not-allowed; transform: none; filter: none; }
.em-nav button { white-space: nowrap; }
.em-nav button.sel {
  background: linear-gradient(#1d1730, #120e1d);
  box-shadow: inset 0 0 0 1px var(--gold), 0 0 0 1px rgba(224, 179, 82, .22), 0 3px 0 #08060d;
  color: var(--gold);
}
.em-box .em-resume, .em-box .em-go {
  background: linear-gradient(#e2b45c, #b0801f 58%, #8d611a);
  border-color: #241804; color: #1b1408; font-weight: 800;
  box-shadow: inset 0 1px 0 #ffe6a8, inset 0 0 0 1px #6f4d12, 0 3px 0 #4a3209;
  text-shadow: 0 1px 0 rgba(255, 233, 180, .5);
}
.em-box .em-resume:active, .em-box .em-go:active { box-shadow: inset 0 1px 0 #ffe6a8, inset 0 0 0 1px #6f4d12, 0 0 0 #4a3209; }
.em-resume { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.em-resume kbd { background: rgba(27, 20, 8, .18); border-color: rgba(27, 20, 8, .45); color: #1b1408; font-weight: 700; }
.em-box .em-stay { background: transparent; color: var(--ink-dim); }
.em-box .em-stay:hover { color: var(--ink); }

.em-pane { flex: 1 1 auto; min-width: 0; overflow-y: auto; padding: 16px 20px 18px; }
.em-pane h3 {
  margin: 0 0 14px; font-size: 11px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--gold);
}
.em-lede { margin: 0 0 14px; font-size: 12.5px; line-height: 1.6; color: var(--ink-dim); }
.em-lede b { color: var(--gold); }
.em-warn { color: #ffb08a; border-left: 3px solid #7d4a2c; padding-left: 9px; }

/* Settings: one per row, the name on the left and its control across. */
.em-row {
  display: grid; grid-template-columns: 150px minmax(0, 1fr) auto; align-items: center; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid #1c1a28; font-size: 13px;
}
.em-row > span { color: var(--ink); }
.em-row input[type="range"] { width: 100%; accent-color: var(--gold); }
.em-row > b { min-width: 28px; text-align: right; font-variant-numeric: tabular-nums; color: var(--gold); font-size: 13px; }
.em-row kbd { font-size: 10px; color: var(--ink-dim); }
.em-keypair { display: flex; gap: 3px; }
.em-check { cursor: pointer; }
/* A square to tick, cut like the fields: dark and keylined, gold inside when on. */
.em-check input {
  justify-self: start; margin: 0; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  width: 18px; height: 18px; display: grid; place-content: center;
  background: #0a0912; border: 2px solid var(--frame);
  box-shadow: inset 0 0 0 1px #2b2740, inset 0 2px 6px rgba(0, 0, 0, .7);
}
.em-check input::before {
  content: ''; width: 8px; height: 8px; background: var(--gold);
  box-shadow: 0 0 6px rgba(224, 179, 82, .45); transform: scale(0); transition: transform .08s;
}
.em-check input:checked::before { transform: scale(1); }
.em-check input:focus-visible { outline: 1px solid var(--gold); outline-offset: 3px; }
.em-check:hover input { box-shadow: inset 0 0 0 1px var(--gold-dim), inset 0 2px 6px rgba(0, 0, 0, .7); }
.em-zoom { display: flex; align-items: center; gap: 10px; }
.em-box .em-zoom button { padding: 2px 11px; font-size: 16px; line-height: 1.2; text-align: center; }
.em-zoom b { min-width: 30px; text-align: center; color: var(--gold); font-variant-numeric: tabular-nums; }

/* The account: two small forms, a field a row. */
.em-form { padding: 12px 0 14px; border-top: 1px solid #1c1a28; }
.em-form + .em-form { margin-top: 2px; }
.em-field { display: grid; grid-template-columns: 130px minmax(0, 1fr); align-items: center; gap: 12px; margin: 0 0 8px; }
.em-field > span { font-size: 11px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .12em; font-weight: 600; }
.em-field input {
  width: 100%; padding: 8px 10px; border-radius: 0;
  background: #0a0912; border: 2px solid var(--frame);
  box-shadow: inset 0 0 0 1px #2b2740, inset 0 2px 8px rgba(0, 0, 0, .7);
  color: var(--ink); font-size: 14px; font-family: var(--font);
}
.em-field input::placeholder { color: #57526b; font-size: 12.5px; }
.em-field input:focus {
  outline: none; border-color: var(--gold-dim);
  box-shadow: inset 0 0 0 1px var(--gold-dim), 0 0 0 2px rgba(224, 179, 82, .16);
}
.em-act { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.em-form .em-act { margin-left: 142px; margin-top: 4px; }
.em-said { font-size: 12px; color: var(--ink-dim); line-height: 1.45; }
/* A recovery code the menu just made, over the forms until Done. */
.em-code {
  display: grid; gap: 6px; justify-items: start;
  margin: 0 0 14px; padding: 12px 14px;
  background: rgba(0, 0, 0, .32);
  border: 2px solid var(--frame); box-shadow: inset 0 0 0 1px var(--gold-dim);
}
.em-box .em-code button { padding: 6px 14px; }
/* Delete account: the one button here that cannot be taken back, in red. */
.em-box .em-drop { color: #ff9d92; border-color: #7d322c; }
/* Google's own button, beside the form's once the form is right, for a
   change confirmed with Google or Google linked (client/js/google.js). */
.em-gslot { display: inline-flex; align-items: center; min-height: 40px; line-height: 0; }
.em-said.good { color: var(--good); }
.em-said.bad { color: #ff9d92; }
.em-pane > .em-said.bad { margin: 14px 0 0; border-left: 3px solid #7d322c; padding-left: 9px; }
.em-confirm { margin-top: 18px; }

/* Keys: the key, and what it does, in two columns. */
.em-keycols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 22px; }
.em-keys { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 7px 12px; align-items: baseline; align-content: start; }
.em-keys .k { display: flex; gap: 3px; justify-content: flex-end; white-space: nowrap; }
.em-keys .d { font-size: 12.5px; color: var(--ink-dim); line-height: 1.4; }

/* Short or narrow: the header gives up the portrait, the list of places runs
   across the top in two rows, and the pane has the rest to scroll in. */
@media (max-width: 640px), (max-height: 520px) {
  #escmenu { padding: 8px; }
  .em-head { padding: 8px 14px; }
  .em-portrait { display: none; }
  .em-main { flex-direction: column; min-height: 0; }
  .em-nav {
    width: auto; flex-direction: row; flex-wrap: wrap; gap: 6px;
    padding: 10px 12px; border-right: none; border-bottom: 1px solid #1f1c2c;
  }
  .em-gap { display: none; }
  .em-box .em-nav button { padding: 6px 10px; font-size: 12px; }
  .em-pane { padding: 12px 14px 14px; }
}
@media (max-width: 560px) {
  .em-row { grid-template-columns: 96px minmax(0, 1fr) auto; }
  .em-keycols { grid-template-columns: minmax(0, 1fr); gap: 7px; }
  .em-field { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .em-form .em-act { margin-left: 0; }
}
