/* ============================================================================
 *  nx-tree.css — 다단계 트리(카테고리 · 문서 목차).
 *
 *  왜 전용 CSS 가 필요한가 (UI.md 규칙 3 의 예외)
 *  --------------------------------------------
 *  Zynix 에도 Preline 에도 **트리 컴포넌트가 없다.** 아코디언은 한 단계뿐이고,
 *  트리는 깊이에 비례하는 들여쓰기 · 세로 안내선 · 노드 위 툴박스 팝업처럼
 *  유틸리티 클래스로 표현되지 않는 규칙을 갖는다.
 *
 *  출처
 *  ----
 *  치수는 기존 운영 서비스의 `ftree.css`(뷰/편집 모드 16규칙)와
 *  `other.css`(툴박스 팝업)에서 가져왔다. 그대로 옮기지 않고 두 가지를 고쳤다:
 *
 *    ① 들여쓰기와 툴 자리를 **분리**했다.
 *       원본은 편집모드에서 레벨당 61px 을 밀었는데, 그 큰 값은 사실
 *       체크박스+툴버튼 자리 때문이지 들여쓰기 때문이 아니었다.
 *       6단계 목차면 366px 이 되어 500px 폭에서 제목이 안 보인다.
 *       → 들여쓰기는 `--nx-tree-indent`(기본 24px), 툴 자리는 행 안쪽 padding.
 *
 *    ② 색을 **Zynix CSS 변수**로 바꿨다. 원본은 #000/#999/#f2f2f2 하드코딩이라
 *       다크모드에서 읽을 수 없었다. Zynix 는 `.dark` 에서 변수를 갈아끼우므로
 *       변수만 쓰면 다크가 공짜로 따라온다.
 *
 *  아이콘은 전부 remixicon(`ri-*`)이며 템플릿에서 <i> 로 넣는다.
 *  대응표는 `ICONMAP.md`. 원본의 SSGizmo·MDI·FontAwesome 는 싣지 않는다.
 * ========================================================================= */

/* ★ 밀도 변수는 **바깥 상자에도** 선언한다.
   CSS 변수는 아래로만 상속된다. 상자(`.nx-tree-box`)가 안쪽(`.nx-tree`)에
   선언된 값을 볼 수 없어, 상자의 `min-height: row-h * 6` 이 폴백(34px)으로만
   계산됐다. 그러면 밀도를 바꿔도 상자 높이가 안 따라온다. */
.nx-tree-box,
.nx-tree {
  /* 이 두 값만 만지면 트리 밀도가 바뀐다. 깊은 목차(6단계)는 20px 로 줄인다. */
  --nx-tree-indent: 24px;
  --nx-tree-row-h: 34px;

  /* ★ 연결선 — 원본(ftree.css)은 `1px solid gray` 였다.
     점선으로 바꾸고 싶으면 이 한 줄만 `1px dotted …` 로 고치면
     세로선·가로선이 함께 바뀐다. 색은 다크모드를 따라가도록 변수로 둔다. */
  --nx-tree-line: 1px solid rgb(var(--default-text-color) / 0.32);

  position: relative;
  width: 100%;
  color: rgb(var(--default-text-color));
}

/* ★ 폭을 묶는다.
   화면 전체 폭으로 늘리면 항목 이름과 오른쪽 [메뉴] 버튼이 수십 cm 떨어져
   **어느 줄의 버튼인지 헷갈린다**(실제로 그랬다).

   값은 모달(`.ti-modal-box`)의 `max-width: 32rem` 과 같게 맞췄다 — 트리를
   팝업에서 볼 때와 페이지에서 볼 때 폭이 같아야 눈이 덜 피로하다.
   원본 `ftree.css` 의 `.nxtreewrap { width:500px }` 과도 거의 같은 값이다.

   검색줄도 같은 폭으로 묶어 왼쪽·오른쪽 끝이 트리와 맞아떨어지게 한다. */
.nx-tree-box,
.nx-tree-search {
  max-width: 32rem;
}

/* --------------------------------------------------------------------------
 * 바깥 상자 — 테두리와 **스크롤**을 맡는다.
 *
 * 왜 `.nx-tree` 가 아니라 한 겹 더 두나
 * -----------------------------------
 * SimpleBar 는 대상의 **자식들을 자기 래퍼(.simplebar-content) 안으로 옮긴다.**
 * `.nx-tree` 에 직접 붙이면 `.nx-tree > .nx-tree-list` 같은 직계 선택자가
 * 전부 끊겨 연결선·필터가 통째로 깨진다. 그래서 스크롤은 바깥이 맡는다.
 *
 * 왜 SimpleBar 인가 — **오버레이라 폭을 차지하지 않는다.** 네이티브 스크롤바는
 * 생기고 사라질 때마다 안쪽 폭이 15~17px 바뀌어 트리가 좌우로 흔들린다.
 * 이미 싣고 있는 라이브러리라 새로 넣는 것도 없다(`shell_app.html`).
 *
 * 모서리는 직각이다 — `nx-form.css` 의 규칙을 트리도 따른다.
 * ----------------------------------------------------------------------- */
