/* 클로드비서 허브 화면 스타일 (PIN-OPS-012)
   목적: Claude Code 데스크톱 앱의 구조(좌 목록 / 중앙 대화 / 우 패널 / 하단 입력칸)를 축소 차용. 토큰은 자체 정의(외부 로고·워드마크 없음).
   테마: :root = 라이트, [data-theme=dark] = 다크, [data-theme=auto] 는 prefers-color-scheme 를 따른다.
   반응형: <760 모바일(하단 탭 + 서랍 + 시트) / 760～1099 2열 / ≥1100 3열. 폴드8 접힘(≈373px)·펼침(≈800px) 둘 다 이 구간에 든다.
   실패 지점: 없음(정적). 클래스 이름은 app.js 와 1:1 이므로 바꾸면 둘 다 바꾼다. */

/* ── 색 토큰(§37-4 · 39 회차 2026-09-09 — 37 의 전면 교체를 옛 색으로 되돌린 판) ──────────
   경위: 37 회차가 §37-1 을 따라 토큰을 통째로 갈아 끼웠으나 요청은 그것이 아니었다(§37-4).
     "화면 색을 다 바꾸라는 것이 아니라 섞어서 가독성을 높여 달라는 것" — 그래서 **옛 값이 기본**이고
     새 팔레트에서는 **넷만 남긴다**. 옛 값의 출처는 커밋 72f2021 의 이 파일이다.
   ★ 남긴 넷(아래 주석 `[39 남김]`) = ① 형광펜 배경 --accent-soft ② 상태 4색(ok·warn·plan·danger)
     ③ 카드와 바탕을 가르는 선 --line ④ 코드·경로의 보조면 --surface-2. 그 밖은 전부 옛 값이다.
   ★ 되돌리지 않은 것 = 고정색을 토큰으로 옮긴 세 자리(.badge.work · .verbar · .toast.err).
     그건 색 취향이 아니라 대비 결함 수정이라 §37-4 가 예외로 못 박았다.
   ★ §37-3 읽기 규칙(--read-w 62ch · 줄 간격 1.7 · tabular-nums · 표만 가로 스크롤)은 그대로 유지한다.
   ★ 화면 어디서도 새 색을 만들지 않는다 — 색이 필요하면 이 목록에서 고른다.
   ★ 어두운 판은 **두 벌**이다: [data-theme=dark](사람이 고른 어두움) · @media prefers-color-scheme 안의
     [data-theme=auto](시스템을 따름). 한쪽만 고치면 '시스템' 설정에서만 다른 색이 남는다 — 반드시 같이 고친다.
     (`_tools\39-test.ps1` 이 두 벌의 값이 같은지, 그리고 되돌린 값이 옛 값과 같은지 검사한다.) */
:root {
  --bg: #f7f6f3;           /* 바탕(따뜻한 회백) */
  --bg-2: #efede8;         /* 사이드바·패널 */
  --surface: #ffffff;      /* 카드·입력칸 */
  --surface-2: #ecebe6;    /* [39 남김] 코드·경로·말풍선 보조면 — 옛 #f2f0eb 보다 한 단계 눌러 코드가 면으로 보인다 */
  --ink: #1f1e1d;
  --ink-2: #4b4842;
  --muted: #7d786f;
  --line: #e2dfd8;         /* 선 — 옛 값. 카드/바탕을 가르는 선은 아래 --line-card 한 겹이 맡는다 */
  --line-2: #cfcbc2;
  --accent: #2f5bea;       /* 코발트: 행동·링크·선택 */
  --accent-ink: #ffffff;
  --accent-soft: #e5ecfb;  /* [39 남김] 강조 배경 = 형광펜(<mark>) 바탕 */
  /* [39 남김] 상태 4색 — 칩·배지에만. 본문 글자색으로 쓰지 않는다(색만으로 뜻을 전하지 않기 위해 늘 낱말과 함께 둔다). */
  --ok: #2f7d4f; --ok-soft: #e2f0e7;         /* 완료 */
  --warn: #a86a12; --warn-soft: #f8ecd8;     /* 대기 */
  --plan: #6a5aa8; --plan-soft: #ece8f7;     /* 기획 */
  --danger: #b23b3b; --danger-soft: #f8e5e3; /* 오류 */
  /* 상태색 면 위 글자는 두 판 모두 어두워야 한다(밝은 판 글자와 같은 값). 판마다 덮어쓰지 않는다. */
  --warn-ink: #1f1e1d;
  --info: #2f5bea;
  --radius: 12px; --radius-s: 8px;
  /* 읽기 폭(§37-3). ch = '0' 글자 폭이라 한글은 한 줄에 약 34자가 된다 — 좁으면 이 값 하나만 올린다. */
  --read-w: 62ch;
  --shadow: 0 1px 2px rgba(31,30,29,.05), 0 8px 24px rgba(31,30,29,.06);
  --mono: ui-monospace, "Cascadia Mono", "D2Coding", "Consolas", monospace;
  --sans: "Pretendard", -apple-system, BlinkMacSystemFont, "Malgun Gothic", "맑은 고딕", "Segoe UI", system-ui, sans-serif;
  color-scheme: light;
}
/* 어두운 판 — 아래 두 블록은 값이 **글자 하나까지 같아야** 한다(39-test 가 검사한다).
   [39 남김] 은 --surface-2 · --line · --accent-soft · 상태 4색. 그 밖은 옛 값(72f2021)이다. */
[data-theme="dark"] {
  --bg: #1a1917; --bg-2: #201f1d; --surface: #262523; --surface-2: #22262d;
  --ink: #e8e4dc; --ink-2: #c9c4ba; --muted: #8f897e; --line: #2b3038; --line-2: #45423d;
  --accent: #6b8cff; --accent-ink: #0e1224; --accent-soft: #1e2738;
  --ok: #6fbf8b; --ok-soft: #1a2a21; --warn: #e0a75a; --warn-soft: #2c2419;
  --plan: #a99bdd; --plan-soft: #221f2e; --danger: #e08585; --danger-soft: #2c1d1d;
  --info: #6b8cff;
  --shadow: 0 1px 2px rgba(0,0,0,.35), 0 8px 24px rgba(0,0,0,.35);
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  [data-theme="auto"] {
    --bg: #1a1917; --bg-2: #201f1d; --surface: #262523; --surface-2: #22262d;
    --ink: #e8e4dc; --ink-2: #c9c4ba; --muted: #8f897e; --line: #2b3038; --line-2: #45423d;
    --accent: #6b8cff; --accent-ink: #0e1224; --accent-soft: #1e2738;
    --ok: #6fbf8b; --ok-soft: #1a2a21; --warn: #e0a75a; --warn-soft: #2c2419;
    --plan: #a99bdd; --plan-soft: #221f2e; --danger: #e08585; --danger-soft: #2c1d1d;
    --info: #6b8cff;
    --shadow: 0 1px 2px rgba(0,0,0,.35), 0 8px 24px rgba(0,0,0,.35);
    color-scheme: dark;
  }
}

* { box-sizing: border-box; }
/* 6b-8: 좁은 폭(폴드8 커버)에서 긴 한 줄이 페이지 자체를 가로로 밀던 것을 막는다.
   본문 스크롤은 .content 가 맡으므로 문서 레벨 가로 스크롤은 언제나 사고다. */
html, body { margin: 0; padding: 0; height: 100%; overflow-x: hidden; }
body { background: var(--bg); color: var(--ink); font-family: var(--sans); font-size: 14.5px; line-height: 1.55; -webkit-text-size-adjust: 100%; overflow: hidden; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--accent); }
code, pre, .mono { font-family: var(--mono); font-size: .92em; }
[hidden] { display: none !important; }
.boot { padding: 40px; color: var(--muted); text-align: center; }
.muted { color: var(--muted); }
.small { font-size: 12.5px; }
.dim { opacity: .55; }
.off { opacity: .45; filter: grayscale(1); }
.spacer { flex: 1; }
.row { display: flex; align-items: center; gap: 8px; }
.wrap { flex-wrap: wrap; }
.grow { flex: 1; min-width: 0; }
.ellipsis { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pre { white-space: pre-wrap; word-break: break-word; }
hr.sep { border: 0; border-top: 1px solid var(--line); margin: 12px 0; }

/* ── 버튼·칩·입력 ── */
/* 33-9-1: 길게 누르기를 쓰는 버튼([📷])이 생겨 글자 선택·안드로이드 길게누르기 팝업을 버튼 전체에서 끈다. */
.btn { border: 1px solid var(--line-2); background: var(--surface); border-radius: var(--radius-s); padding: 7px 12px; font-size: 13.5px; font-weight: 500; color: var(--ink); display: inline-flex; align-items: center; gap: 6px; line-height: 1.2; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.btn:hover { background: var(--surface-2); }
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.btn.primary:hover { filter: brightness(1.08); background: var(--accent); }
.btn.ghost { background: transparent; border-color: transparent; }
.btn.ghost:hover { background: var(--surface-2); }
.btn.danger { color: var(--danger); border-color: var(--danger-soft); }
.btn.sm { padding: 4px 9px; font-size: 12.5px; }
.btn.icon { padding: 6px 8px; }
.btn:disabled { opacity: .45; cursor: default; transform: none; }
.chip { display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; background: var(--surface-2); color: var(--ink-2); white-space: nowrap; }
.chip.ok { background: var(--ok-soft); color: var(--ok); }
.chip.warn { background: var(--warn-soft); color: var(--warn); }
.chip.danger { background: var(--danger-soft); color: var(--danger); }
.chip.accent { background: var(--accent-soft); color: var(--accent); }
/* §37-1 상태 4색의 넷째(기획). 아직 쓰는 자리가 없지만 네 색이 한 벌이라 여기서 함께 정의한다. */
.chip.plan { background: var(--plan-soft); color: var(--plan); }
.badge { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; background: var(--accent); color: var(--accent-ink); }
.badge.work { background: var(--warn); color: var(--warn-ink); }
/* 17-D: 숫자 없는 점 배지(개인 대화 '안 읽은 새 답'). 건수가 아니라 있다/없다뿐이라 숫자를 안 쓴다. */
.badge.dot { min-width: 9px; width: 9px; height: 9px; padding: 0; border-radius: 50%; }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; background: var(--muted); }
.dot.on { background: var(--ok); } .dot.work { background: var(--warn); } .dot.wake { background: var(--accent); }
/* 절전·오프라인은 색이 없어 둘이 구별되지 않았다(6b-2). 점만으로는 못 읽으므로 글자(.dev-state)와 함께 본다. */
.dot.sleep { background: var(--muted); opacity: .55; } .dot.off { background: transparent; border: 1.5px solid var(--muted); }
input[type=text], input[type=search], input[type=password], input[type=time], input[type=number], select, textarea {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-s); padding: 7px 10px; color: var(--ink); outline: none; min-width: 0;
}
input:focus, select:focus, textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
select.sm, input.sm { padding: 4px 8px; font-size: 12.5px; }
.switch { position: relative; width: 38px; height: 22px; border-radius: 11px; background: var(--line-2); border: 0; padding: 0; flex: none; transition: .15s; }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: .15s; box-shadow: 0 1px 2px rgba(0,0,0,.3); }
.switch.on { background: var(--accent); }
.switch.on::after { left: 19px; }
.switch:disabled { opacity: .4; }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; }
.card + .card { margin-top: 10px; }
.card h3 { margin: 0 0 8px; font-size: 14px; }
.card h4 { margin: 12px 0 6px; font-size: 13px; color: var(--ink-2); }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; font-size: 13px; }
.kv dt { color: var(--muted); } .kv dd { margin: 0; }
.list { list-style: none; margin: 0; padding: 0; }
.list li { padding: 8px 0; border-top: 1px solid var(--line); }
.list li:first-child { border-top: 0; }
.list.tight li { padding: 5px 0; }
table.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl th, .tbl td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
.tbl th { color: var(--muted); font-weight: 600; font-size: 12px; }
.tbl-wrap { overflow-x: auto; max-width: 100%; }
.nowrap { white-space: nowrap; }

/* ── 문자·통화 검수 큐(P8-2) ──
   왜 max-width 와 줄수 제한을 같이 거나: 한글 문자 본문은 공백 없이 길게 이어지는 일이 많아
   word-break 없이 두면 표 한 칸이 화면 밖까지 늘어나 버튼이 안 보인다. 3줄까지만 보이고 나머지는 잘린다. */
