/* 예약 웹 — 2a (필터 사이드바 + 목록형, 딥 포레스트) 디자인 토큰
 * 색상 토큰은 전역 파일(common/css/tokens.css) 한 곳에서만 정의한다.
 * 변수명은 기존 계약(--sage 등)을 유지 — JS 인라인 참조 호환 */
/* 폰트는 tokens.css 의 @font-face 가 우리 서버에서 직접 받는다 (2026-08-30).
   외부 CDN @import 를 여기 되살리지 말 것 — 이유는 tokens.css 주석에. */
@import url('../../common/css/tokens.css');
/* 예약(객실 선택) 화면 리디자인 토큰. docs/reservation-redesign/tokens.css 가 원본이며
   그 문서가 «값의 단일 출처» 다 — 이 아래 규칙에서 hex/px 를 새로 쓰지 말고 --rsv-* 를 참조한다. */
@import url('rsv-tokens.css');

/* ─────────────────────────────────────────────
   손님 웹 전용 중립 팔레트 (2026-09-01, 당진 스테이 디자인 이식)

   크림 바탕(#F6F4EF) + 웜 베이지 선에서 «흰 바탕 + 중립 회색 선» 으로 간다.
   브랜드 초록(--sage:#204A12)은 이미 당진 사이트와 같은 값이라 손대지 않는다.

   ⚠ 왜 tokens.css 가 아니라 여기인가 —
     tokens.css 는 관리자·로그인·결제완료가 «같이» 읽는 파일이다. 거기서 --bg 를
     흰색으로 바꾸면 관리자 화면 전체가 같이 하얘진다. 이 파일(web/css/main.css)은
     손님 웹 10개 템플릿만 읽으므로, 여기서 덮으면 범위가 정확히 손님 웹이다.
     관리자까지 통일할 일이 생기면 그때 tokens.css 로 «올리면» 된다.

   ⚠ 값을 --rsv-* 와 «따로» 적지 말 것. 아래는 전부 참조다 — 색을 바꾸려면
     rsv-tokens.css 한 곳만 고친다.
   ──────────────────────────────────────────── */
:root{
  --bg:var(--rsv-bg);
  --card:var(--rsv-surface);
  --line:var(--rsv-line);
  --line2:var(--rsv-line);
  --line3:var(--rsv-line-soft);
  --ink:var(--rsv-text);
  --ink2:var(--rsv-text-2);
  --ink3:var(--rsv-text-3);
  --sage-bg:var(--rsv-surface-sunken);
  --sage-tint-faint:var(--rsv-surface-sunken);

  /* 색을 채운 면 — 담기 바 · 결제 박스 · 예약완료 헤더 · 갤러리가 이 둘을 쓴다.
     거의 검정(#1F241E)이었다. 흰 바탕에 진녹색 띠가 두 군데(객실선택·결제금액 안내)
     들어오면서, 검정 덩어리가 세 번째 색으로 끼어 화면이 «초록·검정·흰» 삼색이 됐다.
     같은 초록으로 모으면 색은 둘로 줄고, 채운 면끼리는 서로 같은 것으로 읽힌다. */
  --dark:var(--rsv-brand);
  --dark-ink:var(--rsv-text-on-brand);

  /* 그 «초록 면 위» 의 주 버튼. 연두(#8FA96B)였는데 바닥이 초록이 되면서
     초록 위 초록이라 버튼으로 보이지 않는다. 흰 버튼 + 초록 글자로 뒤집는다 (10.4:1). */
  --lime:var(--rsv-surface);
  --lime-ink:var(--rsv-brand);

  /* 「주의 · 시간이 간다」 계열 — 홀딩 배지 · 입금 대기 안내 · 결제 남은 시간 · 달력의 오늘.
     갈색/크림(#8A6A3F on #FBF6EC)이라 흰 바탕에서 혼자 빛바랜 종이처럼 보였다.
     같은 «호박색» 을 유지하되 채도를 올려 초록·흰색 옆에서 또렷하게 만든다.
     빨강(--rsv-accent)으로 옮기지 않는 것은 이것이 «오류가 아니라 재촉» 이기 때문이다.
     대비 4.90:1 — 본문 기준(WCAG 1.4.3 AA 4.5:1)을 넘긴다. */
  --terra:#9A5B00;
  --terra-bg:#FFF7E8;
  --terra-line:#EFD9AE;

  /* 「되돌릴 수 없다」 계열 — 취소 버튼 · 수수료 · 필수 표시 · 일요일.
     공용 토큰의 #93502F 는 이 화면의 갈색(--terra)과 거의 같은 색이라, 「예약 취소하기」가
     홀딩 안내와 같은 무게로 읽혔다. 이식해 온 팔레트의 빨강(--rsv-accent)으로 모은다.
     ⚠ 공용 tokens.css 를 고치면 관리자까지 따라오므로 «손님 웹에서만» 덮는다.
     흰 글자 대비 5.4:1 — AA 통과. */
  --danger:var(--rsv-accent);
  --danger-bg:var(--rsv-accent-tint);
  --danger-line:#F0BFC1;

  --rad:var(--rsv-r-md); --rad-s:var(--rsv-r-sm);
  /* 모바일 메뉴 서랍의 폭. 여기 한 곳에서만 정한다.
     280px 은 「긴 라벨 + 22px 아이콘 + 좌우 여백」이 줄바꿈 없이 들어가는 최소치고,
     좁은 폰에서 화면을 다 먹지 않도록 78vw 로도 묶는다 (아래 .gnb.drawer).

     ⚠ 옛 --tabbar-h(68px)는 없앴다. 하단 탭바를 걷으면서 그 높이를 피하던 규칙
     (본문 아래 여백 · 담기 바 · 맨 위로 버튼)이 전부 사라졌기 때문이다 (2026-09-11). */
  --drawer-w:280px;
  /* 그림자는 «거의 없앤다». 흰 바탕에서 카드를 띄우는 일은 #ccc 테두리가 맡는다 —
     당진 사이트에 그림자가 한 곳도 없다. 완전히 0 으로 두지 않는 것은 떠 있는 것
     (담기 바·시트)만큼은 바닥과 구분돼야 하기 때문이다. */
  --sh:none;
  --sh-lg:0 8px 28px rgba(0,0,0,.14);
}
*{margin:0;padding:0;box-sizing:border-box}
/* display 를 지정한 요소(.modal-back 등)에서도 hidden 속성이 항상 이기도록 */
[hidden]{display:none !important}
body{font-family:'Pretendard',-apple-system,'Malgun Gothic',sans-serif;background:var(--bg);color:var(--ink);
  line-height:1.6;-webkit-font-smoothing:antialiased}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
input,select,textarea{font-family:inherit;font-size:inherit}
a{text-decoration:none;color:inherit}

/* 스크롤바 — 관리자(admin/css/common.css)와 같은 바닥값이다 (2026-08-25).
 * 손님 웹은 admin/css/common.css 를 읽지 않아 OS 기본 그대로였다.
 * 토큰 파일이 같아 값도 한 글자까지 같다 — 한쪽을 고치면 다른 쪽도 고칠 것.
 * 손잡이 색은 --scroll-thumb (WCAG 3:1 을 맞춘 전용 토큰. 근거는 tokens.css 주석에).
 * ⚠ scrollbar-width / scrollbar-color 를 같이 쓰면 안 된다 —
 *   Chrome 은 표준 속성이 있으면 아래 규칙을 통째로 무시한다.
 *   (그래서 .chips · .gal-track 은 그 속성으로 «숨기는» 쪽을 택했다) */
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-button,
::-webkit-scrollbar-button:vertical:start,
::-webkit-scrollbar-button:vertical:end{display:none;width:0;height:0}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-corner{background:transparent}
::-webkit-scrollbar-thumb{background:var(--scroll-thumb);border-radius:999px;
  border:1px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:var(--ink2);background-clip:content-box}

/* ── 헤더 ── */
.hd{position:sticky;top:0;z-index:100;background:var(--card);border-bottom:1px solid var(--line)}
.hd-in{max-width:1160px;margin:0 auto;padding:16px 24px;display:flex;align-items:center;justify-content:space-between;gap:14px}
/* 오픈 전 미리보기 띠 — 관리자 세션에서만 그려진다 (publicPage/inc/header.html).
   손님 화면과 헷갈리지 않게 «어두운 면» 으로 둔다. 손님 화면에 없는 색이라야 한눈에 갈린다. */
.pv-bar{background:var(--dark);color:var(--dark-ink);display:flex;align-items:center;justify-content:center;
  flex-wrap:wrap;gap:8px 16px;padding:8px 16px;font-size:14px;line-height:1.45}
.pv-bar-text{margin:0;display:flex;flex-wrap:wrap;gap:4px 10px;align-items:baseline}
.pv-bar-text b{font-weight:800}
.pv-bar-end{min-height:36px;padding:0 14px;border:1px solid var(--dark-ink);border-radius:var(--rad-s);
  background:transparent;color:var(--dark-ink);font-size:13.5px;font-weight:700;cursor:pointer}
.pv-bar-end:hover{background:var(--dark-ink);color:var(--dark)}
.pv-bar-end:focus-visible{outline:2px solid var(--dark-ink);outline-offset:2px}
.brand{display:flex;align-items:center;gap:10px}
/* 가로 조합 로고. 이미지는 2배 해상도(415×64)를 높이로만 제어한다 —
   너비를 지정하면 비율이 틀어지고, 원본 여백은 이미 잘라내 뒀다. */
.brand img{height:28px;width:auto;display:block}
.brand .mark{width:10px;height:26px;border-radius:2px;background:var(--sage);display:block;flex:none}
.brand b{font-size:17px;font-weight:800;letter-spacing:-.01em;display:block;white-space:nowrap}
.brand small{display:block;font-size:9.5px;font-weight:700;letter-spacing:.22em;color:var(--ink2);margin-top:-3px;white-space:nowrap}
.gnb{display:flex;align-items:center;gap:26px}
.gnb a{font-size:14px;font-weight:500;color:var(--ink2);transition:.2s;white-space:nowrap}
.gnb a.on{font-weight:800;color:var(--sage)}
.gnb a:hover:not(.on):not(.disabled){color:var(--ink)}
.gnb a.disabled{opacity:.45;cursor:default}
/* 아이콘과 짧은 라벨은 «좁은 화면 전용» 이다 — 켜는 것은 아래 «모바일 하단 탭바» 블록.
   PC 헤더는 예전 그대로 긴 라벨만 쓴다. */
.gnb-ic{display:none}
.gnb-short{display:none}
@media(max-width:760px){
  .hd-in{flex-wrap:wrap;gap:8px;padding:12px 16px}
  .brand b{font-size:15px}
  .brand img{height:24px}
  /* 탭바로 내려가지 않는 nav(점검 중 헤더)는 예전처럼 로고 아래 줄에 깔린다 */
  .gnb{width:100%;justify-content:space-between;gap:6px}
  .gnb a{flex:1;text-align:center;font-size:12.5px}
}

/* ── 모바일 메뉴 서랍 ──
 *
 * 좁은 화면에서는 메뉴 셋을 헤더 오른쪽 «햄버거» 안으로 넣고, 누르면 오른쪽에서
 * 서랍이 나온다 (2026-09-11, 사용자 지시).
 *
 * 그 전에는 화면 맨 아래 «고정 탭바» 였다. 셋이 늘 보이는 것은 좋았지만 값이 비쌌다 —
 * 모든 화면이 세로 68px + 안전영역을 영구히 내줬고, 객실 목록처럼 세로로 긴 화면에서는
 * 그게 카드 반 장이다. 게다가 담기 바·액션 바가 뜰 때마다 탭바를 감추고 본문 여백을
 * 다시 계산하는 규칙이 CSS 네 곳에 흩어져 있었다. 서랍은 바닥을 아예 안 쓰므로
 * 그 계산이 통째로 없어진다.
 *
 * 잃는 것은 «발견성» 이다. 메뉴가 한 번 눌러야 나오고, 지금 어느 화면인지도 열어야 안다.
 * 셋 중 둘(전체 예약 현황 · 예약 확인·취소)은 자주 눌리지 않고, 가장 많이 눌리는
 * 「실시간 예약」은 로고를 눌러도 간다 — 그 길이 이미 있다.
 *
 * 겹치는 것들 정리:
 *   .hd 는 z-index:100 인 «쌓임 맥락» 이라, 그 안의 서랍은 아무리 높여도 100 층에 머문다.
 *   담기 바·액션 바가 150 이므로 그대로 두면 서랍 아래쪽이 그 바들에 가린다.
 *   그래서 서랍이 열려 있는 «동안만» 헤더 자체를 올린다 (body.gnb-open .hd).
 *   290 인 이유: 담기·액션 바(150)와 필터 시트(280) 위, 모달(300) 아래.
 *   모달이 떠 있는데 서랍이 같이 열려 있는 경우는 없지만, 순서는 정해 두는 편이 낫다.
 */
.gnb-burger{display:none}
.gnb-scrim{display:none}

