/* 국민렌탈 통합 전산시스템 화면.

   거래처 모듈(D:\customers) 의 style.css 를 **복사**해 왔다. hr / KMRENT Terminal 과
   변수명·클래스 이름을 일부러 같게 유지한다 — 코드는 공유하지 않지만(15-1 완전소각),
   한쪽 디자인을 고치면 다른 쪽에 같은 이름으로 옮길 수 있어야 한다.
   클래스 이름을 마음대로 바꾸지 않는다.

   화면 규칙: 이모지를 쓰지 않는다. 가로 스크롤을 만들지 않는다(열 비율 + 말줄임).
   저장은 [저장] 을 눌러야 반영되고, 닫으면 버린다. 목록에는 저장된 값만 나온다.
   확인은 브라우저 팝업(confirm)을 쓰지 않는다 — 창에 따라 차단되면 아무 일도
   일어나지 않은 것처럼 보인다(2026-09-24 실제로 겪음). 모달 안에서 묻는다.

   달라진 것 하나: 로그인 화면이 별도 주소(/login/)다. 옛 규약은 한 문서 안에서
   .hidden 으로 갈아끼웠는데, 그건 화면을 브라우저가 그리던 때의 방식이다. 지금은
   서버가 그려 내려주므로 주소를 나눈다. 마크업과 클래스 이름은 그대로 쓴다. */
:root {
  --bg: #f4f6f8;
  --card-bg: #ffffff;
  --border: #dde2e8;
  --text: #1f2937;
  --text-muted: #6b7280;
  --primary: #2563eb;
  --primary-hover: #1d4ed8;
  --danger: #dc2626;
  --danger-bg: #fee2e2;
  --header-bg: #eef2f7;
  font-family: var(--font-sans);
}

* { box-sizing: border-box; }

.hidden { display: none; }

/* ---------------- 버튼 (hr 과 동일) ---------------- */

.btn-primary { background: var(--primary); color: var(--c-on-dark); }
.btn-primary:hover { background: var(--primary-hover); }
.btn-secondary { background: var(--header-bg); color: var(--text); }
.btn-secondary:hover { background: var(--border); }
.btn-danger { background: var(--danger-bg); color: var(--danger); }
.btn-danger:hover { background: #fbcfcf; }
/* **중요 리셋 단추** — 꽉 찬 빨강. 한 번 더 묻는 확정 단추(`btn-reset-go`)는 판독 알림처럼 더 붉게
   깜빡인다 (대표님 2026-10-04 "관계리셋 버튼은 중요한 버튼이라 빨간색 · 중요 리셋버튼은 앞으로 이
   빨간색 버튼효과 적용하자"). 되돌리기 어려운 리셋은 모두 이 두 칸을 쓴다. */
.btn-reset { background: var(--c-danger); border-color: var(--c-danger); color: var(--c-on-dark); }
.btn-reset:hover { background: #a91f1f; border-color: #a91f1f; }
.btn-reset-go { animation: reset-blink 1s steps(1, end) infinite; }
@keyframes reset-blink {
  50% { background: #ff1f1f; border-color: #ff1f1f; box-shadow: 0 0 0 3px rgba(255, 31, 31, .35); }
}
@media (prefers-reduced-motion: reduce) { .btn-reset-go { animation: none; } }
/* 파랑 확정 깜빡 — [SEND] 뒤 [Confirm] (대표님 2026-10-04 "반짝반짝"). 빨강과 같은 박자 */
.btn-go-blue { background: #1e40af; border-color: #1e40af; animation: go-blue-blink 1s steps(1, end) infinite; }
@keyframes go-blue-blink {
  50% { background: #0b5cff; border-color: #0b5cff; box-shadow: 0 0 0 3px rgba(11, 92, 255, .55); }
}
@media (prefers-reduced-motion: reduce) { .btn-go-blue { animation: none; } }
/* 주황 확정 깜빡 — **정보변경 재확인** (대표님 2026-10-04 색상코드: 빨강 삭제 만류 · 주황 정보변경 · 파랑 발송).
   첫 쓰임은 OCR대기 ocr_shot 의 [분류변경] — 시스템이 정한 분류(자석)를 떼려 할 때. 같은 박자 */
.btn-go-orange { background: var(--c-warn); border-color: var(--c-warn); color: var(--c-on-dark); animation: go-orange-blink 1s steps(1, end) infinite; }
@keyframes go-orange-blink {
  50% { background: #ff7a00; border-color: #ff7a00; box-shadow: 0 0 0 3px rgba(255, 122, 0, .45); }
}
@media (prefers-reduced-motion: reduce) { .btn-go-orange { animation: none; } }

.btn:disabled { opacity: .5; cursor: default; }
.spacer { flex: 1; }

/* ---------------- 로그인 화면 (hr · Terminal 과 동일 구조) ---------------- */
.login-screen {
  position: fixed; inset: 0; background: var(--bg);
  display: flex; align-items: center; justify-content: center; z-index: 200;
}
/* .hidden 과 특이도가 같아서 나중에 선언된 display:flex 가 이겨버린다.
   이 줄이 없으면 로그인에 성공해도 로그인 화면이 안 걷힌다. */
.login-screen.hidden { display: none; }

.login-field-row input:focus { outline: none; border-color: #3a7fc1; box-shadow: 0 0 0 2px rgba(58,127,193,.25); }
.login-submit-btn {
  display: block; width: 100%; margin-top: var(--sp-3); padding: 9px;
  background: linear-gradient(to bottom, #3a7fc1, #1c5a94); color: var(--c-on-dark);
}
.login-submit-btn:hover { background: linear-gradient(to bottom, #4a8fd1, #2c6aa4); }
.login-error { color: var(--danger); font-size: var(--fs-md); margin: 0 0 var(--sp-5); text-align: center; }
.login-error.hidden { display: none; }

/* 열람전용 계정에게는 편집 컨트롤을 일괄로 감춘다 (hr 과 같은 방식) */
body.role-viewer .edit-only { display: none !important; }

/* ---------------- 상단 탭바 (hr 과 동일) ---------------- */

.top-level-tabs-scroll { display: flex; align-items: center; gap: var(--sp-1); flex: 1; min-width: 0; }

/* ---------------- 본문 ---------------- */

.search-input:focus { outline: none; border-color: #3a7fc1; box-shadow: 0 0 0 2px rgba(58,127,193,.25); }

/* 표는 가로로 넘치지 않는다. 열 비율을 고정하고 긴 값은 말줄임한다. */

.grid tbody tr { cursor: pointer; }

.grid tbody tr:last-child td { border-bottom: none; }

/* 열 너비는 **[양식설정] 이 정한다** — 표 위의 <colgroup> 이 유일한 근거다.
   여기에 `.col-code { width: … }` 같은 것을 두면 `table-layout: fixed` 에서 그 열만
   콜그룹을 무시하고 버틴다 (2026-09-27: 양식설정에서 줄여도 거래처코드 열이 안 줄었다). */

/* 판 넘김 — 표 밑에 한 줄. 한 판에 50줄이고, 창을 띄울 때도 그 판만 그린다 */

.pager-at { font-size: var(--fs-lg); font-weight: var(--fw-semi); color: var(--text); }

/* ---------------- 개발로그 ---------------- */
.devlog-title { margin: 0; font-size: var(--fs-2xl); }
.devlog-sub { color: var(--text-muted); font-size: var(--fs-md); }
.devlog-sub code { font-size: var(--fs-md); }

.devlog-item {
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--r-3);
  margin-bottom: var(--sp-4); overflow: hidden;
}
.devlog-head {
  display: flex; align-items: baseline; gap: var(--sp-5);
  padding: var(--sp-5) 14px; cursor: pointer; background: var(--card-bg);
}
.devlog-head:hover { background: var(--c-sunken); }
.devlog-item.open .devlog-head { background: var(--header-bg); border-bottom: 1px solid var(--border); }
.devlog-no { color: var(--text-muted); font-size: var(--fs-md); font-weight: var(--fw-semi); min-width: 34px; }
.devlog-when { color: var(--text-muted); font-size: var(--fs-md); white-space: nowrap; }
.devlog-name { font-size: var(--fs-lg); font-weight: var(--fw-semi); flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.devlog-mark { color: var(--text-muted); font-size: var(--fs-md); }

.devlog-body { padding: var(--sp-6) var(--sp-7) var(--sp-7); font-size: var(--fs-lg); line-height: 1.65; }
.devlog-body.hidden { display: none; }
.devlog-body h4 { margin: 14px 0 var(--sp-3); font-size: var(--fs-lg); color: var(--primary); }
.devlog-body h4:first-child { margin-top: 0; }
.devlog-body p { margin: 0 0 var(--sp-4); }
.devlog-body ul { margin: 0 0 var(--sp-4); padding-left: 18px; }
.devlog-body li { margin-bottom: 3px; }
.devlog-body code {
  background: var(--header-bg); border-radius: 3px; padding: 1px var(--sp-2); font-size: var(--fs-md);
  word-break: break-all;
}
.devlog-body strong { font-weight: var(--fw-semi); }

/* ---------------- 모달 (hr 과 동일 구조) ---------------- */
.modal-backdrop { position: fixed; inset: 0; background: rgba(15,23,42,.35); z-index: 100; }
.modal-backdrop.hidden { display: none; }
.modal {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 560px; max-width: 94vw; max-height: 88vh;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 16px 48px rgba(0,0,0,.25); z-index: 101;
  display: flex; flex-direction: column;
}
.modal.hidden { display: none; }
.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-6) var(--sp-7); border-bottom: 1px solid var(--border); background: var(--header-bg);
  border-radius: 8px 8px 0 0;
}
.modal-header h2 { margin: 0; font-size: var(--fs-2xl); }
.modal-header-actions { display: flex; align-items: center; gap: var(--sp-4); }
.seq-info { color: var(--text-muted); font-size: var(--fs-md); }
.modal-body { padding: var(--sp-7) 18px; overflow-y: auto; overflow-x: hidden; }
.modal-footer {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-6) var(--sp-7); border-top: 1px solid var(--border);
}
.stamp { color: var(--text-muted); font-size: var(--fs-md); margin-right: var(--sp-4); }

.field-row { display: flex; align-items: center; gap: var(--sp-5); margin-bottom: var(--sp-5); }
.field-row label { width: 84px; flex-shrink: 0; text-align: right; font-size: var(--fs-lg); color: var(--text-muted); }
.field-row input {
  flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: var(--r-2);
  padding: 7px 9px; font-size: var(--fs-lg); font-family: inherit;
}
.field-row input:focus { outline: none; border-color: #3a7fc1; box-shadow: 0 0 0 2px rgba(58,127,193,.25); }
.field-row .hint { color: var(--text-muted); font-size: var(--fs-md); white-space: nowrap; }

/* ---------------- 입력칸의 인자 이름 ----------------
   칸 안에 표의 인자 이름(`cust_name`)을 옅게 얹는다. 붙이는 일은 app.js 가 `name` 을 보고
   기계적으로 한다 — 칸마다 손으로 적어 두지 않는다(대표님 2026-09-27 "하드코딩 안 쓴다"). */
.key-box { position: relative; display: flex; min-width: 0; flex: 1 1 auto; }
.key-box > input, .key-box > textarea { flex: 1 1 auto; min-width: 0; width: 100%; }
.key-tag {
  position: absolute; top: 50%; transform: translateY(-50%); right: 9px;
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .2px;
  color: var(--text-muted); opacity: .32; pointer-events: none; user-select: none;
  max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* **늘 오른쪽에 붙인다.** 어떤 칸은 왼쪽 어떤 칸은 오른쪽이면 눈이 헷갈린다
   (대표님 2026-09-27 "전화랑 적요만 앞이네"). 값이 들어 있으면 더 옅게. */
.key-box.filled .key-tag { opacity: .22; }
/* 날짜 칸은 오른쪽 끝에 달력 단추가 있다 */
.key-box.key-inset .key-tag { right: 30px; }
/* 이름표(placeholder)가 이미 있는 칸은 겹치니 평소 감춘다 — 올리거나 커서를 넣을 때만 */
.key-box.key-shy .key-tag { display: none; }
/* 볼 때는 칸 **전체 폭**을 쓴다. `acct_use` 가 `acc…` 로 잘려 식별이 안 됐다
   (대표님 2026-09-27). 그래도 넘치면 칸에 걸린 안내창(title)이 다 알려 준다. */
.key-box.key-shy.key-peek .key-tag {
  display: block; left: 10px; right: 9px; max-width: none;
  font-size: 9.5px; opacity: .6;
}
.key-box textarea ~ .key-tag { top: 9px; transform: none; }

/* ---------------- 공유설정 자물쇠 ----------------
   양식(스키마)은 모두가 같은 한 벌이라 한 번에 한 사람만 고친다. 쥐지 않은 사람에게는
   손댈 수 없다는 것이 **보여야** 한다 — 눌러 놓고 안 되는 것이 제일 나쁘다. */
.lock-note { font-size: var(--fs-md); color: var(--danger); white-space: nowrap; }
.lock-guide { margin: 0 0 var(--sp-5); padding: 7px var(--sp-5); font-size: 12.5px;
              color: var(--text-muted); background: var(--header-bg);
              border: 1px solid var(--border); border-radius: var(--r-2); }
/* 보기만 되는 동안은 안쪽을 흐리고 손이 안 닿게 한다 */
.look-only .grid, .look-only form, .look-only .btn { opacity: .55; }
.look-only .grid, .look-only .grid *, .look-only .btn { pointer-events: none; }
.look-only .lock-guide { opacity: 1; }
.form-error { color: var(--danger); font-size: var(--fs-lg); margin: 0 0 var(--sp-6); }
.form-error.hidden { display: none; }

/* 확인은 브라우저 팝업(confirm)을 쓰지 않는다 — 창에 따라 팝업이 차단되면 아무 일도 일어나지
   않은 것처럼 보인다(2026-09-24 실제로 겪음). 모달 안에서 묻는다. */
.confirm-box {
  border: 1px solid #f0c36d; background: #fdf6e3; border-radius: var(--r-3);
  padding: var(--sp-6) 14px; margin: 0 0 14px;
}
.confirm-box.hidden { display: none; }
.confirm-text { margin: 0 0 var(--sp-5); font-size: var(--fs-lg); line-height: 1.55; white-space: pre-line; }
.confirm-actions { display: flex; justify-content: flex-end; gap: var(--sp-4); }

@media (max-width: 700px) {
  .field-row .hint { display: none; }
  .search-input { width: auto; flex: 1; }
}

/* ---------------- 알림 줄 (서버가 내려주는 메시지) ---------------- */
.notice { list-style: none; margin: 0 0 var(--sp-6); padding: 0; }
.notice:empty { display: none; }

.notice li.error { border-left-color: var(--danger); }
.notice li.success { border-left-color: var(--primary); }
.notice li.fading { opacity: 0; transition: opacity .4s; }   /* 안내는 잠깐 (app.js noticeFade) */

/* 목록 줄 전체를 누르면 열린다 (옛 화면과 같은 동작) */
.grid td a { color: inherit; text-decoration: none; }
.grid td a:hover { text-decoration: underline; }

/* 모달 안에서 [닫기]·[취소] 는 링크지만 단추로 보인다 */
a.btn { display: inline-block; text-decoration: none; line-height: 1.4; }

/* 충돌 표 — 상대 값 / 내 값 나란히 */
.clash { width: 100%; border-collapse: collapse; margin: 0 0 var(--sp-6); font-size: var(--fs-lg); }
.clash th, .clash td {
  border: 1px solid var(--border); padding: var(--sp-3) 9px; text-align: left; vertical-align: top;
}
.clash th { background: var(--header-bg); color: var(--text-muted); font-weight: var(--fw-semi); }
.clash td.mine { background: var(--c-sunken); }

/* ---------------- 이동 가능한 팝업창 ----------------
   옛 모달을 창처럼 쓴다. 제목 줄을 잡아 끌면 따라온다(app.js).
   가운데 정렬은 transform 으로 하고, 처음 끌 때 left/top 으로 바뀐다. */

/* `<a>` 로도 `<button>` 으로도 쓴다 — 자물쇠를 풀어야 하는 창에서는 단추다.
   둘이 똑같이 보여야 한다(글꼴·바탕·테두리를 눌러 둔다). */
.titlebar-close {
  background: none; border: 0; font-family: inherit; cursor: pointer;
  color: var(--c-on-dark); text-decoration: none; font-size: var(--fs-lg); line-height: 1;
  padding: var(--sp-2) var(--sp-4); border-radius: 3px;
}
.titlebar-close:hover { background: rgba(255,255,255,.22); }

/* ---------------- 코드 구분 [사업자][기타] ---------------- */
.kind-pick { display: inline-flex; flex-shrink: 0; }
.kind-pick label { display: inline-block; cursor: pointer; margin: 0; width: auto; text-align: center; }
.kind-pick input { position: absolute; opacity: 0; pointer-events: none; }

.kind-pick label:first-child span { border-radius: var(--r-2) 0 0 var(--r-2); }
.kind-pick label:last-child span { border-radius: 0 var(--r-2) var(--r-2) 0; border-left: none; }
.kind-pick input:checked + span { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }
.kind-pick input:focus-visible + span { box-shadow: 0 0 0 2px rgba(58,127,193,.35); }

/* 내린 거래처(사용중지 · 폐업) — 목록에 섞여 보일 때 흐리게 둔다. 지운 것이 아니다. */
.grid tr.row-off td { color: var(--text-muted); }
.toolbar .off-pick { flex: 0 0 auto; display: flex; align-items: center; gap: 3px; }
.toolbar .off-pick span { color: var(--text-muted); }
.toolbar .off-pick input:checked + span { color: var(--text); }

/* 거래처코드 줄 — 입력칸은 다른 칸만큼 늘어나고, 구분 단추는 오른쪽 끝에 작게 */
.field-row #id_cust_code, .field-row #id_new_cust_code { flex: 1 1 auto; }
.field-row .kind-pick { flex: 0 0 auto; margin-left: var(--sp-3); }

/* 계좌정보 — 줄마다 은행명 · 계좌번호 · 예금주명 · 용도 + [대표]. 한 거래처에 여러 줄이
   선다(대표님 2026-09-25). 이름표는 칸 안(placeholder)에 있고, 너비는 px 가 아니라
   비율이라 창을 넓혀도 같은 결로 늘어난다. 부가정보로 더한 계좌정보도 같은 모양이다. */
/* 칸 이름은 **장고 모델의 칸 이름**을 따라간다 (폼셋, 2026-09-28) */
.acct-row .acct-bank { flex: 3 1 0; }
.acct-row .acct-number { flex: 4 1 0; }
.acct-row .acct-holder { flex: 3 1 0; }
.acct-row .acct-purpose { flex: 2 1 0; }
.acct-row input::placeholder { color: var(--text-muted); opacity: .7; }

.acct-list { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.acct-item { display: flex; align-items: center; gap: var(--sp-2); }
/* 빈 서식([계좌 추가] 때 베낄 본) 은 안 보인다. `display:flex` 가 `hidden` 을 덮으므로
   따로 눌러 준다 — 안 그러면 빈 줄이 하나 더 있는 것처럼 보인다 (2026-09-28). */
.acct-item[hidden] { display: none; }
/* 줄 안의 [대표]·[삭제] 는 **칸 이름표가 아니다.** `.field-row label` 의 84px 고정폭을
   물려받아 둘이 멀찍이 떨어져 있었다 (2026-09-28). 글자만큼만 차지하게 한다. */
.modal.window .field-row .acct-item label { width: auto; flex: 0 0 auto; text-align: left; }
/* 값 칸과 라벨 칸. **라벨은 곁다리다** — `팩스` 두 글자 들어갈 자리가 번호 칸과 반씩
   나눠 갖고 있었다 (대표님 2026-10-01 "라벨칸좀 작게"). 값은 길고 라벨은 짧다. */
.acct-item .acct-no { flex: 1 1 0; min-width: 0; }
.acct-item .acct-use { flex: 0 0 68px; min-width: 0; }
.acct-item .acct-main,
.acct-item .acct-del { display: flex; align-items: center; gap: 3px; white-space: nowrap; }
.acct-item .acct-del { margin-left: var(--sp-1); }
.acct-item .acct-main span { color: var(--text-muted); }
.acct-item .acct-main input:checked + span { color: var(--text); }
/* 지우기는 [삭제] 체크다 — 저장해야 떨어진다. 대표 옆에 나란히 둔다 */

.acct-item .acct-del span { color: var(--text-muted); font-size: var(--fs-md); }
.acct-item .acct-del input:checked + span { color: var(--danger); }
.acct-item .acct-x {
  flex: 0 0 auto; background: none; border: 0; padding: 0 var(--sp-1);
  color: var(--text-muted); cursor: pointer;
}
.acct-item .acct-x:hover { color: var(--danger); }
.acct-list .acct-add {
  align-self: flex-start; background: none; border: 0; padding: 0;
  color: var(--primary); cursor: pointer;
}
.acct-list .acct-add:hover { text-decoration: underline; }

/* 첨부 — 줄 자체가 받는 자리다. [파일 선택] 단추를 두지 않는다
   (대표님 2026-09-25 "행을 클릭하거나 드래그, ctrl+v 로"). */
/* 받는 칸은 **어느 것이든 같게 생긴다** (대표님 2026-09-30 "같은 기능인데 ui가 다름 ·
   가운데정렬로 통일"). [사업자등록증] 과 [OCR입력(수정)] 은 하는 일이 다르지만 받는
   몸짓은 같으므로 같게 보여야 한다 — 다르게 생기면 다르게 쓰는 것인 줄 안다. */
.dropzone {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--border); background: var(--card-bg);
  padding: 0 var(--sp-4); font-size: var(--fs-md); color: var(--text-muted); cursor: pointer;
  overflow: hidden; white-space: nowrap;
}
.dropzone .dz-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dropzone input[type="file"] { display: none; }
.dropzone:hover, .dropzone:focus { border-color: var(--primary); color: var(--text); outline: none; }
.dropzone.over { border-color: var(--primary); border-style: solid; background: var(--header-bg); }
.dropzone.has-file { border-style: solid; color: var(--text); font-family: var(--font-mono); }
.dropzone[data-inner] { position: relative; padding-right: 64px; }
.dropzone .dz-inner { position: absolute; top: 1px; right: 1px; height: var(--h-sm); padding: 0 var(--sp-3); font-size: var(--fs-sm); border: 1px solid var(--border); background: var(--header-bg); color: var(--text); cursor: pointer; font-family: inherit; }
.dropzone .dz-inner:hover { border-color: var(--primary); }
/* 더블클릭 기호 — 파일 고르기 창은 **두 번 눌러야** 뜬다(한 번은 붙는 칸 고르기). 안내 글 앞에 마우스+2x
   그림을 둔다(대표님 2026-10-05 "upload files (더블클릭 심볼 넣어주자)"). 템플릿마다 넣지 않고 여기 한 곳 */
/* 그림 안의 작은 2x 는 안 보여서 뺐고, 그림 **옆에 굵은 글자 `2X`** 로 둔다 (대표님 2026-10-05 "2X 잘 안보여") */
.dropzone .dz-text::before {
  content: "2X"; display: inline-block; margin-right: var(--sp-3); padding-left: 15px; vertical-align: 0;
  font: 700 11px/14px Arial, sans-serif; color: #4b5563;
  background: no-repeat left center/12px 14px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 20' fill='none' stroke='%234b5563' stroke-width='1.6' stroke-linecap='round'%3E%3Crect x='1.5' y='1.5' width='11' height='17' rx='5.5'/%3E%3Cline x1='7' y1='1.5' x2='7' y2='7.5'/%3E%3Cline x1='1.5' y1='8.5' x2='12.5' y2='8.5'/%3E%3C/svg%3E");
}
.dropzone.paste-here .dz-text::before, .dropzone.busy .dz-text::before, .dropzone.is-reading .dz-text::before,
.dropzone.has-file .dz-text::before { display: none; }
/* 한 장 칸이 단추와 한 줄에 설 때(CSV 업로드 · 구글 열쇠) — 이름이 보일 만큼은 넓게 */
.bulk-up .dropzone, form.field-row > .dropzone { min-width: 260px; }
/* 붙는 칸(Ctrl+V 가 갈 곳) — 한 번 누른 칸은 파랑, 아무것도 안 골랐을 때의 기본 칸은 옅게 (대표님 2026-10-05) */
.dropzone.paste-here { border: 2px solid var(--primary); color: var(--primary); background: var(--c-hover); }
.dropzone.paste-default { border-color: #9db4dc; }

/* 붙은 파일은 드롭존 아래에 `파일명 (X)` 로 나열한다 (대표님 2026-09-25).
   드롭존 안에는 안내 문구만 둔다 — 긴 파일 이름이 줄을 다 잡아먹지 않게. */
.file-list { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-1); }

.file-row .shot {
  width: 34px; height: 22px; flex: 0 0 auto; border: 1px solid var(--border);
  background: var(--c-surface); object-fit: cover; object-position: top center; cursor: zoom-in;
}
.file-row .shot.is-doc {
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-muted);
}
.file-row .shot:hover { border-color: var(--primary); }
.file-row .file-name {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; text-align: left; border: 0; background: none; padding: 0;
  font-family: var(--font-mono); font-size: var(--fs-md); color: var(--text); cursor: zoom-in;
}
.file-row .file-name:hover { color: var(--primary); text-decoration: underline; }
.file-row .file-x {
  flex: 0 0 auto; border: 0; background: none; padding: 0 var(--sp-1);
  font-family: var(--font-mono); font-size: var(--fs-md); color: var(--text-muted); cursor: pointer;
}
.file-row .file-x:hover { color: var(--danger); }
.file-row .off-note { font-size: var(--fs-sm); color: var(--danger); white-space: nowrap; }
.file-row .new-note { font-size: var(--fs-sm); color: var(--primary); white-space: nowrap; }
.file-row.is-off .shot { opacity: .4; }
.file-row.is-off .file-name { opacity: .5; text-decoration: line-through; }

/* 크게 보기 — 화면을 덮는 한 판. 바깥을 누르거나 Esc 로 닫는다 */
.lightbox {
  position: fixed; inset: 0; z-index: 400; background: rgba(15, 23, 42, .55);
  display: flex; align-items: center; justify-content: center;
}
.lightbox .frame {
  background: var(--card-bg); border: 1px solid var(--border);
  box-shadow: 2px 2px 0 rgba(15, 23, 42, .18); display: flex; flex-direction: column;
  max-width: 92vw; max-height: 92vh;
}
.lightbox .bar {
  display: flex; align-items: center; gap: var(--sp-4); padding: 3px var(--sp-2) 3px var(--sp-4);
  border-bottom: 1px solid var(--border); font-size: var(--fs-md);
  font-family: var(--font-mono); color: var(--text-muted);
}
.lightbox .bar .spacer { flex: 1 1 auto; }
.lightbox .body {
  overflow: auto; background: var(--c-surface); min-width: 200px; min-height: 120px;
  display: flex; align-items: center; justify-content: center;
}
.lightbox img { display: block; max-width: 90vw; max-height: 82vh; }
.lightbox iframe { display: block; width: 84vw; height: 82vh; border: 0; }

/* 칸 옆에 붙는 작은 체크 (첨부 떼기 따위) */
.inline-pick {
  display: inline-flex; align-items: center; gap: var(--sp-2); flex: 0 0 auto;
  width: auto; margin-left: var(--sp-3); font-size: var(--fs-md); color: var(--c-text-2); cursor: pointer;   /* 옛 var(--muted) 는 정의가 없어 글자색이 빠져 있었다 — 흐린 글자 토큰으로(2026-10-09, common.tests_tokens 가 잡음) */
}
.inline-pick input { margin: 0; }
.field-row input[type="file"] {
  flex: 1 1 auto; min-width: 0; height: var(--h-md); font-size: var(--fs-md);
  font-family: var(--font-mono); padding: 1px 0;
}
.kind-pick span {
  display: inline-block;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text-muted);
  padding: 0 9px;
  font-size: var(--fs-sm);
  font-weight: 500;
}

/* ---------------- 제목에 마우스를 올리면 뜨는 안내창 ----------------
   물음표는 이모지가 아니라 글자다(hr 화면 규칙). 누르지 않아도 올리면 뜬다. */
.field-row label.with-help { position: relative; overflow: visible; cursor: help; }
.help-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; margin-left: var(--sp-2); vertical-align: 1px;
  border: 1px solid var(--text-muted); border-radius: var(--r-round);
  font-size: var(--fs-xs); line-height: 1; color: var(--text-muted);
}
.field-row label.with-help:hover .help-mark { border-color: var(--primary); color: var(--primary); }
.tip {
  display: none; position: absolute; left: 100%; top: -8px; margin-left: var(--sp-6); z-index: 120;
  width: 300px; padding: var(--sp-5) var(--sp-6); text-align: left; white-space: normal;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--r-3);
  box-shadow: 0 6px 20px rgba(15,23,42,.18);
  font-size: var(--fs-md); line-height: 1.6; color: var(--text); font-weight: var(--fw-normal);
}
.field-row label.with-help:hover .tip,
.field-row label.with-help:focus-within .tip { display: block; }

/* 창은 모달보다 조금 넓다 — 거래처코드 줄에 구분 단추 + 코드 + 안내가 한 줄로 들어가야 한다 */

/* ---------------- [Fn] 메뉴 · 고정된 코드 ----------------
   등록한 뒤 거래처코드는 칸이 아니라 글자로 보이고, 바꾸는 길은 [Fn] 뿐이다. */
.code-fixed { font-size: var(--fs-xl); font-weight: var(--fw-semi); letter-spacing: .2px; }
/* 색으로 뜻을 나르지 않는다 — 고정폭 글꼴과 굵기로만 세운다(대표님 2026-09-26
   "글씨 왤케 알록달록하냐 CMD 스타일로 계속 가자"). 바뀐 적이 있다는 표시는
   목록의 `*` 와 [Fn] - [코드변경이력] 이 맡는다. */
.code-fixed.was { color: inherit; }
.fn-menu { position: relative; display: inline-block; }

.fn-list {
  display: none; position: absolute; left: 0; top: calc(100% + 4px); z-index: 130;
  min-width: 128px; padding: var(--sp-2) 0;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--r-3);
  box-shadow: 0 6px 20px rgba(15,23,42,.18);
}
.fn-menu.open .fn-list { display: block; }

.fn-list a:hover { background: var(--header-bg); }
/* 중복병합 창의 줄 — **줄 어디를 눌러도** 그 사람이 열린다 (목록과 같은 `data-href`) */
.dup-grid tr[data-href] { cursor: pointer; }
.dup-grid tr[data-href]:hover td { background: var(--header-bg); }

/* 이력 창은 표가 들어가니 넓게 */
.modal.window.wide { width: 860px; }
/* 대표님 2026-10-06 머리 글자 잘림 */
.modal.window.win-pend { width: min(96vw, 980px); }
.modal.window.wide .modal-body { padding-top: var(--sp-6); }

/* ---------------- 코드 칸 — 바뀐 적이 있으면 마우스를 올려 내력을 본다 ----------------
   전표 화면이 생겨도 같은 조각(_code_cell.html)을 쓴다. */
.code-hist { position: relative; cursor: help; }
.hist-mark { color: var(--primary); font-weight: var(--fw-bold); margin-left: var(--sp-1); }
.code-hist .tip { left: 0; top: 1.6em; margin-left: 0; width: 320px; }
/* 표 칸은 넘치는 것을 잘라내므로(말줄임), 안내창이 뜨는 코드 열만 풀어 준다 */
/* 코드 칸은 **내력 안내창이 있는 줄에서만** 넘치게 둔다. 전부 열어 두면 열을 좁혔을 때
   코드가 옆 열(상호) 위로 올라탄다 (2026-09-27). */
.grid td.col-code:has(.code-hist) { overflow: visible; }
.code-hist:hover .tip { display: block; }

/* ================================================================
   창 결 — CMD 식으로 (대표님 2026-09-25 "파란 컨테이너 너무 크다,
   기계적이고 군더더기 없는 거", 부품모듈 규격 차용)

   부품모듈에서 가져온 것: 한 판 22px · 좌우 여백 4px · 각진 모서리(radius 0) ·
   번지지 않는 그림자(2px 2px 0) · 숫자는 Consolas · 짧고 각진 전환(.12s linear).
   "작게, 컨테이너 키우지 마" (부품-#339)
   ================================================================ */

.modal.window .modal-header,
.veh-openwin > .modal-header,
.vw-float > .modal-header {
  cursor: move;
  user-select: none;
  touch-action: none;
  background: var(--c-dark);
  border-bottom: 1px solid var(--c-line-strong);
  border-radius: 0;
  height: 24px;
  padding: 0 var(--sp-2) 0 var(--sp-4);
}
.veh-openwin > .modal-header { cursor: default; }
.modal.window .modal-header h2,
.veh-openwin > .modal-header h2,
.vw-float > .modal-header h2 {
  font-size: var(--fs-md);
  font-weight: var(--fw-semi);
  letter-spacing: .2px;
  color: #e6e9ee;
}
.modal.window .modal-header .seq-info {
  font-size: var(--fs-sm);
  color: var(--c-text-3);
}
.modal.window .titlebar-close,
.veh-openwin .titlebar-close,
.vw-float .titlebar-close {
  height: 18px; min-width: 18px; padding: 0 var(--sp-2); border-radius: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-md); line-height: 1;
}
.modal.window .titlebar-close:hover,
.veh-openwin .titlebar-close:hover,
.vw-float .titlebar-close:hover { background: #3a4250; }
/* 새로고침도 닫기와 같은 크기·결로 (2026-09-29) */
.modal.window .titlebar-refresh {
  height: 18px; min-width: 18px; padding: 0 var(--sp-2);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-lg); line-height: 1;
}
.modal.window .titlebar-refresh:hover { background: #3a4250; }

.modal.window .modal-body { padding: var(--sp-5) var(--sp-6); }
.modal.window .modal-footer { padding: var(--sp-3) var(--sp-4); gap: var(--sp-2); }

/* 칸 — 한 판 22px */
.modal.window .field-row { gap: var(--sp-3); margin-bottom: var(--sp-2); }
.modal.window .dropzone { height: 22px; }
.modal.window .field-row label {
  width: 92px;
  font-size: var(--fs-md);
}
.modal.window .field-row input,
.modal.window .kind-pick span,
.modal.window .btn {
  box-sizing: border-box; height: var(--h-md); min-height: var(--h-md); padding: 0 var(--sp-3);
  font-size: var(--fs-md); line-height: 20px; border-radius: var(--r-1);
}

.modal.window .btn-small { height: var(--h-sm); min-height: var(--h-sm); font-size: var(--fs-sm); }
.modal.window .hint, .modal.window .stamp, .modal.window .account-info { font-size: var(--fs-sm); }

/* 코드·번호는 고정폭 글꼴 — 자릿수가 눈으로 세어진다 */
.code-fixed, .code-hist, .grid td.col-code, .clash td {
  font-family: var(--font-mono);
}
.modal.window .code-fixed { font-size: var(--fs-lg); font-weight: var(--fw-semi); letter-spacing: .3px; }
.modal.window .field-row input { font-family: inherit; }
.modal.window #id_cust_code, .modal.window #id_new_cust_code {
  font-family: var(--font-mono); letter-spacing: .3px;
}

/* 확인 상자·안내창도 각지게 */
.modal.window .confirm-box { border-radius: var(--r-1); padding: var(--sp-4) var(--sp-5); margin-bottom: var(--sp-4); }
.modal.window .confirm-text { font-size: var(--fs-md); }
.tip, .fn-list { border-radius: var(--r-1); box-shadow: 2px 2px 0 rgba(15, 23, 42, .12); }
.fn-list a {
  display: block;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  padding: var(--sp-2) var(--sp-5);
  font-size: var(--fs-md);
}
.fn-btn {
  font-style: italic;
  min-width: 34px;
  height: var(--h-sm);
  min-height: var(--h-sm);
  padding: 0 var(--sp-3);
  font-size: var(--fs-sm);
  border-radius: var(--r-1);
}

/* ---------------- 목록·탭·도구줄도 같은 결 (대표님 2026-09-25) ---------------- */
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-size: var(--fs-lg);
}

/* 탭 — 모듈은 테두리 없는 칸, 고른 것만 남색 채움(C안, 대표님 2026-10-08) */
.top-level-tabs {
  display: flex;
  background: var(--header-bg);
  border-bottom: 1px solid var(--border);
  padding: 0 var(--sp-4);
  gap: 0;
  align-items: stretch;
}
.top-level-tab {
  border: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  font-family: inherit;
  border-radius: var(--r-2);
  margin: var(--sp-1) 0;
  padding: 0 14px;
  height: 22px;
  font-size: var(--fs-md);
  font-weight: 500;
}
.top-level-tab:hover { background: var(--card-bg); color: var(--text); }
.top-level-tab.active, .top-level-tab.active:hover {
  background: #1e3a8a;
  color: var(--c-on-dark);
  font-weight: var(--fw-semi);
}
.top-level-tabs-right {
  display: flex;
  align-items: center;
  margin-left: auto;
  padding-bottom: var(--sp-4);
  padding: 0;
  gap: var(--sp-3);
}
.account-info {
  color: var(--text-muted);
  white-space: nowrap;
  font-size: var(--fs-sm);
}
/* [테스트서버] — 작업방 서버 표시 (adr/0013). 라이브와 헷갈리지 않게 빨간 글자 */
.test-server-badge { color: var(--c-danger); font-weight: var(--fw-bold); font-size: var(--fs-md); white-space: nowrap; }

/* ── 회사관련서류 (company) — 모양은 옛 hr 8880 "정보관리" 서류 트리(view_company.css company-d*) 값을 그대로 ── */
.cdoc-top { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-3); }
.cdoc-top h2.cdoc-title { margin: 0; font-size: var(--fs-2xl); }
.cdoc-count, .cdoc-picked { color: var(--text-muted); font-size: var(--fs-md); }
.cdoc-hint { margin: 0 0 var(--sp-3); font-size: var(--fs-md); }
.cdoc-tbtn { border: none; background: none; cursor: pointer; padding: 0 var(--sp-2); color: var(--text-muted); font: inherit; font-size: var(--fs-lg); text-decoration: none; flex: none; }
.cdoc-tbtn:hover { color: var(--c-link); }
.cdoc-tbtn-up { color: var(--c-link); }
.cdoc-row { display: flex; align-items: center; gap: var(--sp-3); padding: 5px var(--sp-2) 5px 22px; border-radius: var(--r-2); min-width: 0; position: relative; }
/* ✎ 줄 자리 고치기(erp2 수정 표준 — 고칠 칸이 하나뿐인 줄은 `???_modify` 창 대신 줄이 입력 칸이 된다, 대표님 2026-10-05).
   줄 위에 겹쳐 띄워 틀이 안 움직이고, 투명 막(.cdoc-edit-shield)이 다른 곳 누르기를 막는다. */
.cdoc-edit-shield { position: fixed; inset: 0; z-index: 900; background: transparent; }
.cdoc-row.is-editing { z-index: 901; }
.cdoc-edit { position: absolute; left: 18px; right: 0; top: 50%; transform: translateY(-50%); z-index: 902; display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-1) var(--sp-2); background: var(--card-bg, var(--c-surface)); border: 1px solid var(--c-link); border-radius: 3px; box-shadow: 0 1px 4px rgba(0,0,0,.18); }
.cdoc-edit-id { flex: none; font: 10px var(--font-mono); color: var(--text-muted); }
.cdoc-edit-in { flex: 1 1 auto; min-width: 0; height: 20px; padding: 0 var(--sp-2); font: inherit; font-size: var(--fs-md); border: 1px solid var(--border); border-radius: var(--r-1); }
.cdoc-edit-ext { flex: none; font-size: var(--fs-md); color: var(--text-muted); }
.cdoc-edit .btn-small { flex: none; height: var(--h-sm); min-height: var(--h-sm); padding: 0 var(--sp-3); }
.cdoc-edit-err { position: absolute; left: 4px; top: 100%; margin-top: var(--sp-1); font-size: var(--fs-sm); color: var(--c-danger); background: var(--card-bg, var(--c-surface)); white-space: nowrap; }
.cdoc-edit-err:empty { display: none; }
.cdoc-edit.nudge { animation: cdoc-nudge .35s; }
@keyframes cdoc-nudge { 0%, 100% { box-shadow: 0 1px 4px rgba(0,0,0,.18); } 50% { box-shadow: 0 0 0 3px rgba(26,95,180,.45); } }
.cdoc-row:hover { background: var(--header-bg); }
.cdoc-row.llm-failed { background: var(--c-danger-bg); color: var(--c-danger); }
.cdoc-row.llm-failed .cdoc-name, .cdoc-row.llm-failed .cdoc-ext, .cdoc-row.llm-failed .cdoc-why, .cdoc-row.llm-failed .cdoc-state { color: var(--c-danger); }
.cdoc-row.is-expired .cdoc-name { color: var(--text-muted); text-decoration: line-through; }
.cdoc-row.is-expired .cdoc-date { opacity: .6; }
.cdoc-pick, .cdoc-pickall { margin: 0; flex: none; }
.cdoc-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--c-link); text-decoration: none; }
.cdoc-name:hover { text-decoration: underline; }
.cdoc-ext { color: var(--text-muted); font-size: var(--fs-md); }
.cdoc-date { color: var(--text-muted); font-size: var(--fs-md); white-space: nowrap; flex: none; }
.cdoc-row .cdoc-flag { width: 40px; margin: 0; flex: none; cursor: pointer; }
.cdoc-retry { border: 0; background: none; color: var(--c-danger); cursor: pointer; font-size: var(--fs-xl); padding: 0 var(--sp-1); flex: none; }
.cdoc-empty { color: var(--text-muted); font-size: var(--fs-md); padding: var(--sp-1) var(--sp-2) var(--sp-1) 22px; }
.cdoc-movepick { display: block; padding: 3px 0; font-size: var(--fs-lg); }
.cdoc-rule { flex: 1; font-size: var(--fs-md); }
.btn-del-off { background: var(--c-line); color: var(--c-text-3); border: 1px solid var(--c-line); cursor: not-allowed; }
.cdoc-dropwrap { display: flex; flex-direction: column; align-items: flex-end; gap: var(--sp-1); }
.cdoc-drop { display: flex; align-items: center; gap: var(--sp-4); border: 1.5px dashed var(--c-text-3); border-radius: var(--r-3); padding: var(--sp-3) var(--sp-5); background: var(--c-sunken); }
.cdoc-drop.drop-on { border-color: var(--c-link); background: var(--c-selected); }
.cdoc-drop.busy { opacity: .6; }
.cdoc-drop-pick { font-size: var(--fs-md); color: #475569; cursor: pointer; }
.cdoc-jobs { font-size: var(--fs-sm); color: var(--text-muted); }
.cdoc-jobs.has { color: var(--c-danger); font-weight: var(--fw-bold); }
.cdoc-tabs { display: flex; gap: var(--sp-1); padding: 0 var(--sp-7); border-bottom: 1px solid var(--border); }
.cdoc-why { font-size: var(--fs-sm); color: #9a3412; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40%; }
.cdoc-jobmove { font-size: var(--fs-sm); height: 20px; }
/* 회사관련서류 — 가운데 칸(.cdoc-left)이 예전 왼쪽 판(올리기 칸 + 폴더 묶음) 그대로, 그 왼쪽에 고르기 전용 트리(공용 .ex3-* 아래 "erp2 세 칸 틀" 블록). 9f */
.cdoc-left { overflow-y: auto; overflow-x: hidden; min-width: 0; padding-right: var(--sp-2); }
.cdoc-path { font: 11px var(--font-mono); color: var(--text-muted); margin: -2px 0 6px; word-break: break-all; }
.cdoc-pickbar { display: flex; align-items: center; gap: var(--sp-3); height: 20px; font-size: var(--fs-md); color: var(--text-muted); margin-bottom: var(--sp-3); }
.cdoc-left .cdoc-drop { margin-top: var(--sp-4); justify-content: center; padding: var(--sp-5); }
.cdoc-left .cdoc-jobs { display: block; text-align: right; margin-top: var(--sp-1); }
.cdoc-row.on { background: var(--c-selected); }
.cdoc-vbar { display: flex; align-items: center; gap: var(--sp-3); padding: 5px var(--sp-4); border-bottom: 1px solid var(--border); }
.cdoc-vname { font-size: var(--fs-md); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cdoc-vbody { flex: 1; min-height: 0; background: var(--c-head); overflow: auto; }
.cdoc-vtools { display: inline-flex; align-items: center; gap: var(--sp-2); }
.cdoc-vtools[hidden] { display: none; }
.cdoc-vpage, .cdoc-vzoom { font-size: var(--fs-md); color: var(--text-muted); min-width: 42px; text-align: center; }
.cdoc-vpages { display: flex; flex-direction: column; align-items: center; gap: var(--sp-5); padding: var(--sp-5); }
.cdoc-vpageframe { background: var(--c-surface); box-shadow: 0 1px 4px rgba(0,0,0,.18); line-height: 0; }
.cdoc-vnone { margin: 40px auto; text-align: center; color: var(--text-muted); font-size: var(--fs-lg); }

/* 도구줄 */
.view-body {
  padding: var(--sp-5) var(--sp-6) 40px;
}
.toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.search-input {
  max-width: 46vw;
  border: 1px solid var(--border);
  height: var(--h-md);
  padding: 0 var(--sp-3);
  font-size: var(--fs-md);
  border-radius: var(--r-1);
  width: 280px;
  font-family: var(--font-mono);
}
.btn {
  border: none;
  cursor: pointer;
  font-family: inherit;
  box-sizing: border-box;
  height: var(--h-md);
  min-height: var(--h-md);
  padding: 0 var(--sp-5);
  font-size: var(--fs-md);
  font-weight: 500;
  border-radius: var(--r-1);
  line-height: 20px;
}
.btn-small {
  height: var(--h-sm);
  min-height: var(--h-sm);
  padding: 0 var(--sp-3);
  font-size: var(--fs-sm);
}
/* 글자 대신 기호 하나만 앉는 단추 — 좌우를 좁혀 네모에 가깝게 둔다. */
.btn-sym { padding: 0 7px; font-size: var(--fs-lg); line-height: 1; }

/* 표 — 줄 간격을 좁히고 각지게 */
.grid {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 0;
}
.grid th, .grid td {
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 3px var(--sp-4);
  font-size: var(--fs-md);
  line-height: var(--lh-row);
}
.grid th {
  background: var(--header-bg);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  letter-spacing: .2px;
}
.grid tbody tr:hover {
  background: var(--c-head);
}
/* **여는 칸이 있는 줄은 그 칸만 눌린다** (대표님 2026-10-03) — 손가락 모양과 밑줄은 그 칸에만.
   나머지 칸은 글자 고르기 커서 — 긁어 복사하는 자리다. */
.list-grid tbody tr:has(.open-cell) { cursor: auto; }
/* **파란 글씨 = 여기를 누르면 열린다** (대표님 2026-10-03 "파란색 글씨로 만들어서 '여기
   눌러야된다' 는 강조효과 주자"). 흐린 줄(사용중지 · 사라짐)도 파랑은 남긴다 — 열 곳이다. */
/* 색은 대표님 샘플(이카운트 판매조회의 일자 칸) 톤 — 쨍한 단추 파랑이 아니라 차분한 남색
   (2026-10-03 "파란색 색상 너무 구려 / 샘플 … 이런 느낌으로"). 굵게 하지 않는다. */
.list-grid td.open-cell { cursor: pointer; color: #3b5c9e; }
.grid tr.row-off td.open-cell { color: #3b5c9e; opacity: .65; }
.list-grid td.open-cell:hover { text-decoration: underline; }
.empty {
  color: var(--text-muted);
  font-size: var(--fs-md);
  padding: var(--sp-5) var(--sp-1);
}

/* 알림 줄 */
.notice li {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-muted);
  margin-bottom: var(--sp-3);
  border-radius: 0;
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-md);
}

/* 로그인 창도 같은 결 */
.login-box {
  background: var(--card-bg);
  border: 1px solid #17497a;
  max-width: 92vw;
  overflow: hidden;
  border-radius: 0;
  box-shadow: 3px 3px 0 rgba(15,23,42,.18);
  width: 320px;
  border-color: var(--c-line-strong);
}
.login-titlebar {
  background: var(--c-dark);
  border-bottom: 1px solid var(--c-line-strong);
  padding: 0 var(--sp-4);
  height: 24px;
  display: flex;
  align-items: center;
}
.login-title {
  color: var(--c-on-dark);
  letter-spacing: .3px;
  text-shadow: 0 1px 1px rgba(0,0,0,.25);
  font-size: var(--fs-md);
  font-weight: var(--fw-semi);
}
.login-subtitle {
  color: rgba(255,255,255,.75);
  margin-left: var(--sp-4);
  font-size: var(--fs-sm);
}
.login-body {
  padding: 14px var(--sp-7) var(--sp-7);
}
.login-field-row {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
}
.login-field-row label {
  flex-shrink: 0;
  text-align: right;
  color: var(--text-muted);
  width: 62px;
  font-size: var(--fs-md);
}
.login-field-row input {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--border);
  font-family: inherit;
  height: var(--h-md);
  padding: 0 var(--sp-3);
  font-size: var(--fs-md);
  border-radius: var(--r-1);
}
.login-submit-btn { height: var(--h-lg); border-radius: var(--r-1); background: var(--c-dark); font-size: var(--fs-md); }
.login-submit-btn:hover { background: #3a4250; }
/* 폰 — 로그인 창을 위에 붙이고 칸 · 단추를 손가락 크기로(대표님 2026-10-10 "입력칸이 키보드랑 간섭").
   가운데 정렬(fixed + center)이면 키보드가 올라올 때 창이 화면 아래쪽에 남아 비밀번호 칸이 가려졌다.
   글자 16px — 아이폰은 16px 보다 작은 칸에 커서가 가면 화면을 확대한다. */
@media (max-width: 700px) {
  .login-screen { position: static; min-height: 100dvh; align-items: flex-start; padding: var(--sp-9) var(--sp-5) var(--sp-9); box-sizing: border-box; }
  .login-box { width: 100%; max-width: none; }
  .login-titlebar { height: var(--h-touch); }
  .login-title { font-size: var(--fs-2xl); }
  .login-subtitle { font-size: var(--fs-lg); }
  .login-body { padding: var(--sp-7); }
  .login-field-row { flex-direction: column; align-items: stretch; gap: var(--sp-2); margin-bottom: var(--sp-6); }
  .login-field-row label { width: auto; text-align: left; font-size: var(--fs-xl); }
  .login-field-row input { flex: none; height: var(--h-touch); font-size: var(--fs-2xl); }   /* 세로 줄에선 flex:1 이 높이를 0 에서 키워 칸이 납작해진다 */
  .login-submit-btn { height: var(--h-touch); font-size: var(--fs-2xl); margin-top: var(--sp-7); }
}

/* 구획 제목 — 기본정보 / 부가정보 */
.sect {
  margin: var(--sp-5) 0 5px; padding: var(--sp-1) 0 var(--sp-1) var(--sp-1);
  border-top: 1px solid var(--border); font-size: var(--fs-sm); font-weight: var(--fw-semi);
  color: var(--text-muted); letter-spacing: .3px;
}

/* 양식수정 — 줄을 잡아 옮긴다 */
#specGrid tbody tr { cursor: default; }
#specGrid .grip { cursor: grab; color: var(--text-muted); user-select: none; text-align: center; }
#specGrid tr.dragging { opacity: .45; }
#specGrid tr.is-hidden td { color: var(--c-text-3); }
.modal.window select, .modal.window textarea {
  border: 1px solid var(--border); border-radius: var(--r-1); font: inherit; font-size: var(--fs-md);
  padding: 0 var(--sp-2); height: var(--h-md);
}
.modal.window textarea { height: auto; padding: var(--sp-2) var(--sp-3); font-family: inherit; }
.modal.window input[type=checkbox] { width: 13px; height: 13px; margin: 0; }

/* ---------------- 확장패널 ----------------
   [양식수정] 은 새 창이 아니라 이 창이 오른쪽으로 넓어지면서 붙는 판이다
   (대표님 2026-09-25 "창 하나에서 확장패널 방식으로"). */

/* 체크칸은 늘어나지 않는다 (field-row input 의 flex:1 을 끈다) */

/* ---------------- 확장패널 ----------------
   [양식수정] 은 새 창이 아니라 이 창이 오른쪽으로 넓어지면서 붙는 판이다
   (대표님 2026-09-25 "창 하나에서 확장패널 방식으로"). */
.win-split {
  display: flex;
  align-items: stretch;
  min-height: 0;
}
.win-main {
  flex: 0 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.win-panel {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--c-sunken);
}
.panel-head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 5px var(--sp-4);
  border-bottom: 1px solid var(--border);
  background: var(--header-bg);
}
.panel-title {
  font-size: var(--fs-md);
  font-weight: var(--fw-semi);
}
/* **오른쪽 판 머리줄은 한 꼴** (대표님 2026-10-04 "폰트랑 스타일 통일좀 · 링크매치 / 명함") — 높이 · 여백 · 제목 · ✕ 를
   같게. 첨부 판(`cust_cert_view` · `cont_card_view`) · 고르는 판(`link_pick_*`) · 판독 원본(`*_ocr_shot`)이 다 이 줄을 쓴다.
   잰 것: 첨부 판 43px · 제목 12px 굵게 · ✕ 14px Arial / 링크매치 31px · 제목 13px 보통 · ✕ 12px — 둘 다 아래로 맞춘다. */
.win-panel > .panel-head, .win-side > .panel-head { height: 31px; padding: 0 var(--sp-4); box-sizing: border-box; flex: 0 0 auto; }
.win-panel > .panel-head .panel-title, .win-side > .panel-head .panel-title,
.win-side > .panel-head .panel-label { font-size: var(--fs-md); font-weight: var(--fw-semi); line-height: 1; }

.panel-body {
  padding: var(--sp-4) var(--sp-5);
  overflow-y: auto;
  flex: 1 1 auto;
}
.panel-foot {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
}
.win-panel .grid th, .win-panel .grid td {
  padding: var(--sp-1) var(--sp-3);
  font-size: 11.5px;
}
.win-panel .field-row label {
  width: 74px;
}

/* 체크칸은 늘어나지 않는다 (field-row input 의 flex:1 을 끈다) */
.field-row input[type=checkbox] {
  flex: 0 0 auto;
  margin: 0;
}

/* 새 창은 있던 창을 밀지 않는다 — 제자리에 두고 오른쪽 위에 겹쳐 뜬다.
   (2026-09-25 "위치가 막 이동되면서 나란히 뜬다") */
.modal.window.pair-right {
  left: auto; right: 16px; top: 14px; transform: none;
  width: min(62vw, 840px); max-height: calc(100vh - 28px);
}
@media (max-width: 1000px) {
  .modal.window.pair-right { left: 12px; right: 12px; width: auto; }
}

/* [설정] 은 그 줄 바로 아래로 펼쳐진다. 한 번에 하나만 */
#specGrid tr.is-open > td { background: var(--header-bg); font-weight: var(--fw-semi); }

#specGrid tr.row-open .field-row { margin-bottom: 5px; }
#specGrid tr.row-open .panel-foot { margin-top: var(--sp-4); padding-top: var(--sp-3); }
#specGrid tr.row-open .hint { white-space: normal; }

/* 아직 저장 안 된 초안 표시 */
.draft-mark { font-size: var(--fs-sm); font-weight: var(--fw-semi); color: #b23; letter-spacing: .2px; }
.modal.window.has-panel .win-main.previewing { outline: 2px dashed #e0b4b4; outline-offset: -2px; }

/* ---------------- 창 크기를 고정한다 ----------------
   [설정] 을 눌러도 창이 커지지 않게. 창이 커지면 보고 있던 줄이 위아래로 밀려
   눈이 피로해진다(대표님 2026-09-25). 펼침은 패널 안에서만 일어나고,
   넘치면 패널이 스스로 스크롤한다. 창은 가운데가 아니라 **위에 고정**이다. */
.modal.window.has-panel {
  width: min(96vw, 1180px);
  top: 20px;
  transform: translateX(-50%);
  height: min(86vh, 720px);
}
.modal.window.has-panel .win-split { flex: 1 1 auto; min-height: 0; }
.modal.window.has-panel .win-main {
  width: 46%;
  border-right: 1px solid var(--border);
  min-height: 0;
}
.modal.window.has-panel .win-main .modal-body { flex: 1 1 auto; overflow-y: auto; }
.modal.window.has-panel .panel-body { flex: 1 1 auto; overflow-y: auto; min-height: 0; }



/* **판 전체를 표가 꽉 채운다** — 안쪽 여백 · 테두리를 걷었다 (대표님 2026-10-04 "link_pick_cust 자체가
   별도의 표처럼 되어서 불필요한 공간낭비 … 오른족 익스텐션패널 전체 스페이스를 다 활용하도록") */
.link-pick-side { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
                  padding: 0; min-height: 0; }
.link-pick-side > .panel-head { margin: 0; }
.link-pick-side .link-pick .pick-grid { border: 0; border-radius: 0; margin: 0; }
.link-pick-side .link-bar { display: flex; gap: var(--sp-3); align-items: center; margin-bottom: var(--sp-4); }
.link-pick-side .link-bar input[type="search"] { flex: 1 1 auto; min-width: 0; }
/* 목록은 **판 안에서만** 흐른다 — 창이 가로로 늘어나지 않게(`스크롤바 최소화`). */
.link-pick-side .link-pick { flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; min-height: 0; }
.link-pick-side .link-pick table { font-size: var(--fs-md); }
.link-pick-side .link-pick td, .link-pick-side .link-pick th { padding: 3px var(--sp-3); }
/* ---------------- 수정 창은 창 높이 안에 갇힌다 ----------------
   대표님 2026-10-03 "cust_modify 창 수정좀 해야되겠다 / 이거 범위가 엄청 가변적일수도
   있으니까 세팅좀 적절하게". AJ네트웍스(이어진 사람 29명)를 열면 폼이 1,373px 로 늘어나
   880px 창 밖으로 흘렀고, 맨 아래 [저장] 줄까지 화면 밖으로 밀려 나갔다. 사진 칸이 있는
   창(`.has-panel`)에만 "안에서 흐른다" 가 걸려 있었고 없는 창에는 안 걸려 있었다.

   이제 **모든 수정 창**이 같다 — 폼 · 좌우 칸이 창 높이에 갇히고, 왼쪽 칸 몸통이 제
   안에서 스크롤하며, [저장] 줄은 늘 맨 아래 보인다. 오른쪽 [연락처 조회] 판도 창 안에서
   흐르고 [취소]·[연결] 이 아래 남는다. 관계 칸은 자기 높이에 상한을 둔다(`_script.html`). */
.modal.window > form:has(> .win-split) { flex: 1 1 auto; min-height: 0;
                                         display: flex; flex-direction: column; }
.modal.window > form > .win-split { flex: 1 1 auto; min-height: 0; }
.modal.window .win-split > .win-main { min-height: 0; }
.modal.window .win-split > .win-main > .modal-body { flex: 1 1 auto; min-height: 0;
                                                     overflow-y: auto; }
.modal.window .win-split > .win-main > .modal-footer { flex: 0 0 auto; }
.modal.window .win-split > .win-side { display: flex; flex-direction: column; min-height: 0; }
.modal.window .win-split > .win-side[hidden], .modal.window .win-split > .win-panel[hidden] { display: none; }   /* hidden 이 display:flex 에 덮이던 함정 셋을 한 줄로 (2026-10-07 코드리뷰 A-6) */
/* **판을 열든 닫든 같은 높이** — [연락처 조회] 를 열면 `has-panel` 의 720px 가 끼어들어
   창이 880 -> 720 으로 줄었다. 창이 들썩이면 보던 줄을 놓친다(2026-09-25 "창 크기를
   고정한다" 와 같은 결). 명함 사진 창(`:has(.cert-shot)`)은 제 높이 규칙이 따로 이긴다. */
.modal.window:has(> form > .win-split) { height: min(88vh, 900px); }

.link-pick-foot { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-3) var(--sp-5);
                  border-top: 1px solid var(--border); margin-top: 0; }

/* **같은 값인 칸은 초록 굵은 글씨** (대표님 2026-10-01 "서로 일치하는 항목 … 은
   초록색으로 강조 표시해줘"). 주로 주소와 전화가 걸린다. 잣대는 추천 점수와 같은
   것이라, 추천이 "주소 일치" 라 적어 둔 줄은 주소가 반드시 빛난다. */
/* (2026-10-04) 글씨색 · 굵게는 걷고 **칸 배경**으로 바꿨다 — 같음 연한 초록 · 다름 연한 빨강(`links/_script.html`) */
/* 걸린 까닭은 **이름 밑 작은 글씨**다 — 열로 세우면 그 아래가 통째로 밀려 UI 가 뛴다 */
.pick-grid .pick-why { display: block; color: var(--text-muted); font-size: var(--fs-sm);
                       font-weight: var(--fw-normal); overflow: hidden; text-overflow: ellipsis; }
.pick-grid .pick-code { font-family: var(--font-mono); }
.pick-grid tbody tr { cursor: default; }

/* 마우스를 올려 뜨던 명함·등록증(`.pick-shot`)은 2026-10-04 걷었다 — 누르면 크게 뜬다 */

/* 창은 언제나 위에 고정 — 내용이 늘어도 아래로만 자란다. 가운데 정렬이면 위아래로 벌어져 튄다 */
.modal.window {
  width: calc(var(--win-main) + 2px);
  border-radius: 0;
  border: 1px solid var(--c-line-strong);
  box-shadow: 3px 3px 0 rgba(15, 23, 42, .18);
  top: 20px;
  transform: translateX(-50%);
}

/* 넓어지는 것이 눈에 보이게 짧게 — 부품모듈 결대로 .15s (대표님 2026-09-25) */
@keyframes win-widen {
  from { width: calc(var(--win-main) + 2px); }
  to   { width: min(96vw, 1180px); }
}
@keyframes panel-slide {
  from { opacity: 0; transform: translateX(-10px); }
  to   { opacity: 1; transform: none; }
}
.modal.window.has-panel.opening { animation: win-widen .15s ease-out; }
.modal.window.has-panel.opening .win-panel { animation: panel-slide .15s ease-out .03s both; }

/* 움직임을 싫어하는 설정이면 끈다 */
@media (prefers-reduced-motion: reduce) {
  .modal.window.has-panel.opening, .modal.window.has-panel.opening .win-panel { animation: none; }
}



/* [설정] 이 줄 아래로 펼쳐지는 것도 짧게 보여 준다.
   높이·폭을 건드리는 애니메이션은 매 장면마다 화면 계산을 다시 하게 만든다 —
   그래서 한 줄에만, 0.15초만 쓴다. */
@keyframes row-open {
  from { max-height: 0; opacity: 0; }
  to   { max-height: 340px; opacity: 1; }
}
#specGrid tr.row-open > td {
  background: var(--c-sunken);
  border-top: 0;
  padding: var(--sp-4) var(--sp-5) var(--sp-5) 26px;
  overflow: hidden;
  animation: row-open .15s ease-out;
}
@media (prefers-reduced-motion: reduce) {
  #specGrid tr.row-open > td { animation: none; }
}

/* ---------------- 양식설정 미리보기 표 ----------------
   세로 목록이 아니라 실제 목록 모양 그대로. 머리를 좌우로 끌어 열 차례를 바꾼다. */
.grid.preview { table-layout: fixed; }
.grid.preview th {
  vertical-align: top; padding: var(--sp-2) var(--sp-3); white-space: normal; position: relative;
  background: var(--header-bg); border-right: 1px solid var(--border);
}
.grid.preview td { border-right: 1px solid var(--border); }
.grid.preview th:last-child, .grid.preview td:last-child { border-right: 0; }
.col-grip { display: block; color: var(--text-muted); cursor: grab; user-select: none;
            font-size: var(--fs-sm); line-height: 1; margin-bottom: var(--sp-1); }
.col-pick { display: flex; align-items: flex-start; gap: var(--sp-2); cursor: pointer;
            font-size: var(--fs-sm); font-weight: var(--fw-semi); color: var(--text); }
.col-pick input { flex: 0 0 auto; margin: 1px 0 0; }
/* 열을 좁혀도 **이름이 잘리지 않는다** — 줄이 넘어가고 글씨가 작아질 뿐이다
   (대표님 2026-09-27 "거...  대표자...  이런식으로 다 가려져버리는데"). */
.col-pick span { white-space: normal; word-break: break-all; line-height: 1.25; }
/* 사람 이름표 밑에 **표의 인자 이름**을 같이 보인다 — 무엇을 고치는지 이 이름으로 말한다 */
.col-name { display: block; margin-top: var(--sp-1); font-size: 9.5px; line-height: 1.2;
            color: var(--text-muted); opacity: .75; font-family: var(--font-mono);
            white-space: normal; word-break: break-all; }
.grid.preview th.off, .grid.preview td.off { background: var(--c-page); color: #aeb4bd; }
/* 뺀 열은 좁은 띠로만 남는다. 글자를 접으면 한 글자씩 세로로 늘어져 머리가 치솟는다 —
   가로로 자른다. 무슨 열인지는 체크상자를 켜면 바로 넓어져 보인다 (2026-09-27). */
/* 뺀 열은 좁은 띠로만 남지만 **무슨 열인지는 보여야 한다** (대표님 2026-09-27).
   가로로는 두 글자도 못 들어가니 세로로 적는다. 인자 이름은 너무 길어 접는다 —
   체크를 켜면 바로 넓어지면서 가로로 돌아온다. */
/* 한글 이름과 인자 이름을 **나란히** 세운다. 뺀 열은 차례를 바꿀 일이 없으니 `::` 는 감춘다.

   **`th` 에 `display: flex` 를 주지 마라.** 그러면 그 칸이 테이블 칸 노릇을 못 하고
   뺀 열끼리 한 칸으로 뭉친다 (2026-09-27 실제로 그렇게 됐다). 칸은 `table-cell` 로
   두고 **안쪽 둘만** `inline-*` 으로 나란히 세운다. */
.grid.preview th.off { text-align: center; vertical-align: top; }
.grid.preview th.off .col-grip { display: none; }
.grid.preview th.off .col-pick {
  display: inline-flex; flex-direction: column; align-items: center; gap: var(--sp-1);
  vertical-align: top;
}

/* **뺀 열에서는 인자 이름을 감춘다** (대표님 2026-10-02 "이거 표기방법이 왜
   제각각이지?"). 가는 띠에 세로 글자를 둘이나 세우면 한글과 영문이 뒤엉켜 무슨
   열인지 더 모르게 된다. 무엇을 고치는지는 체크를 켜면 가로로 돌아와 보인다. */
.grid.preview th.off .col-name { display: none; }
.grid.preview th.off .col-pick span, .grid.preview th.off .col-name {
  writing-mode: vertical-rl;
  white-space: nowrap;
  letter-spacing: .5px;
  word-break: normal;
  overflow: visible;
  text-decoration: line-through;
}
.grid.preview th.dragging { opacity: .45; }

/* 미리보기 표가 들어가는 창은 목록만큼 넓게 */
.modal.window.widest { width: min(96vw, 1180px); }

/* 열 경계 — 잡고 끌면 너비가 바뀐다 */
.col-sizer {
  position: absolute; top: 0; right: -3px; width: 7px; height: 100%;
  cursor: col-resize; z-index: 2;
}
.col-sizer:hover { background: rgba(37, 99, 235, .25); }
.grid.preview th:last-child .col-sizer { display: none; }

/* 화면 이름표 — 이 화면·창의 id. 작고 옅게, 제목 바로 옆 (부품모듈 이름표 규약) */
.win-id {
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .2px;
  color: rgba(255, 255, 255, .45); margin-left: var(--sp-3); user-select: all;
}
.top-level-tabs .win-id, .toolbar .win-id, .panel-head .win-id { color: #aeb4bd; }

/* 미리보기 쪽은 손 못 대는 화면 — 옅게, 글자도 못 넣는다 */
.win-main.preview-only { background: var(--c-sunken); }
.win-main.preview-only input:disabled { background: var(--c-surface); color: var(--c-text-3); }
.win-main.preview-only .kind-pick input:checked + span { background: #9aa4b2; border-color: var(--c-text-3); }

/* 내부 키 — 참조용으로만 보인다. 사람이 쓰는 값이 아니다 */
.inner-key {
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text-muted);
  cursor: help; user-select: all; white-space: nowrap;
}

/* 구분 단추가 벌어지던 것 — `.field-row label` 의 92px 고정폭이 여기까지 먹고 있었다.
   안쪽 글자는 58px 인데 칸이 92px 이라 한 쪽에 34px 씩 빈 자리가 생겼다. */
.modal.window .kind-pick label,
.win-panel .kind-pick label { width: auto; text-align: center; }
.modal.window .kind-pick span {
  display: inline-flex;
  align-items: center;
  padding: 0 var(--sp-5);
  font-size: var(--fs-sm);
  font-weight: 500;
}

/* 이메일 도메인 자동완성 — 칸 아래로 떨어지는 목록 */
.suggest-list {
  display: none; position: fixed; z-index: 150;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--r-1);
  box-shadow: 2px 2px 0 rgba(15, 23, 42, .12); padding: var(--sp-1) 0; max-height: 200px;
  overflow-y: auto;
}
.suggest-list.open { display: block; }
.suggest-list button {
  display: block; width: 100%; text-align: left; border: 0; border-radius: 0;
  background: none; padding: 3px var(--sp-5); font-size: var(--fs-md); line-height: 16px;
  font-family: var(--font-mono); cursor: pointer;
}
.suggest-list button:hover, .suggest-list button.on { background: var(--header-bg); }

/* ---------------- 사업자등록증 판독 (cust_ocr · cust_new) ----------------
   판독 창은 받는 줄 하나뿐이라 좁다. 등록 창에는 "읽어서 채웠다" 는 알림 한 판이
   맨 위에 선다 — 값이 저장된 것이 아니라 **채워진 것**임을 분명히 하기 위해서다. */
.modal.window.win-narrow { width: 470px; }
.modal.window.win-narrow .modal-body { display: block; padding: 14px var(--sp-7) var(--sp-7); }
.modal.window.win-narrow .hint {
  margin: 0 0 var(--sp-5); font-size: var(--fs-md); line-height: 17px; color: var(--text-muted);
}
.modal.window.win-narrow .hint:last-child { margin: var(--sp-5) 0 0; }
.ocr-zone { height: 46px; justify-content: center; }
.dropzone.busy { border-style: solid; border-color: var(--primary); cursor: progress; }

.ocr-box {
  border: 1px solid var(--border); border-left: 3px solid var(--primary);
  background: var(--header-bg); padding: var(--sp-4) var(--sp-5); margin-bottom: var(--sp-5);
}
.ocr-line { margin: 0 0 3px; font-size: var(--fs-md); line-height: 17px; }
.ocr-line:last-of-type { margin-bottom: 0; }
.ocr-src { color: var(--text-muted); font-family: var(--font-mono); margin-left: var(--sp-3); }
/* 첫 줄 오른쪽 끝에 재판독 (2026-09-29) */
.ocr-head { display: flex; align-items: center; gap: var(--sp-3); }
.ocr-reread { margin-left: auto; min-width: 22px; padding: 0 var(--sp-3); font-size: var(--fs-lg); }
.ocr-bad { color: var(--danger); margin-left: var(--sp-3); }
.ocr-keep {
  display: flex; align-items: center; gap: 5px; margin-top: 7px;
  font-size: var(--fs-md); color: var(--text); cursor: pointer;
}
.ocr-keep input { margin: 0; }

.cert-shot .shot-body {
  padding: 0; background: var(--c-dark); overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
/* 등록증은 세로로 긴 한 장이다. **판에 맞춰 통째로** 넣는다 — 스크롤해 가며 대질하면
   눈이 왔다 갔다 해서 맞춰 보기 어렵다. 자세히 볼 것은 눌러서 크게 본다. */
.cert-shot .shot-full { max-width: 100%; max-height: 100%; object-fit: contain; cursor: zoom-in; }
/* 값의 자리 — 판독이 읽은 값 위 하이라이트 (대표님 2026-10-04, `_shot_spots.html`). 그림 파일엔 굽지 않고 위에 얹는다 */
.cert-shot .shot-body { position: relative; }
.shot-spots { position: absolute; pointer-events: none; }
/* 첨부 판(Viewer.js) 안 — 뷰어 그림의 크기 · 자리 · 돌림을 그대로 베낀다(`app.js` SpotLink.overlay) */
.shot-spots.in-viewer { position: absolute; left: 0; top: 0; pointer-events: none; }
/* 네모에 마우스 -> 그 값이 든 칸이 옅게 켜진다. 목록 줄 hover(`.grid tbody tr:hover`)와 같은 색 */
.modal.window input.spot-hot, .modal.window textarea.spot-hot { background: var(--c-head); }
/* 테두리 없이 반투명 색만 (대표님 2026-10-04 "테두리가 오히려 시인성을 나쁘게 · 모서리 없애고 반투명한 색상으로만") */
.shot-spots .spot { position: absolute; }
.spot-name  { background: rgba(255, 200, 0, .32); }
.spot-org   { background: rgba(0, 180, 255, .32); }
.spot-title { background: rgba(255, 120, 0, .32); }
.spot-code  { background: rgba(160, 110, 255, .32); }
.spot-tel   { background: rgba(0, 200, 90, .32); }
.spot-mail  { background: rgba(255, 60, 160, .32); }
.spot-addr  { background: rgba(120, 200, 255, .32); }
.spot-etc   { background: rgba(200, 200, 200, .32); }
/* PDF 는 브라우저 뷰어가 제 안에서 맞춰 준다 — 판을 꽉 채우게 둔다(가운데 정렬이면
   높이 100% 가 안 먹는다) */
.cert-shot .shot-frame { align-self: stretch; width: 100%; height: 100%; border: 0; background: var(--c-surface); }
/* 판 머리줄의 [거래처로] · [연락처로] — 파일 이름 옆 (2026-10-03) */
.cert-shot .panel-head .btn-small { margin-left: var(--sp-4); flex: 0 0 auto; }

/* ---------------- 판독 진행 막대 (cust_ocr_wait) ----------------
   **고정폭 글자로 그린다** (대표님 2026-09-29 "좀더 표준적이면서 CMD 스럽게").
   2026-09-26 에 한 번 글자로 했다가 들쭉날쭉해 네모로 물렀는데, 그때는 글꼴을 못박지
   않은 것이 원인이었다. 막대·퍼센트·단계 이름을 **한 글꼴**로 묶어 두면 어긋나지 않는다. */
.cmd-bar { display: flex; align-items: baseline; gap: var(--sp-5); margin: 14px 0 var(--sp-3); }
.cmd-track, .cmd-pct, .cmd-run {
  font-family: var(--font-mono); letter-spacing: 0; white-space: pre;
}
.cmd-track { flex: 1 1 auto; font-size: var(--fs-lg); color: var(--primary); }
.cmd-pct {
  flex: 0 0 auto; min-width: 40px; text-align: right;
  font-size: var(--fs-lg); font-weight: var(--fw-semi);
}
/* [OCR대기] 목록의 흐르는 막대 — 진행률을 모르니 돌고 있다는 것만 보인다.

   **글자로 그리지 않는다** (대표님 2026-09-30 "이거 로드바 모양이 깨져있어").
   전에는 `█`·`░` 를 늘어놓았는데, 그 두 글자가 한 글꼴에 같이 없으면 브라우저가
   서로 다른 글꼴에서 주워 온다 — 칸 너비가 어긋나 막대가 들쭉날쭉해진다.
   칸 하나에 띠를 흘려 보내면 글꼴과 상관이 없다. */
.cmd-run {
  display: inline-block; width: 110px; height: 11px; vertical-align: -1px;
  border: 1px solid var(--border); background: var(--header-bg);
  overflow: hidden; position: relative;
}
.cmd-run::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: -34%; width: 34%;
  background: var(--primary); animation: cmd-run-slide 1.1s linear infinite;
}
@keyframes cmd-run-slide { to { left: 100%; } }
/* 움직임을 줄여 달라고 해 둔 화면에서는 멈춰 세운다 — 띠는 그대로 보인다 */
@media (prefers-reduced-motion: reduce) {
  .cmd-run::after { animation: none; left: 0; }
}

/* [OCR입력(수정)] 칸 — 읽는 동안 흐르는 막대가 선다 (거래처-048) */
.ocr-zone.is-reading { border-color: var(--primary); }
.ocr-zone.is-bad { border-color: var(--danger); }
.ocr-zone .cmd-run { vertical-align: middle; }

/* 판독이 얹은 칸 — **달라진 것만** 표를 한다 (거래처-048) */
.ocr-changed { border-color: var(--primary); background: var(--c-hover); }
/* [되돌리기] — **한 줄로 선다.** 칸 옆에 끼어 들어가 `되돌리 / 기` 로 접혔다
   (대표님 2026-09-30). 줄 안에서 줄어들지 않게 `flex: 0 0 auto` 로 못박는다. */
.ocr-undo {
  flex: 0 0 auto; white-space: nowrap;
  margin-left: var(--sp-3); padding: 0 7px; height: 22px; line-height: 20px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text-muted);
  border-radius: var(--r-1); font-family: inherit; font-size: var(--fs-sm); cursor: pointer;
}
.ocr-undo:hover { border-color: var(--primary); color: var(--primary); }

/* 대표 등록증 — 여럿일 때만 선다 (대표님 2026-09-30) */
.cert-main {
  position: absolute; top: 2px; left: 2px; z-index: 1;
  background: var(--primary); color: var(--c-on-dark); border-radius: var(--r-1);
  padding: 0 var(--sp-2); font-size: var(--fs-xs); line-height: 14px;
}
.file-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
  position: relative;
}
.file-row.is-main .shot { outline: 2px solid var(--primary); outline-offset: -2px; }

/* ---------------- [로그] 창 (대표님 2026-09-30) ----------------
   자취는 **글자 그대로** 읽는 것이라 고정폭 글꼴을 쓴다. 등급은 색으로만 가르지 않고
   글자로도 선다 — 색을 잘 못 가리는 사람에게는 색만으로는 아무 표시가 없다. */
.win-log {
  margin-left: var(--sp-4); font-size: var(--fs-sm); color: var(--text-muted);       /* 머리줄이 밝아진 뒤 흰 글자는 안 보였다(2026-10-05) */
  text-decoration: none; border-bottom: 1px dotted var(--text-muted);
}
.win-log:hover { color: var(--c-on-dark); }
/* 탭 줄은 밝다 — 흰 글씨면 안 보인다(대표님 2026-10-05 "8101에서는 버튼 안보이는데?"). win-id 와 같은 덧칠 */
.top-level-tabs .win-log { color: var(--primary); border-bottom-color: currentColor; }
.top-level-tabs .win-log:hover { color: var(--text); }
/* ---------------- 이력 표 — 8886(구매기록) 이력 규칙의 꼴 ----------------
   대표님 2026-10-05 "erp2는 8886 이력규칙으로". [이력] 은 단추 줄의 단추, 누르면 판 바로 아래 `.hist-box` 가
   펼쳐진다(app.js `data-hist-toggle`). 표는 `table.hist` 한 꼴 — 칸마다 테두리 · 머리줄 바탕 · 가로 스크롤 없이 말줄임.
   원본 D:\purchase\prototype\static\style.css `table.hist` · `.hist-title` · `.empty.small`. */
.hist-box { margin-top: var(--sp-4); }
.hist-title { font-weight: var(--fw-bold); margin: var(--sp-5) 0 var(--sp-2); font-size: var(--fs-md); }
.hist-title:first-child { margin-top: 0; }
table.hist { margin-top: var(--sp-2); table-layout: fixed; width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
table.hist th, table.hist td { border: 1px solid var(--c-line); padding: 3px var(--sp-3); text-align: left;
                               overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.hist thead th { background: var(--c-page); font-weight: var(--fw-semi); }
table.hist .h-at { width: 17%; } table.hist .h-act { width: 11%; } table.hist .h-who { width: 14%; }
table.hist .h-ip { width: 18%; }
table.hist td.h-what { white-space: normal; word-break: break-all; }   /* 바뀐 것은 다 보여야 한다 — 줄바꿈 */
.empty.small { padding: var(--sp-5) var(--sp-1); color: var(--text-muted); font-size: var(--fs-md); }
.log-body { display: flex; flex-direction: column; min-height: 0; }
.log-bar { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.log-level, .log-n {
  height: 22px; border: 1px solid var(--border); border-radius: var(--r-1);
  font-family: inherit; font-size: var(--fs-md);
}
/* 빗장 걸린 줄 — 눈에 띄어야 한다. 이것을 못 보면 열쇠만 계속 고치게 된다 */
/* [중복 첨부파일 정리] — 남길 줄과 지울 줄을 눈으로 가른다.
   검사한 넷은 **0 이라도 세워** 무엇을 봤는지 보인다. 걸린 줄만 진하게. */
.dup-sum { margin-bottom: var(--sp-5); }
.dup-sum td { color: var(--text-muted); font-size: 11.5px; }
.dup-sum td.dup-n { width: 8ch; text-align: right; font-family: var(--font-mono);
                    /* 네 자리 수(`7454명`)가 `7454…` 로 잘렸다 — 관계매칭에서 처음 넘었다 */
                    white-space: nowrap; overflow: visible; text-overflow: clip; }
.dup-sum tr.has td { color: var(--text); }
.dup-sum tr.has td.dup-n { color: var(--danger); font-weight: var(--fw-semi); }
.dup-head { margin: 14px 0 var(--sp-2); font-size: var(--fs-md); }
.dup-grid td { font-size: 11.5px; }
.dup-keep td { color: var(--text-muted); }
.dup-x { color: var(--danger); }
/* [구글 다시 조회] — 흐린 글자 링크는 안 보였다 (대표님 2026-10-04 "파란색글씨로 분명히") */
.dup-recheck { margin-left: var(--sp-4); color: var(--primary); font-weight: var(--fw-semi); }

.conf-blocked { background: var(--danger-bg); padding: var(--sp-3) var(--sp-4); border-radius: var(--r-1); }
.conf-blocked b { color: var(--danger); }
.conf-blocked .btn { margin: 0 var(--sp-3); }

/* 줄로 세운다 — 표가 아니다. 바탕은 다른 창과 같다 (대표님 2026-09-30
   "배경색 이렇게 바꿀필요는 없고 표 형태말고 텍스트 기반이지만 열기도 되게").

   자리는 **가로로 나란히 세워** 맞춘다. 음수 들여쓰기로 맞췄더니 접힌 줄이 왼쪽 밖으로
   삐져나갔다 — 말 칸만 줄바꿈이 일어나게 하면 앞자리를 침범할 수 없다. */
.log-out {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  border: 1px solid var(--border); background: var(--card-bg); border-radius: var(--r-1);
  padding: var(--sp-3) var(--sp-4);
  font-family: var(--font-mono); font-size: 11.5px; line-height: 17px;
}
.log-line, .log-line > summary {
  display: flex; align-items: baseline; gap: 1ch;
  padding: 1px 0; border-bottom: 1px dotted rgba(0,0,0,.05);
}
.log-line > summary { cursor: pointer; }
.log-line.has-more > summary::marker { content: "▸ "; }
.log-line.has-more[open] > summary::marker { content: "▾ "; }
.lg-when { flex: 0 0 20ch; color: var(--text-muted); }   /* "2026-10-05 22:15:27" 19글자 — 17ch 면 두 줄로 접혔다 */
.lg-lv { flex: 0 0 8ch; font-weight: var(--fw-semi); }
.lg-who { flex: 0 0 19ch; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; }
/* 말 칸만 접힌다 — `min-width: 0` 이 없으면 flex 자식이 안 줄어 가로로 넘친다 */
.lg-say { flex: 1 1 auto; min-width: 0; word-break: break-all; }
.log-line.is-error .lg-lv, .log-line.is-error .lg-say { color: var(--danger); }
.log-line.is-warning .lg-lv { color: var(--c-warn); }
.log-line.is-info .lg-lv, .log-line.is-debug .lg-lv { color: var(--text-muted); }
.lg-more {
  margin: var(--sp-1) 0 var(--sp-3) 21ch; padding: var(--sp-3) var(--sp-4);
  background: var(--bg); border-left: 2px solid var(--border);
  font-size: var(--fs-sm); white-space: pre-wrap; word-break: break-all;
}
/* 공용 [로그] 창(_win_log_tabs.html) — 머리 아래 탭 줄 [활동] [시스템] [api] · 활동 거르개의 날짜 칸 */
.log-tabs { display: flex; gap: var(--sp-1); padding: 0 var(--sp-7); border-bottom: 1px solid var(--border); }
.log-bar input[type="date"] { height: var(--h-md); border: 1px solid var(--border); border-radius: var(--r-1); font-family: inherit; font-size: var(--fs-md); }
/* [api] 탭 — 어느 바깥 · 결과 칸 폭, 실패한 줄은 빨갛게(사유까지) */
table.api-hist .h-sys { width: 10%; } table.api-hist .h-act { width: 7%; } table.api-hist .h-ok { width: 20%; }
table.api-hist tr.fail td { color: var(--danger); }

/* [OCR대기] 표 — **줄 간격을 좁힌다** (대표님 2026-09-30 "행간조절 필요").
   스무 줄이 서면 한 화면에 안 들어와 위아래로 훑게 된다. 목록 표와 같은 치수로 맞춘다. */
.pend-grid th, .pend-grid td { padding: 3px var(--sp-4); line-height: 17px; }
/* ADR 0012 (2026-10-04) — 대기 표 · inbox 칸이 같은 칸 너비(`_pend_cols.html`)로 줄 맞춰 선다 */
.pend-grid { table-layout: fixed; width: 100%; }
.pend-grid td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* path 상자 — PC · App · Update 가 같은 폭 */
.pend-grid .pend-from { width: 50px; text-align: center; margin-right: 0; padding: 0; box-sizing: border-box; }
/* result — 중복검출 · 확인필요만 빨간 글자, 굵게 없음 */
.pend-grid td.pend-bad { color: #b42318; }
.pend-grid td.pend-remark { color: var(--text-muted); }
/* [등록이력] (cont_card_log, 2026-10-05) — **리멤버 '전체 명함' 꼴** (대표님 "리멤버 구성 참고해서 비슷하게").
   열 머리 없이 날짜 제목 · 줄 사이 옅은 선 · 두 줄 칸(이름/회사 · 휴대폰/유선)의 아래 줄은 흐린 글자.
   열 너비는 실제 값의 9할이 안 잘리게 재서 정했다(대표님 "열 보정"), 창은 넓은 창(widest). */
.cardlog-head { font-size: var(--fs-xl); font-weight: var(--fw-semi); margin: var(--sp-1) 0 var(--sp-3); }
.cardlog-head span { float: right; font-size: var(--fs-sm); font-weight: var(--fw-normal); color: var(--text-muted); }
.cardlog-grid { table-layout: fixed; width: 100%; border-collapse: collapse; }
.cardlog-grid td { padding: var(--sp-2) var(--sp-4); line-height: 17px; vertical-align: middle;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-bottom: 1px solid var(--border); }
.cardlog-grid tr[data-href] { cursor: pointer; }
.cardlog-grid tr[data-href]:hover td { background: var(--c-page); }
.cardlog-grid tr.cardlog-day td { padding: var(--sp-6) var(--sp-4) var(--sp-2); font-size: var(--fs-lg); font-weight: var(--fw-semi); border-bottom: 0; }
.cardlog-grid tr.cardlog-day span { margin-left: var(--sp-4); font-size: var(--fs-sm); font-weight: var(--fw-normal); color: var(--text-muted); }
.cardlog-grid td.cardlog-time { color: var(--text-muted); font-size: var(--fs-sm); }
.cardlog-grid td.cardlog-pics { padding: 3px var(--sp-3); }
.cardlog-thumb { width: 72px; height: 42px; object-fit: contain; background: var(--c-page);
  border: 1px solid var(--border); vertical-align: middle; }
.cardlog-thumb.back { width: 40px; height: 24px; margin-left: var(--sp-2); }
.cardlog-nopic { display: inline-block; width: 72px; text-align: center; font-size: var(--fs-sm); color: var(--text-muted); }
.cardlog-two b { font-weight: var(--fw-semi); }
.cardlog-two .cardlog-sub { display: block; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; }
.cardlog-tag { margin-left: var(--sp-3); padding: 0 var(--sp-2); font-size: var(--fs-xs); border: 1px solid var(--border);
  border-radius: var(--r-1); color: var(--text-muted); }
/* inbox 단계 — 글자색 없이, 실패한 단계만 빨간 바탕. 스피너는 공용 텍스트 스피너(`.spin`, 아래 "돌아가는 글자") */
.inbox-grid td { white-space: normal; vertical-align: top; user-select: none; caret-color: transparent; }
.inbox-grid td:not([colspan]) { white-space: nowrap; }   /* 단계 칸만 두 줄(사유) — 나머지는 대기 표처럼 한 줄 */
.pend-steps { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pend-steps .bad { color: var(--c-on-dark); background: #b42318; padding: 0 3px; }
/* 메인은 휴대폰만 — 유선 · 팩스 줄의 [메인] 은 흐리게 (ADR 0012 9번) */
.acct-main.is-off { opacity: .35; cursor: not-allowed; }
/* 분류 불가 창 — 판독 원본 아래 [사업자] [명함] [폐기] */
.pick-bar { display: flex; gap: var(--sp-3); padding: var(--sp-3) var(--sp-5); border-bottom: 1px solid var(--border); background: var(--header-bg); }
.pick-bar .btn.on { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }   /* 지금 쪽 */
/* 자석 — 처음 앉은 종류(시스템이 가린 것 · 올린 대기함). 파란 테두리 (대표님 2026-10-04) */
.pick-bar .btn.magnet { outline: 2px solid #0b5cff; outline-offset: 1px; }
.pick-bar .pick-normal, .pick-bar .pick-ask { display: inline-flex; gap: var(--sp-3); align-items: center; }
.pick-bar [hidden] { display: none; }
/* 휴지통 — 줄을 누르면 그림 | 값 (보기 전용) */
.trash-grid tr.trash-row { cursor: pointer; }
.trash-grid tr.trash-row:hover td { background: var(--c-hover); }
.trash-peek-body { display: flex; gap: var(--sp-5); padding: var(--sp-2) 0; }
.trash-pic { flex: 0 0 50%; height: 220px; background: var(--c-page); display: flex; align-items: center; justify-content: center; }
.trash-pic img { max-width: 100%; max-height: 100%; object-fit: contain; }
.trash-facts { flex: 1 1 auto; list-style: none; margin: 0; padding: 0; font-size: var(--fs-md); overflow-y: auto; max-height: 220px; }
.trash-facts li { padding: 1px var(--sp-3); border-bottom: 1px solid var(--border); }
.pend-why-line { font-size: var(--fs-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 사람이 없는 줄이 왜 섰는지 — 이름 자리에 대신 선다 */
.pend-why { color: var(--text-muted); }
/* 어디로 가는지 — [수정등록] 은 이미 있는 거래처를 고치러 가는 것이라 눈에 띄게 */
.pend-way { color: var(--text-muted); }
.pend-way.is-edit { color: var(--primary); font-weight: var(--fw-semi); }

/* ================= 페이지 넘김 — 모든 모듈 공통 모양 =================
   규약 `docs/목록과창.md` 2조. 열 쪽씩 묶고, 멀리는 번호를 직접 친다.
   대표님 2026-09-30 예시 그대로. */
.pager {
  padding: var(--sp-5) var(--sp-1);
  display: flex;
  align-items: center;
  gap: 3px;
  margin: var(--sp-5) 0 var(--sp-2);
}
.pager-page, .pager-step {
  min-width: 22px; height: 22px; padding: 0 5px; border-radius: var(--r-1);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-md); color: var(--text); text-decoration: none;
}
.pager-page:hover, .pager-step:hover { background: var(--header-bg); }
/* 지금 쪽은 **채운 동그라미** — 눌리지 않는다 */
.pager-page.on {
  background: var(--primary); color: var(--c-on-dark); border-radius: var(--r-round); font-weight: var(--fw-semi);
}
.pager-step { color: var(--text-muted); }
.pager-jump { display: flex; align-items: center; gap: var(--sp-2); margin-left: var(--sp-5); }
.pager-jump input {
  width: 52px; height: var(--h-md); padding: 0 var(--sp-3); text-align: center;
  border: 1px solid var(--border); border-radius: var(--r-1);
  font-family: inherit; font-size: var(--fs-md);
}
.pager-jump input::-webkit-outer-spin-button,
.pager-jump input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pager-of, .pager-count { font-size: var(--fs-sm); color: var(--text-muted); }
.pager-count { margin-left: var(--sp-5); }

/* ================= [Filter] — 모든 모듈 공통 모양 =================
   공동규정집 17조 · 규약 원문 `docs/검색과필터.md` 8조.
   대표님 2026-09-30 "filter 색상이나 모양, 방식 전부 통일화해주고".

   **이름과 치수를 여기서 못박는다.** 모듈마다 제 스타일시트에 이 한 벌을 그대로 옮겨
   적는다 — 코드를 같이 쓰지는 않지만(15조) 눈에 보이는 것은 같아야 한다.

       .filter-btn      찾는 줄의 [Filter] 단추 (조건이 걸리면 `.on`)
       .filter-box      펴지는 상자
       .filter-row      갈래 한 줄  > .filter-name  갈래 이름
                                    > .filter-chips 칩들
       .filter-chip     칩 하나 (고르면 `.on`)  > .filter-n  건수
       .filter-foot     안내 한 줄 + [초기화]

   색은 **토큰만** 쓴다(`--primary` · `--border` · `--text` · `--bg` · `--card-bg`).
   모듈마다 토큰 값이 다를 수 있으므로 여기에 색을 직접 적지 않는다 — 적으면 그
   모듈의 다른 화면과 따로 논다.

   모서리는 **2px** 로 통일한다. 이 화면들은 CMD 풍이라 둥근 모서리를 쓰지 않는다. */
.filter-btn.on {
  border-color: var(--primary); color: var(--primary); font-weight: var(--fw-semi);
}
.filter-box {
  margin: 0 0 var(--sp-4); padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--border); background: var(--card-bg); border-radius: var(--r-1);
}
.filter-row { display: flex; align-items: baseline; gap: var(--sp-3); margin-bottom: 5px; }
/* 갈래 이름은 **한 줄로** 선다 — 접히면 그 줄의 칩이 아래로 밀려 어느 갈래 것인지
   알아보기 어렵다(`시·군·구` 가 두 줄로 접혔다, 2026-09-30). */
.filter-row > .filter-name {
  flex: 0 0 66px; font-size: var(--fs-md); color: var(--text-muted); text-align: right;
  white-space: nowrap;
}
.filter-row > .filter-chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* 칩은 [작은 단추]와 같은 높이로 선다 — 나란히 놓였을 때 줄이 어긋나지 않게 */
.filter-chip {
  height: var(--h-sm); padding: 0 var(--sp-4); border-radius: var(--r-1);
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
  font-family: inherit; font-size: var(--fs-sm); line-height: var(--lh-row); cursor: pointer;
}
.filter-chip:hover { border-color: var(--primary); }
.filter-chip.on { border-color: var(--primary); background: var(--primary); color: var(--c-on-dark); }
/* 건수는 **글자보다 흐리게** — 고르는 것은 이름이지 숫자가 아니다 */
.filter-chip > .filter-n { margin-left: 5px; opacity: .65; }
/* 딸린 갈래 — 위엣것에 매달렸다는 것을 표로 보인다 (규약 8-2).
   **글꼴이 가진 글자만 쓴다** — `↳`(↳) 을 썼더니 글꼴에 없어 네모로 떴다
   (2026-09-30). 이 화면들이 쓰는 표는 `▸` 와 `✕` 뿐이다. */
.filter-row.filter-sub > .filter-name { color: var(--primary); }
.filter-row.filter-sub > .filter-name::before { content: "▸ "; opacity: .6; }

.filter-foot {
  display: flex; align-items: center; gap: var(--sp-4);
  margin: var(--sp-3) 0 0; padding-top: var(--sp-3); border-top: 1px dashed var(--border);
}
.filter-foot .hint { flex: 1 1 auto; }

/* 휴지통 — 평소에는 접혀 있다 (대표님 2026-09-30 "드롭박스 형태로 리스트는 숨겨줘") */
.trash-box { margin-top: var(--sp-5); }
.trash-box > summary {
  cursor: pointer; font-size: var(--fs-md); color: var(--text-muted);
  padding: var(--sp-2) 0; user-select: none;
}
.trash-box > summary:hover { color: var(--text); }
.cmd-label {
  margin: 0; font-family: var(--font-mono); font-size: var(--fs-md); color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cmd-label.done { color: var(--primary); }
.cmd-label.bad { color: var(--danger); }

/* 조회줄 — [검색칸][Filter][Option] 을 붙여 둔다(대표님 2026-09-26 "OPTION 버튼은 조회랑
   바짝"). 예전에는 검색 폼이 가로를 다 먹어 Option 이 저만치 밀려 있었다.

   **[조회] 는 없앴다** (대표님 2026-09-30 예시) — 치는 대로 찾으므로 누를 단추가 없다.
   그 자리를 찾는 칸이 쓴다. 옆에 서는 것은 [Filter] 하나뿐이다.

   **이 줄에서 정한다.** 앞쪽에 같은 힘의 규칙을 또 쓰면 여기에 밀린다 —
   CSS 는 같은 힘이면 나중 것이 이긴다(2026-09-30 폰 규칙에서 한 번 겪었다). */
.toolbar .search-form {
  display: flex; align-items: center; gap: var(--sp-3); flex: 0 1 420px;
}
.toolbar .search-form .search-input { width: 100%; max-width: none; }

/* ---------------- 작은 상태 불 (여러 모듈이 같이 쓴다) ----------------
   거래처코드 옆 국세청 상태가 먼저 쓰던 것인데, 연락처가 cards 와 맞는지를 같은
   꼴로 보이게 되면서 공용으로 올렸다 (대표님 2026-10-02 "기존에 쓰던 코드 모듈로
   가져와"). 조각은 `templates/_lamp.html`.

   **불이 없으면 아예 그리지 않는다** — 빈칸이 곧 모름이다. */
.lamp { display: inline-block; width: 7px; height: 7px; border-radius: var(--r-round);
        margin-right: 5px; vertical-align: 1px; flex-shrink: 0; }
.lamp.on   { background: var(--c-ok); box-shadow: 0 0 0 2px rgba(22,163,74,.18); }
.lamp.off  { background: #d33;    box-shadow: 0 0 0 2px rgba(221,51,51,.18); }
.lamp.go   { background: var(--c-primary); box-shadow: 0 0 0 2px rgba(37,99,235,.18); }
.lamp.hold { background: #9ca3af; box-shadow: 0 0 0 2px rgba(156,163,175,.18); }
/* 구글 연결이 끊긴 계정의 불 — 색은 그대로, **흐리게** (원본 전환 설계 10장 ②).
   초록 그대로면 "있다" 는 장담이고, 빨강이면 "없다" 는 거짓말이다. */
.lamp.dim  { opacity: .35; box-shadow: none; }
/* 목록 위 연결 불 — `● 공공API` · `● Google` (대표님 2026-10-03). 글자는 흐리게,
   누르면 그 설정 창이 뜬다. */

.tool-status:hover { color: var(--text); }
.tool-status .lamp { margin: 0; }
/* ════════ 관계매칭 창 (link_match · links/_win_match.html) ════════
   꼴: 왼쪽 대조표(곁판) · 오른쪽 본판(갈래 A·B·C 를 펼치는 표 하나) · 맨 아래 [실행].
   여기 규칙은 이 창에서만 쓴다(`match-*` · `peek-*`). 2026-10-04 흩어진 덧칠을 한 자리로 모았다.
   대표님이 정한 결: **촘촘하게**(설명 한 줄 · 20px 줄) · **본판은 무겁고 곁판은 가볍다**. */

/* ── 창 ──
   오른쪽 끝을 붙잡은 창(`data-anchor-right`) — 자리는 `--win-right` · `--win-top` 둘이고 app.js
   (`makeDraggable` · `pushRight`)가 바꾼다. `!important` 는 예전에 끌어 둔 인라인 left 를 이기려고.
   **펼치면 화면 폭 꽉**: 펼치는 순간 창이 오른쪽 끝으로 밀리고 대조표가 왼쪽 끝까지 찬다. **접으면
   그 자리에서 접힌다**("밀린 위치에서 접기를 누르면 제자리에서 접으란 말이야"). 펼친 폭은 창 자리와
   상관없는 값이라 끌어도 대조표가 늘었다 줄었다 하지 않는다("턱빠진거마냥").
   트랜지션은 **도착하는 상태**의 값을 쓰므로 `.with-side` 에만 단다 — 여는 쪽만 미끄러지고 닫는
   쪽은 한 번에(닫힐 때 본판이 쓸려 가 정신없었다). */
#matchWin { height: calc(100vh - var(--win-top, 20px) - 20px); max-height: none; max-width: none;
            display: flex; flex-direction: column; width: min(96vw, 1180px);
            left: auto !important; right: var(--win-right, 16px) !important;
            top: var(--win-top, 20px) !important; transform: none !important; }
#matchWin.with-side { width: calc(100% - 16px); transition: width .15s ease-out; }
#matchWin .match-split { flex: 1 1 auto; min-height: 0; display: flex; justify-content: flex-end; position: relative; }

/* ── 본판 ── 폭 = 접힌 창 폭 − 창 테두리(2) 로 못 박는다(빼먹으면 접힐 때 2px 밀린다).
   [실행] 바닥줄은 늘 보이고(sticky), 스크롤 판 아래 여백이 0 이라 그 틈으로 줄이 비쳐 나오지 않는다 */
#matchWin .match-split > form { flex: 0 0 calc(min(96vw, 1180px) - 2px); min-width: 0; overflow-y: auto;
                                padding: var(--sp-4) var(--sp-5) 0; }
#matchWin .match-split > form > .modal-footer { position: sticky; bottom: 0; z-index: 2; background: var(--c-surface);
                                                margin: 0 -10px; padding: var(--sp-3) var(--sp-5); }
#matchWin .modal-footer .btn { white-space: nowrap; }
#matchWin .modal-footer .reset-ask .hint { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* 머리 설명은 한 줄 (대표님 2026-10-03 "컨테이너 절약좀 하자 … 한줄로 정리해") */
#matchWin .match-lead { margin: 0 0 var(--sp-3); font-size: 12.5px; line-height: 1.5; color: var(--text);
                        white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── 표 ── 열 너비는 `colgroup` 이 못 박는다(머리와 줄이 같은 자리). 이름 · 거래처는 한 줄로 자르고
   (올리면 통째), 근거만 줄바꿈한다 — 근거는 다 보여야 판단한다 */
#matchWin .match-grid { table-layout: fixed; width: 100%; }
#matchWin .match-grid th, #matchWin .match-grid td { vertical-align: middle; padding: 1px var(--sp-3);
                                                     font-size: var(--fs-md); line-height: 20px; }
#matchWin .match-grid td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#matchWin .match-grid td.match-why { white-space: normal; line-height: 16px; padding-top: var(--sp-1); padding-bottom: var(--sp-1); }
#matchWin .match-grid th.match-score, #matchWin .match-grid td.match-score { text-align: center; }
/* [O][X] 칸은 자르지 않는다 — 말줄임이 [X] 를 `…` 로 먹었다 */
#matchWin .match-grid td.match-ox, #matchWin .match-grid th.match-ox { overflow: visible; text-overflow: clip; cursor: default; }
/* 사람 · 거래처 칸 = 여는 칸(남색) — 누르면 그 수정 창이 겹쳐 뜬다 */
#matchWin .match-grid td.open-cell { cursor: pointer; color: #3b5c9e; }
#matchWin .match-grid td.open-cell:hover { text-decoration: underline; }
/* 짝 옆 꼬리표 — `폐업` · `사용중지` · `후보 3곳` */
.match-state { display: inline-block; padding: 0 5px; margin-left: var(--sp-2); border-radius: 3px;
               font-size: 10.5px; color: var(--text-muted); background: var(--bg);
               border: 1px solid var(--border); }
.match-people { color: var(--text-muted); }

/* ── 갈래 ── 표 하나 안의 `tbody` 하나. 접힌 갈래는 갈래 줄만 남는다(표 안에 표 없음 — 2026-10-04) */
#matchWin tbody.match-group:not(.open) > tr:not(.match-sum) { display: none; }
#matchWin .match-grid tr.match-sum > td { padding: 3px var(--sp-4); white-space: nowrap; overflow: hidden;
                                          text-overflow: ellipsis; font-size: var(--fs-md); }
#matchWin tr.match-sum.has { cursor: pointer; }
#matchWin tr.match-sum.has:hover > td { background: var(--c-hover); }
#matchWin tr.match-sum.open > td { background: var(--c-selected); font-weight: var(--fw-semi); }
#matchWin .match-caret { display: inline-block; width: 1em; transition: transform .1s; }
#matchWin tr.match-sum.open .match-caret { transform: rotate(90deg); }
#matchWin tr.match-sum .match-n { margin-left: var(--sp-5); color: var(--danger); font-weight: var(--fw-semi);
                                  font-family: var(--font-mono); }
#matchWin tr.match-sum .hint { margin-left: var(--sp-5); font-weight: var(--fw-normal); }
#matchWin .match-grid tr.match-head > th { background: var(--bg); }

/* ── 도구줄 ── [정렬] · [필터링] 두 묶음을 금으로 가른다. 근거는 체크 네모 대신 **누르면 켜지는 칩**
   (대표님 2026-10-03 "정렬표, 체크박스 테두리같은거 … 아직도 빈공간 많아") */
#matchWin .match-grid tr.match-tools-row > td { padding: 0 var(--sp-1); background: var(--c-surface); }
#matchWin .match-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3);
                         margin: 0; padding: 3px var(--sp-1); font-size: var(--fs-sm); }
#matchWin .match-tools .tool-box { display: inline-flex; align-items: center; gap: var(--sp-1) var(--sp-2); padding-right: var(--sp-5);
                                   margin-right: var(--sp-2); border-right: 1px solid var(--border); }
#matchWin .match-tools .tool-name { font-weight: var(--fw-semi); color: var(--text); margin-right: var(--sp-2); }
#matchWin .match-tools .btn-small { height: var(--h-xs); min-height: var(--h-xs); font-size: var(--fs-sm); padding: 0 var(--sp-3); }
#matchWin .match-tools .match-sort.on { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }
#matchWin .match-tools label { display: inline-flex; align-items: center; gap: 3px; cursor: pointer;
                               padding: 0 var(--sp-3); height: 18px; border-radius: 9px; border: 1px solid transparent;
                               color: var(--text-muted); }
#matchWin .match-tools label input { display: none; }
#matchWin .match-tools label:hover { border-color: var(--border); }
#matchWin .match-tools label:has(input:checked) { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }
#matchWin .match-tools .hint { margin-left: var(--sp-2); }

/* ── [O] 잇기 · [X] 아님 ── 누르면 **표시만**, [실행] 때 적힌다 (대표님 2026-10-03) */
.dup-grid .match-yes, .dup-grid .match-no { padding: 0 var(--sp-3); min-width: 22px; line-height: var(--lh-row); font-weight: var(--fw-semi); }
.dup-grid .match-yes:hover { color: var(--c-ok); border-color: #a6d8b4; }
.dup-grid .match-no:hover { color: #b42318; border-color: #e0b4b4; }
.dup-grid tr.mark-o td { background: #eaf6ee; }
.dup-grid tr.mark-o .match-yes { color: var(--c-on-dark); background: var(--c-ok); border-color: var(--c-ok); }
.dup-grid tr.mark-x td { background: var(--c-danger-bg); color: var(--text-muted); text-decoration: line-through; }
.dup-grid tr.mark-x td.match-ox { text-decoration: none; }
.dup-grid tr.mark-x .match-no { color: var(--c-on-dark); background: #b42318; border-color: #b42318; }
/* 대조표에 뜬 줄 — 커서 바탕(#eef2f7)보다 **진하게** (대표님 2026-10-04 "커서표시등이랑 색이 같아서
   헷갈리네"). 금줄 테두리는 [O][X] 와 부딪혀 걷었다. [O] · [X] 표시 색이 이긴다(칸 바탕) */
#matchWin .match-grid tr.peek-on { background: #c9d8f0; }

/* ── 대조표(곁판) ── 명함 30% · 등록증 나머지(세로로 길고 글씨가 작다).
   `hidden` 이 이기게 따로 적는다 — `.win-panel` 의 display:flex 가 [hidden] 을 덮어 닫힌 판이 떠 있었다 */
#matchWin .match-side { flex: 1 1 auto; min-width: 0; min-height: 0; border-right: 1px solid var(--border); }
#matchWin .match-side[hidden] { display: none; }
#matchWin.with-side .match-side { animation: panel-slide .15s ease-out .05s both; }
#matchWin .match-side .panel-title, #matchWin .match-side .win-id { white-space: nowrap; }
#matchWin .match-side .account-info { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60%; }
#matchWin .match-side-body { display: flex; flex-direction: column; gap: var(--sp-3); min-height: 0; overflow: hidden; }
.match-side .peek-one { display: flex; flex-direction: column; gap: var(--sp-2); min-height: 0; font-size: var(--fs-md); }
.match-side .peek-card { flex: 0 0 30%; }
.match-side .peek-cert { flex: 1 1 auto; }
.match-side img, .match-side iframe { width: 100%; flex: 1 1 auto; min-height: 0; object-fit: contain;
                                      border: 0; background: var(--c-page); }
.match-side img { cursor: crosshair; }
/* 그림 | 값들 — 대조표 그림 오른쪽에 **칸 이름 없이 값만** (대표님 2026-10-04 "순수 필드값들만").
   값 칸은 좁게(38%), 긴 주소는 줄을 바꾼다. 그림 쪽은 위의 img 규칙 그대로 */
.match-side .peek-pair { flex: 1 1 auto; min-height: 0; display: flex; gap: var(--sp-3); }
.match-side .peek-media { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.match-side .peek-media > .hint { margin: auto; }
.match-side .peek-facts { flex: 0 0 38%; min-width: 0; margin: 0; padding: 0; list-style: none; overflow-y: auto;
                          font-size: var(--fs-md); line-height: var(--lh-row); }
.match-side .peek-facts li { padding: 1px var(--sp-3); border-bottom: 1px solid var(--border); word-break: keep-all;
                             overflow-wrap: anywhere; }
/* 여닫기 탭(‖) — **본판 왼쪽 끝에 붙어 대조표 쪽으로 튀어나온다.** 자리를 먹는 띠는 없다
   (대표님 2026-10-04 "불필요한 구분칸도 없앨것 · 약간 돌출된 손잡이같은 효과 · 아래 자료를 덮어도 됨").
   본판 폭이 고정이라 탭 자리도 고정 — 접히면 창 밖으로, 펼치면 대조표 위로 튀어나온다 */
#matchWin .match-grip { position: absolute; z-index: 5; top: 50%; right: calc(min(96vw, 1180px) - 2px);
                        transform: translateY(-50%); width: 12px; height: 48px;
                        display: flex; align-items: center; justify-content: center;
                        border: 1px solid #c9ced6; border-right: 0; border-radius: var(--r-3) 0 0 var(--r-3);
                        background: var(--c-surface); color: var(--c-text-2); font-size: var(--fs-sm); line-height: 1;
                        box-shadow: -2px 0 3px rgba(15, 23, 42, .12); cursor: pointer; user-select: none; }
#matchWin .match-grip:hover, #matchWin .match-grip:focus-visible {
  background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }
/* 돋보기 — 커서 자리를 크게, 휠로 배율, 왼쪽 위에 배율 글자 (대표님 2026-10-04) */
.match-lens { position: fixed; z-index: 3000; width: 460px; height: 300px; pointer-events: none;
              border: 2px solid var(--c-line-strong); background: var(--c-surface) no-repeat;
              box-shadow: 3px 3px 0 rgba(15, 23, 42, .25); }
.match-lens[hidden] { display: none; }
.match-lens::after { content: attr(data-zoom); position: absolute; left: 0; top: 0; padding: 0 5px;
                     font: 11px/16px var(--font-mono); color: var(--c-on-dark); background: #1b2430; }

@media (prefers-reduced-motion: reduce) {
  #matchWin.with-side { transition: none; }
  #matchWin.with-side .match-side { animation: none; }
}
/* ════════ 관계매칭 창 끝 ════════ */
/* 저장 후 관계 추천 창 (link_recommend) — Connector 와 같은 표(2026-10-04). 창 높이는 고정, 표만 제 안에서
   흐르고 바닥 [건너뛰기] · [저장] 줄은 늘 보인다 */
#recWin { width: min(96vw, 1560px); height: min(88vh, 900px); display: flex; flex-direction: column; }
/* 왼쪽 대조표(명함 · 커서 줄의 등록증) | 오른쪽 본판(표 + 바닥줄). 생김새는 링크매치 대조표(`match-side`) 것 */
#recWin .rec-split { flex: 1 1 auto; min-height: 0; display: flex; }
#recWin .rec-side { flex: 0 0 36%; min-width: 0; min-height: 0; border-right: 1px solid var(--border); }
#recWin .rec-side .panel-title, #recWin .rec-side .win-id { white-space: nowrap; }
#recWin .rec-side .account-info { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60%; }
#recWin .rec-side-body { display: flex; flex-direction: column; gap: var(--sp-3); min-height: 0; overflow: hidden; }
/* 명함 칸은 **값 줄 수만큼** 선다 — 값 목록에 스크롤바가 생기지 않게(대표님 2026-10-05 "왼쪽에 정보쪽 스크롤바").
   그림은 그 높이에 맞춰 줄어든다. 등록증 칸이 남은 자리를 다 쓴다(높이가 고정이라 줄을 옮겨도 안 들썩인다) */
#recWin .rec-side .peek-card { flex: 0 0 auto; }
#recWin .rec-side .peek-card .peek-facts { overflow: visible; }
#recWin .rec-side .peek-card .peek-media { position: relative; }   /* 그림은 높이를 정하지 않는다 — 값 줄이 정한다 */
#recWin .rec-side .peek-card .peek-media > img, #recWin .rec-side .peek-card .peek-media > iframe { position: absolute; inset: 0; width: 100%; height: 100%; }
#recWin .rec-side .peek-cert { flex: 1 1 0; min-height: 0; }
#recWin .rec-side .peek-cert .peek-facts { overflow-y: auto; scrollbar-width: thin; }
#recWin .rec-main { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
#recWin .rec-main > .modal-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; padding: var(--sp-3) 0 0; overflow: hidden; }
#recWin .link-pick-foot .btn { flex: 0 0 auto; white-space: nowrap; }
#recWin .link-pick-foot .hint { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#recWin .rec-lead { margin: 0 var(--sp-5) var(--sp-3); font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 대조표에 뜬 줄 — 링크매치와 같은 진한 바탕. 값 비교 칸 색(hit · miss)이 이긴다 */
#recWin .link-pick tr.pick-row.peek-on td:not(.hit):not(.miss) { background: #c9d8f0; }
/* 중복병합 창 등 `dup-grid` 표의 머리 */
.dup-grid thead th { font-size: var(--fs-md); font-weight: var(--fw-semi); text-align: left; }
/* 고칠 수 없는 열쇠 칸(연락처 구글키) — 칸 모양은 같되 **흐린 바탕**으로 손댈 수 없음을 보인다 */
.field-row input.ro-key { background: var(--bg); color: var(--text-muted); cursor: default; }
/* [Option] 안에서 열쇠가 말을 안 들을 때 그 줄만 빨개진다 */
.fn-list a.fn-bad { color: #d33; font-weight: var(--fw-semi); }

/* 거래처코드 옆 [자동분류] — 저장하는 칸이 아니라 코드를 따라가는 표시다 */
.auto-kind { color: var(--text-muted); font-size: var(--fs-md); white-space: nowrap; }
.auto-kind-clash { color: #b00; font-size: var(--fs-md); white-space: nowrap; }
#biz-kinds { display: none; }
/* 칸에서 Enter 를 쳤을 때 눌릴 기본 단추. 보이지 않지만 `display:none` 은 안 된다 —
   그러면 브라우저가 건너뛰고 그다음 제출 단추([보내기])를 누른다 */
.default-submit { position: absolute; width: 0; height: 0; padding: 0;
                  border: 0; opacity: 0; overflow: hidden; }
/* ===== [SEND] 시작 — 임시 기능. send/떼는법.md ===== */
/* 한 줄에 하나씩: [불] API이름 ..... 결과.
   보낼 값은 창을 늘이지 않고 **마우스를 올리면** 뜬다 — 등록 창이 길어지면 아래가 잘린다. */
.send-box { border-top: 1px solid var(--border); margin-top: 14px; padding-top: var(--sp-5); }
.send-line { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-2) 0; font-size: var(--fs-lg); }
.send-lamp { width: 9px; height: 9px; border-radius: var(--r-round); flex-shrink: 0;
             background: #d33; box-shadow: 0 0 0 2px rgba(221,51,51,.18); }
.send-lamp.on { background: var(--c-ok); box-shadow: 0 0 0 2px rgba(22,163,74,.18); }
.send-peek { cursor: help; white-space: nowrap; }

/* 보낼 값 팝업. 등록 창 안에 그리면 `overflow` 에 잘린다 — **화면에 고정해** 창 밖으로 낸다.
   자리는 app.js 가 마우스 올린 자리에 맞춰 잡는다. */
.send-pop { display: none; position: fixed; z-index: 200;
            background: var(--c-surface); border: 1px solid #333; border-radius: var(--r-2);
            padding: var(--sp-5) var(--sp-6); min-width: 340px; max-width: 520px;
            box-shadow: 0 10px 32px rgba(0,0,0,.28); white-space: normal; }
.send-pop.on { display: block; }
.send-pop-row { display: block; font-size: var(--fs-md); line-height: 1.7; }
.send-pop-row b { display: inline-block; width: 124px; color: var(--text-muted); font-weight: var(--fw-semi); }
.send-dots { flex: 1; border-bottom: 1px dotted var(--border); margin: 0 var(--sp-1); }
/* **단추가 글자에 밀려나지 않게 한다** (대표님 2026-10-01 "왜 마지막까지 아무 버튼이
   안보이냐"). 앞서는 통째로 `nowrap` 이라, 300자짜리 오류 한 줄이 가로로 쭉 늘어나며
   그 끝에 달린 [재확인] 을 창 밖으로 밀어냈다 — HTML 에는 있는데 화면에 없었다.
   줄어드는 것은 **까닭 글자 하나뿐**이고, 단추·시각·결과는 제 너비를 지킨다. */
.send-result { display: flex; align-items: center; gap: var(--sp-3); min-width: 0;
               color: var(--text-muted); }
.send-result > * { flex: 0 0 auto; white-space: nowrap; }
.send-no { color: #b00; flex: 0 1 auto; min-width: 0;
           overflow: hidden; text-overflow: ellipsis; }
.send-done { color: var(--c-ok); font-weight: var(--fw-semi); }
.send-line.send-off .send-peek > b { color: var(--text-muted); }
.send-foot { margin: var(--sp-4) 0 0; color: var(--text-muted); font-size: var(--fs-md); }
/* API 이름은 두 번 누르면 접속설정 창이 뜬다 — 그래서 누를 수 있게 보인다 */
.send-peek > b {
  border-bottom: 1px dotted var(--text-muted);
  cursor: pointer;
}
.conf-window { width: 560px; }
.inline-choice { margin-right: 14px; cursor: pointer; }
.inline-choice input { margin-right: var(--sp-2); vertical-align: -1px; }
/* 접속설정 창의 "거래처정보 연결" — 우리 칸이 상대의 어느 칸으로 가는가.
   가로로 밀지 않는다: 이름은 줄이고 온전한 것은 마우스를 올리면 나온다 */
.map-box { max-height: 380px; overflow-y: auto; margin: var(--sp-1) 0 0; }
.map-line { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-md);
            line-height: 22px; cursor: default; }
.map-dot { width: 7px; height: 7px; border-radius: var(--r-round); flex-shrink: 0; background: #d33; }
.map-line.on .map-dot { background: var(--c-ok); }
.map-line.hold .map-dot { background: #d9880a; }
.map-line.off .map-dot { background: var(--border); }
.map-ours { white-space: nowrap; }
.map-ours i { color: var(--text-muted); font-style: normal; }
.map-theirs { white-space: nowrap; color: var(--text-muted); font-family: inherit; }
.map-n { width: 62px; text-align: right; color: var(--text-muted); flex-shrink: 0; }
.map-state { width: 56px; text-align: right; color: #b00; flex-shrink: 0; }
.map-line.hold .map-state { color: #d9880a; }
.btn-sent { background: #fff1e6; border-color: #f5b98a; color: #c2410c; }   /* 렌트플랜 담당자로 보낸 사람 (대표님 2026-10-07) */
.send-mgr-msg td { color: var(--c-ok); font-size: 11.5px; padding: var(--sp-1) var(--sp-4); white-space: normal; }
.send-mgr-msg.skip td { color: var(--text-muted); }
.send-mgr-msg.bad td { color: #b00; }
.send-mgr-cell { padding: 0 var(--sp-2); text-align: center; }
/* ===== [SEND] 끝 ===== */

/* [OCR대기] 창 — 폰에서 올려 둔 등록증 목록 */
.pend-cell { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.row-acts { white-space: nowrap; text-align: right; }

/* [APP] — 폰에 앱으로 붙이는 단추. 제목줄 오른쪽 끝에 선다 */
.titlebar-app {
  margin-left: auto; background: #3a4450; color: #e8eaed; border: 1px solid #55606d;
  font: inherit; font-size: var(--fs-sm); line-height: 1; padding: 3px var(--sp-4); cursor: pointer;
}
.titlebar-app:hover { background: #47525f; }
/* 크롬이 "설치해도 된다" 고 알려 준 뒤 — 눌러도 되는 때다 */
.titlebar-app.ready { background: #2f6fb5; border-color: #2f6fb5; color: var(--c-on-dark); }
.titlebar-note {
  margin-left: auto; color: var(--text-muted); font-size: var(--fs-sm); max-width: 46%;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.titlebar-note:empty { display: none; }
.titlebar-note + .titlebar-app { margin-left: var(--sp-3); }
/* 할 말이 없으면 그 자리는 접힌다 — 그때는 단추가 오른쪽 끝으로 간다 */
.titlebar-note:empty + .titlebar-app { margin-left: auto; }
.login-titlebar .titlebar-note { color: rgba(255,255,255,.7); }

/* 폰에서만 / 넓은 화면에서만 서는 것들 */
.phone-only { display: none; }
/* 창 제목줄의 새로고침 — 닫기(X) 와 같은 결로 옅게 둔다 */
.titlebar-refresh { color: rgba(255,255,255,.72); text-decoration: none; font-size: var(--fs-lg);
                    padding: 0 var(--sp-3); line-height: 1; }
.titlebar-refresh:hover { color: var(--c-on-dark); }

/* [OCR대기] 창 안의 설치 단추 줄 */
.pend-install { display: flex; align-items: center; gap: var(--sp-4); margin: var(--sp-5) 0 0; }
/* [OCR대기] 에 기다리는 줄이 있을 때 — 눈에 띄지 않으면 며칠씩 그대로 있는다
   (대표님 2026-09-28). 움직임을 싫어하는 설정이면 색만 남기고 멈춘다. */
/* 주황 <-> **평소 단추 바탕**으로 오간다. 어두운 주황으로 내려가면 검게 보여
   눈이 피로하다 (대표님 2026-09-29 "주황색-바탕색 패턴으로"). */
.pend-alert { background: var(--c-warn); border-color: var(--c-warn); color: var(--c-on-dark);
              animation: pend-blink 1.2s steps(1, end) infinite; }
.pend-alert:hover { background: #cf7309; border-color: #cf7309; }
@keyframes pend-blink {
  50% { background: var(--header-bg); border-color: var(--border); color: var(--text); }
}
@media (prefers-reduced-motion: reduce) { .pend-alert { animation: none; } }
/* 수취함에 **아직 분류 안 된** 사진이 있을 때 — 파랑으로 같은 깜빡임(대표님 2026-10-05 "input상태는 파란색 불이었다가
   제대로 된 분류면 주황색 불"). 분류되면 그쪽 단추만 주황(`.pend-alert`)으로 바뀐다 */
.pend-input { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark);
              animation: pend-blink 1.2s steps(1, end) infinite; }
@media (prefers-reduced-motion: reduce) { .pend-input { animation: none; } }
/* 둘 다 설 때 — **주황이 앞서고 파랑은 한 바퀴에 한 번만 섞는다**(대표님 2026-10-05 "파란불/ 주황불 동시 띄워야 하는
   상황이면 주황불 우선으로 하고, 파랑불은 잠깐 신호만 섞어넣어줘 (한번 깜빡)"). 주황 · 바탕 · 주황 · 바탕 · 파랑 · 바탕 */
.pend-alert.pend-mix { animation: pend-mix 3.6s steps(1, end) infinite; }
/* 좋은글귀 — 읽는 중인 줄을 열 번 이상 눌렀을 때 안내 아래 한 편(common/quotes.py) */
.quote-line { display: inline-block; margin-top: var(--sp-1); }
.quote-orig, .quote-src, .quote-why { color: var(--text-muted); }
.quote-why { font-size: var(--fs-sm); }
@keyframes pend-mix {
  0%      { background: #e8820c; border-color: #e8820c; color: #fff; }
  16.66%  { background: var(--header-bg); border-color: var(--border); color: var(--text); }
  33.33%  { background: #e8820c; border-color: #e8820c; color: #fff; }
  50%     { background: var(--header-bg); border-color: var(--border); color: var(--text); }
  66.66%  { background: var(--primary); border-color: var(--primary); color: #fff; }
  83.33%  { background: var(--header-bg); border-color: var(--border); color: var(--text); }
}
@media (prefers-reduced-motion: reduce) { .pend-alert.pend-mix { animation: none; } }

/* 이미 서 있는 거래처와 사업자번호가 같은 줄 — 열어 보기 전에 눈에 띄어야 한다 */
.pend-dup { color: var(--danger); font-weight: var(--fw-semi); margin-right: var(--sp-2); }
.pend-install .titlebar-note { margin-left: 0; max-width: 70%; white-space: normal; }

/* 폰에서 찾기 전에 서는 안내 한 줄. 넓은 화면에서는 나오지 않는다 */
.phone-first { display: none; color: var(--text-muted); font-size: var(--fs-lg);
               padding: 18px var(--sp-2); margin: 0; }

/* ---------------- 폰 (2026-09-28 대표님 "모바일화면 이 모양인데 ui 조절좀") ----------------
   열 열넷을 폰 폭에 욱여넣으면 글자가 한두 자만 남아 아무것도 못 읽는다.
   **가로로 밀지 않는다**(가로 스크롤 금지) — 대신 폰에서는 꼭 볼 넷만 남긴다.
   숨긴 열은 없어진 것이 아니라 접힌 것이다. 줄을 누르면 수정 창에 전부 있다. */
@media (max-width: 700px) {
  /* 칸 너비는 [양식설정] 이 정한 % 다. 좁은 화면에서는 그것을 놓고 글자에 맞춘다 */
  /* 거래처코드는 열두 자라 폰에서 한 열을 통째로 먹는다. 상태는 흐린 줄(row-off)이
     말해 주므로 코드는 접고 **상호·대표·전화** 셋만 남긴다. 누르면 전부 나온다. */
  .list-grid { table-layout: fixed; width: 100%; }
  .list-grid col { width: auto !important; }
  .list-grid th[data-col], .list-grid td[data-col] { display: none; }
  .list-grid th[data-col="cust_name"], .list-grid td[data-col="cust_name"],
  .list-grid th[data-col="cust_owner"], .list-grid td[data-col="cust_owner"],
  .list-grid th[data-col="cust_tel"], .list-grid td[data-col="cust_tel"] { display: table-cell; }
  .list-grid th[data-col="cust_name"], .list-grid td[data-col="cust_name"] { width: 42%; }
  .list-grid th[data-col="cust_owner"], .list-grid td[data-col="cust_owner"] { width: 22%; }
  .list-grid th[data-col="cust_tel"], .list-grid td[data-col="cust_tel"] { width: 36%; }
  .grid td, .grid th { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* 단추는 묶음 하나로 — 늘어놓으면 줄을 넘어가 어느 것이 무엇인지 모른다 */
  .phone-only { display: inline-block; }
  .wide-only { display: none; }

  /* [OCR대기] 창도 폰에서는 꼭 볼 것만 — 올린 때·올린 이·길은 접는다 */
  .pend-grid th:nth-child(-n/**/+3), .pend-grid td:nth-child(-n/**/+3) { display: none; }
  .pend-grid th:nth-child(4), .pend-grid td:nth-child(4) { width: 36%; }
  .pend-grid th:nth-child(5), .pend-grid td:nth-child(5) { width: 30%; }
  .pend-grid th:nth-child(6), .pend-grid td:nth-child(6) { width: 34%; }

  /* 찾기 전에는 줄을 늘어놓지 않는다. 폰에서 볼 것은 **찾은 것**뿐이다 */
  .list-grid:not(.searched) { display: none; }
  .phone-first { display: block; }
  .list-grid:not(.searched) ~ .pager { display: none; }

  /* 머리 단추 줄은 접어 내린다 — 한 줄에 욱여넣으면 서로 겹친다 */
  .top-level-tabs, .toolbar { flex-wrap: wrap; }
  /* 왼쪽 탭이 한 줄을 다 쓰고, 오른쪽 이름 · 로그아웃은 아랫줄로 — 줄어들면 탭이 밖으로 비어져 오른쪽과 겹친다(2026-10-08) */
  .top-level-tabs-scroll { flex: 1 1 100%; flex-wrap: wrap; }
  .top-level-tabs-right { margin-left: auto; padding: var(--sp-1) 0; }
  .top-level-tabs-right { flex-wrap: wrap; gap: var(--sp-2); }
  .win-id { display: none; }
}

/* ================= 폰 (2026-09-30) =================
   **파일 끝에 둔다.** 앞쪽에 두었더니 뒤에 오는 `.modal.window { width: 640px }` 에
   밀렸다 — CSS 는 같은 힘이면 나중 것이 이긴다.

   라벨(오른쪽 정렬 92px) + 칸을 한 줄에 놓으면 폰 폭에서 칸이 잘린다. 대표님이
   보내 주신 화면에서 `cust_c...` · `은ᅙ` · `hhd280@` 처럼 글자가 뭉개졌고,
   거래처코드는 `611-` `88-` `00109` 세 줄로 쪼개졌다(2026-09-30).
   라벨을 위로 올리고 칸을 전폭으로 쓴다. **가로 스크롤은 만들지 않는다.** */
@media (max-width: 700px) {
  /* 창은 **고정**이다 — 화면을 꽉 쓰고 끌어 옮기지 않는다 (대표님 2026-09-30
     "거래처등록,수정은 고정창으로 해줘"). 폰에서는 옮길 자리도 없고, 끌기가 켜져
     있으면 손가락으로 훑을 때 창이 딸려 움직여 스크롤과 부딪힌다. */
  .modal, .modal.window, .modal.window.wide, .modal.window.win-narrow {
    width: auto; max-width: none;
    top: 44px; left: 6px; right: 6px; bottom: 6px;
    transform: none; max-height: none; border-radius: var(--r-3);
  }
  /* 좁은 창(등록증 올리기 · OCR대기)은 내용이 적어 **아래는 내용만큼**만 쓴다 */
  .modal.window.win-narrow { bottom: auto; max-height: calc(100vh - 56px); }
  /* 제목 줄을 잡아도 안 끌린다 — 손가락 동작은 스크롤에 넘긴다 */
  .modal.window .modal-header { cursor: default; touch-action: auto; }

  /* **아래 칸까지 닿게 한다** (대표님 2026-09-30 "스크롤이 안돼서 아래항목 접근안됨").
     창 높이를 위아래로 잡아 두면 안쪽이 그만큼 줄어야 하는데, flex 자식은 기본값이
     "내용만큼" 이라 줄지 않는다 — 그래서 본문이 창 밖으로 밀려 나가고 스크롤 막대가
     설 자리가 없었다. `min-height: 0` 이 그 기본값을 푼다. */
  .modal.window > form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .modal.window .modal-body {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  .modal.window .modal-header, .modal.window .modal-footer { flex: 0 0 auto; }

  .modal.window .field-row {
    display: block;
    margin-bottom: var(--sp-6);
  }
  .modal.window .field-row > label {
    display: block; width: auto; text-align: left;
    margin-bottom: 3px; font-size: var(--fs-md);
  }
  .modal.window .field-row > input,
  .modal.window .field-row > select,
  .modal.window .field-row > .acct-list,
  .modal.window .field-row > .dropzone,
  .modal.window .field-row > .file-list { width: 100%; box-sizing: border-box; }

  /* 거래처코드 — 칸이 한 줄, [사업자][기타] 와 [자동분류] 는 그 아래 */
  .modal.window .field-row .kind-pick { display: inline-flex; margin: var(--sp-2) var(--sp-3) 0 0; }
  /* [자동분류] 줄은 **제 줄로 내린다** — 코드 옆에 붙이면 오른쪽으로 넘쳐 잘린다 */
  .modal.window .field-row .auto-kind,
  .modal.window .field-row .auto-kind-clash {
    display: block; margin: var(--sp-2) 0 0; white-space: normal; line-height: 1.5;
  }
  /* 등록한 뒤의 코드 줄 — 코드·구분·[Fn] 을 한 덩이로 감싸 흐르게 한다 */
  .modal.window .field-row .code-line { display: block; }
  /* 등록한 뒤의 코드는 **한 줄로** — 좁다고 `611-` `88-` `00109` 로 쪼개지던 것 */
  .modal.window .code-fixed { white-space: nowrap; }

  /* 계좌·이메일 줄 — 네 칸을 한 줄에 욱여넣지 않고 **두 줄로 접는다.** */
  .acct-item { flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); }
  .acct-row .acct-bank, .acct-row .acct-holder, .acct-row .acct-purpose,
  .acct-item .mail-address, .acct-item .mail-purpose {
    flex: 1 1 46%; min-width: 0; box-sizing: border-box;
  }
  /* 계좌번호는 길다(`301-0000-0000-01`) — 반 칸에 넣으면 잘려 보인다. 제 줄을 준다 */
  .acct-row .acct-number { flex: 1 1 100%; min-width: 0; box-sizing: border-box; }
  .modal.window .field-row .acct-item label { flex: 0 0 auto; }
  /* 줄과 줄 사이를 눈으로 가른다 — 여럿이면 어디까지가 한 줄인지 안 보였다 */
  .acct-list .acct-item {
    padding: var(--sp-3) 0 var(--sp-4); border-bottom: 1px dashed var(--border);
  }
  .acct-list .acct-item:last-of-type { border-bottom: none; }

  /* 표는 가로로 넘치지 않게 — 긴 값은 줄인다(스크롤바를 만들지 않는다) */
  .modal.window table.grid td { word-break: break-all; }

  /* **핀치로 키운 뒤 밀어도 화면 밖으로 나가지 않게** (대표님 2026-09-30
     "핀치드래그 할때 화면밖으로 안나가도록 해줘"). 가로로 넘칠 것이 없으면 밀어도
     돌아올 자리가 사라지지 않는다. 창은 네 귀를 잡아 두었으니 넘칠 것은 본문뿐이다. */
  html, body { max-width: 100%; overflow-x: hidden; }
  .modal.window .modal-body { overscroll-behavior: contain; }
  /* 긴 글이 칸을 밀어내지 않게 — 줄을 바꾼다 */
  .modal.window .hint, .modal.window p { overflow-wrap: anywhere; }
  /* 폰은 곁판을 아래로 내리고 본판 폭 고정을 푼다 (2026-10-07 코드리뷰 A-5) */
  .modal.window .win-split { flex-direction: column; }
  .modal.window .win-split > .win-main { flex: none; width: auto; }
}

/* ---------------- 명함과 히스토리 (cont_card_view) ----------------
   **연락처에만 있는 판이다** (대표님 2026-10-01 "연락처에서만 사용할 특수한 기능 ·
   현재 명함사진을 오른쪽에 확장시켜서 보여주고, 명함 히스토리도 보여주자").

   거래처의 `.cert-shot` 은 한 장을 판에 꽉 채워 대질하는 자리다. 여기는 **지금 명함
   한 장 + 지나간 것들**이라 위아래로 흐른다 — 그래서 `overflow` 를 열어 둔다. */
.card-hist .panel-body { padding: 0; background: var(--c-dark); overflow-y: auto; }

/* 지금 명함 — 판 너비에 맞춰 통째로 보인다. 자세히 볼 것은 눌러서 크게 본다. */
.card-now { padding: var(--sp-5); background: var(--c-dark); }
.card-hist .shot-full { display: block; width: 100%; height: auto; cursor: zoom-in; }
.card-hist .shot-frame { width: 100%; height: 320px; border: 0; background: var(--c-surface); }

.card-hist .sect {
  margin: 0; padding: var(--sp-5) var(--sp-6) var(--sp-3); background: var(--c-dark);
  color: #cfd4da; font-size: var(--fs-md); font-weight: var(--fw-semi); border: 0;
}

/* 지나간 명함 한 줄. **왼쪽에 점을 찍어 세로로 잇는다** — 시간을 따라 내려온다는 것이
   글자보다 먼저 읽힌다. 리멤버가 쓰는 모양이기도 하다. */
.card-past {
  display: flex; align-items: flex-start; gap: var(--sp-5);
  padding: var(--sp-5) var(--sp-6); position: relative;
}
.card-past::before {                 /* 점과 점을 잇는 실 */
  content: ""; position: absolute; left: 16px; top: 0; bottom: 0;
  width: 1px; background: #3a3f47;
}
.card-past:last-child::before { bottom: 50%; }   /* 마지막 점 아래로는 안 잇는다 */
.card-dot {
  flex: 0 0 auto; width: 9px; height: 9px; margin: 5px 0 0 -0.5px;
  border-radius: var(--r-round); background: #6b7280; position: relative; z-index: 1;
  box-shadow: 0 0 0 3px #2b2f36;     /* 실을 가려 점이 또렷하게 */
}
.card-what { flex: 1 1 auto; min-width: 0; color: #e6e9ed; font-size: 12.5px; }
.card-what b { display: block; font-size: 13.5px; font-weight: var(--fw-semi); }
.card-who { display: block; color: #b6bcc4; }
.card-what .stamp { display: block; margin-top: var(--sp-1); color: #868d96; }
.card-thumb {
  flex: 0 0 auto; width: 88px; height: auto; border-radius: var(--r-1);
  cursor: zoom-in; background: var(--c-surface);
}
.card-hist .hint { padding: var(--sp-6); color: var(--c-text-3); }

/* [CSV 업로드] — 내려받아 적고 올리는 **차례가 눈에 보이게** 한 줄에 둔다
   (대표님 2026-10-02 가 보내 주신 화면 꼴). */
/* 요청로그의 **메시지가 길다** — 무엇을 고쳐야 하는지가 거기 적힌다. 기본 창
   너비(640px)로는 `…` 가 되어 쓸모가 없어지므로 이 창만 넓힌다. */
.modal.window.win-bulk { width: min(96vw, 1180px); }
.bulk-steps { display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap;
              margin: var(--sp-5) 0 14px; padding: var(--sp-5) var(--sp-6); border: 1px solid var(--border);
              border-radius: var(--r-3); background: var(--header-bg); }
.bulk-step-arrow { color: var(--text-muted); font-weight: var(--fw-bold); }
.bulk-up { display: flex; align-items: center; gap: var(--sp-4); margin: 0; }
/* 까닭은 길다 — 줄바꿈해서 다 보인다. 자르면 무엇을 고쳐야 할지 모른다. */
/* `.grid` 는 칸을 한 줄로 자르는데(`nowrap` + `ellipsis`), 여기서는 **다 보여야**
   한다 — 잘린 까닭은 까닭이 아니다. */
.grid td.bulk-note { white-space: normal; overflow: visible; text-overflow: clip;
                     font-size: var(--fs-md); color: var(--text-muted); line-height: 1.5; }

/* ---------------- cards 와 연결된 상태 ----------------

   대표님 2026-10-02: "상태표시만 하자고 card랑 연결상태" · "기존에 쓰던 코드 모듈로
   가져와". 그래서 **거래처코드 옆 국세청 불과 같은 점** 하나다(`.lamp`). 글자 배지와
   단추를 세웠다가 걷어냈다 — 열 하나에 두 가지를 쌓으면 목록이 시끄럽다.

   무슨 색인지는 마우스를 얹으면 글자로 뜬다(`title`). 색만으로 뜻을 나르지 않는다.

   **cards 에 없는 줄에서는 점을 누를 수 있다** — 눌러서 올리기를 켠다. 점 자체는
   7px 이라 못 누르므로 둘레에 누를 자리를 둔다. */
.grid td.lamp-cell { text-align: center; padding: var(--sp-2) 0; }
.lamp-cell .lamp { margin-right: 0; vertical-align: middle; }
.lamp-cell form { margin: 0; }
.lamp-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: var(--h-md); padding: 0; cursor: pointer;
  border: 1px solid transparent; border-radius: var(--r-round); background: none;
}
.lamp-btn:hover { border-color: var(--border); background: var(--card-bg); }
/* 구글 계정을 잇는 두 걸음 — 아직 안 이어졌을 때만 선다. 저장 폼과 **다른 상자**로
   보이게 밑줄 하나로 가른다. */
.link-steps { border-bottom: 1px solid var(--border); padding-bottom: var(--sp-5); }
.link-steps input[type="file"] { flex: 0 0 auto; font-size: var(--fs-sm); width: 230px; }
/* 설명은 **아래 줄**이다 — 같은 줄에 두면 고를 칸과 단추를 밀어낸다 (2026-10-02). */
.link-how { align-items: flex-start; margin: -4px 0 10px; }
.link-how .stamp { flex: 1 1 auto; line-height: 1.6; }
/* ---------------- 잘됐다는 복판 표시 ----------------

   수정 창은 저장해도 그 자리에 남으므로(규약 `목록과창.md` 3조), 위쪽 띠 한 줄만으로는
   창에 가려 안 보인다 (대표님 2026-10-03 "실제 저장이 됐는지 눈에 띄는 식별표시가
   없어서 좀 헷갈려").

   **지나가는 표시다** — 누를 수도 없고(`pointer-events:none`), 그 밑의 글자를 가리지도
   않게 반투명하다. 1.3초 뒤 스스로 사라진다. */
.done-flash {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  /* **무엇보다 위에 뜬다.** 창에 가려 안 보이는 띠를 대신하는 것이라, 창(101)
     보다 아래 두면 만든 뜻이 없어진다 — 60 으로 두어 창 뒤에 깔렸다 (2026-10-03). */
  z-index: 1300; padding: 14px 26px; border-radius: var(--r-3);
  background: rgba(31, 41, 55, .82); color: var(--c-on-dark);
  font-size: 15px; font-weight: var(--fw-semi); letter-spacing: .3px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .25);
  pointer-events: none; animation: done-flash .2s ease-out;
}
@keyframes done-flash { from { opacity: 0; transform: translate(-50%, -46%); } }
.done-flash.off { opacity: 0; transition: opacity .35s ease-in; }

/* 창 맨 아래 한 줄 — 띠와 같은 생김새다 (대표님 2026-10-03 "팝업창에는 이런줄이
   가장 아래에 잠깐 떴으면"). 창 안에 앉으므로 보고 있던 칸을 가리지 않는다. */
.modal .done-line {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  background: var(--card-bg); border-top: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  padding: 5px var(--sp-5); font-size: var(--fs-md); color: var(--text);
  pointer-events: none; animation: done-line .18s ease-out;
}
@keyframes done-line { from { opacity: 0; transform: translateY(6px); } }
.modal .done-line.off { opacity: 0; transition: opacity .4s ease-in; }
/* 안 된 것 — 빨간 선. 읽을 시간이 더 필요해 오래 머문다 (`app.js` 의 `sayDone`) */
.modal .done-line.bad, .done-flash.bad { border-left-color: var(--danger); }

/* **돌아가는 글자** `| / - \` — 기다리는 중이라는 표시 (대표님 2026-10-04 "우분투 설치하면서 터미널
   화면을 봤는데, 대기중일때 ㅣ/ㅡ\ㅣ 이렇게 빙글빙글 돌아가는 표시 … 불러오는중 ... / 여기도").
   표준 용어로 **텍스트 스피너(text spinner)**. 글자 한 칸 너비로 못 박아 옆 글자가 흔들리지 않는다.
   `<span class="spin"></span>` 하나면 어디서나 쓴다. */
.spin::after { content: "|"; display: inline-block; width: 1ch; text-align: center;
               font-family: var(--font-mono);     /* 색 · 굵기는 둘레 글자 그대로 (대표님 "파란색 말고 그냥 일반 텍스트처럼") */
               animation: spin-char .6s steps(1, end) infinite; }
@keyframes spin-char { 0% { content: "|"; } 25% { content: "/"; } 50% { content: "-"; } 75% { content: "\\"; } }
@media (prefers-reduced-motion: reduce) { .spin::after { animation: none; content: "…"; } }

/* ---------------- 누른 뒤의 표시바 (원칙) ----------------
   대표님 2026-10-04 "실행합니다 눌렀는데 처리됐다는 피드백이 없어서 됐는지 안됐는지 모르는 상태로
   새로고침 하니까 반영이 됐더라고" — **원칙: 단추의 응답은 새로고침으로 보이고, 동시에 처리를
   알리는 표시바가 잠깐 뜬다.** 화면 맨 위 3px 띠 하나다(`app.js` 의 `busyBar`).
     run   보내고 답을 기다리는 동안 — 띠가 흐른다
     done  새로 그려진 뒤 — 꽉 찬 띠가 잠깐 머물다 사라진다(안 된 것이면 빨강) */
.busy-bar { position: fixed; left: 0; right: 0; top: 0; height: 3px; z-index: 2000;
            pointer-events: none; overflow: hidden; background: rgba(37, 99, 235, .15); }
.busy-bar.run::after { content: ""; position: absolute; top: 0; bottom: 0; left: -30%; width: 30%;
                       background: var(--primary); animation: cmd-run-slide 1s linear infinite; }
.busy-bar.done { background: var(--primary); animation: busy-done 1.4s ease-in forwards; }
.busy-bar.done.bad { background: var(--danger); }
@keyframes busy-done { 0%, 60% { opacity: 1; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .busy-bar.run::after { animation: none; left: 0; width: 100%; } }

/* 아직 못 누르는 단추 — **왜 못 누르는지는 마우스를 얹으면 뜬다.**
   흐리게만 두고 숨기지 않는다. 숨기면 "원래 없는 기능" 으로 읽힌다. */
.btn:disabled, .num-input:disabled { opacity: .45; cursor: not-allowed; }

/* 구글 계정 잇는 법 — **상세보기** 한 장 (`contacts/google_howto.html`).
   창 안에 여섯 줄을 쓰면 창이 설명으로 덮여, 풀어 쓴 것은 딴 장에 둔다. */
.howto { max-width: 920px; }
.howto h4 { margin: 18px 0 var(--sp-3); font-size: var(--fs-xl); }
.howto-two .howto-k { width: 150px; font-weight: var(--fw-semi); white-space: nowrap; }
.howto-steps { margin: var(--sp-2) 0 0; padding-left: 22px; }
.howto-steps > li { margin: 0 0 9px; line-height: 1.6; }
/* 걸음 안의 곁설명은 **줄을 바꿔** 작게 — 본줄과 섞이면 무엇이 할 일인지 흐려진다 */
.howto-steps .hint { display: block; margin-top: var(--sp-1); }
/* 빠뜨리면 마지막에 막히는 걸음 — 눈에 걸리게 왼쪽에 띠를 둔다 */
.howto-warn { border-left: 3px solid var(--danger); padding-left: 9px; margin-left: -12px; }
/* 콘솔에 넣을 줄 — **손으로 옮겨 적지 않게** 한 줄로 내놓고 복사 단추를 붙인다. */
.howto-uri { display: flex; align-items: center; gap: var(--sp-3); margin: 5px 0 var(--sp-1); }
.howto-uri code { background: var(--bg); border: 1px solid var(--border);
                  padding: 3px var(--sp-3); font-size: var(--fs-md); }

/* [path] 의 앞머리 — **어디서 왔나**(폰 · 화면). 뒤에 오는 "어디로 가나" 와
   같은 칸에 서므로, 작고 흐리게 두어 둘이 섞여 보이지 않게 한다. */
.pend-from { display: inline-block; margin-right: var(--sp-2); padding: 0 var(--sp-2);
             font-size: var(--fs-sm); color: var(--text-muted);
             border: 1px solid var(--border); border-radius: 3px; }

/* [전부 반영] 과 [전부 버림] 은 한 짝이다 — 사이를 붙여 두고 짝끼리 띄운다. */
.bulk-pair { display: inline-flex; gap: var(--sp-1); margin-right: var(--sp-5); }

/* 숫자 몇 자리만 받는 칸 — 그냥 두면 `.field-row` 의 flex 가 끝까지 늘린다.
   주기(분)처럼 세 자리면 족한 자리에 쓴다. */
.field-row .num-input { flex: 0 0 auto; width: 76px; text-align: right; }

/* 수정 창의 한 줄 — 지금 어떤 상태인지와, 빨강이면 [올리기 켜기]. */
.sig-line { display: flex; align-items: center; gap: var(--sp-4); margin: 0 0 var(--sp-5);
            padding: var(--sp-3) var(--sp-5); border: 1px solid var(--border); border-radius: var(--r-2);
            background: var(--header-bg); }
/* 설명은 **늘어나지 않는다** — 늘리면 단추가 오른쪽 끝으로 밀려 설명과 멀어진다.
   대표님 2026-10-03: "올리기를 켜 두었습니다 … [올리기끄기]" 이렇게 붙여 달라. */
.sig-line .hint { flex: 0 1 auto; }
.sig-line form { margin: 0; }

/* ---------------- 창 위에 창 (규약 `목록과창.md` 7조) ----------------
   겹친 창은 화면 전체를 덮는 액자다. 밑의 창은 그대로 있고 어둡게만 가린다. */
.stack-layer { position: fixed; inset: 0; z-index: 1250; background: rgba(15, 23, 42, .28); }
.stack-frame { width: 100%; height: 100%; border: 0; background: transparent; display: block; }
/* 액자 안 — 탭·목록은 숨기고 창만. 어둡게 가리는 일은 밖(`.stack-layer`)이 한다 */
html.stacked, html.stacked body { background: transparent; }
html.stacked .top-level-tabs, html.stacked .view-body { display: none; }
html.stacked .modal-backdrop { background: transparent; }
/* ---------------- 보기 전용 연락처 창 (cont_viewer) ----------------
   대표님 2026-10-03 "수정은 안되는 보기전용 화면". 칸 대신 글자로 선다 —
   입력 상자 모양이면 고칠 수 있는 줄 안다. */
.view-only .field-row { align-items: baseline; margin-bottom: var(--sp-3); }
.view-only .view-val { flex: 1 1 auto; min-width: 0; font-size: var(--fs-lg); overflow-wrap: anywhere; }
.view-only .view-note { white-space: pre-wrap; }
.view-only .view-tag { display: inline-block; padding: 0 5px; margin-left: var(--sp-2); border-radius: 3px;
                       font-size: 10.5px; color: var(--text-muted); border: 1px solid var(--border); }

/* ---------------- 첨부 판 (cust_cert_view · cont_card_view) ----------------
   대표님 2026-10-03 — 사업자 · 연락처가 같은 판(`templates/_att_panel.html`)을 쓴다.
   위는 누른 한 장(Viewer.js 판 안 보기 · 돌리기 · 키우기), 아래는 연락처의 명함 히스토리. */
.att-panel { background: var(--c-dark); }
/* ✕ 는 판 머리줄 공통 꼴(`.win-side > .panel-head .side-shut`) — 2026-10-04 링크매치와 맞춤 */
.att-panel .att-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60%; }
.att-stage { flex: 1 1 62%; min-height: 280px; position: relative; background: var(--c-dark); }
.att-stage > img { display: none; }               /* 뷰어가 제 자리에 그린다 */
.att-stage .viewer-canvas img { cursor: zoom-in; }
.att-stage .att-frame { width: 100%; height: 100%; border: 0; background: var(--c-surface); display: block; }
.att-more { flex: 0 1 auto; max-height: 38%; overflow-y: auto; }
.att-more .sect { margin: 0; padding: var(--sp-5) var(--sp-6) var(--sp-3); background: var(--c-dark);
                  color: #cfd4da; font-size: var(--fs-md); font-weight: var(--fw-semi); border: 0; }
.att-more .card-past { cursor: pointer; }
.att-more .card-past:hover, .att-more .card-past.is-on { background: var(--c-dark); }

.att-more .card-x { flex: 0 0 auto; align-self: center; border: 1px solid #4a505a; background: none;
                    color: #cfd4da; font-size: var(--fs-sm); padding: 1px var(--sp-3); border-radius: 3px; cursor: pointer; }
.att-more .card-x:hover { color: #ff8a80; border-color: #ff8a80; }
.att-more .card-past.is-off .card-what, .att-more .card-past.is-off .card-thumb { opacity: .4; }
.att-more .card-past.is-off .card-what b { text-decoration: line-through; }
.file-row .shot[data-att-full] { cursor: pointer; }
/* 지어지는 칸 — 잠긴 동안은 흐린 바탕, 오른쪽 끝에 `자동생성` 과 연필 (대표님 2026-10-03) */
.field-row input[data-auto-lock] { background: var(--bg); color: var(--text-muted); cursor: default; }
.field-row .auto-tag { flex: 0 0 auto; font-size: var(--fs-sm); color: var(--text-muted); white-space: nowrap;
                       border: 1px solid var(--border); border-radius: 3px; padding: 0 5px; }
.field-row .lock-edit { flex: 0 0 auto; margin-left: auto; border: 1px solid var(--border); background: none;
                        border-radius: 3px; padding: 0 var(--sp-3); line-height: 20px; cursor: pointer;
                        color: var(--text-muted); }
.field-row .lock-edit:hover, .field-row .lock-edit.on { color: var(--primary); border-color: var(--primary); }
/* 목록 위 상태 불(`● 공공API` · `● Google`)은 **보기만** — 누를 것이 아니다 (대표님 2026-10-03
   "OPTION에 들어가면 되는데 구태여 할 필요 없어"). 손가락 모양을 안 띄운다. */
.tool-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: 0 var(--sp-2) 0 var(--sp-3);
  font-size: var(--fs-md);
  color: var(--text-muted);
  text-decoration: none;
  cursor: default;
}

/* ======================================================================
   erp2 — 탭 묶음 (2026-10-04, 대표님 "하위표시를 그룹별로 나란히")
   [처음]  [모듈 탭…]  [지금 상위의 하위…] — 하위는 늘 나란히 펼쳐 둔다.
   모듈 탭에 커서를 올리면 상위(거래처 …)만 한 줄로 뜨고, 누르면 그 첫 하위로 간다.
   ====================================================================== */
.tab-bundle { display: flex; align-items: stretch; margin-left: var(--sp-5); }
.tab-group + .tab-group { margin-left: 0; }
/* 모듈 탭에 커서 → 그 모듈의 묶음 세로 목록 — 가로면 길어서 미끄러진다(대표님 2026-10-08). 탭과 한 묶음(.tab-group)이라 내려가는 사이 안 닫힌다 */
.tab-group { position: relative; }
.tab-sub {
  display: none; position: absolute; top: 100%; left: 0; z-index: 50;
  padding: var(--sp-2); gap: var(--sp-1); white-space: nowrap; flex-direction: column; align-items: stretch; min-width: 100%;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 0 var(--r-3) var(--r-3) var(--r-3);
  box-shadow: 0 4px 12px rgba(15, 23, 42, .12);
}
.tab-group:hover .tab-sub, .tab-group:focus-within .tab-sub { display: flex; }
/* 손가락(마우스 없음) — 올리기가 없으니 첫 누름에 묶음을 열고(app.js tabTouch), 길게 누름의 링크 메뉴는 끈다(대표님 2026-10-10 폰에서 master 누르면 메뉴가 겹침) */
@media (hover: none) {
  .tab-group:hover .tab-sub, .tab-group:focus-within .tab-sub { display: none; }
  .tab-group.open .tab-sub { display: flex; }
  .top-level-tabs a { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
}
.tab-sub .tab-sub-item:hover { background: var(--header-bg); }
.tab-sub .tab-sub-item { border-bottom: 0; border-left: 2px solid transparent; border-radius: var(--r-2); justify-content: flex-start; }
.tab-sub .tab-sub-item.active { border-left-color: var(--primary); background: var(--header-bg); }
a.top-level-tab { display: inline-flex; align-items: center; text-decoration: none; }
.tab-bundle-sub { gap: 0; align-items: center; }
.tab-bundle-sub::before { content: ""; width: 1px; height: 14px; background: var(--border); margin: 0 var(--sp-6) 0 0; }
.tab-sub-item {
  display: inline-flex; align-items: center; height: 26px; padding: 0 var(--sp-6); font-size: var(--fs-md);
  color: var(--text); text-decoration: none; border-bottom: 2px solid transparent;
  box-sizing: border-box; white-space: nowrap;
}
.tab-sub-item:hover { background: var(--card-bg); }
.tab-sub-item.active { color: var(--primary); font-weight: var(--fw-semi); border-bottom-color: var(--primary); }
.tab-sub-parent {
  display: inline-flex; align-items: center; height: 26px; padding: 0 var(--sp-5) 0 0;
  font-size: var(--fs-md); font-weight: var(--fw-bold); color: var(--text); text-decoration: none; white-space: nowrap;
}
.tab-sub-parent:hover { color: var(--primary); }
/* 하위 = 눌림 단추 한 벌(segmented) — 회색 홈 안에서 고른 칸만 흰 단추 */
.tab-bundle-sub > .tab-sub-item { height: 22px; padding: 0 var(--sp-6); background: var(--c-line); color: var(--text-muted); border-bottom: 0; border-radius: 0; }
.tab-bundle-sub > .tab-sub-parent + .tab-sub-item { border-radius: 5px 0 0 5px; }
.tab-bundle-sub > .tab-sub-item:last-child { border-radius: 0 5px 5px 0; }
.tab-bundle-sub > .tab-sub-parent + .tab-sub-item:last-child { border-radius: 5px; }
.tab-bundle-sub > .tab-sub-item:hover { background: var(--c-line); color: var(--text); }
.tab-bundle-sub > .tab-sub-item.active, .tab-bundle-sub > .tab-sub-item.active:hover {
  background: var(--c-surface); color: var(--text); font-weight: var(--fw-semi); border-radius: 5px; box-shadow: inset 0 0 0 2px var(--c-line);
}

/* ── 마이그레이션 · 백업 (master › configuration, migr) ───────────────────────────────────
   경광등 한 줄은 빨강 단추의 깜빡임(`reset-blink`)을 그대로 쓴다 — 같은 뜻 같은 불(대표님 2026-10-05).
   줄마다 결과는 표준 정책: 성공 초록 · 실패 빨강 바탕(adr/0015). 확인은 erp2 꼴 [실행] → [실행합니다](`.drop-ask`). */
.migr-siren { position: sticky; top: 0; z-index: 40; margin: 0 0 var(--sp-4); padding: 3px var(--sp-5); color: var(--c-on-dark); font-weight: var(--fw-bold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; background: var(--c-danger); border: 1px solid var(--c-danger);
  animation: reset-blink 1s steps(1, end) infinite; }
@media (prefers-reduced-motion: reduce) { .migr-siren { animation: none; } }
.migr-warn { margin: var(--sp-2) 0; padding: var(--sp-2) var(--sp-4); border: 2px solid var(--c-danger); background: var(--c-danger-bg); color: #b71c1c; font-weight: var(--fw-semi); }
.migr-ok { color: var(--c-ok); font-weight: var(--fw-semi); }
.migr-bad { color: var(--c-danger); font-weight: var(--fw-bold); }
tr.migr-row-bad td { background: var(--c-danger-bg); }
.migr-sheet td, .migr-sheet th { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 10em; }
.migr-sheet td.migr-why { white-space: normal; max-width: none; color: var(--c-danger); }
.migr-diff td.migr-changed { color: var(--c-danger); font-weight: var(--fw-semi); }
.migr-row { display: flex; gap: var(--sp-4); align-items: center; flex-wrap: wrap; margin: var(--sp-2) 0; }
.migr-job { margin: var(--sp-2) 0 var(--sp-4); padding: var(--sp-2) var(--sp-4); border: 1px solid var(--border); background: var(--header-bg); }
/* 회사정보 km_info · km_info_modify — 이름표가 "사업자등록번호" 처럼 길어 84px 에서 두 줄로 꺾였다 */
.km-info .field-row label { width: 104px; white-space: nowrap; }
.km-info .field-row select { flex: 1 1 auto; height: var(--h-md); }
.ex3-view.info-view { flex: 1 1 0; }
.cinfo-empty { color: var(--c-text-3); }
.cinfo-img { max-height: calc(var(--h-xl) * 2); }
.cinfo-thumb { height: var(--h-xl); margin-left: var(--sp-3); flex-shrink: 0; }

/* [이력] 곁판 — 공용 (로그정책 2절 · 이력표 규약) */
/* `.with-hist` 일 때만 창이 넓어지고 오른쪽에 곁판이 선다 — 접으면 클래스가 빠져 원래 너비(640px).
   폼은 창의 직계 자식 그대로 두고 격자 칸만 나눈다: 머리 줄은 가로 전체, 왼쪽 = 띠 + 폼, 오른쪽 = 곁판.
   창 본문과 곁판은 각자 스크롤, 가로 스크롤은 없다(칸은 말줄임). 표 값은 구매기록 본보기(table.hist)대로. */
.modal.window.with-hist {
  width: min(96vw, 1100px); height: min(88vh, 900px);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 460px);
  grid-template-rows: auto auto minmax(0, 1fr);
}
.modal.window.with-hist > .modal-header { grid-column: 1 / -1; grid-row: 1; }
.modal.window.with-hist > .hist-viewing { grid-column: 1; grid-row: 2; }
.modal.window.with-hist > form { grid-column: 1; grid-row: 3; min-height: 0; display: flex; flex-direction: column; }
.modal.window.with-hist > form > .modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.modal.window.with-hist > form > .modal-footer { flex: 0 0 auto; }
/* 회사정보 수정 창 — 화면이 낮으면 창(최대 88vh) 밖으로 칸이 새던 것(2026-10-09): 본문만 스크롤 */
.modal.window.km-info:not(.with-hist) > form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.modal.window.km-info:not(.with-hist) > form > .modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.modal.window.km-info:not(.with-hist) > form > .modal-footer { flex: 0 0 auto; }
.hist-panel { grid-column: 2; grid-row: 2 / -1; min-height: 0; overflow-y: auto; overflow-x: hidden;
              border-left: 1px solid var(--border); padding: var(--sp-3) var(--sp-4); background: var(--card-bg); }
.hist-head { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-2); font-size: var(--fs-md); }
.hist-head .hist-title { font-weight: var(--fw-semi); }
.hist-head .hist-count { color: var(--text-muted); font-size: var(--fs-sm); }
.hist-head .hist-close { margin-left: auto; color: var(--text-muted); text-decoration: none; padding: 0 var(--sp-2); }
.hist-head .hist-close:hover { color: var(--text); background: var(--header-bg); }
table.hist { margin-top: var(--sp-2); table-layout: fixed; width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
table.hist .h-rev { width: 11%; } table.hist .h-at { width: 25%; } table.hist .h-who { width: 13%; }
table.hist .h-act { width: 14%; } table.hist .h-chg { width: 25%; } table.hist .h-see { width: 12%; }
table.hist th, table.hist td { border: 1px solid var(--border); padding: 3px var(--sp-3);
                               overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.hist thead th { background: var(--header-bg); color: var(--text-muted); font-weight: var(--fw-semi); text-align: left; }
table.hist td.del { text-align: center; padding: 1px var(--sp-1); }
table.hist tr.gone td { color: var(--text-muted); opacity: .6; text-decoration: line-through; }
table.hist tr.on td { background: var(--c-selected); }
.btn.btn-sm { display: inline-flex; align-items: center; height: var(--h-xs); min-height: var(--h-xs); padding: 0 var(--sp-3);
              font-size: var(--fs-sm); line-height: 16px; text-decoration: none; color: var(--text);
              background: var(--header-bg); border: 1px solid var(--border); }
.btn.btn-sm:hover { background: var(--border); }
.btn.btn-sm.on { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }
.modal-header-actions .btn.btn-sm { margin-right: var(--sp-1); }
/* 판을 볼 때 — 창 위 노란 띠 한 줄, 지금과 다른 칸은 입력 칸에 옅은 노랑 */
.hist-viewing { padding: 3px var(--sp-5); font-size: var(--fs-md); background: var(--c-note-bg); border-bottom: 1px solid #ecd98a;
                white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hist-viewing a { margin-left: var(--sp-2); }
.field-row.hist-diff input, .field-row.hist-diff select, .field-row.hist-diff textarea { background: #fff7c2; }
@media (max-width: 700px) {
  .ex3-wrap.ex3-two{flex-direction:column;height:auto;} .ex3-wrap.ex3-two .ex3-list,.ex3-wrap.ex3-two .ex3-view{flex:none;width:100%;min-width:0;}   /* 두 칸 틀 — 폰은 위아래(erp2 폰 폭 700px) */
  .cfg-shell .ex3-tree { flex: none; width: 100%; } .cfg-shell .tree-cap { flex: 0 0 100%; } .ex3-wrap.cfg-shell .ex3-view.cfg-main { flex: none; overflow: visible; }   /* configuration 폰 — 트리는 위에 묶음마다 한 줄, 화면은 그 아래 제 키대로 */
  .modal.window.with-hist { width: auto; height: auto; grid-template-columns: minmax(0, 1fr);
                            grid-template-rows: auto auto minmax(0, 1fr) auto; }
  .hist-panel { grid-column: 1; grid-row: 4; border-left: none; border-top: 1px solid var(--border); max-height: 40vh; }
}
/* 공용 [로그] 창(_win_log_tabs.html) — 머리 아래 탭 줄 [활동] [시스템] [api] · 활동 거르개의 날짜 칸 */
.log-tabs { display: flex; gap: var(--sp-1); padding: 0 var(--sp-7); border-bottom: 1px solid var(--border); }
.log-bar input[type="date"] { height: var(--h-md); border: 1px solid var(--border); border-radius: var(--r-1); font-family: inherit; font-size: var(--fs-md); }
/* 회사관련서류 7단계 — 찾는 칸 + 메인 ⚙ 한 줄 · 틀이 안 움직이게(고름 줄 · [저장] 은 자리를 잡고 visibility 로만) · prompt template */
.cdoc-find { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-2); }
.cdoc-find .cdoc-search { flex: 0 1 420px; min-width: 0; margin: 0; }   /* erp2 표준 찾는 칸 폭 — 거래처 목록(.toolbar .search-form)과 같은 420px, 한 장 폭으로 늘이지 않는다 */
.cdoc-find .cdoc-search .search-input { width: 100%; max-width: none; }
.cdoc-cfg.on { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); box-shadow: inset 0 1px 2px rgba(0,0,0,.25); }
.cdoc-pickinfo { display: inline-flex; align-items: center; gap: var(--sp-3); }
.cdoc-pickinfo.off, .cdoc-save.off, .cdoc-cancel.off { visibility: hidden; }
.cdoc-cancel { margin-right: var(--sp-2); }
.cdoc-pickbar .btn-small { height: var(--h-sm); min-height: var(--h-sm); padding-top: 0; padding-bottom: 0; line-height: var(--lh-row); }
.cdoc-left .cdoc-drop { margin-top: 0; }
.cdoc-left .cdoc-jobs { margin: var(--sp-1) 0 var(--sp-2); }
.cdoc-ptpl-head { margin: var(--sp-4) 0 var(--sp-1); font-size: var(--fs-sm); color: var(--text-muted); font-weight: var(--fw-semi); }
.cdoc-ptpl { margin: 0; max-height: 180px; overflow: auto; padding: var(--sp-3) var(--sp-4); font: 11px/1.45 var(--font-mono);
             white-space: pre-wrap; word-break: break-all; background: var(--header-bg); border: 1px solid var(--border); border-radius: var(--r-2); }
/* 폴더 설정 prompt template — 대표님 2026-10-06 "창높이가 커졌으면 텍스트박스를 가변적으로 키워야지 스크롤바 없게" */
.modal.window.cdoc-fset .cdoc-ptpl { max-height: none; overflow: visible; }
.modal.window.cdoc-fset.with-hist > form > .modal-body { display: flex; flex-direction: column; }
.modal.window.cdoc-fset.with-hist .cdoc-ptpl { flex: 1 0 auto; }

/* 회사서류: 필터와 알림은 겹쳐 띄워 목록 자리를 지킨다. */
.cdoc-find { position: relative; }
.cdoc-lock-form { margin: 0; }
.cdoc-cfg svg { display: block; width: 16px; height: 16px; }
.cdoc-filter-box { position: absolute; top: 100%; left: 0; right: auto; width: min(520px, 100%); z-index: 30; box-shadow: 0 2px 8px var(--border); }
.cdoc-page { position: relative; }
.cdoc-phone-first { display: none; }
/* 회사관련서류 알림도 다른 화면처럼 머리 띠 위 가로로 긴 알림 줄(.notice) — 오른쪽 위에 떠 있던 440px 상자는 걷었다(대표님 2026-10-11 "보통 길죽하게") */
@media (max-width: 768px) { .cdoc-phone-first { display: block; } .cdoc-results.cdoc-unfiltered { display: none; } }
/* 이름 바꾸기 ✎ — 줄마다 글자 단추를 두니 제목이 한두 글자로 잘렸다. 자리는 잡아 두고(틀 안 움직임) 마우스를 올린 줄에서만 보인다 */
.cdoc-row .cdoc-rename { width: 16px; padding: 0; text-align: center; font-size: var(--fs-md); visibility: hidden; flex: none; }
.cdoc-row:hover .cdoc-rename, .cdoc-row:focus-within .cdoc-rename { visibility: visible; }
/* 남이 자물쇠를 쥐었으면 — 빨간 자물쇠 + 밑에 겹쳐 띄운 한 줄(자리를 차지하지 않아 틀이 안 움직인다) */
.cdoc-lock-form { position: relative; }
.cdoc-cfg.held { color: var(--danger); border-color: var(--danger); }
.cdoc-lock-who { position: absolute; right: 0; top: 100%; margin-top: var(--sp-1); white-space: nowrap; font-size: var(--fs-sm); color: var(--danger); background: var(--card-bg); padding: 0 var(--sp-2); z-index: 5; pointer-events: none; }
/* 자물쇠에 묶인 단추(.lock-act) — 디자인시스템 3-2 "자물쇠 단추 색"(대표님 2026-10-11 "얼룩덜룩한 모양 별로" → 줄무늬 걷음).
   잠기면 숨고(풀어야 보임) 그것이 곧 표시라 따로 무늬를 두지 않는다. 역할 셋: 확정(저장) = 파랑 채움 하나 · 나머지(신규 · 추가 · 수정 · 이름 바꾸기 · 설정) = 파랑 테두리 · 지우기 = 빨강 테두리. */
.lock-act, .btn.lock-act { background: var(--c-surface); color: var(--c-primary); border: 1px solid var(--c-primary); }
.lock-act:hover, .btn.lock-act:hover { background: var(--c-hover); color: var(--c-primary-hover); border-color: var(--c-primary-hover); }
.btn.lock-act.lock-save, .btn.lock-act[type=submit] { background: var(--c-primary); color: var(--c-on-dark); border-color: var(--c-primary); }
.btn.lock-act.lock-save:hover, .btn.lock-act[type=submit]:hover { background: var(--c-primary-hover); color: var(--c-on-dark); border-color: var(--c-primary-hover); }
.btn.lock-act.btn-danger, .btn.lock-act.lock-del { background: var(--c-surface); color: var(--c-danger); border-color: var(--c-danger); }
.btn.lock-act.btn-danger:hover, .btn.lock-act.lock-del:hover { background: var(--c-danger-bg); color: var(--c-danger); border-color: var(--c-danger); }
.lock-act > span { background: none; padding: 0; }
.lock-act:disabled, .lock-act.off { opacity: .45; }
/* [공동 프롬프트] — 히트박스 **안쪽** 오른쪽 위(대표님 2026-10-05 "겹치게 하지 말고 안으로") */
/* 폴더 설정 창 — LLM 처리규칙 이름표 밑 [↻ 다시 짓기] (이름표 칸 폭 안) · 이중확인 한 줄은 자리를 늘 잡는다(틀이 안 움직인다) */
.cdoc-rulelab { width: 84px; flex-shrink: 0; align-self: flex-start; display: flex; flex-direction: column; align-items: flex-end; gap: var(--sp-2); }
.cdoc-rulelab label { width: auto; }
.cdoc-rulelab .btn-small { height: var(--h-sm); min-height: var(--h-sm); padding: 0 var(--sp-4); line-height: var(--lh-row); font-size: var(--fs-lg); }
.cdoc-rename-note { margin: -6px 0 6px; min-height: 16px; color: #b34700; white-space: normal; }
.cdoc-prompt-link.lock-act { position: absolute; top: 2px; right: 4px; padding: 0 5px; font-size: var(--fs-xs); line-height: 12px; border-radius: 3px; }   /* 히트박스 크기는 그대로 — 안쪽 모서리에 작게(대표님 "여백 늘리지 말고 안으로") */
/* 회사관련서류 올리기 칸(erp2 표준 dropzone) — 맨 위 칸을 감싼 상자에 [공동 프롬프트] 를 얹는다 */
.cdoc-dropbox { position: relative; }
.cdoc-dropbox form { margin: 0; }
.cdoc-dropbox.has-prompt .dropzone { padding-right: 84px; }   /* 높이는 그대로 — 가운데 글이 모서리 단추 몫만큼 비켜 앉는다 */
.cdoc-left .cdoc-drop.dropzone { justify-content: center; }

/* ===== erp2 세 칸 틀 — 트리 · 문서 목록 · 뷰어 (templates/_ex3.html · docs/문서관리-표준.md 2절 · 9f)
   본보기 치수는 8113 서식 라이브러리: 칸 사이 8px · 트리 160px(줄 22px · 글자 12px · 고른 줄 파란 바탕 흰 글자 · 오른쪽 건수) · 목록 flex 1 · 뷰어 flex 0 1 50%.
   틀이 움직이지 않는다 — 폭은 고정 비율이고 고른 줄이 바뀌어도 그대로. 가로 스크롤 없음(긴 글은 줄임표). ===== */
.ex3-wrap { display: flex; gap: var(--sp-4); align-items: stretch; min-height: 0; height: calc(100vh - 160px); }
.ex3-wrap.ex3-two .ex3-list{flex:0 0 42%;}
.ex3-wrap.ex3-two .ex3-view{flex:1 1 0;display:block;overflow-y:auto;}
.ex3-two .ex3-view > .ex3-head{position:sticky;top:0;background:var(--card-bg);z-index:2;}
.ex3-wrap.cfg-shell { height: calc(100vh - 48px); min-height: 420px; }   /* 위 메뉴 줄만 빼고 화면 끝까지 — 가로 탭 줄이 없어 160px 을 뺄 까닭이 없다(대표님 2026-10-12 "하단 죽은 공간") */
.view-body:has(> .cfg-shell) { padding-bottom: var(--sp-5); }
.cfg-shell .cfg-main { overflow-y: auto; padding: var(--sp-4); }   /* configuration 두 칸 — 왼쪽 트리(_cfg_tree.html) · 오른쪽 화면 */
.ex3-tree, .ex3-list, .ex3-view { background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--r-2); min-height: 0; }
.ex3-tree { flex: 0 0 160px; width: 160px; display: flex; flex-direction: column; overflow: hidden; }
.ex3-nodes { flex: 0 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: var(--sp-1); }   /* 늘어나지 않는다 — 아래 받는 칸이 폴더 줄 바로 밑에 붙어 폴더가 늘면 같이 내려온다(대표님 2026-10-06), 넘치면 폴더 줄만 스크롤 */
.ex3-node { display: flex; align-items: center; gap: var(--sp-2); height: 22px; padding: 0 var(--sp-2) 0 var(--sp-3); border: 1px solid transparent; border-radius: 3px; font-size: var(--fs-md); line-height: 20px; color: var(--text); min-width: 0; }
.ex3-node.sub { padding-left: 14px; }
.ex3-nl { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--sp-2); height: 100%; color: inherit; text-decoration: none; cursor: pointer; }
.ex3-nm { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ex3-n { flex: none; color: var(--text-muted); font-size: var(--fs-sm); }
.ex3-paste { flex: none; font-size: var(--fs-xs); opacity: .8; }   /* 지금 Ctrl+V 가 붙는 곳 — 고른 줄에만 */
.ex3-node:hover { background: var(--header-bg); }
.ex3-node.on, .ex3-node.on:hover { background: var(--primary); color: var(--c-on-dark); }
.ex3-node.on .ex3-n { color: var(--c-on-dark); }
.ex3-node.drop-on { background: var(--c-selected); outline: 2px dashed var(--c-link); outline-offset: -2px; }   /* 서류 줄을 끌어다 놓으면 그 폴더로 옮긴다(분류 바꾸기 — 올리기가 아니다) */
.ex3-list { flex: 1 1 0; min-width: 260px; overflow-y: auto; overflow-x: hidden; position: relative; }
.ex3-view { flex: 0 1 50%; min-width: 260px; display: flex; flex-direction: column; overflow: hidden; }
.ex3-node.on:hover { background: var(--primary); }
.ex3-paste { margin-left: auto; }
/* 자물쇠 안 트리 줄 — ▲▼ 차례 · ⚙ 폴더 설정(대표님 2026-10-06). 이동 고르기 중에는 줄 안에 [이동] 단추 하나만 */
.ex3-ord { display: inline-flex; flex: none; }
.ex3-ord button { border: 0; background: none; padding: 0 1px; font-size: 9px; line-height: 20px; color: var(--text-muted); cursor: pointer; }
.ex3-ord button:hover { color: var(--primary); }
.ex3-node.on .ex3-ord button { color: var(--c-on-dark); }
.ex3-gear { display: inline-flex; align-items: center; height: 16px; padding: 0 3px; font-size: var(--fs-sm); line-height: 14px; border-radius: 3px; flex: none; }
.ex3-mvgo { display: none; flex: none; height: 18px; min-height: 18px; padding: 0 var(--sp-3); }
.ex3-movebar { position: absolute; top: 14px; left: 0; right: 0; z-index: 5; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding: 3px var(--sp-2); font-size: var(--fs-sm); background: var(--c-surface); border-bottom: 1px solid var(--primary); }
.ex3-moving { outline: 2px solid var(--primary); outline-offset: -2px; background: var(--c-head); }   /* 이동 고르기 중 — 트리가 강조된다 */
.ex3-moving .ex3-nodes { padding-top: 30px; }
.ex3-moving .ex3-node, .ex3-moving .ex3-node.on { background: var(--c-selected); color: var(--text); margin-bottom: 1px; }   /* 모든 폴더 줄을 똑같이 옅게(고른 파란 줄 표시는 풀린다) */
.ex3-moving .ex3-node.on .ex3-n { color: var(--text-muted); }
.ex3-moving .ex3-paste, .ex3-moving .ex3-ord, .ex3-moving .ex3-gear { display: none; }
.ex3-moving .ex3-node:hover, .ex3-moving .ex3-node.on:hover { background: #bcd4fb; }   /* 마우스를 올린 줄은 더 진하게 */
.ex3-moving .ex3-node[data-inbox] { opacity: .5; }
/* 고른 줄 · 끌어 올린 줄 · Sortable 끌기 강조는 같은 모양 */
.ex3-node.mv-pick, .ex3-moving .ex3-node.mv-pick, .ex3-node.drop-on, .ex3-node.sortable-chosen { background: #8fb8f7; outline: 2px solid var(--primary); outline-offset: -2px; color: var(--text); }
.ex3-node.mv-pick .ex3-mvgo { display: inline-flex; align-items: center; }
.ex3-node.sortable-ghost { opacity: .45; }
.cdoc-row.sortable-chosen { background: var(--c-selected); }
.cdoc-row.mv-pending td { opacity: .5; }
.cdoc-row.mv-pending td.c-name { opacity: 1; }
.cdoc-row.mv-pending .cdoc-name, .cdoc-row.mv-pending .cdoc-ext { opacity: .5; }
.cdoc-mvto { flex: none; font-size: var(--fs-sm); color: var(--primary); }
.ex3-tree.paste-intake .ex3-paste { display: none; }   /* 아래 전체 받는 칸을 직접 눌러 골랐으면 Ctrl+V 는 그쪽 — 고른 줄의 표시를 걷는다(마지막에 고른 쪽) */
/* 트리 바닥의 맨 위 전체 받는 칸 — 폴더가 많아도 보이게 붙는다. 예전 모양 규칙(.cdoc-left · .cdoc-dropbox · .cdoc-prompt-link · .cdoc-jobs)은 그대로, 폭 160px 에 맞춰 높이만 글자 두세 줄 */
.ex3-foot { flex: none; padding: var(--sp-2); overflow: visible; }
.cdoc-intake .cdoc-drop.dropzone { height: 80px; padding: var(--sp-7) var(--sp-2) var(--sp-2); flex-wrap: wrap; align-content: center; white-space: normal; text-align: center; }
.cdoc-intake .cdoc-drop .dz-text { white-space: normal; text-align: center; overflow: visible; }
.cdoc-intake .cdoc-dropbox.has-prompt .dropzone { padding-right: var(--sp-2); }
.cdoc-intake .cdoc-prompt-link.lock-act { right: 3px; top: 3px; }
.cdoc-intake .cdoc-dropbox { position: relative; }
.cdoc-intake .cdoc-drop-id { position: absolute; left: 4px; bottom: 2px; z-index: 2; margin: 0; font-size: var(--fs-xs); color: #aeb4bd; pointer-events: none; }   /* 받는 칸 이름표 — 상자 안 왼쪽 아래(위쪽은 [공동 프롬프트]와 겹친다) */
.ex3-head { flex: none; height: 14px; display: flex; justify-content: flex-end; align-items: center; padding: 0 var(--sp-2); }   /* 칸 이름표(win-id) 자리 — 칸 머리 오른쪽 */
.ex3-head .win-id { margin: 0; color: #aeb4bd; line-height: 14px; }
/* 목록 칸은 납작하게 — 이름표 띠를 따로 두지 않고 고름 줄(업로드 · N개 고름 …) 오른쪽 끝에 얹는다(대표님 2026-10-06 "불필요한 컨테이너 없애") */
.ex3-list > .ex3-head { position: absolute; top: 0; right: 6px; height: 24px; z-index: 4; padding: 0; pointer-events: none; }
.ex3-list .cdoc-pickbar { padding-right: 104px; flex-wrap: nowrap; overflow: hidden; }
/* 좁은 목록 칸(600px 아래): 고름 줄이 넘치지 않게 — 업로드 상자의 '→ 폴더' 글자 · 칸 이름표를 접는다(폴더는 트리의 파란 줄이 이미 보여 준다) */
@container (max-width: 600px) {
  .cdoc-upgo .cdoc-upto { display: none; }
  .ex3-list > .ex3-head { display: none; }
  .ex3-list .cdoc-pickbar { padding-right: var(--sp-2); }
}
.ex3-tree, .ex3-list, .ex3-view { position: relative; }
.ex3-list { display: flex; flex-direction: column; overflow: hidden; }   /* 스크롤은 안의 폼(표)이 한다 — 고름 줄 · 표 머리는 위에 붙는다 */
.ex3-list.drop-files { outline: 2px dashed var(--primary); outline-offset: -2px; background: var(--c-hover); }   /* 바깥 파일을 끌어다 놓는 동안 칸 테두리 강조 */
.ex3-view .vw { flex: 1 1 0; height: auto; min-height: 0; }
/* 회사관련서류 — 머리 띠(한 장 폭)는 예전 왼쪽 판의 머리 그대로(.cdoc-left 규칙), 그 아래 세 칸이 남은 높이를 채운다 */
.cdoc-page { display: flex; flex-direction: column; height: calc(100vh - 92px); min-height: 420px; }
.cdoc-page > .ex3-wrap { flex: 1 1 0; height: auto; }
.cdoc-head { flex: none; overflow: visible; padding-right: 0; }
.cdoc-pickbar { padding: 0 var(--sp-3); }
.ex3-list .cdoc-pickbar { flex: none; position: sticky; top: 0; z-index: 3; background: var(--card-bg); margin-bottom: 0; border-bottom: 1px solid var(--border); height: 24px; }
.cdoc-upload { display: inline-flex; align-items: center; gap: var(--sp-2); flex: none; min-width: 0; }
.cdoc-gear { display: inline-flex; align-items: center; height: 20px; padding: 0 5px; border-radius: var(--r-1); font-size: var(--fs-md); flex: none; }
.cdoc-upto { font-size: var(--fs-sm); max-width: 84px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* [업로드 → 폴더] — 네이버웍스 [글쓰기] 꼴 파란 상자(대표님 2026-10-06), 고름 줄 오른쪽 */
.cdoc-upgo { display: inline-flex; align-items: center; gap: var(--sp-2); height: 22px; min-height: 22px; padding: 0 var(--sp-5); border: 0; border-radius: 3px; background: #1d6ce0; color: var(--c-on-dark); font-weight: var(--fw-bold); cursor: pointer; }
.cdoc-upgo:hover { background: #1559bd; }
/* 고름 줄 가장 왼쪽 ⚙ — 체크박스 열(24px) 위. 평소엔 회색 · 눌리지 않음 */
.cdoc-pickbar .cdoc-gear { flex: none; width: 22px; height: 20px; margin: 0 var(--sp-2) 0 0; display: inline-flex; align-items: center; justify-content: center; }
.cdoc-pickbar .cdoc-gear.off { color: #b7bdc6; border: 1px solid var(--border); background: var(--card-bg); cursor: default; }
/* 목록 마지막 줄 아래 오른쪽 — 네이버웍스 [글쓰기] 자리(대표님 2026-10-06). 목록과 함께 흘러 마지막 글 바로 밑에 선다 */
.cdoc-upfoot { display: flex; justify-content: flex-end; align-items: center; gap: var(--sp-3); padding: var(--sp-5) var(--sp-3) var(--sp-6); }
.cdoc-upfoot .cdoc-upgo { height: 28px; min-height: 28px; padding: 0 var(--sp-7); font-size: var(--fs-lg); }
.cdoc-upgo .cdoc-upto { color: var(--c-on-dark); font-weight: var(--fw-normal); max-width: 120px; }
.cdoc-pickinfo { white-space: nowrap; }
.ex3-list > form { margin: 0; flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; }
/* 문서 목록 표 — 8100 간결한 표(.grid.list-grid)를 그대로 쓰고, 좁은 칸만 여백을 줄인다 */
.cdoc-grid { border: 0; border-radius: 0; }
.cdoc-grid thead th { position: sticky; top: 24px; z-index: 2; height: 25px; }
.cdoc-grid tbody tr { cursor: default; }
/* 좁은 목록 칸에서도 제목 열이 사라지지 않게 — 칸 폭이 600px 아래면 폴더 열을 접는다(제목이 가장 먼저 · 2026-10-06 1025px 창에서 제목이 0px 이 됐다) */
.ex3-list { container-type: inline-size; min-width: 340px; }
.cdoc-grid col.g-pick { width: 24px; } .cdoc-grid col.g-folder { width: 84px; } .cdoc-grid col.g-date { width: 82px; }
.cdoc-grid col.g-edit { width: 22px; } .cdoc-grid col.g-flag { width: 30px; } .cdoc-grid col.g-del { width: 50px; }
@container (max-width: 600px) {
  .cdoc-grid col.g-folder { width: 0; }
  /* 칸은 두고(열 차례가 colgroup 과 어긋나지 않게) 폭 · 글자만 0 */
  .cdoc-grid th.c-folder, .cdoc-grid td.c-folder { padding: 0; font-size: 0; overflow: hidden; border-left: 0; border-right: 0; }
}
.cdoc-grid .c-pick, .cdoc-grid .c-edit, .cdoc-grid .c-flag, .cdoc-grid .c-del { padding: 3px var(--sp-1); text-align: center; }
.cdoc-grid td.c-name { padding-right: var(--sp-2); }
.cdoc-grid .c-nm { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; width: 100%; }
.cdoc-grid .cdoc-name { cursor: pointer; }
.cdoc-grid td .cdoc-flag { width: auto; margin: 0; cursor: pointer; }
.cdoc-grid td .cdoc-flag:disabled { cursor: default; opacity: .55; }   /* 평소엔 지금 값만 보이고 누를 수 없다 — 자물쇠 안에서만 눌린다 */
.cdoc-grid .c-del .cdoc-del { width: 100%; }
.cdoc-grid .c-edit .cdoc-rename { width: 18px; }
.cdoc-grid .cdoc-empty { padding: var(--sp-4); white-space: normal; }
tr.cdoc-row { display: table-row; }
.cdoc-grid tr.cdoc-row.on, .cdoc-grid tr.cdoc-row.on:hover { background: var(--c-selected); }
.cdoc-grid tr.cdoc-row.llm-failed, .cdoc-grid tr.cdoc-row.llm-failed:hover { background: var(--c-danger-bg); }
.cdoc-edit.fx { position: fixed; right: auto; transform: translateY(-50%); }   /* 표의 줄 위에 겹쳐 띄운다 — 위치 · 폭은 스크립트가 줄과 목록 칸에 맞춘다 */
/* 폰 폭 — 목록 먼저, 트리는 가로로 접어 얹고, 뷰어는 새 창(공용 뷰어가 이미 한다) */
@media (max-width: 768px) {
  .cdoc-page { height: auto; min-height: 0; }
  .ex3-wrap, .cdoc-page > .ex3-wrap { flex-direction: column; height: auto; }
  .ex3-view { display: none; }
  .ex3-tree { flex: none; width: auto; max-height: 96px; }
  .ex3-nodes { display: flex; flex-wrap: wrap; }
  .ex3-node.sub { padding-left: var(--sp-3); }
  .ex3-list { flex: none; min-width: 0; overflow: visible; }
  .ex3-head { display: none; }
}

/* 공용 뷰어 (docs/표준컴포넌트-뷰어.md 8절)
   본보기: parts_catalog/static/parts.css 443~492 · 717 · 818~820 · 965~969 (값은 그대로, 색만 erp2 변수로).
   클래스 이름은 모두 vw- 로 시작 — erp2 다른 것과 안 부딪히게. 틀이 움직이지 않게: 도구줄 높이 고정 · 쪽 칸/배율 글자 폭 고정. */
.vw { position: relative; display: flex; flex-direction: column; height: var(--vw-h, calc(100vh - 140px)); min-height: 360px; min-width: 0; background: var(--card-bg); }   /* relative = 새 창 전용의 세로 슬라이더 · 목차 판이 기댈 자리 */
.vw-head { flex: 0 0 auto; margin-bottom: var(--sp-2); }
.vw-tools { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-2); flex-wrap: nowrap; height: 22px; overflow: hidden; }   /* 오른쪽 정렬 · 단추 사이 4px (parts.css:455) · 높이 22px (parts.css:1093~1097) */
.vw-slot { display: inline-flex; align-items: center; gap: var(--sp-2); }
.vw-slot:empty { display: none; }
.vw-slot[data-slot="lead"] { margin-right: auto; }   /* 앞자리 무리는 왼쪽에 붙고 나머지는 오른쪽 (parts.css:456 · 460 의 margin-left/right:auto 와 같은 효과) */
.vw-gap { flex: 0 0 10px; width: 10px; }                                                                                        /* 무리 사이 10px (.etc-tools-gap) */
.vw-tools button { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; height: var(--h-md); min-height: var(--h-md); min-width: 22px; font: inherit; font-size: var(--fs-md); line-height: 1; padding: 0 var(--sp-2); border: 1px solid var(--border); border-radius: 0; background: var(--card-bg); color: inherit; cursor: pointer; white-space: nowrap; }   /* 최종값: 높이 22 · 여백 0 4px · 글자 12px · 각짐 (parts.css:461 을 :1093~1097 이 덮은 값 · :726~729) */
.vw-tools button:hover:not(:disabled) { background: var(--header-bg); }
.vw-tools button:disabled { opacity: .45; cursor: default; }
.vw-tools button > svg { display: block; width: 14px; height: 14px; }                                                 /* 아이콘 14px (parts.css:1102) — HTML 의 width/height 속성은 이 규칙이 이긴다 */
.vw-tools .vw-icon-btn, .vw-tools button:has(> svg) { width: 22px; padding: 0; }                                      /* 그림만 든 단추는 정사각 22x22 (parts.css:1103) */
.vw-tools .vw-fit-btn, .vw-tools .vw-full-btn { padding: 0 var(--sp-2); }                                                      /* 맞춤 · 전체화면은 ::before 14px + 여백 0 4px (parts.css:976 은 특이도에서 짐) */
.vw-page-input { box-sizing: border-box; flex: 0 0 56px; width: 56px; height: var(--h-md); font: inherit; font-size: var(--fs-md); padding: var(--sp-1) var(--sp-2); border: 1px solid var(--border); border-radius: 0; text-align: right; background: var(--card-bg); color: inherit; }   /* 쪽 칸 56x22 오른쪽 정렬 (parts.css:502 · 1106) */
.vw-dim { flex: 0 0 auto; min-width: 40px; font-size: var(--fs-md); line-height: 22px; color: var(--text-muted); white-space: nowrap; }   /* line-height 22 (parts.css:1107) · 최소폭은 틀 고정용(우리 규칙) */
.vw-fit-btn::before { content: ''; display: inline-block; width: 14px; height: 14px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.8'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M5%2019L19%205'/%3E%3Cpath%20d='M12%205h7v7'/%3E%3Cpath%20d='M12%2019H5v-7'/%3E%3C/svg%3E") center / 14px 14px no-repeat; mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.8'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M5%2019L19%205'/%3E%3Cpath%20d='M12%205h7v7'/%3E%3Cpath%20d='M12%2019H5v-7'/%3E%3C/svg%3E") center / 14px 14px no-repeat; }   /* 맞춤 ⤢ 굵기 2.8 (parts.css:976~977) */
.vw-full-btn::before { content: ''; display: inline-block; width: 14px; height: 14px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M3%209V3h6'/%3E%3Cpath%20d='M3%203l7%207'/%3E%3Cpath%20d='M15%203h6v6'/%3E%3Cpath%20d='M21%203l-7%207'/%3E%3Cpath%20d='M3%2015v6h6'/%3E%3Cpath%20d='M3%2021l7-7'/%3E%3Cpath%20d='M15%2021h6v-6'/%3E%3Cpath%20d='M21%2021l-7-7'/%3E%3C/svg%3E") center / 14px 14px no-repeat; mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M3%209V3h6'/%3E%3Cpath%20d='M3%203l7%207'/%3E%3Cpath%20d='M15%203h6v6'/%3E%3Cpath%20d='M21%203l-7%207'/%3E%3Cpath%20d='M3%2015v6h6'/%3E%3Cpath%20d='M3%2021l7-7'/%3E%3Cpath%20d='M15%2021h6v-6'/%3E%3Cpath%20d='M21%2021l-7-7'/%3E%3C/svg%3E") center / 14px 14px no-repeat; }   /* 네 귀 화살표 (parts.css:979) */
.vw-full .vw-full-btn::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M10%204v6H4'/%3E%3Cpath%20d='M10%2010L3%203'/%3E%3Cpath%20d='M14%204v6h6'/%3E%3Cpath%20d='M14%2010l7-7'/%3E%3Cpath%20d='M4%2014h6v6'/%3E%3Cpath%20d='M10%2014l-7%207'/%3E%3Cpath%20d='M20%2014h-6v6'/%3E%3Cpath%20d='M14%2014l7%207'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M10%204v6H4'/%3E%3Cpath%20d='M10%2010L3%203'/%3E%3Cpath%20d='M14%204v6h6'/%3E%3Cpath%20d='M14%2010l7-7'/%3E%3Cpath%20d='M4%2014h6v6'/%3E%3Cpath%20d='M10%2014l-7%207'/%3E%3Cpath%20d='M20%2014h-6v6'/%3E%3Cpath%20d='M14%2014l7%207'/%3E%3C/svg%3E"); }   /* 전체화면 중엔 안쪽 화살표 = 나가기 (parts.css:980) */
.vw-off { visibility: hidden; }                                    /* PDF 가 아닌 파일은 PDF 단추 자리만 지킨다 */
.vw-nodoc .vw-ipc { visibility: hidden; }                          /* 미리보기가 없는 파일 — 자리는 지킨다 */
.vw-nodoc .vw-pdf-btn, .vw-nodoc [data-act="open"], .vw-nodoc [data-slot="find"], .vw-nodoc [data-slot="index"] { visibility: hidden; }   /* 찾기 · 목차 슬롯은 8e 부터 vw-ipc 가 아니다(PDF 보기에서도 남는다) — 그래서 따로 */
.vw-slider { display: none; }                                      /* PC 에는 쪽 슬라이더가 없다 (parts.css:936) — 새 창 전용(.vw-solo)에서만 그림 오른쪽 세로 */
:root { color-scheme: light; }  /* pdf_viewer.css 의 light dark 가 ERP 화면으로 새지 않게 (검수_2026-10-08_뷰어엔진 1-1) */
.vw-body { position: relative; flex: 1 1 auto; min-height: 0; border: 1px solid var(--border); background: var(--c-head); }   /* 상자 바탕 #e9ecef */
.vw-fig { position: absolute; inset: 0; overflow: auto; }
/* 스크롤바는 얇고 흐리게 — **erp2 전체 표준**(대표님 2026-10-05 "erp2에 적용되는게 무조건 표준"). 브라우저 기본(굵은 회색 막대 +
   화살표)이 화면을 먹고 거슬렸다. 표준 CSS(scrollbar-width · color) 한 벌 — 페이지 전체 · 모든 스크롤 칸 */
html, * { scrollbar-width: thin; scrollbar-color: rgba(0, 0, 0, .28) transparent; }
.vw-pdfjs { position: absolute; inset: 0; overflow: auto; background: var(--c-head); }
.vw-fig.hidden, .vw-pdfjs.hidden { display: none; }
.vw-eng-pdfjs [data-slot="ink"] { visibility: hidden; }
.vw-fig, .vw-pdfjs { cursor: grab; }
.vw-pdfjs .textLayer span { cursor: text; }
.vw-grabbing .vw-fig, .vw-grabbing .vw-pdfjs { cursor: grabbing; user-select: none; }
.vw-loading .vw-fig { cursor: progress; }
.vw-inner { position: relative; padding: var(--sp-4) 0; --pw: 600px; user-select: none; isolation: isolate; }   /* 클릭·끌기로 그림이 파랗게 선택되지 않게 (부품-#49) */
.vw-pg img { -webkit-user-drag: none; }
.vw-pg { position: relative; width: var(--pw); margin: 0 auto var(--sp-4); background: var(--c-surface); box-shadow: 0 1px 4px rgba(0,0,0,.25); }   /* 쪽 사이 8px (parts.css:471) */
.vw-pg::before { content: ''; display: block; padding-bottom: var(--pg-pad, 129.4%); }   /* 그림 오기 전 자리 — JS 가 이 책 비율로 --pg-pad 를 준다 */
.vw-pg-sized::before { display: none; }                                                    /* 비가 다른 쪽은 JS 가 제 너비 · 높이를 준다 */
.vw-pg img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: contain; z-index: 0; }   /* 쪽 그림은 늘이지 않는다 — 본보기 화면-01 */
.vw-pg img.vw-pg-svg, .vw-pg img.vw-pg-tile { z-index: 1; pointer-events: none; }   /* 본보기는 DOM 차례로 쌓았다 — 여기선 z-index 로 분명히: 통짜 < 벡터 · 조각 < 쪽번호 */
.vw-pg img.vw-pg-tile { inset: auto; }                                                     /* 조각은 left · top · width · height 를 JS 가 정한다 */
.vw-pg img.vw-pg-thumb { image-rendering: auto; }                                          /* 훑기용 썸네일 (부품-#279) */
.vw-pg-on { outline: 2px solid var(--primary); }
.vw-pg-no { position: absolute; right: 4px; top: 4px; font-size: var(--fs-sm); color: #999; background: rgba(255,255,255,.8); padding: 0 var(--sp-2); border-radius: 3px; z-index: 2; }   /* 쪽 번호 오른쪽 위 회색 작은 글자 */
.vw-pg-hot { position: absolute; inset: 0; z-index: 3; }                                   /* 강조 층 (8c 검색 상자 자리) */
.vw-ink { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 4; pointer-events: none; }   /* 펜 캔버스 자리 (8c) */
.vw-pg.vw-pg-fail::after { content: '↻'; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font-size: 40px; color: var(--text-muted); z-index: 2; cursor: pointer; }   /* 못 받은 쪽 표시 — 누르면 다시 (부품-#293) */
.vw-nodoc-msg { padding: 48px var(--sp-7); text-align: center; color: var(--text-muted); font-size: var(--fs-lg); }
.vw-nodoc-msg p { margin: 0 0 var(--sp-6); }
.vw-nodoc-msg button { font: inherit; font-size: var(--fs-md); padding: var(--sp-1) var(--sp-4); border: 1px solid var(--border); border-radius: 0; background: var(--card-bg); color: var(--text); cursor: pointer; }
.vw-foot { flex: 0 0 auto; display: flex; align-items: center; gap: var(--sp-4); height: 26px; padding-top: var(--sp-1); min-width: 0; font-size: var(--fs-md); }   /* 배율 글자(.vw-zoomtxt)는 8e 에서 걷었다 — 본보기엔 % 글자가 없다 (P2-15) */
.vw-status { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-muted); }
.vw-title { flex: 0 1 auto; max-width: 60%; font-weight: var(--fw-semi); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 뷰어 [이력] (9e) — 아래 줄 오른쪽 끝 창 이름표 + [이력] 단추(8886 꼴: 흰 바탕 · 테두리 · 굵게 · 높이 22). 누르면 단추 줄 아래로 [첨부파일 이력] 표가 펼쳐진다 —
   그림 칸(.vw-body)이 그만큼 줄고(펼칠 때만 본판이 비켜 밀린다) 접으면 제자리. 표 칸은 판 높이의 40% 까지, 넘치면 표 안에서 스크롤.
   이력 표가 없는 모델이면(.vw-hist-off) 단추 · 이름표는 감추되 자리는 지킨다(visibility). 새 창 전용 보기(.vw-solo)에는 없다. */
.vw-hist-id { flex: 0 0 auto; font-size: var(--fs-xs); color: #aeb4bd; }
.vw-hist-btn { box-sizing: border-box; flex: 0 0 auto; height: var(--h-md); min-height: var(--h-md); padding: 0 var(--sp-6); font: inherit; font-size: var(--fs-md); font-weight: var(--fw-bold); line-height: 20px; border: 1px solid var(--border); border-radius: 0; background: var(--card-bg, var(--c-surface)); color: inherit; cursor: pointer; }
.vw-hist-btn:hover { background: var(--header-bg); }
.vw-hist-btn[aria-pressed="true"] { background: var(--header-bg); border-color: var(--primary); }
.vw-hist-off .vw-hist-btn, .vw-hist-off .vw-hist-id { visibility: hidden; }
.vw-solo .vw-hist-btn, .vw-solo .vw-hist-id, .vw-solo .vw-hist { display: none; }
/* 뷰어 바닥 경계에서 위로 펼쳐져 그림 위에 겹친다(대표님 2026-10-06) — 그림 칸 크기는 그대로(틀 고정). 판 높이는 뷰어의 40% 까지, 넘치면 표 안에서 스크롤 */
.vw-hist { position: absolute; left: 0; right: 0; bottom: 0; z-index: 6; display: flex; flex-direction: column; min-height: 0; max-height: 40%; border-top: 1px solid var(--border); background: var(--card-bg); box-shadow: 0 -3px 10px rgba(0,0,0,.14); }
.vw-hist.hidden { display: none; }
.vw-hist-head { flex: 0 0 auto; display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-1) var(--sp-3); border-bottom: 1px solid var(--border); font-size: var(--fs-md); }
.vw-hist-fold { margin-left: auto; flex: 0 0 auto; width: 22px; height: 20px; padding: 0; border: 1px solid var(--border); border-radius: 0; background: var(--card-bg); cursor: pointer; font-size: var(--fs-sm); line-height: var(--lh-row); }
.vw-hist-note { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-sm); color: var(--text-muted); }
.vw-hist-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.vw-hist-t { margin: 0; }
.vw-hist-t .c-ver { width: 52px; } .vw-hist-t .c-at { width: 112px; } .vw-hist-t .c-who { width: 72px; } .vw-hist-t .c-do { width: 150px; }
.vw-hist-t td.del { text-align: left; }
.vw-hist-f { display: inline-block; margin: 0 var(--sp-1) 0 0; }
.vw-hist-none { color: var(--text-muted); }
/* [보기] 열 (대표님 2026-10-06 공통 규칙) — 파일 칸은 글자만, 맨 끝 열의 [보기] 가 같은 뷰어를 그 판으로 바꾼다. 볼 파일이 없는 판은 회색. 지금 보는 판의 줄은 강조 */
.vw-hist-t .c-view { width: 56px; text-align: center; }
.vw-hist-view { height: 20px; min-height: 20px; padding: 0 var(--sp-4); font-size: var(--fs-sm); line-height: var(--lh-row); }
.vw-hist-view:disabled { opacity: .45; cursor: default; }
.vw-hist-noview { display: inline-block; cursor: not-allowed; }
.vw-hist-t tr.vw-hist-on td { background: #fff3bf; }   /* 줄 강조 — 판 번호는 [보기] 단추의 data-hid */
/* [보기] 띠 — 옛 판을 보는 동안만 그림 위에 겹쳐 뜬다(틀이 안 움직인다) */
.vw-ver { position: absolute; left: 0; right: 0; top: 0; z-index: 5; display: flex; align-items: center; gap: var(--sp-4); box-sizing: border-box; height: 24px; padding: 0 var(--sp-4); background: #ffe066; border-bottom: 1px solid #e0b100; color: #4a3b00; font-size: var(--fs-md); }
.vw-ver.hidden { display: none; }
.vw-ver-txt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--fw-semi); }
.vw-ver-now { flex: 0 0 auto; height: 18px; padding: 0 var(--sp-4); font: inherit; font-size: var(--fs-sm); line-height: 16px; border: 1px solid #b38900; border-radius: 0; background: var(--c-note-bg); color: inherit; cursor: pointer; }
.vw-ver-now:hover { background: var(--c-surface); }
.vw-solo .vw-ver { display: none; }
/* [비교] — 이력 판 머리 단추 + 움직이는 팝업 창(vw_compare). 팝업은 화면에 겹쳐 뜬다(틀 고정) — 머리를 끌어 옮기고 오른쪽 아래 모서리로 크기를 바꾼다 */
.vw-hist-cmp { margin-left: auto; flex: 0 0 auto; height: 20px; padding: 0 var(--sp-5); font: inherit; font-size: var(--fs-sm); line-height: var(--lh-row); border: 1px solid var(--border); border-radius: 0; background: var(--card-bg); color: inherit; cursor: pointer; }
.vw-hist-cmp[aria-pressed="true"] { background: var(--header-bg); border-color: var(--primary); }
.vw-hist-cmp + .vw-hist-fold { margin-left: 0; }
.vw-cmp { position: fixed; z-index: 70; display: flex; flex-direction: column; box-sizing: border-box; background: var(--card-bg); border: 1px solid var(--primary); box-shadow: 0 6px 22px rgba(0,0,0,.28); }
.vw-cmp-bar { flex: 0 0 auto; display: flex; align-items: center; gap: var(--sp-4); height: 24px; padding: 0 var(--sp-3); background: var(--header-bg); border-bottom: 1px solid var(--border); cursor: move; touch-action: none; user-select: none; font-size: var(--fs-md); }
.vw-cmp-id { flex: 0 0 auto; font-size: var(--fs-xs); color: #8a929c; }
.vw-cmp-ver { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--fw-bold); }
.vw-cmp-x { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 18px; padding: 0; border: 1px solid var(--border); border-radius: 0; background: var(--card-bg); color: inherit; cursor: pointer; }
.vw-cmp .vw.vw-cmp-vw { flex: 1 1 auto; height: auto; min-height: 0; padding: var(--sp-2) var(--sp-3); box-sizing: border-box; overflow: hidden; }
.vw-cmp-grip { position: absolute; right: 0; bottom: 0; width: 16px; height: 16px; cursor: nwse-resize; touch-action: none; background: linear-gradient(135deg, transparent 50%, var(--primary) 50%, var(--primary) 58%, transparent 58%, transparent 70%, var(--primary) 70%, var(--primary) 78%, transparent 78%); }
.vw-cmp .vw-exit { display: none; }
.vw-hist-body .empty { margin: var(--sp-3); font-size: var(--fs-md); color: var(--text-muted); }
.vw.vw-full, .vw:fullscreen { width: 100vw; height: 100vh; padding: var(--sp-3) var(--sp-5); box-sizing: border-box; background: var(--card-bg); }   /* 전체화면 (parts.css:829) */
/* 공용 뷰어 8c — 내용검색 · 펜 · 회사서류에 잇기. 본보기 parts.css:322~324(찾기) · 467~493(펜) · 해당 수치 그대로.
   틀이 움직이지 않게: 찾기 결과 폭 고정 · 펜 도구 줄은 꺼져 있어도 자리를 지키고(visibility) · 좁아지면 줄바꿈은 폭으로만 정해진다(상태와 무관). */
.vw-tools { height: auto; min-height: 22px; flex-wrap: wrap; overflow: visible; row-gap: var(--sp-1); }   /* 도구가 늘어 좁은 창에서 끝 단추가 잘렸다 — 잘리는 대신 두 줄로 */
.vw-find-in { flex: 0 0 120px; width: 120px; height: 22px; box-sizing: border-box; font: inherit; font-size: var(--fs-md); padding: 1px var(--sp-2); border: 1px solid var(--border); border-radius: 0; background: var(--card-bg); color: inherit; }   /* 검색 칸 120px (parts.css:323) */
.vw-find-out { flex: 0 0 104px; width: 104px; min-width: 0; font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; }   /* 결과 글자 11px (parts.css:324) · 폭 고정 */
.vw-findhl { position: absolute; background: rgba(255, 213, 0, .45); outline: 1px solid rgba(230, 160, 0, .9); pointer-events: none; z-index: 3; }   /* 찾은 글자 노랑 .45 (parts.css:322) */
.vw-inking .vw-ink { pointer-events: auto; touch-action: none; cursor: crosshair; }   /* 펜이 켜진 동안만 캔버스가 포인터를 받는다 (parts.css:479) */
.vw-inking.vw-erasing .vw-ink { cursor: cell; }
.vw-ink-tools { display: inline-flex; align-items: center; gap: 3px; margin-left: var(--sp-1); visibility: hidden; }   /* 꺼져도 자리 유지 — 켜고 꺼도 도구줄이 안 움직인다 */
.vw-inking .vw-ink-tools { visibility: visible; }
.vw-ink-dot { width: 12px; height: 12px; border-radius: var(--r-round); display: block; }
.vw-tools .vw-ink-color { box-sizing: border-box; width: 22px; height: 22px; min-height: 22px; padding: 0; border-radius: 0; background: transparent; }   /* 색 단추는 22x22 네모 + 안 점 12px 동그라미 — 모서리 0 !important 가 50% 를 이긴다 (parts.css:486 · 1102 · 728) */
.vw-tools .vw-ink-color.vw-on { outline: 2px solid var(--primary); outline-offset: 1px; }
.vw-tools .vw-ink-width { height: 22px; min-height: 22px; padding: 0 var(--sp-2); font-size: var(--fs-sm); font-weight: var(--fw-semi); border-radius: 0; }   /* 굵기 단추 22px · 0 4px · 11px 굵게 · 각짐 (parts.css:489 · 1093~1097) */
.vw-tools .vw-ink-tool-btn { height: var(--h-md); min-height: var(--h-md); padding: 0; border-radius: 0; }   /* 지우개 · 되돌리기 · 지우기 22x22 · 각짐 (parts.css:491) */
.vw-tools .vw-ink-tool-btn > svg { display: block; width: 13px; height: 13px; }                 /* 펜 도구 그림 13px (parts.css:1105) */
.vw-tools .vw-ink-btn.vw-on, .vw-tools .vw-ink-width.vw-on, .vw-tools .vw-ink-tool-btn.vw-on,
.vw-tools .vw-ink-btn.vw-on:hover:not(:disabled), .vw-tools .vw-ink-width.vw-on:hover:not(:disabled), .vw-tools .vw-ink-tool-btn.vw-on:hover:not(:disabled) { background: var(--primary); color: var(--c-on-dark); border-color: var(--primary); }
/* 회사서류 오른쪽 판 — 공용 뷰어를 카드 안에 꽉 채운다 (전체화면은 .vw.vw-full 이 높이를 직접 정해 영향 없다) */
.vw-host { padding: var(--sp-3) var(--sp-4); box-sizing: border-box; }
.vw-host > .vw { --vw-h: 100%; }
/* 공용 뷰어 8e — IPC 뷰어 동일화 (docs/표준컴포넌트-뷰어.md 8절 · data/tasks/ipc_parity_spec.md)
   새 창 전용 보기 .vw-solo (본보기 body.viewer-only, parts.css:924~1002) · 목차 판 [INDEX] (core.js:1429~1586 · parts.css:985~994 · 1113~1143) · PDF 안 쪽 링크 (parts.css:612~613).
   색만 erp2 변수로, 수치(px · ms)는 본보기 그대로. 이 블록의 규칙은 모두 .vw- 로 시작한다. */
.vw-tools > .vw-exit { display: none; }                         /* [닫기] 는 새 창 전용에서만 (parts.css:950 · 1109) — .vw-tools button 의 inline-flex 를 이기려고 두 클래스 */
.vw-slot[data-slot="index"] { display: none; }                  /* 목차 단추는 PC 에서 감춘다 — 왼쪽 손잡이가 대신 (parts.css:1109) */
.vw-linkhot { position: absolute; border: 0; background: transparent; padding: 0; cursor: pointer; border-radius: 0; z-index: 1; box-sizing: border-box; }   /* PDF 안 쪽 링크 (parts.css:612) */
.vw-linkhot:hover { outline: 1px solid var(--primary); }
/* -- 새 창 전용 보기 */
.vw-solo { height: 100vh; height: 100dvh; min-height: 0; padding: var(--sp-2) var(--sp-3); box-sizing: border-box; overflow: hidden; }   /* 창을 가득 · 여백 4px 6px (parts.css:955 · 927) */
.vw-solo.vw-force-mobile { max-width: 420px; margin: 0 auto; }                                                         /* ?mobile=1 — PC 에서 폰 흉내 (parts.css:1053) */
.vw-solo .vw-tools { flex: 0 0 auto; flex-wrap: nowrap; width: 100%; margin: 0; gap: var(--sp-2); height: auto; min-height: 26px; overflow: visible; }   /* 한 줄 얇게 (parts.css:957 · 960) */
.vw-solo .vw-tools > * { display: none; }                                                                              /* 일단 전부 숨기고 아래에서 다시 켠다 (parts.css:963) */
.vw-solo .vw-tools > [data-slot="find"] { order: 0; display: inline-flex; gap: 3px; flex: 1 1 auto; min-width: 0; }     /* 찾기는 맨 앞, 남는 폭은 입력 칸이 다 쓴다 (parts.css:971) */
.vw-solo.vw-has-toc .vw-tools > [data-slot="index"] { order: 1; display: inline-flex; }                                 /* 목차 단추 — 목차가 있는 책만 */
.vw-solo .vw-tools > .vw-page-input { order: 2; display: inline-block; flex: 0 0 40px; width: 40px; height: var(--h-xl); padding: 0 3px; }   /* parts.css:964 · 998 */
.vw-solo .vw-tools > .vw-dim { order: 3; display: inline-block; min-width: 0; }                                        /* "/ N" (parts.css:999 · 931) */
.vw-solo .vw-tools > .vw-full-btn { order: 4; display: inline-flex; }                                                  /* 전체화면 — 그림만 (parts.css:965) */
.vw-solo .vw-tools > [data-slot="ink"] { order: 5; display: inline-flex; }                                             /* 펜 (parts.css:967) — 펜 도구는 켜졌을 때만 바로 뒤에 (order 6) */
.vw-solo .vw-tools > [data-act="rot"] { order: 7; display: inline-flex; }                                              /* 우리가 더한 것 — 대표님이 따로 달라고 한 회전 · 내려받기는 새 창에도 남긴다 (닫기 앞) */
.vw-solo .vw-tools > [data-act="dl"] { order: 8; display: inline-flex; }
.vw-solo .vw-tools > .vw-exit { order: 9; display: inline-flex; }                                                      /* parts.css:1002 */
.vw-solo .vw-tools button { height: var(--h-xl); min-height: var(--h-xl); padding: var(--sp-1) var(--sp-3); font-size: var(--fs-md); line-height: 20px; white-space: nowrap; flex: 0 0 auto; }   /* 단추 26px (parts.css:930 · 958) */
.vw-solo .vw-tools .vw-icon-btn, .vw-solo .vw-tools .vw-full-btn, .vw-solo .vw-tools .vw-index-btn { width: auto; height: var(--h-lg); min-height: var(--h-lg); padding: 0 var(--sp-2); font-size: 0; }   /* 그림 단추 24px 꼴 (parts.css:975) */
.vw-solo .vw-tools .vw-ink-btn { width: 22px; height: var(--h-xl); min-height: var(--h-xl); padding: 0; }                            /* 펜 단추는 본보기에서도 26px 줄 (parts.css:930) */
.vw-solo .vw-find-in { flex: 1 1 50px; width: auto; min-width: 0; height: 26px; padding: 0 var(--sp-2); }                      /* parts.css:971 */
.vw-solo .vw-tools [data-find="go"] { display: none; }                                                                 /* 돋보기는 폰 자판 Enter 가 대신 (parts.css:997) — ▲▼ 는 둘 다 둔다 */
.vw-solo .vw-tools [data-find="prev"], .vw-solo .vw-tools [data-find="next"] { padding: var(--sp-1) 5px; }                      /* parts.css:996 */
.vw-solo .vw-find-out { flex: 0 1 auto; width: auto; max-width: 90px; font-size: var(--fs-xs); }                               /* 결과 10px (parts.css:972) — 폭이 줄면 입력 칸이 흡수한다 */
.vw-solo .vw-ink-tools { display: none; }                                                                              /* 펜 도구는 켜졌을 때만 (parts.css:967 — 본보기는 펜 줄이 켜질 때 늘어난다) */
.vw-solo.vw-inking .vw-ink-tools { display: inline-flex; visibility: visible; }
.vw-solo .vw-fig { scrollbar-width: none; }                                                                            /* 브라우저 스크롤바는 숨김 — 슬라이더가 대신 (parts.css:932) */
.vw-solo .vw-fig::-webkit-scrollbar { display: none; }
.vw-solo .vw-slider { display: block; position: absolute; z-index: 6; width: auto; height: 22px; margin: 0; padding: 0; accent-color: var(--primary); opacity: .75; transform-origin: 0 0; transform: rotate(90deg); touch-action: none; }   /* 그림 오른쪽 가장자리 세로 (parts.css:937) — 자리 · 길이는 viewer.js vslider (core.js:982) */
.vw-solo .vw-foot { flex-direction: column; align-items: stretch; gap: 0; height: auto; padding-top: 0; }               /* 제목 · 안내줄은 각자 한 줄 (parts.css:961 · 962) */
.vw-solo .vw-title { order: 3; max-width: none; margin-top: 3px; line-height: 1.3; }
.vw-solo .vw-status { order: 4; flex: 0 0 auto; margin: var(--sp-1) 0 0; line-height: 1.3; white-space: normal; max-height: 2.6em; }
/* -- 목차 판 [INDEX] — PC 는 왼쪽 드로어(본문을 안 밀고 덮음), 새 창 · 폰은 아래 판 (.vw-sheet) */
.vw-index-panel { position: fixed; right: 18px; top: 120px; bottom: 18px; width: 330px; max-width: calc(100% - 28px); z-index: 30; display: flex; flex-direction: column; box-sizing: border-box; overflow: hidden; font-size: var(--fs-md); color: var(--text);
  background: rgba(255, 255, 255, .84); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); border: 1px solid var(--border); border-radius: 0; box-shadow: 2px 2px 0 rgba(0, 0, 0, .10);
  opacity: 0; transform: translateX(-6px); transition: opacity .12s linear, transform .12s linear; }   /* 열기 .12s · 반투명 .84 + blur 3px (parts.css:1113~1135) — 자리 · 폭은 JS 가 고정 */
.vw-index-panel.vw-hide { display: none; }
.vw-index-panel.is-open { opacity: 1; transform: none; }
.vw-index-panel.vw-sheet { left: 0; right: 0; top: auto; bottom: 0; width: auto; max-width: none; z-index: 50; max-height: 60vh; max-height: 60dvh; font-size: var(--fs-xl); transform: translateY(10px); }   /* 아래 판 (parts.css:994 · 1117) */
.vw-index-panel.vw-sheet.is-open { transform: none; }
.vw-solo.vw-force-mobile .vw-index-panel.vw-sheet { left: 50%; right: auto; width: 420px; transform: translateX(-50%) translateY(10px); }
.vw-solo.vw-force-mobile .vw-index-panel.vw-sheet.is-open { transform: translateX(-50%); }
.vw-index-head { flex: 0 0 auto; display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-2) var(--sp-4); background: rgba(240, 243, 246, .86); border-bottom: 1px solid var(--border); }   /* parts.css:1134 · 1143 */
.vw-index-panel.vw-sheet .vw-index-head { padding: 5px var(--sp-4); }
.vw-index-head > b { font-family: var(--font-mono); font-size: var(--fs-md); letter-spacing: 1px; }                          /* parts.css:1136 */
.vw-index-sub { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-md); color: var(--text-muted); }
.vw-index-x { font: inherit; font-size: var(--fs-2xl); line-height: 1; padding: 0 var(--sp-4); background: transparent; border: 0; color: inherit; cursor: pointer; }   /* parts.css:1137 */
.vw-index-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: var(--sp-1) var(--sp-4) var(--sp-4); background: transparent; -webkit-overflow-scrolling: touch; }
.vw-index-panel.vw-sheet .vw-index-body { padding: var(--sp-2) var(--sp-5) var(--sp-5); }
.vw-toc-node > summary { cursor: pointer; padding: 1px 0; font-weight: var(--fw-semi); list-style: none; line-height: 1.35; }     /* 장 묶음 (parts.css:413~415 · 1143) */
.vw-toc-node > summary::-webkit-details-marker { display: none; }
.vw-toc-node > summary::before { content: '▸'; display: inline-block; width: 14px; color: var(--text-muted); }
.vw-toc-node[open] > summary::before { content: '▾'; }
.vw-toc-children { margin-left: var(--sp-4); }
.vw-toc-sec { padding: 1px var(--sp-2); line-height: 1.35; cursor: pointer; border-radius: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* 절 줄 (parts.css:450 · 1142) */
.vw-toc-sec:hover, .vw-toc-node > summary:hover { background: var(--header-bg); }
.vw-toc-sec.vw-on, .vw-toc-node > summary.vw-on { background: var(--primary); color: var(--c-on-dark); }                          /* 지금 절 (parts.css:452) */
.vw-index-panel.vw-sheet .vw-toc-sec { padding: 7px var(--sp-3); white-space: normal; line-height: normal; }                    /* 손가락으로 누르는 판은 줄을 키운다 (parts.css:991 · 992) */
.vw-index-panel.vw-sheet .vw-toc-node > summary { padding: 7px 0; line-height: normal; }
.vw-index-grip { position: fixed; z-index: 32; width: 16px; height: 44px; padding: 0; box-sizing: border-box; display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(70, 80, 92, .45); border-left: 0; border-radius: 0; background: rgba(255, 255, 255, .92); box-shadow: 1px 1px 0 rgba(0, 0, 0, .10);
  color: #39424e; cursor: pointer; transition: left .12s linear, color .12s linear, background .12s linear; }   /* 왼쪽 손잡이 16x44 (parts.css:1122~1129) */
.vw-index-grip:hover { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }
.vw-index-grip svg { display: block; transition: transform .12s linear; }
.vw-index-grip.vw-on svg { transform: rotate(180deg); }                                                                /* 펼쳐져 있으면 < (접기) */
.vw-index-grip.vw-hide { display: none; }
.vw-tools .vw-index-btn.vw-on, .vw-tools .vw-index-btn.vw-on:hover:not(:disabled) { background: var(--primary); color: var(--c-on-dark); border-color: var(--primary); }   /* 목차가 열려 있는 동안 단추 파랑 (parts.css:1119) */
/* ── 차량정보 (company vehicles) — 표준 칸 틀 (.ex3-*): 왼쪽 620px 목록 / 오른쪽 뷰어 ── */
.veh-page { display: flex; flex-direction: column; height: calc(100vh - 86px); min-height: 420px; }
.veh-page > .ex3-wrap { flex: 1 1 0; height: auto; min-height: 0; }
.veh-wrap { height: calc(100vh - 120px); overflow-x: hidden; }
.veh-pane-list { flex: 0 0 620px; width: 620px; display: flex; flex-direction: column; gap: var(--sp-4); min-height: 0; padding: 0; background: none; border: none; overflow: hidden; box-sizing: border-box; }
.veh-pane-list > .ex3-head { position: static; height: 14px; }
.veh-list-pane { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--r-2); }
.veh-list-pane > .ex3-head { position: static; height: 14px; }
.veh-pane-view { flex: 1 1 auto; min-width: 0; padding: var(--sp-2) var(--sp-3); overflow-y: auto; overflow-x: hidden; display: block; box-sizing: border-box; background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--r-2); }
@media (max-width: 768px) {
  .veh-page { height: auto; }
  .veh-wrap { height: auto; }
  .veh-pane-list { flex: none; width: auto; }
  .veh-pane-view { display: block; flex: none; }
}
.veh-find { position: relative; display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-2); }
.veh-title { margin: 0; font-size: var(--fs-2xl); white-space: nowrap; }
.veh-count { color: var(--text-muted); font-size: var(--fs-md); white-space: nowrap; }
.veh-search { flex: 0 1 420px; width: 420px; min-width: 0; margin: 0; }
.veh-search .search-input { width: 100%; max-width: none; }
.veh-find .spacer { flex: 1 1 auto; }
.veh-find .fn-list { right: 0; left: auto; }
.veh-filter-box { position: absolute; top: 100%; left: 0; right: auto; width: min(520px, 100%); z-index: 30; box-shadow: 0 2px 8px var(--border); }
.veh-grid, .veh-logs { width: 100%; table-layout: fixed; border-collapse: collapse; font-size: var(--fs-md); }
.veh-grid th, .veh-grid td, .veh-logs th, .veh-logs td { height: 25px; padding: 0 var(--sp-3); text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-bottom: 1px solid var(--border); box-sizing: border-box; }
.veh-grid thead th, .veh-logs thead th { background: var(--header-bg); color: var(--text-muted); font-weight: var(--fw-semi); font-size: var(--fs-sm); position: sticky; top: 0; z-index: 2; }
.veh-row, .veh-logrow { cursor: pointer; }
.veh-row:hover td, .veh-logrow:hover td { background: var(--header-bg); }
.veh-row.on td { background: var(--c-selected); }
.veh-row.is-off td { color: var(--text-muted); text-decoration: line-through; }
.veh-plate-link { color: var(--c-link); text-decoration: none; }
.veh-grid td.veh-due-soon, .kv-grid .veh-due-soon { background: #ffe3b3; color: var(--c-warn); font-weight: var(--fw-semi); }   /* 오늘부터 30일 안 — 주황 */
.veh-grid td.veh-due-over, .kv-grid .veh-due-over { background: var(--c-danger-bg); color: var(--c-danger); font-weight: var(--fw-semi); }   /* 지났음 — 빨강 */
.veh-date { padding: 0 var(--sp-2); }
.veh-empty { color: var(--text-muted); text-align: center !important; }
.veh-foot { display: flex; align-items: center; gap: var(--sp-3); padding-top: var(--sp-3); }
.veh-btn-off { display: inline-flex; align-items: center; background: var(--c-line); color: var(--c-text-3); border: 1px solid var(--c-line); cursor: not-allowed; }
.veh-card { background: transparent; border: none; border-radius: 0; padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-4); }
.veh-h { font-size: var(--fs-lg); }
.veh-off { flex: none; color: var(--c-danger); border: 1px solid var(--c-danger); font-size: var(--fs-sm); padding: 0 var(--sp-2); }
.veh-inline { display: inline-flex; margin: 0; }
.veh-ask { height: 16px; margin-bottom: var(--sp-2); font-size: var(--fs-sm); color: var(--c-danger); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kv-f > .veh-memo { white-space: pre-wrap; max-height: 4.5em; overflow-y: auto; }
.veh-att { display: flex; align-items: center; gap: var(--sp-3); min-height: 28px; padding: var(--sp-1) 0; border-top: 1px solid var(--border); }
.veh-att-label { flex: none; width: 76px; white-space: nowrap; text-align: right; font-size: var(--fs-md); color: var(--text-muted); }
.veh-att-files { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-1); max-height: 68px; overflow-y: auto; font-size: var(--fs-md); }
.veh-file { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.veh-file-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--c-link); text-decoration: none; }
.veh-file-name:hover { text-decoration: underline; }
.veh-up { flex: 0 0 150px; margin: 0; display: flex; }
.veh-up .dropzone { height: 22px; }
.veh-view.vw-host > .vw { --vw-h: calc(88vh - 90px); }
.veh-win .field-row textarea { flex: 1; min-width: 0; }
.veh-win .veh-hint { margin: var(--sp-3) 0 0; }
.veh-ins-failed { background: #fff0f3; }
.veh-ins-note { display: block; color: #b45b00; white-space: normal; }
#veh-ins-card .dropzone { flex: 1; }
#veh-ins-card td { white-space: normal; }
/* 회사서류 9단계 — 서류 [삭제] 자리(고정 폭이라 "삭제" ↔ "한 번 더" 로 글자가 바뀌어도 줄이 안 움직인다) · 지운 줄 · 기준일 hover 이력 팝업(겹쳐 띄움) */
.cdoc-row .cdoc-del, .cdoc-colhead .cdoc-del { box-sizing: border-box; display: inline-block; width: 50px; flex: none; }
.cdoc-row button.cdoc-del { height: var(--h-sm); min-height: var(--h-sm); padding: 0; font-size: var(--fs-sm); line-height: var(--lh-row); text-align: center; white-space: nowrap; }
.cdoc-row .cdoc-flaggap { width: 40px; flex: none; } .cdoc-row .cdoc-pickgap { width: 13px; flex: none; } .cdoc-row .cdoc-renamegap { width: 16px; flex: none; }
.cdoc-row.is-deleted .cdoc-name, .cdoc-row.is-deleted .cdoc-ext, .cdoc-row.is-deleted .cdoc-date { color: var(--c-text-3); text-decoration: line-through; cursor: default; }
.cdoc-row.is-deleted .cdoc-date { text-decoration: none; opacity: .6; }
.cdoc-hpop { position: fixed; z-index: 2500; max-width: 420px; padding: var(--sp-2) var(--sp-3); background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--r-3); box-shadow: 0 2px 10px rgba(0,0,0,.18); font-size: var(--fs-sm); pointer-events: none; }
.cdoc-hpop[hidden] { display: none; }
.cdoc-hpop-row { display: flex; gap: var(--sp-3); padding: 1px 0; white-space: nowrap; } .cdoc-hpop-row .hv { color: var(--text-muted); width: 34px; flex: none; } .cdoc-hpop-row .hchg { color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; }

/* ---------------- LLM adapter 화면 (master › configuration ▸ [LLM adapter], 지시문 12a) ----------------
   읽기 화면 = 엔진 표 · 일 표 · 공통 머리말(읽기 전용). 줄을 누르면 창(엔진 · 일). 틀이 안 움직이게 — 시험 결과 줄은 자리를 잡아 둔다. */
.llm-page { padding: var(--sp-1) 0; }
.llm-page .hint { margin: 0 0 var(--sp-2); font-size: var(--fs-md); color: var(--text-muted); }
.llm-h { margin: var(--sp-4) 0 3px; font-size: var(--fs-md); font-weight: var(--fw-semi); }
.llm-note { margin-left: var(--sp-3); font-size: var(--fs-sm); font-weight: var(--fw-normal); color: var(--text-muted); }
.llm-grid { margin-bottom: var(--sp-2); }
.llm-dim { color: var(--text-muted); }
.llm-cap.off { color: var(--text-muted); text-decoration: line-through; }
.llm-st { font-weight: var(--fw-semi); }
.llm-st-ok { color: var(--c-ok); }
.llm-st-rest { color: #b7791f; }
.llm-st-stopped, .llm-st-down { color: var(--danger); }
.llm-st-off { color: var(--text-muted); font-weight: var(--fw-normal); }
.llm-pre { margin: 0; max-height: 220px; overflow: auto; padding: var(--sp-3) var(--sp-4); font: 11px/1.45 var(--font-mono);
           white-space: pre-wrap; word-break: break-all; background: var(--header-bg); border: 1px solid var(--border); border-radius: var(--r-2); }
.llm-win { width: 620px; }
.llm-win .llm-h { margin: var(--sp-3) 0 3px; padding-top: var(--sp-2); border-top: 1px solid var(--border); }
.llm-win .llm-wrap { margin: 0 0 var(--sp-2); line-height: 1.4; }
.llm-sub { margin: var(--sp-4) 0 var(--sp-1); font-size: var(--fs-sm); color: var(--text-muted); font-weight: var(--fw-semi); }
.modal.window .field-row input.llm-check { flex: none; width: auto; height: auto; min-height: 0; padding: 0; margin: 0; }
.modal.window .field-row input.llm-num { flex: none; width: 80px; }
.modal.window .field-row label.llm-inl { width: auto; text-align: left; display: inline-flex; align-items: center; gap: 3px; color: var(--text); }
.modal.window .field-row textarea.llm-note-box { flex: 1; min-width: 0; padding: var(--sp-2) var(--sp-3); font: 12px/1.4 inherit; border: 1px solid var(--border); border-radius: var(--r-1); resize: vertical; }
.llm-why { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-sm); color: var(--text-muted); }
.llm-testline { display: inline-block; min-width: 260px; min-height: 18px; font-size: var(--fs-md); }
.llm-testline.ok { color: var(--c-ok); }
.llm-testline.bad { color: var(--danger); }
table.hist.llm-calls tr.llm-fail td { color: var(--danger); }
table.hist.llm-calls td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 12b — 연결 추가 · 사용중지 · 일 묶음 · 쓸 연결 고르기 */
.llm-h .llm-add { margin-left: var(--sp-4); }
.llm-toggle { float: right; }
.llm-empty { margin: var(--sp-1) 0 var(--sp-3); padding: var(--sp-3) var(--sp-4); font-size: var(--fs-md); border: 1px dashed var(--border); color: var(--text-muted); }
.llm-bad { color: var(--danger); }
.llm-st-removed { color: var(--text-muted); font-weight: var(--fw-normal); }
.llm-grid tr.llm-group th { padding: var(--sp-1) var(--sp-3); font-size: var(--fs-sm); text-align: left; background: var(--header-bg); border-top: 2px solid var(--border); }
.llm-grid tr.llm-pending td { color: var(--text-muted); background: var(--c-page); font-style: italic; }
.llm-pick td { padding: 1px var(--sp-2); }
.llm-pick tr.llm-lack td { color: var(--text-muted); background: var(--c-page); }
.modal.window .field-row input.llm-ord { width: 52px; }
.llm-mask { flex: none; margin-right: var(--sp-3); font-family: var(--font-mono); }
.llm-cmd { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: var(--sp-1) var(--sp-3); font: 11px/1.5 var(--font-mono); background: var(--header-bg); border: 1px solid var(--border); border-radius: var(--r-1); }
.llm-kinds { display: flex; gap: var(--sp-1); padding: var(--sp-2) var(--sp-5) 0; border-bottom: 1px solid var(--border); }
.llm-kind { padding: 3px var(--sp-5); font-size: var(--fs-md); border: 1px solid var(--border); border-bottom: 0; border-radius: 3px 3px 0 0; color: var(--text); text-decoration: none; background: var(--header-bg); }
.llm-kind.on { background: var(--bg, var(--c-surface)); font-weight: var(--fw-semi); margin-bottom: -1px; padding-bottom: var(--sp-2); }
.llm-kind.off { color: var(--text-muted); text-decoration: line-through; cursor: not-allowed; }
.llm-kind.off small { text-decoration: none; display: inline-block; font-size: var(--fs-xs); }
/* 12e — 세 구역 한 장 · 연결 창 네 칸 · 일 창 두 칸. 틀이 안 움직이게 안내 칸은 자리를 잡아 둔다 */
.llm-main { color: var(--c-ok); font-weight: var(--fw-semi); }
.llm-warn { color: #b7791f; }
.llm-st-login { color: #b7791f; }
.llm-win .llm-step { margin: var(--sp-4) 0 3px; padding-top: var(--sp-2); border-top: 2px solid var(--border); }
.llm-win .llm-step:first-child { margin-top: 0; border-top: 0; }
.llm-mon td, .llm-recent td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.llm-duty.off { color: var(--text-muted); }
.llm-recent tr.llm-fail td { color: var(--danger); }
.llm-head-row { display: flex; align-items: center; gap: var(--sp-3); margin: var(--sp-1) 0; }
.llm-pre-head { max-height: 70px; margin-bottom: var(--sp-2); }
.llm-jobline { display: inline-block; min-width: 180px; min-height: 18px; font-size: var(--fs-md); color: var(--text-muted); }
.llm-jobline.ok { color: var(--c-ok); }
.llm-jobline.bad { color: var(--danger); }
.llm-loginbox { min-height: 38px; margin: var(--sp-1) 0 var(--sp-2) 82px; padding: 3px var(--sp-3); font-size: var(--fs-md); border: 1px dashed var(--border); min-width: 0; overflow-wrap: anywhere; }
.llm-loginbox span { display: block; min-width: 0; overflow-wrap: anywhere; }
#llmLogin { white-space: nowrap; flex: none; }
.llm-loginbox .llm-login-paste { display: flex; gap: var(--sp-2); margin-top: var(--sp-1); min-width: 0; overflow-wrap: anywhere; }
.llm-login-paste input { flex: 1; min-width: 0; font: 12px var(--font-mono); }
.llm-login-code b { font: 600 16px/1.4 var(--font-mono); letter-spacing: 2px; }
.llm-models td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 1px var(--sp-2); }
.llm-models tr.llm-lack td { color: var(--text-muted); background: var(--c-page); }
.llm-routes select, .llm-pick select { width: 100%; font-size: var(--fs-md); }
.llm-area { width: 100%; box-sizing: border-box; padding: var(--sp-2) var(--sp-3); font: 12px/1.4 inherit; border: 1px solid var(--border); border-radius: var(--r-1); resize: vertical; }
.llm-area.llm-mono { font: 11px/1.45 var(--font-mono); }
.llm-saverow { margin-top: 3px; }
.llm-reco td { padding: 1px var(--sp-2); vertical-align: top; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.llm-reco-mode { margin: 0 0 3px; font-size: var(--fs-md); }
.llm-reco-mode.rule { color: #b7791f; }
.llm-excluded { margin: 0 0 var(--sp-2) var(--sp-7); padding: 0; font-size: var(--fs-sm); color: var(--text-muted); }
.llm-evidence { margin: 0 0 var(--sp-2) var(--sp-7); padding: 0; font-size: var(--fs-sm); color: var(--text-muted); }
.llm-tag-official { display: inline-block; padding: 0 var(--sp-2); font-size: var(--fs-sm); background: #dafbe1; color: var(--c-ok); border-radius: var(--r-1); margin-left: var(--sp-1); }
.llm-tag-ref { display: inline-block; padding: 0 var(--sp-2); font-size: var(--fs-sm); background: var(--c-sunken); color: var(--text-muted); border-radius: var(--r-1); margin-left: var(--sp-1); }
.llm-reco-win { width: 760px; }
/* 차량정보 뷰 */
.veh-chips { display: flex; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.veh-chip { box-sizing: border-box; height: var(--h-sm); line-height: var(--lh-row); padding: 0 var(--sp-5); border: 1px solid var(--border); border-radius: 3px; color: var(--text-muted); text-decoration: none; font-size: var(--fs-md); display: inline-flex; align-items: center; }
.veh-chip.on { background: var(--c-link); color: var(--c-on-dark); border-color: var(--c-link); font-weight: var(--fw-semi); }
.veh-openwin { border: 1px solid var(--c-line-strong); border-radius: 0; box-shadow: 2px 2px 0 rgba(15, 23, 42, .18); background: var(--card-bg); flex: 0 1 auto; max-height: 50%; min-height: 0; overflow: hidden; display: flex; flex-direction: column; margin-bottom: 0; }
.veh-openwin > .modal-header h2 { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; white-space: nowrap; }
.veh-openwin > .modal-header .win-id { flex: none; }
.veh-openwin > .modal-header-actions { flex: none; }
.veh-title-sub { font-size: var(--fs-sm); font-weight: normal; color: var(--c-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.veh-badge { display: inline-flex; align-items: center; height: 18px; padding: 0 var(--sp-3); border-radius: 3px; font-size: var(--fs-sm); font-weight: var(--fw-semi); flex: none; }
.veh-badge.veh-due-soon { background: var(--c-warn); color: var(--c-on-dark); }
.veh-badge.veh-due-over { background: var(--c-danger); color: var(--c-on-dark); }
span.veh-date { display: inline-block; padding: 0 var(--sp-2); border-radius: var(--r-1); line-height: var(--lh-row); }
.veh-date.veh-due-soon { background: #ffe3b3; color: var(--c-warn); font-weight: var(--fw-semi); }
.veh-date.veh-due-over { background: var(--c-danger-bg); color: var(--c-danger); font-weight: var(--fw-semi); }
.veh-openwin-body, .veh-tree-body { padding: 0; display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden; min-height: 0; }
.veh-cat { border-bottom: 1px solid var(--border); }
.veh-cat-row { box-sizing: border-box; height: 22px; line-height: 22px; display: flex; align-items: center; padding: 0 var(--sp-4); font-size: var(--fs-md); color: var(--text); text-decoration: none; cursor: pointer; user-select: none; }
.veh-cat-row:hover { background: var(--header-bg); }
.veh-cat-summary { margin-left: auto; font-size: var(--fs-sm); color: var(--text-muted); font-weight: normal; }
.veh-cat-body { padding: 0; display: flex; flex-direction: column; }
.veh-tree-row { box-sizing: border-box; height: 22px; line-height: 22px; display: flex; align-items: center; padding: 0 var(--sp-4) 0 var(--sp-9); font-size: var(--fs-md); cursor: pointer; text-decoration: none; color: inherit; white-space: nowrap; overflow: hidden; }
.veh-tree-row:hover { background: var(--header-bg); }
.veh-tree-row.on { background: var(--c-selected); color: var(--c-link); }
.veh-slip-no { font-family: var(--font-mono); font-size: 11.5px; color: var(--c-link); text-decoration: none; flex: none; font-weight: var(--fw-semi); }
.veh-slip-sep { margin: 0 var(--sp-2); color: var(--text-muted); flex: none; }
.veh-slip-date { flex: none; }
.veh-slip-desc { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.veh-slip-amt { flex: none; margin-left: auto; text-align: right; font-variant-numeric: tabular-nums; }
.veh-form-gear { margin-left: auto; color: #888; font-size: var(--fs-2xl); text-decoration: none; }
.veh-slip-row { height: 24px; line-height: 24px; padding: 0 var(--sp-4) 0 var(--sp-3); gap: 0; }
.veh-slip-row > .veh-slip-created { flex: 0 0 16%; min-width: 0; color: inherit; text-decoration: none; }
.veh-slip-values { display: flex; flex: 1 1 0; min-width: 0; overflow: hidden; }
.veh-slip-values > span { flex: none; min-width: 0; box-sizing: border-box; padding: 0 var(--sp-2); }
.veh-slip-row > .veh-slip-amount { flex: 0 0 17%; min-width: 0; text-align: right; }
.veh-slip-created, .veh-slip-values > span, .veh-slip-amount { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.veh-openwin > .modal-header { position: relative; }
.veh-openwin > .modal-header .win-id { position: absolute; left: 50%; transform: translateX(-50%); }
.veh-ins-actions { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-1) var(--sp-4) var(--sp-1) var(--sp-9); height: 24px; box-sizing: border-box; }
.veh-ins-actions .btn { height: var(--h-sm); line-height: var(--lh-row); padding: 0 var(--sp-4); flex: none; }
.veh-ins-up { flex: 1 1 auto; min-width: 0; margin: 0; display: flex; }
.veh-cat.drop-files { outline: 2px solid var(--primary); outline-offset: -2px; background: var(--c-hover); }
.veh-upload-hint { margin-left: var(--sp-6); font-size: var(--fs-sm); color: var(--primary); }
.veh-tree-foot { display: flex; align-items: center; height: 24px; padding: var(--sp-1) var(--sp-4) var(--sp-1) var(--sp-9); box-sizing: border-box; }
.veh-tree-foot .btn { height: var(--h-sm); line-height: var(--lh-row); padding: 0 var(--sp-4); }
.veh-empty-hint { height: 22px; display: flex; align-items: center; padding-left: var(--sp-3); font-size: var(--fs-md); color: var(--text-muted); }
.veh-group-row td { padding: 0 !important; background: var(--card-bg); }
.veh-group-slips { padding: 0; border-bottom: 1px solid var(--border); }
.veh-nothing { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; color: #888; }
.veh-logcard { margin-top: 0; }
.veh-past { opacity: 0.55; }
.llm-step-dim { opacity: 0.55; }
.llm-step-dim input, .llm-step-dim textarea, .llm-step-dim button, .llm-step-dim select, .llm-step-dim table { pointer-events: none; }
.llm-kind.locked { pointer-events: none; opacity: 0.6; cursor: not-allowed; }
.llm-models-sm { font-size: var(--fs-sm); margin: 3px 0; }
.llm-models-sm th, .llm-models-sm td { padding: var(--sp-1) var(--sp-2); }
/* 14-7 — 오토파일럿 config */
.llm-ap-levels td, .llm-ap-runs td, .llm-ap-applied td { padding: 1px var(--sp-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.llm-ap-levels select { width: 100%; font-size: var(--fs-md); }
.llm-job { white-space: nowrap; flex: none; }
/* 14-7 — 기능별 LLM 토큰 사용량 */
.llm-usage td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.llm-usage td:nth-child(4), .llm-usage td:nth-child(5), .llm-usage td:nth-child(6), .llm-usage td:nth-child(7), .llm-usage td:nth-child(8), .llm-usage td:nth-child(9), .llm-usage td:nth-child(10) { text-align: right; }
.llm-usage-row td { color: #888; font-size: var(--fs-sm); }
.llm-usage-row td.llm-usage-sub { padding-left: 14px; }
.llm-usage-row td.llm-usage-text, .llm-total-row th.llm-usage-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }
.llm-total-row th { background: var(--header-bg); border-top: 2px solid var(--border); font-weight: var(--fw-semi); }
.llm-total-row th.llm-usage-text { font-weight: normal; }
.llm-tabs { display: inline-flex; gap: var(--sp-2); }



.hist-panel table.hist { font-size: var(--fs-sm); }
.hist-panel table.hist .h-rev { width: 11%; } .hist-panel table.hist .h-at { width: 25%; }
.hist-panel table.hist .h-who { width: 13%; } .hist-panel table.hist .h-act { width: 14%; }
.hist-panel table.hist .h-chg { width: 25%; } .hist-panel table.hist .h-see { width: 12%; }
.hist-panel table.hist td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hist-panel table.hist td.del { text-align: center; padding: 1px var(--sp-1); }
.hist-panel table.hist tr.gone td { color: var(--text-muted); text-decoration: line-through; }
.hist-panel table.hist tr.on td { background: var(--c-selected); }
.btn.btn-sm { display: inline-flex; align-items: center; height: var(--h-xs); padding: 0 var(--sp-3); font-size: var(--fs-sm);
              text-decoration: none; color: var(--text); background: var(--header-bg); border: 1px solid var(--border); }
.btn.on { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }
.btn[data-hist-toggle].active { background: var(--primary); border-color: var(--primary); color: var(--c-on-dark); }   /* [로그]·[이력] 펼침 중 (대표님 2026-10-07) */
/* [보기] 중 — 위 노란 띠 한 줄, 지금과 다른 칸은 옅은 노랑 + "(지금: …)" */
/* 글(`.hist-viewing-text`)만 말줄임하고 [지금으로] 는 오른쪽에 늘 보인다(대표님 8118) */
.hist-viewing { display: flex; align-items: center; gap: var(--sp-3); margin: -2px 0 8px; padding: 3px var(--sp-4); font-size: var(--fs-md);
                background: var(--c-note-bg); border: 1px solid #ecd98a; }
.hist-viewing-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hist-viewing .btn { flex: 0 0 auto; }
.field-row.hist-diff input, .field-row.hist-diff select, .field-row.hist-diff textarea { background: #fff7c2; }
.hist-now { flex: 0 1 auto; font-size: var(--fs-sm); color: #8a6d00; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40%; }
.hist-line { font-size: var(--fs-md); line-height: 20px; }
.hist-line.gone { color: var(--text-muted); text-decoration: line-through; }

/* [이력] 곁판 아래에 새 블록 */
/* ---------------- 첨부 줄 ---------------- */
.file-row .file-dl {
  visibility: hidden;
  margin-left: var(--sp-2);
}
.file-row.show-dl .file-dl {
  visibility: visible;
}
.file-row.is-lost .file-name { color: var(--text-muted); }

.shot-pop {
  position: fixed;
  z-index: 9999;
  background: var(--c-surface);
  border: 1px solid var(--border);
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  pointer-events: none;
}
.shot-pop img {
  display: block;
  max-width: 420px;
  max-height: 420px;
  object-fit: contain;
}
.shot-pop[hidden] {
  display: none;
}

/* [이력] 비교 — 창 테두리/그림자/24px 머리는 .modal.window 와 같은 값, 모서리는 vw_compare 그대로. */
.hist-panel .hist-head button[data-act="snapcmp"] { height: var(--h-sm); min-height: var(--h-sm); }
.snap-cmp { position: fixed; z-index: 9998; display: flex; flex-direction: column; box-sizing: border-box;
  max-width: 100vw; max-height: 100vh; background: var(--card-bg); border: 1px solid var(--c-line-strong);
  border-radius: 0; box-shadow: 3px 3px 0 rgba(15, 23, 42, .18); }
.snap-cmp-bar { flex: 0 0 auto; display: flex; align-items: center; gap: var(--sp-4); height: 24px;
  padding: 0 var(--sp-2) 0 var(--sp-4); background: var(--c-dark); color: #e6e9ee; border-bottom: 1px solid var(--c-line-strong);
  cursor: move; touch-action: none; user-select: none; font-size: var(--fs-md); }
.snap-cmp-bar .win-id { display: inline; flex: 0 0 auto; margin: 0; }
.snap-cmp-ver { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.snap-cmp-x { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  height: 20px; min-width: 20px; padding: 0 var(--sp-2); border: 0; border-radius: 0; background: transparent;
  color: inherit; cursor: pointer; font-size: var(--fs-md); line-height: 1; }
.snap-cmp-x:hover { background: #3a4250; }
.snap-cmp-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.snap-cmp-body > .modal-body { padding: var(--sp-5) var(--sp-6); }
.snap-cmp .field-row { gap: var(--sp-3); margin-bottom: var(--sp-2); }
.snap-cmp .field-row label { width: 92px; font-size: var(--fs-md); }
.snap-cmp .field-row .acct-item label { width: auto; flex: 0 0 auto; text-align: left; }
.snap-cmp .field-row input, .snap-cmp .kind-pick span, .snap-cmp .btn {
  box-sizing: border-box; height: var(--h-md); min-height: var(--h-md); padding: 0 var(--sp-3); font-size: var(--fs-md);
  line-height: 20px; border-radius: var(--r-1); }
.snap-cmp-grip { position: absolute; right: 0; bottom: 0; width: 16px; height: 16px;
  cursor: nwse-resize; touch-action: none;
  background: linear-gradient(135deg, transparent 50%, var(--primary) 50%, var(--primary) 58%, transparent 58%,
    transparent 70%, var(--primary) 70%, var(--primary) 78%, transparent 78%); }
.shot-pop { z-index: 9999; }
/* 크게 보기 머리 줄 — 창 머리와 같은 어두운 줄(흰 ✕ 가 흰 바탕에 묻히던 것, 대표님 2026-10-07) */
.lightbox .bar {
  background: var(--c-dark);
  color: #e6e9ee;
  border-bottom: 1px solid var(--c-line-strong);
  height: 24px;
  box-sizing: border-box;
}
.lightbox .bar .titlebar-close {
  height: 18px;
  min-width: 18px;
  padding: 0 var(--sp-2);
  border-radius: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-md);
  line-height: 1;
}
.lightbox .bar .titlebar-close:hover {
  background: #3a4250;
}



/* ---------------- 창과 곁판 (설계_곁판_한자리 2-4 · 조각 7, 2026-10-07) ----------------
   창 상태 클래스(has-panel · picking · with-shot · with-rev)는 걷고 곁판 자리(#winSide)의
   내용(:has)에서 폭과 곁판 상태를 파생한다. 양식설정 창의 has-panel 은 그대로 유지한다. */
:root { --win-main: 638px; --win-side: 542px; }

@media (min-width: 701px) {
  .modal.window:has(#winSide:not([hidden])) { width: min(98vw, calc(var(--win-main) + var(--win-side) + 2px)); }
  .modal.window:has(#winSide > .link-pick-side, #winSide.link-pick-side) { --win-side: 922px; }
  .modal.window:has(#winSide > .cert-shot) { --win-side: 562px; height: min(94vh, 920px); }
  .modal.window:has(#winSide > .hist-panel) { --win-side: 562px; }
  .modal.window:has(> form > .win-split > #winSide) .win-split > .win-main { flex: 0 0 var(--win-main); width: var(--win-main); }
  /* 창은 왼쪽 끝 고정 — 처음은 가운데(계산값), 끌면 --win-left · --win-top (설계_곁판_한자리 조각 6, 2026-10-07) */
  .modal.window:has(> form > .win-split) { transform: none;
    left: var(--win-left, calc(50% - var(--win-main) / 2 - 1px)); top: var(--win-top, 20px); }
  .modal.window .win-split > .win-side { display: flex; flex-direction: column; min-width: 0; min-height: 0; flex: 1 1 auto; }
  .win-side > .win-panel, .win-side > .hist-panel { flex: 1 1 auto; min-height: 0; overflow: hidden; }
  .win-side > .hist-panel { overflow-y: auto; overflow-x: hidden; padding: var(--sp-3) var(--sp-4); background: var(--card-bg); }
  .win-side .panel-body { min-height: 0; }
  .win-side > .panel-head .side-shut, .win-side > * > .panel-head .side-shut {
    font-family: inherit; font-size: var(--fs-lg); line-height: 1; color: var(--text-muted); background: none; border: 0; cursor: pointer;
    height: 18px; min-width: 18px; padding: 0 var(--sp-2); display: inline-flex; align-items: center; justify-content: center;
    text-decoration: none;
  }
  .win-side > .panel-head .side-shut:hover, .win-side > * > .panel-head .side-shut:hover { color: var(--danger); background: none; }
}
.grid tr.is-canceled td { text-decoration: line-through; }
/* ---------------- 필드값 공동규정 칸 폭 (설계서 1-3) ---------------- */
.box-biz { width: 13ch; }
.box-corp { width: 15ch; }
.box-tel { width: 14ch; }
.box-zip { width: 7ch; }
.box-date { width: 11ch; }
.box-year { width: 5ch; }
.box-ins { width: 15ch; }
.box-money { width: 12ch; text-align: right; }
.box-qty { width: 9ch; text-align: right; }
.box-acct { width: 20ch; }
.box-plate { width: 10ch; }
/* ── 공용 카드 칸 templates/_cards.html (22조 · 차량 기본정보 · 8886 명세서 꼴) ── */
.cards-panel { border: 1px solid var(--border); border-radius: var(--r-2); background: var(--card-bg); margin-top: var(--sp-5); }
.cards-head { display: flex; align-items: center; gap: var(--sp-4); height: 30px; padding: 0 var(--sp-4); border-bottom: 1px solid var(--border); background: transparent; }
.cards-head .cards-title { font-size: var(--fs-lg); } .cards-head .en { font-size: var(--fs-sm); color: var(--text-muted); }
.cards-head .spacer { flex: 1; }
.cards-head .win-id { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--c-text-2); border: 1px solid var(--border); border-radius: 3px; padding: 0 5px; }
.cards-head.paste-here, .cards-panel.paste-here > .cards-head { outline: 2px solid var(--c-link); outline-offset: -2px; }
.cards-panel.drop-on { outline: 2px dashed var(--c-link); outline-offset: -2px; background: var(--c-head); }
.cards-body { padding: var(--sp-3) var(--sp-4) var(--sp-4); }
.cards-hint { font-size: var(--fs-md); color: var(--text-muted); margin: 0 0 var(--sp-3); }
.cards-flow { display: flex; flex-wrap: wrap; gap: var(--sp-5); align-items: flex-start; }
.cards-empty { font-size: var(--fs-md); color: var(--text-muted); margin: 0; }
.card-item { width: 168px; border: 1px solid var(--border); border-radius: var(--r-2); padding: var(--sp-4); background: var(--c-surface); font-size: var(--fs-md); cursor: pointer; }
.card-item.card-fields { width: 220px; }
.card-item:hover { border-color: #9db4d6; }
.card-item.cards-past { opacity: .55; }
.card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.card-meta { display: flex; flex-direction: column; min-width: 0; }
.card-when { font-weight: var(--fw-bold); } .card-by { color: var(--text-muted); }
.card-head .win-id { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--c-text-2); border: 1px solid var(--border); border-radius: 3px; padding: 0 var(--sp-2); flex: none; }
.card-survey { display: grid; grid-template-columns: 66px 1fr; gap: 1px var(--sp-3); margin: var(--sp-2) 0 var(--sp-3); font-size: 11.5px; }
.card-survey-row { display: contents; }
.card-survey-label { color: var(--text-muted); text-align: right; white-space: nowrap; }
.card-survey-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card-preview-wrap { border: 1px solid var(--border); border-radius: 3px; padding: var(--sp-2); background: var(--c-sunken); }
.card-thumb { width: 100%; display: block; object-fit: cover; }
.card-thumb.thumb-photo { height: 110px; } .card-thumb.thumb-doc { height: 150px; object-position: top; }
.card-thumb-doc { height: 150px; display: flex; align-items: center; justify-content: center; color: var(--text-muted); font-size: var(--fs-sm); }
.card-file-info { margin-top: var(--sp-2); }
.card-filename { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card-filesize { color: var(--text-muted); font-size: var(--fs-sm); }
.card-foot, .card-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-2); align-items: center; }
.card-status-badge { font-size: var(--fs-sm); padding: 0 var(--sp-2); border-radius: 3px; }
.card-status-fail { background: var(--c-danger-bg); color: var(--c-danger); } .card-status-spin { color: var(--text-muted); }
.card-note-warn { color: var(--c-warn); font-size: var(--fs-sm); }
.cards-hist-box { margin-top: var(--sp-4); }

/* ---------------- 화면 갱신 진행 줄 (docs/화면갱신-공동규정.md) ---------------- */
.live-line {
  display: inline-block;
  height: 20px;
  line-height: 20px;
  font-size: var(--fs-md);
  color: var(--text-muted);
  vertical-align: middle;
}
.live-line b.bad {
  color: var(--c-danger);
  font-weight: var(--fw-bold);
}
.cdoc-top .live-line {
  margin-left: var(--sp-4);
}


/* 폰 보기 모드 단추 — PC 와 수정 모드에서는 안 보인다 (대표님 2026-10-08) */
.vm-share, .vm-edit { display: none; }

/* ================= 폰 = 편의성 1순위 (2026-10-08) =================
   대표님 "pc 는 컴팩트 · 간결이 1순위, 모바일은 사용자 편의성 1순위" — 직원 의견: 단추가 너무 작다 · 검색칸을 넓게.
   **PC 값은 그대로** 두고 700px 아래에서만 키운다. 누르는 것은 높이 40px 안팎, 입력 글자 16px(iOS 가 칸을 누를 때 화면을 확대하지 않는 크기).
   파일 끝에 둔다 — 앞쪽 PC 규칙(.modal.window.has-panel 의 translateX(-50%) · 96vw 등)을 같은 힘에서 이기려면 나중이어야 한다. */
/* 보기 모드(view-mode) — 폰에서 처음, 그리고 곁판 액자(html.side-framed) 안에서 뜨는 창. 클래스는 app.js 가 그때만 단다 —
   그래서 @media 밖에 둔다(대표님 2026-10-11 "modify 말고 view 로"). 곁판 안 촘촘 값은 components.css 의 html.side-framed 절 */
/* 폰 보기 모드 — 수정 창이 먼저 이 꼴로 뜬다. [수정] 을 누르면 view-mode 가 빠져 원래 꼴 */
.modal.window.view-mode .modal-body input:not([type=checkbox]):not([type=radio]):not([type=hidden]),
.modal.window.view-mode .modal-body select,
.modal.window.view-mode .modal-body textarea {
  border-color: transparent; background: transparent; pointer-events: none; padding-left: 0;
  min-height: 0; height: auto; -webkit-appearance: none; appearance: none; box-shadow: none; resize: none; color: var(--text);
}
.modal.window.view-mode .modal-body ::placeholder { color: transparent; }
.modal.window.view-mode .vm-empty,
.modal.window.view-mode .acct-add, .modal.window.view-mode .acct-del, .modal.window.view-mode .acct-main,
.modal.window.view-mode .dropzone, .modal.window.view-mode .file-x, .modal.window.view-mode .key-tag,
.modal.window.view-mode .modal-body .fn-menu, .modal.window.view-mode .auto-kind,
.modal.window.view-mode .link-view-find, .modal.window.view-mode .link-view-head .btn,
.modal.window.view-mode .modal-body .edit-only { display: none; }
.modal.window.view-mode .modal-footer > :not(.vm-share):not(.vm-edit):not(.stamp) { display: none; }
.modal.window.view-mode .vm-share { display: inline-block; }
.modal.window.view-mode .vm-edit { display: inline-flex; }
/* ìì  ëª¨ë(view-mode ê° ë¹ ì§ ì)ììë ì¨ê¸´ë¤ â ìì .modal.window .btn { display: inline-flex } ê° PC ì¨ê¹(.vm-edit)ì ì´ê²¼ë¤ */
.modal.window:not(.view-mode) .vm-share, .modal.window:not(.view-mode) .vm-edit { display: none; }
/* 보기 모드 본문에는 일 단추(이름 [자동생성] · ✎ 등)를 두지 않는다 — 첨부 이름(누르면 크게 보기)만 남긴다 */
.modal.window.view-mode .modal-body button:not(.file-name) { display: none; }
.vm-share .fn-list { left: auto; right: 0; top: auto; bottom: calc(100% + 4px); min-width: 140px; }
.vm-share .fn-list button { display: block; width: 100%; min-height: var(--h-touch); padding: 0 var(--sp-7); border: 0; background: none; text-align: left; font: inherit; font-size: 15px; cursor: pointer; }
.vm-share .fn-list button:active { background: var(--header-bg); }
.vm-toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 4000; max-width: calc(100vw - 32px);
            padding: var(--sp-5) var(--sp-7); border-radius: 20px; background: rgba(17, 24, 39, .92); color: var(--c-on-dark); font-size: var(--fs-xl);
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 보기 모드 — 입력칸 대신 글자(줄바꿈, 다 보임). 전화 · 이메일 · 주소는 파란 밑줄 = 누르면 전화 / 복사 */
.modal.window.view-mode .modal-body .vm-has-text { display: none !important; }
.vm-text { display: block; flex: 1 1 auto; min-width: 0; padding: var(--sp-3) 0; font-size: var(--fs-2xl); line-height: 1.45;
           white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text); }
.vm-text[data-kind="tel"], .vm-text[data-kind="mail"], .vm-text[data-kind="addr"] { color: var(--primary); text-decoration: underline; cursor: pointer; }

@media (max-width: 700px) {
  /* 머리 탭 · 단추 */
  .top-level-tab, .top-level-tabs .tab-sub-item { display: inline-flex; align-items: center; height: 38px; min-height: 38px; font-size: var(--fs-xl); padding: 0 var(--sp-6); }
  .top-level-tabs .tab-sub-parent { height: 38px; font-size: var(--fs-xl); }
  .top-level-tabs-right .btn { min-height: 32px; font-size: var(--fs-lg); }
  .toolbar .btn, .modal.window .btn, .top-level-tabs-right .btn { display: inline-flex; align-items: center; justify-content: center; }

  /* 검색칸은 한 줄을 통째로, 단추는 그 아래 한 줄 */
  .toolbar { gap: var(--sp-2); }
  .toolbar .search-form { flex: 1 1 100%; display: flex; }
  .search-input { height: 42px; font-size: var(--fs-2xl); padding: 0 var(--sp-6); box-sizing: border-box; }
  .toolbar .btn, .modal.window .btn, .dropdown-menu a, .dropdown-menu button { min-height: 40px; font-size: var(--fs-xl); padding: 0 14px; box-sizing: border-box; }
  .toolbar .btn { padding: 0 9px; }

  /* 목록 줄 — 손가락 한 마디 */
  .grid tbody td { padding: 11px var(--sp-4); font-size: var(--fs-xl); }
  .grid thead th { padding: var(--sp-4); font-size: var(--fs-lg); }
  /* 연락처 목록 — 앞의 폰 규칙이 거래처 열(cust_*)만 남겨 연락처는 줄이 통째로 비어 보였다 */
  .list-grid th[data-col="cont_name"], .list-grid td[data-col="cont_name"] { display: table-cell; width: 60%; }
  .list-grid th[data-col="cont_main"], .list-grid td[data-col="cont_main"] { display: table-cell; width: 40%; }
  /* 쪽 넘김 — 오른쪽으로 비어져 나가던 것 */
  .pager { flex-wrap: wrap; gap: var(--sp-2); }
  .pager-page { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; min-height: 40px; font-size: var(--fs-xl); }
  .pager-jump input { min-height: 40px; font-size: var(--fs-2xl); }

  /* 창 안 칸 */
  .modal.window input:not([type=checkbox]):not([type=radio]):not([type=hidden]), .modal.window select, .modal.window textarea { min-height: 40px; font-size: var(--fs-2xl); box-sizing: border-box; }
  .modal.window input[type=checkbox], .modal.window input[type=radio] { width: 20px; height: var(--h-sm); }
  .modal.window .modal-header { min-height: 44px; }
  .modal.window .modal-header .close, .modal.window .modal-header button, .win-panel .panel-head button { min-width: 40px; min-height: 40px; font-size: 20px; }
  .modal.window .dropzone { min-height: 48px; }
  .modal.window .file-row { min-height: 48px; align-items: center; }
  .modal.window .file-row img.shot { width: 64px; height: 44px; object-fit: cover; }
  .modal.window .file-row .file-x { min-width: 40px; min-height: 40px; }
  /* 창 아래 단추 줄 — 단추 글자가 한 자씩 꺾이던 것(삭 / 제) */
  .modal.window .modal-footer { gap: var(--sp-3); }
  .modal.window .modal-footer .btn { white-space: nowrap; flex: none; padding: 0 var(--sp-6); }
  .modal.window .modal-footer .stamp { flex: 1 1 0; min-width: 0; font-size: var(--fs-sm); line-height: 1.3; overflow: hidden; }
  .modal.window .modal-footer .spacer { display: none; }
  /* Match connect 띠 — 창 본문 여백(12px)보다 깊게 당겨 오른쪽으로 비어져 나가던 것 */
  .modal.window .link-view { margin-left: -12px; margin-right: -12px; }
  .link-view-head { flex-wrap: wrap; gap: var(--sp-3); }
  .link-view-head .link-view-label { flex: 1 1 100%; }
  .link-view-head .link-view-find { width: auto; flex: 1 1 0; min-width: 0; }
  .link-view-head .btn { white-space: nowrap; flex: none; }

  /* 옆판(사진 · 링크매치 · 이력)이 열리면 — PC 는 창을 넓히고 가운데로 당기는데(translateX(-50%)) 폰에서는 그것이
     창을 왼쪽으로 반쯤 밀어냈다. 폰은 창 자리를 그대로 두고 **판이 창을 통째로 덮는다**. ✕ 로 닫으면 수정 칸이 그대로 있다. */
  .modal.window.has-panel, .modal.window.has-panel.with-shot, .modal.window.picking, .modal.window.has-panel.with-shot.picking {
    width: auto; max-width: none; height: auto; top: 44px; left: 6px; right: 6px; bottom: 6px; transform: none;
  }
  .modal.window.has-panel .win-split { position: relative; }
  .modal.window.has-panel .win-main, .modal.window.has-panel.with-shot .win-main, .modal.window.picking .win-main { width: 100%; flex: 1 1 auto; border-right: 0; }
  .modal.window.has-panel .win-split > .win-panel:not([hidden]):not(.cert-shot),
  .modal.window.has-panel .win-split > .win-side:not([hidden]) {
    position: absolute; inset: 0; z-index: 5; display: flex; flex-direction: column; background: var(--card-bg);
  }
  .modal.window.has-panel .win-split > .win-side > .win-side { flex: 1 1 auto; min-height: 0; width: auto; }
  .att-stage { flex: 1 1 auto; min-height: 0; }
  /* 판독 원본(OCR 창의 바탕 사진)은 덮지 않고 위에 얹는다 — 사진 보며 칸을 고친다 */
  .modal.window.has-panel.with-shot .win-split { flex-direction: column; }
  .modal.window.has-panel.with-shot .win-split > .cert-shot { order: -1; flex: 0 0 38%; min-height: 0; }
  .modal.window.has-panel.with-shot .win-main { flex: 1 1 0; min-height: 0; }
  /* 링크매치 고르는 표 — 앞의 폰 규칙("찾기 전엔 줄을 안 늘어놓는다")이 이 표까지 숨겨 판이 비어 보였다 */
  .list-grid.pick-grid:not(.searched) { display: table; }
  .link-pick-foot .btn { white-space: nowrap; flex: none; }

  /* 사진 보기(Viewer.js) 단추 — 24px 그림 단추를 손가락 크기로 */
  .viewer-toolbar > ul > li { transform: scale(1.6); margin: 0 var(--sp-5); }
  /* 라이트박스 바탕 — 기본 반투명(0.5)은 폰에서 뒤 창이 비쳐 사진과 섞였다 */
  .viewer-fixed.viewer-backdrop { background-color: rgba(0, 0, 0, .9); }
  /* 창 안 안내 글(예: "cards 와 ERP 양쪽에 있습니다 …")이 한 줄로 오른쪽 밖까지 나가던 것 */
  .modal.window .account-info { white-space: normal; }


  /* 새 곁판 한 자리(#winSide) — 본문은 창 안에서 흐르고, 곁판은 창을 덮는다(판독 원본만 위에 얹음). 2078 줄 폰 규칙의 flex:none 을 이긴다 */
  .modal.window .win-split { position: relative; }
  .modal.window .win-split > .win-main { flex: 1 1 0; min-height: 0; }
  .modal.window .win-split > .win-side:not([hidden]):not(:has(> .cert-shot)) {
    position: absolute; inset: 0; z-index: 5; display: flex; flex-direction: column; background: var(--card-bg);
  }
  .modal.window .win-split > .win-side:not([hidden]):has(> .cert-shot) { order: -1; flex: 0 0 38%; min-height: 0; }

  /* 회사관련서류 · 차량정보 — 폰은 칸을 세로로 늘어놓는다(PC 의 flex:1 1 0 은 폰에서 높이 0 으로 접혔다) */
  .cdoc-page > .ex3-wrap, .veh-page > .ex3-wrap { flex: none; height: auto; overflow: visible; }
  .ex3-wrap > .ex3-tree { max-height: none; overflow: visible; }
  .veh-page .veh-list-pane, .veh-page .ex3-list, .cdoc-page .ex3-list { flex: none; min-height: 0; overflow: visible; }
  .ex3-nodes { gap: var(--sp-2); }
  .ex3-nl { min-height: 34px; display: inline-flex; align-items: center; padding: 0 var(--sp-5); font-size: var(--fs-xl); }
  /* 폴더를 고르면 폰에서도 그 파일이 바로 보인다(앞의 "찾기 전엔 목록 안 보임" 은 거래처 · 연락처 몫) */
  .cdoc-results.cdoc-unfiltered { display: block; }
  .list-grid.cdoc-grid:not(.searched), .list-grid.veh-grid:not(.searched), .list-grid.veh-slip-grid:not(.searched) { display: table; }
  .veh-page .ex3-head.veh-bar { flex-wrap: wrap; }
  .veh-bar .veh-search { flex: 1 1 100%; width: auto; order: 5; }
  .veh-list-scroll { overflow: visible; }
  .cdoc-phone-first { display: none; }
  /* 서류 목록 — 제목 · 기준일 · 만료 · 공개만(고르기 · ✎ · 삭제는 PC 에서) */
  .cdoc-grid .c-pick, .cdoc-grid .c-edit, .cdoc-grid .c-del { display: none; }
  .cdoc-grid th:nth-child(2), .cdoc-grid td:nth-child(2) { width: 50%; }
  .cdoc-grid th:nth-child(3), .cdoc-grid td:nth-child(3) { width: 28%; font-size: var(--fs-lg); }
  .cdoc-grid .c-flag { width: 11%; }
  /* 차량 목록 — 차량번호 · 차명 · 보험만료일 · 정기검사일만(만료 색이 보이는 두 날짜). 열 차례: 1 번호 2 차명 3 차종 4 연식 5 소유 6 담당 7 보험 8 검사 9 비고 */
  .veh-find { flex-wrap: wrap; }
  .veh-search { flex: 1 1 100%; width: auto; order: 5; }
  .veh-find .btn { white-space: nowrap; }
  .veh-grid col { width: auto !important; }
  .veh-grid th, .veh-grid td { padding-left: var(--sp-2); padding-right: var(--sp-2); }
  .veh-grid th:nth-child(3), .veh-grid td:nth-child(3), .veh-grid th:nth-child(4), .veh-grid td:nth-child(4),
  .veh-grid th:nth-child(5), .veh-grid td:nth-child(5), .veh-grid th:nth-child(6), .veh-grid td:nth-child(6),
  .veh-grid th:nth-child(9), .veh-grid td:nth-child(9) { display: none; }
  .veh-grid th:nth-child(1), .veh-grid td:nth-child(1), .veh-grid th:nth-child(2), .veh-grid td:nth-child(2) { width: 25%; }
  .veh-grid th:nth-child(7), .veh-grid td:nth-child(7), .veh-grid th:nth-child(8), .veh-grid td:nth-child(8) { width: 25%; font-size: var(--fs-lg); }
  /* configuration 하위 탭 일곱 — 한 줄로 밖까지 나가 겹치던 것, 줄을 바꾼다 */
  .tab-bundle-sub { flex-wrap: wrap; }
  /* "찾기 전엔 목록 안 보임" 은 찾기 안내(.phone-first)가 있는 화면(거래처 · 연락처)만 — 사용자 · 권한그룹 등은 늘 보인다 */
  body:not(:has(.phone-first)) .list-grid:not(.searched) { display: table; }
  /* 목록 위 [Option](양식설정 등 PC 일)은 폰에서 뗀다 — [등록 ▾](파랑)은 남김 */
  .toolbar > .fn-menu:has(> .fn-btn.btn-secondary) { display: none; }
  /* Match connect 표 — 이름(상호) · 연락처 두 열만. 거래처 창 5열 → 2 · 4, 연락처 창 7열 → 3 · 6 */
  .link-view .view-grid th, .link-view .view-grid td { display: none; }
  .link-view .view-grid:not(:has(th:nth-child(6))) :is(th, td):is(:nth-child(2), :nth-child(4)),
  .link-view .view-grid:has(th:nth-child(6)) :is(th, td):is(:nth-child(3), :nth-child(6)) { display: table-cell; width: 50%; }
  /* Match connect 표(.view-grid)는 늘 보인다 — "찾기 전엔 목록 안 보임" 은 목록 화면 몫 */
  .list-grid.view-grid:not(.searched) { display: table; }

  /* 이력 표 — 폰 단추 여백(14px)이 [보기] 칸(41px)보다 넓어 오른쪽이 잘렸다 */
  .modal.window .hist .btn { padding: 0 var(--sp-4); min-width: 0; }
  .modal.window .hist th.h-see { width: 52px; }
  /* 링크매치 Connector 표 — 역할 · 이름(상호) · 전화만 */
  .list-grid.pick-grid { table-layout: auto; width: 100%; }
  .pick-grid col { width: auto !important; }
  .pick-grid tr.pick-row > td:not(.pick-role):not(.pick-name):not(.pick-tel) { display: none; }
  .pick-grid tr.pick-row > td.pick-name { width: 45%; }
  .pick-grid tr.pick-row > td.pick-tel { width: 30%; }
  /* Filter 칩 — 손가락 크기 */
  .filter-chips { gap: var(--sp-3); }
  .filter-chip { min-height: 32px; padding: 0 var(--sp-5); font-size: var(--fs-xl); }
  /* 차량 상세 — 카드 머리줄은 줄바꿈(설명은 제 줄), 라벨 · 값 2열은 공용 .kv-grid */
  .cards-head { flex-wrap: wrap; row-gap: var(--sp-2); height: auto; min-height: 30px; }
  .cards-head .veh-upload-hint { flex: 1 1 100%; order: 9; }

  /* codes 공통코드 · 장비마스터 (2026-10-10) */
  .codes-layout { flex-direction: column; gap: var(--sp-4); }
  .codes-layout .codes-tree { width: auto; }
  .codes-layout.has-k:not(.tree-open) .codes-tree { display: none; }
  /* 아래 codes 기본 규칙이 이 블록보다 뒤에 있어 .codes-layout 을 앞에 붙여 이긴다 */
  .codes-layout .codes-viewer { width: 100%; }
  .codes-layout .equip-crumbs { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); align-items: center; font-size: var(--fs-2xl); padding: var(--sp-2) var(--sp-1) var(--sp-4); }
  .codes-layout .equip-crumbs a { color: var(--c-primary); text-decoration: none; padding: var(--sp-2) var(--sp-1); }
  .codes-layout .equip-cols { display: block; }
  .codes-layout .equip-col { display: none; }
  .codes-layout .equip-col.phone-show { display: flex; }
  .codes-layout .equip-col-body { min-height: 0; max-height: none; overflow: visible; }
  .codes-layout .equip-item { min-height: var(--h-touch); font-size: var(--fs-2xl); padding: var(--sp-3) var(--sp-5); }
  .codes-layout .equip-item .equip-up, .codes-layout .equip-item .equip-dn { display: none !important; }
  .codes-layout .equip-item-name { white-space: normal; }
  .codes-layout .codes-viewer .codes-tree-toggle { display: inline-flex; }
}
.codes-layout .codes-tree-toggle { display: none; }   /* PC 에선 숨김 — .btn 이 display 를 덮어 .phone-only 만으론 안 숨는다 */

/* 공용 카드/표 목록(cards) — 2026-10-08 표준 부품 */
.cards-view-btn { margin-left: var(--sp-2); }
.cards-table-wrap { overflow-x: auto; margin-top: var(--sp-4); width: 100%; }
.cards-table { width: 100%; border-collapse: collapse; }
.cards-table th, .cards-table td { padding: var(--sp-3) var(--sp-4); font-size: var(--fs-lg); text-align: left; vertical-align: middle; }
.cards-table tr.clickable { cursor: pointer; }
.cards-table tr.clickable:hover { background-color: var(--row-hover, var(--c-head)); }
.cards-past { opacity: 0.55; }
.cards-table th, .cards-table td { height: 25px; padding-top: 0; padding-bottom: 0; }
/* 메뉴 주황 불 — 깜빡이는 두 박자를 keyframes 에 다 적는다. keyframes 안의 !important 는 무시돼 꺼진 박자에 흰 글씨만 남았다(10-08). */
.nav-alert { border-radius:3px; outline:2px solid var(--c-warn); outline-offset:-2px; animation: nav-alert-blink 1s steps(1, end) infinite; }
@keyframes nav-alert-blink { 0%, 49% { background:var(--c-warn); color:#fff; } 50%, 100% { background:#fff; color:var(--c-warn); } }
.llm-alert { color:var(--c-warn) !important; font-weight:var(--fw-semi); }
.llm-summary { font-size:var(--fs-md); padding:var(--sp-2) var(--sp-4); }
.llm-sum-row { line-height:20px; }
.llm-dot { display:inline-block; width:8px; height:8px; border-radius:var(--r-round); background:var(--c-warn); margin-right:var(--sp-3); animation: nav-alert-blink 1s steps(1, end) infinite; }
.llm-alert .llm-bad, .llm-alert .llm-warn { color: inherit !important; }
/* 카드 아래 판독 경고는 파일 이름 밑 한 줄로 — 옆에 끼면 세로로 찌그러짐(10-08) */
.card-foot { flex-wrap: wrap; }
.card-foot .card-file-info { min-width: 0; flex: 1 1 auto; }
.card-foot .card-note-warn { flex: 1 0 100%; }

/* codes */
.codes-layout { display: flex; gap: var(--sp-6); align-items: flex-start; }
@media (min-width: 701px) { .codes-layout > .codes-tree { flex: 0 0 160px; width: 160px; } }   /* 표준 트리 폭(.ex3-tree 160px) — 공용 .win-panel 의 flex:1 이 덮어 왼쪽이 넓어졌다(대표님 2026-10-12) */
.codes-viewer { flex: 1 1 0; min-width: 0; }
.codes-viewer .panel-head { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-4); flex-wrap: wrap; }
.codes-viewer .btn-sm { height: var(--h-sm); line-height: var(--lh-row); padding: 0 var(--sp-3); font-size: var(--fs-md); }
tr.row-off { opacity: 0.55; }
.equip-cols { display: flex; gap: var(--sp-4); width: 100%; }
.equip-col { flex: 1 1 0; min-width: 0; border: 1px solid var(--c-line); border-radius: var(--r-2); background: var(--c-surface); display: flex; flex-direction: column; }
.equip-col-head { display: flex; align-items: center; justify-content: space-between; padding: var(--sp-3) var(--sp-4); background: var(--c-sunken); border-bottom: 1px solid var(--c-line); font-size: var(--fs-lg); font-weight: var(--fw-semi); }
.equip-col-body { flex: 1 1 auto; overflow-y: auto; min-height: 200px; }
.equip-item { display: flex; align-items: center; justify-content: space-between; padding: var(--sp-2) var(--sp-4); border-bottom: 1px solid #f1f5f9; font-size: var(--fs-lg); }
.equip-item:hover { background: var(--c-head); }
.equip-item.active { background: var(--c-primary); color: var(--c-on-dark); font-weight: var(--fw-semi); }
.equip-item-name { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.equip-hint { padding: var(--sp-7) var(--sp-4); text-align: center; color: var(--c-text-3); font-size: var(--fs-lg); }
.row-off { opacity: 0.55; }
.acc-d1 { padding-left: 0; }
.acc-d2 { padding-left: var(--sp-6); }
.acc-d3 { padding-left: var(--sp-8); }
.acc-d4 { padding-left: 36px; }
.acc-d5 { padding-left: 48px; }
.acc-d6 { padding-left: 60px; }
.acc-d7 { padding-left: 72px; }
tr.acc-group { font-weight: var(--fw-semi); }
/* 분류 머리 · 아래 줄 꼴은 공용 트리 층위(components.css .tree-cap · .tree-sub, 디자인시스템 3-2 "트리 층위") */
tr.sub-head td { background: var(--c-head); font-weight: var(--fw-semi); color: #475569; }

.modal.window.innerdoc-host { width: 760px; max-width: 96vw; height: 70vh; top: 40px; padding: 0; }
.innerdoc { display: flex; flex-direction: column; height: 100%; }
.innerdoc-body { flex: 1 1 0; min-height: 0; display: flex; }
.innerdoc-tree { width: 180px; flex-shrink: 0; overflow-y: auto; border-right: 1px solid var(--border); padding: var(--sp-2) 0; font-size: var(--fs-md); }
.innerdoc-src { font-weight: var(--fw-semi); padding: var(--sp-1) var(--sp-4); }
.innerdoc-node { display: flex; justify-content: space-between; padding: var(--sp-1) var(--sp-4) var(--sp-1) 18px; cursor: pointer; color: var(--text); text-decoration: none; }
.innerdoc-node.on { background: var(--header-bg); color: var(--primary); }
.innerdoc-main { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; padding: var(--sp-3); gap: var(--sp-3); }
.innerdoc-main input[type=search] { height: var(--h-md); }
.innerdoc-grid { flex: 1 1 0; overflow-y: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: var(--sp-3); align-content: start; }
.innerdoc-item { display: flex; flex-direction: column; border: 1px solid var(--border); padding: 3px; cursor: pointer; font-size: var(--fs-sm); min-width: 0; }
.innerdoc-item img { width: 100%; height: 80px; object-fit: contain; background: var(--c-surface); }
.innerdoc-item.on { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.innerdoc-nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.innerdoc-more { grid-column: 1 / -1; height: 1px; }

/* codes */
.cal-hol { background-color: var(--c-danger); border-color: var(--c-danger); color: var(--c-on-dark); }
.cal-off { background-color: var(--c-text-2); border-color: var(--c-text-2); color: var(--c-on-dark); }
.cal-on { background-color: var(--c-primary); border-color: var(--c-primary); color: var(--c-on-dark); }
.cal-rest { background-color: var(--c-head) !important; }
.fc-day-sun .fc-col-header-cell-cushion, .fc-day-sun .fc-daygrid-day-number { color: var(--c-danger); }
.fc-day-sat .fc-col-header-cell-cushion, .fc-day-sat .fc-daygrid-day-number { color: var(--c-primary); }


/* ---------------- 코드칸(lookup) ---------------- */
.lookup-box {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}
.lookup-name {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  white-space: nowrap;
}
.lookup-slot {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 150;
}
.lookup-panel {
  background: var(--card-bg);
  border: thin solid var(--border);
  border-radius: var(--r-1);
  box-shadow: 0 var(--sp-2) var(--sp-6) rgba(15, 23, 42, 0.15);
  min-width: calc(var(--label-w) * 3);
  max-width: calc(var(--label-w) * 5);
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  color: var(--text);
  overflow: hidden;
}
.lookup-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-2) var(--sp-4);
  background: var(--header-bg);
  border-bottom: thin solid var(--border);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
}
.lookup-head .lookup-title {
  font-weight: var(--fw-bold);
  color: var(--text);
}
.lookup-head .lookup-manage {
  color: var(--primary);
  text-decoration: none;
  font-size: var(--fs-xs);
  margin-left: auto;
  margin-right: var(--sp-3);
}
.lookup-head .lookup-manage:hover {
  text-decoration: underline;
}
.lookup-head .lookup-close {
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--text-muted);
  font-size: var(--fs-md);
  padding: 0;
  line-height: var(--lh-1);
}
.lookup-head .lookup-close:hover {
  color: var(--text);
}
.lookup-rows {
  max-height: calc(var(--h-touch) * 5);
  overflow-y: auto;
  padding: var(--sp-1) 0;
}
.lookup-row-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--sp-2);
}
.lookup-row-item:hover {
  background: var(--header-bg);
}
.lookup-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 1;
  text-align: left;
  border: 0;
  background: none;
  padding: var(--sp-2) var(--sp-2);
  font-size: var(--fs-md);
  line-height: var(--lh-row);
  font-family: var(--font-mono);
  cursor: pointer;
  color: var(--text);
}
.lookup-row .lookup-code {
  font-weight: var(--fw-semi);
  color: var(--primary);
}
.lookup-row .lookup-sep {
  color: var(--text-muted);
}
.lookup-row .lookup-name-text {
  color: var(--text);
  font-family: var(--font-sans);
}
.lookup-edit-btn {
  display: none;
  background: none;
  border: thin solid var(--border);
  border-radius: var(--r-1);
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--text-muted);
  cursor: pointer;
}
.lookup-panel.is-unlocked .lookup-edit-btn {
  display: inline-block;
}
.lookup-edit-btn:hover {
  border-color: var(--primary);
  color: var(--primary);
}
.lookup-empty, .lookup-more {
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  text-align: center;
}
.lookup-add {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  background: var(--header-bg);
  border-top: thin solid var(--border);
}
.lookup-add input {
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-sm);
  border: thin solid var(--border);
  border-radius: var(--r-1);
  background: var(--card-bg);
  color: var(--text);
}
.lookup-add .lookup-add-code {
  width: var(--label-w);
}
.lookup-add .lookup-add-name {
  flex: 1;
}
.lookup-add button {
  padding: var(--sp-1) var(--sp-3);
  font-size: var(--fs-xs);
  border: thin solid var(--border);
  border-radius: var(--r-1);
  background: var(--card-bg);
  cursor: pointer;
}
.lookup-add .lookup-add-save {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--c-on-dark);
}
.lookup-msg {
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--danger);
  background: var(--danger-bg);
  border-top: thin solid var(--border);
}
.lookup-foot {
  display: flex;
  align-items: center;
  padding: var(--sp-2) var(--sp-4);
  background: var(--header-bg);
  border-top: thin solid var(--border);
  gap: var(--sp-2);
  font-size: var(--fs-sm);
}
.lookup-foot .lookup-lock-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  background: var(--card-bg);
  border: thin solid var(--border);
  border-radius: var(--r-1);
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs);
  cursor: pointer;
  color: var(--text);
}
.lookup-foot .lookup-add-open-btn {
  background: var(--card-bg);
  border: thin solid var(--border);
  border-radius: var(--r-1);
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs);
  cursor: pointer;
  color: var(--text);
}
.lookup-foot .lookup-add-open-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.lookup-foot .lookup-spacer {
  flex: 1;
}
.lookup-foot .lookup-free-btn {
  background: none;
  border: 0;
  color: var(--primary);
  font-size: var(--fs-xs);
  cursor: pointer;
  text-decoration: underline;
  padding: 0;
}
.lookup-edit-form {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 1;
  padding: var(--sp-1) 0;
}
.lookup-edit-form input {
  flex: 1;
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-sm);
  border: thin solid var(--border);
  border-radius: var(--r-1);
  background: var(--card-bg);
  color: var(--text);
}
.lookup-edit-form button {
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs);
  border: thin solid var(--border);
  border-radius: var(--r-1);
  background: var(--card-bg);
  cursor: pointer;
}
.lookup-edit-form .lookup-edit-save {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--c-on-dark);
}

r { color: var(--c-danger); }
.fc-day-sat .fc-col-header-cell-cushion, .fc-day-sat .fc-daygrid-day-number { color: var(--c-primary); }

/* ===== 구매 › 견적서 (pq-) — templates/quotes ===== */
.pq-page { display: flex; flex-direction: column; min-height: 0; height: 100%; }
.pq-view { display: flex; flex-direction: column; min-height: 0; height: 100%; overflow: hidden; }
.pq-detail { flex: 1 1 auto; min-height: 0; overflow-y: auto; }   /* 오른쪽 칸 전체 — 첨부는 [새 탭] 뷰어로(2026-10-10) */
.pq-tag { display: inline-block; padding: 0 var(--sp-2); font-size: var(--fs-sm); border-radius: var(--r-1); background: var(--border); color: var(--text); vertical-align: middle; margin-left: var(--sp-2); }
.pq-tag.pq-del { background: var(--danger-bg); color: var(--danger); font-weight: var(--fw-semi); }
.pq-lines td.num, .pq-lines th.num { text-align: right; }
.pq-line { display: grid; grid-template-columns: 14ch 2fr 1fr 9ch 6ch 9ch 10ch 1fr auto; gap: var(--sp-2); align-items: center; min-height: var(--h-lg); margin-bottom: var(--sp-2); font-size: var(--fs-md); }
.pq-line-head { font-weight: var(--fw-semi); color: var(--text-muted); }
.pq-line input { width: 100%; height: var(--h-lg); padding: var(--sp-1) var(--sp-2); font-size: var(--fs-md); }
.pq-files { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-4); font-size: var(--fs-md); }
.pq-file-name { color: var(--primary); text-decoration: none; cursor: pointer; }
.pq-file-name:hover { text-decoration: underline; }
.pq-row { cursor: pointer; }
.pq-row.on { background: var(--header-bg); font-weight: 500; }
/* 목록 열 폭 — 날짜 · 금액은 다 보이게, 나머지(거래처 · 비고)가 남은 폭을 나눈다(가로 스크롤 없음) */
.pq-c-date { width: 13ch; } .pq-c-kind { width: 6ch; } .pq-c-no { width: 11ch; } .pq-c-n { width: 6ch; } .pq-c-amt { width: 11ch; }
/* 빈 줄 서식(empty_form)은 숨긴다 — hidden 속성은 위 display: grid 에 진다 */
.pq-line[hidden] { display: none; }
.pq-line .field-error { grid-column: 1 / -1; }   /* 줄 오류는 격자 한 줄을 다 쓴다 */
/* 첨부 표 (2026-10-10) — 파일명 · 비고가 남은 폭을 나눈다 */
.pq-att { width: 100%; margin-top: var(--sp-3); table-layout: fixed; font-size: var(--fs-md); }
.pq-att td { vertical-align: middle; }
.pq-att .pq-att-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pq-c-who { width: 8ch; } .pq-c-at { width: 11ch; } .pq-c-act { width: 9ch; white-space: nowrap; }
.pq-att-note { width: 100%; height: var(--h-md); font-size: var(--fs-md); padding: 0 var(--sp-2); border: 1px solid var(--border); }
.quote-filter-box { position: absolute; top: 100%; left: 0; right: auto; width: min(calc(var(--sp-9) * 16), 100%); z-index: 30; box-shadow: 0 var(--sp-1) var(--sp-4) var(--border); }
.pq-line .fs-del { display: inline-flex; align-items: center; gap: var(--sp-1); white-space: nowrap; }
/* 고치는 꼴 품목 표(2026-10-10) — 표 안 입력칸이 칸 폭을 다 쓴다, 열 폭은 이름으로 */
/* 떠 있는 뷰어 팝업(ErpViewer.float) 제목 띠 — 창 제목 띠 표준(.modal.window .modal-header)과 같은 꼴, 창 이름표는 띠 위 회색 */
.vw-float > .modal-header .win-id { color: var(--c-text-3); margin-left: auto; margin-right: var(--sp-4); }
.vw-float > .modal-header h2 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vw-float .vw-exit { display: none !important; }   /* 닫기는 제목 띠 ✕ 하나 — 새 창 전용 보기의 [닫기](window.close)는 팝업에선 안 쓴다 */
.vw-float { border-color: var(--c-line-strong); box-shadow: var(--sp-1) var(--sp-1) 0 rgba(15, 23, 42, .18); }   /* 창 테두리 · 그림자 표준(.modal.window)과 같게 */
/* 떠 있는 뷰어 팝업 — 차례는 '새 창 전용 보기' 한 줄 축약, 단추 모양은 도구줄 표준(표준컴포넌트-뷰어 8-1: 높이 22 · 여백 0 4px · 각짐 · 그림 단추 22x22 · 그림 14px). 대표님 2026-10-10 "버튼모양도 표준대로" */
.vw-float .vw-solo .vw-tools { min-height: var(--h-md); }
.vw-float .vw-solo .vw-tools button { height: var(--h-md); min-height: var(--h-md); min-width: var(--h-md); padding: 0 var(--sp-2); line-height: 1; border-radius: 0; }
.vw-float .vw-solo .vw-tools .vw-icon-btn, .vw-float .vw-solo .vw-tools .vw-full-btn, .vw-float .vw-solo .vw-tools .vw-ink-btn, .vw-float .vw-solo .vw-tools button:has(> svg) { width: var(--h-md); height: var(--h-md); min-height: var(--h-md); padding: 0; }
.vw-float .vw-solo .vw-tools > .vw-page-input { height: var(--h-md); flex: 0 0 calc(var(--h-md) * 2.5); width: calc(var(--h-md) * 2.5); }
.vw-float .vw-solo .vw-tools > .vw-dim { line-height: var(--h-md); }
.vw-float .vw-solo .vw-tools [data-find="prev"], .vw-float .vw-solo .vw-tools [data-find="next"] { padding: 0 var(--sp-2); }
.vw-float .vw-solo .vw-tools [data-slot="find"] input { height: var(--h-md); box-sizing: border-box; }   /* 찾기 칸도 도구줄 높이(8-1 검색 칸) */
.pq-detail .pq-lines { table-layout: fixed; }   /* 보기 · 고치기 두 꼴의 열 폭이 같다 — 틀이 안 움직인다 */
.pq-detail .ip-rw-rows td { padding: 0 var(--sp-1); }
.pq-c-no1 { width: 4ch; }
.pq-errs { margin: var(--sp-2) 0; padding-left: var(--sp-7); color: var(--c-danger); font-size: var(--fs-md); }
/* 품목 표 남는 폭 — 정해진 칸(번호 · 코드 · 단위 · 수량 · 단가 · 금액) 뒤 남는 폭을 품목명 > 규격 > 적요 차례로(칸 폭에 따라 같이 늘고 준다) */
.pq-lines th[data-field="item_name"] { width: 24%; } .pq-lines th[data-field="spec"] { width: 14%; } .pq-lines th[data-field="remarks"] { width: 14%; }
.pur-list tr.group th{background:var(--c-head);text-align:left;font-size:var(--fs-sm)}

/* 구매(purchase) — 두 칸 틀 · 전표 칸 */
.pur-view{padding:var(--sp-3) var(--sp-4)}
.pur-view.frozen .groupbox{opacity:.85}
.pur-chip{display:inline-block;padding:0 var(--sp-3);border-radius:var(--r-0);font-size:var(--fs-sm);line-height:var(--h-xs);background:var(--c-head)}
.pur-chip.kind-PO{background:var(--c-selected)}
.pur-chip.kind-PR{background:var(--c-note-bg)}
.pur-chip.st-PO{background:var(--c-selected)}.pur-chip.st-AR{background:var(--c-note-bg)}.pur-chip.st-LP{background:var(--c-hover)}.pur-chip.closed,.pur-chip.chip-closed{background:var(--c-head);border:var(--bw-hair) solid var(--c-line)}.pur-chip.prepaid,.pur-chip.is-prepaid{background:var(--c-note-bg)}.pur-chip.deleted{background:var(--c-danger-bg)}
.pur-view .close-stamp{border:var(--bw-hair) solid var(--c-danger);color:var(--c-danger);padding:0 var(--sp-2);font-size:var(--fs-sm);transform:rotate(-4deg)}
.pur-close-bar{display:flex;gap:var(--sp-2);align-items:center}
.pur-view .view-head .view-title{flex:none}   /* 전표번호는 줄지 않는다 — 단추 무리가 길면 단추 쪽이 접힌다 */
.pur-view .view-head .pur-head-ro{flex-wrap:wrap;justify-content:flex-end;min-width:0}
.pur-row.is-deleted td{text-decoration:line-through;opacity:.6}
.pur-row.on td{background:var(--c-selected)}
.pur-row{cursor:pointer}
.pur-items-head{display:flex;align-items:center;justify-content:space-between;margin:var(--sp-4) 0 var(--sp-2)}
.pur-view .pur-items-head,.pur-view .items-ro{border-top:var(--bw-hair) solid var(--c-line);padding-top:var(--sp-3);margin-top:var(--sp-4)}
.pur-view .ih-title{font-weight:var(--fw-semi);font-size:var(--fs-lg)}
/* 구매 품목표 = 공용 상세 표(.dgrid, 목록과창 10절) — 견적서와 같은 꼴, 열 폭만 구매 것. 보기 · 고치기 두 꼴의 열 폭이 같다(table-layout fixed) */
.pur-lines-wrap{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
.pur-lines{width:100%;min-width:52em;margin:0 0 var(--sp-3);font-size:var(--fs-md);table-layout:fixed}   /* 좁으면 표만 옆으로 민다(품목명 칸이 사라지지 않게) */
.pur-lines td.num,.pur-lines th.num{text-align:right}
.pur-lines td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pur-lines tfoot td{overflow:visible}
.pur-c-no{width:5ch}.pur-c-cd{width:12ch}.pur-c-size{width:11%}.pur-c-qty{width:6ch}.pur-c-price{width:9ch}.pur-c-amt{width:10ch}.pur-c-vat{width:8ch}.pur-c-done{width:5ch}
.pur-view .ip-rw-rows td{padding:0 var(--sp-1)}
.pur-view .ip-rw-rows td input:not([type=checkbox]){width:100%;height:var(--h-md);box-sizing:border-box;border:var(--bw-hair) solid var(--c-line);border-radius:0;padding:0 var(--sp-2);font-size:var(--fs-md);font-family:inherit}
.pur-view .ip-rw-rows td input[data-mask=money],.pur-view .ip-rw-rows td input[data-mask=qty]{text-align:right}
.pur-view .ip-rw-rows td input.manual{background-color:var(--c-hover)}
.pur-lines td .lookup-box{display:flex;align-items:center;min-width:0;width:100%}
.pur-lines td .lookup-box .key-box{flex:1 1 auto;min-width:0}
.pur-lines td .lookup-box .lookup-name{flex:0 1 auto;min-width:0;max-width:4em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pur-lines td .lookup-box.is-matched .lookup-name{display:none}   /* 맞춘 품목 이름은 옆 품목명 칸이 보인다 — [미정] 꼬리만 남긴다 */
.pur-view .view-sec > .dg-bar{margin:0}
.pur-view .pur-memo{white-space:pre-wrap}
.pur-undeliv{margin:0 0 var(--sp-3);font-size:var(--fs-md);color:var(--c-text-2)}
.pur-hist-inline{margin:var(--sp-3) 0;border-top:var(--bw-hair) dashed var(--c-line);padding-top:var(--sp-2)}
.pur-hist-inline .hist-panel{position:static;width:auto;max-width:none;border:0}
.pur-hist-inline table.hist{width:100%}
.pur-link-row summary{display:flex;gap:var(--sp-4);align-items:center;height:var(--h-lg);cursor:pointer}
.pur-link-row .items-ro{margin:var(--sp-2) 0 var(--sp-4) var(--sp-7);border-top:none;padding-top:0}
.pur-lamp{display:inline-flex;align-items:center;height:var(--h-xs);padding:0 var(--sp-3);border:var(--bw-hair) dashed var(--c-danger);border-radius:var(--r-0);font-size:var(--fs-sm);color:var(--c-danger);background:none;margin-right:var(--sp-1)}
.pur-lamp.on{border-style:solid;border-color:var(--c-ok);color:var(--c-ok);background:var(--c-hover)}
.pur-view .gr-card,.pur-view .pe-card{border:var(--bw-sub) solid var(--c-line);border-radius:var(--r-2);margin:var(--sp-3) 0}
.pur-view .gr-card summary{display:flex;gap:var(--sp-4);align-items:center;height:var(--h-xl);padding:0 var(--sp-3);cursor:pointer}
.pur-view .gr-card.is-void summary{opacity:.6;text-decoration:line-through}
.pur-view .ver-stamp{border:var(--bw-hair) solid var(--c-warn);color:var(--c-warn);padding:0 var(--sp-2);font-size:var(--fs-sm)}
.pur-view .gr-items{width:100%;margin-bottom:var(--sp-3)}
.pur-view .gr-items input[type=text]{width:100%;box-sizing:border-box}
.pur-view .gr-items .manual{background-color:var(--c-hover) !important}
.pur-view .gr-items .btn-del-row{background:none;border:0;cursor:pointer;color:var(--c-text-2);font-size:var(--fs-md);padding:0 var(--sp-2)}
.pur-view .gr-items .btn-del-row:hover{color:var(--c-danger)}
.pur-view .gr-items .sum-label{font-weight:var(--fw-semi)}
.pur-view .gr-items input.readonly{background:var(--c-sunken);color:var(--c-text-2)}
.pur-view .gr-card summary .pur-chip.chip-void,.pur-chip.chip-void{background:var(--c-danger-bg);color:var(--c-danger)}
.pur-view .gr-card .gr-attach,.pur-view .pe-card .pe-attach-row{border-top:var(--bw-hair) solid var(--c-line);padding-top:var(--sp-3);margin-top:var(--sp-3)}
.pur-view .att-note{display:inline-flex;gap:var(--sp-2)}.att-note input{width:18em}
.pur-chip.miss{background:var(--c-surface);border:var(--bw-hair) dashed var(--c-danger);color:var(--c-danger)}
.pur-file-row .shot{width:var(--h-xl);height:var(--h-xl);object-fit:cover}
.pur-view .pe-card summary{display:flex;gap:var(--sp-4);align-items:center;height:var(--h-xl);padding:0 var(--sp-3);cursor:pointer}
.pur-view .pe-card.is-void summary{opacity:.6;text-decoration:line-through}
.pur-view .pe-card.is-prepaid{border-color:var(--c-warn)}
.pur-view .pe-card summary .pur-chip.chip-void{background:var(--c-danger-bg);color:var(--c-danger)}
.pur-chip.pay-none{background:var(--c-head)}
.pur-chip.pay-due{background:var(--c-note-bg)}
.pur-chip.pay-paid{background:var(--c-hover)}
.pur-chip.pay-refund{background:var(--c-danger-bg)}
.pur-view .pe-frozen .groupbox{opacity:.85}
.pur-view .pe-lines{width:100%;margin-bottom:var(--sp-3)}
.pur-view .pe-lines input[type=text],.pur-view .pe-lines select{width:100%;box-sizing:border-box}
.pur-view .pe-lines .btn-del-row{background:none;border:0;cursor:pointer;color:var(--c-text-2);font-size:var(--fs-md);padding:0 var(--sp-2)}
.pur-view .pe-lines .btn-del-row:hover{color:var(--c-danger)}
.pur-view .pe-lines .sum-label{font-weight:var(--fw-semi)}
.pur-view .pe-lines .sum-breakdown{font-size:var(--fs-md)}
.pur-chip.done{background:var(--c-ok);color:var(--c-on-dark)}
.pur-view .pe-stamp{border:var(--bw-hair) solid var(--c-link);color:var(--c-link);padding:0 var(--sp-2);font-size:var(--fs-sm)}
.pur-view form#purSlipForm{display:block;width:100%}
.pur-view .is-manual{color:var(--c-ok) !important}
.pur-view .kv-f.hist-diff > span{background:var(--c-note-bg)}   /* 지난 판 보기 — 지금과 다른 칸(이름표 · 값 칸 꼴) */
/* 날짜 달력이 창(.modal.window) 및 상단바 위로 올라오도록 (필드값-013) */
#air-datepicker-global-container, .air-datepicker { z-index: 10000; }
.pq-c-cd { width: 13ch; } .pq-c-unit { width: 7ch; } .pq-c-qty { width: 6ch; } .pq-c-price { width: 9ch; }
/* 품목 표 — 소제목 줄(.view-sec) 바로 아래에 붙는다(헤더 표와 디테일 표 사이 틈은 소제목 한 줄뿐, 2026-10-10 "벌어져있고") */
.pq-lines { width: 100%; margin: 0 0 var(--sp-3); font-size: var(--fs-md); }
.pq-detail .view-sec > .dg-bar { margin: 0; }
.inplace.is-edit .view-sec > .dg-bar.ip-rw-block { display: flex; }   /* 공용 .ip-rw-block 은 block — 단추줄은 flex */
.pq-detail .pq-memo { white-space: pre-wrap; }
/* 품목 표 고치는 꼴 — 입력칸이 칸을 꽉 채운다 */
.pq-detail .ip-rw-rows td input:not([type=checkbox]) { width: 100%; height: var(--h-md); box-sizing: border-box; border: 1px solid var(--c-line); border-radius: 0; padding: 0 var(--sp-2); font-size: var(--fs-md); font-family: inherit; background: var(--c-surface); }
.pq-detail .ip-rw-rows td input[name$="-prod_cd"] { cursor: pointer; }

/* 폰(대표님 2026-10-11 "표때문에 범위 벗어나서 스크롤") — 목록은 견적일 · 거래처 · 합계만(.pq-pc 는 PC 에서만), 디테일표는 제 상자 안에서만 가로로 밀리고 보기 판은 안 밀린다 */
.pq-lines-wrap { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
@media (max-width: 700px) {
  .pq-pc { display: none; }
  .pq-detail { overflow-x: hidden; }
  .pq-lines-wrap .pq-lines { min-width: calc(var(--label-w) * 9); }   /* 폰만 — 표 상자 안 가로 스크롤(PC 는 열이 칸 폭에 맞춰 줄어든다, 대표님 2026-10-11 "불필요한 스크롤 자제") */
}
/* 품목줄 코드칸(2026-10-11 "품목 열 · 단위 열 간격 일그러짐") — 칸 안에서 돋보기 · 글자 · 꼬리표가 칸 폭을 넘지 않게. 단위는 이름 꼬리를 숨긴다(코드가 곧 단위) */
.pq-lines td .lookup-box { display: flex; align-items: center; min-width: 0; width: 100%; }
.pq-lines td .lookup-box .key-box { flex: 1 1 auto; min-width: 0; }
.pq-lines td .lookup-box .lookup-name { flex: 0 1 auto; min-width: 0; max-width: 5em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pq-lines td:has(input[name$="-unit"]) .lookup-name { display: none !important; }
.pq-lines td:has(input[name$="-unit"]) .lookup-box.is-matched input[data-lookup] { color: inherit; }
.pq-tag.pq-tbd { background: var(--c-warn-bg, var(--c-head)); color: var(--c-warn, var(--c-text-2)); }

/* ---------------- 회계(acct) — 매출 · 매입 색 (2026-10-12, 토큰만) ---------------- */
.acct-kind-sales { color: var(--c-primary); font-weight: var(--fw-semi); }
.acct-kind-purchase { color: var(--c-danger); font-weight: var(--fw-semi); }

/* ---------------- 회계(acct) — 승인번호 펼침 한 장 (2026-10-12, 토큰만) ---------------- */
.acct-sheet-row > td { background: var(--c-sunken); padding: var(--sp-3); }
.acct-sheet {
  border: var(--bw-head) solid var(--c-primary);
  background: var(--c-surface);
  font-size: var(--fs-md);
  color: var(--c-text);
  margin-bottom: var(--sp-2);
}
.acct-sheet .acct-sheet-lbl {
  color: var(--c-text-2);
  background: var(--c-head);
  padding: var(--sp-1) var(--sp-2);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-right: var(--bw-hair) solid var(--c-line);
  border-bottom: var(--bw-hair) solid var(--c-line);
}
.acct-sheet .acct-sheet-val {
  color: var(--c-text);
  padding: var(--sp-1) var(--sp-2);
  display: flex;
  align-items: center;
  border-right: var(--bw-hair) solid var(--c-line);
  border-bottom: var(--bw-hair) solid var(--c-line);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.acct-sheet .acct-sheet-val.num {
  justify-content: flex-end;
  text-align: right;
}
.acct-sheet-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--sp-2) var(--sp-4);
  border-bottom: var(--bw-head) solid var(--c-primary);
}
.acct-sheet-title {
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  color: var(--c-primary);
  letter-spacing: var(--sp-2);
}
.acct-sheet-approval {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.acct-sheet-approval .acct-sheet-lbl {
  border: var(--bw-hair) solid var(--c-line);
}
.acct-sheet-approval .acct-sheet-val {
  border: var(--bw-hair) solid var(--c-line);
  font-family: var(--font-mono);
  font-weight: var(--fw-semi);
}
.acct-sheet-parties {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: var(--bw-head) solid var(--c-primary);
}
.acct-party-supplier {
  display: grid;
  grid-template-columns: var(--h-xl) 1fr;
  border-right: var(--bw-head) solid var(--c-primary);
}
.acct-party-buyer {
  display: grid;
  grid-template-columns: var(--h-xl) 1fr;
}
.acct-party-supplier .acct-party-band {
  background: var(--c-danger-bg);
  color: var(--c-danger);
  font-weight: var(--fw-bold);
  writing-mode: vertical-rl;
  text-orientation: upright;
  display: flex;
  align-items: center;
  justify-content: center;
  letter-spacing: var(--sp-4);
  border-right: var(--bw-hair) solid var(--c-line);
}
.acct-party-buyer .acct-party-band {
  background: var(--c-selected);
  color: var(--c-primary);
  font-weight: var(--fw-bold);
  writing-mode: vertical-rl;
  text-orientation: upright;
  display: flex;
  align-items: center;
  justify-content: center;
  letter-spacing: var(--sp-2);
  border-right: var(--bw-hair) solid var(--c-line);
}
.acct-party-supplier .acct-party-grid .acct-sheet-lbl {
  background: var(--c-danger-bg);
}
.acct-party-buyer .acct-party-grid .acct-sheet-lbl {
  background: var(--c-selected);
}
.acct-party-grid {
  display: grid;
  grid-template-columns: 7em 1fr 7em 1fr;
}
.acct-sheet .acct-span-3 {
  grid-column: span 3;
}
.acct-sheet-summary {
  display: grid;
  grid-template-columns: 12ch 1fr 1fr 12ch 1fr;
  border-bottom: var(--bw-head) solid var(--c-primary);
}
.acct-sheet-items {
  border-bottom: var(--bw-head) solid var(--c-primary);
}
.acct-sheet-item-head {
  display: grid;
  grid-template-columns: 4ch 4ch 1fr 10ch 6ch 10ch 12ch 10ch 1fr;
  background: var(--c-head);
  color: var(--c-text-2);
  text-align: center;
}
.acct-sheet-item-head span {
  padding: var(--sp-1) var(--sp-2);
  border-right: var(--bw-hair) solid var(--c-line);
  border-bottom: var(--bw-hair) solid var(--c-line);
}
.acct-sheet-item-row {
  display: grid;
  grid-template-columns: 4ch 4ch 1fr 10ch 6ch 10ch 12ch 10ch 1fr;
  text-align: center;
}
.acct-sheet-item-row span {
  padding: var(--sp-1) var(--sp-2);
  border-right: var(--bw-hair) solid var(--c-line);
  border-bottom: var(--bw-hair) solid var(--c-line);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.acct-sheet-item-row span.num {
  justify-content: flex-end;
  text-align: right;
}
.acct-sheet-footer {
  display: grid;
  grid-template-columns: 2fr 3fr 1.5fr;
}
.acct-sheet-total {
  display: grid;
  grid-template-columns: 7em 1fr;
}
.acct-sheet-total .acct-total-val {
  font-weight: var(--fw-semi);
  font-size: var(--fs-lg);
  color: var(--c-text);
}
.acct-sheet-settle {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.acct-sheet-settle > div {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.acct-sheet-claim {
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: var(--bw-hair) solid var(--c-line);
  color: var(--c-text-2);
}


/* --- veh-svc- (정비내역 서류 제자리 편집) --- */
.inplace.is-edit .veh-svc-radio { display: inline-flex; align-items: center; gap: var(--sp-3); }
.veh-svc-radio label { display: inline-flex; align-items: center; gap: var(--sp-1); margin: 0; font-weight: normal; cursor: pointer; }
.veh-svc-radio > div, .veh-svc-radio div { display: inline-flex; align-items: center; gap: var(--sp-3); flex-wrap: nowrap; }
.veh-svc-radio label { white-space: nowrap; width: auto; }
.inplace.is-edit .kv-f > span > .ip-rw.veh-svc-radio { display: inline-flex; }
.veh-svc-lines-wrap { overflow-x: auto; }
.veh-svc-lines { width: 100%; table-layout: fixed; }
.veh-svc-c-no { width: 3.5ch; text-align: center; }
.veh-svc-c-part { width: 12ch; }
.veh-svc-c-cd { width: 10ch; }
.veh-svc-c-name { min-width: 13ch; }
.veh-svc-c-spec { width: 8ch; }
.veh-svc-c-qty { width: 6ch; text-align: right; }
.veh-svc-c-price { width: 10ch; text-align: right; }
.veh-svc-c-amt { width: 11ch; text-align: right; }
.veh-svc-c-vat { width: 10ch; text-align: right; }
.veh-svc-c-total { width: 11ch; text-align: right; }
.veh-svc-c-remarks { min-width: 10ch; }
.veh-svc-part-refs { display: flex; flex-wrap: wrap; gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); font-size: var(--fs-xs); color: var(--c-text-2); background: var(--c-surface); border-bottom: 1px solid var(--c-line); }
.veh-svc-part-ref { display: inline-flex; gap: var(--sp-1); }
.veh-svc-part-ref b { color: var(--c-text); font-weight: var(--fw-bold); }
.veh-svc-summary { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: flex-end; padding: var(--sp-2) var(--sp-3); font-size: var(--fs-sm); border-bottom: 1px solid var(--c-line); background: var(--c-surface); }
.veh-svc-summary b { color: var(--c-text); font-weight: var(--fw-bold); }
.veh-svc-zone { display: flex; flex-direction: column; gap: var(--sp-1); padding: var(--sp-2) var(--sp-3); border-top: 1px solid var(--c-line); }
.veh-svc-link-row { display: flex; gap: var(--sp-3); font-size: var(--fs-sm); }
.veh-svc-link-lbl { width: 130px; color: var(--c-text-2); }
.veh-svc-link-val { color: var(--c-text); }
.veh-svc-upload { padding: var(--sp-2) 0; }
.veh-svc-errs { color: var(--c-danger); font-size: var(--fs-sm); margin: var(--sp-1) 0; }

/* ---- 차량 정비 부위 와이어프레임 (차량 부위 그림 SVG) ---- */
.veh-wire-wrap {
  width: 100%;
  margin: var(--sp-3) 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
.veh-wire-wrap.is-hide {
  visibility: hidden;
  pointer-events: none;
}
.veh-wire-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: var(--fs-xs);
  color: var(--c-text-3);
}
.veh-wire-svg {
  width: 100%;
  height: auto;
  display: block;
}
.veh-wire-line {
  stroke: var(--c-line-strong);
  fill: none;
  stroke-width: 1.5;
}
.veh-wire-body {
  stroke: var(--c-line-strong);
  fill: var(--c-surface);
  stroke-width: 1.5;
}
.veh-wire-bed {
  stroke: var(--c-line);
  fill: none;
  stroke-width: 1.5;
}
.veh-wire-glass {
  stroke: var(--c-line-strong);
  fill: var(--c-sunken);
  stroke-width: 1.5;
}
.veh-wire-frame {
  stroke: var(--c-line);
  fill: none;
  stroke-width: 1.2;
}
.veh-wire-axle {
  stroke: var(--c-line-strong);
  fill: var(--c-line-strong);
  stroke-width: 3.5;
}
.veh-wire-guide {
  stroke: var(--c-line);
  stroke-width: 1;
  stroke-dasharray: 2, 2;
  fill: none;
}
.veh-wire-hit {
  cursor: pointer;
  transition: all 0.15s ease;
}
.veh-wire-hit:focus-visible {
  outline: 2px solid var(--c-link);
  outline-offset: 2px;
}
.veh-wire-hit .veh-wire-part {
  stroke: var(--c-line-strong);
  fill: var(--c-surface);
  stroke-width: 1.5;
  transition: fill 0.15s ease, stroke 0.15s ease;
}
.veh-wire-hit .veh-wire-tire {
  fill: var(--c-text-2);
  stroke: var(--c-line-strong);
  stroke-width: 1.5;
  transition: fill 0.15s ease, stroke 0.15s ease;
}
.veh-wire-hit .veh-wire-tread {
  stroke: var(--c-surface);
  stroke-width: 1.2;
  fill: none;
}
.veh-wire-hit .veh-wire-icon {
  stroke: var(--c-line-strong);
  fill: var(--c-surface);
  stroke-width: 1.5;
  transition: fill 0.15s ease, stroke 0.15s ease;
}
.veh-wire-oil-accent {
  fill: var(--c-warn);
  stroke: none;
}
.veh-wire-hit[data-part="ENG_OIL"] .veh-wire-icon {
  stroke: var(--c-warn);
}
.veh-wire-hit:hover .veh-wire-part,
.veh-wire-hit:hover .veh-wire-icon {
  stroke: var(--c-link);
  fill: var(--c-selected);
}
.veh-wire-hit:hover .veh-wire-tire {
  stroke: var(--c-link);
}
.veh-wire-hit.has-history .veh-wire-part,
.veh-wire-hit.has-hist .veh-wire-part,
.veh-wire-hit.has-history .veh-wire-icon,
.veh-wire-hit.has-hist .veh-wire-icon,
.veh-wire-hit.has-history .veh-wire-tire,
.veh-wire-hit.has-hist .veh-wire-tire {
  stroke: var(--c-text);
  stroke-width: 2;
}
.veh-wire-hit.is-selected .veh-wire-part,
.veh-wire-hit.is-on .veh-wire-part,
.veh-wire-hit.is-selected .veh-wire-icon,
.veh-wire-hit.is-on .veh-wire-icon {
  fill: var(--c-selected);
  stroke: var(--c-link);
  stroke-width: 2;
}
.veh-wire-hit.is-selected .veh-wire-tire,
.veh-wire-hit.is-on .veh-wire-tire {
  fill: var(--c-link);
  stroke: var(--c-link);
  stroke-width: 2;
}
.veh-wire-text {
  font-size: var(--fs-sm);
  fill: var(--c-text-3);
  text-anchor: middle;
  dominant-baseline: central;
  pointer-events: none;
  user-select: none;
  paint-order: stroke fill;
  stroke: var(--c-surface);
  stroke-width: 3px;
  stroke-linejoin: round;
}
.veh-wire-hit.is-selected .veh-wire-text,
.veh-wire-hit.is-on .veh-wire-text {
  fill: var(--c-link);
  font-weight: var(--fw-semi);
}
.veh-wire-subtext {
  font-size: var(--fs-xs, var(--fs-xs));
  fill: var(--c-text-3);
  dominant-baseline: central;
  pointer-events: none;
  user-select: none;
  paint-order: stroke fill;
  stroke: var(--c-surface);
  stroke-width: 3px;
  stroke-linejoin: round;
}
.veh-wire-hit.is-selected .veh-wire-subtext,
.veh-wire-hit.is-on .veh-wire-subtext {
  fill: var(--c-link);
}
.veh-wire-empty {
  color: var(--c-text-3);
  font-size: var(--fs-xs);
  margin: var(--sp-1) 0;
}

/* 정비 부위 그림 — 승인한 트럭 PNG 위 투명 누르는 자리 (2026-10-12) */
.veh-wire-wrap.is-hide { visibility: hidden; }
.veh-wire-svg { display: block; width: 100%; height: auto; max-height: 320px; }
.veh-wire-zone { fill: transparent; stroke: transparent; stroke-width: 6; }
.veh-wire-hit { cursor: pointer; outline: none; }
.veh-wire-hit:hover .veh-wire-zone, .veh-wire-hit:focus-visible .veh-wire-zone { stroke: var(--c-link); fill: var(--c-selected); fill-opacity: .35; }
.veh-wire-hit.is-selected .veh-wire-zone { stroke: var(--c-link); stroke-width: 8; fill: var(--c-selected); fill-opacity: .55; }
.veh-wire-hit.has-hist:not(.is-selected) .veh-wire-zone { stroke: var(--c-line-strong); stroke-dasharray: 10 8; }
.veh-wire-lbl { font-size: 36px; font-weight: var(--fw-bold); fill: var(--c-text); pointer-events: none; }
.veh-wire-lbl-km { font-size: 31px; fill: var(--c-text-2); pointer-events: none; }
.veh-wire-lbl, .veh-wire-lbl-km { paint-order: stroke; stroke: var(--c-surface); stroke-width: 9px; stroke-linejoin: round; }   /* 그림 선 위에서도 읽히게 흰 테 */
.veh-wire-svg { max-height: 360px; }

.veh-wire-mark { stroke: var(--c-link); stroke-width: 8; fill: var(--c-selected); fill-opacity: .55; pointer-events: none; }

/* 기본정보 그림 부위 이력 — 떠 있는 창 + 잇는 선 (vehicle_wire_pop.js, 2026-10-12) */
.veh-wire-wrap[data-mode="view"] { position: relative; }
.veh-wire-pop-hit { cursor: pointer; outline: none; }
.veh-wire-pop-hit:hover .veh-wire-zone, .veh-wire-pop-hit:focus-visible .veh-wire-zone { stroke: var(--c-link); fill: var(--c-selected); fill-opacity: .35; }
.veh-wire-pop-hit.is-selected .veh-wire-zone { stroke: var(--c-link); stroke-width: 8; fill: var(--c-selected); fill-opacity: .5; }
.veh-wire-pop-hit.has-hist:not(.is-selected) .veh-wire-zone { stroke: var(--c-line-strong); stroke-dasharray: 10 8; }
.veh-wire-link { position: fixed; left: 0; top: 0; pointer-events: none; overflow: visible; display: none; z-index: 999; }
.veh-wire-link line { stroke: var(--c-link); stroke-width: 2; }
.veh-wire-link circle { fill: var(--c-link); }


/* 정비 부위 권장 교환주기 임박(노랑/주황 깜빡임) · 경과(빨강 깜빡임) (2026-10-12) */
@keyframes veh-due-blink { 0%, 100% { fill-opacity: .15; } 50% { fill-opacity: .6; } }
.due-soon .veh-wire-zone, .veh-wire-pop-hit.due-soon .veh-wire-zone, .veh-wire-hit.due-soon .veh-wire-zone { stroke: var(--c-warn); stroke-width: 8px; fill: var(--c-warn-bg, var(--c-warn)); animation: veh-due-blink 1.2s ease-in-out infinite; }
.due-over .veh-wire-zone, .veh-wire-pop-hit.due-over .veh-wire-zone, .veh-wire-hit.due-over .veh-wire-zone { stroke: var(--c-danger); stroke-width: 8px; fill: var(--c-danger); animation: veh-due-blink .8s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .due-soon .veh-wire-zone, .due-over .veh-wire-zone { animation: none; fill-opacity: .4; } }

/* 권장 교환주기 팝업 요약 및 마스터 설정 창 (2026-10-12) */
.veh-wire-pop-summary { font-size: var(--fs-xs); color: var(--c-text-2); padding: var(--sp-1) var(--sp-2); margin-bottom: var(--sp-1); border-bottom: 1px solid var(--c-line); }
.veh-svcint-win { max-width: 760px; width: 100%; }
.veh-svcint-scope { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-3); font-weight: var(--fw-semi); }
.veh-svcint-grid { width: 100%; }
.veh-svcint-grid .ipt { width: 100%; min-width: 80px; }
.veh-svcint-hint { font-size: var(--fs-xs); color: var(--c-text-3); margin-top: var(--sp-1); }


/* 떠 있는 창 = 원래 창 꼴(.modal.window) 그대로, 자리만 그림 아래 — 회색 바탕(backdrop) 없음 */
.modal.window.veh-wire-pop { position: fixed; transform: none; width: 780px; max-width: calc(100vw - 16px); z-index: 1000; }
.modal.window.veh-wire-pop[hidden] { display: none; }
.veh-wire-pop .modal-body { padding: var(--sp-4) var(--sp-6); }
.veh-wire-pop .veh-wire-pop-summary { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); color: var(--c-text-2); }

/* 부위 이력 창 열 폭 — 날짜 · km 는 글자만큼, 부위 · 정비 번호는 다 보이게, 품목명이 남는 폭 */
.veh-pop-grid { table-layout: fixed; width: 100%; }
.veh-pop-grid col.vph-date { width: 11ch; } .veh-pop-grid col.vph-km { width: 12ch; } .veh-pop-grid col.vph-part { width: 17ch; }
.veh-pop-grid col.vph-total { width: 10ch; } .veh-pop-grid col.vph-no { width: 17ch; }
.veh-pop-grid td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 왼쪽 "연 차량" 창 분류 머리줄 — 같은 층위 · 삼각형 없음, 머리줄 = 고르기(오른쪽 목록) + 펼치기 (2026-10-12) */
.veh-cat-row { justify-content: space-between; gap: var(--sp-3); height: 26px; line-height: 26px; padding: 0 var(--sp-4); }
.veh-cat-link { flex: 1 1 auto; min-width: 0; color: var(--c-text); text-decoration: none; font-weight: var(--fw-semi); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.veh-cat-link:hover { text-decoration: none; color: var(--c-link); }
.veh-cat-n { font-weight: var(--fw-normal); color: var(--c-text-3); font-size: var(--fs-sm); margin-left: var(--sp-2); }
.veh-cat-row.on { background: var(--c-selected); box-shadow: inset 3px 0 0 var(--c-link); }
.veh-cat-row.on .veh-cat-link { color: var(--c-link); }
.veh-cat.is-open > .veh-cat-row { border-bottom: 1px solid var(--c-line); }
/* 차량 목록 열 폭 — 날짜는 다 보이게(YYYY-MM-DD), 번호 · 차종 · 연식 · 소유 · 담당은 글자만큼, 차명 · 비고가 남는 폭 */
.veh-grid col.vc-plate { width: 12ch; } .veh-grid col.vc-kind { width: 8ch; } .veh-grid col.vc-year { width: 6ch; }
.veh-grid col.vc-own { width: 7ch; } .veh-grid col.vc-mgr { width: 7ch; } .veh-grid col.vc-date { width: 11.5ch; }
.veh-grid col.vc-model, .veh-grid col.vc-memo { width: auto; }

.veh-cat-body[hidden] { display: none; }

/* 차량정보 표준화(대표님 2026-10-12 "스타일이 하나도 일관성이 없음") — 24조 디자인 시스템 그대로
   · 분류 머리줄 = 트리 머리(.tree-cap 꼴 — 회색 띠 · 굵게), 고르면 파란 칠(--c-selected) + 왼쪽 파란 줄
   · 그 아래 줄 = 트리 아래층(.tree-sub 꼴 — 한 칸 들여 왼쪽 안내선, 고른 분류면 파랑). 고른 줄도 파란 칠(노랑 아님)
   · 칸 사이 세로줄 없음 · 왼쪽에는 더하기 단추 없음([신규] 는 오른쪽 목록 머리줄) */
.veh-openwin .veh-cat { border-bottom: none; }
.veh-openwin .veh-cat-row { background: var(--c-head); border-top: 1px solid var(--c-line); border-bottom: 1px solid var(--c-line); margin-top: -1px; }
.veh-openwin .veh-cat:first-child .veh-cat-row { margin-top: 0; border-top: none; }
.veh-openwin .veh-cat-row:hover { background: var(--c-hover); }
.veh-openwin .veh-cat-row.on { background: var(--c-selected); box-shadow: inset 3px 0 0 var(--c-link); }
.veh-openwin .veh-cat-body, .veh-group-slips { margin: var(--sp-1) 0 var(--sp-1) var(--sp-4); border-left: var(--bw-head) solid var(--c-line); }
.veh-openwin .veh-cat-row.on + .veh-cat-body { border-left-color: var(--c-primary); }
.veh-group-slips { margin-left: var(--sp-6); border-bottom: none; }

/* 칸 머리 도구줄 — 차량 목록(vehicle_list) · slip 목록(vehicle_slip_viewer) 같은 꼴:
   Search · Filter · Option · 사이 · [등록 ▾]/[신규](파랑) · 창 이름. 공용 .ex3-head(14px 이름표 자리 · 목록 칸 위 떠 있음)를 이긴다 */
.veh-page .ex3-head.veh-bar { display: flex; position: relative; top: auto; right: auto; z-index: 5; height: auto; min-height: 32px; justify-content: flex-start; align-items: center; gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); pointer-events: auto; border-bottom: 1px solid var(--border); background: var(--card-bg); box-sizing: border-box; flex-wrap: nowrap; }
.veh-page .veh-pane-view > .ex3-head.veh-bar { position: sticky; top: calc(-1 * var(--sp-2)); margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-3)) var(--sp-2); }
.veh-bar .spacer { flex: 1 1 auto; }
.veh-bar .veh-search { flex: 0 1 220px; width: 220px; }
.veh-bar .win-id { flex: none; margin-left: var(--sp-2); }
.veh-bar .btn { flex: none; white-space: nowrap; }
.veh-bar .spacer ~ .fn-menu .fn-list { right: 0; left: auto; }
.veh-bar-title { flex: none; font-weight: var(--fw-semi); font-size: var(--fs-md); white-space: nowrap; }
.veh-bar .page-count { flex: none; white-space: nowrap; }
.veh-list-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.veh-page .page-head .veh-chips { margin: 0 0 0 var(--sp-4); }

/* slip 목록 표(정비 · 보험처리 · 관리내역) — 차량 목록 표와 같은 꼴, 날짜 · 금액은 다 보이게 */
.veh-slip-grid { width: 100%; table-layout: fixed; border-collapse: collapse; font-size: var(--fs-md); }
.veh-slip-grid th, .veh-slip-grid td { height: 25px; padding: 0 var(--sp-3); text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-bottom: 1px solid var(--border); box-sizing: border-box; }
.veh-slip-grid th.num, .veh-slip-grid td.num { text-align: right; font-variant-numeric: tabular-nums; }
.veh-slip-grid thead th { background: var(--header-bg); color: var(--text-muted); font-weight: var(--fw-semi); font-size: var(--fs-sm); position: sticky; top: 0; z-index: 2; }
.veh-slip-grid col.vs-date { width: 11.5ch; } .veh-slip-grid col.vs-amt { width: 12ch; } .veh-slip-grid col.vs-att { width: 6ch; }
/* 회계 출처 칩(API · MCP) — 합칠 때 토큰으로(없는 --color-* · 날 색 걷음, 2026-10-12) */
.acct-chip { display: inline-block; padding: 0 var(--sp-2); border-radius: var(--r-round); font-size: var(--fs-sm); line-height: 1.6; }
.acct-src-api { background: var(--c-selected); color: var(--c-primary); }
.acct-src-mcp, .acct-src-clobe, .acct-src-demo { background: var(--c-head); color: var(--c-text-2); }