.nx-tree-box {
  padding: 8px;
  /* ★ 오른쪽은 **스크롤바 자리만큼 더** 비운다.
     SimpleBar 는 오버레이라 내용 **위에** 그려진다 — 비워 두지 않으면 스크롤이
     생겼을 때 톱니 버튼을 덮는다. 페이지 쪽 `scrollbar-gutter: stable` 과
     같은 생각이다: 자리를 늘 잡아 두면 스크롤이 생기고 사라져도 안 흔들린다.
     11px 은 SimpleBar 트랙 폭(`.simplebar-track.simplebar-vertical`). */
  padding-right: calc(8px + var(--nx-scrollbar-w, 11px));
  border: 1px solid rgb(var(--default-border));
  border-radius: 0;
  background-color: rgb(var(--custom-white));
  /* ★ 내용이 적어도 상자 높이는 유지한다.
     검색 결과가 0이면 상자가 한 줄 두께로 납작해져 화면이 출렁였다.
     6줄 자리를 늘 잡아 두면 검색을 걸고 풀어도 아래 내용이 안 움직인다. */
  min-height: calc(var(--nx-tree-row-h, 34px) * 6 + 16px);
  /* 길어지면 상자 안에서 스크롤한다 — 페이지가 끝없이 길어지지 않게. */
  max-height: var(--nx-tree-max-h, 60vh);
}

/* ★ SimpleBar 가 아직 안 붙었을 때만 네이티브로 스크롤한다(JS 차단·로드 전).
   **붙은 뒤에는 절대 overflow 를 주면 안 된다** — SimpleBar 는 호스트의
   `overflow-y` 를 읽어 `hidden` 이면 "넘치지 않는다" 로 판단하고 스크롤바를
   숨겨 버린다. `overflow:hidden` 을 걸었더니 트랙이 안 보였다(실제로 그랬다). */
.nx-tree-box:not([data-simplebar="init"]) {
  overflow: auto;
}

.dark .nx-tree-box {
  background-color: transparent;
  border-color: rgb(255 255 255 / 0.1);
}

/* 선택 전용 트리(팝업 안)는 이미 모달 상자 안에 있다 — 테두리를 겹쳐 그리지 않고
   폭도 묶지 않는다. 다만 **스크롤은 필요하다**(팝업이 화면을 넘기면 안 된다). */
.nx-tree.is-picker {
  max-width: none;
}

.nx-tree-box.is-picker-box {
  max-width: none;
  padding: 0;
  border: 0;
  background: none;
  min-height: 0;
  max-height: var(--nx-tree-pick-max-h, 44vh);
}

/* 깊은 트리(문서 목차)는 들여쓰기를 줄여야 6단계가 화면에 들어온다 */
.nx-tree[data-max-depth="5"],
.nx-tree[data-max-depth="6"] {
  --nx-tree-indent: 18px;
}

/* (상자에는 걸지 않는다 — 상자가 쓰는 값은 `--nx-tree-row-h` 뿐이고
   들여쓰기는 안쪽에서만 쓴다. `:has()` 로 상자에 얹어 봐야 아무 효과가 없다.) */

/* --------------------------------------------------------------------------
 * 목록 · 노드
 * 중첩 <ul> 이라 접기가 CSS 만으로 된다 — JS 가 없어도 목록은 보인다.
 * ----------------------------------------------------------------------- */
.nx-tree-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nx-tree-node {
  position: relative;
  list-style: none;
}

/* --------------------------------------------------------------------------
 * 연결선 — 원본은 선이 **두 줄**이다(ftree.css).
 *
 *   세로선  ul.fancytree-container li:before   border-left: 1px solid gray
 *   가로선  .fancytree-expander:before         border-top : 1px solid gray  (32px)
 *
 * 원본은 Fancytree 의 스프라이트(icons.gif) 연결선을 끄고 이렇게 CSS 로 다시
 * 그렸다. 이미지가 아니라서 다크모드에서도 색이 따라온다 — 그 방식을 유지한다.
 *
 * 다른 점 하나: 원본은 마지막 형제도 세로선이 끝까지 내려간다.
 * 여기서는 **마지막 형제만 절반까지** 그려 ㄴ자로 닫는다 — 어디서 끝나는지
 * 눈으로 알 수 있어 깊은 목차에서 훨씬 읽기 쉽다.
 * ----------------------------------------------------------------------- */
