:root {
  /* 2026-09-02(7차, 1단계): design_handoff_tripagit_1c/README.md §1 —
     2차 핸드오프. "토큰 이름은 모두 유지, 값만 교체" 원칙 그대로 적용.
     brand이 azure(밝은 파랑)→ink-blue(짙은 남색)로 바뀜: 지도 위 흰
     배경에서 대비가 확보되고 핀·경로선·CTA가 같은 색으로 묶임. 문서
     §1-1에서 값 변경을 명시한 토큰만 바꾸고, 나머지(1차 값)는 그대로 둠. */
  --brand: oklch(0.48 0.13 258); /* ink-blue, 기존 oklch(0.66 0.17 248) azure */
  --brand-dark: oklch(0.38 0.12 258); /* hover */
  --brand-soft: oklch(0.96 0.02 258); /* 칩/배지 배경 */
  --brand-soft-text: oklch(0.42 0.13 258);
  /* 2026-09-02(다크모드 감사): var(--brand)을 배경으로 채운 요소(버튼/탭/
     아바타 등) 위 글자색 전용 토큰. 라이트모드는 --brand이 충분히
     어두워서 흰 글자가 잘 보이지만, 다크모드는 --brand을 오히려 밝게
     뒤집어서(어두운 페이지 위에서 도드라지게) 흰 글자와 대비가
     2.69:1까지 떨어짐(WCAG AA 최소 3:1 미달, 실측으로 확인) — 이 토큰만
     다크모드에서 짙은 색으로 뒤집어서 그 자리들을 전부 한 번에 고침. */
  --brand-contrast: #fff;
  --bg: #fbfbfc; /* canvas */
  --bg-sunken: #f4f5f7; /* canvas-sunken */
  --card: #ffffff; /* surface */
  --border: #e8eaee;
  /* 2026-09-08: 라이트모드 조작 요소(input/select/textarea/button) 테두리가
     실측 1.23~1.28:1로 3:1 미달이었다(T2는 다크모드만 다룸) — 카드/bg/
     bg-sunken 전부에서 3:1을 넘는 값으로 올림(실측 3.52/3.40/3.22:1).
     카드/섹션 구분선(장식용, --border 그대로)은 대상 아님. */
  --border-strong: #7C8A9C;
  --border-subtle: #edeff2;
  --border-faint: #f1f3f5;
  --border-dashed: #d5dae0;
  --divider-vertical: #dfe3e8;
  --text: #0e1116; /* ink */
  --text-secondary: #333a42; /* ink-secondary */
  /* 2026-09-04 전체 점검(라이트 모드 실측): 이 두 토큰이 WCAG AA 미달이었다.
     --text-faint(#9ca4ae)는 흰 카드 위에서 2.52:1로, 다크모드에서 고친 것보다
     오히려 더 나빴다 — 이동시간 "약 17분 · 7.8km", 날짜칩 "2곳", 코멘트 시각,
     완료한 체크리스트 항목처럼 전부 진짜 정보를 담은 텍스트가 이 토큰을 쓴다.
     --text-muted(#6b7480)도 가라앉은 배경(--bg-sunken) 위 카테고리/세그먼트
     라벨에서 4.34:1로 살짝 미달이었다.
     흰 배경과 --bg-sunken 두 곳 모두에서 4.5:1을 넘는 값 중 **가장 밝은 쪽**으로
     골라서, "약하게 보이는" 디자인 의도는 최대한 살리면서 기준만 넘게 함
     (muted 5.64:1 / faint 4.92:1, 가라앉은 배경 위 5.17:1 / 4.52:1). */
  --text-muted: #5f6874;
  --text-faint: #687080;
  --text-disabled: #b6bdc5;
  --danger: oklch(0.58 0.17 30); /* accent-warn, ~#C4623F */
  /* 2026-09-08: 흩어져 있던 컴포넌트별 @media (prefers-color-scheme: dark)
     블록(.banner/.text-warning/.visa-eta/.visa-free)을 :root 토큰으로
     흡수 — 수동 테마 토글이 :root 토큰만 보고 있어서, 토큰화되지 않은
     컴포넌트는 토글을 눌러도 안 바뀌는 문제가 있었다(OS 라이트 + 토글
     다크 조합에서 실측 확인). 앞으로 새 경고/성공 색이 필요하면 여기
     토큰을 추가하고 컴포넌트에 새 @media 블록을 만들지 말 것. */
  --positive: #15803d; /* "가능/무비자" 같은 허용 상태 텍스트 */
  --text-warning: #b45309; /* 카드/배경 위에 직접 얹는 경고 텍스트(.text-warning, .visa-eta) */
  --warn-bg: #fffbeb; /* 경고 배너(.banner) 전용 — 위 --text-warning과 색조는 같은 계열이나 배경색이라 별도 토큰 */
  --warn-border: #fde68a;
  --warn-text: #92400e;

  --radius: 8px;
  --radius-sm: 6px;
  --radius-md: 9px;
  --radius-lg: 14px;
  --radius-card: 12px;
  --radius-frame: 16px;
  --radius-panel: 18px; /* 신규 — 큰 떠 있는 패널(§1-1) */

  --accent-sunset: oklch(0.82 0.14 92); /* sun, ~#DFC13F — 도구 위젯이 참조, 유지 */
  --accent-teal: oklch(0.74 0.15 178); /* mint, ~#2DBFAD — 도구 위젯이 참조, 유지 */
  --accent-teal-soft: oklch(0.965 0.035 178);
  --accent-teal-soft-text: oklch(0.45 0.11 178);
  --accent-sunset-soft: oklch(0.965 0.045 92);
  --accent-sunset-soft-text: oklch(0.44 0.1 78);
  --accent-coral: oklch(0.58 0.17 30); /* warn과 동일 계열로 통합 */
  --accent-violet: oklch(0.55 0.14 320); /* 세계지도 "다녀옴" 전용 — 아래 주석 참고 */
  --accent-violet-soft: oklch(0.955 0.03 320); /* 지출 "쇼핑" 아이콘/칩 배경 */
  --accent-violet-soft-text: oklch(0.45 0.13 320);
  --accent-coral-soft: oklch(0.96 0.03 30); /* 메모 보드 "연락처" 카드 */
  --accent-coral-soft-text: oklch(0.45 0.13 30);

  /* §1-2 동행자 색 팔레트(신규) — 일정 카드 좌측 색바/지도 핀/실시간
     커서/코멘트 아바타가 전부 이 색을 씀(가입 순서로 고정 배정). 아직
     trip_members가 없어(9단계) 이 턴에서는 소비하는 컴포넌트가 없지만,
     문서가 지정한 토큰이라 미리 선언만 해둠. */
  --member-1: oklch(0.48 0.13 258); /* 남색 */
  --member-2: oklch(0.62 0.16 25); /* 주홍 */
  --member-3: oklch(0.82 0.14 92); /* 노랑 — 이 색 위 글자는 #3d2f00 */
  --member-4: oklch(0.72 0.12 172); /* 청록 */
  --member-5: oklch(0.55 0.14 300); /* 자주 */
  --member-3-text: #3d2f00;

  /* §1-4 — 새 --text(#0e1116 = rgb(14,17,22))에 맞춰 그림자 rgba 갱신,
     신규 2종(panel/pin) 추가. */
  --shadow-sm: 0 1px 3px rgba(14, 17, 22, 0.08);
  --shadow-md: 0 8px 24px rgba(14, 17, 22, 0.12);
  --shadow-lg: 0 16px 40px rgba(14, 17, 22, 0.18);
  --shadow-panel: 0 24px 60px -30px rgba(14, 17, 22, 0.45);
  --shadow-pin: 0 6px 16px rgba(14, 17, 22, 0.3);

  --fs-xs: 12px;
  --fs-sm: 13px;
  --fs-base: 15px;
  --fs-lg: 18px;
  --fs-xl: 22px;
  --fs-2xl: 28px;
  --fs-3xl: 36px;

  --font-sans: "Pretendard Variable", Pretendard, "Noto Sans JP", "Noto Sans SC", "Noto Sans TC", system-ui, -apple-system, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;

  color-scheme: light dark;
}

/* 2026-09-02(7차, 1단계): §1-5 — "명도만 반전, hue는 유지" 원칙을 새 값에
   그대로 적용. prefers-color-scheme 블록은 절대 삭제 금지(2026-08-31에
   모바일 강제다크로 글자 안 보이던 사고 재발 방지, README §1-5 명시).
   brand는 hue가 248→258로, 라이트 L이 0.66→0.48로 크게 바뀌어(지각 가능한
   변화) 다크값도 같은 톤으로 다시 뽑음. bg/border/text 계열은 1차 대비
   라이트값 변화가 1~2 hex 수준으로 미세해서(예: bg #fafbfc→#fbfbfc) 기존
   다크 대응값을 그대로 두는 게 더 안전하다고 판단 — 정밀 변환 대신 이미
   검증된 값 유지. */
/* T2(2026-09-04): 27차/32차 대비 감사가 글자만 봤음 — WCAG 1.4.11(비텍스트
   대비 3:1)은 버튼 테두리/입력칸 경계/구분선에도 적용되는데, 카드 vs 배경
   1.08:1, --border on card 1.23:1로 화면의 뼈대 자체가 실측상 거의 안 보이는
   상태였다. 입체감(카드 vs 배경)만으로 경계를 만들려 하지 않고 테두리가
   경계를 담당하게 함 — 카드 테두리는 보이기만 하면 되고(≥1.8),
   input/select/button 등 실제 조작 요소의 테두리는 --border-strong으로
   3:1을 넘김. 아래 값은 전부 실측 계산 완료(PHASE0.md T2 표 참고).
   이 @media 블록은 절대 삭제 금지(2026-08-31 사고 재발 방지, §1-5) —
   :root[data-theme="dark"]가 수동 토글용으로 별도 존재하며 같은 값을 유지. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --brand: oklch(0.7 0.14 258);
    --brand-dark: oklch(0.78 0.12 258);
    --brand-soft: oklch(0.32 0.05 258);
    --brand-soft-text: oklch(0.85 0.09 258);
    --brand-contrast: #0e1116; /* 실측: 이 밝기의 --brand 위에서 7:1 대비 확보 */
    --bg: #0E1116;
    --bg-sunken: #070A0E;
    --card: #1C222B;
    --border: #474F5C;
    --border-strong: #6A727F;
    --border-subtle: #343D4A;
    --border-faint: #2A313C;
    --border-dashed: #6A727F;
    --divider-vertical: #474F5C;
    --text: #F2F4F7;
    --text-secondary: #D2D8E1;
    --text-muted: #9AA5B5;
    --text-faint: #939DAC;
    --text-disabled: #5C6675;
    --danger: oklch(0.68 0.16 30);
    --positive: #16a34a;
    --text-warning: #e2a13d;
    --warn-bg: #3a2f0f;
    --warn-border: #6b5416;
    --warn-text: #fbd989;
    --accent-sunset: oklch(0.85 0.13 92);
    --accent-teal: oklch(0.78 0.14 178);
    --accent-teal-soft: oklch(0.3 0.05 178);
    --accent-teal-soft-text: oklch(0.82 0.1 178);
    --accent-sunset-soft: oklch(0.32 0.05 92);
    --accent-sunset-soft-text: oklch(0.85 0.1 92);
    --accent-coral: oklch(0.68 0.16 30);
    --accent-violet: oklch(0.7 0.13 320);
    --accent-violet-soft: oklch(0.32 0.05 320);
    --accent-violet-soft-text: oklch(0.85 0.1 320);
    --accent-coral-soft: oklch(0.32 0.05 30);
    --accent-coral-soft-text: oklch(0.85 0.1 30);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.5);
    --shadow-panel: 0 24px 60px -30px rgba(0, 0, 0, 0.55);
    --shadow-pin: 0 6px 16px rgba(0, 0, 0, 0.4);
  }
}

/* T2 추가 C: 수동 다크모드 토글(헤더 ☀/☾ 버튼) — data-theme="dark"일 때는
   OS 설정과 무관하게 항상 다크. 위 @media 블록과 값을 동일하게 유지할 것. */
:root[data-theme="dark"] {
  --brand: oklch(0.7 0.14 258);
  --brand-dark: oklch(0.78 0.12 258);
  --brand-soft: oklch(0.32 0.05 258);
  --brand-soft-text: oklch(0.85 0.09 258);
  --brand-contrast: #0e1116;
  --bg: #0E1116;
  --bg-sunken: #070A0E;
  --card: #1C222B;
  --border: #474F5C;
  --border-strong: #6A727F;
  --border-subtle: #343D4A;
  --border-faint: #2A313C;
  --border-dashed: #6A727F;
  --divider-vertical: #474F5C;
  --text: #F2F4F7;
  --text-secondary: #D2D8E1;
  --text-muted: #9AA5B5;
  --text-faint: #939DAC;
  --text-disabled: #5C6675;
  --danger: oklch(0.68 0.16 30);
  --positive: #16a34a;
  --text-warning: #e2a13d;
  --warn-bg: #3a2f0f;
  --warn-border: #6b5416;
  --warn-text: #fbd989;
  --accent-sunset: oklch(0.85 0.13 92);
  --accent-teal: oklch(0.78 0.14 178);
  --accent-teal-soft: oklch(0.3 0.05 178);
  --accent-teal-soft-text: oklch(0.82 0.1 178);
  --accent-sunset-soft: oklch(0.32 0.05 92);
  --accent-sunset-soft-text: oklch(0.85 0.1 92);
  --accent-coral: oklch(0.68 0.16 30);
  --accent-violet: oklch(0.7 0.13 320);
  --accent-violet-soft: oklch(0.32 0.05 320);
  --accent-violet-soft-text: oklch(0.85 0.1 320);
  --accent-coral-soft: oklch(0.32 0.05 30);
  --accent-coral-soft-text: oklch(0.85 0.1 30);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.5);
  --shadow-panel: 0 24px 60px -30px rgba(0, 0, 0, 0.55);
  --shadow-pin: 0 6px 16px rgba(0, 0, 0, 0.4);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
}

a { color: var(--brand); text-decoration: none; }

header.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  row-gap: 10px;
  padding: 14px 24px;
  background: var(--card);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 50;
}

/* 2026-09-02: 핸드오프 문서 3화면(여행 상세) 헤더. 전역 .topbar와는 별개로
   여행 컨텍스트 정보(제목/D-day/날짜/아바타/공유/일정추가)만 담당 —
   .topbar는 사이트 전체 내비게이션(내 여행/여행도구/로그아웃)을 그대로
   유지해서 다른 페이지와의 일관성을 안 깨뜨림. */
.trip-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 18px 24px 16px;
  background: var(--card);
  border-bottom: 1px solid var(--border-subtle);
}
.trip-breadcrumb {
  font-size: 13px;
  color: var(--text-faint);
  margin-bottom: 4px;
}
.trip-breadcrumb a { color: var(--text-faint); }
.trip-breadcrumb a:hover { color: var(--text-muted); }
.trip-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.trip-title-input {
  border: none;
  background: transparent;
  padding: 2px 0;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--text);
  min-width: 120px;
  max-width: 420px;
}
.trip-title-input:focus {
  outline: none;
  border-bottom: 2px solid var(--brand);
}
.trip-date-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  font-size: 13px;
}
.trip-date-edit-fields {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  margin-top: 10px;
  flex-wrap: wrap;
}
.trip-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding-top: 2px;
}
/* 아바타는 실제 여행 소유자(로그인 세션) 1명 — 동행자 여러 명을 지어내지
   않음. 스택 형태(여러 개 겹침)는 실제 동행자 데이터가 생길 때 확장. */
.avatar-stack {
  display: flex;
}
.avatar {
  width: 28px;
  height: 28px;
  border-radius: 999px;
  border: 2px solid var(--card);
  background: var(--brand);
  color: var(--brand-contrast);
  font-size: 12px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.avatar-stack .avatar + .avatar { margin-left: -9px; }

header.topbar .brand {
  font-weight: 700;
  font-size: 18px;
  color: var(--text);
  white-space: nowrap;
}

/* 모든 페이지의 .brand 안에 <a>가 있다(2026-09-13, index.html도 로고 클릭 시
   메인으로 이동하도록 추가함 — 이전엔 index.html만 링크가 없었음). 각 <a>에
   style="color:inherit"만 믿지 않고 명시적으로 지정한다 — 링크 기본색/방문색
   (:visited)이 껴들어서 전체가 파랗게 보이는 문제 방지. */
header.topbar .brand a,
header.topbar .brand a:visited {
  color: var(--text);
}

header.topbar .brand span { color: var(--brand); }

header.topbar .header-right {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  /* 2026-09-13(재지적): column-gap을 18px로 올렸던 이전 수정이 "EN/테마
     버튼 사이가 너무 벌어졌다"는 반대 방향 재지적을 받음 — row-gap과
     같은 12px로 통일해서 사방 여백을 고르게 좁힌다. */
  gap: 12px;
}

/* 이메일 주소처럼 공백 없는 긴 문자열은 글자 중간에서 줄바꿈될 수 있어서
   (모바일 좁은 화면에서 실제로 겹쳐 보이는 문제가 있었음, 2026-08-31)
   명시적으로 막는다. 후속 배치(2026-09-13) 3번: #auth-area 자신은 flex가
   아니라서(내용은 JS가 채움) 안의 이메일 span+버튼들이 그냥 인라인
   흐름으로 나열되고 있었다 — 간격을 span의 margin-right(10px) 하나에만
   의존하고 버튼 사이는 템플릿 리터럴 줄바꿈이 HTML 공백 한 칸으로
   뭉쳐진 것에 기대고 있어서, 옆의 .header-right(gap:12px 18px)와
   간격이 안 맞고 세로 정렬도 미묘하게 어긋나 보였다("설정 버튼만
   이질적으로 보인다"는 리포트) — index.html/guides.html/trip.html/
   tools.html이 전부 이 하나의 #auth-area 규칙을 공유하므로, 여기에
   직접 flex를 줘서 한 번에 통일한다. */
/* 2026-09-13 수정: gap이 10px라 바깥 .header-right의 column-gap(18px,
   EN/테마 버튼 사이)보다 좁아서 안쪽(설정/로그아웃 버튼 사이)만 더
   빽빽해 보였다 — 바깥 리듬에 맞춰 18px로 통일했었는데, 그 다음 리포트가
   "이번엔 너무 넓어졌다, 특히 일정/지출/체크리스트/바우처/메모 탭에서
   이메일-로그아웃 간격이 멀다"였음 — .header-right도 같은 재지적으로
   12px로 줄였으므로(위 참고) 여기도 같이 12px로 맞춘다. */
#auth-area { white-space: nowrap; display: flex; align-items: center; gap: 12px; }

.nav-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
}

.nav-links a {
  color: var(--text-muted);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  /* 2026-09-04: 실측해보니 글자 높이만으로 16px라 모바일에서 손가락으로 누르기
     너무 작은 타겟이었다. 패딩으로 실제 누를 수 있는 높이를 32px로 넓히되,
     같은 크기의 음수 마진으로 레이아웃상의 높이는 그대로 둬서 헤더가 커지지
     않게 함(가로를 건드리면 링크 사이 간격이 달라지므로 세로만). */
  padding: 8px 0;
  margin: -8px 0;
}

.nav-links a.active,
.nav-links a:hover {
  color: var(--brand);
}

/* 랜딩(.tp-landing / .tp-hero-* / .tp-course-* 등)의 스타일은 css/landing.css 로 분리했다
   (index.html 에서만 로드). 이 아래 다크 블록은 .tp-trip-card 용 — OS 다크인데 토글을 안
   누른(data-theme 미설정) 사용자를 담당하므로 삭제 금지. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .tp-trip-card {
    background: #171d2b !important;
    border-color: #2a3346 !important;
    color: #e8eaf0;
  }
}
:root[data-theme="dark"] .tp-trip-card {
  background: #171d2b !important;
  border-color: #2a3346 !important;
  color: #e8eaf0;
}

.tp-google-cta {
  font-family: "Noto Sans KR", sans-serif;
  cursor: pointer;
}

/* 에러 없을 때 #login-msg가 빈 <p>로 남아있는데, 그것도 히어로의 flex
   gap(22px) + 자기 줄높이만큼 공간을 차지해서 "체험하기" 링크와 지도
   카드 사이 여백이 필요 이상으로 넓어 보였다 (2026-08-31). 비어있을 땐
   레이아웃에서 아예 빼버린다 — 실제 오류 메시지가 채워지면 다시 보임. */
#login-msg:empty {
  display: none;
}

.tp-guest-link {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  font-weight: 500;
  color: oklch(0.5 0.02 250);
}
.tp-guest-link:hover {
  color: oklch(0.62 0.13 220);
}

/* 공유 버튼 + 팝오버 */
.share-popover-wrap {
  position: relative;
}

.share-popover {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 320px;
  background: var(--card);
  border: 1px solid var(--border-strong); /* T2: 클릭 요소가 담긴 뜬 패널 — 3:1 확보 */
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  padding: 14px;
  z-index: 100;
  display: none;
}

.share-popover.open { display: block; }

.share-popover .row { align-items: center; }
.share-scope-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-subtle);
}
.share-scope-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  cursor: pointer;
}
.share-scope-item input[type="checkbox"] { accent-color: var(--brand); cursor: pointer; }

/* 여행 상태 배지 */
.status-badge {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  margin-left: 8px;
}

/* 2026-09-02(다크모드 버그 수정): 배경은 하드코딩된 밝은 hex(#eff6ff 등)로
   고정해두고 글자색만 var(--brand-dark)/var(--text-muted)처럼 다크모드에서
   밝게 뒤집히는 변수를 썼더니, 다크모드에서 "밝은 배경 + 밝은 글자"가
   되어 배지 글자가 거의 안 보였음(실제 리포트로 발견 — D-day 배지는
   여행 카드/헤더마다 나오는 핵심 요소라 영향이 컸음). 배경도 함께
   뒤집히는 기존 짝 변수(--brand-soft/-text, --bg-sunken, --accent-teal-soft,
   --accent-sunset-soft)로 전부 교체 — 배경과 글자색이 항상 같은 테마
   기준으로 같이 바뀌어야 한다는 원칙(다크모드 절 기존 교훈)을 배지에도
   그대로 적용. */
.status-badge.upcoming { background: var(--brand-soft); color: var(--brand-soft-text); }
.status-badge.ongoing { background: var(--accent-teal-soft); color: var(--accent-teal-soft-text); }
.status-badge.done { background: var(--bg-sunken); color: var(--text-muted); }
.status-badge.draft { background: var(--accent-sunset-soft); color: var(--accent-sunset-soft-text); }

/* 2026-09-02(5차): 핸드오프 문서는 1440px 캡처에서도 좌우 여백이 ~48px뿐인
   "화면을 꽉 채우는" 레이아웃인데, 기존엔 max-width:1100px로 가운데 좁은
   기둥을 만들어서 와이드 모니터에서 양옆에 큰 빈 여백이 생기고 있었음
   (사용자 피드백으로 발견). 초광폭(2560px+) 모니터에서 텍스트 줄 길이가
   과도해지는 것만 막는 선에서 상한을 넉넉하게 두고, 기본은 꽉 채움.
   --container-pad-x/y는 아래 지도 전체높이 레이아웃(.trip-col-map)이
   컨테이너 패딩을 정확히 상쇄해서 뷰포트 가장자리까지 붙게 만드는 데 재사용. */
:root {
  --container-pad-x: 32px;
  --container-pad-y: 24px;
}
.container {
  max-width: 1680px;
  margin: 0 auto;
  padding: var(--container-pad-y) var(--container-pad-x);
}
@media (max-width: 860px) {
  :root { --container-pad-x: 16px; }
}

/* 2026-09-02: design_handoff_tripagit_1c §3-1 앱 셸 — 좌측 아이콘 레일 +
   56px 헤더 + 나머지 flex:1 본문(.app-body). 히스토리: (7차) 76px 세로
   레일이 좁은 화면에 안 맞아서 모바일(≤860px)만 상단 가로탭
   (#trip-top-tabs)/사이트 전역 하단탭(.mobile-tabbar)으로 대체 →
   (11단계 이후) "모바일도 레일로 통일"을 시도해서 레일 폭만 줄이는
   방식으로 바꿨었음 → 그런데 세로 배치 아이콘이 비효율적이라는 재피드백을
   받고 최종적으로 **데스크톱은 레일 유지, 모바일은 레일을 완전히 숨기고
   하단 고정 탭바(.trip-bottom-tabbar, 사이트 전역 .mobile-tabbar와 동일한
   시각 패턴)로 교체**하는 걸로 확정함. 레일이 갖고 있던 사이트 전역
   내비게이션(가이드/도구)은 모바일 헤더의 컴팩트 아이콘 링크
   (.app-header-mobile-nav)로 이동. */
.app-shell {
  display: flex;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
.app-rail {
  display: flex;
  flex: 0 0 76px;
  background: var(--card);
  border-right: 1px solid var(--border-subtle);
  flex-direction: column;
  align-items: stretch;
  padding: 0 0 10px;
}
.app-rail-home {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 56px;
  margin-bottom: 6px;
  color: var(--text-muted);
}
.app-rail-home:hover { color: var(--brand); }
.app-rail-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.15;
}
.app-rail-brand-line {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
}
.app-rail-brand-line.app-rail-brand-accent { color: var(--brand); }
.app-rail-tabs { display: flex; flex-direction: column; gap: 2px; }
.app-rail-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 76px;
  height: 56px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  border-radius: 0;
}
.app-rail-btn .icon { width: 20px; height: 20px; }
.app-rail-btn:hover { background: var(--bg-sunken); color: var(--text); }
.app-rail-btn.active { background: var(--brand-soft); color: var(--brand-soft-text); }
.app-rail-bottom {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding-top: 10px;
}
.app-rail-bottom .avatar-stack { justify-content: center; }

