/* work-analysis.css - 최신 모던 디자인 */ /* ========== CSS 변수 정의 ========== */ :root { /* 색상 팔레트 - 모던하고 세련된 색상 */ --primary: #2563eb; --primary-light: #3b82f6; --primary-dark: #1d4ed8; --primary-bg: #eff6ff; --success: #10b981; --success-light: #34d399; --success-bg: #ecfdf5; --warning: #f59e0b; --warning-light: #fbbf24; --warning-bg: #fffbeb; --error: #ef4444; --error-light: #f87171; --error-bg: #fef2f2; --info: #06b6d4; --info-light: #22d3ee; --info-bg: #ecfeff; /* 중성 색상 */ --white: #ffffff; --gray-50: #f8fafc; --gray-100: #f1f5f9; --gray-200: #e2e8f0; --gray-300: #cbd5e1; --gray-400: #94a3b8; --gray-500: #64748b; --gray-600: #475569; --gray-700: #334155; --gray-800: #1e293b; --gray-900: #0f172a; /* 그라디언트 */ --gradient-primary: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); --gradient-success: linear-gradient(135deg, var(--success) 0%, var(--success-light) 100%); --gradient-warning: linear-gradient(135deg, var(--warning) 0%, var(--warning-light) 100%); --gradient-error: linear-gradient(135deg, var(--error) 0%, var(--error-light) 100%); --gradient-bg: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); /* 그림자 */ --shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05); --shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25); /* 테두리 반경 */ --radius-sm: 0.375rem; --radius: 0.5rem; --radius-md: 0.75rem; --radius-lg: 1rem; --radius-xl: 1.5rem; --radius-2xl: 2rem; --radius-full: 9999px; /* 간격 */ --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem; --space-5: 1.25rem; --space-6: 1.5rem; --space-8: 2rem; --space-10: 2.5rem; --space-12: 3rem; --space-16: 4rem; --space-20: 5rem; /* 전환 효과 */ --transition-fast: 150ms ease-in-out; --transition: 200ms ease-in-out; --transition-slow: 300ms ease-in-out; } /* ========== 기본 스타일 리셋 ========== */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--gradient-bg); color: var(--gray-800); line-height: 1.6; min-height: 100vh; } /* ========== 컨테이너 및 레이아웃 ========== */ .analysis-container { max-width: 1400px; margin: 0 auto; padding: var(--space-6); min-height: 100vh; } .page-header { background: var(--white); border-radius: var(--radius-xl); padding: var(--space-8); margin-bottom: var(--space-8); box-shadow: var(--shadow-lg); border: 1px solid var(--gray-200); position: relative; overflow: hidden; } .page-header::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--gradient-primary); } .page-title { font-size: 2.5rem; font-weight: 800; color: var(--gray-900); margin-bottom: var(--space-2); display: flex; align-items: center; gap: var(--space-3); } .page-title .icon { font-size: 2rem; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .page-subtitle { font-size: 1.125rem; color: var(--gray-600); font-weight: 400; } /* ========== 탭 네비게이션 ========== */ .analysis-tabs { background: var(--white); border-radius: var(--radius-xl); padding: var(--space-2); margin-bottom: var(--space-8); box-shadow: var(--shadow-md); border: 1px solid var(--gray-200); display: flex; gap: var(--space-2); } .tab-button { flex: 1; padding: var(--space-4) var(--space-6); border: none; border-radius: var(--radius-lg); font-size: 1rem; font-weight: 600; cursor: pointer; transition: var(--transition); position: relative; background: transparent; color: var(--gray-600); } .tab-button:hover { background: var(--gray-100); color: var(--gray-800); } .tab-button.active { background: var(--gradient-primary); color: var(--white); box-shadow: var(--shadow-md); } .tab-button.active::after { content: ''; position: absolute; bottom: -2px; left: 50%; transform: translateX(-50%); width: 20px; height: 3px; background: var(--white); border-radius: var(--radius-full); } /* ========== 분석 조건 설정 ========== */ .analysis-controls { background: var(--white); border-radius: var(--radius-xl); padding: var(--space-8); margin-bottom: var(--space-8); box-shadow: var(--shadow-lg); border: 1px solid var(--gray-200); } .controls-grid { display: grid; grid-template-columns: 1fr 1fr auto; gap: var(--space-6); margin-bottom: var(--space-6); } .form-group { display: flex; flex-direction: column; gap: var(--space-2); } .form-label { font-size: 0.875rem; font-weight: 600; color: var(--gray-700); display: flex; align-items: center; gap: var(--space-2); } .form-label .icon { font-size: 1rem; color: var(--primary); } .form-input, .form-select { padding: var(--space-3) var(--space-4); border: 2px solid var(--gray-200); border-radius: var(--radius); font-size: 0.875rem; transition: var(--transition); background: var(--white); color: var(--gray-800); } .form-input:focus, .form-select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); } .analyze-button { background: var(--gradient-primary); color: var(--white); border: none; padding: var(--space-4) var(--space-8); border-radius: var(--radius-lg); font-size: 1rem; font-weight: 600; cursor: pointer; transition: var(--transition); box-shadow: var(--shadow-md); display: flex; align-items: center; gap: var(--space-2); justify-self: start; } .analyze-button:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); } .analyze-button:active { transform: translateY(0); } .analyze-button .icon { font-size: 1.125rem; } /* ========== 결과 카드 그리드 ========== */ .results-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: var(--space-6); margin-bottom: var(--space-8); } .result-card { background: var(--white); border-radius: var(--radius-xl); padding: var(--space-6); box-shadow: var(--shadow-lg); border: 1px solid var(--gray-200); transition: var(--transition); position: relative; overflow: hidden; } .result-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-2xl); } .result-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--gradient-primary); } .result-card.success::before { background: var(--gradient-success); } .result-card.warning::before { background: var(--gradient-warning); } .result-card.error::before { background: var(--gradient-error); } .card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-4); } .card-title { font-size: 1.125rem; font-weight: 700; color: var(--gray-900); display: flex; align-items: center; gap: var(--space-2); } .card-title .icon { font-size: 1.25rem; color: var(--primary); } .card-value { font-size: 2rem; font-weight: 800; color: var(--primary); margin-bottom: var(--space-2); } .card-subtitle { font-size: 0.875rem; color: var(--gray-600); margin-bottom: var(--space-4); } .card-progress { width: 100%; height: 8px; background: var(--gray-200); border-radius: var(--radius-full); overflow: hidden; margin-bottom: var(--space-3); } .progress-bar { height: 100%; background: var(--gradient-primary); border-radius: var(--radius-full); transition: width var(--transition-slow); } .progress-bar.success { background: var(--gradient-success); } .progress-bar.warning { background: var(--gradient-warning); } .progress-bar.error { background: var(--gradient-error); } .card-stats { display: flex; justify-content: space-between; align-items: center; font-size: 0.75rem; color: var(--gray-500); } /* ========== 차트 컨테이너 ========== */ .chart-container { background: var(--white); border-radius: var(--radius-xl); padding: var(--space-8); box-shadow: var(--shadow-lg); border: 1px solid var(--gray-200); margin-bottom: var(--space-8); position: relative; min-height: 200px; /* 최소 높이만 설정 */ overflow: visible; /* 테이블이 보이도록 */ } /* 차트 컨테이너 타입별 스타일 */ .chart-container.chart-type { height: 450px; /* 차트일 때만 고정 높이 */ overflow: hidden; /* 차트일 때만 넘치는 부분 숨김 */ } .chart-container.table-type { height: auto; /* 테이블일 때는 자동 높이 */ overflow: visible; /* 테이블 전체 표시 */ max-height: none; /* 최대 높이 제한 해제 */ } .chart-container canvas { max-height: 380px !important; /* 캔버스 최대 높이 제한 */ width: 100% !important; } /* ========== 작업 보고서 테이블 ========== */ .table-container { overflow-x: auto; border-radius: var(--radius-lg); border: 1px solid var(--gray-200); } .work-report-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; background: var(--white); table-layout: fixed; /* 고정 레이아웃으로 열 너비 제어 */ } /* 열 너비 설정 */ .work-report-table th:nth-child(1), /* 작업자 */ .work-report-table td:nth-child(1) { width: 12%; } .work-report-table th:nth-child(2), /* 분류 */ .work-report-table td:nth-child(2) { width: 20%; } .work-report-table th:nth-child(3), /* 작업내용 */ .work-report-table td:nth-child(3) { width: 18%; } .work-report-table th:nth-child(4), /* 투입시간 */ .work-report-table td:nth-child(4) { width: 12%; } .work-report-table th:nth-child(5), /* 작업공수 */ .work-report-table td:nth-child(5) { width: 15%; } .work-report-table th:nth-child(6), /* 작업일/일평균시간 */ .work-report-table td:nth-child(6) { width: 15%; } .work-report-table th:nth-child(7), /* 비고 */ .work-report-table td:nth-child(7) { width: 8%; } .work-report-table th { background: var(--gradient-primary); color: var(--white); font-weight: 600; padding: 1rem 0.75rem; text-align: center; border-right: 1px solid rgba(255, 255, 255, 0.2); vertical-align: middle; line-height: 1.3; } .work-report-table th:last-child { border-right: none; } .work-report-table th small { font-size: 0.75rem; font-weight: 400; opacity: 0.9; } .work-report-table td { padding: 0.75rem; text-align: center; border-right: 1px solid var(--gray-200); border-bottom: 1px solid var(--gray-200); vertical-align: middle; } .work-report-table td:last-child { border-right: none; } .work-report-table tbody tr:hover { background: var(--gray-50); } .work-report-table .total-row { background: var(--warning-bg); font-weight: 600; } .work-report-table .total-row td { border-top: 2px solid var(--warning); padding: 1rem 0.75rem; } /* 작업자별 그룹핑 스타일 */ .work-report-table .worker-group { background: var(--gray-50); border-left: 4px solid var(--primary); } .work-report-table .worker-name { font-weight: 600; color: var(--primary); vertical-align: middle; text-align: center; background: rgba(37, 99, 235, 0.15); /* 파란색 계열 배경 강화 */ border-right: 3px solid var(--primary); /* 작업자 구분선 */ position: relative; } .work-report-table .man-days { vertical-align: middle; text-align: center; background: rgba(16, 185, 129, 0.15); /* 초록색 계열 배경 강화 */ font-weight: 600; white-space: nowrap; /* 텍스트 줄바꿈 방지 */ min-width: 80px; /* 최소 너비 설정 */ } .work-report-table .work-days { vertical-align: middle; text-align: center; background: rgba(245, 158, 11, 0.15); /* 주황색 계열 배경 강화 */ font-weight: 600; white-space: nowrap; /* 텍스트 줄바꿈 방지 */ min-width: 100px; /* 최소 너비 설정 */ } .work-report-table .project-name { font-weight: 500; color: var(--gray-700); background: rgba(59, 130, 246, 0.08); } /* 작업자 그룹 경계선 */ .work-report-table .worker-group-first td { border-top: 3px solid var(--primary); } .work-report-table .worker-group-last td { border-bottom: 2px solid var(--gray-300); } /* 동일 프로젝트 그룹 스타일 */ .work-report-table .project-group { background: rgba(59, 130, 246, 0.05); } .work-report-table .project-group-first .project-name { border-top: 2px solid rgba(59, 130, 246, 0.3); } .work-report-table .project-group-last .project-name { border-bottom: 2px solid rgba(59, 130, 246, 0.3); } /* 연차/휴무 프로젝트 스타일 */ .work-report-table .vacation-project { background: rgba(34, 197, 94, 0.05); /* 연한 초록색 배경 */ } .work-report-table .vacation-project .project-name { background: rgba(34, 197, 94, 0.1); /* 연차/휴무 프로젝트 배경 */ color: var(--success); font-style: italic; } .work-report-table .vacation-project .work-content { color: var(--gray-500); font-style: italic; text-align: center; } .work-report-table .work-content { color: var(--gray-600); } /* ========== Production Report 테이블 ========== */ .production-report-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; background: var(--white); border: 2px solid #000; } .production-report-table th { background: #4472C4; color: var(--white); font-weight: 600; padding: 1rem 0.75rem; text-align: center; border: 1px solid #000; vertical-align: middle; line-height: 1.3; } .production-report-table td { padding: 0.75rem; border: 1px solid #000; text-align: center; vertical-align: middle; } /* 프로젝트명 (Job No.) 스타일 */ .production-report-table .project-name { background: #5D9CEC; color: var(--white); font-weight: 600; text-align: center; writing-mode: horizontal-tb; text-orientation: mixed; width: 150px; min-width: 150px; padding: 0.5rem; line-height: 1.3; } /* 작업 내용 스타일 */ .production-report-table .work-content { background: var(--white); color: var(--gray-800); font-weight: 500; text-align: center; } /* 공수 스타일 */ .production-report-table .man-days { background: var(--white); color: var(--gray-800); font-weight: 600; text-align: center; } /* 부하율 스타일 */ .production-report-table .load-rate { background: var(--white); color: var(--gray-800); font-weight: 600; text-align: center; } /* 인건비 스타일 */ .production-report-table .labor-cost { background: var(--white); color: var(--gray-800); font-weight: 600; text-align: center; } /* 합계 행 스타일 */ .production-report-table .total-row { background: #FFF3CD !important; font-weight: 700; border-top: 2px solid #F39C12; } .production-report-table .total-row td { background: #FFF3CD !important; color: #856404; font-weight: 700; } /* 프로젝트 그룹 스타일 */ .production-report-table .project-group { border-top: 2px solid #000; } .production-report-table .project-group:first-child { border-top: none; } /* 연차/휴무 스타일 */ .production-report-table .vacation-project { background: #E8F5E8 !important; border-top: 3px solid #4CAF50 !important; } .production-report-table .vacation-project .project-name { background: #4CAF50 !important; color: var(--white) !important; font-weight: 700; text-align: center; font-size: 1rem; writing-mode: horizontal-tb !important; text-orientation: mixed !important; } .production-report-table .vacation-project .work-content { background: #E8F5E8 !important; color: #2E7D32 !important; font-weight: 600; text-align: center; } .production-report-table .vacation-project td { background: #E8F5E8 !important; color: #2E7D32 !important; font-weight: 500; } .production-report-table .vacation-project .man-days, .production-report-table .vacation-project .load-rate, .production-report-table .vacation-project .labor-cost { background: #E8F5E8 !important; color: #2E7D32 !important; font-weight: 600; } /* 프로젝트별 합계 행 스타일 */ .production-report-table .project-subtotal { background: #E8F4FD !important; font-weight: 600; border-bottom: 2px solid #5D9CEC; } .production-report-table .project-subtotal td { background: #E8F4FD !important; color: #2E5BBA; font-weight: 600; border-bottom: 2px solid #5D9CEC; } .work-report-table .input-hours { font-weight: 600; color: var(--success); } .work-report-table .man-days { font-weight: 600; color: var(--primary); } .work-report-table .work-days { color: var(--gray-600); font-size: 0.85rem; } .chart-container::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--gradient-primary); } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-6); padding-bottom: var(--space-4); border-bottom: 2px solid var(--gray-100); } /* 기간 확정 버튼 */ .confirm-period-button { background: var(--gradient-primary); color: var(--white); border: none; border-radius: var(--radius-lg); padding: var(--space-3) var(--space-6); font-weight: 600; font-size: 0.9rem; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; gap: var(--space-2); white-space: nowrap; } .confirm-period-button:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); } .confirm-period-button:disabled { background: var(--gray-300); cursor: not-allowed; transform: none; } /* 기간 상태 표시 */ .period-status { background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%); border: 2px solid #10b981; border-radius: var(--radius-lg); padding: var(--space-4) var(--space-6); color: #065f46; font-weight: 600; font-size: 0.95rem; display: flex; align-items: center; gap: var(--space-3); box-shadow: 0 4px 12px rgba(16, 185, 129, 0.15); min-width: 280px; } .period-status .icon { font-size: 1.2rem; color: #10b981; } /* 차트별 분석 버튼 */ .chart-analyze-btn { background: var(--gradient-secondary); color: var(--white); border: none; border-radius: var(--radius-md); padding: var(--space-2) var(--space-4); font-size: 0.85rem; font-weight: 500; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; gap: var(--space-1); } .chart-analyze-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--shadow-md); } .chart-analyze-btn:disabled { background: var(--gray-300); color: var(--gray-500); cursor: not-allowed; transform: none; } /* ========== 탭 네비게이션 ========== */ .tab-navigation { background: var(--white); border-radius: var(--radius-xl); padding: var(--space-6); box-shadow: var(--shadow-lg); border: 1px solid var(--gray-200); margin-bottom: var(--space-8); } .tab-buttons { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-4); } .tab-button { background: var(--gray-50); border: 2px solid var(--gray-200); border-radius: var(--radius-lg); padding: var(--space-4) var(--space-6); font-size: 0.9rem; font-weight: 600; color: var(--gray-700); cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; gap: var(--space-2); text-align: center; } .tab-button:hover { background: var(--gray-100); border-color: var(--primary); transform: translateY(-2px); box-shadow: var(--shadow-md); } .tab-button.active { background: var(--gradient-primary); border-color: var(--primary); color: var(--white); box-shadow: var(--shadow-lg); } .tab-button .icon { font-size: 1.2rem; } /* ========== 탭 컨텐츠 ========== */ .tab-content { display: none; } .tab-content.active { display: block; } .chart-title { font-size: 1.5rem; font-weight: 700; color: var(--gray-900); display: flex; align-items: center; gap: var(--space-3); } .chart-title .icon { font-size: 1.5rem; color: var(--primary); } .chart-canvas { width: 100%; height: 400px; border-radius: var(--radius); } /* ========== 데이터 테이블 ========== */ .data-table-container { background: var(--white); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); border: 1px solid var(--gray-200); overflow: hidden; margin-bottom: var(--space-8); } .table-header { background: var(--gradient-primary); color: var(--white); padding: var(--space-6); } .table-title { font-size: 1.25rem; font-weight: 700; display: flex; align-items: center; gap: var(--space-2); } .data-table { width: 100%; border-collapse: collapse; } .data-table th, .data-table td { padding: var(--space-4); text-align: left; border-bottom: 1px solid var(--gray-200); } .data-table th { background: var(--gray-50); font-weight: 600; color: var(--gray-700); font-size: 0.875rem; } .data-table tr:hover { background: var(--gray-50); } .data-table td { font-size: 0.875rem; color: var(--gray-800); } /* ========== 상태 배지 ========== */ .status-badge { display: inline-flex; align-items: center; gap: var(--space-1); padding: var(--space-1) var(--space-3); border-radius: var(--radius-full); font-size: 0.75rem; font-weight: 600; } .status-badge.success { background: var(--success-bg); color: var(--success); } .status-badge.warning { background: var(--warning-bg); color: var(--warning); } .status-badge.error { background: var(--error-bg); color: var(--error); } .status-badge.info { background: var(--info-bg); color: var(--info); } /* ========== 로딩 상태 ========== */ .loading-container { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-16); background: var(--white); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); border: 1px solid var(--gray-200); } .loading-spinner { width: 48px; height: 48px; border: 4px solid var(--gray-200); border-top: 4px solid var(--primary); border-radius: 50%; animation: spin 1s linear infinite; margin-bottom: var(--space-4); } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loading-text { font-size: 1.125rem; font-weight: 600; color: var(--gray-600); } /* ========== 빈 상태 ========== */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-16); background: var(--white); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); border: 1px solid var(--gray-200); text-align: center; } .empty-icon { font-size: 4rem; color: var(--gray-400); margin-bottom: var(--space-4); } .empty-title { font-size: 1.5rem; font-weight: 700; color: var(--gray-700); margin-bottom: var(--space-2); } .empty-description { font-size: 1rem; color: var(--gray-500); max-width: 400px; } /* ========== 반응형 디자인 ========== */ @media (max-width: 1024px) { .analysis-container { padding: var(--space-4); } .page-title { font-size: 2rem; } .controls-grid { grid-template-columns: 1fr; } .results-grid { grid-template-columns: 1fr; } .chart-canvas { height: 300px; } } @media (max-width: 768px) { .analysis-container { padding: var(--space-3); } .page-header { padding: var(--space-6); } .page-title { font-size: 1.75rem; flex-direction: column; text-align: center; } .analysis-tabs { flex-direction: column; } .tab-button { text-align: center; } .chart-header { flex-direction: column; align-items: flex-start; gap: var(--space-3); } .chart-canvas { height: 250px; } .data-table-container { overflow-x: auto; } .data-table { min-width: 600px; } .error-analysis-table { font-size: 0.8rem; } .error-analysis-table th, .error-analysis-table td { padding: 0.5rem 0.25rem; } .error-analysis-table .job-no { width: 80px; min-width: 80px; font-size: 0.75rem; } .error-analysis-table .work-type-breakdown { gap: 0.15rem; } .error-analysis-table .work-type-item { padding: 0.15rem; } } @media (max-width: 480px) { .analysis-container { padding: var(--space-2); } .page-header { padding: var(--space-4); } .page-title { font-size: 1.5rem; } .analysis-controls { padding: var(--space-4); } .controls-grid { grid-template-columns: 1fr; gap: var(--space-4); } .form-group { width: 100%; } .period-status { min-width: auto; font-size: 0.85rem; } .tab-buttons { grid-template-columns: 1fr; gap: var(--space-3); } .tab-button { padding: var(--space-3) var(--space-4); font-size: 0.85rem; } .result-card { padding: var(--space-4); } .chart-container { padding: var(--space-4); } .chart-canvas { height: 200px; } } /* ========== 애니메이션 ========== */ @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideIn { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } } .fade-in { animation: fadeIn 0.6s ease-out; } .slide-in { animation: slideIn 0.4s ease-out; } /* ========== 접근성 개선 ========== */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } /* 포커스 표시 개선 */ button:focus, input:focus, select:focus { outline: 2px solid var(--primary); outline-offset: 2px; } /* ========== 오류 분석 테이블 스타일 ========== */ .error-analysis-table { width: 100%; border-collapse: collapse; margin-top: 1rem; font-size: 0.9rem; background: var(--white); border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .error-analysis-table th { background: #FF6B6B; /* 오류 분석 전용 빨간색 헤더 */ color: var(--white); font-weight: 600; text-align: center; padding: 1rem 0.75rem; border-bottom: 2px solid #E74C3C; font-size: 0.85rem; line-height: 1.3; } .error-analysis-table td { padding: 0.75rem; border-bottom: 1px solid #F8F9FA; text-align: center; vertical-align: middle; } .error-analysis-table .job-no, .error-analysis-table .project-name { background: #FFE5E5; /* 연한 빨간색 배경 */ color: #C0392B; font-weight: 600; text-align: center; width: 120px; min-width: 120px; vertical-align: middle; } .error-analysis-table .work-content { text-align: left; font-weight: 500; color: var(--gray-800); } .error-analysis-table .total-hours { font-weight: 600; color: var(--gray-900); } .error-analysis-table .detail-hours { text-align: left; line-height: 1.4; } .error-analysis-table .regular-hours { color: #27AE60; font-weight: 500; } .error-analysis-table .error-hours { color: #E74C3C; font-weight: 600; } .error-analysis-table .work-type { text-align: left; padding: 0.5rem; } .error-analysis-table .work-type-breakdown { display: flex; flex-direction: column; gap: 0.25rem; } .error-analysis-table .work-type-item { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.25rem; background: #F8F9FA; border-radius: 4px; margin-bottom: 0.25rem; } /* 정규 작업 스타일 */ .error-analysis-table .work-type-item.regular { background: #E8F5E8; border-left: 3px solid #4CAF50; } .error-analysis-table .work-type-item.regular .work-type-name { color: #2E7D32; } .error-analysis-table .work-type-item.regular .regular-time { color: #4CAF50; font-weight: 600; } .error-analysis-table .work-type-item.regular .work-type-status { color: #388E3C; font-size: 0.7rem; font-weight: 500; } /* 오류 작업 스타일 */ .error-analysis-table .work-type-item.error { background: #FFEBEE; border-left: 3px solid #F44336; } .error-analysis-table .work-type-item.error .work-type-name { color: #C62828; } .error-analysis-table .work-type-item.error .error-time { color: #F44336; font-weight: 600; } .error-analysis-table .work-type-item.error .work-type-status { color: #D32F2F; font-size: 0.7rem; font-weight: 600; } .error-analysis-table .work-type-name { font-weight: 600; color: var(--gray-800); font-size: 0.85rem; } .error-analysis-table .work-type-hours { font-size: 0.75rem; color: var(--gray-600); } .error-analysis-table .error-percentage { font-weight: 600; font-size: 1rem; } .error-analysis-table .error-percentage.has-error { color: #E74C3C; background: #FFE5E5; border-radius: 4px; padding: 0.25rem; } /* 프로젝트 그룹 스타일 */ .error-analysis-table .project-group { border-top: 1px solid #E0E0E0; } .error-analysis-table .project-group:first-child { border-top: none; } /* 연차/휴무 오류 스타일 */ .error-analysis-table .vacation-project { background: #FFF3E0 !important; /* 연한 오렌지 배경 */ border-top: 3px solid #FF9800 !important; } .error-analysis-table .vacation-project .job-no, .error-analysis-table .vacation-project .project-name { background: #FF9800 !important; /* 오렌지 배경 */ color: var(--white) !important; } .error-analysis-table .vacation-project td { background: #FFF3E0 !important; color: #E65100 !important; } /* 총계 행 스타일 */ .error-analysis-table .total-row { background: #FFEBEE !important; color: #C62828; border-top: 2px solid #E74C3C; font-weight: 600; } .error-analysis-table .total-row td { background: #FFEBEE !important; color: #C62828 !important; font-weight: 600; border-bottom: none; } /* 다크 모드 지원 (선택사항) */ @media (prefers-color-scheme: dark) { :root { --white: #1e293b; --gray-50: #0f172a; --gray-100: #1e293b; --gray-200: #334155; --gray-800: #f1f5f9; --gray-900: #ffffff; } }