  :root{
    --bg:#f4f5f7; --panel:#ffffff; --line:#e6e8ec; --line2:#eef0f3;
    --text:#191919; --sub:#8a8f99; --accent:#3b82f6; --accent2:#ffe14d;
    --radius:12px; --shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);
    /* 진행 게이지 색 — 편집 패널의 게이지와 완주 페이지의 막대가 같은 값을 읽는다.
       색을 바꾸려면 여기만 고치면 된다.

       가장 옅은 색은 빈 레일에 두고, 채우는 색은 하늘색에서 푸른색으로 한 방향으로만
       짙어지게 한다 — 그래야 차오르는 것이 색으로도 읽힌다.
       얼음빛(--gauge-1)은 8%까지만 쓴다. 이 색을 앞쪽에 넓게 깔면 한두 칸 채웠을 때
       레일과 구분이 되지 않아 비어 있는 것처럼 보인다. 맨 앞의 옅은 결만 남기고
       곧바로 하늘색으로 넘겨서, 첫 칸부터 채워진 게 눈에 들어오게 했다 */
    --gauge-rail:#e6f4f4;
    --gauge-1:#bbebfb; --gauge-2:#6dd3f7; --gauge-3:#7ab4f9;
    --gauge-grad:linear-gradient(90deg,
      var(--gauge-1) 0%, var(--gauge-2) 8%, var(--gauge-3) 100%);
  }
  *{box-sizing:border-box}
  html,body{margin:0;height:100%}
  body{
    font-family:"Pretendard Variable",Pretendard,-apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo","Malgun Gothic","맑은 고딕",sans-serif;
    background:var(--bg); color:var(--text); font-size:14px; line-height:1.5;
    display:flex; flex-direction:column; height:100vh; overflow:hidden;
  }
  /* ---- top bar ----
     제목과 테마 내보내기를 양 끝으로 민다. 헤더에 남은 것은 이 둘뿐이라,
     가운데 정렬보다 양 끝 정렬이 "무엇을 하는 화면인가 / 다 만들면 무엇을 누르는가"를
     더 곧게 보여준다. 좌우 여백은 아래 패널(.panel-scroll)과 같은 값을 쓴다 */
  header.topbar{
    display:flex; align-items:center; justify-content:space-between; gap:10px;
    padding:12px 18px;
    background:var(--panel); border-bottom:1px solid var(--line); flex:0 0 auto;
  }
  /* 아주 좁은 기기(320px 등)에서는 제목까지 한 단계 줄여야 액션과 한 줄에 들어간다 */
  @media (max-width:360px){
    .editor .panel-subtitle{font-size:15px}
  }
  /* 타이포그래피 굵기는 세 단계만 사용한다 — 600 semibold(타이틀) / 500 medium(레이블) / 400 regular(본문).
     b·strong은 기본 700이므로 600으로 맞춘다. 미리보기(카톡 UI 모사) 영역은 이미 400·500·600만 쓴다 */
  b,strong{font-weight:600}
  /* 로고 그림. 높이로 크기를 정하고 폭은 비율대로 따라오게 둔다 —
     헤더 높이는 내보내기 버튼(37px)이 잡고 있어서, 그보다 크지 않으면 헤더가 자라지 않는다.
     좁은 화면에서 버튼을 밀어내려 하면 max-width에 걸려 그림이 대신 줄어든다 */
  .logo{min-width:0;display:flex;align-items:center}
  .logo img{display:block;height:36px;width:auto;max-width:100%;
    object-fit:contain;object-position:left center}
  /* 좁은 화면용 축소는 반드시 위 기본 규칙 뒤에 와야 한다 — 특정도가 같아서
     앞에 두면 순서에서 밀려 그대로 먹히지 않는다 */
  @media (max-width:430px){
    .logo img{height:30px}
  }
  .btn{border:1px solid var(--line);background:#fff;border-radius:9px;padding:8px 14px;
    font-size:13px;font-weight:500;cursor:pointer;color:var(--text);transition:.12s;white-space:nowrap}
  /* hover는 마우스가 있는 기기에서만 건다 — 손가락에는 hover가 없는데도 :hover를 그대로
     달아두면, iOS Safari가 첫 탭을 "hover 상태 확인"으로만 쓰고 실제 클릭은 두 번째
     탭에야 일어난다(.pick-wrap:hover에 적어둔 것과 같은 함정). 말풍선 편집 모달의
     "적용" 버튼이 첫 탭엔 반응 없다가 두 번째 탭에야 닫히던 게 정확히 이 증상이었다 */
  @media (hover:hover){
    .btn:hover{background:#f7f8fa}
    .btn.primary:hover{background:#000}
  }
  /* 보조 동작(의견·초기화)은 테두리 없이 — 주 동작인 내보내기만 형태로 도드라지게 한다 */
  .btn.ghost{border-color:transparent}
  .btn.small{padding:6px 10px;font-size:12px;border-radius:8px}
  .btn.primary{background:var(--text);color:#fff;border-color:var(--text)}
  .btn:disabled{opacity:.4;cursor:not-allowed}
  .btn.primary:disabled:hover{background:var(--text)}
  .btn.ghost{background:transparent}
  /* ---- 헤더 오른쪽 버튼 묶음 ---- */
  .header-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}
  .menu-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:9px;border:none;background:transparent;color:var(--text);cursor:pointer;padding:0;transition:background .15s;position:relative}
  @media(hover:hover){.menu-btn:hover{background:var(--line2)}}
  .menu-btn-reddot{position:absolute;top:6px;right:6px;width:6px;height:6px;border-radius:50%;background:#ff4757;border:1.5px solid var(--bg)}
  .menu-item-reddot{display:inline-block;width:6px;height:6px;border-radius:50%;background:#ff4757;margin-left:auto;flex-shrink:0}
  .hidden{display:none!important}
  /* ---- 사이드 메뉴 ---- */
  .side-menu-overlay{position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:300;opacity:0;pointer-events:none;transition:opacity .25s}
  .side-menu-overlay.open{opacity:1;pointer-events:auto}
  .side-menu{position:fixed;top:0;right:0;bottom:0;width:80%;max-width:400px;background:#fff;z-index:301;transform:translateX(100%);transition:transform .3s cubic-bezier(.4,0,.2,1);overflow-y:auto;padding:env(safe-area-inset-top,0) 0 env(safe-area-inset-bottom,0)}
  .side-menu.open{transform:translateX(0)}
  .side-menu-list{list-style:none;padding:20px 0;margin:0}
  .side-menu-item{display:flex;align-items:center;gap:14px;width:100%;padding:14px 24px;background:transparent;border:none;color:var(--text);font-size:17px;font-weight:500;cursor:pointer;text-align:left;line-height:1.3}
  @media(hover:hover){.side-menu-item:hover{background:var(--line2)}}
  .side-menu-item:active{background:var(--line2)}
  .side-menu-icon{flex-shrink:0;opacity:.75}
  /* 로딩 상태 — .loading을 붙이면 문구 앞에서 스피너가 돈다. 어느 버튼에나 쓸 수 있다.
     로딩 중에는 중복 클릭을 막으려 :disabled를 함께 거는데, 그 opacity:.4를 그대로 두면
     스피너까지 흐려져 도는 게 잘 안 보인다 — 뒤에 와서 값을 덮어쓴다 */
  .btn.loading{opacity:.7;cursor:progress}
  .btn.loading::before{content:"";display:inline-block;vertical-align:-2px;margin-right:7px;
    width:13px;height:13px;border-radius:50%;border:2px solid currentColor;
    border-top-color:transparent;animation:btn-spin .7s linear infinite}
  @keyframes btn-spin{to{transform:rotate(360deg)}}

  /* ---- layout ---- */
  main{flex:1;display:flex;flex-direction:row;min-height:0}
  /* 헤더의 "카카오톡 테마 메이커"(.logo)와 동일한 타이포그래피 */
  .panel-subtitle{font-size:20px;font-weight:600;color:var(--text);flex:0 0 auto;text-align:left;width:100%}
  /* 편집 패널 제목 줄 — 초기화 버튼을 같은 줄 오른쪽 끝에 붙인다.
     여백은 이 줄이 갖는다(제목의 margin-bottom을 걷어냄) */
  .panel-head{display:flex;align-items:center;gap:6px;margin-bottom:14px;flex:0 0 auto}
  /* .panel-subtitle의 기본값 width:100%·flex:0 0 auto를 그대로 두면 제목이 줄을 다 차지해
     버튼이 패널 밖으로 밀려난다 — 이 줄에서는 남는 만큼만 쓰고 좁아지면 줄어들게 한다 */
  .panel-head .panel-subtitle{margin-bottom:0;width:auto;flex:1 1 auto;min-width:0;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .panel-head .btn{flex:0 0 auto}
  /* 의견 보내기 · 초기화 — 둘 다 이 화면을 벗어나는 보조 동작이라 한 묶음으로 둔다.
     가운뎃점이 이미 둘을 갈라주므로 버튼 안쪽 여백을 줄여도 붙어 보이지 않는다 —
     좁은 화면에서 제목이 줄임표로 잘리지 않게 그만큼을 제목에 넘긴다 */
  .panel-actions{display:flex;align-items:center;gap:1px;flex:0 0 auto}
  .panel-actions .btn{padding-left:8px;padding-right:8px}
  .dot-sep{color:#c9ced8;font-size:12px;user-select:none}
  .preview-wrap .panel-subtitle{margin-bottom:4px}
  /* 패널 타이틀 아래 설명글 — 타이틀과 한 덩어리로 붙이고 아래 여백만 타이틀 몫으로 남긴다 */
  .panel-desc{font-size:13px;font-weight:400;color:var(--sub);line-height:1.5;
    flex:0 0 auto;text-align:left;width:100%;margin-bottom:14px}
  .editor{flex:0 1 400px;min-width:0;background:var(--panel);border-left:1px solid var(--line);
    display:flex;flex-direction:column;min-height:0}
  .preview-wrap{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;
    justify-content:flex-start;padding:22px;overflow:auto;position:relative}

  /* 커스텀 스크롤바 — 스크롤 발생하는 모든 영역(좌측 패널, 미리보기 여백, 채팅 말풍선, 내보내기 모달) 공통 */
  .panel-scroll, .preview-wrap, .croom .cbody, .modal{
    scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.18) transparent}
  .panel-scroll::-webkit-scrollbar, .preview-wrap::-webkit-scrollbar,
  .croom .cbody::-webkit-scrollbar, .modal::-webkit-scrollbar{width:4px;height:4px}
  .panel-scroll::-webkit-scrollbar-track, .preview-wrap::-webkit-scrollbar-track,
  .croom .cbody::-webkit-scrollbar-track, .modal::-webkit-scrollbar-track{background:transparent}
  .panel-scroll::-webkit-scrollbar-thumb, .preview-wrap::-webkit-scrollbar-thumb,
  .croom .cbody::-webkit-scrollbar-thumb, .modal::-webkit-scrollbar-thumb{
    background:rgba(0,0,0,.18);border-radius:999px}
  .panel-scroll::-webkit-scrollbar-thumb:hover, .preview-wrap::-webkit-scrollbar-thumb:hover,
  .croom .cbody::-webkit-scrollbar-thumb:hover, .modal::-webkit-scrollbar-thumb:hover{
    background:rgba(0,0,0,.32)}

  /* ---- editor tabs (legacy) ---- */
  .tabs{display:flex;padding:8px 10px 0;gap:2px;border-bottom:1px solid var(--line);flex:0 0 auto}
  .tabs button{flex:1;border:0;background:transparent;padding:11px 6px;font-size:13px;font-weight:500;
    color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;border-radius:8px 8px 0 0}
  .tabs button.active{color:var(--text);border-bottom-color:var(--text)}
  @media (hover:hover){ .tabs button:hover{color:var(--text)} }
  .panel-scroll{overflow-y:auto;padding:16px 18px 60px;flex:1;min-height:0}
  .tabpage{display:none}
  .tabpage.active{display:block}

  h3.section{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--sub);
    text-transform:uppercase;margin:22px 0 10px;display:flex;align-items:center;gap:7px}
  h3.section:first-child{margin-top:2px}
  h3.section .ln{flex:1;height:1px;background:var(--line2)}

  .field{margin-bottom:13px}
  /* flex+align-items:center로 점(.req)을 라벨 텍스트의 가로선 기준 중앙에 확실히 맞춘다
     (vertical-align:middle은 폰트 베이스라인 특성상 미세하게 어긋나 보일 수 있음) */
  .field label{display:flex;align-items:center;gap:4px;font-size:14px;font-weight:500;color:#555;margin-bottom:5px}
  /* 라벨 안 힌트는 라벨의 크기·굵기를 상속받으므로 12px/400을 명시한다 */
  .field label .hint{font-size:12px;color:var(--sub);font-weight:400}
  .field label .req{display:inline-block;width:4px;height:4px;border-radius:50%;
    background:#e0463a;flex:0 0 auto}
  /* 입력칸 글자는 16px 아래로 내리지 않는다 — iOS 사파리가 그보다 작은 입력칸에 포커스하면
     화면을 확대해버리고, 그러면 모달 아래쪽 버튼이 화면 밖으로 밀려나 누를 수 없게 된다 */
  .field input[type=text]{width:100%;border:1px solid var(--line);border-radius:8px;padding:9px 11px;
    font-size:16px;font-family:inherit;color:var(--text)}
  .field input[type=text]:focus{outline:none;border-color:var(--accent)}
  /* 인풋 하단 보조 설명 — 라벨 옆 .hint와 같은 12px 톤, 위치만 필드 아래 */
  .field-hint{font-size:12px;color:var(--sub);line-height:1.5;margin-top:5px}
  /* 의견 입력창 — 폰트는 body를 따라가야 한다. textarea는 기본값이 monospace라 지정하지 않으면 혼자 다른 글꼴이 된다 */
  .field textarea{width:100%;border:1px solid var(--line);border-radius:8px;padding:9px 11px;
    font-size:16px;font-family:inherit;line-height:1.6;color:var(--text);resize:vertical;min-height:120px}
  .field textarea:focus{outline:none;border-color:var(--accent)}
  /* 허니팟 — display:none은 자동 스크립트가 건너뛰는 경우가 있어 화면 밖으로 밀어낸다.
     사람 눈과 탭 이동에서만 사라지고, 스크립트에는 평범한 입력칸으로 보인다 */
  .hp-field{position:absolute;left:-9999px;width:1px;height:1px;opacity:0;pointer-events:none}

  /* 목록 한 줄 — 색상 행(.crow)도 같은 골격을 쓴다(class="islot crow").
     카드(테두리+배경+안쪽 여백)를 걷어내고 아래 선만 남긴다. 한 줄에 12px씩 쓰던
     좌우 안쪽 여백이 사라져 이름이 접히지 않고, 화면에 들어오는 항목 수가 늘어난다 */
  .islot{display:flex;gap:10px;align-items:center;padding:9px 0;
    border:0;border-bottom:1px solid var(--line2);border-radius:0;margin:0;background:none}
  .islot:last-child{border-bottom:none}
  .islot .thumb{width:32px;height:32px;flex:0 0 32px;border-radius:8px;border:1px solid rgba(0,0,0,.07);
    background:#f2f3f5 center/cover no-repeat;display:grid;place-items:center;color:#b9bec7;font-size:16px;overflow:hidden}
  .islot .thumb.swatch{border:1px solid rgba(0,0,0,.07)}
  .islot .thumb.has{border:1px solid rgba(0,0,0,.07)}
  /* 테마 리스트 아이콘(내보내기 모달) — 라운드는 메인 패널과 동일, 박스 하나만 노출(설명 텍스트 없이)
     + 호버 시 업로드 아이콘 오버레이 */
  #fld_icon .thumb{position:relative;overflow:hidden;width:52px;height:52px;flex:0 0 52px;font-size:22px}
  .ico-tile-overlay{position:absolute;inset:0;width:100%;height:100%;
    background:none;border:none;padding:0;margin:0;cursor:pointer;opacity:0}
  .islot .meta{flex:1;min-width:0}
  /* 항목 이름은 목록에서 눈으로 훑으며 찾는 글자라, 그룹 머리글(13px)보다 한 단계 크게 둔다 */
  .islot .meta .nm{font-size:14px;font-weight:500}
  /* "이미지 올릴 시" 글자 대신 아이콘으로 짧게 — .ico-wrap이 svg를 감싸므로
     줄바꿈 없이 나란히 두려면 행 자체를 flex로 둔다 */
  .islot .meta .sz{font-size:12px;color:var(--sub);font-weight:400;
    display:flex;align-items:center;gap:4px}
  .islot .meta .sz .ico-wrap{flex:0 0 auto;color:var(--sub);display:flex;align-items:center}
  .islot .meta .sz .ico-wrap svg{display:block}
  .islot .acts{display:flex;flex-direction:row;align-items:center;gap:2px}
  .mini{font-size:11px;border:1px solid var(--line);background:#fff;border-radius:6px;padding:4px 8px;
    cursor:pointer;font-weight:500;white-space:nowrap}
  @media (hover:hover){ .mini:hover{background:#f2f3f5} }
  /* ghost 아이콘 버튼 — 업로드·편집·모달 닫기 공통. 배경·테두리 없이 아이콘만.
     본문 검정(#191919)은 목록에서 아이콘만 튀어 보였고, 뮤트톤(var(--sub))은 비활성으로
     읽혔다. 그 사이 톤을 쓰고 호버에서 진해지게 한다 */
  .icon-btn{width:40px;height:40px;flex:0 0 40px;border:none;background:transparent;border-radius:8px;
    display:flex;align-items:center;justify-content:center;cursor:pointer;color:#565c66;padding:0}
  /* 편집·닫기·업로드 등 앱 전체 아이콘 버튼이 이 클래스를 쓴다 — hover:hover로 안 감싸면
     터치 기기에서 전부 첫 탭엔 안 눌리고 두 번째 탭에야 눌리는 버튼이 된다 */
  @media (hover:hover){ .icon-btn:hover{background:#f2f3f5;color:var(--text)} }
  .icon-btn .ico-wrap{width:20px;height:20px}

  .crow .meta .dc{font-size:12px;color:var(--sub);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

  /* 사진과 색상 사이의 세로선 — 둘은 같은 자리를 두고 다투는 수단이라, 하나를 고르면
     다른 하나가 지워진다. 그 배타 관계를 선 하나로 보인다.
     말풍선의 올리기·편집은 서로 다른 동작이라 선을 두지 않는다 */
  .act-div{width:1px;height:18px;background:#c9ced8;flex:0 0 auto;margin:0 1px}
  /* 실제 색상 선택기는 버튼이 대신 열어준다 — 눈에는 보이지 않아야 한다.
     다만 브라우저가 네이티브 피커를 input 위치에 붙여서 띄우므로, 아무 데나 두면
     미리보기 쪽을 덮는다. 팔레트 버튼 바로 아래·오른쪽 끝에 붙여 패널 안쪽으로 열리게 한다.
     (모바일은 위치와 무관하게 하단 시트로 뜬다) */
  .pick-wrap{position:relative;display:inline-flex;flex:0 0 auto}
  /* 투명한 input이 팔레트 버튼을 그대로 덮는다 — 눌리는 것은 버튼이 아니라 이 input이다.
     예전처럼 1px로 숨겨두고 JS(showPicker)로 열면 iOS에서 피커가 뜨지 않는다.
     WebKit은 피커를 input의 상자에 붙여 띄우는데, 1px·opacity:0에는 붙일 자리가 없다.
     버튼과 같은 자리·같은 크기로 겹쳐두면 붙일 상자가 생기고, 탭이 곧장 닿아
     제스처 판정도 거칠 것이 없다. 데스크톱에서 피커가 열리는 위치도 전과 거의 같다 */
  .pick-wrap .hidden-picker{position:absolute;inset:0;width:100%;height:100%;
    opacity:0;border:0;padding:0;margin:0;cursor:pointer;
    -webkit-appearance:none;appearance:none;background:none}
  /* 눌리는 대상이 input으로 옮겨가면서 버튼의 :hover·:focus가 더는 걸리지 않는다 —
     감싼 쪽에서 받아 버튼 모양에 그대로 돌려준다.
     hover는 마우스가 있는 기기에서만 건다 — 손가락에는 hover가 없는데도 :hover를 그대로
     달아두면, iOS Safari가 첫 탭을 "hover 상태 확인"으로만 쓰고 실제로 피커를 여는 동작은
     두 번째 탭에야 일어난다(위 .ico-tile-overlay에 적어둔 것과 같은 함정).
     여기 걸려서 "버벅인다"·"눌리는 것 같은데 안 열린다"는 느낌이 났다 */
  @media (hover:hover){
    .pick-wrap:hover .icon-btn{background:#f2f3f5;color:var(--text)}
  }
  .pick-wrap:focus-within .icon-btn{background:#f2f3f5;color:var(--text);
    outline:2px solid var(--accent);outline-offset:-2px}
  /* 탭 순간 기본으로 뜨는 회색 번쩍임도 걷어낸다 — 버튼은 그대로인데 그 위에 잠깐
     다른 색이 스치고 지나가는 것도 "버벅인다"는 인상을 보탠다 */
  .pick-wrap .hidden-picker{-webkit-tap-highlight-color:transparent}
  /* 섹션 제목 — 본문보다 한 단계 낮춰 목록 항목 이름과 구분되게 한다.
     위 여백을 넉넉히 줘서 섹션 사이가 눈으로 끊긴다 */
  .grouphdr{font-size:13px;font-weight:600;margin:30px 0 8px;color:var(--sub)}
  .grouphdr:first-child{margin-top:2px}
  /* 그룹 헤더 아래 설명글 — 줄바꿈은 desc 문자열의 \n을 그대로 살린다 */
  .grpdesc{font-size:12px;font-weight:400;color:var(--sub);line-height:1.6;
    margin:-3px 0 10px;white-space:pre-line}

  /* 데스크톱에서는 시트 손잡이가 쓰이지 않는다 */
  .sheet-handle{display:none}
  /* 모바일에서만 쓰는 래퍼 — 데스크톱에서는 없는 것처럼 취급한다 */
  /* 모바일에서만 쓰는 래퍼 — 데스크톱에서는 없는 것처럼 취급한다 */
  .phone-fit{display:contents}

  /* ---- preview ---- */
  /* 폭이 모자라면 목업을 아래로 흘린다. 나란히 둔 채 줄여도 봤지만, 셋이 다 들어가는
     배율에서는 화면 안이 안 보여 비교가 되지 않았다 — 크게 보이는 쪽을 택한다 */
  .preview-row{display:flex;flex-wrap:wrap;gap:28px;justify-content:center;align-items:flex-start}
  .preview-col{display:flex;flex-direction:column;align-items:center}
  /* 화면 이름 뱃지 — .preview-col이 이미 flex column + align-items:center라
     아래 목업과 같은 세로선에 저절로 중앙 정렬된다. 폭을 목업에 맞추는 계산이 따로 없다 */
  .preview-badge{font-size:12px;font-weight:600;color:var(--sub);line-height:1;
    background:#f1f3f5;border-radius:999px;padding:4px 10px;margin-bottom:9px;
    white-space:nowrap;flex:0 0 auto}

  /* 미리보기 화면 크기 360×640. 내부 요소(아이콘·폰트·아바타 등)는 고정 px 그대로 두고
     max-width로 좁아질 때 폭만 자동으로 줄어든다 */
  .phone{width:360px;max-width:100%;height:720px;flex:0 1 auto;position:relative}
  .scr{width:100%;height:100%;border-radius:16px;overflow:hidden;position:relative;background:#fff;
    display:flex;flex-direction:column;font-size:12px}
  .scr *{box-sizing:border-box}
  .ico-wrap svg{width:100%;height:100%;display:block}

  /* the layers */
  .kbg{position:absolute;inset:0;background-position:top center;background-size:cover;background-repeat:no-repeat;z-index:0}
  .klayer{position:relative;z-index:1;display:flex;flex-direction:column;height:100%}


  /* tabbar — Figma 78:622 (row 50 + ios-safe-area 34, 세이프에어리어는 미리보기에서 제외) */
  .ktab{height:50px;flex:0 0 50px;position:relative;background-position:top center;background-size:cover;
    display:flex;align-items:stretch}
  .ktab .icowrap{flex:1;min-width:0;display:flex;align-items:center;justify-content:center;padding:4px}
  .ktab .ico{width:40px;height:40px;flex:0 0 40px;background-size:contain;background-repeat:no-repeat;
    background-position:center;display:grid;place-items:center;font-size:26px}

  /* ---- 친구탭 (Figma 68:455) ---- */
  .topnav{display:flex;align-items:center;justify-content:space-between;height:56px;flex:0 0 56px;padding:4px 12px 4px 16px}
  .topnav .profile-area{display:flex;align-items:center;gap:10px;flex:1;min-width:0}
  .topnav .profile-area .av{width:32px;height:32px;border-radius:12px;background-size:cover;background-position:center;background-repeat:no-repeat;flex:0 0 32px;border:0.5px solid rgba(0,0,0,.07)}
  .topnav .profile-area .nm{font-size:24px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .topnav .navicons{display:flex;align-items:center;gap:4px;flex:0 0 auto}
  .topnav .navicons .ibtn{width:40px;height:40px;display:flex;align-items:center;justify-content:center;flex:0 0 40px}
  .topnav .navicons .ibtn .ico-wrap{width:24px;height:24px}

  .pilltabs{display:flex;align-items:center;gap:8px;padding:8px 16px;flex:0 0 auto}
  .pilltabs .pill{display:inline-flex;align-items:center;justify-content:center;height:40px;
    padding:0 18px;border-radius:999px;font-size:15px;font-weight:600;white-space:nowrap;line-height:1}
  /* border 대신 inset box-shadow — 레이아웃 크기에 영향을 주지 않아 .sel 칩과 높이가 완전히 같아짐 */
  .pilltabs .pill.unsel{box-shadow:inset 0 0 0 1px #d2d6dc;background:transparent}

  .updsec{padding:16px 16px 0;display:flex;flex-direction:column;gap:16px;flex:0 0 auto}
  .updsec>.lbl{font-size:14px}
  /* 오른쪽은 updsec의 16px 패딩을 상쇄해 화면 끝까지 채운다 — 캐러셀처럼 마지막 아이템이
     여백 없이 가장자리에서 바로 끊기게(스크롤 기능은 없음, 시각적 형태만) */
  /* padding-top: AD 뱃지가 아바타 위로 -2px 튀어나오는데, overflow:hidden(우측 잘림 처리용)이
     상단도 같이 잘라서 뱃지 위쪽이 살짝 잘려 보였다 — 여유 공간을 줘서 방지 */
  .profiles-row{display:flex;gap:4px;overflow:hidden;margin-right:-16px;padding-top:3px;margin-top:-3px}
  .profile-item{display:flex;flex-direction:column;align-items:center;gap:4px;width:64px;flex:0 0 64px}
  .profile-item .avwrap{position:relative;width:50px;height:50px}
  .profile-item .avimg{width:50px;height:50px;border-radius:20px;background-size:cover;background-position:center;background-repeat:no-repeat;border:0.5px solid rgba(0,0,0,.07)}
  .profile-item .reddot{position:absolute;top:0;left:0;width:4px;height:4px;border-radius:50%;background:#ff4757}
  .profile-item .adbadge{position:absolute;top:-2px;right:-2px;background:#fff;border:1px solid #d2d6dc;border-radius:999px;padding:2px 4px;font-size:9px;font-weight:600;line-height:1;white-space:nowrap}
  .profile-item .editbadge{position:absolute;right:-4px;top:32px;width:18px;height:18px;border-radius:999px;display:flex;align-items:center;justify-content:center}
  .profile-item .pname{font-size:12px;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

  .fr-divider{height:1px;flex:0 0 1px}

  .friendlist{padding:16px 16px 0;display:flex;flex-direction:column;gap:16px;flex:1;min-height:0}
  .friendlist-head{display:flex;align-items:flex-start;flex:0 0 auto}
  .friendlist-head .cnt{font-size:14px;flex:1;min-width:0}
  .sorttoggle{display:flex;align-items:center;gap:4px;font-size:12px;white-space:nowrap;flex:0 0 auto}
  /* 구분자와 비활성 정렬 항목은 사용자 지정색을 따르지 않는 고정색 — 잠금화면 .pass .psub와 동일 */
  .sorttoggle .sep,.sorttoggle .inactive{color:#8391a6}
  .friendrows{display:flex;flex-direction:column;overflow:hidden;flex:1;min-height:0}
  .friendrow{display:flex;align-items:center;gap:12px;padding:8px 0;flex:0 0 auto}
  .friendrow .avimg{width:42px;height:42px;border-radius:16px;background-size:cover;background-position:center;background-repeat:no-repeat;flex:0 0 42px;border:0.5px solid rgba(0,0,0,.07)}
  .friendrow .ct{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;gap:4px}
  .friendrow .nm{font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .friendrow .desc{font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

  /* chatroom (Figma 68:457) */
  /* Figma 70:198 — p-16 + 콘텐츠 48px(아이콘셀 40 + py-4) = 높이 80px */
  .chatheader{display:flex;align-items:center;justify-content:space-between;flex:0 0 auto;padding:16px}
  .chatheader .backpill{background:#fff;border-radius:100px;display:flex;align-items:center;padding:4px 16px 4px 0;flex:0 0 auto}
  .chatheader .ibtn{width:40px;height:40px;flex:0 0 40px;display:flex;align-items:center;justify-content:center}
  .chatheader .ico-wrap{width:24px;height:24px;color:#383838}
  .chatheader .backpill span{font-size:18px;font-weight:500;color:#383838;line-height:1.5}
  .chatheader .title{font-size:16px;font-weight:600;color:#383838;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .chatheader .rightpill{background:#fff;border-radius:100px;display:flex;align-items:center;gap:4px;padding:4px;flex:0 0 auto}

  .croom{flex:1;display:flex;flex-direction:column;overflow:hidden;min-height:0}
  .croom .cbody{flex:1;padding:16px 2px 16px 16px;display:flex;flex-direction:column;gap:16px;
    overflow-y:auto;overflow-x:hidden;min-height:0}
  .msg{display:flex;gap:8px;max-width:100%}
  .msg .who{width:34px;height:34px;flex:0 0 34px;border-radius:13px;background-size:cover;background-position:center;background-repeat:no-repeat;border:0.5px solid rgba(0,0,0,.07)}
  /* 아바타 라운드 — iOS는 원호(border-radius)가 아니라 초타원 곡선을 쓴다.
     반경은 50%로 두고 곡률만 조절한다: superellipse(1)=완전 원형, (2)=squircle, 값이 클수록 사각형에 가까움.
     1.3은 원형과 사각형 사이에서 원형 쪽에 가까운, 카톡 아바타 느낌의 값이다.
     corner-shape 미지원 브라우저(Safari·Firefox 등)는 위 규칙의 px 원호 값으로 그대로 폴백된다 */
  @supports (corner-shape: squircle){
    .topnav .profile-area .av,
    .profile-item .avimg,
    .friendrow .avimg,
    .msg .who{border-radius:50%;corner-shape:superellipse(1.3)}
  }
  /* who를 <a>로 감쌀 때 flex 자식 역할을 앵커가 이어받는다 */
  .msg .who-link{display:block;flex:0 0 34px;align-self:flex-start}
  .avimg-link{display:block}
  .msg .stack{display:flex;flex-direction:column;gap:10px;min-width:0}
  .msg .sender{font-size:12px;font-weight:500;color:#383838}
  .bline{display:flex;gap:6px;align-items:flex-end;max-width:100%}
  .msg.send .bline{flex-direction:row-reverse}
  .bline .meta{display:flex;flex-direction:column;justify-content:center;font-size:11px;line-height:1.35;
    white-space:nowrap;flex:0 0 auto}
  .msg.recv .bline .meta{align-items:flex-start}
  .msg.send .bline .meta{align-items:flex-end}
  .bline .meta .tm{color:#5e5e5e}
  .bubble{padding:12px;font-size:14px;border-radius:16px;line-height:1.5;word-break:break-word;
    background-size:100% 100%;position:relative;display:inline-block;max-width:100%}
  .msg.recv{align-self:flex-start}
  .msg.send{align-self:flex-end;flex-direction:row-reverse}
  .msg.send .stack{align-items:flex-end}
  /* 나인패치 배경 레이어 — 인셋과 독립적으로 말풍선 전체를 덮는다 */
  .nbg{position:absolute;left:0;top:0;right:0;bottom:0;border-style:solid;border-color:transparent;
    pointer-events:none;z-index:0}
  .bubble>.ntxt,.np-box>.ntxt{position:relative;z-index:1}

  /* Figma 96:467 — p-16, 입력바는 w-full / h-48 / p-12 */
  .inputbar{flex:0 0 auto;padding:0 16px 16px;display:flex;flex-direction:column;align-items:center}
  .inputbar .bar{background:#fff;border-radius:999px;display:flex;align-items:center;gap:12px;
    height:48px;padding:12px;overflow:hidden;width:100%}
  .inputbar .plus{width:32px;height:32px;flex:0 0 32px;border-radius:20px;display:flex;align-items:center;justify-content:center}
  .inputbar .tf{flex:1;font-size:14px;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .inputbar .send{width:32px;height:32px;flex:0 0 32px;border-radius:20px;display:flex;align-items:center;justify-content:center;color:#fff}
  .inputbar .ico-wrap{width:24px;height:24px}

  /* passcode (Figma 68:461) */
  /* 잠금화면 배경 이미지가 들어가는 영역 — 키패드를 뺀 위쪽이 곧 이미지 판이다.
     .kbg처럼 화면 전체를 덮지 않으므로 배율이 이 영역 기준으로 잡힌다 */
  .pass{flex:1;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:26px;
    background-position:center;background-size:cover;background-repeat:no-repeat}
  .pass .phead{display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center}
  .pass .ptit{font-size:24px;font-weight:600}
  .pass .psub{font-size:16px;color:#8391a6}
  .pass .dots{display:flex;gap:4px;align-items:center;justify-content:center}
  .pass .dots .d{width:44px;height:44px;background-size:cover;background-position:center;
    display:flex;align-items:center;justify-content:center}
  .pass .dots .d .ico-wrap{width:44px;height:44px}
  .keypad-wrap{flex:0 0 auto}
  .keypad{width:100%;padding:16px;display:grid;grid-template-columns:repeat(3,1fr);grid-auto-rows:51px;gap:16px}
  .keypad .k{display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:400;
    border-radius:12px;position:relative}
  .keypad .k.txt{font-size:16px}
  .keypad .k .ico-wrap{width:24px;height:24px}
  /* 숫자 눌림(pressed) 그래픽 — Figma 스펙: 62×62 고정 크기로 셀 중앙에 겹침, 키패드보다 위 레이어.
     opacity:.8은 카톡 시스템이 항상 적용하는 20% 추가 보정(이미지 자체는 건드리지 않음, 미리보기 표현용) */
  .keypad .k-pressed{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
    width:62px;height:62px;z-index:2;pointer-events:none}
  .keypad .k-pressed img{width:100%;height:100%;object-fit:cover;display:block;opacity:.8}

  .emptyprev{color:#b9bec7;font-size:13px;text-align:center;margin-top:40px}
  input[type=file]{display:none}
  .flash{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--text);color:#fff;
    padding:11px 20px;border-radius:10px;font-size:13px;font-weight:500;opacity:0;pointer-events:none;
    transition:opacity .25s;z-index:100}
  .flash.show{opacity:1}

  /* ---- modal ----
     헤더·풋터·몸통을 세로 flex로 쌓고 몸통(.modal-body)에만 스크롤을 준다. 헤더·풋터는
     flex:0 0 auto라 몸통이 늘어나든 줄어들든 자기 크기를 지키고, 그 결과 스크롤에서
     떨어져 나와 늘 화면에 남는다 — 데스크톱·모바일 모두 같은 구조라 규칙이 하나로 끝난다 */
  .modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.42);display:none;
    align-items:center;justify-content:center;z-index:90;padding:20px}
  .modal-overlay.show{display:flex}
  .modal{position:relative;background:#fff;border-radius:16px;width:420px;max-width:100%;
    max-height:90vh;box-shadow:0 20px 60px rgba(0,0,0,.3);
    display:flex;flex-direction:column;overflow:hidden}
  .modal-head{flex:0 0 auto;display:flex;align-items:center;gap:12px;padding:20px 10px 14px 20px}
  /* 닫기(x) — 이제 절대배치가 아니라 헤더의 평범한 플렉스 항목이다. 마크업에서도
     제목을 먼저, 닫기를 나중에 두어서 화면에 보이는 순서(오른쪽 끝)와 읽어주는
     순서가 어긋나지 않는다 */
  .modal-close{flex:0 0 auto}
  .modal-title{font-size:17px;font-weight:600;flex:1 1 auto;min-width:0;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .modal-sub{font-size:12px;color:var(--sub);margin-top:2px;line-height:1.5}
  /* 제목+보조 문구 묶음 */
  .modal-heading{flex:1 1 auto;min-width:0}
  .modal-body{flex:1;min-height:0;overflow-y:auto;padding:0 20px 20px}
  /* 안내 이미지 — 테두리·라운드는 이미지 슬롯(.islot)과 같은 값을 쓴다 */
  .guide-shot{display:block;width:100%;height:auto;margin-bottom:18px;
    border:1px solid var(--line2);border-radius:10px}
  /* 의견 모달의 그림 — 색이 가장자리까지 차 있어서 안내 이미지(.guide-shot)처럼
     테두리를 두르거나 모서리를 깎지 않는다. 그림을 그대로 편다.
     위 여백은 앞 .field의 13px을 그대로 받는다 */
  .fb-notice{font-size:12.5px;color:var(--text2);line-height:1.55;margin-top:14px}
  .fb-notice a{color:var(--text2);text-decoration:underline;text-underline-offset:2px}
  .update-entry{padding:20px 0}
  .update-date{display:block;font-size:12px;color:var(--text2);margin-bottom:6px;font-variant-numeric:tabular-nums}
  .update-title{font-size:15px;font-weight:600;margin:0 0 8px;line-height:1.4}
  .update-body{font-size:14px;color:var(--text2);line-height:1.65}
  .update-body p{margin:0 0 6px}
  .update-body p:last-child{margin-bottom:0}
  .update-body ol{margin:6px 0 0;padding-left:18px}
  .update-body li{margin-bottom:5px}
  .update-body li:last-child{margin-bottom:0}
  .update-para+.update-para{margin-top:20px}
  .update-img{display:block;width:100%;height:auto;border-radius:10px;margin:10px 0 8px}
  .update-divider{border:none;border-top:1px solid var(--line2);margin:0}
  .history-empty{font-size:14px;color:var(--text2);line-height:1.6;padding:8px 0 4px}
  .history-item{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;padding:14px 0;background:transparent;border:none;border-bottom:1px solid var(--line2);cursor:pointer;text-align:left;color:var(--text)}
  .history-item:last-child{border-bottom:none}
  @media(hover:hover){.history-item:hover .history-name{text-decoration:underline;text-underline-offset:2px}}
  .history-name{font-size:15px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .history-date{font-size:13px;color:var(--text2);flex-shrink:0}
  /* 자동 발급되는 기계값(고유 아이디)을 사람이 정하는 값들과 갈라주는 선.
     flex-shrink:0 — flex 세로 배치(.nine-modal .modal-body 등) 안에서 모달 내용이
     보이는 영역보다 길어지면, 내용 없는 빈 div라 최소 높이가 0인 이 구분선이 다른
     요소보다 먼저 0으로 눌려 사라졌다. 구분선은 절대 눌리면 안 되는 요소라 고정한다 */
  .field-sep{height:1px;background:var(--line);margin:18px 0;flex-shrink:0}
  .radio-group{display:flex;flex-direction:column;gap:10px;margin-top:6px}
  .radio-option{display:flex;align-items:center;gap:8px;cursor:pointer;font-size:14px;color:var(--text)}
  .radio-option input[type="radio"]{width:16px;height:16px;accent-color:var(--text);cursor:pointer;flex-shrink:0}
  .modal-actions{flex:0 0 auto;display:flex;gap:8px;padding:16px 20px 20px}
  /* 모달의 확인 버튼은 그 화면에서 유일한 다음 행동이라 폭을 다 쓴다 */
  .modal-actions .btn{flex:1}
  .modal-error{font-size:12.5px;color:#b3261e;background:#fdecea;border:1px solid #f5c2bd;
    border-radius:9px;padding:9px 12px;margin-bottom:14px;line-height:1.5}
  .field.error label{color:#b3261e}
  .field.error input[type=text]{border-color:#e0463a;background:#fff7f6}
  .field.error .islot{border:1.5px solid #e0463a;border-radius:10px}

  /* 말풍선 만들기 Tip 시트 — 데스크톱은 다른 모달과 똑같이 가운데 뜨는 카드다(.modal-overlay/
     .modal 그대로, 추가 CSS 없음). 모바일에서만 바텀시트 모양으로 바뀐다 — 아래
     @media (max-width:700px) 블록의 .tip-sheet 규칙 참고 */

  /* ================= 진행 게이지 =================
     편집 패널에서 값을 하나 바꿀 때마다 한 칸씩 찬다. 같은 항목을 몇 번 만지든 한 칸이고,
     기본값으로 되돌리면 그 칸은 다시 빠진다 — 게이지가 곧 "기본 테마에서 얼마나
     멀어졌는가"를 뜻해야 내보내기 화면의 칭호가 정직해진다.
     이 화면에서 유일하게 색을 쓰는 자리다. 나머지가 흑백에 가까운 덕에
     여기만 따뜻하게 두어도 요란하지 않고, 오히려 "재미 담당"이라는 게 드러난다 */
  #gauge{display:none}
  .section-nav{flex:0 0 auto;display:flex;align-items:center;gap:6px;
    padding:10px 18px;border-bottom:1px solid var(--line);background:var(--panel)}
  .section-chip{font-size:13px;font-weight:500;padding:5px 13px;border-radius:100px;
    border:1.5px solid var(--line2);background:transparent;color:var(--sub);cursor:pointer;
    transition:background .15s,color .15s}
  @media(hover:hover){.section-chip:hover{background:var(--line2);color:var(--text)}}
  .gauge{position:relative;flex:0 0 auto;display:flex;align-items:center;gap:10px;
    padding:11px 18px;border-bottom:1px solid var(--line);background:var(--panel)}
  .gauge-track{flex:1;min-width:0;height:8px;border-radius:999px;
    background:var(--gauge-rail);overflow:hidden}
  /* 그라디언트를 채워진 부분이 아니라 레일 전체에 걸쳐 그린다.
     채워진 만큼만 배경을 두면 한 칸에서도 처음부터 끝 색까지가 통째로 눌려 들어가,
     차오르는 동안 색이 앞뒤로 요동친다. 레일에 걸어두면 채운 만큼만 드러나서
     옅은 쪽에서 짙은 쪽으로 천천히 건너간다 —
     JS가 넘겨주는 --p(채운 비율)로 배경을 그만큼 늘려 잡는다 */
  .gauge-fill{width:0;height:100%;border-radius:999px;
    background:var(--gauge-grad);
    background-size:calc(100% / var(--p,1)) 100%;
    background-repeat:no-repeat;
    transition:width .45s cubic-bezier(.22,1,.36,1),
               background-size .45s cubic-bezier(.22,1,.36,1)}
  /* 숫자가 바뀔 때 폭이 흔들리면 게이지까지 덩달아 늘었다 줄었다 한다 */
  .gauge-count{flex:0 0 auto;font-size:12px;color:var(--sub);font-variant-numeric:tabular-nums}
  .gauge-count b{font-weight:600;color:var(--text)}

  /* 이모지 블라스터 — 게이지가 찬 끝점(--x)에서 솟았다 떨어진다.
     위로만 크게 뻗으면 데스크톱에서 게이지가 화면 맨 위에 붙어 있어 헤더에 잘린다.
     짧게 솟고 아래(패널 쪽)로 흘려보내면 잘리는 구간 없이 궤적이 다 보인다 */
  .gauge-burst{position:absolute;left:var(--x,0);top:50%;width:0;height:0;pointer-events:none;z-index:5}
  .gauge-burst span{position:absolute;left:0;top:0;font-size:17px;line-height:1;
    will-change:transform,opacity;
    animation:gauge-pop var(--dur,1100ms) cubic-bezier(.2,.6,.35,1) forwards}
  @keyframes gauge-pop{
    0%  {transform:translate(-50%,-50%) scale(.4);opacity:0}
    14% {opacity:1}
    45% {transform:translate(calc(-50% + var(--dx) * .6),calc(-50% + var(--rise))) scale(1.05);opacity:1}
    100%{transform:translate(calc(-50% + var(--dx)),calc(-50% + var(--fall))) scale(.75) rotate(var(--rot));opacity:0}
  }
  /* 마일스톤 문구는 게이지 줄을 덮으며 나타났다 사라진다 — 위나 아래로 띄우면
     모바일에서 미리보기를 가리거나 시트 밖으로 잘린다 */
  .gauge-toast{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:7px;
    background:var(--panel);font-size:13.5px;font-weight:600;color:var(--text);
    opacity:0;pointer-events:none;transform:translateY(5px);
    transition:opacity .22s,transform .22s}
  .gauge-toast.show{opacity:1;transform:none}
  .app-toast{position:fixed;bottom:72px;left:50%;transform:translateX(-50%) translateY(6px);
    background:rgba(0,0,0,0.78);color:#fff;padding:10px 20px;border-radius:24px;
    font-size:14px;font-weight:500;white-space:nowrap;z-index:500;
    opacity:0;transition:opacity .2s,transform .2s;pointer-events:none}
  .app-toast.show{opacity:1;transform:translateX(-50%) translateY(0)}

  /* ---- 내보내기 버튼 ----
     색은 .btn.primary의 검정 한 계열 그대로 둔다. 진행이 드러나는 자리는
     게이지와 여기 앉는 이모지이지, 주 동작 버튼의 색이 아니다.
     이모지가 글자와 같은 줄 가운데에 서도록 플렉스로만 잡는다 */
  #btnExport{display:inline-flex;align-items:center}
  /* 이모지가 앉는 칸. 붙는 이모지는 늘 하나이고, 구간을 넘을 때마다 갈아끼운다.
     기본 상태가 곧 다 붙은 상태다 — 애니메이션은 여기서 출발하거나 여기로 돌아온다 */
  .ex-emos{display:none}
  .ex-emo{display:inline-block;max-width:1.3em;overflow:hidden;
    font-style:normal;line-height:1}
  /* 처음 앉을 때만 폭이 0에서 벌어지고, 그만큼 버튼이 자연스럽게 늘어난다 */
  .ex-emo.grow{animation:emo-grow .5s cubic-bezier(.34,1.4,.64,1)}
  @keyframes emo-grow{
    0%  {max-width:0;opacity:0;transform:scale(.3) rotate(-30deg)}
    55% {opacity:1}
    100%{max-width:1.3em;opacity:1;transform:none}
  }
  /* 갈아끼울 때는 폭을 건드리지 않는다 — 0부터 다시 벌리면 버튼이 움찔거린다 */
  .ex-emo.swap{animation:emo-swap .45s cubic-bezier(.34,1.4,.64,1)}
  @keyframes emo-swap{
    0%  {opacity:0;transform:scale(.35) rotate(-30deg)}
    55% {opacity:1}
    100%{opacity:1;transform:none}
  }
  @media (prefers-reduced-motion:reduce){
    #btnExport{transition:none}
    .ex-emo.grow,.ex-emo.swap{animation:none}
  }

  /* ---- 내보내기 완주 페이지 ----
     편집 화면 위에 얹는 쪽지가 아니라 화면을 통째로 넘겨받는 한 장이다.
     바탕은 편집 화면의 회색(--bg)이 아니라 흰색 — 여기는 작업대가 아니라
     도착한 자리라, 뒤에 아무것도 없다는 게 색으로도 드러나야 한다.
     세로 가운데 정렬은 margin:auto로 잡는다. align-items:center로 잡으면
     내용이 화면보다 길어졌을 때 위쪽이 잘려 스크롤로도 닿지 않는다 */
  .done{position:fixed;inset:0;z-index:80;display:none;background:#fff;
    overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain}
  .done.show{display:flex}
  .done-inner{position:relative;z-index:1;margin:auto;
    width:100%;max-width:420px;padding:40px 24px;text-align:center;
    display:flex;flex-direction:column;align-items:stretch}

  .done-title{font-size:30px;font-weight:600;line-height:1.3;margin:0 0 8px;
    letter-spacing:-.02em;text-wrap:balance}
  .done-sub{font-size:16.5px;font-weight:400;line-height:1.6;color:var(--sub);
    margin:0 0 34px;word-break:keep-all}

  /* 아이콘과 좌우 스티커. 스티커는 흐름에서 빼내 아이콘 옆에 겹쳐 붙인다 —
     가로로 나란히 놓으면 셋이 폭을 나눠 갖느라 아이콘이 쪼그라든다 */
  .done-stage{position:relative;display:flex;justify-content:center;align-items:center;
    margin-bottom:12px}
  /* 자기가 올린 테마 아이콘을 그대로 띄운다 — 완성된 것이 무엇인지 한 눈에 보인다.
     테두리는 누구에게나 같은 뮤트톤이다. 테마 색을 따라가게 두면 밝은 색을 고른
     사람에게는 액자가 사라지고 짙은 색을 고른 사람에게는 아이콘보다 테두리가 먼저 보인다 */
  .done-icon{width:120px;height:120px;flex:0 0 120px;border-radius:30px;
    background:#f4f5f7 center/cover no-repeat;
    border:1.5px solid var(--line)}
  /* 좁은 화면에서도 화면 밖으로 나가지 않게 폭을 vw에 묶어둔다 */
  .done-sticker{position:absolute;width:min(96px,25vw);height:auto;pointer-events:none;user-select:none}
  .done-sticker.left{right:calc(50% + 68px);top:14px}
  .done-sticker.right{left:calc(50% + 68px);bottom:6px}
  /* 무엇을 받았는지 — 방금 저장한 파일의 이름 그대로 */
  .done-file{font-size:14px;color:var(--text);margin-bottom:26px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

  /* 편집 패널의 게이지와 같은 방식 — 그라디언트는 레일 전체에 걸고 채운 만큼만 드러낸다 */
  .done-track{height:10px;border-radius:999px;background:var(--gauge-rail);
    overflow:hidden;margin-bottom:12px}
  .done-track i{display:block;height:100%;width:0;border-radius:999px;
    background:var(--gauge-grad);
    background-size:calc(100% / var(--p,1)) 100%;
    background-repeat:no-repeat;
    transition:width .9s cubic-bezier(.22,1,.36,1),
               background-size .9s cubic-bezier(.22,1,.36,1)}
  /* 개수와 문구는 한 덩어리로 읽힌다 — 몇 개를 바꿨고 그래서 어떤 테마인지 */
  .done-count{font-size:15px;color:var(--sub);font-variant-numeric:tabular-nums}
  .done-msg{font-size:15px;color:var(--sub);margin:2px 0 0;line-height:1.6;
    word-break:keep-all;text-wrap:balance}

  /* 세 버튼은 성격이 다 달라서 한 줄에 늘어놓지 않는다 — 위에서부터 권하는 순서다 */
  .done-actions{display:flex;flex-direction:column;gap:9px;margin-top:36px}
  .done-actions .btn{width:100%;padding:15px 16px;font-size:15px;border-radius:14px}
  /* 되돌아가는 길이라 테두리로 존재를 주장하지 않는다 — 바탕만 살짝 얹는다 */
  .btn.subtle{background:#f2f3f5;border-color:transparent}
  @media (hover:hover){ .btn.subtle:hover{background:#e9ebee} }

  /* 터지는 조각은 콘페티가 아니라 이 테마의 탭 아이콘이다 — 갈아끼운 사람에게는
     자기가 고른 것이, 손대지 않은 사람에게는 기본 아이콘이 그대로 쏟아진다.
     탭 아이콘은 배경이 비치는 그림이라 상자처럼 다루면 안 된다 — 모서리를 깎거나
     그림자를 드리우면 그림에 없는 사각형이 생긴다. 비율 그대로 담기만 한다 */
  .done-divider{height:1px;background:var(--line);width:100%}
  .done-apk-hint{margin-top:28px;display:flex;flex-direction:column;gap:18px;text-align:center}
  .apk-hint-section{display:flex;flex-direction:column;align-items:center;gap:7px}
  .apk-hint-label{font-size:13px;font-weight:500;color:var(--text)}
  .apk-hint-link{font-size:13px;color:var(--sub);text-decoration:underline;cursor:pointer;word-break:keep-all}
  .apk-copy-btn{padding:9px 18px;border-radius:10px;border:1.5px solid var(--line);
    background:var(--bg2);color:var(--text);font-size:13px;cursor:pointer}
  .apk-hint-desc{font-size:13px;color:var(--sub);line-height:1.65;word-break:keep-all;max-width:280px}
  .done-fx{position:fixed;inset:0;overflow:hidden;pointer-events:none;z-index:0}
  /* 한 번 쏟아지고 마는 게 아니라 계속 내린다 — 조각마다 걸리는 시간과 시작 시점이
     달라서, 한 바퀴가 지나면 서로 어긋난 채 끊임없이 떨어지는 것처럼 보인다.
     그래서 조각 수는 적게 둔다. 여기 적힌 수가 곧 한 화면에 동시에 떠 있는 수다.
     떨어지는 거리는 화면 높이에서 바로 가져온다 — JS가 재서 넘기면 화면을 돌렸을 때
     그 값이 낡은 채로 남는다 */
  .done-fx .cf{position:absolute;top:-90px;width:var(--sz);height:var(--sz);
    object-fit:contain;opacity:0;
    animation:confetti-fall var(--dur) linear var(--delay) infinite}
  @keyframes confetti-fall{
    0%  {opacity:0;transform:translateY(0) rotate(0)}
    8%  {opacity:1}
    90% {opacity:1}
    100%{opacity:0;transform:translateY(calc(100vh + 180px)) rotate(var(--rot))}
  }

  /* 움직임을 줄여달라고 한 사람에게는 튀어나오는 것들을 전부 걷어낸다 —
     문구와 게이지 값은 그대로 남으므로 전달되는 정보는 같다 */
  @media (prefers-reduced-motion:reduce){
    .gauge-fill,.done-track i{transition:none}
    .gauge-burst span,.done-fx .cf{display:none}
  }

  /* ── 안드로이드 빌드 로딩 오버레이 ── */
  .build-overlay{position:fixed;inset:0;z-index:95;display:none;flex-direction:column;
    align-items:center;justify-content:center;
    background:rgba(255,255,255,0.6);
    backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}
  .build-overlay.show{display:flex}
  .build-inner{text-align:center;display:flex;flex-direction:column;align-items:center;
    padding:40px 24px;max-width:360px;width:100%}
  .build-title{font-size:22px;font-weight:600;line-height:1.35;letter-spacing:-.02em;
    margin:0 0 12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    width:100%;color:var(--text)}
  .build-desc{font-size:15px;color:var(--sub);margin:0 0 24px;
    line-height:1.6;word-break:keep-all}
  .build-icon{width:96px;height:96px;flex:0 0 96px;border-radius:24px;
    background:#f4f5f7 center/cover no-repeat;
    border:1.5px solid var(--line);margin-bottom:24px}
  .build-track{height:10px;border-radius:999px;background:var(--gauge-rail);
    overflow:hidden;width:100%;margin-bottom:16px}
  .build-track i{display:block;height:100%;width:0;border-radius:999px;
    background:var(--gauge-grad);transition:width 2s ease-out}
  .build-warn{font-size:13px;color:var(--sub);opacity:.6;margin:0;line-height:1.5}

  /* ---- nine-patch editor ---- */
  /* .nine-body를 레이아웃에서 걷어내 미리보기 → 탭 → 영역 지정 순으로 세로로 쌓는다.
     폭·구성 모두 내보내기 모달과 같아서 두 모달이 같은 화면처럼 읽힌다 */
  .nine-modal .modal-body{display:flex;flex-direction:column;align-items:stretch}
  /* 캔버스 위/아래 안내 문구가 선택 가능한 텍스트로 남아 있으면, 모바일에서 꾹 눌러
     드래그를 시작할 때 브라우저가 그 텍스트를 길게 눌러 선택하는 걸로 먼저 해석해버려
     정작 캔버스 드래그가 씹힌다. 이 모달 안 텍스트는 어차피 복사할 내용이 아니므로
     통째로 선택 대상에서 뺀다 */
  .nine-modal{position:relative;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
  /* Tip 트리거·업로드 버튼·구분선은 DOM 순서 그대로 맨 위에 쌓인다 — 아래
     .nine-right/.nine-seg/.nine-left만 order로 재배치되므로 손대지 않아도 이 셋이 먼저 온다.
     Tip 내용 자체는 여기 없다 — 별도 바텀시트(.sheet-overlay#nineTipSheet)로 뺐다.
     이 버튼은 그걸 여는 트리거 이미지 하나뿐이라, 콘테이너 폭의 절반만 차지해 시선이
     쏠리지 않게 한다 */
  /* 말풍선 만들기 타이틀 + 물음표 버튼 묶음 — 타이틀이 flex:1로 늘어나지 않아야 버튼이 바로 옆에 붙는다 */
  .nine-title-row{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:4px}
  .nine-title-row .modal-title{flex:0 0 auto}
  .nine-pill-btn{border:1px solid #eee;border-radius:99px;padding:5px 8px;background:transparent;
    font-size:12px;line-height:1.4;cursor:pointer;color:var(--text);white-space:nowrap;flex:0 0 auto}
  @media (hover:hover){ .nine-pill-btn:hover{background:#f2f3f5} }
  /* QnA 아코디언 */
  .nine-qna{margin:0}
  .nine-qna-item{border-bottom:1px solid var(--line2)}
  .nine-qna-item:first-child{border-top:1px solid var(--line2)}
  .nine-qna-q{width:100%;display:flex;align-items:center;justify-content:space-between;
    gap:12px;padding:16px 0;background:none;border:none;cursor:pointer;text-align:left;
    font-size:15px;font-weight:500;color:var(--text);line-height:1.4}
  @media (hover:hover){.nine-qna-q:hover{color:var(--primary)}}
  /* + 아이콘 — aria-expanded:true 일 때 세로선을 숨겨 × → + 로 전환 */
  .nine-qna-icon{flex-shrink:0;width:20px;height:20px;position:relative}
  .nine-qna-icon::before,.nine-qna-icon::after{content:'';position:absolute;
    background:var(--sub);border-radius:2px;transition:opacity .2s,transform .2s}
  .nine-qna-icon::before{width:2px;height:14px;top:3px;left:9px}
  .nine-qna-icon::after{width:14px;height:2px;top:9px;left:3px}
  .nine-qna-q[aria-expanded="true"] .nine-qna-icon::before{opacity:0}
  .nine-qna-a{padding:0 0 16px}
  .nine-qna-a-text{font-size:14px;color:var(--sub);line-height:1.6;margin:0 0 12px}
  .nine-qna-a-text:last-child{margin-bottom:0}
  .nine-tip-img{display:block;width:100%;height:auto;border:1px solid var(--line2);border-radius:10px}
  /* 완주 페이지의 "또 만들기"와 같은 크기(패딩·글자·라운드)를 쓴다 —
     .btn 기본(흰 배경·테두리)은 그대로 두고 크기만 그쪽에 맞춘다 */
  .nine-upload-btn{width:100%;padding:8px 16px;border-radius:14px;text-align:left;margin-bottom:8px;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:12px}
  .nine-btn-text{display:flex;flex-direction:column;gap:3px;flex:1;min-width:0}
  .nine-btn-label{font-size:14px;font-weight:600;line-height:1.2;color:var(--text)}
  .nine-btn-desc{font-size:12px;font-weight:400;color:var(--sub);line-height:1.3}
  .nine-btn-gif{height:56px;width:auto;flex:0 0 auto;object-fit:contain}
  .nine-upload-btn--secondary{color:var(--text2);border-color:var(--line2)}
  /* ---- 말풍선 값 불러오기 시트 (PC: 중앙 모달 / Mobile: 바텀싯) ---- */
  .nine-import-sheet{position:absolute;inset:0;z-index:5;background:rgba(0,0,0,0.42);
    display:flex;align-items:center;justify-content:center;border-radius:inherit;overflow:hidden}
  .nine-import-inner{background:#fff;width:360px;max-width:calc(100% - 40px);
    border-radius:16px;max-height:80%;overflow:hidden;display:flex;flex-direction:column}
  .nine-import-handle{display:none;align-items:center;justify-content:center;
    height:32px;flex:0 0 32px;touch-action:none;cursor:grab}
  .nine-import-handle:active{cursor:grabbing}
  .nine-import-handle span{width:38px;height:4px;border-radius:999px;background:#d3d7de}
  .nine-import-head{display:flex;align-items:flex-start;gap:12px;padding:20px 20px 10px;flex:0 0 auto}
  .nine-import-head .modal-heading{flex:1;min-width:0}
  .nine-import-head .modal-title{font-size:17px;font-weight:600}
  .nine-import-desc{font-size:12px;color:var(--sub);margin-top:3px;line-height:1.5}
  .nine-import-current{font-size:12px;color:var(--sub);line-height:1.5;
    margin:0;padding:0 20px 10px}
  .nine-import-close{flex:0 0 auto;margin-top:-2px}
  .nine-import-list{overflow-y:auto;display:flex;flex-direction:column;gap:8px;
    padding:0 20px;padding-bottom:calc(20px + env(safe-area-inset-bottom))}
  .nine-import-item{width:100%;display:flex;align-items:center;gap:10px;
    padding:10px 12px;border:1px solid var(--line2);border-radius:12px;
    background:var(--bg2);cursor:pointer;text-align:left;flex:0 0 auto}
  .nine-import-item:active{opacity:.6}
  .nine-import-item--empty{opacity:.38;cursor:default}
  .nine-import-thumb{width:36px;height:36px;flex:0 0 36px;border-radius:8px;
    background:#f2f3f5 center/contain no-repeat;border:1px dashed var(--line)}
  .nine-import-thumb.has{border-style:solid;background-color:#f2f3f5}
  .nine-import-thumb--empty{background:var(--line);border-color:transparent}
  .nine-import-name{font-size:14px;font-weight:500;flex:1;min-width:0;color:var(--text)}
  .nine-body{display:contents}
  .nine-right{order:1;margin-bottom:16px}
  .nine-seg{order:2}
  .nine-left{order:3;max-width:100%}
  .nine-canvas-wrap{position:relative;width:100%;height:230px;border:1px solid var(--line);
    overflow:hidden;cursor:crosshair;touch-action:none;
    background:#fff;
    background-image:linear-gradient(45deg,#eef0f3 25%,transparent 25%),linear-gradient(-45deg,#eef0f3 25%,transparent 25%),
      linear-gradient(45deg,transparent 75%,#eef0f3 75%),linear-gradient(-45deg,transparent 75%,#eef0f3 75%);
    background-size:14px 14px;background-position:0 0,0 7px,7px -7px,-7px 0}
  .nine-canvas-wrap img{position:absolute;left:0;top:0;
    image-rendering:auto;pointer-events:none;user-select:none;
    -webkit-user-drag:none;user-drag:none}
  /* shadcn Tabs 스타일 — 연한 회색 pill 안에서 active 탭만 흰 배경+얕은 그림자로 떠 보이는 방식 */
  .nine-seg{display:flex;gap:2px;padding:3px;background:#f1f3f5;border-radius:10px;margin-bottom:14px}
  .nine-seg button{flex:1;border:none;background:transparent;border-radius:7px;padding:7px 8px;
    font-size:14px;font-weight:500;color:var(--sub);cursor:pointer;transition:background-color .15s,color .15s,box-shadow .15s}
  @media (hover:hover){ .nine-seg button:not(.active):hover{color:var(--text)} }
  .nine-seg button.active{background:#fff;color:var(--text);box-shadow:0 1px 2px rgba(0,0,0,.08)}
  .nine-seg button[hidden]{display:none}
  /* 인셋 박스 */
  .nine-inset{position:absolute;border:1.5px solid #111;pointer-events:none;z-index:2;display:none;
    box-shadow:0 0 0 9999px rgba(47,107,255,.10)}
  .nine-stage-inset .nine-inset{display:block;border-color:#2f6bff;border-width:1px}
  .ins-edge{position:absolute;z-index:6;display:none;background:rgba(47,107,255,0);touch-action:none}
  .nine-stage-inset .ins-edge{display:block}
  .ins-edge[data-edge="t"],.ins-edge[data-edge="b"]{height:10px;cursor:ns-resize}
  .ins-edge[data-edge="l"],.ins-edge[data-edge="r"]{width:10px;cursor:ew-resize}
  @media(hover:hover){.ins-edge:hover{background:rgba(47,107,255,.18)}}
  .nine-vline,.nine-hline,.nine-knob{display:none}
  .nine-stage-center .nine-vline,.nine-stage-center .nine-hline,.nine-stage-center .nine-knob{display:block}
  .nine-vline,.nine-hline{position:absolute;background:#2f6bff;pointer-events:none;z-index:3}
  .nine-vline{width:1px;top:0;bottom:0}
  .nine-hline{height:1px;left:0;right:0}
  .nine-knob{position:absolute;width:13px;height:13px;border-radius:50%;background:#2f6bff;
    border:2px solid #fff;box-shadow:0 1px 5px rgba(0,0,0,.4);transform:translate(-50%,-50%);
    pointer-events:none;z-index:4}
  #nineImg{position:absolute;display:block;box-shadow:0 0 0 1px var(--line);pointer-events:none}
  /* 유저가 불러온 이미지 크기 — 아트보드가 곧 이 크기로 고정된다는 것만 알면 되므로 이 한 줄만 남긴다 */
  .nine-prev-label{font-size:14px;font-weight:600;color:#555;margin-bottom:10px}
  /* 탭(나인패치 중심점/텍스트 영역)별 안내 — 제목은 .nine-prev-label과 동일 스타일 재사용 */
  .nine-step-desc{font-size:12px;color:var(--sub);line-height:1.5;margin:-4px 0 12px}
  .nine-prev-row{display:flex;flex-direction:column;gap:14px}
  /* 회색 카드 배경 — 흰색/투명 모서리 말풍선도 실루엣이 보이게 대비를 준다 */
  .nine-prev-cell{display:flex;flex-direction:column;gap:10px;align-items:center;justify-content:center;
    background:#f1f3f5;border-radius:10px;padding:14px 12px;height:200px;overflow:hidden}
  /* 박스 안 제목은 가운데 — 좌측의 단계 제목(#nineStepTitle)은 그대로 왼쪽 정렬이다 */
  .nine-prev-cell .nine-prev-label{margin-bottom:0;text-align:center}
  /* 미리보기 아래 안내 문구 — .field-hint를 재사용하되, 부모가 이미 flex gap(10px)으로
     간격을 주고 있어 기본 margin-top은 겹치지 않게 지운다 */
  .nine-prev-cell .field-hint{margin-top:0;text-align:center}
  .np-box{font-size:12.5px;line-height:1.45;color:#333;max-width:100%;
    display:flex;align-items:center;background-repeat:no-repeat}
  #npTall{width:80%;min-width:120px}

  /* ================= 말풍선 이미지 컴포저 ================= */
  .composer-overlay{z-index:95}
  .composer-modal{max-width:640px;width:100%;height:600px}
  /* split: 헤더 아래에서 좌(캔버스) / 우(패널)로 나뉨 */
  .composer-split{display:flex;flex:1;min-height:0;overflow:hidden}
  .composer-left{display:flex;flex-direction:column;flex:1;min-width:0;overflow:hidden;background:var(--bg)}
  .composer-content{flex:1;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0 20px;gap:8px}
  /* 데스크톱 전용 우측 샘플 패널 */
  .smpk-panel{
    width:220px;flex:0 0 auto;
    border-left:1px solid var(--line);
    background:#fff;
    display:flex;flex-direction:column;
    overflow:hidden;
    transition:width .3s cubic-bezier(.32,.72,0,1),border-left-width .3s cubic-bezier(.32,.72,0,1)}
  .smpk-panel.slide-out{width:0;border-left-width:0}
  .smpk-panel-body{flex:1;min-height:0;display:flex;flex-direction:column;
    overflow-y:auto;-webkit-overflow-scrolling:touch;width:220px}
  .smpk-panel .smpk-grid{padding:10px 10px 0;gap:10px}
  .smpk-panel .smpk-credit{padding:6px 10px 12px;font-size:11px;color:var(--sub);text-align:center;margin:0}
  /* 데스크톱: 툴바 이미지 추가 버튼 숨김 (패널이 상시 노출) */
  /* smpk-overlay는 JS에서 데스크톱 시 .show를 추가하지 않으므로 별도 규칙 불필요 */
  #imgComposerAdd{display:none}
  .composer-footer{flex:0 0 auto;padding:10px 20px 20px;border-top:1px solid var(--line)}
  .composer-canvas-area{position:relative;width:100%;max-width:340px;margin:0 auto}
  .composer-frame-wrap{
    position:relative;display:block;width:100%;
    overflow:hidden;border:1px solid var(--line)}
  #imgComposerCanvas{display:block;width:100%;aspect-ratio:1;touch-action:none;cursor:default}
  #composerGuideLayer{position:absolute;width:100%;left:0;top:0;aspect-ratio:1;pointer-events:none;z-index:4}
  #composerGuideImg{position:absolute;width:auto;height:auto;top:50%;left:50%;transform:translate(-50%,-50%);opacity:0.38}
  /* ---- 빈 상태 힌트 오버레이 ---- */
  .composer-empty-hint{position:absolute;inset:0;pointer-events:none;z-index:3;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px}
  .ceh-lg{width:70%;max-width:220px;flex:0 0 auto}
  .ceh-label{display:inline-block;border:1px solid #000;padding:4px 10px;background:#fff}
  .ceh-text{margin:0;text-align:center;font-size:12px;line-height:1.6;color:#000}
  .composer-crop-hint{margin:0 0 8px;text-align:center;font-size:12px;line-height:1.6;color:var(--sub)}
  .composer-head{justify-content:space-between;gap:0;border-bottom:1px solid var(--line)}
  .btn-head{font-size:14px;font-weight:500;padding:5px 10px;border-radius:8px;border:none;
    cursor:pointer;background:transparent;color:var(--text2);white-space:nowrap}
  .btn-head-primary{color:#2F6BFF;font-weight:600}
  @media(hover:hover){.btn-head:hover{background:var(--line2)}}
  .composer-toolbar{display:flex;align-items:center;justify-content:center;gap:4px}
  .ctool-btn{display:flex;flex-direction:column;align-items:center;gap:8px;padding:8px 16px;
    border:none;background:transparent;cursor:pointer;border-radius:10px;color:var(--text);width:80px;flex:0 0 auto}
  @media(hover:hover){.ctool-btn:hover{background:var(--line2)}}
  .ctool-btn.active{color:#2f6bff}
  .ctool-tip{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);
    white-space:nowrap;font-size:11px;font-weight:500;color:#fff;background:rgba(0,0,0,.75);
    padding:4px 8px;border-radius:6px;pointer-events:none;display:none}
  .ctool-tip::after{content:'';position:absolute;top:100%;left:50%;transform:translateX(-50%);
    border:4px solid transparent;border-top-color:rgba(0,0,0,.75)}
  .ctool-btn.active .ctool-tip{display:block}
  #imgComposerGuide{position:relative}
  .ctool-icon{width:22px;height:22px;display:grid;place-items:center;flex:0 0 auto}
  .ctool-label{font-size:12px;font-weight:500;color:var(--sub);line-height:1;white-space:nowrap}
  .ctool-btn.active .ctool-label{color:#2f6bff}
  .btn-sm{font-size:13px;font-weight:500;padding:5px 12px;border-radius:8px;
    border:1.5px solid var(--line2);background:transparent;color:var(--text);cursor:pointer;white-space:nowrap}
  @media(hover:hover){.btn-sm:hover{background:var(--line2)}}
  .btn-sm-danger{color:#e53e3e;border-color:#e53e3e}
  @media(hover:hover){.btn-sm-danger:hover{background:#fff0f0}}
  .btn-sm.active{background:var(--text);color:var(--bg);border-color:var(--text)}

  /* ================= 모바일: 미리보기 고정 + 편집 바텀시트 =================
     두 패널을 나란히 놓을 수 없는 폭에서는, 미리보기를 상단에 고정하고
     편집 패널을 끌어올리는 시트로 바꾼다. 시트를 얼마나 올렸느냐에 따라
     미리보기에 남는 높이가 달라지므로 폰 목업 배율(--ps)은 JS가 다시 계산한다 */
  @media (max-width:700px){
    body{height:100dvh}
    main{display:block;position:relative;overflow:hidden}

    /* ---- 미리보기 (고정, 좌우로 넘겨서 화면 전환) ---- */
    /* 두 패널 모두 absolute라 DOM 순서상 미리보기가 위에 그려진다 —
       시트를 올렸을 때 폰 목업이 시트를 뚫고 나오지 않도록 쌓임 순서를 지정한다 */
    .preview-wrap{position:absolute;inset:0;padding:12px 0 0;overflow:hidden;align-items:stretch;z-index:1}
    .preview-wrap .panel-subtitle,.preview-wrap .panel-desc{display:none}
    /* 카드 폭을 축소된 실제 크기에 맞춰 좌측부터 늘어놓는다 —
       다음 화면이 살짝 걸쳐 보여야 넘길 수 있다는 게 드러난다 */
    .preview-row{flex:1;min-height:0;width:100%;flex-wrap:nowrap;gap:12px;
      overflow-x:auto;overflow-y:hidden;scroll-snap-type:x proximity;
      align-items:flex-start;padding:0 14px;scroll-padding-left:14px;
      scrollbar-width:none;overscroll-behavior-x:contain;
      /* 기본값 center를 그대로 두면 넘치는 콘텐츠가 좌우로 밀려 왼쪽이 잘린 채 스크롤로도 닿지 않는다 */
      justify-content:flex-start}
    .preview-row::-webkit-scrollbar{display:none}
    .preview-col{flex:0 0 auto;scroll-snap-align:start;align-items:center}
    .phone-fit{display:block;overflow:hidden;flex:0 0 auto}
    /* 배율은 남는 높이에 따라 달라져서 JS가 인라인으로 지정한다 */
    /* max-width:100%를 그대로 두면 래퍼(축소된 폭)에 걸려 폰이 한 번 더 줄어든다 */
    .phone{max-width:none;transform-origin:top left;
      transition:transform .28s cubic-bezier(.32,.72,0,1)}

    /* ---- 편집 패널 (바텀시트) ---- */
    .editor{position:absolute;left:0;right:0;top:0;bottom:0;z-index:2;
      border-left:0;border-top:1px solid var(--line);border-radius:18px 18px 0 0;
      box-shadow:0 -6px 28px rgba(0,0,0,.12);
      transform:translateY(var(--sheet,48%));
      transition:transform .28s cubic-bezier(.32,.72,0,1)}
    .editor.dragging{transition:none}
    /* 시트는 translateY로 밀려날 뿐 레이아웃 높이는 화면 전체 그대로여서,
       flex로 늘려두면 스크롤 영역의 아랫부분이 화면 밖에 남아 끝까지 닿지 않는다.
       화면에 실제로 보이는 만큼만 높이를 잡도록 JS가 지정한다 */
    /* 위 여백 없이 두면 게이지 바로 아래에 제목이 붙어 숨 쉴 틈이 없다 —
       손잡이·게이지·제목이 한 덩어리로 뭉쳐 보인다 */
    .panel-scroll{flex:0 0 auto;padding:16px 16px calc(24px + env(safe-area-inset-bottom))}
    /* 헤더 좌우 여백도 패널과 같은 16px로 — 데스크톱의 18px과 짝을 이룬다 */
    header.topbar{padding:12px 16px}
    /* 초기화 버튼과 한 줄을 이루므로 가운데 정렬을 풀어 왼쪽에 붙인다 */
    .editor .panel-subtitle{font-size:16px;margin-bottom:0;text-align:left}
    .panel-head{margin-bottom:10px}
    /* 손잡이 — 드래그 시작점을 여기로 한정한다. 시트 전체를 대상으로 하면
       목록 스크롤과 방향이 같아 서로 잡아먹는다 */
    .sheet-handle{display:flex;align-items:center;justify-content:center;
      height:40px;flex:0 0 40px;touch-action:none;cursor:grab;
      -webkit-tap-highlight-color:transparent}
    .sheet-handle:active{cursor:grabbing}
    .sheet-handle span{width:38px;height:4px;border-radius:999px;background:#d3d7de}
    /* 손잡이 바로 아래 한 줄. 시트를 끝까지 내려도 이 줄까지는 화면에 남는다.
       좌우 여백은 아래 목록(.panel-scroll)과 같은 16px */
    .section-nav{padding:8px 16px}
    .gauge{padding:9px 16px 11px}
  }

  /* ==================== 샘플 이미지 피커 ====================
     데스크톱: 가운데 모달, 모바일: 3단 스냅 바텀시트 */
  .smpk-overlay{z-index:96}
  .smpk-sheet{
    background:#fff;border-radius:16px;
    width:400px;max-width:100%;height:600px;
    display:flex;flex-direction:column;overflow:hidden;
    box-shadow:0 20px 60px rgba(0,0,0,.3)}
  .smpk-handle{display:none}
  .smpk-head{
    flex:0 0 auto;display:flex;align-items:center;gap:4px;
    padding:20px 12px 8px}
  .smpk-head .modal-title{flex:1;text-align:center}
  .smpk-body{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}
  .smpk-grid{
    display:grid;grid-template-columns:repeat(3,1fr);
    gap:10px;padding:8px 16px 16px}
  .smpk-cell{
    aspect-ratio:1;border-radius:12px;overflow:hidden;
    border:none;cursor:pointer;
    padding:0;display:block;-webkit-tap-highlight-color:transparent;
    background-color:#fff;
    background-image:linear-gradient(45deg,#e8e8e8 25%,transparent 25%),linear-gradient(-45deg,#e8e8e8 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#e8e8e8 75%),linear-gradient(-45deg,transparent 75%,#e8e8e8 75%);
    background-size:12px 12px;
    background-position:0 0,0 6px,6px -6px,-6px 0}
  .smpk-cell:active{opacity:.7}
  .smpk-cell img{width:100%;height:100%;object-fit:cover;display:block}
  .smpk-upload{
    display:flex;align-items:center;justify-content:center;
    background:var(--bg);border:none;color:var(--sub)}
  .smpk-credit{margin:0;font-size:11px;color:var(--sub);text-align:center;padding:4px 16px 16px}

  /* ================= 모바일: 모달을 전체 화면으로 =================
     좁은 화면에서 사각 컨테이너로 띄우면 남는 여백만 늘고 내용이 눌린다.
     화면을 다 쓰고 헤더·확인 버튼을 고정해 스크롤과 무관하게 보이게 한다 */
  @media (max-width:700px){
    .modal-overlay{padding:0}
    .modal{width:100%;max-width:none;height:100dvh;max-height:none;
      border-radius:0;padding:0;overflow:hidden;
      display:flex;flex-direction:column;box-shadow:none}
    .nine-modal{width:100%}
    /* 인셋 편집 중 버블 높이가 바뀌면 캔버스가 밀려 드래그가 어긋나는 문제 방지 */
    .nine-right{flex-shrink:0}

    /* 모바일: 데스크톱 패널 숨김, 툴바 이미지 추가 버튼 복원 */
    .smpk-panel{display:none}
    #imgComposerAdd{display:flex}
    /* 샘플 피커 — 모바일에서 3단 스냅 바텀시트 */
    .smpk-overlay{align-items:flex-end;justify-content:center}
    .smpk-sheet{
      width:100%;max-width:none;height:var(--smpk-sheet-height, 50dvh);max-height:90dvh;
      border-radius:18px 18px 0 0;
      box-shadow:0 -6px 28px rgba(0,0,0,.12);
      background:#fff;
      transform:translateY(100%)}
    .smpk-handle{
      display:flex;align-items:center;justify-content:center;
      flex:0 0 40px;touch-action:none;cursor:grab;
      -webkit-tap-highlight-color:transparent}
    .smpk-handle:active{cursor:grabbing}
    .smpk-handle span{width:38px;height:4px;border-radius:999px;background:#d3d7de}
    .smpk-head{padding:4px 16px 8px}
    .smpk-grid{padding-bottom:0}
    .smpk-credit{padding-bottom:calc(16px + env(safe-area-inset-bottom))}

    /* 말풍선 만들기 Tip — 다른 모달과 달리 모바일에서 전체 화면이 아니라 화면 아래에
       붙는 시트로 뜬다. 값은 편집 패널(.editor)의 바텀시트와 그대로 맞췄다 — 위쪽만
       둥글고(18px), 그림자·트랜지션 이징까지 같아서 "이 앱의 바텀시트"로 한 번에 읽힌다 */
    /* 값 불러오기 — 모바일에서 바텀싯으로 전환 */
    .nine-import-sheet{align-items:flex-end}
    .nine-import-inner{width:100%;max-width:none;border-radius:18px 18px 0 0;max-height:72vh}
    .nine-import-head{padding:20px 20px 10px}
    .nine-import-list{padding-bottom:calc(24px + env(safe-area-inset-bottom))}
    .tip-sheet{align-items:flex-end}
    .tip-sheet .modal{width:100%;height:auto;max-height:82vh;
      border-radius:18px 18px 0 0;box-shadow:0 -6px 28px rgba(0,0,0,.12);
      transform:translateY(100%);transition:transform .28s cubic-bezier(.32,.72,0,1)}
    .tip-sheet .modal.open{transform:translateY(0)}
    .tip-sheet .modal-body{padding-bottom:calc(20px + env(safe-area-inset-bottom))}
    @media (prefers-reduced-motion:reduce){ .tip-sheet .modal{transition:none} }

    /* 헤더·바디·풋터의 구조(flex 세로쌓기, 닫기 버튼 위치)는 기본 규칙 그대로 쓰고
       여기서는 좁은 화면에 맞춰 여백만 줄인다 */
    .modal-head{padding:16px 6px 12px 16px}
    .modal-title{font-size:16px}
    .modal-body{padding:0 16px 16px}
    .modal-actions{padding:12px 16px calc(12px + env(safe-area-inset-bottom))}

    /* 완주 페이지 — 폰에서는 한 단계씩만 줄인다. 원래 화면 하나를 다 쓰는
       구성이라 좁은 화면에서 따로 접을 것이 없다.
       스티커는 아이콘이 작아진 만큼 안쪽으로 당겨 붙인다 */
    .done-inner{padding:32px 22px}
    .done-title{font-size:26px}
    .done-sub{font-size:15.5px;margin-bottom:30px}
    .done-icon{width:104px;height:104px;flex-basis:104px;border-radius:26px}
    .done-sticker.left{right:calc(50% + 58px)}
    .done-sticker.right{left:calc(50% + 58px)}
  }