/* 모바일은 레일 대신 .trip-bottom-tabbar(아래)를 쓴다 — 레일 자체를 숨김. */
@media (max-width: 860px) {
  .app-rail { display: none; }
}

.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}
.app-header {
  flex: 0 0 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 20px;
  border-bottom: 1px solid var(--border-subtle);
}
/* §3-1은 데스크톱 56px 한 줄 헤더만 명시함 — 모바일은 제목+배지+날짜+
   공유+계정 상태까지 한 줄에 못 들어가서(실측으로 발견: 겹쳐 보임)
   좁은 화면에서는 줄바꿈을 허용하는 자동 높이로 완화.
   2026-09-02(밀도 개선): 처음엔 각 줄 내부(app-header-left/right)까지
   flex-wrap을 허용해서 제목/날짜/아이콘/계정상태가 각자 다른 줄로
   흩어져 4줄까지 늘어났었음("한 화면에 중요한 정보가 안 들어온다"는
   피드백) — 이제 각 줄 내부는 nowrap으로 고정해서 "제목+배지+날짜"
   1줄, "아이콘+공유+동행자+계정상태" 1줄, 총 2줄로 압축. 버튼 텍스트
   라벨(.btn-label)은 모바일에서 숨기고 아이콘+숫자만 남겨 폭을 아낌 —
   두 번째 줄도 그래도 넘치면(계정 이메일이 긴 경우 등) 줄바꿈 대신
   가로 스크롤로 흡수(overflow-x:auto)해서 세로 줄 수가 다시 늘어나지
   않게 함. */
@media (max-width: 860px) {
  .app-header {
    flex: 0 0 auto;
    flex-wrap: wrap;
    height: auto;
    padding: 8px 14px;
    row-gap: 4px;
  }
  .app-header-left {
    flex-wrap: nowrap;
    width: 100%;
    min-width: 0;
  }
  /* 2026-09-02(버그 수정): overflow-x:auto를 줬더니 CSS 스펙상 overflow-y가
     자동으로 auto가 돼서(둘 중 하나가 스크롤이면 나머지도 visible을
     못 씀), 이 안에 있는 공유/동행자 팝오버(position:absolute로 이
     컨테이너 밖까지 튀어나옴)가 그대로 잘려서 안 보이는 버그가 있었음
     ("버튼 눌러도 반응 없음"으로 보고받음 — 실제로는 열리긴 했는데
     클리핑돼서 안 보였던 것, classList로 확인). 이메일을 이미
     .app-auth-email에서 64px로 말줄임해뒀고 아이콘들도 충분히 작아서
     실제로는 한 줄에 다 들어가므로 스크롤 자체가 필요 없음 — 없애서
     팝오버 클리핑 문제를 근본적으로 제거. */
  .app-header-right {
    flex-wrap: nowrap;
    width: 100%;
    gap: 4px;
  }
  .app-header-right .btn { padding: 6px 10px; }
  .app-title-group { flex: 1 1 auto; min-width: 0; }
  .app-title-group .trip-title-input {
    max-width: none;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* 제목만 줄어들고(위 min-width:0+ellipsis) 배지/날짜는 안 짜부러지게 —
     안 그러면 flex-shrink 기본값(1) 때문에 셋이 비율대로 같이 눌린다. */
  #trip-status-badge,
  .app-header-left > .popover-wrap:not(.app-title-group) { flex-shrink: 0; }
  .app-date-btn { padding: 4px 6px; font-size: 11px; }
  .btn-label { display: none; }
  /* 2026-09-04(전체 점검): "투어/티켓 검색" 칩이 .item-row-side로 옮기고
     보니, 이 칩의 텍스트 폭이 좁은 화면에서 .item-row-side 전체를 넓혀서
     정작 장소명·주소가 있는 본문 칸을 짓눌렀다(실측: 375px에서 본문 56px로
     짜부러짐) — 모바일에서는 아이콘만 남기고 글자는 숨김(title 툴팁은 유지).
     .btn-label과 같은 패턴. */
  .item-row-affiliate-label { display: none; }
  .item-row-affiliate { padding: 0; width: 22px; height: 22px; justify-content: center; border: none; }
  /* Phase 2(2026-09-10): "제휴" 배지도 라벨과 같은 이유로 모바일에서 숨김 —
     아이콘 22px 안에 배지까지 넣을 공간이 없다(title 툴팁은 유지). */
  .item-row-affiliate-badge { display: none; }
  .app-auth-email { max-width: 64px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle; }
  .app-auth-area { font-size: 11px; flex-shrink: 0; }
}
.app-header-left { display: flex; align-items: center; gap: 10px; min-width: 0; }
.app-header-right { display: flex; align-items: center; gap: 8px; }
.app-auth-area { display: flex; align-items: center; gap: 8px; font-size: 12px; white-space: nowrap; }
.app-title-group { display: flex; align-items: center; gap: 2px; }
.app-title-group .trip-title-input {
  border: none;
  background: transparent;
  font-size: 15px;
  font-weight: 700;
  padding: 4px 2px;
  width: auto;
  max-width: 220px;
  color: var(--text);
}
.app-title-chevron-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: none;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.app-title-chevron-btn:hover { background: var(--bg-sunken); color: var(--text); }
.app-title-chevron-btn .icon { width: 15px; height: 15px; transform: rotate(90deg); }
.app-date-btn {
  border: none;
  background: transparent;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--text-muted);
  font-size: 12px;
}
.app-date-btn:hover { background: var(--bg-sunken); color: var(--text); }

/* 공유 팝오버(.share-popover)와 같은 뜨는 패널 패턴을 제목전환/날짜수정에도
   재사용하기 위한 범용 버전 — .share-popover는 우측 정렬(right:0)이라
   헤더 좌측 요소에 쓰면 화면 밖으로 나가서 left:0인 새 쌍을 추가. */
.popover-wrap { position: relative; }
.popover {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  width: 280px;
  background: var(--card);
  border: 1px solid var(--border-strong); /* T2: 클릭 요소가 담긴 뜬 패널 — 3:1 확보 */
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  padding: 14px;
  z-index: 100;
}
.popover.open { display: block; }
/* 2026-09-02(버그 수정): 처음엔 날짜/동행자 팝오버만 "헤더 오른쪽에
   있으니 right:0으로 뒤집자"고 좁게 고쳤는데, 그 직후 공유 팝오버
   (기본이 반대로 right:0)에서 똑같은 종류의 문제가 반대 방향으로
   재발함 — 모바일 헤더에 아이콘을 몇 개 넣느냐에 따라 각 버튼이 화면의
   어느 지점에 있을지 계속 바뀌니, 버튼별로 "왼쪽/오른쪽 중 뭐가
   안전한가"를 하나씩 맞추는 방식 자체가 아이콘 구성이 바뀔 때마다
   깨지기 쉬운 접근이었음. 그래서 모바일에서는 헤더에서 여는 팝오버
   전부를 자기 버튼 기준(position:absolute)이 아니라 화면 기준
   (position:fixed, 좌우 12px 여백)으로 통일 — 어떤 버튼에서 열든
   항상 화면 안에 꽉 차게 뜬다(버튼을 정확히 가리키며 뜨는 맛은
   포기하고, 절대 넘치지 않는 쪽을 우선함). 헤더 높이가 대략
   80~90px라 top을 92px로 고정 — 헤더 높이가 크게 바뀌면 같이 조정할 것.
   목록 안 주소 팝오버(.addr-popover, 항목별로 다른 위치에서 열림)는
   이 규칙 대상이 아니라서 그대로 자기 버튼 기준 앵커를 씀. */
@media (max-width: 860px) {
  .app-header .popover,
  .app-header .share-popover {
    position: fixed;
    top: 92px;
    left: 12px;
    right: 12px;
    width: auto;
  }
}
.addr-popover-wrap { display: inline-flex; }
.addr-popover { width: 300px; }

/* 2026-09-02(7차, 2단계 보완): 여행 전환 드롭다운의 실제 여행 목록 항목 */
.trip-switch-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 6px;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
}
.trip-switch-item:hover { background: var(--bg-sunken); }
.trip-switch-item-title { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trip-switch-item-date { font-size: 11px; color: var(--text-muted); flex: none; }

.members-count-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--brand-soft-text);
  font-size: 10px;
  font-weight: 700;
  margin-left: 4px;
}
/* 보류 목록 2번 재검토: 동행자 초대 팝오버(#members-popover) 목록 행 */
.member-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 2px;
  font-size: 13px;
}
.member-row > span:first-child { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.member-row .icon { width: 15px; height: 15px; color: var(--text-faint); }

.app-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
.app-body .tab-panel { display: none; }
.app-body .tab-panel.active {
  display: block;
  padding: var(--container-pad-y) var(--container-pad-x);
}
@media (min-width: 861px) {
  /* 일정 탭만 목록|지도 2분할이 레일/뷰포트 가장자리에 그대로 붙어야 해서
     (§3-1 다이어그램에 여백 없음) 패딩을 0으로 — 목록 칸 자체 패딩은
     .trip-col-main에 따로 있음. 다른 탭은 기존처럼 카드 여백 유지. */
  #tab-panel-sched.active { padding: 0; overflow: hidden; }
}
.no-scrollbar { scrollbar-width: none; }
.no-scrollbar::-webkit-scrollbar { display: none; }

/* 모바일 하단 고정 탭바(64px) + FAB(52px, 탭바 위에 뜸) 둘 다를 가릴
   여유를 둠 — 탭바 높이 64px + FAB가 차지하는 영역(52px+16px 여백)까지. */
@media (max-width: 860px) {
  .app-body { padding-bottom: 150px; }
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 20px;
}

.card > h2:first-child,
.card > h3:first-child {
  margin-top: 0;
}

/* 공용 위젯(js/widgets)은 여러 페이지에 얹히고, 그중 tools.html은 CSP에
   style-src 'unsafe-inline'이 없으므로 위젯 안에서 인라인 style="" 대신 이 유틸을 쓴다. */
.flex-none { flex: 0 0 auto; }
.m-0 { margin: 0; }
.mt-1 { margin-top: 4px; }
.mt-2 { margin-top: 8px; }
.mb-1 { margin-bottom: 4px; }
.mb-2 { margin-bottom: 6px; }
.p-4 { padding: 16px; }

/* 2026-09-01(2차): 로그인 후 화면에 랜딩의 세리프를 부분 적용했던
   .serif-heading은 trablog 참고 전면 개편에서 "굵은 산세리프만" 쓰는
   방향으로 확정하며 제거함 — 이제 세리프는 로그아웃 랜딩(.tp-h1/.tp-h2)
   에만 남음. #trip-title 관련 CSS 명시도 이슈였던 것도 같이 사라짐.
   tools.html 페이지 제목용 margin/font-size 클래스만 남김(CSP가 인라인
   style=를 막아둔 페이지라 클래스로 뺌). */
.tools-page-title { margin: 0 0 4px; font-size: 26px; font-weight: 800; }
/* 2026-09-04(전체 점검): 12개 도구가 무순서로 한 그리드에 쭉 나열돼
   "난잡하다"는 지적 — 성격별로 묶고 제목만 붙임(카드 자체는 그대로). */
.tools-section { margin-top: 28px; }
.tools-section:first-of-type { margin-top: 20px; }
.tools-section-title {
  margin: 0 0 12px;
  font-size: 15px;
  font-weight: 700;
  color: var(--text-muted);
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: 8px;
  border: 1px solid var(--border-strong); /* T2: 클릭 대상 — 3:1 확보 */
  background: var(--card);
  color: var(--text);
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  /* 버튼 안에서 글자가 두 줄로 쪼개지는 문제(좁은 화면에서 버튼이 줄어들 때
     "편집"이 "편\n집"처럼 끊기는 것) 방지 — 버튼 라벨은 항상 한 줄이어야
     한다 (2026-08-31 실제로 겪음). */
  white-space: nowrap;
}

.btn:hover { background: var(--border); }
.btn:disabled { opacity: 0.35; cursor: not-allowed; }
/* 데스크톱은 레일(.app-rail-bottom)에 가이드/도구 링크가 이미 있으니
   숨김 — 모바일은 레일이 없어지는 대신(위 .app-rail 참고) 헤더에 이
   아이콘만 남겨서 사이트 전역 내비게이션을 계속 쓸 수 있게 함.
   .btn의 display:inline-flex보다 소스 순서상 반드시 뒤에 있어야
   이긴다(명시도 동률 — 예전에 겪은 것과 같은 종류의 함정이라 여기 바로
   옆에 둠). */
.app-header-mobile-nav.btn { display: none; }
@media (max-width: 860px) {
  .app-header-mobile-nav.btn { display: inline-flex; padding: 6px 8px; }
}
.btn:disabled:hover { background: var(--card); }

.btn-armed {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-contrast);
}
.btn-armed:hover { background: var(--brand-dark); }

.btn-primary {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-contrast);
}

.btn-primary:hover { background: var(--brand-dark); }

/* 2026-09-01 (2차): 필 버튼(999px) 실험을 되돌림 — trablog 참고 전면
   개편에서 "각진 8px" 쪽으로 확정. .btn과 동일한 var(--radius)로 통일. */

/* 2026-09-02(다크모드 감사): 테두리/hover 배경이 하드코딩된 연분홍
   (#fecaca, #fef2f2)이라 다크모드의 어두운 카드 배경과 안 어울리고,
   특히 hover는 var(--danger)가 다크모드에서 밝은 색으로 뒤집히는데
   배경은 여전히 연분홍(밝음)이라 "밝은 글자 위에 밝은 배경" 대비 문제가
   생길 수 있었음 — var(--danger)를 var(--card)와 섞어서(color-mix)
   테두리/hover 배경 모두 테마에 따라 같이 뒤집히게 함. */
.btn-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, var(--card)); }
.btn-danger:hover { background: color-mix(in srgb, var(--danger) 12%, var(--card)); }

.btn-sm { padding: 5px 10px; font-size: 13px; }

input[type="text"],
input[type="email"],
input[type="date"],
input[type="number"],
textarea,
select {
  width: 100%;
  padding: 7px 10px;
  /* T2: 조작 요소(실제로 클릭/타이핑하는 대상)는 --border-strong으로 3:1
     이상 확보 — 장식용 카드/구분선은 --border 그대로 둔다. */
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  font-size: 14px;
  font-family: inherit;
  background: var(--card);
  color: var(--text);
}

textarea { resize: vertical; min-height: 60px; }

label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 3px;
}

.field { margin-bottom: 10px; }

.row { display: flex; gap: 12px; }
.row > * { flex: 1; }
/* 2026-09-02(7차): .row > *와 .flex-none은 명시도가 (0,1,0)로 동률이라
   소스 순서(.row > *가 뒤에 있어서 이김)에 밀려 .flex-none이 사실상 무시돼
   버튼이 .row 안에서 늘어나 있던 버그 — 명시도를 확실히 높여서 고정.
   (이 프로젝트에 이미 기록된 "명시도 동률→소스 순서" 패턴과 같은 종류의
   버그, style.css 상단 CATEGORY_ICON_MAP 근처 CLAUDE.md 기록 참고.) */
.row > .flex-none { flex: 0 0 auto; }

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

@media (max-width: 860px) {
  .grid-2 { grid-template-columns: 1fr; }
}

/* trip.html/share.html 전용 3분할 레이아웃 (일정 목록 / 지도 / 코멘트).
   PC: 2열 그리드 — 왼쪽 trip-col-main(일정+코멘트), 오른쪽 trip-col-map.
   이 기본(base) 규칙은 이제 share.html에서만 실제로 쓰인다 — trip.html의
   같은 클래스는 항상 #tab-panel-sched 스코프의 flex 규칙(아래 참고)이
   덮어써서 이 grid가 적용될 일이 없음(폭 좁은 문서형 공유화면과, 뷰포트
   전체를 채우는 편집화면은 애초에 요구사항이 달라서 의도적으로 다른 규칙).
   §4 8단계: 코멘트를 별도 trip-col-comments 래퍼 없이 trip-col-main 안
   목록 뒤에 바로 두도록 단순화(2026-08-30에 겪었던 grid-row 다중 걸침
   버그는 애초에 안 생김 — main이 코멘트까지 포함해서 한 열 안에 쌓이므로). */
.trip-layout {
  display: grid;
  grid-template-columns: 460px 1fr;
  gap: 20px;
  align-items: start;
}

/* .card 자체의 margin-bottom과 부모의 gap이 같은 방향으로 겹치면 간격이
   들쭉날쭉해짐 — 실제로 사용자가 지적해서 확인 후 고침 (2026-08-30).
   trip-layout 안에서는 카드 자체 margin을 없애고 gap/폭 하나로만 간격을
   통일한다. */
.trip-col-main > .card:last-child,
.trip-col-map > .card:last-child {
  margin-bottom: 0;
}

/* 2026-09-02(7차, 2단계): design_handoff_tripagit_1c §3-1 — 목록 456px
   고정 + 지도 flex:1. 5차에서는 앱 셸이 없어 뷰포트 높이를 JS로 실측해서
   --sched-height에 주입해야 했는데(트립헤더가 날짜수정 토글 등으로 높이가
   변하는 3층 헤더였음), 이제 헤더가 56px 고정이고 .app-shell 전체가
   height:100vh인 순수 flex 체인이라 각 단계에 min-height:0만 정확히
   전달하면 JS 없이도 높이가 딱 맞음 — updateSchedLayoutHeight()/
   --sched-height/.sched-tab-active 메커니즘 전체를 제거(아래 JS도 동일). */
#tab-panel-sched.active {
  height: auto;
}
@media (min-width: 861px) {
  #tab-panel-sched.active {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    padding: 0;
  }
  #tab-panel-sched .trip-layout {
    display: flex;
    align-items: stretch;
    flex: 1;
    min-height: 0;
  }
  /* 2026-09-03(3차 핸드오프 1단계, 아트보드 2a): "일정이 본문, 지도는
     문맥". 일정 컬럼을 뷰포트 비율(40%)이 아니라 672px 고정으로 바꾼다 —
     장소명이 두세 줄로 깨지지 않고 주소·메모·금액이 한 행에 들어갈 수
     있는 폭이 기준이지, 모니터가 넓다고 같이 넓어져야 하는 값이 아니기
     때문. 목록↔지도 사이 gap은 0, 경계는 선 하나(border-right)로만. */
  #tab-panel-sched .trip-layout { gap: 0; }
  #tab-panel-sched .trip-col-main {
    /* 1100~1280px 구간에서는 유동(최소 560px) — 문서 §반응형 분기 */
    flex: 1 1 560px;
    max-width: 672px;
    min-width: 0;
    /* 컬럼 자체는 스크롤하지 않는다. 날짜 탭·검색줄·요약줄은 고정이고
       그 아래 .sched-list만 스크롤한다(문서 "스크롤 주체"). */
    overflow: hidden;
    display: flex;
    flex-direction: column;
    padding: 0;
    border-right: 1px solid var(--border-subtle);
  }
  #tab-panel-sched .trip-col-map {
    flex: 1;
    min-width: 0;
    display: flex;
  }
  #tab-panel-sched .trip-col-map .card.map-card {
    flex: 1;
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    border-radius: 0;
    border: none;
  }
  #tab-panel-sched .trip-col-map .card.map-card #map {
    flex: 1;
    height: auto;
    width: 100%;
    border-radius: inherit;
    border: none;
  }
}

/* ≥1280px에서만 문서 스펙의 672px 고정. 그보다 좁으면 위 861+ 규칙의
   유동 폭(기준 560px)이 그대로 남아 지도가 완전히 눌리지 않는다. */
@media (min-width: 1280px) {
  #tab-panel-sched .trip-col-main { flex: 0 0 672px; max-width: 672px; }
}
/* 모바일 레이아웃 히스토리:
   1) 지도를 position:fixed로 위에 못박음 → "지도는 안 움직이고 나머지만
      뒤로 말려들어가는" 게 부자연스럽다는 피드백(2026-08-30)
   2) "일정/지도" 탭으로 전환해서 한 번에 하나만 보여줌 → 지도가 안 보이는
      동안 컨테이너가 display:none이라 크기를 못 재서, 처음 지도 탭을 열 때
      확대/축소가 엉망이거나 경로선이 안 보이는 문제가 반복(2026-08-31)
   3) 탭 전환을 없애고 지도를 위에 작게 두고 그 아래 목록이 이어지는 구조
   4) 2026-09-03(3차 핸드오프 4단계, 아트보드 3c): 다시 **목록/지도 전환**으로.
      390px에 둘을 넣으면 둘 다 못 쓴다는 게 문서의 판단이고, 2)의 실패
      원인이던 "숨겨졌다 보일 때 크기를 잘못 잼"은 그 사이에 구조적으로
      해결됐다 — createTripMap()이 컨테이너에 ResizeObserver를 붙여 크기가
      바뀔 때마다 map.resize()를 부르고, 2단계의 지연 생성 덕에 지도를
      "보이는 순간"에 만들기까지 한다. 1)/3)과 달리 sticky/fixed도 전혀
      쓰지 않는다(지도 모드에서는 페이지가 아예 스크롤하지 않고, 스크롤은
      시트 안쪽 목록만 한다). */
@media (max-width: 860px) {
  .trip-layout {
    display: flex;
    flex-direction: column;
    /* align-items 기본값(normal→stretch가 아닌 경우가 있음)에 맡겼다가
       지도 폭이 1.6px로 찌그러지는 버그가 났었음 — 명시적으로 stretch를
       줘서 각 항목이 항상 컨테이너 전체 너비를 채우게 함 (2026-08-30 재발 확인). */
    align-items: stretch;
  }
  .trip-col-map { order: -1; }
  .trip-layout { gap: 0; }
  .trip-col-main { order: 0; }

  /* 기본(목록 모드): 지도를 아예 렌더하지 않는다 */
  #tab-panel-sched .trip-col-map { display: none; }

  .trip-col-map .card {
    border-radius: 0;
    border: none;
    margin-bottom: 0;
    padding: 0;
    overflow: hidden;
  }
  .trip-col-main > .sched-col {
    height: auto;
    padding-top: 8px;
    border-radius: 0;
    border: none;
  }
  .sched-daybar,
  .sched-search-row,
  .sched-aux,
  .sched-summary,
  .sched-list { padding-left: 16px; padding-right: 16px; }
  .sched-aux { max-height: none; overflow: visible; }
  .sched-list { flex: none; overflow: visible; }
  .sched-search-kbd { display: none; }
  .sched-empty { padding-top: 16px; }

  /* 날짜 카드 62px + 요일 생략 — 바로 아래 요약줄이 "4월 4일 토요일"을
     말하므로 요일은 중복이고, 62px에 억지로 넣으면 줄바꿈된다. */
  .sched-day-card { width: 62px; flex: 0 0 62px; height: 58px; padding: 7px 8px; }
  .sched-day-card-dow { display: none; }
  .sched-day-card.is-all { width: 46px; flex: 0 0 46px; }

  /* ---- 지도 모드 ---- */
  /* 패널이 뷰포트 잔여 높이를 그대로 차지하고 페이지는 스크롤하지 않는다.
     .app-body의 padding-bottom(하단 바 자리)이 남아 있으므로 액션 바·탭바와
     겹치지 않는다 — 별도 fixed 계산이 필요 없다. */
  .app-body.map-view { overflow: hidden; }
  #tab-panel-sched.map-view.active {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    padding: 0;
  }
  #tab-panel-sched.map-view .trip-layout {
    flex: 1;
    min-height: 0;
  }
  #tab-panel-sched.map-view .trip-col-map {
    display: flex;
    flex: 1;
    min-height: 0;
  }
  #tab-panel-sched.map-view .trip-col-map .card {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }
  #tab-panel-sched.map-view .trip-col-map #map { flex: 1; height: auto; min-height: 0; }

  /* 바텀시트: 하단 45%, 손잡이를 위로 끌면(또는 탭하면) 전체 */
  #tab-panel-sched.map-view .trip-col-main {
    flex: 0 0 45%;
    min-height: 0;
    z-index: 2;
    border-radius: 20px 20px 0 0;
    background: var(--card);
    box-shadow: 0 -8px 30px -6px rgba(14, 17, 22, 0.16);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  /* 2026-09-04(4차 피드백): "위로 끌면 지도를 덮어버릴 수 있게" — 예전엔
     .trip-col-main만 flex:1로 키웠는데, .trip-col-map도 flex:1이라 flex
     column 안에서 둘이 남는 공간을 반씩 나눠 가져서 시트가 절반 정도밖에
     안 커졌다(실제로는 펼쳐져도 지도가 안 덮이는 것처럼 보였을 것). 지도
     쪽 flex-basis/grow를 0으로 눌러서 시트가 온전히 전체를 차지하게 함 —
     지도 인스턴스 자체는 유지(언마운트 아님), 아래로 다시 끌면 그대로 복귀. */
  #tab-panel-sched.map-view.sheet-expanded .trip-col-main { flex: 1 1 auto; }
  #tab-panel-sched.map-view.sheet-expanded .trip-col-map { flex: 0 0 0; min-height: 0; }
  /* 후속 배치(2026-09-14) 3번 재작업: #mobile-view-toggle을 드래그하는
     동안(tripSchedule.js의 wireMobileViewToggleDrag) JS가 매 프레임
     .trip-col-main의 flex-basis를 손가락 위치로 직접 밀어준다 — 이때
     CSS transition이 걸려 있으면 손가락보다 한 박자 늦게 쫓아오는
     것처럼 보여서(실측으로 확인) 드래그 중엔 꺼둔다. 손을 뗀 순간에만
     .sheet-settling으로 짧게 걸어서 최종 위치까지 부드럽게 안착시키고,
     끝나면 다시 지운다(다음 드래그가 또 지연 없이 반응하도록). */
  #tab-panel-sched.map-view.sheet-live-dragging .trip-col-main,
  #tab-panel-sched.map-view.sheet-live-dragging .trip-col-map { transition: none; }
  #tab-panel-sched.map-view.sheet-settling .trip-col-main,
  #tab-panel-sched.map-view.sheet-settling .trip-col-map { transition: flex-basis 0.25s ease, flex-grow 0.25s ease; }
  #tab-panel-sched.map-view .trip-col-main > .sched-col {
    flex: 1;
    height: auto;
    min-height: 0;
    padding-top: 0;
    border-radius: inherit;
  }
  #tab-panel-sched.map-view .trip-col-main > .sched-empty { flex: 1; min-height: 0; overflow-y: auto; }
  /* 시트 안에서는 목록만 스크롤한다(페이지는 스크롤하지 않음) */
  #tab-panel-sched.map-view .sched-list { flex: 1; min-height: 0; overflow-y: auto; }
  #tab-panel-sched.map-view .sched-aux { max-height: 30vh; overflow-y: auto; }
  /* 시트가 접혀 있을 땐 날짜 탭까지만 보여주고 검색줄은 펼쳤을 때만 */
  #tab-panel-sched.map-view:not(.sheet-expanded) .sched-search-row,
  #tab-panel-sched.map-view:not(.sheet-expanded) .sched-aux,
  /* 접힌 시트(45%)에서는 목록 자체가 더 중요하다 — 타임라인 요약 스트립은
     펼쳤을 때만 보여준다. */
  #tab-panel-sched.map-view:not(.sheet-expanded) .timeline-strip { display: none; }

  /* 손잡이는 시트가 실제로 존재하는 지도 모드에서만 — 목록 모드에서 보이면
     끌 수 있을 것처럼 보이지만 아무 일도 안 일어난다. */
  #tab-panel-sched.map-view .trip-col-main > .sheet-handle { display: block; }
}

