/* ═══ common.css ═══════════════════════════
 * 전역 CSS 변수, 리셋, 공통 컴포넌트
 * 모든 페이지에서 공유. 개별 스타일은 각 CSS 파일에서 관리.
 * ═════════════════════════════════════════ */

/* ─── CSS 변수 (라이트 모드 기본) ─────────── */
:root {
  /* 색상 */
  --color-bg: #ffffff;
  --color-text: #1a1a2e;
  --color-primary: #000000;
  --color-primary-hover: #333333;
  --color-primary-glow: rgba(0, 47, 255, 0.08);
  --color-success: #16a34a;
  --color-warning: #c97000;
  --color-danger: #dc2626;
  --color-danger-hover: #b91c1c;
  --color-border: #dddde8;
  --color-focus: #000000;
  --color-muted: #66667a;
  --color-module-bg: #f8f8fc;

  /* 카드/섹션 */
  --color-card-bg: #ffffff;
  --color-section-bg: #ffffff;
  --color-glass-border: rgba(0, 0, 0, 0.05);

  /* 테이블 */
  --color-table-bg: #ffffff;
  --color-table-row-bg: #ffffff;
  --color-table-th-bg: #f0f0f8;
  --color-table-hover: rgba(0, 0, 0, 0.04);

  /* 배지 */
  --badge-info-bg: rgba(0, 0, 0, 0.08);
  --badge-info-text: #000000;
  --badge-default-bg: rgba(102, 102, 122, 0.12);
  --badge-default-text: #66667a;

  /* 레이아웃 */
  --color-header: #131313;
  --color-sidebar: #131313;
  --color-sidebar-hover: rgba(255, 255, 255, 0.08);
  --color-sidebar-active: rgba(255, 255, 255, 0.15);

  /* 그림자 */
  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.06);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.07), 0 2px 4px -2px rgb(0 0 0 / 0.08);
  --shadow-glass: 0 10px 40px -10px rgba(0, 0, 0, 0.08);

  /* 간격 / border-radius */
  --radius-sm: 5px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;

  /* 폰트 */
  --font-family: "Pretendard Variable", "Pretendard", "Noto Sans KR", -apple-system, sans-serif;
  --fs-base: 1rem;
  --fs-sm: 14px;
  --fs-xs: 12px;
  --fs-code: 11px;
  --fs-badge: 10px;

  /* 컨트롤 (button·form-input·form-select·trigger) 세로 패딩
   * 초소형 4px · 소형 6px · 기본 8px · 대형 10px.
   * 수평 패딩은 컴포넌트별 자율(버튼 16px·입력 10px 등).
   * 높이는 자연 계산 (padding × 2 + 컨텐츠 + border) — min-height 강제 없음 */
  --ctrl-py-xs: 4px;
  --ctrl-py-sm: 6px;
  --ctrl-py: 8px;
  --ctrl-py-lg: 10px;

  /* 상태 배경·테두리·텍스트 (components.md §5) */
  --color-success-bg: #e6f7ed;
  --color-success-border: #b7e6c8;
  --color-success-text: #0a7a3b;
  --color-danger-bg: #fdecec;
  --color-danger-border: #f5b4b4;
  --color-danger-text: #b91c1c;
  --color-warning-bg: #fff7e6;
  --color-warning-border: #ffd79a;
  --color-warning-text: #854d0e;
}

/* ─── 다크 모드 ──────────────────────────── */
[data-theme="dark"] {
  --color-bg: #0a0a0a;
  --color-text: #efefef;
  --color-primary: #ffffff;
  --color-primary-hover: #d4d4d4;
  --color-primary-glow: rgba(255, 255, 255, 0.12);
  --color-success: #22c55e;
  --color-warning: #f59e0b;
  --color-danger: #ef4444;
  --color-danger-hover: #dc2626;
  --color-border: #2a2a2a;
  --color-focus: #ffffff;
  --color-muted: #777777;
  --color-module-bg: rgba(0, 0, 0, 0.5);

  --color-card-bg: #151515;
  --color-section-bg: #151515;
  --color-glass-border: rgba(255, 255, 255, 0.05);

  --color-table-bg: #151515;
  --color-table-row-bg: #151515;
  --color-table-th-bg: rgba(0, 0, 0, 0.5);
  --color-table-hover: rgba(255, 255, 255, 0.06);

  --badge-info-bg: rgba(255, 255, 255, 0.12);
  --badge-info-text: #ffffff;
  --badge-default-bg: rgba(119, 119, 119, 0.15);
  --badge-default-text: #777777;

  --color-header: #0f0f0f;
  --color-sidebar: #111111;
  --color-sidebar-hover: rgba(255, 255, 255, 0.08);
  --color-sidebar-active: rgba(255, 255, 255, 0.15);

  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.6);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.6), 0 2px 4px -2px rgb(0 0 0 / 0.6);
  --shadow-glass: 0 10px 40px -10px rgba(0, 0, 0, 0.9);

  /* 다크 상태 토큰 */
  --color-success-bg: rgba(16, 185, 129, 0.15);
  --color-success-border: rgba(16, 185, 129, 0.35);
  --color-success-text: #34d399;
  --color-danger-bg: rgba(239, 68, 68, 0.18);
  --color-danger-border: rgba(239, 68, 68, 0.45);
  --color-danger-text: #fca5a5;
  --color-warning-bg: rgba(245, 158, 11, 0.18);
  --color-warning-border: rgba(245, 158, 11, 0.45);
  --color-warning-text: #fde68a;
}

/* ─── 리셋 ───────────────────────────────── */
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: var(--font-family);
  font-size: var(--fs-base);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  transition: background 0.3s ease, color 0.3s ease;
}

/* 폼 컨트롤: 브라우저 기본 폰트를 덮어쓰고 Pretendard Variable 상속 강제 */
input,
select,
textarea,
button,
optgroup,
option {
  font-family: var(--font-family);
}

/* ─── 버튼 ───────────────────────────────── */
.btn {
  padding: var(--ctrl-py) 16px;
  box-sizing: border-box;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1.2;    /* icon vs text 동일 content height 보장 */
  cursor: pointer;
  background: var(--color-card-bg);
  color: var(--color-text);
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 4px;
}

/* 버튼 내부 아이콘은 text line-height 와 동일하게 렌더 */
.btn > i,
.btn-sm > i,
.btn-xs > i {
  line-height: inherit;
}

