:root {
  --bg: #f5f6f8;
  --card-bg: #ffffff;
  --text: #1c1e21;
  --muted: #6b7280;
  --border: #e5e7eb;
  --primary: #2563eb;
  --primary-hover: #1d4ed8;
  --danger: #dc2626;
  --danger-hover: #b91c1c;
  --secondary: #eef0f3;
  --secondary-hover: #dfe3e8;
  --green: #16a34a;
  --red: #dc2626;
  --amber: #d97706;
  --gray: #9ca3af;
  --radius: 10px;

  /* 전원 상태 표시등(램프)처럼 보이는 밝은 연두색: 켜짐 버튼이 실제로 켜졌을 때만
     이 색으로 켜지도록 쓴다 (프로젝터 램프 표시등 느낌). 배경이 밝아서 흰 글씨보다
     어두운 글씨가 대비가 훨씬 좋다. */
  --lamp-on: #4ade80;
  --lamp-on-hover: #22c55e;
  --lamp-on-text: #063d17;

  /* 예약 스케줄 아래 주의 문구(caution) 박스 색상 */
  --caution-bg: #fef3c7;
  --caution-border: #f59e0b;
  --caution-text: #92400e;
}

html[data-theme="dark"] {
  --bg: #0b0d10;
  --card-bg: #16191d;
  --text: #f0f2f5;
  --muted: #9aa1ac;
  --border: #2a2e34;
  --secondary: #232730;
  --secondary-hover: #2c313b;
  --gray: #7b828d;
  --lamp-on: #4ade80;
  --lamp-on-hover: #34d058;
  --lamp-on-text: #052e12;
  --caution-bg: #3a2a0a;
  --caution-border: #d97706;
  --caution-text: #fcd34d;
}

* { box-sizing: border-box; }

/* 주의: html/body에 overflow-x: hidden을 주면 position:sticky인 헤더가
   스크롤 시 사라지는 부작용이 있어(스크롤 컨테이너가 바뀌면서 sticky 기준이
   달라짐), 여기서는 쓰지 않는다. 대신 아래 모바일 미디어쿼리에서 실제
   가로 넘침의 원인(헤더 그리드, 로고 고정폭, 아날로그 시계 등)을 직접
   줄여서 가로 스크롤이 생기지 않도록 한다. */
body {
  margin: 0;
  font-family: -apple-system, "Segoe UI", "Noto Sans KR", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  transition: background 0.15s ease, color 0.15s ease;
}

