/*
 * game.css — 인게임 화면(메인 테트리스 보드) 스타일
 *
 * 모든 디자인 값은 tokens.css 의 토큰(var(--token))만 참조한다. 원시
 * 색/서체/간격/모서리/그림자/테두리 값을 직접 쓰지 않는다(하드코딩 금지).
 * 셀 크기·간격·그리드 열·z-index·aspect-ratio 등은 시각 스타일이 아니라
 * 반응형/구현 설정값이므로 토큰으로 만들지 않고 여기서 직접 쓴다.
 *
 * 카툰 렌더링 원칙(팝 컬러 · 잉크 아웃라인 · 하드 그림자 · 둥근 형태)과
 * "게임 보드 적용"(조각 셀 · 고스트 · 락)을 소비한다.
 */

/* ── 레이아웃 ─────────────────────────────────────────────── */
.game {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
}

.game__title {
  color: var(--color-text-inverse);
  text-shadow: var(--shadow-pop-sm);
}

.game__stage {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: var(--space-xl);
}

.game__side {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  width: min(15rem, 60vw);
}

/* ── 메인 보드 (tetris-board) ─────────────────────────────── */
/* 셀 한 변 크기: 가로(vw)와 세로(dvh) 두 축의 제약을 동시에 받아 뷰포트에 꽉 차게
   스케일되는 반응형 치수(구현 설정값). min(vw, dvh) 로 더 빡빡한 축이 크기를 정하므로,
   좁고 긴 화면(모바일 세로)은 폭이, 넓고 낮은 화면(데스크톱)은 높이가 상한을 준다.
   상한 캡을 30→44px 로 상향해 큰 화면에서 보드가 상단 쏠림 없이 더 크게 자라도록 한다.
   dvh 는 모바일 주소창 접힘까지 반영하는 동적 뷰포트 높이로, 100dvh 전체화면 무대와
   맞물려 세로 오버플로 없이 채운다. 셀 크기·간격·종횡비는 토큰이 아닌 구현 설정값이다. */
.board {
  --cell: clamp(15px, min(8.5vw, 4.2dvh), 44px);
  position: relative;
  background-color: var(--color-board-well);
  border: var(--border-width-chunky) solid var(--color-ink);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop-lg);
  padding: var(--space-xs);
}

/* 빈 셀 격자: gap 사이로 격자선 색이 비쳐 은은한 그리드가 된다. */
.board__grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 10), var(--cell));
  grid-auto-rows: var(--cell);
  gap: 1px;
  background-color: var(--color-grid-line);
  border: 1px solid var(--color-grid-line);
}

/* 셀 기본(빈 칸): well 배경. */
.cell {
  background-color: var(--color-board-well);
}

/* 조각 셀(활성 · 잠긴 스택): 조각색 채움 + 잉크 아웃라인 + 말랑한 둥근 형태 +
   조각색에서 파생한 부드러운 입체 면(좌상단 밝은 볼륨 / 우하단 어두운 볼륨) +
   상단 흰빛 광택 시트. 베벨은 흐림 0의 하드 면이 아니라 소량 blur 를 준 젤리
   볼륨으로 완화한다(카툰 아웃라인·조각색 정체성은 유지). 광택·볼륨은 조각색·
   흰빛에서 파생하는 국소 이펙트이며 조각별 하이라이트/그림자 토큰을 만들지 않는다.
   blur·오프셋·그라데이션 기하는 셀 비례 구현 설정값이다. */
.cell--filled {
  background-color: var(--piece-color);
  background-image: radial-gradient(
    118% 90% at 30% 14%,
    color-mix(in srgb, var(--piece-color) 32%, var(--color-text-inverse)) 0%,
    transparent 48%
  );
  border: var(--border-width-thin) solid var(--color-ink);
  border-radius: var(--radius-blob);
  box-shadow:
    inset 0.16em 0.18em 0.3em color-mix(in srgb, var(--piece-color) 42%, var(--color-text-inverse)),
    inset -0.18em -0.22em 0.34em color-mix(in srgb, var(--piece-color) 58%, var(--color-ink));
}

