/* 이어팡 — 스타일 */

/* 웹폰트는 index.html 에서 styles.css 와 나란히 불러온다 (tools/getfonts.mjs).
   @import 로 걸면 styles.css 를 다 받은 뒤에야 폰트를 받으러 가서 한 박자 늦는다. */

:root {
  /* 본문은 Noto Sans KR — 처음엔 둥근 Jua 를 본문에까지 썼는데, 표시용 글꼴이라
     아이템 설명 같은 긴 문장에서 글자가 뭉쳐 읽기 힘들었다.
     개성은 제목·숫자에만 Black Han Sans 로 몰아준다. */
  --font: 'Noto Sans KR', system-ui, -apple-system, "Apple SD Gothic Neo", "Malgun Gothic", sans-serif;
  --font-display: 'Black Han Sans', 'Noto Sans KR', system-ui, sans-serif;

  --bg: #12141c;
  --bg-2: #1a1d29;
  --panel: #232739;
  --line: #333850;
  --text: #eef1f8;
  --muted: #8c93ad;
  --accent: #ffd166;
  --danger: #ff6b6b;
  --frost: #6fd3ff;
  --tray: rgba(255, 255, 255, .07);
  --tray-edge: rgba(255, 255, 255, .13);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* iOS 사파리는 viewport 의 user-scalable=no 를 무시한다(iOS 10부터).
   더블탭 확대를 실제로 막는 건 touch-action: manipulation 이다.
   칩을 빠르게 연달아 누르면 두 번째 탭이 더블탭으로 해석돼 화면이 확대돼 버렸다. */
html { touch-action: manipulation; }
body {
  touch-action: manipulation;
  -webkit-user-select: none; user-select: none;
  -webkit-text-size-adjust: 100%;   /* 가로로 돌릴 때 사파리가 글자를 멋대로 키운다 */
}
/* 누를 수 있는 것들은 확실히 못 박는다 */
.chip, .btn, .item, .ghost, .pill, .node, .sound-btn, #intro-start {
  touch-action: manipulation;
}

html, body {
  margin: 0; height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  overscroll-behavior: none;
}

/* 광고 배너를 화면 바깥에 두어 어떤 화면이든 항상 맨 아래에 남게 한다 */
#app { height: 100%; max-width: 720px; margin: 0 auto; display: grid; grid-template-rows: 1fr auto; }
#screens { position: relative; min-height: 0; overflow: hidden; }   /* 터지는 파편이 화면 밖으로 새어 가로 스크롤을 만들지 않게 */
#intro-screen, #map-screen, #game-screen, #guide-screen { position: absolute; inset: 0; display: grid; }
#map-screen, #guide-screen { background-color: var(--bg); }

/* 지도 배경 — 스크롤과 함께 움직이지 않는 한 장. 챕터가 바뀔 때만 그림을 갈아끼운다.
   (background-attachment:fixed 는 iOS 웹뷰에서 제대로 안 붙어 쓰지 않는다) */
#map-bg {
  position: absolute; inset: 0; z-index: 0;
  background-size: cover; background-position: center; background-repeat: no-repeat;
  background-color: color-mix(in srgb, var(--from, #151a26) 62%, #1b2130);
}
/* 이름 있는 테마를 넘어선 챕터에는 그림이 없다. 색으로만 구역을 만든다. */
#map-bg:not(.has-art) {
  background-image:
    radial-gradient(84% 48% at 16% 12%, color-mix(in srgb, var(--accent) 40%, transparent), transparent 72%),
    radial-gradient(74% 46% at 88% 72%, color-mix(in srgb, var(--glow) 24%, transparent), transparent 70%),
    linear-gradient(180deg, transparent 30%, color-mix(in srgb, var(--to) 80%, transparent));
}
#map-bg::after {
  /* 밝고 경쾌한 느낌을 살려야 하므로 아주 옅게만 덮는다 */
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(255,255,255,.06), rgba(20,30,52,.08) 45%, rgba(20,30,52,.28));
}
#map-bg:not(.has-art)::after { background: none; }
#map-head, #map-summary, #map-scroll { position: relative; z-index: 1; }
#map-summary { background: linear-gradient(180deg, rgba(12,16,26,.3), transparent); }
#map-head { background: linear-gradient(180deg, rgba(12,16,26,.66), rgba(12,16,26,.3) 70%, transparent); }
#map-screen { grid-template-rows: auto auto 1fr; }
#guide-screen { grid-template-rows: auto 1fr; }
#game-screen { grid-template-rows: auto auto 1fr auto; }
#intro-screen[hidden], #map-screen[hidden], #game-screen[hidden], #guide-screen[hidden] { display: none; }

/* 챕터 테마가 게임 화면 배경까지 물들인다. 이미지 없이 구역이 바뀌는 느낌을 낸다. */
/* 그리드 아이템의 기본 min-width:auto는 판 크기에 발이 묶여 페이지가 좁아지지 못하게 만든다.
   0으로 풀어야 화면이 줄어들 때 stage가 먼저 좁아지고, 그 폭에 맞춰 칸 크기가 다시 계산된다. */
#hud, #progress, #stage, #items { min-width: 0; }

/* ---- HUD ---- */
#hud {
  display: flex; align-items: center; justify-content: space-between;
  gap: 6px; padding: 12px 12px 8px;
}
/* 아이폰 사파리는 글자가 조금 더 넓게 잡혀서, 데스크톱에서 딱 맞던 칸이 넘쳐 줄바꿈됐다.
   HUD 의 글자는 어떤 경우에도 안 꺾이게 하고, 대신 남는 자리를 콤보 칸이 먼저 내준다. */
.hud-cell {
  display: flex; flex-direction: column; gap: 2px;
  min-width: 0; flex: 0 0 auto; white-space: nowrap;
}
#hud, #hud * { white-space: nowrap; }
.hud-cell:last-child { text-align: right; }
.hud-label { font-size: 10px; color: var(--muted); letter-spacing: 0; }
.hud-cell strong { font-size: 18px; font-variant-numeric: tabular-nums; }
.hud-combo { flex: 1 1 auto; min-width: 0; text-align: center; gap: 3px; overflow: hidden; }
#ui-combo { font-size: 15px; font-weight: 700; color: var(--accent); opacity: 0; transition: opacity .2s; }
#ui-combo.on { opacity: 1; }
#ui-buffs { font-size: 11px; font-weight: 700; color: var(--frost); min-height: 13px; }
#ui-time-cell.urgent strong { color: var(--danger); animation: pulse .8s ease-in-out infinite; }
/* 스톱이 걸린 동안에는 시간이 줄지 않는다는 걸 색으로 알린다 */
#ui-time-cell.frozen strong { color: var(--frost); }
#ui-time-cell.frozen { animation: frost 1.1s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .45; } }
@keyframes frost { 50% { opacity: .6; } }

