/* ============================================================
   TAP-Core V6.0 — 공통 컴포넌트 스타일시트
   TapModal, TapTreeView, TapImageOptimizer, TapFormulaInput, TapNotify
   ============================================================ */

/* ============================================================
   1. TapModal — 커스텀 모달 시스템
   ============================================================ */
.tap-modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.45);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity 0.2s ease;
  padding: 24px;
}
.tap-modal-overlay.tap-modal-visible { opacity: 1; }
.tap-modal {
  background: var(--bg-card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-height: 90vh;
  display: flex; flex-direction: column;
  transform: translateY(12px) scale(0.97);
  transition: transform 0.2s ease;
}
.tap-modal-visible .tap-modal { transform: translateY(0) scale(1); }
.tap-modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-light);
  flex-shrink: 0;
}
.tap-modal-title { font-size: 16px; font-weight: 600; color: var(--text); }
.tap-modal-close {
  background: none; border: none; font-size: 22px;
  cursor: pointer; color: var(--text-muted);
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm); transition: background 0.15s;
}
.tap-modal-close:hover { background: var(--bg); color: var(--text); }
.tap-modal-body {
  padding: 20px;
  overflow-y: auto; flex: 1;
}
.tap-modal-message { font-size: 14px; color: var(--text-secondary); line-height: 1.7; }
.tap-modal-input { width: 100%; margin-top: 12px; }
.tap-modal-footer {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 12px 20px;
  border-top: 1px solid var(--border-light);
  flex-shrink: 0;
}
/* 로딩 모달 */
.tap-modal-loading-content {
  display: flex; flex-direction: column; align-items: center;
  gap: 16px; padding: 32px 20px;
}
.tap-spinner {
  width: 36px; height: 36px;
  border: 3px solid var(--border-light);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: tap-spin 0.7s linear infinite;
}
@keyframes tap-spin { to { transform: rotate(360deg); } }

/* ============================================================
   2. TapTreeView — 트리 뷰 컴포넌트
   ============================================================ */
.tap-tree-container { display: flex; flex-direction: column; gap: 8px; }
.tap-tree-search { position: sticky; top: 0; z-index: 1; background: var(--bg-card); padding-bottom: 4px; }
.tap-tree-search-input { width: 100%; font-size: 13px; }
.tap-tree-body { overflow-y: auto; }
.tap-tree-empty { padding: 24px; text-align: center; color: var(--text-muted); font-size: 13px; }
.tap-tree-row {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 8px; border-radius: var(--radius-sm);
  cursor: pointer; font-size: 13px;
  transition: background 0.12s;
  user-select: none;
}
.tap-tree-row:hover { background: var(--primary-light); }
.tap-tree-row.selected { background: #dbeafe; outline: 1px solid var(--primary); }
.tap-tree-toggle {
  width: 16px; text-align: center; font-size: 10px;
  color: var(--text-muted); flex-shrink: 0; cursor: pointer;
  transition: transform 0.15s;
}
.tap-tree-toggle.expanded { color: var(--text-secondary); }
.tap-tree-toggle.no-children { visibility: hidden; }
.tap-tree-icon { font-size: 15px; flex-shrink: 0; }
.tap-tree-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; color: var(--text); }
.tap-tree-sub { font-size: 11px; color: var(--text-muted); flex-shrink: 0; }
.tap-tree-badge { flex-shrink: 0; }

/* ============================================================
   3. TapImageOptimizer — 이미지 업로드
   ============================================================ */
.tap-img-uploader { display: flex; flex-direction: column; gap: 12px; }
.tap-img-dropzone {
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  padding: 32px 20px;
  text-align: center; cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
  color: var(--text-secondary); font-size: 13px;
}
.tap-img-dropzone:hover { border-color: var(--primary); background: var(--primary-light); }
.tap-img-dropzone.drag-over { border-color: var(--primary); background: #dbeafe; }
.tap-img-dropzone-icon { font-size: 36px; margin-bottom: 8px; }
.tap-img-dropzone-hint { font-size: 11px; color: var(--text-muted); margin-top: 4px; }
.tap-img-preview-list { display: flex; flex-wrap: wrap; gap: 8px; }
.tap-img-preview-item {
  position: relative; width: 100px;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-sm); overflow: hidden;
}
.tap-img-preview-item img { width: 100%; height: 70px; object-fit: cover; display: block; }
.tap-img-preview-info {
  padding: 4px 6px; font-size: 10px; color: var(--text-secondary);
  display: flex; flex-direction: column; gap: 1px;
}
.tap-img-preview-size { color: var(--success); }
.tap-img-preview-remove {
  position: absolute; top: 2px; right: 2px;
  background: rgba(0,0,0,0.6); color: #fff;
  border: none; border-radius: 50%; width: 18px; height: 18px;
  font-size: 12px; cursor: pointer; display: flex; align-items: center; justify-content: center;
}