.nx-tree-node > .nx-tree-list {
  margin-left: calc(var(--nx-tree-indent) / 2);
  padding-left: calc(var(--nx-tree-indent) / 2);
}

/* 세로선 — 각 항목이 자기 몫을 그린다(최상위에는 부모가 없으므로 안 그린다) */
.nx-tree-node > .nx-tree-list > .nx-tree-node::before {
  content: "";
  position: absolute;
  left: calc(var(--nx-tree-indent) / -2);
  top: 0;
  width: 0;
  height: 100%;
  border-left: var(--nx-tree-line);
}

/* 마지막 형제 — 자기 줄 가운데까지만 내려온다 */
.nx-tree-node > .nx-tree-list > .nx-tree-node:last-child::before {
  height: calc(var(--nx-tree-row-h) / 2);
}

/* 가로선 — 세로선에서 항목 쪽으로 뻗는다 */
.nx-tree-node > .nx-tree-list > .nx-tree-node > .nx-tree-row::before {
  content: "";
  position: absolute;
  left: calc(var(--nx-tree-indent) / -2);
  top: calc(var(--nx-tree-row-h) / 2);
  width: calc(var(--nx-tree-indent) / 2);
  height: 0;
  border-top: var(--nx-tree-line);
}

/* ★ 접힘 — 이 한 줄이 접기 기능의 전부다 */
.nx-tree-node[aria-expanded="false"] > .nx-tree-list {
  display: none;
}

/* --------------------------------------------------------------------------
 * 한 줄
 * ----------------------------------------------------------------------- */
.nx-tree-row {
  position: relative;        /* 가로 연결선(::before)의 기준 */
  display: flex;
  align-items: center;
  gap: 4px;
  min-height: var(--nx-tree-row-h);
  padding: 2px 6px;
  border-radius: 0;
}

.nx-tree-row:hover {
  background-color: rgb(var(--light));
}

/* 방금 건드린 줄 — 배경만 옅게 깐다.
   왼쪽에 파란 세로 막대를 넣었더니 **연결선과 같은 자리라** 선이 하나 더 생긴
   것처럼 보였다. 색만으로 충분하다. */
.nx-tree-node.is-active > .nx-tree-row {
  background-color: rgb(var(--primary) / 0.08);
}

/* --------------------------------------------------------------------------
 * 키보드로 고른 줄 (roving tabindex — tree.ts 의 setRoving)
 *
 * ★ 테두리를 `li` 가 아니라 **그 줄(.nx-tree-row)** 에 그린다.
 *   `li` 에 그리면 자식 가지까지 통째로 둘러싸여, 어느 줄에 있는지가 아니라
 *   "이 가지 전체" 로 보인다.
 * ★ `:focus-visible` 이라 마우스로 눌렀을 때는 안 나온다.
 *   `:focus` 로 두면 클릭할 때마다 테두리가 번쩍인다.
 * ----------------------------------------------------------------------- */
.nx-tree-node:focus {
  outline: none;
}

.nx-tree-node:focus-visible > .nx-tree-row {
  outline: 2px solid rgb(var(--primary));
  outline-offset: -2px;
}

/* 검색 매치 */
.nx-tree-node.is-match > .nx-tree-row .nx-tree-title {
  background-color: rgb(var(--primary) / 0.14);
  border-radius: 0;
  padding: 0 3px;
}

/* 검색 중 매치가 없는 가지 — 원본의 filter mode:'hide' 와 같다 */
.nx-tree.is-filtered .nx-tree-node:not(.is-match):not(.has-match) {
  display: none;
}

/* ★ 다만 **최상위 줄은 남긴다.**
   결과가 하나도 없으면 상자가 통째로 비어, 검색이 걸린 것인지 트리가 원래 빈
   것인지 구분이 안 됐다. 최상위(와 최상위 그룹)를 회색으로 남겨 두면
   "여기 있는데 이 안에 없다" 가 한 눈에 보인다. 하위 가지는 그대로 감춘다. */
/* ★ 위 규칙과 **같은 특이도**로 쓰고 뒤에 둔다 — `:not()` 두 개를 빼면
   특이도가 낮아져 감춤 규칙에 져서 아무 효과가 없다(실제로 그랬다). */
.nx-tree.is-filtered
  > .nx-tree-list
  > .nx-tree-node:not(.is-match):not(.has-match) {
  display: list-item;
}

