/* ═══════════════════════════════════════════════════════════════════════
 * style.css — 컴포넌트 CSS
 * ═══════════════════════════════════════════════════════════════════════
 * 읽는 순서: tokens.css(값) → base.css(정규화·OS 분기) → style.css(모양)
 *
 * 이 파일에는 **색상값·OS 분기를 직접 쓰지 않는다.**
 *   색·치수 → tokens.css의 var(--...)
 *   OS 차이 → base.css 한 곳
 *   safe-area → var(--safe-area-top/-bottom/-left/-right)
 * 자세한 규칙은 STYLE_GUIDE.md.
 * ═══════════════════════════════════════════════════════════════════════ */

/* ─── View 전환 ──────────────────────────────────────────────────────── */

.view {
  display: none;
  flex-direction: column;
  position: relative;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: calc(var(--tabbar-height) + var(--safe-area-bottom));
  isolation: isolate;
}

.view.active {
  display: flex;
}

/* ─── 세팅 화면 ──────────────────────────────────────────────────────── */

.ios-header {
  padding: var(--safe-area-top) var(--space-5) 0;
  background: var(--bg-canvas);
  flex-shrink: 0;
}

.ios-title {
  font-size: var(--text-24);
  font-weight: 700;
  color: var(--text-primary);
  padding-bottom: var(--space-4);
}

/* Alpha 뱃지 */
.alpha-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  background: var(--brand);
  color: var(--text-primary);
  font-size: var(--text-11);
  font-weight: 700;
  border-radius: var(--radius-sm);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  margin-left: var(--space-2-5);
  vertical-align: middle;
  line-height: 1;
}

.ios-title-wrap {
  display: flex;
  align-items: center;
  padding-bottom: var(--space-2);
}

.ios-title-wrap .ios-title {
  padding-bottom: 0;
}

.version-display {
  margin-left: auto;
  font-size: var(--text-11);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.setup-body {
  flex: 1;
  padding: var(--space-5) var(--space-5) 0;
  background: var(--bg-canvas);
  display: flex;
  flex-direction: column;
  min-height: 0;
  position: relative;
}

.setup-body.has-content {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.section-label {
  font-size: var(--text-13);
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: var(--space-2-5);
}

/* 업체 선택 버튼 */
.vendor-select-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: var(--control-lg);
  padding: 0 var(--space-4);
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  font-size: var(--text-15);
  color: var(--text-primary);
  margin-bottom: var(--space-5);
  transition: border-color 0.15s;
}

/* 좁은 폭에서 긴 업체명이 chevron을 밀어내지 않고 한 줄로 생략되게 한다.
   flex:1 과 min-width:0 은 **같이** 줘야 생략이 걸린다 */
.vendor-select-btn > span:first-child {
  flex: 1 1 auto;
  min-width: 0;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vendor-select-btn:active {
  border-color: var(--brand);
  background: var(--brand-a10);
}

.vendor-select-btn .chevron {
  display: flex;
  align-items: center;
  color: var(--text-secondary);
  flex-shrink: 0;
}

/* 조건 칩 그룹 */
.chip-container {
  min-height: var(--chip-area-min-h);
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-10) var(--space-5);
  gap: var(--space-2-5);
}

.empty-text {
  font-size: var(--text-14);
  color: var(--text-secondary);
  text-align: center;
}

.chip-group {
  margin-bottom: var(--space-4);
}

.chip-group-title {
  font-size: var(--text-13);
  font-weight: 600;
  color: var(--brand);
  margin-bottom: var(--space-2);
}

.chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-3);
  background: var(--brand-a15);
  border: 1px solid var(--brand-a40);
  border-radius: var(--radius-pill);
  font-size: var(--text-13);
  color: var(--brand);
}

/* ─── 하단 CTA ──────────────────────────────────────────────────────── */

/* 세로 2단 — 비활성 사유 힌트(위) + 버튼 줄(아래). (R1 / fb259539)
   힌트를 버튼 아래가 아니라 위에 두는 이유: 읽는 순서가 '이유 → 행동'이고,
   아래에 두면 safe-area(홈 인디케이터)에 깎인다. */
.setup-footer {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  background: var(--bg-canvas);
  flex-shrink: 0;
}

.setup-footer-actions {
  display: flex;
  /* 나란히 놓인 두 버튼의 높이를 묶는다. 한쪽 라벨이 2줄로 접혀도 어긋나지 않는다. */
  align-items: stretch;
  gap: var(--space-2-5);
}

/* 조회 버튼이 왜 꺼졌는지 (R1 / fb259539).
   색은 --label-a70 — "유일한 정보 전달 수단인 보조 텍스트"의 규칙이다.
   a40은 bg-canvas 위 3.1:1 / surface-card 위 2.8:1, a60은 surface-card 위 4.49:1로
   미달이고, a70만 두 면 모두 5.5:1 이상이다.
   잘리면 존재 이유가 사라지는 글이라 ellipsis 없이 줄바꿈시킨다(STYLE_GUIDE 4).
   360px + 글씨 1.3배에서 2줄이 되어도 버튼 줄을 밀어내기만 하고 깨지지 않는다. */
.setup-hint {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--text-13);
  line-height: 1.4;
  text-align: center;
  word-break: keep-all;
}

.btn-cta-left,
.btn-cta-right {
  flex: 1 1 0;
  /* 좁은 폭(360px)에서 긴 라벨이 상대 버튼을 밀어내지 않게 한다 */
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: auto;
  min-height: var(--control-lg);
  font-size: var(--text-15);
  font-weight: 600;
  line-height: 1.25;
  /* 한글은 단어 단위로만 접는다. 글자 하나가 떨어져 내려가면 더 깨져 보인다 */
  word-break: keep-all;
  text-align: center;
  border-radius: var(--radius-lg);
  padding: var(--space-1-5) var(--space-3);
}

.btn-cta-left {
  background: var(--surface-card);
  color: var(--text-primary);
  border: 1px solid var(--border-control);
}

.btn-cta-left:active {
  background: var(--surface-pressed);
}

/* ─── 버튼 공통 ──────────────────────────────────────────────────────── */

.btn-primary {
  display: block;
  width: 100%;
  min-height: var(--control-lg);
  padding: 0 var(--space-5);
  background: var(--brand);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 600;
  border-radius: var(--radius-lg);
  transition: background 0.15s, opacity 0.15s;
}

/* 비활성 주요 버튼은 면을 채우지 않는다.
   기존 면 rgba(235,235,245,0.2)은 bg-canvas 위에서 실효 #525256(명도 82)이 되어
   활성 보조 버튼 #3A3A3C(명도 58)보다 41% 밝았다 → "지금 누를 수 있다"는 거짓 신호.
   opacity로 비활성을 표현하지 않는다 — 그 위의 글자까지 흐려져 읽기 어려워진다. */
.btn-primary:disabled {
  background: none;
  border: 1.5px solid var(--border-control);
  color: var(--text-disabled);
}

.btn-primary:active:not(:disabled) {
  background: var(--brand-pressed);
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-md);
  padding: 0 var(--space-4);
  background: var(--surface-card);
  color: var(--text-primary);
  font-size: var(--text-14);
  font-weight: 500;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-control);
  transition: background 0.15s;
}

.btn-secondary:active {
  background: var(--overlay-pressed);
}

.btn-sm {
  min-height: var(--control-sm);
  padding: 0 var(--space-3);
  font-size: var(--text-13);
}

.btn-text {
  min-height: var(--control-md);
  padding: 0;
  color: var(--brand);
  font-size: var(--text-14);
  font-weight: 500;
  background: none;
}

/* ─── 공용 아이콘 (R1 / eb6a2e1e) ──────────────────────────────────────
 * 유니코드 글리프(× ‹ › ∨ ▾ ▴ ✓ ← ↺ ↓)는 글꼴마다 모양·굵기·세로 위치가
 * 달라 iOS와 Android가 다르게 보였다. 전부 인라인 SVG로 바꾼다.
 *
 * 꺾쇠는 **1종만** 둔다(오른쪽 기준). 네 방향은 CSS 회전으로 만들어
 * 모양이 갈라질 여지를 없앤다. 삼각형(▾▴)은 폐기했다.
 *
 * 크기 규칙(디자인 시스템 v18)
 *   - 기본                                    → --icon-sm (16px)
 *   - 단독 아이콘 버튼(닫기·월 이동·재조회)   → --icon-md (20px), 수식어 --lg
 * 아이콘 상자는 고정 크기이고, 담는 자리가 flex 가운데 정렬로 받는다.
 * 터치 영역은 각 버튼의 min-height/히트박스가 따로 책임진다(44px 이상, 기존 유지).
 *
 * 방향의 뜻(디자인 시스템 v18)
 *   오른쪽(회전 없음) = 이동   ·   아래↔위 = 제자리 펼침·접힘(닫힘 아래, 열림 위)
 *   왼쪽 = 오른쪽의 거울(뒤로·이전 달)
 *
 * 굵기는 상자가 작아질수록 두껍게 한다(작은 상자에서 2는 1px 미만으로 보인다).
 * 기존 인라인 SVG(탭바 22px/2, 배지 12px/3)와 같은 방향이다. */
.icon-chevron,
.icon-close,
.icon-check,
.icon-refresh {
  flex-shrink: 0;
  width: var(--icon-sm);
  height: var(--icon-sm);
  /* 글자 흐름 안에 들어가도 베이스라인에 걸려 내려앉지 않게 한다 */
  display: block;
}

/* 굵기는 한 가지다. SVG의 stroke-width 속성보다 CSS가 이기므로
   마크업에 2.2·2.5가 남아 있어도 여기서 눌린다.
   .icon-check는 뺀다 — 16px 상자에서 2는 1px 미만으로 보여 2.5가 확정값이다
   (2026-10-03 eb6a2e1e QA 결정). CSS로 덮으면 그 예외가 사라진다. */
.icon-chevron,
.icon-close,
.icon-refresh {
  stroke-width: var(--icon-stroke);
}

/* 단독 아이콘 버튼 */
.icon-chevron--lg,
.icon-close--lg,
.icon-refresh--lg {
  width: var(--icon-md);
  height: var(--icon-md);
}

/* 방향 — 기본(수식어 없음)은 오른쪽. 회전은 transform으로만 한다. */
.icon-chevron--down {
  transform: rotate(90deg);
}

.icon-chevron--left {
  transform: rotate(180deg);
}

.icon-chevron--up {
  transform: rotate(270deg);
}

/* ─── 결과 화면 ──────────────────────────────────────────────────────── */

.results-action-bar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(var(--safe-area-top) + var(--space-2-5)) var(--space-4) var(--space-2-5);
  background: var(--bg-canvas);
  flex-shrink: 0;
}

.results-action-bar .btn-secondary {
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: var(--space-1-5) var(--space-2);
  min-height: var(--control-md);
  color: var(--text-secondary);
  font-size: var(--text-14);
  font-weight: 500;
  /* 아이콘(꺾쇠·재조회)과 라벨 사이 — 디자인 시스템 Button: 아이콘은 라벨 왼쪽 6px */
  gap: var(--space-1-5);
}

.results-action-bar .btn-secondary:active {
  background: none;
  opacity: 0.6;
}

.action-right {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
}

.results-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-size: var(--text-15);
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  max-width: calc(100% - 160px);
}

.results-container {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-4) 0;
  background: var(--bg-canvas);
  -webkit-overflow-scrolling: touch;
}

/* ─── 날짜 탭 (결과 화면 상단) ──────────────────────────────────────── */

.date-tabs {
  display: flex;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding: var(--space-2-5) var(--space-4);
  gap: var(--space-2);
  flex-shrink: 0;
  background: var(--bg-canvas);
  padding-bottom: var(--space-3);
  /* 스크롤바 숨김 */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.date-tabs::-webkit-scrollbar {
  display: none;
}

.date-tab {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--border-control);
  background: var(--overlay-soft);
  font-size: var(--text-13);
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
  flex-shrink: 0;
  scroll-snap-align: start;
  /* transition: all 이었다. 레이아웃 속성까지 따라와 큰 글씨 조건에서 떨림이 생긴다.
     .date-tab.active 가 실제로 바꾸는 건 아래 셋뿐이다. */
  transition: background var(--dur-state), border-color var(--dur-state), color var(--dur-state);
  min-height: var(--control-sm);
  /* peek 효과: 마지막 탭 뒤에 다음 탭이 살짝 보이도록 */
}

.date-tab.active {
  background: var(--brand-a18);
  border-color: var(--brand);
  color: var(--text-primary);
  font-weight: 600;
}

.date-tab:active {
  background: var(--brand-a10);
}

/* 탭 상태 아이콘 (SVG CSS) */
.tab-icon {
  flex-shrink: 0;
  width: var(--icon-sm);
  height: var(--icon-sm);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tab-icon--available svg {
  stroke: var(--success);
}

.tab-icon--unavailable svg {
  stroke: var(--danger);
}

.tab-icon--loading svg {
  stroke: var(--text-tertiary);
}

/* 결과 그룹 */
.result-group {
  background: var(--surface-card);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: var(--space-4);
  box-shadow: 0 1px 3px var(--scrim-a30);
}

.result-group-header {
  padding: var(--space-3) var(--space-4);
  background: var(--overlay-soft);
  border-bottom: 1px solid var(--border-strong);
  font-size: var(--text-14);
  font-weight: 600;
  color: var(--text-primary);
}

/* ─── 업체 카드 (탭형 결과 화면) ────────────────────────────────────── */

.vendor-card {
  background: var(--surface-card);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: var(--space-4);
  box-shadow: 0 1px 3px var(--scrim-a30);
}

.vendor-card-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--overlay-soft);
  border-bottom: 1px solid var(--border-strong);
}

.vendor-card-name {
  font-size: var(--text-15);
  font-weight: 700;
  color: var(--text-primary);
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 상품 행 */
.product-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-divider);
  gap: var(--space-2-5);
}

.product-row:last-child {
  border-bottom: none;
}

/* 자리 이름 + 사유를 묶는 열. 사유를 배지 쪽에 두면 길 때 이름을 0폭까지 밀어내고
   우측 정렬 여러 줄이 되어 이름보다 시각 무게가 커졌다. */
.product-row-text {
  flex: 1 1 auto;
  min-width: 0;
  padding-top: var(--space-1);
}

.product-row-name {
  display: block;
  font-size: var(--text-14);
  font-weight: 400;
  color: var(--text-primary);
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.product-row--unavailable .product-row-name {
  color: var(--text-secondary);
}

.result-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-13);
}

.result-table th {
  padding: var(--space-2) var(--space-3);
  text-align: left;
  font-size: var(--text-11);
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.4px;
  background: var(--overlay-subtle);
  border-bottom: 1px solid var(--border-strong);
}

.result-table td {
  padding: var(--space-2-5) var(--space-3);
  border-bottom: 1px solid var(--border-divider);
  vertical-align: middle;
  color: var(--text-primary);
}

.result-table tr:last-child td {
  border-bottom: none;
}

.section-header-row td {
  font-size: var(--text-12);
  font-weight: 600;
  padding: var(--space-1-5) var(--space-3);
}

.section-available td {
  background: var(--success-fill);
  color: var(--success);
}

.section-unavailable td {
  background: var(--danger-fill);
  color: var(--danger);
}

.product-header-row td {
  padding: var(--space-2) var(--space-3);
  background: var(--overlay-subtle);
  border-bottom: 1px solid var(--border-strong);
}

.result-product-header-inner {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.result-product-thumb {
  width: var(--thumb-sm);
  height: var(--thumb-sm);
  border-radius: var(--radius-sm);
  object-fit: cover;
  flex-shrink: 0;
}

.result-product-thumb--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--neutral-fill);
  font-size: var(--text-14);
}

/* 스케줄 그룹 헤더 */
.schedule-group-header {
  font-size: var(--text-13);
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: 0.2px;
}