/* 고스트(하드드롭 예상 위치): 채우지 않는 저알파 윤곽 투영. 활성/잠긴
   셀보다 물러나 보인다(조각색 파생 국소 이펙트). */
.cell--ghost {
  background-color: color-mix(in srgb, var(--piece-color) 16%, transparent);
  border: var(--border-width-thin) solid
    color-mix(in srgb, var(--piece-color) 60%, transparent);
  border-radius: var(--radius-blob);
}

/* 쓰레기 셀(공격으로 쌓인 방해 줄): 조각 셀·아이템 셀과 명확히 구분되는 회색 무광
   블록. 방해(쓰레기) 색 플랫 채움(--color-garbage) + 잉크 아웃라인(color-ink,
   border-width-thin) + 셀 형태 일관성을 위한 radius-blob 만 쓴다. 조각 정체성색이
   아니라 '무의미한 방해 블록'이므로 무광(matte)이다 — .cell--filled 의 광택
   radial-gradient·입체 bevel(inset box-shadow)도, .cell--item 의 광택 시트(::before)·
   아이콘 마커(::after)도 갖지 않는 평평한 채움이다(가산 이펙트 없음). */
.cell--garbage {
  background-color: var(--color-garbage);
  border: var(--border-width-thin) solid var(--color-ink);
  border-radius: var(--radius-blob);
}

/* 락 순간 번쩍임(락 flash 다듬기): 조각이 고정되는 찰나 그 칸이 흰빛
   (color-text-inverse)으로 짧게 번쩍였다가 조각색으로 잦아든다. 정적 색 스왑이
   아니라 duration-fast 동안 흰빛→조각색으로 부드럽게 안착하는 펄스로 다듬어, 딱딱한
   점멸 대신 '탁' 박히는 느낌을 준다. board__grid 하위로 두어 아이템 셀 밝기 펄스
   (.cell--item) 위에 얹혀도 이 번쩍임이 우선한다. 붕괴 직전 프레임에서 방금 잠긴
   조각 셀(제거되지 않는 칸)에 적용된다. */
.board__grid .cell--flash {
  animation: cell-flash var(--duration-fast) var(--easing-standard) both;
}

/* 락 flash: 흰빛에서 그 칸의 조각색으로 안착(both 로 조각색에 머문다 → 애니메이션
   후에도 일반 채움 셀과 동일하게 보인다). 색은 토큰만 쓴다. */
@keyframes cell-flash {
  0% { background-color: var(--color-text-inverse); }
  100% { background-color: var(--piece-color); }
}

/* 라인 제거 디졸브/붕괴: 가득 찬 행의 셀이 즉시 사라지지 않고 흰빛으로 번쩍인 뒤
   말랑하게 오그라들며(scale↓) 투명해져 '깨지는' 인상을 준다. 렌더러가 붕괴 직전
   보드를 잠깐 고정해 이 연출(duration-collapse)을 재생한 뒤 실제 붕괴 상태로
   전환한다(후속 낙하 트랜지션으로 이어짐). board__grid 하위로 두어 아이템 셀 밝기
   펄스보다 우선한다. */
.board__grid .cell--clearing {
  animation: cell-clear var(--duration-collapse) var(--easing-standard) both;
  z-index: 1; /* 오그라들 때 이웃 격자선 위로 살짝 떠오르게(구현 설정값) */
}

/* 디졸브 키프레임: 흰빛 flash(0~26%) → 오그라들며 소멸. 흰빛은 색 토큰만 쓰고,
   스케일·오파시티 기하는 셀 비례 구현 설정값이다. */
@keyframes cell-clear {
  0% { background-color: var(--color-text-inverse); transform: scale(1); opacity: 1; }
  26% { background-color: var(--color-text-inverse); transform: scale(1.06); opacity: 1; }
  100% { background-color: var(--color-text-inverse); transform: scale(0.06); opacity: 0; }
}

/* 후속 낙하 트랜지션: 라인이 제거되고 위 스택이 내려와 자리를 잡는 순간, 격자 전체가
   살짝 아래로 떨어졌다 제자리로 안착(easing-pop 오버슈트)하며 낙하를 체감시킨다.
   붕괴 상태로 전환한 직후 1회 재생한다(반복 없음, 렌더러가 클래스를 붙였다 뗀다).
   낙하 거리는 셀 크기 비례 구현 설정값이다. */