.btn:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.btn.is-active {
  background: var(--color-primary);
  color: #ffffff;
  border-color: var(--color-primary);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-primary {
  background: #000000;
  color: #ffffff;
  border-color: #000000;
}
.btn-primary:hover,
.btn-primary:active,
.btn-primary.is-active {
  background: #151515;
  border-color: #151515;
  color: #ffffff;
}

.btn-secondary {
  background: var(--color-card-bg);
  color: var(--color-text);
  border: 1px solid var(--color-border);
}
.btn-secondary:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.btn-danger { background: #ef4444; color: #ffffff; border: 1px solid #ef4444; }
.btn-danger:hover { background: #dc2626; border-color: #dc2626; color: #ffffff; }

.btn-warning { background: var(--color-card-bg); color: var(--color-warning); border: 1px solid var(--color-warning); }
.btn-warning:hover { background: var(--color-warning); color: #ffffff; border-color: var(--color-warning); }

.btn-sm { padding: var(--ctrl-py-sm) 12px; font-size: var(--fs-xs); }
.btn-xs { padding: var(--ctrl-py-xs) 6px; font-size: var(--fs-code); }

/* 다크모드 버튼 */
[data-theme="dark"] .btn {
  background: var(--color-card-bg);
  color: var(--color-text);
  border-color: var(--color-border);
}
[data-theme="dark"] .btn:hover {
  background: #2a2a2a;
  border-color: #3a3a3a;
  color: var(--color-text);
}
[data-theme="dark"] .btn.is-active {
  background: var(--color-primary);
  color: #ffffff;
  border-color: var(--color-primary);
}
[data-theme="dark"] .btn-primary {
  background: #000000;
  color: #ffffff;
  border-color: #000000;
}
[data-theme="dark"] .btn-primary:hover,
[data-theme="dark"] .btn-primary:active,
[data-theme="dark"] .btn-primary.is-active {
  background: #151515;
  border-color: #151515;
  color: #ffffff;
}
[data-theme="dark"] .btn-secondary {
  background: var(--color-card-bg);
  color: var(--color-text);
  border-color: var(--color-border);
}
[data-theme="dark"] .btn-secondary:hover {
  background: #2a2a2a;
  border-color: #3a3a3a;
  color: var(--color-text);
}
[data-theme="dark"] .btn-warning {
  background: transparent;
  color: var(--color-warning);
  border-color: var(--color-warning);
}
[data-theme="dark"] .btn-warning:hover {
  background: var(--color-warning);
  color: #000;
}
[data-theme="dark"] .btn-danger {
  background: #ef4444;
  color: #ffffff;
  border-color: #ef4444;
}
[data-theme="dark"] .btn-danger:hover {
  background: #dc2626;
  border-color: #dc2626;
  color: #ffffff;
}

.btn-icon {
  background: none;
  border: none;
  color: var(--color-primary);
  cursor: pointer;
  padding: var(--ctrl-py-xs) 8px;
  font-size: 14px;
  line-height: 1;
  border-radius: var(--radius-sm);
  transition: color 0.2s, background 0.2s;
}
.btn-icon:hover {
  color: var(--color-primary-hover);
  background: var(--color-primary-glow);
}

/* 테이블 더보기 버튼 (관리 컬럼 2개 이상 액션) */
.btn-table-more {
  width: 28px;
  height: 28px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-muted);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, color 0.15s;
}
.btn-table-more:hover {
  background: var(--color-primary-glow);
  color: var(--color-primary);
}

/* 테이블 컨텍스트 팝업 메뉴 */
.table-ctx-menu {
  position: fixed;
  z-index: 9999;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  min-width: 160px;
  padding: 4px 0;
  animation: tableCtxFadeIn 0.12s ease-out;
}
@keyframes tableCtxFadeIn {
  from { opacity: 0; transform: scale(0.95) translateY(-4px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
.table-ctx-menu__item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 14px;
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  color: var(--color-text);
  text-align: left;
  white-space: nowrap;
  transition: background 0.15s;
}
.table-ctx-menu__item:hover {
  background: var(--color-primary-glow);
  color: var(--color-primary);
}
.table-ctx-menu__item--danger {
  color: #dc2626;
}
.table-ctx-menu__item i {
  width: 14px;
  text-align: center;
  font-size: 12px;
  flex-shrink: 0;
}
.table-ctx-menu__divider {
  height: 1px;
  background: var(--color-border);
  margin: 4px 8px;
}

/* ─── 배지 ───────────────────────────────── */
.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 20px;
  font-size: var(--fs-badge);
  font-weight: 600;
}

/* 의미 기반(의미 기반 우선) — 신규 코드는 이 이름 사용 */
.badge-success  { background: rgba(22, 163, 74, 0.12);  color: #15803d; }
.badge-danger   { background: rgba(220, 38, 38, 0.12);  color: #b91c1c; }
.badge-warning  { background: rgba(201, 112, 0, 0.12);  color: #c97000; }
.badge-info     { background: var(--badge-info-bg);     color: var(--badge-info-text); }
.badge-default  { background: var(--badge-default-bg);  color: var(--badge-default-text); }

/* 레거시 별칭 — DB seed(migrate_portal_init.sql `badge_cls` JSON) 호환. 신규 코드 사용 금지 */
.badge-active   { background: rgba(22, 163, 74, 0.12);  color: #15803d; }
.badge-inactive { background: rgba(220, 38, 38, 0.12);  color: #b91c1c; }
.badge-pending  { background: rgba(201, 112, 0, 0.12);  color: #c97000; }

[data-theme="dark"] .badge-success  { background: rgba(34, 197, 94, 0.15);  color: #86efac; }
[data-theme="dark"] .badge-danger   { background: rgba(239, 68, 68, 0.15);  color: #fca5a5; }
[data-theme="dark"] .badge-warning  { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }
[data-theme="dark"] .badge-active   { background: rgba(34, 197, 94, 0.15);  color: #86efac; }
[data-theme="dark"] .badge-inactive { background: rgba(239, 68, 68, 0.15);  color: #fca5a5; }
[data-theme="dark"] .badge-pending  { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }

/* ─── 카드 ───────────────────────────────── */
.card {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  margin-bottom: 16px;
  box-shadow: var(--shadow-sm);
  transition: background 0.3s ease, border-color 0.3s ease;
  flex-shrink: 0;   /* flex column 부모에서 자연 높이 유지 */
}

.card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: var(--color-module-bg);
  border-bottom: 1px solid var(--color-border);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.card__title { font-size: var(--fs-sm); font-weight: 600; }
.card__header-meta { font-size: var(--fs-xs); color: var(--color-muted); }
.card__header-meta a { color: var(--color-primary); text-decoration: none; }
.card__body { padding: 16px; }
.card__body--flush { padding: 0; }

/* ─── 테이블 ─────────────────────────────── */
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.table th {
  text-align: left;
  padding: 10px 16px;
  background: var(--color-table-th-bg);
  border-bottom: 1px solid var(--color-border);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.table td {
  padding: 10px 16px;
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text);
  transition: background-color 0.2s;
}

.table tr:hover td { background: var(--color-table-hover); }

/* ─── 알럿 ───────────────────────────────── */
.alert {
  display: none;
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  margin-bottom: 12px;
  align-items: center;
  gap: 8px;
}

.alert.visible { display: flex; }

.alert--success {
  background: #f0fdf4;
  color: #15803d;
  border: 1px solid #bbf7d0;
}

.alert--error {
  background: #fef2f2;
  color: #991b1b;
  border: 1px solid #fecaca;
}

.alert--info {
  background: #eff6ff;
  color: #2563eb;
  border: 1px solid #bfdbfe;
}

.alert--warning {
  background: #fef9c3;
  color: #854d0e;
  border: 1px solid #fde68a;
}

/* ─── 다이얼로그 (alert / confirm) ──────── */
.dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: 99998;
  background: rgba(0, 0, 0, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: dialogFadeIn 0.15s ease;
}

.dialog-overlay--hiding {
  animation: dialogFadeOut 0.15s ease forwards;
}

.dialog {
  background: var(--color-card-bg, #fff);
  border-radius: var(--radius-lg);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
  min-width: 280px;
  max-width: 420px;
  padding: 24px 28px 20px;
  text-align: center;
  animation: dialogScaleIn 0.15s ease;
}

.dialog-overlay--hiding .dialog {
  animation: dialogScaleOut 0.15s ease forwards;
}

.dialog__icon {
  font-size: 28px;
  margin-bottom: 8px;
}

.dialog__icon--success { color: var(--color-success); }
.dialog__icon--error { color: var(--color-danger, #dc2626); }
.dialog__icon--warning { color: #d97706; }
.dialog__icon--info { color: var(--color-primary); }
.dialog__icon--question { color: var(--color-primary); }

.dialog__title {
  font-size: 15px;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 6px;
}

.dialog__message {
  font-size: 13px;
  color: var(--color-muted);
  line-height: 1.5;
  margin-bottom: 18px;
  word-break: keep-all;
}

.dialog__actions {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.dialog__actions .btn {
  min-width: 80px;
}

@keyframes dialogFadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes dialogFadeOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes dialogScaleIn { from { transform: scale(0.9); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes dialogScaleOut { from { transform: scale(1); opacity: 1; } to { transform: scale(0.9); opacity: 0; } }

/* ─── 토스트 알림 ───────────────────────── */
#toastContainer {
  position: fixed;
  top: 64px;
  right: 16px;
  z-index: 99999;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-width: 260px;
  max-width: 400px;
  padding: 12px 16px;
  border-radius: var(--radius-lg);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
  pointer-events: auto;
  animation: toastSlideIn 0.25s ease;
}

.toast--hiding {
  animation: toastSlideOut 0.4s ease forwards;
}

.toast__icon { font-size: 16px; flex-shrink: 0; line-height: 1.5; }
.toast__msg {
  flex: 1;
  min-width: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.toast__close {
  background: none;
  border: none;
  font-size: 18px;
  cursor: pointer;
  padding: 0 2px;
  line-height: 1;
  opacity: 0.5;
  color: inherit;
}
.toast__close:hover { opacity: 1; }

.toast--success { background: #f0fdf4; color: #15803d; border: 1px solid #bbf7d0; }
.toast--error   { background: #fef2f2; color: #991b1b; border: 1px solid #fecaca; }
.toast--warning { background: #fffbeb; color: #854d0e; border: 1px solid #fde68a; }
.toast--info    { background: #eff6ff; color: #1e40af; border: 1px solid #bfdbfe; }

[data-theme="dark"] .toast--success { background: #0d2b1e; color: #86efac; border-color: #1a4d3a; }
[data-theme="dark"] .toast--error   { background: #2b0e0e; color: #fca5a5; border-color: #4d1a1a; }
[data-theme="dark"] .toast--warning { background: #2b1f06; color: #fcd34d; border-color: #4d3a10; }
[data-theme="dark"] .toast--info    { background: #1a1a1a; color: #e5e5e5; border-color: #333333; }

[data-theme="dark"] .dialog {
  background: #1a1a1a;
}

@keyframes toastSlideIn {
  from { transform: translateX(100%); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}

@keyframes toastSlideOut {
  from { transform: translateX(0); opacity: 1; }
  to { transform: translateX(100%); opacity: 0; }
}

/* ─── 로딩 오버레이 ─────────────────────── */
.loading-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: var(--color-card-bg);
  opacity: 0.85;
  z-index: 10;
  border-radius: var(--radius-lg);
}

.loading-overlay__spinner {
  width: 28px;
  height: 28px;
  border: 3px solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: loading-spin 0.6s linear infinite;
}

.loading-overlay__text {
  font-size: var(--fs-sm);
  color: var(--color-muted);
}

@keyframes loading-spin {
  to { transform: rotate(360deg); }
}

/* ─── 유틸리티 ───────────────────────────── */
.hidden { display: none !important; }
.text-muted { color: var(--color-muted); }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }

/* ─── 검색 가능 Selectbox (공통 컴포넌트) ──
 * JS: common/js/searchable-select.js
 * 사용: SearchableSelect.from('#id') 또는 createSearchableSelect(el, opts)
 * BEM: .search-select (block) / __element / --modifier 규칙 준수
 */

.search-select {
  position: relative;
  display: inline-block;
  width: 100%;
  font-size: 13px;
  color: var(--color-text);
}

.search-select__trigger {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: var(--ctrl-py) 10px;
  box-sizing: border-box;
  line-height: 1.2;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s, box-shadow 0.15s;
  font: inherit;
  color: inherit;
}

.search-select__trigger:hover {
  border-color: var(--color-border);
}

.search-select__trigger:focus,
.search-select--open .search-select__trigger {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-primary-glow);
}

.search-select__trigger-text {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.search-select__trigger-text.is-placeholder {
  color: var(--color-muted);
}

.search-select__trigger-clear {
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--color-muted);
  font-size: 16px;
  cursor: pointer;
  border-radius: 50%;
  line-height: 1;
  flex-shrink: 0;
}

.search-select__trigger-clear:hover {
  background: var(--color-border);
  color: var(--color-text);
}

.search-select__caret {
  color: var(--color-muted);
  font-size: 12px;
  line-height: 1;           /* 부모 min-height 유지 — 아이콘이 line-box 를 늘리지 않도록 */
  flex-shrink: 0;
  transition: transform 0.15s;
}

.search-select--open .search-select__caret {
  transform: rotate(180deg);
}

.search-select__panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.search-select__panel[hidden] {
  display: none;
}

.search-select__search {
  width: 100%;
  padding: 6px 10px;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  font-size: 13px;
  background: var(--color-section-bg);
  color: var(--color-text);
}

.search-select__search:focus {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-primary-glow);
}

.search-select__list {
  overflow-y: auto;
  overflow-x: hidden;
  margin: 0;
  padding: 0;
}

.search-select__option {
  padding: 7px 10px;
  font-size: 13px;
  border-radius: 4px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  user-select: none;
}

.search-select__option.is-highlighted {
  background: var(--color-primary-glow);
}

.search-select__option.is-selected {
  background: var(--color-primary);
  color: #fff;
  font-weight: 500;
}

.search-select__option.is-selected.is-highlighted {
  background: var(--color-primary-hover);
}

.search-select__option.is-disabled {
  color: var(--color-muted);
  cursor: not-allowed;
}

.search-select__empty {
  padding: 16px 10px;
  text-align: center;
  color: var(--color-muted);
  font-size: 12px;
}

.search-select--disabled {
  opacity: 0.6;
  pointer-events: none;
}

/* 고정 폭 modifier — 기본 width:100% 를 override (form__input--w* 대응) */
.search-select--w120 { width: 120px; }
.search-select--w160 { width: 160px; }
.search-select--w200 { width: 200px; }
.search-select--w240 { width: 240px; }

/* 다크 테마 호환 (data-theme="dark" 루트에서 변수 재정의됨) */
[data-theme="dark"] .search-select__panel {
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
}

/* ═════════════════════════════════════════════
 * 공통 컴포넌트 (components.md §2 기준)
 * 프로젝트·화면 구분 없이 공유. 접두사(admin-, wz-, nl-) 사용 금지.
 * 상태 클래스는 .is-* / .has-* 접두사만 허용.
 * ═══════════════════════════════════════════ */

/* ─── .split-panel — 분할 레이아웃 (components.md §2-1) ─────
 * 높이는 반드시 **부모 flex 체인** 에서 공급받는다.
 * `.page-content > .split-panel { flex:1; min-height:0 }` 규칙이 매칭되어야 화면 높이를 채우고
 * 각 `__left/__right/__col` 내부에서만 스크롤된다.
 * 하드코딩 min-height 금지 — 과거 480px fallback 제거됨. 부모가 height 를 공급하지 않으면
 * split-panel 은 콘텐츠 높이로 축소되므로, 반드시 `.page-content` 같은 flex:1 flex-column 부모에 넣는다.
 * ──────────────────────────────────────────────────────── */
.split-panel {
  display: flex;
  flex: 1;               /* 부모 flex 체인에서 남은 공간을 차지 */
  min-height: 0;         /* flex 자식이 콘텐츠 크기 제약을 받지 않게 해제 */
  gap: 16px;
}

.split-panel__left,
.split-panel__right,
.split-panel__col {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;          /* 각 패널 내부에서 스크롤 처리 */
  overflow-x: hidden;
}

/* 범용 스크롤 원칙 (flex column 부모 → 자식 오버플로우 시 부모 스크롤)
 * ─────────────────────────────────────────────────────────
 *   부모  : display: flex; flex-direction: column;
 *           min-height: 0; overflow-y: auto;
 *   자식 (자연 높이 유지 필요 — 압축되면 안 됨) : flex-shrink: 0
 *   자식 (남은 공간을 채워야 함 — 에디터·미리보기 등) : flex: 1; min-height: 0;
 *
 * 아래 공통 컴포넌트들은 flex column 부모 안에서 기본 flex-shrink:0 을 적용해
 * 내용 총 높이가 부모를 초과하면 부모가 스크롤하도록 한다
 * (각자 자연 높이 유지).
 *   .accordion, .panel-header, .panel-toolbar, .selector-bar,
 *   .filter-bar, .tabs, .settings-card, .card
 * 개별 정의에서 이미 flex-shrink:0 이 지정되어 있거나, 아래 묶음으로 지정됨.
 */

.split-panel__left { flex: 0 0 40%; }
.split-panel__right { flex: 1; }
.split-panel__col { flex: 1 1 0; }

/* 패널 내부 헤더는 스크롤 시 상단 고정 */
/* 최상단 panel-header 만 sticky — 동일 패널에 보조 툴바/필터 행이 있을 경우
 * 겹침을 방지 (보조 행은 자연 스크롤) */
.split-panel__left > .panel-header:first-of-type,
.split-panel__right > .panel-header:first-of-type,
.split-panel__col > .panel-header:first-of-type {
  position: sticky;
  top: 0;
  z-index: 2;
}

/* panel-header 직후 형제에 자동 4px 상단 여백 — 컨텐츠 컴포넌트(list/table/tree 등) 무관하게
 * 좌·우 패널의 panel-header → 컨텐츠 시각 간격을 일관 보장 (components.md §2-1 정책) */
.split-panel__left > .panel-header + *,
.split-panel__right > .panel-header + *,
.split-panel__col > .panel-header + * {
  padding-top: 4px;
}

/* 패널 내부 표준 래퍼 — panel-header 다음 컨텐츠 영역.
 * 스크롤은 패널 자체가 담당하므로 별도 overflow 불필요.
 * 자식에 height:100% 또는 flex layout 이 필요한 컴포넌트(Tabulator, CodeMirror 등)
 * 가 정상 동작하도록 flex column 컨테이너로 운영. */
.split-panel__body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* 라이브러리가 자체적으로 컨테이너 div 에 class 를 부여하는 경우(Tabulator 등)
 * 래퍼의 자연 layout 을 깨지 않도록 자동 fill 처리 */
.split-panel__body > .tabulator,
.split-panel__body > .cm-wrap,
.split-panel__body > .table-host {
  flex: 1;
  min-height: 0;
}

/* Root modifier */
.split-panel--triple { gap: 12px; }
.split-panel--four   { gap: 12px; }
.split-panel--editor { flex: 1; min-height: 0; }
.split-panel--compact { gap: 8px; min-height: 0; }

/* Left modifier */
.split-panel__left--narrow { flex: 0 0 260px; }
.split-panel__left--sidebar { flex: 0 0 220px; }
/* @deprecated — `.split-panel__left--50p` 로 대체. alias 유지(기존 사용처 호환). 신규 사용 금지. */
.split-panel__left--wide { flex: 0 0 50%; }

/* 비율 기반 — 오른쪽은 기본 flex:1 이므로 100% - 좌측% 가 자동 배정.
 * 50p 는 좌/우 5:5 균등 분할. */
.split-panel__left--20p { flex: 0 0 20%; }
.split-panel__left--25p { flex: 0 0 25%; }
.split-panel__left--30p { flex: 0 0 30%; }
.split-panel__left--33p { flex: 0 0 33.333%; }
.split-panel__left--40p { flex: 0 0 40%; }
.split-panel__left--50p { flex: 0 0 50%; }

/* Right modifier */
.split-panel__right--scroll { overflow-y: auto; }

@media (max-width: 1024px) {
  .split-panel--stack\@sm {
    flex-direction: column;
  }
  .split-panel--stack\@sm .split-panel__left,
  .split-panel--stack\@sm .split-panel__right,
  .split-panel--stack\@sm .split-panel__col {
    flex: 1 1 auto;
  }
}

/* ─── .page-header — 페이지 상단 제목/액션 (components.md §2-2A) ─── */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: 0 0 auto;
}

.page-header h1,
.page-header__title {
  font-size: 17px;
  font-weight: 600;
  color: var(--color-text);
  margin: 0;
}

.page-header__actions {
  display: flex;
  gap: 8px;
}

/* ─── .page-content — main 내부 메뉴 컨텐츠 컨테이너 ────
 * 구조: <main> > <.page-header> + <[id="{project}PageContent"]> .page-content
 * 기본: 자체 스크롤. split-panel 직계 자식이면 overflow:hidden + flex chain.
 * ─────────────────────────────────────────────────── */
.page-content {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  --page-gap: 12px;      /* 자식이 gap 값을 참조해 margin 계산할 수 있게 노출 */
  overflow-y: auto;
}

/* split-panel 이 어느 depth 로 있든 (직계 or nested via .layout-fill) 외부 스크롤은 닫음 */
.page-content:has(.split-panel) {
  overflow: hidden;
}

/* Tabulator 를 포함하는 경우 — Tabulator 가 자체 scroll 처리하므로 부모 overflow 닫음.
 * Tabulator 의 `height: '100%'` 옵션이 definite height 로 해결되도록 flex chain 공급. */
.page-content:has(> .tabulator) {
  overflow: hidden;
}
.page-content > .tabulator {
  flex: 1 1 0;
  min-height: 0;
}

/* 직계 자식 split-panel 기본 흐름 — 부모 flex chain 에서 남은 공간 차지 */
.page-content > .split-panel {
  flex: 1;
  min-height: 0;
}

/* ─── .layout-fill — flex 체인 통과 래퍼 ─────
 * .page-content 와 .split-panel 사이에 중간 wrapper 가 불가피한 경우
 * (예: 탭 + 컨텐츠 패턴의 content 영역) 사용.
 * 부모 flex-column 의 남은 공간을 채우고 내부도 flex-column 으로 연결.
 * ──────────────────────────────────────────── */
.layout-fill {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ─── .panel-header — 패널/섹션 헤더 (components.md §2-2) ─── */
.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 16px;
  min-height: 49px;   /* padding 10+10 + btn-sm min-height 28 + border 1 = 49 */
  border-bottom: 1px solid var(--color-border);
  background: var(--color-section-bg);
  flex-shrink: 0;
  box-sizing: border-box;
}

.panel-header__title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-text);
  margin: 0;
}

.panel-header__actions {
  display: flex;
  gap: 6px;
  align-items: center;
}

/* ─── .panel-body — 패널 본문 (스크롤 영역) ─── */
/* 패널 3분할 표준: panel-header(자연 높이) + panel-body(flex:1, 자체 스크롤) + panel-bottom(자연 높이)
 * 컨텐츠가 영역을 초과하면 panel-body 자체에서만 스크롤 — header/bottom 은 항상 보임 */
.panel-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

/* tabs 가 panel-body 안에 있을 때 tab-content 가 자체 스크롤하도록 layout 분리.
 * modifier(`--editor`, `--form`) 가 별도 overflow 정책을 가지면 그쪽이 우선되도록
 * 기본 셀렉터에는 overflow 미설정 — modifier 없는 base `.tab-content` 만 자체 스크롤. */
.panel-body > .tabs { flex-shrink: 0; }
.panel-body > .tab-content {
  flex: 1;
  min-height: 0;
}
.panel-body > .tab-content:not(.tab-content--editor):not(.tab-content--form) {
  overflow-y: auto;
}

/* ─── .panel-bottom — 패널 하단 액션 영역 ─── */
.panel-bottom {
  flex-shrink: 0;
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: flex-end;
  padding: 10px 16px;
  border-top: 1px solid var(--color-border);
  background: var(--color-section-bg);
  box-sizing: border-box;
}

/* 좌측(위험 액션) + 우측(주 액션) 분리 패턴 — 첫 자식만 좌측으로 밀어냄 */
.panel-bottom--split > :first-child { margin-right: auto; }

/* ─── .is-hidden — 표준 숨김 상태 클래스 ─── */
.is-hidden { display: none !important; }

/* Modifier */
.panel-header--page {
  padding: 16px 20px;
}
.panel-header--page .panel-header__title {
  font-size: 17px;
}

.panel-header--sticky {
  position: sticky;
  top: 0;
  z-index: 10;
}

/* ─── .tabs — 탭 (components.md §2-3) ─── */
.tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-section-bg);
  flex-wrap: wrap;
  flex-shrink: 0;
  margin-bottom: 12px;  /* form__group 과 동일 간격 */
}

.tabs__btn {
  padding: var(--ctrl-py) 16px;
  border: none;
  background: transparent;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--color-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
  font-family: inherit;
  line-height: 1.2;
}

.tabs__btn:hover {
  color: var(--color-primary);
  background: rgba(0, 0, 0, 0.06);
}

.tabs__btn.is-active {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
  font-weight: 600;
}

/* Modifier */
.tabs--sub {
  background: transparent;
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  padding: 0 4px;
}

.tabs--justify .tabs__btn {
  flex: 1;
  justify-content: center;
  display: inline-flex;
  align-items: center;
}

.tabs--pills {
  border-bottom: none;
  gap: 4px;
  background: transparent;
  padding: 4px;
}
.tabs--pills .tabs__btn {
  border-bottom: none;
  border-radius: var(--radius-sm);
}
.tabs--pills .tabs__btn.is-active {
  background: var(--color-primary);
  color: #fff;
}

[data-theme="dark"] .tabs__btn:hover {
  background: rgba(255, 255, 255, 0.06);
}

/* ─── .tree — 트리 (components.md §2-4) ─── */
.tree {
  list-style: none;
  margin: 0;
  padding: 4px 0;
  font-size: var(--fs-sm);
  color: var(--color-text);
}

.tree__item {
  margin: 1px 0;
  position: relative;
}

.tree__item.is-collapsed > .tree__children {
  display: none;
}

.tree__node {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 12px;
  min-height: 32px;       /* btn-table-more 유무와 무관하게 모든 트리 노드 동일 높이 */
  box-sizing: border-box;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background 0.15s;
}

/* 트리 노드 내부 더보기 버튼 — list__item--actions 와 동일한 hover-reveal 패턴 */
.tree__node .btn-table-more {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  margin-left: auto;
  opacity: 0;
  transition: opacity 0.15s;
}

.tree__node:hover .btn-table-more,
.tree__node.is-active .btn-table-more {
  opacity: 1;
}

.tree__node.is-active .btn-table-more {
  color: rgba(255, 255, 255, 0.85);
}

.tree__node.is-active .btn-table-more:hover {
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
}

.tree__node:hover {
  background: var(--color-table-hover);
}

.tree__node.is-active {
  background: var(--color-primary);
  color: #ffffff;
}

.tree__node.is-disabled {
  opacity: 0.45;
  pointer-events: none;
}

.tree__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  font-size: 10px;
  color: var(--color-muted);
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.tree__toggle i {
  transition: transform 0.2s;
  transform: rotate(90deg);  /* 기본(펼침): fa-chevron-right 를 90도 회전해 아래로 */
}

.tree__item.is-collapsed > .tree__node > .tree__toggle i {
  transform: rotate(0deg);   /* 접힘: 원래 방향(오른쪽) */
}

.tree__toggle--leaf {
  visibility: hidden;
}

.tree__checkbox {
  margin: 0 4px 0 0;
  cursor: pointer;
  accent-color: var(--color-primary);
  flex: 0 0 auto;
}

.tree__label {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tree__children {
  list-style: none;
  margin: 0;
  padding: 0 0 0 20px;
}

/* Modifier */
.tree--compact .tree__node {
  padding: 3px 10px;
  font-size: var(--fs-xs);
}
.tree--compact .tree__children {
  padding-left: 16px;
}

.tree--sortable .tree__node {
  user-select: none;
}

/* SortableJS 연동 */
.tree .sortable-ghost {
  opacity: 0.3;
  background: rgba(0, 0, 0, 0.12) !important;
}
.tree .sortable-chosen > .tree__node {
  background: rgba(0, 0, 0, 0.12);
}

/* ─── .list — 공통 리스트 (components.md §2-5) ─── */
.list {
  list-style: none;
  margin: 0;
  padding: 4px 0;
}

.list__item {
  padding: 10px 16px;
  cursor: pointer;
  border-bottom: 1px solid var(--color-border);
  transition: background 0.15s;
}

.list__item:hover {
  background: var(--color-table-hover);
}

.list__item.is-active {
  background: var(--color-primary);
  color: var(--color-bg);
}
.list__item.is-active .list__meta {
  color: var(--color-bg);
  opacity: 0.7;
}

.list__item--actions {
  display: flex;
  align-items: center;
  padding: 8px 8px 8px 16px;
  gap: 8px;
}

.list__content {
  flex: 1;
  min-width: 0;
}

.list__name {
  font-size: var(--fs-sm);
  font-weight: 500;
}

.list__meta {
  font-size: var(--fs-xs);
  color: var(--color-muted);
  margin-top: 2px;
}

/* Modifier */
.list--compact .list__item { padding: 6px 12px; }
.list--bordered .list__item {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  margin-bottom: 4px;
}
.list--dense .list__item { border-bottom: none; padding: 4px 12px; }

/* ─── .empty-message — 빈 상태 (components.md §2-6) ─── */
.empty-message {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 200px;
  gap: 12px;
  color: var(--color-muted);
  padding: 24px;
}

.empty-message__icon {
  font-size: 48px;
  opacity: 0.4;
}

.empty-message__text {
  font-size: var(--fs-sm);
  margin: 0;
  text-align: center;
}

/* Modifier */
.empty-message--sm { min-height: 100px; }
.empty-message--sm .empty-message__icon { font-size: 32px; }

.empty-message--lg { min-height: 320px; }
.empty-message--lg .empty-message__icon { font-size: 64px; }

.empty-message--inline {
  flex-direction: row;
  min-height: auto;
  padding: 8px 12px;
}
.empty-message--inline .empty-message__icon { display: none; }

/* ─── .form — 폼 그룹 (components.md §2-7) ─────
 * 공통 .form__* 정의. 레거시 .admin-form__* 는 portal-admin.css 에서
 * selector-list 별칭으로 동일 스타일을 받아 JS 마이그레이션 전까지 병행.
 * ───────────────────────────────────────────── */
.form__group {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  margin-bottom: 12px;
}

.form__group--top { align-items: stretch; }
.form__group--action {
  flex-direction: row;
  justify-content: flex-start;
  margin-top: 16px;
}
.form__group--inline {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.form__label {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-text);
  text-align: left;
  line-height: 1.4;
}

.form__control {
  width: 100%;
  min-width: 0;
}

.form__input,
.form__select {
  width: 100%;
  padding: var(--ctrl-py) 10px;
  box-sizing: border-box;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  font-size: var(--fs-sm);
  line-height: 1.2;
  background: var(--color-card-bg);
  color: var(--color-text);
  font-family: inherit;
  transition: background 0.3s ease, border-color 0.3s ease;
}

.form__input:focus,
.form__select:focus {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-primary-glow);
}

.form__input:disabled,
.form__select:disabled {
  background-color: var(--color-module-bg);
  color: var(--color-muted);
  cursor: not-allowed;
}

.form__input.is-invalid,
.form__select.is-invalid {
  border-color: var(--color-danger);
}

textarea.form__input {
  font-family: inherit;
  resize: vertical;
}

/* flex 컨테이너(panel-toolbar/filter-bar) 내부에서 input 이 남은 공간을 채우도록 */
.form__input--stretch {
  flex: 1 1 0;
  min-width: 0;
}

.form__select {
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  /* chevron 아이콘 (라이트) — 우측 10px 여백 + 12px 아이콘 + 8px gap */
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%23707070' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 12px 12px;
  padding-right: 30px;
}

/* IE 레거시 — 기본 화살표 숨김 */
.form__select::-ms-expand {
  display: none;
}

/* 다크 테마 — chevron 색상만 교체 */
[data-theme="dark"] .form__select {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%23a1a1aa' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.form__input--narrow { width: 80px; }
.form__input--sm { width: 100px; }
.form__input--md { width: 160px; }

.form__hint {
  font-size: var(--fs-xs);
  color: var(--color-muted);
}

.form__hint--success { color: var(--color-success); }
.form__hint--error { color: var(--color-danger); }

/* ─── .search-input — 아이콘 포함 검색 입력 (BEM)
 * 구조:
 *   <div class="search-input">
 *     <i class="fa-solid fa-magnifying-glass search-input__icon"></i>
 *     <input class="search-input__field" placeholder="검색어...">
 *   </div>
 * - 아이콘 슬롯 확보를 위해 좌측 padding 32px 고정
 */
.search-input {
  position: relative;
  display: inline-block;
  width: 100%;
}

.search-input__icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-muted);
  pointer-events: none;
  font-size: var(--fs-sm);
}

.search-input__field {
  width: 100%;
  padding: var(--ctrl-py) 12px var(--ctrl-py) 32px;
  box-sizing: border-box;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-card-bg);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--fs-sm);
  line-height: 1.2;
  outline: none;
  transition: background 0.3s ease, border-color 0.3s ease;
}

.search-input__field:focus {
  box-shadow: 0 0 0 2px var(--color-primary-glow);
}

.search-input__field:disabled {
  background: var(--color-module-bg);
  color: var(--color-muted);
  cursor: not-allowed;
}

/* 고정 폭 modifier */
.search-input--w160 { width: 160px; }
.search-input--w200 { width: 200px; }
.search-input--w240 { width: 240px; }

.form__radios,
.form__checks {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.form__radio,
.form__check {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-sm);
  cursor: pointer;
}

.form__radio input,
.form__check input {
  accent-color: var(--color-primary);
}

.form__actions {
  margin-top: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.form__actions-right {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

.form__divider {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-muted);
  margin: 16px 0 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ─── .filter-bar — 테이블 상단 필터 바 (공통) ─── */
.filter-bar {
  display: flex;
  gap: 8px;
  flex-wrap: nowrap;      /* 한 줄 유지 — 좁은 화면에서 컨트롤 축소 */
  align-items: center;
  flex-shrink: 0;
  min-width: 0;           /* 내부 자식이 필요 시 줄어들도록 */
}

/* 내부 자식은 내용 너비만큼만 차지 — flex grow/shrink 모두 없음 */
.filter-bar > * {
  flex: 0 0 auto;
  min-width: 0;
}

.filter-bar__sep {
  color: var(--color-muted);
  font-size: var(--fs-sm);
  line-height: 1;
}

/* filter-bar 내부 form 컨트롤은 공통 .form__input / .form__select 의 width:100% 를 오버라이드.
 * input 은 브라우저 기본 너비(`size` 속성 또는 ~20ch), select 는 가장 긴 옵션 너비로 자동 조정. */
.filter-bar .form__input,
.filter-bar .form__select {
  width: auto;
}

/* ─── .modal — 모달 (components.md §2-9) ─────
 * 공통 .modal 정의. 레거시 .admin-modal 는 portal-admin.css 에서 별칭 처리.
 * 상태: .is-open (기존 .admin-modal.visible 은 별칭 유지).
 * ───────────────────────────────────────────── */
.modal {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.5);
  align-items: center;
  justify-content: center;
}

.modal.is-open {
  display: flex;
}

.modal__content {
  background: var(--color-section-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
}

.modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--color-border);
}

.modal__title {
  font-size: var(--fs-base);
  font-weight: 600;
  margin: 0;
}

.modal__close {
  background: none;
  border: none;
  font-size: 20px;
  cursor: pointer;
  color: var(--color-muted);
  line-height: 1;
}
.modal__close:hover { color: var(--color-text); }

.modal__body {
  padding: 20px;
}

.modal__footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 20px;
  border-top: 1px solid var(--color-border);
}

/* Modifier */
.modal--sm .modal__content { max-width: 420px; }
.modal--lg .modal__content { max-width: 780px; }
.modal--full .modal__content { max-width: 90vw; max-height: 90vh; }

/* ─── .accordion — 아코디언 (components.md 확장) ──
 * admin-accordion, nl-section 통합. 기본 닫힘, is-open 추가 시 열림.
 * ──────────────────────────────────────────────── */
.accordion {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-bottom: 12px;
  overflow: hidden;
  flex-shrink: 0;   /* flex column 부모 내에서 자연 높이 유지 — 내용이 길면 부모가 스크롤 */
}

.accordion__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px;
  cursor: pointer;
  background: var(--color-table-th-bg);
  user-select: none;
  transition: background 0.15s ease;
}

.accordion__header:hover {
  background: var(--color-table-hover);
}

.accordion__header:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: -2px;
}

.accordion__title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-text);
  margin: 0;
}

.accordion__arrow {
  font-size: 11px;
  color: var(--color-muted);
  transition: transform 0.25s ease;
}

.accordion.is-open .accordion__arrow {
  transform: rotate(180deg);
}

.accordion__body {
  display: none;
  padding: 12px 16px;
  border-top: 1px solid var(--color-border);
}

.accordion.is-open .accordion__body {
  display: block;
}

/* Modifier */
.accordion--card {
  background: var(--color-card-bg);
}
.accordion--card .accordion__header {
  background: var(--color-section-bg);
}

.accordion--static .accordion__header {
  cursor: default;
}
.accordion--static .accordion__header:hover {
  background: var(--color-table-th-bg);
}
.accordion--static .accordion__arrow {
  display: none;
}
.accordion--static .accordion__body {
  display: block;
}

.accordion--flush {
  border: none;
  border-radius: 0;
}
.accordion--flush .accordion__body {
  border-top: 1px solid var(--color-border);
}

/* ═══════════════════════════════════════════════════════════════════
 * 관리 UI 공통 유틸 (2026-04-19 통합)
 *   portal-admin.css 에서 범용 가능한 요소를 이관. context-prefix 금지.
 * ═══════════════════════════════════════════════════════════════════ */

/* ─── Table Toolbar (테이블 상단 컨트롤 바) ──────────────────────── */
.table-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 0;
  position: relative;
  flex-shrink: 0;
}

/* 내부 컨트롤은 내용 너비만큼만 — filter-bar 와 동일 */
.table-toolbar > * {
  flex: 0 0 auto;
  min-width: 0;
}
.table-toolbar .form__input,
.table-toolbar .form__select {
  width: auto;
}

/* 테이블 툴바 바로 다음에 오는 Tabulator 는 부모 flex gap 을 상쇄해 딱 붙여 렌더.
 * .page-content / .split-panel__* gap 이 12px 기준 — 해당 영역에서만 적용. */
.table-toolbar + .tabulator,
.table-toolbar + [id$="Table"] {
  margin-top: calc(-1 * var(--page-gap, 12px));
}

/* ─── Dropdown Panel (컬럼 토글/필터 드롭다운) ─────────────────── */
.dropdown-panel {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 100;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  padding: 12px;
  min-width: 180px;
  flex-direction: column;
  gap: 6px;
}
.dropdown-panel.is-open { display: flex; }

/* ─── Multiselect (체크박스 다중선택) ──────────────────────────── */
.multiselect {
  position: relative;
  width: 100%;
}
.multiselect__btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--ctrl-py) 10px;
  box-sizing: border-box;
  line-height: 1.2;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  background: var(--color-card-bg);
  cursor: pointer;
  color: var(--color-text);
}
.multiselect__btn::after {
  content: '▼';
  font-size: 10px;
  color: var(--color-muted);
}
.multiselect__panel {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  padding: 8px;
  margin-top: 4px;
  max-height: 200px;
  overflow-y: auto;
}
.multiselect__panel.is-open { display: block; }
.multiselect__all {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-sm);
  font-weight: 600;
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
}
.multiselect__item {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-sm);
  padding: 2px 0;
  cursor: pointer;
}
.multiselect__all input,
.multiselect__item input {
  accent-color: var(--color-primary);
}

/* ─── Matrix (권한·서비스·메뉴 매트릭스 테이블 공통) ─────────── */
.matrix {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  text-align: center;
  background: var(--color-card-bg);
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 1px solid var(--color-border);
}
.matrix th {
  background-color: var(--color-table-th-bg);
  color: var(--color-muted);
  font-weight: 600;
  padding: 12px 16px;
  border-bottom: 1px solid var(--color-border);
  text-transform: uppercase;
  font-size: var(--fs-xs);
  letter-spacing: 0.05em;
}
.matrix th:first-child { text-align: left; }
.matrix td {
  padding: 10px 16px;
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text);
  transition: background-color 0.2s;
}
.matrix td:first-child { text-align: left; font-weight: 600; }
.matrix tbody tr { transition: background-color 0.2s; }
.matrix tbody tr:hover td { background-color: var(--color-table-hover); }
.matrix tbody tr:last-child td { border-bottom: none; }
.matrix__flags { font-family: monospace; font-size: var(--fs-code); }
.matrix__empty { color: var(--color-muted); opacity: 0.5; }
.matrix__legend { font-size: var(--fs-code); color: var(--color-muted); margin-top: 8px; }

/* Matrix modifier: compact grid (얇은 표·인라인 입력) */
.matrix--compact {
  border-collapse: collapse;
  font-size: var(--fs-xs);
  border-radius: 0;
}
.matrix--compact th,
.matrix--compact td {
  border: 1px solid var(--color-border);
  padding: 6px 8px;
  vertical-align: middle;
  text-transform: none;
  letter-spacing: normal;
}
.matrix--compact th {
  white-space: nowrap;
}

/* Matrix custom checkbox (body 내부의 권한 체크) */
.matrix input[type="checkbox"].matrix__check {
  appearance: none;
  background-color: var(--color-section-bg);
  margin: 0;
  font: inherit;
  color: currentColor;
  width: 1.3em;
  height: 1.3em;
  border: 2px solid #cbd5e1;
  border-radius: 4px;
  display: grid;
  place-content: center;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
[data-theme="dark"] .matrix input[type="checkbox"].matrix__check { border-color: #475569; }
.matrix input[type="checkbox"].matrix__check::before {
  content: "";
  width: 0.7em;
  height: 0.7em;
  transform: scale(0);
  transition: 150ms transform cubic-bezier(0.34, 1.56, 0.64, 1);
  box-shadow: inset 1em 1em white;
  background-color: white;
  transform-origin: center;
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
.matrix input[type="checkbox"].matrix__check:checked {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
}
.matrix input[type="checkbox"].matrix__check:checked::before { transform: scale(1); }
.matrix input[type="checkbox"].matrix__check:hover { border-color: var(--color-primary-hover); }

/* Matrix row variants */
.matrix__row--highlight td { background: var(--color-primary-glow); font-weight: 600; }
.matrix__row--group td {
  background: var(--color-table-th-bg);
  font-size: var(--fs-code);
  font-weight: 700;
  color: var(--color-muted);
  padding: 4px 12px;
  text-transform: uppercase;
}

/* ─── Info Table (key-value 테이블) ─────────────────────────────── */
.table--info {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 20px;
  font-size: var(--fs-sm);
}
.table--info th,
.table--info td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--color-border);
  text-align: left;
  vertical-align: middle;
}
.table--info th {
  color: var(--color-muted);
  font-weight: 600;
  font-size: var(--fs-xs);
  width: 80px;
  white-space: nowrap;
}
.table--info td { color: var(--color-text); }

/* ─── Icon Grid / Button (아이콘 선택기) ──────────────────────── */
.icon-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.icon-btn {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-card-bg);
  color: var(--color-muted);
  cursor: pointer;
  font-size: 15px;
  transition: all 0.15s ease;
}
.icon-btn:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.icon-btn.is-selected {
  border-color: var(--color-primary);
  background: var(--color-primary-glow);
  color: var(--color-primary);
}

/* ─── Actions Grid (체크박스/버튼 그리드) ────────────────────── */
.actions-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* ─── Form input 너비 유틸 ───────────────────────────────────── */
.form__input--w80  { width: 80px; }
.form__input--w120 { width: 120px; }
.form__input--w160 { width: 160px; }
.form__input--w200 { width: 200px; }
.form__input--w60  { width: 60px; }

/* ─── Badge size modifier ───────────────────────────────────── */
.badge--xs { font-size: 9px; padding: 1px 6px; }

/* ─── Pill (작은 라벨/스텝 표시) ─────────────────────────────── */
.pill {
  display: inline-flex;
  align-items: center;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 10px;
  letter-spacing: 0.5px;
}
.pill--primary {
  color: var(--color-primary);
  background: var(--color-primary-glow);
}
.pill--muted {
  color: var(--color-muted);
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
}

/* ─── Section label (uppercase 보조 라벨) ───────────────────── */
.section-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--color-muted);
  text-transform: uppercase;
}

/* ─── Btn pulse (저장 필요 pulsing 애니메이션) ──────────────── */
.btn--pulse { animation: btn-pulse 1.4s ease-in-out infinite; }
@keyframes btn-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.35); }
  50% { box-shadow: 0 0 0 6px rgba(0, 0, 0, 0); }
}

/* ─── Dirty indicator (미저장 상태 표시) ────────────────────── */
.dirty-indicator {
  display: none;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-warning);
}
.dirty-indicator.is-visible { display: inline-flex; }
.dirty-indicator__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-warning);
  animation: btn-pulse 1.4s ease-in-out infinite;
}

