/* ===================================================== mobile.css - 모바일 전용 스타일 대시보드, TBM, 작업보고서, 출근 관리 페이지 최적화 ===================================================== */ /* ========== 모바일 헤더 (navbar.html 스타일과 동기화) ========== */ @media (max-width: 768px) { .dashboard-header { height: 52px !important; padding: 0 0.5rem !important; } html, body { overflow-x: hidden !important; max-width: 100vw !important; } body { padding-top: 52px !important; } .header-content { padding: 0 !important; flex-wrap: nowrap !important; } .header-left { flex: 1 !important; min-width: 0 !important; overflow: hidden !important; } .brand-logo { width: 30px !important; height: 30px !important; } .brand-subtitle { display: none !important; } .brand-title { font-size: 0.8125rem !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; } .header-right { gap: 0.25rem !important; flex-shrink: 0 !important; } /* 버튼 아이콘만 표시 (숨기지 않음) */ .dashboard-btn .btn-text, .report-btn .btn-text { display: none !important; } .dashboard-btn, .report-btn { padding: 0 !important; width: 32px !important; height: 32px !important; justify-content: center !important; border: none !important; } .notification-btn { width: 32px !important; height: 32px !important; } .user-profile { padding: 0.125rem 0.25rem !important; background: transparent !important; border: none !important; } .user-avatar { width: 30px !important; height: 30px !important; font-size: 0.8rem !important; } } /* ========== 공통 모바일 스타일 ========== */ @media (max-width: 768px) { /* 사이드바 마진 완전 제거 */ .dashboard-container, .dashboard-main, .page-container, .main-content, .work-report-container, .analysis-container { margin-left: 0 !important; margin-right: 0 !important; max-width: 100% !important; width: 100% !important; } /* 기본 여백 조정 */ .dashboard-main, .page-container, .main-content { padding: 0.75rem !important; padding-top: 1rem !important; } /* 카드 스타일 */ .card { border-radius: 12px; margin-bottom: 0.75rem; box-shadow: 0 2px 8px rgba(0,0,0,0.08); } .card-header { padding: 0.875rem 1rem; } .card-body { padding: 0.875rem 1rem; } .card-title { font-size: 1rem; font-weight: 600; } /* 버튼 모바일 최적화 */ .btn { padding: 0.625rem 1rem; font-size: 0.875rem; border-radius: 8px; min-height: 44px; /* 터치 타겟 최소 크기 */ } .btn-sm { padding: 0.5rem 0.75rem; font-size: 0.8125rem; min-height: 36px; } .btn-lg { padding: 0.875rem 1.25rem; font-size: 1rem; min-height: 48px; } /* 폼 요소 */ .form-control, .form-select, input[type="text"], input[type="date"], input[type="time"], input[type="number"], select, textarea { font-size: 16px !important; /* iOS 줌 방지 */ padding: 0.75rem; border-radius: 8px; min-height: 44px; } /* 테이블 스크롤 */ .table-responsive { margin: 0 -1rem; padding: 0 1rem; overflow-x: auto; -webkit-overflow-scrolling: touch; } /* 모달 모바일 최적화 */ .modal-content, [class*="modal-container"] { width: 95% !important; max-width: none !important; margin: 1rem auto; max-height: 90vh; overflow-y: auto; } /* 숨기기 유틸리티 */ .hide-mobile { display: none !important; } /* 푸터 */ .dashboard-footer { padding: 1rem; } .footer-content { flex-direction: column; gap: 0.5rem; text-align: center; } .footer-links { justify-content: center; } } /* ========== 대시보드 페이지 ========== */ @media (max-width: 768px) { /* 작업장 현황 섹션 */ .workplace-status-section .card-header .flex { flex-direction: column; gap: 0.75rem; align-items: stretch !important; } .workplace-status-section .card-header select { width: 100% !important; } .workplace-status-section .card-header .btn { width: 100%; } /* 작업장 카드: 엣지투엣지 */ .workplace-status-section .card { border-radius: 0; margin-left: -0.75rem; margin-right: -0.75rem; border-left: none; border-right: none; } .workplace-status-section .card-body { padding: 0 !important; } #workplaceMapContainer { min-height: auto !important; } /* 캔버스: 높이 제한 해제, 풀와이드 */ #workplaceMapCanvas { max-height: none; border-radius: 0 !important; border-left: none !important; border-right: none !important; } .workplace-status-section .card-header { padding: 0.75rem !important; } /* 범례 숨기기 */ #mapLegend { display: none; } /* 안내 메시지 */ #mapPlaceholder { min-height: 250px !important; padding: 2rem 1rem; } #mapPlaceholder h3 { font-size: 1.125rem; } /* 임시 이동 설비 그리드 */ .moved-equipment-grid { display: flex; flex-direction: column; gap: 0.75rem; } .moved-equipment-item { padding: 1rem; border-radius: 10px; } /* 작업장 모달 */ .workplace-modal-container { width: 100% !important; height: 100% !important; max-height: 100vh !important; border-radius: 0 !important; margin: 0 !important; } .workplace-modal-header { padding: 1rem; position: sticky; top: 0; background: white; z-index: 10; } .workplace-modal-tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; padding: 0.5rem; gap: 0.5rem; flex-wrap: nowrap; } .workplace-tab { flex-shrink: 0; padding: 0.5rem 0.75rem; font-size: 0.8125rem; } .workplace-tab .tab-text { display: none; } .workplace-tab .tab-icon { font-size: 1.25rem; } } /* ========== TBM 페이지 ========== */ @media (max-width: 768px) { /* TBM 헤더 */ .tbm-header { flex-direction: column; gap: 1rem; padding: 1rem; } .tbm-header-left, .tbm-header-right { width: 100%; } /* TBM 폼 */ .tbm-form { padding: 1rem; } .tbm-form-row { flex-direction: column; gap: 0.75rem; } .tbm-form-group { width: 100%; } /* 서명 영역 */ .signature-area { height: 120px; } .signature-canvas { height: 100px; } /* 팀원 목록 */ .team-member-list { display: flex; flex-direction: column; gap: 0.5rem; } .team-member-item { padding: 0.875rem; border-radius: 10px; } .team-member-checkbox { width: 24px; height: 24px; } /* 안전점검 체크리스트 */ .safety-checklist { gap: 0.5rem; } .checklist-item { padding: 0.75rem; flex-direction: column; align-items: flex-start; gap: 0.5rem; } .checklist-item label { font-size: 0.9rem; } .checklist-buttons { width: 100%; display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; } .checklist-btn { padding: 0.5rem; font-size: 0.8rem; } /* TBM 카드 */ .tbm-session-card { padding: 1rem; } .tbm-session-header { flex-direction: column; gap: 0.5rem; } /* 날씨 정보 */ .weather-info { flex-wrap: wrap; gap: 0.5rem; } .weather-item { min-width: 80px; } } /* ========== 작업보고서 페이지 ========== */ @media (max-width: 768px) { /* 작업보고서 헤더 */ .work-report-header { flex-direction: column; gap: 1rem; padding: 1rem; } /* 날짜/작업자 선택 */ .report-filter-row { flex-direction: column; gap: 0.75rem; } .report-filter-group { width: 100%; } /* 작업 목록 */ .work-item { padding: 1rem; border-radius: 10px; margin-bottom: 0.75rem; } .work-item-header { flex-direction: column; gap: 0.5rem; align-items: flex-start; } .work-item-time { font-size: 0.8rem; } /* 작업 입력 폼 */ .work-input-form { padding: 1rem; } .work-form-row { flex-direction: column; gap: 0.75rem; } .work-form-group { width: 100%; } /* 시간 입력 */ .time-input-group { display: flex; gap: 0.5rem; align-items: center; } .time-input-group input { flex: 1; } /* 결함 입력 */ .defect-section { padding: 0.875rem; border-radius: 10px; } .defect-item { padding: 0.75rem; margin-bottom: 0.5rem; } /* 요약 카드 */ .summary-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; } .summary-card { padding: 0.875rem; text-align: center; } .summary-card-value { font-size: 1.25rem; } .summary-card-label { font-size: 0.75rem; } } /* ========== 출근 체크 / 근무 현황 페이지 ========== */ @media (max-width: 768px) { /* 출근 체크 버튼 */ .checkin-button-container { padding: 1rem; } .checkin-btn { width: 100%; padding: 1.5rem; font-size: 1.25rem; border-radius: 16px; min-height: 80px; } .checkin-btn-icon { font-size: 2rem; margin-bottom: 0.5rem; } /* 출근 상태 카드 */ .checkin-status-card { padding: 1.25rem; border-radius: 12px; text-align: center; } .checkin-time { font-size: 2rem; font-weight: 700; } /* 작업자 목록 */ .worker-list { display: flex; flex-direction: column; gap: 0.5rem; } .worker-item { display: flex; align-items: center; justify-content: space-between; padding: 1rem; background: white; border-radius: 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .worker-info { display: flex; align-items: center; gap: 0.75rem; } .worker-avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--primary-100, #dbeafe); display: flex; align-items: center; justify-content: center; font-weight: 600; color: var(--primary-700, #1d4ed8); } .worker-name { font-weight: 600; font-size: 0.9375rem; } .worker-status-badge { padding: 0.375rem 0.75rem; border-radius: 20px; font-size: 0.75rem; font-weight: 600; } /* 근무 현황 테이블 대체 */ .work-status-table-mobile { display: flex; flex-direction: column; gap: 0.5rem; } .work-status-row { display: grid; grid-template-columns: 1fr auto auto; gap: 0.75rem; align-items: center; padding: 0.875rem 1rem; background: white; border-radius: 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); } .work-status-name { font-weight: 600; font-size: 0.9375rem; } .work-status-hours { font-size: 0.875rem; color: var(--gray-600, #4b5563); } /* 날짜 선택 */ .date-selector { display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1rem; background: white; border-radius: 10px; margin-bottom: 1rem; } .date-selector input[type="date"] { flex: 1; border: none; background: transparent; font-size: 1rem; font-weight: 600; } .date-nav-btn { width: 40px; height: 40px; border-radius: 8px; background: var(--gray-100, #f3f4f6); border: none; font-size: 1.25rem; display: flex; align-items: center; justify-content: center; } /* 통계 요약 */ .attendance-summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin-bottom: 1rem; } .attendance-stat { text-align: center; padding: 0.875rem 0.5rem; background: white; border-radius: 10px; } .attendance-stat-value { font-size: 1.5rem; font-weight: 700; color: var(--primary-600, #2563eb); } .attendance-stat-label { font-size: 0.6875rem; color: var(--gray-500, #6b7280); margin-top: 0.25rem; } /* 저장 버튼 영역 */ .save-button-container { position: fixed; bottom: 0; left: 0; right: 0; padding: 1rem; background: white; box-shadow: 0 -2px 10px rgba(0,0,0,0.1); z-index: 100; } .save-button-container .btn { width: 100%; } /* 바디 패딩 (고정 버튼 공간) */ body.has-fixed-button { padding-bottom: 80px; } } /* ========== 모바일 퀵 액션 버튼 (FAB) ========== */ @media (max-width: 768px) { .mobile-fab { position: fixed; bottom: 1.5rem; right: 1.5rem; width: 56px; height: 56px; border-radius: 50%; background: var(--primary-500, #3b82f6); color: white; border: none; box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); font-size: 1.5rem; display: flex; align-items: center; justify-content: center; z-index: 90; transition: transform 0.2s, box-shadow 0.2s; } .mobile-fab:active { transform: scale(0.95); box-shadow: 0 2px 8px rgba(59, 130, 246, 0.4); } } /* ========== 터치 최적화 ========== */ @media (max-width: 768px) { /* 터치 피드백 */ .btn:active, .card:active, .worker-item:active, .nav-item:active { transform: scale(0.98); opacity: 0.9; } /* 스크롤 스냅 */ .horizontal-scroll { scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; } .horizontal-scroll > * { scroll-snap-align: start; } /* 탭 바 최적화 */ .tab-bar { display: flex; overflow-x: auto; -webkit-overflow-scrolling: touch; gap: 0.25rem; padding: 0.25rem; background: var(--gray-100, #f3f4f6); border-radius: 10px; } .tab-bar::-webkit-scrollbar { display: none; } .tab-item { flex-shrink: 0; padding: 0.625rem 1rem; border-radius: 8px; font-size: 0.875rem; font-weight: 500; white-space: nowrap; transition: all 0.2s; } .tab-item.active { background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } } /* ========== 모바일 대시보드 (작업장 리스트 뷰) ========== */ @media (max-width: 768px) { /* 모바일 뷰가 활성화되면 데스크톱 섹션 숨김 */ .mobile-dashboard-view[style*="block"] ~ .workplace-status-section, .mobile-dashboard-view[style*="block"] ~ .moved-equipment-section, .mobile-dashboard-view[style*="block"] ~ .dashboard-footer { display: none !important; } .mobile-dashboard-view { padding-bottom: 8px; } /* --- 날짜 헤더 --- */ .md-date-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 14px; padding: 0 2px; } .md-date-label { font-size: var(--text-lg, 18px); font-weight: 700; color: var(--text-primary, #1a202c); } .md-date-value { font-size: var(--text-sm, 14px); color: var(--text-tertiary, #718096); font-weight: 400; } /* --- 카테고리 탭 --- */ .md-category-tabs { display: flex; gap: 8px; overflow-x: auto; -webkit-overflow-scrolling: touch; padding: 0 2px 12px; margin-bottom: 4px; scrollbar-width: none; } .md-category-tabs::-webkit-scrollbar { display: none; } .md-cat-tab { flex-shrink: 0; padding: 7px 16px; border-radius: var(--radius-full, 9999px); font-size: var(--text-sm, 14px); font-weight: 500; white-space: nowrap; border: 1px solid var(--border-light, #e2e8f0); background: var(--bg-primary, #fff); color: var(--text-secondary, #4a5568); cursor: pointer; transition: all 0.15s; min-height: 36px; -webkit-tap-highlight-color: transparent; } .md-cat-tab:active { transform: scale(0.97); } .md-cat-tab.active { background: var(--primary-500, #3b82f6); color: #fff; border-color: var(--primary-500, #3b82f6); } /* --- 작업장 리스트 --- */ .md-workplace-list { display: flex; flex-direction: column; gap: 10px; } /* --- 작업장 카드 --- */ .md-wp-card { background: var(--bg-primary, #fff); border: 1px solid var(--border-light, #e2e8f0); border-radius: var(--radius-lg, 12px); padding: 14px 16px; } .md-wp-name { font-size: 15px; font-weight: 600; color: var(--text-primary, #1a202c); margin: 0 0 8px; } .md-wp-stats { display: flex; flex-direction: column; gap: 4px; } .md-wp-stat-row { display: flex; align-items: center; gap: 6px; font-size: var(--text-sm, 14px); color: var(--text-secondary, #4a5568); line-height: 1.6; } .md-wp-stat-icon { flex-shrink: 0; width: 18px; text-align: center; font-size: 13px; } .md-wp-stat-text { font-variant-numeric: tabular-nums; } .md-wp-stat--warning { color: var(--status-warning-text, #ca8a04); } /* --- 빈 상태 --- */ .md-wp-no-activity { margin: 0; color: var(--text-tertiary, #718096); font-size: var(--text-sm, 14px); } .md-wp-empty-all { text-align: center; padding: 32px 0; color: var(--text-tertiary, #718096); font-size: var(--text-sm, 14px); } /* --- 카드 확장 상태 --- */ .md-wp-card.expanded { border-color: var(--primary-300, #93c5fd); box-shadow: 0 2px 8px rgba(59,130,246,0.1); } .md-wp-header { cursor: pointer; -webkit-tap-highlight-color: transparent; } .md-wp-toggle { float: right; color: var(--text-tertiary, #718096); font-size: 12px; transition: transform 0.2s; } .md-wp-card.expanded .md-wp-toggle { transform: rotate(180deg); } /* --- 상세 영역 --- */ .md-wp-detail { display: none; border-top: 1px solid var(--border-light, #e2e8f0); margin-top: 10px; padding-top: 10px; } .md-wp-card.expanded .md-wp-detail { display: block; } .md-wp-detail-section { margin-bottom: 10px; } .md-wp-detail-section:last-child { margin-bottom: 0; } .md-wp-detail-title { font-size: 12px; font-weight: 600; color: var(--text-tertiary, #718096); letter-spacing: 0.03em; margin-bottom: 6px; } .md-wp-detail-item { padding: 6px 0; border-bottom: 1px solid var(--gray-100, #f5f5f5); font-size: 14px; } .md-wp-detail-item:last-child { border-bottom: none; } .md-wp-detail-main { font-weight: 500; color: var(--text-primary, #1a202c); } .md-wp-detail-sub { font-size: 13px; color: var(--text-tertiary, #718096); margin-top: 1px; } /* 신고 상태 배지 */ .md-wp-issue-status { display: inline-block; font-size: 11px; padding: 1px 6px; border-radius: 4px; font-weight: 500; } .md-wp-issue-status--reported { background: var(--status-warning-bg, #fef3c7); color: var(--status-warning-text, #ca8a04); } .md-wp-issue-status--received { background: var(--status-info-bg, #dbeafe); color: var(--status-info-text, #2563eb); } .md-wp-issue-status--in_progress { background: var(--status-error-bg, #fee2e2); color: var(--status-error-text, #dc2626); } /* --- 로딩 스켈레톤 --- */ .md-skeleton { height: 48px; border-radius: var(--radius-md, 8px); background: linear-gradient(90deg, var(--gray-100, #f5f5f5) 25%, var(--gray-200, #eee) 50%, var(--gray-100, #f5f5f5) 75%); background-size: 200% 100%; animation: md-shimmer 1.5s infinite; } @keyframes md-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } } /* 데스크톱에서는 모바일 대시보드 절대 표시 안 함 */ @media (min-width: 769px) { .mobile-dashboard-view { display: none !important; } } /* ========== 다크모드 지원 (선택적) ========== */ @media (max-width: 768px) and (prefers-color-scheme: dark) { /* 다크모드 색상 조정 필요시 여기에 추가 */ }