/*
 * 🔴 위치·크기는 대부분 JS(layout.ts)가 인라인으로 넣는다. 여기는 "성격"만 정의한다.
 *    이유: 디자인 좌표 하나를 CSS 미디어쿼리로 두 벌 관리하면 반드시 어긋난다.
 * 🔴 hover 전용 동작 금지 — 터치에는 hover 가 없다. :hover 규칙을 아예 쓰지 않는다.
 */
:root {
  --ink: #f4f8fb;
  --ink-dim: #b9c8d6;
  --panel: #182430;
  --panel-edge: #2f4152;
  --gate-fill: #f2c879;
  --gate-edge: #8a6520;
  --gate-text: #14202b;
  --gain: #3fd6a8;
  --loss: #d98cb4;
  --zone: #223448;
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

/*
 * 🔴 `[hidden]` 을 이기지 못하게 못 박는다.
 *    UA 스타일시트의 `[hidden]{display:none}` 은 특이도 0-0-1 이라 `#ghost{display:flex}`
 *    같은 id 규칙에 **진다**. 그래서 el.hidden=true 인데도 화면에 그대로 남았다 —
 *    데모 고스트가 60초 내내 필드 위에 떠 있었다(실측). 개별 요소마다 막지 않는다.
 */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  background: #0b1118;
  color: var(--ink);
  font-family: system-ui, -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif;
  touch-action: manipulation;
  user-select: none;
}

#stage {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top left;
  background: #141d27; /* 캔버스 그라디언트의 밝은 쪽 — 대비 계측이 보수적으로 나오게 */
  overflow: hidden;
}

#world {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
}

#overlay {
  position: absolute;
  inset: 0;
}

.panel {
  position: absolute;
  background: var(--panel);
  border: 3px solid var(--panel-edge);
  border-radius: 18px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
}

.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 0 1 auto;
}

/* 시간과 점수를 눈으로 갈라 준다 — 4자리 점수에서 두 숫자가 한 덩어리로 읽혔다. */
.stat + .stat {
  border-left: 2px solid var(--panel-edge);
  padding-left: 0.42em;
  margin-left: 0.42em;
}

.panel-label {
  color: var(--ink-dim);
  letter-spacing: 0.04em;
  /* 🔴 접히게 두면 "넘쳤다"가 아니라 "두 줄이 됐다"로 나타나 계측기를 통과한다.
     nowrap 이어야 넘침이 넘침으로 보인다(실측: 「남은 시간」이 「남은 시 / 간」으로 접혔다). */
  white-space: nowrap;
}

.key {
  font-weight: 800;
  color: var(--ink);
  line-height: 1.05;
  white-space: nowrap;
}

.body {
  color: var(--ink);
  line-height: 1.25;
}

#roster-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: center;
  width: 100%;
}

#roster-list li {
  display: flex;
  align-items: center;
  gap: 0.35em;
}

#roster-list li .dot {
  display: inline-block;
  border-radius: 50%;
}

/* 상태는 색이 아니라 **테두리·불투명도**로 구분한다(좌석 색은 정체성 전용). */
#roster-list li[data-state='now'] .dot {
  box-shadow: 0 0 0 5px var(--ink);
}

/*
 * 🔴 '완료'와 '건너뜀'을 **같은 모양**으로 그린다.
 *    로스터의 기능은 "누가 다음이냐"이고 그 관점에서 둘은 동치다. 굳이 구분하면
 *    특정 아이가 한 라운드 내내 흑백으로 공개 표시된다 — 형태만 바뀐 낙인이다.
 *    (결과표의 '건너뜀'은 남긴다. 거기서 비우면 0점처럼 읽혀 더 나쁘다.)
 */
#roster-list li[data-state='done'] .dot,
#roster-list li[data-state='skipped'] .dot {
  opacity: 0.4;
}

#banner {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--panel);
  border: 3px solid var(--panel-edge);
  border-radius: 18px;
  padding: 0 0.4em;
}

#prompt {
  white-space: nowrap;
}

.gate {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gate-fill);
  border: 4px solid var(--gate-edge);
  border-radius: 14px;
  color: var(--gate-text);
  font-weight: 800;
  overflow: hidden;
  will-change: transform;
}