/* 시트 손잡이 — 데스크톱에는 시트 자체가 없어서 숨긴다.
   2026-09-04(4차 피드백 재지적, 5차): 직전 라운드에서 "패딩을 20px씩 키워
   히트 영역을 넓히자"고 했다가, 사용자가 "그 부분이 자리를 너무 많이
   차지해서 비효율적"이라고 재지적 — 시각적 크기까지 같이 커져서 생긴
   부작용이었다(패딩은 실제 레이아웃 공간을 차지함). 27차가 다른 작은
   버튼(내비 링크·순서변경 버튼)에 쓴 것과 같은 "보이는 크기는 그대로,
   안 보이는 히트 박스만 ::after로 넓힌다" 방식으로 교체 — 패딩은 원래
   값(10px 0 8px, 시각적 높이 ~22px)으로 되돌리고, 44px 투명 히트존을
   절대위치로 덧씌운다. */
.sheet-handle {
  display: none;
  position: relative;
  width: 100%;
  padding: 10px 0 8px;
  border: none;
  background: none;
  cursor: grab;
  touch-action: none;
  flex: 0 0 auto;
}
.sheet-handle::before {
  content: "";
  display: block;
  width: 38px;
  height: 4px;
  border-radius: 2px;
  /* 2026-09-04(5차): 다크모드에서 --border-strong(#33363c)이 카드 배경
     (#1a1b1f)과 명도가 거의 같아서 실측 대비 1.4:1 — 손잡이가 사실상
     안 보였다(실제 사용자 스크린샷으로 확인된 버그). 27차에 이미 두 테마
     모두 카드 배경 위 가독성을 검증해둔 --text-faint로 교체. */
  background: var(--text-faint);
  margin: 0 auto;
}
/* 실제 터치 히트 영역만 44px로 확장 — 시각적 알약 크기(4px)는 그대로 두고
   손가락이 닿을 수 있는 범위만 넓힌다(27차 .item-row-action::after와 동일 원칙). */
.sheet-handle::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}
.sheet-handle:active { cursor: grabbing; }

/* 마커를 눌러 목록이 그 항목으로 스크롤했을 때 잠깐 표시 */
.item-row-focused { background: var(--brand-soft); border-radius: var(--radius-sm); }

/* 하단 고정 액션 바(48px) — 하단 탭바(64px) 바로 위 */
.mobile-action-bar { display: none; }
@media (max-width: 860px) {
  /* 2026-09-04(4차 피드백): "장소 추가" 바는 일정 탭에서만 의미가 있는데
     지출/체크리스트/바우처/메모에서도 계속 떠 있었음 — activateTab()이
     붙이는 클래스로 다른 탭에서는 숨김. */
  .mobile-action-bar.is-hidden { display: none; }
  .mobile-action-bar {
    display: flex;
    gap: 8px;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 64px;
    padding: 10px 16px;
    background: var(--card);
    border-top: 1px solid var(--border-subtle);
    z-index: 59;
  }
  .mobile-action-primary {
    flex: 1;
    min-width: 0;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    border: none;
    border-radius: var(--radius-card);
    background: var(--brand);
    color: var(--brand-contrast);
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
  }
  .mobile-action-primary .icon { width: 19px; height: 19px; }
  .mobile-action-icon {
    position: relative;
    width: 48px;
    flex: 0 0 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-card);
    background: var(--card);
    color: var(--text-secondary);
    cursor: pointer;
  }
  .mobile-action-icon .icon { width: 21px; height: 21px; }
  /* 후속 배치(2026-09-14) 3번: #mobile-view-toggle이 탭뿐 아니라 위/아래
     드래그도 받는다(tripSchedule.js의 wireMobileViewToggleDrag 참고) —
     .sheet-handle과 같은 이유로 touch-action:none이 필요하다. 이게 없으면
     모바일 브라우저가 세로 드래그를 "페이지 스크롤 제스처"로 먼저 채가서
     pointerup 전에 pointercancel이 뜰 수 있다. */
  #mobile-view-toggle { touch-action: none; }
  .mobile-action-icon.active {
    border-color: var(--brand);
    background: var(--brand-soft);
    color: var(--brand-soft-text);
  }
  .mobile-action-badge {
    position: absolute;
    top: 5px;
    right: 5px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    box-sizing: border-box;
    border-radius: 999px;
    background: var(--danger);
    color: var(--brand-contrast);
    font-size: 10px;
    font-weight: 600;
    line-height: 16px;
    text-align: center;
  }
  .mobile-action-badge[hidden] { display: none; }
  /* 하단 탭바(64px) + 액션 바(48px+20px 패딩)를 가릴 여유 */
  .app-body { padding-bottom: 160px; }
  /* 지도 모드에서는 패널이 뷰포트 잔여 높이를 정확히 채워야 해서, 실제로
     가려지는 만큼(액션 바 69px + 탭바 64px)만 남긴다. */
  .app-body.map-view { padding-bottom: 133px; }
  .container { padding-bottom: 150px; }
}

.checklist-item,
.expense-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.checklist-item:last-child,
.expense-item:last-child {
  border-bottom: none;
}
.checklist-item label {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
}
.checklist-item label span.checked {
  text-decoration: line-through;
  color: var(--text-faint);
}
/* 2026-09-01(3차): 핸드오프 문서 기준 mint 색 체크박스 — accent-color로
   네이티브 체크박스를 간단히 물들임(별도 커스텀 렌더링 없이 크로스브라우저
   지원 좋음). */
.checklist-item input[type="checkbox"] {
  width: 17px;
  height: 17px;
  accent-color: var(--accent-teal);
  cursor: pointer;
  flex-shrink: 0;
}
/* 2026-09-01(3차): 핸드오프 문서의 모바일 하단 탭바. TripAgit은 실제로
   "내 여행"/"여행도구" 2개 화면뿐이라(문서의 홈/탐색 4탭은 존재하지 않는
   화면이라 가짜로 만들지 않음), 있는 화면만 반영. 데스크톱에서는 숨김 —
   기존 상단 .nav-links가 그 역할을 함. */
.mobile-tabbar {
  display: none;
}
@media (max-width: 640px) {
  .mobile-tabbar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: 64px;
    background: var(--card);
    border-top: 1px solid var(--border-subtle);
    z-index: 60;
  }
  .mobile-tabbar a {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    font-size: 11px;
    color: var(--text-faint);
  }
  .mobile-tabbar a .icon-inline { margin-right: 0; color: var(--text-faint); }
  .mobile-tabbar a.active { color: var(--brand); font-weight: 600; }
  .mobile-tabbar a.active .icon-inline { color: var(--brand); }
  .container { padding-bottom: 80px; }
}

/* trip.html 전용 모바일 하단 탭바 — 일정/지출/체크/바우처/기타 5개.
   사이트 전역 .mobile-tabbar(위)와 시각적으로 완전히 동일한 패턴을 쓰되,
   저건 페이지 이동용 <a>이고 이건 탭 전환용 <button>이라 별도 클래스로 둠.
   ≤860px에서만(레일이 숨는 지점과 동일) 보이고, 스크롤과 무관하게
   position:fixed로 고정. */
.trip-bottom-tabbar {
  display: none;
}
@media (max-width: 860px) {
  .trip-bottom-tabbar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: 64px;
    background: var(--card);
    border-top: 1px solid var(--border-subtle);
    z-index: 60;
  }
  .trip-bottom-tabbar button {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    font-size: 11px;
    color: var(--text-faint);
    background: none;
    border: none;
    cursor: pointer;
  }
  .trip-bottom-tabbar button .tab-icon { color: var(--text-faint); }
  .trip-bottom-tabbar button.active { color: var(--brand); font-weight: 600; }
  .trip-bottom-tabbar button.active .tab-icon { color: var(--brand); }
}


/* 2026-09-01: 이모지 대신 쓰는 라인 아이콘 세트(js/lib/icons.js) 공용 스타일.
   아이콘 자체엔 색을 안 주고 currentColor로 부모 색을 그대로 물려받게 해서,
   .app-rail-btn.active처럼 색이 바뀌는 상태에서도 별도 처리 없이 같이 바뀐다.
   .icon은 어디 있든(버튼 안, 탭 안, 빈 상태 안) 기본 16px — 더 큰 자리가
   필요하면(빈 상태 큰 아이콘 등) 해당 컨테이너에서 .icon 크기만 오버라이드. */
.tab-icon,
.icon-inline {
  display: inline-flex;
  flex-shrink: 0;
  vertical-align: -3px;
}
/* .app-rail-btn처럼 이미 flex+gap인 부모 안에서는 아이콘 자체 마진이 필요 없고,
   <strong>/.label처럼 flex가 아닌 곳에서만 아이콘-텍스트 간격이 필요하다. */
.icon-inline {
  margin-right: 6px;
}
/* .app-rail-btn/.app-header-mobile-nav처럼 아이콘 하나만 있거나 아이콘+글자가
   가로가 아니라 세로로 쌓이는 곳에서는 이 margin-right가 왼쪽으로 3px씩
   밀어버려서 아이콘이 버튼 중앙에서 어긋나 보임(실측으로 발견) — 없앰. */
.app-rail-btn .icon-inline,
.app-header-mobile-nav .icon-inline {
  margin-right: 0;
}
/* 후속 배치(2026-09-14) 2번: 위와 똑같은 함정이 모바일 하단 액션바의
   지도/코멘트 아이콘 전용 버튼(.mobile-action-icon, 아이콘 하나만 있고
   글자가 없음)에도 있었다 — 실측으로 재현: 이 margin-right가 가운데
   정렬된 flex 박스 안에서 아이콘을 왼쪽으로 3px씩 밀어 중앙에서 어긋나
   보이게 함. */
.mobile-action-icon .icon-inline {
  margin-right: 0;
}
.icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  vertical-align: -3px;
}
.top-tab.active {
  background: transparent;
  color: var(--text);
  font-weight: 600;
  box-shadow: none;
  border-bottom-color: var(--brand);
}
.tab-panel { display: none; }
.tab-panel.active { display: block; }

.card-sub { font-size: 12px; color: var(--text-muted); margin-bottom: 14px; }

/* 관리자 페이지(admin.html, 2026-09-14 신규) — .card를 그대로 재사용하고
   이 표/목록/배지 스타일만 새로 추가. 다른 페이지에서 쓰는 클래스가
   없어서(전용 표/뱃지 스타일 자체가 이 코드베이스에 없었음) 최소한으로 신설. */
.admin-topbar-user { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin-bottom: 16px; }
.admin-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.admin-table th, .admin-table td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border-faint); }
.admin-table th { color: var(--text-muted); font-weight: 600; font-size: 12px; }
.admin-list { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.admin-row { padding: 12px; border: 1px solid var(--border-faint); border-radius: var(--radius-sm); background: var(--bg-sunken); }
.admin-row-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 12px; margin-bottom: 6px; }
.admin-row-body { font-size: 14px; white-space: pre-wrap; overflow-wrap: anywhere; }
.admin-badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px; background: var(--brand-soft); color: var(--brand-soft-text); font-size: 11px; font-weight: 600; }
.admin-gate { max-width: 420px; margin: 40px auto; text-align: center; }

.summary-card .label { font-size: 13px; color: var(--text-muted); margin-bottom: 8px; }
.summary-card .big-number { font-size: 24px; font-weight: 700; font-variant-numeric: tabular-nums; margin-bottom: 8px; }
.summary-card .big-number .sub { font-size: 13px; font-weight: 500; color: var(--text-muted); }

.progress-track { height: 8px; border-radius: 999px; background: var(--border); overflow: hidden; }
.progress-fill { height: 100%; border-radius: 999px; background: var(--brand); transition: width 0.3s ease; }
.progress-fill.over { background: var(--danger); }
.progress-caption { font-size: 12px; color: var(--text-muted); margin-top: 6px; display: flex; justify-content: space-between; gap: 10px; }

.add-form { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 8px; }
.field-row { display: flex; gap: 8px; flex-wrap: wrap; }
.field-row input, .field-row select { flex: 1; min-width: 90px; }
/* T1(2026-09-04): 메모를 항목명 뒤로 옮기면서 추가 버튼이 자기 행에 혼자
   남게 됨 — 기본 justify-content(flex-start)면 왼쪽에 붙어버려서 우측 정렬 */
.expense-add-row { justify-content: flex-end; }

/* 체크리스트: 카테고리별 2단 카드 그리드 (2026-08-31, "12개밖에 없냐"는
   피드백으로 32개/6개 카테고리로 확장하면서 함께 도입) */
.checklist-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 640px) { .checklist-grid { grid-template-columns: 1fr; }
}
/* 2026-09-01(3차): 핸드오프 문서의 세그먼트 컨트롤(전체/남은 항목,
   리스트/타임라인 등에서 재사용하는 토글 UI) */
.segment {
  display: inline-flex;
  background: var(--bg-sunken);
  border-radius: var(--radius);
  padding: 3px;
  gap: 2px;
}
.segment-btn {
  border: none;
  background: transparent;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
}
.segment-btn.active {
  background: var(--card);
  color: var(--text);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

.cat-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 18px; }
.cat-card h4 { margin: 0 0 8px; font-size: 13.5px; display: flex; align-items: center; gap: 6px; color: var(--text); }
.cat-count { margin-left: auto; font-size: 11px; color: var(--text-muted); font-weight: 500; }

.cat-pill {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 14%, var(--card));
  color: var(--brand);
}

.expense-main, .voucher-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.expense-title, .voucher-title { font-size: 14px; font-weight: 600; }
.expense-sub, .voucher-sub { font-size: 12px; color: var(--text-muted); display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.expense-amount { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mono-num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* 2026-09-04(4차 피드백): "공유 링크/동행자 팝오버 글자가 얇아서 잘 안 보여"
   — 모노스페이스 폰트 + 500 굵기 조합이 11px에서 특히 가늘어 보였음(게다가
   .muted 회색과 같이 쓰이는 경우가 많음). 굵기만 700으로 올림. */
.mono-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.read-only-badge {
  background: var(--bg-sunken);
  color: var(--text-muted);
  padding: 4px 10px;
  border-radius: 999px;
}

/* design_handoff_tripagit_1c §4 8단계: 상단 히어로 배너(옛 .share-cover)를
   없애고 56px 헤더가 제목/기간/장소 수를 대신 담음 — "히어로 배너는
   없앴습니다(56px 헤더가 이미 담습니다)" 원칙. */
.share-trip-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--text-muted);
  flex-wrap: wrap;
}
.share-trip-meta strong { color: var(--text); font-weight: 700; font-size: 14.5px; }

/* 코멘트 작성자 아바타 — 로그인 사용자 표시용 이니셜(§2-3, 실제 계정 하나당
   실제 이니셜만 씀. 이전(익명 시절) 코멘트는 author_id가 없어 흐린 원으로). */
.comment-avatar {
  width: 30px;
  height: 30px;
  border-radius: 999px;
  background: var(--brand);
  color: var(--brand-contrast);
  font-size: 12px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.comment-avatar.is-legacy { background: var(--bg-sunken); color: var(--text-faint); }
.comment-login-gate {
  display: flex;
  align-items: center;
  gap: 13px;
  margin-top: 12px;
  padding: 14px 15px;
  border-top: 1px solid var(--border-subtle);
  background: var(--bg-sunken);
  border-radius: 0 0 14px 14px;
}
.comment-login-gate-icon {
  width: 30px;
  height: 30px;
  border-radius: 999px;
  background: var(--border-faint);
  color: var(--text-faint);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.comment-login-gate-text { flex: 1; min-width: 0; }
.comment-login-gate-title { font-size: 13px; font-weight: 600; margin-bottom: 2px; }
.comment-login-gate-sub { font-size: 11.5px; color: var(--text-faint); }

/* 2026-09-01(3차): 바우처는 핸드오프 문서 기준 카드형(테두리+radius 14)으로,
   비상연락처는 기존처럼 목록형(밑줄 구분)으로 유지 — 문서에 연락처 카드
   스타일이 별도로 없어서 기존 관례를 그대로 씀. */
.voucher-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  margin-bottom: 10px;
}
.voucher-item:last-child { margin-bottom: 0; }
.contact-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.contact-item:last-child { border-bottom: none; }
/* 2026-09-04(4차 피드백 재지적): 이름/연락처를 세로로 쌓지 않고 한 줄에
   나란히 — 카드 제목에 이미 전화 아이콘이 있어서 행마다 또 넣지 않는다. */
.contact-info { display: flex; align-items: baseline; gap: 10px; min-width: 0; flex-wrap: wrap; }
.contact-name { font-size: 14px; font-weight: 600; }
.contact-phone { font-size: 13px; color: var(--text-muted); }
.contact-item-actions { display: flex; align-items: center; gap: 2px; flex: none; }
.contact-item.is-editing { align-items: flex-start; }
.contact-item.is-editing .field-row { gap: 8px; }
.type-icon {
  width: 42px;
  height: 42px;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  flex: none;
  background: var(--brand-soft);
  color: var(--brand);
}

/* 2026-09-02(6차): 체크리스트 화면 우측 요약 사이드바(바우처/비상연락처)용
   압축 버전 — 기존 카드형 .voucher-item/.contact-item보다 작고, 삭제
   버튼·추가폼 없이 참고용으로만 보여준다(실제 관리는 각자의 탭에서). */
.voucher-item-compact {
  padding: 10px;
  margin-bottom: 8px;
  gap: 10px;
}
.voucher-item-compact .voucher-title { font-size: 13px; }
.voucher-item-compact .voucher-sub { font-size: 11px; }
.type-icon-sm { width: 32px; height: 32px; font-size: 14px; }
.contact-item-compact {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 0;
}
.contact-item-compact .voucher-title { font-size: 13px; font-weight: 600; }

/* 지출관리(.grid-2)와 달리 체크리스트 우측 요약은 좁고 고정폭에 가까운
   참고 패널이라 2:1 비율로 — 메인 콘텐츠(체크리스트 카테고리 카드들)가
   화면을 넓게 쓰고, 사이드는 참고용 요약만 담당. */
.side-layout {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 20px;
  align-items: start;
}
.side-layout-side {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.side-layout-side > .card { margin-bottom: 0; }
@media (max-width: 900px) {
  .side-layout { grid-template-columns: 1fr; }
}

/* 2026-09-04(전체 점검): "줄간격이 답답하다"는 지적 — 실측해보니 body/p에
   line-height를 아예 지정한 적이 없어서, 앱 전체에 걸쳐 가장 많이 쓰이는
   보조 설명 문구(.muted, <p> 대부분이 이 클래스 — 61곳)가 브라우저 기본값
   (~1.15)으로 렌더링되고 있었다. 카드 안 두세 줄짜리 설명 문구가 유독
   빽빽해 보였던 원인. 고정 높이 배지/뱃지류는 전부 span/div + flex 중앙
   정렬이라(line-height에 기대지 않음) 이 변경의 영향 밖 — .sched-day-card
   같은 62px 고정 박스는 실측으로 별도 확인함. */
.muted { color: var(--text-muted); font-size: 13px; line-height: 1.6; }
p { line-height: 1.6; }

/* 2026-09-01(2차): 테두리 박스 카드 목록을 얇은 구분선 리스트로 교체 —
   trablog 참고 전면 개편의 대시보드 재구성 일부. */
.trip-list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  row-gap: 10px;
  padding: 16px 4px;
  border: none;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0;
}
.trip-list-item:last-child { border-bottom: none; }

.trip-list-item h3 { margin: 0 0 4px; font-size: 15.5px; font-weight: 700; }

/* 2026-09-01(3차): 핸드오프 문서의 대시보드 여행 카드(2열 그리드, 커버
   이미지 자리 + D-day 배지 + 진행 바). 이미지 자산이 없어서 커버는
   브랜드색 소프트 배경 + 핀 아이콘으로 대체(문서의 스트라이프 플레이스홀더
   대신 지금 아이콘 시스템과 어울리는 형태로). */
/* 2026-09-02(5차): .container 최대폭을 1680px로 넓힌 뒤, 대시보드엔 아직
   스펙의 우측 사이드바(오늘의 할일/동행자 활동/환율 — 실제 데이터 없이는
   못 만드는 것도 있어 이번엔 보류)가 없어서 고정 2열이면 카드가 지나치게
   넓어짐. 사이드바 없이도 화면을 잘 채우도록 auto-fill로 바꿔서 넓은
   화면에선 자연스럽게 3~4열이 되게 함. */
/* 2026-09-02(밀도 개선): auto-fill은 카드가 몇 개 없을 때도 "몇 열이
   들어갈 수 있는가"만큼 빈 트랙을 그대로 유지해서, 카드 3개인데 4열
   자리를 잡아두고 그중 1개 자리만큼 화면 오른쪽이 통째로 비어보이는
   문제가 있었음(실측으로 발견). auto-fit은 빈 트랙을 접어버리고 실제
   있는 카드들에게 그 폭을 재분배해준다 — 카드 개수가 적을 때 자연스럽게
   더 넓게 채워짐. */
.dash-trip-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.dash-status-tabs {
  flex-wrap: wrap;
}
.dash-sort-select {
  flex: none;
  width: auto;
  font-size: 12.5px;
  padding: 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text-muted);
}
.dash-status-tabs .segment-btn span {
  margin-left: 5px;
  font-size: 11.5px;
}
/* 2026-09-03(5단계): 카드 그리드를 버리고 80px 목록 행(.dash-trip-row)을
   그대로 쌓는다 — 컨테이너 id는 renderTripFilterTabs가 그대로 쓰므로 유지. */
.dash-trip-grid { display: block; }
/* T4-2(2026-09-04): 다녀온 여행 4개 이상 접기 토글 — 체크리스트 그룹 헤더의
   chevron 회전 패턴(.expense-group-head-left .icon)과 동일하게 통일. */
.dash-done-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin-top: 6px;
  padding: 10px 4px;
  background: none;
  border: none;
  border-top: 1px solid var(--border);
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
}
.dash-done-toggle .icon { width: 15px; height: 15px; transition: transform 0.15s; }
.dash-done-toggle.expanded .icon { transform: rotate(180deg); }
.dash-done-group[hidden] { display: none; }
#logged-in-view {
  max-width: 1440px;
  margin: 0 auto;
}

/* 2026-09-02(6차): 공유뷰 스펙 스크린샷은 900px 폭의 좁고 가운데 정렬된
   "읽기 전용 문서"에 가까운 레이아웃이라 1100px로 좁혀뒀었는데, 사용자가
   "편집화면(trip.html)처럼 시원시원하게"를 요청(밀도 개선 8차) — 편집
   화면을 1680px까지 넓힌 것과 결이 안 맞는다고 판단해서 이 캡을 없애고
   .container의 1680px을 그대로 씀. 목록 칸도 고정 460px이 아니라 40%
   비율로 바꿔서(편집화면 4:6 비율과 통일) 넓은 화면에서 목록이 상대적으로
   좁아지지 않게 함. */
