﻿/* erp-steex.css — Steex 어댑터 (Steex ↔ ERP 화면 어휘 연결)
   ────────────────────────────────────────────────────────────
   기존 화면(뷰 100+)이 쓰는 ERP 전용 클래스를 Steex 의 CSS 변수(--tb-*)·
   네이티브 컴포넌트로 "별칭" 처리한다. 새 디자인을 만들지 않는다 — 색·간격은
   전부 Steex 변수 재사용. 뷰를 100개 고치는 대신 이 한 파일로 전 화면을 맞춘다.
   (Steex 원본 CSS 는 수정 금지 — 이 파일은 app.min.css '다음'에 로드) */

/* ── 목록 카드 : Steex 는 페이지 전체가 스크롤되는 구조(콘텐츠 높이 고정 없음) ──
   억지 내부 스크롤 대신 Steex 기본(페이지 스크롤)을 따른다 — 데모 표와 동일. *
   card-body 패딩만 0 으로(표가 카드 끝까지). */
.card-fill > .card-body { padding: 0; }

/* ── 목록 표: 데이터 왼쪽, 액션 오른쪽 끝. col-fit = 내용 폭만 ── */
.table-fit .col-fit { width: 1%; white-space: nowrap; }
.table-fit th, .table-fit td { white-space: nowrap; }
/* 목록 표 가로줄 — Steex table 은 기본 무테이므로 아래줄만 (데모 table 과 동일 톤) */
.table-bottom-border > :not(caption) > * > * { border-bottom: 1px solid var(--tb-border-color); }
/* 세로 구분선 — 열이 많은 업무 표는 행을 눈으로 따라가다 열을 놓친다.
   가로줄보다 연하게(55%) 넣어 격자가 튀지 않게 한다. 마지막 열은 카드 경계가 대신한다.
   color-mix 를 못 읽는 브라우저는 앞줄의 불투명 색으로 떨어진다(줄은 그대로 보인다). */
.table-bottom-border > :not(caption) > * > *:not(:last-child) {
    border-right: 1px solid var(--tb-border-color);
    border-right-color: color-mix(in srgb, var(--tb-border-color) 55%, transparent);
}

/* ══ Alina site.css 삭제로 정의가 사라진 클래스 되살리기 ══════════════════
   Steex 전환 때 site.css 를 지우면서 뷰에는 남았는데 스타일이 없어진 것들.
   화면이 조용히 깨져 있었으므로(사진·스크롤바·타임라인) 여기서 최소한으로 정의한다.
   ※ JS 훅(btn-edit·btn-excel·sortable-table 등)은 CSS 가 필요 없어 대상이 아니다. */

/* 표 내부 스크롤 영역 — 얇은 스크롤바(정품 데모 톤) */
.app-scroll { scrollbar-width: thin; }
.app-scroll::-webkit-scrollbar { width: 6px; height: 6px; }
.app-scroll::-webkit-scrollbar-thumb { background: var(--tb-border-color); border-radius: 3px; }
.app-scroll::-webkit-scrollbar-thumb:hover { background: var(--tb-secondary-color); }

/* 사원 사진(인사카드 등록·수정 화면) — 목록/상세와 같은 원형 아바타 톤 */
.emp-av, .emp-av-lg {
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; overflow: hidden; background: var(--tb-tertiary-bg);
    color: var(--tb-secondary-color); flex-shrink: 0;
}
.emp-av { width: 48px; height: 48px; font-size: 20px; }
.emp-av-lg { width: 120px; height: 120px; font-size: 40px; }
.emp-av img, .emp-av-lg img { width: 100%; height: 100%; object-fit: cover; }
.emp-sub { color: var(--tb-secondary-color); font-size: .9em; }

/* 조직도 트리 — Alina 타임라인 대체(세로선 + 노드) */
.app-timeline-box { position: relative; padding-left: 1.25rem; }
.app-timeline-box::before {
    content: ""; position: absolute; left: .35rem; top: .25rem; bottom: .25rem;
    border-left: 1px dashed var(--tb-border-color);
}
.timeline-section { position: relative; margin-bottom: .75rem; }
.timeline-icon { position: absolute; left: -1.25rem; top: .15rem; color: var(--tb-primary); }
.timeline-content { padding-left: .25rem; }
.d-flex-center { display: flex; align-items: center; justify-content: center; }
.emp-empty { color: var(--tb-secondary-color); padding: 2rem 0; text-align: center; }

/* ── 대시보드 스탯 카드(링크형) ──
   카드 전체를 <a> 로 감쌌으므로 링크 기본색이 아니라 카드 안 글자색을 그대로 쓰게 한다.
   (숫자·라벨이 파랗게 변하면 지표가 아니라 링크 목록처럼 보인다) */
a.card { color: inherit; }
a.card:hover .avatar-title { filter: brightness(.97); }

/* ── 사용 상태 필터 (목록 공통) ────────────────────────────────
   상태 셀렉트(#selStatus)가 tbody 에 data-status="y" 를 걸면 미사용(use_yn='n') 행을 감춘다.
   검색 필터는 화면별 js 가 inline style(display) 로 제어하므로, CSS 인 이 규칙과 서로
   간섭하지 않고 자연스럽게 AND 로 걸린다(둘 중 하나라도 숨기면 안 보임). */
tbody[data-status="y"] tr[data-use="n"] { display: none; }