/* 결과 행 (스케줄 기준 그룹핑) */
.result-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-divider);
}

.result-row:last-child {
  border-bottom: none;
}

.result-row--available {
  background: var(--success-tint);
}

.result-row--loading {
  background: transparent;
}

.result-row--blocked {
  background: transparent;
  opacity: 0.7;
}

.result-thumb-wrap {
  flex-shrink: 0;
}

.result-row-text {
  flex: 1;
  min-width: 0;
}

.result-row-name {
  font-size: var(--text-14);
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.result-row-time {
  font-size: var(--text-12);
  color: var(--text-secondary);
  margin-top: var(--space-1);
}

/* 배지 열에는 배지 하나만 들어간다(사유는 이름 아래로 옮겼다).
   그래도 상한을 남겨 둔다 — 배지 글자가 길어져도 자리 이름이 먼저 사라지지 않는다. */
.result-row-badge {
  flex-shrink: 0;
  max-width: 50%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

/* 상태 배지의 표식은 인라인 SVG.
   유니코드 글리프(✓ ✗ ?)는 글꼴마다 모양·굵기·세로 위치가 달라 두 OS에서
   다르게 보였다. SVG는 글꼴과 무관하게 같은 모양이고 currentColor로 배지 색을 따른다. */
.badge-icon {
  width: var(--icon-xs);
  height: var(--icon-xs);
  flex-shrink: 0;
}

/* 예약 불가 아코디언 */
.unavailable-accordion {
  border-top: 1px solid var(--border-divider);
}

.unavailable-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: var(--text-13);
  font-weight: 500;
  cursor: pointer;
  text-align: left;
}

.unavailable-toggle:active {
  background: var(--overlay-pressed);
}

.unavailable-toggle-label {
  flex: 1;
}

/* 예약 불가 아코디언 꺾쇠 — 삼각형(▾▴) 폐기, 꺾쇠 SVG 1종을 회전해 쓴다. (R1 / eb6a2e1e) */
.unavailable-toggle-chevron {
  display: flex;
  align-items: center;
  margin-left: var(--space-2);
}

.unavailable-body {
  border-top: 1px solid var(--border-divider);
}

.unavailable-body.hidden {
  display: none;
}

/* 배지 */
.badge {
  display: inline-flex;
  align-items: center;
  /* 표식 SVG와 글자 사이. flex 아이템이라 글자 앞 공백은 지워지므로 gap으로 띄운다 */
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-12);
  font-weight: 600;
  text-decoration: none;
}

.badge-available {
  background: var(--success-fill);
  color: var(--success);
}

.badge-unavailable {
  background: var(--danger-fill);
  color: var(--danger);
}

.badge-unknown {
  background: var(--neutral-fill);
  color: var(--text-secondary);
}

.badge-loading {
  background: var(--neutral-fill);
  color: var(--text-tertiary);
  opacity: 0.7;
}

.reason-text {
  font-size: var(--text-11);
  /* a40 → a70 (R4 / fb259539). 배지는 '상태'만 말하고 '왜'는 사유만 말하므로,
     사유는 **유일한 정보 전달 수단**인 보조 텍스트다. a40 은 대비 2.8~3.1:1 로
     미달이다. iOS 외형이 조금 밝아지는 변경이다. */
  color: var(--text-secondary);
  margin-top: var(--space-1);
  /* 이름 아래 **왼쪽 정렬** 보조 텍스트. 우측 정렬 여러 줄이던 때는 읽는 방향이
     이름과 반대라 눈이 두 번 움직였고, 덩어리가 커서 이름보다 먼저 보였다.
     두 줄까지만 보여 준다 — 사유는 거드는 정보이지 이 행의 주인공이 아니다.
     잘린 전체는 `.reason-toggle` 로 되살린다(STYLE_GUIDE 4). */
  text-align: left;
  white-space: normal;
  word-break: keep-all;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* ─── 사유 펼침 토글 (R4 / fb259539) ──────────────────────────────────
   사유 + 라벨을 한 버튼으로 감싸 터치 영역 44px 을 패딩 없이 확보한다
   (사유 2줄 32 + 간격 4 + 라벨 16 + 위아래 6 = 64px).
   버튼 기본 모양은 플랫폼마다 다르므로 전부 눌러 둔다(글꼴·배경·테두리·정렬). */
.reason-toggle {
  display: block;
  width: 100%;
  margin: 0;
  padding: var(--space-1-5) 0;
  background: none;
  border: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

/* 펼치면 clamp 를 푼다. `-webkit-line-clamp` 를 지우는 것만으로는 부족해서
   display 도 block 으로 되돌려야 한다(-webkit-box 가 줄 수를 잡고 있다). */
.reason-toggle--open .reason-text {
  display: block;
  -webkit-line-clamp: unset;
  line-clamp: unset;
  overflow: visible;
}

/* 라벨과 사유가 같은 색이면 라벨이 사유의 일부로 읽힌다 → **굵기로만** 구분한다. */
.reason-toggle-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-1);
  font-size: var(--text-11);
  font-weight: 600;
  color: var(--text-secondary);
}

/* 스피너 */
.spinner {
  display: inline-block;
  width: var(--icon-sm);
  height: var(--icon-sm);
  border: 2px solid var(--spinner-track);
  border-top-color: var(--brand);
  border-radius: var(--radius-circle);
  animation: spin 0.7s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ─── 바텀시트 ──────────────────────────────────────────────────────── */

.sheet-overlay {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: 1000;
  opacity: 1;
  transition: opacity 0.25s;
}

.sheet-overlay.hidden {
  display: none;
}

.bottom-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--surface-card);
  border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
  z-index: 1001;
  display: flex;
  flex-direction: column;
  /* 높이 바닥(78vh)을 없앴다. 업체만 고르는 시트처럼 내용이 적을 때도 화면의 78%를
     차지해 빈 공간이 컸다. 이제 내용만큼 올라오고 max-height(92vh)가 위를 막는다.
     드롭다운·상품 목록이 붙으면 그만큼 커진다(드롭다운을 흐름 안에 둔 이유다). */
  max-height: 92vh;
  transform: translateY(0);
  transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1);
}

.bottom-sheet.hidden {
  display: none;
}

.sheet-handle {
  width: var(--sheet-handle-w);
  height: var(--sheet-handle-h);
  background: var(--handle);
  border-radius: var(--radius-xs);
  margin: var(--space-3) auto var(--space-1);
  flex-shrink: 0;
}

.sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--space-5) var(--space-3);
  border-bottom: 1px solid var(--border-strong);
  flex-shrink: 0;
}

.sheet-title {
  font-size: var(--text-17);
  font-weight: 600;
  color: var(--text-primary);
}

/* 닫기 — 모양은 .icon-close(SVG), 크기는 --icon-md. 버튼은 터치 영역만 책임진다.
   font-size 리터럴(24px)은 글리프 시절의 크기 지정이라 사라졌다. (R1 / eb6a2e1e) */
.sheet-close-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--control-md);
  min-height: var(--control-md);
  color: var(--text-secondary);
  margin: -10px -10px -10px 0;
}

.sheet-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-4) var(--space-5);
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.sheet-footer {
  padding: var(--space-4) var(--space-5);
  padding-bottom: calc(var(--space-4) + var(--safe-area-bottom));
  border-top: 1px solid var(--border-strong);
  flex-shrink: 0;
}

.sheet-section {
  margin-bottom: var(--space-6);
}

.sheet-section-label {
  font-size: var(--text-13);
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: var(--space-2);
}

.optional-hint {
  font-weight: 400;
  color: var(--text-tertiary);
}

/* ─── 커스텀 달력 그리드 ──────────────────────────────────────────── */

.cal-container {
  background: var(--overlay-subtle);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-xl);
  padding: var(--space-3);
  user-select: none;
  -webkit-user-select: none;
}

.cal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}

/* 월 이동 — 모양은 .icon-chevron(SVG), 크기는 --icon-md.
   font-size/font-weight 리터럴은 글리프 굵기를 맞추려던 것이라 사라졌다. (R1 / eb6a2e1e) */
.cal-nav-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--control-md);
  min-height: var(--control-md);
  color: var(--text-secondary);
  background: none;
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  line-height: 1;
  padding: 0;
  transition: background 0.12s;
}

.cal-nav-btn:active {
  background: var(--overlay-pressed);
}

.cal-month-label {
  font-size: var(--text-15);
  font-weight: 600;
  color: var(--text-primary);
  text-align: center;
  flex: 1;
}

.cal-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: var(--space-1);
}

.cal-weekdays span {
  text-align: center;
  font-size: var(--text-11);
  font-weight: 600;
  color: var(--text-tertiary);
  padding: var(--space-1) 0;
}

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--space-1) 0;
}

.cal-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-md);
  font-size: var(--text-14);
  color: var(--text-primary);
  cursor: pointer;
  transition: background 0.1s;
  border-radius: 0;
}

.cal-cell.empty {
  pointer-events: none;
}

.cal-cell.past {
  color: var(--text-disabled);
  pointer-events: none;
  cursor: default;
}

/* 범위 하이라이트 배경 (시작일~종료일 사이)
   셀 전체(44px)를 칠하면 양 끝 동그라미·반쪽 띠(36px)보다 높아 띠가 들쭉날쭉해진다.
   끝 캡과 같은 높이(control-sm)로 맞추고 세로 가운데에 둔다. */
.cal-cell.in-range::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: var(--control-sm);
  background: var(--brand-a12);
  z-index: 0;
}

/* 시작일 / 종료일: 주황 원형 */
.cal-cell.selected-start,
.cal-cell.selected-end {
  color: var(--text-primary);
}

.cal-cell.selected-start .cal-day-num,
.cal-cell.selected-end .cal-day-num {
  background: var(--brand);
  border-radius: var(--radius-circle);
  width: var(--cal-day-size);
  height: var(--cal-day-size);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 1;
}

/* 시작일: 오른쪽 절반만 range 색 */
.cal-cell.selected-start.in-range-start::before {
  content: '';
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 50%;
  height: var(--control-sm);
  background: var(--brand-a12);
  z-index: 0;
}

/* 종료일: 왼쪽 절반만 range 색 */
.cal-cell.selected-end.in-range-end::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 50%;
  height: var(--control-sm);
  background: var(--brand-a12);
  z-index: 0;
}

/* 시작일=종료일인 경우 range 없음 */
.cal-cell.selected-single .cal-day-num {
  background: var(--brand);
  border-radius: var(--radius-circle);
  width: var(--cal-day-size);
  height: var(--cal-day-size);
  display: flex;
  align-items: center;
  justify-content: center;
}

.cal-day-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--cal-day-size);
  height: var(--cal-day-size);
  position: relative;
  z-index: 1;
}

/* 달력 힌트 텍스트 */
.cal-hint {
  margin-top: var(--space-2-5);
  font-size: var(--text-12);
  color: var(--text-tertiary);
  text-align: center;
}

/* 달력 내 추가하기 버튼 */
.cal-add-btn {
  margin-top: var(--space-3);
  width: 100%;
}

/* ─── 시간 입력 ──────────────────────────────────────────────────── */

.time-input {
  width: 100%;
  min-height: var(--control-md);
  padding: 0 var(--space-3);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  font-size: var(--text-15);
  color: var(--text-primary);
  background: var(--overlay-soft);
  appearance: none;
  -webkit-appearance: none;
}

.time-input:focus {
  outline: none;
  border-color: var(--brand);
}

/* 박 수 버튼 그룹 (레거시 — 미사용) */
.duration-btn {
  flex: 1;
  min-width: 0;
  min-height: var(--control-md);
  padding: 0 var(--space-1);
  background: var(--overlay-soft);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-md);
  font-size: var(--text-13);
  font-weight: 500;
  color: var(--text-primary);
  /* transition: all → 실제로 바뀌는 속성만 (위 .date-tab과 같은 이유) */
  transition: background var(--dur-state), border-color var(--dur-state), color var(--dur-state);
}

.duration-btn.active {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--text-primary);
}

.duration-btn:active:not(.active) {
  background: var(--overlay-pressed);
}

.hint-text {
  font-size: var(--text-12);
  color: var(--text-tertiary);
  margin-top: var(--space-1-5);
}

/* 가로 스크롤 칩 행 */
.chip-scroll-row {
  display: flex;
  gap: var(--space-2);
  overflow-x: auto;
  padding-bottom: var(--space-1);
  margin-top: var(--space-2);
  -webkit-overflow-scrolling: touch;
}

.chip-scroll-row:empty {
  display: none;
}

/* 시트 내부 칩 */
.sheet-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-3);
  background: var(--brand-a15);
  border: 1px solid var(--brand-a40);
  border-radius: var(--radius-pill);
  font-size: var(--text-13);
  color: var(--brand);
  white-space: nowrap;
  flex-shrink: 0;
}

/* 미리보기 배너 */
.preview-banner {
  padding: var(--space-3) var(--space-4);
  background: var(--brand-a10);
  border: 1px solid var(--brand-a30);
  border-radius: var(--radius-lg);
  font-size: var(--text-13);
  color: var(--brand);
  font-weight: 500;
}

.preview-banner.hidden {
  display: none;
}

/* ─── 상품 피커 ──────────────────────────────────────────────────────── */

.product-picker {
  max-height: 85vh;
}

.picker-search-wrap {
  padding: var(--space-2) var(--space-5) var(--space-3);
  border-bottom: 1px solid var(--border-strong);
  flex-shrink: 0;
}

.picker-search {
  width: 100%;
  min-height: var(--control-md);
  padding: 0 var(--space-3) 0 var(--space-9);
  background: var(--overlay-soft);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  font-size: var(--text-15);
  color: var(--text-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='7' stroke='%23EBEBF5' stroke-width='2' stroke-opacity='0.6'/%3E%3Cpath d='M20 20l-4-4' stroke='%23EBEBF5' stroke-width='2' stroke-linecap='round' stroke-opacity='0.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 10px center;
}

.picker-search:focus {
  outline: none;
  border-color: var(--brand);
}

.picker-check-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-15);
  color: var(--text-primary);
  cursor: pointer;
  flex-shrink: 0;
  min-height: var(--control-md);
}

.picker-check-row input[type="checkbox"] {
  width: var(--icon-md);
  height: var(--icon-md);
  accent-color: var(--brand);
  cursor: pointer;
  flex-shrink: 0;
}

.picker-divider {
  border: none;
  border-top: 1px solid var(--border-strong);
  flex-shrink: 0;
}

.picker-list {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.picker-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2-5) var(--space-5);
  min-height: var(--list-row-h);
  cursor: pointer;
  border-bottom: 1px solid var(--border-divider);
}

.picker-item.disabled {
  opacity: 0.4;
  pointer-events: none;
}

.picker-item input[type="checkbox"] {
  width: var(--icon-md);
  height: var(--icon-md);
  accent-color: var(--brand);
  flex-shrink: 0;
}

.picker-thumb-wrap {
  width: var(--thumb-md);
  height: var(--thumb-md);
  flex-shrink: 0;
}

.picker-thumb {
  width: var(--thumb-md);
  height: var(--thumb-md);
  border-radius: var(--radius-md);
  object-fit: cover;
}

.picker-thumb--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--neutral-fill);
  border-radius: var(--radius-md);
}

.picker-item-name {
  font-size: var(--text-14);
  color: var(--text-primary);
  flex: 1;
}

.picker-footer {
  display: flex;
  gap: var(--space-2-5);
}

.picker-footer .btn-secondary {
  flex: 1;
}

.picker-footer .btn-primary {
  flex: 2;
}

/* ─── 유틸리티 ──────────────────────────────────────────────────────── */

.hidden {
  display: none !important;
}

/* ─── 업체 드롭다운 ──────────────────────────────────────────────────── */

