:root{
  /* ⚠️ 이 네 값은 홈(twenty-studio-home.html)과 **어긋나 있었다** — 2026-08-13에 맞췄다.
     --muted #8B91A8 · --line #E9E7F2 · --pop-d #E04A76 · --chip #F3F2F9 를 쓰고 있어서,
     탭을 옮기면 같은 회색·테두리·눌림색·칩 배경이 미세하게 달라 보였다.
     (--chip 은 셋을 맞출 때 놓쳤다가 뒤늦게 찾았다 — 여기 12곳·홈 41곳이 쓴다.)
     두 파일은 같은 값을 써야 한다.
     --bg(라벤더 #F6F7FB)는 지웠다 — DS 는 흰 바탕이고 body 를 #fff 로 바꾼 뒤로
     쓰는 곳이 하나도 없다. 죽은 변수를 남겨 두면 다음 사람이 라벤더를 되살린다. */
  --ink:#1A2250; --ink2:#3A4272; --muted:#767B96; --line:#E2E4F0;
  --pop:#FF5C8A; --pop-d:#E8447A; --card:#fff; --chip:#F1F2FA;
  /* 본문·바 안쪽 폭. 홈(twenty-studio-home.html의 .app)과 같은 440 으로 맞춘다 —
     다르면 탭을 옮길 때 같은 탭바가 80px 벌어져 화면이 흔들린다. */
  --shell-w:440px; --tabh:48px; --botpad:142px; --addedbot:136px;

  /* ── 디자인 시스템 토큰 — 홈 문서(:root)와 **같은 값이어야 한다** ──────
     한쪽만 고치면 탭을 옮길 때 색이 바뀐다. 절차는 ../DS-적용-지도.md.
     ⚠️ 여기 없는 hex 를 새로 만들지 않는다. */
  --tmint600:#07D1AE; --tmint700:#04AE90; --tmint100:#D4FDF6;
  --tmint50:#E8FEFA;  --tmint900:#046957;
  --tpurple500:#AD6BFC; --tpurple50:#F7F0FF; --tpurple700:#794BB0;
  --tgray50:#F6F5F7; --tgray100:#EAE9EC; --tgray200:#D4D2D9;
  --tgray300:#C4C2CA; --tgray500:#6E677A; --tgray600:#9A95A2;
  --tred500:#F05252; --tred50:#FDE8E8;
  --tgreen600:#0E9F6E; --tgreen50:#DEF7EC;
  /* 쿠폰·수량 할인 칩 (HANDOFF §1 의 「주의 — tyellow 계열」. 표에 hex 가 없어서
     목업 인라인 style 에서 읽었다: screens-all-final.dc.html 738·847).
     ⚠️ 지도 문서 토큰 표와 홈(:root)에는 아직 없다 — 홈에도 같은 두 값을 넣어야 안 어긋난다. */
  --tyellow50:#FFFCE4; --tyellow500:#FFA505;

  /* 타입 스케일 — 홈과 같은 값. 화면을 고칠 때 그 화면 안에서만 옮긴다(일괄 치환 금지). */
  --fs-title:16px;  --lh-title:24px;
  --fs-sec:18px;    --lh-sec:28px;
  --fs-num:20px;    --lh-num:28px;
  --fs-num-lg:24px; --lh-num-lg:32px;
  --fs-body:14px;   --lh-body:20px;
  --fs-cap:12px;    --lh-cap:16px;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  /* DS 는 흰 바탕 + #F6F5F7 블록이다 (라벤더 --bg #F6F7FB 를 걷어냈다).
     카드가 흰 바탕 위에 서니 구분은 1px var(--tgray100) 테두리가 맡는다. */
  background:#fff; color:#000; overflow-x:hidden;
  /* ⚠️ 예전엔 Pretendard 가 **폴백 4순위**였다(-apple-system 이 먼저 이겼다). 홈 문서는 1순위라,
     같은 앱인데 탭을 옮기면 데스크톱에서 서로 다른 글꼴로 렌더됐다. 홈과 같은 순서로 맞췄다. */
  font-family:'Pretendard','Pretendard Variable',-apple-system,BlinkMacSystemFont,'Apple SD Gothic Neo','Malgun Gothic','Segoe UI',sans-serif;
  letter-spacing:-0.01em;
  -webkit-tap-highlight-color:transparent;
}
h1,h2{margin:0}
button{font:inherit;cursor:pointer}
button,a,[role="button"],input,textarea{touch-action:manipulation}
button,a,[role="button"]{color:inherit}

/* ── 상단바 ── */
/* 고정·붙는 바는 배경이 화면 끝까지 가고, 내용만 본문과 같은 폭으로 좁힌다.
   전에는 바 자체에 max-width 를 걸어서 PC 에서 흰 바가 가운데 520px 만 뜨고
   좌우가 잘려 보였다 (본문·탭바 셋 다 같은 문제였다). */
.top{
  position:sticky; top:0; z-index:40;
  height:60px; min-height:60px; max-height:60px;
  box-sizing:border-box;
  padding:0 20px;
  background:rgba(255,255,255,.9); backdrop-filter:blur(24px); border-bottom:0;
}
.top .in{display:flex; align-items:center; gap:12px; width:100%;
  max-width:var(--shell-w); height:100%; margin:0 auto}
.top h1{flex:1; font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700; color:#000}
/* 목업은 아이콘만 두고 **배경을 안 준다**(24px 글리프). 회색 라운드 버튼을 두면
   상단바가 무거워지고, 제목이 두 버튼 사이에 끼어 가운데 정렬처럼 보인다.
   ⚠️ 탭 영역은 40px 로 유지한다 — 보이는 건 24px 아이콘이지만 누르는 자리는 그대로다. */
.top .back,.top .cart{
  width:40px; height:40px; border:0; border-radius:12px; background:transparent; color:#000;
  display:flex; align-items:center; justify-content:center; position:relative;
}
/* 🚨 `display:flex` 가 `hidden` 속성을 이긴다. shop.js 가 장바구니 화면에서
   `cb.hidden = true` 를 해도 그대로 보였다 (2026-08-15 혜림님이 또 발견 —
   8/14에 이미 「장바구니 페이지 안에 장바구니 아이콘 또 있어」로 고쳤던 자리다). */
.top .back[hidden],.top .cart[hidden]{display:none !important}
.top .back:active,.top .cart:active{background:var(--tgray50)}
.top .back svg,.top .cart svg{width:24px; height:24px; display:block}
/* 목록에서는 뒤로가기가 없다. `visibility:hidden` 으로 두면 **40px 칸과 12px 간격이 그대로
   남아** 제목이 52px 밀린다 — 「굿즈 만들기」 왼쪽 여백이 다른 탭보다 넓어 보였다
   (2026-08-14 혜림님). `display:none` 이면 자리째 빠져 flex gap 도 안 생긴다.
   ⚠️ 다시 `visibility` 로 돌리지 말 것. 흔들림(layout shift)이 걱정이라면, 이 버튼은
      **화면을 옮길 때만** 켜지고 같은 화면에서 나타났다 사라지지 않으므로 문제가 없다. */
.top .back{display:none}
.top .back.on{display:flex}
/* 아이콘이 화면에서 20px 에 오게 한다 (2026-08-14 혜림님 「뒤로가기 앞 여백이 너무 넓어」).
   버튼 칸은 40px 이고 그 안에 24px 아이콘이 가운데 오니 좌우 8px 이 남는다 —
   `.top` 의 padding 20px 에 그 8px 이 더해져 28px 로 보였다.
   ⚠️ 칸은 40px 로 유지한다(누르는 자리). 음수 마진으로 **아이콘만** 당긴다. */
.top .back.on{margin-left:-8px}
/* 쇼핑백의 빨간 개수 배지(20px · --tred500)를 없앴다 — 확정본 상단바(final-goods.html:21)에
   배지가 없다. 빨강은 오류·경고 색이라, 담을수록 빨간 숫자가 커지는 것이 「무언가 잘못됐다」로
   읽혔다. 담긴 개수는 하단 요약 바 한 곳에서만 말한다(「장바구니 3개 · 13,000원」·「주문하기 3」). */

/* 탭 화면(굿즈 목록)은 탭바를 두고, 그보다 깊이 들어간 화면(상품 상세·장바구니·주문서)은
   탭바를 치워 화면 전체를 쓴다. 탭바가 계속 깔려 있으면 "탭 안의 한 단계"로 보여서
   지금 어디인지, 뒤로 갈 곳이 헤더인지 탭바인지 헷갈린다.
   탭바가 사라지면 syncBottomPad() 가 높이 0 으로 재서 --tabh·--botpad 가 저절로 줄어든다. */
body.deep .tabs{display:none}

/* 화면 좌우 20 (DS 치수) — .hero 의 음수 margin 도 같은 값이어야 통째로 번진다 */
.page{display:none; padding:20px; padding-bottom:var(--botpad); max-width:var(--shell-w); margin:0 auto}
.page.on{display:block}
#pgList.page{
  padding-top:0;
  padding-bottom:calc(var(--botpad) + 24px);
}
.lead{margin:0 0 20px; font-size:var(--fs-body); line-height:var(--lh-body); font-weight:400; color:var(--tgray500)}

/* ── 쿠폰 배너 (굿즈 목록 상단) ──
   보이려면 shop.js 가 hidden 을 풀어야 한다 (shop.html 의 #cpBanner 주석 참고). */
.cpbanner{display:flex; align-items:center; gap:12px; margin:0 0 20px;
  background:var(--tyellow50); border-radius:16px; padding:16px}
.cpbanner[hidden]{display:none !important}
/* 누를 수 있는 상태(① 완성하러 가기 · ② 담으러 가기)에만 손 모양을 준다 —
   ③ 적용 중은 알리기만 하는 자리라 누를 곳이 없다 (2026-08-15) */
.cpbanner.go{cursor:pointer}
.cpbanner.go:active{opacity:.7}
.cpbanner .cpic{flex:none; width:44px; height:44px; border-radius:12px; background:#fff;
  display:flex; align-items:center; justify-content:center; color:var(--tyellow500)}
.cpbanner .cpic svg{width:22px; height:22px; display:block}
.cpbanner .cptx{flex:1; min-width:0}
.cpbanner .cptx b{display:block; font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:700; color:#000}
.cpbanner .cptx span{display:block; margin-top:2px;
  font-size:var(--fs-cap); line-height:var(--lh-cap); font-weight:400; color:var(--tgray500)}

/* ── 상품 목록 ── */
/* 묶음(카테고리)을 세로로 쌓고 묶음 안이 2열 그리드다 — 명세 §4 「5개 묶음」.
   전에는 .plist 자체가 2열 그리드였다(평평한 6품목 시절). */
.plist{display:flex; flex-direction:column; gap:20px}
.pgrid{display:grid; grid-template-columns:1fr 1fr; gap:12px}
/* 묶음 기준은 재질이 아니라 「어디에 두는 물건인지」 — 부제가 그걸 말한다.
   ⚠️ 목업은 16/24 다(섹션 18/28 이 아니다) — 묶음 제목이 화면 제목만큼 커지면
      2열 카드가 딸려 보인다. 부제는 tgray600(흐림). */
.pcatH{
  display:flex; align-items:baseline; gap:8px; margin:0 0 12px;
  font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700;
}
.pcatH span{
  font-size:var(--fs-cap); line-height:var(--lh-cap); font-weight:400; color:var(--tgray600);
}
/* 오픈 기념 20% 배너 — 할인 안내가 상품 목록에서 바로 읽히도록 노란 주의 톤을 쓴다. */
/* 쿠폰 배너(.cpbanner)와 같은 카드 문법 — 위아래 두 배너의 스타일이 다르면
   거슬린다 (2026-08-19 혜림님). 전엔 화면 폭을 다 쓰는 띠였다. */
.evbar{
  display:flex; align-items:center; gap:12px;
  background:var(--tyellow50); border-radius:16px; padding:16px;
  margin:0 0 20px;
}
/* 키링 묶음 안으로 들어간 쿠폰 배너 — 제목과 카드 사이 */
.pcat .cpbanner{margin:0 0 12px}
.evbar .cpic{
  flex:none; width:44px; height:44px; border-radius:12px; background:#fff;
  color:var(--tyellow500); display:flex; align-items:center; justify-content:center;
}
.evbar .cpic svg{width:22px; height:22px; display:block}
.evbar .tx{display:flex; flex-direction:column; flex:1; min-width:0}
.evbar b{
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; color:#000;
}
.evbar .sub{
  font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray500); margin-top:2px;
}
.evbar .days{
  flex:none; background:#fff; color:#8A5A16;
  font-size:var(--fs-cap); line-height:var(--lh-cap); font-weight:700;
  border-radius:9999px; padding:4px 12px; font-style:normal;
}
/* 사진이 아직 없는 신규 품목 — 목업은 **캐릭터 그림을 그대로 두고** 오른쪽 아래에
   딱지만 얹는다. 전에는 그림 없이 딱지만 가운데 있어서 카드가 통째로 비어 보였다. */