/* ── 목록 표 가독성 (전 92개 목록 공통) ──────────────────────────────
   세로줄 없이 가로줄만 두고, 행에 숨 쉴 공간을 준다. 헤더는 조용하게 눌러
   "데이터가 주인공" 이 되게 한다 — 헤더가 굵고 진하면 눈이 매 줄 위쪽으로 끌려간다. */
.table-bottom-border > tbody > tr > td,
.table-bottom-border > thead > tr > th { padding-top: .62rem; padding-bottom: .62rem; }

.table-bottom-border > thead > tr > th {
    font-weight: 600;
    /* 컬럼명 글자색 — 사용자 지정값이다. 테마 본문색(--tb-body-color #0f1114)보다 한 톤 옅게 해서
       헤더가 데이터보다 앞으로 나오지 않게 한다. 대응하는 테마 변수가 없어 값을 여기서 한 번만 정의한다. */
    color: var(--erp-th-color);
    white-space: nowrap;
}
/* 마지막 행 밑줄 제거 — 카드 아래 테두리와 겹쳐 2px 로 두꺼워 보인다 */
.table-bottom-border > tbody > tr:last-child > * { border-bottom: 0; }

/* 숫자·코드·날짜는 자릿수를 맞춰 세로로 정렬되게(tabular) — 수량·금액 비교가 쉬워진다 */
.table td.text-end, .table td.text-center, .table td.num,
.table th.text-end, .table th.text-center { font-variant-numeric: tabular-nums; }

/* ── 목록은 페이지가 아니라 카드 안에서 스크롤 (데스크톱) ───────────────
   카드가 화면 아래까지 차지하고 표만 그 안에서 굴러간다. 검색·툴바(card-header)는 카드 위쪽에
   그대로 남고 컬럼명(thead)은 스크롤 컨테이너 기준 sticky 라 top:0 이면 된다.
   카드 높이는 화면마다 시작 위치가 달라(안내 배너·업로드 폼) erp-ux.js 가 실측해 넣는다.
   ※ 예전에는 페이지를 스크롤하고 card-header·thead 를 상단바(71px) 아래에 붙였는데,
     스크롤 막대가 창 오른쪽 끝에 생겨 표와 멀고 카드 경계 밖까지 내용이 흘렀다. */
@media (min-width: 992px) {
    .card-fill { display: flex; flex-direction: column; }
    /* 스크롤은 card-body 가 맡는다. 표를 감싼 form 처럼 클래스 없는 래퍼가 중간에 끼는 화면이 있어
       table-responsive 에 flex 를 걸면 체인이 끊긴다 — 몇 겹이 끼든 무관하게 여기서 자른다.
       min-height:0 이 없으면 flex 자식이 내용 높이만큼 부풀어 스크롤이 안 생긴다. */
    .card-fill > .card-body { flex: 1 1 auto; min-height: 0; overflow: auto; }
    .card-fill .table-responsive { overflow: visible; }   /* 안쪽 스크롤 해제 — 컨테이너가 둘이면 갇힌다 */

    .card-fill thead th {
        position: sticky; top: 0; z-index: 2;
        background: var(--tb-tertiary-bg);      /* 스크롤된 행이 헤더 뒤로 비쳐 보이지 않게 불투명 */
    }
    /* 고정된 헤더 아래 경계선 (sticky 는 border 가 잘려 보일 수 있어 가상요소로) */
    .card-fill thead th::after {
        content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
        border-bottom: 1px solid var(--tb-border-color);
    }
}

/* ── 툴바 아이콘 버튼(신규·삭제·엑셀) : Steex btn-icon 크기 + outline 톤 그대로 ──
   .btn-outline-* 는 Steex 네이티브라 색은 이미 맞다. 정사각 아이콘 버튼 크기만 준다. */
.btn.icon-btn.tb-btn {
    width: calc(var(--tb-btn-line-height) * 1em + 2 * var(--tb-btn-padding-y) + 2px);
    padding-left: 0; padding-right: 0; display: inline-flex; align-items: center; justify-content: center;
}

/* ── 행 액션(수정·미사용·복구) : 테두리 없는 아이콘, hover 때만 의미색 ──
   실측(FHD): 버튼이 20.7px 높이라 WCAG 최소 타깃 24px 에 못 미쳤고, 작은 아이콘을
   정확히 조준해야 했다. 행 높이(34.1px)는 밀도 때문에 늘릴 수 없으므로
   ① 가로는 padding 으로 조금 넓히고 ② 세로는 레이아웃을 건드리지 않는 판정 영역으로 넓힌다. */
.icon-act {
    position: relative;
    border: 0; background: transparent; padding: 2px 8px; font-size: 16px; line-height: 1;
    color: var(--tb-secondary-color); cursor: pointer; transition: color .12s ease;
}
/* 클릭 판정만 위아래로 넓힌다 — 행에 남는 여유(위아래 6.7px) 안이라 행 높이는 그대로다.
   ★가로로는 넓히지 않는다: 바로 옆이 '미사용'(빨강)이라, 빗나간 클릭이 파괴적 동작으로
     흘러가면 안 된다. 버튼 사이 4px 는 일부러 남기는 죽은 구역이다.
   ※ hover 배경은 두지 않는다(2026-07-29 사용자 결정) — 화면은 예전 그대로 두고
      조준성만 넓히는 것이 목적이다. 눌리는 범위는 hover 시 색 변화로만 알린다. */