.vendor-dropdown {
  position: fixed;
  z-index: 1100;
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  overflow: hidden;
  max-height: 280px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 8px 24px var(--scrim-a40);
}

.vendor-dropdown-item {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 100%;
  min-height: var(--list-row-h);
  padding: 0 var(--space-4);
  text-align: left;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border-divider);
  cursor: pointer;
  gap: var(--space-2);
}

.vendor-dropdown-item:active {
  background: var(--brand-a12);
}

.vendor-dropdown-item:last-child {
  border-bottom: none;
}

.vendor-picker-name {
  font-size: var(--text-15);
  font-weight: 500;
  color: var(--text-primary);
  /* 좁은 폭에서 긴 업체명이 플랫폼 배지를 밀어내지 않게.
     flex:1 과 min-width:0 은 **같이** 줘야 생략이 걸린다 */
  flex: 1 1 auto;
  min-width: 0;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 드롭다운 "더 있음" 표시 — 업체가 8개인데 5개만 보이고 더 있다는 신호가 없어
   "이게 전부"로 읽혔다. 안내 행이지 고를 수 있는 항목이 아니므로 업체 행보다
   낮고 작게, 보조 톤으로 둔다(같은 높이·굵기면 탭하면 뭔가 될 것처럼 보인다). */
.vendor-dropdown-more {
  position: sticky;
  bottom: 0;
  display: none;
  padding: var(--space-1) var(--space-4) var(--space-1-5);
  background: linear-gradient(to top, var(--surface-card) 70%, transparent);
  color: var(--text-secondary);
  font-size: var(--text-12);
  font-weight: 500;
  text-align: center;
  letter-spacing: 0.2px;
  pointer-events: none;
  cursor: default;
}

/* 글자 + 아래쪽 꺾쇠를 한 줄로. 컨테이너의 display는 .has-more 토글이 쓰므로 안쪽에 둔다. */
.vendor-dropdown-more-inner {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

/* 업체 0개 EmptyState(empty-new) — OS 경고창을 대신해 드롭다운 자리에 뜬다. (R2 / eb6a2e1e)
   위아래 여백 20px + 행동 버튼 1개(44px)는 디자인 시스템 확정 값이다.
   드롭다운 max-height(230px) 안에 큰 글씨에서도 들어가야 해서 EmptyState 기본
   space-10(40px)이 아니라 space-5(20px)를 쓴다. 넘치면 드롭다운이 스크롤한다. */
.vendor-dropdown-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-4);
}

/* 행동은 Button Secondary 하나. 터치 영역 44px을 채운다. */
.vendor-dropdown-empty .kalarm-retry-btn {
  min-height: var(--control-md);
}

.vendor-dropdown-list.has-more .vendor-dropdown-more {
  display: block;
}

/* 안내 행 바로 위 항목의 구분선을 지운다. 선이 남아 있으면 안내 행이
   "하나 더 있는 항목"처럼 테두리를 갖게 되어 고를 수 있는 것처럼 보인다. */
.vendor-dropdown-list.has-more .vendor-dropdown-item:nth-last-child(2) {
  border-bottom: none;
}

.vendor-picker-platform {
  font-size: var(--text-12);
  color: var(--text-secondary);
}

/* 플랫폼(출처) 배지.
   색은 **CSS 클래스로만** 정한다. 예전에는 app.js가 인라인 스타일로 칠했는데
   (1) 토큰을 우회하고 (2) 서버가 주는 platform_name('네이버')과 키(호스트명)가
   어긋나 녹색 분기가 한 번도 안 타고 전부 회색 fallback으로 그려졌다. */
.platform-badge {
  display: inline-block;
  font-size: var(--text-11);
  font-weight: 700;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  border: none;
  line-height: 1.5;
  flex-shrink: 0;
  /* 기본값 = 출처를 모를 때. 모든 변형이 이 위에 색만 덮어쓴다 */
  background: var(--neutral-fill);
  color: var(--text-secondary);
}

/* 네이버: 연한 배경 + 녹색 글자.
   솔리드 녹색 + 흰 글자는 쓰지 않는다 — 상태색(success, 예약 가능)과 같은 세기가 되어
   '출처' 표시가 '상태'처럼 읽힌다. 출처는 분류이지 사실 통지가 아니다. */
.platform-badge--naver {
  background: var(--platform-naver-a20);
  color: var(--platform-naver);
}

/* 그 밖의 출처: neutral-fill + text-secondary.
   브랜드색을 새로 만들지 않는다 — 액센트는 brand 하나뿐이고, 출처마다 색을 늘리면
   화면에서 색이 뜻을 잃는다. 구분은 배지의 '글자'가 한다. */
.platform-badge--etc {
  background: var(--neutral-fill);
  color: var(--text-secondary);
}

/* ─── 메인 달력 (상시 노출) ──────────────────────────────────────────── */

.main-cal-container {
  margin-bottom: var(--space-4);
}

/* ─── 메인 화면 날짜 칩 ──────────────────────────────────────────────── */

.main-date-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  min-height: 0;
}

.main-date-chips:empty {
  display: none;
}

.main-date-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-3);
  background: var(--brand-a15);
  border: 1px solid var(--brand-a40);
  border-radius: var(--radius-pill);
  font-size: var(--text-13);
  color: var(--brand);
}

/* ─── 업체 선택하기 버튼 (메인 화면) ────────────────────────────────── */

.btn-vendor-select-main {
  margin-bottom: var(--space-6);
}

/* ─── 바텀시트 날짜 배너 ─────────────────────────────────────────────── */

.sheet-date-banner {
  padding: var(--space-2-5) var(--space-5);
  background: var(--brand-a12);
  border-bottom: 1px solid var(--brand-a20);
  font-size: var(--text-13);
  font-weight: 600;
  color: var(--brand);
  flex-shrink: 0;
}

.sheet-date-banner.hidden {
  display: none;
}

/* ─── 바텀시트 인라인 상품 체크박스 ──────────────────────────────────── */

.sheet-inline-products {
  display: flex;
  flex-direction: column;
  gap: 0;
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.sheet-inline-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  min-height: var(--list-row-h);
  cursor: pointer;
  border-bottom: 1px solid var(--border-divider);
  background: var(--overlay-subtle);
  transition: background 0.12s;
}

.sheet-inline-item:last-child {
  border-bottom: none;
}

.sheet-inline-select-all {
  font-weight: 600;
  color: var(--brand);
}

.sheet-inline-item:active {
  background: var(--brand-a7);
}

.sheet-inline-item input[type="checkbox"] {
  width: var(--icon-md);
  height: var(--icon-md);
  accent-color: var(--brand);
  flex-shrink: 0;
  cursor: pointer;
}

.sheet-inline-item-name {
  font-size: var(--text-14);
  color: var(--text-primary);
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sheet-inline-empty {
  padding: var(--space-5);
  font-size: var(--text-14);
  color: var(--text-tertiary);
  text-align: center;
}

/* ─── 스케줄 보드 ────────────────────────────────────────────────────── */

.schedule-board {
  padding-bottom: var(--space-4);
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.schedule-empty {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.schedule-empty-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 80%;
  font-size: var(--text-14);
  color: var(--text-tertiary);
  text-align: center;
}

/* 스케줄 카드 */
.schedule-card {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  overflow: hidden;
  margin-bottom: var(--space-3);
  box-shadow: 0 1px 4px var(--scrim-a30);
}

.schedule-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  background: var(--brand-a10);
  border-bottom: 1px solid var(--brand-a20);
}

.schedule-card-date {
  font-size: var(--text-14);
  font-weight: 700;
  color: var(--brand);
  flex: 1;
  min-width: 0;
}

.schedule-card-delete {
  font-size: var(--text-12);
  color: var(--text-tertiary);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  min-height: var(--control-sm);
}

.schedule-card-delete:active {
  background: var(--overlay-pressed);
  color: var(--text-secondary);
}

/* 업체 행 */
.vendor-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-divider);
  cursor: pointer;
  transition: background 0.12s;
  min-height: var(--list-row-h);
}

.vendor-row:active {
  background: var(--overlay-pressed);
}

.vendor-row-left {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
}

.vendor-row-name {
  font-size: var(--text-14);
  font-weight: 500;
  color: var(--text-primary);
  /* min-width:0 만으로는 생략이 걸리지 않는다. flex:1 과 **같이** 줘야 한다 */
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vendor-row-product-count {
  font-size: var(--text-12);
  color: var(--text-secondary);
  white-space: nowrap;
  flex-shrink: 0;
}

.vendor-row-delete {
  font-size: var(--text-12);
  color: var(--text-tertiary);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  min-height: var(--control-sm);
  margin-left: var(--space-2);
}

.vendor-row-delete:active {
  background: var(--overlay-pressed);
  color: var(--text-secondary);
}

.vendor-row-empty {
  padding: var(--space-4);
  font-size: var(--text-13);
  color: var(--text-tertiary);
  text-align: center;
}

/* 업체 추가 버튼 (카드 하단) */
.btn-add-vendor {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--control-md);
  font-size: var(--text-14);
  font-weight: 500;
  color: var(--text-secondary);
  background: var(--overlay-subtle);
  border-top: 1px solid var(--border-strong);
  transition: background 0.12s;
}

.btn-add-vendor:active {
  background: var(--overlay-pressed);
}

/* ─── 업체 드롭다운 (시트 내부) ──────────────────────────────────────── */

.vendor-dropdown-wrap {
  position: relative;
}

/* 드롭다운은 **흐름 안에** 둔다(절대배치 아님).
   절대배치로 띄우면 스크롤 컨테이너(.sheet-body)의 아래 경계에서 잘려,
   시트가 짧을 때 목록이 세 줄만 보이고 "더 있음" 표시까지 가려졌다.
   흐름에 두면 시트가 내용만큼 늘어나고(최대 92vh) 잘릴 일이 없다. */
.vendor-dropdown-list {
  margin-top: var(--space-1);
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  overflow: hidden;
  /* 항목 높이(50px)의 배수를 피해 다음 항목이 반쯤 걸치게 한다
     → "여기서 끝"이 아니라 "더 있다"로 읽힌다.
     개수는 .vendor-dropdown-more 가 글자로도 말해 준다. */
  max-height: 230px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 8px 24px var(--scrim-a40);
}

/* ─── 상품 검색 인풋 ─────────────────────────────────────────────────── */

.product-search-wrap {
  margin-bottom: var(--space-2-5);
}

.product-search {
  width: 100%;
  min-height: var(--control-md);
  padding: 0 var(--space-3) 0 var(--space-9);
  background: var(--overlay-soft);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  font-size: var(--text-15);
  color: var(--text-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='7' stroke='%23EBEBF5' stroke-width='2' stroke-opacity='0.6'/%3E%3Cpath d='M20 20l-4-4' stroke='%23EBEBF5' stroke-width='2' stroke-linecap='round' stroke-opacity='0.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 10px center;
}

.product-search:focus {
  outline: none;
  border-color: var(--brand);
}

.product-search::placeholder {
  color: var(--text-tertiary);
}

/* ─── 하단 탭바 ──────────────────────────────────────────────────────── */

.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 900;
  display: flex;
  align-items: flex-start;
  background: var(--bg-base);
  padding-bottom: var(--safe-area-bottom);
}

.tab-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  height: var(--tabbar-height);
  color: var(--text-secondary);
  font-size: var(--text-10);
  font-weight: 500;
  letter-spacing: 0.2px;
  transition: color 0.15s;
  background: none;
  border: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.tab-item.active {
  color: var(--brand);
}

.tab-item:active {
  opacity: 0.7;
}

.tab-icon-img {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--icon-lg);
  height: var(--icon-lg);
}

.tab-icon-img svg {
  width: var(--icon-md);
  height: var(--icon-md);
}

.tab-label {
  font-size: var(--text-10);
  font-weight: 500;
}

/* 탭바 회피는 .view padding-bottom에서 일괄 처리 */

/* ─── 관리 화면 ──────────────────────────────────────────────────────── */

/* 하단 여백은 **이 규칙 안에서** 준다.
   예전에는 위쪽에 `.manage-body { padding-bottom: 120px }` 규칙이 따로 있었는데,
   아래 `padding: 16px 16px 0` 단축 속성이 뒤에 와서 그 값을 **0으로 덮고 있었다**.
   그래서 FAB 회피 여백이 실제로는 없었고, 떠 있는 FAB가 마지막 업체 카드의
   토글·화살표를 가렸다.
   하한은 fab-size(56) + FAB 하단 여백(28) + space-4(16) = 100px. */
.manage-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-4) var(--space-4) var(--fab-clearance);
  background: var(--bg-canvas);
  -webkit-overflow-scrolling: touch;
}

/* ─── Speed Dial FAB ────────────────────────────────────────────────── */

.manage-fab-backdrop {
  position: fixed;
  inset: 0;
  z-index: 49;
  /* 0.35에서는 뒤 업체 토글(주황)이 FAB·라벨과 섞여 보였다. 확정 scrim 값(0.5)으로 올려
     "가려진 것"이 아니라 "지금 잠긴 것"으로 읽히게 한다. */
  background: var(--scrim);
}
.manage-fab-backdrop.hidden {
  display: none;
}

.manage-fab-wrap {
  position: absolute;
  bottom: 28px;
  right: 20px;
  z-index: 50;
  pointer-events: none;
}