/* ---- 전체 시스템 켜기/끄기: 헤더 가운데 칸(.system-bar-center)에 표시 ---- */
.system-bar-title {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

/* 전체 시스템 제어 진행 문구와 시간 동기화 진행 문구가 같은 자리(전체켜기/전체끄기
   버튼 바로 아래)에 같은 모양으로 표시되도록 공통 클래스로 스타일을 준다. */
.system-bar-status {
  font-size: 13px;
  min-height: 16px;
  /* 오류 요약처럼 여러 줄을 표시해야 할 때 줄바꿈(\n)이 그대로 반영되도록 한다. */
  white-space: pre-line;
  /* 응답 없는 장비가 많으면 줄이 계속 쌓여서 헤더 오른쪽(마지막 업데이트/언어 선택 등)
     영역까지 침범했었다. 가운데 칸 폭을 넘지 않게 최대 너비를 정해주고, 내용이
     넘치면 2줄까지만 보여준 뒤 "..."으로 줄인다 - 전체 내용은 title(마우스 오버
     툴팁)로 확인 가능하다. */
  max-width: 480px;
  text-align: center;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.4;
}

.system-bar-actions {
  display: flex;
  gap: 16px;
}

.btn.btn-lg {
  padding: 14px 36px;
  font-size: 16px;
  border-radius: 12px;
}

header {
  border-bottom: 1px solid var(--border);
  background: var(--card-bg);
  /* 로고/전체 시스템 제어(전체 켜기/끄기) 버튼을 아래로 스크롤해도 계속 볼 수
     있도록 화면 맨 위에 고정한다. position: fixed 대신 sticky를 쓰면 레이아웃
     흐름 안에 그대로 남아 있어서(처음 위치에서는 평소처럼 보이다가 그 지점을
     지나야 고정됨) 본문에 별도로 위쪽 여백(padding-top)을 줄 필요가 없다. */
  position: sticky;
  top: 0;
  z-index: 60;
}

/* 로고/제목(왼쪽) - 전체 시스템 제어(가운데) - 마지막 업데이트/테마(오른쪽), 세 칸을
   한 줄(그리드)에 배치한다. 가운데 칸은 "auto"로 내용 크기만큼만 차지하고 양옆
   칸이 똑같이 1fr씩 나눠 가지므로, 왼쪽/오른쪽 내용 너비가 서로 달라도 가운데
   칸(전체 시스템 제어)은 항상 헤더 전체 폭의 정중앙에 오게 된다.
   이 그리드 레이아웃은 header 자체가 아니라 안쪽 .header-content에 둬서,
   아래 header-collapse-btn으로 header는 그대로 두고 이 영역만 접었다 펼 수
   있게 한다(접기 버튼은 .header-content의 형제 요소라 접힘 상태와 무관하게
   항상 보인다). */
.header-content {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: 16px;
  /* 위/아래 여백을 같게 주어, 로고가 없을 때도 "전체 시스템 제어" 영역이
     우측(마지막 업데이트/테마 버튼)처럼 헤더 상하 정중앙에 오도록 한다. */
  padding: 16px 28px;
  max-height: 600px;
  opacity: 1;
  overflow: hidden;
  transition: max-height 0.25s ease, opacity 0.2s ease, padding 0.25s ease;
}

header.collapsed .header-content {
  max-height: 0;
  opacity: 0;
  padding-top: 0;
  padding-bottom: 0;
  pointer-events: none;
}

/* 헤더 하단 중앙에 작게 튀어나온 탭 버튼: 눌러서 .header-content를 접었다
   펼 수 있다. header가 position: sticky(= positioned)라서 별도의
   position: relative 래퍼 없이도 이 버튼의 위치 기준이 된다. */
.header-collapse-btn {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translate(-50%, 50%);
  width: 36px;
  height: 20px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 10px 10px;
  background: var(--card-bg);
  color: var(--muted);
  cursor: pointer;
  z-index: 61;
  font-size: 13px;
  line-height: 1;
}

.header-collapse-btn:hover {
  color: var(--text);
  background: var(--secondary);
}

.header-collapse-chevron {
  display: inline-block;
  transition: transform 0.2s ease;
}

header.collapsed .header-collapse-chevron {
  transform: rotate(180deg);
}

header h1 {
  font-size: 20px;
  margin: 0;
  /* 로고가 있을 때는 JS(alignDashboardTitleUnderLogo)가 margin-left로 정렬을
     맞춘다: 제목이 로고보다 짧으면 중앙정렬, 길면 로고와 같은 시작 위치에서
     오른쪽으로 늘어난다. 줄바꿈되면 폭 계산이 어긋나므로 한 줄로 고정한다. */
  white-space: nowrap;
}

.header-title-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* 로고와 대시보드 제목 사이 간격(기존 4px의 절반) */
  gap: 2px;
}

.dashboard-logo {
  /* 이미지 원본 크기와 상관없이 항상 이 크기로 고정 표시(예전 대비 3배 크기) */
  max-height: 120px;
  max-width: 660px;
  object-fit: contain;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  /* 그리드 칸(1fr) 전체로 늘어나지 않고 내용 크기만큼만 차지한 채, 헤더 오른쪽
     가장자리에 그대로 붙도록 한다(기존 justify-content:space-between과 동일한
     위치). */
  justify-self: end;
}