.tri-prev { max-width: 34em; max-height: 4.4em; overflow: hidden; line-height: 1.45; word-break: break-word; overflow-wrap: anywhere; white-space: pre-wrap; color: var(--ink-2); }
.seg { display: inline-flex; gap: 4px; flex-wrap: wrap; }

/* ── 로그인 ── */
.login-wrap { min-height: 100svh; display: flex; align-items: center; justify-content: center; padding: 24px 18px calc(24px + env(safe-area-inset-bottom)); background: var(--bg); }
.login-card { width: 100%; max-width: 360px; background: var(--surface); border: 1px solid var(--line); border-radius: 18px; padding: 26px 22px 20px; box-shadow: var(--shadow); }
.login-card .brand { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.login-card .brand img { width: 36px; height: 36px; border-radius: 9px; }
.login-card h1 { margin: 0; font-size: 20px; letter-spacing: -.02em; }
.login-card .sub { margin: 0 0 18px; color: var(--muted); font-size: 12.5px; }
.pin-display { display: flex; gap: 10px; justify-content: center; margin: 4px 0 14px; }
.pin-dot { width: 13px; height: 13px; border-radius: 50%; background: var(--line-2); transition: .15s; }
.pin-dot.on { background: var(--accent); transform: scale(1.1); }
.keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.keypad button { padding: 13px 0; font-size: 19px; font-weight: 600; border: 1px solid var(--line); background: var(--surface); border-radius: 12px; }
.keypad button:active { background: var(--surface-2); }
.keypad button.wide { font-size: 13px; color: var(--muted); }
.login-err { color: var(--danger); font-size: 13px; min-height: 20px; margin-top: 10px; text-align: center; }
.login-foot { margin-top: 12px; text-align: center; font-size: 11.5px; color: var(--muted); }

/* ── 셸 레이아웃 ── */
.shell { display: grid; grid-template-columns: 250px 1fr; grid-template-rows: 100svh; height: 100svh; }
.shell.with-panel { grid-template-columns: 250px 1fr 320px; }
.sidebar { background: var(--bg-2); border-right: 1px solid var(--line); display: flex; flex-direction: column; min-height: 0; }
/* ── 안전영역 위쪽 인셋(8-18-1) ────────────────────────────────────────────
   ★ 위쪽 인셋을 쓰는 자리는 아래 다섯뿐이고, 전부 `var(--sai-top, env(safe-area-inset-top))` 한 낱말로 읽는다.
     --sai-top 은 app.js applySafeTop() 이 실측해 **화면 높이의 25% 상한**을 씌운 값이다.
     왜: 안드로이드 WebView 가 앱 복귀 직후 부풀린 인셋을 준다 — 그대로 쓰면 머리가 통째로 아래로 밀린다
     (재희님 2026-09-10 13:05 캡처). JS 가 값을 못 넣으면 종전대로 env() 로 떨어진다(폴백). */
.side-head { display: flex; align-items: center; gap: 8px; padding: calc(12px + var(--sai-top, env(safe-area-inset-top))) 14px 8px; }
.side-head img { width: 26px; height: 26px; border-radius: 7px; }
.side-head .name { font-weight: 700; letter-spacing: -.02em; font-size: 15px; }
/* 40 ①② · 아이콘+이름 전체가 단추다(홈 이동 · 홈에서는 새로고침 · 길게 누르면 강력 새로고침).
   음수 여백으로 눌리는 면만 넓히고 머리줄 높이는 그대로 둔다 — 6b-12/8-18-1 의 머리 실측이 어긋나지 않게. */
.side-home { display: flex; align-items: center; gap: 8px; padding: 3px 5px; margin: -3px -5px; border: 0; background: none; color: var(--ink); border-radius: 8px; text-align: left; }
.side-home:hover { background: var(--surface-2); }
.side-home:active { transform: scale(.98); }
/* 40 ④ · ↻ 는 도는 동안만 돈다(아무 반응 없이 멎은 것처럼 보이지 않게). 회전은 기존 spin 키프레임을 쓴다. */
.side-head .refresh.spinning { animation: spin .9s linear infinite; }
/* 6b-7(§8-10): 사이드바는 자기만 스크롤한다. body 는 overflow:hidden 이고 .shell 이 100svh 격자라 문서 스크롤은 없다.
   overscroll-behavior:contain = 목록 끝에서 더 굴려도 뒤(본문·폰 드로어 배경)로 스크롤이 넘어가지 않게.
   scroll-behavior:auto = 재렌더 뒤 scrollTop 을 되돌릴 때 부드럽게 미끄러지지 않고 즉시 제자리로. */
.side-scroll { flex: 1; overflow-y: auto; overscroll-behavior: contain; scroll-behavior: auto; min-height: 0; padding: 0 8px 8px; }
.side-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; padding: 10px 8px 4px; }
/* 새 대화 — 사업 목록 맨 위. 왜: 첫 화면에서 "그냥 물어보기" 가 갈 곳. */
.newchat { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; margin-top: 8px; padding: 8px 9px; border: 1px solid var(--line); background: var(--surface); border-radius: var(--radius-s); color: var(--ink); font-size: 13.5px; font-weight: 600; }
.newchat:hover { border-color: var(--accent); color: var(--accent); }
.newchat .ico { width: 18px; text-align: center; font-size: 13px; color: var(--accent); }
/* 그룹 머리(사업·개인·클로드비서 개발) — 눌러서 접고 편다. 애니메이션 없이 즉시(목록이 길어 스크롤이 튀는 것을 피한다). */
.side-group { display: flex; align-items: center; gap: 6px; width: 100%; text-align: left; margin-top: 10px; padding: 6px 8px; border: 0; background: transparent; border-radius: var(--radius-s); color: var(--muted); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.side-group:hover { background: var(--surface); color: var(--ink-2); }
.side-group:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.side-group.open { color: var(--ink-2); }
.side-group .caret { width: 12px; flex: none; font-size: 10px; }
.side-group .nm { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.side-group .cnt { font-family: var(--mono); font-size: 10.5px; color: var(--muted); flex: none; }
.side-group-body { display: flex; flex-direction: column; }
/* 그룹 머리 줄: 접기 버튼 + (사업 그룹만) 새 사업 ＋. 버튼 안에 버튼을 넣을 수 없어 한 줄로 감쌌다. */
.side-group-head { display: flex; align-items: center; }
.side-group-head .side-group { flex: 1; min-width: 0; }
.side-group-add { flex: none; margin-top: 10px; padding: 5px 7px; border: 0; background: transparent; color: var(--muted); border-radius: var(--radius-s); font-size: 13px; line-height: 1; }
.side-group-add:hover { background: var(--surface); color: var(--ink); }
.side-group-add:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* 개인 절 — 사업과 다른 색으로 구분(업무 대화와 헷갈리지 않게). */
.biz.personal .num { color: var(--accent); }
/* §17-B 개인 대화 스레드 — 개인 줄 아래에 한 단 들여 붙는다(사업 줄과 층이 다르다는 것을 들여쓰기로만 표시). */
.biz.thread { padding-left: 20px; font-size: 13px; color: var(--muted); }
/* 17-C ④: 지금 열려 있는 대화는 한눈에 보여야 한다(메인 화면이 이 한 줄에 종속된다). 왼쪽 굵은 선 + 배경. */
.biz.thread.on { color: var(--ink); background: var(--surface); box-shadow: inset 2px 0 0 var(--accent); font-weight: 600; }
.biz.thread .num { width: 14px; font-size: 10px; }
/* §24-2 알림에서 들어온 카드 강조. 링크로 왔는데 카드가 여러 장이면 어느 것을 보라는 건지 알 수 없다.
   2.5초 뒤 클래스가 떨어지므로 테두리만 잠깐 켠다(레이아웃은 건드리지 않는다 — 켜질 때 화면이 밀리면 안 된다). */
.hit { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }
/* 스레드 이력(개인 탭 메인 대화의 앞부분) — 답변 카드와 구분되게 왼쪽 선 하나로만 묶는다. */
.threadhist:not(:empty) { border-left: 2px solid var(--line); padding: 4px 0 4px 10px; margin-bottom: 8px; display: flex; flex-direction: column; gap: 10px; }
/* 대화 머리(제목·건수·닫기) — 어느 대화를 보고 있는지 본문 위에서도 읽히게. */
.threadhist .thead { align-items: center; gap: 6px; }
.threadhist .turn { display: flex; flex-direction: column; gap: 4px; }
.threadhist .turn .q { font-weight: 600; color: var(--ink); white-space: pre-wrap; }
.threadhist .turn .a { color: var(--ink-2); font-size: 14px; }
.biz { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; padding: 7px 9px; border: 0; background: transparent; border-radius: var(--radius-s); color: var(--ink-2); font-size: 13.5px; }
.biz:hover { background: var(--surface); }
.biz.on { background: var(--surface); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.biz .num { font-family: var(--mono); font-size: 11px; color: var(--muted); width: 22px; flex: none; align-self: flex-start; margin-top: 1px; }
/* 기획 §2-1: 사업명은 두 줄까지 접고 그래도 넘치면 말줄임. 전체 이름은 title 툴팁에 있다.
   -webkit-line-clamp 는 크롬·사파리·최신 파폭이 모두 지원한다(줄바꿈만 되고 말줄임이 없어도 읽기에는 문제 없음). */
.biz .nm { flex: 1; min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; white-space: normal; overflow: hidden; overflow-wrap: anywhere; line-height: 1.32; }
.biz .st { font-size: 10.5px; color: var(--muted); flex: none; }
/* 17-D: 개인 대화의 주고받은 건수. 알림이 아니라 사실이므로 회색 작은 글자로만 둔다(동그라미 금지). */
.biz .turns { font-family: var(--mono); font-size: 10.5px; color: var(--muted); flex: none; align-self: flex-start; margin-top: 2px; }
.biz .badge { align-self: flex-start; }
.biz .badge.dot { margin-top: 5px; }
/* 사업 한 줄 = [본문 버튼][⋯]. 버튼 안에 버튼을 넣을 수 없어 감쌌다. ⋯ 는 호버·포커스·열림일 때만 보인다. */
.bizrow { position: relative; display: flex; align-items: stretch; }
.bizrow .biz { align-items: flex-start; padding-right: 28px; } /* ⋯ 자리를 늘 비워 둔다 — 나타날 때 이름이 밀리지 않게 */
.bizrow .dots { flex: none; width: 24px; margin-left: -26px; padding: 0; border: 0; background: transparent; color: var(--muted); border-radius: var(--radius-s); font-size: 14px; line-height: 1; opacity: 0; }
.bizrow:hover .dots, .bizrow .dots:focus-visible, .bizrow .dots[aria-expanded=true] { opacity: 1; background: var(--surface-2); color: var(--ink); }
.bizrow .dots:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* 손가락에는 호버가 없다 — 폰 서랍에서는 항상 보인다. */
@media (hover: none) { .bizrow .dots { opacity: .7; } }
/* 제자리 이름 편집 — 줄이 그대로 입력칸이 된다(미리보기 시트 없음). */
.bizrename { align-items: center; gap: 8px; padding: 4px 9px; }
.bizrename input { flex: 1; min-width: 0; font-size: 13.5px; padding: 4px 6px; }
/* ⋯ 메뉴 — 사이드바 스크롤에 잘리지 않게 body 에 붙이고 위치를 계산해 넣는다.
   z-index 는 80: ≤759px 에서 사이드바가 fixed·45(서랍 배경 44), 패널 40, 모달 50, 토스트 60, 버전 막대 70이라
   30이던 예전 값은 폰 폭에서 서랍 뒤로 깔렸다(재희님 "메뉴가 뒤로 가려짐", 6b-4). */
.bizmenu { position: fixed; z-index: 80; min-width: 150px; padding: 4px; background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-s); box-shadow: var(--shadow); }
.bizmenu button { display: block; width: 100%; text-align: left; padding: 7px 10px; border: 0; background: transparent; border-radius: var(--radius-s); color: var(--ink-2); font-size: 13px; }
.bizmenu button:hover { background: var(--bg-2); color: var(--ink); }
.bizmenu button.danger { color: var(--danger); }
/* 좁은 폭(≤430, 폴드8 접힌 화면·폰 서랍)은 드롭다운 대신 하단 시트 — 손가락 타깃을 키우고 화면 밖으로 나갈 여지를 없앤다. */
.bizmenu-bg { position: fixed; inset: 0; background: rgba(0,0,0,.35); z-index: 79; }
.bizmenu.sheet { top: auto; left: 0; right: 0; bottom: 0; width: auto; min-width: 0; padding: 6px 10px calc(10px + env(safe-area-inset-bottom));
  border-width: 1px 0 0; border-radius: 14px 14px 0 0; }
.bizmenu.sheet .sheet-title { padding: 8px 10px 6px; font-size: 11.5px; color: var(--muted); overflow-wrap: anywhere; }
.bizmenu.sheet button { padding: 13px 12px; font-size: 15px; min-height: 46px; }
.bizmenu.sheet button.sheet-cancel { margin-top: 4px; text-align: center; color: var(--muted); background: var(--bg-2); }
.nav { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; padding: 7px 9px; border: 0; background: transparent; border-radius: var(--radius-s); color: var(--ink-2); font-size: 13.5px; }
.nav:hover { background: var(--surface); }
.nav.on { background: var(--surface); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.nav .ico { width: 18px; text-align: center; font-size: 13px; color: var(--muted); }
/* 21-A 휴대폰 묶음 안의 줄(주소록·문자·통화·메세지). 사업 줄과 같은 들여쓰기로 "묶음에 속한 것"으로 읽히게 한다. */
.nav.sub { padding-left: 20px; }
.side-foot { padding: 8px 14px calc(10px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); font-size: 11px; color: var(--muted); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.side-foot .ver { white-space: nowrap; } /* 허브·앱 버전 병기가 길어져도 한 덩어리로 */
.side-foot .devs { display: flex; gap: 6px; align-items: center; }

.main { display: flex; flex-direction: column; min-height: 0; min-width: 0; background: var(--bg); }
/* ── 머리줄(.topbar) 한 자리 규칙 ──────────────────────────────────────────
   ★ 화면 조건 우선순위(6b-12에서 한 자리로 모음. app.js MQS 와 순서·문자열이 같아야 한다):
       ① 낮은 화면 LOW    '(max-height: 600px), (orientation: landscape) and (max-width: 1100px)'  — 머리 한 줄(제목+⋯)
       ② 좁은 폭  NARROW  '(max-width: 420px)'   — 버튼 셋을 ⋯ 로 접는다(JS 몫)
       ③ 두 줄    TWOROW  '(max-width: 600px)'   — .acts 를 둘째 줄로 내린다(CSS 몫)
     ①이 ②·③보다 세다. CSS 는 아래쪽 블록이 이기므로 LOW 블록(파일 끝쪽)이 TWOROW 블록보다 뒤에 있어야 하고,
     LOW 블록은 flex-wrap 을 nowrap 으로 되돌려 ③의 두 줄 배치를 명시적으로 끈다(둘 다 참인 가로 폰이 있다).
   ★ 6b-12 · 머리는 본문(.content) 보다 위 층에 둔다.
     왜: .content 는 스크롤 컨테이너라 브라우저가 하나의 층으로 늦게 그린다. 머리 글자가 조금이라도 상자 밖으로
     흘러 있으면 스크롤된 카드의 불투명 배경이 그 글자를 덮는다(스크롤 0 에서는 카드가 아직 아래에 있어 멀쩡해 보인다).
     z-index 5 = 본문 안 sticky(.outpins·.brf-head 3) 위, 패널 40·서랍 45·모달 50·토스트 60·버전막대 70 아래.
   ★ flex:none — .main 의 세로가 모자랄 때 머리가 먼저 찌그러지는 것을 막는다(머리는 늘 온전해야 한다). */
.topbar { --head-h: 44px; position: relative; z-index: 5; flex: none;
  display: flex; align-items: center; gap: 8px; padding: calc(8px + var(--sai-top, env(safe-area-inset-top))) 14px 8px; border-bottom: 1px solid var(--line); background: var(--bg); min-height: 48px; }
/* 실측 안전망(6b-12) — app.js measureHead() 가 "내용이 상자보다 높다" 고 판단하면 상한을 푼다.
   회전·안전영역 변화로 계산이 어긋나도 글자가 잘리지 않게 하는 마지막 방어선이다. */
.topbar.tall { max-height: none; }
.topbar .title { font-weight: 700; font-size: 15px; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar .sub { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* ── 머리줄 버튼 묶음(6b-11) ────────────────────────────────────────────
   증상(재희님 2026-09-09 16:02 캡처): 사업 머리 버튼이 21-B-1 로 하나 늘어 폭이 모자라자
   버튼 묶음이 아래로 밀려 'PIN-OPS-012' 칩 줄 위에 겹쳤다.
   원인: 버튼이 .topbar 의 형제로 늘어서 있어 각자 줄어들며(기본 flex-shrink:1) 글자가 접히고,
     .topbar 가 한 줄(nowrap)이라 넘친 만큼이 제목·칩 상자를 덮었다.
   고침: 버튼은 app.js 가 .acts 한 상자로 묶고(넓은 화면은 종전과 같은 한 줄),
     좁은 폭에서는 그 상자만 통째로 둘째 줄로 내려 겹칠 자리를 없앤다.
   ★ 아래 420px 조건은 app.js 의 NARROW_MQ 와 문자열이 같아야 한다(그쪽이 버튼 셋을 ⋯ 로 접는다). */
.topbar .acts { display: flex; align-items: center; gap: 8px; min-width: 0; }
.topbar .acts > * { flex: none; white-space: nowrap; }

@media (max-width: 600px) {
  /* 두 줄 고정 — 1줄 [☰ 제목·칩] / 2줄 [버튼 묶음]. 버튼 줄은 접지 않고 넘치면 그 상자 안에서만 가로로 굴린다(6b-8 규칙). */
  .topbar { flex-wrap: wrap; row-gap: 4px; padding-bottom: 6px; }
  .topbar > .grow { flex: 1 1 auto; min-width: 0; }
  .topbar .acts { flex: 1 0 100%; width: 100%; flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .topbar .acts::-webkit-scrollbar { width: 0; height: 0; }
}
/* 6b-7: 메인은 사이드바와 별개의 스크롤 컨테이너다(라우트가 바뀌면 여기만 맨 위로 돌아간다). */
/* 6b-8 · overflow-y:auto 는 overflow-x 를 auto 로 만든다 — 실제 가로 스크롤은 여기서 났다. 명시적으로 막는다.
   가로로 넘칠 수 있는 것(표·코드 블록)은 자기 상자 안에서만 스크롤한다(.md pre · .md table · .tbl-wrap). */
.content { flex: 1; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; min-height: 0; min-width: 0; padding: 14px 16px 24px; }
.content.narrow { max-width: 900px; width: 100%; margin: 0 auto; }
.panel { background: var(--bg-2); border-left: 1px solid var(--line); overflow-y: auto; min-height: 0; padding: 12px 14px calc(14px + env(safe-area-inset-bottom)); font-size: 13px; }
.panel h3 { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; margin: 14px 0 6px; }
.panel h3:first-child { margin-top: 0; }
.panel .box { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-s); padding: 8px 10px; }
.panel .box + .box { margin-top: 6px; }
/* 왜: 상자 높이를 줄 높이의 배수로 맞춰 마지막 줄이 반쯤 잘리지 않게 하고, 넘칠 때만 아래를 흐리게 해 이어짐을 알린다. */
.panel .clamp { --lh: 1.5; line-height: var(--lh); max-height: calc(var(--lh) * 1em * 8 + 16px); overflow: hidden; position: relative; }
.panel .clamp.overflow::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2.2em; background: linear-gradient(to bottom, transparent, var(--surface)); pointer-events: none; }
.panel .clamp.open { max-height: none; }
.panel .clamp.open::after { display: none; }
.panel .clamp.md h1, .panel .clamp.md h2, .panel .clamp.md h3 { font-size: 12.5px; margin: 6px 0 3px; color: var(--ink-2); }
.panel .clamp.md h1:first-child, .panel .clamp.md h2:first-child { margin-top: 0; }
.panel .clamp.md blockquote { margin: 0 0 6px; padding-left: 8px; border-left: 2px solid var(--line-2); color: var(--muted); }
.panel .clamp.md ul { margin: 0 0 6px; padding-left: 16px; }
.panel .clamp.md p { margin: 0 0 6px; }
.panel .more { display: block; margin-top: 4px; }
.panel .recent button { background: transparent; border: 0; color: var(--ink-2); text-align: left; padding: 3px 0; width: 100%; font-size: 12.5px; }
.panel .recent button:hover { color: var(--accent); }
.mobile-only { display: none; }

/* ── 대화 ── */
.chat { display: flex; flex-direction: column; gap: 14px; max-width: 900px; margin: 0 auto; }
.tip { border: 1px dashed var(--line-2); background: var(--surface); border-radius: var(--radius); padding: 10px 14px; display: flex; gap: 10px; align-items: flex-start; font-size: 13px; }
.tip .t { font-weight: 600; margin-right: 6px; }
.tip .x { margin-left: auto; }
.msg { display: flex; flex-direction: column; gap: 8px; }
.q { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 14px; white-space: pre-wrap; word-break: break-word; }
.q .meta { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; font-size: 11.5px; color: var(--muted); margin-top: 6px; }
/* §41 · 고쳐 보낸 원 질문. **지우지 않고 접는다** — 무엇을 왜 멈췄는지 기록이 남아야 한다.
   접는 것은 높이뿐이고 글자는 그대로 있다(찾기·복사가 죽지 않게). [펼치기]가 .folded 만 떼면 원래대로 돌아온다.
   ★ 왼쪽 굵은 선은 "이건 지나간 판" 이라는 표시다 — 색은 §37-1 토큰만 쓴다(새 색을 만들지 않는다). */
.q.edited { border-left: 3px solid var(--line-2); opacity: .82; }
.q.edited.folded .qtext { max-height: 3.4em; overflow: hidden; -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent); mask-image: linear-gradient(180deg, #000 55%, transparent); }
.q .qmore { padding: 0 6px; font-size: 11.5px; }
.q .editfrom { margin-bottom: 6px; }
.prog { border-left: 2px solid var(--line-2); margin-left: 6px; padding-left: 10px; }
.prog summary { cursor: pointer; font-size: 12.5px; color: var(--muted); list-style: none; display: flex; align-items: center; gap: 6px; }
.prog summary::-webkit-details-marker { display: none; }
.prog summary::before { content: "▸"; font-size: 11px; }
.prog[open] summary::before { content: "▾"; }
.prog .lines { margin: 6px 0 0; padding: 0; list-style: none; font-family: var(--mono); font-size: 12px; color: var(--ink-2); }
.prog .lines li { padding: 1px 0; white-space: pre-wrap; word-break: break-word; }
.prog .lines li .ts { color: var(--muted); margin-right: 8px; }
.spin { display: inline-block; width: 10px; height: 10px; border: 2px solid var(--line-2); border-top-color: var(--accent); border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.a { padding: 2px 4px; }
.md h1, .md h2, .md h3, .md h4 { margin: 14px 0 6px; line-height: 1.3; }
.md h1 { font-size: 18px; } .md h2 { font-size: 16px; } .md h3 { font-size: 14.5px; } .md h4 { font-size: 14px; }
.md p { margin: 6px 0; } .md ul, .md ol { margin: 6px 0; padding-left: 22px; } .md li { margin: 2px 0; }
/* 6b-8 · 본문 규칙(브리핑 본문·사업 답변 공통).
   왜: 인라인 코드(`01 신용보증재단 대출 (우리은행)` — 화면에서는 칩으로 보인다)가 줄바꿈되지 않아 좁은 폭에서
   한 줄이 화면 밖으로 나갔다. 인라인 코드·본문 칩은 줄바꿈을 허용하고, 원문 그대로 읽어야 하는
   코드 블록·표만 자기 상자 안에서 가로 스크롤한다. */
.md { min-width: 0; overflow-wrap: anywhere; }
.md pre { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-s); padding: 10px 12px; overflow-x: auto; max-width: 100%; }
.md code { background: var(--surface-2); padding: 1px 5px; border-radius: 4px; white-space: normal; overflow-wrap: anywhere; }
.md pre code { background: transparent; padding: 0; white-space: pre; overflow-wrap: normal; }
.md .chip { white-space: normal; }
.md blockquote { margin: 6px 0; padding: 2px 12px; border-left: 3px solid var(--line-2); color: var(--ink-2); }
.md table { border-collapse: collapse; margin: 8px 0; font-size: 13px; display: block; overflow-x: auto; max-width: 100%; }
.md th, .md td { border: 1px solid var(--line); padding: 4px 8px; }
.md hr { border: 0; border-top: 1px solid var(--line); margin: 12px 0; }

/* ── 형광펜(§37-2 · 37 회차) ──────────────────────────────────────────────
   한 규칙을 둘이 쓴다: ① 세션이 직접 고른 `==강조==`(md() 가 <mark> 로 바꾼다)
   ② 화면이 자동으로 칠하는 세 자리(app.js autoMark — 답 첫 문장 · 저장 경로 · 결정/확인 필요 항목 제목, class="hl").
   노란 형광을 안 쓰는 이유: 어두운 판에서 눈이 아프고 상태 4색(완료·대기·기획·오류)과 섞여 뜻이 흐려진다.
   글자색은 건드리지 않는다 — 대비는 (글자 vs 강조 배경) 한 쌍만 보면 된다(밝은 14.2:1 · 어두운 12.3:1).
   box-decoration-break:clone = 두 줄로 접힌 강조의 끝줄에도 둥근 모서리·좌우 여백이 그대로 붙는다. */
mark, .md mark { background: var(--accent-soft); color: inherit; border-radius: 3px; padding: 0 2px;
  -webkit-box-decoration-break: clone; box-decoration-break: clone; }

/* ── 읽기 규칙(§37-3) ─────────────────────────────────────────────────────
   ★ 줄 길이는 --read-w 한 값에서만 나온다. 본문(문단·목록·인용)에만 걸고 표·코드 블록은 뺀다 —
     그 둘은 자기 상자 안에서 가로로 굴러야 한다(6b-8 규칙). max-width 라 좁은 폭에서는 아무 일도 안 한다.
   ★ 제목 text-wrap:balance = 두 줄로 접힐 때 아랫줄에 한 낱말만 남는 것을 막는다(미지원 브라우저는 무시). */
.md p, .md li, .md blockquote { max-width: var(--read-w); }
.md p, .md li { line-height: 1.7; }
.md h1, .md h2, .md h3, .md h4, .card h3, .modal h2, .topbar .title { text-wrap: balance; }
/* 숫자가 줄지어 나오는 자리(표·사용량·시각). 자릿수가 흔들리면 세로로 비교해 읽을 수 없다. */
.mono, .tbl, .md table, .kv dd, .stat .n, .lim-row, .uptime-lab, .fbar .when, .prog .lines { font-variant-numeric: tabular-nums; }

/* ── 카드 위계(§37-3) ─────────────────────────────────────────────────────
   규칙 셋: 답 카드는 '면'(테두리·그림자 없음) · 상태는 '칩 색' · 구분은 '선 하나'.
   그림자는 **떠 있는 것**(모달·메뉴·팝오버·토스트·버전 막대)에만, 그것도 --shadow 한 겹만.
   문서 흐름에 놓인 상자(.card·.brf-head·.outpins)는 테두리만 갖는다 — 셋을 다 주면 위계가 사라진다. */
.mem { border: 1px solid var(--line); border-left: 3px solid var(--accent); background: var(--surface); border-radius: var(--radius-s); padding: 8px 12px; font-size: 13px; }
.mem .h { font-size: 11.5px; color: var(--muted); font-weight: 600; margin-bottom: 4px; }
.mem ul { margin: 0; padding-left: 18px; }
.att { display: flex; flex-wrap: wrap; gap: 6px; }
.att a { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line-2); border-radius: var(--radius-s); padding: 4px 10px; font-size: 12.5px; text-decoration: none; color: var(--ink); background: var(--surface); }
.actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; font-size: 12px; color: var(--muted); }
/* §41 · [✏ 수정]은 넓은 화면에서는 제 단추로, 폰(좁은 폭)에서는 카드 ⋯ 메뉴 **첫 줄**로 간다(§41 ⑦).
   ★ 폭 판정을 CSS 에 맡긴 이유: 카드는 한 번만 그려지므로 JS 로 정하면 화면을 돌렸을 때 옛 판이 그대로 남는다.
   ★ 아래 600px 조건은 이 파일의 다른 두 줄 머리(.topbar) 조건과 같은 값이다 — 한쪽만 고치면 어긋난다. */
.actions .card-more { display: none; }
@media (max-width: 600px) {
  .actions .edit-wide { display: none; }
  .actions .card-more { display: inline-flex; }
}
.err { border: 1px solid var(--danger-soft); background: var(--danger-soft); border-radius: var(--radius-s); padding: 10px 12px; font-size: 13px; }
.err .h { font-weight: 700; color: var(--danger); margin-bottom: 4px; }
.err .dev { font-family: var(--mono); font-size: 12px; color: var(--ink-2); white-space: pre-wrap; word-break: break-all; margin-top: 4px; }
.empty { color: var(--muted); text-align: center; padding: 40px 10px; font-size: 13.5px; }
/* 대화 위 안내 줄(개인 모드 등). */
.note { border: 1px solid var(--line); background: var(--bg-2); border-radius: var(--radius-s); padding: 8px 11px; font-size: 12.5px; color: var(--ink-2); margin-bottom: 4px; }
/* 새 대화 시트 — 개인 버튼 + 검색 + 목록. */
.newchat-sheet input[type=search] { width: 100%; margin: 10px 0 2px; }
.newchat-sheet .picklist { max-height: 46svh; overflow-y: auto; }
.pick { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; padding: 9px 10px; border: 0; background: transparent; border-radius: var(--radius-s); color: var(--ink-2); font-size: 13.5px; }
.pick:hover { background: var(--bg-2); color: var(--ink); }
.pick .num { font-family: var(--mono); font-size: 11px; color: var(--muted); width: 22px; flex: none; }
.pick .nm { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pick.personal { border: 1px solid var(--line); background: var(--bg-2); font-weight: 600; color: var(--ink); }
.pick.personal:hover { border-color: var(--accent); }
.pick.personal .num { color: var(--accent); }
.newchat-sheet .pick.personal + .pick.personal { margin-top: 6px; }

/* 사업 추가 마법사 — 한 번에 한 질문(1/10) → 요약 → 만들기. */
.wiz-bar { height: 4px; border-radius: 2px; background: var(--bg-2); overflow: hidden; margin-bottom: 10px; }
.wiz-bar i { display: block; height: 100%; background: var(--accent); transition: width .15s ease; }
.wiz-head .row { gap: 8px; }
.wiz-body { min-height: 128px; margin-top: 12px; }
.wiz-body label { display: block; font-size: 12.5px; color: var(--muted); margin: 10px 0 3px; }
.wiz-body input[type=text], .wiz-body textarea { width: 100%; }
.wiz-pick { display: flex; flex-wrap: wrap; gap: 6px; }
.wiz-rows .row { margin-bottom: 6px; }
.wiz-rows input[type=date] { flex: none; }
.wiz-err { color: var(--danger); font-size: 12.5px; min-height: 17px; margin-top: 8px; }
.wiz-sum { max-height: 44svh; overflow-y: auto; }
.wiz-sum-row { display: flex; gap: 10px; padding: 6px 0; border-top: 1px solid var(--line); font-size: 13px; }
.wiz-sum-row:first-child { border-top: 0; }
.wiz-sum-row .k { flex: none; width: 78px; color: var(--muted); }
.wiz-sum-row .v { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.wiz-sum-row .v ul { padding-left: 0; }
.wiz-sum-row .v .list li { border-top: 0; padding: 2px 0; }

/* ── 입력칸 ── */
.composer { border-top: 1px solid var(--line); background: var(--bg); padding: 8px 12px calc(10px + env(safe-area-inset-bottom)); }
.composer .inner { max-width: 900px; margin: 0 auto; background: var(--surface); border: 1px solid var(--line-2); border-radius: 14px; padding: 8px 10px; position: relative; }
.composer .inner:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.composer textarea { width: 100%; border: 0; background: transparent; resize: none; padding: 4px 4px 2px; min-height: 40px; max-height: 40vh; outline: none; box-shadow: none; }
.composer .bar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.composer .bar select { font-size: 12px; padding: 3px 6px; border-radius: 6px; background: var(--surface-2); border-color: transparent; }
.composer .send { margin-left: auto; }
/* 입력칸 사업 드롭다운(기획 §3) — 버튼 + 위로 열리는 목록(새 대화 시트와 같은 .picklist 부품). */
/* 왜 위로 여나: 입력칸이 화면 맨 아래라 아래로 열면 목록이 잘린다(.slash 와 같은 방식). */
.composer .bizwrap { position: relative; }
/* 왜 nowrap 인가(6b-2): 사업명이 길면 "사업:" 라벨과 ▾ 가 따로 줄바꿈되어 버튼이 두 줄이 되고 입력칸 높이가 흔들렸다.
   라벨·화살표는 접지 않고, 줄어드는 것은 사업명(.v) 하나뿐이다(말줄임). 좁은 화면에서는 .v 를 더 줄인다. */
.composer .bizsel { font-size: 12px; padding: 3px 8px; border-radius: 6px; background: var(--surface-2); border-color: transparent; max-width: 190px; white-space: nowrap; flex: 0 1 auto; min-width: 0; }
.composer .bizsel .v { max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: bottom; font-weight: 600; }
@media (max-width: 520px) { .composer .bizsel { max-width: 150px; } .composer .bizsel .v { max-width: 92px; } }
.bizpop { position: absolute; left: 0; bottom: calc(100% + 6px); background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-s); box-shadow: var(--shadow); width: 320px; max-width: 78vw; z-index: 6; padding: 8px; }
.bizpop input[type=search] { width: 100%; margin-bottom: 4px; }
.bizpop .picklist { max-height: 44svh; overflow-y: auto; }
.composer .files { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.composer .files .chip button { border: 0; background: transparent; padding: 0 0 0 4px; color: inherit; }
/* 첨부 칩(기획 §6) — 붙여넣기·드래그·📎 가 모두 같은 칩으로 모인다. 이미지는 썸네일, 그 밖은 문서 아이콘. */
/* 폰(폴드8 웹뷰)에서도 ✕ 가 눌려야 하므로 최소 터치 크기 28px 을 지킨다. */
.composer .files .chip.att { padding: 3px 4px 3px 5px; gap: 6px; max-width: 240px; }
.composer .files .chip.att .th { width: 28px; height: 28px; object-fit: cover; border-radius: 5px; display: block; }
.composer .files .chip.att .ico { width: 28px; text-align: center; font-size: 15px; }
.composer .files .chip.att .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 130px; }
.composer .files .chip.att .x { min-width: 28px; min-height: 28px; padding: 0; border-radius: 999px; font-size: 13px; }
.composer .files .chip.att .x:hover { background: var(--surface); }
/* 파일을 끌어다 놓는 동안의 표시. dragover 를 막지 않으면 브라우저가 파일을 새 탭으로 연다(app.js 쪽에서 막는다). */
.composer .inner.dropping { border-color: var(--accent); border-style: dashed; background: var(--accent-soft); }

/* ── 35-C · 파일 서랍 + 입력창 위 띠(§8-21) ──────────────────────────────────
   왜 .composer 안인가: 입력창 바로 위가 재희님이 지목한 자리이고(사용량 경고 띠와 같은 층),
   구조적으로 하단 탭바·입력창 아래로 내려갈 수 없어 겹침 계산이 아예 필요 없다.
   본문 위로 뜨는 것은 펼친 목록(.fd-pop) 하나뿐이다 — 그것만 absolute 다.
   폭은 입력창(.inner)과 같은 900px 로 맞춘다(가운데 정렬이 어긋나면 손잡이가 화면 끝으로 달아난다). */
.fdock { max-width: 900px; margin: 0 auto 4px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.fbar { display: flex; align-items: center; gap: 6px; min-width: 0; flex-wrap: wrap;
  background: var(--accent-soft); border: 1px solid var(--line-2); border-radius: 10px; padding: 4px 6px 4px 9px; font-size: 12.5px; }
.fbar .ico { flex: 0 0 auto; }
.fbar .nm { flex: 1 1 120px; min-width: 0; border: 0; background: transparent; padding: 0; font: inherit; font-weight: 600; color: var(--accent); text-align: left; cursor: pointer; }
.fbar .nm:hover { text-decoration: underline; }
.fbar .when { flex: 0 0 auto; font-size: 11.5px; }
.fbar .btn { min-height: 26px; padding: 2px 8px; }
.fbar .btn.x { min-width: 28px; padding: 2px 6px; }
/* 서랍 — 손잡이는 오른쪽 아래(입력창 바로 위 오른쪽), 목록은 손잡이 위로 펼쳐진다. */
.fdrawer { position: relative; align-self: flex-end; max-width: 100%; }
.fd-handle { border-radius: 999px; background: var(--surface-2); border-color: transparent; font-size: 12px; padding: 3px 10px; }
.fd-handle.on { background: var(--accent-soft); color: var(--accent); }
.fd-pop { position: absolute; right: 0; bottom: calc(100% + 6px); z-index: 30; width: 320px; max-width: min(92vw, 360px);
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-s); box-shadow: var(--shadow); padding: 6px; }
.fd-pop[hidden] { display: none; }
.fd-head { display: flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; color: var(--muted); padding: 2px 4px 6px; }
.fd-head .btn { min-height: 26px; padding: 2px 7px; }
/* 목록만 굴린다. 행 ⋯ 메뉴는 이 상자 안에 있어 같이 굴러간다(허공에 뜬 메뉴가 생기지 않는다). */
.fd-listwrap { position: relative; max-height: min(46svh, 340px); overflow-y: auto; overflow-x: hidden; }
.fd-row { display: flex; align-items: center; gap: 7px; padding: 5px 4px; border-radius: 8px; cursor: pointer; min-width: 0; }
.fd-row:hover { background: var(--surface-2); }
.fd-row .ico { flex: 0 0 auto; font-size: 15px; }
.fd-row .nm { font-size: 12.5px; font-weight: 600; }
.fd-row .dots { flex: 0 0 auto; min-width: 28px; min-height: 28px; padding: 0; }
.fd-empty { padding: 12px 6px; font-size: 12.5px; text-align: center; }
.fd-menu { position: absolute; right: 6px; z-index: 2; display: flex; flex-direction: column; align-items: stretch; gap: 2px;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-s); box-shadow: var(--shadow); padding: 4px; }
.fd-menu[hidden] { display: none; }
.fd-menu .btn { justify-content: flex-start; white-space: nowrap; font-size: 12px; min-height: 30px; }
/* 폰(§8-21) — 접은 앞화면·좁은 폭에서는 띠만 두고 서랍은 [파일] 패널이 갈음한다. 손잡이 한 줄만큼도 아깝다. */
@media (max-width: 420px) { .fdrawer { display: none; } .fbar { font-size: 12px; padding: 3px 5px 3px 7px; } }
/* 분할 화면·버블(compact=1)은 대화와 입력창만 그리는 자리다 — 여기에도 두지 않는다. */
.shell.compact .fdock { display: none; }
/* §33-1 · 본문 어디나 드롭. 창 전체에 테두리를 둘러 "여기 놓아도 된다" 를 알린다(입력창 위가 아니어도 된다).
   pointer-events:none 이 없으면 이 겹이 drop 이벤트를 가로채 파일이 어디에도 안 붙는다. */
html.dropping-page::after { content: '여기에 놓으면 던지기'; position: fixed; inset: 8px; z-index: 90; pointer-events: none;
  border: 2px dashed var(--accent); border-radius: 10px; background: var(--accent-soft);
  display: flex; align-items: flex-end; justify-content: center; padding-bottom: 18px; font-size: 13px; color: var(--accent); opacity: .85; }
/* §33-3 · 답 카드 맨 위 "저장:" 줄. 경로가 길어도 버튼이 밀려나지 않게 줄바꿈을 허용한다. */
.msg .saved { display: flex; flex-direction: column; gap: 4px; margin: 0 0 8px; }
.msg .saved .row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.msg .saved .chip.ok { max-width: 100%; overflow-wrap: anywhere; }
/* 35-B(§8-19) · "저장:" 칩 자체가 파일을 여는 단추다. 칩 모양은 그대로 두고 단추 티(테두리·기본 글꼴)만 지운다. */
.chip.as-link { border: 0; cursor: pointer; font: inherit; font-size: 11.5px; font-weight: 600; text-align: left; }
.chip.as-link:hover { text-decoration: underline; }
.slash { position: absolute; left: 10px; bottom: calc(100% + 6px); background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-s); box-shadow: var(--shadow); min-width: 260px; max-width: 90%; z-index: 5; overflow: hidden; }
.slash button { display: flex; gap: 10px; width: 100%; text-align: left; padding: 7px 12px; border: 0; background: transparent; font-size: 13px; }
.slash button.on, .slash button:hover { background: var(--accent-soft); }
.slash .c { font-family: var(--mono); color: var(--accent); min-width: 70px; }
.slash .d { color: var(--muted); }

/* ── 브리핑·목록 화면 ── */
.two { display: grid; grid-template-columns: 220px 1fr; gap: 14px; }
.datelist button { display: block; width: 100%; text-align: left; border: 0; background: transparent; padding: 7px 10px; border-radius: var(--radius-s); color: var(--ink-2); font-size: 13px; }
.datelist button.on { background: var(--surface); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
/* 6b-8 · 미리보기는 2줄 말줄임. 옛 nowrap+ellipsis 는 부모가 좁아지지 않으면 잘리지 않고 그대로 밀어냈다.
   마크다운 기호 제거는 서버(routes/briefings.js briefingPreview)가 한다. */
.datelist .pv { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; white-space: normal; font-size: 11px; line-height: 1.4; color: var(--muted); }
.datelist button { min-width: 0; }

/* 6b-9 · 브리핑 탭 재배치 — 머리줄 고정 → 날짜 칩 한 줄 → (접힘) 전체 목록 → 본문.
   왜: 2단(.two)에서는 좁은 폭에서 왼쪽 날짜 목록이 위로 접혀 첫 화면을 통째로 차지했다.
   머리줄은 sticky 라 본문을 내려도 날짜와 [지금 만들기]가 늘 보인다(파란 띠 버튼 제거). */
.brf-head { position: sticky; top: 0; z-index: 3; display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 7px 10px; margin-bottom: 8px; background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-s); }
.brf-head .ttl { min-width: 0; font-weight: 700; font-size: 14px; overflow-wrap: anywhere; }
.brf-head .act { flex: none; margin-left: auto; display: flex; gap: 6px; }
/* 칩 줄은 자기 상자 안에서만 좌우로 굴러간다(6b-8 규칙 — 화면 전체는 안 밀린다). */
.brf-chips { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; overflow-x: auto; padding-bottom: 2px; }
.brf-chips .dchip { flex: none; padding: 3px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink-2); font-size: 12.5px; white-space: nowrap; cursor: pointer; }
.brf-chips .dchip.on { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); font-weight: 600; }
.brf-list { margin-bottom: 8px; }

/* ── 파일 ── */
.tree { font-size: 13px; }
.tree .node { display: flex; align-items: center; gap: 6px; padding: 3px 6px; border-radius: 6px; cursor: pointer; user-select: none; }
.tree .node:hover { background: var(--surface-2); }
.tree .node.on { background: var(--accent-soft); }
.tree .node .ico { width: 16px; text-align: center; color: var(--muted); font-size: 12px; }
.tree .kids { margin-left: 16px; border-left: 1px dashed var(--line); padding-left: 4px; }
.files-grid { display: grid; grid-template-columns: 300px 1fr; gap: 12px; min-height: 60vh; }
.viewer { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); min-height: 60vh; overflow: hidden; display: flex; flex-direction: column; }
.viewer .vhead { padding: 8px 12px; border-bottom: 1px solid var(--line); display: flex; gap: 8px; align-items: center; font-size: 13px; }
.viewer iframe { flex: 1; border: 0; width: 100%; min-height: 55vh; background: #fff; }
.viewer textarea { flex: 1; border: 0; border-radius: 0; min-height: 55vh; font-family: var(--mono); font-size: 13px; }
.viewer .vbody { flex: 1; overflow: auto; padding: 12px 14px; }
.viewer img { max-width: 100%; }

/* ── PDF 뷰어(8-19-1) — pdf.js 가 캔버스로 그린다. 폰 WebView 에는 내장 PDF 뷰어가 없다 ── */
.pdfv { display: flex; flex-direction: column; gap: 8px; }
.pdfv-bar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
/* position:relative — 쪽 번호·[◀▶] 가 offsetTop 을 이 상자 기준으로 잰다(기준이 바뀌면 엉뚱한 쪽으로 뛴다). */
/* touch-action — 브라우저 기본 핀치를 끄고 뷰어가 직접 배율을 잡는다(끄지 않으면 화면 전체가 확대된다). */
.pdfv-pages { position: relative; overflow: auto; max-height: 70vh; background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px; padding: 8px; -webkit-overflow-scrolling: touch; touch-action: pan-x pan-y; }
/* min-width:fit-content — 확대해 캔버스가 상자보다 넓어져도 가운데 정렬이 왼쪽을 잘라먹지 않는다. */
.pdfv-page { display: flex; justify-content: center; min-width: fit-content; margin-bottom: 10px; }
.pdfv-page:last-child { margin-bottom: 0; }
/* 배경은 흰색 고정 — 어두운 판에서도 종이는 종이다(투명 PDF 가 검게 뭉개지는 것을 막는다). max-width 는 두지 않는다(확대가 막힌다). */
.pdfv-cv { background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .18); display: block; }