.icon-act::after { content: ""; position: absolute; inset: -6px 0; }
.icon-act:hover, .icon-act:focus-visible { color: var(--tb-primary); }               /* 수정=파랑 */
.icon-act.act-danger:hover, .icon-act.act-danger:focus-visible { color: var(--tb-danger); }   /* 미사용=빨강 */
.icon-act.act-success:hover, .icon-act.act-success:focus-visible { color: var(--tb-success); } /* 복구=초록 */

/* ── 상태·회사 배지 : Steex 서브틀 배지로 별칭 (bg-*-subtle text-*) ── */
.badge.text-outline-primary   { background: var(--tb-primary-bg-subtle);   color: var(--tb-primary-text-emphasis); }
.badge.text-outline-secondary { background: var(--tb-secondary-bg-subtle); color: var(--tb-secondary-color); }
.badge.text-outline-success   { background: var(--tb-success-bg-subtle);   color: var(--tb-success-text-emphasis); }
.badge.text-outline-danger    { background: var(--tb-danger-bg-subtle);    color: var(--tb-danger-text-emphasis); }
.badge.text-outline-warning   { background: var(--tb-warning-bg-subtle);   color: var(--tb-warning-text-emphasis); }
.badge.text-outline-info      { background: var(--tb-info-bg-subtle);      color: var(--tb-info-text-emphasis); }

/* ── 검색줄 : Steex search-box(돋보기 내장)와 같은 톤. 아이콘은 입력 안 왼쪽 ── */
.apps-search { position: relative; }
.apps-search > input { padding-left: 2.5rem; }
.apps-search > i { position: absolute; left: 0.9rem; top: 50%; transform: translateY(-50%); }

/* ── 상단바 아이콘 버튼 : 한 세트로 보이게 ────────────────────────
   회사·전체화면·글자크기 버튼에 옅은 원형 테두리를 둘러 "누를 수 있는 것" 임을 알린다.
   (아이콘만 떠 있으면 장식인지 버튼인지 구분이 안 된다)
   아이콘은 전부 FA5 Regular·fs-lg 로 통일 — 예전엔 Bootstrap Icons·Light 가 섞여 굵기가 제각각이었다. */
#page-topbar .btn-topbar.rounded-circle {
    border: 1px solid var(--tb-border-color);
    width: 38px; height: 38px;
    display: inline-flex; align-items: center; justify-content: center;
    transition: border-color .12s, background-color .12s, color .12s;
}
#page-topbar .btn-topbar.rounded-circle:hover,
#page-topbar .btn-topbar.rounded-circle[aria-expanded="true"] {
    border-color: var(--tb-primary);
    color: var(--tb-primary);
}

/* ── 폼 검증 표시 ──────────────────────────────────────────
   Steex 빌드에는 Bootstrap 의 `.was-validated :invalid` 규칙이 빠져 있다(변수 --tb-form-invalid-* 는 있음).
   그래서 필수항목을 비우고 저장해도 어느 칸이 문제인지 화면에 표시되지 않았다 → 여기서 정의한다.
   erp-ux.js 가 제출 시 폼에 was-validated 를 붙이고 첫 오류 칸으로 포커스를 옮긴다. */
.was-validated .form-control:invalid,
.was-validated .form-select:invalid,
.form-control.is-invalid, .form-select.is-invalid {
    border-color: var(--tb-form-invalid-border-color);
}
.was-validated .form-control:invalid:focus,
.was-validated .form-select:invalid:focus,
.form-control.is-invalid:focus, .form-select.is-invalid:focus {
    border-color: var(--tb-form-invalid-border-color);
    /* 포커스 링은 테마 danger 색을 그대로 옅게 — 예전엔 같은 색을 rgba(225,91,96) 로 베껴 적어
       테마 색이 바뀌면 테두리(변수)와 링(리터럴)이 서로 다른 빨강이 될 수 있었다 */
    box-shadow: 0 0 0 .2rem rgba(var(--tb-danger-rgb), .18);
}
/* 라벨도 함께 붉게 — 스크롤된 긴 폼에서 어느 항목인지 빨리 찾게 */
.was-validated .form-control:invalid ~ .invalid-feedback,
.was-validated .form-select:invalid ~ .invalid-feedback { display: block; }

/* ══ 모달(등록·수정 폼) UX — 전 78개 공통 ══════════════════════════
   ① 긴 폼에서 제목·저장버튼이 화면 밖으로 밀리지 않게 : 본문만 스크롤하고 헤더·푸터는 제자리.
      (Bootstrap 의 modal-dialog-scrollable 과 같은 효과를 클래스 추가 없이 전 모달에 적용) */
.modal-dialog { max-height: calc(100% - 3.5rem); }
.modal-content { max-height: 100%; }
.modal-body { overflow-y: auto; }

/* ② 헤더·푸터 배경은 두지 않는다 — 테마 기본 구분선(header 아래·footer 위)만으로 충분히 나뉘고,
      배경을 깔면 모달이 무거워 보인다(§8.1 테마 기본값 존중). */

/* ③ 읽기전용 칸(수정 시 코드 등)은 배경을 눌러 '고칠 수 없는 칸' 임을 알린다.
      기존엔 readonly 여도 흰 배경이라 왜 입력이 안 되는지 알 수 없었다. */
