/* LILT 콘솔/대시보드 공통 스타일 — 깔끔하고 입력이 편한 폼 중심 UI */
/* 네오고딕 계열 UI 폰트 (self-hosted, 외부 의존 없음) */
@font-face{
  font-family:'Pretendard';
  src:url('../fonts/PretendardVariable.woff2') format('woff2-variations');
  font-weight:45 920; font-style:normal; font-display:swap;
}
/* 색·활자·모션의 정본은 lilt-tokens.css 다(첫 화면·편집기·콘솔이 같은 값을 쓴다).
   여기서는 그 토큰을 이 화면들이 오래 써 온 이름(--cobalt · --soft …)에 이어 붙인다 —
   2천 줄이 그 이름을 부르고 있어서, 이름을 갈면 화면이 통째로 무색이 된다.
   ⚠ 새 색을 여기서 만들지 말 것. 토큰에 없는 색이 필요하면 토큰에 먼저 넣는다. */
:root{
  /* 모노 — 흰 지면 위 잉크 한 색. 코발트는 걷어냈다(design_handoff_lilt). */
  --bg:#f4f3f1; --card:#ffffff;
  /* ⚠ 이름은 --cobalt 로 남았지만 값은 잉크다. 부르는 곳이 많아 이름만 두고 색을 갈았다. */
  --cobalt:#1a1a1a; --cobalt-deep:#1a1a1a;
  --sw-on:#1a1a1a;                  /* 토글 켜짐 — 잉크로 채운다 */
  --sw-off:rgba(0,0,0,.2);          /* 토글 꺼짐 — 윤곽선만 */
  --cobalt-soft:#f4f3f1; --baby:rgba(0,0,0,.05); --danger:#9a4a30; --ok:#1a1a1a;
}
*{box-sizing:border-box}
html,body{margin:0}
body{ line-height:1.6; font-size:15px; }
a{color:var(--cobalt-deep)}

/* 상단바 — 흰 띠. 아래 헤어라인 한 줄로만 본문과 나뉜다(유리·그림자 없음). */
.topbar{ position:sticky; top:0; z-index:10; }
.topbar__in{ display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  padding:18px var(--side) 6px; }
.topbar__out{ margin:0 0 0 auto; }
.brand-role{ font-size:11.5px; color:var(--soft); }
.brand{ font-weight:800; letter-spacing:.32em; color:var(--cobalt); text-indent:.32em; font-size:15px; }

/* 로고는 **마스크로만** 쓴다 — 색을 CSS 가 쥐고 있어야 지면 톤이 바뀔 때 따라온다.
   ⚠ 잉크가 캔버스 가운데 작게 앉은 파일이라, 박스를 키운 뒤 음수 마진으로 자리를 되돌린다. */
.brand-mark{ display:block;
  background-color:var(--cobalt);
  -webkit-mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
          mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
  transition:background-color .2s; }
.brand-link:hover .brand-mark{ background-color:var(--cobalt-deep); }
/* logo.png 은 1254x1254 정사각 캔버스에 잉크(별+워드마크)가 가로 59% / 세로 53% 만 차지하고
   나머지는 투명 여백이다. 그래서 박스를 키운 뒤 여백만큼 음수 마진으로 상쇄한다
   → 화면에는 크게, 레이아웃은 잉크 크기만큼만 차지.
   잉크 세로 50px 기준: 박스 94px, 상하 여백 (94-50)/2 = 22px */
.brand-img{
  height:94px; width:auto; display:block;
  margin-top:-22px; margin-bottom:-22px;
  margin-left:-12px; margin-right:-12px;
}
/* 로고를 감싼 링크(첫 화면으로). 자리를 차지하지 않게 flex 로 두어 위 음수 마진이 그대로 먹는다.
   ⚠ 모양을 바꾸지 않는다 — 로고는 원래도 눌러 보고 싶게 생겼고, 여기서 밑줄이나 테두리가
     생기면 상단바가 어수선해진다. 눌리는 느낌은 커서와 아주 옅은 투명도로만 준다. */
.brand-link{ display:flex; align-items:center; text-decoration:none;
  -webkit-tap-highlight-color:transparent; transition:opacity .18s ease; }
.brand-link:hover{ opacity:.72; }
.brand-link:active{ opacity:.6; }
/* 키보드 이동 표시는 남긴다 — 로고가 이제 링크라 탭 순서에 들어온다.
   ⚠ 링크 상자는 그림 상자(94px)가 아니라 **음수 마진을 뺀 잉크 크기(50px)** 다.
     그래서 평범한 offset 으로도 테두리가 로고에 딱 붙는다. */
.brand-link:focus-visible{ outline:2px solid var(--cobalt-deep); outline-offset:2px;
  border-radius:8px; }
.topbar .who{ font-size:13px; color:var(--soft); display:flex; align-items:center; gap:6px; }
.topbar .who b{ color:var(--ink); font-weight:450; }
/* 로그아웃 — 선만 두른 알약. 이 화면에서 채운 면은 [저장]·[발급] 같은 주 동작뿐이다. */
/* 로그아웃 — 테두리도 면도 없는 글자 하나(design_handoff_lilt).
   ⚠ 알약 테두리로 되돌리지 말 것. 상단바에 남는 유일한 동작이라 선을 두르면 그것만 부품처럼 뜬다. */
.logout{ display:inline-flex; align-items:center; height:34px; padding:0;
  border:none; border-radius:0; background:none; cursor:pointer;
  font-family:inherit; font-size:13px; font-weight:400; color:var(--soft); text-decoration:none;
  transition:color .2s; }
.logout:hover{ color:var(--ink); background:none; }

.wrap{ max-width:760px; margin:0 auto; padding:22px 16px 60px; }
.pagehead{ margin:8px 4px 20px; }
.pagehead h1{ margin:0 0 4px; }
.pagehead p{ margin:0; font-size:14px; font-weight:300; }
/* 한 단 위로 돌아가는 줄 — 제목 위에 얇게 붙는다 */
.back-link{ display:inline-flex; align-items:center; gap:4px; margin-bottom:8px;
  font-size:13px; color:var(--soft); text-decoration:none; transition:color .2s; }
.back-link:hover{ color:var(--cobalt); }
.card > h2{ display:flex; align-items:center; gap:8px; }
.card > h2 .badge{ font-size:11px; font-weight:450; padding:2px 9px; border-radius:999px;
  background:var(--cobalt-soft); color:var(--cobalt-deep); letter-spacing:.02em; }

.field{ margin-bottom:22px; }
/* 폼 내 소섹션 구분 헤딩(예: 오시는 길) */
.group-head{ font-size:12px; font-weight:450; color:var(--cobalt-deep); letter-spacing:.06em;
  margin:28px 0 14px; padding-bottom:8px; border-bottom:1px solid var(--line); }
.field:last-child{ margin-bottom:0; }
.field label{ display:block; font-size:13px; font-weight:600; color:var(--ink); margin-bottom:7px; }
.field .hint{ font-weight:400; color:var(--faint); }
.field input, .field select, .field textarea{
  width:100%; padding:12px 14px; border:1px solid var(--line); border-radius:11px;
  background:#fff; font-family:inherit; font-size:16px; color:var(--ink); transition:.15s; }
/* iOS Safari 포커스 자동확대 방지: 모든 텍스트 입력 16px 이상 */
input[type=text], input[type=tel], input[type=password], input[type=search], input:not([type]), textarea, select{ font-size:16px; }
.field input:focus, .field select:focus, .field textarea:focus{
  outline:none; border-color:var(--cobalt); box-shadow:0 0 0 3px rgba(58,95,176,.12); background:#fff; }
.row{ display:flex; gap:12px; margin-bottom:20px; }
.row > *{ flex:1; min-width:0; }
.row .field{ margin-bottom:0; }
@media (max-width:520px){ .row{ flex-direction:column; gap:15px; } }
.choice input{ position:absolute; opacity:0; }
/* ⚠ 여기에 **테두리를 두지 않는다**(2026-09-21). 고르는 칸은 선이 아니라 밑줄로 말한다 —
   아래 3a 블록의 `.choice .opt` 가 정본이다. 예전에는 이 줄에 1.5px 테두리와 12px 모서리가
   남아 있었고, 그것을 `border:0 !important` 로 눌러 두고 있었다. 그런 목발을 두면
   캐스케이드가 조금만 달라져도(브라우저·기기 배율) 눌린 선이 되살아난다. */
.choice .opt{ display:block; padding:13px 14px;
  text-align:center; font-weight:600; font-size:14px; color:var(--soft); transition:.15s; }

.btn{ display:inline-flex; align-items:center; justify-content:center; gap:8px; cursor:pointer;
  padding:12px 20px; border:1px solid transparent; font-family:inherit;
  font-size:14px; text-decoration:none; white-space:nowrap; }
.btn-ghost{ border-color:var(--line); }
.btn-danger{ border-color:rgba(154,74,48,.22); }
.btn-sm{ padding:8px 13px; font-size:13px; font-weight:600; }
.actions{ display:flex; gap:10px; margin-top:20px; }

.flash{ padding:12px 16px; border-radius:11px; font-size:14px; margin-bottom:18px; font-weight:600; }

.pill{ display:inline-block; padding:3px 10px; border-radius:999px; font-size:12px; font-weight:450; }

.list{ display:flex; flex-direction:column; gap:10px; }
.item{ display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:14px 16px; border:1px solid var(--line); border-radius:12px; background:#fff; }
.item .meta{ min-width:0; }
.item .t{ font-weight:450; font-size:14px; display:flex; align-items:center; gap:8px; }
.item .s{ font-size:12px; color:var(--soft); margin-top:2px; word-break:break-all; }
.item .grow{ flex:1; }
.item > form{ flex:none; }
.item > form .btn{ width:100%; }
/* 계좌 스테이징(전체 저장 전) 상태 */
.item.staged-add{ border-style:dashed; border-color:var(--cobalt); background:var(--cobalt-soft); }
.item.staged-del{ opacity:.55; }
.item.staged-del .t, .item.staged-del .s{ text-decoration:line-through; }
.stage-tag{ font-size:11px; font-weight:450; color:var(--cobalt-deep); background:#fff;
  border:1px solid var(--baby); border-radius:999px; padding:1px 7px; }
.acct-add{ border-top:1px dashed var(--line); margin-top:6px; padding-top:14px; }
.inline-form{ display:flex; gap:8px; align-items:center; }
.inline-form select{ padding:8px 10px; border:1px solid var(--line); border-radius:9px; background:#fff; font-size:13px; }

.empty{ text-align:center; padding:34px 16px; color:var(--soft); }
.empty .big{ font-size:15px; font-weight:450; color:var(--ink); margin-bottom:6px; }

.preview-link{ display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:600; }
.muted{ color:var(--faint); font-size:12px; }

/* 클릭 가능한 리스트 항목(고객 행) */
.item.clickable{ cursor:pointer; transition:.15s; }
.item.clickable:hover{ box-shadow:0 4px 14px rgba(43,71,136,.06); }
.item .chev{ color:var(--faint); font-size:18px; flex:none; }
/* 순서 이동 — 테두리 박스가 그대로 드러나 행마다 화살표 버튼 두 개가 대놓고 붙어 보였다.
   박스와 배경을 걷어내고 평소에는 흐리게 두었다가, 그 행에 마우스가 올라오거나
   키보드 포커스가 들어올 때만 또렷해지게 한다. 기능·마크업은 그대로다. */
.acct-move{ display:flex; flex-direction:column; gap:0; flex:none; margin-right:-2px;
  opacity:.26; transition:opacity .15s; }
.item:hover .acct-move,
.item:focus-within .acct-move{ opacity:1; }
.acct-move__btn{ display:flex; align-items:center; justify-content:center; width:20px; height:15px;
  border:none; border-radius:5px; background:none; color:var(--faint);
  font-size:9px; line-height:1; cursor:pointer; padding:0; transition:.12s; }
.acct-move__btn:hover{ color:var(--cobalt-deep); background:var(--cobalt-soft); }
.acct-move__btn:focus-visible{ outline:2px solid var(--cobalt); outline-offset:1px; }
/* 터치 기기에는 hover 가 없어 흐린 채로 남는다 — 항상 보이게 둔다. */
@media (hover:none){ .acct-move{ opacity:.75; } }
.item.staged-del .acct-move__btn{ pointer-events:none; opacity:.5; }

/* 모달(팝업) */
.modal{ display:none; position:fixed; inset:0; z-index:50; align-items:center; justify-content:center; padding:18px; }
.modal.open{ display:flex; }
.modal__backdrop{ position:absolute; inset:0; }
.modal__box{ position:relative; width:100%; max-width:440px; max-height:88vh; overflow:auto; }
/* 고객 상세는 담는 값이 많아 440px 에서는 거의 모든 줄이 두 줄로 접혔다.
   ⚠ 폭만 넓힌다. 라벨 열(.info-row .k)은 그대로 둬야 다른 팝업과 눈높이가 같다. */
.modal--wide .modal__box{ max-width:560px; }
.modal__head{ display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  padding:20px 22px 14px; border-bottom:1px solid var(--line); position:sticky; top:0; background:var(--card); }
.modal__title{ font-size:17px; font-weight:450; }
.modal__sub{ font-size:12px; color:var(--soft); margin-top:3px; }
.modal__x{ flex:none; width:30px; height:30px; font-size:14px; cursor:pointer; }
.modal__x:hover{ background:rgba(0,0,0,.08); }
/* 팝업 안의 글은 전부 어절로 끊는다 — 안내문이 "않습니/다" 처럼 갈라지지 않게.
   .info-row .v 만 고쳐서는 .hint·설명문이 그대로 남는다. */
.modal__body{ padding:18px 22px; word-break:keep-all; overflow-wrap:anywhere; }
/* ⚠ flex-wrap 이 없으면 버튼이 좁은 화면에서 상자 밖으로 삐져나온다 */
.modal__foot{ padding:14px 22px 20px; display:flex; align-items:center; gap:8px; border-top:1px solid var(--line); }
.modal__foot form{ margin:0; display:inline-flex; }
.modal__foot .btn{ height:38px; padding:0 15px; font-size:13px; font-weight:600; white-space:nowrap; }
.modal__foot .del-form{ margin-left:auto; }

.info-row{ display:flex; align-items:flex-start; gap:12px; padding:9px 0; border-bottom:1px dashed var(--line); }
.info-row:last-child{ border-bottom:none; }
.info-row .k{ flex:none; width:78px; color:var(--soft); line-height:1.55; }
/* ⚠ word-break:break-all 이었다 — 한글이 낱자 단위로 아무 데서나 끊겨 "않습/니다" 처럼
   보였다. 한국어는 어절로 끊어야 읽힌다.
   긴 주소·슬러그처럼 띄어쓰기가 없는 값은 overflow-wrap 이 받아 낸다. */
.info-row .v{ flex:1; min-width:0; font-size:14px; color:var(--ink); line-height:1.55;
  word-break:keep-all; overflow-wrap:anywhere; white-space:pre-line; }
.info-empty{ text-align:center; color:var(--soft); padding:26px 10px; font-size:14px; }

/* 핸드폰 3칸 입력 */
.phone-3{ display:flex; align-items:center; gap:8px; }
.phone-3 input{ flex:1; min-width:0; text-align:center; letter-spacing:.05em; }
.phone-3 input[data-phone="1"]{ flex:0 0 74px; }
.phone-3 .sep{ flex:none; color:var(--faint); }
/* 첫 칸이 고르는 칸인 경우(편집 화면) — 직접 적게 두면 오타가 그대로 전화 버튼이 된다.
   ⚠ 폭을 고정한다. 늘어나게 두면 국번 칸이 뒤 두 칸보다 넓어져 균형이 깨진다. */
.phone-3 select[data-phone]{ flex:0 0 82px; min-width:0; text-align:center;
  letter-spacing:.05em; }
/* 좁은 화면에서는 세 칸이 서로를 눌러 숫자가 잘린다 — 구분자를 지우고 간격을 좁힌다 */
@media (max-width:420px){
  .phone-3{ gap:5px; }
  .phone-3 .sep{ display:none; }
  .phone-3 select[data-phone]{ flex:0 0 74px; }
}
.pagehead h1{ font-size:23px; }

/* 접기(혼주 정보 등) */
.foldable{ border:1px solid var(--line); border-radius:13px; padding:0 15px; margin-bottom:16px; background:#fff; }
.foldable > summary{ cursor:pointer; padding:14px 0; font-size:14px; font-weight:600; color:var(--ink);
  list-style:none; display:flex; align-items:center; gap:9px; }
.foldable > summary::-webkit-details-marker{ display:none; }
.foldable > summary::before{ content:"+"; color:var(--cobalt); font-weight:800; font-size:16px; width:14px; text-align:center; }
.foldable[open] > summary::before{ content:"\2013"; }
.fold-body{ padding:2px 0 14px; }
/* 섹션 안의 소제목. ⚠ 코발트 굵은 대문자 라벨로 되돌리지 말 것 — 다른 섹션의 라벨은 전부
   조용한 회색이라, 여기만 색이 들어가면 공유·음원 화면이 딴 화면처럼 보인다.
   한글 제목은 얇은 톤으로 쓰고 크기로만 세운다. */
.subhead{ font-size:13px; font-weight:450; color:var(--ink); letter-spacing:-.01em; margin:14px 0 2px; }
.fold-body .subhead:first-child{ margin-top:2px; }

/* 혼주(부모) 접기 — 신랑/신부 각 1줄 */
.fold-details{ margin-top:8px; margin-bottom:16px; border:1px solid var(--line); border-radius:12px; background:#fff; }
.fold-details > summary{ cursor:pointer; padding:12px 14px; font-weight:600; font-size:13.5px; color:var(--soft);
  list-style:none; display:flex; align-items:center; justify-content:space-between; gap:8px; }
.fold-details > summary::-webkit-details-marker{ display:none; }
.fold-details > summary::after{ content:"\25BE"; color:var(--faint); font-size:12px; transition:transform .2s ease; }
.fold-details[open] > summary::after{ transform:rotate(180deg); }
.fold-details[open] > summary{ border-bottom:1px solid var(--line); }
.fold-details .fold-body{ padding:12px 14px 14px; }
.parent-group{ margin-bottom:15px; }
.parent-group:last-child{ margin-bottom:0; }
.parent-group__label{ font-size:12.5px; font-weight:450; color:var(--ink); margin-bottom:7px; }
.parent-group__row{ display:flex; gap:8px; margin-bottom:8px; }
.parent-group input{ width:100%; min-width:0; padding:10px 11px; border:1px solid var(--line); border-radius:9px;
  background:#fff; font-family:inherit; font-size:16px; color:var(--ink); transition:.15s; }
.parent-group__row input{ flex:1; }
.parent-group input:focus{ outline:none; border-color:var(--cobalt); box-shadow:0 0 0 3px rgba(58,95,176,.12); }

/* 대중교통 안내(여러 개) — 폰에서 넓게 쓰도록 설명 입력은 한 줄 전체 */
.transit-list{ display:flex; flex-direction:column; gap:7px; margin-bottom:9px; }
.transit-list:empty{ display:none; }
.transit-row{ display:flex; align-items:flex-start; gap:9px; padding:10px 12px; border:1px solid var(--line); border-radius:10px; background:#fff; }
/* 분류 라벨은 글자 수(버스 2 ~ 셔틀버스 4)에 따라 폭이 달라져 뒤따르는 내용 텍스트의
   시작점이 행마다 어긋났다. 라벨 폭을 고정해 내용의 좌측 정렬선을 하나로 맞춘다. */
.transit-row__type{ flex:none; margin-top:1px; font-size:11.5px; font-weight:450; color:var(--cobalt-deep); background:var(--cobalt-soft); border-radius:999px; padding:2px 9px;
  display:inline-flex; align-items:center; justify-content:center; width:70px; white-space:nowrap; }
.transit-row__desc{ flex:1; min-width:0; font-size:13.5px; color:var(--ink); word-break:break-word; line-height:1.5; }
.transit-row__x{ flex:none; width:24px; height:24px; border:none; border-radius:50%; background:rgba(20,28,45,.5); color:#fff; font-size:13px; line-height:1; cursor:pointer; }
.transit-add{ display:flex; flex-direction:column; gap:8px; }
.transit-add__row{ display:flex; gap:8px; }
.transit-add__row select{ flex:none; width:120px; }
.transit-add__row .btn{ flex:none; }
/* ⚠ 120px 셀렉트 + 입력 + 버튼은 360px 화면에서 20px 넘친다.
   좁아지면 줄을 바꿔 셀렉트와 버튼이 한 줄을 나눠 갖게 한다. */
@media (max-width:420px){
  .transit-add__row{ flex-wrap:wrap; }
  .transit-add__row select{ flex:1 1 auto; width:auto; min-width:0; }
  .transit-add__row .btn{ flex:none; }
}
.transit-add > input{ width:100%; }

/* 방명록 목록 페이징 — 편집 페이지 모달이 대시보드 카드로 옮겨 가면서
   모달 전용 규칙(#guestbookModal · #gbManageList)은 지웠고 페이저만 남겨 재사용한다. */
.gb-mpager{ display:flex; align-items:center; justify-content:center; gap:14px; }
.gb-mpager:empty{ display:none; }

/* 방명록 관리 모달의 목록 — 편집 화면을 떠나지 않고 여기서 지운다.
   ⚠ 글이 수십 개가 될 수 있어 목록 자체에 스크롤을 준다. 모달 전체가 길어지면
     삭제 버튼을 누르러 매번 끝까지 내려가야 한다. */
.gb-list{ display:flex; flex-direction:column; gap:8px; max-height:min(52vh, 420px); overflow-y:auto; }
.gb-item{ display:flex; align-items:flex-start; gap:10px; padding:11px 13px;
  border:1px solid var(--line); border-radius:11px; background:#fff; }
.gb-item__txt{ flex:1; min-width:0; display:flex; flex-direction:column; gap:3px; }
.gb-item__txt b{ font-size:13px; color:var(--ink); }
/* 하객이 줄바꿈 없이 길게 적는 경우가 있다 — 넘치지 않게 끊는다 */
.gb-item__txt span{ font-size:12.5px; line-height:1.6; color:var(--soft);
  word-break:break-word; overflow-wrap:anywhere; white-space:pre-line; }
.gb-item__del{ flex:none; }
.gb-item__del:hover{ border-color:var(--danger); color:var(--danger); }
.gb-empty{ padding:16px; border:1px dashed var(--line); border-radius:12px;
  background:#fff; color:var(--soft); font-size:13px; text-align:center; }
.gb-empty[hidden]{ display:none; }
.gb-mpg{ width:34px; height:34px; border-radius:50%; border:1px solid var(--line); background:#fff; color:var(--cobalt-deep); font-size:16px; line-height:1; cursor:pointer; }
.gb-mpg:disabled{ color:var(--faint); opacity:.5; cursor:default; }
.gb-mpg-info{ font-size:13px; color:var(--soft); }

/* ── 초대 문구 예시 — **선으로 나눈 행 목록** ──────────────────────────────
   문구의 첫머리를 그대로 보여 준다. 번호만 적힌 알약("추천 1"~"추천 5")은 눌러 보기 전에는
   무슨 글인지 알 수 없어 2026-09-20 에 걷어냈다 — **칩으로 되돌리지 말 것.**
   행 어휘는 이 지면의 목록들(.item · .sortrow)과 같다: 면 없음 · radius 0 · 아래 헤어라인. */
.preset-list{ display:flex; flex-direction:column; margin:2px 0 12px; }
.preset-item{ display:grid; grid-template-columns:auto minmax(0,1fr); align-items:baseline;
  gap:14px; width:100%; padding:12px 0; text-align:left; cursor:pointer;
  background:none; border:0; border-bottom:1px solid var(--line-soft); border-radius:0;
  font-family:inherit; transition:color .2s; }
.preset-item__n{ font-size:11px; font-weight:400; letter-spacing:.04em; color:var(--ghost); }
/* 한 줄로 훑는다 — 목록에서 전문을 펼치면 다섯 덩어리가 지면을 덮는다 */
.preset-item__t{ font-size:13.5px; font-weight:300; line-height:1.6; color:var(--soft);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.preset-item:hover .preset-item__t{ color:var(--ink); }
.preset-item.is-on .preset-item__n{ color:var(--acc); }
.preset-item.is-on .preset-item__t{ color:var(--acc-ink); }
/* 비우고 직접 쓰기 — 목록에 끼우지 않고 아래에 조용히 둔다(예시가 아니라 되돌리기다) */
.preset-reset{ align-self:flex-start; margin:0 0 26px; padding:0; border:0; background:none;
  font-family:inherit; font-size:12.5px; font-weight:300; color:var(--soft); cursor:pointer;
  text-decoration:underline; text-underline-offset:4px; text-decoration-color:var(--line); }
.preset-reset:hover{ color:var(--acc-ink); }

/* 토글 스위치 */
/* 스위치 줄 — 시안: 라벨 16px/500 · 오른쪽에 [상태 문구][트랙] · 아래 헤어라인 하나. */
.switch-row{ display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding:2px 0 14px; border-bottom:1px solid var(--line); margin:0; cursor:pointer; }
.switch-label{ font-weight:500; font-size:16px; color:var(--ink); }
/* 상태 문구(사용 중 / 꺼짐) — 마크업이 아니라 여기서 붙인다(스위치 줄이 열 곳이 넘는다).
   ⚠ `.wiz-use` 안의 스위치에는 이미 "사용" 글자가 있으므로 `.switch-row` 로 좁힌다. */
.switch-row .switch::before{
  content:'꺼짐'; position:absolute; right:calc(100% + 9px); top:50%; transform:translateY(-50%);
  font-size:13px; color:var(--ghost); white-space:nowrap; transition:color .3s;
}
.switch-row:has(input:checked) .switch::before{ content:'사용 중'; color:var(--acc-ink); }
/* iOS 토글 — 51×31 트랙에 27px 노브(실제 iPhone 비율).
   불투명 컬러 대신 반투명 유리: 트랙이 뒤를 비추고, 테두리 하이라이트로 두께를 만든다. */
/* ── 토글 — **얇은 트랙 위의 작은 노브** ───────────────────────────────────
   근거: design_handoff_lilt — "노출 스위치(26×3px 트랙 + 13px 노브)".
   ⚠ iOS 유리 스위치(51×31, 두꺼운 트랙, blur, 그림자)로 되돌리지 말 것 —
     헤어라인 지면에서 그것만 다른 서비스의 부품처럼 튄다(2026-09-18 지적).
   ⚠ 누르는 자리는 그대로 넓게 둔다(상자는 40×28). 트랙만 얇고, 손가락이 닿는 면적은
     줄이지 않는다 — 넓은 연령대가 쓰는 화면이다. */
/* 근거: InvitationEditor.dc.html — 트랙 **26×3px**(rgba(0,0,0,.14)) 위를
   **13×3px accent 막대**가 왼→오로 미끄러진다. 원형 노브도, 링도, 그림자도 없다.
   ⚠ 이동폭 = 트랙폭 − 막대폭 = 26 − 13 = **13px**. 트랙 크기를 고치면 이 값도 같이 고칠 것.
   ⚠ 누르는 자리는 넓게 둔다(상자 세로 28px + 감싼 라벨의 패딩) — 넓은 연령대가 쓰는 화면이다. */
.switch{ position:relative; display:inline-block; width:26px; height:28px; flex:none;
  cursor:pointer; }
.switch input{ position:absolute; opacity:0; width:0; height:0; }
.switch .slider{
  position:absolute; left:0; right:0; top:50%; height:3px; margin-top:-1.5px;
  border-radius:0; background:var(--line);
  -webkit-backdrop-filter:none; backdrop-filter:none; box-shadow:none;
  transition:background-color .28s var(--ease-ios, cubic-bezier(.32,.72,0,1));
}
/* 막대 — 트랙과 같은 두께다. 꺼져 있어도 왼쪽 끝에 보인다(무엇이 움직이는지 알린다). */
.switch .slider::before{
  content:""; position:absolute; width:13px; height:3px; left:0; top:50%;
  margin-top:-1.5px; border-radius:0;
  background:var(--acc); box-shadow:none; opacity:.34;
  transition:transform .34s var(--e-spring, cubic-bezier(.34,1.56,.64,1)), opacity .28s;
}
.switch input:checked + .slider{ background:var(--line); box-shadow:none; }
.switch input:checked + .slider::before{ transform:translateX(13px); opacity:1; }
.switch input:focus-visible + .slider::before{ box-shadow:var(--acc-glow); }

/* 옵션 설정 블록 */
.opt-block{ padding:14px 2px 6px; }
/* 지도 안내 — 스위치가 무엇을 켜는지 설명하는 한 줄뿐이라 **그 줄에 붙여** 둔다.
   ⚠ 기본 .opt-block 여백(위 14px)은 칸·선택지를 담는 블록 기준이다. 한 줄 안내가
     그만큼 떨어지면 스위치와 딴 항목처럼 읽힌다(2026-09-22 지적). */
#block-venuemap{ padding:4px 2px 0; }
.sub-upload{ border-top:1px dashed var(--line); margin-top:8px; padding-top:16px; }
/* ── 파일 고르기 ── 브라우저 기본 버튼은 OS·브라우저마다 다르게 생겨 이 지면과 따로 논다.
   ⚠ input 을 감추고 label 로 바꾸지 않는다 — 키보드와 스크린리더가 닿는 길을 잃는다.
     기본 버튼의 **모양만** 지면 어휘로 갈아입힌다(선 1px · radius 0 · 작은 활자).
   ⚠ 약도·앨범·공유 카드가 같은 .upload-form 을 쓴다 — 한 곳에서 같이 바뀐다. */
.upload-form input[type=file]{
  width:100%; max-width:100%; padding:0; border:0; background:none;
  font-family:inherit; font-size:12.5px; font-weight:300; color:var(--soft);
}
.upload-form input[type=file]::file-selector-button{
  height:34px; margin-right:12px; padding:0 16px;
  border:1px solid rgba(0,0,0,.2); border-radius:0; background:none;
  font-family:inherit; font-size:12.5px; font-weight:450; color:var(--ink);
  letter-spacing:-.01em; cursor:pointer;
  transition:background-color .16s, border-color .16s;
}
.upload-form input[type=file]::file-selector-button:hover{
  background:rgba(0,0,0,.04); border-color:var(--ink);
}
.upload-form input[type=file]:focus-visible::file-selector-button{
  outline:1px solid var(--ink); outline-offset:2px;
}
/* 옛 브라우저(웹킷 전용 이름) — 위와 같은 모양을 한 번 더 적는다. */
.upload-form input[type=file]::-webkit-file-upload-button{
  height:34px; margin-right:12px; padding:0 16px;
  border:1px solid rgba(0,0,0,.2); border-radius:0; background:none;
  font-family:inherit; font-size:12.5px; font-weight:450; color:var(--ink);
  letter-spacing:-.01em; cursor:pointer;
}

/* 이미지 썸네일 / 갤러리 */
.thumb-row{ margin-bottom:12px; }
/* 좁은 화면은 3열. 넓어지면 칸 수가 늘어나 썸네일이 커지지 않는다 — 
   3열 고정이면 편집 컬럼이 760px 까지 넓어질 때 한 장이 240px 넘게 부풀었다. */
.gallery-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:6px; margin-bottom:6px; }
/* ⚠ 칸 높이는 저마다의 aspect-ratio(1:1)가 정한다. 그리드 아이템 기본값(stretch)을 두면
   같은 줄에서 한 칸이 커질 때 나머지가 따라 늘어나, 저장된 사진과 새로 고른 사진의
   아래 경계가 어긋났다. */
.gallery-grid > *{ align-self:start; }
/* ⚠ 모서리는 각이다(radius 0) — 토큰 정본이자 편집기 핸드오프의 사진 칸 규격이다.
   둥근 모서리(11px)로 되돌리지 말 것. */
.thumb{ position:relative; border-radius:0; overflow:hidden; background:rgba(0,0,0,.05); border:1px solid var(--line); aspect-ratio:1/1; }
.thumb.thumb-wide{ aspect-ratio:16/10; max-width:340px; }
.thumb img{ width:100%; height:100%; object-fit:cover; display:block; }
.thumb-del{ position:absolute; top:5px; right:5px; margin:0; }
.thumb-x{ width:24px; height:24px; border:none; border-radius:50%; background:rgba(20,28,45,.6);
  color:#fff; font-size:12px; line-height:1; cursor:pointer; display:flex; align-items:center; justify-content:center; }
.thumb-x:hover{ background:rgba(192,69,69,.92); }
/* 첫 화면 대표 사진 선택 */
.thumb .hero-pick{ position:absolute; left:50%; bottom:6px; transform:translateX(-50%); z-index:3;
  font-size:10.5px; font-weight:450; line-height:1; padding:4px 9px; border-radius:999px; cursor:pointer;
  border:1px solid var(--cobalt-deep); background:rgba(255,255,255,.92); color:var(--cobalt-deep); white-space:nowrap; }
.thumb .hero-pick:hover{ background:#fff; }
.thumb.is-hero{ border-color:var(--cobalt-deep); box-shadow:inset 0 0 0 2px var(--cobalt-deep); }
.thumb.is-hero .hero-pick{ background:var(--cobalt-deep); color:#fff; }
.thumb.is-hero .hp-txt::after{ content:' ✓'; }

/* 업로드 폼 — 사진 칸은 저장된 사진과 **한 그리드로 이어진다**(핸드오프 §사진).
   ⚠ 파일 입력은 감춘다. 브라우저 기본 버튼은 이 화면의 어휘와 맞지 않고, 예전에는
     그 줄 때문에 저장된 사진(정사각 4열)과 새로 고른 사진(64px 조각)이 따로 놀았다.
   ⚠ display:none 이 아니라 자리만 없앤다 — none 이면 일부 브라우저에서 click() 이 먹지 않는다. */
.gal-file{ position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; }
/* ⚠ contents — 미리보기 칸이 위 그리드에 **직접** 들어가야 저장된 사진과 같은 크기로 선다.
   감쌀 상자를 만들면 새 사진 전체가 한 칸에 욱여넣어진다. */
.preview-strip{ display:contents; }
.preview-strip .pv{ width:100%; height:100%; object-fit:cover; border-radius:0; border:1px solid var(--line); }
/* ── 약도 미리보기 ── 앨범 그리드가 아니라 **혼자 놓이는** 자리다(2026-09-22).
   ⚠ .preview-strip 은 display:contents 라 상자가 없다 — 앨범 그리드 칸에 낱장으로 들어가려고
     그렇게 둔 것이다. 그리드가 아닌 여기서는 그림이 폭을 꽉 채우고 파일 버튼에 붙어 버린다.
     **id 로 좁혀** 이 자리에서만 상자로 세운다 — 앨범 규칙(.preview-strip > .pv)은 건드리지 않는다.
   ⚠ 약도는 가로로 긴 그림이 많다. cover 로 자르지 말고 contain 으로 비율을 지킨다. */
#map-preview{ display:block; margin-top:16px; }
#map-preview .pv{ width:auto; max-width:200px; height:auto; max-height:140px;
  object-fit:contain; border:1px solid var(--line); border-radius:0; }
#map-preview:empty{ margin-top:0; }

/* ＋ 칸 — 사진과 같은 정사각. 누르면 감춰 둔 파일 입력이 열린다. */
.gal-add{ aspect-ratio:1/1; border:1px solid var(--line); border-radius:0; background:transparent;
  font-family:inherit; font-size:18px; line-height:1; color:var(--ink); cursor:pointer;
  transition:background-color .2s, transform 90ms; }
.gal-add:hover{ background:var(--acc-bg); }
.gal-add:active{ transform:scale(.95); }
/* 새 사진 미리보기에서 대표 지정
   ⚠ overflow:hidden — 저장된 사진(.thumb)과 같이 칸 안에 가둔다. 없으면 [대표] 알약이
     칸 아래로 삐져나와 그 줄만 키가 커진다. */
/* ⚠ 상자 구조를 .thumb 과 **똑같이** 둔다 — 테두리를 바깥 상자가 들고 안쪽 그림은 꽉 채운다.
   예전에는 테두리를 .pv 가 들어, 같은 줄에 선 저장된 사진과 아래 경계가 1~2px 어긋났다. */
.pv-wrap{ position:relative; width:auto; margin:0; aspect-ratio:1/1; overflow:hidden;
  background:rgba(0,0,0,.05); border:1px solid var(--line); }
/* ⚠ `object-fit` 을 여기 **직접** 적는다 — 위 `.preview-strip .pv` 에서 흘러오기를 기대하면,
   그 규칙을 손댈 때 조용히 `fill` 로 떨어져 사진이 찌그러진다(저장된 `.thumb img` 와 같은 값이다). */
.pv-wrap .pv{ margin-bottom:0; width:100%; height:100%; object-fit:cover; border:none; }
/* ⚠ 자리·크기를 저장된 사진의 [대표](.hero-pick)와 같게 둔다 — 한 그리드에 나란히 서므로
   둘이 다르면 새 사진만 버튼이 작고 아래로 처져 보인다. */
.pv-wrap .pv-hero{ position:absolute; left:50%; bottom:6px; transform:translateX(-50%); z-index:2;
  font-size:10.5px; font-weight:450; line-height:1; padding:4px 9px; border-radius:999px; cursor:pointer; white-space:nowrap;
  border:1px solid var(--cobalt-deep); background:rgba(255,255,255,.92); color:var(--cobalt-deep); }
.pv-wrap.is-hero .pv{ outline:2px solid var(--cobalt-deep); outline-offset:0; }
.pv-wrap.is-hero .pv-hero{ background:var(--cobalt-deep); color:#fff; }

/* ── 버튼 리스타일 (플랫 · 그라데이션/무거운 그림자 제거) ── */
.btn{ transition:transform .12s ease, background .15s, border-color .15s; }
.btn:active{ transform:translateY(1px); }
.btn-ghost{ background:#fff; color:var(--cobalt-deep); border:1px solid var(--line); }
.btn-danger{ background:#fff; border:1px solid rgba(154,74,48,.22); }
.btn-sm{ border-radius:9px; }
.btn-block{ width:100%; }

/* ── 모달 애니메이션 ── */
.modal.open .modal__backdrop{ animation:liltFade .22s ease both; }
.modal.open .modal__box{ animation:liltPop .34s cubic-bezier(.2,1.05,.32,1) both; }
@keyframes liltFade{ from{opacity:0} to{opacity:1} }
@keyframes liltPop{ 0%{opacity:0; transform:translateY(14px) scale(.9);} 60%{opacity:1;} 100%{opacity:1; transform:translateY(0) scale(1);} }

/* ── 하단 푸터 ── */
/* 푸터 — **세 화면 공통 규격**(첫 화면 · 편집기 · 운영자 콘솔).
   한 줄로 얇게, 왼쪽 로고 30px / 오른쪽 저작권. 세로로 쌓거나 가운데 정렬하지 말 것.
   ⚠ bridge.css 의 `.ct__foot` 가 같은 규격이다 — 한쪽만 고치지 않는다. */
.site-foot{ display:flex; align-items:center; gap:12px;
  margin-top:26px; padding:18px 2px 24px; border-top:1px solid var(--line);
  color:var(--faint); text-align:left; }
.site-foot .mark{ display:block; flex:none; width:44px; height:44px;
  background-color:rgba(0,0,0,.28);
  -webkit-mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
          mask:url(../img/apple-touch-icon.png) center/contain no-repeat; }
/* 알약 버튼이 아니라 작은 글자 링크다 — 버튼으로 두면 푸터가 그만큼 두꺼워진다 */
.site-foot .insta{ display:inline-flex; align-items:center; gap:6px; color:var(--soft);
  text-decoration:none; font-size:11.5px; font-weight:400; padding:0; border:0;
  border-radius:0; background:none; transition:color .15s; }
.site-foot .insta:hover{ color:var(--acc-ink); }
.site-foot .insta .ico{ flex:none; width:13px; height:13px; background-color:currentColor;
  -webkit-mask:url(../img/instagram.png) center/contain no-repeat;
          mask:url(../img/instagram.png) center/contain no-repeat; }
.site-foot .copy{ margin:0 0 0 auto; font-size:11.5px; font-weight:300;
  color:var(--faint); letter-spacing:-.005em; }

/* 앨범 유형 미리보기 */
.gtype-row{ display:flex; gap:9px; margin-bottom:6px; }
.gtype{ flex:1; cursor:pointer; position:relative; }
.gtype input{ position:absolute; width:0; height:0; opacity:0; margin:0; }
.gtype .gt-card{ display:block; border:1px solid var(--line); border-radius:12px; padding:10px 8px; text-align:center; background:#fff; transition:.15s; }
.gtype .gt-name{ display:block; }
.gtype input:checked + .gt-card{ border-color:var(--cobalt); background:var(--cobalt-soft); }
.gt-prev{ display:block; height:38px; margin-bottom:7px; overflow:hidden; }
.gt-prev i{ display:block; background:rgba(0,0,0,.14); border-radius:3px; }
/* 썸네일 격자 */
.gt-grid{ display:grid; grid-template-columns:repeat(3,1fr); grid-template-rows:repeat(3,1fr); gap:3px; height:100%; }
.gt-grid i{ height:100%; }
/* 비정형(3×3 그리드에 행 스팬으로 배치 → 카드 밖으로 넘치지 않음) */
.gt-mason{ display:grid; grid-template-columns:repeat(3,1fr); grid-template-rows:repeat(3,1fr); gap:3px; height:100%; }
.gt-mason i{ height:auto; }
.gt-mason i:nth-child(1){ grid-column:1; grid-row:1/3 }
.gt-mason i:nth-child(2){ grid-column:1; grid-row:3 }
.gt-mason i:nth-child(3){ grid-column:2; grid-row:1 }
.gt-mason i:nth-child(4){ grid-column:2; grid-row:2/4 }
.gt-mason i:nth-child(5){ grid-column:3; grid-row:1 }
.gt-mason i:nth-child(6){ grid-column:3; grid-row:2/4 }
/* 슬라이드(큰 사진 + 옆 사진이 살짝 보이는 캐러셀 느낌, 넘침은 클립) */
.gt-slide{ display:flex; gap:3px; height:100%; }
.gt-slide i{ height:100%; flex:0 0 22%; }
.gt-slide i:nth-child(1){ flex:0 0 68% }
.gt-name{ font-size:12px; font-weight:450; color:var(--ink); }
.gtype input:checked + .gt-card .gt-name{ color:var(--cobalt-deep); }


/* ── 대화상자 — 알림 · 확인 · 한 줄 입력 ──
   묻는 말 한 줄을 가운데 모은 작은 상자다. 활자는 본문보다 **작게** 간다 — 상자가 커지면
   지면을 밀어내는 경고처럼 보인다.
   ⚠ `.btn` 을 쓰지 않는다. 콘솔(.adm-body .btn)과 편집기가 각자 `.btn` 을 덮어써서
     **같은 상자가 화면마다 다른 버튼**으로 보였다(콘솔 11.5px 각진 버튼 / 편집기 14.5px 알약).
     이 상자는 어느 화면에 떠도 제 모양이라야 한다.
   ⚠ 한글은 어절로 끊는다 — 없으면 "되돌/릴", "남습/니다" 처럼 갈라진다.
   ⚠ 그림 아이콘(체크·✕ 동그라미)은 2026-09-21 에 걷었다. 되살리지 말 것 —
     묻는 말이 곧 내용이고, 이 지면은 활자로 말한다. */
.modal__box.dlg{ max-width:296px; padding:0; background:#fff;
  border:1px solid var(--line); border-radius:0; box-shadow:none;
  word-break:keep-all; overflow-wrap:anywhere; text-align:center; }
.dlg__body{ padding:26px 22px 22px; }
.dlg__title{ font-size:14px; font-weight:450; line-height:1.6; letter-spacing:-.015em; color:var(--ink); }
.dlg__sub{ margin-top:8px; font-size:11.5px; font-weight:300; line-height:1.75;
  color:var(--soft); white-space:pre-line; }
/* 되돌릴 수 없는 일 — 제목만 물들인다(면을 붉게 칠하지 않는다) */
.dlg--err .dlg__title{ color:var(--danger); }
/* 하단 액션 — 상자 폭을 꽉 채운 칸. 채운 면이 주 동작이라는 규칙은 여기서도 같다. */
.dlg__acts{ display:flex; border-top:1px solid var(--line); }
.dlg__btn{ flex:1 1 0; min-width:0; height:42px; padding:0; margin:0;
  border:0; border-radius:0; background:#fff; color:var(--ink);
  font-family:inherit; font-size:12.5px; font-weight:400; letter-spacing:-.01em;
  cursor:pointer; transition:background-color .16s, opacity .16s; }
.dlg__btn + .dlg__btn{ border-left:1px solid var(--line); }
.dlg__btn:hover{ background:rgba(0,0,0,.035); }
.dlg__btn--go{ background:var(--ink); color:#fff; }
.dlg__btn--go:hover{ background:var(--ink); opacity:.86; }
.dlg__btn[disabled]{ color:var(--faint); background:#fff; cursor:default; }
.dlg__btn--go[disabled]{ background:rgba(0,0,0,.12); color:#fff; }
/* 상자를 열면 주 버튼에 포커스가 간다. 브라우저 기본 외곽선은 이 지면과 어긋나므로 바꾼다. */
.dlg__btn:focus{ outline:none; }
/* 상자를 열면 주 버튼에 포커스가 간다 — 그때마다 검은 네모가 그려지면 눌린 것처럼 보인다.
   ⚠ 옅은 선이라 **채운 버튼(--go) 위에서는 보이지 않는다.** 그래서 마우스로 여는 보통의
     경우에는 아무 표식도 남지 않고, Tab 으로 흰 버튼에 간 사람에게만 은은하게 드러난다.
   ⚠ 아예 `outline:none` 으로 지우지 말 것 — 키보드로 쓰는 사람이 어디 있는지 알 수 없게 된다. */
.dlg__btn:focus-visible{ outline:1px solid rgba(0,0,0,.22); outline-offset:-1px; }
/* 한 줄 입력(liltPrompt) — 편집기와 같은 밑줄 입력이다. 상자만 다른 어휘를 쓰지 않는다. */
/* ⚠ 이 칸도 가운데다 — 상자 안에서 이것만 왼쪽에 붙으면 축이 어긋나 보인다.
   한 줄 사유를 받는 자리라 글이 길어져도 감당된다. */
.dlg__input{ width:100%; box-sizing:border-box; height:36px; margin-top:16px; padding:0;
  border:0; border-bottom:1px solid var(--line); border-radius:0; background:none;
  font-family:inherit; font-size:13px; font-weight:300; color:var(--ink);
  text-align:center; outline:none; transition:border-color .2s; }
.dlg__input:focus{ border-bottom-color:var(--ink); }
.dlg__input::placeholder{ color:var(--faint); }

/* ═══════════════ 고객 검색 + 페이징(운영자) ═══════════════ */
.search-box{ position:relative; margin-bottom:14px; }
/* ⚠ 돋보기는 **오른쪽 끝**에 둔다. 밑줄 입력에서는 왼쪽에 두면 글자가 시작하는 자리가
   아이콘만큼 밀려, 아래 목록의 이름 열과 눈높이가 어긋난다. */
.search-box svg{ position:absolute; right:2px; top:50%; transform:translateY(-50%);
  width:16px; height:16px; color:var(--ghost); pointer-events:none; }
.search-box input{ width:100%; height:40px; padding:0 26px 0 0; border:none;
  border-bottom:1px solid var(--line); border-radius:0; background:transparent;
  font-family:inherit; font-size:18px; font-weight:300; letter-spacing:-.012em;
  color:var(--ink); transition:border-color .2s; }
.search-box input::placeholder{ color:var(--ghost); font-weight:300; }
.search-box input:focus{ outline:none; border-bottom-color:var(--acc); box-shadow:none; }
.pager{ display:flex; align-items:center; justify-content:center; gap:14px; margin-top:14px; }
.pg-btn{ border:1px solid var(--line); background:none; color:var(--ink);
  border-radius:var(--r-pill); padding:8px 14px; font:inherit; font-weight:400; cursor:pointer;
  transition:border-color .2s, background-color .2s; }
.pg-btn:hover:not(:disabled){ border-color:var(--acc); background:var(--a05, rgba(0,0,0,.03)); }
.pg-btn:disabled{ color:var(--faint); cursor:default; opacity:.5; }
.pg-info{ font-size:14px; color:var(--soft); }
.pg-info b{ color:var(--ink); }

/* ═══════════════ 슬러그(공개 주소) 편집 ═══════════════ */
.slug-edit{ margin-top:16px; padding-top:16px; border-top:1px dashed var(--line); }
.slug-lab{ font-size:13px; font-weight:450; color:var(--ink); margin-bottom:9px; }
.slug-lab .hint{ font-weight:400; color:var(--faint); font-size:12px; }
/* 청첩장 주소 — 다른 입력과 같은 어휘다(밑줄 하나). 앞의 `/invite/` 는 조용한 접두어. */
.slug-input{ display:flex; align-items:center; border:none;
  border-bottom:1px solid var(--line); border-radius:0; overflow:hidden;
  background:transparent; transition:border-color .2s; }
.slug-input:focus-within{ border-bottom-color:var(--acc); box-shadow:none; }
.slug-prefix{ display:flex; align-items:center; padding:0 8px 0 0; background:transparent; font-weight:300; border-right:none; white-space:nowrap; }
.slug-field{ flex:1; border:none; outline:none; background:transparent; padding:0;
  height:40px; font-family:inherit; font-size:18px; font-weight:300; letter-spacing:-.012em;
  color:var(--ink); min-width:0; }
.slug-msg{ font-size:12.5px; min-height:1em; }
.slug-msg.ok{ color:var(--ok); }
.slug-msg.err{ color:var(--danger); }
.slug-msg.neutral{ color:var(--faint); }

/* ═══════════════ 예식 일시 선택기(캘린더) ═══════════════ */

/* ═══ 예식 일시 선택기 ═══
   ⚠ 강조는 --cobalt 계열이다 — iOS 블루(--acc)를 그대로 쓰면 선택한 날짜만 형광으로 튄다.
   ⚠ 날짜 칸에 aspect-ratio:1 을 주지 말 것 — 컬럼이 넓어질수록 칸이 커져 캘린더가 세로로 길어진다. */
/* ⚠ 흰 카드(radius 16px + 그림자 + 틴트 그라데이션 머리)로 되돌리지 말 것 — 밑줄 입력들
   사이에서 혼자 옛 3a 화면으로 보였다. 선 하나, radius 0, 면 없음이 이 지면의 어휘다. */
.dtpick{ box-shadow:none; }

/* 년·월 고르는 줄 — 캘린더보다 존재감이 크지 않게 낮춘다 */
/* ⚠ 달력 안의 손잡이는 편집기의 다른 버튼과 같은 **알약**이다(2026-09-19 고객 지시).
   예전에는 전부 `radius:0` 이었는데, 한 화면에서 저장·발행 버튼만 둥글어 짝이 맞지 않았다.
   한 줄에 나란히 서는 것끼리 함께 맞춘다 — 화살표만 둥글리면 가운데 연·월 칸이 각져
   그 줄이 오히려 더 어수선해진다. */


/* 정사각 대신 높이 고정 — 폭이 넓어져도 칸이 커지지 않는다 */
/* 고른 날짜 칸도 알약이다 — 화살표·세그먼트를 둥글린 뒤 이것만 각지면 달력에서 그 한 칸이
   유독 도드라진다(2026-09-19). 칸이 세로로 낮아 실제로는 둥근 알약처럼 보인다. */
/* 선택 — 파스텔 톤 안에서 도드라지되 형광은 아니게 */

/* 오전·오후 — 두 칸이 붙은 한 덩이라 **바깥만** 둥글린다. 안쪽 버튼에 각자 반경을 주면
   가운데 경계가 벌어져 알약 두 개가 겹친 것처럼 보인다(overflow 가 끝을 잘라 준다). */

/* ═══════════════ 드래그 정렬(앨범·섹션) ═══════════════ */
.drag-hint{ font-size:12.5px; }
/* 손가락으로 잡는 자리 — 여기서 시작한 터치만 '끌기'로 본다(assets/js/sortable.js).
   ⚠ 글자만으로는 과녁이 너무 작다. 여백으로 넓히되 글자 자리는 그대로 두려고 음수 위치를 준다.
   ⚠ touch-action:none 이 없으면 브라우저가 스크롤을 먼저 가져가 끌기가 시작되지 않는다. */
.drag-badge{ touch-action:none; }
.thumb .drag-badge{ position:absolute; top:-2px; left:-2px; z-index:2; padding:8px;
  color:#fff; font-size:13px;
  line-height:1; text-shadow:0 1px 3px rgba(0,0,0,.5); cursor:grab; opacity:.85; }
.gallery-grid.sortable .thumb{ cursor:grab; }
.gallery-grid.sortable .thumb.dragging{ opacity:.4; }
.thumb.dragging{ transform:scale(.97); }
.save-hint{ font-size:12.5px; margin-top:8px; min-height:1em; }
.save-hint.saving{ color:var(--faint); } .save-hint.done{ color:var(--ok); } .save-hint.err{ color:var(--danger); }
.sortlist{ display:flex; flex-direction:column; gap:8px; }
.sortrow{ display:flex; align-items:center; gap:10px; padding:13px 14px; border:1.5px solid var(--line);
  border-radius:12px; background:#fff; cursor:grab; transition:.12s; }
/* ⚠ display:flex 는 UA 의 [hidden]{display:none} 을 이긴다 — 이 규칙이 없어서 섹션을 꺼도
   순서 목록에서 사라지지 않았다. .order-swap 과 같은 함정이다. */
.sortrow[hidden]{ display:none; }
.sortrow:hover{ border-color:var(--cobalt); }
.sortrow.dragging{ opacity:.4; }
.sortrow .drag-badge{ color:var(--faint); font-size:16px; line-height:1;
  padding:8px 6px; margin:-8px -6px; }
.sortrow__label{ font-weight:450; color:var(--ink); font-size:14.5px; }
.sortrow__label small{ font-weight:400; color:var(--soft); font-size:12px; margin-left:15px; }

/* ═══════════════ 방명록 관리(운영자 모달) ═══════════════ */
.gb-admin{ margin-top:16px; padding-top:16px; border-top:1px dashed var(--line); }
.gb-admin > summary{ cursor:pointer; font-weight:450; color:var(--cobalt-deep); list-style:none; }
.gb-admin > summary::-webkit-details-marker{ display:none; }
.gb-admin > summary::before{ content:'▸'; margin-right:6px; font-size:11px; color:var(--faint); }
.gb-admin[open] > summary::before{ content:'▾'; }
.gb-admin > summary .hint{ font-weight:400; color:var(--faint); font-size:12px; margin-left:4px; }
.gb-admin-list{ margin-top:12px; display:flex; flex-direction:column; gap:8px; }
.gb-admin-empty{ font-size:13px; color:var(--faint); padding:8px 0; }
.gb-admin-item{ position:relative; padding:11px 13px; border:1px solid var(--line); border-radius:11px;
  background:#fff; transition:opacity .2s; }
.gb-admin-meta{ display:flex; align-items:baseline; gap:8px; margin-bottom:4px; }
.gb-admin-meta b{ font-size:13px; color:var(--ink); }
.gb-admin-meta span{ font-size:11px; color:var(--faint); }
.gb-admin-msg{ font-size:13px; color:var(--soft); line-height:1.6; white-space:pre-line; padding-right:52px; }
.gb-admin-del{ position:absolute; top:10px; right:10px; border:1px solid rgba(154,74,48,.22); background:#fff;
  color:var(--danger); border-radius:8px; padding:5px 10px; font:inherit; font-size:12px; font-weight:600; cursor:pointer; }
.gb-admin-del:hover{ background:rgba(154,74,48,.06); }
.gb-admin-del:disabled{ opacity:.5; cursor:default; }

/* ═══════════════ 표시설정: 미니라벨 / 선택 버튼 / 폰트 카드 ═══════════════ */
.mini-label{ font-size:13px; font-weight:450; color:var(--ink); margin-bottom:9px; }
.mini-label .hint{ font-weight:400; color:var(--faint); font-size:12px; margin-left:4px; }
/* 값을 보여 주고 고르는 모달을 여는 한 줄. **상자를 두르지 않는다** — 밑줄 한 줄이
   이 화면의 입력 어휘다(토큰 정본: 카드 없음 · 밑줄 입력 · radius 0). */
.picker-open{ width:100%; display:flex; align-items:center; justify-content:space-between;
  padding:12px 0; border:0; border-bottom:1px solid var(--line); border-radius:0; background:none;
  font:inherit; cursor:pointer; margin-bottom:12px; transition:.15s; }
.picker-open:hover{ border-bottom-color:var(--cobalt); }
.picker-open__val{ font-weight:450; color:var(--ink); font-size:14.5px; }
.picker-open__act{ color:var(--cobalt-deep); font-size:13px; font-weight:600; }

/* 앨범 유형 모달 내 선택 카드 */
.gt-pick{ border:none; background:none; padding:0; cursor:pointer; }
.gt-pick.sel .gt-card{ border-color:var(--cobalt); background:var(--cobalt-soft); }
.gt-pick.sel .gt-name{ color:var(--cobalt-deep); }

/* 한글 폰트 선택 카드 */
.kfont-row{ display:grid; grid-template-columns:repeat(2,1fr); gap:9px; }
.kfont{ cursor:pointer; position:relative; }
.kfont input{ position:absolute; width:0; height:0; opacity:0; margin:0; }
.kf-card{ display:block; border:1px solid var(--line); border-radius:12px; padding:14px 3px 10px;
  text-align:center; background:#fff; transition:.15s; }
.kfont input:checked + .kf-card{ border-color:var(--cobalt); background:var(--cobalt-soft); }
/* ⚠ 폰트 이름이 아니라 **글꼴 자체**를 보여 주는 칸이라 줄바꿈하지 않는다. 대신 390px 에서
   세 칸을 나누면 한 칸이 113px 뿐이라, 글자 크기를 칸에 맞춰 둔다 — 17px 로 두면
   "민준 · 서연"이 카드 밖으로 비어져 나온다. */
.kf-sample{ display:block; font-size:15.5px; color:var(--ink); line-height:1.2; margin-bottom:8px; min-height:22px;
  white-space:nowrap; }
.kfs-batang{ font-family:'Gowun Batang', serif; }
.kfs-sans{ font-family:'Pretendard', sans-serif; }
.kfs-buri{ font-family:'ChosunGu', sans-serif; }
.kfs-plex{ font-family:'IBM Plex Sans KR', sans-serif; }

/* 색 조합 — 칩 하나가 두 색을 보인다: 가운데 점이 강조색, 둘레 링이 패널색.
   청첩장 표지의 고르개(`.pal i`)와 같은 꼴이라 고객이 같은 것으로 읽는다.
   ⚠ display 를 주는 요소라 [hidden] 짝 규칙을 함께 둔다. */
.cs-set{ display:flex; flex-wrap:wrap; gap:15px; padding:4px 3px 3px; }
.cs-set[hidden]{ display:none; }
.cs{ cursor:pointer; position:relative; line-height:0; }
.cs input{ position:absolute; width:0; height:0; opacity:0; margin:0; }
.cs-chip{ display:block; width:13px; height:13px; border-radius:50%; background:var(--d);
  box-shadow:0 0 0 3px var(--p), 0 0 0 4px rgba(0,0,0,.10); transition:box-shadow .15s; }
.cs input:checked + .cs-chip{ box-shadow:0 0 0 3px var(--p), 0 0 0 4.5px var(--cobalt); }
.cs input:focus-visible + .cs-chip{ outline:1px solid var(--cobalt); outline-offset:5px; }
/* 표지 문구 — 고를 수 있는 템플릿에서만 뜬다. .choice 가 flex 라 [hidden] 짝 규칙을 함께 둔다. */
.ct-set[hidden]{ display:none; }

/* 안내 사항 — 화환·식사·주차 세 덩어리를 한 섹션 안에 쌓는다(청첩장에서도 카드 한 덩어리다).
   ⚠ 토글이 셋이라 각 덩어리에 제목 줄을 둔다 — 없으면 어느 스위치가 무엇인지 알 수 없다. */
.info-part + .info-part{ margin-top:22px; padding-top:20px; border-top:1px solid var(--line); }
/* 표시 방식 고르개 바로 다음의 **첫** 덩어리 — 덩어리끼리는 위 규칙이 띄우지만 첫 장은 그냥 붙는다. */
.choice--gal + .info-part{ margin-top:22px; }
.info-part__hd{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:9px; }
.info-part__t{ font-size:13.5px; font-weight:450; color:var(--ink); letter-spacing:-.01em; }
.info-part__hd .wiz-use{ flex:none; margin:0; }
.kf-name{ display:block; font-size:11.5px; font-weight:450; color:var(--soft); }
.kfont input:checked + .kf-card .kf-name{ color:var(--cobalt-deep); }

/* 예식 종료 잠금 배너 */
.lock-banner{ display:flex; gap:12px; align-items:flex-start; padding:15px 17px; margin:0 4px 18px; }
.lock-banner b{ display:block; color:var(--danger); font-size:14px; margin-bottom:3px; }
.lock-banner span{ font-size:12.5px; color:var(--soft); line-height:1.6; }

/* ═══════════════ 전체 저장 고정 바 ═══════════════ */
.savebar{ position:fixed; left:0; right:0; bottom:0; z-index:30; }
.savebar__inner{ max-width:760px; margin:0 auto; display:flex; align-items:center; justify-content:space-between; gap:14px; }
.savebar__hint{ font-size:12.5px; color:var(--soft); line-height:1.4; }
.savebar #saveAllBtn{ flex:none; }
body:has(.savebar){ padding-bottom:82px; }
/* 전체 저장 진행바 (사진 업로드 중 렉처럼 보이지 않도록) */
.savebar__progress{ position:absolute; left:0; right:0; top:0;
  opacity:0; transition:opacity .2s ease; pointer-events:none; }
.savebar__progress.on{ opacity:1; }
.savebar__bar{ display:block; height:100%; width:0;
  transition:width .28s cubic-bezier(.4,.1,.2,1); }
@media (max-width:520px){ .savebar__hint{ display:none; } .savebar #saveAllBtn{ width:100%; } .savebar__inner{ display:block; } }

/* ═══════════════ 임시 보관함 ═══════════════
   근거: design_handoff_invitation_editor/InvitationEditor.dc.html §임시 보관함.
   ⚠ [전체 저장]과 헷갈리지 않게 **아이콘 하나 + 선 두른 버튼**으로 무게를 낮춘다 —
     채운 버튼은 이 지면에 저장 하나뿐이다. */
.savebar__box{ position:relative; flex:0 0 auto; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  border:none; background:none; cursor:pointer;
  font-size:16px; line-height:1;
  transition:background-color .18s, opacity .16s; }
/* 담아 둔 것이 있을 때만 켜지는 점 — 보관함을 열어 보지 않아도 알 수 있게.
   ⚠ display 를 주는 요소라 [hidden] 짝 규칙을 함께 둔다. */
.savebar__dot[hidden]{ display:none; }
.savebar__dot{ display:block; position:absolute; width:7px; height:7px;
  border-radius:50%; background:var(--acc); box-shadow:0 0 0 2px #fff; }
.draft-empty{ padding:34px 20px; text-align:center; font-size:13.5px; line-height:1.7;
  color:var(--soft); word-break:keep-all;
  box-shadow:inset 0 0 0 1px var(--line); }
.draft-empty b{ color:var(--acc); font-weight:450; }
.draft-row[hidden]{ display:none; }
.draft-row{ display:flex; align-items:center; gap:14px; padding:4px 0; }
/* 저장본 표식 — 사진을 담지 않으므로 썸네일 대신 종이 한 장을 세운다 */
/* 보관함 한 줄의 얼굴 — 그 청첩장이 쓰는 템플릿 썸네일. 세로 지면이라 1:1.35 로 자른다.
   ⚠ 빈 색면이던 자리다. 아무것도 안 들어가 "이 네모는 뭔가" 싶게 비어 있었다. */
.draft-row__th{ flex:0 0 46px; width:46px; height:62px; object-fit:cover; display:block;
  background:var(--cobalt-soft); box-shadow:inset 0 0 0 1px var(--line); }
.draft-row__body{ flex:1; min-width:0; }
.draft-row__t{ display:block; font-size:15px; font-weight:450; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.draft-row__m{ display:block; margin-top:4px; font-size:12.5px; color:var(--soft);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.draft-row__at{ display:block; margin-top:5px; font-size:11.5px; font-weight:450;
  letter-spacing:.02em; color:var(--faint); }
.draft-row__acts{ flex:0 0 auto; display:flex; flex-direction:column; gap:6px; align-items:stretch; }
.draft-row__acts .btn{ min-width:92px; }
/* 삭제 — 버튼 꼴을 두르지 않는다. 옆 둘과 무게가 같으면 잘못 누른다. */
.draft-rm{ border:none; background:none; padding:2px 0; cursor:pointer;
  font-family:inherit; font-size:12.5px; font-weight:450; color:var(--faint);
  transition:color .16s; }
.draft-rm:hover{ color:var(--danger); }
.draft-note{ margin:18px 0 0; font-size:12px; line-height:1.6; color:var(--faint);
  word-break:keep-all; }

@media (max-width:520px){
  .draft-row{ flex-wrap:wrap; }
  .draft-row__acts{ flex-direction:row; width:100%; }
  .draft-row__acts .btn{ flex:1 1 0; min-width:0; }
}

/* 비밀번호 변경 링크(하단 소형 버튼) */
.pw-link-row{ text-align:left; margin:4px 2px 0; }
.pw-link{ background:none; border:none; padding:0; cursor:pointer; font-family:inherit;
  font-size:13px; font-weight:600; color:var(--soft); text-decoration:underline; text-underline-offset:3px; }
.pw-link:hover{ color:var(--cobalt-deep); }

/* ── QR 코드 모달 ──
   지면과 같은 어휘로 그린다 — 면을 깔지 않고 헤어라인으로 나누며, 고른 것은 밑줄 2px 로 세운다.
   채운 면은 [QR 만들기]·[이미지 저장] 두 주 동작뿐이다.
   ⚠ 흰 카드·알약 칩·radius 12~14px 로 되돌리지 말 것 — 팝업만 옛 화면으로 튄다. */

/* QR 그림 자리 — 선도 면도 두르지 않는다. 그림 둘레에 선을 그으면 QR 자체의 흰 여백과 겹쳐
   테두리가 두 겹으로 읽힌다(2026-09-20 지적). 자리는 여백으로만 나눈다. */
.qr-box{ display:flex; flex-direction:column; align-items:center; gap:12px;
  background:none; border:none; border-radius:0;
  padding:26px 0 4px; margin-top:4px; }
/* 하트는 세로가 짧아 정사각과 크기가 다르다 — 높이를 맞춰 두면 모양을 바꿔도 모달이 덜컹이지 않는다. */
/* ⚠ 240px 고정이면 팝업(max-height:88vh) 안에서 옵션·안내까지 합쳐 넘쳐 세로 스크롤이 생겼다. 화면 높이에 맞춰 줄여 팝업이 한 화면에 들어오게 한다. */
.qr-box img{ width:auto; height:min(176px, 26vh); max-width:100%; display:block; image-rendering:pixelated; }
/* ⚠ display 를 준 요소는 UA 의 [hidden]{display:none} 을 이긴다 — 이 두 줄이 없으면
   로딩과 그림이 **동시에** 자리를 차지해 팝업이 그만큼 길어진다. */
.qr-box img[hidden]{ display:none; }
.qr-loading[hidden]{ display:none; }
/* 서버가 그리는 1초 동안 자리를 지킨다 — 빈 칸만 있으면 고장 난 줄 안다 */
.qr-loading{ height:min(176px, 26vh); display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:10px; font-size:12px; font-weight:300; color:var(--soft); }
.qr-loading i{ width:20px; height:20px; border-radius:50%; display:block;
  border:1px solid var(--line); border-top-color:var(--acc); animation:qrSpin .8s linear infinite; }
@keyframes qrSpin{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce){ .qr-loading i{ animation:none; } }
/* 곡선이 있는 하트에 픽셀 확대를 쓰면 가장자리가 계단진다. */
.qr-box img.is-heart{ image-rendering:auto; }
/* 구워진 주소 — 읽어 확인하는 값이라 고정폭으로, 조용히 */
.qr-url{ font-family:var(--mono); font-size:11.5px; letter-spacing:-.01em;
  color:var(--faint); word-break:break-all; text-align:center; }
.qr-tip{ margin-top:12px; font-size:11.5px; font-weight:300; color:var(--faint); text-align:center; }

/* ── QR 잠금 화면(만들기 전) ──
   ⚠ 진짜 QR 그림 요청이 곧 발급 기록이라, 만들기 전에는 부르면 안 된다 — 여기 보이는 것은 가짜 QR(장식 SVG)이다.
   ⚠ 높이를 .qr-box img 와 같은 값으로 맞춘다(만들기 전후로 팝업이 덜컹이지 않게). */
.qr-lock{ position:relative; width:min(176px, 26vh); height:min(176px, 26vh); }
.qr-lock[hidden]{ display:none; }
/* ⚠ 176px 안에 29칸이라 한 칸이 6px 남짓이다 — blur 4px 를 주면 격자가 통째로 뭉개져
     "빈 회색 판"으로 보였다. 흐리되 QR 인 것은 알아볼 만큼만 남긴다. */
.qr-lock__fake{ width:100%; height:100%; display:block;
  filter:blur(2.2px); opacity:.5; }
/* 버튼이 앉는 자리 — 옅은 막을 한 겹 더 깔아 가짜 QR 이 글자를 방해하지 않게 한다.
   ⚠ 막의 모서리는 각이다(지면 기본 radius 0). */
/* ⚠ 막도 지면색이다. 흰 막을 깔면 가짜 QR 둘레에 흰 사각이 도로 생긴다. */
.qr-lock__veil{ position:absolute; inset:0; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:10px;
  background:rgba(247,243,234,.72); border-radius:0; }
.qr-lock__veil .btn{ min-height:38px; padding:0 20px; }
.qr-lock__hint{ font-size:11px; font-weight:300; line-height:1.55; color:var(--soft);
  text-align:center; max-width:82%; }
@media (prefers-reduced-motion:reduce){ .qr-lock__fake{ filter:blur(1.6px); } }

/* 아직 만들기 전의 [이미지 저장] — 누를 것이 없다는 걸 보이게만 하고 클릭은 JS 가 막는다 */
.btn.is-off{ opacity:.42; pointer-events:none; }

/* ── QR 모양·색 고르기 ──
   고르는 줄은 선으로 나눈 행이다. 라벨은 값보다 한참 작고 조용하다(.field label 과 같은 눈높이). */
/* ⚠ 첫 줄 **위에는 선을 두지 않는다** — 바로 위 머리글에도 선이 있어 두 줄이 겹쳐 보였다. */
.qr-opt{ display:flex; align-items:center; gap:20px; margin:0;
  padding:14px 0; border-bottom:1px solid var(--line-soft); }
.qr-opt__label{ flex:none; width:30px; font-size:11.5px; font-weight:400;
  letter-spacing:-.004em; color:var(--soft); }
/* 모양 — 상자가 아니라 **글자를 늘어놓는다**(.choice 와 같은 어휘). 고른 것만 밑줄 2px 로 선다. */
.qr-shapes{ display:flex; gap:20px; }
.qr-shape{ display:inline-block; cursor:pointer;
  padding:0 0 5px; border:0; border-radius:0; background:none;
  font-family:inherit; font-size:15px; font-weight:400; color:var(--soft);
  box-shadow:none; transform:translateY(0);
  transition:color .26s, box-shadow .26s,
    transform .34s var(--e-spring, cubic-bezier(.34,1.56,.64,1)); }
.qr-shape:hover{ color:var(--ink); }
.qr-shape.is-on{ color:var(--acc-ink); box-shadow:inset 0 -2px 0 -0.5px var(--acc); transform:translateY(-2px); }


/* 색 — 색 자체가 견본이다. 모서리는 각(지면 기본)이고, 고른 표시는 바깥 링으로 준다. */
.qr-colors{ display:flex; flex-wrap:wrap; gap:12px; align-items:center; }
/* 고른 색의 HEX — 견본을 없앤 뒤 "지금 무슨 색인지"를 알려 주는 유일한 단서다 */
.qr-colors__hint{ font-family:var(--mono); font-size:11.5px; color:var(--ink); letter-spacing:.02em; }
/* 무지개 링을 걷어낸 자리 — 눌러서 색상판이 열린다는 것을 글자로 알린다 */
.qr-colors__act{ font-size:11.5px; font-weight:300; color:var(--faint);
  text-decoration:underline; text-underline-offset:3px; cursor:pointer; }
.qr-sw{ position:relative; width:26px; height:26px; padding:0; cursor:pointer;
  border:1px solid var(--line); border-radius:0; background:var(--sw,#000); }
.qr-sw.is-on{ box-shadow:0 0 0 2px var(--bg), 0 0 0 3px var(--acc); }
/* 직접 고르기 — 색상판을 여는 input 은 견본 뒤에 숨기고 겉면만 보인다. */
.qr-sw--pick{ display:inline-block; overflow:hidden; background:none; }
.qr-sw--pick::after{ content:''; position:absolute; inset:0; border-radius:0;
  background:var(--sw,#2E2A24); }
.qr-sw--pick input{ position:absolute; inset:0; width:100%; height:100%;
  opacity:0; border:none; padding:0; cursor:pointer; }
/* 안내 — 면을 깔지 않고 왼쪽 선 하나로 세운다(.info-note 와 같은 어휘) */
.qr-note{ margin-top:16px; font-size:12px; font-weight:300; line-height:1.7; color:var(--soft);
  background:none; border:none; border-left:2px solid var(--acc-line);
  border-radius:0; padding:2px 0 2px 14px; }
.qr-note b{ font-weight:450; color:var(--ink); }
/* 실제로 밝은 색을 골랐을 때만 뜨는 경고 — 상시 안내와 선 색으로 구분한다 */
.qr-note--warn{ background:none; border-left-color:var(--danger); }
.qr-note--warn b{ color:var(--danger); }
/* 주소를 직접 정할 수 없는 요금제 안내 — 오류가 아니라 알림이라 붉은색을 쓰지 않는다 */
.slug-msg.locked{ color:var(--soft); }

/* 전체 저장 로딩 오버레이 — 전체화면 원형 진행 */
/* ── 공통 진행 막대 ── 숫자를 보여 주지 않는다(읽는 사이에 넘어가 정보가 되지 않고 "97%에서 멈췄다"를 만든다).
   · 진행을 아는 경우(업로드) : .lilt-bar__fill 의 width 를 JS 가 넣는다
   · 모르는 경우(로그인 대기) : .lilt-bar.is-indeterminate — 막대가 좌우로 오간다 */
.lilt-bar{ width:100%;
  overflow:hidden; position:relative; }
.lilt-bar__fill{ display:block; height:100%; width:0; transition:width .18s ease; }
/* 얼마나 걸릴지 모르는 기다림. 끝을 아는 척하지 않고 움직임만 보여 준다. */
.lilt-bar.is-indeterminate .lilt-bar__fill{ transition:none; }
@keyframes lilt-bar-slide{
  0%   { transform:translateX(-105%); }
  100% { transform:translateX(255%); }
}
/* 움직임을 싫어하는 사용자에게는 흐려졌다 진해지는 것으로 대신한다(자리는 그대로) */
@media (prefers-reduced-motion: reduce){
  .lilt-bar.is-indeterminate .lilt-bar__fill{ width:100%; animation:lilt-bar-pulse 1.4s ease-in-out infinite; }
  @keyframes lilt-bar-pulse{ 0%,100%{ opacity:.35; } 50%{ opacity:1; } }
}

/* 전체화면 대기 — 로그인처럼 "누르고 나면 할 일이 없는" 기다림에 쓴다.
   ⚠ 화면을 덮으므로 되돌릴 수 없는 조작 뒤에만 띄운다. */
/* ⚠ 배경은 모달과 같은 값이다(.modal__backdrop) — 흰 막으로 덮으면 무엇을 하다 말았는지조차 안 보인다.
   ⚠ 배경이 어두우므로 막대와 글자는 밝은 쪽으로 뒤집는다. */
.lilt-wait{ position:fixed; inset:0; z-index:300; display:none;
  flex-direction:column; align-items:center; justify-content:center; gap:14px;
  background:rgba(0,0,0,.46); }
.lilt-wait.on{ display:flex; }
.lilt-wait__label{ font-size:13px; font-weight:400; letter-spacing:-.01em; color:#fff;
  text-shadow:none; }

/* 저장 대기도 위 .lilt-wait 와 같은 배경을 쓴다 — 두 기다림이 서로 다르게 보일 이유가 없다 */
.save-overlay{ position:fixed; inset:0; z-index:200; display:none; flex-direction:column; align-items:center; justify-content:center; gap:16px;
  background:rgba(0,0,0,.46); }
.save-overlay.on{ display:flex; }
/* 막대 모양은 위 .lilt-wait 와 함께 한 규칙으로 잡는다(두 기다림이 같아 보여야 한다) */
/* ⚠ 원형 링 + 퍼센티지는에 걷어냈다 — 되살리지 말 것.
   저장은 막대 하나로 충분하고, 숫자는 오히려 없는 문제를 만든다(위 .lilt-bar 주석 참고). */
.save-overlay .lilt-bar{ width:min(260px, 66vw); }
.save-overlay__label{ font-size:14px; font-weight:600; color:#fff;
  text-shadow:0 1px 3px rgba(0,0,0,.35); }

/* 템플릿 샘플 보기 링크 */
/* 라벨과 [샘플 보기] 를 한 줄에 놓는다.
   ⚠ float 로 되돌리지 말 것 — 링크가 라인박스에서 빠져 세로 정렬이 어긋나고, 아래 상자의 폭까지 줄어든다. */
/* ⚠ .field label{display:block} 이 먼저 있고 명시도가 더 높다(클래스+타입).
   그래서 label 을 함께 적어 이긴다 — .tpl-label 만 쓰면 조용히 무시된다. */
label.tpl-label,
.field label.tpl-label{ display:flex; align-items:center; justify-content:space-between;
  gap:10px; flex-wrap:wrap; }
.tpl-preview{ flex:none; font-size:12px; font-weight:600; color:var(--cobalt-deep); text-decoration:none;
  padding:5px 9px; border:1px solid var(--line); border-radius:8px; white-space:nowrap;
  transition:border-color .14s, background .14s; }
.tpl-preview:hover{ border-color:var(--cobalt); background:var(--cobalt-soft); }
.tpl-preview:focus-visible{ outline:2px solid var(--cobalt-deep); outline-offset:2px; }

/* 앨범·약도 삭제 버튼(폼 없이 단독) — 삭제 예정 표시용 */
.thumb-x.gal-del, .thumb-x.map-del{ position:absolute; top:5px; right:5px; z-index:3; cursor:pointer; }

/* 고른 사진을 올리기 전에 하나씩 빼는 ✕. 선택이 누적되므로 빼는 수단이 함께 있어야 한다. */
/* ⚠ 칸 **안쪽**에 둔다. 예전에는 -4px 로 칸 밖에 걸쳐 있었는데, 사진 칸이 한 그리드로
   이어지면서 옆 칸 사진 위에 올라탔다. 저장된 사진의 .thumb-x(5px)와 같은 자리다. */
.pv-wrap .pv-x{ position:absolute; top:5px; right:5px; z-index:3; width:20px; height:20px; padding:0;
  border:none; border-radius:50%; background:rgba(20,28,45,.6); color:#fff;
  font-size:10px; line-height:1; cursor:pointer; display:flex; align-items:center; justify-content:center; }
.pv-wrap .pv-x:hover{ background:rgba(192,69,69,.92); }

/* 소멸 안내 / 정보 배너(고객 대시보드) */
.info-note{ display:flex; gap:12px; align-items:flex-start; margin:0 4px 18px; }
.info-note__ico{ font-size:17px; line-height:1.4; }
.info-note div{ line-height:1.6; }

/* 모노 표면 — 고객 대시보드·고객 홈·운영자 콘솔이 공유하는 토큰/표면.
   색·활자·모션의 정본은 **lilt-tokens.css**(design_handoff_lilt)다.
   ⚠ 이 블록은 위 :root 뒤에 와서 같은 이름을 덮는다 — 두 곳을 늘 같이 본다.
   ⚠ 폐기된 톤: iOS 블루 #007aff · 회청색 지면 #eef1f5 · 아이보리 + 코발트 · 유리(글래스).
     되살리지 말 것. 지금은 흰 패널 + 헤어라인 + 잉크 한 색이다.
   ⚠ --gl-* 이름은 남긴다(편집기 카드·입력·저장바가 전부 부르고 있다). 값만 불투명 흰색이다. */
:root{
  /* 지면 — 따뜻한 회색 한 색. */
  --g-bg:#f4f3f1;
  /* 텍스트 4단계 */
  --ink:#1a1a1a;
  --soft:#9a9a9a;
  --faint:#c0c0c0;
  --ghost:rgba(0,0,0,.28);
  /* 악센트 — 잉크 한 색. 색으로 강조하지 않고 굵기·자리로 강조한다. */
  --acc:#1a1a1a; --acc-ink:#1a1a1a;
  --acc-bg:rgba(0,0,0,.05);
  --acc-line:rgba(0,0,0,.2);
  --acc-glow:none;
  /* 패널 표면 — 흰 면 + 1px 헤어라인. 그림자도 블러도 없다. */
  --gl-head:#ffffff;
  --gl-card:#ffffff;
  --gl-note:#ffffff;
  --gl-field:#ffffff;
  --gl-solid:#ffffff;
  --gl-line:rgba(0,0,0,.05);
  --gl-blur:none;
  /* 구분선 — 헤어라인 2단 */
  --line:rgba(0,0,0,.08);
  --line-soft:rgba(0,0,0,.055);
  /* 반경 — **전부 0 이다.** 둥근 것은 미리보기 폰 목업뿐(그건 기기 모양이라 남는다).
     ⚠ 카드를 둥글게 말던 옛 값(12~26px)을 되살리지 말 것. */
  --r-pill:999px; --r-preview:22px; --r-head:0; --r-card:0;
  --r-share:0; --r-act:0; --r-field:0;
  --radius:0;
  /* 그림자 — 없다. 면을 나누는 것은 헤어라인이 전부 맡는다. */
  --sh-head:none;
  --sh-card:none;
  --sh-preview:0 18px 40px -12px rgba(0,0,0,.28);
  --shadow:none;
  /* 타이포 — 프리텐다드 우선. 세리프는 쓰지 않는다(한글도 영문도). */
  --sans:'Pretendard',-apple-system,'Apple SD Gothic Neo',system-ui,sans-serif;
  --mono:ui-monospace,Menlo,'SF Mono',monospace;
  /* 전환 */
  --ease-ios:cubic-bezier(.32,.72,0,1);
}

html{ min-height:100%; }
body{
  min-height:100vh; background:var(--g-bg); color:var(--ink);
  font-family:var(--sans); letter-spacing:-.01em; -webkit-font-smoothing:antialiased;
}

/* ── 공통 표면: 기존 컴포넌트를 흰 패널로 매핑 ── */
/* ⚠ 상단바의 자리·패딩은 위 .topbar__in / .tabs 가 쥔다 — 여기서는 재질만 준다.
   패딩을 여기에 다시 넣으면 탭 줄이 로고와 겹친다.
   ⚠ 순백이 아니라 **비치는 흰 띠**다(2026-09-22) — 붙박이(sticky)라 밑으로 지나가는
     지면이 비쳐야 띠가 지면 위에 떠 있는 것으로 읽힌다.
     ⚠ **세 화면이 같은 값을 쓴다** — 첫 화면(bridge.css 의 .hd)·대시보드·운영자 콘솔.
       한쪽만 고치지 말 것.
     이것은 유리 "카드"를 되살린 것이 아니다 — 카드·저장바는 그대로 불투명하고,
     비치는 것은 이 띠 하나뿐이다. radius·그림자·흰 테두리는 여전히 없다.
   ⚠ backdrop-filter 를 못 읽는 브라우저에서는 반투명만 남아 글자가 그대로 비친다 —
     그래서 @supports 로 불투명한 흰 띠를 되돌려 준다. */
.topbar{
  background:#ffffff8c;
  -webkit-backdrop-filter:saturate(180%) blur(12px);
          backdrop-filter:saturate(180%) blur(12px);
  border-bottom:1px solid rgba(0,0,0,.07);
  padding:0;
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .topbar{ background:var(--card); }
}
.pagehead h1{ color:var(--ink); font-weight:400; letter-spacing:-.018em; }
.pagehead p{ color:var(--faint); letter-spacing:-.01em; }

/* ── 카드를 두르지 않는다 ────────────────────────────────────────────────────
   근거: design_handoff_lilt — "카드/그림자 없음. 1px 헤어라인 UI".
   면과 그림자로 묶던 것을 **위쪽 헤어라인 한 줄**로 대신한다.

   ⚠ **유리 카드로 되돌리지 말 것.** 옛 3a 는 반투명 흰 면 + 0.5px 흰 테두리 + radius 18px +
     그림자였고, 색만 갈았을 때 "아이보리색 3a 화면"이 되었다(2026-09-18 지적).
   ⚠ 클래스 이름(.card)은 그대로 둔다 — 2천 줄과 네 화면의 마크업이 그 이름을 부르고 있다.
     여기서 바꾸는 것은 "그 이름이 무엇으로 보이는가" 뿐이다.
   ⚠ 제목은 작은 대문자 영문 라벨이 아니라 한글 제목이다 — 얇게(400) 쓰고 크기로만 세운다. */
.card{
  background:none; border:none; border-top:1px solid var(--line);
  border-radius:0; box-shadow:none;
  -webkit-backdrop-filter:none; backdrop-filter:none;
  padding:26px 0 30px; margin-bottom:0;
}
/* 첫 카드는 위 선을 지운다 — 머리말과 붙어 두 줄로 보인다 */
.card:first-of-type{ border-top:none; padding-top:6px; }
.card > h2{ font-weight:400; font-size:19px; letter-spacing:-.018em; color:var(--ink);
  margin:0 0 6px; }
.card > .desc{ color:var(--soft); font-size:12.5px; font-weight:300; line-height:1.7;
  letter-spacing:-.01em; margin:0 0 20px; }

/* 저장 바 — 흰 띠 + 위 헤어라인. 유리는 쓰지 않는다. */
.savebar{
  background:var(--card);
  border-top:1px solid var(--line-soft); box-shadow:none;
}

/* ── 입력 요소 — **밑줄 하나.** ─────────────────────────────────────────────
   근거: 바탕화면 design_handoff_lilt — Screen 2.
     라벨 11.5px/400 · 값은 **18px/300**(textarea 17px) · 테두리는 아래 1px 뿐
     · 배경 없음 · 포커스 때만 밑줄이 코발트로.

   ⚠ **테두리 박스로 되돌리지 말 것.** 옛 3a 글래스는 사방 테두리 + radius 14px + 유리 배경이었고,
     색만 갈았을 때 "아이보리색 3a 화면"이 되었다(2026-09-18 지적). 값을 크게 쓰고 선을 하나만
     두는 것이 이 지면의 어휘다.
   ⚠ 글자 크기를 16px 아래로 내리지 말 것 — iOS Safari 가 포커스 때 화면을 확대한다.
   ⚠ select 는 밑줄만 두면 화살표가 지면에 붙어 보인다. 오른쪽에 자리를 비워 둔다. */
.field input, .field select, .field textarea, .parent-group input,
.search-box input, .slug-input, .dtpick, .picker-open, .inline-form select,
.transit-add__row select{
  background:transparent; border:none;
  border-bottom:1px solid var(--line); border-radius:0;
  padding:0; color:var(--ink);
  font-size:18px; font-weight:300; letter-spacing:-.012em;
  -webkit-backdrop-filter:none; backdrop-filter:none;
  transition:border-color .2s;
}
.field input, .parent-group input, .search-box input, .inline-form select,
.transit-add__row select, .field select{
  height:40px;
}
.field select, .inline-form select, .transit-add__row select{
  padding-right:18px;          /* 화살표 자리 */
}
.field textarea{
  font-size:17px; line-height:1.75; letter-spacing:-.014em;
  padding:0 0 10px; resize:none; min-height:0;
}
.field input::placeholder, .field textarea::placeholder, .parent-group input::placeholder{
  color:var(--ghost); font-weight:300;
}
.field input:focus, .field select:focus, .field textarea:focus, .parent-group input:focus,
.search-box input:focus, .slug-input:focus-within{
  outline:none; border-bottom-color:var(--acc);
  box-shadow:none; background:transparent;
}
/* 라벨 — 값보다 한참 작고 조용하다(값이 주인공이다) */
.field label, .wiz-f__label{
  display:block; font-size:11.5px; font-weight:400; letter-spacing:-.004em;
  color:var(--soft); margin-bottom:8px;
}
/* 저장이 거절된 칸(서버가 칸 이름을 알려 준 경우 — customer.jsp focusSaveField).
   다시 입력을 시작하면 스크립트가 떼어 낸다. */
input.field-err, textarea.field-err{
  border-bottom-color:var(--danger) !important; box-shadow:none !important;
}

/* 버튼 */
.btn{ border-radius:var(--r-pill); font-weight:500; letter-spacing:-.01em; }
/* 주 버튼 — **채운 코발트 알약** 하나. 이 화면에서 채도가 있는 면은 주 동작뿐이고,
   나머지(.btn-ghost)는 선만 두른다 — 채움 여부가 둘을 가르는 유일한 단서다.
   ⚠ 옛 파우더 글래스 버튼(투명 틴트 + 스펙큘러 림 + 상단 하이라이트)은 폐기됐다.
     주 동작이 유리라 지면에 묻혀 "저장한 것 같지 않다"가 되었다. 되살리지 말 것. */
/* ⚠ 그림자를 얹지 않는다. 이 지면에서 그림자는 팝업과 미리보기 패널에만 쓴다 —
   버튼이 떠 보이면 헤어라인 지면에서 그것만 다른 층에 있는 부품처럼 읽힌다. */
.btn-primary{
  background:var(--acc); color:#fff; font-weight:400; border:none; box-shadow:none;
  transition:opacity .16s, transform 90ms, background-color .2s;
}
.btn-primary:hover{ background:var(--acc); opacity:.88; box-shadow:none; }
.btn-primary:active{ background:var(--acc-ink); transform:scale(.99); }
.btn-primary[disabled]{
  background:var(--acc-bg); color:var(--ghost); box-shadow:none; cursor:default; opacity:1;
}
/* 보조 버튼 — **선만 두른다.** 채운 면은 주 동작 하나뿐이라, 채움 여부가 둘을 가르는 단서다. */
.btn-ghost, .btn-danger{
  background:none; border:1px solid var(--line); color:var(--ink);
  -webkit-backdrop-filter:none; backdrop-filter:none;
  transition:border-color .2s, background-color .2s;
}
.btn-ghost:hover{ border-color:var(--acc); background:var(--a05, rgba(0,0,0,.03)); }
.btn-danger{ color:var(--danger); }
.btn-danger:hover{ border-color:var(--danger); background:rgba(154,74,48,.06); }

/* 리스트 · 정렬 · 접기 · 방명록 표면 */
/* ── 목록의 한 줄 — 상자가 아니라 **선으로 나뉜 행** ──────────────────────────
   근거: design_handoff_lilt — 섹션 행 · 연락처 행 · 계좌 행이 모두 아래 1px 선이다.
   ⚠ 유리 상자로 되돌리지 말 것(radius 14px + 흰 반투명 면). 행이 상자가 되면 목록이
     "카드 여러 장"으로 읽혀 지면이 어수선해진다. */
.item, .transit-row, .gb-admin-item, .sortrow{
  background:none; border:none; border-bottom:1px solid var(--line-soft);
  border-radius:0;
}
.item.clickable:hover{ background:var(--a05, rgba(0,0,0,.03)); border-color:var(--line); }
.sortrow:hover{ background:var(--a05, rgba(0,0,0,.03)); }
/* 접었다 펴는 블록 — 면을 두르지 않고 위아래 선으로만 묶는다 */
.foldable, .fold-details{
  background:none; border:none; border-top:1px solid var(--line-soft); border-radius:0;
}
/* 고르는 칸(옵션·갤러리 유형·글꼴) — **선만.** radius 0 이 이 지면의 기본이다. */
/* ── 고르는 칸(choice) — **글자를 늘어놓는다.** ─────────────────────────────
   근거: InvitationEditor.dc.html — `flex-wrap; gap:18px`, 옵션은 `padding:0 0 5px` 인
   맨 글자(16px)이고, 고른 것만 **밑줄 2px + translateY(-2px)** 로 선다.
   ⚠ 테두리 상자(radius 12px + 틴트 면)로 되돌리지 말 것 — 밑줄 입력만 있는 지면에서
     선택지만 상자가 되면 그 줄이 옛 화면으로 튄다. */
.choice{ display:flex; flex-wrap:wrap; gap:18px; }
.choice label{ flex:0 0 auto; margin:0; cursor:pointer; position:relative; }
.opt-block .choice .opt, .choice .opt{
  display:block; padding:0 0 5px; border:0; border-radius:0; background:none;
  text-align:left; font-size:16px; font-weight:400; color:var(--soft);
  box-shadow:none; transform:translateY(0);
  transition:color .26s, box-shadow .26s,
    transform calc(.34s) var(--e-spring, cubic-bezier(.34,1.56,.64,1));
}
.choice .opt small{ display:block; margin-top:3px; font-size:12px; font-weight:400; color:var(--faint); }
.choice input:checked + .opt{
  background:none; border:0; color:var(--acc-ink);
  /* ⚠ spread 가 **음수**다(-0.5px). 칸 폭은 글자에 따라 소수(47.55px 등)로 잡히는데,
     밑줄을 폭에 딱 맞춰 그리면 고배율 화면(아이폰 Pro Max · dpr 3)에서 자투리 0.65px 이
     좌우 끝에 **세로 선처럼** 남는다(2026-09-21 지적). 그림자를 반 픽셀 안으로 당겨 없앤다.
     ⚠ 같은 이유로 이 파일의 다른 밑줄(qr-shape · dtp__seg · choice--preset)도 함께 당겼다. */
  box-shadow:inset 0 -2px 0 -0.5px var(--acc); transform:translateY(-2px);
}
.choice input:focus-visible + .opt{ outline:2px solid var(--acc); outline-offset:3px; }

/* ── 견본 칸(swatch) — 갤러리 유형·글꼴처럼 **그림으로 고르는** 것.
   시안의 테마 스와치와 같은 어휘다: 면 하나 + 아래 이름, 고른 것만 링 + 4px 들림. */
/* ⚠ .picker-open 은 여기 묶지 않는다. 그림으로 고르는 견본 칸이 아니라 **값을 보여 주고
   모달을 여는 한 줄**이라, 위에서 정한 밑줄 입력 어휘를 따른다. 여기 넣으면 사방 테두리가
   덮어써서 네모 상자가 된다. */
.gt-card, .kf-card{
  background:none; border:0; border-radius:0;
  box-shadow:inset 0 0 0 1px var(--line);
  transform:translateY(0);
  transition:box-shadow .26s, transform .4s var(--e-spring, cubic-bezier(.34,1.56,.64,1)), color .2s;
}
.gtype input:checked + .gt-card, .kfont input:checked + .kf-card, .gt-pick.sel .gt-card{
  background:none; color:var(--acc-ink);
  box-shadow:0 0 0 2px var(--acc); transform:translateY(-4px);
}

/* 배지 · 필 */
/* 작은 표식 — 알약은 그대로 두되(핸드오프의 칩과 같은 어휘) 흰 테두리를 걷는다. */
.card > h2 .badge, .stage-tag, .transit-row__type{
  background:none; color:var(--faint);
  border:1px solid var(--line); font-weight:400;
}

/* ── 배너 · 플래시 — 면은 얇은 틴트 하나, 왼쪽 2px 선으로만 세운다 ──
   ⚠ 유리 카드로 되돌리지 말 것. 안내가 카드가 되면 본문 카드와 무게가 같아져
     "읽고 넘어갈 것"인지 "해야 할 일"인지 가려지지 않는다. */
/* 소멸 안내 — 매번 보는 글이라 **면을 깔지 않는다.** 왼쪽 선 한 줄이면 충분하고,
   면을 깔면 그것만으로 지면의 절반이 코발트로 물든다(2026-09-18 지적). */
.info-note{
  background:none; border:none; border-left:2px solid var(--acc-line);
  border-radius:0; box-shadow:none; padding:2px 0 2px 14px;
  -webkit-backdrop-filter:none; backdrop-filter:none;
}
.info-note div{ color:var(--soft); font-size:12.5px; font-weight:300; }
.info-note b{ color:var(--ink); font-weight:450; }
.lock-banner{
  background:rgba(154,74,48,.07); border:none; border-left:2px solid var(--danger);
  border-radius:0 var(--r-field) var(--r-field) 0;
}
.flash-ok{ background:var(--acc-bg); border:none; border-left:2px solid var(--acc);
  border-radius:0 var(--r-field) var(--r-field) 0; color:var(--acc-ink); }
.flash-err{ background:rgba(154,74,48,.07); border:none; border-left:2px solid var(--danger);
  border-radius:0 var(--r-field) var(--r-field) 0; color:var(--danger); }

/* 모달 */
.modal__backdrop{ background:rgba(0,0,0,.26); }
/* 반투명 흰색(.78) + 블러라 어두운 백드롭이 비쳐 회색으로 탁해 보였다 → 불투명 흰 지면으로. */
/* 팝업은 지면 위에 뜨는 것이라 면과 그림자를 쓴다 — 헤어라인만으로는 뒤와 구분되지 않는다.
   ⚠ 지면(아이보리)과 같은 색을 쓴다. 흰 상자를 띄우면 그것만 다른 서비스처럼 보인다. */
.modal__box{
  background:var(--bg);
  border:none; border-radius:var(--r-preview);
  box-shadow:var(--sh-preview);
}
/* ⚠ 머리글은 sticky 다(위 .modal__head 참고). 배경을 투명하게 두면 스크롤할 때
   **본문 글자가 제목 위로 비쳐 겹친다**. 상자와 같은 불투명 흰 지면을 준다.
   바닥글은 sticky 가 아니라 투명해도 되지만, 같이 맞춰 두는 편이 안전하다. */
.modal__head, .modal__foot{ background:var(--bg); border-color:var(--line); }
/* 스크롤된 내용이 머리글 아래로 지나가야 한다 — 쌓임 순서를 못박는다 */
.modal__head{ z-index:2; }
.modal__foot{ position:sticky; bottom:0; z-index:2; }
.modal__x{ background:none; border:1px solid var(--line); border-radius:var(--r-pill);
  color:var(--soft); transition:border-color .2s, color .2s; }
.modal__x:hover{ border-color:var(--acc); color:var(--ink); }
/* ⚠ 사진 칸의 모서리는 **각**이다(위 .thumb 참고 · 편집기 핸드오프 §사진).
   여기서 radius 를 다시 주면 위 선언을 덮어 둥글어진다 — 테두리 색만 맞춘다. */
.thumb{ border-color:rgba(255,255,255,.7); }

/* ═══════════════ 3a 입력 폼 (아코디언 위저드) ═══════════════ */
/* 폭은 상단 "자동 소멸" 안내(.info-note)와 동일하게 — .wrap 콘텐츠 폭에서 좌우 4px 인셋 */
.wiz{ max-width:none; padding:0; }
/*.wiz-scroll{ padding:14px 0 16px; }*/


/* B. 섹션 카드(아코디언) */
/* 섹션 — 목록에서는 **선으로 나뉜 행 하나**다(카드가 아니다).
   근거: design_handoff_lilt — "섹션 행 = 번호 + 영문 코드 + 제목 + 요약 + 완료 점".
   ⚠ 유리 카드로 되돌리지 말 것. 섹션이 카드가 되면 열일곱 장이 쌓여 목록이 아니라
     카드 더미가 된다(2026-09-18 지적). */
.wiz-sec{
  margin-bottom:0; border-radius:0; background:none;
  -webkit-backdrop-filter:none; backdrop-filter:none;
  border:none; border-top:1px solid var(--line-soft); box-shadow:none; overflow:hidden;
}
.wiz-sec:first-of-type{ border-top:none; }
/* 시안: `padding:20px 28px; gap:16px`, 손을 올리면 옅은 accent 면 + **왼쪽이 6px 밀린다.**
   ⚠ 여는 표식(＋)은 목록에 두지 않는다 — 시안의 행은 번호·제목/요약·점 넷뿐이다. */
.wiz-sec__head{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:20px 2px; cursor:pointer; width:100%; background:none; border:none;
  font-family:inherit; text-align:left; -webkit-tap-highlight-color:transparent;
  /* ⚠ 들여쓰기는 **transform** 으로 준다(2026-09-22). padding-left 로 밀던 때는 평상시 값이
     화면 폭마다 달라(PC 26px · 좁은 화면 18px) hover 값과 어긋났고, 그 차이만큼 글자가
     좌우로 크게 튀었다 — hover 값을 줄일수록 오히려 더 튀는 구조였다.
     transform 은 그 값과 무관하게 **늘 같은 거리**만 움직이고, 레이아웃을 다시 잡지도 않는다.
   ⚠ 스프링 이징을 쓰지 않는다 — 되튕기는 곡선이라 짧은 거리에서도 출렁여 보인다. */
  transition:background-color .2s, transform .18s ease;
}
/* 들여쓰기는 짚어 주는 정도 — 3px 이면 충분하다. */
body:not(.wiz-detail) .wiz-sec__head:hover{
  background-color:var(--a05, rgba(0,0,0,.03)); transform:translateX(3px);
}
body:not(.wiz-detail) .wiz-sec__head .wiz-sec__sign{ display:none; }

/* ── 추가 설정 — 번호 없는 아코디언 ── '청첩장 공유'·'배경음악'은 청첩장 본문이 아니라 01~12 목록 밖이다.
   카드 모양·여닫기는 .wiz-sec 규칙을 그대로 쓰고 여기서는 번호가 없다는 차이만 손본다. */
.wiz-extra__sep{
  display:flex; align-items:center; gap:12px; margin:26px 2px 12px;
  font-size:11px; letter-spacing:.06em; color:var(--ghost); text-transform:uppercase;
}
.wiz-extra__sep::before, .wiz-extra__sep::after{
  content:''; flex:1; height:1px; background:rgba(0,0,0,.1);
}
/* ⚠ .wiz-hint 에는 border-top 이 있다. 바로 위 구분선과 겹쳐 **줄이 두 개**로 보였다. 구분선이 이미 경계를 그으므로 여기서는 지운다. */
.wiz-extra__lead{ margin:0 2px 12px; border-top:none; padding-top:0; }
/* 번호가 없는 대신 라벨을 조금 굵게 — '추가 설정'임을 제목만 보고도 알게 한다 */
.wiz-sec--extra .wiz-sec__label{ font-weight:600; }
.wiz-sec__head:focus-visible{ outline:2px solid var(--acc); outline-offset:-2px; border-radius:var(--r-card); }
.wiz-sec__no{ font-family:inherit; font-weight:500; font-size:10px; letter-spacing:.14em; color:var(--ghost); }
/* 제목 — 16px/400(핸드오프 값). 한 줄로 두고 넘치면 말줄임한다. */
.wiz-sec__label{ font-weight:400; color:var(--ink); letter-spacing:-.008em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.wiz-sec__right{ display:flex; align-items:center; gap:9px; }
.wiz-chip{
  padding:5px 11px; border-radius:var(--r-pill); font-weight:400; font-size:10.5px;
  letter-spacing:-.01em; border:1px solid var(--line); white-space:nowrap;
  -webkit-backdrop-filter:none; backdrop-filter:none;
  background:none; color:var(--faint);
  transition:background .15s linear, color .15s linear, border-color .15s linear;
}
.wiz-chip.on{ background:var(--acc-bg); color:var(--acc-ink); border-color:transparent; }

/* 섹션 헤더의 "사용" 토글 — 청첩장에 이 항목을 넣을지 여부. 펼치기와는 별개다. */

/* ── 신랑·신부 표시 순서 토글 ──
   섹션 헤더의 "사용" 토글(.wiz-use)과 달리 본문 안에 놓이는 줄이라,
   스위치를 왼쪽에 두고 설명을 오른쪽에 편다. 설명이 길어 두 줄이 될 수 있어 위쪽 정렬. */



/* ── 항상 펼쳐 두는 설정 카드(공개·주소·QR) ──
   아코디언과 같은 카드 껍데기를 쓰되 머리를 눌러 접지 않는다 — 편집을 시작할 때
   가장 먼저 보는 값이라 접어 둘 이유가 없다. */
/* 설정 카드(공개·주소·QR) — 여기도 카드를 두르지 않는다. 머리와 본문을 선으로만 가른다. */
.cfg-card{
  background:none; border:none; border-top:1px solid var(--line);
  border-radius:0; box-shadow:none; overflow:visible; margin-bottom:0;
}

/* ═══════════════ 발행 · 요금제 ═══════════════
   승인 전에는 주소가 열리지 않는다는 사실을 알리고, 요금제를 고르고 입금을 요청하는 자리.
   ⚠ 금액·계좌·무엇이 열리는지는 **서버가 말한다**(Plan · PlanPriceService · BankAccountInfo).
     여기에 숫자를 적어 두지 말 것.
   ⚠ 발행은 **목록에 놓지 않는다**(핸드오프 Screen 2). 아래 버튼에서 시트로 올라온다 —
     다 만든 뒤 한 번 누르는 것이라, 목록에 두면 매번 스크롤을 가로막는다. */

/* ── 발행 시트 ── 아래에서 올라오는 판. 위 모서리만 둥글다(26px, 핸드오프 값).
   ⚠ display:flex 라 [hidden] 짝을 반드시 함께 둔다 — 브라우저 기본 [hidden]{display:none} 은
     명시도에서 밀려 감춰지지 않는다(같은 함정으로 세 번 터졌다). */
.pay-sheet{ position:fixed; inset:0; z-index:60; display:flex;
  align-items:flex-end; justify-content:center; }
.pay-sheet[hidden]{ display:none; }
.pay-sheet__backdrop{ position:absolute; inset:0; background:rgba(0,0,0,.42);
  animation:payVeil .24s ease both; }
/* ⚠ 한 화면에 다 들어와야 한다(2026-09-21) — 폰에서 스크롤이 생기면 [입금 확인 요청]이
   접힌 아래로 숨는다. 아래 여백 값들은 그 높이를 맞춰 잡은 것이라 함부로 늘리지 말 것. */
.pay-sheet__card{ position:relative; width:min(100%, 520px); max-height:92vh;
  overflow-y:auto; -webkit-overflow-scrolling:touch;
  background:var(--card); border-radius:26px 26px 0 0;
  padding:0 0 calc(12px + env(safe-area-inset-bottom));
  box-shadow:0 -18px 60px rgba(0,0,0,.22);
  animation:paySheetUp .46s cubic-bezier(.32,.72,0,1) both; }
/* 손잡이 — 시트라는 표식. 끌어 닫기는 붙이지 않았다(닫는 길이 이미 셋이다: ×·배경·ESC). */
.pay-sheet__grip{ display:flex; justify-content:center; padding:8px 0 0; }
.pay-sheet__grip span{ width:38px; height:4px; border-radius:999px; background:var(--line); }
/* 닫기 — 기호가 아니라 글자다(핸드오프 §결제). 안내문 오른쪽 끝에 같은 눈높이로 선다. */
.pay-sheet__x{ position:absolute; top:22px; right:22px; z-index:2;
  border:0; background:none; padding:0; color:var(--soft);
  font-family:inherit; font-size:13.5px; font-weight:400; line-height:1.7;
  cursor:pointer; transition:color .16s; }
.pay-sheet__x:hover{ color:var(--ink); }
/* 시트 안에서는 카드가 면을 두르지 않는다 — 시트 자체가 그 면이다. */
.pay-sheet .pay-card{ background:none; margin:0; border-radius:0; }
/* ⚠ 닫기(×)가 머리줄 위에 떠 있다 — 오른쪽을 비워 두지 않으면 상태 칩과 겹친다. */
.pay-sheet .pay-card__head{ padding-right:52px; }
body.pay-open{ overflow:hidden; }
@keyframes payVeil{ from{ opacity:0 } to{ opacity:1 } }
@keyframes paySheetUp{ from{ transform:translateY(100%) } to{ transform:translateY(0) } }
@media (prefers-reduced-motion:reduce){
  .pay-sheet__card, .pay-sheet__backdrop{ animation:none; }
}

/* 발행 카드 — 시트의 내용물. 옅은 코발트 면은 시트 밖에 있을 때만 쓴다. */
.pay-card{
  background:var(--a05, rgba(0,0,0,.03)); border:none; border-radius:var(--r-field);
  box-shadow:none; overflow:hidden; margin:0 0 26px;
}
.pay-card__head{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:18px 18px 12px; border-bottom:1px solid var(--acc-line);
  background:none;
}
.pay-card__label{ font-size:17px; font-weight:400; color:var(--acc-ink); letter-spacing:-.018em; }
.pay-card__body{ padding:12px 18px 14px; display:flex; flex-direction:column; gap:12px; }
.pay-note{ margin:0; font-size:12.5px; font-weight:300; line-height:1.7; color:var(--soft);
  word-break:keep-all; }
.pay-note b{ color:var(--ink); font-weight:500; }
.pay-note--weak{ font-size:11.5px; color:var(--faint); }
/* 요금제를 올릴 수 있다는 안내 — 이미 옅은 면 위라 면을 한 겹 더 깔지 않는다. */
.pay-note--up{ padding:0 0 0 12px; border-left:2px solid var(--acc-line);
  color:var(--acc-ink); }
/* 확인 중 화면의 요청 요약 — 값 세 개를 한 줄로 */
.pay-sum{ display:flex; flex-wrap:wrap; gap:6px 14px; font-size:13px; color:var(--ink); }
.pay-sum span{ font-weight:450; }

/* 요금제 고르기 — 라디오는 감추고 칸 전체를 누르게 한다(손가락으로 잡기 쉽게). */
/* 요금제 — 카드가 아니라 **행 두 줄**이다(핸드오프 Screen 2: 라디오 점 + 이름 + 스펙 + 금액).
   ⚠ 면·테두리·radius 를 두르지 말 것. 고르는 자리는 점 하나로 충분하고,
     시트 안에서 면을 두르는 곳은 입금 계좌 하나뿐이다. */
.plan-pick{ display:flex; flex-direction:column; }
.plan{ display:block; cursor:pointer; }
.plan + .plan{ border-top:1px solid var(--line-soft); }
.plan input{ position:absolute; opacity:0; width:0; height:0; }
.plan__box{ display:grid; grid-template-columns:auto 1fr; column-gap:12px; row-gap:4px;
  padding:11px 2px; border:none; border-radius:0; background:none; }
/* 라디오 점 — 가운데를 채워 고른 것을 알린다(inset 그림자라 크기가 흔들리지 않는다) */
.plan__box::before{ content:''; grid-row:1 / span 2; align-self:center;
  width:16px; height:16px; border-radius:999px; border:1px solid var(--line);
  transition:border-color .18s, box-shadow .18s; }
.plan input:checked + .plan__box::before{ border-color:var(--acc); box-shadow:inset 0 0 0 4px var(--acc); }
.plan input:checked + .plan__box .plan__nm{ color:var(--acc-ink); }
.plan input:focus-visible + .plan__box::before{ box-shadow:var(--acc-glow); }
.plan__top{ display:flex; align-items:baseline; gap:8px; }
.plan__nm{ font-size:14.5px; font-weight:500; color:var(--ink); letter-spacing:-.02em; }
.plan__tag{ padding:2px 7px; border-radius:999px; background:var(--acc); color:#fff;
  font-size:10px; font-weight:500; }
.plan__price{ margin-left:auto; font-size:14.5px; font-weight:500; color:var(--acc-ink); }
.plan__spec{ font-size:12px; font-weight:300; color:var(--soft); }
/* 가격이 정해지지 않은 요금제 — 고를 수 없다(서버도 같이 막는다) */
.plan--off{ cursor:default; }
.plan--off .plan__box{ opacity:.5; }

/* 입금 확인 대기 띠 — 지면 위쪽에 한 줄(핸드오프 §결제).
   ⚠ 저장바에는 같은 말을 적지 않는다(한 화면에 두 번 적으면 또 눌러야 하나 싶어진다). */
.pay-pending{ display:flex; align-items:center; gap:9px; margin:0 0 4px;
  padding:10px 14px; border-radius:999px; margin-top: 20px;
  background:var(--acc-bg); box-shadow:inset 0 0 0 1px var(--acc-line); }
.pay-pending__t{ flex:1; font-size:13px; font-weight:500; color:var(--acc-ink); word-break:keep-all; }
.pay-pending__dot{ flex:0 0 6px; width:6px; height:6px; border-radius:999px; background:var(--acc);
  animation:breathe 1.6s ease-in-out infinite; }
@keyframes breathe{ 0%,100%{ opacity:1 } 50%{ opacity:.3 } }
@media (prefers-reduced-motion:reduce){ .pay-pending__dot{ animation:none; } }

/* 시트 머리 한 줄 — 무엇을 하는 자리인지는 이 문장이 말한다(상태 라벨을 겹쳐 적지 않는다). */
.pay-lead{ margin:0; padding-right:44px; font-size:13px; font-weight:300; line-height:1.7;
  color:var(--soft); word-break:keep-all; }

/* ⚠ 시트 본문의 간격은 **폼 안에서 따로 준다.** pay-card__body 의 gap 은 폼 전체를 한 덩어리로
   보기 때문에 그 안의 요금제·계좌·입금자가 서로 달라붙는다(실제로 붙어 나왔다).
   값은 핸드오프 §결제 그대로다. */
.pay-card__body form{ display:flex; flex-direction:column; }
/*.pay-card__body .plan-pick{ margin-top:16px; }*/
.pay-card__body .pay-bank{ margin-top:12px; }
.pay-card__body .pay-payer{ margin-top:16px; }
.pay-card__body .pay-submit{ margin-top:16px; }

/* 입금 계좌 — 시트에서 **면을 두르는 유일한 자리**다(옮겨 적을 값이라 눈에 걸려야 한다).
   ⚠ 은행·번호 / 예금주 / 보내실 금액을 세 줄로 나눈다(핸드오프 §결제). 한 줄에 다 넣으면
     좁은 폰에서 예금주가 "릴 / 트" 로 끊긴다(390px 에서 실제로 끊겼다). */
.pay-bank{ padding:16px 16px; border:none; border-radius:14px;
  background:var(--acc-bg); box-shadow:inset 0 0 0 1px var(--acc-line); }
.pay-bank__l{ font-size:11.5px; font-weight:450; color:var(--acc-ink); }
.pay-bank__row{ margin-top:8px; display:flex; align-items:center; justify-content:space-between; gap:10px; }
.pay-bank__v{ flex:1; min-width:0; font-size:15px; font-weight:450; color:var(--ink);
  letter-spacing:-.018em; word-break:keep-all; }
/* 복사 — 겹친 사각 둘로 그린다(외부 아이콘 의존 없음) */
.pay-bank__copy{ flex:0 0 auto; display:flex; align-items:center; gap:6px;
  border:0; background:none; padding:0; cursor:pointer;
  font-family:inherit; font-size:12.5px; font-weight:450; color:var(--acc-ink);
  transition:opacity .2s, transform 90ms; }
.pay-bank__copy:hover{ opacity:.7; }
.pay-bank__copy:active{ transform:scale(.95); }
.pay-bank__copyico{ position:relative; width:13px; height:13px; flex:0 0 auto; }
.pay-bank__copyico::before, .pay-bank__copyico::after{ content:''; position:absolute;
  width:9px; height:9px; border-radius:2px; box-shadow:inset 0 0 0 1.4px currentColor; }
.pay-bank__copyico::before{ left:0; top:0; }
.pay-bank__copyico::after{ right:0; bottom:0; background:var(--acc-bg); }
.pay-bank__holder{ margin-top:4px; font-size:12.5px; color:var(--soft); }
.pay-bank__amt{ margin-top:10px; display:flex; align-items:baseline;
  justify-content:space-between; gap:10px; font-size:13px; color:var(--soft); }
.pay-bank__amt b{ font-size:15px; font-weight:450; letter-spacing:-.018em; color:var(--acc-ink); }

/* 입금자 — 밑줄 입력 두 칸을 **세로로** 쌓는다(핸드오프 §결제).
   ⚠ 나란히 세우면 390px 에서 연락처가 잘린다. */
.pay-payer{ display:flex; flex-direction:column; gap:14px; }
.pay-f{ display:block; }
.pay-f__l{ display:block; margin-bottom:5px; font-size:11.5px; font-weight:400; color:var(--soft); }
.pay-f input{ width:100%; box-sizing:border-box; height:36px; padding:0;
  border:none; border-bottom:1px solid var(--line); background:transparent;
  font-family:inherit; font-size:18px; font-weight:300; letter-spacing:-.012em; color:var(--ink);
  outline:none; transition:border-color .22s; }
.pay-f input:focus{ border-bottom-color:var(--acc); }

/* 보내는 버튼 — 시트에서 유일하게 채운 면이다. */
.pay-submit{ width:100%; height:48px;
  border:none; border-radius:999px; background:var(--acc); color:#fff;
  font-family:inherit; font-size:14.5px; font-weight:400; letter-spacing:-.01em;
  cursor:pointer; transition:opacity .16s, transform 90ms; }
.pay-submit:hover{ opacity:.88; }
.pay-submit:active{ transform:scale(.995); }
.pay-foot{ margin:8px 0 0; font-size:12px; line-height:1.6; color:var(--soft);
  text-align:center; word-break:keep-all; }
/* 결제 수단 탭 — 계좌 이체 / 카드 결제.
   ⚠ 두 길은 **서로 다른 것을 묻는다**(계좌만 입금자명·연락처가 필요하다). 한 화면에 겹쳐 두면
     카드로 낼 사람에게도 입금자 칸이 보이고, 어느 쪽으로 내야 하는지 고르게 만든다.
   ⚠ 어휘는 콘솔 탭(.tabs/.tab)과 같다 — 면을 두르지 않고 얇은 밑줄 하나로만 고른 것을 드러낸다.
   ⚠ `[hidden]` 짝을 반드시 둔다 — display 를 준 요소는 `element.hidden` 으로 안 감춰진다
     (브라우저 기본 `[hidden]{display:none}` 이 명시도에서 밀린다). 카드로 못 파는 요금제일 때
     JS 가 그 탭을 감춘다. */
.pay-tabs{ display:flex; gap:20px; margin:18px 0 0; border-bottom:1px solid var(--line); }
.pay-tab{ position:relative; border:none; background:none; padding:0 0 10px; cursor:pointer;
  font-family:inherit; font-size:13px; font-weight:400; letter-spacing:-.01em; color:var(--soft);
  transition:color .16s; }
.pay-tab[hidden]{ display:none; }
.pay-tab::after{ content:""; position:absolute; left:0; right:0; bottom:-1px; height:1.5px;
  background:transparent; }
.pay-tab:hover{ color:var(--ink); }
.pay-tab.is-on{ color:var(--ink); font-weight:500; }
.pay-tab.is-on::after{ background:var(--ink); }

/* 탭 내용 — 한 번에 하나만 편다. */
.pay-pane{ display:none; }
.pay-pane.is-on{ display:block; }

/* 카드 결제 금액 — 계좌의 "보내실 금액"을 대신하는 한 줄.
   ⚠ 이 탭에서는 아무것도 묻지 않는다(결제자는 그로블이 알려 준다). 금액과 버튼이면 족하다. */
.pay-card-sum{ display:flex; align-items:baseline; justify-content:space-between;
  margin-top:16px; font-size:12.5px; color:var(--soft); }
.pay-card-sum b{ font-size:15px; font-weight:500; color:var(--ink); letter-spacing:-.01em; }

/* 카드 결제 문의 — 결제 수단이 아니라 **곁들인 안내**다. 위 줄보다 한 단 작고 옅게 둔다.
   ⚠ 링크는 밑줄로만 드러낸다. 여기에 버튼을 놓으면 [입금 확인 요청]과 같은 무게로 읽혀
     "어느 쪽으로 내야 하나"를 고르게 만든다 — 기본 길은 계좌 하나다. */
.pay-foot--ask{ margin-top:6px; font-size:11px; color:var(--faint); }
.pay-foot--ask a{ color:var(--soft); text-decoration:underline;
  text-underline-offset:2px; text-decoration-color:rgba(0,0,0,.25); }
.pay-foot--ask a:hover{ color:var(--ink); text-decoration-color:currentColor; }

/* 템플릿 고르기(체험 중에만) — 썸네일 카드 라디오. 결제 뒤에는 이 자리가 고정 표시로 바뀐다.
   ⚠ 썸네일은 첫 화면 Shop 카드와 같은 파일이다(assets/bridge/cards/tpl-0N.jpg) — 지면을 고치면 그 파일을
     다시 뽑아야 두 화면이 같은 그림을 보여 준다. */
.tplpick{ display:grid; grid-template-columns:repeat(auto-fill, minmax(96px, 1fr));
  gap:8px; margin-top:2px; }
.tplpick__i{ cursor:pointer; }
.tplpick__i input{ position:absolute; opacity:0; width:0; height:0; }
.tplpick__box{ display:block; overflow:hidden; border-radius:var(--r-field);
  background:var(--gl-field); box-shadow:inset 0 0 0 1px var(--line);
  transition:box-shadow .2s, transform .28s var(--e-spring, cubic-bezier(.34,1.56,.64,1)); }
.tplpick__i:hover .tplpick__box{ box-shadow:inset 0 0 0 1px var(--acc-line); }
.tplpick__i.sel .tplpick__box{ box-shadow:0 0 0 2px var(--acc); transform:translateY(-3px); }
.tplpick__i input:focus-visible + .tplpick__box{ box-shadow:var(--acc-glow), inset 0 0 0 1px var(--acc); }
.tplpick__box img{ display:block; width:100%; aspect-ratio:3 / 4; object-fit:cover;
  object-position:50% 22%; }
.tplpick__nm{ display:block; padding:7px 8px 8px; font-size:11px; font-weight:450;
  color:var(--soft); text-align:center; letter-spacing:-.01em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.tplpick__i.sel .tplpick__nm{ color:var(--acc-ink); }

/* 요금제가 막은 기능 — **감추지 않고 잠근다.** 아예 없애면 그 기능이 있는 줄도 모르고,
   요금제를 올릴 이유도 알 수 없다.
   ⚠ 서버도 같이 막고 있다(updateOwnedMusicEnabled · updateOwnedSlug) — 화면만 잠그면
     요청을 직접 보내 우회된다. */
.plan-lock{ margin-left:7px; padding:2px 7px; border-radius:999px;
  background:var(--acc-bg); color:var(--acc-ink);
  font-size:10px; font-weight:500; letter-spacing:0; white-space:nowrap; }
.wiz-sec--plan-locked .wiz-sec__label{ color:var(--faint); }
.wiz-sec--plan-locked .wiz-sec__pad{ opacity:.55; }
/* ⚠ 안내문은 흐리게 하지 않는다 — 왜 잠겼는지 읽혀야 한다. */
.wiz-sec--plan-locked .wiz-sec__pad > .wiz-hint{ opacity:1; }
.cfg-row--locked .slug-field{ color:var(--faint); cursor:default; }
.cfg-card__head{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:26px 0 14px; border-bottom:none;
}
.cfg-card__label{ font-size:19px; font-weight:400; color:var(--ink); letter-spacing:-.018em; }
.cfg-card__body{ padding:0; }

/* 카드 안의 세 줄은 같은 열에서 시작해야 한다.
   ⚠ .item 은 제 테두리와 16px 패딩을 갖고 있어, 카드 안에 그대로 두면 글자가 안쪽으로 밀려
     주소 라벨과 열이 어긋난다. 카드 안에서는 테두리를 걷고 여백을 0 으로 맞춘다. */
.cfg-card__body > .item{
  border:0; background:none; border-radius:0;
  padding:14px 0; gap:14px;
}
.cfg-card__body > .item + .item,
.cfg-card__body > .cfg-row + .item,
.cfg-card__body > .item + .cfg-row{ border-top:1px solid var(--line-soft, var(--line)); }
/* 주소 줄 — 라벨·입력·안내가 한 덩어리 */
.cfg-row{ display:flex; flex-direction:column; gap:7px; padding:14px 0; }
.cfg-row .wiz-f__label{ margin:0; }
/* ── 혼주 "고인" 체크박스 ──
   토글이 아니라 체크박스다 — 켜고 끄는 설정이 아니라 사실 표시라서,
   네모 체크가 의미에 맞고 네 자리에 나란히 놓아도 시끄럽지 않다. */
.late-chk{
  display:inline-flex; align-items:center; gap:5px;
  margin-top:6px; cursor:pointer; user-select:none;
}
.late-chk input{
  width:15px; height:15px; margin:0; flex:none;
  accent-color:var(--cobalt); cursor:pointer;
}
.late-chk span{ font-size:12px; color:var(--soft); letter-spacing:-.01em; }
.late-chk input:checked + span{ color:var(--ink); font-weight:600; }
/* ⚠ display:flex 는 UA 의 [hidden]{display:none} 을 이긴다 — 흑백 표지가 아닌 템플릿에서
   "표지 사진 흑백" 줄을 감추려면 [hidden] 규칙을 따로 둬야 한다. */
.order-swap[hidden]{ display:none; }
/* ⚠ 유리 카드(테두리 + radius 12px + 흰 면)로 되돌리지 말 것 — 입력 칸들 사이에 홀로
   상자가 서서 3a 화면으로 보였다. 다른 토글 줄과 같이 아래 헤어라인 한 줄로만 끊는다. */
.order-swap{
  display:flex; align-items:flex-start; gap:10px; cursor:pointer;
  padding:2px 0 14px; margin:0 0 4px;
  border:0; border-bottom:1px solid var(--line-soft); border-radius:0; background:none;
}
.order-swap .switch{ flex:none; margin-top:1px; }
.order-swap__t{
  display:flex; flex-direction:column; gap:3px;
  font-size:13px; font-weight:600; color:var(--ink); line-height:1.4;
}
.order-swap__t .hint{
  font-size:11.5px; font-weight:400; color:var(--soft); letter-spacing:-.01em;
}
.wiz-use{
  flex:0 0 auto;                 /* ⚠ 목록 행에서 눌리면 "사용"이 두 줄로 쪼개진다 */
  display:inline-flex; align-items:center; gap:7px; cursor:pointer;
  padding:2px 0 2px 4px; /* 손가락으로 누르기 좋게 */
}
/* ⚠ 목록에서는 `사용` 토글을 내보내지 않는다 — 행마다 점·칩·토글·＋ 가 겹쳐 서서 어수선했다.
   켜고 끄는 일은 **상세 머리말에서만** 한다. DOM 에서 지우지 말고 감출 것(저장은 그대로 간다). */
body:not(.wiz-detail) .wiz-sec__head .wiz-use{ display:none; }
.wiz-use__txt{
  font-weight:500; font-size:10.5px; letter-spacing:-.01em; white-space:nowrap;
  color:rgba(0,0,0,.3); transition:color .15s linear;
}
.wiz-sec:not(.off) .wiz-use__txt{ color:var(--soft); }
/* 글자는 **지금 상태**를 가리킨다 — 스위치와 같은 뜻이다(누르면 될 일을 적지 않는다).
   ⚠ 마크업은 비워 두고 여기서 넣는다. 토글이 14곳이라 JSP 마다 분기를 적지 않으려는 것이다.
   ⚠ `:empty` 로 좁힌다 — 같은 클래스를 쓰는 청첩장 공개 토글(#pubTxt)은 제 글자('공개중'
     /'비공개')를 서버와 JS 가 넣으므로 여기에 걸리면 안 된다.
   ⚠ min-width 는 '미사용'(석 자) 기준이다. 없으면 글자가 바뀔 때마다 옆 스위치가 좌우로 흔들린다. */
.wiz-use__txt:empty{ display:inline-block; min-width:3.2em; text-align:right; }
.wiz-use__txt:empty::after{ content:'미사용'; }
.wiz-use:has(input:checked) .wiz-use__txt:empty::after{ content:'사용'; }
/* 헤더용 축소 스위치 */
/* 목록 행에 붙는 축소판 — 트랙만 짧아지고 노브 크기는 같다(작아지면 누르기 어렵다). */
/* 축소판 — 트랙만 짧아진다(22 − 11 = 11px 이동). 막대 두께는 같다. */
.switch--sm{ width:22px; height:26px; }
.switch--sm .slider::before{ width:11px; height:3px; margin-top:-1.5px; }
.switch--sm input:checked + .slider::before{ transform:translateX(11px); }

/* 펼침 기호 — 열림 상태만 나타낸다 */
.wiz-sec__sign{
  font-weight:300; font-size:15px; color:rgba(0,0,0,.28);
  width:10px; text-align:center; line-height:1;
}
.wiz-sec__sign::before{ content:'＋'; }
.wiz-sec.open .wiz-sec__sign::before{ content:'−'; }

/* 사용 안 함 — 내용은 그대로 두고 헤더만 조용하게(접기·편집은 계속 가능) */
/* 사용 안 함 — 면을 깔지 않고 글자만 조용하게. 헤어라인 지면에서는 면이 곧 카드로 읽힌다. */
.wiz-sec.off{ background:none; }
.wiz-sec.off .wiz-sec__label{ color:rgba(0,0,0,.42); }
.wiz-sec.off .wiz-sec__no{ color:rgba(0,0,0,.2); }

/* ═══════════════ 편집 화면의 뼈대 ═══════════════
   근거: 바탕화면 design_handoff_lilt — Screen 2.
   지면 위에 **떠 있는 줄 하나** + 목록에서만 보이는 히어로(로고·제목·진행 막대).
   ⚠ 서비스 상단바(.topbar)를 여기에 쓰지 않는다 — 편집은 한 가지 일에 집중하는 화면이다. */

/* 위쪽 베일 — 스크롤한 내용이 상단 줄 밑으로 비쳐 글자가 겹치는 것을 막는다.
   ⚠ 그림만 그린다(pointer-events:none). 빼면 그 아래 버튼이 눌리지 않는다. */
/* ⚠ 색을 **토큰에서만** 가져온다. 여기 옛 아이보리(#f7f3ea)가 남아 있어 상단이 누렇게
     보였다(2026-09-21 지적). 지면색을 직접 적지 말 것 — 톤을 갈면 여기만 뒤처진다.
   ⚠ 높이는 상단 줄이 덮는 만큼이면 된다. 108px 은 그보다 한참 길어 섹션 제목까지 흐렸다. */
.ed-veil{
  position:fixed; left:0; right:0; top:0; height:76px; z-index:27; pointer-events:none;
  background:linear-gradient(180deg, var(--bg) 0%, var(--bg) 62%, rgba(244,243,241,0) 100%);
}
.ed-bar{
  position:fixed; left:0; right:0; top:0; z-index:30;
  display:flex; align-items:center; gap:14px;
  padding:14px max(clamp(16px,4vw,22px), (100vw - 1240px) / 2) 0;
}
.ed-bar__sp{ flex:1; }
.ed-bar__out{ margin:0; display:flex; align-items:center; }
/* ★ 한쪽은 <a>, 다른 쪽은 <button> 이라 상속되는 line-height 가 다르다(링크 1.6 / 버튼 normal).
   그대로 두면 두 글자가 서로 다른 높이의 줄상자에 앉아 눈높이가 어긋난다.
   높이와 line-height 를 직접 고정해 둘을 맞춘다(.pv__btn 과 같은 사정). */
.ed-bar__link{ display:inline-flex; align-items:center; height:20px; line-height:1;
  border:none; background:none; padding:0; cursor:pointer;
  font-family:inherit; font-weight:400; color:var(--soft);
  text-decoration:none; transition:color .2s; }
.ed-bar__link:hover{ color:var(--ink); }
/* ‹ 목록 — 상세에서만 뜬다. 목록으로 되돌아가는 유일한 길이다. */
/* 상단 줄 왼쪽의 브랜드 표식 — **목록·상세 두 화면 모두**. 로고가 드는 자리는 헤더 하나다.
   ⚠ 마스크 그림(apple-touch-icon.png)은 정사각 캔버스에 잉크가 일부만 차지하고 나머지가
     투명 여백이다. 그래서 박스를 키운 뒤 여백만큼 음수 마진으로 상쇄한다 — 화면에는 크게,
     레이아웃은 잉크 크기만큼만(다른 화면의 .brand-mark 와 같은 방식). */
.ed-bar__mark{
  display:block; flex:none;
  background-color:var(--acc);
  -webkit-mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
          mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
}
/* 되돌아가는 길은 **상세 머리말 왼쪽**이다(상단 줄에는 로고와 계정 링크만 남는다).
   ⚠ 머리말은 가운데 정렬 세로 흐름이라, 제목과 같은 줄에 세우려면 흐름에서 빼야 한다.
     그래서 absolute 다 — 제목은 지면 한가운데, 이 버튼은 왼쪽 끝에 선다.
   ⚠ **기본은 숨김이다.** 한 번 만들어진 버튼은 DOM 에 그대로 남으므로, 목록으로 돌아갔을 때
     이 짝이 없으면 button 기본 display 로 되살아나 목록 행에 [‹ 목록] 이 붙는다. */
.wiz-sec__back{ display:none; }
body.wiz-detail .wiz-sec.open .wiz-sec__back{
  position:absolute; left:0; z-index:1;
  display:inline-flex; align-items:center; gap:3px;
  border:none; background:none; padding:0; cursor:pointer;
  font-family:inherit; font-size:13.5px; font-weight:400; color:var(--soft);
  animation:fadeIn .3s both; transition:opacity .16s;
}
body.wiz-detail .wiz-sec.open .wiz-sec__back:hover{ opacity:.55; }
body.wiz-detail .wiz-sec.open .wiz-sec__back span{
  font-size:18px; line-height:1; font-weight:300; margin-top:-2px; }

/* 히어로 — 목록에서만. 상세로 들어가면 통째로 접는다.
   ⚠ 로고가 상단 줄로 올라가면서 **제목이 첫 요소가 됐다.** 그 전에는 로고 68px 가 완충이라
     제목이 베일(.ed-veil, 108px) 밖에서 시작했는데, 그대로 두면 제목이 베일에 묻힌다 —
     상세 머리말에서 겪은 것과 같은 일이다. 그만큼 위 여백을 늘린다(54px + 42px = 96px). */
.ed-hero{ padding:42px 0 0; }
body.wiz-detail .ed-hero{ display:none; }
/* 입금 확인 띠는 목록 화면에서만 보인다. 상세의 붙박이 머리말 뒤에 잔상이 남지 않게 함께 접는다. */
body.wiz-detail .pay-pending{ display:none; }
.ed-hero__hd{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.ed-hero__t{ margin:2px 0 0; font-size:19px; font-weight:400; letter-spacing:-.014em;
  line-height:1.5; color:var(--ink); }
/* 제목 옆의 [Guide] — 제목에 딸린 곁말이라 제목보다 작고 옅다.
   ⚠ 얼굴은 **왼쪽 세로선 하나**다(2026-09-29). 상자(네모)도 알약도 밑줄도 거쳤다 —
     앞의 둘은 제목 옆에서 덩어리로 읽혔고, 셋 다 되살리지 말 것.
   ⚠ 세로선을 고른 이유: **가이드를 열면 나오는 목차가 같은 어휘**다(왼쪽 세로선으로
     현재 장을 가리킨다) → 버튼과 그 안의 화면이 한 벌로 이어진다.
   ⚠ 아이콘은 자산이 아니라 인라인 SVG 라 색이 글자를 따라온다. */
.ed-hero__guide{
  flex:none; display:inline-flex; align-items:center; gap:6px;
  height:20px; padding:0 0 0 12px; margin-top:3px;
  border:0; border-left:1px solid var(--line); border-radius:0; background:none;
  font-family:inherit; font-size:12.5px; font-weight:400; letter-spacing:.02em;
  color:var(--soft); cursor:pointer;
  transition:color .18s, border-color .18s;
}
.ed-hero__guide:hover{ color:var(--ink); border-left-color:var(--ink); }
.ed-hero__guide:active{ opacity:.6; }
.ed-hero__guide-i{ flex:none; width:15px; height:15px; display:block; }
/* 진행 막대 — 값이 들어간 섹션 ÷ 전체. 폭은 JS 가 넣는다. */
.ed-prog{ position:relative; height:1px; margin-top:18px; background:var(--line); }
.ed-prog span{ position:absolute; left:0; top:0; height:1px; width:0;
  background:var(--acc); transition:width .6s var(--e-in, cubic-bezier(.22,.61,.36,1)); }

/* 상세 아래의 이전·다음 — 한 섹션을 끝내고 다음으로 넘어가는 길 */
.wiz-nav{ display:flex; gap:18px; margin-top:44px; padding-top:22px;
  border-top:1px solid var(--line-soft); }
.wiz-nav__sp{ flex:1; }
.wiz-nav__b{ border:none; background:none; padding:0; cursor:pointer;
  font-family:inherit; font-size:14px; color:var(--acc-ink);
  transition:opacity .16s, color .2s; }
.wiz-nav__b:hover{ opacity:.6; }
.wiz-nav__b:disabled{ color:var(--ghost); cursor:default; opacity:1; }

/* 상단 줄이 떠 있으므로 편집 지면은 그만큼 내려 시작한다.
   ⚠ 편집 화면(.wrap--split)에만 준다 — 다른 화면은 상단바(.topbar)가 자리를 차지한다. */
.wrap--split{ padding-top:54px; }

/* ═══════════════ 섹션 목록 → 한 섹션씩 열기 ═══════════════
   근거: 바탕화면 design_handoff_lilt — Screen 2.
   기본은 목록이고, 행을 누르면 `body.wiz-detail` 이 붙어 그 섹션만 남는다.
   ⚠ 숨기는 것은 **CSS 뿐**이다. 숨은 섹션의 입력도 그대로 제출된다 —
     hidden/disabled 로 감추면 그 값이 통째로 날아간다. */

/* 목록 행 — 핸드오프 Screen 2 그대로 [번호] [제목 / 요약] [완료 점] 이다.
   ⚠ 영문 코드는 **목록에 두지 않는다.** 폭이 390px 뿐이라 제목과 나란히 세우면 한글 제목이
     두세 줄로 흘러 목록이 읽히지 않는다(실측: "디자 / 인 · 글 / 꼴").
     DOM 에서 지우지 말고 여기서 감춘다 — 완료 점을 켜는 JS 가 data-code 를 읽는다. */
/* ⚠ 번호는 **제목과 같은 줄에, 글자 밑선을 맞춰** 세운다(baseline).
   예전에는 번호를 1~2행에 걸쳐 두고 세로 가운데(align-self:center)로 뒀는데, 목록에서는
   2행(요약)이 비어 있어도 그 행과 row-gap 만큼 아래로 내려앉아 **번호만 제목보다 처져** 보였다
   (2026-09-20 지적: "01 신랑·신부 가 한 줄로 안 맞는다"). 번호는 1행에만 둔다. */
.wiz-sec__left{ display:grid; grid-template-columns:auto minmax(0,1fr);
  column-gap:14px; row-gap:3px; align-items:baseline; min-width:0; }
.wiz-sec__no{ grid-area:1 / 1; }
.wiz-sec__label{ grid-area:1 / 2; }
.wiz-sec__code{ display:none; }
/* 번호가 없는 섹션(추가 설정)은 한 칸으로 — 빈 번호 자리만큼 제목이 밀리면 줄이 어긋난다 */
.wiz-sec--extra .wiz-sec__left{ grid-template-columns:minmax(0,1fr); }
.wiz-sec--extra .wiz-sec__label{ grid-column:1; }
/* 요금제 뱃지(스탠다드)는 제목 **옆**이다(2026-09-21 고객 지시).
   ⚠ grid 에서 자리를 정해 주지 않으면 자동 배치로 다음 줄에 떨어져 제목 **아래**에 붙는다.
     칸을 하나 더 열고 1행에 못박는다 — PC·모바일이 같은 규칙을 쓴다. */
.wiz-sec--extra .wiz-sec__left:has(.plan-lock){ grid-template-columns:auto auto; justify-content:start; }
.wiz-sec__left .plan-lock{ grid-row:1; grid-column:2; align-self:center; }
.wiz-sec__dot{ flex:0 0 5px; width:5px; height:5px; border-radius:999px;
  background:rgba(0,0,0,.14); transition:background-color .24s; }
.wiz-sec__dot.on{ background:var(--acc); }
/* 상세에서만 보이는 안내문 — 목록에서는 감춘다(행이 두 줄로 늘어난다) */
.wiz-sec__lead{ display:none; }

/* 되돌아가는 길은 **상단 바의 `‹ 목록` 하나**다(핸드오프 Screen 2: 뒤로는 고정 바에 있다).
   ⚠ 지면에도 같은 버튼을 두면 상세 머리말 위에 되돌아가기가 두 개로 겹친다.
     마크업은 남겨 둔다 — data-sec-back 을 JS 가 함께 묶어 두고 있다. */
.wiz-back{ display:none; }

/* 상세 — 열린 섹션만 남긴다. 카드 테를 벗고 지면에 바로 놓인다. */
body.wiz-detail .wiz-sec:not(.open),
body.wiz-detail .wiz-group-label,
body.wiz-detail .wiz-extra__sep,
body.wiz-detail .cfg-card{ display:none; }
body.wiz-detail .wiz-sec.open{
  background:none; border:0; box-shadow:none; overflow:visible;
  -webkit-backdrop-filter:none; backdrop-filter:none;
}
/* 머리말 — 가운데 정렬 영문 코드 → 제목 → 안내문 → 구분선 */
body.wiz-detail .wiz-sec.open .wiz-sec__head{          /* 왼쪽 [‹ 목록] 의 기준 상자 */
  flex-direction:column; align-items:center; gap:10px; cursor:default;
}
/* ⚠ 목록에서 .wiz-sec__left 는 grid 다 — 여기서 flex 로 되돌리지 않으면
     flex-direction 이 먹지 않아 머리말이 가운데로 서지 않는다. */
body.wiz-detail .wiz-sec.open .wiz-sec__left{
  display:flex; flex-direction:column; align-items:center; gap:9px; }
body.wiz-detail .wiz-sec.open .wiz-sec__label{ font-weight:400; letter-spacing:-.022em;
  white-space:normal; overflow:visible; text-align:center; }
/* 상세 머리말은 제목 하나로 연다 — 목록용 표식은 전부 감춘다.
   ⚠ 영문 코드(GUESTBOOK · THE DAY …)는 **띄우지 않는다.** 한글 제목 바로 위에 같은 뜻을
     영어로 한 번 더 적는 셈이라 머리말이 두 겹이 된다. DOM 에서 지우지 말고 여기서 감춘다 —
     완료 점을 켜는 JS 가 data-code 를 읽는다. */
body.wiz-detail .wiz-sec.open .wiz-sec__code{ display:none; }
body.wiz-detail .wiz-sec.open .wiz-sec__no,
body.wiz-detail .wiz-sec.open .wiz-sec__sign,
body.wiz-detail .wiz-sec.open .wiz-sec__dot{ display:none; }
/* 안내문 아래는 **전폭 선이 아니라 32×1px 짧은 선**이다(시안 §섹션 머리말).
   ⚠ 전폭 헤어라인으로 되돌리지 말 것 — 가운데 정렬한 머리말을 가로줄이 끊어 버린다. */
body.wiz-detail .wiz-sec.open .wiz-sec__lead{
  display:block; margin:0; padding:0 0 22px;
  font-size:13px; font-weight:300; line-height:1.75; color:var(--soft);
  text-align:center; word-break:keep-all; overflow-wrap:break-word;
  max-width:248px; margin-left:auto; margin-right:auto;
  border-bottom:none;
}
body.wiz-detail .wiz-sec.open .wiz-sec__lead::after{
  content:''; display:block; width:32px; height:1px; margin:22px auto 0; background:var(--line);
}
/* 사용 토글은 머리말 아래 가운데로 — 상세에서도 켜고 끌 수 있어야 한다 */
body.wiz-detail .wiz-sec.open .wiz-sec__right{ justify-content:center; }

/* 아코디언 열림 전환 — iOS 감각 */
.wiz-sec__body{
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows .22s var(--ease-ios);
}
.wiz-sec.open .wiz-sec__body{ grid-template-rows:1fr; }
/* ⚠ 접혀 있는 동안에만 잘라 낸다. 열린 섹션까지 잘라 두면 상세에서 좌우 패딩이 0 이라
   (`body.wiz-detail … .wiz-sec__pad`) **고른 견본 칸의 바깥으로 2px 뻗는 선택 링이
   왼쪽 가장자리에서 잘린다**(글꼴 카드 첫 칸에서 눈에 띈다). */
.wiz-sec__inner{ overflow:hidden; }
.wiz-sec.open .wiz-sec__inner{ overflow:visible; }
.wiz-sec__pad{ display:flex; flex-direction:column; }
.wiz-hint{
  font-weight:400; line-height:1.65; color:rgba(0,0,0,.5); letter-spacing:-.01em;
}
/* 값 입력 — 밑줄 하나다. 핸드오프 Screen 2 의 형태 정본이고, 이 화면의 다른 입력
   (.field 계열)도 이미 같은 어휘다.
   ⚠ 박스로 되돌리지 말 것 — 지면 전체가 헤어라인인데 입력만 면과 radius 를 두르면
     그 줄에서 결이 끊긴다. 값이 주인공이라 글자도 라벨보다 한참 크다. */
.wiz-sec__pad input[type=text], .wiz-sec__pad input[type=tel],
.wiz-sec__pad input[type=url], .wiz-sec__pad input[type=number],
.wiz-sec__pad textarea,
.pay-sheet input[type=text], .pay-sheet input[type=tel]{
  width:100%; box-sizing:border-box; padding:0 0 9px;
  border:none; border-bottom:1px solid var(--line); border-radius:0;
  background:transparent; -webkit-backdrop-filter:none; backdrop-filter:none;
  font-family:inherit; font-size:16px; font-weight:300;
  color:var(--ink); letter-spacing:-.012em; transition:border-color .2s;
}
/* 정본: 값 18px / 글상자만 17px. 편집 상세만 17px 이라 다른 화면 입력과 어긋나 있었다. */
.wiz-sec__pad textarea{ font-size:17px; line-height:1.75; resize:none; padding-bottom:10px; }
.wiz-sec__pad input::placeholder, .wiz-sec__pad textarea::placeholder,
.pay-sheet input::placeholder{ color:var(--ghost); font-weight:300; }
.wiz-sec__pad input:focus, .wiz-sec__pad textarea:focus,
.pay-sheet input:focus{
  outline:none; border-bottom-color:var(--acc); box-shadow:none; background:transparent;
}
/* 2열 배치(이름/연락처 등) */
.wiz-pair{ display:grid; grid-template-columns:1fr 1fr; gap:10px; }
@media (max-width:359px){ .wiz-pair{ grid-template-columns:1fr; } }

/* 사진 그리드 */
.wiz-photos{ display:grid; grid-template-columns:repeat(4,1fr); gap:6px; }
.wiz-photo{ aspect-ratio:1; border-radius:var(--r-field); overflow:hidden; position:relative;
  background:rgba(0,0,0,.06); }
.wiz-photo img{ width:100%; height:100%; object-fit:cover; display:block; }
/* 사진 추가 칸 — 핸드오프의 `＋` 칸 그대로: 정사각, 선 1px, 면 없음, 모서리 각짐.
   ⚠ 점선으로 되돌리지 말 것 — 이 지면의 선은 전부 실선 1px 이다. */
.wiz-photo--add{
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  border:1px solid var(--line); background:none; border-radius:0;
  font-weight:300; font-size:18px; color:var(--ink);
  transition:background-color .2s, border-color .2s;
}
.wiz-photo--add:hover{ background:var(--a05, rgba(0,0,0,.03)); border-color:var(--acc); color:var(--acc); }


/* iOS 확대 방지: 입력 폰트 16px 미만이면 포커스 시 줌 — 터치 기기에서만 16px */
@media (hover:none) and (pointer:coarse){
  .wiz-sec__pad input, .wiz-sec__pad textarea,
  .field input, .field select, .field textarea{ font-size:16px; }
}

/* 성능: 뷰포트 밖 섹션 카드의 blur 비용을 줄인다 */
.wiz-sec{ content-visibility:auto; contain-intrinsic-size:auto 64px; }
/* ⚠ 열린 섹션에서는 끈다. `content-visibility:auto` 는 paint containment 를 함께 걸어
   **자식이 섹션 박스 밖으로 그리는 것을 잘라 낸다** — overflow 로는 풀리지 않는다.
   상세는 좌우 패딩이 0 이라 견본 칸이 경계에 붙고, 그 바깥으로 2px 뻗는 선택 링의
   **왼쪽이 통째로 사라졌다**(글꼴 카드 첫 칸). 한 섹션만 해제하므로 성능 이득은 그대로다. */
.wiz-sec.open{ content-visibility:visible; }

@media (prefers-reduced-motion:reduce){
  .wiz-sec__body, .switch .slider, .switch .slider::before{ transition:none; }
}

/* 설정 그룹 구분 라벨 */
/* 설정 / 입력 항목 그룹 구분 라벨.
   --mono(시스템 모노)를 쓰던 자리라 이 화면에서 혼자 튀었다 → 본문과 같은 서체로. */
.wiz-group-label{
  display:flex; align-items:center; gap:10px;
  font-family:var(--sans); font-size:12px; font-weight:450; letter-spacing:.02em;
  color:var(--soft);
  margin:34px 0 12px; padding-left:2px;
}
.wiz-group-label::after{                     /* 라벨 오른쪽으로 흐르는 헤어라인 */
  content:""; flex:1; height:1px; background:var(--line);
}
.wiz-group-label:first-of-type{ margin-top:6px; }   /* 맨 위 그룹은 위 여백을 줄인다 */
/* 설정 섹션 — 콘텐츠 섹션보다 한 단계 조용하게 */
/* 설정 섹션도 면을 두르지 않는다(디자인·글꼴). */
.wiz-sec--cfg{ background:none; }
.wiz-sec--cfg .wiz-sec__no{ font-size:12px; color:rgba(0,0,0,.22); }

/* 섹션 본문 안의 select — 입력과 같은 밑줄 어휘다(둘이 나란히 서는 자리가 많다) */
.wiz-sec__pad select{
  width:100%; box-sizing:border-box; padding:0 18px 9px 0;
  border:none; border-bottom:1px solid var(--line); border-radius:0;
  background:transparent; font-family:inherit; font-size:17px; font-weight:300;
  color:var(--ink); letter-spacing:-.012em; transition:border-color .2s;
}
.wiz-sec__pad select:focus{
  outline:none; border-bottom-color:var(--acc); box-shadow:none;
}
/* ⚠ 바로 위 `width:100%` 가 `.transit-add__row select{width:120px}`(224행) 을 덮는다 —
   명시도가 같고 파일에서 더 뒤라서 이긴다. 그러면 셀렉트가 줄 전체를 먹고 옆의 "추가" 버튼이
   행 밖으로 밀려나 **화면에서 사라진다**(실측: select w=724px, button right=1318 > row right=1260).
   교통 줄만 다시 좁혀 둔다. 좁은 화면 규칙(228행)도 같은 이유로 여기서 한 번 더 적는다. */
.wiz-sec__pad .transit-add__row select{ flex:none; width:120px; }
@media (max-width:420px){
  .wiz-sec__pad .transit-add__row select{ flex:1 1 auto; width:auto; min-width:0; }
}
/* 섹션 안에 들어간 기존 .field 위젯은 여백을 폼 gap 에 맡긴다 */
.wiz-sec__pad .field{ margin:0; }
.wiz-sec__pad .switch-row{ border-bottom:none; padding:2px 0; }
.wiz-f__label .hint{ font-weight:400; color:var(--ghost); margin-left:4px; }


/* ═══ PC 2단 — 미리보기 + 편집 (1024px↑ 전용) ═══
   ★ 시작점 미만은 픽셀 하나도 바뀌면 안 된다 — 레이아웃을 바꾸는 규칙은 전부 min-width 블록 안에 있다.
     1024~1279px 은 기기 칸을 300px 로 좁혀 편집 폭을 확보한다(맨 아래 블록). */
/* ⚠ 반드시 `.wrap--split > .pv` 로 좁힌다. 그냥 `.pv` 로 두면 **업로드 썸네일**
   (.preview-strip .pv / .pv-wrap .pv)까지 display:none 이 걸린다 — 같은 클래스 이름을 쓴다.
   그래서 사진을 고르면 64px 빈 칸에 `대표` 버튼만 남아 있었다. */
.wrap--split > .pv{ display:none; }   /* 모바일: 미리보기 패널 없음 — 기존 화면 그대로 */
.savebar__url{ display:none; }

@media (min-width:1024px){
  /* 편집이 왼쪽, 미리보기가 오른쪽이다(핸드오프 §Screen 2 — 읽는 순서가 편집 → 결과).
     ⚠ 자리를 되돌리려면 아래 두 grid-column 과 1279px 블록의 열 폭까지 함께 고친다.
     ⚠ 두 칸에 `grid-row:1` 을 **반드시** 적는다. .pv 가 DOM 에서 먼저인데 2열이라,
       행을 비워 두면 자동배치 커서가 되돌아가지 못해 .split__main 이 2행으로 떨어진다
       (폼이 화면 한참 아래에서 시작하고, .pv 의 height:100% 사슬이 끊겨 미리보기가 사라진다). */
  .wrap--split{
    max-width:1300px;
    display:grid; grid-template-columns:minmax(0,1fr) minmax(0,356px);
    column-gap:48px;
    row-gap:0;
  }
  /* 좌측은 세로로 쌓인 바+기기 — 이 배치는 그대로 둔다 */
  .wrap--split > .pv{ display:flex; flex-direction:column; gap:10px; }
  /* ══ 2단 레이아웃 — 좌측 미리보기는 고정, 우측만 스크롤 ══
     ⚠ sticky 를 쓰지 말 것 — 자기 grid area 를 벗어나면 위로 밀려 올라간다(실측 405px).
       페이지(body)를 아예 스크롤하지 않게 하고 우측 .split__main 한 곳만 스크롤한다.
     세로 구성은 상단바 / (좌 미리보기 | 우 편집) / 푸터 세 층이다(푸터는 우측 칸 안쪽 맨 끝). */
  /* ⚠ 이 세 줄은 반드시 body.split-page 로 좁힌다 — 그냥 body 로 두면 이 파일을 함께 쓰는
     대시보드·관리자 화면까지 overflow:hidden 이 걸려 스크롤이 통째로 죽는다.
     범위는 :has() 로 잡는다(JSP 에 클래스를 다는 방식은 서버 재시작이 필요하다). */
  html{ height:100%; }
  body:has(.wrap--split){ height:100%; overflow:hidden; display:flex; flex-direction:column; }
  /* ⚠ 편집 화면에는 .topbar 가 없다(고정 줄 .ed-bar 로 바뀌었다). 이 규칙은 남겨 두어도
     해가 없지만, 세로 세 층 구성이 이제 "고정 줄 + 2단"임을 기억할 것. */
  /* 가운데 층 — 남는 높이를 전부 먹는다. min-height:0 이 없으면 내용이 밀어내 넘친다.
     ⚠ `width:100%` 를 빼지 말 것. `.wrap` 이 물려주는 `margin:0 auto` 는 이 세로 flex 안에서
       **가로 auto 마진**이라 `align-items:stretch` 를 무효로 만든다 — 그러면 2단 격자가
       내용 폭(fit-content)으로 줄어, **섹션을 열 때마다 좌우 칸 너비가 제각각**이 된다
       (목록 1234px ↔ 짧은 섹션 834px 로 요동쳤다). 폭을 못박으면 auto 마진은 가운데 정렬만 맡는다. */
  /* ⚠ 고정 줄의 좌우는 **본문과 같은 선**이어야 한다. `.ed-bar` 의 기본값은 1240px 기준이고
     `.wrap--split` 는 1300px + 24px 이라, 넓은 화면일수록 둘이 어긋났다(1600px 에서 6px).
     여기서 같은 계산으로 덮는다 — 한쪽 폭을 고치면 다른 쪽도 같이 고칠 것. */
  .ed-bar{
    padding-left: max(24px, calc((100vw - 1300px) / 2 + 24px));
    padding-right: max(24px, calc((100vw - 1300px) / 2 + 24px));
  }
  .wrap--split{
    flex:1 1 auto; min-height:0;
    width:100%;
    align-items:stretch;
    overflow:hidden;
    padding: 54px 24px 0;   /* 위는 고정 줄(.ed-bar) 자리 */
  }
  /* 좌측 — 스크롤도 없고 움직이지도 않는다.
     ⚠ padding-top 은 [PREVIEW·새로고침·새 창] 툴바를 내려 오른쪽 제목줄과 눈높이를 맞추는 실측값이다(42px).
       오른쪽 제목의 위치(wrap 패딩·pagehead 마진·「← 대시보드」 줄)가 바뀌면 다시 재야 한다.
     ⚠ box-sizing:border-box 라 이 패딩은 칸 높이를 늘리지 않는다(마스크 퍼센트는 영향 없다). */
  .wrap--split > .pv{
    grid-column:2; grid-row:1;
    position:static;
    height:100%; min-height:0;
    padding-top:42px;
    overflow:hidden;
  }
  /* 편집 칸 — 스크롤은 여기서만 일어난다 */
  .split__main{
    grid-column:1; grid-row:1;
    height:100%; min-height:0;
    overflow-y:auto; overflow-x:hidden;
    overscroll-behavior:contain;      /* 끝까지 내려도 뒤 페이지로 스크롤이 넘어가지 않는다 */
    padding-bottom:24px;
    /* 스크롤바는 패딩 박스 **바깥**(테두리 자리)에 그려진다 — 그래서 padding-right 를 주면
       막대는 그대로 두고 카드만 안으로 들어와 사이에 간격이 생긴다. 카드 폭은 그만큼 줄어든다. */
    padding-right:18px;
  }
  /* 우측 안쪽 요소는 원래 폭 규칙을 그대로 쓴다 */
  .split__main > *{ max-width:760px; width:100%; margin-left:0; }
  .split__main > *:not(:last-child){ margin-bottom:32px; }
  /* 마지막 항목(비밀번호 변경)과 푸터 사이는 한 칸만 */
  .split__main > .pw-link-row{ margin-bottom:8px; }
  /* 푸터 — 우측 스크롤 칸 맨 끝. 규격은 위 `.site-foot` 과 같다(좌 로고 / 우 저작권 한 줄). */
  .split__main > .site-foot{ max-width:none;
    padding:16px 2px 8px; margin-top:4px; }
  /* ── 우측 스크롤바 — 모노 지면에 맞춘 잉크색 막대 ──
     옛 하늘색을 걷고 페이지 전체 스크롤과 같은 무채색으로 맞춘다.
     ⚠ 이 스크롤바는 창이 아니라 .split__main 안쪽 것이라 페이지 전체 스크롤바와 무관하다. */
  .split__main{ scrollbar-width:thin; scrollbar-color:rgba(26,26,26,.28) transparent; }
.split__main::-webkit-scrollbar{ width:12px; }
  .split__main::-webkit-scrollbar-track{ background:transparent; }
  .split__main::-webkit-scrollbar-thumb{
    /* 안쪽으로 물러서게 해 막대가 벽에 붙지 않고 떠 있는 것처럼 보인다 */
    border:4px solid transparent; background-clip:padding-box;
    border-radius:999px;
    background-color:rgba(26,26,26,.22);
    box-shadow:none;
    transition:background-color .18s ease; }
  .split__main::-webkit-scrollbar-thumb:hover{ background-color:rgba(26,26,26,.38); }
  .split__main::-webkit-scrollbar-thumb:active{ background-color:rgba(26,26,26,.55); }
  .pv__bar{ display:flex; align-items:center; gap:8px; padding:0 4px; }
  .pv__spacer{ flex:1; }
  /* 새로고침 — 지면 위에 남는 유일한 손잡이라 글자 없이 아이콘만, 작게 둔다.
     ⚠ 여기에 라벨·배지를 다시 늘어놓지 말 것(2026-09-19 고객 지시). */
  .pv__refresh{ flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center;
    width:26px; height:26px; padding:0; border:none; border-radius:var(--r-pill);
    background:none; font-family:inherit; font-size:15px; line-height:1;
    color:var(--faint); cursor:pointer; transition:color .18s, background-color .18s; }
  .pv__refresh:hover{ color:var(--acc); background:var(--a05, rgba(0,0,0,.03)); }
  .pv__refresh:active{ transform:scale(.94); }
  /* ⚠ 기기 프레임은 실사 목업 PNG 다 — assets/social/mockups/iphone-15-pro-white-titanium.png (1419×2796).
     ★ 화면 자리는 알파 실측값이다(구멍은 완전 투명, left 120 / top 120 / 1179×2556):
         left  120/1419 = 8.457%     top    120/2796 =  4.292%
         width 1179/1419 = 83.087%   height 2556/2796 = 91.416%
     ⚠ 목업을 바꾸면 이 네 퍼센트와 iframe 높이를 함께 고쳐야 한다. */
  /* ★ **폰 베젤을 두지 않는다**(핸드오프 §Screen 2) — 지면 한 장을 radius 22px 패널로 세운다.
       베젤 목업(iphone-15-pro PNG 두 겹)은 폐기했다. 되살리지 말 것:
       기기 그림이 들어가면 그 안에서 지면이 한 단 더 축소돼 본문 글자가 실기기보다 작게 보인다
       (모바일 미리보기 카드에 같은 이유로 "축소·베젤 금지" 규칙이 있다).
     ⚠ 비율은 iframe 렌더 크기(402×872)와 **같아야** 한다 — 어긋나면 아래위에 빈 띠가 남는다. */
  .pv__phone{ flex:0 1 auto; min-height:0;
    aspect-ratio:402 / 872; height:100%; width:auto; max-width:100%; margin:8px auto 18px;
    position:relative; }
  /* ⚠ 모서리를 둥글리지 않는다 — 지면 한 장을 그대로 세운다(radius 0 이 이 지면의 기본이다).
     ⚠ **그림자를 두지 않는다**(2026-09-19 고객 지시). 아래로 28px 내려앉는 큰 그림자가 있었는데,
       지면과 같은 아이보리라 판이 떠 보이는 게 아니라 **바닥에 얼룩이 번진 것처럼** 보였다.
       경계는 헤어라인 한 줄이면 충분하다 — 이 지면의 정본은 그림자 없음이다. */
  .pv__screen{ position:absolute; inset:0;
    border-radius:0; overflow:hidden; background:var(--bg);
    box-shadow:inset 0 0 0 1px var(--line); }
  /* ★ iframe 은 402×872 로 렌더하고 패널에 맞춰 축소한다 — 그래야 글자 크기가 실기기와 같다.
       --pv-k 는 스크립트가 floor((폭-1)/402) 로 넣는다.
     ⚠ 배율은 내림이다 — 올리면 둥근 모서리 밖으로 지면이 삐져나온다.
     ⚠ 축소된(transform 걸린) iframe 은 부모의 overflow 로 잘리지 않아 clip-path 로 직접 자른다.
       모서리는 둥글리지 않는다 — 반경을 되살리려면 축소 배율 k 로 나눠 줘야 한다(그냥 22px 을
       적으면 축소된 만큼 작아 보인다). */
  .pv__screen iframe{ position:absolute; top:0; left:0;
    width:402px; height:872px; border:0; display:block;
    clip-path:inset(0);
    transform:scale(var(--pv-k, 1)); transform-origin:0 0; }

  /* ── 미리보기 로딩 ── 기다림 어휘는 화면마다 다르지 않다(.lilt-wait 와 같은 결).
     ⚠ 파란 shimmer 뼈대(가짜 사진·글줄)는 2026-09-21 에 걷었다 — 내용이 있는 척하는 그림이라
       실제 지면과 다르면 오히려 어수선했고, 색도 이 지면의 것이 아니었다. 되살리지 말 것.
     ⚠ display:flex 가 UA 의 [hidden]{display:none} 을 이기므로 [hidden] 규칙을 함께 둔다. */
  .pv__loading{ position:absolute; inset:0; z-index:2;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:0;
    padding:32px 26px; background:var(--bg);
    opacity:1; transition:opacity .32s ease; }
  .pv__loading[hidden]{ display:none; }
  .pv__loading.is-done{ opacity:0; pointer-events:none; }
  /* 뼈대는 감춘다 — 마크업은 남겨 두되(다른 화면이 같은 조각을 쓴다) 그리지 않는다 */
  .pv__skel{ display:none; }

  /* 워드마크 · 훑는 선 · 한 줄 — .lilt-wait 와 같은 짜임이다 */
  .pv__bar-wrap{ width:100%; display:flex; flex-direction:column; align-items:center; gap:14px; }
  .pv__bar-wrap::before{
    content:""; width:74px; height:40px;
    background-color:rgba(0,0,0,.3);
    -webkit-mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
            mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
    animation:liltBreath 1.9s ease-in-out infinite; }
  .pv__prog{ width:min(180px, 62%); height:1px; border-radius:0; overflow:hidden;
    background:rgba(0,0,0,.12); }
  .pv__prog span{ display:block; width:34%; height:100%; border-radius:0;
    background:var(--ink);
    animation:liltSweep 1.25s cubic-bezier(.65,.05,.36,1) infinite; }
  .pv__loading-t{ font-size:12px; font-weight:300; letter-spacing:-.01em; color:var(--soft); }

  @media (prefers-reduced-motion:reduce){
    .pv__prog span{ animation:none; width:100%; opacity:.45; }
    .pv__bar-wrap::before{ animation:none; opacity:.55; }
  }

  /* ★ 예식 일시 선택기 — 편집 컬럼이 760px 까지 넓어지면 .dt-day 가 aspect-ratio:1 이라
       날짜 한 칸이 100px 가까이 커져 오히려 읽기 나빠졌다. 폭을 묶어 한 칸을 52px 선에 둔다.
       (시간 입력 줄도 같은 컨테이너 안이라 함께 정리된다) */
  /* 편집 컬럼이 760px 까지 넓어져도 캘린더는 이 폭 안에서만 자란다.
     날짜 칸 높이를 고정해 두었으므로 폭이 늘어도 세로로 길어지지 않는다. */
  .dtpick{ max-width:470px; }
  /* 앨범 썸네일 — 폭이 넓어져도 한 장이 커지지 않게 칸 수를 늘린다(최소 96px) */
  .gallery-grid{ grid-template-columns:repeat(auto-fill, minmax(88px, 1fr)); gap:6px; }
  /* ⚠ **`>` 를 빼지 말 것.** 이 56px 은 지도처럼 스트립에 낱장으로 놓이는 썸네일의 크기다.
     앨범에서 새로 고른 사진은 `.pv-wrap` 에 싸여 그리드 칸을 꽉 채워야 하는데, 후손 선택자로
     두면 같은 명시도로 `.pv-wrap .pv` 의 100% 를 덮어(뒤에 있어서 이긴다) 칸 귀퉁이에
     56px 짜리가 박힌다 — 저장된 사진만 꽉 차고 방금 고른 것만 작아 보인다. */
  .preview-strip > .pv{ width:56px; height:56px; }

  /* 넓은 화면에서는 하단 붙박이 저장바를 쓰지 않는다 — 화면 아래를 가로로 가로막아
     미리보기 기기가 애매하게 잘렸다. 저장 버튼만 우하단 플로팅으로 띄운다.
     (모바일은 기존 붙박이 저장바 그대로 — 이 블록은 1024px 이상에서만 적용된다) */
  .savebar{ left:auto; right:30px; bottom:26px; width:auto;
    padding:0; background:none; border-top:none; box-shadow:none;
    -webkit-backdrop-filter:none; backdrop-filter:none; }
  /* ⚠ 붙박이 바를 비켜 주려고 body 아래에 둔 82px 을 여기서 되돌린다.
     플로팅에서는 비켜 줄 바가 없는데도 그 여백이 남아, 화면 맨 아래에 빈 띠가 깔리고
     그만큼 미리보기 기기가 잘렸다 — "저장바가 푸터처럼 보인다"의 정체다. */
  body:has(.savebar){ padding-bottom:0; }
  /* ⚠ display:block 으로 풀지 말 것 — 체험자 화면에는 버튼이 셋이다([보관함]·[임시 저장]·
     [결제하기]). 흐름 배치로 두면 글자 버튼과 아이콘 버튼이 baseline 으로 서서 열이 어긋난다. */
  .savebar__inner{ max-width:none; margin:0; padding:0;
    display:flex; align-items:center; justify-content:flex-end; gap:10px; }
  /* 공개 주소·안내 문구는 플로팅에서 뺀다. 주소는 상단 "공개 설정 · 주소" 섹션에서 볼 수 있다. */
  .savebar__url, .savebar__hint{ display:none; }

  /* ── 플로팅에서도 보조 동작은 **한 어휘**로 (모바일과 같은 규칙) ──
     ⚠ 결제 전 고객에게는 saveAllBtn 이 없다. 주 버튼에만 무게를 주면 [보관함]·[임시 저장]이
       선도 면도 없이 남아, 바닥 없는 지면 위에 흐린 글자만 떠 있게 된다(2026-09-21 지적).
     ⚠ 그림자는 여기서만 준다 — 받쳐 줄 바가 없어 지면에 묻히기 때문이다. 형태(선 1px ·
       radius 0 · 흰 면)는 모바일 저장바와 같은 것을 쓴다. */
  .savebar .btn,
  .savebar__box{ height:48px; box-shadow:0 14px 34px rgba(0,0,0,.28); }
  .savebar__box,
  .savebar .btn-quiet{
    border:1px solid var(--line); border-radius:0; background:#fff; color:var(--ink);
    transition:border-color .18s, color .18s; }
  .savebar__box{ width:48px; }
  .savebar .btn-quiet{ padding:0 18px; font-size:13px; font-weight:400; }
  .savebar__box:hover,
  .savebar .btn-quiet:hover{ border-color:var(--ink); background:#fff; color:var(--ink); }
  .savebar__dot{ top:12px; right:11px; }
  .savebar #saveAllBtn,
  .savebar #payOpenBtn{ padding:0 28px; border-radius:var(--r-pill); }
}

/* ═══ 1024~1279px — 노트북 가로. 기기 칸을 좁혀 편집 폭을 확보한다 ═══
   356px 그대로 두면 편집 컬럼이 570px 아래로 내려가 폼 두 칸(.wiz-pair)이 답답해진다. */
@media (min-width:1024px) and (max-width:1279px){
  .wrap--split{
    grid-template-columns:minmax(0,1fr) minmax(0,300px);
    column-gap:32px;
    padding:20px 18px 0;
  }
}

/* ═══ 고객 대시보드 지면 — **한 단 880px** ═══
   근거: design_handoff_lilt/README-customer-dashboard.md — "Column max-width for all three tabs:
   880px, centered — 탭을 옮겨도 지면이 흔들리지 않게 세 탭이 같은 폭을 쓴다."

   ⚠ PC 2단은 2026-09-20 에 걷었다. 한 장 스크롤이던 시절에는 760px 한 줄이 "모바일 페이지를
     크게 띄운 것" 같아 두 단으로 폈는데, 지금은 내용이 세 탭으로 나뉘어 한 단이 비지 않는다.
     **되살리려면 탭도 같이 걷어야 한다** — 둘은 한 쌍이다.
   ⚠ 탭 줄·패널·푸터가 모두 이 폭을 쓴다. 한 곳만 고치면 줄이 어긋난다. */
.wrap--cards{ max-width:880px; }

/* ═══ 운영자 콘솔 지면 ═══
   ⚠ 좌우 2단(.admin-grid)은 2026-09-19 에 걷었다 — 고객 탭이 한 판 표가 되면서 지면을
     쪼갤 이유가 없어졌고, 표를 절반 폭에 넣으면 일곱 열이 다 뭉갠다.
   ⚠ **읽기 칸은 1100px 중앙이다**(design_handoff_lilt/README-admin-console.md).
     한동안 와이드로 열어 두었는데(2026-09-19), 모노 핸드오프가 1100 으로 못박았다.
     상단바·탭·지면·푸터가 모두 이 값을 따라온다 — 한 곳만 고치면 줄이 어긋난다.
   ⚠ 일곱 열 표가 1100px 에 들어가려면 열 템플릿이 `minmax(0,Xfr)` 여야 한다.
     맨 `fr` 은 칸 내용보다 못 줄어들어 행마다 세로줄이 어긋난다. */
.adm-body{ --side:max(clamp(24px, 4vw, 64px), (100vw - 1100px) / 2); }
.wrap--admin{ max-width:none; padding:26px var(--side) 60px; }
/* ⚠ `width:100%` 를 빼지 말 것. `.wrap` 이 `margin:0 auto` 를 갖고 있는데, 세로 flex 안에서
   가로 auto 마진은 stretch 를 죽여 지면을 fit-content 로 줄인다 — 내용이 가운데로 몰린다.
   ⚠ 세로 flex 자체와 푸터 여백은 **admin-console.css** 가 쥔다(콘솔 전용 규칙은 그 파일 한 곳).
     여기에 다시 적어 두었더니 같은 말을 두 파일이 하고 있었다(2026-09-22 정리). */
.adm-body > .wrap--admin{ flex:1 0 auto; width:100%; }

/* ═══ QR 팝업 — 세로가 짧은 화면에서 한 화면에 담기게 조인다 ═══
   내용을 빼지 않고 여백만 줄인다. 그래도 아주 짧은 화면(뷰포트 600 미만)에서는 스크롤이 남는데,
   그때는 스크롤이 나는 편이 글자를 더 줄이는 것보다 낫다. */
@media (max-height:820px){
  #qrModal .modal__box{ max-height:92vh; }
  #qrModal .modal__head{ padding:16px 22px 12px; }
  #qrModal .modal__body{ padding:14px 22px; }
  #qrModal .qr-box{ padding:18px 0 2px; margin-top:2px; gap:8px; }
  #qrModal .qr-opt{ padding:11px 0; }
  #qrModal .qr-note{ margin-top:10px; }
  #qrModal .qr-tip{ margin-top:8px; }
  #qrModal .actions{ margin-top:12px; }
  #qrModal .qr-box img,
  #qrModal .qr-loading{ height:min(176px, 22vh); }
}

/* ═══ 모바일 미리보기 — PIP ═══ PC(1024px↑)에서는 보이지 않는다(거기선 패널이 늘 떠 있다).
   근거: design_handoff_lilt/README-mobile-live-preview.md.

   ⚠ **접힘과 펼침은 한 요소의 두 상태다.** 위치·크기를 transition 으로 이어 구석에서 자라게 한다 —
     모달처럼 갈아 끼우면 이 동작의 뼈대가 사라진다. 그래서 `display` 를 건드리지 않는다.
   ⚠ 접힘 규격은 핸드오프 값 그대로다: **110×182**, 오른쪽 20px · 아래 28px.
   ⚠ 지면은 언제나 402px 로 그리고 `--mpv-k` 로 줄인다(JS fitMobile). 보는 폭 그대로 그리면
     비율로 그린 오프닝 도형이 깨진다. 접힘에서는 세로가 넘쳐 잘리는데, 그게 맞다(표지만 보인다).
   ⚠ 폰 베젤(목업 PNG)은 쓰지 않는다 — 110px 판에 베젤을 두르면 지면이 더 줄어든다. */
.mpv{ display:none; }

@media (max-width:1023.98px){
  /* 접힘 — **화면 모양 아이콘 하나**(2026-09-21). 지면 조각을 띄우던 110×182 는 걷었다.
     ⚠ 크기·자리만 바뀌었을 뿐 **여전히 한 요소의 두 상태**다 — 눌렀을 때 이 자리에서
       자라나는 동작이 이 부품의 뼈대라, 모달로 갈아 끼우지 말 것. */
  .mpv{ display:block; position:fixed; z-index:60;
    right:18px; bottom:calc(88px + env(safe-area-inset-bottom));
    width:48px; height:48px;
    overflow:hidden; background:var(--ink); border-radius:999px; cursor:pointer;
    box-shadow:0 8px 22px -10px rgba(0,0,0,.55);
    transition:right .5s var(--ease-ios), bottom .5s var(--ease-ios),
               width .5s var(--ease-ios), height .5s var(--ease-ios),
               border-radius .38s var(--ease-ios), background-color .3s,
               box-shadow .5s var(--ease-ios); }
  .mpv:active{ transform:scale(.94); }
  /* 펼침 — 같은 요소가 구석에서 화면 전체로 자란다 */
  body.mpv-open .mpv{ right:0; bottom:0; width:100%; height:100%;
    background:#fff; border-radius:0; box-shadow:none; cursor:default; transform:none; }
  body.mpv-open{ overflow:hidden; }
  /* ⚠ **dvh 다**(svh 로 바꿨다가 되돌렸다, 2026-09-27) — 카드는 bottom:0 기준이라 svh 를 쓰면
     주소창이 접힌 순간 카드가 화면보다 작아져 **위가 댕강 잘린 것처럼** 빈다.
     아래가 먹히던 문제는 높이가 아니라 **iframe 논리 높이**(JS 의 --mpv-h)가 잡는다. */
  @supports (height:100dvh){ body.mpv-open .mpv{ height:100dvh; } }

  /* 지면 — 접혀 있을 때는 **누르는 판**이라 안쪽이 터치를 먹지 않게 한다.
     ⚠ pointer-events 를 빼면 접힌 판을 눌러도 iframe 이 먹어 펼쳐지지 않는다. */
  .mpv__screen{ position:absolute; inset:0; overflow:hidden; background:#fff;
    pointer-events:none; }
  body.mpv-open .mpv__screen{ pointer-events:auto; }
  .mpv__screen iframe{ position:absolute; top:0; left:0;
    width:402px; height:var(--mpv-h, 872px); border:0; display:block; background:#fff;
    transform:scale(var(--mpv-k, 1)); transform-origin:0 0; }

  /* 접힘의 얼굴 — 화면 모양 아이콘. 펼치면 사라진다.
     ⚠ 점 하나를 겹쳐 "살아 있는 화면"임을 남긴다. 이 파랑은 지면의 색이 아니라
       **살아 있음의 신호**라 다른 곳에 쓰지 않는다. */
  .mpv__icon{ position:absolute; inset:0; z-index:4;
    display:flex; align-items:center; justify-content:center; color:#fff;
    pointer-events:none; transition:opacity .2s; }
  .mpv__icon svg{ width:22px; height:22px; display:block; }
  .mpv__dot{ position:absolute; right:13px; top:13px;
    width:5px; height:5px; border-radius:50%; background:#4d78ff;
    animation:mpvBreathe 2s ease-in-out infinite; }
  @keyframes mpvBreathe{ 0%,100%{ opacity:.4 } 50%{ opacity:1 } }
  body.mpv-open .mpv__icon{ opacity:0; }
  /* 접혀 있을 때는 지면을 보여 주지 않는다 — 아이콘 하나가 얼굴이다 */
  body:not(.mpv-open) .mpv__screen, body:not(.mpv-open) .mpv__loading{ opacity:0; }

  /* 닫기 · 아래 버튼 줄 — 펼쳤을 때만 뜬다 */
  .mpv__x, .mpv__bar{ opacity:0; pointer-events:none; transition:opacity .2s .1s; }
  body.mpv-open .mpv__x, body.mpv-open .mpv__bar{ opacity:1; pointer-events:auto; }
  /* 닫기 — 지면 위에 뜨는 반투명 유리 원. */
  /* ⚠ 테두리는 **아주 옅은 회색**이다(2026-09-28) — 예전엔 흰색 반투명이라 지면이 흰
     템플릿 위에서는 버튼의 윤곽이 통째로 사라졌다. 흰 바탕과 겨우 갈릴 만큼만 얹는다. */
  .mpv__x{ position:absolute; z-index:5;
    top:calc(14px + env(safe-area-inset-top)); right:12px;
    width:40px; height:40px; display:grid; place-content:center;
    border:1px solid rgba(38,37,34,.10); border-radius:50%;
    background:rgba(244,243,241,.58); color:var(--ink);
    font-size:15px; line-height:1; cursor:pointer;
    -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
    text-shadow:none; box-shadow:0 8px 24px -16px rgba(0,0,0,.48); }
  .mpv__x:active{ opacity:.6; }
  .mpv__bar{ position:absolute; z-index:5; left:0; right:0;
    bottom:calc(16px + env(safe-area-inset-bottom));
    display:flex; align-items:center; justify-content:center; gap:10px; }
  /* 아래 두 동작 — 청첩장을 가리지 않는 반투명 유리 버튼. */
  .mpv__btn{ min-height:40px; padding:0 18px;
    border:1px solid rgba(38,37,34,.10); border-radius:999px;
    background:rgba(244,243,241,.58); color:var(--ink); cursor:pointer;
    font-family:inherit; font-size:13px; font-weight:400; letter-spacing:-.01em;
    -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
    box-shadow:0 10px 28px -18px rgba(0,0,0,.52); transition:opacity .16s; }
  .mpv__btn:active{ opacity:.7; }

  .mpv__loading{ position:absolute; inset:0; z-index:2;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:11px;
    background:#fff; transition:opacity .3s ease; }
  .mpv__loading[hidden]{ display:none; }
  .mpv__loading.is-done{ opacity:0; pointer-events:none; }
  /* 접힌 판에서는 글자가 들어갈 자리가 없다 — 점만 돈다 */
  .mpv__loading-t{ font-size:12px; color:var(--soft); letter-spacing:-.01em; }
  body:not(.mpv-open) .mpv__loading-t{ display:none; }
  /* 반짝이는 별 — PC 미리보기(.pv__prog)·첫 화면 샘플 미리보기(.tpv__spark)와 같은 스프라이트.
     ⚠ 12칸 · 384px · steps(12) 는 한 벌이다(아래 liltSpark 블록 주석 참조). */
  .mpv__spin{ display:block; position:relative; width:32px; height:32px; overflow:hidden; }
  .mpv__spin::before{ content:""; display:block; position:absolute; top:0; left:0;
    width:384px; height:32px;
    background:url(../bridge/spark.png) 0 0/384px 32px no-repeat;
    transform:translate3d(0,0,0); will-change:transform;
    animation:liltSpark 1.5s steps(12) infinite; }
  @media (prefers-reduced-motion:reduce){
    .mpv__spin::before{ animation:liltBreath 1.9s ease-in-out infinite; }
    .mpv__live i{ animation:none; }
    .mpv{ transition:none; }
  }
}

/* ═══════════════ 운영자 콘솔 — 소멸 임박 · 비밀번호 초기화 ═══════════════ */
/* 소멸은 사진까지 되돌릴 수 없게 지우는 작업이라, 이 카드만 색으로 눈에 걸리게 둔다.
   ⚠ 이 톤은 운영자 화면 전용이다 — 청첩장 템플릿에는 소멸 안내를 넣지 않는다. */
.card--warn{ border-color:rgba(154,74,48,.22); background:linear-gradient(180deg, rgba(154,74,48,.04), var(--card) 120px); }
.card--warn > h2{ color:var(--danger); }
.badge-warn{ background:rgba(154,74,48,.07); color:var(--danger); }

/* 값이 여럿인 상세 행 — 라벨 옆에 배지·안내가 나란히 온다.
   ⚠ .info-row .v 의 white-space:pre-line 을 끈다. 그대로 두면 마크업 개행이 빈 줄로 렌더돼
     행이 세로로 벌어진다(초대 문구 때문에 .v 자체의 pre-line 은 남겨 둬야 한다). */
.info-row .v-inline{ white-space:normal; display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  min-height:calc(14px * 1.55); }

/* ═══════════════ 운영자 콘솔 — 고객 상세 팝업의 글 ═══════════════ */
/* 이 팝업 안에는 값 · 배지 · 안내문 · 입력칸이 섞여 있다. 크기와 색으로 세 단을 만든다:
     값(14px 잉크) > 라벨·요약(12.5~13px 흐린 잉크) > 안내문(12px 더 흐리게).
   ⚠ `.hint` 는 전역 기본 규칙이 없다 — 여기서 주지 않으면 본문과 같은 크기·같은 색으로
     나와 안내문이 값처럼 읽힌다. */
.modal__body .hint,
.gb-admin .hint{ font-size:12px; font-weight:400; line-height:1.65; color:var(--faint);
  letter-spacing:0; }
.modal__body .hint b,
.gb-admin .hint b{ font-weight:600; color:var(--soft); }

/* 접이식 영역 — 요약 줄과 그 아래 안내문·입력칸의 간격을 한 규칙으로 잡는다. */
.gb-admin > summary{ font-size:13px; }
.gb-admin > .hint{ margin-top:8px; }
.gb-admin > form + .hint{ margin-top:10px; }
.gb-admin > summary + .hint{ margin-bottom:10px; }

/* 상세 행 — 라벨은 값보다 작고 흐리게, 값이 주인공이다. */
.info-row .k{ font-size:12.5px; letter-spacing:.01em; }
/* 라벨 옆에 붙는 짧은 안내("122일 남음" 등)는 배지와 같은 줄에서 한 단 물러나 보여야 한다. */
.info-row .v-inline .hint{ font-size:12px; }

/* ── 상태 알약 팔레트 ── 승인됨·공개중·대기·지남이 저마다 다른 색을 쥔다(2026-09-22).
   그 전에는 on/off 가 같은 회색이었고 warn 과 danger 는 **완전히 같은 값**이라, 알약이
   상태를 알려 주지 못하고 자리만 차지했다.

   ⚠ 아이보리 지면(#f4f3f1) 위에서 **채도를 낮게** 둔다 — 원색 배지를 붙이면 지면이
     대시보드가 아니라 경고판처럼 읽힌다. 면은 옅게, 글자는 같은 색상의 어두운 쪽으로.
   ⚠ 배지는 **배경이 보여야** 배지다. 3a 글래스 규칙이 .pill-off 를 반투명 흰색으로 덮어
     흰 팝업 위에서 배경이 사라졌고 "미발급"·"비공개"가 그냥 글씨로 보인 적이 있다.
   ⚠ 이 넷은 한 벌이다 — 하나만 고치면 서로 구별되지 않는다. */
/* 다 된 것 — 승인됨 · 공개중 · 요금제 확정. 세이지 */
.pill-on{ background:#e6ece6; color:#4c6b54; border:1px solid transparent; }
/* 기다리는 것 — 입금 확인 대기 · 소멸 D-n. 황토 */
.pill-warn{ background:#f2ebda; color:#8a6a33; border:1px solid transparent; }
/* 손이 필요한 것 — 소멸 지남. 테라코타(지면에서 가장 진한 알약이다) */
.pill-danger{ background:#f0e0db; color:var(--danger); border:1px solid transparent; }
/* 아직인 것 — 미입력 · 비공개 · 체험 중. 미색 회색(색을 쥐지 않는다) */
.pill-off{ background:#eae7e3; color:#8b857e; border:1px solid transparent; font-weight:450; }

/* 좁은 화면 대비 — 상자는 flex item 이라 기본값 min-width:auto 면 내용의 최소 폭 아래로
   줄지 않는다. 글상자·버튼이 길어져도 팝업이 화면을 넘지 않게 못박아 둔다. */
.modal__box{ min-width:0; }
.modal__body textarea,
.modal__body input{ min-width:0; max-width:100%; }
.modal__foot{ flex-wrap:wrap; row-gap:8px; }

/* 상세 팝업의 접이식 영역(비밀번호 초기화·템플릿 변경·예식일·소멸 미루기).
   ⚠ 입력·선택·버튼이 **한 줄에서 높이가 맞아야** 한다. 예전에는 select 에만 규칙이 없어
     브라우저 기본 모양(각진 테두리·다른 높이)으로 튀어나왔다.
     그래서 아래 규칙은 input 과 select 를 **같이** 잡는다 — 한쪽만 고치지 말 것. */
.pw-reset{ display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.pw-reset input,
.pw-reset select{ flex:1; min-width:0; height:38px; padding:0 12px;
  border:1px solid var(--line); border-radius:var(--r-field, 11px);
  background:var(--gl-field, #fff); font-family:inherit; font-size:13px; color:var(--ink); }
.pw-reset input:focus,
.pw-reset select:focus{ outline:none; border-color:var(--acc); }
.ext-days{ flex:none; height:38px; padding:0 12px; border:1px solid var(--line);
  border-radius:var(--r-field, 11px); background:var(--gl-field, #fff);
  font-family:inherit; font-size:13px; color:var(--ink); }
.ext-days:focus{ outline:none; border-color:var(--acc); }
/* 고르는 칸은 기본 화살표를 지우고 같은 모양의 화살표를 직접 그린다 —
   기본 화살표를 두면 OS 마다 폭이 달라 옆 버튼과의 간격이 들쭉날쭉해진다. */
.pw-reset select,
select.ext-days{ -webkit-appearance:none; appearance:none; padding-right:30px; cursor:pointer;
  background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236b7688' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 11px center; }
/* ── 예식장 찾기 ── 편집 화면의 상호 검색. 고르면 이름·주소·좌표가 한 번에 채워진다.
   ⚠ 지면 어휘를 따른다 — 면을 두르지 않고 헤어라인으로만 나눈다(radius 0 · 그림자 없음). */
.vsearch{ margin-bottom:18px; }
/* 칸 위 안내 한 줄 — 눌러 보기 전에 무엇을 해 주는지 알린다. */
.vsearch__tip{ margin:-4px 0 8px; font-size:12px; font-weight:300; color:var(--faint);
  letter-spacing:-.01em; }
.vsearch__tip b{ font-weight:500; color:var(--soft); }
.vsearch__bar{ display:flex; gap:8px; align-items:center; }
.vsearch__bar input{ flex:1; min-width:0; }
.vsearch__bar .btn{ flex:none; }
/* 결과는 칸 아래로 흐른다 — 팝오버로 띄우면 좁은 화면에서 아래 칸을 가린다. */
.vsearch__list{ display:flex; flex-direction:column; margin-top:10px;
  border-top:1px solid var(--line); }
.vsearch__list[hidden]{ display:none; }   /* [hidden] 짝 규칙 */
.vsearch__item{ display:block; width:100%; padding:11px 2px; border:0;
  border-bottom:1px solid var(--line-soft); background:none; cursor:pointer; text-align:left;
  font-family:inherit; transition:background-color .14s; }
.vsearch__item:hover{ background:rgba(0,0,0,.03); }
.vsearch__item b{ display:block; font-size:14px; font-weight:450; color:var(--ink);
  letter-spacing:-.01em; }
.vsearch__item span{ display:block; margin-top:3px; font-size:12.5px; font-weight:300;
  color:var(--soft); }
.vsearch__msg{ margin-top:8px; font-size:12.5px; font-weight:300; color:var(--faint); }
.vsearch__msg[hidden]{ display:none; }
/* 좌표를 쥐고 있다는 표시 — 값이 아니라 안심시키는 한 줄이라 아주 옅게. */
.vsearch__pin{ margin-top:6px; font-size:11.5px; font-weight:300; color:var(--faint); }
.vsearch__pin[hidden]{ display:none; }

/* ── 날짜 고르기 ── 브라우저 기본 달력 대신 콘솔 어휘로 그린 달력(admin.jsp 의 스크립트).
   ⚠ 콘솔의 면은 **사각**이다(핸드오프 §7 · 토큰의 radius 0) — 둥근 모서리·그림자를 붙이지 말 것.
   ⚠ 팝오버는 fixed 이고, 열릴 때 스크립트가 <body> 로 옮긴다 — 팝업 상자 안에 두면
     그 상자의 transform(열기 애니메이션 잔상) + overflow:hidden 에 잘려 보이지 않는다. */
.ldate{ position:relative; display:block; min-width:0; }
/* 예식일처럼 줄 하나를 혼자 쓰는 칸은 남는 폭을 다 쓴다 — 날짜가 답답해 보이지 않게. */
.ldate--wide{ flex:1 1 auto; }
.ldate__in{ width:100%; cursor:pointer; }
.ldate__pop{ position:fixed; z-index:1200; width:252px; padding:12px;
  background:#fff; border:1px solid var(--line); border-radius:0; box-shadow:none; }
/* ⚠ [hidden] 짝 — display 를 준 요소는 브라우저 기본 [hidden] 이 명시도에서 밀린다. */
.ldate__pop[hidden]{ display:none; }
.ldate__hd{ display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; }
.ldate__ym{ font-size:13px; font-weight:450; color:var(--ink); letter-spacing:.02em; }
.ldate__nav{ width:26px; height:26px; padding:0; border:0; background:none; cursor:pointer;
  font-family:inherit; font-size:16px; line-height:1; color:var(--soft); transition:color .16s; }
.ldate__nav:hover{ color:var(--ink); }
.ldate__grid{ display:grid; grid-template-columns:repeat(7,1fr); gap:1px; }
.ldate__w{ height:22px; display:grid; place-items:center; font-size:11px; color:var(--faint); }
.ldate__d{ height:29px; padding:0; border:0; border-radius:0; background:none; cursor:pointer;
  font-family:inherit; font-size:12.5px; color:var(--ink); transition:background-color .14s; }
.ldate__d:hover:not(:disabled){ background:rgba(0,0,0,.06); }
.ldate__d:disabled{ color:var(--faint); opacity:.35; cursor:default; }
/* 오늘은 밑줄 하나로만 짚는다 — 고른 날(채운 면)과 섞이지 않게. */
.ldate__d.is-today{ text-decoration:underline; text-underline-offset:3px; }
.ldate__d.is-on{ background:var(--ink); color:#fff; }
.ldate__ft{ display:flex; gap:14px; justify-content:flex-end; margin-top:9px;
  padding-top:9px; border-top:1px solid var(--line-soft); }
.ldate__act{ padding:0; border:0; background:none; cursor:pointer;
  font-family:inherit; font-size:12px; color:var(--soft); transition:color .16s; }
.ldate__act:hover{ color:var(--ink); }
/* 접이식 영역 안의 안내문은 summary 아래에 붙어 한 덩어리로 읽혀야 한다 */
.gb-admin > .hint,
.gb-admin > form + .hint{ line-height:1.6; }
.gb-admin > form{ margin-top:10px; }

/* ═══════════════ 운영자 콘솔 — 템플릿 판매가 ═══════════════ */
/* 여섯 줄뿐이라 표를 쓰지 않는다. 번호·이름·금액이 한 줄에 앉고, 금액칸만 오른쪽에 고정폭으로
   떨어져 세로로 가지런히 읽힌다(금액을 훑을 때 눈이 한 축만 따라가면 된다). */
/* ⚠ 흰 카드(테두리로 두른 상자 + radius + 흰 행)로 되돌리지 말 것 — 행마다 위쪽 헤어라인
   한 줄이 이 지면의 목록 어휘다(고객 목록·섹션 목록과 같다). */
.prices{ border:0; border-radius:0; background:none; }
.price-row{ display:flex; align-items:flex-start; gap:12px; padding:13px 2px;
  border-top:1px solid var(--line); background:none; }
.price-no{ flex:none; width:22px; font-size:11px;
  letter-spacing:.1em; color:var(--faint); }
.price-name{ flex:1; min-width:0; font-size:13.5px; font-weight:450; color:var(--ink);
  display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
/* 값이 비어 있는 줄에만 나온다. 첫 화면에 금액이 안 걸린다는 사실이 목록에서 바로 보여야 한다
   (코드에 기본가가 없으므로, 비어 있으면 정말로 "가격 문의"가 나간다). */
.price-ask{ font-style:normal; font-size:11px; font-weight:400; color:var(--faint);
  padding:2px 7px; border-radius:999px; background:rgba(0,0,0,.05); }
.price-input{ flex:none; display:flex; align-items:center; gap:6px; }
/* 다른 입력과 같은 어휘 — 밑줄 하나 */
.price-input input{ width:110px; padding:6px 2px; border:0;
  border-bottom:1px solid var(--line); border-radius:0; background:none;
  font-family:inherit; font-size:16px; font-weight:300; color:var(--ink); text-align:right; }
.price-input input:focus{ outline:none; border-bottom-color:var(--acc); }
.price-input b{ flex:none; font-size:12.5px; font-weight:500; color:var(--soft); }

/* 첫 화면 노출 스위치 — 끄면 브릿지 카드에서 빠지고 샘플 주소도 막힌다.
   ⚠ 금액칸 오른쪽에 고정폭으로 붙인다. 스위치만 덩그러니 두면 무엇을 켜고 끄는지 알 수 없어
     작은 글자로 "노출"을 달아 둔다(체크박스 자체에는 aria-label 이 따로 있다). */
.price-sw{ flex:none; display:flex; align-items:center; gap:7px; }
.price-sw b{ flex:none; font-size:11.5px; font-weight:500; color:var(--soft); }
/* 내려 둔 줄에만 나온다. 목록을 훑을 때 "지금 안 팔고 있다"가 바로 보여야 한다. */
/* ⚠ 색은 토큰(--danger)만 쓴다 — 여기서 새 빨강을 만들면 지면에 없는 색이 하나 더 생긴다. */
.price-off{ font-style:normal; font-size:11px; font-weight:450; color:var(--danger);
  padding:2px 7px; border-radius:999px; background:rgba(154,74,48,.08); }

/* 좁은 화면 — 한 줄에 번호·이름·금액·스위치를 다 세우면 스위치가 카드 밖으로 밀려난다.
   줄바꿈에 맡기면 배지가 붙은 줄만 높이가 달라져 금액칸이 세로로 어긋난다.
   그래서 격자로 바꿔 번호는 두 줄에 걸쳐 두고, 아래 줄에 금액과 스위치를 나란히 앉힌다. */
@media (max-width:520px){
  .price-row{ display:grid; grid-template-columns:22px 1fr auto;
    grid-template-areas:"no name name" "no input sw";
    column-gap:10px; row-gap:9px; align-items:center; padding:13px 2px; }
  /* 번호는 첫 줄(이름)에 맞춘다 — 가운데로 두면 두 줄짜리 행에서 이름과 한참 어긋난다 */
  .price-no{ grid-area:no; align-self:start; padding-top:3px; }
  .price-name{ grid-area:name; font-size:14px; gap:6px; }
  .price-input{ grid-area:input; min-width:0; }
  /* 고정폭을 버리고 남는 폭을 다 쓴다 — 칸의 왼쪽 끝이 이름과 같은 선에서 시작한다.
     ⚠ 글자는 16px 아래로 내리지 않는다(iOS 가 포커스 때 화면을 확대해 버린다). */
  .price-input input{ width:100%; font-size:16px; padding:7px 2px; }
  .price-sw{ grid-area:sw; justify-self:end; }
}


/* ═══════════════ 운영자 콘솔 — 탭 · 대시보드 ═══════════════
   근거: 바탕화면 design_handoff_lilt/README.md — Screen 3.
   ⚠ 여기서 새 색을 만들지 않는다. 위 :root(=lilt-tokens.css)만 쓴다. */

/* 탭 — 화면만 갈아 끼운다. 숨은 탭의 폼·모달은 DOM 에 그대로 남아 있다.
   ⚠ [hidden] 이 아니라 클래스로 여닫는다 — 안의 폼이 hidden 속성 때문에
     제출에서 빠지는 일이 없도록. */
/* ⚠ 탭 id 는 주소의 해시로도 쓰인다 — #tab-tpl 로 직접 열면 브라우저가 그 자리로 스크롤한다.
   상단바가 sticky 라 그만큼 비워 두지 않으면 제목이 바 밑에 깔린다. */
.tabpane{ display:none; scroll-margin-top:120px; }
.tabpane.on{ display:block; animation:riseIn .42s var(--e-in, cubic-bezier(.22,.61,.36,1)) both; }

/* 면을 두르지 않는 카드 — 대시보드처럼 지면에 바로 놓이는 자리에 쓴다.
   ⚠ 아이보리 지면 위에서는 흰 카드가 따로 떠 보인다. 조회 전용 화면은 평면이 맞다.
   ⚠ 위 3a 블록의 `.card` 뒤에 와야 이긴다 — 앞으로 옮기지 말 것. */
.card--flat{ background:none; border:0; box-shadow:none; padding:0;
  -webkit-backdrop-filter:none; backdrop-filter:none; }

/* ⚠ 탭 줄은 **상단바 안이 아니라 콘텐츠 칼럼 안**이다(design_handoff_lilt).
   그래서 좌우 여백은 지면(.wrap)이 이미 쥐고 있다 — 여기에 --side 를 다시 주지 말 것.
   ⚠ 선택 표시는 밑줄 하나뿐이다. 알약·면·색을 붙이지 않는다. */
.tabs{ display:flex; gap:24px; padding:0; margin:0 0 26px;
  border-bottom:1px solid var(--line-soft); }
.tab{ position:relative; border:none; background:none; padding:0 0 12px; cursor:pointer;
  font-family:inherit; font-size:14px; font-weight:400; color:var(--soft);
  transition:color .2s; }
.tab::after{ content:""; position:absolute; left:0; right:0; bottom:-1px; height:1.5px;
  background:transparent; transition:background-color .24s; }
.tab:hover{ color:var(--ink); }
.tab.on{ color:var(--ink); font-weight:500; }
.tab.on::after{ background:var(--ink); }
/* 탭에 붙는 건수 — 승인 대기처럼 "지금 손이 필요한" 수만 붙인다.
   ⚠ 0 건이면 JSP 가 아예 그리지 않는다(빈 배지가 뜨면 처리할 것이 있는 줄 안다). */
.tab__n{ display:inline-flex; align-items:center; justify-content:center;
  min-width:17px; height:17px; margin-left:6px; padding:0 5px;
  border-radius:999px; background:var(--acc); color:#fff;
  font-size:10.5px; font-weight:500; letter-spacing:0; vertical-align:1px; }

/* SYSTEM 줄 — "지금 서버가 어떤 상태인가"를 한 줄로. 조회 전용이라 값을 바꾸는 버튼을 두지 않는다
   (탭을 옮기는 [고객 목록] 은 예외다 — 화면을 바꾸기만 한다). */
.sysline{ display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding-bottom:18px; margin-bottom:22px; border-bottom:1px solid var(--line); }
.sysline__v{ font-size:13px; font-weight:300; color:var(--soft); }
.sysline__v b{ color:var(--ink); font-weight:450; }
.sysline__v.is-stale b, .sysline__v.is-warn{ color:var(--danger); }
.sysline__v.is-none{ color:var(--faint); }
.sysline__v .hint{ margin-left:5px; }
.sysline__bar{ width:1px; height:11px; background:var(--line); }
.sysline__sp{ flex:1; }
.sysline__go{ border:none; background:none; padding:0; cursor:pointer;
  font-family:inherit; font-size:12.5px; color:var(--cobalt); transition:opacity .16s; }
.sysline__go:hover{ opacity:.66; }

/* KPI — 카드가 아니라 1px 헤어라인 격자다. 칸 사이 선은 배경색이 비쳐 생긴다. */
/* ⚠ 컨테이너를 선 색으로 칠하고 1px gap 으로 줄을 내는 방식으로 되돌리지 말 것 —
   칸 수가 열 수로 나눠떨어지지 않으면 **빈 칸이 회색 덩어리**로 남는다(5칸 2열에서 발견).
   칸마다 위쪽 헤어라인 한 줄이면 빈 칸은 아무것도 그리지 않는다. */
.kpis{ display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%,150px),1fr));
  gap:0 1px; margin-bottom:6px; background:none; }
.kpi{ padding:18px 18px 20px; background:none; border-top:1px solid var(--line); }
.kpi__l{ font-size:11.5px; color:var(--soft); letter-spacing:-.01em; }
.kpi__n{ margin-top:9px; font-size:27px; font-weight:300; letter-spacing:-.03em; color:var(--ink);
  display:flex; align-items:baseline; gap:6px; }
.kpi__n.is-warn{ color:var(--danger); }
/* 한 칸에 여러 숫자를 넣을 때(고객·청첩장) 뒤쪽은 한 단계 낮춘다 */
.kpi__s{ font-size:16px; font-weight:300; color:var(--faint); letter-spacing:-.01em; }

.dash-sub{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  margin:38px 0 14px; font-size:19px; font-weight:300; letter-spacing:-.018em; color:var(--ink); }
.dash-sub .eyebrow{ flex:0 0 100%; }

/* 방문 추이 — 코발트 유리 막대. 뒤에는 눈금 네 줄만 깔린다.
   ⚠ 값이 0 인 날도 칸을 남긴다. 빠지면 날짜 축이 어긋나 추세를 잘못 읽는다.
   ⚠ 흰 유리 패널(흰 그라데이션 + 흰 림 + radius 18px)로 되돌리지 말 것 — 폐기된 3a 의 카드다.
     눈금은 그림이지 면이 아니다. */
.vgraph{ position:relative; display:flex; align-items:flex-end; justify-content:space-between;
  gap:9px; height:170px; }
/* 눈금 네 줄 — 막대 뒤에 깔린다(그리기만 하는 층이라 클릭을 받지 않는다) */
.vgraph::before{ content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:repeating-linear-gradient(180deg, rgba(0,0,0,.06) 0 1px, transparent 1px 25%); }
.vbar-col{ position:relative; z-index:1; flex:1 1 0;
  display:flex; flex-direction:column; align-items:center; height:100%; min-width:0; }
.vbar-track{ flex:1; width:100%; display:flex; align-items:flex-end; justify-content:center; }
/* 막대 — 유리 기둥. 위쪽 하이라이트 림과 측면 광택이 재질을 만든다. */
/* ⚠ 납작한 막대다 — 알약도, 그러데이션도, 유리도 아니다(폐기된 글래스 어휘). */
.vbar{ position:relative; width:74%; max-width:14px; min-height:3px; overflow:hidden;
  border-radius:0;
  background:rgba(0,0,0,.16);
  box-shadow:none;
  transition:background .24s, transform .24s var(--e-spring, cubic-bezier(.34,1.56,.64,1)); }
/* 유리 기둥의 광택 — 왼쪽에서 22% 폭으로 흐르는 흰 띠 */
.vbar::before{ content:""; position:absolute; left:14%; top:0; bottom:0; width:22%;
  border-radius:999px;
  background:linear-gradient(180deg,rgba(255,255,255,.5),rgba(255,255,255,0)); }
.vbar.zero{ background:rgba(0,0,0,.08); box-shadow:none; }
/* 기둥 안쪽의 진한 칸 — 그날 방문자 수. 막대 전체(조회 수)에서 차지하는 비율만큼 아래부터 찬다.
   ⚠ 높이가 0 이면 마크업 자체를 그리지 않는다(JSP) — 집계 이전 날짜를 "0 명"으로 보이게 하면 안 된다.
   ⚠ 광택 띠(::before) 위에 와야 비율이 읽히므로 z-index 를 못박는다. */
.vbar__u{ position:absolute; left:0; right:0; bottom:0; z-index:1;
  border-radius:999px; background:var(--cobalt); opacity:.88; }
.vbar-lab{ font-size:9.5px; color:var(--faint); margin-top:6px; }
/* 그래프 아래 한 줄 안내(집계 이전 구간 등). 문단이 아니라 덧말이라 한 단계 낮춘다. */
.dash-note{ margin:-4px 0 12px; font-size:12px; font-weight:300; color:var(--faint); }

/* ── 막대에 손을 대면 그날 수치를 띄운다 ── title 속성만으로는 모바일에서 아예 뜨지 않는다.
   ⚠ 말풍선 자리는 그래프 위쪽에 비워 둔 띠다(padding-top) — 막대 위에 겹치면 가장 높은 막대를 가린다.
   ⚠ pointer-events:none. 안 그러면 말풍선이 자기가 가리키던 막대를 가로채 깜빡인다. */
.vgraph-wrap{ position:relative; padding-top:30px; }
/* ⚠ display 를 주는 요소라 hidden 속성만으로는 안 감춰진다 — 브라우저 기본
   [hidden]{display:none} 이 명시도에서 밀린다. 짝을 반드시 함께 둔다. */
.vtip[hidden]{ display:none; }
.vtip{ position:absolute; top:0; left:0; z-index:2; pointer-events:none;
  display:flex; align-items:baseline; gap:6px; white-space:nowrap;
  padding:4px 9px; border-radius:999px; background:var(--ink); color:#fff;
  box-shadow:0 4px 12px rgba(0,0,0,.18); }
.vtip__n{ font-size:12.5px; font-weight:700; letter-spacing:-.02em; }
.vtip__n::after{ content:'회'; margin-left:1px; font-size:10.5px; font-weight:500; opacity:.72; }
.vtip__d{ font-size:11px; font-weight:500; opacity:.72; }
/* 짚고 있는 막대 — 말풍선과 같은 색으로 바꿔 둘이 한 쌍임을 보인다.
   ⚠ 0 회 막대(.zero)도 짚으면 색이 들어온다. 안 그러면 "안 짚혔나?" 싶어 다시 누르게 된다. */
/* 짚고 있는 막대 — 진해지고 살짝 늘어난다(말풍선과 한 쌍임을 보인다).
   ⚠ 0 회 막대(.zero)도 짚으면 색이 들어온다. 안 그러면 "안 짚혔나?" 싶어 다시 누르게 된다. */
.vbar-col.on .vbar{ background:var(--ink);
  transform:scaleY(1.03); }
.vbar-col.on .vbar.zero{ background:rgba(0,0,0,.22); }
.vbar-col.on .vbar-lab{ color:var(--ink); font-weight:500; }

/* 샘플 열람 순위 — 숫자만 나열하면 비교가 안 돼서 1위 대비 점유율 막대를 함께 그린다.
   이름·횟수는 한 줄, 막대는 그 아래 2px 선으로 깔린다(핸드오프 §Screen 3). */
.rank{ list-style:none; margin:0; padding:0; }
.rank__i{ display:grid; grid-template-columns:auto 1fr auto; align-items:baseline;
  column-gap:10px; padding:13px 0; border-top:1px solid var(--line); }
/* ⚠ 자리를 **네 칸 모두** 못박는다. 마크업 순서가 [번호][이름][막대][횟수]라서, 행을 비워 두면
   전폭 막대가 2행을 먹고 횟수가 3행 왼쪽으로 떨어진다(자동배치 커서는 되돌아가지 않는다). */
.rank__no{ grid-column:1; grid-row:1; font-size:11px; letter-spacing:.1em; color:var(--faint); }
.rank__nm{ grid-column:2; grid-row:1; min-width:0; font-size:14px; font-weight:350; color:var(--ink);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rank__c{ grid-column:3; grid-row:1; text-align:right; font-size:13.5px; font-weight:300; color:var(--soft); }
/* 조회 수 뒤에 붙는 사람 수. 순위 기준이 아니므로 한 단계 낮춰 적는다. */
.rank__u{ margin-left:7px; font-style:normal; font-size:11.5px; color:var(--faint); }
.rank__bar{ grid-column:1 / -1; grid-row:2; margin-top:9px; height:2px;
  background:var(--line); overflow:hidden; }
.rank__bar i{ display:block; height:100%; background:var(--cobalt); min-width:2px;
  transition:width .5s var(--e-in, cubic-bezier(.22,.61,.36,1)); }

@media (max-width:520px){
  .kpi__n{ font-size:20px; }
  .rank__nm{ width:82px; font-size:12.5px; }
  .vgraph{ height:96px; }
}

/* 예식일 잠금(고객) — 예식일 당일부터는 날짜를 못 바꾼다.
   ⚠ 입력칸을 disabled 로 두지 않고 아예 다른 블록으로 바꾼다. 회색 입력칸은 "왜 안 눌리지"로
     읽히지만, 값 + 이유를 함께 보여 주면 묻지 않아도 알 수 있다. */
.wed-locked{ padding:14px 16px; border:1px solid var(--line); border-radius:var(--r-field, 11px);
  background:var(--gl-field, #fff); }
.wed-locked__d{ display:block; font-size:15px; font-weight:450; color:var(--ink);
  letter-spacing:-.02em; }
.wed-locked__m{ display:block; margin-top:6px; font-size:12px; line-height:1.5; color:var(--faint);
  word-break:keep-all; }

/* 대시보드 기간 선택 */
.range{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:16px; }
/* 다른 입력과 같은 어휘 — 밑줄 하나. ⚠ 16px 아래로 내리지 말 것(iOS 가 포커스 때 확대한다).
   ⚠ 날짜 칸은 type=date 가 아니라 .ldate__in 이다(달력을 직접 그린다) — 둘 다 적어 둔다. */
.range input[type="date"], .range .ldate__in{ padding:7px 2px; border:0;
  border-bottom:1px solid var(--line); border-radius:0; background:none;
  font-family:inherit; font-size:16px; font-weight:300; color:var(--ink); }
.range input[type="date"]:focus, .range .ldate__in:focus{ outline:none; border-bottom-color:var(--acc); }
/* 달력을 감싼 칸이 이제 flex 항목이다 — 글자 폭만 차지하게 둔다(두 칸이 나란히 서야 한다). */
.range .ldate{ flex:0 0 auto; width:124px; }
.range__t{ color:var(--faint); font-size:13px; }
/* 자주 쓰는 기간은 링크로 — 두 칸을 손으로 채우지 않아도 되게 한다 */
.range__p{ display:flex; align-items:center; gap:12px; margin-left:4px; }
.range__p a{ font-size:12px; color:var(--soft); text-decoration:none; border-bottom:1px solid var(--line); }
.range__p a:hover{ color:var(--ink); border-bottom-color:currentColor; }
/* KPI 라벨 옆 단위·기간 표시 */
.kpi__u{ font-weight:500; color:var(--ghost, rgba(0,0,0,.4)); }
/* 집계가 꺼진 환경(로컬·개발)에서 띄우는 안내 */
.stat-off{ display:inline-block; margin-top:6px; font-size:12px; font-weight:450; color:var(--danger); }

/* 마지막 백업 한 줄 — 평소엔 조용하고, 멈췄을 때만 눈에 걸리게 색이 바뀐다.
   ⚠ 카드로 두르지 않는다 — 안내·플래시는 왼쪽 2px 선으로만 세우는 것이 이 지면의 규칙이다. */
.bk{ margin:-8px 0 18px; padding:8px 0 8px 12px; border-radius:0;
  font-size:12.5px; line-height:1.6; border:0; border-left:2px solid var(--line);
  background:none; color:var(--soft); }
.bk b{ color:var(--ink); font-weight:500; }
.bk code{ font-family:'IBM Plex Mono', ui-monospace, monospace; font-size:11.5px;
  padding:1px 5px; border-radius:0; background:rgba(0,0,0,.05); color:var(--ink); }
.bk--ok{ border-left-color:var(--acc); }
.bk--stale{ border-left-color:var(--danger); color:var(--danger); }
.bk--stale b{ color:var(--danger); }
/* 막대 간격·굵기는 일수에 연동한다(핸드오프 §3) — 20일까지 9/14px, 40일까지 5/9px,
   그보다 길면 3/6px. 한 값으로 버티면 짧은 기간은 헐겁고 긴 기간은 뭉개진다.
   ⚠ 기본값(.vgraph)이 20일 이하 값이다. 아래 두 줄은 그 위에 덮는다. */
.vgraph--mid{ gap:5px; }
.vgraph--mid .vbar{ max-width:9px; }
.vgraph--dense{ gap:3px; }
.vgraph--dense .vbar{ width:100%; max-width:6px; border-radius:999px; }

/* ═══════════════ 고객 표 ═══════════════
   근거: 바탕화면 adminconsole/LiltAdminConsole.dc.html §고객(2026-09-19).
   카드를 두르지 않는다 — 지면 위에 헤어라인으로만 나눈 한 판이다.
   ⚠ 열 비율은 핸드오프 값 그대로다. 바꾸면 머리글과 행이 어긋난다.
   ⚠ 좁은 화면에서는 머리글을 감추고 행을 2열로 접는다(맨 아래 미디어쿼리). */
/* 머리줄은 **두 줄**이다 — 위는 제목 + [계정 발급], 아래는 찾는 도구(검색·좁히기·줄 세우기). */
.listhead{ display:flex; flex-direction:column; align-items:stretch; gap:16px; }
.listhead__top{ display:flex; align-items:flex-end; justify-content:space-between;
  gap:16px; flex-wrap:wrap; }
.listhead__t{ margin:10px 0 0; font-size:19px; font-weight:300; letter-spacing:-.018em;
  color:var(--ink); }
/* 계정 발급 — **자주 쓰지 않는 기능**이라 작은 글자 한 줄이다.
   ⚠ `.btn` 을 쓰지 않는다. 콘솔의 `.btn-primary` 는 글자+화살표로 바뀌지만 14px 이고,
     제목(19px) 옆에서 그 크기는 매일 쓰는 것처럼 보인다. */
.listhead__new{ flex:none; display:inline-flex; align-items:center; gap:5px;
  padding:0; margin:0 0 3px; border:0; background:none; cursor:pointer;
  font-family:inherit; font-size:12.5px; font-weight:400; letter-spacing:-.01em;
  color:var(--soft); transition:color .18s, gap .2s; }
.listhead__new::after{ content:"\2192"; }
.listhead__new:hover{ color:var(--ink); gap:9px; }
.listhead__new:active{ opacity:.6; }
/* ⚠ 줄바꿈을 허용한다 — 검색칸 + 좁히기 + 줄 세우기 + [계정 발급] 넷이 한 줄에 다 서지 않는
   폭이 있다. 없으면 선택 상자가 글자가 안 보일 만큼 찌부러진다. */
.listhead__acts{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
/* 표 위에서는 검색칸이 제목 줄에 얹히므로 아래 여백을 뺀다(원래는 목록 카드 안이었다) */
.listhead__acts .search-box{ width:210px; margin-bottom:0; }

/* 좁히기·줄 세우기 — 검색칸 옆의 작은 선택기.
   ⚠ **상자를 두르지 않는다**(2026-09-30). 34px 네모가 일곱 개 늘어서니 줄 전체가 투박했다.
     같은 줄의 검색칸이 이미 밑줄이라, 어휘를 밑줄 하나로 모았다 — 되살리지 말 것.
   ⚠ 화살표는 배경 그림으로 그린다 — appearance:none 으로 기본 화살표를 지웠기 때문이다. */
.ctpick{
  flex:none; height:30px; padding:0 20px 0 6px;
  border:0; border-radius:0; background:transparent;
  box-shadow:inset 0 -1px 0 0 var(--line);
  font-family:inherit; font-size:12.5px; font-weight:400; letter-spacing:-.01em;
  color:var(--ink); cursor:pointer;
  -webkit-appearance:none; appearance:none;
  background-image:linear-gradient(45deg, transparent 50%, var(--soft) 50%),
                   linear-gradient(135deg, var(--soft) 50%, transparent 50%);
  background-position:calc(100% - 10px) 13px, calc(100% - 5px) 13px;
  background-size:5px 5px, 5px 5px;
  background-repeat:no-repeat;
  transition:box-shadow .2s;
}
.ctpick:hover{ box-shadow:inset 0 -1px 0 0 var(--ink); }
.ctpick:focus{ outline:none; box-shadow:inset 0 -1.5px 0 0 var(--ink); }
.ctpick:focus-visible{ outline:1px solid rgba(0,0,0,.22); outline-offset:-2px; }
/* 한 쪽에 몇 줄 — 걸러내는 장치가 아니라 **보는 방식**이라, 줄 끝으로 밀어 따로 세운다.
   ⚠ 좁은 화면에서는 아래 규칙이 .ctpick 을 늘리므로 auto 마진이 저절로 풀린다. */
.listhead__acts .ctsize{ margin-left:auto; }

/* 결제 상태 — 네 칸이 한 줄로 선 라디오. **고른 칸만 잉크 글자 + 밑줄**이다.
   ⚠ 칸을 두르던 네모는 2026-09-30 에 걷었다(같은 날 .ctpick 도 같이) — 되살리지 말 것.
     그때 칸끼리 테두리를 겹치던 margin-left:-1px 도 함께 없앴다(겹칠 선이 없다).
   ⚠ 라디오는 감추되 display:none 은 쓰지 않는다(키보드 화살표 이동이 끊긴다). */
.ctseg{ flex:none; display:flex; gap:4px; }
.ctseg label{ position:relative; flex:1 1 auto; cursor:pointer; }
.ctseg input{ position:absolute; inset:0; margin:0; opacity:0; cursor:pointer; }
.ctseg span{ display:flex; align-items:center; justify-content:center; height:30px; padding:0 10px;
  font-size:12.5px; font-weight:400; letter-spacing:-.01em;
  color:var(--soft); white-space:nowrap; transition:color .18s, box-shadow .18s; }
.ctseg label:hover span{ color:var(--ink); }
.ctseg input:checked + span{ color:var(--ink); box-shadow:inset 0 -1.5px 0 0 var(--ink); }
.ctseg input:focus-visible + span{ outline:1px solid rgba(0,0,0,.22); outline-offset:-3px; }

/* 소멸 임박만 보기 — 결제 상태와 겹칠 수 있는 조건이라 라디오 밖에서 따로 켜고 끈다.
   경고색은 숫자에만, 켜지면 테두리까지. */
.ctflag{ flex:none; display:inline-flex; align-items:center; gap:6px; height:30px; padding:0 10px;
  border:0; border-radius:0; background:transparent; cursor:pointer;
  font-family:inherit; font-size:12.5px; font-weight:400; letter-spacing:-.01em; color:var(--soft);
  transition:color .18s, box-shadow .18s; }
.ctflag b{ font-weight:450; color:var(--danger); }
.ctflag:hover{ color:var(--ink); }
/* 켜진 표시는 밑줄 — 옆 칸들과 같은 어휘로(네모 테두리는 2026-09-30 에 걷었다) */
.ctflag[aria-pressed="true"]{ color:var(--danger); box-shadow:inset 0 -1.5px 0 0 var(--danger); }
.ctflag:focus{ outline:none; }
.ctflag:focus-visible{ outline:1px solid rgba(0,0,0,.22); outline-offset:-3px; }

/* 소멸 임박 한 줄 — 카드가 아니라 왼쪽 선 하나로 알린다(경고색은 숫자에만) */
.noteline{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  margin-top:20px; padding:12px 0 12px 13px; border-left:2px solid var(--danger); }
.noteline__n{ font-size:13px; font-weight:450; color:var(--danger); }
.noteline__d{ flex:1; min-width:200px; font-size:12.5px; font-weight:300;
  line-height:1.7; color:var(--soft); word-break:keep-all; }
.noteline__d b{ color:var(--ink); font-weight:450; }

.ctable{ margin-top:22px; overflow-x:auto;
  /* 가로 막대는 감춘다 — 표 바로 아래 붙어 지면을 어지럽힌다. 이 폭이 필요한 구간은
     720~830px 남짓으로 좁고, 그 구간에서는 손가락·트랙패드로 밀 수 있다. */
  scrollbar-width:none; -ms-overflow-style:none; }
.ctable::-webkit-scrollbar{ display:none; }
.ctable__in{ min-width:960px; }
/* ⚠ **`minmax(0,·)` 를 빼지 말 것.** 맨 `fr` 은 `minmax(auto,·)` 이라 칸 내용보다 못 줄어든다.
   머리글과 행, 그리고 행끼리도 **따로 선 격자**여서, 긴 주소가 든 행만 세 번째 열이 벌어지고
   나머지 열이 밀려 **행마다 세로줄이 어긋난다**(고객이 한 명일 때는 드러나지 않는다).
   ⚠ **머리글과 행이 같은 선언을 공유한다.** 한쪽에만 열 폭을 적으면 그 순간 두 줄이 어긋난다
   — 이 사고는 한 번 났다(design_handoff_lilt/README-admin-console.md 가 같은 경고를 남겼다).
   ⚠ 일곱 열: 고객 / 청첩장 / 결제 상태 / 요금제 / 예식일 / 소멸 / 공개·관리.
     `주소`·`방문`은 열이 아니다 — 전화는 이름 아래로 내려갔고 나머지는 [상세]에 있다.
     청첩장 칸은 **템플릿 이름 한 줄**이다(주소·QR 은 [상세]에 있다 — 2026-09-22). */
.ctable__head, .ctable__r{ display:grid;
  grid-template-columns:minmax(0,1.2fr) minmax(0,1.6fr) minmax(0,.95fr) minmax(0,.75fr)
                        minmax(0,.85fr) minmax(0,.7fr) minmax(0,1fr);
  gap:16px; }
/* ⚠ 머리글 밑줄만 한 단계 진하다(.14) — 행 사이 선(--line, .1)과 같으면 머리글이 행처럼 읽힌다 */
.ctable__head{ padding:0 4px 11px; border-bottom:1px solid rgba(0,0,0,.14);
  font-size:11px; font-weight:400; letter-spacing:.06em; color:var(--soft); }
.ctable__r{ align-items:center; padding:15px 4px; border-bottom:1px solid var(--line);
  animation:riseIn .4s var(--e-in, cubic-bezier(.22,.61,.36,1)) both;
  transition:background-color .18s; }
.ctable__r:hover{ background:var(--a05, rgba(0,0,0,.03)); }
.ctable .empty{ padding:34px 16px; }
.ta-r{ text-align:right; }

/* 고객 칸 — 이름 아래 로그인 아이디. 두 줄이지만 한 사람이라 한 칸이다. */
.ct-who{ min-width:0; }
.ct-who b{ display:block; font-size:14px; font-weight:450; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ct-who i{ display:block; margin-top:3px; font-size:11.5px; font-weight:300;
  font-style:normal; color:var(--faint);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* 결제 상태 — 점 하나와 글자. **점의 진하기가 곧 단계다**(완료 1 · 체험 .18).
   ⚠ 입금 확인 중만 경고색이다 — 운영자가 손써야(승인) 하는 유일한 상태라서.
   ⚠ 공개 여부(오른쪽 끝)와 **다른 축**이다. 둘 다 참이어야 하객이 볼 수 있다 — 합치지 말 것. */
.ct-pay{ display:inline-flex; align-items:center; gap:6px; white-space:nowrap;
  font-size:12.5px; font-weight:400; color:var(--soft); }
.ct-pay i{ flex:0 0 auto; width:6px; height:6px; border-radius:50%;
  background:var(--ink); opacity:.18; }
.ct-pay.is-wait i{ background:var(--danger); opacity:1; }
.ct-pay.is-done i{ opacity:1; }
.ct-pay.is-done{ color:var(--ink); }

/* 칸 안의 작은 덧말 — 「수정 잠김」·「연장됨」. 값이 아니라 단서다. */
.ct-note{ display:block; margin-top:3px; font-size:11px; font-weight:300; color:var(--faint);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

.ct-nm{ min-width:0; font-size:14px; font-weight:450; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ct-sub{ min-width:0; font-size:13px; font-weight:300; color:var(--soft);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* 요금제 — 정해지지 않았으면 결제 상태가 아니라 **요금제가 없다는 뜻**이다(둘을 섞지 말 것) */
.ct-plan{ min-width:0; font-size:12.5px; font-weight:400; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ct-plan.is-none{ color:var(--faint); font-weight:300; }
/* 청첩장 칸 — 주소(누르면 새 탭) 아래 템플릿 이름.
   ⚠ 강조색(--acc)이 잉크와 같은 검정이라 색으로는 링크인 줄 모른다 — 밑줄과 커서로 알린다.
     표 안에서 늘 밑줄을 그으면 행마다 선이 하나씩 더 생겨 지면이 시끄럽다. */
.ct-inv{ min-width:0; }
.ct-inv b, .ct-inv__url{ display:block; font-size:13px; font-weight:300; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ct-inv b.is-none{ color:var(--faint); }
.ct-inv__url{ text-decoration:none; transition:opacity .16s; }
.ct-inv__url:hover{ text-decoration:underline; text-underline-offset:3px; opacity:.72; }
.ct-inv i{ display:block; margin-top:3px; font-size:11.5px; font-weight:300;
  font-style:normal; color:var(--soft);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* 소멸 — 3일 이내는 경고, 14일 이내는 코발트. 그 외에는 보통 글자색이다.
   ⚠ nowrap — "소멸 예정" 이 좁은 열에서 두 줄로 갈라지면 그 행만 키가 커진다. */
.ct-exp{ font-size:12.5px; font-weight:400; color:var(--soft); white-space:nowrap; }
.ct-exp.is-near{ color:var(--acc); }
.ct-exp.is-warn{ color:var(--danger); }

/* ⚠ 두 칸을 **고정 폭**으로 세운다. flex 로 오른쪽에 몰면 「공개중」과 「비공개」의 글자 폭
   차이만큼 점과 [상세]가 행마다 좌우로 흔들려 세로줄이 어긋난다(2026-09-19 지적). */
.ct-act{ display:grid; grid-template-columns:auto 34px; align-items:center;
  justify-content:end; gap:12px; }
/* 발행 상태 — 점 하나와 글자. **여기서는 누르지 않는다**(발행은 [발행] 탭의 승인 흐름이다). */
.ct-pub{ display:inline-flex; align-items:center; gap:6px; white-space:nowrap;
  min-width:52px;                      /* 「공개중」·「비공개」 어느 쪽이 와도 점 위치가 같게 */
  font-size:12.5px; font-weight:400; color:var(--faint); }
.ct-pub i{ flex:0 0 auto; width:6px; height:6px; border-radius:50%; background:currentColor; }
.ct-pub.is-on{ color:var(--acc); }
/* 글자만 남긴 버튼 — 표 안에서 테두리를 두르면 행마다 상자가 생겨 지면이 시끄럽다.
   ⚠ 오른쪽 칸(34px)에 딱 맞춰 선다 — 폭이 흔들리면 열 끝이 들쭉날쭉해진다. */
.linkbtn{ border:none; background:none; padding:0; cursor:pointer; text-align:right;
  font-family:inherit; font-size:12.5px; font-weight:400; color:var(--acc);
  white-space:nowrap; transition:opacity .16s; }
.linkbtn:hover{ opacity:.66; }

/* 모달 머리 — 오버라인 + 제목 + 닫기.
   ⚠ 좌우 패딩은 본문(`.modal__body` 의 22px)과 같은 값이어야 한다. 다르면 제목만 덜
   들여써져 상자 왼쪽 선이 두 겹으로 보인다. */
.modal__hd{ display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  padding:20px 22px 0; }
.modal__t{ margin:10px 0 0; font-size:20px; font-weight:300; letter-spacing:-.02em;
  color:var(--ink); }

/* ⚠ 콘솔의 버튼은 **사각**이다(핸드오프 §7 · 디자인 토큰의 radius 0).
   알약은 탭 옆 [로그아웃]처럼 지면을 떠 있는 것에만 남긴다.
   ⚠ 이 규칙을 `.btn` 전역으로 올리지 말 것 — 같은 파일을 고객 편집기가 함께 쓴다. */
/* ⚠ 모서리와 글자 크기는 admin-console.css 가 쥔다 — 여기서는 칸 크기만 준다. */
.adm-body .pg-btn{ width:32px; height:32px; }

/* ── 콘솔 팝업 ───────────────────────────────────────────────────────────
   ⚠ 예전에는 **상자 전체**가 스크롤 컨테이너였다(`.modal__box{overflow:auto}`). 그러면
     스크롤 막대가 머리글 위부터 바닥글 아래까지 관통하면서 **둥근 모서리를 뚫고 나가** 상자
     모양이 망가진다(2026-09-19 지적). 이제 **본문만** 구르고 머리·바닥은 제자리에 선다.
   ⚠ `min-height:0` 을 빼지 말 것 — flex 자식은 기본이 `min-height:auto` 라 내용만큼
     부풀고, 그러면 본문이 안 줄어 스크롤이 다시 상자로 넘어간다.
   ⚠ `:has()` 를 못 읽는 브라우저에서는 예전처럼 상자가 구른다 — 모양만 덜 곱고 기능은 같다. */
.adm-body .modal__box:has(.modal__body){ display:flex; flex-direction:column; overflow:hidden; }
.adm-body .modal__box:has(.modal__body) .modal__body{ flex:1 1 auto; min-height:0; overflow-y:auto; }
/* 막대는 가늘고 옅게 — 있는 줄은 알되 지면을 어지럽히지 않는 정도로. 아주 감추지는 않는다
   (더 볼 것이 남았다는 신호까지 사라지면 아래 내용을 못 찾는다). */
.adm-body .modal__body{ scrollbar-width:thin; scrollbar-color:rgba(0,0,0,.22) transparent; }
.adm-body .modal__body::-webkit-scrollbar{ width:6px; }
.adm-body .modal__body::-webkit-scrollbar-thumb{ background:rgba(0,0,0,.22); border-radius:999px; }
.adm-body .modal__body::-webkit-scrollbar-track{ background:transparent; }
/* 콘솔의 면은 사각이다(핸드오프 §7 · 토큰의 radius 0) — 버튼과 같은 어휘로 맞춘다. */
.adm-body .modal__box{ border-radius:0; }

@media (max-width:720px){
  /* ══ 표를 가로로 밀지 않는다 — 머리글을 감추고 **행 하나를 카드 한 장**으로 세운다 ══
     ⚠ 2열 격자는 걷었다(2026-09-29). 머리글이 없는 폭에서 값끼리 짝지어 놓으니
       「미결제 ↔ 2027.02.27」처럼 **관계없는 둘이 한 줄에 서서** 무슨 값인지 알 수 없었다.
     ⚠ 대신 **한 줄씩 흐르게 하고 값 앞에 라벨을 붙인다.** 라벨은 마크업이 아니라 `::before` 다 —
       같은 행을 JS(rowHtml)도 그리므로, 마크업에 넣으면 두 곳을 다 고쳐야 한다. */
  .ctable{ overflow-x:visible; }
  .ctable__in{ min-width:0; }
  .ctable__head{ display:none; }
  .ctable__r{ display:flex; flex-wrap:wrap; align-items:baseline; gap:3px 12px;
    padding:16px 4px; }
  /* 이름과 결제 상태가 **첫 줄**이다(가장 먼저 보는 두 값).
     ⚠ 마크업 차례는 who → inv → pay 라, `order` 로 끌어올리지 않으면 결제 상태가
       주소 아래로 밀린다. `margin-left:auto` 가 그것을 오른쪽 끝으로 민다. */
  .ctable__r .ct-pay{ order:2; flex:none; margin-left:auto; }
  /* 이름 옆에 로그인 아이디(연락처·카카오 ID)를 붙인다 — 두 줄로 세우면 행만 길어진다. 색은 그대로 둘로 갈린다. */
  .ctable__r .ct-who{ order:1; flex:1 1 auto; min-width:0; display:flex; align-items:baseline; gap:8px; }
  .ctable__r .ct-who b{ flex:none; max-width:60%; }
  .ctable__r .ct-who i{ flex:0 1 auto; min-width:0; margin-top:0; }
  /* 주소 줄 오른쪽 끝에 템플릿 이름 — 한 줄로 */
  .ctable__r .ct-inv{ order:3; flex:1 1 100%; margin-top:5px; display:flex; align-items:baseline; gap:10px; }
  .ctable__r .ct-inv__url, .ctable__r .ct-inv b{ flex:0 1 auto; min-width:0; }
  .ctable__r .ct-inv i{ flex:none; margin:0 0 0 auto; }
  /* 요금제·예식일·소멸은 한 줄에 나란히 — 라벨이 없으면 숫자만 남아 못 읽는다 */
  .ctable__r .ct-plan,
  .ctable__r .ct-sub,
  .ctable__r .ct-exp{ flex:none; margin-top:7px; font-size:12px; }
  .ctable__r .ct-plan{ order:4; }
  .ctable__r .ct-sub { order:5; }
  .ctable__r .ct-exp { order:6; }
  .ctable__r .ct-sub::before { content:'예식 ';  color:var(--faint); }
  .ctable__r .ct-exp::before { content:'소멸 ';  color:var(--faint); }
  /* 덧말(「수정 잠김」·「연장됨」)은 값 옆에 붙인다 — 줄을 바꾸면 그 값만 키가 커진다 */
  .ctable__r .ct-note{ display:inline; margin:0 0 0 4px; }
  .ct-act{ order:7; flex:1 1 100%; margin-top:12px; justify-content:space-between; gap:14px; }
  /* 머리글이 없는 폭이라 숫자만 있으면 무엇인지 모른다 — 방문 수에만 단위를 붙인다 */
  .ct-views::after{ content:'회'; margin-left:2px; font-size:11.5px; color:var(--faint); }
  /* ⚠ 좁은 폭에서는 **검색칸이 한 줄을 통째로** 쓴다(2026-09-29).
     선택 상자와 한 줄을 나눠 쓰게 두었더니 `flex:1` 인 검색칸이 60px 까지 찌부러져
     글자가 겹쳐 보였다. 선택 상자 둘은 아래 줄을 반씩 나눠 선다. */
  .listhead__acts{ width:100%; row-gap:12px; }
  .listhead__acts .search-box{ flex:1 1 100%; width:auto; }
  /* `min-width:0` 이 없으면 선택 상자가 글자 길이만큼 버텨 줄을 넘긴다 */
  .listhead__acts .ctpick{ flex:1 1 0; min-width:0; }
  /* 결제 상태 라디오도 한 줄을 통째로 — 네 칸이 폭을 나눠 쓴다 */
  .listhead__acts .ctseg{ flex:1 1 100%; }
  .ctseg label{ flex:1 1 0; min-width:0; }
  .ctseg span{ padding:0 4px; }
}

@media (max-width:520px){
  /* 폰 폭 — 선택기 둘이 한 줄을 반씩 쓴다("입금 확인 중" 이 잘리지 않을 만큼).
     ⚠ 글자는 **왼쪽에 붙인다** — 상자를 걷은 뒤(2026-09-30) 가운데 정렬은 기댈 테두리가
       없어져, 칸 한가운데 글자만 떠 있는 꼴이 됐다. */
  .listhead__acts .ctpick,
  .listhead__acts .ctflag{ flex:1 1 calc(50% - 5px); justify-content:flex-start; }
  .range{ gap:6px; }
  .range input[type="date"]{ flex:1; min-width:0; padding:7px 2px; }
  .range .ldate{ flex:1 1 0; width:auto; min-width:0; }
  .range__p{ width:100%; margin-left:0; }
}

/* 소제목·라벨 옆 보조 문구는 한 칸 떨어뜨린다 — 붙으면 한 낱말처럼 읽힌다
   ("샘플을 많이 열어 본 순서같은 기간" / "기간 내 방문14일") */
/* ⚠ 크기를 적어 두지 않으면 소제목(19px)을 그대로 물려받아 보조 문구가 제목만큼 커진다
   — 굵기까지 한 단계 위라 위계가 거꾸로 보였다("입금 확인 요청" < "오래 기다린 것이 위에 옵니다"). */
.dash-sub .hint{ margin-left:7px; font-size:12.5px; font-weight:400; color:var(--faint);
  letter-spacing:-.01em; }
.kpi__u{ margin-left:5px; }

/* ═══════════════ 청첩장 공유 카드 — 사진 고르기 · 자리 잡기 ═══════════════
   카카오톡 카드는 800×420 이라 세로 사진이 가운데만 남는다. 고객이 사진과 그 안에서
   보여 줄 자리를 직접 잡는 자리다. 프레임 비율은 실제 카드와 같아야 한다 — 여기서 본 것과
   실제로 나가는 그림이 다르면 이 편집기의 존재 이유가 없다. */
.subhead .hint{ margin-left:7px; font-size:11.5px; font-weight:500; color:var(--faint); letter-spacing:0; }

/* 지금 무엇이 카드에 나가는지 한 줄로. 고르는 일은 팝업(#sharePickModal)이 맡는다 —
   썸네일을 섹션에 늘어놓으면 사진이 많을 때 아래 편집기가 화면 밖으로 밀린다. */
.share-cur{ display:flex; align-items:center; gap:12px; padding:12px 0; margin-bottom:14px;
  border:0; border-top:1px solid var(--line); border-radius:0; background:none; }
.share-cur__thumb{ flex:none; width:52px; height:52px; border-radius:0; overflow:hidden;
  background:var(--a05, rgba(0,0,0,.03)); }
.share-cur__thumb img{ width:100%; height:100%; object-fit:cover; display:block; }
.share-cur__thumb img[hidden]{ display:none; }
.share-cur__txt{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
.share-cur__txt b{ font-size:13.5px; color:var(--ink); }
.share-cur__txt span{ font-size:11.5px; color:var(--soft); }
.share-cur .btn{ flex:none; }

/* 카드 모양 고르기 — 네모 두 개로 비율을 눈에 보이게 한다(글자만으로는 감이 안 온다) */
.shape-pick{ display:flex; gap:8px; margin-bottom:14px; }
/* 고르는 칸은 다른 섹션(.choice .opt)과 같은 어휘다 — 선만, radius 0, 고른 것만 옅은 코발트 면 */
.shape-pick__i{ flex:1; display:flex; flex-direction:column; align-items:center; gap:4px;
  padding:12px 8px 11px; cursor:pointer; transition:.14s;
  border:1px solid var(--line); border-radius:0; background:none; }
.shape-pick__i:hover{ border-color:var(--acc); }
.shape-pick__i.is-on{ border-color:var(--acc); background:var(--acc-bg); }
.shape-pick__i b{ font-size:13px; font-weight:450; color:var(--ink); }
.shape-pick__d{ font-size:11px; color:var(--soft); }
.shape-pick__i.is-on b{ color:var(--acc-ink); }
/* 비율 견본 — 실제 카드 비율 그대로 그린다 */
/* ⚠ 두 그림의 **높이가 다르다**(가로형 27px · 세로형 40px). 그냥 두면 아래 글자가 서로 다른
   높이에서 시작해 두 칸이 어긋나 보인다. 그림이 들어갈 자리를 **더 큰 쪽
   높이로 고정**하고 그 안에서 아래 정렬하면, 글자는 늘 같은 줄에서 시작한다.
   ⚠ 높이를 바꾸려면 세로형 그림의 높이(30px × 1200/900 = 40px)와 함께 고칠 것 —
     이 값보다 작으면 세로형 그림이 잘린다. */
.shape-pick__box-slot{ height:40px; display:flex; align-items:flex-end; justify-content:center;
  margin-bottom:2px; }
.shape-pick__box{ display:block; border:1.5px solid var(--faint); border-radius:0; background:none; }
.shape-pick__box--wide{ width:52px; aspect-ratio:1200/630; }
.shape-pick__box--tall{ width:30px; aspect-ratio:900/1200; }
.shape-pick__i.is-on .shape-pick__box{ border-color:var(--acc); background:none; }

/* 카드 사진 팝업에는 '새로 첨부하기' 하나만 남았다.
   그 칸의 스타일(.pickgrid*)도 함께 지웠다. */

/* 첫 화면(표지) 사진에서 보일 영역 팝업.
   칸은 템플릿 표지 칸 모양 그대로다 — 비율은 인라인 aspect-ratio, 모서리는 data-shape.
   사진은 표지와 **같은 규칙**으로 그린다: cover + object-position · transform-origin · scale
   (HeroFocus#cssStyle). 여기를 다른 방식(left/top 등)으로 바꾸면 팝업과 표지가 어긋난다. */
.hero-focus__frame{ position:relative; width:min(100%, 240px); margin:4px auto 0; overflow:hidden;
  isolation:isolate; border:1px solid var(--line); border-radius:10px; background:rgba(0,0,0,.05);
  cursor:grab; touch-action:none; user-select:none; }
.hero-focus__frame[data-shape="oval"]{ border-radius:50%; }
.hero-focus__frame[data-shape="arch"]{ border-radius:50% 50% 50% 50% / 47% 47% 53% 53%; }
.hero-focus__frame.is-dragging{ cursor:grabbing; }
.hero-focus__frame img{ position:absolute; inset:0; width:100%; height:100%; max-width:none;
  object-fit:cover; display:block; pointer-events:none; }
/* 새로 첨부하기 — 파일 입력은 감추고 넓은 영역을 누르게 한다(작은 기본 버튼은 누르기 어렵다) */
.pick-new__drop{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:5px;
  padding:26px 16px; border:1.5px dashed var(--cobalt); border-radius:13px; background:var(--cobalt-soft);
  cursor:pointer; text-align:center; transition:.14s; }
.pick-new__drop:hover{ background:rgba(0,0,0,.03); }
.pick-new__drop b{ font-size:14px; color:var(--cobalt-deep); }
.pick-new__drop span{ font-size:12px; color:var(--soft); }

/* 자리 잡기 — 프레임이 곧 카드다(800:420) */
.share-crop{ margin-bottom:6px; }
.share-crop__frame{ position:relative; width:100%; aspect-ratio:1200/630; overflow:hidden;
  border:1px solid var(--line); border-radius:0; background:var(--a05, rgba(0,0,0,.03)); cursor:grab;
  touch-action:none;   /* 끌 때 화면이 같이 스크롤되면 자리를 잡을 수 없다 */
  user-select:none; }
/* 세로형(3:4). 폭을 그대로 두면 세로가 너무 길어 편집기 아래가 화면 밖으로 밀린다 — 폭을 조인다. */
.share-crop__frame.is-tall{ aspect-ratio:900/1200; max-width:300px; }
.share-crop__frame.is-dragging{ cursor:grabbing; }
/* 사진이 한 장도 없을 때만 손이 아니다 — 대표 사진을 그대로 쓰는 중에도 자리는 잡을 수 있다. */
.share-crop__frame.is-empty{ cursor:default; }
.share-crop__frame img{ position:absolute; left:0; top:0; max-width:none; display:block;
  pointer-events:none; }
/* 카드는 1.91:1 인데 카카오톡 공유 버튼(피드)은 2:1 로 보여 준다. 그 차이만큼 위아래가 잘리므로
   미리 띠로 알려 준다 — 높이의 (0.525-0.5)/0.525 ≈ 2.38% 씩이다.
   ⚠ 이 값은 OgImageService 의 CARD_HEIGHT/CARD_WIDTH · FEED_RATIO 에서 나온 것이다. 함께 고칠 것. */
.share-crop__safe{ position:absolute; inset:0; z-index:1; pointer-events:none; }
.share-crop__frame.is-tall .share-crop__safe{ display:none; }
.share-crop__safe::before, .share-crop__safe::after{ content:''; position:absolute; left:0; right:0;
  height:2.38%; background:rgba(20,28,45,.30); }
.share-crop__safe::before{ top:0; border-bottom:1px dashed rgba(255,255,255,.75); }
.share-crop__safe::after{ bottom:0; border-top:1px dashed rgba(255,255,255,.75); }
/* 아직 자리를 직접 안 잡았을 때(=서버 자동 크롭) 프레임 위에 덮는 안내. 사진은 그대로 비쳐 보인다. */
/* 가운데 정렬은 grid 로 하되, 글은 안쪽 블록(.share-crop__auto-in)에서 보통 글줄로 흐르게 둔다.
   컨테이너의 직계 자식이 되면 <b> 가 제 줄을 차지해 낱말마다 줄이 바뀐다.
   바탕을 반투명하게만 덮는 이유: 어떤 사진이 나가는지는 보여야 한다. 대신 글자 뒤에만
   흰 알약을 깔아 사진 위에서도 읽히게 한다.
   ⚠ pointer-events:none — 이 안내는 **덮기만 하고 막지는 않는다**. 빼면 안내 위를
     끌었을 때 pointerdown 이 이 판에 먹혀 프레임이 못 받고, 고객은 "안내만 뜨고 안 움직인다"를
     만난다. 안내가 사라지는 건 자리를 잡은 뒤라 순서가 거꾸로다. */
.share-crop__auto{ position:absolute; inset:0; z-index:2; display:grid; place-content:center;
  padding:0 16px; text-align:center; background:rgba(255,255,255,.30); backdrop-filter:blur(1px);
  pointer-events:none; }
.share-crop__auto-in{ padding:10px 16px; border-radius:0; background:rgba(255,255,255,.90);
  font-size:13px; font-weight:450; color:var(--ink); line-height:1.6; }
.share-crop__auto span{ display:block; margin-top:3px; font-size:11.5px; font-weight:500; color:var(--soft); }
.share-crop__auto[hidden]{ display:none; }   /* ⚠ display:grid 는 기본 [hidden] 을 이긴다 */
/* 안쪽 안내는 두 벌(사진 있음 / 없음)을 JS 로 갈아 끼운다 — display 를 주지 않아 기본 [hidden] 이
   먹지만, 나중에 누가 display 를 주면 조용히 새므로 짝을 지어 둔다. */
.share-crop__auto-in[hidden]{ display:none; }

.share-crop__ctrl{ display:flex; align-items:center; gap:12px; margin-top:10px; }
.share-crop__ctrl input[type=range]{ flex:1; accent-color:var(--cobalt-deep); }
.share-crop__ctrl input[type=range]:disabled{ opacity:.45; }

/* ═══ 카카오톡 말풍선 미리보기 ═══
   실제 카카오 SDK 를 부르지 않는다(미리보기가 진짜 공유창을 띄우면 실수로 보내게 된다).
   대화방 배경 위에 피드 카드 모양만 흉내 낸 모형이다.

   보내는 길이 둘이라 탭으로 나눈다 — 공유 버튼(카드 + 버튼)과 주소 붙여넣기(버튼 없음 + 주소 줄).
   내가 보낸 말풍선이므로 오른쪽에 붙인다(카톡에서 내 말풍선에는 이름도 프로필도 붙지 않는다). */
.kkt-tabs{ display:flex; gap:6px; margin-bottom:12px; }
.kkt-tab{ flex:1; padding:9px 8px; border:1px solid var(--line); border-radius:0; background:#fff;
  font-size:12.5px; font-weight:450; color:var(--soft); cursor:pointer; transition:.14s; }
.kkt-tab:hover{ border-color:var(--ink); }
.kkt-tab.is-on{ border-color:var(--ink); background:none; color:var(--ink); }

/* 말풍선 지면 — 카카오의 하늘색 대신 **연한 회색**이다(2026-09-21 고객 지시).
   이 화면은 카카오를 흉내 내는 자리가 아니라 우리 지면 안의 미리보기라,
   채도가 있는 면 하나가 통째로 튀었다. */
.kkt{ background:#efeeec; border-radius:14px; padding:16px 14px; }
.kkt[hidden]{ display:none; }
.kkt__me{ display:flex; flex-direction:column; align-items:flex-end; gap:4px; }
/* 붙여넣은 주소는 카드에 딸린 노란 말풍선으로 그대로 남는다 */
.kkt__url{ max-width:240px; padding:8px 11px; border-radius:12px; background:#fee500;
  font-size:11.5px; line-height:1.45; color:#2b2b2b; word-break:break-all; text-align:left; }
.kkt-note{ margin-top:10px; font-size:12.5px; color:var(--soft); line-height:1.65; }
.kkt-note[hidden]{ display:none; }
.kkt__bubble{ width:240px; max-width:100%; background:#fff; border-radius:12px; overflow:hidden;
  box-shadow:0 1px 2px rgba(0,0,0,.08); }
/* 스크랩 미리보기는 카드 비율 그대로, 공유 버튼(피드)은 2:1 — 가로형에서는 실제로 다르다.
   세로형(3:4)은 피드도 그대로 받아 주므로 둘이 같아진다. */
.kkt__thumb{ position:relative; width:100%; aspect-ratio:1200/630; overflow:hidden; background:rgba(0,0,0,.05); }
.kkt__thumb[data-ratio="feed"]{ aspect-ratio:2/1; }
/* ★ 주소 붙여넣기(스크랩)는 **언제나 2:1** 이다 — 카카오가 og:image 를 무조건 그 비율로
   리사이즈·크롭한다(og:image:width/height 를 정확히 내보내도 소용없다는 카카오 공식 답변).
   그래서 아래 .is-tall 규칙에서 **일부러 빼 둔다.** 예전에는 카드 모양을 그대로 따라가
   세로형일 때 이 탭도 3:4 로 그렸고, 실제와 다른 그림을 보여 주고 있었다. */
.kkt__thumb[data-ratio="scrap"]{ aspect-ratio:2/1; }
.kkt.is-tall .kkt__thumb:not([data-ratio="scrap"]),
.kkt.is-tall .kkt__thumb[data-ratio="feed"]{ aspect-ratio:900/1200; }
.kkt__thumb img{ position:absolute; left:0; top:0; max-width:none; display:block; }
/* 사진이 없을 때는 서버도 로고 카드를 내보낸다 — 그 모습 그대로 */
/* 사진을 고르지 않았을 때 — **검정 바탕에 흰 로고**(2026-09-21).
   ⚠ 로고 파일은 검은 잉크 PNG 라 그대로 얹으면 검정 위 검정이 된다. 마스크로 바꿔 칠한다.
   ⚠ 서버가 내보내는 기본 카드도 같은 모양이어야 한다 — 한쪽만 고치면 미리보기가 거짓말을 한다. */
.kkt__thumb.is-fallback{ background:#111; display:flex; align-items:center; justify-content:center; }
.kkt__thumb.is-fallback img{ display:none; }
.kkt__thumb.is-fallback::after{
  content:""; width:52%; aspect-ratio:1/1; background-color:#fff;
  -webkit-mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
          mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
}
.kkt__txt{ padding:10px 12px 11px; }
.kkt__t{ font-size:13.5px; font-weight:700; color:#1a1a1a; line-height:1.35;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.kkt__d{ font-size:11.5px; color:#7b8794; line-height:1.45; margin-top:3px;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.kkt__host{ font-size:11px; color:#b0b8c1; margin-top:6px; }
.kkt__cta{ border-top:1px solid #f0f0f0; padding:9px 0; text-align:center;
  font-size:12.5px; color:#4a4a4a; background:#fafafa; }

/* ═══════════════ 배경음악(편집 화면) —═══════════════ */

/* 지금 올라간 음원 한 줄 */
.music-cur{ margin-bottom:14px; }
.music-cur__empty{ padding:14px 0; border:0; border-top:1px solid var(--line); border-radius:0;
  background:none; color:var(--soft); font-size:13px; }
/* 음원 카드 — 위층(정보·버튼) / 아래층(재생 막대) 두 칸으로 나눈다.
   ⚠ 예전에는 <audio> 가 이름 줄 **안쪽**에 있어서, 미리듣기를 누르면 재생 막대가 이름을
     밀어내며 줄 밖으로 삐져나왔다. 층을 나눠 위층이 자리를 지키게 한다. */
/* ⚠ 흰 카드(테두리 + radius 12px + 흰 면)로 되돌리지 말 것 — 위쪽 헤어라인 한 줄이 이 지면의 어휘다. */
.music-card{ border:0; border-top:1px solid var(--line); border-radius:0; background:none; overflow:hidden; }
.music-card__top{ display:flex; align-items:center; gap:11px; padding:12px 0; }
/* ⚠ 면을 걷어내고 나니 34px 빈칸에 ♪ 하나만 떠서 파일명을 다음 줄로 밀었다 — 아예 내린다.
   무엇인지는 섹션 제목이 이미 말한다. */
.music-card__ico{ display:none; }
.music-card__txt{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
.music-card__txt b{ font-size:13.5px; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.music-card__txt span{ font-size:11.5px; color:var(--soft); }
.music-card__btns{ flex:none; display:flex; gap:6px; }
.music-card__btns .btn{ white-space:nowrap; }
.music-card__del:hover{ border-color:var(--danger); color:var(--danger); }
/* 재생 막대 전용 칸. 브라우저 기본 컨트롤이라 높이가 기기마다 달라 폭만 채워 준다. */
.music-card__player{ padding:0 0 12px; border-top:1px solid var(--line-soft); padding-top:11px;
  background:none; }
.music-card__player[hidden]{ display:none; }
.music-card__player audio{ display:block; width:100%; }
/* 좁은 화면에서는 버튼이 이름을 눌러 찌그러뜨린다 — 아래로 내린다 */
@media (max-width:520px){
  .music-card__top{ flex-wrap:wrap; }
  .music-card__txt{ flex:1 1 100%; order:2; }
  .music-card__btns{ order:3; margin-left:auto; }
}
/* 운영자가 막아 둔 음원 — 사유 원문은 내지 않고 사실만 알린다 */
.music-blocked{ color:var(--danger); }
/* ⚠ 색은 토큰(--danger)만. 안내는 왼쪽 2px 선으로 세운다(카드로 두르지 않는다). */
.music-blocked-note{ margin-top:8px; padding:9px 0 9px 12px; border-radius:0;
  background:none; border:0; border-left:2px solid var(--danger); color:var(--danger);
  font-size:12.5px; line-height:1.65; }

/* 파일 고르기 — 작은 기본 버튼은 누르기 어려워 넓은 영역을 준다.
   ⚠ 점선 + 틴트 면으로 되돌리지 말 것. 선 하나, radius 0 이다. */
.music-drop{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px;
  padding:22px 16px; border:1px solid var(--acc-line); border-radius:0; background:none;
  cursor:pointer; text-align:center; transition:.14s; }
.music-drop:hover{ background:var(--acc-bg); }
.music-drop b{ font-size:14px; font-weight:450; color:var(--acc-ink); }
.music-drop span{ font-size:12px; color:var(--soft); }

/* 권리 확인 전에는 **누를 수 없다**.
   ⚠ label 에는 disabled 속성이 없다. 파일 입력만 잠그면 라벨은 여전히 눌리는 것처럼 보이고,
     눌러도 아무 일이 없어 고장으로 읽힌다. 그래서 여기서 클릭 자체를 막고 잠긴 모양을 준다. */
.music-drop.is-locked{ pointer-events:none; cursor:default;
  border-color:var(--line); background:none; }
.music-drop.is-locked b{ color:var(--soft); }
.music-drop.is-locked b::before{ content:'🔒 '; }

/* 올리는 중 진행률 — 막대만 보여 준다. 숫자는 읽는 사이에 이미 끝나 있다 */
.music-prog{ height:6px; margin-top:10px; border-radius:999px; background:var(--line); overflow:hidden; }
.music-prog[hidden]{ display:none; }
.music-prog i{ display:block; height:100%; width:0; border-radius:999px;
  background:var(--cobalt-deep); transition:width .18s ease; }

/* 재생 버튼 자리 — 네 구석 중 하나.
   글자만 늘어놓으면 "좌상단"이 어느 쪽인지 한 번 더 생각해야 하므로, 화면 모형에 점을 찍어
   그림으로 보여 준다. ⚠ data-pos 값은 MusicButtonPosition.getCssSuffix() 와 같은 문자열이다. */
.music-pos{ display:grid; grid-template-columns:repeat(4, 1fr); gap:8px; }
.music-pos__i{ display:flex; flex-direction:column; align-items:center; gap:6px; cursor:pointer; }
.music-pos__i input{ position:absolute; opacity:0; width:0; height:0; }
/* 세로로 긴 화면 모형(청첩장은 세로다). 안쪽 점이 버튼 자리를 나타낸다. */
.music-pos__box{ position:relative; width:100%; aspect-ratio:3/4; border-radius:0;
  border:1px solid var(--line); background:none; transition:.14s; }
.music-pos__box i{ position:absolute; width:9px; height:9px; border-radius:50%;
  background:var(--soft); transition:.14s; }
.music-pos__i[data-pos="top-left"]     .music-pos__box i{ top:7px;    left:7px; }
.music-pos__i[data-pos="top-right"]    .music-pos__box i{ top:7px;    right:7px; }
.music-pos__i[data-pos="bottom-left"]  .music-pos__box i{ bottom:7px; left:7px; }
.music-pos__i[data-pos="bottom-right"] .music-pos__box i{ bottom:7px; right:7px; }
.music-pos__i:hover .music-pos__box{ border-color:var(--acc); }
.music-pos__i input:checked ~ .music-pos__box{ border-color:var(--acc);
  background:var(--acc-bg); }
.music-pos__i input:checked ~ .music-pos__box i{ background:var(--acc);
  box-shadow:0 0 0 3px var(--acc-bg); }
/* 키보드로 옮겨 다닐 때 어디에 있는지 보여야 한다 */
.music-pos__i input:focus-visible ~ .music-pos__box{ outline:2px solid var(--cobalt-deep); outline-offset:2px; }
.music-pos__t{ font-size:11.5px; color:var(--soft); }
.music-pos__i input:checked ~ .music-pos__t{ color:var(--acc-ink); font-weight:500; }

/* 권리 확인 전문 — 스크롤 상자.
   ⚠ 별도 약관 페이지 대신 여기서 전문을 그대로 보여 준다.
     서버(MusicRightsConsent.TEXT)가 가진 글이 그대로 나오고, 그 글의 해시가 동의 기록에 남는다. */
/* 스크롤 상자라 경계는 남긴다 — 다만 선 하나, radius 0, 면 없음 */
.music-terms{ max-height:190px; overflow-y:auto;
  padding:14px 15px; border:1px solid var(--line); border-radius:0; background:none;
  font-size:12.5px; line-height:1.75; color:var(--soft); white-space:pre-line;
  -webkit-overflow-scrolling:touch; }
.music-terms:focus-visible{ outline:2px solid var(--cobalt-deep); outline-offset:1px; }

.music-agree{ display:flex; align-items:flex-start; gap:9px; padding:12px 0;
  border:0; border-top:1px solid var(--line); border-radius:0; background:none; cursor:pointer; }
.music-agree input{ margin-top:2px; width:17px; height:17px; accent-color:var(--cobalt-deep); flex:none; }
.music-agree span{ font-size:13px; line-height:1.6; color:var(--ink); }

/* 운영자 콘솔 — 음원 조치 버튼 묶음 */
.music-adm-btns{ display:flex; flex-direction:column; gap:6px; flex:none; align-items:stretch; }
.music-adm-btns .btn{ white-space:nowrap; text-align:center; }
/* 이력(조치 이력)은 폭을 다 쓰는 칸이라 줄을 바꿔야 한다 — 감싸 두지 않으면
   메타·이력·버튼이 한 줄에 셋으로 서서 파일명이 한 글자씩 세로로 쪼개진다. */
#music .item{ flex-wrap:wrap; align-items:flex-start; }
#music .item .meta{ flex:1 1 260px; }
/* 파일명은 고객이 올린 이름 그대로라 길다. 다만 한글까지 아무 데서나 끊지는 않는다
   (공용 .item .s 의 break-all 은 "박지훈"을 세 줄로 만든다). */
#music .item .t{ flex-wrap:wrap; gap:6px 8px; overflow-wrap:anywhere; }
#music .item .t .pill{ flex:none; }
#music .item .s{ word-break:normal; overflow-wrap:anywhere; }
/* 조치 이력 — 메타·버튼 아래로 폭을 다 쓰는 한 줄 */
.music-adm-hist{ flex-basis:100%; margin-top:8px; }
/* 넓은 화면에서는 이력이 있든 없든 버튼이 같은 자리(오른쪽 위)에 있어야 한다 —
   마크업 순서대로 두면 이력이 있는 줄만 버튼이 이력 아래로 밀려 내려간다. */
@media (min-width:521px){
  #music .item .meta{ order:1; }
  .music-adm-btns{ order:2; }
  .music-adm-hist{ order:3; }
}

/* 좁은 화면 — 버튼 세 개를 오른쪽에 세로로 세우면 이름 칸이 눌려 찌그러진다.
   메타 아래로 내리고, 버튼은 가로 한 줄에 나눠 앉힌다. */
@media (max-width:520px){
  #music .item{ flex-direction:column; align-items:stretch; gap:10px; }
  /* ⚠ 세로로 세운 flex 에서 flex-basis 는 높이다 — 가로 기준으로 잡아 둔 값을 풀지 않으면
     칸마다 260px 짜리 빈 공백이 생긴다. */
  #music .item .meta{ flex:0 1 auto; }
  .music-adm-hist{ flex-basis:auto; margin-top:0; }
  /* 이력이 있든 없든 같은 자리에서 칸이 끊기게 — 항목마다 구조가 같아 보인다 */
  .music-adm-btns{ flex-direction:row; flex-wrap:wrap; gap:7px;
    padding-top:10px; border-top:1px dashed var(--line); }
  /* 폭을 고르게 나눈다. 글자보다 좁아지지는 않으니 "재생 막기"가 잘릴 일은 없다. */
  .music-adm-btns > *{ flex:1 1 0; }
  .music-adm-btns form .btn{ width:100%; }
}

/* 잠긴 템플릿 표시 — 고르는 자리가 아니라 확인하는 자리다.
   입력칸처럼 보이되 눌리지 않게, 회색 바탕으로 "고정된 값"임을 드러낸다. */
.tpl-fixed{ display:flex; flex-direction:column; gap:3px; padding:12px 14px;
  border:1px solid var(--line); border-radius:11px; background:#fff; }
.tpl-fixed b{ font-size:14px; color:var(--ink); }
.tpl-fixed span{ font-size:11.5px; color:var(--soft); }


/* ═══════════════ 편집기 핸드오프에서 온 입력들 ═══════════════
   근거: design_handoff_invitation_editor/InvitationEditor.dc.html (2026-09-20 반영)
   ⚠ 어휘는 이 지면의 것을 그대로 쓴다 — 밑줄 입력 · 글자 나열 선택 · radius 0. */

/* 예식 일시 — 날짜 칸과 시간 칸을 나란히. 좁으면 한 줄씩 내려온다.
   ⚠ 열은 `minmax(0,1fr)` 로 적는다(맨 1fr 은 칸 내용보다 못 줄어든다). */
.wed-when{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; }
@media (max-width:560px){ .wed-when{ grid-template-columns:minmax(0,1fr); } }
/* ── 날짜·시간 칸 ────────────────────────────────────────────────────────────
   기기의 선택기는 그대로 쓰되 **겉면은 이 지면의 것**이다.
   네이티브 입력을 투명하게 덮어 두고(.dtf__in) 보이는 글자는 JS 가 한글로 그린다.
   ⚠ 네이티브 칸을 그냥 노출하지 말 것 — 회색 상자·고정폭 숫자·OS 아이콘이 이 지면에서 혼자 튄다.
   ⚠ 덮개는 `opacity:0` 이다. `display:none` 으로 감추면 기기 선택기가 열리지 않는다. */
.dtf{ position:relative; display:flex; align-items:center; gap:10px;
  height:40px; border-bottom:1px solid var(--line); cursor:pointer;
  transition:border-color .2s; }
.dtf:hover{ border-bottom-color:var(--line); }
.dtf:focus-within{ border-bottom-color:var(--acc); }
.dtf__v{ flex:1; min-width:0; font-size:18px; font-weight:300; letter-spacing:-.012em;
  color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.dtf__v.is-empty{ color:var(--ghost); }
/* 아이콘 — 얇은 선으로 그린다(그림 파일을 쓰지 않는다) */
.dtf__ico{ position:relative; flex:none; width:17px; height:17px; color:var(--soft);
  transition:color .2s; }
.dtf:focus-within .dtf__ico{ color:var(--acc); }
.dtf__ico--cal::before{ content:''; position:absolute; inset:2px 0 0; border:1px solid currentColor;
  border-radius:2px; }
.dtf__ico--cal::after{ content:''; position:absolute; left:0; right:0; top:6px;
  border-top:1px solid currentColor; }
.dtf__ico--clk::before{ content:''; position:absolute; inset:1px; border:1px solid currentColor;
  border-radius:50%; }
.dtf__ico--clk::after{ content:''; position:absolute; left:7.5px; top:4px; width:1px; height:5px;
  background:currentColor; box-shadow:1px 4px 0 -0.5px currentColor; }
.dtf__in{ position:absolute; inset:0; width:100%; height:100%; opacity:0; cursor:pointer;
  border:0; background:none; font:inherit; }

/* 회신 마감일도 같은 밑줄 어휘로. 이쪽은 값이 짧아 네이티브 그대로 둔다. */
#rsvpDue{
  width:100%; height:40px; padding:0; color:var(--ink);
  background:transparent; border:none; border-bottom:1px solid var(--line); border-radius:0;
  font-family:inherit; font-size:18px; font-weight:300; letter-spacing:-.012em;
  transition:border-color .2s;
}
#rsvpDue:focus{ outline:none; border-bottom-color:var(--acc); }

/* 앨범 배치 고르기 — 글자 나열(.choice)과 같은 어휘라 따로 꾸미지 않는다.
   ⚠ 예전의 모달(.gtype 카드 세 장)은 걷어냈다. 되살리지 말 것. */
.choice--gal{ margin-top:2px; }

/* 중간 사진 고르기 — 앨범 사진을 네 열로 늘어놓고 한 장만 고른다(사진 4열은 핸드오프 규격). */
.band-pick{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:6px; margin-top:4px; }
/* ⚠ display 를 준 요소는 `hidden` 만으로 안 감춰진다(브라우저 기본 [hidden] 이 명시도에서 밀린다).
   스크립트가 이 목록을 감추므로 짝 규칙을 함께 둔다. */
.band-pick[hidden]{ display:none; }
.band-pick__i{ position:relative; padding:0; border:0; border-radius:0; background:none;
  aspect-ratio:1/1; overflow:hidden; cursor:pointer;
  box-shadow:inset 0 0 0 1px var(--line); transition:box-shadow .2s, transform .2s; }
.band-pick__i img{ width:100%; height:100%; object-fit:cover; display:block; }
.band-pick__i:hover{ box-shadow:inset 0 0 0 1px var(--acc); }
/* 고른 한 장 — 코발트 링. 사진 위에 글자를 얹지 않는다(어떤 사진이든 읽히게). */
.band-pick__i.on{ box-shadow:0 0 0 2px var(--acc); transform:translateY(-2px); }
@media (max-width:560px){ .band-pick{ grid-template-columns:repeat(3,minmax(0,1fr)); } }

/* ── 계좌 — 측별 그룹, 한 줄에 [은행 · 예금주 · ×] + 아래 계좌번호 ──
   근거: 편집기 핸드오프 06 GIFT. ⚠ "목록 + 아래 공용 입력 폼"으로 되돌리지 말 것. */
.acct-g{ margin-top:22px; }
.acct-g:first-of-type{ margin-top:6px; }
.acct-rows{ display:flex; flex-direction:column; }
.acct-r{ display:block; padding:13px 0; border-bottom:1px solid var(--line-soft); }
.acct-r__top{ display:flex; align-items:baseline; gap:10px; }
.acct-r__bank{ flex:1; min-width:0; font-size:15px; font-weight:400; color:var(--ink); }
.acct-r__holder{ flex:none; font-size:13px; font-weight:300; color:var(--soft); }
.acct-r__no{ margin-top:6px; font-size:14px; font-weight:300; color:var(--soft);
  letter-spacing:-.01em; word-break:break-all; }
/* 지우기 — 글자 하나. 한 번 더 누르면 되돌아온다(줄이 흐려진 상태가 그 표시다). */
.acct-r__x{ flex:none; width:24px; height:24px; padding:0; border:0; border-radius:0;
  background:none; color:var(--ghost); font-size:16px; line-height:1; transition:color .2s; }
.acct-r__x:hover{ color:var(--danger); }
.acct-r.staged-del{ opacity:.4; }
.acct-r.staged-del .acct-r__bank{ text-decoration:line-through; }
/* ⚠ 계좌 줄에는 `.item` 클래스를 붙이지 않는다. 목록이 카드였던 시절의 `.item`(사방 테두리·면)과
   `.item.staged-add`(점선 + 코발트 면)가 그대로 걸려 **입력 중인 줄만 상자로 튀었다**(2026-09-20 지적).
   줄을 찾는 JS 선택자도 `.acct-r` 로 맞춰 두었다. */
/* 새로 여는 줄 — 값 자리가 그대로 입력칸이다.
   ⚠ **선을 두지 않는다.** 줄 아래 헤어라인 하나면 충분한데, 칸마다 밑줄이 생기면 한 줄에 선이
     세 조각으로 갈라져 보인다(2026-09-20 지적).
   ⚠ 세 칸 모두 `input.클래스`(0,3,0)로 적어야 `.wiz-sec__pad input[type=text]`(0,2,1)를 이긴다 —
     `.acct-r--new input`(0,2,0)으로는 밑줄이 그대로 남는다.
   ⚠ 은행 칸에 `flex:1` 을 준다. 폭을 주지 않으면 input 기본 폭(약 170px)에 눌려
     예금주 칸이 오른쪽으로 밀리고 줄이 넘친다. */
.acct-r--new input.acct-r__bank,
.acct-r--new input.acct-r__holder,
.acct-r--new input.acct-r__no{
  border:0; background:none; padding:0; font-family:inherit;
  color:var(--ink); letter-spacing:-.01em;
}
.acct-r--new input.acct-r__bank:focus,
.acct-r--new input.acct-r__holder:focus,
.acct-r--new input.acct-r__no:focus{ outline:none; border:0; }
.acct-r--new input::placeholder{ color:var(--ghost); }
.acct-r--new input.acct-r__bank{ flex:1; min-width:0; width:auto; font-size:15px; font-weight:400; }
.acct-r--new input.acct-r__holder{ flex:none; width:90px; text-align:right; font-size:13px; font-weight:300; }
.acct-r--new input.acct-r__no{ display:block; width:100%; margin-top:6px; font-size:14px; font-weight:300; }
/* 추가 — 글자 버튼 하나(알약 금지) */
.acct-add-btn{ margin-top:12px; padding:0; border:0; background:none;
  font-family:inherit; font-size:13px; font-weight:400; color:var(--acc);
  transition:opacity .2s; }
.acct-add-btn:hover{ opacity:.7; }

/* ── 연락처 — 한 줄에 [역할 · 이름 · 전화번호] ──
   근거: 편집기 핸드오프 07 CONTACT. 이름은 다른 섹션에서 받은 값을 비춰 주기만 한다. */
.ct-list{ display:flex; flex-direction:column; margin-top:6px; }
.ct-row{ display:grid; grid-template-columns:76px minmax(0,1fr) minmax(0,150px);
  align-items:baseline; gap:12px; padding:12px 0; border-bottom:1px solid var(--line-soft); }
.ct-row__k{ font-size:11.5px; font-weight:400; color:var(--soft); }
.ct-row__n{ font-size:15px; font-weight:400; color:var(--ink);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* 번호 칸만 입력이다 — 밑줄 없이 줄 테두리에 기댄다(줄마다 선이 두 겹이 되지 않게) */
/* ⚠ 밑줄을 두지 않는다. 줄 아래에 이미 헤어라인이 있어 선이 두 겹으로 보인다
   — 명시도를 한 단 올려(`.ct-row input`) 공용 입력 규칙을 덮는다. */
.ct-row input.ct-row__t{ width:100%; padding:0; border:0; background:none; text-align:right;
  font-family:inherit; font-size:14px; font-weight:300; color:var(--ink); letter-spacing:-.01em; }
.ct-row__t:focus{ outline:none; }
.ct-row__t::placeholder{ color:var(--ghost); }
@media (max-width:560px){
  .ct-row{ grid-template-columns:70px minmax(0,1fr); row-gap:4px; }
  .ct-row__t{ grid-column:1 / -1; text-align:left; }
}

/* ═══════════════ 로그인 화면(운영자 · 고객) ═══════════════
   근거: design_handoff_lilt — README-admin-login.md · README-customer-login.md.
   두 화면은 **같은 부품**을 쓴다. 한쪽만 고치지 말 것.

   ⚠ 워드마크는 마스크로만 쓴다(색을 CSS 가 쥔다) — 잉크가 정사각 캔버스 가운데 앉은 파일이라
     박스를 가로로 넓게 잡고 contain 으로 맞춘다.
   ⚠ 로그인 버튼은 채우지 않는다. 글자 + 화살표뿐이고, 호버에서 화살표만 멀어진다. */
/* body 가 flex 라 최소폭이 내용 기준으로 잡히지 않도록 min-width 를 풀어 둔다 */
.auth{ width:100%; min-width:0; max-width:400px; margin:0 auto; }
.auth__mark{ display:block; margin:0 auto; background-color:var(--ink);
  -webkit-mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
          mask:url(../img/apple-touch-icon.png) center/contain no-repeat; }
.auth__mark--admin{ width:150px; height:82px; }
.auth__mark--cust{ width:118px; height:64px; }
.auth__sub{ margin:14px 0 0; text-align:center;
  font-size:13px; font-weight:300; color:var(--soft); letter-spacing:-.01em; }
.auth__rule{ height:1px; margin-top:26px; background:rgba(0,0,0,.08); }
.auth__panel{ margin-top:26px; padding:30px 30px 32px;
  background:#fff; border:1px solid rgba(0,0,0,.05); border-radius:0; box-shadow:none; }
.auth__note{ margin:26px 0 0; text-align:center;
  font-size:11.5px; font-weight:300; line-height:1.7; color:var(--faint); word-break:keep-all; }

/* 칸 사이는 26px — 카드 안이 넉넉해야 밑줄 입력이 줄자처럼 보이지 않는다 */
.auth__panel .field{ margin-bottom:26px; }
.auth__panel .field:last-of-type{ margin-bottom:0; }
.auth__panel .field label{ font-size:11px; color:var(--soft); }
.auth__panel .field input{ border-bottom-color:rgba(0,0,0,.14); font-size:16px; }
.auth__panel .field input:focus{ border-bottom-color:var(--ink); }

/* 오류 한 줄 — 상자를 두르지 않는다(지면에 상자가 없다) */
.auth__panel .flash{ padding:0; margin:0 0 20px; border:none; background:none; border-radius:0;
  font-size:12px; font-weight:300; color:var(--danger); animation:fadeIn .2s var(--e-in, ease); }
.auth__panel .flash-ok{ color:var(--ink); }

/* 보내기 — 글자 + 화살표. 호버에서 사이가 벌어진다 */
.auth__send{ display:flex; justify-content:flex-end; margin-top:28px; }
.btn-arrow{ display:inline-flex; align-items:center; gap:8px; padding:0; border:none;
  background:none; color:var(--ink); font-family:inherit; font-size:14px; font-weight:400;
  letter-spacing:-.01em; cursor:pointer; text-decoration:none; border-radius:0;
  transition:gap .2s, opacity .16s; }
.btn-arrow:hover{ gap:12px; opacity:.6; }
.btn-arrow[disabled]{ color:var(--faint); cursor:default; gap:8px; opacity:1; }

@media (max-width:519px){
  .auth__panel{ padding:26px 22px 28px; }
}

/* 콘솔 상단바 — 탭이 콘텐츠 칼럼으로 내려간 뒤로 헤더에는 로고와 로그아웃만 남는다.
   ⚠ 예전에는 여기서 아래 패딩만 16px 로 따로 줬다. 그 한 줄이 **클래스 두 개**라,
     아래쪽에서 세 화면을 13/13 으로 맞춘 .topbar__in 을 콘솔에서만 덮어써서
     운영자 콘솔의 로고만 위로 붙어 있었다(2026-09-22 지적). 세 화면은 같은 값을 쓴다. */

/* ═══════════════ 흰 패널 — 운영자 콘솔 · 고객 대시보드 ═══════════════
   근거: design_handoff_lilt — "content wraps in flat white panels:
   background #fff · border 1px rgba(0,0,0,.05) · no shadow · no radius".

   ⚠ **편집기에는 적용하지 않는다.** 핸드오프에서 편집기는 색만 바뀌었고 레이아웃은 그대로다
     (README-invitation-editor-color-delta.md). 그래서 body 클래스로 울타리를 친다.
   ⚠ 지면이 흰색이 아니라 따뜻한 회색(#f4f3f1)이라 흰 면이 성립한다 — 지면을 흰색으로
     되돌리면 패널이 사라져 보인다. 둘은 같이 움직인다.
   ⚠ `.card--flat`(콘솔)도 같은 패널이다. 조회 화면이라 면을 없앴던 것인데, 이 핸드오프는
     조회 화면도 패널에 담는다. 이름만 남기고 규칙을 되돌린다. */
/* ⚠ 콘솔(.adm-body) 몫은 **admin-console.css** 에 있다 — 그 파일이 뒤에 로드되며 이 값을
     통째로 덮고 있었다. 여기 남은 것은 고객 대시보드뿐이다(2026-09-22 정리). */
.dash-body .card{
  background:#fff; border:1px solid rgba(0,0,0,.05); border-radius:0;
  box-shadow:none; padding:30px 32px; margin-bottom:16px;
}
.adm-body .card:first-of-type, .dash-body .card:first-of-type{ padding-top:30px; }
@media (max-width:719px){
  .adm-body .card, .adm-body .card--flat, .dash-body .card{ padding:24px 20px; }
}

/* ═══════════════ 주 동작 — 채운 알약을 걷는다 ═══════════════
   근거: design_handoff_lilt — "flat text button, ink color, no fill/border, with a → glyph;
   hover widens the gap 8px→12px and drops to opacity .6. This replaced all solid black
   filled pill buttons project-wide."

   ⚠ **편집기는 제외다.** 핸드오프에서 편집기는 색만 바뀌었다 — 저장 버튼이 글자가 되면
     "저장한 것 같지 않다"는 지적이 그대로 돌아온다(그때 문제였던 것은 유리였지만, 지면에
     묻히는 사정은 같다). 그래서 여기도 body 클래스로 울타리를 친다.
   ⚠ 화살표는 마크업이 아니라 ::after 로 붙인다 — 같은 버튼이 네 화면에 흩어져 있어
     마크업을 일일이 고치면 하나씩 빠진다.
   ⚠ 작은 확인 버튼(.btn-sm)과 팝업의 꽉 찬 버튼(.btn-block)은 **채운 채로 둔다.**
     핸드오프도 승인 버튼 하나만은 채워 남겼다 — 줄 안에서 누르는 확인은 글자로 두면
     눌러야 할 것으로 안 읽힌다. */
.adm-body .btn-primary:not(.btn-sm):not(.btn-block),
.dash-body .btn-primary:not(.btn-sm):not(.btn-block){
  background:none; color:var(--ink); border:none; box-shadow:none;
  padding:0; gap:8px; font-weight:400;
  transition:gap .2s, opacity .16s;
}
.adm-body .btn-primary:not(.btn-sm):not(.btn-block)::after,
.dash-body .btn-primary:not(.btn-sm):not(.btn-block)::after{
  content:"\2192";                     /* → */
}
.adm-body .btn-primary:not(.btn-sm):not(.btn-block):hover,
.dash-body .btn-primary:not(.btn-sm):not(.btn-block):hover{
  background:none; gap:12px; opacity:.6;
}
.adm-body .btn-primary:not(.btn-sm):not(.btn-block):active,
.dash-body .btn-primary:not(.btn-sm):not(.btn-block):active{
  background:none; transform:none;
}
/* 고객 대시보드도 모서리를 두지 않는다(콘솔은 위에서 이미 0 이다) */
.dash-body .btn, .dash-body .pg-btn{ border-radius:0; }

/* ── [내 청첩장]의 두 동작 — **상자는 주 동작에 간다**(2026-09-29 지시) ──
   위 규칙 탓에 [청첩장 편집하기]는 맨 글씨, [청첩장 열기]는 테두리 상자였다. 주 동작이
   보조보다 약해 보여 뒤집는다: **편집하기에 테두리를 두르고, 열기에서는 뺀다.**
   ⚠ 테두리를 주면 padding 도 같이 돌려놓아야 한다 — 위 규칙이 0 으로 눌러 둔다.
   ⚠ 선택자에 클래스 넷이 필요하다(`.dash-body .btn-primary:not(.btn-sm):not(.btn-block)` 이
     이미 넷이다). 하나라도 줄이면 위 규칙에 밀려 아무 일도 일어나지 않는다. */
.dash-body .inv-acts .btn.btn-primary{
  padding:12px 20px; border:1px solid var(--line);
}
.dash-body .inv-acts .btn.btn-primary:hover{
  border-color:var(--acc); background:var(--a05, rgba(0,0,0,.03)); opacity:1;
}
/* 열기 — 새 창으로 나가는 보조 동작이라 글자와 ↗ 만 남긴다. */
.dash-body .inv-acts .btn-bare,
.dash-body .inv-acts .btn-bare:hover{ border-color:transparent; }
.dash-body .inv-acts .btn-bare{ background:none; }
.dash-body .inv-acts .btn-bare:hover{ background:var(--a05, rgba(0,0,0,.03)); }

/* ── 브라우저 기억 체크박스 ── 두 로그인 화면이 같은 부품을 쓴다.
   근거: design_handoff_lilt — 13×13px 상자(`box-shadow: inset 0 0 0 1px`),
   켜지면 잉크로 차고 `✓`, 꺼지면 윤곽선만. 글자색도 켜짐/꺼짐을 따라간다.
   ⚠ 진짜 <input type=checkbox> 를 감춰 두고 그 위에 그린다 — 키보드·스크린리더가 그대로 동작해야 한다. */
/* ⚠ `flex-end` 다 — 예전에는 왼쪽에 "브라우저 기억" 체크박스가 서서 `space-between` 이었다.
   그 칸을 걷어낸 뒤(자동 로그인은 늘 켠다) `space-between` 으로 두면 로그인 버튼이 왼쪽에 붙는다. */
.auth__foot{ display:flex; align-items:center; justify-content:flex-end;
  gap:16px; margin-top:28px; }
.auth__foot .auth__send{ margin-top:0; }
.ckbox{ display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  font-size:12.5px; font-weight:300; color:var(--soft); transition:color .2s; }
.ckbox input{ position:absolute; opacity:0; width:0; height:0; }
.ckbox__b{ flex:none; width:13px; height:13px; display:grid; place-content:center;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.2); background:none;
  font-size:9px; line-height:1; color:transparent; transition:box-shadow .2s, background-color .2s, color .2s; }
.ckbox input:checked + .ckbox__b{ background:var(--ink); box-shadow:inset 0 0 0 1px var(--ink); color:#fff; }
.ckbox:has(input:checked){ color:var(--ink); }
.ckbox input:focus-visible + .ckbox__b{ outline:2px solid var(--ink); outline-offset:2px; }

/* ── 요금제 줄(운영자 콘솔) ── 상자를 두르지 않는다. 줄과 줄은 헤어라인으로 나눈다.
   ⚠ 칸 이름은 마크업에 없다(JS 가 제출 직전에 붙인다) — 줄을 지우면 번호가 밀리기 때문이다. */
.plan-list{ margin:20px 0 14px; }
.plan-row{ padding:16px 0; border-bottom:1px solid var(--line-soft); }
.plan-row:first-child{ border-top:1px solid var(--line-soft); }
.plan-row__main{ display:grid; gap:12px 18px;
  grid-template-columns:minmax(0,1fr) minmax(0,1.4fr) minmax(0,.7fr); }
.plan-row__caps{ display:flex; align-items:flex-end; gap:18px; flex-wrap:wrap; margin-top:12px; }
.plan-f{ display:block; min-width:0; }
.plan-f__k{ display:block; margin-bottom:6px; font-size:11px; font-weight:400; color:var(--soft); }
.plan-f input{ width:100%; background:transparent; border:none; border-bottom:1px solid var(--line);
  border-radius:0; padding:0; height:32px; color:var(--ink);
  font-family:inherit; font-size:16px; font-weight:300; letter-spacing:-.012em;
  transition:border-color .2s; }
.plan-f input:focus{ outline:none; border-bottom-color:var(--ink); }
.plan-f--num{ width:72px; flex:none; }
.plan-chk{ display:inline-flex; align-items:center; gap:7px; padding-bottom:6px;
  font-size:12.5px; font-weight:300; color:var(--soft); cursor:pointer; }
.plan-chk input{ width:13px; height:13px; accent-color:var(--ink); }
.plan-del{ margin-left:auto; padding:0 0 6px; border:none; background:none; cursor:pointer;
  font-size:13px; color:var(--faint); transition:color .2s; }
.plan-del:hover{ color:var(--danger); }
@media (max-width:719px){
  .plan-row__main{ grid-template-columns:minmax(0,1fr); }
}

/* 푸터 로고도 첫 화면으로 간다(2026-09-21) — 상단바 로고와 같은 규칙이다.
   ⚠ <a> 가 인라인이라 마스크 박스가 줄상자에 앉는다. block 으로 세워 높이를 로고가 정하게 둔다. */
.site-foot .mark-link{ display:block; line-height:0; text-decoration:none;
  transition:opacity .16s; }
.site-foot .mark-link:hover{ opacity:.6; }

/* ═══════════════════════════════════════════════════════════════════════════
   편집기 다듬기 (2026-09-21 지적 반영)
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 고르는 줄(.choice) — 테두리가 비치던 것 ──
   숨긴 라디오에 크기를 주지 않아, 기본 appearance 를 그리는 브라우저에서 칸 오른쪽에
   네모 한 조각이 비쳤다(갤러리 배치 · 카운트다운 유형). 상자를 0 으로 접고 그리기를 끈다.
   ⚠ `display:none` 으로 감추지 말 것 — 키보드 탭 이동과 라벨 클릭이 함께 죽는다. */
.choice input[type=radio], .choice input[type=checkbox]{
  position:absolute; width:0; height:0; margin:0; padding:0;
  opacity:0; pointer-events:none;
  -webkit-appearance:none; appearance:none; border:0; background:none;
}
/* 마지막 안전망 — 어떤 상속도 이 칸에 테두리를 주지 못하게 못 박는다(밑줄은 box-shadow 로 그린다).
   ⚠ 이 줄에 기대어 위쪽에 테두리 선언을 되살리지 말 것. 눌러 둔 선은 캐스케이드가 조금만
     달라져도 되살아난다 — 옛 `.choice .opt` 의 1.5px 테두리는 2026-09-21 에 아예 걷어냈다. */
.choice label, .choice .opt{ border:0 !important; }

/* 배치·유형 고르기와 그 아래 스위치 줄이 딱 붙어 있었다 — 한 덩이로 읽힌다.
   ⚠ `.wiz-sec__pad` 의 flex gap(14px)은 형제 사이에만 먹는다. 여기는 `.opt-block` 안이라
     따로 띄워야 한다. */
.opt-block .choice{ margin-bottom:6px; }
.opt-block .choice + .switch-row,
.opt-block .choice ~ .switch-row{ margin-top:10px; }
.wiz-sec__pad .switch-row + .switch-row{ margin-top:6px; }

/* ── 글꼴 칸 왼쪽 선이 잘리던 것 ──
   고른 칸은 상자 **바깥으로** 2px 링을 그리는데(`box-shadow:0 0 0 2px`), 격자가 지면
   왼쪽 끝에 붙어 있어 그 2px 이 잘려 나갔다. 격자에 링만큼 자리를 주고, 잘라 내는
   컨테이너에서도 넘치도록 둔다.
   ⚠ `.wiz-sec{overflow:hidden}` 과 `content-visibility` 둘 다 자른다 — 둘 다 풀어야 보인다. */
.kfont-row{ padding:2px; margin:0 -2px; }
.wiz-sec.open, .wiz-sec.open .wiz-sec__inner{ overflow:visible; }

/* ── 공개 설정 · 주소 ──
   주소 한 줄에 라벨·규칙 안내·요금제 배지가 한꺼번에 서서 좁은 화면에서 뭉쳤다.
   라벨은 제 줄에, 안내는 그 아래로 내린다. */
.slug-head{ flex-wrap:wrap; }
.slug-head .hint{ font-size:11.5px; color:var(--faint); }
.slug-input{ gap:2px; }
.slug-prefix{ flex:none; font-size:15px; color:var(--faint); }
.slug-input input{ flex:1 1 auto; min-width:0; }
.slug-msg{ margin-top:6px; }

/* ── 상단 고정 줄 ── 로고를 키우고 높이를 준다(헤더가 납작했다) ── */
.ed-bar{ height:56px; padding-top:16px; }
/* ⚠ 음수 마진은 **투명 여백만큼만** 상쇄한다. 더 밀면 로고가 지면 왼쪽 선 밖으로 나가
     본문과 축이 어긋난다(2026-09-21). 잉크는 캔버스의 60% 남짓이라 76px 박스에서 한쪽 8px 이다. */
.ed-bar__mark{ width:76px; height:76px; margin:0 -8px 0 -8px; }
/* 대시보드와 로그아웃은 **무게가 다른 동작**이다 — 하나는 이동, 하나는 끝냄.
   같은 회색 글자 둘로 두면 어느 쪽이 무엇인지 읽히지 않는다. */
.ed-bar__link{ font-size:13px; }
.ed-bar__link--go{ color:var(--ink); font-weight:400; gap:6px; }
.ed-bar__link--go::after{ content:"\2197"; font-size:12px; transition:transform .2s; }
.ed-bar__link--go:hover::after{ transform:translate(2px,-2px); }
.ed-bar__link--out{ color:var(--faint); }
.ed-bar__link--out:hover{ color:var(--danger); }
.ed-bar__out{ margin-left:14px; padding-left:14px; border-left:1px solid var(--line-soft); }

/* 다른 화면(대시보드·콘솔)의 상단바도 같은 높이감으로.
   ⚠ 위아래를 **같은 값**으로 준다(2026-09-22) — 예전에는 위 20px / 아래 6px 이라
     로고가 띠 안에서 위로 붙어 보였다. 띠 높이(68px)는 그대로 두고 로고만 가운데로. */
.topbar__in{ padding-top:13px; padding-bottom:13px; }
/* ⚠ 위아래 마진이 다른 것은 실수가 아니다 — 마스크 캔버스 안에서 잉크(별+워드마크)가
     3px 남짓 위로 앉아 있어, 대칭으로 두면 띠 안에서 로고만 떠 보인다(2026-09-22).
     차지하는 높이는 그대로 42px(76-14-20)이고 그림만 3px 내려온다. */
.brand-mark{ width:76px; height:76px; margin:-14px 0 -20px -8px; }

/* ── 전체 저장 ── 검은 알약을 걷고 지면과 같은 어휘로 ──
   ⚠ 그래도 **채운 면**은 남긴다. 이 화면에서 가장 무거운 동작이고, 글자만 두면
     "저장한 것 같지 않다"는 지적이 돌아온다(주 버튼 규칙의 예외다). */
.savebar{ padding:10px 16px; padding-bottom:calc(10px + env(safe-area-inset-bottom)); }
.savebar #saveAllBtn{
  min-width:150px; height:46px; border-radius:0;
  background:var(--ink); color:#fff; font-size:14px; font-weight:400; letter-spacing:.01em;
  box-shadow:none; transition:opacity .16s;
}
.savebar #saveAllBtn:hover{ background:var(--ink); opacity:.84; }
.savebar #saveAllBtn[disabled]{ background:rgba(0,0,0,.12); color:var(--faint); }

/* ── 기다림 막대 ── 알약·하늘빛을 걷고 납작한 잉크 막대로 ── */
.lilt-bar{ height:3px; border-radius:0; background:rgba(0,0,0,.1); }
.lilt-bar__fill{ border-radius:0; background:var(--ink); }

/* ── 스크롤바 ── 지면 색에 맞춘 가는 막대 ── */
html{ scrollbar-width:thin; scrollbar-color:rgba(0,0,0,.22) transparent; }
::-webkit-scrollbar{ width:9px; height:9px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{ background:rgba(0,0,0,.18); border:3px solid transparent;
  background-clip:content-box; border-radius:999px; }
::-webkit-scrollbar-thumb:hover{ background:rgba(0,0,0,.32); background-clip:content-box; }
/* 상단 줄의 로고 링크 — 마스크 박스가 줄상자에 앉지 않게 block 으로 세운다 */
.ed-bar__home{ display:block; line-height:0; text-decoration:none; transition:opacity .16s; }
.ed-bar__home:hover{ opacity:.6; }

/* ── 상세 머리말은 **붙박이**다 (2026-09-21) ──
   아래로 한참 내려가도 지금 어떤 항목인지, [‹ 목록]으로 돌아가는 길이, 사용 토글이
   늘 손 닿는 곳에 있어야 한다. 그 전에는 스크롤을 끝까지 올려야 목록으로 나갈 수 있었다.

   ⚠ `position:sticky` 는 **조상 중 하나라도 `overflow:hidden`이면 죽는다.**
     `.wiz-sec`·`.wiz-sec__inner` 의 overflow 를 열린 섹션에서 풀어 둔 이유가 이것이다.
   ⚠ 안내문(.wiz-sec__lead)은 머리말 **안**으로 옮겼다(paint 함수) — 바깥에 두면 혼자 올라간다.
   ⚠ 지면과 같은 색을 깔아 둔다. 투명이면 아래 글이 머리말을 통과해 겹쳐 보인다. */
body.wiz-detail .wiz-sec.open .wiz-sec__head{
  position:sticky; top:0; z-index:12;
  background:var(--bg);
  /* ⚠ 위 패딩은 **상단 줄(.ed-bar)이 덮는 높이**다. 지금 그 줄은 56px + 위 패딩 16px 이고,
     로고(76px)가 음수 마진으로 걸쳐 있어 실제로는 그보다 조금 더 내려온다. 88px 은 그 값이다.
     ⚠ .ed-bar 의 높이를 고치면 **여기와 아래 [‹ 목록] 의 top 도 함께** 고칠 것 —
       모자라면 제목이 상단 줄에 가려지고, 남으면 머리말이 허공에 뜬다. */
  padding:calc(88px + env(safe-area-inset-top)) 0 0;
  margin:0 0 4px;
}
/* 붙박이가 된 뒤로 [‹ 목록] 의 기준선도 함께 내려온다 */
body.wiz-detail .wiz-sec.open .wiz-sec__back{ top:calc(94px + env(safe-area-inset-top)); }
/* 안내문이 머리말 안으로 들어오면서 위 여백은 머리말이 쥔다 */
body.wiz-detail .wiz-sec.open .wiz-sec__lead{ padding-bottom:18px; }
body.wiz-detail .wiz-sec.open .wiz-sec__lead::after{ margin-top:18px; }
/* 머리말이 제 패딩으로 상단 줄 자리를 만드므로 지면의 위 여백은 걷는다 */
body.wiz-detail .wrap--split{ padding-top:0; }

/* ═══ 예식일 고르는 창 (2026-09-21 다시 그림) ═══
   "기본 UI 라 투박하다"는 지적을 받은 자리다. 알약 손잡이·네이티브 셀렉트 상자·틴트 면을
   걷고, 이 지면의 어휘(글자 · 밑줄 · 각진 면 · 잉크 한 색)로 맞춘다.

   ⚠ 2026-09-19 에 "달력 손잡이는 알약"이라고 정했던 것은 **코발트 시절 규칙**이다.
     지금 지면에는 radius 가 없다 — 되살리지 말 것.
   ⚠ 이 창은 **두 화면이 함께 쓴다**(대시보드 홈 · 편집 화면). 한쪽만 보고 고치지 말 것. */
.modal__box:has(.dtpick){ max-width:392px; }
/* 달력은 상자 안의 상자가 아니다 — 테두리를 걷고 모달 본문에 그대로 얹는다 */
.dtpick{ overflow:visible; }

/* 연·월 줄 — 가운데 글자, 양옆에 테두리 없는 화살표 */

/* 요일 줄 — 색으로 나누지 않는다(지면에 채도가 없다). 토·일은 옅게만 */

/* 날짜 칸 — 각진 면. 고른 날만 잉크로 찬다 */

/* 시각 — 오전·오후는 글자 나열(.choice 와 같은 어휘), 시·분은 밑줄 */

/* 창 자체 — 제목·바닥글을 지면과 같은 결로 */
.modal__box:has(.dtpick) .modal__head{ padding:24px 24px 0; border-bottom:none; }
.modal__box:has(.dtpick) .modal__title{ font-size:20px; font-weight:300; letter-spacing:-.02em; }
.modal__box:has(.dtpick) .modal__sub{ margin-top:6px; font-size:12.5px; font-weight:300; }
.modal__box:has(.dtpick) .modal__body{ padding:20px 24px 4px; }
.modal__box:has(.dtpick) .modal__foot{ padding:16px 24px 22px; border-top:none; gap:14px; }
/* [나중에]는 물러나는 길, [저장]은 하려던 일 — 무게를 다르게 둔다 */
.modal__box:has(.dtpick) .modal__foot .btn-ghost{
  border:none; background:none; color:var(--soft); padding:0; height:auto; font-weight:300; }
.modal__box:has(.dtpick) .modal__foot .btn-ghost:hover{ color:var(--ink); background:none; }
.modal__box:has(.dtpick) .modal__foot .btn-primary{
  margin-left:auto; height:44px; padding:0 22px; border-radius:0;
  background:var(--ink); color:#fff; font-weight:400; }
.modal__box:has(.dtpick) .modal__foot .btn-primary[disabled]{
  background:rgba(0,0,0,.1); color:var(--faint); }
/* 주소 칸 — 라벨 줄과 규칙 안내를 나눈다(2026-09-21) */
.slug-head{ display:flex; align-items:center; gap:8px; margin-bottom:2px; }
.slug-rule{ font-size:11.5px; font-weight:300; color:var(--faint); margin-bottom:8px; }
/* `.opt-block` 은 flex 가 아니라 흐름이라 `.wiz-sec__pad` 의 gap 이 안쪽까지 먹지 않는다.
   그대로 두면 안내문과 첫 입력이 붙어 한 덩이로 읽힌다(혼주 · 중간 사진에서 드러났다). */
.opt-block > * + *{ margin-top:14px; }
.opt-block > .wiz-hint{ margin-bottom:2px; }
/* 섹션 안의 넓은 보조 버튼(방명록 관리 등) — 알약을 걷는다. 이 지면에 둥근 것은 없다. */
.wiz-sec__pad .btn-ghost.btn-block{ border-radius:0; height:46px; font-weight:400; }
/* ── 편집기 버튼도 각지다 ── 지면 규칙(radius 0)을 마지막까지 따르지 않은 자리가 남아 있었다:
   [미리보기] · [QR 만들기] · [사진 선택] · [처음으로] 같은 알약들.
   ⚠ 알약으로 남기는 것은 **점·배지**뿐이다(칩, 완료 점, 개수 표시). */
.wiz-sec__pad .btn, .wiz .btn, .modal__foot .btn{ border-radius:0; }
.wiz-sec__pad .btn-primary{ background:var(--ink); color:#fff; font-weight:400; }
.wiz-sec__pad .btn-primary:hover{ background:var(--ink); opacity:.84; }
/* 팝업 안의 채운 버튼에는 화살표를 붙이지 않는다.
   `→` 는 **지면을 떠나 어딘가로 간다**는 표식이라, 그 자리에서 끝나는 저장에는 맞지 않는다.
   (고객 대시보드의 주 버튼 규칙이 팝업 안까지 따라 들어와 붙었다 — 2026-09-21) */
.modal .btn-primary::after{ content:none !important; }

/* ── 고객 대시보드 상단바는 **읽기 칸(880px)에 맞춘다** (2026-09-21) ──
   콘솔은 `--side` 를 제 폭(1100px)으로 다시 정의해 헤더와 본문의 좌우 끝점이 맞는데,
   대시보드만 공통 토큰(1240px 기준)을 쓰고 있어 로고·로그아웃이 본문보다 바깥에 섰다.
   ⚠ `.wrap` 의 좌우 패딩 16px 까지 더해야 글자 시작점이 같아진다(max-width 에 패딩이 포함된다).
   ⚠ 푸터도 같은 값을 쓴다 — 한 곳만 고치면 아래 선만 어긋난다. */
.dash-body{ --side:max(16px, calc((100vw - 880px) / 2 + 16px)); }

/* ═══════════════ 기다림 — 하나의 어휘로 (2026-09-21 다시 만듦) ═══════════════
   "프로그레스바가 마음에 안 든다"는 지적을 두 번 받은 자리다. 세 곳(폼 대기 · 저장 · 미리보기)이
   저마다 다른 모양이었고, 파란 shimmer 와 남색 유리판이 남아 있었다.

   ★ 어휘 하나로 통일한다 — **지면색 판 · 워드마크 · 1px 헤어라인 위를 훑는 잉크 선 · 조용한 한 줄.**
   ⚠ 어두운 판(남색·검정 스크림)으로 되돌리지 말 것. 이 서비스의 기다림은 화면을 덮어 가리는
     일이 아니라 "잠깐 멈춰 있다"를 알리는 일이다.
   ⚠ 원형 링·퍼센티지는 예전에 걷어냈다(그때 이유가 지금도 유효하다).
   ⚠ shimmer(뼈대 그림)도 쓰지 않는다 — 내용이 있는 척하는 그림이라, 실제와 다르면 더 어수선하다. */

/* 판 — 지면색을 덮는다. 뒤가 비쳐야 무엇을 기다리는지 보인다. */
.lilt-wait, .save-overlay{
  background:rgba(244,243,241,.92);
  -webkit-backdrop-filter:none; backdrop-filter:none;
  gap:0;
}
/* 가운데 한 덩이 — 워드마크 · 선 · 글자 */
.lilt-wait .lilt-bar, .save-overlay .lilt-bar{
  position:relative; width:min(180px, 52vw); height:1px;
  margin:0 0 14px; background:rgba(0,0,0,.12);
  border:none; border-radius:0; box-shadow:none;
  -webkit-backdrop-filter:none; backdrop-filter:none;
}
/* 워드마크는 선 위에 얹는다 — 가짜 요소라 마크업을 건드리지 않는다 */
.lilt-wait .lilt-bar::before, .save-overlay .lilt-bar::before{
  content:""; position:absolute; left:50%; bottom:22px;
  width:74px; height:40px; transform:translateX(-50%);
  background-color:rgba(0,0,0,.3);
  -webkit-mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
          mask:url(../img/apple-touch-icon.png) center/contain no-repeat;
  animation:liltBreath 1.9s ease-in-out infinite;
}
@keyframes liltBreath{ 0%,100%{ opacity:.35 } 50%{ opacity:.85 } }
.lilt-wait .lilt-bar__fill, .save-overlay .lilt-bar__fill{
  height:1px; background:var(--ink); box-shadow:none; border-radius:0;
}
.lilt-wait__label, .save-overlay__label{
  font-size:12px; font-weight:300; letter-spacing:-.01em; color:var(--soft);
  text-shadow:none; margin-top:2px;
}
/* 끝을 모르는 기다림 — 선 하나가 좌에서 우로 훑는다 */
.lilt-bar.is-indeterminate .lilt-bar__fill{
  width:34%; animation:liltSweep 1.25s cubic-bezier(.65,.05,.36,1) infinite;
}
@keyframes liltSweep{ 0%{ transform:translateX(-110%) } 100%{ transform:translateX(320%) } }
@media (prefers-reduced-motion:reduce){
  .lilt-bar.is-indeterminate .lilt-bar__fill{ width:100%; animation:none; opacity:.45; }
  .lilt-wait .lilt-bar::before, .save-overlay .lilt-bar::before{ animation:none; opacity:.55; }
}

/* 저장 진행바(하단 띠 위) — 같은 결로 가늘게 */
.savebar__progress{ height:1px; background:rgba(0,0,0,.08); }
.savebar__bar{ background:var(--ink); border-radius:0; }

/* ═══ 기다림 표시 = 반짝이는 별(2026-09-29) ═══
   로그인 대기(.lilt-wait) · 전체 저장(.save-overlay) · 편집 미리보기 불러오기(.pv__prog) 의 가는 선과 워드마크를
   걷고, 첫 화면 샘플 미리보기와 **같은 별**로 바꿨다. bridge/spark.png = 64px 12칸을 가로로 이은 768×64.
   ⚠ steps(12) · 칸 폭(384px = 32px×12) · 그림은 한 벌 — bridge.css 의 .tpv__spark 와 같은 값이다.
   ⚠ 진행률(업로드 width)은 보여 주지 않는다 — 숫자·막대는 원래도 "가고 있다"만 알리는 용도였다.
   ⚠ 칸을 넘기는 건 `background-position` 이 아니라 **`transform`** 이다 — 앞엣것은 메인 스레드에서만
     돌아서, 페이지가 떠나는 중(조회·새로고침)이면 모바일에서 첫 칸에 멈춰 버린다. 되돌리지 말 것. */
.lilt-wait .lilt-bar, .save-overlay .lilt-bar, .pv__prog{
  position:relative; width:32px; height:32px; margin:0 0 14px; overflow:hidden;
  background:none; }
/* 12칸을 가로로 이은 판을 창 안에서 왼쪽으로 민다(판은 ::before, 창이 .lilt-bar). */
.lilt-wait .lilt-bar::before, .save-overlay .lilt-bar::before, .pv__prog::before{
  content:""; display:block; position:absolute; top:0; left:0; bottom:auto;
  width:384px; height:32px;
  background:url(../bridge/spark.png) 0 0/384px 32px no-repeat;
  background-color:transparent;
  -webkit-mask:none; mask:none;
  transform:translate3d(0,0,0); will-change:transform;
  animation:liltSpark 1.5s steps(12) infinite; }
.lilt-wait .lilt-bar__fill, .save-overlay .lilt-bar__fill,
.pv__prog span, .pv__bar-wrap::before{ display:none; }
@keyframes liltSpark{ to{ transform:translate3d(-384px,0,0); } }
/* 동작 줄이기에서도 멈춰 선 그림만 남기지는 않는다 — 칸은 넘기지 않고 숨만 쉰다 */
@media (prefers-reduced-motion:reduce){
  .lilt-wait .lilt-bar::before, .save-overlay .lilt-bar::before, .pv__prog::before{
    animation:liltBreath 1.9s ease-in-out infinite; } }

/* ═══════════════ 예식 일시 선택기 (2026-09-21 새로 만듦) ═══════════════
   마크업은 `assets/js/datepicker.js` 가 그린다. 클래스 이름은 전부 `dtp-` 다 —
   옛 `dt-` 규칙과 섞이지 않게 새로 붙였으니 되살려 섞지 말 것.

   ★ 어휘: 글자 · 밑줄 · 각진 면 · 잉크 한 색. 상자도 알약도 없다.
   ⚠ 머리 글자(연·월)를 누르면 **연·월 고르기 판**이 달력 자리에 뜬다(둘을 함께 세우지 않는다).
   ⚠ 이 선택기는 **두 화면이 함께 쓴다**(대시보드 홈 · 편집 화면 팝업). 한쪽만 보고 고치지 말 것. */
.dtpick{ border:none; border-radius:0; background:none; }
.dtpick--editor{ width:min(100%, 460px); margin:0 auto; padding:12px 0 6px; }

/* 머리 줄 — ‹ 2026년 10월 › */
.dtp__head{ display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:0 0 14px; }
.dtp__title{ flex:1; border:none; background:none; padding:4px 0; cursor:pointer;
  font-family:inherit; font-size:17px; font-weight:400; letter-spacing:-.02em; color:var(--ink);
  transition:opacity .16s; }
.dtp__title:hover{ opacity:.6; }
.dtp__title.is-open{ box-shadow:inset 0 -1px 0 0 var(--ink); }
.dtp__nav{ flex:none; width:34px; height:34px; border:none; background:none; cursor:pointer;
  font-size:17px; line-height:1; color:var(--soft); transition:color .18s; }
.dtp__nav:hover{ color:var(--ink); }

/* 연·월 고르기 판 */
.dtp__jump[hidden]{ display:none; }
.dtp__jump-year{ display:flex; align-items:center; justify-content:center; gap:10px;
  padding-bottom:12px; }
.dtp__jump-y{ min-width:76px; text-align:center;
  font-size:15px; font-weight:400; letter-spacing:-.02em; color:var(--ink); }
.dtp__jump-months{ display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:2px; }
.dtp__month{ height:44px; border:none; background:none; cursor:pointer; border-radius:0;
  font-family:inherit; font-size:14px; font-weight:300; color:var(--ink);
  transition:background-color .16s, color .16s; }
.dtp__month:hover{ background:rgba(0,0,0,.05); }
.dtp__month.is-on{ background:var(--ink); color:#fff; font-weight:400; }

/* 요일 · 날짜 */
.dtp__cal[hidden]{ display:none; }
.dtp__week{ display:grid; grid-template-columns:repeat(7, minmax(0,1fr)); }
.dtp__week span{ text-align:center; padding:0 0 8px;
  font-size:10.5px; font-weight:400; letter-spacing:.06em; color:var(--faint); }
.dtp__days{ display:grid; grid-template-columns:repeat(7, minmax(0,1fr)); gap:2px; }
.dtp__day{ height:40px; display:flex; align-items:center; justify-content:center;
  border:none; border-radius:0; background:none; cursor:pointer;
  font-family:inherit; font-size:14px; font-weight:300; color:var(--ink);
  transition:background-color .16s, color .16s; }
.dtp__day.is-empty{ visibility:hidden; cursor:default; }
.dtp__day:hover:not(.is-empty):not(.is-on){ background:rgba(0,0,0,.05); }
/* 오늘 — 고른 날과 헷갈리지 않게 **점 하나**로만 표시한다(면을 채우지 않는다) */
.dtp__day.is-today{ position:relative; }
.dtp__day.is-today::after{ content:''; position:absolute; left:50%; bottom:7px;
  width:3px; height:3px; margin-left:-1.5px; border-radius:50%; background:var(--faint); }
.dtp__day.is-on{ background:var(--ink); color:#fff; font-weight:400; }
.dtp__day.is-on.is-today::after{ background:rgba(255,255,255,.7); }

/* 시각 */
.dtp__time{ margin-top:20px; padding-top:18px; border-top:1px solid var(--line-soft); }
.dtp__lab{ font-size:11px; font-weight:400; color:var(--soft); margin-bottom:12px; }
.dtp__time-row{ display:flex; align-items:flex-end; gap:16px; flex-wrap:wrap; }
.dtp__ampm{ display:flex; gap:12px; }
.dtp__seg{ border:none; background:none; padding:0 0 4px; cursor:pointer;
  font-family:inherit; font-size:15px; font-weight:400; color:var(--soft);
  box-shadow:none; transition:color .2s, box-shadow .2s; }
.dtp__seg.is-on{ color:var(--ink); box-shadow:inset 0 -2px 0 -0.5px var(--ink); }
.dtp__unit{ position:relative; }
.dtp__value{ min-width:54px; padding:0 18px 4px 2px; border:0;
  border-bottom:1px solid var(--line); border-radius:0; background:none;
  color:var(--ink); font-family:inherit; font-size:14px; font-weight:300;
  text-align:left; cursor:pointer; }
.dtp__value::after{ content:"⌄"; position:absolute; right:2px; color:var(--faint); }
.dtp__value[aria-expanded="true"]{ border-bottom-color:var(--ink); }
.dtp__menu{ position:absolute; z-index:8; top:calc(100% + 7px); left:0;
  display:grid; grid-template-columns:repeat(3, 42px); gap:1px; padding:5px;
  border:1px solid var(--line); background:var(--card, #fff);
  box-shadow:0 14px 30px -22px rgba(0,0,0,.45); }
.dtp__menu[hidden]{ display:none; }
.dtp__option{ min-height:34px; padding:0; border:0; border-radius:0; background:none;
  color:var(--soft); font-family:inherit; font-size:12px; font-weight:300; cursor:pointer; }
.dtp__option:hover{ background:rgba(0,0,0,.045); color:var(--ink); }
.dtp__option.is-on{ background:var(--ink); color:#fff; }

/* ═══════════════ 편집기 활자·여백 다듬기 (2026-09-21) ═══════════════
   "폰트가 너무 크고 좌우 여백이 없어 효도폰 같다, 미니멀한 느낌이 없다"는 지적.

   ★ 무엇을 줄였나
     · 값 입력 18px → **16.5px**(iOS 자동확대 하한 16px 은 지킨다)
     · 섹션 제목 16px → 15px · 상세 제목 22px → 20px
     · 좌우 패딩 17px → **26px**(상세는 더 넉넉히), 세로 gap 14px → 20px
   ⚠ **16px 아래로 내리지 말 것** — iOS Safari 가 포커스 때 화면을 확대한다.
   ⚠ 여백을 늘리는 것이 곧 미니멀이다. 글자를 더 줄이는 쪽으로 가지 말 것 —
     넓은 연령대가 쓰는 화면이라 읽는 크기는 지켜야 한다. */
.wiz-sec__pad{ padding:2px 26px 24px; gap:20px; }
.wiz-sec__head{ padding-left:26px; padding-right:26px; }
.wiz-sec__label{ font-size:15px; }
body.wiz-detail .wiz-sec.open .wiz-sec__label{ font-size:20px; }
body.wiz-detail .wiz-sec.open .wiz-sec__pad{ padding:26px 6px 22px; }

/* 값 입력 — 한 단계 낮춘다(라벨과의 대비는 그대로 유지된다) */
.wiz-sec__pad input[type=text], .wiz-sec__pad input[type=tel],
.wiz-sec__pad input[type=url], .wiz-sec__pad input[type=number],
.wiz-sec__pad input[type=date], .wiz-sec__pad input[type=time],
.wiz-sec__pad textarea, .wiz-sec__pad select,
.field input, .field select, .field textarea{
  font-size:16.5px;
}
.field textarea, .wiz-sec__pad textarea{ font-size:16px; line-height:1.8; }
.wiz-f__label{ font-size:11px; margin-bottom:9px; }
.wiz-hint{ font-size:11.5px; }

/* 목록 행도 같은 여백을 쓴다 — 헤더와 본문의 좌우 선이 어긋나면 그것만 튄다 */
.wiz{ margin:0; }

/* 좁은 화면에서는 여백을 조금 줄인다(26px 면 390px 에서 내용 폭이 338px 뿐이다) */
@media (max-width:519px){
  .wiz-sec__pad{ padding:2px 18px 22px; gap:18px; }
  .wiz-sec__head{ padding-left:18px; padding-right:18px; }
  body.wiz-detail .wiz-sec.open .wiz-sec__pad{ padding:12px 2px 20px; }
}

/* ── 예시 문구 버튼 — 갤러리 배치(.choice--gal)와 **같은 줄**이 되게 ──
   `.choice` 는 라벨 안의 라디오를 전제로 짜여 있는데 여기는 버튼이라, 칸 크기·간격이
   저 혼자 달랐다. 버튼도 같은 자리에 서도록 맞춘다. */
.choice--preset{ gap:16px 18px; margin-top:2px; }
.choice--preset .opt{
  display:block; padding:0 0 5px; border:0; border-radius:0; background:none;
  font-size:15px; font-weight:400; color:var(--soft); cursor:pointer;
  box-shadow:none; transform:translateY(0);
  transition:color .26s, box-shadow .26s,
    transform .34s var(--e-spring, cubic-bezier(.34,1.56,.64,1));
}
.choice--preset .opt:hover{ color:var(--ink); }
.choice--preset .opt.is-on{
  color:var(--ink); box-shadow:inset 0 -2px 0 -0.5px var(--ink); transform:translateY(-2px);
}

/* ── 저장바의 세 부품 (2026-09-21) ──
   [보관함 아이콘] [임시 저장] [결제하기] — 무게가 셋 다 달라야 한다.
   ⚠ 보관함 아이콘은 **선으로 그린 SVG** 다. 이모지로 되돌리지 말 것(OS 마다 다른 그림 + 컬러). */
.savebar__box{ width:40px; height:46px; border-radius:0; color:var(--soft); }
.savebar__box svg{ width:19px; height:19px; display:block; }
.savebar__box:hover{ background:none; color:var(--ink); }
.savebar__dot{ top:11px; right:7px; }

/* 임시 저장 — 되돌릴 수 있는 가벼운 동작이라 **글자만** 둔다(선도 면도 없다) */
.btn-quiet{
  height:46px; padding:0 8px; border:none; background:none; border-radius:0;
  color:var(--soft); font-weight:400; box-shadow:none;
  transition:color .18s;
}
.btn-quiet:hover{ color:var(--ink); background:none; }

/* 결제하기 — 돈이 오가는 자리라 이 화면에서 가장 무겁다. 각진 잉크 면 하나. */
.savebar #payOpenBtn{
  min-width:132px; height:46px; border-radius:0;
  background:var(--ink); color:#fff; font-size:14px; font-weight:400; letter-spacing:.01em;
  box-shadow:none; transition:opacity .16s;
}
.savebar #payOpenBtn:hover{ background:var(--ink); opacity:.84; }
.savebar #payOpenBtn::after{ content:none; }

/* ── 모바일 미리보기 — 닫힌 플로팅 아이콘 대신 저장바의 작은 보조 버튼으로 연다 ── */
.savebar__preview{ display:none; }
@media (max-width:1023.98px){
  .savebar__inner{ justify-content:flex-end; gap:10px; }
  .savebar__url, .savebar__hint{ display:none; }
  .savebar__preview{
    flex:0 0 auto; height:46px; padding:0 13px;
    display:inline-flex; align-items:center; justify-content:center; gap:7px;
    border:1px solid var(--line); border-radius:0; background:#fff; color:var(--ink);
    font:inherit; font-size:12.5px; font-weight:400; cursor:pointer;
  }
  .savebar__preview svg{ width:16px; height:16px; display:block; }
  /* 미리보기는 **맨 오른쪽**이다(2026-09-21 고객 지시) — 결제하기보다도 뒤.
     저장은 갈래마다 다른 버튼이라(전체 저장/임시 저장) 마크업을 갈래별로 늘리는 대신
     order 로 자리만 바꾼다.
     차례: [보관함] [임시 저장] [결제하기] [미리보기] / 결제 뒤에는 [전체 저장] [미리보기]. */
  .savebar #payOpenBtn{ order:1; }
  .savebar__preview{ order:2; }

  /* ── 보조 동작은 **한 어휘**로 (2026-09-21) ──
     보관함·임시 저장·미리보기는 무게가 같은 곁동작이다. 예전에는 셋이 제각각이었다
     (아이콘만 40px / 글자만 / 선 두른 46px) — 한 줄에 서면 그것만 눈에 걸렸다.
     ⚠ 채운 면은 주 동작 하나뿐이라는 규칙은 그대로다(결제하기·전체 저장). */
  .savebar__box,
  .savebar__preview,
  .savebar .btn-quiet{
    height:46px; border:1px solid var(--line); border-radius:0;
    background:#fff; color:var(--ink); box-shadow:none;
    transition:border-color .18s, color .18s;
  }
  .savebar__box{ width:46px; }
  .savebar .btn-quiet{ padding:0 14px; font-size:12.5px; font-weight:400; }
  .savebar__box:hover,
  .savebar__preview:hover,
  .savebar .btn-quiet:hover{ border-color:var(--ink); background:#fff; color:var(--ink); }
  .savebar__dot{ top:11px; right:10px; }
  /* 미리보기 본체는 열린 동안에만 전체화면으로 표시한다. 닫힌 플로팅 상태는 없다. */
  body:not(.mpv-open) .mpv{ display:none; }
  body.mpv-open .mpv{ display:block; box-shadow:none; }
}
@media (max-width:520px){
  .savebar__inner{ display:flex; gap:8px; }
  .savebar__preview{ width:46px; padding:0; }
  .savebar__preview span{ display:none; }
  /* 남는 폭은 **주 동작**이 갖는다 — 네 개가 한 줄에 서는 체험자 화면에서도 넘치지 않는다.
     (보관함 46 + 임시 저장 + 미리보기 46 + 결제하기 나머지) */
  .savebar #saveAllBtn,
  .savebar #payOpenBtn{ width:auto; min-width:0; flex:1 1 auto; }
  .savebar .btn-quiet{ flex:0 0 auto; padding:0 10px; }
}

/* 임시 보관함 — 삭제는 제목 줄 오른쪽 끝에 선다(결제하기·불러오기와 붙이지 않는다). 제목이 길면 제목만 말줄임된다. */
.draft-row__hd{ display:flex; align-items:baseline; gap:10px; }
.draft-row__hd .draft-row__t{ flex:1 1 auto; min-width:0; }
.draft-row__hd .draft-rm{ flex:none; }
/* 소멸 기한 안내 — 다른 안내보다 한 톤 진하게, 왼쪽 선으로 세운다. */
.draft-note--warn{ margin-top:10px; padding-left:10px; border-left:2px solid var(--danger); color:var(--ink); }
.draft-note--warn b{ font-weight:600; }