.board__grid--settle {
  animation: board-settle var(--duration-base) var(--easing-pop);
}
@keyframes board-settle {
  0% { transform: translateY(calc(var(--cell, 24px) * -0.4)); }
  100% { transform: translateY(0); }
}

/* 다중/연속 줄 제거 강화 연출 — 보드 프레임 전체 화면 흔들림(M-5). 렌더러가 강화 트리거
   (2줄 이상 또는 콤보≥2)에서 자기 메인 보드 프레임(.board)에 이 modifier 를 붙였다 지속
   후 뗀다(1줄 단발 제거에는 붙이지 않는다 → 기존 연출만). 프레임이 짧게 흔들려 '한 방'의
   타격감을 준다. 흔들림 지속은 motion 토큰 --duration-shake 단일 출처, 이징은 easing-
   standard 를 소비하고, 흔들림 진폭(px)은 셀·프레임 비례 구현 설정값이다(값을 바꿔도
   '흔들림' 역할 불변). 보드 프레임을 통째로 흔들므로 안쪽 격자·이펙트 오버레이·콤보 팝업이
   함께 흔들린다(프레임 전체 흔들림). 순수 표현 계층 — 낙하/판정(clear freeze envelope
   --duration-collapse)에 관여하지 않는다. */
.board--shake {
  animation: board-shake var(--duration-shake) var(--easing-standard) both;
}
@keyframes board-shake {
  0% { transform: translate(0, 0); }
  15% { transform: translate(-5px, 3px); }
  30% { transform: translate(5px, -3px); }
  45% { transform: translate(-4px, -3px); }
  60% { transform: translate(4px, 3px); }
  75% { transform: translate(-3px, 2px); }
  100% { transform: translate(0, 0); }
}

/* 모션 최소화 선호: 라인 제거 연출(락 flash·디졸브·낙하 settle)과 강화 연출 화면
   흔들림(.board--shake)을 끈다. 렌더러도 이 경우 붕괴 프레임을 열지 않고 흔들림 modifier
   를 붙이지 않지만(콤보 팝업 정보·낭독은 유지), 어떤 경로로 남더라도 애니메이션 없이 즉시
   반영되도록 방어한다. */
@media (prefers-reduced-motion: reduce) {
  .board__grid .cell--flash,
  .board__grid .cell--clearing,
  .board__grid--settle,
  .board--shake {
    animation: none;
  }
}

/* 조각 타입 → 조각 정체성 색 매핑(I/O/T/S/Z/J/L). */
.cell--i,
.preview-cell--i { --piece-color: var(--color-piece-i); }
.cell--o,
.preview-cell--o { --piece-color: var(--color-piece-o); }
.cell--t,
.preview-cell--t { --piece-color: var(--color-piece-t); }
.cell--s,
.preview-cell--s { --piece-color: var(--color-piece-s); }
.cell--z,
.preview-cell--z { --piece-color: var(--color-piece-z); }
.cell--j,
.preview-cell--j { --piece-color: var(--color-piece-j); }
.cell--l,
.preview-cell--l { --piece-color: var(--color-piece-l); }

/* ── 다음 조각 프리뷰 (next-preview) ─────────────────────── */
.next-preview {
  background-color: var(--color-surface-raised);
  border: var(--border-width-thick) solid var(--color-ink);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop-md);
  padding: var(--space-md);
}

.next-preview__label {
  font-size: var(--text-size-sm);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-muted);
  letter-spacing: var(--letter-spacing-wide);
}

.next-preview__pieces {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  margin-top: var(--space-sm);
}

/* 프리뷰 조각: 보드 조각 셀 처리를 축소 스케일로 적용(프리뷰 셀 크기는
   구현 설정값). */
.preview-piece {
  --preview-cell: clamp(12px, 2.2vh, 20px);
  display: grid;
  gap: 1px;
}

.preview-cell {
  width: var(--preview-cell);
  height: var(--preview-cell);
}

