  :root{--bg:#0b0e14;--panel:#141925;--line:#232a3a;--fg:#e6ebf5;--muted:#8a93a6;--accent:#4f8cff;--danger:#ff5d6c;--ok:#3ecf8e;--input:#0d111a;--hover:#161c28;--active:#16203a}
  :root[data-theme="light"]{--bg:#f6f7f9;--panel:#ffffff;--line:#e4e7ec;--fg:#1a1f2b;--muted:#697586;--accent:#3b82f6;--danger:#e5484d;--ok:#12a150;--input:#f1f3f6;--hover:#eef1f5;--active:#e7eefc}
  /* ★모바일 브라우저의 ★자동 글자 확대를 끔다(26/08/29 유저제보 "표 그려달라하면 어찌다 폰트가 크게나오더라 어떤칸만").
     iOS·안드로이드는 ★가로로 넓은 블록(표는 가로스크롤 래퍼 안에 들어간다)을 만나면
     ★읽기 편하라고 그 안 글자만 스스로 키운다 — 그래서 ★때때로 ★어떤 칸만 크게 보였다.
     CSS 의 font-size 로는 막지 못하고 ★이 속성으로만 끔는다. */
  html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
  html,body{background:var(--bg);color:var(--fg);height:100%;overflow:hidden;overscroll-behavior:none;touch-action:manipulation}
  *{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
  /* 네이티브 앱 느낌: UI는 선택·롱프레스콜아웃·드래그 금지(입력/메시지만 선택 허용) */
  /* ★키보드 구조 v3(유저확정 CF패리티): body 는 항상 전체 화면 높이(100dvh) — 키보드가 위에 '덮는' CF/사파리 모델.
     전체높이로 두면 콘텐츠가 iOS 입력보조바 뒤로 자연스럽게 비친다.
     도달성(맨아래 요소도 키보드 위로)은 .content padding-bottom:--kbH + bring()(포커스칸 자동 끌올)이 담당.
     top:--appTop(=vv.offsetTop) 유지 — iOS 가 포커스時 레이아웃뷰포트를 밀면 앱 상단을 가시영역 상단에 재정렬. */
  body{margin:0;position:fixed;top:var(--appTop,0);left:0;right:0;background:var(--bg);color:var(--fg);font:15px/1.5 -apple-system,Segoe UI,Roboto,sans-serif;height:100dvh;display:flex;flex-direction:column;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
  input,textarea,select,.bubble,.chatmsgs,.diffbody,.umhist{-webkit-user-select:text;user-select:text;-webkit-touch-callout:default}
  /* ★iOS 선택핸들 드래그(2026-07-30 유저 실기기): body none + 자식 text '섬' 구조는 핸들이 none 경계에
     닿는 순간 드래그가 죽는 WebKit 쿼크(웹검색 n2) → 채팅 패널 전체를 연속 선택영역으로 만들고 컨트롤만 재차단. */
  /* ★코드모드 화면도 텍스트 선택 허용(유저지적 2026-08-05 "드래그해서 복사가 아예 안 되잖아") —
     종전엔 #tab-chat 만 예외라 코드 화면은 통째로 선택 불가였다. 카드 본문·diff·설명 전부 복사 가능하게. */
  #tab-chat,#tab-code{-webkit-user-select:text;user-select:text;-webkit-touch-callout:default}
  #tab-chat button,#tab-chat .ctool,#tab-chat .tgl,#tab-chat .reasonbox>summary,#tab-chat .roombar,#tab-chat .chathub{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}   /* ★상단바·허브 목록은 UI — 드래그 선택 금지(유저지적) */
  #tab-code .code-topbar,#tab-code .code-side,#tab-code .code-dock button{-webkit-user-select:none;user-select:none}
  #tab-code .crow .cl,#tab-code .crow .cs,#tab-code .cdiff,#tab-code .cstep-note,#tab-code .bubble{-webkit-user-select:text;user-select:text}
  /* ★iOS PWA 키보드 대응: html 전역 touch-action:manipulation 이 iOS 네이티브 입력/키보드 뷰포트
     조정을 방해한다. 입력요소만 touch-action:auto 로 되돌려 키보드時 뷰포트가 정상 축소되게 한다. */
  input,textarea,select{touch-action:auto}
  /* ★placeholder 대비: 브라우저 기본은 라이트에서 너무 옅다. 다크는 현행 유지, 라이트만 진하게. */
  input::placeholder,textarea::placeholder{color:var(--muted);opacity:.9}
  :root[data-theme="light"] input::placeholder,:root[data-theme="light"] textarea::placeholder{color:#5a6473;opacity:1}
  .chatmsgs,.content,.modalbox,.sidebar,.diffpanel,.umhist,.utblwrap{overscroll-behavior:contain}
  img,button,a{-webkit-user-drag:none;user-drag:none}
  header{display:flex;align-items:center;gap:12px;padding:14px 20px;border-bottom:1px solid var(--line)}
  /* ★로고가 이름의 첫 글자를 대신한다 — (S로고)ECTOR 한 줄로 읽히게 가로 배치
     (유저확정 26/08/19 "앞에 글자 하나 떼서 로고를 넣고 그 뒤로 나머지 이름"). */
  .logo{display:flex;flex-direction:row;align-items:center;gap:4px;cursor:pointer;user-select:none;line-height:1}
  .logomark{height:30px;width:auto;flex:none;display:block}
  .logotext{font-weight:700;font-size:10px;letter-spacing:3px;color:var(--fg);padding-left:3px}
  /* ★서버가 로고를 박아 줄 때 쓰는 클래스(webfiles.js paintBrand) — 이 규칙이 없으면
     로고 SVG 가 ★원본 크기 그대로 화면 절반을 먹는다(26/08/19 우리 서비스 주소 실사고). */
  .logo .brandlogo{height:40px;width:40px;object-fit:contain;display:block;flex:none}
  .logo .brandlogo[hidden]{display:none}
  .logo .brandname{display:flex;align-items:center;min-width:0}
  /* 이름 글자 높이는 ★마크 속 글자와 눈높이가 맞아야 한 단어로 읽힌다 — 20px 실측 조정 */
  .logo .brandword{height:30px;width:auto;max-width:280px;display:block}
  /* ★boot.js 가 /brand 를 받아 다시 그릴 때는 클래스가 wordmark 다 — 서버 페인트(brandword)와
     ★둘 다 잡아야 한다. 부모 클래스가 logotext→brandname 으로 바뀌어도 .logo 밑이면 맞게. */
  .logo .wordmark{height:30px;width:auto;max-width:280px;display:block}
  .grow{flex:1}
  /* ★overflow:hidden 이면 로그인/가입 화면은 스크롤이 아예 불가능해, 키보드가 뜨면 가려진 칸으로 갈 방법이 없다
     (scrollIntoView 도 안 먹는다). 세로 스크롤만 허용하고 가로는 계속 막는다(좌우 흔들림 방지). */
  main{flex:1;min-height:0;display:flex;flex-direction:column;align-items:center;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}
  /* ★모달이 열린 동안 뒤 화면은 완전히 잠근다 — 스크롤 전파를 CSS로 원천 차단(배경 움직임·새로고침 방지) */
  body.modal-open main,body.modal-open .content{overflow:hidden!important;touch-action:none}
  /* ★로그인 화면 = 로고 중앙 + 바로 아래 카드(유저확정 26/08/19 "로고를 입력칸에 붙이고 중앙정렬").
     채팅 등 앱 화면으로 들어가면 body.inapp 을 붙여 ★원래 왼쪽 상단 배치로 돌아간다. */
  body:not(.inapp) header{justify-content:center;border-bottom:0;padding:34px 20px 0}
  body:not(.inapp) header .grow{display:none}
  .card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:28px;width:100%;max-width:380px;margin:18px auto auto;flex:0 0 auto}
  h2{margin:0 0 4px}
  .sub{color:var(--muted);margin:0 0 20px;font-size:13px}
  label{display:block;font-size:12px;color:var(--muted);margin:12px 0 5px}
  input,select{width:100%;padding:11px 12px;background:var(--input);border:1px solid var(--line);border-radius:9px;color:var(--fg);font-size:14px}
  input:focus,select:focus{outline:none;border-color:var(--accent)}
  button{width:100%;margin-top:18px;padding:12px;background:var(--accent);border:0;border-radius:9px;color:#fff;font-weight:700;font-size:15px;cursor:pointer}
  button:hover{filter:brightness(1.08)}
  /* ★④ 터치/마우스 :focus 로 남는 흰 배경·잔상 제거 — 키보드 탐색(:focus-visible)만 접근성 아웃라인. */
  button:focus{outline:none}
  button:focus:not(:focus-visible){outline:none;box-shadow:none}
  button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  button.ghost{background:transparent;border:1px solid var(--line);color:var(--muted);font-weight:500;margin-top:0}
  .msg{margin-top:14px;font-size:13px;min-height:18px}
  .msg.err{color:var(--danger)} .msg.ok{color:var(--ok)}
  .pwhint{margin-top:5px;font-size:12px} .pwhint.ok{color:var(--ok)} .pwhint.err{color:var(--danger)}
  .switch{text-align:center;margin-top:16px;font-size:13px;color:var(--muted)}
  .switch a{color:var(--accent);cursor:pointer;text-decoration:none}
  /* dashboard */
  /* ★PWA 웹/앱 겸용 — 폰은 전폭, PC는 넓게 쓰되 과하게 늘어나지 않게 단계적으로.
     860px 고정이면 1440 모니터에서 좌우가 텅 비어 "모바일 화면"처럼 보인다. */
  .dash{max-width:860px;width:100%;margin:0 auto;flex:1;min-height:0;display:flex;flex-direction:column}
  @media (min-width:1024px){ .dash{max-width:1080px} }
  @media (min-width:1440px){ .dash{max-width:1320px} }
  .stack{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:20px}
  .tile{flex:1;min-width:150px;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 16px}
  .tile .k{font-size:12px;color:var(--muted)} .tile .v{font-size:20px;font-weight:700;margin-top:4px}
  .navtile{flex:1;min-width:140px;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 16px;cursor:pointer;text-align:left;color:var(--fg);margin:0;font:inherit}
  .navtile:hover{border-color:var(--muted)}
  .navtile.active{border-color:var(--accent);background:var(--active)}
  .navtile .k{font-size:12px;color:var(--muted)} .navtile .v{font-size:19px;font-weight:700;margin-top:4px}
  /* ★가로 스크롤 원천차단 — html,body 는 이미 overflow:hidden 이지만 실제 스크롤은 여기서 난다.
     자식 하나가 넘치면 화면 전체가 좌우로 밀린다(실측: 헤더 4요소가 밀어냄). */
  /* overflow-x 는 clip 을 쓴다. hidden 이면 세로가 auto 로 승격돼 중첩 스크롤 컨테이너가 된다(iOS 스크롤 불안정). */
  .tabpanel{width:100%;max-width:100%;overflow-x:clip}
  .hdrcredit{font-weight:700;font-size:14px;color:var(--ok);white-space:nowrap}
  .inst{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px}
  .inst .itop{display:flex;align-items:center;gap:8px;margin-bottom:6px}
  .inst .gpu{font-weight:700}
  .inst .kv{display:flex;gap:10px;padding:6px 0;font-size:14px;border-top:1px solid var(--line)}
  .inst .kv:first-of-type{border-top:0}
  .inst .kv .kk{color:var(--muted);min-width:110px}
  .inst .kv .kk:after{content:' :'}
  .inst .kv .vv{color:var(--fg);font-weight:600}
  .badge{font-size:11px;padding:2px 8px;border-radius:20px;font-weight:700;flex:none}
  .badge.running{background:rgba(62,207,142,.15);color:var(--ok)}
  .badge.stopped{color:var(--muted);border:1px solid var(--line)}
  .badge.stop_failed{background:rgba(255,93,108,.15);color:var(--danger)}
  .hist{display:flex;justify-content:space-between;align-items:center;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--panel);margin-bottom:8px;font-size:14px}
  .hist .amt{font-weight:700}.hist .plus{color:var(--ok)}.hist .minus{color:var(--muted)}
  .storagebox{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:18px;line-height:1.9}
  .del{margin-top:8px;padding:8px;background:transparent;border:1px solid var(--line);color:var(--muted);font-weight:600}
  .del:hover{border-color:var(--danger);color:var(--danger)}
  .addbtn{width:36px;height:36px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;font-size:21px;line-height:1;border-radius:10px;flex:none}
  /* ★키보드가 올라오면 100dvh(=키보드 포함 높이)를 쓰면 모달이 키보드 밑에 깔린다.
     --appH = visualViewport 실측 높이(키보드 뜨면 줄어듦) → 모달도 그걸 따라야 입력칸이 키보드 위로 온다.
     내용이 화면보다 길면 위쪽 정렬로 바꿔 스크롤이 가능하게 한다(가운데 정렬이면 위가 잘려 못 올라간다). */
  /* ★overscroll-behavior:contain — 없으면 모달 스크롤이 끝에 닿는 순간 뒤 화면으로 전파돼
     배경이 같이 움직이고 브라우저 당겨서새로고침까지 터진다(실측). */
  .modal{position:fixed;left:0;right:0;top:var(--appTop,0);height:var(--appH,100dvh);background:rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;z-index:50;padding:14px;overflow-y:auto;overscroll-behavior:contain;touch-action:pan-y}
  /* 키보드 영역 덮개 없음 — 덮으면 iOS 입력보조바 뒤가 비치지 않는다. 재도입 금지. */
  /* ★확인/알림 다이얼로그는 다른 모달 위에 떠야 한다. 같은 z-index(50)면 회원창 뒤에 깔려
     'PW 초기화 결과'가 뜬 줄도 모른다(실측). 항상 최상위. */
  #confModal{z-index:70}
  .modalbox{position:relative;background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:18px;width:100%;max-width:360px;max-height:calc(var(--appH,100dvh) - 28px);overflow-x:hidden;overflow-y:auto;margin:auto}
  .modalx{position:absolute;top:12px;right:12px;width:32px;height:32px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--input);border:1px solid var(--line);color:var(--muted);font-size:19px;line-height:1;cursor:pointer;z-index:3}
  .modalx:hover{color:var(--fg)}
  .modalbox h3{padding-right:34px}
  .modalbox h3{margin:0 0 16px}
  .paybtn{width:100%;margin-top:10px;padding:13px;background:var(--input);border:1px solid var(--line);border-radius:10px;color:var(--fg);font-weight:600;font-size:14px;text-align:left;display:flex;align-items:center;gap:10px}
  .paybtn:hover{border-color:var(--accent)}
  .paybtn .ic{font-size:18px}
  /* 사이드바 메뉴 (햄버거 드로어) */
  .menubtn{width:36px;height:36px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;background:transparent;border:1px solid var(--line);color:var(--fg);font-size:18px;border-radius:10px;line-height:1;cursor:pointer;flex:none}
  .sidebar{position:fixed;top:0;left:0;bottom:0;width:236px;max-width:80vw;background:var(--panel);border-right:1px solid var(--line);z-index:60;padding:60px 10px 14px;display:flex;flex-direction:column;gap:3px;overflow-y:auto;transform:translateX(-100%);transition:transform .2s ease}
  .sidebar.open{transform:translateX(0)}
  .sideoverlay{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:55}
  [dir=rtl] .sidebar{left:auto;right:0;border-right:0;border-left:1px solid var(--line);transform:translateX(100%)}
  [dir=rtl] .sidebar.open{transform:translateX(0)}
  .sideitem{width:100%;margin:0;display:flex;align-items:center;gap:11px;padding:7px 12px;background:transparent;border:0;border-radius:9px;color:var(--fg);font-size:14px;font-weight:500;letter-spacing:-.1px;text-align:left;cursor:pointer}
  .sideitem:hover{background:var(--hover)}
  .sideitem.active{background:var(--active);color:var(--accent);font-weight:600}
  .sideitem .si-ic{width:18px;height:18px;flex:none;color:var(--muted)}
  .sideitem.active .si-ic{color:var(--accent)}
  .si-badge{margin-left:auto;background:var(--line);color:var(--muted);font-size:11px;padding:1px 8px;border-radius:20px;font-weight:700}
  .si-badge:empty{display:none}
  /* ★새 문의 등 알림 카운트 뱃지(빨강) — 고객센터 메뉴에 미답변 수 표시 */
  .si-badge.alert{background:var(--danger);color:#fff}
  /* 이중처리 방지 잠금 중인 버튼 표시(전역 가드) — pointer-events는 두지 않는다(캡처 타겟 유지) */
  button.is-busy{opacity:.55;cursor:progress}
  /* ★로고를 메뉴 ★제일 상단으로(유저지시 26/08/22) — 위 여백 60px 를 로고가 차지하게 당긴다 */
  .sidebrand{font-weight:800;letter-spacing:2px;font-size:18px;padding:calc(8px + env(safe-area-inset-top)) 14px 8px;margin-top:-60px}
  .sidebrand b{color:var(--accent)}
  .sidespace{flex:none;height:8px}
  /* ★최근 대화 — 방 목록이 메뉴 안에 산다(챗지피티식 26/08/22). 남는 세로를 이 칸이 차지하고 안에서 굴린다 */
  .side-recent{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;margin-top:0}
  .side-recent .sesslist{flex:1;min-height:0;overflow-y:auto;gap:2px;padding-right:2px}
  .side-recent .sessitem{padding:8px 10px;border:none;border-radius:10px;background:transparent;gap:8px}
  .side-recent .sessitem:hover{background:var(--hover)}
  .side-recent .ss-ic{display:none}   /* 좁은 메뉴 — 말풍선 아이콘은 생략, 제목·시간만 */
  .side-recent .ss-mid{min-width:0;flex:1}
  .side-recent .ss-ttrow{min-width:0}
  .side-recent .ss-tt{font-size:13px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* ★휴지통 = 우측 끝 고정(유저지시 26/08/22) · 제목은 연필+휴지통 뿐 공간 전부 */
  .side-recent .ss-more{display:flex;flex:none;width:22px;height:22px;align-items:center;justify-content:center;padding:0;margin:0;background:none;border:none;color:var(--muted)}
  .side-recent .ss-when{display:block;margin-top:1px}
  .side-recent .ss-ttrow{display:flex;align-items:center;gap:4px}
  .side-recent .ss-tt{flex:0 1 auto;min-width:0}   /* 제목 길이만큼만 — 연필이 제목 끝에 바로 붙는다 */
  .side-recent .ss-pen{flex:none;width:18px;height:18px;padding:0;margin:0;background:none;border:none;color:var(--muted)}
  .side-recent .sessitem{align-items:center}
  .side-recent .ss-rt{flex:none}
  /* ★좁은 메뉴(236px)에서 선택 툴바가 넘쳐 버튼이 안 보였다(IMG_2457) — 줄바꿈 허용·축소 */
  .side-recent .sesstools{gap:6px;padding:6px 8px;margin:4px 0 2px}
  .side-recent .st-del,.side-recent .st-cancel{padding:6px 10px;font-size:12px}
  .side-recent .ss-when{font-size:10.5px}
  .ss-pin{margin-right:4px;font-size:11px}
  /* ★계정 단위 직렬 잠금(26/09/15) — 지금 도는 방 표시. 요란한 배지가 아니라 작은 점 하나만. */
  .ss-gendot{display:inline-block;width:6px;height:6px;margin-right:5px;border-radius:50%;
             background:#3ba55d;vertical-align:middle;animation:ssGenPulse 1.4s ease-in-out infinite}
  @keyframes ssGenPulse{0%,100%{opacity:.4}50%{opacity:1}}
  /* ★플로팅 동그라미 버튼(챗지피티식 26/08/22) — 전역 button{width:100%} 를 이기게 크기 명시 */
  .fab{width:38px;height:38px;margin-top:0;padding:0;flex:none;border-radius:50%;
       background:color-mix(in srgb,var(--panel) 88%,transparent);border:1px solid var(--line);
       color:var(--fg);display:flex;align-items:center;justify-content:center;cursor:pointer;
       box-shadow:0 2px 10px rgba(0,0,0,.25);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}
  .fab-back{position:fixed;top:calc(4px + env(safe-area-inset-top));left:10px;z-index:61;display:none}
  body.inapp .fab-back{display:flex}
  #sidebar.open ~ .fab-back{display:none}
  body.inapp:has(.modal:not(.hidden)) .fab-back{display:none}
  body.inapp:has(.lib-modal) .fab-back{display:none}   /* 라이브러리(업로드 파일)도 동일 — 그릇이 있으면 열린 상태 */   /* 설정 등 모달이 떠 있으면 메뉴버튼 숨김 — 겹침 방지(유저지적 26/08/22) */   /* 메뉴가 열리면 로고를 가리지 않게 숨긴다(IMG_2461) */   /* 로그인 화면엔 안 보임 · z-index 61 = 사이드바(60) 위 */
  .fab-right{position:fixed;top:calc(4px + env(safe-area-inset-top));right:10px;z-index:40;display:flex;gap:8px}
  .fabmenu{position:absolute;top:46px;right:0;min-width:180px;background:var(--panel);
           border:1px solid var(--line);border-radius:12px;padding:6px;display:flex;flex-direction:column;gap:2px;
           box-shadow:0 8px 24px rgba(0,0,0,.35);z-index:41}
  .fabmenu.hidden{display:none}
  .fabmenu button{width:100%;margin-top:0;padding:10px 12px;background:transparent;border:none;border-radius:8px;
                  color:var(--fg);font-size:13.5px;font-weight:500;text-align:left;cursor:pointer}
  .fabmenu button:hover{background:var(--hover)}
  .fabmenu button.danger{color:var(--danger);background:transparent}
  /* ★채팅 화면에서는 상단 로고라인(헤더)을 없앤다(유저지시 26/08/22) — 로그인 화면에선 유지 */
  body.inapp header{display:none}
  .sidefoot{margin-top:6px;border-top:1px solid var(--line);padding-top:8px}
  .sideprofile{width:100%;margin:0;display:flex;align-items:center;gap:10px;padding:9px 11px;background:var(--input);border:1px solid var(--line);border-radius:10px;color:var(--fg);cursor:pointer;text-align:left}
  .sideprofile:hover{background:var(--hover);border-color:var(--muted)}
  .sideprofile:active{transform:scale(.985)}
  .sideprofile .sp-ic{width:18px;height:18px;flex:none;color:var(--muted)}
  .sideprofile .sp-txt{display:flex;flex-direction:column;min-width:0;flex:1;gap:1px}
  .sideprofile .sp-label{font-size:10.5px;font-weight:600;color:var(--muted);line-height:1.25}
  .sideprofile .sp-email{font-size:12.5px;font-weight:500;color:var(--fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.25}
  .sideprofile .sp-chev{width:15px;height:15px;flex:none;color:var(--muted)}
  .acctinfo{display:flex;flex-direction:column;gap:7px;margin:8px 0 4px}
  .acctinfo .air{display:flex;justify-content:space-between;font-size:14px}
  .acctinfo .air .k{color:var(--muted)}
  .acctsub{font-size:13px;color:var(--muted);margin:18px 0 8px;font-weight:600;border-top:1px solid var(--line);padding-top:14px}
  .accthist{max-height:190px;overflow-y:auto}
  .accthist .hnone{color:var(--muted);font-size:13px;padding:6px 2px}
  .plancredit{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:12px 14px}
  .plancard{border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-top:10px}
  /* 등급 선택 = 탭 + 카드 + 아래 버튼(가로 스크롤 없음·모바일 우선) */
  /* ★탭 자체는 위로 붙이고(내부 top padding 최소), 위 카드와의 간격은 ★margin 으로 준다(유저확정 2026-08-03) */
  .planseg{display:flex;gap:2px;background:var(--input);border-radius:9px;padding:1px 3px 3px;margin:16px 0 10px}
  /* ★margin:0 필수 — 전역 button 규칙의 margin-top 18px 이 상속돼 탭 안 버튼이 아래로 밀렸다(실측).
     컨테이너 padding 을 줄여도 이 마진 때문에 위쪽이 계속 비어 보였다. */
  .plansegb{flex:1;width:auto;margin:0;padding:7px 2px;border:0;border-radius:7px;background:transparent;color:var(--muted);font-size:13px;font-weight:600;cursor:pointer;white-space:nowrap;letter-spacing:-.2px;transition:background .15s,color .15s}
  .plansegb.on{background:var(--bg);color:var(--fg);font-weight:800;box-shadow:0 1px 2px rgba(0,0,0,.10)}
  .plancard2{border:1px solid var(--line);border-radius:14px;padding:0 16px 4px;background:var(--bg);box-shadow:0 1px 2px rgba(0,0,0,.04)}
  .plancard2.hi{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset,0 2px 10px rgba(45,125,246,.10)}
  /* ★플랜명 위 여백을 최소로(유저확정 2026-08-03) — 14px 이면 카드 위가 회색으로 크게 비어 보인다 */
  .plancard2h{display:flex;justify-content:space-between;align-items:flex-end;padding:8px 0 10px;border-bottom:1px solid var(--line)}
  .plantag{display:inline-block;margin-left:6px;padding:2px 7px;border-radius:99px;background:var(--accent);color:#fff;font-size:10.5px;font-weight:800;letter-spacing:.2px;vertical-align:2px}
  .planrow{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:12px 0;border-bottom:1px solid var(--line)}
  .planrow:last-child{border-bottom:0}
  .planrowl{color:var(--muted);font-size:13.5px;display:flex;align-items:center;gap:7px;white-space:nowrap}
  .planrowl svg{width:15px;height:15px;flex:0 0 15px;opacity:.75}
  .planrowv{text-align:right;font-weight:800;font-size:15.5px;letter-spacing:-.2px}
  .planbadge{margin-top:12px;text-align:center;color:var(--accent);font-weight:700;font-size:13.5px;padding:13px 0;border:1px dashed var(--line);border-radius:11px}
  .plancard.cur{border-color:var(--accent)}
  /* 토스트 알림 (상용) */
  .toastwrap{position:fixed;top:calc(env(safe-area-inset-top,0px) + 14px);left:0;right:0;display:flex;flex-direction:column;align-items:center;gap:8px;z-index:120;pointer-events:none;padding:0 14px}
  .toast{pointer-events:auto;max-width:440px;width:100%;background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--muted);border-radius:10px;padding:12px 15px;font-size:14px;box-shadow:0 8px 24px rgba(0,0,0,.28);display:flex;gap:10px;align-items:flex-start;animation:toastin .22s ease}
  .toast.ok{border-left-color:var(--ok)} .toast.err{border-left-color:var(--danger)} .toast.info{border-left-color:var(--accent)}
  .toast .tic{flex:none;font-size:15px;line-height:1.4} .toast .tmsg{flex:1;line-height:1.45}
  @keyframes toastin{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
  /* 충전 진행 3단계 — 점(paydot)+라벨. pulse=진행중(노랑 깜빡), ok=완료(초록), bad=만료(빨강) */
  .paystep{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--muted);padding:3px 0}
  .paydot{width:9px;height:9px;border-radius:50%;flex:0 0 auto;background:var(--line)}
  .paydot.ok{background:var(--ok)}
  .paydot.bad{background:var(--danger)}
  .paydot.pulse{background:#f59e0b;animation:paypulse 1.1s ease-in-out infinite}
  @keyframes paypulse{0%,100%{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1.15)}}
  @media (prefers-reduced-motion:reduce){.paydot.pulse{animation:none;opacity:1}}
  .paystep.done{color:var(--ok)}
  .paystep.bad{color:var(--danger)}
  /* 확인 다이얼로그 (상용) — 안내가 길어져 글자를 줄이고 여백을 회수했다(폰 1화면에 들어가야 함). */
  .confbox{padding:18px}
  .confbox h3{font-size:16px;margin:0 0 12px}
  .confbox .confmsg{white-space:pre-line;font-size:13px;line-height:1.55;margin:0 0 14px;color:var(--fg)}
  /* 안내사항 = 약관동의서 형태. 스크롤 박스 안에 조항을 넣고, 끝까지 읽어야 동의할 수 있다.
     번호는 <ol>이 그린다(1. 2. 를 문자열에 넣으면 번역·RTL에서 깨짐). */
  .confnotice{position:relative;background:var(--input);border:1px solid var(--line);border-radius:9px;padding:10px 12px;margin:0 0 10px;max-height:180px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
  .confnotice .cn-h{position:sticky;top:-10px;background:var(--input);padding:2px 0 6px;font-size:11.5px;font-weight:700;color:var(--muted);margin:0}
  .confnotice ol{margin:0;padding-inline-start:17px;font-size:12.5px;line-height:1.5;color:var(--fg)}
  .confnotice ol li{margin:0 0 6px} .confnotice ol li:last-child{margin-bottom:0}
  /* 동의 체크 — 끝까지 읽기 전엔 잠김(회색+커서금지) */
  /* ★.hidden 이 안 먹는다 — 이건 <label>이라 뒤에 오는 .modalbox label{display:block} 가 덮어써서
     '기능 없는 체크박스'가 임대 외 확인창(공지 삭제 등)에도 그대로 보였다(실측 display:block).
     2클래스 규칙으로 확실히 숨긴다(.bdot 때와 같은 계열). */
  .cn-agree.hidden{display:none!important}
  .cn-hint.hidden{display:none!important}
  .cn-agree{display:flex;align-items:flex-start;gap:8px;font-size:12.5px;line-height:1.45;color:var(--fg);margin:0 0 8px;cursor:pointer}
  .cn-agree input{flex:0 0 auto;width:16px;height:16px;margin:1px 0 0;accent-color:var(--accent,#4b8cf7)}
  .cn-agree.locked{color:var(--muted);cursor:not-allowed}
  .cn-agree.locked input{cursor:not-allowed}
  .cn-hint{font-size:11.5px;color:var(--muted);margin:0 0 10px}
  /* 미동의 상태의 시작 버튼 = 눌리지 않음을 눈으로 보이게 */
  .confbtns button:disabled{opacity:.45;cursor:not-allowed}
  /* 결제 요약 — 버튼 바로 위. 금액이 문장에 묻히지 않게 박스로 분리(유저확정) */
  .costbox{background:var(--input);border:1px solid var(--line);border-radius:9px;padding:10px 12px;margin:0 0 12px}
  .costrow{display:flex;align-items:baseline;justify-content:space-between;gap:10px;padding:4px 0;font-size:12.5px}
  .costk{color:var(--muted);flex:0 0 auto}
  .costv{font-weight:700;text-align:right;word-break:break-all}
  .costrow.now .costv{color:#22d3ee}                       /* 지금 나가는 돈 */
  /* 계산식 줄 — 필요액이 어떻게 나왔는지 눈으로 잇는다(구성요소는 흐리게, 합계만 강조) */
  .costrow.calc .costk,.costrow.calc .costv{color:var(--muted);font-weight:600}
  .costsep{height:1px;background:var(--line);margin:6px 0 2px}
  .costwhy{font-size:11px;color:var(--muted);line-height:1.45;margin-top:8px;padding-top:8px;border-top:1px solid var(--line)}
  .costrow.need{border-top:1px solid var(--line);margin-top:4px;padding-top:8px}
  .costrow.need .costk,.costrow.need .costv{font-size:13.5px;font-weight:800}
  .costrow.need .costv{color:#f87171}                      /* 필요 최소 크레딧 */
  .costrow.have .costv{color:var(--muted)}
  .confbtns{display:flex;gap:8px} .confbtns button{flex:1;margin:0;padding:10px;font-size:14px}
  .btn-ghost{background:var(--input);border:1px solid var(--line);color:var(--fg)}
  .btn-danger{background:var(--danger);border:1px solid var(--danger);color:#fff}
  .offer-calc{color:var(--muted);font-size:12.5px;margin-top:3px}
  .setrow{margin-top:8px} .setact{width:100%;justify-content:center;padding:11px;border-radius:10px}
  .emptyst{display:flex;flex-direction:column;align-items:center;gap:12px;padding:44px 16px;color:var(--muted);text-align:center}
  .emptyst .eic{font-size:34px;opacity:.65} .emptyst .emsg{font-size:14px} .emptyst button{margin-top:2px}
  .onb-ov{position:fixed;inset:0;background:rgba(0,0,0,.74);z-index:130;display:flex;align-items:center;justify-content:center;padding:18px}
  .onb-card{background:var(--panel);border:1px solid var(--line);border-radius:16px;max-width:360px;width:100%;padding:26px 24px}
  .onb-card h3{text-align:center;margin:0 0 4px} .onb-sub{text-align:center;color:var(--muted);font-size:13px;margin-bottom:8px}
  .onb-step{display:flex;gap:12px;margin:16px 0;align-items:flex-start}
  .onb-step .n{flex:none;width:26px;height:26px;border-radius:50%;background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px}
  .onb-step .tt{font-weight:700;font-size:15px} .onb-step .dd{color:var(--muted);font-size:13px;margin-top:2px}
  .onb-card .rent{margin-top:14px}
  .sidelogout{width:100%;margin:0;display:flex;align-items:center;gap:11px;padding:9px 12px;background:transparent;border:0;border-radius:9px;color:var(--muted);font-size:13px;font-weight:500;letter-spacing:-.1px;text-align:left;cursor:pointer}
  .sidelogout:hover{background:var(--hover);color:var(--danger)}
  .sidelogout svg{width:17px;height:17px;flex:none}
  .setrow{display:flex;align-items:center;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--line);font-size:14px}
  .setval{color:var(--muted);font-weight:600}
  .seg{display:flex;gap:0;border:1px solid var(--line);border-radius:9px;overflow:hidden}
  .segbtn{width:auto;margin:0;padding:6px 14px;background:transparent;border:0;color:var(--muted);font-size:15px;border-radius:0}
  .segbtn.on{background:var(--active);color:var(--accent)}
  .setsel{width:auto;margin:0;padding:7px 12px;background:var(--input);border:1px solid var(--line);border-radius:9px;color:var(--fg);font-size:14px;font-weight:600;cursor:pointer}
  /* 기억 저장 슬롯(5칸·200자) */
  .memslots{padding:14px 0 2px}
  .memslots .ms-h{font-size:13px;font-weight:700;margin-bottom:8px}
  .memslots .ms-row{display:flex;align-items:center;gap:8px;margin-bottom:7px}
  .memslots .ms-row .ms-mk{color:var(--muted);font-weight:700;flex:none}
  .memslots .ms-row input{flex:1;margin:0;padding:9px 11px;background:var(--input);border:1px solid var(--line);border-radius:9px;color:var(--fg);font-size:13px}
  /* ★칸당 글자수 카운터(유저확정 2026-08-04) — 상한만 걸면 왜 더 안 써지는지 알 수 없다. */
  .memslots .ms-row .ms-cnt{flex:none;min-width:46px;text-align:right;font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
  .memslots .ms-row .ms-cnt.full{color:#e0245e}
  .memslots .ms-hint{font-size:11.5px;color:var(--muted);margin:2px 0 10px}
  .memslots .ms-btns{display:flex;gap:8px}
  .memslots .ms-btns button{width:auto;margin:0;flex:1;padding:9px;font-size:13px;font-weight:700;border-radius:9px;cursor:pointer}
  .memslots .ms-clear{background:transparent;border:1px solid var(--line);color:var(--muted)}
  .memslots .ms-apply{background:var(--accent);border:0;color:#fff}
  /* 키보드時 스크롤 여유(--kbH): 마지막 요소를 키보드 위로 올리려면 그 아래 여유가 필요하다. */
  .content{width:100%;flex:1;min-height:0;overflow-y:auto;padding:14px 16px calc(14px + var(--kbH,0px));display:flex;flex-direction:column}   /* ⑫ 상단 여백 축소 + ★flex column: content 가 block 이면 자식 tab-chat 의 flex:1 이 셸 하단까지 안 늘어나 입력창이 키보드 위로 뜬다. + ★v3 padding-bottom --kbH: body 가 전체높이(키보드가 덮음)라, 키보드 높이만큼 스크롤 여유를 줘야 맨아래 요소(저장버튼 등)도 키보드 위로 끌어올릴 수 있다. 스크롤 중간엔 아랫내용이 이 패딩영역(보조바 뒤)까지 그려져 CF처럼 부옇게 비친다. flex 자식(tab-chat)은 content-box 를 채우므로 채팅패널은 여전히 키보드 위에서 끝난다(독 정렬 유지). */
  /* 얇고 은은한 스크롤바(전역 — OS 기본 스크롤바 대체) */
  *{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
  ::-webkit-scrollbar{width:9px;height:9px}
  ::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px;border:2px solid transparent;background-clip:padding-box}
  ::-webkit-scrollbar-thumb:hover{background:var(--muted);background-clip:padding-box}
  ::-webkit-scrollbar-track{background:transparent}
  /* 코드모드 — 데스크톱 앱 안내 */
  .codepanel .codeinner{display:flex;flex-direction:column;align-items:center;text-align:center;padding:64px 16px;color:var(--muted)}
  .codepanel .codemark{font-size:44px;font-weight:800;color:var(--accent);letter-spacing:2px}
  .codepanel .codetitle{font-size:22px;font-weight:800;letter-spacing:1px;color:var(--fg);margin-top:14px}
  .codepanel .codedesc{font-size:14px;margin-top:10px;max-width:420px;line-height:1.55}
  .sidesep{height:1px;background:var(--line);margin:0 6px 3px}   /* 여백 축소 — 방 목록 최대한(유저지시 26/08/22 IMG_2465) */
  /* 채팅 — GPU바(상단) + 메시지(스크롤) + 입력칸(하단 고정) */
  .chatpanel{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;position:relative}   /* ★flex:1: 부모 content 가 flex 가 됐으니 flex:1 로 셸 하단까지 채워 입력창을 키보드 바 위에 붙인다(height:100% 는 flex 안에서 stretch 안 됨). / position:relative = 상단 오버레이(.chatover) 기준점 */
  /* ★상단 오버레이 — 연결상태 카드 + 기록초기화 버튼(유저확정 2026-07-31 "독립으로 공중에 붕 떠서 뒷배경이 보여야").
     래퍼는 ★투명·클릭통과, 실제 카드/버튼만 배경과 클릭을 갖는다 → 카드에 덮인 부분만 가려지고 나머지는 대화가 비친다. */
  .chatover{position:absolute;top:0;left:0;right:0;z-index:6;pointer-events:none}
  .chatover > *{pointer-events:auto}
  /* 얇은 GPU 상태 라인바 */
  .gpubar{flex:none;background:var(--panel);border:1px solid var(--line);border-radius:12px;margin-bottom:6px}   /* ⑬ 카드↔아래 버튼줄 간격 축소 */
  .gpuline{display:flex;align-items:center;gap:8px;padding:8px 14px 8px 16px;font-size:13px;flex-wrap:wrap}   /* ⑬ 세로 padding 축소(카드 얇게) */
  .gpuline .dot{width:8px;height:8px;border-radius:50%;flex:none}
  .gpuline .dot.on{background:var(--ok);box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 22%,transparent)}
  .gpuline .dot.off{background:var(--danger)}
  .gpuline .gl-label{color:var(--muted)}
  .gpuline .gl-name{font-weight:700;color:var(--fg)}
  .gpuline .gl-sub{color:var(--muted)}
  .gpuline .gl-btn{width:auto;margin:0;padding:4px 10px;font-size:11.5px;font-weight:700;border-radius:16px;background:transparent;border:1px solid var(--line);color:var(--fg);cursor:pointer;line-height:1.6}
  .gpuline .gl-btn:hover{border-color:var(--muted)}
  .gpuline .gl-spend{font-size:11.5px;font-weight:700;color:var(--ok);font-variant-numeric:tabular-nums;letter-spacing:.2px;flex:1;min-width:0}
  /* 소진·잔여 텍스트 + 새로고침 + diff 를 한 줄로 묶는 둘째 줄(세로공간 절약) */
  .gpuline2{padding:6px 14px 7px 16px;border-top:1px solid var(--line)}
  .skel{border-radius:12px;background:linear-gradient(100deg,var(--input) 30%,color-mix(in srgb,var(--input) 55%,var(--fg) 10%) 50%,var(--input) 70%);background-size:200% 100%;animation:shimmer 1.3s ease-in-out infinite}
  @keyframes shimmer{from{background-position:200% 0}to{background-position:-200% 0}}
  @media (prefers-reduced-motion:reduce){.skel{animation:none}}
  .gpuline .gl-btn.accent{background:var(--accent);border-color:var(--accent);color:#fff}
  .gpuline .gl-btn.gl-icon{margin-left:auto;padding:5px 8px;display:flex;align-items:center}
  /* ★우측 아이콘 묶음(새로고침·diff·접기토글) — 접어도 항상 보임(유저확정). 묶음 안에선 개별 margin-left:auto 무효화 */
  .gpuline .gl-right{margin-left:auto;display:inline-flex;align-items:center;gap:3px;flex:none}
  .gpuline .gl-right .gl-icon{margin-left:0}
  /* ★소진 3줄(계단식): 라벨 좌측·값 우측정렬·세로 중앙(테이블규칙) */
  .gpuline.gl-spendbox{flex-direction:column;align-items:stretch;gap:6px}
  .gl-spendbox .gl-sr{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:12.5px;line-height:1.5}
  .gl-spendbox .gl-sk{color:var(--muted)}
  .gl-spendbox .gl-sv{font-weight:700;color:var(--fg);font-variant-numeric:tabular-nums;text-align:right}
  .gl-spendbox .gl-sv.num{color:var(--ok)}
  /* ★임대 수명주기 3단계 스텝퍼(①임대중→②세팅중→③채팅시작) — 전이는 전부 자동, 배지로 진행만 표시 */
  .gpuline .gl-steps{display:inline-flex;align-items:center;gap:3px;font-size:10.5px;font-weight:700;flex-wrap:wrap}
  .gpuline .gl-step{padding:2px 8px;border-radius:12px;border:1px solid var(--line);color:var(--muted);white-space:nowrap;line-height:1.6}
  .gpuline .gl-step.done{color:var(--ok);border-color:color-mix(in srgb,var(--ok) 55%,transparent)}
  .gpuline .gl-step.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .gpuline .gl-arrow{color:var(--muted);font-size:10px;flex:none}
  /* GPU 세부정보 모달 */
  .gpubox{max-width:440px}
  .gpubox .gsec-h{font-size:12px;font-weight:800;letter-spacing:1px;color:var(--muted);text-transform:uppercase;margin:18px 0 8px}
  .gpubox .kv{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-top:1px solid var(--line);font-size:13.5px}
  .gpubox .kv .kk{color:var(--muted)} .gpubox .kv .vv{font-weight:600;text-align:right}
  .mgroup{background:var(--input);border:1px solid var(--line);border-radius:10px;padding:10px 12px;margin-bottom:8px}
  .mgroup .mg-h{display:flex;justify-content:space-between;font-size:12.5px;font-weight:700;margin-bottom:6px}
  .mgroup .mg-h .mg-use{color:var(--muted);font-weight:600}
  .mrow{display:flex;align-items:center;padding:3px 0;font-size:13px}
  .mrow .mname{color:var(--fg);display:flex;align-items:center;gap:7px}
  .mrow .mdot{display:inline-block;width:8px;height:8px;border-radius:50%;flex:none}
  .mrow .mdot.on{background:var(--ok);box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 20%,transparent)}
  .mrow .mdot.off{background:var(--danger)}
  /* 채팅 툴바(대화 비우기 · 기억 초기화) */
  .chattools{flex:none;display:flex;justify-content:flex-end;gap:8px;margin-bottom:6px}   /* ⑬ 카드↔툴바 간격 축소 */
  /* ★배경 불투명 필수(유저지적 2026-07-31 "기록초기화 버튼이 투명해서 글자가 겹쳐 지저분해"):
     오버레이(.chatover)로 띄우면서 버튼 뒤로 대화가 지나가는데, 배경이 transparent 면 글자가 그대로 비쳐 겹친다. */
  .ctool{width:auto;margin:0;padding:5px 11px;font-size:12px;font-weight:600;background:var(--panel);border:1px solid var(--line);border-radius:20px;color:var(--muted);cursor:pointer;display:flex;align-items:center;gap:6px}
  .ctool:hover{color:var(--fg);border-color:var(--muted)}
  .ctool svg{width:14px;height:14px}
  /* diff | 채팅 중앙영역 */
  .chatmid{flex:1;min-height:0;display:flex;flex-direction:column;gap:10px}
  /* ── ★멀티 대화방(유저확정 2026-08-04): 허브(목록) ↔ 방(채팅) 모드 전환 ──
     허브 = GPU 상태카드(gpuBar 재사용) + 방 목록 + 새 대화 플로팅. 방 = 상단바(뒤로·제목·diff)만.
     ★키보드 확정 배선(dock·tabpanel)은 불변 — display 전환만 한다. */
  /* ★상단바 = 맨 위에 바짝 붙은 ★얇은 줄(유저지적 "창 좁은 건 마찬가지잖아, 얇게").
     카드 박스가 아니라 반투명 띠 — 높이 최소·모서리 없음·대화가 뒤로 비치지 않게만 배경. */
  .roombar{display:none;align-items:center;gap:20px;background:color-mix(in srgb, var(--bg) 82%, transparent);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:none;border-bottom:1px solid var(--line);border-radius:0;margin:0 -2px;padding:2px 6px;pointer-events:auto}
  .roombar button{width:auto;margin:0;padding:0}   /* 전역 button(width:100%·margin-top:18px) 상속 차단 */
  .rb-back{flex:none;width:42px;height:36px;border:none;background:transparent;color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center}
  .rb-chev{width:13px;height:13px;border-left:2.2px solid currentColor;border-bottom:2.2px solid currentColor;transform:rotate(45deg);display:block;margin-left:4px}
  .rb-mid{flex:1;display:flex;align-items:center;justify-content:center;gap:8px;min-width:0}
  .rb-dot{width:8px;height:8px;border-radius:50%;background:var(--muted);flex:none}
  .rb-dot.ok{background:var(--ok)} .rb-dot.bad{background:var(--danger)}
  .rb-title{font-size:15px;font-weight:500;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:60vw}
  .rb-diff{flex:none;width:42px;height:36px;border:none;background:transparent;color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center}
  .rb-diff svg{width:19px;height:19px}   /* HTML width/height 속성보다 CSS 가 우선 — 아이콘 확대(유저지적 "아직도 좀 많이 작네") */
  .chathub{display:none;flex:1;min-height:0;overflow-y:auto;flex-direction:column;gap:8px;padding:4px 2px 90px;position:relative}
  .hub-label{font-size:13px;color:var(--muted);margin:6px 2px 0}
  /* ★묶음 삭제(26/08/22) — 머리줄(제목+[선택]) · 툴바(전체선택·개수·삭제·취소) · 선택 카드
     ★전역 button{width:100%;margin-top:18px} 에 걸리지 않게 새 버튼은 width:auto;margin-top:0 를
       ★명시한다(안 하면 [선택] 이 100% 폭을 먹어 제목이 세로로 찌부러진다 — IMG_2449 실측). */
  .hub-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:2px 2px 0}
  .hub-head .hub-label{margin:0;white-space:nowrap;flex:none}
  .hub-sel{width:auto;margin-top:0;flex:none;background:none;border:none;color:var(--accent);font-size:14px;font-weight:600;cursor:pointer;padding:4px 6px}
  .sesstools{display:flex;align-items:center;gap:10px;margin:8px 2px 2px;padding:8px 10px;background:var(--panel);border:1px solid var(--line);border-radius:12px}
  .sesstools.hidden{display:none}
  .st-all{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--fg);cursor:pointer;white-space:nowrap}
  .st-all input{width:18px;height:18px;margin:0;flex:none;accent-color:var(--accent)}
  .st-txt{display:flex;flex-direction:column;align-items:flex-start;line-height:1.25}   /* 전체 위 / N개 선택 아래(유저지시 26/08/22 IMG_2464) */
  .st-cnt{font-size:11px;color:var(--muted);white-space:nowrap;margin-top:1px}
  .st-del{width:auto;margin-top:0;margin-left:auto;flex:none;background:var(--danger);color:#fff;border:none;border-radius:9px;padding:8px 14px;font-size:13px;font-weight:600;cursor:pointer}
  .st-del:disabled{opacity:.4;cursor:default}
  .st-cancel{width:auto;margin-top:0;flex:none;background:none;border:1px solid var(--line);color:var(--muted);border-radius:9px;padding:8px 12px;font-size:13px;cursor:pointer}
  .sessitem.picking{cursor:default}
  .sessitem.picking.on{border-color:var(--accent);background:var(--hover)}
  .sessitem .ss-ck{width:20px;height:20px;margin:0;flex:none;accent-color:var(--accent)}
  .sesslist{display:flex;flex-direction:column;gap:10px}
  .sessitem{display:flex;align-items:center;gap:12px;background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:14px 12px 14px 14px;cursor:pointer;transition:background .12s}
  .sessitem:hover{background:var(--hover)}
  .ss-ic{flex:none;width:38px;height:38px;border-radius:12px;background:var(--input);color:var(--accent);display:flex;align-items:center;justify-content:center}
  .ss-mid{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
  .ss-ttrow{display:flex;align-items:center;gap:6px;min-width:0}
  .ss-tt{font-size:14.5px;font-weight:600;color:var(--fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ss-pen{flex:none;width:22px;height:20px;border:none;background:transparent;color:var(--muted);opacity:.45;cursor:pointer;padding:0;margin:0;display:flex;align-items:center;justify-content:center}
  .ss-pen:hover{opacity:1;color:var(--accent)}
  .ss-pv{font-size:12.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ss-rt{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:2px}
  .ss-when{font-size:11.5px;color:var(--muted)}
  .ss-more{width:34px;height:30px;border:none;background:transparent;color:var(--muted);opacity:.8;cursor:pointer;line-height:1;padding:0;margin:0;display:flex;align-items:center;justify-content:center}
  .ss-more:hover{opacity:1;color:var(--danger)}
  .newsess{position:sticky;bottom:14px;align-self:flex-end;width:auto;margin:8px 6px 0 0;padding:11px 18px;border:none;border-radius:24px;background:var(--accent);color:#fff;font-size:14px;font-weight:600;cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,.25)}
  /* ── ★코드모드(데스크톱 앱 전용) 2열 화면(유저확정 2026-08-04) ── */
  #tab-code:not(.hidden){display:flex;flex-direction:column;flex:1 1 auto;min-height:0}
  .content:has(#tab-code:not(.hidden)){padding-top:4px}   /* ★코드모드 상단 여백 축소(유저지적 "상단 내부 패딩이 너무 커") */
  .codeapp{display:flex;flex:1;min-height:0;gap:10px}
  .code-side{flex:none;width:var(--codeW,232px);min-width:150px;max-width:420px;display:flex;flex-direction:column;gap:6px;padding:2px 4px 2px 0}
  .code-resizer{flex:none;width:5px;cursor:col-resize;background:transparent;border-left:1px solid var(--line)}   /* ★사이드바 좌우 리사이즈(유저확정) */
  .code-resizer:hover{border-left-color:var(--accent)}
  .code-topbar{flex:none;display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--line);padding:1px 4px;margin-bottom:2px}   /* ★얇은 상단바 — 채팅 방 상단바 스타일 */
  .ct-title{flex:1;text-align:center;font-size:13.5px;font-weight:500;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* ★유저지적 "너무 넓다" — 채팅방용 42×36 rb-diff 를 그대로 써서 띠가 높아졌다 → 코드모드 상단바만 축소.
     ★전역 button(width:100%·margin-top:18px·padding:12px) 리셋 필수 — 없으면 24px 버튼에 상하 패딩 12px 로
     콘텐츠가 0 이 돼 아이콘이 통째로 사라진다(유저 실측 "diff가 안 보이고"). roombar 와 같은 차단. */
  .code-topbar button{width:auto;margin:0;padding:0;background:transparent}
  /* ★3모드 칩+펼침 메뉴(유저확정: 폴더선택 옆 · 누르면 3개+설명) — 완전자동은 빨강 강조 */
  #codeModeChip.full{color:#e66;border-color:#e66}
  /* ★＋버튼·미리보기(챗 동일 형식) — 전역 button 리셋 필수(oops 5회 재발 항목) */
  /* ＋ = 전송 버튼과 ★같은 40×40 로 맞춰 좌우 균형·세로 중앙을 시각적으로도 일치시킨다 */
  .code-add{flex:none;width:40px;height:40px;margin:0;padding:0;background:transparent;border:0;color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:50%}
  .code-add:disabled{opacity:.35;cursor:default}
  .code-add:hover{color:var(--fg)}
  #codePrevStrip{display:flex;gap:6px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding:4px 0}
  #codePrevStrip.hidden{display:none}
  .code-modepop{position:absolute;bottom:100%;left:8px;margin-bottom:6px;background:var(--input);border:1px solid var(--line);border-radius:12px;padding:6px;display:flex;flex-direction:column;gap:4px;z-index:40;box-shadow:0 6px 24px rgba(0,0,0,.4)}
  .code-modepop.hidden{display:none}
  .cmp-item{width:auto;margin:0;padding:7px 12px;background:transparent;border:1px solid transparent;border-radius:9px;text-align:left;cursor:pointer;display:block}
  .cmp-item.on{border-color:var(--line)}
  .cmp-item.danger .cmp-t{color:#e66}
  .cmp-t{font-size:12.5px;font-weight:700}
  .cmp-d{font-size:11px;color:var(--muted);margin-top:2px}
  /* ★도구 진행 카드 — 에이전트 루프의 스텝별 한 줄 표시(📖 읽기·🔍 검색·✏️ 쓰기·▶ 실행) */
  .code-toolcard{align-self:flex-start;max-width:92%;font-size:11.5px;color:var(--muted);background:var(--input);border:1px solid var(--line);border-radius:8px;padding:3px 9px;margin:1px 0;white-space:pre-wrap;word-break:break-all}
  .code-toolcard.write{color:#7c8}
  .code-toolcard.run{color:#8ac}
  .code-toolcard.err,.code-toolcard.danger{color:#e66;border-color:#e66}
  /* ★작업 중계(유저확정 2026-08-05): 설명 문장 · 접이식 판단과정 · 펼치는 도구카드(diff) */
  .code-note{align-self:flex-start;max-width:92%;font-size:12.5px;color:var(--fg);margin:4px 0 2px;line-height:1.5}
  .code-think{align-self:flex-start;max-width:92%;margin:1px 0}
  /* ★전역 button{width:100%;margin-top:18px;padding:12px} 리셋 필수 — 안 하면 버튼이 뭉개진다(oops 5회 재발 항목) */
  .code-think .ct-h{background:none;border:0;color:var(--muted);font-size:11.5px;cursor:pointer;width:auto;margin:0;padding:2px 0}
  .code-think .ct-b{font-size:11.5px;color:var(--muted);background:var(--input);border:1px solid var(--line);border-radius:8px;padding:6px 9px;margin-top:3px;white-space:pre-wrap;max-height:260px;overflow:auto}
  /* ★상용 수준 작업 카드(유저확정 2026-08-05 "클로드코드/코덱스/커서처럼") —
     [아이콘][라벨][부가정보][상태칩] 한 줄 + 펼침 diff. 흐름은 좌측 가이드선으로 묶는다. */
  /* ★content-visibility=화면 밖 카드는 렌더 계산 생략(카드 수천 개 방 대책) — 스크롤로 보일 때만 계산 */
  .cstep{align-self:stretch;max-width:100%;margin:0;padding:0 0 0 14px;position:relative;content-visibility:auto;contain-intrinsic-size:auto 40px}
  .cstep::before{content:'';position:absolute;left:4px;top:2px;bottom:2px;width:1.5px;background:var(--line);border-radius:1px}
  /* ★개행을 살린다(유저지적 2026-08-06: diff 안 ★긴 생각이 줄바꿈 없이 뭉쳐 무슨 말인지 이해 불가).
     innerHTML 로 넣는데 white-space 가 기본값(normal)이라 ★모든 개행이 공백 하나로 접혔다.
     짧은 설명은 티가 안 나고 긴 설명일수록 통째로 뭉쳐 보였다. */
  /* ★모드 전환 배너 — 대화 로그가 아니라 화면 상단에 얇게. 전환이 끝나면 노드째 사라진다. */
  .modebanner{position:sticky;top:0;z-index:30;margin:0 0 6px;padding:7px 12px;border-radius:8px;
    background:var(--panel);border:1px solid var(--line);color:var(--muted);font-size:12.5px;text-align:center}
  .cstep-note{font-size:13px;line-height:1.62;color:var(--fg);margin:6px 0 4px;white-space:pre-wrap;word-break:break-word}
  .cstep-note .cinl{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;padding:1px 5px;border-radius:5px;background:var(--input);border:1px solid var(--line);color:var(--fg)}
  .crow{display:flex;align-items:center;gap:8px;width:auto;margin:2px 0;padding:6px 10px;border:1px solid var(--line);border-radius:10px;background:var(--panel);cursor:default;text-align:left;max-width:100%}
  .crow.tap{cursor:pointer}
  .crow.tap:hover{background:var(--input)}
  .crow .ci{flex:none;width:15px;height:15px;color:var(--muted);display:flex;align-items:center;justify-content:center}
  .crow .cl{flex:none;font-size:12.5px;font-weight:600;color:var(--fg)}
  .crow .cs{flex:1 1 auto;min-width:0;font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,Consolas,monospace}
  .crow .cst{flex:none;font-size:11px;padding:1px 7px;border-radius:999px;border:1px solid var(--line);color:var(--muted)}
  .crow .cst.ok{color:#5cb87a;border-color:#5cb87a55}
  .crow .cst.bad{color:#e06c6c;border-color:#e06c6c55}
  .crow .cspin{flex:none;width:12px;height:12px;border:2px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:cspin .7s linear infinite}
  @keyframes cspin{to{transform:rotate(360deg)}}
  /* ★★★되묻기 카드(유저확정 2026-08-12: 막연한 요청이면 ★필요한 사항을 유저한테 물어보고
     ★선택박스를 클릭하게끔 / 같은 자리가 계속 막혀도 ★되묻기). 답은 대화로 들어가 계획·검수 기준이 된다. */
  /* ★★전역 button{width:100%;margin-top:18px;padding:12px;font-weight:700} 를 ★반드시 리셋한다 —
     이 함정은 지금까지 ★6번 재발했다(oops 기록). 새 버튼을 만들 때마다 width·margin 을 되돌린다. */
  .cask button{width:auto;margin:0;font-weight:400}
  .cask{margin:4px 0 8px;border:1px solid var(--line);border-radius:12px;background:var(--panel);padding:10px 12px}
  .cask-h{font-size:12.5px;color:var(--muted);margin:0 0 8px}
  .cask-q{margin:0 0 10px}
  .cask-t{font-size:13.5px;margin:0 0 6px;line-height:1.45}
  .cask-os{display:flex;flex-wrap:wrap;gap:6px}
  .cask-o{padding:6px 12px;border:1px solid var(--line);border-radius:999px;background:transparent;
    color:inherit;font-size:12.5px;cursor:pointer;text-align:left;max-width:100%}
  .cask-o:hover{border-color:var(--accent)}
  .cask-o.on{border-color:var(--accent);background:var(--accent);color:#fff}
  .cask-in{width:100%;margin-top:6px;padding:6px 10px;border:1px solid var(--line);border-radius:10px;
    background:transparent;color:inherit;font-size:12.5px}
  .cask-b{display:flex;gap:8px;margin-top:4px}
  .cask-go{padding:7px 16px;border:0;border-radius:10px;background:var(--accent);color:#fff;
    font-size:13px;cursor:pointer}
  .cask-go[disabled]{opacity:.45;cursor:default}
  .cask-skip{padding:7px 14px;border:1px solid var(--line);border-radius:10px;background:transparent;
    color:var(--muted);font-size:13px;cursor:pointer}
  .cask.done .cask-o,.cask.done .cask-in,.cask.done .cask-go,.cask.done .cask-skip{pointer-events:none;opacity:.55}
  .cdiff{margin:2px 0 6px;border:1px solid var(--line);border-radius:10px;overflow:hidden}
  .cdiff-h{padding:5px 10px;font-size:11.5px;color:var(--muted);background:var(--panel);border-bottom:1px solid var(--line);font-family:ui-monospace,Menlo,Consolas,monospace}
  .cdiff-b{max-height:340px;overflow:auto;background:var(--input)}
  .cdl{display:flex;font:11.5px/1.6 ui-monospace,Menlo,Consolas,monospace;white-space:pre}
  .cdl .cdn{flex:none;width:52px;text-align:right;padding:0 8px;color:var(--muted);opacity:.65;user-select:none;background:rgba(127,127,127,.06)}
  .cdl .cdt{flex:1 1 auto;padding:0 10px;color:var(--fg);overflow-wrap:anywhere;white-space:pre-wrap}
  .cdl.add{background:rgba(70,180,110,.12)} .cdl.add .cdt{color:#7fd39b}
  .cdl.del{background:rgba(220,90,90,.12)} .cdl.del .cdt{color:#f0a0a0}
  .code-tool{align-self:flex-start;max-width:92%;margin:1px 0}
  .code-tool .ct-row{background:var(--input);border:1px solid var(--line);border-radius:8px;width:auto;margin:0;padding:3px 9px;font-size:11.5px;color:var(--muted);cursor:pointer;text-align:left;max-width:100%;word-break:break-all}
  .code-tool.write .ct-row{color:#7c8}
  .code-tool.run .ct-row{color:#8ac}
  .code-tool.err .ct-row{color:#e66;border-color:#e66}
  .code-tool .ct-d{margin-top:3px;background:var(--input);border:1px solid var(--line);border-radius:8px;padding:6px 9px;font-size:11px;font-family:ui-monospace,Menlo,Consolas,monospace;max-height:320px;overflow:auto}
  .code-tool .ct-l{white-space:pre-wrap;word-break:break-all;color:var(--muted)}
  .code-tool .ct-l.add{color:#7c8}
  .code-tool .ct-l.del{color:#e88}
  .code-topbar .rb-diff{width:28px;height:24px}
  .code-topbar .rb-diff svg{width:15px;height:15px}
  /* ★코드모드 = 전폭 화면(유저지적 "창 넓히면 붕 떠 있어") — dash 의 중앙 max-width(860~1320px)를 풀어
     좌측 메뉴가 창 왼쪽 끝에 붙게 한다(데스크톱 앱 전용 화면이라 모바일 영향 없음). */
  .dash:has(#tab-code:not(.hidden)){max-width:none}
  .cs-row{display:flex;align-items:center;gap:6px}
  .cs-del{flex:none;width:26px;height:24px;border:none;background:transparent;color:var(--muted);opacity:.55;cursor:pointer;padding:0;margin:0;display:flex;align-items:center;justify-content:center}
  .cs-del:hover{opacity:1;color:var(--danger)}
  .code-gpu{display:flex;align-items:center;gap:7px;background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:7px 10px;font-size:12.5px;color:var(--muted)}
  .code-sesslist{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:6px}
  /* ★삭제가 도는 동안 — 항목은 ★포인터를 아예 안 받는다(클릭·개별삭제·이름변경 전부 차단).
     스크롤은 살려 두려고 컨테이너가 아니라 ★항목에만 건다. */
  .code-sesslist.deling .code-sessitem{pointer-events:none;opacity:.45}
  /* ★선택 삭제 바(유저확정 2026-08-06 "체크박스 만들고 항목별로 체크해서 삭제 버튼으로 한방에") */
  /* ★한 줄로 얇게(유저지적 "전체선택은 굳이 적을 필요 없고, 아래위 너무 넓잖아 — 얇게 한 줄로") */
  /* ★★전역 button{width:100%;margin-top:18px;padding:12px} 리셋을 ★반드시 끊는다.
     이 상속 함정은 ★6번째 재발이다 — 이번엔 margin-top:18px 가 먹어 삭제 버튼만 아래로 밀려
     체크박스와 세로가 어긋났다(유저지적 "체크박스는 중앙보다 살짝 위, 선택삭제는 아래에 붙어 있고").
     둘 다 ★같은 높이 상자로 만들고 flex 로 세로 중앙에 세운다. */
  /* ★margin 을 주지 않는다 — 목록(.code-sesslist)이 이미 gap:6px 을 주므로 여기에 margin-bottom 을
     더하면 ★아래만 12px 이 되어 위아래가 어긋난다(유저지적 "아래 여백이 좀 더 넓어"). 간격은 gap 에 맡긴다. */
  .cs-selbar{display:flex;align-items:center;gap:8px;height:18px;padding:0 4px;margin:0;line-height:1}
  .cs-selbar input{width:13px;height:13px;margin:0;padding:0;flex:none;display:block;cursor:pointer;accent-color:var(--accent)}
  .cs-selbar .cs-selspace{flex:1}
  .cs-selbtn{width:auto;margin:0;height:18px;display:flex;align-items:center;justify-content:center;font-size:11px;
             font-weight:500;line-height:1;padding:0 8px;border:1px solid var(--line);border-radius:5px;
             background:transparent;color:var(--muted);cursor:pointer;white-space:nowrap}
  .cs-selbtn:disabled{opacity:.35;cursor:default}
  .cs-selbtn.on{color:#e5484d;border-color:#e5484d}
  .cs-chk{width:13px;height:13px;margin:0;padding:0;flex:none;display:block;cursor:pointer;accent-color:var(--accent)}
  /* ★한 줄로 얇게(유저지적 "아래위 너무 넓잖아 — 그냥 얇게 한 줄로 깔끔하게") */
  .code-sessitem{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:5px 8px;cursor:pointer}
  .code-sessitem:hover{background:var(--hover)}
  .code-sessitem.on{border-color:var(--accent)}
  .cs-tt{font-size:12.5px;font-weight:600;color:var(--fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.5}
  .cs-pv{font-size:11.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
  .code-newbtn{width:100%;margin:0;padding:9px;border:none;border-radius:10px;background:var(--accent);color:#fff;font-size:13px;font-weight:600;cursor:pointer}
  .code-main{flex:1;min-width:0;display:flex;flex-direction:column}
  /* ★contain=레이아웃 격리(2026-08-07 유저 실기기 "채팅 치는데 뚝뚝 끊겨") — 입력칸 높이 재계산이
     카드 수천 개짜리 메시지 트리 전체 리플로우로 번지던 것을 차단(스크롤 컨테이너라 시각 변화 없음) */
  .code-msgs{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:10px;padding:4px;contain:layout paint}
  /* ★에이전트 화면: 이름 헤더+날짜시간은 ★항상 표시(유저확정 "서비스 이름은 항상 떠있어야지 날짜시간이랑").
     footer(복사·tok/s·컨텍스트)만 평소 숨김 → ★마우스 올리면 표시. userfoot(버블 뒤 형제)는 + 로 잡는다. */
  #codeMsgs .chatfoot,#codeMsgs .userfoot{opacity:0;transition:opacity .15s ease}
  #codeMsgs .bubble.ai:hover .chatfoot{opacity:1}
  #codeMsgs .bubble.user:hover + .userfoot{opacity:1}
  #codeMsgs .userfoot:hover,#codeMsgs .chatfoot:hover{opacity:1}
  /* 재생성·편집은 에이전트 배선 전이라 숨김(본채팅 함수 재사용分 — 눌리면 본채팅 상태를 건드린다) */
  #codeMsgs .cf-regen,#codeMsgs .uf-edit{display:none}
  .code-dock{flex:none;display:flex;flex-direction:column;gap:6px;padding:4px 0 6px}
  .code-chips{display:flex;gap:6px;position:relative}   /* relative = 모드 펼침 메뉴(absolute)의 기준 */
  .code-chip{display:inline-flex;align-items:center;gap:5px;width:auto;margin:0;padding:5px 10px;border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--muted);font-size:12px;cursor:pointer}
  .code-chip:hover{background:var(--hover);color:var(--fg)}
  /* ★세로 중앙정렬(유저확정 2026-08-05 "채팅입력칸이랑 + 랑 대각선이잖아, 위아래 중앙정렬이 안 돼 있잖아").
     flex-end 였던 탓에 크기가 다른 ＋·입력칸·전송이 바닥선만 맞아 어긋나 보였다. */
  .code-inputrow{display:flex;align-items:center;gap:8px}
  .code-inputrow textarea{flex:1;min-height:42px;max-height:160px;resize:none;border:1px solid var(--line);border-radius:12px;background:var(--input);color:var(--fg);padding:11px 13px;font:14px/1.5 inherit;outline:none}
  .code-inputrow textarea:disabled{opacity:.6}
  .code-send{flex:none;width:40px;height:40px;margin:0;padding:0;border:none;border-radius:50%;background:var(--accent);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center}
  .code-send:disabled{opacity:.35;cursor:default}
  #tab-chat.hubmode .chatover{position:static;pointer-events:auto}
  #tab-chat.hubmode .gpubar .gl-icon:not(.gl-toggle){display:none}   /* ★허브에선 diff(생성결과) 버튼 제거 — 방 상단바로 이사(유저지적) */
  #tab-chat .chattools{display:none}   /* ★비우기 버튼 줄 폐기(유저지적 "위쪽 여백 커") — 상단바 아이콘으로 이사. --overH 실측이 그만큼 줄어 채팅이 위로 붙는다 */
  #tab-chat.hubmode .chatmid,#tab-chat.hubmode .chatdock,#tab-chat.hubmode .scrollbtm,#tab-chat.hubmode .chattools{display:none}
  #tab-chat.hubmode #chatHub{display:flex}
  #tab-chat:not(.hubmode) .gpubar{display:none}
  /* (roomBar 폐지 26/08/22) 표시 규칙 제거 — 상단 선(border-bottom)이 이 규칙으로 살아나 보였다(IMG_2455) */
  .diffpanel{flex:none;max-height:42%;overflow:auto;background:var(--input);border:1px solid var(--line);border-radius:12px;padding:10px 12px;margin-top:var(--overH,0px)}   /* ★상단 오버레이(상단바) 아래에서 시작 — 유저지적 "diff 열면 생성결과가 아예 안 보여"(위 29px 가림) */
  .diffpanel .diffhead{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
  .diffpanel .diffhead #panelTitle{font-size:12.5px;font-weight:800;letter-spacing:.5px;color:var(--muted);text-transform:uppercase}
  .diffpanel .diffclear{width:auto;margin:0;padding:4px 10px;font-size:11.5px;font-weight:700;background:transparent;border:1px solid var(--line);border-radius:16px;color:var(--danger);cursor:pointer}
  /* ★diff = 가로 한 줄 + 우측 스크롤(유저확정) — 썸네일이 줄바꿈 없이 옆으로 이어진다 */
  .diffbody{font:12.5px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:var(--muted);white-space:nowrap;overflow-x:auto;overflow-y:hidden;padding-bottom:4px}
  .diffbody .empty{color:var(--muted);opacity:.7}
  .diffbody .dl{padding:0 4px;border-radius:3px}
  .diffbody .dl.add{background:color-mix(in srgb,var(--ok) 16%,transparent);color:var(--ok)}
  .diffbody .dl.del{background:color-mix(in srgb,var(--danger) 16%,transparent);color:var(--danger)}
  /* ★생성결과(diff) 썸네일 그리드 — 생성된 이미지/동영상 + 개별 × 삭제. 클릭=라이트박스 */
  .diffbody .pitem{position:relative;display:inline-block;margin:6px 8px 2px 0;vertical-align:top}
  .diffbody .pi-thumb{max-width:96px;max-height:96px;border-radius:8px;border:1px solid var(--line);display:block}
  .diffbody .pi-x{position:absolute;top:-7px;right:-7px;width:21px;height:21px;padding:0;border:none;border-radius:50%;background:var(--danger);color:#fff;font-weight:700;font-size:14px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
  /* ★이미지 라이트박스(큰 화면) — 배경/Esc/× 로 닫기 */
  .lightbox{position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.9);display:flex;align-items:center;justify-content:center;padding:20px}
  .lightbox .lb-img{max-width:96vw;max-height:92vh;border-radius:8px;object-fit:contain}
  .lightbox .lb-x{position:absolute;top:14px;right:14px;width:44px;height:44px;padding:0;border:none;border-radius:50%;background:rgba(255,255,255,.14);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center}
  .lightbox .lb-x:hover{background:rgba(255,255,255,.26)}
  .lightbox .lb-dl{position:absolute;top:14px;right:66px;width:44px;height:44px;padding:0;border:none;border-radius:50%;background:rgba(255,255,255,.14);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center}
  .lightbox .lb-dl:hover{background:rgba(255,255,255,.26)}
  /* ★생성 미디어 결과 wrapper + 우상단 다운로드(SVG·이모지 금지) */
  .medwrap{position:relative;display:inline-block;max-width:100%}
  /* ★결과 이미지/영상 미리보기는 작게 — 클릭(이미지)/확대버튼(영상)으로 크게(유저확정) */
  .medwrap .medel{max-width:min(320px,100%);max-height:240px;border-radius:8px;display:block;object-fit:contain}
  .medwrap .medz{position:absolute;top:8px;right:48px;width:34px;height:34px;padding:0;border:none;border-radius:9px;background:rgba(0,0,0,.55);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:.85}
  .medwrap .medz:hover{opacity:1;background:rgba(0,0,0,.75)}
  /* ★첨부 미리보기(클로드 스타일·유저확정): 유저버블/처리중버블에 작은 썸네일 */
  .att-thumb{max-width:180px;max-height:120px;border-radius:8px;display:block;margin:0 0 8px;cursor:zoom-in;object-fit:cover}
  .medwrap .medl{position:absolute;top:8px;right:8px;width:34px;height:34px;padding:0;border:none;border-radius:9px;background:rgba(0,0,0,.55);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:.85}
  .medwrap .medl:hover{opacity:1;background:rgba(0,0,0,.75)}
  /* ★소진박스 새로고침 행 — 라벨 좌·아이콘 우 */
  .gl-spendbox .gl-refrow{justify-content:space-between}
  .gl-spendbox .gl-refrow .gl-icon{margin:0;padding:4px 7px;border:1px solid var(--line);border-radius:8px;color:var(--muted)}
  .gl-spendbox .gl-refrow .gl-icon:hover{color:var(--fg);border-color:var(--muted)}
  /* ★padding-top = 상단 오버레이 높이(--overH·JS 실측). 콘텐츠는 오버레이 아래에서 시작하되,
     스크롤하면 그 뒤로 지나간다(가려지는 게 아니라 비친다). 오버레이가 접히면 --overH 도 같이 준다. */
  .chatmsgs{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:10px;padding:4px;padding-top:calc(4px + var(--overH,68px) + env(safe-area-inset-top));contain:layout paint}
  .chatwarn{align-self:stretch;margin:2px 4px;padding:9px 12px;background:rgba(224,160,58,.13);border:1px solid rgba(224,160,58,.5);border-radius:9px;color:var(--fg);font-size:12.5px;line-height:1.5;text-align:center}
  .chatmsgs .emptyhint{margin:auto;text-align:center;color:var(--muted)}
  .chatmsgs .emptyhint img{width:44px;height:auto;opacity:.85;filter:drop-shadow(0 4px 14px color-mix(in srgb, var(--accent) 45%, transparent))}
  .chatmsgs .emptyhint .eh-t{margin-top:10px;font-size:15px;font-weight:600;color:var(--fg)}
  .chatmsgs .emptyhint .eh-s{margin-top:4px;font-size:12.5px}
  /* ★빈 화면 예시 프롬프트 칩(클릭=입력칸 삽입·유저확정) */
  .chatmsgs .emptyhint .eh-chips{margin-top:18px;display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:440px}
  .chatmsgs .emptyhint .eh-chip{width:auto;min-width:0;margin:0;padding:8px 14px;background:var(--input);border:1px solid var(--line);border-radius:16px;font-size:13px;font-weight:500;color:var(--fg);cursor:pointer;transition:border-color .15s,background .15s}
  .chatmsgs .emptyhint .eh-chip:hover{border-color:var(--accent);background:var(--hover)}
  /* ── 메시지 칸분리(유저확정): 유저=우측 약한강조 / AI=전폭 문서형(클로드/챗지피티식) ── */
  .bubble{max-width:100%;font-size:14px;line-height:1.65;word-break:break-word}
  .bubble.user{align-self:flex-end;max-width:80%;padding:9px 13px;border-radius:14px;background:color-mix(in srgb, var(--accent) 15%, var(--panel));border:1px solid color-mix(in srgb, var(--accent) 28%, transparent);color:var(--fg);white-space:pre-wrap}
  .qbubble{align-self:flex-end;max-width:80%;display:flex;flex-direction:column;gap:7px;padding:10px 13px 9px;border-radius:14px;background:color-mix(in srgb, var(--accent) 5%, var(--panel));border:1px dashed color-mix(in srgb, var(--accent) 32%, var(--line));opacity:.92}
  .qbubble .qb-head{display:flex;align-items:center;gap:7px}
  .qbubble .qb-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 9px;border-radius:20px;background:color-mix(in srgb, var(--accent) 13%, transparent);color:var(--accent);font-size:11px;font-weight:700;letter-spacing:-.1px;white-space:nowrap}
  .qbubble .qb-badge .qb-dot{width:6px;height:6px;border-radius:50%;background:var(--accent);animation:qbpulse 1.4s ease-in-out infinite}
  .qbubble .qb-num{font-size:11px;font-weight:600;color:var(--muted)}
  .qbubble .qb-text{white-space:pre-wrap;word-break:break-word;font-size:14px;line-height:1.55;color:var(--fg)}
  .qbubble .qb-ctl{display:flex;justify-content:flex-end;gap:6px;margin-top:1px}
  .qbubble .qb-btn{width:auto;min-width:0;margin:0;padding:3px 11px;background:transparent;border:1px solid var(--line);border-radius:8px;font-size:11.5px;font-weight:600;line-height:1;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;gap:4px}
  .qbubble .qb-btn.edit:hover{border-color:var(--accent);color:var(--accent)}
  .qbubble .qb-btn.del:hover{border-color:var(--danger);color:var(--danger)}
  @keyframes qbpulse{0%,100%{opacity:1}50%{opacity:.3}}
  .bubble.ai{align-self:stretch;max-width:100%;padding:2px 0 4px;background:transparent;border:0}
  .bubble.ai>.chathead{display:flex;align-items:baseline;gap:7px;margin:0 0 5px;flex-wrap:nowrap}
  .bubble.ai>.chathead>span{white-space:nowrap;flex:none}   /* ★이름·시간 줄바꿈 방지 */
  .bubble.ai>.chathead .ch-name{font-size:11.5px;font-weight:800;letter-spacing:.04em;color:var(--accent);opacity:.9}
  .bubble.ai>.chathead .ch-time{font-size:10.5px;color:var(--muted);opacity:.55;white-space:nowrap}
  .bubble.sys{align-self:center;background:transparent;color:var(--muted);font-size:13px;text-align:center;max-width:100%;white-space:pre-wrap}
  .bubble.ai img,.bubble.ai video{max-width:100%;border-radius:10px}
  .bubble .reasonbox{margin:2px 0 8px}
  /* ★대화 정리(압축) 안내 — 검색 카드와 같은 규격(같은 자리에 뜨므로 모양이 달라지면 어색하다).
     ㄴ답이 아니라 ★상태를 알리는 카드다: 무슨 일인지 · 얼마나 남았는지 · 닫아도 되는지. */
  /* 대기 안내(chat_wait.js) — 자리가 없어 기다리는 동안 뜬다.
     ★압축 카드와 같은 결로 둔다: 손님에게 둘은 '지금은 못 하지만 곧 된다' 는 같은 성격의 말이다. */
  .wtcard{display:flex;flex-direction:column;gap:5px;margin:2px 0 8px;font-size:13px;color:var(--muted);line-height:1.55;border:1px solid var(--line);background:var(--panel);border-radius:10px;padding:10px 12px;max-width:100%}
  .wtcard .wtHead{color:var(--fg);opacity:.92;font-weight:600}
  .wtcard .wtSub{font-size:13px;opacity:.9}
  .wtcard .wtLine{font-size:12px;opacity:.7}
  .wtcard .wtLine:empty{display:none}
  .cmpcard{display:flex;flex-direction:column;gap:6px;margin:2px 0 8px;font-size:13px;color:var(--muted);line-height:1.5;border:1px solid var(--line);background:var(--panel);border-radius:10px;padding:9px 12px;max-width:100%}
  .cmpcard .cmprow1{display:flex;align-items:center;gap:8px;min-width:0}
  .cmpcard .cmplab{flex:none;color:var(--fg);opacity:.9;font-weight:600}
  .cmpcard .cmprow2{font-size:13px;opacity:.9}
  .cmpcard .cmprow3{font-size:12px;opacity:.7;line-height:1.5}
  /* 점은 검색 카드와 같은 애니메이션을 쓴다 — 규칙을 새로 만들지 않는다(어긋남 방지) */
  .cmpcard .cmpdot{width:6px;height:6px;border-radius:50%;background:var(--muted);flex:none;animation:typingdot 1.25s infinite ease-in-out}
  /* ★웹검색 진행 표시(유저확정 2026-07-31·ChatGPT 레퍼런스): "<검색어> 검색 중" 회색 한 줄.
     답변 첫 토큰이 오면 사라진다. */
  .websearching{display:flex;flex-direction:column;gap:7px;margin:2px 0 8px;font-size:13px;color:var(--muted);line-height:1.5;border:1px solid var(--line);background:var(--panel);border-radius:10px;padding:9px 12px;max-width:100%}
  .websearching .wsrow1{display:flex;align-items:center;gap:8px;min-width:0}
  .websearching .wslab{flex:none;color:var(--fg);opacity:.8}
  .websearching .wssep{flex:none;opacity:.35}
  .websearching .wsq{opacity:.85;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
  .websearching .wsnote{font-size:12px;opacity:.7;line-height:1.5}
  .websearching .wssites{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .websearching .wsst{display:inline-flex;align-items:center;gap:5px;font-size:12px;opacity:.75}
  .websearching .wsst img{width:14px;height:14px;border-radius:50%;object-fit:cover;display:block}
  .websearching .wsdot{width:6px;height:6px;border-radius:50%;background:var(--muted);flex:none;animation:typingdot 1.25s infinite ease-in-out}
  /* ★출처 = footer(복사버튼 옆)에 ★겹친 아이콘 + "소스" 한 덩어리. 누르면 모달로 전체 목록(유저확정 2026-07-31) */
  /* ★복사버튼과 ★같은 높이·같은 정렬로 맞춘다(유저확정): footer 는 flex 라 아이콘 버튼들과 같은 규격을 쓴다 */
  /* ★검색 이미지 스트립(유저확정 2026-07-31) — 답변 아래 가로 스크롤. 폭이 좁으면 그대로 밀린다. */
  /* ★min-height/flex-shrink 명시 = 과거 첨부 미리보기 높이0 붕괴 재발 방지(project_error 26/07/29 13:20).
     overflow-x:auto 래퍼가 flex 아이템이 되면 min-height:auto 가 0 으로 계산돼 통째로 사라진다. */
  .webimgs{display:flex;gap:8px;margin-top:12px;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px;
    flex:0 0 auto;min-height:84px}
  .webimgs::-webkit-scrollbar{height:0}
  .wi-item{flex:0 0 auto;display:block;width:112px;height:84px;border-radius:10px;overflow:hidden;
    border:1px solid var(--bd);background:var(--bg2)}
  .wi-item img{width:100%;height:100%;object-fit:cover;display:block}
  .srcbtn{display:inline-flex;align-items:center;justify-content:center;gap:5px;background:none;border:0;
    height:26px;padding:0 8px;margin:0;cursor:pointer;color:var(--muted);font-size:12px;width:auto;line-height:1;
    vertical-align:middle;border-radius:6px}
  .srcbtn:hover{color:var(--fg);background:var(--input)}
  .srcbtn .sc-stack{display:inline-flex;align-items:center}
  .srcbtn .sc-ico{width:17px;height:17px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;
    background:var(--accent);color:#fff;font-size:9px;font-weight:800;text-transform:uppercase;
    border:1.5px solid var(--panel);margin-left:-6px}   /* --card(옛 팔레트) → --panel: 새 팔레트의 같은 역할(카드 바탕) */
  .srcbtn .sc-ico:first-child{margin-left:0}
  /* 출처 모달 — 하단 시트. 항목마다 도메인 + 제목, 누르면 새 탭 */
  .srcsheet{position:fixed;inset:0;z-index:80;display:flex;align-items:flex-end;justify-content:center;
    background:rgba(0,0,0,.72);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
  .srcsheet.hidden{display:none}
  /* ★시트는 ★불투명 배경(뒤가 비치면 내용이 안 읽힌다·유저확정) */
  .srcsheet .ss-box{width:100%;max-width:640px;max-height:78vh;overflow-y:auto;background:var(--bg);
    border:1px solid var(--line);border-bottom:0;box-shadow:0 -8px 32px rgba(0,0,0,.5);
    border-radius:16px 16px 0 0;padding:6px 0 max(18px,env(safe-area-inset-bottom))}
  .srcsheet .ss-grab{width:38px;height:4px;border-radius:2px;background:var(--line);margin:8px auto 4px}
  .srcsheet .ss-head{font-size:13px;color:var(--muted);padding:6px 18px 10px}
  .srcsheet .ss-item{display:block;padding:12px 18px;border-top:1px solid var(--line);text-decoration:none;color:var(--fg)}
  .srcsheet .ss-item:hover{background:var(--input)}
  .srcsheet .ss-dom{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--muted);margin-bottom:3px}
  .srcsheet .ss-dom .sc-ico{width:17px;height:17px;border-radius:50%;flex:none;display:flex;align-items:center;
    justify-content:center;background:var(--accent);color:#fff;font-size:9px;font-weight:800;text-transform:uppercase}
  .srcsheet .ss-url{font-size:13.5px;line-height:1.45;word-break:break-all}
  /* ★파일 출력 카드 — 모델이 만든 파일 다운로드 */
  .filecard{margin:8px 0 2px;padding:10px 12px;background:var(--input);border:1px solid var(--line);border-radius:10px;font-size:13.5px}
  .filecard .filedl{display:inline-block;color:var(--accent);font-weight:700;text-decoration:none;word-break:break-all}
  .filecard .filedl:hover{text-decoration:underline}
  .bubble .reasonbox>summary{cursor:pointer;list-style:none;padding:2px 0;font-size:12px;font-weight:500;color:var(--muted);user-select:none;display:inline-flex;align-items:center;gap:5px}
  .bubble .reasonbox>summary::-webkit-details-marker{display:none}
  .bubble .reasonbox>summary .rb-chev{transition:transform .15s;flex:none;color:var(--muted)}
  .bubble .reasonbox[open]>summary .rb-chev{transform:rotate(90deg)}
  .bubble .reasonbody{padding:6px 0 4px 8px;margin-left:6px;border-left:2px solid var(--line);font-size:12.5px;line-height:1.5;color:var(--muted);white-space:pre-wrap;word-break:break-word}
  /* 추론 실시간 스트립(답변 시작 전 마지막 줄 노출) */
  /* ★답변 대기 인디케이터(유저확정: '…' 대신 펄스 도트) */
  /* ★무엇을 하는 중인지 한 줄(26/08/26) — 이름 + 점.
     점만 있으면 멈춘 줄 안다(유저지시 "서비스이름 생각중 or 답변생성중 …"). */
  .waitline{display:flex;align-items:center;gap:8px}
  .wait-t{font-size:13px;color:var(--muted)}
  .typing-dots{display:inline-flex;gap:5px;align-items:center;padding:5px 0}
  .typing-dots span{width:6px;height:6px;border-radius:50%;background:var(--muted);opacity:.4;animation:typingdot 1.25s infinite ease-in-out}
  .typing-dots span:nth-child(2){animation-delay:.18s}
  .typing-dots span:nth-child(3){animation-delay:.36s}
  @keyframes typingdot{0%,60%,100%{opacity:.28;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
  .bubble .thinkstrip{margin:0 0 8px;font-size:12px;color:var(--muted);opacity:.9;display:flex;align-items:center;gap:6px;min-width:0}
  .bubble .thinkstrip .ts-ic{flex:none;color:var(--accent);animation:tsspin 2.4s linear infinite}
  .bubble .thinkstrip .ts-tx{white-space:normal;word-break:break-word;min-width:0}
  @keyframes tsspin{to{transform:rotate(360deg)}}
  .bubble .answerbody{white-space:pre-wrap;word-break:break-word}
  .bubble .answerbody.md{white-space:normal}
  .bubble .answerbody.md>*:first-child{margin-top:0}
  .bubble .answerbody.md>*:last-child{margin-bottom:0}
  /* AI 답변 하단 footer(HH:MM · N초 · X tok/s · 복사) — 평소 흐림, hover 시 진하게 */
  .bubble.ai .chatfoot{display:flex;align-items:center;justify-content:flex-start;gap:8px;margin-top:10px;padding-top:8px;border-top:1px solid var(--line);font-size:11px;color:var(--muted);opacity:.6;transition:opacity .15s}
  .bubble.ai .chatfoot .cf-meta{flex:0 0 auto;white-space:nowrap}
  .bubble.ai:hover .chatfoot{opacity:.9}
  .bubble.ai .chatfoot .cf-icon{flex:0 0 auto;width:auto;min-width:0;margin:0;padding:3px;background:none;border:0;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:0}
  .bubble.ai .chatfoot .cf-icon:hover{color:var(--accent)}
  .bubble.ai .chatfoot .cf-icon.copied{color:var(--ok)}
  .bubble.ai .chatfoot .cf-icon.loading{opacity:.45}
  /* ★유저 말풍선 footer(시각 좌·컨텍스트 중앙·복사 우·상하중앙·유저확정) */
  .userhead{align-self:flex-end;max-width:80%;text-align:right;font-size:10.5px;color:var(--muted);opacity:.55;margin:8px 4px 3px;white-space:nowrap}
  .userfoot{align-self:flex-end;max-width:80%;display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:4px;padding:0 4px;font-size:11px;color:var(--muted);opacity:.55}
  .userfoot .uf-ctx{flex:0 0 auto;white-space:nowrap}
  .userfoot .uf-copy,.userfoot .uf-edit{flex:0 0 auto;width:auto;min-width:0;margin:0;padding:3px;background:none;border:0;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:0}
  .userfoot .uf-copy:hover,.userfoot .uf-edit:hover{color:var(--accent)}
  .userfoot .uf-copy.copied{color:var(--ok)}
  @media (max-width:640px){ .bubble.ai .chatfoot{opacity:.7} }
  /* ★이미지 생성중 취소 버튼(동적버튼: width:auto·margin 명시로 전역 button{width:100%} 회피) */
  .bubble.ai .gen-cancel{width:auto;min-width:0;margin:8px 0 0;padding:4px 12px;background:transparent;border:1px solid var(--line);border-radius:8px;font-size:12px;font-weight:600;line-height:1;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;gap:4px}
  .bubble.ai .gen-cancel:hover{border-color:var(--danger);color:var(--danger)}
  /* ── 마크다운 렌더 요소 ── */
  .md-h{margin:22px 0 8px;line-height:1.35;font-weight:600}   /* ★유저지적: 타이틀 과굵음(700→600) / 위 여백=섹션 구분(카드 폐기 2026-07-31) */
  h3.md-h{font-size:15px} h4.md-h{font-size:13.5px} h5.md-h{font-size:13px} h6.md-h{font-size:12.5px;color:var(--muted)}
  .md-p{margin:7px 0}
  /* ★정리 카드(유저확정): 제목 단위 섹션을 카드로 묶는다. */
  /* ★.md-card(제목마다 테두리 박스) 폐기 2026-07-31 — 상용 챗처럼 단일 흐름. 박스는 코드블록·표·인용에만.
     테두리가 없어진 만큼 ★제목 위 여백으로 섹션을 구분한다(GPT 형식). */
  .answerbody > .md-h:first-child{margin-top:2px}
  .md-hr{border:0;border-top:1px solid var(--line);margin:12px 0}
  /* ★수식(markdown.js texHtml) — LaTeX 를 글자로 바꿔 담는 그릇. 블록 수식은 가운데(유저지적 IMG_2430 달러 원문 노출) */
  .mathx{font-family:Georgia,'Times New Roman',serif}
  .mathx sup,.mathx sub{font-size:.72em}
  .mathx.mathblk{display:block;text-align:center;margin:10px 0;font-size:1.06em}
  .md-q{margin:8px 0;padding:6px 12px;border-left:3px solid var(--line);color:var(--muted)}
  .md-ul,.md-ol{margin:8px 0;padding-left:22px}
  .md-ul li,.md-ol li{margin:3px 0}
  .md-p a,.md-ul a,.md-ol a,.md-tbl a{color:var(--accent);text-decoration:underline}
  code.ic{background:color-mix(in srgb, var(--muted) 16%, transparent);color:#e0902b;padding:1px 5px;border-radius:5px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:.9em;word-break:break-word}
  /* 표 — 가로스크롤 래퍼 */
  .md-tblwrap{overflow-x:auto;margin:10px 0;-webkit-overflow-scrolling:touch}
  table.md-tbl{border-collapse:collapse;font-size:13px;min-width:100%}
  table.md-tbl th,table.md-tbl td{border:1px solid var(--line);padding:6px 10px;text-align:left;white-space:nowrap;font-size:13px;line-height:1.5}
  /* ★셀 안에 중첩된 요소(강조·문단·목록 등)가 자기 크기를 들고 오면 표 글자가 행마다 점점 커진다(유저 실측)
     → 표 내부는 무엇이 오든 셀 크기를 물려받게 고정한다. */
  table.md-tbl th *,table.md-tbl td *{font-size:inherit;line-height:inherit;margin:0}
  table.md-tbl th{background:color-mix(in srgb, var(--muted) 14%, transparent);font-weight:700}
  /* 코드블록 */
  .cblock{margin:10px 0;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:color-mix(in srgb, var(--muted) 8%, transparent);text-align:left}   /* ★좌측정렬 명시(2026-07-30 유저: 코드가 우측/중앙으로 밀림 — 부모 text-align 상속) */
  .cbhead{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:4px 8px 4px 12px;background:color-mix(in srgb, var(--muted) 14%, transparent);border-bottom:1px solid var(--line)}
  .cblang{font-size:10.5px;font-weight:500;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;white-space:nowrap}
  .cbacts{display:flex;gap:6px}
  /* ★전역 button{width:100%;margin-top:18px} 오버라이드(유저지적: 복사버튼이 헤더 폭 전체를 먹음) — 아이콘 크기·우측 끝·세로 중앙 */
  .cbbtn{width:auto;flex:0 0 auto;margin:0 0 0 auto;background:none;border:1px solid var(--line);color:var(--muted);border-radius:6px;padding:4px 6px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1}
  .cbbtn:hover{color:var(--fg);border-color:var(--accent)}
  .cbbtn.copied{color:var(--ok);border-color:var(--ok)}
  .qblock,.tblblock{position:relative}
  .qblock .qbcopy,.tblblock .tblcopy{position:absolute;top:4px;right:4px;z-index:1;width:auto;flex:0 0 auto;margin:0;background:var(--panel,rgba(20,22,28,.85));border:1px solid var(--line);color:var(--muted);border-radius:6px;padding:3px 5px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1;opacity:.5;transition:opacity .15s}
  .qblock:hover .qbcopy,.tblblock:hover .tblcopy{opacity:1}
  .qblock .qbcopy:hover,.tblblock .tblcopy:hover{color:var(--fg);border-color:var(--accent)}
  .qblock .qbcopy.copied,.tblblock .tblcopy.copied{color:var(--ok);border-color:var(--ok);opacity:1}
  .idcopy{width:auto;flex:none;margin:0 0 0 6px;padding:2px 4px;background:none;border:1px solid var(--line);color:var(--muted);border-radius:5px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1;vertical-align:middle;opacity:.6;transition:opacity .15s}
  .idcopy:hover{opacity:1;color:var(--fg);border-color:var(--accent)}
  .cbbody{margin:0;padding:10px 12px;overflow-x:auto;-webkit-overflow-scrolling:touch;text-align:left}
  .cbbody code{display:block;text-align:left;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.55;white-space:pre;color:var(--fg)}
  /* ★코드 구문강조(라이브러리 없이 정규식·CSP 안전) — 다크 기본 + 라이트 오버라이드 */
  .cbbody code .tk-k{color:#c678dd}
  .cbbody code .tk-s{color:#98c379}
  .cbbody code .tk-c{color:#7d8799;font-style:italic}
  .cbbody code .tk-n{color:#d19a66}
  :root[data-theme="light"] .cbbody code .tk-k{color:#a626a4}
  :root[data-theme="light"] .cbbody code .tk-s{color:#50820f}
  :root[data-theme="light"] .cbbody code .tk-c{color:#9199a5}
  :root[data-theme="light"] .cbbody code .tk-n{color:#b76b01}
  .setupprog{align-self:stretch;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 16px;margin:6px 0}
  .setupprog .sp-head{font-weight:700;font-size:13px;color:var(--fg);margin-bottom:10px}
  .setupprog .sp-bar{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;letter-spacing:-1px;color:var(--accent);font-weight:700;white-space:nowrap;overflow:hidden}
  .setupprog .sp-meta{font-size:12px;color:var(--muted);margin-top:8px;font-variant-numeric:tabular-nums}
  .setupprog .sp-wait{font-size:12px;color:var(--muted)}
  .setupprog .sp-notice{font-size:12px;color:var(--danger);margin-top:10px;background:color-mix(in srgb,var(--danger) 10%,transparent);border-radius:8px;padding:8px 10px;white-space:pre-wrap;word-break:break-word}
  .setupprog .sp-overall{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11px;letter-spacing:-.5px;color:var(--accent);font-weight:700;white-space:nowrap;overflow:hidden;margin-bottom:4px}
  .setupprog .sp-items{margin:12px 0 4px;display:flex;flex-direction:column;gap:6px}
  .setupprog .sp-item{display:flex;justify-content:space-between;align-items:center;gap:10px;font-size:13px}
  .setupprog .sp-item .sp-it-nm{color:var(--fg);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .setupprog .sp-item .sp-it-sz{color:var(--muted);font-variant-numeric:tabular-nums;flex:none;font-size:12px}
  .setupprog .sp-cur{margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
  .setupprog .sp-cur .sp-cur-hd{font-size:13px;font-weight:700;color:var(--fg);margin-bottom:7px}
  /* ★세팅중 국면 스트립(다운로드→설치→웜업) — 백엔드 국면 필드 있으면 GB 병기, 없으면 로그 파싱 폴백 */
  .setupprog .sp-phase{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin:0 0 10px;font-size:11px;font-weight:700}
  .setupprog .sp-ph{padding:2px 9px;border-radius:12px;border:1px solid var(--line);color:var(--muted);white-space:nowrap;line-height:1.6}
  .setupprog .sp-ph.done{color:var(--ok);border-color:color-mix(in srgb,var(--ok) 55%,transparent)}
  .setupprog .sp-ph.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .setupprog .sp-ph-arrow{color:var(--muted);font-size:10px;flex:none}
  .setupprog .sp-auto{font-size:11.5px;color:var(--muted);margin-top:10px}
  /* 첨부 미리보기 스트립 */
  .previewstrip{flex:none;display:flex;gap:8px;flex-wrap:wrap;margin:8px 0 0}
  .pvchip{display:flex;align-items:center;gap:6px;background:var(--input);border:1px solid var(--line);border-radius:10px;padding:5px 8px 5px 10px;font-size:12px;max-width:180px}
  .pvchip .pvn{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .pvchip .pvx{cursor:pointer;color:var(--muted);font-weight:700;flex:none}
  .pvchip .pvx:hover{color:var(--danger)}
  /* 컨트롤 토글(추론모드·교육모드) */
  /* ★설정 모달 안 스위치 — .modalbox label(block)이 .tgl(flex)을 특이도로 이겨 스위치가 붕괴되던 사고(26/08/22 IMG_2442 실측) */
.modalbox label.tgl{display:flex;margin:0}
.tgl{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--muted);cursor:pointer;user-select:none}
  /* ★162차: hidden 속성이 display:flex 에 진다 — 코드 방에서 추론 토글이 그대로 보였다(19차 실측 hidden:true·display:flex). 자동 진행 토글도 같은 병 */
  .tgl[hidden]{display:none!important}
  .tgl input{display:none}
  .tgl .tgl-b{width:32px;height:18px;border-radius:20px;background:var(--input);border:1px solid var(--line);position:relative;transition:background .15s;flex:none}
  .tgl .tgl-b:after{content:'';position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:var(--muted);transition:transform .15s,background .15s}
  .tgl input:checked + .tgl-b{background:color-mix(in srgb,var(--accent) 55%,transparent);border-color:var(--accent)}
  .tgl input:checked + .tgl-b:after{transform:translateX(14px);background:#fff}
  .tgl input:checked ~ span:last-child{color:var(--fg)}
  /* ★4단 추론깊이 select(26/09/15) — 지원 모델일 때 .tgl(체크박스) 대신 이 칸이 뜬다 */
  .selwrap{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--muted);cursor:pointer;user-select:none}
  .selwrap[hidden]{display:none!important}
  .selwrap select{font:inherit;color:var(--fg);background:var(--input);border:1px solid var(--line);border-radius:8px;padding:3px 6px;cursor:pointer}
  /* ＋ 드롭다운 메뉴 */
  /* ★+ 버튼(예 web.js 892~894 원문) — 마크업-CSS 쌍 규칙(oops 26/08/19 18:25 재발방지) */
  .ci-btn{flex:none;width:38px;height:38px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--input);border:1px solid var(--line);color:var(--muted);cursor:pointer}
  .ci-btn:hover{color:var(--fg);border-color:var(--muted)}
  .ci-btn svg{width:17px;height:17px}
  .pluswrap{position:relative;flex:none}
  .plusmenu{position:absolute;bottom:52px;left:0;min-width:160px;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:6px;box-shadow:0 12px 34px rgba(0,0,0,.4);z-index:30}
  .plusmenu button,.plusmenu label{display:block;width:100%;margin:0;text-align:left;background:transparent;border:0;color:var(--fg);font-size:13.5px;font-weight:600;padding:9px 11px;border-radius:8px;cursor:pointer}
  .plusmenu button:hover,.plusmenu label:hover{background:var(--hover)}
  /* ★미디어 생성 패널(genpanel) — [+]→이미지 생성. 헤더 우측에 명확한 '닫기' 버튼(창닫기 인지) */
  .genpanel{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:12px 14px;margin-bottom:8px}
  .genpanel .gp-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:6px}
  .genpanel .gp-head b{font-size:14px;font-weight:700;color:var(--fg)}
  .genpanel .gp-x{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;background:transparent;border:none;border-radius:8px;color:var(--muted);cursor:pointer;flex:none}
  .genpanel .gp-x:hover{background:var(--input);color:var(--fg)}
  .genpanel .gp-lbl{color:var(--muted);font-size:12.5px}
  .genpanel .gp-imgprev{position:relative;display:inline-block;margin-top:4px}
  .genpanel .gp-imgprev.hidden{display:none}
  .genpanel .gp-thumb{max-width:110px;max-height:110px;border-radius:8px;border:1px solid var(--line);display:block}
  .genpanel .gp-thumbx{position:absolute;top:-8px;right:-8px;width:22px;height:22px;border-radius:50%;background:var(--danger);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:15px;line-height:1;cursor:pointer}
  .genpanel .gp-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:9px;font-size:13px;color:var(--muted)}
  .genpanel .gp-imgbtn{background:color-mix(in srgb,var(--accent) 16%,transparent);border:1px solid color-mix(in srgb,var(--accent) 45%,transparent);border-radius:10px;padding:10px 14px;color:var(--accent);font-size:13px;font-weight:700;cursor:pointer;flex:1;min-width:150px}
  .genpanel .gp-imgbtn:hover{background:color-mix(in srgb,var(--accent) 24%,transparent)}
  .genpanel .gp-imgname{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
  .genpanel select{background:var(--input);border:1px solid var(--line);border-radius:9px;padding:7px 9px;color:var(--fg);font-size:13px;vertical-align:middle}
  /* ★chatDock: 입력영역(추론토글+입력창)을 visualViewport 하단(키보드 바 위)에 좌표로 fixed 고정.
     JS(positionDock)가 top=offsetTop+vv.height·transform:translateY(-100%) 로 매 키보드변화마다 붙인다.
     flex/body높이 계산과 무관하게 입력칸이 항상 키보드 바로 위에 붙는다(iOS 검증방식). */
  .chatdock{position:fixed;left:0;right:0;z-index:40;background:var(--bg);padding:4px 16px calc(6px + env(safe-area-inset-bottom));border-top:1px solid var(--line)}
  /* ★PC 전용 하단 여백(유저확정: "PC 웹은 채팅 입력칸이 너무 화면 아래에 딱 붙어있어").
     ★모바일(≤1023px)은 손대지 않는다 — positionDock 이 키보드 위에 붙이는 ★확정 배선이라 건드리면 회귀한다.
     포인터가 정밀(마우스)한 큰 화면에서만 적용해 태블릿 터치 환경도 제외한다. */
  @media (min-width:1024px) and (pointer:fine){
    /* ★PC 레이아웃 정돈(유저확정 "입력칸이 창 맨 끝에 붙고, 추론모드 위 여백이 너무 많고,
       모바일/PWA 는 괜찮은데 PC 만 이상하다"): ①바닥에서 띄우고 ②dock 내부 상단 여백을 줄이고
       ③대화·입력칸을 같은 폭의 중앙 컬럼으로 묶어 글이 화면 폭 전체로 퍼지지 않게 한다. */
    /* ★269: 26px 은 너무 넓다 — 하단 한 줄을 모은 뒤라 그만큼 채팅 화면을 내준다(유저지적 "아래쪽 여백은 또 왜 이렇게 넓어"). */
    .chatdock{padding:2px 16px 8px}
    .inputrow{margin-top:2px}
    /* ★중앙 컬럼 폭 고정 제거(유저확정 "채팅창 좌우로 자꾸 움직인다 — 고정인데 왜 건드리냐"):
       max-width 중앙정렬이 스크롤바 유무·내용 길이에 따라 좌우로 흔들려 보였다 → 원래대로 되돌린다. */
  }
  /* ★맨아래로 버튼: 채팅을 위로 올렸을 때만 표시, 클릭시 최하단. bottom 은 positionDock 이 dock 바로 위로 갱신. */
  /* ★가운데 배치(유저확정) */
  .scrollbtm{position:fixed;left:50%;transform:translateX(-50%);bottom:120px;z-index:41;width:34px;height:34px;border-radius:50%;background:var(--panel);border:1px solid var(--line);color:var(--muted);display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 3px 10px rgba(0,0,0,.28);padding:0}
  .scrollbtm svg{width:17px;height:17px}
  .scrollbtm:active{background:var(--hover)}
  .scrollbtm.hidden{display:none}
  /* ★클로드 스타일 입력부 v2(2026-07-30 유저확정): 한줄=[+][입력필(전송 내장·첨부는 필 안 위)][마이크] / 아래행=추론토글···컨텍스트링 */
  .inputrow{display:flex;align-items:flex-end;gap:7px;margin-top:5px;margin-bottom:2px}
  .inputpill{flex:1;border:1.5px solid var(--line);border-radius:22px;background:var(--input);padding:4px 6px 4px 13px;display:flex;flex-direction:column;min-width:0}
  .inputpill .previewstrip{margin:4px 0 6px}
  .pillrow{display:flex;align-items:flex-end;gap:6px}
  .pillrow #chatText{flex:1;border:none;background:transparent;box-shadow:none;outline:none;padding:7px 0;margin:0;resize:none;min-width:0;color:var(--fg);caret-color:var(--fg);font-size:16px;font-family:inherit;line-height:1.4;max-height:132px;overflow-y:auto}   /* ★색·16px 명시(다크 글자 안보임 + iOS 포커스 자동확대 방지 — 옛 .chatinput 스코프 속성 이식) */
  .pillrow #chatSend{flex:none;width:32px;height:32px;margin:0 0 1px;padding:0;display:flex;align-items:center;justify-content:center;border-radius:50%}
  .cardbar{display:flex;align-items:center;gap:12px;padding:4px 4px 0}
  .cardbar .tgl{margin:0}
  .cardsp{flex:1}
  .ctxbtn{width:26px;height:26px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer}
  .ctxpop{position:absolute;right:16px;bottom:calc(100% + 8px);background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:12px 14px;min-width:240px;box-shadow:0 8px 24px rgba(0,0,0,.28);z-index:60}
  .ctxrow{display:flex;justify-content:space-between;align-items:baseline;gap:14px;font-size:13px;margin-bottom:8px}
  .ctxbar{height:6px;border-radius:3px;background:var(--line);overflow:hidden}
  .ctxbar i{display:block;height:100%;width:0;background:#3b82f6;border-radius:3px;transition:width .2s}
  #chatText:disabled{opacity:.6}
  .inputpill.off{opacity:.5}
  .inputpill.off textarea,.inputpill.off input,.inputpill.off button{pointer-events:none}
  /* ★유저확정 채팅락: 전송버튼 비활성 색 변경(회색) — 오류가 아니라 잠금임이 보이게 */
  #chatSend:disabled{background:var(--line);color:var(--muted);cursor:not-allowed}
  #chatText:disabled{cursor:not-allowed}
  /* ★시스템프롬프트(상용 퀄리티·유저리뷰): 에디터 카드 = 상단 상태바(배지+글자수) /
     프레임리스 에디터 / 하단 메타+적용. 등록한 형태(줄바꿈) 그대로. */
  .sp-head{margin:4px 2px 14px}
  .sp-title{font-size:16px;font-weight:700;letter-spacing:-.2px}
  .sp-sub{font-size:12.5px;color:var(--muted);line-height:1.65;margin-top:5px;max-width:720px}
  .sp-card{border:1px solid var(--line);border-radius:14px;background:rgba(255,255,255,.02);overflow:hidden;transition:border-color .15s,box-shadow .15s}
  .sp-card:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px rgba(91,124,250,.12)}
  .sp-bar{display:flex;align-items:center;gap:8px;padding:10px 14px;border-bottom:1px solid var(--line)}
  .sp-badge{font-size:11px;font-weight:600;padding:3px 10px;border-radius:999px;border:1px solid var(--line);color:var(--muted)}
  .sp-badge.on{color:#31c48d;border-color:rgba(49,196,141,.35);background:rgba(49,196,141,.08)}
  .sp-badge.dirty{color:#e6b84a;border-color:rgba(230,184,74,.35);background:rgba(230,184,74,.08)}
  .sp-count{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
  .sp-count.full{color:#e0245e}
  /* ★키보드 대응: 고정 min-height:280px 는 키보드 뜨면 좁은 가시영역보다 커서 입력칸이 키보드에 가려진다.
     → --appH(키보드時 줄어드는 실높이) 기반으로 캡. 키보드 없을 땐 280px, 뜨면 가시영역의 40~55%로 자동 축소해 카드가 키보드 위에 들어온다. */
  #sysPromptTa{display:block;width:100%;min-height:min(280px, calc(var(--appH,100dvh) * 0.4));max-height:calc(var(--appH,100dvh) * 0.55);resize:vertical;border:0;background:transparent;color:var(--fg);font-family:inherit;font-size:13.5px;line-height:1.7;padding:14px;outline:none}
  #sysPromptTa::placeholder{color:var(--muted);opacity:.6}


  /* ★로딩 덮개 — 정중앙 로고 한 장(26/09/03 유저확정) */
  .bootmask{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;
    background:var(--bg,#0b0e14);transition:opacity .18s ease}
  .bootmask.gone{opacity:0;pointer-events:none}
  .bootmask img{width:92px;height:92px;object-fit:contain}
  .bootmask span{font:600 22px/1.2 system-ui,-apple-system,"Segoe UI",sans-serif;
    letter-spacing:.18em;color:var(--fg,#e6e9ef);opacity:.9}

  /* ★비밀값 입력(pages/code_secret.js · 26/09/03) — API 키를 그 자리에서 받는다 */
  .sec-back{position:fixed;inset:0;z-index:9000;display:flex;align-items:center;justify-content:center;
    background:rgba(0,0,0,.45);padding:18px}
  /* ★'만들기 전에 정하기' 카드는 채팅칸을 막지 않는다 — 뒤판은 눌림을 통과시키고 카드만 받는다(pages/code_plan_ask.js · 26/09/14) */
  .sec-back.plan-back{pointer-events:none}
  .sec-back.plan-back .sec-box{pointer-events:auto}
  .sec-box{width:100%;max-width:420px;background:var(--panel);border:1px solid var(--line);
    border-radius:16px;padding:18px 18px 14px;box-shadow:0 12px 40px rgba(0,0,0,.3)}
  .sec-title{font-size:15px;font-weight:700;margin-bottom:6px}
  /* ★무슨 값인지 한 눈에(API 키·비밀번호·아이디…) — 유저지시 26/09/03 */
  .sec-kind{display:inline-block;font-size:11px;font-weight:600;color:var(--accent);
    border:1px solid var(--accent);border-radius:999px;padding:1px 9px;margin-bottom:8px}
  .sec-why{font-size:13px;color:var(--muted);line-height:1.5;margin-bottom:10px}
  .sec-how{font-size:12.5px;line-height:1.55;background:var(--input);border-radius:10px;
    padding:10px 12px;margin-bottom:12px;white-space:pre-wrap;max-height:180px;overflow-y:auto}
  .sec-howt{font-weight:600;margin-bottom:4px;color:var(--fg)}
  .sec-input{width:100%;height:40px;border-radius:10px;border:1px solid var(--line);
    background:var(--input);color:var(--fg);padding:0 12px;font-size:14px;margin:0}
  .sec-note{font-size:11.5px;color:var(--muted);margin:8px 2px 0;line-height:1.5}
  .sec-row{display:flex;gap:8px;margin-top:14px}
  /* ★310: 높이를 못박지 않는다 — 글자가 두 줄이 되면 38px 안에서 ★잘렸다(유저스샷 26/09/08).
     언어마다 문구 길이가 다르므로(독일어·러시아어는 더 길다) ★뒤는 쌀이 맞춰지게 한다. */
  .sec-row button{flex:1;min-height:38px;padding:8px 10px;margin:0;border-radius:10px;
    font-size:13.5px;font-weight:600;line-height:1.25;cursor:pointer}
  .sec-skip{border:1px solid var(--line);background:transparent;color:var(--muted)}
  .sec-ok{border:0;background:var(--accent);color:#fff}
  /* 고르게 하기(code_ask.js) — 배포·도메인·관리자 페이지 · 비밀값 창과 같은 결 */
  .ask-list{display:flex;flex-direction:column;gap:8px;margin:12px 0 4px}
  .ask-choice{height:44px;padding:0 14px;border-radius:8px;border:1px solid var(--line);background:var(--panel);
    color:var(--text);font-size:15px;text-align:left;cursor:pointer;transition:background .15s,border-color .15s;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ask-choice:hover{border-color:var(--accent)}
  .ask-choice:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  /* ★만들기 전에 정하기 시트(pages/code_plan.js · 26/09/06) — 항목 카드 + 선택지 버튼(추천 표시) · 폰 폭 우선 */
  .plan-box{max-width:520px;max-height:88vh;overflow-y:auto}
  .plan-list{display:flex;flex-direction:column;gap:12px;margin:12px 0 4px}
  .plan-item{padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--card)}
  .plan-name{font-size:14.5px;font-weight:700;color:var(--text);margin-bottom:4px}
  .plan-why{font-size:12.5px;color:var(--muted);line-height:1.5;margin-bottom:8px;white-space:normal}
  .plan-opts{display:flex;flex-direction:column;gap:6px}
  .plan-opt{width:100%;margin:0;padding:8px 12px;border-radius:8px;border:1px solid var(--line);background:var(--panel);
    color:var(--text);text-align:left;cursor:pointer;font-size:13.5px;line-height:1.4;white-space:normal}
  .plan-opt.on{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
  .plan-opt-line{display:flex;align-items:center;gap:8px}
  .plan-opt-label{font-weight:600}
  .plan-rec{font-size:11px;padding:1px 7px;border-radius:999px;background:var(--accent);color:#fff;flex:none}
  .plan-opt-desc{font-size:12px;color:var(--muted);margin-top:2px}
  .plan-box .sec-row{flex-wrap:wrap}
  .plan-box .sec-row button{flex:1 1 30%;min-width:96px}
  /* ★310: 좁은 화면에서는 ★세로로 쌓는다 — 폭을 다 쓰면 접힐 이유가 없다.
     폰 390px 에서 모달 안쪽은 약 330px — 단추 3개를 가로로 놓으면 하나당 약 100px 뿐이다. */
  @media (max-width: 460px){
    .plan-box .sec-row,.ask-box .sec-row,.cv-ask .sec-row{flex-direction:column}
    .plan-box .sec-row button,.ask-box .sec-row button,.cv-ask .sec-row button{flex:none;width:100%}
  }
  /* ★코드 방 화면(pages/code_view.js · 26/09/03) */
  /* ★여백을 좁힌다 — 유저지적 26/09/09 22:32 "답변이나 작업내용같은게 위아래 여백이 너무 크잖아
     한줄인데 두줄도마찬가지고 / 그아래에 작업내용카드가 들어가야지 깔끔해보이지않겠냐".
     ㄴ말 머리글 8px→4/2px · 그 아래 카드 4px→2px 로 붙여 ★말+작업이 한 덩어리로 보이게 한다. */
  .cv-note{margin:4px 12px;padding:7px 12px;border-radius:12px;background:var(--card);border:1px solid var(--line)}
  .cv-role{font-size:11.5px;color:var(--muted);margin-bottom:4px;font-weight:600}
  /* ★26/09/19 유저지시: 판의 생각·말은 ★가장 잘 보이는 본문색(다크 흰 계열 · 라이트 검정 계열),
     그 아래 "뭘 했는지" 줄은 회색으로 한 단계 내린다 — 종전에는 둘이 같은 --fg 라 층이 안 갈렸다. */
  .cv-text{font-size:13.5px;line-height:1.55;white-space:pre-wrap;word-break:break-word;color:var(--fg)}
  /* ★말 안의 강조·인라인코드 — 26/09/04: 마크다운 원문이 그대로 보이던 것을 그린다 */
  .cv-line{min-height:1.55em}
  .cv-line:empty{min-height:.7em}
  .cv-b{font-weight:650;color:var(--fg)}
  .cv-link{color:var(--pri,#2f6fed);text-decoration:none;border-bottom:1px solid currentColor;
    cursor:pointer;word-break:break-all}
  .cv-link:hover{opacity:.75}
  .cv-link:focus-visible{outline:2px solid var(--pri,#2f6fed);outline-offset:2px;border-radius:3px}
  .cv-code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;
    padding:1px 5px;border-radius:5px;background:var(--chip,rgba(127,127,127,.14));
    border:1px solid var(--line);white-space:nowrap}
  /* ★작업 한 줄(유저지시 26/09/03 · 받은 스샷 그대로): 테두리 없는 한 줄 —
     [동사][대상][+N -M][›]. 누르면 세부 시트가 올라온다. */
  /* ★306 코드 문법 색 — 모달 안 코드가 한 덩어리 글자로 보이지 않게(유저지시 26/09/08).
     손님 테마가 밝아도 읽힐 만큼만 채도를 준다 — 눈이 아프면 고급스럽지 않다. */
  .hl-com{color:#7d8590}
  .hl-str{color:#a5d6ff}
  .hl-kw{color:#ff7b72}
  .hl-num{color:#f0b072}
  .hl-fn{color:#d2a8ff}
  .cv-pre .hl-com,.cv-cmd .hl-com,.cv-dt .hl-com{font-style:italic}
  .cv-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:3px 12px;font-size:12px;color:var(--muted);
    background:none;border:0;padding:0;line-height:1.5;min-width:0}
  /* ★26/09/19 유저지시 "멘트는 위로 작업내용은 아래로해서 두줄로만들라고안했냐?":
     근거 문장은 ★줄 전체를 차지해(flex-basis 100%) 아래로 접히고 order:-1 로 ★맨 위에 선다.
     ㄴ아랫줄에는 [동사][경로][+N -M][›] 만 남는다. cv-why 가 없는 줄(진행·오류·상태)은 종전대로 한 줄. */
  .cv-why{flex:0 0 100%;order:-1;color:var(--fg);opacity:.82;font-size:12.5px;line-height:1.5;
    white-space:normal;word-break:break-word}
  .cv-row.tap{cursor:pointer}
  .cv-row.tap:hover .cv-sub{opacity:1}
  /* ★26/09/19 유저지시 "뭘했는지 글자 좀 작게(회색계열 모드에따라서 다잘보이게)":
     종전 color:var(--fg) 는 ★판의 말과 같은 색이라 한 덩어리로 보였다. 회색(--muted)으로 한 층 내리고
     불투명도는 오히려 올려(.72 → .95) 두 모드 모두에서 또렷하게 읽히게 한다. */
  .cv-act{flex:none;font-weight:600;color:var(--muted);opacity:.95;font-size:11.5px}
  /* ★끝 카드 [열기] — 결과물을 언제든 다시 여는 작은 버튼(26/09/06 유저지적 "웹도 띄워서 보여줘야지 링크도 주지만") */
  .cv-open{flex:none;width:auto;margin:0;padding:3px 11px;border:1px solid var(--line);border-radius:7px;background:none;
    color:var(--fg);font-size:12px;line-height:1.4;cursor:pointer;opacity:.85}   /* width·margin 명시 — 전역 button{width:100%;margin-top:18px} 방어(26/08/22 사고) */
  .cv-open:hover{opacity:1;background:var(--line)}
  /* ★코드 방 손님 요청 말풍선(26/09/06 유저지적 "질문한 것도 안 보이고") — 채팅과 같은 오른쪽 말풍선 모양 */
  .cv-user{display:flex;justify-content:flex-end;margin:10px 12px 6px}
  .cv-user-bubble{max-width:86%;padding:10px 14px;border-radius:16px 16px 4px 16px;background:var(--accent);color:#fff;
    font-size:14px;line-height:1.55;white-space:pre-wrap;word-break:break-word}
  /* ★끝 카드 다음 할 일 안내(i18n cv.next · 26/09/06) — 조용한 한 줄 */
  .cv-next{margin:2px 12px 10px;font-size:12.5px;line-height:1.5;color:var(--muted);white-space:normal}
  /* ★+N -M 은 글자 ★끝에 바로 붙는다 — flex:1 로 늘리면 우측 끝으로 밀려 ★손님 말풍선처럼 보인다(유저지적 26/09/05 "+ - 가 왜 우측 끝에 있어") */
  .cv-sub{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:.8;
    color:var(--muted);font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11.5px}
  .cv-num{flex:none;display:flex;gap:6px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;font-weight:600}
  /* ★+N -M 은 ★초록·빨강으로 또렷하게(유저지시 26/09/19) — 라이트 모드에서는 밝은 초록이 배경에 묻히므로 진한 값으로 바꾼다. */
  .cv-add{color:#3ecf6a} .cv-del{color:#e5484d}
  :root[data-theme="light"] .cv-add{color:#12a150} :root[data-theme="light"] .cv-del{color:#d02a2f}
  .cv-dim{opacity:.6} .cv-dim2{font-size:11.5px;color:var(--muted);margin-top:5px}
  .cv-caret{flex:none;margin-left:auto;color:var(--muted);opacity:.55;font-size:15px;line-height:1}   /* 화살표만 우측 끝 · 숫자는 글자 옆 */
  /* 비밀번호 칸 — Edge/IE 내장 '표시' 단추가 우리 눈 아이콘과 ★겹친다(26/09/05 폰 폭 Edge 스샷) */
  input[type=password]::-ms-reveal, input[type=password]::-ms-clear{display:none}
  /* ★321: 멈췄던 일 — 빨간 오류가 아니라 ★누런 경고 톤(판이 다음 턴에 설명한다). */
  .cv-warn .cv-act{color:#d8a657;opacity:1}
  .cv-warn .cv-sub{font-family:inherit;font-size:13px;white-space:normal;overflow:visible;opacity:.85}
  .cv-bad .cv-act{color:#e5484d;opacity:1}
  /* 오류 줄은 명령·경로가 아니라 ★사람 말(humanErr) — 고정폭이면 자간이 벌어져 깨져 보인다(26/09/05 3판 스샷) */
  .cv-bad .cv-sub{font-family:inherit;font-size:13px;white-space:normal;overflow:visible;opacity:.9}
  .cv-ok .cv-act{color:#3ecf6a;opacity:1}
  .cv-dimrow{opacity:.7}
  /* 150차: 판의 말 = 작업 묶음 머리글 — 문장은 굵게, 이어지는 카드 줄은 그 안에 들여서 */
  /* ★153차(유저지적 'llm 이 한 말은 좌측에 붙는게 맞지'): 손님 말풍선 같은 전체 폭 상자가 아니라 왼쪽에 붙는 말 */
  .cv-note-head{padding:3px 12px 3px 12px;margin:4px auto 2px 12px;max-width:92%;width:fit-content;min-width:60%;background:transparent;border:0;border-left:3px solid var(--accent);border-radius:0 10px 10px 0}
  .cv-note-head>:first-child{font-weight:600}
  .cv-note-head .cv-row{margin:2px 0 0 6px;padding-left:8px;border-left:2px solid var(--line,rgba(255,255,255,.12))}
  /* ★진행 표 — 몇 개 중 몇 번째인지 한눈에(유저지시 26/09/04 '필요한 정보 다 나오게').
     ㄴ한 장만 두고 갈아끼우므로 ★맨 아래에 고정된 느낌으로 보인다. */
  .cv-ask{margin:10px 12px;padding:12px;border:1px solid var(--accent);border-radius:12px;background:var(--card)}
  .cv-ask .sec-title{margin:0 0 4px;font-size:15px;font-weight:700}
  .cv-ask .sec-why{margin:0 0 8px;font-size:13px;color:var(--muted);white-space:normal}
  .cv-ask-hint{margin:0 0 10px;font-size:12px;color:var(--accent)}
  .cv-ask-done{font-size:13px;color:var(--muted)}
  .cv-ask-view .plan-opt,.cv-ask-view .ask-choice{pointer-events:none}
  .cv-ask-ans{margin-top:6px;display:flex;flex-direction:column;gap:4px}
  .cv-ask-ans-line{font-size:13.5px;color:var(--text);padding:6px 10px;border:1px solid var(--accent);border-radius:8px;background:var(--panel)}
  .cv-ask .plan-list{display:flex;flex-direction:column;gap:8px}
  .cv-ask .plan-opts{display:flex;flex-direction:column;gap:6px;margin-top:6px}
  .cv-ask .ask-list{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
  .cv-plan{margin:10px 12px;padding:10px 12px;border:1px solid var(--line);border-radius:12px;
    background:var(--card,rgba(127,127,127,.04))}
  .cv-plan-h{display:flex;align-items:center;gap:8px;margin-bottom:6px}
  .cv-plan-t{font-size:11.5px;font-weight:600;color:var(--muted);letter-spacing:.02em}
  .cv-plan-r{display:flex;align-items:center;gap:8px;padding:3px 0;font-size:12.5px;color:var(--fg);
    line-height:1.45;min-width:0}
  .cv-plan-x{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* 상태는 ★모양과 색으로만 — wait/check/pass 같은 내부값을 글자로 쓰지 않는다 */
  .cv-plan-i{flex:none;width:14px;height:14px;border-radius:50%;border:1.6px solid var(--line);
    position:relative;transition:.15s}
  .cv-st-wait .cv-plan-x{opacity:.55}
  .cv-st-check .cv-plan-i{border-color:#f5a623;border-style:dashed}
  .cv-st-error .cv-plan-i{border-color:#e5484d}
  .cv-st-error .cv-plan-i::after{content:'';position:absolute;inset:3px;border-radius:50%;background:#e5484d}
  .cv-st-pass .cv-plan-i{border-color:#3ecf6a;background:#3ecf6a}
  .cv-st-pass .cv-plan-i::after{content:'';position:absolute;left:4px;top:1px;width:4px;height:8px;
    border:solid #fff;border-width:0 1.6px 1.6px 0;transform:rotate(43deg)}
  .cv-st-pass .cv-plan-x{opacity:.6;text-decoration:line-through;text-decoration-thickness:1px}
  .cv-spin{flex:none;width:11px;height:11px;border:2px solid var(--line);border-top-color:var(--accent);
    border-radius:50%;animation:cvspin .7s linear infinite}
  /* ★26/09/18 상태 줄 — 방이 도는 동안 맨 아래에 항상 살아 있는 한 줄('(무엇) 하는 중… N초 · 명령어 N개 실행 …').
     유저지적 "화면이 정적으로 멈춰있는게 아니라 작업중… 명령어 몇개 실행함 뭐함 생각중… 1초 2초 이런게 있어야". */
  .cv-status{position:sticky;bottom:0;margin:6px 12px 2px;padding:6px 10px;border-radius:10px;
    background:var(--panel,rgba(20,24,32,.92));border:1px solid var(--line);font-size:12.5px}
  .cv-status .cv-sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .cv-status .cv-status-cnt{flex:none;color:var(--muted);opacity:.85}
  @keyframes cvspin{to{transform:rotate(360deg)}}
  /* ★세부 시트 — 아래에서 올라온다(폰·PC 같은 모양) */
  .cv-sheetback{position:fixed;inset:0;z-index:9100;background:rgba(0,0,0,.45);
    display:flex;align-items:flex-end;justify-content:center}
  .cv-sheet{width:100%;max-width:760px;max-height:86vh;display:flex;flex-direction:column;
    background:var(--panel);border:1px solid var(--line);border-radius:18px 18px 0 0;overflow:hidden}
  .cv-sheet-h{display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid var(--line)}
  /* ★전역 button{width:100%;margin-top:18px;padding:12px} 리셋 — 안 하면 닫기 버튼이 시트를 먹는다(재발 6회 함정) */
  .cv-sheet-x{width:32px;height:32px;flex:none;margin:0;padding:0;border-radius:50%;border:1px solid var(--line);
    background:transparent;color:var(--muted);font-size:14px;cursor:pointer;line-height:1}
  .cv-sheet-t{flex:1 1 auto;text-align:center;font-size:14px;font-weight:700;padding-right:32px}
  .cv-sheet-b{flex:1 1 auto;overflow-y:auto;padding:12px 14px 20px}
  .cv-det{padding:10px 0;border-bottom:1px solid var(--line)}
  .cv-det:last-child{border-bottom:0}
  .cv-det-h{display:flex;align-items:center;gap:8px;margin-bottom:7px;min-width:0}
  .cv-det-h .cv-sub{white-space:normal;word-break:break-all;overflow:visible;opacity:.85}
  .cv-plain{font-size:12.5px;color:var(--fg);opacity:.86;line-height:1.55;margin:3px 0}
  .cv-pre{margin:6px 0 0;padding:9px 11px;border-radius:9px;background:var(--input);border:1px solid var(--line);
    font:11.5px/1.6 ui-monospace,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-all;
    max-height:280px;overflow:auto;color:var(--fg)}
  .cv-preErr{color:#e5484d}
  /* ★말 속 코드 울타리(```)는 접힌 상자 — 26/09/12 유저지적 "xml 코드 그대로 전부 노출". 누르면 펼친다. */
  .cv-fence{margin:6px 0;border:1px solid var(--line);border-radius:9px;overflow:hidden;background:var(--input)}
  .cv-fence-h{display:flex;align-items:center;gap:6px;padding:5px 10px;font-size:12px;cursor:pointer;opacity:.86;user-select:none}
  .cv-fence-h:hover{opacity:1}
  .cv-fence .cv-caret{display:inline-block;transition:transform .15s}
  .cv-fence.open .cv-caret{transform:rotate(90deg)}
  .cv-fence .cv-pre{margin:0;border:0;border-top:1px solid var(--line);border-radius:0}
  .cv-cmd{margin:6px 0 0;padding:8px 11px;border-radius:9px;background:var(--input);border:1px solid var(--line);
    font:11.5px/1.6 ui-monospace,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-all;color:var(--fg)}
  .cv-shot{display:block;margin-top:8px;max-width:100%;border:1px solid var(--line);border-radius:10px}
  /* ★+ - 색줄 — 무엇이 어떻게 바뀌었는지(AI_setting/web.js cdiff 원문 이식) */
  .cv-diff{margin:6px 0 0;border:1px solid var(--line);border-radius:10px;overflow:hidden}
  .cv-diff-h{padding:5px 10px;font-size:11.5px;color:var(--muted);background:var(--panel);
    border-bottom:1px solid var(--line);font-family:ui-monospace,Menlo,Consolas,monospace;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .cv-diff-b{max-height:360px;overflow:auto;background:var(--input)}
  .cv-dl{display:flex;font:11.5px/1.6 ui-monospace,Menlo,Consolas,monospace}
  .cv-dl .cv-dn{flex:none;width:50px;text-align:right;padding:0 8px;color:var(--muted);opacity:.6;
    user-select:none;background:rgba(127,127,127,.06)}
  .cv-dl .cv-dt{flex:1 1 auto;padding:0 10px;color:var(--fg);overflow-wrap:anywhere;white-space:pre-wrap}
  .cv-dl.add{background:rgba(62,207,106,.12)} .cv-dl.add .cv-dt{color:#7fd39b}
  .cv-dl.del{background:rgba(229,72,77,.12)} .cv-dl.del .cv-dt{color:#f0a0a0}
  /* ★모드 탭(챗|에이전트) — 전역 button(width:100%·margin-top:18px·padding:12px) 리셋 필수(재발 5회 함정) */
  .sp-modes{display:inline-flex;gap:6px;margin-left:10px;vertical-align:middle}
  .sp-modes .spm{width:auto;min-width:0;margin:0;padding:3px 12px;font-size:12px;font-weight:600;border-radius:8px;background:transparent;border:1px solid var(--line);color:var(--muted);cursor:pointer}
  .sp-modes .spm.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .sp-foot{display:flex;align-items:center;gap:10px;padding:12px 14px;border-top:1px solid var(--line);flex-wrap:wrap}
  .sp-meta,.sp-msg{font-size:12px;color:var(--muted)}
  .sp-meta:empty,.sp-msg:empty{display:none}   /* 빈 메타/메시지가 자리 차지 금지 */
  .sp-msg.ok{color:#31c48d}
  /* ★전역 button{width:100%;margin-top:18px} 오버라이드(유저지적: 구분선-버튼 간격 과대+정렬 어긋남) */
  .sp-apply{width:100%;margin:0;padding:11px;border-radius:10px;font-weight:600;font-size:14px;text-align:center}
  /* ★유저확정 모델 상태 테이블(연결상태 펼침·새로고침 아래): 구분선+테이블. UI규칙=중앙정렬·세로중앙 */
  .gl-mhr{border-top:1px solid var(--line);margin:10px 0 8px}
  .gl-mt-title{font-size:12px;color:var(--muted);margin:0 0 6px;text-align:left}
  .gl-mtable{width:100%;border-collapse:collapse;table-layout:fixed}
  .gl-mtable th{font-size:10.5px;color:var(--muted);font-weight:500;padding:3px 1px;text-align:center;vertical-align:middle;line-height:1.3}   /* ★keep-all 제거(유저스샷: 긴 라벨이 옆칸과 겹침)→한국어 글자단위 줄바꿈 허용 */
  .gl-mtable td{font-size:12px;padding:4px 2px;text-align:center;vertical-align:middle}
  .gl-mtable td.mst-ready{color:var(--ok,#31c48d)}
  .gl-mtable td.mst-heal{color:var(--danger,#f66)}
  .gl-mtable td.mst-warm{color:#e6b84a}
  .gl-mtable td.mst-none{color:var(--muted)}
  .ci-btn:disabled,#chatSend:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}
  .ci-btn{flex:none;width:38px;height:38px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--input);border:1px solid var(--line);color:var(--muted);cursor:pointer}   /* ★스코프 해제(2026-07-30): .chatinput 이 DOM 에서 사라지며 버튼 거대화된 사고 재발 방지 */
  .ci-btn:hover{color:var(--fg);border-color:var(--muted)}
  .ci-btn svg{width:17px;height:17px}
  .ci-btn.rec{color:var(--danger);border-color:var(--danger)}
  #chatSend{font-size:17px;font-weight:700}
  /* ★가로 넘침 차단: 자식이 안 줄어들면(min-width:auto 기본) flex가 화면 밖으로 밀어낸다.
     실측(폰 390px): 매물개수+GPU+정렬+"Refresh" 4개가 안 들어가 좌우로 짓눌려 세로글씨가 됐다. */
  .rowhead{display:flex;align-items:center;gap:8px;margin:6px 0 14px;min-width:0;max-width:100%}
  .rowhead>*{min-width:0}
  .rowhead h3{margin:0;font-size:18px}
  .rowhead .cnt{color:var(--muted);font-size:13px}
  /* 새로고침 = 아이콘 고정폭. "Refresh"/"새로고침" 글자는 번역 길이에 따라 헤더를 터뜨린다.
     이모지(🔄)는 OS 폰트가 제멋대로 그려서(윈도우=파랑, iOS=초록) 테마색과 따로 논다.
     → 사이드바와 같은 Feather 세트 + stroke:currentColor 로 통일한다. */
  .refresh{flex:0 0 auto;width:36px;height:34px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;background:transparent;border:1px solid var(--line);border-radius:9px;color:var(--muted);cursor:pointer;transition:color .15s,border-color .15s}
  .refresh:hover{color:var(--fg);border-color:var(--fg)}
  .refresh svg{width:16px;height:16px;display:block}
  .refresh.spin svg{animation:rspin .7s linear infinite}
  @keyframes rspin{to{transform:rotate(360deg)}}
  /* 당겨서 새로고침 — 평소 height:0(자리 안 먹음). 당긴 만큼만 열리고, 놓으면 원래 높이로 되돌아간다. */
  .ptr{height:0;overflow:hidden;display:flex;align-items:center;justify-content:center;color:var(--muted)}
  .ptr.snap{transition:height .22s ease}          /* 손 뗀 뒤에만 애니메이션(끄는 중엔 손가락을 그대로 따라가야 함) */
  .ptr-ic{width:20px;height:20px;display:block;opacity:0;transform:rotate(0deg)}
  .ptr.ready .ptr-ic{opacity:1}                    /* 임계치 넘음 = 놓으면 새로고침 */
  .ptr.spin .ptr-ic{opacity:1;animation:rspin .7s linear infinite}
  /* 드롭박스 2개가 남는 폭을 반씩 나눠 갖고, 모자라면 스스로 줄어든다(넘치지 않음). */
  .sortsel{flex:1 1 0;min-width:0;width:auto;margin:0;padding:7px 8px;font-size:13px;background:var(--input);border:1px solid var(--line);border-radius:9px;color:var(--fg);text-overflow:ellipsis}
  .offers{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
  .offer{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px;display:flex;flex-direction:column}
  .offer .gpu{font-weight:700;font-size:16px;margin-bottom:8px}
  .offer .desc{color:var(--muted);font-size:12.5px;margin:4px 0 12px}
  /* 라벨(좌) / 값(우) 2컬럼 grid — 값이 오른쪽에서 시작해 세로줄이 맞는다. 테두리는 안 보임. */
  .offer .spec{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:baseline;gap:10px;font-size:12.5px;padding:4px 0;border-top:1px solid var(--line)}
  .offer .spec .sk{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* ★nowrap 만 주면 값이 길 때(ru/ka 등급 + 긴 숫자) 칸을 밀어내 카드가 화면을 넘는다.
     minmax(0,1fr) + 값 줄바꿈 허용 = 넘치는 대신 두 줄이 된다(깨지지 않게). */
  .offer .spec .gv{text-align:right;min-width:0;overflow-wrap:anywhere}
  /* 등급(영어 고정) + 숫자. 등급은 굵게, 숫자는 흐리게 — 등급이 먼저 읽히게. */
  .grade{font-weight:700}
  .g-very-low{color:#f87171} .g-low{color:#fb923c} .g-normal{color:var(--txt)} .g-high{color:#4ade80} .g-very-high{color:#22d3ee}
  .gn{color:var(--muted);font-style:normal;font-size:11.5px;margin-left:6px}
  /* 가격표 2칸 — ★칸이 나뉘어 블렌딩이 물리적으로 불가능. stretch라 헤더가 2줄(ru/ka)이어도 값은 나란히. */
  .ptbl{display:grid;grid-template-columns:1fr 1fr;align-items:stretch;gap:1px;background:var(--line);border:1px solid var(--line);border-radius:8px;overflow:hidden;margin-top:10px}
  .pcell{background:var(--panel);display:flex;flex-direction:column;align-items:center;justify-content:space-between;padding:6px 4px;gap:2px}
  .ph{color:var(--muted);font-size:11px;text-align:center;line-height:1.25}
  .pv{font-weight:700;font-size:16px}
  .pnote{color:#22d3ee;font-size:11px;margin:6px 0 2px;text-align:center}
  /* 재임대 경고 — 붉은색. 다크/라이트 양쪽에서 읽히는 톤(#f87171은 검은 배경에서 #ef4444보다 대비가 높다). */
  .pnote.warn{color:#f87171;margin:2px 0 2px;font-weight:600}
  .offer .spec .sk{color:var(--muted)}
  .offer .price{margin-top:12px;font-size:22px;font-weight:800}
  .offer .price small{font-size:13px;color:var(--muted);font-weight:600}
  .offer .rent{margin-top:12px;padding:10px}
  .note{color:var(--muted);font-size:13px;text-align:center;padding:24px}
  /* 관리자 개요 카드 */
  .asection{margin-bottom:18px}
  .asec-h{font-size:12px;font-weight:800;letter-spacing:1px;color:var(--muted);text-transform:uppercase;margin:0 2px 8px}
  .asec-reset{width:auto;margin:0;padding:4px 12px;font-size:11px;font-weight:700;letter-spacing:.3px;border-radius:16px;background:transparent;border:1px solid color-mix(in srgb,var(--danger) 45%,transparent);color:var(--danger);cursor:pointer;text-transform:none}
  .asec-reset:hover{border-color:var(--danger)}
  .admincards{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:10px}
  .acard{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px 18px}
  .acard .ak{font-size:12.5px;color:var(--muted)}
  .acard .av{font-size:23px;font-weight:800;margin-top:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .acard .av.txt{font-size:15px;font-weight:600;white-space:normal}
  .acard .av.neg{color:var(--danger)} .acard .av.pos{color:var(--ok)}
  .oversell{background:color-mix(in srgb,var(--danger) 14%,transparent);border:1px solid var(--danger);color:var(--danger);border-radius:10px;padding:12px 14px;font-size:13.5px;font-weight:600;margin-bottom:12px}
  /* 유저 관리 행(마진률 편집) */
  .urow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;background:var(--panel);border:1px solid var(--line);border-radius:10px;margin-bottom:8px;flex-wrap:wrap}
  .urow .u-em{font-weight:600;font-size:13.5px;word-break:break-all}
  .urow .u-cr{color:var(--muted);font-size:12px;margin-top:2px}
  .urow .u-r{display:flex;align-items:center;gap:6px;flex:none}
  /* ★.urow 하위로 스코프하면 회원 상세 모달(.kv)에서 기본 button{width:100%;padding:12px}이 살아나
     '저장'이 전체폭 거대 버튼이 된다(실측). .mini 때와 같은 계열 — 전역으로 둔다. */
  .u-mk{width:66px;margin:0;padding:7px 8px;background:var(--input);border:1px solid var(--line);border-radius:8px;color:var(--fg);font-size:13px;text-align:right}
  .urow .u-pct{color:var(--muted);font-size:13px}
  .urow.suspended{opacity:.6}
  .urow .u-cr{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .u-save,.u-susp,.u-del,.u-alloc{width:auto;margin:0;padding:6px 11px;font-size:12px;font-weight:700;border-radius:8px;cursor:pointer;border:1px solid var(--line);flex:0 0 auto;line-height:1.3}
  .u-save{background:var(--accent);color:#fff;border-color:var(--accent)}
  .urow .u-alloc{background:transparent;color:var(--accent);border-color:var(--accent);padding:3px 9px;font-size:11px}
  .urow .u-susp{background:transparent;color:var(--muted)}
  .urow .u-del{background:transparent;color:var(--danger);border-color:color-mix(in srgb,var(--danger) 45%,transparent)}
  .allocmode{display:flex;align-items:center;gap:14px;margin:14px 0 4px;font-size:13px}
  .seg2{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden}
  .seg2b{width:auto;margin:0;padding:7px 18px;background:transparent;border:0;color:var(--muted);font-size:13px;font-weight:700;cursor:pointer;white-space:nowrap}
  .seg2b.on{background:var(--accent);color:#fff}
  .setval{color:var(--muted);font-weight:600}
  /* 유저 관리 테이블(가로 컬럼) */
  .utblwrap{overflow-x:auto;border:1px solid var(--line);border-radius:12px}
  .utbl{width:100%;border-collapse:collapse;font-size:13px;min-width:560px}
  .utbl th{text-align:center;padding:10px 12px;color:var(--muted);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;border-bottom:1px solid var(--line);white-space:nowrap}
  .utbl td{text-align:center;vertical-align:middle;padding:10px 12px;border-bottom:1px solid var(--line);white-space:nowrap}
  .utbl th{vertical-align:middle}
  .utbl tbody tr:last-child td{border-bottom:0}
  /* ★compact = 짧은 컬럼(문의내역 등) — 고정 min-width만 없앤다(억지 넓힘 제거).
     칸은 내용 글자 폭만큼만 자연스럽게 늘어난다(nowrap 유지 = '처리 상태'·'답변 대기'가 두 줄로 안 찢김).
     넘치면 래퍼(.utblwrap overflow-x:auto)가 가로 스크롤 — 억지로 쪼개 보이지 않게. 마지막 버튼칸은 최소폭. */
  .utbl.compact{min-width:0;width:auto}
  .utbl.compact th,.utbl.compact td{padding:9px 12px}
  .stbadge{white-space:nowrap}
  /* 등급별 할당 테이블 — 4개 짧은 컬럼이라 min-width 강제 스크롤 해제(내용 맞춤), 현재 등급 강조 */
  .tiertbl{min-width:auto;width:100%}
  .tiertbl tbody tr.cur td{color:var(--accent);font-weight:700}
  .utbl tbody tr.susp{opacity:.5}
  .utbl .tag{display:inline-block;margin-left:6px;font-size:10px;font-weight:700;padding:1px 6px;border-radius:10px;background:var(--active);color:var(--accent)}
  .utbl .tag.danger{background:color-mix(in srgb,var(--danger) 18%,transparent);color:var(--danger)}
  .utbl .u-detail{width:auto;margin:0;padding:5px 11px;font-size:12px;font-weight:700;border-radius:8px;background:transparent;border:1px solid var(--accent);color:var(--accent);cursor:pointer}
  /* 유저 세부정보 모달 */
  .umact{margin-top:16px}
  .umact #umAlloc{width:100%;justify-content:center}
  /* ★4개를 한 줄에 균등분할하면 'PW 초기화'가 2줄로 쪼개진다 → 2열 그리드로. 버튼처럼 보이게 배경도 준다. */
  .umbtns{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:10px}
  .umbtn{width:auto;margin:0;padding:10px 8px;font-size:12.5px;font-weight:700;border-radius:9px;background:var(--input);border:1px solid var(--line);color:var(--fg);cursor:pointer;white-space:nowrap;line-height:1.3}
  .umbtn:hover{border-color:var(--muted)}
  .umbtn.danger{color:var(--danger);border-color:color-mix(in srgb,var(--danger) 45%,transparent)}
  .umhist{margin-top:10px;max-height:220px;overflow-y:auto}
  #umMk{width:120px;text-align:right}   /* ⑨ '기본 60%' placeholder 힌트가 짤리지 않게 폭 확대 */
  /* 로그인 옵션(아이디 저장·자동 로그인) */
  .authopts{display:flex;gap:18px;margin:12px 0 4px;flex-wrap:wrap}
  /* 모달 입력(비번 변경 등) */
  /* 인증 폼 — display:contents 로 감싸 레이아웃 영향 0(엔터 제출만 얻는다) */
  #authForm{display:contents}
  /* 탭 세그먼트 — 내정보/관리자 내부 섹션 분리. 폰에서 넘치면 가로로만 스크롤(본문은 안 밀림). */
  .segs{display:flex;gap:4px;padding:4px;margin:0 0 14px;background:var(--input);border:1px solid var(--line);border-radius:11px;overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .segs::-webkit-scrollbar{display:none}
  .segb{flex:1 1 auto;white-space:nowrap;margin:0;padding:8px 12px;background:transparent;border:0;border-radius:8px;color:var(--muted);font-size:13px;font-weight:600;cursor:pointer}
  .segb.on{background:var(--panel);color:var(--fg);box-shadow:0 1px 3px rgba(0,0,0,.3)}
  /* 위젯 그리드 — PC는 여러 칸, 폰은 1칸. minmax(0,·)로 내용이 칸을 밀어내지 못하게 한다. */
  .wgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(240px,100%),1fr));gap:12px}
  .wcard{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px;min-width:0}
  .wcard-h{font-size:11.5px;font-weight:700;color:var(--muted);letter-spacing:.02em;margin:0 0 8px;text-transform:uppercase}
  .wcard-v{font-size:20px;font-weight:800;word-break:break-all}
  .wcard-s{font-size:11.5px;color:var(--muted);margin-top:4px}
  /* 키:값 줄 — 값이 길어도 라벨을 밀지 않고 값 쪽에서 줄바꿈(넘침 방지) */
  .kvl{display:flex;align-items:baseline;gap:10px;padding:9px 2px;border-bottom:1px solid var(--line);font-size:13.5px}
  .kvl:last-child{border-bottom:0}
  .kvl-k{flex:0 0 auto;color:var(--muted);font-size:12.5px}
  .kvl-v{flex:1 1 auto;min-width:0;text-align:right;font-weight:600;word-break:break-word}
  /* ★.mini는 전역 클래스다. .kvl 하위로 스코프하면 .kvl 밖(첨부·공지 버튼)에서
     기본 button(width:100%, padding:12px, font-size:15px)이 그대로 먹어 버튼이 화면을 다 먹는다(실측).
     ※web.js=백틱 템플릿이라 주석에도 백틱을 쓰면 안 된다 — 거기서 템플릿이 끊긴다. */
  .mini{flex:0 0 auto;width:auto;margin:0;padding:5px 10px;font-size:12px;font-weight:700;border-radius:8px;background:var(--input);border:1px solid var(--line);color:var(--fg);cursor:pointer;line-height:1.3}
  /* 코드 표시 — 복사 가능한 고정폭 */
  .refbox{display:flex;align-items:center;gap:8px}
  .refval{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:15px;font-weight:800;letter-spacing:2px}
  /* 표 — 좌우 넘침은 표 안에서만(페이지는 안 흔들림) */
  .tblwrap{width:100%;overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch}
  .dtbl{width:100%;border-collapse:collapse;font-size:12.5px;white-space:nowrap}
  .dtbl th{text-align:center;vertical-align:middle;padding:8px 10px;color:var(--muted);font-size:11px;font-weight:700;text-transform:uppercase;border-bottom:1px solid var(--line)}
  .dtbl td{text-align:center;vertical-align:middle;padding:9px 10px;border-bottom:1px solid var(--line)}
  .dtbl tr:last-child td{border-bottom:0}
  .dtbl .pos{color:#34d399;font-weight:700}
  .dtbl .neg{color:#f87171;font-weight:700}
  /* ★모든 테이블 표준(유저확정 2026-07-19): 금액칸(.num)만 우측정렬(자릿수 세로 정렬), 나머지 텍스트는 중앙 */
  .dtbl .num,.utbl .num{text-align:right}
  /* 총판 마진율 설정칸 */
  .distmk-wrap{display:flex;align-items:center;justify-content:center;gap:3px}
  .distmk-inp{width:36px;padding:3px 4px;font-size:12px;text-align:right;border:1px solid var(--line);border-radius:5px;background:var(--input);color:var(--fg)}
  .distmk-inp::-webkit-outer-spin-button,.distmk-inp::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
  .distmk-pct{color:var(--muted);font-size:12px}
  .distmk-btn{padding:3px 8px;font-size:12px;font-weight:700;border:1px solid var(--accent);border-radius:5px;background:transparent;color:var(--accent);cursor:pointer;white-space:nowrap}
  .distmk-btn:hover{background:var(--active)}
  .mini.danger{background:transparent;border-color:var(--danger);color:var(--danger)}
  .mini:disabled{opacity:.45;cursor:not-allowed}
  /* System 메시지(지급 대기) — 유저 문의와 시각적으로 구분. 답변칸이 없다. */
  .sysmsg{background:var(--input);border:1px solid var(--line);border-left:3px solid #f59e0b;border-radius:9px;padding:11px 12px;margin:0 0 9px}
  .sysmsg.done{border-left-color:#34d399;opacity:.75}
  .sysmsg-h{display:flex;align-items:center;gap:8px;margin-bottom:6px}
  .sysmsg-au{font-size:11.5px;font-weight:800;color:#f59e0b;letter-spacing:.04em}
  .sysmsg.done .sysmsg-au{color:#34d399}
  .sysmsg-d{font-size:11px;color:var(--muted)}
  .sysmsg-b{font-size:12.5px;line-height:1.5;word-break:break-word}
  .sysmsg-a{display:flex;align-items:center;gap:8px;margin-top:9px}
  .sysmsg-wait{font-size:11px;color:var(--muted)}
  .sysmsg-ok{font-size:11px;color:#34d399;font-weight:600}
  /* 비율 조절 — 슬라이더 + 숫자칸. 폰에서 줄바꿈돼도 넘치지 않게 wrap. */
  .pctrow{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .pctrng{flex:1 1 140px;min-width:0;margin:0;accent-color:var(--accent,#4b8cf7)}
  .pctbox{flex:0 0 auto;display:flex;align-items:center;gap:3px;background:var(--input);border:1px solid var(--line);border-radius:8px;padding:0 8px}
  .pctnum{width:52px;margin:0;padding:7px 0;background:transparent;border:0;color:var(--fg);font-size:13px;font-weight:700;text-align:right}
  .pctsuf{font-size:12px;color:var(--muted)}
  .pcthint{font-size:11.5px;color:var(--muted);margin-top:8px;line-height:1.45}
  .fundrow{display:flex;align-items:baseline;justify-content:space-between;gap:10px;padding:3px 0;font-size:12.5px}
  /* 크레딧 부족 = 임대 버튼 비활성. 눌러도 안 되는 걸 눈으로 알려준다 */
  .offer .rent:disabled,.offer .rent.short{opacity:.5;cursor:not-allowed;background:var(--input);border:1px solid var(--line);color:var(--muted)}
  /* 비밀번호 + 눈 아이콘. 아이콘이 글자를 가리지 않게 input 오른쪽 패딩을 확보한다. */
  .pwwrap{position:relative}
  .pwwrap input{width:100%;padding-right:44px!important}
  .eye{position:absolute;top:50%;right:6px;transform:translateY(-50%);width:32px;height:32px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;background:transparent;border:0;border-radius:8px;color:var(--muted);cursor:pointer}
  .eye:hover{color:var(--fg)}
  .eye svg{width:18px;height:18px;display:block}
  .eye .ey-off{display:none}
  .eye.on .ey-on{display:none} .eye.on .ey-off{display:block}   /* 보이는 상태 = 취소선 눈 */
  .modalbox label{display:block;font-size:12.5px;color:var(--muted);margin:12px 0 5px}
  .modalbox input[type=password],.modalbox input[type=text]{width:100%;padding:11px 13px;background:var(--input);border:1px solid var(--line);border-radius:9px;color:var(--fg);font-size:14px}
  .modalbox #pwSubmit{width:100%;margin-top:16px;padding:11px;font-weight:700}
  .hidden{display:none}
  [dir=rtl] .spec{direction:rtl}
  /* ── 알림/문의 시스템 ── */
  .bell{position:relative;width:36px;height:36px;margin:0 0 0 8px;padding:0;display:flex;align-items:center;justify-content:center;background:transparent;border:1px solid var(--line);color:var(--fg);border-radius:10px;cursor:pointer;flex:none}
  .bell .bic{width:19px;height:19px}
  .bell:hover{border-color:var(--muted)}
  .bdot{position:absolute;top:-6px;right:-6px;min-width:17px;height:17px;padding:0 4px;background:var(--danger);color:#fff;border-radius:9px;font-size:10px;font-weight:800;display:flex;align-items:center;justify-content:center;line-height:1}
  .bell .bdot.hidden{display:none}   /* ★.bdot{display:flex} 가 뒤라 .hidden 을 덮음 → 2클래스 규칙으로 확실히 숨김(미읽음 0) */
  /* 알림 팝오버 — 종 아래에 붙는다. 헤더 기준 fixed라 본문 스크롤과 무관하게 제자리.
     폰에선 좌우 12px 여백 안에서 화면폭을 넘지 않게(가로 스크롤 유발 금지). */
  .bellpop{position:fixed;top:56px;right:12px;z-index:40;width:min(340px,calc(100vw - 24px));max-height:min(420px,calc(100dvh - 90px));overflow-y:auto;overscroll-behavior:contain;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:12px;box-shadow:0 12px 32px rgba(0,0,0,.45)}
  .bellpop-h{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:800;letter-spacing:1px;color:var(--muted);text-transform:uppercase;margin:0 2px 10px}
  .bellpop-list{font-size:13px}
  /* 공지사항 — 제목 줄(제목 + 작성일자), 클릭 시 본문 펼침 */
  .nitem{border-bottom:1px solid var(--line)}
  .nitem:last-child{border-bottom:0}
  .nitem-h{width:100%;margin:0;padding:12px 2px;display:flex;align-items:center;gap:10px;background:transparent;border:0;color:var(--fg);text-align:left;cursor:pointer;font:inherit}
  .nitem-t{flex:1;min-width:0;font-size:13.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}  /* 긴 제목이 날짜를 밀어내지 않게 */
  .nitem-d{flex:0 0 auto;font-size:11.5px;color:var(--muted)}
  .nitem.open .nitem-t{color:var(--accent,#4b8cf7)}
  .nitem-b{padding:0 2px 14px;font-size:13px;line-height:1.6;color:var(--muted);word-break:break-word;white-space:pre-wrap}   /* ★등록한 줄바꿈 형태 그대로(유저확정) */
  .nitem-a{display:flex;align-items:center;gap:8px;padding:0 2px 12px;flex-wrap:wrap}
  /* 등록 '+' — 정사각. 제목 옆에서 폭을 안 먹는다. */
  .nplus{width:30px;height:30px;padding:0;display:flex;align-items:center;justify-content:center;font-size:17px;font-weight:800}
  /* 첨부 삭제 '×'도 같은 정사각 */
  .atrow .mini.danger,.nemedia .mini.danger{width:26px;height:26px;padding:0;display:flex;align-items:center;justify-content:center;font-size:14px}
  .nempty{padding:22px 2px;text-align:center;color:var(--muted);font-size:13px}
  /* 공지 본문 블록 — 글은 줄바꿈 보존, 미디어는 폭에 맞춰 축소(가로 넘침 금지) */
  .nbtext{white-space:pre-wrap;margin:0 0 10px}
  .nbmedia{display:block;max-width:100%;height:auto;border-radius:9px;margin:0 0 10px;background:var(--input)}
  /* 첨부파일 목록 — 제목 바로 아래 */
  .atlabel{font-size:11.5px;font-weight:700;color:var(--muted);text-transform:uppercase;margin:0 0 6px}
  .atlist{margin:0 0 12px}
  .atrow{display:flex;align-items:center;gap:8px;padding:7px 9px;background:var(--input);border:1px solid var(--line);border-radius:8px;margin-bottom:6px}
  /* ★파일명은 자르지 않고 전부 보인다(유저확정) — 긴 이름은 줄바꿈. 잘라놓으면 뭘 받는지 모른다. */
  .atname{flex:1 1 auto;min-width:0;font-size:12.5px;color:var(--fg);word-break:break-all;line-height:1.35}
  .atsize{flex:0 0 auto;font-size:11px;color:var(--muted);white-space:nowrap}
  /* 다운로드 = 아이콘 정사각 버튼. 글자를 넣으면 언어마다 폭이 달라지고 파일명 자리를 뺏는다. */
  .atdl{flex:0 0 auto;width:30px;height:30px;padding:0;display:flex;align-items:center;justify-content:center}
  .atdl svg{width:15px;height:15px;display:block}
  /* 공지 편집기 */
  .atbtns{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:10px 0 4px}
  .upmsg{font-size:11.5px;color:var(--muted)}
  /* 본문 = 글과 이미지가 한 칸에 같이 사는 리치 에디터(textarea로는 이미지를 못 담는다) */
  /* ★46vh 고정은 키보드가 뜨면 화면보다 커져 커서가 박스 밖으로 나간다 → --appH 기준으로.
     min-height도 낮춘다(키보드 올라온 상태에서 160px을 강제하면 버튼이 화면 밖으로 밀린다). */
  .nebody{width:100%;min-height:96px;max-height:calc(var(--appH,100dvh) * 0.32);overflow-y:auto;overscroll-behavior:contain;padding:10px 12px;background:var(--input);border:1px solid var(--line);border-radius:9px;color:var(--fg);font-size:13.5px;line-height:1.6;outline:none}
  .nebody:focus{border-color:var(--accent,#4b8cf7)}
  .nebody:empty:before{content:attr(data-ph);color:var(--muted)}
  /* 이미지는 원본 크기 유지 + 상한만(늘리면 32px 이미지도 박스가 200px로 부푼다) */
  .nebody img,.nebody video{display:block;max-width:100%;height:auto;max-height:220px;border-radius:6px;margin:8px 0}
  .nebody img.sel,.nebody video.sel{outline:2px solid var(--accent,#4b8cf7)}
  /* 미리보기를 못 받았을 때(권한·네트워크) — X박스 대신 회색 자리 */
  .nemedia-err{min-height:60px;min-width:60px;background:var(--line);opacity:.5}
  .notifcols{display:flex;gap:14px;align-items:flex-start;flex-wrap:wrap}
  .notifcol{flex:1;min-width:290px;background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px}
  .notifcol-h{font-size:12px;font-weight:800;letter-spacing:1px;color:var(--muted);text-transform:uppercase;margin:0 2px 12px;display:flex;align-items:center;gap:8px}
  .notifcol-h .grow{flex:1}
  .nclear{width:auto;margin:0;padding:5px 11px;font-size:12px;font-weight:700;border-radius:8px;background:transparent;border:1px solid var(--line);color:var(--muted)}
  .nclear:hover{border-color:var(--danger);color:var(--danger)}
  .ncard{position:relative;border:1px solid var(--line);border-radius:10px;padding:12px 34px 12px 14px;margin-bottom:8px;cursor:pointer;background:var(--bg)}
  .ncard:hover{border-color:var(--muted)}
  .ncard.unread{border-color:var(--accent);background:var(--active)}
  .ncard .nt{font-weight:700;font-size:14px;display:flex;align-items:center;gap:7px}
  .ncard .ndot{width:7px;height:7px;border-radius:50%;background:var(--accent);flex:none}
  .ncard .nmeta{color:var(--muted);font-size:12px;margin-top:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ncard .nx{position:absolute;top:8px;right:8px;width:22px;height:22px;margin:0;padding:0;display:flex;align-items:center;justify-content:center;border-radius:6px;background:transparent;border:0;color:var(--muted);font-size:16px;line-height:1}
  .ncard .nx:hover{color:var(--danger)}
  .segrow{display:flex;gap:0;margin-bottom:14px}
  .msgbody{white-space:pre-wrap;word-break:break-word;font-size:14px;line-height:1.6;background:var(--input);border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-top:6px}
  .msgreply{margin-top:14px}
  .msgreply .rl{font-size:12px;font-weight:800;letter-spacing:.5px;color:var(--muted);text-transform:uppercase;margin-bottom:6px}
  .modalbox textarea{width:100%;padding:11px 13px;background:var(--input);border:1px solid var(--line);border-radius:9px;color:var(--fg);font-size:14px;font-family:inherit;resize:vertical;min-height:104px}
  /* ★알림 탭 폼 요소(탭 패널·모달 밖) — 제목 input/select 는 전역 input,select 규칙으로 정상이나 textarea 는 전역 규칙이 없어 브라우저 기본(좁은 폭·흰 배경)으로 깨짐 → 기존 인풋과 동일 스타일로 통일. */
  #tab-notif textarea{width:100%;padding:11px 13px;background:var(--input);border:1px solid var(--line);border-radius:9px;color:var(--fg);font-size:14px;font-family:inherit;line-height:1.5;resize:vertical;min-height:104px}
  #tab-notif input,#tab-notif select,#tab-notif textarea{box-sizing:border-box}
  .pager{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:12px}
  .pager button{width:auto;margin:0;padding:6px 14px;font-size:13px;font-weight:700;border-radius:8px;background:var(--input);border:1px solid var(--line);color:var(--fg)}
  .pager button:disabled{opacity:.4;cursor:default}
  .pager .pgnum{font-size:13px;color:var(--muted)}
  .stbadge{display:inline-block;font-size:11px;font-weight:700;padding:2px 9px;border-radius:20px}
  .stbadge.pending{background:rgba(255,159,67,.16);color:#ff9f43}
  .stbadge.answered{background:rgba(62,207,142,.15);color:var(--ok)}
  .stbadge.off{background:rgba(140,140,150,.15);color:var(--muted)}
  .umsec-h{margin:16px 0 6px;font-size:12px;font-weight:700;color:var(--muted);letter-spacing:.02em}
  #umTabInfo .kv:first-child,#umTabStatus .umsec-h:first-child{margin-top:2px}

  /* ── 로고를 등록하지 않았을 때 ────────────────────────────
     ★로고 등록을 강요하지 않는다 — 없는 사람은 거기서 막힌다.
     대신 ★이름 첫 글자를 로고와 ★같은 자리·같은 크기로 띄운다.
     (이름을 바꾸면 글자도 따라 바뀐다 — 서버가 letter 를 계산해 준다) */
  .logoletter{height:30px;width:30px;flex:none;display:flex;align-items:center;justify-content:center;
    border-radius:8px;background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 45%,#7c5cff));
    color:#fff;font-weight:800;font-size:15px;line-height:1;letter-spacing:0}
  .logoletter[hidden]{display:none}

  /* 이름을 그림으로 받은 경우 — 글자 대신 그림이 들어온다(그 글씨체가 이 컴퓨터엔 없다) */
  .logotext .wordmark{height:16px;width:auto;max-width:180px;display:block}

  /* ── 채팅 모드 배치(26/08/19 이식) — 로그인 화면은 카드 중앙, 채팅은 통짜로 채운다 ── */
  body.inapp main{align-items:stretch;overflow:hidden;padding:0 12px}
  #tab-chat.hidden{display:none}
  .chatdock{bottom:0}
  /* (26/08/19) 입력창 겹침 여백은 삭제 — positionDock(JS)이 tab-chat 높이를 dock 위에서 끝낸다(옛 방식 이식) */

  /* 메뉴 버튼은 로그인 전엔 숨긴다(로그인 화면은 로고 중앙 단독) */
  body:not(.inapp) .menubtn{display:none}
  /* 아직 안 만든 메뉴 = SOON — 눌리지 않게, 눌릴 것처럼 보이지도 않게 */
  .sideitem:disabled{opacity:.55;cursor:default}

  /* ── 이식 화면 3개(공지·고객센터·저장공간) — 26/08/19 ──
     body.inapp main 은 overflow:hidden(채팅 전용 잠금)이라, 이 패널들은 옛 .content(원문
     web.js 269줄: flex:1·overflow-y:auto·padding 14px 16px)의 성질을 자기 몸에 지니고 스스로 스크롤한다. */
  #tab-storage,#tab-notif,#tab-notice{flex:1;min-height:0;overflow-y:auto;padding:14px 16px calc(14px + var(--kbH,0px))}
  /* ★내 계정 — 위쪽에 ★제목 줄이 오므로 플로팅 [메뉴] 버튼(.fab-back top:4px)만큼 더 내린다.
     안 내리면 제목이 그 버튼에 가려 잘린다(유저제보 26/08/25 IMG_2543/2544 "글자잘림"). */

  /* 로고 클릭 = 채팅 메인(허브·유저지시 26/08/21) — 로그인 화면에서는 동작 없음(pointer 도 없음).
     당겨서 새로고침의 .ptr/.ptr-ic CSS 는 위 917~921(옛 화면 이식분)을 그대로 쓴다 — 중복 신설 금지. */
  body.inapp .logo{cursor:pointer}

  /* ── 라이브러리(pages/library.js · 26/08/22) — 전체 화면 모달 + 썸네일 그리드 ──
     ★전역 button{width:100%;margin-top:18px} 규칙이 있어 새 버튼은 width:auto·margin-top:0 을 명시한다. */
  .lib-modal{position:fixed;inset:0;z-index:90;background:var(--bg);display:flex;flex-direction:column}
  .lib-head{flex:none;display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--line)}
  .lib-title{font-size:16px;font-weight:700;color:var(--fg)}
  .lib-x{width:auto;margin-top:0;padding:2px 10px;background:transparent;border:0;color:var(--muted);font-size:22px;line-height:1;font-weight:400;cursor:pointer}
  .lib-x:hover{color:var(--fg);filter:none}
  .lib-body{flex:1;min-height:0;overflow-y:auto;padding:14px 16px calc(14px + var(--kbH,0px))}
  .lib-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:10px}
  .lib-cell{display:flex;flex-direction:column;gap:6px;min-width:0}
  .lib-thumb{width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:10px;border:1px solid var(--line);background:var(--input);display:block}
  .lib-doc-ic{width:100%;aspect-ratio:1/1;display:flex;align-items:center;justify-content:center;font-size:34px;border-radius:10px;border:1px solid var(--line);background:var(--input)}
  .lib-name{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center}
  /* 빈 상태 — 가운데 아이콘+문구(챗지피티 라이브러리 결). 그리드 전체 폭을 차지한다. */
  .lib-empty{grid-column:1/-1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:64px 0;color:var(--muted)}
  .lib-empty-ic{font-size:40px;opacity:.7}
  .lib-empty-t{font-size:14px}
  .lib-more{width:auto;margin:16px auto 0;display:block;padding:9px 22px;background:transparent;border:1px solid var(--line);color:var(--muted);font-weight:500;font-size:13.5px;border-radius:999px;cursor:pointer}
  .lib-more:hover{background:var(--input);filter:none}
  .lib-more[hidden]{display:none}

/* ★대기줄 말풍선 — 답하는 중에 보낸 글(원본 web.js 597~606 그대로 이식 · 유저지시 26/08/23) */
  .qbubble{align-self:flex-end;max-width:80%;display:flex;flex-direction:column;gap:7px;padding:10px 13px 9px;border-radius:14px;background:color-mix(in srgb, var(--accent) 5%, var(--panel));border:1px dashed color-mix(in srgb, var(--accent) 32%, var(--line));opacity:.92}
  .qbubble .qb-head{display:flex;align-items:center;gap:7px}
  .qbubble .qb-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 9px;border-radius:20px;background:color-mix(in srgb, var(--accent) 13%, transparent);color:var(--accent);font-size:11px;font-weight:700;letter-spacing:-.1px;white-space:nowrap}
  .qbubble .qb-badge .qb-dot{width:6px;height:6px;border-radius:50%;background:var(--accent);animation:qbpulse 1.4s ease-in-out infinite}
  .qbubble .qb-num{font-size:11px;font-weight:600;color:var(--muted)}
  .qbubble .qb-text{white-space:pre-wrap;word-break:break-word;font-size:14px;line-height:1.55;color:var(--fg)}
  .qbubble .qb-ctl{display:flex;justify-content:flex-end;gap:6px;margin-top:1px}
  .qbubble .qb-btn{width:auto;min-width:0;margin:0;padding:3px 11px;background:transparent;border:1px solid var(--line);border-radius:8px;font-size:11.5px;font-weight:600;line-height:1;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;gap:4px}
  .qbubble .qb-btn.edit:hover{border-color:var(--accent);color:var(--accent)}
  .qbubble .qb-btn.del:hover{border-color:var(--danger);color:var(--danger)}
  @keyframes qbpulse{0%,100%{opacity:1}50%{opacity:.3}}

/* 시작 화면 안내 한 줄 — 예시 카드 아래(유저제안 26/08/24) */
.eh-note{margin-top:14px;font-size:12px;line-height:1.5;opacity:.55;text-align:center;
  max-width:420px;padding:0 16px;word-break:keep-all}


/* 대기줄 카드의 첨부 — ★무엇이 같이 나갈지 대기 중에도 보여 준다(26/08/25).
   종전엔 큐에 글만 담겨 이미지가 조용히 빠졌다(유저지적 "큐스텍에 왜 이미지는안들어가고"). */
.qb-att{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.qb-att img{width:44px;height:44px;object-fit:cover;border-radius:8px;flex:none}
.qb-att span{font-size:11px;padding:3px 8px;border-radius:8px;border:1px solid var(--line);
  color:var(--muted);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ══ 내 계정(모달) — 26/08/25 전면 개편 ═══════════════════════════════════
   ★유저지적 "너무 허접해 · 상용앱 수준으로 진짜 오디자인잘뽑았다싶을정도로".
   ★설계: ①모달이라 플로팅 [메뉴] 버튼이 자동으로 숨는다(겹침 원천 제거)
          ②닫는 길은 × 하나 · 되돌아가는 길은 ‹ 하나 — 버튼이 겹쳐 보이지 않는다
          ③손가락이 닿는 높이(56px)와 넉넉한 안쪽 여백 — 잘림이 생길 수 없게 min-height 로 잡는다 */
.acctbox{width:min(560px,92vw);max-height:86vh;padding:0;overflow:hidden;display:flex;flex-direction:column}
#acctBox{overflow-y:auto;-webkit-overflow-scrolling:touch;padding:34px 20px 24px}

/* 프로필 카드 — 동그란 머리글자 + 메일 + 등급 */
.acct-me{display:flex;align-items:center;gap:14px;padding:4px 2px 20px}
.acct-av{width:52px;height:52px;flex:none;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-size:21px;font-weight:700;color:#fff;letter-spacing:.5px;
  background:linear-gradient(135deg,#4f8cff,#7b5cff);box-shadow:0 4px 14px rgba(79,140,255,.28)}
.acct-me-c{min-width:0;display:flex;flex-direction:column;gap:6px}
.acct-mail{font-size:16px;font-weight:600;word-break:break-all;line-height:1.3}
.acct-badge{align-self:flex-start;font-size:11px;font-weight:600;letter-spacing:.3px;
  padding:3px 10px;border-radius:999px;background:var(--input);border:1px solid var(--line);color:var(--muted)}
.acct-badge.paid{background:linear-gradient(135deg,#4f8cff,#7b5cff);border-color:transparent;color:#fff}

/* 목록 — 한 줄 56px, 아이콘 + 이름 + 값 + 화살표 */
.acct-list{border:1px solid var(--line);border-radius:16px;overflow:hidden;background:var(--card)}
.acct-row{display:flex;align-items:center;justify-content:space-between;width:100%;
  min-height:56px;padding:0 16px;margin:0;background:none;border:0;border-bottom:1px solid var(--line);
  color:inherit;font-size:15px;text-align:left;cursor:pointer;transition:background .15s}
.acct-row:last-child{border-bottom:0}
.acct-row:active{background:var(--input)}
.acct-row-l{display:flex;align-items:center;gap:12px;font-weight:500;min-width:0}
.acct-ic{width:19px;height:19px;flex:none;opacity:.75}
.acct-row-r{display:flex;align-items:center;gap:8px;color:var(--muted);font-size:14px;flex:none}
.acct-arrow{width:16px;height:16px;opacity:.4}

/* 항목 화면 머리 — ‹ + 제목. ★min-height 로 잡아 글자가 잘릴 수 없게 한다 */
.acct-bar{display:flex;align-items:center;gap:10px;min-height:40px;margin:0 0 18px}
.acct-back{width:36px;height:36px;flex:none;margin:0;padding:0;border-radius:11px;
  border:1px solid var(--line);background:var(--input);color:inherit;cursor:pointer;
  display:flex;align-items:center;justify-content:center}
.acct-back svg{width:17px;height:17px}
.acct-title{font-size:18px;font-weight:700;letter-spacing:-.2px}
.acct-body{display:flex;flex-direction:column;gap:14px}

/* 카드 */
.acct-card{border:1px solid var(--line);border-radius:16px;background:var(--card);padding:18px}
.acct-card.danger{border-color:rgba(217,83,79,.35)}
.acct-lab{font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--muted);
  text-transform:uppercase;margin-bottom:12px}
.acct-help{font-size:12.5px;color:var(--muted);line-height:1.65;margin-top:10px;word-break:keep-all}
.acct-warn{font-size:12px;color:#e0a33e;line-height:1.6;margin:8px 0 14px;word-break:keep-all}
.acct-over{font-size:13px;color:#e2635f;line-height:1.65;margin-bottom:14px;word-break:keep-all}

/* 입력칸 · 버튼 */
.acct-in{width:100%;margin:0 0 10px;padding:13px 14px;border-radius:12px;
  border:1px solid var(--line);background:var(--input);color:inherit;font-size:15px;
  transition:border-color .15s}
.acct-in:focus{outline:none;border-color:#4f8cff}
.acct-btn{width:100%;margin:8px 0 0;padding:13px 14px;border-radius:12px;border:0;
  background:#4f8cff;color:#fff;font-size:15px;font-weight:600;cursor:pointer;transition:opacity .15s}
.acct-btn:active{opacity:.85}
.acct-btn:disabled{opacity:.45}
.acct-btn.ghost{background:var(--input);color:inherit;border:1px solid var(--line)}
.acct-btn.danger{background:transparent;color:#e2635f;border:1px solid rgba(217,83,79,.5)}

/* 결제 — 지금 등급 크게, 그 아래 등급 카드들 */
.acct-now-card{border:1px solid var(--line);border-radius:16px;padding:18px;
  background:linear-gradient(135deg,rgba(79,140,255,.10),rgba(123,92,255,.06))}
.acct-now{font-size:26px;font-weight:700;letter-spacing:-.4px}
.acct-plans{display:flex;flex-direction:column;gap:12px}
.acct-plan{border:1px solid var(--line);border-radius:16px;background:var(--card);padding:18px}
.acct-plan.cur{border-color:#4f8cff;box-shadow:0 0 0 1px rgba(79,140,255,.35)}
.acct-plan-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.acct-plan-n{font-size:17px;font-weight:700}
.acct-plan-p{font-size:15px;color:var(--muted);white-space:nowrap}
.acct-plan-p b{font-size:20px;color:inherit;font-weight:700}
.acct-plan-mo{font-size:12px;opacity:.7}
.acct-plan-d{font-size:13px;color:var(--muted);margin-top:8px}
.acct-empty{font-size:13px;color:var(--muted);text-align:center;padding:28px 10px;line-height:1.6}

/* 입금 안내 — 눈으로 옮겨 적는 값이라 크고 또렷하게 */
.acct-amt{font-size:25px;font-weight:700;font-family:ui-monospace,Menlo,Consolas,monospace;
  word-break:break-all;letter-spacing:-.3px}
.acct-addr{font-size:12.5px;font-family:ui-monospace,Menlo,Consolas,monospace;word-break:break-all;
  background:var(--input);border:1px solid var(--line);border-radius:12px;padding:13px;line-height:1.55}
.acct-wait{display:flex;align-items:center;gap:9px;margin-top:16px;font-size:13px;color:var(--muted)}
.acct-dot{width:8px;height:8px;border-radius:50%;background:#4f8cff;flex:none;animation:acctp 1.4s ease-in-out infinite}
.acct-wait.done .acct-dot{background:#43c07a;animation:none}
.acct-wait.off .acct-dot{background:var(--muted);animation:none}
.acct-wait.done .acct-wait-t{color:#43c07a;font-weight:600}
@keyframes acctp{0%,100%{opacity:1}50%{opacity:.25}}

/* 사용량 — 퍼센트 + 굵은 막대(숫자는 안 보여 준다) */
.acct-use-top{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:14px}
.acct-use-top .acct-lab{margin:0}
.acct-use-p b{font-size:24px;font-weight:700;letter-spacing:-.5px}
.acct-use-s{font-size:12px;color:var(--muted)}
.acct-gauge{height:10px;background:var(--input);border-radius:99px;overflow:hidden}
.acct-gauge-f{height:100%;border-radius:99px;transition:width .45s cubic-bezier(.4,0,.2,1);
  background:linear-gradient(90deg,#4f8cff,#7b5cff)}
.acct-gauge-f.over{background:linear-gradient(90deg,#e2635f,#d9534f)}

/* 알림 — 토글 스위치(네이티브 체크박스는 앱처럼 안 보인다) */
/* ★label 은 전역 규칙(display:block 등)이 걸려 있어 ★!important 로 못을 박는다 —
   안 그러면 flex 가 안 먹어 토글이 2px 로 찌부러진다(실측 26/08/25). */
.acct-sw{display:flex !important;align-items:center;justify-content:space-between;gap:12px;
  margin:16px 0 0 !important;font-size:15px;cursor:pointer;user-select:none;width:100%}
.acct-sw-t{font-weight:500}
.acct-sw input{position:absolute;opacity:0;width:0;height:0}
.acct-sw-b{position:relative;display:block;width:50px;height:30px;flex:none;border-radius:99px;
  background:var(--input);border:1px solid var(--line);transition:background .2s,border-color .2s}
.acct-sw-b::after{content:'';position:absolute;top:3px;left:3px;width:22px;height:22px;border-radius:50%;
  background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform .2s}
.acct-sw input:checked + .acct-sw-b{background:#4f8cff;border-color:#4f8cff}
.acct-sw input:checked + .acct-sw-b::after{transform:translateX(20px)}

/* 결제 화면에 합류한 것들 — 내 씀씀이 막대 + 등급이 주는 것 목록(26/08/25) */
.acct-ub{margin-bottom:14px}
.acct-ub:last-child{margin-bottom:0}
.acct-ub-t{display:flex;justify-content:space-between;align-items:baseline;
  font-size:13px;color:var(--muted);margin-bottom:6px}
.acct-ub-v{font-weight:600;color:inherit;opacity:.9;font-size:12.5px}
.acct-gauge.sm{height:6px}
.acct-feat{display:flex;flex-direction:column;gap:7px;margin:12px 0 4px}
.acct-feat-i{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--muted)}
.acct-fi{width:14px;height:14px;flex:none;color:#4f8cff;stroke-width:2.4}

/* 한도 소진 안내 — 말풍선 자리에 '무엇을 하면 되는지' 까지 담는다(26/08/25).
   ★막혔다는 말만 하면 손님은 고장으로 읽는다. */
.quotacard{border:1px solid var(--line);border-radius:14px;background:var(--input);padding:16px;margin:2px 0}
.qc-msg{font-size:14px;line-height:1.7;white-space:pre-line;word-break:keep-all}
.qc-when{font-size:12px;color:var(--muted);margin-top:10px}
.qc-btn{width:100%;margin-top:14px;padding:12px;border-radius:11px;border:0;
  background:#4f8cff;color:#fff;font-size:15px;font-weight:600;cursor:pointer}
.qc-btn:active{opacity:.85}
/* 사이드바 하단이 [로그인] 일 때 — 메일 줄이 비므로 라벨을 가운데로 */
.sideprofile.guest .sp-email{display:none}
.sideprofile.guest .sp-label{font-size:13px;font-weight:600;color:inherit}

/* ── 등급 고르기 = 탭 + 카드 하나 + 아래 버튼 ─────────────────────────────
   ★AI_setting backend/src/web.js 157~180 원문 이식(색 변수만 이 프로젝트 것으로).
   ★왜 이 짜임인가: 등급 카드를 나란히 늘어놓으면 ★모바일에서 가로 스크롤이 생겨
   버튼이 화면 밖으로 나간다(옛 실측). 한 번에 ★하나만 보여 주면 그 일이 원천적으로 없다. */
.acct-planbox{display:flex;flex-direction:column}
.planseg{display:flex;gap:2px;background:var(--input);border-radius:11px;padding:3px;margin:2px 0 12px}
/* ★margin:0 !important 필수 — 전역 button 규칙의 margin-top:18px 이 상속돼 탭 버튼이 아래로 밀린다(옛 실측) */
.plansegb{flex:1;width:auto;margin:0 !important;padding:8px 2px;border:0;border-radius:8px;background:transparent;
  color:var(--muted);font-size:12.5px;font-weight:600;cursor:pointer;white-space:nowrap;letter-spacing:-.2px;
  transition:background .15s,color .15s}
.plansegb.on{background:var(--panel);color:var(--fg);font-weight:800;box-shadow:0 1px 3px rgba(0,0,0,.25)}
.plancard2{border:1px solid var(--line);border-radius:16px;padding:0 16px 6px;background:var(--panel)}
.plancard2.hi{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset,0 4px 16px rgba(79,140,255,.12)}
.plancard2h{display:flex;justify-content:space-between;align-items:flex-end;gap:10px;
  padding:14px 0 12px;border-bottom:1px solid var(--line)}
.plancard2n{font-size:16px;font-weight:800;letter-spacing:-.3px}
.plancard2p{text-align:right;white-space:nowrap}
.plancard2p b{font-size:26px;font-weight:800;letter-spacing:-.6px}
.plancard2mo{font-size:12.5px;color:var(--muted);font-weight:600}
.plantag{display:inline-block;margin-left:6px;padding:2px 7px;border-radius:99px;background:var(--accent);
  color:#fff;font-size:10.5px;font-weight:800;letter-spacing:.2px;vertical-align:2px}
.planrow{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:12px 0;
  border-bottom:1px solid var(--line)}
.planrow:last-child{border-bottom:0}
.planrowl{color:var(--muted);font-size:13px;display:flex;align-items:center;gap:7px;white-space:nowrap}
.planrowl svg{width:15px;height:15px;flex:0 0 15px;opacity:.75}
.planrowv{text-align:right;font-weight:800;font-size:15px;letter-spacing:-.2px}
.planbadge{margin-top:12px;text-align:center;color:var(--accent);font-weight:700;font-size:13.5px;
  padding:13px 0;border:1px dashed var(--line);border-radius:12px}
.plannote{margin-top:10px;text-align:center;font-size:12px;color:var(--muted);line-height:1.6}

/* ── 사용량 창 4단 표 ────────────────────────────────────────────────────
   ★한 줄 = 한 창(4시간·하루·주·월). 막힌 창은 붉게 — 어디에 걸렸는지가 한눈에 보여야 한다. */
.usetab{margin-top:12px}
.userow{padding:12px 0;border-bottom:1px solid var(--line)}
.userow:first-child{padding-top:2px}
.userow:last-child{border-bottom:0;padding-bottom:2px}
.userowt{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-bottom:8px}
.userown{font-size:13.5px;font-weight:600;color:var(--fg)}
.userowp{text-align:right;white-space:nowrap}
.userowp b{font-size:15px;font-weight:800;letter-spacing:-.2px}
.userowc{font-size:11.5px;color:var(--muted);font-weight:600}
.userowr{margin-top:6px;font-size:11.5px;color:var(--muted)}
.userow.over .userowp b{color:var(--danger)}
/* 등급 항목의 부가 한 줄 — 값 아래 작게(아래 등급 대비 배수) */
.planrowsub{display:block;margin-top:2px;font-size:11.5px;font-weight:600;color:var(--accent);letter-spacing:-.1px}
/* 로그인·가입 모달 — 안쪽 카드가 이미 max-width 380 이라 그릇은 폭만 잡아 준다 */
.authbox{width:min(420px,92vw);max-height:88vh;padding:0;overflow:auto}
.authbox #authCard{margin:0;border:0;background:transparent;box-shadow:none;max-width:none;padding:26px 22px 22px}
.authbox .modalx{z-index:2}

/* ★손님이 중지해서 끝난 답 표시 — 본문과 구분되게 작게·흐리게(26/08/29) */
.stopmark{margin-top:6px;font-size:12px;opacity:.6}

  /* ── ★PC 앱 전용 배치(26/09/03 · 유저확정) ─────────────────────────
     유저원문: "메뉴를 ㅁㅁ 이거 두 개 합쳐진 걸로 해서 ★계속 나와 있게 하거나 들어가게 해도
     되지 않겠냐 ★화면을 덮는 걸로 말고 ★새로운 화면 배치로 해서 ★채팅창이 줄어드는 걸로"

     ★폰·브라우저는 종전 그대로다(사이드바가 덮는다) — body.deskapp 일 때만 갈린다.
     ★덮지 않고 ★자리를 나눈다: 사이드바가 자리를 차지하고 본문이 그만큼 줄어든다. */
  /* ★모바일용 뒤로/메뉴 단추는 앱에서 지운다 — 사이드바가 늘 떠 있으므로 쓸 일이 없고,
     ★로고를 가린다(26/09/03 실화면 확인). body.inapp 규칙(181줄)이 다시 켜므로 !important 로 못박는다. */
  body.deskapp .fab-back,body.deskapp #roomBack{display:none!important}
  body.deskapp .sidebar{position:fixed;transform:none;z-index:40;padding-top:52px;
    transition:width .18s ease,padding .18s ease;overflow-x:hidden}
  body.deskapp main,body.deskapp .content{margin-left:236px;transition:margin-left .18s ease}
  [dir=rtl] body.deskapp main,[dir=rtl] body.deskapp .content{margin-left:0;margin-right:236px}

  /* 접었을 때 — ★사라지지 않고 자리만 준다(다시 펴는 단추가 보여야 한다) */
  body.deskapp.narrow .sidebar{width:0;padding-left:0;padding-right:0;border-right:0}
  body.deskapp.narrow main,body.deskapp.narrow .content{margin-left:0}
  [dir=rtl] body.deskapp.narrow main,[dir=rtl] body.deskapp.narrow .content{margin-right:0}

  /* ★입력칸도 자리를 나눈다 — .chatdock 은 left:0;right:0 이라 ★사이드바를 덮는다.
     유저지적 26/09/03: "채팅 입력칸이 저렇게 가는 게 맞냐 ★메뉴를 덮잖아 ★채팅창 크기랑 똑같아야지" */
  body.deskapp .chatdock{left:236px}
  [dir=rtl] body.deskapp .chatdock{left:0;right:236px}
  body.deskapp.narrow .chatdock{left:0}
  [dir=rtl] body.deskapp.narrow .chatdock{right:0}

  /* 접기 단추 — ★아이콘만(상자 없음).
     유저지적 26/09/03: "메뉴 안에 넣고 ★접었을 때는 끝자락에 띄워놓으면 되잖아"
     ⇒ 펴져 있으면 ★사이드바 안 오른쪽 위, 접으면 ★화면 끝자락. */
  #deskToggle{display:none}
  body.deskapp #deskToggle{display:flex;position:fixed;top:1px;left:200px;z-index:70;
    width:26px;height:26px;align-items:center;justify-content:center;
    border:0;background:none;padding:0;cursor:pointer;color:var(--fg);
    transition:left .18s ease,opacity .15s ease;opacity:.6}
  body.deskapp #deskToggle:hover{opacity:1}
  .cardbar .planpick:hover{color:var(--fg)}
  /* ★토글은 ★안 눌린다 — 옆 칸이 커져도 라벨이 줄바꿈되면 안 된다. */
  .cardbar .tgl{flex:none;white-space:nowrap}



  /* ★모드 탭 — 챗 | 코드 (pages/mode_tabs.js · 유저확정 26/09/03 "테이블을 가로로 두 개") */
  /* ★한 줄 · 낮게 — 유저확정 26/09/03 "두 줄로 말고 ★한 줄로 깔끔하게 심플하게",
     "구분선에 붙여서 ★아래 목록 공간 좀 더 키우라고" */
  .modetabs{display:flex;gap:6px;margin:0 6px 4px;padding:0;background:none}
  .modetab{flex:1;margin:0;display:flex;flex-direction:row;align-items:center;justify-content:center;gap:6px;
    height:34px;border:1px solid var(--line);border-radius:10px;background:var(--card);color:var(--muted);
    font-size:12.5px;font-weight:600;cursor:pointer;padding:0;
    transition:border-color .14s,color .14s,background .14s}
  .modetab svg{width:15px;height:15px;flex:none}
  .modetab:hover{color:var(--fg)}
  .modetab.on{border-color:var(--accent);color:var(--fg);
    background:color-mix(in srgb,var(--accent) 10%,var(--card))}
  /* ── 코드 세션 목록(pages/code_rooms.js · 유저참고 IMG_2654 · 26/09/03) ── */
  #tab-code{padding:14px 14px 96px;overflow-y:auto}
  .code-head{display:flex;align-items:center;gap:8px;margin:2px 0 14px}
  .code-back{width:32px;height:32px;display:flex;align-items:center;justify-content:center;
    border:1px solid var(--line);border-radius:50%;background:transparent;color:var(--fg);cursor:pointer;padding:0}
  .code-back svg{width:18px;height:18px}
  .code-title{flex:1;text-align:center;font-size:16px;font-weight:600;margin-inline-end:32px}
  .code-sec{font-size:12.5px;color:var(--muted);margin:14px 2px 8px}
  .code-devs{display:flex;flex-wrap:wrap;gap:8px}
  .code-dev{display:flex;align-items:center;gap:6px;height:38px;padding:0 14px;border-radius:19px;
    border:1px solid var(--line);background:var(--card);color:var(--fg);font-size:13px}
  .code-dev.add{cursor:pointer}
  .code-dev svg{width:16px;height:16px}
  .code-list{display:flex;flex-direction:column;gap:10px}
  .code-card{display:block;width:100%;text-align:start;padding:13px 14px;border-radius:14px;
    border:1px solid var(--line);background:var(--card);color:var(--fg);cursor:pointer}
  .cc-top{display:flex;align-items:baseline;gap:10px}
  .cc-title{flex:1;font-size:14.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .cc-when{font-size:12px;color:var(--muted);flex:none}
  .cc-sub{display:flex;align-items:center;gap:6px;margin-top:5px;font-size:12.5px;color:var(--muted)}
  .cc-dot{width:8px;height:8px;border-radius:50%;background:var(--muted);opacity:.5;flex:none;margin-left:8px}
  .cc-dot.on{background:#3ecf6a;opacity:1}
  /* ★231(유저확정): 연결 안 됨은 ★빨강 — 회색이면 '안 됨' 인지 '모름' 인지 구별이 안 된다 */
  .cc-dot.off{background:#e5484d;opacity:1}
  .cc-state{flex:none}
  .cc-folder{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .code-empty{padding:22px 4px;color:var(--muted);font-size:13px;text-align:center}
  .code-fab{position:fixed;right:18px;bottom:22px;display:flex;align-items:center;gap:7px;
    height:46px;padding:0 18px;border-radius:23px;border:0;background:var(--fg);color:var(--bg);
    font-size:14px;font-weight:600;cursor:pointer;box-shadow:0 6px 20px rgba(0,0,0,.25);z-index:45}
  .code-fab svg{width:18px;height:18px}
  /* ★작업 폴더 줄 — 채팅 입력칸 ★바로 위(pages/code_root.js · 유저확정 26/09/03) */
  /* ★폭은 가변 — 글자만큼만 차지하고, 길면 … 로 줄인다(유저확정 26/09/03) */
  .coderoot{display:inline-flex;align-items:center;gap:6px;margin:0 4px 6px;height:26px;padding:0 10px;
    border-radius:13px;border:1px solid var(--line);background:var(--card);color:var(--muted);
    font-size:12px;cursor:pointer;width:auto;max-width:min(260px,70%);align-self:flex-start;flex:none}
  .coderoot svg{width:14px;height:14px;flex:none}
  .coderoot span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .coderoot.on{color:var(--fg)}
  .coderoot:hover{border-color:var(--accent)}
  body.deskapp.narrow #deskToggle{left:10px}
  [dir=rtl] body.deskapp #deskToggle{left:auto;right:198px}
  [dir=rtl] body.deskapp.narrow #deskToggle{right:10px}
  #deskToggle svg{width:20px;height:20px;stroke-width:1.7}
  /* ★화살표는 지금 무엇이 일어나는지를 가리킨다 — 펴져 있으면 '접기'(왼쪽), 접혀 있으면 '펴기'(오른쪽) */
  body.deskapp.narrow #deskToggle svg .dt-arrow{transform:rotate(180deg);transform-origin:14px 12px}
  /* 좁은 창에서는 앱이어도 덮개로 — 자리를 나눌 만큼 넓지 않다 */
  /* ★좁은 창 예외(≤860px 덮개) 제거(123차) — 앱은 창 폭과 관계없이 자리를 나눈다. 접으면 사이드바 폭 0 · 본문·입력칸이 전폭. */

  /* ★모델 선택 시트(261) — 판마다 이름·쓰임·대기·지금 되는지. 폰 폭 우선 */
  .planwrap{position:fixed;inset:0;z-index:60;background:rgba(0,0,0,.45);
    display:flex;align-items:flex-end;justify-content:center;padding:14px}
  @media (min-width:700px){ .planwrap{align-items:center} }
  .planbox{width:100%;max-width:420px;background:var(--card);border:1px solid var(--line);
    border-radius:14px;padding:10px;box-shadow:0 10px 40px rgba(0,0,0,.35)}
  .planbox-h{font-size:13px;color:var(--muted);text-align:center;padding:6px 0 10px}
  .planrow{display:flex;align-items:center;gap:10px;width:100%;text-align:start;
    background:transparent;border:0;border-radius:10px;padding:10px 10px;cursor:pointer;color:inherit}
  .planrow:hover{background:var(--input)}
  .planrow.on{background:var(--input)}
  .planrow-l{flex:1;min-width:0}
  .planrow-t{font-size:14px;font-weight:600}
  .planrow-s{font-size:12px;color:var(--muted);margin-top:2px}
  .planrow-r{font-size:11.5px;color:var(--muted);flex:none;white-space:nowrap}
  .planrow-r.ok{color:var(--ok,#3fb950)}

  /* ★268 하단 한 줄 — [자동 진행] [모델 선택] [폴더 선택]
     유저지시 26/09/08: "추론토글 있는 위치로 모델선택 카드 옮기고 그 옆으로 폴더선택 옮겨"
                       "그 라인에 오브젝트들 전부 다 아래위 중앙정렬" "위아래 여백 줄여서 프레임 사이즈를 줄이라고"
     ㄴ종전에는 폴더 줄이 ★입력칸 위에 한 줄을 통째로 먹고, 모델 선택은 ★우측 끝에 배경색으로 묻혀 있었다. */
  .cardbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
    padding:4px 2px 0;margin:0;min-height:26px}
  .cardbar>*{align-self:center;margin:0}
  /* 모델 선택 — ★버튼처럼 보이게(배경·테두리를 바닥과 다르게) */
  /* ★269: ★width:auto 가 반드시 있어야 한다 — 이 파일에는 ★전역 `button{width:100%}` 이 있고,
     쓰지 않으면 버튼이 ★줄 전체(994px)를 먹어 다음 칸이 줄바꿈된다(실측 26/09/08). */
  .cardbar .planpick{display:inline-flex;align-items:center;gap:6px;height:24px;
    width:auto;min-width:0;padding:0 10px;border-radius:999px;border:1px solid var(--line);
    background:var(--input);color:var(--fg);font-size:12px;line-height:1;margin:0;
    cursor:pointer;flex:0 0 auto;max-width:none;appearance:none;-webkit-appearance:none}
  .cardbar .planpick:hover{border-color:var(--accent,#4f8cff)}
  .cardbar .planpick:after{content:'\25BE';font-size:10px;opacity:.7}
  /* 폴더 선택 — 같은 줄 · 같은 높이 */
  .cardbar .coderoot{display:inline-flex;align-items:center;gap:6px;height:24px;
    width:auto;min-width:0;padding:0 10px;border-radius:999px;border:1px solid var(--line);
    background:var(--input);color:var(--muted);font-size:12px;line-height:1;margin:0;
    cursor:pointer;flex:0 0 auto;max-width:220px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
  .cardbar .coderoot.on{color:var(--fg)}
  .cardbar .coderoot:hover{border-color:var(--accent,#4f8cff)}
  /* 입력 프레임 여백 최소 — 채팅 화면을 그만큼 넓힌다 */
  #chatDock .inputrow{margin-bottom:0}
  /* ★모달 뒤를 확실히 가린다(유저지적 "모달 뒤가 다 비쳐서 뭔 내용인지 제대로 못 보겠잖아 혼잡해서") */
  /* ★270: 아예 ★불투명 — 반투명은 뒤가 비친다(유저지적 "야 뒤가 뭐가 가려져 뒤에 비치잖아 그냥 아예 불투명하게 만들라고"). */
  .planwrap{background:var(--bg)}
  .planbox{background:var(--card);border:1px solid var(--line);box-shadow:0 18px 60px rgba(0,0,0,.6)}