/* ─── Custom scrollbar ──────────────────────────────────────── */
.custom-scrollbar::-webkit-scrollbar { width: 6px; height: 6px; }
.custom-scrollbar::-webkit-scrollbar-thumb {
  background: var(--color-border);
  border-radius: 3px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover { background: var(--color-muted); }

/* ─── Workspace (상단바 + 다중 컬럼 + 하단바 구성) ──────────── */
/* ─── list__item 상태 클래스 확장 ────────────────────────────── */
.list__item.is-dragging { opacity: 0.3; }
.list__item.is-dragover { border-top: 2px solid var(--color-primary); }
.list__item.is-inactive { opacity: 0.5; }
.list__item--highlight {
  background: var(--color-primary-glow);
  border: 1px dashed var(--color-primary);
  font-weight: 600;
}

/* ─── panel-header 보조 ────────────────────────────────────── */
.panel-header__hint {
  font-size: var(--fs-xs);
  color: var(--color-muted);
}

/* ─── Settings card (환경설정 섹션 카드) ────────────────────── */
.settings-card {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 24px;
  margin-bottom: 16px;
  flex-shrink: 0;
}
.settings-card__title {
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--color-border);
}
.settings-card__actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
}

/* ═══════════════════════════════════════════════════════════════════
 * 공통 sub-elements / helpers — 2026-04-19 2차 확장
 * ═══════════════════════════════════════════════════════════════════ */