.trip-layout { grid-template-columns: 40% 1fr; }
/* design_handoff_tripagit_1c §3-4: 사진 대신 실제 좌표로 그리는 루트 도식.
   .dash-trip-cover(대시보드 카드)가 이 안에 이 클래스를 그대로 담아서 씀 —
   나중에 가이드 목록(4e, 11단계)에도 같은 클래스를 재사용할 것. */
/* 2026-09-02(밀도/디자인 개선, 9→10차): 점(장소)+선(경로)만 떠 있는 배경이
   "허전하다"는 지적으로 도트 격자 텍스처를 깔았었는데, 사용자가 "이건
   예뻐 보이지 않는다"고 재피드백 — 기계적인 격자 무늬 대신 한쪽 구석에
   은은하게 번지는 빛 덩어리(glow)를 깔아 공항 라운지/여행 앱들이 흔히
   쓰는 "대기 중인 하늘/노을" 느낌의 은은한 대기감을 줌. 점 배열보다
   훨씬 유기적이고, 카드마다 색조가 다르므로(hueFromId) glow도 자연히
   카드마다 미묘하게 달라짐. 실제 사진처럼 보이지 않는 순수 장식이라
   "없는 데이터를 지어낸다" 원칙 위반은 아님. ::before로 분리한 이유는
   그대로 — 실제 배경(그라디언트)은 JS 인라인 style이라 같은 엘리먼트에
   CSS background-image를 얹으면 shorthand 충돌로 인라인이 이김. */
.route-cover {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.route-cover::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 82% 18%, color-mix(in oklch, var(--brand) 30%, transparent), transparent 55%);
}
.route-cover svg, .route-cover-label { position: relative; z-index: 1; }
.route-cover svg { width: 100%; height: 100%; display: block; }
.route-cover-label { color: var(--brand); opacity: 0.55; }
/* T3(2026-09-04): 사진(Pexels) 대신 나라명/장소 수/D-day 정보 오버레이 —
   w>=200일 때만 그려짐(utils.js routeCoverOverlayHtml). 배경(route-cover)이
   항상 밝은 파스텔 고정색이라 스크림/글자는 테마 토큰이 아니라 고정
   흰색/검정 — 다크모드에서도 이 카드 자체는 안 뒤집히기 때문(랜딩 목업
   프레임과 같은 이유, CLAUDE.md 32차 참고). */
.route-cover-overlay {
  position: absolute;
  z-index: 2;
  inset: auto 0 0 0;
  padding: 10px 12px;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.55), transparent);
  color: #fff;
  text-align: left;
}
.route-cover-overlay-line1 { font-size: 13px; font-weight: 700; margin-bottom: 2px; }
.route-cover-overlay-line2 { font-size: 11.5px; opacity: 0.9; }
/* Phase 1-C C1(2026-09-09): 위키미디어 커먼즈 사진 저작자 표시 — 큰 커버
   (#dash-featured, w>=200)에만 그려진다(utils.js tripCoverHtml).
   2026-09-11: 사진 위에 읽히는 문장을 겹쳐 그리던 걸(반투명 검은 박스 +
   저작자 이름 텍스트) 사진 우하단의 작은 원형 ⓘ 배지로 축소 — CC BY-SA
   저작자 표시 요건은 title 속성(호버/길게 누르기)으로 유지하되, 사진
   위에는 몇 px짜리 아이콘 하나만 남아서 캡션처럼 안 보인다. */
.trip-cover-attribution {
  position: absolute;
  z-index: 2;
  right: 6px;
  bottom: 6px;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  cursor: help;
}
.dash-card-menu-wrap { position: relative; }
.dash-card-menu-btn { padding: 5px 8px; }
.dash-card-menu {
  right: 0;
  left: auto;
  width: 160px;
  padding: 6px;
}
.dash-card-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  background: none;
  border-radius: var(--radius-sm);
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.dash-card-menu-item:hover { background: var(--bg-sunken); }
.dash-card-menu-item.danger { color: var(--danger); }
.dash-trip-title-input {
  display: block;
  width: 100%;
  margin: 0 0 4px;
  padding: 0;
  border: none;
  border-bottom: 1.5px solid var(--brand);
  font-size: 16px;
  font-weight: 700;
  font-family: inherit;
  color: var(--text);
  background: transparent;
}
.dash-trip-title-input:focus { outline: none; }

/* design_handoff_tripagit_1c §2-4/§3-6: 도시 가이드 목록+상세 (11단계) */
.guide-warning-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  margin-bottom: 18px;
  border: 1px solid oklch(0.9 0.06 92);
  border-radius: var(--radius-md, 10px);
  background: oklch(0.98 0.02 92);
  color: oklch(0.42 0.09 78);
  font-size: 12.5px;
  line-height: 1.6;
}
.guide-warning-banner .icon { flex: 0 0 auto; margin-top: 1px; color: oklch(0.5 0.11 78); }
.guide-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
  margin-bottom: 22px;
}
.guide-card {
  display: block;
  /* 2026-09-08: 카드 전체가 클릭 가능한 <a>라 조작 요소 — --border-strong로 */
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--card);
  color: inherit;
}
.guide-card:hover { border-color: var(--brand); }
.guide-card-cover { position: relative; height: 118px; }
.guide-card-city {
  position: absolute;
  left: 12px;
  top: 10px;
  padding: 4px 9px;
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.9);
  color: var(--text-muted);
}
.guide-card-body { padding: 13px 14px 15px; }
/* 2026-09-14(사용자 리포트, 시도했다가 되돌림): "Tokyo 4-Day In-Depth
   Itinerary" 같은 가이드 제목(DB 콘텐츠라 문자열마다 다름)이 좁은 카드
   폭에서 "Itinerary" 한 단어만 다음 줄에 남는 고아 줄이 있었다 —
   `.dash-featured-title`처럼 `text-wrap: pretty`를 넣어봤더니 오히려
   "In-Depth"의 하이픈 자리에서 "In-" / "Depth"로 쪼개버려서(하이픈은
   브라우저가 원래 줄바꿈 가능 지점으로 취급함, pretty가 그 지점을
   골라버림) **합성어가 두 조각 난 것처럼 보이는 더 나쁜 결과**가
   났다(실측). 외로운 "Itinerary" 한 줄보다 깨진 것처럼 보이는 "In-/
   Depth"가 더 어색하다고 판단해 되돌림 — 이 문자열은 관리자가 채우는
   가이드 콘텐츠라 코드에서 임의로 하이픈을 줄바꿈 불가로 바꾸면 다른
   패턴의 제목(예: "3-Day")에서 부작용이 날 수 있어 보류. */
.guide-card-title { font-size: 14.5px; font-weight: 700; line-height: 1.4; margin-bottom: 6px; }
.guide-request-block {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px 20px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--card);
  flex-wrap: wrap;
}
.guide-request-icon {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--bg-sunken);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
/* 2026-09-02(버그 수정): 입력창+버튼 묶음이 flex:0 0 auto(안 줄어듦) +
   입력창 자체는 min-width:200px라, 좁은 화면에서 줄바꿈을 해도 그 묶음
   폭(입력창 200px+버튼)만으로 뷰포트를 넘어서 화면 밖으로 삐져나갔음
   (실측: 375px 화면에 필요한 폭이 훨씬 큼). 모바일에서는 그 줄이 전체
   폭을 쓰고 입력창도 자유롭게 줄어들 수 있게 함. */
@media (max-width: 640px) {
  .guide-request-block > .row {
    flex: 1 1 100%;
    width: 100%;
  }
  .guide-request-block #guide-request-input {
    min-width: 0;
    flex: 1;
  }
}
/* 가이드 전면 개편(2026-09-11) — 국가별 목록 + 도시 허브. 기존 .guide-grid/
   .guide-card는 도시 허브의 "코스 카드" 목록에 그대로 재사용하고, 여기는
   국가 섹션/도시 카드/코스 배지/브레드크럼만 새로 추가한다. */
.guide-country-section { margin-bottom: 34px; }
.guide-country-header {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-subtle);
}
.guide-country-flag { font-size: 22px; line-height: 1; }
/* 이모지 국기(Windows에서 신뢰 못 함, js/lib/utils.js flagIconHtml() 주석
   참고) 대신 쓰는 실제 벡터 국기 — 어디서 쓰든 살짝 둥근 모서리+옅은
   테두리로 통일. */
.flag-icon { border-radius: 2px; vertical-align: middle; box-shadow: 0 0 0 1px var(--border-subtle) inset; }
.guide-country-name { font-size: 17px; font-weight: 700; }
.guide-country-count { color: var(--text-faint); font-size: 12.5px; }
.guide-city-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
}
.guide-city-card {
  display: block;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--card);
  color: inherit;
}
.guide-city-card:hover { border-color: var(--brand); }
.guide-city-cover { position: relative; height: 130px; }
.guide-city-name-badge {
  position: absolute;
  left: 12px;
  bottom: 10px;
  padding: 4px 9px;
  border-radius: 7px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-weight: 700;
  font-size: 13.5px;
}
.guide-city-body { padding: 12px 14px 14px; }
.guide-course-badges { display: flex; flex-wrap: wrap; gap: 6px; }
.guide-course-badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--bg-sunken);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
}
.guide-course-badge:hover { background: var(--brand-soft); color: var(--brand-soft-text); }
.guide-breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 12.5px;
  color: var(--text-faint);
  margin-bottom: 14px;
}
.guide-breadcrumb a { color: var(--text-muted); }
.guide-breadcrumb a:hover { color: var(--brand); }
.guide-city-hero {
  position: relative;
  height: 220px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: 18px;
}
.guide-city-hero img, .guide-city-hero svg { width: 100%; height: 100%; object-fit: cover; }
.guide-city-hero-caption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 16px 18px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.6), transparent);
  color: #fff;
}
.guide-city-hero-caption h1 { margin: 0 0 4px; font-size: 22px; }
.guide-city-intro { max-width: 68ch; margin: 0 0 22px; color: var(--text-secondary); line-height: 1.7; }
.guide-other-course-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 4px;
}
.guide-other-course-link:hover { color: var(--brand); }
@media (max-width: 640px) {
  .guide-city-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
}

.guide-detail-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 0;
  flex-wrap: wrap;
}
.guide-detail-layout {
  display: grid;
  grid-template-columns: 460px 1fr;
  gap: 20px;
  align-items: start;
}
.guide-detail-map .card.map-card { padding: 0; overflow: hidden; }
.guide-day-group { margin-bottom: 22px; }
.guide-day-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  font-size: 15px;
  font-weight: 700;
}
.guide-place-row {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 13px;
  margin-bottom: 8px;
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  background: var(--card);
  cursor: pointer;
}
.guide-place-row.is-selected { border-color: var(--brand); background: var(--brand-soft); }
.guide-place-row.is-missing { cursor: default; color: var(--text-faint); }
.guide-place-check { flex: 0 0 auto; display: flex; }
.guide-place-num {
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: var(--bg-sunken);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  flex: 0 0 auto;
}
.guide-action-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 18px;
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  box-shadow: var(--shadow-md);
  flex-wrap: wrap;
  position: sticky;
  bottom: 16px;
}
@media (max-width: 860px) {
  .guide-detail-layout { grid-template-columns: 1fr; }
  .guide-detail-map .card.map-card #map { height: 260px; }
}

.tabs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.tab {
  min-width: 46px;
  padding: 8px 10px;
  border-radius: var(--radius-md, 10px);
  border: 1px solid var(--border-strong);
  background: var(--card);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  text-align: center;
  line-height: 1.3;
}

.tab.tab-all {
  font-size: 12px;
}

.tab.active {
  background: var(--brand);
  color: var(--brand-contrast);
  border-color: var(--brand);
}

/* design_handoff_tripagit_1c §4 7단계: 다구간 여행의 구간 탭 — 날짜 칩
   위에 한 줄 더 붙어서 날짜 칩 목록을 그 구간 날짜로만 필터한다(day_index
   자체는 여행 전체를 통산, §5 미해결 1번 참고). trip_legs가 없는(단일 도시)
   여행은 tripEditor.js가 이 컨테이너를 비워둬서 :empty로 자동 숨김. */
.leg-tabs {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.leg-tabs:empty { display: none; margin-bottom: 0; }
.leg-tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--card);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
}
.leg-tab-dot { width: 7px; height: 7px; border-radius: 999px; flex: 0 0 auto; }
.leg-tab .mono-num { color: inherit; opacity: 0.75; font-weight: 500; }
.leg-tab.active {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand);
}
/* 2026-09-14(사용자 리포트): 다구간 여행 구간별 날짜 수정 — 칩 안의 작은
   연필 아이콘(클릭 시 부모 칩의 필터 클릭으로 안 번지게 tripSchedule.js에서
   stopPropagation) + 그 옆에 뜨는 팝오버. */
.leg-tab-edit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: none;
  background: none;
  padding: 0;
  margin-left: 2px;
  color: inherit;
  opacity: 0.55;
  cursor: pointer;
  flex: 0 0 auto;
}
.leg-tab-edit:hover { opacity: 1; }
.leg-tab-edit .icon { width: 13px; height: 13px; }
.leg-edit-popover { cursor: default; }

/* ============================================================
   2026-09-03 — design_handoff_tripagit_3 §구현 순서 1단계
   아트보드 2a "일정 탭 골격". 색은 전부 기존 :root 토큰만 참조한다
   (새 토큰 없음). 핵심은 "일정 컬럼이 본문" — 목록을 감싸던 .card
   박스와 카드마다 반복되던 그림자를 걷어내고, 구분선 1px
   (--border-subtle) + 좌측 색상 바 3px만으로 목록을 구성한다.
   ============================================================ */

/* 컬럼 골격: 날짜 탭 / 검색줄 / 요약줄은 고정, .sched-list만 스크롤 */
.sched-col {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  background: var(--card);
}
.sched-col > .leg-tabs { padding: 12px 24px 0; margin-bottom: 0; }

/* ---- 날짜 탭: "Day 1" 라벨 → 요일/날짜/장소 수 3줄 카드 ----
   탭 줄만 보고 "2일차는 7곳인데 5일차는 2곳"이 읽혀야 한다는 게
   이 변경의 목적. chevron은 스크롤 영역 밖에 고정한다. */
.sched-daybar {
  flex: 0 0 auto;
  display: flex;
  gap: 6px;
  align-items: stretch;
  padding: 12px 24px 0;
}
.sched-daybar-scroll {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 6px;
  align-items: stretch;
  overflow-x: auto;
}
/* 2026-09-14(사용자 리포트): 오른쪽으로만 넘기는 chevron이 있고 왼쪽으로
   되돌아가는 chevron이 없었음(공유뷰는 둘 다 아예 없었음) — 이제
   -prev/-next 둘 다 같은 규칙을 공유(선택자만 나눔). */
.sched-daybar-prev,
.sched-daybar-next {
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  padding: 0;
  color: var(--text-faint);
  cursor: pointer;
}
.sched-daybar-prev[hidden],
.sched-daybar-next[hidden] { display: none; }
.sched-daybar-prev:hover,
.sched-daybar-next:hover { color: var(--text); }
.sched-daybar-prev .icon,
.sched-daybar-next .icon { width: 18px; height: 18px; }
.sched-day-card {
  width: 86px;
  flex: 0 0 86px;
  height: 62px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--card);
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.sched-day-card-label { font-size: 12px; color: var(--text-muted); }
.sched-day-card-date {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
}
.sched-day-card-count { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
.sched-day-card.is-all {
  width: 52px;
  flex: 0 0 52px;
  align-items: center;
  justify-content: center;
  padding: 8px 4px;
}
.sched-day-card.is-all .sched-day-card-label { font-size: 11px; font-weight: 600; }
.sched-day-card.is-all .sched-day-card-count { font-size: 10px; }
.sched-day-card.active {
  background: var(--brand);
  border-color: var(--brand);
  box-shadow: var(--shadow-sm);
}
.sched-day-card.active .sched-day-card-date { color: var(--brand-contrast); font-weight: 600; }
.sched-day-card.active .sched-day-card-label,
.sched-day-card.active .sched-day-card-count { color: var(--brand-contrast); opacity: 0.72; }

/* ---- 검색줄: 비슷하게 생긴 검색 박스 두 개 → 입력 하나 + 보조 버튼 둘 ---- */
.sched-search-row {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  padding: 14px 24px 12px;
}
.sched-aux .sched-search-row { padding: 0 0 10px; }
.sched-search-wrap {
  flex: 1;
  min-width: 0;
  height: 38px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg);
}
.sched-search-wrap:focus-within {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
.sched-search-wrap .icon { width: 17px; height: 17px; color: var(--text-faint); flex: none; }
/* "아이콘 + input을 테두리 박스 안에 넣는" 패턴의 이중 패딩 함정 —
   전역 input 패딩이 wrap 패딩과 겹쳐 박스가 의도보다 커진다. 반드시 0. */
.sched-search-wrap input {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 14px;
  color: var(--text);
}
.sched-search-wrap input:focus { outline: none; }
.sched-search-wrap input::placeholder { color: var(--text-faint); }
.sched-search-wrap input:disabled { color: var(--text-disabled); }
.sched-search-kbd {
  margin-left: auto;
  flex: none;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-faint);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 2px 5px;
  background: var(--card);
}
.sched-search-btn {
  height: 38px;
  flex: none;
  padding: 0 11px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--card);
  font-family: inherit;
  font-size: 13px;
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
}
.sched-search-btn .icon { width: 16px; height: 16px; }
.sched-search-btn:hover { border-color: var(--text-faint); }
.sched-search-btn.active { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); }
.sched-search-btn:disabled { color: var(--text-disabled); cursor: default; }
.sched-search-btn:disabled:hover { border-color: var(--border-strong); }

/* 검색 결과 / 주변 명소 — 목록 위 고정 영역이라 길어지면 자체 스크롤 */
.sched-aux {
  flex: 0 0 auto;
  padding: 0 24px;
  max-height: 38vh;
  overflow-y: auto;
}
.sched-aux:empty { display: none; }

/* ---- 요약줄: 날짜 · 장소 수 · 총 이동 · 그 날 지출 · 날씨 ---- */
.sched-summary {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 24px 10px;
  border-bottom: 1px solid var(--border-subtle);
}
.sched-summary:empty { display: none; }
.sched-summary-date { font-size: 15px; font-weight: 600; white-space: nowrap; }
.sched-summary-sep { width: 1px; height: 12px; flex: none; background: var(--border-strong); }
.sched-summary-item { font-size: 13px; color: var(--text-muted); white-space: nowrap; }
.sched-summary-item .mono-num { font-family: var(--font-mono); }
.sched-summary-weather {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  color: var(--text-muted);
  white-space: nowrap;
}
.sched-summary-weather .place { color: var(--text-faint); }
/* "전체" 모드에서 날짜 그룹마다 목록 안에 같은 줄을 그릴 때 */
.sched-summary.is-inline { padding: 0 0 8px; border-bottom: none; }
/* 2026-09-04(전체 점검): trip.html은 날짜 탭 바로 아래에 검색줄(padding-top
   14px)이 있어서 탭↔요약줄 간격이 저절로 생기는데, share.html(공유뷰)은
   검색줄이 없어 탭 바로 밑에 요약줄이 붙어서 실제로 딱 붙어 보였음
   (둘 다 위/아래쪽 padding이 0인 지점끼리 맞닿는 구조) — 공유뷰에서만 위쪽
   여백을 보충. */
#share-summary .sched-summary { padding-top: 14px; }
.sched-summary-slot { flex: 0 0 auto; }
.sched-summary-slot:empty { display: none; }
.day-group + .day-group { margin-top: 26px; }

/* ---- 목록: 이 영역만 스크롤 ---- */
.sched-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 24px 24px;
}
.sched-list-end { padding: 12px 0 0; font-size: 13px; color: var(--text-faint); }

/* 코멘트는 3차 핸드오프상 지도 하단 도킹 바로 가야 하지만 그건 지도
   컬럼 작업이라 1단계 범위 밖 — 지금은 .card 박스만 걷어내고 목록
   끝으로 위계를 낮춰둔다("계획"과 "대화"가 동급으로 안 보이게). */
.sched-comments {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--border-subtle);
}
.sched-comments-title {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
}
.sched-comments-title .icon { width: 15px; height: 15px; }

/* ---- 일정 행: 카드 박스·그림자 없이 구분선 1px로만 나눈다 ----
   [좌측바 3px][번호 26px][시각 54px mono][본문 flex][카테고리+액션] */
.item-row {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 0 14px 2px;
}
.item-connector + .item-row { border-top: 1px solid var(--border-subtle); }
/* 이동시간 행(30px): 좌측 2px 세로선 + "전철 18분 · A → B".
   share.html이 아직 옛 .item-card 구조를 쓰므로 .sched-list 안으로만
   범위를 좁힌다(공유 뷰는 §구현 순서 6단계에서 같이 바꿀 것). */
.sched-list .item-connector {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 30px;
  min-height: 0;
  padding: 0 0 0 6px;
  border-top: 1px solid var(--border-subtle);
  font-size: 13px;
  color: var(--text-faint);
}
.sched-list .item-connector::before {
  content: "";
  position: static;
  width: 2px;
  height: 30px;
  flex: none;
  background: var(--border);
}
.sched-list .item-connector .icon { width: 15px; height: 15px; }
.sched-list .item-connector .mono-num { font-family: var(--font-mono); }
.item-row-bar {
  width: 3px;
  flex: 0 0 3px;
  align-self: stretch;
  border-radius: 2px;
}
/* 번호 원은 지도 마커 번호와 같은 값 — 배경 --text 위 글자는 반드시
   --brand-contrast(다크에서 같이 뒤집힘). #fff를 하드코딩하지 말 것. */
.item-row-num {
  width: 26px;
  flex: 0 0 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--text);
  color: var(--brand-contrast);
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: center;
}
.item-row-time {
  width: 54px;
  flex: 0 0 54px;
  padding-top: 3px;
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 500;
  color: var(--text-secondary);
}
.item-row-time-empty {
  width: 54px;
  flex: 0 0 54px;
  margin-top: 3px;
  padding: 0;
  border: none;
  background: none;
  text-align: left;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-faint);
  cursor: pointer;
}
.item-row-time-empty:hover { color: var(--brand); }
.item-row-body { flex: 1; min-width: 0; }
/* 2026-09-04(2차 피드백): 카테고리를 오른쪽 옆칸의 글자 배지("명소")가
   아니라 제목 앞 아이콘으로, 예약 링크도 옆칸이 아니라 제목 바로 뒤로
   옮김 — 제목 한 줄 안에서 "무엇인지 + 이름 + (있다면) 예약 링크"가
   한눈에 읽히게 함. */
.item-row-title {
  margin: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: -0.005em;
}
.item-row-title-icon {
  display: inline-flex;
  align-items: center;
  flex: none;
  color: var(--text-muted);
}
.item-row-title-icon .icon { width: 16px; height: 16px; }
.item-row-title-text {
  min-width: 0;
  word-break: keep-all;
  text-wrap: pretty;
  cursor: pointer;
}
.item-row-title-text:hover { color: var(--brand); }
/* 2026-09-04(3차 피드백): 세부 주소를 기본 접어두고 이 버튼으로 펼침 —
   회전하는 화살표라 "펼쳐진다"는 의도가 아이콘만으로도 읽힘. */
.item-row-addr-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 20px;
  height: 20px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
}
.item-row-addr-toggle .icon { width: 14px; height: 14px; transition: transform 0.15s; }
.item-row-addr-toggle.is-open .icon { transform: rotate(180deg); }
.item-row-addr-toggle:hover { color: var(--text-muted); }
.item-row-addr {
  margin-top: 3px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-muted);
}
.item-row-memo {
  margin-top: 7px;
  padding-left: 9px;
  border-left: 2px solid var(--border-subtle);
  font-size: 14px;
  line-height: 1.65;
  color: var(--text-secondary);
}
.item-row-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 7px;
  flex: none;
}
/* 2026-09-04(2차 피드백): 카테고리를 옆칸 글자 배지(.item-row-cat)로 두던
   걸 제목 앞 아이콘(.item-row-title-icon)으로 옮기면서 이 클래스는 더 이상
   안 쓴다. */
.item-row-affiliate {
  display: flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  padding: 0 8px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  text-decoration: none;
}
.item-row-affiliate:hover { color: var(--brand); border-color: var(--brand); }
.item-row-affiliate .icon { width: 13px; height: 13px; }
/* Phase 2(2026-09-10): 제휴 링크라는 사실을 툴팁이 아니라 눈에 보이게
   표시(공정위 추천·보증 심사지침, PHASE2.md P2-2) — 무료 Google 지도
   링크에는 안 붙는다(js/lib/utils.js affiliateBookingLinks()의
   isAffiliate 참고). 2026-09-13: 테두리를 없애고 글자만 더 옅게 —
   요건(눈에 보일 것)은 그대로 지키면서 시각적으로는 덜 거슬리게. */
.item-row-affiliate-badge {
  font-size: 9.5px;
  font-weight: 700;
  color: var(--text-faint);
  opacity: 0.75;
  padding: 1px 2px;
  line-height: 1.4;
}

/* Phase 2 P2-1(2026-09-10): 장소 상세 패널(js/widgets/placeDetailPanel.js) —
   .fb-overlay/.fb-modal 셸 재사용, 내용물만 이 클래스들. */
