/* FestMap — 모바일 우선. 순수 CSS, 프레임워크 0. */

/* ---- 웹폰트(★P1.4 ④ — Jua 교체, Gaegu 채택, OFL 무료 라이선스, 셀프호스팅) ----
   Google Fonts에서 이 사이트가 실제 쓰는 문자셋(UI 텍스트+전체 시도/시군구 지명)만
   text= 파라미터로 서브셋 요청해 받은 woff2 파일을 로컬로 내려받아 서빙한다.
   외부 CDN(fonts.googleapis.com/fonts.gstatic.com) 요청 없음 — CSP·오프라인 환경 안전.
   Gaegu·Do Hyeon·Gowun Dodum 3종을 실제 UI 크기(제목18px·본문14.5px·메타12.5px)로 렌더
   비교한 결과 Gaegu 채택 — Do Hyeon은 Jua와 마찬가지로 단일굵기라 위계 구현 도구가 폰트크기뿐이고
   두께가 두꺼워 손글씨 느낌의 "정겨움"이 약함, Gowun Dodum은 무난하지만 캐릭터성이 옅음.
   Gaegu는 300/400/700 3굵기가 있어 크기뿐 아니라 굵기로도 제목/본문 위계를 구현할 수 있고
   손글씨체라 "따뜻·정겨움" 컨셉에 가장 부합 — 실제 렌더에서 12.5px 메타 텍스트도 또렷이 읽힘. */
@font-face {
  font-family: 'Gaegu';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('../assets/fonts/Gaegu-300.woff2') format('woff2');
}
@font-face {
  font-family: 'Gaegu';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../assets/fonts/Gaegu-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Gaegu';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../assets/fonts/Gaegu-700.woff2') format('woff2');
}

