/* SFiT-Bank-Plan — SFiT-Bank(ledger) 디자인 언어 이식 (P0.14.0). 포인트 색만 teal. */
:root {
    --bg: #f5f6f8;
    --card: #ffffff;
    --border: #e2e5e9;
    --text: #1a1d23;
    --text-sub: #6b7280;
    --primary: #475569;
    --primary-hover: #334155;
    --accent: #0f766e;          /* SFiT-Bank 의 red 대신 teal */
    --accent-bg: #f0fdfa;
    --deposit: #059669;
    --withdrawal: #dc2626;
    --danger: #dc2626;
    --balance: #2e5a88;
    --radius: 6px;
    --brand: var(--accent);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
/* ⚠⚠ (사용자 신고 2026-08-29 "매입대금에 날짜 일괄변경 버튼이 여전히 두 개" — A 화면 실측으로 원인 확정)
   **`hidden` 속성이 이 앱의 여러 요소에서 조용히 안 먹고 있었다.** 브라우저 기본 스타일시트의
   `[hidden]{display:none}` 은 특정도 (0,0,1) 이라, `display` 를 지정한 **클래스 규칙 (0,1,0)** 에 진다.
   그래서 JS 가 `el.hidden = true` 로 껐는데도 화면엔 계속 보였다 — 기타(경비/투자)용 컨트롤 줄
   (pbRow_std)이 매입대금 화면에 남아 "버튼이 두 개" 로 보인 것이 그 증상이다.
   A 가 실행 중인 화면에서 `[hidden]` 이면서 computed display ≠ none 인 요소를 전수로 세어 보니
   **8건**이었다: pbRow_std · pbRow_payable · pbRow_hru · noteYearRow(.filter-row, flex) 와
   noteSumCashed · noteSumNotDue · noteSumNotReceived · noteOverdueWarn(.badge, block).
   개별 클래스마다 `[hidden]` 규칙을 덧붙이면 앞으로 새 클래스가 생길 때마다 같은 사고가 재발하므로
   **여기서 한 번에 못 박는다.** HTML 명세상 `hidden` 은 "이 요소는 아직/이제 관련이 없다" 라는 의미라
   어떤 display 규칙보다 우선해야 맞다.
   ⚠ 같은 함정을 직전 라운드에도 겪었다(그땐 인라인 style="display:flex" 가 이겼다) — 인라인까지
     이기려면 !important 가 필요하다. 요소를 "hidden 인데도 보이게" 하려는 의도적 코드는 이 저장소에
     없다(위 8건은 전부 버그였다). */
[hidden] { display: none !important; }
html { scrollbar-gutter: stable; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
       background: var(--bg); color: var(--text); line-height: 1.5; font-size: 13px; }

/* ── 헤더 (ledger 와 동일 구조: 로고 + 타이틀/서브) ── */
.header { background: var(--card); border-bottom: 1px solid var(--border);
          padding: 12px 32px; display: flex; align-items: center; justify-content: space-between; }
.header-brand { display: flex; align-items: center; gap: 10px; }
.header-logo { width: 36px; height: 36px; border-radius: 6px; object-fit: contain; flex-shrink: 0; }
.header-left { display: flex; flex-direction: column; gap: 1px; }
.header h1 { font-size: 22px; font-weight: 700; letter-spacing: -0.3px; line-height: 1.2; color: var(--accent); }
.header-sub { font-size: 11px; color: var(--text-sub); letter-spacing: -0.2px; }
.header-right { display: flex; gap: 10px; align-items: center; }
.user-chip { font-size: 12px; display: inline-flex; align-items: center; gap: 6px; }
.role-badge { font-size: 10.5px; background: var(--accent-bg); color: var(--accent);
              padding: 1px 8px; border-radius: 8px; border: 1px solid #ccfbf1; }

/* ── 탭 (ledger 언더라인 스타일) ── */
.tabs { margin: 12px 32px 0; display: flex; gap: 0; border-bottom: 1px solid var(--border); overflow-x: auto;
        padding-top: 4px; }
/* ── 상단 고정 래퍼 (사용자 지시 2026-09-16 "메뉴뿐 아니라 메뉴 윗부분 전체가 상단 고정되면 좋겠다") ──
   허브 앱바(.sf-appbar — shared/appbar.js 가 body 맨 앞에 주입, 7131 게이트웨이에서만 있다)·앱 헤더
   (.header)·탭 줄(.tabs)을 app.js setupTopFixed() 가 이 래퍼로 묶어 셋을 통째로 고정한다
   (V3.2.60 의 .tabs 단독 sticky 는 폐지 — 두 개가 겹치면 탭이 헤더 위로 올라붙는다).
   겹침 순서: 모달 오버레이(1000)·드롭 오버레이(9998/9999)는 이보다 위라 그대로 덮는다.
   배경은 탭 줄 뒤로 본문이 비치지 않게(앱바·헤더는 제 배경이 있다). 높이는 JS 가
   --top-fixed-h 로 알려준다(아래 앵커 여유). */
.top-fixed { position: sticky; top: 0; z-index: 100; background: var(--bg); }
@media print { .top-fixed { position: static; } }
.tab { padding: 8px 14px; font-size: 12.5px; font-weight: 500; color: var(--text-sub); cursor: pointer;
       background: none; border: 1px solid transparent; border-bottom: 2px solid transparent;
       margin-bottom: -1px; white-space: nowrap; transition: all 0.15s; user-select: none;
       border-radius: var(--radius) var(--radius) 0 0; }
.tab:hover { color: var(--text); background: #f8fafc; }
.tab.active { color: var(--accent); background: var(--card); border-color: var(--border);
              border-bottom-color: var(--card); font-weight: 700; }
.tab.tab-over { border-bottom-color: var(--accent); }

/* ── 카드 ── */
.panel { padding: 0 0 24px; }
.card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
        margin: 14px 32px; padding: 14px 18px; }
.card h2 { font-size: 14px; font-weight: 700; margin-bottom: 10px; }
.hint { font-weight: normal; font-size: 11px; color: var(--text-sub); }

/* ── 설정 패널 목차 + 카드 접기/펼치기 (범용 — 일반설정에 이번에 적용, A 지시 2026-08-25) ──
   카드 마크업 관례: <div class="card" id="식별자"> 의 <h2> 안에 <button class="rep-toggle card-toggle">
   (.rep-toggle 은 report 카테고리 펼치기에 이미 쓰던 클래스 재사용 — 새 스타일 체계 안 만듦). 접힘은
   .sc-collapsed 클래스 하나로만 처리 — DOM 은 그대로 둔다(검색·앵커 이동 유지, A 지시). */
.sc-toc { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 14px 32px 0; padding: 8px 14px;
          background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); font-size: 12px; }
.sc-toc-link { background: none; border: none; padding: 2px 0; font: inherit; color: var(--accent);
               cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.sc-toc-link:hover { color: var(--primary-hover); }
.card-toggle { font-weight: 700; }
/* 목차로 스크롤 이동 시 카드 상단 여유 — (2026-09-16 갱신) 이젠 페이지 레벨 sticky 바(.top-fixed:
   앱바+헤더+탭)가 있어 그 높이만큼 더 빼줘야 앵커가 바 밑에 숨지 않는다. 높이는 app.js
   setupTopFixed() 가 --top-fixed-h 로 심어준다(앱바 유무·반응형 줄바꿈에 따라 달라진다).
   표 안 sticky thead(.table-scroll thead th)는 그 표 내부 스크롤 기준이라 페이지 스크롤과 무관. */
.card[id] { scroll-margin-top: calc(var(--top-fixed-h, 0px) + 12px); }
/* ⚠ 화면(screen)에서만 접는다 — 인쇄는 이 규칙 자체가 없어(revert 로 되돌리지 않음, .form-row 의 flex 등
   다른 규칙과 충돌 위험 없음) 접힌 카드도 항상 전부 펼쳐진 채로 나온다(A 지시 — "인쇄 시엔 전부 펼쳐져야"). */
@media screen {
    .card.sc-collapsed > *:not(h2) { display: none; }
    /* (구획 단위 접기, 사용자 지시 2026-08-29 — 노무비 "개인별 명세") 카드 **안**의 한 구획을 접는 변형.
       래퍼 <div class="sc-sect" id="…"> + 머리글 <h3> 안에 같은 .rep-toggle.card-toggle 버튼(같은
       data-action="toggleSettingsCard"). 카드 규칙과 같은 이 @media screen 안에 두므로 인쇄에는 이
       규칙이 없어 접힌 구획도 전부 펼쳐진 채로 나온다(위 카드 규칙과 동일한 이유). */
    .sc-sect.sc-collapsed > *:not(h3) { display: none; }
}
@media print {
    .sc-toc { display: none; }   /* 목차는 인쇄에 의미 없음(페이지 이동 개념이 없다) */
}

/* ── 폼 · 필터 ── */
.form-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 10px;
            padding: 8px 10px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); }
/* 수정 클릭 시 폼 강조 (P0.15.4 — 폼이 표 상단이라 아래쪽 행 수정 시 안 보이던 문제) */
@keyframes formFlash { 0% { box-shadow: 0 0 0 0 rgba(15,118,110,0.5); } 100% { box-shadow: 0 0 0 8px rgba(15,118,110,0); } }
.form-flash { animation: formFlash 0.8s ease-out; border-color: var(--accent) !important; }
.form-row input[type=text], .form-row input[type=number], .form-row input[type=date],
.form-row input[type=month], .form-row select,
.filter-row input, .filter-row select {
    padding: 5px 8px; font-size: 12px; border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--card); color: var(--text); outline: none; }
