/* ============================================================
   Nightfall — UI shell
   Canvas draws the world; everything here is chrome on top.
   ============================================================ */

:root {
  --bg: #07050c;
  --ink: #f2ecff;
  --dim: #a99cc4;
  --line: rgba(180, 150, 255, .18);
  --panel: rgba(18, 11, 30, .92);
  --blood: #e0345a;
  --blood-dark: #7d0f2b;
  --xp: #57d8ff;
  --gold: #ffd166;
  --violet: #a06bff;
  --radius: 14px;
  --font: "Trebuchet MS", "Segoe UI", Roboto, system-ui, -apple-system, sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  /* `100%` on a phone measures the viewport the browser *wishes* it had, with
     the address bar already gone — so the bottom of the HUD sat under it.
     `--vh` is the visual viewport, written by resize() every time that bar
     slides; `dvh` is the static fallback for anything that hasn't run JS yet. */
  height: 100dvh;
  height: var(--vh, 100dvh);
  overflow: hidden;
  /* It's a game. Dragging an item should never leave half the character sheet
     highlighted in blue behind it. */
  user-select: none;
  -webkit-user-select: none;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  touch-action: none;
}

#app {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100dvh;
  height: var(--vh, 100dvh);
  display: block;
}

#game {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  background: #07050c;
  touch-action: none;
}

.hidden { display: none !important; }

#vignette, #hurt {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}

#vignette {
  background: radial-gradient(ellipse at center,
    rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, .55) 78%, rgba(0, 0, 0, .88) 100%);
}

#hurt {
  background: var(--blood);
  opacity: 0;
  mix-blend-mode: screen;
  will-change: opacity;
}

/* ============================================================
   HUD
   ============================================================ */

#hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Landscape is the orientation this is played in, and that is the one where
     a notch eats a *side* rather than the top. */
  padding: calc(env(safe-area-inset-top, 0px) + 10px)
           calc(env(safe-area-inset-right, 0px) + 12px)
           calc(env(safe-area-inset-bottom, 0px) + 10px)
           calc(env(safe-area-inset-left, 0px) + 12px);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  font-variant-numeric: tabular-nums;
  z-index: 2;
}

.hud-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.hud-left { display: flex; align-items: center; gap: 8px; flex: 1 1 0; min-width: 0; max-width: 340px; }
.hud-center { text-align: center; flex: 0 0 auto; }
.hud-right { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex: 1 1 0; min-width: 0; }

.bar {
  position: relative;
  height: 16px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .55);
  border: 1px solid var(--line);
  overflow: hidden;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .6);
}

.bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 100%;
  border-radius: 999px;
  transition: width .12s linear;
}

.hp-bar { flex: 1 1 auto; min-width: 90px; }
.hp-bar .bar-fill { background: linear-gradient(180deg, #ff5c7a, var(--blood) 55%, var(--blood-dark)); }

/* Shield rides on top of the health bar rather than beside it, so one glance
   reads both. It's translucent so the health underneath stays legible. */
.shield-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(180,245,255,.85), rgba(87,216,255,.6));
  box-shadow: 0 0 10px rgba(87, 216, 255, .5);
  transition: width .12s linear;
}

.bar-label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-shadow: 0 1px 2px #000, 0 0 6px #000;
}

.lvl-chip {
  display: flex;
  align-items: baseline;
  gap: 3px;
  padding: 2px 9px;
  border-radius: 999px;
  background: rgba(87, 216, 255, .14);
  border: 1px solid rgba(87, 216, 255, .45);
  color: var(--xp);
  font-weight: 800;
  font-size: 14px;
  line-height: 1.3;
  white-space: nowrap;
}
.lvl-word { font-size: 9px; opacity: .8; letter-spacing: .1em; }
/* The room level rides in the same chip, dimmer: it's the one that resets. */
.lvl-word.room { margin-left: 5px; opacity: .55; }
.room-lv { color: var(--violet); font-size: 12px; }
.room-lv.maxed { color: var(--gold); font-size: 10px; letter-spacing: .08em; }

.timer {
  font-size: clamp(22px, 5vw, 34px);
  font-weight: 800;
  letter-spacing: .06em;
  line-height: 1;
  text-shadow: 0 2px 10px rgba(0, 0, 0, .9);
}

.wave {
  font-size: 10px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--dim);
  margin-top: 3px;
}

/* Nest counter — the one HUD line that tells you to go somewhere. */
.nests {
  display: inline-block;
  margin-top: 4px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #ffb37a;
  background: rgba(255, 122, 60, .13);
  border: 1px solid rgba(255, 122, 60, .42);
  animation: nestPulse 1.6s ease-in-out infinite;
}

@keyframes nestPulse {
  0%, 100% { box-shadow: 0 0 0 rgba(255, 122, 60, 0); }
  50%      { box-shadow: 0 0 14px rgba(255, 122, 60, .45); }
}

@media (prefers-reduced-motion: reduce) {
  .nests { animation: none; }
}