.preview-cell--filled {
  background-color: var(--piece-color);
  background-image: radial-gradient(
    118% 90% at 30% 14%,
    color-mix(in srgb, var(--piece-color) 32%, var(--color-text-inverse)) 0%,
    transparent 48%
  );
  border: var(--border-width-thin) solid var(--color-ink);
  border-radius: var(--radius-blob);
  box-shadow:
    inset 0.14em 0.16em 0.26em color-mix(in srgb, var(--piece-color) 42%, var(--color-text-inverse)),
    inset -0.16em -0.2em 0.3em color-mix(in srgb, var(--piece-color) 58%, var(--color-ink));
}

/* 프리뷰 아이템 마커: 아이템을 품은 예정 조각의 그 칸에, 보드 아이템 셀(.cell--item)과
   동일한 패턴(광택 + 그 칸이 품은 아이템의 카탈로그 아이콘 코믹 아웃라인)을 프리뷰 축소
   스케일로 얹는 가산 규칙. 조각색 채움 셀 위에 마커만 덧입혀 프리뷰에서도 아이템 유무·
   종류가 구분되게 한다. 프리뷰는 읽기용 정보이므로 보드 셀의 점멸(flicker)은 얹지 않고
   광택·아이콘 표식만 소비한다. 글리프는 --item-glyph-{id} 단일 출처를 소비하고
   미주입 시 ★ 로 폴백한다(items.css 의 보드 셀과 동일 계약). */
.preview-cell--item {
  position: relative;
}

/* 광택(gloss): 보드 아이템 셀과 동일한 color-text-inverse 투명 mix 파생 국소 이펙트. */
.preview-cell--item::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    circle at 32% 28%,
    color-mix(in srgb, var(--color-text-inverse) 62%, transparent),
    transparent 62%
  );
  pointer-events: none;
}

/* 아이콘 마커: 셀 중앙에 그 칸이 품은 아이템의 아이콘. 조각색 위에서도 또렷하도록
   color-ink 하드 그림자(shadow-pop-sm) 코믹 아웃라인(item-card §아이콘 스타일 규칙 계승).
   크기는 프리뷰 셀에 비례하는 구현 설정값(em). */
.preview-cell--item::after {
  content: "★";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.82em;
  line-height: 1;
  color: var(--color-text-inverse);
  text-shadow: var(--shadow-pop-sm);
  pointer-events: none;
}

/* 아이템 id 별 아이콘 글리프. 카탈로그 단일 출처에서 주입된 --item-glyph-{id} 를 소비하고
   미주입 시 ★ 로 폴백한다(보드 셀과 동일 계약, CSS 에 이모지 중복 하드코딩 없음). */
.preview-cell--item--bomb::after { content: var(--item-glyph-bomb, "★"); }
.preview-cell--item--lightning::after { content: var(--item-glyph-lightning, "★"); }
.preview-cell--item--shield::after { content: var(--item-glyph-shield, "★"); }
.preview-cell--item--potion::after { content: var(--item-glyph-potion, "★"); }
.preview-cell--item--magnet::after { content: var(--item-glyph-magnet, "★"); }
.preview-cell--item--star::after { content: var(--item-glyph-star, "★"); }
.preview-cell--item--meteor::after { content: var(--item-glyph-meteor, "★"); }

/* ── 점수·레벨·줄 (game-hud) ─────────────────────────────── */
.game-hud {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  background-color: var(--color-surface-raised);
  border: var(--border-width-thick) solid var(--color-ink);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop-md);
  padding: var(--space-md);
}

.game-hud__stat {
  display: flex;
  flex-direction: column;
}

.game-hud__label {
  font-size: var(--text-size-sm);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-muted);
  letter-spacing: var(--letter-spacing-wide);
}

.game-hud__value {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-black);
  color: var(--color-text-default);
  line-height: var(--line-height-tight);
  font-size: var(--text-size-xl);
}

.game-hud__value--primary {
  font-size: var(--text-size-2xl);
}

/* ── 조작 안내 (controls-guide) ──────────────────────────── */
.controls-guide {
  background-color: var(--color-surface-raised);
  border: var(--border-width-thick) solid var(--color-ink);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
}