.manage-fab-dial {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

/* 메인 버튼 */
.manage-fab-main {
  width: var(--fab-size);
  height: var(--fab-size);
  border-radius: var(--radius-circle);
  background: var(--brand);
  color: var(--text-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
  margin-top: var(--space-3);
  position: relative;
  transition: background 0.2s ease, transform 0.15s ease;
  pointer-events: auto;
}
.manage-fab-main:active {
  transform: scale(0.93);
}
.manage-fab-dial.open .manage-fab-main {
  background: var(--surface-card);
}

/* + 아이콘 / × 아이콘 전환 */
.manage-fab-main-plus,
.manage-fab-main-close {
  position: absolute;
  transition: opacity 0.2s ease, transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.manage-fab-main-close {
  opacity: 0;
  transform: rotate(-45deg) scale(0.7);
}
.manage-fab-dial.open .manage-fab-main-plus {
  opacity: 0;
  transform: rotate(45deg) scale(0.7);
}
.manage-fab-dial.open .manage-fab-main-close {
  opacity: 1;
  transform: rotate(0deg) scale(1);
}

/* 서브 아이템 */
.manage-fab-item {
  display: flex;
  align-items: center;
  /* 라벨이 버튼 왼쪽에 붙고 묶음 전체는 오른쪽 정렬을 유지한다 */
  justify-content: flex-end;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  opacity: 0;
  transform: translateY(16px) scale(0.85);
  pointer-events: none;
  transition: opacity 0.22s ease, transform 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.manage-fab-dial.open .manage-fab-item {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.manage-fab-dial.open .manage-fab-item[data-index="1"] { transition-delay: 0s; }
.manage-fab-dial.open .manage-fab-item[data-index="0"] { transition-delay: 0.06s; }
.manage-fab-item[data-index="0"] { transition-delay: 0s; }
.manage-fab-item[data-index="1"] { transition-delay: 0.04s; }

/* 아이콘만 있어서 열어 봐도 무슨 동작인지 알 수 없었다 → 라벨을 띄운다.
   알약 모양은 "사용자가 고르는 것"이라는 모양 규칙과 맞고, 칩과 같은 13px이다.
   다이얼이 열린 동안은 scrim이 뒤를 덮으므로 라벨이 목록을 가리는 게 아니다.
   버튼의 aria-label은 그대로 두고 라벨은 aria-hidden 이다(중복 낭독 방지). */
.manage-fab-label {
  max-width: 160px;
  padding: var(--space-1-5) var(--space-3);
  background: var(--surface-card);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-overlay);
  color: var(--text-primary);
  font-size: var(--text-13);
  font-weight: 600;
  line-height: 1.45;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

.manage-fab-child {
  width: var(--fab-size);
  height: var(--fab-size);
  border-radius: var(--radius-circle);
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.manage-fab-child:active {
  transform: scale(0.9);
}
.manage-fab-child--add {
  background: var(--brand);
  color: var(--text-primary);
  position: relative;
}

.manage-fab-add-icon {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.manage-fab-add-badge {
  position: absolute;
  top: -6px;
  right: -8px;
  width: var(--icon-sm);
  height: var(--icon-sm);
  background: var(--text-primary);
  color: var(--brand);
  border-radius: var(--radius-circle);
  font-size: var(--text-13);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.manage-fab-child--refresh {
  background: var(--bg-canvas);
  color: var(--brand);
  border: 1.5px solid var(--brand-a45);
}
.manage-fab-child--refresh:disabled {
  opacity: 0.45;
}

/* ─── 업체 추가 모달 ────────────────────────────────────────────────── */
/* 가운데 뜨는 모달.
   위아래 여백에 safe-area를 더해, 키보드 때문에 보이는 영역이 줄어도 상자가
   상태바(시계)나 제스처 바 밑으로 들어가지 않는다. */
.manage-url-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(var(--space-6) + var(--safe-area-top)) var(--space-5) calc(var(--space-6) + var(--safe-area-bottom));
  /* **이 레이어가 자기 스크롤 컨테이너여야 한다.**
     iOS WKWebView는 입력창에 포커스가 가면 가장 가까운 스크롤 컨테이너를 스크롤한다.
     그런 컨테이너가 없으면 대신 **페이지 전체를 밀어 올려서** 상단 내용이 상태바
     밑으로 들어간다. 바텀시트가 멀쩡했던 건 안쪽 .sheet-body가 그 역할을 해서다. */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.manage-url-modal.hidden {
  display: none;
}

.manage-url-modal-backdrop {
  position: absolute;
  inset: 0;
  background: var(--scrim);
}

.manage-url-modal-box {
  position: relative;
  width: 100%;
  max-width: 400px;
  background: var(--bg-canvas);
  border-radius: var(--radius-2xl);
  padding: var(--space-6) var(--space-5) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-height: 80vh;
  overflow: hidden;
}

.manage-modal-step.hidden {
  display: none;
}

.manage-modal-step {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.manage-url-modal-title {
  font-size: var(--text-17);
  font-weight: 700;
  color: var(--text-primary);
}

.manage-url-modal-row {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* 모달 액션 버튼 */
.manage-modal-actions {
  display: flex;
  /* 한쪽 라벨이 접혀도 두 버튼 높이를 묶는다 */
  align-items: stretch;
  gap: var(--space-2);
}

.manage-modal-btn {
  flex: 1 1 0;
  min-width: 0;
  /* height 고정(46px) → min-height. 고정 높이는 라벨이 접히면 글자가 잘린다 */
  min-height: var(--control-lg);
  border-radius: var(--radius-lg);
  font-size: var(--text-15);
  font-weight: 600;
  -webkit-tap-highlight-color: transparent;
}

.manage-modal-btn--cancel {
  background: var(--surface-card);
  color: var(--text-secondary);
}

.manage-modal-btn--primary {
  background: var(--brand);
  color: var(--text-primary);
}

/* opacity 비활성 폐기 — 면 없음 + border-control + text-disabled */
.manage-modal-btn--primary:disabled {
  background: none;
  border: 1.5px solid var(--border-control);
  color: var(--text-disabled);
}

/* Step2 미리보기 */
.manage-modal-preview-vendor {
  font-size: var(--text-15);
  font-weight: 700;
  color: var(--text-primary);
}

.manage-modal-preview-list {
  overflow-y: auto;
  max-height: 40vh;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.manage-preview-product-row {
  font-size: var(--text-14);
  color: var(--text-primary);
  padding: var(--space-2-5) 0;
  border-bottom: 1px solid var(--border-divider);
}

/* URL 등록 영역 */
.manage-register-section {
  margin-bottom: var(--space-5);
}

.manage-register-row {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

.manage-url-input {
  flex: 1;
  min-height: var(--control-lg);
  padding: 0 var(--space-3);
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  font-size: var(--text-14);
  color: var(--text-primary);
  transition: border-color 0.15s;
}

.manage-url-input:focus {
  outline: none;
  border-color: var(--brand);
}

.manage-url-input::placeholder {
  color: var(--text-tertiary);
}

.manage-register-btn {
  min-height: var(--control-lg);
  padding: 0 var(--space-5);
  background: var(--brand);
  color: var(--text-primary);
  font-size: var(--text-14);
  font-weight: 600;
  border-radius: var(--radius-lg);
  flex-shrink: 0;
  transition: background 0.15s, opacity 0.15s;
}

/* opacity 비활성 폐기 — 면 없음 + border-control + text-disabled */
.manage-register-btn:disabled {
  background: none;
  border: 1.5px solid var(--border-control);
  color: var(--text-disabled);
}

.manage-register-btn:active:not(:disabled) {
  background: var(--brand-pressed);
}

/* 업체 리스트 */
.manage-vendor-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2-5);
  padding-bottom: var(--space-6);
}

/* 업체 카드 */
.manage-vendor-card {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  overflow: hidden;
  border: 1.5px solid transparent;
  transition: border-color 0.15s;
}

.manage-vendor-card.open {
  border-color: var(--brand);
}

/* 카드 헤더 */
.manage-vendor-header {
  display: flex;
  align-items: stretch;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* 왼쪽 갱신 섹션 (칼람 벨 섹션과 동일한 구조) */
.manage-sync-section {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--sync-col-w);
  flex-shrink: 0;
  border-right: 1px solid var(--border-divider);
}

/* 오른쪽 헤더 콘텐츠 */
.manage-vendor-header-content {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-4) var(--space-4) var(--space-3);
  gap: var(--space-2-5);
}

.manage-vendor-header-left {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
}

.manage-vendor-header-right {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  flex-shrink: 0;
}

/* 플랫폼 뱃지 */
.manage-platform-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-11);
  font-weight: 700;
  flex-shrink: 0;
  white-space: nowrap;
}

/* 업체명 */
.manage-vendor-name {
  font-size: var(--text-15);
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}

/* 갱신 버튼 */
.manage-sync-btn {
  background: none;
  border: none;
  padding: var(--space-2);
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.2s;
  -webkit-tap-highlight-color: transparent;
}

.manage-sync-btn:active:not(:disabled) {
  color: var(--brand);
  opacity: 0.8;
}

.manage-sync-btn:disabled {
  opacity: 0.3;
}

.manage-sync-btn.loading {
  color: var(--brand);
  animation: manage-spin 0.8s linear infinite;
}

@keyframes manage-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* 아코디언 화살표 */
/* 아코디언 꺾쇠 — 모양은 .icon-chevron(SVG), 열리면 --down 으로 회전한다.
   font-size 리터럴(18px)은 글리프 크기 지정이라 사라졌다. (R1 / eb6a2e1e) */
.manage-chevron {
  display: flex;
  align-items: center;
  color: var(--text-secondary);
  flex-shrink: 0;
  line-height: 1;
  user-select: none;
  -webkit-user-select: none;
}

/* 카드 바디 (열린 상태) */
.manage-vendor-body {
  padding: 0 var(--space-4) var(--space-4);
  border-top: 1px solid var(--border-strong);
}


/* 전체 활성/비활성 토글 행 */
.manage-bulk-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) 0 var(--space-2-5);
  border-bottom: 1px solid var(--border-strong);
}

.manage-bulk-toggle-label {
  font-size: var(--text-13);
  font-weight: 600;
  color: var(--text-secondary);
}

/* 상품 검색 */
.manage-product-search-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  padding: var(--space-3) 0 var(--space-2);
}

.manage-product-search-wrap .manage-product-search {
  flex: 1;
  min-width: 0;
}

.manage-product-search {
  padding-left: var(--space-9);
}

/* 상품 행 */
.manage-product-list {
  display: flex;
  flex-direction: column;
}

.manage-product-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border-divider);
  gap: var(--space-2-5);
}

.manage-product-row:last-child {
  border-bottom: none;
}

.manage-product-name {
  font-size: var(--text-14);
  color: var(--text-primary);
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* iOS 스타일 토글 */
.ios-toggle {
  position: relative;
  display: inline-flex;
  width: var(--toggle-w);
  height: var(--toggle-h);
  flex-shrink: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.ios-toggle input {
  opacity: 0;
  width: 0;
  height: 0;
  position: absolute;
}

.ios-toggle-slider {
  position: absolute;
  inset: 0;
  background: var(--control-off);
  border-radius: var(--radius-xl);
  transition: background 0.2s;
}

.ios-toggle-slider::before {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: var(--toggle-knob);
  height: var(--toggle-knob);
  background: var(--text-primary);
  border-radius: var(--radius-circle);
  box-shadow: 0 1px 3px var(--scrim-a30);
  transition: transform 0.2s;
}

.ios-toggle input:checked + .ios-toggle-slider {
  background: var(--brand);
}

.ios-toggle input:checked + .ios-toggle-slider::before {
  transform: translateX(20px);
}


/* 전체 갱신 버튼 로딩 상태 */
.manage-fab-child--refresh.loading {
  opacity: 0.5;
}

/* 상태 텍스트 */
.manage-loading,
.manage-error,
.manage-empty,
.manage-empty-products {
  padding: var(--space-5) var(--space-4);
  font-size: var(--text-14);
  color: var(--text-secondary);
  text-align: center;
}

.manage-error {
  color: var(--danger);
}

/* ─── 결과화면 칼람 CTA ──────────────────────────────────────────────── */

.kalarm-cta-bar {
  padding: var(--space-3) var(--space-4);
  background: var(--bg-canvas);
  border-top: 1px solid var(--border-divider);
  flex-shrink: 0;
}

/* 추가됨 상태에서 체크 SVG가 라벨 왼쪽에 붙는다(디자인 시스템 Button: 16px + 6px).
   display:block 이면 SVG가 베이스라인에 걸려 내려앉으므로 flex 가운데 정렬로 바꿨다.
   글자만 있을 때의 가운데 정렬은 그대로다. (R1 / eb6a2e1e) */
.kalarm-cta-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  width: 100%;
  min-height: var(--control-lg);
  padding: 0 var(--space-5);
  background: var(--brand);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 600;
  border-radius: var(--radius-lg);
  transition: background 0.15s, opacity 0.15s;
}

.kalarm-cta-btn:active:not(:disabled) {
  background: var(--brand-pressed);
}

/* 비활성·등록완료 모두 면을 채우지 않는다 (.btn-primary:disabled와 같은 규칙) */
.kalarm-cta-btn:disabled,
.kalarm-cta-btn.kalarm-cta-added {
  background: none;
  border: 1.5px solid var(--border-control);
  color: var(--text-disabled);
}

/* ─── 칼람 탭 ────────────────────────────────────────────────────────── */

.kalarm-body {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: var(--space-4) var(--space-4) 0;
  background: var(--bg-canvas);
  -webkit-overflow-scrolling: touch;
  padding-bottom: var(--space-6);
}

.kalarm-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-10) var(--space-5);
}

.kalarm-empty-icon {
  opacity: 0.6;
}

.kalarm-empty-text {
  font-size: var(--text-14);
  color: var(--text-secondary);
  text-align: center;
  line-height: 1.6;
}

.kalarm-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* 스와이프-투-딜리트 래퍼 */
.kalarm-swipe-wrapper {
  position: relative;
  border-radius: var(--radius-xl);
  overflow: hidden;
}

/* 칼람 카드 (래퍼 안에서 좌우로 이동) */
.kalarm-card {
  position: relative;
  z-index: 1;
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  overflow: hidden;
}

.kalarm-swipe-delete {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: var(--swipe-action-w);
  background: var(--surface-card);
  color: var(--destructive);
  font-size: var(--text-14);
  font-weight: 600;
  border: none;
  border-left: 1px solid var(--border-divider);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.kalarm-swipe-delete:active {
  background: var(--destructive-a15);
}

.kalarm-card-header {
  display: flex;
  align-items: stretch;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s;
}

.kalarm-card-header:active {
  background: var(--overlay-pressed);
}

.kalarm-card-header--open {
  border-bottom: 1px solid var(--border-strong);
}

/* 벨 섹션 (왼쪽 독립 영역) */
.kalarm-bell-section {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--space-4);
  border-right: 1px solid var(--border-strong);
  flex-shrink: 0;
}

/* 콘텐츠 섹션 (날짜 + 칩) */
.kalarm-content-section {
  flex: 1;
  padding: var(--space-4) var(--space-3) var(--space-4) var(--space-4);
  min-width: 0;
}

.kalarm-card-date {
  display: block;
  font-size: var(--text-17);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.3px;
  margin-bottom: var(--space-2);
}

/* 업체명 칩 */
.kalarm-vendor-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1-5);
}

.kalarm-vendor-chip {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1-5) var(--space-3);
  background: var(--surface-raised);
  color: var(--text-primary);
  font-size: var(--text-12);
  font-weight: 500;
  border-radius: var(--radius-pill);
}

/* 벨 버튼 */
.kalarm-bell-btn {
  background: none;
  border: none;
  padding: var(--space-1-5);
  cursor: pointer;
  color: var(--control-off);
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.2s;
}

.kalarm-bell-btn--on {
  color: var(--brand);
}

.kalarm-bell-btn:active {
  opacity: 0.6;
}

/* 액션 버튼 (조회 / 삭제) */
.kalarm-action-btns {
  display: flex;
  align-items: center;
  padding: var(--space-3) var(--space-4) var(--space-3) var(--space-2);
  flex-shrink: 0;
}

.kalarm-action-btn--search {
  background: var(--brand);
  border: none;
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-13);
  font-weight: 600;
  color: var(--text-primary);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  white-space: nowrap;
}

.kalarm-action-btn--search:active {
  background: var(--brand-pressed);
}

.kalarm-action-btn--search:disabled {
  opacity: 0.4;
}

/* 아코디언 */
.kalarm-accordion-body {
  background: var(--bg-canvas);
}

.kalarm-accordion-empty {
  padding: var(--space-4);
  font-size: var(--text-13);
  color: var(--text-tertiary);
  text-align: center;
}

/* 업체 탭 (아코디언 내) */
.kalarm-vendor-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border-strong);
  padding: 0 var(--space-3);
  overflow-x: auto;
  scrollbar-width: none;
}

.kalarm-vendor-tabs::-webkit-scrollbar {
  display: none;
}

.kalarm-vendor-tab {
  padding: var(--space-2-5) var(--space-3);
  font-size: var(--text-13);
  font-weight: 500;
  color: var(--text-secondary);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s;
}

.kalarm-vendor-tab.active {
  color: var(--text-primary);
  border-bottom-color: var(--brand);
}

.kalarm-vendor-panel {
  padding: var(--space-1) 0;
}

/* 상품 목록 (아코디언 내) */
.kalarm-product-list {
  padding: 0;
}

.kalarm-product-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-divider);
}

.kalarm-product-row:last-child {
  border-bottom: none;
}

.kalarm-product-name {
  font-size: var(--text-14);
  color: var(--text-primary);
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ─── 히스토리 탭 ────────────────────────────────────────────────── */

.history-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--space-3) var(--space-4);
}

.history-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-15) var(--space-5);
}

.history-empty-text {
  font-size: var(--text-14);
  color: var(--text-secondary);
  text-align: center;
  line-height: 1.6;
  /* 빈 상태 문구는 줄바꿈을 허용한다(ellipsis 금지).
     왜 비었는지가 잘리면 이 자리의 존재 이유가 사라진다. */
  white-space: pre-line;
  word-break: keep-all;
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2-5);
}

/* 히스토리 카드 */
.history-card {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  padding: var(--space-4) var(--space-4);
  cursor: pointer;
  transition: background 0.12s;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
}