.nx-tree.is-filtered
  > .nx-tree-list
  > .nx-tree-node:not(.is-match):not(.has-match)
  > .nx-tree-row {
  /* ★ 0.4 였다. 흰 바탕에서 재 보면 대비가 2.29:1 로, 읽을 수 있는 글자가
     아니라 **얼룩**이다(WCAG AA 는 4.5:1). 이 줄들은 "여기 있지만 결과는
     이 안에 없다" 를 알리는 이정표라 읽혀야 뜻이 있다.
     0.7 이면 회색으로 물러나면서도 4.5:1 을 넘긴다. */
  opacity: 0.7;
}

/* 회색으로 남은 줄에서는 손댈 것이 없다 — 툴버튼·메모를 감춘다 */
.nx-tree.is-filtered
  > .nx-tree-list
  > .nx-tree-node:not(.is-match):not(.has-match)
  > .nx-tree-row
  :is(.nx-tree-tool, .nx-tree-memo, .nx-tree-exp) {
  visibility: hidden;
}

/* --------------------------------------------------------------------------
 * 펼침 버튼 — Zynix 의 ti-btn 위에 크기만 덮어쓴다
 * ----------------------------------------------------------------------- */
.nx-tree .nx-tree-exp {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  min-height: 20px;
  padding: 0;
  border: 0;
  background: none;
  color: rgb(var(--text-muted, var(--default-text-color)));
  font-size: 15px;
  line-height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.nx-tree .nx-tree-exp.is-leaf {
  visibility: hidden;
}

/* 원본과 같은 +/− 기호 (remixicon \EA13 / \F1AF) */
.nx-tree-node[aria-expanded="true"] > .nx-tree-row > .nx-tree-exp::before {
  content: "\f1af";
  font-family: remixicon;
}

.nx-tree-node[aria-expanded="false"] > .nx-tree-row > .nx-tree-exp::before {
  content: "\ea13";
  font-family: remixicon;
}

/* --------------------------------------------------------------------------
 * 아이콘 · 제목
 * ----------------------------------------------------------------------- */
/* 폴더(그룹) · 문서(항목) 아이콘.
   16px 이면 34px 짜리 행 안에서 글자보다 작아 보여 **눈에 안 들어온다**.
   행 높이의 절반쯤은 되어야 한 눈에 그룹인지 항목인지 구분된다. */
.nx-tree-ico {
  flex: 0 0 auto;
  width: 20px;
  font-size: 18px;
  line-height: 1;
  text-align: center;
  /* 블랙 · 입체감 없음 — 파란 폴더는 시선을 뺏고 계층보다 아이콘이 먼저 읽힌다 */
  color: rgb(var(--default-text-color));
}

/* 항목(그룹이 아닌 것)은 조금 흐리게 — 폴더가 계층의 뼈대다 */
.nx-tree-node:not(.is-group) > .nx-tree-row > .nx-tree-ico {
  opacity: 0.55;
}

.nx-tree-hide {
  flex: 0 0 auto;
  font-size: 14px;
  opacity: 0.5;
}

.nx-tree-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 숨김(status=9) 항목은 옅게 — 관리자에게만 보이는 상태다 */
.nx-tree-node.is-hidden > .nx-tree-row .nx-tree-title {
  opacity: 0.5;
  text-decoration: line-through;
}

.nx-tree-node.is-group > .nx-tree-row .nx-tree-title {
  font-weight: 600;
}

/* 빈 상태 — 회색 한 줄로 두면 처음 온 사람이 여기서 멈춘다.
   무엇을 눌러야 하는지 크게 보여준다.
   (트리 상자 안에 들어가므로 테두리는 점선으로 구분만 한다) */
.nx-tree-empty {
  padding: 32px 16px;
  text-align: center;
  border: 1px dashed rgb(var(--default-border));
  border-radius: 0;
}

.nx-tree-empty > i {
  font-size: 34px;
  color: rgb(var(--primary));
  opacity: 0.35;
}

.nx-tree-empty-title {
  margin: 10px 0 0;
  font-weight: 600;
}

.nx-tree-empty-lead {
  margin: 4px 0 0;
  font-size: 13px;
  opacity: 0.6;
}

.nx-tree-empty-btns {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 16px;
}

/* 검색으로 걸러져 아무것도 안 보일 때 — 트리가 비어 보이는 것과 구분한다 */
.nx-tree.is-filtered .nx-tree-empty {
  display: none;
}

/* --------------------------------------------------------------------------
 * 메모 — 있으면 진하게, 없으면 옅게 (원본 .fancytree-memo.on 규칙)
 * ----------------------------------------------------------------------- */
.nx-tree .nx-tree-memo {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  min-height: 22px;
  padding: 0;
  border: 0;
  background: none;
  display: none;
  opacity: 0.35;
  font-size: 15px;
  line-height: 22px;
}

.nx-tree.use-memo .nx-tree-memo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.nx-tree .nx-tree-memo.is-on {
  opacity: 1;
  color: rgb(var(--primary));
}

/* 메모 팝업 안의 점 — 트리의 점과 **같은 색**이어야 뜻이 이어진다.
   트리 점(.nx-tree-dot)은 아이콘 위 절대 배치라 따로 둔다. */
.nx-memo-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 0;   /* 사장님 확정 2026-08-07: 전부 라운드 0 */
  flex: 0 0 auto;
}