@media(max-width:760px){
  /* 헤더는 «로고 + 햄버거» 한 줄이다. 예전에는 wrap 으로 메뉴 줄을 아래에 깔았는데
     (탭바가 되기 전의 모양), 이제 nav 가 서랍이라 흐름에서 빠져 줄바꿈할 것이 없다. */
  .hd-in{flex-wrap:nowrap;gap:8px;padding:12px 16px}
  .brand b{font-size:15px}
  .brand img{height:24px}
  /* 탭바로도 서랍으로도 내려가지 않는 nav(점검 중 헤더)는 예전처럼 로고 아래 줄에 깔린다.
     :not(.drawer) 로 좁혀 둔다 — 안 그러면 서랍이 이 규칙을 같이 맞아 폭이 100% 가 된다. */
  .gnb:not(.drawer){width:100%;justify-content:space-between;gap:6px;flex-wrap:wrap}
  .gnb:not(.drawer) a{flex:1;text-align:center;font-size:12.5px}
  .hd-in:has(.gnb:not(.drawer)){flex-wrap:wrap}

  /* ── 여는 단추 ──
     보이는 것은 19px 짜리 세 줄이지만 «누르는 것» 은 40px 이다 — 터치 최소 권장치(44px)에
     가깝게 두고, 음수 margin 으로 헤더 높이는 늘리지 않는다. */
  /* ⚠ display:grid 로 두지 말 것. 세 막대가 «각자의 행» 이 되고 행이 버튼 높이(40px)에
     맞춰 늘어나, 사이 여백을 2px 로 적어도 실제로는 12px 씩 벌어진다 (2026-09-11에 겪었다 —
     막대 셋의 전체 높이가 10px 이어야 하는데 30px 이었다). 세로 flex 는 내용만큼만 차지하고
     남는 높이는 justify-content 가 «바깥» 으로 돌리므로 gap 이 적은 그대로 선다. */
  .gnb-burger{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;
    flex:none;width:40px;height:40px;margin:-6px -8px -6px 0;border-radius:8px;color:var(--ink)}
  /* ── 막대 사이 6px ──
     여기까지 온 길 (전부 2026-09-11, 사용자가 보고 정했다):
       12px  처음. display:grid 탓에 «의도한 3px 이 아니라» 그렇게 벌어져 있었다 → 너무 넓다
        2px  flex 로 고치면서 바짝 붙였다 → 이번엔 너무 밀집됐다
        6px  둘의 가운데. 세 줄이 한 덩어리로 읽히면서도 틈이 답답하지 않다
     막대 폭을 19px 그대로 두면 아이콘이 19 × 18px 로 «거의 정사각» 이 된다. 햄버거는
     보통 가로가 긴 물건이라 22px 로 넓혀 균형을 되돌린다 (22 × 18, 가로세로비 1.2).
     보이는 것은 22 × 18px 이지만 «누르는 것» 은 40px 그대로다. */
  .gnb-burger span{display:block;width:22px;height:2px;background:currentColor;border-radius:2px}
  .gnb-burger:focus-visible{outline:2px solid var(--sage);outline-offset:1px}

  /* ── 서랍 ──
     visibility 로 닫는다. transform 만으로 화면 밖에 밀어 두면 «보이지 않는 채로» 탭 이동과
     스크린리더에 남아, 닫힌 메뉴를 훑게 된다. transition 에 visibility 를 0s 지연으로 함께
     걸어 닫힐 때는 미끄러짐이 끝난 뒤에 사라지게 한다. */
  .gnb.drawer{position:fixed;top:0;right:0;bottom:0;z-index:2;
    width:min(78vw,var(--drawer-w));
    flex-direction:column;align-items:stretch;justify-content:flex-start;gap:2px;
    background:var(--card);border-left:1px solid var(--line);
    padding:calc(10px + env(safe-area-inset-top)) 10px calc(14px + env(safe-area-inset-bottom));
    transform:translateX(100%);visibility:hidden;
    /* .26s → .18s (2026-09-11, 사용자 지시 — 「반응이 느리다」).
       메뉴는 «보러» 여는 것이지 감상하는 것이 아니라, 미끄러짐이 길면 그만큼 기다림이 된다.
       0 으로 두지 않는 이유는 어디서 나왔는지를 보여 주기 위해서다 — 갑자기 나타나면
       화면이 «바뀐» 것으로 읽혀 뒤로 가기로 되돌리려 한다. */
    transition:transform .18s cubic-bezier(.2,.8,.2,1),visibility 0s .18s}
  body.gnb-open .gnb.drawer{transform:none;visibility:visible;transition-delay:0s}
  body.gnb-open .hd{z-index:290}
  body.gnb-open{overflow:hidden}

  /* 서랍 안의 줄. 탭바처럼 아이콘을 위에 얹지 않는다 — 가로로 긴 자리라 «아이콘 + 글자»가
     한 줄로 읽히고, 그래야 손가락이 줄 전체를 누를 수 있다. */
  .gnb.drawer a{display:flex;align-items:center;gap:12px;flex:none;
    padding:14px 12px;border-radius:8px;font-size:14px;font-weight:500;
    text-align:left;color:var(--ink)}
  .gnb.drawer a.on{background:var(--sage-bg);font-weight:700;color:var(--sage)}
  .gnb.drawer .gnb-ic{display:block;width:22px;height:22px;flex:none;color:var(--ink2);
    fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
  /* 활성 — 면을 채우고 선은 끈다. 채운 면 위의 «파내는 선»(.c)만 배경색으로 뒤집어
     덩어리에 묻히지 않게 한다. 클래스 없는 것(달력 걸이·침대 다리)은 면 밖이라 그대로 선이다.
     색 하나로만 알리지 않는다는 규칙(SPEC 10)을 이 «채움» 이 지켜 준다. */
  .gnb.drawer a.on .gnb-ic{color:var(--sage)}
  .gnb.drawer a.on .gnb-ic .f{fill:currentColor;stroke:none}
  .gnb.drawer a.on .gnb-ic .c{stroke:var(--card)}
  /* 라벨은 «긴 쪽» 을 쓴다 — 서랍 폭이 280px 이라 줄일 이유가 없다.
     짧은 쪽(.gnb-short)은 전역 규칙이 이미 감추고 있어 여기서 할 일이 없다. */

  /* ── 뒤를 덮는 막 ──
     서랍보다 «먼저» 나오는 형제라 같은 층에서 아래에 깔린다 (둘 다 헤더 안이다). */
  /* 막은 서랍보다 «조금 빨리» 짙어진다. 같이 끝나면 어두워지는 것이 늦게 느껴진다 */
  .gnb-scrim{display:block;position:fixed;inset:0;z-index:1;
    background:rgba(31,36,30,.42);opacity:0;pointer-events:none;transition:opacity .14s ease}
  body.gnb-open .gnb-scrim{opacity:1;pointer-events:auto}
}

@media(prefers-reduced-motion:reduce){
  .gnb.drawer,.gnb-scrim{transition:none}
}

/* ── 검색 밴드 (입실일 · 퇴실일 · 조회하기) ──
 *
 * 당진 스테이 이식 (2026-09-02). 칸을 각각 상자로 두는 대신 «하나의 테두리 상자» 안에
 * 두 날짜와 버튼을 담는다 — 셋이 한 동작(조회)의 부품이라 한 덩어리로 읽혀야 한다.
 *
 * 인원 칸은 없앴다. 인원은 객실 카드마다 그 자리에서 고른다 (main.js 의 paxRowHtml).
 */
.band{background:var(--card);border-bottom:1px solid var(--line)}
.band-in{max-width:1160px;margin:0 auto;padding:18px 24px;position:relative}
.band-box{display:flex;align-items:center;gap:var(--rsv-sp-4);
  border:1px solid var(--rsv-brand);border-radius:var(--rsv-r-md);padding:12px 16px}
/* 날짜 칸은 «버튼» 이다. 눌러서 달력을 여는 것이므로 테두리 없이 내용만 놓는다 */
.s-date{flex:1;display:flex;align-items:center;justify-content:center;gap:var(--rsv-sp-3);
  padding:8px 10px;border-radius:var(--rsv-r-sm);cursor:pointer;transition:background .15s}
/* hover 는 «중립 회색» 이다. 연둣빛(--rsv-brand-tint #F2FAEC)을 쓰면 흰 바탕 위에서
   누렇게 떠 보인다 — 브랜드 초록도 아니고 회색도 아닌 색이 손끝을 따라다닌다.
   같은 이유로 스테퍼·필터 항목 hover 도 이 값으로 맞췄다. */
.s-date:hover{background:var(--rsv-surface-sunken)}
/* 「입실일자」 pill — 값과 라벨이 나란히 서므로 라벨은 테두리로 묶어 구분한다 */
.s-tag{flex:none;border:1px solid var(--rsv-line);border-radius:var(--rsv-r-pill);
  padding:6px 16px;font-size:var(--rsv-fs-sm);font-weight:700;color:var(--rsv-text)}
.s-date b{font-size:18px;font-weight:700;color:var(--rsv-text);white-space:nowrap}
.s-cal{width:20px;height:20px;flex:none;color:var(--rsv-text-3)}
.s-sep{width:1px;height:22px;background:var(--rsv-line);flex:none}
.search-go{flex:none;background:var(--sage);color:var(--dark-ink);border-radius:var(--rad-s);
  font-size:15px;font-weight:800;padding:14px 40px;transition:.2s}
.search-go:hover{background:var(--sage-deep)}
/*
 * 좁은 화면 — 날짜·인원을 화면 위에 붙인다.
 *
 * 예전에는 밴드가 그냥 흘러가 버려서, 목록을 조금만 내려도 「지금 며칠·몇 명으로 보고 있는지」가
 * 사라졌다. 객실 카드 하나가 화면을 거의 채우는 폭이라 두어 장만 넘겨도 그렇게 된다.
 *
 * 자리를 내주려고 두 가지를 한다.
 *   ① 헤더(.hd)의 sticky 를 푼다 — 메뉴는 이미 하단 탭바에 있어 로고를 계속 붙여 둘 이유가 없다.
 *   ② 밴드를 한 줄로 압축한다 — 보조 설명(small)은 접고 값만 남긴다.
 * 조회 버튼도 뺀다: 날짜 「선택 완료」와 인원 「적용」이 그 자리에서 곧바로 조회하고
 * 조건은 고르는 즉시 목록에 반영되므로, 좁은 줄에서 자리만 차지한다.
 */
@media(max-width:760px){
  /* 헤더 · 밴드 · 조건 줄이 «세 층으로 쌓여» 화면 위에 붙는다.
     각자 부모가 달라 서로의 높이를 모르므로, 위 두 층의 실제 높이를 main.js 가 재서
     --hd-h · --band-h 로 넘긴다 (값이 없으면 0 이라 그냥 겹치지 않고 맨 위에 붙는다). */
  .hd{position:sticky;top:0;z-index:100}
  /* ⚠ z-index 는 담기 바(150)·하단 탭바(140)보다 «높아야» 한다. sticky + z-index 는
     쌓임 맥락을 만들어서, 안에 든 날짜 시트(.range-pop, z 200)가 밴드 값으로 눌린다 —
     90 을 주면 전체 화면 달력 위로 탭바가 얹힌다. 서로 겹칠 일은 없다(위/아래 끝). */
  .band{position:sticky;top:var(--hd-h,0px);z-index:160}
  /* 좌우 여백은 본문(.wrap)과 같은 16px 로 맞춘다 — .wrap 쪽 규칙은 아래 «본문 폭» 에 있다 */
  .band-in{padding:8px 16px}
  /* 셋을 한 줄에 넣으면 날짜가 잘린다. 날짜 둘만 나란히 두고 버튼은 아래로 내린다 */
  .band-box{flex-wrap:wrap;gap:var(--rsv-sp-2);padding:8px 10px}
  .s-date{flex:1 1 40%;flex-direction:column;gap:2px;padding:6px 4px}
  .s-tag{padding:3px 10px;font-size:11px}
  .s-date b{font-size:14px}
  .s-cal{display:none}          /* 좁은 줄에서 아이콘은 자리만 먹는다 */
  .s-sep{display:none}
  .search-go{flex:1 1 100%;padding:11px 0}
  /* 날짜 문구는 길다. 줄을 접는 대신 말줄임 — 밴드 높이가 글자에 따라 들썩이면 안 된다 */
  .search-go{display:none}
}

/* 날짜 범위 팝오버 */
/* 가운데 정렬 — 예전에는 left:24px 로 밴드 왼쪽 끝에 붙었다. 날짜 칸이 「입실 · 퇴실」
   둘로 나뉘면서 어느 칸에서 열든 달력은 왼쪽에만 떠, 퇴실일을 누르면 달력이 엉뚱한 쪽에
   나타났다. 두 칸 «사이» 를 기준으로 삼을 수도 없다 — 칸 너비가 글자 길이에 따라 변한다.
   밴드 폭 한가운데면 어느 칸에서 열어도 같은 자리다. */
.range-pop{position:absolute;top:calc(100% + 6px);left:50%;transform:translateX(-50%);
  z-index:120;width:648px;
  background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:var(--sh-lg);padding:14px;
  /* 날짜 칸은 글자라, 손가락으로 굴리면 스크롤 대신 텍스트가 선택된다(iOS 확인).
     달력에서 글자를 긁을 일은 없으므로 선택·길게 눌러 나오는 메뉴를 함께 끈다. */
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
/* 두 달을 나란히. 달 사이 경계선이 있어야 "8월 31일"과 "9월 1일"이 붙어 보이지 않는다 */
.rc-months{display:grid;grid-template-columns:1fr 1fr;gap:24px}
.rc-months .rc-month + .rc-month{border-left:1px solid var(--line);padding-left:24px}
.rc-title{display:block;text-align:center;font-size:14.5px;font-weight:800;margin-bottom:8px}
/* 이동 버튼은 두 달 바깥 양 끝에 둔다 — 어느 달에 딸린 버튼인지 헷갈리지 않게 */
.rc-nav{position:absolute;top:14px;width:30px;height:30px;border-radius:8px;
  border:1px solid var(--line2);background:var(--card);
  font-size:14px;font-weight:800;color:var(--ink2);transition:.15s;z-index:1}
.rc-prev{left:14px}
.rc-next{right:14px}
.rc-nav:hover:not(:disabled){border-color:var(--sage);color:var(--sage)}
/* 예약 범위 밖의 달 — 눌러도 전부 비활성인 달이 나오므로 아예 잠근다 */
.rc-nav:disabled{color:var(--line2);border-color:var(--line);background:var(--bg);cursor:default}
.rc-dow{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;font-size:11px;font-weight:800;
  color:var(--ink2);padding:4px 0;border-bottom:1px solid var(--line);margin-bottom:4px}
/* 요일·공휴일 색은 관리자 달력(랙 · 예약현황 · 요금관리 · 공용 날짜 피커)과 같은 토큰을 쓴다.
   예전에는 여기만 #A0503A/#3F5F86 로 하드코딩돼 있어 브랜드 색을 바꿔도 안 따라왔다.
   이 줄은 모바일의 고정 요일줄(.rc-dow-fixed)도 함께 받는다 — 같은 요소가 두 클래스를 쓴다. */
.rc-dow .sun{color:var(--danger)}
.rc-dow .sat{color:var(--info)}
.rc-grid{display:grid;grid-template-columns:repeat(7,1fr)}
.rc-day{height:38px;display:grid;place-items:center;font-size:13px;font-weight:600;border-radius:8px;
  cursor:pointer;transition:.12s;position:relative}
/* 고른 날(start/end)은 hover 에서 뺀다. 빼지 않으면 :hover 쪽 명시도가 높아
   선택 배경을 덮어써, 흰 글씨가 연한 배경에 얹혀 방금 고른 날이 사라진 것처럼 보인다.
   터치 기기는 탭한 뒤에도 :hover 가 남아 있어 특히 눈에 띈다. */
.rc-day:hover:not(.off):not(.dis):not(.start):not(.end){background:var(--sage-bg)}
.rc-day.off{visibility:hidden}
.rc-day.dis{color:var(--line2);cursor:default}
/* 순서 주의 — .holiday 가 .sat 뒤에 와야 한다. 명시도가 같아 순서가 승패를 정하는데,
   앞으로 옮기면 토요일에 걸린 공휴일(2026-10-03 개천절)이 그냥 토요일 색으로 나온다. */
.rc-day.sun{color:var(--danger)}
.rc-day.sat{color:var(--info)}
.rc-day.holiday{color:var(--danger)}
/* 고를 수 없는 날은 무슨 날이든 회색이다. 공휴일만 빨갛게 남으면 누를 수 있어 보인다 */
.rc-day.dis.sun,.rc-day.dis.sat,.rc-day.dis.holiday{color:var(--line2)}
.rc-day.in-range{background:var(--sage-bg);border-radius:0}
.rc-day.start,.rc-day.end{background:var(--sage);color:var(--on-brand) !important;font-weight:800;border-radius:8px}
.rc-day.start.has-range{border-radius:8px 0 0 8px}
.rc-day.end.has-range{border-radius:0 8px 8px 0}
.rc-day.today::after{content:"";position:absolute;bottom:4px;width:4px;height:4px;border-radius:50%;background:var(--terra)}
.rc-hint{margin-top:8px;font-size:11.5px;font-weight:600;color:var(--ink2);text-align:center;
  background:var(--bg);border-radius:8px;padding:7px}
/* 예약 가능한 마지막 날 안내. 비어 있으면(경계를 못 받았을 때) 자리도 차지하지 않는다 */
.rc-range{font-size:11.5px;font-weight:600;color:var(--ink2);text-align:center}
.rc-range:not(:empty){margin-top:6px}
/* 데스크톱에서는 시트용 조각(헤더·요약·하단바)을 쓰지 않는다 */
.rc-sheet-head,.rc-sum,.rc-dow-fixed,.rc-actions{display:none}

/* ── 모바일: 전체 화면 시트 ──
   좁은 화면에 두 달을 나란히 두면 한 칸이 30px 이하로 줄어 손가락으로 못 누른다.
   그래서 화면을 덮는 시트로 바꾸고 예약 가능한 달을 전부 쌓아 세로로 굴린다.
   이동 버튼이 사라지므로 「다음 달이 안 열린다」 같은 막다른 길도 같이 사라진다. */
@media(max-width:720px){
  body.rc-sheet-open{overflow:hidden}
  /* ⚠ transform 을 «반드시» 되돌린다. 넓은 화면의 가운데 정렬이 translateX(-50%) 인데,
     여기서는 inset:0 로 화면을 꽉 채우므로 그게 남으면 시트가 화면 밖으로 절반 밀린다. */
  .range-pop{position:fixed;inset:0;top:0;left:0;right:0;bottom:0;width:auto;transform:none;
    border:0;border-radius:0;box-shadow:none;padding:0;z-index:200;
    display:flex;flex-direction:column}
  .rc-nav{display:none}

  .rc-sheet-head{display:flex;align-items:center;justify-content:center;position:relative;
    padding:16px;border-bottom:1px solid var(--line);flex:0 0 auto}
  .rc-sheet-head b{font-size:16px;font-weight:800}
  .rc-close{position:absolute;left:10px;top:50%;transform:translateY(-50%);
    width:40px;height:40px;border-radius:10px;background:none;font-size:16px;color:var(--ink2)}

  /* 지금 무엇이 잡혔는지 항상 위에 보인다 — 굴려 내려가도 선택 상태를 놓치지 않는다 */
  .rc-sum{display:block;flex:0 0 auto;padding:14px 16px;font-size:15px;font-weight:800;
    color:var(--ink);border-bottom:1px solid var(--line)}

  /* 요일 줄은 달마다 반복하지 않고 하나만 위에 고정한다 */
  .rc-dow-fixed{display:grid;flex:0 0 auto;font-size:12px;padding:10px 0;margin:0;
    background:var(--card);border-bottom:1px solid var(--line)}
  .rc-month .rc-dow{display:none}

  .rc-months{display:block;position:relative;flex:1 1 auto;overflow-y:auto;
    -webkit-overflow-scrolling:touch;padding:4px 10px 20px}
  .rc-months .rc-month + .rc-month{border-left:0;padding-left:0}
  .rc-title{text-align:left;font-size:16px;font-weight:800;padding:18px 6px 10px}

  /* 손가락으로 누를 수 있는 크기. 44px 은 터치 타깃 최소 권장치다 */
  .rc-day{height:46px;font-size:15px;border-radius:10px}
  .rc-day.start,.rc-day.end{border-radius:10px}
  .rc-day.start.has-range{border-radius:10px 0 0 10px}
  .rc-day.end.has-range{border-radius:0 10px 10px 0}

  .rc-foot{flex:0 0 auto;padding:12px 16px calc(12px + env(safe-area-inset-bottom));
    border-top:1px solid var(--line);background:var(--card)}
  /* 「체크인 날짜를 선택해 주세요」 는 위 요약 줄이 이미 말하고 있다. 둘 다 두면
     날짜를 골라 둔 상태에서도 고르라고 하는 꼴이 된다 */
  .rc-hint{display:none}
  .rc-range{font-size:12.5px}
  .rc-actions{display:flex;align-items:center;gap:12px;margin-top:10px}
  .rc-reset{flex:0 0 auto;padding:14px 16px;font-size:14px;font-weight:700;
    color:var(--ink2);background:none;border-radius:10px}
  .rc-reset:disabled{color:var(--line2)}
  .rc-done{flex:1 1 auto;height:52px;border-radius:12px;background:var(--sage);
    color:var(--dark-ink);font-size:16px;font-weight:800}
  .rc-done:disabled{background:var(--line);color:var(--ink3)}
}

/* 인원 팝오버 */
.g-hint{margin-top:10px;font-size:11.5px;color:var(--ink2);line-height:1.6}

/* ── 본문 레이아웃 (사이드바 + 목록) ── */
/* width:100% 가 있어야 한다. body 가 flex column 이고 .wrap 은 margin:0 auto 라,
   가로 auto 마진이 stretch 를 이겨 «내용 폭»으로 줄어든다 — 내용이 화면보다 넓으면
   그만큼 본문이 «넓어져» 페이지 전체가 오른쪽으로 삐져나간다. */
.wrap{max-width:1160px;margin:0 auto;padding:0 24px;width:100%}
/* 좁은 화면에서는 좌우를 16px 로 줄여 헤더·담기 바와 맞춘다. 24px 은 그냥 버리는 폭이라,
   인원 ± 버튼처럼 한 줄을 셋으로 나눠 쓰는 자리가 그만큼 좁아진다.
   ⚠ 이 규칙은 위 .wrap 보다 «뒤» 에 있어야 한다 — 미디어쿼리는 명시도를 올리지 않아
   앞에 두면 같은 명시도끼리 뒤엣것(24px)이 이긴다. */
@media(max-width:760px){.wrap{padding:0 16px}}
/* 조건이 «배치도와 목록 사이» 로 내려오면서 한 칸이 됐다 (2026-09-01).
   예전에는 236px 기둥이 왼쪽에 서서, 배치도에서 방을 보고 목록으로 내려오는 흐름을
   가로로 한 번 꺾었고 조건을 안 쓰는 손님에게도 목록 폭을 236px 뺏었다.
   .flt-back 이 display:contents 라 .filter 가 그대로 첫 줄, section 이 둘째 줄이 된다. */
.layout{display:grid;grid-template-columns:1fr;gap:0;align-items:start;padding-top:28px}
@media(max-width:900px){.layout{padding-top:16px}}
/* 그리드 칸의 최소 너비는 «내용의 min-content» 다. 안에 가로 스크롤 줄(.chips)이 있으면
   그 줄이 접히지 않은 폭만큼 칸이 벌어지고, 좁은 화면에서는 그만큼 오른쪽이 잘린다.
   0 으로 내려야 칸이 화면에 맞고, 넘치는 것은 스크롤 줄이 «자기 안에서» 굴린다. */
.layout > section{min-width:0}

/* ── 결제를 마치지 않은 «내» 예약 안내 ──
   담았던 방이 목록에서 사라진 이유와, 되돌아갈 길을 함께 말한다. */
.pending{margin-top:20px;background:var(--terra-bg);border:1px solid var(--terra-line);border-radius:var(--rad);
  padding:14px 18px;display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.pending .pd-txt{flex:1;min-width:0}
.pending .pd-txt b{display:block;font-size:14.5px;font-weight:800;color:var(--terra)}
.pending .pd-txt small{display:block;font-size:12.5px;color:var(--ink2);line-height:1.6;margin-top:3px}
.pending .pd-left{font-weight:800;color:var(--danger);font-style:normal}
.pending .pd-act{display:flex;align-items:center;gap:10px;flex:none}
.pending .pd-go{font-size:13.5px;font-weight:800;color:var(--dark-ink);background:var(--sage);
  border-radius:var(--rad-s);padding:11px 20px;transition:.2s;white-space:nowrap}
.pending .pd-go:hover{background:var(--sage-deep)}
/* 링크에서 버튼으로 바뀌었다 — 그 자리에서 놓는다 (ui.js pendingBar 주석).
   font/cursor 를 되돌리지 않으면 버튼 기본 글꼴이 그대로 나와 옆 버튼과 어긋난다. */
.pending .pd-cancel{font:inherit;font-size:13px;font-weight:700;color:var(--ink2);
  border:1px solid var(--line2);cursor:pointer;
  border-radius:var(--rad-s);padding:10px 16px;transition:.2s;white-space:nowrap;background:var(--card)}
.pending .pd-cancel:disabled{opacity:.6;cursor:default}
.pending .pd-cancel:hover{border-color:var(--danger-line);color:var(--danger)}
@media(max-width:640px){
  .pending{padding:13px 15px;gap:12px}
  .pending .pd-act{width:100%}
  .pending .pd-go,.pending .pd-cancel{flex:1;text-align:center;padding:12px 10px}
}

/* 필터 사이드바 */
.filter{background:var(--card);border:1px solid var(--line);border-radius:var(--rad);padding:20px 22px;position:sticky;top:86px}
.filter .f-t{font-size:13px;font-weight:800;padding-bottom:12px;border-bottom:1px solid var(--line3)}
.flt-group{padding:16px 0;border-bottom:1px solid var(--line3)}
.flt-group .g-label{font-size:12px;font-weight:800;color:var(--ink2);letter-spacing:.06em;margin-bottom:10px}
.flt-item{display:flex;align-items:center;gap:9px;font-size:13.5px;color:#3F4239;padding:5px 0;cursor:pointer}
.flt-none{font-size:12.5px;color:var(--ink2)}
.flt-item input{width:15px;height:15px;accent-color:var(--sage)}
.flt-reset{width:100%;margin-top:16px;font-size:13px;font-weight:700;color:var(--ink2);
  border:1px solid var(--line2);border-radius:var(--rad-s);padding:11px;transition:.2s;background:none}
.flt-reset:hover{border-color:var(--sage);color:var(--sage)}
/* 바닥 버튼 줄 — 적용은 시트(좁은 화면)에서만 보인다. 넓은 화면은 아래 미디어 쿼리가 줄을 지운다 */
.flt-foot{display:flex;gap:8px;margin-top:16px}
.flt-foot .flt-reset{margin-top:0}
.flt-apply{display:none}
/* 껍데기는 데스크톱 레이아웃에서 사라진다 — .filter 가 그대로 그리드 칸이 된다 */
.flt-back{display:contents}
.flt-close{display:none}

/* 고른 조건 태그. 드롭다운을 닫으면 값이 안 보이므로 이 줄이 «무엇으로 좁혔는지» 를 들고 있다. */
.flt-picked{display:none;align-items:center;gap:6px;flex-wrap:wrap}
.flt-picked:empty{display:none}
.flt-tag{display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:700;
  background:var(--sage-tint);color:var(--sage);border-radius:999px;padding:4px 5px 4px 10px}
.flt-tag button{padding:0 3px;font-size:12px;line-height:1;color:inherit;opacity:.7;background:none;border:0}
.flt-tag button:hover{opacity:1}

/* ── 넓은 화면 — 조건이 가로 밴드가 된다 ──────────────────────────────
   마크업은 시트와 «같은 것 하나» 다. 데스크톱용을 따로 만들면 조건 목록이 두 곳에 생기고
   한쪽만 고치는 사고가 난다 (관리자 OFFLINE_METHODS 가 그랬다). */
@media(min-width:901px){
  .filter{position:static;display:flex;align-items:center;flex-wrap:wrap;gap:8px;
    padding:12px 14px;margin-bottom:10px}
  /* 태그가 없을 때도 밴드와 목록 사이가 벌어져야 한다.
     .flt-picked 는 :empty 면 사라지므로 그 몫을 섹션이 들고 있는다. */
  .layout > section{padding-top:8px}
  /* 「조건」 제목은 드롭다운 이름들이 대신한다 */
  .filter .f-t{display:none}
  .flt-group{position:relative;padding:0;border-bottom:0}

  /* 묶음 이름 → 드롭다운 버튼 */
  .flt-group > .g-label{display:inline-flex;align-items:center;gap:6px;margin:0;
    font-size:13.5px;font-weight:600;letter-spacing:0;color:var(--ink2);
    background:var(--card);border:1px solid var(--line2);border-radius:var(--rad-s);
    padding:9px 13px;transition:.2s;white-space:nowrap;cursor:pointer}
  .flt-group > .g-label::after{content:"▾";font-size:9px;opacity:.65}
  .flt-group > .g-label:hover{border-color:var(--sage);color:var(--sage)}
  .flt-group > .g-label[aria-expanded="true"]{border-color:var(--sage);color:var(--sage)}
  .flt-group > .g-label.has{background:var(--sage-tint);border-color:var(--sage);
    color:var(--sage);font-weight:800}
  .flt-group > .g-label .g-n{font-size:11px;font-weight:800;background:var(--sage);
    color:var(--dark-ink);border-radius:999px;padding:0 6px;line-height:1.6}

  /* 값 목록 → 팝오버. 열기 전에는 그리지 않는다 */
  .flt-values{position:absolute;top:calc(100% + 6px);left:0;z-index:120;min-width:172px;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--rad);
    padding:8px;box-shadow:0 10px 28px rgba(31,36,30,.13);display:none}
  .flt-group.is-open > .flt-values{display:block}
  .flt-values .flt-item{padding:7px 8px;border-radius:6px;white-space:nowrap}
  .flt-values .flt-item:hover{background:var(--rsv-surface-sunken)}
  .flt-values .flt-none{padding:7px 8px}

  .flt-picked{display:flex;margin:0 0 8px}
  /* 바닥 버튼 줄은 밴드에서 사라진다 — 초기화가 그대로 밴드의 한 칸이 된다 */
  .flt-foot{display:contents}
  /* 초기화는 오른쪽 끝. 고른 것이 없으면 눌러도 할 일이 없다 */
  .flt-reset{width:auto;margin:0 0 0 auto;padding:9px 14px;font-size:12.5px}
  .flt-reset[disabled]{opacity:.4;cursor:default}
  .flt-reset[disabled]:hover{border-color:var(--line2);color:var(--ink2)}
}
@media(max-width:900px){
  /* 좁은 화면 — «조건» 버튼으로 여는 시트. 예전에는 여기서 사이드바를 통째로 감췄는데,
     대신 나오는 칩 줄은 시설유형만 그려서 구역·시설옵션으로 좁힐 길이 사라졌다. */
  .flt-back{display:none;position:fixed;inset:0;z-index:280;background:rgba(31,36,30,.42);
    backdrop-filter:blur(2px);align-items:center;justify-content:center;padding:20px}
  .flt-back.open{display:flex}
  .filter{position:relative;top:auto;width:100%;max-width:420px;max-height:calc(100vh - 40px);
    overflow-y:auto;overscroll-behavior:contain;border-radius:16px;padding:20px 18px;
    animation:pop .3s cubic-bezier(.2,.8,.2,1) both}
  .filter .f-t{display:flex;align-items:center;gap:8px}
  /* 시트에서는 열고 닫을 것이 없다 — 버튼이지만 예전 라벨 그대로 보인다.
     실제 잠금(aria-disabled·tabindex)은 main.js 가 건다. */
  .flt-group > .g-label{display:block;width:100%;text-align:left;background:none;
    border:0;padding:0;cursor:default}
  .flt-group > .g-label .g-n{display:none}
  .flt-picked{display:none}
  /* 적용이 주 버튼이다. 목록이 길어도 손이 닿게 시트 바닥에 붙인다
     (.filter 의 padding 20px 만큼 내려야 시트 끝에 맞닿는다) */
  .flt-foot{position:sticky;bottom:-20px;margin:16px -18px -20px;padding:12px 18px 16px;
    background:var(--card);border-top:1px solid var(--line3)}
  .flt-foot .flt-reset{width:auto;flex:0 0 auto;padding:12px 14px}
  .flt-apply{display:block;flex:1;font-size:14px;font-weight:800;color:var(--rsv-text-on-brand);
    background:var(--rsv-brand);border:0;border-radius:var(--rad-s);padding:12px}
  .flt-close{display:grid;place-items:center;margin-left:auto;width:30px;height:30px;
    border-radius:8px;font-size:13px;color:var(--ink2);background:var(--card);border:1px solid var(--line2)}
  /* 시트가 화면을 덮는 동안 뒤 목록이 같이 굴러가면 어느 쪽을 만지는지 알 수 없다
     (달력 시트의 rc-sheet-open 과 같은 처리) */
  body.flt-sheet-open{overflow:hidden}
}

/* 섹션 타이틀 — 진녹색 바 (당진 스테이의 .room-info 를 그대로 옮겼다).
 *
 * 흰 바탕에 카드가 줄줄이 늘어서면 「어디서부터가 목록인가」가 사라진다.
 * 색을 채운 띠 하나가 그 경계를 만든다 — 당진 사이트가 객실선택·결제금액 안내
 * 두 군데에서 같은 띠를 쓰는 이유다. 그래서 여기도 «한 벌» 로 두고 둘 다 쓴다.
 *
 * 실측값: padding 10px 20px · radius 5px · 좌 16px/700 · 우 14px/500 · #204A12
 */
.sec-t{display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin:0 0 var(--rsv-sp-4);padding:10px 20px;
  background:var(--rsv-brand);color:var(--rsv-text-on-brand);
  border-radius:var(--rsv-r-sm);flex-wrap:wrap}
.sec-t h2{font-size:var(--rsv-fs-name);font-weight:700;letter-spacing:-.01em}
/* ⚠ 색을 상속시키지 않는다. 전역 span 규칙이 --ink2(회색)라 녹색 위에서 읽히지 않는다. */
.sec-t span{font-size:var(--rsv-fs-body);font-weight:500;color:var(--rsv-text-on-brand)}
@media(max-width:560px){
  /* 좁은 화면에서 좌우를 고집하면 오른쪽 안내가 두세 글자씩 끊겨 접힌다. 세로로 쌓는다. */
  .sec-t{flex-direction:column;align-items:flex-start;gap:2px;padding:10px 16px}
  .sec-t span{font-size:var(--rsv-fs-sm)}
}

/* 필터 줄 (모바일) — «조건» 버튼 + 유형 칩 */
.fltbar{display:none}
@media(max-width:900px){
  /* 가운데가 아니라 «윗줄» 을 맞춘다. .chips 는 숨긴 스크롤바 자리로 padding-bottom:4px 을
     달고 있어 상자가 칩보다 4px 크다 — 가운데로 맞추면 그 절반인 2px 만큼 칩이 떠올라
     「조건」 버튼과 높낮이가 어긋나 보인다. 두 상자의 높이는 33px 로 이미 같다. */
  .fltbar{display:flex;align-items:flex-start;gap:8px;margin:0 0 14px;min-width:0}
  .fltbar .chips{margin:0;min-width:0}
}
/* 좁은 화면에서는 헤더·검색 밴드 바로 아래에 함께 붙는다 — 조건과 유형 칩도 목록을 내리는
   내내 손에 닿아야 한다. 두 층의 높이는 main.js 가 재서 --hd-h · --band-h 로 넣는다.
   바탕색을 깔지 않으면 아래로 지나가는 카드가 칩 사이로 비쳐 보인다. */
@media(max-width:760px){
  /* ⚠ 아래 여백은 padding 이 아니라 margin 이다. padding 은 sticky 요소의 «배경 안쪽» 이라
     카드 위 테두리가 그 배경 경계에 그대로 맞닿아 «잘린 것처럼» 보였다 — 선택된 카드의
     초록 테두리에서 특히 눈에 띈다. margin 으로 빼면 배경 밖에 실제 간격이 생긴다. */
  .fltbar{position:sticky;top:calc(var(--hd-h,0px) + var(--band-h,0px));z-index:80;
    margin:0 0 var(--rsv-sp-3);padding:10px 0;background:var(--bg)}
}
.flt-open-btn{flex:none;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  font-size:12.5px;font-weight:700;color:var(--ink2);background:var(--card);
  border:1px solid var(--line2);border-radius:999px;padding:8px 14px;transition:.2s}
.flt-open-btn.on{border-color:var(--sage);color:var(--sage);font-weight:800}
.flt-open-btn .n{display:inline-grid;place-items:center;min-width:16px;height:16px;padding:0 4px;
  border-radius:999px;background:var(--sage);color:var(--on-brand);font-size:10.5px;font-weight:800}

/* 필터 칩 (모바일).
   스크롤바를 숨긴 가로 스크롤러라 그냥 두면 «오른쪽이 잘린» 것처럼 보인다 (실제로 그런
   제보를 받았다). 굴릴 수 있는 쪽 끝을 흐려 「더 있다」를 말한다 — 끝에 닿으면 사라진다.
   폭은 --fl/--fr 로만 준다: 한 줄짜리 mask 하나로 좌·우를 같이 다루기 위해서다. */
.chips{display:none;gap:6px;flex-wrap:nowrap;overflow-x:auto;margin:0 0 14px;padding-bottom:4px;scrollbar-width:none;
  --fl:0px;--fr:0px;
  -webkit-mask-image:linear-gradient(to right,transparent 0,#000 var(--fl),#000 calc(100% - var(--fr)),transparent 100%);
          mask-image:linear-gradient(to right,transparent 0,#000 var(--fl),#000 calc(100% - var(--fr)),transparent 100%)}
.chips.fade-l{--fl:26px}
.chips.fade-r{--fr:26px}
.chips::-webkit-scrollbar{display:none}
.chip{font-size:12.5px;font-weight:600;color:var(--ink2);background:var(--card);border:1px solid var(--line2);
  border-radius:999px;padding:8px 16px;transition:.2s;white-space:nowrap;flex:none}
.chip.on{background:var(--sage);border-color:var(--sage);color:var(--on-brand);font-weight:800}
@media(max-width:900px){.chips{display:flex}.chips[hidden]{display:none !important}}

/* ── 객실 목록 (요약 카드, SPEC 4-1) ──
 *
 * 카드는 «어느 객실인가» 와 «몇 명인가» 를 말한다. 옵션은 다음 화면이 맡는다.
 * 값은 docs/reservation-redesign/tokens.css 의 --rsv-* 를 참조한다.
 */
.rooms{display:flex;flex-direction:column;gap:var(--rsv-sp-3);padding-bottom:40px}
.rooms-notice{margin:0 0 12px;padding:11px 14px;border-radius:var(--rsv-r-md);
  background:var(--rsv-brand-tint);border:1px solid var(--rsv-line);
  font-size:var(--rsv-fs-sm);font-weight:700;color:var(--rsv-brand);line-height:var(--rsv-lh)}
.rooms .empty{text-align:center;color:var(--rsv-text-2);font-size:var(--rsv-fs-body);padding:64px 0;
  background:var(--rsv-surface);border:1px dashed var(--rsv-line);border-radius:var(--rsv-r-lg)}

.room{background:var(--rsv-surface);border:1px solid var(--rsv-line);border-radius:var(--rsv-r-lg);
  padding:var(--rsv-sp-3);display:grid;grid-template-columns:var(--rsv-thumb-card) 1fr;
  gap:var(--rsv-sp-3);align-items:stretch;cursor:pointer;
  transition:border-color var(--rsv-dur-state) ease,box-shadow var(--rsv-dur-state) ease;
}
.room.is-new{animation:pop .4s cubic-bezier(.2,.8,.2,1) both}
@keyframes pop{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
/* 선택 시 테두리가 굵어지면 카드가 1px 씩 움직인다 — padding 으로 상쇄한다 (SPEC 4-1) */
.room.sel{border:1.5px solid var(--rsv-brand);padding:11.5px}
.room:focus-visible{outline:2px solid var(--rsv-brand);outline-offset:2px}

/* 담기 한 건이 캠핑톡 응답을 기다리는 동안 다른 객실 클릭을 막는다 (2026-11-05 정책 복원).
   누른 카드(.is-busy)는 밝게 두어 「지금 반응하고 있는 방」임을 보이고, 나머지는
   반투명 + 포인터 차단으로 「대기 중」을 알린다. 스피너는 .r-pick 의 .btn-loading 이 맡는다. */
body.is-pick-busy .room:not(.is-busy){opacity:.55;pointer-events:none;filter:saturate(.7)}
body.is-pick-busy .room.is-busy{cursor:wait}

/* 내 결제 대기 예약이 잡고 있는 객실.
   «보이되 담을 수 없다» — 안 보이면 방이 사라진 것처럼 보이고, 담을 수 있으면 두 번 잡는다.
   그래서 커서도 손가락이 아니고, 눌러도 아무 일이 없다는 것이 색으로 먼저 읽혀야 한다. */
.room.held{cursor:default;border-style:dashed;background:var(--rsv-surface-2,#faf9f6)}
.room.held .r-photo{opacity:.7}
.r-held-badge{flex:0 0 auto;align-self:flex-start;padding:3px 10px;border-radius:999px;
  background:var(--rsv-warn-bg,#fdf1e3);color:var(--rsv-warn,#b26a1a);
  font-size:12px;font-weight:700;white-space:nowrap}
.r-held-msg{margin:6px 0 0;color:var(--rsv-ink-2,#6b6f63);font-size:13px}
.r-held-act{margin-top:10px}
.r-held-go{display:inline-block;padding:8px 16px;border-radius:var(--rsv-r-sm,8px);
  background:var(--rsv-brand);color:#fff;font-size:13px;font-weight:700;text-decoration:none}
.r-held-go:hover{filter:brightness(1.06)}
.r-held-go:focus-visible{outline:2px solid var(--rsv-brand);outline-offset:2px}

/* 사진 자리는 «중립 회색» 이다. 웜 베이지(#E2DDD0)였는데 흰 바탕으로 바뀌면서
   혼자 누렇게 떴다 — 사진이 안 붙은 카드가 고장난 것처럼 보였다.
   최소 높이를 두는 것은 세로로 짧은 카드에서 사진이 띠처럼 눌리기 때문이다. */
.r-photo{position:relative;border-radius:var(--rsv-r-md);
  background:var(--rsv-surface-sunken) center/cover no-repeat;
  background-image:repeating-linear-gradient(135deg,rgba(0,0,0,.05) 0 1px,transparent 1px 11px)}
.r-photo.has-img{cursor:zoom-in}
.r-shots{position:absolute;left:6px;bottom:6px;font-size:10.5px;font-weight:700;
  color:var(--rsv-text-on-brand);background:rgba(0,0,0,.6);border-radius:var(--rsv-r-sm);padding:2px 7px}
.r-zone{position:absolute;top:6px;left:6px;font-size:10.5px;font-weight:700;
  color:var(--rsv-text-on-brand);background:rgba(0,0,0,.6);border-radius:var(--rsv-r-sm);padding:2px 7px}

.r-body{display:flex;flex-direction:column;gap:var(--rsv-sp-1);min-width:0}
.r-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--rsv-sp-2)}
.r-title{min-width:0}
/* 긴 이름은 한 줄 말줄임. 금액은 절대 줄바꿈되지 않는다 (SPEC 4-1) */
.r-body h3{font-size:var(--rsv-fs-name);font-weight:600;color:var(--rsv-text);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/*
 * 아주 좁은 화면(≤389px)에서는 «두 줄까지» 편다.
 *
 * 한 줄 말줄임(SPEC 4-1)은 이름 «뒤» 를 자르는데, 이 시설의 이름은 뒤가 「3호」처럼
 * 카드를 구별하는 번호다. 360px 에서 21곳 중 17곳, 375px 에서 14곳이 그 번호를 잃었다
 * (390px 이상은 한 곳도 안 잘린다 — 그래서 경계를 389px 로 잡았다).
 * 「A구역 - STANDARD 3호」와 「… 8호」가 둘 다 「A구역 - STANDARD…」로 보이면
 * 무엇을 담는지 알 수 없다. 두 줄로 묶어(line-clamp) 카드 높이는 지키면서 번호를 살린다.
 */
@media(max-width:389px){
  .r-body h3{white-space:normal;overflow-wrap:anywhere;
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}
}
.r-body .cap{font-size:var(--rsv-fs-cap);color:var(--rsv-text-2)}
.r-body .cap b{color:var(--rsv-brand);font-weight:700}

/* 카드 안 인원 줄 (2026-09-02). 예전의 «요약 + 변경 링크»(.r-sum/.r-edit)를 대신한다 —
   요약을 읽고 링크를 눌러 시트를 여는 대신, 고칠 것을 그 자리에 둔다.
   라벨과 스테퍼를 붙여 짝을 만들고, 항목들은 내용 크기대로 흐르다 넘치면 줄을 바꾼다
   (권종은 관리자가 만드는 것이라 셋으로 못박을 수 없다). */
.r-pax{display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--rsv-sp-2) var(--rsv-sp-4);margin:var(--rsv-sp-1) 0}
.r-pax-item{display:flex;align-items:center;gap:var(--rsv-sp-2)}
.r-pax-name{font-size:var(--rsv-fs-sm);color:var(--rsv-text-2);white-space:nowrap}
/* 카드 안에서는 조금 작게 — 스물여덟 장이 각자 스테퍼 셋을 들고 있다 */
.r-pax .rsv-stepper button{width:30px;height:30px;font-size:15px}
.r-pax .rsv-stepper__val{min-width:26px;font-size:var(--rsv-fs-sm)}

/*
 * 좁은 화면에서는 스테퍼 대신 «요약 한 줄» 을 둔다 (2026-09-03).
 *
 * 실측: 375px 화면에서 카드 본문은 235px 인데 스테퍼 한 벌이 118.5px + 간격 16px 이라
 * 권종 셋이면 387.5px 이 필요하다 — 석 줄로 쌓여 카드 한 장이 화면의 4분의 1을 먹었다.
 * 390px 도 가용 253px 대 필요 253.0px 으로 종이 한 장 차이라, 권종이 넷이 되거나 이름이
 * 한 글자 길어지는 순간 무너진다. 카드 폭을 다 내줘도(358px) 387.5px 에 못 미친다.
 *
 * 그래서 고르는 일은 시트(.rsv-sheet)로 내보내고, 카드에는 «지금 몇 명인지» 만 남긴다.
 * 두 벌을 다 그려 두고 CSS 로 가른다 — 화면을 돌릴 때마다 JS 로 다시 그리면 스테퍼를
 * 누르던 손끝에서 카드가 갈아 끼워진다.
 */
.r-pax-sum{display:none}
@media(max-width:760px){
  .r-pax{display:none}
  .r-pax-sum{display:flex;align-items:center;justify-content:space-between;
    gap:var(--rsv-sp-3);margin:var(--rsv-sp-1) 0;min-width:0}
  .r-pax-sum-txt{font-size:var(--rsv-fs-sm);color:var(--rsv-text-2);min-width:0;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* 「인원 변경」은 카드 전체가 이미 시트를 여는 과녁이라 «표지» 에 가깝다. 그래도 버튼으로
     두는 것은 키보드·스크린리더에서 그 길이 이름을 갖게 하기 위해서다. */
  .r-pax-edit{flex:none;font-size:var(--rsv-fs-sm);font-weight:700;color:var(--rsv-brand);
    text-decoration:underline;text-underline-offset:2px;padding:2px 0;background:none}
}
.r-addon{display:flex;align-items:center;justify-content:space-between;gap:var(--rsv-sp-2);
  min-width:0;font-size:var(--rsv-fs-sm);color:var(--rsv-text-2)}
.r-addon span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.r-addon b{flex:none;color:var(--rsv-accent);font-weight:600}

.r-price{display:flex;align-items:baseline;justify-content:flex-end;gap:var(--rsv-sp-2);
  margin-top:auto;white-space:nowrap}
.r-price .lbl{font-size:var(--rsv-fs-cap);color:var(--rsv-text-2)}
.r-price b{font-size:var(--rsv-fs-price);font-weight:700;color:var(--rsv-text)}

/* ── 결제금액 안내 (당진 스테이 이식) ──
 *
 * 목록 «아래» 본문 흐름 안에 있는 패널이다. 떠 있는 담기 바와 역할이 갈린다:
 * 담기 바는 굴리는 내내 따라다니며 남은 시간을 말하고, 이 패널은 멈춰 서서 내역을 편다.
 *
 * 금액 줄은 <dl> 이다 — 「이름: 값」 쌍이 네 개라 목록이 아니라 정의 목록이 맞다.
 * 스크린리더가 「객실요금, 200,000원」으로 짝지어 읽는다.
 */
.paysum{margin:var(--rsv-sp-5) 0 40px}
.paysum-body{display:grid;grid-template-columns:1fr auto;gap:var(--rsv-sp-4);
  align-items:start;padding:var(--rsv-sp-5);
  background:var(--rsv-surface);border:1px solid var(--rsv-line);border-radius:var(--rsv-r-lg)}
.paysum-rooms{min-width:0}
.paysum-rooms>b{display:block;font-size:var(--rsv-fs-name);font-weight:700;color:var(--rsv-text);
  margin-bottom:var(--rsv-sp-3)}
.paysum-rooms ul{list-style:none;display:flex;flex-direction:column;gap:var(--rsv-sp-2)}
.paysum-rooms li{font-size:var(--rsv-fs-sm);color:var(--rsv-text-2);line-height:var(--rsv-lh)}
.paysum-rooms li b{color:var(--rsv-text);font-weight:600}
/* 아직 아무것도 안 담았을 때. 자리를 비워 두면 패널이 「고장난 상자」로 보인다 */
.paysum-rooms .none{color:var(--rsv-text-3)}

.paysum-amt{text-align:right;white-space:nowrap}
.paysum-amt>div{display:flex;align-items:baseline;justify-content:flex-end;
  gap:var(--rsv-sp-4);font-size:var(--rsv-fs-sm);color:var(--rsv-text-2)}
.paysum-amt dd{font-variant-numeric:tabular-nums}
.paysum-amt .paysum-total{margin-bottom:var(--rsv-sp-3)}
.paysum-amt .paysum-total dt{font-size:var(--rsv-fs-name);font-weight:700;color:var(--rsv-text)}
.paysum-amt .paysum-total dd{font-size:var(--rsv-fs-total);font-weight:700;color:var(--rsv-brand)}

.paysum-foot{display:flex;justify-content:flex-end;margin-top:var(--rsv-sp-4)}
.paysum-foot .rsv-cta{min-width:180px}

@media(max-width:760px){
  /* 좁은 화면에서 좌우 두 칸을 고집하면 금액이 오른쪽 끝에 몰려 이름과 멀어진다.
     세로로 쌓고, 금액 묶음은 선 하나로 객실 목록과 나눈다. */
  .paysum-body{grid-template-columns:1fr;gap:var(--rsv-sp-3);padding:var(--rsv-sp-4)}
  .paysum-amt{padding-top:var(--rsv-sp-3);border-top:1px solid var(--rsv-line-soft)}
  .paysum-amt>div{justify-content:space-between}

  /* 「다음단계」를 숨긴다 — 담기 바의 「예약하기」와 «같은 곳으로 가는 같은 버튼» 이고,
     좁은 화면에서는 둘이 맞붙어 초록 버튼 두 개가 겹친 것처럼 보인다.
     담기 바는 화면 아래 붙어 있어 언제든 닿으므로 잃는 길이 없다.
     넓은 화면에서는 담기 바가 가운데 카드로 떨어져 있어 그대로 둔다. */
  .paysum-foot{display:none}
}

/*
 * 카드에 손을 얹으면 «누를 수 있다» 를 알린다.
 *
 * 인원 스테퍼가 카드 안으로 들어오면서 「선택하면 인원을 설정합니다」 안내 줄이 사라졌고,
 * 그 뒤로 카드가 눌리는 것인지 알려 주는 것이 커서 모양뿐이었다.
 *
 * 테두리 «색» 만 바꾸고 굵기는 그대로 둔다 — 굵어지면 카드가 1px 씩 움직인다.
 * 옅은 링을 더해 「지금 이 카드」를 짚어 준다. 바탕은 칠하지 않는다: 카드 안에 흰 스테퍼가
 * 셋 있어서 바탕을 회색으로 깔면 그것들만 떠 보인다.
 */
/*
 * ⚠ hover 규칙은 «마우스가 있는 기기» 로 한정한다 (@media (hover:hover)).
 *   터치 기기에서는 탭한 카드에 :hover 가 «그대로 남는다» — 다른 카드를 누를 때까지
 *   초록 테두리와 링이 붙어 있어 「담긴 카드」로 오해된다. 담김 표시는 .sel 하나뿐이어야 한다.
 */
@media (hover:hover){
  .room:hover{border-color:var(--rsv-brand);box-shadow:0 0 0 3px rgba(var(--sage-rgb),.10)}
  /* 담긴 카드는 이미 초록 테두리다 — 링만 조금 더 또렷하게 해서 «뺄 수 있다» 를 알린다 */
  .room.sel:hover{box-shadow:0 0 0 3px rgba(var(--sage-rgb),.18)}
  .room:hover .r-pick-hint{opacity:1}
  /* 손을 얹으면 과녁인 원도 같이 반응해야 «저기를 누르는구나» 로 읽힌다 */
  .room:hover .r-pick:not(.on){border-color:var(--rsv-brand)}
}
/* 「담기」/「빼기」 — 평소에는 자리만 지키고 있다가 손을 얹으면 나타난다.
   opacity 로만 감춘다: display 로 지우면 나타날 때 원이 옆으로 밀린다. */
.r-actions{display:flex;align-items:center;gap:var(--rsv-sp-2)}
.r-pick-hint{font-size:var(--rsv-fs-sm);font-weight:700;color:var(--rsv-brand);
  white-space:nowrap;opacity:0;transition:opacity var(--rsv-dur-state) ease}
.room:focus-within .r-pick-hint{opacity:1}
/*
 * 터치 기기에서는 «항상» 보인다.
 *
 * hover 가 없는 기기에서 opacity:0 + :hover 조합은 「영영 안 보인다」와 같다 — 손님 눈에는
 * 26px 짜리 빈 동그라미만 남아, 그것이 누를 수 있는 것인지 담김 표시인지 알 수 없었다.
 */
@media (hover:none){
  .r-pick-hint{opacity:1}
}
/*
 * ⚠ 단, 좁은 화면에서는 «아예 뺀다».
 *
 * 카드 머리는 「객실명 + 원」 한 줄인데, 그 사이에 「담기」가 끼면 객실명이 그만큼 눌린다 —
 * 이 시설의 이름은 뒤가 「3호」처럼 카드를 구별하는 번호라 말줄임에 가장 먼저 걸리는 곳이다.
 *
 * 빼도 잃는 것이 적다: 좁은 화면에서는 카드를 누르면 시트가 열려 「이 객실 담기 · N원」이
 * 큰 CTA 로 그 말을 하고, 원 자체도 눌리면 초록으로 차고 체크가 들어와 담김을 알린다.
 * 스크린리더에는 그대로 남는다 — 원의 aria-label 과 aria-pressed 가 같은 말을 하고 있고,
 * 이 문구는 어차피 aria-hidden 이라 처음부터 읽히지 않았다.
 *
 * opacity 가 아니라 display 로 지운다. 투명하게만 두면 자리를 그대로 차지해
 * 「이름이 눌리는 것」이 하나도 나아지지 않는다.
 */
@media(max-width:760px){
  .r-pick-hint{display:none}
}

/* 담기 토글 — 색 단독으로 알리지 않는다: 테두리 + 체크 + aria-pressed (SPEC 10) */
.r-pick{flex:none;width:26px;height:26px;border-radius:50%;position:relative;
  border:1.5px solid var(--rsv-line);background:var(--rsv-surface);
  transition:background var(--rsv-dur-state) ease,border-color var(--rsv-dur-state) ease}
.r-pick.on{border-color:var(--rsv-selected);background:var(--rsv-selected)}
.r-pick.on::after{content:'';position:absolute;left:8px;top:5px;width:6px;height:11px;
  border-right:2px solid var(--rsv-text-on-brand);border-bottom:2px solid var(--rsv-text-on-brand);
  transform:rotate(45deg)}
/* 보이는 원은 26px 이지만 누를 자리는 44px 로 넓힌다 */
.r-pick::before{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:44px;height:44px}
/*
 * 빼는 동안에는 체크를 «지우고» 로딩만 남긴다.
 *
 * 체크는 CSS 의사요소(::after)라 StayUI.spin 이 innerHTML 을 바꿔도 그대로 남는다 —
 * 그래서 초록 원 위에 체크와 도는 원이 겹쳐 보였다. 지금 일어나는 일은 «빼는 중» 하나이므로
 * 보이는 것도 하나여야 한다.
 */
.r-pick.btn-loading::after{display:none}
.r-pick.btn-loading{opacity:1}                 /* 26px 원은 흐려지면 아예 안 보인다 */
/*
 * ⚠ 스피너를 transform 으로 가운데 두지 말 것.
 *   회전 애니메이션(@keyframes spin)이 transform:rotate 를 매 프레임 덮어써서
 *   translate(-50%,-50%) 가 지워진다 — 원 가운데가 아니라 «왼쪽 위» 로 튄다.
 *   버튼을 격자로 만들어 정렬을 맡기면 transform 은 회전만 하면 된다.
 */
.r-pick{display:grid;place-items:center}
.r-pick .spinner{width:14px;height:14px;border-width:2px;margin:0;vertical-align:0;
  border-color:rgba(255,255,255,.4);border-top-color:var(--rsv-text-on-brand)}

.r-err{display:none;font-size:var(--rsv-fs-cap);font-weight:600;color:var(--rsv-accent);
  background:var(--rsv-accent-tint);border-radius:var(--rsv-r-sm);padding:6px 10px;margin-top:var(--rsv-sp-1)}
.r-err.show{display:block}

/* ── 인원 선택 시트 (좁은 화면 전용, 2026-09-03 복원) ──
 *
 * 9/1 까지 쓰던 시트를 되살린 것이다. 그때는 인원과 «옵션» 을 함께 맡았는데, 옵션은
 * 다음 화면(/reserve)으로 옮겨 갔으므로 여기에는 인원만 남는다 — 스크롤 없이 한 화면이다.
 *
 * ⚠ 넓은 화면에서는 열지 않는다 (main.js 의 isSheetView). 거기서는 카드 안 .r-pax 가
 *   그대로 맡으므로 이 규칙들이 걸릴 일 자체가 없다.
 */
body.rsv-sheet-open{overflow:hidden}
/* ⚠ z-index 는 토큰(--rsv-z-scrim 50)이 아니라 이 화면의 층에 맞춘다.
   토큰은 예약 화면만 있는 전제로 매겨졌는데, 여기에는 하단 탭바(140)와 담기 바(150)가
   이미 있다. 50 으로 두면 시트가 열려도 탭바가 그 위에 그려져 「담기」 버튼을 덮는다.
   화면을 덮는 것들(.flt-back 280 · .modal-back 300)과 같은 층에 세운다. */
.rsv-sheet-wrap{position:fixed;inset:0;z-index:300;display:flex;
  align-items:flex-end;justify-content:center}
.rsv-scrim{position:absolute;inset:0;border:0;padding:0;background:var(--rsv-scrim)}
.rsv-sheet-wrap.is-open .rsv-scrim{animation:rsvScrim 200ms ease-out both}
@keyframes rsvScrim{from{opacity:0}to{opacity:1}}
/*
 * ⚠ 시트의 «기본» 상태는 제자리(transform 없음)다. 등장 효과는 열릴 때(.is-open)만 얹는다.
 *
 * 예전에는 .rsv-sheet 에 곧바로 animation 을 걸었다. 시트는 페이지가 열릴 때부터
 * hidden(=display:none) 이라 그 애니메이션은 재생되지 않은 채 fill-mode:both 때문에
 * 첫 프레임(translateY(28%))에 «멈춰» 버렸다 — 시트를 열면 화면 아래로 내려간 자리에
 * 그려져 「담기」 버튼이 화면 밖으로 나갔다.
 */
.rsv-sheet{position:relative;z-index:1;width:100%;
  max-height:calc(100% - 34px);overflow-y:auto;overscroll-behavior:contain;
  background:var(--rsv-surface);border-radius:var(--rsv-r-xl) var(--rsv-r-xl) 0 0;
  box-shadow:var(--rsv-shadow-sheet);
  padding:var(--rsv-sp-2) var(--rsv-sp-4) calc(var(--rsv-sp-4) + env(safe-area-inset-bottom))}
.rsv-sheet-wrap.is-open .rsv-sheet{animation:rsvSheet var(--rsv-dur-sheet) var(--rsv-ease) both}
@keyframes rsvSheet{from{transform:translateY(28%);opacity:.4}to{transform:none;opacity:1}}
.rsv-grip{width:36px;height:4px;border-radius:var(--rsv-r-pill);background:var(--rsv-line);
  margin:0 auto var(--rsv-sp-3)}
.rsv-sheet-title{font-size:17px;font-weight:700;color:var(--rsv-text);line-height:1.35}
.rsv-sheet-title:focus{outline:none}
.rsv-sheet-cap{font-size:var(--rsv-fs-cap);color:var(--rsv-text-2);margin-top:2px}
.rsv-sec{font-size:var(--rsv-fs-label);font-weight:700;letter-spacing:.08em;
  color:var(--rsv-text-3);margin:var(--rsv-sp-4) 0 var(--rsv-sp-2)}
/* ⚠ .rsv-row 는 «시트 안으로» 한정한다. 예약 화면의 옵션 표(.rsv-opts .rsv-row)가
   같은 이름을 쓰고 있어, 바깥에 두면 그 표의 여백·밑줄까지 바뀐다. */
.rsv-sheet .rsv-row{display:flex;align-items:center;justify-content:space-between;
  gap:var(--rsv-sp-3);padding:var(--rsv-sp-2) 0;border-bottom:1px solid var(--rsv-line-soft)}
.rsv-sheet .rsv-row:last-child{border-bottom:none}
.rsv-sheet .rsv-row-label{min-width:0}
.rsv-sheet .rsv-row-label b{display:block;font-size:var(--rsv-fs-body);font-weight:600;
  color:var(--rsv-text)}
.rsv-sheet-err{margin-top:var(--rsv-sp-3);padding:9px 12px;border-radius:var(--rsv-r-sm);
  background:var(--rsv-accent-tint);color:var(--rsv-accent);
  font-size:var(--rsv-fs-sm);font-weight:600}
.rsv-sheet-tot{display:flex;align-items:baseline;justify-content:space-between;
  margin-top:var(--rsv-sp-4);padding-top:var(--rsv-sp-3);border-top:1px solid var(--rsv-line);
  font-size:var(--rsv-fs-body);color:var(--rsv-text-2)}
.rsv-sheet-tot strong{font-size:var(--rsv-fs-total);font-weight:700;color:var(--rsv-text)}
#paxSheetCta{margin-top:var(--rsv-sp-3)}

/* ── 넓은 화면(PC) ──
 *
 * 모바일에서 정한 것들을 그대로 늘리지 않는다. 여기서는 폭이 남으므로
 *   ① 썸네일을 키우고
 *   ② 담기 바를 가운데 상자가 아니라 화면 아래 «띠» 로 붙이고(내용은 본문 폭에 정렬)
 */
@media(min-width:761px){
  /* 당진 사이트 실측(193px). 사진을 크게 쓰는 것이 그 디자인의 인상 절반이다 */
  :root{ --rsv-thumb-card:190px }
  .r-photo{min-height:110px}

}

/* ── 홀딩 타이머 (담기 바 안, 「N곳 담김」 아래) ──
 * 담기 바는 이미 어두운 바탕이라 브랜드색 띠를 겹치면 두 겹으로 보인다 — 옅은 반투명으로 얹는다. */
.rsv-hold{display:flex;align-items:center;gap:var(--rsv-sp-2);flex-basis:100%;
  margin:2px 0 0;padding:7px 11px;border-radius:var(--rsv-r-sm);
  background:rgba(255,255,255,.12);color:var(--rsv-text-on-brand);
  font-size:var(--rsv-fs-cap);transition:background var(--rsv-dur-state) ease}
.rsv-hold svg{width:16px;height:16px;flex:none}
.rsv-hold-txt{flex:none}
.rsv-hold-txt b{font-variant-numeric:tabular-nums;font-weight:700}
.rsv-hold-track{flex:1;height:3px;border-radius:var(--rsv-r-pill);
  background:rgba(255,255,255,.25);overflow:hidden;min-width:36px}
.rsv-hold-fill{display:block;height:100%;width:100%;background:var(--rsv-text-on-brand);
  transition:width 1s linear}
/*
 * 임박 — 색만 바꾸지 않는다. 문구도 「곧 만료」로 올라간다 (main.js).
 *
 * 예전에는 띠 전체를 순빨강(#D0121B)으로 칠했다. 담기 바가 이미 진녹색 면이라 그 위에
 * 빨간 판이 얹히면 화면 아래에 «빨간 줄» 이 그어진 것처럼 보였다 — 남은 시간을 알리는
 * 것치고 너무 크게 말한다. 붉은 기운만 얹고, 실제로 빨개지는 것은 «줄어드는 진행 바» 다.
 * 그 편이 「무엇이 줄고 있는가」를 가리키기도 한다.
 */
.rsv-hold.is-urgent{background:rgba(208,18,27,.34)}
.rsv-hold.is-urgent .rsv-hold-txt{color:var(--rsv-accent-on-brand)}
.rsv-hold.is-urgent .rsv-hold-fill{background:var(--rsv-accent-on-brand)}

/* 담긴 것이 있으면 하단 바가 선다 (SPEC 3).
   본문 아래는 담기 바 높이(--cartbar-h, ui.js 가 잰다)만큼 비운다 — 안 그러면 목록 끝이 가린다.
   ⚠ 2026-09-11 이전에는 여기서 탭바를 감추고 담기 바를 탭바 «위» 로 띄웠다. 메뉴가 서랍으로
     올라가면서 바닥을 다투는 것이 없어져, 담기 바는 그냥 바닥에 선다. */
@media(max-width:760px){
  body.has-cart{padding-bottom:var(--cartbar-h,0px)}
  body.has-cart .cartbar.show ~ .topbtn{bottom:calc(var(--cartbar-h,0px) + 10px)}
}
/* 넓은 화면도 담기 바가 화면 바닥 «띠» 로 붙는다(아래 «하단 담기 바» 의 min-width:761px).
   여백 규칙이 위 좁은 화면 블록에만 있어서 넓은 화면에서는 푸터 아래 126px 이 바에 가렸다
   (2026-09-11). 좁은 화면은 위 :has(.gnb.tabbar) 규칙이 명시도로 이기므로 그대로다.
   ⚠ 미디어쿼리 안으로 다시 넣지 말 것 — PublicCartBarKeepsFooterVisibleTest 가 막는다. */
body.has-cart{padding-bottom:var(--cartbar-h,0px)}

/* ── 하단 액션 바 (예약 정보 입력 · 결제) ──
 *
 * 2026-09-02 부터 «넓은 화면에서도» 뜬다. 예전에는 좁은 화면 전용이었다 — 넓은 화면에는
 * 오른쪽에 결제 금액 상자가 붙어 있어 총액과 버튼이 늘 보였기 때문이다.
 * 당진 스테이 디자인으로 옮기면서 그 사이드바를 걷어냈고, 그러자 넓은 화면에서
 * 폼을 채우는 동안 총액도 다음 버튼도 사라졌다. 그 자리를 이 바가 대신한다.
 *
 * 늘 떠 있다 — 홀딩 타이머가 이 바 안에 있어서다. 같은 버튼을 위아래로 두지 않으려고
 * 본문 맨 아래 버튼 줄(#reserveFoot)을 감춘다 (.rsv-foot 주석). .is-hidden 은 이제 붙이는 곳이 없다.
 */
.rsv-actionbar{position:fixed;left:0;right:0;bottom:0;z-index:150;
  background:var(--rsv-brand);color:var(--rsv-text-on-brand);
  padding:12px var(--rsv-sp-4) calc(12px + env(safe-area-inset-bottom));
  box-shadow:0 -8px 24px -12px rgba(0,0,0,.45);
  transition:transform .28s var(--rsv-ease), opacity .28s var(--rsv-ease)}
/* 감출 때 display:none 이 아니라 «밀어낸다» — 높이를 재는 ResizeObserver 가 0 을 읽으면
   본문 아래 여백이 사라져 페이지가 통째로 튄다. */
.rsv-actionbar.is-hidden{transform:translateY(110%);opacity:0;pointer-events:none}
/*
 * 담기 바(.cart-card)와 «똑같은» 두 줄 배치다 —
 *   윗줄  「총 N건 결제금액」            「총 결제 금액 / 금액」
 *   아랫줄 「홀딩 띠 ────────」          「이전단계 · 결제 단계로」
 *
 * flex 로 흘리면 홀딩 띠가 자기 줄을 독점해 세 줄이 되고 바가 목록을 그만큼 가린다.
 * grid-template-areas 로 자리를 직접 지정해 DOM 순서에 기대지 않는다.
 */
.rsv-actionbar-in{max-width:1200px;margin:0 auto;
  display:grid;grid-template-columns:1fr auto;
  grid-template-areas:"info total" "hold go";
  column-gap:var(--rsv-sp-4);row-gap:10px;align-items:center}
.ab-info{grid-area:info;font-size:var(--rsv-fs-sm);color:rgba(255,255,255,.75)}
.ab-info b{color:var(--rsv-text-on-brand);font-size:14.5px}
.ab-total{grid-area:total;text-align:right;white-space:nowrap}
.ab-total small{display:block;font-size:10.5px;color:rgba(255,255,255,.5)}
.ab-total b{font-size:20px;color:var(--rsv-text-on-brand)}
.rsv-actionbar .rsv-hold{grid-area:hold;margin:0}
.rsv-actionbar-btns{grid-area:go}
.rsv-actionbar-btns{display:flex;gap:var(--rsv-sp-2)}
.rsv-back{min-height:var(--rsv-touch-cta);padding:0 26px;border-radius:var(--rsv-r-md);
  background:var(--rsv-surface);color:var(--rsv-brand);font-size:15px;font-weight:700}
.rsv-actionbar .rsv-cta{background:var(--rsv-surface);color:var(--rsv-brand)}
.rsv-actionbar .rsv-cta:hover:not(:disabled){background:var(--rsv-surface-sunken)}
body:has(.rsv-actionbar){padding-bottom:var(--actionbar-h,96px)}
@media(max-width:760px){
  /*
   * 좁은 화면은 «세 줄» 이다:
   *   1줄  「총 N건 결제금액」        「금액」
   *   2줄  홀딩 띠 ───────────────────
   *   3줄  [이전단계] [결제 단계로]
   *
   * 예전에는 네 줄이었다(185px = 812px 화면의 23%). 격자를 풀어 세로로 쌓았더니
   * 「총 N건 결제금액」과 「총 결제 금액」이 «같은 말을 두 번» 하면서 각자 한 줄을 먹었다.
   * 금액은 건수 줄의 오른쪽으로 올리고, 되풀이되는 작은 라벨은 지운다.
   */
  .rsv-actionbar-in{display:grid;grid-template-columns:1fr auto;
    grid-template-areas:"info total" "hold hold" "go go";
    column-gap:var(--rsv-sp-3);row-gap:8px;align-items:center}
  .ab-info{text-align:left}
  .ab-total{text-align:right}
  .ab-total small{display:none}
  .ab-total b{font-size:22px}
  .rsv-actionbar-btns .rsv-back{flex:0 0 38%;padding:0}
  .rsv-actionbar .rsv-cta{flex:1}
  /* 폴백은 세 줄 바의 실측(≈150px)보다 넉넉하게. 모자라면 본문 마지막 줄이 바 뒤로 들어간다 */
  body:has(.rsv-actionbar){padding-bottom:var(--actionbar-h,164px)}

  /* 위쪽 결제 상자의 버튼은 아래 바가 대신한다 */
  .paybox .pay-btn{display:none}
  /*
   * 결제 화면의 상자는 좁은 화면에서 «껍데기» 가 된다.
   *
   * 이 상자에 들어 있던 것은 총액과 결제하기 둘뿐인데, 버튼은 바로 위 규칙이 감추고
   * 총액은 아래 바가 똑같이 다시 보여준다. 남는 것은 아무것도 안 나누는 구분선 하나와
   * 빈 어두운 카드다 — 갤럭시에서 실제로 그렇게 떴다 (2026-09-02).
   * 같은 금액이 두 번 뜨는 것도 «어느 쪽이 정본인가» 를 흔든다.
   *
   * 예약 화면(reserve.html)의 paybox 는 건드리지 않는다 — 그쪽은 객실료·옵션료 내역이
   * 있어서 합계가 그 계산의 마지막 줄이다. 지우면 내역만 남고 답이 사라진다.
   * 그래서 결제 화면 전용 클래스(.paybox-pay)에만 건다.
   *
   * 총액 줄은 «지우지» 않고 감추기만 한다 — 하단 바가 이 값을 그대로 비춘다
   * (web/js/ui.js 의 mountActionBar).
   */
  .paybox-pay .row.tot{display:none}
  /* 카드를 벗었으니 문구도 어두운 배경용 색을 벗는다 (카드 자체를 벗기는 규칙은
     .paybox 정의 «뒤» 에 있어야 이긴다 — 아래 .pay-err 근처 참고) */
  .paybox-pay .pay-note{color:var(--ink2);margin-top:0}
}

/* ── 예약 정보 입력 화면 (당진 스테이 이식, 2026-09-02) ──
 *
 * 「제목 + 3px 진녹색 밑줄」 한 벌이 이 화면의 뼈대다. 목록 화면은 «색을 채운 띠»
 * (.sec-t)를 쓰는데, 여기서는 섹션이 다섯이라 그걸 반복하면 화면이 초록 줄무늬가 된다.
 * 밑줄은 같은 초록을 쓰면서도 면적이 작아 여러 번 나와도 배경으로 물러난다.
 * 값은 당진 사이트 실측이다 — h2 36px/700, padding 21px 0, margin-top 80px.
 */
.rsv-page{max-width:1200px}
.rsv-sec-h{display:flex;align-items:center;justify-content:space-between;gap:var(--rsv-sp-4);
  border-bottom:3px solid var(--rsv-brand);margin-top:64px}
.rsv-sec-h h2{font-size:32px;font-weight:700;color:var(--rsv-text);
  padding:21px 0;letter-spacing:-.02em}
.rsv-loading{padding:40px 0;text-align:center;color:var(--rsv-text-2);font-size:var(--rsv-fs-body)}
.rsv-loading.err{color:var(--rsv-accent)}
.rsv-loading a{color:var(--rsv-brand);font-weight:700;text-decoration:underline}

/* 객실 안내 — 사진 · 이름/정원/상세보기 · 객실요금 (설명은 모달로, V071) */
.rsv-rooms{display:flex;flex-direction:column}
.rsv-room{display:grid;grid-template-columns:210px 1fr auto;gap:var(--rsv-sp-5);
  align-items:center;padding:30px 0;border-bottom:1px solid var(--rsv-line-soft)}
.rsv-room-photo{height:140px;border-radius:var(--rsv-r-md);
  background:var(--rsv-surface-sunken) center/cover no-repeat}
.rsv-room-body{min-width:0}
.rsv-room-head{display:flex;align-items:baseline;gap:var(--rsv-sp-3);flex-wrap:wrap}
.rsv-room-head b{font-size:24px;font-weight:700;color:var(--rsv-brand)}
.rsv-room-head .cap{font-size:var(--rsv-fs-name);color:var(--rsv-text-2)}
/* 인원 바로 옆. 이름·정원과 한 줄에 서므로 높이를 글줄에 맞춘다 */
.rsv-room-more{border:1px solid var(--rsv-line);background:var(--rsv-surface);
  color:var(--rsv-text-2);border-radius:999px;padding:4px 12px;
  font-size:var(--rsv-fs-sm);font-family:inherit;cursor:pointer;
  transition:border-color .15s,color .15s}
.rsv-room-more:hover{border-color:var(--rsv-brand);color:var(--rsv-brand)}
.rsv-room-more:focus-visible{outline:2px solid var(--rsv-brand);outline-offset:2px}
/* 상세 보기 모달 본문 — 약관 모달 껍데기를 그대로 쓰고 안쪽만 라벨–값 표로 */
.rsv-room-spec{display:grid;grid-template-columns:80px minmax(0,1fr);
  gap:10px 16px;margin:0}
.rsv-room-spec dt{font-weight:700;color:var(--rsv-text)}
.rsv-room-spec dd{margin:0;color:var(--rsv-text-2);word-break:keep-all}
.rsv-room-price{text-align:right;white-space:nowrap}
.rsv-room-price small{display:block;font-size:var(--rsv-fs-sm);color:var(--rsv-text-2)}
.rsv-room-price b{font-size:26px;font-weight:700;color:var(--rsv-text)}

/* 눌러서 크게 볼 수 있는 사진 — 돋보기 배지로 클릭 가능함을 알린다 */
.rsv-room-photo.is-zoomable{position:relative;cursor:zoom-in}
.rsv-room-photo.is-zoomable:focus-visible{outline:2px solid var(--rsv-brand);outline-offset:2px}
.rsv-room-zoom{position:absolute;right:8px;bottom:8px;width:28px;height:28px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.55);color:#fff;border-radius:50%;pointer-events:none}
.rsv-room-zoom svg{width:16px;height:16px}

/* 사진 확대 라이트박스 (전체화면 오버레이) */
.rsv-lightbox{position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,.85);
  display:flex;align-items:center;justify-content:center;padding:24px;cursor:zoom-out}
.rsv-lightbox img{max-width:100%;max-height:100%;border-radius:var(--rsv-r-md);
  box-shadow:0 10px 40px rgba(0,0,0,.5)}
.rsv-lightbox-close{position:absolute;top:16px;right:16px;width:40px;height:40px;
  border:0;border-radius:50%;background:rgba(255,255,255,.15);color:#fff;
  font-size:20px;line-height:1;cursor:pointer}
.rsv-lightbox-close:hover{background:rgba(255,255,255,.28)}

/* 예약 정보 확인 표 */
.rsv-table-wrap{overflow-x:auto}
/*
 * table-layout:fixed — 칸 폭을 «내용이 아니라 우리가» 정한다.
 *
 * 기본값(auto)에서는 브라우저가 글자 길이를 재서 폭을 나눈다. 그래서 인원을 한 명 올릴
 * 때마다 「성인 2」→「성인 3 · 아동 1」, 금액도 「990원」→「2,490원」 으로 글자 수가 바뀌고,
 * 표 전체가 매번 다시 배치돼 화면이 미세하게 흔들렸다. 폭을 못박으면 그 일이 없다.
 *
 * 아래 백분율 합은 100 이다. 좁은 화면에서는 min-width 가 가로 스크롤을 만든다.
 */
.rsv-table{width:100%;border-collapse:collapse;table-layout:fixed}
.rsv-table th:nth-child(1),.rsv-table td:nth-child(1){width:24%}   /* 객실명/기간 */
.rsv-table th:nth-child(2),.rsv-table td:nth-child(2){width:26%}   /* 예약일 */
.rsv-table th:nth-child(3),.rsv-table td:nth-child(3){width:9%}    /* 기간 */
.rsv-table th:nth-child(4),.rsv-table td:nth-child(4){width:17%}   /* 인원 */
.rsv-table th:nth-child(5),.rsv-table td:nth-child(5){width:24%}   /* 결제 금액 */
/* 반려동물 칸이 켜지면 여섯 칸이 된다 — 인원·금액에서 조금씩 떼어 준다 */
.rsv-table thead .col-pet:not([hidden]) ~ th{width:20%}
.rsv-table:has(thead .col-pet:not([hidden])) th:nth-child(4),
.rsv-table:has(thead .col-pet:not([hidden])) td:nth-child(4){width:14%}
.rsv-table:has(thead .col-pet:not([hidden])) th:nth-child(5),
.rsv-table:has(thead .col-pet:not([hidden])) td:nth-child(5){width:10%}
.rsv-table:has(thead .col-pet:not([hidden])) th:nth-child(6),
.rsv-table:has(thead .col-pet:not([hidden])) td:nth-child(6){width:20%}
/* 편집기 줄은 colspan 이라 위 폭 규칙에 걸리지 않는다 — 그대로 전체 폭을 쓴다 */
.rsv-table .sel-editrow td{width:auto}
.rsv-table th{font-size:18px;font-weight:700;color:var(--rsv-text);
  padding:22px 8px;border-bottom:1px solid var(--rsv-line-soft)}
.rsv-table td{padding:18px 8px;text-align:center;vertical-align:middle;
  font-size:var(--rsv-fs-name);color:var(--rsv-text-2);border-bottom:1px solid var(--rsv-line)}
.rsv-table .c-room{font-size:19px;font-weight:700;color:var(--rsv-brand)}
/*
 * 예약일은 «두 줄을 묶어» 가운데에 둔다.
 *
 * 각 줄을 따로 가운데 정렬하면 두 줄의 폭이 같을 때만 배지가 세로로 맞는다 —
 * 지금은 날짜가 늘 같은 자릿수라 맞지만, 문구가 하나라도 바뀌면(「입실 예정」 같은)
 * 배지가 어긋난다. 감싸개를 inline-block 으로 두고 그 «덩어리» 를 가운데 두면,
 * 안쪽은 계속 왼쪽 정렬이라 배지가 언제나 한 세로선에 선다.
 */
.rsv-table .c-date{text-align:center}
.rsv-dates{display:inline-block;text-align:left}
.rsv-date{display:flex;align-items:center;gap:10px;white-space:nowrap}
.rsv-date + .rsv-date{margin-top:8px}
.rsv-date-tag{flex:none;display:inline-grid;place-items:center;width:48px;height:25px;
  border:1px solid var(--rsv-line-soft);border-radius:2px;
  font-size:11px;font-weight:500;color:var(--rsv-text-2)}
.rsv-table .c-price{white-space:nowrap;position:relative}
.rsv-table .c-price > b{font-size:24px;font-weight:700;color:var(--rsv-brand)}
/* 그 객실의 내역. 목록 화면의 「결제금액 안내」와 같은 세 줄이다 */
.rsv-breakdown{margin-top:10px;padding:10px 12px;border-radius:var(--rsv-r-sm);
  background:var(--rsv-surface-sunken);font-size:var(--rsv-fs-cap);color:var(--rsv-text-2)}
.rsv-breakdown div{display:flex;justify-content:space-between;gap:var(--rsv-sp-4)}
.rsv-acts{display:flex;gap:var(--rsv-sp-2);justify-content:center;margin-top:12px;flex-wrap:wrap}
/* 「인원 변경」은 손님이 «누를 수 있는 것» 으로 보여야 한다 — 예전에는 맨몸 회색 글자라
   못 찾았다(2026-09-06). 브랜드색 알약으로 세워 눈에 걸리게 한다. (빼기는 아래 .rsv-x 로 뺐다) */
.rsv-acts .rm{font-family:inherit;line-height:1;white-space:nowrap;cursor:pointer;
  border:1px solid var(--rsv-brand);border-radius:var(--rsv-r-pill);padding:8px 15px;
  font-size:13px;font-weight:600;background:var(--rsv-surface);color:var(--rsv-brand);
  transition:background .15s,border-color .15s,color .15s}
.rsv-acts .js-edit:hover{background:var(--rsv-surface-sunken)}

/* 「빼기」는 «이 객실을 지우는» 동작이라 행 우측의 × 로 뺐다 — 인원 변경(초록 알약)과 뜻이
   섞이지 않고, 카트 한 줄을 닫듯 지운다. 짚으면 빨강으로 지우는 동작임을 알린다.
   .js-rm 클래스는 그대로라 reserve.js 의 빼기 핸들러가 그대로 잡는다. */
.rsv-x{position:absolute;top:12px;right:6px;width:26px;height:26px;padding:0;
  border:1px solid var(--rsv-line);border-radius:50%;background:var(--rsv-surface);
  color:var(--rsv-text-2);font-size:18px;line-height:1;cursor:pointer;
  display:grid;place-items:center;
  transition:border-color .15s,color .15s,background .15s}
.rsv-x:hover{border-color:var(--rsv-accent);color:var(--rsv-accent);background:var(--rsv-accent-tint)}
.rsv-dropped{margin-top:10px;font-size:var(--rsv-fs-sm);color:var(--terra)}
/* 편집기 줄은 «표의 한 칸» 이라 가운데 정렬을 물려받는다 — 왼쪽으로 되돌린다 */
/*
 * 편집기 줄은 «표 밖» 처럼 보이면 안 된다.
 *
 * 표 칸은 가운데 정렬인데 이 줄만 왼쪽 끝에서 시작해서, 「기준 2명 · 최대 4명」과 스테퍼가
 * 표 테두리에 붙어 어느 줄에 딸린 것인지 읽히지 않았다. 안쪽 여백을 표 칸(18px)에 맞추고
 * 옅은 바탕을 깔아 «위 줄의 속» 임을 보인다.
 */
.rsv-table .sel-editrow td{text-align:left;padding:0 24px;border-bottom:1px solid var(--rsv-line);
  background:var(--rsv-surface-sunken)}
.rsv-table .sel-editrow:has(.sel-edit[hidden]) td{padding:0;border:0}

/* 합계금액 · 총 결제 금액 */
.rsv-sum-row,.rsv-final-row{display:flex;align-items:center;justify-content:space-between;
  gap:var(--rsv-sp-4);padding:26px 24px}
.rsv-sum-row{font-size:19px;font-weight:600;color:var(--rsv-text-2);
  border-bottom:2px solid var(--rsv-text-2)}
/* 총액만 빨강이다 — 당진 사이트와 같은 값(#D0121B = --rsv-accent).
   이 화면에서 빨강은 여기 한 곳뿐이라 「마지막 숫자」로 읽힌다. */
.rsv-final-row{font-size:26px;font-weight:700;color:var(--rsv-accent)}

/* 추가 옵션 — 담은 객실마다 한 묶음.
   방이 하나뿐이면 객실명 줄은 군더더기다(위 표에 이미 있다). :only-child 로 그때만 감춘다. */
.rsv-opts{padding:var(--rsv-sp-5) 0 0}
.rsv-opt-group + .rsv-opt-group{margin-top:var(--rsv-sp-5);
  padding-top:var(--rsv-sp-5);border-top:1px solid var(--rsv-line-soft)}
.rsv-opt-room{display:block;font-size:var(--rsv-fs-name);font-weight:700;
  color:var(--rsv-brand);margin-bottom:var(--rsv-sp-3)}
.rsv-opt-group:only-child .rsv-opt-room{display:none}
/*
 * 날짜 블록 (V064) — 「이용일 : 9월 7일(월)」 아래에 그 밤에 살 수 있는 옵션만 편다.
 *
 * 날짜가 옵션보다 «위» 다. 반대로 옵션 아래에 날짜를 늘어놓으면, 같은 날 무엇무엇을
 * 골랐는지 보려고 목록을 세로로 훑어야 한다 — 손님이 실제로 묻는 것은 「그날 뭘 시킬까」다.
 *
 * 1회 과금 옵션은 「숙박 전체」 블록으로 맨 위에 선다. 날짜마다 반복하면 픽업이 세 번 떠서
 * 「매일 픽업해 준다」로 읽힌다.
 */
.rsv-opt-day + .rsv-opt-day{margin-top:var(--rsv-sp-4)}
.rsv-opt-date{display:block;font-size:var(--rsv-fs-sm);font-weight:700;
  color:var(--rsv-text-2);padding-bottom:6px;border-bottom:1px solid var(--rsv-line-soft)}
/*
 * 옵션은 «표» 다 — 한 줄에 하나, 넓은 화면에서만 두 칸.
 *
 * 예전에는 라벨과 스테퍼를 붙여 옆으로 흘렸다(flex-wrap). 옵션이 둘일 때는 한 줄에 담겨
 * 깔끔했지만, 이름 길이가 제각각이라 스테퍼가 줄마다 다른 자리에 섰다. 옵션이 대여섯 개로
 * 늘면 「화목난로 … [− 0 +] 바베큐세트 … [− 0 +]」가 한 덩어리로 이어져,
 * 어느 스테퍼가 어느 옵션의 것인지 눈으로 되짚어야 한다.
 *
 * 칸을 고정하면 스테퍼가 «같은 세로선» 에 서고, 밑줄이 옵션 하나의 경계를 긋는다.
 * 개수가 늘어도 줄만 늘어난다. 관리자가 옵션을 몇 개 만들지는 정해져 있지 않다.
 */
.rsv-opts .rsv-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:48px;row-gap:0}
.rsv-opts .rsv-row{display:flex;align-items:center;justify-content:space-between;
  gap:var(--rsv-sp-4);min-width:0;padding:14px 0;background:none;border:0;
  border-bottom:1px solid var(--rsv-line-soft)}
/* 마지막 «줄» 에는 밑줄을 긋지 않는다. 두 칸이므로 마지막 항목과 —
   그 줄이 꽉 찼을 때만 — 그 왼쪽 항목까지 둘이다. */
.rsv-opts .rsv-row:last-child,
.rsv-opts .rsv-row:nth-last-child(2):nth-child(odd){border-bottom:none}
.rsv-opts .rsv-row-label{display:block;min-width:0}
.rsv-opts .rsv-row-label b{font-weight:700}
.rsv-opts .rsv-row-label small{color:var(--rsv-text-2);font-size:var(--rsv-fs-cap)}
/* 단가는 이름 아래 «따로» 둔다. 이름 옆에 이어 붙이면 어디까지가 옵션 이름인지 흐려진다 */
.rsv-opts .rsv-row-price{display:block;margin-top:4px;
  font-size:var(--rsv-fs-sm);font-weight:600;color:var(--rsv-text-2)}
/* 「언제부터 쓸 수 있는가」는 «주의» 지 오류가 아니다 — 빨강이 아니라 호박색(--terra) */
.rsv-opts .opt-from{margin-top:4px;font-size:var(--rsv-fs-cap);color:var(--terra)}
.rsv-opts .rsv-stepper{display:inline-flex;width:auto;flex:none}
/* [hidden] 이 이 display 에 져서 안 사라진다 — 체크 전에는 스테퍼를 감춰야 하므로 되돌린다 */
.rsv-opts .rsv-stepper[hidden]{display:none}
/*
 * 한 줄이 «그 날 담는가, 담으면 몇 개인가» 다 (V064·V066).
 *
 * 왼쪽 절반(.rsv-optmain)만 <label> 이다 — 이름·설명·가격 어디를 눌러도 체크가 바뀌되,
 * 오른쪽 스테퍼의 −/+ 는 체크를 건드리지 않는다. 예전에는 줄 전체가 <label> 이라
 * 수량을 올릴 때마다 체크가 함께 뒤집혔다.
 */
.rsv-opts .rsv-optrow{justify-content:space-between}
.rsv-opts .rsv-optmain{display:flex;align-items:center;gap:var(--rsv-sp-3);
  flex:1 1 auto;min-width:0;cursor:pointer}
.rsv-opts .rsv-optchk{flex:none;width:18px;height:18px;margin:0;
  accent-color:var(--rsv-brand);cursor:pointer}
.rsv-opts .rsv-optrow .rsv-row-label{flex:1 1 auto}
/* 「2개부터」는 단가 옆에 붙인다 — 제 줄을 주면 옵션마다 줄 높이가 들쭉날쭉해진다 */
.rsv-opts .opt-min{margin-left:6px;font-weight:600;color:var(--terra)}
/* 체크하면 오른쪽이 개수를 말한다 — 왼쪽의 «몇 개부터» 는 할 일을 다 했고,
   둘이 같이 떠 있으면 한 줄에 같은 숫자가 두 번 적힌다. */
.rsv-opts .rsv-optrow:has(.rsv-optchk:checked) .opt-min{display:none}
.rsv-opts .rsv-optqty{margin-left:var(--rsv-sp-3)}
/* 최소와 최대가 같으면 고를 것이 없다 — 스테퍼 대신 «몇 개인지» 만 세운다.
   자리는 스테퍼와 같다: 체크한 줄들의 개수가 오른쪽에서 한 열로 읽힌다. */
.rsv-opts .rsv-optfixed{flex:none;margin-left:var(--rsv-sp-3);
  font-size:var(--rsv-fs-sm);font-weight:700;color:var(--rsv-text)}
.rsv-opts .rsv-optfixed[hidden]{display:none}
/* 안 고른 줄은 한 톤 내린다 — 고른 것이 먼저 읽혀야 한다 */
.rsv-opts .rsv-optrow:has(.rsv-optchk:not(:checked)) .rsv-row-label b{font-weight:600}
@media(max-width:760px){
  /* 좁은 화면은 한 칸. 두 칸 기준의 «마지막 줄» 규칙도 같이 되돌린다 —
     한 칸에서는 홀수번째 항목이 마지막 줄이 아니다. */
  .rsv-opts .rsv-list{grid-template-columns:minmax(0,1fr)}
  .rsv-opts .rsv-row:nth-last-child(2):nth-child(odd){border-bottom:1px solid var(--rsv-line-soft)}
  .rsv-opts .rsv-row:last-child{border-bottom:none}
}

/* 객실 예약 안내 */
/* 아래 옅은 선으로 끝을 닫는다 — 기존 스테이의 안내 구획과 같은 모양 (2026-10-29) */
.rsv-notice{list-style:disc;padding:26px 0 26px 22px;border-bottom:1px solid var(--rsv-line-soft);
  display:flex;flex-direction:column;gap:10px}
.rsv-notice li{font-size:var(--rsv-fs-name);color:var(--rsv-text-2);line-height:1.7}
/* 객실 유형마다 안내 값이 다를 때의 유형 이름 줄 (V095) — 점 없이, 본문보다 진하게.
   두 번째 묶음부터는 위를 조금 띄워 «여기서 다른 방 이야기» 가 보이게 한다. */
.rsv-notice li.rsv-notice-group{list-style:none;margin-left:-22px;font-weight:700;color:var(--rsv-text)}
.rsv-notice li.rsv-notice-group:not(:first-child){margin-top:10px}

/*
 * 예약 화면의 패널은 «상자를 두르지 않는다».
 *
 * 초록 밑줄 제목(.rsv-sec-h)이 이미 섹션의 시작을 긋고 있어서, 그 바로 아래 다시 테두리를
 * 치면 선이 두 겹이 된다 — 제목선 하나, 상자 윗변 하나. 손님 눈에는 「제목 밖의 상자」라
 * 둘이 한 덩어리로 읽히지 않는다.
 *
 * ⚠ .panel 자체를 고치지 말 것. 결제(pay) · 결제완료 · 예약조회 화면도 이 클래스를 쓰는데,
 *   그 화면들에는 밑줄 제목이 없어 상자가 유일한 경계다. 그래서 .rsv-page 안으로 가둔다.
 */
.rsv-page .panel{background:none;border:0;border-radius:0;padding:22px 0;margin-bottom:0}

/* 본문 맨 아래 버튼 줄 */
/* 아래 여백은 푸터와의 «사이» 다. 0 으로 두면 버튼 바로 밑에 푸터 경계선이 붙어
   버튼이 푸터에 얹힌 것처럼 보인다 — 본문이 여기서 끝난다는 표시가 필요하다. */
/* 본문 맨 아래 버튼 줄은 «모든 폭에서» 감춘다 (2026-10-29) — 고정 바가 같은 버튼을 갖는다.
   예전에는 넓은 화면에서 이 줄을 보이고, 이 줄이 화면에 들어오면 고정 바를 통째로 밀어냈는데
   (ui.js IntersectionObserver), 홀딩 타이머가 그 바 안에 있어 «페이지 끝까지 내리면 타이머가
   사라졌다». 바를 남기고 이 줄을 감추는 것이 좁은 화면이 이미 하던 방식이다.
   마크업은 남긴다 — #submitBtn 이 진짜 버튼이고 바의 버튼은 그것을 누른다. */
.rsv-foot{display:none;align-items:center;justify-content:space-between;
  gap:var(--rsv-sp-4);margin:40px 0 80px}
.rsv-foot .rsv-back{border:1px solid var(--rsv-line);color:var(--rsv-text);white-space:nowrap}
/*
 * .pay-btn 은 원래 «초록 상자 안» 버튼이었다 — width:100% 로 상자를 채우고,
 * 색은 --lime(흰 면) / --lime-ink(초록 글자)라 초록 바닥 위에서만 버튼으로 보였다.
 * 그 상자를 걷어낸 지금은 흰 바탕에 흰 버튼이 되고, width:100% 가 옆의 「이전단계」를
 * 눌러 글자를 두 줄로 접었다. 여기서는 색을 뒤집고 폭을 내용에 맡긴다.
 */
.rsv-foot .pay-btn{width:auto;min-width:200px;margin-top:0;white-space:nowrap;
  background:var(--rsv-cta);color:var(--rsv-text-on-brand)}
.rsv-foot .pay-btn:hover:not(:disabled){background:var(--rsv-cta-hover);filter:none}
.rsv-foot .pay-btn .spinner{border-color:rgba(255,255,255,.35);border-top-color:#fff}

@media(max-width:760px){
  .rsv-sec-h{margin-top:36px}
  .rsv-sec-h h2{font-size:22px;padding:14px 0}
  /* 사진을 위로 올리고 이름·요금을 아래로 — 210px 사진은 좁은 화면의 절반이다 */
  .rsv-room{grid-template-columns:1fr;gap:var(--rsv-sp-3);padding:20px 0}
  .rsv-room-photo{height:180px}
  .rsv-room-price{text-align:left}
  /*
   * 표를 «세로로 접는다».
   *
   * 예전에는 min-width:720px 로 가로 스크롤을 줬다. 「칼럼을 접으면 어느 값이 무엇인지
   * 사라진다」는 이유였는데, 실제로는 더 나빴다 — 374px 화면에 720px 표가 들어가면서
   * «결제 금액» 열이 화면 밖(563~736px)으로 밀려 아예 보이지 않았고, 굴릴 수 있다는
   * 표시도 없었다. 게다가 감싸개(.rsv-table-wrap)의 가로 스크롤바가 「총 결제 금액」
   * 바로 아래에 회색 막대로 그려져, 없는 UI 가 하나 있는 것처럼 보였다.
   *
   * 라벨은 각 td 의 data-label 로 살린다(reserve.js) — 접어도 뜻이 남는다.
   */
  .rsv-table{min-width:0;table-layout:auto}
  .rsv-table thead{display:none}
  .rsv-table,.rsv-table tbody,.rsv-table tr,.rsv-table td{display:block;width:auto}
  .rsv-table th:nth-child(n),.rsv-table td:nth-child(n){width:auto}
  .rsv-table .sel-item{padding:18px 0;border-bottom:1px solid var(--rsv-line)}
  .rsv-table .sel-item td{padding:7px 0;border:0;text-align:right;
    display:flex;align-items:baseline;justify-content:space-between;gap:var(--rsv-sp-4)}
  .rsv-table .sel-item td::before{content:attr(data-label);flex:none;text-align:left;
    font-size:var(--rsv-fs-sm);font-weight:400;color:var(--rsv-text-2)}
  /* 객실명은 «값» 이 아니라 이 묶음의 제목이다 — 라벨을 달지 않고 한 줄 차지한다 */
  .rsv-table .sel-item .c-room{display:block;text-align:left;font-size:17px;padding-top:0}
  .rsv-table .sel-item .c-date{display:block;padding:7px 0}
  /* 날짜는 제 안에 입실일·퇴실일 꼬리표를 이미 갖고 있다. 라벨을 또 붙이지 않는다 */
  .rsv-table .sel-item .c-date::before{content:none}
  .rsv-table .c-date .rsv-date{display:flex;justify-content:space-between;gap:var(--rsv-sp-4)}
  .rsv-table .sel-item .c-price{display:block;text-align:right;padding-top:10px}
  .rsv-table .sel-item .c-price::before{float:left;padding-top:4px}
  /* 빼기(×)는 «객실명 줄» 오른쪽에 둔다 (2026-10-29). 금액 칸 기준으로 두면 접힌 표에서
     금액이 칸 오른쪽 끝에 붙어 ×가 «2,200원» 의 끝자리를 덮었다. 객실명 줄은 왼쪽만 차 있다. */
  .rsv-table .sel-item{position:relative}
  .rsv-table .sel-item .c-price{position:static}
  .rsv-table .sel-item .rsv-x{top:16px;right:0}
  /* 편집 줄은 표 칸이 아니라 «그 아래 딸린 패널» 이다 — 좌우 여백을 0 으로 되돌린다 */
  .rsv-table .sel-editrow td{display:block;padding:0;background:none;border:0;text-align:left}
  .rsv-sum-row,.rsv-final-row{padding:18px 4px}
  .rsv-sum-row{font-size:var(--rsv-fs-name)}
  .rsv-final-row{font-size:20px}
}


/* ── 하단 담기 바 ── */
.cartbar{position:fixed;left:0;right:0;bottom:0;z-index:150;transform:translateY(120%);transition:.4s cubic-bezier(.2,.8,.2,1)}
.cartbar.show{transform:none}
.cart-in{max-width:820px;margin:0 auto 16px;padding:0 16px}
/* ⚠ flex-wrap 은 «항상» 켜 둔다. 홀딩 띠가 flex-basis:100% 로 자기 줄을 차지하는데,
   wrap 이 없으면 같은 줄의 「N곳 담김」이 0 폭으로 눌려 글자가 한 자씩 세로로 쪼개진다. */
.cart-card{background:var(--dark);color:var(--dark-ink);border-radius:12px;
  display:flex;flex-wrap:wrap;align-items:center;gap:10px 18px;
  padding:15px 22px;box-shadow:var(--sh-lg)}
/* 「N곳 담김」은 담은 목록을 여닫는 버튼이다. 화살표는 «목록이 어느 쪽으로 열리는지» 를 가리킨다.
   이 목록은 담기 바 «위로» 펼쳐지므로 접혔을 때 ∧(위로 열림), 펼쳤을 때 ∨(아래로 닫힘)이다
   — 아래로 열리는 흔한 메뉴와 방향이 반대다. */
.cart-card .info{flex:1;min-width:0;text-align:left}
.cart-card .info b{font-size:14.5px}
.cart-card .info b::after{content:'';display:inline-block;margin-left:7px;width:6px;height:6px;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:translateY(2px) rotate(-135deg);transition:transform .2s}
.cartbar.list-open .cart-card .info b::after{transform:translateY(-2px) rotate(45deg)}
.cart-card .info small{display:block;font-size:11.5px;color:rgba(255,255,255,.55);margin-top:1px}

/* 담은 목록 — 담기 바 카드 위로 펼쳐진다. 길어지면 목록 안에서만 굴린다 */
.cart-list{background:var(--dark);color:var(--dark-ink);border-radius:12px;padding:6px;margin-bottom:8px;
  max-height:min(46vh,320px);overflow-y:auto;overscroll-behavior:contain;box-shadow:var(--sh-lg)}
.cl-row{display:flex;align-items:center;gap:10px;padding:6px 8px}
.cl-row + .cl-row{border-top:1px solid rgba(255,255,255,.13)}
.cl-go{flex:1;min-width:0;text-align:left;padding:4px 0}
.cl-go b{display:block;font-size:13.5px;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cl-go small{display:block;font-size:11px;color:rgba(255,255,255,.55)}
.cl-price{font-size:13px;font-weight:800;white-space:nowrap}
/* 44px 은 터치 타깃 최소 권장치다 */
.cl-del{flex:none;display:inline-flex;align-items:center;min-height:44px;padding:0 13px;
  font-size:12.5px;font-weight:700;color:rgba(255,255,255,.85);
  border:1px solid rgba(255,255,255,.3);border-radius:9px;transition:.2s}
.cl-del:hover{background:rgba(255,255,255,.12)}
.cart-card .total{text-align:right;white-space:nowrap}
.cart-card .total small{display:block;font-size:10.5px;color:rgba(255,255,255,.5)}
.cart-card .total b{font-size:20px}
.cart-go{background:var(--lime);color:var(--lime-ink);font-size:14.5px;font-weight:800;border-radius:var(--rad-s);
  padding:13px 30px;transition:.2s;white-space:nowrap}
.cart-go:hover{filter:brightness(1.06)}
/* 좁은 화면에서는 화면 바닥에 붙인다. 홈 인디케이터(아이폰)만 피하면 된다 —
   예전에는 여기서 하단 탭바 높이만큼 더 띄웠는데, 그 탭바가 없어졌다 (2026-09-11).
   이 블록을 위쪽 서랍 블록으로 옮기지 않는 이유: .cart-in 의 margin 단축 속성이 아래에 있어,
   위에서 margin-bottom 만 덮으면 같은 명시도끼리 뒤엣것이 이긴다. */
@media(max-width:760px){
  .cart-in{margin-bottom:calc(11px + env(safe-area-inset-bottom))}
}
@media(max-width:640px){.cart-card{flex-wrap:wrap;gap:8px;padding:13px 15px;border-radius:14px}.cart-go{width:100%;text-align:center}}
/* 넓은 화면 — 담기 바를 가운데 상자가 아니라 화면 아래 «띠» 로 붙인다.
   배경은 바 전체가 깔고, 안쪽 내용만 본문(.wrap)과 같은 1160px 에 맞춰 줄을 세운다.
   ⚠ 이 블록은 위 .cart-in 기본 규칙 «뒤» 에 있어야 한다 — 미디어쿼리는 명시도를 올리지 않아
   앞에 두면 max-width:820px 이 그대로 이긴다. */
@media(min-width:761px){
  .cartbar{background:var(--dark);box-shadow:0 -8px 24px -14px rgba(27,33,22,.5)}
  .cart-in{max-width:1160px;margin:0 auto;padding:12px 24px}
  .cart-list{background:rgba(255,255,255,.08)}
  /*
   * 두 줄로 못박는다 — 「담김 수 · 총액」 / 「홀딩 · 예약하기」.
   *
   * flex 로 흘리면 홀딩 띠가 자기 줄을 독점해 세 줄이 되고, 바가 150px 을 넘어 목록을
   * 그만큼 가린다. 폭이 남는 화면에서 홀딩과 예약 버튼은 같은 줄에 서는 편이 읽기 쉽다.
   * grid-template-areas 로 자리를 직접 지정해 DOM 순서에 기대지 않는다.
   */
  .cart-card{background:none;box-shadow:none;border-radius:0;padding:0;
    display:grid;grid-template-columns:1fr auto;
    grid-template-areas:"info total" "hold go";
    column-gap:var(--rsv-sp-4);row-gap:10px;align-items:center}
  .cart-card .info{grid-area:info}
  .cart-card .total{grid-area:total}
  .cart-card .rsv-hold{grid-area:hold;margin:0}
  .cart-card .cart-go{grid-area:go}
}

/* ── 맨 위로 버튼 ──
 *
 * 담기 바가 떠 있으면 그 «위»로 올라간다 — 겹치면 「예약하기」를 가린다.
 * 높이는 담긴 방 수에 따라 달라지므로 web/js/ui.js 가 재서 --cartbar-h 로 넘긴다.
 * z-index 는 담기 바(150)보다 낮게 둔다: 겹칠 일은 없지만, 어긋나더라도 결제 버튼이 이긴다.
 */
.topbtn{position:fixed;right:20px;bottom:24px;z-index:145;
  width:46px;height:46px;border-radius:50%;
  background:var(--card);border:1px solid var(--line2);color:var(--ink2);
  box-shadow:var(--sh);display:grid;place-items:center;
  opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity .22s,transform .22s,visibility .22s}
.topbtn.show{opacity:1;visibility:visible;transform:none}
.topbtn:hover{color:var(--sage);border-color:var(--sage)}
.cartbar.show ~ .topbtn{bottom:calc(var(--cartbar-h,0px) + 12px)}
/*
 * 예약·결제 화면의 하단 액션 바도 «똑같이» 피한다. 담기 바만 피하고 이 바는 빠뜨려서,
 * /reserve · /pay 에서는 버튼이 바 뒤에 통째로 깔려 아예 보이지 않았다
 * (바 높이 131px 안에 버튼 46px 이 완전히 들어간다).
 *
 * 바가 스스로 물러났을 때(.is-hidden — 본문 맨 아래 버튼 줄이 보이는 동안)는 올리지 않는다.
 * 빈 자리 위에 떠 있으면 그것대로 어긋나 보인다.
 * 높이는 문구에 따라 달라져 ui.js 가 재서 --actionbar-h 로 넘긴다.
 * 폴백은 «넉넉한» 132px 이다 — 홀딩 띠까지 두 줄인 바가 131px 이라, 예전 한 줄 기준 96px 을
 * 그대로 쓰면 변수를 못 받은 순간에 버튼이 바 «속» 에 갇힌다. 남는 편이 가리는 편보다 낫다.
 */
.rsv-actionbar:not(.is-hidden) ~ .topbtn{bottom:calc(var(--actionbar-h,132px) + 12px)}
/* 「움직임 줄이기」를 켠 사람에게는 나타나고 사라지는 것만 남긴다 */
@media(prefers-reduced-motion:reduce){
  .topbtn{transition:opacity .01s,visibility .01s;transform:none}
}
@media(max-width:760px){
  /* 바닥에 앉힌다. 예전에는 하단 탭바 높이만큼 더 올렸는데 그 탭바가 없어졌다 (2026-09-11). */
  .topbtn{right:14px;width:42px;height:42px;
    bottom:calc(14px + env(safe-area-inset-bottom))}
  .cartbar.show ~ .topbtn{bottom:calc(var(--cartbar-h,0px) + 10px)}
  /* 이 블록이 위 규칙보다 뒤라 여기서 한 번 더 적어야 이긴다. */
  .rsv-actionbar:not(.is-hidden) ~ .topbtn{bottom:calc(var(--actionbar-h,132px) + 10px)}
}

/* ── 푸터 ──
 *
 * 높이를 «화면마다 다르게» 두지 않는다. 예전에는 위아래 여백이 넉넉해서, 본문이 짧은
 * 화면(결제 실패·예약 완료)에서는 푸터가 화면의 절반을 차지하고 본문이 긴 화면에서는
 * 얇은 띠로 보였다. 같은 회사 정보를 보여주는 자리가 페이지마다 달라 보일 이유가 없다.
 *
 * 그래서 두 가지를 건다.
 *   ① 여백을 줄이고 min-height 로 띠 높이를 못박는다 — 어느 화면에서나 같은 높이다.
 *   ② body 를 세로 flex 로 만들어 본문이 짧아도 푸터가 화면 아래에 붙는다.
 *      (min-height 만으로는 본문이 짧을 때 푸터가 화면 중간에 떠 버린다)
 * 좁은 화면은 주소가 여러 줄로 접히므로 높이를 풀어 준다 — 못박으면 글자가 잘린다.
 */
body{min-height:100vh;display:flex;flex-direction:column}
body > main,body > .wrap,body > .done-wrap{flex:1 0 auto}
.ft{border-top:1px solid var(--line);background:var(--bg);color:var(--ink);flex:none}
.ft-in{max-width:1160px;margin:0 auto;padding:20px 24px 22px;font-size:13px;line-height:1.65;
  min-height:158px}
.ft-in p{margin:0 0 10px}
.ft-in p.copy{margin:0;font-size:12.5px;color:var(--ink2)}
.ft-logo{display:flex;align-items:center;flex-wrap:wrap;gap:6px 12px;margin-bottom:8px}
.ft-mark{width:28px;height:28px;display:block;margin-bottom:2px}
.ft-logo b{font-size:18px;font-weight:800;letter-spacing:-.01em;color:#2E5F51}
/* 사이트 브랜드 | 운영사(모두패스) 로고를 한 줄로. 로고는 슬로건을 뺀 푸터용 판이다 —
   이 크기에선 슬로건이 3px 로 뭉개진다. 높이 30px ≒ 가로 122px (가이드 최소 70px). */
/* 지점 로고 이미지(footer.logo). 당진은 위아래로 쌓인 로고, 완주는 한 줄로 긴 로고라
   높이·폭 상한을 둘 다 걸어 먼저 닿는 쪽에 맞춘다 (당진 → 높이 48, 완주 → 폭 240). */
.ft-site-logo{display:block;width:auto;height:auto;max-height:48px;max-width:min(240px,100%);flex:none}
.ft-sep{width:1px;height:18px;background:var(--line2);flex:none}
.ft-op-logo{display:block;height:30px;width:auto;flex:none}
.ft-in p.ft-broker{margin:0 0 4px;color:var(--ink2)}
/* 통신판매중개 고지 · 공정위 사업자정보 조회 링크 (전자상거래법 제12조 제4항·제20조) */
.ft-bizinfo{color:var(--ink);text-decoration:underline;text-underline-offset:2px;white-space:nowrap}
.ft-bizinfo:hover{color:var(--sage)}
@media(max-width:760px){.ft-in{min-height:0;padding:18px 16px 20px}
  /* 375px 폭에서 「완주 로고 240 | MODUPASS 122」 가 한 줄을 넘어 세로선만 남고 떨어진다 */
  .ft-site-logo{max-width:180px}.ft-op-logo{height:26px}}

/* ── 스텝 인디케이터 (예약 진행) ── */
.steps{margin:28px 0 24px;display:grid;grid-template-columns:repeat(4,1fr);background:var(--card);
  border:1px solid var(--line);border-radius:var(--rad);overflow:hidden}
.step{display:flex;align-items:center;justify-content:center;gap:9px;font-size:13.5px;font-weight:800;
  color:#A5A395;padding:15px 6px;border-right:1px solid var(--line3)}
.step:last-child{border-right:none}
.step i{font-style:normal;width:21px;height:21px;border-radius:4px;display:grid;place-items:center;
  background:#F1EFE8;font-size:11.5px;color:#A5A395;flex:none}
.step.on{background:var(--sage);color:var(--dark-ink)}
.step.on i{background:rgba(255,255,255,.22);color:var(--dark-ink)}
.step.done{color:var(--sage)}
.step.done i{background:#E4EBE0;color:var(--sage)}
@media(max-width:640px){
  /* 남은 단계의 이름을 숨기면 「3」「4」만 남아 앞으로 무엇을 하는지 알 수 없다.
     숨기는 대신 글자를 줄여 네 칸을 모두 이름째로 보여준다. */
  .step{font-size:10.5px;gap:4px;padding:10px 2px;letter-spacing:-.02em}
  .step span{display:inline;white-space:nowrap}
  .step i{width:16px;height:16px;font-size:9.5px}
}

/* ── 패널/폼 (예약 정보 입력) ── */
.panel{background:var(--card);border:1px solid var(--line);border-radius:var(--rad);padding:22px 24px;margin-bottom:16px}
.panel h3{font-size:16px;font-weight:800;letter-spacing:-.02em;margin-bottom:16px}
/* 결제 화면 남은 시간. 예약 정보 화면의 홀딩 배지와 같은 톤으로 맞춘다 —
   두 화면이 같은 「시간 안에 끝내야 한다」를 말하고 있어야 한다 */
.pay-left{float:right;font-size:12.5px;font-weight:800;color:var(--terra);
  background:var(--bg);border-radius:8px;padding:4px 10px}
.pay-left.urgent{color:var(--on-brand);background:var(--danger)}
.f-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px 16px}
.f-grid .full{grid-column:1/-1}
.fld label{display:block;font-size:12.5px;font-weight:700;color:var(--ink2);margin-bottom:6px}
.fld label em{font-style:normal;color:var(--danger)}
/* 바탕은 흰색이다. 회색으로 깔면 «비활성 칸» 으로 읽힌다 — 실제로 못 쓰는 칸과
   구분이 안 된다. 칸의 경계는 테두리가 이미 긋고 있다. */
.fld input,.fld select,.fld textarea{width:100%;border:1px solid var(--line2);border-radius:var(--rad-s);background:var(--rsv-surface);
  padding:13px 15px;font-size:14.5px;transition:.2s;color:var(--ink)}
.fld input:focus,.fld textarea:focus,.fld select:focus{outline:none;border-color:var(--sage);box-shadow:0 0 0 3px rgba(var(--sage-rgb),.1)}
.fld textarea{min-height:96px;resize:vertical}
/* 16px 미만이면 iOS Safari 가 칸을 누르는 순간 화면을 확대한다 — 결제 직전에 화면이 튄다.
   토큰이 아니라 iOS 의 기준값이라 숫자로 쓴다. PC 는 그대로 두고 좁은 화면·터치 기기에서만 올린다.
   두 손가락 확대는 막지 않는다 (viewport maximum-scale 을 쓰지 않는 이유, 2026-09-11 결정).
   예약 조회 칸(.lk-row input)은 reservation-check.html 안에 같은 규칙이 있다. */
@media (max-width:760px), (pointer:coarse){.fld input,.fld select,.fld textarea{font-size:16px}}
@media(max-width:640px){.f-grid{grid-template-columns:1fr}}

/* 예약 입력 2컬럼 (본문 + sticky 결제 요약) */
.re-layout{display:grid;grid-template-columns:1fr 340px;gap:20px;align-items:start;padding-bottom:60px}
.re-side{position:sticky;top:86px}
@media(max-width:900px){
  .re-layout{grid-template-columns:1fr;padding-bottom:40px}
  .re-side{position:static}
}

/* 선택 객실 요약 */
.sel-room{display:flex;gap:14px;align-items:center;padding:14px 0;border-top:1px solid var(--line3)}
.sel-thumb{width:92px;height:66px;border-radius:6px;flex:none;background:#E2DDD0 center/cover no-repeat;
  background-image:repeating-linear-gradient(135deg,rgba(31,36,30,.06) 0 1px,transparent 1px 11px)}
.sel-room .m{flex:1;min-width:0}
.sel-room .m b{font-size:14.5px;font-weight:800}
.sel-room .m small{display:block;font-size:12px;color:var(--ink2);margin-top:2px}
.sel-room .p{font-size:15px;font-weight:800;white-space:nowrap}
.sel-room .rm{font-size:12.5px;color:var(--ink2);text-decoration:underline;white-space:nowrap}
.sel-room .sel-acts{display:flex;flex-direction:column;align-items:flex-end;gap:5px;flex:none}
/* 좁은 화면에서는 두 링크를 «아랫줄» 로 내려 가로로 편다.
   ⚠ flex 컨테이너는 .sel-item 이 아니라 .sel-room 이다. 여기에 width:100% 를 주면
   같은 줄의 이름(.m)이 0 으로 눌려 글자가 한 자씩 세로로 쪼개진다 — 줄을 바꾸려면
   부모에 flex-wrap 을 주고 자신은 flex-basis:100% 를 잡아야 한다. */
@media(max-width:760px){
  .sel-room{flex-wrap:wrap}
  .sel-room .sel-acts{flex-basis:100%;flex-direction:row;align-items:center;
    justify-content:flex-end;gap:16px;margin-top:2px}
  .sel-room .rm{padding:4px 0}
}

/* 선택 객실 — 인원·옵션 변경 패널.
 *
 * 상자를 두르지 않는다. 이 패널은 «표의 한 칸 안» 에서 열리는데, 표에 이미 가로 구분선이
 * 그어져 있어 테두리를 더하면 선이 겹쳐 격자가 두 겹으로 보인다.
 * 「여기가 그 줄에 딸린 내용」이라는 것은 위아래 여백과 표의 선이 이미 말한다. */
/*
 * 인원 변경 패널.
 *
 * 「기준 2명 · 최대 4명」 은 «지시» 가 아니라 «조건» 이다 — 스테퍼가 어디서 멈추는지를
 * 미리 말해 준다. 그래서 스테퍼 위에 작게 얹지 않고, 왼쪽에 세워 한 줄로 나란히 둔다.
 * 초록 세로선은 이 묶음이 위 줄에 딸린 것임을 가리킨다 (표 안이라 테두리는 쓸 수 없다 —
 * 칸 경계와 겹쳐 격자가 두 겹으로 보인다).
 */
/* 열 때 스크롤로 데려온다 — 아래 고정 바만큼 띄워야 바 뒤로 숨지 않는다 (reserve.js) */
.sel-edit{scroll-margin-bottom:calc(var(--actionbar-h,96px) + 12px)}
.sel-edit{display:flex;align-items:center;flex-wrap:wrap;gap:var(--rsv-sp-3) var(--rsv-sp-5);
  padding:18px 0;margin:0}
.sel-edit .ed-cap{flex:none;margin:0;padding-left:12px;
  border-left:3px solid var(--rsv-brand);
  font-size:var(--rsv-fs-sm);font-weight:700;color:var(--rsv-text-2);line-height:1.35}
/* 오류 줄은 제 줄을 갖는다 — 인원 옆에 끼면 스테퍼가 밀린다 */
.sel-edit .ed-err{flex:0 0 100%}
/*
 * 넓은 화면 — 인원·옵션을 «한 줄» 로 흘린다.
 * 목록 화면의 펼친 카드(.room .rsv-list)와 «같은 규칙» 이다. 손님은 방금 그 화면에서
 * 같은 스테퍼를 만졌으므로, 한 걸음 넘어와 모양이 달라지면 다른 기능으로 읽힌다.
 *
 * 예전에는 인원과 옵션이 «같은 격자» 를 써서(--ed-cols) 두 줄의 스테퍼가 한 세로선에
 * 서게 했다. 그 세로선을 얻는 대가가 컸다 — 옵션 라벨이 격자 칸에 갇혀 이름·설명·단가가
 * 세 줄로 쌓이고(실측 67px), 스테퍼는 75px 떨어진 오른쪽 끝에 남았다. 짝을 눈으로 이어야
 * 하는 그 배치가 목록 화면에서 이미 버린 것이다.
 *
 * 세로선 정렬은 포기한다. 라벨과 스테퍼가 «붙어 있는 것» 이 줄과 줄이 맞는 것보다 낫다.
 * 그 격자를 위해 reserve.js 가 심던 --ed-cols 도 같이 걷어냈다.
 *
 * ⚠ 스테퍼를 늘리지 않는다 (width:auto). 늘리면 ± 가 칸 양 끝으로 벌어진다.
 */
@media(min-width:761px){
  .sel-edit .ed-guests{display:flex;flex-wrap:wrap;align-items:center;
    gap:var(--rsv-sp-3) var(--rsv-sp-4)}
  .sel-edit .ed-guests > .rsv-row{flex:0 1 auto;min-width:0;
    display:flex;align-items:center;gap:var(--rsv-sp-3);
    padding:0;border:0;background:none}
  /* 라벨도 눕는다 — 이름·설명·단가가 세로로 쌓이면 옆의 스테퍼만 혼자 떠 보인다 */
  .sel-edit .rsv-row-label{display:flex;align-items:baseline;flex-wrap:wrap;
    gap:2px 6px;margin:0}
  .sel-edit .rsv-row-label b,
  .sel-edit .rsv-row-label small{display:inline}
  /* 「○월 ○일부터 사용 가능합니다」는 제 줄을 갖는다 — 단가 옆에 붙으면 가격의 일부로 읽힌다 */
  .sel-edit .rsv-row-label .opt-from{flex:0 0 100%}
  .sel-edit .rsv-stepper{display:inline-flex;width:auto;flex:none}
}

/*
 * 좁은 화면에서는 «목록에서 담을 때 본 선택 시트와 똑같이» 보이게 한다.
 *
 * 가로로 흘리면 권종이 셋일 때 2 + 1 로 갈려 유아만 외따로 떨어지고, 옵션은 라벨과
 * 스테퍼가 양 끝으로 벌어져 짝을 눈으로 이어야 했다. 한 줄에 하나씩 쌓고 라벨을 왼쪽,
 * 스테퍼를 오른쪽에 두면 두 화면이 «같은 것» 으로 읽힌다.
 *
 * ⚠ 예전 주석은 「기본 .rsv-row 가 이미 라벨 왼쪽 · 스테퍼 오른쪽이라 구분선만 손보면
 *   된다」고 했는데, 그 «기본 .rsv-row» 는 없다. 어느 정리 과정에서 사라졌고 그 뒤로
 *   좁은 화면의 이 패널은 배치 없이 블록으로 쌓여 있었다 — 라벨 한 줄, 스테퍼 한 줄이
 *   권종마다 되풀이됐다. 게다가 .sel-edit 이 flex-row 라 「기준 N명 · 최대 N명」이
 *   min-content 폭으로 눌려 왼쪽에 세로로 접혔다. 배치를 여기서 «직접» 준다.
 */
@media(max-width:760px){
  /* 조건 문구와 인원 목록을 위아래로 쌓는다 — 옆에 세울 폭이 없다 */
  .sel-edit{flex-direction:column;align-items:stretch;gap:var(--rsv-sp-3)}
  .sel-edit .ed-cap{align-self:flex-start}
  .sel-edit .ed-guests .rsv-row{display:flex;align-items:center;justify-content:space-between;
    gap:var(--rsv-sp-4);padding:11px 0;border-bottom:1px solid var(--rsv-line-soft)}
  .sel-edit .ed-guests .rsv-row:last-child{border-bottom:none}
  .sel-edit .rsv-row-label{display:flex;align-items:baseline;flex-wrap:wrap;
    gap:2px 6px;margin:0;min-width:0}
  .sel-edit .rsv-stepper{flex:none}
}
.sel-edit .ed-hint{font-size:12.5px;color:var(--ink2)}
.sel-edit .ed-err{display:none;font-size:12px;font-weight:600;color:var(--danger);background:var(--danger-bg);
  border-radius:6px;padding:8px 11px;margin-top:10px}
.sel-edit .ed-err.show{display:block}
.badge{display:inline-block;font-size:10.5px;font-weight:800;border-radius:4px;padding:3px 8px;margin-right:6px;background:var(--sage-bg);color:var(--sage)}
@media(max-width:640px){.sel-thumb{width:64px;height:50px}}

/* 약관 */
.terms .t-all{display:flex;align-items:center;gap:10px;font-size:14.5px;font-weight:800;padding:13px 16px;
  background:var(--sage-bg);border:1px solid #DCE3D6;border-radius:var(--rad-s);margin-bottom:8px;cursor:pointer}
.terms .t-row{display:flex;align-items:center;gap:10px;font-size:13px;color:#5B5A50;padding:8px 16px}
.terms .t-row > label{display:flex;align-items:center;gap:10px;flex:1;min-width:0;cursor:pointer}
.terms input{width:16px;height:16px;accent-color:var(--sage);flex:none}
/* 약관 「내용보기」 — 라벨 오른쪽 끝, 밑줄로 링크임을 알린다 */
.terms .t-view{flex:none;border:0;background:none;color:#6E7B63;font-size:12.5px;
  padding:4px 2px;cursor:pointer;text-decoration:underline;text-underline-offset:2px;white-space:nowrap}
.terms .t-view:hover{color:var(--sage)}

/* 약관 전문 모달 (내용보기) */
.terms-modal-back{position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,.5);
  display:flex;align-items:center;justify-content:center;padding:20px}
.terms-modal{background:var(--card,#fff);border-radius:var(--rad-s,10px);width:min(560px,100%);
  max-height:82vh;display:flex;flex-direction:column;box-shadow:0 12px 40px rgba(0,0,0,.25)}
.terms-modal-head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:16px 20px;border-bottom:1px solid var(--line,#E7E5DC)}
.terms-modal-head h4{margin:0;font-size:16px;font-weight:800;color:var(--ink,#2C2B24)}
.terms-modal-close{border:0;background:none;font-size:20px;line-height:1;color:#8A897E;cursor:pointer;padding:2px 4px}
.terms-modal-body{padding:18px 20px;overflow-y:auto;font-size:13px;line-height:1.7;color:#4B4A42;
  white-space:pre-wrap;word-break:break-word}
.terms-modal-body.is-loading{color:#8A897E}

/* 취소/환불 규정 표 (취소일 · 취소수수료) */
.fee-table{border:1px solid var(--line);border-radius:var(--rad-s);overflow:hidden;margin-top:6px;background:var(--card)}
.fee-row{display:grid;grid-template-columns:1.4fr 1fr;font-size:12.5px;color:#5B5A50;border-top:1px solid var(--line3)}
.fee-row:first-child{border-top:none}
.fee-row > div{padding:10px 14px}
.fee-row.head{background:var(--bg);font-weight:800;color:var(--ink2);font-size:12px}
.fee-row > div:last-child{text-align:right;font-weight:700}
.fee-row.head > div:last-child{font-weight:800}

/*
 * 결제 화면 본문.
 *
 * width:100% 가 있어야 한다. body 가 flex column 이고 .wrap 은 margin:0 auto 라,
 * cross 축에서 auto 마진이 stretch 를 이겨 «내용 폭»으로 줄어든다. 그러면 결제수단을
 * 바꿀 때마다 안내 문구 길이를 따라 카드 폭이 70px 씩 널뛴다 (계좌이체는 문구가 짧다).
 *
 * 아래 여백은 결제 상자와 푸터 사이를 띄우는 몫이다. 좁은 화면에서는 하단 액션 바가
 * 이미 body 에 제 높이만큼 여백을 만들어 두므로(--actionbar-h) 여기서 또 주면
 * 본문 끝에 빈 화면 한 뼘이 생긴다.
 */
.pay-wrap{width:100%;max-width:680px;padding-bottom:80px}
@media(max-width:760px){.pay-wrap{padding-bottom:0}}

/* 결제 요약 (다크 카드) */
.paybox{background:var(--dark);color:var(--dark-ink);border-radius:var(--rad);padding:22px 24px}
.paybox .bx-t{display:block;font-size:15px;font-weight:800;margin-bottom:12px}
.paybox .row{display:flex;justify-content:space-between;font-size:13px;color:rgba(255,255,255,.62);padding:5px 0}
.paybox .row.tot{border-top:1px solid rgba(255,255,255,.16);margin-top:12px;padding-top:14px;align-items:baseline}
.paybox .row.tot span{font-size:14px;font-weight:700;color:var(--dark-ink)}
.paybox .row.tot b{font-size:24px;color:var(--dark-ink)}
.pay-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;margin-top:16px;
  background:var(--lime);color:var(--lime-ink);font-size:15px;font-weight:800;border:none;cursor:pointer;
  border-radius:var(--rad-s);padding:16px;transition:.2s}
.pay-btn:hover{filter:brightness(1.06)}
.pay-btn:disabled{opacity:.5;cursor:default;filter:none}
.pay-note{font-size:11.5px;color:rgba(255,255,255,.5);margin-top:12px;text-align:center;line-height:1.65}
/* 초록 상자 안에서는 밝은 살구색이라야 읽혔다. 예약 화면에서는 상자가 사라져 흰 바탕이므로
   그 색은 보이지 않는다 — 바닥에 맞춰 강조 빨강으로 뒤집는다. 결제 화면(.paybox)은 그대로. */
.pay-err{display:none;font-size:12.5px;font-weight:600;color:var(--rsv-accent);margin-top:12px;text-align:center}
.paybox .pay-err{color:#F0B9A2}
/*
 * ⚠ 이 자리에 있어야 한다 — 위 .paybox 규칙들과 명시도가 같아(클래스 1~2개) «순서» 가 이긴다.
 * 좁은 화면 규칙을 모아 둔 앞쪽 미디어쿼리로 옮기면 여기 .paybox 가 도로 덮어써서
 * 어두운 카드가 그대로 남는다 (develop 에서 실제로 그렇게 만들었다가 고친 자리다).
 *
 * 좁은 화면에서 «결제 화면»의 이 상자에 남는 것은 오류·안내 문구뿐이다. 카드로 감싸 두면
 * 내용 없는 검은 상자가 본문 끝에 떠서 무엇을 말하려는 것인지 알 수 없다.
 */
@media(max-width:760px){
  .paybox-pay{background:none;color:inherit;padding:0;border-radius:0}
  /* 오류 문구는 어두운 카드 위에서 읽히라고 밝은 살구색이었다. 배경이 밝아졌으니
     그대로 두면 «결제가 왜 안 되는지» 가 흰 바탕에 흐릿하게 깔린다. */
  .paybox-pay .pay-err{color:var(--danger)}
}
.pay-err.show{display:block}
.pay-btn .spinner{border-color:rgba(27,32,22,.3);border-top-color:var(--lime-ink)}

/* 홀딩 타이머 */
.hold-badge{font-size:12px;font-weight:800;color:var(--terra);border:1px solid var(--terra-line);background:var(--terra-bg);
  border-radius:6px;padding:5px 11px;white-space:nowrap}

/* ── 완료/결과 페이지 ── */
.done-wrap{max-width:580px;margin:0 auto;padding:44px 24px 80px;text-align:center}
.done-wrap .ic{width:44px;height:44px;border-radius:8px;background:var(--sage);display:grid;place-items:center;
  font-size:22px;font-weight:800;color:var(--dark-ink);margin:0 auto 16px}
.done-wrap .ic.warn{background:var(--danger)}
.done-wrap h2{font-size:24px;font-weight:800;letter-spacing:-.025em}
.done-wrap .sub{font-size:14px;color:var(--ink2);margin-top:8px}
.res-card{background:var(--card);border:1px solid var(--line);border-radius:var(--rad);overflow:hidden;margin-top:24px;text-align:left}
.res-top{background:var(--dark);color:var(--dark-ink);padding:20px 24px;display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap}
.res-top .no{font-size:11px;color:rgba(255,255,255,.55);letter-spacing:.14em}
.res-top .no b{display:block;font-size:19px;margin-top:3px;letter-spacing:.03em;color:var(--dark-ink)}
.st-badge{font-size:12px;font-weight:800;background:rgba(143,169,107,.24);border:1px solid rgba(143,169,107,.5);
  color:#C7D8AA;border-radius:6px;padding:6px 14px}
.st-badge.cancel{background:rgba(147,80,47,.22);border-color:rgba(147,80,47,.45);color:#E8B9A2}
.res-body{padding:6px 24px 16px}
.res-row{display:flex;justify-content:space-between;gap:16px;padding:13px 0;border-bottom:1px solid var(--line3);font-size:13.5px}
.res-row:last-child{border-bottom:none}
.res-row span{color:var(--ink2);flex:none}
.res-row b{text-align:right}
.res-row b small{display:block;color:var(--ink2);font-weight:400}
/* 취소된 객실 — 지우지 않고 색만 내리고 「취소됨」 을 단다. 어떤 방이 빠졌는지가 곧 「지금 무엇이 남았나」다.
   예약 조회와 예약 완료 화면이 같이 쓴다 (예약 완료에는 없어서 취소된 방이 살아 있는 듯 보였다 — QA B-009) */
.res-room.is-cancelled b{color:var(--ink3)}
.res-tag{font-style:normal;font-size:var(--rsv-fs-cap);font-weight:600;color:var(--ink2);
  background:var(--rsv-surface-sunken);border-radius:99px;padding:1px 8px;margin-left:6px;vertical-align:middle}
/* 요청사항 — 손님이 «적은 문장» 이라 한 줄에 안 들어간다. 금액처럼 오른쪽 정렬하면
   줄바꿈이 지그재그로 읽히므로 라벨 아래에 왼쪽으로 편다.
   pre-wrap 인 이유는 손님이 textarea 에서 나눈 줄을 그대로 보여 주기 위해서다. */
.res-row.res-request{display:block}
.res-row.res-request b{display:block;margin-top:6px;text-align:left;font-weight:400;
  white-space:pre-wrap;word-break:break-word;color:var(--ink)}
/* 결제 정보 모달을 여는 링크형 버튼. 링크처럼 보이되 버튼이라 새 탭이 열리지 않는다 —
   손님은 예약 확인 화면을 떠나지 않고 영수증을 본다 (common/js/payment-modal.js). */
.res-link-btn{padding:0;border:none;background:none;font:inherit;font-weight:700;
  color:var(--sage);text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.res-link-btn:hover{color:var(--sage-deep)}
.btn-solid{display:inline-block;text-align:center;font-size:14px;font-weight:800;color:var(--dark-ink);background:var(--sage);
  border:none;cursor:pointer;border-radius:var(--rad-s);padding:14px 26px;transition:.2s}
.btn-solid:hover{background:var(--sage-deep)}
.btn-ghost{display:inline-block;text-align:center;font-size:14px;font-weight:800;color:var(--ink);background:var(--card);
  border:1px solid var(--line2);cursor:pointer;border-radius:var(--rad-s);padding:14px 26px;transition:.2s}
.btn-ghost:hover{border-color:var(--sage);color:var(--sage)}
.talk{display:flex;gap:10px;align-items:center;font-size:12.5px;color:var(--ink2);background:var(--card);
  border:1px solid var(--line);border-radius:var(--rad-s);padding:13px 16px;margin-top:16px;text-align:left;line-height:1.7}
.talk i{font-style:normal;flex:none;background:var(--sage-bg);color:var(--sage);font-size:10.5px;font-weight:900;border-radius:5px;padding:3px 8px}

/* ── 모달 ── */
.modal-back{position:fixed;inset:0;z-index:300;background:rgba(31,36,30,.5);backdrop-filter:blur(3px);
  display:grid;place-items:center;padding:20px}
.modal{position:relative;width:100%;max-width:380px;background:var(--bg);border-radius:16px;
  padding:26px 24px 22px;box-shadow:var(--sh-lg);animation:pop .3s cubic-bezier(.2,.8,.2,1) both}
.modal h4{font-size:17px;font-weight:800;letter-spacing:-.02em;margin-bottom:8px}
.modal p{font-size:13.5px;color:var(--ink2);line-height:1.7}
.modal .m-actions{display:flex;flex-direction:column;gap:8px;margin-top:16px}
.modal .m-solid{background:var(--sage);color:var(--dark-ink);font-size:14.5px;font-weight:800;border-radius:var(--rad-s);padding:14px;transition:.2s}
.modal .m-solid:hover{filter:brightness(1.08)}
.modal .m-line{background:none;color:var(--ink2);font-size:14px;font-weight:700;border:1px solid var(--line2);
  border-radius:var(--rad-s);padding:13px;transition:.2s}
.modal .m-line:hover{border-color:var(--ink2);color:var(--ink)}
.modal .m-close{position:absolute;top:14px;right:16px;font-size:15px;color:var(--ink2)}
.modal .m-field{width:100%;border:1px solid var(--line2);border-radius:var(--rad-s);background:var(--card);
  padding:14px 15px;font-size:19px;letter-spacing:.4em;text-align:center;margin-top:12px}
.modal .m-field:focus{outline:none;border-color:var(--sage)}
.modal .m-err{display:none;font-size:12.5px;font-weight:600;color:var(--danger);margin-top:8px;text-align:center}
.modal .m-err.show{display:block}
.modal .m-preview{background:var(--card);border:1px solid var(--line);border-radius:var(--rad-s);padding:13px 16px;margin-top:14px;font-size:12.5px}
.modal .m-preview .row{display:flex;justify-content:space-between;padding:3px 0;color:var(--ink2)}
.modal .m-preview .row b{color:var(--ink)}
.modal .m-preview .row.tot{border-top:1px solid var(--line3);margin-top:6px;padding-top:8px;font-size:13.5px}
.modal .m-preview .row.tot b{color:var(--ink)}

/* ── 이미지 갤러리 (가로 슬라이드 라이트박스) ── */
.gal-back{position:fixed;inset:0;z-index:400;background:rgba(31,36,30,.94);display:flex;flex-direction:column;
  animation:galFade .25s ease both}
@keyframes galFade{from{opacity:0}to{opacity:1}}
.gal-head{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;color:var(--dark-ink);flex:none}
.gal-head b{font-size:15px;font-weight:800;letter-spacing:-.02em}
.gal-close{color:var(--dark-ink);font-size:18px;padding:6px 10px;border-radius:8px;transition:.15s}
.gal-close:hover{background:rgba(255,255,255,.14)}
.gal-stage{flex:1;position:relative;display:flex;min-height:0}
.gal-track{flex:1;display:flex;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;scrollbar-width:none}
.gal-track::-webkit-scrollbar{display:none}
.gal-slide{flex:none;width:100%;height:100%;scroll-snap-align:center;display:grid;place-items:center;padding:0 20px 8px}
.gal-slide img{max-width:100%;max-height:100%;object-fit:contain;border-radius:6px}
.gal-broken{color:rgba(255,255,255,.55);font-size:13.5px;font-weight:700;border:1px dashed rgba(255,255,255,.3);
  border-radius:10px;padding:40px 60px}
.gal-nav{position:absolute;top:50%;transform:translateY(-50%);width:44px;height:44px;border-radius:8px;z-index:2;
  background:rgba(255,255,255,.14);color:var(--dark-ink);font-size:20px;font-weight:800;transition:.15s}
.gal-nav:hover{background:rgba(255,255,255,.3)}
.gal-nav.prev{left:16px}
.gal-nav.next{right:16px}
.gal-count{flex:none;text-align:center;color:rgba(255,255,255,.7);font-size:12.5px;font-weight:700;padding:12px 0 18px}
@media(max-width:640px){.gal-nav{display:none}} /* 모바일은 스와이프 */
/* 아래 미리보기 줄 (2026-10-29) — 누르면 그 사진으로 간다. 지금 사진은 흰 테두리로 짚는다 */
.gal-thumbs{flex:none;display:flex;gap:6px;justify-content:center;overflow-x:auto;scrollbar-width:none;
  padding:0 20px 18px;margin-top:-6px}
.gal-thumbs::-webkit-scrollbar{display:none}
.gal-thumbs[hidden]{display:none}
.gal-thumb{flex:none;width:96px;height:64px;padding:0;border:2px solid transparent;border-radius:6px;
  overflow:hidden;opacity:.55;transition:opacity .15s,border-color .15s;background:none;cursor:pointer}
.gal-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.gal-thumb:hover{opacity:.85}
.gal-thumb.is-on{opacity:1;border-color:#fff}
@media(max-width:640px){.gal-thumb{width:64px;height:44px}}

/* ── 화면 스피너 (DB 를 읽는 동안) ──
 *
 * 관리자 화면의 것(admin/css/header.css .overlay/.photo-spinner)과 «같은 모양» 이다.
 * 두 화면이 다른 모양으로 기다리게 할 이유가 없다.
 *
 * 250ms 넘게 걸리는 요청에만 뜬다 — 곧바로 띄우면 금방 끝나는 조회에서도 화면이
 * 번쩍이고, 그게 더 느려 보인다. 대신 뜨는 동안은 클릭을 막는다: 응답을 기다리는
 * 사이에 같은 버튼을 두 번 누르는 것이 이 화면에서 가장 흔한 사고다.
 */
.web-overlay{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;
  background:rgba(31,36,30,.22)}
.web-overlay[hidden]{display:none !important}
.web-spinner{width:68px;height:68px;border-radius:50%;
  background:conic-gradient(from -90deg,
    var(--sage) 0deg,
    rgba(var(--sage-rgb),.9) 90deg,
    rgba(var(--sage-rgb),.55) 150deg,
    rgba(var(--sage-rgb),.25) 210deg,
    rgba(var(--sage-rgb),.1) 270deg,
    rgba(var(--sage-rgb),0) 360deg);
  -webkit-mask:radial-gradient(farthest-side,transparent 63%,#000 64%);
  mask:radial-gradient(farthest-side,transparent 63%,#000 64%);
  box-shadow:0 0 10px rgba(var(--sage-rgb),.18);
  animation:spin 1s linear infinite}

/* ── 버튼 스피너 ── */
.spinner{display:inline-block;width:14px;height:14px;margin-right:8px;vertical-align:-2px;
  border:2px solid rgba(255,255,255,.35);border-top-color:var(--card);border-radius:50%;animation:spin .7s linear infinite}
.btn-loading{opacity:.75;cursor:default}
/* 링 색은 --danger 의 옅은 판이다. hex 를 직접 쓴 것은 rgba() 가 변수를 못 받아서고,
   --danger 를 바꾸면 이 값도 같이 바꿔야 한다. */
.btn-line .spinner{border-color:rgba(208,18,27,.3);border-top-color:var(--danger)}
@keyframes spin{to{transform:rotate(360deg)}}

/* ── 결제수단 선택 (pay.html) ─────────────────────────────────────────────
   수단이 3개일 수도 8개일 수도 있어 개수에 맞춰 늘어나는 그리드로 둔다. */
.pm-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px}
.pm-item{display:flex;align-items:center;justify-content:center;gap:8px;min-height:52px;padding:12px 14px;
  border:1px solid var(--line);border-radius:12px;background:var(--card);cursor:pointer;
  font-size:13.5px;font-weight:700;color:var(--ink2);transition:.15s;text-align:center}
.pm-item:hover{border-color:var(--line2);color:var(--ink)}
.pm-item.on{border-color:var(--sage);background:var(--sage-bg);color:var(--sage);box-shadow:inset 0 0 0 1px var(--sage)}
.pm-hint{font-size:12px;color:var(--ink2);margin-top:12px;line-height:1.7}

/* 예약 조회 결과 QR
   설명 문구를 걷어내고 나면 상자 안에 이미지 하나만 남는다. 폭을 내용에 맞춰
   줄이지 않으면 오른쪽이 텅 빈 넓은 상자가 된다.
   그렇게 줄인 상자를 왼쪽에 붙여 두면 카드 아래가 한쪽으로 쏠린다 —
   가로 auto 마진으로 가운데에 세운다 (현장에서 내미는 화면이라 가운데가 맞다). */
.res-qr {
    display: flex;
    align-items: center;
    justify-content: center;
    width: fit-content;
    gap: 14px;
    margin: 16px auto 6px;
    padding: 14px;
    border: 1px solid var(--rsv-line-soft);
    border-radius: 12px;
    background: var(--rsv-surface-sunken);
}
/* 카드의 마지막 요소일 때 — 아래로 숨 쉴 자리를 준다.
   예약 확인 화면은 뒤에 안내문·버튼이, 예약 완료 화면은 캡션이 이어져서 보통은 안 걸린다. */
.res-card > .res-qr:last-child { margin-bottom: 20px; }
.res-qr-img {
    width: 140px;
    height: 140px;
    flex: none;
    border-radius: 8px;
    background: var(--card);
    border: 1px solid var(--rsv-line-soft);
}
/* QR 아래 한 줄. 상자 «안»에 옆으로 붙이면 좁은 화면에서 QR 과 자리를 다투다 둘 다 줄어든다.
   상자 밖 아래에 가운데로 놓는다. */
.res-qr-cap {
    font-size: 12.5px;
    color: var(--ink2);
    line-height: 1.6;
    margin: 0 24px 20px;
    text-align: center;
}

/* ══════════════════════════════════════════════════════════════
   배치도 (web/js/facility-map.js)

   검색 밴드 바로 아래, 객실 목록 위에 본문 폭 그대로 깔리는 블록이다.
   조회한 날짜의 예약 가능 여부가 버튼 색으로 보이고, 누르면 그 객실 카드로 간다.

   좁은 화면에서는 아예 만들지 않는다 — CSS 로 숨기는 게 아니라 JS 가 DOM 도
   API 호출도 이미지 로드도 하지 않는다. 아래 미디어 쿼리는 이중 안전장치다.
   ══════════════════════════════════════════════════════════════ */

.mapblock{padding-top:24px}
@media(max-width:899px){.mapblock{display:none !important}}

/* 위 줄 — 범례(왼쪽) · 배치도 탭 · 닫기(오른쪽) */
.mp-bar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:0 2px 10px}
.mp-legend{display:flex;gap:14px;font-size:12.5px;color:var(--ink2)}
.mp-legend span{display:inline-flex;align-items:center;gap:6px}
.mp-legend i{width:11px;height:11px;border-radius:999px;display:block;flex:none}
.mp-legend i.ok{background:var(--mp-open)}
.mp-legend i.full{background:var(--mp-full)}

.mp-tabs{display:flex;gap:6px;margin-left:6px}
.mp-tabs button{font-size:12.5px;font-weight:700;color:var(--ink2);padding:5px 12px;
  border-radius:999px;background:var(--bg)}
.mp-tabs button.on{background:var(--sage-tint);color:var(--sage-deep)}

.mp-spacer{flex:1 1 auto}
.mp-close{width:28px;height:28px;border-radius:8px;border:1px solid var(--line2);
  color:var(--ink2);font-size:13px;line-height:1}
.mp-close:hover{background:var(--bg);color:var(--ink)}

/* 열기 버튼 — 닫아 둔 동안 그 자리에 남는다. 닫으면 다시 볼 길이 없으면 안 된다 */
.mp-open{font-size:13px;font-weight:700;color:var(--sage);background:var(--sage-tint-soft);
  padding:8px 14px;border-radius:var(--rad-s);border:1px solid var(--sage-tint)}
.mp-open:hover{background:var(--sage-tint)}

.mp-box{border:1px solid var(--line);border-radius:var(--rad);background:var(--card);
  padding:20px;box-shadow:var(--sh)}

/* 캔버스 — 버튼 지름은 원본 이미지 px 기준이라 --mp-scale 을 곱한다 */
.mp-canvas{position:relative;line-height:0;margin:0 auto;--mp-scale:1}

/* 버튼 색 — 배경 그림 위를 «덮는» 색이라 반투명이 아니다.
   예약 가능은 빨강, 마감은 회색. 종이 배치도의 관례를 그대로 따른다. */
:root{
  --mp-open:#D8342C;      /* 예약 가능 */
  --mp-full:#9E9C92;      /* 예약 마감 — 판매 중지·방막기도 손님에게는 이 얼굴이다 */
  --mp-carted:var(--sage);    /* 장바구니에 담김 */
}
.mp-canvas img{display:block;width:100%;height:auto}

/*
 * 테두리와 글자는 «버튼 지름에 비례»한다. px 로 고정하면 작은 버튼에서는 테두리가
 * 버튼을 다 먹고 글자는 넘치며, 큰 버튼에서는 실오라기처럼 보인다.
 * 비율은 배치도마다 다르게 줄 수 있다 — JS 가 --mp-bd / --mp-fw 를 채운다(V041).
 */
.mp-pin{position:absolute;transform:translate(-50%,-50%);
  --mp-d:calc(var(--d) * var(--mp-scale) * 1px);
  width:var(--mp-d);height:var(--mp-d);
  min-width:18px;min-height:18px;border-radius:999px;
  display:flex;align-items:center;justify-content:center;
  font-size:max(9px, calc(var(--mp-d) * .42));
  font-weight:var(--mp-fw, 600);
  line-height:1;padding:0;
  transition:box-shadow .15s,background .15s,border-color .15s}

/* 투명 클릭 영역 — 배경 그림에 번호가 이미 있을 때. 그림을 가리지 않고 상태만 얹는다.
   마감·미운영은 흰 반투명으로 덮어 흐리게 만든다. */
.mp-pin.is-hotspot{background:transparent;color:transparent;
  border:max(1.5px, calc(var(--mp-d) * var(--mp-bd, .05))) solid transparent}
.mp-pin.is-hotspot.is-idle:hover{border-color:rgba(31,36,30,.35)}
.mp-pin.is-hotspot.is-open{border-color:var(--mp-open);box-shadow:0 0 0 3px rgba(216,52,44,.18)}
.mp-pin.is-hotspot.is-open:hover{box-shadow:0 0 0 6px rgba(216,52,44,.28)}
.mp-pin.is-hotspot.is-full{background:rgba(255,255,255,.66);border-color:rgba(31,36,30,.18)}
.mp-pin.is-hotspot.is-carted{background:rgba(var(--sage-rgb),.22);border-color:var(--mp-carted)}

/* 번호 원형 버튼 — 배경 그림에 그려진 번호를 «덮고» 그 위에 우리 번호를 다시 쓴다.
   그림 위에 얹는 반투명 링과 달리 상태가 한눈에 읽힌다. */
.mp-pin.is-pin{
  border:max(1px, calc(var(--mp-d) * var(--mp-bd, .05))) solid var(--card);
  box-shadow:0 1px 4px rgba(31,36,30,.3);color:var(--on-brand)}
.mp-pin.is-pin.is-idle{background:var(--ink3)}
.mp-pin.is-pin.is-open{background:var(--mp-open)}
.mp-pin.is-pin.is-open:hover{filter:brightness(1.12)}
.mp-pin.is-pin.is-full{background:var(--mp-full)}
.mp-pin.is-pin.is-carted{background:var(--mp-carted)}

.mp-pin.is-open,.mp-pin.is-full,.mp-pin.is-idle{cursor:pointer}
.mp-pin.is-hi{outline:3px solid var(--sun);outline-offset:2px;z-index:4}
.mp-pin:focus-visible{outline:3px solid var(--info);outline-offset:2px;z-index:4}

/* 담긴 방 체크 배지 */
.mp-pin .mp-chk{position:absolute;top:-6px;right:-6px;width:15px;height:15px;border-radius:999px;
  background:var(--sage-deep);color:var(--on-brand);font-size:9.5px;line-height:15px;text-align:center;
  font-weight:800;pointer-events:none}

.mp-note{padding:10px 2px 0;font-size:12.5px;line-height:1.6;color:var(--ink2)}
.mp-note:empty{display:none}

/* 배치도에서 고른 객실 카드 강조 — 어디로 이동했는지 눈으로 확인시켜 준다 */
.room.mp-hl{box-shadow:0 0 0 3px rgba(var(--sage-rgb),.35)}

/************************************************************************
* 모션 줄이기 (prefers-reduced-motion)
*
* 손님 웹은 이 파일 하나로 돌아가는데 transition 이 34곳, 애니메이션이 5종인데도
* 이 규칙이 없었다 (2026-08-30). 관리자 쪽 8개 파일에는 있었으니 뒤집힌 우선순위였다 —
* 어지럼증·전정기관 질환으로 OS 에 「동작 줄이기」를 켜 둔 사람이 먼저 만나는 화면이
* 손님 웹이다.
*
* 값을 0 이 아니라 .01ms 로 두는 이유: 0s 면 브라우저가 transitionend/animationend 를
* 아예 쏘지 않는 경우가 있어, 그 이벤트로 뒷정리를 하는 코드가 조용히 멈춘다.
*
* `*` 는 명시도가 (0,0,0) 이라 화면 규칙에 지지만 !important 가 그걸 뒤집는다.
* 이 파일 안에 transition/animation 에 !important 를 쓴 곳은 없으므로 전부 이긴다.
************************************************************************/
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }

  /* 스피너는 예외다. 「통신 중」임을 알리는 유일한 표시라 멈춰 세우면 화면이 죽은 것처럼
     보인다 — 정보를 없애는 쪽이 더 나쁘다. 제자리 회전은 시차·확대·이동이 없어
     전정기관 반응을 일으키는 종류의 모션이 아니다. 대신 느리게 돌린다. */
  .web-spinner,.spinner{
    animation-duration:2s !important;
    animation-iteration-count:infinite !important;
  }
}

/************************************************************************
* 터치 목표 44×44 (pointer: coarse)
*
* 손가락으로 만지는 기기에만 건다. 마우스는 커서 끝이 1px 이라 30px 로 충분하고,
* 데스크톱까지 키우면 검색 밴드가 통째로 뚱뚱해진다.
*
* 두 가지 방법을 자리에 따라 나눠 쓴다 —
*   ① 옆에 다른 것이 붙어 있으면 «칸 자체» 를 키운다.
*      스테퍼(−/숫자/+)는 가짜 히트영역으로 넓히면 44px 짜리 두 영역이 가운데 숫자를
*      덮어, 숫자 왼쪽 끝을 눌렀는데 인원이 줄어든다. 그건 오작동이지 개선이 아니다.
*   ② 혼자 떨어져 있으면 «보이는 크기는 그대로» 두고 ::after 로 히트영역만 넓힌다.
*      닫기·달 이동 버튼은 모서리에 홀로 있어 겹칠 상대가 없다.
*
* ⚠ ::after 를 쓰는 요소에 position 을 새로 주지 말 것 — .rc-nav 와 .rc-close 는
*   이미 absolute 로 «위치가 정해져» 있다. relative 로 덮으면 제자리를 잃는다.
*   position 이 static 인 것(.flt-close · .mp-close)에만 relative 를 준다.
************************************************************************/
@media (pointer: coarse){
  /* ① 칸을 키운다 — 숫자 폭도 같이 넓혀 좌우 버튼이 숫자를 침범하지 않게 한다 */
  .stp output{width:34px}

  /* ② 히트영역만 넓힌다.
        .rc-nav 는 이미 absolute 라 ::after 가 자기 자신을 기준으로 잡힌다.
        .flt-close · .mp-close 는 static 이라 relative 를 줘야 한다 — 안 주면 ::after 가
        위쪽의 «위치가 잡힌» 조상을 기준으로 튀어, 엉뚱한 자리에 44px 짜리 보이지 않는
        클릭 영역이 생긴다 (그 영역을 눌러도 닫기가 실행된다). */
  .flt-close,.mp-close{position:relative}
  .rc-nav::after,.flt-close::after,.mp-close::after{
    content:"";position:absolute;top:50%;left:50%;
    width:44px;height:44px;transform:translate(-50%,-50%);
  }

  /* .rc-close 만 «칸을 키우는» 쪽이다. 720px 이하에서 absolute + translateY(-50%) 로
     세로 가운데를 잡고 있어, 여기서 relative 를 덮으면 제자리를 잃는다.
     40→44 는 4px 차이라 시트 헤더 모양이 흐트러지지 않는다. */
  .rc-close{width:44px;height:44px}
}

/* ── 결제 직전 약관 동의 레이어 (2026-09-11) ──────────────────────────
   .terms-modal-back/.terms-modal 을 그대로 빌려 쓰고, 안쪽만 여기서 그린다.
   약관 «전문» 모달은 이 레이어 «위» 에 떠야 하므로 z-index 를 1200 으로 올려 연다
   (consent-layer.js 참고) — 그래서 이 레이어는 1100 이다. */
.cs-back{z-index:1100}
.cs-modal{width:min(520px,100%);display:flex;flex-direction:column;max-height:86vh}
.cs-body{padding:18px 20px;overflow-y:auto}
.cs-all{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:700;
  color:var(--ink,#2C2B24);padding:12px 14px;border-radius:var(--rad-s,10px);
  background:var(--bg,#F5F4EF);cursor:pointer}
.cs-all .cs-sub{font-size:12.5px;font-weight:500;color:var(--ink2,#6B6A5F)}
.cs-list{margin-top:6px}
.cs-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 14px}
.cs-row + .cs-row{border-top:1px solid var(--line,#E6E3DA)}
.cs-row label{display:flex;align-items:center;gap:8px;font-size:14px;
  color:var(--ink,#2C2B24);cursor:pointer;min-width:0}
.cs-row .cs-tag{font-size:12px;color:var(--ink2,#6B6A5F);white-space:nowrap}
.cs-view{flex:none;border:0;background:none;padding:4px;font-size:12.5px;
  color:var(--ink2,#6B6A5F);text-decoration:underline;cursor:pointer}
.cs-err{margin:10px 14px 0;font-size:13px;color:var(--accent,#B4453C)}
.cs-foot{display:flex;gap:8px;padding:14px 20px;border-top:1px solid var(--line,#E6E3DA)}
.cs-foot button{flex:1;height:46px;border-radius:var(--rad-s,10px);font-size:15px;
  font-weight:700;cursor:pointer;font-family:inherit}
.cs-cancel{border:1px solid var(--line2,#DDD8CB);background:var(--card,#fff);color:var(--ink2,#6B6A5F)}
.cs-ok{border:0;background:var(--sage,#204A12);color:#fff}
.cs-ok:disabled{opacity:.6;cursor:default}

/* =====================================================================
   사이트 팝업 (V083) — docs/DESIGN_web-popup.md §5
   ---------------------------------------------------------------------
   관리자가 편집기에서 잡아 둔 자리를 그대로 재현한다.

   ⚠ 배경을 덮는 막이 없다. 팝업은 «예약을 막지 않는다» — 뒤쪽 화면이 계속
     동작해야 하므로 무대 자체는 pointer-events 를 받지 않고, 팝업 «상자» 만 받는다.
   ===================================================================== */

/* 무대 — 편집기와 «같은 크기» 다. JS 가 통째로 scale() 한다.
   transform-origin 이 위 가운데라, 줄어들어도 화면 가운데·위 기준으로 남는다. */
.wp-stage {
    position: fixed;
    top: 0;
    left: 50%;
    transform-origin: top center;
    z-index: var(--z-site-popup);
    pointer-events: none;   /* 빈 자리는 뒤쪽 화면이 받는다 */
}

.wp-box {
    position: absolute;
    pointer-events: auto;   /* 팝업 «상자» 만 클릭을 받는다 */
    display: flex;
    flex-direction: column;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .18);
    border-radius: 6px;
    overflow: hidden;
    background: #fff;
}

.wp-img {
    display: block;
    width: 100%;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/* 링크가 없으면 커서도 바뀌지 않는다 — 누를 수 있다고 읽히면 안 된다 */
.wp-img.is-link { cursor: pointer; }

/* 아래 띠. 이미지 «밖» 이라 그림을 가리지 않는다 —
   위에 얹으면 관리자가 넣은 문구와 겹쳐 둘 다 안 읽힌다. */
.wp-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 8px 10px;
    background: #2b2b2b;
    color: #fff;
    font-size: 13px;
    line-height: 1;
}

.wp-today {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    user-select: none;
}

/* 체크박스는 브라우저 기본 모양을 쓴다 — 짙은 띠 위에서 커스텀 체크는
   포커스 링까지 직접 그려야 하고, 여기서는 한 칸뿐이라 값이 없다. */
.wp-today input { width: 14px; height: 14px; margin: 0; cursor: pointer; }

.wp-close {
    padding: 4px 10px;
    border: 0;
    border-radius: 4px;
    background: rgba(255, 255, 255, .16);
    color: #fff;
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
}

.wp-close:hover { background: rgba(255, 255, 255, .28); }
.wp-close:focus-visible,
.wp-today input:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
