/*
 * game-stage.css — 멀티플레이 인게임 뷰(GameStage) 셸 스타일
 *
 * 로비/대기방과 병존하는 SPA 뷰. tokens.css 의 토큰만 참조한다(하드코딩 금지).
 * breakpoint/position/display/overflow/min-*/aspect 등은 반응형·구현 설정값이므로
 * 토큰으로 만들지 않고 직접 쓴다.
 *
 * Design Spec:
 *   - components/game-stage/base.md — 자신 메인 보드(중앙) · 상대 미니 보드
 *     측면 레일 · 자신 사이드 정보의 배치·정렬·반응형 규칙.
 *   - components/opponent-board/base.md — 상대 진행을 미러링하는 미니 보드의
 *     프레임·네임플레이트·상태 표현(대기/플레이/게임오버).
 *
 * 이 grain(셸)은 배치·프레임·네임플레이트·상태 라벨만 담당한다. 자신 보드/사이드
 * 정보의 실제 렌더와 미니 격자 셀·실시간 동기화는 후속 grain(GameClient)이 채운다.
 */

/* ── GameStage 레이아웃 ─────────────────────────────────────── */
/* 무대 루트는 뷰포트 높이(100dvh)를 최소 높이로 삼고 콘텐츠를 세로 중앙에 둔다 —
   보드가 상단에 쏠리지 않고 화면 중앙에서 자라며, 남는 상하 여백은 justify-content:center
   가 균등하게 배분한다. min-height/display/justify-content·max-width 는 레이아웃 배치를
   위한 구현 설정값이라 토큰을 소비하지 않는다(영역 사이 간격만 space-lg 토큰). */
.game-stage {
  max-width: 72rem; /* 레이아웃 제약(구현 설정값) */
  min-height: 100dvh; /* 동적 뷰포트 높이 채움(구현 설정값) */
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center; /* 세로 중앙 정렬(구현 설정값) */
  gap: var(--space-lg);
}

.game-stage[hidden] {
  display: none;
}

/* 인게임 무대는 보드를 시각 중심에 두어 화면상 제목을 노출하지 않는다.
   제목은 시각적으로 숨기고 보조기술용 접근성 이름(main 의 aria-labelledby 대상)으로만
   남긴다 — 결과 화면 aria-live 안내(.result-screen__announce)와 동일한 clip 선례.
   clip 은 구현 설정값이라 시각 토큰이 아니다. */
.game-stage__title {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/*
 * 무대: [상대 레일] – [자신 메인 보드] – [자신 사이드 정보].
 * 좁은 화면(mobile-first 기본)은 세로로 접어 자신 보드를 맨 위에 두고, 그 아래로
 * 레일·사이드를 내린다(가로 스크롤을 만들지 않는다). 넓은 화면은 한 줄에 나란히
 * 두어 자신 보드가 가운데 오게 한다. 무대 주요 영역 사이 간격은 space-xl.
 */
.game-stage__arena {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xl);
  width: 100%;
}

/* 좁은 화면: 자신 메인 보드를 시각 중심으로 맨 위에 올린다. */
.game-stage__main {
  order: -1;
  display: flex;
  justify-content: center;
}

/* 자신 사이드 정보: 진행 정보 묶음을 세로로 쌓는다(레일 내부 리듬과 동일 space-lg).
   단일 보드 화면 game__side 의 폭 처리를 계승한다. */
.game-stage__side {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  width: min(15rem, 60vw);
}

/* ── 상대 레일 (Opponent Rail) ─────────────────────────────── */
/* 레일 내부 요소 간격 space-lg. 좁은 화면에서는 미니 보드를 가로로 나란히
   배치하고 필요 시 줄바꿈한다. */
.opponent-rail {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: var(--space-lg);
}

/* 넓은 화면: [상대 레일] – [자신 메인 보드] – [자신 사이드 정보] 를 3열 그리드로
   세운다. 좌우 바깥 열(1fr)을 대칭으로 두어 가운데 auto 열(자신 보드)이 화면의
   '참 중심'에 오게 한다 — flex 의 justify-content:center 는 세 열을 한 그룹으로만
   중앙에 두어(레일·사이드 폭이 달라) 자신 보드가 실제 중심에서 벗어났고, 레일이
   좌측 가장자리로 밀려 보드와 사이 빈틈이 벌어졌다. 상대 레일과 사이드 정보는
   각자 안쪽(보드 쪽)으로 붙여 여백을 바깥으로 밀어내, 자신 보드가 시각 중심으로
   도드라지고 좌우는 보조 위계로 대칭을 이루게 한다.
   분기점(900px)·열 구성·justify-self 는 뷰포트에 맞춘 구현 설정값이다. */
@media (min-width: 900px) {
  .game-stage__arena {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: start;
    justify-content: center;
    gap: var(--space-xl);
  }

  /* 상대 레일: 왼쪽 바깥 열. 세로로 쌓아 한 측면에 컴팩트하게 묶고, 안쪽(보드 쪽=
     오른쪽)으로 붙인다. */
  .opponent-rail {
    flex-direction: column;
    flex-wrap: nowrap;
    justify-self: end;
    align-items: flex-end;
  }

  /* 자신 메인 보드: 가운데 auto 열. 좁은 화면의 order:-1 을 되돌려 소스 순서
     (레일 – 보드 – 사이드)대로 가운데 놓이게 한다. */
  .game-stage__main {
    order: 0;
  }

  /* 자신 사이드 정보: 오른쪽 바깥 열. 안쪽(보드 쪽=왼쪽)으로 붙인다. */
  .game-stage__side {
    justify-self: start;
  }
}