.pd-modal { width: 380px; }
.pd-basic p, .pd-note, .pd-rating, .pd-hours, .pd-website, .pd-phone { margin: 0 0 8px; font-size: 13.5px; line-height: 1.6; }
.pd-address { color: var(--text-secondary); }
.pd-category { font-size: 12.5px; }
.pd-photo { width: 100%; height: 160px; object-fit: cover; border-radius: var(--radius-md); margin: 4px 0 10px; }
.pd-photo-attribution { font-size: 11px; margin: -6px 0 10px; }
.pd-rating { font-weight: 600; }
.pd-hours-closed { color: var(--danger); display: flex; align-items: center; gap: 5px; }
.pd-hours-closed .icon { width: 14px; height: 14px; flex: none; }
.pd-website a { color: var(--brand); }
.pd-actions { margin-top: 12px; }
.pd-actions .btn { display: inline-flex; align-items: center; gap: 6px; }
/* 액션은 hover와 키보드 포커스에서만. 터치 기기는 항상 보임(아래 미디어) */
.item-row-actions {
  display: flex;
  gap: 2px;
  color: var(--text-faint);
  opacity: 0;
  transition: opacity 0.12s;
}
.item-row:hover .item-row-actions,
.item-row:focus-within .item-row-actions { opacity: 1; }
@media (hover: none) {
  .item-row-actions { opacity: 1; }
}
.item-row-action {
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  cursor: pointer;
}
.item-row-action .icon { width: 16px; height: 16px; }
.item-row-action:hover { color: var(--text); }
.item-row-action.is-danger:hover { color: var(--danger); }

/* 2026-09-04(전체 점검): "순서 변경 버튼이 사라졌다"는 리포트 — 데스크톱은
   행 전체가 draggable인데 그걸 알려주는 화면 요소가 없었음. 늘 옅게 보이다가
   hover/드래그 중엔 진해지는 grip으로 "여긴 끌 수 있다"를 알려준다. 모바일은
   ▲▼(.item-order-mobile)를 계속 쓰므로 grip 자체를 숨김. */
.item-row-grip {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  flex: 0 0 14px;
  align-self: stretch;
  color: var(--text-faint);
  cursor: grab;
}
.item-row-grip .icon { width: 14px; height: 14px; }
.item-row:hover .item-row-grip { color: var(--text-muted); }
.item-row-grip:active,
.item-row.dragging .item-row-grip { cursor: grabbing; }
@media (max-width: 860px) {
  .item-row-grip { display: none; }
}
.item-row.dragging { opacity: 0.4; }
.item-row.drag-over { box-shadow: inset 0 2px 0 var(--brand); }
.item-row.presence-editing { background: var(--brand-soft); }
.item-row.editing {
  padding: 14px 12px;
  border-radius: var(--radius-card);
  background: var(--brand-soft);
  border: 1px solid var(--brand);
}

.gantt-empty {
  padding: 10px 4px;
  font-size: 13px;
}
.gantt-empty .icon { margin-right: 4px; vertical-align: -2px; }

/* 2026-09-02(7차, 5단계): design_handoff_tripagit_1c §3-5 타임라인 스트립.
   08–22시로 "정규화"한 고정 축 위에 접힘(38px)/펼침(~110px) 두 상태를
   토글 — 목록 위에 항상 떠 있는 요약 위젯(리스트를 대체하지 않음). */
.timeline-strip {
  margin-bottom: 14px;
  border-radius: var(--radius-md, 10px);
  background: var(--bg-sunken);
}

/* 접힘: 8px 트랙 + 가장 큰 공백 안내. 전체를 눌러서 펼칠 수 있음 */
.timeline-collapsed {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 38px;
  padding: 0 10px;
  cursor: pointer;
}
.timeline-collapsed-track {
  position: relative;
  flex: 1;
  height: 8px;
  background: var(--border-faint, var(--border));
  border-radius: 4px;
  overflow: hidden;
}
.timeline-seg { position: absolute; top: 0; height: 100%; border-radius: 4px; min-width: 2px; }
.timeline-gap-label {
  flex: none;
  font-size: 11px;
  color: var(--text-faint);
  white-space: nowrap;
}

/* 펼침: 시각눈금 + 46px 트랙(일정 블록, 이동시간 6px 바, 빈시간 점선) */
.timeline-expanded { padding: 10px 10px 8px; }
.timeline-axis {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--text-faint, var(--text-muted));
  padding: 0 2px;
  margin-bottom: 6px;
  font-variant-numeric: tabular-nums;
}
.timeline-track {
  position: relative;
  height: 46px;
  border-radius: 6px;
}
.timeline-block {
  position: absolute;
  top: 4px;
  height: 38px;
  border-radius: 6px;
  min-width: 2%;
  overflow: hidden;
  cursor: grab;
  display: flex;
  align-items: center;
  padding: 0 6px;
  box-shadow: var(--shadow-sm);
}
.timeline-block:active,
.timeline-block.dragging { cursor: grabbing; box-shadow: var(--shadow-md); z-index: 2; }
.timeline-block span {
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}
.timeline-travel-bar {
  position: absolute;
  top: 20px;
  height: 6px;
  border-radius: 3px;
  background: var(--text-disabled, var(--border-strong));
}
.timeline-gap-block {
  position: absolute;
  top: 4px;
  height: 38px;
  border: 1px dashed var(--border-dashed);
  border-radius: 6px;
}
.timeline-caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11.5px;
  margin-top: 8px;
}
.timeline-toggle-btn {
  flex: none;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.timeline-toggle-btn:hover { background: var(--border-faint); color: var(--text); }
.timeline-toggle-btn .icon { width: 14px; height: 14px; transform: rotate(90deg); }
.timeline-expanded .timeline-toggle-btn .icon { transform: rotate(-90deg); }

/* 모바일 세로 시간축(§3-5 "가로 리본을 쓰지 마세요") */
.timeline-vertical { padding: 10px; }
.timeline-v-body { position: relative; }
.timeline-v-hours {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 40px;
}
.timeline-v-hour {
  position: absolute;
  left: 0;
  font-size: 10.5px;
  color: var(--text-faint);
  transform: translateY(-50%);
}
.timeline-v-track {
  position: relative;
  margin-left: 48px;
  height: 100%;
}
.timeline-v-block {
  position: absolute;
  left: 0;
  right: 0;
  border-radius: 6px;
  padding: 3px 8px;
  font-size: 11.5px;
  font-weight: 600;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}
/* share.html이 아직 쓰는 예전 일정 카드(테두리 박스형). trip.html은
   2026-09-03(3차 핸드오프 1단계)에 .item-row 구분선 목록으로 바뀌었고,
   공유 뷰는 §구현 순서 6단계에서 같이 옮긴다. */
.item-card {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 11px 12px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  margin-bottom: 0;
  background: var(--card);
}
.item-order-mobile {
  display: flex;
  /* 2026-09-03(4단계): 세로로 쌓으면 375px 화면에서 행 오른쪽 열이 너무
     길어져 본문 폭을 잡아먹는다 — 가로로 눕힘. */
  flex-direction: row;
  align-items: center;
  gap: 3px;
  flex: 0 0 auto;
}
.item-order-mobile .btn {
  padding: 1px 6px;
  font-size: 10px;
  line-height: 1.4;
  border-color: transparent;
  color: var(--text-faint);
}
.item-order-mobile .btn:hover { border-color: var(--border); color: var(--text); }
@media (min-width: 861px) {
  .item-order-mobile { display: none; }
}

/* 2026-09-04(전체 점검): 실측해보니 모바일 일정 행의 ▲▼ 순서변경 버튼이
   23.9x18px, 행 액션 아이콘이 26x26px로 손가락 기준으로는 너무 작았다.
   보이는 크기는 스펙대로 유지해야 하므로(작고 조용한 아이콘이 의도), 대신
   투명한 가상 요소로 실제 누를 수 있는 영역만 세로로 넓힌다. 가로로도 넓히면
   바로 옆 버튼(gap 2~3px)과 히트 영역이 겹쳐서 위/아래 버튼을 서로 잘못
   누르게 되므로 세로만 넓히는 게 중요하다. */
@media (max-width: 860px) {
  .item-order-mobile .btn,
  .item-row-action {
    position: relative;
  }
  .item-order-mobile .btn::after,
  .item-row-action::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 40px;
    transform: translateY(-50%);
  }
}

.item-color-bar {
  width: 4px;
  align-self: stretch;
  border-radius: 999px;
  flex: none;
}

.item-main { flex: 1; min-width: 0; }
.item-meta-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 2px;
}
.item-meta-num {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-faint);
}
.item-meta-time {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
}
.item-meta-category {
  font-size: 11px;
  color: var(--text-faint);
}
.item-card-title {
  font-size: 14.5px;
  font-weight: 600;
  margin: 0 0 2px;
  word-break: keep-all;
}
.item-card-memo {
  font-size: 12px;
  color: var(--text-muted);
}

/* 이동시간 커넥터 — 인접한 두 일정 카드 사이에 자동 계산된 이동 수단·시간·
   거리를 보여준다. "(추정)" 표기는 직선거리 기반 근사치라 반드시 유지. */
.item-connector {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 0 7px 39px;
  min-height: 14px;
  font-size: 11.5px;
  color: var(--text-faint);
  position: relative;
}
.item-connector::before {
  content: "";
  position: absolute;
  left: 13px;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--divider-vertical);
}

/* 인라인 편집 폼(§3-2) — 카드 자체가 그 자리에서 펼쳐짐. 기존 add-item
   폼과 똑같은 select/input/textarea 스타일을 그대로 물려받음. */
.item-edit-form { flex: 1; min-width: 0; }
.item-edit-form select,
.item-edit-form input[type="text"] {
  padding: 6px 8px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  background: var(--card);
  color: var(--text);
}
.item-edit-form textarea {
  width: 100%;
  min-height: 52px;
  padding: 6px 8px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  resize: vertical;
  background: var(--card);
  color: var(--text);
}

.item-title-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.btn-xs {
  padding: 2px 8px;
  font-size: 11px;
  border-radius: 999px;
}
.btn-xs .icon { width: 12px; height: 12px; }

.color-swatches {
  display: flex;
  gap: 8px;
}

.color-swatch {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid transparent;
  padding: 0;
}

.color-swatch.selected {
  /* 하드코딩된 짙은 남색 테두리라 다크모드의 어두운 카드 배경과 거의
     구분이 안 됐음(선택 표시가 안 보이는 문제) — 테마에 따라 뒤집히는
     var(--text)로 교체. */
  border-color: var(--text);
  box-shadow: 0 0 0 2px #fff inset;
}

/* 검색 결과 한 줄 — 정보 + "{날짜}에 담기" 버튼(1클릭 담기, §3-3-2) */
.place-result-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  margin-top: 6px;
  border-radius: var(--radius-sm);
}
.place-result-item:hover { background: var(--bg-sunken); }
.place-result-info { min-width: 0; flex: 1; }
.place-result-info strong { font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.place-result-info .muted { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.place-result-title-row { display: flex; align-items: center; gap: 5px; min-width: 0; }
.place-result-icon { flex: none; display: flex; color: var(--text-muted); }
.place-result-icon .icon { width: 14px; height: 14px; }
.place-result-area-badge {
  flex: none;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-muted);
  background: var(--bg-sunken);
  border: 1px solid var(--border-faint);
  border-radius: 999px;
  padding: 1px 7px;
}

/* §3-3 카테고리 칩(인라인 편집 폼) */
.category-chip-row { display: flex; flex-wrap: wrap; gap: 6px; }
.category-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 11px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card);
  color: var(--text-muted);
  font-size: 12px;
  cursor: pointer;
}
/* 2026-09-02(밀도/일관성 개선): 예전엔 ITEM_CATEGORIES의 이모지(🏨🍽️ 등,
   원래 <select><option>용으로만 만든 값)를 여기서도 그대로 썼는데, 카드
   오른쪽 사진 자리(.item-photo)는 이미 새 라인 아이콘(categoryIcon())을
   쓰고 있어서 "수정" 눌렀을 때 보이는 카테고리 칩만 옛날 이모지로 따로
   놀았음 — 사용자가 실제로 지적. categoryIcon()으로 통일했고, 칩
   크기(12px 텍스트)에 맞춰 아이콘도 살짝 줄임. */
.category-chip .icon { width: 14px; height: 14px; }
.category-chip:hover { border-color: var(--text-faint); }
.category-chip.selected {
  border-color: var(--brand);
  background: var(--brand-soft);
  color: var(--brand-soft-text);
  font-weight: 600;
}

/* time이 null인 카드의 "시간 정하기" 자리(§3-3) — 인라인 편집으로 진입 */
.item-meta-time-empty {
  font-size: 11px;
  color: var(--brand);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* "1클릭 담기" 되돌리기 토스트(§3-3-2) — 기본 .toast는 안내문만이라
   pointer-events:none인데, 이건 버튼이 있어야 해서 켜줌. */
.toast.with-action { pointer-events: auto; display: flex; align-items: center; gap: 12px; }
.toast-undo-btn {
  flex: none;
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: #fff;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  cursor: pointer;
}
.toast-undo-btn:hover { background: rgba(255, 255, 255, 0.15); }

/* 2026-09-02: 스펙의 카드 우측 사진 썸네일(§3-2: 40px) — 실제 장소 사진이
   없어(저작권상 임의 이미지를 못 가져옴) 카테고리 아이콘 플레이스홀더로
   대체. 가짜 사진을 보여주지 않는다는 프로젝트 원칙 유지. */
.item-photo {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  color: var(--text-faint, var(--text-muted));
  display: flex;
  align-items: center;
  justify-content: center;
  /* 카드 내용(메모/주소/제휴 링크 등)이 있으면 카드가 길어지는데, 이
     아이콘 박스를 카드 세로 중앙에 두면(align-self:center) 어느 줄과도
     안 이어진 채 붕 떠 보임 — 사용자 지적. 맨 위 줄(번호·시각·카테고리
     라벨)과 나란한 높이로 붙여서 "카드 앞머리의 썸네일" 느낌이 나게 함. */
  align-self: flex-start;
}
.item-photo .icon { width: 18px; height: 18px; }
.item-actions { display: flex; gap: 6px; align-items: flex-start; flex-wrap: wrap; }

/* 2026-09-01: 지도를 클릭해서 위치를 고르면 그 자리 팝업에 바로 뜨는
   "일정에 추가" 버튼 — 사이드 폼까지 안 가도 한 번의 클릭으로 추가됨. */
/* 2026-09-01(3차): 핸드오프 문서의 "좌하단 장소 카드"(width 300, radius 13,
   map-card 섀도우) 스펙에 맞춰 Mapbox 팝업 컨테이너 자체를 재스타일 —
   기본 흰 삼각형 화살표 팝업 대신 카드형으로. */
.mapboxgl-popup-content {
  border-radius: var(--radius-lg);
  box-shadow: 0 14px 34px -16px rgba(20, 23, 26, 0.4);
  padding: 14px 16px;
  font-family: var(--font-sans);
}
.mapboxgl-popup-tip { display: none; }

.map-add-popup {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 268px;
}
.map-add-popup-title-row { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; }
.map-add-popup-icon { flex: none; display: flex; color: var(--brand); }
.map-add-popup-icon .icon { width: 16px; height: 16px; }
.map-add-popup b { font-size: 14px; font-weight: 700; color: var(--text); }
.map-add-popup-meta {
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.map-add-popup .map-add-btn { justify-content: center; }

/* 검색 결과를 고른 직후 지도에 보여주는 미리보기 표시 — 글자 없이 펄스 링만 */
.map-pin-preview-wrap {
  position: relative;
  width: 20px;
  height: 20px;
}

.map-pin-preview-dot {
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  background: var(--accent-sunset);
  border: 2px solid #fff;
  box-shadow: var(--shadow-sm);
}

.map-pin-preview-pulse {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--accent-sunset);
  opacity: 0.5;
  animation: map-pin-pulse 1.4s ease-out infinite;
}

@keyframes map-pin-pulse {
  0% { transform: scale(0.6); opacity: 0.6; }
  100% { transform: scale(1.8); opacity: 0; }
}

/* 420px는 share.html처럼 목록 옆에 나란히 두는 기본값 — 목록이 지도보다
   훨씬 길어지는 경우가 많아서 지도가 "일부만 보여주다 마는" 것처럼
   답답해 보인다는 지적으로 늘림(trip.html 일정 탭은 이 값을 안 쓰고
   #tab-panel-sched 전용 규칙으로 뷰포트 잔여 높이를 꽉 채움 — 그쪽엔
   영향 없음). */
#map {
  width: 100%;
  height: 600px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  overflow: hidden;
}

/* 2026-09-02(7차, 4단계): design_handoff_tripagit_1c §3-3 — 장소 검색 입구가
   패널 최상단(.add-search-row)으로 옮겨가서 지도 위 검색 오버레이는 삭제.
   앱 셸 다이어그램(§3-1)도 지도를 순수 "map flex:1"로만 그림. */
.map-card { position: relative; }

/* design_handoff_tripagit_1c §2-5: 실시간 커서(Presence, DB 테이블 없음).
   #map의 자식으로 붙어서 map.project()가 주는 픽셀 좌표를 그대로 씀 —
   Mapbox GL이 컨테이너에 이미 position:relative를 걸어두므로 별도 처리 불필요. */
.presence-cursor {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 20;
  transition: transform 80ms linear;
  filter: drop-shadow(0 1px 2px rgba(14, 17, 22, 0.35));
}

/* 2026-09-01(3차): 핸드오프 문서의 지도 오버레이 스펙 — 줌 컨트롤을
   38x38 두 칸 세로 스택, 컨테이너만 radius 10으로 감싸는 모양으로.
   Mapbox 네이티브 컨트롤 클래스를 직접 오버라이드(별도 커스텀 컨트롤을
   새로 만들지 않고 기존 기능은 그대로 두고 겉모양만 맞춤). */
.mapboxgl-ctrl-bottom-right .mapboxgl-ctrl-group {
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 8px 20px -10px rgba(20, 23, 26, 0.4);
  border: none;
}
.mapboxgl-ctrl-group button {
  width: 38px;
  height: 38px;
}
.mapboxgl-ctrl-group button + button {
  border-top: 1px solid var(--border-subtle);
}
/* 모바일 지도는 화면 자체가 작아서(280~420px 높이) 38px 버튼이 상대적으로
   커 보인다는 지적 — 좀 더 작게. */
@media (max-width: 860px) {
  .mapboxgl-ctrl-group button { width: 30px; height: 30px; }
}

/* 모바일에서 지도는 상단에 고정(sticky)되니, 화면을 너무 많이 잡아먹지 않게
   낮춤 — CSS 소스 순서상 위의 기본 #map 규칙보다 뒤에 있어야 이긴다
   (미디어쿼리라고 우선하는 게 아니라 같은 우선순위면 나중 규칙이 이김). */
@media (max-width: 860px) {
  #map { height: 280px; }
}

.widget-tabs {
  display: flex;
  border-bottom: 1px solid var(--border);
  margin-bottom: 14px;
}

.widget-tab {
  padding: 10px 16px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-muted);
  border-bottom: 2px solid transparent;
}

.widget-tab.active {
  color: var(--brand);
  border-bottom-color: var(--brand);
}

.comment-author { font-weight: 700; font-size: 13px; }
.comment-time { color: var(--text-faint); font-size: 11px; }

/* 2026-09-02: 코멘트 "채팅창" 재설계(js/widgets/commentsWidget.js) —
   목록은 고정 높이 안에서 스크롤(대화가 길어져도 카드가 한없이
   늘어나지 않음), 입력창은 그 박스 아래쪽에 항상 붙어있음. 내가 쓴
   코멘트는 오른쪽 정렬 + 브랜드색 말풍선으로 구분해서 실제 메신저처럼
   보이게 함.
   2026-09-04(4차 피드백 재지적): "높이를 재설계하라는 게 아니라, 코멘트가
   하나도 없는데도 넓은 영역을 차지하는 비효율을 줄여달라는 뜻이었다" —
   고정 height:360px라 코멘트가 0개여도 항상 360px를 차지하고 있었음.
   height를 max-height로 바꿔서 상한선(길어지면 여기서 스크롤)은 유지하되,
   실제 콘텐츠가 적으면(코멘트 0~2개) 박스 자체가 그만큼만 짧아지게 함 —
   flex-basis:0%인 .chat-list가 부모에 남는 공간이 없으면 억지로 안 늘어나는
   flexbox 기본 동작을 그대로 이용한 것이라 별도 JS 계산이 필요 없다. */
.chat-box {
  display: flex;
  flex-direction: column;
  max-height: 360px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--card);
}
.chat-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.chat-empty { margin: 6px auto; text-align: center; }
.chat-message { display: flex; gap: 10px; align-items: flex-start; }
.chat-message-mine { flex-direction: row-reverse; }
.chat-bubble-col { min-width: 0; max-width: 78%; display: flex; flex-direction: column; }
.chat-message-mine .chat-bubble-col { align-items: flex-end; }
.chat-bubble-meta { display: flex; align-items: baseline; gap: 7px; margin-bottom: 3px; }
.chat-bubble {
  background: var(--bg-sunken);
  border-radius: 14px;
  padding: 8px 12px;
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}
.chat-message-mine .chat-bubble { background: var(--brand-soft); color: var(--brand-soft-text); }
.chat-composer {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 10px;
  border-top: 1px solid var(--border-subtle);
  background: var(--card);
}
.chat-composer-input { flex: 1; resize: none; max-height: 90px; min-height: 36px; overflow-y: auto; }
.chat-composer-send { flex: 0 0 auto; padding: 8px 10px; }
/* 로그인 게이트는 채팅창 자리를 그대로 대신 차지 — 위 .comment-login-gate
   원래 스타일(border-top/radius)이 카드 하단에 붙는 모양을 전제해서
   만들어졌던 걸 그대로 재사용. */
.chat-composer .comment-login-gate { flex: 1; margin-top: 0; border-top: none; border-radius: 0; }

.share-box {
  display: flex;
  gap: 8px;
  align-items: center;
  background: var(--bg);
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 13px;
}

.share-box input { background: var(--card); }

.banner {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  color: var(--warn-text);
  padding: 10px 14px;
  border-radius: 8px;
  font-size: 13px;
  margin-bottom: 20px;
}
.banner .icon-inline, .banner .icon { flex: none; }

/* T6-후속(2026-09-04): 오프라인 스냅샷 읽기 전용 화면(tripEditor.js
   renderOfflineSnapshot) — 지도/편집 없이 목록만. */
.offline-day-group { margin-bottom: 18px; }
.offline-day-group h3 { font-size: 13px; margin: 0 0 6px; color: var(--text-secondary); }
.offline-item-row {
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 6px 0;
  border-bottom: 1px solid var(--border-subtle);
}

/* 2026-09-01(3차): 핸드오프 문서 기준 점선 테두리 빈 상태로 통일. */
.empty-state {
  text-align: center;
  padding: 40px 20px;
  color: var(--text-muted);
  border: 1px dashed var(--border-dashed);
  border-radius: var(--radius-card);
}

.empty-state-icon {
  line-height: 1;
  margin-bottom: 10px;
  opacity: 0.85;
  display: flex;
  justify-content: center;
}
.empty-state-icon .icon { width: 40px; height: 40px; }

/* 두 클래스 다 단일 클래스 셀렉터로만 구성 — .empty-state p 같은 요소+클래스
   결합 셀렉터를 섞으면 #trip-title 세리프 폰트 버그와 같은 우선순위 충돌이
   재발할 수 있어 일부러 피함 (자세한 경위는 CLAUDE.md 참고). */
.empty-state-title {
  font-weight: 600;
  color: var(--text);
  margin: 0 0 4px;
}

.empty-state-sub {
  margin: 0;
}

/* 2026-09-11: 404.html 전용 — 좁은 폭으로 화면 중앙에 띄운다. 이 페이지는
   privacy.html/terms.html과 같은 엄격한 CSP(style-src에 'unsafe-inline'
   없음)를 쓰므로 인라인 style="" 대신 클래스로 뺀다. */
.notfound-wrap {
  max-width: 520px;
  padding-top: min(18vh, 140px);
}
.notfound-wrap .btn {
  margin-top: 14px;
}

/* 2026-09-01: 대시보드 "다음 여행은 어디로 떠나세요?" 검색 중심 히어로 —
   trablog 참고 후 "새 여행 만들기" 버튼 하나뿐이던 걸 검색+빠른 도시
   선택으로 확장. 검색어가 그대로 여행 제목이 되어 trip.html로 넘어간다. */
/* 2026-09-01(3차): 핸드오프 문서의 대시보드 인사말 헤더. */
.dash-date-label {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 6px;
}
.dash-greeting {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.03em;
  margin: 0 0 6px;
  color: var(--text);
}
.dash-sub {
  font-size: 15px;
  color: var(--text-muted);
  margin: 0;
}
.dash-sub b { color: var(--brand); font-weight: 600; }

.dash-hero { text-align: center; }
/* 다구간 여행 만들기 — 처음엔 grid-template-rows 0fr→1fr 트릭을 썼는데,
   이 브라우저 환경에서 닫을 때(1fr→0fr) 트랙이 다시 안 접히는 문제를
   실측으로 확인함(fr 단위 그리드 트랙 애니메이션은 브라우저 지원이
   일관되지 않기로 알려져 있음) — 훨씬 널리 지원되는 max-height 트랜지션
   으로 교체. 정확한 내용물 높이를 몰라도 넉넉한 목표값(600px, 구간을
   웬만큼 추가해도 넘지 않을 값)만 주면 됨 — 실제 높이가 더 작으면 그
   지점에서 트랜지션이 자연스럽게 멈춘다. */
