/* 장치 제어 관련 스타일 */ /* 장치 제어 섹션 */ #deviceSection { display: flex; flex-direction: column; gap: 20px; max-width: 1000px; margin: 0 auto; padding: 20px; } /* 장치 연결 컨테이너 */ .device-connection { background-color: var(--bg-color-secondary); border-radius: 8px; padding: 15px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .device-connection h3 { margin-top: 0; margin-bottom: 15px; color: var(--text-color-primary); font-size: 1.2rem; } .device-connection-form { display: flex; gap: 10px; margin-bottom: 15px; } .device-connection-form input { flex: 1; padding: 10px; border: 1px solid var(--border-color); border-radius: 4px; font-size: 0.95rem; } .device-connection-form button { background-color: var(--primary-color); color: white; border: none; border-radius: 4px; padding: 10px 15px; cursor: pointer; font-weight: 500; transition: background-color 0.2s; } .device-connection-form button:hover { background-color: var(--primary-color-dark); } .device-connection-form button:disabled { background-color: var(--disabled-color); cursor: not-allowed; } .connection-status { padding: 10px; border-radius: 4px; font-size: 0.9rem; } .connection-status.connected { background-color: rgba(25, 135, 84, 0.1); color: #198754; border: 1px solid rgba(25, 135, 84, 0.2); } .connection-status.disconnected { background-color: rgba(108, 117, 125, 0.1); color: #6c757d; border: 1px solid rgba(108, 117, 125, 0.2); } .connection-status.error { background-color: rgba(220, 53, 69, 0.1); color: #dc3545; border: 1px solid rgba(220, 53, 69, 0.2); } /* 장치 기능 컨테이너 */ /* 서버 연결 후 활성화되는 섹션들의 기본 스타일 */ .device-functions, .program-control { background-color: var(--bg-color-secondary); border-radius: 8px; padding: 15px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); display: none; /* 초기에는 숨김 */ } .device-functions.active, .program-control.active { display: block; /* 활성화 시 보임 */ } .device-functions h3, .program-control h3 { margin-top: 0; margin-bottom: 15px; color: var(--text-color-primary); font-size: 1.2rem; } .function-buttons { display: flex; gap: 10px; margin-bottom: 15px; flex-wrap: wrap; } .function-buttons button { background-color: var(--secondary-color); color: white; border: none; border-radius: 4px; padding: 8px 12px; cursor: pointer; font-size: 0.9rem; transition: background-color 0.2s; } .function-buttons button:hover { background-color: var(--secondary-color-dark); } .function-buttons button:disabled { background-color: var(--disabled-color); cursor: not-allowed; } .device-status-result { width: 100%; min-height: 100px; max-height: 200px; padding: 10px; border: 1px solid var(--border-color); border-radius: 4px; font-family: monospace; font-size: 0.9rem; overflow-y: auto; background-color: var(--bg-color-tertiary); margin-bottom: 15px; resize: vertical; } /* 프로그램 실행 컨테이너 */ .program-list-container { margin-bottom: 20px; /* 스크롤이 필요할 경우를 대비 */ max-height: 300px; overflow-y: auto; border: 1px solid var(--border-color); border-radius: 4px; padding: 10px; } .program-list { width: 100%; border-collapse: collapse; margin-bottom: 15px; } .program-list th, .program-list td { padding: 10px; text-align: left; border-bottom: 1px solid var(--border-color); font-size: 0.9rem; } .program-list th { background-color: var(--bg-color-tertiary); font-weight: 500; } .program-list tr:hover { background-color: var(--bg-color-tertiary); } .program-select-container { margin-bottom: 15px; } .program-select-container select { width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 4px; font-size: 0.95rem; background-color: var(--bg-color-tertiary); } .execute-btn { background-color: var(--primary-color); color: white; border: none; border-radius: 4px; padding: 10px 15px; cursor: pointer; font-weight: 500; transition: background-color 0.2s; width: 100%; margin-bottom: 15px; } .execute-btn:hover { background-color: var(--primary-color-dark); } .execute-btn:disabled { background-color: var(--disabled-color); cursor: not-allowed; } .execute-result { padding: 10px; border-radius: 4px; margin-top: 10px; font-size: 0.9rem; min-height: 20px; /* 결과 없을 때도 최소 높이 유지 */ } .execute-result.success { background-color: rgba(25, 135, 84, 0.1); color: #198754; border: 1px solid rgba(25, 135, 84, 0.2); } .execute-result.error { background-color: rgba(220, 53, 69, 0.1); color: #dc3545; border: 1px solid rgba(220, 53, 69, 0.2); } .execute-result.warning { background-color: rgba(255, 193, 7, 0.1); color: #ffc107; border: 1px solid rgba(255, 193, 7, 0.2); } /* 사용자 정의 프로그램 실행 */ .custom-command-container { display: flex; gap: 10px; margin-bottom: 15px; } .custom-command-container input { flex: 1; padding: 10px; border: 1px solid var(--border-color); border-radius: 4px; font-size: 0.95rem; } .custom-command-container button { background-color: var(--primary-color); color: white; border: none; border-radius: 4px; padding: 10px 15px; cursor: pointer; font-weight: 500; transition: background-color 0.2s; } .custom-command-container button:hover { background-color: var(--primary-color-dark); } .custom-command-container button:disabled { background-color: var(--disabled-color); cursor: not-allowed; } /* 명령어 실행 결과 스타일 */ .command-output, .command-error { margin-top: 10px; padding: 10px; background-color: var(--bg-color-tertiary); border-radius: 4px; border: 1px solid var(--border-color); } .command-output pre, .command-error pre { white-space: pre-wrap; word-wrap: break-word; font-size: 0.85rem; margin: 0; } .command-error pre { color: #dc3545; /* 오류 텍스트 색상 */ } /* 로딩 표시 */ .loading-spinner { display: inline-block; width: 16px; height: 16px; border: 2px solid rgba(0, 0, 0, 0.1); border-radius: 50%; border-top-color: var(--primary-color); animation: spin 1s ease-in-out infinite; margin-right: 8px; vertical-align: middle; } @keyframes spin { to { transform: rotate(360deg); } } .loading-message { display: flex; align-items: center; justify-content: center; padding: 20px; font-size: 0.95rem; color: var(--text-color-secondary); } /* 에러 메시지 */ .error-message { background-color: rgba(220, 53, 69, 0.1); color: #dc3545; border: 1px solid rgba(220, 53, 69, 0.2); padding: 10px; border-radius: 4px; margin-top: 10px; font-size: 0.9rem; } /* 없음 메시지 */ .no-programs-message { text-align: center; padding: 20px; font-size: 0.95rem; color: var(--text-color-secondary); border: 1px dashed var(--border-color); border-radius: 4px; margin-top: 10px; } /* 재시도 버튼 */ .retry-button { background-color: var(--secondary-color); color: white; border: none; border-radius: 4px; padding: 8px 12px; cursor: pointer; font-size: 0.9rem; margin-top: 10px; /* 필요시 조정 */ margin-left: 10px; /* 앞 요소와 간격 */ transition: background-color 0.2s; } .retry-button:hover { background-color: var(--secondary-color-dark); } /* ================== 장치 포트 조회 스타일 추가 ================== */ .ports-status { margin: 10px 0; padding: 10px; border-radius: 5px; min-height: 20px; font-size: 0.9rem; /* 다른 상태 메시지와 일관성 */ } .ports-status.success { background-color: rgba(0, 200, 83, 0.1); /* 기존 .success 스타일과 유사하게 */ color: #00c853; /* 좀 더 밝은 녹색 */ border: 1px solid #00c853; } .ports-status.error { background-color: rgba(244, 67, 54, 0.1); /* 기존 .error 스타일과 유사하게 */ color: #f44336; /* 좀 더 밝은 빨강 */ border: 1px solid #f44336; } .ports-status.warning { background-color: rgba(255, 152, 0, 0.1); /* 기존 .warning 스타일과 유사하게 */ color: #ff9800; /* 좀 더 밝은 주황 */ border: 1px solid #ff9800; } .ports-results { margin-top: 15px; border: 1px solid var(--border-color); /* 변수 사용 */ border-radius: 5px; padding: 0; /* 내부 섹션 패딩으로 조정 */ max-height: 500px; /* 최대 높이 제한 */ overflow-y: auto; /* 내용 많으면 스크롤 */ background-color: var(--bg-color-tertiary); /* 약간의 배경색 */ } /* 포트 결과 컨테이너 (내부 패딩용) */ .ports-results-container { padding: 15px; } .ports-section { margin-bottom: 20px; } /* 마지막 섹션의 하단 마진 제거 */ .ports-section:last-child { margin-bottom: 0; } .ports-section h4 { margin-top: 0; margin-bottom: 10px; font-size: 1rem; /* 다른 h3 와 유사하게 */ color: var(--text-color-primary); /* 변수 사용 */ border-bottom: 1px solid var(--border-color); /* 변수 사용 */ padding-bottom: 5px; } .info-row { display: flex; margin-bottom: 5px; font-size: 0.9rem; /* 글자 크기 통일 */ } .info-label { font-weight: bold; width: 100px; flex-shrink: 0; /* 라벨 너비 고정 */ color: var(--text-color-secondary); /* 약간 연한 색 */ } .info-value { color: var(--text-color-primary); } .ports-table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 0.85rem; /* 테이블 글자 약간 작게 */ } .ports-table th, .ports-table td { padding: 8px 10px; /* 패딩 조정 */ text-align: left; border-bottom: 1px solid var(--border-color-lighter, #eee); /* 더 연한 구분선, 변수 없으면 기본값 */ vertical-align: top; /* 여러 줄일 경우 위 정렬 */ } .ports-table th { background-color: var(--bg-color-secondary); /* 약간 다른 배경 */ font-weight: 500; /* 보통 두께 */ color: var(--text-color-primary); } .ports-table tbody tr:hover { background-color: var(--bg-color-hover, #f9f9f9); /* 변수 없으면 기본값 */ } .no-ports-message { color: var(--text-color-secondary); /* 변수 사용 */ font-style: italic; padding: 10px 0; font-size: 0.9rem; } /* ================== 추가 끝 ================================= */