/* ============================================================
   components.css — 공통 컴포넌트 (BEM)
   네이밍: [앱접두사]-[블록]__[요소]--[상태]
   ⚠️ tokens.css → base.css 이후 로드
   ============================================================ */

/* ══════════════════════════════════════════
   버튼
══════════════════════════════════════════ */
.nv-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--nv-sp-2);
  padding: var(--nv-sp-2) var(--nv-sp-4);
  border-radius: var(--nv-r-md);
  font-size: var(--nv-text-sm);
  font-weight: var(--nv-fw-medium);
  line-height: 1;
  transition: background var(--nv-tr-fast), opacity var(--nv-tr-fast), transform var(--nv-tr-fast);
  white-space: nowrap;
  cursor: pointer;
  border: none;
  user-select: none;
}
.nv-btn:active:not(:disabled) { transform: scale(0.97); }
.nv-btn:disabled               { opacity: 0.4; cursor: not-allowed; }

/* 크기 */
.nv-btn--sm   { padding: var(--nv-sp-1) var(--nv-sp-3); font-size: var(--nv-text-xs); }
.nv-btn--lg   { padding: var(--nv-sp-3) var(--nv-sp-6); font-size: var(--nv-text-base); }
.nv-btn--full { width: 100%; }

/* 변형 */
.nv-btn--primary   { background: var(--nv-primary); color: #fff; }
.nv-btn--primary:hover:not(:disabled) { background: var(--nv-primary-h); }

.nv-btn--secondary { background: var(--nv-surface); color: var(--nv-text); border: 1px solid var(--nv-border); }
.nv-btn--secondary:hover:not(:disabled) { background: var(--nv-bg-3); }

.nv-btn--ghost     { background: transparent; color: var(--nv-text-2); }
.nv-btn--ghost:hover:not(:disabled) { background: var(--nv-surface); color: var(--nv-text); }

.nv-btn--danger    { background: var(--nv-error); color: #fff; }
.nv-btn--danger:hover:not(:disabled) { opacity: 0.85; }

.nv-btn--nvc       { background: var(--nv-nvc); color: #111; font-weight: var(--nv-fw-bold); }

/* ══════════════════════════════════════════
   폼
══════════════════════════════════════════ */
.nv-form-group  { display: flex; flex-direction: column; gap: var(--nv-sp-2); }

.nv-label {
  font-size: var(--nv-text-sm);
  font-weight: var(--nv-fw-medium);
  color: var(--nv-text-2);
}

.nv-input,
.nv-select,
.nv-textarea {
  width: 100%;
  padding: var(--nv-sp-2) var(--nv-sp-3);
  background: var(--nv-bg-3);
  border: 1px solid var(--nv-border);
  border-radius: var(--nv-r-md);
  color: var(--nv-text);
  font-size: var(--nv-text-sm);
  transition: border-color var(--nv-tr-fast), box-shadow var(--nv-tr-fast);
}
.nv-input:focus,
.nv-select:focus,
.nv-textarea:focus {
  border-color: var(--nv-primary);
  box-shadow: 0 0 0 3px rgba(108,99,255,0.2);
  outline: none;
}
.nv-input--error { border-color: var(--nv-error); }
.nv-textarea     { resize: vertical; min-height: 100px; }
.nv-select       { cursor: pointer; }
.nv-form-error   { font-size: var(--nv-text-xs); color: var(--nv-error); }

/* ══════════════════════════════════════════
   카드
══════════════════════════════════════════ */
.nv-card {
  background: var(--nv-bg-2);
  border: 1px solid var(--nv-border);
  border-radius: var(--nv-r-lg);
  padding: var(--nv-sp-4);
}
.nv-card--hoverable {
  transition: border-color var(--nv-tr-normal), box-shadow var(--nv-tr-normal);
  cursor: pointer;
}
.nv-card--hoverable:hover { border-color: var(--nv-primary); box-shadow: var(--nv-shadow-md); }

/* 통계 카드 */
.nv-stat-card {
  background: var(--nv-bg-2);
  border: 1px solid var(--nv-border);
  border-radius: var(--nv-r-lg);
  padding: var(--nv-sp-4) var(--nv-sp-5);
  display: flex; flex-direction: column; gap: var(--nv-sp-2);
}
.nv-stat-card__label  { font-size: var(--nv-text-xs); color: var(--nv-text-3); text-transform: uppercase; letter-spacing: 0.05em; }
.nv-stat-card__value  { font-size: var(--nv-text-2xl); font-weight: var(--nv-fw-bold); }
.nv-stat-card__value--nvc    { color: var(--nv-nvc); }
.nv-stat-card__value--points { color: var(--nv-points); }

/* ══════════════════════════════════════════
   뱃지
══════════════════════════════════════════ */
.nv-badge {
  display: inline-flex; align-items: center;
  padding: 2px var(--nv-sp-2);
  border-radius: var(--nv-r-full);
  font-size: var(--nv-text-xs);
  font-weight: var(--nv-fw-semibold);
  line-height: 1.4; white-space: nowrap;
}
.nv-badge--primary  { background: rgba(108,99,255,0.2);  color: var(--nv-primary-h); }
.nv-badge--success  { background: rgba(76,175,80,0.2);   color: var(--nv-success); }
.nv-badge--warning  { background: rgba(255,193,7,0.2);   color: var(--nv-warning); }
.nv-badge--error    { background: rgba(244,67,54,0.2);   color: var(--nv-error); }
.nv-badge--nvc      { background: rgba(255,215,0,0.2);   color: var(--nv-nvc); }
.nv-badge--soon     { background: var(--nv-surface);     color: var(--nv-text-3); }
.nv-badge--free     { background: rgba(107,108,128,0.2); color: var(--tier-free); }
.nv-badge--basic    { background: rgba(120,193,243,0.2); color: var(--tier-basic); }
.nv-badge--pro      { background: rgba(108,99,255,0.2);  color: var(--tier-pro); }
.nv-badge--premium  { background: rgba(255,215,0,0.2);   color: var(--tier-premium); }
.nv-badge--vip      { background: rgba(255,107,107,0.2); color: var(--tier-vip); }

/* ══════════════════════════════════════════
   스켈레톤
══════════════════════════════════════════ */
.nv-skeleton {
  background: var(--nv-border);
  border-radius: var(--nv-r-md);
  animation: nv-skeleton-pulse 1.5s ease-in-out infinite;
}
.nv-skeleton--text   { height: 1em; width: 100%; }
.nv-skeleton--circle { border-radius: var(--nv-r-full); }
.nv-skeleton--card   { height: 120px; width: 100%; }

/* ══════════════════════════════════════════
   스피너
══════════════════════════════════════════ */
.nv-spinner {
  width: 20px; height: 20px;
  border: 2px solid var(--nv-border);
  border-top-color: var(--nv-primary);
  border-radius: var(--nv-r-full);
  animation: nv-spin 600ms linear infinite;
  flex-shrink: 0;
}
.nv-spinner--sm { width: 14px; height: 14px; }
.nv-spinner--lg { width: 32px; height: 32px; border-width: 3px; }

/* ══════════════════════════════════════════
   토스트 컨테이너
══════════════════════════════════════════ */
#nv-toast-container {
  position: fixed;
  top: calc(var(--nv-header-h) + var(--nv-sp-4));
  right: var(--nv-sp-4);
  z-index: var(--z-toast);
  display: flex; flex-direction: column; gap: var(--nv-sp-2);
  pointer-events: none;
  max-width: 360px;
  width: calc(100% - var(--nv-sp-8));
}
.nv-toast {
  display: flex; align-items: flex-start; gap: var(--nv-sp-3);
  padding: var(--nv-sp-3) var(--nv-sp-4);
  background: var(--nv-surface);
  border: 1px solid var(--nv-border);
  border-radius: var(--nv-r-lg);
  box-shadow: var(--nv-shadow-lg);
  pointer-events: auto;
  animation: nv-toast-in 200ms ease forwards;
  font-size: var(--nv-text-sm);
}
.nv-toast--success { border-left: 3px solid var(--nv-success); }
.nv-toast--error   { border-left: 3px solid var(--nv-error); }
.nv-toast--warning { border-left: 3px solid var(--nv-warning); }
.nv-toast--info    { border-left: 3px solid var(--nv-info); }
.nv-toast__icon { font-size: 1.1em; flex-shrink: 0; margin-top: 1px; }
.nv-toast__msg  { flex: 1; color: var(--nv-text); }

/* ══════════════════════════════════════════
   글로벌 로딩 오버레이
══════════════════════════════════════════ */
#nv-loading-overlay {
  position: fixed; inset: 0;
  background: rgba(22,23,28,0.7);
  z-index: var(--z-overlay);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none;
  transition: opacity var(--nv-tr-normal);
}
#nv-loading-overlay.is-visible { opacity: 1; pointer-events: auto; }

/* ══════════════════════════════════════════
   프로그레스 바
══════════════════════════════════════════ */
.nv-progress {
  width: 100%; height: 6px;
  background: var(--nv-bg-3);
  border-radius: var(--nv-r-full);
  overflow: hidden;
}
.nv-progress__bar {
  height: 100%; background: var(--nv-primary);
  border-radius: var(--nv-r-full);
  transition: width var(--nv-tr-normal);
}
.nv-progress__bar--success { background: var(--nv-success); }
.nv-progress__bar--nvc     { background: var(--nv-nvc); }

/* EXP 게이지 */
.nv-exp-bar { height: 8px; background: var(--nv-bg-3); border-radius: var(--nv-r-full); overflow: hidden; }
.nv-exp-bar__fill {
  height: 100%;
  background: linear-gradient(90deg, var(--nv-primary) 0%, var(--nv-secondary) 100%);
  border-radius: var(--nv-r-full);
  transition: width 600ms cubic-bezier(0.34,1.56,0.64,1);
}

/* ══════════════════════════════════════════
   아바타
══════════════════════════════════════════ */
.nv-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--nv-r-full);
  background: var(--nv-surface);
  color: var(--nv-text-2);
  font-weight: var(--nv-fw-semibold);
  overflow: hidden; flex-shrink: 0;
}
.nv-avatar img { width: 100%; height: 100%; object-fit: cover; }
.nv-avatar--sm { width: 28px; height: 28px; font-size: var(--nv-text-xs); }
.nv-avatar--md { width: 36px; height: 36px; font-size: var(--nv-text-sm); }
.nv-avatar--lg { width: 48px; height: 48px; font-size: var(--nv-text-base); }
.nv-avatar--xl { width: 64px; height: 64px; font-size: var(--nv-text-xl); }