.multi-leg-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
  text-align: left;
}
.multi-leg-panel.open { max-height: 600px; }
.dash-mini-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 0;
  font-size: 13px;
  border-bottom: 1px solid var(--border-subtle);
}
.dash-mini-row:last-child { border-bottom: none; }
.world-map-wrap { position: relative; }
.world-map-svg-slot { line-height: 0; }
.world-map-svg { width: 100%; height: auto; display: block; }
.world-map-svg path[data-cc] {
  fill: var(--bg-sunken);
  stroke: var(--card);
  stroke-width: 0.5;
}
/* "다녀옴"을 원래 --text-faint(회색)로 칠했는데, 빈 대륙 기본색(--bg-sunken)도
   같은 무채색 계열이라 옆에서 보면 거의 구분이 안 된다는 지적 — 아예 다른
   색상(--accent-violet)으로 바꿔서 세 상태(여행중/예정/다녀옴)가 전부 뚜렷한
   색조 차이로 구분되게 함(빈 대륙만 무채색으로 남김). */
.world-map-svg path.wm-done { fill: var(--accent-violet); }
.world-map-svg path.wm-ongoing { fill: var(--accent-teal); }
.world-map-svg path.wm-upcoming { fill: var(--brand); }
.world-map-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-muted);
}
.world-map-legend-item { display: inline-flex; align-items: center; gap: 5px; }
.world-map-legend-item .wm-swatch { width: 9px; height: 9px; border-radius: 2px; background: var(--bg-sunken); }
.world-map-legend-item.wm-done .wm-swatch { background: var(--accent-violet); }
.world-map-legend-item.wm-ongoing .wm-swatch { background: var(--accent-teal); }
.world-map-legend-item.wm-upcoming .wm-swatch { background: var(--brand); }
.world-map-tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--text);
  color: var(--card);
  font-size: 12px;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  z-index: 5;
}
/* 2026-09-14: 여행중+과거방문처럼 한 나라가 상태를 두 개 이상 가지면
   주 상태 아래에 덧붙는 보조 줄 — 주 상태보다 옅게 */
.world-map-tooltip-sub { opacity: 0.75; margin-top: 2px; }

/* 가이드 목록 페이지 세계지도(2026-09-12, 3차 재작업) — 대륙 목록(왼쪽) +
   선택한 대륙 확대 지도(오른쪽) + 나라에 마우스를 올리면(터치는 탭)
   뜨는 정보 패널 구조. 1·2차(전체 지도 하나 + 클릭 좌표 기준 팝오버)가
   "위치가 들쭉날쭉하다"/"작은 나라를 못 누르겠다"는 지적을 받아, 아예
   대륙 단위로 확대해서 보여주는 구조로 바꿨다 — 나라 간 상대 크기 차이가
   훨씬 줄고, 정보 패널도 클릭 좌표가 아니라 항상 같은 고정 자리(지도
   오른쪽 위 모서리)에 뜨므로 위치 계산 자체가 필요 없어졌다.
   js/widgets/worldMapWidget.js의 renderGuideWorldMap() 참고. */
.guide-worldmap { display: flex; gap: 14px; align-items: stretch; }
.guide-worldmap-continents {
  flex: none;
  width: 148px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.guide-worldmap-continent-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 9px 12px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-muted);
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}
.guide-worldmap-continent-btn:hover { background: var(--bg-sunken); color: var(--text); }
.guide-worldmap-continent-btn.is-active {
  background: var(--brand);
  color: var(--brand-contrast);
  font-weight: 700;
}
.guide-worldmap-continent-count {
  font-size: 11px;
  min-width: 18px;
  text-align: center;
  padding: 1px 5px;
  border-radius: 999px;
  background: var(--bg-sunken);
  color: var(--text-muted);
}
.guide-worldmap-continent-btn.is-active .guide-worldmap-continent-count {
  background: rgba(255, 255, 255, 0.25);
  color: inherit;
}
/* 대륙마다 실제 도형의 가로세로 비율이 다르지만(유럽은 넓적, 아시아는
   길쭉…) 지도를 담는 상자 자체의 크기는 항상 고정한다 — 1·2차 재작업 때
   상자 크기를 SVG 콘텐츠 비율에 맞춰 매번 바꿨더니(width:100%;
   height:auto) 대륙을 바꿀 때마다 페이지 전체 높이가 출렁여 "정신
   없다"는 지적을 받았다. aspect-ratio로 상자를 고정하고, 그 안에서
   SVG는 preserveAspectRatio(기본값 xMidYMid meet, JS에서 별도 설정 안
   함)로 레터박스 방식으로 맞춰 넣는다 — 내용물만 대륙마다 다르게
   보이고 바깥 상자는 절대 안 움직인다. */
.guide-worldmap-stage {
  position: relative;
  flex: 1;
  min-width: 0;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-md);
  background: var(--bg-sunken);
  overflow: hidden;
}
.guide-worldmap-stage .world-map-svg-slot { height: 100%; line-height: 0; }
.guide-worldmap-stage .world-map-svg { width: 100%; height: 100%; display: block; }
.world-map-guide-hint { text-align: center; font-size: 12.5px; margin: 8px 0 0; }
.world-map-guide-missing {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin-top: 8px;
}
.world-map-guide-missing-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  font-size: 12px;
  color: var(--text-muted);
  background: var(--bg-sunken);
  border-radius: 999px;
}
.world-map-guide-missing-chip:hover { color: var(--text); background: var(--border-subtle); }

/* 2026-09-13, 5차 재작업 — 나라마다 다른 색(4차, --member-1~5 순환)을
   되돌렸다. 대륙당 나라가 5개를 넘으면 산술적으로 색이 겹치는 쌍이
   반드시 생기고(비둘기집 원리), 동행자 배지용 원색 팔레트를 나라만한
   넓은 면적에 칠하니 "촌스럽다"는 지적도 맞았다. 실제 잘 만든 지도
   (항공 노선도, "방문한 나라" 트래커)는 대부분 강조색 하나 + 라벨
   조합을 쓴다 — 색으로 구분하려 하지 말고 이름표로 구분하게 한다.

   국경선은 vector-effect:non-scaling-stroke로 화면 픽셀 기준 굵기를
   고정한다 — 이게 없으면 SVG 좌표 기준 stroke-width가 대륙마다 다른
   확대 배율을 그대로 타서, 어떤 대륙에서는 굵게 어떤 대륙에서는 가늘게
   보이는 불일치가 실측으로 확인됐다.

   가이드 없는 나라(회색)도 기존엔 테두리가 배경색과 거의 같아서
   (--card 흰색 위에 --card 테두리) 사실상 안 보였다 — 그 결과 가이드
   있는 나라만 "허허벌판에 뚝 떨어진 섬"처럼 보인다는 지적을 받음(대한민국·
   미국 등). 대시보드의 "다녀온 나라" 위젯은 그대로 두고(공유 base 규칙,
   그 화면에선 문제로 지적된 적 없음) 이 위젯 범위에서만 국경선 대비를
   올려 이웃 나라와의 경계가 항상 보이게 한다.
   ⚠️ 2026-09-13, 4차 재작업 — 테두리 대비만으론 "섬처럼 보임"이 안
   고쳐졌다(사용자 재지적). 실측해보니 진짜 원인은 채우기 색 자체였다 —
   `.world-map-svg path[data-cc]`(공용 base 규칙)의 기본 채우기가
   `var(--bg-sunken)`인데, 이 위젯을 담는 `.guide-worldmap-stage`의
   배경색도 똑같이 `var(--bg-sunken)`다(getComputedStyle로 둘 다
   rgb(244,245,247)임을 확인) — 즉 비활성국은 "칠해져 있지만 배경과
   완전히 같은 색이라 실제로는 안 보이는" 상태였다. 0.9px 테두리 선
   하나만으로는 "여기 나라가 있다"는 느낌을 주기에 부족했던 것 — 채우기
   자체를 배경과 뚜렷이 다른 회색(--border-dashed, 배경보다 확실히
   어둡다)으로 바꿔서 이제 비활성국도 "칠해진 하나의 나라 모양"으로
   또렷이 보인다(활성국의 브랜드색과는 여전히 확연히 구분됨). */
.guide-worldmap-stage .world-map-svg path[data-cc] {
  fill: var(--border-dashed);
  stroke: var(--border-subtle);
  stroke-width: 0.9;
  vector-effect: non-scaling-stroke;
}
/* 9차 재작업 — 대륙 소속과 안 맞는 해외 영토 조각(프랑스령 기아나 등,
   위 renderGuideWorldMap()의 exclave 분리 로직 참고)을 원래 <path>에서
   떼어내 별도로 그리는 자리 — 비활성국과 완전히 같은 모양으로 그려서
   "그냥 배경 지도의 일부"처럼 보이게 하고, 클릭/호버 대상이 아니므로
   pointer-events도 꺼둔다. */
.guide-worldmap-stage .world-map-svg path.wm-guide-exclave {
  fill: var(--border-dashed);
  stroke: var(--border-subtle);
  stroke-width: 0.9;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}
/* .guide-worldmap-stage 접두어까지 붙여 위 국경선 대비 규칙과 명시도를
   맞추고(둘 다 클래스 2개+속성/원소 1개), 소스 순서상 이 규칙이 나중에
   와서 이겨야 활성국이 회색 국경선이 아니라 원래 의도한 흰 국경선으로
   보인다 — 명시도가 낮으면(원래처럼 .world-map-svg path.wm-guide-active
   만 쓰면) 위 규칙에 밀려 활성국도 회색 국경선이 돼버린다(실제로 이
   버그를 만들 뻔해서 여기 적어둠). */
.guide-worldmap-stage .world-map-svg path.wm-guide-active {
  fill: var(--brand);
  cursor: pointer;
  stroke: var(--card);
  stroke-width: 1;
  transition: filter 0.12s ease;
  /* ⚠️ 2026-09-13, 10차 재작업 — outline:none을 :hover/:focus-visible
     상태에만 걸어뒀었는데, 사용자가 나라를 클릭하면 "검은 박스 또는
     노란 박스"가 뜬다고 재지적 — 실측(getComputedStyle)해보니 클릭이
     이 <path>에 실제로 포커스를 주고(SVG 요소에 tabindex를 줬으므로
     클릭도 포커스 이동을 유발함) `:focus`는 참이 되지만 `:focus-visible`
     은 거짓인 상황이 있었다(브라우저별로 마우스 클릭을 focus-visible로
     간주하는 기준이 다르다 — 이 세션의 크롬에서는 거짓이었지만 다른
     브라우저/버전에서는 다를 수 있고, 그 경우 여기 안 걸린 기본 포커스
     테두리가 브라우저 기본값(검은 실선이나 시스템 강조색인 노란 점선
     등)으로 그대로 그려진다). 상태 무관하게 이 규칙 자체에 outline:none을
     박아서 어떤 브라우저의 어떤 포커스 판정 기준을 타든 항상 꺼지게 한다
     — 키보드 사용자를 위한 시각 피드백은 이미 아래 :focus-visible
     규칙의 filter:brightness()가 대신하므로 접근성 손실은 없다. 모바일
     웹킷 브라우저가 탭할 때 기본으로 씌우는 반투명 회색/노란 박스
     (-webkit-tap-highlight-color)도 같은 계열의 "박스" 오인을 만들 수
     있어 같이 꺼둔다. */
  outline: none;
  -webkit-tap-highlight-color: transparent;
}
.world-map-svg path.wm-guide-active:hover,
.world-map-svg path.wm-guide-active:focus-visible {
  filter: brightness(1.15);
  outline: none;
}
/* tiny-hit/selected도 위 국경선 대비 규칙과 명시도를 맞추려고
   .guide-worldmap-stage 접두어를 붙였다 — 안 붙이면 명시도가 낮아서
   (클래스 2개 vs 3개) 국경선 규칙에 밀려 호버해도 테두리가 안 바뀌는
   버그가 난다(activie 규칙과 같은 이유, 바로 위 주석 참고). */
.guide-worldmap-stage .world-map-svg path.wm-guide-tiny-hit { stroke: transparent; stroke-width: 7; }
/* ⚠️ 2026-09-13, 3차 재작업 — 예전엔 선택 표시를 굵은 테두리(stroke)로
   했는데, 테두리는 그 나라의 실제 도형을 그대로 따라 그려지므로 나라
   크기·모양에 따라 테두리 자체의 크기도 완전히 달라진다(작은 나라는
   작은 테두리, 프랑스처럼 큰 나라는 화면을 가로지르는 큰 테두리) — 이게
   사용자에게 "나라를 클릭할 때마다 불규칙한 박스가 생긴다"는 인상을 줬다
   (실제로는 국가 모양 그대로인데, 국경선이 대체로 각진 다각형이라 "박스"
   처럼 보였다). stroke 대신 filter:brightness()로 바꾸면 나라 크기와
   무관하게 항상 같은 "밝기 변화" 하나로만 보여서 이 문제가 구조적으로
   없어진다 — 어떤 나라를 선택해도 시각 효과의 "세기"가 똑같다. */
.guide-worldmap-stage .world-map-svg path.wm-guide-selected {
  filter: brightness(1.22);
}
/* 나라 이름 라벨 — 흰 글자 + 어두운 반투명 외곽선(paint-order로 외곽선을
   글자 뒤에 깔아서 안 뭉개지게 함) 조합은 지도에서 배경이 뭐든(브랜드색
   채우기든, 회색 바다든) 항상 읽히는 표준적인 지도 라벨 기법이다.
   pointer-events:none이라 라벨이 그 아래 나라 도형의 클릭/호버를
   가리지 않는다. font-size는 JS(selectContinent)가 대륙 확대 배율에
   맞춰 매번 다시 계산해서 항상 비슷한 화면 크기로 보이게 한다. */
.guide-worldmap-country-label {
  fill: #fff;
  stroke: rgba(0, 0, 0, 0.55);
  stroke-width: 3px;
  paint-order: stroke;
  vector-effect: non-scaling-stroke;
  font-weight: 700;
  text-anchor: middle;
  dominant-baseline: middle;
  pointer-events: none;
  font-family: inherit;
}
/* 선택된 나라의 라벨을 살짝 키워서(transform-box:fill-box로 텍스트 자기
   자신의 bbox를 기준 삼아 중앙에서 확대 — text-anchor:middle/dominant-
   baseline:middle과 같은 중심점이라 위치가 안 틀어짐) 위 filter:brightness
   와 같이 "선택됨"을 이중으로 표시한다. */
.guide-worldmap-country-label.is-selected {
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(1.25);
}
/* 정보 패널 — 2026-09-13, 5차 재작업. 4차에서 "지도를 가린다"는 지적에
   지도 아래 일반 블록으로 뺐었는데, 사용자가 다시 지도 위(나라 옆)에
   붙는 쪽을 선호한다고 재지적 — 대신 "나라마다 크기가 들쭉날쭉해서
   불규칙해 보인다"는 지적은 여전히 유효하므로, 이번엔 크기 자체를
   완전히 고정한다(JS positionInfoPanel()의 PANEL_W/PANEL_H와 반드시
   같은 값 — 하나만 바꾸면 위치 계산이 어긋난다). 도시가 패널 높이보다
   많으면 본문(body)만 내부 스크롤 — 패널 자체의 바깥 크기는 절대 안
   변한다. 위치(left/top)는 JS가 나라 옆으로 매번 계산해서 인라인
   style로 주므로 여기서는 크기·모양만 정의. */
.guide-worldmap-info {
  position: absolute;
  width: 190px;
  height: 190px;
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 10px;
  z-index: 5;
  animation: world-map-info-in 0.12s ease;
}
/* ⚠️ 2026-09-13, 9차 재작업 — 위 규칙에서 display:flex를 직접 줘버려서
   브라우저 기본 `[hidden] { display:none }` 규칙과 명시도가 같아지고
   (둘 다 (0,1,0)), 소스 순서상 이 author 규칙이 이겨서 `.hidden = true`로
   꺼도 실제로는 계속 flex로 보이는 심각한 버그가 있었다(실측 확인 —
   대륙을 바꿔도 JS의 hidden 프로퍼티는 true가 되는데 화면에는 이전
   나라 패널이 그대로 남아 있었음, "대륙을 바꿔도 패널이 안 사라진다"는
   사용자 리포트의 진짜 원인 중 하나였다). `[hidden]`에 명시도를 더 준
   규칙을 따로 둬서 확실히 이기게 한다. */
.guide-worldmap-info[hidden] {
  display: none;
}
@keyframes world-map-info-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.guide-worldmap-info-header {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
  font-weight: 700;
  font-size: 13.5px;
  padding-bottom: 8px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border-subtle);
}
.guide-worldmap-info-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
/* ⚠️ 2026-09-13, 10차 재작업(1차 시도: 세로로 쌓기 → 2차 시도로 교체) —
   도시명+기간을 한 줄에 나란히 뒀더니 패널 폭(190px)이 좁아서 각자의
   남은 공간 안에서 줄바꿈이 일어나 세로 정렬이 안 맞았다("2줄이 되는
   경우가 많고 정렬도 안 맞음" 지적). 처음엔 도시명→기간을 세로로 쌓는
   방식으로 고쳤는데, 이러면 한 줄이 두 줄이 되어 패널 전체 높이가
   커져야 했다(4개 도시 기준 138px→183px, 스크롤이 다시 필요해짐) — 더
   나은 방법은 "세로로 쌓기"가 아니라 "한 줄 안에서 절대 안 넘치게"다.
   각 span에 white-space:nowrap+text-overflow:ellipsis를 걸어서 폭이
   부족하면 줄바꿈 대신 말줄임표로 자르게 하고, flex-shrink를 다르게
   줘서(도시명은 0 — 어지간해선 안 줄어듦, 기간은 1+min-width:0 — 공간이
   부족하면 기간 쪽부터 먼저 줄어들며 말줄임) 도시명(더 중요한 정보)이
   먼저 보호되게 했다. 이러면 (1) 절대 2번째 줄로 안 넘어가고 (2) 한 줄
   구조라 정렬 문제 자체가 생길 수 없고 (3) 패널 높이도 원래대로 유지된다
   — 한글·영문 둘 다 언어와 무관한 레이아웃 규칙이라 그대로 적용됨. */
.guide-worldmap-info-city {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 6px;
  border-radius: var(--radius-sm);
  color: inherit;
}
.guide-worldmap-info-city-name {
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 0;
  max-width: 62%;
}
.guide-worldmap-info-city-duration {
  font-size: 10.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
}
.guide-worldmap-info-city:hover { background: var(--bg-sunken); }

@media (max-width: 640px) {
  /* 모바일은 왼쪽 세로 목록을 둘 폭이 없어서 지도 위 가로 스크롤 칩
     줄로 바꾼다 — 인터랙션(탭으로 대륙 전환)은 동일. */
  .guide-worldmap { flex-direction: column; }
  .guide-worldmap-continents {
    width: auto;
    flex-direction: row;
    overflow-x: auto;
    padding-bottom: 2px;
  }
  .guide-worldmap-continent-btn { flex: none; white-space: nowrap; }
}
.dash-search-row {
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 480px;
  margin: 0 auto;
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  padding: 6px 8px 6px 16px;
  box-shadow: var(--shadow-sm);
}
/* 2026-09-04(4차 피드백): "여행 만들기 버튼의 + 가 잘 안 보여" — 실측해보니
   이 회색(--text-muted)이 검색창 돋보기 아이콘뿐 아니라 바로 옆 파란
   버튼 안의 + 아이콘까지 자손 선택자로 덮어써서, 흰색이어야 할 아이콘이
   버튼과 거의 같은 톤의 회색이 되어 안 보였다(실측: rgb(95,104,116) —
   .btn-primary가 주는 --brand-contrast 흰색이 아니라 이 규칙이 이겼음).
   돋보기 아이콘은 .dash-search-row의 직계 자식이고 + 아이콘은 버튼
   안(손자)이라, 자식결합자(>)로 좁혀서 버튼 안 아이콘은 안 건드리게 함. */
.dash-search-row > .icon-inline { margin-right: 0; color: var(--text-muted); }
.dash-search-row input {
  flex: 1;
  /* "아이콘 in 박스" wrap 패턴 공통 버그 — .add-search-input-wrap input의
     주석 참고. wrap 패딩과 기본 input 패딩이 겹쳐 불필요하게 높아짐. */
  padding: 0;
  border: none;
  outline: none;
  background: transparent;
  font-size: 14px;
  color: var(--text);
}
.dash-chip-row {
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 14px;
}

.leg-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.leg-row .leg-city-input { flex: 1; width: auto; }
.leg-row .leg-date-input { width: 110px; flex: 0 0 110px; cursor: pointer; }
.chip {
  font-size: 12.5px;
  color: var(--text-muted);
  background: transparent;
  border: 1px solid var(--border-strong); /* T2: 클릭 가능한 칩 — 3:1 확보 */
  border-radius: 999px;
  padding: 5px 14px;
  cursor: pointer;
}
.chip:hover { border-color: var(--brand); color: var(--brand); }

/* 2026-09-01: 대시보드 검색으로 여행을 만들면 그 목적지 주변 명소를
   가로 스크롤로 보여주고, 클릭 한 번으로 바로 일정에 추가하는 기능.
   "인기 장소"라고 안 하고 "이 지역 명소"라고 쓴 이유는 CLAUDE.md 참고 —
   Overpass(OSM)에는 진짜 인기도/평점 데이터가 없어서 과장하지 않음. */
.nearby-places-block { margin-bottom: 16px; }
/* 보조 동작(카드의 주제와 같은 무게로 다투면 안 되는 부가 기능)을 위한
   공용 텍스트 링크 버튼 — 테두리 있는 .btn 박스 대신 아이콘+글자만 있는
   가벼운 형태. 원래 "주변 명소 찾기" 하나만을 위한 클래스였는데, 지출
   탭의 "CSV 내보내기"가 카드 제목과 나란히 테두리 있는 버튼으로 있으니
   "이 화면만 패턴이 다르다"는 지적을 받아 같은 스타일을 재사용하는
   일반 클래스로 승격함. */
.card-link-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: none;
  padding: 6px 2px;
  margin-bottom: 10px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
}

.card-link-btn:hover { color: var(--brand); }
#nearby-places-section { margin-bottom: 16px; }
.nearby-places-label {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-muted);
  margin-bottom: 8px;
}
.nearby-places-row {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 6px;
  /* 명소가 많을 때(카드 20개 등) 이 줄 자체가 내용물 폭만큼 옆으로 계속
     늘어나면서 카드 전체/페이지가 오른쪽으로 밀리는 문제를 막기 위한
     방어적 코드 — 데스크톱/모바일 재현은 못 했지만(이미 부모 체인에
     min-width:0이 있어서), 문제가 생기는 조건을 정확히 특정 못 한
     채로 안전장치만 추가해둠. */
  min-width: 0;
  max-width: 100%;
}
.nearby-place-card {
  flex: 0 0 auto;
  width: 140px;
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  padding: 12px;
  cursor: pointer;
  background: var(--card);
  text-align: left;
}
.nearby-place-card:hover { border-color: var(--brand); }
.nearby-place-card .name {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.nearby-place-card .add-hint {
  font-size: 11.5px;
  color: var(--brand);
  display: flex;
  align-items: center;
  gap: 4px;
}

.toast {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: #1f2937;
  color: #fff;
  padding: 10px 18px;
  border-radius: 8px;
  font-size: 13px;
  z-index: 200;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
  /* 원래 그림자가 아예 없었음 — 페이지의 다른 모든 것 위에 뜨는
     요소(z-index:200)라 가장 강한 단계인 --shadow-lg로 새로 추가함. */
  box-shadow: var(--shadow-lg);
}

.toast.show { opacity: 1; }

.destination-result {
  display: flex;
  gap: 12px;
  margin-top: 12px;
}

.destination-result img {
  width: 100px;
  height: 100px;
  object-fit: cover;
  border-radius: 8px;
  flex-shrink: 0;
}

/* 2026-09-13(사용자 리포트): "사진과 내용이 정렬이 안 맞는다" — 진짜 원인은
   <h4>의 브라우저 기본 margin-top(약 21px, 이 위젯 어디에도 리셋이 없었음)이
   사진 상단보다 제목을 그만큼 아래로 밀어내던 것(실측: img top 441.99px vs
   h4 top 463.26px). 제목/설명 블록이 사진과 같은 높이에서 시작하도록
   margin-top만 0으로 리셋 — margin-bottom은 이미 .mb-1/.mb-2 유틸리티가
   맡고 있으므로 그대로 둠. */
.destination-result h4 { margin-top: 0; }

.currency-result {
  font-size: 22px;
  font-weight: 700;
  margin-top: 10px;
  color: var(--brand-dark);
}

/* 2026-08-31 신규 여행도구(세계시간/팁/경비정산) */
.wc-item {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.wc-item:last-child { border-bottom: none; }
.wc-city { flex: 1; font-weight: 600; font-size: 13.5px; }
.wc-time { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 15px; }
.wc-date { font-size: 12px; flex: none; }

/* 2026-09-13: 대륙별 아코디언 — 네이티브 <details>라 열림/닫힘 애니메이션·
   상태 관리가 전부 브라우저 기본 제공, JS는 처음 채워 넣는 마크업만 담당. */
.wc-continent { border: 1px solid var(--border); border-radius: var(--radius-md); margin-bottom: 8px; overflow: hidden; }
.wc-continent-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 14px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  background: var(--bg-sunken);
  list-style: none;
}
.wc-continent-summary::-webkit-details-marker { display: none; }
.wc-continent-summary::before {
  content: "▸";
  margin-right: 8px;
  color: var(--text-faint);
  transition: transform 0.15s ease;
}
.wc-continent[open] .wc-continent-summary::before { transform: rotate(90deg); }
.wc-continent-count {
  margin-left: auto;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-faint);
  background: var(--card);
  border-radius: 999px;
  padding: 1px 8px;
}
.wc-continent-cities { padding: 4px 14px 6px; }

