/* Карта мира: канвас, маркеры, подписи, подсказки, панели поверх карты. */

/* ---------- Карта мира (MONO: карта в рамке, маркеры поверх) ---------- */
.map-wrap {
  position: relative; background: var(--panel-bg); border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
}
/* Карта занимает почти весь экран: под ней больше ничего нет, поэтому высоту
   берём по вьюпорту, а не по контенту страницы. */
.map-viewport {
  position: relative; overflow: hidden; height: calc(100vh - 190px); min-height: 560px;
  cursor: grab; touch-action: none; background: #0a0a0e;
}
.map-viewport.dragging { cursor: grabbing; }
/* --- Режим расстановки иконок мышью ---
   Панель висит поверх карты снизу, маркеры в этом режиме курсором «возить» и
   с подсветкой, чтобы их было видно среди рисунка. */
.map-place {
  position: absolute; left: .6rem; right: .6rem; bottom: .6rem; z-index: 6;
  display: grid; gap: .45rem; padding: .6rem .7rem;
  background: rgba(10, 10, 14, .95); border: 1px solid var(--accent);
}
/* display:grid выше перебивает браузерное [hidden]{display:none}, поэтому
   атрибут hidden нужно поддержать явно — иначе панель видна всегда. */
.map-place[hidden] { display: none; }
.map-place-head { display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap; }
.map-place-head .muted { font-size: .8rem; }
.map-place-row { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.map-place-token { display: flex; gap: .35rem; align-items: center; font-size: .82rem; }
.map-place-token input {
  min-width: 12rem; padding: .2rem .4rem; font: inherit; font-size: .82rem;
  color: var(--text); background: #0a0a0e; border: 1px solid var(--border);
}
.map-place-status { font-size: .8rem; color: var(--green); }
.map-place-status.bad { color: var(--accent-strong); }
.map-place-list {
  display: flex; flex-wrap: wrap; gap: .3rem .5rem; max-height: 5.5rem; overflow: auto;
  font-size: .76rem; color: var(--muted);
}
.map-place-item { white-space: nowrap; }
/* В режиме расстановки маркер только показывает курсор «возить» — рамки вокруг
   иконок нет: жёлтый контур перекрывал арт и сливался с подсветкой нарисованных
   структур на пергаменте. Отличать перемещённые можно по списку правок в панели. */
.map-placing .map-marker { cursor: grab; }
.map-placing .map-marker:active { cursor: grabbing; }
.map-placing .map-marker:hover > * { filter: brightness(1.25); }
.btn.on { border-color: var(--accent-strong); color: var(--accent-strong); }

/* Рейд с клиента без серверного состояния: маленькая точка, чтобы не спорить
   с картинками шестерки отслеживаемых боссов. */
.marker-boss.boss-plain > * {
  width: 7px; height: 7px; border-radius: 50%;
  background: #c2413f; box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .65);
}
.marker-boss.boss-plain:hover > * { background: var(--accent-strong); }

/* Подсказка при наведении: описание зоны из HuntingZone, состояние босса.
   В браузере это заменяет штатный title, который показывается через секунду. */
.map-tip {
  position: absolute; z-index: 8; max-width: 22rem; padding: .45rem .6rem;
  background: rgba(8, 8, 12, .96); border: 1px solid var(--accent);
  display: grid; gap: .15rem; pointer-events: none;
  font-size: .8rem; line-height: 1.35;
}
.map-tip[hidden] { display: none; }
.map-tip b { color: var(--accent); }
.map-tip-kind { color: var(--muted); font-size: .74rem; }
.map-tip-kind.alive { color: var(--green); }
.map-tip-kind.dead { color: #9aa0aa; }
/* Закреплённая подсказка: подпись в её конце и рамка на маркере, чтобы было
   видно, что она не прячется сама. */
.map-tip-pinned { color: var(--muted); font-size: .68rem; }
.marker-pinned .marker-icon { outline: 2px solid var(--accent); outline-offset: 2px; }
.map-tip-desc { margin: .15rem 0 0; color: var(--text); }

/* Подробная подсказка рейд-босса: картинка или знак рейда слева, статы
   справа, дроп-лист отдельной прокручиваемой полосой. Ширину подсказки для
   боссов расширяем — иначе дроп в две колонки не влезет. */
.map-tip:has(.map-tip-raid) {
  /* Ширину задаём явно, а не только максимальную: подсказка позиционирована
     абсолютно и иначе подстраивается под содержимое, а сетка дропа
     auto-fill в такой ширине схлопывалась бы в одну колонку. */
  width: min(94vw, 58rem); max-width: 94vw; pointer-events: auto;
  /* Аварийный случай: босс с сотней предметов. Тогда прокручивается вся
     подсказка целиком, а не список внутри неё. */
  max-height: calc(100vh - 190px); overflow-y: auto;
}
.map-tip-loading { color: var(--muted); font-size: .74rem; padding: .2rem 0; }
/* Шапка подсказки: картинка и статы в одной строке, дроп-лист под ними во всю
   ширину окна. Раньше шапка была блоком во всю ширину и съедала ~300px, а при
   попытке задать ей колонки список предметов получал втрое меньше места. */
.map-tip-raid {
  margin-top: .35rem; padding-top: .4rem;
  border-top: 1px solid var(--border-strong);
}
.map-tip-head { display: flex; gap: .6rem; align-items: flex-start; }
.map-tip-pic { width: 5.5rem; flex: 0 0 5.5rem; }
.map-tip-pic img { width: 100%; height: 6.5rem; object-fit: contain;
                   background: #0b0b0f; border: 1px solid var(--border); border-radius: 3px; }
.map-tip-mark { width: 3rem !important; height: 3rem !important; margin: 2rem auto; border: 0 !important; }
.map-tip-body { flex: 0 1 30rem; display: grid; gap: .2rem; align-content: start; }
.map-tip-title { margin: 0; color: var(--muted); font-size: .74rem; }
.map-tip-stats {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .05rem .7rem;
  margin-top: .15rem;
}
.map-tip-stat { display: flex; justify-content: space-between; gap: .5rem;
                font-size: .76rem; color: var(--muted); }
.map-tip-stat b { color: var(--text); font-weight: 500; font-variant-numeric: tabular-nums; }
.map-tip-drops-head { display: block; margin-top: .1rem; font-size: .8rem; }
.map-tip-drops {
  /* Без своей прокрутки: колонок столько, сколько влезло в широкую подсказку,
     предметов — сколько есть у босса. У Антараса их 111, у большинства 20. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: 0 .5rem; align-content: start;
}
.map-tip-drop { display: flex; gap: .28rem; align-items: center; font-size: .7rem;
                      line-height: 1.2; }
.map-tip-drop img { width: 16px; height: 16px; flex: 0 0 16px; }
.map-tip-drop-noic {
  width: 16px; height: 16px; flex: 0 0 16px; display: grid; place-items: center;
  font-size: .7rem;
  color: var(--muted); border: 1px solid var(--border); border-radius: 3px;
}
/* Строка дропа целиком в одну линию: раньше «33% ×17–51» переносилось на две
   строки и каждая позиция занимала 26px вместо 18 — список у Антараса вылезал
   за окно. Теперь название сокращается многоточием (полное — в подсказке при
   наведении), а цифры не переносятся никогда. */
.map-tip-drop-txt { display: flex; align-items: baseline; gap: .35em; min-width: 0;
                    white-space: nowrap; }
.map-tip-drop-name { color: var(--text); overflow: hidden; text-overflow: ellipsis;
                     white-space: nowrap; min-width: 0; flex: 0 1 auto; }
.map-tip-drop-chance { color: var(--muted); font-size: .68rem; white-space: nowrap;
                       flex: 0 0 auto; font-variant-numeric: tabular-nums; }
/* Полный экран: карта занимает весь экран целиком, рамка и отступы не нужны. */
.map-wrap:fullscreen, .map-wrap:-webkit-full-screen {
  background: #0a0a0e; border: none; margin: 0; width: 100%; height: 100%;
}
.map-wrap:fullscreen .map-viewport, .map-wrap:-webkit-full-screen .map-viewport {
  height: 100%; min-height: 0;
}
.map-wrap:fullscreen .map-legend, .map-wrap:-webkit-full-screen .map-legend {
  max-width: calc(100% - 1.2rem);
}
.map-canvas { position: absolute; top: 0; left: 0; transform-origin: 0 0; will-change: transform; }
.map-image { display: block; user-select: none; -webkit-user-drag: none; image-rendering: auto; }
.map-layer { position: absolute; inset: 0; }

/* Маркер рисуется 1:1 с картой: его размер задан в пикселях карты (арт клиента
   для зон, 10-17px для точек городов), поэтому при увеличении масштаба иконка
   растёт вместе с картой, а при отдалении уменьшается. Контр-масштаб
   (--map-inv) остаётся только у подписей: текст должен оставаться читаемым
   на любом масштабе. */
.map-marker {
  position: absolute; margin: 0; padding: 0;
  border: none; background: none; cursor: pointer; line-height: 0;
  transform: translate(-50%, -50%);
}
.map-marker .marker-icon { width: 30px; height: 30px; display: block; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .8)); }
.map-marker .marker-dot {
  display: block; width: 9px; height: 9px; border-radius: 50%;
  background: var(--green); box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .6);
}
/* Города: квадрат — обычный, ромб — с замком. Контр-масштаб маркера общий,
   поэтому у ромба остаётся только поворот. */
.marker-town .marker-square { border-radius: 1px; background: var(--text); width: 10px; height: 10px; }
.marker-town .marker-diamond {
  border-radius: 2px; background: var(--accent-strong); width: 12px; height: 12px;
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .6);
  transform: rotate(45deg);
}
.marker-town.marker-active .marker-dot { outline: 2px solid var(--accent); outline-offset: 2px; }
.marker-region .marker-region-zone {
  width: 7px; height: 7px; background: transparent;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .75);
}
.marker-region .marker-region-castle {
  width: 8px; height: 8px; background: transparent; border-radius: 2px;
  box-shadow: 0 0 0 1.5px var(--accent-strong);
}
.marker-region.marker-active .marker-dot { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Иконка зоны — арт клиента (WorldIcon). Размер приходит из MinimapRegion
   инлайном (Width/Height в пикселях карты), поэтому правило фиксированных
   30px ниже её не трогает: иконка живёт в координатах карты и масштабируется
   вместе с ней. */
.marker-region .marker-icon { filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .75)); }
.marker-region.marker-active .marker-icon { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Подпись зоны: позиция в координатах карты (едет с зумом), а размер текста
   контр-масштабируется, иначе на мелком зуме он превратится в нечитаемую кашу.
   На обзорном масштабе видны только подписи замков — их мало, и они важнее;
   остальные включаются приближением (класс .map-labels-on ставит map.js). */
.region-label {
  /* Подписи зон: Verdana, кегль как в игре (MapFontSize9/10), цвет
     светло-серый, обводка тонкая чёрная. Обводка идёт под заливкой
     (paint-order), иначе буквы выглядят жирнее, чем в клиенте.
     В игре те же подписи рисует Tahoma — он стоит вторым в списке и есть в
     системе (в Linux ставится пакетом ttf-tahoma). Ни Verdana, ни Tahoma в
     проект не кладутся: оба Microsoft's, лицензия не наша. */
  font-family: Verdana, Tahoma, 'DejaVu Sans', sans-serif;
  -webkit-text-stroke: 1px rgba(0, 0, 0, .82);
  paint-order: stroke fill;
  position: absolute; transform-origin: 0 0; pointer-events: none;
  white-space: nowrap; font-size: 10px; line-height: 1.1; font-weight: 400;
  color: #c9c9c9; text-shadow: 0 1px 1px rgba(0, 0, 0, .35);
  transform: scale(var(--map-inv, 1));
  display: none;
}
/* Замки в игре подписаны золотом, как и поселения. */
.region-label[data-kind="castle"] { display: block; color: #e8d17a; }
.map-labels-on .region-label { display: block; }
/* Плашка рекомендуемого уровня у названия зоны: цифры из rc_level клиента. */
.region-lvl {
  margin-left: .35em; padding: 0 .3em; border: 1px solid var(--accent-deep);
  border-radius: 3px; color: var(--accent); font-style: normal;
  font-size: .85em; line-height: 1.35; vertical-align: 1px;
  background: rgba(200, 162, 74, .1); text-shadow: none;
}
/* Места без значка (названия охотничьих зон, места «по блоку»): подпись
   включается раньше подписей зон — на обзорном плане они разнесены и не спорят
   друг с другом, а подписи зон с иконкой наезжают уже при 60%. Чуть мельче и
   приглушённее, чтобы не спорить с названиями поселений. */
.region-label[data-place] { display: none; font-size: 10px; }
.map-places-on .region-label[data-place] { display: block; }
.map-places-on .region-label[data-kind="castle"][data-place] { color: #ffeb9c; }
/* Галочка слоя сильнее правила приближения, поэтому объявлена последней. */
.region-label[hidden] { display: none; }
/* Подпись города: видна всегда, в отличие от подписей зон. Позиция в
   координатах карты, а размер контр-масштабируется — иначе на зуме текст
   превратится в нечитаемую кашу или растянется вместе с картой. */
.town-label {
  /* Поселения — тем же шрифтом и золотом, иначе зоны и города на карте
     выглядят по-разному. */
  font-family: Verdana, Tahoma, 'DejaVu Sans', sans-serif;
  -webkit-text-stroke: 1px rgba(0, 0, 0, .82);
  paint-order: stroke fill;
  position: absolute; transform-origin: 0 0; pointer-events: none;
  white-space: nowrap; font-size: 11px; line-height: 1.1;
  color: #e8d17a; text-shadow: 0 1px 1px rgba(0, 0, 0, .35);
  transform: translate(9px, 4px) scale(var(--map-inv, 1));
}
.town-label[hidden] { display: none; }
.marker-boss .marker-icon { border-radius: 50%; }
/* Поверженный рейд не гасим фильтром: клиентский знак map_raid_respawn
   уже серый, фильтр сделал бы его нечитаемым. */
.marker-boss.marker-active .marker-icon,
/* Точка игрока — элемент интерфейса, а не арт клиента, поэтому её размер не
   должен ехать вместе с картой. Без контр-масштаба на обзорном плане (21%)
   точка 9px превращалась в 1.9px, и игроков на карте просто не было видно.
   Считаем от центра (transform-origin 50% 50%), поэтому маркер остаётся
   точно на своём месте: translate(-50%,-50%) совмещает центр с точкой. */
.marker-player { transform: translate(-50%, -50%) scale(var(--map-inv, 1)); }
.marker-player.marker-active .marker-dot { outline: 2px solid var(--accent); outline-offset: 2px; }

.map-controls, .map-legend {
  position: absolute; z-index: 5; display: flex; gap: .4rem; align-items: center;
  background: rgba(10, 10, 14, .82); border: 1px solid var(--border); padding: .35rem .5rem;
}
/* Панель управления — в правом нижнем углу: сверху слева лежит легенда с
   галочками слоёв, а правый верхний угол карты остаётся свободным. В режиме
   расстановки снизу раскрывается панель на всю ширину — панель управления там
   не нужна, поэтому прячем её, чтобы не лезла под неё. */
.map-controls { bottom: .6rem; right: .6rem; }
.map-placing .map-controls { display: none; }
.map-legend { top: .6rem; left: .6rem; flex-wrap: wrap; max-width: calc(100% - 1.2rem); }
.map-zoom-label { color: var(--muted); font-size: .8rem; font-variant-numeric: tabular-nums; min-width: 3.2em; }
.map-counts { color: var(--muted); font-size: .8rem; }
.map-toggle { display: flex; align-items: center; gap: .3rem; color: var(--text); font-size: .82rem; cursor: pointer; }

.map-card {
  position: absolute; left: .6rem; bottom: .6rem; z-index: 5;
  display: flex; align-items: center; gap: .7rem;
  /* Панель управления переехала в правый нижний угол, поэтому карточку выбора
     ограничиваем, чтобы длинное описание зоны не заезжало под кнопки. */
  max-width: calc(100% - 25rem);
  background: rgba(10, 10, 14, .9); border: 1px solid var(--accent); padding: .45rem .7rem;
}
.map-card[hidden] { display: none; }
.map-card b { color: var(--accent-strong); }
.map-card-link { color: var(--muted); font-size: .85rem; }
/* Описание зоны — штатный текст клиента, он длинный: карточка переносится и
   прижимается к верху, иначе описание растянуло бы её во всю карту. */
.map-card-desc {
  margin: 0; flex: 1 1 22rem; min-width: 0; font-size: .82rem; line-height: 1.32;
  color: var(--text); border-left: 1px solid var(--border); padding-left: .7rem;
}
/* Карта города из клиента (RadarMap_*_Classic) — квадратная, показываем
   уменьшенной; полный размер открывается кликом по картинке. */
.map-card-shot {
  width: 92px; height: 92px; object-fit: cover; cursor: zoom-in;
  border: 1px solid var(--border); background: #0a0a0e;
}
/* Пергамент стартовой деревни рисуем целиком: на нём мелкие домики, обрезка
   сделала бы нечитаемую кашу. */
.map-card-starter { object-fit: contain; }
.map-card:has(.map-card-desc), .map-card:has(.map-card-shot) {
  align-items: flex-start; flex-wrap: wrap; max-width: min(64rem, calc(100% - 1.2rem));
}
.map-shot-full {
  position: fixed; inset: 0; z-index: 40; display: grid; place-items: center;
  background: rgba(6, 6, 10, .92); padding: 1.5rem; cursor: zoom-out;
}
.map-shot-full img {
  max-width: min(92vw, 1100px); max-height: 92vh; border: 1px solid var(--accent);
}
.map-shot-full figcaption { color: var(--muted); text-align: center; margin-top: .6rem; }
.map-shot-full figure { margin: 0; display: grid; gap: .6rem; }

.map-boss-list { list-style: none; display: grid; gap: .45rem; }
.map-boss-row { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; font-size: .9rem; }
.map-boss-row .muted { font-size: .82rem; }
.map-boss-state { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; padding: .1rem .45rem; border: 1px solid var(--border); }
.map-boss-state.alive { color: var(--green); border-color: var(--green); }
.map-boss-state.dead { color: var(--red); border-color: var(--red); }
.map-town-castle {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--accent-strong); border: 1px solid var(--accent); padding: .1rem .45rem;
}
.map-region-desc-badge {
  font-size: .7rem; letter-spacing: .04em;
  color: var(--muted); border: 1px solid var(--border); padding: .1rem .45rem;
}