.modal .form-control[readonly]:not(.form-control-plaintext) {
    background-color: var(--tb-tertiary-bg);
    color: var(--tb-secondary-color);
    cursor: not-allowed;
}

/* ④ 필수 표시(*)를 또렷하게 — 라벨 끝에서 눈에 걸리게 */
.form-label .text-danger { font-weight: 700; margin-left: .1rem; }

/* ⑤ 라벨을 누르면 입력칸으로 포커스가 가므로(for 연결) 손가락 모양으로 알린다 */
.modal .form-label[for] { cursor: pointer; }

/* ── 모달 폼 구역 : 제목 + 아래 구분선 (Steex 변수) ── */
.form-section + .form-section { margin-top: 1.75rem; }
/* 크기는 본문 눈금을 따른다 — 고정 px 를 박으면 글자 크기 토글에 반응하지 않고,
   QHD(본문 14px)에서 구역 제목이 본문보다 작아지는 역전이 생겼다(§8.2). */
.form-section-title {
    font-size: var(--erp-fs); font-weight: 600; color: var(--tb-heading-color);
    margin: 0 0 .75rem; padding-bottom: .4rem; border-bottom: 1px solid var(--tb-border-color);
}

/* ── 헤더 클릭 정렬 표식 (js/table.js · 3단계: 없음 → ▲ → ▼ → 없음) ──
   평상시엔 아이콘을 감춰 표를 깔끔하게 두고, 마우스를 올렸을 때만 흐린 세모로
   "누르면 정렬됨" 을 알린다. 정렬 중인 컬럼만 진한 세모로 남는다. */
th.sortable-th { cursor: pointer; user-select: none; }
th.sortable-th:hover { color: var(--tb-primary); }
.sort-ico {
    font-size: .9em; margin-left: .25rem;
    opacity: 0;                              /* 자리는 차지 — 클릭 때 글자가 밀리지 않게 */
}
/* hover 힌트 아이콘은 두지 않는다 — 3클릭으로 정렬을 푼 뒤에도 마우스가 헤더 위에 남아
   세모가 계속 보이면 "아직 정렬 중" 으로 오해돼 1↔2단계를 오가는 느낌을 준다.
   누를 수 있다는 신호는 커서(pointer)와 헤더 글자색 변화로 충분하다. */
th.sorted .sort-ico { opacity: 1; color: var(--tb-primary); }   /* 정렬 중일 때만 표시 */
th.sorted { color: var(--tb-primary); }

/* ── 폭 유틸(인라인 style 대체, 전 화면 공용) ── */
.w-300 { width: 300px; max-width: 100%; }
.w-250 { width: 250px; max-width: 100%; }
/* 목록 헤더 검색창 표준 폭 — search-box 는 왼쪽 돋보기 자리로 40px 를 먹으므로
   가장 긴 안내문구("거래처코드 · 거래처명 · 대표자 검색" = 212px)에 패딩 54px 를 더해 300 으로 잡는다.
   더 짧아지면 문구가 "…대표자 걷" 처럼 잘린다. */
.card-fill .search-box .form-control { min-width: 300px; }
.w-150 { width: 150px; max-width: 100%; }   /* 목록 헤더 필터 셀렉트 */
.cw-44 { width: 44px; } .cw-80 { width: 80px; } .cw-100 { width: 100px; }
.cw-110 { width: 110px; } .cw-120 { width: 120px; } .cw-130 { width: 130px; }
.cw-160 { width: 160px; } .cw-min-240 { min-width: 240px; }

/* 버튼 라벨은 항상 한 줄 (Bootstrap 기본은 좁으면 글자단위로 접힘) */
.btn { white-space: nowrap; }

/* ══ 글자 크기 조절 (작게/중간/크게) — 헤더 토글, localStorage 저장(erp-sidebar.js) ══
   본문·표·메뉴·버튼·폼 글자를 변수 --erp-fs 로 묶어 한 번에 스케일한다. 중간(14)이 표준. */
:root { --erp-fs: 14px; }                 /* 중간(기본) */
html[data-fs="small"] { --erp-fs: 13px; } /* 작게 */
html[data-fs="large"] { --erp-fs: 15px; } /* 크게 */
body { font-size: var(--erp-fs); }        /* 본문·표(상속)·기타 텍스트가 함께 스케일 */
/* 버튼·폼도 본문과 동일 스케일 (Steex 기본 12.25px 덮음). 아이콘 전용 버튼은 제외 */
.btn:not(.icon-btn), .form-control, .form-select { font-size: var(--erp-fs); }

/* ══════════ 커스텀 사이드바 (레일 + 패널) — Steex two-column 대체 ══════════
   Steex 색·변수만 쓰고(§8.1) 마크업·레이아웃은 자체 소유 → 정렬·위계·구분선 완전 제어.
   폭 : 레일 96 + 패널 205 = 301. 콘텐츠 오프셋(main-content margin·topbar left)이 아래 두
   --tb-twocolumn-* 변수를 calc 로 쓰므로 사이드바 총폭과 같게 유지해 본문이 딱 맞는다.
   (app.js 의 빈 Steex 스켈레톤은 숨김 — _Layout 참고) */