/* ─── Hint text (italic muted 보조 문구) ─────────────────────── */
.hint-text {
  font-size: var(--fs-xs);
  color: var(--color-muted);
  font-style: italic;
}

/* ─── Description box (템플릿/모드 설명 카드) ───────────────── */
.description-box {
  padding: 10px 12px;
  background: var(--color-section-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
}
.description-box__name {
  font-weight: 600;
  font-size: var(--fs-xs);
  margin-bottom: 4px;
}
.description-box__meta {
  color: var(--color-muted);
  margin-bottom: 4px;
}
.description-box__meta code {
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  background: var(--color-card-bg);
  padding: 1px 4px;
  border-radius: 3px;
}
.description-box__text {
  font-style: italic;
  color: var(--color-muted);
}

/* ─── Matrix 보조 요소 (wrap·info·컬럼 너비·셀 유틸) ────────── */
.matrix-wrap {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.matrix-info {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin-bottom: 8px;
  background: var(--color-primary-glow);
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
}
.matrix-info__cus {
  margin-left: auto;
  color: var(--color-muted);
}
.matrix__col-menu { text-align: left; width: 50%; }
.matrix__col-act  { width: 36px; text-align: center; }
.matrix__cell     { text-align: center; }
.matrix__cell input[type="checkbox"],
.matrix__cell-check input[type="checkbox"] {
  accent-color: var(--color-primary);
  cursor: pointer;
}
.matrix__cell-del { text-align: center; width: 50px; }
.matrix__key {
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  font-size: var(--fs-code);
  color: var(--color-muted);
}

/* ─── Accordion 추가 sub-elements (header-left, header-actions, summary, arrow--sm) ─── */
.accordion__header-left {
  display: flex;
  align-items: center;
  gap: 12px;
}
/* 헤더 우측 액션 영역 — 버튼 + arrow 를 묶어 space-between 레이아웃에 함께 배치 */
.accordion__header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.accordion__summary {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  font-size: var(--fs-code);
}
.accordion__arrow--sm {
  font-size: 9px;
}

/* ─── List item sub-elements (item 내부 구성요소) ──────────── */
.list__item-title {
  font-weight: 600;
  font-size: var(--fs-sm);
  display: flex;
  align-items: center;
  gap: 6px;
}
.list__item-meta {
  font-size: var(--fs-code);
  color: var(--color-muted);
  display: flex;
  gap: 4px;
}
.list__item-meta code {
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  background: var(--color-table-th-bg);
  padding: 1px 4px;
  border-radius: 3px;
  font-size: 10px;
}
.list__item-desc {
  font-size: var(--fs-code);
  color: var(--color-muted);
  margin-top: 4px;
  font-style: italic;
}
.list__item-label {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  cursor: pointer;
}
.list__item-icon {
  color: var(--color-primary);
  font-size: 14px;
  width: 18px;
  text-align: center;
}
.list__item-name { font-weight: 500; }
.list__item-count {
  color: var(--color-muted);
  font-size: var(--fs-code);
}
.list__item-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}
.list__item-drag {
  padding: 0 6px 0 0;
  display: flex;
  align-items: center;
  color: var(--color-muted);
  font-size: var(--fs-code);
  cursor: grab;
}

/* list item font-weight for active (background/color 는 상위 정의 사용 — 다크모드 대응) */
.list__item.is-active { font-weight: 600; }

/* ─── List 그룹 (섹션 타이틀로 묶기) ────────────────────────── */
.list__group-wrap {
  margin-bottom: 12px;
}
.list__group-wrap + .list__group-wrap {
  margin-top: 12px;
}
.list__group {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* ─── Tree 추가 sub-elements ────────────────────────────────── */
.tree__text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.tree__state-icon {
  font-size: 10px;
  color: var(--color-muted);
  transition: transform 0.2s ease;
  width: 12px;
  text-align: center;
  flex-shrink: 0;
}
.tree__group {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  margin-bottom: 8px;
  overflow: hidden;
}
.tree__group-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background-color: var(--color-table-th-bg);
  border-bottom: 1px solid var(--color-border);
}
.tree__group-icon {
  color: var(--color-primary);
  font-size: 13px;
}
.tree__group-name {
  font-weight: 600;
  font-size: var(--fs-sm);
}
.tree__group-id {
  color: var(--color-muted);
  font-size: var(--fs-code);
}
.tree__group-actions {
  margin-left: auto;
  display: flex;
  gap: 4px;
}
.tree__item-info {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}
.tree__item-icon {
  color: var(--color-muted);
  font-size: var(--fs-xs);
}
.tree__item-id {
  color: var(--color-muted);
  font-size: var(--fs-code);
}
.tree__item-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* ─── form__check 확장 (하이라이트 체크 라벨) ──────────────── */
.form__check--highlight {
  background: var(--color-section-bg);
  border: 1px solid var(--color-border);
  padding: 7px 16px;
  border-radius: 8px;
  transition: all 0.2s ease;
}
.form__check--highlight:hover {
  background: var(--color-table-hover);
  border-color: var(--color-primary);
}

/* ─── Mode switcher (탭·토글 그룹 대체) ────────────────────── */
.mode-switcher {
  display: flex;
  gap: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 12px;
}

/* ─── Form section (폼 그룹 섹션 분리) ─────────────────────── */
.form-section {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--color-border);
}

