/* 놀이 화면. 값은 ../../css/tokens.css가 정한다 — 이 파일에 색·글씨 크기를
   직접 적지 않는다. 부모용 칩과 아이콘은 ../../css/controls.css가 메뉴와
   공유한다. */
* { margin: 0; padding: 0; box-sizing: border-box; }

/* 캔버스가 상태바 아래까지 깔리므로(#stage의 inset: 0 + viewport-fit=cover)
   장면이 안전영역을 알아야 한다. env()는 JS가 읽지 못해 변수로 꺼내 둔다 —
   읽는 쪽은 stage.js의 safeTop()이다. */
:root { --safe-top: env(safe-area-inset-top, 0px); }

html, body {
  height: 100%;
  /* iOS 홈 화면 앱은 상태바 뒤까지 깔리면(black-translucent) 페이지 높이를 상태바만큼 짧게
     잡고, 그 아래를 그리지 않는다 — 캔버스를 852로 키워도 793 아래가 빈 띠로 남았다 (#130,
     실기기 실측). 상단 인셋만큼 최소 높이를 늘리면 그려진다. 사파리 탭·가로는 상단 인셋이
     0이라 그대로다. 캔버스·오버레이 높이는 따로 stage.js·아래 :root.standalone이 잡는다. */
  min-height: calc(100% + env(safe-area-inset-top));
  overflow: hidden;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  overscroll-behavior: none;
  background: var(--bg);
  font-family: var(--font-stack);
}

#stage { position: fixed; inset: 0; display: block; }

/* ---- 시작 / 부모 오버레이 ----
   한 요소가 두 얼굴을 가진다. data-state="intro"는 아이가 곧 만질 화면이라
   부모 컨트롤을 접어두고, "paused"는 좌상단 2초 홀드로 부모임이 증명된 뒤라
   전부 펼친다. 증명된 뒤에는 무엇을 크게 둬도 안전하다. 화면이 가려지면 증명이
   만료되어 "intro"로 돌아간다 (main.js의 visibilitychange, #94).

   시트는 반투명이다 (--bg-veil). 불투명한 시트는 시작 전 화면에서 장면을 통째로
   가렸고, 글자를 못 읽는 아이에게 "무슨 놀이인가"의 단서는 그림뿐이다. 캔버스는
   처음부터 계속 돌고 있으므로 가리개만 걷으면 된다. */
#overlay {
  position: fixed;
  inset: 0;
  background: var(--bg-veil);
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 10;
  padding: 24px;
  text-align: center;
  transition: opacity 0.45s ease;

  /* 안내를 한 판으로 묶어 세로를 줄였고 폰 가로는 2열로 나누지만, 글씨 크기는
     기기 설정을 따라 커질 수 있으므로 스크롤은 안전망으로 남긴다.
     justify-content: center는 넘칠 때 위쪽을 잘라내므로 쓰지 않고, 안쪽 블록의
     margin: auto로 가운데를 만든다 — 여유가 있으면 가운데, 없으면 스크롤이다. */
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}
/* 부모가 읽는 화면이다 — 장면은 기척만 남기고 글자에 자리를 준다. */
#overlay[data-state="paused"] { background: var(--bg-veil-strong); }
#overlay.hidden { opacity: 0; pointer-events: none; }

/* 대표 색이 화면 아래에서 한 번 더 번진다. 제목·친구와 같은 색이라 아이가
   "이 색 놀이"로 기억할 표면이 넓어진다.

   알파를 섞으려면 color-mix가 필요한데 사파리 16.2 미만은 그 규칙을 통째로
   버리므로, 대표 색을 그대로 칠하고 불투명도로 낮춘다 (site.css의 카드 테두리와
   같은 방식). position: fixed인 이유는 #overlay가 스크롤 컨테이너여서다 —
   absolute로 두면 안내를 스크롤할 때 빛무리가 같이 밀려 올라간다.

   불투명도의 하한이 아니라 상한을 부모 안내의 가독성이 정한다. 이 빛무리는
   시트와 안내 판 사이에 끼는 층이라, 진할수록 --ink-muted가 얹히는 면이 밝아진다.
   0.12에서는 정원(연둣빛 대표 색)의 안내가 4.20:1로 4.5:1 아래였다. 이 계산도
   play/tests/test_css_tokens.py가 대신 해 준다 — 여기 값을 올리면 그쪽이 먼저
   실패한다.

   세로 반경 40%에 70%에서 투명해지므로 빛무리는 화면 아래 28%에만 산다.
   --bg-veil이 62%에서 마지막 정지점에 닿으므로 그 구간의 시트는 늘 가장 두껍다 —
   테스트가 이 겹침을 그렇게 모델링하고, 그 전제도 함께 검사한다. */
#overlay::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(90% 40% at 50% 100%, var(--accent-band) 0%, transparent 70%);
  opacity: 0.08;
}