/* ---- 전체 시스템 켜기/끄기: 헤더 가운데 칸에 그대로 들어간다 ---- */
.system-bar-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.muted {
  color: var(--muted);
  font-size: 13px;
}

/* ---- 테마 선택 ---- */
.theme-toggle {
  display: flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.theme-btn {
  border: none;
  background: var(--secondary);
  color: var(--text);
  padding: 6px 12px;
  font-size: 13px;
  cursor: pointer;
}

.theme-btn + .theme-btn {
  border-left: 1px solid var(--border);
}

.theme-btn.active {
  background: var(--primary);
  color: #fff;
  font-weight: 600;
}

.admin-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

/* ---- 테마 선택 아래에 놓이는 언어 선택(한국어/English/日本語) ---- */
.header-actions-stack {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}

.language-select {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--secondary);
  color: var(--text);
  padding: 5px 8px;
  font-size: 13px;
  cursor: pointer;
  /* 모바일에서는 이 칸이 폭 100%로 넓어지는데(아래 미디어쿼리), 기본값(왼쪽
     정렬)으로는 선택된 글자가 넓은 칸의 왼쪽에 쏠려 보인다. 가운데 정렬해서
     칸 폭과 상관없이 글자가 항상 중앙에 오도록 한다. */
  text-align: center;
  text-align-last: center;
}

/* PC 제어(상단) / 프로젝터 제어(하단) 두 구역으로 나뉜 메인 영역. PC는
   사운드 조절 등 손댈 일이 잦은 반면 프로젝터는 켜짐/꺼짐/입력 전환 정도의
   디스플레이 역할이라 중요도가 상대적으로 낮으므로, 공간마다 프로젝터 수량이
   달라 PC 카드를 찾기 어려워지지 않도록 PC를 항상 화면 위쪽에 고정해둔다. */
.device-sections {
  padding-bottom: 40px;
}

.device-section + .device-section {
  margin-top: 8px;
}

.device-section-title {
  margin: 0;
  padding: 20px 28px 4px;
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
}

.device-grid {
  padding: 8px 28px 24px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 20px;
}

.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.card-header h2 {
  margin: 0;
  font-size: 17px;
}

.projector-list,
.pc-list {
  display: flex;
  flex-direction: column;
}

.block {
  padding: 12px 0;
  border-top: 1px solid var(--border);
}

.projector-list > .block:first-child,
.pc-list > .block:first-child {
  border-top: none;
  padding-top: 0;
}

.pc-list {
  margin-top: 4px;
}

.block-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  gap: 8px;
}

.block-header .block-name {
  margin: 0;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

/* 관리자 페이지에서 설정한 IP를 카드에 참고용으로 표시 (연결 안됨/온라인 배지 바로
   아래) — 이 상태가 어느 주소를 보고 판단한 것인지 한눈에 알 수 있도록. */
.block-ip {
  margin: -4px 0 8px;
  font-size: 12px;
  font-family: 'Consolas', 'Menlo', monospace;
}

.block-ip:empty {
  display: none;
}

.row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  padding: 3px 0;
}

.row .label {
  color: var(--muted);
  width: 44px;
  flex-shrink: 0;
}

.row.error-row .value.error-text {
  color: var(--red);
  font-size: 13px;
}

.badge {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--secondary);
  color: var(--muted);
  white-space: nowrap;
}