/* ─── Hint section (점선 구분 보조 영역) ──────────────────── */
.hint-section {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--color-border);
}

/* ─── Split-panel 보조 modifier ─────────────────────────────── */
.split-panel__body--padded { padding: 16px; }
.split-panel__search {
  padding: 8px;
  border-bottom: 1px solid var(--color-border);
}
.split-panel__search input {
  width: 100%;
  font-size: var(--fs-sm);
}

/* ─── Card 상태/modifier 확장 ───────────────────────────────── */
.card.is-active {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 1px var(--color-primary);
}
.card--flush {
  background: var(--color-section-bg);
  border-radius: var(--radius-lg);
  padding: 17px;
  box-shadow: 0 0 0 1px var(--color-border);
  border: none;
}

/* ─── badge 보조 variant ────────────────────────────────────── */
.badge-danger-text {
  background: transparent;
  color: var(--color-danger);
  border: 1px solid var(--color-danger);
}
.btn-danger-text {
  background: transparent;
  color: var(--color-danger);
  border: 1px solid var(--color-danger);
}
.btn-danger-text:hover {
  background: var(--color-danger);
  color: #fff;
}

/* ═══════════════════════════════════════════════════════════════════
 * 이미지맵/에디터 공통 컴포넌트 — 2026-04-19 newsletter 이관
 * ═══════════════════════════════════════════════════════════════════ */