/* 홈 화면 앱에서는 inset: 0이 상태바만큼 짧다 — 높이를 lvh로 다시 잡는다 (#130, stage.js의
   viewportHeight와 같은 규칙). lvh를 모르는 옛 WebKit은 이 선언을 버리고 inset: 0에 남는다. */
/* 빛무리(::after)도 fixed; inset: 0이라 같이 짧다 — 빠뜨리면 793에서 빛무리가 끊겨 띠로 보인다. */
:root.standalone #overlay,
:root.standalone #overlay::after {
  bottom: auto;
  height: max(100lvh, 100dvh);
}
/* stage.js가 lvh를 재는 보이지 않는 자. */
.lvh-ruler {
  position: absolute;
  top: 0;
  width: 0;
  height: 100lvh;
  visibility: hidden;
  pointer-events: none;
}

.overlay-inner,
.state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
}
.overlay-inner {
  position: relative; /* 대표 색 빛무리(::after) 위로 올린다 */
  z-index: 1;
  margin: auto 0;
  width: 100%;
  max-width: 460px;
}

#overlay[data-state="intro"] .state-paused,
#overlay[data-state="paused"] .state-intro { display: none; }

/* 칩은 두 상태 모두 아이콘만 남긴다. 크기는 줄이지 않는다 — 부모가 눌러야
   하는 버튼이고, 아이의 오작동은 위치와 무채색으로 막는다. 일시정지 화면에서
   "다른 놀이 고르기"라는 이름은 가운데의 .leave 버튼이 들고 간다. */
#overlay .chip {
  width: var(--tap-parent);
  min-width: 0;
  padding: 0;
}
#overlay .chip-label { display: none; }

.title {
  color: var(--ink);
  font-size: var(--fs-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

/* 메뉴에서 초록 카드를 누르면 초록 제목과 초록 친구가 뜬다 — 아이가 색으로
   놀이를 기억하게 하려는 것이다. 일시정지 화면의 제목은 놀이가 아니라 상태를
   말하므로 이 색을 쓰지 않는다. 그 화면에서 놀이를 말하는 것은 .now의 색 점이다. */
.title-band { color: var(--accent-band); }

.subtitle {
  color: var(--ink-muted);
  font-size: var(--fs-body);
  line-height: 1.6;
  max-width: 34ch;
  word-break: var(--wrap-ko);
}

/* ---- 시작 버튼 = 이 놀이의 친구 ----
   네 놀이가 같은 노란 원을 쓰던 자리다. 카드에서 시작 화면으로 이어지던 색
   연결이 제목 글자 하나에만 걸려 있었다. 이제 친구의 몸이 대표 색이다. */
#startBtn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 0;
  border: none;
  background: none;
  color: var(--ink);
  font-family: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#startBtn:focus-visible { outline: 3px solid var(--accent); outline-offset: 6px; border-radius: var(--radius-panel); }

.start-label {
  font-size: var(--fs-title);
  font-weight: 800;
}

/* 친구의 색은 ../../css/friend.css에 있다 — 메뉴의 책 표지도 같은 친구를
   쓰므로 색을 두 화면이 함께 읽는 파일로 옮겼다. 여기 남는 것은 시작 버튼에서만
   쓰는 크기와 숨쉬는 모션이다. */
.friend {
  display: block;
  width: clamp(150px, 44vw, 200px);
  height: auto;
  /* 숨쉬듯 커졌다 작아진다. 옛 시작 버튼의 box-shadow 파동은 원에만 통하는
     방법이라 얼굴이 생긴 지금은 쓸 수 없다. */
  animation: breathe 2.8s ease-in-out infinite;
}

/* ---- 일시정지 화면 ----
   어떤 놀이 중이었는지 말하지 않던 화면이다. 대표 색 점이 그것을 말한다. */
.now {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 40px;
  padding: 0 18px;
  border-radius: 20px;
  background: var(--bg-raised);
  border: 1px solid var(--border-raised);
  color: var(--ink);
  font-size: var(--fs-label);
  font-weight: 600;
}
.now-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent-band);
}

/* 부모가 이미 증명된 화면의 버튼이므로 크고 명확하게 둔다. 아이 손이 닿는
   상황이 아니다 — 시작 버튼과 달리 시선을 끌 필요도, 숨을 필요도 없다. */
#resumeBtn,
.leave {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border-radius: var(--radius-button);
  font-family: inherit;
  font-weight: 800;
  cursor: pointer;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
#resumeBtn {
  min-height: 72px;
  padding: 0 34px;
  border: none;
  background: var(--accent);
  color: var(--ink-on-accent);
  font-size: var(--fs-title);
}
/* 나가는 길은 계속하기와 나란히, 다만 한 단 낮게. 좌상단의 작은 칩 하나가
   유일한 탈출구이던 것을 고친 자리다. */