.badge.on { background: #dcfce7; color: var(--green); }
.badge.off { background: #fee2e2; color: var(--red); }
.badge.warming, .badge.cooling { background: #fef3c7; color: var(--amber); }
.badge.unknown { background: var(--secondary); color: var(--gray); }
.badge.online { background: #dcfce7; color: var(--green); }
.badge.offline { background: #f3f4f6; color: var(--gray); }

html[data-theme="dark"] .badge.on { background: #14532d; color: #86efac; }
html[data-theme="dark"] .badge.off { background: #7f1d1d; color: #fca5a5; }
html[data-theme="dark"] .badge.warming,
html[data-theme="dark"] .badge.cooling { background: #78350f; color: #fcd34d; }
html[data-theme="dark"] .badge.unknown { background: var(--secondary); color: var(--gray); }
html[data-theme="dark"] .badge.online { background: #14532d; color: #86efac; }
html[data-theme="dark"] .badge.offline { background: var(--secondary); color: var(--gray); }

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}

/* 프로젝터 전원 ON/OFF 행과, 입력 전환 행을 분리해서 입력 전환 쪽의 시인성을 높인다. */
.actions.power-actions {
  margin-top: 10px;
}

.actions.input-actions {
  margin-top: 8px;
  align-items: center;
  background: var(--secondary);
  border-radius: 10px;
  padding: 8px 10px;
}

.actions.input-actions .input-select {
  flex: 1;
  min-width: 120px;
}

.btn {
  border: none;
  border-radius: 8px;
  padding: 7px 12px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--primary-hover); }

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

.btn-secondary { background: var(--secondary); color: var(--text); }
.btn-secondary:hover:not(:disabled) { background: var(--secondary-hover); }

/* ---- 전원 ON/OFF 버튼의 "상태 표시등" 색상 ----
   전체켜기/전원 ON/PC 켜기(WOL)과 전체끄기/전원 OFF/PC 종료 버튼은 이제 고정된
   색이 아니라, 기기의 실제 현재 상태에 따라 JS(applyPowerIndicator)가 이 세
   클래스 중 하나를 매번 새로 붙여서 "지금 켜져있는지/꺼져있는지"를 한눈에 보여준다. */
.btn-state-on { background: var(--lamp-on); color: var(--lamp-on-text); }
.btn-state-on:hover:not(:disabled) { background: var(--lamp-on-hover); }

.btn-state-off { background: var(--danger); color: #fff; }
.btn-state-off:hover:not(:disabled) { background: var(--danger-hover); }

.btn-state-inactive { background: var(--secondary); color: var(--muted); }
.btn-state-inactive:hover:not(:disabled) { background: var(--secondary-hover); }

/* ---- PC 카드 하단의 마스터 볼륨 컨트롤바 (음소거 + 슬라이더 + 상태 점) ----
   volume-agent(에이전트 배포 파일)이 그 PC에 설치/실행 중이어야 실제로 동작하며,
   설치되어 있지 않거나 사용 설정을 꺼둔 PC는 항상 적색 점 + 비활성 상태로 표시된다
   (그 자체로 "이 PC는 볼륨 제어가 안 되는 상태"임을 바로 알 수 있다). */
.volume-control {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--border);
}

.volume-control-header {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}

.volume-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--gray);
  flex-shrink: 0;
}

.volume-dot.online { background: var(--green); }
.volume-dot.offline { background: var(--red); }

.volume-label {
  font-weight: 600;
}

.volume-value {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

.volume-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.act-mute-toggle {
  flex-shrink: 0;
  padding: 6px 10px;
}

.act-mute-toggle.is-muted {
  background: var(--danger);
  color: #fff;
}

.act-mute-toggle.is-muted:hover:not(:disabled) {
  background: var(--danger-hover);
}

.volume-slider {
  flex: 1;
  accent-color: var(--primary);
}

.volume-slider:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.input-select {
  padding: 6px 8px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  font-size: 13px;
}

.toast {
  display: block;
  min-height: 16px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted);
}

.toast.error { color: var(--red); }
.toast.success { color: var(--green); }

.settings-footer {
  padding: 16px 28px 32px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--muted);
  flex-wrap: wrap;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

.checkbox-label input[type="checkbox"] {
  width: 15px;
  height: 15px;
  cursor: pointer;
}

.checkbox-label input[type="checkbox"]:disabled {
  cursor: not-allowed;
}

/* ---- 예약 스케줄 (메인 대시보드 하단) ---- */
.scheduler-section {
  padding: 28px 28px 8px;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 28px;
  flex-wrap: wrap;
}

.scheduler-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  width: 100%;
  max-width: 640px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px 28px;
}

.scheduler-title {
  margin: 0;
  /* 요청에 따라 기존 15px 대비 2배 크기로 키움 */
  font-size: 30px;
  font-weight: 700;
  color: var(--text);
}

.scheduler-mode-toggle {
  display: flex;
  gap: 16px;
}

/* 상단 "전체 시스템 제어" 버튼(.btn.btn-lg)과 동일한 크기감을 갖도록
   .btn.btn-lg 쪽에서 padding/font-size/border-radius를 그대로 물려받고,
   여기서는 색상(기본/활성)만 지정한다. */
.mode-btn {
  border: 1px solid var(--border);
  background: var(--secondary);
  color: var(--text);
  cursor: pointer;
}

.mode-btn.active {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

/* ---- 요일별 한 줄: 체크박스 / 요일 / 켜는 시간 / 끄는 시간 ---- */
.scheduler-day-grid {
  display: grid;
  grid-template-columns: 26px 40px minmax(120px, 1fr) minmax(120px, 1fr);
  align-items: center;
  column-gap: 16px;
  row-gap: 10px;
  width: 100%;
}

.scheduler-day-grid-header {
  display: contents;
}

.scheduler-day-grid-header span {
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.scheduler-day-row {
  display: contents;
  cursor: pointer;
}

.scheduler-day-row .day-label {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
}

.scheduler-day-row input[type="checkbox"] {
  width: 17px;
  height: 17px;
  cursor: pointer;
}

.scheduler-day-row input[type="time"] {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card-bg);
  color: var(--text);
  font-size: 14px;
}

/* 체크가 해제된(휴무) 요일은 시간 입력이 흐리게 보여서 한눈에 구분되도록 한다. */
.scheduler-day-row:has(input[type="checkbox"]:not(:checked)) input[type="time"] {
  opacity: 0.4;
}

.scheduler-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 4px;
}

/* 저장 버튼을 "자동/수동" 버튼(.mode-btn, 테두리 1px 포함)과 완전히 같은
   크기로 맞추기 위해, 투명 테두리로 같은 두께만큼의 여백을 맞춰준다. */
#scheduleSaveBtn {
  border: 1px solid transparent;
}

/* ---- 예약 스케줄 바로 위 주의(caution) 안내 박스 ----
   "자동" 모드로 둔 채 이 페이지를 닫아도 예약 스케줄대로 계속 켜짐/꺼짐이
   실행된다는 것을, 눈에 띄는 색으로 한 번 더 강조해서 알려준다. 너비는 아래
   "예약 스케줄 + 아날로그 시계" 줄과 같은 폭(1026px)으로 맞추고 화면 중앙에
   배치한다(불필요하게 옆으로 길게 늘어나 보이지 않도록). */
.schedule-caution-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 느낌표 아이콘이 커진 만큼(아래 .caution-icon 주석 참고) 문구와 너무 붙어
     보이지 않도록 간격을 12px → 20px로 넓힌다. */
  gap: 20px;
  max-width: 1026px;
  margin: 24px auto 0;
  padding: 14px 18px;
  background: var(--caution-bg);
  border: 1px solid var(--caution-border);
  border-left: 4px solid var(--caution-border);
  border-radius: var(--radius);
  color: var(--caution-text);
}

.schedule-caution-banner .caution-icon {
  /* 문구(.caution-text, 14px/line-height 1.6)가 지금 3줄(cautionLine1a,
     cautionLine1b, cautionLine2)이라 전체 블록 높이가 약 14px * 1.6 * 3 ≈
     67px이다. 예전처럼 20px짜리 작은 느낌표 하나만 있으면 옆의 3줄 문구에
     비해 너무 작아 보이므로, 그 높이와 비슷하게 보이도록 느낌표 자체를
     3줄 크기로 키운다(이모지 글자는 font-size 전체를 다 채우지 않으므로
     67px이 아니라 그보다 조금 큰 52px로 맞췄다). 문구 줄 수가 달라지면
     (번역이 길어져 줄이 늘거나 줄면) 이 값도 함께 조정해야 한다. */
  font-size: 52px;
  line-height: 1;
  align-self: center;
}

.schedule-caution-banner .caution-text {
  font-size: 14px;
  line-height: 1.6;
  text-align: center;
  /* 한글은 기본적으로 글자 단위로 줄바꿈될 수 있어("동작합니" / "다." 처럼 단어
     중간이 잘리는 모양) word-break: keep-all로 단어(어절) 단위까지만 줄바꿈
     하도록 한다. 줄1(cautionLine1a/1b)은 이미 <br/>로 보기 좋은 지점에서
     강제 줄바꿈해두었지만, 번역 문구가 더 길어지는 언어(영어/일본어)나 아주
     좁은 화면에서도 단어가 잘리지 않도록 보강한다. */
  word-break: keep-all;
}

.schedule-caution-banner .caution-text strong {
  font-weight: 700;
}

/* ---- 예약 스케줄 오른쪽의 아날로그 시계 (현재 시스템 시간, 초까지 표시) ---- */
.clock-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px 28px;
  align-self: stretch;
  justify-content: center;
}

/* 시계 전체 크기를 --clock-size 변수 하나로 관리한다. 아래 눈금/바늘/중심점의
   모든 위치·크기는 300px 기준 비율(calc(var(--clock-size) * N / 300))로
   표현해뒀기 때문에, 이 변수 하나만 바꾸면(예: 모바일 미디어쿼리에서 220px로)
   바늘 길이까지 같은 비율로 줄어들어 테두리 밖으로 삐져나오지 않는다. */
.analog-clock {
  --clock-size: 300px;
  width: var(--clock-size);
  height: var(--clock-size);
}

.clock-face {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--card-bg);
  border: 6px solid var(--border);
  box-shadow: inset 0 0 0 2px var(--bg);
}

