.app-header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 20px;
  background: #0B2E5C;        /* Navy — /lab 헤더와 동일(테마 무관 고정) 정합 */
  border-bottom: 1px solid rgba(255,255,255,0.10);
  position: sticky; top: 0; z-index: 11;
  box-shadow: 0 1px 3px rgba(0,0,0,0.18);
}

/* 인기 도서 ticker — 헤더 직후 sticky-stack.
   데스크탑: 헤더 아래 top:--header-h 에 고정. 모바일은 @media 에서 static 으로. */
.popular-ticker {
  position: sticky; top: var(--header-h); z-index: 10;
  display: flex; align-items: center; gap: 12px;
  height: 36px; padding: 0 20px;
  background: var(--surface-alt);
  border-bottom: 1px solid var(--border);
  font-size: var(--font-sm);
  white-space: nowrap; overflow: hidden;
}
.app-title { font-size: 17px; font-weight: 700; color: #fff; }
.app-subtitle { display: block; font-size: 12px; font-weight: 400; color: rgba(255,255,255,0.72); margin-top: 2px; line-height: 1.4; }
.header-meta { display: flex; gap: 12px; align-items: center; }

/* 네이비 헤더 위 컨트롤(소개·장애인 안내·테마토글·신선도 chip) — 반투명 흰색 정합 (lab 헤더 방식) */
.app-header .intro-btn,
.app-header .icon-btn,
.app-header .freshness-pill {
  background: rgba(255,255,255,0.12);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.22);
}
.app-header .intro-btn:hover,
.app-header .icon-btn:hover,
.app-header .freshness-pill:hover {
  background: rgba(255,255,255,0.20);
}
.app-header .freshness-pill .freshness-prefix,
.app-header .freshness-pill .freshness-time,
.app-header .freshness-pill .freshness-suffix { color: #fff; }

/* 오픈러닝랩(출품작) 강조 링크 — 네이비 헤더에서 시안 칩으로 부각 (lab 의 참고도서 칩과 동일 정합) */
.lab-cta-link {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--accent); color: #fff;
  font-size: 13px; font-weight: 700; white-space: nowrap;
  padding: 5px 13px; border-radius: 999px; text-decoration: none;
  box-shadow: 0 1px 6px rgba(15, 163, 177, 0.42);
  transition: background 0.15s, transform 0.15s, box-shadow 0.15s;
}
.lab-cta-link:hover,
.lab-cta-link:focus-visible {
  background: #0c8a96; transform: translateY(-1px);
  box-shadow: 0 2px 9px rgba(15, 163, 177, 0.55);
}

.banner {
  padding: 10px 20px;
  background: var(--accent);
  color: var(--primary-text);
  font-size: var(--font-sm);
}

.layout-3pane {
  display: grid;
  grid-template-columns: 360px 1fr 480px;
  grid-template-areas: "left map result";
  gap: 12px;
  padding: 12px;
  height: calc(100vh - var(--header-h) - var(--ticker-h) - var(--stepper-h, 0px));
  overflow: hidden;
}
/* flex column + position:relative — pane-totop 가 패널 안 sticky bottom 으로
   스크롤을 따라 항상 우하단에 머무르게 하기 위함. */
#left-panel  { grid-area: left;   overflow-y: auto; position: relative; display: flex; flex-direction: column; }
#map-pane    { grid-area: map;    position: relative; min-height: 240px; scroll-margin-top: 64px; }
#result-pane { grid-area: result; overflow-y: auto; position: relative; display: flex; flex-direction: column; }
/* flex 자식 기본 flex-shrink:1 이라 카드/리스트가 패널 높이에 맞춰 강제 압축
   → overflow-y:auto 가 트리거되지 않아 스크롤 사라지는 부작용. 자식들 shrink:0
   으로 자연 높이 유지 + 컨테이너가 넘치면 정상 스크롤. */
#left-panel > *, #result-pane > * { flex-shrink: 0; }

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
}

#vmap {
  position: relative;     /* map-context-menu absolute 기준 */
  width: 100%; height: 100%; min-height: 280px;
  border-radius: var(--radius-sm);
  background: var(--surface-alt);
}

.map-overlay {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: var(--surface-alt);
  color: var(--text-muted);
  border-radius: var(--radius);
  pointer-events: none;
  transition: opacity .25s ease;
}
.map-overlay.hide { opacity: 0; }

@media (max-width: 1100px) {
  .layout-3pane {
    grid-template-columns: 1fr;
    grid-template-areas: "left" "map" "result";
    height: auto;
    /* 모바일: 좌우 외곽 padding 제거, 상하 간격만 유지 — 좁은 화면 최대 활용 */
    gap: 8px;
    padding: 0;
  }
  /* 모바일: ticker 가 sticky 면 가시영역 30%↓ → static 으로 풀어 스크롤 시 사라지게.
     헤더만 sticky 유지. CSS 변수 --ticker-h 도 0 으로 되돌려 layout-3pane 가 영향 없도록. */
  .popular-ticker { position: static; }
  :root { --ticker-h: 0px; }
  /* 패널을 viewport 에 edge-to-edge — rounded corner 와 좌우 border 제거 */
  .panel {
    padding: 12px;
    border-radius: 0;
    border-left: none;
    border-right: none;
  }
  #map-pane { height: min(60vh, 480px); min-height: 300px; }
  /* 모바일 long-press 시 텍스트 선택/콜아웃 차단 */
  #vmap {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }
  /* 모바일은 page scroll 이 sticky 컨텍스트. overflow:auto 그대로 두면 #result-pane
     이 비록 자체 스크롤은 안 되더라도 sticky containing block 이 되어
     .selection-bar 가 viewport 따라가지 못함. visible 로 풀어 body 가 ancestor. */
  #result-pane { overflow: visible; }
}

@media (max-width: 640px) {
  body { font-size: 16px; }
  .field label, .field legend { font-size: 14px; }
  .muted { font-size: 14px; }
  /* 모바일 헤더: 우측 버튼들(소개/♿/칩/테마)이 제목을 압축시키는 문제 해결.
     제목을 단독 윗줄로 내리고 버튼은 그 아래 줄에 본래 크기로 노출. */
  .app-header { padding: 10px 12px; flex-wrap: wrap; row-gap: 6px; }
  .app-title { font-size: 16px; flex: 1 1 100%; order: 1; line-height: 1.3; }
  .header-meta { order: 2; flex-wrap: wrap; justify-content: flex-end; width: 100%; }
  /* 모바일 freshness chip 축소 — '대출 정보 ' / ' 갱신' 라벨 숨기고 시간만 표시
     (예: '5분 전'). dot 색상만으로도 신호 충분. */
  .freshness-pill .freshness-prefix,
  .freshness-pill .freshness-suffix { display: none; }
  /* 모바일 ticker 라벨 축소: '🔥 인기 도서 TOP 20' → '🔥 TOP 20' */
  .popular-ticker { padding: 0 12px; gap: 8px; height: 32px; }
  .ticker-label .ticker-label-full { display: none; }
  .ticker-label .ticker-label-short { display: inline; }
  #map-pane { height: 50vh; }
  /* 카드 사이 간격 컴팩트화 */
  .card { padding: 4px 0 10px; margin-bottom: 10px; }
  .card-title { font-size: 15px; }
  /* 더 작은 화면: 패널 padding 도 더 좁게 */
  .panel { padding: 10px; }
}
