/* ═══════════════════════════════════════════════════════════════
   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 (patches.js ensureWorkspacePolishStyle) ── */
#workspaceHubDebug{display:none !important; visibility:hidden !important; height:0 !important; overflow:hidden !important;}
.workspace-hub-card{position:relative; border:1px solid #e2e8f0; border-radius:1.25rem; background:#fff; box-shadow:var(--shadow-sm); transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease;}
.workspace-hub-card:hover{transform:translateY(-2px); box-shadow:0 12px 28px rgba(15,23,42,.08); border-color:#cbd5e1;}
.workspace-hub-card::before{content:''; position:absolute; inset:0 auto 0 0; width:4px; border-radius:1.25rem 0 0 1.25rem; background:var(--hub-accent,#3b82f6); opacity:.95;}
.workspace-ops-meta{display:flex; flex-wrap:wrap; gap:.5rem; margin-top:.875rem;}
.workspace-ops-meta .meta-chip{display:inline-flex; align-items:center; padding:.35rem .65rem; border-radius:999px; background:#f8fafc; border:1px solid #e2e8f0; color:#475569; font-size:11px; font-weight:800; line-height:1;}
.workspace-ops-actions{display:flex; flex-wrap:wrap; gap:.5rem; margin-top:1rem; padding-top:1rem; border-top:1px solid #f1f5f9;}
.workspace-ops-actions button{appearance:none; border:1px solid #e2e8f0; background:#fff; color:#334155; border-radius:.75rem; padding:.55rem .8rem; font-size:11px; font-weight:900; line-height:1; transition:all .16s ease;}
.workspace-ops-actions button:hover{border-color:#60a5fa; color:#2563eb; background:#eff6ff;}
.workspace-ops-actions button.primary{background:#0f172a; border-color:#0f172a; color:#fff;}
.workspace-ops-actions button.primary:hover{background:#2563eb; border-color:#2563eb; color:#fff;}
.workspace-ops-empty{border:1px dashed #cbd5e1; border-radius:1.5rem; background:linear-gradient(180deg,#fff,#f8fafc); padding:2.75rem 1.5rem; text-align:center;}
.workspace-ops-empty .empty-icon{font-size:2.25rem; margin-bottom:.75rem;}
.workspace-ops-empty .empty-title{font-size:1rem; font-weight:900; color:#0f172a;}
.workspace-ops-empty .empty-desc{font-size:.875rem; color:#64748b; margin-top:.45rem;}
.workspace-ops-empty .empty-actions{display:flex; gap:.5rem; justify-content:center; flex-wrap:wrap; margin-top:1rem;}
.workspace-ops-empty .empty-actions button{border-radius:.9rem; padding:.7rem 1rem; font-size:.8125rem; font-weight:900; border:1px solid #cbd5e1; background:#fff; color:#334155;}
.workspace-ops-empty .empty-actions button.primary{background:#0f172a; border-color:#0f172a; color:#fff;}
@media (max-width: 640px){
  .workspace-ops-actions{gap:.4rem;}
  .workspace-ops-actions button{flex:1 1 calc(50% - .4rem); justify-content:center;}
}

/* ── 2. workspaceHubSummaryStyle (patches.js ensureStyle) ── */
.workspace-hub-summary-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:0 0 20px;}
.workspace-hub-summary-card{background:#fff;border:1px solid #e2e8f0;border-radius:var(--radius-lg);padding:18px 18px 16px;box-shadow:var(--shadow-sm)}
.workspace-hub-summary-card .label{font-size:11px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#94a3b8;margin-bottom:6px}
.workspace-hub-summary-card .value{font-size:clamp(1.1rem,2vw,1.65rem);font-weight:900;color:#0f172a;line-height:1.1}
.workspace-hub-summary-card .sub{font-size:12px;color:#64748b;margin-top:6px;font-weight:700}
.workspace-hub-quickbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;justify-content:space-between;padding:14px 16px;margin:0 0 20px;border:1px solid #e2e8f0;border-radius:var(--radius-lg);background:linear-gradient(180deg,#fff,#f8fafc);box-shadow:var(--shadow-xs)}
.workspace-hub-quickbar .quick-title{font-size:13px;font-weight:900;color:#0f172a}
.workspace-hub-quickbar .quick-sub{font-size:12px;color:#64748b;font-weight:700;margin-top:3px}
.workspace-hub-quickbar .quick-actions{display:flex;flex-wrap:wrap;gap:8px}
.workspace-hub-quickbar .quick-actions button{appearance:none;border:1px solid #dbeafe;background:#eff6ff;color:#1d4ed8;border-radius:12px;padding:10px 12px;font-size:12px;font-weight:900;line-height:1;transition:all .15s ease}
.workspace-hub-quickbar .quick-actions button:hover{background:#dbeafe;border-color:#93c5fd}
.workspace-hub-quickbar .quick-actions button.primary{background:#0f172a;border-color:#0f172a;color:#fff}
.workspace-hub-quickbar .quick-actions button.primary:hover{background:#2563eb;border-color:#2563eb}
.workspace-hub-quickbar .quick-actions button.ghost{background:#fff;border-color:#e2e8f0;color:#334155}
.workspace-hub-quickbar .quick-actions button[disabled]{opacity:.45;cursor:not-allowed}
.workspace-hub-current-badge{display:inline-flex;align-items:center;padding:.3rem .6rem;border-radius:999px;background:#dbeafe;border:1px solid #93c5fd;color:#1d4ed8;font-size:11px;font-weight:900;margin-left:8px}
@media (max-width:1024px){.workspace-hub-summary-grid{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media (max-width:640px){.workspace-hub-summary-grid{grid-template-columns:1fr;}.workspace-hub-quickbar{padding:14px}.workspace-hub-quickbar .quick-actions{width:100%}.workspace-hub-quickbar .quick-actions button{flex:1 1 calc(50% - 8px);justify-content:center}}

/* ── 3. opsConsistencyV2710Style (patches.js ops consistency) ── */
.ops-summary-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:0 0 18px}
.ops-summary-card{background:linear-gradient(180deg,#ffffff,#f8fafc);border:1px solid #e2e8f0;border-radius:var(--radius-lg);padding:16px 18px 14px;box-shadow:var(--shadow-sm)}
.ops-summary-card .label{font-size:11px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#94a3b8;margin-bottom:6px}
.ops-summary-card .value{font-size:clamp(1rem,2vw,1.5rem);font-weight:900;color:#0f172a;line-height:1.12}
.ops-summary-card .sub{font-size:12px;color:#64748b;margin-top:6px;font-weight:700}
.ops-currentbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;margin:0 0 18px;border:1px solid #e2e8f0;border-radius:var(--radius-lg);background:linear-gradient(180deg,#fff,#f8fafc);box-shadow:var(--shadow-xs)}
.ops-currentbar .title{font-size:13px;font-weight:900;color:#0f172a}
.ops-currentbar .sub{font-size:12px;color:#64748b;font-weight:700;margin-top:3px}
.ops-currentbar .actions{display:flex;flex-wrap:wrap;gap:8px}
.ops-currentbar .actions button{appearance:none;border:1px solid #dbeafe;background:#eff6ff;color:#1d4ed8;border-radius:12px;padding:10px 12px;font-size:12px;font-weight:900;line-height:1;transition:all .15s ease}
.ops-currentbar .actions button:hover{background:#dbeafe;border-color:#93c5fd}
.ops-currentbar .actions button.primary{background:#0f172a;border-color:#0f172a;color:#fff}
.ops-currentbar .actions button.primary:hover{background:#2563eb;border-color:#2563eb}
.ops-currentbar .actions button.ghost{background:#fff;border-color:#e2e8f0;color:#334155}
.ops-currentbar .actions button[disabled]{opacity:.45;cursor:not-allowed}
.ops-badge{display:inline-flex;align-items:center;padding:.32rem .62rem;border-radius:999px;background:#dbeafe;border:1px solid #93c5fd;color:#1d4ed8;font-size:11px;font-weight:900;margin-left:8px}
@media (max-width:1024px){.ops-summary-grid{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media (max-width:640px){.ops-summary-grid{grid-template-columns:1fr}.ops-currentbar{padding:14px}.ops-currentbar .actions{width:100%}.ops-currentbar .actions button{flex:1 1 calc(50% - 8px);justify-content:center}}

/* ── 4. removeCurrentProjectQuickbarsStyle (patches.js quickbar hide) ── */
#workspaceHubQuickbar,.workspace-hub-quickbar,#homeOpsQuickbar,#dashOpsQuickbar,.ops-currentbar{display:none !important;}

/* ── 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, body.workspace-board-mode-v8 #currentWorkspaceBox, body.workspace-board-mode-v8 #currentDeleteBtn { 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,
body.workspace-detail-mode-v27 #ctxnav-wbs,
body.workspace-detail-mode-v27 #ctxnav-issues,
body.workspace-detail-mode-v27 #ctxnav-runningorder,
body.workspace-detail-mode-v27 #ctxnav-dailylog,
body.workspace-detail-mode-v27 #ctxnav-estimate,
body.workspace-detail-mode-v27 #ctxnav-quote,
body.workspace-detail-mode-v27 #ctxnav-expense,
body.workspace-detail-mode-v27 #ctxnav-finance,
body.workspace-detail-mode-v27 #ctxnav-portal,
body.workspace-detail-mode-v27 #ctxnav-extcrew{display:flex !important;}
body.workspace-detail-mode-v27 #currentWorkspaceBox,
body.workspace-detail-mode-v27 #currentDeleteBtn{display:block !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. v47DetailHeaderCleanupStyle (patches.js save chip) ── */
#projectContextStrip .pcs-chip#pcsSaveChip{background:#f8fafc;border-color:#cbd5e1;color:#475569}
#projectContextStrip .pcs-chip#pcsSaveChip.pcs-saving{background:#eff6ff;border-color:#93c5fd;color:#1d4ed8}

/* ── 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}

/* ── 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%); }

/* 포탈 헤더 */
.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); }

/* projQuickModal 오버레이 */
.proj-quick-overlay { background:rgba(15,23,42,0.5); 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:#94a3b8; }

/* 퇴근 모달 */
.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-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:#94a3b8; z-index:5; }
.seal-btn-pos { right:4px; top:4px; z-index:30; }

/* 설정 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:850px; 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;
  }
  /* 인감 버튼 + 직인 영역 컴팩트 */
  .seal-btn-pos { transform: scale(0.85); transform-origin: top right; }
  /* "귀하" 폰트 축소 */
  .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: #94a3b8; }
#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 + 콜그룹 너비 비율 사용
     ───────────────────────────────────────────────── */
  #estimateTable {
    display: table !important;
    table-layout: fixed !important;
    width: 100% !important;
    min-width: 0 !important;
    font-size: 10px !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;
  }

  /* 견적서 표 */
  .quote-table {
    display: table !important;
    table-layout: fixed !important;
    width: 100% !important;
    min-width: 0 !important;
    font-size: 10px !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-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;
    font-size: 9px !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;
  }
  #view-estimate table.w-full th {
    font-size: 8px !important;
  }

  /* ─────────────────────────────────────────────────
     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) — 모바일 숨김 (자동 계산되는 보조 정보, 데스크톱에서 편집) */
  #expBody tr.exp-row td:nth-child(6),
  #expBody tr.exp-row td:nth-child(7),
  #expBody tr.exp-row td:nth-child(8) {
    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: 9px !important;
    color: #94a3b8 !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(12) {
    grid-column: 3 !important;
    grid-row: 3 !important;
    text-align: right !important;
  }
  /* delete(13) — 모바일 숨김 (col 3 어수선함 정리, 삭제는 데스크톱) */
  #expBody tr.exp-row td:nth-child(13) {
    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(12) {
    padding-right: 2px !important;
    text-align: right !important;
  }
  /* 첨부(11)·지급(12) 같은 grid cell 안에서 클릭 영역 분리 —
     justify-self: start/end + width:auto 로 td 자체 box 가 콘텐츠 폭만큼만 차지.
     이전 padding-right:22px 방식은 11 td 가 12 자리까지 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(12) {
    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 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;
  }
  /* 체크박스는 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 select:focus {
    background: #f8fafc !important;
    border-bottom-color: #94a3b8 !important;
  }
  /* 첨부 등 버튼 압축 */
  #expBody tr.exp-row td button {
    font-size: 9px !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(12) {
    min-height: 0 !important;
    align-self: center;
  }
  /* grid row 명시는 위쪽 #expBody tr.exp-row 정의에서 24/22/22 (3행) 처리됨 */

  /* ─── 상단 5컬럼 합계표 — 한 줄에 다 보이도록 압축 ─── */
  .fin-exp-summary {
    min-width: 0 !important;
    font-size: 9px !important;
    table-layout: fixed !important;
  }
  .fin-exp-summary thead th {
    padding: 4px 2px !important;
    font-size: 8px !important;
    word-break: keep-all;
    line-height: 1.15;
  }
  .fin-exp-summary tbody td {
    padding: 6px 2px !important;
    font-size: 11px !important;
  }
  .fin-exp-summary #expGrandTotal {
    font-size: 13px !important;
  }
  #view-expense .doc-table-wrap {
    overflow-x: hidden !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%;
    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; }

  /* ── 💰 자금 거래내역 (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%;
    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; }
  .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; }
  .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; }
}


/* ═══════════════════════════════════════════════════════════
   🗓 전사 일정 (간트 매트릭스) — 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: #94a3b8; 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: #94a3b8; 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: #94a3b8; 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: #94a3b8; letter-spacing: 0.02em; white-space: nowrap;
}
.gg-lidiv {
    padding: 7px 12px; font-size: 10.5px; font-weight: 700; color: #94a3b8;
    background: #f8fafc; border-bottom: 1px solid var(--gg-line, #e2e8f0);
}

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

/* D-1a. 빈 편집 가능 셀 → "＋ 항목" 어포던스 (버튼처럼 무겁지 않게) */
/* 대비: #b6c0cd 는 흰 배경에서 약 2.2:1 로 흐릿해 '비어 있음'조차 안 읽힌다 → 한 단계 진하게 */
.gg-ph {
    color: #94a3b8; 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: #94a3b8; }

/* D-3a. 편집 가능 셀 — hover/focus 시 ✎ 마이크로 아이콘 */
.gg-cellpen {
    position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
    font-size: 9px; color: #94a3b8; 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: #94a3b8; 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: #92400e; background: #fef3c7; border: 1px solid #fde68a;
    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: #f5f3ff; border: 1px solid #e9d5ff; border-radius: 8px;
}
.msgr-installbar:empty { display: none; }
/* 🖼 방 아이콘 — 이미지가 있으면 사진, 없으면 색 이니셜. **자리는 항상 같은 크기**라
   방마다 목록 정렬이 흔들리지 않는다. */
.msgr-roomav {
    flex: 0 0 34px; width: 34px; height: 34px; border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden; color: #fff; 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: #6d28d9; box-shadow: 0 0 0 3px rgba(109, 40, 217, .15); }
.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: #f8fafc; border-color: #e2e8f0; }
.msgr-installbar.is-muted .msgr-ibtxt { color: #64748b; font-weight: 500; }
.msgr-installbar.is-muted .msgr-ibx { color: #94a3b8; }
.msgr-ibic { flex: 0 0 auto; font-size: 17px; line-height: 1; }
.msgr-ibtxt { flex: 1 1 auto; font-size: var(--m-badge); color: #6d28d9; font-weight: 600; line-height: 1.45; }
.msgr-ibgo {
    flex: 0 0 auto; border: 0; border-radius: 999px; padding: 6px 14px; cursor: pointer;
    background: #6d28d9; color: #fff; font-size: var(--m-badge); font-weight: 700; white-space: nowrap;
    transition: all .12s;
}
.msgr-ibgo:hover { background: #5b21b6; }
.msgr-ibx {
    flex: 0 0 auto; border: 0; background: transparent; color: #a78bfa; cursor: pointer;
    font-size: var(--m-meta); padding: 2px 4px; transition: all .12s;
}
.msgr-ibx:hover { color: #6d28d9; }
/* ═══ 💬 메신저 디자인 토큰 (2026-08-06) ═══
   ⚠ 이 파일에 메신저 규칙을 **덧붙이지 말 것** — 원본 규칙을 고칠 것.
   스크린샷을 받을 때마다 말미에 override 블록을 쌓은 결과 글자 크기가 14종,
   모서리가 14종이 됐고 그게 '투박함'의 정체였다(실측). 값이 필요하면 토큰을 늘린다. */
.msgr-root {
    --m-base: 14px;    /* 셸 기본 */
    --m-body: 15px;    /* 대화 본문 — 여기가 제일 중요하다 */
    --m-title: 16px;   /* 패널 제목 */
    --m-name: 14px;    /* 사람 이름 */
    --m-meta: 12px;    /* 시각·부가정보 */
    --m-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);
    --m-glass-bg: rgba(255, 255, 255, .72);
}
/* 유리를 못 그리는 브라우저에서 반투명만 남으면 **글자 뒤로 대화가 비쳐 못 읽는다** */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .msgr-root, .msgr-ov, .msgr-sheetov { --m-glass-bg: #fff; }
}
/* 투명 효과 줄이기를 켠 사용자 — 대비가 배경에 따라 변하는 걸 원치 않는다는 뜻이다 */
@media (prefers-reduced-transparency: reduce) {
    .msgr-root, .msgr-ov, .msgr-sheetov { --m-glass-bg: #fff; }
}
.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 #e2e8f0; border-radius: 12px; overflow: hidden;
    background: #fff; font-size: var(--m-base); color: #0f172a;
    position: relative;   /* 🏢 거래처 패널(absolute)의 기준 */
}
.msgr-root * { box-sizing: border-box; }

/* ⌨️ 키보드 포커스 링은 **여기서 만들지 않는다** — style.css:1334 의 전역
   `:focus-visible`(2px #3B82F6)이 이미 앱 전체를 덮는다. 메신저만 다른 색 링을
   두면 그게 바로 «OS 안의 별도 프로그램»처럼 보이는 원인이 된다(2026-08-06 검토·기각). */

/* ✨ 전환 — 눌렀을 때 «뻣뻣하게 툭» 바뀌던 것을 짧게 이어 준다(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 안에서 곁다리로 있을 때 만든 치수를 그대로 쓰면 앱의 중심축이 곁다리로 보인다). */
.msgr-rail {
    width: 68px; flex: 0 0 68px; background: #fff; border-right: 1px solid #e2e8f0;
    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: #64748b;
    transition: all .12s;   /* 앱 전역 관용구 — 없으면 hover 가 «툭» 바뀐다 */
}
.msgr-railbtn:hover { background: #eef2ff; color: #4f46e5; }
.msgr-railbtn.is-active { background: #ede9fe; color: #6d28d9; }
/* 활성 표시를 색만으로 하지 않는다 — 색각이상·저대비 화면에서 어느 쪽인지 안 보인다 */
.msgr-railbtn.is-active::before {
    content: ''; position: absolute; left: 0; width: 3px; height: 26px;
    border-radius: 0 999px 999px 0; background: #6d28d9;
}
.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: #fff; 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: #22c55e; border: 2px solid #fff;
}

/* ── 2) 대화 목록 ── */
.msgr-list {
    width: 282px; flex: 0 0 282px; border-right: 1px solid #e2e8f0;
    display: flex; flex-direction: column; background: #fff; min-height: 0;
}
.msgr-searchwrap { display: flex; gap: 6px; padding: 10px; border-bottom: 1px solid #f1f5f9; }
/* 🏢 회사 로고 — 이름 왼쪽 (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 #e2e8f0; border-radius: 8px;
    padding: 0 10px; font-size: 12px; background: #f8fafc; outline: none;
}
.msgr-search:focus { border-color: #a5b4fc; background: #fff; }
.msgr-newbtn {
    width: 32px; height: 32px; flex: 0 0 32px; border: 0; border-radius: 8px;
    background: #6d28d9; color: #fff; font-size: 17px; font-weight: 700; cursor: pointer; line-height: 1;
}
.msgr-fixed { padding: 6px; border-bottom: 1px solid #f1f5f9; }
.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: #334155; text-align: left;
}
.msgr-fixitem:hover { background: #f1f5f9; }
.msgr-fixitem:disabled { opacity: .42; cursor: default; }
.msgr-fixitem:disabled:hover { background: transparent; }
.msgr-fixitem.is-active { background: #eef2ff; color: #4338ca; 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: #475569;
    position: sticky; top: 0; background: #fff; 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;
    /* 🖼 방 아이콘 + 제목/미리보기 — 아이콘이 왼쪽 한 칸, 나머지 두 줄은 오른쪽에 쌓인다.
       ⚠ 이 규칙을 **여기서** 고칠 것. 앞쪽에 `.msgr-room { display:flex }` 를 덧붙이면
         이 선언이 뒤에 있어 그대로 이긴다(2026-08-07 실제로 그렇게 만들었다가 잡음). */
    display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0 10px;
}
.msgr-room > .msgr-roomav { order: 0; }
.msgr-room > .msgr-room-top { order: 1; flex: 1 1 0; min-width: 0; }
.msgr-room > .msgr-room-bot { order: 2; flex: 0 0 100%; min-width: 0; padding-left: 44px; }
.msgr-room:hover { background: #f8fafc; }
.msgr-room.is-active { background: #6d28d9; }
.msgr-room.is-active .msgr-room-title,
.msgr-room.is-active .msgr-room-last { color: #fff; }
.msgr-room.is-active .msgr-room-at,
.msgr-room.is-active .msgr-room-cnt { color: #ddd6fe; }
.msgr-room-top { display: flex; align-items: center; gap: 5px; }
.msgr-room-title {
    font-size: var(--m-name); font-weight: 600; color: #0f172a;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px;
}
.msgr-room-cnt { font-size: var(--m-badge); color: #cbd5e1; font-weight: 500; }
.msgr-room-lock { font-size: 9px; }
.msgr-room-at { margin-left: auto; font-size: var(--m-badge); color: #94a3b8; 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: #64748b;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msgr-room-by {
    flex: 0 0 auto; max-width: 62px; font-size: var(--m-meta); color: #94a3b8;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msgr-room-by::after { content: ':'; margin-left: 1px; }
.msgr-room.is-active .msgr-room-by { color: #ddd6fe; }
/* ★ 미읽음 점 — absolute 로 우측에 띄우면 '5분 전' 시각과 겹친다(실측). 행 흐름 안에 둔다. */
.msgr-unread {
    flex: 0 0 auto; color: #ef4444; font-size: 9px; line-height: 1; margin-left: 1px;
}
.msgr-room.is-active .msgr-unread { color: #fff; }

/* ── 3) 중앙 ── */
.msgr-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; background: #fff; }
.msgr-tabbar {
    display: flex; align-items: center; gap: 4px; padding: 8px 10px;
    border-bottom: 1px solid #e2e8f0; overflow-x: auto;
}
.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: #475569;
    white-space: nowrap; font-weight: 600;
}
.msgr-tab:hover { background: #f1f5f9; }
.msgr-tab.is-active { background: #fff; border-color: #ddd6fe; color: #0f172a; font-weight: 800; box-shadow: 0 1px 2px rgba(15,23,42,.06); }
.msgr-tabdot { width: 12px; height: 12px; border-radius: 999px; flex: 0 0 12px; }
.msgr-tabbadge {
    min-width: 16px; height: 16px; border-radius: 8px; background: #ede9fe; color: #6d28d9;
    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: #94a3b8; cursor: pointer; padding: 3px 6px; }

.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: #94a3b8; background: #f1f5f9; 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: #0f172a; }
.msgr-orgbadge { font-size: var(--m-badge); font-weight: 600; border-radius: var(--m-r1); padding: 1px 6px; }
.msgr-guest {
    font-size: var(--m-badge); font-weight: 700; color: #be185d; background: #fce7f3;
    border-radius: var(--m-r1); padding: 1px 6px; letter-spacing: .02em;
}
.msgr-msgat { font-size: var(--m-meta); color: #94a3b8; }
.msgr-msgtext {
    /* 💬 말풍선 — 거래처 화면(guest `.tx`)과 같은 모양. inline-block 이라
       내용만큼만 넓어진다(블록이면 짧은 «넵»도 컬럼 전체를 차지한다). */
    display: inline-block; max-width: 100%;
    background: #f1f5f9; border-radius: var(--m-r3); padding: 9px 12px;
    font-size: var(--m-body); line-height: 1.62; color: #0f172a; margin-top: 2px;
    white-space: pre-wrap; word-break: keep-all; overflow-wrap: anywhere;
}

/* ── 💬 내 메시지 = **왼쪽** 보라 말풍선 ────────────────────────────────
   ⚠ 판정은 uid 로만(msgr-shell-msgs.js) — 이름은 동명이인이 있으면 오판한다.
   ★**오른쪽 정렬을 쓰지 않는다**(2026-08-06 사장님 «너무 먼거같아») — 카톡식
     좌우 배치는 폰에선 자연스럽지만 데스크톱 대화 컬럼은 폭이 넓어 눈이 좌우로
     왕복하게 되고, 아바타·이름·시각의 세로 정렬이 두 줄로 갈라져 흐름이 끊긴다.
     구분은 **색 하나로 충분**하다 — 전부 왼쪽에 두고 내 것만 보라로 칠한다. */
.msgr-msg.is-mine .msgr-msgtext { background: #6d28d9; color: #fff; }
/* 보라 위 남색 링크는 안 읽힌다 */
.msgr-msg.is-mine .msgr-msgtext .msgr-link { color: #ede9fe; }
.msgr-msg.is-mine .msgr-msgtext .msgr-mention { background: rgba(255, 255, 255, .22); color: #fff; }
/* 🗑 삭제 자리표시는 말풍선이 아니다(빈 보라 상자가 되면 무슨 일인지 모른다) */
.msgr-deleted { background: none; padding: 2px 0; }
.msgr-reactions { display: flex; gap: 4px; margin-top: 5px; flex-wrap: wrap; }
.msgr-reaction {
    display: flex; align-items: center; gap: 3px; border: 1px solid #e0e7ff; background: #eef2ff;
    border-radius: 999px; padding: 1px 7px; font-size: var(--m-meta); cursor: pointer; line-height: 1.6;
}
.msgr-reactn { font-weight: 700; color: #4338ca; font-size: var(--m-badge); }
.msgr-reactadd { background: #f8fafc; border-color: #e2e8f0; color: #94a3b8; }
.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: #4338ca; }
.msgr-threadat { font-size: var(--m-meta); color: #94a3b8; }
/* ✓ 읽음 — **말풍선 옆 작은 숫자**(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: #94a3b8; white-space: nowrap;
}

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

/* 컴포저 */
.msgr-composer { border-top: 1px solid #e2e8f0; padding: 8px 12px 10px; background: #fff; }
.msgr-composer.is-internal { background: #faf5ff; }
.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: #64748b; font-size: 12px; padding: 0 5px;
}
.msgr-tool:hover { background: #f1f5f9; }
.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: #e2e8f0; margin: 0 5px; }
.msgr-seg { display: flex; border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden; }
.msgr-segbtn {
    border: 0; background: #fff; padding: 3px 12px; font-size: 11px; font-weight: 700;
    color: #64748b; cursor: pointer;
}
.msgr-segbtn.is-active { background: #6d28d9; color: #fff; }
.msgr-inputwrap { border: 1px solid #e2e8f0; border-radius: 8px; padding: 7px 10px; background: #fff; }
.msgr-composer.is-internal .msgr-inputwrap { border-color: #c4b5fd; }
.msgr-input {
    width: 100%; border: 0; outline: none; resize: none; font-size: 13px; line-height: 1.6;
    font-family: inherit; color: #0f172a; background: transparent;
}
.msgr-cfoot { display: flex; align-items: center; gap: 2px; margin-top: 6px; }
.msgr-send {
    width: 30px; height: 30px; border: 0; border-radius: 8px; background: #6d28d9; color: #fff;
    font-size: 13px; cursor: pointer;
}

/* ── 4) 우측 정보 패널 ── */
.msgr-side {
    width: 300px; flex: 0 0 300px; border-left: 1px solid #e2e8f0; background: #fff;
    display: flex; flex-direction: column; min-height: 0;
}
.msgr-sidetabs { display: flex; gap: 4px; padding: 9px 10px; border-bottom: 1px solid #f1f5f9; }
.msgr-sidetab {
    flex: 1 1 0; padding: 5px 0; border: 0; background: #f8fafc; border-radius: 8px;
    font-size: 11.5px; font-weight: 700; color: #64748b; cursor: pointer;
}
.msgr-sidetab.is-active { background: #ede9fe; color: #6d28d9; 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 #e2e8f0; border-radius: 8px; padding: 7px 10px;
    font-size: 12px; background: #f8fafc; color: #0f172a;
}
.msgr-filesearch:focus { outline: 0; border-color: #a5b4fc; background: #fff; }
.msgr-filechips { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 10px; }
.msgr-filechip {
    border: 1px solid #e2e8f0; background: #fff; border-radius: 999px;
    padding: 3px 9px; font-size: 11px; color: #475569; cursor: pointer; white-space: nowrap;
}
.msgr-filechip:hover { background: #f1f5f9; }
.msgr-filechip.is-active { background: #4f46e5; border-color: #4f46e5; color: #fff; font-weight: 700; }
.msgr-filerow {
    display: flex; align-items: center; gap: 9px; padding: 8px 6px;
    border-radius: 8px; border-bottom: 1px solid #f8fafc;
}
.msgr-filerow:hover { background: #f8fafc; }
.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: #0f172a;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msgr-filename.is-link { cursor: pointer; }
.msgr-filename.is-link:hover { color: #4f46e5; text-decoration: underline; }
.msgr-filemeta {
    display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
    font-size: var(--m-badge); color: #94a3b8; margin-top: 2px;
}
.msgr-filedot { color: #cbd5e1; }
.msgr-fileorg { font-weight: 700; }

/* 🔗 본문 자동 링크 (msgr-text.js) */
.msgr-link { color: #4f46e5; text-decoration: underline; word-break: break-all; }
.msgr-link:hover { color: #3730a3; }

/* ✨ 메시지 보정 바 — 컴포저 바로 위 인라인(모달 아님) */
.msgr-aibar {
    border: 1px solid #ddd6fe; background: #f5f3ff; 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: #6d28d9; }
.msgr-aitone { font-weight: 700; font-size: var(--m-badge); color: #7c3aed; background: #ede9fe; border-radius: 6px; padding: 1px 6px; }
.msgr-aix { border: 0; background: transparent; color: #a78bfa; cursor: pointer; font-size: 12px; padding: 0 2px; }
.msgr-aix:hover { color: #6d28d9; }
.msgr-aitext {
    margin-top: 6px; font-size: 13px; color: #1e1b4b; 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: #b45309; background: #fffbeb; border-radius: 6px; padding: 5px 8px; line-height: 1.5; }
.msgr-aiblock { margin-top: 6px; font-size: 11.5px; color: #b91c1c; background: #fef2f2; border: 1px solid #fecaca; border-radius: 6px; padding: 7px 9px; font-weight: 700; }
.msgr-aisub { font-weight: 400; color: #991b1b; 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: #6d28d9; color: #fff; border-radius: 8px;
    padding: 6px 14px; font-size: 12px; font-weight: 700; cursor: pointer;
}
.msgr-aiapply:hover { background: #5b21b6; }
.msgr-aiagain {
    border: 1px solid #ddd6fe; background: #fff; color: #6d28d9; border-radius: 8px;
    padding: 6px 12px; font-size: 12px; font-weight: 700; cursor: pointer;
}
.msgr-aiagain:hover { background: #f5f3ff; }
.msgr-ainote { margin-top: 7px; font-size: var(--m-badge); color: #a78bfa; line-height: 1.5; }
.msgr-aiundo { display: flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700; color: #6d28d9; }

/* 📅 일정 공유 모달 */
.msgr-schedback {
    position: fixed; inset: 0; z-index: 80; background: rgba(15,23,42,.45);
    display: flex; align-items: center; justify-content: center; padding: 20px;
}
.msgr-schedbox {
    background: #fff; border-radius: 12px; width: 100%; max-width: 420px;
    max-height: 82vh; display: flex; flex-direction: column; padding: 14px;
    box-shadow: 0 20px 50px rgba(15,23,42,.25);
}
.msgr-schedhead { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 800; color: #0f172a; margin-bottom: 10px; }
.msgr-schedsel {
    width: 100%; border: 1px solid #e2e8f0; border-radius: 8px; padding: 7px 9px;
    font-size: 12.5px; background: #fff; color: #0f172a;
}
.msgr-schedopts { display: flex; gap: 14px; margin: 8px 0; }
.msgr-schedopt { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: #475569; cursor: pointer; }
.msgr-schedlist { flex: 1 1 auto; overflow-y: auto; min-height: 0; max-height: 260px; border: 1px solid #f1f5f9; border-radius: 8px; padding: 4px; }
.msgr-schedrow {
    display: flex; align-items: center; gap: 7px; padding: 5px 6px;
    border-radius: 6px; cursor: pointer; font-size: 12px;
}
.msgr-schedrow:hover { background: #f8fafc; }
.msgr-scheddate { flex: 0 0 auto; font-weight: 700; color: #4f46e5; font-size: 11px; min-width: 62px; }
.msgr-schedtask { flex: 1 1 auto; min-width: 0; color: #0f172a; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-schedwho { flex: 0 0 auto; font-size: var(--m-badge); color: #94a3b8; }
.msgr-schedprev {
    margin-top: 10px; background: #f8fafc; border-radius: 8px; padding: 8px 10px;
    font-size: 11.5px; color: #334155; white-space: pre-wrap; line-height: 1.6;
    max-height: 130px; overflow-y: auto;
}
.msgr-schedempty { font-size: 11.5px; color: #94a3b8; padding: 14px 8px; text-align: center; line-height: 1.6; }
.msgr-msg.is-mine .msgr-link { color: #e0e7ff; }
.msgr-filelock { color: #b45309; background: #fef3c7; 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: #64748b; line-height: 1;
}
.msgr-filebtn:hover { background: #e2e8f0; color: #0f172a; }
.msgr-filebtn:disabled { opacity: .5; cursor: default; }
.msgr-filenote {
    margin-top: 12px; padding: 8px 10px; background: #f8fafc; border-radius: 8px;
    font-size: var(--m-badge); color: #94a3b8; line-height: 1.5;
}
.msgr-scanbtn {
    margin-top: 6px; width: 100%; border: 1px solid #c7d2fe; background: #eef2ff;
    color: #4338ca; border-radius: 8px; padding: 6px 8px; font-size: 11px;
    font-weight: 700; cursor: pointer;
}
.msgr-scanbtn:hover { background: #e0e7ff; }
.msgr-scanbtn:disabled { opacity: .55; cursor: default; }

/* 😊 컴포저 이모지 격자 · @멘션 목록 (팝오버 공통 껍데기는 .msgr-emojipop) */
.msgr-emojigrid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px; max-width: 236px; }
.msgr-mentionpop { display: block; min-width: 190px; max-height: 260px; overflow-y: auto; padding: 4px; }
.msgr-mentionhead { font-size: var(--m-badge); color: #94a3b8; 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: #eef2ff; }
.msgr-mentionname { font-size: 12px; font-weight: 600; color: #0f172a; }
.msgr-mentionrole { font-size: var(--m-badge); color: #94a3b8; }
.msgr-mentionempty { font-size: 11px; color: #94a3b8; padding: 8px 10px; }

/* ⚙️ 정보 패널 하단 대화방 관리 */
.msgr-sidemanage { margin-top: 14px; padding-top: 12px; border-top: 1px solid #f1f5f9; display: flex; flex-direction: column; gap: 6px; }
.msgr-mngbtn {
    border: 1px solid #e2e8f0; background: #fff; border-radius: 8px; padding: 8px 10px;
    font-size: 12px; color: #334155; cursor: pointer; text-align: left; font-weight: 600;
}
.msgr-mngbtn:hover { background: #f8fafc; }
.msgr-mngbtn.is-danger { color: #b91c1c; border-color: #fecaca; }
.msgr-mngbtn.is-danger:hover { background: #fef2f2; }

/* 📎 드래그앤드롭 오버레이 */
.msgr-main { position: relative; }
.msgr-dropover::after {
    content: '📎 여기에 놓으면 파일이 전송됩니다';
    position: absolute; inset: 8px; z-index: 40;
    display: flex; align-items: center; justify-content: center;
    background: rgba(79, 70, 229, .08); border: 2.5px dashed #818cf8; border-radius: 12px;
    color: #4338ca; 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 #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; }

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

/* 🚪 외부 참여자 내보내기 */
.msgr-kick {
    flex: 0 0 auto; border: 0; background: transparent; color: #cbd5e1; cursor: pointer;
    font-size: 12px; padding: 3px 6px; border-radius: 6px; margin-left: 2px;
}
.msgr-kick:hover { background: #fef2f2; color: #dc2626; }
.msgr-kick:disabled { opacity: .5; }

/* 🖼 이미지 첨부 썸네일 */
.msgr-imgthumb {
    display: inline-block; max-width: 240px; margin-top: 4px; border-radius: 8px;
    overflow: hidden; cursor: zoom-in; border: 1px solid #e2e8f0; 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, #eef2f7 30%, #f8fafc 50%, #eef2f7 70%) #eef2f7;
    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: #fff; border: 1px solid #e2e8f0; border-radius: 8px;
    box-shadow: 0 10px 30px rgba(15, 23, 42, .16); 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: #0f172a; cursor: pointer;
}
.msgr-tahit:hover { background: #eef2ff; }
/* 🖼 이미지 라이트박스 — 모달(z-50)·문서뷰어보다 위 */
.msgr-lightbox {
    position: fixed; inset: 0; z-index: 90; background: rgba(15, 23, 42, .88);
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 12px; padding: 24px; cursor: zoom-out;
}
.msgr-lightimg { max-width: 100%; max-height: 84vh; object-fit: contain; border-radius: 8px; cursor: default; }
.msgr-lightcap { color: #e2e8f0; font-size: 12px; max-width: 90%; text-align: center; word-break: break-all; }
.msgr-sidehead { margin-bottom: 8px; }
.msgr-sidetitle { font-size: var(--m-title); font-weight: 700; color: #0f172a; }
.msgr-sidemeta { font-size: 11px; color: #64748b; margin-top: 3px; }
.msgr-sidedesc {
    font-size: 11.5px; line-height: 1.6; color: #475569; background: #f8fafc;
    border-radius: 8px; padding: 9px 10px; margin-bottom: 12px;
}
.msgr-card { border: 1px solid #f1f5f9; border-radius: 8px; padding: 9px 10px; margin-bottom: 12px; }
.msgr-cardhead { font-size: 11.5px; font-weight: 800; color: #334155; margin-bottom: 6px; }
.msgr-bmitem { background: #f8fafc; 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: #0f172a; }
.msgr-bmage { font-size: var(--m-badge); color: #6d28d9; background: #ede9fe; border-radius: 6px; padding: 0 5px; font-weight: 700; }
.msgr-bmtext { font-size: 11.5px; color: #475569; 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; }
.msgr-groupcnt { font-size: var(--m-badge); color: #94a3b8; font-weight: 700; }
.msgr-invite {
    border: 1px solid #e2e8f0; background: #fff; border-radius: 6px; padding: 2px 8px;
    font-size: var(--m-badge); font-weight: 700; color: #475569; cursor: pointer;
}
.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: #0f172a; }
.msgr-personrole { font-size: var(--m-meta); color: #94a3b8; }
.msgr-level { flex: 0 0 auto; font-size: var(--m-badge); color: #94a3b8; 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; }
}
@media (min-width: 769px) and (max-width: 900px) {
    .msgr-list { width: 232px; flex: 0 0 232px; }
    .msgr-room-title { max-width: 108px; }
}

@media (max-width: 768px) {
    .msgr-root {
        /* 모바일은 화면을 꽉 채운다 — '앱에 얹힌 작은 상자' 느낌을 없앤다.
           dvh 로 주소창 접힘까지 대응. */
        min-height: 0;   /* 높이는 fitHeight() 실측이 정한다 */
        border-radius: 12px;
    }
    /* 📱 자체 레일 **제거**(2026-08-06) — 메시지·거래처·팀 관리는 OS 사이드바(#ctx-msgr)에
       있고, 모바일에선 왼쪽 가장자리 «›» 서랍으로 연다. 다른 OS 화면과 여는 방법이
       같아야 «메신저만 다른 앱» 느낌이 사라진다(사장님).
       🚨 **단독 앱(/msgr)은 예외** — 거기엔 그 서랍도 OS 사이드바도 없다(2026-08-07). */
    body:not(.msgr-popout) .msgr-rail { display: none; }

    /* 📱 단독 앱 모바일: 레일을 **하단 탭바**로 눕힌다. 세로 60px 컬럼을 폰에서 유지하면
       대화 목록 폭을 그만큼 먹는다.
       ★ flex 방향을 바꾸지 않고 **fixed 로 띄운다** — `.msgr-root` 의 가로 배치(목록/대화)를
         건드리면 모바일 pane 전환(is-mobile-list/room)이 함께 흔들린다. 구조를 안 만지는 쪽.
       ★ 방 화면에서는 숨긴다 — 대화 중엔 내비게이션보다 입력창 자리가 우선이고,
         ⬅️ 뒤로가기·오른쪽 스와이프로 목록에 돌아간다. */
    body.msgr-popout .msgr-rail {
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
        flex-direction: row; width: auto;
        border-right: 0; border-top: 1px solid #e2e8f0;
        justify-content: space-around;
        /* 🫧 떠 있는 면 — fixed 라 대화 목록이 이 밑으로 흐른다(여기가 유리가 가장 잘 읽히는 자리) */
        background: var(--m-glass-bg, #fff);
        -webkit-backdrop-filter: var(--m-glass); backdrop-filter: var(--m-glass);
        /* 🚨 **높이를 고정하지 않는다** (2026-08-07 아이폰 실화면 "하단 네비게이션 짤리고"):
           종전엔 52px 로 못박았는데 그 안의 `.msgr-railbtn` 이 **53px**(실측)이라 1px 넘쳐
           활성 탭의 둥근 배경이 잘렸다. 데스크톱 세로 레일 치수를 그대로 눕힌 결과다.
           ★ 아래 여백에 safe-area 를 더한다 — 홈 인디케이터가 있는 기기에서 바가 그 위로 올라온다
             (viewport-fit=cover 가 아닌 지금은 0 이라 무해하고, 홈 화면 앱으로 설치되면 살아난다). */
        height: auto;
        padding: 4px 0 calc(4px + env(safe-area-inset-bottom, 0px));
    }
    /* 눕힌 바에서는 버튼 세로 여백을 줄인다 — 세로 레일의 치수는 여기서 맞지 않는다 */
    body.msgr-popout .msgr-railbtn { padding: 5px 0 4px; border-radius: 8px; }
    body.msgr-popout .msgr-railbtn.is-active::before { display: none; }   /* 좌측 바는 세로 레일용 */
    body.msgr-popout .msgr-railme { display: none; }   /* 폰에선 내 아바타가 자리만 먹는다 */
    /* 🚨 **스페이서도 같이 없앤다** (2026-08-08 사장님 "너무 왼쪽에 붙어있는것같고").
       `.msgr-railspacer{flex:1 1 auto}` 는 **세로 레일**에서 내 아바타를 맨 아래로 밀려고
       둔 것이다. 눕힌 바에서는 그게 남는 가로 공간을 **전부** 먹어서 `space-around` 가
       작동할 자리가 없어지고 버튼 셋이 왼쪽에 뭉친다(아바타를 숨겨도 스페이서는 남는다).
       ⓘ 상단 탭바는 이미 같은 이유로 빼고 있다(:3730) — 같은 함정, 다른 자리. */
    body.msgr-popout .msgr-rail > .msgr-railspacer { display: none; }
    /* 탭바에 마지막 방이 가리지 않게 — 바 높이 + safe-area 만큼 */
    body.msgr-popout .msgr-listscroll { padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px)); }
    body.msgr-popout .msgr-root.is-mobile-room .msgr-rail { display: none; }

    /* 🚪 OS 좌측 패널 손잡이(«›»)는 메신저 전용 창에 **필요 없다** — 열어도 그 뒤에
       OS 컨텍스트 패널이 없다(body.msgr-popout 이 #contextPanel 을 숨긴다).
       화면 한가운데 떠 있는 «누르면 아무 일도 안 나는 손잡이»가 된다(사장님 아이폰 실화면). */
    body.msgr-popout #leftPanelHandle { display: none !important; }

    /* 목록·대화 둘 다 남는 폭 전체를 쓴다 — 동시에 하나만 보인다 */
    .msgr-list, .msgr-main { width: auto; flex: 1 1 auto; min-width: 0; }
    .msgr-room-title { max-width: none; }

    .msgr-root.is-mobile-list .msgr-main { display: none; }
    .msgr-root.is-mobile-room .msgr-list { display: none; }

    /* 대화 화면의 ‹ 뒤로 — 데스크톱에선 숨긴다 */
    .msgr-back { display: inline-flex !important; }

    .msgr-msgs { padding: 10px 12px; }
    .msgr-composer { padding: 7px 10px calc(8px + env(safe-area-inset-bottom)); }
    /* ⚠ 모바일에서 `.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 { min-width: 44px; height: 44px; padding: 0; }
    .msgr-root .msgr-back { min-width: 44px; height: 44px; }
    /* 세그먼트는 두 칸이 맞붙어 있어 투명 확장이 서로를 먹는다 — 높이만 키운다 */
    .msgr-root .msgr-segbtn { padding: 8px 14px; font-size: 12px; }
}
/* 데스크톱: 뒤로 버튼 숨김 (모바일 미디어쿼리에서만 되살린다) */
/* ⚠ 기본 스타일이 없으면 브라우저 UA 기본값(2px outset 테두리·회색 배경)이 그려진다 —
   실제로 그 상태로 배포돼 있었다. `display:none` 만 준 요소도 켜지는 순간을 보고 스타일할 것. */
.msgr-back {
    display: none; background: none; border: 0; padding: 0; color: #334155;
    cursor: pointer; align-items: center; justify-content: center;
}
.msgr-back:active { color: #7c3aed; }

/* 💬 메신저 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: #64748b; font-size: 12.5px;
}
.msgr-emptyic { font-size: 26px; line-height: 1; margin-bottom: 2px; }
.msgr-emptysub { font-size: 11px; color: #94a3b8; 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: rgba(15,23,42,.28);
    display: flex; align-items: center; justify-content: center; padding: 16px;
}
.msgr-dlg {
    /* 🫧 떠 있는 면 — 딤 오버레이 위라 뒤가 흐른다 */
    background: var(--m-glass-bg, #fff);
    -webkit-backdrop-filter: var(--m-glass); backdrop-filter: var(--m-glass);
    border-radius: 12px; width: 400px; max-width: 100%;
    max-height: 90vh; display: flex; flex-direction: column; overflow: hidden;
    box-shadow: 0 18px 48px rgba(15,23,42,.28); font-size: 13px; color: #0f172a;
}
.msgr-dlghead { padding: 14px 16px; font-size: 14.5px; font-weight: 800; border-bottom: 1px solid #f1f5f9; }
.msgr-dlgbody { padding: 14px 16px; overflow-y: auto; }
.msgr-fl { display: block; font-size: 11.5px; font-weight: 800; color: #475569; margin: 10px 0 4px; }
.msgr-fl:first-child { margin-top: 0; }
.msgr-fi {
    width: 100%; height: 34px; border: 1px solid #e2e8f0; border-radius: 8px;
    padding: 0 10px; font-size: 13px; font-family: inherit; background: #fff; outline: none; color: #0f172a;
}
.msgr-fi:focus { border-color: #a5b4fc; }
.msgr-fh { font-size: var(--m-badge); color: #94a3b8; 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 #e2e8f0; background: #f8fafc; border-radius: 12px; padding: 3px 10px;
    font-size: 11.5px; color: #475569; cursor: pointer;
}
.msgr-chip.is-on { background: #ede9fe; border-color: #c4b5fd; color: #6d28d9; font-weight: 700; }
.msgr-dlgfoot {
    display: flex; align-items: center; gap: 6px; padding: 11px 16px;
    border-top: 1px solid #f1f5f9; background: #f8fafc;
}
.msgr-dlgerr { flex: 1 1 auto; font-size: 11px; color: #dc2626; }
.msgr-btn {
    border: 1px solid #e2e8f0; background: #fff; border-radius: 8px; padding: 6px 14px;
    font-size: 12.5px; font-weight: 700; color: #475569; cursor: pointer;
}
.msgr-btn-p { background: #6d28d9; border-color: #6d28d9; color: #fff; }
.msgr-btn:disabled { opacity: .55; cursor: not-allowed; }

/* 💬 메신저 — 외부 초대 모달 결과 */
.msgr-invres { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--bd, #e2e8f0); }
.msgr-invres .msgr-link {
    font-size: var(--m-meta); color: #4338ca; background: #eef2ff; border: 1px solid #e0e7ff;
    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-invbtns .msgr-btn { flex: 1 1 0; text-align: center; }
.msgr-invite:disabled { 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 #e2e8f0; background: #fff;
    border-radius: var(--m-r2); padding: 8px 11px; font-size: var(--m-meta); color: #334155;
    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: #0f172a;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msgr-filedl { flex: 0 0 auto; font-size: var(--m-meta); color: #6d28d9; }
.msgr-file:hover { background: #f8fafc; border-color: #c7d2fe; }
.msgr-file:disabled { opacity: .5; cursor: wait; }
.msgr-filesz { font-size: var(--m-badge); color: #94a3b8; 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: #64748b;
}
.msgr-tempdot { width: 7px; height: 7px; border-radius: 999px; background: #94a3b8; flex: 0 0 auto; }
.msgr-tempdot.is-hot { background: #f97316; }
.msgr-tempdot.is-cold { background: #93c5fd; }
.msgr-templabel { font-weight: 600; color: #334155; }
.msgr-tempmeta { color: #94a3b8; }

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

/* 💬 메신저 — 댓글 스레드 · 챙겨야 할 메시지 · 시스템 안내 */
.msgr-sys { display: flex; justify-content: center; margin: 8px 0; }
.msgr-sys span {
    font-size: 11px; color: #6d28d9; background: #f5f3ff; border: 1px solid #ddd6fe;
    border-radius: 12px; padding: 3px 12px; line-height: 1.5; text-align: center;
}
.msgr-threadcaret { font-size: 9px; color: #94a3b8; margin-left: 2px; }
.msgr-threadbox {
    margin: 4px 0 8px 43px; padding: 6px 10px; border-left: 2px solid #ddd6fe;
    background: #fafaff; border-radius: 0 8px 8px 0;
}
.msgr-threadadd {
    border: 0; background: transparent; color: #6d28d9; font-size: 11.5px;
    font-weight: 700; padding: 4px 0; cursor: pointer;
}
/* 메시지 액션 — **떠 있는 형태**라 평소엔 높이를 예약하지 않는다(대화 간격 유지).
   메시지 우상단에 hover 시 나타난다. 터치기기는 상시. */
.msgr-msgbody { position: relative; }
.msgr-msgact {
    position: absolute; top: -10px; right: 0; z-index: 5;
    display: flex; gap: 3px; background: #fff; border: 1px solid #e2e8f0; border-radius: 8px;
    padding: 2px; box-shadow: 0 3px 10px rgba(15, 23, 42, .1);
    opacity: 0; pointer-events: none; transition: opacity .12s;
}
.msgr-msg:hover .msgr-msgact { opacity: 1; pointer-events: auto; }
@media (hover: none) { .msgr-msgact { opacity: 1; pointer-events: auto; } }
.msgr-actbtn {
    border: 1px solid #e2e8f0; background: #fff; border-radius: 6px; padding: 1px 7px;
    font-size: var(--m-badge); color: #64748b; cursor: pointer;
}
.msgr-actbtn:hover { background: #f1f5f9; }
.msgr-actbtn.is-on { background: #fef3c7; border-color: #fde68a; color: #92400e; font-weight: 700; }
/* 답글 바 */
.msgr-replybar {
    display: flex; align-items: center; gap: 6px; padding: 5px 9px; margin-bottom: 6px;
    background: #f5f3ff; border: 1px solid #ddd6fe; border-radius: 8px;
}
.msgr-replyic { font-size: 12px; flex: 0 0 auto; }
.msgr-replytxt {
    flex: 1 1 auto; min-width: 0; font-size: 11.5px; color: #4338ca;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msgr-replyx { border: 0; background: transparent; color: #6d28d9; font-size: 12px; cursor: pointer; flex: 0 0 auto; }
/* 챙겨야 할 메시지 */
.msgr-carecnt { margin-left: auto; font-size: var(--m-badge); color: #94a3b8; font-weight: 700; }
.msgr-cardhead { display: flex; align-items: center; }
.msgr-bmitem { background: #f8fafc; border-radius: 8px; padding: 7px 9px; margin-bottom: 5px; }
.msgr-bmitem.is-done { opacity: .55; }
.msgr-bmitem.is-done .msgr-bmtext { text-decoration: line-through; }
.msgr-bmdone {
    margin-top: 5px; border: 1px solid #e2e8f0; background: #fff; border-radius: 6px;
    padding: 2px 8px; font-size: var(--m-badge); font-weight: 700; color: #047857; cursor: pointer;
}

/* 💬 메신저 — 내 반응 강조 */
.msgr-reaction.is-mine { background: #ddd6fe; border-color: #a78bfa; }
.msgr-reaction.is-mine .msgr-reactn { color: #5b21b6; }

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

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

/* 메시지 밀도 */


/* 이모지 팔레트 */
.msgr-emojipop {
    position: fixed; z-index: 720; display: flex; gap: 2px;
    background: #fff; border: 1px solid #e2e8f0; border-radius: 8px;
    padding: 5px 7px; box-shadow: 0 8px 24px rgba(15,23,42,.16);
}
.msgr-emojibtn {
    border: 0; background: transparent; font-size: 17px; line-height: 1;
    padding: 3px 4px; border-radius: 6px; cursor: pointer;
}
.msgr-emojibtn:hover { background: #f1f5f9; }

/* ═══ 💬 메신저 — 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: 5px; margin-bottom: 1px; line-height: 1.35; }
.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-reaction { padding: 0 6px; font-size: 11px; line-height: 1.65; }
.msgr-reactn { font-size: var(--m-badge); }

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

/* 💬 메신저 — ⋮ 방 관리 메뉴 */
.msgr-menu {
    position: fixed; z-index: 720; min-width: 190px;
    background: #fff; border: 1px solid #e2e8f0; border-radius: 8px;
    padding: 5px; box-shadow: 0 8px 24px rgba(15,23,42,.16);
}
.msgr-menuitem {
    display: block; width: 100%; text-align: left; border: 0; background: transparent;
    border-radius: 8px; padding: 7px 10px; font-size: 12.5px; color: #334155; cursor: pointer;
}
.msgr-menuitem:hover { background: #f1f5f9; }
.msgr-menuitem.is-danger { color: #dc2626; }
.msgr-menuitem.is-danger:hover { background: #fef2f2; }
.msgr-menunote { padding: 6px 10px; font-size: var(--m-badge); color: #94a3b8; line-height: 1.5; }

/* 💬 메신저 — 🌡 대화방 온도 */
.msgr-tempchart {
    display: flex; align-items: flex-end; gap: 2px; height: 54px;
    padding: 4px 2px 0; border-bottom: 1px solid #f1f5f9;
}
.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, #fb923c, #f59e0b);
}
.msgr-tempbar.is-empty { background: #e2e8f0; }
.msgr-tempbar.is-today { background: linear-gradient(180deg, #a78bfa, #7c3aed); }
.msgr-tempaxis { display: flex; justify-content: space-between; font-size: var(--m-badge); color: #94a3b8; 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: #475569; background: #f1f5f9;
    border-radius: 8px; padding: 1px 8px;
}
.msgr-tempdeg.is-hot { color: #c2410c; background: #ffedd5; }
.msgr-tempdeg.is-cold { color: #0369a1; background: #e0f2fe; }
.msgr-tempnote { font-size: var(--m-badge); color: #cbd5e1; margin-top: 6px; line-height: 1.5; }
.msgr-level { font-size: var(--m-badge); }

/* 💬 메신저 — 🗂 여러 대화방 탭 */
.msgr-tabstrip { display: flex; align-items: center; gap: 3px; overflow-x: auto; min-width: 0; flex: 1 1 auto; }
.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: #94a3b8; 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: #e2e8f0; color: #334155; }
@media (hover: none) { .msgr-tabx { opacity: .6; } }
.msgr-tabdotunread { font-size: 7px; color: #ef4444; margin-left: 1px; }

/* 💬 메신저 — 📌 인용 블록 · 메시지로 이동 */
.msgr-syswrap { margin: 8px 0; }
/* ★ 인용 블록은 **왼쪽 정렬**(2026-08-06 사장님) — 안내 알약은 가운데지만 인용은
   실제 대화 내용이라 말풍선과 같은 줄에서 시작해야 눈이 따라간다.
   들여쓰기 43px 은 아바타 폭 + 간격(.msgr-threadbox 와 같은 값)이라 본문선에 맞는다. */
.msgr-quote {
    max-width: 460px; margin: 5px 0 0 43px; padding: 7px 11px;
    border-left: 3px solid #c4b5fd; background: #faf5ff; border-radius: 0 8px 8px 0;
}
@media (max-width: 768px) { .msgr-quote { margin-left: 12px; } }
.msgr-quotehead { display: flex; align-items: center; gap: 5px; }
.msgr-quoteby { font-size: 11px; font-weight: 800; color: #6d28d9; }
.msgr-quotetext { font-size: 11.5px; color: #475569; line-height: 1.5; margin-top: 2px; }
.msgr-quotego {
    margin-top: 4px; border: 0; background: transparent; padding: 0;
    font-size: 11px; font-weight: 700; color: #6d28d9; cursor: pointer;
}
.msgr-quotego:hover { text-decoration: underline; }
.msgr-bmtext.is-link { cursor: pointer; }
.msgr-bmtext.is-link:hover { color: #6d28d9; text-decoration: underline; }

/* 📍 이동 대상 하이라이트 — 잠깐 번쩍이고 사라진다 */
.msgr-msg.msgr-hl { background: #fef9c3; 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 #e2e8f0; }
.msgr-linkwrap .msgr-fi { margin-top: 6px; }

/* 💬 메신저 — 📌 고정 배너 (대화 스크롤 맨 위 sticky) */
.msgr-pinbar {
    position: sticky; top: 0; z-index: 5;
    display: flex; align-items: center; gap: 4px;
    margin: 0 12px 6px; padding: 7px 10px;
    background: #fffbeb; border: 1px solid #fde68a; border-radius: 8px;
    box-shadow: 0 2px 8px rgba(15, 23, 42, .06);
}
.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: #78350f; 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: #b45309; font-size: 12px; padding: 2px 5px; border-radius: 6px;
}
.msgr-pinx:hover { background: #fef3c7; }

/* 💬 메신저 — 목록 안읽음 필터 칩 · 방 행 아이콘 */
.msgr-ufilter {
    flex: none; width: 30px; border: 1px solid #e2e8f0; border-radius: 8px;
    background: #fff; color: #cbd5e1; font-size: 11px; cursor: pointer;
}
.msgr-ufilter:hover { background: #f8fafc; }
.msgr-ufilter.is-on { color: #2563eb; border-color: #bfdbfe; background: #eff6ff; }
.msgr-room-pin { flex: none; font-size: 10px; }
.msgr-room-mute { flex: none; font-size: 10px; opacity: .55; }

/* 💬 메신저 — 관리 버튼 켜짐 상태 · 초대 첫 메시지 textarea */
.msgr-mngbtn.is-on { background: #eff6ff; border-color: #bfdbfe; color: #1d4ed8; }
.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: #f0f9ff; border: 1px solid #bae6fd; border-radius: 999px;
    color: #0369a1; font-size: 11px; font-weight: 600; cursor: pointer;
    width: fit-content;
}
.msgr-datechip:hover { background: #e0f2fe; }

/* 💬 메신저 — ✏️ 메시지 편집 */
.msgr-edited { font-size: var(--m-badge); color: #94a3b8; margin-top: 2px; }
.msgr-editta {
    width: 100%; min-height: 56px; resize: vertical;
    border: 1px solid #bfdbfe; border-radius: 8px; padding: 8px 10px;
    font: inherit; font-size: 13px; outline: none; background: #fff;
}
.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: 64px;
    background: #f8fafc; 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: #0f172a; }
.msgr-clihint { font-size: 11.5px; color: #94a3b8; margin: 6px 0 14px; }
.msgr-clitbl { border: 1px solid #e2e8f0; border-radius: 12px; background: #fff; 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: #fff; border: none; border-bottom: 1px solid #f1f5f9;
    cursor: pointer; font-size: 12.5px; color: #334155; align-items: center;
}
.msgr-clirow:hover { background: #f8fafc; }
.msgr-clirow.is-active { background: #eef2ff; }
.msgr-clirow.is-head {
    cursor: default; font-size: 11px; font-weight: 700; color: #94a3b8;
    background: #f8fafc; border-bottom: 1px solid #e2e8f0;
}
.msgr-clicell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-clicell.c0 { display: flex; align-items: center; gap: 7px; font-weight: 700; color: #0f172a; }
.msgr-clicell.c3 { text-align: center; }
.msgr-clicell.c4 { color: #94a3b8; }
.msgr-cliprof {
    width: 340px; flex: none; border-left: 1px solid #e2e8f0; background: #fff;
    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: #0f172a; }
.msgr-clip-sec { margin-top: 14px; padding-top: 12px; border-top: 1px solid #f1f5f9; }
.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: #334155; }
.msgr-clip-secsub { font-size: var(--m-badge); color: #94a3b8; }
.msgr-clip-memo { font-size: 12.5px; color: #475569; white-space: pre-wrap; line-height: 1.55; }
.msgr-clip-memo.is-empty { color: #cbd5e1; }
.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: #94a3b8; 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 #e2e8f0; border-radius: 999px;
    background: #f8fafc; font-size: 11.5px; color: #334155; cursor: pointer;
}
.msgr-clip-achip:hover { background: #fef2f2; border-color: #fecaca; }
.msgr-clip-ax { font-size: 9px; color: #94a3b8; }
.msgr-clip-aempty { font-size: 11.5px; color: #cbd5e1; }
.msgr-clip-aadd {
    width: 24px; height: 24px; border: 1px dashed #cbd5e1; border-radius: 999px;
    background: #fff; color: #64748b; font-size: 12px; cursor: pointer;
}
.msgr-clip-aadd:hover { background: #f8fafc; }
.msgr-clip-room {
    display: block; width: 100%; text-align: left; padding: 9px 10px; margin-top: 6px;
    border: 1px solid #f1f5f9; border-radius: 8px; background: #fff; cursor: pointer;
}
.msgr-clip-room:hover { background: #f8fafc; }
.msgr-clip-roomname { display: block; font-size: 12.5px; font-weight: 700; color: #0f172a; }
.msgr-clip-roomat { display: block; font-size: var(--m-badge); color: #94a3b8; margin-top: 2px; }

/* 💬 메신저 — 🏠 홈 칩 + 🔖 챙길 메시지 목록 + 그룹 접기 */
/* ⚖️ 위아래 여백을 맞춘다 (2026-08-08 사장님 "팀대화방 칸 위에 선이 붙어있잖아").
   종전 `0 10px 8px` — **위가 0** 이라 브랜드 줄의 밑선이 칩에 그대로 닿고 아래만 떠 있었다.
   같은 줄 간격이면 선이 «칸을 나누는 선»으로 읽히고, 붙으면 «칸에 달린 테두리»로 보인다. */
.msgr-homechips { padding: 8px 10px; border-bottom: 1px solid #f1f5f9; }
.msgr-homechiprow { display: flex; gap: 6px; }
.msgr-homechip {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 5px 12px; border: 1px solid #e2e8f0; border-radius: 999px;
    background: #fff; font-size: 12px; font-weight: 600; color: #64748b; cursor: pointer;
}
.msgr-homechip.is-on { background: #eef2ff; border-color: #c7d2fe; color: #3730a3; }
.msgr-homechipn {
    min-width: 17px; height: 17px; padding: 0 5px; border-radius: 999px;
    background: #3b82f6; color: #fff; 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: #fff; border: none; border-bottom: 1px solid #f1f5f9; cursor: pointer;
}
.msgr-carerow:hover { background: #f8fafc; }
.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: #0f172a; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-carerow-txt { font-size: 11.5px; color: #64748b; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-acccaret { margin-left: auto; font-size: 10px; color: #cbd5e1; }
.msgr-acchead { cursor: pointer; }
.msgr-accunread {
    min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
    background: #ef4444; color: #fff; font-size: var(--m-badge); font-weight: 800;
    display: inline-flex; align-items: center; justify-content: center;
}

/* 모바일 — 거래처 패널은 세로 스택, 프로필이 아래로 */
@media (max-width: 900px) {
    .msgr-root.is-clients .msgr-clients { left: 0; }
    .msgr-cliwrap { flex-direction: column; }
    .msgr-cliprof { width: auto; border-left: none; border-top: 1px solid #e2e8f0; }
}

/* 🪟 창분리(팝업) — 메신저 외 모든 뷰를 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 #e2e8f0; border-radius: 8px; background: #fff;
    font-size: 13px; cursor: pointer;
}
.msgr-notibtn:hover { background: #f8fafc; }
.msgr-notibtn.is-on { background: #eef2ff; border-color: #c7d2fe; }
.msgr-notibadge {
    position: absolute; top: -5px; right: -5px;
    min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
    background: #ef4444; color: #fff; font-size: var(--m-badge); font-weight: 800;
    display: inline-flex; align-items: center; justify-content: center;
    border: 2px solid #fff;
}
.msgr-invcard { padding: 12px; border-bottom: 1px solid #f1f5f9; background: #fff; }
.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 #f1f5f9; background: #fff; }
.msgr-notimain {
    flex: 1; min-width: 0; text-align: left; padding: 10px 12px;
    background: none; border: none; cursor: pointer;
}
.msgr-notimain:hover { background: #f8fafc; }
.msgr-notiread {
    flex: none; align-self: center; margin-right: 10px;
    padding: 4px 10px; border: 1px solid #e2e8f0; border-radius: 999px;
    background: #fff; font-size: 11px; color: #64748b; cursor: pointer;
}
.msgr-notiread:hover { background: #eff6ff; border-color: #bfdbfe; color: #1d4ed8; }
.msgr-notiall {
    display: block; width: calc(100% - 20px); margin: 10px;
    padding: 7px; border: 1px dashed #cbd5e1; border-radius: 8px;
    background: #f8fafc; font-size: 12px; color: #475569; cursor: pointer;
}
.msgr-notiall:hover { background: #eff6ff; }

/* 🪟 창분리 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: #f1f5f9;
}
/* ⚠ 목업 배너(.msgr-phase)를 **숨기지 않는다** — 2026-08-06 실사고: 전용 창이 목업으로
   고정됐는데 배너까지 가려져 있어 직원들이 가짜 대화를 진짜로 봤다. 자리를 조금 차지해도
   «지금 보는 게 실데이터가 아니다»는 사실이 화면에 남아 있어야 한다. */
body.msgr-popout .msgr-phase { font-size: 12px; padding: 6px 12px; }

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

/* 💬 메신저 — ⌨️ 입력 중 (컴포저 바로 위, 대화 재렌더와 분리) */
.msgr-typing {
    display: flex; align-items: center; gap: 6px;
    padding: 4px 16px; font-size: 11.5px; color: #64748b;
    border-top: 1px solid #f8fafc; background: #fff;
}
.msgr-typedots { color: #6366f1; letter-spacing: 1px; animation: msgrTypeBlink 1.2s ease-in-out infinite; }
@keyframes msgrTypeBlink { 0%, 100% { 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 #e2e8f0; border-radius: 999px;
    background: #fff; font-size: var(--m-badge); color: #475569; cursor: pointer;
}
.msgr-bmdue:hover { background: #f8fafc; }
.msgr-bmdue.is-empty { border-style: dashed; color: #94a3b8; }
.msgr-bmdue.is-over { background: #fef2f2; border-color: #fecaca; color: #b91c1c; font-weight: 700; }
.msgr-bmdueinput {
    border: 1px solid #bfdbfe; border-radius: 8px; padding: 2px 6px;
    font: inherit; font-size: 11px; outline: none;
}
.msgr-overdue {
    padding: 1px 7px; border-radius: 999px;
    background: #fef2f2; color: #b91c1c; 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 #e2e8f0; border-radius: 999px;
    background: #f8fafc; font-size: 11px; color: #334155; max-width: 100%;
}
.msgr-invfilechip > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-invfilex { border: 0; background: none; color: #94a3b8; font-size: 10px; cursor: pointer; padding: 0; }
.msgr-invfilex:hover { color: #b91c1c; }

/* 💬 메신저 — 🤖 봇 보고서 카드 (자금일보·다이제스트)
   ★ 가운데 알약이 아니라 좌측 카드다: 여러 줄 보고서라 줄바꿈이 살아야 하고,
     가로로 늘어나면 읽는 눈이 갈 곳을 잃는다. */
.msgr-botcard {
    max-width: 440px; margin: 10px 0 10px 43px;
    border: 1px solid #e2e8f0; border-left: 3px solid #6366f1;
    border-radius: 0 12px 12px 0; background: #fff; overflow: hidden;
}
.msgr-bothead {
    display: flex; align-items: center; gap: 7px;
    padding: 9px 12px 7px; border-bottom: 1px solid #f8fafc;
}
.msgr-botbadge {
    flex: none; padding: 1px 6px; border-radius: 6px;
    background: #eef2ff; color: #4338ca; 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: #0f172a;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msgr-botat { flex: none; font-size: var(--m-badge); color: #cbd5e1; }
.msgr-botbody {
    padding: 9px 12px 11px; font-size: 12.5px; color: #334155; 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: #64748b; margin-bottom: 5px; }
.msgr-caremsg .msgr-quote { margin-left: 0; max-width: 460px; }
.msgr-quotehead { display: flex; align-items: center; gap: 6px; }
.msgr-av-xs { width: 18px; height: 18px; font-size: 8px; border-radius: 6px; }
.msgr-quotefoot {
    display: flex; align-items: center; gap: 8px; margin-top: 7px;
    padding-top: 6px; border-top: 1px solid #f1f5f9;
    font-size: var(--m-badge); color: #94a3b8;
}
.msgr-quotefoot .msgr-quotego { margin: 0 0 0 auto; }
.msgr-quotedone { color: #059669; font-weight: 700; }
.msgr-quotecancel { color: #cbd5e1; }
.msgr-quotedue { color: #64748b; }
.msgr-quotedue.is-over { color: #b91c1c; font-weight: 700; }

/* 💬 메신저 — 👥 팀 관리 패널 */
.msgr-teamrow {
    display: flex; align-items: center; gap: 11px;
    padding: 11px 14px; background: #fff;
    border-bottom: 1px solid #f1f5f9;
}
.msgr-teamrow:last-child { border-bottom: 0; }
.msgr-teamrow:hover { background: #f8fafc; }
.msgr-teaminfo { flex: 1; min-width: 0; }
.msgr-teamname {
    display: flex; align-items: center; gap: 6px;
    font-size: 13px; font-weight: 700; color: #0f172a;
}
.msgr-teamme {
    padding: 1px 6px; border-radius: 999px;
    background: #eef2ff; color: #4338ca; font-size: var(--m-badge); font-weight: 800;
}
.msgr-teamrole { font-size: 11px; color: #94a3b8; margin-top: 1px; }
.msgr-av-sm { width: 34px; height: 34px; font-size: 12px; }
.msgr-clip-dbval { font-size: 12px; color: #334155; word-break: break-all; }
.msgr-phonechip { background: #f0fdf4; border-color: #bbf7d0; color: #15803d; }
.msgr-phonechip:hover { background: #dcfce7; }

/* ═══════════════════════════════════════════════════════════
   💬 메신저 — 시각 폴리시 (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: 12.5px; }
.msgr-newbtn, .msgr-notibtn, .msgr-ufilter { height: 32px; }
.msgr-newbtn { border-radius: 8px; }

/* ② 고정 메뉴 — 켜짐 상태를 실제로 보여준다(죽은 항목을 없앤 자리) */
.msgr-fixitem.is-active { background: #eef2ff; color: #4338ca; 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: #4f46e5; border-radius: 0 999px 999px 0;
}

/* ④ 말풍선 — 행 간격은 12px 하나로 통일(그룹은 3px) */
.msgr-msg { margin-bottom: 12px; }
.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: #f1f5f9; }
.msgr-cardhead { font-size: 12px; }

/* ⑦ 컴포저 — 입력 영역과 도구줄 사이 여백 정리 */
.msgr-composer { padding: 10px 14px 12px; }
.msgr-cfoot { margin-top: 8px; }

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

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

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

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

@media (max-width: 768px) {
    /* ① 헤더 — 검색창 대신 **로고 + 브랜드 + 아이콘**. 검색은 🔍 로 펼친다.
       ⚠ 로고는 `.msgr-brand` 와 **짝으로 켜고 끈다** — 위 :3545 가 둘 다 숨기므로
         여기서 하나만 켜면 이름만 나오고 로고는 영영 안 보인다(실측으로 잡음). */
    .msgr-brandlogo { display: block; }
    .msgr-searchwrap.is-search-open .msgr-brandlogo { display: none; }   /* 검색 펼치면 자리 양보 */
    .msgr-brand {
        display: block; flex: 1; min-width: 0;
        font-size: 16px; font-weight: 800; color: #0f172a;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .msgr-searchtog {
        display: inline-flex; align-items: center; justify-content: center;
        width: 34px; height: 34px; flex: none;
        border: 0; background: none; font-size: 15px; cursor: pointer; border-radius: 8px;
    }
    .msgr-searchtog:active { background: #f1f5f9; }
    .msgr-searchwrap { padding: 10px 12px; gap: 2px; }
    .msgr-search { display: none; }
    .msgr-searchwrap.is-search-open .msgr-brand { display: none; }
    .msgr-searchwrap.is-search-open .msgr-search { display: block; flex: 1; }
    .msgr-notibtn, .msgr-newbtn { width: 34px; height: 34px; border: 0; background: none; }
    /* ● 안읽음 필터는 모바일에서 숨긴다 — 🔔(안 읽은 대화 모아보기)와 하는 일이 겹치는데
       아이콘만으로는 구분이 안 돼 '무슨 버튼인지 모를 회색 점'이 된다 */
    .msgr-ufilter { display: none; }
    .msgr-newbtn { background: #4f46e5; color: #fff; border-radius: 8px; }
    .msgr-notibtn:active, .msgr-ufilter:active { background: #f1f5f9; }

    /* ② 터치 타깃 — 행을 키우고 위계를 벌린다 */
    .msgr-room { padding: 12px 14px; }
    .msgr-room-top { gap: 6px; }
    .msgr-room-bot { margin-top: 4px; }
    .msgr-fixitem { padding: 11px 14px; font-size: 13px; }

    /* ③ 활성 방 표시는 **모바일에 필요 없다** — 누르면 대화 화면으로 넘어가므로
       목록에 남은 선택 상태는 의미가 없고, 통짜 보라색은 미읽음 톤까지 덮는다.
       🚨 배경을 지웠으면 **보라 배경용 글자색을 전부** 되돌려야 한다(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: #0f172a; }
    .msgr-room.is-active .msgr-room-last,
    .msgr-room.is-active.is-unread .msgr-room-last { color: #64748b; }
    .msgr-room.is-active .msgr-room-at,
    .msgr-room.is-active.is-unread .msgr-room-at { color: #94a3b8; }
    .msgr-room.is-active .msgr-room-by,
    .msgr-room.is-active.is-unread .msgr-room-by { color: #94a3b8; }
    .msgr-room.is-active .msgr-room-cnt { color: #94a3b8; }
    .msgr-room.is-active .msgr-unread { color: #6d28d9; }

    /* ④ 홈 칩 — 손가락으로 누를 크기 */
    .msgr-homechip { padding: 7px 14px; font-size: 12.5px; }
}

/* ═══════════════════════════════════════════════════════════
   🧩 메신저를 **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 #e2e8f0; background: #fff; }
.msgr-main { background: #fff; }
.msgr-side { background: #fff; border-left: 1px solid #e2e8f0; }

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

    /* 📱 액션 바는 **띄우지 않는다** — 종전엔 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: rgba(15, 23, 42, .22);
    display: flex; align-items: flex-end;
}
.msgr-sheet {
    /* 🫧 떠 있는 면 — 딤 오버레이 위 */
    width: 100%; background: var(--m-glass-bg, #fff);
    -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 rgba(15, 23, 42, .2);
}
.msgr-sheetgrab { width: 36px; height: 4px; border-radius: 999px; background: #e2e8f0; margin: 4px auto 10px; }
.msgr-sheetquote {
    font-size: 12px; color: #94a3b8; padding: 0 6px 10px; margin-bottom: 4px;
    border-bottom: 1px solid #f1f5f9;
    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: #0f172a; border-radius: 8px;
}
.msgr-sheetitem:active { background: #f1f5f9; }
.msgr-sheetitem.is-danger { color: #b91c1c; }
.msgr-sheetcancel {
    display: block; width: 100%; margin-top: 6px; padding: 13px;
    border: 0; border-radius: 12px; background: #f1f5f9;
    font-size: 15px; font-weight: 700; color: #475569;
}

/* 📎 파일 칩 — 긴 파일명이 줄바꿈되며 글자가 겹쳐 보이던 것 수리 */
/* (파일 칩 → 카드 구조로 교체됨 — 이름 말줄임은 .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: #eef2ff; color: #4338ca; font-weight: 700;
    border-radius: 6px; padding: 0 3px;
}
.msgr-msg.is-mine .msgr-mention { background: rgba(255,255,255,.22); color: #fff; }

/* 📱 대화 화면 헤더 — 지금 어느 방인지 상단에 (2026-08-06 사장님).
   데스크톱은 탭 줄이 그 역할이라 감춘다. */
.msgr-roomhead { display: none; }
@media (max-width: 768px) {
    .msgr-roomhead {
        display: flex; align-items: baseline; gap: 6px;
        flex: 1; min-width: 0; padding-left: 2px;
    }
    .msgr-roomheadname {
        font-size: 15px; font-weight: 800; color: #0f172a;
        flex: 1 1 auto; min-width: 0;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    /* 거래처명은 **양보한다** — 방 이름이 먼저 보여야 어느 방인지 안다 */
    .msgr-roomheadcli {
        font-size: 11px; color: #94a3b8; 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: 10px 12px; align-items: center; }
    /* 터치 히트 영역 최소 40px — 아이콘만 22px 로 키우고 여백으로 면적을 만든다 */
    .msgr-back { font-size: 22px; line-height: 1; min-width: 34px; height: 40px; margin-left: -6px; }

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

/* ══════════════════════════════════════════════════════════════
   🏷 브랜드 분기 — 같은 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; }
}

/* ══════════════════════════════════════════════════════════════
   📐 그리드 칸끼리 침범하던 것 (2026-08-07 사장님 스크린샷 — 마감일이 반복 칸을 침범)

   ★ **Chrome 에서는 재현되지 않는다.** 아이폰 사파리에서만 난다 —
     실측(402px 화면, iPhone 17 시뮬레이터):
       칸 167px  /  `<input type=date>` 실제 렌더폭 **193px**
       → 26px 이 칸 밖으로, 옆 셀렉트를 **14px 침범**
   🚨 **`width:100%` 도 `min-width:0` 도 듣지 않는다** — 사파리의 날짜 입력은 내부 필드
     때문에 193px 아래로 줄어들지 않는다(처음에 그 두 가지로 고치려다 수치가 1px 도 안
     바뀌는 것을 대조군으로 확인했다).
   → **칸을 넓혀 주는 수밖에 없다**: 좁은 화면에서 날짜가 든 2열 그리드는 1열로 떨군다.
     193×2 + gap ≈ 398px 이 필요해 뷰포트 ~460px 아래에서는 2열이 원리적으로 안 들어간다.
   ⚠ 날짜가 **없는** 2열 그리드는 건드리지 않는다 — 셀렉트·텍스트 입력은 잘 줄어든다.
   ══════════════════════════════════════════════════════════════ */
@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;
    }
}
/* 날짜·시간 입력이 자기 칸을 넘지 않게 (사파리에서는 193px 이 하한이라 위 규칙이 본체다) */
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; }

/* ══════════════════════════════════════════════════════════════════════
   📱 어니스트 메신저 — 상단 안전영역 (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);
    /* 🎨 이 패딩이 드러내는 색이 곧 «상태바 배경»이다. 어두워야 흰 시계가 읽힌다.
       남색을 고른 이유: 로그인 화면 배경과 같은 색이라 거기서는 이음매가 아예 없고,
       흰 대화 목록 위에서는 «앱이 가진 짙은 바»로 읽힌다(브라우저 잔해가 아니라). */
    background: #0f172a;
}
/* 📐 높이의 재계산 — 위에 패딩이 생긴 만큼 `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;
}
/* ⓘ `#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-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 #e2e8f0;
        border-radius: 12px 12px 0 0;   /* ⚠ 토큰 밖 값 금지 — 6·8·12·999 만(디자인 스케일 테스트) */
        /* 🫧 떠 있는 면 — fixed 라 대화가 이 밑으로 흐른다 */
        background: var(--m-glass-bg, #fff);
        -webkit-backdrop-filter: var(--m-glass); backdrop-filter: var(--m-glass);
        box-shadow: 0 -8px 32px rgba(15, 23, 42, .18);
        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: #f1f5f9; color: #475569; 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; }
}

/* 📱 컴포저에서 **빈 줄 접기** (2026-08-08) — 「전체/내부」가 도구 줄로 내려가면서
   `.msgr-tools` 에는 레일 스페이서만 남는다. 그 줄이 그대로 있으면 아무것도 없는데
   높이만 차지한다(사장님 "빡빡한 느낌"의 한 조각).
   ⚠ `:has` 없는 구형 브라우저에서는 종전대로 빈 줄이 남을 뿐 깨지지는 않는다. */
.msgr-tools:empty,
.msgr-tools:has(> .msgr-railspacer:only-child) { display: none; }
/* 도구 줄이 좁아졌으니 토글은 오른쪽 끝(➤ 앞)에 붙는다 */
.msgr-cfoot .msgr-seg { margin-left: auto; flex: 0 0 auto; }

/* ⚰️ 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 {
    position: sticky; top: 6px; z-index: 3;
    pointer-events: none;           /* 떠 있는 라벨이 그 아래 메시지의 클릭을 먹지 않게 */
    /* 🚨 **높이를 0 으로 만들어 띄운다** — 종전엔 sticky 만 걸었더니 라벨이 원래 자리를
       계속 차지한 채 떠올라 **메시지와 겹쳐** 보였다(하네스 실화면에서 「8월 5일」이
       말풍선 위에 얹혀 있었다). 자리를 비우고 라벨만 띄운다. */
    height: 0; margin: 14px 0 10px; overflow: visible;
}
.msgr-daysep span { transform: translateY(-50%); }
.msgr-daysep span {
    box-shadow: 0 1px 6px rgba(15, 23, 42, .10);
    border: 1px solid #e2e8f0;
    background: #fff;               /* 반투명이면 지나가는 글자가 비친다 */
}

/* 💬 답장 인용 카드 (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 #c4b5fd;
    background: #f8fafc; border-radius: 0 var(--m-r1) var(--m-r1) 0;
    font-size: var(--m-meta); cursor: pointer;
}
.msgr-quote:hover { background: #f1f5f9; }
.msgr-quotename { flex: 0 0 auto; font-weight: 800; color: #6d28d9; }
.msgr-quotetext { flex: 1 1 auto; min-width: 0; color: #64748b;
    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: #64748b;
}
.msgr-clisec.is-static { cursor: default; }
.msgr-clisec:hover:not(.is-static) { color: #0f172a; }
.msgr-clisec-car { font-size: 11px; color: #94a3b8; width: 11px; }   /* ⚠ 11px 미만 금지(디자인 스케일 테스트) — 10px 로 썼다가 걸렸다 */