/* 12개의 눈금(시 위치)을 시계 중심을 기준으로 30도씩 회전시켜 배치한다. 눈금 자체는
   .clock-tick 안의 span(중심에서 바깥쪽으로 뻗은 막대)이며, JS(app.js)가 12개를
   생성해 각각 다른 rotate 각도를 인라인 style로 지정한다. */
.clock-tick {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
}

.clock-tick span {
  position: absolute;
  left: calc(var(--clock-size) * -2 / 300);
  top: calc(var(--clock-size) * -136 / 300);
  width: calc(var(--clock-size) * 4 / 300);
  height: calc(var(--clock-size) * 16 / 300);
  background: var(--muted);
}

.clock-tick.major span {
  left: calc(var(--clock-size) * -3 / 300);
  top: calc(var(--clock-size) * -136 / 300);
  width: calc(var(--clock-size) * 6 / 300);
  height: calc(var(--clock-size) * 24 / 300);
  background: var(--text);
}

/* 시/분/초 바늘: 회전 기준점(중심)에 크기 0인 wrap 요소를 두고, 그 자식 span이
   중심에서 위쪽(12시 방향, 0도)으로 뻗어나가도록 배치한 뒤, JS가 wrap에
   transform: rotate(...)를 매 초 갱신해서 시계처럼 움직이게 한다. */