/* Room counter turns cyan the moment the doors are the objective. */
.wave.open { color: #8ff0ff; text-shadow: 0 0 12px rgba(143, 240, 255, .6); }

.frenzy { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 5px; }
.frenzy-k { font-size: 8px; letter-spacing: .18em; color: var(--dim); }
.frenzy-bar {
  width: 92px;
  height: 5px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .55);
  border: 1px solid var(--line);
  overflow: hidden;
}
.frenzy-bar i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, #a8324a, #ff5c7a); }
.frenzy.hot .frenzy-k { color: #ff5c7a; }
.frenzy.hot .frenzy-bar { border-color: rgba(255, 92, 122, .8); box-shadow: 0 0 12px rgba(255, 92, 122, .6); }
.frenzy.hot .frenzy-bar i { background: linear-gradient(90deg, #ff5c7a, #ffd166); }

.stat-v.coin { color: var(--gold); }

/* Blood moon tints the whole frame through the existing vignette layer. */
body.bloodmoon #vignette {
  box-shadow: inset 0 0 200px 30px rgba(160, 14, 44, .5);
  transition: box-shadow .6s ease;
}

.stat { display: flex; align-items: baseline; gap: 6px; line-height: 1.15; }
.stat-k { font-size: 9px; letter-spacing: .16em; color: var(--dim); }
.stat-v { font-size: clamp(13px, 2.6vw, 17px); font-weight: 800; }

/* boss */
.boss-wrap {
  position: absolute;
  left: 50%;
  top: calc(env(safe-area-inset-top, 0px) + 74px);
  transform: translateX(-50%);
  width: min(560px, 82vw);
  text-align: center;
}
.boss-name {
  font-size: 11px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #ffb3c2;
  margin-bottom: 4px;
  text-shadow: 0 1px 6px #000;
}
.boss-bar { height: 11px; }
.boss-bar .bar-fill { background: linear-gradient(180deg, #ff8fa3, #c31437 60%, #4a0616); }

/* bottom */
.hud-bottom { display: flex; flex-direction: column; align-items: flex-start; gap: 7px; }

/* The build sits in the bottom-left corner as rows of bare icons. Names and
   levels are reading you only ever do on a screen that has stopped, and the
   sheet is where you do it — mid-fight this is a glance at what you own, so
   it is icons, and it is capped at half the width so it can never crawl into
   the middle of the screen where the fight is. */
.loadout {
  display: flex;
  flex-flow: row wrap;
  align-items: flex-end;
  align-content: flex-end;
  max-width: 50%;
  gap: 4px;
}

/* Minimised everywhere, not only on a phone: a skill you own is a thing you
   check, not a thing you read, and thirty of them spelled out is a wall of
   text over the play area. The sheet has the names. */
.chip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 4px;
  min-width: 24px;
  border-radius: 8px;
  background: rgba(24, 14, 38, .8);
  border: 1px solid var(--line);
  font-size: 11px;
  font-weight: 700;
  line-height: 1.4;
  white-space: nowrap;
}
.chip .ic { font-style: normal; font-size: 14px; line-height: 1; }
.chip b { display: none; }
.chip .lv { display: none; color: var(--gold); font-size: 10px; }
.chip.max .lv { color: #7dffa8; }
/* One exception: the bag chip *is* its number — "you have loose gems" is the
   whole message, and the icon alone doesn't carry it. */
.chip.bagchip .lv { display: inline; margin-left: 3px; }
.chip.pass { opacity: .78; }
.chip.tal {
  padding: 3px 7px;
  border-color: rgba(255, 209, 102, .5);
  background: rgba(255, 209, 102, .1);
  color: var(--gold);
}
.chip.tal .ic { font-size: 12px; }
/* Loose items are a nudge to open the pause screen, so they read as a warning
   rather than as part of the build. */
.chip.bagchip {
  border-color: rgba(160, 107, 255, .5);
  background: rgba(160, 107, 255, .12);
}
.chip.bagchip .lv { color: var(--violet); }

/* Half the width, out of the corner the loadout lives in: the bar starts at
   the middle of the screen and fills toward the right edge. */
.xp-bar { height: 9px; width: 50%; align-self: flex-end; }
.xp-bar .bar-fill {
  background: linear-gradient(180deg, #a5edff, var(--xp) 60%, #1b7fa8);
  box-shadow: 0 0 12px rgba(87, 216, 255, .55);
}

.hud-buttons {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 8px);
  right: calc(env(safe-area-inset-right, 0px) + 12px);
  display: flex;
  gap: 6px;
  pointer-events: auto;
}

.icon-btn {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: rgba(18, 11, 30, .8);
  color: var(--ink);
  font-size: 13px;
  font-family: var(--font);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background .15s, transform .1s;
}
.icon-btn:hover { background: rgba(50, 30, 80, .9); }
.icon-btn:active { transform: scale(.94); }
.icon-btn.off { color: #6b5f85; }
.icon-btn.on { color: var(--xp); border-color: rgba(87, 216, 255, .45); }

/* Give the right-hand stats room to clear the pause/mute buttons. */
.hud-right { padding-right: 82px; }

/* ============================================================
   Overlay screens
   ============================================================ */

.overlay {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: block;
  pointer-events: none;
}

.screen {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 16px;
  background: radial-gradient(ellipse at center, rgba(10, 5, 20, .82), rgba(4, 2, 8, .96));
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  pointer-events: auto;
  overflow-y: auto;
  animation: fade .18s ease-out;
}

@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.panel {
  width: min(520px, 100%);
  max-height: 100%;
  padding: clamp(18px, 4vw, 30px);
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .75), inset 0 1px 0 rgba(255, 255, 255, .05);
  text-align: center;
}
.panel-wide { width: min(760px, 100%); }
.panel-sm { width: min(420px, 100%); }

.title {
  font-size: clamp(40px, 11vw, 76px);
  font-weight: 900;
  letter-spacing: .04em;
  line-height: .95;
  background: linear-gradient(180deg, #fff 10%, #ff87a3 55%, var(--blood) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 4px 18px rgba(224, 52, 90, .45));
}
.title span { display: inline; opacity: .92; }

.tagline {
  color: var(--dim);
  font-size: clamp(12px, 2.6vw, 15px);
  margin: 8px 0 20px;
  letter-spacing: .04em;
}

.h1 { font-size: clamp(24px, 6vw, 34px); font-weight: 800; letter-spacing: .04em; margin-bottom: 12px; }
.h1.dead { color: var(--blood); text-shadow: 0 0 26px rgba(224, 52, 90, .5); }
.h2 { font-size: 11px; letter-spacing: .2em; text-transform: uppercase; color: var(--dim); margin-bottom: 10px; }

.cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px;
  margin-top: 24px;
  text-align: left;
  border-top: 1px solid var(--line);
  padding-top: 20px;
}
.col { min-width: 0; }

.keys { list-style: none; font-size: 12px; color: var(--dim); line-height: 2.1; }
.keys em { font-style: normal; color: var(--ink); opacity: .85; }

kbd {
  display: inline-block;
  min-width: 20px;
  padding: 1px 5px;
  border-radius: 5px;
  background: rgba(255, 255, 255, .07);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  color: var(--ink);
  text-align: center;
}

.note { font-size: 11px; color: var(--dim); margin-top: 10px; line-height: 1.5; opacity: .8; }

.scores { list-style: none; counter-reset: s; font-size: 12.5px; }
.scores li {
  counter-increment: s;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 0;
  border-bottom: 1px dashed rgba(180, 150, 255, .12);
}
.scores li::before {
  content: counter(s);
  flex: none;
  width: 17px;
  color: var(--gold);
  font-weight: 800;
  font-size: 11px;
}
.scores li.empty { color: var(--dim); font-style: italic; }
.scores li.empty::before { content: "—"; color: var(--dim); }
.scores .sc { font-weight: 800; }
.scores .meta { margin-left: auto; color: var(--dim); font-size: 11px; white-space: nowrap; }
.scores li.fresh .sc { color: var(--gold); }

/* buttons */
.btn {
  display: block;
  width: 100%;
  margin: 8px 0 0;
  padding: 13px 18px;
  border: none;
  border-radius: 11px;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: .06em;
  cursor: pointer;
  transition: transform .1s, filter .15s, background .15s;
}
.btn:active { transform: translateY(1px) scale(.99); }

.btn-primary {
  background: linear-gradient(180deg, #ff5c7a, var(--blood) 55%, #a81238);
  color: #fff;
  box-shadow: 0 8px 24px rgba(224, 52, 90, .35);
}
.btn-primary:hover { filter: brightness(1.12); }

.btn-ghost {
  background: rgba(255, 255, 255, .06);
  border: 1px solid var(--line);
  color: var(--dim);
}
.btn-ghost:hover { background: rgba(255, 255, 255, .11); color: var(--ink); }

/* The two ways in, side by side. Smash is the ghost button: it is the variant,
   and the first thing a new player presses should be the normal game. */
.modes { display: flex; gap: 9px; align-items: stretch; }
.modes .btn { margin-top: 0; flex: 1 1 0; }
.modes .btn-ghost .hint { display: block; margin-top: 3px; letter-spacing: .02em; }
@media (max-width: 560px) {
  .modes { flex-direction: column; }
  .modes .btn:last-child { margin-top: 8px; }
}

.btn-sm { padding: 8px 14px; font-size: 12px; width: auto; margin: 12px auto 0; }
.hint { opacity: .6; font-size: 11px; font-weight: 600; }

/* ============================================================
   Level-up cards
   ============================================================ */

.level-title {
  font-size: clamp(22px, 5vw, 30px);
  font-weight: 900;
  letter-spacing: .1em;
  color: var(--xp);
  text-shadow: 0 0 26px rgba(87, 216, 255, .45);
}
.level-sub { font-size: 11px; letter-spacing: .2em; text-transform: uppercase; color: var(--dim); margin: 5px 0 18px; }

/* Talent screens borrow the card layout but swap cyan for gold, so hitting a
   talent level looks like a different, rarer event than a normal level. */
.level-title.talent-head {
  color: var(--gold);
  text-shadow: 0 0 26px rgba(255, 209, 102, .45);
}
.tal-lv {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 12px;
  letter-spacing: .14em;
  vertical-align: middle;
  color: var(--gold);
  background: rgba(255, 209, 102, .13);
  border: 1px solid rgba(255, 209, 102, .45);
}

.cards { display: grid; gap: 10px; }

.card.talent {
  border-color: rgba(255, 209, 102, .38);
  background: rgba(255, 209, 102, .07);
  padding: 16px 14px;
}
.card.talent:hover, .card.talent:focus-visible {
  border-color: rgba(255, 209, 102, .8);
  background: rgba(255, 209, 102, .13);
}
.card.talent .card-name { color: var(--gold); }

@media (min-width: 760px) {
  .cards.talents { grid-template-columns: 1fr 1fr; }
  .cards.talents .card { flex-direction: column; align-items: flex-start; gap: 8px; }
  .cards.talents .card-body { width: 100%; }
  .cards.talents .card-key { position: absolute; top: 10px; right: 10px; }
}

/* ============================================================
   Split panel: character sheet on one side, choices on the other
   ============================================================ */

.panel-split { width: min(980px, 100%); }

@media (min-width: 900px) {
  .panel-split {
    display: grid;
    grid-template-columns: 300px 1fr;
    gap: 22px;
    align-items: start;
    text-align: left;
  }
}

.charpanel {
  text-align: left;
  border-radius: 13px;
  padding: 13px;
  background: rgba(0, 0, 0, .3);
  border: 1px solid var(--line);
}

/* On narrow screens the sheet collapses to a strip above the choices, so the
   cards still get the space they need to be readable. */
@media (max-width: 899px) {
  .charpanel { margin-bottom: 14px; }
  .charpanel .stat-grid,
  .charpanel .stat-cols,
  .charpanel .tal-list,
  .charpanel .slot-head.extras { display: none; }

  /* A level-up is a three-second decision, and the whole sheet — portrait,
     vitals, weapons, the paper doll, the armoury, the auto-sell row — pushed
     the cards you are meant to be reading off the bottom of a phone. What is
     worth seeing here is what you picked up since the last one, so that is all
     that is left: the gems, and the button that puts them on.
     The Wayhouse and the pause screen still show the whole body — those are
     where you sit and sort your kit. */
  #screenLevel .charpanel > *:not(.gems-head):not(.bag):not(.fit-actions) { display: none; }
  #screenLevel .charpanel { margin-bottom: 12px; padding: 10px; }
  /* Thirty empty squares are a bag, not an inventory. Here only what you are
     actually carrying is drawn, so the panel is as tall as the loot is. */
  #screenLevel .charpanel .bag .slot:not(.filled) { display: none; }
}

.ch-head { display: flex; align-items: center; gap: 11px; margin-bottom: 12px; }

.ch-portrait {
  position: relative;
  flex: none;
  width: 54px;
  height: 54px;
  border-radius: 12px;
  border: 1px solid rgba(143, 240, 255, .35);
  background:
    radial-gradient(circle at 50% 38%, rgba(143, 240, 255, .28), transparent 62%),
    linear-gradient(180deg, #2b2150, #150e2c);
}
/* The hood, drawn in CSS so the sheet needs no extra canvas. */
.ch-portrait::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 12px;
  width: 26px;
  height: 30px;
  transform: translateX(-50%);
  border-radius: 13px 13px 5px 5px;
  background: linear-gradient(180deg, #4a3a86, #2b2150);
}
.ch-portrait::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 22px;
  width: 14px;
  height: 4px;
  transform: translateX(-50%);
  border-radius: 3px;
  background: #8ff0ff;
  box-shadow: 0 0 8px rgba(143, 240, 255, .9);
}
.ch-lv {
  position: absolute;
  right: -6px;
  bottom: -6px;
  min-width: 20px;
  padding: 1px 5px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  text-align: center;
  color: var(--xp);
  background: #150e2c;
  border: 1px solid rgba(87, 216, 255, .5);
}
/* Room level, on the opposite corner from the character level. */
.ch-rl {
  position: absolute;
  left: -6px;
  bottom: -6px;
  min-width: 20px;
  padding: 1px 5px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 800;
  text-align: center;
  color: var(--violet);
  background: #150e2c;
  border: 1px solid rgba(160, 107, 255, .5);
}

.ch-vitals { flex: 1 1 auto; min-width: 0; }
.ch-bar {
  position: relative;
  height: 15px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .55);
  border: 1px solid var(--line);
  overflow: hidden;
}
.ch-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  background: linear-gradient(180deg, #ff5c7a, var(--blood));
}
.ch-bar b {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 10px;
  font-weight: 700;
  text-shadow: 0 1px 2px #000;
}
.ch-shield { font-size: 10.5px; color: #8ff0ff; margin-top: 3px; }
.ch-coins { font-size: 12px; font-weight: 800; color: var(--gold); margin-top: 3px; }

.slot-head {
  display: flex;
  justify-content: space-between;
  font-size: 9px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--dim);
  margin: 12px 0 6px;
}
.slot-head span { color: var(--ink); opacity: .7; }

.slots { display: flex; flex-wrap: wrap; gap: 6px; }
.slot {
  position: relative;
  width: 38px;
  height: 38px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, .35);
  border: 1px dashed rgba(255, 255, 255, .12);
}
.slot.filled {
  background: rgba(255, 255, 255, .06);
  border: 1px solid var(--line);
  border-style: solid;
}
.slot.maxed { border-color: rgba(125, 255, 168, .5); }
.slot i { font-style: normal; font-size: 17px; line-height: 1; }
.slot b {
  position: absolute;
  right: 1px;
  bottom: 0;
  font-size: 9px;
  font-weight: 800;
  color: var(--gold);
  text-shadow: 0 1px 2px #000;
}
.slot.maxed b { color: #7dffa8; }

/* ---------- paper doll + bag ----------
   Worn pieces sit in named slots so the sheet reads as a body rather than a
   list; the bag below it is deliberately plain, because it's a holding pen. */

/* Laid out as a body: head, throat, torso with a hand either side, feet. The
   named areas mean the markup can stay in whatever order SLOTS is declared in. */
.doll {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-areas:
    ".     helm   amulet"
    "hands chest  ring"
    "dash  boots  .";
  gap: 7px;
  align-items: start;
}
.d-helm   { grid-area: helm; }
.d-amulet { grid-area: amulet; }
.d-chest  { grid-area: chest; }
.d-hands  { grid-area: hands; }
.d-ring   { grid-area: ring; }
.d-boots  { grid-area: boots; }
.d-dash   { grid-area: dash; }
/* A gearless run (Smash) has no body to lay out — just the dash, which isn't
   gear and still has to go somewhere. Drop the named areas so it doesn't sit
   in the bottom-left corner of a grid with nothing else in it. */
.doll.gearless {
  grid-template-columns: 44px;      /* one cell, sized like a weapon slot */
  grid-template-areas: none;
  justify-content: start;
  margin-top: 4px;
}
.doll.gearless .d-dash { grid-area: auto; }

.doll-cell { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.doll-k {
  font-size: 8px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
  opacity: .75;
}
/* Every cell is the same size when closed — a ring reads as the same kind of
   thing as a cuirass until you open the cuirass up. */
.doll .slot { width: 100%; height: 44px; }
.doll-cell { min-width: 0; }

/* ---------- armour ----------
   Four of the six slots hold armour, and armour is the biggest thing on the
   sheet on purpose: it is the piece with the irreversible decision in it. Each
   one shows its quality, its "+ to skills" roll if it has one, a row of
   sockets you can read at a glance, and the break button. */

.doll { gap: 8px; }
/* Closed armour: a slot, with the only number that matters printed on it. */
.armour-mini { position: relative; cursor: pointer; }
.armour-mini:hover { background: rgba(160, 107, 255, .16); }
.sock-count {
  position: absolute;
  left: 3px;
  bottom: 1px;
  font-style: normal;
  font-size: 8.5px;
  font-weight: 800;
  color: var(--dim);
}
.armour-mini .mini-plus {
  position: absolute;
  left: 3px;
  top: 1px;
  font-style: normal;
  font-size: 8px;
  font-weight: 800;
  color: var(--gold);
}
.armour-none { cursor: default; }

/* The opened piece is drawn under the doll, never inside it — a grid item with
   a fixed grid-area cannot be widened without drawing over its neighbours. */
.armour-mini.picked {
  border-color: #8ff0ff !important;
  box-shadow: 0 0 0 1px #8ff0ff, inset 0 0 12px -4px #8ff0ff;
}
.armour-close {
  margin-left: 4px;
  width: 15px;
  height: 15px;
  line-height: 13px;
  text-align: center;
  font-size: 8px;
  border-radius: 5px;
  color: var(--dim);
  border: 1px solid rgba(255, 255, 255, .12);
  cursor: pointer;
}
.armour-close:hover { color: var(--ink); background: rgba(255, 255, 255, .12); }

.armour {
  width: 100%;
  margin-top: 7px;
  min-height: 62px;
  padding: 5px 6px 6px;
  border-radius: 11px;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--tc, var(--line));
  box-shadow: inset 0 0 16px -6px var(--tc, transparent);
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.armour-top { cursor: pointer; }
.armour-top { display: flex; align-items: center; gap: 5px; line-height: 1; }
.armour-top i { font-style: normal; font-size: 15px; }
.armour-top b { font-size: 10.5px; font-weight: 800; color: var(--tc); flex: 1 1 auto; }
.armour-plus {
  font-style: normal;
  font-size: 8.5px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: 999px;
  color: var(--gold);
  background: rgba(255, 209, 102, .14);
  border: 1px solid rgba(255, 209, 102, .5);
}
.armour-break {
  margin-left: auto;
  width: 15px;
  height: 15px;
  line-height: 13px;
  text-align: center;
  font-size: 9px;
  border-radius: 5px;
  color: var(--dim);
  border: 1px solid rgba(255, 255, 255, .12);
  cursor: pointer;
}
.armour-break:hover { color: #fff; background: var(--blood); border-color: var(--blood); }

/* The sockets themselves: square, obvious, and obviously countable. */
.sockets { display: flex; gap: 4px; flex-wrap: wrap; }
.sock {
  flex: 1 1 34px;
  min-width: 30px;
  height: 30px;
  font-size: 12px;
  color: rgba(255, 255, 255, .22);
  border-radius: 7px;
  display: grid;
  place-items: center;
  position: relative;
  background: rgba(0, 0, 0, .45);
  border: 1px dashed rgba(255, 255, 255, .16);
}
.sock.filled {
  background: rgba(255, 255, 255, .07);
  border: 1px solid var(--tc);
  box-shadow: inset 0 0 10px -4px var(--tc);
}
.sock i { font-style: normal; font-size: 13px; line-height: 1; }
.sock b {
  position: absolute;
  right: 2px;
  bottom: 0;
  font-size: 7px;
  font-weight: 800;
  color: var(--tc);
}

.bag {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 5px;
}
.bag .slot { width: 100%; height: 34px; }

/* Stack count. Top-left, opposite the tier mark, so a full stack reads as one
   thing you have several of rather than as two competing numbers. */
.slot .stack {
  position: absolute;
  left: 2px;
  top: 1px;
  font-style: normal;
  font-size: 9px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 2px #000;
}

/* Tier is carried entirely by --tc, set inline, so adding a tier needs no CSS. */
.slot.filled[style*="--tc"] {
  border-color: var(--tc);
  background: linear-gradient(180deg, rgba(255, 255, 255, .05), transparent);
  box-shadow: inset 0 0 12px -4px var(--tc);
}
.slot.filled[style*="--tc"] b { color: var(--tc); }
.slot.t4, .slot.t5, .slot.t6, .slot.t7,
.slot.t8, .slot.t9, .slot.t10 { animation: tierGlow 2.4s ease-in-out infinite; }

@keyframes tierGlow {
  0%, 100% { box-shadow: inset 0 0 12px -4px var(--tc); }
  50%      { box-shadow: inset 0 0 12px -4px var(--tc), 0 0 10px -2px var(--tc); }
}

.slot[data-bag], .slot[data-eq] { cursor: pointer; }
.slot[data-bag]:hover, .slot[data-eq]:hover { background: rgba(160, 107, 255, .2); }
.slot.empty { cursor: default; }
.slot .ghost { opacity: .22; font-size: 15px; }

.btn.btn-xs {
  width: 100%;
  margin: 7px 0 0;
  padding: 6px 10px;
  font-size: 11px;
  letter-spacing: .1em;
}
.btn.combine b { color: var(--gold); margin-left: 4px; }
.btn.combine:disabled { opacity: .38; cursor: default; }
.btn.combine:not(:disabled) {
  border-color: rgba(255, 209, 102, .45);
  color: var(--gold);
}

/* The ¢ corner on a bag cell: sells the stack and frees the slot. */
.slot-sell {
  position: absolute;
  top: -5px;
  right: -5px;
  width: 15px;
  height: 15px;
  line-height: 14px;
  text-align: center;
  font-size: 10px;
  font-weight: 700;
  border-radius: 50%;
  color: var(--gold);
  background: #17111f;
  border: 1px solid rgba(255, 209, 102, .5);
  opacity: 0;
  cursor: pointer;
}
.slot:hover .slot-sell, .slot:hover .slot-forge { opacity: 1; }
.slot-sell:hover { background: var(--gold); color: #17111f; }

/* The merge button for one stack, opposite the sell button. */
.slot-forge {
  position: absolute;
  top: -5px;
  left: -5px;
  width: 15px;
  height: 15px;
  line-height: 14px;
  text-align: center;
  font-size: 9px;
  border-radius: 50%;
  color: var(--xp);
  background: #17111f;
  border: 1px solid rgba(87, 216, 255, .5);
  opacity: 0;
  cursor: pointer;
}
.slot-forge:hover { background: var(--xp); color: #17111f; }
.slot-forge.broke { color: var(--blood); border-color: rgba(224, 52, 90, .5); }

/* The ♺ corner: auto-sell this exact gem and quality from now on. Unlike its
   two neighbours it is a *state*, so once it is on it stays lit whether or not
   the cell is hovered — otherwise a flagged stack looks like an unflagged one. */
.slot-auto {
  position: absolute;
  bottom: -5px;
  right: -5px;
  width: 15px;
  height: 15px;
  line-height: 14px;
  text-align: center;
  font-size: 9px;
  border-radius: 50%;
  color: var(--gold);
  background: #17111f;
  border: 1px solid rgba(255, 209, 102, .5);
  opacity: 0;
  cursor: pointer;
}
.slot:hover .slot-auto { opacity: 1; }
.slot-auto:hover { background: var(--gold); color: #17111f; }
.slot-auto.on {
  opacity: 1;
  background: var(--gold);
  color: #17111f;
  border-color: var(--gold);
}

/* Equip and forge sit side by side under the fittings. */
.fit-actions { display: flex; gap: 6px; }
.fit-actions .btn { flex: 1 1 0; }
.btn.forge:not(:disabled) { border-color: rgba(87, 216, 255, .45); color: var(--xp); }
.btn.forge b { color: var(--xp); margin-left: 4px; }
.fee { color: var(--gold); font-size: 9.5px; margin-left: 4px; }

/* Auto-sell: one chip per low tier, lit in that tier's own colour when on. */
.autosell {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 7px;
}
.as-k {
  flex: 1 1 auto;
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}
.as-t {
  min-width: 30px;
  padding: 3px 5px;
  border-radius: 7px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--dim);
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--line);
  cursor: pointer;
}
.as-t:hover { border-color: var(--tc); color: var(--tc); }
.as-t.on {
  color: #0b0810;
  background: var(--tc);
  border-color: var(--tc);
}
.as-t:disabled { opacity: .3; cursor: not-allowed; }
.autosell.locked .as-k { opacity: .5; }

.tal-list { display: flex; flex-wrap: wrap; gap: 4px; }
.tal-pill {
  font-size: 10px;
  padding: 2px 7px;
  border-radius: 999px;
  color: var(--gold);
  background: rgba(255, 209, 102, .1);
  border: 1px solid rgba(255, 209, 102, .4);
}

/* Three columns: what you hit with, what keeps you alive, everything else. */
.stat-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px 10px; }
.stat-col { min-width: 0; }
.sc-h {
  margin: 0 0 3px;
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line);
  padding-bottom: 2px;
}
.sc-h.off  { color: #ff8fa3; }
.sc-h.def  { color: #8ff0ff; }
.sc-h.misc { color: var(--gold); }
.stat-col .sr { gap: 6px; }
.stat-col .sr span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 12px; }
.sr { display: flex; justify-content: space-between; font-size: 10.5px; line-height: 1.6; }
.sr span { color: var(--dim); }
.sr b { font-weight: 700; }

.pick-actions { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }

/* Banish: a small ✕ that removes an option from the run's pool for good. */
.card-ban {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 19px;
  height: 19px;
  border-radius: 6px;
  display: grid;
  place-items: center;
  font-size: 10px;
  color: var(--dim);
  background: rgba(0, 0, 0, .4);
  border: 1px solid var(--line);
  z-index: 2;
}
.card-ban:hover { color: #ff5c7a; border-color: rgba(255, 92, 122, .7); }

/* ============================================================
   Town
   ============================================================ */

.town-title { color: var(--gold); text-shadow: 0 0 26px rgba(255, 209, 102, .4); }
.purse {
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 12px;
}
.purse b { font-size: 17px; color: var(--gold); margin-left: 5px; }

.card.shop .price {
  flex: none;
  font-size: 12px;
  font-weight: 800;
  color: var(--gold);
  white-space: nowrap;
}
.card.shop.broke { opacity: .42; cursor: not-allowed; }
.card.shop.broke .price { color: var(--blood); }
.card.shop.sold { opacity: .35; }
.card.shop.sold .price { color: #7dffa8; }
#screenTown .cards { margin-bottom: 16px; }

/* ---------- the ward ---------- */

.ward-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
  font-size: 12px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gold);
}
.ward-head span {
  font-size: 10px;
  letter-spacing: .06em;
  text-transform: none;
  color: var(--dim);
}

.ward { display: grid; gap: 6px; margin-bottom: 16px; }
.ward-opt {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 11px;
  border-radius: 10px;
  font-size: 12px;
  text-align: left;
  color: var(--ink);
  background: rgba(255, 209, 102, .07);
  border: 1px solid rgba(255, 209, 102, .28);
  cursor: pointer;
}
.ward-opt:hover:not(:disabled) { background: rgba(255, 209, 102, .14); border-color: rgba(255, 209, 102, .55); }
.ward-opt i { font-style: normal; font-size: 17px; }
.ward-opt span { flex: 1 1 auto; font-weight: 700; display: flex; flex-direction: column; }
.ward-opt em { font-style: normal; font-size: 10px; font-weight: 400; color: var(--dim); }
.ward-opt b { color: var(--gold); font-size: 11.5px; white-space: nowrap; }
.ward-opt.broke { opacity: .42; cursor: not-allowed; }
.ward-opt.broke b { color: var(--blood); }
.ward-opt.done { border-color: rgba(125, 255, 168, .5); background: rgba(125, 255, 168, .07); }
.ward-opt.done b { color: #7dffa8; }

.card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .045);
  border: 1px solid var(--line);
  text-align: left;
  cursor: pointer;
  font-family: var(--font);
  color: var(--ink);
  transition: transform .12s, background .15s, border-color .15s;
}
.card:hover, .card:focus-visible {
  background: rgba(160, 107, 255, .16);
  border-color: rgba(160, 107, 255, .6);
  transform: translateX(3px);
  outline: none;
}

.card-icon {
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  font-size: 21px;
  background: rgba(0, 0, 0, .4);
  border: 1px solid var(--line);
}
.card-body { flex: 1 1 auto; min-width: 0; }
.card-name { font-size: 14.5px; font-weight: 800; letter-spacing: .02em; display: flex; align-items: center; gap: 7px; }
.card-desc { font-size: 11.5px; color: var(--dim); line-height: 1.45; margin-top: 3px; }
.card-key {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 800;
  color: var(--dim);
  background: rgba(255, 255, 255, .06);
  border: 1px solid var(--line);
}
.tag {
  font-size: 9px;
  letter-spacing: .12em;
  padding: 2px 6px;
  border-radius: 5px;
  text-transform: uppercase;
  font-weight: 800;
}
.tag.new { background: rgba(255, 209, 102, .18); color: var(--gold); border: 1px solid rgba(255, 209, 102, .4); }
.tag.lv { background: rgba(87, 216, 255, .15); color: var(--xp); border: 1px solid rgba(87, 216, 255, .38); }
.tag.max { background: rgba(125, 255, 168, .15); color: #7dffa8; border: 1px solid rgba(125, 255, 168, .38); }
/* Item tiers colour themselves inline, so this only needs the border box. */
.tag.tier { border: 1px solid; }

/* ============================================================
   Pause / game over stats
   ============================================================ */

.pause-stats, .over-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin: 6px 0 18px;
}
.ovs {
  padding: 9px 6px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--line);
}
.ovs .k { display: block; font-size: 9px; letter-spacing: .16em; text-transform: uppercase; color: var(--dim); }
.ovs .v { display: block; font-size: clamp(17px, 4.4vw, 22px); font-weight: 800; margin-top: 2px; }
.ovs.big { grid-column: 1 / -1; }
.ovs.big .v { color: var(--gold); font-size: clamp(28px, 8vw, 40px); }

.rank {
  display: inline-block;
  margin-bottom: 12px;
  padding: 5px 14px;
  border-radius: 999px;
  background: rgba(255, 209, 102, .14);
  border: 1px solid rgba(255, 209, 102, .45);
  color: var(--gold);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  animation: pop .35s cubic-bezier(.2, 1.6, .4, 1);
}
@keyframes pop { from { transform: scale(.7); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ============================================================
   Touch stick
   ============================================================ */

/* `display: none` unless the stick is actually in use. It is a full-screen
   layer sitting directly over the canvas, and leaving it in the tree the whole
   time makes the compositor deal with it on every frame for the benefit of the
   two rings inside it, which are invisible until you touch the screen. */
.stick { display: none; position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.stick.on, .stick.latched { display: block; }
.stick-base, .stick-knob {
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity .12s;
}
.stick-base {
  width: 116px; height: 116px;
  border: 2px solid rgba(200, 180, 255, .3);
  background: rgba(20, 10, 35, .3);
}
.stick-knob {
  width: 52px; height: 52px;
  background: rgba(224, 52, 90, .55);
  border: 2px solid rgba(255, 190, 205, .7);
  box-shadow: 0 0 20px rgba(224, 52, 90, .5);
}
.stick.on .stick-base, .stick.on .stick-knob { opacity: 1; }

/* Latched: no finger down, still running. The base stays as a faint ghost
   where you let go, so "why am I still moving" has an answer on screen. The
   knob goes — there is nothing under your thumb any more. */
.stick.latched:not(.on) .stick-base { opacity: .22; }

.touch-only { display: none; }

/* A settings pill under the controls list. `.on` is the only state worth
   colouring — off should read as the quiet default, not as a warning. */
.btn.opt { margin-top: 10px; letter-spacing: .06em; }
.btn.opt b { color: var(--dim); margin-left: 3px; text-transform: uppercase; }
.btn.opt.on { border-color: rgba(87, 216, 255, .45); color: var(--xp); }
.btn.opt.on b { color: var(--xp); }

/* ============================================================
   Responsive
   ============================================================ */

@media (max-width: 620px) {
  .cols { grid-template-columns: 1fr; gap: 18px; }
  .hud-right { padding-right: 78px; }
  .hud-left { max-width: 46%; }
  .stat-k { display: none; }
  .stat { gap: 0; }
  .stat::after { content: ""; }
  /* Keyed off the stat, not off its position — by position, coins were wearing
     the skull that belongs to kills. */
  .hud-right .stat-score .stat-v::before { content: "★ "; color: var(--gold); font-size: 11px; }
  .hud-right .stat-coin .stat-v::before { content: "¢ "; color: var(--gold); font-size: 11px; }
  .hud-right .stat-kills .stat-v::before { content: "☠ "; color: var(--blood); font-size: 11px; }
  .hud-right .stat-best .stat-v::before { content: "♛ "; color: var(--dim); font-size: 11px; }
  .card-desc { font-size: 11px; }
  /* Already icon-only; on a phone they just get tighter. */
  .chip { padding: 3px; min-width: 22px; }
  .chip .ic { font-size: 13px; }
  .chip.bagchip .lv { font-size: 9px; }
  .loadout { gap: 3px; max-width: 62%; }
}

@media (max-width: 380px) {
  .card-icon { width: 34px; height: 34px; font-size: 17px; }
  .panel { padding: 16px 13px; }
}

/* Short/landscape phones: the level-up list must not overflow the viewport. */
@media (max-height: 520px) {
  .cards { gap: 7px; }
  .card { padding: 8px 11px; }
  .card-icon { width: 32px; height: 32px; font-size: 16px; }
  .card-desc { font-size: 10.5px; }
  .level-sub { margin-bottom: 11px; }
  .tagline { margin-bottom: 12px; }
}

@media (hover: none) and (pointer: coarse) {
  .touch-only { display: list-item; }
  .no-touch { display: none !important; }
  .icon-btn { width: 40px; height: 40px; font-size: 17px; }
  /* One button up there now, and one number beside it. Score, kills and best
     are all end-of-run reading; coins are the only figure you spend *during*
     a run, so it is the only one that stays. */
  .hud-right { padding-right: 52px; }
  .hud-right .stat { display: none; }
  .hud-right .stat-coin { display: flex; }
  .hud-right .stat-coin .stat-v { font-size: 16px; }

  /* A gem cell must never hand its gesture to the scroller. */
  .bag .slot, .armoury .slot, .sock, .doll .slot { touch-action: manipulation; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Version stamp. Deliberately faint: it is for a bug report, not for reading. */
.version {
  margin-top: 14px;
  font-size: 9.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  text-align: right;
  color: var(--dim);
  opacity: .45;
}

/* ============================================================
   Popups: infoboxes, notes, and the one confirm
   ============================================================ */

/* Replaces the browser `title` everywhere it mattered. An item is not one line
   any more — it is a stat, a place it can go, whether that place is one-way,
   what it sells for, and (on Shift) what it beats. */
.tip {
  position: fixed;
  z-index: 40;
  max-width: 300px;
  padding: 9px 11px;
  border-radius: 12px;
  background: rgba(14, 9, 24, .97);
  border: 1px solid var(--line);
  box-shadow: 0 12px 34px rgba(0, 0, 0, .7);
  font-size: 11.5px;
  line-height: 1.45;
  pointer-events: none;
}
.tip-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.tip-head i { font-style: normal; font-size: 20px; }
.tip-head span { display: flex; flex-direction: column; min-width: 0; }
.tip-head b { font-size: 12.5px; color: var(--tc, var(--ink)); }
.tip-head em {
  font-style: normal;
  font-size: 9.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
}
.tip-row { display: flex; justify-content: space-between; gap: 12px; }
.tip-row span { color: var(--ink); }
.tip-row b { color: var(--dim); font-weight: 700; white-space: nowrap; }
.tip-row.good b { color: #7dffa8; }
.tip-row.bad b { color: var(--blood); }
.tip-row.dimrow span, .tip-row.dimrow b { color: var(--dim); opacity: .7; }
.tip-note { margin-top: 6px; color: var(--dim); font-size: 11px; }
.tip-note b { color: var(--ink); }
.tip-note.warn { color: #ff9eb1; }
.tip-note.warn b { color: #ffd166; }
.tip-note.dim { opacity: .72; }
.tip-cmp {
  margin-top: 8px;
  padding-top: 7px;
  border-top: 1px dashed var(--line);
}
.tip-cmp-h {
  font-size: 9px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--violet);
  margin-bottom: 4px;
}
.tip-hint { margin-top: 7px; font-size: 9.5px; color: var(--dim); opacity: .6; }
.tip-hint kbd {
  padding: 0 4px;
  border-radius: 4px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .06);
}

/* A line of explanation where a click did nothing and you deserve to know why. */
.note-pop {
  position: fixed;
  left: 50%;
  bottom: 96px;
  transform: translateX(-50%);
  z-index: 41;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(14, 9, 24, .96);
  border: 1px solid rgba(255, 209, 102, .45);
  color: var(--gold);
  font-size: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .6);
  pointer-events: none;
}

/* The one destructive act in the game asks first. */
.ask {
  position: fixed;
  inset: 0;
  z-index: 42;
  display: grid;
  place-items: center;
  background: rgba(5, 3, 11, .72);
}
.ask-box {
  width: min(420px, 88vw);
  padding: 20px;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid rgba(224, 52, 90, .5);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .75);
  text-align: center;
}
.ask-text { font-size: 13px; line-height: 1.6; margin-bottom: 16px; }
.ask-text b { color: var(--gold); }
.ask-actions { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
/* The alternative is not a lesser choice — it is the other half of the same
   decision — so it is weighted like the primary rather than like a cancel. */
#askAlt { border-color: rgba(160, 107, 255, .6); color: var(--violet); }
#askAlt:hover { background: rgba(160, 107, 255, .16); }
.ask-actions .btn { flex: 1 1 0; margin: 0; }

/* A weapon past its own table, thanks to "+ to skills" on armour. */
.slot.filled.over { border-color: var(--gold); box-shadow: inset 0 0 12px -4px var(--gold); }
.slot.filled.over b { color: var(--gold); }

/* Armour on the shelf reads as its own kind of thing. */
.card.shop.armour { border-color: rgba(160, 107, 255, .45); }
.card.shop.forge { border-color: rgba(87, 216, 255, .38); }
.card.shop.gem { border-color: rgba(125, 255, 168, .3); }

/* ---------- dragging an item into a socket ---------- */

.drag-ghost {
  position: fixed;
  z-index: 45;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  background: rgba(20, 13, 34, .96);
  border: 1px solid var(--tc);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .7), inset 0 0 12px -4px var(--tc);
  pointer-events: none;
}
.drag-ghost i { font-style: normal; font-size: 16px; }
.drag-ghost b { position: absolute; right: 2px; bottom: 0; font-size: 8px; color: var(--tc); }

/* The hole under the cursor lights up, so you never guess where it will land. */
.drop-ok {
  border-color: #7dffa8 !important;
  border-style: solid !important;
  background: rgba(125, 255, 168, .16) !important;
  box-shadow: 0 0 12px -2px rgba(125, 255, 168, .7) !important;
}

/* ============================================================
   The gem menu (touch)
   ============================================================ */

/* A bottom sheet, because it is the part of a phone a thumb can actually
   reach. It answers the question the hover tooltip answers on a desktop —
   what is this, and where can it go — but every answer is a button. */
.item-menu {
  position: fixed;
  z-index: 46;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 12px 12px calc(env(safe-area-inset-bottom, 0px) + 14px);
  background: linear-gradient(180deg, rgba(24, 15, 40, .97), rgba(12, 7, 22, .99));
  border-top: 1px solid var(--line);
  box-shadow: 0 -14px 40px rgba(0, 0, 0, .75);
  border-radius: 16px 16px 0 0;
  max-height: 72vh;
  overflow-y: auto;
  animation: menuUp .14s ease-out;
}
@keyframes menuUp { from { transform: translateY(14px); opacity: 0; } to { transform: none; opacity: 1; } }

.im-head { display: flex; align-items: center; gap: 10px; margin-bottom: 11px; }
.im-head i {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  font-style: normal;
  font-size: 19px;
  border-radius: 10px;
  border: 1px solid var(--tc);
  background: rgba(0, 0, 0, .35);
  box-shadow: inset 0 0 14px -5px var(--tc);
}
.im-head span { flex: 1 1 auto; min-width: 0; display: block; }
.im-head b { display: block; color: var(--tc); font-size: 13px; }
.im-head em { display: block; font-style: normal; font-size: 11px; color: var(--dim); }
.im-x {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .05);
  color: var(--dim);
  font-family: var(--font);
  font-size: 14px;
}

.im-acts { display: flex; flex-direction: column; gap: 7px; }

/* Every row is a 46px target: this exists because a 34px gem square was too
   small to drag, so the menu it opens must not repeat the mistake. */
.im-act {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  min-height: 46px;
  padding: 7px 11px;
  text-align: left;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .05);
  color: var(--ink);
  font-family: var(--font);
}
.im-act:active { background: rgba(255, 255, 255, .12); }
.im-act i { font-style: normal; font-size: 18px; flex: none; width: 22px; text-align: center; }
.im-act b { display: block; font-size: 12.5px; font-weight: 800; }
.im-act em { display: block; font-style: normal; font-size: 10.5px; color: var(--dim); }
/* Socketing is the one-way one, so it is the one that looks like a decision. */
.im-act.sock-act { border-color: rgba(160, 107, 255, .5); background: rgba(160, 107, 255, .1); }
.im-act.sock-act em { color: #c9a3ff; }
.im-act.sell-act i { color: var(--gold); }
.im-act.broke { opacity: .55; }
.im-none { font-size: 11px; color: var(--dim); text-align: center; margin: 6px 0 2px; }

/* ---------- the dash slot ---------- */

/* The dash sits on the doll, drawn like the armour beside it — same size,
   same shape, its own colour so it reads as a different kind of thing. */
.dash-slot {
  position: relative;
  border-color: rgba(143, 240, 255, .5) !important;
  box-shadow: inset 0 0 12px -4px #8ff0ff;
}
.dash-slot b { color: #8ff0ff; }
.dash-slot .sock-count { color: rgba(143, 240, 255, .75); letter-spacing: .04em; }
.dash-slot.cooling { opacity: .45; }

.chip.dash { border-color: rgba(143, 240, 255, .5); }
.chip.dash .lv { color: #8ff0ff; font-size: 9px; }
.chip.dash.cooling { opacity: .4; }

/* ---------- the armoury ----------
   The second inventory. Fittings stack and merge and sell by tier; a piece of
   armour is a specific set of holes with specific things in them and stacks
   with nothing, so it gets a grid of its own. */
.armoury {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 5px;
}
.armoury .slot { width: 100%; height: 38px; }
.armoury .armour-mini { cursor: pointer; }
