/* ═══════════════════════════════════════════════════════════════
   patches-extracted.css
   patches.js / org-views.js / wbs-modal.js에서 추출한 정적 CSS
   (CSS-in-JS → 외부 CSS 전환 — style-src unsafe-inline 축소)
   ═══════════════════════════════════════════════════════════════ */

/* ── 0. 로그인 애니메이션 (index.html <style> 태그에서 추출) ── */
@keyframes loginFadeIn { from { opacity:0; transform:translateY(20px); } to { opacity:1; transform:translateY(0); } }
@keyframes loginFloat { 0%,100% { transform:translateY(0); } 50% { transform:translateY(-8px); } }
.login-card { animation: loginFadeIn 0.6s ease-out; }
.login-logo { animation: loginFloat 3s ease-in-out infinite; }
.login-bg-dot { position:absolute; border-radius:50%; background:rgba(59,130,246,.08); }

/* ── 1. workspaceHubPolishStyle — 2026-09-29 삭제: 허브 카드·디버그 칸은 마크업이 없었다(docs/modules/removed.md) ── */

/* ── 3·4. opsConsistencyV2710Style · removeCurrentProjectQuickbarsStyle — 2026-09-30 삭제: 대시보드 운영 막대를 만들던 코드(patch-dashboard.js)와 함께 뺐다(docs/modules/removed.md) ── */

/* ── 5. workspaceRebuildV4SafeStyle (patches.js project selectors hide) ── */
#projectSelect,#mobProjectSelect,#btnRenameWs{display:none !important;}

/* ── 6. workspaceBoardFlowV8Style (patches.js board mode) ── */
body.workspace-board-mode-v8 #ctxnav-dashboard, body.workspace-board-mode-v8 #ctxnav-wbs, body.workspace-board-mode-v8 #ctxnav-issues, body.workspace-board-mode-v8 #ctxnav-runningorder, body.workspace-board-mode-v8 #ctxnav-dailylog, body.workspace-board-mode-v8 #ctxnav-estimate, body.workspace-board-mode-v8 #ctxnav-quote, body.workspace-board-mode-v8 #ctxnav-expense, body.workspace-board-mode-v8 #ctxnav-finance, body.workspace-board-mode-v8 #ctxnav-portal, body.workspace-board-mode-v8 #ctxnav-extcrew { display:none !important; }

/* ── 7. workspaceSidebarSafeV27Style (patches.js detail mode) ── */
body.workspace-detail-mode-v27 #ctx-project{display:block !important;}
body.workspace-detail-mode-v27 #ctx-project.hidden{display:block !important;}
body.workspace-detail-mode-v27 #ctx-project .ctx-section-header{display:block !important;}
body.workspace-detail-mode-v27 #ctx-project .ctx-divider{display:block !important;}
body.workspace-detail-mode-v27 #ctxnav-dashboard:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-wbs:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-issues:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-runningorder:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-dailylog:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-estimate:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-quote:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-expense:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-finance:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-portal:not(.nav-role-hidden),
body.workspace-detail-mode-v27 #ctxnav-extcrew:not(.nav-role-hidden){display:flex !important;}
body #contextPanel .ctx-nav-item.nav-role-hidden { display:none !important; }

/* ── 8. projectContextStripStyle (patches.js project context strip) ── */
#projectContextStrip{display:none;margin:-2px 0 14px 0;padding:12px 14px;border:1px solid #dbeafe;background:linear-gradient(180deg,#f8fbff 0%,#eef6ff 100%);border-radius:var(--radius-lg);box-shadow:0 4px 14px rgba(15,23,42,.05)}
#projectContextStrip.pcs-show{display:block}
#projectContextStrip .pcs-row{display:flex;gap:12px;align-items:flex-start;justify-content:space-between;flex-wrap:wrap}
#projectContextStrip .pcs-title{font-size:16px;font-weight:900;color:#0f172a;line-height:1.2}
#projectContextStrip .pcs-meta{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
#projectContextStrip .pcs-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:999px;background:#fff;border:1px solid #dbeafe;font-size:11px;font-weight:800;color:#334155}
#projectContextStrip .pcs-chip.pcs-status{background:#eff6ff;color:#1d4ed8;border-color:#bfdbfe}
#projectContextStrip .pcs-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
#projectContextStrip .pcs-btn{appearance:none;border:1px solid #cbd5e1;background:#fff;color:#0f172a;padding:8px 12px;border-radius:12px;font-size:12px;font-weight:900;cursor:pointer}
#projectContextStrip .pcs-btn:hover{border-color:#60a5fa;color:#1d4ed8;background:#eff6ff}
@media (max-width: 768px){
  #projectContextStrip{padding:10px 12px;border-radius:16px}
  #projectContextStrip .pcs-title{font-size:14px}
  #projectContextStrip .pcs-chip{font-size:10px;padding:5px 8px}
}

/* ── 9. 저장 칩 (patch-ui-cleanup-detail.js — 상단바 #saveStatusText 를 따라간다 · v47 칩은 2026-10-07 삭제) ── */
#projectContextStrip .pcs-chip.pcs-save{background:#f8fafc;border-color:#cbd5e1;color:#475569}
#projectContextStrip .pcs-chip.pcs-save-pending{background:#fffbeb;border-color:#fcd34d;color:#b45309}
#projectContextStrip .pcs-chip.pcs-save-bad{background:#fef2f2;border-color:#fca5a5;color:#b91c1c}

/* ── 10. wbsPanelCSS (wbs-modal.js + org-views.js slide panel)
 *  2026-04-27: right-slide-panel 디자인 언어와 정렬 — 폭/위치/dim 통일 */
/* dim overlay: 데스크탑 무, 모바일만 (≤767px) */
.wbs-panel-overlay{position:fixed;inset:60px 0 0 0;z-index:997;background:rgba(0,0,0,0);transition:background .25s ease;pointer-events:none}
@media (max-width:767px){
  .wbs-panel-overlay.open{background:rgba(15,23,42,0.22);pointer-events:auto}
}
/* 패널: top 60 (앱 토프바 아래), 폭은 right-slide-panel 과 동일 공식 */
.wbs-panel{position:fixed;top:60px;right:0;bottom:0;z-index:998;
  width:min(92vw,50vw + 80px);max-width:720px;min-width:320px;
  background:#ffffff;box-shadow:-8px 0 32px rgba(15,23,42,.10);border-left:1px solid #e2e8f0;
  transform:translateX(100%);transition:transform .28s cubic-bezier(.4,0,.2,1);
  overflow-y:auto;-webkit-overflow-scrolling:touch}
@media (min-width:768px){
  .wbs-panel{width:58vw;max-width:760px;min-width:480px}
}
.wbs-panel.open{transform:translateX(0) !important}
/* 🪟 업체 정보 모달 (org-client-panel.js, 2026-10-14 사장님 «모달이 나은가» → 업체 정보만 모달) — PC 2열, 폰 전체 화면 */
.cl-modal-overlay{position:fixed;inset:0;z-index:997;background:rgba(15,23,42,0);transition:background .2s ease}
.cl-modal-overlay.open{background:rgba(15,23,42,.38)}
.cl-modal{position:fixed;z-index:998;left:50%;top:calc(var(--os-viewport-top,0px) + var(--os-viewport-height,100dvh)/2);transform:translate(-50%,-48%);opacity:0;transition:opacity .2s ease,transform .2s ease;
  width:min(1040px,calc(100vw - 48px));max-height:calc(var(--os-viewport-height,100dvh) - 32px);display:flex;flex-direction:column;
  background:#fff;border-radius:16px;box-shadow:0 24px 64px rgba(15,23,42,.22);overflow:hidden}
.cl-modal.open{opacity:1;transform:translate(-50%,-50%)}
.cl-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:20px 24px;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:8px 24px;align-items:start}
.cl-modal-top{grid-column:1 / -1;display:flex;flex-direction:column;gap:12px}
.cl-modal-col{display:flex;flex-direction:column;gap:12px;min-width:0}
.cl-modal-foot{flex-shrink:0;display:flex;justify-content:flex-end;gap:8px;padding:12px 24px;border-top:1px solid #e2e8f0;background:#fff}
@media (max-width:767px){
  .cl-modal{left:0;top:var(--os-viewport-top,0px);width:100%;max-height:none;height:var(--os-viewport-height,100dvh);border-radius:0;transform:translateY(12px)}
  .cl-modal.open{transform:none}
  .cl-modal-body{grid-template-columns:minmax(0,1fr);padding:16px}
  .cl-modal-foot{padding:12px 16px calc(12px + env(safe-area-inset-bottom))}
  .cl-modal input:not([type=checkbox]):not([type=file]),.cl-modal textarea,.cl-modal select{font-size:16px !important}   /* 16px 미만이면 아이폰이 확대하고 안 돌아온다 */
}
/* 🧭 2026-10-14 사장님 «사이드패널 레이아웃이 오류 같다» — 상세 패널이 열리면
 *  ① 넓은 화면(≥1440)에선 본문이 패널 폭(최대 760)만큼 비켜 선다 — 가운데 놓인 목록이 패널에 반쯤 잘려 보이던 것.
 *     좁은 화면은 비키면 본문이 너무 좁아져 종전대로 위에 뜬다.
 *  ② 오른쪽 끝 «◀» 손잡이(#rightPanelHandle)를 숨긴다 — 패널 옆에 검은 띠처럼 붙어 보였다.
 *  ⓘ :has() 라 패널을 여는 곳(업체·WBS·크루 …)을 하나도 안 고친다. 패널을 닫으면(.open 해제) 저절로 돌아온다. */
@media (min-width:1440px){
  body:has(.wbs-panel.open) #mainContent{padding-right:760px}
}
body:has(.wbs-panel.open) #rightPanelHandle{display:none !important}

/* ── 11. CSP inline-style 제거 유틸리티 ── */

/* 모달 사이징 */
.os-modal-lg { width:560px; max-width:95vw; max-height:85vh; }
.os-modal-md { width:520px; max-width:95vw; max-height:85vh; }
.os-modal-sm { width:480px; max-width:95vw; max-height:85vh; }
.os-modal-xl { width:600px; max-width:95vw; max-height:85vh; }

/* 홈 섹션 아이콘 서클 — 각 색상별 */
.section-icon { border-radius:12px; width:42px; height:42px; display:flex; align-items:center; justify-content:center; font-size:20px; flex-shrink:0; }
.section-icon-amber { background:linear-gradient(135deg,#f59e0b,#d97706); box-shadow:0 4px 12px rgba(217,119,6,0.35); }
.section-icon-green { background:linear-gradient(135deg,#059669,#047857); box-shadow:0 4px 12px rgba(5,150,105,0.35); }
.section-icon-purple { background:linear-gradient(135deg,#7c3aed,#6d28d9); box-shadow:0 4px 12px rgba(124,58,237,0.35); }
.section-icon-sky { background:linear-gradient(135deg,#0284c7,#0369a1); box-shadow:0 4px 12px rgba(2,132,199,0.35); }
.section-icon-rose { background:linear-gradient(135deg,#be185d,#9d174d); box-shadow:0 4px 12px rgba(190,24,93,0.35); }
.section-icon-indigo { background:linear-gradient(135deg,#4338ca,#3730a3); box-shadow:0 4px 12px rgba(67,56,202,0.35); }
.section-icon-blue { background:linear-gradient(135deg,#2563eb,#1d4ed8); box-shadow:0 4px 12px rgba(37,99,235,0.35); }
.section-icon-teal { background:linear-gradient(135deg,#0f766e,#0d9488); box-shadow:0 4px 12px rgba(15,118,110,0.35); }

/* 그래디언트 헤더 */
.grad-header-dark { background:linear-gradient(135deg,#1e293b,#334155); }
.grad-header-blue { background:linear-gradient(135deg,#1e3a8a,#3b82f6); }
.grad-header-navy { background:linear-gradient(135deg,#0f172a,#1e3a5f); }
.grad-header-violet { background:linear-gradient(135deg,#7c3aed,#a78bfa); }

/* 커스텀 색상 피커 배경 */
.color-picker-conic { background:conic-gradient(from 0deg, #ef4444, #f59e0b, #eab308, #10b981, #06b6d4, #3b82f6, #8b5cf6, #ec4899, #ef4444); }

/* patchLogModal overlay — display:none(hidden)과 충돌하므로 기본은 none, JS에서 열 때 grid 적용 */
.patch-log-overlay { display:none; place-content:center; align-items:safe center; justify-items:center; background:rgba(0,0,0,0.95); overflow:auto; }

/* 로그인 오버레이 */
.login-overlay-bg { background:linear-gradient(135deg,#0f172a 0%,#1e3a5f 40%,#1a365d 70%,#0f172a 100%); overflow-y:auto; overflow-x:hidden; align-items:flex-start; padding:24px 0; }
.login-overlay-bg > .login-card { width:calc(100% - 32px); margin-block:auto; flex-shrink:0; }
.login-overlay-bg input { font-size:16px; }

/* 포탈 헤더 */
.portal-header-bg { background:linear-gradient(135deg,#0f172a,#1e3a5f); }

/* 재무 clamp 폰트 */
.fin-card-amount { font-size:clamp(.85rem,2.5vw,1.3rem); }

/* cmdPalette 오버레이 */
.cmd-palette-overlay { background:rgba(15,23,42,0.6); backdrop-filter:blur(4px); }

/* 출근 모달 헤더 */
.mand-clock-header { background:linear-gradient(135deg,#1e293b,#334155); padding:32px 28px; text-align:center; color:white; }
.mand-clock-body { padding:24px 28px; }
.mand-clock-grid { display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-bottom:16px; }
.mand-clock-bypass { width:100%; padding:10px; border-radius:10px; border:1px solid #e2e8f0; background:#f8fafc; cursor:pointer; font-size:12px; font-weight:700; color:#64748b; }

/* 퇴근 모달 */
.eod-header { background:linear-gradient(135deg,#7c3aed,#a78bfa); padding:28px 24px; text-align:center; color:white; }
.eod-body { padding:20px 24px; display:flex; flex-direction:column; gap:12px; }
.eod-btn-primary { padding:14px; border-radius:12px; border:none; background:#10b981; color:white; cursor:pointer; font-size:15px; font-weight:800; }
.eod-btn-secondary { padding:14px; border-radius:12px; border:2px solid #7c3aed; background:white; color:#7c3aed; cursor:pointer; font-size:15px; font-weight:800; }

/* 프로젝트 컬러 닷 */
.proj-color-dot { width:14px; height:14px; border-radius:50%; background:#3B82F6; flex-shrink:0; cursor:pointer; border:2px solid rgba(0,0,0,0.1); }

/* TODO 배지 */
.todo-badge-style { background:#dc2626; color:white; min-width:18px; text-align:center; }

/* 프로젝트 목록 네비 */
.ctx-projlist-btn { color:#3b82f6; font-weight:700; margin-bottom:4px; }

/* 런닝오더 헤더 셀 패딩 */
.ro-hdr-cell { padding:8px 6px; }
.ro-hdr-time { color:#93c5fd; padding:8px 10px; }

/* 견적서 공급자 테이블 */
.quote-receiver-supplier > div { min-width:0; }
.quote-receiver-supplier :is(input, select, textarea) { min-width:0; max-width:100%; box-sizing:border-box; }
.quote-supplier-tbl { table-layout:fixed; width:100%; flex:1; }
.quote-th-vertical { writing-mode:vertical-rl; letter-spacing:6px; width:26px; border-bottom:1px solid #000; }
.quote-th-label { font-size:9px; }
.quote-input-sm { font-size:11px; }
.quote-input-xs { font-size:10px; }

/* 견적서 합계 행 */
.quote-grand-row { display:flex; align-items:baseline; gap:8px; flex-wrap:nowrap; overflow:hidden; }
.quote-grand-label { font-size:13px; font-weight:700; white-space:nowrap; flex-shrink:0; }
.quote-grand-word { font-weight:900; letter-spacing:0.5px; color:#1d4ed8; white-space:nowrap; font-size:12px; flex-shrink:1; overflow:hidden; text-overflow:ellipsis; }
.quote-grand-num { font-weight:900; margin-left:auto; white-space:nowrap; font-size:17px; flex-shrink:0; }

/* 직인/인감 이미지 */
.seal-img { width:65px; height:65px; object-fit:contain; opacity:0.85; mix-blend-mode:multiply; }
.seal-text-fallback { position:absolute; right:8px; top:8px; font-size:10px; color:#64748b; z-index:5; }

/* 설정 doc-table-wrap 오버라이드 */
.dtw-flat { overflow:visible; box-shadow:none; border-radius:0; }
.dtw-flat-scroll { overflow-x:auto; box-shadow:none; border-radius:0; }

/* 재무 원장 테이블 */
.ldg-table-income { min-width:800px; border-collapse:collapse; table-layout:fixed; }
.ldg-table-expense { min-width:930px; border-collapse:collapse; table-layout:fixed; }

/* 제안서 AI 뷰 */
.proposal-wrap { display:flex; flex-direction:column; height:calc(100vh - 60px); gap:8px; }
.proposal-toolbar { display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:4px 0; }
.proposal-badge { background:linear-gradient(135deg,#1a365d,#2b6cb0); color:#fff; padding:5px 12px; border-radius:8px; font-size:11px; font-weight:800; }
.proposal-btn-green { margin-left:auto; padding:5px 10px; background:#059669; border:none; border-radius:6px; font-size:10px; font-weight:700; color:white; cursor:pointer; }
.proposal-btn-purple { padding:5px 10px; background:#7c3aed; border:none; border-radius:6px; font-size:10px; font-weight:700; color:white; cursor:pointer; }
.proposal-btn-red { padding:5px 10px; background:#dc2626; border:none; border-radius:6px; font-size:10px; font-weight:700; color:white; cursor:pointer; }
.proposal-btn-ghost { padding:5px 10px; background:#f1f5f9; border:1px solid #e2e8f0; border-radius:6px; font-size:10px; font-weight:700; color:#475569; cursor:pointer; }
.proposal-frame { flex:1; border:1px solid #e2e8f0; border-radius:8px; background:#fff; min-height:0; }

/* 모바일 서브네비 */
.mobile-sub-nav-inner { display:flex; width:100%; justify-content:center; gap:4px; flex-wrap:wrap; }

/* TODO 토글 버튼 기본 상태 */
.todo-toggle-default { border-color:#cbd5e1; background:white; color:#64748b; }

/* 재무 profit 색상 */
.fin-profit-color { color:#7c3aed; }

/* 파이프라인 그리드 */
.pipeline-grid-7 { grid-template-columns:repeat(7,1fr); }

/* ──────────────────────────────────────────────────────────
   급여관리 모바일 반응형 테이블 (data-label 패턴, 640px 이하)
   데스크톱: 기존 테이블 그대로, 모바일: 각 행이 세로 카드로 변환
   2026-04-18 추가 (fin-payroll.js _renderFinPayroll)
   ──────────────────────────────────────────────────────────*/
@media (max-width: 640px) {
  .fin-payroll-table { min-width: 0 !important; font-size: 13px !important; }
  .fin-payroll-table thead { position: absolute; left: -9999px; top: -9999px; }
  .fin-payroll-table tbody, .fin-payroll-table tr, .fin-payroll-table td { display: block; width: 100%; box-sizing: border-box; }
  .fin-payroll-table tr { background: #ffffff !important; border: 1px solid #e2e8f0 !important; border-radius: 12px; margin-bottom: 12px; padding: 6px 2px; }
  .fin-payroll-table td { display: flex !important; justify-content: space-between !important; align-items: center !important; gap: 12px !important; padding: 8px 12px !important; border-bottom: 1px dashed #f1f5f9 !important; text-align: right !important; }
  .fin-payroll-table td:last-child { border-bottom: none !important; }
  .fin-payroll-table td::before { content: attr(data-label); font-weight: 700; color: #64748b; font-size: 11px; white-space: nowrap; flex-shrink: 0; }
  .fin-payroll-table td input, .fin-payroll-table td select { width: auto !important; min-width: 120px; max-width: 60%; }
  .fin-payroll-table td.fin-payroll-del { justify-content: flex-end !important; }
  .fin-payroll-table td.fin-payroll-del::before { content: ""; }
  .fin-payroll-wrap { border: none !important; background: transparent !important; overflow-x: visible !important; }
}

/*──────────────────────────────────────────────────────────
   모바일 데이터 테이블 → 카드 변환 (통합 스타일)
   2026-04-18 추가 — 재무/자금/근태/조직/리포트 전체 테이블
   data-label 속성 기반 ::before 라벨 표시
   ──────────────────────────────────────────────────────────*/
@media (max-width: 640px) {
  .fin-ec-table,
  .fin-trs-table,
  .fin-vendor-table,
  .fin-cashflow-table,
  .fin-vat-table,
  .fin-daily-table,
  .fin-card-table,
  .fin-budget-table,
  .fin-rep-pnl-table,
  .fin-rep-proj-table,
  .fin-rep-recv-table,
  .fin-overview-proj-table,
  .fin-quote-list-table,
  .fin-expenses-list-table,
  .fin-att-table,
  .fin-vendor-db-table,
  .fin-client-db-table,
  .fin-crew-table {
    min-width: 0 !important;
    font-size: 13px !important;
    display: block !important;
    width: 100% !important;
  }

  .fin-ec-table thead,
  .fin-trs-table thead,
  .fin-vendor-table thead,
  .fin-cashflow-table thead,
  .fin-vat-table thead,
  .fin-daily-table thead,
  .fin-card-table thead,
  .fin-budget-table thead,
  .fin-rep-pnl-table thead,
  .fin-rep-proj-table thead,
  .fin-rep-recv-table thead,
  .fin-overview-proj-table thead,
  .fin-quote-list-table thead,
  .fin-expenses-list-table thead,
  .fin-att-table thead,
  .fin-vendor-db-table thead,
  .fin-client-db-table thead,
  .fin-crew-table thead {
    position: absolute;
    left: -9999px;
    top: -9999px;
  }

  .fin-ec-table tbody, .fin-ec-table tr, .fin-ec-table td,
  .fin-trs-table tbody, .fin-trs-table tr, .fin-trs-table td,
  .fin-vendor-table tbody, .fin-vendor-table tr, .fin-vendor-table td,
  .fin-cashflow-table tbody, .fin-cashflow-table tr, .fin-cashflow-table td,
  .fin-vat-table tbody, .fin-vat-table tr, .fin-vat-table td,
  .fin-daily-table tbody, .fin-daily-table tr, .fin-daily-table td,
  .fin-card-table tbody, .fin-card-table tr, .fin-card-table td,
  .fin-budget-table tbody, .fin-budget-table tr, .fin-budget-table td,
  .fin-rep-pnl-table tbody, .fin-rep-pnl-table tr, .fin-rep-pnl-table td,
  .fin-rep-proj-table tbody, .fin-rep-proj-table tr, .fin-rep-proj-table td,
  .fin-rep-recv-table tbody, .fin-rep-recv-table tr, .fin-rep-recv-table td,
  .fin-overview-proj-table tbody, .fin-overview-proj-table tr, .fin-overview-proj-table td,
  .fin-quote-list-table tbody, .fin-quote-list-table tr, .fin-quote-list-table td,
  .fin-expenses-list-table tbody, .fin-expenses-list-table tr, .fin-expenses-list-table td,
  .fin-att-table tbody, .fin-att-table tr, .fin-att-table td,
  .fin-vendor-db-table tbody, .fin-vendor-db-table tr, .fin-vendor-db-table td,
  .fin-client-db-table tbody, .fin-client-db-table tr, .fin-client-db-table td,
  .fin-crew-table tbody, .fin-crew-table tr, .fin-crew-table td {
    display: block !important;
    width: 100% !important;
    box-sizing: border-box;
  }

  .fin-ec-table tr,
  .fin-trs-table tr,
  .fin-vendor-table tr,
  .fin-cashflow-table tr,
  .fin-vat-table tr,
  .fin-daily-table tr,
  .fin-card-table tr,
  .fin-budget-table tr,
  .fin-rep-pnl-table tr,
  .fin-rep-proj-table tr,
  .fin-rep-recv-table tr,
  .fin-overview-proj-table tr,
  .fin-quote-list-table tr,
  .fin-expenses-list-table tr,
  .fin-att-table tr,
  .fin-vendor-db-table tr,
  .fin-client-db-table tr,
  .fin-crew-table tr {
    background: #ffffff !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 12px;
    margin-bottom: 12px;
    padding: 6px 2px;
  }

  .fin-ec-table td,
  .fin-trs-table td,
  .fin-vendor-table td,
  .fin-cashflow-table td,
  .fin-vat-table td,
  .fin-daily-table td,
  .fin-card-table td,
  .fin-budget-table td,
  .fin-rep-pnl-table td,
  .fin-rep-proj-table td,
  .fin-rep-recv-table td,
  .fin-overview-proj-table td,
  .fin-quote-list-table td,
  .fin-expenses-list-table td,
  .fin-att-table td,
  .fin-vendor-db-table td,
  .fin-client-db-table td,
  .fin-crew-table td {
    display: flex !important;
    justify-content: space-between !important;
    align-items: center !important;
    gap: 12px !important;
    padding: 8px 12px !important;
    border-bottom: 1px dashed #f1f5f9 !important;
    text-align: right !important;
    min-height: 36px;
  }

  .fin-ec-table td:last-child,
  .fin-trs-table td:last-child,
  .fin-vendor-table td:last-child,
  .fin-cashflow-table td:last-child,
  .fin-vat-table td:last-child,
  .fin-daily-table td:last-child,
  .fin-card-table td:last-child,
  .fin-budget-table td:last-child,
  .fin-rep-pnl-table td:last-child,
  .fin-rep-proj-table td:last-child,
  .fin-rep-recv-table td:last-child,
  .fin-overview-proj-table td:last-child,
  .fin-quote-list-table td:last-child,
  .fin-expenses-list-table td:last-child,
  .fin-att-table td:last-child,
  .fin-vendor-db-table td:last-child,
  .fin-client-db-table td:last-child,
  .fin-crew-table td:last-child {
    border-bottom: none !important;
  }

  .fin-ec-table td::before,
  .fin-trs-table td::before,
  .fin-vendor-table td::before,
  .fin-cashflow-table td::before,
  .fin-vat-table td::before,
  .fin-daily-table td::before,
  .fin-card-table td::before,
  .fin-budget-table td::before,
  .fin-rep-pnl-table td::before,
  .fin-rep-proj-table td::before,
  .fin-rep-recv-table td::before,
  .fin-overview-proj-table td::before,
  .fin-quote-list-table td::before,
  .fin-expenses-list-table td::before,
  .fin-att-table td::before,
  .fin-vendor-db-table td::before,
  .fin-client-db-table td::before,
  .fin-crew-table td::before {
    content: attr(data-label);
    font-weight: 700;
    color: #64748b;
    font-size: 11px;
    white-space: nowrap;
    flex-shrink: 0;
    text-align: left;
  }

  /* 입력/선택자 폭 제한 (카드에서 우측 정렬) */
  .fin-ec-table td input,
  .fin-ec-table td select,
  .fin-trs-table td input,
  .fin-trs-table td select,
  .fin-vendor-db-table td input,
  .fin-vendor-db-table td select,
  .fin-client-db-table td input,
  .fin-client-db-table td select,
  .fin-crew-table td input,
  .fin-crew-table td select {
    width: auto !important;
    min-width: 120px;
    max-width: 60%;
    text-align: right;
  }

  /* 삭제/액션 셀: 라벨 숨김 + 우측 정렬 */
  .fin-ec-act,
  .fin-trs-del,
  .fin-att-act,
  .fin-vendor-del,
  .fin-crew-del,
  .fin-ec-check,
  .fin-trs-check {
    justify-content: flex-end !important;
  }

  .fin-ec-act::before,
  .fin-trs-del::before,
  .fin-att-act::before,
  .fin-vendor-del::before,
  .fin-crew-del::before,
  .fin-ec-check::before,
  .fin-trs-check::before {
    content: "" !important;
  }

  /* 긴 설명/사유 셀: 세로 스택 (라벨 위, 내용 아래) */
  .fin-ec-desc,
  .fin-trs-num {
    flex-direction: column !important;
    align-items: flex-start !important;
    text-align: left !important;
    gap: 4px !important;
  }

  .fin-ec-desc::before,
  .fin-trs-num::before {
    text-align: left;
  }

  /* 랩퍼 박스 (외부 테두리/스크롤 제거) */
  .fin-ec-wrap,
  .fin-trs-wrap,
  .fin-att-wrap,
  .fin-vendor-wrap,
  .fin-client-wrap,
  .fin-crew-wrap {
    border: none !important;
    background: transparent !important;
    overflow-x: visible !important;
    box-shadow: none !important;
  }

  /* ── 근태 모바일: 일자당 1줄 요약 (개별 셀 전부 숨김, att-mobile-row만 flex 한 줄) ──
     데스크톱은 inline display:none, 모바일에서만 아래 규칙이 !important 로 1줄 표시 */
  .fin-att-table td:not(.att-mobile-row) { display: none !important; }
  .fin-att-table tr { border-radius: 12px; margin-bottom: 6px !important; padding: 0 !important; overflow: hidden; }
  .fin-att-table td.att-mobile-row {
    display: flex !important;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 9px 12px !important;
    min-height: 0 !important;
    border-bottom: none !important;
    text-align: left !important;
  }
  .fin-att-table td.att-mobile-row::before { content: "" !important; }
  .att-mobile-row .amr-date { font-weight: 800; font-size: 12px; color: #0f172a; white-space: nowrap; flex-shrink: 0; min-width: 56px; }
  .att-mobile-row .amr-type { flex-shrink: 0; display: flex; align-items: center; }
  .att-mobile-row .amr-time { margin-left: auto; font-size: 11px; color: #475569; white-space: nowrap; font-variant-numeric: tabular-nums; }
  .att-mobile-row .amr-act { flex-shrink: 0; display: flex; align-items: center; gap: 2px; }
}

/*──────────────────────────────────────────────────────────
   비재무 영역 모바일 반응형 테이블 (홈/파이프라인/산출·지출/손익)
   2026-04-18 추가 — home-widgets, pipeline-views, treasury,
   est-exp-views, project-pnl, treasury-pnl, quote, dashboard-charts
   ──────────────────────────────────────────────────────────*/
@media (max-width: 640px) {
  .fin-home-proj-table,
  .fin-pipeline-quote-table,
  .fin-trs-recent-table,
  .fin-trs-vendor-table,
  .fin-est-list-table,
  .fin-exp-list-table,
  .fin-pnl-cat-table,
  .fin-pnl-inc-table,
  .fin-trs-pnl-month-table,
  .fin-trs-pnl-proj-table,
  .fin-dashboard-bva-table {
    min-width: 0 !important;
    font-size: 13px !important;
    display: block !important;
    width: 100% !important;
  }

  .fin-home-proj-table thead,
  .fin-pipeline-quote-table thead,
  .fin-trs-recent-table thead,
  .fin-trs-vendor-table thead,
  .fin-est-list-table thead,
  .fin-exp-list-table thead,
  .fin-pnl-cat-table thead,
  .fin-pnl-inc-table thead,
  .fin-trs-pnl-month-table thead,
  .fin-trs-pnl-proj-table thead,
  .fin-dashboard-bva-table thead {
    position: absolute;
    left: -9999px;
    top: -9999px;
  }

  .fin-home-proj-table tbody, .fin-home-proj-table tr, .fin-home-proj-table td,
  .fin-pipeline-quote-table tbody, .fin-pipeline-quote-table tr, .fin-pipeline-quote-table td,
  .fin-pipeline-quote-table tfoot, .fin-pipeline-quote-table tfoot tr, .fin-pipeline-quote-table tfoot td,
  .fin-trs-recent-table tbody, .fin-trs-recent-table tr, .fin-trs-recent-table td,
  .fin-trs-vendor-table tbody, .fin-trs-vendor-table tr, .fin-trs-vendor-table td,
  .fin-est-list-table tbody, .fin-est-list-table tr, .fin-est-list-table td,
  .fin-exp-list-table tbody, .fin-exp-list-table tr, .fin-exp-list-table td,
  .fin-pnl-cat-table tbody, .fin-pnl-cat-table tr, .fin-pnl-cat-table td,
  .fin-pnl-inc-table tbody, .fin-pnl-inc-table tr, .fin-pnl-inc-table td,
  .fin-trs-pnl-month-table tbody, .fin-trs-pnl-month-table tr, .fin-trs-pnl-month-table td,
  .fin-trs-pnl-proj-table tbody, .fin-trs-pnl-proj-table tr, .fin-trs-pnl-proj-table td,
  .fin-dashboard-bva-table tbody, .fin-dashboard-bva-table tr, .fin-dashboard-bva-table td,
  .fin-dashboard-bva-table tfoot, .fin-dashboard-bva-table tfoot tr, .fin-dashboard-bva-table tfoot td {
    display: block !important;
    width: 100% !important;
    box-sizing: border-box;
  }

  .fin-home-proj-table tr,
  .fin-pipeline-quote-table tbody tr,
  .fin-pipeline-quote-table tfoot tr,
  .fin-trs-recent-table tr,
  .fin-trs-vendor-table tr,
  .fin-est-list-table tr,
  .fin-exp-list-table tr,
  .fin-pnl-cat-table tr,
  .fin-pnl-inc-table tr,
  .fin-trs-pnl-month-table tr,
  .fin-trs-pnl-proj-table tr,
  .fin-dashboard-bva-table tbody tr,
  .fin-dashboard-bva-table tfoot tr {
    background: #ffffff !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 12px;
    margin-bottom: 12px;
    padding: 6px 2px;
  }

  .fin-home-proj-table td,
  .fin-pipeline-quote-table td,
  .fin-trs-recent-table td,
  .fin-trs-vendor-table td,
  .fin-est-list-table td,
  .fin-exp-list-table td,
  .fin-pnl-cat-table td,
  .fin-pnl-inc-table td,
  .fin-trs-pnl-month-table td,
  .fin-trs-pnl-proj-table td,
  .fin-dashboard-bva-table td {
    display: flex !important;
    justify-content: space-between !important;
    align-items: center !important;
    gap: 12px !important;
    padding: 8px 12px !important;
    border-bottom: 1px dashed #f1f5f9 !important;
    text-align: right !important;
    min-height: 36px;
    width: 100% !important;
    max-width: 100% !important;
  }

  .fin-home-proj-table td:last-child,
  .fin-pipeline-quote-table td:last-child,
  .fin-trs-recent-table td:last-child,
  .fin-trs-vendor-table td:last-child,
  .fin-est-list-table td:last-child,
  .fin-exp-list-table td:last-child,
  .fin-pnl-cat-table td:last-child,
  .fin-pnl-inc-table td:last-child,
  .fin-trs-pnl-month-table td:last-child,
  .fin-trs-pnl-proj-table td:last-child,
  .fin-dashboard-bva-table td:last-child {
    border-bottom: none !important;
  }

  .fin-home-proj-table td::before,
  .fin-pipeline-quote-table td::before,
  .fin-trs-recent-table td::before,
  .fin-trs-vendor-table td::before,
  .fin-est-list-table td::before,
  .fin-exp-list-table td::before,
  .fin-pnl-cat-table td::before,
  .fin-pnl-inc-table td::before,
  .fin-trs-pnl-month-table td::before,
  .fin-trs-pnl-proj-table td::before,
  .fin-dashboard-bva-table td::before {
    content: attr(data-label);
    font-weight: 700;
    color: #64748b;
    font-size: 11px;
    white-space: nowrap;
    flex-shrink: 0;
    text-align: left;
  }

  /* 액션 셀: 라벨 숨김 + 우측 정렬 */
  .fin-home-proj-act,
  .fin-pipeline-quote-open,
  .fin-est-list-act,
  .fin-exp-list-act,
  .fin-quote-list-act {
    justify-content: flex-end !important;
  }

  .fin-home-proj-act::before,
  .fin-pipeline-quote-open::before,
  .fin-est-list-act::before,
  .fin-exp-list-act::before,
  .fin-quote-list-act::before {
    content: "" !important;
  }

  /* ★ 2026-04-25 v2: 산출/지출/견적 목록을 한 줄 카드로 — 사용자 피드백 "여백 엄청 많아"
     기존 카드 패턴은 5 td 가 각각 한 줄씩 = 5줄/카드. 인라인 flex 로 한 줄에 모음. */
  .fin-est-list-table tr,
  .fin-exp-list-table tr,
  .fin-quote-list-table tr {
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    flex-wrap: wrap;
    padding: 8px 10px !important;
    margin-bottom: 6px !important;
    gap: 6px 10px !important;
  }
  .fin-est-list-table td,
  .fin-exp-list-table td,
  .fin-quote-list-table td {
    display: inline-flex !important;
    flex-direction: row !important;
    align-items: center;
    padding: 0 !important;
    border: none !important;
    min-height: 0 !important;
    text-align: left !important;
    width: auto !important;
    flex: 0 0 auto;
    font-size: 12px !important;
    gap: 4px;
  }
  /* 라벨 (::before) 숨김 — 값만 표시 */
  .fin-est-list-table td::before,
  .fin-exp-list-table td::before,
  .fin-quote-list-table td::before {
    display: none !important;
  }
  /* 명칭 셀이 가로 공간 차지 (가운데) */
  .fin-est-list-table td:nth-child(2),
  .fin-exp-list-table td:nth-child(2),
  .fin-quote-list-table td:nth-child(2) {
    flex: 1 1 auto !important;
    font-weight: 700;
  }
  /* 액션 셀 (삭제/수정 등) — 우측 끝 */
  .fin-est-list-act,
  .fin-exp-list-act,
  .fin-quote-list-act {
    margin-left: auto;
  }

  /* ★ 2026-04-25: 산출 편집의 모드 토글 + 템플릿 영역 — 모바일 한 줄 강제
     사용자 피드백: "한 줄로 만들어줘" — 좌측 토글 + 우측 템플릿 버튼 한 행에 모음 */
  #estModeBar {
    flex-wrap: nowrap !important;
    padding: 6px 8px !important;
    gap: 4px !important;
  }
  /* 좌측: '표시' 라벨 + 힌트 텍스트 숨김 → 토글 버튼만 */
  #estModeBar > div:first-child > span:first-child,
  #estModeBar #estModeHint {
    display: none !important;
  }
  /* 토글 버튼 컴팩트 */
  #estModeBar .est-mode-btn {
    padding: 3px 8px !important;
    font-size: 11px !important;
  }
  /* 우측: 템플릿 버튼 한 줄 + 컴팩트 (아이콘+텍스트 → 아이콘만) */
  #estModeBar > div:last-child {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    gap: 4px !important;
  }
  #estModeBar #estTplSaveBtn,
  #estModeBar #estTplLoadBtn {
    padding: 3px 6px !important;
    font-size: 11px !important;
    white-space: nowrap;
  }
  /* 모바일에선 텍스트 숨기고 이모지만 (font-size: 0 + ::before 로 다시 보이게는 복잡 → 그냥 폰트 줄임) */
  #estModeBar #estTplSaveBtn { font-size: 0 !important; }
  #estModeBar #estTplSaveBtn::before { content: '💾'; font-size: 13px; }
  #estModeBar #estTplLoadBtn { font-size: 0 !important; }
  #estModeBar #estTplLoadBtn::before { content: '📂'; font-size: 13px; }

  /* 랩퍼 박스 (외부 테두리/스크롤 제거) */
  .fin-home-proj-wrap {
    border: none !important;
    background: transparent !important;
    overflow-x: visible !important;
    box-shadow: none !important;
  }
}

/*──────────────────────────────────────────────────────────
   홈 툴바 + 근태 카드 모바일 레이아웃
   2026-04-25 추가 (사용자 피드백: 모바일 근태 카드 버튼 크라우드)
   ──────────────────────────────────────────────────────────*/
@media (max-width: 768px) {
  /* 홈 상단 툴바 (내보내기 / 알림 / 편집) — 좁은 화면에서 줄바꿈 허용 */
  #view-home > .flex.items-center.justify-end.gap-2 {
    flex-wrap: wrap;
    gap: 6px !important;
  }
  /* ★ 2026-04-25: style.css 의 @media (max-width: 1024px) #topbarActionsWrapper { display: none } 무력화
     모바일에서도 PDF/Excel/수동저장 버튼이 필요 (사용자 피드백) */
  #topbarActionsWrapper {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 6px !important;
    margin-top: 6px;
  }
  #topbarActionsWrapper .btn,
  #topbarActions .btn {
    font-size: 11px !important;
    padding: 6px 10px !important;
  }

  /* ★ 2026-04-25: 견적서 상단 헤더 (공급받는자 + 공급자 + 타이틀) 컴팩트화
     사용자 피드백 "견적서 상단부분이 화면 하나를 가득 채울 필요 없음" */
  .quote-paper > h1 {
    font-size: 18px !important;
    margin-bottom: 14px !important;
    letter-spacing: 0.2em !important;
  }
  .quote-receiver-supplier {
    margin-bottom: 16px !important;
    gap: 10px !important;
  }
  /* 좌측 공급받는자 영역 — 빈 placeholder 입력 줄 압축 */
  .quote-receiver-supplier > div:first-child {
    padding-right: 0 !important;
  }
  .quote-receiver-supplier > div:first-child > div.border-b-2 {
    font-size: 11px !important;
    padding-bottom: 2px !important;
    margin-bottom: 4px !important;
  }
  .quote-receiver-supplier input[type="text"],
  .quote-receiver-supplier input[type="date"] {
    font-size: 12px !important;
    padding: 2px 4px !important;
  }
  .quote-receiver-supplier input#quoteReceiverCompany {
    font-size: 14px !important;
    padding: 2px 4px !important;
  }
  .quote-receiver-supplier #quoteReceiverBizNum,
  .quote-receiver-supplier #quoteReceiverAddr,
  .quote-receiver-supplier #quoteReceiverEmail {
    font-size: 10px !important;
    padding: 1px 4px !important;
    margin-bottom: 0 !important;
  }
  /* 견적일자/건명/유효기간 표 — 모바일 컴팩트 */
  .quote-receiver-supplier table.w-full {
    margin-top: 8px !important;
  }
  .quote-receiver-supplier table.w-full td {
    padding: 2px 0 !important;
    font-size: 11px !important;
  }
  /* 우측 공급자 표 컴팩트 */
  .quote-supplier-table th,
  .quote-supplier-table td {
    padding: 2px 4px !important;
    font-size: 10px !important;
  }
  .quote-supplier-table input {
    font-size: 10px !important;
    padding: 1px 2px !important;
  }
  .quote-th-vertical {
    font-size: 10px !important;
  }
  /* "귀하" 폰트 축소 */
  .quote-receiver-supplier .text-xl.font-black { font-size: 14px !important; }
}

/* ★ 2026-04-26 v2: 우측 슬라이드 패널 — Jarvis-style chrome (topbar + footer + no-dim)
   레퍼런스: 좌측 목록 유지 + 우측 디테일 패널, dim 없이 사이드바이드(side-by-side) 편집
   적용: 견적/산출 + 추후 TODO/결재/CRM 등 확장 가능 (.right-slide-panel 클래스만 부착) */
.right-slide-panel {
  position: fixed !important;
  top: 60px;
  right: 0;
  bottom: 0;
  /* 모바일 88vw, 데스크탑 ≥768px 에서는 미디어쿼리로 재설정 */
  width: min(92vw, 50vw + 80px);
  max-width: 720px;
  min-width: 320px;
  z-index: 60;
}
/* 데스크탑 (768px 이상): 절반 + α */
@media (min-width: 768px) {
  .right-slide-panel {
    width: 58vw !important;
    max-width: 760px !important;
    min-width: 480px !important;
  }
}
.right-slide-panel {
  background: #ffffff;
  box-shadow: -8px 0 32px rgba(15, 23, 42, 0.10);
  border-left: 1px solid #e2e8f0;
  transform: translateX(100%);
  transition: transform 0.28s cubic-bezier(.4,0,.2,1);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* topbar 56px + 여백 / footer 60px + 여백 */
  padding: 72px 20px 84px !important;
  margin-bottom: 0 !important;
}
body.right-panel-open .right-slide-panel { transform: translateX(0); }
/* dim overlay 제거 — 좌측 목록을 계속 보면서 우측 디테일 편집 (Jarvis 스타일) */
/* 모바일에서만 dim 살림 (좌측 목록이 거의 안 보일 정도로 좁기 때문) */
@media (max-width: 767px) {
  body.right-panel-open::after {
    content: '';
    position: fixed;
    inset: 60px 0 0 0;
    background: rgba(15, 23, 42, 0.22);
    z-index: 55;
    pointer-events: auto;
  }
}

/* ─── Topbar (← 닫기 / 타이틀 / 액션) ─── */
#rightPanelTopbar {
  display: none;
  position: fixed;
  top: 60px;
  right: 0;
  width: min(92vw, 50vw + 80px);
  max-width: 720px;
  min-width: 320px;
  height: 52px;
  background: #ffffff;
  border-bottom: 1px solid #e2e8f0;
  border-left: 1px solid #e2e8f0;
  z-index: 62;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  font-family: inherit;
}
@media (min-width: 768px) {
  #rightPanelTopbar {
    width: 58vw;
    max-width: 760px;
    min-width: 480px;
  }
}
body.right-panel-open #rightPanelTopbar { display: flex; }
#rightPanelTopbar .rp-tb-left { display: flex; align-items: center; gap: 10px; min-width: 0; }
#rightPanelTopbar .rp-tb-back {
  width: 32px; height: 32px;
  border-radius: 8px;
  border: none;
  background: transparent;
  color: #475569;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px;
  transition: background 0.12s;
}
#rightPanelTopbar .rp-tb-back:hover { background: #f1f5f9; color: #0f172a; }
#rightPanelTopbar .rp-tb-title {
  font-size: 13px; font-weight: 700; color: #0f172a;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#rightPanelTopbar .rp-tb-right { display: flex; align-items: center; gap: 6px; }
#rightPanelTopbar .rp-tb-action {
  font-size: 12px; font-weight: 600; color: #475569;
  background: transparent; border: 1px solid transparent;
  padding: 6px 10px; border-radius: 6px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
#rightPanelTopbar .rp-tb-action:hover { background: #f8fafc; color: #0f172a; }
#rightPanelTopbar .rp-tb-action.danger:hover { background: #fef2f2; color: #b91c1c; }
#rightPanelTopbar .rp-tb-close {
  width: 32px; height: 32px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: transparent;
  color: #64748b;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px;
  transition: background 0.12s, color 0.12s;
}
#rightPanelTopbar .rp-tb-close:hover { background: #f1f5f9; color: #0f172a; }

/* ─── Footer (저장 상태 / 바로 저장) ─── */
#rightPanelFooter {
  display: none;
  position: fixed;
  bottom: 0;
  right: 0;
  width: min(92vw, 50vw + 80px);
  max-width: 720px;
  min-width: 320px;
  height: 56px;
  background: #ffffff;
  border-top: 1px solid #e2e8f0;
  border-left: 1px solid #e2e8f0;
  z-index: 62;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  font-family: inherit;
}
@media (min-width: 768px) {
  #rightPanelFooter {
    width: 58vw;
    max-width: 760px;
    min-width: 480px;
  }
}
body.right-panel-open #rightPanelFooter { display: flex; }
/* 자체 저장/액션 버튼 보유 패널은 chrome 푸터 숨김 (혼동 방지) */
body.rp-no-footer #rightPanelFooter { display: none !important; }
body.rp-no-footer .right-slide-panel { padding-bottom: 24px !important; }
#rightPanelFooter .rp-fb-status {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; color: #64748b;
}
#rightPanelFooter .rp-fb-status .rp-fb-time { color: #64748b; }
#rightPanelFooter .rp-fb-status .rp-fb-badge {
  font-size: 10px; font-weight: 600;
  padding: 2px 8px; border-radius: 999px;
  background: #ecfdf5; color: #047857;
}
#rightPanelFooter .rp-fb-status .rp-fb-badge.dirty { background: #fef3c7; color: #92400e; }
#rightPanelFooter .rp-fb-save {
  font-size: 12px; font-weight: 700; color: #ffffff;
  background: #0f172a;
  border: none; padding: 8px 16px; border-radius: 8px;
  cursor: pointer;
  transition: background 0.12s;
}
#rightPanelFooter .rp-fb-save:hover { background: #1e293b; }
#rightPanelFooter .rp-fb-save:disabled {
  background: #cbd5e1; cursor: not-allowed;
}

/* 모바일: 패널 열릴 때 하단 네비 숨김 (z-index 150 이 푸터 z-62 가림 방지) */
@media (max-width: 767px) {
  body.right-panel-open .mobile-bottom-nav,
  body.right-panel-open #mobileBottomNav {
    display: none !important;
  }
}

/* 2026-05-06 fix: 모바일 패널 클릭 안 되는 페인 해결
   원인: 패널 92vw → 좌측 8vw 에 ▶ rightPanelHandle (z-65) 가 카드 좌측 일부 가림 + dim 흡수.
   해결: 모바일에서 패널 100vw 풀스크린 + 핸들/dim 숨김 (닫기는 ✕/← 버튼 또는 좌측 스와이프). */
@media (max-width: 767px) {
  .right-slide-panel,
  #rightPanelTopbar,
  #rightPanelFooter {
    width: 100vw !important;
    max-width: 100vw !important;
    min-width: 100vw !important;
    border-left: none !important;
  }
  /* 풀스크린이면 핸들 의미 없음 + 카드 클릭 막아 페인 발생 */
  body.right-panel-open #rightPanelHandle {
    display: none !important;
  }
  /* 풀스크린이면 dim 자체가 의미 없음 (메인 가려짐) — pointer-events 흡수 차단 */
  body.right-panel-open::after {
    display: none !important;
  }
}

/* ─── 패널 내부 타이포그래피 (Jarvis-style metadata rows) ─── */
.right-slide-panel .rp-meta-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid #f1f5f9;
}
.right-slide-panel .rp-meta-row:last-child { border-bottom: none; }
.right-slide-panel .rp-meta-label {
  font-size: 12px; color: #64748b; font-weight: 500;
}
.right-slide-panel .rp-meta-value {
  font-size: 13px; color: #0f172a; font-weight: 600;
}

/* 기존 핸들 버튼 — 위치 보정 (패널 폭 변경에 맞춤) */
/* 우측 엣지 핸들 버튼 — JS 동적 생성, 견적/산출 view 활성 시만 표시 */
#rightPanelHandle {
  display: none;
  position: fixed;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  z-index: 65;
  width: 28px;
  height: 56px;
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-right: none;
  border-radius: 12px 0 0 12px;
  box-shadow: -2px 2px 8px rgba(15, 23, 42, 0.08);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: #475569;
  padding: 0;
  transition: right 0.25s cubic-bezier(.4,0,.2,1), background 0.15s;
}
#rightPanelHandle.active { display: flex; }
#rightPanelHandle:hover { background: #f8fafc; color: #0f172a; }
body.right-panel-open #rightPanelHandle {
  /* 패널 폭과 동일하게 좌측 이동 — width 와 정확히 매칭 */
  right: min(92vw, 50vw + 80px);
  max-right: 720px;
}
@media (min-width: 768px) {
  body.right-panel-open #rightPanelHandle {
    right: min(58vw, 760px);
  }
}

/* ★ 우측 슬라이드 패널 안의 버전 목록 — 카드 폭이 좁아 글자별 wrap 되는 문제 fix
   명칭 cell 을 첫 줄 전체로, 나머지 메타는 둘째 줄 wrap */
.right-slide-panel .fin-est-list-table tr,
.right-slide-panel .fin-quote-list-table tr,
.right-slide-panel .fin-exp-list-table tr {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: wrap !important;
  align-items: center !important;
  gap: 4px 10px !important;
  padding: 10px 12px !important;
  margin-bottom: 6px !important;
}
.right-slide-panel .fin-est-list-table td,
.right-slide-panel .fin-quote-list-table td,
.right-slide-panel .fin-exp-list-table td {
  display: inline-flex !important;
  white-space: nowrap !important;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 11px !important;
  color: #64748b;
}
/* 명칭 cell (2번째) — 첫 줄 전체 + 굵은 글씨 */
.right-slide-panel .fin-est-list-table td:nth-child(2),
.right-slide-panel .fin-quote-list-table td:nth-child(2),
.right-slide-panel .fin-exp-list-table td:nth-child(2) {
  flex: 1 1 100% !important;
  font-size: 13px !important;
  font-weight: 700 !important;
  color: #0f172a !important;
  display: block !important;
  max-width: 100% !important;
}

@media (max-width: 768px) {
  /* 근태 카드 — 상태 텍스트가 길면 줄바꿈 허용, 우측 버튼 그룹 자체 줄로 분리 */
  #clockWidget > .flex.items-center.justify-between {
    flex-wrap: wrap;
    gap: 8px !important;
  }
  #clockWidget #clockWidgetStatus {
    font-size: 10px !important;
  }
  #clockWidget select#clockWorkType {
    flex: 1 1 auto;
    min-width: 0;
  }
  /* 2026-04-25: 출퇴근/근무시간 3개 통계 — 모바일에서 한 줄 가운데 정렬 강제
     (모바일에서 어떤 사유로 세로 stack 되던 문제 해결) */
  #clockWidget #clockTodayInfo {
    flex-direction: row !important;
    justify-content: center !important;
    flex-wrap: nowrap !important;
    white-space: nowrap !important;
    gap: 16px !important;
  }
  #clockWidget #clockTodayInfo > span {
    display: inline-flex !important;
    align-items: center;
    gap: 4px;
  }

  /*──────────────────────────────────────────────────────
     프로젝트 목록 통계 카드 — 모바일 세로 스택 + 라벨/값 가로 정렬
     2026-04-25 추가 (사용자 피드백: 계약금액 합계가 카드 폭 넘어 삐져나옴)
     ──────────────────────────────────────────────────────*/
  .pl-stats-row {
    flex-direction: column !important;
    gap: 8px !important;
  }
  .pl-stats-row > div {
    min-width: 0 !important;
    flex: 1 1 100% !important;
    width: 100% !important;
    display: flex !important;
    justify-content: space-between !important;
    align-items: center !important;
    padding: 10px 14px !important;
    box-sizing: border-box;
  }
  .pl-stats-row > div > div:nth-child(2) {
    font-size: 16px !important;
    text-align: right !important;
    word-break: break-all;
    flex-shrink: 0;
  }
}

/*──────────────────────────────────────────────────────────
   산출(estimate) / 견적서(quote) 입력 테이블 — 모바일 가로 스크롤 표 모드
   2026-04-25 v3: 카드 변환 → 표 형태 유지 + 가로 스크롤 (사용자 선호)

   · 카드 stack 대신 본래 표 레이아웃 보존
   · table-layout: fixed 해제 → 컬럼이 콘텐츠 크기에 맞춰 자동 사이즈
   · .doc-table-wrap / .quote-table 부모에 overflow-x:auto → 가로 스와이프로 우측 컬럼 확인
   · data-label ::before 라벨은 표시하지 않음 (헤더가 이미 sticky 가능)
   ──────────────────────────────────────────────────────────*/
@media (max-width: 768px) {
  /* ─────────────────────────────────────────────────
     산출/견적 표 — viewport 안에 모든 컬럼 표시 (가로 스크롤 X)
     2026-04-25 v4: 사용자 요청 "오른쪽 잘림 한 화면에 다 나오게"
     · font 10px + padding 2-4px 으로 압축
     · 드래그 핸들 컬럼 숨김 (모바일에선 drag-and-drop 비현실, 어차피 print-hide)
     · 산출의 산출근거 컬럼도 너무 좁으면 숨김 (보조 정보)
     · table-layout: fixed + 콜그룹 너비 비율 사용
     ───────────────────────────────────────────────── */
  /* 10px → 11px (2026-09-29, 순서표 24단계) — 종전엔 전역 `th, td { 11px !important }`(지움)가 칸 글자를 11px 로 올려 줬다.
     그 규칙이 빠지면 칸이 이 10px 를 물려받아 오히려 작아진다. 입력칸은 아래 자기 규칙 그대로. */
  #estimateTable {
    display: table !important;
    table-layout: fixed !important;
    width: 100% !important;
    min-width: 0 !important;
    font-size: 11px !important;
  }
  #estimateTable thead { display: table-header-group !important; }
  #estimateTable tbody { display: table-row-group !important; }
  #estimateTable tr { display: table-row !important; }
  /* 활성 탭 접기 토글(est-exp-views.js) — 위 display:table !important가 인라인 none을
     이겨 모바일에서 테이블이 안 접히던 것 방어 (2026-07-12) */
  #estimateTable.est-tbl-collapsed { display: none !important; }
  #estimateTable th,
  #estimateTable td {
    display: table-cell !important;
    padding: 4px 3px !important;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
  }
  /* 모바일에서 비핵심 컬럼 숨김 — col+th+td 3중 display:none + 보이는 컬럼 폭 명시
     ★ 2026-07-21: nth-child → c-* 클래스 전환 (사전내수표 스타일 개편 — 컬럼 삽입에 내성).
     데스크탑 전용 신규 컬럼(구분 rowspan c-group·단위 c-unit/c-unit2)도 모바일에선 숨겨
     기존 fit 레이아웃(2026-04-25 사용자 선호 "한 화면에 다 나오게") 유지.
     c-group td는 rowspan이지만 display:none 시 열 예약도 함께 사라져 전 행이 균일하게 당겨짐 */
  #estimateTable col.c-group, #estimateTable th.c-group, #estimateTable td.c-group { display: none !important; }
  #estimateTable col.c-drag, #estimateTable th.c-drag, #estimateTable td.c-drag { display: none !important; }
  #estimateTable col.c-cat, #estimateTable th.c-cat, #estimateTable td.c-cat { display: none !important; }
  #estimateTable col.c-lvl, #estimateTable th.c-lvl, #estimateTable td.c-lvl { display: none !important; }
  #estimateTable col.c-unit, #estimateTable th.c-unit, #estimateTable td.c-unit { display: none !important; }
  #estimateTable col.c-unit2, #estimateTable th.c-unit2, #estimateTable td.c-unit2 { display: none !important; }
  #estimateTable col.c-note, #estimateTable th.c-note, #estimateTable td.c-note { display: none !important; }
  /* 푸터는 #estimateTable 에 없어 (산출은 td colspan 푸터 행 없음) — 안전 */
  /* 핵심 컬럼 폭 강제 (col + th + td 모두) */
  #estimateTable col.c-no, #estimateTable thead th.c-no, #estimateTable tbody td.c-no { width: 8% !important; }
  #estimateTable col.c-role, #estimateTable thead th.c-role, #estimateTable tbody td.c-role { width: 23% !important; }
  #estimateTable col.c-qty, #estimateTable thead th.c-qty, #estimateTable tbody td.c-qty { width: 10% !important; }
  #estimateTable col.c-days, #estimateTable thead th.c-days, #estimateTable tbody td.c-days { width: 9% !important; }
  #estimateTable col.c-price, #estimateTable thead th.c-price, #estimateTable tbody td.c-price { width: 20% !important; }
  #estimateTable col.c-amt, #estimateTable thead th.c-amt, #estimateTable tbody td.c-amt { width: 22% !important; }
  #estimateTable col.c-del, #estimateTable thead th.c-del, #estimateTable tbody td.c-del { width: 8% !important; }
  /* 본문 외 (구분 행 colspan 등) — 기본 셀 동작 유지 */
  #estimateTable tbody tr.est-divider-row td { width: auto !important; }
  #estimateTable td input,
  #estimateTable td select {
    width: 100%;
    box-sizing: border-box;
    font-size: 10px !important;
    padding: 0 !important;
  }

  /* 견적서 표 — 10px → 11px (2026-09-29, 위 #estimateTable 과 같은 까닭) */
  .quote-table {
    display: table !important;
    table-layout: fixed !important;
    width: 100% !important;
    min-width: 0 !important;
    font-size: 11px !important;
  }
  .quote-table thead { display: table-header-group !important; }
  .quote-table tbody { display: table-row-group !important; }
  .quote-table tfoot { display: table-footer-group !important; }
  .quote-table tr { display: table-row !important; }
  .quote-table th,
  .quote-table td {
    display: table-cell !important;
    padding: 4px 3px !important;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
  }
  /* 견적서 비핵심 컬럼 숨김 — 클래스 기반 (2026-07-22 배치② nth-child → c-* 전환, 컬럼 추가 내성)
     데스크탑 전용 신규 컬럼(구분 rowspan c-group·단위 c-unit/c-unit2)도 모바일에선 숨겨 기존 fit 유지.
     c-group td는 rowspan이지만 display:none 시 열 예약도 함께 사라져 전 행이 균일하게 당겨짐 (산출과 동일) */
  .quote-table col.c-group, .quote-table th.c-group, .quote-table td.c-group { display: none !important; }
  .quote-table col.c-drag, .quote-table th.c-drag, .quote-table td.c-drag { display: none !important; }
  .quote-table col.c-spec, .quote-table th.c-spec, .quote-table td.c-spec { display: none !important; }
  .quote-table col.c-note, .quote-table th.c-note, .quote-table td.c-note { display: none !important; }
  .quote-table col.c-unit, .quote-table th.c-unit, .quote-table td.c-unit { display: none !important; }
  .quote-table col.c-unit2, .quote-table th.c-unit2, .quote-table td.c-unit2 { display: none !important; }
  /* tfoot — table layout 유지하되 pad 셀만 숨기고 label 우측 정렬 */
  .quote-table tfoot {
    display: table-row-group !important;
  }
  .quote-table tfoot tr {
    display: table-row !important;
  }
  .quote-table tfoot tr td {
    display: table-cell !important;
    padding: 4px 8px !important;
    border: none !important;
    border-bottom: 1px dashed #e2e8f0 !important;
    overflow: visible !important;
    white-space: nowrap !important;
    text-overflow: clip !important;
    text-align: right !important;
  }
  .quote-table tfoot tr td.print-hide,
  .quote-table tfoot tr td.share-hide {
    display: none !important;
  }
  /* tfoot — label colspan=6 + value colspan=2 (JS 변경) → cell:nth-child 로 폭 명시 */
  .quote-table tfoot tr td:nth-child(1) {
    width: 70% !important;
    text-align: right !important;
    padding-right: 12px !important;
  }
  .quote-table tfoot tr td:nth-child(2) {
    width: 30% !important;
    min-width: 90px !important;
    text-align: right !important;
    padding-right: 12px !important;
    font-weight: 700;
  }
  /* 핵심 컬럼 폭 강제 (col + th + td — 클래스 기반) */
  .quote-table col.c-name, .quote-table thead th.c-name, .quote-table tbody td.c-name { width: 24% !important; }
  .quote-table col.c-qty, .quote-table thead th.c-qty, .quote-table tbody td.c-qty { width: 11% !important; }
  .quote-table col.c-days, .quote-table thead th.c-days, .quote-table tbody td.c-days { width: 8% !important; }
  .quote-table col.c-price, .quote-table thead th.c-price, .quote-table tbody td.c-price { width: 17% !important; }
  .quote-table col.c-dc, .quote-table thead th.c-dc, .quote-table tbody td.c-dc { width: 13% !important; }
  .quote-table col.c-amt, .quote-table thead th.c-amt, .quote-table tbody td.c-amt { width: 20% !important; }
  .quote-table col.c-del, .quote-table thead th.c-del, .quote-table tbody td.c-del { width: 7% !important; }
  /* 푸터 (공급가액/일반관리비/이윤/부가세) — colspan 행이라 :nth-child 적용 안 됨,
     단 폭이 0이 되지 않도록 명시적 100% */
  .quote-table tfoot tr,
  .quote-table tfoot td { width: auto !important; }
  /* 구분 행 (divider) */
  .quote-table tbody tr.quote-divider-row td { width: auto !important; }
  .quote-table td input {
    width: 100%;
    box-sizing: border-box;
    font-size: 10px !important;
    padding: 0 !important;
  }
  /* 부모 wrapper — 가로 스크롤 불필요 (표가 viewport 안에 들어감) */
  #view-estimate .doc-table-wrap,
  #view-quote .doc-table-wrap {
    overflow-x: hidden !important;
    max-width: 100%;
  }

  /* ★ 산출 상단 요약표 (인력비/경비/순원가/일반관리비/이윤/총공급가액)
     class 가 'w-full' 만 가져서 style.css 의 .quote-table,...,table.w-full { display:block }
     적용으로 깨짐 → display:table 강제 + 폰트 압축 */
  #view-estimate table.w-full {
    display: table !important;
    table-layout: fixed !important;
    width: 100% !important;
    min-width: 0 !important;
  }
  #view-estimate table.w-full thead { display: table-header-group !important; }
  #view-estimate table.w-full tbody { display: table-row-group !important; }
  #view-estimate table.w-full tr { display: table-row !important; }
  /* ⚠ 위 tr 광역 !important가 집행관리 정산 카드의 조건부 행(부가세/실지급 — JS 인라인
     display:none)까지 강제로 살려 모바일에서만 빈 행이 노출되던 버그(2026-07-02) —
     JS가 붙이는 숨김 클래스는 여기서 다시 이겨야 함 (PC와 표시 조건 일치) */
  #view-estimate #estInternalFooter tr.est-int-row-hidden,
  #estInternalFooter tr.est-int-row-hidden { display: none !important; }
  /* 같은 계열 방어(2026-07-12): 위 광역 tr 규칙이 Tailwind .hidden(비-!important)을 이겨
     비율(%) 행 #summaryPctRow가 체크박스 꺼짐 상태에도 모바일에 뜨던 것 재차단.
     .hidden은 의미상 항상 숨김이어야 하므로 부작용 없음 */
  #view-estimate table.w-full tr.hidden { display: none !important; }
  #view-estimate table.w-full th,
  #view-estimate table.w-full td {
    display: table-cell !important;
    padding: 4px 2px !important;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
  }
  /* #summarySupply 는 text-3xl (Tailwind 22px) 인데 모바일에선 너무 큼 */
  #view-estimate #summarySupply {
    font-size: 12px !important;
  }
  #view-estimate table.w-full td {
    font-size: 11px !important;
  }
  /* 머리글 8px → 11px(2026-09-29, 순서표 24단계) — 줄여서 맞추지 않고 두 줄로 접는다 */
  #view-estimate table.w-full th {
    font-size: 11px !important;
    white-space: normal !important;
    line-height: 1.2;
  }

  /* ─────────────────────────────────────────────────
     2026-05-06 v6: 지출결의 카드 — 진짜 콤팩트 grid (밀도 최대 + 잘림 0)
     사용자 요구: "최대한 밀도 있게 압축해서 잘리는거 없이"

     설계:
       - grid 2열 7행 (잘림 방지를 위해 행 통합 X)
       - 모든 치수 최소화 (gap 1px / padding 0 / input height 18px / font 9-10px)
       - 점선 테두리 → 하단 1px 라인 (시각 노이즈 ↓)
       - 카드 ~100px 목표 (이전 v494 ~180px 대비 -45%)
     ───────────────────────────────────────────────── */
  #expBody tr.exp-row {
    display: grid !important;
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.25fr) minmax(0, 1.05fr);
    grid-template-rows: 24px 22px 22px !important;
    gap: 1px 8px !important;
    padding: 4px 6px !important;
    margin-bottom: 4px !important;
    align-items: center;
  }
  #expBody tr.exp-row td {
    padding: 0 !important;
    margin: 0;
    white-space: normal !important;
    overflow: visible !important;
    word-break: break-all;
    min-width: 0;
    display: block !important;  /* style.css:1273 inline-block 무력화 */
    line-height: 1.2;
    font-size: 10px;
  }
  /* 0.00 MM 보조 div 강제 숨김 (multiple specificity, 안 먹는 케이스 대응) */
  #expBody tr.exp-row td .exp-mm,
  #expBody tr.exp-row .exp-mm,
  #expBody .exp-mm,
  .exp-row .exp-mm,
  .exp-mm {
    display: none !important;
    height: 0 !important;
    width: 0 !important;
    overflow: hidden !important;
    visibility: hidden !important;
  }
  /* No(1) 숨김 */
  #expBody tr.exp-row td:nth-child(1) {
    display: none !important;
  }
  /* 일수(6)·계약금(7)·세액(8)·지급 예정일(12) — 모바일 숨김 (보조 정보, 데스크톱에서 편집) */
  #expBody tr.exp-row td:nth-child(6),
  #expBody tr.exp-row td:nth-child(7),
  #expBody tr.exp-row td:nth-child(8),
  #expBody tr.exp-row td:nth-child(12) {
    display: none !important;
  }
  /* Row 1: 구분 col1 | 상호 col2 | 사업자번호 col3 */
  #expBody tr.exp-row td:nth-child(2) {
    grid-column: 1 !important;
    grid-row: 1 !important;
  }
  #expBody tr.exp-row td:nth-child(3) {
    grid-column: 2 !important;
    grid-row: 1 !important;
    font-weight: 700 !important;
    color: #0f172a !important;
  }
  #expBody tr.exp-row td:nth-child(4) {
    grid-column: 3 !important;
    grid-row: 1 !important;
    font-size: var(--fs-badge) !important;
    color: #64748b !important;
    text-align: right !important;
  }
  /* Row 2: 적요 col1-2 | 실지급액 col3 (핵심 강조) */
  #expBody tr.exp-row td:nth-child(5) {
    grid-column: 1 / 3 !important;
    grid-row: 2 !important;
  }
  #expBody tr.exp-row td:nth-child(9) {
    grid-column: 3 !important;
    grid-row: 2 !important;
    text-align: right !important;
    font-weight: 900 !important;
    color: #dc2626 !important;
    font-size: 13px !important;
  }
  /* Row 3: 계좌 col1-2 | 증빙·지급 col3 */
  #expBody tr.exp-row td:nth-child(10) {
    grid-column: 1 / 3 !important;
    grid-row: 3 !important;
    font-size: 10px !important;
  }
  #expBody tr.exp-row td:nth-child(11) {
    grid-column: 3 !important;
    grid-row: 3 !important;
    text-align: right !important;
  }
  #expBody tr.exp-row td:nth-child(13) {
    grid-column: 3 !important;
    grid-row: 3 !important;
    text-align: right !important;
  }
  /* delete(14) — 모바일 숨김 (col 3 어수선함 정리, 삭제는 데스크톱) */
  #expBody tr.exp-row td:nth-child(14) {
    display: none !important;
  }
  /* col 3 우측 정렬 일관 — 사업자번호/실지급액/체크박스 모두 right 라인 맞춤 */
  #expBody tr.exp-row td:nth-child(4),
  #expBody tr.exp-row td:nth-child(9),
  #expBody tr.exp-row td:nth-child(11),
  #expBody tr.exp-row td:nth-child(13) {
    padding-right: 2px !important;
    text-align: right !important;
  }
  /* 첨부(11)·지급(13) 같은 grid cell 안에서 클릭 영역 분리 —
     justify-self: start/end + width:auto 로 td 자체 box 가 콘텐츠 폭만큼만 차지.
     이전 padding-right:22px 방식은 11 td 가 13 자리까지 box 확장 → 클릭 흡수 페인. */
  #expBody tr.exp-row td:nth-child(11) {
    grid-column: 3 !important;
    grid-row: 3 !important;
    justify-self: start !important;
    width: auto !important;
    padding: 0 !important;
    display: flex !important;
    align-items: center !important;
  }
  #expBody tr.exp-row td:nth-child(13) {
    grid-column: 3 !important;
    grid-row: 3 !important;
    justify-self: end !important;
    width: auto !important;
    padding: 0 !important;
    display: flex !important;
    align-items: center !important;
  }
  /* input/select — 셀 가득 채움 + 최대 압축 + 점선 제거 (하단 라인만)
     iOS Safari native UI 무력화 (-webkit-appearance:none) 필수 — 안 그러면 height 무시됨 */
  #expBody tr.exp-row td input,
  #expBody tr.exp-row td textarea,
  #expBody tr.exp-row td select {
    -webkit-appearance: none !important;
    appearance: none !important;
    width: 100% !important;
    max-width: none !important;
    min-width: 0 !important;
    font-size: 10px !important;
    padding: 1px 4px !important;
    min-height: 20px !important;
    height: 20px !important;
    line-height: 1.2 !important;
    box-sizing: border-box !important;
    background: transparent !important;
    border: none !important;
    border-bottom: 1px solid #f1f5f9 !important;
    border-radius: 0 !important;
    -webkit-border-radius: 0 !important;
  }
  /* 구분 칸 «쇼핑몰 가격이면 VAT포함» 안내는 PC 표에서만 — 카드 줄에선 옆 칸(적요) 글자와 겹친다 (2026-10-22) */
  #expBody tr.exp-row .exp-vat-hint { display: none !important; }
  /* 체크박스는 native UI 유지 — appearance:none 영향 받지 않게 */
  #expBody tr.exp-row td input[type="checkbox"] {
    -webkit-appearance: checkbox !important;
    appearance: checkbox !important;
    width: 16px !important;
    height: 16px !important;
    min-height: 16px !important;
    border: 1px solid #cbd5e1 !important;
  }
  #expBody tr.exp-row td input:focus,
  #expBody tr.exp-row td textarea:focus,
  #expBody tr.exp-row td select:focus {
    background: #f8fafc !important;
    border-bottom-color: #94a3b8 !important;
  }
  /* 첨부 등 버튼 압축 */
  #expBody tr.exp-row td button {
    font-size: var(--fs-badge) !important;
    padding: 1px 4px !important;
    min-height: 18px;
  }
  /* select 도 input 처럼 22px max — 안 그러면 row 1 height 가 select 따라가서 td 44px */
  #expBody tr.exp-row td select {
    -webkit-appearance: none !important;
    appearance: none !important;
    height: 22px !important;
    min-height: 22px !important;
    max-height: 22px !important;
    line-height: 1 !important;
    background-image: linear-gradient(45deg, transparent 50%, #94a3b8 50%), linear-gradient(135deg, #94a3b8 50%, transparent 50%) !important;
    background-position: calc(100% - 9px) 9px, calc(100% - 5px) 9px !important;
    background-size: 4px 4px, 4px 4px !important;
    background-repeat: no-repeat !important;
    padding-right: 14px !important;
  }
  /* td 자체 max-height 강제 (grid row max-content 무력화) */
  #expBody tr.exp-row td:nth-child(2),
  #expBody tr.exp-row td:nth-child(3),
  #expBody tr.exp-row td:nth-child(4),
  #expBody tr.exp-row td:nth-child(5),
  #expBody tr.exp-row td:nth-child(6),
  #expBody tr.exp-row td:nth-child(7),
  #expBody tr.exp-row td:nth-child(8),
  #expBody tr.exp-row td:nth-child(10),
  #expBody tr.exp-row td:nth-child(11),
  #expBody tr.exp-row td:nth-child(13) {
    min-height: 0 !important;
    align-self: center;
  }
  /* grid row 명시는 위쪽 #expBody tr.exp-row 정의에서 24/22/22 (3행) 처리됨 */

  #view-expense .doc-table-wrap {
    overflow-x: hidden !important;
  }
  /* 카드 표는 화면 폭으로 (2026-09-29, 순서표 24단계) — style.css 의 `#view-expense table { min-width: 500px }`(요약표용)가
     지출 카드 표까지 500px 로 넓혀, 위 overflow 숨김에 오른쪽 열(실지급액·첨부·지급 체크)이 잘려 **폰에서 금액이 안 보였다**
     (스테이징 375px 실측 — 글자 크기와 무관하게 전부터 그랬다). */
  #view-expense #expenseTable {
    min-width: 0 !important;
  }
  /* 폰 카드 3줄 (2026-10-22 사장님 «폰 화면은 글자가 너무 많아» · 시안 승인): 상호·실지급 / 적요 / 계좌·첨부·지급.
     구분·사업자번호·표 머리 줄은 PC 에서 고친다 — 위 v6 그리드를 같은 선택자로 덮는다(뒤에 와야 이긴다). */
  #view-expense #expenseTable thead { display: none !important; }
  #expBody tr.exp-row {
    grid-template-columns: minmax(0, 1fr) auto auto !important;
    grid-template-rows: auto auto auto !important;
    gap: 2px 10px !important;
    padding: 8px 26px 8px 10px !important;   /* 오른쪽 «◀» 서랍 탭(화면 가장자리 고정)이 지급 체크를 가리지 않게 */
  }
  #expBody tr.exp-row td:nth-child(2),
  #expBody tr.exp-row td:nth-child(4) { display: none !important; }
  #expBody tr.exp-row td:nth-child(3) { grid-column: 1 !important; grid-row: 1 !important; text-align: left !important; }
  #expBody tr.exp-row td:nth-child(3) input { font-size: var(--fs-base) !important; font-weight: 700 !important; text-align: left !important; }
  #expBody tr.exp-row td:nth-child(9) { grid-column: 2 / 4 !important; grid-row: 1 !important; font-size: var(--fs-base) !important; }
  #expBody tr.exp-row td:nth-child(5) { grid-column: 1 / 4 !important; grid-row: 2 !important; }
  #expBody tr.exp-row td:nth-child(5) textarea { font-size: var(--fs-meta) !important; text-align: left !important; }
  #expBody tr.exp-row td:nth-child(10) { grid-column: 1 !important; grid-row: 3 !important; text-align: left !important; }
  #expBody tr.exp-row td:nth-child(10) textarea { text-align: left !important; }
  #expBody tr.exp-row td:nth-child(11) { grid-column: 2 !important; grid-row: 3 !important; justify-self: end !important; }
  #expBody tr.exp-row td:nth-child(13) { grid-column: 3 !important; grid-row: 3 !important; justify-self: end !important; }
}

/*──────────────────────────────────────────────────────────
   모바일 컴팩트 요약행 — 재무 대시보드(프로젝트별 재무) + 자금 거래내역
   기본: 1행 = 1줄 요약(att-mobile-row 패턴), 탭하면 기존 상세 카드 펼침.
   요약 td(.fop-m/.trs-m)는 데스크톱에서 inline display:none —
   테이블 레이아웃에 불참여하므로 컬럼 수/colSpan 영향 없음.
   2026-07-02 추가
   ──────────────────────────────────────────────────────────*/
@media (max-width: 640px) {
  /* ── 📊 프로젝트별 재무 (fin-overview.js) ── */
  .fin-overview-proj-table td.fop-m {
    display: flex !important;
    flex-direction: column;
    gap: 3px !important; /* 베이스 규칙 gap:12px !important 상쇄 */
    width: 100% !important; flex: 1 1 100% !important; /* ≤900 카드 공통 규칙이 width:auto 로 덮던 것 */
    min-width: 0; /* 줄(tr)이 flex 라 기본 최소 폭 = 긴 이름 전체 → 표가 가로로 밀렸다(2026-10-12 아이폰 신고) */
    padding: 10px 12px !important;
    min-height: 0 !important;
    border-bottom: none !important;
    text-align: left !important;
    cursor: pointer;
  }
  .fin-overview-proj-table td.fop-m::before { content: "" !important; }
  .fin-overview-proj-table tr:not(.fop-open) > td:not(.fop-m) { display: none !important; }
  .fin-overview-proj-table tr.fop-open td.fop-m { border-bottom: 1px dashed #e2e8f0 !important; }
  .fin-overview-proj-table tr { margin-bottom: 6px !important; }
  .fop-line1 { display: flex; align-items: center; gap: 8px; width: 100%; }
  .fop-name { flex: 1; min-width: 0; font-weight: 800; font-size: 13px; color: #0f172a; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .fop-line2 { display: flex; gap: 10px; width: 100%; font-size: 11px; color: #64748b; font-variant-numeric: tabular-nums; }

}

/* 자금 목록은 카드 전환과 요약/펼침의 경계를 맞춘다(폴드 포함). */
@media (max-width: 900px) {
  /* ── 💰 자금 거래내역 (treasury-transactions-row.js) ──
     월 그룹 헤더(td[colspan])는 요약행 규칙에서 제외 → 그대로 표시 */
  .fin-trs-table td.trs-m {
    display: flex !important;
    align-items: center;
    gap: 8px !important; /* 베이스 규칙 gap:12px !important 상쇄 */
    width: 100% !important; flex: 1 1 100% !important; /* ≤900 카드 공통 규칙(td width:auto·flex:0 1 auto !important)이 덮어 칸이 내용 폭만 차지했다 — 줄을 채워야 금액이 오른쪽 끝 */
    min-width: 0; /* 긴 거래처·내역이 칸을 늘려 목록이 좌우로 밀렸다 — 0 이어야 .trs-m-txt 말줄임이 먹는다(2026-10-12) */
    padding: 10px 12px !important;
    min-height: 0 !important;
    border-bottom: none !important;
    text-align: left !important;
    cursor: pointer;
  }
  .fin-trs-table td.trs-m::before { content: "" !important; }
  /* 월 머리줄(td[colspan]) — 같은 공통 규칙에 줄어 회색 띠가 카드 중간에서 끝나고 «10월1건»처럼 붙었다. 칸과 안쪽 «라벨 ↔ 금액» 줄 모두 폭을 채운다 */
  .fin-trs-table td[colspan] { width: 100% !important; flex: 1 1 100% !important; min-width: 0; }
  .fin-trs-table td[colspan] > div { flex: 1 1 auto; min-width: 0; }
  .fin-trs-table tr:not(.trs-open) > td:not(.trs-m):not([colspan]) { display: none !important; }
  .fin-trs-table tr.trs-open td.trs-m { border-bottom: 1px dashed #e2e8f0 !important; }
  .fin-trs-table tr { margin-bottom: 6px !important; }
  /* ✏️ 펼친 거래 = 편집 양식 — ≤900 공통 «읽기 카드» 배치(거래처를 제목으로·금액을 오른쪽 끝으로·칸은 오른쪽 정렬 60%)가
     입력칸 줄에 맞지 않아 요약 줄이 가운데 끼고, 체크·번호·삭제가 한 줄씩 떠 있고, 내역·메모 칸이 카드 밖으로 나갔다
     (2026-10-12 사장님 «너무 못생겼다»). 요약 줄 = 맨 위 머리 · 입력 = «라벨 | 칸» 한 줄씩 · 선택·번호·삭제 = 맨 아래 한 줄 */
  .fin-trs-table tr.trs-open { column-gap: 0 !important; padding-bottom: 8px !important; }
  .fin-trs-table tr.trs-open td.trs-m { order: -10; margin-bottom: 6px; }
  .fin-trs-table tr.trs-open td[data-label] {
    order: 0;
    flex: 1 1 100% !important; width: 100% !important; min-width: 0;
    justify-content: flex-start !important; align-items: center !important; gap: 10px !important;
    margin-left: 0; padding: 3px 12px !important;
    font-size: 13px; font-weight: 400; color: inherit;
  }
  .fin-trs-table tr.trs-open td[data-label]::before {
    content: attr(data-label) !important; display: block !important;
    flex: 0 0 44px; font-size: 11px; font-weight: 700; color: #94a3b8;
  }
  .fin-trs-table tr.trs-open td[data-label] input:not([type="checkbox"]),
  .fin-trs-table tr.trs-open td[data-label] select { flex: 1 1 auto; width: auto !important; min-width: 0; max-width: none; text-align: left; }
  .fin-trs-table tr.trs-open td[data-label="금액"] input { text-align: right; font-weight: 800; }
  .fin-trs-table tr.trs-open td[data-label="날짜"] { order: 1; }
  .fin-trs-table tr.trs-open td[data-label="거래처"] { order: 2; }
  .fin-trs-table tr.trs-open td[data-label="내역"] { order: 3; }
  .fin-trs-table tr.trs-open td[data-label="금액"] { order: 4; }
  .fin-trs-table tr.trs-open td[data-label="구분"] { order: 5; }
  .fin-trs-table tr.trs-open td[data-label="프로젝트"] { order: 6; }
  .fin-trs-table tr.trs-open td[data-label="계좌"] { order: 7; }
  .fin-trs-table tr.trs-open td[data-label="증빙"] { order: 8; }
  .fin-trs-table tr.trs-open td[data-label="영수증"] { order: 9; }
  .fin-trs-table tr.trs-open td[data-label="메모"] { order: 10; }
  .fin-trs-table tr.trs-open td.fin-trs-check,
  .fin-trs-table tr.trs-open td.fin-trs-num,
  .fin-trs-table tr.trs-open td.fin-trs-del {
    order: 20; flex: 0 0 auto !important; width: auto !important; min-height: 0 !important;
    padding: 10px 12px 0 !important;
  }
  .fin-trs-table tr.trs-open td.fin-trs-del { margin-left: auto; }
  /* 번호·✏️(수정 이력은 마우스를 올려야 보이는 말풍선)는 폰에서 읽을 수 없어 세로로 쌓인 군더더기였다 */
  .fin-trs-table tr.trs-open td.fin-trs-num { display: none !important; }
  .trs-m-date { font-weight: 800; font-size: 12px; color: #0f172a; white-space: nowrap; flex-shrink: 0; font-variant-numeric: tabular-nums; }
  .trs-m-cat { font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 8px; background: #f1f5f9; color: #475569; white-space: nowrap; flex-shrink: 0; }
  .trs-m-cat.trs-m-cat-none { background: #fef3c7; color: #92400e; }
  .trs-m-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: #334155; }
  .trs-m-amt { font-weight: 900; font-size: 13px; white-space: nowrap; flex-shrink: 0; font-variant-numeric: tabular-nums; margin-left: auto; } /* 짧은 내역에서도 금액은 오른쪽 끝 — 줄마다 금액 위치가 달라 읽기 어려웠다 */
}


/* ═══════════════════════════════════════════════════════════
   🗓 전사 일정 (간트 매트릭스) — global-gantt-view.js
   ⚠️ 로컬 데모, 미배포.

   여기 있는 이유: 리포 규약상 JS 의 createElement('style') 은 금지
   (tests/css-extraction.test.js). 새 CSS 파일을 만들면 sw.js PRECACHE_URLS
   를 건드려야 해서, 이미 링크·프리캐시된 이 파일에 덧붙인다.

   전 클래스 gg- 프리픽스 + .gg-root 스코프 — OS 의
   .btn/.modal/.toast/.proj/.sub/.last/.lg/.meta/.primary 와 이름 충돌 회피.
   ═══════════════════════════════════════════════════════════ */
.gg-root {
    --gg-line: #e2e8f0; --gg-line2: #cbd5e1;
    --gg-ink: #0f172a; --gg-ink2: #475569; --gg-ink3: #94a3b8;
    --gg-soft: #f8fafc; --gg-wknd: #f1f5f9; --gg-projbg: #f5f7fb; --gg-today: #dc2626;
    display: block; background: #fff; border-radius: 12px; font-size: 13px; color: var(--gg-ink);
}
.gg-root * { box-sizing: border-box; }

.gg-bar-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 11px 14px; border-bottom: 1px solid var(--gg-line); }
.gg-note { font-size: 11px; font-weight: 700; color: #92400e; background: #fef3c7; border: 1px solid #fcd34d; border-radius: 9999px; padding: 3px 9px; }
.gg-meta-txt { font-size: 12px; color: var(--gg-ink2); }
.gg-spacer { flex: 1 1 auto; }
.gg-b { font: inherit; font-size: 12px; color: var(--gg-ink2); background: #fff; border: 1px solid var(--gg-line2); border-radius: 8px; padding: 5px 11px; cursor: pointer; }
.gg-b:hover { background: var(--gg-soft); color: var(--gg-ink); }
.gg-b.gg-b-pri { background: #2563eb; border-color: #1d4ed8; color: #fff; font-weight: 600; }
.gg-b.gg-b-pri:hover { background: #1d4ed8; color: #fff; }

.gg-legend { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; padding: 7px 14px; font-size: 11.5px; color: var(--gg-ink2); border-bottom: 1px solid var(--gg-line); }
.gg-lgi { display: inline-flex; align-items: center; gap: 5px; }
.gg-sw { width: 22px; height: 9px; border-radius: 4px; display: inline-block; }
.gg-sw-today { width: 2px; height: 13px; background: var(--gg-today); border-radius: 0; }
.gg-sw-wknd { background: var(--gg-wknd); border: 1px solid var(--gg-line); }
.gg-sw-tmp { border: 1.5px dashed rgba(15, 23, 42, .45); background: repeating-linear-gradient(45deg, #94a3b8, #94a3b8 4px, rgba(255,255,255,.7) 4px, rgba(255,255,255,.7) 8px); }

.gg-scroll { overflow: auto; max-height: 60vh; min-height: 280px; background: #fff; }
.gg-wrap { position: relative; width: max-content; }
.gg-empty { padding: 40px 16px; text-align: center; color: var(--gg-ink3); font-size: 13px; }

.gg-table { border-collapse: separate; border-spacing: 0; table-layout: fixed; background: #fff; }
.gg-table th, .gg-table td { padding: 0; margin: 0; border-right: 1px solid var(--gg-line); border-bottom: 1px solid var(--gg-line); background: #fff; font-weight: 400; white-space: nowrap; }
/* ⚠ overflow:hidden 은 좌측 고정열에만. 타임라인 셀에 걸면 여러 날에 걸친 간트 바가
   시작 셀 폭(22px)으로 잘려 1일짜리처럼 보인다. */
.gg-table th.gg-lft, .gg-table td.gg-lft { overflow: hidden; text-overflow: ellipsis; }

.gg-table thead th { color: var(--gg-ink2); font-size: 11.5px; font-weight: 600; background: var(--gg-soft); position: sticky; z-index: 3; }
.gg-table thead tr.gg-r1 th { height: 26px; top: 0; }
.gg-table thead tr.gg-r2 th { height: 24px; }
.gg-table thead th.gg-month { text-align: center; border-right: 1px solid var(--gg-line2); background: #eef2f7; color: var(--gg-ink); }
.gg-table thead th.gg-dnum { text-align: center; font-size: 10.5px; color: var(--gg-ink2); font-variant-numeric: tabular-nums; }
.gg-table thead th.gg-dnum.gg-wk { background: #e7ecf3; color: var(--gg-ink3); }
.gg-table thead th.gg-dnum.gg-td { background: var(--gg-today); color: #fff; font-weight: 700; }
.gg-table th.gg-ms, .gg-table td.gg-ms { border-left: 1px solid var(--gg-line2); }

/* 좌·상 동시 고정: 모서리(4) > 헤더(3) > 본문 좌측열(2) > 바(1) > 일반 셀 */
.gg-table .gg-lft { position: sticky; z-index: 2; }
.gg-table thead .gg-lft { z-index: 4; background: #eef2f7; text-align: center; border-bottom: 1px solid var(--gg-line2); vertical-align: middle; }
.gg-table .gg-lft.gg-lastcol { border-right: 2px solid var(--gg-line2); }
.gg-table tbody td.gg-lft { background: #fff; font-size: 12px; padding: 0 7px; color: var(--gg-ink); vertical-align: middle; }
.gg-table tbody tr.gg-prow td { background: var(--gg-projbg); }
.gg-table tbody tr.gg-prow td.gg-lft { background: var(--gg-projbg); font-weight: 700; cursor: pointer; }
.gg-table tbody tr.gg-srow td.gg-lft { color: var(--gg-ink2); }
.gg-table tbody tr:hover td.gg-lft { background: #eef4ff; }
.gg-table tbody tr.gg-prow:hover td.gg-lft { background: #e6ecfa; }
.gg-table tbody tr { height: 28px; }

/* ⚠ 명시도 주의: `tbody td.gg-lft`(0,2,1) 보다 높아야 12px 굵은 글씨에 안 덮인다 */
.gg-table tbody td.gg-lft.gg-c-budget { text-align: right; font-variant-numeric: tabular-nums; }
.gg-table tbody td.gg-lft.gg-c-date { text-align: center; font-size: 11px; color: var(--gg-ink2); font-variant-numeric: tabular-nums; font-weight: 400; }
.gg-table tbody td.gg-lft.gg-c-days { text-align: center; font-size: 11px; color: var(--gg-ink2); font-variant-numeric: tabular-nums; }
.gg-table tbody td.gg-lft.gg-c-owner, .gg-table tbody td.gg-lft.gg-c-client { font-size: 11.5px; }

/* ⚠ .gg-c-name 에 position:relative 금지 — `.gg-lft{position:sticky}` 보다 명시도가 높으면
   가로 스크롤 시 프로젝트명 열의 좌측 고정이 풀린다. sticky 도 위치 지정 요소라 ::before 기준으로 충분. */
.gg-table td.gg-c-name .gg-nm { display: inline-block; vertical-align: middle; max-width: calc(100% - 14px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gg-table tbody tr.gg-srow td.gg-c-name .gg-nm { padding-left: 18px; color: var(--gg-ink2); }
.gg-table tbody tr.gg-srow td.gg-c-name .gg-nm::before { content: ""; position: absolute; left: 12px; top: 50%; width: 8px; height: 1px; background: var(--gg-line2); }
.gg-caret { display: inline-block; width: 12px; color: var(--gg-ink3); font-size: 9px; line-height: 1; }
.gg-chip { display: inline-block; width: 4px; height: 13px; border-radius: 4px; vertical-align: -2px; margin-right: 6px; }
.gg-badge-tmp { display: inline-block; vertical-align: middle; margin-left: 6px; font-size: 10px; font-weight: 700; color: #9a3412; background: #ffedd5; border: 1px solid #fdba74; border-radius: 4px; padding: 2px 7px; line-height: 1.3; }
.gg-table td.gg-c-name.gg-has-tmp .gg-nm { max-width: calc(100% - 54px); }

.gg-table td.gg-day { position: relative; }
.gg-table td.gg-day.gg-wk { background: var(--gg-wknd); }
.gg-table tbody tr.gg-prow td.gg-day.gg-wk { background: #eaeef5; }

/* ⚠ z-index 필수: td.gg-day 가 position:relative 라 바 뒤쪽 셀들도 '위치 지정 요소'가 된다.
   z-index 없이 두면 뒤 셀의 흰 배경이 트리 순서상 나중에 칠해져 긴 바를 덮는다(첫 칸만 남음). */
.gg-bar { position: absolute; z-index: 1; top: 5px; left: 2px; height: 18px; border-radius: 4px; color: #fff; font-size: 10.5px; line-height: 18px; padding: 0 6px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; box-shadow: 0 1px 2px rgba(15, 23, 42, .18); }
.gg-bar.gg-bsub { top: 7px; height: 14px; line-height: 14px; font-size: 10px; border-radius: 4px; box-shadow: none; }
.gg-bar.gg-btmp { border: 1.5px dashed rgba(15, 23, 42, .45); box-shadow: none; color: #1f2937; text-shadow: 0 1px 0 rgba(255, 255, 255, .75); }

.gg-todayline { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--gg-today); opacity: .8; z-index: 1; pointer-events: none; }

.gg-rowact { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); display: flex; align-items: center; gap: 4px; opacity: 0; pointer-events: none; }
.gg-table tbody tr.gg-prow:hover .gg-rowact { opacity: 1; pointer-events: auto; }
.gg-rb { font: inherit; font-size: 10.5px; font-weight: 600; line-height: 1; padding: 4px 6px; border-radius: 4px; border: 1px solid var(--gg-line2); background: #fff; color: var(--gg-ink2); cursor: pointer; white-space: nowrap; }
.gg-rb.gg-rb-del { color: #b91c1c; border-color: #fecaca; background: #fef2f2; }
.gg-rb.gg-rb-win { color: #fff; background: #16a34a; border-color: #15803d; }

.gg-foot { padding: 7px 14px; font-size: 11px; color: var(--gg-ink3); border-top: 1px solid var(--gg-line); }
.gg-foot .gg-warn { color: #b45309; font-weight: 600; }

/* 임시 일정 추가 모달 */
.gg-modal { position: fixed; inset: 0; z-index: 600; background: rgba(15, 23, 42, .42); display: flex; align-items: center; justify-content: center; padding: 16px; }
.gg-mbox { background: #fff; border-radius: 12px; width: 100%; max-width: 460px; box-shadow: 0 18px 44px rgba(15, 23, 42, .28); overflow: hidden; }
.gg-mhead { display: flex; align-items: center; justify-content: space-between; padding: 13px 16px; border-bottom: 1px solid var(--gg-line); font-size: 14px; font-weight: 700; }
.gg-mx { font: inherit; font-size: 14px; line-height: 1; border: 0; background: none; color: var(--gg-ink3); cursor: pointer; padding: 4px 6px; border-radius: 4px; }
.gg-mbody { padding: 14px 16px; display: flex; flex-direction: column; gap: 11px; }
.gg-f { display: flex; flex-direction: column; gap: 4px; flex: 1 1 0; min-width: 0; }
.gg-f > span { font-size: 11.5px; color: var(--gg-ink2); font-weight: 600; }
.gg-f > span b { color: #dc2626; }
.gg-f input { font: inherit; font-size: 13px; color: var(--gg-ink); border: 1px solid var(--gg-line2); border-radius: 8px; padding: 7px 9px; background: #fff; width: 100%; min-width: 0; }
.gg-frow { display: flex; gap: 10px; }
.gg-err { margin: 0; font-size: 11.5px; color: #b91c1c; font-weight: 600; }
.gg-mfoot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--gg-line); background: var(--gg-soft); }
.gg-hide { display: none !important; }

/* ⚠ 모바일 광역 table 규칙 예외 — 아래 둘이 간트 매트릭스를 부순다:
     style.css @media(max-width:768px)          table{display:block!important}
     compact-sidebar.css @media(max-width:900px) .content-area table tr{display:table;table-layout:fixed}
   후자는 tr 을 독립 표로 만들어 colgroup 을 무력화(열 붕괴)시킨다.
   estimate-naesu.js(.naesu-table) 선례대로 900px 범위에서 통째로 되돌린다.
   ★ 이 블록은 로드 순서상 compact-sidebar.css 보다 앞서므로 !important 가 필수. */
@media (max-width: 900px) {
    .content-area table.gg-table, table.gg-table {
        display: table !important; overflow: visible !important;
        max-width: none !important; table-layout: fixed !important;
    }
    .content-area table.gg-table thead, table.gg-table thead {
        display: table-header-group !important; width: auto !important; table-layout: auto !important;
    }
    .content-area table.gg-table tbody, table.gg-table tbody {
        display: table-row-group !important; width: auto !important; table-layout: auto !important;
    }
    .content-area table.gg-table tr, table.gg-table tr {
        display: table-row !important; width: auto !important; table-layout: auto !important;
    }
    .content-area table.gg-table th, .content-area table.gg-table td,
    table.gg-table th, table.gg-table td { display: table-cell !important; }
}

/* 전사 일정 ↔ 통합 캘린더 보기 토글 (사이드바 탭 1개로 통합하며 추가) */
.gg-viewtoggle { display: inline-flex; border: 1px solid var(--gg-line2, #cbd5e1); border-radius: 8px; overflow: hidden; background: #fff; }
.gg-vt { font: inherit; font-size: 12px; font-weight: 600; color: #475569; background: #fff; border: 0; padding: 5px 12px; cursor: pointer; }
.gg-vt + .gg-vt { border-left: 1px solid var(--gg-line2, #cbd5e1); }
.gg-vt:hover:not(:disabled) { background: #f1f5f9; color: #0f172a; }
.gg-vt.gg-vt-on { background: #2563eb; color: #fff; cursor: default; }

/* 전사 일정 — WBS 단계 표시 체크박스 */
.gg-chkwrap { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: #475569; cursor: pointer; user-select: none; }
.gg-chkwrap input { width: 15px; height: 15px; accent-color: #2563eb; cursor: pointer; }

/* 홈 "전사 일정 요약" 위젯 — 행/바 높이 축약 */
.gg-sumtitle { font-size: 13px; font-weight: 800; color: #0f172a; }
.gg-compact .gg-bar-top { padding: 0 0 10px; border-bottom: 1px solid var(--gg-line, #e2e8f0); }
.gg-compact .gg-scroll, .gg-scroll-sum { max-height: 300px; min-height: 0; }
.gg-compact .gg-table tbody tr { height: 22px; }
.gg-compact .gg-table thead tr.gg-r1 th { height: 22px; }
.gg-compact .gg-table thead tr.gg-r2 th { height: 20px; }
.gg-compact .gg-table thead th.gg-dnum { font-size: 9px; }

.gg-compact .gg-bar { top: 3px; height: 15px; line-height: 15px; font-size: 9.5px; padding: 0 4px; }
.gg-compact .gg-table tbody td.gg-lft { font-size: 11.5px; }
.gg-compact .gg-empty { padding: 20px 12px; font-size: 12px; }
/* ⚠ 위 .gg-compact 폰트 규칙이 .gg-c-date(11px)와 명시도 동률이라 나중 선언이 이긴다.
   날짜가 "2026-07-…"로 잘리지 않게 요약에서는 한 단계 더 줄인다. */
.gg-compact .gg-table tbody td.gg-lft.gg-c-date { font-size: 10.5px; padding: 0 4px; }

/* ═══ 🗓 전사 일정 — 레드팀 수정 배치 (2026-07-28) ═══ */

/* M7. 임시 행 액션 버튼이 hover 전용이면 터치 기기에서 영영 안 보인다.
   ⚠ display:none 으로 숨기면 :focus-within 이 **원리상 절대 발동하지 않는다** —
   display:none 요소는 포커스를 받을 수 없어서 키보드로는 영영 도달 못 한다(실측: activeElement=false).
   그래서 opacity+pointer-events 로 숨긴다(레이아웃은 absolute 라 영향 없음, 포커스는 살아 있음). */
@media (hover: none) {
    .gg-rowact { opacity: 1; pointer-events: auto; }
}
.gg-table tbody tr.gg-prow:focus-within .gg-rowact { opacity: 1; pointer-events: auto; }
.gg-li .gg-rowact { opacity: 1; pointer-events: auto; }

/* P3. 접을 게 있을 때만 클릭 커서
   ⚠ 위쪽 `.gg-table tbody tr.gg-prow td.gg-lft { ... cursor: pointer }`(0,3,3)가 td 를 직접 노려서
   tr 단위 규칙으로는 못 이긴다 → 같은 td 셀렉터로 되돌린 뒤 clickable 일 때만 pointer. */
.gg-table tbody tr.gg-prow td.gg-lft { cursor: default; }
.gg-table tbody tr.gg-prow.gg-clickable td.gg-lft { cursor: pointer; }

/* D7. 수주 확정됐지만 저장은 안 된 임시 행 / 요약 헤더 미저장 뱃지 */
.gg-badge-won { display: inline-block; vertical-align: middle; margin-left: 6px; font-size: 10px; font-weight: 700; color: #166534; background: #dcfce7; border: 1px solid #86efac; border-radius: 4px; padding: 2px 7px; line-height: 1.3; }
.gg-badge-unsaved { display: inline-block; font-size: 10px; font-weight: 700; color: #9a3412; background: #ffedd5; border: 1px solid #fdba74; border-radius: 9999px; padding: 2px 7px; }

/* 주 단위 컬럼(홈 요약) — 라벨이 "M/D" 라 일 단위보다 폭이 넓다 */
.gg-table thead th.gg-wcol { font-size: 9.5px; letter-spacing: -0.3px; }

/* B2. 리스트 모드 — 좁은 화면에서 표 대신. 고정열 746px 라 375px 화면엔 바 자리가 0px 였다. */
.gg-list { display: flex; flex-direction: column; }
.gg-li {
    display: flex; align-items: center; gap: 8px;
    padding: 9px 12px; border-bottom: 1px solid var(--gg-line, #e2e8f0);
    font-size: 12.5px; min-height: 42px;
}
.gg-li:last-child { border-bottom: 0; }
.gg-li-sub { padding-left: 30px; background: #fbfcfe; font-size: 11.5px; }
.gg-li-dot { width: 10px; height: 10px; border-radius: 4px; flex-shrink: 0; }
.gg-li-dot-sub { width: 7px; height: 7px; }
.gg-li-dday {
    flex-shrink: 0; min-width: 46px; text-align: center;
    font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums;
    color: #475569; background: #f1f5f9; border-radius: 4px; padding: 2px 5px;
}
.gg-li-dday.gg-li-live { color: #166534; background: #dcfce7; }
.gg-li-dday.gg-li-dday0 { color: #fff; background: #dc2626; }
.gg-li-mid { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px; }
.gg-li-nm { font-weight: 700; color: #0f172a; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gg-li-cl { color: #64748b; font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex-shrink: 0; max-width: 40%; }
.gg-li-date { flex-shrink: 0; font-size: 11px; color: #64748b; font-variant-numeric: tabular-nums; }
.gg-li .gg-rowact { position: static; transform: none; display: flex; flex-shrink: 0; opacity: 1; pointer-events: auto; }

/* D4. ≤768 광역 `th,td{...!important}` 에 지지 않도록 간트 셀 규칙에 !important
   (naesu 선례) — 표 모드가 태블릿 폭(컨테이너 1000px↑)에서 쓰일 때 대비 */
@media (max-width: 768px) {
    .gg-table tbody td.gg-lft { padding: 0 7px !important; font-size: 12px !important; }
    .gg-table tbody td.gg-lft.gg-c-date,
    .gg-table tbody td.gg-lft.gg-c-days { font-size: 11px !important; }
    .gg-table thead th { font-size: 11.5px !important; padding: 0 !important; }
    .gg-table thead th.gg-dnum { font-size: 10.5px !important; padding: 0 !important; }
    .gg-table td.gg-day { padding: 0 !important; }
}

/* 배치 A — 임시 일정 실저장: '저장됨' 상태 표기 (경고 톤이 아니라 안내 톤) */
.gg-note.gg-note-ok { color: #166534; background: #dcfce7; border-color: #86efac; }
.gg-foot .gg-ok { color: #15803d; font-weight: 600; }

/* ═══ 배치 B — 데이터 규율 (기간 미입력 안내 · 휴가 그룹 · 이름 링크 · 지난 프로젝트) ═══ */

/* B-2. 기간 미입력 안내 — 왜 표에 없는지 화면이 스스로 설명 */
.gg-noperiod {
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
    padding: 9px 14px; border-top: 1px solid var(--gg-line, #e2e8f0);
    background: #fffbeb; font-size: 11.5px;
}
.gg-np-head { font-weight: 800; color: #92400e; flex-shrink: 0; }
.gg-np-names { color: #78350f; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60%; }
.gg-np-hint { color: #a16207; }
.gg-badge-noperiod {
    display: inline-block; font-size: 10px; font-weight: 700; color: #92400e;
    background: #fef3c7; border: 1px solid #fcd34d; border-radius: 9999px; padding: 2px 7px;
}

/* B-5. 프로젝트명 링크 (실프로젝트만) */
.gg-table td.gg-c-name .gg-nm-link { cursor: pointer; }
.gg-table td.gg-c-name .gg-nm-link:hover { text-decoration: underline; color: #1d4ed8; }
.gg-table td.gg-c-name .gg-nm-link:focus-visible { outline: 2px solid #93c5fd; outline-offset: 1px; border-radius: 2px; }
.gg-li.gg-li-nav { cursor: pointer; }
.gg-li.gg-li-nav:hover { background: #f8fafc; }
.gg-li.gg-li-nav:hover .gg-li-nm { text-decoration: underline; color: #1d4ed8; }

/* B-6. 각주(중립 톤 — 경고가 아니라 상태 안내) */
.gg-foot .gg-muted { color: #64748b; font-weight: 600; }

/* ═══ 배치 C — 간트 인라인 편집 (기간 · WBS 작업) ═══ */
.gg-table tbody td.gg-lft.gg-editable { cursor: pointer; }
.gg-table tbody td.gg-lft.gg-editable:hover { background: #eff6ff; box-shadow: inset 0 0 0 1px #bfdbfe; }
.gg-inline-date, .gg-inline-task {
    font: inherit; font-size: 11px; padding: 2px 4px; width: 100%;
    border: 1px solid #60a5fa; border-radius: 4px; outline: none; box-sizing: border-box;
}
.gg-inline-task { min-width: 120px; }
/* '＋ 작업 추가' 행 — 편집 중엔 입력들이 가로로 늘어선다 */
.gg-table tbody tr.gg-addrow td.gg-c-name {
    display: flex; align-items: center; gap: 6px; padding: 0 7px; overflow: visible;
}
.gg-table tbody tr.gg-addrow td.gg-c-name .gg-inline-date { width: 120px; flex: 0 0 auto; }
.gg-table tbody tr.gg-addrow td.gg-c-name .gg-inline-task { flex: 1 1 auto; }
.gg-addbtn {
    font: inherit; font-size: 11px; font-weight: 700; color: #2563eb;
    background: none; border: 1px dashed #93c5fd; border-radius: 4px;
    padding: 2px 8px; cursor: pointer;
}
.gg-addbtn:hover { background: #eff6ff; }
/* 하위 작업 행의 ✕ 는 이름 셀 안 — 위치 기준을 위해 셀을 relative 로 두지 않고
   .gg-rowact 의 absolute 가 sticky 셀(=위치 지정 요소)을 기준으로 잡힌다 */
.gg-table tbody tr.gg-srow:hover .gg-rowact,
.gg-table tbody tr.gg-srow:focus-within .gg-rowact { opacity: 1; pointer-events: auto; }

/* ═══ 홈 요약 스케일 게이지 [주|월|년] ═══ */
.gg-scalegauge {
    display: inline-flex; border: 1px solid var(--gg-line2, #cbd5e1);
    border-radius: 8px; overflow: hidden; background: #fff; flex-shrink: 0;
}
.gg-sc {
    font: inherit; font-size: 11.5px; font-weight: 700; color: #64748b;
    background: #fff; border: 0; padding: 4px 11px; cursor: pointer; line-height: 1.4;
}
.gg-sc + .gg-sc { border-left: 1px solid var(--gg-line2, #cbd5e1); }
.gg-sc:hover:not(:disabled) { background: #f1f5f9; color: #0f172a; }
.gg-sc.gg-sc-on { background: #2563eb; color: #fff; cursor: default; }
/* 월/년 스케일 컬럼 — 라벨이 "M월" 이라 주 컬럼보다 여유가 있다 */
.gg-table thead th.gg-mcol { font-size: 10px; letter-spacing: -0.2px; }

/* C6. 프로젝트명 ✎ 편집 아이콘 (이름 클릭=이동이므로 편집은 별도 진입점) */
.gg-pen {
    font: inherit; font-size: 10px; line-height: 1; margin-left: 5px;
    border: 0; background: none; color: #64748b; cursor: pointer;
    padding: 2px 3px; border-radius: 3px; opacity: 0; vertical-align: middle;
}
.gg-table tbody tr.gg-prow:hover .gg-pen,
.gg-table tbody tr.gg-prow:focus-within .gg-pen { opacity: 1; }
.gg-pen:hover { background: #e0e7ff; color: #1d4ed8; }
@media (hover: none) { .gg-pen { opacity: 1; } }
/* 견적이 원본인 예산 셀 — 편집 불가, 이동만 */
.gg-table tbody td.gg-lft.gg-locked { cursor: help; }
.gg-table tbody td.gg-lft.gg-locked:hover { background: #fef9c3; }

/* C8. 확정 ↔ 임시 구분 행 (클릭 무동작 — 순수 라벨) */
.gg-table tbody tr.gg-divrow td {
    background: #f8fafc; border-bottom: 1px solid var(--gg-line2, #cbd5e1);
    height: 22px; padding: 0; cursor: default;
}
.gg-divlabel {
    position: sticky; left: 8px;      /* 가로 스크롤 중에도 라벨이 보이게 */
    display: inline-block; font-size: 10.5px; font-weight: 700;
    color: #64748b; letter-spacing: 0.02em; white-space: nowrap;
}
.gg-lidiv {
    padding: 7px 12px; font-size: 10.5px; font-weight: 700; color: #64748b;
    background: #f8fafc; border-bottom: 1px solid var(--gg-line, #e2e8f0);
}

/* ═══ 배치 D — 폴리시 (빈 데이터 어포던스 · 시각 완성도 · 편집 발견성) ═══ */

/* D-1a. 빈 편집 가능 셀 → "＋ 항목" 어포던스 (버튼처럼 무겁지 않게) */
/* 대비: #b6c0cd 는 흰 배경에서 약 2.2:1 로 흐릿해 '비어 있음'조차 안 읽힌다 → 한 단계 진하게 */
.gg-ph {
    color: #64748b; font-weight: 600; font-size: 11px;
    border-bottom: 1px dashed #cbd5e1; padding-bottom: 1px;
}
.gg-table tbody td.gg-lft:hover .gg-ph { color: #2563eb; border-bottom-color: #93c5fd; }

/* D-2a. 빗금(임시) 바 위 라벨 — 반투명 흰 pill 로 대비 확보 */
.gg-barlabel {
    background: rgba(255, 255, 255, .85); color: #1f2937;
    border-radius: 3px; padding: 0 4px; font-weight: 700;
}
.gg-bar.gg-btmp { text-shadow: none; }        /* pill 이 대비를 맡으므로 그림자 불필요 */

/* D-2b. 범례 — 상태만 (프로젝트 색 나열 제거) */
.gg-sw-np {
    background: #fef3c7; border: 1px solid #fcd34d;
}

/* D-2c. 표 톤 — 행 경계선 옅게 통일 */
.gg-table tbody td { border-bottom-color: #eef2f6; }
.gg-table tbody tr.gg-prow td { border-bottom-color: #e2e8f0; }
.gg-legend { color: #64748b; }
.gg-foot { color: #64748b; }

/* D-3a. 편집 가능 셀 — hover/focus 시 ✎ 마이크로 아이콘 */
.gg-cellpen {
    position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
    font-size: 9px; color: #64748b; opacity: 0; pointer-events: none;
}
/* ⚠ 여기에 position:relative 를 주면 안 된다 — `.gg-table .gg-lft{position:sticky}`(0,2,1)보다
   명시도가 높아(0,3,2) 좌측 고정이 풀린다(이 파일에 이미 기록된 함정의 재발).
   sticky 자체가 위치 지정 요소라 ✎ 의 absolute 기준으로 충분하다. */
.gg-table tbody td.gg-lft.gg-editable { padding-right: 14px; }
.gg-table tbody tr:hover td.gg-lft.gg-editable .gg-cellpen,
.gg-table tbody td.gg-lft.gg-editable:focus-within .gg-cellpen { opacity: 1; }
@media (hover: none) { .gg-cellpen { opacity: .55; } }

/* ═══ 배치 E — '📁 기타 과업' 버킷 그룹 ═══ */
/* 일반 프로젝트 행보다 한 톤 낮게 — 묶음이라 개별 프로젝트와 같은 무게로 보이면 안 된다 */
.gg-table tbody tr.gg-bkrow td.gg-lft { background: #f1f5f9; color: var(--gg-ink2, #475569); }
.gg-table tbody tr.gg-bkrow:hover td.gg-lft { background: #e2e8f0; }
.gg-bkicon { display: inline-block; margin-right: 4px; vertical-align: middle; font-size: 11px; }
.gg-bar.gg-bbk { opacity: .55; }
.gg-lidiv.gg-libk { display: flex; align-items: center; gap: 4px; }
.gg-lidiv.gg-libk.gg-libk-on { cursor: pointer; }
.gg-lidiv.gg-libk.gg-libk-on:hover { background: #eef2f6; }

/* ═══ 배치 F — 수주 전 '제안 중' 표시 + 견적 작성 전환 ═══ */
/* 임시(주황)와 구분되는 보라 톤 — 같은 색이면 "저장 안 된 임시"와 혼동된다 */
.gg-badge-prop {
    display: inline-block; vertical-align: middle; margin-left: 6px;
    font-size: 10px; font-weight: 700; color: #6d28d9; background: #ede9fe;
    border: 1px solid #c4b5fd; border-radius: 4px; padding: 2px 7px; line-height: 1.3;
}
.gg-rb.gg-rb-quote { color: #4338ca; background: #eef2ff; border-color: #c7d2fe; }
.gg-rb.gg-rb-quote:disabled { color: #64748b; background: #f8fafc; border-color: #e2e8f0; cursor: not-allowed; }

/* ═══════════════════════════════════════════════════════
   💬 메신저 — 4열 셸 (msgr-shell.js)
   Phase 1: 레이아웃. 전 클래스 msgr- 프리픽스 + .msgr-root 스코프로
   OS 의 .btn/.modal/.toast/.meta/.primary 등과 충돌 회피.
   ⚠ 새 CSS 파일을 만들지 않고 여기 붙이는 이유: sw.js PRECACHE 동기화 대상이
     index.html 의 JS 목록뿐이라 CSS 파일 추가는 캐시 누락을 만든다(gg- 선례).
   ═══════════════════════════════════════════════════════ */
.msgr-phase {
    font-size: 11px; color: var(--m-warn); background: var(--m-warn-tint-2); border: 1px solid var(--m-warn-line);
    border-radius: 6px; padding: 5px 10px; margin: 0 0 8px;
}
/* 📲 설치 유도 배너 — 거래처 화면(.installbar)과 **같은 톤**. 두 화면이 같은 제품으로
   보여야 한다. 비어 있으면(설치 불가·닫음) 자식이 없어 자리도 안 먹는다(:empty). */
.msgr-installbar {
    display: flex; align-items: center; gap: 10px; padding: 9px 14px; margin: 0 0 8px;
    background: var(--m-brand-tint); border: 1px solid var(--m-brand-line); border-radius: 8px;
}
.msgr-installbar:empty { display: none; }
/* 🖼 방 아이콘 — 이미지가 있으면 사진, 없으면 색 이니셜. **자리는 항상 같은 크기**라
   방마다 목록 정렬이 흔들리지 않는다. */
.msgr-roomav { box-shadow: inset 0 0 0 100px var(--m-avatar-shade);
    flex: 0 0 34px; width: 34px; height: 34px; border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden; color: var(--m-on-avatar); font-weight: 800; font-size: var(--m-meta);
}
.msgr-roomav img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 🎯 «설치하러 왔다»(?install=1) — 자동으로 눌러 줄 수 없으니(제스처 필요) 눈에 띄게 한다 */
.msgr-installbar.is-cta { border-color: var(--m-brand); box-shadow: 0 0 0 3px var(--m-brand-ring); }
.msgr-installbar.is-cta .msgr-ibgo { animation: msgr-ctapulse 1.4s ease-in-out 3; }
@keyframes msgr-ctapulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }

/* ℹ️ 설치를 못 하는 사유를 적는 상태 — 권유가 아니라 설명이므로 톤을 낮춘다 */
.msgr-installbar.is-muted { background: var(--m-canvas); border-color: var(--m-hairline); }
.msgr-installbar.is-muted .msgr-ibtxt { color: var(--m-muted); font-weight: 500; }
.msgr-installbar.is-muted .msgr-ibx { color: var(--m-muted); }
.msgr-ibic { flex: 0 0 auto; font-size: 17px; line-height: 1; }
.msgr-ibtxt { flex: 1 1 auto; font-size: var(--m-badge); color: var(--m-brand); font-weight: 600; line-height: 1.45; }
.msgr-ibgo {
    flex: 0 0 auto; border: 0; border-radius: 999px; padding: 6px 14px; cursor: pointer;
    background: var(--m-brand); color: var(--m-on-brand); font-size: var(--m-badge); font-weight: 700; white-space: nowrap;
    transition: all .12s;
}
.msgr-ibgo:hover { background: var(--m-brand-strong); }
.msgr-ibx {
    flex: 0 0 auto; border: 0; background: transparent; color: var(--m-brand); cursor: pointer;
    font-size: var(--m-meta); padding: 2px 4px; transition: all .12s;
}
.msgr-ibx:hover { color: var(--m-brand); }
/* ═══ 💬 메신저 디자인 토큰 (2026-08-06) ═══
   ⚠ 이 파일에 메신저 규칙을 **덧붙이지 말 것** — 원본 규칙을 고칠 것.
   스크린샷을 받을 때마다 말미에 override 블록을 쌓은 결과 글자 크기가 14종,
   모서리가 14종이 됐고 그게 '투박함'의 정체였다(실측). 값이 필요하면 토큰을 늘린다. */
html.msgr-popout-root, body.msgr-view,
.msgr-root, .msgr-installbar, .msgr-ov, .msgr-sheetov, .msgr-emojipop, .msgr-menu, .msgr-lightbox, .mr-back, .msgr-schedback, .msgr-video-viewer {
    --m-brand: #2563eb;
    --m-tool-purple: #7c3aed;
    --m-tool-purple-bg: #f3e8ff;
    --m-brand-strong: #1d4ed8;
    --m-on-brand: #fff;
    --m-brand-tint: #eff6ff;
    --m-brand-tint-2: #dbeafe;
    --m-brand-line: #bfdbfe;
    --m-hover-fill: #bfdbfe;
    --m-on-secret-head: #dbeafe;
    --m-mine-link: #dbeafe;
    --m-bubble-mine: #2563eb;
    --m-on-bubble-mine: #fff;
    --m-canvas: #f8fafc;
    --m-surface: #fff;
    --m-surface-2: #f1f5f9;
    --m-hairline: #e2e8f0;
    --m-ink: #0f172a;
    --m-ink-tertiary: #1e293b;
    --m-lightbox-ink: #e2e8f0;
    --m-self-avatar: #0f172a;
    --m-ink-2: #475569;
    --m-muted: #64748b;
    --m-brand-ring: rgba(37, 99, 235, .15);
    --m-brand-overlay: rgba(37, 99, 235, .08);
    --m-brand-focus: rgba(37, 99, 235, .35);
    --m-ink-secondary: #334155;
    --m-ink-meta: #94a3b8;
    --m-danger: #b91c1c;
    --m-danger-strong: #991b1b;
    --m-danger-action: #dc2626;
    --m-danger-tint: #fef2f2;
    --m-danger-line: #fecaca;
    --m-danger-line-strong: #fca5a5;
    --m-warn: #92400e;
    --m-warn-strong: #78350f;
    --m-warn-action: #b45309;
    --m-warn-tint: #fffbeb;
    --m-warn-tint-2: #fef3c7;
    --m-warn-line: #fde68a;
    --m-warn-line-strong: #fcd34d;
    --m-ok: #047857;
    --m-ok-action: #059669;
    --m-ok-strong: #166534;
    --m-ok-phone: #15803d;
    --m-ok-tint: #f0fdf4;
    --m-ok-tint-2: #dcfce7;
    --m-ok-tint-3: #ecfdf5;
    --m-ok-line: #bbf7d0;
    --m-ok-line-strong: #a7f3d0;
    --m-info: #0369a1;
    --m-info-tint: #e0f2fe;
    --m-info-accent: #93c5fd;
    --m-hot: #c2410c;
    --m-hot-tint: #ffedd5;
    --m-hot-tint-2: #fff7ed;
    --m-hot-accent: #f97316;
    --m-hot-gradient: #fb923c;
    --m-warm-accent: #f59e0b;
    --m-online: #22c55e;
    --m-online-strong: #16a34a;
    --m-placeholder: #eef2f7;
    --m-line-strong: #cbd5e1;
    --m-highlight: #fef9c3;
    --m-badge: #ef4444;
    --m-on-badge: #fff;
    --m-swipe-read: #64748b;
    --m-swipe-muted: #a16207;
    --m-swipe-hide: #334155;
    --m-on-swipe: #fff;
    --m-toast: #18181b;
    --m-on-toast: white;
    --m-surface-raised: #1e293b;
    --m-on-avatar: #fff;
    --m-avatar-shade: rgba(0, 0, 0, 0);
    --m-mention-mine: rgba(255, 255, 255, .22);
    --m-glass-bg: rgba(255, 255, 255, .72);
    --m-quote-line: #a5b4fc;
    --m-quote-label: #6366f1;
    --m-reaction-label: #4338ca;
    --m-install-line: #e9d5ff;
    --m-video-ink: #172033;
    --m-video-stage: #172033;
    --m-video-stage-ink: #e2e8f0;
    --m-video-play-line: #ffffff80;
    --m-video-play-bg: #0f172acc;
    --m-video-scrim: #020617d9;
    --m-video-dialog: #0f172a;
    --m-video-on-dialog: #f8fafc;
    --m-video-player: #000;
    --m-video-close: #1e293b;
    --m-video-line: #64748b;
    --m-video-download: #334155;
    --m-video-on-control: #fff;
    --m-video-focus: #93c5fd;
    --m-video-dialog-line: #475569;
    --m-shadow-xs: rgba(15, 23, 42, .06);
    --m-shadow-sm: rgba(15, 23, 42, .10);
    --m-shadow-md: rgba(15, 23, 42, .12);
    --m-shadow-lg: rgba(15, 23, 42, .16);
    --m-shadow-xl: rgba(15, 23, 42, .18);
    --m-shadow-sheet: rgba(15, 23, 42, .2);
    --m-shadow-float: rgba(15, 23, 42, .25);
    --m-shadow-dialog: rgba(15, 23, 42, .28);
    --m-shadow-segment: rgb(0 0 0 / .12);
    --m-scrim: rgba(15, 23, 42, .28);
    --m-scrim-sheet: rgba(15, 23, 42, .22);
    --m-scrim-schedule: rgba(15, 23, 42, .45);
    --m-scrim-guest: rgba(15, 23, 42, .5);
    --m-scrim-image: rgba(15, 23, 42, .88);
}
html[data-theme="dark"].msgr-popout-root,
html[data-theme="dark"] :is(body.msgr-view,.msgr-root, .msgr-installbar, .msgr-ov, .msgr-sheetov, .msgr-emojipop, .msgr-menu, .msgr-lightbox, .mr-back, .msgr-schedback, .msgr-video-viewer) {
    --m-identity-ink: #cbd5e1;
    --m-dim-opacity: 1;
    --m-disabled-ink: #a1b0c4;
    --m-brand: #60a5fa;
    --m-tool-purple: #c4b5fd;
    --m-tool-purple-bg: #2e1065;
    --m-brand-strong: #93c5fd;
    --m-on-brand: #0b1220;
    --m-brand-tint: #172554;
    --m-brand-tint-2: #1e3a8a;
    --m-brand-line: #1e40af;
    --m-hover-fill: #203563;
    --m-on-secret-head: #0b1220;
    --m-mine-link: #93c5fd;
    --m-dot-min-opacity: .8;
    --m-bubble-mine: #1d4ed8;
    --m-bubble-mine-desktop: #1e3a5f;
    --m-on-bubble-mine-desktop: #e2e8f0;
    --m-on-bubble-mine: #f8fafc;
    --m-canvas: #0b1220;
    --m-surface: #111827;
    --m-surface-2: #1e293b;
    --m-hairline: #334155;
    --m-ink: #f1f5f9;
    --m-ink-tertiary: #cbd5e1;
    --m-lightbox-ink: #e2e8f0;
    --m-self-avatar: #334155;
    --m-ink-2: #cbd5e1;
    --m-muted: #a1b0c4;
    --m-brand-ring: rgba(96,165,250,.25);
    --m-brand-overlay: rgba(96,165,250,.12);
    --m-brand-focus: rgba(96,165,250,.45);
    --m-ink-secondary: #cbd5e1;
    --m-ink-meta: #a1b0c4;
    --m-danger: #fca5a5;
    --m-danger-strong: #fca5a5;
    --m-danger-action: #fca5a5;
    --m-danger-tint: #450a0a;
    --m-danger-line: #7f1d1d;
    --m-danger-line-strong: #991b1b;
    --m-warn: #fcd34d;
    --m-warn-strong: #fcd34d;
    --m-warn-action: #fcd34d;
    --m-warn-tint: #422006;
    --m-warn-tint-2: #422006;
    --m-warn-line: #854d0e;
    --m-warn-line-strong: #854d0e;
    --m-ok: #86efac;
    --m-ok-action: #86efac;
    --m-ok-strong: #86efac;
    --m-ok-phone: #86efac;
    --m-ok-tint: #052e16;
    --m-ok-tint-2: #052e16;
    --m-ok-tint-3: #052e16;
    --m-ok-line: #166534;
    --m-ok-line-strong: #166534;
    --m-info: #7dd3fc;
    --m-info-tint: #082f49;
    --m-info-accent: #7dd3fc;
    --m-hot: #fdba74;
    --m-hot-tint: #431407;
    --m-hot-tint-2: #431407;
    --m-hot-accent: #f97316;
    --m-hot-gradient: #fb923c;
    --m-warm-accent: #f59e0b;
    --m-online: #22c55e;
    --m-online-strong: #16a34a;
    --m-placeholder: #1e293b;
    --m-line-strong: #475569;
    --m-highlight: #422006;
    --m-badge: #991b1b;
    --m-on-badge: #fff;
    --m-swipe-read: #475569;
    --m-swipe-muted: #854d0e;
    --m-swipe-hide: #334155;
    --m-on-swipe: #fff;
    --m-toast: #1e293b;
    --m-on-toast: white;
    --m-surface-raised: #334155;
    --m-on-avatar: #fff;
    --m-avatar-shade: rgba(0, 0, 0, .5);
    --m-mention-mine: rgba(255, 255, 255, .08);
    --m-glass-bg: rgba(17,24,39,.88);
    --m-quote-line: #60a5fa;
    --m-quote-label: #93c5fd;
    --m-reaction-label: #93c5fd;
    --m-install-line: #1e40af;
    --m-video-ink: #f1f5f9;
    --m-video-stage: #0b1220;
    --m-video-stage-ink: #e2e8f0;
    --m-video-play-line: #ffffff80;
    --m-video-play-bg: #0f172acc;
    --m-video-scrim: #020617d9;
    --m-video-dialog: #0f172a;
    --m-video-on-dialog: #f8fafc;
    --m-video-player: #0b1220;
    --m-video-close: #1e293b;
    --m-video-line: #64748b;
    --m-video-download: #334155;
    --m-video-on-control: #fff;
    --m-video-focus: #93c5fd;
    --m-video-dialog-line: #475569;
    --m-shadow-xs: rgba(2, 6, 23, .45);
    --m-shadow-sm: rgba(2, 6, 23, .45);
    --m-shadow-md: rgba(2, 6, 23, .45);
    --m-shadow-lg: rgba(2, 6, 23, .45);
    --m-shadow-xl: rgba(2, 6, 23, .45);
    --m-shadow-sheet: rgba(2, 6, 23, .45);
    --m-shadow-float: rgba(2, 6, 23, .45);
    --m-shadow-dialog: rgba(2, 6, 23, .45);
    --m-shadow-segment: rgba(2, 6, 23, .45);
    --m-scrim: rgba(2, 6, 23, .65);
    --m-scrim-sheet: rgba(2, 6, 23, .65);
    --m-scrim-schedule: rgba(2, 6, 23, .65);
    --m-scrim-guest: rgba(2, 6, 23, .65);
    --m-scrim-image: rgba(2, 6, 23, .88);
}
html.msgr-popout-root { color-scheme: light dark; }
html.msgr-popout-root[data-theme="light"] { color-scheme: light; }
html.msgr-popout-root[data-theme="dark"] { color-scheme: dark; }

/* 화면 밝기: PC의 설정 펼침과 폰 더 보기에서 같은 컨트롤을 쓴다. */
.msgr-theme-control { padding: 12px; color: var(--m-ink); font-size: var(--fs-base); }
.msgr-theme-control label { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.msgr-theme-control select { min-height: 44px; max-width: 100%; border: 1px solid var(--m-hairline); border-radius: 8px; padding: 8px; background: var(--m-surface); color: var(--m-ink); font: inherit; font-size: var(--fs-title); }
.msgr-theme-control p { margin: 4px 0 0; color: var(--m-danger); font-size: var(--fs-meta); }
.msgr-theme-control p:empty { display: none; }
.msgr-theme-menu { position: relative; flex: none; color: var(--m-ink-2); font-size: var(--fs-meta); }
.msgr-theme-menu summary { list-style: none; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.msgr-theme-menu summary::-webkit-details-marker { display: none; }
.msgr-theme-row { cursor: default; }
.msgr-theme-row .msgr-theme-control { flex: 1; padding: 0; }
.msgr-theme-row .msgr-theme-control select { min-height: 36px; padding: 4px 8px; font-size: var(--fs-base); }
.msgr-theme-menu > .msgr-theme-control { position: absolute; right: 0; top: 100%; z-index: 60; width: 290px; max-width: calc(100vw - 32px); background: var(--m-surface); border: 1px solid var(--m-hairline); border-radius: 12px; box-shadow: 0 8px 24px var(--m-shadow-lg); }
.msgr-native-theme-error { position: fixed; bottom: 12px; left: 12px; right: 12px; z-index: 10000; padding: 12px; background: var(--m-danger-tint); color: var(--m-danger); }
html.msgr-popout-root[data-theme="dark"] :is(.msgr-root, .msgr-ov, .msgr-sheetov, .msgr-schedback, .mr-back) :is(input, textarea, select) { color: var(--m-ink); }
html.msgr-popout-root[data-theme="dark"] :is(.msgr-root, .msgr-ov, .msgr-sheetov, .msgr-schedback, .mr-back) :is(input, textarea)::placeholder { color: var(--m-muted); opacity: 1; }
.msgr-root {
    /* 글자 크기는 앱 전체 5단계(style.css :root --fs-*, 2026-09-29 순서표 24단계)의 별칭 — 값은 거기 한 곳에서 바꾼다 */
    --m-base: var(--fs-base);    /* 셸 기본 14px */
    --m-body: var(--fs-body);    /* 대화 본문 15px — 여기가 제일 중요하다 */
    --m-title: var(--fs-title);  /* 패널 제목 16px */
    --m-name: var(--fs-base);    /* 사람 이름 14px */
    --m-meta: var(--fs-meta);    /* 시각·부가정보 12px */
    --m-badge: var(--fs-badge);  /* 배지 11.5px — 이보다 작으면 글자가 아니라 잡음이다 */
    --m-r1: 6px;       /* 배지·작은 칩 */
    --m-r2: 8px;       /* 파일칩·버튼 */
    --m-r3: 12px;      /* 카드·팝오버 */
}
/* ═══ 🫧 리퀴드 글래스 (2026-08-08) ═══
   ★ **떠 있는 면에만** 쓴다 — 하단 탭바 · 동작 시트 · ☰ 정보 시트 · 모달 넷.
     유리는 «뒤에 흐르는 것»이 있어야 유리로 읽힌다. 목록·말풍선에 깔면 뒤가 흰
     배경이라 그냥 흐린 회색이 되고, 보라 말풍선·🔒내부 블록처럼 **색으로 뜻을
     구분하던 것**이 한 겹 뒤로 밀려 죽는다.
   ⚠ 상단 탭바(`.msgr-tabbar`)에는 **안 건다** — `position` 이 없는 정적 flex 자식이라
     대화가 그 밑으로 흐르지 않는다(`.msgr-main` 이 column 이고 스크롤 영역은 그 *아래*).
     씌워 봐야 부모의 단색을 흐리는 것이라 보이는 변화가 0 이다. 띄우려면 sticky 로
     만드는 별개의 작업이 먼저다.
   🚨 값은 **토큰으로만** — 아래 두 폴백이 `--m-glass-bg` 하나만 덮어 전 면을 되돌린다.
     면마다 배경색을 직접 쓰면 폴백이 그만큼 갈라진다(이 파일이 겪은 그 퇴적층). */
.msgr-root, .msgr-ov, .msgr-sheetov {
    --m-glass: saturate(180%) blur(20px);
}
/* 유리를 못 그리는 브라우저에서 반투명만 남으면 **글자 뒤로 대화가 비쳐 못 읽는다** */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    :is(html.msgr-popout-root, body.msgr-view) :is(.msgr-root, .msgr-ov, .msgr-sheetov) { --m-glass-bg: var(--m-surface) !important; }
}
/* 투명 효과 줄이기를 켠 사용자 — 대비가 배경에 따라 변하는 걸 원치 않는다는 뜻이다 */
@media (prefers-reduced-transparency: reduce) {
    :is(html.msgr-popout-root, body.msgr-view) :is(.msgr-root, .msgr-ov, .msgr-sheetov) { --m-glass-bg: var(--m-surface) !important; }
}
.msgr-root {
    display: flex; align-items: stretch; gap: 0;
    /* ⚠ 첫 페인트용 **대략값**일 뿐 — 실제 높이는 msgr-shell.js `fitHeight()` 가
       visualViewport 를 실측해 인라인 !important 로 덮는다. 여기 상수를 조정해
       맞추려 하지 말 것: 기기·브라우저(아이폰 사파리 / 갤럭시 크롬 / 홈화면 PWA)마다
       주소창·하단바 높이가 달라 **맞는 상수가 존재하지 않는다**.
       ★ min-height 는 낮게 — 화면보다 크면 아래가 잘린다. */
    height: calc(100vh - 170px); min-height: 280px;
    border: 1px solid var(--m-hairline); border-radius: 12px; overflow: hidden;
    background: var(--m-surface); font-size: var(--m-base); color: var(--m-ink);
    position: relative;   /* 🏢 거래처 패널(absolute)의 기준 */
}
.msgr-root * { box-sizing: border-box; }

/* ⌨️ 포커스는 style.css의 공용 파란색을 유지한다. 입력부만 테두리 없는 textarea
   안쪽 대신 실제 입력 상자(inputwrap)에 링을 그려 겹친 사각 테두리를 없앤다. */

/* ✨ 전환 — 눌렀을 때 «뻣뻣하게 툭» 바뀌던 것을 짧게 이어 준다(120ms).
   ⚠ 길게 주면 느리게 느껴진다. 색·투명도만 — layout 속성엔 걸지 않는다(리플로우). */
.msgr-room, .msgr-btn, .msgr-homechip, .msgr-segbtn, .msgr-sidetab,
.msgr-reaction, .msgr-tool, .msgr-notibtn {
    transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}
/* ⓘ `prefers-reduced-motion` 과 스크롤바 스타일은 **여기서 만들지 않는다** —
   style.css:1479(모션 축소 전역) · style.css:1369(스크롤바 7px)이 이미 앱 전체를
   덮는다. 메신저만 다른 값을 두면 그게 «OS 안의 별도 프로그램»처럼 보이는 원인이다
   (2026-08-06 셋 다 검토·기각 — 포커스 링·모션·스크롤바). */
.msgr-railspacer { flex: 1 1 auto; }

/* ── 1) 아이콘 레일 ── */
/* 🧭 아이콘 레일 — 단독 앱(/msgr)에서는 **유일한 내비게이션**이라 그만큼의 대접이 필요하다
   (OS 안에서 곁다리로 있을 때 만든 치수를 그대로 쓰면 앱의 중심축이 곁다리로 보인다). */
body:not(.msgr-popout) .msgr-rail { display: none; }
.msgr-rail {
    width: 68px; flex: 0 0 68px; background: var(--m-surface); border-right: 1px solid var(--m-hairline);
    display: flex; flex-direction: column; align-items: center; padding: 12px 0 14px; gap: 4px;
}
.msgr-railbtn {
    position: relative;
    width: 56px; padding: 9px 0 8px; border: 0; background: transparent; border-radius: 12px;
    display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; color: var(--m-muted);
    transition: all .12s;   /* 앱 전역 관용구 — 없으면 hover 가 «툭» 바뀐다 */
}
.msgr-railbtn:hover { background: var(--m-brand-tint); color: var(--m-brand); }
.msgr-railbtn.is-active { background: var(--m-brand-tint); color: var(--m-brand); }
/* 활성 표시를 색만으로 하지 않는다 — 색각이상·저대비 화면에서 어느 쪽인지 안 보인다 */
.msgr-railbtn.is-active::before {
    content: ''; position: absolute; left: 0; width: 3px; height: 26px;
    border-radius: 0 999px 999px 0; background: var(--m-brand);
}
.msgr-railic { font-size: 19px; line-height: 1; }
.msgr-raillabel { font-size: var(--m-badge); font-weight: 700; letter-spacing: -.02em; }
.msgr-railme { position: relative; }
.msgr-av-rail { width: 32px; height: 32px; font-size: 11px; }

/* ── 아바타 공통 ── */
.msgr-av {
    width: 34px; height: 34px; flex: 0 0 34px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: var(--m-on-avatar); box-shadow: inset 0 0 0 100px var(--m-avatar-shade); font-size: 11px; font-weight: 800; letter-spacing: -.02em;
}
.msgr-av-sm { width: 28px; height: 28px; flex: 0 0 28px; font-size: 10px; }
.msgr-dot-online {
    position: absolute; right: -1px; bottom: -1px; width: 10px; height: 10px;
    border-radius: 50%; background: var(--m-online); border: 2px solid var(--m-surface);
}

/* ── 2) 대화 목록 ── */
.msgr-list {
    width: var(--msgr-list-w, 300px); flex: 0 0 var(--msgr-list-w, 300px); border-right: 1px solid var(--m-hairline);
    display: flex; flex-direction: column; background: var(--m-surface); min-height: 0;
}
.msgr-searchwrap { display: flex; gap: 6px; padding: 10px; border-bottom: 1px solid var(--m-surface-2); }
/* 🏢 회사 로고 — 이름 왼쪽 (2026-08-08). 데스크톱에서는 `.msgr-brand` 와 함께 숨는다(:3542).
   ⓘ `flex: none` 필수 — 안 주면 좁은 폭에서 로고가 먼저 찌그러진다(이름이 밀어낸다). */
.msgr-brandlogo { flex: none; width: 22px; height: 22px; border-radius: 6px; object-fit: cover; }
.msgr-search {
    flex: 1 1 auto; min-width: 0; height: 32px; border: 1px solid var(--m-hairline); border-radius: 8px;
    padding: 0 10px; font-size: var(--m-base); background: var(--m-canvas); outline: none;
}
.msgr-search:focus { border-color: var(--m-brand-line); background: var(--m-surface); }
.msgr-newbtn {
    width: 32px; height: 32px; flex: 0 0 32px; border: 0; border-radius: 8px;
    background: var(--m-brand); color: var(--m-on-brand); font-size: 17px; font-weight: 700; cursor: pointer; line-height: 1;
}
.msgr-fixed { padding: 6px; border-bottom: 1px solid var(--m-surface-2); }
.msgr-fixitem {
    width: 100%; display: flex; align-items: center; gap: 8px; padding: 6px 8px;
    border: 0; background: transparent; border-radius: 8px; cursor: pointer;
    font-size: 12px; color: var(--m-ink-secondary); text-align: left;
}
/* 터치 기기는 누른 뒤 hover 가 남는다(2026-11-01 사장님 «눌림 표시 계속됨») — 마우스 기기에서만 */
@media (hover: hover) { .msgr-fixitem:hover { background: var(--m-surface-2); } .msgr-fixitem:disabled:hover { background: transparent; } }
.msgr-fixitem:disabled { color: var(--m-disabled-ink, var(--m-ink-secondary)); opacity: var(--m-dim-opacity, .42); cursor: default; }
.msgr-fixitem.is-active { background: var(--m-brand-tint); color: var(--m-brand-strong); font-weight: 600; }
.msgr-fixic { font-size: 13px; }
.msgr-listscroll { flex: 1 1 auto; overflow-y: auto; min-height: 0; padding-bottom: 12px; }
.msgr-acchead {
    display: flex; align-items: center; gap: 6px; padding: 10px 12px 5px;
    font-size: 11px; font-weight: 800; color: var(--m-ink-2);
    position: sticky; top: 0; background: var(--m-surface); z-index: 1;
}
.msgr-accdot { width: 14px; height: 14px; border-radius: 6px; flex: 0 0 14px; }
.msgr-accic { font-size: 12px; }
.msgr-accname { letter-spacing: -.01em; }
.msgr-room {
    position: relative; width: calc(100% - 12px); margin: 1px 6px;
    border: 0; background: transparent; border-radius: 8px; cursor: pointer; text-align: left;
    /* 🖼 방 아이콘 + 제목/미리보기 — **아이콘이 두 줄을 함께 덮는다**(카톡·iMessage 구조).
       ⚠ 이 규칙을 **여기서** 고칠 것. 앞쪽에 `.msgr-room { display:flex }` 를 덧붙이면
         이 선언이 뒤에 있어 그대로 이긴다(2026-08-07 실제로 그렇게 만들었다가 잡음).
       📏 **왜 grid 인가** (2026-08-08 사장님 "조인트에 비해 우리 방은 너무 두꺼운것같음"):
         종전은 `flex-wrap` 이라 미리보기가 **아바타 아래로 줄바꿈**되고, 아바타에 가리지
         않으려고 `padding-left: 44px` 로 밀고 있었다. 그래서 높이가
         `여백 + 아바타(34) + 미리보기(15)` 로 쌓여 **77px**(실측) — 카톡 72·iMessage 76 보다
         두꺼웠다. 두 줄을 아바타 **오른쪽 한 칸**에 넣으면 아바타가 두 줄 안에 들어가
         `여백 + (제목+미리보기)` 만 남는다.
       ⓘ DOM 은 그대로다(아바타·제목·미리보기 3형제) — 자리만 grid 가 정한다.
         그래서 JS 렌더러를 한 글자도 안 고쳤다. */
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr);
    grid-template-areas: 'av top' 'av bot';
    align-items: center; gap: 0 10px;
}
.msgr-room > .msgr-roomav { grid-area: av; align-self: center; }
.msgr-room > .msgr-room-top { grid-area: top; min-width: 0; }
/* ⚠ 종전의 `padding-left: 44px` 는 아바타를 피하려던 것 — 이제 열이 나뉘어 필요 없다 */
.msgr-room > .msgr-room-bot { grid-area: bot; min-width: 0; }
.msgr-room:hover { background: var(--m-canvas); }
.msgr-room.is-active { background: var(--m-brand-tint); }
.msgr-room.is-active .msgr-room-title,
.msgr-room.is-active .msgr-room-last { color: var(--m-brand); }
.msgr-room.is-active .msgr-room-at,
.msgr-room.is-active .msgr-room-cnt { color: var(--m-brand); }
.msgr-room-top { display: flex; align-items: center; gap: 5px; }
.msgr-room-title {
    font-size: var(--m-name); font-weight: 600; color: var(--m-ink);
    flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msgr-room-cnt { font-size: var(--m-badge); color: var(--m-ink-meta); font-weight: 500; }
/* 거래처 이름보다 방 제목에 먼저 공간을 배정한다. 긴 제목도 행 안에서 말줄임한다. */
.msgr-room-name { display: flex; align-items: center; gap: 5px; flex: 1 1 auto; min-width: 0; }
.msgr-room-name .msgr-room-title { flex: 0 0 auto; max-width: 70%; }
.msgr-room-client {
    flex: 0 1 auto; min-width: 0; max-width: 90px;
    font-size: var(--m-badge); color: var(--m-ink-meta); font-weight: 500;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.msgr-room-lock { font-size: 9px; }
.msgr-room-at { margin-left: auto; font-size: var(--m-badge); color: var(--m-muted); white-space: nowrap; }
.msgr-room-bot { display: flex; align-items: center; gap: 6px; }
.msgr-room-last {
    flex: 1 1 auto; min-width: 0; font-size: var(--m-meta); color: var(--m-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msgr-room-by {
    flex: 0 0 auto; max-width: 62px; font-size: var(--m-meta); color: var(--m-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msgr-room-by::after { content: ':'; margin-left: 1px; }
.msgr-room.is-active .msgr-room-by { color: var(--m-brand); }
/* ★ 미읽음 점 — absolute 로 우측에 띄우면 '5분 전' 시각과 겹친다(실측). 행 흐름 안에 둔다. */
.msgr-unread {
    flex: 0 0 auto; color: var(--m-brand); font-size: 9px; line-height: 1; margin-left: 1px;
}
.msgr-room.is-active .msgr-unread { color: var(--m-brand); }

/* ── 3) 중앙 ── */
.msgr-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; background: var(--m-surface); }
.msgr-tabbar {
    /* 🚨 **여기에 `overflow-x` 를 두지 말 것** (2026-08-08 사장님 "이창이 사이드 스크롤이
       있을게 이유가 있나?"). 두 가지가 한꺼번에 잘못됐었다:
       ① **스크롤이 두 겹**이었다 — 자식 `.msgr-tabstrip` 이 이미 가로 스크롤을 담당한다.
          넘치는 건 탭 목록이지 탭바 전체가 아니다.
       ② 더 나쁜 건 **세로가 잘린 것**이다. CSS 명세상 한 축이 `visible` 이 아니면
          **다른 축도 `auto` 로 계산된다** — `overflow-x: auto` 하나가 세로 스크롤까지
          켜서 탭 글자 윗부분이 잘렸다(실측 `overflowY: auto`).
       ⓘ 가로로 미는 동작 자체는 남는다 — 아래 `.msgr-tabstrip` 이 그대로 한다. */
    display: flex; align-items: center; gap: 4px; padding: 8px 10px;
    border-bottom: 1px solid var(--m-hairline);
}
.msgr-tab {
    display: flex; align-items: center; gap: 5px; padding: 5px 10px; border: 1px solid transparent;
    background: transparent; border-radius: 8px; cursor: pointer; font-size: 12px; color: var(--m-ink-2);
    white-space: nowrap; font-weight: 600;
}
.msgr-tab:hover { background: var(--m-surface-2); }
.msgr-tab.is-active { background: var(--m-surface); border-color: var(--m-brand-tint-2); color: var(--m-ink); font-weight: 800; box-shadow: 0 1px 2px var(--m-shadow-xs); }
.msgr-tabdot { width: 12px; height: 12px; border-radius: 999px; flex: 0 0 12px; }
.msgr-tabbadge {
    min-width: 16px; height: 16px; border-radius: 8px; background: var(--m-brand-tint); color: var(--m-brand);
    font-size: var(--m-badge); font-weight: 800; display: flex; align-items: center; justify-content: center; padding: 0 4px;
}
.msgr-sidetoggle { border: 0; background: transparent; font-size: 15px; color: var(--m-muted); cursor: pointer; padding: 3px 6px; white-space: nowrap; flex: 0 0 auto; }   /* 2026-10-07: «요청»이 «요/청»으로 쪼개졌다 */

.msgr-msgs { flex: 1 1 auto; overflow-y: auto; min-height: 0; }
.msgr-daysep { display: flex; align-items: center; justify-content: center; margin: 14px 0 10px; }
.msgr-daysep span { font-size: var(--m-badge); color: var(--m-muted); background: var(--m-surface-2); border-radius: 8px; padding: 2px 10px; font-weight: 700; }
.msgr-msg { display: flex; }
.msgr-msgbody { flex: 1 1 auto; min-width: 0; max-width: 78%; }
.msgr-msghead { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.msgr-msgby { font-size: var(--m-name); font-weight: 700; color: var(--m-ink); }
.msgr-orgbadge { font-size: var(--m-meta); font-weight: 400; color: var(--m-muted); max-width: 12em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-guest {
    font-size: var(--m-badge); font-weight: 600; color: var(--m-ink-2); background: var(--m-surface-2);
    border-radius: var(--m-r1); padding: 1px 6px; white-space: nowrap;
}
.msgr-msgat { font-size: var(--m-meta); color: var(--m-muted); }
.msgr-msgtext {
    /* 💬 말풍선 — 거래처 화면(guest `.tx`)과 같은 모양. inline-block 이라
       내용만큼만 넓어진다(블록이면 짧은 «넵»도 컬럼 전체를 차지한다). */
    display: inline-block; max-width: 100%;
    background: var(--m-surface-2); border-radius: var(--m-r3); padding: 8px 12px;
    font-size: var(--m-body); line-height: 1.55; color: var(--m-ink); margin-top: 2px;
    white-space: pre-wrap; word-break: keep-all; overflow-wrap: anywhere;
}

/* 💬 내 메시지는 오른쪽 + 전용 말풍선 색 (2026-11-02 사장님 결정).
   uid로 판정하며, 넓은 PC의 시선 이동은 대화 내용 최대 820px로 제한한다. */
.msgr-msg.is-mine .msgr-msgtext { background: var(--m-bubble-mine); color: var(--m-on-bubble-mine); }
/* 파란 내 말풍선 안의 링크·멘션도 흰 글자로 — 파랑 위 파랑 글자는 안 읽힌다. */
.msgr-msg.is-mine .msgr-msgtext .msgr-link { color: var(--m-on-bubble-mine); text-decoration: underline; }
.msgr-msg.is-mine .msgr-msgtext .msgr-mention { background: var(--m-mention-mine); color: var(--m-on-bubble-mine); }
/* 🗑 삭제 자리표시는 말풍선이 아니다(빈 보라 상자가 되면 무슨 일인지 모른다) */
.msgr-deleted { background: none; padding: 2px 0; }
.msgr-reactions { display: flex; gap: 4px; margin-top: 2px; flex-wrap: wrap; }
.msgr-reaction {
    --reaction-fill: var(--m-canvas); --reaction-line: var(--m-hairline);
    position: relative; isolation: isolate; display: inline-flex; align-items: center; justify-content: center; gap: 4px;
    min-width: 36px; min-height: 28px; border: 0; background: transparent;
    border-radius: 8px; padding: 4px 9px; font-size: var(--m-meta); cursor: pointer; line-height: 1.6;
}
/* 보이는 칩과 누르는 영역을 분리해 작은 반응도 손가락으로 누르기 쉽다. */
.msgr-reaction::before {
    content: ""; position: absolute; inset: 2px 0; z-index: -1; pointer-events: none;
    background: var(--reaction-fill); border: 1px solid var(--reaction-line); border-radius: 8px;
}
.msgr-reactn { font-weight: 700; color: var(--m-brand-strong); font-size: var(--m-badge); }
.msgr-reactadd { color: var(--m-muted); }
.msgr-thread {
    display: flex; align-items: center; gap: 6px; margin-top: 5px; border: 0; background: transparent;
    cursor: pointer; padding: 2px 0;
}
.msgr-threadn { font-size: var(--m-meta); font-weight: 700; color: var(--m-brand-strong); }
.msgr-threadat { font-size: var(--m-meta); color: var(--m-muted); }
/* ✓ 읽음 — **말풍선 옆 작은 숫자**(2026-08-08). 종전 `margin-top:3px` 인 블록은
   메시지마다 한 줄을 더 먹었다. `inline-block` + `vertical-align:bottom` 이라
   `.msgr-msgtext`(inline-block) 아래쪽에 나란히 앉는다.
   ⚠ 마크업도 `span` 이어야 한다 — div 로 되돌리면 CSS 만으론 다시 줄이 생긴다. */
.msgr-readmark {
    display: inline-block; vertical-align: bottom;
    margin: 0 0 2px 5px;
    font-size: var(--m-badge); color: var(--m-muted); white-space: nowrap;
}
/* 말풍선 + 읽음 숫자 한 줄 — 말풍선은 flex 로 줄어든다(퍼센트 폭 계산을 안 써서 폰에서 한 단어씩 쪼개지지 않는다) */
.msgr-bubline { display: flex; align-items: flex-end; gap: 5px; }
.msgr-bubline > .msgr-msgtext { min-width: 0; }
.msgr-bubline > .msgr-readmark { flex: none; margin: 0 0 2px; }
/* 폰의 오른쪽 배치를 PC에도 적용한다 (2026-11-02). 아바타·이름은 숨기고 읽음 숫자는 왼쪽. */
.msgr-msg.is-mine { flex-direction: row-reverse; }
.msgr-msg.is-mine > .msgr-av, .msgr-msg.is-mine > .msgr-avspacer, .msgr-msg.is-mine .msgr-msgby { display: none; }
.msgr-msg.is-mine .msgr-msgbody { text-align: right; }
.msgr-msg.is-mine .msgr-msgbody > * { margin-left: auto; }   /* 스레드 줄·인용·칩처럼 내용 폭인 블록도 오른쪽에 */
.msgr-msg.is-mine .msgr-msgtext { text-align: left; }
.msgr-msg.is-mine .msgr-msghead { justify-content: flex-end; }
.msgr-msg.is-mine .msgr-bubline { justify-content: flex-end; }
.msgr-msg.is-mine .msgr-bubline > .msgr-readmark { order: -1; }
.msgr-msg.is-mine .msgr-files { align-items: flex-end; }   /* 내 사진·파일 카드도 말풍선처럼 오른쪽 끝(2026-11-02 PC 실측: 가운데쯤 남았다) */

/* ★ 팀 비밀 대화 — 대화 흐름 안의 인라인 구간 */
.msgr-secret { border: 1px solid var(--m-brand-line); border-radius: 8px; margin: 8px 0; overflow: hidden; background: var(--m-brand-tint); }
.msgr-secrethead {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    background: var(--m-brand); color: var(--m-on-brand); padding: 6px 12px; font-size: var(--m-meta); font-weight: 700;
}
.msgr-secretnote { font-size: var(--m-badge); font-weight: 500; color: var(--m-on-secret-head); }
.msgr-secret .msgr-msg { padding: 6px 11px; }

/* 컴포저 */
.msgr-composer { flex: 0 0 auto; border-top: 1px solid var(--m-hairline); padding: 10px 14px 12px; background: var(--m-surface); }
.msgr-composer.is-internal { background: var(--m-brand-tint); }
.msgr-tools { display: flex; align-items: center; gap: 2px; margin-bottom: 6px; }
.msgr-tool {
    min-width: 26px; height: 26px; border: 0; background: transparent; border-radius: 6px;
    cursor: pointer; color: var(--m-muted); font-size: 12px; padding: 0 5px;
}
.msgr-tool:hover { background: var(--m-surface-2); }
.msgr-tool-b { font-weight: 900; }
.msgr-tool-i { font-style: italic; }
.msgr-tool-u { text-decoration: underline; }
.msgr-tool-s { text-decoration: line-through; }
.msgr-toolsep { width: 1px; height: 15px; background: var(--m-hairline); margin: 0 5px; }
.msgr-seg { display: flex; border: 1px solid var(--m-hairline); border-radius: 8px; overflow: hidden; }
.msgr-segbtn {
    border: 0; background: var(--m-surface); padding: 3px 12px; font-size: 11px; font-weight: 700;
    color: var(--m-muted); cursor: pointer;
}
.msgr-segbtn.is-active { background: var(--m-brand); color: var(--m-on-brand); }
.msgr-scopebar { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; min-width: 0; }
.msgr-scopebar .msgr-seg { flex: 0 0 auto; border: 0; background: var(--m-surface-2); padding: 3px; gap: 2px; }
.msgr-scopebar .msgr-segbtn { min-width: 48px; min-height: 32px; padding: 4px 10px; border-radius: 6px; background: transparent; font-size: var(--m-meta); }
.msgr-scopebar .msgr-segbtn.is-active { background: var(--m-surface); color: var(--m-brand-strong); box-shadow: 0 1px 3px var(--m-shadow-sm); }
.msgr-scopehint { min-width: 0; font-size: var(--m-meta); line-height: 1.4; color: var(--m-muted); word-break: keep-all; overflow-wrap: anywhere; }
.msgr-composer.is-internal .msgr-scopehint { color: var(--m-brand); }
.msgr-inputwrap { border: 1px solid var(--m-hairline); border-radius: 12px; padding: 7px 10px; background: var(--m-canvas); }
.msgr-composer.is-internal .msgr-inputwrap { border-color: var(--m-brand-line); }
.msgr-composer .msgr-inputwrap:focus-within { border-color: var(--m-brand); box-shadow: 0 0 0 3px var(--m-brand-focus); }
.msgr-input:focus-visible { box-shadow: none; }
.msgr-input {
    display: block; width: 100%; border: 0; outline: none; resize: none; font-size: var(--m-body); line-height: 1.5;
    font-family: inherit; color: var(--m-ink); background: transparent;
}
.msgr-cfoot { display: flex; align-items: center; gap: 4px; margin-top: 8px; }
.msgr-send {
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    width: 36px; height: 36px; border: 0; border-radius: 12px; background: var(--m-brand); color: var(--m-on-brand);
    font-size: var(--m-base); cursor: pointer;
}

.msgr-composer-icon { display: block; width: 20px; height: 20px; flex: 0 0 20px; }

/* ── 4) 우측 정보 패널 ── */
.msgr-side {
    width: 300px; flex: 0 0 300px; border-left: 1px solid var(--m-hairline); background: var(--m-surface);
    display: flex; flex-direction: column; min-height: 0;
}
.msgr-sidetabs { display: flex; gap: 4px; padding: 9px 10px; border-bottom: 1px solid var(--m-surface-2); }
.msgr-sidetab {
    flex: 1 1 0; padding: 5px 0; border: 0; background: var(--m-canvas); border-radius: 8px;
    font-size: 11.5px; font-weight: 700; color: var(--m-muted); cursor: pointer;
}
.msgr-sidetab.is-active { background: var(--m-brand-tint); color: var(--m-brand); font-weight: 800; }
.msgr-sidescroll { flex: 1 1 auto; overflow-y: auto; min-height: 0; padding: 12px; }

/* 📁 파일 관리 탭 */
.msgr-filehead { margin-bottom: 8px; }
.msgr-filesearch {
    width: 100%; border: 1px solid var(--m-hairline); border-radius: 8px; padding: 7px 10px;
    font-size: 12px; background: var(--m-canvas); color: var(--m-ink);
}
.msgr-filesearch:focus { outline: 0; border-color: var(--m-brand-line); background: var(--m-surface); }
.msgr-filechips { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 10px; }
.msgr-filechip {
    border: 1px solid var(--m-hairline); background: var(--m-surface); border-radius: 999px;
    padding: 3px 9px; font-size: 11px; color: var(--m-ink-2); cursor: pointer; white-space: nowrap;
}
.msgr-filechip:hover { background: var(--m-surface-2); }
.msgr-filechip.is-active { background: var(--m-brand); border-color: var(--m-brand); color: var(--m-on-brand); font-weight: 700; }
.msgr-filedate { padding: 12px 6px 4px; font-size: var(--m-meta); font-weight: 700; color: var(--m-muted); }
.msgr-filedate:first-child { padding-top: 4px; }
.msgr-filerow {
    display: flex; align-items: center; gap: 9px; padding: 8px 6px;
    border-radius: 8px; border-bottom: 1px solid var(--m-canvas);
}
.msgr-filerow:hover { background: var(--m-canvas); }
.msgr-fileicon { font-size: 17px; flex: 0 0 auto; width: 22px; text-align: center; }
.msgr-filemid { flex: 1 1 auto; min-width: 0; }
.msgr-filename {
    font-size: 12px; font-weight: 600; color: var(--m-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msgr-filename.is-link { cursor: pointer; }
.msgr-filename.is-link:hover { color: var(--m-brand); text-decoration: underline; }
.msgr-filemeta {
    display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
    font-size: var(--m-badge); color: var(--m-muted); margin-top: 2px;
}
.msgr-filedot { color: var(--m-ink-meta); }
.msgr-fileorg { font-weight: 700; }

/* 🔗 본문 자동 링크 (msgr-text.js) */
.msgr-link { color: var(--m-brand); text-decoration: underline; word-break: break-all; }
.msgr-link:hover { color: var(--m-brand-strong); }

/* ✨ 메시지 보정 바 — 컴포저 바로 위 인라인(모달 아님) */
.msgr-aibar {
    border: 1px solid var(--m-brand-tint-2); background: var(--m-brand-tint); border-radius: 8px;
    padding: 8px 10px; margin-bottom: 6px;
}
.msgr-aihead { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 800; color: var(--m-brand); }
.msgr-aitone { font-weight: 700; font-size: var(--m-badge); color: var(--m-brand-strong); background: var(--m-brand-tint); border-radius: 6px; padding: 1px 6px; }
.msgr-aix { border: 0; background: transparent; color: var(--m-brand); cursor: pointer; font-size: 12px; padding: 0 2px; }
.msgr-aix:hover { color: var(--m-brand); }
.msgr-aitext {
    margin-top: 6px; font-size: 13px; color: var(--m-ink); line-height: 1.6;
    white-space: pre-wrap; word-break: keep-all; overflow-wrap: anywhere; max-height: 180px; overflow-y: auto;
}
.msgr-aiwarn { margin-top: 6px; font-size: 11px; color: var(--m-warn-action); background: var(--m-warn-tint); border-radius: 6px; padding: 5px 8px; line-height: 1.5; }
.msgr-aiblock { margin-top: 6px; font-size: 11.5px; color: var(--m-danger); background: var(--m-danger-tint); border: 1px solid var(--m-danger-line); border-radius: 6px; padding: 7px 9px; font-weight: 700; }
.msgr-aisub { font-weight: 400; color: var(--m-danger-strong); margin-top: 3px; font-size: var(--m-badge); line-height: 1.5; }
.msgr-aiact { display: flex; gap: 5px; margin-top: 8px; }
.msgr-aiapply {
    border: 0; background: var(--m-brand); color: var(--m-on-brand); border-radius: 8px;
    padding: 6px 14px; font-size: 12px; font-weight: 700; cursor: pointer;
}
.msgr-aiapply:hover { background: var(--m-brand-strong); }
.msgr-aiagain {
    border: 1px solid var(--m-brand-tint-2); background: var(--m-surface); color: var(--m-brand); border-radius: 8px;
    padding: 6px 12px; font-size: 12px; font-weight: 700; cursor: pointer;
}
.msgr-aiagain:hover { background: var(--m-brand-tint); }
.msgr-ainote { margin-top: 7px; font-size: var(--m-badge); color: var(--m-brand); line-height: 1.5; }
.msgr-aiundo { display: flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700; color: var(--m-brand); }

/* 📅 일정 공유 모달 */
.msgr-schedback {
    position: fixed; inset: 0; z-index: 80; background: var(--m-scrim-schedule);
    display: flex; align-items: center; justify-content: center; padding: 20px;
}
.msgr-schedbox {
    background: var(--m-surface); border-radius: 12px; width: 100%; max-width: 420px;
    max-height: 82vh; display: flex; flex-direction: column; padding: 14px;
    box-shadow: 0 20px 50px var(--m-shadow-float);
}
.msgr-schedhead { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 800; color: var(--m-ink); margin-bottom: 10px; }
.msgr-schedlist { flex: 1 1 auto; overflow-y: auto; min-height: 0; max-height: 360px; }
.msgr-schedproject {
    display: flex; align-items: center; gap: 10px; width: 100%; min-height: 54px;
    padding: 10px 8px; border: 0; border-radius: 8px; background: transparent;
    color: var(--m-ink); text-align: left; cursor: pointer; font-size: var(--fs-base);
}
.msgr-schedproject:hover, .msgr-schedproject:focus-visible { background: var(--m-brand-tint); }
.msgr-schedproject:focus-visible { outline: 2px solid var(--m-brand); outline-offset: -2px; }
.msgr-schedicon { flex: none; }
.msgr-schedname { flex: 1; min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
.msgr-schedcount { flex: none; font-size: var(--fs-meta); color: var(--m-muted); }
.msgr-schedempty { font-size: var(--fs-meta); color: var(--m-muted); padding: 14px 8px; text-align: center; line-height: 1.6; }
.msgr-msg.is-mine .msgr-link { color: var(--m-mine-link); }
.msgr-filelock { color: var(--m-warn-action); background: var(--m-warn-tint-2); border-radius: 6px; padding: 0 4px; font-weight: 700; }
.msgr-fileact { flex: 0 0 auto; display: flex; gap: 2px; }
.msgr-filebtn {
    border: 0; background: transparent; cursor: pointer; font-size: 12px;
    padding: 4px 5px; border-radius: 6px; color: var(--m-muted); line-height: 1;
}
.msgr-filebtn:hover { background: var(--m-hairline); color: var(--m-ink); }
.msgr-filebtn:disabled { opacity: var(--m-dim-opacity, .5); cursor: default; }
.msgr-filenote {
    margin-top: 12px; padding: 8px 10px; background: var(--m-canvas); border-radius: 8px;
    font-size: var(--m-badge); color: var(--m-muted); line-height: 1.5;
}
.msgr-scanbtn {
    margin-top: 6px; width: 100%; border: 1px solid var(--m-brand-line); background: var(--m-brand-tint);
    color: var(--m-brand-strong); border-radius: 8px; padding: 6px 8px; font-size: 11px;
    font-weight: 700; cursor: pointer;
}
.msgr-scanbtn:hover { background: var(--m-brand-tint-2); }
.msgr-scanbtn:disabled { opacity: var(--m-dim-opacity, .55); cursor: default; }

/* 😊 컴포저 이모지 격자 · @멘션 목록 (팝오버 공통 껍데기는 .msgr-emojipop)
   ⚠ 껍데기와 묶어 쓴다(.msgr-emojipop.…) — 껍데기의 display:flex 가 이 파일 **아래쪽**에 있어 한 단어 선택자면 순서로 져서
     격자·목록이 가로 한 줄로 눕고 «부/를/사/람»처럼 글자가 쪼개졌다(8/5 부터, 2026-10-07 발견). */
.msgr-emojipop.msgr-emojigrid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px; }   /* 폭 상한(236px)을 두면 8칸(약 246px)이 상자 밖으로 삐져나온다 */
.msgr-emojipop.msgr-mentionpop { display: block; min-width: 190px; max-height: 260px; overflow-y: auto; padding: 4px; }
.msgr-mentionhead { font-size: var(--m-badge); color: var(--m-muted); padding: 3px 7px 5px; font-weight: 700; }
.msgr-mentionitem {
    display: flex; align-items: center; gap: 6px; width: 100%; border: 0; background: transparent;
    padding: 5px 7px; border-radius: 6px; cursor: pointer; text-align: left;
}
.msgr-mentionitem:hover { background: var(--m-brand-tint); }
.msgr-mentionname { font-size: 12px; font-weight: 600; color: var(--m-ink); }
.msgr-mentionrole { font-size: var(--m-badge); color: var(--m-muted); }
.msgr-mentionempty { font-size: 11px; color: var(--m-muted); padding: 8px 10px; }



/* 📎 드래그앤드롭 오버레이 */
.msgr-main { position: relative; }
.msgr-dropover::after {
    content: '📎 여기에 놓으면 파일이 전송됩니다';
    position: absolute; inset: 8px; z-index: 40;
    display: flex; align-items: center; justify-content: center;
    background: var(--m-brand-overlay); border: 2.5px dashed var(--m-brand-line); border-radius: 12px;
    color: var(--m-brand-strong); font-size: 15px; font-weight: 800; pointer-events: none;
}
/* 🪟 메신저 별도 창(pop-out) — OS 크롬을 숨기고 메신저만 꽉 채운다 */
body.msgr-popout #appTopbar,
body.msgr-popout #contextPanel,
body.msgr-popout .sidebar-overlay,
body.msgr-popout #leftPanelHandle,
body.msgr-popout .compact-ham-btn,
body.msgr-popout .compact-overlay-bg,
body.msgr-popout #mobileBottomNav { display: none !important; }
body.msgr-popout #mainContent { margin: 0 !important; padding: 0 !important; height: 100dvh !important; }
body.msgr-popout .content-area { padding: 0 !important; height: 100dvh !important; max-width: none !important; }
body.msgr-popout .global-content-wrap { max-width: none !important; height: 100dvh !important; padding: 0 !important; }
body.msgr-popout #global-msgr { height: 100dvh; }
body.msgr-popout .msgr-root { height: 100dvh !important; border-radius: 0 !important; box-shadow: none !important; max-width: none !important; }
/* 📱 설치 앱: 문서 전체가 고무줄처럼 끌리지 않게 + 안쪽 칸의 끝 스크롤이 문서로 번지지 않게 (2026-09-16 폰 실측 — msgr-shell.js touchmove 가드와 한 쌍) */
/* 🚨 **문서는 스크롤되지 않는다** (2026-09-16 폰 캡처 3차 — «대화방 열면 바로 이렇게 됨»).
   키보드가 열리면 iOS 는 입력칸을 보이려고 문서를 386px 올리는데, 문서 높이만 줄이고 overflow 를 안 막으면
   안쪽 내용이 넘쳐 스크롤 여지가 남아 **밀림이 풀리지 않는다** — 화면엔 대화창 맨 아래 114px(입력창)만 남고
   그 아래 394px 이 빈 배경이었다. 높이를 화면에 맞추는 것과 «더 스크롤할 곳이 없게» 하는 것은 다른 일이다. */
html.msgr-popout-root, body.msgr-popout { overscroll-behavior: none; overflow: hidden; }
body.msgr-popout .msgr-root, body.msgr-popout .msgr-root * { overscroll-behavior: contain; }

/* ✅ 초대 링크 준비됨 카드 */
.msgr-invok { background: var(--m-brand-tint); border: 1px solid var(--m-brand-tint-2); border-radius: 8px; padding: 11px 12px; margin: 4px 0 10px; }
.msgr-invoktitle { font-size: 13px; font-weight: 800; color: var(--m-brand-strong); }
.msgr-invoksub { font-size: var(--m-badge); color: var(--m-muted); margin-top: 3px; line-height: 1.5; }
.msgr-invurlrow { margin-top: 9px; }
.msgr-invurl {
    width: 100%; border: 1px solid var(--m-brand-tint-2); border-radius: 8px; padding: 8px 10px;
    font-size: 11.5px; color: var(--m-brand); background: var(--m-surface); font-family: ui-monospace, monospace;
    text-overflow: ellipsis;
}
.msgr-invurl:focus { outline: 0; border-color: var(--m-brand); }

/* 🔢 접속 번호 — 초대 폼의 켬/끔과, 발급 후 화면에 보여 주는 번호 카드.
   ★ 번호는 **크고 자간을 벌린다** — 담당자가 화면을 보며 전화로 불러 주는 값이라
     6·8·0 이 붙어 보이면 그대로 오전달된다. */
.msgr-invpin { display: flex; align-items: center; gap: 7px; margin: 12px 0 2px; font-size: var(--m-name); font-weight: 700; color: var(--m-ink-secondary); cursor: pointer; }
.msgr-invpin input { width: 15px; height: 15px; accent-color: var(--m-brand); cursor: pointer; }
.msgr-invpincard {
    display: flex; align-items: center; gap: 9px; margin-top: 9px;
    background: var(--m-surface); border: 1px solid var(--m-brand-tint-2); border-radius: 8px; padding: 9px 11px;
}
.msgr-invpinlabel { font-size: var(--m-badge); font-weight: 700; color: var(--m-muted); flex: 0 0 auto; }
.msgr-invpinval {
    flex: 1 1 auto; font-size: 21px; font-weight: 800; color: var(--m-brand);
    letter-spacing: .18em; font-family: ui-monospace, monospace;
}
.msgr-invpinwarn { font-size: var(--m-badge); color: var(--m-warn-action); background: var(--m-warn-tint); border-radius: 6px; padding: 7px 9px; margin-top: 8px; line-height: 1.55; }

/* 🚪 외부 참여자 내보내기 */
.msgr-kick {
    flex: 0 0 auto; border: 0; background: transparent; color: var(--m-ink-meta); cursor: pointer;
    font-size: 12px; padding: 3px 6px; border-radius: 6px; margin-left: 2px;
}
.msgr-kick:hover { background: var(--m-danger-tint); color: var(--m-danger-action); }
.msgr-kick:disabled { opacity: var(--m-dim-opacity, .5); }

/* 🖼 이미지 첨부 썸네일 */
.msgr-imgthumb {
    display: inline-block; max-width: 240px; margin-top: 4px; border-radius: 8px;
    overflow: hidden; cursor: zoom-in; border: 1px solid var(--m-hairline); line-height: 0;
}
.msgr-imgthumb img { max-width: 240px; max-height: 240px; display: block; object-fit: cover; }
/* 로딩 자리표시 — **스켈레톤**이지 «깨진 사진»이 아니다.
   종전엔 회색 칸에 🖼 이모지였는데, 그게 바로 브라우저가 못 읽은 이미지를 그리는 모양이라
   «사진이 깨졌다»로 읽혔다(2026-08-06 사장님 신고). 사진 URL 은 메시지에 안 심고
   getDownloadURL 로 그때그때 받으므로(보안 결정) 이미지당 왕복 1회는 원래 걸린다 —
   없앨 수 없는 대기는 «기다리는 중»으로 보이게 하는 것이 정답이다.
   ⓘ prefers-reduced-motion 은 style.css:1479 의 전역 `*` 규칙이 이미 처리한다. */
.msgr-imgph {
    width: 180px; height: 120px;
    background: linear-gradient(100deg, var(--m-placeholder) 30%, var(--m-canvas) 50%, var(--m-placeholder) 70%) var(--m-placeholder);
    background-size: 220% 100%;
    animation: msgr-shim 1.1s ease-in-out infinite;
}
@keyframes msgr-shim { from { background-position: 180% 0; } to { background-position: -40% 0; } }

.msgr-typeahead { position: relative; }
.msgr-tahdd {
    position: absolute; left: 0; right: 0; top: 100%; margin-top: 3px; z-index: 60;
    background: var(--m-surface); border: 1px solid var(--m-hairline); border-radius: 8px;
    box-shadow: 0 10px 30px var(--m-shadow-lg); max-height: 240px; overflow-y: auto; padding: 4px;
}
.msgr-tahit {
    display: block; width: 100%; text-align: left; border: 0; background: transparent;
    padding: 7px 9px; border-radius: 6px; font-size: 12.5px; color: var(--m-ink); cursor: pointer;
}
.msgr-tahit:hover { background: var(--m-brand-tint); }
/* 🖼 이미지 라이트박스 — 모달(z-50)·문서뷰어보다 위 */
.msgr-lightbox {
    position: fixed; inset: 0; z-index: 90; background: var(--m-scrim-image);
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 12px; padding: 24px; cursor: zoom-out; overflow: hidden;
}
.msgr-lightimg { max-width: 100%; max-height: 84vh; object-fit: contain; border-radius: 8px; cursor: zoom-in; }
.msgr-lightcap { color: var(--m-lightbox-ink); font-size: 12px; max-width: 90%; text-align: center; word-break: break-all; }
.msgr-lighttools { position: relative; z-index: 1; display: flex; gap: 8px; justify-content: center; }
.msgr-lighttools .msgr-btn { min-width: 76px; min-height: 40px; }
.msgr-sidehead { position: relative; margin-bottom: 12px; padding-right: 38px; }
.msgr-side-more { position: absolute; top: 0; right: 0; width: 32px; min-height: 32px; border: 1px solid var(--m-hairline); border-radius: 8px; background: var(--m-surface-2); color: var(--m-ink); font-size: var(--m-title); cursor: pointer; }
.msgr-participant-card { margin-top: 12px; padding: 12px; border: 1px solid var(--m-hairline); border-radius: 12px; background: var(--m-surface); }
.msgr-participant-card .msgr-grouphead { margin-top: 0; }
.msgr-presence { flex: none; display: inline-flex; align-items: center; gap: 5px; color: var(--m-muted); font-size: var(--m-badge); white-space: nowrap; }
.msgr-presence.is-now::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--m-ok-action); }
.msgr-sidetitle { font-size: var(--m-title); font-weight: 700; color: var(--m-ink); word-break: keep-all; overflow-wrap: anywhere; }   /* «현 / 장» 처럼 낱말 중간에서 끊기지 않게 (2026-11-03) */
.msgr-sidemeta { font-size: 11px; color: var(--m-muted); margin-top: 3px; }
.msgr-sidedesc {
    font-size: 11.5px; line-height: 1.6; color: var(--m-ink-2); background: var(--m-canvas);
    border-radius: 8px; padding: 9px 10px; margin-bottom: 12px;
}
.msgr-card { border: 1px solid var(--m-surface-2); border-radius: 8px; padding: 9px 10px; margin-bottom: 12px; }
.msgr-cardhead { font-size: 11.5px; font-weight: 800; color: var(--m-ink-secondary); margin-bottom: 6px; }
.msgr-bmitem { background: var(--m-canvas); border-radius: 8px; padding: 7px 9px; }
.msgr-bmhead { display: flex; align-items: center; gap: 6px; }
.msgr-bmby { font-size: 11.5px; font-weight: 700; color: var(--m-ink); }
.msgr-bmage { font-size: var(--m-badge); color: var(--m-brand); background: var(--m-brand-tint); border-radius: 6px; padding: 0 5px; font-weight: 700; }
.msgr-bmtext { font-size: 11.5px; color: var(--m-ink-2); margin-top: 3px; line-height: 1.5; }
.msgr-grouphead { display: flex; align-items: center; gap: 6px; margin: 12px 0 5px; }
.msgr-groupname { font-size: 11.5px; font-weight: 800; min-width: 0; flex: 0 1 auto; word-break: keep-all; overflow-wrap: anywhere; }
.msgr-groupcnt { font-size: var(--m-badge); color: var(--m-muted); font-weight: 700; }
.msgr-invite {
    border: 1px solid var(--m-hairline); background: var(--m-surface); border-radius: 6px; padding: 2px 8px;
    font-size: var(--m-badge); font-weight: 700; color: var(--m-ink-2); cursor: pointer;
    white-space: nowrap; flex: none;   /* 긴 회사 이름 옆에서 «거래처 / 초대» 두 줄로 쪼개지던 것(PC 점검) */
}
.msgr-person { display: flex; align-items: center; gap: 8px; padding: 5px 0; }
.msgr-personav { position: relative; flex: 0 0 auto; }
.msgr-personinfo { flex: 1 1 auto; min-width: 0; }
.msgr-personname { display: flex; align-items: center; gap: 4px; font-size: var(--m-name); font-weight: 600; color: var(--m-ink); }
/* 긴 이름·직함은 한 줄로 줄이고(전체는 title) — PC 정보 패널에서 4줄로 쪼개졌다 */
.msgr-personname > .msgr-personnm { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-personrole { font-size: var(--m-meta); color: var(--m-muted); }
.msgr-level { flex: 0 0 auto; font-size: var(--m-badge); color: var(--m-muted); white-space: nowrap; }

/* ── 좁은 화면 ──────────────────────────────────────────
   ★ 모바일에 4열을 우겨넣지 않는다. 375px 에서는 대화 영역에 남는 폭이
     사실상 없어(레일60+목록232 = 292) 컴포저가 세로로 찌그러진다(실측).
     카톡·Slack·Joint 처럼 **목록 ↔ 대화 2단 토글**로 간다.
     전환은 CSS 가 아니라 JS 상태(.is-mobile-list / .is-mobile-room)가 정한다 —
     '어느 화면을 보고 있나'는 폭이 아니라 사용자의 선택이기 때문. */
@media (max-width: 1180px) {
    .msgr-side { display: none; }
}
/* 창 크기에 따른 목록/대화 전환은 msgr-shell.js MOBILE_Q와 같은 경계다.
   PC는 800px부터 두 열, 터치·호버 없는 기기는 기존 960px 기준을 유지한다.
   하단 내비게이션과 터치 크기는 화면 폭과 입력 수단을 함께 본다. */
@media (max-width: 799px), (max-width: 959px) and (pointer: coarse), (max-width: 959px) and (hover: none) {
    .msgr-list, .msgr-main { width: auto; flex: 1 1 auto; min-width: 0; }
    .msgr-root.is-mobile-list .msgr-main { display: none; }
    .msgr-root.is-mobile-room .msgr-list { display: none; }
    body.msgr-popout .msgr-root.is-mobile-room .msgr-rail { display: none; }
    body.msgr-popout .msgr-root.is-clients .msgr-rail { display: flex; }
    .msgr-back { display: inline-flex !important; }
}

@media (max-width: 768px) and (pointer: coarse), (max-width: 768px) and (hover: none) {
    .msgr-root {
        /* 모바일은 화면을 꽉 채운다 — '앱에 얹힌 작은 상자' 느낌을 없앤다.
           dvh 로 주소창 접힘까지 대응. */
        min-height: 0;   /* 높이는 fitHeight() 실측이 정한다 */
        border-radius: 12px;
    }
    .msgr-msgs { padding: 10px 12px; }
    .msgr-msgbody { max-width: calc(100% - 40px); }
    /* ⚠ 모바일에서 `.msgr-tools` 안의 도구 버튼은 숨긴다(전체/내부 토글만 남긴다).
       서식 버튼을 지운 2026-08-05 이후로 이 줄에 걸리는 버튼은 현재 없지만,
       **여기에 새 버튼을 넣으면 모바일에서 조용히 사라진다** — 도구 버튼은 `.msgr-cfoot`(📎 😊 @)에 둘 것. */
    .msgr-tools .msgr-tool { display: none; }
    .msgr-cfoot .msgr-tool { display: inline-flex; }
    .msgr-searchwrap { padding: 8px; }
    .msgr-fixed { padding: 4px; }
}

/* ══════════════════════════════════════════════════════════════
   👆 손가락 크기 — 터치 기기에서만 (2026-08-07 아이폰 실측)
   위 값들(도구 26px · 전송 30px · 사이드토글 25px · 세그먼트 높이 19px)은
   **마우스 기준**이라 데스크톱에선 옳다. 폰에서는 손가락 접촉면이 ~9mm 라
   그대로 두면 옆 버튼을 누른다 — 특히 📎 첨부와 ➤ 전송이 붙어 있는 컴포저.
   ⓘ 실측: 도구 3개가 26px 에 **간격 2px** 였다. 투명 히트영역을 44px 로 넓히면
     서로 겹쳐서 오히려 오작동하므로 **실제 크기를 키우고 간격도 벌린다**.
     자리는 넉넉하다 — 그 줄에 262px 의 빈 공간이 있었다.
   ⓘ 기준은 44×44(Apple HIG). 아이콘 글자 크기는 그대로라 «뚱뚱해» 보이지 않는다.
   ⚠ `pointer: coarse` 로 가른다 — 화면 폭이 아니라 **입력 수단**이 기준이다
     (마우스를 쓰는 좁은 창은 커질 이유가 없다).
   ══════════════════════════════════════════════════════════════ */
@media (pointer: coarse) {
    .msgr-root .msgr-tool { min-width: 44px; height: 44px; font-size: 17px; }
    .msgr-root .msgr-cfoot { gap: 4px; }
    .msgr-root .msgr-send { width: 44px; height: 44px; font-size: 15px; }
    .msgr-root .msgr-sidetoggle, .msgr-root .msgr-threadx, .msgr-root .msgr-threadback { min-width: 44px; height: 44px; padding: 0; }
    .msgr-root .msgr-back { min-width: 44px; height: 44px; }
    /* 세그먼트는 두 칸이 맞붙어 있어 투명 확장이 서로를 먹는다 — 높이만 키운다 */
    .msgr-root .msgr-segbtn { min-width: 44px; min-height: 44px; padding: 8px 14px; font-size: var(--m-meta); }
    .msgr-root .msgr-reaction { min-width: 44px; min-height: 44px; }
    .msgr-reaction::before { inset: 8px 0; }
}
/* 데스크톱: 뒤로 버튼 숨김 (모바일 미디어쿼리에서만 되살린다) */
/* ⚠ 기본 스타일이 없으면 브라우저 UA 기본값(2px outset 테두리·회색 배경)이 그려진다 —
   실제로 그 상태로 배포돼 있었다. `display:none` 만 준 요소도 켜지는 순간을 보고 스타일할 것. */
.msgr-back {
    display: none; background: none; border: 0; padding: 0; color: var(--m-ink-secondary);
    cursor: pointer; align-items: center; justify-content: center;
}
.msgr-back:active { color: var(--m-brand-strong); }

/* 💬 메신저 Phase 2 추가 — 부분 갱신 컨테이너 · 빈 상태 · 묶음 메시지 */
.msgr-listbody { flex: 1 1 auto; overflow: hidden; min-height: 0; display: flex; }
.msgr-listbody > .msgr-listscroll { flex: 1 1 auto; }
.msgr-msgsinner { display: flex; flex-direction: column; }
.msgr-empty {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 5px; padding: 34px 16px; text-align: center; color: var(--m-muted); font-size: 12.5px;
}
.msgr-emptyic { font-size: 26px; line-height: 1; margin-bottom: 2px; }
.msgr-emptysub { font-size: 11px; color: var(--m-muted); line-height: 1.5; }
/* 묶음 메시지 — 아바타 자리만 비우고 이름·시간 생략 */
.msgr-msg.is-grouped { padding-top: 1px; padding-bottom: 1px; }
.msgr-avspacer { width: 34px; flex: 0 0 34px; }
.msgr-secret .msgr-avspacer { width: 34px; flex: 0 0 34px; }
/* 정보 패널 접기 (탭바 ▣) */
.msgr-side.msgr-side-hidden { display: none; }

/* 💬 메신저 — 새 대화방 모달 */
.msgr-ov {
    /* 🫧 .45 → .28 — 위 `.msgr-sheetov` 와 같은 이유(유리 + 진한 딤 = 이중 분리) */
    position: fixed; inset: 0; z-index: 700; background: var(--m-scrim);
    display: flex; align-items: center; justify-content: center; padding: 16px;
}
.msgr-dlg {
    /* 🫧 떠 있는 면 — 딤 오버레이 위라 뒤가 흐른다 */
    background: var(--m-glass-bg, var(--m-surface));
    -webkit-backdrop-filter: var(--m-glass); backdrop-filter: var(--m-glass);
    border-radius: 12px; width: 400px; max-width: 100%;
    /* 자판이 뜨면 덮개 높이가 보이는 띠로 줄어든다(msgr-shell pinFullScreenOverlays) — 상자도 그 안에 */
    max-height: 90vh; max-height: min(90vh, 100%); display: flex; flex-direction: column; overflow: hidden;
    box-shadow: 0 18px 48px var(--m-scrim); font-size: 13px; color: var(--m-ink);
}
.msgr-dlghead { padding: 14px 16px; font-size: 14.5px; font-weight: 800; border-bottom: 1px solid var(--m-surface-2); }
.msgr-dlgbody { padding: 14px 16px; overflow-y: auto; }
.msgr-fl { display: block; font-size: 11.5px; font-weight: 800; color: var(--m-ink-2); margin: 10px 0 4px; }
.msgr-fl:first-child { margin-top: 0; }
.msgr-fi {
    width: 100%; height: 34px; border: 1px solid var(--m-hairline); border-radius: 8px;
    padding: 0 10px; font-size: 13px; font-family: inherit; background: var(--m-surface); outline: none; color: var(--m-ink);
}
.msgr-fi:focus { border-color: var(--m-brand-line); }
.msgr-fh { font-size: var(--m-badge); color: var(--m-muted); line-height: 1.5; margin-top: 4px; }
.msgr-segwide { width: 100%; }
.msgr-segwide .msgr-segbtn { flex: 1 1 0; padding: 6px 0; }
.msgr-members { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.msgr-chip {
    border: 1px solid var(--m-hairline); background: var(--m-canvas); border-radius: 12px; padding: 3px 10px;
    font-size: 11.5px; color: var(--m-ink-2); cursor: pointer;
}
.msgr-chip.is-on { background: var(--m-brand-tint); border-color: var(--m-brand-line); color: var(--m-brand); font-weight: 700; }
.msgr-dlgfoot {
    display: flex; align-items: center; gap: 6px; padding: 11px 16px;
    border-top: 1px solid var(--m-surface-2); background: var(--m-canvas);
}
.msgr-dlgerr { flex: 1 1 auto; font-size: 11px; color: var(--m-danger-action); }
.msgr-paste-confirm .msgr-dlghead, .msgr-paste-confirm .msgr-dlgfoot { flex-shrink: 0; }
.msgr-paste-confirm .msgr-dlgbody { min-height: 0; }
.msgr-paste-confirm .msgr-dlgfoot { justify-content: flex-end; }
.msgr-paste-room, .msgr-paste-name { overflow-wrap: anywhere; }
.msgr-paste-room { font-weight: 400; }
.msgr-paste-file { display: flex; align-items: center; gap: 12px; padding: 8px 0; }
.msgr-paste-info { min-width: 0; }
.msgr-paste-thumb { width: 64px; height: 64px; flex: 0 0 64px; object-fit: contain; border-radius: 8px; background: var(--m-surface-2); }
.msgr-btn {
    border: 1px solid var(--m-hairline); background: var(--m-surface); border-radius: 8px; padding: 6px 14px;
    font-size: 12.5px; font-weight: 700; color: var(--m-ink-2); cursor: pointer;
}
.msgr-btn-p { background: var(--m-brand); border-color: var(--m-brand); color: var(--m-on-brand); }
.msgr-btn:disabled { opacity: var(--m-dim-opacity, .55); cursor: not-allowed; }
/* 다크는 흐림(opacity) 대신 색으로 «못 누름»을 보인다 — 흐림 값이 1 이라 «카톡으로 보내기 (0명)»이 켜진 버튼처럼 보였다(2026-11-02) */
html[data-theme="dark"] :is(.msgr-root, .msgr-ov, .msgr-sheetov) :is(.msgr-btn, .msgr-invite, .msgr-filebtn, .msgr-scanbtn, .msgr-kick, .msgr-file, .msgr-olderbtn):disabled {
    background: var(--m-surface-2); color: var(--m-disabled-ink); border-color: var(--m-hairline); border-style: dashed; box-shadow: none;
}

/* 💬 메신저 — 외부 초대 모달 결과 */
.msgr-invres { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--bd, var(--m-hairline)); }
.msgr-invres .msgr-link {
    font-size: var(--m-meta); color: var(--m-brand-strong); background: var(--m-brand-tint); border: 1px solid var(--m-brand-tint-2);
    border-radius: 8px; padding: 8px 10px; word-break: break-all; user-select: all; line-height: 1.5;
}
.msgr-invbtns { display: flex; gap: 6px; margin-top: 9px; }
.msgr-invshare { width: 100%; margin-top: 12px; }
.msgr-invsharetext { font-size: 16px; min-height: 120px; }
.msgr-invbtns .msgr-btn { flex: 1 1 0; text-align: center; }
.msgr-invite:disabled { opacity: var(--m-dim-opacity, .45); cursor: not-allowed; }

/* 💬 메신저 — 첨부 */
.msgr-files { display: flex; flex-direction: column; gap: 3px; margin-top: 5px; align-items: flex-start; }
.msgr-file {
    display: flex; align-items: center; gap: 9px; width: 100%; max-width: 300px;
    border: 1px solid var(--m-hairline); background: var(--m-surface);
    border-radius: var(--m-r2); padding: 8px 11px; font-size: var(--m-meta); color: var(--m-ink-secondary);
    cursor: pointer; text-align: left; font-family: inherit;
    transition: background .12s, border-color .12s;
}
.msgr-fileic { flex: 0 0 auto; font-size: 17px; line-height: 1; }
.msgr-filebody { flex: 1 1 auto; min-width: 0; }
.msgr-filename {
    font-size: var(--m-meta); font-weight: 600; color: var(--m-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msgr-filedl { flex: 0 0 auto; font-size: var(--m-meta); color: var(--m-brand); }
.msgr-file:hover { background: var(--m-canvas); border-color: var(--m-brand-line); }
.msgr-file:disabled { opacity: var(--m-dim-opacity, .5); cursor: wait; }
.msgr-filesz { font-size: var(--m-badge); color: var(--m-muted); margin-top: 1px; }

/* 🌡 대화방 온도 — **한 줄**. 종전 카드(차트+축+온도+설명+각주)는 우측 패널에서
   가장 무거운데 말하는 건 «요즘 활발한가»뿐이었다(2026-08-06 축소). */
.msgr-temprow {
    display: flex; align-items: center; gap: 7px;
    padding: 8px 2px 12px; font-size: var(--m-meta); color: var(--m-muted);
}
.msgr-tempdot { width: 7px; height: 7px; border-radius: 999px; background: var(--m-ink-meta); flex: 0 0 auto; }
.msgr-tempdot.is-hot { background: var(--m-hot-accent); }
.msgr-tempdot.is-cold { background: var(--m-video-focus); }
.msgr-templabel { font-weight: 600; color: var(--m-ink-secondary); }
.msgr-tempmeta { color: var(--m-muted); }

/* 🕰 이전 대화 더 보기 — 대화 맨 위. 눈에 띄되 대화를 방해하지 않는 무게. */
.msgr-older { display: flex; justify-content: center; padding: 4px 0 10px; }
.msgr-olderbtn {
    border: 1px solid var(--m-hairline); background: var(--m-surface); border-radius: 999px;
    padding: 6px 14px; font-size: var(--m-meta); color: var(--m-ink-2); cursor: pointer;
    transition: background-color .12s ease, border-color .12s ease;
}
.msgr-olderbtn:hover { background: var(--m-canvas); border-color: var(--m-brand-line); }
.msgr-olderbtn:disabled { opacity: var(--m-dim-opacity, .6); cursor: wait; }

/* 💬 메신저 — 댓글 스레드 · 챙겨야 할 메시지 · 시스템 안내 */
.msgr-sys { display: flex; justify-content: center; margin: 8px 0; }
.msgr-sys span {
    font-size: 11px; color: var(--m-brand); background: var(--m-brand-tint); border: 1px solid var(--m-brand-tint-2);
    border-radius: 12px; padding: 3px 12px; line-height: 1.5; text-align: center;
}
/* 💬 팀 스레드 패널 (2026-09-14) — 넓은 화면은 오른쪽 열(정보 패널 자리), 좁으면 위에 띄운다.
   ⚠ 표시는 `.has-thread` 로만 한다 — [hidden] 은 앱 CSS 리셋과 명시도 싸움이 난다.
   ★ 보라 톤 = «팀만 보는 영역»(본 흐름의 🔒 내부 블록과 같은 뜻의 색). */
.msgr-thread.is-open .msgr-threadn { text-decoration: underline; }
.msgr-root.has-thread { position: relative; }
.msgr-threadpane {
    display: none; flex-direction: column; min-height: 0;
    width: 360px; flex: 0 0 360px; border-left: 1px solid var(--m-hairline); background: var(--m-surface);
}
.msgr-root.has-thread .msgr-threadpane { display: flex; }
.msgr-root.has-thread .msgr-side { display: none; }
.msgr-threadhead {
    display: flex; align-items: center; gap: 4px; padding: 9px 8px 8px 14px;
    border-bottom: 1px solid var(--m-brand-tint);
}
.msgr-threadttl { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.msgr-threadname { font-size: var(--m-title); font-weight: 800; color: var(--m-ink); }
.msgr-threadsub {
    font-size: var(--m-badge); color: var(--m-brand);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msgr-threadx, .msgr-threadback {
    border: 0; background: transparent; color: var(--m-muted); font-size: var(--m-title);
    cursor: pointer; padding: 4px 9px; border-radius: 8px;
}
.msgr-threadx:hover, .msgr-threadback:hover { background: var(--m-surface-2); }
.msgr-threadback { display: none; }
@media (hover: hover) and (pointer: fine) {
    .msgr-sidetoggle, .msgr-threadx, .msgr-threadback {
        width: 32px; height: 32px; padding: 0; border-radius: 8px;
        align-items: center; justify-content: center;
    }
    .msgr-sidetoggle, .msgr-threadx { display: inline-flex; }
    .msgr-sidetoggle:hover { background: var(--m-surface-2); }
}
.msgr-threadlist { flex: 1 1 auto; overflow-y: auto; min-height: 0; padding: 10px 12px; background: var(--m-canvas); }
.msgr-threadsep {
    margin: 4px 0 8px; padding-bottom: 6px; border-bottom: 1px solid var(--m-brand-tint);
    font-size: var(--m-meta); font-weight: 700; color: var(--m-brand);
}
.msgr-threadcomp {
    display: flex; align-items: flex-end; gap: 6px;
    padding: 8px 10px calc(8px + var(--m-composer-safe-bottom, env(safe-area-inset-bottom, 0px)));
    border-top: 1px solid var(--m-brand-tint); background: var(--m-surface);
}
.msgr-threadinput {
    flex: 1 1 auto; min-width: 0; resize: none; max-height: 120px;
    border: 1px solid var(--m-brand-tint-2); border-radius: 8px; padding: 7px 9px; background: var(--m-brand-tint);
    font-family: inherit; font-size: var(--m-body); line-height: 1.45; color: var(--m-ink);
}
.msgr-threadinput:focus { outline: 2px solid var(--m-brand-line); outline-offset: 0; }
.msgr-threadsend {
    flex: 0 0 auto; border: 0; border-radius: 8px; background: var(--m-brand); color: var(--m-on-brand);
    padding: 8px 13px; font-size: var(--m-name); cursor: pointer;
}
.msgr-threadsend:disabled { opacity: var(--m-dim-opacity, .5); cursor: default; }
/* 🔔 따라가기 · 방에도 보내기 · 사본 링크 · 비공개 대화방 (2026-09-15) */
.msgr-threadfollow {
    flex: 0 0 auto; border: 1px solid var(--m-hairline); background: var(--m-surface); color: var(--m-muted);
    font-size: var(--m-meta); padding: 4px 8px; border-radius: 999px; cursor: pointer; white-space: nowrap;
}
.msgr-threadfollow.is-on { border-color: var(--m-brand-line); color: var(--m-brand); background: var(--m-brand-tint); }
.msgr-threadbc {
    display: flex; align-items: center; gap: 6px; padding: 6px 12px 0; background: var(--m-surface);
    border-top: 1px solid var(--m-brand-tint); font-size: var(--m-meta); color: var(--m-muted); cursor: pointer;
    white-space: nowrap;   /* 2026-10-07: 옆 선택 상자(폭 100%)에 밀려 «댓글 공개 / 범위» 두 줄로 쪼개졌다 */
}
.msgr-threadbc + .msgr-threadcomp { border-top: 0; }
.msgr-fromthread {
    display: inline-block; margin: 2px 0 4px; border: 0; background: transparent; padding: 0;
    font-size: var(--m-meta); color: var(--m-brand); cursor: pointer; text-decoration: underline;
}
.msgr-parentbar {
    position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 8px;
    padding: 8px 12px; background: var(--m-brand-tint); border-bottom: 1px solid var(--m-brand-tint);
}
.msgr-parentbartxt { flex: 1 1 auto; min-width: 0; font-size: var(--m-meta); color: var(--m-brand); }
.msgr-parentbargo {
    flex: 0 0 auto; border: 1px solid var(--m-brand-line); background: var(--m-surface); color: var(--m-brand);
    font-size: var(--m-meta); padding: 4px 10px; border-radius: 999px; cursor: pointer;
}
.msgr-room-parent { flex: 0 0 auto; margin-right: 4px; font-size: var(--m-meta); color: var(--m-brand-strong); }
.msgr-carerow.is-unread .msgr-carerow-txt { font-weight: 700; color: var(--m-ink); }
@media (max-width: 1180px) {
    /* 정보 패널이 이미 숨는 폭 — 대화를 좁히지 않고 위에 띄운다 */
    .msgr-root.has-thread .msgr-threadpane {
        position: absolute; top: 0; right: 0; bottom: 0; z-index: 30;
        width: min(380px, 100%); box-shadow: -8px 0 24px var(--m-shadow-md);
    }
}
@media (max-width: 799px), (max-width: 959px) and (pointer: coarse), (max-width: 959px) and (hover: none) {
    /* 작은 창 — 방 화면을 통째로 덮는다(카톡 «답장 모아보기»처럼 들어갔다 나오는 화면) */
    .msgr-root.has-thread .msgr-threadpane { left: 0; width: auto; border-left: 0; box-shadow: none; }
    .msgr-threadback { display: inline-flex; }
    .msgr-threadx { display: none; }
}
/* ⌨️ 16px 미만이면 아이폰이 입력칸을 누를 때 화면을 확대하고 돌아오지 않는다 — 본 입력창(13px)도
   같았다(2026-09-15). 폭(폰)과 입력 수단(태블릿 터치) 둘 다 덮는다. 확대는 키보드 높이 계산도 흔든다. */
@media (max-width: 768px), (pointer: coarse) {
    .msgr-input, .msgr-threadinput { font-size: 16px; }
}
/* 메시지 액션 — **떠 있는 형태**라 평소엔 높이를 예약하지 않는다(대화 간격 유지).
   2026-10-07 (사장님 «동작막대가 너무 어색함»): 8개를 한 줄로 펼쳐 이름·시간을 덮고, 짧은 말풍선(본문) 끝에 붙어
   작은 창에선 왼쪽이 잘렸다 → 아이콘 둘(😊·🔖)+⋯ 로 줄였다(본문 오른쪽 위 — 내 글은 그 바로 오른쪽이 줄 끝 ⋯ 라 겹치지 않는다).
   마우스 PC 는 hover·키보드 포커스 때만. 터치는 띄우지 않는다(길게 누르기 시트 · 내 글은 줄 끝 ⋯). */
.msgr-msgbody { position: relative; }
.msgr-msgact {
    /* top -24px: 막대(34px)를 메시지 위에 띄우고 아래 10px 만 말풍선 위 여백에 걸친다(첫 글자는 11px 아래) — -6px 이면 긴 글의 첫 줄 끝을 덮었다(2026-10-07).
       위가 모자라면 JS(wireActbarPlace)가 .is-actin 을 붙여 종전 자리. 마우스를 위로 옮길 때 줄 안에서 막대에 닿게 10px 걸친다. */
    position: absolute; top: -24px; right: 0; z-index: 5;
    display: flex; gap: 2px; background: var(--m-surface); border: 1px solid var(--m-hairline); border-radius: 8px;
    padding: 2px; box-shadow: 0 4px 12px var(--m-shadow-md);
    opacity: 0; pointer-events: none; transition: opacity .12s;
}
.msgr-msg.is-actin .msgr-msgact { top: -6px; }
.msgr-msg:hover .msgr-msgact, .msgr-msg.is-actkeep .msgr-msgact { opacity: 1; pointer-events: auto; }
/* 셸의 위임 이벤트가 :focus-visible 상태만 옮긴다. 마우스 클릭 뒤 남은 포커스는 제외한다. */
.msgr-msg.is-keyboard-focus .msgr-msgact { opacity: 1; pointer-events: auto; }
@media (hover: none) { .msgr-msgact { display: none; } }
.msgr-actbtn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 28px; padding: 0; border: 0; border-radius: 6px;
    background: transparent; font-size: var(--m-body); line-height: 1; color: var(--m-ink-2); cursor: pointer;
}
@media (hover: hover) {
    .msgr-actbtn:hover { background: var(--m-surface-2); }
}
.msgr-actbtn:focus-visible { outline: 2px solid var(--m-brand-strong); outline-offset: 1px; }
.msgr-actbtn.is-on { background: var(--m-warn-tint-2); color: var(--m-warn); }
/* 챙겨야 할 메시지 */
.msgr-carecnt { margin-left: auto; font-size: var(--m-badge); color: var(--m-muted); font-weight: 700; }
.msgr-cardhead { display: flex; align-items: center; }
.msgr-bmitem { background: var(--m-canvas); border-radius: 8px; padding: 7px 9px; margin-bottom: 5px; }
.msgr-bmitem.is-done { opacity: var(--m-dim-opacity, .55); }
.msgr-bmitem.is-done .msgr-bmtext { text-decoration: line-through; }
.msgr-bmdone {
    margin-top: 5px; border: 1px solid var(--m-hairline); background: var(--m-surface); border-radius: 6px;
    padding: 2px 8px; font-size: var(--m-badge); font-weight: 700; color: var(--m-ok); cursor: pointer;
}

/* 💬 메신저 — 내 반응 강조 */
.msgr-reaction.is-mine { --reaction-fill: var(--m-brand-tint); --reaction-line: var(--m-brand-line); }
.msgr-reaction.is-mine .msgr-reactn { color: var(--m-brand-strong); }

/* ═══ 💬 메신저 — 폭·밀도 정리 (2026-08-05 실화면 피드백) ═══
   ★ .global-content-wrap 의 max-width:1400px 때문에 4열이 화면 가운데 절반에만 몰렸다.
     메신저는 파일함처럼 **전체 폭**을 쓴다 — 대화 영역이 좁으면 한 줄에 몇 글자 안 들어간다. */
body.msgr-view .global-content-wrap {
    max-width: none;
    padding: 14px 18px;
}
#global-msgr { max-width: none; }
/* (높이 상수는 fitHeight() 실측으로 대체됨 — 2026-08-06) */

/* ★ 반응 추가(☺+)는 hover 에서만 — 항상 펴 두면 메시지마다 칩이 붙어 대화가 안 읽힌다.
   이미 달린 반응은 항상 보인다(그건 정보다). 터치기기는 hover 가 없으니 상시 노출. */
.msgr-reactadd { opacity: 0; transition: opacity .12s; }
.msgr-msg:hover .msgr-reactadd { opacity: 1; }
@media (hover: none) { .msgr-reactadd { opacity: var(--m-dim-opacity, .55); } }

/* 메시지 밀도 */


/* 이모지 팔레트 */
.msgr-emojipop {
    position: fixed; z-index: 720; display: flex; gap: 2px;
    background: var(--m-surface); border: 1px solid var(--m-hairline); border-radius: 8px;
    padding: 5px 7px; box-shadow: 0 8px 24px var(--m-shadow-lg);
}
.msgr-emojibtn {
    border: 0; background: transparent; font-size: 17px; line-height: 1;
    padding: 3px 4px; border-radius: 6px; cursor: pointer;
}
.msgr-emojibtn:hover { background: var(--m-surface-2); }

/* ═══ 💬 메신저 — Joint 대비 밀도 맞추기 (2026-08-05 나란히 비교) ═══
   원본(joint.now)은 여백이 타이트하고 한 화면에 대화가 많이 담긴다.
   우리는 메시지마다 padding·margin 이 겹쳐 성겼다 — 특히 연속 메시지(묶음)가 벌어졌다. */
.msgr-msgs { padding: 10px 16px; }
.msgr-msg { gap: 8px; padding: 2px 0; }
.msgr-msg.is-grouped { padding: 0 0 1px; }
.msgr-msghead { gap: 6px; margin-bottom: 3px; line-height: 1.4; }
.msgr-msgtext { margin-top: 1px; }
.msgr-daysep { margin: 10px 0 6px; }

/* 아바타 — 사진이 들어오면 <img> 가 채운다(앱 공용 헬퍼가 삽입) */
.msgr-av { width: 32px; height: 32px; flex: 0 0 32px; overflow: hidden; }
.msgr-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.msgr-avspacer { width: 32px; flex: 0 0 32px; }
.msgr-secret .msgr-avspacer { width: 32px; flex: 0 0 32px; }
.msgr-personav .msgr-av { overflow: hidden; }


/* 목록 카드도 한 칸 좁게 */
/* ⚰️ `.msgr-room { margin: 1px 6px }` 제거 — 위 원본 규칙과 **값이 같은 완전 중복**이었다
   (같은 날 padding 을 걷어내자 남은 것이 margin 뿐이었고, 그마저 원본과 동일했다). */
.msgr-acchead { padding: 9px 12px 4px; }

/* 💬 메신저 — ⋮ 방 관리 메뉴 */
.msgr-menu {
    position: fixed; z-index: 720; min-width: 190px;
    background: var(--m-surface); border: 1px solid var(--m-hairline); border-radius: 8px;
    padding: 5px; box-shadow: 0 8px 24px var(--m-shadow-lg);
}
.msgr-menuitem {
    display: block; width: 100%; text-align: left; border: 0; background: transparent;
    border-radius: 8px; padding: 7px 10px; font-size: 12.5px; color: var(--m-ink-secondary); cursor: pointer;
}
.msgr-menuitem:hover { background: var(--m-surface-2); }
.msgr-menuitem.is-danger { color: var(--m-danger-action); }
.msgr-menuitem.is-danger:hover { background: var(--m-danger-tint); }
.msgr-menunote { padding: 6px 10px; font-size: var(--m-badge); color: var(--m-muted); line-height: 1.5; }

/* 💬 메신저 — 🌡 대화방 온도 */
.msgr-tempchart {
    display: flex; align-items: flex-end; gap: 2px; height: 54px;
    padding: 4px 2px 0; border-bottom: 1px solid var(--m-surface-2);
}
.msgr-tempcol { flex: 1 1 0; height: 100%; display: flex; align-items: flex-end; }
.msgr-tempbar {
    width: 100%; border-radius: 6px 6px 0 0;
    background: linear-gradient(180deg, var(--m-hot-gradient), var(--m-warm-accent));
}
.msgr-tempbar.is-empty { background: var(--m-hairline); }
.msgr-tempbar.is-today { background: var(--m-brand); }
.msgr-tempaxis { display: flex; justify-content: space-between; font-size: var(--m-badge); color: var(--m-muted); margin-top: 3px; }
.msgr-tempmood { display: flex; align-items: center; gap: 6px; margin-top: 9px; font-size: 12.5px; }
.msgr-tempdeg {
    font-size: 11px; font-weight: 800; color: var(--m-ink-2); background: var(--m-surface-2);
    border-radius: 8px; padding: 1px 8px;
}
.msgr-tempdeg.is-hot { color: var(--m-hot); background: var(--m-hot-tint); }
.msgr-tempdeg.is-cold { color: var(--m-info); background: var(--m-info-tint); }
.msgr-tempnote { font-size: var(--m-badge); color: var(--m-ink-meta); margin-top: 6px; line-height: 1.5; }
.msgr-level { font-size: var(--m-badge); }

/* 💬 메신저 — 🗂 여러 대화방 탭 */
/* 📑 탭 목록 — 가로 스크롤은 **여기 한 곳만**. 방을 여러 개 열면 넘치는 건 자연스럽다(브라우저 탭).
   ⚠ `overflow-y: hidden` 을 **명시**한다 — 안 쓰면 `overflow-x: auto` 때문에 세로도 `auto` 가
     되어 스크롤바 자리만큼 탭이 잘린다(위 `.msgr-tabbar` 가 겪은 그 함정).
     높이 제한이 없어 숨겨도 잘릴 내용이 없다. */
.msgr-tabstrip { display: flex; align-items: center; gap: 3px; overflow-x: auto; overflow-y: hidden; min-width: 0; flex: 1 1 auto; scrollbar-width: none; }   /* 2026-10-07: 표준 속성이 있어야 숨는다 — 전역 `* { scrollbar-width: thin }`(style.css)이 걸리면 크롬·PC 앱은 아래 ::-webkit-scrollbar 를 무시해 회색 막대가 보였다 */
.msgr-tabstrip::-webkit-scrollbar { height: 0; }
.msgr-tab { flex: 0 0 auto; max-width: 190px; }
.msgr-tablabel { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 130px; }
.msgr-tabx {
    font-size: 10px; color: var(--m-muted); margin-left: 2px; padding: 0 2px;
    border-radius: 6px; opacity: 0; transition: opacity .12s;
}
.msgr-tab:hover .msgr-tabx, .msgr-tab.is-active .msgr-tabx { opacity: 1; }
.msgr-tabx:hover { background: var(--m-hairline); color: var(--m-ink-secondary); }
@media (hover: none) { .msgr-tabx { opacity: var(--m-dim-opacity, .6); } }
.msgr-tabdotunread { font-size: 7px; color: var(--m-brand); margin-left: 1px; }

/* 💬 메신저 — 📌 인용 블록 · 메시지로 이동 */
.msgr-syswrap { margin: 8px 0; }
/* 챙김 원문은 작성자·본문·상태를 세로로 읽는다. 일반 답장 미리보기와 스타일을 분리한다. */
.msgr-carequote {
    display: block; min-width: 0; max-width: 460px; margin: 5px 0 0; padding: 8px 12px;
    border-left: 3px solid var(--m-brand-line); background: var(--m-canvas); border-radius: 0 8px 8px 0;
}
.msgr-quotehead { display: flex; align-items: center; gap: 6px; min-width: 0; }
.msgr-quoteby { min-width: 0; overflow-wrap: anywhere; font-size: var(--m-meta); font-weight: 700; color: var(--m-brand); }
.msgr-carequote-text { min-width: 0; font-size: var(--m-meta); color: var(--m-ink-2); line-height: 1.5; margin-top: 6px; white-space: pre-wrap; overflow-wrap: anywhere;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.msgr-quotego {
    margin-top: 4px; border: 0; background: transparent; padding: 0;
    font-size: 11px; font-weight: 700; color: var(--m-brand); cursor: pointer;
}
.msgr-quotego:hover { text-decoration: underline; }
.msgr-bmtext.is-link { cursor: pointer; }
.msgr-bmtext.is-link:hover { color: var(--m-brand); text-decoration: underline; }

/* 📍 이동 대상 하이라이트 — 잠깐 번쩍이고 사라진다 */
.msgr-msg.msgr-hl { background: var(--m-highlight); border-radius: 8px; }
.msgr-msg.msgr-hl { animation: msgrHl 1.6s ease-out; }
@keyframes msgrHl {
    0% { background: #fde68a; }
    100% { background: transparent; }
}

/* 💬 메신저 — ⚠ `scroll-behavior: smooth` 를 쓰지 말 것.
   붙이면 `scrollTop` **대입까지 애니메이션**이 되어, 대입 직후 값을 읽는 코드
   (paintMessages 의 하단 고정, scrollToMessage 의 위치 확인)가 전부 0 을 본다.
   실제로 그 CSS 한 줄 때문에 '방을 열어도 맨 아래로 안 가고 메시지 이동도 안 되는'
   상태가 됐다(2026-08-05 하네스 실측). 즉시 이동이 확실한 쪽을 택한다. */

/* 💬 메신저 — 생성 모달 연결 영역 */
.msgr-linkwrap { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--m-hairline); }
.msgr-linkwrap .msgr-fi { margin-top: 6px; }

/* 💬 메신저 — 📌 고정 배너 (대화 스크롤 맨 위 sticky) */
.msgr-pinbar {
    /* top 은 대화 목록 위 여백(.msgr-msgs padding-top 10px)만큼 음수 — 0 이면 그 틈으로 지나가는 메시지·날짜가 비쳤다(2026-10-07) */
    position: sticky; top: -10px; z-index: 5;
    display: flex; align-items: center; gap: 4px;
    margin: 0 12px 6px; padding: 7px 10px;
    background: var(--m-warn-tint); border: 1px solid var(--m-warn-line); border-radius: 8px;
    box-shadow: 0 2px 8px var(--m-shadow-xs);
}
.msgr-pinmain {
    display: flex; align-items: center; gap: 7px; min-width: 0; flex: 1;
    background: none; border: none; cursor: pointer; padding: 0;
    font-size: 12.5px; color: var(--m-warn-strong); text-align: left;
}
.msgr-pintxt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.msgr-pinx {
    flex: none; background: none; border: none; cursor: pointer;
    color: var(--m-warn-action); font-size: 12px; padding: 2px 5px; border-radius: 6px;
}
.msgr-pinx:hover { background: var(--m-warn-tint-2); }

/* 💬 메신저 — 목록 안읽음 필터 칩 · 방 행 아이콘 */
.msgr-ufilter {
    flex: none; width: 30px; border: 1px solid var(--m-hairline); border-radius: 8px;
    background: var(--m-surface); color: var(--m-ink-meta); font-size: 11px; cursor: pointer;
}
.msgr-ufilter:hover { background: var(--m-canvas); }
.msgr-ufilter.is-on { color: var(--m-brand); border-color: var(--m-brand-line); background: var(--m-brand-tint); }
.msgr-room-pin { flex: none; font-size: 10px; }
.msgr-room-mute { flex: none; font-size: 10px; opacity: var(--m-dim-opacity, .55); }

/* 💬 메신저 — 관리 버튼 켜짐 상태 · 초대 첫 메시지 textarea */
.msgr-fta { resize: vertical; min-height: 44px; font-family: inherit; }

/* 💬 메신저 — 📅 날짜 감지 일정 등록 칩 */
.msgr-datechip {
    display: inline-flex; align-items: center; gap: 4px;
    margin-top: 5px; padding: 3px 9px;
    background: var(--m-brand-tint); border: 1px solid var(--m-brand-line); border-radius: 999px;
    color: var(--m-brand); font-size: 11px; font-weight: 600; cursor: pointer;
    width: fit-content;
}
.msgr-datechip:hover { background: var(--m-hover-fill); }

/* 💬 메신저 — ✏️ 메시지 편집 */
.msgr-edited { font-size: var(--m-badge); color: var(--m-muted); margin-top: 2px; }
.msgr-editta {
    width: 100%; min-height: 56px; resize: vertical;
    border: 1px solid var(--m-brand-line); border-radius: 8px; padding: 8px 10px;
    font: inherit; font-size: 13px; outline: none; background: var(--m-surface);
}
.msgr-editrow { display: flex; gap: 6px; margin-top: 6px; }

/* 💬 메신저 — 🏢 거래처 관리 패널 (레일 오른쪽 전체 오버레이) */
.msgr-clients { display: none; }
.msgr-root.is-clients .msgr-clients {
    display: block; position: absolute; top: 0; right: 0; bottom: 0; left: 68px;
    background: var(--m-canvas); z-index: 8; overflow: hidden;
}
.msgr-root.is-clients .msgr-list,
.msgr-root.is-clients .msgr-main,
.msgr-root.is-clients .msgr-side { visibility: hidden; }
.msgr-cliwrap { display: flex; height: 100%; }
.msgr-clilist { flex: 1; min-width: 0; overflow-y: auto; padding: 18px 20px; }
.msgr-clihead { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.msgr-clititle { font-size: 17px; font-weight: 800; color: var(--m-ink); }
.msgr-clihint { font-size: 11.5px; color: var(--m-muted); margin: 6px 0 14px; }
.msgr-clitbl { border: 1px solid var(--m-hairline); border-radius: 12px; background: var(--m-surface); overflow: hidden; }
.msgr-clirow {
    /* 거래처 · 메인담당 · 메인연락처 · 대화방수 · 메모 (2026-08-06 연락처 열 추가)
       ⓘ 실제 열 목록은 JS 가 `--cli-cols` 로 정한다 — 담당·연락처가 **한 줄도 없으면
         그 열을 빼기** 때문에(msgr-shell-dialogs.js paintClients) 여기 값은 5열 폴백이다. */
    display: grid; grid-template-columns: var(--cli-cols, minmax(130px, 1.3fr) .9fr .9fr 60px 1.1fr);
    gap: 8px; width: 100%; text-align: left; padding: 10px 14px;
    background: var(--m-surface); border: none; border-bottom: 1px solid var(--m-surface-2);
    cursor: pointer; font-size: 12.5px; color: var(--m-ink-secondary); align-items: center;
}
.msgr-clirow:hover { background: var(--m-canvas); }
.msgr-clirow.is-active { background: var(--m-brand-tint); }
.msgr-clirow.is-head {
    cursor: default; font-size: 11px; font-weight: 700; color: var(--m-muted);
    background: var(--m-canvas); border-bottom: 1px solid var(--m-hairline);
}
.msgr-clicell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-clicell.c0 { display: flex; align-items: center; gap: 7px; font-weight: 700; color: var(--m-ink); }
.msgr-clicell.c3 { text-align: center; }
.msgr-clicell.c4 { color: var(--m-muted); }
.msgr-cliprof {
    width: 340px; flex: none; border-left: 1px solid var(--m-hairline); background: var(--m-surface);
    overflow-y: auto; padding: 18px 16px;
}
.msgr-clip-top { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.msgr-clip-avatar {
    width: 44px; height: 44px; border-radius: 12px; flex: none;
    display: flex; align-items: center; justify-content: center;
    font-size: 18px; font-weight: 800;
}
.msgr-clip-name { flex: 1; min-width: 0; font-size: 15px; font-weight: 800; color: var(--m-ink); }
.msgr-clip-sec { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--m-surface-2); }
.msgr-clip-sechead { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.msgr-clip-sechead .msgr-btn { margin-left: auto; padding: 3px 9px; font-size: 11px; }
.msgr-clip-sectitle { font-size: 12px; font-weight: 800; color: var(--m-ink-secondary); }
.msgr-clip-secsub { font-size: var(--m-badge); color: var(--m-muted); }
.msgr-clip-memo { font-size: 12.5px; color: var(--m-ink-2); white-space: pre-wrap; line-height: 1.55; }
.msgr-clip-memo.is-empty { color: var(--m-ink-meta); }
.msgr-clip-arow { display: flex; align-items: flex-start; gap: 8px; margin-top: 8px; position: relative; }
.msgr-clip-alabel { flex: none; width: 62px; font-size: 11.5px; color: var(--m-muted); padding-top: 4px; }
.msgr-clip-achips { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; min-width: 0; }
.msgr-clip-achip {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 9px; border: 1px solid var(--m-hairline); border-radius: 999px;
    background: var(--m-canvas); font-size: 11.5px; color: var(--m-ink-secondary); cursor: pointer;
}
.msgr-clip-achip:hover { background: var(--m-danger-tint); border-color: var(--m-danger-line); }
.msgr-clip-ax { font-size: 9px; color: var(--m-muted); }
.msgr-clip-aempty { font-size: 11.5px; color: var(--m-ink-meta); }
.msgr-clip-aadd {
    width: 24px; height: 24px; border: 1px dashed var(--m-line-strong); border-radius: 999px;
    background: var(--m-surface); color: var(--m-muted); font-size: 12px; cursor: pointer;
}
.msgr-clip-aadd:hover { background: var(--m-canvas); }
.msgr-clip-room {
    display: block; width: 100%; text-align: left; padding: 9px 10px; margin-top: 6px;
    border: 1px solid var(--m-surface-2); border-radius: 8px; background: var(--m-surface); cursor: pointer;
}
.msgr-clip-room:hover { background: var(--m-canvas); }
.msgr-clip-roomname { display: block; font-size: 12.5px; font-weight: 700; color: var(--m-ink); }
.msgr-clip-roomat { display: block; font-size: var(--m-badge); color: var(--m-muted); margin-top: 2px; }

/* 💬 메신저 — 🏠 홈 칩 + 🔖 챙길 메시지 목록 + 그룹 접기 */
/* ⚖️ 위아래 여백을 맞춘다 (2026-08-08 사장님 "팀대화방 칸 위에 선이 붙어있잖아").
   종전 `0 10px 8px` — **위가 0** 이라 브랜드 줄의 밑선이 칩에 그대로 닿고 아래만 떠 있었다.
   같은 줄 간격이면 선이 «칸을 나누는 선»으로 읽히고, 붙으면 «칸에 달린 테두리»로 보인다. */
.msgr-homechips { padding: 8px 10px; border-bottom: 1px solid var(--m-surface-2); }
.msgr-homechiprow { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.msgr-homechip {
    display: inline-flex; align-items: center; justify-content: center; gap: 5px;
    min-width: 0; min-height: 36px; white-space: nowrap; word-break: keep-all;
    padding: 7px 10px; border: 1px solid var(--m-hairline); border-radius: var(--m-r2);
    background: var(--m-surface); font-size: var(--m-meta); font-weight: 600; color: var(--m-ink-2); cursor: pointer;
}
.msgr-homechip.is-on { background: var(--m-brand-tint); border-color: var(--m-brand-line); color: var(--m-brand); }
.msgr-homechipn {
    flex: 0 0 auto; min-width: 17px; height: 17px; padding: 0 5px; border-radius: 999px;
    background: var(--m-brand); color: var(--m-on-brand); font-size: var(--m-badge); font-weight: 800;
    display: inline-flex; align-items: center; justify-content: center;
}
.msgr-carerow {
    display: block; width: 100%; text-align: left; padding: 10px 12px;
    background: var(--m-surface); border: none; border-bottom: 1px solid var(--m-surface-2); cursor: pointer;
}
.msgr-carerow:hover { background: var(--m-canvas); }
.msgr-carerow-top { display: flex; align-items: center; gap: 8px; }
.msgr-carerow-room { flex: 1; min-width: 0; font-size: 12px; font-weight: 700; color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-carerow-txt { font-size: 11.5px; color: var(--m-muted); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-acccaret { margin-left: auto; font-size: 10px; color: var(--m-ink-meta); }
.msgr-acchead { cursor: pointer; }
.msgr-accunread {
    min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
    background: var(--m-brand); color: var(--m-on-brand); font-size: var(--m-badge); font-weight: 800;
    display: inline-flex; align-items: center; justify-content: center;
}

/* 모바일 — 거래처 패널은 세로 스택, 프로필이 아래로 */
body:not(.msgr-popout) .msgr-root.is-clients .msgr-clients { left: 0; }
@media (max-width: 768px) and (pointer: coarse), (max-width: 768px) and (hover: none) {
    .msgr-root.is-clients .msgr-clients { left: 0; padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px)); }
}
@media (max-width: 799px), (max-width: 959px) and (pointer: coarse), (max-width: 959px) and (hover: none) {
    .msgr-cliwrap { flex-direction: column; }
    .msgr-cliprof { width: auto; border-left: none; border-top: 1px solid var(--m-hairline); }
}

/* 🪟 창분리(팝업) — 메신저 외 모든 뷰를 CSS 로 물리 차단.
   부팅(fast paint → 전체 onSnapshot)이 홈을 몇 번을 다시 그리고 #view-home 의
   active 를 되살려도 화면에 나올 수 없다. 라우팅 재확인 루프(msgr-popout.js)는
   탭 active 만 보므로 '홈 컨테이너만 되살아나는' 이 경우를 원리상 못 잡는다 —
   표시 계층에서 끝내는 것이 유일하게 레이스 없는 수리다(2026-08-05 실사고 2차). */
body.msgr-popout .view-section:not(#view-global) { display: none !important; }
body.msgr-popout #view-global { display: block !important; }
body.msgr-popout .global-content-wrap > div:not(#global-msgr) { display: none !important; }
body.msgr-popout #global-msgr { display: block !important; }

/* 💬 메신저 — 🔔 알림 센터 + 📨 받은 초대 */
.msgr-notibtn {
    position: relative; flex: none; width: 34px;
    border: 1px solid var(--m-hairline); border-radius: 8px; background: var(--m-surface);
    font-size: 13px; cursor: pointer;
}
.msgr-notibtn:hover { background: var(--m-canvas); }
.msgr-notibtn.is-on { background: var(--m-brand-tint); border-color: var(--m-brand-line); }
.msgr-notibadge {
    position: absolute; top: -5px; right: -5px;
    min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
    background: var(--m-brand); color: var(--m-on-brand); font-size: var(--m-badge); font-weight: 800;
    display: inline-flex; align-items: center; justify-content: center;
    border: 2px solid var(--m-surface);
}
.msgr-invcard { padding: 12px; border-bottom: 1px solid var(--m-surface-2); background: var(--m-surface); }
.msgr-invbtnrow { display: flex; gap: 6px; margin-top: 8px; }
.msgr-invbtnrow .msgr-btn { flex: 1; }
.msgr-notirow { display: flex; align-items: stretch; border-bottom: 1px solid var(--m-surface-2); background: var(--m-surface); }
.msgr-notimain {
    flex: 1; min-width: 0; text-align: left; padding: 10px 12px;
    background: none; border: none; cursor: pointer;
}
.msgr-notimain:hover { background: var(--m-canvas); }
.msgr-notiread {
    flex: none; align-self: center; margin-right: 10px;
    padding: 4px 10px; border: 1px solid var(--m-hairline); border-radius: 999px;
    background: var(--m-surface); font-size: 11px; color: var(--m-muted); cursor: pointer;
}
.msgr-notiread:hover { background: var(--m-brand-tint); border-color: var(--m-brand-line); color: var(--m-brand-strong); }
.msgr-notiall {
    display: block; width: calc(100% - 20px); margin: 10px;
    padding: 7px; border: 1px dashed var(--m-line-strong); border-radius: 8px;
    background: var(--m-canvas); font-size: 12px; color: var(--m-ink-2); cursor: pointer;
}
.msgr-notiall:hover { background: var(--m-brand-tint); }

/* 🪟 창분리 3차 — JS 형제 격리(msgr-popout.js isolate)가 붙이는 클래스 + 여백 제거.
   페이지 헤더(#topbarTitle)처럼 뷰 섹션 밖에 사는 요소는 CSS 열거로 못 덮는다(실측). */
.msgr-pop-hide { display: none !important; }
body.msgr-popout .content-area { margin: 0 !important; padding: 0 !important; }
body.msgr-popout #view-global { padding: 0 !important; }

/* 🪟 창분리 4차(최종) — 재부모화된 #global-msgr 가 창 전체를 차지 */
body.msgr-popout #global-msgr {
    /* 🚨 **`inset: 0` 이 상단 안전영역 처리를 통째로 무효화하고 있었다** (2026-08-08
       아이폰 17 홈 화면 설치본 실측 — 「어니스트」가 시계와, 🔍🔔 가 배터리와 겹쳤다).
       위 `html.msgr-popout-root body { padding-top: var(--m-safetop) }` 는 **일반 흐름**을
       밀 뿐이고, 이 요소는 `position: fixed` 라 body 패딩을 원리상 안 받는다 → top 0.
       ⚠ 게다가 아래 :3830 이 높이만 `100dvh − safetop` 으로 줄여 놔서, 위는 상태바에
         물리고 **아래는 그만큼 떠 «찌그러진» 띠**가 생겼다 — 한 원인의 두 증상이다.
       → 높이를 줄이는 대신 **시작점을 안전영역만큼 내린다.** top=safetop·bottom=0 이라
         :3830 의 높이(=100dvh−safetop)와 정확히 같은 상자가 되어 두 규칙이 안 싸운다.
       ⓘ 좌우도 받는다 — 가로 모드에서 노치 쪽으로 내용이 들어가지 않게. */
    position: fixed;
    inset: var(--m-safetop, 0px) env(safe-area-inset-right, 0px) 0 env(safe-area-inset-left, 0px);
    z-index: 10;
    overflow: hidden; background: var(--m-surface-2);
}
/* ⚠ 목업 배너(.msgr-phase)를 **숨기지 않는다** — 2026-08-06 실사고: 전용 창이 목업으로
   고정됐는데 배너까지 가려져 있어 직원들이 가짜 대화를 진짜로 봤다. 자리를 조금 차지해도
   «지금 보는 게 실데이터가 아니다»는 사실이 화면에 남아 있어야 한다. */
body.msgr-popout .msgr-phase { font-size: 12px; padding: 6px 12px; }

/* 💬 메신저 — 🗑 삭제된 메시지 자리표시 */
.msgr-deleted {
    font-size: 12.5px; color: var(--m-muted); font-style: italic;
    padding: 2px 0;
}

/* 💬 메신저 — ⌨️ 입력 중 (컴포저 바로 위, 대화 재렌더와 분리) */
.msgr-typing {
    display: flex; align-items: center; gap: 6px;
    padding: 4px 16px; font-size: 11.5px; color: var(--m-muted);
    border-top: 1px solid var(--m-canvas); background: var(--m-surface);
}
.msgr-typedots { color: var(--m-brand); letter-spacing: 1px; animation: msgrTypeBlink 1.2s ease-in-out infinite; }
@keyframes msgrTypeBlink { 0%, 100% { opacity: var(--m-dot-min-opacity, .3); } 50% { opacity: 1; } }

/* 💬 메신저 — 🔖 챙기기 기한 */
.msgr-bmfoot { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.msgr-bmdue {
    display: inline-flex; align-items: center;
    padding: 2px 8px; border: 1px solid var(--m-hairline); border-radius: 999px;
    background: var(--m-surface); font-size: var(--m-badge); color: var(--m-ink-2); cursor: pointer;
}
.msgr-bmdue:hover { background: var(--m-canvas); }
.msgr-bmdue.is-empty { border-style: dashed; color: var(--m-muted); }
.msgr-bmdue.is-over { background: var(--m-danger-tint); border-color: var(--m-danger-line); color: var(--m-danger); font-weight: 700; }
.msgr-bmdueinput {
    border: 1px solid var(--m-brand-line); border-radius: 8px; padding: 2px 6px;
    font: inherit; font-size: 11px; outline: none;
}
.msgr-overdue {
    padding: 1px 7px; border-radius: 999px;
    background: var(--m-danger-tint); color: var(--m-danger); font-size: var(--m-badge); font-weight: 800;
}
.msgr-bmfoot .msgr-bmdone { margin-left: auto; }

/* 💬 메신저 — 📎 초대 첫 메시지 첨부 */
.msgr-invfiles { margin-top: 8px; }
.msgr-invfilelist { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.msgr-invfilechip {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 9px; border: 1px solid var(--m-hairline); border-radius: 999px;
    background: var(--m-canvas); font-size: 11px; color: var(--m-ink-secondary); max-width: 100%;
}
.msgr-invfilechip > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-invfilex { border: 0; background: none; color: var(--m-muted); font-size: 10px; cursor: pointer; padding: 0; }
.msgr-invfilex:hover { color: var(--m-danger); }

/* 💬 메신저 — 🤖 봇 보고서 카드 (자금일보·다이제스트)
   ★ 가운데 알약이 아니라 좌측 카드다: 여러 줄 보고서라 줄바꿈이 살아야 하고,
     가로로 늘어나면 읽는 눈이 갈 곳을 잃는다. */
.msgr-botcard {
    max-width: 440px; margin: 10px 0 10px 43px;
    border: 1px solid var(--m-hairline); border-left: 3px solid var(--m-brand);
    border-radius: 0 12px 12px 0; background: var(--m-surface); overflow: hidden;
}
.msgr-bothead {
    display: flex; align-items: center; gap: 7px;
    padding: 9px 12px 7px; border-bottom: 1px solid var(--m-canvas);
}
.msgr-botbadge {
    flex: none; padding: 1px 6px; border-radius: 6px;
    background: var(--m-brand-tint); color: var(--m-brand-strong); font-size: var(--m-badge); font-weight: 800; letter-spacing: .4px;
}
.msgr-bottitle {
    flex: 1; min-width: 0; font-size: 12.5px; font-weight: 800; color: var(--m-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msgr-botat { flex: none; font-size: var(--m-badge); color: var(--m-ink-meta); }
.msgr-botbody {
    padding: 9px 12px 11px; font-size: 12.5px; color: var(--m-ink-secondary); line-height: 1.75;
    white-space: pre-line;           /* ★ 서버가 보낸 \n 을 살리는 한 줄 */
    word-break: keep-all; overflow-wrap: anywhere;
}
@media (max-width: 768px) { .msgr-botcard { margin-left: 12px; max-width: none; } }

/* 💬 메신저 — 🔖 챙기기 안내 (사람이 보낸 말처럼 · 인용 카드 일체형) */
.msgr-caremsg .msgr-caretext { font-size: 12.5px; color: var(--m-muted); margin-bottom: 5px; }
.msgr-av-xs { width: 18px; height: 18px; font-size: 8px; border-radius: 6px; }
.msgr-quotehead .msgr-av-xs { flex: 0 0 18px; }
.msgr-quotefoot {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 7px;
    padding-top: 6px; border-top: 1px solid var(--m-surface-2);
    font-size: var(--m-badge); color: var(--m-muted);
}
.msgr-quotefoot > * { min-width: 0; overflow-wrap: anywhere; }
.msgr-quotefoot .msgr-quotego { margin: 0 0 0 auto; }
.msgr-quotedone { color: var(--m-ok-action); font-weight: 700; }
.msgr-quotecancel { color: var(--m-ink-meta); }
.msgr-quotedue { color: var(--m-muted); }
.msgr-quotedue.is-over { color: var(--m-danger); font-weight: 700; }

/* 팀 통계와 표는 거래처 목록과 같은 표면·경계 토큰을 공유한다. */
.msgr-team .msgr-clilist { flex: 1; width: 100%; min-width: 0; }
.msgr-team-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin: 0 0 18px; }
.msgr-team-stat { min-width: 0; padding: 16px 14px; border: 1px solid var(--m-hairline); border-radius: 12px; background: var(--m-surface); }
.msgr-team-stat-label { margin-bottom: 8px; color: var(--m-muted); font-size: var(--m-badge); overflow-wrap: anywhere; }
.msgr-team-stat-value { margin-right: 8px; color: var(--m-ink); font-size: var(--m-title); font-variant-numeric: tabular-nums; }
.msgr-team-stat-detail { display: inline-block; color: var(--m-muted); font-size: var(--m-badge); }
.msgr-team-error { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; color: var(--m-danger); }
.msgr-team.is-table .msgr-clilist { display: flex; flex-direction: column; min-height: 0; padding: 20px 24px 0; overflow: hidden; }
.msgr-team.is-table .msgr-clihead, .msgr-team-stats, .msgr-team-error { flex: none; }
.msgr-team .msgr-team-table th:nth-child(1) { width: 26%; }
.msgr-team .msgr-team-table th:nth-child(2) { width: 14%; }
.msgr-team .msgr-team-table th:nth-child(3), .msgr-team .msgr-team-table th:nth-child(4), .msgr-team .msgr-team-table th:nth-child(5) { width: 15%; }
.msgr-team .msgr-team-table th:nth-child(6) { width: 15%; }
.msgr-team-table-row:hover { background: var(--m-canvas); }
.msgr-teamrow > .msgr-cli-company { flex: 1; min-width: 0; }
.msgr-teamname { overflow-wrap: anywhere; }
@media (max-width: 999px) {
    .msgr-team-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* 💬 메신저 — 👥 팀 관리 패널 */
.msgr-teamrow {
    display: flex; align-items: center; gap: 11px;
    padding: 11px 14px; background: var(--m-surface);
    border-bottom: 1px solid var(--m-surface-2);
}
.msgr-teamrow:last-child { border-bottom: 0; }
.msgr-teamrow:hover { background: var(--m-canvas); }
.msgr-teaminfo { flex: 1; min-width: 0; }
.msgr-teamname {
    display: flex; align-items: center; gap: 6px;
    font-size: 13px; font-weight: 700; color: var(--m-ink);
}
.msgr-teamme {
    padding: 1px 6px; border-radius: 999px;
    background: var(--m-brand-tint); color: var(--m-brand-strong); font-size: var(--m-badge); font-weight: 800;
}
.msgr-teamrole { font-size: 11px; color: var(--m-muted); margin-top: 1px; }
.msgr-av-sm { width: 34px; height: 34px; font-size: 12px; }
.msgr-clip-dbval { font-size: 12px; color: var(--m-ink-secondary); word-break: break-all; }
.msgr-phonechip { background: var(--m-ok-tint); border-color: var(--m-ok-line); color: var(--m-ok-phone); }
.msgr-phonechip:hover { background: var(--m-ok-tint-2); }

/* ═══════════════════════════════════════════════════════════
   💬 메신저 — 시각 폴리시 (2026-08-06)
   "흉내낸 수준이지 깔끔하지 않다"는 지적에 대한 정리. 색·모양을 새로 만들지 않고
   **이미 쓰던 값들의 일관성**을 맞춘다: 경계선 한 톤(#f1f5f9/#e2e8f0), 라운드 2단계
   (칩 999px / 면 12px), 여백 4의 배수, 폰트 3단(11 보조·12.5 본문·13 강조).
   ═══════════════════════════════════════════════════════════ */

/* ① 목록 — 검색줄 밀도와 정렬 */
.msgr-searchwrap { gap: 5px; padding: 11px 10px 9px; align-items: center; }
.msgr-search { height: 32px; border-radius: 8px; font-size: var(--m-base); }
.msgr-newbtn, .msgr-notibtn, .msgr-ufilter { height: 32px; }
.msgr-newbtn { border-radius: 8px; }

/* ② 고정 메뉴 — 켜짐 상태를 실제로 보여준다(죽은 항목을 없앤 자리) */
.msgr-fixitem.is-active { background: var(--m-brand-tint); color: var(--m-brand-strong); font-weight: 700; }
.msgr-fixitem.is-active .msgr-fixic { opacity: 1; }

/* ③ 대화방 행 — 제목/미리보기 사이 숨 쉴 틈, 활성 행은 색면 대신 좌측 인디케이터 */
.msgr-room { padding: 10px 12px; }
.msgr-room-bot { margin-top: 3px; }
.msgr-room.is-active { position: relative; }
.msgr-room.is-active::before {
    content: ''; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px;
    background: var(--m-brand); border-radius: 0 999px 999px 0;
}

/* ④ 말풍선 — 새 발화는 8px, 연속 발화는 3px로 구분한다. */
.msgr-msg { margin-bottom: 8px; }
.msgr-msg.is-grouped { margin-bottom: 3px; }

/* ⑤ 칩 — 날짜·전화·기한이 같은 크기·같은 라운드로 보이게 */
.msgr-datechip, .msgr-phonechip { padding: 3px 10px; font-size: var(--m-meta); margin-top: 6px; }

/* ⑥ 우측 패널 — 카드 경계를 한 톤으로, 제목은 한 급 작게 */
.msgr-card { border-color: var(--m-surface-2); }
.msgr-cardhead { font-size: 12px; }


/* ═══════════════════════════════════════════════════════════
   📱 메신저 모바일 — Joint 배치에 맞춤 (2026-08-06)
   참조: 헤더 «워크스페이스명 + 🔍 🔔 ＋» · 미읽음은 행 전체 톤 · 그룹 헤더에 빨간 N
   ═══════════════════════════════════════════════════════════ */

/* 브랜드·검색 토글은 데스크톱에선 없다(검색창이 항상 열려 있다) */
.msgr-brand, .msgr-brandlogo, .msgr-searchtog { display: none; }

/* 미읽음 = 행 전체 톤 — 작은 점보다 목록에서 먼저 눈에 들어온다 */
/* 📬 미읽음 — **글자 굵기와 점**으로 알린다. 배경을 칠하면 대부분의 방이
   미읽음인 평소 상태에서 목록 전체가 분홍으로 물들어(실측) 정작 어느 게
   급한지 구분이 안 된다. 색은 '드문 것'에만 써야 신호가 된다. */
.msgr-room.is-unread .msgr-room-title { font-weight: 700; color: var(--m-ink); }
.msgr-room.is-unread .msgr-room-last { color: var(--m-ink-secondary); font-weight: 500; }
.msgr-room.is-unread .msgr-room-at { color: var(--m-brand); font-weight: 600; }
/* ⚠ 선택 중인 방(보라 배경)은 **반드시 뒤에서 되돌린다** — 위 미읽음 색이 같은
   명시도라 파일 순서로 이겨 흰 글자를 덮고, 보라 위 남색 글자가 안 읽힌다(실측). */
.msgr-room.is-active.is-unread .msgr-room-title,
.msgr-room.is-active.is-unread .msgr-room-last { color: var(--m-brand); }
.msgr-room.is-active.is-unread .msgr-room-at,
.msgr-room.is-active.is-unread .msgr-room-by { color: var(--m-brand); }

.msgr-phone-nav, .msgr-phone-page, .msgr-phone-filters { display: none; }
.msgr-phone-icon { width: 22px; height: 22px; flex: none; }
.msgr-searchwrap .msgr-phone-icon { display: none; }
.msgr-phone-tab { font-size: var(--fs-badge); }
.msgr-brand { font-size: var(--fs-title); }
.msgr-phone-fixed .msgr-room-bot { font-size: var(--fs-meta); }
.msgr-phone-badge { font-size: var(--fs-badge); border-radius: 999px; padding: 0 5px; background: var(--m-badge); color: var(--m-on-badge); font-weight: 700; }
.msgr-phone-heading { font-size: var(--fs-title); font-weight: 800; margin: 0; padding: 16px; }
.msgr-phone-menuitem, .msgr-phone-profile { font-size: var(--fs-base); }
.msgr-phone-care, .msgr-phone-back, .msgr-phone-segment { font-size: var(--fs-base); }
.msgr-swipe-actions button { font-size: var(--fs-badge); }
.msgr-phone-undo { font-size: var(--fs-meta); }
@media (max-width: 768px) {
    .msgr-root > .msgr-rail, body.msgr-popout .msgr-root > .msgr-rail, body.msgr-popout .msgr-root.is-clients > .msgr-rail { display: none; }
    .msgr-root .msgr-homechips, .msgr-root .msgr-fixed,
    .msgr-root .msgr-desktop-only, .msgr-root .msgr-desktop-icon,
    .msgr-root .msgr-brandlogo, .msgr-root .msgr-ufilter { display: none; }
    body.msgr-view .msgr-installbar { display: none; }
    .msgr-root .msgr-brand { display: block; flex: 1; min-width: 0; font-weight: 800; }
    .msgr-root .msgr-search { display: none; font-size: 16px; }
    .msgr-root .is-search-open .msgr-brand { display: none; }
    .msgr-root .is-search-open .msgr-search { display: block; flex: 1; min-width: 0; }
    .msgr-root .msgr-searchwrap { gap: 10px; padding: 10px 16px; }
    .msgr-root .msgr-searchtog, .msgr-root .msgr-notibtn, .msgr-root .msgr-newbtn {
        display: inline-flex; align-items: center; justify-content: center;
        position: relative; flex: none; width: 34px; height: 34px; min-width: 34px; min-height: 34px; padding: 0; border: 0;
    }
    .msgr-root .msgr-searchtog::after, .msgr-root .msgr-notibtn::after, .msgr-root .msgr-newbtn::after { content: ''; position: absolute; inset: -5px; }
    .msgr-root .msgr-searchwrap .msgr-phone-icon { display: block; }
    .msgr-root .msgr-searchwrap .msgr-desktop-only { display: none; }
    .msgr-root .msgr-newbtn { background: var(--m-brand); color: var(--m-on-brand); border-radius: 8px; }
    .msgr-root .msgr-notibtn, .msgr-root .msgr-searchtog { background: transparent; color: var(--m-ink-2); }
    .msgr-phone-filters { display: block; }
    .msgr-phone-segment { display: flex; margin: 5px 16px 9px; border-radius: 9px; background: var(--m-surface-2); padding: 2px; }
    .msgr-phone-segment button { flex: 1; position: relative; height: 30px; border: 0; background: transparent; border-radius: 7px; color: var(--m-ink-2); font: inherit; font-weight: 600; }
    .msgr-phone-segment button::before { content: ''; position: absolute; inset: -7px 0; }
    .msgr-phone-segment button.is-active { background: var(--m-surface); color: var(--m-ink); box-shadow: 0 1px 3px var(--m-shadow-segment); }
    .msgr-phone-segment .msgr-phone-badge { margin-left: 5px; }
    .msgr-phone-care { display: block; width: calc(100% - 32px); margin: 0 16px 4px; min-height: 44px; padding: 6px 12px; border: 1px solid var(--m-warn-line); border-radius: 9px; background: var(--m-warn-tint); color: var(--m-warn); text-align: left; font-weight: 600; }
    .msgr-phone-back { background: none; border: 0; min-height: 44px; padding: 8px 16px; color: var(--m-brand); }
    .msgr-root .msgr-room { grid-template-columns: 30px minmax(0, 1fr); min-height: 54px; padding: 7px 16px; width: 100%; margin: 0; border-radius: 0; }
    .msgr-root .msgr-roomav { width: 30px; height: 30px; border-radius: 8px; }
    .msgr-root .msgr-room-bot { margin-top: 1px; }
    .msgr-phone-fixed .msgr-roomav { display: flex; align-items: center; justify-content: center; background: var(--m-brand); color: var(--m-on-avatar); }
    .msgr-phone-fixed:first-of-type .msgr-roomav { background: var(--m-self-avatar); color: var(--m-on-avatar); }
    .msgr-phone-fixed .msgr-room-top .msgr-phone-icon { width: 13px; height: 13px; color: var(--m-muted); }
    .msgr-phone-fixed .msgr-room-bot { color: var(--m-muted); }
    .msgr-room-swipe { position: relative; overflow: hidden; touch-action: pan-y; }
    .msgr-root .msgr-room-swipe > .msgr-room { position: relative; z-index: 1; background: var(--m-surface); touch-action: pan-y; }
    .msgr-swipe-actions { position: absolute; top: 0; bottom: 0; display: flex; }
    .msgr-swipe-actions.is-left { left: 0; }
    .msgr-swipe-actions.is-right { right: 0; }
    .msgr-swipe-actions button { width: 60px; border: 0; padding: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; color: var(--m-on-swipe); }
    .msgr-swipe-actions .msgr-phone-icon { width: 18px; height: 18px; }
    .msgr-swipe-actions .msgr-swipe-pinned { color: var(--m-on-brand); width: 84px; background: var(--m-brand); }
    .msgr-swipe-read { background: var(--m-swipe-read); }
    .msgr-swipe-muted { background: var(--m-swipe-muted); }
    .msgr-swipe-hide { background: var(--m-swipe-hide); }
    .msgr-phone-nav { position: absolute; left: 0; right: 0; bottom: 0; z-index: 10; display: flex; height: calc(54px + env(safe-area-inset-bottom, 0px)); box-sizing: border-box; padding-bottom: env(safe-area-inset-bottom, 0px); border-top: 1px solid var(--m-hairline); background: var(--m-surface); }
    .msgr-phone-tab { position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 0; border: 0; background: none; color: var(--m-muted); font-weight: 600; }
    .msgr-phone-tab.is-active { color: var(--m-brand); }
    /* 누르는 순간 바로 반응 — 두 번 눌러 확대 대기를 없애고(manipulation), 눌림 표시를 즉시 보인다(11-01 «터치 반응이 느려») */
    .msgr-root button, .msgr-phone-tab, .msgr-room { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
    .msgr-root .msgr-room:active, .msgr-phone-tab:active, .msgr-root .msgr-phone-page button:active { background: var(--m-surface-2); }
    .msgr-phone-tab .msgr-phone-badge { position: absolute; top: 2px; left: calc(50% + 6px); }
    .msgr-root.is-mobile-room .msgr-phone-nav { display: none; }
    .msgr-root.is-clients .msgr-phone-nav, .msgr-root.is-phone-page .msgr-phone-nav { display: flex; }
    .msgr-root .msgr-list { padding-bottom: calc(54px + env(safe-area-inset-bottom, 0px)); }
    body.msgr-popout .msgr-root .msgr-listscroll { padding-bottom: 8px; }
    .msgr-root.is-clients .msgr-clients { left: 0; padding-bottom: calc(54px + env(safe-area-inset-bottom, 0px)); }
    .msgr-root.is-phone-page > .msgr-list, .msgr-root.is-phone-page > .msgr-main, .msgr-root.is-phone-page > .msgr-side { visibility: hidden; }
    .msgr-root.is-phone-page > .msgr-phone-page { display: block; position: absolute; inset: 0 0 calc(54px + env(safe-area-inset-bottom, 0px)); overflow: auto; background: var(--m-surface); z-index: 9; }
    .msgr-phone-profile { display: flex; gap: 10px; align-items: center; padding: 6px 16px 12px; }
    .msgr-phone-menu { margin: 6px 16px 14px; border: 1px solid var(--m-hairline); border-radius: 14px; overflow: hidden; }
    .msgr-phone-menuitem { display: flex; width: 100%; min-height: 44px; padding: 10px 14px; align-items: center; gap: 10px; border: 0; border-top: 1px solid var(--m-hairline); background: var(--m-surface); color: var(--m-ink); text-align: left; }
    .msgr-phone-menuitem:first-child { border-top: 0; }
    .msgr-phone-chevron { margin-left: auto; color: var(--m-muted); }
    .msgr-phone-undo { position: absolute; left: 12px; right: 12px; bottom: calc(66px + env(safe-area-inset-bottom, 0px)); z-index: 11; border-radius: 10px; background: var(--m-toast); color: var(--m-on-toast); padding: 8px 12px; }
    .msgr-phone-undo button { min-height: 44px; background: none; border: 0; color: var(--m-on-toast); text-decoration: underline; font: inherit; }
}

/* 그룹 헤더 — 거래처 색 원 + 이름 + 빨간 N + 캐럿 */
.msgr-acchead { padding: 9px 12px; background: var(--m-canvas); }
.msgr-accdot { width: 16px; height: 16px; border-radius: 999px; }
.msgr-accname { font-size: 12px; font-weight: 800; color: var(--m-ink-secondary); }

@media (max-width: 768px) {
    .msgr-room, .msgr-fixitem, .msgr-homechip, .msgr-sheet, .msgr-sheetitem { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
    /* ③ 활성 방 표시는 **모바일에 필요 없다** — 누르면 대화 화면으로 넘어가므로
       목록에 남은 선택 상태는 의미가 없고, 통짜 보라색은 미읽음 톤까지 덮는다.
       🚨 배경을 지웠으면 **보라 배경용 글자색을 전부** 되돌려야 한다(2026-08-07 실화면):
         종전엔 `.is-active .msgr-room-title` 만 되돌렸는데, 미읽음 방은
         `.is-active.is-unread .msgr-room-title`(명시도 0,4,0)가 이겨 **흰 글자가 남았다**
         → 흰 배경 위 흰 제목 = **방 이름이 통째로 안 보임**. 목록에서 대부분의 방이
         미읽음이라 하필 제일 흔한 경우였다.
       ⓘ 되돌리는 값은 지어내지 않고 기본 규칙(2227~2241)의 색을 그대로 쓴다. */
    .msgr-room.is-active,
    .msgr-room.is-active.is-unread { background: transparent; }
    .msgr-room.is-active::before { display: none; }
    .msgr-room.is-active .msgr-room-title,
    .msgr-room.is-active.is-unread .msgr-room-title { color: var(--m-ink); }
    .msgr-room.is-active .msgr-room-last,
    .msgr-room.is-active.is-unread .msgr-room-last { color: var(--m-muted); }
    .msgr-room.is-active .msgr-room-at,
    .msgr-room.is-active.is-unread .msgr-room-at { color: var(--m-muted); }
    .msgr-room.is-active .msgr-room-by,
    .msgr-room.is-active.is-unread .msgr-room-by { color: var(--m-muted); }
    .msgr-room.is-active .msgr-room-cnt { color: var(--m-muted); }
    .msgr-room.is-active .msgr-unread { color: var(--m-brand); }

}

/* ═══════════════════════════════════════════════════════════
   🧩 메신저를 **OS 안의 별도 프로그램처럼 보이지 않게** (2026-08-06 사장님)
   원인 셋: ①둥근 테두리 카드가 페이지 위에 얹혀 있었고 ②자체 아이콘 레일이 OS
   사이드바와 겹쳤으며 ③모바일에선 OS 상단 네비 + 메신저 하단 탭바 + 방 탭까지
   **네비가 3층**이었다. 카드 크롬을 걷고 네비를 한 겹으로 줄인다.
   ═══════════════════════════════════════════════════════════ */
.msgr-root {
    border: 0; border-radius: 0; box-shadow: none;
    background: transparent;
}
/* 컬럼 경계만 남긴다 — 상자가 아니라 '영역 구분' */
.msgr-list { border-right: 1px solid var(--m-hairline); background: var(--m-surface); }
.msgr-main { background: var(--m-surface); }
.msgr-side { background: var(--m-surface); border-left: 1px solid var(--m-hairline); }

@media (max-width: 768px) {
    /* 📱 네비를 한 겹으로 — 하단 탭바는 두되(거래처·팀 관리에 닿는 유일한 길),
       **열린 방 탭 줄은 숨긴다**(왼쪽 목록이 이미 그 역할이고, ‹ 뒤로만 남기면 된다). */
    .msgr-tabbar { padding: 6px 8px; border-bottom: 1px solid var(--m-surface-2); }
    .msgr-tab { display: none; }
    .msgr-back { margin-right: 4px; }
    .msgr-root { min-height: 0; }

}

@media (max-width: 768px) and (pointer: coarse), (max-width: 768px) and (hover: none) {
    /* 📱 액션 바는 **띄우지 않는다** — 종전엔 hover 가 없다는 이유로 상시 노출해
       6개 버튼이 메시지 위를 덮었다. 길게 누르면 시트가 뜬다(wireLongPress). */
    .msgr-msgact { display: none !important; }
}

/* 📱 메시지 동작 시트 — 아래에서 올라온다 */
.msgr-sheetov {
    /* 🫧 딤을 .38 → .22 로 낮췄다 (2026-08-08 유리 도입). 유리가 이미 뒤를 흐려
       «떠 있다»를 말하는데 진한 딤까지 겹치면 **이중 분리**가 된다 — 아이폰 실측에서
       시트가 흰색이 아니라 회색 진흙이 됐고, 불투명한 「취소」 칩(#f1f5f9)이 시트보다
       밝아 위아래가 뒤집혀 보였다. 딤 + 재질을 같이 쓸 땐 딤을 양보한다(iOS 관용). */
    position: fixed; inset: 0; z-index: 120; background: var(--m-scrim-sheet);
    display: flex; align-items: flex-end;
}
.msgr-sheet {
    /* 🫧 떠 있는 면 — 딤 오버레이 위 */
    width: 100%; max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); max-height: min(calc(100dvh - 24px), calc(100% - 24px)); overflow-y: auto; box-sizing: border-box; background: var(--m-glass-bg, var(--m-surface));
    -webkit-backdrop-filter: var(--m-glass); backdrop-filter: var(--m-glass);
    border-radius: 12px 12px 0 0;
    padding: 8px 12px calc(12px + env(safe-area-inset-bottom));
    box-shadow: 0 -8px 32px var(--m-shadow-sheet);
}
.msgr-sheetgrab { width: 36px; height: 4px; border-radius: 999px; background: var(--m-hairline); margin: 4px auto 10px; }
.msgr-sheetquote {
    font-size: 12px; color: var(--m-muted); padding: 0 6px 10px; margin-bottom: 4px;
    border-bottom: 1px solid var(--m-surface-2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msgr-sheetitem {
    display: block; width: 100%; text-align: left; border: 0; background: none;
    padding: 14px 8px; font-size: 15px; color: var(--m-ink); border-radius: 8px;
}
.msgr-sheetitem:active { background: var(--m-surface-2); }
.msgr-sheetitem.is-danger { color: var(--m-danger); border-top: 1px solid var(--m-hairline); margin-top: 6px; }
/* 🖱 마우스 PC 의 ⋯ 메뉴 — 아래 시트 대신 누른 버튼 옆(2026-10-07, 넓은 창에서 전체 폭 시트가 어색했다). 터치는 위 시트 그대로 */
.msgr-sheetov.is-popover { background: transparent; display: block; }
.msgr-sheetov.is-popover .msgr-sheet {
    position: fixed; width: 248px; max-height: min(70vh, 440px);
    border: 1px solid var(--m-hairline); border-radius: 12px; padding: 6px;
    box-shadow: 0 12px 32px var(--m-shadow-xl);
}
.msgr-sheetov.is-popover .msgr-sheetgrab { display: none; }
.msgr-sheetov.is-popover .msgr-sheetquote { padding: 4px 8px 8px; }
.msgr-sheetov.is-popover .msgr-sheetitem { padding: 8px 10px; font-size: var(--m-base); cursor: pointer; }
@media (hover: hover) {
    .msgr-sheetov.is-popover .msgr-sheetitem:hover { background: var(--m-surface-2); }
}
.msgr-sheetov.is-popover .msgr-sheetcancel { margin-top: 4px; padding: 8px; font-size: var(--m-base); border-radius: 8px; cursor: pointer; }
.msgr-sheetcancel {
    display: block; width: 100%; margin-top: 6px; padding: 13px;
    border: 0; border-radius: 12px; background: var(--m-surface-2);
    font-size: 15px; font-weight: 700; color: var(--m-ink-2);
}

/* 📎 파일 칩 — 긴 파일명이 줄바꿈되며 글자가 겹쳐 보이던 것 수리 */
/* (파일 칩 → 카드 구조로 교체됨 — 이름 말줄임은 .msgr-filename 이 담당, 2026-08-06) */

/* 🧩 데스크톱: 메신저 자체 아이콘 레일을 **감춘다** — 같은 메뉴(메시지·거래처·팀 관리)가
   OS 사이드바(#ctx-msgr)에 있다. 둘 다 두면 세로 아이콘 줄이 두 개가 되어
   «OS 안의 별도 프로그램»처럼 보인다(2026-08-06 사장님 · PC 도 같은 지적).
   🚨 **단, 단독 앱(/msgr)에서는 감추면 안 된다** — 거기엔 OS 사이드바 자체가 없다
   (`body.msgr-popout #contextPanel { display:none }`). 2026-08-07 에 메신저를 독립
   PWA 로 빼면서 이 두 규칙이 겹쳐 **거래처·팀 관리로 가는 길이 아예 사라졌다**
   (사장님 "단독으로 빠지면서 팀정보 거래처 정보 등 왼쪽에 있던 내용이 빠졋어").
   숨기는 근거가 «중복»이었으니, 중복이 아닌 창에서는 숨길 이유가 없다. */
@media (min-width: 769px) {
    body:not(.msgr-popout) .msgr-rail { display: none; }
    .msgr-list { border-left: 0; }
}

/* 📐 메신저 화면 = **페이지 스크롤 없음**. 안쪽 컬럼만 스크롤한다.
   종전엔 .content-area 가 스크롤되면서 메신저 블록 전체가 휠에 밀렸고, 그 위에
   대화 목록·대화창이 또 스크롤돼 **스크롤이 두 겹**이었다 — 그게 «OS 위에 얹힌
   별도 프로그램» 느낌의 실체다(2026-08-06 사장님). body.msgr-view 는 app.js 가 켠다. */
body.msgr-view { overflow: hidden; }
body.msgr-view .content-area {
    padding: 0 !important; max-width: none !important;
    overflow: hidden; height: 100%;
}
body.msgr-view .msgr-root { min-height: 0; }

/* 🔔 @멘션 강조 — 부른 티가 나야 부른 값을 한다 */
.msgr-mention {
    background: var(--m-brand-tint); color: var(--m-brand-strong); font-weight: 700;
    border-radius: 6px; padding: 0 3px;
}
.msgr-msg.is-mine .msgr-mention { background: var(--m-brand-tint-2); color: var(--m-brand-strong); }

/* 📱 대화 화면 헤더 — 지금 어느 방인지 상단에 (2026-08-06 사장님).
   데스크톱은 탭 줄이 그 역할이라 감춘다. */
.msgr-roomhead { display: none; }
@media (max-width: 799px), (max-width: 959px) and (pointer: coarse), (max-width: 959px) and (hover: none) {
    .msgr-roomhead {
        display: flex; align-items: baseline; gap: 6px;
        flex: 1; min-width: 0; padding-left: 2px;
    }
    .msgr-roomheadname {
        font-size: var(--m-title); font-weight: 700; color: var(--m-ink);
        flex: 1 1 auto; min-width: 0;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    /* 거래처명은 **양보한다** — 방 이름이 먼저 보여야 어느 방인지 안다 */
    .msgr-roomheadcli {
        font-size: 11px; color: var(--m-muted); flex: 0 1 auto; min-width: 0; max-width: 40%;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    /* 🚫 데스크톱 탭 줄·정렬 여백은 모바일에서 **자리도 차지하면 안 된다**.
       탭 버튼만 숨기면 빈 스트립(flex:1)과 레일 정렬용 여백(131px 실측)이
       방 이름 몫을 그대로 빼앗아 «2··» 로 잘린다. `display:none` 이 아닌 것을
       하나씩 걷어내야 폭이 돌아온다 — 안 보이는 것과 자리를 안 먹는 것은 다르다. */
    .msgr-tabstrip { display: none; }
    .msgr-tabbar > .msgr-railspacer { display: none; }
    .msgr-tabbar { padding: 6px 12px; min-height: 56px; align-items: center; }
    /* 작은 화면에서도 뒤로가기와 방 메뉴는 최소 44px 터치 영역을 가진다. */
    .msgr-back { font-size: 22px; line-height: 1; min-width: 44px; height: 44px; margin-left: -6px; }
    .msgr-sidetoggle { min-width: 44px; min-height: 44px; }

    /* 🚪 대화 중에는 OS 상단 네비가 비켜준다 — 방 화면이 자기 헤더를 갖는다(카톡·Joint).
       ‹ 뒤로로 목록에 오면 되돌아온다. 모바일에서 세로 공간은 가장 비싼 자원이다. */
    body.msgr-mobile-room #appTopbar { display: none !important; }
}

/* 대화별 창은 크기를 넓혀도 해당 방만 유지한다. 목록은 원래 창에 있다. */
html.msgr-chat-window .msgr-rail,
html.msgr-chat-window .msgr-phone-nav,
html.msgr-chat-window .msgr-phone-page,
html.msgr-chat-window .msgr-list,
html.msgr-chat-window .msgr-list-resize,
html.msgr-chat-window .msgr-side:not(.msgr-side-sheet),
html.msgr-chat-window .msgr-tabstrip,
html.msgr-chat-window .msgr-tabbar > .msgr-railspacer,
html.msgr-chat-window .msgr-back,
html.msgr-chat-window .msgr-detach { display: none !important; }
html.msgr-chat-window .msgr-main { display: flex !important; }
html.msgr-chat-window .msgr-roomhead { display: flex; align-items: baseline; gap: 6px; flex: 1; min-width: 0; }
html.msgr-chat-window .msgr-roomheadname { flex: 1; min-width: 0; font-size: var(--m-title); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.msgr-chat-window .msgr-roomheadcli { max-width: 35%; font-size: var(--m-meta); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.msgr-chat-window .msgr-tabbar { min-height: 56px; padding: 8px 12px; }
html.msgr-chat-window .msgr-root.has-thread .msgr-threadpane { position: absolute; inset: 0; width: auto; z-index: 30; }
html.msgr-chat-window .msgr-threadback { display: inline-flex; }
html.msgr-chat-window .msgr-threadx { display: none; }

/* ══════════════════════════════════════════════════════════════
   🏷 브랜드 분기 — 같은 index.html 이 두 앱(어니스트 OS / 어니스트 메신저)을 띄운다
   ★ **JS 가 아니라 CSS 로 고르는 이유**: 스크립트가 도는 시점은 첫 페인트 뒤라
     메신저를 열었는데 「어니스트 OS」가 한 번 번쩍이고 나서 바뀐다.
     `.is-msgr` 는 index.html **head** 에서 documentElement 에 붙으므로
     (이 파일 <link> 보다 앞) 첫 페인트부터 올바른 브랜드로 그려진다.
   🚨 **`!important` 를 쓰지 않는다** — 쓰면 «숨김»이 «보임»보다 항상 세서
     보여야 할 쪽까지 눌러 버린다(important 는 명시도와 무관하게 이긴다).
     대신 **숨기는 규칙만** 명시도를 올리고, 보이는 쪽은 아예 매칭시키지 않는다.
     그래야 각 요소의 원래 display(로고 = img, 칩 = Tailwind `flex`)가 그대로 산다.
   ══════════════════════════════════════════════════════════════ */
:root:not(.is-msgr) .brand-msgr { display: none; }
html.is-msgr .brand-os { display: none; }

/* ══════════════════════════════════════════════════════════════
   📱 OS 본체 모바일 — 실측으로 고른 두 가지 (2026-08-07)
   375×812 에서 게스트로 들어가 전 화면을 잰 결과다. 「전반적으로 깨졌다」가 아니라
   ①한 곳의 잘림 ②조작부 크기 — 이 둘이었다(가로 스크롤은 어느 화면에서도 0).
   ══════════════════════════════════════════════════════════════ */

/* ① 🕐 출퇴근 줄이 화면 밖으로 나가던 것
   `shrink-0` 이라 부모가 좁아져도 줄이 안 줄고, 그래서 같은 클래스의 `flex-wrap` 이
   한 번도 발동하지 못했다 — 410px 짜리 줄이 375px 화면에서 54px 잘렸다.
   ⚠ 데스크톱에서는 `shrink-0` 이 옳다(제목 옆에서 버튼이 찌그러지지 않게) → 좁을 때만 푼다. */
@media (max-width: 640px) {
    .clock-actions { flex-shrink: 1 !important; min-width: 0; }
}

/* ② 👆 손가락 크기 — 터치 기기에서만
   실측: 홈은 조작부 35개 중 20개, 프로젝트 목록은 20개 중 14개가 36px 미만이었다
   (홈에는 28px 미만이 16개). 메신저에서 고친 것과 같은 문제·같은 방식이다.
   ⚠ **표 안은 제외한다** — 행마다 44px 를 강제하면 한 화면에 보이는 줄 수가 줄어
     오히려 쓰기 나빠진다(재무·프로젝트 표가 그 대상). 표는 마우스로 보는 화면이다.
   ⚠ 폭이 아니라 **입력 수단**(pointer: coarse)으로 가른다. */
@media (pointer: coarse) {
    .content-area button,
    .content-area select,
    .content-area a[data-action] { min-height: 44px; }
    .content-area table button, .content-area table select,
    .content-area td button, .content-area td select,
    .content-area th button, .content-area th select { min-height: 0; }
}

/* 좁은 화면의 날짜·시간 격자는 한 열로 읽는다.
   과거 iOS의 기본 외형이 지정 폭을 넘던 문제는 아래 appearance 규칙으로 처리한다.
   가로 flex 폼은 style.css의 os-form-row, 가변 입력 격자는 os-form-grid를 사용한다. */
@media (max-width: 480px) {
    :is(.grid, [class*="grid-cols"]):has(input[type="date"], input[type="datetime-local"],
                                          input[type="time"], input[type="month"], input[type="week"]) {
        grid-template-columns: 1fr !important;
    }
}
/* 날짜·시간 입력이 자기 칸을 넘지 않게 한다. */
input[type="date"], input[type="datetime-local"], input[type="time"],
input[type="month"], input[type="week"] { min-width: 0; max-width: 100%; box-sizing: border-box; }
/* iOS Safari: 기본 외형은 padding+border를 지정 폭 밖에 더한다(실측 +18px).
   날짜·시간 선택기는 type 그대로 유지하고 외형만 해제한다. */
@supports (-webkit-touch-callout: none) {
    input:is([type="date"], [type="datetime-local"], [type="time"], [type="month"], [type="week"]) {
        -webkit-appearance: none; appearance: none; min-height: 44px;
    }
}


/* ══════════════════════════════════════════════════════════════════════
   📱 어니스트 메신저 — 상단 안전영역 (2026-08-07 사장님 "위아래가 네이티브 앱처럼
   나오면 좋겟는데 지금은 그냥 화면만 띄워둔것 같음")

   ★ **아래는 이미 돼 있었다** — `env(safe-area-inset-bottom)` 이 탭바·컴포저·목록에
     들어가 있다. 비어 있던 건 **위**뿐이다. 시뮬레이터에 홈 화면 설치본을 만들어
     실제로 보고서야 알았다(브라우저 탭에서는 이 띠가 아예 안 보인다).

   ★ index.html 의 `black-translucent` 와 **한 벌**이다. 셋 중 하나만 있으면 깨진다.
     여기(②③)만 되돌리면 헤더가 시계 밑으로 숨고, 저기(①)만 되돌리면 아무 일도 안 난다.

   ⓘ `env(safe-area-inset-top)` 는 노치 있는 아이폰의 **설치된 앱**에서만 0 이 아니다 —
     맥·안드로이드·사파리 탭에서는 0 이라 이 블록이 통째로 무동작이 된다(안전한 확장).
   ══════════════════════════════════════════════════════════════════════ */
html.msgr-popout-root {
    --m-safetop: env(safe-area-inset-top, 0px);
}
html.msgr-popout-root body {
    padding-top: var(--m-safetop);
    /* 🎨 이 패딩이 드러내는 색이 곧 «상태바 배경»이다. 어두워야 흰 시계가 읽힌다.
       🚨 **세 곳이 같은 값이어야 한다** (2026-08-08 사장님이 인디고로 확정):
         ①`msgr.webmanifest` 의 `theme_color` — 안드로이드 홈 화면 앱의 상태바를 칠한다
         ②`index.html` 의 `/msgr` 블록 `theme-color` 메타 — 브라우저 상단 크롬
         ③여기 — 아이폰(black-translucent)에서 **우리가** 칠하는 안전영역 띠
       세 곳 모두 포인트 파랑으로 맞춘다. CSS 밖의 메타·매니페스트도 같은 값을 유지한다.
       ⚠ 로그인 화면(남색 그라데이션)과는 이제 이음매가 생긴다 — 그 화면 배경을 맞추려면
         `guest`·로그인 카드 쪽도 같이 봐야 하므로 여기서는 손대지 않았다. */
    /* 2026-11-01 흰색으로 — iOS 26 흐림 효과가 파란 띠를 헤더 위로 번지게 했다(메타는 default·theme-color 흰색과 한 벌). */
    background: var(--m-surface);
}
/* 📐 높이의 재계산 — 위에 패딩이 생긴 만큼 `100dvh` 는 화면 밖으로 넘친다.
   ⚠ `.msgr-root` 만 고치면 안 된다: 그 위 네 겹(#mainContent·.content-area·
     .global-content-wrap·#global-msgr)이 전부 `100dvh` 라, 하나라도 남으면
     본문이 통째로 밀려 **입력창이 화면 아래로 잘린다**(이 리포가 이미 한 번 겪은 증상).
   ⓘ `.msgr-root` 는 런타임에 `fitHeight()` 실측이 다시 덮는다 — 이 값은 그전 폴백이다. */
body.msgr-popout #mainContent,
body.msgr-popout .content-area,
body.msgr-popout .global-content-wrap,
body.msgr-popout .msgr-root {
    height: calc(100dvh - var(--m-safetop)) !important;
    /* ⚠ **높이에 transition 을 걸지 말 것** (2026-09-16 넣었다가 같은 날 제거). 키보드와 함께 미끄러지게 하려고
       .22s 를 줬더니 높이가 바뀌는 매 프레임마다 메시지 목록(실사용 177건)이 통째로 다시 배치돼 오히려 더 끊겼다.
       네이버웍스가 부드러운 건 애니메이션을 해서가 아니라 **OS 가 레이아웃 뷰포트를 직접 줄여** 주기 때문이다. */
}
/* ⓘ `#global-msgr` 는 **이 목록에서 뺐다** (2026-08-08). 그건 `position: fixed` 라
   위 :3352 의 `inset: var(--m-safetop) … 0 …` 이 top·bottom 으로 상자를 이미 정한다.
   높이까지 여기서 또 주면 top+bottom+height 로 과제약이 되어 (bottom 이 무시되는) 두
   출처가 생긴다 — 값이 우연히 같아 지금은 안 싸우지만, 한쪽만 고치는 날 조용히 어긋난다. */

/* ══════════════════════════════════════════════════════════════════════
   📱 모바일 서랍이 열리면 본문의 sticky 바가 그 위로 올라오지 않는다
   (2026-08-07 사장님 스크린샷 — 재무 서랍의 「전자결재」를 칩 줄이 가로로 잘라 덮음)

   🚨 **숫자만 보면 맞는데 틀린 부류다.** 서랍은 `z-index:300`, 칩 줄은 `z-40` 이라
     서랍이 이겨야 하는데 실제로는 칩이 위였다 — `position:sticky` 가 **자기 쌓임 맥락을
     만들기** 때문이다. z-index 는 같은 맥락 안에서만 비교되므로, 조상이 만든 맥락이
     서랍보다 앞이면 안쪽 z 값이 40이든 4든 상관없이 서랍을 덮는다.
   → 그래서 z 를 더 낮추는 게 아니라 **맥락 자체를 없앤다**(`position:static`).
     서랍이 닫히면 이 규칙이 빠지면서 sticky 가 그대로 돌아온다.
   ⓘ 서랍 클래스가 두 군데에 붙는다 — `body.mob-menu-open`(style.css 계열)과
     `.context-panel.mob-menu-open`(compact-sidebar 계열). 둘 다 받는다.
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
    body.mob-menu-open #finMobileTabBar,
    body:has(.context-panel.mob-menu-open) #finMobileTabBar,
    body.mob-menu-open .mobile-header,
    body:has(.context-panel.mob-menu-open) .mobile-header {
        position: static !important;
    }
}

/* ══════════════════════════════════════════════════════════════════════
   📱 재무 표 — 모바일 카드 (2026-08-07 사장님 "가독이 너무 떨어져 … 자금, 결재, 경비 등등 전부")

   실측(아이폰 402pt): 경비 1건 = 9줄 → 한 화면에 **1건**, 자금 6줄 → 2건.
   ⚠ 행 높이 문제가 아니다(이미 36px). «한 건에 필드가 몇 개냐»가 문제였다 —
     열이 8~10개인 원장 표에 3~4열용 «모든 셀을 한 줄씩» 패턴을 쓰고 있었다.
   ⓘ 결재(전용 카드 렌더러)는 3줄 = 5건으로 멀쩡했다. **그게 목표 모양**이다.

   ★ 그런데 렌더러를 6개 새로 쓰지 않는다 — 표가 이미 모든 셀에 `data-label` 을 달아 두어서
     그 라벨만으로 같은 모양을 만들 수 있다. 코드가 늘지 않고, 표를 고치면 카드도 따라온다.

   구조:
     ① 행 = **감싸는 플렉스**(고정 2열 그리드보다 촘촘하다 — 짧은 필드 셋이 한 줄에 들어간다)
     ② 머리글(거래처·사유·성명…) = 한 줄 전체 + 큰 글씨, **라벨을 지운다**
        («사유」라는 라벨 위에 「물품구매」가 오는 건 제목에 제목표를 붙이는 격이다)
     ③ 금액 = 오른쪽 끝(`margin-left:auto`) + 굵게, 라벨 없음 → 다음 필드는 자연히 줄바꿈
     ④ 배지(구분·상태)는 금액 왼쪽
     ⑤ 나머지는 작은 «라벨 값» 칩으로 흘러간다 — **아무것도 숨기지 않는다**

   ★ 숨기지 않는 이유: 어느 열이 중요한지는 표마다 다르고, 잘못 감추면 정작 필요한 값이
     사라진다. 접었다 펴는 장치를 만드는 대신 **줄 수를 줄여** 같은 목적을 달성한다.
   ⚠ 위 SPEC 의 라벨은 **렌더러 소스에서 뽑은 실제 값**이다(추측 금지) — 표의 헤더를 바꾸면
     여기도 같이 고쳐야 하고, 안 고치면 그 표만 조용히 옛 모양으로 돌아간다.
   ⓘ **`.fin-trs-table`(자금 본 표)은 이 규칙의 영향을 사실상 안 받는다** — 이 파일 :1686 이
     이미 «요약 셀(`td.trs-m`)만 보이고 `.trs-open` 이면 펼쳐지는» 접힘 카드를 만들어 뒀다.
     ⚠ 2026-08-07 에 «자금이 6줄»이라고 본 것은 같은 탭의 **「최근 거래」**(`fin-trs-recent-table`)
       였다 — 이름이 비슷한 다른 표다. 하네스(`public/_fin.html`)에서 자금이 **빈 카드**로
       나온 것이 그 사실을 드러냈다(하네스 결함이 아니라 실제 규칙이었다).
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  .fin-payroll-table tr,
  .fin-ec-table tr,
  .fin-trs-table tr,
  .fin-vendor-table tr,
  .fin-cashflow-table tr,
  .fin-vat-table tr,
  .fin-daily-table tr,
  .fin-card-table tr,
  .fin-budget-table tr,
  .fin-rep-pnl-table tr,
  .fin-rep-proj-table tr,
  .fin-rep-recv-table tr,
  .fin-overview-proj-table tr,
  .fin-quote-list-table tr,
  .fin-expenses-list-table tr,
  .fin-att-table tr,
  .fin-vendor-db-table tr,
  .fin-client-db-table tr,
  .fin-crew-table tr,
  .fin-home-proj-table tr,
  .fin-pipeline-quote-table tr,
  .fin-trs-recent-table tr,
  .fin-trs-vendor-table tr,
  .fin-est-list-table tr,
  .fin-exp-list-table tr,
  .fin-pnl-cat-table tr,
  .fin-pnl-inc-table tr,
  .fin-trs-pnl-month-table tr,
  .fin-trs-pnl-proj-table tr,
  .fin-dashboard-bva-table tr {
    display: flex !important;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 10px;
    padding: 4px 2px 8px !important;
  }
  .fin-payroll-table td,
  .fin-ec-table td,
  .fin-trs-table td,
  .fin-vendor-table td,
  .fin-cashflow-table td,
  .fin-vat-table td,
  .fin-daily-table td,
  .fin-card-table td,
  .fin-budget-table td,
  .fin-rep-pnl-table td,
  .fin-rep-proj-table td,
  .fin-rep-recv-table td,
  .fin-overview-proj-table td,
  .fin-quote-list-table td,
  .fin-expenses-list-table td,
  .fin-att-table td,
  .fin-vendor-db-table td,
  .fin-client-db-table td,
  .fin-crew-table td,
  .fin-home-proj-table td,
  .fin-pipeline-quote-table td,
  .fin-trs-recent-table td,
  .fin-trs-vendor-table td,
  .fin-est-list-table td,
  .fin-exp-list-table td,
  .fin-pnl-cat-table td,
  .fin-pnl-inc-table td,
  .fin-trs-pnl-month-table td,
  .fin-trs-pnl-proj-table td,
  .fin-dashboard-bva-table td {
    flex: 0 1 auto !important;
    /* 🚨 **`width:auto` 가 없으면 아무것도 안 붙는다** — 위 카드 변환 블록이 td 에
       `width:100% !important` 를 걸어 둬서, 감싸는 플렉스로 바꿔도 셀마다 전폭을
       차지해 결국 한 줄씩 그대로다(하네스 실측: 경비 9줄 유지). `order` 는 먹는데
       줄은 안 줄어서 «반쯤 고쳐진» 상태로 보였다 — 이게 이 수정의 급소다. */
    width: auto !important;
    max-width: 100%;
    justify-content: flex-start !important;
    gap: 5px !important;
    padding: 3px 10px !important;
    min-height: 0 !important;
    border-bottom: none !important;
    text-align: left !important;
  }

  /* ② 머리글 */
  .fin-trs-table td[data-label="거래처"],
  .fin-trs-recent-table td[data-label="거래처"],
  .fin-ec-table td[data-label="사유"],
  .fin-expenses-list-table td[data-label="프로젝트"],
  .fin-payroll-table td[data-label="성명"],
  .fin-card-table td[data-label="프로젝트명"],
  .fin-vendor-table td[data-label="거래처"] {
    flex: 1 1 100% !important;
    order: -3;
    font-size: 14.5px;
    font-weight: 800;
    color: #0f172a;
    padding-top: 7px !important;
  }
  /* ④ 배지 */
  .fin-trs-table td[data-label="구분"],
  .fin-trs-recent-table td[data-label="구분"],
  .fin-ec-table td[data-label="상태"],
  .fin-expenses-list-table td[data-label="상태"],
  .fin-payroll-table td[data-label="구분"],
  .fin-card-table td[data-label="상태"],
  .fin-vendor-table td[data-label="상태"] {
    order: -2;
  }
  /* ③ 금액 */
  .fin-trs-table td[data-label="금액"],
  .fin-trs-recent-table td[data-label="금액"],
  .fin-ec-table td[data-label="금액"],
  .fin-expenses-list-table td[data-label="총액"],
  .fin-payroll-table td[data-label="실지급액"],
  .fin-card-table td[data-label="실집행"],
  .fin-vendor-table td[data-label="미수"] {
    order: -1;
    margin-left: auto;
    font-weight: 800;
    font-size: 14px;
  }
  /* 머리글·금액은 라벨을 지운다 */
  .fin-trs-table td[data-label="거래처"]::before,
  .fin-trs-recent-table td[data-label="거래처"]::before,
  .fin-ec-table td[data-label="사유"]::before,
  .fin-expenses-list-table td[data-label="프로젝트"]::before,
  .fin-payroll-table td[data-label="성명"]::before,
  .fin-card-table td[data-label="프로젝트명"]::before,
  .fin-vendor-table td[data-label="거래처"]::before,
  .fin-trs-table td[data-label="금액"]::before,
  .fin-trs-recent-table td[data-label="금액"]::before,
  .fin-ec-table td[data-label="금액"]::before,
  .fin-expenses-list-table td[data-label="총액"]::before,
  .fin-payroll-table td[data-label="실지급액"]::before,
  .fin-card-table td[data-label="실집행"]::before,
  .fin-vendor-table td[data-label="미수"]::before {
    display: none !important;
  }

  /* 💰 자금 월 머리줄도 같은 구역 제목 — 흰 카드 안에 회색 띠·윗줄이 떠 «탭이 얹혀 있는» 모양이었다(2026-10-12 사장님).
     회색 띠·윗줄은 PC 표용 인라인 스타일이라 !important 로 걷는다 */
  .fin-trs-table tr.trs-month {
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
    padding: 12px 0 2px !important;
    margin-bottom: 0 !important;
  }
  .fin-trs-table tr.trs-month td { background: transparent !important; border: none !important; padding: 4px 6px !important; }
}

/* 📱 폰(≤768) — 카드 줄을 담는 tbody 는 block (2026-09-17 폰 글자 겹침 수리의 짝)
   폰에서 thead·tbody·tr 를 표 부품 그대로 두게 되면서(style.css ≤768 · compact-sidebar.css 참조),
   카드(flex) 줄이 든 tbody 를 브라우저가 보이지 않는 표로 감싸 카드 폭이 내용만큼 줄어든다
   (실측 700px: 예산관리 카드 688→474px). ≤640 은 위 카드 블록이 이미 block 이라 641~768 이 대상이다.
   ⚠ 위 flex 목록에 표를 추가하면 여기에도 추가할 것 — 빠지면 그 표만 폰 가로에서 카드가 줄어든다 */
@media (max-width: 768px) {
  .fin-payroll-table tbody,
  .fin-ec-table tbody,
  .fin-trs-table tbody,
  .fin-vendor-table tbody,
  .fin-cashflow-table tbody,
  .fin-vat-table tbody,
  .fin-daily-table tbody,
  .fin-card-table tbody,
  .fin-budget-table tbody,
  .fin-rep-pnl-table tbody,
  .fin-rep-proj-table tbody,
  .fin-rep-recv-table tbody,
  .fin-overview-proj-table tbody,
  .fin-quote-list-table tbody,
  .fin-expenses-list-table tbody,
  .fin-att-table tbody,
  .fin-vendor-db-table tbody,
  .fin-client-db-table tbody,
  .fin-crew-table tbody,
  .fin-home-proj-table tbody,
  .fin-pipeline-quote-table tbody,
  .fin-trs-recent-table tbody,
  .fin-trs-vendor-table tbody,
  .fin-est-list-table tbody,
  .fin-exp-list-table tbody,
  .fin-pnl-cat-table tbody,
  .fin-pnl-inc-table tbody,
  .fin-trs-pnl-month-table tbody,
  .fin-trs-pnl-proj-table tbody,
  .fin-dashboard-bva-table tbody {
    display: block;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   📱 메신저 정보 패널 — 폰에서는 **바텀시트**로 (2026-08-08 사장님 "편의성 고도화")

   종전엔 참여자·파일·챙기기를 **폰에서 볼 방법이 아예 없었다**: 위 :2675 가 ≤1180px 에서
   `.msgr-side { display:none }` 으로 패널을 통째로 없앴고, 그걸 여는 ▣ 만 남아
   눌러도 아무 일이 없었다(오늘 그 유령 버튼을 ☰ 로 바꿔 이 시트를 연다).

   ★ **같은 `.msgr-side` 를 그대로 띄운다** — `paintSide` 가 그린 DOM 을 재사용하므로
     폰용 내용을 따로 짜지 않는다(두 벌이 되면 한쪽만 고치는 사고가 시작된다).
   ⚠ `.msgr-side-sheet` 는 위 `display:none` 을 이겨야 한다 — 같은 명시도라 **뒤에 온다**.
     그래서 이 블록은 파일 말미에 있어야 하고, 앞으로 옮기면 조용히 안 열린다.
   ⓘ 높이 85%·하단 안전영역 — 시트 위로 대화가 살짝 보여야 «덮개»라는 게 읽힌다.
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 1180px) {
    .msgr-side.msgr-side-sheet {
        display: flex !important;
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
        width: auto; flex: none;
        max-height: 85%;
        border-left: 0; border-top: 1px solid var(--m-hairline);
        border-radius: 12px 12px 0 0;   /* ⚠ 토큰 밖 값 금지 — 6·8·12·999 만(디자인 스케일 테스트) */
        /* 🫧 떠 있는 면 — fixed 라 대화가 이 밑으로 흐른다 */
        background: var(--m-glass-bg, var(--m-surface));
        -webkit-backdrop-filter: var(--m-glass); backdrop-filter: var(--m-glass);
        box-shadow: 0 -8px 32px var(--m-shadow-xl);
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }
    /* ✕ 는 시트 안 우상단에 띄워 둔다 — 탭 줄의 높이를 밀어내지 않게 */
    .msgr-side.msgr-side-sheet .msgr-sheetclose {
        position: absolute; top: 6px; right: 8px;
        width: 32px; height: 32px; border: 0; border-radius: 999px;
        background: var(--m-surface-2); color: var(--m-ink-2); font-size: 15px; font-weight: 700;
        cursor: pointer; z-index: 1;
    }
    /* 🚨 그 대신 **탭이 ✕ 밑으로 들어가지 않게 자리를 비켜준다** (2026-08-08 아이폰 17 실측).
       종전엔 「파일 관리」 탭(폭 191px)의 오른쪽 **30px 이 ✕ 밑에 깔려** 있었다 —
       탭처럼 보이는 데를 눌렀는데 탭이 안 바뀌고 **시트가 닫혔다**. 오류는 안 난다.
       ⚠ 8(right) + 32(✕) + 6(숨돌릴 틈) = 46. ✕ 크기를 바꾸면 이 값도 같이 고칠 것. */
    .msgr-side.msgr-side-sheet .msgr-sidetabs { padding-right: 46px; }
    /* 데스크톱으로 넓어지면 시트가 아니라 원래 컬럼으로 돌아가야 한다 */
    .msgr-side .msgr-sheetclose { display: none; }
    .msgr-side.msgr-side-sheet .msgr-sheetclose { display: block; }
}
/* 🖱 마우스 PC 는 아래 시트 대신 **오른쪽 서랍** (2026-10-07 사장님 «대화방 정보 서랍으로 바꿔줘»).
   1180px 이하에서 이미 오른쪽에 겹쳐 뜨는 스레드 창(.msgr-threadpane)과 같은 자리·폭·그림자.
   전체 폭 시트 + 반투명 유리는 폰 몸짓이라 PC 창에선 휑하고 뒤의 보라·아바타 색이 번졌다.
   열고 닫기(☰·✕·ESC·바깥 클릭)는 openSideSheet 그대로 — 모양만 바꾼다. 폰·태블릿(터치)은 위 시트 그대로.
   ⚠ 위 시트 블록보다 **뒤**에 둔다(같은 명시도 — 순서로 이긴다). */
@media (max-width: 1180px) and (hover: hover) and (pointer: fine) {
    .msgr-side.msgr-side-sheet {
        position: absolute; top: 0; right: 0; bottom: 0; left: auto;
        width: min(380px, 100%); max-height: none;
        border-top: 0; border-left: 1px solid var(--m-hairline); border-radius: 0;
        background: var(--m-surface); -webkit-backdrop-filter: none; backdrop-filter: none;
        box-shadow: -8px 0 24px var(--m-shadow-md);
    }
}

/* 📱 컴포저에서 **빈 줄 접기** (2026-08-08) — 「전체/내부」가 도구 줄로 내려가면서
   `.msgr-tools` 에는 레일 스페이서만 남는다. 그 줄이 그대로 있으면 아무것도 없는데
   높이만 차지한다(사장님 "빡빡한 느낌"의 한 조각).
   셸이 spacer만 있는 줄에 is-empty를 붙인다. */
.msgr-tools:empty,
.msgr-tools.is-empty { display: none; }

/* ⚰️ 2026-08-08 여백 정리 — 아래 선언들은 **뒤에서 덮여 한 번도 이긴 적이 없는**
   죽은 줄이었다(전역 스코프 중복). 지워도 계산값이 1px 도 안 바뀐다(하네스로 전후 대조).
   ⚠ 값을 «바꾼» 게 아니라 «이기지 못하는 줄»을 걷어낸 것이다 — 여백을 키우는 작업은
     이 정리 뒤에 별도로 한다(먼저 키우면 군더더기까지 같이 커진다).
   제거: .msgr-room padding:6px 9px · .msgr-msg gap:9px/padding:6px 0 · .msgr-msg padding:3px 0
        · .msgr-msgs padding:14px 18px · .msgr-room-bot margin-top:2px */

/* ══════════════════════════════════════════════════════════════════════
   💬 말풍선 꼬리 + 연속 메시지 묶기 (2026-08-08 사장님 "카톡·네이트온 같은 레이아웃")

   묶기(`is-grouped`)는 이미 있었고 **꼬리가 없었다** — 그래서 같은 사람이 연달아 보낸
   메시지가 «한 덩어리»로 안 읽히고 낱장으로 떠 있었다.
   ★ 삼각형(::before)을 붙이지 않는다 — 배경이 둘(내 것 보라·남 것 회색)이라 규칙이
     두 벌이 되고, 다크·링크·멘션까지 색을 따라다녀야 한다.
     **모서리 하나를 각지게** 하는 것으로 같은 효과를 낸다: 아바타 쪽(왼쪽 위)만 4px.
   ⓘ 그룹의 **첫 말풍선만** 각진다 — 이어지는 것들은 완전히 둥글어서, 각진 모서리가
     «여기서 새 사람/새 덩어리가 시작한다»는 표시가 된다.
   ⚠ 모서리 값은 토큰 밖(4px)이지만 이건 «둥글기»가 아니라 **꼬리**다 — 6·8·12 중
     하나를 쓰면 그냥 덜 둥근 상자가 되어 표시로 읽히지 않는다.
   ══════════════════════════════════════════════════════════════════════ */
.msgr-msg:not(.is-grouped) .msgr-msgtext { border-top-left-radius: 4px; }
/* 이어지는 말풍선은 더 바짝 — 덩어리 안의 간격이 덩어리 사이보다 좁아야 묶여 보인다 */
.msgr-msg.is-grouped .msgr-msgtext { margin-top: 1px; }

/* ══════════════════════════════════════════════════════════════════════
   📅 날짜 구분선 **고정** (2026-08-08 사장님 "카톡·네이트온 같은 레이아웃")

   위로 올려 예전 대화를 볼 때 «지금 며칠 보는 중인지»가 화면에서 사라졌다. 카톡·슬랙은
   그 날짜가 상단에 붙어 따라온다 — 긴 대화에서 **날짜를 다시 찾으러 스크롤하지 않게** 해 준다.

   ★ 새 요소를 만들지 않는다 — 이미 그리고 있는 `.msgr-daysep` 을 `sticky` 로 바꾼다.
     JS 로 «현재 날짜»를 따로 계산해 헤더에 그리는 방식은 스크롤마다 계산이 돌고
     경계에서 어긋난다(그리고 지금 있는 구분선과 값이 두 벌이 된다).
   ⚠ **`.msgr-pinbar` 가 이미 `top:0`** 에 붙어 있다(📌 고정 메시지). 둘 다 0 이면 겹치므로
     날짜는 그 아래(top:34px)에 세우고 z-index 도 낮춘다 — 고정 메시지가 위다.
   ⚠ 부모(`.msgr-msgs`)에 `overflow-y:auto` 가 있어야 sticky 가 산다. 지금 그렇다 —
     스크롤 컨테이너를 다른 곳으로 옮기면 이 규칙이 조용히 죽는다.
   ⓘ 배경 알약(span)에만 색이 있어 sticky 로 떠도 뒤 글자가 비쳐 보이지 않는다.
   ══════════════════════════════════════════════════════════════════════ */
.msgr-daysep {
    /* top 19px: 라벨은 0 높이 줄 위로 제 높이(≈23px)만큼 올라가 그려진다(가운데 맞춤 + 아래 translateY(-50%)).
       6px 이면 위에 멈출 때 7px 가 잘려 «어제»가 반쯤 보였다(2026-10-07) — 19px 면 목록 위 끝에서 6px 아래 */
    position: sticky; top: 19px; z-index: 3;
    pointer-events: none;           /* 떠 있는 라벨이 그 아래 메시지의 클릭을 먹지 않게 */
    /* 🚨 **높이를 0 으로 만들어 띄운다** — 종전엔 sticky 만 걸었더니 라벨이 원래 자리를
       계속 차지한 채 떠올라 **메시지와 겹쳐** 보였다(하네스 실화면에서 「8월 5일」이
       말풍선 위에 얹혀 있었다). 자리를 비우고 라벨만 띄운다. */
    height: 0; margin: 14px 0 10px; overflow: visible;
}
.msgr-daysep span { transform: translateY(-50%); }
/* 📌 고정 막대가 있으면 날짜는 그 아래에 뜬다(막대 높이 38px + 틈) — 위 주석의 «top:34px» 약속이 빠져 날짜가 막대 뒤에 숨었다 */
.msgr-msgs.has-pinbar .msgr-daysep { top: 56px; }
.msgr-daysep span {
    box-shadow: 0 1px 6px var(--m-shadow-sm);
    border: 1px solid var(--m-hairline);
    background: var(--m-surface);               /* 반투명이면 지나가는 글자가 비친다 */
}

/* 💬 답장 인용 카드 (2026-08-08) — 말풍선 **위**에 붙는 작은 원문 조각.
   ★ 말풍선 «안»에 넣지 않았다: 내 말풍선은 보라 배경이라 그 안에 또 상자를 넣으면
     색이 세 겹이 되고, 인용문의 링크·멘션 색까지 따라다녀야 한다.
   ⓘ 왼쪽 세로 막대가 «인용»의 관용 표현이다 — 새 아이콘을 만들지 않는다. */
.msgr-quote {
    display: flex; align-items: baseline; gap: 6px;
    max-width: 100%; margin: 2px 0 3px;
    padding: 4px 9px; border-left: 3px solid var(--m-brand-line);
    background: var(--m-canvas); border-radius: 0 var(--m-r1) var(--m-r1) 0;
    font-size: var(--m-meta); cursor: pointer;
}
.msgr-quote:hover { background: var(--m-surface-2); }
.msgr-quotename { flex: 0 0 auto; font-weight: 800; color: var(--m-brand); }
.msgr-quotetext { flex: 1 1 auto; min-width: 0; color: var(--m-muted); font-size: 11.5px; line-height: 1.5; margin-top: 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 📌🔕 대화방 길게 누르기 시트 (2026-08-08) — **기존 메시지 시트와 같은 옷을 입는다.**
   🚨 처음엔 `.msgr-sheetitem` 을 여기서 다시 정의했다가 그게 **뒤에 와서 이겨**,
     원래 있던 메시지 시트까지 통째로 «회색 상자 + 굵은 글씨 + 큰 여백»으로 바꿔 버렸다
     (사장님 "지금 너무 큼 그리고 너무 구림"). 오늘 아침 내가 잡아낸 «override 퇴적층»을
     내가 그대로 만든 것이다.
   ★ 그래서 새 클래스를 만들지 않고 **:3596 의 `.msgr-sheetov`/`.msgr-sheet`/
     `.msgr-sheetitem`/`.msgr-sheetcancel` 을 그대로 쓴다**(JS 쪽 클래스명을 맞췄다).
     시트가 둘인데 옷이 하나여야 «같은 앱»으로 보인다. */

/* 🚫 대화 목록 행 — **길게 누를 때 iOS 텍스트 선택이 같이 뜨던 것** (2026-08-08 사장님
   "누르고 있으면 버튼인데 블록쳐지면서 복사 붙여넣기 이런게 뜸")
   길게 누르기를 액션 시트에 쓰기 시작했더니, iOS 기본 동작(선택 블록 + 복사/번역 바)이
   같은 제스처를 가로채 시트 위에 겹쳐 떴다.
   ★ **목록 행에만** 끈다 — 방 이름·미리보기는 복사할 글이 아니다.
   ⚠ **말풍선(`.msgr-msg`)에는 절대 걸지 말 것** — 거기서 선택을 끄면 메시지 본문을
     복사할 방법이 사라진다. 말풍선 쪽은 시트에 「복사」를 넣은 **뒤에** 꺼야 한다.
   ⓘ `-webkit-touch-callout` 이 «꾹 눌렀을 때 뜨는 바»이고, `user-select` 가 «블록»이다 —
     둘은 다른 것이라 하나만 끄면 나머지가 남는다. */
.msgr-room, .msgr-room * {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

/* 🗂 거래처 관리 — 섹션 헤더 (2026-08-08, 슬랙 관용: 캐럿 + 건수, 눌러서 접기) */
.msgr-clisec {
    display: flex; align-items: center; gap: 6px;
    width: 100%; border: 0; background: none; text-align: left;
    padding: 10px 8px 6px; cursor: pointer;
    font-size: var(--m-meta); font-weight: 800; color: var(--m-muted);
}
.msgr-clisec.is-static { cursor: default; }
.msgr-clisec:hover:not(.is-static) { color: var(--m-ink); }
.msgr-clisec-car { font-size: 11px; color: var(--m-muted); width: 11px; }   /* ⚠ 11px 미만 금지(디자인 스케일 테스트) — 10px 로 썼다가 걸렸다 */

/* 📱 폰 컴포저 — 공개 범위와 입력을 서로 다른 줄에 배치한다.
   전체/내부가 입력 폭을 먹지 않으며, 도구 시트는 계속 떠 있는 면으로 연다. */
.msgr-composer .msgr-more { display: none; }

@media (max-width: 768px) {
    .msgr-composer { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 6px; }
    .msgr-composer { padding: 6px 12px calc(8px + var(--m-composer-safe-bottom, env(safe-area-inset-bottom, 0px))); }
    .msgr-composer .msgr-scopebar { flex: 0 0 100%; margin-bottom: 0; }
    .msgr-composer .msgr-scopebar .msgr-segbtn { min-width: 48px; min-height: 44px; padding: 6px 10px; }
    .msgr-composer .msgr-aibar { flex: 0 0 100%; width: 100%; }
    .msgr-composer > .msgr-btn { flex: 0 0 100%; order: 1; min-height: 44px; }
    .msgr-composer .msgr-inputwrap { flex: 1 1 0; min-width: 0; padding: 9px 12px; }
    .msgr-composer .msgr-input { min-height: 24px; max-height: 96px; }
    .msgr-composer .msgr-cfoot { flex: 0 0 auto; margin-top: 0; gap: 6px; }
    .msgr-composer .msgr-cfoot .msgr-railspacer { display: none; }
    .msgr-composer .msgr-cfoot .msgr-tool:not(.msgr-more) { display: none; }
    .msgr-composer .msgr-more {
        display: inline-flex; align-items: center; justify-content: center;
        min-width: 44px; height: 44px; background: var(--m-surface-2); border-radius: 12px;
        color: var(--m-ink-2); padding: 0;
    }
    .msgr-composer .msgr-send { width: 44px; height: 44px; }
    .msgr-composer .msgr-more:active { background: var(--m-hairline); }
}

/* 🧰 ＋ 도구 시트 — 떠 있는 목록이라 입력줄 레이아웃을 건드리지 않는다(위 블록 주석 참조).
   기본 상자(`.msgr-emojipop`)의 그림자·테두리를 그대로 쓰고 세로 목록만 얹는다. */
.msgr-emojipop.msgr-toolpop {
    display: block; padding: 6px; width: 248px; max-width: calc(100vw - 16px);
    box-sizing: border-box; border-radius: 14px; box-shadow: 0 8px 28px var(--m-shadow-float);
}
.msgr-toolitem {
    display: flex; align-items: center; gap: 10px; width: 100%; min-height: 58px;
    border: 0; background: transparent; border-radius: 8px; padding: 8px;
    cursor: pointer; text-align: left; color: var(--m-ink-tertiary); font-size: var(--fs-base);
}
.msgr-toolitem:hover, .msgr-toolitem:active, .msgr-toolitem:focus-visible { background: var(--m-surface-2); }
.msgr-toolitem-ic { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; flex: none; border-radius: 8px; }
.msgr-toolitem-ic.is-blue { color: var(--m-brand); background: var(--m-brand-tint-2); }
.msgr-toolitem-ic.is-purple { color: var(--m-tool-purple); background: var(--m-tool-purple-bg); }
.msgr-toolitem-ic.is-green { color: var(--m-ok); background: var(--m-ok-tint-2); }
.msgr-toolitem-ic.is-yellow { color: var(--m-warn); background: var(--m-warn-tint-2); }
.msgr-toolitem-copy { display: flex; flex-direction: column; min-width: 0; gap: 3px; }
.msgr-toolitem-tx { font-weight: 700; }
.msgr-toolitem-hint { font-size: var(--fs-meta); color: var(--m-muted); line-height: 1.4; }
.msgr-composer .msgr-more.is-open { background: var(--m-brand-tint-2); color: var(--m-brand); }
.msgr-more.is-open .msgr-composer-icon { transform: rotate(45deg); }

/* 상세 패널도 키보드가 줄인 실제 화면 안에서 스크롤한다. 인라인 목록은 제외한다. */
.right-slide-panel[role="dialog"], .wbs-panel {
  top: calc(var(--os-viewport-top, 0px) + 60px) !important;
  bottom: auto !important;
  height: calc(var(--os-viewport-height, 100dvh) - 60px);
}
body.right-panel-open #rightPanelTopbar { top: calc(var(--os-viewport-top, 0px) + 60px) !important; }
body.right-panel-open #rightPanelFooter { bottom: max(0px, calc(100dvh - var(--os-viewport-height, 100dvh) - var(--os-viewport-top, 0px))) !important; }
.right-slide-panel[role="dialog"] :is(input, select, textarea), .wbs-panel :is(input, select, textarea) { min-width: 0; max-width: 100%; box-sizing: border-box; }

/* Company invitation: compact contact list and reachable actions on narrow screens. */
.msgr-company-dialog { max-height: min(100%, calc(100dvh - 32px)); }
.msgr-company-dialog .msgr-dlgbody { min-height: 0; }
.msgr-company-dialog .msgr-dlghead, .msgr-company-dialog .msgr-dlgfoot { flex-shrink: 0; }
.msgr-company-dialog .msgr-dlgfoot { flex-wrap: wrap; }
.msgr-company-dialog .msgr-dlgerr { flex-basis: 100%; overflow-wrap: anywhere; }
.msgr-company-dialog .msgr-fi { font-size: 16px; min-width: 0; }
.msgr-company-selected { display: flex; align-items: center; gap: 10px; background: var(--m-surface-2); border-radius: 8px; padding: 8px 10px; }
.msgr-company-selected strong { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.msgr-company-person { display: flex; align-items: center; gap: 10px; padding: 12px 0; border-bottom: 1px solid var(--m-hairline); flex-wrap: wrap; }
.msgr-company-person input { width: 18px; height: 18px; flex: none; }
/* 긴 이름·회사·번호 줄은 상태·버튼을 아랫줄로 내린다 — 종전엔 버튼 옆 100px 칸에 9줄로 눌리고 번호가 «010-»/«9999»로 쪼개졌다(2026-11-02 360폭 점검) */
.msgr-company-persontext { flex: 1 1 9em; min-width: 0; overflow-wrap: anywhere; }
.msgr-company-state { margin-left: auto; }
.msgr-company-persontext strong, .msgr-company-persontext small { display: block; }
.msgr-company-persontext small { color: var(--m-muted); margin-top: 3px; }
.msgr-company-state { color: var(--m-brand-strong); font-size: var(--m-meta); }
.msgr-company-pick { display: block; width: 100%; min-height: 44px; text-align: left; padding: 10px; border: 0; border-bottom: 1px solid var(--m-hairline); background: var(--m-surface); color: var(--m-ink); overflow-wrap: anywhere; }
.msgr-company-steps { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; font-size: var(--m-meta); }
.msgr-company-steps[hidden], .msgr-company-purposes[hidden] { display: none; }
.msgr-company-step { padding: 5px 8px; border-radius: 12px; background: var(--m-surface-2); color: var(--m-muted); }
.msgr-company-step.is-active { background: var(--m-brand-tint); color: var(--m-brand-strong); }
.msgr-company-flowhead { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px; }
.msgr-company-flowhead .msgr-company-steps { flex-basis: 100%; margin-top: 0; }
.msgr-company-purposes { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.msgr-company-purposes .msgr-chip { min-height: 44px; }
.msgr-company-greeting-page textarea { height: 150px; padding: 10px; margin-top: 8px; resize: vertical; box-sizing: border-box; }
.msgr-company-preview { padding: 12px; border: 1px solid var(--m-hairline); border-radius: 8px; background: var(--m-surface-2); white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.6; }
.msgr-company-preview strong { display: block; margin-bottom: 6px; }
.msgr-company-recipients { margin-top: 12px; color: var(--m-muted); overflow-wrap: anywhere; }
.msgr-company-add { margin: 10px 0; }
.msgr-company-manual { min-height: 150px; }
.msgr-company-status { padding: 12px 0; border-bottom: 1px solid var(--m-hairline); }
.msgr-company-dialog [hidden] { display: none; }
@media (max-width: 600px) {
    /* 폰: «카톡으로 보내기»를 맨 위 꽉 찬 줄로, 나머지 버튼은 그 아래 같은 폭으로(줄마다 폭이 들쭉날쭉하던 것) */
    .msgr-company-dialog .msgr-dlgfoot .msgr-btn-p { flex-basis: 100%; order: -1; }
    .msgr-company-dialog .msgr-dlgfoot .msgr-btn:not(.msgr-btn-p) { flex: 1 1 0; }
    .msgr-company-dialog .msgr-dlgfoot .msgr-dlgerr { order: -2; flex-basis: 100%; }
}

.msgr-company-dialog .msgr-btn { min-height: 44px; }
.msgr-company-dialog .msgr-fi { min-height: 44px; }

/* 거래처 DB 목록: 폰과 PC가 같은 데이터·타입 토큰을 사용한다. */
.msgr-cli-db { min-height: 0; flex-direction: row; }
.msgr-cli-db .msgr-clilist { flex: 0 0 340px; padding: 12px 0; border-right: 1px solid var(--m-hairline); }
.msgr-cli-db .msgr-clihead, .msgr-cli-db .msgr-cli-chips { padding: 0 16px; }
.msgr-cli-db .msgr-clititle { font-size: var(--fs-title); }
.msgr-cli-search { display: block; margin: 12px 16px 8px; width: calc(100% - 32px); box-sizing: border-box; }
.msgr-cli-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.msgr-cli-chips .msgr-btn { border-radius: 999px; font-size: var(--fs-meta); padding: 4px 9px; }
.msgr-cli-chips [aria-pressed="true"] { background: var(--m-ink); color: var(--m-surface); }
.msgr-cli-item { display: flex; align-items: center; gap: 10px; min-height: 54px; width: 100%; padding: 6px 16px; border: 0; background: var(--m-surface); color: var(--m-ink); text-align: left; cursor: pointer; }
.msgr-cli-item:hover, .msgr-cli-item.is-active { background: var(--m-brand-tint); }
.msgr-cli-logo, .msgr-cli-photo { width: 30px; height: 30px; flex: none; border-radius: 8px; object-fit: cover; }
.msgr-cli-logo { box-shadow: inset 0 0 0 100px var(--m-avatar-shade); display: flex; align-items: center; justify-content: center; overflow: hidden; color: var(--m-on-badge); font-size: var(--fs-meta); font-weight: 700; }
.msgr-cli-logo img { width: 100%; height: 100%; object-fit: cover; }
.msgr-cli-itemtext, .msgr-cli-persontext { min-width: 0; flex: 1; }
.msgr-cli-itemtext strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-base); }
.msgr-cli-summary { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-meta); color: var(--m-ink-2); }
.msgr-cli-dots { display: flex; align-items: center; flex-wrap: wrap; gap: 3px; margin-top: 3px; }
.msgr-cli-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--m-ink-meta); }
.msgr-cli-dot.is-joined { background: var(--m-online-strong); }
.msgr-cli-dot.is-invited, .msgr-cli-dot.is-requested { background: var(--m-warm-accent); }
.msgr-cli-dot.is-unknown, .msgr-cli-dot.is-locked { background: transparent; border: 1px solid var(--m-warn-action); box-sizing: border-box; }
.msgr-cli-count, .msgr-cli-badge { flex: none; padding: 2px 5px; border-radius: 6px; font-size: var(--fs-meta); background: var(--m-canvas); color: var(--m-ink-2); }
.msgr-cli-badge.is-joined { color: var(--m-ok-strong); background: var(--m-ok-tint-2); }
.msgr-cli-badge.is-invited, .msgr-cli-badge.is-requested, .msgr-cli-badge.is-locked { color: var(--m-warn); background: var(--m-warn-tint-2); }
.msgr-cli-status-note { font-size: var(--fs-meta); color: var(--m-muted); }
.msgr-cli-warning { margin: 12px 16px; padding: 10px; border: 1px dashed var(--m-warm-accent); border-radius: 12px; background: var(--m-warn-tint); color: var(--m-warn); font-size: var(--fs-meta); overflow-wrap: anywhere; }
.msgr-cli-warning .msgr-btn { margin: 4px 4px 0 0; }
.msgr-cli-db .msgr-cliprof { flex: 1; width: auto; min-width: 0; border-left: 0; }
.msgr-cli-db .msgr-clip-name { font-size: var(--fs-title); overflow-wrap: anywhere; }
.msgr-cli-db .msgr-clip-sec { border: 1px solid var(--m-hairline); border-radius: 12px; padding: 12px; margin: 0 0 12px; min-width: 0; }
.msgr-cli-db .msgr-clip-top { margin-bottom: 12px; }
.msgr-cli-db .msgr-clip-sectitle, .msgr-cli-db .msgr-clip-dbval, .msgr-cli-db .msgr-clip-alabel, .msgr-cli-db .msgr-clip-memo, .msgr-cli-db .msgr-clip-roomname { font-size: var(--fs-base); color: var(--m-ink-2); }
.msgr-cli-db .msgr-clip-alabel { width: 80px; }
.msgr-cli-columns { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
.msgr-cli-person { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--m-hairline); font-size: var(--fs-base); }
.msgr-cli-persontext strong, .msgr-cli-persontext small { display: block; overflow-wrap: anywhere; }
.msgr-cli-persontext small { color: var(--m-muted); font-size: var(--fs-meta); }
.msgr-cli-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.msgr-cli-actions .msgr-btn { flex: 1; white-space: nowrap; }
.msgr-cli-placeholder { flex: 1; padding: 30px; color: var(--m-muted); font-size: var(--fs-base); }
.msgr-cli-detaildots { display: none; }
@media (max-width: 1000px) { .msgr-cli-columns { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 768px) {
    .msgr-cli-db { flex-direction: column; }
    .msgr-cli-db .msgr-clilist { flex: 1; width: 100%; box-sizing: border-box; border-right: 0; }
    .msgr-cli-db.has-selection .msgr-clilist, .msgr-cli-db .msgr-cli-placeholder { display: none; }
    .msgr-cli-db .msgr-cliprof { border-top: 0; }
}
/* PC 는 거래처 목록이 옆에 보이므로 «‹ 목록» 이 필요 없다 */
@media (min-width: 769px) { .msgr-cli-back { display: none; } }

/* 1000px 이상은 입력 장치와 무관하게 표 + 고정 프로필. 모드 전환은 입력 보호 뒤에 적용한다. */
.msgr-cli-db.is-table .msgr-clilist { display: flex; flex-direction: column; flex: 1 1 0; min-height: 0; padding: 20px 24px 0; overflow: hidden; }
.msgr-cli-db.is-table .msgr-clihead { flex: none; flex-wrap: wrap; justify-content: flex-start; padding: 0; margin-bottom: 14px; }
.msgr-cli-db.is-table .msgr-cli-search { flex: 1 1 220px; width: auto; min-width: 180px; margin: 0; font-size: var(--fs-title); }
.msgr-cli-db.is-table .msgr-cli-chips { padding: 0; margin: 0; }
.msgr-cli-db.is-table .msgr-clihead > .msgr-btn { margin-left: auto; }
.msgr-cli-db.is-table .msgr-cli-warning { flex: none; margin: 0 0 14px; }
.msgr-cli-db.is-table .msgr-clilist > .msgr-fh { flex: none; margin: 0 0 10px; }
.msgr-cli-table-scroll { flex: 1 1 0; min-height: 0; overflow: auto; }
.msgr-cli-table { width: 100%; min-width: 700px; border-collapse: collapse; table-layout: fixed; font-size: var(--fs-base); color: var(--m-ink); }
.msgr-cli-table th { position: sticky; top: 0; z-index: 1; background: var(--m-surface); color: var(--m-muted); font-size: var(--fs-meta); font-weight: 600; text-align: left; }
.msgr-cli-table th, .msgr-cli-table td { padding: 12px 10px; border-bottom: 1px solid var(--m-hairline); vertical-align: middle; overflow-wrap: anywhere; }
.msgr-cli-table th:nth-child(1) { width: 25%; }
.msgr-cli-table th:nth-child(2) { width: 16%; }
.msgr-cli-table th:nth-child(3) { width: 16%; }
.msgr-cli-table th:nth-child(4) { width: 9%; }
.msgr-cli-table th:nth-child(5) { width: 13%; }
.msgr-cli-table th:nth-child(6) { width: 21%; }
.msgr-cli-table-row { cursor: pointer; }
.msgr-cli-table-row.is-active { background: var(--m-brand-tint); }
.msgr-cli-table-row.is-active > td:first-child { box-shadow: inset 3px 0 var(--m-brand); }
.msgr-cli-company { display: flex; align-items: center; gap: 8px; min-width: 0; }
.msgr-cli-company-name { display: block; max-width: 100%; min-height: 32px; padding: 0; border: 0; background: none; color: var(--m-ink); font-size: var(--fs-base); font-weight: 700; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.msgr-cli-company-name:focus-visible { outline: 2px solid var(--m-brand); outline-offset: 2px; }
.msgr-cli-subnames, .msgr-cli-number.is-empty, .msgr-cli-table-memo { color: var(--m-muted); }
.msgr-cli-number { font-variant-numeric: tabular-nums; }
.msgr-cli-table-memo, .msgr-cli-table-line { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-cli-table-group > td { padding: 0; }
.msgr-cli-table-group .msgr-clisec { margin: 0; padding: 12px 10px; font-size: var(--fs-meta); }
.msgr-cli-db.is-table .msgr-cliprof, .msgr-cli-db.is-table .msgr-cli-placeholder { flex: 0 0 380px; width: 380px; box-sizing: border-box; min-height: 0; overflow-y: auto; padding: 20px; }
.msgr-cli-db.is-table .msgr-cli-columns { grid-template-columns: minmax(0, 1fr); gap: 0; }
.msgr-cli-db.is-table .msgr-clip-top { align-items: flex-start; }
.msgr-cli-db.is-table .msgr-clip-name { flex: 1; min-width: 0; }
.msgr-cli-close { flex: none; margin-left: auto; }
@media (hover: hover) {
    .msgr-cli-table-row:hover { background: var(--m-brand-tint); }
}

/* 메신저 설치 안내는 PC 띠 또는 목록 버튼 한 곳, 폰은 더 보기에서 제공한다. */
.msgr-installbar:not(:empty) + .msgr-root .msgr-installbtn { display: none; }
.msgr-greetings { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 8px; }
.msgr-activity { color: var(--m-ink); font-size: var(--fs-base); padding: 12px; line-height: 1.6; word-break: keep-all; }

/* 승인 시안 ① — 마우스 PC 전용. 터치·폰은 기존 폭·색·입력 배치를 유지한다. */
.msgr-list-resize, .msgr-actbtn.msgr-act-desktop { display: none; }
@media (hover: none), (pointer: coarse) {
    .msgr-root { --msgr-list-w: 300px !important; }
}
@media (min-width: 800px) and (hover: hover) and (pointer: fine) {
    .msgr-list-resize {
        display: block; position: relative; flex: 0 0 10px; width: 10px; margin: 0 -5px;
        z-index: 6; cursor: col-resize; touch-action: none;
    }
    .msgr-list-resize::after {
        content: ''; position: absolute; top: calc(50% - 18px); left: 3px;
        width: 4px; height: 36px; border-radius: 999px; background: var(--m-brand);
    }
    .msgr-list-resize:hover, .msgr-list-resize:focus-visible { background: var(--m-brand-ring); outline: none; }
    .msgr-root.is-list-resizing { cursor: col-resize; user-select: none; }
    .msgr-root.is-clients .msgr-list-resize, .msgr-root.is-phone-page .msgr-list-resize { display: none; }
}
@media (min-width: 769px) and (hover: hover) and (pointer: fine) {
    /* 명시도: 어두운 토큰 블록(:is(body.msgr-view, .msgr-root) = 0,2,2)과 같게 맞춰 뒤에 오는 이 규칙이 이긴다 */
    html[data-theme="dark"] :is(body.msgr-view, .msgr-root) {
        --m-bubble-mine: var(--m-bubble-mine-desktop);
        --m-on-bubble-mine: var(--m-on-bubble-mine-desktop);
    }
    .msgr-actbtn.msgr-act-desktop { display: inline-flex; }
    .msgr-msg .msgr-msgact {
        left: var(--msgr-act-left, auto); top: var(--msgr-act-top, 50%); right: auto;
        width: max-content; transform: translateY(-50%);
    }
    /* 6px 간격을 건너갈 때도 hover가 이어져 실제 버튼에 닿는다. */
    .msgr-msgact::before { content: ''; position: absolute; right: 100%; top: 0; width: 7px; height: 100%; }
    .msgr-msg.is-mine .msgr-msgact::before { right: auto; left: 100%; }
    .msgr-msg.is-actin .msgr-msgact { left: auto; right: 0; top: var(--msgr-act-over-top, -24px); transform: none; }
    .msgr-composer {
        margin: 0 14px 10px; padding: 8px 10px; border: 1px solid var(--m-hairline); border-radius: var(--m-r3);
        background: var(--m-surface);
    }
    .msgr-composer:focus-within { border-color: var(--m-brand); box-shadow: 0 0 0 3px var(--m-brand-focus); }
    .msgr-composer .msgr-inputwrap, .msgr-composer .msgr-inputwrap:focus-within {
        border: 0; border-radius: 0; padding: 2px 0; background: transparent; box-shadow: none;
    }
    .msgr-composer .msgr-cfoot { flex-wrap: wrap; }
    .msgr-composer .msgr-sendgroup { display: flex; align-items: center; flex: 0 0 auto; margin-left: auto; }
    .msgr-composer .msgr-scopebar { margin: 0 6px 0 0; flex: 0 0 auto; }
    .msgr-composer .msgr-scopehint {
        position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
        overflow: hidden; clip-path: inset(50%); white-space: nowrap;
    }
}

/* PC 대화 내용과 입력 상자의 중심·폭을 맞춘다. 스크롤·sticky 기준과 스레드 폭은 유지한다. */
@media (min-width: 769px) {
    .msgr-msgs {
        padding-left: max(16px, calc((100% - 820px) / 2));
        padding-right: max(16px, calc((100% - 820px) / 2));
    }
    .msgr-composer {
        box-sizing: border-box; width: calc(100% - 32px); max-width: 820px;
        margin-left: auto; margin-right: auto;
    }
}

/* 전송 중 첨부 — 구독 메시지와 분리한 마지막 칸, 내 말풍선과 같은 테마 토큰 */
.msgr-sending { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; padding: 12px 16px; }
.msgr-sending[hidden], .msgr-sending-card[hidden] { display: none; }
.msgr-sending-card { max-width: min(85%, 380px); min-width: 0; padding: 12px; border-radius: 12px; background: var(--m-bubble-mine); color: var(--m-on-bubble-mine); font-size: var(--fs-sm); overflow-wrap: anywhere; }
.msgr-sending-status { font-weight: 600; margin-bottom: 8px; }
.msgr-sending-thumbs { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.msgr-sending-thumbs img { width: 64px; height: 64px; object-fit: cover; border-radius: 6px; }
.msgr-sending-file, .msgr-sending-reason { margin-top: 6px; }
.msgr-sending-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
.msgr-sending-actions button { min-height: 44px; min-width: 44px; padding: 6px 10px; border: 1px solid currentColor; border-radius: 8px; background: transparent; color: inherit; cursor: pointer; }