.clock-hand-wrap {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
}

.clock-hand {
  position: absolute;
  border-radius: 3px;
  background: var(--text);
}

.clock-hand.hour {
  left: calc(var(--clock-size) * -4 / 300);
  top: calc(var(--clock-size) * -76 / 300);
  width: calc(var(--clock-size) * 8 / 300);
  height: calc(var(--clock-size) * 76 / 300);
}

.clock-hand.minute {
  left: calc(var(--clock-size) * -3 / 300);
  top: calc(var(--clock-size) * -112 / 300);
  width: calc(var(--clock-size) * 6 / 300);
  height: calc(var(--clock-size) * 112 / 300);
}

.clock-hand.second {
  left: calc(var(--clock-size) * -1.5 / 300);
  top: calc(var(--clock-size) * -124 / 300);
  width: calc(var(--clock-size) * 3 / 300);
  height: calc(var(--clock-size) * 124 / 300);
  background: var(--red);
}

.clock-center {
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(var(--clock-size) * 18 / 300);
  height: calc(var(--clock-size) * 18 / 300);
  margin: calc(var(--clock-size) * -9 / 300) 0 0 calc(var(--clock-size) * -9 / 300);
  border-radius: 50%;
  background: var(--red);
  border: calc(var(--clock-size) * 4 / 300) solid var(--card-bg);
}

