:root {
  --bg: #050913;
  --panel: rgba(11, 15, 25, 0.84);
  --panel-border: rgba(255,255,255,0.12);
  --text: #f8fafc;
  --muted: rgba(248,250,252,0.76);
  --btn: rgba(255,255,255,0.12);
  --btn-border: rgba(255,255,255,0.18);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
  --keyboard-inset: 0px;
}
* { box-sizing: border-box; }
html, body {
  margin: 0;
  height: 100%;
  overscroll-behavior: none;
  background:
    radial-gradient(circle at top, rgba(42,78,154,0.20), transparent 30%),
    radial-gradient(circle at center, rgba(16,22,36,0.88), rgba(5,9,19,1) 70%);
  color: var(--text);
  font-family: Inter, Arial, sans-serif;
  overflow: hidden;
}
button, input { font: inherit; }
[hidden] { display: none !important; }

html.hq-immersive, body.hq-immersive {
  width: 100%;
  height: var(--app-height, 100dvh);
}
body.hq-immersive {
  position: fixed;
  inset: 0;
}

.hq-shell {
  position: relative;
  width: 100vw;
  height: var(--app-height, 100dvh);
  overflow: hidden;
  background: linear-gradient(180deg, #060b15, #030712);
  touch-action: none;
}

.hq-frame {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: max(10px, var(--safe-t)) 10px max(10px, var(--safe-b)) 10px;
}

.hq-stage {
  position: relative;
  width: min(calc(100vw - 20px), calc((100vh - 20px - var(--safe-t) - var(--safe-b)) * (16 / 9)));
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 24px;
  border: 1px solid rgba(255,255,255,0.10);
  box-shadow: 0 30px 80px rgba(0,0,0,0.42);
  background: #07101c;
}

.hq-world {
  position: absolute;
  left: 0;
  top: 0;
  width: 1280px;
  height: 720px;
  transform-origin: top left;
  will-change: transform;
  /* Nothing in the world is text to be selected. Characters became click targets
     for the party menu, which also made them drag-selectable — so any click that
     moved a pixel painted a blue selection box over the character and its name.
     Scoped to the world, not the stage: chat and the HUD live outside it and must
     stay selectable so a message can still be copied. */
  user-select: none;
  -webkit-user-select: none;
}

.hq-bg-layer { position: absolute; inset: 0; }
.hq-bg-layer--image {
  background-position: center center;
  background-size: cover;
  background-repeat: no-repeat;
  filter: saturate(1.04) contrast(1.04) brightness(0.92);
  transform: scale(1.04);
  transform-origin: center center;
}
.hq-bg-layer--shade {
  background:
    linear-gradient(to top, rgba(4,8,15,0.80) 0%, rgba(4,8,15,0.46) 36%, rgba(4,8,15,0.16) 100%),
    radial-gradient(circle at top center, rgba(255,255,255,0.04), transparent 42%);
}

.hq-ground {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 50px;
  height: 20px;
  background:
    linear-gradient(to bottom, rgba(19,27,43,0.10), rgba(9,13,22,0.70) 18%, rgba(5,8,15,0.92) 100%);
  border-top: 1px solid rgba(255,255,255,0.08);
  box-shadow: 0 -24px 50px rgba(0,0,0,0.28) inset;
}

.map-visual-layer{
  position:absolute;
  inset:0;
  pointer-events:none;
}
.map-visual{
  position:absolute;
  pointer-events:none;
  user-select:none;
  will-change:transform,bottom,left,width,height;
}
.map-visual img{
  width:100%;
  height:100%;
  display:block;
  /* MUST match .ga-obj--visual img in the map builder, which uses fill.
     With contain the art was letterboxed and CENTRED inside its box, so a tree
     placed on the ground rendered floating by half the leftover height — the
     placement data was always correct, the fitting was not. The builder is the
     authoring surface: the box IS the art. */
  object-fit:fill;
  /* no drop-shadow: builder decor (buildings etc.) must blend into the map —
     the shadow smeared a dark silhouette behind every transparent PNG/WebP */
}

.hq-topbar {
  position: absolute;
  top: 14px;
  left: 18px;
  right: 18px;
  z-index: 25;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: flex-start;
  pointer-events: none;
}
.hq-topbar > * { pointer-events: auto; }

/* The old floating map title/subtitle is redundant now that map info lives in the top-left HUD card. */
.hq-topbar--actions-only {
  justify-content: flex-end;
}
.hq-topbar--actions-only .hq-map-heading {
  display: none !important;
}
.hq-topbar-title {
  font-size: 34px;
  font-weight: 900;
  letter-spacing: -0.03em;
  text-shadow: 0 4px 14px rgba(0,0,0,0.55);
}
.hq-topbar-sub {
  margin-top: 4px;
  color: var(--muted);
  font-size: 12px;
  max-width: 600px;
  text-shadow: 0 2px 10px rgba(0,0,0,0.55);
}
.hq-back-link {
  color: #fff;
  text-decoration: none;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 10px 14px;
  font-weight: 700;
  backdrop-filter: blur(10px);
}

.player {
  position: absolute;
  left: 0;
  bottom: 160px;
  /* Scaled to 65% with PLAYER_WIDTH (was 176x520). This box positions the name
     label and HP bar, so it has to track the sprite or they drift off. */
  width: 114px;
  height: 338px;
  display: block;
  z-index: 30;
  /* scale from the FEET so per-map player scaling never floats characters */
  transform-origin: 50% 100%;
  will-change: transform, bottom;
  overflow: visible;
}
.player-sprite {
  position: absolute;
  left: 50%;
  bottom: 28px;
  width: 176px;
  height: auto;
  display: block;
  transform: translateX(-50%);
  transform-origin: center bottom;
  filter: drop-shadow(0 10px 24px rgba(0,0,0,0.44));
}
.player-name {
  position: absolute;
  left: 50%;
  bottom: -30px;   /* sits UNDER the feet, not on the ankles */
  transform: translateX(-50%);
  margin-top: 0;
  font-size: 18px;
  font-weight: 900;
  text-shadow: 0 2px 8px rgba(0,0,0,0.72);
  white-space: nowrap;
}
.player-bubble {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  /* Anchor at a fixed height over the head. The .player wrapper is a tall 520px
     box (headroom for weapons/headwear), so 'calc(100% + 16px)' floated the bubble
     ~536px up — far above non-layered players (default-sprite fallback: new guests
     and any player whose skin hasn't loaded). 250px matches the .player--layered
     override so the bubble sits just over the head regardless of skin. */
  bottom: 250px;
  /* max-content frees the bubble from the 176px player box — otherwise text
     wrapped one word per line no matter what max-width said. 22ch caps each
     line at ~22 characters (owner rule); the bubble is bottom-anchored, so
     longer messages stack upward instead of growing wide. */
  width: max-content;
  min-width: 120px;
  max-width: 22ch;
  min-height: 50px;
  padding: 13px 18px;
  border-radius: 20px;
  background: rgba(255,255,255,0.97);
  color: #0f172a;
  font-size: 17px;
  font-weight: 700;
  text-align: center;
  line-height: 1.34;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
  box-shadow: 0 12px 30px rgba(0,0,0,0.35);
}
.player-bubble::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 100%;
  border: 8px solid transparent;
  border-top-color: rgba(255,255,255,0.96);
}

.projectile-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 28;
}
/* A sibling of .projectile-layer and .players-layer, not a child of either — that is
   the whole reason it exists. .projectile-layer sits below .players-layer (28 vs 29
   by default), and the two are siblings that each become their own stacking context
   once z-index is set on them. That means no z-index applied to something INSIDE
   .projectile-layer can ever climb above .players-layer — it is trapped in its
   parent's stacking context no matter how high the number. Cleave, Ground Slam and
   Warcry need to draw in front of the character, so they render into this layer
   instead, which — being a sibling of .players-layer with its own higher z-index —
   is the only way to actually get in front.
   61, not 30: a later, unscoped rule further down this file ("Keep MMO combat above
   profile video thumbnails/cards") pins .projectile-layer AND .players-layer to
   z-index 60 with !important on every page that loads this stylesheet, and that beats
   the 28/29 shown above outright — 60 is the number actually in effect in the live
   game, with .players-layer only winning today because it happens to come after
   .projectile-layer in the HTML. Map-specific rules push these further still (e.g.
   .exp-map-home-hq raises .player to 34, though that particular rule is itself
   silently shadowed by the same !important block). Chasing each of those with a
   matching override is fragile — the home-hq one is already dead from exactly that
   trap — so this layer just sits above the highest value any of them reach instead. */
.knight-fx-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 61;
}

.knight-monster-fx-layer {
  position: absolute; inset: 0; pointer-events: none;
  z-index: 62; /* one above .knight-fx-layer's 61 */
}
.projectile {
  position: absolute;
  width: 28px;
  height: 28px;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 0 8px rgba(255,255,255,0.45));
}
.projectile::before,
.projectile::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 50%, #f8fafc 0%, #cbd5e1 28%, #94a3b8 58%, rgba(148,163,184,0) 62%);
  clip-path: polygon(50% 0%, 61% 36%, 98% 36%, 68% 57%, 79% 100%, 50% 72%, 21% 100%, 32% 57%, 2% 36%, 39% 36%);
}
.projectile::after {
  transform: scale(0.42);
  filter: blur(0.5px);
}

.touch-controls {
  position: absolute;
  inset: auto 14px calc(18px + var(--safe-b)) 14px;
  display: none;
  justify-content: space-between;
  pointer-events: none;
  z-index: 70;
}
.touch-pad {
  display: flex;
  gap: 10px;
  pointer-events: auto;
}
.touch-pad--right {
  align-items: flex-end;
}
.touch-pad--left {
  align-items: flex-end;
}
.touch-btn {
  width: 58px;
  height: 58px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(11,15,25,0.72);
  color: #fff;
  font-size: 23px;
  font-weight: 800;
  backdrop-filter: blur(10px);
  box-shadow: 0 12px 22px rgba(0,0,0,0.25);
  touch-action: none;
  user-select: none;
}
.touch-btn--jump { width: 74px; height: 74px; font-size: 28px; }
.touch-btn--attack { width: 74px; height: 74px; font-size: 28px; background: rgba(120, 70, 8, 0.72); border-color: rgba(255, 178, 0, 0.55); }
/* Word labels on the action buttons (their own font-size beats the button's 28px in every rule). */
.touch-btn-label { font-size: 15px; font-weight: 800; letter-spacing: .5px; line-height: 1; text-transform: uppercase; }
.touch-btn--melee { width: 56px; height: 56px; font-size: 21px; }
.touch-btn--chat { width: 52px; height: 52px; font-size: 20px; }

/* Left-thumb virtual joystick (move / drop / climb) */
.touch-stick {
  position: relative;
  width: 122px;
  height: 122px;
  border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,0.22);
  background: rgba(11,15,25,0.55);
  backdrop-filter: blur(10px);
  box-shadow: 0 12px 22px rgba(0,0,0,0.25);
  touch-action: none;
  user-select: none;
  pointer-events: auto;
}
.touch-stick-nub {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: rgba(255,255,255,0.26);
  border: 1.5px solid rgba(255,255,255,0.45);
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.touch-stick.active { border-color: rgba(255, 178, 0, 0.6); }
.touch-stick.active .touch-stick-nub { background: rgba(255, 178, 0, 0.45); }

/* ---- Mobile PLAY mode: clean cockpit — everything else lives behind the ☰ button ---- */
.hq-mobile-menu-btn { display: none; }
@media (max-width: 980px) {
  /* Phones never see the video-thumbnail panel — it boots EXPANDED and covers the
     whole screen before the game starts (owner: extremely confusing on mobile). */
  .exp-video-panel { display: none !important; }

  /* TRUE fullscreen on phones: the stage stops being a centered 16:9 rounded card
     and becomes the entire viewport, edge to edge. */
  body.hq-mobile-play .hq-frame { padding: 0 !important; }
  body.hq-mobile-play .hq-stage {
    width: 100vw !important;
    height: var(--app-height, 100dvh) !important;
    aspect-ratio: auto !important;
    max-width: none !important;
    max-height: none !important;
    border-radius: 0 !important;
    border: 0 !important;
    box-shadow: none !important;
  }

  body.hq-mobile-play .hq-mobile-menu-btn {
    display: flex; align-items: center; justify-content: center;
    position: absolute; top: calc(8px + var(--safe-t, 0px)); right: 10px; z-index: 130;
    width: 46px; height: 46px; border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.18); background: rgba(11,15,25,0.72); color: #fff;
    font-size: 20px; font-weight: 800; backdrop-filter: blur(10px);
    box-shadow: 0 12px 22px rgba(0,0,0,0.25); touch-action: manipulation; user-select: none;
  }
  body.hq-mobile-play.hq-mobile-menu-open .hq-mobile-menu-btn {
    background: rgba(255,178,0,0.35); border-color: rgba(255,178,0,0.6);
  }

  /* hidden while actually playing (menu closed) */
  body.hq-mobile-play:not(.hq-mobile-menu-open) .exp-social-nav,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .hq-topbar,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .hud-stack--map-info,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .exp-video-panel,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .exp-progression-toggle,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .exp-progression-panel,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .exp-abilities-toggle,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .hq-utility-stack,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .hq-utility-btn,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .hq-economy-dock,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .hq-economy-btn,
  body.hq-mobile-play:not(.hq-mobile-menu-open) .hq-back-link {
    display: none !important;
  }

  /* compact status HUD tucked top-left so the arena stays clear */
  body.hq-mobile-play .maple-status-hud {
    position: absolute !important;
    top: calc(6px + var(--safe-t, 0px)) !important;
    left: 8px !important;
    right: auto !important;
    bottom: auto !important;
    transform: scale(0.68);
    transform-origin: top left;
    z-index: 90;
  }

  /* while the ☰ drawer is open, fade the combat controls out of the way */
  body.hq-mobile-play.hq-mobile-menu-open .touch-controls { opacity: 0.25; pointer-events: none; }
}