.nx-memo-dot.is-shared {
  background-color: rgb(var(--primary));
}

.nx-memo-dot.is-mine {
  background-color: rgb(var(--success));
}

/* --------------------------------------------------------------------------
 * 메모 점 — 아이콘 위에 어느 종류가 있는지 표시한다
 *
 *   파랑(primary) = 공통 메모   모두가 본다
 *   초록(success) = 내 개인 메모  나만 본다
 *
 * ★ `::before` 는 아이콘 글리프가 이미 쓰고 있어 비어 있지 않다.
 *   그래서 점은 **자식 span** 으로 넣는다(`::after` 하나로는 두 개를 못 그린다).
 * ★ 버튼 안에서 절대 배치한다 — 아이콘 크기가 바뀌어도 따라온다.
 * ----------------------------------------------------------------------- */
.nx-tree .nx-tree-memo {
  position: relative;
}

.nx-tree .nx-tree-dot {
  position: absolute;
  top: 1px;
  width: 5px;
  height: 5px;
  border-radius: 0;   /* 사장님 확정 2026-08-07: **전부 라운드 0** —
                         전에는 점을 형태상 예외로 뒀다. 이제 아니다. */
  /* 배경 위에 점이 얹히면 경계가 안 보인다 — 상자 색으로 얇게 두른다. */
  box-shadow: 0 0 0 1px rgb(var(--custom-white));
}

/* 둘 다 있으면 나란히, 하나면 그 자리 그대로 — 오른쪽 끝을 기준으로 잡는다. */
.nx-tree .nx-tree-dot.is-shared {
  right: 1px;
  background-color: rgb(var(--primary));
}

.nx-tree .nx-tree-dot.is-mine {
  right: 1px;
  background-color: rgb(var(--success));
}

/* 둘 다 있을 때만 공통 점을 왼쪽으로 밀어 겹치지 않게 한다. */
.nx-tree .nx-tree-dot.is-shared:not(:only-child) {
  right: 7px;
}

.dark .nx-tree .nx-tree-dot {
  box-shadow: 0 0 0 1px rgb(var(--body-bg));
}

.nx-tree .nx-tree-memo::before {
  content: "\ecc5";           /* ri-file-3-line */
  font-family: remixicon;
}

/* 편집모드에서는 툴박스의 [메모] 버튼으로 들어간다 — 줄이 시끄러워진다 */
.nx-tree.is-edit .nx-tree-memo {
  display: none !important;
}

/* 검색줄의 아이콘 버튼(.nx-tree-sbtn)은 **nx-form.css 의 `.nx-sbtn` 한 곳**
 * 에 있다(F159 — 목록 화면과 같은 모양으로 통일). 여기서 다시 정의하면
 * 두 벌이 갈린다(9-12 의 '복사된 코드 = 갈라진 검사' 유형). */

/* --------------------------------------------------------------------------
 * 툴 진입 버튼 — 편집모드에서만
 * ----------------------------------------------------------------------- */
.nx-tree .nx-tree-tool {
  flex: 0 0 auto;
  display: none;
}

.nx-tree.is-edit .nx-tree-tool {
  display: inline-flex;
}

/* F155(사장님 실측 2026-08-04): 톱니가 줄마다 가로로 몇 px 어긋나 보였다.
   루트 행은 템플릿이 <a class="ti-btn">, 노드 행은 doxtree.js 가
   <button class="ti-btn"> 로 그린다 — 요소가 다르면 Zynix `.ti-btn` 의
   기본 여백이 달리 먹는다. 슬롯 폭과 여백을 못 박아 **요소 종류와 무관하게**
   같은 세로선에 오게 한다. (어느 기본값이 2px 를 만들었는지는 확인 못
   했습니다 — 원인을 짚는 대신 그 차이가 생길 자리를 없앴다.) */