/* ── 미니 보드 (opponent-board) 셸 ─────────────────────────── */
.opponent-board {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  width: min(9rem, 40vw); /* 미니 위계 footprint(구현 설정값) */
}

/* 네임플레이트: 흰 스티커 라벨. 넘치면 말줄임. */
.opponent-board__nameplate {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2xs);
  background-color: var(--color-surface-raised);
  border: var(--border-width-thin) solid var(--color-ink);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-pop-sm);
  padding: var(--space-2xs) var(--space-xs);
}

.opponent-board__name {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-size-sm);
  color: var(--color-text-default);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* AI 표식: 프로젝트 전역 AI 색(color-support). 사람 플레이어는 표식 없음. */
.opponent-board__badge {
  flex: none;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-black);
  font-size: var(--text-size-xs);
  letter-spacing: var(--letter-spacing-wide);
  color: var(--color-text-inverse);
  background-color: var(--color-support);
  border: var(--border-width-thin) solid var(--color-ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-pop-sm);
  padding: 0 var(--space-xs);
}

/* 미니 well·프레임: 메인 프레임(chunky)보다 한 단계 얇은 아웃라인(thick),
   작은 하드 그림자(pop-sm). 격자 셀 렌더는 후속 grain(GameClient) 소유이며,
   셸 단계에서는 well 프레임만 둔다(footprint 는 구현 설정값). */
.opponent-board__grid {
  position: relative;
  background-color: var(--color-board-well);
  border: var(--border-width-thick) solid var(--color-ink);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop-sm);
  padding: var(--space-2xs);
  min-height: 9rem; /* 빈 셸의 미니 보드 자리(구현 설정값) */
}

/* 상태 라벨(대기 중 · 게임 오버): 짧은 명사구 마이크로카피(opponent-board 소유). */
.opponent-board__status {
  text-align: center;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-size-xs);
  letter-spacing: var(--letter-spacing-wide);
  color: var(--color-text-muted);
}

/* 대기(waiting): 물러난 표현 — 네임플레이트 라벨과 상태 라벨을 옅게. */
.opponent-board--waiting .opponent-board__name {
  color: var(--color-text-muted);
}

.opponent-board--waiting .opponent-board__status {
  color: var(--color-text-muted);
}

/* 플레이(playing): 진행 중. 실시간 갱신 자체가 진행을 나타내므로 상태 라벨 없음. */
.opponent-board--playing .opponent-board__status {
  display: none;
}

/* 게임오버(game over): color-ink 파생 반투명 스크림으로 진행 정지를 신호하고,
   color-danger 로 "게임 오버" 라벨을 얹는다. 스크림 아래 마지막 스택은 남는다. */
.opponent-board--over .opponent-board__grid::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: color-mix(in srgb, var(--color-ink) 60%, transparent);
  border-radius: var(--radius-md);
}

.opponent-board--over .opponent-board__status {
  color: var(--color-danger);
}

/* ── 반응형: 작은 화면 전체화면(모바일) ─────────────────────────
   작은 화면에서는 무대가 뷰포트 전체(100dvh × 100vw)를 채우고 페이지 스크롤을 만들지
   않는다(overflow: hidden). 세로 중앙 정렬(justify-content:center)은 유지해 보드가
   화면 중앙에 오고, 자신 사이드 정보(HUD·프리뷰·조작 안내)와 상대 레일은 보드를 가리지
   않도록 보드 아래에 가로로 접어 컴팩트하게 배치한다(단일 보드 화면 game.css 의 좁은 화면
   사이드 재배치 선례와 동일 방향). height/width/overflow·flex 방향 전환·분기점(640px)은
   뷰포트에 맞춘 구현 설정값이며, 영역 간격만 spacing 토큰을 소비한다. */
@media (max-width: 640px) {
  .game-stage {
    width: 100vw;
    height: 100dvh;
    max-width: none;
    overflow: hidden;
    padding: var(--space-md) var(--space-sm);
  }

  /* 아레나 내부 간격을 좁혀 보드 + 주변 정보가 한 화면에 담기게 한다. */
  .game-stage__arena {
    gap: var(--space-md);
  }

  /* 자신 사이드 정보: 보드 아래로 접어 가로 나열(보드를 가리지 않는 보조 위계). */
  .game-stage__side {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    width: auto;
  }

  /* 상대 레일: 좁은 화면 기본(mobile-first)에서 이미 보드(.game-stage__main 의
     order:-1) 아래로 접혀 미니 보드를 가로로 나란히(flex-wrap) 나열한다 — 전체화면에서는
     레일 내부 간격을 space-sm 으로 좁혀(무대 영역 간격을 space-md 로 좁힌 것과 같은 결)
     미니 보드를 촘촘히 눌러, 세로 중심의 보드를 가리지 않는 컴팩트한 보조 위계로 담는다.
     미니 보드 자체의 footprint 는 미니 격자 셀 크기(렌더 grain 소유 구현 설정값)에
     맞춰진 base 폭을 유지한다 — 격자보다 좁혀 잘라내지 않는다. */
  .opponent-rail {
    gap: var(--space-sm);
  }
}