#progress { height: 4px; background: var(--line); margin: 0 16px; border-radius: 999px; overflow: hidden; }
#progress-bar {
  height: 100%; width: 0;
  background: linear-gradient(90deg, #4c8dff, #3fb984);
  transition: width .3s cubic-bezier(.2,.8,.3,1);
}

/* ---- 판 ---- */
#stage { display: flex; align-items: center; justify-content: center; padding: 4px; min-height: 0; }
#board-wrap { position: relative; display: inline-block; }
#board { position: relative; }
#links { position: absolute; overflow: visible; pointer-events: none; z-index: 3; }
#fx { position: absolute; inset: 0; overflow: visible; pointer-events: none; z-index: 4; }

/* ---- 칩 ----
   구조: 받침판(tray) → 몸통(body) → 아이콘
   받침판이 "이 칸은 찼다"를 알려주기 때문에 원형 칩에서도 빈칸 착시가 생기지 않는다. */
.chip {
  position: absolute; padding: 0; border: 0; background: none;
  cursor: pointer; z-index: 1;
  transition: transform .16s cubic-bezier(.34,1.56,.64,1), opacity .2s,
              left .28s cubic-bezier(.3,.9,.3,1), top .28s cubic-bezier(.3,.9,.3,1),
              width .28s, height .28s;
  line-height: 1;
}
/* 받침판은 칩이 칸보다 작던 시절 "빈 칸처럼 보이는 착시"를 막던 장치였다.
   이제 칩이 칸을 꽉 채워 서로 맞닿으므로 없앤다 — 배경도 그만큼 더 보인다. */
.chip .tray { display: none; }
.chip .body {
  position: absolute; inset: 13%;
  background: linear-gradient(160deg, var(--chip-color), var(--chip-dark));
  box-shadow: inset 0 -2px 0 rgba(0,0,0,.22), 0 2px 5px rgba(0,0,0,.35);
}
.chip .icon {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.4));
  pointer-events: none;
}

/* 모양이 곧 종류다 — 실루엣만으로도 구분되므로 작은 크기에서 가독성이 좋다 */
.shape-circle .body { border-radius: 50%; }
.shape-square .body { border-radius: 24%; }
.shape-hex .body { clip-path: polygon(25% 4%, 75% 4%, 100% 50%, 75% 96%, 25% 96%, 0 50%); }
.shape-long .body { border-radius: 12%/24%; inset: 0; }
.shape-long .tray { border-radius: 12%/22%; }

.chip:hover { transform: translateY(-2px); }
.chip.selected { z-index: 2; transform: scale(1.09); }
.chip.selected .body { box-shadow: 0 0 0 3px #fff, 0 0 18px 4px var(--chip-color); }
.chip.hinted .body { animation: hint 620ms ease-in-out infinite; }
@keyframes hint {
  50% { box-shadow: 0 0 0 3px var(--accent), 0 0 20px 4px var(--accent); }
}
.chip.gone { transform: scale(0); opacity: 0; pointer-events: none; }
.chip.drop {
  transform: translateY(60vh) rotate(28deg); opacity: 0;
  transition: transform .55s cubic-bezier(.5,0,.75,0), opacity .55s;
}

/* ---- 연결선 ---- */
.link-line { fill: none; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }
.link-glow { fill: none; stroke-width: 12; stroke-linecap: round; stroke-linejoin: round; opacity: .28; filter: blur(4px); }

/* ---- 파티클 / 팝업 ---- */
.particle { position: absolute; border-radius: 50%; pointer-events: none; }
/* 동그라미만 뿌리면 "점이 퍼진다"로 보인다. 모양을 섞어야 부서진 느낌이 난다. */
.particle.shard { border-radius: 22%; }
.particle.spark { border-radius: 50%; box-shadow: 0 0 6px 2px rgba(255,255,255,.8); }
.particle.star {
  background: none !important; border-radius: 0;
  display: flex; align-items: center; justify-content: center;
  line-height: 1; text-shadow: 0 0 8px currentColor;
}
.fx-flash { position: absolute; border-radius: 50%; pointer-events: none; mix-blend-mode: screen; }
.fx-ring {
  position: absolute; border-radius: 50%; pointer-events: none;
  border-style: solid; border-width: 5px; background: none;
}
.float-text {
  position: absolute; font-weight: 800; font-size: 15px; white-space: nowrap;
  text-shadow: 0 2px 6px rgba(0,0,0,.65); pointer-events: none;
}
.float-text.combo { color: var(--accent); font-size: 18px; }

/* ---- 아이템 ----
   5개가 좁은 화면에도 들어가야 하므로 아이콘 / 이름 / 개수를 세로로 쌓는다 */
#items { display: flex; gap: 6px; padding: 10px 12px calc(16px + env(safe-area-inset-bottom)); }
.item {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 9px 2px; border-radius: 14px;
  background: var(--panel); border: 1px solid var(--line); color: var(--text);
  font-size: 12px; font-weight: 600; cursor: pointer;
  transition: transform .12s, background .15s, border-color .15s;
}
.item:active { transform: scale(.95); }
.item[disabled] { opacity: .4; cursor: default; }
.item[hidden] { display: none; }
.item-icon { font-size: 18px; line-height: 1.15; }
.item-name { font-size: 11px; color: var(--muted); }
.item b { font-size: 12px; color: var(--accent); font-variant-numeric: tabular-nums; }
.item.empty b { color: var(--muted); }
/* 효과가 걸려 있는 동안 버튼 자체가 켜져 보이게 한다 */
.item.active { background: #2b3550; border-color: var(--frost); }
.item.active .item-name, .item.active b { color: var(--frost); }

/* ---- 토스트 / 모달 ---- */
#toast {
  position: fixed; left: 50%; top: 76px; transform: translateX(-50%);
  background: rgba(20,22,32,.95); border: 1px solid var(--line);
  padding: 10px 18px; border-radius: 999px; font-size: 13.5px;
  z-index: 20; animation: toast-in .25s ease-out;
  max-width: calc(100% - 40px); text-align: center;
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, -8px); } }