.split-row { align-items: center; margin-bottom: 8px; }
.split-row .split-name { flex: 1.3; }
.split-row .split-amount { flex: 1; }

/* tools.html은 CSP가 style-src 'self'로 인라인 스타일 자체를 막아둔 페이지라
   (외부 의존 없는 독립 페이지 원칙, SECURITY.md 참고), 위젯에서 자잘한 여백을
   주려면 인라인 style= 대신 이런 유틸리티 클래스를 써야 한다. */
.mt-3 { margin-top: 12px; }
.tools-note-list { margin: 8px 0 0; padding-left: 18px; }
.tools-details > summary { cursor: pointer; }
.hr-divider { border: none; border-top: 1px solid var(--border); margin: 16px 0; }
.text-warning { color: var(--text-warning); }
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* 2026-09-01 신규 여행도구(전압/짐무게/비자/짐리스트) — 음식룰렛/여행스타일/
   비행시간/팁 계산기는 T5(2026-09-04)에서 삭제됨 */
.baggage-row {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.baggage-row:last-child { border-bottom: none; }

.visa-disclaimer {
  background: color-mix(in srgb, #b45309 12%, var(--card));
  border: 1px solid color-mix(in srgb, #b45309 35%, var(--border));
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 12.5px;
  color: var(--text);
  margin-bottom: 14px;
  line-height: 1.6;
}
.visa-status { font-size: 15px; font-weight: 600; padding: 10px 0; }
/* 2026-09-08: --positive/--text-warning 토큰으로 흡수(라이트 #15803d/#b45309,
   다크 #16a34a/#e2a13d는 :root 토큰 정의 쪽 참고) — 수동 테마 토글이 이제
   여기도 적용됨. 비자 정보는 틀리면 실제 피해로 이어지는 화면이라 읽히는 게
   특히 중요하다는 원래 판단은 토큰 값 그대로 유지. */
.visa-free { color: var(--positive); }
.visa-eta { color: var(--text-warning); }
.visa-required { color: var(--danger); }
.visa-check { color: var(--text-muted); }

/* ============================================================
   2026-09-03 — design_handoff_tripagit_3 §구현 순서 2단계
   아트보드 2b "빈 상태". 장소가 0곳이면 날짜 탭·목록·지도 대신
   질문 하나 + 자동 포커스 검색창 + 출구 3개를 보여준다.
   색은 전부 기존 :root 토큰(새 토큰 없음).
   ============================================================ */
.sched-empty {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 40px 56px;
  background: var(--card);
}
.sched-empty[hidden] { display: none; }
.sched-col[hidden] { display: none; }

.sched-empty-title {
  margin: 0;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.4;
  word-break: keep-all;
}
.sched-empty-lead {
  margin: 8px 0 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--text-muted);
  word-break: keep-all;
  text-wrap: pretty;
}

/* 자동 포커스되는 48px 검색창 — 커서가 이미 들어가 있어야 타이핑만 하면
   된다. 포커스 링은 다른 입력과 같은 3px --brand-soft. */
.sched-empty-search {
  margin-top: 24px;
  height: 48px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  border: 1px solid var(--brand);
  border-radius: 10px;
  background: var(--card);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
.sched-empty-search .icon { width: 19px; height: 19px; color: var(--brand); flex: none; }
/* "아이콘 in 박스" 이중 패딩 함정 — 안쪽 input은 반드시 padding:0 */
.sched-empty-search input {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: none;
  background: none;
  outline: none;
  font-family: inherit;
  font-size: 15px;
  color: var(--text);
}
.sched-empty-search input::placeholder { color: var(--text-disabled); }
.sched-empty-results:not(:empty) { margin-top: 12px; }

.sched-empty-chips {
  margin-top: 14px;
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
}
.sched-empty-chip {
  height: 32px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: 16px;
  background: var(--card);
  font-family: inherit;
  font-size: 13px;
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
}
.sched-empty-chip:hover { border-color: var(--brand); color: var(--brand); }

/* 검색이 막힌 사람을 위한 출구 3개 — 셋 다 이미 있는 기능이다 */
.sched-empty-outs {
  margin-top: 36px;
  padding-top: 28px;
  border-top: 1px solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.sched-empty-outs-label { font-size: 13px; font-weight: 600; color: var(--text-muted); }
.sched-empty-card {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  width: 100%;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--card);
  font-family: inherit;
  text-align: left;
  text-decoration: none;
  color: var(--text);
  cursor: pointer;
}
.sched-empty-card[hidden] { display: none; }
.sched-empty-card:hover { border-color: var(--brand); }
.sched-empty-card-icon { flex: 0 0 22px; margin-top: 2px; color: var(--brand); }
.sched-empty-card-icon .icon { width: 22px; height: 22px; }
.sched-empty-card-body { flex: 1; min-width: 0; }
.sched-empty-card-title { display: block; font-size: 15px; font-weight: 600; }
.sched-empty-card-sub {
  display: block;
  margin-top: 4px;
  font-size: 14px;
  line-height: 1.65;
  color: var(--text-muted);
  word-break: keep-all;
  text-wrap: pretty;
}
.sched-empty-card-go { flex: 0 0 18px; margin-top: 4px; color: var(--text-disabled); }
.sched-empty-card-go .icon { width: 18px; height: 18px; }

/* 지도 자리 안내면 — 좌표가 0개면 Mapbox 인스턴스를 아예 만들지 않으므로
   (js/pages/tripEditor.js ensureMap 참고) 이 판이 그 자리를 대신한다. */
.map-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--bg-sunken);
}
.map-placeholder[hidden] { display: none; }
#map[hidden] { display: none; }
/* 진짜 지도인 척하지 않는 순수 장식 격자(없는 데이터를 그리는 게 아님) */
.map-placeholder::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(var(--border-faint) 1px, transparent 1px),
    linear-gradient(90deg, var(--border-faint) 1px, transparent 1px);
  background-size: 78px 78px;
}
.map-placeholder-inner {
  position: relative;
  width: 420px;
  max-width: 100%;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.map-placeholder-pin { color: var(--text-disabled); }
.map-placeholder-pin .icon { width: 40px; height: 40px; stroke-width: 1.5; }
.map-placeholder-title { font-size: 16px; font-weight: 600; color: var(--text); word-break: keep-all; }
.map-placeholder-sub {
  margin: 0;
  font-size: 14px;
  line-height: 1.7;
  color: var(--text-secondary);
  word-break: keep-all;
  text-wrap: pretty;
}
.map-placeholder-btn {
  margin-top: 6px;
  height: 40px;
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
}
.map-placeholder-btn:hover { border-color: var(--brand); color: var(--brand); }
.map-placeholder-btn .icon { width: 17px; height: 17px; }
/* 안내면이 지도 카드 안에 겹쳐 뜨려면 카드가 기준 컨테이너여야 한다 */
.card.map-card { position: relative; }

/* 아직 보여줄 게 없는 탭·공유 링크는 낮추되 숨기지 않는다 — 누르면 각
   탭의 빈 상태로 가고, 공유 링크도 원하면 여전히 복사할 수 있다. */
.app-rail-btn.is-dimmed,
.btn.is-dimmed { color: var(--text-disabled); }
.app-rail-btn.is-dimmed .icon,
.btn.is-dimmed .icon { color: var(--text-disabled); }

/* 제목이 비어 있을 때만 뜨는 연필 — "여기를 눌러 이름을 정할 수 있다" */
.trip-title-pencil { flex: none; color: var(--text-faint); }
.trip-title-pencil[hidden] { display: none; }
.trip-title-pencil .icon { width: 16px; height: 16px; }

/* 날짜를 아직 안 정한 상태를 회색 글씨가 아니라 배지로 말한다 */
.app-date-btn.is-unset {
  background: var(--bg-sunken);
  border-color: transparent;
  border-radius: var(--radius-sm);
  font-weight: 600;
  color: var(--text-muted);
}
.app-date-btn.is-unset .mono-num { font-family: var(--font-sans); font-size: 12px; }

@media (max-width: 860px) {
  .sched-empty { padding: 24px 16px 32px; overflow: visible; flex: none; }
  .map-placeholder-inner { width: 100%; }
  .map-placeholder { position: static; min-height: 300px; }
}

/* ============================================================
   2026-09-03 — design_handoff_tripagit_3 §구현 순서 3단계
   되돌리기 토스트 · 이동시간 경고 · 지도 범위 토글.
   색은 전부 기존 :root 토큰(새 토큰 없음).
   ============================================================ */

/* 이동시간 경고(34px) — 시각 차이 대비 이동시간이 80%를 넘는 줄.
   --danger를 그대로 쓰면 흰 배경에서 본문 대비가 4.5:1에 못 미쳐서,
   이 프로젝트가 .btn-danger에서 이미 쓰던 color-mix 방식으로 --text를
   섞어 톤만 눌러준다(다크에서도 --danger/--text가 같이 뒤집혀서 따라옴). */
.sched-list .item-connector.is-tight {
  height: 34px;
  color: color-mix(in oklab, var(--danger), var(--text) 22%);
}
.sched-list .item-connector.is-tight::before {
  height: 34px;
  background: var(--danger);
  opacity: 0.35;
}
.sched-list .item-connector.is-tight .icon {
  width: 15px;
  height: 15px;
  flex: none;
  margin-right: -4px;
}

/* 지도 범위 토글 — 지도 좌상단. 줌(bottom-right)/전체화면(bottom-left)과
   안 겹치는 자리. 세그먼트 컨트롤 모양은 .segment와 같은 결로 맞췄지만,
   지도 위에 떠 있어야 해서 그림자와 배경이 따로 필요하다. */
.map-scope {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  display: flex;
  gap: 2px;
  padding: 3px;
  border-radius: var(--radius-md);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--border);
}
.map-scope[hidden] { display: none; }
.map-scope-btn {
  height: 26px;
  padding: 0 10px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  white-space: nowrap;
  cursor: pointer;
}
.map-scope-btn:hover { color: var(--text); }
.map-scope-btn.active {
  background: var(--brand);
  color: var(--brand-contrast);
}

/* Phase 1-B B4(2026-09-09): 지도가 Mapbox로 폴백됐지만 장소는 Google
   Places로 담긴 경우의 저작권 표기(tripEditor.js updateGoogleAttribution()
   참고) — .map-scope(top-left)와 겹치지 않게 반대쪽, Mapbox 자체 컨트롤
   (NavigationControl bottom-right/FullscreenControl bottom-left)과도
   안 겹치게 top-right에 둔다. */
.map-google-attrib {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
}
.map-google-attrib[hidden] { display: none; }

/* 되돌리기 토스트 — 8초 동안 떠 있고 버튼이 있어야 해서 pointer-events를
   켠다(기본 .toast는 안내문만이라 꺼져 있음). .toast는 사이트 테마와
   무관하게 항상 짙은 배경으로 고정된 컴포넌트라 버튼 색도 흰색 계열 고정. */
.toast .toast-msg { flex: 1; min-width: 0; }

/* ============================================================
   2026-09-03 — design_handoff_tripagit_3 §구현 순서 5단계
   아트보드 3a 대시보드: 카드 그리드 → 가장 가까운 여행 1개 큰 패널 +
   80px 목록 행 + 우측 340px(다녀온 나라 / 여행 도구).
   ============================================================ */
.dash-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 20px;
  align-items: start;
  margin-top: 20px;
}
.dash-main { min-width: 0; }
.dash-side { min-width: 0; }
@media (max-width: 1100px) {
  .dash-layout { grid-template-columns: minmax(0, 1fr); }
}

/* 가장 가까운 여행 하나만 큰 패널로 */
.dash-featured-panel {
  display: flex;
  gap: 20px;
  /* 2026-09-14(사용자 리포트, 2차): margin-top:auto를 없애 내용을 위에서부터
     쌓았더니 이번엔 "왼쪽 내용 전체 높이가 사진(232px)과 밸런스가 안 맞는다"는
     재지적 — stretch 대신 center로 바꿔서, 내용이 사진보다 짧은(가장 흔한)
     경우 그 블록 전체가 사진과 나란히 세로 중앙에 오도록 함. 위/아래에
     공백이 균등하게 나뉘어 "짧게 떠 있는" 느낌 대신 "사진과 무게가 맞는"
     느낌을 준다 — 내용이 사진보다 길면(날씨+할일+2줄 제목 등) 기존과 동일하게
     그 내용 높이가 패널 전체 높이를 정하고 사진이 그 안에서 중앙에 온다. */
  align-items: center;
  padding: 20px;
  margin-bottom: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}
.dash-featured-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.dash-featured-top { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.dash-featured-title {
  margin: 8px 0 0;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  word-break: keep-all;
  text-wrap: pretty;
}
/* 지표 4개 — 세로선으로 구분(문서 스펙) */
.dash-featured-metrics {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.dash-metric { display: flex; flex-direction: column; gap: 2px; position: relative; }
.dash-metric + .dash-metric::before {
  content: "";
  position: absolute;
  left: -9px;
  top: 4px;
  bottom: 4px;
  width: 1px;
  background: var(--border-strong);
}
.dash-metric[hidden] { display: none; }
.dash-metric-label { font-size: 12px; color: var(--text-muted); }
.dash-metric-value { font-size: 17px; font-weight: 600; }
.dash-featured-weather:not(:empty) { margin-top: 14px; font-size: 13px; }
/* 2026-09-14(사용자 리포트): 여행 제목 반복을 없애고 대신 3일치 예보를
   가로로 나란히 — 카드 자체가 그리 넓지 않아 3칸이 자연스럽게 들어간다. */
.dash-weather-days { display: flex; gap: 10px; }
.dash-weather-day { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 8px 4px; background: var(--bg-sunken); border-radius: var(--radius-sm); min-width: 0; }
.dash-weather-day-label { font-size: 11.5px; color: var(--text-muted); font-weight: 600; }
.dash-weather-day-icon { font-size: 20px; line-height: 1; }
.dash-weather-day-temp { font-size: 12.5px; font-weight: 600; }
/* 할 일 제안 한 줄 — items를 날짜별로 세면 나오는 값(신규 데이터 아님) */
.dash-featured-todo {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding: 10px 12px;
  border-radius: var(--radius-md);
  background: var(--brand-soft);
  color: var(--brand-soft-text);
  font-size: 13px;
}
.dash-featured-todo[hidden] { display: none; }
.dash-featured-todo .icon { width: 16px; height: 16px; flex: none; }
.dash-featured-todo .btn { margin-left: auto; flex: none; }
/* 2026-09-14(사용자 리포트): margin-top:auto가 버튼 줄을 지도 높이(232px)에
   맞춰 카드 맨 아래로 강제로 밀어냈다 — 날씨/할 일 제안이 없는(가장 흔한)
   경우 지표 줄과 버튼 사이에 큰 빈 공백이 생겨 "안 맞아떨어진다"는 인상을
   줬다. auto 마진을 없애고 고정 간격만 둬서 내용이 위에서부터 자연스럽게
   쌓이게 함 — 카드가 짧아지면 남는 공백은 버튼 아래(카드 하단)로 옮겨갈
   뿐, 내용과 버튼 사이에 끼는 어색한 빈 줄은 사라진다. */
.dash-featured-actions { display: flex; gap: 8px; margin-top: 16px; }
/* 우측 미니 지도 — Mapbox GL 인스턴스가 아니라 좌표로 그린 SVG 폴리라인.
   후속 배치(2026-09-13) 4번: 실제 커버 사진이 있으면 tripCoverHtml()이
   .route-cover(SVG 폴백) 대신 .trip-cover-wrap(실사진 <img>)을 그리는데,
   그 안의 wrap div/img가 인라인 style="height:100%"를 쓴다(tripCoverHtml()
   자체가 여러 크기 맥락에서 재사용되는 범용 함수라 그렇게 짜여 있음) —
   퍼센트 높이는 조상이 "확정된" 높이를 가져야 계산되는데, 이 앵커
   (.dash-featured-map) 자체엔 높이가 없고 아래 .route-cover 규칙처럼
   SVG 전용 클래스에만 높이가 걸려 있었다. 그 결과 사진 쪽은 이미지가
   실제로 디코딩되어 고유 비율을 알기 전까지 높이가 미확정이었다가, 로드가
   끝나는 순간 최종 높이로 갑자기 스냅되면서 object-fit:cover가 보여주는
   잘린 범위도 같이 바뀐다 — "사진이 한 번 나왔다가 한 번 더 확대되는
   느낌"의 정체. 인라인 height:100%는 CSS 클래스로 못 이기므로(자식을
   직접 겨냥해도 소용없음), 조상인 .dash-featured-map 자체에 높이를 못박아
   퍼센트 높이가 처음부터 확정값으로 계산되게 한다 — .dash-row-thumb(64x48
   행 썸네일)가 이미 이 방식으로 높이를 갖고 있어서 같은 문제가 없었던
   것과 같은 원리(dash-row-thumb { height:48px } 참고). */
.dash-featured-map {
  flex: 0 0 320px;
  width: 320px;
  height: 232px;
  border-radius: var(--radius-card);
  overflow: hidden;
  display: block;
}
@media (max-width: 860px) {
  .dash-featured-panel { flex-direction: column; padding: 16px; }
  .dash-featured-map { flex: none; width: 100%; height: 160px; }
}

/* 나머지 여행 — 80px 목록 행(여행이 20개가 돼도 무너지지 않게) */
.dash-trip-row {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 80px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--border-subtle);
}
.dash-row-thumb {
  flex: 0 0 64px;
  width: 64px;
  height: 48px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  display: block;
}
.dash-row-thumb .route-cover { height: 48px; }
.dash-row-main { flex: 1; min-width: 0; }
.dash-row-title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  word-break: keep-all;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-row-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  font-size: 13px;
  color: var(--text-muted);
  flex-wrap: wrap;
}
.dash-row-sep { width: 1px; height: 11px; background: var(--border-strong); flex: none; }
.dash-row-side { display: flex; align-items: center; gap: 8px; flex: none; }
@media (max-width: 640px) {
  .dash-trip-row { flex-wrap: wrap; }
  .dash-row-side { width: 100%; justify-content: flex-end; }
}

/* 여행 도구 — 행마다 지금 값을 미리 붙인다 */
.dash-tool-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 2px;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text);
  text-decoration: none;
  font-size: 13px;
}
.dash-tool-row:last-child { border-bottom: none; }
.dash-tool-row:hover { color: var(--brand); }
.dash-tool-row .icon { width: 17px; height: 17px; color: var(--text-faint); flex: none; }
.dash-tool-label { flex: 1; min-width: 0; }
.dash-tool-value { color: var(--text-muted); font-size: 12px; white-space: nowrap; }
.tp-step { display: flex; gap: 12px; align-items: flex-start; }
.tp-step-num {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--brand);
  color: var(--brand-contrast);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 13px;
}
.tp-step b { display: block; font-size: 14.5px; margin-bottom: 2px; }
.tp-step p { margin: 0; font-size: 13px; line-height: 1.6; color: var(--text-muted); }

/* ============================================================
   2026-09-03 — design_handoff_tripagit_3 §구현 순서 6단계
   아트보드 4c 공유 뷰: 권한을 상단 한 줄로 말하고, 편집 UI는 아예
   렌더하지 않는다(비활성으로 남기지 않음). 좌측 레일도 없다 —
   공유 뷰는 앱이 아니라 문서라는 걸 구조로 알린다.
   ============================================================ */
.share-topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 40px;
  padding: 6px 16px;
  /* 사이트 테마와 무관하게 항상 짙은 바 — .toast와 같은 결(라이트/다크
     양쪽에서 "이 화면은 남의 여행"이라는 신호가 흔들리지 않게). */
  background: #14161a;
  color: #fff;
  font-size: 13px;
}
.share-topbar[hidden] { display: none; }
.share-topbar-msg { font-weight: 600; }
.share-topbar-sub { color: rgba(255, 255, 255, 0.62); }
.share-topbar-btn {
  margin-left: auto;
  flex: none;
  height: 28px;
  padding: 0 12px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  background: none;
  color: #fff;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.share-topbar-btn:hover { background: rgba(255, 255, 255, 0.14); }
.share-topbar-btn:disabled { opacity: 0.6; cursor: default; }
@media (max-width: 640px) {
  .share-topbar { flex-wrap: wrap; row-gap: 4px; }
  .share-topbar-sub { display: none; }
}

/* 공유 뷰의 일정 컬럼 — trip.html과 같은 .sched-col 부품을 쓴다.
   2026-09-14(사용자 리포트): 예전엔 "페이지 전체가 문서처럼 흐르므로
   목록만 스크롤하는 체인은 풀어준다"고 의도적으로 다르게 설계했는데,
   그 결과 지도 위에서 스크롤하면(페이지 자체가 스크롤되는 컨테이너
   안에 있어 Google Maps의 기본 gestureHandling="auto"가 "cooperative"로
   판정) Ctrl을 눌러야만 확대/축소가 되는 게 오히려 불편하다는 지적 —
   trip.html 편집 화면과 똑같이 지도는 고정, 왼쪽 일정+코멘트만 안 보이는
   스크롤(.no-scrollbar)로 바꾼다(아래 데스크톱 전용 규칙). 모바일은
   화면이 좁아 지도를 고정할 자리가 없으므로 기존처럼 문서 스크롤 유지. */
.share-sched-col {
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 20px;
  padding-bottom: 8px;
}
.share-sched-col .sched-list { flex: none; overflow: visible; }
.share-tabs { margin-bottom: 16px; }
.share-comments-card { margin-bottom: 0; }

@media (min-width: 861px) {
  /* body 직계를 flex 세로 체인으로 — .app-shell(trip.html)과 같은 원리를
     공유 화면 전용 래퍼(.share-shell)에 적용. share-topbar/header는 원래
     콘텐츠 높이 그대로, 나머지(.container)만 남는 뷰포트를 채운다. */
  .share-shell { display: flex; flex-direction: column; height: 100vh; height: 100dvh; overflow: hidden; }
  /* 2026-09-14(사용자 리포트로 발견): .container의 기존 margin:0 auto가
     (다른 페이지에서는 일반 블록 흐름 안에서 가운데 정렬용으로 잘 동작
     하지만) 여기서는 flex-direction:column인 .share-shell의 자식이 되면서
     "cross axis(가로)에 auto 마진이 있으면 stretch를 포기하고 콘텐츠
     기준으로 shrink-to-fit한다"는 flex 스펙 규칙에 걸려, 지도 컬럼이
     779px 폭 컨테이너 안에서 43px로, 그 안의 #map은 1.6px로 찌그러지는
     실측 버그로 이어졌다(이 프로젝트에 이미 기록된 "align-items 없으면
     찌그러진다"와 같은 계열, 이번엔 auto 마진이 원인이라는 점만 다름).
     width:100%를 명시해 auto 마진이 흡수할 여유 공간 자체를 없앤다. */
  .share-shell > .container { flex: 1; min-height: 0; width: 100%; margin: 0; overflow-y: auto; display: flex; flex-direction: column; }
  .share-shell > .container > #content { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  /* 일정 탭이 보일 때만 목록|지도 2분할 체인을 켠다 — 다른 탭
     (#share-panel-extra)은 그냥 이 컨테이너의 overflow-y:auto로 평범하게
     스크롤(카드 스택이라 지도처럼 고정할 이유가 없음). */
  #share-panel-sched:not([hidden]) { display: flex; flex: 1; min-height: 0; align-items: stretch; gap: 0; }
  #share-panel-sched .trip-col-main {
    flex: 1 1 560px;
    max-width: 672px;
    min-width: 0;
    overflow-y: auto;
    padding-right: 20px;
    border-right: 1px solid var(--border-subtle);
  }
  #share-panel-sched .trip-col-map { flex: 1; min-width: 0; display: flex; }
  #share-panel-sched .trip-col-map .card { flex: 1; display: flex; flex-direction: column; margin: 0; }
  #share-panel-sched .trip-col-map #map { flex: 1; height: auto; width: 100%; }
}
@media (min-width: 1280px) {
  #share-panel-sched .trip-col-main { flex: 0 0 672px; }
}

/* 어느 장소에 대화가 붙었는지 목록에서 바로 보이게 하는 개수 배지 */
.item-row-comment-badge {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 22px;
  padding: 0 8px;
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  color: var(--brand-soft-text);
  font-size: 12px;
}
.item-row-comment-badge .icon { width: 13px; height: 13px; }

/* 비로그인 코멘트 입력 — 이름 한 줄 + 내용(가입 없음) */
.chat-anon-composer {
  display: grid;
  grid-template-columns: 110px 1fr auto;
  gap: 8px;
  align-items: end;
  width: 100%;
}
.chat-anon-name {
  height: 38px;
  box-sizing: border-box;
  padding: 0 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--card);
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
}
@media (max-width: 520px) {
  .chat-anon-composer { grid-template-columns: 1fr auto; }
  .chat-anon-name { grid-column: 1 / -1; }
}

/* 2026-09-03(7단계 선행 작업): 헤더 동행자 아바타 스택에서 5명을 넘을 때
   "+N"으로 접는 칸. 색은 사람 색이 아니라 중립 — 특정 사람을 가리키지
   않는다는 걸 색으로도 구분한다. */