:root {
    --tb-twocolumn-menu-iconview-width: 96px;   /* = 레일 폭 (콘텐츠 오프셋 계산에 쓰임) */
    --tb-twocolumn-menu-width: 205px;           /* = 패널 폭 (총 301) */
    --erp-rail-w: 96px;
    --erp-panel-w: 205px;

    /* ── 셸 치수 : 값을 베껴 적지 말고 테마 변수에서 끌어온다 ────────────────
       예전에는 71 / 15 / 60 을 손으로 적어뒀는데, 전부 "다른 요소의 높이"를 옮겨 적은 것이라
       그 요소가 바뀌면 조용히 어긋났다(BOM 구성도의 22rem 이 실제로 그렇게 깨졌다). */

    /* 로고 밴드 = 상단바와 같은 높이. Steex 상단바 = --tb-header-height + 아래 테두리 1px */
    --erp-brand-h: calc(var(--tb-header-height) + 1px);
    /* 본문 시작 높이 = Steex .page-content 의 padding-top (= --tb-header-height + 1rem, 실측 86px) */
    --erp-content-top: calc(var(--tb-header-height) + 1rem);
    /* 밴드 아래 첫 메뉴 여백 — 레일 첫 항목이 본문 제목과 같은 높이에 오게 (86 - 71 = 15) */
    --erp-top-pad: calc(var(--erp-content-top) - var(--erp-brand-h));
    /* 고정 푸터 높이 — Steex 는 이 값을 변수로 내주지 않아(--tb-footer-height 없음) 여기서 한 번만 정의한다.
       .footer 의 실제 높이(60px)와 반드시 같아야 한다 */
    --erp-footer-h: 60px;

    /* ── 쌓임 순서(z-index) : 서로 지켜야 하는 사다리라 한곳에 모은다 ──────────
       Bootstrap 기준 modal-backdrop 1050 · modal 1055 보다 토스트가 위에 와야 한다.
       erp-ux.js 의 토스트도 이 변수를 읽어 쓴다(값이 두 곳에 흩어지지 않게). */
    --erp-z-overlay: 1001;   /* 모바일 사이드바 뒤 어두운 막 */
    --erp-z-sidebar: 1002;   /* 사이드바 (막보다 위) */
    --erp-z-footer: 1004;    /* 고정 푸터 (사이드바보다 위 — 전체 폭 한 줄) */
    --erp-z-toast: 1090;     /* 토스트 (모달 1055 보다 위) */
    --erp-z-loading: 1095;   /* 페이지 이동 로딩 표시 (가장 위 — 무엇을 하든 보여야 한다) */

    /* 목록 컬럼명 글자색 (사용자 지정 — §4-9). 테마에 대응 변수가 없어 여기서 한 번만 정한다 */
    --erp-th-color: #333;
}

.erp-sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: var(--erp-z-sidebar);
    width: calc(var(--erp-rail-w) + var(--erp-panel-w));
    display: flex; flex-direction: column;
    background: var(--tb-secondary-bg);
    /* 우측 세로 테두리는 로고 밴드가 아니라 '바디'에만 → 헤더(로고 밴드)가 상단바와 한 셀로 이어짐 */
}
/* 로고 밴드 : 상단바 헤더와 같은 높이·한 줄. 아래 구분선이 topbar 밑줄과 이어짐.
   로고 뱃지(파란 아이콘) 중심을 레일 아이콘 중심(레일 96px 가운데 = x48)과 세로로 맞춘다.
   뱃지 중심 = padding-left + 18.3(SVG 뱃지 중심 오프셋) → padding-left 30 ⇒ 중심 ≈ 48. */
.erp-brand {
    flex: 0 0 var(--erp-brand-h); height: var(--erp-brand-h);
    display: flex; align-items: center; justify-content: flex-start;
    padding-left: 30px;
    border-bottom: 1px solid var(--tb-border-color);
}
.erp-brand-link { display: inline-flex; }
.erp-brand img { height: 40px; width: auto; }
.erp-sidebar-body {
    flex: 1 1 auto; display: flex; min-height: 0;
    border-right: 1px solid var(--tb-border-color);   /* 메뉴 영역만 콘텐츠와 구분 (로고 밴드 제외) */
}