/* ══════════════════════════════════════════
   기타
══════════════════════════════════════════ */
.nv-divider { width: 100%; height: 1px; background: var(--nv-border); }

.nv-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--nv-sp-3); padding: var(--nv-sp-16) var(--nv-sp-8);
  color: var(--nv-text-3); text-align: center;
}
.nv-empty__icon  { font-size: 3rem; opacity: 0.5; }
.nv-empty__title { font-size: var(--nv-text-lg); font-weight: var(--nv-fw-semibold); color: var(--nv-text-2); }
.nv-empty__desc  { font-size: var(--nv-text-sm); }

/* SPA 에러 바운더리 Fallback */
#app-fallback {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 100vh; gap: var(--nv-sp-4);
  color: var(--nv-text-2); text-align: center; padding: var(--nv-sp-8);
}

/* ══════════════════════════════════════════
   네비게이션 컴포넌트 (BEM: nav-)
══════════════════════════════════════════ */
.nav-list {
  list-style: none;
  padding: 0; margin: 0;
  display: flex; flex-direction: column;
  gap: 2px;
}

/* LNB 아이템 행 */
.nav-item__row {
  display: flex; align-items: center;
  gap: var(--nv-sp-3);
  padding: var(--nv-sp-2) var(--nv-sp-3);
  border-radius: var(--nv-r-md);
  cursor: pointer;
  color: var(--nv-text-2);
  font-size: var(--nv-text-sm);
  white-space: nowrap; overflow: hidden;
  transition: background var(--nv-tr-fast), color var(--nv-tr-fast);
  min-height: 40px;
  user-select: none;
}
.nav-item__row:hover { background: var(--nv-surface); color: var(--nv-text); }
.nav-item__row.is-active {
  background: rgba(108,99,255,0.15);
  color: var(--nv-primary-h);
}