#modal {
  position: fixed; inset: 0; z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(8, 9, 14, .74); backdrop-filter: blur(3px);
}
#modal[hidden] { display: none; }
.sheet {
  width: 100%; max-width: 340px; background: var(--bg-2);
  border: 1px solid var(--line); border-radius: 20px; padding: 26px 22px 20px;
  text-align: center; animation: sheet-in .28s cubic-bezier(.34,1.4,.64,1);
}
@keyframes sheet-in { from { opacity: 0; transform: translateY(14px) scale(.96); } }
.sheet h2 { margin: 0 0 8px; font-size: 21px; }
.sheet p { margin: 0 0 18px; color: var(--muted); font-size: 14px; line-height: 1.6; white-space: pre-line; }
#modal-actions { display: flex; flex-direction: column; gap: 8px; }
.btn {
  padding: 13px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--panel); color: var(--text); font-size: 15px; font-weight: 600; cursor: pointer;
}
.btn.primary { background: linear-gradient(135deg, #4c8dff, #3fb984); border-color: transparent; }
.btn.ad { background: var(--accent); color: #241c00; border-color: transparent; }
.btn:active { transform: scale(.97); }

/* 섞기 연출 중에는 CSS transition을 꺼둔다 — transform 애니메이션과 좌표 변경이 겹치면
   칩이 새 자리로 흘러가버려서 "가운데서 섞이는" 그림이 깨진다 */
#board.shuffling .chip { transition: none !important; }

/* ---- 장애물 ----
   얼음과 안개 모두 그림 파일이 필요 없다. 서리는 그라데이션과 테두리로,
   안개는 몸통을 흐린 회색으로 덮고 물음표를 얹어 만든다. */

/* 얼음: 한 번 맞추면 얼음만 깨지고 칩은 남는다 */
.chip .frost { display: none; }
.chip.iced .frost {
  display: block;
  position: absolute; inset: 13%;
  background:
    linear-gradient(140deg, rgba(198,238,255,.62), rgba(140,205,240,.34) 45%, rgba(226,248,255,.58));
  box-shadow: inset 0 0 0 2px rgba(214,244,255,.9), 0 0 10px rgba(140,215,255,.45);
  pointer-events: none;
}
/* 서리도 칩 모양을 따라가야 "덮여 있다"로 읽힌다 */
.chip.iced.shape-circle .frost { border-radius: 50%; }
.chip.iced.shape-square .frost { border-radius: 22%; }
.chip.iced.shape-hex .frost { clip-path: polygon(25% 4%, 75% 4%, 100% 50%, 75% 96%, 25% 96%, 0 50%); }
.chip.iced.shape-long .frost { border-radius: 16%/32%; inset: 9% 7%; }
.chip.iced .icon { opacity: .78; }

/* 안개: 사방이 막혀 있는 동안 정체를 가린다. 옆이 비면 걷힌다. */
.chip.fogged .body {
  background: linear-gradient(160deg, #4a5068, #2b3043);
  box-shadow: inset 0 -2px 0 rgba(0,0,0,.25), 0 2px 5px rgba(0,0,0,.35);
}
.chip.fogged .icon { visibility: hidden; }
.chip.fogged .frost { display: none; }
.chip.fogged::after {
  content: '?';
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: #9aa3bd; font-weight: 800; font-size: .8em;
  pointer-events: none;
}

/* ---- 기록 ----
   로그인 없이 기기에 남는다. 자세한 배경은 README의 '기록' 절 참고. */
#ui-best { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
#modal-badge {
  display: inline-block; margin-bottom: 8px;
  padding: 3px 12px; border-radius: 999px;
  background: var(--accent); color: #241c00;
  font-size: 12px; font-weight: 800;
  animation: badge-in .4s cubic-bezier(.34,1.6,.64,1);
}
#modal-badge[hidden] { display: none; }
@keyframes badge-in { from { opacity: 0; transform: scale(.6) rotate(-8deg); } }

/* ================= 스테이지 지도 =================
   캔디크러시식 굽은 길. 배경·잠금·난이도 표시 전부 코드로 그린다(이미지 0개). */

/* 네모난 테두리 버튼은 웹페이지처럼 보였다. 둥근 유리 버튼으로 바꾸고
   글자 대신 그림(assets/ui)을 얹는다. */
.ghost {
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.26);
  color: var(--text);
  border-radius: 999px; padding: 0 12px; min-width: 40px; height: 40px;
  font-size: 14px; font-weight: 700; cursor: pointer;
  box-shadow: 0 3px 10px rgba(6,10,20,.35), inset 0 1px 0 rgba(255,255,255,.28);
  backdrop-filter: blur(6px);
  transition: transform .12s;
}
.ghost:active { transform: scale(.92); }
.ghost img { width: 20px; height: 20px; object-fit: contain; display: block; }
.ghost .ico { width: 19px; height: 19px; }
/* 아이콘만 든 버튼은 완전한 원으로 */
#to-map, #to-pause, #guide-back { width: 38px; height: 38px; padding: 0; flex: 0 0 auto; }

#map-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px 10px;
}
/* 게임 이름은 인트로에서만 보여준다. 지도·게임 화면에서는 그 자리를 하트가 쓴다. */
#map-head #hearts-map { margin-right: auto; }
#map-summary {
  display: flex; align-items: center; gap: 8px;
  padding: 0 16px 12px; color: rgba(255,255,255,.82); font-size: 12px;
  text-shadow: 0 1px 3px rgba(0,0,0,.5);
}
#map-stats { display: flex; align-items: baseline; gap: 4px; white-space: nowrap; }
#map-summary strong { font-size: 15px; color: var(--text); font-variant-numeric: tabular-nums; }
#map-summary em { font-style: normal; opacity: .5; margin: 0 4px; }

#map-scroll {
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin;
}

/* 챕터 제목 — 화면을 가로지르는 짙은 띠였던 것을 떠 있는 알약으로 바꿨다.
   배경 그림을 보여주는 게 목적이므로 가리는 면적을 최소로 줄인다. */
