/* DMRS Phase 5 design system (confirmed 2026-07-16).
   토큰(:root)·셸(사이드바+상단바)은 shell.css — 이 파일보다 먼저 로드된다.
   Tables: 13px, ~32px rows, ink rules (2px header line, double total line),
   tabular numerals. Gray scale/semantic colors follow GitHub Primer values. */

* { box-sizing: border-box; }
body {
    margin: 0;
    font-family: "Pretendard", system-ui, "Malgun Gothic", sans-serif;
    color: var(--gray-9);
    font-size: 14px;
    word-break: keep-all;
}

/* 본문 영역(회계 화면 전용 — 셸은 shell.css) */
/* overflow를 두지 않는다(스크롤 조상은 창 하나) — 두면 thead sticky가 죽는다.
   넓은 표의 가로 스크롤은 .tbl-wrap이 담당. */
.content { flex: 1; min-width: 0; padding: 22px 24px; }
.page { max-width: var(--page-w); margin: 0 auto; }
.page.full { max-width: none; }
/* ── 문서형 보고서(재무상태표·손익계산서 — 07-17 D안 확정) ──
   캔버스(책상, gray-1) 위 흰 종이(.doc-sheet 중앙 880px 대칭) + 옆 여백 레일.
   레일은 흐름 밖 오버레이(absolute 스트립 안 sticky)라 종이 배치에 영향이 없고,
   여백이 레일을 못 담으면(컨테이너 1180px 미만) 종이 위 우측으로 접힌다.
   인쇄 시 종이만 남는다(print.css에서 평면화). */
.content:has(.page.doc) { background: var(--gray-1); }
.doc-layout { container-type: inline-size; }
.doc-wrap { position: relative; max-width: 880px; margin: 0 auto; }
/* 문서형 드릴다운 안내: 종이 위가 아닌 책상(회색 영역)에 — 종이 은유 보존.
   doc-wrap 밖(레일 top:0 정렬 유지)에서 종이 폭(880px)에 맞춰 우측 정렬 */
.doc-desk-note { max-width: 880px; margin: 0 auto 8px; text-align: right; }
.doc-sheet {
    background: #fff;
    border: 1px solid var(--gray-2); border-radius: 2px;
    box-shadow: 0 1px 2px rgba(31, 35, 40, .10), 0 12px 28px rgba(31, 35, 40, .10);
    padding: 40px 56px 56px; margin-bottom: 32px;
}
.doc-title { text-align: center; margin: 2px 0 4px; }
/* 종이 안에서 표는 종이 폭을 채운다. 금액 열은 고정폭(당기·전기말 2열 대응) */
.tbl-doc { margin: 0 auto; }
.doc-sheet .tbl-doc th.num, .doc-sheet .tbl-doc td.num { width: 168px; }
.doc-railzone {
    position: absolute; top: 0; bottom: 0; left: calc(100% + 16px);
    width: 164px; /* 고정폭 — max-content는 % 폭 자식과 순환해 레일이 무한정 넓어진다.
                     날짜 입력(110px)+요일 (수) 한 줄 수용 폭 */
}
.doc-rail {
    position: sticky; top: calc(var(--topbar-h) + 16px);
    display: flex; flex-direction: column; align-items: stretch; gap: 6px;
    padding: 10px;
    background: var(--gray-0); border: 1px solid var(--gray-2); border-radius: 8px;
}
.doc-rail .btn { text-align: center; }
/* 날짜 입력+요일(.date-wd)을 한 줄 유지 — 요일이 다음 줄로 떨어지지 않게 */
.doc-rail .inline-form { display: flex; align-items: center; gap: 4px; }
.doc-rail .inline-form input.date-smart { flex: 1; min-width: 0; }
.doc-rail .date-wd { margin-left: 0; white-space: nowrap; }
.doc-rail .filter-form { flex-direction: column; align-items: stretch; }
.doc-rail input, .doc-rail select { width: 100%; box-sizing: border-box; }
@container (max-width: 1180px) {
    .doc-railzone { position: static; width: auto; margin-bottom: 10px; }
    .doc-rail {
        position: static; flex-direction: row; justify-content: flex-end;
        flex-wrap: wrap; background: transparent; border: 0; padding: 0;
    }
    .doc-rail .inline-form { display: inline; }
    .doc-rail .filter-form { flex-direction: row; align-items: center; }
    .doc-rail input[type="date"], .doc-rail select { width: auto; }
    .doc-rail input[type="number"] { width: 72px; }
}

h1 { font-size: 20px; margin: 0 0 16px; }

/* ── 홈(대시보드) — 이 화면만 본문 배경을 옅은 회색으로(카드가 뜨는 데스크) ── */
.content:has(.page.home) { background: var(--gray-0); }
.dash-date { font-size: 13px; color: var(--gray-5); margin: 0 0 12px; }
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin-bottom: 14px; }
.tile { background: #fff; border: 1px solid var(--gray-2); border-radius: 8px; padding: 12px 16px 10px;
        display: flex; flex-direction: column; gap: 2px; text-decoration: none; color: var(--gray-9); }
.tile:hover { border-color: var(--gray-3); }
.tile .lb { font-size: 12px; font-weight: 600; color: var(--gray-6); letter-spacing: .03em; }
.tile .val { font-size: 21px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.3; }
.tile .cap { font-size: 12px; color: var(--gray-5); font-variant-numeric: tabular-nums; }
.tile svg { margin-top: 4px; }
.up { color: var(--ok); font-weight: 600; }
.warn-t { color: var(--warn); font-weight: 600; }
.ok-t { color: var(--ok); font-weight: 600; }
/* [환율 검증]: 적용환율이 유도값과 어긋난 출금 줄을 옅은 적색으로 짚는다 */
tr.fx-bad > td { background: var(--danger-subtle); }
/* 지금 잃을 것이 있을 때만 뜨는 경고(2026-08-12 수석) — 늘 떠 있으면 눈이 지나친다.
   그래서 색을 아끼지 않고 danger를 쓴다: 드물게 뜨는 만큼 셀 수 있다. */