.controls-guide__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.controls-guide__item {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

/* 키캡: 인셋 표면 + 잉크 아웃라인 + 둥근 모서리. */
.keycap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.75em;
  background-color: var(--color-surface-sunken);
  border: var(--border-width-thin) solid var(--color-ink);
  border-radius: var(--radius-sm);
  padding: var(--space-2xs) var(--space-xs);
  font-size: var(--text-size-sm);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-default);
}

.controls-guide__action {
  font-size: var(--text-size-sm);
  color: var(--color-text-muted);
  margin-left: auto;
}

/* ── 게임 상태 오버레이 (game-overlay) ───────────────────── */
/* 상태 오버레이는 기본 숨김, 활성 상태(일시정지·게임 오버·관전)에서만 노출한다
   (Design Spec: game-overlay §가시성). 아래 요소들은 class 선택자로 display 를
   지정하므로, JS 가 세팅하는 hidden 속성이 UA 의 [hidden]{display:none} 을
   이기지 못한다 — 같은 요소에 [hidden] 규칙을 명시해 hidden 을 존중시킨다.
   display 는 구현 설정값이라 토큰을 소비하지 않는다(coding.md §구현 설정값). */
.game-overlay[hidden],
.game-overlay__summary[hidden],
.game-overlay__hint[hidden],
.game-overlay__actions[hidden] {
  display: none;
}

.game-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
}

/* 스크림: color-ink 파생 반투명 막(모달 스크림과 동일 계층의 국소 이펙트). */
.game-overlay__scrim {
  position: absolute;
  inset: 0;
  background-color: color-mix(in srgb, var(--color-ink) 74%, transparent);
  border-radius: var(--radius-md);
}

.game-overlay__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  width: min(88%, 16rem);
  background-color: var(--color-surface-raised);
  border: var(--border-width-chunky) solid var(--color-ink);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop-lg), var(--shadow-float);
  padding: var(--space-lg);
  text-align: center;
}

.game-overlay__title {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-black);
  font-size: var(--text-size-2xl);
  line-height: var(--line-height-tight);
  color: var(--color-text-default);
}

.game-overlay__summary {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  width: 100%;
}

.game-overlay__summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
}

.game-overlay__summary-label {
  font-size: var(--text-size-sm);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-muted);
  letter-spacing: var(--letter-spacing-wide);
}

.game-overlay__summary-value {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-black);
  font-size: var(--text-size-lg);
  color: var(--color-text-default);
}

.game-overlay__hint {
  font-size: var(--text-size-sm);
  color: var(--color-text-muted);
}

.game-overlay__actions {
  display: flex;
  gap: var(--space-md);
}

/* ── 버튼 (button/base + primary) ─────────────────────────
   공유 button Component 를 이 화면에서 토큰으로 실현한다(game.html 단독 페이지는
   로비 스타일시트를 불러오지 않으므로, 로비의 확정 참조원과 동일한 토큰 조합으로
   같은 컴포넌트를 구성한다 — 값 드리프트 없는 화면별 실현).
   상호작용 피드백 시간·곡선은 motion 토큰이 소유한다(duration-fast: hover/press,
   easing-standard: 일반 상태 전환). 원시 0.08s/0.12s 하드코딩을 lobby.css 와
   동일하게 토큰으로 교정한다. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-black);
  font-size: var(--text-size-lg);
  line-height: var(--line-height-tight);
  letter-spacing: var(--letter-spacing-wide);
  padding: var(--space-sm) var(--space-xl);
  border: var(--border-width-chunky) solid var(--color-ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-pop-md);
  cursor: pointer;
  transition: transform var(--duration-fast) var(--easing-standard),
    box-shadow var(--duration-fast) var(--easing-standard),
    background-color var(--duration-fast) var(--easing-standard);
}

.btn:active {
  transform: translate(3px, 3px);
  box-shadow: var(--shadow-pop-sm);
}

.btn--primary {
  color: var(--color-text-inverse);
  background-color: var(--color-primary);
}

.btn--primary:hover {
  background-color: var(--color-primary-strong);
}

/* ── 반응형: 좁은 화면에서 사이드를 보드 아래로 ───────────── */
@media (max-width: 640px) {
  .game__side {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    width: auto;
  }
}