.form-row input:focus, .filter-row input:focus { border-color: #64748b; }
.form-row input[type=number] { width: 130px; text-align: right; }
.chk { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; white-space: nowrap; }
.filter-row { display: flex; gap: 10px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; }
/* (A 지시, C — 2026-08-29 ②) 지급일 일괄 변경 컨트롤 줄의 표 이름표. 매입대금은 원화·외화 두 표에
   줄이 하나씩 붙어 "같은 버튼이 두 개" 로 보인다는 신고가 있었다 — 어느 표에 대한 줄인지 먼저 읽히게
   한다. 텍스트는 app.js _pbUi() 가 PAY_BULK_TABLES[k].title 로 채운다(빈 값이면 폭도 0). */
.pb-title { font-size: 12px; color: var(--text-sub); white-space: nowrap; }
.table-search { padding: 5px 10px; font-size: 12px; border: 1px solid var(--border);
                border-radius: var(--radius); min-width: 260px; outline: none; }
.table-search:focus { border-color: var(--accent); }

/* ── 버튼 (ledger 톤) ── */
.btn { padding: 6px 14px; border-radius: var(--radius); border: 1px solid var(--border);
       background: var(--card); color: var(--text); font-size: 12px; font-weight: 500;
       cursor: pointer; transition: all 0.15s; }
.btn:hover { background: var(--bg); }
.btn-primary { background: var(--primary); color: #fff; border-color: var(--primary); }
.btn-primary:hover { background: var(--primary-hover); }
.btn-sm { padding: 3px 8px; font-size: 11px; }
.btn-danger { color: var(--danger); }
/* 헤더 업로드 버튼 (ledger btn-upload 패턴) */
.btn-upload { background: var(--card); border: 1px solid var(--border); color: var(--text-sub);
              font-size: 12px; padding: 6px 12px; border-radius: var(--radius); cursor: pointer; transition: all 0.15s; }
.btn-upload:hover { background: var(--bg); color: var(--text); }
.upload-msg { font-size: 11px; padding: 4px 10px; border-radius: var(--radius); display: none; }
.upload-msg.success { display: inline-block; background: #ecfdf5; color: var(--deposit); }
.upload-msg.error { display: inline-block; background: #fef2f2; color: var(--withdrawal); }
.upload-msg.busy { display: inline-block; background: var(--accent-bg); color: var(--accent); }

/* ── 표 ── */
table.grid { width: 100%; border-collapse: collapse; font-size: 12px; background: var(--card); }
.grid th { background: #f8fafc; border: 1px solid var(--border); padding: 6px 8px; text-align: left;
           white-space: nowrap; font-weight: 600; color: var(--text-sub); }
.grid td { border: 1px solid var(--border); padding: 5px 8px; }
.grid tbody tr:hover { background: #fafbfc; }
.grid th.num, .grid td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.grid td.actions { white-space: nowrap; text-align: center; }
/* (A 지시, C — 2026-09-30) 수금계획 액션 칸 고정 슬롯 — 버튼이 없는 행은 .act-ph(투명 복제)가 같은 폭을 차지해
   ▲▼·수정·배분·삭제·진단이 세로로 한 줄에 선다. 칸 전체는 가운데 정렬(inline-flex 묶음). */
.act-slots { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.act-slots .act-mv { display: inline-flex; gap: 4px; }
.act-slots .act-ph { visibility: hidden; pointer-events: none; }
/* (A 지시, C — 2026-08-28 지급계획 일괄 날짜 변경) 행 선택 체크박스 열. 체크박스 하나만 들어가는 좁은
   열이라 기본 좌우 padding(8px)을 줄이고 가운데 정렬한다. ⚠ 열을 숨기는 데 display:none 을 쓰지
   않는다(셀을 빼면 뒤 칸이 앞 열 폭으로 밀리는 사고 이력) — 이 열은 항상 그려지고, 고를 수 없는 행은
   체크박스만 disabled 로 둔다. */
.grid th.sel, .grid td.sel { width: 34px; text-align: center; white-space: nowrap; padding-left: 4px; padding-right: 4px; }
.grid td.sel input[type="checkbox"] { margin: 0; cursor: pointer; }
.grid td.sel input[type="checkbox"]:disabled { cursor: not-allowed; opacity: .45; }
.grid tr.inactive { color: #94a3b8; }
/* (A 지시, C — 2026-09-09 미지급금 행 [수정]) 버튼을 누르면 그 행의 편집 칸으로 포커스가 옮겨가는데,
   행이 많은 표(미지급금 100여 행)에서는 커서만으로는 어느 행이 잡혔는지 안 보인다. 1.4초 뒤 JS 가
   클래스를 떼므로(payableEditRow) 상태가 남지 않는다. tr:hover 배경보다 진하게 잡아 겹쳐도 보인다.
   ⚠ 행 색을 인라인 style 로 쓰는 행(처리=자동이체 #eff6ff / 고정 #f8fafc)이 있어 td 배경으로 칠한다 —
   tr 배경은 인라인 스타일에 밀린다. */
.grid tr.row-flash > td { background: #fef9c3; transition: background .25s ease; }
.grid tr.row-warn { background: #fef2f2; }
.grid tr.row-warn td:first-child { border-left: 3px solid var(--danger); }
.grid select { padding: 2px 4px; font-size: 11px; border: 1px solid var(--border); border-radius: 4px; }

/* 실적 분류 규칙 표 (rcrTbody, 사용자 요청 2026-09-01 "규칙표에 토글도 넣어주고") — 꺼진 규칙은 회색으로
   눌러 두되 **숨기지 않는다**(꺼진 규칙도 목록에 계속 보여야 다시 켤 수 있다). 색만 바꾸므로 열 폭에
   영향이 없다(display 를 건드리는 규칙 없음). */
.grid tr.rule-off td { color: var(--text-sub); background: #f8fafc; }
.badge.rcr-off-badge { background: #fecaca; color: #991b1b; }
.rcr-memo { font-size: 11px; color: var(--text-sub); word-break: break-all; }

/* 근로자 은행계좌정보 마스터 — 한 근로자 = 한 줄 (A 지시 2026-08, 사용자 요청). 이 모달의 표에만 스코프
   (#workerCard) — 전역 .grid td 에 걸면 다른 표(적요·비고 등 긴 텍스트를 일부러 줄바꿈하는 곳)까지
   전부 영향받는다. text-overflow:ellipsis 로 자르지 않는다 — 사번·계좌구분 같은 값은 담당자가 읽어야
   한다(A 지시). 대신 index.html 의 <th style="width:..."> 폭 배분 + 모달 폭 확장(min(1450px,96vw))으로
   실제로 한 줄에 담기게 한다. */
#workerCard .grid td, #workerCard .grid th { white-space: nowrap; }

/* 배지 */
.badge { display: inline-block; padding: 1px 7px; border-radius: 8px; font-size: 10.5px; background: #e2e8f0; }
.badge.auto { background: #ddd6fe; }
.badge.pre { background: #fef3c7; }
.badge.rec { background: #ccfbf1; color: #0f766e; }
.badge.emp { background: #dbeafe; color: #1e40af; }

/* 인사비 연봉제/시급제 토글 (P0.19.0) */
.seg { display: inline-flex; gap: 0; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.seg-btn { border: none; background: #fff; padding: 4px 12px; font-size: 12px; cursor: pointer; color: var(--text, #334155); }
.seg-btn + .seg-btn { border-left: 1px solid var(--border); }
.seg-btn.active { background: var(--accent, #0d9488); color: #fff; }

/* 선급금 장부 — 거래처별 요약 카드 (A 지시 4차, C — 2026-09-04) */
.pp-sum-grid { display: flex; gap: 22px; flex-wrap: wrap; }
.pp-sum-item { display: flex; flex-direction: column; gap: 2px; min-width: 96px; }
.pp-sum-label { font-size: 11px; color: var(--text-sub); }
.pp-sum-value { font-size: 15px; font-weight: 700; }

/* 보고서 표 (P0.20.0) */
#repTable tr.rep-head td { background: #f1f5f9; font-weight: 600; color: #0f766e; }
#repTable tr.rep-sub td { background: #f8fafc; }
#repTable tr.rep-total td { background: #ecfdf5; border-top: 2px solid var(--accent, #0d9488); }
#repTable tr.rep-bal td { background: #fffbeb; font-weight: 600; }
.grid tr.rep-total td { background: #ecfdf5; font-weight: 600; }
.grid tr.grand-total td { background: #ecfdf5; font-weight: 600; border-top: 2px solid var(--accent, #0d9488); }
/* 말일 밀림 — 소계 행만 달별 연한 톤 구분 (P0.27.2) */
.grid tr.rep-sub.mgrp-a td { background: #dceaf6; }
.grid tr.rep-sub.mgrp-b td { background: #fbedd6; }
/* 전월미수 블록 — 소계 행만 톤 (개별 행은 흰색) (P0.61.0) */
.grid tr.rep-sub.mgrp-od td { background: #e9e2fb; }
/* 어음만기 블록 — 표 맨 아래로 재배치, 소계 행만 톤 (개별 행은 흰색, 기존 관행과 동일) */
.grid tr.rep-sub.mgrp-note td { background: #e5e7eb; }
/* 선급금 장부 — 전기이월 행 (엑셀 양식 재현, A 지시 2026-09-04) */
.grid tr.pp-carry td { background: #f8fafc; font-style: italic; color: #555; }

/* (A 지시, C — 헤더 고정 + 내부 스크롤, 사용자 원문 "상단에 항목을 보여주고 내부 스크롤이 되면
   좋겠네") 표를 감싸는 래퍼에만 적용 — 전역 .grid 스타일은 그대로 두고 이 래퍼 안에서만 sticky.
   같은 <table> 안에서 헤더만 sticky 로 고정하는 방식(표를 두 개로 쪼개지 않음, A 권고 그대로)이라
   열 폭·permute() 컬럼 순서가 어긋나지 않는다. ⚠ _attachColumnUX()(app.js) 가 th 에 인라인
   style.position='relative' 를 직접 찍어(폭조절 핸들 기준점) 외부 CSS 보다 우선하므로 여기서
   !important 로 덮어써야 sticky 가 실제로 먹는다 — position:sticky 도 absolute 자식의 containing
   block 이 되므로(CSS 스펙) 폭조절 핸들(.col-resize) 동작은 그대로 안 깨진다.
   높이는 고정값이 아니라 뷰포트 비율(vh)로 — 화면 크기가 달라도 잘리거나 빈 공간이 남지 않는다.
   ⚠ (매입대금/미지급금 라운드, A 지시 — 재사용, 새 클래스 금지) overflow-y 단일축이던 걸 overflow
   양축으로 넓혔다 — 미지급금(payableTbody, 12열)·매입대금 표는 기존에 별도 overflow-x:auto 래퍼가
   따로 있었는데, 이 래퍼로 통합해 가로 스크롤도 같이 처리한다(수금계획은 원래 가로로 안 넘쳐 시각
   변화 없음, 세로 sticky 동작도 축을 늘렸다고 안 깨짐 — sticky 는 가장 가까운 스크롤 조상 기준). */
.table-scroll { max-height: 68vh; overflow: auto; border: 1px solid var(--border); }
.table-scroll table.grid { margin: 0; }
.table-scroll table.grid thead th { position: sticky !important; top: 0; z-index: 3; }
/* 합계(총계) 행 하단 고정 — "맨 아래에 진짜 합계가 딱 하나"인 표에만 켠다(모디파이어 클래스
   table-scroll-total 로 opt-in, .table-scroll 자체(헤더 sticky)는 세 표 다 그대로 공유 재사용).
   ⚠ (매입대금/미지급금 라운드, A 지시 — 총계 하단고정 필요 여부 판단) 표마다 grand-total 클래스의
   쓰임이 다르다: 수금계획(receiptsTbody)·매입대금 원화(apKrwBody)는 표 맨 끝에 딱 1번, 진짜 "전체
   합계"로만 쓴다 — 하단 고정이 자연스럽다. 반면 미지급금(payableTbody)은 같은 grand-total 클래스를
   "계획 반영 N건" / "제외 N건" 두 개의 표 중간 구분행으로도 재사용한다(app.js:3452~3457) — 하단
   고정을 켜면 구분행 여러 개가 동시에 바닥에 눌러붙어 더 지저분해진다. 그래서 payableTbody 래퍼에는
   이 모디파이어를 안 붙인다(구조가 다르면 그대로 두는 쪽, A 지시 그대로) — 헤더 sticky 만 적용. */
.table-scroll.table-scroll-total table.grid tr.grand-total td { position: sticky; bottom: -1px; z-index: 2; }
/* (열 폭 연동 마무리/A 실측 2026-08-28) 미지급금·경비·세금 고정 항목 세 표는 같은 key(fixedItemColumns)로
   열 폭을 공유하는데, 그래도 화면에서 15px 씩 어긋났다. 원인은 폭 계산이 아니라 **세로 스크롤바**다 —
   미지급금은 93행이라 스크롤바가 생겨 내부 폭이 1786, 경비는 10행이라 안 생겨 1801 이었다. 표가
   width:100% 라 그 15px 이 11개 열에 비례 배분되며 전 열이 1~4px 씩 밀린다(폭 맵은 정상이었다).
   ⚠ scrollbar-gutter 를 .table-scroll 전체에 걸지 않는다 — 20여 개 표가 그 클래스를 공유해 전부
     15px 씩 좁아진다. 열 폭을 공유하는 이 세 표에만 건다. */
.table-scroll.fixed-item-scroll { scrollbar-gutter: stable; }
/* (3표 폭 정합 마무리/A 실측 2026-08-29) 인라인 지정 폭은 세 표가 이미 완전히 같은데도 **렌더 폭이
   달랐다.** 원인은 `table-layout: auto` 다 — auto 에서는 셀 내용의 min-content 가 지정 폭을 이긴다.
   담당자가 지급예정일을 106px 로 줄여 두면, 그 칸에 접힌 날짜 표기 + ✎ 버튼이 들어가는 경비 표는
   최소 188px 을 요구해 지정값을 무시하고 벌어지고(미지급금은 114px), 그 차이만큼 남은 폭이 다른
   열에 다르게 배분돼 11열이 통째로 어긋난다.
   ⇒ 이 세 표만 fixed 로 바꿔 지정 폭이 그대로 강제되게 한다. A 가 배포 전 화면에서 실측 확인:
      fixed 적용 시 두 표의 11열 폭이 완전히 동일해지고, **잘리는 셀은 0개**였다.
   ⚠ 성능 목적이 아니다 — 앞서 드래그 지연을 fixed 로 줄여 보려던 시도는 효과가 없었고(비용은 셀 안
     폼 컨트롤 558개였다, 그건 안내선 방식으로 따로 해결했다), 이건 순전히 **폭 정합** 목적이다.
   ⚠ `.table-scroll` 전체에 걸지 않는다 — 20여 개 표가 그 클래스를 공유한다. */
.fixed-item-scroll table.grid { table-layout: fixed; }
.fixed-item-scroll table.grid th,
.fixed-item-scroll table.grid td { overflow: hidden; }
/* (가운데 정렬, 사용자 지시 2026-08-29 — "각 셀의 내용을 가운데 정렬해줘") 고정 항목 표
   (payableExclTbody·recExpTbody)에만 건다 — 이 표들만 .fixed-item-scroll 을 달고 있어 범위가 정확히
   닫힌다(.grid td 전역에 걸면 20여 개 표가 전부 바뀐다).
   ⚠ (2026-09-10) 세 번째였던 노무비 "세금 반복항목" 표(recTaxTbody)는 없어졌다 — 규칙은 클래스 기준이라
   무변경(남은 두 표에 그대로 적용된다).
   ⚠ 금액 칸(.fx-amt)만 오른쪽 정렬을 유지한다 — 자릿수가 안 맞으면 금액 비교가 불가능해진다
   (이 저장소가 .grid td.num 으로 이미 그렇게 하고 있고, 사용자 요구의 취지는 "칸이 휑해 보인다"라
   숫자 정렬과 어긋나지 않는다).
   ⚠ 기존 .num 을 쓰지 않고 새 클래스(.fx-amt)를 둔 이유 — .grid td.num 에는 white-space:nowrap 이
   같이 걸려 있다. 이 칸에는 금액 input 뒤에 [⚠ 금액 미입력] 배지가 붙을 수 있어 nowrap 이면 한 줄로
   버티며 열을 밀어내, 방금 맞춰 놓은 3표 폭 연동(FIXED_ITEM_COL_WIDTHS '금액' 120px)이 깨진다.
   .fx-amt 는 정렬만 바꾸고 줄바꿈 규칙은 건드리지 않는다.
   ⚠ 선택자 특정도: 앞(0,2,2) < 뒤(0,3,2) — 순서가 아니라 특정도로 이긴다. */
.fixed-item-scroll table.grid th,
.fixed-item-scroll table.grid td { text-align: center; vertical-align: middle; }
.fixed-item-scroll table.grid th.fx-amt,
.fixed-item-scroll table.grid td.fx-amt { text-align: right; }
@media print {
    .table-scroll { max-height: none; overflow: visible; border: none; }
    .table-scroll table.grid thead th { position: static !important; }
    .table-scroll.table-scroll-total table.grid tr.grand-total td { position: static; }
}

/* 자금보고 — 카테고리 세부 펼치기 (P0.105.0). ledger 세부적요처럼 한 칸에 여러 줄. 기본 접힘. */
.rep-toggle { background: none; border: none; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; text-align: left; }
.rep-toggle:hover { color: var(--accent); }
.rep-toggle-mark { display: inline-block; width: 10px; color: var(--text-sub); }
/* 접힌 상태 대표 텍스트("○○상사 외 6건") — 표가 좁을 수 있어 말줄임, 전체는 title 로 */
.rep-lead { display: inline-block; max-width: 100%; vertical-align: bottom; white-space: normal;
            word-break: keep-all; overflow-wrap: anywhere; color: var(--text-sub); font-weight: 400; }
.grid td.rep-detail-cell { background: #fbfdfd; padding: 6px 10px 8px 26px; }
.rep-detail-line { display: flex; align-items: baseline; gap: 10px; padding: 1px 0; font-size: 11.5px; color: var(--text); }
.rep-detail-line .rd-date { width: 76px; flex-shrink: 0; color: var(--text-sub); }
.rep-detail-line .rd-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rep-detail-line .rd-amt { width: 110px; flex-shrink: 0; text-align: right; font-variant-numeric: tabular-nums; }
.rep-detail-line .rd-due { width: 150px; flex-shrink: 0; text-align: right; color: var(--text-sub); font-size: 11px; }
.rep-detail-more { margin-top: 4px; color: var(--text-sub); font-size: 11px; }
/* 계획/실적 내역 구분(P0.107.0) — 한 카테고리를 펼치면 두 구간을 소제목·구분선으로 나눈다 */
.rep-detail-sub { font-weight: 600; font-size: 11px; color: var(--text-sub); margin: 4px 0 2px; }
.rep-detail-cell .rep-detail-sub:first-child { margin-top: 0; }
.rep-detail-divider { border-top: 1px dashed var(--border); margin: 6px 0; }
/* 계좌간 내부이체 제외분(P0.108.0) — uncategorized_in(빨강 경고)과 달리 "정상적으로 빠진 것"이라 흐리게만 */
.grid td.rep-excluded { color: var(--text-sub); font-style: italic; }

/* 자금보고 본표(#repTable) — 화면 표 1200px 고정 + 실적/계획 동일 폭 (C 2026-09-03, 사용자 지시
   "자금보고에서 표 폭을 일반화면에서는 1200 으로 고정해서 맞춰 주고, HTML 다운 받을 때는 780").
   ⚠ 화면 1200 / 다운로드·PDF 780 은 **의도된 불일치**다 — 화면은 넓은 모니터에서 세부내역을 편하게
     보는 용도, 다운로드본은 A4 한 장(인쇄폭 717px)에 들어가야 하는 종이 문서라 요구가 다르다.
     다운로드 쪽 폭은 이 파일이 아니라 app.js REP_PRINT_CSS(780/752) 에 있다.
   ⚠ 이 표 하나에만 스코프를 건다(#repTable) — .grid 는 20여 개 표가 공유하므로 전역 규칙을 건드리지
     않는다. 인쇄본(REPORT_CSS/REP_PRINT_CSS)과도 완전히 별개다(그쪽은 app.js 상수, 이 파일을 타지 않는다).
   ⚠ table-layout:fixed 로 열 폭을 <colgroup>(index.html)에서 받는다 — 120+199+150+290+150+290 = 1199px.
     실적(150/290)과 계획(150/290)이 문자열 수준에서 같아 어긋날 수 없다(인쇄본 REP_COL_SUM 과 같은 관례).
   ⚠ 1199px 인 이유 — border-collapse 표는 바깥 테두리의 절반(0.5px×2)이 지정 폭 **밖에** 그려져 실측 폭이
     +1px 이 된다. DPR=1 크롬 실측 스윕(C 2026-09-03): 합 798 → 799.0 / 799 → 800.0 / 1198 → 1199.0 /
     **1199 → 1200.0** / 1200 → 1201.0. ⚠ 직전 라운드 주석의 "+2px" 은 과대 추정이라 798 로 둔 배포분이
     실제로는 799.0 이었다 — 이번에 1199 로 잡아 처음으로 실측이 정확히 1200.0 이 된다.
   ⚠ max-width:100% 는 그대로 둔다 — 카드 안쪽 가용폭(뷰포트 − 카드 margin 64 − padding 36 − 테두리 2)이
     1200 보다 좁은 화면(뷰포트 < 1302px)에서 표가 카드 밖으로 넘치는 것을 막는다. 그런 화면에서는 표가
     비례 축소돼 실측이 1200 미만이 되지만, 가로 스크롤·잘림보다 낫다(A 지시 "가로 넘침 0").
   ⚠ (폭 보존 드래그, C 2026-09-03 — 사용자 지시 "드래그할 땐 빈칸이 늘어나고 표는 800px 에 맞추어 세팅")
     직전 라운드엔 열을 넓히면 표가 같이 넓어졌다(실측 860px) — CSS2.1 상 표 폭 = max(지정 폭, 열 폭 합)
     이라 max-width 로는 못 막기 때문. 이제 **꼬리에 여백 열(.rep-gap, 7번째)** 을 두고 드래그 증감을 그
     열이 흡수한다 → 열 폭 합이 항상 1199 로 유지돼 표는 언제나 실측 1200px 이다. 기본 폭은 0px 이라 조절
     전에는 빈 열이 안 보이고, 열을 좁히면 그만큼 오른쪽에 빈 칸이 생긴다.
     계산·클램프는 app.js FIXED_WIDTH_TABLES('report@v4') 한 곳에만 있다(다른 표 28곳은 미등록 → 무변화).
   ⚠ 말줄임·nowrap 금지(사용자 기존 지시 "잘림 없이 줄바꿈으로") — 숫자 칸(td.num)만 nowrap 을 유지한다
     (천원 표기 최장 "4,478,268" ≈ 63px < 150-16 = 134px 라 안 넘친다). 머리행은 월간 라벨
     "(2026-08-01~2026-08-31)"(≈103px)이 150-16 = 134px 안에 한 줄로 들어가지만, 더 긴 라벨이 와도
     접히도록 .grid th 의 nowrap 해제는 그대로 둔다. */
#repTable { table-layout: fixed; width: 1199px; max-width: 100%; }
#repTable th, #repTable td { box-sizing: border-box; white-space: normal; word-break: keep-all; overflow-wrap: anywhere; }
#repTable td.num { white-space: nowrap; word-break: normal; }
/* 머리행 1단 — 실적/계획 그룹 묶음(빈 <th> 2개 + colspan=2 두 개, 합 6열). 현금출납장과 같이
   rowspan 을 안 쓴다 — 그래야 라벨 행(마지막 행)이 본문과 같은 6칸을 유지해 enhanceTable() 이 안 깨진다. */
#repTable thead tr.rep-grp th { text-align: center; background: #eef2f7; color: var(--text-sub); }
#repTable thead tr.rep-grp th:empty { background: #f8fafc; }
/* 여백 열(.rep-gap, 꼬리 7번째) — 드래그 증감을 흡수하는 빈 칸. 폭은 app.js 가 <col>·<th> 에 찍는다.
   ⚠ padding 을 0 으로 둔다 — .grid th/td 의 좌우 padding(8px)이 남아 있으면 폭 0px 을 지정해도 셀이
     16px 로 벌어져 "조절 전 화면이 직전 배포분과 동일" 이라는 전제가 깨진다(크롬 실측 확인).
   ⚠ 테두리·배경은 일반 셀 그대로 둔다 — 여백이 표 **밖**이 아니라 표 안의 빈 칸이라야 표 오른쪽 끝이
     항상 800px 자리에 남는다(사용자 표현 그대로 "빈칸"). 소계·합계 행의 배경색도 이 칸까지 이어진다.
   ⚠ 이 클래스는 #repTable 스코프 안에서만 쓴다 — 다른 표에는 .rep-gap 셀이 하나도 없다(전수 확인). */
#repTable .rep-gap { padding: 0; }
/* [ 단위 : 천원 ] — 표 **바깥** 오른쪽 상단(사용자 지시). 표와 같은 1200px 폭 상자 안에서
   왼쪽 안내문·오른쪽 단위를 양끝 정렬한다 — 표 오른쪽 끝과 정확히 맞는다(표 실측 폭과 같은 값이라야
   하므로 #repTable 을 바꿀 때 이 값도 같이 바꾼다). */
.rep-unit-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px;
                width: 1200px; max-width: 100%; margin-bottom: 4px; }
.rep-unit-row .rep-unit { font-size: 11px; font-weight: 700; color: var(--text-sub); white-space: nowrap; }
/* 펼친 세부 내역 줄 — 이 표 **안에서만** 다른 칸 폭(기간+내역 = 150+290 = 440px)에 맞춰 재배분한다.
   🔴 .rep-detail-line/.rd-* 는 전역 클래스로 수금계획(2414·2523·4413행)·미지급금(5977)·노무비(8979)
      화면이 같이 쓴다 — 전역 규칙은 한 글자도 안 고치고 #repTable 스코프로만 덮는다(무회귀).
   ⚠ 원래 .rd-name 은 overflow:hidden + ellipsis + nowrap 이라 좁아진 칸에서 거래처명이 잘린다 —
     사용자 지시("잘림 없이 줄바꿈으로")대로 줄바꿈으로 바꾼다. 날짜 66px("2026-08-24" ≈64px),
     금액 88px(원 단위 최장 "3,666,268,469" 13자 ≈83px)만 고정하고 남는 폭을 이름이 쓴다.
   ⚠ 만기 표기(.rd-due)는 한 줄을 통째로 차지하게(flex-basis:100%) 내려 보낸다 — 좁은 칸에서 같은
     줄에 두면 이름 칸이 40px 대로 눌린다. */
#repTable .rep-detail-line { flex-wrap: wrap; gap: 2px 8px; }
#repTable .rep-detail-line .rd-date { width: 66px; }
#repTable .rep-detail-line .rd-name { flex: 1 1 80px; overflow: visible; text-overflow: clip;
                                      white-space: normal; word-break: keep-all; overflow-wrap: anywhere; }
#repTable .rep-detail-line .rd-amt { width: 88px; }
#repTable .rep-detail-line .rd-due { width: auto; flex: 0 0 100%; }

/* 참고 양식 3종 폭 맞춤 — *외화 입출금 내역 / *매출채권 미수 내역 / *계획 대비 차이 (C 2026-09-09,
   사용자 지시 "월간 자금보고에서 *외화 입출금 내역, *매출채권 미수 내역의 셀 너비도 제일 상단의 표와
   전체 표의 너비를 맞춰주고 … HTML 로 다운받을 땐 760px 가 되게 맞춰줘").
   ⚠ 직전 라운드엔 이 표들에 colgroup·고정폭이 없어(폭 자동) 카드 안쪽 가용폭(≈1430px)까지 늘어나
     본표 #repTable(실측 1200px)과 오른쪽 끝이 어긋났다 — 사용자가 지적한 실체가 이것이다.
   ⚠ 폭 값 1199px 은 #repTable 과 **같은 근거·같은 값**이다(위 #repTable 주석: border-collapse 표는
     바깥 테두리 절반이 지정 폭 밖에 그려져 실측 = 열 폭 합 + 1 → 1199 지정 = 1200.0 실측).
     열 폭 자체는 app.js _repFxFlowSection/_repOverdueSection 의 scrCols(합 1199)가 <colgroup> 으로 준다.
   ⚠ max-width:100% 는 #repTable 과 같은 이유로 유지 — 좁은 화면에서 카드 밖 넘침·가로 스크롤 방지.
   🔴 HTML 다운로드·PDF 는 이 파일을 타지 않는다 — 그쪽 폭은 app.js REP_PRINT_CSS(.rpt 760px /
      .rpt table 732px)가 잡고, 새 표 2개의 인쇄 colgroup 합도 732 로 다른 표(REP_COL_SUM/DET/T3/
      BANK/FX)와 같다. .rep-fixw/.rep-fixbox 클래스 문자열이 인쇄본에도 같이 나가지만 그쪽 CSS 엔
      정의가 없어 무해하다(화면·인쇄가 한 빌더를 공유하는 구조를 깨지 않으려는 의도적 선택).
   ⚠ 이 두 클래스는 자금보고 참고 양식 3종에서만 쓴다 — 은행별 잔액(#repBankTable) 등 나머지 .grid
     표는 종전대로 폭 자동이다(전역 .grid 규칙은 한 글자도 안 고쳤다). */
table.grid.rep-fixw { table-layout: fixed; width: 1199px; max-width: 100%; }
.rep-fixw th, .rep-fixw td { box-sizing: border-box; white-space: normal; word-break: keep-all; overflow-wrap: anywhere; }
.rep-fixw td.num, .rep-fixw th.num { white-space: nowrap; word-break: normal; }
.rep-fixbox { width: 1200px; max-width: 100%; }

/* 어음 관리 2열 배치 (P0.68.0) */
.note-grid { display: flex; gap: 10px; align-items: flex-start; }
.note-grid > .note-tbl { width: 50%; }
.note-grid > div { flex: 1; min-width: 0; }
.note-grid > div .note-tbl { width: 100%; }
.note-tbl { font-size: 11px; }
.note-tbl th, .note-tbl td { padding: 2px 4px; white-space: nowrap; }
.note-tbl input[type=date] { font-size: 11px; padding: 0 2px; }
.note-tbl .nowrap { white-space: nowrap; }
@media (max-width: 900px) { .note-grid { flex-direction: column; } .note-grid > .note-tbl { width: 100%; } }
/* 설정 — 공휴일 관리 + 고정지출 실질 지급일 2열 배치 */
.settings-2col { display: flex; gap: 12px; align-items: flex-start; }
.settings-2col > .card { flex: 1; min-width: 0; margin: 0; }
@media (max-width: 900px) { .settings-2col { flex-direction: column; } }

/* 일일자금 보고 서식 — ⚠ 규칙이 여기 있으면 안 된다. app.js 의 DAILY_CSS 하나가 단일 원천이고,
   화면은 ensureDailyStyle() 이 그걸 <style id="dailyStyle"> 로 주입한다(HTML/PDF 는 문서에 인라인).
   예전엔 여기(화면)와 DAILY_CSS(인쇄)에 규칙이 이중으로 있어서, DAILY_CSS 만 새 양식으로 고쳤을 때
   화면에는 새 클래스(.daily-form/.d-assets 등)가 하나도 안 붙는 채로 남았다 — 같은 함수로 그려도
   CSS 경로가 둘이면 화면·인쇄가 갈린다. 그 재발을 막으려고 이 블록을 비워 둔다. */

/* 수금계획 보고서 팝업 (P0.66.0) */
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 1000; display: flex; align-items: flex-start; justify-content: center; padding: 20px; }
.modal-overlay[hidden] { display: none; }
.modal-box { background: #fff; border-radius: 8px; max-width: 1120px; width: 100%; max-height: 92vh; display: flex; flex-direction: column; box-shadow: 0 10px 40px rgba(0,0,0,.3); }
.modal-bar { display: flex; align-items: center; gap: 6px; padding: 10px 14px; border-bottom: 1px solid #e5e7eb; }
.modal-scroll { overflow: auto; padding: 16px; background: #f1f5f9; }
/* (보고서 월 이동, 사용자 요청 2026-09-01) 조회 중 잠금 표시 — 이 모달 바 안에서만. 전역 .btn:disabled
   을 새로 만들면 이미 disabled 를 쓰는 다른 화면(pbBtn_*, splitSaveBtn 등)의 모양이 같이 바뀐다. */
#reportModal .modal-bar .btn:disabled { opacity: .5; cursor: not-allowed; }
#reportModal .modal-bar input:disabled { opacity: .6; }
#reportModal .modal-bar #reportYm { font-size: 12px; padding: 2px 4px; }
/* 실패 사유 — 조용히 삼키지 않되 본문(직전 달 내용)은 그대로 두므로 바에만 남긴다. */
.rpt-bar-err { font-size: 11.5px; color: #b91c1c; }
.rpt-bar-err[hidden] { display: none; }
#reportPreview { max-width: 1060px; margin: 0 auto; background: #fff; padding: 24px; }
/* 보고서 문서 스타일 (프리뷰·다운로드 공통) */
.rpt { font-family: 'Malgun Gothic', sans-serif; color: #111; font-size: 10px; }
.rpt h1 { font-size: 17px; text-align: center; margin: 0 0 4px; }
.rpt .rpt-sub { text-align: center; color: #555; margin-bottom: 12px; font-size: 10px; }
.rpt h2 { font-size: 12px; margin: 14px 0 5px; border-left: 4px solid #0d9488; padding-left: 6px; }
.rpt table { border-collapse: collapse; width: 100%; }
.rpt th, .rpt td { border: 1px solid #cbd5e1; padding: 2px 4px; }
.rpt th { background: #f1f5f9; font-weight: 600; white-space: nowrap; }
.rpt td.num, .rpt th.num { text-align: right; }
.rpt td.ctr { text-align: center; }
/* (V3.2.24/사용자 지시 2026-09-09 "가시성 높인 게 보고서 플로팅 화면에는 안 보임") 미리보기(#reportPreview)는 style.css 의
   .rpt 규칙으로 그려지므로 REPORT_CSS(다운로드 문서용)에 넣은 강조·소계 톤을 여기에도 같은 값으로 둔다. */
.rpt table.s1 td.s1-key { font-weight: 700; color: #1e3a8a; }
.rpt table.s1 td.s1-sum { background: #eef2ff; }
.rpt table.mt td.mt-lab, .rpt table.mt th.mt-lab { font-weight: 700; background: #e2e8f0; }
.rpt table.mt th.mt-cur, .rpt table.mt td.mt-cur { font-weight: 700; color: #1e3a8a; background: #eef2ff; }
.rpt tr.rpt-sub td { background: #f1f5f9; font-weight: 700; }
.rpt tr.rpt-sub.sub-od td { background: #e9e2fb; }
.rpt tr.rpt-sub.sub-a td { background: #dceaf6; }
.rpt tr.rpt-sub.sub-note td { background: #e5e7eb; }
/* (V3.2.25/사용자 지시 2026-09-09 "외화 입출금 내역 ↔ 매출채권 미수 내역 ↔ 계획 대비 차이 제목이 너무 붙었음, 여유 공간") */
h2.rep-x-h { margin-top: 26px !important; }
/* (V3.2.27) 기타(경비/투자) 처리 배지 '투자' — 자산매입(감가상각 대상) */
.badge.inv { background: #fef3c7; color: #92400e; }
.rpt table.s1 { table-layout: fixed; }
.rpt table.s1 td, .rpt table.s1 th { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rpt tr.rpt-total td { background: #ecfdf5; font-weight: 700; }
.rpt .rpt-done { color: #0d9488; font-weight: 600; }
.rpt input { font: inherit; padding: 1px 3px; border: 1px solid #cbd5e1; box-sizing: border-box; }
.rpt table.mchart-t, .rpt table.mt { table-layout: fixed; width: 100%; border-collapse: collapse; }
.rpt col.mc-h { width: 7%; }
.rpt table.mchart-t td { border: 1px solid #e5e7eb; vertical-align: bottom; padding: 2px; text-align: center; height: 88px; }
.rpt table.mchart-t td.mc-lab { background: #f8fafc; }
.rpt .mbars { height: 82px; display: flex; align-items: flex-end; justify-content: center; gap: 2px; }
.rpt .mbars .b { width: 42%; }
.rpt .mbars .b-plan { background: #cbd5e1; }
.rpt .mbars .b-recv { background: #0d9488; }
/* 월별 막대그래프 — 12칸 균등 */
.rpt .mchart { display: table; table-layout: fixed; width: 100%; border-collapse: collapse; }
.rpt .mchart .mcol { display: table-cell; width: 8.333%; text-align: center; vertical-align: bottom; border: 1px solid #e5e7eb; padding: 2px; }
.rpt .mbars { height: 90px; display: flex; align-items: flex-end; justify-content: center; gap: 2px; }
.rpt .mbars .b { width: 40%; }
.rpt .mbars .b-plan { background: #cbd5e1; }
.rpt .mbars .b-recv { background: #0d9488; }
.rpt .mcol .mlabel { font-size: 10px; margin-top: 2px; }
.rpt .mcol .mval { font-size: 9px; color: #555; }

/* 선급금 장부 출력 모달(#ppReportModal, 5차 개편 A 지시 2026-09-04) 미리보기 — 다운로드본(app.js
   PP_REPORT_CSS)과 같은 규칙을 이 모달 스코프로 다시 쓴다(전역 .rpt 를 바꾸면 다른 보고서 미리보기에도
   번진다 — REPORT_CSS 의 .rpt table.s1 td,th{white-space:nowrap;...} 를 이 모달 안에서만 줄바꿈 허용으로
   덮어써야 해서, PP_REPORT_CSS 주석과 같은 이유로 전역이 아니라 스코프를 택했다). 760px 문서를 가운데
   정렬한다. */
#ppReportModal .modal-scroll { display: flex; justify-content: center; }
#ppReportModal #ppRptPreview { width: 100%; }
#ppReportModal .rpt { box-sizing: border-box; width: 760px; max-width: 760px; margin: 0 auto; background: #fff; padding: 16px; }
#ppReportModal .pp-block { margin-bottom: 18px; }
#ppReportModal .pp-block + .pp-block { border-top: 2px solid #94a3b8; padding-top: 10px; }
#ppReportModal .rpt table.s1 { table-layout: fixed; width: 732px; }
#ppReportModal .rpt table.s1 td, #ppReportModal .rpt table.s1 th { white-space: normal; overflow: visible; text-overflow: clip; word-break: keep-all; overflow-wrap: anywhere; }
#ppReportModal .rpt table.s1 td.num, #ppReportModal .rpt table.s1 th.num, #ppReportModal .rpt table.s1 td.ctr, #ppReportModal .rpt table.s1 th.ctr { word-break: normal; }
#ppReportModal .rpt table.s1 td.ctr, #ppReportModal .rpt table.s1 th.ctr { text-align: center; }
#ppReportModal .pp-unit { text-align: right; color: #555; font-size: 9.5px; margin: -2px 0 4px; }
#ppReportModal .pp-foot { color: #555; font-size: 9px; margin-top: 3px; }
#ppReportModal .pp-block tr.pp-carry td { background: #f8fafc; font-style: italic; color: #555; }

/* 탭·컬럼 드래그 + 폭 조절 (P0.13.0) */
.grid th.th-over { background: var(--accent-bg); }
.grid th[draggable="true"] { cursor: grab; user-select: none; }
.col-resize { position: absolute; right: -3px; top: 0; width: 7px; height: 100%; cursor: col-resize; z-index: 2; }
.col-resize:hover { background: rgba(15, 118, 110, 0.35); }
.grid th { position: relative; }
/* (폭 조절 성능, A 지시 2026-08-29 — 실측 "1px 변경당 18.7~22.7ms") 드래그 중에는 표를 전혀 안 건드리고
   이 안내선만 움직인다. position:fixed + <body> 직속이라 표 서브트리(미지급금 고정항목 표의 select 372 +
   input 186 = 폼 컨트롤 558개) 레이아웃과 완전히 분리된다 — th.style.width 를 바꾸면 그 558개가 매 프레임
   재배치되지만, 이 요소는 out-of-flow 라 자기 자신만 움직인다. 이동은 반드시 transform 으로만 한다
   (left 를 바꾸면 이 요소 자체의 레이아웃이 다시 잡힌다 — transform 은 합성 단계). 실제 폭 적용은 mouseup
   한 번뿐(_attachColumnUX 참조). pointer-events:none 이라 드래그 중 mousemove/mouseup 을 가로채지 않는다. */
.col-resize-guide { position: fixed; left: 0; top: 0; width: 2px; background: #0f766e; z-index: 60; pointer-events: none; will-change: transform; }
/* 담당자가 "지금 얼마나 넓어지는지"를 숫자로 봐야 한다(A 지시) — 안내선에 붙어 함께 움직이는 폭 배지. */
.col-resize-guide b { position: absolute; top: 2px; left: 6px; padding: 1px 6px; border-radius: 3px; background: #0f766e; color: #fff; font-size: 11px; font-weight: 600; line-height: 1.6; white-space: nowrap; }

#dashStatus, #dashRecurring, #genResult, #splitResult, #receiptCheckResult { font-size: 12.5px; line-height: 1.9; white-space: pre-line; }
/* (사용자 지시 2026-10-01) 버전은 자금장부와 동일하게 화면 하단 중앙 푸터 */
.footer { text-align: center; padding: 16px 0 8px; color: #94a3b8; font-size: 11px; letter-spacing: 0.3px; line-height: 1.6; }
.empty { color: var(--text-sub); text-align: center; padding: 14px !important; }

/* ── 로그인 오버레이 (ledger 스타일) ── */
.auth-overlay { position: fixed; inset: 0; background: rgba(15, 23, 42, 0.55); display: flex;
                align-items: center; justify-content: center; z-index: 9999; backdrop-filter: blur(2px); }
.auth-card { background: var(--card); border-radius: 10px; padding: 28px 32px; width: 340px;
             box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25); }
.auth-logo { display: block; width: 52px; height: 52px; border-radius: 10px; margin: 0 auto 12px; }
.auth-card h2 { font-size: 18px; margin-bottom: 4px; text-align: center; }
.auth-sub { font-size: 12px; color: var(--text-sub); margin-bottom: 18px; text-align: center; }
.auth-card label { display: block; font-size: 12px; color: var(--text-sub); margin-bottom: 12px; }
.auth-card input { width: 100%; margin-top: 4px; padding: 9px 11px; font-size: 13px;
                   border: 1px solid var(--border); border-radius: var(--radius); outline: none; }
.auth-card input:focus { border-color: #64748b; }
.auth-err { color: var(--danger); font-size: 12px; min-height: 16px; margin-bottom: 8px; }
.auth-submit { width: 100%; padding: 10px; font-size: 13px; font-weight: 600; }
.auth-overlay[hidden] { display: none; }

/* 권한 노출은 전부 JS 가 제어 (P0.17.0 탭별 레벨) — CSS 역할 규칙 제거.
   설정 탭(need-sys)은 시스템관리자만 진입하므로 별도 숨김 불필요. 일반설정 탭(need-genadmin, A 지시
   2026-08)도 같은 이유로 별도 CSS 숨김 규칙이 없다 — app.js allowedTabs()/switchTab 이 탭 자체를
   막는다(need-sys 와 동일한 관례, 새 CSS 메커니즘을 만들지 않음). */
.perm-lv-none { color: #94a3b8; }

/* 노무비 반영 — 이중계상 충돌/경고 박스 (P0.104.0) */
.warn-box { background: #fef2f2; border: 1px solid #fecaca; border-radius: var(--radius); padding: 10px 12px; margin: 6px 0 4px; }
.grid tr.row-warn td.reason { color: var(--danger); font-weight: 600; }

/* 노무비 — 지급월 그룹 헤더행 (P0.106.0, #repTable tr.rep-head 와 동일 톤을 .grid 전역에) */
.grid tr.ph-group-head td { background: #f1f5f9; font-weight: 600; color: #0f766e; }

/* 드래그앤드롭 오버레이 (P0.15.2 — 수금계획 탭에서 ERP Excel 드롭) */
.drop-overlay { position: fixed; inset: 0; background: rgba(15, 118, 110, 0.12);
                border: 3px dashed var(--accent); display: none; align-items: center;
                justify-content: center; z-index: 9998; pointer-events: none; }
.drop-overlay.active { display: flex; }
.drop-inner { background: var(--card); border-radius: 12px; padding: 30px 44px; font-size: 18px;
              font-weight: 700; color: var(--accent); box-shadow: 0 12px 40px rgba(0,0,0,0.2); text-align: center; }
.drop-sub { font-size: 13px; font-weight: 400; color: var(--text-sub); margin-top: 6px; }

/* 버튼별 드롭존 강조 (노무비 업로드 3종 — A 지시 C, 사용자 지시 2026-09-16)
   파일을 버튼 위로 끌고 왔을 때만 붙는다(app.js 가 dragenter/dragover 에서 .drop-hot 토글) —
   "여기에 놓으면 이 종류로 올라간다"를 전면 오버레이 대신 버튼 자체로 알린다. */
.btn.drop-hot, .drop-hot { outline: 2px dashed var(--accent); outline-offset: 2px;
                           background: rgba(15, 118, 110, 0.12); }

/* 권한 관리 표 */
#permsTbody .chk { justify-content: center; }
.perm-default { color: var(--text-sub); font-size: 10.5px; }

/* 권한 레벨 히트맵 (P0.17.x — 없음/조회/수정 색상 구분) */
.grid td.perm-cell { padding: 3px 4px; transition: background .12s; }
.grid td.perm-cell.perm-lv-none { background: #f8fafc; }
.grid td.perm-cell.perm-lv-read { background: #eff6ff; }
.grid td.perm-cell.perm-lv-write { background: #fff7ed; box-shadow: inset 3px 0 0 #c2410c; }
.grid tbody tr:hover td.perm-cell { filter: brightness(0.97); }

.perm-cell select { font-size: 11.5px; padding: 2px 4px; border-radius: 4px; cursor: pointer; outline: none; }
.perm-cell.perm-lv-none select { color: #94a3b8; border: 1px solid #e2e8f0; background: transparent; font-weight: 400; }
.perm-cell.perm-lv-read select { color: #1d4ed8; border: 1px solid #bfdbfe; background: transparent; font-weight: 600; }
.perm-cell.perm-lv-write select { color: #c2410c; border: 1px solid #fed7aa; background: transparent; font-weight: 700; }

.grid td.perm-cell.perm-locked { opacity: .65; }
.perm-cell.perm-locked select { cursor: not-allowed; }

.perm-legend { margin-left: 8px; display: inline-flex; gap: 4px; vertical-align: middle; }
.perm-chip { font-size: 10.5px; font-weight: 600; padding: 1px 8px; border-radius: 8px; border: 1px solid; }
.perm-chip.perm-lv-none { background: #f8fafc; color: #94a3b8; border-color: #e2e8f0; }
.perm-chip.perm-lv-read { background: #eff6ff; color: #1d4ed8; border-color: #bfdbfe; }
.perm-chip.perm-lv-write { background: #fff7ed; color: #c2410c; border-color: #fed7aa; }

/* 4대보험 사업주분 대사 — 아직 저장 안 된 1:1 기본값 입력칸 (A 지시, C 2026-09-01)
   "담당자가 시스템이 채운 기본값을 자기가 확정한 값으로 오해하면 안 된다" — 옆 배지(기본값(1:1))와
   같은 사실을 칸 자체로도 한 번 더 말한다. 점선 테두리 + 흐린 글자 = "임시값" 이라는 이 파일의
   기존 관용(.perm-default 흐린 회색과 같은 톤), 새 색 도입 없음. 포커스하면 평범한 입력칸으로 돌아온다. */
input.nm-amt.ins-inv-default { border: 1px dashed #93c5fd; background: #f8fbff; color: #475569; }
input.nm-amt.ins-inv-default:focus { border-style: solid; color: inherit; background: #fff; }

/* 4대보험 사업주분 대사 — 사업주분 음수 (🔴 사용자 신고 2026-09-02, A 지시 C ②)
   "담당자가 빨간 숫자를 보고도 원인을 몰랐다" — 음수 자체를 감추거나 0 으로 깎지 않고(그건 틀린
   입력값을 숨기는 것) 그 칸과 **원인이 되는 고지액 입력칸**을 함께 눈에 띄게 해 시선이 고칠 곳으로
   가게 한다. 색은 기존 위험 톤(var(--danger) / .warn-box 배경 #fef2f2) 재사용 — 새 색 도입 없음.
   ⚠ .ins-inv-bad 는 .ins-inv-default 와 같은 특이도라 뒤에 선언해 이긴다(둘이 동시에 붙는 조합은
   없다 — 기본값(1:1)은 정의상 사업주분이 근로자분과 같아 음수가 될 수 없음 — 다만 순서로 보장한다). */
.grid td.num.ins-neg { color: var(--danger); font-weight: 700; background: #fef2f2; }
input.nm-amt.ins-inv-bad { border: 1px solid var(--danger); background: #fef2f2; color: var(--danger); font-weight: 600; }
input.nm-amt.ins-inv-bad:focus { background: #fff; }

/* (사용자 지시 2026-09-09 "미지급금과 기타(경비/투자)는 담당팀별로 Sorting 이나 필터링이 되게… 지급예정일도
   마찬가지고… 처리 부분도") 정렬 가능한 표 머리셀(처리·담당팀·지급예정일).
   ⚠ .grid th[draggable="true"] { cursor: grab } 와 특이도가 같아(둘 다 0,2,1) **뒤에 선언해서** 이긴다 —
   열 순서 드래그는 그대로 되지만 커서는 "누를 수 있다"(pointer)로 보인다. 열 폭 손잡이(.col-resize)는
   자기 영역에서 col-resize 커서를 유지한다(자식 요소라 이 규칙에 안 걸림). */
.grid th.th-sort { cursor: pointer; }
.grid th.th-sort:hover { background: var(--accent-bg); }
.grid th.th-sorted { color: #1d4ed8; }
.grid th .sort-ind { font-size: 10px; color: #1d4ed8; margin-left: 3px; }
/* 기타(경비/투자) 표 전용 필터 묶음 — .filter-row(flex) 안에서 두 select 를 한 덩어리로 묶고,
   표가 숨는 분류에서는 [hidden] 으로 통째로 감춘다(display 를 지정했으므로 [hidden] 규칙을 함께 둔다). */
.grid-f-wrap { display: inline-flex; gap: 10px; align-items: center; }
.grid-f-wrap[hidden] { display: none; }

/* ── 🔁 계좌간 이체 (잔액대체) — 전용 탭 panel-bank-transfer 의 본문 카드 #btCard
      (사용자 요청 2026-09-11, 전용 탭 이관도 같은 날 지시) ── */
/* '지연' 배지 — 예정일이 지났는데 통장 실적과 매칭되지 않은 행. 기존 .badge 체계에 얹는다(새 체계 X).
   ⚠ 다른 기능 전용 클래스(.rcr-off-badge 등)를 재활용하지 않는다 — 그쪽 색을 나중에 바꾸면
   이 카드까지 딸려 변하는 숨은 결합이 생긴다. */
.badge.bt-late { background: #fecaca; color: #991b1b; font-weight: 700; }
/* (상태 태그 체계, 사용자 지시 2026-09-11 "완료 표시를 해주고 새로 등록한 것은 계획으로 태그") —
   계획(파랑) / 완료(초록, 기존 .badge.rec 재사용) / 완료·미계획(회색-초록: 장부에서 발견된 실적).
   '계획'은 기존 .badge.pre(amber, '예정')가 아니라 파란 계열을 따로 둔다 — 같은 표 안에서 지연(빨강)·
   완료(초록)와 세 색이 뚜렷이 갈려야 한 눈에 읽힌다. */
.badge.bt-plan { background: #dbeafe; color: #1e40af; }
.badge.bt-unplanned { background: #e2e8f0; color: #0f766e; }
/* 은행명 + 계좌번호 두 줄이 한 칸에 들어가므로 위 정렬. */
#btCard .grid td { vertical-align: top; }
/* 계좌번호 보조줄(.hint)은 중간에서 끊기면 눈으로 대조가 안 된다 — 한 줄로 고정. */
#btCard .grid td .hint { white-space: nowrap; }
/* (전용 탭 이관, 2026-09-11) 인쇄 숨김(@media print { #dailyBtCard { display:none } })은 없앴다 —
   그 규칙은 이 카드가 **일일보고 탭 안**에 있어서, 보고서를 브라우저로 인쇄하면 관리 UI 가 보고서
   밑에 딸려 나오던 문제 때문이었다. 이제 카드가 자기 탭에 혼자 있으니 숨길 이유가 사라졌고(오히려
   이 탭을 인쇄하면 빈 종이가 나온다), 일일보고 탭에는 이 카드가 아예 없다(다른 패널은 hidden 이라
   인쇄에도 안 실린다). 일일보고 HTML·PDF 내려받기는 원래대로 buildDailyBody() 의 별도 문서다. */

/* ── 💳 대금결제 (결재문서) — 전용 탭 panel-settlement 의 본문 미리보기 #stlDoc
      (사용자 지시 2026-09-11 "15일에 지급해야 할 외상매입금과 미지급금을 보고하는 결재문서") ──
   🔴 문서 자체의 모양(760px 폭·표 테두리·구분 셀 배경·소계/합계 톤)은 여기 두지 않는다 — app.js 의
      STL_CSS 한 곳에만 있고, 미리보기에는 그 상수를 <style> 로 함께 꽂는다(선택자가 전부 `.stl-doc`
      로 시작해 다른 탭의 .rpt 인쇄물에 새어 나가지 않는다). 그래야 화면과 다운로드본이 갈리지 않는다.
      여기 있는 건 **미리보기 컨테이너**(문서 바깥) 규칙뿐이다. */
#stlDoc { margin-top: 10px; overflow-x: auto; }
/* 결재문서는 760px 고정 폭이다 — 카드가 그보다 좁을 때만 위 overflow-x 로 가로 스크롤이 생긴다
   (문서 폭을 줄이지 않는다 — 줄이면 다운로드본과 모양이 갈린다). 그래서 여기서 flex 로 다시
   감싸지 않는다(flex 아이템은 기본으로 축소되어 760px 이 무너진다). */
#stlDoc .stl-doc { min-width: 760px; }
/* (사용자 지시 2026-09-11 "표를 왼쪽으로 붙여서 보여줘") 미리보기는 **좌측 정렬**이다 —
   STL_CSS 의 `.stl-doc .rpt{margin:0 auto}` 를 #stlDoc 안에서만 덮는다(id 가 붙어 특이도가 높다).
   🔴 STL_CSS 자체는 손대지 않는다 — 다운로드 HTML/PDF 는 다른 문서(.rpt)와 같은 가운데 여백
   관례를 그대로 쓰고, 여백은 문서의 '모양'(폭·표·색)이 아니라서 미리보기와 갈려도 무방하다. */
#stlDoc .stl-doc .rpt { margin-left: 0; margin-right: 0; zoom: 1.3; }
/* (사용자 지시 2026-09-11 "일반창 폰트가 너무 작다 — 자금보고 정도로") 화면 미리보기만 1.3배(10px→13px 상당).
   zoom 이라 폭·여백·표가 같은 비율로 커지고, 다운로드 HTML/PDF(STL_CSS 10px·760px)는 그대로다. */
/* 인쇄(브라우저 Ctrl+P)로도 이 화면이 그대로 나가게 — 다운로드 PDF 와 같은 문서라 숨길 이유가 없다. */
@media print { #panel-settlement .filter-row { display: none; } }

/* ── 🏦 하나은행 「일괄처리(지급) 요청서」 작성 카드 #hbfCard (대량이체 탭, 사용자 지시 2026-09-11) ──
   🔴 **인쇄물의 모양은 여기 없다** — 요청서는 은행 원본 PNG 를 배경에 깔고 pt 절대좌표로 글자를 얹는
      독립 문서다(app.js 의 HBF 상수 · _hbfPageHtml() · _hbfDoc()). 그 좌표·폰트는 전부 인라인 style 로
      들어가고, 같은 함수가 화면 미리보기와 PDF·HTML 다운로드를 함께 만든다. 여기 있는 건 **작성 UI**
      (좌 후보 / 우 요청서 내용)와 미리보기 **컨테이너** 규칙뿐이다 — 이 파일을 고쳐도 인쇄물은 안 변한다. */
#hbfCard .hbf-f { display: inline-flex; align-items: center; gap: 4px; }
/* (사용자 지시 2026-09-11 — "요청서 처리 관련된 건 왼쪽으로 모으고 오른쪽엔 항상 미리보기")
   카드 본문 최상위 2단: 왼쪽 .hbf-edit = 작성 UI 전부(헤더 입력·버튼·후보·장 탭·항목 표),
   오른쪽 .hbf-side = 미리보기(sticky). 미리보기는 A4 고정폭이라 오른쪽을 먼저 확보하고(flex:0 0 auto)
   왼쪽이 남는 폭을 가져간다 — min-width:0 이 없으면 안쪽 표가 왼쪽 열을 밀어 미리보기를 화면 밖으로
   내보낸다(flex 기본 min-width:auto). */
#hbfCard .hbf-main { display: flex; gap: 14px; align-items: flex-start; }
#hbfCard .hbf-edit { flex: 1 1 0; min-width: 0; }
/* 좌(후보) / 우(요청서 내용) 2단. 왼쪽 열 안이라 좁아지면 자연스럽게 위아래로 접힌다. */
#hbfCard .hbf-wrap { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; }
#hbfCard .hbf-col { flex: 1 1 340px; min-width: 300px; }
#hbfCard .hbf-col h3 { font-size: 13px; margin: 6px 0; display: flex; align-items: center; gap: 6px; }
/* 이미 담긴 후보 — 지우지 않고 흐리게 남긴다(무엇을 담았는지 목록에서 바로 대조되어야 한다). */
#hbfCard tr.hbf-dim td { opacity: .45; }
#hbfCard .hbf-warn { color: var(--danger); }
/* 페이지 탭 — "1장 / 3건 / 12,300,000" 3줄. 선택한 장만 강조(앱 공통 .btn 위에 얹는다).
   장 배정이 수동이 된 뒤로(사용자 지시 2026-09-11) 탭은 단순 이동이 아니라 **담을 장을 고르는 자리**
   라, 어느 장이 얼마나 찼는지(건수·합계)가 버튼 안에 보여야 한다. */
#hbfCard .hbf-tabs { display: flex; gap: 4px; flex-wrap: wrap; margin: 4px 0 6px; align-items: stretch; }
#hbfCard .hbf-tab { min-width: 64px; line-height: 1.25; text-align: center; padding: 3px 6px; }
#hbfCard .hbf-tab .hbf-tab-n,
#hbfCard .hbf-tab .hbf-tab-s { display: block; font-size: 10px; opacity: .75; white-space: nowrap; }
#hbfCard .hbf-tab.active { background: var(--primary); color: #fff; border-color: var(--primary); }
/* 한 장 한도(10건)까지 찬 장 — 여기엔 더 못 담는다는 걸 색으로 먼저 알린다. */
#hbfCard .hbf-tab-full { border-color: #fcd34d; }
#hbfCard .hbf-tab-full:not(.active) { background: #fffbeb; }
#hbfCard .hbf-tab-add { align-self: center; }
/* (사용자 지시 2026-09-11 — "일괄처리 요청서에는 별도의 수기 항목이 없어야 해") 수기 항목 추가 폼
   (.hbf-new / #hbfManualRow) 삭제. 요청서 줄은 지급계획 후보에서만 담는다 — 폼을 되살리지 말 것. */
/* 항목 배지 — 지금은 '계획 없음'(payment_id 가 없는 옛 저장분) 한 종류뿐이라 경고색만 쓴다. */
#hbfCard .hbf-badge { display: inline-block; padding: 0 4px; border-radius: 3px; font-size: 10px;
    background: #e0e7ff; color: #3730a3; border: 1px solid #c7d2fe; }
#hbfCard .hbf-badge-warn { background: #fef2f2; color: #991b1b; border-color: #fecaca; }
/* 저장 API 미배포·실패 안내 — alert 은 사라지지만 이 줄은 화면에 남아야 한다. */
#hbfCard .hbf-msg { margin: 6px 0; padding: 6px 10px; border-radius: 4px; font-size: 12px;
    background: #ecfdf5; color: #065f46; border: 1px solid #a7f3d0; }
#hbfCard .hbf-msg.hbf-msg-warn { background: #fffbeb; color: #92400e; border-color: #fcd34d; }
/* 미리보기(오른쪽 열) — A4 한 장(595.28pt ≈ 794px × 841.89pt ≈ 1122px)을 **실치수 그대로** 그린 뒤
   화면에서만 축소한다(인쇄물과 같은 _hbfPageHtml 출력이라 손대면 안 된다).
   ⚠ transform:scale 은 레이아웃 상자 크기를 안 줄인다 — 컨테이너 폭·높이를 축소비로 직접 계산해 준다
   (안 그러면 오른쪽·아래로 수백 px 빈 공간이 남는다). 축소비는 --hbf-scale 한 곳에서만 바꾼다.
   스크롤을 내려도 편집 중인 줄이 미리보기에 반영되는 걸 봐야 하므로 sticky. */
#hbfCard .hbf-side { --hbf-scale: .72; flex: 0 0 auto; position: sticky; top: 8px;
    width: calc(794px * var(--hbf-scale)); }
#hbfCard .hbf-prev-head { font-size: 12px; color: var(--text-sub); padding: 2px 0 4px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#hbfCard .hbf-preview { border: 1px solid var(--border); background: #f8fafc; overflow: hidden;
    width: 100%; height: calc(1122px * var(--hbf-scale)); }
#hbfCard .hbf-prev-inner { transform: scale(var(--hbf-scale)); transform-origin: top left;
    width: 794px; height: 1122px; }
#hbfCard .hbf-prev-err { padding: 10px; font-size: 12px; color: #92400e; }
/* 창이 좁으면 축소비를 더 낮춘다(0.72 → 0.6). A4 비율은 그대로 유지된다. */
@media (max-width: 1500px) { #hbfCard .hbf-side { --hbf-scale: .6; } }
/* ≤1100px — 2단을 포기하고 세로로 접는다(미리보기가 왼쪽 작성 UI 아래로 내려간다). */
@media (max-width: 1100px) {
    #hbfCard .hbf-main { flex-wrap: wrap; }
    #hbfCard .hbf-side { position: static; width: calc(794px * var(--hbf-scale)); max-width: 100%; margin-top: 10px; }
}
/* 작성 UI 는 인쇄 대상이 아니다 — 요청서는 PDF/HTML 다운로드가 정본이다(브라우저 Ctrl+P 로는
   배경 이미지가 기본 꺼져 있어 빈 양식이 나간다). */
@media print { #hbfCard { display: none; } }

/* 📒 계획장부 작성 (사용자 지시 2026-09-24) — 대량이체 탭, 일괄처리 요청서와 대량이체 파일 생성 사이.
   자금장부(실적) + 그날 계획을 합쳐 보여주는 A4 미리보기. 페이지 자체 스타일(.pl-page/.pl-table 등)은
   app.js 의 PL_CSS 상수 하나가 화면·PDF 공용 단일 원천이다(DAILY_CSS 관례 — 바로 아래 "일일자금 보고
   서식" 주석과 같은 이유: 화면·인쇄 CSS 가 두 곳이면 갈라진다). 여기는 카드 UI(탭·스크롤 컨테이너·
   스케일 래퍼)만 — 인쇄·PDF 대상이 아닌 화면 전용 chrome. */
#plCard .pl-tabs { display: flex; flex-wrap: wrap; gap: 2px; margin-bottom: 0; }
#plCard .pl-tab { padding: 6px 12px; font-size: 12px; border: 1px solid var(--border); border-bottom: none;
    border-radius: 6px 6px 0 0; background: #f1f5f9; color: var(--text-sub); cursor: pointer; }
#plCard .pl-tab:hover { background: #e2e8f0; color: var(--text); }
#plCard .pl-tab.active { background: #fff; color: var(--text); font-weight: 700; border-bottom: 1px solid #fff; margin-bottom: -1px; }
/* (A 지시 C, 2026-09-24) 페이지 컨트롤 — ledger 장부 출력 .lp-pagectrl/.lp-pg-btn 관례
   (ledger/templates/index.html 586~604행)을 pl- 카드에 그대로 포팅. 미리보기가 현재 페이지 1장만
   그리므로(스크롤 스택 아님) ‹ n/N › 형식으로 총 페이지도 같이 보여준다(ledger 는 숨기지만 여기는
   A 지시대로 표시). */
#plCard .pl-pagectrl { display: none; align-items: center; gap: 6px; padding: 5px 2px;
    border-bottom: 1px solid var(--border); background: #fff; font-size: 12px; }
#plCard .pl-pagectrl.active { display: flex; }
#plCard .pl-pagectrl .lp-pg-btn { min-width: 28px; padding: 3px 8px; border: 1px solid var(--border);
    background: #fff; border-radius: 4px; cursor: pointer; font-size: 12px; color: var(--text); }
#plCard .pl-pagectrl .lp-pg-btn:hover:not(:disabled) { background: var(--bg); }
#plCard .pl-pagectrl .lp-pg-btn:disabled { opacity: .4; cursor: not-allowed; }
#plCard .pl-pagectrl .lp-pg-info { font-weight: 700; padding: 0 10px; font-feature-settings: "tnum"; min-width: 40px; text-align: center; }
#plCard .pl-pagectrl .lp-pg-hint { font-size: 10px; color: #94a3b8; margin-left: 8px; }
/* (A 지시 C, 2026-09-24) "창에는 한 페이지만 전체가 나오게" — 페이지 1장만 그리므로(스크롤 스택
   아님) 높이를 뷰포트 기준 고정값으로 둔다(콘텐츠에 안 좌우돼야 plApplyScale 이 폭·높이 양쪽 fit
   스케일을 안정적으로 계산한다 — ledger lpApplyScale 과 같은 방식, app.js 참조). overflow:hidden —
   스크롤이 필요하면 스케일이 잘못 잡힌 것이다. */
#plCard .pl-preview { background: #525659; padding: 16px 0 28px; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 14px; overflow: hidden;
    height: min(760px, calc(100vh - 300px)); border-radius: 6px;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
/* 카드에 포커스(PageUp/Down·Home/End 활성) 상태를 시각적으로도 알려준다 — outline 만, 레이아웃 불변 */
#plCard .pl-preview:focus-visible { outline: 2px solid var(--balance, #2563eb); outline-offset: -2px; }
#plCard .pl-init { color: #fff; font-size: 13px; padding: 40px 24px; text-align: center; }
/* 스케일 래퍼 — app.js plApplyScale() 이 --pl-scale/--pl-scaled-w/-h 를 계산해 채운다
   (ledger 장부 출력 모달 lpApplyScale 과 같은 방식 — 컨테이너 폭에 맞춰 A4 페이지를 축소). */
#plCard .pl-page-wrap { width: var(--pl-scaled-w, 210mm); height: var(--pl-scaled-h, 297mm); flex-shrink: 0;
    box-shadow: 0 3px 14px rgba(0,0,0,.35); overflow: hidden; position: relative; background: #fff; }
#plCard .pl-page-wrap .pl-page { transform: scale(var(--pl-scale, 1)); transform-origin: top left;
    position: absolute; top: 0; left: 0; margin: 0 !important; box-shadow: none !important; }
@media print { #plCard { display: none; } }

/* ── 노무비 업로드·반영 상태 표식 (A 지시, C — 사용자 지시 2026-09-16 개정) ──
   사용자 확정: "업로드 여부는 녹색·빨강 두 개로, **버튼 색깔로만** 표시. 업로드된 것은 녹색."
   → 별도 배지(.badge.up-ok/up-no/up-na)는 제거했다. 상태는 버튼에 붙는 이 두 클래스가 전부이고,
   자세한 내용(완료 일시·사업장별 ✓/●)은 버튼 title 로만 따라간다.
   색은 한눈에 갈리게 진하게 — 녹 #bbf7d0/#166534, 빨 #fecaca/#991b1b(.badge.bt-late 계열).
   ⚠ .btn-done/.btn-todo 는 **색만** 바꾼다 — disabled 를 주지 않는다(녹색이어도 재업로드=덮어쓰기 허용).
   ⚠ .btn-primary(반영 버튼)보다 뒤에 있어야 색이 이긴다 — 이 블록을 위로 옮기지 말 것. */
.btn.btn-done { background: #bbf7d0; border-color: #4ade80; color: #166534; font-weight: 600; }
.btn.btn-done:hover { background: #86efac; }
.btn.btn-todo { background: #fecaca; border-color: #f87171; color: #991b1b; font-weight: 600; }
.btn.btn-todo:hover { background: #fca5a5; }

/* 📈 자금추이 (사용자 지시 2026-10-01) */
#panel-fund-trend .ft-chart { width: 100%; max-width: 1100px; }
#panel-fund-trend .ft-chart svg { width: 100%; height: auto; display: block; }
#panel-fund-trend .ft-years { display: inline-flex; gap: 12px; flex-wrap: wrap; align-items: center; }
#panel-fund-trend .ft-yr { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; font-size: 13px; }
#panel-fund-trend .ft-sw { display: inline-block; width: 14px; height: 4px; border-radius: 2px; }
#panel-fund-trend .ft-ax { font-size: 11px; fill: #475569; }
#panel-fund-trend .ft-ax.ft-pt { font-size: 8px; fill: #94a3b8; }
#panel-fund-trend .ft-ax.ft-mo { font-size: 12px; font-weight: 600; fill: #334155; }
#panel-fund-trend .ft-grid { stroke: #e2e8f0; stroke-width: 1; }
#panel-fund-trend .ft-zero { stroke: #64748b; stroke-width: 1; }
#panel-fund-trend .ft-vsep { stroke: #cbd5e1; stroke-width: 1; stroke-dasharray: 3 3; }
#panel-fund-trend table.ft-table th { text-align: center; white-space: nowrap; }
#panel-fund-trend table.ft-table td.ft-n { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
#panel-fund-trend table.ft-table td.ft-mo-c { text-align: center; font-weight: 600; white-space: nowrap; }
#panel-fund-trend table.ft-table td.ft-rem { min-width: 200px; max-width: 260px; font-size: 10.5px; white-space: normal; padding: 2px 6px; }
#panel-fund-trend .ft-rem-in { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.35; }
#panel-fund-trend table.ft-table td.ft-n, #panel-fund-trend table.ft-table th { padding-left: 5px; padding-right: 5px; }
#panel-fund-trend table.ft-table td.ft-td-chg { font-weight: 700; }   /* 정기예금 전달 대비 변동 시점 */
/* (사용자 지시 2026-10-01) 1~12월 행 높이 동일 — Remarks 줄바꿈 금지(ellipsis, 전문은 title) + 고정 높이 */
#panel-fund-trend table.ft-table tbody tr { height: 44px; }
#panel-fund-trend table.ft-table tbody td { white-space: nowrap; }
#panel-fund-trend .ft-d { font-size: 9px; color: #94a3b8; line-height: 1.1; }
#panel-fund-trend .ft-future, #panel-fund-trend .ft-future .ft-d { color: #94a3b8; }
#panel-fund-trend .ft-neg { color: #dc2626; }
@media print { #panel-fund-trend .filter-row { display: none; } }
/* (사용자 지시 2026-10-01) 자금추이 표 시재소계 금액은 굵게 */
#panel-fund-trend td.ft-cash { font-weight: 700; }