/* ─── Step indicator (단계 표시기) ────────────────────────────── */
.step-indicator {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 10px 16px;
  background: var(--color-section-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: var(--fs-xs);
}
.step-indicator__badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 20px;
  background: var(--color-section-bg);
  color: var(--color-muted);
  font-size: var(--fs-xs);
  letter-spacing: 0.2px;
  user-select: none;
}
.step-indicator__badge.is-active {
  background: var(--badge-info-bg);
  color: var(--badge-info-text);
}
.step-indicator__badge.is-done {
  background: var(--color-success);
  color: #fff;
}
.step-indicator__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.5;
}
.step-indicator__badge.is-active .step-indicator__dot,
.step-indicator__badge.is-done   .step-indicator__dot {
  opacity: 1;
}
.step-indicator__sep {
  color: var(--color-border);
  font-size: var(--fs-sm);
}

/* ─── Node status (서비스/노드 상태 배지) ────────────────────── */
.node-status {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: var(--fs-code);
  font-weight: 500;
  letter-spacing: 0.2px;
  vertical-align: middle;
  border: 1px solid transparent;
  white-space: nowrap;
}
.node-status__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.node-status.is-checking {
  color: var(--color-muted);
  background: var(--color-section-bg);
  border-color: var(--color-border);
}
.node-status.is-checking .node-status__dot {
  animation: status-pulse 1s ease-in-out infinite;
}
.node-status.is-ok {
  color: var(--color-success-text);
  background: var(--color-success-bg);
  border-color: var(--color-success-border);
}
.node-status.is-fail {
  color: var(--color-danger-text);
  background: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  cursor: pointer;
}
@keyframes status-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}