.nx-tree .nx-tree-tool {
  width: 26px;
  justify-content: flex-end;
  margin: 0;
  padding: 0;
}
.nx-tree .nx-tree-toolbtn {
  margin: 0;
  flex: 0 0 auto;
}

/* ★ 크게, 그리고 **글자와 함께**. 원본은 작은 톱니 아이콘 하나였는데
   처음 보는 사람은 그게 눌리는 것인지도 모른다. */
.nx-tree .nx-tree-toolbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  min-height: 26px;
  padding: 0;
  border: 0;
  background: none;
  color: rgb(var(--default-text-color));
  font-size: 17px;
  line-height: 26px;
}

.nx-tree .nx-tree-toolbtn::before {
  content: "\f0e3";           /* ri-settings-2-fill — 톱니 */
  font-family: remixicon;
}

.nx-tree .nx-tree-toolbtn:hover {
  color: rgb(var(--primary));
}

/* --------------------------------------------------------------------------
 * 툴박스 팝업 — other.css `.wr_toolbtn_edit_pop` 을 옮긴 것
 * 원본: 220px × 47px 검정 박스. 아이콘은 흰색.
 * ----------------------------------------------------------------------- */
/* ★ 두 가지가 중요하다.
   ① position:fixed — absolute 로 두면 "위치가 정해진 조상" 을 찾아 올라가는데,
      툴박스는 트리 밖(페이지 끝)에 있어 그 조상이 화면마다 다르다.
      fixed + getBoundingClientRect() 면 어디에 두든 좌표가 한 가지로 맞는다.
   ② z-index — Zynix 는 `.app-header` 가 100, `.app-sidebar` 가 103 이다.
      이보다 낮으면 팝업이 **헤더 뒤로 들어가 보이지 않는다**(실제로 겪었다).
      모달(.ti-modal)은 999 이므로 그 아래, 헤더 위인 200 을 쓴다. */
.nx-tree-pop {
  position: fixed;
  /* ★ F492: 단추에 **붙는 팝업** 칸. 사이드바·서랍보다 위, 보통 팝업보다 아래.
     옛 값 200 은 뷰어 사이드바보다 낮아 «뒤로 들어간다» 를 냈다. */
  z-index: var(--nx-z-pop);
  min-width: 210px;
  max-width: 280px;
  padding: 6px;
  border-radius: 0;
  background-color: rgb(var(--custom-white));
  border: 1px solid rgb(var(--default-border));
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.18);
}

.dark .nx-tree-pop {
  background-color: rgb(var(--dark-bg, 25 24 26));
  border-color: rgb(255 255 255 / 0.12);
}

.nx-tree-pop[hidden] {
  display: none;
}

/* 무엇에 대한 메뉴인지 — JS 가 노드 이름을 넣는다 */
.nx-tree-pop-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px 8px;
  margin-bottom: 4px;
  border-bottom: 1px solid rgb(var(--default-border));
  font-size: 12px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nx-tree-pop-set {
  display: none;
  flex-direction: column;
  gap: 1px;
}

.nx-tree-pop-set.is-on {
  display: flex;
}

/* 구분선 */
.nx-tree-div {
  display: block;
  height: 1px;
  margin: 4px 6px;
  background-color: rgb(var(--default-border));
}

/* ★ 아이콘만 두지 않는다 — 글자를 함께 보여준다.
   원본은 아이콘만 썼지만 그건 몇 년 써 온 사람 기준이다. 처음 보는 사람은
   톱니바퀴가 무슨 뜻인지 알 수 없다. */
.nx-tree-pop .nx-tree-act {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 38px;
  padding: 0 10px;
  border: 0;
  border-radius: 0;
  background: none;
  color: rgb(var(--default-text-color));
  font-size: 13px;
  text-align: start;
  justify-content: flex-start;
}

.nx-tree-pop .nx-tree-act:hover {
  background-color: rgb(var(--primary) / 0.1);
  color: rgb(var(--primary));
}

.nx-tree-pop .nx-tree-act[data-act="delete"]:hover {
  background-color: rgb(var(--danger) / 0.1);
  color: rgb(var(--danger));
}

/* 동작 아이콘(방향) — 대상 아이콘과 나란히 놓이므로 겹침 기준(relative)이 필요 없다 */
.nx-tree-pop .nx-tree-act > i:first-child {
  flex: 0 0 auto;
  width: 22px;
  font-size: 19px;
  line-height: 1;
  text-align: center;
}

/* 대상 아이콘(폴더 = 그룹 / 문서 = 항목) — 동작 아이콘 **옆**에 나란히.
   겹쳐 붙이면 라벨 첫 글자를 가린다(실제로 가렸다).
   대상이 없는 줄도 같은 폭의 빈 span 이 들어가 라벨 왼쪽 끝이 전부 맞는다. */