/* ── 대메뉴 레일 : 아이콘 + 아래 텍스트 ── */
.erp-rail {
    flex: 0 0 var(--erp-rail-w); width: var(--erp-rail-w);
    overflow-y: auto; overflow-x: hidden;
    border-right: 1px solid var(--tb-border-color);   /* 대메뉴(레일) ↔ 패널 구분선 */
    padding: var(--erp-top-pad) 0 var(--erp-footer-h);   /* top = 본문 제목 맞춤 / bottom = 고정 푸터 회피 */
    display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.erp-rail-item {
    width: 70px; height: 70px; flex-shrink: 0;    /* 정사각 — 활성/hover 배경이 정사각형. flex-shrink:0 로 컬럼에서 안 눌리게(넘치면 레일 스크롤) */
    border: 0; background: transparent; cursor: pointer;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    padding: 0; border-radius: 8px; line-height: 1.1;
    color: var(--tb-body-color);   /* 대메뉴 폰트색 = 본문 잉크 변수 (사용자 지정) */
    transition: background .12s, color .12s;
}
.erp-rail-item i { font-size: 25px; }
.erp-rail-item span { font-size: calc(var(--erp-fs) - 2px); font-weight: 500; letter-spacing: -.3px; white-space: nowrap; }
.erp-rail-item:hover { color: var(--tb-primary); background: var(--tb-light); }
.erp-rail-item.active { color: var(--tb-primary); background: var(--tb-vertical-menu-item-active-bg); }

/* ── 중·소메뉴 패널 : 활성 대메뉴 1개만 표시 ── */
.erp-panel {
    flex: 1 1 auto; min-width: 0; overflow-y: auto; overflow-x: hidden;
    padding: var(--erp-top-pad) 0 var(--erp-footer-h);
}
.erp-menu { display: none; }
.erp-menu.active { display: block; }

/* 중메뉴 = 그룹 헤더 (진하게·크게 → 소메뉴와 확실히 구분) */
.erp-group-title {
    padding: 0 18px 8px; font-size: var(--erp-fs); font-weight: 700;
    color: var(--tb-body-color); letter-spacing: -.2px;   /* 중메뉴 폰트색 = 본문 잉크 변수 (사용자 지정) */
}
/* 그룹 사이 점선 구분선 (첫 그룹 제외) — 패널 전체 폭, 좌우 대칭 */
.erp-group + .erp-group {
    margin-top: 16px; padding-top: 16px;
    border-top: 1px dashed var(--tb-border-color);
}
/* 소메뉴 = 항목 (들여쓰기·얇게·활성 왼쪽바) */
.erp-item {
    display: block; padding: 7px 18px 7px 30px; font-size: var(--erp-fs);
    color: var(--tb-body-color); text-decoration: none;    /* 소메뉴 폰트색 = 본문 잉크 변수 (사용자 지정) */
    border-left: 2px solid transparent; transition: background .12s, color .12s;
}
.erp-item:hover { color: var(--tb-primary); background: var(--tb-light); }
.erp-item.active {
    color: var(--tb-primary); font-weight: 600;
    border-left-color: var(--tb-primary);
    background: var(--tb-vertical-menu-item-active-bg);
}
/* ── 메뉴 즐겨찾기(별표) ──
   항목과 별표를 한 줄에 둔다. 앵커 안에 버튼을 넣을 수 없어 .erp-item-row 로 감쌌다.
   별표는 평소 숨어 있다가 hover·활성·이미 담긴 것만 보인다 — 100줄에 별이 다 떠 있으면 메뉴가 시끄럽다. */
.erp-item-row { display: flex; align-items: center; }
.erp-item-row > .erp-item { flex: 1 1 auto; min-width: 0; }
.erp-fav-btn {
    flex: 0 0 auto; border: 0; background: none; cursor: pointer;
    padding: 0 10px 0 4px; line-height: 1;
    color: var(--tb-secondary-color);
    opacity: 0; transition: opacity .12s, color .12s;
}
.erp-item-row:hover .erp-fav-btn,
.erp-fav-btn:focus-visible { opacity: 1; }
.erp-fav-btn.on { opacity: 1; color: var(--tb-warning); }   /* 담긴 것은 항상 보인다 */
.erp-fav-btn:hover { color: var(--tb-warning); }

/* 즐겨찾기 영역 — 검색창 아래, 평소 메뉴 위 */
.erp-favs { padding-bottom: 4px; margin-bottom: 12px; border-bottom: 1px dashed var(--tb-border-color); }
/* 드래그로 순서를 바꿀 수 있음을 커서로 알린다(즐겨찾기 안에서만) */
.erp-fav-items > .erp-item-row { cursor: grab; }
.erp-fav-items > .erp-item-row:active { cursor: grabbing; }
/* 끌고 가는 동안 원래 자리에 남는 잔상 — 어디로 들어가는지 보이게 옅게 깐다 */
.erp-fav-ghost { opacity: .4; background: var(--tb-light); }
/* 검색 중에는 즐겨찾기도 감춘다 — 결과에 집중하게 */
.erp-panel.searching > .erp-favs { display: none; }

/* ── 메뉴 검색 (패널 맨 위 — 본문 제목과 같은 높이에서 시작) ──
   화면이 100개라 대메뉴를 하나씩 뒤지는 비용이 컸다. 활성 대메뉴와 무관하게 전체에서 찾는다.
   좌우 여백은 소메뉴 들여쓰기(30px)가 아니라 패널 기준(14px)으로 둔다 — 입력칸은 항목이 아니라 도구다. */
.erp-menu-search { padding: 0 14px 10px; }
.erp-menu-search .form-control { font-size: var(--erp-fs); }

/* 검색 결과 — 입력이 있을 때만 나타난다(.on) */
.erp-menu-results { display: none; }
.erp-menu-results.on { display: block; }
/* 검색 중에는 평소 메뉴를 감춘다. .active 를 건드리지 않으므로 검색을 지우면 원래 대메뉴로 그대로 돌아온다 */
.erp-panel.searching > .erp-menu { display: none; }
.erp-menu-result {
    display: block; padding: 5px 18px 5px 30px; text-decoration: none;
    color: var(--tb-body-color); border-left: 2px solid transparent;
    transition: background .12s, color .12s;
}
.erp-menu-result:hover, .erp-menu-result.cursor {
    color: var(--tb-primary); background: var(--tb-light); border-left-color: var(--tb-primary);
}
/* 어느 대메뉴·중메뉴 아래인지 — 같은 이름의 화면이 여럿이라 경로가 없으면 고를 수 없다 */
.erp-menu-result .erp-result-path {
    display: block; font-size: calc(var(--erp-fs) - 2px); color: var(--tb-secondary-color);
}
.erp-menu-empty { padding: 10px 18px 10px 30px; color: var(--tb-secondary-color); }

.erp-sidebar-overlay { display: none; }

/* ── 데스크톱(≥992) : 사이드바 상시 표시, 햄버거 숨김, 푸터 전체폭 고정 ── */
@media (min-width: 992px) {
    #topnav-hamburger-icon { display: none !important; }
    .footer {
        position: fixed !important;
        left: 0 !important; right: 0 !important; bottom: 0;
        z-index: var(--erp-z-footer);  /* 사이드바 위로 — 전체 폭 한 줄 */
    }
    /* 고정 푸터(60px) 아래 여유는 Steex 가 .page-content 에 이미 padding-bottom:60px 로 두고 있다.
       여기에 .main-content 로 60px 을 더 주면 이중이 되어(합 120px) 카드 아래 여백이
       좌우(16px)보다 60px 넓어졌다. _Layout 이 항상 .main-content > .page-content 로 감싸므로
       Steex 것 하나로 충분하다. */
}

/* ── 모바일(<992) : 사이드바 숨김 → 햄버거로 슬라이드 인 (erp-sidebar.js) ── */
@media (max-width: 991.98px) {
    .erp-sidebar {
        transform: translateX(-100%); transition: transform .2s ease;
        box-shadow: var(--tb-box-shadow-lg);     /* 떠 있는 면의 그림자는 테마 것을 쓴다(§8.1-3) */
    }
    body.erp-sidebar-open .erp-sidebar { transform: none; }
    body.erp-sidebar-open .erp-sidebar-overlay {
        display: block; position: fixed; inset: 0; z-index: var(--erp-z-overlay);
        /* 뒤를 덮는 막 색은 테마에 대응 변수가 없다(--tb-backdrop-* 미정의) → 리터럴 유지 */
        background: rgba(0, 0, 0, .4);
    }
    /* 사이드바가 오버레이이므로 본문·상단바는 전체 폭 */
    .main-content { margin-left: 0 !important; }
    #page-topbar { left: 0 !important; }
}

/* ── 인쇄 : no-print 숨김 + 인사카드 탭 전체 펼침 ── */
@media print {
    .no-print { display: none !important; }
    /* emp-print-all 안의 탭은 인쇄 시 전부 펼친다(탭별로 잘리지 않게) */
    .emp-print-all > .tab-pane { display: block !important; opacity: 1 !important; margin-bottom: 1rem; }
}

/* (구 Steex two-column 로고 배너·collapse 전환 오버라이드는 커스텀 사이드바 전환으로 삭제됨) */

/* ══ BOM 구성도 (테마에 없는 요소) ══════════════════════════════════
   Steex 에는 트리 컴포넌트가 없고 정품 데모(147개)에도 계층 전개 화면이 없어
   복사할 마크업이 없었다. 색·글꼴은 테마 변수를 그대로 쓰고 자리(연결선·간격)만 잡는다. */

/* 좌우 패널이 화면 높이를 함께 채우고 각자 안에서 스크롤한다 */
.bom-page > [class*="col-"] { display: flex; }
/* height:100% — 우측 계층이 짧아도 카드 높이는 좌측 목록과 맞춘다(둘이 어긋나 보이지 않게) */
.bom-page .card { width: 100%; height: 100%; }
/* 높이·스크롤은 전 목록 화면과 같은 방식(card-fill + erp-ux.js syncListHead)을 쓴다.
   예전에는 .bom-roots 에 height:calc(100vh - 22rem) 를 박고 syncListHead 에서 이 화면만
   제외했는데, 22rem 이 상단바·카드헤더·푸터 높이의 합을 손으로 더한 값이라 그 중 하나만
   바뀌어도 어긋났다(FHD 밀도 조정 후 아래 69px 이 비었다). 실측으로 맞추는 쪽이 정확하다. */
.bom-panes { padding: .75rem 1rem 1.25rem; }

/* ── 좌: 완제품 목록 ── */
.bom-root {
    display: block; width: 100%; text-align: left; border: 0; background: none;
    padding: .55rem 1rem; border-left: 3px solid transparent;
    border-bottom: 1px solid var(--tb-border-color);
}
.bom-root:hover { background: var(--tb-tertiary-bg); }
.bom-root.active { background: var(--tb-tertiary-bg); border-left-color: var(--tb-primary); }
.bom-root-no { display: block; font-weight: 500; }
.bom-root-name, .bom-root-meta { display: block; }

/* ── 우: 계층 ──
   연결선은 li 의 ::before(가로) · ::after(세로)로 그린다.
   마지막 자식이면 세로선을 가로선 높이까지만 그어 ┗ 모양이 된다. */
.bom-tree, .bom-tree ul { list-style: none; margin: 0; padding: 0; }
.bom-tree ul { padding-left: 1.5rem; }
.bom-tree li { position: relative; }
.bom-tree ul > li::before {
    content: ""; position: absolute; left: -.75rem; top: 1.05rem;
    width: .75rem; border-top: 1px solid var(--tb-border-color);
}
.bom-tree ul > li::after {
    content: ""; position: absolute; left: -.75rem; top: 0; bottom: 0;
    border-left: 1px solid var(--tb-border-color);
}
.bom-tree ul > li:last-child::after { bottom: auto; height: 1.05rem; }
.bom-node[data-open="0"] > ul { display: none; }

.bom-row { display: flex; align-items: center; gap: .5rem; padding: .3rem 0; }
.bom-row:hover { background: var(--tb-tertiary-bg); border-radius: var(--tb-border-radius); }
.bom-toggle, .bom-toggle-blank {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 1.25rem; height: 1.25rem;
}
.bom-toggle { padding: 0; border: 0; background: none; color: var(--tb-secondary-color); }
.bom-toggle:hover { color: var(--tb-primary); }
.bom-no { font-weight: 500; }
.bom-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 소요량은 자릿수가 맞아야 눈으로 비교된다 */
.bom-qty { flex: 0 0 auto; margin-left: auto; font-variant-numeric: tabular-nums; }
.bom-meta { flex: 0 0 auto; }

/* ══ 페이지 이동 로딩 표시 (테마에 없는 요소) ═══════════════════════════
   목록은 서버 렌더 전체 페이지라, 링크·필터를 누르면 새 문서가 그려지기 전까지
   브라우저가 '이전 화면'을 그대로 보여준다. 그 사이 아무 반응이 없어 먹통으로 보였다
   (출하 화면 실측 10.6초). 그래서 이동이 시작된 순간부터 이전 화면 위에 표시한다.
   ※ Steex #preloader 는 첫 진입용 전체 가림막이라 화면 전환에는 맞지 않아 쓰지 않는다. */

/* 상단 진행 바 — 끝(100%)에 도달하지 않는다. 실제 완료는 새 문서가 그려지며 이 요소가 사라지는 것 */
.erp-loading-bar {
    position: fixed; top: 0; left: 0; height: 3px; width: 0;
    background: var(--tb-primary);
    z-index: var(--erp-z-loading);
    pointer-events: none;
    animation: erp-loading-grow 12s cubic-bezier(.1, .8, .2, 1) forwards;
}
@keyframes erp-loading-grow {
    0%   { width: 0; }
    5%   { width: 22%; }
    25%  { width: 55%; }
    60%  { width: 78%; }
    100% { width: 94%; }
}

/* 오래 걸리는 화면(출하·재고 등)은 바만으로는 부족해 안내를 덧붙인다.
   2.5초 뒤에야 나타난다 — 빠른 화면에서 깜빡이면 그게 더 산만하다 */
.erp-loading-note {
    position: fixed; left: 50%; top: 45%; transform: translate(-50%, -50%);
    z-index: var(--erp-z-loading);
    display: flex; align-items: center; gap: .75rem;
    padding: .9rem 1.25rem;
    background: var(--tb-secondary-bg);
    border: 1px solid var(--tb-border-color);
    border-radius: var(--tb-border-radius);
    box-shadow: var(--tb-box-shadow-lg);
    color: var(--tb-body-color);
}
.erp-loading-note small { color: var(--tb-secondary-color); }

/* 이동 중에는 커서로도 알린다 */
body.erp-navigating { cursor: progress; }

/* ══ FHD(≤1920) 밀도 ═══════════════════════════════════════════════
   기준 수치는 QHD(2560)에서 잡혀 FHD 에서는 한 화면에 들어오는 행이 부족했다
   (1920x1080 실측: 목록 16행). 프레임(레이아웃·폭·구조)은 그대로 두고
   글자 눈금과 세로 여백만 한 단계 내린다.

   ※ 이 블록은 파일 맨 끝에 둔다 — 위의 기본값(글자 크기·행 패딩·카드 변수)을
     덮어야 하므로 반드시 그 뒤에 와야 한다.
   ※ 경계 1920px 은 CSS 픽셀 기준이라 배율이 함께 계산된다
     (FHD 100%≈1920 · FHD 125%≈1536 · QHD 100%≈2560 → 제외 · QHD 150%≈1707 → 포함).
   ※ <992 는 모바일 레이아웃이라 제외 — 거기는 자체 규칙이 따로 있다. */
@media (min-width: 992px) and (max-width: 1920px) {

    /* 글자 눈금을 통째로 한 단계 내린다. 헤더 토글(작게/중간/크게)은 그대로 동작하고
       눈금만 13/14/15 → 12/13/14 로 옮겨간다 — 고정 크기를 박지 않는 이유는 §8.2. */
    :root                 { --erp-fs: 13px; }
    html[data-fs="small"] { --erp-fs: 12px; }
    html[data-fs="large"] { --erp-fs: 14px; }

    /* 목록 행 — 세로 패딩만 줄인다. 가로(padX)는 그대로 둬야 열이 붙어 보이지 않는다.
       .62rem→.4rem + 글자 축소로 행 41.5px → 33px 대. */
    .table-bottom-border > tbody > tr > td,
    .table-bottom-border > thead > tr > th { padding-top: .4rem; padding-bottom: .4rem; }

    /* 카드 세로 여백 — 선택자를 덮지 않고 Steex 변수만 바꾼다(§8.1-3).
       가로 여백(--tb-card-spacer-x·cap-padding-x)은 건드리지 않는다. */
    .card { --tb-card-spacer-y: .9rem; --tb-card-cap-padding-y: .9rem; }

    /* 사이드바 소메뉴도 리스트다 — 항목이 많은 그룹(교육 11개)이 FHD 에서 스크롤되던 것을 줄인다 */
    .erp-item { padding-top: 5px; padding-bottom: 5px; }
}