/* ── 파일 탐색기(§8-1·§8-2·§8-3, 6b-1) ── */
.fx .fx-list { margin-top: 10px; }
.fx .list-flat { padding: 6px; }
.fx-row { display: flex; align-items: center; gap: 8px; padding: 8px 8px; border-radius: 8px; cursor: pointer; }
.fx-row + .fx-row { border-top: 1px solid var(--line); }
.fx-row:hover { background: var(--surface-2); }
.fx-row.on { background: var(--accent-soft); }
.fx-row .ico { width: 22px; text-align: center; font-size: 15px; flex: none; }
.fx-row .nm { font-size: 13.5px; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 오늘 클로드가 만진 줄(§8-4 [클로드 작업]·"방금 만든 파일" 묶음). 색을 더 쓰면 대표에게 보임·잠김 칩과 다툰다. */
.fx-row.today .nm { font-weight: 700; }
/* 파일 종류 3분류 배지(§8-4). 산출물=파랑 · 원본=회색 · 작업용=옅은 노랑 */
.chip.k-out { background: var(--accent-soft); color: var(--accent); }
.chip.k-src { background: var(--surface-2); color: var(--ink-2); }
.chip.k-work { background: var(--warn-soft); color: var(--warn); }
.fx-row .fx-acts { flex: none; opacity: 0.55; }
.fx-row:hover .fx-acts, .fx-row.on .fx-acts { opacity: 1; }
.fx-row .fx-acts .btn { padding: 2px 6px; }
/* 8-13b · 다중 선택. 체크는 평소 흐리게 두고 마우스를 올리거나 고른 줄에서만 또렷해진다(줄마다 체크가 보이면 목록이 시끄럽다). */
.fx-row .fx-ck { flex: none; width: 16px; height: 16px; margin: 0; opacity: .35; cursor: pointer; }
.fx-row:hover .fx-ck, .fx-row.picked .fx-ck { opacity: 1; }
.fx-row.picked { background: var(--accent-soft); }
/* 선택 바는 버튼이 다섯이라 좁은 폭에서 반드시 접혀야 한다(6b-8: 가로로 굴러가지 않게). */
.fx .selbar { flex-wrap: wrap; border-radius: 14px; }
/* 8-13 · 파일 탭 루트의 사업 카드. 좁은 폭에서는 자동으로 1단이 된다(6b-8: 가로로 굴러가지 않게 minmax 하한을 0 으로). */
.fx-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); gap: 8px; }
.fx-cards .fx-biz { cursor: pointer; min-width: 0; margin: 0; }
.fx-cards .fx-biz:hover { background: var(--surface-2); }
/* 답변·기억 줄의 파일 경로 링크 */
a.fpath { text-decoration: underline dotted; word-break: break-all; }
/* 답변 속 파일 링크 옆 [핀](§8 · 6b-2). 글자 흐름을 밀지 않도록 아주 작게 두고, 카드를 인쇄·복사할 땐 빠진다. */
.pinbtn { border: 0; background: transparent; padding: 0 2px; font-size: 11px; line-height: 1; cursor: pointer; opacity: .45; }
.pinbtn:hover, .pinbtn.on { opacity: 1; }
/* 사업 탭 머리 아래 고정 산출물 목록. 대화가 쌓여도 위에 붙어 있어야 "아까 그 문서" 에 바로 닿는다. */
.outpins { position: sticky; top: 0; z-index: 3; display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  padding: 6px 8px; margin-bottom: 8px; background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius-s); }
.outpins .chip.pin { max-width: 260px; gap: 4px; }
.outpins .chip.pin a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 210px; display: inline-block; vertical-align: bottom; }
.outpins .chip.pin button.x { border: 0; background: transparent; padding: 0 0 0 2px; color: inherit; cursor: pointer; }
/* 입력칸의 PC 파일 첨부 칩(경로 참조) */
.composer .pins:empty { display: none; }