/* ─── Mode display (현재 모드 안내 박스) ─────────────────────── */
.mode-display {
  padding: 8px 12px;
  background: var(--color-section-bg);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  color: var(--color-muted);
}
.mode-display__label {
  font-weight: 500;
  color: var(--color-text);
}

/* ─── Code output (검은 배경 monospace 출력) ────────────────── */
.code-output {
  font-family: ui-monospace, monospace;
  font-size: var(--fs-sm);
  background: #0f172a;
  color: #e2e8f0;
  padding: 12px;
  border-radius: var(--radius-sm);
  max-height: 450px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-all;
}

/* ─── Button group (작은 버튼 그룹 — 크기 프리셋 등) ──────── */
.button-group {
  display: inline-flex;
  gap: 4px;
  flex-wrap: wrap;
  padding: 4px;
  background: var(--color-section-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
.button-group__btn {
  padding: var(--ctrl-py-xs) 10px;
  font-size: var(--fs-xs);
  background: transparent;
  border: none;
  cursor: pointer;
  border-radius: var(--radius-sm);
  color: var(--color-muted);
}
.button-group__btn:hover,
.button-group__btn.is-active {
  background: var(--color-primary);
  color: #fff;
}
/* ghost variant (no surrounding container) */
.button-group--ghost {
  background: transparent;
  border: none;
  padding: 0;
}
.button-group--ghost .button-group__btn {
  padding: var(--ctrl-py-xs) 10px;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
}
.button-group--ghost .button-group__btn:hover,
.button-group--ghost .button-group__btn.is-active {
  background: transparent;
  border-color: var(--color-primary);
  color: var(--color-primary);
}

/* ─── Recent cards (가로 스크롤 카드 리스트) ───────────────── */
.recent-list {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 6px 0;
}
.recent-list__item {
  flex-shrink: 0;
  width: 140px;
  padding: 8px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-card-bg);
  cursor: pointer;
  font-size: var(--fs-xs);
  transition: border-color 0.15s;
}
.recent-list__item:hover {
  border-color: var(--color-primary);
}
.recent-list__thumb {
  width: 100%;
  height: 72px;
  background: var(--color-section-bg);
  border-radius: var(--radius-sm);
  margin-bottom: 6px;
  background-size: cover;
  background-position: center;
}
.recent-list__title {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.recent-list__meta {
  color: var(--color-muted);
  font-size: 10px;
  margin-top: 2px;
}

/* ─── Candidate list (아코디언 리스트 — 자동 모드 후보 요소) ── */
.candidate {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  flex-shrink: 0;   /* .candidate-list flex column 내부에서 자연 높이 유지 — 총 높이 초과 시 부모(list)가 스크롤 */
}
.candidate__header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  cursor: pointer;
  user-select: none;
}
.candidate__header:hover { background: var(--color-table-hover); }
.candidate__selector {
  font-family: ui-monospace, monospace;
  font-size: var(--fs-xs);
  color: var(--color-primary);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.candidate__count {
  font-size: var(--fs-xs);
  color: var(--color-muted);
  white-space: nowrap;
}
.candidate__items {
  border-top: 1px solid var(--color-border);
  padding: 6px 10px;
  display: none;
  flex-direction: column;
  gap: 4px;
  background: var(--color-section-bg);
}
.candidate.is-expanded .candidate__items { display: flex; }
.candidate__item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-xs);
}
.candidate__item input[type="url"],
.candidate__item input[type="text"] {
  flex: 1;
  font-family: ui-monospace, monospace;
  font-size: var(--fs-xs);
}