/* ============================================================
   4. TapFormulaInput — 수식 입력 스타일 (기존 form-input 확장)
   ============================================================ */
.formula-input { font-family: 'Pretendard', monospace; text-align: right; }
.formula-input:focus { background: #fffbeb; }

/* ============================================================
   5. TapNotify — 토스트/스피너/스켈레톤
   ============================================================ */
/* 토스트 아이콘 추가 */
.toast-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%; font-size: 11px;
  flex-shrink: 0; font-weight: 700;
}
.toast-success .toast-icon { background: var(--success); color: #fff; }
.toast-error .toast-icon { background: var(--danger); color: #fff; }
.toast-warning .toast-icon { background: var(--warning); color: #fff; }
.toast-info .toast-icon { background: var(--info); color: #fff; }
.toast-message { flex: 1; }
.toast-close {
  background: none; border: none; color: inherit; opacity: 0.6;
  cursor: pointer; font-size: 16px; padding: 0 4px;
}
.toast-close:hover { opacity: 1; }

/* 인라인 스피너 */
.tap-spinner-wrap {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 12px;
  padding: 40px 20px; min-height: 120px;
}
.tap-spinner-msg { font-size: 13px; color: var(--text-secondary); }

/* 스켈레톤 */
.tap-skeleton-wrap { display: flex; flex-direction: column; gap: 12px; padding: 8px 0; }
.tap-skeleton-line {
  height: 14px; border-radius: 4px;
  background: linear-gradient(90deg, #eee 25%, #f5f5f5 50%, #eee 75%);
  background-size: 200% 100%;
  animation: tap-shimmer 1.5s ease infinite;
}
.tap-skeleton-line.w-100 { width: 100%; }
.tap-skeleton-line.w-90 { width: 90%; }
.tap-skeleton-line.w-80 { width: 80%; }
.tap-skeleton-line.w-70 { width: 70%; }
.tap-skeleton-line.w-60 { width: 60%; }
.tap-skeleton-line.w-55 { width: 55%; }
.tap-skeleton-line.w-40 { width: 40%; }
.tap-skeleton-card {
  padding: 16px; border: 1px solid var(--border-light);
  border-radius: var(--radius); display: flex; flex-direction: column; gap: 10px;
}
.tap-skeleton-table { display: flex; flex-direction: column; gap: 8px; }
.tap-skeleton-row { display: flex; gap: 12px; }
.tap-skeleton-cell { height: 14px; border-radius: 4px; background: linear-gradient(90deg, #eee 25%, #f5f5f5 50%, #eee 75%); background-size: 200% 100%; animation: tap-shimmer 1.5s ease infinite; }
.tap-skeleton-cell.w-20 { width: 20%; }
.tap-skeleton-cell.w-25 { width: 25%; }
.tap-skeleton-cell.w-30 { width: 30%; }
.tap-skeleton-cell.w-15 { width: 15%; }
@keyframes tap-shimmer { 0%{background-position:200% 0} 100%{background-position:-200% 0} }

/* 빈 상태 / 에러 상태 */
/* ============================================================
   6. KPI 카드 — 대시보드 주요 지표
   ============================================================ */
.kpi-card { position: relative; overflow: hidden; }
.kpi-header { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.kpi-icon {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 8px; font-size: 16px; flex-shrink: 0;
}
.kpi-icon-project { background: #eff6ff; }
.kpi-icon-revenue { background: #f0fdf4; }
.kpi-icon-cost { background: #fffbeb; }
.kpi-icon-invoice { background: #fef2f2; }
.kpi-sub { font-size: 11px; color: var(--text-muted); margin-top: 2px; min-height: 16px; }
.kpi-sub-danger { color: var(--danger); font-weight: 600; }
.kpi-sub-warning { color: var(--warning); font-weight: 600; }
.kpi-sub-success { color: var(--success); font-weight: 600; }

/* ============================================================
   7. 프로젝트 원가 게이지 — 매출 대비 원가율 시각화
   ============================================================ */
.cost-gauge-item {
  padding: 14px 16px; border-radius: var(--radius-sm);
  border-left: 4px solid var(--border); margin-bottom: 10px;
  background: var(--bg); transition: background 0.15s;
}
.cost-gauge-item:hover { background: #f0f0f3; }
.cost-gauge-safe { border-left-color: var(--success); }
.cost-gauge-warning { border-left-color: var(--warning); background: #fffdf5; }
.cost-gauge-danger { border-left-color: var(--danger); background: #fef8f8; }
.cost-gauge-critical { border-left-color: #991b1b; background: #fef2f2; }
.cost-gauge-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.cost-gauge-name { font-size: 14px; font-weight: 600; color: var(--text); }
.cost-gauge-badge { font-size: 11px; font-weight: 600; }
.cost-gauge-numbers { display: flex; justify-content: space-between; font-size: 12px; color: var(--text-secondary); margin-bottom: 8px; }
.cost-gauge-numbers strong { color: var(--text); }
.cost-gauge-rate { font-size: 20px; font-weight: 800; line-height: 1; }
.cost-rate-safe { color: var(--success); }
.cost-rate-warning { color: var(--warning); }
.cost-rate-danger { color: var(--danger); }
.cost-rate-critical { color: #991b1b; }
.cost-gauge-bar { position: relative; margin-top: 2px; }
.cost-gauge-bar-bg { height: 18px; background: #e5e7eb; border-radius: 9px; overflow: hidden; }
.cost-gauge-bar-fill {
  height: 100%; border-radius: 9px; display: flex; overflow: hidden;
  transition: width 0.6s ease;
}
.cost-bar-safe { background: var(--success); }
.cost-bar-warning { background: var(--warning); }
.cost-bar-danger { background: var(--danger); }
.cost-bar-critical { background: #991b1b; animation: cost-pulse 1.5s ease infinite; }
@keyframes cost-pulse { 0%,100%{opacity:1;} 50%{opacity:0.7;} }
.cost-seg { display: block; height: 100%; min-width: 3px; }
.cost-gauge-markers { position: relative; height: 14px; font-size: 9px; color: var(--text-muted); margin-top: 2px; }
.cost-gauge-markers span { position: absolute; transform: translateX(-50%); }
.cost-gauge-legend {
  display: flex; gap: 14px; justify-content: center; padding: 10px 0 4px;
  font-size: 11px; color: var(--text-secondary);
}
.cost-dot { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 3px; vertical-align: middle; }

/* ============================================================
   8. 미귀속 데이터 패널 — 대시보드 알림
   ============================================================ */
.unalloc-panel { border-left: 4px solid var(--warning); background: var(--warning-light); }
.unalloc-header { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.unalloc-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; height: 24px; padding: 0 6px;
  background: var(--danger); color: #fff; border-radius: 12px;
  font-size: 12px; font-weight: 700;
}
.unalloc-grid { display: flex; gap: 10px; flex-wrap: wrap; }
.unalloc-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; background: var(--bg-card);
  border: 1px solid var(--border-light); border-radius: var(--radius-sm);
  cursor: pointer; transition: all 0.15s; flex: 1; min-width: 200px;
}
.unalloc-item:hover { border-color: var(--primary); background: var(--primary-light); }
.unalloc-icon { font-size: 22px; flex-shrink: 0; }
.unalloc-info { flex: 1; display: flex; flex-direction: column; gap: 1px; }
.unalloc-label { font-size: 13px; font-weight: 600; color: var(--text); }
.unalloc-count { font-size: 11px; color: var(--text-secondary); }
.unalloc-arrow { font-size: 18px; color: var(--text-muted); flex-shrink: 0; }
/* 미귀속 모달 테이블 */
.unalloc-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.unalloc-table th { padding: 8px 10px; background: var(--bg); text-align: left; font-weight: 600; color: var(--text-secondary); font-size: 11px; text-transform: uppercase; border-bottom: 2px solid var(--border-light); white-space: nowrap; }
.unalloc-table td { padding: 8px 10px; border-bottom: 1px solid var(--border-light); }
.unalloc-table tr:hover { background: var(--primary-light); }
.unalloc-table .text-right { text-align: right; }
.btn-sm { padding: 4px 10px; font-size: 11px; }

/* ============================================================
   9. AI 매칭 추천 — 미귀속 테이블 내 AI 결과
   ============================================================ */
.ai-suggest-cell { min-width: 140px; }
.ai-suggest-result { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.ai-suggest-name { font-size: 11px; font-weight: 600; color: var(--text); max-width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-suggest-conf { font-size: 10px; font-weight: 700; padding: 1px 5px; border-radius: 8px; }
.ai-conf-high { background: #dcfce7; color: #166534; }
.ai-conf-mid { background: #fef9c3; color: #854d0e; }
.ai-conf-low { background: #fee2e2; color: #991b1b; }
.ai-accept-btn { background: var(--success) !important; color: #fff !important; border: none; font-size: 10px !important; padding: 2px 6px !important; cursor: pointer; border-radius: 4px; }
.ai-accept-btn:hover { background: #15803d !important; }

/* ============================================================
   10. 원가 트리 요약 — 금융관리 원가 뷰어
   ============================================================ */
.cost-tree-summary { padding: 4px 0; }
.cost-tree-row { display: flex; justify-content: space-between; padding: 8px 0; font-size: 14px; }
.cost-tree-row strong { font-weight: 700; }

.tap-empty-state, .tap-error-state {
  display: flex; flex-direction: column; align-items: center;
  gap: 8px; padding: 48px 20px; text-align: center;
}
.tap-empty-icon, .tap-error-icon { font-size: 40px; }
.tap-empty-state p, .tap-error-state p { font-size: 14px; color: var(--text-muted); }
.tap-error-retry { margin-top: 8px; }