.pcard .nophoto,.rcell .nophoto{
  position:absolute; right:8px; bottom:8px;
  font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray600);
  background:rgba(255,255,255,.9); border-radius:8px; padding:2px 6px;
}
/* 가격 표기 — 통상 커머스 방식 하나로 통일한다(2026-08-14 확정, A안).
   목록 카드·상세·장바구니·담기 시트가 **같은 마크업**을 쓴다(shop.js priceHtml).

     [20%(빨강)] [2,880원(굵게)]
     [3,600원(취소선·작게)]      ← 다음 줄

   할인율을 빨강으로 두는 이유는 그게 「지금 싸다」를 읽게 하는 유일한 신호이기 때문이다.
   전에는 「3,600원 · 담으면 2,880원」이었는데, 20% 가 합계에서 빠지는 우리 사정을
   손님에게 설명하는 문장이라 뺐다. */
.pr{display:block; margin-top:6px}
.pr .now{display:flex; align-items:baseline; gap:6px; flex-wrap:wrap}
.pr .pct{font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700; color:var(--tred500)}
.pr .amt{font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700}
.pr .was{display:block; font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray500)}
.pcard{
  background:var(--card); border:1px solid var(--tgray100); border-radius:16px; overflow:hidden;
  cursor:pointer; transition:transform .12s ease; position:relative;
}
.pcard:active{transform:scale(.97)}
.pcard.soon{
  cursor:default;
}
.pcard.soon:active{
  transform:none;
}
/* 사진 자리는 **회색 면**(--tgray50) 이고 높이는 150px 고정이다 — 목업 값.
   정사각(aspect-ratio:1)으로 두면 390px 2열에서 169px 이 되어 이름·가격이 한 화면에서 밀린다.
   실물 사진은 칸을 꽉 채우고(cover), 캐릭터 그림은 64% 로 앉힌다(contain). */
.pcard .im{
  height:150px; background:var(--tgray50); display:flex; align-items:center; justify-content:center;
  position:relative; overflow:hidden;
}
.pcard .im img{width:100%; height:100%; object-fit:cover}
.pcard .im .pimg{width:64%; height:64%}
.pcard .im .pimg img{width:100%; height:100%; object-fit:contain}
.pcard .im .ph{font-size:40px; opacity:.35}
.pcard .coming{
  position:absolute; inset:0; z-index:4;
  display:flex; align-items:center; justify-content:center;
  background:rgba(0,0,0,.44); color:#fff;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700;
  letter-spacing:0; text-align:center;
  -webkit-backdrop-filter:blur(1px); backdrop-filter:blur(1px);
}
/* 상품 태그(「얇고 가벼워요」)는 **이름 아래 한 줄**이다 — 목업 카드 구조.
   전에는 사진 위에 pill 로 겹쳐 놨는데, 사진을 가리고 「인기」 배지처럼 읽혔다.
   한 줄을 넘기면 줄임표로 자른다(카드 폭이 좁아 두 줄이 되면 아래 가격이 밀린다). */
.pcard .tag{
  display:block; margin-top:2px;
  font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray600);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.pcard .bd{padding:12px}
/* 이름은 한 줄 — 가장 긴 「모니터 클립형 스탠드」(11자)도 390px 2열에서 들어간다 */
.pcard .nm{font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; letter-spacing:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
/* 카드 안 가격은 위 `.pr` 공통 규칙을 그대로 쓴다 — 카드만 다르게 두면
   상세·장바구니와 어긋나고, 그게 예전에 화면마다 가격이 달라 보인 원인이었다. */
.pcard .opt{font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray600);
  font-weight:400; margin-top:4px}

.note{
  background:var(--tgray50); border:0; border-radius:8px;
  padding:16px; margin-top:24px;
}
.note>b{display:block; font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:700; margin-bottom:4px}
.note p{margin:0; font-size:var(--fs-body); line-height:var(--lh-body);
  color:var(--tgray500); font-weight:400}