.nx-tree-pop .nx-tree-act > .nx-tree-act-t {
  flex: 0 0 auto;
  width: 18px;
  font-size: 16px;
  line-height: 1;
  text-align: center;
  opacity: 0.75;
}

.nx-tree-pop .nx-tree-act > .nx-act-label {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 상한에 걸려 못 쓰는 항목 — 숨기지 않고 **이유를 붙여** 흐리게 둔다.
   사라지면 "있었는데 없어졌다" 로 보여 더 혼란스럽다. */
.nx-tree-pop .nx-tree-act[disabled],
.nx-tree-pop .nx-tree-act.is-off {
  opacity: 0.4;
  pointer-events: none;
}

/* ★ 7차 검수 — 여기 `content: " (최대 깊이)"` 라고 **한국어가 박혀 있었다.**
   EN/JA 화면에도 그대로 나왔다. CSS 는 테스트의 한국어 스캐너가 훑는 대상이
   아니라(템플릿과 .ts 만 본다) 아무도 못 봤다.
   문구는 템플릿이 `data-off-label` 로 내려주고, 여기서는 그걸 그린다. */
.nx-tree-pop .nx-tree-act.is-off .nx-act-label::after {
  content: " " attr(data-off-label);
  font-size: 11px;
  opacity: 0.8;
}

.nx-tree-pop .nx-tree-pop-close {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 26px;
  height: 26px;
  min-height: 26px;
  padding: 0;
  border: 0;
  background: none;
  color: rgb(var(--default-text-color));
  opacity: 0.5;
  font-size: 15px;
}

/* --------------------------------------------------------------------------
 * 검색줄
 * ----------------------------------------------------------------------- */
.nx-tree-search {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 10px;
}

/* ★ select 와 input 은 **줄여서** 오른쪽에 아이콘·개수 뱃지 자리를 남긴다.
   검색어를 넣으면 [해제] 아이콘과 개수 뱃지가 더 나타나는데, 폭을 꽉 채우면
   그때 버튼 글자가 세로로 쪼개진다(실제로 그랬다). */
.nx-tree-search .nx-tree-scope {
  flex: 0 0 auto;
  width: 96px;
}

.nx-tree-search .nx-tree-q {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 15rem;
}

/* 매치 개수 뱃지 — 원본 .fancytree-searchcount */
/* 개수 뱃지 — 버튼과 같은 높이의 **직각** 사각형(둥근 알약이 아니다) */
.nx-tree-count {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--nx-control-h, 35px);
  height: var(--nx-control-h, 35px);
  padding: 0 8px;
  font-size: 12px;
  font-weight: 600;
  border: 1px solid rgb(var(--default-border));
  border-radius: 0;
  /* 검색 아이콘(🔍·↻)과 같은 secondary — 셋이 한 덩어리로 읽힌다 */
  color: rgb(var(--secondary, 141 145 160));
}

.nx-tree-count[hidden] {
  display: none;
}

.nx-tree-exp-btns {
  flex: 0 0 auto;
  display: inline-flex;
  gap: 2px;
  margin-left: auto;
}

/* 검색 · 해제 — 아이콘만. secondary 색, 버튼 높이의 직각 사각형 */

.nx-tree .nx-tree-expall,
.nx-tree-search .nx-tree-expall {
  width: 30px;
  height: 30px;
  min-height: 30px;
  padding: 0;
  border: 0;
  background: none;
  color: rgb(var(--text-muted, var(--default-text-color)));
  font-size: 16px;
}

.nx-tree-search .nx-tree-expall:hover {
  color: rgb(var(--primary));
}

/* --------------------------------------------------------------------------
 * 선택 전용 트리 — [상위 변경] 팝업에서 쓴다.
 * 원본 pop_favcategory.php 가 CSS 네 줄로 같은 트리를 선택 전용으로 바꿨다.
 * ----------------------------------------------------------------------- */
.nx-tree.is-picker .nx-tree-tool,
.nx-tree.is-picker .nx-tree-memo {
  display: none !important;
}

.nx-tree.is-picker .nx-tree-title {
  cursor: pointer;
}

/* 현재 위치 — 원본 .tmpmatch */
.nx-tree.is-picker .nx-tree-node.is-current > .nx-tree-row {
  outline: 1px solid rgb(var(--primary));
  outline-offset: -1px;
}

/* 지금 고른 자리 */
.nx-tree.is-picker .nx-tree-node.is-picked > .nx-tree-row {
  background-color: rgb(var(--primary) / 0.14);
  box-shadow: inset 2px 0 0 rgb(var(--primary));
}