.chapter-head {
  position: sticky; top: 10px; z-index: 2;
  width: fit-content; margin: 12px auto 0;
  padding: 7px 20px 9px;
  border-radius: 20px;
  background: color-mix(in srgb, var(--from) 78%, transparent);
  border: 1px solid rgba(255,255,255,.18);
  box-shadow: 0 6px 18px rgba(10,16,28,.32);
  backdrop-filter: blur(6px);
  text-align: center;
  pointer-events: none;   /* 노드 위를 지나가도 탭을 가로채지 않는다 */
}
.chapter-head h2 { margin: 2px 0 0; font-size: 16px; color: var(--glow); }
.chapter-range { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.chapter-head p { margin: 6px 0 0; font-size: 12px; color: var(--muted); }
.chapter.locked { opacity: .72; }
.chapter.locked .chapter-head { padding-bottom: 14px; pointer-events: auto; }

/* 굽은 길 */
.path { position: relative; }
.path svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.path polyline {
  fill: none; stroke: rgba(255,255,255,.16);
  stroke-width: 3; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 2 10;
}

/* ================= 하트 ================= */
.hearts {
  display: flex; align-items: center; gap: 5px;
  font-size: 13px; font-variant-numeric: tabular-nums;
}
.hearts .pip { color: var(--danger); font-size: 14px; letter-spacing: -1px; }
.hearts .pip .off { opacity: .25; }
.hearts .wait {
  /* 배경 사진 위에 옅은 회색 글씨를 얹으니 읽히지 않았다. 배지로 띄운다. */
  font-size: 11px; font-weight: 700; color: #fff; white-space: nowrap;
  background: rgba(10,14,24,.72); border: 1px solid rgba(255,255,255,.18);
  padding: 3px 9px; border-radius: 999px; text-shadow: none;
}
.hearts.empty .pip { animation: pulse 1.1s ease-in-out infinite; }

/* ================= 아이템 (아이콘만) ================= */
.item-name { display: none; }              /* 아이콘만 남긴다 — 이름은 도움말 화면에서 */
.item { gap: 1px; padding: 7px 2px; }
.item-icon { font-size: 27px; }
.item b { font-size: 11px; }

/* 지도 요약을 헤더 밖으로 뺐다 */
#map-summary { padding: 0 16px 8px; }

/* ================= 에셋 =================
   assets/ 에 PNG가 있으면 아이콘 자리에 <img>가 들어오고, 없으면 이모지 글자가 그대로 남는다.
   그래서 8종을 한꺼번에 다 만들 필요 없이 하나씩 갈아끼울 수 있다. */

/* SVG 실루엣은 마스크로 그린다 — 부모의 color 로 칠해지므로 테마·아이템 색을 그대로 입힌다 */
.ico {
  display: block;
  background-color: currentColor;
  -webkit-mask-image: var(--ico); mask-image: var(--ico);
  -webkit-mask-size: contain;     mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  pointer-events: none;
}

/* 칩 아이콘: 흰 실루엣 + 옅은 그림자로 밝은 칩 위에서도 형태가 산다 */
.chip .icon { color: #fff; }
.chip .icon .ico { width: 54%; height: 54%; filter: drop-shadow(0 1px 1px rgba(0,0,0,.45)); }
.chip .icon img  { width: 76%; height: 76%; object-fit: contain; pointer-events: none; }
.chip.fogged .icon .ico { visibility: hidden; }

/* 아이템 버튼: 아이템 고유색으로 */
.item-icon { display: flex; align-items: center; justify-content: center; }
.item-icon .ico { width: 27px; height: 27px; }
.item-icon img  { width: 30px; height: 30px; object-fit: contain; display: block; }
[data-item="shuffle"] .item-icon { color: #4c8dff; }
[data-item="hammer"]  .item-icon { color: #ff8a3d; }
[data-item="hint"]    .item-icon { color: #ffd166; }
[data-item="stop"]    .item-icon { color: #6fd3ff; }
[data-item="bend"]    .item-icon { color: #a96be0; }
.item.empty .item-icon { color: var(--muted); }

/* 도움말 카드: 카드의 고유색으로 */
.g-icon { color: var(--c); }
.g-icon .ico { width: 27px; height: 27px; }
.g-icon img  { width: 26px; height: 26px; object-fit: contain; }

/* 지도 노드: 흰 실루엣 */
.node .art { color: #fff; display: flex; align-items: center; justify-content: center; }
.node .art .ico { width: 78px; height: 78px; filter: drop-shadow(0 2px 3px rgba(0,0,0,.5)); }
.node.milestone .art .ico { width: 98px; height: 98px; }
.node.current .art, .node.is-next .art { color: #2b3245; }
.node.locked .art .ico { opacity: .45; }

/* 챕터 배경 사진 — 칩이 읽혀야 하므로 어두운 막을 한 겹 덮는다 */
/* 테마 배경은 게임 화면 "안"에 깔아야 한다.
   body 에 깔면 #app 이 가운데 정렬돼 있어서 앱 바깥 여백에만 보이고,
   정작 판 뒤에는 안 깔린다. */
#game-screen {
  background-image:
    /* 칩이 읽히도록 아주 옅게만 덮는다. 예전엔 .74~.88로 덮어서 배경이 안 보였다. */
    linear-gradient(rgba(10,12,20,.14), rgba(10,12,20,.32)),
    var(--theme-bg, none);
  background-size: cover, cover;
  background-position: center, center;
  background-color: var(--bg);
}
/* 테마마다 배경이 확실히 달라야 한다.
   배경 PNG가 아직 없어도 강조색 글로우로 구역이 바뀐 느낌을 낸다.

   글로우는 반드시 "타일링"해야 한다. 챕터 한 칸이 50 x 205 = 10,250px라서,
   요소 전체를 덮는 그라데이션을 쓰면 한 화면에는 그 중 7% 정도만 걸린다.
   실제로는 거의 단색으로 보여서 테마가 바뀐 티가 나지 않는다.
   그래서 화면 높이 정도로 잘라 반복시킨다. */
.chapter {
  position: relative;
  /* 배경은 스크롤하지 않는 #map-bg 층이 전부 든다. 챕터 하나가 만 픽셀이라
     여기에 무엇을 깔든 늘어나거나(cover) 가로 이음매가 생긴다(repeat). */
  background: none;
  border-top: 1px solid rgba(255,255,255,.14);
}

/* 굽은 길 */
.path { position: relative; }
.path svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.path polyline {
  fill: none; stroke: rgba(255,255,255,.16);
  stroke-width: 3; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 2 10;
}

/* ================= 하트 ================= */
.hearts {
  display: flex; align-items: center; gap: 5px;
  font-size: 13px; font-variant-numeric: tabular-nums;
}
.hearts .pip { color: var(--danger); font-size: 14px; letter-spacing: -1px; }
.hearts .pip .off { opacity: .25; }
.hearts .wait { font-size: 11px; color: var(--muted); }
.hearts.empty .pip { animation: pulse 1.1s ease-in-out infinite; }

/* ================= 아이템 (아이콘만) ================= */
.item-name { display: none; }              /* 아이콘만 남긴다 — 이름은 도움말 화면에서 */
.item { gap: 1px; padding: 8px 2px; }
.item-icon { font-size: 21px; }
.item b { font-size: 11px; }

/* 지도 요약을 헤더 밖으로 뺐다 */
#map-summary { padding: 0 16px 8px; }

/* ================= 에셋 =================
   assets/ 에 PNG가 있으면 아이콘 자리에 <img>가 들어오고, 없으면 이모지 글자가 그대로 남는다.
   그래서 8종을 한꺼번에 다 만들 필요 없이 하나씩 갈아끼울 수 있다. */

.chip .icon img { width: 82%; height: 82%; object-fit: contain; pointer-events: none; }
.item-icon img  { width: 22px; height: 22px; object-fit: contain; display: block; }
.g-icon img     { width: 26px; height: 26px; object-fit: contain; }

/* (배경은 위쪽 #game-screen 규칙에서 화면 안쪽에 깐다. 여기 있던 body 배경 +
   진한 막 조합은 앱 바깥에만 배경을 보이게 하고 판 뒤는 어둡게 눌러서 제거했다) */
/* 테마마다 배경이 확실히 달라야 한다.
   배경 PNG가 아직 없어도 강조색 글로우 두 개로 구역이 바뀐 느낌을 낸다. */

/* ================= 지도 노드 (큰 버전) =================
   숫자만 있으면 지도가 아니라 목록이다. 장소 그림을 얹고 한 화면에 3~4개만 보이게 키웠다. */

.node {
  position: absolute; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: none; border: 0; padding: 0; cursor: pointer;
  transition: transform .16s cubic-bezier(.34,1.56,.64,1);
}
.node:active { transform: translate(-50%, -50%) scale(.94); }

/* 장소 그림이 앉는 둥근 받침 */
.node .disc {
  position: relative;
  width: 146px; height: 146px; border-radius: 42px;
  display: flex; align-items: center; justify-content: center;
  /* 밝은 배경 사진 위에 놓이므로 반투명 흰색이 아니라 밝은 받침이어야 형태가 산다 */
  background: linear-gradient(165deg, rgba(255,255,255,.9), rgba(223,234,250,.72));
  border: 3px solid rgba(255,255,255,.92);
  box-shadow: 0 10px 22px rgba(24,38,64,.32), inset 0 2px 0 rgba(255,255,255,.9);
  backdrop-filter: blur(2px);
}
.node .art { font-size: 64px; line-height: 1; filter: drop-shadow(0 3px 5px rgba(0,0,0,.25)); }
.node .art img { width: 108px; height: 108px; object-fit: contain; display: block; }

/* 단계 번호 + 난이도를 한 덩어리 명패로 */
.node .plate {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 14px; border-radius: 999px;
  background: rgba(12,14,20,.9);
  border: 1px solid rgba(255,255,255,.16);
}
.node .num { font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums; }
.node .time {
  font-size: 12px; font-weight: 700; color: #fff; font-variant-numeric: tabular-nums;
  padding: 2px 9px; border-radius: 999px; background: rgba(12,14,20,.8);
}

/* 이정표(10단계마다)는 한 뼘 더 크게 */
.node.milestone .disc { width: 182px; height: 182px; border-radius: 52px; }
.node.milestone .art { font-size: 82px; }
.node.milestone .art img { width: 136px; height: 136px; }

.node.cleared .disc {
  background: linear-gradient(165deg, color-mix(in srgb, var(--accent) 46%, #fff), color-mix(in srgb, var(--accent) 20%, #fff));
  border-color: color-mix(in srgb, var(--accent) 70%, #fff);
}
.node.cleared .plate { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }

.node.current .disc, .node.is-next .disc {
  background: linear-gradient(165deg, rgba(255,255,255,.94), rgba(226,234,250,.8));
  border-color: #fff;
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--glow) 34%, transparent), 0 10px 24px rgba(0,0,0,.5);
}
.node.current .art, .node.is-next .art { filter: none; }
.node.is-next .plate { background: #fff; color: #171a24; border-color: #fff; }
.node.is-next .num { color: #171a24; }

.node.locked { cursor: default; }
.node.locked .disc { background: rgba(236,240,248,.5); border-color: rgba(255,255,255,.55); box-shadow: 0 6px 14px rgba(24,38,64,.2); }
.node.locked .art { filter: grayscale(1) brightness(.85); opacity: .55; }
.node.locked .lock {
  position: absolute; right: -4px; bottom: -4px;
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 18px;
  background: #171a24; border: 2px solid rgba(255,255,255,.16);
}
.node.locked .plate { background: rgba(14,17,24,.86); color: rgba(255,255,255,.7); }
.node.locked .diff i.on { background: rgba(255,255,255,.32); }

.node.pulse .disc { animation: node-pulse 1.6s ease-in-out infinite; }
@keyframes node-pulse {
  50% { box-shadow: 0 0 0 13px color-mix(in srgb, var(--glow) 16%, transparent), 0 10px 24px rgba(0,0,0,.5); }
}

/* 난이도 — 숫자 대신 채워진 마름모 */
.diff { display: flex; gap: 3px; }
.diff i {
  width: 7px; height: 7px; transform: rotate(45deg);
  background: rgba(255,255,255,.16); border-radius: 1px;
}
.diff i.on { background: var(--glow); }
.node.is-next .diff i { background: rgba(0,0,0,.18); }
.node.is-next .diff i.on { background: color-mix(in srgb, var(--accent) 80%, #000); }

/* 길을 더 굵게 — 노드가 커졌으니 선도 같이 커져야 균형이 맞는다 */
.path polyline { stroke: rgba(255,255,255,.8); stroke-width: 6; stroke-dasharray: 2 14; }

/* ================= 아이템 설명 (개편) =================
   목록처럼 딱딱하던 것을 카드로 바꾸고, 글자를 키우고 줄간격을 넓혔다.
   아이템마다 고유색을 줘서 게임 화면의 버튼과 눈으로 이어지게 했다. */

/* 이 화면만 짙은 남색 웹페이지처럼 남아 있어 같은 게임으로 보이지 않았다.
   지도·게임과 같은 언어를 쓴다: 테마 배경 사진 + 밝은 카드 + 지도 노드와 같은 둥근 받침. */
#guide-screen {
  background-image:
    linear-gradient(rgba(10,14,24,.16), rgba(10,14,24,.34)),
    var(--theme-bg, none);
  background-size: cover, cover;
  background-position: center, center;
  background-color: var(--bg);
}
#guide-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px 10px;
  background: linear-gradient(180deg, rgba(12,16,26,.74), rgba(12,16,26,.34) 70%, transparent);
}
#guide-head h2 {
  margin: 0; font-size: 22px; font-weight: 900; letter-spacing: -.02em;
  text-shadow: 0 2px 8px rgba(6,10,20,.6);
}
#guide-scroll { overflow-y: auto; padding: 4px 16px 20px; }

#guide-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
#guide-list li {
  --c: var(--item-color, #4c8dff);
  position: relative;
  display: flex; gap: 14px; align-items: flex-start;
  /* 지도 노드 받침과 같은 밝은 재질 — 배경 사진 위에서 카드가 떠 보인다 */
  background: linear-gradient(165deg, rgba(255,255,255,.94), rgba(228,236,250,.86));
  border: 2px solid rgba(255,255,255,.9);
  border-radius: 24px; padding: 16px;
  box-shadow: 0 10px 22px rgba(16,26,46,.3);
}
#guide-list .g-icon {
  /* 노드 원반과 같은 모양 — 화면이 달라도 같은 손이 그린 것으로 보이게 */
  flex: 0 0 58px; height: 58px; border-radius: 19px;
  display: flex; align-items: center; justify-content: center; font-size: 27px;
  background: linear-gradient(165deg,
    color-mix(in srgb, var(--c) 34%, #fff),
    color-mix(in srgb, var(--c) 16%, #fff));
  border: 2px solid color-mix(in srgb, var(--c) 55%, #fff);
  box-shadow: inset 0 2px 0 rgba(255,255,255,.85), 0 3px 8px rgba(16,26,46,.16);
}
#guide-list .g-icon img { width: 34px; height: 34px; object-fit: contain; }
#guide-list .g-icon .ico { width: 30px; height: 30px; color: color-mix(in srgb, var(--c) 70%, #000); }
#guide-list .g-text { min-width: 0; padding-top: 3px; }
#guide-list h3 {
  margin: 0 0 6px; font-size: 17px; font-weight: 900; letter-spacing: -.02em;
  color: #1b2233;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
#guide-list .g-when {
  font-size: 11px; font-weight: 800; letter-spacing: 0;
  color: #fff;
  background: color-mix(in srgb, var(--c) 82%, #000);
  border-radius: 999px; padding: 3px 10px;
}
#guide-list p {
  margin: 0; font-size: 14px; line-height: 1.7;
  color: #4a5468; letter-spacing: -.01em; word-break: keep-all;
}

/* 콤보·하트 안내는 아이템이 아니므로 색을 달리해 구분한다 */
.guide-note {
  margin-top: 14px; padding: 18px;
  background: linear-gradient(165deg, rgba(255,255,255,.94), rgba(255,235,240,.88));
  border: 2px solid rgba(255,255,255,.9);
  border-radius: 24px;
  box-shadow: 0 10px 22px rgba(16,26,46,.3);
  font-size: 14px; line-height: 1.8; color: #4a5468;
  letter-spacing: -.01em; white-space: pre-line; word-break: keep-all;
}
.guide-note strong {
  display: block; margin: 10px 0 6px;
  color: #1b2233; font-size: 17px; font-weight: 900; letter-spacing: -.02em;
}
.guide-note strong:first-child { margin-top: 0; }

/* ================= 칩 몸통 다시 그리기 =================
   앞서 만든 건 2색 그라데이션 + 2px 선이 전부라 80년대 카드처럼 보였다.
   상용 매치3 타일은 광택·안쪽 림·바닥 그늘·타일 두께·바깥 그림자를 겹쳐 쓴다.
   이미지 없이 CSS만으로 그 층들을 쌓는다. */

.chip .body {
  inset: 0;   /* 칸을 꽉 채워 칩끼리 맞닿는다 */
  background:
    /* 위쪽 광택 */
    radial-gradient(125% 85% at 32% 12%, rgba(255,255,255,.6), rgba(255,255,255,0) 52%),
    /* 본체: 밝은 위 -> 진한 아래 3단 */
    linear-gradient(178deg,
      color-mix(in srgb, var(--chip-color) 62%, #fff) 0%,
      var(--chip-color) 46%,
      color-mix(in srgb, var(--chip-color) 55%, #000) 100%);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.55),      /* 윗면 림 */
    inset 0 0 0 1.5px rgba(255,255,255,.22),  /* 안쪽 테두리 */
    inset 0 -4px 6px rgba(0,0,0,.3),          /* 바닥 그늘 */
    0 2px 0 color-mix(in srgb, var(--chip-color) 38%, #000), /* 타일 두께 */
    0 3px 6px rgba(0,0,0,.35);                /* 맞닿으므로 그림자는 짧게 */
}

/* 아래쪽 반사광 — 있고 없고가 "유리 느낌"을 가른다 */
.chip .body::after {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(90% 55% at 50% 108%, rgba(255,255,255,.3), transparent 60%);
  border-radius: inherit;
  clip-path: inherit;
}

/* 아이콘은 자기 색 + 흰 테두리 (스티커처럼 몸통 위로 떠 보이게) */
.chip .icon { color: var(--icon-color, #fff); }
.chip .icon .ico {
  width: 56%; height: 56%;
  filter:
    drop-shadow(0 0 1.5px #fff) drop-shadow(0 0 1.5px #fff)
    drop-shadow(0 0 1px rgba(255,255,255,.9))
    drop-shadow(0 2px 2px rgba(0,0,0,.5));
}

/* 판에도 바닥을 깔아 칩이 떠 보이게 한다 */
#board::before {
  content: ''; position: absolute; inset: -6px;
  border-radius: 22px;
  background: radial-gradient(120% 90% at 50% 0%, rgba(255,255,255,.04), rgba(0,0,0,.10));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.06);
  pointer-events: none;
}
.chip .tray {
  background: rgba(0,0,0,.28);
  border-color: rgba(255,255,255,.08);
}

/* 선택 상태도 같이 화려하게 */
.chip.selected .body {
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.7),
    inset 0 0 0 2px rgba(255,255,255,.5),
    inset 0 -4px 6px rgba(0,0,0,.25),
    0 0 0 3px #fff,
    0 0 22px 6px var(--chip-color),
    0 6px 14px rgba(0,0,0,.5);
}

/* ================= 일시정지 =================
   흐리게 덮는 게 아니라 완전히 가린다. 멈춘 채로 판을 들여다보며
   수를 읽을 수 있으면 제한시간이 의미를 잃는다.

   (이 블록은 한 번 통째로 지워진 적이 있다. 그러면 커버가 오버레이가 아니라
    문서 흐름으로 밀려나 화면 아래에 그냥 붙어버린다.
    tools/browsertest.html 의 pause-covers 검사가 그걸 잡는다.) */

#pause-cover {
  position: absolute; inset: 0; z-index: 25;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(120% 90% at 50% 0%, var(--theme-from, #1a1d29), transparent 75%),
    var(--bg);
  overflow: hidden;
  animation: cover-in .18s ease-out;
}
#pause-cover[hidden] { display: none; }
@keyframes cover-in { from { opacity: 0; } }

/* 배경 무늬 — 게임 칩과 같은 모양을 크게 흩뿌린다 */
.pause-art { position: absolute; inset: 0; pointer-events: none; }
.ghost-chip {
  position: absolute; display: block;
  background: var(--theme-glow, #8fa8d8);
}
.ghost-chip.shape-circle { border-radius: 50%; }
.ghost-chip.shape-square { border-radius: 22%; }
.ghost-chip.shape-hex { clip-path: polygon(25% 4%, 75% 4%, 100% 50%, 75% 96%, 25% 96%, 0 50%); }

.pause-body {
  position: relative; z-index: 1;
  text-align: center; padding: 24px;
  width: 100%; max-width: 320px;
}
.pause-icon { font-size: 40px; display: block; margin-bottom: 6px; }
.pause-body h2 { margin: 0 0 6px; font-size: 26px; font-weight: 800; letter-spacing: -.02em; }
#pause-info { margin: 0 0 22px; color: var(--muted); font-size: 13px; }
.pause-actions { display: flex; flex-direction: column; gap: 8px; }

#to-pause { font-size: 12px; }


/* ================= 망치 조준 =================
   망치를 켜면 어느 칩을 부술지 직접 고른다. 켜져 있다는 걸 판 전체로 알린다. */
#board.aiming .chip { cursor: crosshair; }
#board.aiming .chip:hover .body { box-shadow: 0 0 0 3px #ff8a3d, 0 0 18px 4px rgba(255,138,61,.6); }
#board.aiming::after {
  content: '부술 칩을 고르세요';
  position: absolute; left: 50%; top: -34px; transform: translateX(-50%);
  background: #ff8a3d; color: #241000;
  font-size: 12px; font-weight: 800; padding: 5px 14px; border-radius: 999px;
  white-space: nowrap; pointer-events: none;
  animation: aim-in .2s ease-out;
}
@keyframes aim-in { from { opacity: 0; transform: translate(-50%, 6px); } }
.item.aiming { background: #3a2a1a; border-color: #ff8a3d; }
.item.aiming .item-name { color: #ff8a3d; }

/* ================= 배경 위 가독성 =================
   배경이 밝아지니 HUD 글씨가 묻힌다. 상단과 하단에만 어두운 막을 깔아
   배경은 살리면서 글씨는 읽히게 한다. */
#hud {
  background: linear-gradient(180deg, rgba(10,12,20,.82), rgba(10,12,20,.55) 70%, transparent);
  position: relative; z-index: 2;
}
#progress {
  position: relative; z-index: 2;
  background: rgba(10,12,20,.55);
}
#items {
  background: linear-gradient(0deg, rgba(10,12,20,.86), rgba(10,12,20,.6) 70%, transparent);
  position: relative; z-index: 2;
}

/* 판 뒤 패널 — 배경 사진 위에서도 칩이 도드라지게 */
#board::before {
  /* 배경이 비쳐 보여야 한다. .42 + 흐림 + 큰 그림자가 배경을 통째로 덮고 있었다. */
  background: rgba(12,16,26,.12);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.10);
  backdrop-filter: none;
}


/* ================= 콤보 보너스 =================
   10콤보마다 "아무 칩이나 눌러 터뜨리기"가 한 번 열린다.
   조준(망치)과 헷갈리면 안 되므로 색을 금색으로 완전히 분리했다. */
#board.bonus .chip { cursor: pointer; animation: bonus-breathe 1.1s ease-in-out infinite; }
#board.bonus .chip .body { box-shadow: 0 0 0 2px rgba(255,217,74,.55), 0 3px 6px rgba(0,0,0,.35); }
#board.bonus::after {
  content: '보너스! 아무 칩이나 누르세요';
  position: absolute; left: 50%; top: -34px; transform: translateX(-50%);
  background: linear-gradient(180deg, #ffe172, #ffb703);
  color: #3a2600; font-size: 12px; font-weight: 900;
  padding: 5px 14px; border-radius: 999px; white-space: nowrap; pointer-events: none;
  box-shadow: 0 4px 14px rgba(255,183,3,.5);
  animation: aim-in .2s ease-out;
}
#board.bonus::before { box-shadow: inset 0 0 0 2px rgba(255,217,74,.5); }
@keyframes bonus-breathe {
  50% { filter: brightness(1.18) saturate(1.15); }
}
.item.bonus-on { border-color: #ffd94a; }

/* ================= 인트로 =================
   토스 목록에서 바로 들어오는 자리다. 이름 · 얼굴 · 시작 버튼 셋이면 충분하다. */
#intro-screen { overflow: hidden; background-color: var(--bg); }
#intro-bg {
  position: absolute; inset: 0;
  background-image: var(--theme-bg, none);
  background-size: cover; background-position: center;
}
#intro-bg::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(14,20,34,.18) 40%, rgba(14,20,34,.62));
}
#intro-body {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 13px; padding: 20px 20px calc(24px + env(safe-area-inset-bottom)); text-align: center;
}
#intro-mascots { display: flex; align-items: flex-end; gap: 2px; margin-bottom: 2px; }
#intro-mascots .m {
  width: 54px; height: 54px; display: flex; align-items: center; justify-content: center;
  font-size: 42px; filter: drop-shadow(0 6px 10px rgba(10,16,30,.45));
  animation: mascot-bob 2.4s ease-in-out infinite;
}
#intro-mascots .m img { width: 100%; height: 100%; object-fit: contain; }
#intro-mascots .m1 { animation-delay: .18s; margin-bottom: 10px; }
#intro-mascots .m2 { animation-delay: .36s; }
#intro-mascots .m3 { animation-delay: .54s; margin-bottom: 10px; }
@keyframes mascot-bob { 50% { transform: translateY(-9px) rotate(-3deg); } }

/* 타이틀은 글자가 아니라 그림이다.
   글꼴로 찍은 이름은 아무리 굵게 해도 "제목 텍스트"로 보이지 유희의 로고로 안 보인다.
   에셋이 없으면 아래 글자 버전이 그대로 남는다(assets.js 의 대체 구조). */
#intro-title {
  margin: 0; font-size: 42px; letter-spacing: -.03em; line-height: 1.1;
  color: #fff; text-shadow: 0 3px 0 rgba(10,16,30,.35), 0 8px 24px rgba(10,16,30,.5);
}
#intro-title.has-logo { text-shadow: none; }
#intro-title img {
  display: block;
  width: min(84vw, 380px); height: auto;
  filter: drop-shadow(0 8px 18px rgba(8,14,28,.45));
  animation: logo-in .7s cubic-bezier(.2,1.5,.4,1) both, logo-bob 3.4s ease-in-out 1s infinite;
}
@keyframes logo-in {
  from { opacity: 0; transform: scale(.72) rotate(-4deg); }
}
@keyframes logo-bob { 50% { transform: translateY(-7px) rotate(-1.2deg); } }
#intro-tagline { margin: 0; font-size: 15px; font-weight: 700; color: rgba(255,255,255,.9);
  text-shadow: 0 2px 6px rgba(0,0,0,.5); }
#intro-sub { margin: 0; font-size: 13px; color: rgba(255,255,255,.78);
  text-shadow: 0 1px 4px rgba(0,0,0,.5); }
.btn.big { font-size: 18px; font-weight: 900; padding: 15px 54px; border-radius: 999px; }
#intro-start { margin-top: 6px; animation: start-pulse 1.8s ease-in-out infinite; }
@keyframes start-pulse { 50% { transform: scale(1.045); } }
#intro-hearts {
  /* 시간 배지를 옆에 두면 그만큼 하트가 왼쪽으로 밀려 가운데가 아니게 된다 */
  flex-direction: column; align-items: center; gap: 9px;
}

/* ================= 하트 (직접 그린 버전) ================= */
.hearts .pip { display: flex; align-items: center; gap: 3px; }
.hearts .pip > span { display: block; width: 26px; height: 26px; }
.hearts .pip svg { width: 100%; height: 100%; display: block; overflow: visible; }
.hearts .pip .h-body {
  fill: #ff456a;
  stroke: rgba(120,10,35,.55); stroke-width: 1.4;
  filter: drop-shadow(0 2px 3px rgba(120,10,35,.45));
}
.hearts .pip .on .h-body { fill: #ff456a; }
.hearts .pip .h-shine { fill: rgba(255,255,255,.72); }
.hearts .pip .off { opacity: 1; }
.hearts .pip .off .h-body { fill: rgba(255,255,255,.14); stroke: rgba(255,255,255,.22); filter: none; }
.hearts .pip .off .h-shine { fill: rgba(255,255,255,.14); }
/* 인트로는 주인공이라 크게, 지도 요약 줄은 점수와 나눠 써야 하므로 한 치수 작게 */
#intro-hearts .pip > span { width: 32px; height: 32px; }
#hearts-map .pip > span { width: 27px; height: 27px; }
#hearts-map .pip { gap: 3px; }

/* 게임 화면 하트 — 개수만, 자리를 거의 안 먹게 */
.hearts.compact .pip > span { width: 17px; height: 17px; }
.hearts.compact .pip { gap: 1px; }
#hearts-game { flex: 0 0 auto; }
.hearts.empty .pip .on .h-body { animation: heart-warn 1.2s ease-in-out infinite; }
@keyframes heart-warn { 50% { fill: #ff8fa3; } }

/* ================= 아이템 안내 버튼 ================= */
#map-head .pill {
  flex: 0 0 auto; white-space: nowrap;    /* 줄바꿈 금지 — 좁은 화면에서 글자가 쪼개졌다 */
  padding: 9px 18px; border-radius: 999px;
  font-size: 14px; font-weight: 800; color: #26170a;
  background: linear-gradient(180deg, #ffd76a, #ffab2e);
  border: 0; box-shadow: 0 4px 0 #c9781a, 0 6px 14px rgba(0,0,0,.32);
  cursor: pointer;
}
#map-head .pill:active { transform: translateY(2px); box-shadow: 0 2px 0 #c9781a; }

/* 총점은 눈에 띄어야 한다 — 나중에 남과 겨룰 숫자다 */
#map-summary .score { color: #ffd76a; }

/* ================= 지도 노드 성장 =================
   구역 안에서 초반 → 중반 → 후반으로 갈수록 장소가 커지고 결국 둘로 늘어난다.
   같은 그림을 50판 내내 보면 진행감이 없어서, 눈에 보이는 변화를 붙였다. */
.node.tier0 .art img { width: 88px; height: 88px; }
.node.tier0 .art .ico { width: 62px; height: 62px; }
.node.tier0 .art { font-size: 52px; }

.node.tier2 .art { gap: 1px; }
/* 둘로 늘어나면 원반을 넘치므로 한 개당 크기를 줄인다 */
.node.tier2 .art img { width: 64px; height: 64px; }
.node.tier2 .art .ico { width: 46px; height: 46px; }
.node.tier2 .art { font-size: 38px; }
.node.tier2 .art > :last-child { transform: scale(.92) rotate(6deg); transform-origin: bottom center; }

/* 이정표는 성장 단계와 무관하게 항상 가장 크다 — 구역의 얼굴이다 */
.node.milestone .art img { width: 136px !important; height: 136px !important; }
.node.milestone .art .ico { width: 98px !important; height: 98px !important; }

/* 스테이지별 "최고 40초"는 HUD 안에서 옆 버튼을 파고들었고,
   기록은 총점으로 대체하기로 했으므로 숨긴다. */
#ui-best { display: none; }

/* 안내 토스트가 두 줄로 어색하게 꺾였다 */
#toast { max-width: min(340px, calc(100vw - 32px)); }


/* ================= 글꼴 배분 =================
   Jua 한 벌로만 가면 굵기 대비가 없어 다시 밋밋해진다.
   "숫자와 제목"만 Black Han Sans 로 올려 무게 차이를 만든다. */
#intro-title, #guide-head h2, .modal-title, #modal-title,
.node .num, #ui-level, #ui-score, #ui-time, #map-stats strong,
#intro-mascots + #intro-title, .chapter-head h2 {
  font-family: var(--font-display);
  font-weight: 400;             /* 이 폰트는 굵기가 하나뿐이라 합성 굵기를 끈다 */
  letter-spacing: -.01em;
}
/* Black Han Sans 는 굵기가 하나뿐이다. font-weight 로 더 굵게 해달라고 하면
   브라우저가 획을 인위적으로 부풀려 뭉갠다. 이 글꼴을 쓰는 자리만 400 으로 못 박는다.
   (본문 Noto Sans KR 은 400~900 이 실제로 있으므로 지정한 굵기를 그대로 쓴다) */
#intro-title, #guide-head h2, #modal-title, .chapter-head h2,
.node .num, #ui-level, #ui-score, #ui-time, #map-stats strong {
  font-weight: 400;
}
body { letter-spacing: -.005em; }
#toast, #modal-body, #guide-list p, .guide-note { line-height: 1.7; }

/* ================= 소리 =================
   효과음과 BGM을 한 스위치로 묶었다. 기본은 꺼짐 —
   조용한 곳에서 열자마자 소리가 터지면 그 자체로 민폐고,
   이미 음악을 듣고 있는 사람의 재생을 멈춰버릴 수도 있다. */
#intro-sound {
  display: flex; align-items: center; gap: 8px;
  margin-top: 2px; padding: 9px 18px 9px 14px;
  border-radius: 999px; cursor: pointer;
  background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.3);
  color: #fff; font-size: 13px; font-weight: 700;
  backdrop-filter: blur(6px);
  text-shadow: 0 1px 3px rgba(0,0,0,.45);
}
#intro-sound img { width: 19px; height: 19px; object-fit: contain; }
#intro-sound .ico { width: 18px; height: 18px; }
#intro-sound.on { background: rgba(255,215,106,.24); border-color: rgba(255,215,106,.6); }
#intro-sound:active { transform: scale(.95); }

#map-sound { width: 40px; padding: 0; }
#map-sound img { width: 20px; height: 20px; object-fit: contain; }


/* ?debug=1 일 때만 생긴다 — 폰에서 이벤트가 실제로 오는지 보는 창 */
#debug-box {
  position: fixed; left: 6px; right: 6px; bottom: 56px; z-index: 999;
  background: rgba(6,10,18,.88); color: #9fe8b0;
  font: 11px/1.5 ui-monospace, Menlo, Consolas, monospace;
  white-space: pre-wrap; padding: 8px 10px; border-radius: 10px;
  border: 1px solid rgba(255,255,255,.18); pointer-events: none;
}


/* ================= 망치 타격 ================= */
.fx-hammer {
  position: absolute; pointer-events: none; line-height: 1;
  filter: drop-shadow(0 8px 12px rgba(0,0,0,.55));
  z-index: 6;
}
.fx-hammer img { width: var(--fx-size); height: var(--fx-size); object-fit: contain; display: block; }
.fx-crack {
  position: absolute; pointer-events: none; width: 3px;
  background: linear-gradient(180deg, rgba(255,255,255,.95), rgba(255,210,160,.1));
  border-radius: 2px;
}