:root {
  --brand: #2f9e8f;
  --brand-dark: #1f6e63;
  --bg: #f6f9f8;
  --card-bg: #ffffff;
  --ink: #1c2b28;
  --muted: #6a7d78;
  /* ---- 지도 색(아이보리 계열, T-FESTMAP-P1.2 ② · 바다 표기 P1.6 ①) ---- */
  --map-sea: linear-gradient(160deg, #eef8f5 0%, #cfeae3 55%, #a9dcd1 100%); /* 하늘~청록 바다(놀루 몸색 #61a59a 계열과 조화) */
  --sido-fill: #ecdcb8;    /* 지역 채움(육지·아이보리 유지) */
  --sido-fill-hover: #d8a24a; /* 선택/호버 — 대비 확보용 따뜻한 강조색 */
  --sido-fill-visited: #7fc2a8; /* ★W2 게임레이어 — 방문 색칠(브랜드 청록 계열, "정복 완료" 느낌) */
  --sido-stroke: #fdf8ec;  /* 지역 경계선 */
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body {
  margin: 0; padding: 0; height: 100%;
  font-family: var(--ksk-font);
  background: var(--bg); color: var(--ink);
  overscroll-behavior: none;
}

/* ---------- 상단바 ---------- */
/* ★W4(2026-08-16, NOLLUTRIP_GRILL_DECISIONS) — 바텀시트(카드) 열린 상태에서 뒤로가기(.back-btn)가
   안 눌리던 원인: .card-backdrop(z-index 60)·.card-sheet(z-index 61)가 topbar(구 z-index 20)보다
   위에 그려져 pointer-events를 가로챘다(실측: onBack()은 closeCard()도 함께 처리하므로 로직 자체는
   문제 없음 — 순수 스택 순서 문제). topbar를 backdrop·sheet보다 위(70)로 올려 카드가 열려 있어도
   상단 고정 바(뒤로가기·진행률 배지)가 항상 눌리게 한다. */
.topbar {
  position: sticky; top: 0; z-index: 70;
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px; background: var(--brand); color: #fff;
  box-shadow: 0 2px 6px rgba(0,0,0,.12);
}
.topbar-title { margin: 0; font-size: 19px; font-weight: 700; }
.back-btn {
  border: none; background: rgba(0,0,0,.30); color: #fff;
  padding: 6px 12px; border-radius: 20px; font-size: 14px; cursor: pointer;
}
.back-btn:active { background: rgba(0,0,0,.45); }
.topbar-btn {
  border: none; background: rgba(0,0,0,.30); color: #fff;
  padding: 6px 12px; border-radius: 20px; font-size: 14px; font-weight: 700;
  cursor: pointer; white-space: nowrap;
}
.topbar-btn:active { background: rgba(0,0,0,.45); }

/* ---------- 진행률 배지(★W2 게임레이어) ---------- */
.progress-badge {
  margin-left: auto; flex: none;
  background: rgba(0,0,0,.32); color: #fff;
  font-size: 12.5px; font-weight: 700;
  padding: 5px 12px; border-radius: 16px; white-space: nowrap;
}
.progress-badge:empty { display: none; }

/* ---------- 무대(★P1.2 ③ — 지도 전체화면화) ---------- */
.stage { position: relative; height: calc(100vh - 52px); height: calc(100dvh - 52px); overflow: hidden; }

.map-view {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--map-sea);
  transition: opacity .35s ease;
  overflow: hidden;
}
/* 미세 물결(★P1.6 ①) — 아주 옅은 대각선 줄무늬로 잔물결 느낌만 암시(과하지 않게) */
.map-view::before {
  content: "";
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: repeating-linear-gradient(
    120deg, rgba(255,255,255,.35) 0 2px, transparent 2px 34px
  );
  opacity: .5;
}
.map-view > * { position: relative; z-index: 1; }
/* map-wrap의 width/height는 app.js가 SVG viewBox 비율에 맞춰 px로 계산해 지정한다(letterbox
   없이 mascot % 좌표계산이 정확히 맞도록 — fitMapWrap()) */
.map-wrap {
  position: relative;
  flex-shrink: 0; /* fitMapWrap()이 px로 준 크기를 flexbox가 임의로 축소하지 않도록(오버스캔 확대 유지) */
  touch-action: manipulation;
}
.svg-host { width: 100%; height: 100%; transition: transform .7s cubic-bezier(.4,.0,.2,1), opacity .35s ease; }
.svg-host svg { width: 100%; height: 100%; display: block; }
.svg-host path { fill: var(--sido-fill); stroke: var(--sido-stroke); stroke-width: 1.2; cursor: pointer; transition: fill .15s; }
.svg-host path.is-empty { fill: #e2d6b8; cursor: default; }
/* ★W2 게임레이어 — 방문색은 "고정 채움"(is-empty보다 우선 — 방문 여부는 실제 데이터 유무와
   무관한 사용자 기록이라 데이터 0건 지역이라도 방문했으면 방문색을 보여준다), hover/is-active는
   상호작용 피드백이라 방문색 위에서도 항상 마지막에 이겨야 한다(선택・포인팅 시엔 순간적으로
   강조색이 보이고 떼면 방문색으로 복귀 — 동일 tie 특이도(0,2,1)에서 소스 순서로 우선순위 결정). */
.svg-host path.is-visited { fill: var(--sido-fill-visited); }
.svg-host path:hover, .svg-host path.is-active { fill: var(--sido-fill-hover); }

/* ---------- 지역명 라벨(★P1.2 ②) ---------- */
.region-label {
  font-family: var(--ksk-font);
  font-weight: 700;
  fill: var(--ink);
  paint-order: stroke fill;
  stroke: #fdf8ec;
  stroke-width: 3px;
  stroke-linejoin: round;
  pointer-events: none;
  text-anchor: middle;
  dominant-baseline: central;
}

.hint {
  position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%);
  background: rgba(255,255,255,.88); color: var(--muted); font-size: 12.5px;
  padding: 5px 14px; border-radius: 14px; box-shadow: 0 2px 8px rgba(0,0,0,.1);
  margin: 0; white-space: nowrap; pointer-events: none;
}

/* ---------- ★2026-09-05 KSK1 — 홈 화면(검색 중심 진입)
   round/review-snapshots/DESIGN_NOLTRIP_KSK_ENTRY_DESIGN_20260905@a3ce8f19.md §5-2 와이어를
   기존 토큰(--brand·--card-bg·--muted 등)만으로 구현 — 새 색상 팔레트를 만들지 않는다. ---------- */
.home-view {
  position: absolute; inset: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--bg);
  padding: 16px 14px calc(24px + var(--safe-bottom));
}
.home-search-wrap {
  display: flex; gap: 8px; margin-bottom: 18px;
}
.home-search-input {
  flex: 1; min-width: 0;
  padding: 12px 14px; border-radius: 14px; border: 1px solid #d7e3e0;
  background: var(--card-bg); color: var(--ink); font-size: 15px;
  font-family: inherit;
}
.home-search-input::placeholder { color: #97a8a4; }
.home-search-input:focus { outline: 2px solid var(--brand); outline-offset: 1px; }
.home-search-btn {
  flex: none; padding: 0 18px; border: none; border-radius: 14px;
  background: var(--brand); color: #fff; font-size: 15px; font-family: inherit;
  cursor: pointer;
}
.home-search-btn:active { background: var(--brand-dark); }

.home-section {
  background: var(--card-bg); border-radius: 16px; padding: 14px 16px;
  margin-bottom: 14px; box-shadow: 0 1px 4px rgba(0,0,0,.06);
}
.home-section-title { margin: 0 0 4px; font-size: 16px; font-weight: 700; color: var(--ink); }
.home-section-desc { margin: 0 0 10px; font-size: 12.5px; color: var(--muted); line-height: 1.45; }
.home-section-btn {
  display: inline-block; padding: 9px 16px; border: none; border-radius: 12px;
  background: var(--brand); color: #fff; font-size: 14px; font-family: inherit; cursor: pointer;
}
.home-section-btn:active { background: var(--brand-dark); }
.home-section--perk { background: linear-gradient(135deg, #fff 0%, var(--sido-fill) 140%); }

.home-chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.home-chip {
  padding: 7px 14px; border-radius: 999px; border: 1px solid var(--brand);
  background: #fff; color: var(--brand-dark); font-size: 13.5px; font-family: inherit; cursor: pointer;
  /* ★2026-09-06 WIRING — 이 클래스를 <a>(내 여행 링크)에도 재사용하므로 링크 밑줄 제거 +
     inline-block(버튼과 동일한 박스 모델). 기존 버튼 사용처는 이미 인라인 성격이라 영향 없음. */
  display: inline-block; text-decoration: none;
}
.home-chip:active { background: var(--brand); color: #fff; }


/* ---------- 마스코트(★P1.4 ③ — 56px→92px 확대, 좌표계는 %기반 left/top이라 크기와 무관) ---------- */
.mascot {
  position: absolute;
  width: 92px; height: auto;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  transition: left .7s cubic-bezier(.4,.0,.2,1), top .7s cubic-bezier(.4,.0,.2,1);
  filter: drop-shadow(0 4px 6px rgba(0,0,0,.25));
  pointer-events: none;
  z-index: 5;
}
.mascot--run { animation: mascotBob .3s infinite alternate; }
.mascot--flip { transform: translate(-50%, -50%) scaleX(-1); }
@keyframes mascotBob { from { margin-top: 0; } to { margin-top: -6px; } }

/* ---------- 온보딩(★P1.2 ① — 단계별 말풍선+음성+건너뛰기) ---------- */
/* ★W4 자체검증 중 발견·즉시 수정(2026-08-16) — topbar를 60/61(backdrop/sheet)보다 위인 70으로
   올렸더니(위 .topbar 참조) 온보딩(기존 z-index 50)이 topbar보다 아래로 밀려 topbar의
   progressBadge가 온보딩의 #onboardSkip(우상단) 위를 가로막아 건너뛰기 버튼이 안 눌리는
   새 회귀가 생겼다(Playwright 클릭 타임아웃으로 실측 발견). 온보딩은 최초 진입 시 전체를
   덮는 최상위 모달이어야 하므로 topbar(70)보다도 위인 80으로 올려 해결한다. */
.onboard {
  position: fixed; inset: 0; z-index: 80;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 24px; text-align: center;
  background: linear-gradient(180deg, rgba(47,158,143,.08), rgba(47,158,143,.02));
  backdrop-filter: blur(2px);
}
.onboard-mascot { width: 220px; filter: drop-shadow(0 8px 12px rgba(0,0,0,.2)); animation: floaty 2.4s ease-in-out infinite; }
@keyframes floaty { 0%,100% { transform: translateY(0);} 50% { transform: translateY(-10px);} }
.onboard-bubble {
  background: #fff; border-radius: 20px; padding: 26px 28px; max-width: 440px;
  box-shadow: 0 8px 24px rgba(0,0,0,.12); line-height: 1.55; font-size: 19px;
}
.onboard-bubble p { margin: 0 0 12px; min-height: 3.2em; }

/* ---------- 한국어 줄바꿈 개선(★P1.7 — 고아 줄바꿈 방지) ----------
   word-break:keep-all = 한글 어절 중간에서 끊기지 않게(공백 단위로만 개행)
   overflow-wrap:break-word = 어절이 컨테이너보다 길 때만 안전망으로 강제개행
   text-wrap = normal(기본, 전 브라우저) → pretty(지원 시 마지막 줄 고아 방지) →
               balance(지원 시 전체 줄 길이 균등분배, 1~2글자 낙오 방지) — 셋을 순서대로
               선언해 뒤에 올수록 우선 적용되되, 미지원 브라우저는 인식 못하는 값을 무시하고
               직전 유효값을 유지하는 CSS 표준 동작으로 자연 폴백된다. */
.onboard-bubble p, .card-empty, .card-sheet-header h2 {
  word-break: keep-all;
  overflow-wrap: break-word;
  text-wrap: normal;
  text-wrap: pretty;
  text-wrap: balance;
}
.btn-primary {
  margin-top: 6px; border: none; background: var(--brand); color: #fff;
  padding: 10px 22px; border-radius: 24px; font-size: 15px; font-weight: 700; cursor: pointer;
}
.btn-primary:active { background: var(--brand-dark); }

.skip-btn {
  position: absolute; top: 16px; right: 16px;
  border: none; background: rgba(0,0,0,.08); color: var(--muted);
  padding: 6px 12px; border-radius: 16px; font-size: 12.5px; cursor: pointer;
}
.skip-btn:active { background: rgba(0,0,0,.16); }

.onboard-dots { display: flex; justify-content: center; gap: 6px; margin-bottom: 10px; }
.onboard-dots span { width: 6px; height: 6px; border-radius: 50%; background: #dfe8e6; }
.onboard-dots span.active { background: var(--brand); }

/* ---------- 데이터 카드(바텀시트) ---------- */
.card-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,.35); z-index: 60;
  opacity: 0; transition: opacity .25s ease;
}
.card-backdrop.show { opacity: 1; }

.card-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 61;
  background: var(--card-bg);
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -6px 24px rgba(0,0,0,.18);
  max-height: 78vh;
  display: flex; flex-direction: column;
  transform: translateY(100%);
  transition: transform .32s cubic-bezier(.2,.8,.2,1);
  padding-bottom: calc(10px + var(--safe-bottom));
}
.card-sheet.open { transform: translateY(0); }

.card-sheet-handle {
  width: 40px; height: 4px; background: #d8e0de; border-radius: 3px;
  margin: 10px auto 8px; cursor: pointer; flex: none;
}
.card-sheet-header { display: flex; align-items: baseline; gap: 8px; padding: 4px 18px 8px; flex: none; }
.card-sheet-header h2 { margin: 0; font-size: 18px; }
.card-count { color: var(--muted); font-size: 13px; }

.search-panel {
  display: flex; flex-direction: column; gap: 8px;
  padding: 2px 14px 10px; flex: none;
}
.search-row {
  display: flex; gap: 8px; align-items: center;
}
.search-input {
  flex: 1 1 auto; min-width: 0;
  border: 1px solid #dfe8e6; border-radius: 16px;
  padding: 10px 12px; font-size: 14.5px; font-family: inherit;
  color: var(--ink); background: #fff;
}
.search-input::placeholder { color: #97a8a4; }
.search-input:focus {
  outline: 2px solid rgba(47,158,143,.22);
  border-color: var(--brand);
}
.search-clear {
  flex: none;
  border: 1px solid #dfe8e6; background: #fff; color: var(--muted);
  padding: 9px 11px; border-radius: 16px; font-size: 13px; font-weight: 700;
  cursor: pointer; white-space: nowrap;
}
.search-clear:active { opacity: .8; }

.search-sort-row {
  display: flex; gap: 6px; overflow-x: auto; overflow-y: hidden; flex: none;
  padding-bottom: 2px;
}
.search-sort-btn {
  flex: 0 0 auto;
  border: 1px solid #dfe8e6; background: #fff; color: var(--ink);
  border-radius: 16px; padding: 6px 12px; font-size: 13px; font-weight: 700;
  cursor: pointer; white-space: nowrap;
}
.search-sort-btn.active { background: var(--brand); border-color: var(--brand); color: #fff; }
.search-sort-btn:disabled {
  background: #f4f7f6; color: #8a9995; cursor: not-allowed; opacity: 1;
}
.search-note { margin: 0; color: var(--muted); font-size: 12.5px; line-height: 1.45; }

/* ---------- 방문 토글(★W2 게임레이어 — 명시적 트리거, 카드시트 헤더) ---------- */
.visit-toggle {
  margin-left: auto; flex: none;
  border: 1.5px solid #dfe8e6; background: #fff; color: var(--muted);
  padding: 5px 12px; border-radius: 16px; font-size: 12.5px; font-weight: 700; cursor: pointer;
  white-space: nowrap;
}
.visit-toggle.active { background: var(--sido-fill-visited); border-color: var(--sido-fill-visited); color: #114235; }
.visit-toggle:active { opacity: .8; }

/* ★P1.9 — 핸들·헤더·월칩·탭(필터 영역)은 flex-shrink:0으로 고정해 결과 스크롤과 분리한다.
   이게 없으면 flex column의 기본 shrink 동작 때문에 결과가 119건처럼 많을 때 필터 행이
   실측 9~10px까지 눌려찌그러졌다(핸들 0px·월칩 9px·탭 10px — 육안 확인 불가 수준). */
.month-chips { display: flex; gap: 5px; padding: 4px 14px 8px; overflow-x: auto; overflow-y: hidden; flex: none; }
.month-chip {
  flex: 0 0 auto; border: 1px solid #dfe8e6; background: #fff; color: var(--muted);
  border-radius: 14px; padding: 4px 10px; font-size: 12.5px; cursor: pointer; white-space: nowrap;
}
.month-chip.active { background: var(--brand-dark); border-color: var(--brand-dark); color: #fff; font-weight: 700; }
.month-chip.is-today::after { content: " •"; }

.card-tabs { display: flex; gap: 6px; padding: 4px 14px 8px; overflow-x: auto; overflow-y: hidden; flex: none; }
.card-tab {
  flex: 0 0 auto; border: 1px solid #dfe8e6; background: #fff; color: var(--ink);
  border-radius: 16px; padding: 6px 12px; font-size: 13px; cursor: pointer; white-space: nowrap;
}
.card-tab.active { background: var(--brand); border-color: var(--brand); color: #fff; }

.card-list { overflow-y: auto; padding: 4px 14px 18px; display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 0; }
.card-item { position: relative;
  display: flex; gap: 10px; background: #fbfdfc; border: 1px solid #eef3f1; border-radius: 12px;
  padding: 8px; align-items: center;
}
.card-item img { width: 64px; height: 64px; object-fit: cover; border-radius: 8px; background: #e8efed; flex: none; }
.card-item .no-img { width: 64px; height: 64px; border-radius: 8px; background: #e8efed; flex: none;
  display: flex; align-items: center; justify-content: center; font-size: 22px; }
.card-item-body { min-width: 0; flex: 1; }
.card-item-title { font-size: 14.5px; font-weight: 700; margin: 0 0 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card-item-meta { font-size: 12.5px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 6px; }
.card-badge { display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 10px; background: var(--sido-fill); color: var(--brand-dark); font-weight: 700; }
.card-status { display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 10px; font-weight: 700; }
.card-status--ongoing { background: #ffe1b3; color: #8a5300; }
.card-status--upcoming { background: #dcecff; color: #275a9e; }
.card-status--past { background: #e5e2dc; color: #6a6455; } /* ★백필 지난축제 — 진행중/예정과 확실히 구분되는 무채색 톤 */
/* ★2026-08-16(공동리뷰 합의③) — 좌표무효 항목 카드 표기. card-status--past와 같은 무채색 계열이되
   ⚠아이콘 색으로 "정보 자체가 없다"는 것을 시각적으로 구분(past는 시제 구분, 이건 데이터 결측 구분). */
.card-coord-invalid { display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 10px; background: #f3ede0; color: #8a7455; font-weight: 700; }
.card-empty { text-align: center; color: var(--muted); padding: 30px 10px; font-size: 14px; }

.card-item-link {
  display: inline-block; margin-top: 4px; font-size: 12px; font-weight: 700;
  color: #fff; background: var(--brand); border-radius: 12px; padding: 3px 10px; text-decoration: none;
}
.card-item-link:active { background: var(--brand-dark); }

/* ---------- 반응형(태블릿 이상 — 여전히 모바일 레이아웃을 기본으로 확장만) ---------- */
@media (min-width: 700px) {
  .card-sheet { left: 50%; right: auto; width: 480px; margin-left: -240px; border-radius: 20px 20px 0 0; }
}

/* ---------- ★2026-09-01 지도핀 배선(master #5) ---------- */
.map-view-toggle {
  border: 1px solid #dfe8e6; background: #fff; color: var(--ink);
  padding: 5px 11px; border-radius: 16px; font-size: 12.5px; font-weight: 700;
  cursor: pointer; white-space: nowrap; margin-left: auto;
}
.map-view-toggle:active { background: #eef4f2; }
/* ★2026-09-06 WIRING 작업5 — 인페이지 시트↔festival/region/theme.html 계통 일원화 링크 */
.sheet-fullpage-link {
  border: 1px solid var(--brand); background: #fff; color: var(--brand-dark);
  padding: 5px 11px; border-radius: 16px; font-size: 12.5px; font-weight: 700;
  white-space: nowrap; text-decoration: none; display: inline-block;
}
.sheet-fullpage-link:active { background: var(--brand); color: #fff; }

.card-map-view {
  flex: 1 1 auto; min-height: 0; position: relative;
}
.kakao-map-canvas { width: 100%; height: 100%; min-height: 320px; }
.map-view-error {
  text-align: center; color: var(--muted); padding: 30px 14px; font-size: 13.5px; line-height: 1.5;
}
.kakao-infowindow { padding: 6px 8px; font-size: 12.5px; max-width: 180px; }
.kakao-infowindow strong { display: block; font-size: 13.5px; margin-bottom: 2px; }
.kakao-infowindow-cat { color: var(--muted); font-size: 11.5px; margin-bottom: 4px; }
.kakao-infowindow a { color: var(--brand); font-weight: 700; text-decoration: none; }