.warn-inline { color: var(--danger); font-size: 12px; margin-left: 8px; white-space: nowrap; }
.btn.attention { box-shadow: 0 0 0 2px var(--danger-subtle); border-color: var(--danger); }
.dash-grid { display: grid; grid-template-columns: 1.15fr .85fr; gap: 12px; align-items: start; }
@media (max-width: 1100px) { .dash-grid { grid-template-columns: 1fr; } }
.dcard { background: #fff; border: 1px solid var(--gray-2); border-radius: 8px; padding: 12px 16px 14px; margin-bottom: 12px; }
.dcard h4 { margin: 0 0 8px; font-size: 13px; font-weight: 700; color: var(--gray-6); display: flex; align-items: center; }
.dcard h4 .go { margin-left: auto; font-size: 12px; font-weight: 600; color: var(--accent); text-decoration: none; }
.dcard h4 .go:hover { text-decoration: underline; }
.todo { list-style: none; margin: 0; padding: 0; }
.todo li { display: flex; align-items: center; gap: 8px; padding: 8px 2px; border-bottom: 1px solid var(--gray-1); font-size: 13px; }
.todo li:last-child { border-bottom: 0; }
.todo .cnt { font-weight: 700; font-variant-numeric: tabular-nums; }
.todo .b { margin-left: auto; font-size: 12px; color: var(--accent); font-weight: 600; white-space: nowrap; text-decoration: none; }
.todo .b:hover { text-decoration: underline; }
.todo .dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }
.dot.blue { background: var(--accent); }
.dot.amber { background: #d4a72c; }
.dot.gray { background: var(--gray-3); }
h2 { font-size: 16px; margin: 24px 0 10px; }

.messages { list-style: none; padding: 0; margin: 0 0 16px; }
.msg { padding: 9px 12px; border-radius: 6px; margin-bottom: 6px; }
.msg.success { background: var(--ok-subtle); color: var(--ok); }
.msg.error { background: var(--danger-subtle); color: var(--danger); }
/* 에이전트 자동 업로드 도착 배너([은행내역] 폴링) — 작업 중일 때만 노출.
   display:flex가 hidden 속성(UA display:none)을 이기므로 [hidden] 복원 필수 */
.msg.poll-banner { display: flex; align-items: center; gap: 10px; background: var(--accent-subtle); color: var(--accent); font-weight: 600; }
.msg.poll-banner[hidden] { display: none; }

/* ── tables: ledger grammar ── */
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { padding: 7px 10px; border-bottom: 1px solid var(--gray-1); text-align: left; }
thead th {
    background: var(--gray-0); font-weight: 600; font-size: 12px;
    color: var(--gray-6);
    /* 긴 표에서 머리행이 화면 상단에 고정. collapse된 border는 sticky를
       따라오지 않으므로 머리행 괘선(2px 먹선·차대 세로선)은 inset shadow로 그린다.
       line-height 고정 → 줄 높이 28px(7+14+7) 확정, 2단 머리 오프셋의 기준. */
    position: sticky; top: var(--topbar-h); z-index: 2; line-height: 14px;
    border-bottom: 0; box-shadow: inset 0 -2px 0 var(--rule);
}
thead th.vr { border-right: 0; box-shadow: inset -1px 0 0 var(--gray-3), inset 0 -2px 0 var(--rule); }
thead th.vl { border-left: 0; box-shadow: inset 1px 0 0 var(--gray-3), inset 0 -2px 0 var(--rule); }
/* 일·월계표 2단 머리행: 둘째 줄은 상단바+첫 줄 높이(28px)만큼 내려 고정 */
thead tr + tr th { top: calc(var(--topbar-h) + 28px); }
tbody tr:hover > td { background: var(--gray-0); }
/* 드릴다운 어포던스: 이동 가능 행(tr[data-href])만 커서 + 연청 hover — 일반 행과 구분 */
tbody tr[data-href] { cursor: pointer; }
tbody tr[data-href]:hover > td { background: var(--accent-subtle); }
/* data-rowkey 행(은행·매출매입·전표): hover 시 커서+연청 강조로 작업 행을 또렷이,
   상세로 나갔다 돌아오면 클릭했던 행을 .row-active로 강조 유지(remember_scroll.js) */
tbody tr[data-rowkey] { cursor: pointer; }
tbody tr[data-rowkey]:hover > td { background: var(--accent-subtle); }
tbody tr[data-rowkey].row-active > td { background: var(--accent-subtle); }
/* 분개장: 하이라이트가 라인(행)이 아니라 전표 단위로 움직인다 — 같은 data-entry 행 묶음
   (entry_group 인라인 JS가 hover 시 .entry-hover를 묶음 전체에 부여) */
tbody tr.entry-hover > td { background: var(--accent-subtle); }
/* 체크박스 선택 행: 연노랑 형광펜(2026-07-24 채택 — 연청은 드릴다운/복귀와 겹침).
   table_select.js가 체크 상태와 .sel을 동기화 — 긴 행에서 선택 대상 검산용 */
tbody tr.sel > td, tbody tr.sel:hover > td { background: var(--attention-subtle); }
/* 선택 작업 바: 표 위 고정(N건 선택 + 일괄 작업, 0건 시 비활성).
   thead sticky와 층을 나눔 — .has-selbar 표의 머리행은 바 높이만큼 내려 고정 */
.sel-bar {
    position: sticky; top: var(--topbar-h); z-index: 3;
    display: flex; align-items: center; gap: 8px; height: 40px;
    background: var(--gray-0); border: 1px solid var(--gray-2); border-radius: 6px;
    padding: 0 12px; margin-bottom: 8px;
}
.sel-bar .sel-count { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.sel-bar .sel-count.zero { color: var(--gray-5); font-weight: 400; }
.has-selbar thead th { top: calc(var(--topbar-h) + 48px); }
/* 일괄 작업 버튼의 아이콘(+라벨 유지) */
.btn .ic { font-size: 13px; line-height: 1; margin-right: 1px; }
/* 대표 식별자(행의 주체 한 곳만 세미볼드 — 화면당 1열) */
td.cell-key { font-weight: 600; }
/* 반복 행 액션 아이콘 버튼: 툴팁·aria-label 필수. 30px 원형 테두리 —
   테두리 없는 소형은 발견성이 낮다는 피드백(07-24)으로 키움 */
.ib {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border: 1px solid var(--gray-3); border-radius: 50%;
    background: #fff; cursor: pointer; font-size: 15px; color: var(--gray-6); padding: 0;
}
.ib:hover { background: var(--gray-1); color: var(--gray-9); border-color: var(--gray-5); }
.ib.danger:hover { background: var(--danger-subtle); color: var(--danger); border-color: var(--danger); }
/* 행 액션 묶음(.ib-seg, 고스트형): 아이콘+라벨 **가로 나란히**, 테두리 없음 — [○○관리]
   머리글이 구분을 맡으므로 행 안 박스 불필요(07-30 수석 협의 3라운드: 이중 박스→한
   테두리→무테두리. 경위·규칙 정본 docs/phase-5-ui-design.md §4).
   가로 배열은 08-02 확정 — 세로(아이콘 위+라벨 아래)는 행 높이를 키워 한 화면에 보이는
   행 수를 줄인다(수석 지적). 클릭 어포던스는 색 아이콘+hover 배경이 담당,
   파괴 칸은 ✕ 아이콘만 적색(행마다 반복되는 빨강 최소화). a·button 공용(.seg). */
.ib-seg { display: inline-flex; gap: 4px; vertical-align: middle; }
.ib-seg form { display: contents; }   /* POST 삭제(inline-form)도 칸으로 참여 */
.ib-seg .seg {
    display: inline-flex; align-items: center; gap: 3px;
    padding: 2px 6px; border: 0; border-radius: 6px;
    background: none; color: var(--gray-6); font-family: inherit;
    font-size: 10.5px; line-height: 1.6; text-decoration: none; cursor: pointer;
    white-space: nowrap;
}
.ib-seg .ic { font-size: 13px; line-height: 1; }
.ib-seg .ic.info { color: var(--accent); }   /* ⓘ = 화면 사용법과 같은 안내 파랑 */
/* hover 강조는 색이 아니라 형태로 — 숨겼던 테두리가 링으로 되살아난다(07-30 수석 협의:
   연노랑은 체크 선택 의미로 예약·연청은 이동 의미라 표 안 새 hue 금지) */
.ib-seg .seg:hover {
    background: var(--gray-1); color: var(--gray-9);
    box-shadow: inset 0 0 0 1px var(--gray-3);
}
.ib-seg .seg.danger .ic { color: var(--danger); font-weight: 700; }
.ib-seg .seg.danger:hover {
    background: var(--danger-subtle); color: var(--danger);
    box-shadow: inset 0 0 0 1px var(--danger);
}
/* 머리글 정렬(목록 화면 전용): 비활성 열 흐린 ↕, 활성 열 강조색 ▲▼ + aria-sort */
th.sortable { padding: 0; }
th.sortable .thb {
    display: flex; align-items: center; gap: 4px; width: 100%;
    padding: 7px 10px; font: inherit; font-size: 12px; font-weight: 600;
    color: var(--gray-6); text-decoration: none;
}
th.sortable.num .thb { justify-content: flex-end; }
th.sortable .thb:hover { color: var(--gray-9); }
th.sortable .arrow { font-size: 11px; color: var(--gray-3); }
th.sortable[aria-sort] .arrow { color: var(--accent); }
th.sortable[aria-sort] .thb { color: var(--gray-9); }
/* 정렬과 필터를 **한 머리글에** 이는 열(채권채무 흐름 [상태], 2026-08-19).
   th.sortable은 padding:0 + .thb width:100%라, 그대로 두면 ▾·칩이 셀 밖으로 밀린다. */
th.sortable.thmix { padding: 7px 10px; }
th.sortable.thmix .thb { display: inline-flex; width: auto; padding: 0; }
/* 매출매입 상태 탭 — 은행내역과 같은 탭 카드 문법(08-05). 상자 맨 윗줄이라 여백 없음.
   ⚠ 선택자에 .tabs를 함께 적어야 한다 — 뒤에 오는 `.seg.tabs { border: 0 }`이
   더 구체적이라 `.sp-tabs`만으로는 아래 구분선이 지워진다(은행내역은 이 선을
   탭이 아니라 감싸는 `.bank-scope`가 그려서 문제가 없었다).
   ⚠ display도 flex로 — `.seg`는 inline-flex라 상자가 버튼 폭까지만이고, 그러면
   구분선도 거기서 끊긴다(같은 이유의 다른 얼굴). */
.seg.tabs.sp-tabs { display: flex; margin: 0; padding: 6px 10px;
    border-bottom: 1px solid var(--line); }
/* 상자 안 도구줄(선택 작업 바·필터줄)은 테두리 없는 '띠'로 — 상자 안의 상자 방지.
   선택 바의 sticky도 푼다: 표가 내부 스크롤이라 바는 어차피 늘 화면에 있다. */
.tab-card .sel-bar { position: static; top: auto; z-index: auto; height: auto;
    margin: 0; padding: 8px 12px; border: 0; border-bottom: 1px solid var(--line);
    border-radius: 0; background: #fff; }
.tab-card .filter-form.wrap { margin: 0; padding: 10px 12px;
    border-bottom: 1px solid var(--line); }
.tab-card > div > p.muted { margin: 0; padding: 14px 12px; }   /* 비어 있을 때 안내문 */
/* 탭 패널 표시 — html[data-*-tab]는 탭 버튼 직후의 동기 스크립트가 첫 페인트 전에
   스탬프(하단 스크립트로 숨기면 모든 표가 겹쳐 보였다 사라지는 깜박임). JS 꺼짐=전부 표시 */
html[data-sp-tab="pending"] #sp-view-posted,
html[data-sp-tab="posted"] #sp-view-pending,
html[data-bank-tab="pending"] .bank-view:not(#view-pending),
html[data-bank-tab="excluded"] .bank-view:not(#view-excluded),
html[data-bank-tab="posted"] .bank-view:not(#view-posted) { display: none; }
/* 고정 레이아웃(재설계 a): 표만 내부 스크롤(은행 bank-scroll과 동일 방식) —
   제목·안내·업로드·탭·필터는 화면에 남고 창 스크롤이 생기지 않는다 */
.tbl-scroll { max-height: calc(100vh - 320px); min-height: 280px; overflow: auto; }
/* 상단 구성이 가벼운 화면(분개장 등): 표 높이를 더 크게 */
.tbl-scroll.tall { max-height: calc(100vh - 240px); }
/* 표 처음/끝 이동 레일(table_scroll_nav.js) — 화면당 1개, body에 fixed로 두고
   지금 보이는 내부 스크롤 표에 갖다 붙인다. 우측 상단=처음(⇈)·우측 하단=끝(⇊):
   ⇈는 sticky 머리행 위, ⇊는 표 아래 경계에 얹혀 마지막 열(잔액·행 액션)을 가리지 않는다.
   레일 자체는 클릭을 통과시키고 26×26 버튼만 받는다. z-index는 머리행(2)·선택 바(3)
   위, 팝오버(40)·모달(100) 아래. */
.tsn-rail {
    position: fixed; z-index: 5; width: 26px; pointer-events: none;
    display: flex; flex-direction: column; justify-content: space-between;
}
.tsn-rail[hidden] { display: none; }
.tsn-btn {
    pointer-events: auto;
    width: 26px; height: 26px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--gray-2); border-radius: 7px;
    background: rgba(255, 255, 255, .72); color: var(--gray-6);
    cursor: pointer; box-shadow: 0 2px 6px rgba(31, 35, 40, .14);
    transition: background-color .15s, color .15s, transform .15s;
}
.tsn-btn:not(:disabled):hover {
    background: var(--gray-0); color: var(--accent); transform: scale(1.06);
}
.tsn-btn:not(:disabled):active { transform: scale(.95); }
/* 경계에 닿은 버튼은 숨기지 않고 흐리게 남긴다 — 밑에 깔린 합계 행 기말잔액이 비쳐 읽힌다. */
.tsn-btn:disabled { opacity: .4; cursor: not-allowed; box-shadow: none; }
.tsn-btn svg {
    width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
}
/* 자금출납장 계좌 세그먼트 — 계좌가 많으면 줄바꿈 */
.seg.cb-accounts { margin: 0 0 12px; flex-wrap: wrap; }
/* 자금계획 결제예정 관리: 탭·인라인 수정 폼·분할 행 */
.seg.cp-tabs { margin: 0 0 12px; }
.btn.sm { padding: 3px 9px; font-size: 12px; }
input.w-date { width: 108px; }
input.w-amt { width: 110px; text-align: right; }
tr.cp-split-row > td { background: var(--gray-0); }
/* [자금흐름 대사]: 은행 대체 묶음 문법 재사용 — 발생+짝 행은 좌측 색 바(같은 색=
   같은 묶음, 인접 교대 b1/b2·미회수=앰버 bw) + 🔗 pairchip. 폰트는 본 행과 동일 */
.flow-occ td:first-child, .flow-occ th:first-child { border-left: 4px solid transparent; }
/* 색 바는 의사요소로 — 묶음 시작(발생 행)·끝(마지막 짝 행)에 3px 여백을 둬
   인접 묶음의 바가 이어 붙지 않고 끊겨 보인다(묶음 간 구분) */
.flow-occ tr.bundle > td:first-child { position: relative; }
.flow-occ tr.bundle > td:first-child::before {
    content: ""; position: absolute; left: -4px; top: 0; bottom: 0;
    width: 4px; background: var(--b-bar);
}
.flow-occ tr[data-occ].bundle > td:first-child::before { top: 3px; }
.flow-occ tr.bundle-end > td:first-child::before { bottom: 3px; }
.flow-occ tr.b1 { --b-bar: #8250df; }
.flow-occ tr.b2 { --b-bar: #bf3989; }
.flow-occ tr.bw { --b-bar: #bf8700; }
tr.flow-hit > td { background: var(--accent-subtle); }
/* 짝 행 = 트리(└ 들여쓰기) + 배지 칩 — 폰트는 본 행과 동일 */
.flow-occ .sub-lbl { padding-left: 22px; color: var(--gray-6); }
form.flow-bulk { margin: 0 0 10px; }
/* 거래처원장: 요약+상세를 flex 한 상자로 — 요약이 쓰고 남은 높이를 상세가
   전부 차지(요약은 최대 40%에서 캡), 창 스크롤 없이 각자 내부 스크롤 */
.pl-stack {
    display: flex; flex-direction: column; gap: 12px;
    height: calc(100vh - 320px); min-height: 320px;
}
/* 요약은 축소 금지(flex-shrink 0) — 내용 높이만큼 온전히 차지하고 40%에서만 캡.
   shrink를 허용하면 상세에 밀려 한 줄도 안 보인 채 스크롤이 생긴다 */
.pl-summary-wrap { flex: 0 0 auto; max-height: 40%; overflow: auto; margin: 0; }
.pl-summary tbody tr[data-fold-target] { cursor: pointer; }
.pl-summary tbody tr[data-fold-target]:hover > td { background: var(--accent-subtle); }
.tbl-scroll.pl-detail { flex: 1 1 auto; max-height: none; min-height: 0; }

/* ── 상태 칩(P6, A안 방향 중심 — 재설계 c 채택 화면부터) ── */
.chip {
    display: inline-block; font-size: 11px; font-weight: 600;
    padding: 2px 8px; border-radius: 10px; white-space: nowrap;
}
.chip.sale, .chip.in { background: var(--accent-subtle); color: var(--accent); }
.chip.buy, .chip.out { background: var(--orange-subtle); color: var(--orange); }
.chip.transfer { background: var(--purple-subtle); color: var(--purple); }
.chip.done { background: var(--ok-subtle); color: var(--ok); }
.chip.wait { background: var(--attention-subtle); color: var(--attention); }
.chip.off { background: var(--gray-1); color: var(--gray-6); }
.chip.danger { background: var(--danger-subtle); color: var(--danger); }
/* 증빙유형(2026-08-11 수석) — 부가세에서 자리가 다른 것끼리 색을 가른다.
   앞 열 [구분]이 파랑(매출)·주황(매입)을 쓰므로 그 둘은 피한다.
   흔한 세금계산서는 회색으로 두고 **드문 것에 색을 준다** — 그래야 색이 신호가 된다. */
.chip.doc-tax { background: var(--gray-1); color: var(--gray-6); }        /* 과세 — 기본 */
.chip.doc-export { background: var(--ok-subtle); color: var(--ok); }      /* 영세율(과세표준 안, 세율 0) */
.chip.doc-exempt { background: var(--attention-subtle); color: var(--warn); }  /* 면세(과세표준 밖) */
.chip.doc-card,                                                            /* 영수증 갈래 — 둘을 한 색으로 */
.chip.doc-cash_rcpt { background: var(--purple-subtle); color: var(--purple); }
/* 출처 배지 = 원천 화면 역링크(분개장): 클릭하면 은행내역·매출/매입장·급여대장으로 */
a.src-link { text-decoration: none; cursor: pointer; }
a.src-link .chip { cursor: pointer; }
a.src-link:hover .chip { box-shadow: inset 0 0 0 1.5px currentColor; }

/* ── 화면 안내 통합 블록(P4, 재설계 f) — 첫 방문 펼침, 이후 상태 기억(screen_help.js) ── */
details.screen-help { margin: 0 0 10px; font-size: 12px; color: var(--gray-6); }
details.screen-help summary {
    cursor: pointer; list-style: none; display: inline-flex; gap: 6px; align-items: center;
    color: var(--gray-5);
}
details.screen-help summary::before { content: "ⓘ"; color: var(--accent); }
details.screen-help[open] {
    background: var(--gray-0); border: 1px solid var(--gray-2); border-radius: 6px;
    padding: 8px 12px;
}
details.screen-help .help-body { margin-top: 6px; line-height: 1.7; }

/* ── 헤더 검색(P3, 재설계 e) — 🔍 팝오버 + 활성 시 값 칩 ── */
/* 모양은 공유하되 동작 클래스는 분리(07-31): .hsearch=header_search.js(GET 필터형),
   .lf-open=ledger_find.js(원장 강조형). 한 버튼에 둘 다 달면 팝오버가 두 개 열린다. */
th button.hsearch, th button.lf-open {
    border: 0; background: none; cursor: pointer; padding: 0 2px;
    font-size: 12px; color: var(--gray-5);
}
th button.hsearch:hover, th.searched button.hsearch,
th button.lf-open:hover, th.searched button.lf-open { color: var(--accent); }
.hchip {
    display: inline-flex; align-items: center; gap: 4px; margin-left: 4px;
    background: var(--accent-subtle); color: var(--accent);
    border-radius: 10px; padding: 1px 8px; font-size: 11px; font-weight: 600;
}
.hchip a { color: inherit; text-decoration: none; font-weight: 700; }
.hpop {
    position: fixed; z-index: 40;
    background: #fff; border: 1px solid var(--gray-3); border-radius: 8px;
    box-shadow: 0 8px 24px rgba(31, 35, 40, .15); padding: 8px;
}
.hpop input { font: inherit; font-size: 13px; padding: 5px 8px; width: 220px;
              border: 1px solid var(--gray-3); border-radius: 6px; }
.hpop .hint { font-size: 11px; color: var(--gray-5); margin-top: 6px; }
/* 금액 검색 팝오버(2026-08-12) — 연산자 + 금액 + 버튼이 한 줄. 텍스트 검색보다 좁다. */
.hpop-amt .hamt-row { display: flex; align-items: center; gap: 6px; }
.hpop-amt select { font: inherit; font-size: 13px; padding: 5px 6px; }
.hpop-amt input { width: 120px; text-align: right; }
/* 일자 검색 팝오버(2026-08-27) — 부터 ~ 까지 두 칸. 금액과 같은 한 줄 문법이되,
   날짜는 왼쪽 정렬이고 물결(~)이 두 칸을 잇는다. */
.hpop-date .hdate-row { display: flex; align-items: center; gap: 6px; }
.hpop-date input { width: 104px; text-align: left; }
.hpop-date .hdate-tilde { color: var(--gray-5); }
/* 제안 목록(.hsug) — 네이티브 datalist 대신 자체 렌더. 행 모양은 .acombo-list와 공유(아래 그룹 선택자) */
.hpop .hsug { margin: 6px 0 0; padding: 0; list-style: none; max-height: 240px; overflow-y: auto; }
.hpop .hlist { min-width: 140px; max-height: 220px; overflow: auto; font-size: 13px; }
.hpop .hlist div { padding: 5px 10px; border-radius: 5px; cursor: pointer; }
.hpop .hlist div:hover, .hpop .hlist div.on { background: var(--accent-subtle); color: var(--accent); }
th button.hfilter {
    border: 0; background: none; cursor: pointer; padding: 0 2px;
    font-size: 11px; color: var(--gray-5);
}
th button.hfilter:hover, th.searched button.hfilter { color: var(--accent); }

/* 한눈에 보기(도움말) 요점 목록 */
.note-list { font-size: 13px; color: var(--gray-6); margin: 8px 0 20px; padding-left: 20px; }
.note-list li { margin: 3px 0; }
.note-list b { color: var(--accent); }

/* 자금일보: 좌우 2단 구획(자산/부채, 입금/출금) — 좁아지면 세로 적층 */
.dcr-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 24px; align-items: start; }
@media (max-width: 1000px) { .dcr-cols { grid-template-columns: 1fr; } }
.dcr-cols h3 { font-size: 14px; margin: 10px 0 6px; }
/* 관리항목 편집 줄(화면 전용) */
.dcr-items { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center;
             background: var(--gray-0); border: 1px solid var(--gray-2); border-radius: 6px;
             padding: 8px 12px; margin: 10px 0 4px; font-size: 13px; }
.dcr-items label { font-weight: 600; color: var(--gray-6); font-size: 12px; }
.dcr-items input[type=text] { width: 110px; }

/* 찾기/검색 입력의 발견성: 아이콘 + 충분한 폭 (label은 각 화면에서 제공) */
.search-box { position: relative; display: inline-flex; }
.search-box .mag {
    position: absolute; left: 8px; top: 50%; transform: translateY(-50%);
    color: var(--gray-5); font-size: 13px; pointer-events: none;
}
.search-box input { width: 300px; padding-left: 28px; }
.find-bar label { font-size: 12px; font-weight: 600; color: var(--gray-6); white-space: nowrap; }
/* 연월 입력 규격 폭(P2) — 원장 시작/종료월 등 */
input.w-ym { width: 84px; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
tfoot tr.totals td {
    border-top: 2px solid var(--rule); border-bottom: 3px double var(--rule);
    background: var(--gray-0);
}
/* negative amounts: sign first, color second (△1,234 pattern) */
.neg { color: var(--danger); }

/* 외화 병기(외화금액 @ 환율): 회색 축소 표기가 묻힌다는 피드백(07-17) —
   원화보다 한 단계 작게 유지하되 청색+세미볼드로 또렷하게 */
small.fx {
    font-size: 12px; font-weight: 600; color: var(--accent);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ── 전폭 표 보고서 머리(07-17 확정 문법) — 2줄 ──
   줄1 .report-tools: 도구 전부(토글·이동·필터·인쇄) 우측 정렬, 좁아지면 이 줄
   안에서만 줄바꿈. 줄2 .report-head: 좌(기간 라벨)·중앙(제목)·우(균형칸) 3분할.
   제목은 nowrap — 어떤 폭에서도 문서 머리는 안 깨진다. (이력: 도구가 제목과
   한 줄이던 3분할 단일 줄은 창 축소 시 세 구역이 폭을 다투며 붕괴해 개정) */
.report-tools {
    display: flex; justify-content: flex-end; align-items: center;
    gap: 6px; row-gap: 6px; flex-wrap: wrap; margin-bottom: 6px;
}
.report-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.report-head .side { flex: 1; display: flex; align-items: center; gap: 6px; min-width: 0; }
.report-head .side.r { justify-content: flex-end; }
.report-head h1 { margin: 0; text-align: center; white-space: nowrap; }
.report-note { text-align: center; margin: -4px 0 14px; }

td.ctr, th.ctr { text-align: center; }

/* 세로 괘선: 일계표·월계표의 차/대 구획 */
td.vr, th.vr { border-right: 1px solid var(--gray-3); }
td.vl, th.vl { border-left: 1px solid var(--gray-3); }

/* 대차 일치/불일치 등 상태 문구 */
.flag-ok { color: var(--ok); font-weight: 700; }
.flag-bad { color: var(--danger); font-weight: 700; }
/* 서술 문구 안 핵심 단어 강조(계표 검증의 줄었다/늘었다 등) */
.emph { font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }

/* 세그먼트 토글(계표 일계/월계/누계 등 화면 전환) */
.seg { display: inline-flex; border: 1px solid var(--gray-2); border-radius: 6px; overflow: hidden; }
.seg a {
    padding: 7px 12px; font-size: 13px; color: var(--gray-6);
    text-decoration: none; border-left: 1px solid var(--gray-2); white-space: nowrap;
}
.seg a:first-child { border-left: 0; }
.seg a:hover { background: var(--gray-0); }
.seg a.on { background: var(--accent-subtle); color: var(--accent); font-weight: 600; }
/* .seg 를 button 으로도(은행 처리상태 탭) */
.seg button { padding: 7px 14px; font: inherit; font-size: 13px; color: var(--gray-6);
    background: transparent; border: 0; border-left: 1px solid var(--gray-2);
    white-space: nowrap; cursor: pointer; }
.seg button:first-child { border-left: 0; }
.seg button:hover { background: var(--gray-0); }
.seg button.on { background: var(--accent-subtle); color: var(--accent); font-weight: 600; }
.seg button b { font-weight: 800; }
.bank-tabs { margin: 0 0 16px; }
/* 라운드 박스형 탭(08-05 수석 선택, 은행내역 상태 탭) — 테두리·칸막이 없이
   버튼 하나하나가 둥근 상자. 지금 탭만 연청색 배경으로 채운다. */
.seg.tabs { border: 0; border-radius: 0; overflow: visible; gap: 4px; }
.seg.tabs button { border: 0; border-radius: 8px; padding: 8px 16px; }
/* 탭 아이콘 — 아래 작업 버튼과 같은 기호를 쓴다(⊘=제외·✓=분개 완료, ○=아직 할 일).
   색은 표 안 상태 칩과 같은 뜻으로 맞춘다: 대기=주의(호박)·제외=회색(안 하는 것)·
   완료=녹색. 활성/비활성과 무관하게 색을 유지 — 아이콘 색 자체가 상태의 표시다. */
.seg.tabs .ic { font-size: 13px; line-height: 1; margin-right: 5px; }
.seg.tabs button[data-view="pending"] .ic { color: var(--attention); }
.seg.tabs button[data-view="excluded"] .ic { color: var(--gray-5); }
.seg.tabs button[data-view="posted"] .ic { color: var(--ok); }
/* 비활성 탭은 글자가 회색이라 아이콘만 튀지 않게 한 톤 죽인다 */
.seg.tabs button:not(.on) .ic { opacity: .8; }
.seg.tabs button:hover { background: var(--gray-0); color: var(--gray-9); }
.seg.tabs button.on { background: var(--accent-subtle); color: var(--accent);
    font-weight: 700; }

/* 조회 필터 폼(툴바 안 인라인) */
.filter-form { display: flex; gap: 6px; align-items: center; margin: 0; }
.filter-form.wrap { flex-wrap: wrap; }
.filter-form .spacer { flex: 1; }   /* 액션(조회·초기화)을 오른쪽으로 밀어냄 */

/* 테이블 셀·툴바 속 POST 폼 */
.inline-form { margin: 0; display: inline; }

/* 작은 보조 각주 */
.note { color: var(--muted); font-size: 12px; }

/* 넓은 표: 페이지가 아니라 표 안에서만 가로 스크롤 */
.tbl-wrap { overflow-x: auto; }
/* 상자 안 sticky는 상자 기준 — 상단바 오프셋(46px)이 아니라 상자 맨 위에 붙는다 */
.tbl-wrap thead th { top: 0; }

/* 작업대형 그리드(은행내역 등 .page.workbench): 창 대신 표만 내부 스크롤.
   sticky 머리행이 .tbl-wrap(스크롤 조상)에 갇히는 화면 — 상자에 세로 스크롤을
   줘서 머리행을 상자 위에 고정하고, 위 필터·아래 액션 버튼은 항상 보이게 한다. */
/* flex: none — .content의 기본 flex:1(basis 0)이 height를 무시하고 늘어나는 것을 막는다 */
.content:has(.page.workbench) { flex: none; height: calc(100vh - var(--topbar-h)); overflow: auto; }
.page.workbench { height: 100%; display: flex; flex-direction: column; min-height: 0; }
.page.workbench form:has(> .tbl-wrap) { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.page.workbench .tbl-wrap { flex: 1; min-height: 180px; overflow: auto; }

/* 은행내역: 계좌 버튼 그리드·상태 바·행 표시 */
.account-grid { display: grid; grid-template-columns: repeat(3, minmax(180px, 240px)); gap: 8px 16px; margin-bottom: 12px; }
.btn.ctr { text-align: center; }
.toolbar.nowrap-bar { flex-wrap: nowrap; white-space: nowrap; }
.range-inline { display: inline-flex; gap: 4px; align-items: center; white-space: nowrap; }
tr.row-flag > td { background: var(--warn-subtle); }

/* 폭·간격 유틸 */
.w-xs { width: 60px; }
.w-sm { width: 80px; }
.w-md { width: 110px; }
.w-lg { width: 320px; }   /* 목록형 텍스트 입력(배정 제외 등) */
/* 세로형 등록 폼 표의 라벨 열(발주 등록 등) — 인라인 style 금지 규칙의 공용 클래스 */
th.form-th { width: 130px; text-align: left; }
.tbl-narrow { max-width: 520px; }
.mt { margin-top: 14px; }
.mt-sm { margin-top: 8px; }
.tight { margin: 6px 0 0; }
.indent { padding-left: 24px; }
.indent2 { padding-left: 44px; }
/* 본문 중간의 굵은 합계 행(재무상태표 자산총계 등) */
tr.grand > td { border-top: 2px solid var(--rule); background: var(--gray-0); }
/* 블록 안의 소계 행(사업계획 실적의 한계이익 등) — 위 행과 가는 선으로 가른다 */
tr.subtotal > td { border-top: 2px solid var(--gray-3); }  /* = tr.pa-blk 블록 경계선과 같은 색 */
tr.row-strong > td { font-weight: 600; }
.btn.disabled { opacity: .45; cursor: not-allowed; }
.nonfield.warn { background: var(--warn-subtle); color: var(--warn); }

.btn {
    display: inline-block; padding: 7px 14px; border-radius: 6px;
    border: 1px solid var(--gray-2); background: #fff; color: var(--gray-9);
    text-decoration: none; cursor: pointer; font-size: 13px; font-family: inherit;
    white-space: nowrap;  /* 버튼 라벨은 절대 줄바꿈하지 않는다 */
}
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
/* 행 단위 파괴 액션은 .ib-seg .seg.danger로 통일(07-30) — 종전 .btn.danger-outline 폐기 */
.btn:disabled { opacity: .5; cursor: not-allowed; }

/* 기간 이동 위젯 — ◀◀ ◀ [from]~[to] ▶ ▶▶ ⌂당월 «라벨» */
.date-nav { display: inline-flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.date-nav button {
    padding: 4px 8px; border-radius: 6px; font-size: 12px; font-family: inherit;
    border: 1px solid var(--gray-2); background: var(--gray-0); color: var(--gray-6); cursor: pointer;
}
.date-nav button:hover { background: var(--accent-subtle); color: var(--accent); border-color: var(--accent); }
.date-nav select.dn-month {
    margin-left: 6px; padding: 4px 6px; border-radius: 6px; font-size: 12px;
    font-family: inherit; border: 1px solid var(--gray-2); background: var(--gray-0); cursor: pointer;
}
.date-nav .dn-label { color: var(--gray-5); font-size: 12px; white-space: nowrap; }
/* 요일 스팬 폭 예약 — 템플릿이 빈 스팬을 미리 그리고 date.js가 "(화)"만 채운다.
   폭을 안 잡아두면 채워질 때 오른쪽 요소가 밀려 리로드마다 깜박인다. */
.date-nav .date-wd { display: inline-block; min-width: 26px; white-space: nowrap; }

/* ── 조회기간 선택기 팝오버(daterange.js) — .date-nav[data-range-picker] 전용, 분개장 시범.
   내부 버튼은 .date-nav button 규칙(0-1-1)을 .drp 스코프(0-2-0+)로 전량 덮어쓴다 ── */
.date-nav.drp-anchor { position: relative; }
.date-nav button.drp-open.open { background: var(--accent-subtle); border-color: var(--accent); }
/* fixed — .tab-card(overflow:hidden) 안에서 absolute면 상자에 잘린다(08-11 수석 발견).
   좌표는 daterange.js placePopover()가 버튼 위치에서 잡는다. */
.drp {
    position: fixed; z-index: 40; display: none;
    background: #fff; border: 1px solid var(--gray-2); border-radius: 8px;
    box-shadow: 0 8px 24px rgba(31, 35, 40, .15); font-size: 13px;
}
.drp.open { display: flex; flex-direction: column; }
.drp-main { display: flex; }
.drp-presets {
    display: flex; flex-direction: column; gap: 1px;
    border-right: 1px solid var(--gray-2); padding: 10px 8px; min-width: 110px;
}
.drp-presets .pt { font-size: 11px; font-weight: 600; letter-spacing: .5px; color: var(--gray-5); padding: 2px 10px 6px; }
.drp .drp-presets button {
    text-align: left; font-size: 13px; color: var(--gray-9); background: none; border: 0;
    border-radius: 5px; padding: 5px 10px; cursor: pointer; white-space: nowrap;
}
.drp .drp-presets button:hover { background: var(--gray-1); color: var(--gray-9); }
.drp .drp-presets button.on { background: var(--accent-subtle); color: var(--accent); font-weight: 600; }
.drp-cals { display: flex; gap: 18px; padding: 12px 14px 8px; }
.drp-cal-head {
    position: relative; display: flex; align-items: center; justify-content: center;
    height: 26px; margin-bottom: 4px; font-weight: 600;
}
.drp .drp-nav {
    position: absolute; top: 0; width: 26px; height: 26px; padding: 0; border: 0; border-radius: 5px;
    background: none; color: var(--gray-5); font-size: 12px; cursor: pointer;
}
.drp .drp-nav:hover { background: var(--gray-1); color: var(--gray-9); border-color: transparent; }
.drp .drp-nav.prev { left: 0; }
.drp .drp-nav.next { right: 0; }
.drp-grid { display: grid; grid-template-columns: repeat(7, 32px); justify-content: center; }
.drp-grid .dow { text-align: center; font-size: 11px; color: var(--gray-5); padding: 2px 0 4px; }
.drp-grid .dow.sun { color: var(--danger); }
.drp-grid .dow.sat { color: var(--accent); }
/* 📅 안의 [년][월] 고르기(2026-08-05) — bar를 넓히지 않으려고 팝오버 안에 뒀다 */
.drp-ym { display: flex; align-items: center; gap: 4px; padding: 6px 8px 2px; }
.drp-ym .pt { font-size: 11px; color: var(--gray-5); margin-right: 2px; }
.drp-ym select { font-size: 12px; padding: 3px 4px; }

/* 월 달력(월계표) — 12칸 3열. 하루 달력과 같은 결이되 알약 모양(2026-08-05) */
.drp-grid.mgrid { grid-template-columns: repeat(3, 64px); gap: 2px; }
.drp .mon {
    height: 32px; padding: 0; border: 0; background: none;
    font-size: 12.5px; color: var(--gray-9); cursor: pointer; font-variant-numeric: tabular-nums;
}
.drp .mon span {
    display: flex; align-items: center; justify-content: center;
    height: 26px; margin: 3px 4px; border-radius: 13px;
}
.drp .mon:hover span { background: var(--gray-1); }
.drp .mon.today span { box-shadow: inset 0 0 0 1px var(--gray-3); }
.drp .mon.edge span { background: var(--accent); color: #fff; }
/* 연월 범위(손익분기) — 날짜 달력과 같은 띠 문법을 12칸 격자에도(2026-08-11) */
.drp .mon { position: relative; }
.drp .mon.in::before {
    content: ""; position: absolute; z-index: 0; top: 2px; bottom: 2px; left: 0; right: 0;
    background: var(--accent-subtle);
}
.drp .mon span { position: relative; z-index: 1; }

.drp .day {
    position: relative; height: 30px; padding: 0; border: 0; background: none;
    font-size: 12.5px; color: var(--gray-9); cursor: pointer; font-variant-numeric: tabular-nums;
}
.drp .day span {
    position: relative; z-index: 2; display: flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; margin: 2px auto; border-radius: 50%;
}
.drp .day:hover { background: none; }
.drp .day:hover span { background: var(--gray-1); }
.drp .day.out { color: var(--gray-3); }
.drp .day.today span { box-shadow: inset 0 0 0 1px var(--gray-3); }
/* 범위 띠: 셀 전폭으로 이어지는 배경, 양끝은 원형 강조 */
.drp .day.in::before, .drp .day.edge.has-range::before {
    content: ""; position: absolute; z-index: 1; top: 2px; bottom: 2px; left: 0; right: 0;
    background: var(--accent-subtle);
}
.drp .day.edge.start.has-range::before { left: 50%; }
.drp .day.edge.end.has-range::before { right: 50%; }
.drp .day.edge.start.end::before { display: none; }
.drp .day.edge span, .drp .day.edge:hover span { background: var(--accent); color: #fff; font-weight: 600; }
.drp-foot {
    display: flex; align-items: center; gap: 8px;
    border-top: 1px solid var(--gray-2); padding: 9px 14px;
}
.drp-foot .drp-sum { margin-right: auto; color: var(--gray-5); }
.drp-foot .drp-sum b { color: var(--accent); }
.drp .drp-foot .btn { padding: 5px 14px; font-size: 13px; background: #fff; color: var(--gray-9); border: 1px solid var(--gray-2); }
.drp .drp-foot .btn:hover { background: var(--gray-1); }
.drp .drp-foot .btn.primary, .drp .drp-foot .btn.primary:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.drp .drp-foot .btn:disabled { opacity: .45; cursor: not-allowed; }
@media (max-width: 760px) {
    .drp { min-width: min(340px, 94vw); }
    .drp-main { flex-direction: column; }
    .drp-presets { flex-direction: row; flex-wrap: wrap; border-right: 0; border-bottom: 1px solid var(--gray-2); }
    .drp-presets .pt { width: 100%; }
    .drp-cals { flex-direction: column; align-items: center; }
}

/* 2행 필터 폼 — 1행 날짜+액션(조회·초기화·조건저장) / 2행 조건. 행 폭 균형. */
.filter-form.rows { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
.filter-form.rows .frow { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.filter-form.rows .frow .spacer { flex: 1; }   /* 액션을 행 오른쪽으로 밀어냄 */

/* 표 내 찾기(하이라이트) — 필터 아님, 잔액 유지하며 매칭 행만 강조 */
.find-bar { display: inline-flex; gap: 8px; align-items: center; margin: 4px 0 8px; }
tr.find-hit > td { background: var(--warn-subtle); }
/* Enter로 짚은 '지금 이 매칭' = 연청(--accent-subtle) — hover·복귀(row-active)와 같은
   "지금 이 행" 의미라 같은 색을 쓴다(07-31 수석). 노란 매칭들 사이에서 색으로 구분.
   hover(연청)보다 우선해야 하므로 규칙 순서상 뒤에 두고 !important 없이 특이도로 이긴다. */
tbody tr.find-cur > td, tbody tr.find-cur:hover > td { background: var(--accent-subtle); }

/* 저장된 조회조건(즐겨찾기) */
.saved-filters { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.sf-chip {
    display: inline-flex; align-items: center; gap: 6px; padding: 3px 4px 3px 10px;
    border: 1px solid var(--gray-2); border-radius: 999px; background: var(--gray-0); font-size: 12px;
}
.sf-chip .sf-go { cursor: pointer; color: var(--gray-9); text-decoration: none; }
.sf-chip .sf-go:hover { color: var(--accent); }
.sf-chip .sf-del { cursor: pointer; color: var(--gray-5); text-decoration: none; padding: 0 4px; }
.sf-chip .sf-del:hover { color: var(--danger); }
.toolbar { display: flex; gap: 8px; align-items: center; margin-bottom: 14px; }
.toolbar .spacer { flex: 1; }
.toolbar h1 { white-space: nowrap; margin: 0; }

.badge { padding: 2px 8px; border-radius: 999px; font-size: 12px; white-space: nowrap; }
.badge.draft { background: var(--warn-subtle); color: var(--warn); }
.badge.confirmed { background: var(--ok-subtle); color: var(--ok); }
.badge.opening { background: var(--accent-subtle); color: var(--accent); }
.badge.normal { background: var(--gray-1); color: var(--gray-6); }
.badge.deleted { background: var(--danger-subtle); color: var(--danger); }

.form-grid { display: grid; grid-template-columns: 120px 1fr; gap: 10px 14px; max-width: 520px; margin-bottom: 18px; }
/* 안내문을 칸 **옆**에 붙이는 줄 — 그 줄만 한 줄로 유지하고 폼 폭 밖으로 흘려보낸다.
   폼 전체를 넓히면 다른 줄의 배치까지 흐트러진다(2026-08-11 되돌린 시도). */
.form-grid .hint-side { white-space: nowrap; }
/* 매출/매입 입력 — 숫자 칸은 폭을 하나로(수석 지시 08-11). 수량을 기준으로 단가·세액과
   계산 결과 칸(공급가액·합계·원화 단가)까지 맞춰, 원화·수출 어느 모드에서도 줄이 선다. */
.sp-grid input.money,
.sp-grid input[type="number"],
.sp-grid input.calc-out { width: 150px; }
.form-grid label { align-self: center; color: var(--muted); }
input, select {
    padding: 6px 8px; border: 1px solid var(--gray-2); border-radius: 5px;
    font-size: 14px; font-family: inherit;
}
/* 계산 결과 칸(readonly) — 테두리를 지우고 옅은 회색을 깔아 "여기는 채우는 자리가
   아니다"를 색으로 말한다(2026-08-11 수석). 세금계산서 [합계]·매출입 [공급가액/합계] 공용. */
input.calc-out {
    width: 140px; text-align: right; border-color: transparent;
    background: var(--gray-0); font-weight: 600; color: var(--gray-9);
    font-variant-numeric: tabular-nums; cursor: default;
}
table input, table select { font-size: 13px; }
/* 재고수불부 — **월 소계 줄 + 그 달 내역**을 한 표에(2026-08-08 수석 3안).
   계정별원장 문법(전기이월 → 거래 → 차기이월)이고, 달마다 tbody로 묶어 접을 수 있다.
   소계 줄은 표 전체를 가로지르므로 colspan 한 칸에 숫자를 나란히 놓는다. */
tr.mon-sum > th {
    background: var(--gray-0); border-top: 2px solid var(--gray-3);
    text-align: left; font-weight: 600; padding: 6px 8px; cursor: pointer;
}
tr.mon-sum > th:hover { background: var(--accent-subtle); }
.ms-n { margin-left: 16px; font-weight: 400; color: var(--muted); }
/* 숫자는 **자리를 고정**해 달마다 세로로 맞춘다(2026-08-08 수석 — [요약만]에서 소계 줄이
   붙어 서면 자릿수가 들쭉날쭉해 읽기 나쁘다). 6ch = "99,999"가 들어가는 폭
   (2026-08-11 수석 — 본류 편입으로 월 3만 대가 들어와 5자리가 표준이 됐다).
   tabular-nums라 1과 8의 폭이 같아 진짜로 맞아떨어진다. 더 커지면 알아서 늘어난다. */
.ms-n b {
    display: inline-block; min-width: 6ch; text-align: right;
    font-weight: 600; color: var(--gray-9); font-variant-numeric: tabular-nums;
}
.ms-n b.in { color: var(--accent); }
.ms-n b.out { color: var(--orange); }
.ms-n.close b { font-weight: 700; }   /* 기말은 굵기로 세운다 — 글자 크기를 키우면 자리가 어긋난다 */
tbody.folded > tr:not(.mon-sum) { display: none; }   /* 달 접기 — 초기 상태(2026-08-11) */
tbody:not(.folded) > tr.mon-sum .caret::before { content: "▾"; }   /* 펼친 달 표시 */
/* 구간 칸(박스구간·바코드 구간) — 한 칸에 구간이 여럿일 수 있어 **줄바꿈으로 쌓는다**.
   접두(묶음번호·FTEQ+K코드)와 수량은 흐리게, 연번만 또렷하게.
   ⚠ 행 액션용 .ib-seg를 여기 쓰지 말 것 — 그것은 버튼 묶음(inline-flex) 문법이다. */
.rng { display: block; font-variant-numeric: tabular-nums; color: var(--muted); }
/* 구간 = 자연 키 → 클릭 링크 병행 허용(행 상호작용 규칙, 2026-08-11) —
   그 구간만 [시리얼 조회]로. 링크여도 구간 색 문법은 그대로, hover에서만 티를 낸다. */
a.rng { text-decoration: none; }
a.rng:hover { background: var(--accent-subtle); border-radius: 3px; }
.rng + .rng { margin-top: 3px; }
.rng small { margin-left: 6px; }

/* 시작·종료 짚기(2026-08-08 수석 요청) — **박스구간과 바코드 구간에 같은 두 색**을 쓴다.
   같은 색끼리 짝이라 "박스 시작 ↔ 바코드 시작"이 눈으로 이어진다(한 구간을 두 가지
   표기로 적은 것이므로, 두 칸을 잇는 것이 이 표의 핵심이다).
   ⚠ 상태 칩 색 문법(입금 청·출금 주황…)과 뜻이 겹치지 않는다 — 여기 색은 상태가 아니라
     **구간 안의 위치**다. 그래서 칩이 아니라 밑줄로 칠해 배지처럼 보이지 않게 했다.
   ⚠ 색만으로 뜻을 지지 않는다(색약 대응) — 순서와 `~`가 이미 시작·끝을 말한다. */
.rng-a, .rng-b { font-weight: 600; padding-bottom: 1px; }
.rng-a { color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent-subtle); }
.rng-b { color: var(--orange); box-shadow: inset 0 -2px 0 var(--orange-subtle); }
input:focus-visible, select:focus-visible, .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* 일계표 상세 펼침 — 계정 행 클릭 시 전표 라인(전표번호·적요·금액)이 아래로 열린다 */
tr.expandable { cursor: pointer; }
.caret { display: inline-block; width: 13px; color: var(--muted); font-size: 11px; }
.caret::before { content: "▸"; }
tr.expandable.open .caret::before { content: "▾"; }
/* 원장 멀티계정 접힘/펼침(재설계 E): 계정 제목 클릭 = 그 원장 토글 */
/* ── 손익분기 도표(CVP, 07-31) — 서버가 좌표를 계산한 인라인 SVG ──
   색: 매출액=accent(파랑) / 총원가=warn(앰버) — 색맹 대비 ΔE 28.6(dataviz 검증기 통과),
   색만으로 구분하지 않도록 범례 + 선 끝 직접 라벨을 함께 단다. 고정비는 회색 점선(참조선). */
figure.cvp { margin: 0 0 16px; max-width: 860px; }
figure.cvp svg { width: 100%; height: auto; }
figure.cvp figcaption {
    display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
    font-size: 12px; color: var(--gray-6); margin-bottom: 6px;
}
figure.cvp .lg { display: inline-flex; align-items: center; gap: 5px; }
figure.cvp .lg::before { content: ""; width: 14px; height: 2px; border-radius: 1px; background: currentColor; }
figure.cvp .lg-sales { color: var(--accent); }
figure.cvp .lg-cost { color: var(--warn); }
figure.cvp .lg-fixed { color: var(--gray-5); }
figure.cvp .lg-fixed::before { height: 0; border-top: 2px dashed currentColor; }

.cvp-grid { stroke: var(--gray-2); stroke-width: 1; }
.cvp-axis { stroke: var(--gray-5); stroke-width: 1; }
.cvp-line { fill: none; stroke-width: 2; stroke-linecap: round; }
.cvp-sales { stroke: var(--accent); }
.cvp-cost { stroke: var(--warn); }
.cvp-fixed { stroke: var(--gray-5); stroke-width: 1.5; stroke-dasharray: 5 4; }
.cvp-bepline { stroke: var(--gray-3); stroke-width: 1; stroke-dasharray: 3 3; }
.cvp-bep { fill: var(--gray-9); stroke: #fff; stroke-width: 2; }   /* 겹친 선 위 2px 흰 링 */
/* 선 위에 겹쳐도 읽히도록 흰 헤일로(겹친 마크에 2px 흰 링을 두는 규칙과 같은 취지) */
.cvp-beplabel {
    fill: var(--gray-9); font-size: 12px; font-weight: 600; text-anchor: middle;
    paint-order: stroke; stroke: #fff; stroke-width: 3px; stroke-linejoin: round;
}
.cvp-tick { fill: var(--gray-6); font-size: 11px; }
.cvp-tick.r { text-anchor: end; }
.cvp-tick.c { text-anchor: middle; }
.cvp-endlabel { font-size: 12px; font-weight: 600; paint-order: stroke; stroke: #fff; stroke-width: 3px; stroke-linejoin: round; }
.cvp-endlabel.s { fill: var(--accent); }
.cvp-endlabel.c { fill: var(--warn); }
.cvp-endlabel.f { fill: var(--gray-6); font-weight: 400; }

/* 자금출납장 = 예금현황 요약(Part2) + 계좌 내역(Part3) 통합(08-02).
   요약 행은 '선택'이라 연청(row-active와 같은 '지금 이 행' 의미) — 새 색을 만들지 않는다. */
.cb-summary { margin-bottom: 6px; }
a.cb-jump { margin-left: 4px; text-decoration: none; opacity: .55; }
a.cb-jump:hover { opacity: 1; }
.cb-summary tbody tr.cb-pick, .cb-summary tfoot tr.cb-pick { cursor: pointer; }
.cb-summary tr.cb-pick:hover > td { background: var(--accent-subtle); }
.cb-summary tr.cb-pick.row-active > td { background: var(--accent-subtle); font-weight: 600; }

/* 한 화면 안의 절 제목(손익분기분석의 실적표·분석표·예상 손익) — 표 사이 구분 */
h2.sec-title { border-bottom: 1px solid var(--gray-2); padding-bottom: 4px; }
h2.sec-title small { font-weight: 400; font-size: 12px; margin-left: 6px; }

h2.ledger-fold { cursor: pointer; user-select: none; }
h2.ledger-fold:hover { color: var(--accent); }
h2.ledger-fold .caret::before { content: "▾"; }
h2.ledger-fold.closed .caret::before { content: "▸"; }
h2.ledger-fold small { font-weight: 400; font-size: 13px; color: var(--gray-5); }
tr.detail-row > td {
    font-size: 12px; color: var(--gray-6); background: var(--bg-soft);
    padding-top: 3px; padding-bottom: 3px;
}
tr.detail-row .detail-label { text-align: left; padding-left: 20px; white-space: nowrap; }
tr.detail-row .detail-label::before { content: "\2022  "; color: var(--gray-3); }
tr.detail-row .detail-label.muted::before { content: ""; }  /* "외 N건" 안내 행은 제외 */

/* 은행내역 분개됨 탭 — 행 hover 시 전표 내용 툴팁(차/대·계정·금액 열 정렬).
   position:fixed + top은 템플릿 스크립트가 행 좌표(getBoundingClientRect)로 지정 —
   표 안쪽 스크롤(.tbl-wrap)과 무관하게 hover한 행 바로 아래에 뜬다 */
.entry-tip {
    display: none; position: fixed; right: 16px; z-index: 40;
    background: #fff; border: 1px solid var(--gray-2); border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12); padding: 4px 6px;
}
tr:hover > td > .entry-tip { display: block; }
.entry-tip table { border-collapse: collapse; }
.entry-tip td { padding: 2px 8px; font-size: 12px; border: 0; white-space: nowrap; }
.entry-tip td + td { border-left: 1px solid var(--gray-1); }
.entry-tip .num { text-align: right; }

/* 날짜 약식 입력(date.js) — 정규화 실패 시 적색, 정규화 후 요일 병기 */
input.date-smart { width: 110px; }
input.date-smart:invalid { border-color: var(--danger); background: var(--danger-subtle); }
/* 급여대장 [상여] — 4대보험 칸 접기(2026-09-10 수석). 상여에는 보통 보험료를 떼지 않는다.
   숨기면 '공제부분' 묶음이 소득세·주민세 둘만 남으므로 세로 구분선을 소득세 쪽으로 옮긴다. */
/* [상여] 4대보험 접기(payroll-hide-ins, 2026-09-10)는 폐기 — 공제 전 열 상시 표시(09-17 수석) */
.payroll-insopt { gap: 8px; }
.payroll-insopt label { display: inline-flex; align-items: center; gap: 4px; }
.payroll-tabs { gap: 6px; }

/* 자금일보 마감 시각 지정(2026-09-09 수석) — 툴바 한 줄에 들어가게 좁게 */
.dcr-closetime { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.dcr-closetime input.date-smart { width: 104px; }
.dcr-closetime input.time-smart { width: 88px; }
.date-wd { margin-left: 4px; color: var(--muted); }
.errorlist { color: var(--danger); list-style: none; padding: 0; margin: 4px 0; }
.nonfield { background: var(--danger-subtle); color: var(--danger); padding: 9px 12px; border-radius: 6px; margin-bottom: 12px; }
/* 맨몸 .nonfield는 **폼 오류용 빨강**이다. 같은 상자 모양으로 결과·경과를 알릴 때는
   반드시 색을 지정할 것 — 안 그러면 "배정 완료"가 에러처럼 보인다(2026-08-12). */
/* 손으로 할 일 목록(⑥ 포털 구획) — 번호를 매기지 않는다(단계 번호와 충돌). */
.kt-todo { list-style: none; margin: 4px 0 0; padding: 0; line-height: 1.9; }
.kt-todo li::before { content: "·"; color: var(--gray-5); margin-right: 7px; }

.nonfield.ok   { background: var(--ok-subtle); color: var(--ok); }
.nonfield.info { background: var(--gray-1); color: var(--gray-9); }

/* ── 로그인(전용 페이지 — 셸 없음, admin/login.html) ── */
body.login-page { background: var(--gray-0); }
.login-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; }
.login-card {
    width: 340px; background: #fff; border: 1px solid var(--gray-2);
    border-top: 4px solid var(--navy); border-radius: 10px; padding: 26px 28px 24px;
}
.login-brand { display: flex; align-items: center; gap: 9px; font-size: 21px; font-weight: 700; letter-spacing: .02em; }
.login-brand .mark { width: 13px; height: 13px; border-radius: 3px; background: var(--navy); flex: 0 0 auto; }
.login-cap { margin: 3px 0 20px; font-size: 12px; color: var(--gray-5); }
.login-card label { display: block; font-size: 12px; font-weight: 600; color: var(--gray-6); margin: 12px 0 4px; }
.login-card input[type=text], .login-card input[type=password] { width: 100%; }
.login-btn { width: 100%; margin-top: 20px; padding: 9px; font-size: 14px; }

.lines td, .lines th { padding: 5px 6px; }
/* 분개장: 전표 그룹을 실선 대신 배경 교대(zebra)로 구분 — 가로선 없음, 줄 높이 유지.
   짝수 전표만 옅은 회색, 홀수는 흰색. hover(entry-hover)·선택(row-active)이 특이도상 우선. */
/* row-alt: 단일 행 표(매출입·은행)의 짝수 행 교대 — 같은 문법·같은 색 */
tr.egrp-alt > td, tr.row-alt > td { background: var(--gray-0); }
/* 얼룩무늬가 hover·복귀 강조를 덮지 않게(2026-08-06 발견) — 이 규칙이 뒤에 있어
   짝수 행에서는 연청 강조가 회색에 묻혔다. '지금 이 행'이 얼룩보다 우선한다. */
tbody tr[data-rowkey].row-alt:hover > td,
tbody tr[data-rowkey].row-alt.row-active > td { background: var(--accent-subtle); }
/* 상태 배경(제외 제안 앰버)이 교대색보다 우선 — 정의 순서상 뒤에 온 row-alt에 안 덮이게 */
tr.row-alt.row-flag > td { background: var(--warn-subtle); }
.lines input[type=number] { width: 110px; text-align: right; }
.lines select { max-width: 170px; }

/* 세금계산서 첨부(전표 상세) — 입력 줄이 표의 마지막 행이라 열은 표가 맞춘다.
   표 밖 flex로 늘어놓았을 때는 칸과 머리글이 어긋났다(2026-08-11 수석). */
.tax-add-row > td { padding: 6px 8px; vertical-align: middle; }
.tax-add-row input.money { width: 108px; text-align: right; }
.tax-add-row input.date-smart { width: 110px; }
.tax-add-row input[name="approval_no"], .tax-add-row input[name="remark"] { width: 140px; }
.tax-invoices .acombo input { width: 190px; }
.tax-add-row input#tax-total { width: 108px; }
.totals { font-weight: 700; }
.totals.balanced { color: var(--ok); }
.totals.unbalanced { color: var(--danger); }
.muted { color: var(--muted); }

/* 은행내역 이미지 붙여넣기(OCR) 미리보기 모달 (bank_paste.js) */
.ocr-modal { position: fixed; inset: 0; z-index: 100; background: rgba(31,35,40,.45);
    display: flex; align-items: flex-start; justify-content: center; padding: 40px 16px; overflow: auto; }
/* hidden 속성이 display:flex를 이기도록(특이도 상향) — 없으면 모달이 항상 보임 */
.ocr-modal[hidden] { display: none; }
.ocr-dialog { background: #fff; border: 1px solid var(--gray-2); border-radius: 10px;
    box-shadow: 0 12px 40px rgba(0,0,0,.22); padding: 14px 16px; width: min(920px, 96vw); }
/* 패널 1: 제목 바(제목 크게 + 우측 상단 버튼) */
.ocr-titlebar { display: flex; align-items: center; gap: 8px;
    border-bottom: 1px solid var(--gray-2); padding-bottom: 10px; margin-bottom: 12px; }
.ocr-titlebar h2 { margin: 0; font-size: 20px; }   /* [은행내역 가져오기] h1과 동일 */
.ocr-titlebar .spacer { flex: 1; }                 /* 버튼을 우측 최상단으로 밀어냄 */
/* 패널 2·3: 카드형 구획 */
.ocr-panel { border: 1px solid var(--gray-2); border-radius: 8px; padding: 12px; margin-bottom: 12px; }
.ocr-panel:last-child { margin-bottom: 0; }
#ocr-status { margin: 0; }   /* 상태문 아래 빈 여백 제거 */
/* 패널 3 표: 헤더 고정 + 5행 높이 세로 스크롤 */
.ocr-tbl-scroll { max-height: 224px; overflow: auto; border: 1px solid var(--gray-1); border-radius: 6px; }
.ocr-tbl-scroll thead th { position: sticky; top: 0; z-index: 2; background: var(--gray-0);
    box-shadow: inset 0 -2px 0 var(--rule); }
#ocr-paste-zone { border: 2px dashed var(--gray-3); border-radius: 8px; background: var(--gray-0);
    padding: 22px; text-align: center; cursor: text; outline: none; }
#ocr-paste-zone:focus { border-color: var(--accent); background: var(--accent-subtle); }
/* 붙여넣기 처리 단계 표시(인식→파싱→처리결과→잔액대조) — 공용 .chip 사용 */
.ocr-steps { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 14px 0; }
.ocr-steps[hidden] { display: none; }   /* hidden 속성이 display:flex를 이기도록 */
.ocr-steps .chip { font-size: 13px; padding: 3px 10px; }   /* 단계 칩 조금 크게 */
.ocr-steps .sep { color: var(--gray-3); }
/* 배지 바: 배지(좌) + 계좌 지정 dropdown(우, 같은 줄), 아래 표와 구분선 */
.ocr-badgebar { display: flex; align-items: center; gap: 12px; flex-wrap: nowrap;
    border-bottom: 1px solid var(--gray-2); padding-bottom: 10px; margin-bottom: 10px; }
#ocr-account-row { margin-left: auto; flex: 0 0 auto; }   /* 배지 우측·같은 줄 */
#ocr-account-row[hidden] { display: none; }
/* 계좌 배지(붙여넣기 즉시 누적, 클릭=그 계좌 재편집) — 일반 chip보다 크게 */
.ocr-badges { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; flex: 1 1 auto; min-width: 0; }
.ocr-badges .chip { cursor: pointer; font-size: 14px; padding: 5px 14px; border-radius: 14px; }
.ocr-badges .chip.in { box-shadow: inset 0 0 0 1.5px currentColor; }   /* 활성 계좌 강조 */
.ocr-badges .chip .bx { margin-left: 8px; cursor: pointer; opacity: .55; font-weight: 700; }
.ocr-badges .chip .bx:hover { opacity: 1; color: var(--danger); }
tr.ocr-warn > td { background: var(--danger-subtle); }
#ocr-rows input { width: 100%; box-sizing: border-box; }
#ocr-rows input.w-date { min-width: 92px; }
#ocr-rows input.w-time { min-width: 70px; }
#ocr-rows input.num { text-align: right; }
#ocr-rows input[readonly] { background: var(--gray-0); color: var(--gray-6); cursor: default; }   /* 날짜·시간·잔액=수정 금지 */

/* print-only elements (see print.css) are hidden on screen */
.print-only { display: none; }

/* dates, entry numbers: never wrap mid-value */
td.nowrap, th.nowrap, span.nowrap, small.nowrap { white-space: nowrap; }

/* 계정 자동완성 콤보(account_combo.js) — 원본 select는 숨기고 검색 입력으로 대체 */
select.acombo-src { display: none; }
.acombo { position: relative; display: inline-block; }
.acombo input { width: 240px; }              /* 일반 폼(매출입·자금·원장) */
.lines .acombo input { width: 170px; }       /* 그리드 행(은행 라인) */
.bank-panel .acombo-partner input { width: 130px; }  /* 은행내역 거래처 — 계정보다 짧게(09-21 수석) */
/* 거래처 제안 목록은 가장 긴 상호(영문 병기 등)만큼 통째로 넓어진다(실측 539px vs 계정 220px,
   09-22 수석 "콤보가 너무 크다"의 실체). 은행 화면은 최대 폭을 두고 넘치는 글자는 말줄임. */
.bank-panel .acombo-partner .acombo-list { max-width: 320px; }
.bank-panel .acombo-partner .acombo-list li { overflow: hidden; text-overflow: ellipsis; }
.journal-lines .acombo input { width: 240px; }  /* 전표 라인: 계정과목 5글자(≈70px) 확대 */
/* 숫자 칸은 오른쪽 정렬 — 그리드·상세 칸과 같은 문법(2026-09-05 수석) */
.journal-lines input.money { text-align: right; }
/* 목록에 없는 이름을 친 상태(data-allow-new) — 저장 시 새로 등록된다는 표시.
   경고가 아니라 예고이므로 앰버 계열로 두되 테두리만 바꾼다(2026-08-11). */
.acombo input.acombo-new { border-color: var(--warn); background: var(--warn-subtle); }
/* 칸 **옆**에 뜬다 — 아래에 두면 줄이 밀려 다른 칸과 어긋난다(2026-08-11 수석) */
.acombo-new-note { margin-left: 8px; color: var(--warn); font-size: 12px; white-space: nowrap; }
.acombo-list {
    position: absolute; z-index: 30; left: 0; top: 100%; margin: 2px 0 0; padding: 0;
    list-style: none; background: #fff; border: 1px solid var(--gray-2); border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .12); max-height: 260px; overflow-y: auto;
    min-width: 220px; white-space: nowrap;
}
/* 제안 행 문법은 헤더 검색 팝오버(.hpop .hsug)와 공유 — 어디서든 같은 폰트·hover·커서 */
.acombo-list li, .hpop .hsug li { padding: 5px 10px; cursor: pointer; font-size: 13px; }
.acombo-list li:hover, .hpop .hsug li:hover { background: var(--accent-subtle); }
/* 키보드 커서 위치는 반전(진한 배경+흰 글자)으로 뚜렷하게 */
.acombo-list li.active, .hpop .hsug li.active { background: var(--accent); color: #fff; }
/* 보조 단서(거래처 제안의 대표자) — 오른쪽에 흐리게. 고르는 값은 앞의 이름뿐.
   콤보(전표 입력)와 헤더 검색 팝오버(분개장·매출/매입장) 양쪽에서 같은 모양 */
.acombo-list li .sub, .hpop .hsug li .sub { margin-left: 10px; color: var(--gray-5); font-size: 12px; }
.acombo-list li.active .sub, .hpop .hsug li.active .sub { color: rgba(255, 255, 255, .8); }

/* 급여대장 입력 그리드 — 숫자칸 우측 정렬, 자동 계산칸은 옅은 배경으로 구분 */
.payroll-grid input.pay-num { width: 78px; text-align: right; }
.payroll-grid input.pay-day { width: 40px; text-align: right; }
.payroll-grid td.calc { background: var(--gray-0); }
/* NO·직책·성명 3열은 가로 스크롤에 왼쪽 고정 — 스크롤 중에도 누구 행인지 유지.
   left 오프셋(--fz2/--fz3)은 payroll_form.js가 실제 렌더 폭으로 계산.
   collapse 보더는 sticky를 따라오지 않으므로 고정 경계선은 inset shadow(머리행 관행). */
.payroll-grid thead tr:first-child th:nth-child(-n+3),
.payroll-grid tbody td:nth-child(-n+3),
.payroll-grid tfoot td:first-child { position: sticky; }
.payroll-grid thead tr:first-child th:nth-child(-n+3) { z-index: 3; }
.payroll-grid tbody td:nth-child(-n+3) { z-index: 1; background: #fff; white-space: nowrap; }
.payroll-grid tbody tr:hover > td:nth-child(-n+3) { background: var(--gray-0); }
.payroll-grid tfoot td:first-child { z-index: 1; }
.payroll-grid thead tr:first-child th:nth-child(1),
.payroll-grid tbody td:nth-child(1),
.payroll-grid tfoot td:first-child { left: 0; }
.payroll-grid thead tr:first-child th:nth-child(2),
.payroll-grid tbody td:nth-child(2) { left: var(--fz2, 40px); }
.payroll-grid thead tr:first-child th:nth-child(3),
.payroll-grid tbody td:nth-child(3) { left: var(--fz3, 100px); }
.payroll-note { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }
.payroll-note textarea { font: inherit; padding: 6px 8px; border: 1px solid var(--gray-2); border-radius: 4px; }
/* 급여대장과 그 아래(정산·미리보기)를 가르는 쌍선(=) — 급여대장 아님을 명시 */
.payroll-sep {
    border-top: 3px double var(--gray-5); margin: 20px 0 12px; text-align: center;
}
.payroll-sep span {
    display: inline-block; transform: translateY(-50%); padding: 0 12px;
    background: #fff; font-size: 12px; font-weight: 600; color: var(--gray-5);
}
/* 정산표·미리보기 타이틀은 급여대장 제목(h1)과 같은 크기 */
.payroll-insurance .ci-head, .payroll-preview .ci-head { font-size: 20px; font-weight: 700; color: var(--gray-9); margin: 0 0 8px; }
.payroll-insurance .ci-head small, .payroll-preview .ci-head small { font-size: 12px; font-weight: 400; }
.payroll-insurance .ins-table, .payroll-preview .preview-table { width: auto; font-size: 13px; }
.payroll-preview .preview-table { min-width: 620px; }
.payroll-insurance .ins-table th, .payroll-insurance .ins-table td,
.payroll-preview .preview-table th, .payroll-preview .preview-table td { border: 1px solid var(--gray-2); padding: 5px 10px; }
.payroll-insurance .ins-table th, .payroll-insurance .ins-table td { text-align: right; }
.payroll-insurance .ins-table thead th, .payroll-insurance .ins-table tbody th { text-align: center; background: var(--gray-0); font-weight: 600; }
.payroll-insurance input.ci-num { width: 96px; text-align: right; font-size: 13px; }
.payroll-insurance .ins-sum td, .payroll-insurance .ins-sum th { background: var(--gray-0); font-weight: 700; }
.payroll-insurance [data-emp-total], .payroll-insurance [data-comp-total], .payroll-insurance [data-grand-total] { background: var(--gray-0); font-weight: 700; }
/* 건강·요양은 통합건강 내역(참고) — 연하게 */
.payroll-insurance .ins-table .sub { color: var(--gray-5); background: var(--gray-0); }
.payroll-preview { margin-top: 4px; }
.payroll-preview .preview-table tfoot .ins-sum td { background: var(--gray-0); font-weight: 700; }
.login-version { margin: 14px 0 0; text-align: center; font-size: 11px; color: var(--gray-5); }
/* 전표 엑셀 붙여넣기: 계정 미확인 칸 표시(journal_form.js) — 선택하면 해제 */
.paste-miss .acombo input { border-color: var(--danger); background: var(--danger-subtle); }
.payroll-body { border: 0; margin: 0; padding: 0; min-width: 0; }

/* 페이지 로딩 표시(loading.js) — 상단 중앙 토스트 */
.load-indicator {
    position: fixed; top: 14px; left: 50%;
    transform: translateX(-50%) translateY(-10px);
    z-index: 9999; display: none; align-items: center; gap: 8px;
    padding: 8px 16px; border-radius: 999px;
    background: var(--navy, #1f2d4d); color: #fff;
    font-size: 13px; font-weight: 600;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .22);
    opacity: 0; transition: opacity .16s ease, transform .16s ease;
}
.load-indicator.on { display: flex; opacity: 1; transform: translateX(-50%) translateY(0); }
.load-spinner {
    width: 14px; height: 14px; border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, .35); border-top-color: #fff;
    animation: load-spin .7s linear infinite;
}
@keyframes load-spin { to { transform: rotate(360deg); } }
@media print { .load-indicator { display: none !important; } }

/* 오래 걸리는 생성 버튼의 진행 표시(KT 업로드 파일 ZIP ≈ 10초, 2026-08-19 대표).
   전역 오버레이(load-indicator)는 fetch로 받는 화면에서 끌 신호가 없어 못 쓴다 —
   그래서 표시를 **버튼과 그 자리**에 둔다. 진행률을 모르므로 퍼센트를 지어내지 않고
   불확정 막대 + 경과 초로 "돌고 있다"만 정직하게 보인다. */
.btn.busy { display: inline-flex; align-items: center; gap: 7px; }
.btn.busy .load-spinner { width: 13px; height: 13px; }
.prog { height: 4px; margin: 8px 0 6px; border-radius: 999px;
        background: var(--gray-1); overflow: hidden; }
.prog i { display: block; height: 100%; width: 38%; border-radius: 999px;
          background: var(--accent); animation: prog-slide 1.15s ease-in-out infinite; }
@keyframes prog-slide { from { margin-left: -38%; } to { margin-left: 100%; } }
@media print { .prog { display: none; } }

/* KT ⑤ 오더바코드 — 줄을 방향으로 가른다(윗줄=들여옴, 아랫줄=내보냄+결과, 08-19 대표).
   한 자리에서 방향이 두 번 바뀌는 곳이라, 한 줄에 섞으면 어느 칩이 무엇에 걸리는지 흐려진다. */
.kt-order-rows { display: flex; flex-direction: column; gap: 9px; margin: 10px 0 4px; }
.kt-order-rows > div { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.kt-order-rows label { display: inline-flex; align-items: center; gap: 8px; }
.kt-order-msg:empty { display: none; }
.kt-order-msg { color: var(--muted); font-size: 12px;
                background: var(--gray-1); border-radius: 6px; padding: 5px 10px; }
/* 진행 막대는 **일을 시키는 줄 바로 아래**에 눕는다 — flex 줄바꿈으로 제 줄을 차지한다 */
.prog-slot { flex: 1 0 100%; }
.prog-slot:empty { display: none; }
/* 읽은 결과는 **흰 바탕 카드**로 띄운다(2026-08-19 대표). ⑤는 지금 단계라 구획 전체가
   연청색(.kstep-now)인데, 그 위에 표가 바로 얹히면 표가 읽기 어렵다 — 색은 "지금 여기"를
   가리키는 구획의 몫으로 두고, 표는 제 바탕을 갖는다. */
#kt-order-preview:not([hidden]) {
    background: #fff; border: 1px solid var(--gray-2);
    border-radius: 8px; padding: 10px 14px;
}
#kt-order-preview table { width: 100%; }
#kt-order-preview h4 { margin: 2px 0 6px; }
@media print { .kt-order-rows { display: none; } }

/* ── 은행내역 3단 화면(처리 대기 / 처리 제외 / 처리 완료) ── */
/* 탭 카드(08-05 수석): 탭 줄 + 계좌 상태 줄 + 지금 탭의 표를 한 상자에.
   탭이 '이 상자의 내용을 갈아 끼우는 손잡이'라는 관계가 눈에 보인다.
   테두리는 이 상자가 하나만 가지고, 안의 패널들은 내려놓는다. */
.tab-card { border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
    margin-bottom: 20px; background: #fff; }
/* 상자 맨 윗줄 = 탭 + 계좌(이 상자 전체의 스코프) */
.bank-scope { display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap;
    margin: 0; padding: 6px 10px; border: 0; border-bottom: 1px solid var(--line); }
/* 한 줄 안: 왼쪽 탭 + 오른쪽 계좌 스코프(적재범위는 오른끝) */
.bank-scope-form { display: flex; align-items: center; gap: 8px 14px; flex: 1;
    min-width: 0; flex-wrap: wrap; }
.bank-scope .bank-tabs { margin: 0; }
.bank-scope .lbl { font-size: 12px; font-weight: 700; color: var(--gray-6); }
select.bank-acct { height: 32px; min-width: 0; width: 160px; padding: 0 10px;
    border: 1px solid var(--gray-2); border-radius: 6px; background: #fff;
    font: inherit; font-size: 13px; font-weight: 600; color: var(--gray-9); }
/* 재고 [모델] 콤보(2026-08-28) — 은행 [계좌] 콤보와 같은 결. 라벨이 "모델명 ·수량"이라
   `.w-md`(110px)로는 잘린다(실측 최장 20자). 모델명이 길어질 수 있어 넉넉히 두되
   `max-width`로 도구줄을 밀지 않게 한다. */
select.model-pick { height: 32px; min-width: 0; width: 240px; max-width: 40vw;
    padding: 0 10px; border: 1px solid var(--gray-2); border-radius: 6px;
    background: #fff; font: inherit; font-size: 13px; font-weight: 600;
    color: var(--gray-9); }
.bank-sum { font-size: 12.5px; color: var(--gray-6); }
.bank-sum b { color: var(--gray-9); }
/* 잔액 대조 줄 — 은행 거래후잔액 ↔ 장부잔액(정본 docs/workspace-launcher-design.md §7.2).
   계좌를 지정했을 때만 계좌줄 바로 아래에 뜬다. 차이가 [처리 대기]로 설명되지 않으면 경고색 */
.bank-recon { display: flex; align-items: center; gap: 6px 18px; flex-wrap: wrap;
    margin: 0; padding: 7px 14px; border: 0; border-bottom: 1px solid var(--line);
    background: #fff; font-size: 13px; }
.bank-recon .lbl { font-size: 12px; font-weight: 700; color: var(--gray-6); }
.bank-recon .ri { display: inline-flex; align-items: baseline; gap: 6px; }
.bank-recon .ri i { font-style: normal; font-size: 12px; color: var(--gray-6); }
.bank-recon .ri b { font-weight: 700; color: var(--gray-9); font-variant-numeric: tabular-nums; }
.bank-recon .verdict { margin-left: auto; font-weight: 700; }
.bank-recon .verdict.ok { color: var(--ok); }
.bank-recon .verdict.pend { color: var(--gray-6); font-weight: 600; }
.bank-recon .verdict.bad { color: var(--danger); }
.bank-recon.warn { border-bottom-color: var(--warn); background: var(--warn-subtle); }
/* 잔액 흐름 검사 — 은행이 준 잔액이 이어지지 않는 날(= 안 들어온 거래가 있는 날).
   대조 줄 바로 아래, 평소엔 접혀 있고 문제가 있을 때만 나타난다. */
.bank-chain { margin: 0; border: 0; border-bottom: 1px solid var(--warn);
    background: var(--warn-subtle); font-size: 13px; }
.bank-chain > summary { padding: 7px 14px; cursor: pointer; font-weight: 700; color: var(--gray-9); }
.bank-chain > summary .muted { font-weight: 400; }
.bank-chain .chain-body { padding: 0 14px 12px; }
.bank-chain .note { margin: 0 0 8px; font-size: 12px; color: var(--gray-6); }
.bank-chain .tbl-wrap { background: #fff; border: 1px solid var(--line); border-radius: 6px; }
.bank-chain td.gap { font-weight: 700; color: var(--danger); }
/* 패널은 상자 안에서 자리만 바꾼다 — 테두리·여백은 .bank-box가 가진다 */
.bank-panel { border: 0; border-radius: 0; margin: 0; }
/* 패널 머리(제목+건수 배지)는 삭제(08-05) — 지금 탭이 그 말을 그대로 하고 있었다.
   처리 완료의 '조회 건수'는 탭 숫자를 [조회/전체]로 바꿔 살렸다. 표 한 줄만큼 이득. */
/* 탭으로 한 표만 보이므로 화면 높이에 맞춰 크게(액션바는 아래 유지) */
/* 표 높이: 상단(제목·안내·탭·계좌줄)+하단(페이지줄) 크롬을 빼고 계산 —
   창 스크롤과 표 스크롤이 동시에 생기지 않게(수석 지적 07-27) */
/* 375 → 320(08-05): 위에서 걷어낸 크롬만큼 표에 돌려준다 — 패널 머리 37px +
   탭 줄과 상자 사이 여백 12px + 탭 줄 안팎 여백 5px ≈ 54px. 이 값을 안 줄이면
   아낀 공간이 표가 아니라 페이지 아래 빈자리로 간다. (상수 자체의 한계는 여전 —
   계좌를 고르면 뜨는 대조·끊김 줄은 이 값에 안 들어 있다. 대기 데이터 쌓인 뒤 재검토) */
.bank-scroll { max-height: calc(100vh - 320px); min-height: 260px; overflow: auto; }
/* 행 숨통: 은행 표는 입력 콤보·칩이 빽빽해 어지럽다는 피드백 — 상하 여백 확대 */
.bank-panel .lines td { padding-top: 8px; padding-bottom: 8px; }
/* 패널 안 액션바는 표 아래 흐름 배치(상단 sticky 해제).
   높이는 고정 40px이 아니라 위아래 같은 여백으로 — 고정 높이 + 아래 margin 8px이라
   버튼이 위로 쏠려 보였다(08-05 수석 지적). margin 0 = 패널 바닥에 딱 붙는 띠. */
.sel-bar.flow { position: static; top: auto; z-index: auto; border-top: 1px solid var(--line);
    border-bottom: 0; background: var(--gray-0);
    height: auto; min-height: 44px; padding: 8px 12px; margin-bottom: 0; }
.bank-panel .empty-row { padding: 16px 14px; color: var(--gray-5); }
/* 도구 줄은 흰 배경 — 표 머리글(회색 띠)과 무게가 같으면 둘이 한 덩어리로 읽힌다 */
.bank-filter { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 10px 14px; border-bottom: 1px solid var(--line); background: #fff; }
.bank-search { height: 30px; border: 1px solid var(--gray-2); border-radius: 6px;
    padding: 0 10px; font: inherit; font-size: 13px; min-width: 160px; }
.bank-pager { display: flex; align-items: center; gap: 6px; padding: 8px 14px; flex-wrap: wrap; }
/* 알약형 페이지네이션(은행 처리대기·완료) */
.pagination { display: inline-flex; align-items: center; gap: 3px; flex-wrap: wrap; }
.pagination .pg { display: inline-flex; align-items: center; justify-content: center;
    min-width: 28px; height: 28px; padding: 0 7px; border: 1px solid var(--gray-2);
    border-radius: 6px; background: #fff; color: var(--gray-9); font-size: 12.5px;
    font-weight: 600; text-decoration: none; font-variant-numeric: tabular-nums; }
.pagination a.pg:hover { background: var(--gray-0); border-color: var(--gray-3); }
.pagination .pg.on { background: var(--accent); border-color: var(--accent); color: #fff; cursor: default; }
.pagination .pg.arrow { color: var(--gray-6); font-size: 15px; line-height: 1; }
.pagination .pg.disabled { opacity: .35; pointer-events: none; }
.pagination .pg-gap { min-width: 16px; text-align: center; color: var(--gray-5); }
.pagination .pg-count { margin-left: 6px; font-size: 12px; color: var(--gray-6); white-space: nowrap; }

/* ── 은행 대체 묶음 표시 — 확신(실선 인디고)·의심(점선 인디고)·한쪽만(앰버) ── */
.bank-panel .lines td:first-child,
.bank-panel .lines th:first-child { border-left: 4px solid transparent; }  /* 정렬 예약 */
/* 배경 틴트는 제외(지저분) — 왼쪽 세로 바만 얇게 남긴다 */
.bank-panel tr.bundle > td:first-child { border-left-color: var(--b-bar); }
.bank-panel tr.b1 { --b-bar: #8250df; }  /* 묶음A(인디고) */
.bank-panel tr.b2 { --b-bar: #bf3989; }  /* 묶음B(분홍, 인접 구분) */
.bank-panel tr.bw { --b-bar: #bf8700; }  /* 한쪽만 처리됨(앰버) */
/* 대체 묶음 안내(제목 밑 접이식) + 색상 견본 */
.bank-help { margin: -2px 0 14px; font-size: 12.5px; color: var(--gray-6); }
.bank-help > summary { cursor: pointer; font-weight: 600; color: var(--accent); width: fit-content; }
.bank-help .help-body { padding: 8px 2px 0; }
.bank-help .help-body p { margin: 5px 0; line-height: 1.6; }
.sw { display: inline-block; width: 11px; height: 11px; border-radius: 3px; vertical-align: -1px; margin-right: 1px; }
.sw-b1 { background: #8250df; } .sw-b2 { background: #bf3989; } .sw-bw { background: #bf8700; }
/* [짝] 칩(클립) — 상대 계좌 + 상태를 알약으로 감쌈. 색은 묶음 색을 따름 */
.pairchip { display: inline-flex; align-items: center; gap: 4px; padding: 1px 9px;
    border-radius: 999px; font-size: 11px; font-weight: 600; white-space: nowrap;
    border: 1px solid var(--pc); color: var(--pc); background: var(--pcs); }
/* 재고 수불의 [짝] 칩 — 은행 [대체] 짝과 같은 문법.
   **칩 색은 가리키는 쪽의 색**이다: 입고 줄의 짝(나간 곳)=주황, 출고 줄의 짝(온 곳)=청.
   [구분] 칩(입고 청·출고 주황)과 같은 색 문법이라 화살표 없이도 방향이 읽힌다.
   아직 안 나간 몫은 회색 — 짝이 아니라 잔량이라 눈에 덜 띄어야 한다. */
.mate-cell .pairchip.to-in { --pc: var(--accent); --pcs: var(--accent-subtle); }
.mate-cell .pairchip.to-out { --pc: var(--orange); --pcs: var(--orange-subtle); }
.mate-cell .pairchip.stock { --pc: var(--gray-6); --pcs: var(--gray-1); }
/* ── KT 검수·납품 [진행 단계] — 두 줄 sticky 바 + **본문이 곧 수직 바**(§4(G-5)) ──
   수석의 문제는 "지금 단계가 화면 어느 부분인지 모르겠다"였다. 세로 레일을 따로 세우면
   폭을 먹고 스크롤에서 본문과 어긋난다 → **본문 왼쪽 여백에 마디를 찍어 본문을 레일로
   삼는다.** 상단 칩의 번호와 본문 마디의 번호가 같은 것이 이 장치의 전부다. */
.kstep-done { --kc: var(--ok);     --kcs: var(--ok-subtle); }
.kstep-now  { --kc: var(--accent); --kcs: var(--accent-subtle); }
.kstep-wait { --kc: var(--gray-5); --kcs: var(--gray-1); }

.ksteps {
    position: sticky; top: 0; z-index: 50;
    display: flex; flex-direction: column; gap: 8px;
    padding: 8px 10px; margin: 0 0 14px;
    background: #fff; border: 1px solid var(--gray-2); border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0,0,0,.06);
}
.ksteps .krow { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ksteps .kchip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 11px; border-radius: 999px; font-size: 13px; font-weight: 600;
    border: 1.5px solid var(--kc); color: var(--kc); background: var(--kcs);
    text-decoration: none; white-space: nowrap;
}
.ksteps .kchip-out { border-style: dashed; }      /* KT 포털 = DMRS 밖 */
.ksteps .kstep-now { box-shadow: 0 0 0 3px var(--accent-subtle); }
.ksteps .ksep { color: var(--gray-3); font-size: 12px; }
.ksteps .kmark { font-size: 11px; }
.ksteps .know {
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
    padding: 8px 11px; border-radius: 7px;
    background: var(--accent-subtle); border-left: 4px solid var(--accent);
}
.ksteps .know .lead { color: var(--accent); font-weight: 700; white-space: nowrap; }
.ksteps .know .body { color: var(--gray-9); font-size: 13px; line-height: 1.5; }
.ksteps .know .after { color: var(--gray-5); font-size: 12px; white-space: nowrap; margin-left: auto; }
.ksteps .kdone { padding: 7px 11px; border-radius: 7px; background: var(--ok-subtle);
    border-left: 4px solid var(--ok); color: var(--ok); font-weight: 600; font-size: 13px; }

/* 본문 = 수직 바. 왼쪽 여백에 마디가 서고, 마디끼리 선으로 이어진다. */
.kspine { position: relative; padding-left: 44px; }
.kspine::before {                                  /* 잇는 선 — 첫 마디부터 아래로 */
    content: ""; position: absolute; left: 13px; top: 14px; bottom: 24px;
    width: 2px; background: var(--gray-2); border-radius: 2px;
}
.kstep { position: relative; }
.kstep-no {
    position: absolute; left: -44px; top: 0; z-index: 1;   /* 선 위로 */
    width: 28px; height: 28px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-style: normal; font-size: 14px; font-weight: 700;
    border: 2px solid var(--kc); color: var(--kc); background: var(--kcs);
}
.kstep-now > .kstep-no { box-shadow: 0 0 0 5px var(--accent-subtle); }
.kstep-now::after {                                /* 지금 구획을 옅게 감싼다 */
    content: ""; position: absolute; left: -14px; right: -10px; top: -10px; bottom: -10px;
    border-radius: 8px; background: var(--accent-subtle); opacity: .35; z-index: -1;
}
/* "지금 여기" — **마디 바로 아래, 왼쪽 여백 안**(2026-08-12 수석 지적).
   ⚠ 오른쪽(마디 옆)에 두면 본문 첫 글자와 겹친다 — 구획마다 첫 요소가 다르기 때문에
   (입고 파일 라벨·[배정 결과표 엑셀] 버튼…) 비켜 둘 안전한 자리가 없다.
   여백은 44px이고 마디가 28px이라, 두 줄로 접히지 않게 글자를 줄이고 자간을 좁힌다. */
.kstep-here {
    position: absolute; left: -46px; top: 31px; width: 32px;
    font-size: 9.5px; font-weight: 700; line-height: 1.25; letter-spacing: -.03em;
    text-align: center; color: var(--accent);
}
@media (max-width: 900px) {                        /* 좁은 화면에선 여백을 접는다 */
    .kspine { padding-left: 0; }
    .kspine::before { display: none; }
    .kstep-no { position: static; margin-bottom: 6px; }
    .kstep-here { display: none; }
}

/* [잔량] — 아직 창고에 남은 몫. 0이 아닌 것만 또렷하게(남은 것이 곧 볼 일이다). */
.left-qty { color: var(--accent); }
.mate-cell .pairchip + .pairchip { margin-top: 3px; }
.mate-cell .pairchip { display: flex; }        /* 짝이 여럿이면 줄바꿈으로 쌓는다 */
.b1 .pairchip { --pc: #8250df; --pcs: #f2ebfd; }
.b2 .pairchip { --pc: #bf3989; --pcs: #ffeff7; }
.bw .pairchip { --pc: #9a6700; --pcs: #fdf3d0; }

/* ── 재고현황(.sst-*) — 월 리듬 미러 + 로트 생애 리본 현황판 ──────────────
   phase-4 §8.8. 기하(left/width/height)는 stock_status.js가 인라인 속성으로 놓고,
   여기는 생김새만 든다. 색 문법은 수불부 [구분] 칩 그대로: 입고/보유=청, 출고=주황. */
.sst-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 10px; margin-bottom: 10px; }
.sst-kpi { background: #fff; border: 1px solid var(--gray-2); border-radius: 6px;
    padding: 10px 14px 9px; }
.sst-kpi .sk-lab { font-size: 12px; color: var(--gray-6); }
.sst-kpi .sk-val { font-size: 21px; font-weight: 700; margin-top: 2px; letter-spacing: -.2px; }
.sst-kpi .sk-val small { font-size: 13px; font-weight: 600; color: var(--gray-6); }
.sst-kpi .sk-sub { font-size: 12px; color: var(--gray-5); margin-top: 1px; }
.sst-kpi .sk-in { color: var(--accent); }
.sst-kpi .sk-out { color: var(--orange); }

.sst-trace { background: #fff; border: 1px solid var(--gray-2); border-radius: 6px;
    padding: 10px 14px; margin-bottom: 10px; }
.sst-trace form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.sst-trace label { font-size: 13px; font-weight: 600; }
.sst-trace input { flex: 1; min-width: 220px; max-width: 420px; font: inherit; font-size: 13px;
    padding: 6px 10px; border: 1px solid var(--gray-2); border-radius: 6px;
    font-variant-numeric: tabular-nums; }
.sst-journey { margin-top: 9px; padding: 9px 12px; border: 1px solid var(--gray-2);
    border-radius: 6px; background: var(--gray-0); font-size: 13px; display: none; }
.sst-journey.show { display: block; }
.sst-journey.err { background: var(--danger-subtle); border-color: var(--danger); color: var(--danger); }
.sst-journey .sj-in { color: var(--accent); font-weight: 600; }
.sst-journey .sj-out { color: var(--orange); font-weight: 600; }
.sst-journey .sj-stock { color: var(--accent); font-weight: 700; }
.sst-journey .sj-arrow { color: var(--gray-5); padding: 0 6px; }

.sst-board { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 12px;
    align-items: start; }
.sst-chart { background: #fff; border: 1px solid var(--gray-2); border-radius: 6px;
    padding: 12px 14px 16px; }
.sst-chart-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.sst-chart-head h2 { font-size: 15px; margin: 0; }
.sst-legend { display: flex; gap: 14px; margin-left: auto; font-size: 12px;
    color: var(--gray-6); flex-wrap: wrap; }
.sst-legend i { display: inline-block; width: 12px; height: 8px; border-radius: 2px;
    margin-right: 4px; }
.sst-legend .sl-now i { background: var(--accent); }
.sst-legend .sl-past i { background: var(--rib-past); }
.sst-legend .sl-out i { background: none; width: 0; height: 0; border-radius: 0;
    border-left: 6px solid transparent; border-right: 6px solid transparent;
    border-top: 8px solid var(--orange); }
.sst-legend .sl-today i { background: none; border-top: 2px dashed var(--gray-3);
    height: 0; width: 14px; }

.sst-tlwrap { overflow-x: auto; }
.sst-tl { position: relative; }
.sst-row { display: grid; grid-template-columns: 136px minmax(0, 1fr); }
.sst-rlab { font-size: 12px; color: var(--gray-6); align-self: center;
    padding-right: 12px; text-align: right; }
.sst-rlab b { color: var(--gray-9); font-size: 12.5px; }
.sst-track { position: relative; }
.sst-overlay { position: absolute; top: 0; bottom: 0; left: 136px; right: 0;
    pointer-events: none; z-index: 0; }
.sst-gline { position: absolute; top: 22px; bottom: 0; width: 0;
    border-left: 1px solid var(--gray-1); }
.sst-today { position: absolute; top: 0; bottom: 0; width: 0;
    border-left: 2px dashed var(--gray-3); }
.sst-today small { position: absolute; top: 2px; right: 4px; font-size: 10.5px;
    color: var(--gray-5); white-space: nowrap; }
.sst-guide { position: absolute; top: 22px; bottom: 0; width: 0;
    border-left: 2px dashed var(--orange); display: none; }
.sst-guide.show { display: block; }
.sst-axis .sst-track { height: 22px; }
.sst-mlab { position: absolute; top: 2px; font-size: 11px; color: var(--gray-6);
    transform: translateX(-50%); white-space: nowrap; }
.sst-mlab b { color: var(--gray-9); }
.sst-mirror .sst-track { height: 150px; }
.sst-baseline { position: absolute; left: 0; right: 0; top: 50%;
    border-top: 1px solid var(--gray-2); }
.sst-bar { position: absolute; width: 4.6%; min-width: 8px; max-width: 34px;
    transform: translateX(-50%); border: 0; padding: 0; cursor: pointer; z-index: 1; }
.sst-bar.in { background: var(--accent); bottom: calc(50% + 2px); border-radius: 3px 3px 0 0; }
.sst-bar.out { background: var(--orange); top: calc(50% + 2px); border-radius: 0 0 3px 3px; }
.sst-bar:hover, .sst-bar.rel { filter: brightness(1.18); }
.sst-bar.sel { outline: 2px solid var(--gray-9); outline-offset: 1px; }
.sst-blab { position: absolute; transform: translateX(-50%); font-size: 10.5px;
    color: var(--gray-6); font-variant-numeric: tabular-nums; white-space: nowrap; z-index: 1; }
.sst-stock .sst-track { height: 64px; }
.sst-stseg { position: absolute; border-top: 2px solid var(--gray-9); }
.sst-stcon { position: absolute; width: 0; border-left: 2px solid var(--gray-9); }
.sst-stlab { position: absolute; transform: translateX(-50%); font-size: 10.5px;
    color: var(--gray-6); font-variant-numeric: tabular-nums; }
.sst-lotcap .sst-rlab { padding: 8px 12px 4px 0; font-weight: 600; }
.sst-lotcap .sst-track { border-bottom: 1px solid var(--gray-1); }
.sst-lot { border-bottom: 1px solid var(--gray-1); }
.sst-lot .sst-track { height: 42px; }
.sst-lot:hover { background: var(--gray-0); }
.sst-lot.sel { background: #eef6ff; }
.sst-lot.rel { background: #f4f9ff; }
.sst-seg { position: absolute; top: 50%; transform: translateY(-50%); border: 0;
    padding: 0; cursor: pointer; z-index: 1; }
.sst-seg.past { background: var(--rib-past); }
.sst-seg.now { background: var(--accent); border-radius: 0 3px 3px 0; }
.sst-seg:hover { filter: brightness(1.08); }
.sst-indot { position: absolute; top: 50%; width: 7px; height: 7px; border-radius: 50%;
    background: var(--accent); transform: translate(-50%, -50%); z-index: 2; }
.sst-omk { position: absolute; top: 1px; width: 18px; height: 16px;
    transform: translateX(-50%); background: none; border: 0; padding: 0;
    cursor: pointer; z-index: 2; }
.sst-omk::before { content: ""; position: absolute; left: 50%; top: 3px;
    transform: translateX(-50%); border-left: 6px solid transparent;
    border-right: 6px solid transparent; border-top: 8px solid var(--orange); }
.sst-omk:hover::before, .sst-omk.rel::before { border-top-color: #e05d00; }
.sst-omk.sel::before { border-top-color: var(--gray-9); }
.sst-olab { position: absolute; top: 1px; font-size: 10.5px; color: var(--orange);
    font-variant-numeric: tabular-nums; white-space: nowrap; z-index: 1; }
/* 잔여 라벨은 리본 **아래쪽** — 출고 수량 라벨(▼, 위쪽)과 높이를 갈라 오늘 선 근처에서
   겹치지 않는다(2026-08-11 수석 발견: 7월 ▼29,850과 '잔여 300'이 포개짐) */
.sst-remlab { position: absolute; bottom: 2px; transform: translateX(-100%);
    font-size: 11px; font-weight: 700; color: var(--accent);
    font-variant-numeric: tabular-nums; white-space: nowrap; z-index: 1; }
/* 행 라벨의 대수는 고정폭 우측정렬 — 자릿수가 달라도(430 vs 30,150) 월이 세로로 맞는다 */
.sst-rlab .sst-rqty { display: inline-block; min-width: 8ch; text-align: right; }

.sst-panel { position: sticky; top: 12px; max-height: calc(100vh - 24px); overflow: auto;
    background: #fff; border: 1px solid var(--gray-2); border-radius: 6px;
    padding: 12px 14px; font-size: 13px; }
.sst-pempty { color: var(--gray-5); font-size: 12.5px; line-height: 1.6; }
.sst-phead { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.sst-pqty { font-size: 20px; font-weight: 700; margin: 6px 0 2px; }
.sst-pqty small { font-size: 12px; font-weight: 600; color: var(--gray-6); }
.sst-pmeta { margin: 6px 0; color: var(--gray-6); font-size: 12.5px; line-height: 1.7; }
.sst-pmeta b { color: var(--gray-9); font-weight: 600; }
.sst-psec { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--gray-1); }
.sst-psec h3 { font-size: 12px; color: var(--gray-6); margin: 0 0 5px; font-weight: 600; }
.sst-mate { display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
    background: none; border: 0; padding: 3px 2px; font: inherit; font-size: 12.5px;
    border-radius: 4px; }
.sst-mate.link { cursor: pointer; }
.sst-mate.link:hover { background: var(--gray-0); }
.sst-mate .sm-q { margin-left: auto; color: var(--gray-6); }
.sst-plink { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--gray-1);
    font-size: 12px; }

.sst-tip { position: fixed; display: none; z-index: 50; background: #fff;
    border: 1px solid var(--gray-2); border-radius: 6px;
    box-shadow: 0 4px 14px rgba(31, 35, 40, .12); padding: 6px 10px; font-size: 12px;
    line-height: 1.55; pointer-events: none; max-width: 280px; }
.sst-tip b { font-variant-numeric: tabular-nums; }

@media (max-width: 1080px) {
    .sst-board { grid-template-columns: 1fr; }
    .sst-panel { position: static; max-height: none; }
}
.sst-nav { display: flex; gap: 6px; margin-left: 10px; }
/* 이월/계속 표시(⋯) — 창 밖으로 리본이 잘렸다는 표식(2026-08-11 12개월 창) */
.sst-clipmark { position: absolute; top: 50%; transform: translateY(-50%);
    color: var(--gray-5); font-weight: 700; letter-spacing: 1px; z-index: 2; }
.sst-clipmark::before { content: "⋯"; }

/* 계획대비실적 — 제품 구획(한 제품이 6행이라 어디서 끊기는지 보여야 한다).
   색을 새로 들이지 않고 **구조**로 가른다(표 안 새 hue 금지, phase-5 §4):
   블록 첫 행 위에 구분선, 제품명 칸은 세로 가운데 + 세미볼드 + gray-0 띠. */
tr.pa-blk > td { border-top: 2px solid var(--gray-3); }
td.pa-name { font-weight: 600; vertical-align: middle; background: var(--gray-0);
    border-right: 1px solid var(--gray-2); }
tbody tr:hover > td.pa-name { background: var(--gray-1); }
/* 그 달 실적도 계획도 없는 제품 — 자리는 지키되 뒤로 물린다 */
td.pa-name.pa-idle { color: var(--gray-5); font-weight: 400; }
/* 필터줄 강제 줄바꿈 — 입력이 많은 줄을 뜻 단위로 끊는다(자연 줄바꿈과 별개).
   .filter-form은 기본 nowrap이므로 쓰는 쪽에서 .wrap을 함께 켠다. */
.filter-form.wrap .row-break { flex-basis: 100%; height: 0; margin: 0; }
.filter-form label { white-space: nowrap; }   /* 라벨이 두 줄로 깨지지 않게 */

/* 접히는 알림 상자 — 요약 줄(건수·합계)은 늘 보이고 상세 목록만 접는다.
   `.nonfield`의 색(warn·info·ok)을 그대로 쓰고 여는 장치만 얹는다. */
details.nonfield.fold > summary {
    cursor: pointer; list-style: none; display: flex; gap: 6px; align-items: baseline;
}
details.nonfield.fold > summary::-webkit-details-marker { display: none; }
details.nonfield.fold > summary::before { content: "▸"; font-size: 11px; }
details.nonfield.fold[open] > summary::before { content: "▾"; }
details.nonfield.fold .fold-body { margin-top: 6px; }
/* 계획대비실적 머리행 — 제품·구분은 2줄에 걸치므로 세로 가운데,
   그 아래로 본문이 이어져 보이도록 머리행 밑선(2px 먹선)을 그 두 칸에서만 뺀다. */
thead th.pa-h-name { vertical-align: middle; box-shadow: none; }
thead th.pa-h-name.vl { box-shadow: inset 1px 0 0 var(--gray-3); }
/* 편집 가능한 실적 셀·계획 입력 그리드 — 셀 안 입력칸은 오른쪽 정렬로 숫자에 맞춘다.
   (2026-08-25 사업계획 실적 개편: 실적은 표에서 고쳐 저장, 계획은 12개월 그리드로 입력) */
form.pa-actual td.num > input,
table.pa-plan-grid td.num > input { width: 100%; max-width: 130px; text-align: right; }
table.pa-plan-grid td.num { padding: 2px 4px; }
/* 제품|구분·구분|계획 세로선을 머리행부터 영업이익까지 끊김 없이 — 제품|구분은 구분 셀의
   .vl(왼쪽선)이 그리고(합계행은 아래에서 빈 구분 셀로 이어 준다), 구분|계획은 구분 셀
   바로 뒤 계획 셀 왼쪽에 그린다. .num.vl(누계 계획 구분선)은 제외한다. */
form.pa-actual tbody td.vl:not(.num) + td { border-left: 1px solid var(--gray-3); }
/* 계획|실적 사이 세로선(09-01 수석 지시) — 월별·누계 두 묶음 모두, 색은 묶음 경계선과 같은
   --gray-3. 월별 실적 = 구분 셀(.vl) 뒤 둘째 셀, 누계 실적 = 누계 계획(.num.vl) 다음 셀
   (환율 행처럼 월별 계획이 .num.vl인 곳도 같은 규칙으로 실적 앞에 선이 온다). */
form.pa-actual tbody td.vl:not(.num) + td + td,
form.pa-actual tbody td.num.vl + td,
form.pa-actual tbody td.vl:not(.num) + td + td + td,      /* 실적|달성률 (월별) */
form.pa-actual tbody td.num.vl + td + td { border-left: 1px solid var(--gray-3); }   /* 실적|달성률 (누계) */
form.pa-actual thead th.num.vl + th,
form.pa-actual thead th.num.vl + th + th { border-left: 0; box-shadow: inset 1px 0 0 var(--gray-3), inset 0 -2px 0 var(--rule); }
/* 총계 행(한계이익·비용 계·영업이익)은 원본 양식처럼 위아래 굵은 선으로 상자를 만든다(09-01) */
form.pa-actual tbody tr.grand > td { border-bottom: 2px solid var(--rule); }
/* 유엠로직스(용역개발비) 한 줄짜리 블록 — 제품 블록 경계선과 같은 선으로 위아래를 두른다 */
form.pa-actual tbody tr.pa-solo > td { border-top: 2px solid var(--gray-3); border-bottom: 2px solid var(--gray-3); }

/* 요인분석([사업계획 실적]>[요인분석]) — 서버 렌더 SVG 차트 + 요약 표.
   차트 색은 새 hue를 들이지 않는다: 개선=--accent·악화=--orange·총계=--navy
   (2026-08 보고서의 파랑/주황을 토큰으로 승계). 기하는 SVG 속성, 색·글꼴은 여기. */
.pv-h { margin: 26px 0 8px; }
.pv-scope { color: var(--muted); font-size: 13px; }
.pv-fig { margin: 10px 0 18px; }
.pv-fig svg { width: 100%; max-width: 940px; height: auto; display: block; }
.pv-fig figcaption { font-size: 12px; color: var(--muted); margin-top: 4px; }
.pv-note { font-size: 12px; }
table.pv-headline, table.pv-bridge, table.pv-sens { max-width: 720px; }
table.pv-products { min-width: 900px; }
.pv-wrap { overflow-x: auto; }
/* 스크롤 컨테이너 안에서는 sticky 머리행이 첫 행을 덮는다 — 이 표만 고정 해제 */
.pv-wrap thead th { position: static; }
tr.pv-base > td { font-weight: 700; background: var(--gray-0); }
.pv-sens-form label { margin-right: 10px; }
/* 전표 입력 [계속] — 방금 저장한 전표를 위에 접이식으로 보여 이어서 치게 한다(2026-09-02) */
details.prev-entry { margin: 0 0 14px; padding-bottom: 12px; border-bottom: 1px solid var(--line);  /* 마지막 전표 아래 회색 선(09-03 수석) */
    width: max-content; min-width: 100%; }  /* 블록 폭은 본문 폭까지라 선이 표(더 넓다)보다 짧다 — 표 폭을 따르게(09-03 수석) */
details.prev-entry > summary { cursor: pointer; color: var(--muted); font-size: 13px; }
details.prev-entry > summary a { margin-left: 6px; }
details.prev-entry .prev-item { margin-top: 8px; }
details.prev-entry .prev-item + .prev-item { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); }  /* 전표 사이 구분선(09-03 수석) */
details.prev-entry .prev-head { font-size: 12px; color: var(--muted); }
details.prev-entry .prev-head a { margin-left: 6px; }
details.prev-entry table.prev-lines { margin-top: 2px; font-size: 12px; table-layout: fixed; }  /* 폭은 JS가 입력 표에 맞춘다 */
details.prev-entry table.prev-lines td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

details.pv-basis { margin: 10px 0; }
details.pv-basis > summary { cursor: pointer; color: var(--muted); font-size: 13px; }
details.pv-basis table { max-width: 560px; margin-top: 6px; }
.pv-grid { stroke: var(--gray-1); stroke-width: 1; }
.pv-axis { stroke: var(--gray-5); stroke-width: 1.2; }
.pv-conn { stroke: var(--gray-3); stroke-width: 1; stroke-dasharray: 2 3; }
.pv-ref { stroke: var(--gray-3); stroke-width: 1.4; stroke-dasharray: 5 4; }
.pv-ref-lbl { fill: var(--muted); font-size: 11px; }
.pv-ax { fill: var(--muted); font-size: 11px; }
.pv-cat { fill: var(--gray-9); font-size: 11.5px; }
.pv-val { fill: var(--gray-9); font-size: 11px; font-weight: 700; }
.pv-pos { fill: var(--accent); }
.pv-neg { fill: var(--orange); }
.pv-total { fill: var(--navy); }

/* ══ 채권채무 공통(2층) ═══════════════════════════════════════════════════
   [채권채무 흐름]의 **두 보기가 함께 쓰는 것만** 여기 둔다 — 요약(.afb-)도
   타임라인(.agt-)도 이 규칙을 그대로 쓴다. 반대로 **여기서 .afb-/.agt-를
   참조하지 않는다**: 공통이 한쪽 보기를 알기 시작하면 그 순간 공통이 아니다.

   2층에 넣을지 가르는 3문 — 하나라도 "아니오"면 3층(보기 전용)으로 내린다.
     ① 값이 같아야 하는가        → 예면 클래스가 아니라 **토큰**(--rib-*)
     ② 사용자가 같은 것으로 인식하고 **같은 픽셀**로 봐야 하는가
     ③ 기하·배치·상호작용이 **완전히** 같은가 — 조금이라도 다르면 3층
        (나중에 한쪽만 고칠 때 공유 규칙은 반드시 오염된다)

   ⚠ 왜 이렇게까지 가르나: `.off` 하나를 상계(offset)와 창 밖 캡(off-screen)
   두 뜻으로 쓴 탓에 캡의 sticky가 마크의 absolute를 이겨 **상계 마크만
   스크롤을 따라다녔다**(2026-08-21). 한 이름을 두 화면이 나눠 쓰면 이런
   사고는 우연이 아니라 구조다. 얇게 유지할 것 — 목표 40줄 이내.
   ══════════════════════════════════════════════════════════════════════ */
/* KPI 상자 4개 — 두 보기의 머리에 똑같이 앉는다(templates/accounting/_arap_kpis.html) */
.arap-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 0 0 12px; }
.arap-kpi { border: 1px solid var(--gray-2); border-radius: 8px; padding: 10px 14px; color: inherit; }
.arap-kpi .t { font-size: 12px; color: var(--gray-5); }
.arap-kpi .v { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.3px; }
.arap-kpi .s { font-size: 11px; color: var(--gray-5); }
.arap-kpi .fx { font-size: 12px; color: var(--accent); font-weight: 600; }
a.arap-kpi { text-decoration: none; display: block; }
a.arap-kpi:hover { background: var(--gray-0); }
a.arap-kpi.on { outline: 2px solid var(--danger); outline-offset: -2px; }
.arap-kpi.warnv .v { color: var(--danger); }
/* 범례 — 설명 대상 곁에 둔다(§4). 자리는 보기마다 다르지만 생김새는 한 벌. */
.arap-legend { font-size: 12px; color: var(--gray-5); margin: 6px 0 8px; display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
.arap-legend .lgl { font-weight: 700; color: var(--gray-6); }
/* 범례 상자 — 마크 한 벌, Timeline 한 벌(2026-08-19 대표). 읽는 방법이 다른 두 무리라
   테두리가 경계를 말한다. 한 줄에 늘어놓기만 하면 어디까지가 한 벌인지 흐려진다. */
.arap-legend .lgrp { display: inline-flex; align-items: center; gap: 12px; flex-wrap: wrap;
                    padding: 4px 11px; border: 1px solid var(--gray-2); border-radius: 8px;
                    background: #fff; }
.arap-sw { display: inline-block; width: 16px; height: 7px; border-radius: 3px; vertical-align: -1px; margin-right: 4px; }
.arap-swd { display: inline-block; width: 16px; border-top: 2px dashed; vertical-align: 2px; margin-right: 4px; }
/* Timeline 범례 색칠 — 리본(.afb-rib)과 **같은 값을 두 곳에 적지 않으려고** 클래스로 뽑았다.
   종전엔 템플릿 인라인 style이었고(phase-5 §금지), 펼칠 때마다 되풀이됐다(2026-08-19 대표:
   범례는 위에 한 번, 펼침 자리에는 "마크 옆 숫자=일"만). */
.arap-sw.base { background: var(--rib-past); }
.arap-sw.late { background: var(--rib-late-fill);
               border: 1px solid var(--rib-late-line); }
.arap-sw.late-long { background: var(--rib-overdue-fill);
                    border: 1px solid var(--danger); }
.arap-swd.torow { border-top-color: var(--warn); }
.arap-swd.early { border-top-color: var(--gray-3); }
/* 이력 표 — 요약은 펼침 오른쪽, 타임라인은 팝오버 안. 자리는 달라도 표는 한 벌이다. */
.arap-hist { background: #fff; border: 0; border-radius: 0; }
/* 머리행 괘선은 **먹선을 쓰지 않는다**(2026-08-19 대표: "너무 너무 진한 black").
   `--rule` 2px 먹선은 원장·시산표처럼 큰 장부 표를 위한 굵기다 — 펼침 안의 작은 표에는
   과하고, 이 자리에서 가장 진한 것이 되어 정작 봐야 할 숫자보다 먼저 눈에 든다.
   sticky도 필요 없으니(짧은 표) 함께 끈다 — 스크롤에 머리행이 따라붙을 이유가 없다. */
.arap-hist thead th { box-shadow: none; position: static; }
.arap-hist td.sy { white-space: nowrap; }
.arap-hist .sym { font-size: 9px; }
.arap-hist .sym.o { color: var(--accent); }
.arap-hist .sym.s { color: var(--ok); }
.arap-hist .sym.f { color: var(--purple); }
/* [구분] = 기호 + 글자(2026-08-19 대표). 기호만 두면 ●와 ▼를 **색으로 갈라 읽어야** 한다 —
   글자가 붙으면 색은 거들 뿐이 된다(색각 이상·흑백 인쇄에서도 읽힌다). */
.arap-hist .syl { margin-left: 3px; font-size: 11px; color: var(--gray-6); }
.arap-hist .xn { font-size: 10px; color: var(--gray-5); }
.arap-hist .lg { font-size: 10px; color: var(--warn); font-weight: 600; }
.arap-hist .lg.long { color: var(--danger); }

/* ══ (3층) 요약 보기 .afb- ════════════════════════════════════════════════
   한 줄=한 정산그룹, 발생→예정→회수·집행 노드 흐름 + 행 펼침(로컬 날짜축).
   좌표는 **서버가 %로 구워** 준다(reports.py::arap_flow_board). 타임라인(.agt-)을
   참조하지 않는다 — 두 보기는 서로를 몰라야 각자 고쳐도 안전하다.
   색 역할: 발생=accent 파랑 · 예정=warn 앰버 · 회수/집행=ok 초록 · 상계·전환=보라 ·
   기한초과=danger. 상태 칩은 §4-(L) '색은 드문 것에' — 완료(대다수)=회색. */
/* 흐름 셀 노드 */
td.afb-flowcell { max-width: 640px; }
.afb-flow { display: flex; align-items: center; overflow-x: auto; padding: 2px 0; }
.afb-nd { display: inline-flex; align-items: center; gap: 5px; border: 1px solid; border-radius: 6px;
  padding: 1px 8px; font-size: 11px; white-space: nowrap; flex: none; background: #fff; color: var(--gray-9); }
.afb-nd b { font-variant-numeric: tabular-nums; font-weight: 600; }
.afb-nd .dt { color: var(--gray-5); }
.afb-nd.occ { border-color: #9ec8f2; background: #f1f8ff; }
.afb-nd.occ::before { content: "●"; color: var(--accent); font-size: 9px; }
.afb-nd.due { border-color: var(--rib-late-line); background: var(--attention-subtle); }
.afb-nd.due::before { content: "◇"; color: var(--warn); font-size: 11px; }
.afb-nd.due.over { border-color: var(--danger); background: var(--danger-subtle); }
.afb-nd.due.over::before { color: var(--danger); }
.afb-nd.set { border-color: #8fd19e; background: var(--ok-subtle); }
.afb-nd.set::before { content: "▼"; color: var(--ok); font-size: 9px; }
.afb-nd.off { border-color: #c9b8f2; background: #f8f5ff; }
.afb-nd.off::before { content: "▼"; color: var(--purple); font-size: 9px; }
.afb-nd .lag { color: var(--warn); font-weight: 600; }
.afb-nd .lag.long { color: var(--danger); }
.afb-arr { flex: none; width: 16px; height: 1px; background: var(--gray-3); margin: 0 3px; position: relative; }
.afb-arr::after { content: ""; position: absolute; right: -1px; top: -2.5px; border-left: 5px solid var(--gray-3);
  border-top: 3px solid transparent; border-bottom: 3px solid transparent; }
.afb-ndcol { display: flex; flex-direction: column; gap: 2px; flex: none; }
.afb-more { flex: none; font-size: 11px; color: var(--gray-5); margin: 0 4px; }
tr.expandable .afb-pname { font-weight: 600; }
tr.expandable .afb-pacct { color: var(--gray-5); font-size: 12px; }
td.afb-st { white-space: nowrap; }
td.afb-num-zero { color: var(--gray-3); }
/* 펼침 상세 */
/* 펼침 상세 = **요약행과 한 덩어리**(2026-08-19 대표, 최종). 오래 헤맨 끝의 진단:
   경계가 없었던 게 아니라 **배경에 잠겨 있었다** — 행 구분선 `--gray-1`(#eaeef2)과
   상세 배경 `--gray-0`(#f6f8fa)이 거의 같은 색이라 선이 안 보였다. 상세를 흰색으로
   두면 원래 있던 선이 제 몫을 한다. 경계를 위해 **새로 그린 것은 없다**
   (마감선·묶음 얼룩·모서리 자국은 모두 시도했다가 걷어냈다).
   그리고 펼친 요약행 아래 선은 **지운다** — 요약행과 상세는 한 거래묶음이다.

   ⚠ 이 규칙은 **이 표에만** 걸어야 한다(table.afb-board). 스코프 없이 두었더니
   계획대비실적·요약표·손익분기까지 따라 지워지고 있었다 — 그 셋의 상세는 흰색이
   아니라 `--bg-soft`(gray-0)라 **전제가 정반대**다. 진단이 옳아도 그 진단이
   서지 않는 화면까지 데려가면 안 된다. */
tr.detail-row > td.afb-detail { background: #fff; padding: 10px 14px 14px; }
table.afb-board tr.expandable.open > td { border-bottom: 0; }
.afb-dwrap { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px; }
.afb-dtl h4 { font-size: 12px; color: var(--gray-5); margin: 0 0 6px; font-weight: 600; }
/* 제목 + 범례를 한 줄로(2026-08-19 대표) — 차트 위에 머리가 두 겹 얹히지 않게. */
.afb-dhead { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin: 0 0 5px; }
.afb-dhead h4 { margin: 0; }
.afb-dhead .afb-legend-in { margin: 0; }
/* 로컬 날짜축(기하 값은 서버 계산 — 재고현황과 같은 분업: 위치는 인라인, 생김새는 여기) */
/* 상자를 걷어내고 **윗줄만 남긴다**(2026-08-19 대표) — 상세 안에 상자가 겹겹이면 그만큼
   덩어리가 쪼개진다. 위쪽 한 줄은 "여기부터 차트"를 말하는 데 충분하다. */
/* 상자를 걷어내고 **축 줄을 머리행처럼 회색 띠**로(2026-08-19 대표). 옆 [이력] 표의
   머리행이 이미 gray-0 띠라, 차트도 같은 문법이 되어 두 패널이 나란히 읽힌다.
   띠는 gradient로 깔아 **자리를 한 픽셀도 바꾸지 않는다** — 축 라벨은 %로 절대 배치돼
   있어 padding을 건드리면 격자선과 어긋난다. */
/* 띠는 옆 [이력] 표의 머리행과 **똑같이** 생겨야 한다(2026-08-19 대표). 색은 처음부터
   같은 토큰(--gray-0)이었고, 달라 보였던 것은 높이다 — 표 머리행 7+14+7=28px를 따른다.
   **마감선은 두 곳 다 없앤다**: 회색 띠 자체가 이미 머리와 본문을 가르고 있어, 선은
   그 위에 얹히는 군더더기다(오늘 내내 덜어낸 방향과 같다). */
.afb-ltl { position: relative; border: 0; border-radius: 0; padding: 7px 84px 8px 64px;
           background: linear-gradient(var(--gray-0) 0 28px, #fff 28px); }
.afb-dtl h4 .hnote { font-weight: 400; color: var(--gray-5); }
.afb-lax { position: relative; height: 18px; }
.afb-lax .m { position: absolute; top: 1px; font-size: 10px; color: var(--gray-5); transform: translateX(-50%); white-space: nowrap; }
/* 월 경계 세로선은 **머리 띠까지 올라간다**(2026-08-19 대표) — 축 줄이 머리행 노릇을
   하게 됐으니, 표의 머리행을 세로선이 가로지르는 것과 같은 문법이다. 월 라벨은 달의
   가운데에, 세로선은 달의 경계에 있어 서로 부딪히지 않는다. */
.afb-lgrid { position: absolute; top: 3px; bottom: 8px; left: 64px; right: 84px; pointer-events: none; }
.afb-lgrid .gv { position: absolute; top: 0; bottom: 0; border-left: 1px solid var(--gray-2); }
/* 오늘선만은 **띠 아래에서 시작**한다(2026-08-19 대표) — 머리 띠는 **월 경계**를 말하는
   자리다. 오늘은 달의 경계가 아니라 축 위의 한 점이라, 머리까지 올라가면 뜻이 섞인다.
   25px = 띠 높이 28px − 격자 시작 3px. */
.afb-lgrid .today { top: 25px; border-left: 2px dashed var(--gray-3); }
.afb-lrow { position: relative; height: 50px; }
.afb-lrow .lmeta { position: absolute; left: -58px; top: 50%; transform: translateY(-50%); font-size: 10px;
  color: var(--gray-5); width: 52px; text-align: right; font-variant-numeric: tabular-nums; }
.afb-lrow .ltrack { position: absolute; left: 0; right: 0; top: 0; bottom: 0; }
.afb-dl { position: absolute; transform: translateX(-50%); font-size: 9px; line-height: 1; color: var(--gray-5);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.afb-dl.up { top: 1px; }
.afb-dl.dn { top: 40px; }
.afb-dl.imm { color: var(--ok); font-weight: 600; }
.afb-rib { position: absolute; top: 50%; height: 7px; transform: translateY(-50%); border-radius: 4px; }
.afb-rib.base { background: var(--rib-past); }
.afb-rib.late { height: 11px; background: var(--rib-late-fill);
  border: 1px solid var(--rib-late-line); border-radius: 3px; }
/* 장기 연체는 빗금 방향 반전(45°) — 색약에서도 색 아닌 결로 구분(+일수 라벨 병행) */
.afb-rib.late-long { height: 11px; background: var(--rib-overdue-fill);
  border: 1px solid var(--danger); border-radius: 3px; }
.afb-rib.torow { background: none; border-top: 2px dashed var(--warn); height: 0; border-radius: 0; transform: translateY(-1px); }
.afb-rib.early { background: none; border-top: 2px dashed var(--gray-3); height: 0; border-radius: 0; transform: translateY(-1px); }
.afb-mark.dot { position: absolute; top: 34%; width: 8px; height: 8px; border-radius: 50%;
  transform: translate(-50%, -50%); background: var(--accent); }
.afb-mark.diam { position: absolute; top: 34%; width: 7px; height: 7px;
  transform: translate(-50%, -50%) rotate(45deg); background: #fff; border: 2px solid var(--warn); }
.afb-mark.diam.mut { border-color: var(--gray-3); }
.afb-mark.mk { position: absolute; top: 66%; transform: translate(-50%, -50%); width: 12px; height: 12px; }
.afb-mark.mk::before { content: ""; position: absolute; left: 2px; top: 2px; border-left: 5px solid transparent;
  border-right: 5px solid transparent; border-bottom: 8px solid var(--ok); }
.afb-mark.mk.off::before { border-bottom-color: var(--purple); }
.afb-endlab { position: absolute; top: 50%; left: 100%; transform: translateY(-50%); font-size: 10px; font-weight: 600;
  white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--accent); padding-left: 6px; }
.afb-endlab .latehint { color: var(--danger); }
/* 단위 안내 — 차트 **왼쪽 위 여백**(padding-left 64px 안쪽)에 앉힌다. 절대 배치라 축·행의
   자리를 밀지 않고, 두 줄로 접혀 여백 안에 머문다. 월 라벨은 플롯 영역(left≥64px)이라 안 겹친다. */
/* 차트 바로 위 범례 — 제목(h4 Timeline)과 차트 사이에 바싹 붙인다(2026-08-19 3차).
   상단으로 모았더니 차트에서 멀어 한눈에 안 들어왔다 — 되풀이보다 안 읽히는 쪽이 손해다.
   **자리는 그대로 두고 존재감만 낮춘다**(4차): 펼친 줄마다 되풀이되므로, 필요할 때만
   초점이 가고 평소엔 배경으로 지나가게 한 급 아래 밝기·크기로. 마우스를 얹으면 또렷해진다. */
/* ⚠ `--gray-4`는 없는 토큰이다(척도가 0·1·2·3·5·6·9). 처음에 그것을 쓰는 바람에 색
   지정이 통째로 무효가 되어 본문색(gray-9)이 상속됐고, hover도 티가 안 났다(대표 발견).
   한 급 아래 = **gray-3**, 얹으면 gray-6. */
.afb-legend-in { margin: 0 0 5px; gap: 11px; font-size: 11px; color: var(--gray-3);
                 transition: color .12s ease; }
.afb-legend-in:hover { color: var(--gray-6); }
.afb-legend-in .arap-sw { width: 14px; height: 6px; }
.afb-legend-in .arap-swd { width: 14px; }
.afb-ltl .lhint { position: absolute; left: 5px; top: 3px; white-space: nowrap;
                  font-size: 9.5px; color: var(--gray-5); }


/* ══ (3층) 타임라인 보기 .agt- ════════════════════════════════════════════
   모든 행이 **하나의 시간축**을 공유한다(요약은 그룹마다 로컬 축). 좌표는 JS가
   원시 날짜로 계산한다(arap_timeline.js) — 서버 %는 로컬 축이라 여기 못 쓴다.
   요약(.afb-)을 참조하지 않는다. 색은 2층 토큰(--rib-*)에서 나오므로, 규칙이
   두 벌이어도 **값은 한 벌**이다.

   **파일 분리 트리거**(지금 적어 둔다 — 기준 없는 "언젠가 분리"는 영원히 안 온다):
   이 블록이 250줄을 넘거나 app.css가 2000줄을 넘으면 화면별 css 파일로 뺀다.
   지금 app.css에 두는 이유는 base.html에 화면별 CSS를 실을 자리(extra_head)가 없어,
   새 파일 하나를 위해 전 화면 공용 템플릿을 고쳐야 하기 때문이다.
   ══════════════════════════════════════════════════════════════════════ */
/* 이 화면의 치수는 **화면 상자에** 건다 — `:root`는 shell.css 한 곳뿐이라는 규약을 지킨다
   (phase-5 §2). 전역 토큰이 아니라 이 보기의 사정이므로 자리도 여기가 맞다. */
.agt-board { --agt-lane-w: 580px; --agt-row-h: 44px; --agt-head-h: 28px; }
/* 축 조작 — **범례 줄 오른쪽**에 얹는다(2026-08-25 대표: "위의 라인으로 이동").
   전용 줄을 하나 더 두면 표가 그만큼 아래로 밀리는데, 범례 줄은 오른쪽이 비어 있다.
   ◀ ▶는 뺐다 — **가로 스크롤이 이미 그 일을 한다**(같은 일을 하는 조작이 둘이면
   어느 쪽이 정본인지 흐려진다). 남는 것은 [오늘](제자리로)과 축 폭.
   ⚠ margin-left:auto는 **자기 클래스에** 건다 — 부모(.arap-legend)를 선택자에 쓰면
   3층이 2층을 아는 셈이 된다. */
.agt-axtools { margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
               font-size: 11px; color: var(--gray-5); }
.agt-axtools button { border: 1px solid var(--gray-2); background: #fff; border-radius: 5px;
                      font: inherit; font-size: 11px; padding: 2px 8px; cursor: pointer; color: var(--gray-6); }
.agt-axtools button:hover { border-color: var(--accent); color: var(--accent); }
.agt-axtools input[type=range] { width: 90px; }
.agt-axtools .agt-srt { font-weight: 700; }
/* 본체 = 가로 스크롤 한 통 + 왼쪽 열 sticky */
.agt-board { border: 1px solid var(--gray-1); border-radius: 8px; overflow: auto;
             max-height: 68vh; position: relative; background: #fff; }
/* ⚠ `width:max-content`가 핵심 — 행 상자가 **화면 폭**에 묶이면 스크롤이 그 상자를
   벗어나는 순간 sticky 왼쪽 열이 따라오지 못한다(거래처 이름이 사라진다). 블록의 기본
   폭은 화면 폭이지 스크롤 폭이 아니다. min-width:100%는 짧은 목록의 빈 칸 방지. */
.agt-row { display: flex; align-items: stretch; height: var(--agt-row-h);
           position: relative; width: max-content; min-width: 100%; }
.agt-body { position: relative; }
/* 행 경계 — 간트에는 표와 달리 칸 괘선이 없어 거래처가 어디서 갈리는지 알 수 없다
   (08-20 대표). 표의 행 구분선과 **같은 값**으로 긋는다. */
.agt-row[data-key] { border-bottom: 1px solid var(--gray-1); cursor: pointer; }
.agt-row[data-key]:last-child { border-bottom: 0; }
.agt-row[data-key]:hover .agt-lane { background: var(--gray-0); }
.agt-row.sel .agt-lane { background: var(--accent-subtle); }
.agt-row[data-key]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.agt-lane { position: sticky; left: 0; z-index: 3; width: var(--agt-lane-w);
            min-width: var(--agt-lane-w); background: #fff; border-right: 1px solid var(--gray-1);
            padding: 3px 9px; display: flex; flex-direction: row; align-items: center; gap: 8px;
            overflow: hidden; }
/* 고정바 = 요약 보드의 [구분·거래처·총액·잔액·상태] 다섯 열 그대로(흐름 열만 축이 대신한다).
   두 줄로 욱여넣지 않고 **열로 세운다** — 세로로 훑을 때 숫자가 같은 자리에 있어야 읽힌다. */
/* 열 폭은 **JS가 머리글을 재서 정한다**(arap_timeline.js fitLane) — 표가 자동으로 하는
   일을 여기서는 대신 해 줘야 한다. `<table>`은 머리와 본문이 track을 공유해 넓은 쪽에
   맞춰 주지만, flex 행은 서로를 모른다.
   ⚠ 고정 픽셀로는 못 푼다: 걸린 조건에 따라 머리글 폭이 달라지고(칩 유무·"100만+" vs
   "1,000만+"), 좁게 잡으면 이름이 잘린다("총액"이 "택"으로 — 2026-08-25 대표).
   좁게 잡고 **이름을 지우는** 쪽을 택했다가 되돌렸다 — 칸이 좁다는 것은 칸을 넓힐
   이유이지 이름을 지울 이유가 아니다. 아래 값은 JS가 못 돌 때의 밑값일 뿐이다. */
.agt-lane .c-dir { width: var(--agt-c-dir, 84px); flex: 0 0 var(--agt-c-dir, 84px); }
/* ⚠ 각 칸은 **넘쳐도 옆 열을 침범하지 않는다**. 이것이 없어서 [구분]에 "채권 ×" 칩이
   붙자 칩이 [거래처] 글자 위에 겹쳐 그려졌다(대표 발견). */
.agt-lane > * { overflow: hidden; white-space: nowrap; }
.agt-lane .c-nm { flex: 1 1 auto; min-width: 0; overflow: hidden; }
.agt-lane .c-nm b { display: block; font-weight: 600; white-space: nowrap;
                    overflow: hidden; text-overflow: ellipsis; }
.agt-lane .c-nm small { color: var(--gray-5); font-size: 10px; }
/* [총액]과 [잔액]은 **같은 형식·같은 폭**이다(2026-08-25 대표) — 같은 성격의 숫자를
   한쪽은 약식(2.5억), 다른 쪽은 원 단위로 두면 세로로 훑을 때 자릿수가 비교되지 않는다. */
.agt-lane .c-num { width: var(--agt-c-num, 96px); flex: 0 0 var(--agt-c-num, 96px);
                   text-align: right; font-variant-numeric: tabular-nums; font-size: 11px; }
.agt-lane .c-num.rm { font-weight: 600; }
.agt-lane .agt-zero { color: var(--gray-3); }
.agt-lane .c-st { width: var(--agt-c-st, 104px); flex: 0 0 var(--agt-c-st, 104px); text-align: right; }
.agt-plot { position: relative; flex: 0 0 auto; }
/* 머리 괘선 = **장부 먹선**(요약 보드의 thead와 같은 2px). collapse된 border는 sticky를
   따라오지 않으므로 inset shadow로 그린다 — 보드가 쓰는 방법 그대로. */
.agt-row.hd { position: sticky; top: 0; z-index: 4; height: var(--agt-head-h); }
.agt-row.hd .agt-lane, .agt-row.hd .agt-plot {
    background: var(--gray-0); box-shadow: inset 0 -2px 0 var(--rule); }
.agt-row.hd .agt-lane > * { font-size: 11px; color: var(--gray-6); font-weight: 700;
    display: flex; align-items: center; gap: 3px; }
.agt-row.hd .c-num, .agt-row.hd .c-st { justify-content: flex-end; }
.agt-row.hd .searched { color: var(--accent); }
/* 머리행 칩은 한 급 작게 — 다섯 칸에 이름·버튼·칩이 모두 들어가야 한다.
   ⚠ 두 줄로 접히면 안 된다(한 번 고친 결함): nowrap + 줄어들지 않게 flex:0 0 auto. */
.agt-row.hd .hchip { white-space: nowrap; flex: 0 0 auto; font-size: 10px; padding: 0 5px; }
.agt-row.hd .hchip a { margin-left: 3px; }
.agt-srt { color: inherit; text-decoration: none; }
.agt-srt:hover { color: var(--gray-9); }
.agt-srt.on { color: var(--accent); }
/* 월 라벨은 굵게 — 머리행의 다른 글자(열 이름)와 같은 무게로 서야 축이 '머리'로 읽힌다 */
.agt-mlab { position: absolute; top: 6px; font-size: 11px; font-weight: 700; color: var(--gray-6);
            transform: translateX(-50%); white-space: nowrap; pointer-events: none; }
/* 격자는 **컨테이너 한 장**으로 깐다(행마다 만들면 200행이면 span이 수천 개다) */
.agt-grid { position: absolute; top: 0; bottom: 0; left: var(--agt-lane-w);
            pointer-events: none; z-index: 0; }
.agt-gv { position: absolute; top: 0; bottom: 0; border-left: 1px solid var(--gray-1); }
.agt-gv.q { border-left-color: var(--gray-2); }
.agt-gv.today { border-left: 2px dashed var(--gray-3); z-index: 1; }
/* 리본·마크 — 요약 보기와 **같은 문법·같은 값**(색은 --rib-* 한 벌에서).
   위층(34%)=약속(● 발생 · ◇ 예정), 아래층(66%)=실제(▼ 집행).
   연체는 빗금 135°, 장기 연체는 45° 반전 — 색약에서도 색이 아니라 결로 구분한다. */
.agt-rib { position: absolute; top: 50%; height: 7px; transform: translateY(-50%); border-radius: 4px; }
.agt-rib.base { background: var(--rib-past); }
.agt-rib.late { height: 11px; background: var(--rib-late-fill);
                border: 1px solid var(--rib-late-line); border-radius: 3px; }
.agt-rib.late-long { height: 11px; background: var(--rib-overdue-fill);
                     border: 1px solid var(--danger); border-radius: 3px; }
.agt-rib.torow { background: none; border-top: 2px dashed var(--warn); height: 0;
                 border-radius: 0; transform: translateY(-1px); }
.agt-rib.early { background: none; border-top: 2px dashed var(--gray-3); height: 0;
                 border-radius: 0; transform: translateY(-1px); }
.agt-mk { position: absolute; z-index: 2; }
.agt-mk.dot { top: 34%; width: 8px; height: 8px; border-radius: 50%;
              transform: translate(-50%, -50%); background: var(--accent); }
.agt-mk.diam { top: 34%; width: 7px; height: 7px; transform: translate(-50%, -50%) rotate(45deg);
               background: #fff; border: 2px solid var(--warn); }
.agt-mk.diam.mut { border-color: var(--gray-3); }
.agt-mk.mk-tri { top: 66%; transform: translate(-50%, -50%); width: 12px; height: 12px; }
.agt-mk.mk-tri::before { content: ""; position: absolute; left: 2px; top: 2px;
    border-left: 5px solid transparent; border-right: 5px solid transparent;
    border-bottom: 8px solid var(--ok); }
.agt-mk.mk-tri.off::before { border-bottom-color: var(--purple); }
.agt-dl { position: absolute; transform: translateX(-50%); font-size: 9px; line-height: 1;
          color: var(--gray-5); white-space: nowrap; pointer-events: none;
          font-variant-numeric: tabular-nums; }
.agt-dl.up { top: 2px; }
.agt-dl.dn { bottom: 2px; }
.agt-dl.imm { color: var(--ok); font-weight: 600; }
.agt-endlab { position: absolute; top: 50%; transform: translateY(-50%); font-size: 10px;
              font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums;
              color: var(--accent); padding-left: 6px; }
.agt-endlab .latehint { color: var(--danger); }
/* 창 밖 신호 — 신호가 곧 조작이다(누르면 그 자리로 축이 뛴다). 얼어붙은 왼쪽 열
   **바로 오른쪽**에 붙는다(left:0이면 이름을 가린다).
   ⚠ 이름은 `cap`이다 — 처음에 `off`로 지었더니 상계 마크(.off)와 부딪혀 상계 삼각형이
   캡의 sticky를 물려받아 스크롤을 따라다녔다(08-21). 한 이름을 두 뜻으로 쓰지 말 것. */
.agt-cap { position: sticky; z-index: 3; font-size: 10px; font-weight: 700; color: var(--gray-5);
           top: 50%; transform: translateY(-50%); line-height: 16px; cursor: pointer;
           background: #fff; border: 1px solid var(--gray-2); border-radius: 9px;
           padding: 0 6px; white-space: nowrap; }
.agt-cap:hover { color: var(--accent); border-color: var(--accent); }
/* ⚠ sticky의 기준은 스크롤 상자이지 이 요소의 부모가 아니다. left:5px로 두면
   0~470px를 덮고 있는 고정 열 **밑에 깔려** 보이지 않는다(안 그려진 게 아니라 덮인 것).
   고정 열 바로 오른쪽에 붙이려면 그 폭만큼 밀어야 한다. */
.agt-cap.l { left: calc(var(--agt-lane-w) + 5px); float: left; }
.agt-cap.r { right: 5px; float: right; }
.agt-cap[hidden] { display: none; }
.agt-empty { padding: 26px; text-align: center; color: var(--gray-5); }
/* 이력 = **행 아래 팝오버**(08-20 대표). 이력이 대개 2~5줄이라 세로 막대는 빈 공간이 크고,
   인라인은 아래 행들을 밀어낸다. 팝오버는 레이아웃을 건드리지 않고 내용 높이만큼만 뜬다.
   ⚠ position:fixed — 스크롤 컨테이너 안에 두면 잘리거나 함께 흘러간다. */
.agt-pop { position: fixed; z-index: 30; background: #fff; border: 1px solid var(--gray-2);
           border-radius: 9px; box-shadow: 0 8px 26px rgba(0, 0, 0, .14);
           padding: 9px 12px 11px; max-width: 660px; max-height: 70vh; overflow: auto; }
.agt-pop[hidden] { display: none; }
.agt-pop-head { display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
                margin: 0 0 6px; font-size: 12px; }
.agt-pop-x { margin-left: auto; border: 0; background: none; font-size: 15px;
             cursor: pointer; color: var(--gray-5); }
.agt-pop-x:hover { color: var(--gray-9); }
/* **인쇄는 요약 보기가 담당한다** — 가로 스크롤 축은 종이에 담기지 않는다(넉 달만 나오고
   나머지는 잘린다). 같은 조건 그대로 [요약]으로 전환해 인쇄하면 전 구간이 나온다. */
@media print {
    .agt-board, .agt-axtools, .agt-pop { display: none; }
}

/* [환율 검증] 재계산 로그 — 관리 명령의 출력을 **그대로** 보여 준다(가공하면 또 갈라진다) */
.fx-recalc-log {
    font-family: ui-monospace, "D2Coding", Consolas, monospace; font-size: 11.5px;
    line-height: 1.55; margin: 8px 0 0; padding: 10px 12px; max-height: 380px;
    overflow: auto; background: var(--gray-0); border: 1px solid var(--gray-1);
    border-radius: 6px; white-space: pre; color: var(--gray-9);
}
/* 현금흐름표(관리) — 3대분류 구획 머리행과 검증 문구 톤 */
tr.cfs-sec td { background: var(--gray-0); font-weight: 600; border-bottom: 1px solid var(--gray-2); }
.ok-note { color: var(--ok); }
.warn-note { color: var(--warn); font-weight: 600; }
/* 자금출납장 총계 3분해 — 실입출금·대체 행은 옅게, 총계(.totals)가 마무리 괘선 */
tfoot tr.cb-split:first-child td { border-top: 2px solid var(--rule); }
tfoot tr.cb-split td { color: var(--gray-5); border-bottom: 1px solid var(--gray-1); }

/* ── [전표 입력(그리드)] Tabulator — 자금예측과 같은 표 문법. 저장된 행(회색)=읽기 전용,
   같은 전표는 번호를 공유하고 묶음별로 띠를 교차(.jg-g1). */
#jg-grid { margin-bottom: 12px; border: 1px solid var(--line); }
#jg-grid .tabulator-cell, #jg-grid .tabulator-col { font-size: 13px; }
#jg-grid .tabulator-cell { font-variant-numeric: tabular-nums; }
#jg-grid .tabulator-row.jg-saved { background: var(--bg-soft); color: var(--gray-6); }
#jg-grid .tabulator-row.jg-saved.jg-g1 { background: var(--gray-1); }
#jg-grid .tabulator-row.jg-first .tabulator-cell { border-top: 1px solid var(--gray-2); }   /* 전표 경계선 */
#jg-grid .tabulator-row.jg-input { background: #fff; }
#jg-grid .tabulator-row.jg-input.jg-g1 { background: var(--gray-0); }
#jg-grid .tabulator-row.jg-unbal .tabulator-cell[tabulator-field="debit"],
#jg-grid .tabulator-row.jg-unbal .tabulator-cell[tabulator-field="credit"] { color: var(--warn); }   /* 묶음 대차 불일치 */
#jg-grid .tabulator-row.jg-error { outline: 2px solid var(--danger); outline-offset: -2px; }         /* 저장 오류 행 */
/* 저장된 전표를 고치는 중(2026-09-06 수석 확정 문법): 배경은 **입력 행과 같은 흰색**(=아직 장부에 반영 안 됨),
   왼쪽에 주황 띠로 신규 입력과 구분. 일자·번호 칸만 회색으로 잠긴다. */
#jg-grid .tabulator-row.jg-editing { background: #fff; }
#jg-grid .tabulator-row.jg-editing.jg-g1 { background: var(--gray-0); }
#jg-grid .tabulator-cell.tabulator-editing { background: #fff; }
/* 편집 입력칸은 셀 폭에 맞춘다 — 기본 <input> 폭(≈292px)이 셀(120px)을 넘쳐 브라우저가 "…"를 그렸다(2026-09-05 수석) */
#jg-grid .tabulator-cell.tabulator-editing input { background: #fff; color: var(--gray-9); width: 100%; box-sizing: border-box; }
/* 숫자 칸은 편집 중에도 오른쪽 정렬 — 칸을 열면 왼쪽으로 튀어 보였다(2026-09-05 수석) */
#jg-grid .tabulator-cell.tabulator-editing[tabulator-field="entry_no"] input,
#jg-grid .tabulator-cell.tabulator-editing[tabulator-field="debit"] input,
#jg-grid .tabulator-cell.tabulator-editing[tabulator-field="credit"] input,
#jg-grid .tabulator-cell.tabulator-editing[tabulator-field="foreign_amount"] input,
#jg-grid .tabulator-cell.tabulator-editing[tabulator-field="fx_rate"] input { text-align: right; }
#jg-grid .jg-cell-select { width: 100%; height: 100%; box-sizing: border-box; font: inherit; border: 1px solid var(--accent); border-radius: 3px; background: #fff; }
/* 제품 칸은 평상시에도 폼의 select처럼 — 테두리 상자 + ▾. 클릭하면 진짜 드롭다운이 열린다(2026-09-05 수석) */
#jg-grid .jg-selbox { display: block; position: relative; border: 1px solid var(--gray-2); border-radius: 5px;
    padding: 1px 18px 1px 6px; background: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#jg-grid .jg-selbox.empty { color: var(--gray-6); }
/* 빈 칸 안내 글자 — 폼 [전표 입력]의 placeholder와 같은 자리·같은 회색(2026-09-05 수석) */
#jg-grid .jg-ph { color: var(--gray-6); }
#jg-grid .jg-selbox::after { content: "▾"; position: absolute; right: 5px; top: 0; color: var(--gray-6); font-size: 11px; }
#jg-grid .gce-wrap .acombo input { width: 100%; }
/* 선택된 입력 묶음(펼침 패널이 붙은 전표) */
#jg-grid .tabulator-row.jg-sel .tabulator-cell { background: var(--accent-subtle); }
/* 고른 묶음의 연청(.jg-sel)보다 이 문법이 앞선다 — 수정 중은 '흰 배경 + 주황 띠'로 읽혀야 한다 */
#jg-grid .tabulator-row.jg-editing .tabulator-cell { background: transparent; }
#jg-grid .tabulator-row.jg-editing .tabulator-cell[tabulator-field="date"],
#jg-grid .tabulator-row.jg-editing .tabulator-cell[tabulator-field="entry_no"] {
    background: var(--gray-1); color: var(--gray-6); cursor: default;
}
/* 주황 띠는 **첫 셀**에 — 행에 주면 잠긴 일자 칸의 배경이 덮는다(실측) */
#jg-grid .tabulator-row.jg-editing .tabulator-cell:first-child { box-shadow: inset 3px 0 0 var(--warn); }
/* 펼침 패널(2판 C 배치) — 묶음 마지막 행 요소 안에 블록으로 덧붙는다(Tabulator nested 패턴). 셀은 건드리지 않는다 */
/* 패널은 행 아래에 절대배치 + 행의 margin-bottom으로 자리를 만든다 — 행 offsetHeight에 패널이 들어가면 Tabulator 범위 테두리·
   활성 셀 표시가 패널까지 늘어난다(09-04 수석 스크린샷). margin은 offsetHeight에 안 들어가고 다음 행 위치에는 반영된다. */
#jg-grid .jg-panel { position: absolute; left: 0; top: 100%; width: 100%; box-sizing: border-box; padding: 8px 12px 10px; background: #fff; z-index: 3;
    white-space: normal; font-size: 13px; }
    /* 위 점선(09-05)에 이어 **아래 진한 회색 구분선도 뺐다**(2026-09-05 수석) — 입력 칸이 사라져 합계 한 줄만 남은 뒤로는
       패널이 폼처럼 보이지 않으므로 굵은 경계가 필요 없고, 다음 전표 행은 자기 괘선으로 이미 구분된다. */
/* 합계 줄 한 줄 — 입력 칸을 걷어낸 뒤 남은 유일한 줄이라 열 격자가 아니라 한 줄 흐름이다(2026-09-05 수석) */
#jg-grid .jg-panel-foot { display: flex; align-items: center; gap: 12px; }
#jg-grid .jg-panel-foot .jg-p-head { display: flex; align-items: center; gap: 8px; }
#jg-grid .jg-panel-foot .chip { font-size: 11px; padding: 1px 8px; border-radius: 10px; background: var(--accent-subtle); color: var(--accent); }
#jg-grid .jg-panel-foot .chip.edit { background: #fff3cd; color: #8a6100; }     /* 수정 중 */
#jg-grid .jg-panel-foot .jg-p-undo { font: inherit; font-size: 12px; padding: 1px 8px; border: 1px solid var(--gray-2);
    border-radius: 5px; background: #fff; color: var(--gray-9); cursor: pointer; white-space: nowrap; }
#jg-grid .jg-panel-foot .jg-p-undo:hover { background: var(--gray-0); }
#jg-grid .jg-panel-foot.aligned .jg-p-undo { position: absolute; top: -1px; }
#jg-grid .jg-panel-foot .num { min-width: 92px; text-align: right; font-variant-numeric: tabular-nums; }
#jg-grid .jg-panel-foot .jg-p-bal { font-weight: 600; white-space: nowrap; }
/* 합계 숫자를 차변·대변 열 아래에 세운 상태(alignPanelCols) — 좌표는 JS가 넣는다 */
#jg-grid .jg-panel-foot.aligned { position: relative; min-height: 18px; }
#jg-grid .jg-panel-foot.aligned .jg-p-label,
#jg-grid .jg-panel-foot.aligned .num,
#jg-grid .jg-panel-foot.aligned .jg-p-bal { position: absolute; top: 0; }
#jg-grid .jg-panel-foot.aligned .jg-p-label { text-align: right; }
#jg-grid .jg-panel .spacer { flex: 1; }
#jg-form { margin-bottom: 8px; flex-wrap: wrap; }
/* 툴바 단축키 안내 — 좁은 화면에서는 두 줄로 접히되 툴바 높이가 따라 늘어나게(2026-09-05 수석) */
#jg-form .jg-keyhint { flex: 1 1 auto; min-width: 0; font-size: 12px; line-height: 1.5; }
/* 열 그룹(외화 @ 환율)이 생겨 머리가 2단 — 1단짜리 열 제목을 세로 가운데로(2026-09-05 수석).
   ⚠ `.tabulator-col`에 flex를 주면 머리 전체 배치가 무너진다(실측: 열이 세로로 쌓임). Tabulator 6.3에는 headerVertAlign도 없다.
   흐름은 그대로 두고 제목만 상대 위치로 내린다. 열 그룹과 그 자식(외화금액·환율)은 이미 한 줄이라 대상이 아니다. */
#jg-grid .tabulator-headers > .tabulator-col:not(.tabulator-col-group) { position: relative; }
#jg-grid .tabulator-headers > .tabulator-col:not(.tabulator-col-group) > .tabulator-col-content {
    position: relative; top: 50%; transform: translateY(-50%);
}

/* 합계는 펼침 패널 바닥에만 — 표 아래 합계 행(tabulator-calcs)은 중복이라 뺐다(2026-09-05 수석) */
#jg-grid .jg-calc-ok { color: #1a7f37; white-space: nowrap; }
#jg-grid .jg-calc-bad { color: var(--danger); white-space: nowrap; }
#jg-draft { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
#jg-draft[hidden] { display: none; }
/* 버튼 안 단축키 안내(작은 글씨) — 그리드 전표 입력이 첫 용처(09-04 수석) */
.btn kbd.key { font: inherit; font-size: 11px; font-weight: 400; opacity: .7; margin-left: 4px; }
.muted kbd.key { font: inherit; font-size: 11px; }

/* ── [자금예측] Tabulator 그리드 — 표 문법(13px·tabular-nums)에 맞춘 최소 보정.
   계산 칸(.fc-calc)은 회색 바탕 = "시스템이 계산, 직접 못 고침" 신호. */
#fc-grid { margin-bottom: 12px; border: 1px solid var(--line); }
#fc-grid .tabulator-cell, #fc-grid .tabulator-col { font-size: 13px; }
#fc-grid .tabulator-cell { font-variant-numeric: tabular-nums; }
#fc-grid .tabulator-cell.fc-calc { background: var(--bg-soft); color: var(--gray-6); }
/* 월중 최저 — 이 달 잔액이 가장 얇아지는 지점의 잔액 셀(원화·외화 각 한 곳, 09-02 수석) */
#fc-grid .tabulator-cell.fc-low-cell { background: var(--attention-subtle); color: var(--attention); font-weight: 600; }
/* 편집 중인 셀은 흰 바탕 — "지금 여기 입력 중" 신호(2026-08-27 수석 요청) */
#fc-grid .tabulator-cell.tabulator-editing { background: #fff; }
#fc-grid .tabulator-cell.tabulator-editing input,
#fc-grid .tabulator-cell.tabulator-editing select { background: #fff; color: var(--gray-9); }
/* 반복항목 제안 표 — 10행쯤에서 자르고 컨테이너 안에서 세로 스크롤(2026-08-27 수석 요청).
   머리행은 컨테이너 상단에 고정(전역 thead sticky는 topbar 기준이라 안에서는 top:0로). */
#fc-compare { max-height: 405px; overflow-y: auto; }
#fc-compare thead th { position: sticky; top: 0; z-index: 2; background: var(--gray-0); }
/* 드롭다운 셀 표시(▾) + 선택 리스트 키보드 이동 반전(research/2026-08-28-grid-edit-ux.md).
   리스트는 body에 뜨므로 #fc-grid 밖 — .tabulator-edit-list로만 좁힌다. */
/* ▾는 절대배치 — float이면 글자+▾가 칸 폭을 넘칠 때 다음 줄로 떨어져 행이 2줄
   높이가 된다(08-29 실사고: Windows 폰트에서 "달러(×단가)" 행만 커짐) */
#fc-grid .fc-dd { position: absolute; right: 2px; top: 50%; transform: translateY(-50%); color: var(--muted); font-size: 10px; }
/* 출처 칸의 삭제 ✕ — 같은 이유로 절대배치, hover 전엔 옅게 */
#fc-grid .fc-del { position: absolute; right: 2px; top: 50%; transform: translateY(-50%); color: var(--muted); font-size: 11px; cursor: pointer; padding: 0 2px; }
#fc-grid .fc-del:hover { color: var(--danger, #c00); }
@media print { #fc-grid .fc-del { display: none; } }
.tabulator-edit-list .tabulator-edit-list-item.focused { outline: none; background: var(--accent); color: #fff; }
.tabulator-edit-list .tabulator-edit-list-item.active { background: var(--gray-1); color: var(--gray-9); }
.tabulator-edit-list .tabulator-edit-list-item.active::after { content: " ✓"; }
.tabulator-edit-list .tabulator-edit-list-item.active.focused { background: var(--accent); color: #fff; }
@media print { #fc-grid .fc-dd { display: none; } }
/* 열 폭 다이어트 보조 — 셀 좌우 패딩 축소(19열×2px 절약, 2026-08-28 수석: 가로 스크롤 최소화) */
#fc-grid .tabulator-cell { padding-left: 3px; padding-right: 3px; }
#fc-grid .tabulator-col-content { padding-left: 3px; padding-right: 3px; }

/* 반복항목 제안 접힘 — 제목 줄이 h2 역할(접힘 기본, 요약 카운트 동반) */
.fc-fold > summary { cursor: pointer; user-select: none; font-size: 16px; font-weight: 600; margin: 24px 0 10px; }
.fc-fold[open] > summary { margin-bottom: 6px; }
/* [자금예측] 도움말 흐름도 — 세 갈래(마스터·납품·확정)가 ④예측표로 모인다.
   담당자 교육용 첫 그림(2026-08-28 수석 요청) — 토큰만, 인라인 style 없음 */
.fc-map { display: grid; grid-template-columns: 1fr auto; gap: 6px 10px; align-items: stretch;
    margin: 4px 0 10px; }
.fc-map .fc-lane { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.fc-map .fmb { border: 1px solid var(--gray-2); border-radius: 6px; background: #fff;
    padding: 3px 8px; font-size: 12px; line-height: 1.25; white-space: nowrap; }
.fc-map .fmb small { display: block; color: var(--muted); font-size: 11px; }
.fc-map .fmb.fmm { border-color: var(--accent); }
.fc-map .fma { color: var(--muted); }
.fc-map .fmn { color: var(--muted); font-size: 12px; }
.fc-map .fc-goal { grid-column: 2; grid-row: 1 / span 3; display: flex; flex-direction: column;
    justify-content: center; text-align: center; border: 1px solid var(--accent); border-radius: 6px;
    background: var(--bg-soft); padding: 6px 14px; font-size: 12px; }
.fc-map .fc-goal small { color: var(--muted); font-size: 11px; line-height: 1.5; }
.fc-map .fc-lane::after { content: "▶"; color: var(--accent); margin-left: auto; }
/* 납품계획 묶음 합계행 — 표 합계 문법(먹선 위 경계) */
.fc-plan-total td { border-top: 2px solid var(--gray-9); font-weight: 600; }
/* 예측표 그리드 맨 아래 합계 행 — 같은 합계 문법(값은 서버 계산 totals·closing) */
#fc-grid .fc-total-row .tabulator-cell { border-top: 2px solid var(--gray-9); font-weight: 600; }
/* 납품계획 표 열 폭(2026-08-28 수석) — 금액 두 열 넓게, 수량·단가 좁게, 리드일 최소 */
#fc-plan-fold td.fc-amt, #fc-plan-fold th.fc-amt { min-width: 140px; }
#fc-plan-fold input.w-qty { width: 72px; text-align: right; }
#fc-plan-fold input.w-lead { width: 34px; text-align: right; }
/* 예측 그리드 2단 헤더 — 묶음 없는 열 제목은 세로 가운데(08-29 수석) */
#fc-grid .tabulator-header .tabulator-col:not(.tabulator-col-group) .tabulator-col-content {
    height: 100%; display: flex; flex-direction: column; justify-content: center;
}