.digital-clock-text {
  /* 기존 56px(14px의 4배)에서 다시 절반 크기로 줄이되,
     눈에 띄는 붉은색 굵은 글씨 강조는 그대로 유지한다. */
  font-size: 28px;
  font-weight: 800;
  color: var(--red);
  font-family: 'Consolas', 'Menlo', monospace;
  letter-spacing: 0.03em;
}

/* ---- 관리자 페이지 바로가기 (우측 하단 고정) ----
   일반 사용자 화면에서는 눈에 띄지 않도록 글씨 없이 톱니 아이콘만, 회색 톤으로
   낮은 불투명도로 표시한다(흰색/검정 배경 모두에서 은은하게 묻히도록). 마우스를
   올리면(hover) 살짝 또렷해져서 관리자는 여전히 쉽게 찾아 누를 수 있다. */
.admin-fab {
  position: fixed;
  right: 24px;
  bottom: 24px;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gray);
  color: var(--card-bg);
  text-decoration: none;
  border-radius: 50%;
  font-size: 17px;
  box-shadow: none;
  opacity: 0.32;
  z-index: 50;
  transition: opacity 0.15s ease;
}

.admin-fab:hover {
  opacity: 0.9;
  background: var(--gray);
}

/* ---- 모바일 화면(가로폭 768px 이하) ----
   헤더는 기본적으로 "로고/제목(왼쪽) - 전체 시스템 제어(가운데) -
   마지막 업데이트/테마/언어(오른쪽)"을 3칸 그리드로 한 줄에 배치한다. 하지만
   로고 이미지(dashboard-logo, 최대 660px)처럼 그리드 칸 안에 크기가 있는
   내용이 있으면, 그리드는 기본적으로 칸을 내용 크기보다 작게 줄이지 않아서
   (min-width:auto) 좁은 화면에서는 전체 폭이 넘쳐 좌우 스크롤이 생기고
   오른쪽 칸(전체켜기/끄기, 테마, 언어)이 화면 밖으로 밀려났었다.
   모바일에서는 3칸을 포기하고 로고 → 전체 시스템 제어 → 테마/언어 순으로
   위에서 아래로 쌓아서, 가로 스크롤 없이 로고 바로 아래에 자동 정렬되도록
   한다. */