.history-card:active {
  background: var(--overlay-pressed);
}

.history-card-fired {
  font-size: var(--text-15);
  font-weight: 600;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.history-card-right {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
}

.history-card-count-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--brand);
}

.history-card-count {
  font-size: var(--text-14);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.history-card-push {
  display: flex;
  align-items: center;
  color: var(--brand);
}

.history-card-push--muted {
  color: var(--text-disabled);
}

/* ─── 히스토리 상세 모달 ─────────────────────────────────────────── */

.history-modal {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-5);
}

.history-modal.hidden {
  display: none;
}

.history-modal-backdrop {
  position: absolute;
  inset: 0;
  background: var(--scrim);
}

.history-modal-box {
  position: relative;
  width: 100%;
  max-width: 400px;
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-height: 72vh;
}

/* 모달 헤더: fired_at + 닫기 버튼 */
.history-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4) var(--space-3);
  border-bottom: 1px solid var(--border-strong);
  flex-shrink: 0;
}

.history-modal-meta-fired {
  font-size: var(--text-17);
  font-weight: 700;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.3px;
}

.history-modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-md);
  height: var(--control-md);
  color: var(--text-secondary);
  flex-shrink: 0;
}

.history-modal-close:active {
  opacity: 0.6;
}

/* ── 칼람 목록: 스크롤 컨테이너 ── */
#history-modal-kalarm-list {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  min-height: 0; /* flex 자식 스크롤 활성화 필수 */
}

/* ── 칼람 카드 구분선 ── */
.history-modal-kalarm-card + .history-modal-kalarm-card {
  border-top: 1px solid var(--border-strong);
}

/* ── 1뎁스: 칼람 카드 헤더 레이아웃 재활용 ── */
.history-modal-summary {
  display: flex;
  align-items: stretch;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s;
  flex-shrink: 0;
}

.history-modal-summary:active {
  background: var(--overlay-pressed);
}

/* 콘텐츠 섹션 */
.history-modal-content-section {
  flex: 1;
  padding: var(--space-4) var(--space-3) var(--space-4) var(--space-4);
  min-width: 0;
}

/* chevron 섹션 */
.history-modal-chevron-section {
  display: flex;
  align-items: center;
  padding: 0 var(--space-4);
  flex-shrink: 0;
}

.history-modal-chevron {
  display: flex;
  align-items: center;
  color: var(--text-tertiary);
  transition: transform 0.2s;
}

.history-modal-chevron--open {
  transform: rotate(180deg);
}

/* ── 2뎁스: 상품 결과 ── */
.history-modal-products {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  border-top: 1px solid var(--border-strong);
}

.history-modal-products.hidden {
  display: none;
}

/* 업체 그룹 */
.history-vendor-group {
  padding: 0;
}

.history-vendor-group + .history-vendor-group {
  margin-top: var(--space-2);
}

.history-vendor-group-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2-5) var(--space-4) var(--space-1-5);
  background: var(--overlay-subtle);
}

.history-vendor-group-name {
  font-size: var(--text-13);
  font-weight: 600;
  color: var(--text-secondary);
}

/* source 뱃지 */
.history-source-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-11);
  font-weight: 500;
  background: var(--brand-a18);
  color: var(--brand);
}

/* 상품 row */
.history-modal-product-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2-5) var(--space-4);
  border-bottom: 1px solid var(--border-divider);
  gap: var(--space-3);
}

.history-modal-product-row:last-child {
  border-bottom: none;
}

.history-modal-product {
  font-size: var(--text-14);
  color: var(--text-primary);
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.history-modal-empty {
  padding: var(--space-5) var(--space-4);
  font-size: var(--text-14);
  color: var(--text-tertiary);
  text-align: center;
}

/* 가용성 뱃지 */
.history-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-12);
  font-weight: 600;
  flex-shrink: 0;
}

.history-badge--available {
  background: var(--success-fill);
  color: var(--success);
}

.history-badge--unavailable {
  background: var(--danger-fill);
  color: var(--danger);
}

.history-badge--unknown {
  background: var(--neutral-fill);
  color: var(--text-secondary);
}

/* 칼람 섹션 구분 */
.history-kalarm-section {
  margin-bottom: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-strong);
}

.history-kalarm-section:first-child {
  padding-top: 0;
  border-top: none;
}

.history-kalarm-section:last-child {
  margin-bottom: 0;
}

/* 히스토리 모달 2뎁스 — kalarm 그룹 */
.history-kalarm-group {
  background: var(--overlay-subtle);
  border-radius: var(--radius-lg);
  padding: var(--space-3);
  margin-bottom: var(--space-2-5);
}

.history-kalarm-group-date {
  font-size: var(--text-11);
  font-weight: 600;
  color: var(--text-secondary);
  padding-bottom: var(--space-1-5);
  letter-spacing: 0.02em;
}

/* kalarm 그룹 내 상품 없음 표시 */
.history-kalarm-no-products {
  padding: var(--space-2-5) var(--space-4) var(--space-3);
  font-size: var(--text-13);
  color: var(--text-disabled);
}

/* 모달 summary 날짜 — kalarm-card-date보다 작게, 보조 정보 */
.history-modal-summary-date {
  display: block;
  font-size: var(--text-13);
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: 0;
  margin-bottom: var(--space-2);
}

/* ── 2뎁스 테이블 ── */
.history-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.history-table-header {
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  background: var(--overlay-subtle);
  border-bottom: 1px solid var(--border-strong);
}

.history-table-header-cell {
  font-size: var(--text-11);
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.history-table-header-cell:first-child {
  flex: 0 0 44%;
}

.history-table-header-cell:nth-child(2) {
  flex: 1;
  padding-left: var(--space-2);
}

.history-table-header-cell:last-child {
  flex: 0 0 56px;
  text-align: right;
}

.history-table-row {
  display: flex;
  align-items: center;
  padding: var(--space-2-5) var(--space-4);
  border-bottom: 1px solid var(--border-divider);
}

.history-table-row:last-child {
  border-bottom: none;
}

.history-table-cell {
  font-size: var(--text-13);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.history-table-cell:first-child {
  flex: 0 0 44%;
  font-weight: 500;
}

.history-table-cell:nth-child(2) {
  flex: 1;
  padding-left: var(--space-2);
  color: var(--text-primary);
}

.history-table-cell:last-child {
  flex: 0 0 56px;
  display: flex;
  justify-content: flex-end;
}


/* ─── 터치 타겟 히트박스 확장 ────────────────────────────────────────────
 *
 * iOS HIG 44pt / Material 48dp 최소 터치 타겟을 만족시키되, **시각 크기는
 * 1px도 바꾸지 않는다**. 투명한 ::before를 절대배치로 덮어 히트박스만 넓힌다.
 * (position:absolute 라 레이아웃에서 빠지므로 flex gap·간격에 영향 없음)
 *
 * 규칙
 *   1. 배경/테두리를 주지 않는다 — 보이는 픽셀이 변하면 안 된다
 *   2. 확장 폭은 "인접한 다른 터치 타겟과 겹치지 않는 선"까지만.
 *      아래 값들은 에뮬레이터(412x915 CSS px) 실측 간격 기준으로 정했다.
 *   3. 부모의 overflow:hidden 안쪽에 머물러야 한다(잘리면 히트도 잘린다)
 *
 * 확장 대상이 아닌 것 — 이미 44px 이상이라 손대지 않는다:
 *   - .sheet-inline-item 의 체크박스: <label> 행 전체(370x50)가 타겟
 *   - .cal-day-num: 클릭 핸들러가 closest('.cal-cell') → 셀(49x44)이 타겟
 * ------------------------------------------------------------------- */

/* 결과 화면 상단 액션바: ← 뒤로(60x36), ↺ 새로고침(30x36)
   좌우로 제목(비인터랙티브)까지 100px 이상 여유 → ±7px 안전 */
.btn-sm {
  position: relative;
}
.btn-sm::before {
  content: '';
  position: absolute;
  top: -4px;
  bottom: -4px;
  left: -7px;
  right: -7px;
}

/* 날짜 탭(100x37): 가로는 이미 충분, 탭 간 gap이 8px뿐이라 세로만 확장.
   ⚠ .date-tab은 1px 테두리가 있고 절대배치 ::before의 기준은 **패딩 박스**라
   inset 값이 테두리 두께만큼 깎인다(-4px → 실측 43.4px로 44 미달이었음).
   ±6px로 잡아 실측 47px 확보. .date-tabs 패딩 박스(상10/하14) 안쪽이라 잘리지 않고,
   탭은 한 줄로만 배치돼 세로 인접 타겟이 없다 */
.date-tab {
  position: relative;
}
.date-tab::before {
  content: '';
  position: absolute;
  top: -6px;
  bottom: -6px;
  left: 0;
  right: 0;
}

/* 예약 불가 접기/펼치기 토글(380x43): 1px 모자람.
   ⚠ 아래쪽은 조상 .vendor-card의 overflow:hidden에 잘려 확장이 먹지 않는다.
   → 위로만 3px 확장(실측 46px). 바로 위 .product-row는 클릭 핸들러가 없어
   가로채는 터치가 없다 */
.unavailable-toggle {
  position: relative;
}
.unavailable-toggle::before {
  content: '';
  position: absolute;
  top: -3px;
  bottom: 0;
  left: 0;
  right: 0;
}

/* 스케줄 카드·업체 행의 "삭제"(38x32).
   두 버튼이 세로로 25px 간격 → ±6px면 13px 남아 겹치지 않는다.
   .schedule-card가 overflow:hidden이지만 확장분은 카드 안쪽에 머문다 */
.schedule-card-delete,
.vendor-row-delete {
  position: relative;
}
.schedule-card-delete::before,
.vendor-row-delete::before {
  content: '';
  position: absolute;
  top: -6px;
  bottom: -6px;
  left: -4px;
  right: -4px;
}

/* 관리 탭 갱신 버튼(36x36) — 행 카드 안쪽, 좌우에 구분선까지 여유 있음 */
.manage-sync-btn {
  position: relative;
}
.manage-sync-btn::before {
  content: '';
  position: absolute;
  top: -4px;
  bottom: -4px;
  left: -4px;
  right: -4px;
}

/* iOS 스타일 토글(48x28) — 가로는 충분, 세로만 ±8px.
   .ios-toggle은 이미 position:relative 이므로 ::before만 추가한다.
   슬라이더(.ios-toggle-slider)보다 먼저 그려져 시각적으로 가리지 않는다 */
.ios-toggle::before {
  content: '';
  position: absolute;
  top: -8px;
  bottom: -8px;
  left: 0;
  right: 0;
}

/* 칼람 카드 벨 토글(40x40) — 카드 왼쪽 독립 영역.
   .kalarm-bell-section 좌우 패딩 16px / 헤더 세로 여백 24px 안쪽이라 ±2px는 안전.
   카드 헤더 클릭(아코디언)과 겹치지만, 헤더 핸들러가
   e.target.closest('.kalarm-bell-btn')로 먼저 걸러내므로 의도대로 동작한다 */
.kalarm-bell-btn {
  position: relative;
}
.kalarm-bell-btn::before {
  content: '';
  position: absolute;
  inset: -2px;
}

/* 칼람 카드 "조회" 버튼(52x35) — 가로는 충분, 세로만 ±5px.
   .kalarm-action-btns의 상/하 패딩 12px 안쪽이라 잘리지 않고,
   위아래 카드의 같은 버튼과는 65px 떨어져 있어 겹치지 않는다 */
.kalarm-action-btn--search {
  position: relative;
}
.kalarm-action-btn--search::before {
  content: '';
  position: absolute;
  top: -5px;
  bottom: -5px;
  left: 0;
  right: 0;
}

/* 기록 상세 모달 닫기(32x32) — 모달 헤더(372x59) 안쪽.
   좌측 fired_at 텍스트는 x=170에서 끝나 확장분(x≥338)과 만나지 않는다 */
.history-modal-close {
  position: relative;
}
.history-modal-close::before {
  content: '';
  position: absolute;
  inset: -6px;
}

/* ─── 오류·복구 UI (릴리즈 38a218e2 / FE-03·05·06·07·16) ─────────────────────
 *
 * 범위를 일부러 좁게 잡았다. 레이아웃·글꼴·색 토큰은 건드리지 않고, 기존 화면에
 * "없던 요소"(토스트 / 다시 시도 버튼 / 오류 배너 / 알림 안내)만 추가한다.
 * 기존 셀렉터를 재정의하지 않으므로 현재 화면 렌더에는 영향이 없다.
 * iOS·Android 공용이고, safe-area는 기존 규약(max(env, var(--safe-*)))을 그대로 쓴다.
 * ──────────────────────────────────────────────────────────────────────── */

/* 토스트 — 탭바(z-index 50) · 시트(1100) 위에 떠야 하므로 가장 높게 둔다 */
.kalarm-toast-host {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(76px + var(--safe-area-bottom));
  z-index: 2000;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-4);
  pointer-events: none;
}

.kalarm-toast {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  max-width: 100%;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--bg-canvas-a96);
  box-shadow: 0 6px 20px var(--scrim-a40);
  pointer-events: auto;
}

.kalarm-toast--error {
  border: 1px solid var(--danger-a50);
}

.kalarm-toast-text {
  flex: 1;
  font-size: var(--text-13);
  line-height: 1.5;
  color: var(--text-primary);
}

.kalarm-toast-action {
  flex-shrink: 0;
  padding: var(--space-1-5) var(--space-3);
  border: 0;
  border-radius: var(--radius-md);
  background: var(--brand);
  color: var(--text-primary);
  font-size: var(--text-13);
  font-weight: 600;
  font-family: inherit;
}

/* 다시 시도 블록 (칼람 / 기록 / 관리 / 상품 시트 공용) */
.kalarm-retry-detail {
  font-size: var(--text-13);
  line-height: 1.6;
  color: var(--text-tertiary);
  text-align: center;
  white-space: pre-line;
}

.kalarm-retry-btn {
  padding: var(--space-2-5) var(--space-5);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-lg);
  background: transparent;
  color: var(--text-primary);
  font-size: var(--text-14);
  font-weight: 600;
  font-family: inherit;
}

/* 관리 화면·상품 시트처럼 가운데 정렬 래퍼가 없는 곳에서 쓰는 범용 래퍼 */
.kalarm-retry-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-6) var(--space-4);
}

/* 상품 시트 안의 오류 문구 */
.sheet-inline-empty-text {
  font-size: var(--text-14);
  color: var(--text-tertiary);
  text-align: center;
}

/* 조회 결과 상단 오류/부분실패 배너 */
.results-error-banner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--danger-a45);
  border-radius: var(--radius-lg);
  background: var(--danger-a10);
}

.results-error-text {
  flex: 1;
  font-size: var(--text-13);
  line-height: 1.5;
  color: var(--danger);
}

.results-error-retry {
  flex-shrink: 0;
  padding: var(--space-1-5) var(--space-3);
  border: 0;
  border-radius: var(--radius-md);
  background: var(--brand);
  color: var(--text-primary);
  font-size: var(--text-13);
  font-weight: 600;
  font-family: inherit;
}

/* 알림 권한 안내 (칼람 탭 상단) */
.kalarm-notice {
  margin: var(--space-3) var(--space-4) 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--brand-a45);
  border-radius: var(--radius-lg);
  background: var(--brand-a10);
}

.kalarm-notice-text {
  font-size: var(--text-13);
  line-height: 1.5;
  color: var(--text-primary);
}