/* 옮길 수 없는 자리(자기 자신·자기 후손·깊이 초과)는 고를 수 없게 */
.nx-tree.is-picker .nx-tree-node.is-blocked > .nx-tree-row {
  opacity: 0.35;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
 * 좁은 화면 — 들여쓰기를 줄이고 툴버튼을 항상 보인다(hover 가 없다)
 * ----------------------------------------------------------------------- */
@media (max-width: 640px) {
  /* ★ 상자도 함께 — 변수는 아래로만 상속되므로 `.nx-tree` 에만 선언하면
     상자의 `min-height` 계산이 데스크톱 값(34px)으로 남는다.
     `[data-max-depth]` 규칙(특이도 0,1,1)에 지지 않게 속성 선택자를 하나 붙인다. */
  .nx-tree-box,
  .nx-tree[data-max-depth] {
    --nx-tree-indent: 16px;
    --nx-tree-row-h: 40px;
  }
}

/* 인쇄 — 접힌 것도 전부 펼쳐서 목차로 쓴다 */
@media print {
  .nx-tree-node[aria-expanded="false"] > .nx-tree-list {
    display: block;
  }
  .nx-tree-tool,
  .nx-tree-search,
  .nx-tree-pop {
    display: none !important;
  }
}

/* ===========================================================================
 * F270(사장님 2026-08-08) — 트리 [다른 위치로 이동] 대화상자 (doxtree ACTS.move)
 * 오버레이는 에디터 팝업과 같은 .nxe-modal(정본 nx-shell-parts.css)을 쓰고,
 * 여기는 패널 안쪽만 그린다. 라운드 0 · 트리 팝업과 같은 색 어휘.
 * =========================================================================== */
.nx-move-panel {
  margin: auto;
  width: min(480px, calc(100vw - 32px));
  max-height: min(70vh, 640px);
  display: flex;
  flex-direction: column;
  background: var(--nx-surface, #fff);
  border: 1px solid var(--nx-line, #e5e7eb);
  box-shadow: 0 10px 24px rgba(15, 23, 42, .18);
}
.nx-move-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--nx-line, #e5e7eb);
  font-size: 14px;
}
.nx-move-head i { color: var(--nx-menu-icon-color, #7b8698); }
.nx-move-head span { color: var(--nx-menu-cat-color, #9aa3b5); font-size: 12.5px; }
.nx-move-list { overflow-y: auto; padding: 6px 0; }
.nx-move-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  font-size: 13.5px;
  cursor: pointer;
}
.nx-move-row:hover { background: var(--nx-menu-hover-bg, #f4f6fa); }
.nx-move-row i { color: var(--nx-menu-icon-color, #7b8698); }
.nx-move-row em {
  margin-left: auto;
  font-style: normal;
  font-size: 11.5px;
  color: var(--nx-menu-cat-color, #9aa3b5);
}
.nx-move-row.is-off { opacity: .55; cursor: not-allowed; }
.nx-move-foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 10px 14px;
  border-top: 1px solid var(--nx-line, #e5e7eb);
}
/* ★★★★ F515 화살표1(사장님 실기동 2026-08-17): *"색상이 있는 버튼으로 해 줘."*
   단추에는 `ti-btn-primary`·`ti-btn-secondary` 가 이미 붙어 있었다. 그런데
   **이 팝업은 뷰어 문서 안**이고, 뷰어는 Zynix 를 안 싣는 독립 문서다 —
   그 클래스들이 색을 얻는 곳이 없어 **글자만** 보였다(사장님 캡처 그대로).
   ★ 색을 새로 짓지 않는다: primary **정본**(`--nx-primary`)에서 온다.
     실행 버튼 테두리·언어 고르개와 같은 값이고, 다크에서도 정본이 뒤집는다.
   ★ 라운드 0 — 전 화면 규칙. */
.nx-move-foot .ti-btn {
  border-radius: 0;
  padding: 6px 16px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
}
.nx-move-foot [data-move-go] {
  /* ★ 2026-09-05 — 흰 글자를 얹은 **채움 버튼**이라 Light 가 아니라
     primary 다(Light 로 두면 흰 글자가 안 보인다). */
  background: var(--nx-primary);
  border: 1px solid var(--nx-primary);
  color: #fff;
}
.nx-move-foot [data-move-go][disabled] { opacity: .45; cursor: default; }
.nx-move-foot [data-move-cancel] {
  background: transparent;
  border: 1px solid var(--nx-primary-soft-bd);
  color: inherit;
}