.leave {
  min-height: 64px;
  padding: 0 28px;
  background: var(--bg-raised);
  border: 1px solid var(--border-raised);
  color: var(--ink);
  font-size: var(--fs-label);
  font-weight: 600;
}
.leave:active { background: var(--bg-raised-active); }
#resumeBtn:focus-visible,
.leave:focus-visible { outline: 3px solid var(--accent); outline-offset: 4px; }

@keyframes breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}
@media (prefers-reduced-motion: reduce) {
  .friend { animation: none; }
}

/* ---- 부모 안내 ----
   화면의 절반을 쓰던 세 줄이다. 숨기지 않고 한 판으로 묶어 위계만 낮춘다.
   아이콘이 붙은 이유는 부모가 필요한 줄만 골라 읽기 때문이다. */
.tips {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  padding: 18px;
  border-radius: var(--radius-panel);
  background: var(--bg-raised);
  border: 1px solid var(--border-raised);
  color: var(--ink-muted);
  font-size: var(--fs-body);
  line-height: 1.5;
  list-style: none;
  text-align: left;
  word-break: var(--wrap-ko);
}
.tips li { display: flex; align-items: flex-start; gap: 10px; }
.tips .icon { width: 20px; height: 20px; margin-top: 2px; }
.tips b { color: var(--ink); font-weight: 600; }

/* 부모용 숨김 핫스팟 (좌상단 길게 누르기).
   0.18에서 0.4로 올렸다 — 부모는 찾아낼 수 있어야 하고, 아이는 2초를 못 버틴다.
   발견을 어렵게 하는 것으로 막던 것을 시간으로 막는다. */
#parentSpot {
  position: fixed;
  top: 0;
  left: 0;
  width: 72px;
  height: 72px;
  z-index: 6;
  opacity: 0.4;
  display: flex;
  align-items: flex-start;
  padding: calc(10px + env(safe-area-inset-top)) 0 0 calc(14px + env(safe-area-inset-left));
  color: var(--ink);
}
#parentSpot .icon { width: 22px; height: 22px; }

/* 세로가 짧은 화면 — 폰 가로가 대표적이다. 쌓으면 무엇을 줄여도 넘치므로
   나눈다: 왼쪽은 아이가 보는 것(친구·제목), 오른쪽은 부모가 읽는 것(안내 판).
   스크롤은 안전망으로 남지만 여기서 실제로 쓸 일이 없어야 한다. */
@media (max-height: 480px) {
  #overlay {
    /* 왼쪽은 칩이 앉는 자리라 비운다 — 칩은 fixed라 흐름에 없다. */
    padding: 14px 20px calc(14px + env(safe-area-inset-bottom));
    padding-left: calc(var(--tap-parent) + 28px + env(safe-area-inset-left));
    /* 가로에서 iOS는 노치가 어느 쪽에 있든 양쪽 인셋을 같게 준다 — 오른쪽을 비우지
       않으면 노치가 오른쪽일 때 안내 판 끝이 노치 아래에 깔린다 (#122). */
    padding-right: calc(20px + env(safe-area-inset-right));
  }
  .overlay-inner {
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 20px;
    max-width: 820px;
  }
  .state {
    flex: 1 1 0;
    min-width: 0;
    gap: 10px;
  }
  .tips {
    flex: 1 1 0;
    min-width: 0;
    padding: 14px;
    gap: 10px;
    font-size: var(--fs-label);
  }
  .title { font-size: clamp(24px, 7vh, 34px); }
  .friend { width: clamp(104px, 34vh, 150px); }
  .start-label { font-size: var(--fs-label); }
  .subtitle { font-size: var(--fs-label); line-height: 1.4; }
  #resumeBtn { min-height: 60px; font-size: var(--fs-label); }
  .leave { min-height: 56px; }
  .now { height: 34px; padding: 0 14px; }
}

/* ---- 안전영역 디버그 (`?debug=1`, main.js, #128) ----
   .inset-probe는 보이지 않는 자다 — env()는 JS가 읽지 못하므로 padding으로 받아 읽는다.
   표시는 아이 손이 닿아도 아무것도 하지 않게 pointer-events를 끈다. */
.inset-probe {
  position: fixed;
  visibility: hidden;
  pointer-events: none;
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
    env(safe-area-inset-bottom) env(safe-area-inset-left);
}
#insetDebug {
  position: fixed;
  left: 50%;
  top: calc(8px + env(safe-area-inset-top));
  transform: translateX(-50%);
  z-index: 20;
  /* 두 줄로 끊는다(main.js의 줄바꿈) — 줄바꿈이 늘면 제목을 가린다. */
  white-space: pre;
  padding: 6px 12px;
  border-radius: 12px;
  background: var(--bg-raised-active);
  color: var(--ink);
  font-size: 13px; /* 디버그 전용 — 부모·아이가 읽는 글자가 아니라 토큰 하한을 따르지 않는다 */
  line-height: 1.4;
  text-align: center;
  pointer-events: none;
}