/* ── 기기 ── */
.dev-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; align-items: stretch; }
/* 왜 flex column + margin-top:auto(6b-2): 그램·집PC 는 담는 항목 수가 다르다(집PC 는 사무실 Z: 백업이 없고,
   구 실행기는 세션 슬롯 줄이 없다). 그대로 두면 카드 높이와 가동 막대의 바닥 선이 어긋나 두 PC 를 나란히 못 읽는다.
   격자는 카드를 같은 높이로 늘이고, 가동 막대는 남는 자리를 밀어 카드 맨 아래에 붙는다. */
.dev-cards > .card { display: flex; flex-direction: column; }
/* ★ 6b-6 높이 불일치의 실제 원인: 전역 `.card + .card { margin-top: 10px }` 가 격자 안에서도 먹는다.
   격자는 stretch 로 카드를 행 높이에 맞추지만 그 높이에서 margin 을 빼므로, 첫 장을 뺀 모든 카드가
   10px 아래로 밀리고 10px 짧아진다(재희님 01:03 스크린샷의 확장 카드·앱 카드 4장). 격자 안에서는 여백을 gap 이 맡는다. */
.dev-cards > .card + .card { margin-top: 0; }
/* 카드마다 담는 항목 수가 다르다(집PC 는 Z: 백업 없음, 확장은 가동 막대 없음, 앱 카드는 안내문 길이가 제각각).
   맨 아래에 붙일 요소에 .card-foot(또는 기기 카드의 .uptime)을 주면 남는 자리를 밀어 바닥선이 맞는다. */