/* ═══════════════════════════════════════════════════════════════════════
 * 로그 탭 — 실제로 간 캠핑 기록 (61d901fd / R1·R6·R8·R9)
 * ═══════════════════════════════════════════════════════════════════════
 * 신규 부품 6개(LogCard · PhotoGrid · PhotoAddTile · PhotoCarousel ·
 * UploadProgress · TextArea)는 디자인 시안의 부품 시트를 그대로 구현한 것이다.
 *
 * 공용 부품은 **다시 만들지 않고 그대로 쓴다** — Header(.ios-header),
 * BottomSheet(.bottom-sheet/.sheet-*), Calendar(.cal-*),
 * EmptyState(.kalarm-empty/.kalarm-retry-btn, app.js의 kalarmRenderRetry).
 * 시안의 그 부품들 치수는 디자인 시스템 확정값이고 지금 코드값과 몇 px 다르지만,
 * 여기서만 확정값을 쓰면 **같은 앱의 다른 탭과 로그 탭이 달라 보인다.**
 * 확정값 이행은 전 화면을 같이 바꾸는 별도 릴리즈 몫이다.
 *
 * 두 OS 동일 보장 — 이 절에서 직접 그리는 것들
 *   - 사진 비율: aspect-ratio 로 고정하고 object-fit: cover 로 같은 영역을 자른다
 *   - 페이저: scroll-snap. 플랫폼 페이저 컨트롤(UIPageControl/ViewPager)을 쓰지 않고
 *     점 인디케이터 대신 숫자 카운터를 올린다(30장이면 점이 들어가지 않는다)
 *   - 진행 바: div 두 개. 플랫폼 스피너·인디케이터를 쓰지 않는다
 *   - 날짜 선택: input[type=date] 금지 — 두 OS가 서로 다른 OS 피커를 띄운다
 *   - 정렬: 길게 눌러 끌기에 기대지 않는다(두 WebView의 터치 가로채기가 다르다).
 *     대표 지정·순서·삭제는 타일을 눌러 뜨는 BottomSheet 로 받는다
 * ═══════════════════════════════════════════════════════════════════════ */

/* ─── 뷰 안의 두 화면(피드 · 상세) ─────────────────────────────────────── */

.log-screen {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.log-screen.hidden {
  display: none;
}

/* 헤더 오른쪽 '추가' — 모양은 Header 부품 그대로, 자리만 오른쪽 끝 */
.log-header-action {
  margin-left: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-md);
  height: var(--control-md);
  margin-right: calc(-1 * var(--space-2-5));
  border-radius: var(--radius-md);
  color: var(--brand);
  flex-shrink: 0;
}

.log-header-action--off {
  visibility: hidden;   /* 자리는 남긴다 — 헤더가 흔들리지 않게 (QA D4) */
}

.log-header-action:active {
  background: var(--brand-a10);
}

/* 헤더 오른쪽 묶음 — 정렬 칩 + '추가' (R19). 오른쪽 끝 정렬은 묶음이 맡는다 */
.log-header-actions {
  margin-left: auto;
  margin-right: calc(-1 * var(--space-2-5));
  display: flex;
  align-items: center;
  gap: var(--space-0-5);   /* 칩과 ＋ 사이 — 시안 값 */
  flex-shrink: 0;
}

.log-header-actions .log-header-action {
  margin: 0;
}

/* 정렬 칩 — 보이는 알약은 작고, 누르는 자리는 44px */
.log-sort-btn {
  display: flex;
  align-items: center;
  min-height: var(--control-md);
  padding: 0 var(--space-0-5);
  color: var(--text-primary);
}

.log-sort-btn.hidden {
  display: none;
}

.log-sort-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1-5) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-card);
  color: var(--text-primary);
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
  white-space: nowrap;
}

.log-sort-btn:active .log-sort-chip {
  background: var(--surface-pressed);
}

.log-sort-icon {
  width: var(--icon-inline);    /* 13px 글자 옆 아이콘 — .log-detail-place-icon 과 같다 */
  height: var(--icon-inline);
  display: block;
}

.log-icon-plus {
  width: var(--icon-lg);
  height: var(--icon-lg);
  display: block;
}

.log-icon-md {
  width: var(--icon-md);
  height: var(--icon-md);
  display: block;
  flex-shrink: 0;
}

.log-icon-sm {
  width: var(--icon-sm);
  height: var(--icon-sm);
  display: block;
  flex-shrink: 0;
}

/* 13px — '칼람에서 불러왔어요' 줄의 작은 연결 아이콘. 글자(12px)보다 조금 크다 */
.log-icon-xs {
  width: var(--icon-badge);
  height: var(--icon-badge);
  display: block;
  flex-shrink: 0;
}

/* 접근성용 숨김 라벨 — display:none 이면 스크린리더도 못 읽는다 */
.log-vh {
  position: absolute;
  width: var(--hairline);
  height: var(--hairline);
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ─── 피드 (S12) ───────────────────────────────────────────────────────── */

.log-feed-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0 var(--space-5) var(--space-4);
  display: flex;
  flex-direction: column;
}

.log-feed-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* ─── LogCard (신규) ───────────────────────────────────────────────────── */

.log-card {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  overflow: hidden;
  color: var(--text-primary);
  padding: 0;
}

.log-card:active {
  background: var(--surface-pressed);
}

/* 커버는 16:9 고정. 폭이 줄면 높이도 같이 줄어 두 OS·모든 폭에서 같은 영역을 보여준다 */
.log-card-cover {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--surface-raised);
  display: flex;
  align-items: center;
  justify-content: center;
}

.log-photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* 사진이 아직 없는 로그의 커버 자리 */
.log-photo-blank {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1-5);
  color: var(--text-disabled);
}

.log-photo-blank-icon {
  width: var(--icon-placeholder);   /* 커버(16:9) 안의 빈 자리 표시. icon-lg(22)는 큰 면에서 작아 보인다 */
  height: var(--icon-placeholder);
  display: block;
}

/* 장수 배지 — 인라인 SVG + 숫자. 이모지·플랫폼 심볼을 쓰지 않는다 */
.log-count-badge {
  position: absolute;
  right: var(--space-2-5);
  bottom: var(--space-2-5);
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  /* 사진 위 배지는 전부 불투명 bg-base 바닥이다 — 밝은 사진에서도 글자가 읽힌다 (R14) */
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: var(--text-11);
  font-weight: 700;
  letter-spacing: 0.4px;
  line-height: 1.5;
}

.log-count-badge svg {
  width: var(--icon-xs);   /* 11px 글자 옆에 서는 아이콘. icon-sm(16)은 글자보다 커 보인다 */
  height: var(--icon-xs);
  display: block;
}

.log-count-badge span {
  font-variant-numeric: tabular-nums;
}

.log-card-text {
  padding: var(--space-3) var(--space-4) var(--panel-pad);
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
}

/* 캠핑장 이름은 잘리면 안 되는 글자다 — ellipsis 대신 줄바꿈 */
.log-card-title {
  font-size: var(--text-15);
  font-weight: 700;
  line-height: 1.4;
  color: var(--text-primary);
  word-break: keep-all;
}

.log-card-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-secondary);
}

.log-card-date {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.log-card-sep {
  flex-shrink: 0;
  width: var(--hairline);
  height: var(--card-sep-h);
  background: var(--border-control);
}

/* 사이트 이름만 생략한다. flex:1 과 min-width:0 을 같이 줘야 ellipsis가 걸린다 */
.log-card-site {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.log-card-body {
  font-size: var(--text-14);
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-secondary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ─── 불러오는 중 골격 (S12c) ─────────────────────────────────────────── */

.log-skel-card {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  overflow: hidden;
}

.log-skel-cover {
  aspect-ratio: 16 / 9;
  background: var(--surface-raised);
}

.log-skel-text {
  padding: var(--space-3) var(--space-4) var(--panel-pad);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.log-skel-line {
  height: var(--skel-line-h);
  border-radius: var(--radius-sm);
  background: var(--overlay-pressed);
}

/* 제목 줄만 조금 높다. 폭은 % 라서 기기 폭에 따라 같이 줄어든다 */
.log-skel-line--title {
  height: var(--skel-line-title-h);
  width: 42%;
}

.log-skel-line--meta {
  width: 56%;
}

.log-skel-line--body {
  width: 100%;
}

/* ─── 상세 (S13) ───────────────────────────────────────────────────────── */

.log-detail-header {
  flex-shrink: 0;
  padding: var(--safe-area-top) var(--space-3) 0;
  background: var(--bg-canvas);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.log-detail-actions {
  display: flex;
  align-items: center;
  gap: var(--space-0-5);
}

.log-icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-md);
  height: var(--control-md);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  flex-shrink: 0;
}

.log-icon-btn--muted {
  color: var(--text-secondary);
}

.log-icon-btn:active {
  background: var(--overlay-pressed);
}

/* 헤더만 고정, 사진과 본문은 한 스크롤 안에 (R25 / 시안 v10) — 사진이 1:1 로 커져
   본문 영역이 좁아졌다 */
.log-detail-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
}

/* ─── PhotoCarousel (신규) ─────────────────────────────────────────────── */

.log-carousel {
  position: relative;
  flex-shrink: 0;
}

/* 한 장 단위로 멈춘다. 자동 재생·전환 애니메이션 없음.
   스크롤바는 두 OS 모두 숨긴다(엔진마다 기본값이 다르다). */
.log-carousel-track {
  display: flex;
  overflow-x: auto;
  /* 가로는 페이저, 세로 드래그는 페이지 스크롤로 넘긴다 — 두 WebView 같게 명시 */
  touch-action: pan-x pan-y;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.log-carousel-track::-webkit-scrollbar {
  display: none;
}

.log-carousel-slide {
  flex: 0 0 100%;
  cursor: zoom-in;
  outline: none;
  scroll-snap-align: start;
  aspect-ratio: 1 / 1;   /* 정방형, 가운데 크롭(R25 PM 요청) */
  background: var(--surface-raised);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 점 인디케이터를 쓰지 않는다 — 30장이면 점이 들어가지 않고,
   숫자는 '끝이 어디인지'까지 알려준다 */
.log-carousel-counter {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);   /* 우하단 (시안 v10) */
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--bg-base);   /* 사진 위 배지 — 불투명 바닥 (R14) */
  color: var(--text-primary);
  font-size: var(--text-12);
  font-weight: 600;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
}

.log-detail-text {
  flex-shrink: 0;
  padding: var(--space-4) var(--space-5) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.log-detail-title {
  font-size: var(--text-24);
  font-weight: 700;
  line-height: 1.2;
  color: var(--text-primary);
  word-break: keep-all;
}

.log-detail-meta {
  font-size: var(--text-14);
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.log-detail-place {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1-5);
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-secondary);
}

.log-detail-place-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  height: var(--line-box-13);   /* 13px/1.45 첫 줄 높이 — 아이콘이 첫 줄 가운데에 선다 */
  color: var(--text-tertiary);
}

.log-detail-place-icon svg {
  width: var(--icon-inline);    /* 13px 글자 옆 아이콘 */
  height: var(--icon-inline);
  display: block;
}

.log-detail-divider {
  height: var(--hairline);
  background: var(--overlay-pressed);
  margin: var(--space-2) 0;
}

.log-detail-review {
  font-size: var(--text-15);
  font-weight: 400;
  line-height: 1.5;
  color: var(--text-primary);
  white-space: pre-line;
}

/* ─── 작성·수정 화면 (S14 · S18) ──────────────────────────────────────── */
/* 탭바(z-index 900)와 시트(1001) 사이에 둔다 — 탭바는 덮고 시트에는 덮인다 */

.log-compose {
  position: fixed;
  inset: 0;
  z-index: 950;
  background: var(--bg-canvas);
  display: flex;
  flex-direction: column;
}

.log-compose.hidden {
  display: none;
}

.log-compose-header {
  flex-shrink: 0;
  padding: var(--safe-area-top) var(--space-2) 0;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--overlay-pressed);
}

.log-compose-side {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--header-side-min-w);
  height: var(--control-md);
  padding: 0 var(--space-2);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: var(--text-15);
  font-weight: 400;
}

.log-compose-side--save {
  color: var(--brand-text);   /* 글자용 주황 — '저장' · 업로드 중 '목록으로' (R17-4) */
  font-weight: 600;
}

/* 저장하는 동안 — 비활성을 opacity로 말하지 않는다(글자까지 흐려진다) */
.log-compose-side:disabled {
  color: var(--text-disabled);
}

.log-compose-title {
  flex: 1 1 auto;
  min-width: 0;
  text-align: center;
  font-size: var(--text-15);
  font-weight: 700;
  line-height: 1.4;
  color: var(--text-primary);
}

/* 이 화면의 스크롤 컨테이너. 키보드가 올라올 때 iOS가 페이지를 밀지 않게 하는
   조건이다(STYLE_GUIDE 5절 (1)) */
.log-compose-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--space-4) var(--space-5) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.log-compose-body.hidden {
  display: none;
}

.log-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.log-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-2);
}

.log-section-label {
  font-size: var(--text-13);
  font-weight: 600;
  letter-spacing: 0.5px;
  line-height: 1.45;
  color: var(--text-secondary);
}

/* 사진 헤더 (R17-3) — 왼쪽은 늘 '사진 n / 30', 오른쪽은 순서 상태 */
.log-photo-head {
  align-items: center;
  min-height: var(--space-6);
}