.nav-item__icon  { font-size: 1.1rem; flex-shrink: 0; width: 32px; text-align: center; }
.nav-item__label { flex: 1; opacity: 0; transition: opacity var(--nv-tr-normal); }
.nav-item__arrow {
  margin-left: auto; font-size: 12px; flex-shrink: 0;
  transition: transform var(--nv-tr-normal), opacity var(--nv-tr-normal);
  opacity: 0;
}
.nav-item__arrow.is-open { transform: rotate(90deg); }

/* 사이드바 열렸을 때 텍스트 보이기 */
.nv-sidebar.is-open .nav-item__label,
.nv-sidebar.is-open .nav-item__arrow,
.nv-sidebar.is-mobile-open .nav-item__label,
.nv-sidebar.is-mobile-open .nav-item__arrow { opacity: 1; }

/* 서브메뉴 아코디언 */
.nav-sub {
  list-style: none; padding: 0; margin: 0;
  max-height: 0; overflow: hidden;
  transition: max-height var(--nv-tr-normal);
}
.nav-sub.is-open { max-height: 500px; }

.nav-sub__item {
  display: flex; align-items: center; gap: var(--nv-sp-2);
  padding: var(--nv-sp-2) var(--nv-sp-3) var(--nv-sp-2) calc(var(--nv-sp-3) + 32px + var(--nv-sp-3));
  cursor: pointer;
  color: var(--nv-text-3); font-size: var(--nv-text-sm);
  border-radius: var(--nv-r-md);
  transition: background var(--nv-tr-fast), color var(--nv-tr-fast);
  white-space: nowrap; overflow: hidden;
}
.nav-sub__item:hover   { background: var(--nv-surface); color: var(--nv-text-2); }
.nav-sub__item.is-active { color: var(--nv-primary-h); }

/* 오버레이 메뉴 확대 스타일 */
.nv-menu-overlay .nav-item__row  { font-size: var(--nv-text-base); padding: var(--nv-sp-3) var(--nv-sp-4); min-height: 52px; }
.nv-menu-overlay .nav-item__label { opacity: 1; }
.nv-menu-overlay .nav-item__arrow { opacity: 1; }
.nv-menu-overlay .nav-sub__item  { font-size: var(--nv-text-sm); padding: var(--nv-sp-3) var(--nv-sp-4) var(--nv-sp-3) calc(var(--nv-sp-4) + 32px + var(--nv-sp-3)); }