.dev-cards > .card .uptime, .dev-cards > .card .card-foot { margin-top: auto; }
/* 카드 안이 한 겹 더 감싸인 경우(APK 카드는 비동기로 통째 교체된다) 그 겹도 세로로 늘여야 바닥 정렬이 통한다. */
.dev-cards > .card > .col-fill { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* 확장 카드의 '최근 전송 이력 6칸'(6b-6). 가동 막대 자리를 대신해 카드 구조를 다른 카드와 같게 만든다. */
.ext-hist { display: flex; gap: 4px; margin-top: 8px; }
.ext-hist .h { flex: 1; min-width: 0; text-align: center; border-radius: 4px; background: var(--accent-soft); padding: 4px 0 3px; }
.ext-hist .h.empty { background: transparent; border: 1px dashed var(--line-2); }
.ext-hist .h.bad { background: var(--danger-soft); }
.ext-hist .h i { display: block; width: 6px; height: 6px; border-radius: 50%; margin: 0 auto 3px; background: var(--accent); }
.ext-hist .h.novalue i { background: var(--muted); }
.ext-hist .h.bad i { background: var(--danger); }
.ext-hist .h.empty i { background: transparent; border: 1px solid var(--line-2); }
.ext-hist .h span { font-size: 9.5px; color: var(--muted); }
/* 긴 안내문(앱 카드 설치 방법 등)은 3줄까지만 — 카드 하나가 길어지면 같은 줄 전체가 그 높이로 늘어난다. */
.clamp3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.more-btn { border: 0; background: transparent; color: var(--accent); padding: 2px 0 0; font-size: 12px; cursor: pointer; }
.dev-state { font-weight: 700; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
/* Z: 백업 경고는 실행기가 올리는 한 줄 문장이라 칩 안에 넣으면 카드 폭을 밀어냈다. 칩은 낱말만, 문장은 아래 두 줄까지. */
.zbk { display: flex; flex-direction: column; gap: 2px; align-items: flex-start; min-width: 0; }
.zbk .chip { white-space: nowrap; }
.clamp2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.uptime { display: flex; gap: 4px; align-items: flex-end; height: 42px; margin-top: 6px; }
.uptime .bar { flex: 1; background: var(--accent-soft); border-radius: 3px 3px 0 0; position: relative; min-height: 2px; }
.uptime .bar i { position: absolute; left: 0; right: 0; bottom: 0; background: var(--accent); border-radius: 3px 3px 0 0; }
.uptime-lab { display: flex; gap: 4px; font-size: 10px; color: var(--muted); }
.uptime-lab span { flex: 1; text-align: center; }

/* ── 사용 한도(§1 · 1-A) ──
   막대는 기기 탭 카드, .limit-hint 는 입력창 상태줄. 색만으로 알리지 않고 % 숫자를 항상 함께 둔다. */
.lim { display: grid; gap: 8px; }
.lim-row { display: grid; grid-template-columns: 76px 1fr 46px auto; align-items: center; gap: 8px; }
.lim-lab { font-size: 12px; color: var(--muted); }
.lim-bar { height: 8px; border-radius: 4px; background: var(--accent-soft); overflow: hidden; }
.lim-bar i { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
.lim-bar.warn i { background: var(--warn); }
.lim-bar.danger i { background: var(--danger); }
.lim-pct { font-size: 12px; font-variant-numeric: tabular-nums; text-align: right; }
.lim-pct.warn { color: var(--warn); font-weight: 600; }
.lim-pct.danger { color: var(--danger); font-weight: 600; }
.lim-res { white-space: nowrap; }
.limit-hint { white-space: nowrap; color: var(--muted); }
/* 22-1 · 70% 이상은 색만, 90%(보류임계) 이상은 색+굵기, 100% 는 빨강. 색만으로 알리지 않으려고 % 숫자는 늘 함께 둔다. */
.limit-hint.caution { color: var(--warn); }
.limit-hint.warn { color: var(--warn); font-weight: 600; }
.limit-hint.danger { color: var(--danger); font-weight: 600; }
/* 23-4 · 큐 계획 카드에서도 같은 '주의' 색을 쓴다(.limit-hint 안이 아니라 일반 줄이라 규칙이 따로 필요하다). */
.caution { color: var(--warn); }
/* 22-1 · 입력창 상태줄 슬롯. 폴링이 이 안만 다시 그린다 — display:contents 라 도구 줄 배치는 슬롯이 없던 때와 같다. */
.cstat { display: contents; }
@media (max-width: 480px) { .lim-row { grid-template-columns: 64px 1fr 42px; } .lim-res { grid-column: 2 / -1; } }

/* ── 사용 패턴 히트맵(§20-4 · 20-A) ──
   24칸 격자 2장 + 창 띠. 진하기(opacity)로만 값을 그리고 정확한 값은 마우스 올림(title)에 둔다 —
   색 단계로 숫자를 읽게 만들면 색약·다크 테마에서 틀리게 읽힌다. 폰(≤480)에서도 24칸이 한 줄에 들어가야
   요일 비교가 가능하므로 칸 높이만 줄이고 칸 수는 줄이지 않는다. */
.heat, .wband { display: grid; grid-template-columns: 20px repeat(24, 1fr); gap: 2px; align-items: center; margin-top: 4px; }
.heat b, .wband b { font: 10px/12px var(--mono); color: var(--muted); font-weight: 400; text-align: right; padding-right: 2px; }
.heat i { display: block; height: 12px; border-radius: 2px; background: var(--accent); }
.heat.burn i { background: var(--warn); }
.wband { margin-top: 6px; }
.wband i { display: block; height: 8px; border-radius: 2px; background: var(--line); }
.wband i.wsleep { background: var(--accent-soft); }
.wband i.wfocus { background: var(--accent); }
.wband i.wfree { background: var(--ok); }
.chip.wsleep { background: var(--accent-soft); color: var(--ink); }
.chip.wfocus { background: var(--accent); color: var(--accent-ink); }
.chip.wfree { background: var(--ok-soft); color: var(--ink); }
@media (max-width: 480px) { .heat i { height: 9px; } .heat, .wband { gap: 1px; } }

/* ── 설정 ── */
.set-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line); }
.set-row:first-of-type { border-top: 0; }
.set-row .lab { flex: 1; }
.set-row .lab small { display: block; color: var(--muted); font-size: 11.5px; }
.set-row.sub { padding-left: 18px; }

/* ── 상태 ── */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; }
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-s); padding: 8px 12px; }
.stat .n { font-size: 20px; font-weight: 700; } .stat .l { font-size: 11.5px; color: var(--muted); }
.logx { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-s); padding: 8px 10px; font-family: var(--mono); font-size: 11.5px; white-space: pre-wrap; word-break: break-all; max-height: 50vh; overflow: auto; }