.note p b{font-weight:700; color:#000}   /* 문장 안의 강조는 줄을 바꾸지 않는다 */

/* ── 상품 형태 ──────────────────────────────────────
   실물 사진이 없어서, 캐릭터 그림 위에 상품 형태만 도식으로 얹는다.
   사진인 척하지 않으면서도 목록에서 다섯 상품이 구분된다. */
.im{--sh:#C9CEE0}
.im.k-keyring .pimg{clip-path:none}
.im.k-keyring::before{                       /* 키링 고리 */
  content:""; position:absolute; top:7%; left:50%; transform:translateX(-50%);
  width:15px; height:15px; border-radius:50%; border:2.5px solid var(--sh); z-index:2;
}
.im.k-badge .pimg, .im.k-smarttok .pimg, .im.k-magsafe .pimg{
  border-radius:50%; overflow:hidden; background:#fff;
  box-shadow:0 0 0 3px #fff, 0 0 0 5px var(--sh);
}
.im.k-smarttok::after, .im.k-magsafe::after{ /* 그립톡 받침 */
  content:""; position:absolute; bottom:12%; left:50%; transform:translateX(-50%);
  width:38%; height:6px; border-radius:99px; background:var(--sh); opacity:.55;
}
.im.k-corotto .pimg{border-radius:44% 44% 40% 40%/48% 48% 36% 36%; overflow:hidden; background:#fff;
  box-shadow:0 0 0 3px #fff, 0 0 0 5px var(--sh)}
.im.k-corotto::after{                        /* 세워두는 받침 */
  content:""; position:absolute; bottom:9%; left:50%; transform:translateX(-50%);
  width:46%; height:7px; border-radius:3px; background:var(--sh); opacity:.6;
}
.im.k-magnet .pimg{border-radius:16%; overflow:hidden; background:#fff;
  box-shadow:0 0 0 3px #fff, 0 0 0 5px var(--sh)}
.im .pimg{width:74%; height:74%; display:flex; align-items:center; justify-content:center; position:relative}
.im .pimg img{width:100%; height:100%; object-fit:contain}
.heroImg .pimg{width:80%; height:80%}

/* ── 상세 (목업 §2 이식) ────────────────────────────────
   사진 칸은 **화면 폭을 다 쓰는 260px 회색 띠**다 — radius 도, 좌우 여백도 없다.
   전에는 240px 둥근 상자가 가운데 떠 있고 아래에 52px 썸네일이 줄지어 있었다. */
/* 높이는 **화면 폭과 같다**(정사각). 확정본은 260px 인데, 그건 「사진 준비 중」 상태를 그린
   값이다 — 실물 사진이 없어서 캐릭터 그림만 62% 로 앉히던 때다. 2026-08-14에 실물 사진이
   정사각(880×880) 27장으로 들어오면서 260px 로는 위아래 33% 가 잘렸고(키링 고리·코롯토
   받침이 날아갔다), 잘리지 않게 두면 좌우에 흰 여백이 남았다. 칸을 사진과 같은 비율로 두면
   둘 다 없다. 320px 도 재봤는데 좌우 35px 씩 남아 어중간했다. 27장 중 25장이 정사각이다. */
.hero{position:relative; aspect-ratio:1; background:var(--tgray50); margin:-20px -20px 0; padding:0}
.heroImg{
  width:100%; height:100%; margin:0; background:none; border-radius:0;
  display:flex; align-items:center; justify-content:center; overflow:hidden;
}
/* 캐릭터 그림은 62% 로 앉히고(목업 값), 실물 사진은 띠를 꽉 채운다.
   ⚠️ 이 칸은 이제 390×260 **직사각형**이다. `width:62%;height:62%` 로 두면 상품 형태
      도식(.k-badge 의 원, .k-corotto 의 곡선)이 타원으로 늘어난다 — 높이로만 재고
      가로는 aspect-ratio 로 정사각을 지킨다. */
.heroImg .pimg{height:62%; width:auto; aspect-ratio:1}
/* 상품 형태 도식(키링 고리·뱃지 원·코롯토 받침)은 **사진 칸에서 끈다** — 목업 §2 의 사진
   칸은 그림만 놓는다. 그 도식은 정사각 타일(목록 카드) 기준으로 % 배치돼 있어서,
   390×260 직사각형에서는 고리가 그림에서 떨어져 허공에 뜬다(375px 에서 확인).
   무엇으로 만들어지는지는 칼선 미리보기와 사양 표가 말한다. 목록 카드는 그대로 둔다. */
.heroImg.im::before,.heroImg.im::after{display:none !important}
.heroImg .pimg{box-shadow:none !important; border-radius:0 !important; clip-path:none !important}
.heroImg img{width:100%; height:100%; object-fit:contain}
/* 실물 사진은 **잘리지 않게** 앉힌다(contain). 2026-08-14에 사진을 정사각(880×880)으로
   다시 찍으면서 cover 로는 위아래 33% 가 날아갔다 — 키링은 고리가, 코롯토는 받침이
   화면 밖으로 나갔다. 캡션이 「볼체인과 고리」라고 말하는데 고리가 안 보였다.
   칸 높이 260px 과 회색 면은 확정본 값 그대로다(확정본은 「사진 준비 중」 상태만 그려서
   실물 사진 배치를 정하지 않았다 — 같은 칸의 캐릭터 그림이 62% contain 인 것을 따랐다).
   ⚠️ 아래쪽 `.im img.real{object-fit:cover}` 가 같은 요소를 잡는다(사진 칸은 `class="heroImg im"`
      을 함께 쓴다). 특이성이 같으면 뒤가 이기므로 `.heroImg.im` 으로 한 칸 올려 둔다. */
.heroImg.im img.real, .heroImg img.real{width:100%; height:100%; object-fit:contain; border-radius:0}
.heroImg .ph{font-size:56px; opacity:.3}
@media (max-width:600px){
  .hero{aspect-ratio:auto; height:260px}
}
/* 오른쪽 아래 딱지 — 「사진 준비 중」. 목업은 반투명 흰 배경이라 사진 위에서도 읽힌다 */
.heroTag{
  position:absolute; right:12px; bottom:12px;
  background:rgba(255,255,255,.9); color:var(--tgray600);
  font-size:var(--fs-cap); line-height:var(--lh-cap); font-weight:400;
  border-radius:8px; padding:2px 8px; display:none; z-index:2;
}
.heroTag.on{display:inline-block}
/* 사진 위 「바꾸기」 pill(.heroArtPick)은 없앴다 — 아래 `.artbar.dart` 주석 참고 */

/* 좌우 넘기기 화살표. 44×44 (손가락이 닿는 최소 크기)에 반투명 원.
   화살표는 글자가 아니라 **테두리 두 변을 돌린 사각형**이다 — 폰트에 따라 모양이
   달라지는 ‹ › 를 피한다. 사진이 한 장뿐이면 JS 가 `.on` 을 떼서 숨긴다. */
.heroNav{
  position:absolute; top:50%; transform:translateY(-50%); z-index:3;
  width:44px; height:44px; border:0; border-radius:9999px; padding:0;
  background:rgba(0,0,0,.32); color:#fff; display:none;
  -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
  cursor:pointer;
}
.heroNav.on{display:block}
.heroNav.prev{left:12px}
.heroNav.next{right:12px}
.heroNav::before{
  content:""; position:absolute; top:50%; left:50%;
  width:10px; height:10px; border:2px solid #fff; border-width:2px 2px 0 0;
}
.heroNav.prev::before{transform:translate(-30%,-50%) rotate(-135deg)}
.heroNav.next::before{transform:translate(-70%,-50%) rotate(45deg)}
.heroNav:active{background:rgba(0,0,0,.5)}
/* 화면이 좁으면 사진을 가리므로 조금 작게 */
@media (max-width:359px){
  .heroNav{width:38px; height:38px}
  .heroNav.prev{left:8px} .heroNav.next{right:8px}
}
/* 사진 넘기기 = 7px 점 (목업). 누를 수 있게 버튼 그대로 두고 모양만 점으로 만든다 */
.dots{position:absolute; left:0; right:0; bottom:12px; z-index:2;
  display:flex; gap:6px; justify-content:center}
.dots:empty{display:none}
.dots .shot{
  width:7px; height:7px; padding:0; border:0; border-radius:9999px;
  background:var(--tgray200); overflow:visible;
}
.dots .shot.on{background:var(--tmint600)}
/* 점은 **인디케이터**다 (2026-08-19 혜림님) — 넘기기는 스와이프와 좌우 화살표가 한다.
   pointer-events 만 끈다: 화살표(wireHeroNav)가 t.click() 으로 점을 대신 눌러 주므로
   버튼 구조와 onclick 은 그대로 둬야 한다. */
.dots .shot{pointer-events:none}
.dots .shot{position:relative}

.dbody{padding-top:16px; display:flex; flex-direction:column; gap:20px}
.dtop{display:flex; flex-direction:column; gap:6px}
.dname{display:flex; align-items:center; gap:8px;
  font-size:var(--fs-num); line-height:var(--lh-num); letter-spacing:0}
.dname b{font-weight:700}
/* #dIc 는 이모지를 뺀 뒤로 늘 빈 칸이다 — 비었을 때 gap 8px 만큼 이름이 밀려 있었다 */
.dname span:empty{display:none}
/* 가격 줄 — 확정본 상품 상세(final-goods.html:223)는 **24/32** 다:
     [20%(빨강 24/32)] [12,640원(24/32)] [15,800원(취소선 12/16)]
   목록 카드·장바구니·담기 시트는 같은 표기를 16/24 로 쓴다(확정본 39·260·400줄) —
   표기 방식(priceHtml)은 한 곳이고 **크기만** 화면마다 다르다.
   ⚠️ `.dprice b` 24px 이 안 먹고 있었다: priceHtml 이 붙이는 `.pr .pct`·`.pr .amt`
      (선택자 두 칸)가 `.dprice b`(한 칸)를 이겨서 상세 가격이 목록과 같은 16px 로 떴다.
      그래서 여기서 같은 두 칸으로 다시 적는다. */
.dprice{margin:0; display:flex; align-items:baseline; flex-wrap:wrap; gap:8px}
.dprice b{font-size:var(--fs-num-lg); line-height:var(--lh-num-lg);
  font-weight:700; letter-spacing:0}
.dprice .pr .pct,.dprice .pr .amt{font-size:var(--fs-num-lg); line-height:var(--lh-num-lg)}
/* 기간 칩 — 목업은 **민트 pill**이다(전에는 노란 쿠폰 칩이었다) */
.dtier{display:inline-flex; align-items:center; gap:6px; width:max-content; margin:2px 0 0;
  background:var(--tmint50); border-radius:9999px; padding:4px 10px;
  font-size:var(--fs-cap); line-height:var(--lh-cap); font-weight:700; color:var(--tmint700)}
.dtier svg{width:14px; height:14px; flex:none; color:var(--tmint700)}
/* 설명과 칼선 안내는 **같은 글자**다 — 14px 검정 (2026-08-14 혜림님).
   전에는 설명이 회색 14px, 칼선 안내가 회색 12px 로 세 단이 겹쳐 있었다.
   둘 다 「사기 전에 읽어야 하는 말」이라 크기·색을 나눌 이유가 없다.
   (사양 아래 `.dcaution` 세 줄은 사전 양해라 계속 한 단 낮은 회색이다.) */
.ddesc, .dnote{margin:0; font-size:var(--fs-body); line-height:var(--lh-body);
  color:#000; font-weight:400; text-wrap:pretty}
.dnote{margin-top:8px}

/* 그림 카드 — 목록의 그림 바(.artbar)와 같은 모양, 썸네일만 44px (목업 §2①)
   2026-08-14: 한동안 `display:none` 으로 숨기고 사진 위에 검은 「바꾸기」 pill 을 띄웠는데
   되돌렸다(혜림님 「굿즈 페이지 바꾸기 UI로 통일」). 확정본 상품 상세가 이 카드를 쓰고,
   목록에도 같은 카드가 있어 두 화면이 같은 모양이 된다. pill 은 그림을 가리고
   「무슨 그림으로 만들어지는지」를 말해주지 못했다. */
.artbar.dart{margin:0; width:100%; border:0; text-align:left; font:inherit; cursor:pointer}
.artbar.dart .thumb{width:44px; height:44px}
/* 아직 그림을 안 골랐을 때 — 빈 흰 칸 대신 회색 사진 아이콘 (목록 §1② 점선 줄과 같은 모양) */
.artbar.dart .thumb.none{background:var(--tgray100); color:var(--tgray300)}
.artbar.dart .thumb.none svg{width:22px; height:22px; display:block}
.artbar.dart .swap{font-style:normal; flex:none; padding:0 0 0 12px;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; color:var(--tmint600)}
.artbar.dart:active{background:var(--tgray100)}

/* 사양 — 목업은 접지 않고 펼쳐 둔다 */
.dspec{display:flex; flex-direction:column; gap:8px}
.dspec > b{font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700}

/* 옛 그림 선택 카드(.art / .artHead / .artNow)는 마크업이 없어진 지 오래다 — 지웠다.
   지금 그 자리는 목록의 .artbar 와 상세의 .artbar.dart 다. */

/* ── 옵션 (목업 §2①) ─────────────────────────────────
   칸 하나 = 높이 44 · 좌우 16 · radius 16 · 한 줄 텍스트.
   ⚠️ 선택 상태는 **테두리가 아니라 inset box-shadow** 로 그린다 — 테두리 두께를
      1px↔1.5px 로 바꾸면 고를 때마다 칸이 1px 씩 움직인다(목업도 shadow 를 쓴다). */
.optg{display:flex; flex-direction:column; gap:8px; margin-top:0}
#sOpts{display:flex; flex-direction:column; gap:20px}
.optg .lb{font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700;
  color:#000; margin:0}
.optg .row{display:flex; gap:8px; flex-wrap:wrap}
.optg button{
  height:44px; padding:0 16px; border:1px solid var(--tgray100); background:#fff;
  border-radius:16px; display:flex; align-items:center; gap:8px;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:400; color:#000;
}
/* 선택 상태는 민트다 — 분홍 --pop 은 뽑기 카드 전용이라 여기서 쓰지 않는다(TOKENS.md) */
.optg button.on{
  border-color:transparent; background:var(--tmint100); color:var(--tmint900); font-weight:700;
  box-shadow:inset 0 0 0 1.5px var(--tmint600);
}
.optg button:active{box-shadow:inset 0 0 0 1.5px var(--tmint700)}
/* 옵션은 값을 바꾸지 않는다(명세 §3) — 목업은 그 사실을 **줄 아래 회색 한 줄**로 적는다 */
/* 줄 색은 「고리」에 딸린 선택이다 — 들여쓰기로 그걸 보인다. D링을 고르면 사라진다 */
.optg.sub{padding-left:12px; border-left:2px solid var(--tgray100)}
/* 고를 게 없는 상품(톡 2종·모니터)은 제목과 값이 **같은 줄**이다 (목업 §2②) */
.optg.only1{flex-direction:row; align-items:center; gap:8px}
.optg .only{font-size:var(--fs-body); line-height:var(--lh-body); color:var(--tgray500)}
/* 색 견본 하나 — 군번줄 12색·펄 3색이 같은 모양을 쓴다.
   12개는 한 줄에 안 들어가므로 .row 의 flex-wrap 으로 두세 줄이 된다.
   ⚠️ 목업 §2 에는 색 축이 있는 상품이 없어서 이 모양은 우리 것을 유지한다 —
      색 이름 12개를 글자로만 두면 무엇이 다른지 알 수 없다.
   ⚠️ 375px 에서 넘치는지 확인할 것(QA I 그룹). */
.optg .opv.sw1{padding:0 14px 0 10px}
.optg .dot{width:22px; height:22px; flex:none; border-radius:50%;
  border:1px solid rgba(0,0,0,.12)}
/* 흰색·화이트가 배경과 안 구분되므로 테두리를 한 겹 더 준다 */
.optg .opv.on .dot{box-shadow:0 0 0 2px #fff, 0 0 0 4px var(--tmint600)}

/* 아직 못 고르는 값 (2026-08-14 군번줄 입고 전).
   회색으로만 두면 「왜 안 눌리지」가 되므로 이유를 값 옆에 작게 적는다.
   테두리를 점선으로 둬서, 색을 못 보는 경우에도 「지금은 아닌 것」이 구분된다. */
.optg .opv.off{color:var(--tgray400); background:var(--tgray50);
  box-shadow:inset 0 0 0 1.5px var(--tgray100); border-style:dashed;
  cursor:not-allowed; opacity:1}
.optg .opv.off:active{box-shadow:inset 0 0 0 1.5px var(--tgray100)}
.optg .opv.off .offn{margin-left:6px; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:var(--tgray400)}

/* 수량 (목업 §2③) — 「수량」이 왼쪽을 채우고 스테퍼가 오른쪽에 붙는다. 버튼은 44×44. */
.qtyrow{display:flex; align-items:center; gap:16px; margin-top:0;
  font-size:var(--fs-body);line-height:var(--lh-body)}
.qtyrow b{flex:1; font-weight:700; color:#000}
.qty{display:flex; align-items:center; gap:0; border:1px solid var(--tgray100); border-radius:16px; overflow:hidden}
.qty button{width:44px; height:44px; border:0; background:#fff; color:#000;
  display:flex; align-items:center; justify-content:center; padding:0}
.qty button svg{width:20px; height:20px; display:block}
/* 하한 1·상한 20 에서 비활성이 보여야 한다 — 안 그러면 눌러도 안 되는 이유를 모른다.
   목업은 회색 면까지 깐다. cursor 까지 바꿔야 「지금 못 누른다」가 전해진다(명세 §12). */
.qty button:disabled{color:var(--tgray300); background:var(--tgray50); cursor:not-allowed}
/* 상한에 닿았을 때 이유 한 줄 — 비활성만 두면 왜인지 모른다 */
.qhint{margin:0; font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray500)}
.qhint[hidden]{display:none !important}
.qty b{min-width:40px; text-align:center; flex:none;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700}

/* 상세의 큰 섹션 제목(.sec)은 쓰는 곳이 없어졌다 — 「실물 사진」 섹션이 사진 칸으로 합쳐졌고,
   「사양」은 .dspec > b (14/20) 이다. */
/* 사양 표 — 목업은 라벨 96px 고정 + 값은 **굵지 않다**(전에는 34%·bold 였다). */
.spec{width:100%; border-collapse:collapse; background:var(--card);
  border:1px solid var(--tgray100); border-radius:16px; overflow:hidden}
.spec td{padding:10px 14px; font-size:var(--fs-body); line-height:var(--lh-body);
  border-bottom:1px solid var(--tgray100)}
.spec tr:last-child td{border-bottom:0}
.spec td:first-child{color:var(--tgray500); font-weight:400; width:96px}
.spec td:last-child{font-weight:400; color:#000}

/* 상세의 규격 한 줄(.dsum)은 없앴다 — 같은 값이 사양 표에 있고 목업 §2 에는 없다 */

/* 실물 사진 가로 스트립(.dphotos)은 없앴다 — 목업 §2 는 사진을 260px 사진 칸 하나에
   넣고 아래 점으로 넘긴다. 그 점은 위 「.dots」 절이 그린다. */

/* 접힘 영역(.dmore 「주문하면 이렇게 진행돼요」)과 그 안의 단계 목록(.flow·.flownote)을
   통째로 지웠다(2026-08-14) — 확정본 상품 상세에 그 카드가 없다. 단계 원에만 쓰던
   분홍 --pop 도 그래서 사라졌다. 되살릴 일이 있으면 확정본에 먼저 그려야 한다. */

/* 상세 하단 바 — 담기 버튼 하나만 (56px, 화면 폭 전체).
   여기 있던 왼쪽 배송 안내(#dShip1·#dShip2)는 DS 에서 금지돼 마크업째 빠졌다. */

/* 하단 구매바 — 배경은 화면 끝까지, 내용은 본문(.page)과 같은 최대 너비로 가운데 정렬 */
.buybar{
  position:fixed; left:0; right:0; bottom:var(--tabh); z-index:45; display:none;
  padding:16px 20px calc(20px + env(safe-area-inset-bottom));
  background:rgba(255,255,255,.9); backdrop-filter:blur(24px); border-top:1px solid var(--tgray100);
}
.buybar .in{display:flex; gap:12px; align-items:center; max-width:var(--shell-w); margin:0 auto}
.buybar .sum{flex:none; font-size:var(--fs-num); line-height:var(--lh-num); font-weight:700}
/* 상세 하단 바 왼쪽 (목업 §2①) — 고른 옵션 12/16 위, 금액 20/28 아래 */
.buybar .bsum{flex:none; min-width:0}
.buybar .bsum span{display:block; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:var(--tgray600); max-width:12em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.buybar .bsum span:empty{display:none}
.buybar .bsum b{display:block; font-size:var(--fs-num); line-height:var(--lh-num);
  font-weight:700; color:#000}
.buybar .buy{
  flex:1; border:0; border-radius:16px; background:var(--tmint600); color:#fff;
  height:56px; padding:0 16px; font-size:var(--fs-title); font-weight:700;
}
.buybar .buy:active{background:var(--tmint700)}
.buybar .buy[disabled]{background:var(--tgray50); color:var(--tgray300)}
/* 목록 화면의 주문하기 바 — 왼쪽 장바구니 요약 + 오른쪽 주문 버튼(개수).
   탭바 위에 얹히니 bottom 을 그만큼 올린다. */
#listBar{bottom:var(--tabh); padding:8px 20px calc(8px + env(safe-area-inset-bottom))}
#listBar .in{gap:8px}
/* 굿즈 탭 하단은 장바구니 버튼만 남긴다. 왼쪽 개수/금액 문구는 버튼 숫자와 겹친다. */
/* 담긴 금액을 다시 켠다 (2026-08-16 혜림님 「장바구니 보기 왼쪽에 담긴 금액」) —
   장바구니 하단 바(cpay)와 같은 꼴: 큰 결제 예정 금액 + 작은 할인 줄.
   syncListBar 가 비었을 때 글자를 지우므로 0개면 자연히 안 보인다. */
/* 장바구니 바(cpay)와 **완전히 같은 꼴** (2026-08-16 혜림님) —
   민트 할인 줄이 위, 큰 결제 금액이 아래. 순서는 order 로 뒤집는다(마크업은 b 가 먼저). */
#listBar .ship{display:flex; flex-direction:column; flex:none; min-width:0}
#listBar .ship b{display:block; order:2; font-size:var(--fs-num); line-height:var(--lh-num);
  font-weight:700; color:#000}
#listBar .ship span{display:block; order:1; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:var(--tmint700)}
#listBar .buy{flex:1; width:100%; height:56px; padding:0 16px;
  font-size:var(--fs-body); font-weight:700;
  display:flex; align-items:center; justify-content:center; gap:8px}
#listBar .buy,
#listBar .buy[disabled]{
  background:var(--tmint600);
  color:#fff;
  opacity:1;
}
/* 장바구니 수량은 버튼 옆의 원형 배지로 읽힌다. 0개면 JS 가 빈 문자열을 넣는다. */
/* 수량 배지 — 목록의 「장바구니 보기」와 장바구니의 「주문하기」가 같이 쓴다
   (2026-08-15 혜림님). 몇 개를 담았는지/주문하는지 버튼이 말한다. */
#cartBar .buy, #listBar .buy{ display:inline-flex; align-items:center; justify-content:center; gap:8px }
#cartBar .buy .cnt,
#listBar .buy .cnt{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:24px; height:24px; padding:0 6px; box-sizing:border-box;
  border-radius:9999px; background:#fff;
  font-style:normal; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:700; color:var(--tmint600);
}
#cartBar .buy .cnt:empty,
#listBar .buy .cnt:empty{display:none}
/* 목록에서만 보인다 — 상세·장바구니·주문서에는 각자의 바가 있다 */
#listBar{display:none}
#pgList.on #listBar{display:block}

#pgDetail.on > .buybar{display:block}
#pgCart.on #cartBar:not(:empty){display:block}
#pgOrder.on #orderBar{display:block}

/* 장바구니 줄(.citem)의 정의는 이 파일 아래쪽 「장바구니 줄」 절 **한 곳**에 모았다.
   ⚠️ 예전에는 여기와 아래 세 자리에 나뉘어 있어서 display 는 마지막이, padding 은 중간이
      이기는 상태였다 — 목업으로 다시 맞추면서 뒤쪽 하나로 합쳤다.
   옛 진행 게이지(.gauge)도 지웠다: #cartGauge 는 이제 「받은 혜택」과 문턱 안내만 담는다. */

/* 금액 블록 — 장바구니(합계)와 주문서(결제 금액)가 같은 마크업을 쓴다.
   여기가 정의 한 곳이다. 아래 「주문서」 절에 있던 같은 이름의 두 번째 정의는 지웠다 —
   두 곳에 나뉘어 있어서 padding 은 아래가, border 는 위가 이기는 상태였다. */
.sumbox{background:var(--card); border:1px solid var(--tgray100); border-radius:16px;
  padding:4px 16px; margin-top:16px}
.sumrow{display:flex; justify-content:space-between; gap:12px; padding:8px 0;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:400; color:var(--tgray500)}
.sumrow>span:last-child{font-weight:700; color:#000}
.sumrow.tot{border-top:1px solid var(--tgray100); margin-top:8px; padding:16px 0}
.sumrow.tot>span:last-child{font-size:var(--fs-num); line-height:var(--lh-num)}
/* 깎인 금액·무료는 초록. 위의 :last-child 와 같은 무게라 반드시 뒤에 와야 이긴다 */
.sumrow>span.free{color:var(--tgreen600); font-weight:700}
/* 시트의 주 버튼 — 56px · radius 16 · **민트**.
   ⚠️ 여기가 분홍(--pop)이었다. 분홍은 뽑기 카드 전용이고(TOKENS.md) 목업의 담기 버튼은
      primary 민트다 — 담기·그림 확정이 모두 이 클래스를 쓴다. */
.bigbtn{width:100%; margin:0; border:0; border-radius:16px; background:var(--tmint600); color:#fff;
  height:56px; padding:0 16px; font-size:var(--fs-title);line-height:var(--lh-title); font-weight:700}
.bigbtn:active{background:var(--tmint700)}
.bigbtn[disabled]{background:var(--tgray50); color:var(--tgray300)}
.bigbtn.ghost{background:#fff; border:1px solid var(--tgray100); color:#000}
/* 빈 장바구니 (목업 §3③) — 화면 가운데 세 줄 + 민트 56px 버튼.
   전에는 회색 면 한 장이었다: 「비었다」만 말하고 갈 곳을 안 줬다. */
.cempty{min-height:340px; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:10px; text-align:center; padding:0 24px}
.cempty > b{font-size:var(--fs-sec); line-height:var(--lh-sec); font-weight:700; color:#000}
.cempty > span{font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:400; color:var(--tgray500); text-wrap:pretty}
.cempty > span b{font-weight:700; color:var(--tmint700)}
.cempty .ego{margin-top:4px; height:56px; padding:0 24px; border:0; border-radius:16px;
  background:var(--tmint600); color:#fff;
  font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700}
.cempty .ego:active{background:var(--tmint700)}

/* ── 시트 공통 (목업 §2③ · §4④) ────────────────────────
   좌우 20 · 아래 20 · radius 24 위쪽만 · 조각 사이 16. 손잡이는 40×4. */
.sheet{position:fixed; inset:0; z-index:70; display:none; background:rgba(20,18,40,.5)}
.sheet.on{display:block}
/* 본문(.page)이 --shell-w 로 가운데 정렬이라 시트도 같은 폭이어야 한다 —
   left:0;right:0 이면 넓은 화면에서 시트만 끝까지 퍼졌다. */
.sheet .sbox{position:absolute; left:50%; transform:translateX(-50%); bottom:0;
  width:100%; max-width:var(--shell-w); background:#fff;
  border-radius:24px 24px 0 0; padding:12px 20px calc(20px + env(safe-area-inset-bottom));
  max-height:76vh; overflow:auto}
/* 조각 사이 16px 은 담기·그림 시트만 — 저장 갈래 시트(#dlSheet)는 자기 여백을 쓴다 */
#optSheet .sbox,#artSheet .sbox{display:flex; flex-direction:column; gap:16px}

/* ── 머리·바닥 고정 + 가운데만 스크롤 (2026-08-14, 혜림님) ──────────────────
   마크업에는 .sbody / .sfoot 이 있었는데 **규칙이 아예 없어서** .sbox 전체가 스크롤됐다.
   옵션이 많은 상품(펄 아크릴 키링 — 크기·고리·줄 색 12개·펄 색)에서는 「담기」가 화면
   밖으로 밀려 내려가, 어디를 눌러야 담기는지가 상품마다 달라졌다.
   확정본 값: 최대 높이 화면의 84% · radius 24 24 0 0 · 바닥에 1px #EAE9EC 구분선. */
#optSheet .sbox,#artSheet .sbox{
  max-height:84vh;
  overflow:hidden;                 /* 스크롤은 .sbody 가 맡는다 */
  /* 바닥 여백은 .sfoot 이 자기 안에 갖는다 — 여기 두면 고정 바 아래에 빈 칸이 생긴다 */
  padding-bottom:0;
  gap:0;
}
#optSheet .sbody,#artSheet .sbody{
  flex:1 1 auto; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
  display:flex; flex-direction:column; gap:16px;
  padding:16px 0 16px;             /* 잡이(.grab)와 첫 조각 사이 · 바닥 구분선과의 사이 */
}
#optSheet .sfoot,#artSheet .sfoot{
  flex:none; background:#fff;
  border-top:1px solid var(--tgray100);
  /* 좌우 20px 은 .sbox 가 이미 준다 — 위아래만 여기서 준다 */
  padding:16px 0 calc(16px + env(safe-area-inset-bottom));
}
/* 고정 바닥 안에서는 「담을 금액」 아래 여백을 버튼이 아니라 이 규칙이 정한다 */
#optSheet .sfoot .oTot{margin:0 0 12px}
#artSheet .sfoot{display:none !important}
.sheet .grab{width:40px; height:4px; border-radius:9999px; background:var(--tgray100); margin:0 auto}
.sheet h2{font-size:var(--fs-title);line-height:var(--lh-title); letter-spacing:-.02em}
.sheet .ssub{margin:5px 0 14px; font-size:var(--fs-cap);line-height:var(--lh-cap); color:var(--muted); font-weight:700}
/* 그림 고르기 시트 제목 — 18/28 + 부제 14/20 (목업 §4④) */
.stitle{display:flex; flex-direction:column; gap:4px}
.stitle b{font-size:var(--fs-sec); line-height:var(--lh-sec); font-weight:700; color:#000}
.stitle span{font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:400; color:var(--tgray500)}
.snote{margin:0; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:var(--tgray600)}
/* 3열 격자 · 정사각 · radius 12. 고른 것에 민트 링 3px, 나머지는 1px 회색.
   ⚠️ 테두리(border) 대신 inset shadow 를 쓴다 — 두께가 1↔3px 로 바뀌면 칸이 움찔한다. */
/* 그림 고르기 — 「내가 꾸민 그림」/「다른 사람이 꾸민 그림」 두 묶음이 들어오므로
   격자는 바깥(#agrid)이 아니라 묶음(.agsec)이 만든다. */
.agrid{display:block}
.agsec{display:grid; grid-template-columns:repeat(3,1fr); gap:10px}
.agh{margin:0 0 8px; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:700; color:var(--tgray600)}
.agsec + .agh{margin-top:16px}
.acell{border:0; border-radius:12px; overflow:hidden; background:#fff; padding:0; cursor:pointer;
  aspect-ratio:1; box-shadow:inset 0 0 0 1px var(--tgray100)}
.acell.on{box-shadow:inset 0 0 0 3px var(--tmint600)}
.acell .im{width:100%; height:100%; background:#fff; display:flex; align-items:center; justify-content:center; overflow:hidden}
.acell .im img{width:100%; height:100%; object-fit:contain}
/* 「+ 새로 꾸미기」 — 마음에 드는 게 없을 때 여기서 바로 꾸미기로 나간다 */
.acell.anew{display:flex; align-items:center; justify-content:center; box-shadow:none;
  background:var(--tgray50); color:var(--tgray600); text-decoration:none;
  font-size:var(--fs-cap); line-height:var(--lh-cap); font-weight:400; text-align:center}
.sclose{width:100%; margin-top:14px; border:1.5px solid var(--line); background:#fff;
  border-radius:14px; padding:13px; font-size:var(--fs-body);line-height:var(--lh-body); font-weight:800}

.toast{position:fixed; left:50%; bottom:96px; transform:translateX(-50%) translateY(8px);
  background:rgba(20,18,40,.92); color:#fff; padding:11px 16px; border-radius:13px;
  font-size:var(--fs-body);line-height:var(--lh-body); font-weight:700; opacity:0; pointer-events:none; transition:.2s; z-index:90;
  /* 말줄임표 금지 (2026-08-19 혜림님) — 넘치면 두 줄로 감싼다 */
  width:max-content; max-width:calc(100vw - 32px); box-sizing:border-box; white-space:normal;
  word-break:keep-all; text-align:center}
.toast.show{opacity:1; transform:translateX(-50%)}

@media (prefers-reduced-motion:reduce){*{animation:none!important; transition-duration:.01ms!important}}

/* ── 하단 탭 (본 화면과 같은 모양) ── */
/* 탭 아이콘 — twenty-studio-home.html 과 같은 파일을 쓴다 */
.tabs a .ic{width:24px;height:24px;display:block;margin:0 auto 2px;
  background-repeat:no-repeat;background-size:24px 24px;background-position:center;
  font-size:var(--fs-sec);line-height:24px;text-align:center}
/* 선택 색은 필터 대신 마스크로 — 필터(hue-rotate)로는 #07D1AE 를 정확히 못 맞춘다 */
.tabs a .ic{background-image:none; background-color:var(--tgray600);
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
  -webkit-mask-size:24px 24px; mask-size:24px 24px}
.tabs a[data-p=pgHome]  .ic{-webkit-mask-image:url(assets/icons/tab-deco.png);  mask-image:url(assets/icons/tab-deco.png)}
.tabs a[data-p=pgAlbum] .ic{-webkit-mask-image:url(assets/icons/tab-dex.png);   mask-image:url(assets/icons/tab-dex.png)}
.tabs a[data-p=pgGoods] .ic{-webkit-mask-image:url(assets/icons/tab-goods.png); mask-image:url(assets/icons/tab-goods.png)}
.tabs a[data-p=pgMy]    .ic{-webkit-mask-image:url(assets/icons/tab-my.png);    mask-image:url(assets/icons/tab-my.png)}
.tabs a.on .ic{background-color:var(--tmint600)}

.tabs{position:fixed; left:0; right:0; bottom:0; z-index:50;
  background:#fff; backdrop-filter:blur(12px); border-top:1px solid var(--tgray50);
  display:flex;
  padding:8px max(20px,env(safe-area-inset-left)) calc(8px + env(safe-area-inset-bottom))}
.tabs .in{max-width:var(--shell-w); margin:0 auto; display:flex; width:100%; gap:4px}
.tabs a{flex:1; text-decoration:none; color:var(--tgray600); padding:7px 4px 5px; border-radius:13px;
  display:flex; flex-direction:column; align-items:center; gap:2px;
  font-size:var(--fs-cap);line-height:var(--lh-cap); font-weight:800; position:relative}
.tabs a .ic{font-size:var(--fs-sec); line-height:1}
.tabs a.on{color:var(--tmint600)}
/* 탭의 개수 배지도 없앴다 — 확정본 탭바(final-goods.html:69)에 없고, 이 파일에서
   분홍(--pop)을 UI 에 쓰던 마지막 자리였다(분홍은 뽑기 카드 전용 · TOKENS.md). */
/* 아래쪽 여백은 위 .buybar 정의(20px + safe-area)를 쓴다 —
   여기서 12px 로 덮고 있었어서 홈 버튼 있는 기기에서 바가 아래에 붙어 보였다. */
.buybar{bottom:var(--tabh)}
.toast{bottom:130px}

/* 「이 그림으로 만들어져요 · 바꾸기」 버튼(.heroSwap)은 없앴다 — 목업 §2① 은 이걸
   사진 칸 아래 가운데 버튼이 아니라 **본문 안의 그림 카드**로 둔다(.artbar.dart). */

/* ── 담기 시트 (목업 §2③) ────────────────────────────
   그림과 수량만 있다 — 옵션은 상세 화면으로 올라갔다.
   상품 줄: 56px 썸네일(radius 8) + 이름 16/24 + 부제 12/16, 구분선 없음. */
.oHead{display:flex; align-items:center; gap:12px}
.oTh{width:56px; height:56px; border-radius:8px; background:var(--tgray50); flex:none;
  display:flex; align-items:center; justify-content:center; overflow:hidden; position:relative}
.oHead .otx{flex:1; min-width:0}
.oNm{font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700; letter-spacing:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.oArt{font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray600); font-weight:400;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
/* 담을 금액 — 구분선 위, 왼쪽 라벨 14/20 회색 / 오른쪽 금액 20/28 */
.oTot{display:flex; align-items:baseline; justify-content:space-between; margin:0 0 16px;
  padding-top:16px; border-top:1px solid var(--tgray100);
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:400; color:var(--tgray500)}
/* 담을 금액은 priceHtml() 이 그린다 — 할인율(빨강)·할인가(크게)·정가(취소선).
   한 줄에 담기게 오른쪽 정렬로 세운다(위 .pr 은 블록이라 그대로 두면 왼쪽으로 흐른다). */
.oTot .pr{margin-top:0; text-align:right}
.oTot .pr .now{justify-content:flex-end}
.oTot .pr .amt{font-size:var(--fs-num); line-height:var(--lh-num); color:#000}
.oTot .pr .pct{font-size:var(--fs-num); line-height:var(--lh-num)}
#optSheet .oTot{display:none !important}
#optSheet .sfoot .bigbtn{width:100%}

/* 장바구니 썸네일에도 상품 형태를 씌운다 */
.citem .th.im{--sh:#C9CEE0}
.citem .th .pimg{width:78%; height:78%}

/* ── 장바구니 선택 ── */
/* 체크박스 20px 민트 (HANDOFF §2.6) — 목업의 「민트 네모 + 흰 체크」가 accent-color 의 모양이다 */
.allrow input,.citem .pick{width:20px; height:20px; accent-color:var(--tmint600); flex:none; margin:0}
.allrow b{color:var(--tgray500); font-weight:400}
.rcell .pr,
.rcell .pr b{color:#000}
.rcell .pr s{color:var(--tgray500)}
/* .citem .del(줄마다 ✕)은 없앴다 — 아래 「장바구니 줄」 절의 같은 이름 주석 참고 */
/* 장바구니 바는 renderCart()가 내용을 채운 뒤에만 보인다.
   빈 고정 바가 먼저 자리 잡으면 첫 진입 때 아래 여백이 덜컥거린다. */
#pgCart.on #cartBar:not(:empty){display:block}

#cartGauge{display:none !important}

/* 최소 주문 안내는 주문 버튼 위 한 줄만 남긴다. 게이지/혜택 블록은 금액 문턱을
   중복으로 읽히게 해서 장바구니 화면에서 숨긴다. */
/* 받은 혜택 (목업 §3①) — 카드 **전체**가 옅은 민트다. 전에는 머리줄만 초록 tint 였고
   줄은 흰 배경이라, 「혜택 목록」이 아니라 접힌 표처럼 보였다.
   글자는 모두 tmint900, 체크만 tgreen600. 덧붙임은 줄을 바꾸지 않고 같은 줄에 작게 붙는다. */
.benefits{margin-bottom:12px; border-radius:16px;
  background:var(--tmint50); border:1px solid var(--tmint100);
  padding:12px 16px; display:flex; flex-direction:column; gap:10px}
.benefits .bhd{font-size:var(--fs-body); line-height:var(--lh-body)}
.benefits .bhd b{font-weight:700; color:var(--tmint900)}
.benefits .brow{display:flex; align-items:center; gap:8px;
  font-size:var(--fs-body); line-height:var(--lh-body); color:var(--tmint900)}
.benefits .brow .ck{width:18px; height:18px; flex:none; color:var(--tgreen600)}
.benefits .brow .bt{flex:1; min-width:0}
.benefits .brow .bt i{font-style:normal;
  font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tmint700)}
.benefits .brow .bv{flex:none; font-weight:700; color:var(--tmint900)}
/* 아직 못 받은 것 하나 — 노란 카드 + **진행 막대**. 여러 개 띄우지 않는다(목업 §3②).
   ⚠️ 아래 세 hex 는 TOKENS.md 에 없다 — 목업에서 그대로 읽어온 값이라 임의로
      가까운 토큰에 끼워 맞추지 않았다. 토큰으로 승격할지 알려주시면 옮긴다.
      #FFF0B3 테두리·막대 바탕 · #723B13 제목 · #8A5A16 설명 */
.nextup{display:flex; flex-direction:column; gap:8px; margin-bottom:12px;
  background:var(--tyellow50); border:1px solid #FFF0B3; border-radius:16px; padding:12px 16px;
  font-size:var(--fs-body); line-height:var(--lh-body)}
.nextup > b{font-weight:700; color:#723B13}
.nextup .bar{display:block; height:6px; border-radius:9999px; background:#FFF0B3; overflow:hidden}
.nextup .bar i{display:block; height:100%; background:var(--tyellow500)}
.nextup > i{font-style:normal; font-size:var(--fs-cap); line-height:var(--lh-cap); color:#8A5A16}
.nextup > i b{font-weight:700}
/* 이미 쿠폰을 쓴 사람에게는 **회색 상자 한 줄**만 (목업 §3②) —
   못 받는 걸 노랑으로 재촉하면 함정으로 읽힌다. */
/* ── 장바구니 (배민 패턴) ── */
.allrow{display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:0 0 16px; margin-bottom:0}
.allrow label{display:flex; align-items:center; gap:12px;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; color:#000}
/* 「선택 삭제」는 글자 버튼 — 히트 영역 44px 을 padding 으로 만든다 (12+20+12) */
.allrow #delPicked{border:0; background:none; border-radius:0;
  padding:12px 0; font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:700; color:var(--tgray500)}
/* 하단 고정 바 (목업 §3①②) — 금액 블록과 버튼이 **한 줄에 나란히** 선다.
   문턱을 못 넘겼을 때만 그 위에 안내 한 줄이 가운데로 붙는다(목업 ②).
   ⚠️ 예전에는 안내 한 줄 위 / 버튼 아래로 세로 배치였고, 그래서 `.buybar .buy` 의
      `flex:1` 이 **높이**에 걸려 버튼이 납작해지는 걸 `flex:none` 으로 막아야 했다.
      지금은 다시 가로 배치라 `flex:1` 이 폭으로 제대로 걸린다. */
#pgCart .buybar .in{flex-direction:column; align-items:stretch; gap:8px}
#pgCart .crow{display:flex; align-items:center; gap:12px}
#pgCart .cwhy{text-align:center; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:var(--tgray600)}
/* 왼쪽 금액 블록 — 위에 「8,200원 아꼈어요」 12/16 민트, 아래 결제 금액 20/28 */
#pgCart .cpay{flex:none; min-width:0}
#pgCart .cpay span{display:block; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:var(--tmint700)}
#pgCart .cpay b{display:block; font-size:var(--fs-num); line-height:var(--lh-num);
  font-weight:700; color:#000}
#pgCart .buy{flex:1; width:auto; height:56px}
.buy.ghost{background:#fff; border:1px solid var(--tgray100); color:#000}

#pgCart{overflow-x:hidden}

/* 사진 저장 — 미리보기 우상단 */
.heroDl{position:absolute; right:20px; top:20px; width:40px; height:40px; border:0;
  border-radius:12px; background:var(--tgray50); color:#000; font-size:var(--fs-title); line-height:1}
.heroDl:active{transform:scale(.94)}


/* ── 옵션 시각 표현 ──
   ⚠️ 여기 있던 `.optg button.opv{padding:9px 13px …}` 를 지웠다 — 위 「옵션」 절이
      높이 44 · padding 0 16 으로 정한 걸 이 줄이 뒤에서 덮고 있었다.
      크기 비율 네모(.sz)도 지웠다: 목업은 「작은 것 4cm」 한 줄로 쓴다. */
.optg .ol{display:flex; flex-direction:column; align-items:flex-start; line-height:1.3}
/* 펄 색상 견본 */
.optg .sw{width:24px; height:24px; flex:none; border-radius:50%; border:1px solid rgba(26,34,80,.12)}
.sw-rainbow{background:conic-gradient(from 210deg,#ffd9ec,#d9f0ff,#dcffe4,#fff6cf,#f0dcff,#ffd9ec)}
.sw-silver{background:linear-gradient(135deg,#f4f6fa,#c9cfdd 45%,#f7f9fc 60%,#b8c0d2)}
.sw-gold{background:linear-gradient(135deg,#fff3cf,#e8c15f 45%,#fff8e2 60%,#d4a63c)}

/* ── 실물 사진 ── */
.im.has-photo{background:#fff}
.im img.real{width:100%; height:100%; object-fit:cover; display:block}
/* 사진 칸은 회색 면을 그대로 둔다 — 목업 §2 의 사진 칸은 흰색이 아니다 */
/* 칼선 미리보기는 잘리면 안 된다 — cover로 두면 키링 고리와 코롯토 바닥이 화면 밖으로 나간다.
   실물 사진은 잘려도 무엇인지 알지만, 이건 "이 모양대로 잘려 옵니다"를 보여주는 그림이다. */
img.sian{object-fit:contain !important; background:#fff}
.citem .th img.sian{padding:2px}
/* 칼선도 사진 칸(390×390)을 그대로 쓴다. 한때 여기에 max-height:260px 을 걸어 뒀는데,
   그건 칼선이 125×207 로 나오던 때의 임시 방편이었다 — 3배로 늘어나 빨간 선이 계단처럼
   깨졌기 때문이다. 원인은 크기 요청이 40mm 대신 4mm 로 나가던 것이었고(pod-core.js 의
   `mmOf` 주석 참고), 고치니 302×384 로 나와 확대가 거의 없다. 제한은 그래서 뺐다. */
/* 52px 사진 썸네일(.shots)은 없앴다 — 목업 §2 는 그 자리를 7px 점(.dots)으로 쓴다.
   「내 그림」 딱지도 함께 사라졌다: 점 하나에 글자를 얹을 자리가 없다. */

/* ── 담았어요 (토스트 아님 — 썸네일·문구·버튼이 한 줄에 들어가는 카드) ── */
/* 본문 폭에 맞춰 가운데로 — 넓은 화면에서 혼자 끝까지 퍼지지 않게 */
/* 「담았어요」 알림 — 본문 폭 안에 들어오게 한다 (전엔 496px 로 본문보다 넓었다) */
/* 「담았어요」 배너는 화면 위 안내라 팝업(.ordone 82)보다 아래에 둔다.
   전에는 95 라서, 배너가 사라지기 전에 주문을 마치면 완료 팝업 위로 올라와 가렸다. */
/* 모양은 확정본의 검정 토스트다(final-goods.html:495·499) — 검정 면 · radius 16 ·
   padding 12/16 · 20px 민트 아이콘 · 흰 14/20 700. 전에는 흰 카드 + 44px 썸네일 +
   민트 네모 버튼이라 화면 아래에 카드가 하나 더 뜬 것처럼 보였다. */
.added{position:fixed; left:50%; transform:translateX(-50%); width:calc(100% - 24px); max-width:var(--shell-w);
  bottom:126px; z-index:78;
  display:flex; align-items:center; gap:10px; padding:12px 16px;
  background:#000; border-radius:16px;
  opacity:0; pointer-events:none; transition:opacity .22s, bottom .22s}
.added.show{opacity:1; pointer-events:auto}   /* transform은 가운데 정렬용이라 지우면 안 된다 */
.added .aic{width:20px; height:20px; flex:none; color:var(--tmint600)}
.added .aic svg{width:20px; height:20px; display:block}
.added .atx{flex:1; min-width:0}
.added .atx b{display:block; font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:700; color:#fff; letter-spacing:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.added .atx small{display:block; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:rgba(255,255,255,.65); margin-top:2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
/* 「장바구니 보기」는 민트 글자 버튼 — 확정본 토스트에 채운 버튼이 없다 */
/* 담은 직후 한 줄 — 「주문하려면 번호 인증이 필요해요」 (2026-08-15).
   옵션 줄보다 한 단 낮은 회색이라 「담았다」가 먼저 읽힌다. 눌러서 장바구니로 간다. */
.added .anote{display:block; margin-top:4px; font-size:var(--fs-cap); line-height:var(--lh-cap);
  color:var(--tyellow500); cursor:pointer;
  /* ⚠️ 위의 `.atx small` 이 한 줄로 자른다(nowrap+ellipsis) — 이 문장은 길어서 잘린다.
     여기서 되돌린다. 잘린 안내는 없는 것만 못하다. */
  white-space:normal; overflow:visible; text-overflow:clip}
.added .anote[hidden]{display:none}
.added button{flex:none; border:0; background:none; padding:0 0 0 4px; color:var(--tmint600);
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; white-space:nowrap}

/* ── 장바구니 줄 (목업 §3①) — 이 파일에서 .citem 정의는 여기 한 곳이다 ────────
   체크(20) · 썸네일(56 · radius 8) · 본문(이름 14/20 → 옵션·캐릭터 12/16 →
   한 줄 안에 왼쪽 수량 스테퍼 + 오른쪽 금액 두 줄).
   전에는 금액이 위, 수량이 그 아래로 쌓여 줄 높이가 20px 더 컸다. */
.citem{display:flex; align-items:flex-start; gap:12px; position:relative;
  background:var(--card); border:1px solid var(--tgray100); border-radius:16px;
  padding:16px; margin-bottom:12px; min-width:0; max-width:100%}
.citem .pick{margin-top:2px}
.citem .th{width:56px; height:56px; flex:none; border-radius:8px; background:var(--tgray50);
  overflow:hidden; display:flex; align-items:center; justify-content:center; cursor:pointer}
.citem .th img{width:100%; height:100%; object-fit:cover}
.citem .bd{flex:1; min-width:0; max-width:100%}
/* ✕ 가 없어졌으니 이름 줄의 오른쪽 여백(28px)도 없앴다 — 긴 이름이 그만큼 덜 잘린다 */
.citem .nm{
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700;
  letter-spacing:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.citem .ch{font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray600);
  font-weight:400; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
/* 수량과 금액이 **한 줄**에 — 금액은 오른쪽 끝으로 밀어 붙인다 */
.citem .rw{display:flex; align-items:center; gap:8px; margin-top:8px}
/* 줄 안의 스테퍼는 36px · radius 12 (시트의 44px 보다 작다 — 목업 값) */
.citem .qty{margin:0; width:max-content; flex:none; border-radius:12px}
.citem .qty button{width:36px; height:36px}
.citem .qty button svg{width:18px; height:18px}
.citem .qty b{min-width:32px}
/* 가격은 **옵션 줄 바로 아래 왼쪽**이다 — 확정본 장바구니 줄(final-goods.html:383·400):
     [20%(빨강 16/24)] [12,640원(16/24)]  /  아래 줄에 [15,800원 취소선 12/16]
   오른쪽으로 밀어 두었더니(margin-left:auto·text-align:right) 폭이 좁아 세 줄로 쪼개졌고,
   글자도 14px 로 눌려서 목록·상세·담기 시트와 가격이 달라 보였다(확정 사항 ① 위반).
   크기는 공용 `.pr` 규칙(16/24)을 그대로 쓴다 — 여기서 다시 정하지 않는다. */
.citem .pr{min-width:0}
/* 줄마다 있던 ✕ 를 없앴다(2026-08-14) — 확정본 장바구니 줄(final-goods.html:378~410)에
   삭제 단추가 없다. 빼는 길은 「선택 삭제」와, 수량을 1에서 한 번 더 줄이는 것 둘이다. */
/* 어떤 이름이 와도 가로로 밀리지 않게 (담긴 품목마다 폭이 달라지는 걸 막는다) */
.citem .nm, .citem .ch{overflow-wrap:anywhere}

/* 장바구니 요약 — 목업 §3① 은 **카드가 아니라** 위쪽 구분선 아래의 맨 줄들이다.
   결제 금액과 「아꼈어요」는 하단 고정 바가 들고 있으므로 여기서 되풀이하지 않는다. */
.sumbox.csum{background:none; border:0; border-top:1px solid var(--tgray100);
  border-radius:0; padding:12px 0 0; margin-top:12px;
  display:flex; flex-direction:column; gap:8px}
.sumbox.csum .sumrow{padding:0}

/* 담기 시트 안 그림 고르기 */
/* 담기 시트 안 그림 줄 (목업 §2③) — 64px 정사각 · radius 16 · 캡션 없음.
   고른 것은 **바깥쪽** 민트 링 2px, 나머지는 안쪽 회색 1px.
   ⚠️ 선택 색이 분홍(--pop)이었다 — 분홍은 뽑기 카드 전용이다(TOKENS.md). */
.artstrip{display:flex; gap:8px; overflow-x:auto; padding:2px; scrollbar-width:none}
.artstrip::-webkit-scrollbar{display:none}
.artstrip .acell2{flex:none; width:64px; height:64px; padding:0; border:0;
  border-radius:16px; overflow:hidden; background:#fff;
  box-shadow:inset 0 0 0 1px var(--tgray100)}
.artstrip .acell2.on{box-shadow:0 0 0 2px var(--tmint600)}
.artstrip .acell2 .im{display:block; width:100%; height:100%; background:#fff}
.artstrip .acell2 .im img{width:100%; height:100%; object-fit:contain}
/* 담기 시트의 그림 줄이 비었을 때 (renderSheetArt) — 목록의 큰 빈 화면과 같은 클래스를
   쓰지만 여기서는 회색 한 줄이다. ⚠️ 스코프를 꼭 붙일 것: 스코프가 없어서 목록의
   #artEmpty 까지 12px 회색 글씨로 만들고 있었다. */
.artstrip .artempty{display:block; font-size:var(--fs-cap);line-height:var(--lh-cap);
  font-weight:400; color:var(--tgray600); padding:10px 2px; margin:0}

/* 하단 고정 요소(탭바 + 구매바)의 실제 높이를 JS가 재서 --botpad 에 넣는다.
   고정값으로 두면 바 높이를 바꿀 때마다 여백이 남거나 가려진다. */
.added{bottom:var(--addedbot,126px)}

/* ── 주문서 ── (본체에서 옮겨온 폼)
   배송 주소 / 구매자 정보를 각각 한 장의 카드로 (HANDOFF §2.6). */
/* 확정본 주문서 ①(final-goods.html:508~544) — 카드 padding 16 · 조각 사이 12 ·
   제목은 **14/20**(18/28 이 아니다) · 칸은 **라벨 없는 48px row** 다.
   라벨(.fld label)과 카드 아래 안내문(.fsub)은 2026-08-14에 지웠다 — 확정본에 둘 다 없다.
   무슨 칸인지는 placeholder 가 말하고(「받는 분 휴대폰 번호」처럼 라벨 문구를 그대로 옮겼다),
   빠진 칸은 하단 바의 한 줄(#placeWhy)이 말한다. */
.fbox{background:var(--card);border:1px solid var(--tgray100);border-radius:16px;
  padding:16px;margin-bottom:16px}
.fbox h3{font-size:var(--fs-body);line-height:var(--lh-body);font-weight:700;margin:0;
  letter-spacing:0;color:#000}
.fbox h3 + .fld,.fbox h3 + .chkrow{margin-top:12px}
.fld{margin-bottom:12px}
.fld:last-child{margin-bottom:0}
/* ⚠️ 입력칸 글자는 16px 아래로 내리지 말 것.
   iOS 사파리는 16px 미만 입력칸에 포커스가 가면 화면을 확대한다(그리고 안 돌아온다).
   주소를 치려고 누르면 화면이 확 커지던 게 이것이었다.
   viewport 에 maximum-scale=1 을 걸어 막는 방법도 있지만, 그러면 손가락으로
   확대하는 것 자체가 막혀서 잘 안 보이는 사람이 못 키운다 — 글자 크기로 푼다. */
/* 칸 높이는 목업의 48px 로 낮췄다.
   ⚠️ 글자 크기는 **16px 아래로 내리지 말 것** — 목업이 14 로 그렸어도 여기는 16 이다.
   iOS 사파리는 16px 미만 입력칸에 포커스가 가면 화면을 확대한다(그리고 안 돌아온다).
   주소를 치려고 누르면 화면이 확 커지던 게 이것이었다. viewport 에 maximum-scale=1 을
   걸어 막는 방법도 있지만, 그러면 손가락 확대 자체가 막혀 잘 안 보이는 사람이 못 키운다. */
.fld input,.fld textarea{width:100%;border:1px solid var(--tgray100);background:#fff;border-radius:16px;
  padding:0 16px;height:48px;font:inherit;font-size:var(--fs-title);line-height:var(--lh-title);color:#000;letter-spacing:-.01em}
.fld input::placeholder,.fld textarea::placeholder{color:var(--tgray300)}
.fld input:focus,.fld textarea:focus{outline:none;border-color:var(--tmint600)}
.fld input[disabled],.fld input[readonly]{background:var(--tgray50);color:var(--tgray500)}
.fld textarea{min-height:80px;height:auto;padding:14px 16px;resize:vertical}
.fld .hint{font-size:var(--fs-cap);line-height:var(--lh-cap);color:var(--tgray600);
  font-weight:400;margin-top:6px}
.chkrow{display:flex;align-items:center;gap:12px;margin-bottom:12px;
  font-size:var(--fs-body);line-height:var(--lh-body);font-weight:400;color:#000}
.chkrow input[type=checkbox]{width:20px;height:20px;accent-color:var(--tmint600);flex:none;margin:0}
.vrowin{display:flex;gap:8px;align-items:stretch}
.vrowin input{flex:1;min-width:0}
/* 「주소 찾기」·「인증」은 보조 버튼 — 회색 면(tgray-50) 위 검정 글자 (HANDOFF §2.6).
   목업은 폭 96 · 높이 48 이다. */
.vrowin button{flex:none;width:96px;height:48px;padding:0 12px;border:0;background:var(--tgray50);color:#000;
  border-radius:16px;font:inherit;font-size:var(--fs-body);font-weight:700;white-space:nowrap}
.vrowin button:active{background:var(--tgray100)}
.vrowin button[disabled]{color:var(--tgray300);background:var(--tgray50);cursor:default}
.vrowin button.ok{color:var(--tgreen600);background:var(--tgreen50)}
/* .paynote(「주문 완료를 누르면 결제 화면으로 넘어가요」)는 없앴다 — 확정본 주문서 ①에 없다 */
/* ⚠️ 여기 있던 .sumbox·.sumrow 두 번째 정의를 지웠다 — 위쪽(「금액 블록」)이 정의 한 곳이다.
   주문서에서만 다른 것은 아래 두 줄뿐. */
/* 주문 요약은 .fbox 카드 안에 들어간다 — 카드가 이미 테두리·padding 을 갖고 있어
   안쪽 .sumbox 는 테두리를 벗고 줄 간격(10px)만 낸다 (목업 §4①). */
#pgOrder .sumcard{padding:16px}
#pgOrder .sumbox{margin:10px 0 0;padding:0;background:none;border:0;border-radius:0;
  display:flex;flex-direction:column;gap:10px}
#pgOrder .sumbox .sumrow{padding:0}
#pgOrder .sumbox .sumrow.tot{margin-top:0;padding-top:10px}
#pgOrder .note{margin-top:20px;font-size:var(--fs-cap);line-height:var(--lh-cap);
  color:var(--tgray600);font-weight:400;text-align:center;background:none;padding:0 6px}
/* 막힌 이유를 버튼 「위」에 한 줄로 — 모르면 사용자가 그냥 나간다.
   .buybar .in 은 가로 배치라 그냥 두면 이유가 버튼 왼쪽 옆에 붙어 버튼을 밀었다. */
#pgOrder .buybar .in{flex-direction:column;align-items:stretch;gap:0}
/* 위 #pgCart 와 같은 이유 — 세로 바에서는 flex:1 이 높이를 눌러 버린다 */
#pgOrder .buybar .buy{flex:none;height:56px;width:100%}
/* 「전에 담아두신 N개가 더 있어요」 — renderDraftExtra 가 그리는 칸.
   버튼에 클래스가 `ghost` 하나뿐이라 브라우저 기본 버튼(회색 각진 네모)으로 떠 있었다. */
#orderExtra{background:var(--tyellow50);border-radius:16px;padding:16px}
#orderExtra .hint{margin:0 0 12px;font-size:var(--fs-body);line-height:var(--lh-body);
  font-weight:400;color:#723B13}
#orderExtra .ghost{width:100%;height:48px;border:1px solid var(--tgray100);background:#fff;
  border-radius:16px;color:#000;font:inherit;
  font-size:var(--fs-body);line-height:var(--lh-body);font-weight:700}
#orderExtra .ghost:active{background:var(--tgray50)}

/* 막힌 이유 — 목업 §4① 은 버튼 위 **가운데 12/16 회색** 한 줄이다 */
#orderBar #placeWhy{text-align:center;margin:0 0 8px;color:var(--tgray600);font-weight:400;
  font-size:var(--fs-cap);line-height:var(--lh-cap)}
.buy.ghost{background:var(--card);color:var(--ink);border:1.5px solid var(--line)}

/* ── 주문 접수됨 (결제 대기) ──
   부품을 확정본 주문서 ②(final-goods.html:545~576)에서 가져왔다:
     · 성공 아이콘 = 64px tint 원 + 32px 글리프 (확정본 결제 완료 584줄과 같은 치수)
     · 주문번호 = mono 12/16 700 · #F6F5F7 면 · radius 9999 (560·586줄)
     · 상태 배지 「결제 대기」 = #FFFCE4 면 · #723B13 글자 · radius 9999 (560줄)
     · 안내 한 줄 = #F6F5F7 면 · radius 12 · 14/20 #6E677A (568줄)
     · 주 버튼 56px 민트 → 보조 버튼 48px 흰 면 + #EAE9EC 테두리 · 14/700 #6E677A (571·572줄)
   전에는 800 굵기·--ink 남색·--chip 라벤더 회색으로 이 화면만 다른 팔레트를 쓰고 있었다. */
.ordone{position:fixed;inset:0;background:rgba(20,18,40,.55);z-index:82;display:none;
  align-items:center;justify-content:center;padding:22px}
.ordone.show{display:flex}
/* 아이폰 안내 — 주문 목록의 노란 카드와 같은 꼴 (2026-08-15 혜림님) */
.doneWarn{display:flex;gap:8px;align-items:flex-start;text-align:left;
  margin:14px 0 16px;padding:12px 14px;border-radius:14px;background:var(--tyellow50)}
.doneWarn .ic{flex:none;width:18px;height:18px;border-radius:9999px;
  background:var(--tyellow500);color:#fff;display:flex;align-items:center;justify-content:center;
  font-size:12px;line-height:1;font-weight:700}
.doneWarn .tx{flex:1;min-width:0;font-size:var(--fs-cap);line-height:var(--lh-cap);
  color:var(--myds-warn-ink2,#8A5A16)}
.doneWarn .tx b{display:block;margin-bottom:2px;font-size:var(--fs-body);line-height:var(--lh-body);
  font-weight:700;color:var(--myds-warn-ink,#723B13)}
.doneBox{background:#fff;border-radius:24px;padding:24px 20px 20px;max-width:330px;width:100%;text-align:center;
  box-shadow:0 14px 44px rgba(0,0,0,.28)}
/* 🚨 `> .ic` 로 좁힌다 — `.doneBox .ic` 로 두면 같은 특이도가 **나중에 선언**돼
   위 .doneWarn .ic(18px 노란 원)를 덮는다. 실제로 노란 카드의 ! 가 64px 민트 원이
   됐었다 (2026-08-16 혜림님이 잡았다). 이 규칙은 맨 위 체크 원 하나만의 것이다. */
.doneBox > .ic{width:64px;height:64px;border-radius:9999px;margin:0 auto 16px;
  background:var(--tgreen50);color:var(--tgreen600);
  display:flex;align-items:center;justify-content:center}
.doneBox > .ic svg{width:32px;height:32px;display:block}
.doneBox h3{font-size:var(--fs-num-lg);line-height:var(--lh-num-lg);font-weight:700;margin:0;
  letter-spacing:-.02em;word-break:keep-all}
.doneBox .donerow{display:flex;align-items:center;justify-content:center;gap:8px;
  flex-wrap:wrap;margin-top:12px}
.doneBox .no{font-size:var(--fs-cap);line-height:var(--lh-cap);font-weight:700;color:var(--tgray500);
  font-family:ui-monospace,Menlo,monospace;
  background:var(--tgray50);border-radius:9999px;padding:4px 12px;display:inline-block}
.doneBox .donerow .st{font-size:var(--fs-cap);line-height:var(--lh-cap);font-weight:700;
  color:#723B13;background:var(--tyellow50);border-radius:9999px;padding:4px 10px}
.doneBox p{margin:16px 0 0;padding:12px 16px;border-radius:12px;background:var(--tgray50);
  font-size:var(--fs-body);line-height:var(--lh-body);font-weight:400;color:var(--tgray500);
  text-align:left;word-break:keep-all}
.doneBox p b{font-weight:700;color:#000}
/* 주문번호 아래 한 줄 — 어느 번호로 접수됐는지 보여준다. 비어 있으면 자리를 차지하지 않는다. */
.doneBox .donePhone{font-size:var(--fs-cap);line-height:var(--lh-cap);font-weight:400;
  color:var(--tgray600);margin:8px 0 0}
.doneBox .donePhone:empty{display:none;margin:0}
/* 버튼 묶음 — 주 버튼 56 · 보조 48. 첫 버튼만 위 간격 16, 나머지는 8 로 붙는다 */
.doneBox .buy{width:100%;height:56px;margin-top:16px;border:0;border-radius:16px;
  background:var(--tmint600);color:#fff;
  font-size:var(--fs-title);line-height:var(--lh-title);font-weight:700}
.doneBox .buy:active{background:var(--tmint700)}
.doneBox .buy.ghost{height:48px;margin-top:8px;background:#fff;color:var(--tgray500);
  border:1px solid var(--tgray100);font-size:var(--fs-body);font-weight:700}
.doneBox .buy.ghost:active{background:var(--tgray50)}
.doneBox .hint{margin-top:8px;text-align:left;
  font-size:var(--fs-cap);line-height:var(--lh-cap);font-weight:400;color:var(--tgray600)}
.doneBox .hint b{font-weight:700;color:#000}

/* 주소 찾기 */
.addrLayer{position:fixed;inset:0;z-index:200;background:#fff;display:none;flex-direction:column}
.addrLayer.show{display:flex}
.addrHead{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;
  border-bottom:1px solid var(--line);font-size:var(--fs-title);line-height:var(--lh-title);font-weight:800;
  padding-top:max(14px,env(safe-area-inset-top))}
.addrHead button{width:32px;height:32px;border:0;background:var(--chip);border-radius:10px;font-size:var(--fs-body);line-height:var(--lh-body)}
.addrBox{flex:1;min-height:0}

/* 다음 할인 계단 안내 — 한 개 더 담는 자리 */
.tiernudge{margin-top:12px;background:var(--tmint50);border:0;border-radius:8px;
  padding:12px;font-size:var(--fs-body);line-height:var(--lh-body);font-weight:400;
  color:var(--tmint700);text-align:center}
.tiernudge b{color:var(--tmint900);font-weight:700}

/* 쿠폰 안내 (장바구니 맨 위).
   ⚠️ 이 칸을 담는 #cartGauge 는 지금 `display:none` 이라 화면에 안 뜬다 — 아래 그 자리 주석 참고. */
.cpbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px;
  padding:12px;border-radius:8px;background:var(--tyellow50);border:0}
.cpbar b{font-size:var(--fs-body);line-height:var(--lh-body);font-weight:700;color:#000}
.cpbar span{font-size:var(--fs-cap);line-height:var(--lh-cap);font-weight:400;color:var(--tgray500)}
/* 「주문하면 이렇게 진행돼요」 단계 목록(.flow·.flownote)과 사진 캡션(.dcap·.dsample)을
   지웠다(2026-08-14) — 확정본 상품 상세에 넷 다 없다. 단계 원의 분홍 --pop 도 여기서 사라졌다. */

/* 저장 갈래 (#dlSheet)
   ⚠️ 2026-08-14 — 아이콘에 크기 규칙이 아예 없어서 SVG 가 칸 너비만큼 커져 있었다
      (한 줄이 화면 한 장을 잡아먹었다). 여는 자리(#dlArt)가 2026-08-12에 빠져
      화면에 안 뜨는 동안 아무도 못 봤다. 되살릴 때를 대비해 DS 로 맞춘다.
      틀은 담기 시트(.optrow)와 같다 — 아이콘 24 · 글 · 오른쪽 chevron 20. */
.dlopt{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  border:1px solid var(--line);background:#fff;min-height:56px;
  border-radius:16px;padding:12px 16px;margin-bottom:8px;cursor:pointer}
.dlopt:last-child{margin-bottom:0}
.dlopt .dic{flex:none;width:24px;height:24px;color:var(--muted)}
.dlopt .dtx{flex:1;min-width:0}
.dlopt .dch{flex:none;width:20px;height:20px;color:#C4C2CA}
.dlopt b{display:block;font-size:var(--fs-body);line-height:var(--lh-body);font-weight:800;letter-spacing:-.01em}
.dlopt i{display:block;font-style:normal;font-size:var(--fs-cap);line-height:var(--lh-cap);font-weight:700;color:var(--muted);margin-top:3px}
.dlopt:active{transform:scale(.99)}

/* 금액이 뒤에서 바뀌었을 때 눈에 띄게 — 못 보고 지나치면 그대로 결제된다 */
.sumbox.flash{animation:sumflash 1.6s ease}
@keyframes sumflash{0%,100%{box-shadow:none}
  20%,60%{box-shadow:0 0 0 3px var(--pop)}}

/* ─── 하단 네비 — 홈 문서와 같은 모양 (Figma BottomNav 100:4008) ─── */
.tabs{
  background:rgba(0,0,0,.8) !important;
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  border-top:0 !important;
  padding:8px max(20px,env(safe-area-inset-left)) calc(8px + env(safe-area-inset-bottom)) !important;
}
.tabs .in{display:flex; align-items:center; gap:0; max-width:640px; margin:0 auto}
.tabs a{
  flex:1 1 0; min-width:0; height:40px; padding:0; border-radius:0; gap:0;
  display:flex; flex-direction:row; align-items:center; justify-content:center;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:400;
  color:var(--tgray600); text-decoration:none; position:relative;
}
.tabs a.on{ color:#fff !important; font-weight:700 }
.tabs .ic{ display:none !important }
/* 트웬티 로고 — 누르면 앱이 열린다. 자리는 그대로 두고 span 만 a 로 바꿨다.
   SVG 안에 민트 바탕이 들어 있어서 배경색은 SVG 가 안 뜰 때만 보인다. */
/* 목업 §1 의 탭바: 로고 28px · 구분선 1×20 · 사이 간격 16 */
.tabs .navlogo{
  flex:0 0 auto; width:28px; height:28px; border-radius:999px;
  background:var(--tmint600) url(assets/twenty-logo.svg) center/cover no-repeat;
  display:flex; align-items:center; justify-content:center; margin-right:16px;
  -webkit-tap-highlight-color:transparent;
}
a.navlogo{ transition:transform .12s ease }
a.navlogo:active{ transform:scale(.9) }
.tabs .navdiv{ flex:0 0 auto; width:1px; height:20px; background:rgba(255,255,255,.2); margin-right:16px }

/* display 를 지정한 요소는 hidden 속성을 무시한다 — 아래 둘 다 flex 라서
   숨겼다고 생각한 빈 카드가 화면에 남았다(2026-08-12). */
.artbar[hidden], .artempty[hidden]{ display:none !important }

/* ── 목록 상단: 지금 고른 그림 ────────────────────────
   어떤 그림으로 만들어지는지 상품을 열기 전에 보여준다. */
.artbar{
  display:flex; align-items:center; gap:12px;
  padding:12px 16px; margin:0 0 20px;
  background:var(--tgray50); border:0; border-radius:16px;
}
.artbar .thumb{
  flex:0 0 auto; width:48px; height:48px; border-radius:8px;
  background:#fff; overflow:hidden;
  display:flex; align-items:center; justify-content:center;
}
.artbar .thumb img{ width:100%; height:100%; object-fit:contain }
.artbar .tx{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:2px }
.artbar .tx b{ font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; color:#000;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.artbar .tx span{ font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:var(--tgray600) }
/* 「바꾸기」는 글자 버튼 — 히트 영역 44px 은 위아래 padding 12 로 만든다 */
.artbar .swap{
  flex:0 0 auto; padding:12px 0 12px 12px; border:0; background:none; border-radius:0;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; color:var(--tmint600);
}
.artbar .swap:active{ color:var(--tmint700) }

/* ── 그림을 아직 안 골랐을 때 (목업 §1②) ────────────────
   두 조각이다: ① 점선 「고르기」 줄 — 그림 바(.artbar)와 같은 자리·같은 치수, 테두리만 점선
              ② 다음 걸음 하나 — 화면 가운데 세 줄 + 민트 56px 버튼
   ⚠️ 목업은 ② 아래에 상품을 안 그린다. 우리는 그대로 보여준다 — 그림이 없어도 무엇을
      파는지는 봐야 하기 때문이다. 그래서 ② 의 높이를 화면 전체가 아니라 280px 로 죈다. */
.artempty{ display:flex; flex-direction:column; gap:20px; margin:0 0 20px }
.artempty .apick{
  display:flex; align-items:center; gap:12px;
  padding:12px; border:1px dashed var(--tgray300); border-radius:16px;
  text-decoration:none;
}
.artempty .apick .ath{
  flex:none; width:48px; height:48px; border-radius:8px; background:var(--tgray50);
  display:flex; align-items:center; justify-content:center; color:var(--tgray300);
}
.artempty .apick .ath svg{ width:22px; height:22px; display:block }
.artempty .apick .tx{ flex:1; min-width:0; display:flex; flex-direction:column }
.artempty .apick .tx b{ font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:700; color:#000 }
.artempty .apick .tx span{ font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:400; color:var(--tgray600) }
.artempty .apick i{ flex:none; font-style:normal;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; color:var(--tmint600) }
.artempty .anone{
  min-height:280px; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:12px; text-align:center; padding:0 20px;
}
.artempty .anone > b{ font-size:var(--fs-sec); line-height:var(--lh-sec); font-weight:700; color:#000 }
.artempty .anone > span{ font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:400; color:var(--tgray500); text-wrap:pretty }
.artempty .anonego{
  margin-top:4px; height:56px; padding:0 24px; border-radius:16px;
  background:var(--tmint600); color:#fff; text-decoration:none;
  display:flex; align-items:center;
  font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700;
}
.artempty .anonego:active{ background:var(--tmint700) }

/* ── 목록을 못 불러왔을 때 (목업 §1④) ──────────────────
   무슨 일이 났는지 + 다음에 뭘 하면 되는지, 두 줄. 56px 붉은 tint 원 + 아이콘. */
.lerr{
  min-height:420px; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:12px; text-align:center;
}
.lerr[hidden]{ display:none !important }
.lerr .ic{
  width:56px; height:56px; border-radius:9999px; background:var(--tred50);
  display:flex; align-items:center; justify-content:center; color:var(--tred500);
}
.lerr .ic svg{ width:28px; height:28px; display:block }
.lerr > b{ font-size:var(--fs-sec); line-height:var(--lh-sec); font-weight:700 }
.lerr > span{ font-size:var(--fs-body); line-height:var(--lh-body);
  color:var(--tgray500); font-weight:400; text-wrap:pretty }
.lerr button{
  margin-top:4px; height:48px; padding:0 20px; border-radius:16px;
  border:1px solid var(--tgray100); background:#fff; color:#000;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700;
}
.lerr button:active{ background:var(--tgray50) }

/* ── 목록을 기다리는 동안 (목업 §1③) ──────────────────
   실제 카드와 **같은 높이·radius** 의 회색 면. 「비어 있다」와 「아직 모른다」는 다르다.
   renderList() 가 #plist 를 통째로 덮으면 이 마크업은 사라진다. */
.lskel{ display:flex; flex-direction:column; gap:20px; animation:skelpulse 1.3s ease-in-out infinite }
.lskel .lsec{ display:flex; flex-direction:column; gap:12px }
.lskel .sb{ display:block; height:14px; border-radius:6px; background:var(--tgray50) }
.lskel .sim{ display:block; height:150px; border-radius:0; background:var(--tgray50) }
.lskel .sc{
  display:flex; flex-direction:column; gap:6px;
  border:1px solid var(--tgray100); border-radius:16px; overflow:hidden;
}
.lskel .sc .sb{ margin:0 12px }
.lskel .sc .sb:last-child{ margin-bottom:12px }

/* ── 장바구니: 모자란 금액을 채울 상품 추천 ──────────────
   「1,000원 더 담으면」만 말하고 무엇을 담을지는 안 알려줬다. */
/* 목업 §3② — 추천은 **목록 카드와 같은 모양**의 2열이다. 전에는 이모지 3칸이었는데
   DS 는 이모지를 금지하고, 무엇보다 「어떤 물건인지」가 안 보였다.
   첫 칸만 민트 테두리 + 민트 담기 버튼: 「이거 하나면 된다」를 하나만 가리킨다. */
.reco{
  margin-top:16px; padding:0; background:none; border:0;
  display:flex; flex-direction:column; gap:8px;
}
.reco .rhd{ display:flex; align-items:baseline; gap:6px }
.reco .rhd b{ font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; color:#000 }
.reco .rrow{ display:grid; grid-template-columns:1fr 1fr; gap:12px }
.reco .rcell{
  display:block; padding:0; text-align:left;
  border:1px solid var(--tgray100); border-radius:16px; overflow:hidden; background:#fff;
}
.reco .rcell.on{ border-color:var(--tmint600) }
.reco .rcell:active{ transform:scale(.98) }
.reco .rcell .im{ display:flex; align-items:center; justify-content:center;
  aspect-ratio:1; background:var(--tgray50); position:relative; overflow:hidden }
.reco .rcell .im img{ width:100%; height:100%; object-fit:cover }
.reco .rcell .im .pimg{ width:64%; height:64% }
.reco .rcell .im .pimg img{ width:100%; height:100%; object-fit:contain }
.reco .rcell .bd{ display:block; padding:10px 12px 12px }
.reco .rcell .nm{ display:block; font-size:var(--fs-body); line-height:var(--lh-body);
  font-weight:700; color:#000; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.reco .rcell .pr{ display:flex; align-items:baseline; gap:6px; flex-wrap:wrap; margin-top:6px }
.reco .rcell .pr b{ font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700 }
.reco .rcell .pr s{ font-size:var(--fs-cap); line-height:var(--lh-cap); color:var(--tgray600) }
.reco .rcell .pr .save{ display:block; flex-basis:100%; margin-top:-2px;
  font-size:var(--fs-cap); line-height:var(--lh-cap); font-style:normal; color:var(--tmint600) }
/* 「담기」는 카드 안 라벨이다 — 카드 전체가 눌리는 자리라 따로 버튼을 넣지 않는다 */
.reco .rcell .go{ display:block; margin-top:8px; height:36px; border-radius:12px;
  border:1px solid var(--tgray100);
  font-size:var(--fs-body); line-height:34px; font-weight:700; text-align:center; color:#000 }
.reco .rcell.on .go{ border-color:transparent; background:var(--tmint600); color:#fff; line-height:36px }

/* ── 기다리는 동안 (스켈레톤) ─────────────────────────
   「비어 있어요」와 「아직 모른다」는 다르다. 서버 응답 전에는 이걸 둔다. */
@keyframes skelpulse{ 0%,100%{opacity:.55} 50%{opacity:.9} }
.skel{ animation:skelpulse 1.3s ease-in-out infinite }
.skel .srow{
  display:flex; align-items:center; gap:12px;
  background:#fff; border:1px solid var(--tgray100); border-radius:16px;
  padding:20px; margin-bottom:8px;
}
.skel .sth{ width:64px; height:64px; border-radius:8px; background:var(--tgray50); flex:none }
.skel .sbd{ flex:1; display:flex; flex-direction:column; gap:8px }
.skel i{ display:block; height:12px; border-radius:6px; background:var(--tgray50) }
.skel .scard{
  background:#fff; border:1px solid var(--tgray100); border-radius:16px;
  padding:20px; margin-bottom:8px; display:flex; flex-direction:column; gap:8px;
}

/* 칼선을 기다리는 자리 — 실물 사진을 먼저 보여주면 「내가 산 게 저 사진인가」로 읽힌다.
   칼선이 도착하면 이 클래스가 빠지고, 못 그렸으면 실물 사진으로 되돌아온다. */
.im.waiting{ position:relative; overflow:hidden }
.im.waiting::after{
  content:""; position:absolute; inset:0;
  background:var(--chip);
  animation:skelpulse 1.3s ease-in-out infinite;
}

/* BottomNav 배경은 화면 전체 폭으로 깔고, 내부 콘텐츠만 앱 폭으로 묶는다. */
.tabs{
  left:0 !important;
  right:0 !important;
  width:auto !important;
  max-width:none !important;
  transform:none !important;
  box-sizing:border-box !important;
}
.tabs .in{
  width:100% !important;
  max-width:var(--shell-w) !important;
  margin:0 auto !important;
}

/* 모바일에서는 시트가 전체 화면처럼 보이지 않게 위쪽 여백을 남긴다. */
.sheet .sbox,
#optSheet .sbox,
#artSheet .sbox{
  max-height:min(80dvh, calc(100dvh - 72px)) !important;
}
@media (max-height:700px){
  .sheet .sbox,
  #optSheet .sbox,
  #artSheet .sbox{
    max-height:min(78dvh, calc(100dvh - 56px)) !important;
  }
}

/* 모든 상품에 같은 안내 세 줄 (2026-08-14). 사양 표 아래에 회색 작은 글씨로 둔다 —
   사는 데 필요한 정보가 아니라 사전 양해라 사양과 같은 크기면 두 덩어리가 경쟁한다.
   가운뎃점 목록으로 둬서 세 줄이 각각 읽힌다(문단으로 이으면 한 덩어리가 된다). */
.dcaution{margin:12px 0 0; padding:0; list-style:none;
  display:flex; flex-direction:column; gap:4px}
.dcaution li{position:relative; padding-left:10px;
  font-size:var(--fs-cap); line-height:var(--lh-cap);
  color:var(--tgray400); font-weight:400; text-wrap:pretty}
.dcaution li::before{content:"·"; position:absolute; left:2px}

/* ── 문의 안내 창 ─────────────────────────────────────────────────
   시트가 아니라 **가운데 창**이다 — 「네/아니오」 하나만 묻는 자리라 아래에서 올라올 필요가 없다.
   z 는 시트(56)보다 위 · DS 사다리에서 이 층은 창 몫이다. */
.mdl{position:fixed; inset:0; z-index:60; display:flex; align-items:center; justify-content:center;
  /* 백드롭은 검정 40% — `rgba(26,34,80,.45)`(남색)은 우리 팔레트에 없다 (2026-08-15 혜림님) */
  padding:20px; background:rgba(0,0,0,.4)}
.mdl[hidden]{display:none}
.mdl .mbox{width:100%; max-width:320px; background:#fff; border-radius:20px; padding:20px}
.mdl .mbox > b{display:block; font-size:var(--fs-sec); line-height:var(--lh-sec); font-weight:700; color:#000}
.mdl .mbox > p{margin:8px 0 0; font-size:var(--fs-body); line-height:var(--lh-body);
  color:var(--tgray500); font-weight:400; text-wrap:pretty}
.mdl .mbox > p b{font-weight:700; color:#000}
.mdl .mbtn{display:flex; gap:8px; margin-top:20px}
.mdl .mbtn button{flex:1; height:48px; border-radius:14px; font:inherit;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; cursor:pointer}
.mdl .mno{border:1.5px solid var(--line); background:#fff; color:#000}
.mdl .mgo{border:0; background:var(--tmint600); color:#fff}
.mdl .mbtn button:active{transform:scale(.98)}
/* 문의 아이콘 — 뒤로·장바구니와 같은 40px 칸 */
.top .ask{width:40px; height:40px; border:0; border-radius:12px; background:transparent; color:#000;
  display:none; align-items:center; justify-content:center}
.top .ask.on{display:flex}
.top .ask:active{background:var(--tgray50)}
.top .ask svg{width:24px; height:24px; display:block}

/* 「1개 무료 적용」 — 쿠폰이 걸린 장바구니 줄에만. 금액 바로 위에 둬서
   「이 금액에 이미 반영됐다」로 읽힌다 (2026-08-14). */
.citem .cfree{margin:2px 0 0; font-size:var(--fs-cap); line-height:var(--lh-cap);
  font-weight:700; color:var(--tmint700)}
/* 결제 금액 — 요약의 마지막 셈. 위 줄들보다 굵고 검다 */
.sumbox .sumrow.paid{margin-top:8px; padding-top:8px; border-top:1px solid var(--tgray100)}
.sumbox .sumrow.paid span{font-weight:700; color:#000}

/* 쿠폰 배너의 「담으러 가기」 — 배너 안 오른쪽. 배너가 두 줄이라 버튼은 아래로 내린다. */
.cpbar{position:relative}
.cpbar .cpgo{margin-top:10px; width:100%; height:44px; border:0; border-radius:12px;
  background:var(--tmint600); color:#fff; font:inherit;
  font-size:var(--fs-body); line-height:var(--lh-body); font-weight:700; cursor:pointer}
.cpbar .cpgo:active{transform:scale(.99)}

/* ── 활동 캐러셀 (2026-08-18 · 8-19 카드형으로) — 「실제로 만들어지고 팔리고 있어요」
   알약은 필터로 읽혀서(혜림님) 썸네일+두 줄 카드로 바꿨다 — 실시간 구매 모듈의 관례. ── */
/* 카테고리 제목(.pcatH)과 같은 치수 — 섹션 제목이 두 크기면 위계가 흔들린다 (8/19) */
.secH{ font-size:var(--fs-title); line-height:var(--lh-title); font-weight:700;
  color:var(--tblack,#111); margin:0 0 12px; }
.actbar{ margin:0 0 14px; }
.acttrack{ display:flex; gap:8px; overflow-x:auto; -webkit-overflow-scrolling:touch;
  scrollbar-width:none; padding:2px 2px 4px; }
.acttrack::-webkit-scrollbar{ display:none; }
.actcell{ flex:0 0 auto; display:flex; align-items:center; gap:10px; text-align:left;
  border:1px solid var(--tgray150,#eee); background:var(--card,#fff); border-radius:14px;
  padding:8px 14px 8px 8px; font:inherit; cursor:pointer; max-width:76vw; }
.actcell .im{ width:40px; height:40px; border-radius:10px; overflow:hidden; flex:0 0 40px;
  background:var(--tgray100,#f4f4f4); display:flex; align-items:center; justify-content:center;
  font-size:19px; }
.actcell .im img{ width:100%; height:100%; object-fit:cover; display:block; }
.actcell .tx{ display:flex; flex-direction:column; gap:1px; min-width:0; }
.actcell .tx b{ font-size:13px; color:var(--tblack,#111); font-weight:700;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:52vw; }
.actcell .tx i{ font-style:normal; font-size:11.5px; color:var(--tgray500,#999);
  white-space:nowrap; }
.actcell .tx i em{ font-style:normal; font-weight:800; color:var(--tmint,#12b489); }
.actcell.order{ border-color:var(--tmint,#1fc7a8); background:#f2fbf8; }
.actskel{ flex:0 0 auto; width:200px; height:56px; border-radius:14px;
  background:var(--tgray50); animation:skelpulse 1.3s ease-in-out infinite; }

/* ── 터치 히트 영역 확장 (2026-08-19) — 44px 미만 버튼만, 보이는 크기는 유지 ── */
#topBack, #askBtn, #cartBtn, #navLogo, .tabs button{ position:relative }
#topBack::after, #askBtn::after, #cartBtn::after, #navLogo::after, .tabs button::after{
  content:''; position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:max(100%, 44px); height:max(100%, 44px) }