.gate[data-hidden='1'] {
  visibility: hidden;
}

.gate-text {
  white-space: nowrap;
  padding: 0 0.12em;
}

.zone {
  position: absolute;
  background: var(--zone);
  border: 4px solid var(--panel-edge);
  border-radius: 24px;
  color: var(--ink);
  font-size: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}

.zone:active {
  background: #2f4762;
}

#ghost {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  color: var(--gain);
  text-shadow: 0 0 24px rgba(0, 0, 0, 0.9);
  animation: ghost-pulse 0.5s ease-in-out infinite alternate;
}

@keyframes ghost-pulse {
  from { opacity: 0.55; transform: scale(0.92); }
  to   { opacity: 1;    transform: scale(1.06); }
}

.modal {
  position: absolute;
  inset: 0;
  background: rgba(9, 14, 20, 0.9);
}

.modal-card {
  position: absolute;
  background: var(--panel);
  border: 4px solid var(--panel-edge);
  border-radius: 24px;
  text-align: center;
  overflow: auto;
}

.modal-actions {
  position: absolute;
  display: flex;
  gap: 24px;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}

.btn {
  background: var(--gate-fill);
  color: var(--gate-text);
  border: 4px solid var(--gate-edge);
  border-radius: 18px;
  font-weight: 800;
  font-family: inherit;
  cursor: pointer;
}

.btn.secondary {
  background: var(--zone);
  color: var(--ink);
  border-color: var(--panel-edge);
}

.btn:active {
  transform: translateY(2px);
}

table.standings {
  border-collapse: collapse;
  margin: 0 auto;
}

/**
 * 🔴 결과 카드는 **세로 예산이 고정**이다(버튼줄 위까지). 그런데 안의 문단은 브라우저 기본
 *    여백(상하 1em = 48px 씩)을 그대로 달고 있어서, 문단 두 개가 여백만으로 ~190px 를 먹었다.
 *    그 사이 GDD 필수인 우연 기준선(33.3%) 병기가 화면 밖으로 밀려났다 — `overflow:auto`
 *    라 아무 신호도 없이. 여백을 직접 쥔다.
 */
#modal-title {
  margin: 0 0 12px;
}

.modal-card p {
  margin: 10px 0 0;
}

/**
 * 🔴 표를 세로로만 쌓으면 **인원·항목이 늘 때 반드시 넘친다.** 6인 학급 순위표가 그렇게
 *    4·5·6번을 화면 밖으로 밀어냈다. 세로 예산이 고정이면 넘치는 쪽은 가로여야 한다 —
 *    열로 흘린다(한 열 최대 N행, 넘으면 옆 열).
 */
.statflow {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: 0 56px;
}

/** 안내 문단들도 한 줄로 나란히 — 세로로 쌓으면 그만큼 표가 밀린다. */
.notes {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0 36px;
}

table.standings th,
table.standings td {
  /* 🔴 세로 여백은 아낀다. 0.25em 이면 행이 84px(폰트 48 × 1.25 + 여백 24)이 되고,
     행 4개면 그것만으로 카드 세로 예산의 절반을 쓴다. 글자 크기는 그대로 둔다 —
     줄여도 되는 건 여백이지 글자가 아니다(본문 하한 48px 은 감사가 지킨다). */
  padding: 0.12em 0.6em;
  text-align: center;
  color: var(--ink);
}

table.standings tr[data-skipped='1'] td {
  color: var(--ink-dim);
}

.baseline-note {
  color: var(--ink-dim);
}

/* 라스트 스퍼트 — 마지막 10초. 색만으로 알리지 않는다(크기도 함께 커진다). */
#timer.climax {
  color: var(--gain);
  transform: scale(1.12);
  transform-origin: left center;
}

/* 관전자 안내 — 교실 모드 전용. 60초 동안 나머지 25명이 할 일을 준다.
   🔴 화면 아래쪽(대열 밑 빈 공간)에 둔다. 판정선~게이트 구간을 절대 가리지 않는다. */
.spectator {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-dim);
  font-weight: 700;
  letter-spacing: -0.01em;
  pointer-events: none;
}