/* ── 모달·토스트 ── */
.modal-bg { position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 50; display: flex; align-items: center; justify-content: center; padding: 16px; }
.modal { background: var(--surface); border: 1px solid var(--line); border-radius: 16px; width: 100%; max-width: 560px; max-height: 90svh; overflow: auto; box-shadow: var(--shadow); padding: 18px 20px; }
.modal h2 { margin: 0 0 12px; font-size: 16px; }
.modal .foot { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }
.modal label { display: block; font-size: 12.5px; color: var(--muted); margin: 10px 0 3px; }
.modal input[type=text], .modal select, .modal textarea { width: 100%; }
.toast { position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom)); transform: translateX(-50%); background: var(--ink); color: var(--bg); padding: 9px 16px; border-radius: 10px; font-size: 13px; z-index: 60; box-shadow: var(--shadow); max-width: 90vw; }
/* §37-1 · 오류 토스트 글자를 흰색 고정에서 바탕 토큰으로 바꿨다. 어두운 판의 오류색(#e08585)은 밝은 면이라
   흰 글자가 2.3:1 밖에 안 나왔다(밝은 판은 반대). 바탕색을 쓰면 두 판 모두 6:1 위로 올라간다. */
.toast.err { background: var(--danger); color: var(--bg); }

/* ── 새 버전 배너(기획 §3-1) ── */
/* 왜 위쪽 고정인가: 배포 뒤에도 열어 둔 화면이 옛 코드를 쓰고 있는 것을 사람이 알아채는 유일한 자리다. */
.verbar { position: fixed; top: 0; left: 0; right: 0; z-index: 70; display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: calc(7px + var(--sai-top, env(safe-area-inset-top))) 12px 7px; background: var(--accent); color: var(--accent-ink); font-size: 13px; font-weight: 600; box-shadow: var(--shadow); }
.verbar .btn { min-height: 28px; padding: 3px 10px; }
/* §37-1 · 흰색 고정을 강조면 글자 토큰으로. 어두운 판의 강조색(#7aa2f7)은 밝아서 흰 글자가 안 읽힌다. */
.verbar .btn.ghost { color: inherit; border-color: currentColor; background: transparent; }
.verbar .btn.x { min-width: 28px; padding: 3px 8px; }