.log-photo-title {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

/* 'n / 30' 카운터가 한도를 상시로 말한다 — 29장에서 경고를 띄우지 않는다 */
.log-photo-count {
  font-size: var(--text-12);
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

.log-photo-order {
  display: flex;
  align-items: center;
  gap: var(--space-0-5);   /* '·' 뒤 글자 버튼과의 틈 — 시안 값 */
  font-size: var(--text-12);
  font-weight: 600;
  line-height: 1.4;
  color: var(--text-secondary);
}

/* 글자 버튼이지만 터치는 44px — 음수 여백으로 줄 높이를 늘리지 않는다.
   사진 헤더 '찍은 순서로'와 사이트·위치 안내 줄 '되돌리기'(R22)가 같이 쓴다 */
.log-photo-order-btn,
.log-text-btn {
  display: flex;
  align-items: center;
  min-height: var(--control-md);
  padding: 0 var(--space-1);
  margin: calc(-1 * var(--space-3)) calc(-1 * var(--space-1));
  color: var(--brand-text);
  font-size: var(--text-12);
  font-weight: 600;
  line-height: 1.4;
}

.log-text-btn.hidden {
  display: none;
}

.log-photo-order-btn:disabled {
  color: var(--text-disabled);
  cursor: default;
}

/* ─── PhotoGrid · PhotoAddTile (신규) ─────────────────────────────────── */
/* 열 수는 3 고정이고 타일만 줄어든다. 폭에 따라 2열로 바뀌지 않는다 —
   스캔 단위가 폭에 따라 달라지면 안 된다. 폭 360에서도 타일이 101px로
   터치 하한 44px에 여유가 있다. */

.log-photo-grid {
  position: relative;   /* 끌어 옮길 때 점선 빈칸의 기준 */
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
}

.log-tile {
  position: relative;
  aspect-ratio: 1 / 1;
  padding: 0;
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  color: var(--text-disabled);
  transition: opacity var(--dur-state);
}

.log-tile:active {
  background: var(--surface-pressed);
}

.log-tile-icon {
  width: var(--space-6);   /* 24px — 타일(1:1) 안의 빈 자리 표시 */
  height: var(--space-6);
  display: block;
}

/* 타일 전체가 버튼이다. 타일 안에 작은 × 를 두지 않는다(44px을 못 지킨다) */
.log-tile-add {
  position: relative;
  aspect-ratio: 1 / 1;
  padding: 0;
  border-radius: var(--radius-md);
  background: none;
  border: 1.5px dashed var(--border-control);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  color: var(--text-secondary);
}

/* 비활성은 테두리를 유지하고 글자만 흐리게 — 면을 채우지 않는다(디자인 시스템 규칙) */
.log-tile-add:disabled,
.log-tile-add[aria-disabled="true"] {
  color: var(--text-disabled);
  cursor: default;
}

.log-tile-add svg {
  width: var(--icon-lg);
  height: var(--icon-lg);
  display: block;
}

.log-tile-add-label {
  font-size: var(--text-12);
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
}

/* 대표 배지 */
.log-tile-cover-badge {
  position: absolute;
  left: var(--space-1-5);
  bottom: var(--space-1-5);
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  border: none;
  background: var(--bg-base);   /* 사진 위 배지 — 불투명 바닥 (R14) */
  color: var(--brand-text);     /* 글자용 주황 (R17-4) */
  font-size: var(--text-11);
  font-weight: 700;
  letter-spacing: 0.4px;
  line-height: 1.5;
}

/* 타일 + × 를 감싸는 칸. 길게 눌러 들 때 iOS 콜아웃·글자 선택이 끼어들지 않게 */
.log-tile-cell {
  position: relative;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.log-tile-cell > .log-tile {
  width: 100%;
}

/* × 칩 (R17-1) — 터치는 타일 우상단 44×44 안쪽(옆 타일을 먹지 않는다),
   보이는 것은 22px 원. 대표 배지(좌하단)와 겹치지 않는다 */
.log-tile-x {
  position: absolute;
  top: 0;
  right: 0;
  width: var(--control-md);
  height: var(--control-md);
  padding: 0;
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
}

.log-tile-x-chip {
  margin: var(--space-1) var(--space-1) 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--icon-lg);
  height: var(--icon-lg);
  border-radius: var(--radius-circle);
  background: var(--bg-base);
  color: var(--text-primary);
}

.log-tile-x-chip svg {
  width: var(--icon-xs);
  height: var(--icon-xs);
  display: block;
}

/* ─── 끌어서 순서 바꾸기 (S18d / R17-2) ─────────────────────────────── */
/* 옮기는 동안은 × 를 숨기고, 나머지 타일은 transform 으로만 비킨다 */
.log-photo-grid--dragging .log-tile-x {
  display: none;
}

.log-photo-grid--dragging .log-tile-cell {
  transition: transform var(--dur-state);
}

/* 들린 타일 — 손가락을 바로 따라간다(전환 없음). 크기는 inline transform 의 scale */
.log-photo-grid--dragging .log-tile-cell--lifted {
  z-index: 2;
  transition: none;
  opacity: 0.95;
  box-shadow: var(--shadow-overlay);
  border-radius: var(--radius-md);
}

/* 놓았을 때 빈칸으로 / 취소했을 때 원래 자리로 0.15s 안착 */
.log-tile-cell--settling {
  z-index: 2;
  transition: transform var(--dur-state);
}

/* 놓일 자리를 미리 보여 주는 점선 빈칸. 위치·크기는 들 때 잰 값으로 JS 가 준다 */
.log-tile-slot {
  position: absolute;
  left: 0;
  top: 0;
  border: 1.5px dashed var(--border-control);
  border-radius: var(--radius-md);
  background: var(--overlay-subtle);
  pointer-events: none;
  transition: transform var(--dur-state);
}

/* 사진 시트를 끌어내리는 동안은 시트 기본 전환을 끈다 */
.log-sheet--dragging {
  transition: none;
}

/* 지금 시트를 열어 둔 타일 */
.log-tile--selected {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

/* 담기가 끝나 한 번에 들어온 타일 — opacity 만 바뀐다(.log-tile 의 transition).
   자리를 밀어내는 애니메이션은 없다 (R15) */
.log-tile--enter {
  opacity: 0;
}

/* ─── 사진 담는 중 (S14d / R15) ───────────────────────────────────────── */
/* 추가 타일 자리가 그리드 전폭 한 줄로 바뀐다. 저장 뒤 '올리기'(UploadProgress)와
   다른 부품이다 — 이건 작성 폼 안에서 사진을 고르고 준비하는 단계다.
   남은 시간·"거의 다 됐어요" 같은 추정 문구를 쓰지 않는다. */
.log-adding {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: var(--space-2-5);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-card);
  border-radius: var(--radius-lg);
}

.log-adding-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.log-adding-text {
  flex: 1;
  min-width: 0;
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* 글자 버튼이지만 터치 영역은 44px — 음수 여백으로 줄 높이를 늘리지 않는다 */
.log-adding-stop {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-md);
  padding: 0 var(--space-3);
  margin: calc(-1 * var(--space-2-5)) calc(-1 * var(--space-2)) calc(-1 * var(--space-2-5)) 0;
  border: none;
  border-radius: var(--radius-md);
  background: none;
  color: var(--text-secondary);
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
}

.log-adding-stop:active {
  background: var(--overlay-pressed);
}

.log-adding-bar {
  display: block;
  height: var(--log-progress-h);
  border-radius: var(--radius-xs);
  background: var(--overlay-pressed);
  overflow: hidden;
}

.log-adding-bar-fill {
  display: block;
  height: var(--log-progress-h);
  border-radius: var(--radius-xs);
  background: var(--brand);
}

/* 받는 중(브리지 수신) — 몇 장·얼마나 남았는지 모르니 진행률 대신 흐르는 막대.
   transform 만 움직인다. 움직임을 줄인 설정에서는 멈춘 막대로 */
.log-adding-bar--indeterminate .log-adding-bar-fill {
  width: 40%;
  animation: log-indeterminate 1.2s ease-in-out infinite;
}

@keyframes log-indeterminate {
  from { transform: translateX(-100%); }
  to { transform: translateX(250%); }
}

@media (prefers-reduced-motion: reduce) {
  .log-adding-bar--indeterminate .log-adding-bar-fill {
    animation: none;
  }
}

/* ─── 그리드 아래 안내 줄 (S14e / R16) ─────────────────────────────────── */
/* 30장 초과 · 열 수 없는 사진 · 꽉 참. 다음 사진 동작이나 저장 때까지 남는다 */
.log-photo-notes {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
  padding-top: var(--space-1);
}

.log-photo-notes:empty {
  display: none;
}

.log-photo-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1-5);
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-secondary);
}

/* 되돌리기 줄 — 아이콘 없이 오른쪽 끝에 글자 버튼 (R17-1 · R17-3) */
.log-photo-note--undo {
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.log-photo-note-action {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  min-height: var(--control-md);
  padding: 0 var(--space-1);
  margin: calc(-1 * var(--space-3)) calc(-1 * var(--space-1));
  color: var(--brand-text);
  font-size: var(--text-13);
  font-weight: 600;
  line-height: 1.45;
}

.log-photo-note-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  height: var(--line-box-13);   /* 13px/1.45 첫 줄 높이 — .log-detail-place-icon 과 같은 이유 */
  color: var(--text-secondary);
}

.log-photo-note-icon svg {
  width: var(--icon-inline);    /* 13px 글자 옆 아이콘 — .log-detail-place-icon 과 같다 */
  height: var(--icon-inline);
  display: block;
}

/* ─── 입력 필드 ───────────────────────────────────────────────────────── */

.log-field-block {
  display: flex;
}

.log-input {
  width: 100%;
  min-height: var(--control-lg);
  padding: 0 var(--field-pad);
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 400;
}

.log-input:focus {
  outline: none;
  border-color: var(--brand);
}

/* text-tertiary. opacity 를 1로 눌러 둔다 — 엔진 기본 placeholder 투명도가 달라
   같은 색을 줘도 두 OS 의 실효 농도가 갈린다 */
.log-input::placeholder {
  color: var(--text-tertiary);
  opacity: 1;
}

/* ─── TextArea (신규) ─────────────────────────────────────────────────── */
/* 글자 수 제한·카운터 없음 — 후기 길이를 우리가 정하지 않는다.
   엔진 기본값(글꼴·리사이즈 핸들·스크롤바·포커스 링)은 base.css가 눌러 둔다. */

.log-textarea {
  width: 100%;
  min-height: var(--textarea-min-h);
  padding: var(--field-pad);
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 400;
  line-height: 1.5;
}

.log-textarea:focus {
  border-color: var(--brand);
}

.log-textarea::placeholder {
  color: var(--text-tertiary);
  opacity: 1;
}

/* ─── 캠핑장 칸 · 필수 안내 · 선택 사항 (v8) ─────────────────────────── */

/* 캠핑장 칸 — 날짜 칸과 같은 모양의 버튼. 오른쪽 › 가 '눌러서 고른다'를 말한다 */
.log-pick-btn {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--control-lg);
  padding: 0 var(--field-pad);
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 400;
  line-height: 1.4;
  text-align: left;
}

.log-pick-btn:active {
  background: var(--surface-pressed);
}


.log-pick-value {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

/* 아직 고르지 않았다 — placeholder 가 아니라 버튼 안 글자다 */
.log-pick-value--empty {
  color: var(--text-secondary);
}

.log-pick-chevron {
  flex-shrink: 0;
  display: flex;
  color: var(--text-secondary);
}

.log-pick-chevron svg {
  width: var(--icon-chevron);   /* 시안 값 — 불러오기 시트 업체 행 꺾쇠와 같은 크기 */
  height: var(--icon-chevron);
  display: block;
}

/* 수정 화면 — 캠핑장은 바꾸지 않는다(QA D2). 버튼 모양 없이 글자만 */
.log-pick-btn--static,
.log-pick-btn--static:active {
  padding: 0;
  background: none;
  border-color: transparent;
  cursor: default;
}

.log-pick-btn--static .log-pick-chevron {
  display: none;
}

/* '캠핑장을 골라야 저장할 수 있어요.' — 칸 바로 아래. 모양은 사진 안내 줄과 같다 */
.log-need.hidden {
  display: none;
}

/* 라벨 줄 오른쪽 '선택 사항' */
.log-label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.log-optional {
  font-size: var(--text-12);
  font-weight: 600;
  line-height: 1.4;
  color: var(--text-secondary);
}

/* 저장할 수 없을 때 — 모양은 비활성이지만 탭은 받는다(왜 안 되는지 말하려고) */
.log-compose-side[aria-disabled="true"] {
  color: var(--text-disabled);
}

.log-origin-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1-5);
  font-size: var(--text-12);
  font-weight: 600;
  line-height: 1.4;
  color: var(--text-secondary);
}

.log-origin-note.hidden {
  display: none;
}

/* 사이트·위치 칸 아래 안내 줄 (R22) — 칸과 8px(섹션 gap). 되돌리기는 오른쪽 끝 */
.log-field-note {
  align-items: center;
}

.log-field-note-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.log-origin-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  height: var(--line-box-12);   /* 12px/1.4 첫 줄 높이 */
  color: var(--brand);
}

/* ─── 방문 날짜 버튼 ─────────────────────────────────────────────────── */

.log-date-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--control-lg);
  padding: 0 var(--field-pad);
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 400;
  text-align: left;
}

.log-date-btn:active {
  background: var(--surface-pressed);
}

.log-date-value {
  flex: 1 1 auto;
  min-width: 0;
  font-variant-numeric: tabular-nums;
}

/* 날짜 칸 오른쪽 'n박 n+1일' (R13). 당일치기면 비어 있다 */
.log-date-nights {
  flex-shrink: 0;
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-secondary);
  white-space: nowrap;
}

.log-date-nights:empty {
  display: none;
}

/* 달력 아래 요약 줄 (S16) */
.log-cal-summary-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-2);
  margin-top: var(--space-4);
}

.log-cal-summary {
  font-size: var(--text-15);
  font-weight: 600;
  line-height: 1.5;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.log-cal-nights {
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-secondary);
  white-space: nowrap;
}

.log-date-icon {
  flex-shrink: 0;
  display: flex;
  color: var(--text-secondary);
}

/* 파일 입력은 네이티브 피커를 열기 위한 것뿐이라 화면에 두지 않는다 */
.log-file-input {
  display: none;
}

/* ─── UploadProgress (신규) ───────────────────────────────────────────── */
/* 전체 진행 바 하나가 아니라 사진마다 따로 끝난다. 집계는 글자로 말한다.
   남은 시간·"거의 다 됐어요" 같은 추정 문구를 쓰지 않는다. */

.log-upload-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
}

/* 몇 장이 올라갔는지가 이 부품의 전부다 — 생략하지 않고 줄바꿈한다 */
.log-upload-count {
  font-size: var(--text-15);
  font-weight: 600;
  line-height: 1.5;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.log-upload-hint.hidden,
.log-upload-fail-actions .hidden {
  display: none;
}

.log-upload-hint {
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-secondary);
}

/* 올라가기 전·올라가는 중 타일은 사진을 어둡게 덮는다 */
.log-tile-scrim {
  position: absolute;
  inset: 0;
  background: var(--scrim);
}

.log-tile-bar {
  position: absolute;
  left: var(--space-2-5);
  right: var(--space-2-5);
  bottom: var(--space-2-5);
  height: var(--log-progress-h);
  border-radius: var(--radius-xs);
  background: var(--overlay-pressed);
  overflow: hidden;
  display: block;
}

.log-tile-bar-fill {
  display: block;
  height: var(--log-progress-h);
  border-radius: var(--radius-xs);
  background: var(--brand);
}

.log-tile-done {
  position: absolute;
  right: var(--space-1-5);
  top: var(--space-1-5);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--icon-md);
  height: var(--icon-md);
  border-radius: var(--radius-sm);
  background: var(--bg-base);   /* 사진 위 배지 — 불투명 바닥 (R14) */
  color: var(--success);
}

.log-tile-done svg {
  width: var(--icon-badge);   /* 20px 배지 안의 체크 */
  height: var(--icon-badge);
  display: block;
}

/* 실패는 색만으로 말하지 않는다 — 테두리 + ↺ + '다시' 글자가 같이 바뀐다 */
.log-tile--failed {
  border: 1.5px solid var(--danger);
}

/* 사진 위에 겹쳐 가운데에 둔다. 타일은 flex 컨테이너이고 사진이 폭을 100% 차지해서,
   흐름 안에 두면 ↺ 가 사진 옆으로 밀려 타일 밖으로 잘린다(하네스 검증에서 재현). */
.log-tile-fail-mark {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  color: var(--danger);
}

.log-tile-fail-mark svg {
  width: var(--icon-md);
  height: var(--icon-md);
  display: block;
}

.log-tile-fail-label {
  font-size: var(--text-11);
  font-weight: 700;
  letter-spacing: 0.4px;
  line-height: 1.5;
}

.log-upload-fail {
  display: flex;
  flex-direction: column;
  gap: var(--space-2-5);
  padding: var(--panel-pad) var(--space-4);
  background: var(--surface-card);
  border-radius: var(--radius-lg);
}

.log-upload-fail.hidden {
  display: none;
}

/* 실패 사유는 잘리면 안 되는 글자다 — ellipsis 없이 줄바꿈한다 */
.log-upload-fail-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1-5);
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
  color: var(--text-primary);
  word-break: keep-all;
}

.log-upload-fail-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  height: var(--icon-md);
  color: var(--danger);
}

.log-upload-fail-actions {
  display: flex;
  align-items: stretch;
  gap: var(--space-2);
}

/* ─── 저장 실패 띠 (S18c) ────────────────────────────────────────────── */

.log-save-fail-wrap {
  flex-shrink: 0;
  padding: var(--space-3) var(--space-5) 0;
}

.log-save-fail-wrap.hidden {
  display: none;
}

.log-save-fail {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  padding: var(--space-3) var(--panel-pad);
  background: var(--danger-fill);
  border-radius: var(--radius-lg);
}

.log-save-fail-icon {
  flex-shrink: 0;
  display: flex;
  color: var(--danger);
}

.log-save-fail-icon svg {
  width: var(--icon-chevron);   /* 14px 글자 옆 아이콘 */
  height: var(--icon-chevron);
}

/* 실패 사유는 잘리면 안 되는 글자다 — 줄바꿈한다 */
.log-save-fail-text {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
  color: var(--text-primary);
  word-break: keep-all;
}