.chat-dock {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(74px + var(--safe-b));
  transform: translateY(calc(-1 * var(--keyboard-inset)));
  transition: transform 0.18s ease;
  z-index: 96;
  display: flex;
  justify-content: center;
  pointer-events: none;
}
.chat-hint {
  position: absolute;
  top: calc(14px + var(--safe-t, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 96;
  pointer-events: auto;
  color: #fff;
  background: rgba(8, 12, 20, 0.70);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 999px;
  padding: 9px 16px;
  font-size: 13px;
  font-weight: 800;
  white-space: nowrap;
  backdrop-filter: blur(10px);
}

.chat-history-btn {
  pointer-events: auto;
  margin-left: 10px;
  color: #fff;
  background: rgba(8, 12, 20, 0.70);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 999px;
  padding: 9px 14px;
  font-size: 12px;
  font-weight: 800;
  backdrop-filter: blur(10px);
}
.chat-history-panel {
  pointer-events: auto;
  position: absolute;
  right: 20px;
  bottom: 64px;
  width: min(420px, calc(100% - 40px));
  max-height: 320px;
  overflow: hidden;
  background: rgba(7, 10, 18, 0.92);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 18px;
  box-shadow: 0 18px 40px rgba(0,0,0,0.32);
  backdrop-filter: blur(14px);
}
.chat-history-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}
.chat-history-title {
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.chat-history-close {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 0;
  background: rgba(255,255,255,0.08);
  color: #fff;
  font-weight: 900;
}
.chat-history-list {
  max-height: 260px;
  overflow: auto;
  padding: 10px 12px 12px;
}
.chat-history-item {
  padding: 10px 11px;
  border-radius: 12px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.06);
  margin-bottom: 8px;
}
.chat-history-name {
  font-size: 12px;
  font-weight: 900;
  color: rgba(255,255,255,0.96);
  margin-bottom: 4px;
}
.chat-history-text {
  font-size: 13px;
  line-height: 1.4;
  color: rgba(255,255,255,0.84);
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.chat-history-time {
  margin-top: 5px;
  font-size: 11px;
  color: rgba(255,255,255,0.48);
}
.chat-send-btn[disabled] {
  opacity: 0.55;
}
.chat-spam-note {
  color: #fca5a5;
  font-size: 12px;
  font-weight: 700;
  margin-left: 6px;
}

.chat-bar {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  width: min(720px, calc(100% - 28px));
  background: rgba(7, 10, 18, 0.86);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 18px;
  padding: 10px 12px;
  backdrop-filter: blur(12px);
  box-shadow: 0 18px 40px rgba(0,0,0,0.30);
}
.chat-label {
  color: rgba(255,255,255,0.9);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.chat-input {
  flex: 1;
  min-width: 0;
  height: 44px;
  border-radius: 14px;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.06);
  color: #fff;
  padding: 0 14px;
  outline: none;
}
.chat-send-btn {
  height: 44px;
  border-radius: 14px;
  border: 0;
  padding: 0 18px;
  font-weight: 900;
  background: #fff;
  color: #0f172a;
}

.hq-overlay, .rotate-overlay {
  position: absolute;
  inset: 0;
  z-index: 120;
  display: grid;
  place-items: center;
  background: rgba(2,6,12,0.70);
  backdrop-filter: blur(6px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease;
}
.hq-overlay--visible {
  opacity: 1;
  pointer-events: auto;
}
.hq-overlay > .hq-panel,
.hq-overlay > .hq-loading-card {
  display: none;
}
.hq-overlay.hq-overlay--entry > .hq-panel {
  display: block;
}
.hq-overlay.hq-overlay--loading > .hq-loading-card {
  display: grid;
}
.hq-panel, .rotate-card, .hq-loading-card {
  width: min(92vw, 520px);
  background: rgba(11,15,25,0.90);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 24px;
  padding: 26px;
  text-align: center;
  box-shadow: 0 30px 80px rgba(0,0,0,0.45);
}
.hq-loading-card {
  width: min(92vw, 420px);
  background: rgba(11,15,25,0.92);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 24px;
  padding: 28px 26px;
  text-align: center;
  box-shadow: 0 30px 80px rgba(0,0,0,0.45);
  justify-items: center;
}
.hq-loading-eyebrow {
  color: #cbd5e1;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 12px;
  font-weight: 900;
}
.hq-loading-title {
  margin-top: 10px;
  color: #fff;
  font-size: clamp(24px, 3vw, 32px);
  font-weight: 950;
  letter-spacing: -0.02em;
}
.hq-loading-copy {
  margin-top: 14px;
  color: var(--muted);
  line-height: 1.55;
  font-weight: 700;
}
.hq-loading-spinner {
  width: 66px;
  height: 66px;
  margin-top: 18px;
  border-radius: 999px;
  border: 6px solid rgba(255,255,255,0.10);
  border-top-color: #2df19a;
  border-right-color: #39c8ff;
  box-shadow: 0 0 0 6px rgba(255,255,255,0.03);
  animation: hqLoadingSpin 0.9s linear infinite;
}
@keyframes hqLoadingSpin {
  to { transform: rotate(360deg); }
}
.hq-eyebrow {
  color: #cbd5e1;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 12px;
  font-weight: 800;
}
.hq-copy, .rotate-copy { color: var(--muted); line-height: 1.6; }
.hq-entry-actions{display:flex;flex-direction:column;gap:10px;margin-top:10px}
.hq-primary-btn,
.hq-secondary-btn {
  border: 0;
  border-radius: 16px;
  padding: 14px 18px;
  font-weight: 900;
  cursor: pointer;
}
.hq-primary-btn {
  background: #fff;
  color: #0f172a;
}
.hq-secondary-btn {
  background: rgba(255,255,255,0.12);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.18);
}
.rotate-card { width: min(90vw, 360px); }
.rotate-icon { font-size: 42px; margin-bottom: 12px; }
.rotate-title { font-size: 24px; font-weight: 900; }

@media (max-width: 980px) {
  .touch-controls { display: flex; }
  .chat-hint { display: none; }
  .chat-history-btn { display: inline-flex; align-items:center; justify-content:center; }
  .chat-history-panel { left: 10px; width: calc(100% - 20px); bottom: 64px; }
  .hq-stage {
    width: min(calc(100vw - 12px), calc((100vh - 12px - var(--safe-t) - var(--safe-b)) * (16 / 9)));
    border-radius: 18px;
  }
  .hq-back-link { padding: 8px 11px; font-size: 12px; }
}


.players-layer{position:absolute;inset:0;pointer-events:none;z-index:29}
.player--remote{z-index:29}
.hud-stack{position:absolute;left:14px;top:14px;z-index:75;display:flex;flex-direction:column;gap:10px;pointer-events:none}
.map-info-card{min-width:200px;padding:12px 14px;border-radius:16px;background:rgba(8,12,20,.76);border:1px solid rgba(255,255,255,.12);backdrop-filter:blur(10px);box-shadow:0 12px 24px rgba(0,0,0,.25);font-size:12px;font-weight:800;color:#fff}
.map-info-card__title{font-size:16px;font-weight:950;letter-spacing:.01em;margin-bottom:7px;max-width:230px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.map-info-card__row{display:flex;justify-content:space-between;gap:16px;align-items:center;padding:3px 0;color:rgba(255,255,255,.72)}
.map-info-card__row strong{color:#fff;text-align:right;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.conn-status{align-self:flex-start;padding:8px 12px;border-radius:999px;background:rgba(8,12,20,.76);border:1px solid rgba(255,255,255,.12);font-size:12px;font-weight:800;backdrop-filter:blur(10px);pointer-events:none}
.conn-status.is-good{color:#86efac}
.conn-status.is-bad{color:#fca5a5}
.bottom-bars-hud{position:absolute;left:14px;right:14px;bottom:12px;z-index:95;display:flex;align-items:center;gap:10px;pointer-events:none}
.bottom-status-bar{height:52px;padding:0;border-radius:999px;background:rgba(255,255,255,.92);border:2px solid rgba(23,104,170,.62);box-shadow:0 12px 30px rgba(10,120,145,.14);backdrop-filter:blur(12px);color:#fff;font-size:12px;font-weight:950;overflow:hidden}
.bottom-status-bar__track{position:relative;height:100%;border-radius:999px;background:#02070a;border:4px solid #1768aa;box-shadow:inset 0 0 0 2px rgba(0,0,0,.65), 0 2px 10px rgba(23,104,170,.18);overflow:hidden}
.bottom-status-bar__fill{position:absolute;left:0;top:0;height:100%;width:0%;border-radius:999px;transition:width .12s linear}
.bottom-status-bar__inside{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:0 14px;text-shadow:0 2px 3px rgba(0,0,0,.9),0 0 8px rgba(0,0,0,.7);letter-spacing:.01em;z-index:2;white-space:nowrap}
.bottom-status-bar--exp{flex:1 1 520px;max-width:680px}
.bottom-status-bar--hp{flex:0 1 260px;max-width:330px}
.bottom-status-bar--mp{flex:0 1 260px;max-width:330px}
.bottom-status-bar--exp .bottom-status-bar__fill{background:#25e121;box-shadow:inset 18px 0 0 rgba(255,255,255,.16), inset 52px 0 0 rgba(255,255,255,.13), inset 86px 0 0 rgba(255,255,255,.10), inset 120px 0 0 rgba(255,255,255,.08)}
.bottom-status-bar--hp .bottom-status-bar__track{border-color:#08242c}
.bottom-status-bar--hp .bottom-status-bar__fill{background:#b10000}
.bottom-status-bar--mp .bottom-status-bar__track{border-color:#08242c}
.bottom-status-bar--mp .bottom-status-bar__fill{background:#1646d9}
.bottom-resource-pill{height:52px;min-width:88px;display:flex;align-items:center;justify-content:center;gap:4px;padding:0 14px;border-radius:999px;background:rgba(8,12,20,.82);border:1px solid rgba(255,255,255,.16);box-shadow:0 12px 30px rgba(0,0,0,.22);backdrop-filter:blur(12px);color:#fff;font-size:13px;font-weight:950;white-space:nowrap}
.bottom-resource-pill--pots{min-width:128px}
@media (max-width: 980px){.hud-stack{left:10px;top:10px}.map-info-card{min-width:180px;padding:10px 12px}.map-info-card__title{font-size:13px}.map-info-card__row{font-size:10px;padding:2px 0}.bottom-bars-hud{left:8px;right:8px;bottom:8px;gap:6px}.bottom-status-bar{height:42px;font-size:10px}.bottom-status-bar__track{border-width:3px}.bottom-status-bar--exp{flex-basis:38%}.bottom-status-bar--hp,.bottom-status-bar--mp{flex-basis:23%}.bottom-resource-pill{height:42px;min-width:54px;padding:0 8px;font-size:10px}.bottom-resource-pill--pots{min-width:84px}}

.hq-scene{position:absolute;left:0;top:0;width:1280px;height:720px;will-change:transform;overflow:hidden}
.platform-layer,.rope-layer,.portal-layer,.monster-layer,.drop-layer,.projectile-layer,.players-layer,.map-visual-layer{position:absolute;inset:0;pointer-events:none}
.map-visual-layer--back{z-index:24}
.platform-layer{z-index:25}
.rope-layer{z-index:26}
.monster-layer{z-index:27}
.drop-layer{z-index:28}
.projectile-layer{z-index:28}
.players-layer{z-index:29}
/* 70, not 30: the combat block below pins players/monsters to 60 !important, so
   builder "In front" visuals must clear that or the player never walks behind them */
.map-visual-layer--front{z-index:70}
.portal-layer{z-index:33;pointer-events:auto}
.portal{position:absolute;width:250px;height:340px;transform:translate(-50%,0);cursor:pointer;filter:drop-shadow(0 12px 28px rgba(0,0,0,.42));}
.portal img{width:100%;height:100%;object-fit:contain;display:block}
.portal-prompt{position:absolute;left:50%;bottom:100%;transform:translate(-50%,-10px);padding:9px 14px;border-radius:999px;background:rgba(255,255,255,.96);color:#0f172a;font-size:13px;font-weight:900;white-space:nowrap;box-shadow:0 10px 24px rgba(0,0,0,.28)}
.monster{position:absolute;display:flex;align-items:flex-end;justify-content:center;filter:drop-shadow(0 10px 20px rgba(0,0,0,.35));transform-origin:center bottom}
.monster img{display:block;width:100%;height:100%;object-fit:contain;transform-origin:center bottom}
.monster-hp{position:absolute;left:50%;bottom:100%;transform:translate(-50%,-8px);width:86px;height:10px;border-radius:999px;background:rgba(0,0,0,.55);overflow:hidden;border:1px solid rgba(255,255,255,.12)}
.monster-hp-fill{height:100%;background:linear-gradient(90deg,#ef4444,#f97316)}
.monster--hurt img{filter:brightness(1.3) saturate(1.15)}
/* TShirtTube product cards: a gentle hop so the shirts feel alive as they roam the shop. */
@keyframes tshirtCardHop { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-30px)} }
.monster.monster--product-card{animation:tshirtCardHop 1.5s ease-in-out infinite;will-change:transform}
.monster.monster--product-card .monster-body-img{filter:drop-shadow(0 16px 22px rgba(0,0,0,.42))}
/* Kill the shirt -> its clipart design pops off as its own monster: burst flash + the
   loose design darts around with a glow (and stops hopping). */
.monster--pop::after{content:'';position:absolute;inset:-12%;border-radius:16px;pointer-events:none;z-index:2;background:radial-gradient(circle,rgba(255,255,255,.6),rgba(124,58,237,.28) 45%,transparent 70%);animation:tshirtPopBurst .55s ease-out forwards}
@keyframes tshirtPopBurst{0%{opacity:.9;transform:scale(.4)}100%{opacity:0;transform:scale(1.65)}}
.monster.monster--product-card.monster--design-phase{animation:none}
.monster--design-phase .monster-body-img{filter:drop-shadow(0 0 10px rgba(124,58,237,.8)) drop-shadow(0 8px 14px rgba(0,0,0,.4))}
@media (max-width:980px){.portal{width:220px;height:300px}.monster-hp{width:72px;height:9px}}

.drop-layer{position:absolute;inset:0;pointer-events:none;z-index:26}
.drop{position:absolute;width:40px;height:40px;transform:translate(-50%,0);filter:drop-shadow(0 6px 14px rgba(0,0,0,.35));}
.drop img{width:100%;height:100%;object-fit:contain;display:block}
.hp-hud__inv{margin-top:8px;font-size:12px;font-weight:800;color:rgba(248,250,252,.82)}
.exp-hud{min-width:230px;padding:12px 14px;border-radius:16px;background:rgba(8,12,20,.76);border:1px solid rgba(255,255,255,.12);backdrop-filter:blur(10px);box-shadow:0 12px 24px rgba(0,0,0,.25)}
.exp-hud__row{display:flex;justify-content:space-between;gap:12px;align-items:center;margin-bottom:8px;font-size:13px;font-weight:800}
.exp-hud__bar{height:10px;border-radius:999px;background:rgba(255,255,255,.08);overflow:hidden;border:1px solid rgba(255,255,255,.08)}
.exp-hud__fill{height:100%;width:0%;border-radius:999px;background:linear-gradient(90deg,#22c55e,#a3e635);box-shadow:0 0 16px rgba(163,230,53,.35)}
.touch-btn--potion{width:58px;height:58px;font-size:22px}
@media (max-width:980px){.exp-hud{min-width:180px;padding:10px 12px}.exp-hud__row{font-size:12px}.drop{width:34px;height:34px}}


.player-sprite-shell{
  position:absolute;
  left:50%;
  bottom:28px;
  width:280px;
  height:430px;
  transform:translateX(-50%);
  margin:0;
  pointer-events:none;
  overflow:visible;
}
.player-layer{
  position:absolute;
  left:50%;
  bottom:0;
  width:0;
  height:0;
  overflow:visible;
  pointer-events:none;
}
.player-layer img{
  position:absolute;
  left:0;
  bottom:0;
  display:block;
  max-width:none;
  width:auto;
  height:auto;
  object-fit:contain;
  transform-origin:center bottom;
  pointer-events:none;
  filter:drop-shadow(0 10px 24px rgba(0,0,0,.35));
}
.player-layer--body{z-index:2}
.player-layer--head{z-index:3}
.player-layer--weapon{z-index:4}
.player-layer--headwear{z-index:5}

.player--hurt{animation:playerHurtDimFlicker .18s steps(2,end) infinite}
.player--hurt .player-sprite,
.player--hurt .player-layer img{filter:brightness(.55) opacity(.58) drop-shadow(0 10px 24px rgba(0,0,0,.35))}
@keyframes playerHurtDimFlicker{
  0%,100%{opacity:.42}
  50%{opacity:1}
}

.player--layered .player-name{
  bottom:-30px;   /* below the feet, matching the base nameplate position */
}
.player--layered .player-bubble{
  bottom: 250px;
  max-width: 22ch;   /* match the base bubble: ~22 chars per line, stacks upward */
}
.player--layered .player-bubble::after{
  top: 100%;
}

.char-builder-overlay{
  position:fixed;
  inset:0;
  z-index:140;
  display:grid;
  place-items:center;
  background:rgba(2,6,12,.82);
  backdrop-filter:blur(12px);
  padding:20px;
}
.char-builder-modal{
  width:min(1180px, 100%);
  max-height:calc(100dvh - 40px);
  overflow:auto;
  -webkit-overflow-scrolling:touch;
  background:linear-gradient(180deg, rgba(13,18,31,.98), rgba(8,12,22,.98));
  border:1px solid rgba(255,255,255,.12);
  border-radius:24px;
  box-shadow:0 30px 80px rgba(0,0,0,.45);
  padding:22px;
}
.char-builder-header{display:flex;justify-content:space-between;gap:18px;align-items:flex-start;position:sticky;top:-22px;z-index:2;padding:0 0 16px;background:linear-gradient(180deg, rgba(13,18,31,.98), rgba(13,18,31,.92));backdrop-filter:blur(10px)}
.char-builder-header h2{margin:6px 0 8px;font-size:32px;line-height:1.03}
.char-builder-header p{margin:0;color:rgba(248,250,252,.76);max-width:700px;line-height:1.5}
.char-builder-eyebrow{color:#cbd5e1;text-transform:uppercase;letter-spacing:.12em;font-size:12px;font-weight:800}
.char-builder-close{width:42px;height:42px;border-radius:12px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.08);color:#fff;font-size:20px;font-weight:800;flex:0 0 auto}
.char-builder-layout{display:grid;grid-template-columns:320px 1fr;gap:22px;margin-top:18px;align-items:start}
.char-builder-preview-wrap{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);border-radius:18px;padding:16px;position:sticky;top:72px}
.char-builder-preview-label{font-size:12px;font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:#cbd5e1;margin-bottom:10px}
.char-builder-preview{position:relative;width:100%;height:360px;border:1px dashed rgba(255,255,255,.12);border-radius:18px;overflow:hidden;background:radial-gradient(circle at top, rgba(59,130,246,.12), rgba(255,255,255,.02) 55%, rgba(255,255,255,.01) 100%)}
.char-builder-preview .player-sprite-shell{position:absolute;left:50%;bottom:28px;transform:translateX(-50%);width:280px;height:430px}
.char-builder-preview-note{margin-top:12px;font-size:12px;line-height:1.45;color:rgba(248,250,252,.68)}
.char-builder-slots{display:flex;flex-direction:column;gap:16px;min-width:0}
.char-builder-slot{padding:16px;border-radius:18px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07)}
.char-builder-slot h3{margin:0 0 10px;font-size:18px}
.char-builder-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:12px}
.char-builder-card{display:flex;flex-direction:column;gap:8px;align-items:center;justify-content:center;padding:12px;min-height:138px;border-radius:16px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);color:#fff;font-weight:800;text-align:center;cursor:pointer;transition:transform .14s ease,border-color .14s ease,background .14s ease,box-shadow .14s ease}
.char-builder-card:hover{transform:translateY(-1px);border-color:rgba(255,255,255,.22);background:rgba(255,255,255,.06)}
.char-builder-card img{width:88px;height:88px;object-fit:contain}
.char-builder-none-thumb{display:grid;place-items:center;width:88px;height:88px;border-radius:18px;background:rgba(255,255,255,.06);border:1px dashed rgba(255,255,255,.15);font-size:12px;line-height:1.2;padding:8px}
.char-builder-card.is-selected{border-color:#93c5fd;background:rgba(147,197,253,.15);box-shadow:0 0 0 1px rgba(147,197,253,.24) inset,0 12px 24px rgba(37,99,235,.12)}
.char-builder-empty{padding:16px;border-radius:14px;background:rgba(255,255,255,.04);color:rgba(248,250,252,.68)}
.char-builder-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:20px;position:sticky;bottom:-22px;padding:16px 0 0;background:linear-gradient(180deg, rgba(13,18,31,0), rgba(13,18,31,.94) 28%, rgba(13,18,31,.98) 100%)}
.char-builder-status{font-size:13px;line-height:1.4;color:#fda4af;min-height:18px;flex:1 1 auto}
.char-builder-save{height:52px;padding:0 22px;border:0;border-radius:14px;background:#fff;color:#0f172a;font-weight:900;flex:0 0 auto}
.char-builder-save[disabled]{opacity:.45}
@media (max-width:980px){
  .char-builder-overlay{padding:0;place-items:end center}
  .char-builder-modal{width:100%;max-height:100dvh;border-radius:24px 24px 0 0;padding:16px 14px calc(16px + var(--safe-b));}
  .char-builder-header{top:-16px;gap:12px;padding:0 0 12px}
  .char-builder-header h2{font-size:24px}
  .char-builder-header p{font-size:13px;max-width:none}
  .char-builder-layout{grid-template-columns:1fr;gap:14px;margin-top:10px}
  .char-builder-preview-wrap{position:relative;top:auto;padding:12px}
  .char-builder-preview{height:260px;max-width:320px;margin:0 auto}
  .char-builder-preview .player-sprite-shell{width:220px;height:330px;bottom:16px}
  .char-builder-slot{padding:12px}
  .char-builder-slot h3{font-size:16px;margin-bottom:8px}
  .char-builder-grid{grid-template-columns:repeat(3, minmax(0, 1fr));gap:10px}
  .char-builder-card{min-height:112px;padding:10px;border-radius:14px;font-size:12px}
  .char-builder-card img,.char-builder-none-thumb{width:64px;height:64px}
  .char-builder-actions{bottom:calc(-16px - var(--safe-b));padding:12px 0 0;flex-direction:column;align-items:stretch}
  .char-builder-save{width:100%}
}
@media (max-width:640px){
  .char-builder-grid{grid-template-columns:repeat(2, minmax(0, 1fr))}
}

.hq-account-card{
  margin-top:16px;
  padding:16px;
  border-radius:20px;
  background:rgba(255,255,255,0.06);
  border:1px solid rgba(255,255,255,0.10);
  text-align:left;
}
.hq-account-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.hq-account-eyebrow{font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:rgba(248,250,252,.6)}
.hq-account-status{margin-top:6px;color:rgba(248,250,252,.82);line-height:1.45;font-size:13px}
.hq-signed-in-box{margin-top:12px}
.hq-signed-in-pill{display:inline-flex;align-items:center;gap:6px;padding:10px 12px;border-radius:999px;background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.10);font-size:13px;font-weight:700}
.hq-auth-actions{display:flex;gap:10px;margin-top:14px}
.hq-ghost-btn,.hq-inline-link,.hq-primary-btn--small{cursor:pointer}
.hq-ghost-btn{
  flex:1;
  border-radius:16px;
  padding:14px 18px;
  font-weight:900;
  color:#fff;
  background:transparent;
  border:1px solid rgba(255,255,255,.18);
}
.hq-inline-link{
  border:0;
  background:transparent;
  color:#cbd5e1;
  font-weight:800;
  padding:10px 0;
}
.hq-auth-form{margin-top:14px}
.hq-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.hq-field{display:flex;flex-direction:column;gap:6px}
.hq-field span{font-size:12px;font-weight:800;color:rgba(248,250,252,.72)}
.hq-field input{
  width:100%;
  border-radius:14px;
  border:1px solid rgba(255,255,255,.12);
  background:rgba(2,6,12,.64);
  color:#fff;
  padding:12px 14px;
  outline:none;
}
.hq-field input:focus{border-color:rgba(255,255,255,.28);box-shadow:0 0 0 3px rgba(255,255,255,.06)}
.hq-field--full{grid-column:1 / -1}
.hq-form-actions{display:flex;align-items:center;gap:12px;margin-top:12px}
.hq-primary-btn--small{padding:12px 16px;min-width:160px}
.hq-auth-message{margin-top:12px;padding:10px 12px;border-radius:14px;background:rgba(255,255,255,.08);color:#e2e8f0;font-size:13px;font-weight:700}
.hq-auth-message.is-error{background:rgba(127,29,29,.55);color:#fecaca;border:1px solid rgba(248,113,113,.22)}
.hq-auth-message.is-success{background:rgba(20,83,45,.55);color:#bbf7d0;border:1px solid rgba(74,222,128,.22)}
button:disabled{cursor:not-allowed;opacity:.65}

@media (max-width: 680px){
  .hq-panel{padding:18px}
  .hq-auth-actions,.hq-form-actions,.hq-account-head{flex-direction:column;align-items:stretch}
  .hq-form-grid{grid-template-columns:1fr}
  .hq-field--full{grid-column:auto}
}

.hq-google-btn {
  width: 100%;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(255,255,255,0.08);
  color: #fff;
  border-radius: 16px;
  padding: 14px 16px;
  font-weight: 800;
  cursor: pointer;
  transition: background 0.16s ease, transform 0.16s ease, border-color 0.16s ease;
}
.hq-google-btn:hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.24);
}
.hq-google-btn:active {
  transform: translateY(1px);
}
.hq-google-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.hq-google-btn--inline {
  width: auto;
  min-width: 190px;
}
@media (max-width: 680px){
  .hq-google-btn--inline { width: 100%; }
}


/* ---- iPhone landscape / portrait lock fixes ---- */
.rotate-overlay {
  background: #000;
}
.rotate-card {
  border: none;
  background: transparent;
  box-shadow: none;
}
.rotate-title {
  font-size: 20px;
}
.rotate-copy {
  font-size: 14px;
  opacity: 0.7;
}

@media (max-width: 980px) and (orientation: landscape) {
  .touch-controls {
    left: 10px !important;
    right: 10px !important;
    bottom: calc(10px + var(--safe-b)) !important;
  }

  .touch-pad {
    gap: 8px;
  }

  .touch-btn {
    width: 48px;
    height: 48px;
    font-size: 18px;
  }

  .touch-btn--jump {
    width: 64px;
    height: 64px;
  }

  .touch-btn--attack {
    width: 64px;
    height: 64px;
    font-size: 24px;
  }

  .touch-btn--melee {
    width: 46px;
    height: 46px;
  }

  .touch-btn--chat {
    width: 44px;
    height: 44px;
  }

  .touch-stick {
    width: 104px;
    height: 104px;
  }

  .touch-stick-nub {
    width: 46px;
    height: 46px;
  }

  .hq-stage {
    overflow: hidden;
  }

  body {
    overflow: hidden;
  }
}


/* ---- pre-game mobile auth layout fix ---- */
html.hq-prestart-mobile,
body.hq-prestart-mobile {
  overflow: auto;
}

html.hq-prestart-mobile .hq-shell,
body.hq-prestart-mobile .hq-shell {
  overflow-y: auto;
  touch-action: auto;
}

html.hq-prestart-mobile .hq-frame,
body.hq-prestart-mobile .hq-frame {
  display: block;
  padding: max(10px, var(--safe-t)) 10px max(18px, var(--safe-b)) 10px;
}

html.hq-prestart-mobile .hq-stage,
body.hq-prestart-mobile .hq-stage {
  width: 100%;
  min-height: calc(var(--app-height, 100dvh) - var(--safe-t) - var(--safe-b) - 20px);
  aspect-ratio: auto;
  height: auto;
  overflow: visible;
  border-radius: 18px;
}

html.hq-prestart-mobile .hq-world,
body.hq-prestart-mobile .hq-world {
  display: none !important;
}

html.hq-prestart-mobile .hq-overlay,
body.hq-prestart-mobile .hq-overlay {
  position: relative;
  inset: auto;
  min-height: 0;
  opacity: 1;
  pointer-events: auto;
  background: transparent;
  backdrop-filter: none;
  place-items: start center;
  padding-top: 66px;
  padding-bottom: calc(18px + var(--safe-b));
}

html.hq-prestart-mobile .hq-panel,
body.hq-prestart-mobile .hq-panel {
  width: min(100%, 720px);
  max-height: none;
  text-align: left;
  padding: 20px;
}

html.hq-prestart-mobile .hq-topbar,
body.hq-prestart-mobile .hq-topbar {
  position: sticky;
  top: max(10px, var(--safe-t));
  z-index: 130;
}

html.hq-prestart-mobile .touch-controls,
body.hq-prestart-mobile .touch-controls,
html.hq-prestart-mobile .chat-dock,
body.hq-prestart-mobile .chat-dock,
html.hq-prestart-mobile .hud-stack,
body.hq-prestart-mobile .hud-stack {
  display: none !important;
}

@media (max-width: 980px) and (orientation: portrait) {
  html.hq-prestart-mobile .hq-stage,
  body.hq-prestart-mobile .hq-stage {
    box-shadow: none;
    border: none;
    background: transparent;
  }

  html.hq-prestart-mobile .hq-panel,
  body.hq-prestart-mobile .hq-panel {
    border-radius: 20px;
  }
}


.hq-economy-dock {
  /* bottom-right column, clear of the top-right utility stack and video panel */
  position: fixed;
  bottom: 88px;
  right: 18px;
  top: auto;
  z-index: 9000;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}
.hq-economy-btn {
  border: 1px solid rgba(255,255,255,0.14);
  background: rgba(7,10,18,0.82);
  color: #fff;
  border-radius: 14px;
  padding: 10px 14px;
  font-weight: 800;
  cursor: pointer;
  backdrop-filter: blur(10px);
}
.hq-economy-btn--primary {
  background: linear-gradient(90deg,#6ea8fe,#9b6bff);
  border: 0;
}
.hq-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.62);
  z-index: 12000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.hq-modal-backdrop[hidden] { display:none !important; }
.hq-modal-box {
  width: min(560px,92vw);
  max-height: 86vh;
  overflow: auto;
  background: linear-gradient(180deg,#101a31,#0a1122);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 20px;
  box-shadow: 0 20px 60px rgba(0,0,0,.45);
  padding: 18px;
  color:#eef3ff;
}
.hq-modal-head {
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:12px;
  margin-bottom:14px;
}
.hq-modal-head h2 { margin:0; font-size:22px; }
.hq-modal-close {
  background:#1a2a52;
  color:#fff;
  border:1px solid rgba(255,255,255,.12);
  border-radius:12px;
  padding:10px 14px;
  cursor:pointer;
}
.hq-modal-coins { font-size:14px; color:#cfe2ff; margin-bottom: 10px; }
.hq-shop-list { display:grid; gap:12px; }
.hq-shop-item {
  display:grid;
  grid-template-columns: 64px minmax(0,1fr) auto auto;
  gap:12px;
  align-items:center;
  padding:12px 14px;
  border-radius:16px;
  background:rgba(255,255,255,.04);
  border:1px solid rgba(255,255,255,.08);
}
.hq-shop-item-icon {
  width:64px; height:64px; border-radius:12px; background:rgba(255,255,255,.06); display:flex; align-items:center; justify-content:center;
}
.hq-shop-item-icon img { width:54px; height:54px; object-fit:contain; image-rendering:auto; }
.hq-shop-meta,.hq-item-meta{font-size:13px;color:#a8b7d9}
.hq-shop-price{font-size:14px;font-weight:800;color:#fff}
.hq-shop-buy{background:linear-gradient(90deg,#6ea8fe,#9b6bff);border:0;color:#fff;border-radius:12px;padding:10px 14px;font-weight:700;cursor:pointer}
.hq-shop-buy[disabled]{opacity:.45;cursor:not-allowed}
.hq-inventory-box {
  width: min(440px, 94vw);
  padding: 0;
  overflow: hidden;
  background: linear-gradient(180deg,#1e335f,#102145);
}
.hq-inventory-frame { padding: 10px; }
.hq-inventory-titlebar {
  display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:8px;
}
.hq-inventory-title { font-size:18px; font-weight:900; }
.hq-inventory-tabs { display:flex; gap:6px; margin-bottom:10px; flex-wrap: wrap; }
.hq-inventory-tab {
  border:1px solid rgba(255,255,255,.12);
  background:rgba(255,255,255,.08);
  color:#fff; border-radius:8px; padding:6px 10px; font-size:12px; font-weight:800;
}
.hq-inventory-tab.is-active { background:#f37b7b; border-color:#ffb0b0; }
.hq-inventory-panel { background: rgba(255,255,255,.04); border-radius: 12px; padding: 10px; }
.hq-inventory-grid {
  display:grid;
  grid-template-columns: repeat(4, 1fr);
  gap:8px;
  margin-top:10px;
}
.hq-inventory-slot {
  aspect-ratio:1/1;
  border-radius: 10px;
  border:1px solid rgba(255,255,255,.12);
  background: linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.04));
  position:relative;
}
.hq-inventory-slot.has-item { cursor: grab; }
.hq-inventory-slot-icon {
  width: 100%; height: 100%; object-fit: contain; padding: 8px; user-select:none; pointer-events:none;
}
.hq-inventory-slot-count {
  position:absolute; right:6px; bottom:4px; color:#fff; font-weight:900; font-size:13px; text-shadow:0 1px 3px rgba(0,0,0,.8);
}
.hq-inventory-help { margin-top: 10px; font-size: 12px; color: #cfe2ff; }
.hq-qty-box { width: min(360px, 92vw); }
.hq-qty-label { margin-bottom: 10px; color: #cfe2ff; }
.hq-qty-range { width: 100%; }
.hq-qty-readout { margin-top: 12px; text-align: center; font-size: 28px; font-weight: 900; }
.hq-qty-actions { margin-top: 16px; display:flex; justify-content:flex-end; gap:10px; }
.drop img { width: 46px; height: 46px; object-fit: contain; }


.hq-floating-window {
  position: fixed;
  z-index: 12000;
  width: min(440px, 94vw);
}
.hq-floating-window[hidden] { display: none !important; }
.hq-floating-window .hq-inventory-box {
  width: 100%;
  max-height: min(78vh, 620px);
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
}
.hq-floating-window .hq-inventory-titlebar {
  cursor: grab;
  user-select: none;
  touch-action: none;
}
.hq-floating-window.is-dragging .hq-inventory-titlebar { cursor: grabbing; }
.hq-floating-window .hq-inventory-panel {
  max-height: calc(min(78vh, 620px) - 116px);
  overflow: auto;
}
.hq-inventory-slot { overflow: hidden; }
.hq-inventory-slot.has-item:hover {
  border-color: rgba(255,255,255,.28);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.08), 0 8px 20px rgba(0,0,0,.22);
}
.hq-inventory-slot.has-item:active { cursor: grabbing; }
.hq-inventory-slot-icon { image-rendering: auto; }

.platform-surface{position:absolute;transform:translate(0,0);border-radius:12px;border:2px dashed rgba(75,58,39,.95);box-shadow:inset 0 1px 0 rgba(255,255,255,.14),0 10px 22px rgba(0,0,0,.24);background:linear-gradient(180deg,#a88a61,#6c553a)}
.platform-surface--solid{border-style:solid}
.rope-surface{position:absolute;border-radius:999px;background:repeating-linear-gradient(180deg,#b88952 0,#b88952 12px,#7b5427 12px,#7b5427 24px);box-shadow:0 8px 18px rgba(0,0,0,.18)}
/* Ladder: two rails at the box edges, a rung every 34px. !important because the
   home map restyles every .rope-surface with !important. */
.rope-surface.rope-surface--ladder{border-radius:4px !important;background:linear-gradient(90deg,#6b4520 0 8px,transparent 8px calc(100% - 8px),#6b4520 calc(100% - 8px)),repeating-linear-gradient(180deg,transparent 0 26px,#a8743d 26px 34px) !important;box-shadow:0 8px 18px rgba(0,0,0,.22) !important}

.player-attack-fx{position:absolute;pointer-events:none;z-index:9;overflow:visible;filter:drop-shadow(0 0 12px rgba(255,255,255,.12));animation:hqAttackFxPulse .22s ease-out both;}
.player-attack-fx__arc,.player-attack-fx__burst{position:absolute;inset:0;border-radius:999px;pointer-events:none;}
.player-attack-fx__arc{transform:skewX(-16deg) rotate(-8deg);opacity:.96;}
.player-attack-fx__burst{inset:24% auto auto 54%;width:38%;height:52%;opacity:.74;}
@keyframes hqAttackFxPulse{0%{opacity:0;transform:scale(.72)}35%{opacity:1;transform:scale(1)}100%{opacity:.15;transform:scale(1.08)}}

.hq-inventory-slot--equip .hq-inventory-slot-icon{padding:6px;}
/* A garment with no drawing of its own -- a plain tee, plain shorts -- shows
   its COLOUR. The rig owns the picture and the item is only a hex, so without
   this the tile fell back to the unknown-item icon and the bag filled up with
   red potions. Inset and rounded so it reads as a swatch rather than as a
   broken image filling the cell. */
.hq-inventory-slot-tinted{
  box-sizing:border-box;
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
  padding:8px;
}
.hq-inventory-slot-swatch{
  box-sizing:border-box;
  border-radius:8px;
  border:1px solid rgba(255,255,255,.28);
  box-shadow:inset 0 -6px 12px rgba(0,0,0,.35);
}
.hq-inventory-slot-badge,.hq-inventory-slot-sub,.hq-inventory-slot-eq{position:absolute;left:6px;right:6px;font-weight:900;text-shadow:0 1px 3px rgba(0,0,0,.9);pointer-events:none}
.hq-inventory-slot-badge{top:6px;font-size:11px;color:#fef3c7;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hq-inventory-slot-sub{bottom:4px;font-size:11px;color:#dbeafe}
.hq-inventory-slot-eq{top:6px;left:auto;right:6px;width:auto;font-size:11px;color:#fde68a;background:rgba(0,0,0,.45);padding:2px 6px;border-radius:999px;border:1px solid rgba(255,255,255,.18)}
.hq-inventory-slot--equip.is-equipped{border-color:#facc15;box-shadow:inset 0 0 0 1px rgba(250,204,21,.28),0 0 0 1px rgba(250,204,21,.18),0 10px 24px rgba(250,204,21,.18)}
.hq-inventory-slot--equip.is-blocked{border-color:rgba(248,113,113,.55);box-shadow:inset 0 0 0 1px rgba(248,113,113,.18)}
.hq-inventory-slot--equip.is-blocked::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(248,113,113,.12),rgba(0,0,0,.18));pointer-events:none}

/* EXP Tube background video + cards */
.exp-bg-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  z-index: 2;
  pointer-events: none;
  filter: saturate(1.05) contrast(1.04) brightness(1);
  transition: opacity 220ms ease;
  background: transparent;
}
.exp-bg-video.is-playing { opacity: 1; }

/* ---- First Job: ability hotbar + advancement screen ---- */
.hq-jobbar {
  position: absolute;
  top: 14px;
  right: 132px;   /* compact cluster left of the Home/Settings utility stack */
  z-index: 10115;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 13px;
  border: 1px solid rgba(255,255,255,.16);
  background: rgba(6,10,20,.82);
  box-shadow: 0 10px 26px rgba(0,0,0,.34);
  backdrop-filter: blur(10px);
  pointer-events: auto;
}
.hq-jobbar-slot {
  position: relative;
  width: 42px;
  height: 42px;
  border-radius: 11px;
  border: 1px solid rgba(255,255,255,.2);
  background: linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.03));
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
  overflow: visible;
}
.hq-jobbar-slot:hover { border-color: rgba(140,255,236,.75); }
.hq-jobbar-slot.is-unlearned { filter: grayscale(1) brightness(.62); }
.hq-jobbar-slot--passive { cursor: default; border-style: dashed; }
.hq-jobbar-slot__icon { font-size: 20px; line-height: 1; pointer-events: none; }
.hq-jobbar-slot__img { width: 30px; height: 30px; object-fit: contain; display: block; pointer-events: none; }
.hq-jobbar-slot__key {
  position: absolute; top: -7px; left: -6px;
  min-width: 19px; height: 19px; padding: 0 5px;
  border-radius: 7px; background: #fff; color: #0f172a;
  font-size: 11px; font-weight: 1000; line-height: 19px;
  box-shadow: 0 3px 8px rgba(0,0,0,.35); pointer-events: none;
}
.hq-jobbar-slot__lvl {
  position: absolute; bottom: -7px; left: 50%; transform: translateX(-50%);
  padding: 1px 7px; border-radius: 999px;
  background: rgba(6,12,24,.94); border: 1px solid rgba(255,255,255,.22);
  font-size: 10px; font-weight: 1000; color: #a7f3d0; pointer-events: none; white-space: nowrap;
}
.hq-jobbar-slot__cd {
  position: absolute; inset: 0; border-radius: 12px;
  display: grid; place-items: center;
  font-size: 17px; font-weight: 1000; color: #fff;
  opacity: 0; pointer-events: none; transition: opacity 120ms ease;
}
.hq-jobbar-slot__plus {
  position: absolute; top: -9px; right: -8px;
  width: 21px; height: 21px; border-radius: 999px; border: 0;
  background: #22c55e; color: #052e16; font-size: 15px; font-weight: 1000; line-height: 1;
  cursor: pointer; box-shadow: 0 4px 10px rgba(34,197,94,.5);
  animation: hqJobSpPulse 1.1s infinite alternate;
}
.hq-jobbar-sp {
  margin-left: 2px; padding: 4px 9px; border-radius: 999px;
  background: rgba(34,197,94,.18); border: 1px solid rgba(34,197,94,.55);
  color: #86efac; font-size: 12px; font-weight: 1000; white-space: nowrap;
}
@keyframes hqJobSpPulse { from { transform: scale(1); } to { transform: scale(1.22); } }
/* ---- PHONES: the hotbar is a thumb target, not a keyboard legend ----
 *
 * It used to sit at bottom:156px, centred. On a landscape phone that is the
 * MIDDLE OF THE SCREEN — a slab of UI parked over the thing you are playing.
 *
 * It now sits on the bottom edge, in the gap between the two thumb clusters.
 * Those widths are measured, not guessed, from .touch-controls:
 *   left  14px inset + 58 + 10 + 58              = 140px  (move)
 *   right 14px inset + 52+10+74+10+56+10+74      = 300px  (chat/attack/melee/jump)
 * so the free band is the width minus ~464px with a little air either side.
 *
 * Wrapping rather than scrolling: reaching a skill mid-fight by scrolling a
 * strip is worse than a second row. max-height caps it so it can never grow
 * back up into the play area.
 */
/* ---- PHONES: chat is a popup, not a layout change ----
 *
 * .chat-dock is position:absolute INSIDE the game stage, lifted by
 * translateY(-var(--keyboard-inset)). That ties it to the stage, so when the
 * keyboard opened the whole screen appeared to shift and rescale instead of a
 * bar simply appearing.
 *
 * position:fixed takes it out of the stage entirely. The game behind it does
 * not move at all: the keyboard pushes nothing, the world is not re-fitted,
 * and only the bar travels. The inset becomes bottom spacing rather than a
 * transform, so it sits directly on top of the keyboard.
 */
body.hq-mobile-play .chat-dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  top: auto;
  transform: none;                                  /* no lift: fixed already stays put */
  padding-bottom: calc(var(--keyboard-inset) + 8px);
  transition: padding-bottom 0.16s ease;
  z-index: 10200;                                   /* above the hotbar and touch buttons */
}
body.hq-mobile-play .chat-bar {
  width: calc(100% - 16px);
  border-radius: 14px;
  padding: 7px 9px;
  gap: 7px;
}
body.hq-mobile-play .chat-label { display: none; }  /* the input placeholder says it */

/* The log never opens by itself on a phone — see open() in ui/chat.js. When
   the history button does open it, it is a sheet across the bottom rather than
   a floating card, so it cannot sit over the head bubbles. */
body.hq-mobile-play .chat-history-panel {
  position: fixed;
  left: 8px;
  right: 8px;
  bottom: calc(var(--keyboard-inset) + 64px);
  width: auto;
  max-height: 34vh;
  z-index: 10199;
}

body.hq-mobile-play .hq-jobbar {
  top: auto;
  right: auto;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(10px + var(--safe-b));
  max-width: calc(100% - 464px);
  max-height: 88px;
  overflow-y: auto;
  flex-wrap: wrap;
  justify-content: center;
  gap: 5px;
  padding: 5px 7px;
  border-radius: 11px;
}
body.hq-mobile-play .hq-jobbar-slot { width: 36px; height: 36px; border-radius: 9px; }
body.hq-mobile-play .hq-jobbar-slot__icon { font-size: 17px; }
body.hq-mobile-play .hq-jobbar-slot__img { width: 25px; height: 25px; }

/* The number badge is a KEYBOARD KEY. There is no keyboard on a phone, so it
   was labelling every skill with an instruction nobody could follow. The slot
   is already a <button> with a click handler — tapping it always worked. */
body.hq-mobile-play .hq-jobbar-slot__key { display: none; }

/* Level and MP cost are reference, not action, and at 36px neither is legible.
   Affordability still reads: .is-nomp desaturates the whole slot. */
body.hq-mobile-play .hq-jobbar-slot__lvl,
body.hq-mobile-play .hq-jobbar-slot__mp { display: none; }

/* Kept, because it is the only way to spend a skill point — but pulled inside
   the slot so a wrapped row cannot clip it. */
body.hq-mobile-play .hq-jobbar-slot__plus { top: -6px; right: -5px; width: 18px; height: 18px; font-size: 13px; }
body.hq-mobile-play .hq-jobbar-sp { padding: 3px 7px; font-size: 11px; }
/* Active buff tray (MapleStory-style): sits under the skill cluster, top right */
.hq-buff-tray {
  position: absolute;
  top: 68px;
  right: 132px;
  z-index: 10115;
  display: flex;
  gap: 6px;
  pointer-events: none;
}
.hq-buff {
  position: relative;
  width: 40px;
  height: 40px;
  border-radius: 11px;
  border: 1px solid rgba(52,211,153,.75);
  background: rgba(6,16,14,.86);
  box-shadow: 0 0 14px rgba(52,211,153,.45);
  display: grid;
  place-items: center;
  font-size: 20px;
  animation: hqBuffPulse 1s infinite alternate;
}
.hq-buff img { width: 30px; height: 30px; object-fit: contain; }
.hq-buff__timer {
  position: absolute; bottom: -7px; left: 50%; transform: translateX(-50%);
  padding: 0 6px; border-radius: 999px;
  background: rgba(3,10,8,.95); border: 1px solid rgba(52,211,153,.6);
  font-size: 10px; font-weight: 1000; color: #a7f3d0; white-space: nowrap;
}
@keyframes hqBuffPulse { from { box-shadow: 0 0 8px rgba(52,211,153,.35); } to { box-shadow: 0 0 20px rgba(52,211,153,.7); } }
.hq-jobbar-slot__mp {
  position: absolute; bottom: -7px; right: -7px;
  padding: 1px 6px; border-radius: 999px;
  background: rgba(30,64,175,.95); border: 1px solid rgba(147,197,253,.6);
  font-size: 9px; font-weight: 1000; color: #dbeafe; pointer-events: none; white-space: nowrap;
}
.hq-jobbar-slot.is-nomp { filter: saturate(.4) brightness(.6); }
.hq-jobbar-slot.is-nomp .hq-jobbar-slot__mp { background: rgba(127,29,29,.95); border-color: rgba(248,113,113,.7); color: #fecaca; }

.hq-jobadv-chip { border-color: rgba(250,204,21,.6) !important; animation: hqJobSpPulse 0.9s infinite alternate; }
.hq-jobadv-overlay {
  position: fixed; inset: 0; z-index: 10160;
  display: grid; place-items: center; padding: 20px;
  background: rgba(2,6,14,.66); backdrop-filter: blur(6px);
}
/* The card itself no longer scrolls. It is a fixed-height column — header,
   jobs, footer — and the SKILL LISTS scroll inside their own cards instead.
   Scrolling the whole card meant the "Become a ..." buttons sat below the fold
   and the header scrolled away from the choice it was explaining. */
.hq-jobadv-card {
  width: min(1080px, 96vw); max-height: 92vh;
  display: flex; flex-direction: column; min-height: 0;
  border-radius: 22px; border: 1px solid rgba(255,255,255,.16);
  background: linear-gradient(180deg, rgba(13,18,30,.98), rgba(7,11,20,.98));
  box-shadow: 0 30px 90px rgba(0,0,0,.6); padding: 22px; color: #fff;
}
.hq-jobadv-head { flex: 0 0 auto; }
.hq-jobadv-head h2 { margin: 0 0 6px; font-size: 26px; letter-spacing: -0.03em; }
.hq-jobadv-head p { margin: 0 0 16px; color: rgba(255,255,255,.78); font-size: 14px; }

/* auto-fit rather than a hardcoded column count: this was `1fr 1fr` and the
   third job silently wrapped onto a second row, half-width, under the other
   two. A fourth job would have done the same again. */
.hq-jobadv-jobs {
  flex: 1 1 auto; min-height: 0;
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  align-items: stretch;
}
@media (max-width: 900px) { .hq-jobadv-jobs { grid-template-columns: 1fr; overflow-y: auto; } }

/* Every card is the same height whatever its kit: header pinned top, button
   pinned bottom, list absorbing the difference. Candy Dealer has eleven skills
   and Knight has none, and without this they were wildly different objects. */
.hq-jobadv-job {
  border-radius: 16px; border: 1px solid rgba(255,255,255,.14);
  background: rgba(255,255,255,.05); padding: 14px;
  display: flex; flex-direction: column; min-height: 0;
}
.hq-jobadv-job.is-disabled { opacity: .55; }
.hq-jobadv-job h3 { flex: 0 0 auto; margin: 0 0 10px; font-size: 19px; }
.hq-jobadv-job ul {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  list-style: none; margin: 0 0 12px; padding: 0 6px 0 0;
  display: grid; gap: 9px; align-content: start;
  /* A thin, dim scrollbar: the list scrolling is information, but it should not
     compete with the artwork of the cards. */
  scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.24) transparent;
}
.hq-jobadv-job ul::-webkit-scrollbar { width: 6px; }
.hq-jobadv-job ul::-webkit-scrollbar-thumb { background: rgba(255,255,255,.24); border-radius: 999px; }
.hq-jobadv-job li { display: grid; grid-template-columns: 26px auto; gap: 2px 8px; font-size: 13px; }
.hq-jobadv-job li i { grid-row: span 2; font-style: normal; font-size: 19px; }
.hq-jobadv-job li b { color: #fff; }
.hq-jobadv-job li span { grid-column: 2; color: rgba(255,255,255,.66); font-size: 12px; line-height: 1.35; }
/* Full width, not squeezed into the 26px icon column. As a plain <li> it
   inherited the icon grid above and wrapped one word per line. */
.hq-jobadv-soon {
  display: block; grid-template-columns: none;
  padding: 18px 6px; text-align: center;
  color: rgba(255,255,255,.55); font-size: 13px;
}
.hq-jobadv-pick {
  flex: 0 0 auto;
  width: 100%; height: 44px; border-radius: 12px; border: 0;
  background: linear-gradient(135deg, #34d399, #22c55e); color: #052e16;
  font-size: 14px; font-weight: 1000; cursor: pointer;
}
.hq-jobadv-pick:disabled { background: rgba(255,255,255,.14); color: rgba(255,255,255,.5); cursor: not-allowed; }
.hq-jobadv-later {
  flex: 0 0 auto; align-self: flex-start;
  margin-top: 12px; height: 38px; padding: 0 16px; border-radius: 999px;
  border: 1px solid rgba(255,255,255,.2); background: transparent; color: rgba(255,255,255,.75);
  font-weight: 900; cursor: pointer;
}

/* Minimap (top-left radar) + World Map overlay */
.hq-minimap {
  position: absolute;
  top: 46px;
  left: 12px;
  z-index: 10110;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,.18);
  overflow: hidden;
  background: rgba(4,10,22,.55);
  box-shadow: 0 10px 26px rgba(0,0,0,.32);
  pointer-events: none;
}
.hq-minimap canvas { display: block; }
.hq-minimap__label {
  padding: 3px 8px 4px;
  font-size: 10px;
  font-weight: 900;
  color: rgba(255,255,255,.82);
  background: rgba(2,6,14,.8);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 200px;
}
body.hq-mobile-play .hq-minimap { display: none; }   /* phones: keep the screen clear */
.hq-worldmap-overlay {
  position: fixed; inset: 0; z-index: 10150;
  display: grid; place-items: center; padding: 20px;
  background: rgba(2,6,14,.6); backdrop-filter: blur(5px);
}
.hq-worldmap-card {
  width: min(520px, 94vw); max-height: 84vh; overflow: auto;
  border-radius: 20px; border: 1px solid rgba(255,255,255,.16);
  background: linear-gradient(180deg, rgba(13,18,30,.98), rgba(7,11,20,.98));
  box-shadow: 0 30px 90px rgba(0,0,0,.55); padding: 18px; color: #fff;
}
.hq-worldmap-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.hq-worldmap-head h2 { margin: 0; font-size: 24px; letter-spacing: -.02em; }
.hq-worldmap-close { width: 34px; height: 34px; border-radius: 999px; border: 1px solid rgba(255,255,255,.18); background: rgba(255,255,255,.08); color: #fff; font-weight: 900; cursor: pointer; }
.hq-worldmap-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 12px; margin-bottom: 6px;
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.08);
}
.hq-worldmap-row b { flex: 1; font-size: 14px; }
.hq-worldmap-row span { font-size: 12px; color: #93c5fd; font-weight: 900; white-space: nowrap; }
.hq-worldmap-row em { font-style: normal; font-size: 10px; font-weight: 1000; color: #052e16; background: #34d399; border-radius: 999px; padding: 2px 8px; white-space: nowrap; }
.hq-worldmap-row.is-here { border-color: rgba(52,211,153,.6); background: rgba(52,211,153,.10); }
.hq-worldmap-note { margin: 10px 0 0; font-size: 12px; color: rgba(255,255,255,.55); }

/* Monster nameplate: shows under a monster once it's been attacked */
.monster-name {
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  padding: 2px 9px;
  border-radius: 999px;
  background: rgba(3,8,18,.78);
  border: 1px solid rgba(255,255,255,.22);
  color: #eafff5;
  font-size: 12px;
  font-weight: 900;
  white-space: nowrap;
  pointer-events: none;
  z-index: 3;
}
.monster-name--danger {
  color: #fecaca;
  border-color: rgba(248,113,113,.75);
  background: rgba(60,7,12,.82);
  box-shadow: 0 0 10px rgba(248,113,113,.35);
}
.monster--defeated .monster-name { display: none; }

/* Candy Rush aura + Sugar Bomb projectile */
.player--rush .player-sprite,
.player--rush .char-layer-stack { filter: drop-shadow(0 0 14px rgba(52,211,153,.85)) saturate(1.15); }
.player--rush::after {
  content: '⚡';
  position: absolute; top: -14px; right: -4px; font-size: 20px;
  animation: hqJobSpPulse .5s infinite alternate; pointer-events: none;
}
.projectile-sugar-bomb {
  display: block; font-size: 34px; line-height: 1;
  filter: drop-shadow(0 0 10px rgba(244,114,182,.9));
  animation: hqSugarSpin .5s linear infinite;
}
@keyframes hqSugarSpin { to { transform: rotate(360deg); } }
/* Admin-uploaded skill projectile art (Skills admin) */
.projectile-art { display: block; width: 44px; height: 44px; object-fit: contain; filter: drop-shadow(0 4px 10px rgba(0,0,0,.35)); }
.projectile-art--bomb { width: 100%; height: 100%; animation: hqSugarSpin .9s linear infinite; }
/* Giant thrown backpack: the container itself must grow — the duckies container
   rules (76x36 + img 100%) outrank any class on the img alone */
.projectile.projectile--bomb-art { width: 460px; height: 460px; }
.projectile.projectile--bomb-art img { width: 100%; height: 100%; object-fit: contain; }
/* Backpack Burst: candy shrapnel flies FAR with green/red/blue glows
   (uploaded PNGs are transparent, the glow sells the hit) */
.candy-burst-piece {
  position: absolute;
  z-index: 29;
  font-size: 38px;
  line-height: 1;
  pointer-events: none;
  transform: translate(-50%, 50%);
  animation: hqCandyBurst .85s cubic-bezier(.2,.7,.4,1) forwards;
}
.candy-burst-piece img { width: 44px; height: 44px; object-fit: contain; }
.candy-burst-piece--g, .candy-burst-piece--g img { filter: drop-shadow(0 0 12px rgba(52,211,153,.95)) drop-shadow(0 0 26px rgba(52,211,153,.5)); }
.candy-burst-piece--r, .candy-burst-piece--r img { filter: drop-shadow(0 0 12px rgba(248,113,113,.95)) drop-shadow(0 0 26px rgba(248,113,113,.5)); }
.candy-burst-piece--b, .candy-burst-piece--b img { filter: drop-shadow(0 0 12px rgba(96,165,250,.95)) drop-shadow(0 0 26px rgba(96,165,250,.5)); }
@keyframes hqCandyBurst {
  0% { opacity: 1; transform: translate(-50%, 50%) scale(.7); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--burst-x, 0px)), calc(50% - var(--burst-y, 60px))) scale(1.25) rotate(220deg); }
}
/* Central explosion flash at the impact point */
.candy-burst-flash {
  position: absolute;
  z-index: 28;
  width: 90px; height: 90px;
  border-radius: 999px;
  pointer-events: none;
  transform: translate(-50%, 50%) scale(.4);
  background: radial-gradient(circle, rgba(255,255,255,.95) 0%, rgba(52,211,153,.55) 32%, rgba(96,165,250,.35) 58%, transparent 72%);
  animation: hqCandyFlash .5s ease-out forwards;
}
@keyframes hqCandyFlash {
  0% { opacity: 1; transform: translate(-50%, 50%) scale(.4); }
  100% { opacity: 0; transform: translate(-50%, 50%) scale(3.4); }
}

/* ---- Visual keyboard mapper (MapleStory-style) ---- */
.hq-kbmap-overlay {
  position: fixed;
  inset: 0;
  z-index: 10150;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(2, 6, 14, 0.72);
  backdrop-filter: blur(6px);
}
.hq-kbmap-overlay[hidden] { display: none; }
.hq-kbmap-panel {
  width: min(1060px, 96vw);
  max-height: 92vh;
  overflow: auto;
  border-radius: 18px;
  background: linear-gradient(180deg, rgba(13, 22, 36, 0.98), rgba(7, 12, 22, 0.98));
  border: 1px solid rgba(94, 234, 212, 0.35);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
  padding: 16px 18px;
  color: #e6fffb;
}
.hq-kbmap-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.hq-kbmap-title { font-size: 19px; font-weight: 1000; letter-spacing: 0.02em; }
.hq-kbmap-sub { margin-top: 3px; font-size: 12px; color: rgba(178, 226, 216, 0.75); }
.hq-kbmap-close {
  width: 32px; height: 32px; border-radius: 9px; border: 1px solid rgba(255,255,255,0.16);
  background: rgba(255,255,255,0.07); color: #fff; font-weight: 900; cursor: pointer;
}
.hq-kbmap-close:hover { background: #e5484d; }
.hq-kbmap-status { min-height: 20px; margin: 8px 2px 10px; font-size: 12.5px; font-weight: 800; color: rgba(178, 226, 216, 0.85); }
.hq-kbmap-status[data-tone="arm"] { color: #fbbf24; }
.hq-kbmap-status[data-tone="ok"] { color: #4ade80; }
.hq-kbmap-status[data-tone="err"] { color: #f87171; }
.hq-kbmap-body { display: flex; gap: 14px; align-items: flex-start; }
.hq-kbmap-grid { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.hq-kbmap-row { display: flex; gap: 5px; }
.hq-kbmap-key {
  flex: 1 0 0;
  min-width: 0;
  height: 52px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 2px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.13);
  background: rgba(255, 255, 255, 0.05);
  color: #dbeafe;
  cursor: pointer;
  overflow: hidden;
}
.hq-kbmap-key:hover { border-color: rgba(94, 234, 212, 0.6); background: rgba(94, 234, 212, 0.1); }
.hq-kbmap-key.is-target { border-style: dashed; border-color: rgba(251, 191, 36, 0.55); }
.hq-kbmap-key.is-reserved { opacity: 0.35; cursor: not-allowed; }
.hq-kbmap-cap { font-size: 10px; font-weight: 900; opacity: 0.75; line-height: 1; }
.hq-kbmap-cap--empty { font-size: 12px; opacity: 0.55; }
.hq-kbmap-chip {
  max-width: 100%;
  padding: 2px 6px;
  border-radius: 6px;
  color: #08131f;
  font-size: 10px;
  font-weight: 1000;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}
.hq-kbmap-palette {
  flex: 0 0 250px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 380px;
  overflow: auto;
  padding: 8px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.09);
}
.hq-kbmap-palette__group { margin: 6px 4px 2px; font-size: 10px; font-weight: 1000; letter-spacing: 0.12em; text-transform: uppercase; }
.hq-kbmap-palette__row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 9px;
  border: 1px solid transparent; background: rgba(255, 255, 255, 0.04);
  color: #e6fffb; font-size: 12.5px; font-weight: 800; cursor: pointer; text-align: left;
}
.hq-kbmap-palette__row i { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.hq-kbmap-palette__row span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hq-kbmap-palette__row em { font-style: normal; font-size: 11px; color: rgba(148, 233, 217, 0.8); }
.hq-kbmap-palette__row:hover { background: rgba(94, 234, 212, 0.12); }
.hq-kbmap-palette__row.is-armed { border-color: rgba(251, 191, 36, 0.7); background: rgba(251, 191, 36, 0.12); }
.hq-kbmap-palette__row.is-locked { opacity: 0.5; }
.hq-kbmap-foot { display: flex; justify-content: space-between; gap: 10px; margin-top: 12px; }
.hq-kbmap-reset, .hq-kbmap-done {
  padding: 9px 16px; border-radius: 11px; font-weight: 900; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.16); background: rgba(255, 255, 255, 0.07); color: #fff;
}
.hq-kbmap-done { background: linear-gradient(180deg, #2dd4bf, #0d9488); border-color: rgba(94, 234, 212, 0.6); color: #04211c; }
@media (max-width: 900px) {
  .hq-kbmap-body { flex-direction: column; }
  .hq-kbmap-palette { flex: 1 1 auto; width: 100%; max-height: 220px; }
  .hq-kbmap-key { height: 42px; }
}

/* ---- Channel picker (top-left, under the status chip) ---- */
body:not(.hq-in-game) .hq-channel-btn,
body:not(.hq-in-game) .hq-channel-menu { display: none !important; }
.hq-channel-btn {
  position: absolute;
  left: 12px;
  top: 52px;
  z-index: 93;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid rgba(94, 234, 212, 0.4);
  background: rgba(8, 12, 20, 0.82);
  color: #7ff0dd;
  font-size: 12px;
  font-weight: 900;
  cursor: pointer;
  backdrop-filter: blur(10px);
  pointer-events: auto;
}
.hq-channel-menu {
  position: absolute;
  left: 12px;
  top: 88px;
  z-index: 10130;
  min-width: 230px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px;
  border-radius: 14px;
  background: rgba(5, 9, 18, 0.96);
  border: 1px solid rgba(94, 234, 212, 0.35);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5);
  pointer-events: auto;
}
.hq-channel-menu[hidden] { display: none; }
.hq-channel-menu__head {
  padding: 4px 8px 6px;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(148, 233, 217, 0.75);
}
.hq-channel-menu__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid transparent;
  background: rgba(255, 255, 255, 0.05);
  color: #e6fffb;
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
  text-align: left;
}
.hq-channel-menu__row em {
  font-style: normal;
  font-size: 11px;
  font-weight: 800;
  color: rgba(148, 233, 217, 0.8);
}
.hq-channel-menu__row:hover { background: rgba(94, 234, 212, 0.14); }
.hq-channel-menu__row.is-current {
  border-color: rgba(94, 234, 212, 0.6);
  background: rgba(94, 234, 212, 0.16);
}

/* ---- In-game minimal HUD: heavy info chrome collapses while playing ---- */
body.hq-in-game .hud-stack--map-info .map-info-card { display: none !important; }  /* big HQ/Players/Server card */
body.hq-in-game .hq-topbar { display: none !important; }                            /* center map-title text block */
body.hq-in-game #expVideoControls { display: none !important; }                     /* legacy Pause/Sound/Close pills — the video window bar replaced them */
body.hq-in-game .conn-status {
  padding: 4px 10px 4px 22px;
  font-size: 11px;
  opacity: 0.85;
  position: relative;
}
body.hq-in-game .conn-status::before {
  content: "";
  position: absolute;
  left: 9px;
  top: 50%;
  transform: translateY(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ef4444;
  box-shadow: 0 0 8px rgba(239, 68, 68, 0.8);
}
body.hq-in-game .conn-status.is-good::before {
  background: #22c55e;
  box-shadow: 0 0 8px rgba(34, 197, 94, 0.8);
}

/* Video window chrome — a real WINDOW: roomy title bar above the video (easy to
   grab, like a browser), glassy teal frame, grip-corner resize. The chrome floats
   above the game; the video pixels stay in the world stack below platforms. */
.exp-video-window {
  position: absolute;
  z-index: 96;
  pointer-events: none;
  filter: drop-shadow(0 26px 48px rgba(2, 10, 18, 0.5));
}
.exp-video-window[hidden] { display: none; }
.exp-video-window__bar {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 38px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 8px 0 12px;
  border-radius: 14px 14px 0 0;
  background: linear-gradient(180deg, rgba(13, 24, 38, 0.96), rgba(8, 15, 26, 0.92));
  border: 1px solid rgba(94, 234, 212, 0.38);
  border-bottom: 1px solid rgba(94, 234, 212, 0.22);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  cursor: grab;
  pointer-events: auto;
  touch-action: none;
  box-sizing: border-box;
}
.exp-video-window__bar:active { cursor: grabbing; }
.exp-video-window__grip {
  width: 26px;
  height: 14px;
  flex: none;
  background-image: radial-gradient(rgba(148, 233, 217, 0.7) 1.5px, transparent 1.9px);
  background-size: 8px 7px;
  opacity: 0.9;
}
.exp-video-window__title {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.01em;
  color: rgba(226, 250, 245, 0.92);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  pointer-events: none;
}
.exp-video-window__close {
  flex: none;
  width: 26px; height: 26px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.08);
  color: rgba(255, 235, 235, 0.92);
  font-size: 13px;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
  pointer-events: auto;
  transition: background 0.15s ease, color 0.15s ease;
}
.exp-video-window__close:hover {
  background: #e5484d;
  border-color: rgba(255, 255, 255, 0.5);
  color: #fff;
}
.exp-video-window__frame {
  position: absolute;
  left: 0; right: 0; top: 38px; bottom: 0;
  border: 1px solid rgba(94, 234, 212, 0.38);
  border-top: 0;
  border-radius: 0 0 14px 14px;
  box-shadow: inset 0 0 0 1px rgba(2, 10, 18, 0.45);
  pointer-events: none;
}
.exp-video-window__resize {
  position: absolute;
  right: -4px; bottom: -4px;
  width: 26px; height: 26px;
  border-radius: 8px 4px 10px 4px;
  background:
    linear-gradient(135deg, transparent 0 44%, rgba(94, 234, 212, 0.95) 44% 52%, transparent 52% 62%,
      rgba(94, 234, 212, 0.95) 62% 70%, transparent 70% 80%, rgba(94, 234, 212, 0.95) 80% 88%, transparent 88%),
    rgba(8, 15, 26, 0.92);
  border: 1px solid rgba(94, 234, 212, 0.45);
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.35);
  cursor: nwse-resize;
  pointer-events: auto;
  touch-action: none;
}
/* fill / fit modes: no frame, just the ✕ pinned upper-LEFT of the stage
   (the right side belongs to the Home/Settings/Info button stack) */
.exp-video-window--pinned {
  right: auto !important;
  left: 12px !important;
  top: 118px;
  width: auto !important;
  height: auto !important;
  filter: none;
}
.exp-video-window--pinned .exp-video-window__bar {
  position: static;
  height: auto;
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  cursor: default;
}
.exp-video-window--pinned .exp-video-window__grip,
.exp-video-window--pinned .exp-video-window__title,
.exp-video-window--pinned .exp-video-window__frame,
.exp-video-window--pinned .exp-video-window__resize { display: none; }
.exp-video-window--pinned .exp-video-window__close {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: #e5484d;
  border: 2px solid rgba(255, 255, 255, 0.85);
  color: #fff;
  font-size: 15px;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.35);
}
.hq-bg-layer--image { z-index: 1; }
.hq-bg-layer--shade { z-index: 3; pointer-events: none; }
.hq-ground { z-index: 4; }
.map-visual-layer--back { z-index: 24; }

.exp-video-panel {
  position: absolute;
  right: 14px;
  top: 178px;   /* below the Home/Settings/Info utility stack */
  width: min(360px, calc(100% - 28px));
  max-height: calc(100% - 28px);
  z-index: 95;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: 20px;
  background: rgba(5, 9, 19, 0.72);
  box-shadow: 0 20px 60px rgba(0,0,0,0.36);
  backdrop-filter: blur(14px);
  pointer-events: auto;
}
.exp-video-panel.is-collapsed {
  width: 242px;
}
.exp-video-panel.is-collapsed .exp-video-grid,
.exp-video-panel.is-collapsed .exp-video-empty {
  display: none;
}
.exp-video-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.exp-video-panel__eyebrow {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(248,250,252,0.62);
  font-weight: 800;
}
.exp-video-panel__title {
  color: #fff;
  font-weight: 900;
  font-size: 14px;
  max-width: 210px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.exp-video-panel__toggle,
.exp-video-controls button {
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(255,255,255,0.12);
  color: #fff;
  border-radius: 999px;
  padding: 8px 10px;
  cursor: pointer;
  font-weight: 800;
}
.exp-video-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  overflow: auto;
  padding-right: 2px;
}
.exp-video-card {
  display: grid;
  grid-template-columns: 86px 1fr;
  gap: 10px;
  align-items: center;
  text-align: left;
  width: 100%;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.08);
  color: #fff;
  border-radius: 15px;
  padding: 8px;
  cursor: pointer;
}
.exp-video-card:hover { background: rgba(255,255,255,0.14); }
.exp-video-thumb {
  width: 86px;
  height: 52px;
  object-fit: cover;
  border-radius: 11px;
  background: rgba(0,0,0,0.3);
}
.exp-video-copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.exp-video-copy strong,
.exp-video-copy em {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.exp-video-copy strong { font-size: 13px; }
.exp-video-copy em {
  font-size: 11px;
  color: rgba(248,250,252,0.66);
  font-style: normal;
}
.exp-video-controls {
  display: grid;
  grid-template-columns: auto auto 1fr;
  gap: 8px;
  align-items: center;
}
.exp-video-controls input { width: 100%; }
.exp-video-empty {
  color: rgba(248,250,252,0.68);
  font-size: 12px;
  padding: 8px 2px;
}

@media (max-width: 980px) {
  .exp-video-panel {
    top: 10px;
    right: 10px;
    width: min(310px, calc(100% - 20px));
    padding: 10px;
    max-height: 48%;
  }
  .exp-video-panel.is-collapsed { width: 210px; }
  .exp-video-card { grid-template-columns: 72px 1fr; }
  .exp-video-thumb { width: 72px; height: 44px; }
}

/* Camera-locked background video player.
   The video stays fixed to the camera/viewport, but sits BEHIND gameplay.
   Characters, portals, monsters, projectiles, platforms, HUD, and UI render on top. */
.exp-bg-video--camera-locked{
  position:absolute;
  z-index:2;
  pointer-events:none;
}
.hq-stage > .exp-bg-video{
  z-index:2;
}
/* A playing video must stay visible as the map background on every map.
   Do not hide it on combat/monster maps; the gameplay world remains above it. */
.exp-bg-video.is-playing {
  display: block;
}
.hq-world{
  z-index:10;
}

/* EXP Tube video worlds: profile thumbnails become playable portals */
.portal--video-thumb {
  border-radius: 18px;
  overflow: visible;
  background: rgba(3, 7, 18, 0.82);
  border: 3px solid rgba(255,255,255,.78);
  box-shadow: 0 18px 45px rgba(0,0,0,.38), 0 0 0 4px rgba(59,130,246,.24);
}
.portal--video-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 14px;
  filter: saturate(1.08) contrast(1.05);
}
.portal--video-thumb .portal-video-title {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 8px;
  z-index: 3;
  padding: 6px 8px;
  border-radius: 10px;
  background: rgba(0,0,0,.68);
  color: #fff;
  font-weight: 900;
  font-size: 13px;
  line-height: 1.1;
  text-shadow: 0 1px 2px rgba(0,0,0,.85);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.portal--video-thumb .portal-prompt {
  min-width: 230px;
  text-align: center;
  background: rgba(37, 99, 235, .96);
  color: #fff;
  border: 2px solid rgba(255,255,255,.8);
  box-shadow: 0 12px 30px rgba(0,0,0,.38);
}
/* The framed dark "screen card" look belongs to VIDEO/PROFILE worlds' Video Frame
   visuals ONLY. Unscoped, it painted EVERY builder decor (buildings etc.) as a dark
   rounded card and cover-cropped the art — the "dark box behind my building" bug. */
body.is-video-world .map-visual,
body.is-profile-world .map-visual {
  overflow: hidden;
  border-radius: 20px;
  border: 4px solid rgba(255,255,255,.72);
  background: rgba(15,23,42,.88);
  box-shadow: 0 22px 60px rgba(0,0,0,.34), inset 0 0 0 1px rgba(0,0,0,.35);
}
body.is-video-world .map-visual img,
body.is-profile-world .map-visual img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.platform-surface {
  border-radius: 999px;
  border: 2px solid rgba(255,255,255,.36);
  box-shadow: inset 0 4px 0 rgba(255,255,255,.25), inset 0 -6px 0 rgba(0,0,0,.22), 0 12px 26px rgba(0,0,0,.22);
}
/* invisible collision platforms (builder "hidden") — paint NOTHING */
/* Invisible collider. The home-map selector is here because the home map's own
   .platform-surface rule is also !important and more specific, and it was
   drawing every invisible collider there as a glass pill. */
.platform-surface--ghost,
.exp-map-home-hq .platform-surface.platform-surface--ghost {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
}
/* builder platform with no color picked — emerald-glass default so players can
   see where to jump, with a white edge + soft dark drop for contrast against
   the bright city art */
.platform-surface--glass {
  background: linear-gradient(180deg, rgba(255,255,255,.85), rgba(64,205,190,.55)) !important;
  border: 2px solid rgba(255,255,255,.95) !important;
  border-radius: 999px;
  box-shadow: inset 0 2px 0 rgba(255,255,255,.6), 0 8px 16px rgba(6,40,38,.35), 0 0 14px rgba(140,255,236,.35) !important;
}
/* Art platforms: builder-uploaded PNG hangs from the collision line at its
   natural aspect — zero pill chrome; the thin walk-line box paints nothing */
.platform-surface--art {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  border-radius: 0;
  overflow: visible;
}
.platform-surface--art img {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 0;
  width: 100%;
  height: auto;
  pointer-events: none;
  filter: drop-shadow(0 22px 34px rgba(4,36,34,.35));
}

/* Profile/video worlds use thumbnails as map portals, not the homepage video list. */
body.is-profile-world .exp-video-panel.is-world-video-mode,
body.is-video-world .exp-video-panel.is-world-video-mode {
  display: none !important;
}

/* Profile/video worlds must stay visible at 100% browser zoom and below. */
body.is-profile-world .exp-video-panel.is-world-video-mode,
body.is-video-world .exp-video-panel.is-world-video-mode {
  display: none !important;
}
body.is-profile-world .hq-frame,
body.is-video-world .hq-frame {
  align-items: start;
}
body.is-profile-world .hq-stage,
body.is-video-world .hq-stage {
  margin-top: 92px;
}
@media (max-width: 980px) {
  body.is-profile-world .hq-stage,
  body.is-video-world .hq-stage {
    margin-top: 84px;
  }
}


/* EXB hand audio bar + video controls protection.
   Keeps the visual overlay from stealing clicks and keeps video controls above the game/effect layers. */
#exbHandAudioBarOverlay,
#exbHandAudioBarOverlay *,
.exb-hand-audio-bar-overlay,
.exb-hand-audio-bar-overlay * {
  pointer-events: none !important;
}

.exp-video-player,
.exp-video-player *,
.exp-video-player-controls,
.exp-video-player-controls *,
.exp-video-controls,
.exp-video-controls *,
#expVideoControls,
#expVideoControls *,
#expVideoPlayPauseBtn,
#expVideoMuteBtn,
#expVideoCloseBtn,
#expVideoVolume {
  pointer-events: auto !important;
}

.exp-video-player,
.exp-video-player-controls,
#expVideoControls,
.exp-video-controls {
  position: relative;
  z-index: 10050 !important;
}

body.exp-video-playing .exp-video-player,
body.exp-video-playing .exp-video-player-controls,
body.exp-video-playing #expVideoControls,
body.exp-video-playing .exp-video-controls {
  pointer-events: auto !important;
  z-index: 10050 !important;
}


/* EXP Tube Duckies projectile update */
.projectile.projectile--duckies-pack {
  width: 76px;
  height: 36px;
  background: transparent;
  filter: drop-shadow(0 8px 12px rgba(0,0,0,.32)) drop-shadow(0 0 10px rgba(255,255,255,.35));
}
.projectile.projectile--duckies-pack::before,
.projectile.projectile--duckies-pack::after {
  display: none !important;
  content: none !important;
}
.projectile.projectile--duckies-pack img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
}
.monster--tropi-duck img {
  image-rendering: auto;
}


/* EXP Tube v2 Duckies projectile size fix */
.projectile.projectile--duckies-pack {
  width: 76px !important;
  height: 36px !important;
  z-index: 30;
}
.projectile.projectile--duckies-pack img {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain !important;
}

/* Keep MMO combat above profile video thumbnails/cards */
.monster-layer,
.projectile-layer,
.drop-layer,
.players-layer {
  z-index: 60 !important;
}


/* Live/profile portal glow for main.png. Drop-shadow follows PNG alpha, not transparent canvas box. */
.portal--glow {
  overflow: visible !important;
}
.portal--glow img {
  filter:
    drop-shadow(0 0 8px rgba(39, 255, 255, .95))
    drop-shadow(0 0 18px rgba(34, 211, 238, .8))
    drop-shadow(0 0 34px rgba(168, 85, 247, .65));
}
.portal--glow-live img {
  filter:
    drop-shadow(0 0 8px rgba(34, 211, 238, .95))
    drop-shadow(0 0 20px rgba(14, 165, 233, .8))
    drop-shadow(0 0 36px rgba(236, 72, 153, .55));
}
.portal--glow-profile img {
  filter:
    drop-shadow(0 0 8px rgba(250, 204, 21, .95))
    drop-shadow(0 0 20px rgba(34, 197, 94, .8))
    drop-shadow(0 0 36px rgba(59, 130, 246, .55));
}
.portal--glow .portal-prompt {
  filter: drop-shadow(0 0 10px rgba(34, 211, 238, .65));
}


/* EXP Tube live map offline background.
   Shows when live_stream is open without an active livestream video. */
body.exp-live-offline-bg,
.exp-live-offline-bg .game-stage,
.exp-live-offline-bg .map-viewport {
  background:
    radial-gradient(circle at 18% 18%, rgba(34, 211, 238, .30), transparent 28%),
    radial-gradient(circle at 78% 22%, rgba(236, 72, 153, .28), transparent 30%),
    radial-gradient(circle at 50% 70%, rgba(250, 204, 21, .12), transparent 36%),
    linear-gradient(180deg, #07111f 0%, #0b1026 45%, #120922 100%) !important;
}

.exp-live-offline-bg .map-visual-layer::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(34,211,238,.08) 1px, transparent 1px),
    linear-gradient(0deg, rgba(236,72,153,.06) 1px, transparent 1px);
  background-size: 86px 86px;
  opacity: .65;
  transform: perspective(700px) rotateX(58deg) translateY(150px) scale(1.25);
  transform-origin: center bottom;
  filter: drop-shadow(0 0 12px rgba(34,211,238,.22));
}

.exp-live-offline-bg .map-visual-layer::after {
  content: "LIVE ARENA";
  position: absolute;
  left: 50%;
  top: 80px;
  transform: translateX(-50%);
  font-size: 72px;
  font-weight: 1000;
  letter-spacing: 10px;
  color: rgba(255,255,255,.12);
  text-shadow:
    0 0 18px rgba(34,211,238,.28),
    0 0 40px rgba(236,72,153,.20);
  pointer-events: none;
  white-space: nowrap;
}

.exp-live-offline-bg .profile-video-bg,
.exp-live-offline-bg .live-video-bg {
  opacity: 0;
}


/* Duckies Pack projectile: smaller but readable, image based, no CSS star. */
.projectile.projectile--duckies-pack {
  width: 64px !important;
  height: 30px !important;
  background: transparent !important;
  filter: drop-shadow(0 5px 8px rgba(0,0,0,.36)) drop-shadow(0 0 6px rgba(255,255,255,.30)) !important;
  z-index: 80 !important;
}
.projectile.projectile--duckies-pack::before,
.projectile.projectile--duckies-pack::after {
  display: none !important;
  content: none !important;
}
.projectile.projectile--duckies-pack img {
  display: block !important;
  width: 100% !important;
  height: 100% !important;
  object-fit: contain !important;
  pointer-events: none !important;
}

.monster--tropi-duck {
  min-width: 260px;
  min-height: 260px;
}


/* Live stream map must not show profile video cards/thumbnails. */
body.exp-map-live-stream .portal--video-thumb,
body.exp-map-live-stream .profile-video-card,
body.exp-map-live-stream .video-card,
body.exp-map-live-stream [data-video-id],
body.exp-map-live-stream [data-kind="video"] {
  display: none !important;
}


/* Profile owner name visibility */
body[data-profile-display-name] .brand-title,
body[data-profile-display-name] #brandTitle {
  text-shadow: 0 0 14px rgba(34,211,238,.35);
}


/* EXP loot burst + pickup */
.drop {
  position: absolute;
  width: 58px;
  height: 58px;
  pointer-events: none;
  transform: translate(-50%, 0);
  z-index: 72;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,.45)) drop-shadow(0 0 10px rgba(255,255,255,.18));
}

.drop img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  animation: expDropSlowSpin 3.8s linear infinite;
  transform-origin: center center;
}

.drop--flying img {
  animation: expDropFastSpin .55s linear infinite;
}

.drop--settled {
  filter: drop-shadow(0 6px 8px rgba(0,0,0,.42)) drop-shadow(0 0 12px rgba(34,211,238,.42));
}

.drop--settled::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -10px;
  width: 48px;
  height: 12px;
  transform: translateX(-50%);
  border-radius: 999px;
  background: radial-gradient(circle, rgba(34,211,238,.42), transparent 70%);
  opacity: .8;
}

.drop--rare {
  filter: drop-shadow(0 6px 10px rgba(0,0,0,.48)) drop-shadow(0 0 14px rgba(250,204,21,.72)) drop-shadow(0 0 26px rgba(34,211,238,.35));
}

.drop--boss {
  width: 68px;
  height: 68px;
}

@keyframes expDropSlowSpin {
  from { transform: rotate(var(--drop-spin-seed, 0rad)); }
  to { transform: rotate(calc(var(--drop-spin-seed, 0rad) + 360deg)); }
}

@keyframes expDropFastSpin {
  from { transform: rotate(var(--drop-spin-seed, 0rad)) scale(1.08); }
  to { transform: rotate(calc(var(--drop-spin-seed, 0rad) + 360deg)) scale(1.08); }
}

/* Monster death PNG fade */
.monster--defeated {
  pointer-events: none;
}
.monster--defeated .monster-visual {
  animation: expMonsterDeathFade 1.8s ease-out forwards;
}

@keyframes expMonsterDeathFade {
  0% { opacity: 1; transform: scaleX(var(--monster-facing, 1)) scale(1); filter: brightness(1.15) saturate(1.1); }
  45% { opacity: .82; transform: scaleX(var(--monster-facing, 1)) scale(.98); }
  100% { opacity: 0; transform: scaleX(var(--monster-facing, 1)) scale(.82) translateY(-18px); filter: blur(1px) brightness(1.4); }
}


/* Clean root patch: keep profile layout, add right boundary + visible drops */
.drop-layer, #dropLayer {
  position: absolute !important;
  inset: 0 !important;
  overflow: visible !important;
  z-index: 120 !important;
  pointer-events: none !important;
}
.drop {
  z-index: 121 !important;
  min-width: 44px !important;
  min-height: 44px !important;
}
.exp-profile-boundary-right,
.profile-world-boundary-right {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 12px;
  pointer-events: none;
}

/* EXP Tube duck/drop follow-up */
.monster--tropi-duck {
  min-width: 190px !important;
  min-height: 190px !important;
}
.monster--tropi-duck .monster-hp {
  width: 112px !important;
  height: 12px !important;
}
.drop--flying {
  animation: expDropPopSquash 1.1s ease-out both;
}
.drop--flying img {
  animation: expDropFastSpin .42s linear infinite !important;
}
@keyframes expDropPopSquash {
  0% { transform: translate(-50%, 0) scale(.72); }
  18% { transform: translate(-50%, 0) scale(1.18); }
  60% { transform: translate(-50%, 0) scale(1); }
  82% { transform: translate(-50%, 0) scale(1.08,.88); }
  100% { transform: translate(-50%, 0) scale(1); }
}

/* Cash Store mansion placed on the map — render the PNG as a clean building, not a portal frame */
.portal--mansion { filter: drop-shadow(0 14px 22px rgba(0,0,0,.5)); animation: none; z-index: 6 !important; }
/* Stretch to fill the width x height box — matches the admin preview's drawImage() exactly, so
   the door portal (positioned at doorX of this box) always lines up with the art's doorway. */
.portal--mansion img { width: 100%; height: 100%; object-fit: fill; }
.portal--mansion::before, .portal--mansion::after { display: none !important; }
.portal--mansion .portal-prompt { background: rgba(250,204,21,.94); color: #1a1400; font-weight: 800; }

/* Small gold door portal that sits on the mansion's doorway */
.portal--glow-gold img { filter: drop-shadow(0 0 12px rgba(250,204,21,.95)) drop-shadow(0 0 26px rgba(250,204,21,.6)); }
.portal--glow-gold .portal-prompt { background: rgba(250,204,21,.95); color: #1a1400; font-weight: 800; }

/* "Pick up" button on a Cash-tab mansion slot (removes the placed mansion from the map) */
.hq-mansion-pickup { position:absolute; top:3px; left:3px; width:22px; height:22px; padding:0; border:none; border-radius:6px; background:rgba(0,0,0,.55); color:#fde047; font-size:13px; font-weight:900; line-height:1; cursor:pointer; z-index:3; }
.hq-mansion-pickup:hover { background:rgba(0,0,0,.82); transform:scale(1.08); }

body.exp-profile-clean-mode .bottom-bars-hud {
  display: flex !important;
  visibility: visible !important;
  opacity: 1 !important;
  position: fixed !important;
  left: 18px !important;
  right: 18px !important;
  bottom: 12px !important;
  z-index: 980 !important;
}




/* Home HQ: giant explorable map + YouTube-style video browser in front. */
.exp-map-home-hq .hq-stage {
  background: #06131b;
}

.exp-map-home-hq .hq-bg-layer--image {
  z-index: 1;
  opacity: 1;
  filter: saturate(1.18) contrast(1.08) brightness(1.06);
  transform: none;
  background-size: 100% 100% !important;
  background-position: center center !important;
  background-repeat: no-repeat !important;
}

.exp-map-home-hq .hq-bg-layer--shade {
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to top, rgba(0,0,0,.22), rgba(0,0,0,.04) 50%, rgba(255,255,255,.02)) !important;
}

/* Builder-saved home map AND foreign/brand maps (Maylex, tshirttube worlds, etc.):
   show the uploaded art bright and unfiltered. The engine's default scene shade
   (rgba(4,8,15,.8) gradient) + brightness(.92) buried brand maps in darkness and
   made them look flat next to their native tshirttube render. */
.exp-map-home-built .hq-bg-layer--image,
.exp-map-bright .hq-bg-layer--image {
  filter: none;
  transform: none;
}
.exp-map-home-built .hq-bg-layer--shade,
.exp-map-bright .hq-bg-layer--shade {
  pointer-events: none;
  background: linear-gradient(to top, rgba(0,0,0,.14), rgba(0,0,0,0) 40%) !important;
}

/* Foreign/brand maps (Maylex + other tshirttube worlds) author portal.x as the LEFT
   edge — the tshirttube builder + native client anchor portals with no centering
   (transform:none; transform-origin:left bottom). EXP's renderer centers portals on x
   via translate(-50%,0), which pulled every brand portal ~half-a-width to the left.
   Match the tshirttube anchor for foreign maps so portals land exactly where the author
   placed them. Scoped to foreign maps, so EXP's own maps keep center-on-x. */
.exp-map-foreign .portal {
  transform: none;
  transform-origin: left bottom;
}

/* ---- Branded door chrome (tshirttube, twistvids, any non-EXP host) ----
   door-chrome.js adds .exp-door-branded to <html>/<body> on a brand door. The EXP
   social nav collapses to a single Home button (→ the brand's own site); EXP-only
   actions (Profile/Upload/Go Live) + auth buttons + the cross-world map list are
   hidden so a brand player stays inside the brand and never wanders into EXPtube.
   The in-game HUD (stats, shop, inventory, abilities, minimap) is untouched. */
.exp-door-branded .exp-social-brand,
.exp-door-branded .exp-social-link[href="/profile/"],
.exp-door-branded .exp-social-link[href$="/profile/"],
.exp-door-branded .exp-social-link[href="/upload/"],
.exp-door-branded #expNavCreateBtn,
.exp-door-branded #expNavGoLiveBtn {
  display: none !important;
}
/* Log In / Sign Out stay on branded doors (guests need to log in). Visibility is driven
   by the game auth (gameAuth) in legacy-game.js, so it's the brand's account, not EXP. */
.exp-door-branded #hqWorldMapBtn {
  display: none !important;
}

.exp-map-home-hq .map-visual-layer--back { z-index: 3; }
.exp-map-home-hq .hq-ground { z-index: 4; }
.exp-map-home-hq .platform-layer { z-index: 20; }
.exp-map-home-hq .rope-layer { z-index: 21; }
.exp-map-home-hq .drop-layer { z-index: 28; }
.exp-map-home-hq .projectile-layer { z-index: 29; }
.exp-map-home-hq .monster-layer { z-index: 30; }
.exp-map-home-hq .players-layer,
.exp-map-home-hq .player { z-index: 34; }
.exp-map-home-hq .portal-layer { z-index: 38; }
.exp-map-home-hq .map-visual-layer--front { z-index: 70; }

.exp-map-home-hq .map-visual img {
  object-fit: fill;
  filter: saturate(1.16) contrast(1.08) brightness(1.06);
}

.exp-map-home-hq .platform-surface {
  border: 2px solid rgba(210, 255, 255, .88);
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(215,255,255,.34), rgba(69,220,255,.20)) !important;
  box-shadow: 0 0 0 1px rgba(255,255,255,.25) inset, 0 0 18px rgba(107,232,255,.36), 0 8px 18px rgba(0,0,0,.18);
}

.exp-map-home-hq .rope-surface {
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(180,255,255,.10), rgba(235,255,255,.70), rgba(180,255,255,.10)) !important;
  box-shadow: 0 0 18px rgba(107,232,255,.32);
}

.exp-video-panel.exp-video-panel--home-layer {
  position: fixed;
  left: 24px;
  right: 24px;
  top: 86px;
  bottom: 84px;
  width: auto;
  height: auto;
  max-height: none;
  z-index: 5000;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 14px;
  border: 0 !important;
  border-radius: 0;
  background: transparent !important;
  border-color: transparent !important;
  box-shadow: none !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  opacity: 1;
  pointer-events: auto;
}

.exp-video-panel.exp-video-panel--home-layer.is-collapsed {
  left: auto;
  right: 22px;
  top: 82px;
  bottom: auto;
  width: auto;
  height: auto;
  padding: 0;
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-panel__head {
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  flex: 0 0 auto;
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-panel__eyebrow,
.exp-video-panel.exp-video-panel--home-layer .exp-video-panel__title {
  display: none;
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-panel__toggle {
  border: 1px solid rgba(255,255,255,.62);
  background: rgba(6, 12, 24, .88);
  color: #fff;
  box-shadow: 0 12px 30px rgba(0,0,0,.28);
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(252px, 1fr));
  align-content: start;
  gap: 18px;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 10px 26px 4px;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.exp-video-panel.exp-video-panel--home-layer.is-collapsed .exp-video-grid {
  display: none;
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-card {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  width: 100%;
  padding: 0;
  border: 1px solid rgba(255,255,255,.20);
  border-radius: 16px;
  background: rgba(4, 8, 16, .74);
  overflow: hidden;
  box-shadow: 0 14px 35px rgba(0,0,0,.28);
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-card:hover {
  background: rgba(4, 8, 16, .88);
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-thumb {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border-radius: 0;
  object-fit: cover;
  display: block;
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-copy {
  padding: 0 10px 10px;
  min-width: 0;
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-copy strong {
  color: #fff;
  font-size: 14px;
  line-height: 1.12;
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.exp-video-panel.exp-video-panel--home-layer .exp-video-copy em,
.exp-video-panel.exp-video-panel--home-layer .exp-video-controls,
.exp-video-panel.exp-video-panel--home-layer .exp-video-empty {
  display: none;
}

@media (max-width: 900px) {
  .exp-video-panel.exp-video-panel--home-layer {
    left: 10px;
    right: 10px;
    top: 68px;
    bottom: 84px;
    padding: 10px;
  }
  .exp-video-panel.exp-video-panel--home-layer .exp-video-grid {
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 12px;
  }
}

.exp-map-no-video-cards .exp-video-panel,
.exp-map-no-video-cards .exp-video-panel--home-layer,
.exp-map-no-video-cards .exp-video-grid,
.exp-map-no-video-cards .exp-video-card,
.exp-map-no-video-cards .exp-video-thumb,
.exp-map-no-video-cards .portal--video-thumb,
.exp-map-no-video-cards .portal-video-title,
.exp-map-no-video-cards .exp-video-empty {
  display: none !important;
}

/* MapleStory-inspired EXP Tube HUD + chat split from hq.js */
.maple-status-hud{
  position:absolute;
  left:10px;
  right:10px;
  bottom:8px;
  z-index:98;
  height:74px;
  display:flex;
  align-items:stretch;
  gap:8px;
  padding:8px 10px;
  pointer-events:none;
  border-radius:10px 10px 0 0;
  border:2px solid rgba(34,54,71,.9);
  background:linear-gradient(180deg,rgba(236,239,244,.96),rgba(137,148,160,.96));
  box-shadow:0 -4px 16px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.72);
  color:#101820;
  font-family:Arial,Helvetica,sans-serif;
}
.maple-status-identity{
  flex:0 0 275px;
  min-width:220px;
  display:grid;
  grid-template-columns:72px 1fr;
  grid-template-rows:1fr 1fr;
  gap:5px 7px;
  align-items:center;
  padding:5px 8px;
  border-radius:8px;
  background:rgba(255,255,255,.58);
  border:1px solid rgba(50,65,80,.34);
  box-shadow:inset 0 1px 2px rgba(255,255,255,.7);
}
.maple-status-level{
  grid-row:1 / 3;
  height:100%;
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius:7px;
  color:#fff;
  background:linear-gradient(180deg,#3e4b57,#151b21);
  border:1px solid rgba(0,0,0,.5);
  font-size:17px;
  font-weight:950;
  text-shadow:0 2px 2px rgba(0,0,0,.9);
}
.maple-status-job,.maple-status-name{
  min-width:0;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
  font-weight:950;
  color:#15202a;
  text-shadow:0 1px 0 rgba(255,255,255,.8);
}
.maple-status-job{font-size:12px;opacity:.86;letter-spacing:.02em;text-transform:uppercase}
.maple-status-name{font-size:15px}
.maple-status-bars{
  flex:1 1 auto;
  min-width:0;
  display:flex;
  align-items:stretch;
  gap:8px;
}
.maple-stat{
  min-width:120px;
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
  gap:4px;
}
.maple-stat--hp,.maple-stat--mp{flex:0 1 235px}
.maple-stat--exp{flex:1 1 360px}
.maple-stat-label{
  height:20px;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:0 8px;
  border-radius:7px 7px 3px 3px;
  color:#fff;
  background:linear-gradient(180deg,rgba(30,37,47,.98),rgba(5,8,13,.98));
  border:1px solid rgba(255,255,255,.2);
  box-shadow:0 2px 4px rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.14);
  font-size:12px;
  font-weight:950;
  text-shadow:0 2px 2px rgba(0,0,0,1),0 0 5px rgba(0,0,0,.9);
  white-space:nowrap;
  letter-spacing:.01em;
}
.maple-stat-track{
  position:relative;
  height:25px;
  overflow:hidden;
  border-radius:5px;
  background:#171b21;
  border:2px solid #3f4b55;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.8),0 1px 0 rgba(255,255,255,.42);
}
.maple-stat-fill{
  position:absolute;
  left:0;
  top:0;
  height:100%;
  width:0%;
  transition:width .12s linear;
  box-shadow:inset 0 8px 0 rgba(255,255,255,.20),inset 0 -6px 0 rgba(0,0,0,.14);
}
.maple-stat--hp .maple-stat-fill{background:linear-gradient(180deg,#ff5a55,#c20b0b 55%,#710000)}
.maple-stat--mp .maple-stat-fill{background:linear-gradient(180deg,#5f8cff,#244de8 55%,#101f9a)}
.maple-stat--exp .maple-stat-fill{background:linear-gradient(180deg,#78ff65,#31d224 55%,#168a13)}
.maple-status-resources{
  flex:0 0 auto;
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:5px;
}
.maple-resource-pill{
  height:27px;
  min-width:106px;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:3px;
  border-radius:8px;
  color:#fff;
  background:linear-gradient(180deg,#3c4853,#111820);
  border:1px solid rgba(0,0,0,.55);
  font-size:12px;
  font-weight:950;
  text-shadow:0 2px 2px rgba(0,0,0,.9);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16);
}
.chat-dock{
  bottom:calc(88px + var(--safe-b));
  z-index:110;
  /* A column, so the log stacks directly on top of the input instead of
     floating loose over the world. The input never moves as the log grows. */
  flex-direction:column;
  align-items:center;
  justify-content:flex-end;
  gap:6px;
}
.chat-history-btn{display:none!important}
.chat-history-panel--maple{
  /* Docked, not floating: in normal flow inside .chat-dock, directly above the
     chat bar and the same width as it. Height is driven by --chat-log-h, which
     chat.js sets from the player's drag and clamps to the hard cap. */
  position:relative;
  left:auto;
  right:auto;
  bottom:auto;
  width:min(720px,calc(100% - 28px));
  height:var(--chat-log-h,88px);
  /* The cap is a real px value set by chat.js from the stage height. A percentage
     here would resolve against .chat-dock, which is auto-height, and quietly do
     nothing. */
  max-height:var(--chat-log-cap,240px);
  background:rgba(10,14,18,.58);
  border:1px solid rgba(255,255,255,.22);
  border-radius:8px;
  box-shadow:0 10px 32px rgba(0,0,0,.32);
  backdrop-filter:blur(4px);
}
.chat-history-panel--maple .chat-history-header{
  /* The grip. Deliberately slim -- every pixel here is a pixel of world the
     player cannot see, and there is nothing to read in it. */
  cursor:ns-resize;
  position:relative;          /* positioning context for the grip bar below */
  padding:2px 8px;
  min-height:16px;
  background:rgba(255,255,255,.08);
  border-bottom:1px solid rgba(255,255,255,.12);
  touch-action:none;
}
.chat-history-panel--maple .chat-history-header::before{
  content:'';
  position:absolute;
  left:50%;
  transform:translateX(-50%);
  top:6px;
  width:34px;
  height:3px;
  border-radius:2px;
  background:rgba(255,255,255,.34);
}
.chat-history-panel--maple .chat-history-title{display:none}
.chat-history-panel--maple .chat-history-close{
  width:20px;height:20px;border-radius:6px;font-size:11px;line-height:1;
}
.chat-history-panel--maple .chat-history-list{
  /* Fills whatever the grip left. calc() rather than a fixed max-height so the
     list tracks the panel as it is dragged. */
  height:calc(100% - 18px);
  max-height:none;
  overflow:auto;
  padding:6px 9px;
  scrollbar-width:thin;
}
.chat-history-panel--maple .chat-history-item{
  margin-bottom:5px;
  padding:5px 7px;
  border-radius:6px;
  background:rgba(0,0,0,.18);
  border:1px solid rgba(255,255,255,.05);
}
.chat-history-panel--maple .chat-history-name{font-size:11px;margin-bottom:2px;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.9)}
.chat-history-panel--maple .chat-history-text{font-size:12px;line-height:1.25;color:rgba(255,255,255,.88);text-shadow:0 1px 2px rgba(0,0,0,.9)}
.chat-history-panel--maple .chat-history-time{font-size:10px;margin-top:2px;color:rgba(255,255,255,.56)}

/* PEEK: someone spoke while you were playing.
   The head bubble is the primary read now, so the log only needs to be glanceable.
   Compact, translucent, and click-through so it can never eat a click meant for the
   game, sitting low-left clear of where the character stands. */
.chat-history-panel--maple.is-peek{
  bottom:14px;
  width:min(340px,calc(100vw - 32px));
  max-height:132px;
  background:rgba(10,14,18,.42);
  border-color:rgba(255,255,255,.14);
  box-shadow:0 6px 18px rgba(0,0,0,.28);
  pointer-events:none;          /* never steals a click during play */
  opacity:.92;
  animation:chat-peek-in 180ms ease-out;
}
.chat-history-panel--maple.is-peek .chat-history-header{display:none}
.chat-history-panel--maple.is-peek .chat-history-list{max-height:132px;padding:6px 8px}
.chat-history-panel--maple.is-peek .chat-history-item{
  margin-bottom:3px;padding:3px 6px;background:rgba(0,0,0,.26);border-color:transparent;
}
.chat-history-panel--maple.is-peek .chat-history-time{display:none}
@keyframes chat-peek-in{from{opacity:0;transform:translateY(8px)}to{opacity:.92;transform:translateY(0)}}

@media (prefers-reduced-motion: reduce){
  .chat-history-panel--maple.is-peek{animation:none}
}
.chat-bar--maple{
  width:min(720px,calc(100vw - 36px));
  border-radius:8px;
  background:rgba(245,247,250,.94);
  border:2px solid rgba(47,59,70,.78);
  box-shadow:0 8px 24px rgba(0,0,0,.35);
  padding:7px 9px;
}
.chat-bar--maple .chat-label{color:#17202a;text-shadow:0 1px 0 rgba(255,255,255,.8)}
.chat-bar--maple .chat-input{
  height:34px;
  border-radius:5px;
  color:#0f172a;
  background:#fff;
  border:1px solid rgba(48,62,75,.42);
}
.chat-bar--maple .chat-send-btn{height:34px;border-radius:5px;background:#263441;color:#fff}
@media (max-width:980px){
  .maple-status-hud{left:6px;right:6px;bottom:6px;height:64px;gap:5px;padding:6px;font-size:10px}
  .maple-status-identity{flex-basis:178px;min-width:150px;grid-template-columns:54px 1fr;padding:4px;gap:3px}
  .maple-status-level{font-size:12px}.maple-status-job{font-size:9px}.maple-status-name{font-size:11px}
  .maple-status-bars{gap:5px}.maple-stat--hp,.maple-stat--mp{flex-basis:115px}.maple-stat--exp{flex-basis:160px}
  .maple-stat-label{height:16px;font-size:9px;padding:0 4px}.maple-stat-track{height:20px;border-width:2px}
  .maple-status-resources{display:none}.chat-dock{bottom:calc(74px + var(--safe-b))}
}

/* Beginner Power Ball projectile: MP skill visual, no asset needed. */
.projectile.projectile--power-ball {
  width: 46px;
  height: 46px;
  border-radius: 999px;
  background: radial-gradient(circle at 35% 30%, #ffffff 0 10%, #bfdbfe 22%, #60a5fa 48%, #7c3aed 76%, rgba(49,46,129,.2) 100%);
  box-shadow: 0 0 12px rgba(96,165,250,.95), 0 0 28px rgba(124,58,237,.72), 0 0 48px rgba(59,130,246,.38);
  filter: saturate(1.15);
}
.projectile.projectile--power-ball::before,
.projectile.projectile--power-ball::after {
  content: '';
  position: absolute;
  inset: -8px;
  border-radius: inherit;
  border: 2px solid rgba(191,219,254,.6);
  box-shadow: inset 0 0 18px rgba(255,255,255,.28);
}
.projectile.projectile--power-ball::after {
  inset: 8px 34px 8px -28px;
  background: linear-gradient(90deg, rgba(96,165,250,0), rgba(96,165,250,.65));
  border: 0;
  filter: blur(6px);
}
.projectile-power-ball-core {
  position: absolute;
  inset: 10px;
  border-radius: inherit;
  background: rgba(255,255,255,.85);
  filter: blur(1px);
}

/* Global customizable keybind settings */
.hq-key-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}
.hq-key-group {
  display: grid;
  gap: 7px;
  padding: 10px;
  border-radius: 14px;
  background: rgba(255,255,255,.055);
  border: 1px solid rgba(255,255,255,.10);
}
.hq-key-group-title {
  color: rgba(255,255,255,.72);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.hq-key-row {
  display: grid;
  grid-template-columns: minmax(130px, 1fr) 96px 72px;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 9px 10px;
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 10px;
  background: rgba(0,0,0,.24);
  color: #fff;
  text-align: left;
  cursor: pointer;
}
.hq-key-row:hover,
.hq-key-row.is-waiting {
  border-color: rgba(96,165,250,.72);
  background: rgba(37,99,235,.20);
}
.hq-key-row strong {
  font-size: 13px;
  font-weight: 900;
}
.hq-key-row span {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  min-height: 28px;
  padding: 3px 9px;
  border-radius: 8px;
  color: #111827;
  background: rgba(255,255,255,.92);
  font-weight: 950;
  box-shadow: inset 0 -2px 0 rgba(0,0,0,.18);
}
.hq-key-row em {
  color: rgba(255,255,255,.56);
  font-size: 10px;
  font-style: normal;
  font-weight: 900;
  text-align: right;
  text-transform: uppercase;
}
.hq-settings-title {
  margin-top: 8px;
  color: #fff;
  font-size: 15px;
  font-weight: 950;
  letter-spacing: .02em;
}
.hq-settings-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
.hq-settings-mini-btn {
  border: 1px solid rgba(255,255,255,.16);
  border-radius: 999px;
  background: rgba(255,255,255,.10);
  color: #fff;
  font-weight: 900;
  padding: 8px 12px;
  cursor: pointer;
}
.hq-settings-status {
  min-height: 18px;
  color: rgba(255,255,255,.72);
  font-size: 12px;
  font-weight: 800;
}

/* Settings tabs cleanup: one category at a time, no horizontal overflow. */
#hqSettingsOverlay .hq-info-card {
  width: min(760px, 94vw);
  max-height: 86vh;
  overflow-y: auto;
  overflow-x: hidden;
}
#hqSettingsOverlay .hq-info-body,
#hqSettingsOverlay .hq-key-grid,
#hqSettingsOverlay .hq-key-group,
#hqSettingsOverlay .hq-key-list {
  min-width: 0;
  max-width: 100%;
}
#hqSettingsOverlay .hq-settings-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 2px;
}
#hqSettingsOverlay .hq-settings-tab {
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px;
  background: rgba(255,255,255,.08);
  color: #dbeafe;
  font: inherit;
  font-size: 12px;
  font-weight: 950;
  padding: 9px 12px;
  cursor: pointer;
}
#hqSettingsOverlay .hq-settings-tab.is-active {
  background: linear-gradient(180deg,#60a5fa,#2563eb);
  border-color: rgba(147,197,253,.7);
  color: #fff;
  box-shadow: 0 8px 22px rgba(37,99,235,.28);
}
#hqSettingsOverlay .hq-key-grid {
  display: block;
  width: 100%;
  margin-top: 0;
}
#hqSettingsOverlay .hq-key-group--active {
  display: grid;
  gap: 10px;
  padding: 12px;
  border-radius: 16px;
  background: rgba(255,255,255,.055);
  border: 1px solid rgba(255,255,255,.10);
}
#hqSettingsOverlay .hq-key-group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
#hqSettingsOverlay .hq-key-group-subtitle {
  margin-top: 3px;
  color: rgba(255,255,255,.58);
  font-size: 12px;
  font-weight: 800;
}
#hqSettingsOverlay .hq-key-list {
  display: grid;
  gap: 8px;
}
#hqSettingsOverlay .hq-key-row {
  display: grid;
  grid-template-columns: minmax(160px, 1fr) minmax(90px, 128px) 74px;
  align-items: center;
  gap: 10px;
  width: 100%;
  box-sizing: border-box;
}
#hqSettingsOverlay .hq-key-row strong {
  margin: 0;
}
#hqSettingsOverlay .hq-key-row span {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  min-height: 30px;
  padding: 3px 10px;
  border-radius: 9px;
  background: rgba(255,255,255,.94);
  color: #111827;
  font-weight: 950;
  box-shadow: inset 0 -2px 0 rgba(0,0,0,.18);
}
#hqSettingsOverlay .hq-key-row em {
  text-align: right;
  text-transform: uppercase;
}
#hqSettingsOverlay .hq-key-row.is-waiting {
  border-color: rgba(96,165,250,.75);
  background: rgba(37,99,235,.20);
}
@media (max-width: 720px) {
  #hqSettingsOverlay .hq-key-row {
    grid-template-columns: 1fr;
    gap: 7px;
  }
  #hqSettingsOverlay .hq-key-row em {
    text-align: left;
  }
  #hqSettingsOverlay .hq-key-group-head {
    align-items: stretch;
    flex-direction: column;
  }
}


/* Direct fallback X weapon strike. This does not depend on the surfboard PNG, hitbox debug, or character renderer. */
.player > .weapon-strike-fx {
  position: absolute;
  pointer-events: none;
  z-index: 9999;
  display: none;
  border-radius: 999px;
  transform-origin: center center;
  mix-blend-mode: screen;
  filter: drop-shadow(0 0 12px rgba(125, 230, 255, .95)) drop-shadow(0 0 22px rgba(255,255,255,.7));
}
.player > .weapon-strike-fx.is-active {
  display: block !important;
  animation: expWeaponStrikeFallbackPulse .16s ease-out both;
}
@keyframes expWeaponStrikeFallbackPulse {
  0% { opacity: 0; }
  20% { opacity: 1; }
  100% { opacity: 0; }
}
.weapon-strike-fx__arc {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: radial-gradient(circle at 18% 50%, rgba(255,255,255,.98) 0%, rgba(125,230,255,.95) 36%, rgba(125,230,255,.42) 55%, rgba(125,230,255,0) 74%);
  -webkit-mask-image: radial-gradient(circle at 0% 50%, transparent 34%, black 37%);
  mask-image: radial-gradient(circle at 0% 50%, transparent 34%, black 37%);
  border: 2px solid rgba(255,255,255,.42);
}
.weapon-strike-fx__spark {
  position: absolute;
  left: 52%;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 999px;
  transform: translate(-50%, -50%);
  background: rgba(255,255,255,.96);
  box-shadow: 0 0 18px rgba(255,255,255,.96), 0 0 32px rgba(125,230,255,.9);
}

/* EXP Tube live face monster heads */
.live-face-capture-status {
  position: fixed;
  right: 18px;
  bottom: 118px;
  z-index: 100000;
  max-width: 320px;
  border-radius: 999px;
  padding: 10px 14px;
  background: rgba(10, 15, 28, .86);
  color: #fff;
  border: 1px solid rgba(255,255,255,.16);
  box-shadow: 0 14px 38px rgba(0,0,0,.38);
  font: 800 12px/1.25 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  pointer-events: none;
}
.live-face-capture-status[data-kind="ok"] { border-color: rgba(34,197,94,.45); }
.live-face-capture-status[data-kind="error"] { border-color: rgba(248,113,113,.58); }
.monster { overflow: visible; }
.monster .monster-body-img { position: relative; z-index: 1; }
/* Sprite + face live in ONE wrapper so they flip, scale, rotate and die as a single unit —
   the face is locked to the PNG (fixes the face detaching on death and landing on the wrong
   side when the monster faces the other way). Flip + death animation ride on the wrapper. */
.monster .monster-visual { position: absolute; inset: 0; transform: scaleX(var(--monster-facing, 1)); transform-origin: center bottom; }
.monster .monster-face-head {
  position: absolute;
  z-index: 2;
  left: 50%;
  /* Admin-tunable placement for persistent face monsters (falls back to the
     live-face defaults when the monster doesn't set them). */
  top: var(--face-top, 19%);
  width: calc(39% * var(--face-scale, 1));
  height: 43%;
  object-fit: contain;
  transform: translateX(-50%);
  transform-origin: center center;
  border-radius: 0;
  filter: drop-shadow(0 5px 8px rgba(0,0,0,.38));
  pointer-events: none;
}
.monster--cake-boss .monster-face-head {
  top: 11%;
  width: 26%;
  height: 28%;
}
/* Face monster: inline left/top/height come from the admin's normalized facebox;
   center the face on that point (top is the box CENTER, not the top edge). */
.monster--facebox .monster-face-head {
  transform: translate(-50%, -50%);
}
/* face fades together with the sprite via the .monster-visual death animation */


/* Fullscreen game mode: the stage becomes the whole screen while the existing game
   camera/render loop keeps control. Covers BOTH the stage-fullscreen path and the
   documentElement-fullscreen path (the latter keeps body-appended menus visible). */
.hq-stage:fullscreen,
.hq-stage:-webkit-full-screen,
:fullscreen .hq-stage,
:-webkit-full-screen .hq-stage {
  width: 100vw !important;
  height: 100vh !important;
  max-width: none !important;
  max-height: none !important;
  border-radius: 0 !important;
  border: 0 !important;
  box-shadow: none !important;
  background: #07101c !important;
}
.hq-stage:fullscreen .hq-world,
.hq-stage:-webkit-full-screen .hq-world,
:fullscreen .hq-stage .hq-world,
:-webkit-full-screen .hq-stage .hq-world {
  transform-origin: top left !important;
}
.hq-stage:fullscreen .exp-social-nav,
.hq-stage:-webkit-full-screen .exp-social-nav,
:fullscreen .exp-social-nav,
:-webkit-full-screen .exp-social-nav {
  display: none !important;
}
/* Document fullscreen is the path the game uses, because fullscreening the stage
   hides every overlay appended to <body>. That means the page's own chrome is now
   inside the fullscreen element, so it has to be told to get out of the way — and
   the frame's letterbox padding has to go, or the 100vw stage overflows it. */
:fullscreen .app-header,
:-webkit-full-screen .app-header {
  display: none !important;
}
:fullscreen .hq-frame,
:-webkit-full-screen .hq-frame {
  padding: 0 !important;
}

/* Video playback should overlay the current map art, not replace it.
   The full video element can be used for fit/background modes, but its
   empty letterbox area must stay transparent so the real map background remains visible. */
.exp-bg-video,
.exp-bg-video.is-playing,
.exp-bg-video[data-video-mode="fit"],
.exp-bg-video[data-video-mode="background"],
.exp-bg-video[data-video-mode="theater"],
.exp-bg-video[data-video-mode="corner"] {
  background: transparent !important;
}
.exp-bg-video.is-playing[data-video-mode="fit"] {
  opacity: 1 !important;
  object-fit: contain !important;
}
.exp-bg-video.is-playing[data-video-mode="background"] {
  opacity: 1 !important;
  object-fit: cover !important;
}
.exp-bg-video.is-playing[data-video-mode="theater"],
.exp-bg-video.is-playing[data-video-mode="corner"] {
  opacity: 1 !important;
}
/* Monster Map background is resolved by map config/runtime, not CSS fallbacks. */



/* Active video lives inside the moving scene between the real map art and gameplay.
   This keeps Monster Map background visible while theater/corner video plays below monsters, portals, paths, projectiles, and player. */
.hq-scene > .hq-bg-layer--image { z-index: 1; }
.hq-scene > .exp-bg-video { z-index: 20; pointer-events: none; }
.hq-scene > .hq-bg-layer--shade { z-index: 3; pointer-events: none; }
.hq-scene > .hq-ground { z-index: 4; }
.exp-map-monster-map .hq-bg-layer--image {
  background-position: center bottom;
  background-repeat: no-repeat;
}

/* Active video controls must sit above gameplay hit layers.
   The thumbnail wall stays behind gameplay until a video is selected; once
   selected, the collapsed player controls are real UI and must receive clicks
   before portals/monsters/player layers. */
.exp-video-panel.exp-video-panel--player-active,
.exp-map-home-hq .exp-video-panel.exp-video-panel--player-active,
body.exp-video-has-active-player .exp-video-panel {
  z-index: 10060 !important;
  pointer-events: auto !important;
}
.exp-video-panel.exp-video-panel--player-active .exp-video-controls,
.exp-video-panel.exp-video-panel--player-active .exp-video-controls *,
body.exp-video-has-active-player #expVideoControls,
body.exp-video-has-active-player #expVideoControls * {
  pointer-events: auto !important;
}

.exp-video-panel.exp-video-panel--player-active .exp-video-controls,
body.exp-video-has-active-player #expVideoControls {
  display: grid !important;
  grid-template-columns: auto auto auto minmax(110px, 190px);
  align-items: center;
  gap: 8px;
}

#expVideoCloseBtn {
  border-color: rgba(248,113,113,.72) !important;
  background: rgba(127,29,29,.88) !important;
  color: #fff !important;
}

/* Active video click target.
   This sits exactly over the rendered video rectangle so gameplay layers under it
   cannot steal video play/pause clicks. It is runtime-positioned from the video
   element's real bounding box, so it does not fake/override the map background. */
.exp-video-click-layer {
  position: absolute;
  z-index: 10055 !important;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  padding: 0;
  margin: 0;
  border-radius: inherit;
  background: transparent;
  color: #fff;
  cursor: pointer;
  pointer-events: auto !important;
  user-select: none;
  touch-action: manipulation;
}
.exp-video-click-layer[hidden] {
  display: none !important;
}
.exp-video-click-layer__icon {
  width: 74px;
  height: 74px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(5, 9, 19, .58);
  border: 2px solid rgba(255,255,255,.72);
  box-shadow: 0 18px 48px rgba(0,0,0,.38), 0 0 26px rgba(59,130,246,.22);
  font-size: 30px;
  font-weight: 900;
  line-height: 1;
  opacity: 0;
  transform: scale(.92);
  transition: opacity .14s ease, transform .14s ease;
}
.exp-video-click-layer:hover .exp-video-click-layer__icon,
.exp-video-click-layer.is-paused .exp-video-click-layer__icon {
  opacity: 1;
  transform: scale(1);
}

/* Active video positioning is calculated in legacy-game.js.
   Theater/corner are world-anchored scene objects, not camera/player locked overlays. */
.hq-scene > .exp-bg-video[data-video-mode="background"],
.hq-scene > .exp-bg-video[data-video-mode="fit"],
.hq-scene > .exp-bg-video[data-video-mode="theater"],
.hq-scene > .exp-bg-video[data-video-mode="corner"] {
  right: auto !important;
  bottom: auto !important;
}
.exp-bg-video--world-anchored {
  position: absolute !important;
  transform: none !important;
}

/* Theater mode: video window only. No fake/blank screen or video backdrop. */
.exp-bg-video[data-video-mode="theater"] {
  background: transparent !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
.exp-bg-video[data-video-mode="theater"]::before,
.exp-bg-video[data-video-mode="theater"]::after {
  display: none !important;
  content: none !important;
}


/* Monster Map + Theater video final layer rule:
   real map art stays visible at all times; Theater is only the video rectangle. */
.exp-map-monster-map .hq-bg-layer--image {
  display: block !important;
  visibility: visible !important;
  opacity: 1 !important;
  z-index: 1 !important;
  filter: none !important;
  transform: none !important;
  background-image: url('/assets/maps/monster-map/main.webp') !important;
  background-size: cover !important;
  background-position: center bottom !important;
  background-repeat: no-repeat !important;
}
.exp-map-monster-map .hq-bg-layer--shade {
  display: none !important;
  opacity: 0 !important;
  background: transparent !important;
}
.exp-map-monster-map .hq-scene > .exp-bg-video[data-video-mode="theater"],
.exp-map-monster-map .hq-scene > .exp-bg-video[data-video-mode="corner"] {
  z-index: 22 !important;
  opacity: 1 !important;
  background: transparent !important;
  filter: none !important;
  mix-blend-mode: normal !important;
}
.exp-map-monster-map .hq-scene > .exp-bg-video[data-video-mode="theater"] {
  object-fit: cover !important;
}
.exp-map-monster-map .hq-ground,
.exp-map-monster-map .platform-layer,
.exp-map-monster-map .map-visual-layer--back {
  z-index: 24 !important;
}
.exp-map-monster-map .portal-layer,
.exp-map-monster-map .monster-layer,
.exp-map-monster-map .projectile-layer,
.exp-map-monster-map .players-layer,
.exp-map-monster-map .player,
.exp-map-monster-map .map-visual-layer--front {
  z-index: 30 !important;
}

/* Attack Studio runtime animation frames */
.studio-ability-fx {
  position: absolute;
  z-index: 18;
  display: none;
  width: auto;
  height: auto;
  max-width: none;
  pointer-events: none;
  transform-origin: center center;
  image-rendering: auto;
  filter: drop-shadow(0 5px 7px rgba(0,0,0,.26));
}
.studio-ability-fx.is-active { display: block; }

/* Backpack Burst projectile. Deliberately not .projectile--duckies-pack — that
   class is pinned to 64x30 with !important further up this file, which was
   shrinking the thrown backpack to a sliver and overriding the size configured
   in the Attack Studio. 176px matches PLAYER_WIDTH, so an unconfigured backpack
   still reads as roughly character-sized. */
.projectile.projectile--backpack {
  width: 176px;
  height: 176px;
  background: transparent;
  z-index: 80;
  filter:
    drop-shadow(0 0 14px rgba(239, 68, 68, .95))
    drop-shadow(0 0 34px rgba(239, 68, 68, .65))
    drop-shadow(0 8px 14px rgba(0, 0, 0, .4));
}
.projectile.projectile--backpack img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
}
.projectile.projectile--backpack .projectile-sugar-bomb {
  display: block;
  font-size: 150px;
  line-height: 1;
}

/* MapleStory-style EXP ticker, bottom right. Stacks upward so the newest kill
   sits closest to the corner and older lines drift away. */
.exp-gain-tray {
  position: fixed;
  right: 26px;
  bottom: 96px;
  z-index: 7000;
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-end;
  gap: 4px;
  pointer-events: none;
}
.exp-gain-line {
  font: 900 28px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
  letter-spacing: .5px;
  color: #ffffff;
  -webkit-text-stroke: 4px #14532d;
  paint-order: stroke fill;
  text-shadow: 0 3px 0 #14532d, 0 0 16px rgba(74, 222, 128, .85);
  animation: expGainRise 2.4s ease-out forwards;
}
@keyframes expGainRise {
  0%   { opacity: 0; transform: translateY(16px) scale(.75); }
  12%  { opacity: 1; transform: translateY(0) scale(1.1); }
  24%  { opacity: 1; transform: translateY(0) scale(1); }
  75%  { opacity: 1; transform: translateY(-6px); }
  100% { opacity: 0; transform: translateY(-30px); }
}

/* ---- Keyboard Settings: filter tabs, icons, drag-to-bind ---- */
.hq-kbmap-side {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 8px;
}
.hq-kbmap-tabs {
  display: flex;
  gap: 6px;
  flex: 0 0 auto;
}
.hq-kbmap-tab {
  flex: 1;
  padding: 7px 4px;
  border-radius: 9px;
  border: 1px solid rgba(148, 163, 184, .22);
  background: rgba(15, 23, 42, .6);
  color: #cbd5e1;
  font: 700 12px/1 system-ui, sans-serif;
  letter-spacing: .3px;
  cursor: pointer;
}
.hq-kbmap-tab:hover { border-color: rgba(148, 163, 184, .5); color: #f8fafc; }
.hq-kbmap-tab.is-active {
  background: linear-gradient(180deg, rgba(45, 212, 191, .28), rgba(13, 148, 136, .22));
  border-color: rgba(45, 212, 191, .65);
  color: #f0fdfa;
}

/* Icon in a palette row or on a bound key */
.hq-kbmap-icon {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  object-fit: contain;
  border-radius: 5px;
}
.hq-kbmap-icon--emoji {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  line-height: 1;
}
.hq-kbmap-note {
  font: 700 10px/1 system-ui, sans-serif;
  color: #fbbf24;
  margin-left: 5px;
}
.hq-kbmap-palette__row.is-dim { opacity: .5; }
.hq-kbmap-palette__row.is-dim:hover { opacity: .78; }

/* The thing that follows the cursor while dragging */
.hq-kbmap-ghost {
  position: fixed;
  z-index: 99999;
  transform: translate(-50%, -140%);
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 11px;
  border-radius: 10px;
  pointer-events: none;
  background: rgba(2, 8, 20, .94);
  border: 1px solid rgba(45, 212, 191, .7);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .5);
  color: #f0fdfa;
  font: 700 12px/1 system-ui, sans-serif;
  white-space: nowrap;
}
.hq-kbmap-overlay.is-dragging { cursor: grabbing; }
.hq-kbmap-overlay.is-dragging .hq-kbmap-key { transition: none; }
.hq-kbmap-key.is-drop {
  outline: 2px solid rgba(45, 212, 191, .95);
  outline-offset: 1px;
  background: rgba(45, 212, 191, .2);
}

/* Skill / potion art on a bound key. The key is ~31px wide, so a text chip
   truncated "Backpack Burst" to "Back..." — the icon reads instantly and the full
   name stays on the tooltip. */
.hq-kbmap-keyicon {
  display: block;
  width: 26px;
  height: 26px;
  margin: 1px auto 0;
  object-fit: contain;
  border-radius: 5px;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .6));
  pointer-events: none;
}
.hq-kbmap-keyicon--emoji {
  font-size: 20px;
  line-height: 26px;
  text-align: center;
}
.hq-kbmap-key.is-icon {
  padding-bottom: 3px;
}
.hq-kbmap-key.is-icon .hq-kbmap-cap {
  font-size: 9px;
  opacity: .72;
  line-height: 1;
}

/* Thrown fruit: 3x the 44px default, because a coconut read as a speck.
   The CONTAINER has to grow too — .projectile is 28px and its rules outrank a
   class on the <img> alone, which is the same trap the thrown backpack hit. */
.projectile.projectile--fruit { width: 190px; height: 190px; }
.projectile.projectile--fruit .projectile-art { width: 100%; height: 100%; }
/* Tumbling, so a big sprite reads as thrown rather than sliding sideways. */
.projectile.projectile--fruit .projectile-art { animation: hqFruitSpin .7s linear infinite; }
@keyframes hqFruitSpin { to { transform: rotate(360deg); } }

/* A jackfruit falling out of a tree, not a loot pip. .drop is 40px — correct
   for a coin, absurd for fruit the size of a character's torso. */
.drop.drop--farm-fruit { width: 132px; height: 132px; }
.drop.drop--farm-fruit img { width: 100%; height: 100%; object-fit: contain; }

/* ── The Fort ────────────────────────────────────────────────────────────────
   The one structure with HP. The art draws exactly like a building (.map-fort
   inherits .map-visual), and the bar hangs above it so a siege is readable
   from across a 6000px map without hunting for a health number. */
.map-fort-bar{
  position:absolute;
  pointer-events:none;
  user-select:none;
  z-index:26;
  font:700 clamp(13px,1.1vw,20px)/1.2 system-ui,-apple-system,"Segoe UI",sans-serif;
  text-align:center;
}
.map-fort-bar__label{
  display:flex;
  justify-content:center;
  gap:.6em;
  color:#fde68a;
  text-shadow:0 2px 6px rgba(0,0,0,.9),0 0 2px rgba(0,0,0,1);
  letter-spacing:.04em;
  text-transform:uppercase;
  margin-bottom:.35em;
}
.map-fort-bar__label span{ color:#fff; font-variant-numeric:tabular-nums; }
.map-fort-bar__track{
  height:clamp(10px,.9vw,16px);
  border-radius:999px;
  background:rgba(0,0,0,.62);
  border:2px solid rgba(253,230,138,.55);
  overflow:hidden;
  box-shadow:0 2px 10px rgba(0,0,0,.6);
}
.map-fort-bar__fill{
  height:100%;
  background:#fbbf24;
  transition:width .25s ease-out,background-color .25s ease-out;
}
/* The colour is set from the actual HP fraction in fortHtml rather than from
   the fill's own width, because a gradient on a shrinking box just compresses
   and a fort at 5% would still show the full healthy sweep. */
.map-fort-bar.is-hurt .map-fort-bar__fill{ background:#f59e0b; }
.map-fort-bar.is-low .map-fort-bar__fill{ background:#ef4444; }
.map-fort-bar.is-low .map-fort-bar__track{ border-color:rgba(239,68,68,.85); }
.map-fort-bar__label em{
  font-style:normal;
  padding:0 .5em;
  border-radius:999px;
  background:rgba(0,0,0,.6);
  border:1px solid rgba(253,230,138,.5);
  color:#fde68a;
}

/* The place's name standing over its own HQ. Every world is built from the
   same three maps, so this is what makes one belong to somebody. */
.map-worldname{
  position:absolute;
  left:0;
  right:0;
  text-align:center;
  pointer-events:none;
  user-select:none;
  z-index:1;
  font-family:'Anton',Impact,'Arial Black',system-ui,sans-serif;
  font-weight:400;             /* Anton has one weight; 700 would fake-bold it */
  letter-spacing:.015em;
  line-height:1;
  text-transform:uppercase;
  color:#f8fbff;
  white-space:nowrap;
  /* Outline BEHIND the fill, not through it. Without paint-order a centred
     stroke eats half the letterform and the name reads as mush at this size. */
  -webkit-text-stroke:.075em #0a1030;
  paint-order:stroke fill;
  text-shadow:
    0 0 .08em rgba(147,197,253,.95),
    0 0 .22em rgba(59,130,246,.85),
    0 0 .5em rgba(37,99,235,.6),
    0 .04em .1em rgba(0,0,0,.65);
  opacity:.96;
}

/* ── Monster speech ──────────────────────────────────────────────────────────
   What a monster says when it is hit, when it is nearly dead, or when the thing
   standing next to it dies. Sits above the sprite and outside .monster-visual
   so it never flips with the monster's facing — a mirrored speech bubble reads
   as a rendering bug.

   z-index above the HP bar: a bubble that appears behind the bar looks like it
   is glitching through the monster rather than belonging to it. */
.monster .monster-bubble {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 10px);
  transform: translateX(-50%);
  z-index: 6;
  width: max-content;
  max-width: 22ch;
  padding: 7px 12px;
  border-radius: 14px;
  background: rgba(255, 255, 255, .97);
  color: #14181d;
  font: 800 15px/1.3 system-ui, -apple-system, "Segoe UI", sans-serif;
  text-align: center;
  white-space: normal;
  overflow-wrap: anywhere;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .35);
  pointer-events: none;
  animation: monsterBubbleIn .16s ease-out;
}
.monster .monster-bubble[hidden] { display: none; }

/* The tail, so it reads as speech rather than as a floating label. */
.monster .monster-bubble::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 7px solid transparent;
  border-top-color: rgba(255, 255, 255, .97);
}

@keyframes monsterBubbleIn {
  from { opacity: 0; transform: translateX(-50%) translateY(4px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* A defeated monster's last words stay put while it falls, rather than sinking
   through the floor with the sprite. */
.monster--defeated .monster-bubble { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .monster .monster-bubble { animation: none; }
}

/* ── The graffiti wall, from inside the world ────────────────────────────────
   The one piece of scenery you can touch. Everything else in .map-visual is
   backdrop, so this has to announce itself or nobody discovers it — the hint
   is always visible rather than hover-only, because on a phone there is no
   hover and this is the whole point of standing here. */
.map-visual--graffiti { cursor: pointer; pointer-events: auto; }
.map-visual--graffiti img { transition: filter .15s ease; }
.map-visual--graffiti:hover img { filter: brightness(1.12) saturate(1.08); }

.map-visual--graffiti .map-visual__hint {
  position: absolute;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(8, 20, 30, .82);
  color: #43dced;
  font: 800 15px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .4);
  animation: graffitiHintPulse 2.4s ease-in-out infinite;
}
.map-visual--graffiti:hover .map-visual__hint {
  background: #43dced;
  color: #062238;
  animation: none;
}

@keyframes graffitiHintPulse {
  0%, 100% { opacity: .78; }
  50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .map-visual--graffiti .map-visual__hint { animation: none; }
}

/* Flipbook monsters (monsters/monster-frames.mjs). The frames carry the pose;
   these add the motion between them. They move the IMG, never .monster-visual:
   that wrapper owns the facing flip and the death fade. Because the img sits
   inside the flip, translateX(+) always means "forward". */
.monster--framed .monster-body-img { transform-origin: 50% 100%; will-change: transform; }
.monster--framed.monster--clip-idle .monster-body-img { animation: mfBreathe 1.6s ease-in-out infinite; }
.monster--framed.monster--clip-walk .monster-body-img { animation: mfScuttle .3s ease-in-out infinite; }
.monster--framed.monster--clip-attack .monster-body-img { animation: mfLunge .42s cubic-bezier(.3,1.4,.5,1) both; }
.monster--framed.monster--clip-hit .monster-body-img { animation: mfShake .24s linear both; }
.monster--framed.monster--clip-aggro .monster-body-img { animation: mfPuff .48s ease-out both; }
.monster--framed.monster--clip-emote .monster-body-img { animation: mfHop .46s ease-in-out 2; }
.monster--framed.monster--clip-stunned .monster-body-img { animation: mfWobble .9s ease-in-out infinite; }
.monster--framed.monster--clip-spawn .monster-body-img { animation: mfRise .74s cubic-bezier(.2,1.3,.5,1) both; }
@keyframes mfBreathe { 0%,100% { transform: scale(1,1); } 50% { transform: scale(.985,1.035); } }
@keyframes mfScuttle { 0%,100% { transform: translateY(0) rotate(-1.5deg); } 50% { transform: translateY(-4%) rotate(1.5deg); } }
@keyframes mfLunge { 0% { transform: translateX(-4%) scale(1.03,.95); } 45% { transform: translateX(9%) scale(1.06,.97); } 100% { transform: translateX(0) scale(1); } }
@keyframes mfShake { 0%,100% { transform: translateX(0); } 20% { transform: translateX(-5%) rotate(-3deg); } 40% { transform: translateX(4%) rotate(2deg); } 60% { transform: translateX(-3%); } 80% { transform: translateX(2%); } }
@keyframes mfPuff { 0% { transform: scale(1); } 35% { transform: scale(1.12,1.08); } 100% { transform: scale(1); } }
@keyframes mfHop { 0%,100% { transform: translateY(0) scale(1.04,.95); } 50% { transform: translateY(-14%) scale(.97,1.04); } }
@keyframes mfWobble { 0%,100% { transform: rotate(-4deg); } 50% { transform: rotate(4deg); } }
@keyframes mfRise { 0% { transform: translateY(30%) scale(1,.5); opacity: .2; } 60% { transform: translateY(-6%) scale(1,1.08); opacity: 1; } 100% { transform: translateY(0) scale(1); } }

/* Drop ownership (server/dropClaim.js): the killer has a few seconds to take
   their drops. Theirs glow gold for them; everyone else sees them faded with a
   lock until the hold runs out. */
.drop.drop--mine { filter: drop-shadow(0 4px 8px rgba(0,0,0,.45)) drop-shadow(0 0 12px rgba(250,204,21,.85)); }
.drop.drop--claimed { opacity: .5 !important; filter: grayscale(.55) drop-shadow(0 4px 8px rgba(0,0,0,.4)); }
.drop.drop--claimed::before {
  content: "\1F512"; position: absolute; right: -6px; top: -8px; z-index: 1;
  font-size: 15px; line-height: 1; filter: drop-shadow(0 1px 2px rgba(0,0,0,.6));
}
/* Picked up: scooped into the picker (renderPickedDrops), shrinking as it goes. */
.drop.drop--picked { z-index: 80; transform: translate(-50%, 0) scale(var(--pick-scale, 1)); }
.drop.drop--picked img { animation: none; }

/* Inventory + Equipped windows: black instead of blue, and smaller with the
   same layout (user, 2026-09-29). Scoped by id so the shop and every other
   modal keep their look. The item profile is on hover (item-tooltip.js). */
#hqInventoryModal, #hqEquippedModal { width: min(320px, 94vw); }
#hqInventoryModal .hq-inventory-box, #hqEquippedModal .hq-inventory-box {
  background: linear-gradient(180deg, #161616, #050505);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 14px;
  max-height: min(70vh, 470px);
  color: #f5f5f5;
}
#hqInventoryModal .hq-inventory-frame, #hqEquippedModal .hq-inventory-frame { padding: 7px; }
#hqInventoryModal .hq-inventory-titlebar, #hqEquippedModal .hq-inventory-titlebar { margin-bottom: 6px; gap: 8px; }
#hqInventoryModal .hq-inventory-title, #hqEquippedModal .hq-inventory-title { font-size: 14px; }
#hqInventoryModal .hq-modal-close, #hqEquippedModal .hq-modal-close {
  background: #262626; border-color: rgba(255,255,255,.16); border-radius: 8px; padding: 4px 9px; font-size: 12px;
}
#hqInventoryModal .hq-inventory-tabs { gap: 4px; margin-bottom: 7px; }
#hqInventoryModal .hq-inventory-tab { padding: 4px 7px; font-size: 10px; border-radius: 6px; background: rgba(255,255,255,.07); }
#hqInventoryModal .hq-inventory-panel, #hqEquippedModal .hq-inventory-panel {
  background: rgba(255,255,255,.035); border-radius: 9px; padding: 7px;
  max-height: calc(min(70vh, 470px) - 88px);
}
#hqInventoryModal .hq-modal-coins { font-size: 11px; color: #d4d4d4; margin-bottom: 6px; }
#hqInventoryModal .hq-inventory-grid, #hqEquippedModal .hq-inventory-grid { gap: 6px; margin-top: 7px; }
#hqInventoryModal .hq-inventory-slot, #hqEquippedModal .hq-inventory-slot {
  border-radius: 8px; border-color: rgba(255,255,255,.12);
  background: linear-gradient(180deg, rgba(255,255,255,.09), rgba(255,255,255,.025));
}
#hqInventoryModal .hq-inventory-slot-icon, #hqEquippedModal .hq-inventory-slot-icon { padding: 6px; }
#hqInventoryModal .hq-inventory-slot-count { font-size: 10px; right: 4px; bottom: 2px; }
#hqInventoryModal .hq-inventory-slot-badge, #hqInventoryModal .hq-inventory-slot-sub, #hqInventoryModal .hq-inventory-slot-eq,
#hqEquippedModal .hq-inventory-slot-badge, #hqEquippedModal .hq-inventory-slot-sub, #hqEquippedModal .hq-inventory-slot-eq { font-size: 9px; left: 4px; right: 4px; }
#hqInventoryModal .hq-inventory-slot-sub, #hqEquippedModal .hq-inventory-slot-sub { color: #e5e5e5; bottom: 2px; }
#hqInventoryModal .hq-inventory-slot-eq, #hqEquippedModal .hq-inventory-slot-eq { top: 4px; left: auto; padding: 1px 5px; }
#hqInventoryModal .hq-inventory-help, #hqEquippedModal .hq-inventory-help { font-size: 10px; color: #a3a3a3; margin-top: 7px; }

/* Using a scroll: the items it can go on glow, the rest step back. */
.hq-inventory-slot.is-scroll-target { outline: 2px solid #f6b93b; outline-offset: -2px; box-shadow: 0 0 12px rgba(246,185,59,.55); cursor: pointer; }
.hq-inventory-slot.is-scroll-dim { opacity: .35; filter: grayscale(.6); }
/* The piece a dragged scroll is over: it lands here on release. */
.hq-inventory-slot.is-scroll-target.is-scroll-hover { outline-color: #2ee6d6; box-shadow: 0 0 18px rgba(46,230,214,.85); transform: scale(1.06); }
.hq-inventory-slot--scroll .hq-inventory-slot-icon { filter: drop-shadow(0 0 4px rgba(120,170,255,.35)); }

/* The minimap (200 x 74 + label, top 46px, z-index 10110) was drawn OVER the
   channel button, so the MMO had channels nobody could find. The button sits
   just right of the minimap now (phones hide the minimap: back in the corner). */
body.hq-in-game .hq-channel-btn { left: 222px; top: 46px; z-index: 10112; }
body.hq-in-game .hq-channel-menu { left: 222px; top: 82px; }
body.hq-mobile-play .hq-channel-btn, body.hq-mobile-play .hq-channel-menu { left: 12px; }

/* Drops by the dozen without the lag (2026-10-05). Every drop carried two or
   three stacked drop-shadow FILTERS over a picture spinning forever, so the
   browser repainted each glow every frame -- forty coins, forty repaints.
   Drops now carry no filter at all: the shadow and the gold "yours" glow are a
   soft spot drawn underneath (a gradient, painted once), and the spin runs on
   the GPU. Coins and EXP coins draw smaller. */
.drop, .drop.drop--settled, .drop.drop--rare, .drop.drop--mine, .drop.drop--claimed { filter: none !important; }
.drop img { will-change: transform; backface-visibility: hidden; }
.drop.drop--settled img { animation-duration: 6s; }
.drop::after {
  content: ""; position: absolute; left: 50%; bottom: -6px; width: 80%; height: 10px; z-index: -1;
  transform: translateX(-50%); border-radius: 999px; pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.38), transparent 70%);
}
.drop.drop--settled::after { background: radial-gradient(ellipse at center, rgba(34,211,238,.38), rgba(0,0,0,.2) 45%, transparent 72%); opacity: 1; }
.drop.drop--mine::after { height: 16px; bottom: -8px; background: radial-gradient(ellipse at center, rgba(250,204,21,.75), rgba(250,204,21,.2) 50%, transparent 72%); }
.drop.drop--rare::after { height: 16px; bottom: -8px; background: radial-gradient(ellipse at center, rgba(250,204,21,.6), rgba(34,211,238,.25) 50%, transparent 72%); }
.drop.drop--claimed { opacity: .45 !important; }
.drop.drop--coin { width: 40px !important; height: 40px !important; min-width: 40px !important; min-height: 40px !important; }
/* Money drops by amount (engine step 30): the EXP dollar stack (100-999) and
   the money bag (1,000+) stand still and draw a little bigger than a coin. */
.drop.drop--cash { width: 50px !important; height: 50px !important; min-width: 50px !important; min-height: 50px !important; }
.drop.drop--bag { width: 58px !important; height: 58px !important; min-width: 58px !important; min-height: 58px !important; }
.drop.drop--cash img, .drop.drop--bag img { animation: none !important; transform: none !important; }
.drop.drop--flying.drop--cash img, .drop.drop--flying.drop--bag img { animation: none !important; }

/* Equipped window laid out as a body: head on top, face, chest with the
   weapon hand and the glove hand either side, legs, feet. A faint figure
   sits behind the middle two columns. */
#hqEquippedModal .hq-inventory-grid.eq-body {
  grid-template-columns: repeat(4, 1fr);
  grid-template-areas:
    ".        cap    bandana    ."
    "earrings mask   cape       ."
    "weapon   shirt  sweatshirt gloves"
    ".        shorts sweats     ."
    ".        shoes  .          .";
  position: relative;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 250'%3E%3Cg fill='%23ffffff' fill-opacity='.06'%3E%3Ccircle cx='50' cy='30' r='22'/%3E%3Crect x='24' y='58' width='52' height='80' rx='14'/%3E%3Crect x='4' y='64' width='16' height='66' rx='8'/%3E%3Crect x='80' y='64' width='16' height='66' rx='8'/%3E%3Crect x='26' y='136' width='21' height='92' rx='9'/%3E%3Crect x='53' y='136' width='21' height='92' rx='9'/%3E%3C/g%3E%3C/svg%3E") center / 50% 100% no-repeat;
}
#hqEquippedModal .eq-body [data-body-slot="cap"] { grid-area: cap; }
#hqEquippedModal .eq-body [data-body-slot="bandana"] { grid-area: bandana; }
#hqEquippedModal .eq-body [data-body-slot="earrings"] { grid-area: earrings; }
#hqEquippedModal .eq-body [data-body-slot="mask"] { grid-area: mask; }
#hqEquippedModal .eq-body [data-body-slot="cape"] { grid-area: cape; }
#hqEquippedModal .eq-body [data-body-slot="weapon"] { grid-area: weapon; }
#hqEquippedModal .eq-body [data-body-slot="shirt"] { grid-area: shirt; }
#hqEquippedModal .eq-body [data-body-slot="sweatshirt"] { grid-area: sweatshirt; }
#hqEquippedModal .eq-body [data-body-slot="gloves"] { grid-area: gloves; }
#hqEquippedModal .eq-body [data-body-slot="shorts"] { grid-area: shorts; }
#hqEquippedModal .eq-body [data-body-slot="sweats"] { grid-area: sweats; }
#hqEquippedModal .eq-body [data-body-slot="shoes"] { grid-area: shoes; }
#hqEquippedModal .eq-body .hq-inventory-slot:not(.has-item) { border-style: dashed; background: rgba(0,0,0,.18); }

/* Monsters stand ON the floor: a picture whose shape differs from its box is
   fitted to the box's BOTTOM edge, not centred in it (centring floated every
   monster whose box was taller than its picture). */
.monster .monster-body-img { object-position: 50% 100%; }

/* PHONES: NO PROMOTED LAYERS IN THE GAME.
   Everything above that says will-change asks the browser for a GPU layer of
   its own -- about 110 of them on a busy map, including the 7500x3500 scene
   at ~2.8x device pixels. A phone runs out of graphics memory long before a
   PC does, and Chrome then stops compositing layers: the HUD, weapon,
   monsters and name tags flickered and then vanished while the background
   stayed. Tested on a Galaxy A54 over USB (2026-10-13): flags on, flicker;
   off, none -- three times. Touch screens only; desktop keeps its layers. */
@media (pointer: coarse) {
  #gameRoot, #gameRoot * { will-change: auto !important; }
}