/* ── 개발 판 띠(§42-B, 2026-09-13) ──────────────────────────────────────────
   왜 위쪽 고정 + 아래 내용을 그만큼 내리는가: 새 버전 배너(.verbar)는 fixed 로 머리를 **덮는다**(6b-5 미완 ③).
     그건 잠깐 뜨는 배너라 참았지만 이 띠는 **늘 떠 있다** — 덮으면 머리줄을 영구히 못 쓴다.
     그래서 띠 높이(--devbar-h)만큼 .app 을 내리고 .shell 의 100svh 에서 같은 값을 뺀다(문서 스크롤이 생기지 않게).
   ★ 높이는 --devbar-h **한 값**이다. 띠 두께를 바꾸려면 아래 첫 줄만 고친다.
   ★ html.devmode .app 에서 --sai-top 을 0 으로 덮는 이유: 위쪽 안전영역 인셋을 **띠가 대신 먹는다**.
     안 덮으면 머리줄이 인셋을 한 번 더 밀어 폰에서 빈 띠가 두 겹으로 생긴다.
     ★ 이 블록은 `var(--sai-top, env(safe-area-inset-top))` 꼴을 **새로 쓰지 않는다** — 8-18-1 단위 시험이
       그 낱말이 style.css 에 몇 번 나오는지(여섯) 세어 회귀를 막기 때문이다. 띠 자신은 env() 를 직접 읽는다
       (dev 전용 장식이라 25% 상한 밖에 둔 것이고, 부풀어도 띠와 본문이 같은 값으로 함께 움직인다).
   ★ 운영(claude.aisend.co.kr)에서는 이 블록의 어느 줄도 걸리지 않는다 — html.devmode 가 붙지 않는다. */
html.devmode { --devbar-h: 24px; }
.devbar { position: fixed; top: 0; left: 0; right: 0; z-index: 71; overflow: hidden;
  display: flex; align-items: center; justify-content: center; gap: 10px; white-space: nowrap;
  height: calc(var(--devbar-h) + env(safe-area-inset-top)); padding: env(safe-area-inset-top) 12px 0;
  background: var(--danger); color: var(--bg); font-size: 12.5px; font-weight: 600; }
.devbar .b { letter-spacing: .04em; border: 1px solid currentColor; border-radius: 5px; padding: 0 5px; }
.devbar .go { color: inherit; text-decoration: underline; }
html.devmode .app { --sai-top: 0px; padding-top: calc(var(--devbar-h) + env(safe-area-inset-top)); }
html.devmode .shell { grid-template-rows: calc(100svh - var(--devbar-h) - env(safe-area-inset-top));
  height: calc(100svh - var(--devbar-h) - env(safe-area-inset-top)); }
html.devmode .login-wrap { min-height: calc(100svh - var(--devbar-h) - env(safe-area-inset-top)); }
/* 새 버전 배너는 띠 아래로 내린다 — 둘이 같은 top:0 에서 겹치면 뒤엣것이 통째로 가려진다. */
html.devmode .verbar { top: calc(var(--devbar-h) + env(safe-area-inset-top)); }
/* 좁은 폭(폴드8 커버·세로)에서는 긴 문구를 접고 `개발 판` 딱지와 링크만 남긴다(띠가 두 줄로 늘지 않게). */
@media (max-width: 600px) { .devbar span:not(.b) { display: none; } }

/* ── 하단 탭·서랍(모바일) ── */
.tabbar { display: none; }
.drawer-bg { display: none; }

@media (max-width: 1099px) {
  .shell, .shell.with-panel { grid-template-columns: 250px 1fr; }
  .panel { position: fixed; top: 0; right: 0; bottom: 0; width: min(360px, 92vw); z-index: 40; transform: translateX(100%); transition: transform .2s; box-shadow: var(--shadow); }
  .panel.open { transform: none; }
  .mobile-only { display: inline-flex; }
}
@media (max-width: 759px) {
  .shell, .shell.with-panel { grid-template-columns: 1fr; grid-template-rows: 1fr auto; }
  .sidebar { position: fixed; top: 0; left: 0; bottom: 0; width: min(300px, 85vw); z-index: 45; transform: translateX(-100%); transition: transform .2s; box-shadow: var(--shadow); }
  .sidebar.open { transform: none; }
  .drawer-bg { display: block; position: fixed; inset: 0; background: rgba(0,0,0,.35); z-index: 44; }
  .drawer-bg[hidden] { display: none; }
  .content { padding: 10px 12px 20px; }
  .tabbar { display: flex; border-top: 1px solid var(--line); background: var(--bg-2); padding: 4px 4px calc(4px + env(safe-area-inset-bottom)); }
  .tabbar button { flex: 1; border: 0; background: transparent; padding: 6px 2px; font-size: 11px; color: var(--muted); display: flex; flex-direction: column; align-items: center; gap: 2px; border-radius: 8px; }
  .tabbar button .ico { font-size: 16px; }
  .tabbar button.on { color: var(--accent); background: var(--surface); }
  .two { grid-template-columns: 1fr; }
  .files-grid { grid-template-columns: 1fr; }
  .composer .bar select { max-width: 96px; }
}

/* 왜: 그리드 안 카드가 긴 해시·URL 때문에 min-content 폭으로 커져 화면 밖으로 잘리던 문제(2026-09-06 기기 탭). 카드는 줄어들 수 있게, 긴 문자열은 아무 데서나 줄바꿈. */
.card, .dev-cards > *, .kv dd { min-width: 0; }
.mono, .kv dd, .card .small { overflow-wrap: anywhere; word-break: break-word; }
.dev-cards { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }

/* 왜: 좁은 폭(폴드 접힘)에서 하단 탭 글자가 두 줄로 넘치던 문제. 한 줄 고정·말줄임, 버튼 최소폭 0. */
@media (max-width: 900px) { .tabbar button { min-width: 0; white-space: nowrap; overflow: hidden; } .tabbar button span:last-child { max-width: 100%; overflow: hidden; text-overflow: ellipsis; } }

/* ── 좁은 폭(폴드8 앞면 커버 세로 ≈ 360px) — 6b-8 ──────────────────────────
   6b-5 의 '낮은 화면' 조건(세로 600px 이하·가로 모드)과는 별개다. 커버 세로는 높이가 아니라 폭이 문제였다.
   ① 넘칠 수 있는 상자를 전부 min-width:0 으로 눌러 그리드·플렉스 자식이 내용 폭으로 부풀지 않게 하고
   ② 여백·글자를 한 단계 줄여 같은 카드가 한 화면에 들어오게 한다. 표·코드 블록만 자기 상자 안에서 가로 스크롤.
   조건을 420px 로 잡은 이유: 커버(≈360)와 접힌 상태의 일반 폰(≈390～412)까지 함께 걸린다. */
@media (max-width: 420px) {
  body { font-size: 13.5px; }
  .content { padding: 8px 10px 18px; }
  .card { padding: 10px 11px; }
  .card h3 { font-size: 13.5px; }
  /* 넘침의 뿌리 — 플렉스·그리드 자식은 기본 min-width:auto 라 내용이 길면 부모를 밀어낸다. */
  .card, .row, .row > *, .list li, .kv dd, .set-row, .set-row .lab, .tri-row, .dev-cards > *, .stat, .datelist, .two > * { min-width: 0; }
  .row { flex-wrap: wrap; }
  .list li, .set-row .lab, .tri-row, .bizrow { overflow-wrap: anywhere; word-break: break-word; }
  /* 검수 큐 카드 미리보기는 em 고정폭 대신 카드 폭을 따른다. */
  .tri-prev { max-width: 100%; }
  .chip { padding: 1px 6px; font-size: 11px; }
  .tbl th, .tbl td { padding: 5px 5px; }
  .stat-grid { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 6px; }
  .md h1 { font-size: 16.5px; } .md h2 { font-size: 15px; } .md h3 { font-size: 14px; }
  .md ul, .md ol { padding-left: 18px; }
  .two { gap: 10px; }
  .modal-bg { padding: 8px; }
  .modal { padding: 13px 14px; border-radius: 12px; }
  /* 6b-9 · 좁은 폭(폴드 앞면·접힌 폰)에서는 머리줄이 두 줄이 된다. 버튼 줄은 아래 왼쪽에 붙인다. */
  .brf-head { padding: 6px 8px; }
  .brf-head .act { margin-left: 0; }
  .brf-head .ttl { font-size: 13.5px; }
}

/* 왜: compact=1(앱 분할 화면·팝업·버블) — 대화와 입력창만. */
.shell.compact { grid-template-columns: 1fr; }
.shell.compact .sidebar, .shell.compact .tabbar, .shell.compact .panel, .shell.compact .topbar .sub, .shell.compact .drawer-bg { display: none !important; }
.shell.compact .topbar { padding: 4px 8px; min-height: 0; flex-wrap: nowrap; }
/* 6b-11 · 분할 화면·버블은 세로가 더 귀하다. 두 줄로 늘리지 않고 버튼 줄만 가로로 굴린다. */
.shell.compact .topbar .acts { flex: 0 1 auto; width: auto; overflow-x: auto; }
.shell.compact .content { padding: 6px 8px; }
.shell.compact .composer .inner { padding: 6px 8px; }

/* ── 낮은 화면(폴드8 커버 가로 등) — 6b-5 ────────────────────────────────
   왜: 커버 화면 가로에서 머리 3줄(제목·칩·설명) + 입력창 묶음(입력 2줄·도구줄·상태문구·보내기) + 큰 하단 탭바가
       세로를 거의 다 먹어 대화 본문이 2줄만 남았다(재희님 2026-09-08 23:07 스크린샷).
   조건 둘: 세로 600px 이하 · 가로 모드이면서 폭 1100px 이하. 데스크톱 창은 세로가 더 높아 걸리지 않고,
       세로로 돌리면(폴드 펼침·폰 세로) 두 조건 모두 벗어나 원래 레이아웃으로 돌아온다.
   ★ app.js 의 LOWH_MQ 가 이 조건 문자열을 그대로 복사해 쓴다 — 한쪽만 고치면 머리 ⋯ 와 CSS 가 어긋난다. */
.lowh-only { display: none; }
.composer .tools { display: contents; }   /* 넓은 화면: 묶음이 없는 것처럼 도구가 .bar 에 그대로 늘어선다 */

@media (max-height: 600px), (orientation: landscape) and (max-width: 1100px) {
  /* 1. 머리 한 줄 — 칩·설명 줄은 app.js 가 아예 그리지 않고(⋯ 안으로 옮김) 높이만 여기서 조인다.
     ★ 6b-12 · 상한에 반드시 안전영역 인셋을 더한다(재희님 2026-09-09 17:17 가로 캡처의 원인).
       box-sizing:border-box 라 max-height 안에 padding-top(3px + 위쪽 인셋)이 들어간다.
       ★ 8-18-1 · 인셋은 --sai-top(실측 + 25% 상한)으로 읽는다. 파일 위 '안전영역 위쪽 인셋' 절 참조.
       가로·edge-to-edge(viewport-fit=cover)에서 상태바 인셋이 40~50px 이므로 옛 44px 상한은 안쪽 높이를 0 으로 만들었고,
       제목 줄이 상자 밖(본문 위)으로 흘러 스크롤한 카드에 위 절반이 덮였다.
       이제 안쪽 높이는 어느 인셋에서도 --head-h(44px) 로 지켜진다.
     ★ flex-wrap:nowrap — 위 TWOROW(≤600px) 블록과 동시에 걸리는 가로 폰에서 ①이 이기게 명시적으로 되돌린다. */
  .topbar { min-height: 0; max-height: calc(var(--head-h) + var(--sai-top, env(safe-area-inset-top))); gap: 6px;
    padding: calc(3px + var(--sai-top, env(safe-area-inset-top))) 10px 3px; flex-wrap: nowrap; }
  .topbar > .grow { min-width: 0; }
  /* 새 버전 배너는 fixed 라 낮은 화면에서는 머리를 통째로 가린다 — 높이만이라도 줄인다(완전한 자리 확보는 미완 ③). */
  .verbar { padding: calc(3px + var(--sai-top, env(safe-area-inset-top))) 10px 3px; font-size: 12px; }
  .topbar .title { font-size: 14px; }
  .topbar .sub { display: none; }
  /* 2. 입력칸 한 줄(포커스하면 두 줄). 도구줄은 ⚙ 로 접고, 상태문구는 점 하나로 줄인다. */
  .content { padding: 8px 10px 10px; }
  .main > .content { min-height: 55svh; }   /* 본문이 남은 높이를 다 갖되 뷰포트의 55% 아래로는 안 내려간다 */
  .composer { padding: 4px 8px calc(4px + env(safe-area-inset-bottom)); }
  .composer .inner { padding: 4px 6px; border-radius: 10px; }
  .composer textarea { min-height: 24px; max-height: 26px; padding: 2px 4px; }
  .composer .inner:focus-within textarea { max-height: 54px; }
  .composer .bar { margin-top: 0; flex-wrap: wrap; }
  .composer .lowh-only { display: inline-flex; }
  .composer .tools { display: none; }
  .composer .inner.tools-open .tools { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; flex-basis: 100%; margin-top: 4px; }
  .composer .send { margin-left: auto; }
  /* 35-C · 낮은 화면(폴드 커버 가로·폰 가로)은 본문이 두세 줄뿐이라 서랍이 펼쳐질 자리가 없다.
     띠 한 줄만 남기고 손잡이는 숨긴다 — [외 N개]를 누르면 app.js fdNarrow() 가 [파일] 패널로 갈음한다.
     ★ 조건 문자열은 이 블록(= MQS.low)과 max-width:420px(= MQS.narrow) 두 개뿐이고 app.js 가 같은 둘을 본다. */
  .fdrawer { display: none; }
  .fdock { margin-bottom: 3px; }
  .fbar { font-size: 12px; padding: 2px 5px 2px 7px; }
  .fbar .btn { min-height: 24px; }
  /* 3. 하단 탭바 — 아이콘만, 본문을 내리면 감춘다(.hid 는 app.js bindTabbarAutoHide 가 붙인다). */
  /* 6b-12 · 머리줄과 같은 병(상한에 안전영역이 안 들어가 아이콘 아래가 잘린다). 여기도 인셋을 더해 준다. */
  .tabbar { max-height: calc(40px + env(safe-area-inset-bottom)); padding: 2px 4px calc(2px + env(safe-area-inset-bottom)); overflow: hidden; transition: max-height .15s ease, padding .15s ease; }
  .tabbar button { font-size: 0; gap: 0; padding: 4px 2px; }
  .tabbar button .ico { font-size: 17px; }
  .tabbar.hid { max-height: 0; padding-top: 0; padding-bottom: 0; border-top-width: 0; }
}

