/* 앱 공통 레이아웃 · UI 키트 (리드 소유). tokens.css 위에 얹습니다. 계약: ARCH.md §8-4.
   기준: _design/v2/final/tokens.css 의 컴포넌트 클래스를 같은 이름 · 같은 값으로 옮김(1:1). 다른 점은 둘뿐:
     ① flex gap · inset 대신 마진 · top/left (옛 WebView, tests/lint.sh)  ② dvh · clamp · min 앞에 옛 브라우저용 값 한 줄.
   "옛 이름" 표시가 붙은 규칙은 레인이 새 클래스로 옮기는 동안만 두는 별칭입니다(새 코드에서 쓰지 않기).
   화면 고유 모양은 각 레인 css 에, 이름 앞에 f- l- a- g- e- 를 붙입니다. */

/* ---------- 아이콘: Lucide 선 아이콘 1.5px (스프라이트 i-*), 16 · 20 · 24 ---------- */
.ic { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; flex: none; vertical-align: middle; }
.ic-16 { width: 16px; height: 16px; }
.ic-24 { width: 24px; height: 24px; }
svg.k { width: 20px; height: 20px; flex: none; fill: #000; stroke: none; vertical-align: middle; }   /* 카카오톡 심볼 (k-talk) */
svg.m { display: inline-block; vertical-align: middle; overflow: visible; stroke: none; flex: none; }   /* 옛 이름: 면 그림 스프라이트 m-* (은퇴 예정) */
.hh { display: inline-block; width: .6em; height: 1px; visibility: hidden; }   /* 옛 이름: 이름 사이 하트 → 그리지 않음(빈칸) */
.grow { -webkit-box-flex: 1; flex: 1 1 auto; min-width: 0; }

/* ---------- 화면 틀 ---------- */
#app { position: relative; }
.app-h { min-height: 100vh; min-height: calc(var(--vh, 1vh) * 100); }
/* 화면 들어올 때: 불투명도만 (움직이지 않음 · 고정 바가 따라 움직이지 않게 transform 없음) */
.screen { min-height: 100vh; min-height: calc(var(--vh, 1vh) * 100); padding-bottom: var(--dock-pad, 0px);
  -webkit-transition: opacity var(--t-mid) linear; transition: opacity var(--t-mid) linear; }
.screen.enter { opacity: 0; }
.screen.no-pad { padding-bottom: 0; }
html.rm { --t-mid: 0ms; --t-slow: 0ms; }   /* 저사양 · 동작 줄이기: 이름이 선명해지는 160ms 만 남김 */
.page { padding: 24px var(--m) 0; }
.stack > * + * { margin-top: 12px; }
.stack-lg > * + * { margin-top: 24px; }
.stack-sm > * + * { margin-top: 8px; }
.row { display: -webkit-box; display: flex; align-items: center; }
.row > * + * { margin-left: 8px; }
body.adm { max-width: none; background: #F8F3EC; }   /* 관리자: 넓게 · 단색 (main.js 가 /admin 에서 붙임) */
body.wide { max-width: none; }                       /* 녹화 무대처럼 화면 전체를 쓰는 곳 (레인이 붙였다 뗌) */

/* ---------- 머리 ---------- */
.hd { height: 56px; display: -webkit-box; display: flex; align-items: center; justify-content: space-between; margin: 0 var(--m); }
.hd.ruled { border-bottom: 1px solid var(--line); }
.hd .logo, .logo-s { display: block; height: 18px; width: auto; }
.hd-acts { display: -webkit-box; display: flex; align-items: center; margin-right: -12px; }
.hd-act { min-width: 44px; height: 44px; padding: 0 12px; display: -webkit-inline-box; display: inline-flex; align-items: center; justify-content: center;
  font: 500 .875rem/1 var(--sans); color: var(--ink); }
.hd-act > * + * { margin-left: 4px; }
.hd-act.rose { color: var(--rose); }
.nav { height: 56px; display: -webkit-box; display: flex; align-items: center; margin: 0 var(--m); border-bottom: 1px solid var(--line); }
.nav > * + * { margin-left: 4px; }
.nav .back, .back { width: 44px; height: 44px; margin-left: -12px; display: -webkit-box; display: flex; align-items: center; justify-content: center; flex: none; color: var(--ink); }
.nav .back.lbl { width: auto; padding: 0 8px; font: 500 .9375rem/1 var(--sans); }
.nav .back.lbl > * + * { margin-left: 2px; }
.nav .ttl, .topbar-title { -webkit-box-flex: 1; flex: 1 1 auto; min-width: 0; font: 600 1rem/1.3 var(--sans); letter-spacing: -.02em; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav .side { font: 500 .875rem/1 var(--sans); color: var(--stone); display: -webkit-inline-box; display: inline-flex; align-items: center; white-space: nowrap; }
.nav .side > * + * { margin-left: 6px; }
.menu-btn { width: 44px; height: 44px; display: -webkit-box; display: flex; align-items: center; justify-content: center; color: var(--ink); }   /* 옛 이름 */
.scrim-lift { position: relative; z-index: 9; }   /* 시트가 열려도 로고 줄은 종이 그대로 */
.hd.scrim-lift { margin: 0; padding: 0 var(--m); }

/* ---------- 버튼: 채운 버튼은 화면에 하나. 나머지는 선 또는 글자 ---------- */
.btn { display: -webkit-box; display: flex; align-items: center; justify-content: center; width: 100%; min-height: 56px; padding: 0 20px;
  border-radius: var(--r-1); background: var(--berry); color: #fff; font: 600 1rem/1.2 var(--sans); letter-spacing: -.01em; text-align: center;
  -webkit-transition: opacity var(--t-fast) linear; transition: opacity var(--t-fast) linear; }
.btn > * + * { margin-left: 8px; }
.btn:active { opacity: .88; }
.btn.line, .btn.btn-ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.btn.berry-line, .btn.btn-outline { background: transparent; color: var(--berry); box-shadow: inset 0 0 0 1px var(--berry); }
.btn.md, .btn.btn-md { min-height: 48px; font-size: .9375rem; }
.btn.sm, .btn.btn-sm { width: auto; min-height: 48px; padding: 0 16px; font-size: .875rem; }   /* 작은 행동도 높이 48 */
.btn.kakao, .btn.btn-kakao { background: var(--kakao); color: rgba(0, 0, 0, .85); font-weight: 700; border-radius: 12px; box-shadow: none; }
.btn.kakao .k, .btn.kakao .ic { width: 20px; height: 20px; fill: #000; stroke: none; }
.btn.off, .btn[disabled], .btn[aria-disabled="true"] { background: var(--seg-bg); color: #8E7E78; box-shadow: inset 0 0 0 1px var(--line-2); pointer-events: none; }
.btn[aria-busy="true"] { cursor: progress; }   /* 저장 중: 흐리게 하지 않는다. 글자만 바뀜 (WD.ui.busy) */
.btn .ic { width: 20px; height: 20px; }
.btn-text { display: -webkit-inline-box; display: inline-flex; align-items: center; justify-content: center; min-height: 48px; padding: 0 8px;
  font: 500 .9375rem/1.3 var(--sans); color: var(--rose); text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px;
  background: none; box-shadow: none; width: auto; }
.btn-text > * + * { margin-left: 4px; }
.btn-text.ink { color: var(--ink); }
.btn.btn-text { display: -webkit-inline-box; display: inline-flex; width: auto; min-height: 48px; padding: 0 8px; background: none; color: var(--rose); font-weight: 500; font-size: .9375rem; }   /* 옛 이름: btn btn-text */
.btn-row { display: -webkit-box; display: flex; }
.btn-row > * { -webkit-box-flex: 1; flex: 1 1 0; min-width: 0; }
.btn-row > * + * { margin-left: 8px; }
.btn-primary { }   /* 옛 이름: .btn 이 곧 채운 버튼 */

/* ---------- 아래 고정 바 (키보드가 열리면 흐름 배치로). .bottom 은 옛 이름 ---------- */
.dock, .bottom { position: fixed; left: 50%; -webkit-transform: translateX(-50%); transform: translateX(-50%); bottom: 0; width: 100%; max-width: 520px; z-index: 5;
  padding: 12px var(--m) calc(16px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); }
.bottom { background-color: var(--paper); background-image: linear-gradient(rgba(248, 243, 236, .65), rgba(248, 243, 236, .65)), url("/assets/img/paper-tile.jpg"); background-size: auto, 300px 300px; }
.dock.bare, .bottom.bare { border-top: 0; }
.dock > * + *, .bottom > * + * { margin-top: 8px; }
.dock .hint, .bottom .hint { margin-top: 8px; text-align: center; font: 400 .875rem/1.25rem var(--sans); color: var(--stone); }
.dock-space { height: calc(var(--dock-h) + 24px); }

/* ---------- 그림 (WD.ui.picture) ---------- */
.plate { position: relative; overflow: hidden; margin: 0 var(--m); }
.plate > img, .plate > picture > img, .plate > picture { display: block; width: 100%; height: 100%; }
.plate > img, .plate > picture > img { object-fit: cover; }
.plate.bleed { margin: 0; }
.fade-24 img { -webkit-mask-image: linear-gradient(#000 calc(100% - 24px), transparent); mask-image: linear-gradient(#000 calc(100% - 24px), transparent); }
.fade-32 img { -webkit-mask-image: linear-gradient(#000 calc(100% - 32px), transparent); mask-image: linear-gradient(#000 calc(100% - 32px), transparent); }
/* 물건 그림: 상자 없이 종이 위에. 가장자리는 그림 파일의 알파가 맡으므로 자르지 않고 비율 그대로 */
.obj { position: relative; margin: 0 var(--m); }
.obj img { display: block; width: 100%; height: auto; }
.obj.narrow { margin-left: auto; margin-right: auto; width: 300px; max-width: calc(100% - 2 * var(--m)); }
/* 자리 카드 위 이름: 그림 상자 기준 % 좌표, 곱하기 합성. 그림 속 글자는 px (큰 글씨에서도 그림과 같이). WD.fitNames 로 맞춤 */
.card-ink { position: absolute; -webkit-transform: translate(-50%, -50%) rotate(var(--rot, 0deg)); transform: translate(-50%, -50%) rotate(var(--rot, 0deg)); text-align: center; white-space: nowrap;
  font: 600 21px/1.1 var(--serif); letter-spacing: -.03em; color: #3B2B2E; mix-blend-mode: multiply; opacity: .94; }

/* ---------- 사실 목록 (엔딩 크레디트처럼) ---------- */
.facts { border-top: 1px solid var(--line); }
.facts .row { display: -webkit-box; display: flex; align-items: baseline; padding: 14px 0; border-bottom: 1px solid var(--line); }
.facts .row > * + * { margin-left: 16px; }
.facts .k { width: 2.75rem; flex: none; font: 500 .875rem/1.5rem var(--sans); color: var(--stone); }
.facts .v { -webkit-box-flex: 1; flex: 1; font: 500 1rem/1.5rem var(--sans); color: var(--ink); letter-spacing: -.02em; }
.facts .v.quiet { font-weight: 400; color: var(--stone); }

/* ---------- 목록 행 (머리카락 선, 번호, 글, 오른쪽 하나) ---------- */
.rows { border-top: 1px solid var(--line); }
.rowl { display: -webkit-box; display: flex; align-items: center; width: 100%; min-height: 64px; padding: 12px 0; border-bottom: 1px solid var(--line); color: inherit; text-align: left; }
.rowl > * + * { margin-left: 14px; }
.rowl .grow { -webkit-box-flex: 1; flex: 1; min-width: 0; }
.rowl b { display: block; font: 600 1rem/1.5rem var(--sans); color: var(--ink); letter-spacing: -.02em; }
.rowl .s { display: block; font: 400 .875rem/1.375rem var(--sans); color: var(--stone); }
.rowl .chev, .chev { color: var(--chev); }
.rowl .no, .no { width: 24px; flex: none; align-self: baseline; align-self: first baseline; font: 500 1.125rem/1.5rem var(--latin); font-variant-numeric: lining-nums; color: var(--rose); }
.rowl.kakao-row b { font-weight: 600; }
/* 게임 입구 행 (홈 맨 아래 작은 행 하나, game_enabled 일 때만). 옛 카드 → 목록 행 */
.extra-card { display: -webkit-box; display: flex; align-items: center; min-height: 64px; padding: 12px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  color: var(--ink); font: 500 .9375rem/1.5rem var(--sans); }
.extra-card > * + * { margin-left: 14px; }
.extra-card .ic, .extra-card svg { color: var(--stone); }
.extra-card .cap { display: block; }

/* ---------- 응답 고르기: 세 행 같은 상자, 선택은 테두리 + 옅은 면 + 체크 원 ---------- */
.opts > * + * { margin-top: 10px; }
.opt { position: relative; display: -webkit-box; display: flex; align-items: center; width: 100%; min-height: 76px; padding: 14px 16px; text-align: left;
  border-radius: var(--r-2); background: var(--paper-hi); box-shadow: inset 0 0 0 1px var(--field);
  -webkit-transition: background-color var(--t-fast) linear, box-shadow var(--t-fast) linear; transition: background-color var(--t-fast) linear, box-shadow var(--t-fast) linear; }
.opt > * + * { margin-left: 14px; }
.opt .t { -webkit-box-flex: 1; flex: 1; }
.opt b { display: block; font: 600 1.0625rem/1.625rem var(--sans); color: var(--ink); letter-spacing: -.02em; }
.opt .s { display: block; font: 400 .875rem/1.375rem var(--sans); color: var(--stone); }
.opt .rd { width: 24px; height: 24px; border-radius: 50%; flex: none; box-shadow: inset 0 0 0 1.5px var(--field); display: -webkit-box; display: flex; align-items: center; justify-content: center; }
.opt .rd .ic { width: 16px; height: 16px; stroke-width: 2; }
.opt.on { background: var(--blush); box-shadow: inset 0 0 0 1.5px var(--berry); }
.opt.on .rd { background: var(--berry); box-shadow: none; color: #fff; }
.opt.on .s { color: var(--sub-ink); }

/* ---------- 입력 ---------- */
.field { display: block; width: 100%; min-height: 56px; padding: 0 16px; border: 0; border-radius: var(--r-1); background: var(--paper-hi);
  box-shadow: inset 0 0 0 1px var(--field); font: 400 1.0625rem/3.5rem var(--sans); color: var(--ink); -webkit-appearance: none; appearance: none; }
input.field { height: 56px; line-height: normal; }
.field::-webkit-input-placeholder { color: var(--stone); }
.field::placeholder { color: var(--stone); }
.field.ph { color: var(--stone); }
/* :focus-visible 을 모르는 옛 WebView(iOS 12–15.3 · 크롬 6x–85)가 규칙째 버리지 않게 따로 둠 (lint 가 묶음을 막음) */
.field.focus, .field:focus { outline: 0; box-shadow: inset 0 0 0 1.5px var(--berry), 0 0 0 3px rgba(126, 47, 69, .12); }
.field:focus-visible { outline: 0; box-shadow: inset 0 0 0 1.5px var(--berry), 0 0 0 3px rgba(126, 47, 69, .12); }
.field.err, .field.field-error, .field-error { box-shadow: inset 0 0 0 1.5px var(--berry); }
textarea.field, .field.area { min-height: 112px; padding: 14px 16px; line-height: 1.75rem; resize: none; }
.field-ro { display: -webkit-box; display: flex; align-items: center; background: var(--paper); box-shadow: inset 0 0 0 1px var(--line); }   /* 읽기 전용 */
.help-err, .msg-error { margin-top: 8px; font: 500 .875rem/1.375rem var(--sans); color: var(--berry); }
.help-err { display: -webkit-box; display: flex; align-items: flex-start; }
.help-err > * + * { margin-left: 6px; }
.help-err:empty, .msg-error:empty { display: none; }
/* 휴대폰 뒷자리 4칸 (WD.ui.pin): 투명 입력 하나 위에 네 칸 그림(칸 64). 목업처럼 .pin > span 으로 써도 같은 모양 */
.pin { position: relative; max-width: 340px; }
.pin-input { position: absolute; left: 0; top: 0; width: 100%; height: 100%; opacity: 0; font-size: 16px; color: transparent; caret-color: transparent; z-index: 2; border: 0; background: none; }
.pin-cells, .pin.grid { display: -webkit-box; display: flex; }
.pin-cells span, .pin > span { -webkit-box-flex: 1; flex: 1 1 0; min-width: 0; height: 64px; border-radius: var(--r-1); background: var(--paper-hi); box-shadow: inset 0 0 0 1px var(--field);
  display: -webkit-box; display: flex; align-items: center; justify-content: center; font: 500 1.875rem/1 var(--latin); font-variant-numeric: lining-nums; color: var(--ink); }
.pin-cells span + span, .pin > span + span { margin-left: 12px; }
.pin-cells span.on, .pin-cells span.now, .pin > span.on { box-shadow: inset 0 0 0 1.5px var(--berry), 0 0 0 3px rgba(126, 47, 69, .12); }
.pin-cells span.on::after, .pin-cells span.now::after, .pin > span.on::after { content: ""; width: 1.5px; height: 28px; background: var(--berry); }
.pin.err .pin-cells span, .pin.err > span { box-shadow: inset 0 0 0 1.5px var(--berry); }
.pin.off .pin-cells span, .pin.off > span { background: var(--paper); box-shadow: inset 0 0 0 1px rgba(149, 133, 128, .4); }
.check { display: -webkit-box; display: flex; align-items: flex-start; min-height: 48px; padding: 4px 0; cursor: pointer; }
.check > * + * { margin-left: 14px; }
.check input[type="checkbox"] { width: 24px; height: 24px; margin: 1px 0 0; flex: none; accent-color: var(--berry); }
.box { width: 24px; height: 24px; border-radius: 4px; flex: none; margin-top: 1px; box-shadow: inset 0 0 0 1.5px var(--field); display: -webkit-box; display: flex; align-items: center; justify-content: center; }
.box.on { background: var(--berry); box-shadow: none; color: #fff; }
.box .ic { width: 16px; height: 16px; stroke-width: 2; }
.check b { display: block; font: 600 1rem/1.5rem var(--sans); color: var(--ink); }
.check .s { display: block; margin-top: 2px; font: 400 .875rem/1.375rem var(--sans); color: var(--stone); }
.fold { display: -webkit-box; display: flex; align-items: center; width: 100%; min-height: 52px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); font: 600 1rem/1.5rem var(--sans); color: var(--ink); text-align: left; }
.fold > * + * { margin-left: 10px; }
.fold .grow { -webkit-box-flex: 1; flex: 1; text-align: left; }
.fold .t2 { font-weight: 400; color: var(--stone); font-size: .875rem; }

/* ---------- 칩 · 세그먼트 · 스위치 (WD.ui.chips). 고른 칩 = blush 면 + 베리 1.5 + 600 ---------- */
.chips, .chip-row { display: -webkit-box; display: flex; flex-wrap: wrap; margin: -4px; }
.chips > *, .chip-row > * { margin: 4px; }
.chip { position: relative; display: -webkit-inline-box; display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px; border-radius: 22px; background: var(--paper-hi);
  box-shadow: inset 0 0 0 1px var(--field); font: 500 .875rem/1.2 var(--sans); color: var(--ink); white-space: nowrap; }
.chip > * + * { margin-left: 4px; }
.chip.on, .chip.chip-on, .chip-btn.chip-on { background: var(--blush); box-shadow: inset 0 0 0 1.5px var(--berry); color: var(--ink); font-weight: 600; }
.seg { display: -webkit-box; display: flex; min-height: 48px; padding: 4px; border-radius: 10px; background: var(--seg-bg); }
.seg > span, .seg > button, .seg > .seg-i { -webkit-box-flex: 1; flex: 1 1 0; min-height: 40px; padding: 0 8px; display: -webkit-box; display: flex; align-items: center; justify-content: center; border-radius: 7px;
  font: 500 .9375rem/1 var(--sans); color: var(--stone); }
.seg > span.on, .seg > button.on, .seg > .seg-i.on { background: var(--paper-hi); color: var(--ink); font-weight: 600; box-shadow: 0 1px 2px rgba(51, 40, 42, .12); }
.sw { width: 44px; height: 26px; border-radius: 13px; background: #E6DCD1; box-shadow: inset 0 0 0 1.5px var(--field); position: relative; flex: none; display: inline-block; }
.sw::after { content: ""; position: absolute; left: 3px; top: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
  -webkit-transition: left var(--t-fast) var(--ease); transition: left var(--t-fast) var(--ease); }
.sw.on { background: var(--berry); box-shadow: none; }
.sw.on::after { left: 21px; }
/* 옛 이름: 작은 상태 칩 (span.chip · chip-ok · chip-wait · chip-pink) → 꼬리표(.tag) 모양 */
span.chip { min-height: 28px; padding: 0 10px; border-radius: 14px; background: transparent; }
.chip.chip-ok { color: var(--berry); box-shadow: inset 0 0 0 1px var(--berry); }
.chip.chip-wait, .chip.chip-pink { background: var(--blush); box-shadow: none; color: #6A3442; }

/* ---------- 꼬리표 (관리자 · 그룹장 상태) ---------- */
.tag { display: -webkit-inline-box; display: inline-flex; align-items: center; min-height: 28px; padding: 0 10px; border-radius: 14px; font: 500 .875rem/1 var(--sans); color: var(--ink); box-shadow: inset 0 0 0 1px var(--field); white-space: nowrap; }
.tag > * + * { margin-left: 4px; }
.tag.yes { color: var(--berry); box-shadow: inset 0 0 0 1px var(--berry); }
.tag.done { background: var(--berry); color: #fff; box-shadow: none; }
.tag.soft { background: var(--blush); box-shadow: none; color: #6A3442; }
.tag.mute { color: var(--stone); box-shadow: inset 0 0 0 1px var(--line-2); }

/* ---------- 짧은 상태 줄 · 안내 상자 ---------- */
.note { display: -webkit-box; display: flex; align-items: flex-start; font: 400 .875rem/1.375rem var(--sans); color: var(--stone); }
.note > * + * { margin-left: 8px; }
.note .ic { width: 18px; height: 18px; margin-top: 2px; color: var(--rose); }
.alert { padding: 18px 18px 14px; border-radius: var(--r-2); background: var(--paper-hi); box-shadow: inset 0 0 0 1px var(--line); text-align: left; }
.alert h3 { font: 400 1.1875rem/1.75rem var(--serif); letter-spacing: -.02em; color: var(--ink); }
.alert p { margin-top: 6px; font: 400 .9375rem/1.5rem var(--sans); color: var(--stone); }
.alert .left { margin-top: 8px; font: 600 .875rem/1.25rem var(--sans); color: var(--berry); }
.alert .btns { margin-top: 14px; display: -webkit-box; display: flex; align-items: center; }
.alert .btns > * + * { margin-left: 8px; }
.alert .btns .btn { width: auto; -webkit-box-flex: 1; flex: 1; }
.alert .btns .btn-text { flex: none; }

/* ---------- 토스트 (WD.ui.toast): 아래 고정 바 위 16px, 아래에서 8px 올라오며 220ms ---------- */
.toast { position: fixed; left: 50%; -webkit-transform: translateX(-50%); transform: translateX(-50%); bottom: calc(var(--dock-h) + 16px); width: calc(100% - 32px); max-width: 488px; z-index: 20;
  display: -webkit-box; display: flex; align-items: center; padding: 14px 16px; border-radius: 10px; background: var(--ink); color: #fff; font: 500 .9375rem/1.375rem var(--sans);
  -webkit-animation: wd-toast var(--t-mid) var(--ease) both; animation: wd-toast var(--t-mid) var(--ease) both; }
html.no-dock .toast { bottom: calc(16px + env(safe-area-inset-bottom)); }
.toast > * + * { margin-left: 12px; }
.toast .act, .toast-act { margin-left: auto; min-height: 40px; padding: 0 4px; color: #F3C9D0; font-weight: 600; white-space: nowrap; text-decoration: none; }
.toast-error { background: var(--ink); }
@-webkit-keyframes wd-toast { from { opacity: 0; -webkit-transform: translate(-50%, 8px); } to { opacity: 1; -webkit-transform: translate(-50%, 0); } }
@keyframes wd-toast { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }

/* ---------- 시트 (WD.ui.sheet): .sheet-wrap.on > .scrim(.sheet-dim) + .sheet. 최대 높이 100dvh − 8 안에서 스크롤 ---------- */
.sheet-wrap { position: static; }
.scrim, .sheet-dim { position: fixed; left: 0; top: 0; right: 0; bottom: 0; background: var(--scrim); z-index: 8; }
.sheet { position: fixed; left: 50%; bottom: 0; width: 100%; max-width: 520px; z-index: 9; -webkit-transform: translateX(-50%); transform: translateX(-50%);
  padding: 10px var(--m) calc(20px + env(safe-area-inset-bottom)); border-radius: var(--r-sheet) var(--r-sheet) 0 0; box-shadow: var(--sh-sheet);
  max-height: calc(100vh - 8px); max-height: calc(var(--vh, 1vh) * 100 - 8px); max-height: calc(100dvh - 8px);
  overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; text-align: left; }
.sheet-wrap .scrim, .sheet-wrap .sheet-dim { opacity: 0; -webkit-transition: opacity var(--t-mid) linear; transition: opacity var(--t-mid) linear; }
.sheet-wrap .sheet { -webkit-transform: translate(-50%, 100%); transform: translate(-50%, 100%); box-shadow: none;
  -webkit-transition: -webkit-transform var(--t-slow) var(--ease), box-shadow var(--t-slow) linear; transition: transform var(--t-slow) var(--ease), box-shadow var(--t-slow) linear; }
.sheet-wrap.on .scrim, .sheet-wrap.on .sheet-dim { opacity: 1; }
.sheet-wrap.on .sheet { -webkit-transform: translate(-50%, 0); transform: translate(-50%, 0); box-shadow: var(--sh-sheet); }
.sheet-wrap:not(.on) .scrim, .sheet-wrap:not(.on) .sheet-dim { pointer-events: none; }
.sheet .grab, .sheet-grip { width: 36px; height: 4px; border-radius: 2px; background: #D6C9BC; margin: 0 auto 20px; }
.sheet .grab-row { position: relative; height: 24px; margin: -10px 0 10px; }
.sheet .grab-row .grab { position: absolute; left: 50%; top: 10px; margin: 0 0 0 -18px; }
.sheet .grab-row .big-act { position: absolute; right: -12px; top: 0; }
.big-act { display: -webkit-inline-box; display: inline-flex; align-items: center; min-height: 44px; padding: 0 12px; font: 500 .875rem/1 var(--sans); color: var(--stone); white-space: nowrap; }
.sheet .h1, .sheet-title { font: 400 1.5rem/2.125rem var(--serif); letter-spacing: -.03em; color: var(--ink); text-wrap: balance; }
.sheet-title { margin-bottom: 8px; }
.sheet-body > .cap:first-child, .sheet-body > .small:first-child { margin-top: 0; }
.sheet-actions { margin-top: 24px; }
.sheet-actions > * + * { margin-top: 8px; }
body.sheet-on { overflow: hidden; }
.sheet:focus, [tabindex="-1"]:focus { outline: none; }   /* 시트 · 제목에 옮긴 포커스는 테두리를 그리지 않음 (칸 · 버튼은 :focus-visible) */

/* ---------- 날짜 덩어리 (날짜가 주정보, D-day는 보조) ---------- */
.when { display: -webkit-box; display: flex; align-items: center; justify-content: space-between; padding: 16px 0; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--line); }
.when > * + * { margin-left: 16px; }
.when .d { font: 600 1.25rem/1.75rem var(--sans); color: var(--ink); letter-spacing: -.02em; }
.when .n { font: 500 2.125rem/1 var(--latin); font-variant-numeric: lining-nums; color: var(--stone); letter-spacing: 0; white-space: nowrap; }

/* ---------- 편지지 (실물 결과물일 때만 그림자 한 겹). .paper 는 옛 이름 ---------- */
.sheet-paper, .paper { position: relative; background: var(--paper-hi) url("/assets/img/paper-hi-tile.jpg") repeat; background-size: 300px; border-radius: 2px; box-shadow: inset 0 0 0 1px #EDE3D8; }
.sheet-paper.object, .paper.object { box-shadow: var(--sh-object); }
.sheet-paper .to   { font: 400 1.1875rem/1.875rem var(--serif); letter-spacing: -.02em; color: var(--ink); }
.sheet-paper .text { font: 400 1rem/1.875rem var(--sans); color: var(--ink); }
.sheet-paper .read { font: 400 1.0625rem/2rem var(--serif); letter-spacing: -.02em; color: var(--ink); }
.sheet-paper .from { font: 400 1rem/1.625rem var(--serif); letter-spacing: -.02em; color: var(--ink); text-align: right; }
.caret { display: inline-block; width: 1.5px; height: 20px; background: var(--berry); vertical-align: -4px; margin-left: 1px; }

/* ---------- 얇은 진행 막대 ---------- */
.prog { height: 3px; background: var(--line); border-radius: 2px; overflow: hidden; }
.prog i { display: block; height: 100%; background: var(--berry); }
.bar3 { display: -webkit-box; display: flex; height: 4px; margin-top: 14px; }   /* 완성 berry · 준비 중 rose · 시작 전 line, 구간 사이 2px 틈 */
.bar3 i { display: block; height: 100%; border-radius: 1px; }
.bar3 i + i { margin-left: 2px; }
.bar3 .d { background: var(--berry); } .bar3 .p { background: var(--rose); } .bar3 .w { background: var(--line); -webkit-box-flex: 1; flex: 1; }
.legend3 { margin-top: 10px; display: -webkit-box; display: flex; flex-wrap: wrap; font: 400 .875rem/1.375rem var(--sans); color: var(--stone); }
.legend3 span { display: -webkit-inline-box; display: inline-flex; align-items: center; margin: 0 14px 4px 0; }
.legend3 span::before { content: ""; width: 8px; height: 8px; margin-right: 6px; border-radius: 1px; background: var(--line); box-shadow: inset 0 0 0 1px var(--line-2); }
.legend3 .d::before { background: var(--berry); box-shadow: none; } .legend3 .p::before { background: var(--rose); box-shadow: none; }

/* ---------- 상태 카드 (WD.ui.stateCard): 그림 한 장(≤250) 또는 56 원 아이콘 + 제목 + 한 문장 + 버튼 ---------- */
.state-card { padding: 32px var(--m) 0; text-align: center; }
.state-card.left { padding-top: 48px; text-align: left; }
.state-card .state-art { width: 250px; max-width: 100%; margin: 0 auto 16px; }
.state-card .state-art img { width: 100%; height: auto; }
.state-card .state-plate { height: 224px; margin: -32px calc(-1 * var(--m)) 24px; }
.state-mark { width: 56px; height: 56px; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--line); background: var(--paper-hi); display: -webkit-box; display: flex; align-items: center; justify-content: center; color: var(--rose); margin: 0 auto 20px; }
.state-card.left .state-mark { margin: 0 0 20px; }
.state-mark .ic { width: 26px; height: 26px; }
.state-card .state-sub { margin-bottom: 4px; }
.state-title { font: 400 1.625rem/2.25rem var(--serif); letter-spacing: -.03em; color: var(--ink); text-wrap: balance; }
.state-body { margin-top: 10px; font: 400 .9375rem/1.5rem var(--sans); color: var(--stone); text-wrap: pretty; }
.state-acts { margin-top: 24px; text-align: center; }
.state-acts > * + * { margin-top: 8px; }
.state-card.left .state-acts { text-align: left; }

/* ---------- 로딩: 종이 가운데 원 마크 28 + "잠시만요", 160ms 페이드만 (마카롱 · 움직임 없음) ---------- */
.loading { min-height: 60vh; min-height: calc(var(--vh, 1vh) * 60); display: -webkit-box; display: flex; -webkit-box-orient: vertical; flex-direction: column; align-items: center; justify-content: center;
  -webkit-animation: wd-fade var(--t-fast) linear 240ms both; animation: wd-fade var(--t-fast) linear 240ms both; }
.loading-mark { display: block; width: 28px; height: 28px; }
.loading-msg { margin-top: 12px; font: 400 .875rem/1.25rem var(--sans); color: var(--stone); }

/* ---------- 하단 탭 (옛 L1. 새 시안은 머리 오른쪽 [도움말]) ---------- */
.tabbar { position: fixed; left: 50%; -webkit-transform: translateX(-50%); transform: translateX(-50%); bottom: 0; width: 100%; max-width: 520px; z-index: 5; display: -webkit-box; display: flex;
  border-top: 1px solid var(--line); padding-bottom: env(safe-area-inset-bottom);
  background-color: var(--paper); background-image: linear-gradient(rgba(248, 243, 236, .65), rgba(248, 243, 236, .65)), url("/assets/img/paper-tile.jpg"); background-size: auto, 300px 300px; }
.tabbar a, .tabbar button { -webkit-box-flex: 1; flex: 1 1 0; min-height: 56px; display: -webkit-box; display: flex; -webkit-box-orient: vertical; flex-direction: column; align-items: center; justify-content: center; font: 500 .875rem/1.2 var(--sans); color: var(--stone); }
.tabbar .on { color: var(--ink); font-weight: 600; }

/* ---------- 옛 이름: 카드 · 깅엄 · 리본 띠 (금지된 모양이라 그리지 않음, 자리만) ---------- */
.card { background: var(--paper-hi); border-radius: var(--r-2); box-shadow: inset 0 0 0 1px var(--line); padding: 16px; }
.card + .card { margin-top: 12px; }
.card-cream { background: transparent; }
.gingham, .gingham-l { background-image: none !important; background-color: transparent !important; }
.scallop, .scallop-l, .band { display: none !important; }

/* ---------- 키보드가 열렸을 때 (visualViewport 가 150px 넘게 줄면 body.kb, shared.js) ----------
   고정 바는 흐름으로, 그림 · 큰 제목 · 도움 칩은 숨긴다. 시트는 일반 화면이 된다(뒤 화면은 로고 줄 .scrim-lift 만 남음). */
body.kb .dock, body.kb .bottom { position: static; -webkit-transform: none; transform: none; border-top: 0; padding-top: 16px; }
body.kb .dock-space, body.kb .hide-on-kb, body.kb .sheet-bg, body.kb .scrim, body.kb .sheet-dim, body.kb .tabbar { display: none !important; }
body.kb .screen { padding-bottom: 24px; }
body.kb .sheet, body.kb .sheet-wrap .sheet, body.kb .sheet-wrap.on .sheet { position: static; -webkit-transform: none; transform: none; max-height: none; overflow: visible; border-radius: 0; box-shadow: none; padding-top: 4px; background: none; }
body.kb .sheet .grab-row { display: none; }
body.kb .sheet-wrap:not(.on) { display: none; }
body.kb.sheet-on { overflow: visible; }
body.kb.sheet-on #app .screen { min-height: 0; padding-bottom: 0; }
body.kb.sheet-on #app .screen > *:not(.scrim-lift):not(.sheet-wrap) { display: none; }

/* 세션이 끊겼을 때 다시 확인 시트 (main.js, 상태 카드 3) */
.reauth-f1 { margin-top: 22px; }
.reauth-f2 { margin-top: 18px; }
