/*
 * 이미지 기반 아이소메트릭 맵 (game-site AI 그래픽 이식).
 *  맵은 assets/pieces/ 의 조각들을 assets/map-layout.json 배치대로 쌓아 만든다.
 *  오브젝트·캐릭터는 맵 위에 백분율(0~100%) 좌표로 얹는다.
 */
/* 처음 들어왔을 때 상단 바·좌측 패널이 맵을 가리지 않도록 그만큼 비워 둔다
   (사용자 지시 2026-09-09). 값은 layout.css 의 .hud, mission-guide.css 의
   .mission-guide-col 과 같은 식이라 한쪽을 고치면 여기도 같이 고쳐야 한다.
     --ui-top   상단 바 아래 끝 (top 1.6% + 높이 96.8) + 간격
     --ui-left  좌측 패널 오른쪽 끝 (left 1.6% + 폭) + 간격
     --ui-gap   좌우·아래 여백 */
.map {
  /* 터치로 끌고 핀치로 확대하려면 브라우저가 먼저 스크롤·확대로 가져가지 않아야 한다.
     map.js 의 touchstart/touchmove 가 직접 처리한다(2026-09-14 모바일 대응). */
  touch-action: none;
  --ui-gap: 20px;
  --ui-top: calc(1.6vh + 121px + var(--ui-gap));
  /* 발주처 0910 S4: 맵을 가로 중앙에. 예전엔 좌측 패널 폭만큼 왼쪽을 밀어 맵이 우측으로
     치우쳤다. 이제 좌우 여백을 같게 둬 중앙에 놓는다(좌측 패널은 맵 위에 겹쳐 뜬다). */
  --ui-left: var(--ui-gap);
  position: absolute; inset: 0;
  padding: var(--ui-top) var(--ui-gap) var(--ui-gap) var(--ui-left);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  background: #f4f1ee;
}

/* 맵 무대: 배치 캔버스 비율을 유지하며 최대한 채운다.
   자식 요소는 이 무대 기준 %로 배치된다.
   주의: 조각은 width 만 %로 주고 높이는 auto(가로 배율)로 늘어나는데,
   캐릭터는 top 을 무대 높이 % 로 잡는다. 무대 비율이 캔버스 비율과 다르면
   둘의 배율이 어긋나 캐릭터가 맵 밖으로 밀려난다.
   그래서 비율을 여기 적지 않고 map.js 가 LAYOUT 크기에서 --map-ar 로 넣어준다.
   아래 기본값은 map.js 없이 CSS 만 볼 때를 위한 것이다. */
.map__stage {
  position: relative;
  --map-ar: 2372 / 2048;
  /* --fit = 화면 안에 다 들어가는 크기. 그대로 쓰면 좌우에 검은 여백이 남는다.
     맵은 마우스로 잡고 끌 수 있으므로 화면을 채우도록 키우고 넘치는 부분은
     잘라 보여준다(.map 이 overflow:hidden). 다만 초광폭 화면에서 너무 확대돼
     가운데 띠만 보이지 않도록 --fit 의 1.4배까지만 커지게 막는다. */
  /* --fit = 세로를 화면에 꽉 채웠을 때의 가로 크기.
     예전에는 이 값 이상으로 키워 화면을 채우고 넘치는 부분을 잘라 보여줬는데,
     그러면 처음 들어왔을 때 맵의 일부만 보였다. 이제는 맵 전체가 들어오도록
     가로·세로 중 모자란 쪽에 맞춘다(contain). 확대는 휠로 한다. */
  /* 위·아래로 비워 둔 만큼 빼고 잰다. 안 빼면 무대가 상단 바 뒤로 들어간다. */
  --fit: calc((100vh - var(--ui-top) - var(--ui-gap)) * var(--map-ar));
  /* 확대는 transform: scale 이 아니라 무대 크기(--zoom)로 한다.
     scale 은 1배로 이미 그려 둔 화면을 늘리는 것이라 확대할수록 흐려진다.
     크기를 키우면 조각 PNG(원본 3888px)를 그 크기에 맞춰 다시 그려 선명하다. */
  --zoom: 1;
  width: calc(min(100%, var(--fit)) * var(--zoom));
  aspect-ratio: var(--map-ar);
  /* .map 이 flex 라 기본값(flex-shrink:1)이면 확대해도 가로가 화면 폭으로 도로 줄어든다. */
  flex: none;
}
/* 마우스 팬(패럴랙스)을 받는 레이어. 맵 아트·오브젝트·캐릭터를 담는다.
   scale 로 살짝 키워 팬 이동 시 가장자리 여백이 보이지 않게 한다. */
.map__world {
  position: absolute; inset: 0;
  transform-origin: center center;
  will-change: transform;
}
.map__art {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: fill;
  pointer-events: none;
  user-select: none;
}