@media (max-width: 768px) {
  .header-content {
    grid-template-columns: 1fr;
    justify-items: center;
    row-gap: 16px;
    padding: 16px 16px;
  }

  .header-title-block {
    align-items: center;
    width: 100%;
  }

  .dashboard-logo {
    /* 고정 660px 대신 화면 폭에 맞춰 줄어들도록 한다 */
    max-width: 100%;
    height: auto;
  }

  header h1 {
    /* 좁은 화면에서는 로고 아래 중앙 정렬만 하면 충분하므로, JS가 계산해
       넣어주는 margin-left(왼쪽 정렬 보정값)는 무시하고 항상 중앙에 둔다.
       제목이 길면 한 줄 고정(nowrap) 대신 줄바꿈을 허용해 화면 밖으로
       넘치지 않게 한다. */
    margin-left: 0 !important;
    text-align: center;
    white-space: normal;
    word-break: keep-all;
  }

  .system-bar-center {
    width: 100%;
  }

  .system-bar-status {
    max-width: 100%;
  }

  .header-actions {
    justify-self: center;
    justify-content: center;
    width: 100%;
  }

  .header-actions-stack {
    width: 100%;
    max-width: 280px;
    align-items: stretch;
  }

  .theme-toggle {
    align-self: stretch;
  }

  .theme-btn {
    flex: 1;
  }

  .language-select {
    width: 100%;
  }

  /* 예약 스케줄의 아날로그 시계(300x300 기준 크기)가 아주 좁은 화면(360px
     이하)에서 양옆 패딩과 합쳐 가로 스크롤을 만들 수 있어 축소한다. --clock-size만
     바꾸면 눈금/바늘 길이도 같은 비율로 따라 줄어들어(위 .analog-clock 주석 참고)
     초침이 테두리 밖으로 삐져나와 바로 아래 디지털 시계와 겹치는 일이 없다. */
  .analog-clock {
    --clock-size: 220px;
    width: var(--clock-size);
    height: var(--clock-size);
  }

  .scheduler-section {
    padding-left: 12px;
    padding-right: 12px;
  }

  .scheduler-inner,
  .schedule-caution-banner {
    padding-left: 16px;
    padding-right: 16px;
  }

  /* 켜는/끄는 시간 입력칸이 각각 최소 120px를 요구해서(기존
     minmax(120px, 1fr)) 좁은 화면에서는 체크박스/요일 칸까지 합친 전체
     너비가 뷰포트보다 넓어져 가로 스크롤이 생겼다. 모바일에서는 칸 사이
     간격과 최소 너비를 줄여서 한 줄에 다 들어오도록 한다. */
  .scheduler-day-grid {
    grid-template-columns: 22px 32px minmax(96px, 1fr) minmax(96px, 1fr);
    column-gap: 8px;
  }

  .scheduler-day-row input[type="time"] {
    padding: 8px 4px;
    font-size: 13px;
  }

  /* PC/프로젝터 카드 영역(.device-grid)도 한 칸이 최소 320px를 요구해서
     (minmax(320px, 1fr)) 그보다 좁은 화면에서는 가로 스크롤이 생겼다.
     모바일에서는 카드 한 장이 화면 폭 전체를 쓰도록 1열로 바꾼다. */
  .device-grid {
    grid-template-columns: 1fr;
    padding-left: 12px;
    padding-right: 12px;
  }

  .device-section-title {
    padding-left: 12px;
    padding-right: 12px;
  }
}

/* ---- 로그인 사용자 표시 (session.js) ----
   대시보드/관리자 페이지 왼쪽 아래에 작게 띄운다. 오른쪽 아래의 관리자 버튼(⚙)과
   겹치지 않도록 반대편에 둔다. */
.session-chip {
  position: fixed;
  left: 16px;
  bottom: 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 12px;
  color: var(--muted);
  z-index: 60;
  opacity: 0.85;
  max-width: calc(100vw - 90px);
  flex-wrap: wrap;
}
.session-chip:hover {
  opacity: 1;
}
.session-chip-user {
  color: var(--text);
  font-weight: 600;
}
.session-chip a {
  color: var(--primary);
  text-decoration: none;
}
.session-chip a:hover {
  text-decoration: underline;
}
.session-toast {
  position: fixed;
  left: 50%;
  top: 16px;
  transform: translateX(-50%);
  background: var(--danger);
  color: #fff;
  padding: 10px 16px;
  border-radius: 8px;
  font-size: 14px;
  z-index: 100;
}
.admin-fab[hidden] {
  display: none;
}
@media (max-width: 768px) {
  .session-chip {
    position: static;
    margin: 16px auto 70px;
    justify-content: center;
    width: fit-content;
  }
}