/* 운영 절 제목(상태 탭 안). 왜: 헬스·오류·알림과 운영(P11) 카드를 시각적으로 갈라 놓는다. */
.sec-title { margin: 20px 0 8px; padding-top: 14px; border-top: 1px solid var(--line); font-size: 15px; color: var(--ink-2); }

/* ── 28-B 휴대폰 받은함 ────────────────────────────────────────────────
   ① 사이드바 트리: 종(문자·통화·메세지) 아래 연락처 줄이 한 단 더 들어간다.
   ② 대화 화면: 수신 좌·발신 우 말풍선. 폭은 카드 안에서만 자라고(6b-8 규칙) 긴 낱말은 끊어 접는다.
   ③ 선택 바: 화면 아래에 떠서 발췌 보내기로 이어진다(입력창이 없는 탭이라 자리가 비어 있다). */
.nav.sub .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }
.nav.sub.kindhead .caret { width: 12px; flex: none; font-size: 10px; }
.side-kind { display: flex; flex-direction: column; }
.nav.sub2 { padding-left: 40px; font-size: 12.5px; }
.nav.sub2 .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }

/* ── 44-A · 2.0 PC 3단 배치(≥1280px) ──────────────────────────────────────
   기획 정본 `기획_클로드비서_2.0_v0.1.html` PC 3단·W 절 · 근거 §43·§43-1·§43-2.
   ★ 1279px 이하에서는 이 절의 어느 줄도 걸리지 않는다 — 폰·태블릿 배치(6b-12 네 뷰포트)는 한 줄도 바뀌지 않는다.
     `html.topnav3` 는 app.js render() 가 `wide3()`(= MQS.wide3, 아래 @media 와 같은 문자열)일 때만 붙인다.
     클래스와 요소는 반드시 함께 켜고 끈다 — 클래스만 남으면 .shell 이 48px 짧은 채로 굳는다.
   ★ 높이는 --topnav-h **한 값**이다. 내비 두께를 바꾸려면 아래 첫 줄만 고친다(devbar 와 같은 방식).
   ★ 위쪽 안전영역: 이 폭은 PC 창이라 인셋이 0 이다. 내비는 인셋을 읽지 않고, 대신 그 아래 .topbar 의
     --sai-top 을 0 으로 눌러 둔다(안 누르면 노치 있는 큰 화면에서 빈 띠가 두 겹으로 생긴다).
     ※ 여기에 `var(--sai-top, env(safe-area-inset-top))` 꼴을 **새로 쓰지 않는다** — 8-18-1 단위 시험이
       그 낱말이 style.css 에 몇 번 나오는지(여섯) 세어 회귀를 막는다. */
html.topnav3 { --topnav-h: 48px; }
.topnav { display: flex; align-items: center; gap: 10px; height: var(--topnav-h, 48px); padding: 0 14px;
  border-bottom: 1px solid var(--line); background: var(--bg-2); }
html.topnav3 .shell { grid-template-rows: calc(100svh - var(--topnav-h)); height: calc(100svh - var(--topnav-h)); }
/* 개발 판 띠와 겹칠 때 — 띠 높이·인셋은 .app 의 padding-top 이 이미 먹었고 여기서 같은 값을 한 번 더 뺀다. */
html.topnav3.devmode .shell { grid-template-rows: calc(100svh - var(--topnav-h) - var(--devbar-h) - env(safe-area-inset-top));
  height: calc(100svh - var(--topnav-h) - var(--devbar-h) - env(safe-area-inset-top)); }
html.topnav3 .topbar { --sai-top: 0px; }
.topnav .side-home { flex: none; }
.topnav .tn-here { display: flex; align-items: center; gap: 6px; min-width: 0; max-width: 320px; }
.topnav .tn-name { font-size: 13.5px; font-weight: 600; color: var(--ink-2); min-width: 0; }
/* 진행 점 자리(44-C). 지금은 빈 상자지만 폭을 잡아 둔다 — 44-C 가 점을 채울 때 머리가 밀리지 않게. */
.topnav .tn-dots { flex: none; width: 34px; height: 8px; }
.topnav .tn-lims { display: flex; align-items: center; gap: 10px; flex: none; border: 0; background: transparent; padding: 2px 6px; border-radius: var(--radius-s); }
.topnav .tn-lims:hover { background: var(--surface); }
.topnav .tn-lim { display: flex; align-items: center; gap: 5px; }
.topnav .tn-lim .lim-bar { width: 64px; height: 5px; }
.topnav .tn-lab, .topnav .tn-pct { font-size: 11px; color: var(--muted); white-space: nowrap; }
.topnav .tn-pct { font-family: var(--mono); }
.topnav .tn-pct.warn { color: var(--warn); }
.topnav .tn-pct.danger { color: var(--danger); }
.topnav .tn-q { flex: none; width: 220px; font-size: 12.5px; padding: 4px 8px; }

@media (min-width: 1280px) {
  /* 오른쪽 패널 상설 300px(지시서 44-A 2). 접기 없음 — .panel 의 ✕ 는 .mobile-only 라 이 폭에서 애초에 안 뜬다. */
  .shell.with-panel { grid-template-columns: 250px 1fr 300px; }
  /* 파일 서랍이 패널 둘째 칸으로 올라갔으므로 입력창 오른쪽 아래 손잡이는 이 폭에서만 숨긴다(<1280 은 종전 그대로).
     띠(.fbar)는 그대로 둔다 — 방금 만든 파일 한 줄은 입력창 바로 위가 제자리다(§8-21). */
  .shell.with-panel .composer .fdrawer { display: none; }
}
/* 패널 두 층 — [세 칸 받침대(고정)] + [본문(스크롤)]. 받침대가 없는 폭에서는 .panel 이 종전처럼 통째로 구른다. */
.panel.has-dock { display: flex; flex-direction: column; gap: 10px; overflow: hidden; }
.panel.has-dock .panel-body { flex: 1; min-height: 0; overflow-y: auto; }
.pdock { flex: none; display: flex; flex-direction: column; gap: 8px; }
.pdock-sec { border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--surface); overflow: hidden; }
.pdock-sec > h4 { margin: 0; padding: 5px 9px; border-bottom: 1px solid var(--line); background: var(--bg-2);
  font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
.pdock-sec .pd-body { padding: 7px 9px; max-height: 30svh; overflow-y: auto; overscroll-behavior: contain; }
/* 패널 안 파일 서랍 — 같은 fileDrawer() 를 띄우지 않고 제자리에 눕힌다(그림자·고정폭·절대위치를 끈다). */
.fdrawer.in-panel { position: static; align-self: stretch; }
.fdrawer.in-panel .fd-pop { position: static; width: auto; max-width: none; border: 0; box-shadow: none; background: transparent; padding: 0; }
.fdrawer.in-panel .fd-listwrap { max-height: none; }

.chat { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.msg { max-width: 84%; min-width: 0; padding: 7px 9px; border-radius: 12px; background: var(--surface-2); border: 1px solid var(--line); }
.msg.in { align-self: flex-start; border-bottom-left-radius: 4px; }
.msg.out { align-self: flex-end; border-bottom-right-radius: 4px; background: var(--accent-soft); }
.msg.pick { outline: 2px solid var(--accent); outline-offset: 1px; }
.msg-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }
.msg-body { margin-top: 3px; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; line-height: 1.45; }
.msg-acts { margin-top: 5px; gap: 4px; }
/* §28-6 · 받은함 카드 안 첨부 줄. 이름만 보이던 자리에 썸네일·종류·크기를 넣는다. */
.msg-atts { margin-top: 5px; gap: 6px; align-items: flex-start; }
.attthumb { display: flex; flex-direction: column; align-items: center; gap: 2px; max-width: 132px; padding: 4px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); cursor: pointer; }
.attthumb img { display: block; width: 120px; height: 90px; object-fit: cover; border-radius: 6px; background: var(--surface-2); }
.attthumb .small { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attlock { display: flex; align-items: center; justify-content: center; width: 120px; height: 90px; border-radius: 6px; background: var(--surface-2); font-size: 22px; }

/* §37-3 · 그림자 한 겹 규칙에 맞춰 두 겹짜리 고정값을 --shadow 로 통일했다(떠 있는 막대라 그림자 자체는 남긴다). */
.selbar { position: sticky; bottom: 8px; z-index: 30; display: flex; align-items: center; gap: 8px; margin-top: 10px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); box-shadow: var(--shadow); }
.selbar[hidden] { display: none; }

/* 좁은 폭(6b-8 규칙과 같은 조건) — 말풍선이 카드를 넘지 않게 하고 버튼 줄은 접는다. */
@media (max-width: 420px) {
  .msg { max-width: 100%; }
  .selbar { flex-wrap: wrap; border-radius: 12px; }
  .nav.sub2 { padding-left: 32px; }
}

/* ── 40 홈 대시보드(#/home) ─────────────────────────────────────────────
   폰은 한 줄에 카드 하나, 760px 이상이면 2열(§40 ③). 카드 껍데기·칩·막대는 다른 탭과 같은 부품을 쓴다. */
.home-head { margin-bottom: 10px; }
.home-head h2 { margin: 0; font-size: 17px; letter-spacing: -.02em; }
.home-grid { display: grid; grid-template-columns: 1fr; gap: 12px; align-items: start; }
@media (min-width: 760px) { .home-grid { grid-template-columns: 1fr 1fr; } }
.home-card { margin: 0; }
.home-card .home-ul { margin: 6px 0 0; padding-left: 17px; font-size: 13px; }
.home-card .home-ul li { margin: 3px 0; }
.home-card .home-ul.plain { list-style: none; padding-left: 0; }
/* 파일 한 줄 — 누르면 §8-19-1 뷰어. 이름은 길면 말줄임, 시각은 오른쪽 끝. */
.home-file { display: flex; align-items: center; gap: 6px; width: 100%; padding: 2px 0; border: 0; background: none; color: var(--ink); font-size: 13px; text-align: left; }
.home-file .nm { flex: 1; min-width: 0; }
.home-file:hover .nm { color: var(--accent); text-decoration: underline; }