/* ─── Candidate list container (스크롤 트리) ────────────────── */
.candidate-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 340px;
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-section-bg);
}

/* ─── Preview iframe ──────────────────────────────────────── */
.preview-frame {
  width: 100%;
  height: 500px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: #fff;
}

/* ─── Icon-btn 확장 (위험/비활성) ─────────────────────────── */
.icon-btn--danger {
  color: var(--color-danger);
  border-color: var(--color-danger);
}
.icon-btn--danger:hover {
  background: var(--color-danger);
  color: #fff;
  border-color: var(--color-danger);
}

/* ─── Form__meta (form hint 계열의 보조 메타 정보) ────────── */
.form__meta {
  font-size: var(--fs-xs);
  color: var(--color-muted);
  margin-top: 2px;
}

/* ─── Panel toolbar (split-panel 내부 sticky 상단 툴바) ────
 * 에디터 패널의 상단 고정 액션/모드 바. split-panel__col/__right 최상단에 배치.
 * 캔버스 에디터, 코드 에디터, 폼 에디터 등 범용 사용.
 * ─────────────────────────────────────────────────── */
.panel-toolbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--color-card-bg);
  /* border-bottom: 1px solid var(--color-border); */
  padding: 8px 0 4px 0;
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 4px;
  flex-shrink: 0;
}
/* 툴바 내부 인라인 버튼 그룹 (줄바꿈 없음) */
.panel-toolbar__group {
  display: inline-flex;
  gap: 6px;
  flex-shrink: 0;
}
/* 툴바 내부 좌측 정렬·남은 공간 차지 정보 슬롯 (모드 표시용) */
.panel-toolbar__info {
  flex: 1;
  min-width: 160px;
}

/* ─── Canvas editor (이미지맵 드로잉 / 이미지 영역 편집) ──── */
.canvas-editor {
  position: relative;
  line-height: 0;
}
.canvas-editor__wrap {
  flex: 1;
  min-height: 400px;
  border: 2px dashed var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-section-bg);
  overflow: auto;
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  margin-bottom: 12px;
}
.canvas-editor__wrap.is-empty {
  align-items: center;
  color: var(--color-muted);
  font-size: var(--fs-sm);
}
.canvas-editor__img {
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}
.canvas-editor__svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: auto;
  touch-action: none;
  -ms-touch-action: none;
  user-select: none;
}
.canvas-editor__first-marker {
  stroke: var(--color-warning);
  stroke-width: 1.5;
  pointer-events: none;
  animation: marker-pulse 1s ease-in-out infinite;
}
@keyframes marker-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}
.canvas-editor__shape {
  fill: rgba(59, 130, 246, 0.18);
  stroke: var(--color-primary);
  stroke-width: 2;
  cursor: pointer;
}
.canvas-editor__shape--preview {
  fill: rgba(59, 130, 246, 0.10);
  stroke: var(--color-primary);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
  pointer-events: none;
}
/* href(클릭 시 이동할 URL) 가 설정된 영역 — 푸른색 계열로 강조 */
.canvas-editor__shape.is-configured {
  fill: rgba(37, 99, 235, 0.30);
  stroke: #2563eb;
  stroke-width: 2;
}
.canvas-editor__shape.is-selected {
  fill: rgba(234, 88, 12, 0.22);
  stroke: var(--color-warning);
  stroke-width: 3;
  stroke-dasharray: 4 2;
  cursor: move;
}
/* 선택+설정 동시 상태 — 선택 상태(orange) 우선 */
.canvas-editor__shape.is-configured.is-selected {
  fill: rgba(234, 88, 12, 0.22);
  stroke: var(--color-warning);
  stroke-dasharray: 4 2;
}
.canvas-editor__handle {
  fill: #fff;
  stroke: var(--color-primary);
  stroke-width: 1.5;
  pointer-events: auto;
  transition: r 0.1s, fill 0.1s;
}
.canvas-editor__handle:hover,
.canvas-editor__handle.is-active {
  fill: var(--color-primary);
}
.canvas-editor__handle[data-corner="nw"],
.canvas-editor__handle[data-corner="se"] { cursor: nwse-resize; }
.canvas-editor__handle[data-corner="ne"],
.canvas-editor__handle[data-corner="sw"] { cursor: nesw-resize; }
.canvas-editor__handle[data-corner="n"],
.canvas-editor__handle[data-corner="s"] { cursor: ns-resize; }
.canvas-editor__handle[data-corner="e"],
.canvas-editor__handle[data-corner="w"] { cursor: ew-resize; }

/* ═══════════════════════════════════════════════════════════════════
 * 코드 에디터 / 검증 리스트 / 전송 레이아웃 — 2026-04-19 webzine 이관
 * ═══════════════════════════════════════════════════════════════════ */

/* ─── Code editor (CodeMirror 래퍼 + textarea fallback) ───── */
.code-editor {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.cm-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.cm-wrap .CodeMirror,
.cm-wrap .cm-editor {
  flex: 1;
  height: 100%;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  line-height: 1.6;
}
.cm-wrap .cm-editor { overflow: hidden; }
.cm-wrap .cm-scroller { overflow: auto; }

.code-editor__textarea {
  width: 100%;
  min-height: 300px;
  padding: 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
  font-size: var(--fs-sm);
  line-height: 1.6;
  resize: vertical;
  background: #1e1e2e;
  color: #cdd6f4;
  tab-size: 2;
}
.code-editor__textarea--css {
  font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
}

/* ─── Validation list (검증 결과 리스트) ─────────────────── */
.validation-list {
  list-style: none;
  margin: 0;
  padding: 12px;
}
.validation-list__item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
  font-size: var(--fs-sm);
  border-bottom: 1px solid var(--color-border);
}
.validation-list__item:last-child { border-bottom: none; }
.validation-list__item.is-success { color: var(--color-success-text); }
.validation-list__item.is-error   { color: var(--color-danger-text); }
.validation-list__item.is-warning { color: var(--color-warning-text); }

/* ─── Preview frame content (iframe wrap 확장) ───────────── */
.preview-frame__content {
  width: 100%;
  height: 100%;
  border: none;
  background: #fff;
}

/* ─── Preview layout (iframe + side panel 2열) ─────────── */
.preview-layout {
  display: flex;
  gap: 12px;
  flex: 1;
  min-height: 0;
}
.preview-layout__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.preview-layout__side {
  flex: 0 0 300px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow-y: auto;
}

/* ─── Transfer layout (2개 패널 + 버튼 중앙 — 항목 이동용) ─── */
.transfer-layout {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 12px;
  align-items: stretch;
  min-height: 0;
}
.transfer-layout__panel {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-card-bg);
  overflow: hidden;
  min-height: 0;
}
.transfer-layout__panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}
.transfer-buttons {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  padding: 0 8px;
}
.transfer-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: background 0.15s;
}
.transfer-item:hover { background: var(--color-table-hover); }
.transfer-item.is-selected {
  background: var(--color-primary-glow);
  color: var(--color-primary);
}

/* ─── Selector bar (상단 고객사·볼륨 선택 바) ─────────── */
.selector-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  flex-shrink: 0;
}
.selector-bar__item {
  display: flex;
  align-items: center;
  gap: 6px;
}
.selector-bar__label {
  font-size: var(--fs-xs);
  color: var(--color-muted);
  font-weight: 500;
  white-space: nowrap;
}
.selector-bar__select {
  min-width: 180px;
}
.selector-bar__fixed {
  display: inline-flex;
  align-items: center;
  min-width: 180px;
  padding: var(--ctrl-py) 10px;
  background: var(--color-section-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  color: var(--color-text);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.selector-bar__deploy {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}
.selector-bar__deploy-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--color-section-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  color: var(--color-text);
  text-decoration: none;
  transition: all 0.15s;
}
.selector-bar__deploy-link:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

/* ─── Editor content (에디터 본문 영역) ─────────────────── */
.editor-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  gap: 8px;
}
/* @deprecated — `.split-panel__body` 로 통합. 기존 외부 사용 호환을 위해 alias 만 유지. 신규 사용 금지. */
.editor-panel-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.editor-toolbar {
  display: flex;
  gap: 8px;
  padding: 8px 0;
  border-top: 1px solid var(--color-border);
  margin-top: 8px;
}

/* ─── Visual editor placeholder ─────────────────────────── */
.visual-editor {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 300px;
  background: var(--color-section-bg);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-sm);
}
.visual-editor__placeholder {
  color: var(--color-muted);
  text-align: center;
  font-size: var(--fs-sm);
}