/* 오브젝트: 배경에 이미 그려져 있으므로 클릭 핫스팟 + 이름표 + ! 아이콘만 얹는다.
   left/top 은 JS가 mx/my(%)로 지정. transform 으로 중심 정렬. */
.obj {
  position: absolute;
  transform: translate(-50%, -100%);
  cursor: pointer;
  text-align: center;
  /* 조각보다 위인 것은 층이 갈려(.map__objs 가 .map__world 뒤에 온다) 저절로 보장된다.
     이 값은 화면 전체 기준 순서다. 맵 그림·캐릭터(6) 보다는 위,
     좌측 패널(9)·상단 바(10) 보다는 아래. 발주처 0921: 이름표·아이콘이 맵 위 최상단인 건 맞지만
     UI(미션 가이드·조작법·상단 바)를 침범하면 안 된다 — 맵을 확대해 그 밑으로 들어가면 패널 뒤에 숨는다.
     (2026-09-09 의 '패널보다 위' 결정을 이 요청이 뒤집었다.) */
  z-index: 7;
}
.obj__label {
  display: inline-block;
  border: 1.5px solid rgba(31,36,41,.18);
  border-radius: 999px;
  background: rgba(42,35,32,.82);
  color: #ffffff;
  /* 크기 확대(발주처 요청 2026-09-08 슬라이드 13, 2026-09-09 사용자 지시로 1.5배) */
  padding: 8px 21px;
  font-size: 22px; font-weight: bold;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(42,35,32,.14);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  pointer-events: none;
}
.obj:hover .obj__label { background: rgba(233,0,45,.92); }
.obj--active .obj__label { background: var(--flat-blue); }

/* 미션 발생 ! 아이콘: 이름표 위에 붉게 통통 튀는 마커 */
.obj__icon {
  /* 크기 확대(발주처 요청 2026-09-08 슬라이드 13, 2026-09-09 사용자 지시로 1.5배) */
  /* 이름표 바로 위에 붙인다. 예전 -102px 은 이름표와 너무 떨어져 보였다(발주처 0918 저녁). */
  position: absolute; left: 50%; top: -84px;
  transform: translateX(-50%);
  width: 96px; height: 96px; border-radius: 50%;
  background-color: transparent; color: #ffffff;
  background-repeat: no-repeat; background-position: center; background-size: contain;
  border: 0;
  font-weight: 900; font-size: 36px; line-height: 96px;
  filter: drop-shadow(0 4px 8px rgba(42,35,32,.42));
  display: none;
  animation: gs-marker-float 1.7s ease-in-out infinite;
  z-index: 3;
}
.obj--hasMission .obj__icon { display: block; }
/* 미션 아이콘이 옆 오브젝트의 이름표(상호작용 버튼)에 가리던 문제(발주처 지적).
   .obj 하나하나가 z-index 로 쌓임 맥락을 만들어, 아이콘은 자기 상자 안에서만 위였다.
   아이콘이 뜬 오브젝트를 통째로 한 단 올려 다른 이름표들보다 확실히 앞에 오게 한다.
   (좌측 패널 9·상단 바 10 보다는 아래라 UI 를 침범하지 않는다 — 발주처 0921.) */
.obj--hasMission { z-index: 8; }
/* 같은 상자 안에서도 아이콘이 이름표보다 앞이어야 한다(이름표는 static 이라 기본은 뒤지만 명시한다). */
.obj__label { position: relative; z-index: 1; }


/*
 * 캐릭터: 스프라이트시트 배경. 걷기 6프레임 × 4방향(행).
 *  row 0=앞(아래로), 1=뒤(위로), 2=좌, 3=우
 *  이동은 map.js 가 left/top(%)과 background-position 을 갱신한다.
 */
.character {
  position: absolute;
  /* width / aspect-ratio / transform / background 는 선택 캐릭터에 따라 map.js 가 설정한다. */
  background-repeat: no-repeat;
  image-rendering: auto;
  pointer-events: none;
  z-index: 6;
  filter: drop-shadow(0 6px 8px rgba(42,35,32,.38));
}

/* 오브젝트(이름표·미션 아이콘) 층.
   map__world 와 같은 자리·같은 크기지만 transform 을 쓰지 않는다.
   transform 은 쌓임 맥락을 만들어, 그 안의 z-index 가 바깥(상단 바·좌측 패널)과
   같은 자리에서 비교되지 못하게 막는다. 이 층에는 걸지 않아야 위 z-index 가 화면 기준으로 먹는다. */
.map__objs {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  pointer-events: none;              /* 빈 곳은 맵 드래그가 받도록 */
}
.map__objs .obj { pointer-events: auto; }

/* 맵 조각(에디터 배치) */
.map__piece {
  transition: opacity .18s ease; position: absolute; user-select: none; pointer-events: none; }