.avatar.avatar-more {
  background: var(--bg-sunken);
  color: var(--text-muted);
  font-size: 11px;
}

/* ============================================================
   2026-09-03 — design_handoff_tripagit_3 §구현 순서 7단계
   아트보드 4a 지출 탭: 좌측(유동) + 우측 356px 고정 패널.
   색 역할 분리 — 좌측 3px 바는 사람(결제자), 카테고리는 아이콘,
   색을 카테고리에 쓰는 건 스택 바 하나뿐.
   ============================================================ */
.expense-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 356px;
  gap: 20px;
  align-items: start;
}
.expense-main { min-width: 0; }
.expense-side { min-width: 0; }
@media (max-width: 1100px) {
  .expense-layout { grid-template-columns: minmax(0, 1fr); }
}

.expense-summary-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  /* 2026-09-14(사용자 리포트): 14px가 지출 내역/예산 대비 토글까지 여백을
     불필요하게 넓혀 보였음 — 8px로 살짝 줄임(가로 gap 14px는 그대로,
     세로 여백만 조정). */
  margin-bottom: 8px;
}
.expense-summary-metrics { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.expense-metric { display: flex; flex-direction: column; gap: 2px; }
.expense-metric-label { font-size: 12px; color: var(--text-muted); }
.expense-metric-value { font-size: 17px; font-weight: 600; }
.expense-metric-value.is-big { font-size: 30px; letter-spacing: -0.02em; }
.expense-metric-note { font-size: 12px; color: var(--text-muted); align-self: center; }
.expense-metric-note .icon { width: 14px; height: 14px; vertical-align: -2px; margin-right: 3px; }
.expense-summary-actions { display: flex; align-items: center; gap: 10px; flex: none; }

/* 카테고리 스택 바 10px + 범례 */
.expense-stack {
  display: flex;
  height: 10px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--bg-sunken);
}
.expense-stack:empty { display: none; }
.expense-stack i { display: block; height: 100%; }
/* margin-bottom: 2026-09-04 전체 점검에서 실측 — 범례 바로 아래 지출 목록이
   여백 0으로 붙어 있어서 색상 범례와 첫 날짜 헤더가 한 덩어리로 보였다. */
.expense-legend { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 10px; margin-bottom: 16px; font-size: 12.5px; color: var(--text-secondary); }
.expense-legend-item { display: inline-flex; align-items: center; gap: 5px; }
.expense-legend-item i { width: 8px; height: 8px; border-radius: 2px; flex: none; }

/* 2026-09-14(사용자 리포트, 2차 정정): 처음엔 이 자리에 완전히 새로운
   "일자별 지출 그래프" 섹션을 만들었었는데, 사용자 의도는 "새 그래프가
   아니라 원래 있던 색상 스택 바(.expense-stack)를 지출 내역/예산 대비로
   전환해서 보여달라"는 것이었다 — 새 섹션 대신 그 바로 위에 토글만 추가. */
.expense-stack-head { display: flex; justify-content: flex-end; margin-bottom: 8px; }

/* 2026-09-04(4차 피드백): "입력란과 지출 내역란이 너무 딱 붙어있다" —
   입력 폼을 별도 박스(옅은 배경+테두리)로 감싸고 아래 목록과의 간격을
   늘려서 "여기까지가 입력, 여기부터가 목록"이 한눈에 갈리게 함. */
.expense-add-form {
  margin: 16px 0 20px;
  padding: 14px;
  background: var(--bg-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.expense-add-form[hidden] { display: none; }
.expense-field-label { flex: 0 0 92px; font-size: 13px; color: var(--text-muted); align-self: center; }
.expense-payer-row[hidden],
.expense-split-row[hidden],
.expense-filter-row[hidden] { display: none; }
.expense-cat-row { display: flex; align-items: center; gap: 8px; }
.expense-cat-chips { display: flex; flex-wrap: wrap; gap: 6px; flex: 1; min-width: 0; }
.expense-cat-chip,
.expense-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 12px 0 9px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card);
  font-family: inherit;
  font-size: 13px;
  color: var(--text-secondary);
  cursor: pointer;
}
.expense-cat-chip .icon,
.expense-filter-chip .icon { width: 16px; height: 16px; flex: none; color: var(--cat-ink, var(--text-muted)); }
.expense-cat-chip:hover,
.expense-filter-chip:hover { background: var(--cat-soft, var(--bg-sunken)); }
.expense-cat-chip.selected {
  border-color: var(--cat, var(--brand));
  background: var(--cat-soft, var(--brand-soft));
  color: var(--cat-ink, var(--brand-soft-text));
  font-weight: 600;
  box-shadow: 0 0 0 1px var(--cat, var(--brand));
}
.expense-filter-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 14px; }
.expense-filter-chip { height: 32px; padding: 0 12px; }
.expense-filter-chip .icon { margin-right: -1px; }
.expense-filter-chip .mono-num { font-size: 11.5px; color: var(--text-muted); }
.expense-filter-chip.selected {
  border-color: var(--text);
  background: var(--text);
  color: var(--bg);
  font-weight: 600;
}
.expense-filter-chip.selected .icon,
.expense-filter-chip.selected .mono-num { color: var(--bg); }
/* 카테고리 필터(숙소·교통…)를 고르면 검은색 대신 "지출 추가" 카테고리 칩과 같은 색으로 채운다.
   '전체'·'내가 낸 것'은 data-expense-cat 이 없어 위의 어두운 선택 스타일 그대로다. */
.expense-filter-chip[data-expense-cat].selected {
  border-color: var(--cat, var(--brand));
  background: var(--cat-soft, var(--brand-soft));
  color: var(--cat-ink, var(--brand-soft-text));
  box-shadow: 0 0 0 1px var(--cat, var(--brand));
}
.expense-filter-chip[data-expense-cat].selected .icon,
.expense-filter-chip[data-expense-cat].selected .mono-num { color: var(--cat-ink, var(--brand-soft-text)); }
/* 결제자/분담 안내 문구와 추가·취소 버튼 사이가 너무 벌어져 있던 여백(문단 10px + 폼 gap 8px)을 줄인다. */
.expense-solo-hint { margin: 0; font-size: 12px; line-height: 1.5; }
.expense-solo-hint + .expense-add-row { margin-top: -2px; }
@media (max-width: 640px) {
  /* 좁은 화면: 라벨을 칩 위로 올려 칩이 한 줄 더 넓게 쓰이게 한다. */
  .expense-cat-row { flex-direction: column; align-items: flex-start; gap: 6px; }
  .expense-cat-row .expense-field-label { flex: none; }
}
.expense-split-row { display: flex; align-items: center; gap: 8px; }
.expense-split-chips { display: flex; flex-wrap: wrap; gap: 6px; flex: 1; min-width: 0; }
.expense-split-chip {
  height: 30px;
  padding: 0 12px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card);
  font-family: inherit;
  font-size: 13px;
  color: var(--text-secondary);
  cursor: pointer;
}
.expense-split-chip.selected {
  border-color: var(--brand);
  background: var(--brand-soft);
  color: var(--brand-soft-text);
  font-weight: 600;
}

/* 날짜로 묶고 헤더에 그 날 합계 — 일정 탭 요약줄과 같은 숫자가 같은 자리에 */
.expense-group + .expense-group { margin-top: 18px; }
/* 2026-09-04(4차 피드백): 날짜 헤더를 접기 버튼으로 — 원래 div였던 걸
   button으로 바꾸면서 기본 버튼 스타일(테두리/배경/폰트)을 지운다. */
.expense-group-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 0 0 6px;
  border: none;
  border-bottom: 1px solid var(--border-subtle);
  background: none;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
}
.expense-group-head-left { display: flex; align-items: center; gap: 4px; }
.expense-group-head-left .icon { width: 14px; height: 14px; transition: transform 0.15s; }
.expense-group-head.is-collapsed .expense-group-head-left .icon { transform: rotate(-90deg); }
.expense-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.expense-row.is-settled { opacity: 0.55; }
/* 카테고리 색: 위 색상 막대·범례(catColor)와 같은 색 계열. --cat=막대색, --cat-soft/--cat-ink=아이콘 상자 */
[data-expense-cat="lodging"] { --cat: var(--brand); --cat-soft: var(--brand-soft); --cat-ink: var(--brand-soft-text); }
[data-expense-cat="transport"] { --cat: var(--accent-teal); --cat-soft: var(--accent-teal-soft); --cat-ink: var(--accent-teal-soft-text); }
[data-expense-cat="food"] { --cat: var(--accent-sunset); --cat-soft: var(--accent-sunset-soft); --cat-ink: var(--accent-sunset-soft-text); }
[data-expense-cat="shopping"] { --cat: var(--accent-violet); --cat-soft: var(--accent-violet-soft); --cat-ink: var(--accent-violet-soft-text); }
[data-expense-cat="etc"] { --cat: var(--text-faint); --cat-soft: var(--bg-sunken); --cat-ink: var(--text-muted); }
/* 세로 색 바를 없애고 그만큼 아이콘을 키웠다(제목+메타 두 줄 높이와 같은 42px). */
.expense-row-icon {
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 13px;
  background: var(--cat-soft, var(--bg-sunken));
  color: var(--cat-ink, var(--text-muted));
  display: flex;
  align-items: center;
  justify-content: center;
}
.expense-row-icon .icon { width: 21px; height: 21px; }
.expense-row-body { flex: 1; min-width: 0; }
/* 2026-09-13(사용자 리포트): "메모를 매우 길게 입력하면 화면 밖으로
   돌출된다" — .expense-row-body에 min-width:0은 이미 있어서 flex 자체는
   줄어들 수 있었지만, 정작 안의 제목+메모 텍스트에는 줄바꿈 없는 긴
   문자열(공백 없는 URL 등)을 강제로 꺾어줄 규칙이 없어서 그 문자열
   길이만큼 옆으로 계속 삐져나갈 수 있었다 — overflow-wrap:anywhere로
   필요하면 단어 중간에서도 줄바꿈되게 한다(word-break:keep-all은 한글
   "단어" 단위 줄바꿈만 담당하고 이 문제는 안 막아줌, 둘은 서로 다른 문제).
*/
.expense-row-title { font-size: 14.5px; font-weight: 600; word-break: keep-all; overflow-wrap: anywhere; }
.expense-row-memo-inline { font-weight: 400; color: var(--text-muted); overflow-wrap: anywhere; }
.expense-row-meta { margin-top: 2px; font-size: 12.5px; color: var(--text-muted); }
.expense-row-amounts { display: flex; flex-direction: column; align-items: flex-end; flex: none; }
.expense-row-krw { font-size: 15px; font-weight: 600; }
.expense-row-original { font-size: 12px; color: var(--text-faint); }
.expense-row-edit,
.expense-row-del { flex: none; opacity: 0; transition: opacity 0.12s; }
.expense-row:hover .expense-row-edit,
.expense-row:hover .expense-row-del,
.expense-row:focus-within .expense-row-edit,
.expense-row:focus-within .expense-row-del { opacity: 1; }
@media (hover: none) {
  .expense-row-edit,
  .expense-row-del { opacity: 1; }
}

/* 정산 패널 — "지민이 나에게 ₩224,800" 한 문장이 이 카드의 존재 이유 */
.settle-box {
  padding: 12px;
  border-radius: var(--radius-md);
  background: var(--brand-soft);
  margin-bottom: 12px;
}
.settle-line { display: flex; align-items: center; gap: 8px; }
.settle-line + .settle-line { margin-top: 8px; }
.settle-text { flex: 1; min-width: 0; font-size: 13px; color: var(--brand-soft-text); }
.settle-amount { font-size: 16px; font-weight: 700; color: var(--brand-soft-text); }
.settle-avatar {
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 50%;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.settle-table { display: flex; flex-direction: column; gap: 2px; }
.settle-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  font-size: 13px;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-subtle);
}
.settle-row:last-child { border-bottom: none; }
.settle-row span:nth-child(2) { flex: 1; min-width: 0; }

.budget-nums { display: flex; align-items: baseline; gap: 6px; font-size: 18px; font-weight: 600; }
.budget-nums .muted { font-size: 13px; font-weight: 400; }

/* 2026-09-03(7단계, 아트보드 4d): 체크리스트 항목별 담당자 + 사이드바 담당 카드 */
.check-assignee {
  width: 22px;
  height: 22px;
  flex: none;
  border: none;
  border-radius: 50%;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.check-assignee.is-empty {
  background: none;
  /* 2026-09-08: 클릭 가능한 버튼이라 --border-dashed(장식용, 3:1 미달)가
     아니라 --border-strong을 씀 — 담당자 배정 버튼임을 실측 대비로도 보장. */
  border: 1px dashed var(--border-strong);
  color: var(--text-faint);
  font-weight: 400;
}
.check-assignee.is-empty:hover { border-color: var(--brand); color: var(--brand); }

.assignee-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 6px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.assignee-row:hover { background: var(--bg-sunken); }
.assignee-row.active { background: var(--brand-soft); color: var(--brand-soft-text); font-weight: 600; }
.assignee-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.assignee-avatar {
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 50%;
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.assignee-avatar.is-empty {
  background: var(--bg-sunken);
  color: var(--text-faint);
  /* 같은 이유로 --border-strong(클릭 가능한 담당자 행 안의 아이콘) */
  border: 1px dashed var(--border-strong);
}

/* 2026-09-04(7단계 마무리, 아트보드 4d): 카테고리마다 끝에 "점선 입력 행".
   별도 입력 영역을 여닫지 않고 마지막 행에 바로 타이핑한다 — 준비물은 한
   번에 여러 개를 적는 작업이라 폼을 여닫는 비용이 항목 수만큼 곱해진다. */
.cat-card .cat-add-input {
  border: none;
  background: none;
  padding: 0;
  font-size: 13px;
}
.cat-card .cat-add-input::placeholder { color: var(--text-faint); }
.cat-card .row:has(.cat-add-input) {
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding: 8px 10px;
  border: 1px dashed var(--border-dashed);
  border-radius: var(--radius-sm);
}
.cat-card .row:has(.cat-add-input):focus-within { border-color: var(--brand); border-style: solid; }

/* 목적지 기반 준비물 제안 한 줄 */
.checklist-suggest {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-md);
  background: var(--brand-soft);
  color: var(--brand-soft-text);
  font-size: 13px;
}
.checklist-suggest[hidden] { display: none; }
.checklist-suggest .icon { width: 16px; height: 16px; flex: none; }
.checklist-suggest-text { flex: 1; min-width: 0; word-break: keep-all; }
/* T2: 이 배경(--brand-soft)은 중성 --border-strong과 대비가 2.63:1로 부족했다
   (audit-contrast.js __contrastBorders로 발견) — 이미 브랜드 톤 배경이니
   테두리도 --brand로 맞춰서 3:1을 확보 */
.checklist-suggest .btn { border-color: var(--brand); }

/* 2026-09-04(§결정 2번): 환율 기준 토글 + 기록 시점 환율이 없어 현재 환율로
   대신 계산한 행 표시 */
.rate-mode-segment { margin-bottom: 4px; }
.expense-row-original.is-fallback { color: var(--danger); }

/* 2026-09-04: 뷰어 역할 배너 — 공유 뷰 상단 바와 같은 역할(무엇이 되는지
   한 줄로). 편집 UI 자체는 JS가 DOM에서 제거하므로 CSS로 숨기지 않는다. */
.viewer-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 20px;
  background: var(--brand-soft);
  color: var(--brand-soft-text);
  font-size: 13px;
  font-weight: 500;
  border-bottom: 1px solid var(--border-subtle);
  flex: 0 0 auto;
}
.viewer-banner[hidden] { display: none; }
.viewer-banner .icon { width: 15px; height: 15px; flex: none; }
/* 뷰어에게는 "일정 추가"(모바일 주 버튼)도 의미가 없다 */
.is-viewer .mobile-action-primary { display: none; }
.is-viewer .mobile-action-bar { justify-content: flex-end; }
/* 뷰어에게 보여주는 담당자 배지 — 누를 수 없으므로 커서/hover 없음 */
.check-assignee.is-static { cursor: default; }

/* ==========================================================================
   Phase 1-A(2026-09-08) A1: 피드백 창구 (js/widgets/feedbackWidget.js)
   대부분의 페이지(trip.html 등)에 실제 <footer> 요소가 없어서(풀스크린
   앱 셸 구조), "모든 페이지 푸터에 상시 링크"를 각 페이지 레이아웃을
   건드리지 않고 만족시키려고 위젯이 자체적으로 삽입하는 우측 하단 링크 +
   모달. 색은 전부 기존 토큰만 사용 — 새 다크모드 분기 없음(T2/다크토글
   마무리 원칙 그대로 유지).
   ========================================================================== */
.fb-launcher-btn {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 150;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--card);
  color: var(--text-secondary);
  font-size: 12.5px;
  font-family: inherit;
  cursor: pointer;
  box-shadow: var(--shadow-md);
}
.fb-launcher-btn:hover { color: var(--brand); border-color: var(--brand); }
/* 모바일 하단 고정 탭바(64px, ≤640px/≤860px)와 안 겹치게 띄움 */
@media (max-width: 860px) {
  .fb-launcher-btn { bottom: 80px; }
  /* 2026-09-09 긴급 수정: trip.html "일정" 탭에서는 .trip-bottom-tabbar(64px)
     위에 .mobile-action-bar(장소 추가/지도 보기/코멘트, 패딩 포함 약 68px)가
     하나 더 쌓여서 총 132px를 차지하는데, 의견 보내기 버튼은 탭바 하나만
     계산한 80px에 떠 있어서 그 액션바의 지도/코멘트 버튼을 그대로 덮었다
     (실사용 리포트로 발견). 이 액션바가 실제로 보일 때만(다른 탭에서는
     .is-hidden으로 숨겨짐) 그 위로 한 번 더 띄운다. */
  body:has(#mobile-action-bar:not(.is-hidden)) .fb-launcher-btn { bottom: 148px; }
}

.fb-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(14, 17, 22, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.fb-overlay[hidden] { display: none; }
.fb-modal {
  width: 420px;
  max-width: 100%;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  background: var(--card);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-panel);
  padding: 22px;
}
.fb-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.fb-modal-head h2 { margin: 0; font-size: 17px; }
.fb-close-btn {
  background: none;
  border: none;
  font-size: 22px;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px 6px;
}
.fb-close-btn:hover { color: var(--text); }
.fb-kind-chips { display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.fb-kind-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 7px 12px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--card);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
}
.fb-kind-chip .icon { width: 14px; height: 14px; }
.fb-kind-chip.active { background: var(--brand-soft); border-color: var(--brand); color: var(--brand-soft-text); font-weight: 600; }
.fb-modal textarea#fb-message { resize: vertical; margin-bottom: 4px; }
.fb-char-count { text-align: right; font-size: 11.5px; color: var(--text-faint); margin-bottom: 12px; }
.fb-modal input#fb-contact { margin-bottom: 12px; }
/* 허니팟 — display:none은 봇이 감지하므로 화면 밖으로 밀어내기만 함 */
.fb-honeypot-wrap { position: absolute; left: -9999px; top: -9999px; width: 1px; height: 1px; overflow: hidden; }
.fb-context-detail { margin-bottom: 14px; font-size: 12px; color: var(--text-muted); }
.fb-context-detail summary { cursor: pointer; color: var(--text-secondary); }
.fb-context-detail p { margin: 6px 0 0; word-break: break-all; }
.fb-error { color: var(--danger); font-size: 12.5px; margin: 0 0 10px; }
.fb-error[hidden] { display: none; }
#fb-submit-btn { width: 100%; justify-content: center; }
/* 런치 트랙(2026-09-10) L5: trip.html/share.html처럼 실제 <footer>가 없는
   풀스크린 앱 셸 페이지에서도 법률 문서에 닿을 수 있게 이 모달 하단에 둠
   (js/widgets/feedbackWidget.js 참고 — "모든 페이지 푸터" 요구를 페이지
   레이아웃을 안 건드리고 만족시키는 기존 전략과 같은 자리). */
.fb-legal-links { display: flex; justify-content: center; gap: 16px; margin-top: 14px; font-size: 12px; }
.fb-legal-links a { color: var(--text-faint); }
.fb-legal-links a:hover { color: var(--text-muted); }

/* ==========================================================================
   런치 트랙(2026-09-10) L2/L3: 설정 모달(js/widgets/accountSettingsWidget.js)
   .fb-overlay/.fb-modal 셸을 그대로 쓰고 내용물만 이 클래스들로 구성.
   ========================================================================== */
.acct-section { padding-bottom: 16px; margin-bottom: 16px; border-bottom: 1px solid var(--border-faint); }
.acct-section:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
.acct-section h3 { margin: 0 0 4px; font-size: 14.5px; }
.acct-section p.muted { margin: 0 0 12px; font-size: 13px; line-height: 1.6; }
.acct-confirm { margin-top: 12px; }
.acct-confirm-text { white-space: pre-line; font-size: 13px; line-height: 1.6; color: var(--text-secondary); margin: 0 0 12px; }

/* 7건 후속 배치(2026-09-13) 4번: 로그인 동의 모달(js/widgets/loginConsentModal.js)
   — .fb-overlay/.fb-modal 셸 재사용, 내용물만 이 클래스. 링크 줄(.login-consent-links)은
   2회차(2026-09-13) 5번에서 "링크까지 필요 없다"는 재지적으로 제거했다가,
   3회차(2026-09-14, "스캠 같다" 리포트)에서 신뢰감 보강을 위해 다시 추가함
   — 아래 .login-consent-brand/-body-*/-google-btn/-legal-links 참고. */
.login-consent-actions { justify-content: flex-end; margin-top: 4px; }
.login-consent-brand { display: flex; align-items: center; justify-content: center; gap: 7px; margin-bottom: 14px; }
.login-consent-brand-word { font-weight: 700; font-size: 15px; color: var(--text); }
.login-consent-brand-word span { color: var(--brand); }
.login-consent-body-main { margin: 0 0 6px; font-size: 14px; line-height: 1.6; color: var(--text); }
.login-consent-body-legal { margin: 0 0 16px; font-size: 12.5px; line-height: 1.5; color: var(--text-faint); }
.login-consent-google-btn { display: inline-flex; align-items: center; gap: 8px; }
.login-consent-google-btn svg { flex: none; }
.login-consent-legal-links { display: flex; justify-content: center; gap: 16px; margin-top: 14px; font-size: 12px; }
.login-consent-legal-links a { color: var(--text-faint); }
.login-consent-legal-links a:hover { color: var(--text-muted); }

/* 런치 트랙(2026-09-10) L4: 공유 링크 재발급 트리거 — 눈에 띄면 안 되는
   보조 동작이라 일반 텍스트처럼 보이다가 hover에서만 링크임을 드러냄. */
.link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  font-family: inherit;
  display: block;
}
.link-btn:hover { color: var(--text-secondary); }
.share-reissue-confirm { margin-top: 8px; }

/* 런치 트랙(2026-09-10) L5: privacy.html/terms.html 본문 — .container(1680px)는
   법률 문서를 읽기엔 너무 넓어서 별도 좁은 wrapper를 둔다. */
.legal-content { max-width: 760px; margin: 0 auto; padding-bottom: 60px; }
.legal-content h1 { margin: 4px 0 2px; font-size: 24px; }
.legal-content .legal-meta { color: var(--text-muted); font-size: 13px; margin-bottom: 22px; }
.legal-content section { margin-bottom: 26px; }
.legal-content h2 { font-size: 16.5px; margin: 0 0 10px; }
.legal-content p { font-size: 14px; line-height: 1.75; color: var(--text-secondary); margin: 0 0 10px; }
.legal-content ul, .legal-content ol { padding-left: 20px; margin: 6px 0 10px; }
.legal-content li { font-size: 14px; line-height: 1.7; color: var(--text-secondary); margin-bottom: 4px; }
.legal-content table { width: 100%; border-collapse: collapse; font-size: 13.5px; margin: 10px 0; }
.legal-content th, .legal-content td { text-align: left; padding: 7px 10px; border: 1px solid var(--border-faint); vertical-align: top; }
.legal-content th { background: var(--bg-sunken); font-weight: 600; }
.legal-content a { color: var(--brand); }
[data-lang-block][hidden] { display: none; }

/* 런치 트랙(2026-09-10) L5: 대시보드(로그인)/guides.html/tools.html 공용
   푸터 — index.html 로그아웃 랜딩의 .tp-footer(인라인 스타일, 32차부터
   있던 것)와는 별개로 앱 셸 쪽에서 재사용하는 클래스 기반 버전. */
.app-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 40px;
  padding: 20px 0;
  border-top: 1px solid var(--border-faint);
  font-size: 13px;
  color: var(--text-muted);
}
.app-footer-brand { font-family: Poppins, sans-serif; font-weight: 600; color: var(--text-secondary); }
.app-footer-links { display: flex; gap: 18px; flex-wrap: wrap; }
.app-footer-links a { color: var(--text-muted); }
.app-footer-links a:hover { color: var(--text-secondary); }
.app-footer-biz {
  flex: 1 0 100%;
  order: 3;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-faint);
}
.app-footer-biz-info {
  display: flex;
  flex-wrap: wrap;
  row-gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-faint);
}
.app-footer-biz-info li + li::before {
  content: "·";
  display: inline-block;
  margin: 0 10px;
  color: var(--border-strong);
}
.app-footer-biz-label {
  color: var(--text-muted);
  margin-right: 3px;
}