.log-save-fail-btn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-md);
  padding: 0 var(--space-3);
  margin: calc(-1 * var(--space-2)) calc(-1 * var(--space-1-5)) calc(-1 * var(--space-2)) 0;
  border: 1px solid var(--danger);   /* 위험은 테두리로, 글자는 읽히게 (R17-4) */
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
}

/* ─── 공용 버튼 변형 (로그 탭) ───────────────────────────────────────── */
/* 나란히 놓인 버튼은 stretch + flex:1 + min-width:0 — 한쪽 라벨이 2줄로 접혀도
   높이가 어긋나지 않는다 */

.log-btn-outline {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-md);
  padding: 0 var(--space-3);
  background: var(--surface-card);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
  text-align: center;
}

.log-btn-outline:active {
  background: var(--overlay-pressed);
}


.log-btn-quiet {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-md);
  padding: 0 var(--space-3);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
}

/* 그만두기 — 위험은 테두리로, 글자는 읽히게(R17-4 와 같은 규칙) */
.log-btn-danger-outline {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-lg);
  padding: 0 var(--space-3);
  border: 1px solid var(--danger);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 600;
  line-height: 1.45;
  text-align: center;
}

.log-btn-danger-outline:active {
  background: var(--overlay-pressed);
}

.log-btn-destructive {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-lg);
  padding: 0 var(--space-3);
  background: var(--destructive);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 600;
  line-height: 1.45;
  text-align: center;
}

/* ─── 칼람에서 불러오기 시트 (S15) ───────────────────────────────────── */

.log-import-sheet {
  height: 86vh;   /* 목록이 짧아도 시트 높이가 튀지 않게 고정한다(검색이 있는 시트) */
}

.log-import-search {
  flex-shrink: 0;
  padding: var(--space-3) var(--space-5);
}

.log-search-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--control-md);
  padding: 0 var(--space-3);
  background: var(--surface-raised);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
}

.log-search-wrap:focus-within {
  border-color: var(--brand);
}

.log-search-icon {
  flex-shrink: 0;
  display: flex;
  color: var(--text-tertiary);
}

.log-search-input {
  flex: 1 1 auto;
  min-width: 0;
  background: none;
  border: 0;
  outline: none;
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 400;
}

.log-search-input::placeholder {
  color: var(--text-tertiary);
}

/* 시트 바디 기본 padding 을 지운다 — 행이 시트 폭을 꽉 채워야 한다 */
.log-import-list {
  padding: 0 0 var(--space-1);
}

.log-import-vendor {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  min-height: var(--control-lg);
  padding: var(--space-2) var(--space-5);
  text-align: left;
  border-bottom: 1px solid var(--border-divider);
}

.log-import-vendor--open {
  background: var(--overlay-soft);
}

.log-import-vendor-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
  color: var(--text-primary);
  word-break: keep-all;
}

.log-import-vendor-count {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--overlay-pressed);
  color: var(--text-secondary);
  font-size: var(--text-11);
  font-weight: 700;
  letter-spacing: 0.4px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

.log-import-chevron {
  flex-shrink: 0;
  display: flex;
  color: var(--text-tertiary);
}

.log-import-chevron svg {
  width: var(--icon-chevron);   /* 업체 행(50px)의 펼침 꺾쇠. 상품 행은 16px */
  height: var(--icon-chevron);
}

.log-import-product {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  min-height: var(--list-row-sm-h);
  padding: var(--space-2) var(--space-5) var(--space-2) var(--list-indent);
  text-align: left;
  border-bottom: 1px solid var(--border-divider);
}

.log-import-product:active,
.log-import-vendor:active {
  background: var(--overlay-pressed);
}

.log-import-product-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-14);
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-primary);
  word-break: keep-all;
}

/* '자리 없이 캠핑장만 불러오기' — 자리 줄과 같은 들여쓰기·높이, 글자만 보조 톤 */
.log-import-product--camp-only .log-import-product-name {
  color: var(--text-secondary);
}

/* 자리 0개 캠핑장 — 한 줄뿐이라 주 글자로, 아래에 이유를 한 줄 */
.log-import-product--only .log-import-product-name {
  color: var(--text-primary);
}

.log-import-product-sub {
  display: block;
  margin-top: var(--space-0-5);
  font-size: var(--text-12);
  line-height: 1.4;
  color: var(--text-secondary);
}

.log-import-note {
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-13);
  line-height: 1.6;
  color: var(--text-tertiary);
  text-align: center;
  white-space: pre-line;
}

/* ─── 사진 하나 다루기 시트 (S18b) ───────────────────────────────────── */

.log-sheet-menu {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.log-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  /* button 리셋이 color 를 물려주지 않아 WebView 기본 글자색(검정 계열)로 떨어졌다 (R17-4) */
  color: var(--text-primary);
  min-height: var(--tabbar-height);
  padding: var(--space-2) var(--space-5);
  text-align: left;
  border-bottom: 1px solid var(--border-divider);
}

.log-menu-item:last-of-type {
  border-bottom: 0;
}

.log-menu-item:active {
  background: var(--overlay-pressed);
}

.log-menu-item:disabled {
  color: var(--text-disabled);
  cursor: default;
}

.log-menu-item.hidden {
  display: none;
}

.log-menu-icon {
  flex-shrink: 0;
  display: flex;
  color: var(--text-secondary);
}

.log-menu-icon--brand {
  color: var(--brand);
}

.log-menu-icon--destructive {
  color: var(--destructive);
}

/* 비활성 행은 아이콘까지 같이 흐려진다 */
.log-menu-item:disabled .log-menu-icon {
  color: var(--text-disabled);
}

.log-menu-label {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-15);
  font-weight: 400;
  line-height: 1.5;
  color: inherit;
}

/* 위험 표시는 아이콘만 맡는다 — 빨간 글자는 surface-card 위에서 읽기 어렵다 (R17-4) */
.log-menu-item--destructive .log-menu-label {
  color: var(--text-primary);
}

/* 시트 바닥 여백 — safe-area 가 0인 기기에서도 마지막 행이 화면 끝에 붙지 않게 */
.log-sheet-menu-tail {
  flex-shrink: 0;
  height: calc(var(--space-6) + var(--safe-area-bottom));
}

/* ─── 삭제 확인 (S17) ────────────────────────────────────────────────── */

.log-confirm-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-10);
}

.log-confirm-modal.hidden {
  display: none;
}

.log-confirm-backdrop {
  position: absolute;
  inset: 0;
  background: var(--scrim);
}

.log-confirm-box {
  position: relative;
  width: 100%;
  max-width: 400px;
  background: var(--surface-card);
  border-radius: var(--radius-2xl);
  padding: var(--space-6) var(--space-5) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.log-confirm-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.log-confirm-title {
  text-align: center;
  font-size: var(--text-17);
  font-weight: 700;
  letter-spacing: -0.3px;
  line-height: 1.3;
  color: var(--text-primary);
}

.log-confirm-desc {
  text-align: center;
  font-size: var(--text-14);
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-secondary);
  white-space: pre-line;
}

.log-confirm-actions {
  display: flex;
  align-items: stretch;
  gap: var(--space-2);
}

/* 확인 모달의 '그대로 두기'는 지우기 버튼과 높이를 맞춘다 */
.log-confirm-actions .log-btn-outline {
  min-height: var(--control-lg);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  font-size: var(--text-15);
}

/* ─── LoadMoreRow (신규 부품 7번 / 시안 v5 S12e) ──────────────────────────
 * 목록 맨 아래에서 다음 묶음을 불러오는 자리. 상태는 셋뿐이다 —
 * 불러오는 중 / 실패 / 끝(아무것도 두지 않음).
 *
 * '더 보기' 버튼을 두지 않는다 — 스크롤이 이미 그 뜻이다.
 * **토스트를 쓰지 않는다**: 사라지는 알림은 다시 시도할 길도 같이 가져가고,
 * 못 본 사람에게는 아무 일도 일어나지 않은 화면이 남는다. 실패는 자기 자리에
 * 머물러야 한다. 이미 불러온 카드는 그대로 둔다(읽던 자리가 움직이면 안 된다). */

.log-more-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--tabbar-height);
  color: var(--text-secondary);
  font-size: var(--text-14);
  font-weight: 600;
}

/* 카드와 같은 폭·같은 모양이다. 목록의 일부지 떠 있는 알림이 아니다.
   폭이 좁아 한 줄에 안 들어가면 버튼이 아랫줄로 내려가 전폭이 된다 —
   문구에 grow 를 몰아줘서(999) 한 줄일 때는 버튼이 제 너비를 지킨다. */
.log-more-fail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--panel-pad) var(--space-4);
  background: var(--surface-card);
  border-radius: var(--radius-xl);
}

.log-more-fail-icon {
  flex-shrink: 0;
  display: flex;
  color: var(--danger);
}

.log-more-fail-icon svg {
  width: var(--icon-chevron);   /* 14px 글자 옆 아이콘 */
  height: var(--icon-chevron);
  display: block;
}

/* 실패 사유는 잘리면 안 되는 글자다 — 생략하지 않고 줄바꿈한다 */
.log-more-fail-text {
  flex: 999 1 140px;
  min-width: 0;
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
  color: var(--text-primary);
  word-break: keep-all;
}

.log-more-fail-btn {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  min-height: var(--control-md);
  padding: 0 var(--field-pad);
  background: none;
  border: 1px solid var(--border-control);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
}

.log-more-fail-btn:active {
  background: var(--overlay-pressed);
}

.log-more-fail-btn svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  display: block;
  flex-shrink: 0;
}

/* 업로드 실패 사유 한 줄 — 제목 줄의 아이콘 폭(16+6)만큼 들여써 글자가 맞춰진다 */
.log-upload-fail-reason {
  margin: -4px 0 0 22px;
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-secondary);
  word-break: keep-all;
}

.log-upload-fail-reason.hidden {
  display: none;
}

/* ─── 사진 크게 보기 (S19 / R26) ───────────────────────────────────────── */
/* 탭바(900)·작성 화면(950)과 같은 층 위 — 상세에서만 열리므로 둘이 겹치지 않는다 */
.log-viewer {
  position: fixed;
  inset: 0;
  z-index: 960;
  display: flex;
  flex-direction: column;
  background: var(--bg-base);
  padding-bottom: var(--safe-area-bottom);
}

.log-viewer.hidden {
  display: none;
}

.log-viewer-bar {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: calc(var(--control-md) + var(--safe-area-top));
  padding: var(--safe-area-top) var(--space-3) 0 var(--space-1);
}

.log-viewer-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-md);
  height: var(--control-md);
  border-radius: var(--radius-md);
  color: var(--text-primary);
}

.log-viewer-close:active {
  background: var(--overlay-pressed);
}

.log-viewer-count {
  font-size: var(--text-15);
  font-weight: 600;
  line-height: 1.4;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* 상세와 같은 가로 페이저 */
.log-viewer-track {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  touch-action: pan-x;
}

.log-viewer-track::-webkit-scrollbar {
  display: none;
}

/* 확대 중에는 좌우 넘기기를 끈다 — 한 손가락 끌기는 사진 이동(JS) */
.log-viewer-track--zoomed {
  overflow-x: hidden;
  touch-action: none;
}

.log-viewer-slide {
  flex: 0 0 100%;
  min-width: 0;
  height: 100%;
  scroll-snap-align: start;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 확대 대상 — 표시본과 원본을 같은 자리에 겹친다 */
.log-viewer-frame {
  position: relative;
  width: 100%;
  height: 100%;
}

/* 자르지 않은 전체 */
.log-viewer-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* 원본 — decode 가 끝난 뒤 겹쳐 0.15s 로 나타난다 */
.log-viewer-img--orig {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--dur-state);
}

.log-viewer-img--orig.log-viewer-img--in {
  opacity: 1;
}

/* 아래 가운데 한 줄 — 확대 칩 · 사본 문구 · 원본 실패(+다시 시도). 높이를 늘 잡아 두어
   문구가 생겨도 사진 자리가 움직이지 않는다 */
.log-viewer-note {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--viewer-foot-h);   /* 시안 S19b 아래 줄 높이 */
  padding: 0 var(--space-5);
  font-size: var(--text-12);
  font-weight: 600;
  line-height: 1.4;
  color: var(--text-secondary);
  text-align: center;
}

.log-viewer-chip {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1-5) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-card);
  color: var(--text-primary);
  font-size: var(--text-13);
  font-weight: 500;
  line-height: 1.45;
}

.log-viewer-copy {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1-5);
  max-width: 320px;   /* 시안 S19c 최대 폭 */
  text-align: left;
}

.log-viewer-copy-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  height: var(--line-box-12);   /* 12px/1.4 첫 줄 높이 */
}

.log-viewer-copy-icon svg {
  width: var(--icon-inline);
  height: var(--icon-inline);
  display: block;
}

/* ─── 식사 (S14g · S13b / R28) ─────────────────────────────────────────── */

.log-meals-section {
  gap: var(--space-1);
}

.log-meals {
  display: flex;
  flex-direction: column;
}

.log-meal-day {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--border-divider);
}

/* 날짜 머리 — 누르면 접고 편다(여러 날 동시에 펼칠 수 있다) */
.log-meal-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--control-md);
  padding: 0;
  text-align: left;
  color: var(--text-primary);
}

.log-meal-head-label {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-14);
  font-weight: 600;
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
}

/* 접힌 날에 적은 끼니 수 */
.log-meal-head-count {
  flex-shrink: 0;
  font-size: var(--text-12);
  font-weight: 600;
  line-height: 1.4;
  color: var(--text-secondary);
}

.log-meal-chevron {
  flex-shrink: 0;
  display: flex;
  color: var(--text-secondary);
}

.log-meal-chevron svg {
  width: var(--icon-chevron);   /* 불러오기 시트 업체 행 꺾쇠와 같은 크기 */
  height: var(--icon-chevron);
  display: block;
}

/* 접혀 있으면 › 방향 */
.log-meal-chevron:not(.log-meal-chevron--open) svg {
  transform: rotate(-90deg);
}

.log-meal-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-bottom: var(--space-2);
}

.log-meal-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.log-meal-label {
  flex-shrink: 0;
  width: var(--meal-label-w);   /* 시안 값 — 두 글자 라벨 열 */
  padding-top: var(--space-3);
  font-size: var(--text-13);
  font-weight: 600;
  line-height: 1.45;
  color: var(--text-secondary);
}

/* 한 줄로 시작해 쓰는 만큼 늘어난다(JS 가 높이를 맞춘다). 잘리지 않는다 */
.log-meal-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--control-md);
  padding: var(--field-pad-y-sm) var(--field-pad);   /* 시안 값 — 44px 한 줄에 15/1.4 글자가 가운데 */
  background: var(--surface-card);
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-size: var(--text-15);
  font-weight: 400;
  line-height: 1.4;
  overflow: hidden;
}

.log-meal-input:focus {
  border-color: var(--brand);
}

.log-cal-meal-warn {
  margin-top: var(--space-2);
}

.log-cal-meal-warn.hidden,
#log-meals-undo.hidden {
  display: none;
}

/* 상세 식사 */
.log-detail-meals {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.log-detail-meals-title {
  font-size: var(--text-15);
  font-weight: 700;
  line-height: 1.4;
  color: var(--text-primary);
}

.log-detail-meal-day {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.log-detail-meal-head {
  font-size: var(--text-13);
  font-weight: 600;
  line-height: 1.45;
  color: var(--text-secondary);
}

.log-detail-meal-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: var(--text-15);
  font-weight: 400;
  line-height: 1.5;
  color: var(--text-primary);
}

.log-detail-meal-label {
  flex-shrink: 0;
  width: var(--meal-label-w);
  color: var(--text-secondary);
}

/* 생략 없이 끝까지 */
.log-detail-meal-text {
  flex: 1 1 auto;
  min-width: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
