/* ==========================================================================
   games.css — 게임별 스타일
   섹션 순서는 js/core/registry.js 의 카테고리 순서를 따른다.
   ========================================================================== */

[hidden] { display: none !important; }

/* ==========================================================================
   공통: 오버레이 / 진행바 / 로딩 / 캔버스 스테이지
   ========================================================================== */

.overlay-host { position: absolute; inset: 0; pointer-events: none; z-index: 5; }
.overlay-host[data-on] { pointer-events: auto; }

.game-overlay {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  /* 칸 폭을 부모에 맞춘다 — 기본(auto)이면 닉네임 입력칸의 기본 폭 때문에 작은 폰(360px)에서 상자가
     화면보다 넓어져 브라우저가 페이지 전체를 축소해 버린다 */
  grid-template-columns: minmax(0, 1fr);
  padding: 18px;
  touch-action: manipulation;         /* 두 번 탭 확대 방지 (아이폰) */
  background: color-mix(in oklab, var(--bg) 78%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-radius: var(--r-md);
  animation: ov-in .18s ease;
}
@keyframes ov-in { from { opacity: 0; } }

.ov-box {
  width: min(420px, 100%);
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  padding: 24px 22px;
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
}
.ov-icon { font-size: 2.3rem; line-height: 1; }
.ov-title { font-size: 1.45rem; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.ov-sub { font-size: .88rem; color: var(--text-dim); line-height: 1.55; word-break: keep-all; }

.ov-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
  gap: 7px;
  width: 100%;
  margin-top: 5px;
}
.ov-stat {
  display: flex; flex-direction: column; gap: 1px;
  padding: 8px 6px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
}
.ov-stat-k { font-size: .68rem; font-weight: 700; color: var(--text-mute); letter-spacing: .03em; }
.ov-stat-v { font-size: .98rem; font-weight: 750; font-variant-numeric: tabular-nums; }
.ov-stat[data-tone="good"] .ov-stat-v { color: var(--good); }
.ov-stat[data-tone="bad"] .ov-stat-v { color: var(--bad); }

.ov-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-top: 8px; }

/* 랭킹 등록 (닉네임) */
.ov-register { width: 100%; margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.ov-nick-row { display: flex; gap: 8px; }
.ov-nick {
  flex: 1; min-width: 0;
  width: 0;                           /* 기본 폭(글자 20칸)을 버리고 남은 자리만 쓴다 */
  height: 42px; padding: 0 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-2);
  font-size: 16px;                    /* 16px 보다 작으면 아이폰이 입력칸을 누를 때 화면을 확대한다 */
  outline: none;
}
.ov-nick:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.ov-nick:disabled { opacity: .6; }
.ov-register .btn { height: 42px; min-height: 42px; }
.ov-nick-msg { min-height: 1.2em; font-size: .8rem; color: var(--text-mute); text-align: left; }
.ov-nick-msg[data-tone="bad"] { color: var(--bad); }
.ov-nick-msg[data-tone="good"] { color: var(--good); }
/* 자동 등록 방지 확인 칸 — 평소엔 비어 있고, 의심스러울 때만 Cloudflare 확인 칸이 뜬다 */
.ov-bot { max-width: 100%; overflow: hidden; }
.ov-bot:empty { display: none; }

.game-overlay[data-kind="over"] .ov-box { border-color: color-mix(in oklab, var(--accent) 36%, transparent); }

/* 결과 화면이 막 떴을 때는 버튼이 눌리지 않는다 (_shared.js OVER_LOCK_MS) */
.game-overlay button { transition: opacity .2s; }
.game-overlay[data-locked] button { pointer-events: none; opacity: .45; }
/* 닉네임 칸도 — 연타하던 손가락이 칸을 눌러 휴대폰 키보드가 튀어 오르지 않게 */
.game-overlay[data-locked] input { pointer-events: none; }

/* 진행바 */
.pbar {
  height: 7px; width: 100%;
  border-radius: var(--r-pill);
  /* 판 위에 놓이는 막대다 — 판 바탕과 구분되도록 칸 색을 쓰고 테두리를 한 줄 두른다 */
  background: var(--field-cell);
  box-shadow: inset 0 0 0 1px var(--line);
  overflow: hidden;
}
.pbar-fill {
  height: 100%; width: 0%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width .08s linear;
}
.pbar[data-tone="bad"] .pbar-fill { background: linear-gradient(90deg, var(--warn), var(--bad)); }

/* 로딩 */
/* 앱이 뜨기 전 자리 (배포 HTML 에 미리 들어 있다 — tools/site-pages.mjs). 맨 아래 소개 글이 잠깐 위로 올라와 보이지 않게 높게 */
.game-loading.is-boot { min-height: min(72vh, 680px); }
.game-loading {
  display: grid; place-items: center; gap: 12px;
  min-height: 300px;
  color: var(--text-mute); font-size: .86rem;
}
.spinner {
  width: 26px; height: 26px;
  border: 2.5px solid var(--surface-3);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* 캔버스 스테이지
   래퍼의 높이는 aspect-ratio 로 "가로에서만" 결정된다.
   캔버스를 absolute 로 띄워 래퍼 높이에 영향을 주지 못하게 하는 것이 핵심이다.
   (둘이 서로의 크기를 참조하면 캔버스가 기본 300×150 에 갇힌다) */
.act-wrap { position: relative; display: flex; flex-direction: column; gap: 10px; }
.stage-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: var(--aspect, 3 / 2);
  max-height: min(62vh, 560px);
  /* 높이가 상한에 걸리면 폭도 비율대로 줄인다 — 안 그러면 캔버스 양옆에 빈 띠가 생겨
     테두리가 실제 판 경계보다 바깥에 그려진다 (±6px = 위아래·좌우 테두리 3px 씩) */
  max-width: calc((min(62vh, 560px) - 6px) * var(--aspect-num, 1.5) + 6px);
  margin-inline: auto;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--field-bg);
}
/* 벽돌깨기: 아래는 벽이 아니라 공을 놓치는 선 */
.stage-wrap.is-open-bottom { border-bottom: 3px dashed var(--bad); }
.stage-canvas {
  position: absolute;
  inset: 0;
  margin: auto;
  display: block;
  touch-action: none;
}

/* 모바일 화면 버튼 */
.touch-pad {
  display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;
}
.touch-btn {
  appearance: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  min-width: 68px; height: 52px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text);
  font-size: 1.1rem; font-weight: 700;
  cursor: pointer;
  user-select: none; -webkit-user-select: none;
  touch-action: none;
}
.touch-btn.is-wide { min-width: 150px; }
.touch-btn.is-on { background: var(--accent); color: var(--accent-ink); border-color: transparent; }

/* ==========================================================================
   클릭 많이하기
   ========================================================================== */

.cs-wrap { position: relative; display: flex; flex-direction: column; gap: 12px; }
/* 키보드 연타 — 휴대폰에서 화면 키보드를 여는 보이지 않는 입력칸 (16px: 아이폰이 확대하지 않게) */
.cs-sink {
  position: absolute; left: 50%; top: 50%;
  width: 1px; height: 1px;
  padding: 0; border: 0;
  opacity: 0;
  font-size: 16px;
  caret-color: transparent;
  pointer-events: none;
}

.cs-pad {
  appearance: none;
  position: relative;
  width: 100%;
  min-height: 320px;
  display: grid; place-items: center;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  color: var(--text);
  cursor: pointer;
  user-select: none; -webkit-user-select: none;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: border-color .15s, background .15s;
}
.cs-pad:hover { border-color: color-mix(in oklab, var(--accent) 50%, transparent); }
.cs-wrap[data-state="running"] .cs-pad {
  border-style: solid;
  border-color: var(--accent);
  cursor: crosshair;
}
.cs-wrap[data-state="done"] .cs-pad { cursor: default; border-color: var(--good); }
/* 키보드 연타: 패드는 표시만 한다 */
.cs-wrap[data-input="keyboard"] .cs-pad,
.cs-wrap[data-input="keyboard"][data-state="running"] .cs-pad { cursor: default; }

.cs-pad.is-hit { animation: cs-pulse .09s ease-out; }
@keyframes cs-pulse { 50% { transform: scale(.994); background-color: var(--surface-3); } }

.cs-pad-inner { display: flex; flex-direction: column; align-items: center; gap: 4px; pointer-events: none; }
.cs-count {
  font-size: clamp(3.4rem, 12vw, 6rem);
  font-weight: 800; line-height: 1;
  letter-spacing: -.05em;
  font-variant-numeric: tabular-nums;
}
.cs-live { font-size: 1.1rem; font-weight: 700; color: var(--accent); min-height: 1.5em; }
.cs-hint { font-size: .9rem; color: var(--text-mute); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   반응속도 테스트
   ========================================================================== */

.rt-wrap { position: relative; display: flex; flex-direction: column; gap: 12px; }

.rt-pad {
  appearance: none;
  width: 100%;
  min-height: 330px;
  display: grid; place-items: center;
  border-radius: var(--r-lg);
  cursor: pointer;
  user-select: none; -webkit-user-select: none;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  color: #fff;
  /* 색 전환은 즉시여야 한다 — transition 을 주면 "바뀐 순간" 이 흐려진다 */
  transition: none;
}
.rt-pad[data-phase="intro"]  { background: var(--surface-3); color: var(--text); }
.rt-pad[data-phase="wait"]   { background: #d5372f; }
.rt-pad[data-phase="arming"] { background: #d5372f; }
.rt-pad[data-phase="go"]     { background: #12b76a; }
.rt-pad[data-phase="foul"]   { background: #2e5cc5; }
.rt-pad[data-phase="result"] { background: var(--surface-3); color: var(--text); }
.rt-pad[data-phase="done"]   { background: var(--surface-3); color: var(--text); }

.rt-pad-inner { display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none; }
.rt-icon { font-size: 2.6rem; line-height: 1; }
.rt-big {
  font-size: clamp(2rem, 7vw, 3.2rem);
  font-weight: 800; line-height: 1; letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}
.rt-sub { font-size: .92rem; opacity: .88; text-align: center; padding: 0 16px; }

.rt-dots { display: flex; gap: 7px; justify-content: center; flex-wrap: wrap; }
.rt-dot {
  min-width: 52px; padding: 5px 10px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  color: var(--text-mute);
  font-size: .82rem; font-weight: 700; text-align: center;
  font-variant-numeric: tabular-nums;
}
.rt-dot[data-state="done"] { background: var(--good-soft); color: var(--good); border-color: color-mix(in oklab, var(--good) 34%, transparent); }
.rt-dot[data-state="active"] { border-color: var(--accent); color: var(--accent); }

/* ==========================================================================
   에임 트레이너
   ========================================================================== */

.aim-wrap { position: relative; display: flex; flex-direction: column; gap: 12px; }

.aim-area {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 280px;
  /* 넓은 화면에서 16:9 를 그대로 두면 판만 600px 가까이 되어 스크롤 없이는 아래가 잘린다.
     표적 자리는 판 크기에 대한 비율이라(placeTarget) 높이를 줄여도 규칙은 그대로다 */
  max-height: min(56vh, 520px);
  border-radius: var(--r-lg);
  background:
    linear-gradient(var(--line) 1px, transparent 1px) 0 0 / 100% 40px,
    linear-gradient(90deg, var(--line) 1px, transparent 1px) 0 0 / 40px 100%,
    var(--field-bg);
  overflow: hidden;
  cursor: crosshair;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.aim-area.is-miss { animation: aim-miss .18s ease; }
@keyframes aim-miss { 50% { box-shadow: inset 0 0 0 3px var(--bad); } }

.aim-target {
  position: absolute;
  left: 0; top: 0;
  width: calc(var(--r, 20px) * 2);
  height: calc(var(--r, 20px) * 2);
  transform: translate(calc(var(--x, 0px) - var(--r, 20px)), calc(var(--y, 0px) - var(--r, 20px)));
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #ff9aa4, var(--bad) 62%);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--bad) 30%, transparent), 0 6px 18px -6px rgba(0,0,0,.6);
  opacity: 0;
  pointer-events: none;
}
.aim-target[data-on] { opacity: 1; animation: aim-pop .09s ease-out; }
@keyframes aim-pop { from { transform: translate(calc(var(--x) - var(--r)), calc(var(--y) - var(--r))) scale(.6); } }

.aim-cross {
  position: absolute; left: 0; top: 0;
  width: 18px; height: 18px;
  transform: translate(calc(var(--x, -100px) - 9px), calc(var(--y, -100px) - 9px));
  pointer-events: none;
  opacity: .5;
  background:
    linear-gradient(var(--accent), var(--accent)) 8px 0 / 2px 100% no-repeat,
    linear-gradient(var(--accent), var(--accent)) 0 8px / 100% 2px no-repeat;
}
@media (hover: none) { .aim-cross { display: none; } }

/* ==========================================================================
   두더지 잡기
   ========================================================================== */

.wm-wrap { position: relative; display: flex; flex-direction: column; gap: 12px; }

.wm-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  max-width: 480px;
  margin-inline: auto;
  width: 100%;
  padding: 14px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}

/* 구멍: 흙더미(원) 안의 어두운 굴. 두더지·폭탄은 굴 뒤에서 솟아오른다 */
.wm-hole {
  --soil: #7a5634;
  --soil-dark: #4a3220;
  appearance: none;
  position: relative;
  aspect-ratio: 1;
  border: 0;
  border-radius: 50%;
  background: radial-gradient(ellipse 40% 15% at 50% 70%, #150d07 0 92%, transparent 97%), var(--soil);
  box-shadow: inset 0 -6px 0 var(--soil-dark);
  cursor: pointer;
  overflow: hidden;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
}
/* 올라와 있는 동안에는 색 표시가 없다 — 모양만 보고 판단 (whack-a-mole.js B8) */

/* 굴 앞턱 — 내려가 있는 두더지를 가린다 */
.wm-dirt {
  position: absolute; inset: auto 0 0 0; height: 30%;
  background: var(--soil);
  box-shadow: inset 0 -6px 0 var(--soil-dark);
  border-radius: 50% 50% 0 0 / 30% 30% 0 0;
  pointer-events: none;
  z-index: 2;
}

/* 두더지 몸통 (CSS 도형) — 솟아오르면 얼굴 전체가 앞턱 위로 나온다 */
.wm-mole {
  position: absolute;
  left: 50%; bottom: 22%;
  width: 62%; height: 68%;
  z-index: 1;
  border-radius: 50% 50% 42% 42% / 56% 56% 44% 44%;
  background: radial-gradient(circle at 50% 26%, #a87650, #5e3b22 74%);
  box-shadow: inset 0 -4px 0 rgba(0, 0, 0, .18);
  transform: translate(-50%, 115%);
  /* 내려갈 때: 처음엔 천천히, 끝에 빨리. 다 숨을 때까지 누르면 잡힌다 (whack-a-mole.js B9) */
  transition: transform var(--wm-down, .17s) cubic-bezier(.5, 0, 1, 1);
  pointer-events: none;
}
.wm-hole[data-kind] .wm-mole {
  transform: translate(-50%, 0);
  transition: transform .12s cubic-bezier(.2,.9,.3,1);
}

.wm-eye {
  position: absolute; top: 22%; left: 25%;
  width: 14%; aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff 0 18%, #151515 24%);
}
.wm-eye + .wm-eye { left: auto; right: 25%; }
/* 주둥이 */
.wm-mole::after {
  content: "";
  position: absolute; left: 50%; top: 40%;
  width: 50%; height: 28%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: #e0b88f;
}
.wm-nose {
  position: absolute; left: 50%; top: 41%;
  width: 22%; height: 12%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: #ff7f96;
  z-index: 1;
}

/* 폭탄 (같은 요소를 다르게 그린다).
   모양은 data-look 으로 고른다 — data-kind(올라옴)는 내려가기 시작하는 순간 지워지지만
   data-look 은 남아 있어서, 내려가는 동안에도 폭탄은 폭탄으로 보인다. */
.wm-hole[data-look="bomb"] .wm-mole {
  width: 54%; height: 54%;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #707070, #111 62%);
  box-shadow: none;
}
.wm-hole[data-look="bomb"] .wm-eye,
.wm-hole[data-look="bomb"] .wm-nose { display: none; }
.wm-hole[data-look="bomb"] .wm-mole::before {   /* 심지 */
  content: "";
  position: absolute; left: 58%; top: -14%;
  width: 9%; height: 22%;
  border-radius: 3px;
  background: #b08a52;
  transform: rotate(28deg);
}
.wm-hole[data-look="bomb"] .wm-mole::after {    /* 불꽃 */
  left: 76%; top: -26%;
  width: 24%; height: 24%;
  transform: none;
  background: radial-gradient(circle, #fff6c2 0 25%, #ffb020 45%, rgba(255, 90, 40, .9) 60%, transparent 72%);
}

/* 누른 결과만 색으로 — 맞힘 초록 · 폭탄 빨강 · 헛손질 주황. 잠깐 켜졌다가 사라진다 */
.wm-hole.is-hit  { animation: wm-hit .35s ease-out; }
.wm-hole.is-miss { animation: wm-miss .35s ease-out; }
.wm-hole.is-boom { animation: wm-boom .45s ease-out; }
@keyframes wm-hit {
  0%, 50% { box-shadow: inset 0 -6px 0 var(--soil-dark), 0 0 0 5px var(--good); }
  20% { transform: scale(.95); }
}
@keyframes wm-miss {
  0%, 50% { box-shadow: inset 0 -6px 0 var(--soil-dark), 0 0 0 5px var(--warn); }
}
@keyframes wm-boom {
  0%, 55% { box-shadow: inset 0 -6px 0 var(--soil-dark), 0 0 0 5px var(--bad); }
  20% { transform: scale(1.05); }
}

/* ==========================================================================
   타이핑 속도
   ========================================================================== */

.ty-wrap { position: relative; display: flex; flex-direction: column; gap: 12px; }

.ty-stream {
  min-height: 132px;
  max-height: 132px;
  overflow: hidden;
  padding: 16px 18px;
  border-radius: var(--r-md);
  background: var(--field-bg);
  font-size: 1.24rem;
  line-height: 1.85;
  letter-spacing: .01em;
  color: var(--text-mute);
  word-break: keep-all;
}
.ty-word { display: inline-block; padding: 0 1px; border-radius: 4px; }
.ty-word[data-state="ok"]  { color: var(--good); }
.ty-word[data-state="bad"] { color: var(--bad); text-decoration: underline wavy color-mix(in oklab, var(--bad) 60%, transparent); text-underline-offset: 4px; }
.ty-word[data-state="now"] { background: var(--accent-soft); color: var(--text); box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 34%, transparent); }
.ty-ch[data-st="hit"]     { color: var(--good); }
.ty-ch[data-st="miss"]    { color: var(--bad); background: var(--bad-soft); border-radius: 3px; }
.ty-ch[data-st="extra"]   { color: var(--bad); opacity: .65; }
.ty-ch[data-st="pending"] { color: var(--text); }

.ty-input-row { display: flex; }
.ty-input {
  width: 100%;
  padding: 13px 16px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: 1.05rem;
  outline: none;
  transition: border-color .14s, box-shadow .14s;
}
.ty-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.ty-wrap[data-state="done"] .ty-input { opacity: .5; }
.ty-caption { font-size: .82rem; color: var(--text-mute); text-align: center; min-height: 1.2em; }

/* ==========================================================================
   숫자 기억력
   ========================================================================== */

.nm-wrap {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  min-height: 320px;
  justify-content: center;
  padding: 24px 12px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}

.nm-lives { display: flex; gap: 6px; }
.nm-life { font-size: 1.2rem; line-height: 1; color: var(--bad); }
.nm-life[data-on="0"] { color: var(--text-mute); opacity: .5; }

/* 선택·복사 불가 — 긁어서 붙여넣는 치트 방지 (number-memory.js B5) */
.nm-display {
  user-select: none; -webkit-user-select: none;
  font-weight: 800;
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  text-align: center;
  line-height: 1.15;
  word-break: break-all;
  max-width: 100%;
  min-height: 1.2em;
}
.nm-display[data-size="lg"] { font-size: clamp(2.6rem, 9vw, 4.2rem); }
.nm-display[data-size="md"] { font-size: clamp(2rem, 6.5vw, 3rem); }
.nm-display[data-size="sm"] { font-size: clamp(1.4rem, 4.6vw, 2.1rem); }
.nm-display[data-size="xs"] { font-size: clamp(1.1rem, 3.6vw, 1.6rem); }
.nm-display[data-flash="ok"]  { color: var(--good); }
.nm-display[data-flash="bad"] { color: var(--bad); }

.nm-bar { max-width: 320px; }
.nm-input-row { display: flex; gap: 8px; width: min(340px, 100%); transition: opacity .15s; }
/* 숫자를 보여 주는 동안 — 입력칸은 그대로 두고(휴대폰 키보드가 닫히지 않게) 흐리게만 */
.nm-input-row[data-ready="0"] { opacity: .35; }
.nm-input-row[hidden] { display: none; }
.nm-input {
  flex: 1; min-width: 0;
  padding: 12px 16px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--field-cell);
  font-size: 1.3rem; text-align: center;
  letter-spacing: .1em;
  outline: none;
}
.nm-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ==========================================================================
   순서 기억력
   ========================================================================== */

.sq-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; }
.sq-banner {
  font-size: .95rem; font-weight: 700; color: var(--text-dim);
  min-height: 1.5em;
}
.sq-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  gap: 10px;
  width: min(420px, 100%);
  padding: 12px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
/* 칸 바탕은 --field-cell: 판 바탕(--field-bg)과 확실히 구분되는 색 (밝은 테마 포함) */
.sq-tile {
  appearance: none;
  aspect-ratio: 1;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--field-cell);
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: background .07s, box-shadow .07s, transform .07s;
}
.sq-wrap[data-state="playing"] .sq-tile { cursor: default; }
.sq-tile:hover { background: var(--surface-3); }
.sq-tile[data-lit] {
  background: var(--accent);
  box-shadow: 0 0 22px -4px var(--accent);
  transform: scale(1.03);
}
.sq-tile[data-wrong] {
  background: var(--bad);
  box-shadow: 0 0 22px -4px var(--bad);
}
.sq-wrap[data-state="ok"] .sq-banner { color: var(--good); }

/* ==========================================================================
   카드 짝 맞추기
   ========================================================================== */

.mm-wrap { position: relative; display: flex; flex-direction: column; gap: 12px; }
/* 카드 폭(--card-w)은 memory-match.js fitBoard() 가 화면 높이에 맞춰 정한다 */
.mm-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols), var(--card-w, 1fr));
  justify-content: center;
  gap: 8px;
  margin-inline: auto;
  padding: 12px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.mm-card {
  appearance: none;
  width: var(--card-w, auto);
  aspect-ratio: 1;
  border: 0; padding: 0; background: none;
  perspective: 700px;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.mm-card[disabled] { cursor: default; }
.mm-inner {
  position: relative;
  display: block;
  width: 100%; height: 100%;
  transform-style: preserve-3d;
  transition: transform .3s cubic-bezier(.2,.8,.3,1);
}
.mm-card[data-state="up"] .mm-inner,
.mm-card[data-state="done"] .mm-inner { transform: rotateY(180deg); }

.mm-face, .mm-back {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border: 1px solid var(--line);
}
.mm-back {
  background: linear-gradient(140deg, var(--accent), var(--accent-2));
  border-color: transparent;
}
.mm-back::after {
  content: "";
  width: 42%; height: 42%;
  border-radius: 50%;
  border: 2.5px dashed rgba(255,255,255,.5);
}
.mm-face {
  background: var(--surface-2);
  transform: rotateY(180deg);
  font-size: calc(var(--card-w, 80px) * .46);
  line-height: 1;
}
.mm-card[data-state="done"] .mm-face {
  background: var(--good-soft);
  border-color: color-mix(in oklab, var(--good) 40%, transparent);
  opacity: .72;
}

/* ==========================================================================
   지뢰찾기
   ========================================================================== */

.ms-wrap { position: relative; }
.ms-scroll {
  overflow: auto;
  padding: 4px;
  border-radius: var(--r-md);
  -webkit-overflow-scrolling: touch;
}
.ms-board {
  /* 닫힌 칸: 판 바탕보다 확실히 진하게(밝은 테마) / 밝게(어두운 테마) — 연 칸은 --surface */
  --ms-hidden: #2a3a62;
  display: grid;
  grid-template-columns: repeat(var(--cols), var(--cell, 30px));
  gap: var(--ms-gap, 2px);
  margin-inline: auto;
  width: max-content;
  padding: var(--ms-pad, 8px);
  border-radius: var(--r-md);
  background: var(--field-bg);
  /* 칸 크기·틈은 minesweeper.js 가 실제 폭을 재서 넣는다 (판이 화면 폭에 다 들어오게). 아래는 그 전의 기본값 */
  --cell: clamp(12px, calc((min(100vw, var(--shell)) - 90px) / var(--cols)), 34px);
}
.ms-cell {
  appearance: none;
  width: var(--cell); height: var(--cell);
  display: grid; place-items: center;
  border: 0;
  border-radius: 4px;
  background: var(--ms-hidden);
  color: var(--text);
  font-size: calc(var(--cell) * 0.6);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  cursor: pointer;
  user-select: none; -webkit-user-select: none;
  /* 판은 화면 폭에 맞춰 작아진다 — 칸이 작으면 두 손가락으로 확대해서 누른다(핀치 허용, 두 번 탭 확대는 막음).
     밀거나 확대하는 동안에는 칸이 열리지 않는다 (minesweeper.js — 10px 넘게 움직이거나 pointercancel) */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  transition: background .1s;
}
:root[data-theme="light"] .ms-board { --ms-hidden: #c3cde6; }
.ms-cell:hover { background: color-mix(in oklab, var(--ms-hidden) 70%, var(--accent) 30%); }
.ms-cell[data-state="open"] { background: var(--surface); cursor: default; }
.ms-cell[data-state="open"]:hover { background: var(--surface); }
.ms-cell[data-state="flag"] { background: var(--warn-soft); }
.ms-cell[data-state="mine"] { background: var(--surface); }
.ms-cell[data-state="boom"] { background: var(--bad); }
.ms-cell[data-state="wrongflag"] { background: var(--bad-soft); }
.ms-cell[disabled] { cursor: default; }

.ms-cell[data-n="1"] { color: #4d8dff; }
.ms-cell[data-n="2"] { color: #22c07a; }
.ms-cell[data-n="3"] { color: #ff6b7a; }
.ms-cell[data-n="4"] { color: #a479ff; }
.ms-cell[data-n="5"] { color: #ff9f43; }
.ms-cell[data-n="6"] { color: #2ec5c5; }
.ms-cell[data-n="7"] { color: var(--text); }
.ms-cell[data-n="8"] { color: var(--text-mute); }


/* ==========================================================================
   스도쿠
   ========================================================================== */

.sd-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; }

/* 행 높이도 고정 분할 — auto 행이면 숫자가 없는 행이 줄어들었다가
   숫자를 넣는 순간 늘어나며 판 전체의 선이 움직인다 */
.sd-grid {
  display: grid;
  grid-template-columns: repeat(9, minmax(0, 1fr));
  grid-template-rows: repeat(9, minmax(0, 1fr));
  width: min(480px, 100%);
  aspect-ratio: 1;
  background: var(--line);
  border-radius: 6px;
  overflow: hidden;
  gap: 1px;
}
.sd-cell {
  position: relative;
  display: grid; place-items: center;
  background: var(--surface);
  cursor: pointer;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background .1s;
}
/* 3×3 박스 경계 굵게 */
.sd-cell[data-edge*="t"] { box-shadow: inset 0 2px 0 var(--text-mute); }
.sd-cell[data-edge*="l"] { box-shadow: inset 2px 0 0 var(--text-mute); }
.sd-cell[data-edge="tl"] { box-shadow: inset 0 2px 0 var(--text-mute), inset 2px 0 0 var(--text-mute); }

.sd-val {
  font-size: clamp(1rem, 4.2vw, 1.5rem);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--accent);
}
.sd-cell[data-given="1"] .sd-val { color: var(--text); font-weight: 800; }
.sd-cell[data-wrong="1"] .sd-val { color: var(--bad); }
.sd-cell[data-wrong="1"] { background: var(--bad-soft); }

.sd-cell[data-peer="1"] { background: var(--surface-2); }
.sd-cell[data-same="1"] { background: color-mix(in oklab, var(--accent) 16%, var(--surface)); }
.sd-cell[data-sel="1"]  { background: var(--accent-soft); box-shadow: inset 0 0 0 2px var(--accent); }
.sd-cell[data-sel="1"][data-edge] { box-shadow: inset 0 0 0 2px var(--accent); }

.sd-notes {
  position: absolute; inset: 2px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  pointer-events: none;
}
.sd-notes i {
  display: grid; place-items: center;
  font-style: normal;
  font-size: clamp(.5rem, 1.5vw, .62rem);
  font-weight: 700;
  color: var(--text-mute);
  line-height: 1;
}

/* 오답 흔들림은 숫자만 — 칸째 흔들면 칸에 그려진 3×3 굵은 선까지 같이 흔들린다 */
.sd-cell.is-shake .sd-val { animation: sd-shake .28s ease; }
@keyframes sd-shake {
  25% { transform: translateX(-3px); }
  50% { transform: translateX(3px); }
  75% { transform: translateX(-2px); }
}

.sd-tools {
  display: flex; gap: 7px;
  width: min(480px, 100%);
  margin-bottom: -4px;
}
.sd-tool { flex: 1; }
.sd-tool.is-on { background: var(--warn-soft); color: var(--warn); border-color: color-mix(in oklab, var(--warn) 45%, transparent); }

.sd-pad {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 7px;
  width: min(480px, 100%);
}
.sd-key {
  appearance: none;
  position: relative;
  aspect-ratio: 1;
  max-height: 58px;
  display: grid; place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text);
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: background .12s, opacity .12s;
}
.sd-key:hover { background: var(--surface-3); }
.sd-key[data-done="1"] { opacity: .35; }
.sd-key-n { font-size: 1.3rem; font-weight: 700; line-height: 1; }
.sd-key-left {
  position: absolute; right: 5px; bottom: 3px;
  font-size: .6rem; font-weight: 700; color: var(--text-mute);
}
.sd-key-erase { font-size: 1.1rem; }
.sd-wrap[data-note="1"] .sd-key-n { color: var(--warn); }

/* ==========================================================================
   2048
   ========================================================================== */

.tw-wrap { position: relative; display: flex; justify-content: center; }
.tw-board {
  position: relative;
  width: min(480px, 100%);
  aspect-ratio: 1;
  padding: var(--pad, 10px);
  border-radius: var(--r-lg);
  background: var(--surface-3);
  --pad: 10px;
  --gap: 8px;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.tw-cells, .tw-tiles {
  position: absolute;
  inset: var(--pad);
}
.tw-cells {
  display: grid;
  grid-template-columns: repeat(var(--n), 1fr);
  grid-template-rows: repeat(var(--n), 1fr);
  gap: var(--gap);
}
.tw-cell { border-radius: var(--r-sm); background: color-mix(in oklab, var(--bg) 42%, transparent); }

.tw-tile {
  position: absolute;
  left: 0; top: 0;
  width: calc((100% - (var(--n) - 1) * var(--gap)) / var(--n));
  height: calc((100% - (var(--n) - 1) * var(--gap)) / var(--n));
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  font-weight: 800;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  transform: translate(
    calc(var(--c) * (100% + var(--gap))),
    calc(var(--r) * (100% + var(--gap)))
  );
  transition: transform .13s cubic-bezier(.25,.9,.35,1);
  background: var(--surface-2);
  color: var(--text);
  font-size: clamp(1rem, 5.2vw, 1.9rem);
}
.tw-tile[data-dead] { z-index: 1; }
.tw-tile[data-new="1"]    { animation: tw-appear .18s cubic-bezier(.2,1.2,.4,1); }
.tw-tile[data-merged="1"] { animation: tw-pop .2s cubic-bezier(.2,1.3,.4,1); z-index: 3; }
@keyframes tw-appear { from { opacity: 0; } }
@keyframes tw-pop { 45% { filter: brightness(1.25); } }

/* 값별 색 — 2048 원작 팔레트를 다크/라이트 양쪽에 맞게 재구성 */
/* 2 와 4 는 색 차이가 가장 작아 헷갈리기 쉽다 — 빈칸과도, 서로도 구분되도록 벌려 둔다 */
.tw-tile[data-v="2"]    { background: #35426b; }
.tw-tile[data-v="4"]    { background: #43569c; }
.tw-tile[data-v="8"]    { background: #3f63c9; color: #fff; }
.tw-tile[data-v="16"]   { background: #4a7ae0; color: #fff; }
.tw-tile[data-v="32"]   { background: #6a5ce0; color: #fff; }
.tw-tile[data-v="64"]   { background: #8b4fe0; color: #fff; }
.tw-tile[data-v="128"]  { background: #c04fc0; color: #fff; font-size: clamp(.9rem, 4.6vw, 1.7rem); }
.tw-tile[data-v="256"]  { background: #e0527f; color: #fff; font-size: clamp(.9rem, 4.6vw, 1.7rem); }
.tw-tile[data-v="512"]  { background: #e5733d; color: #fff; font-size: clamp(.9rem, 4.6vw, 1.7rem); }
.tw-tile[data-v="1024"] { background: #e0a021; color: #1a1a1a; font-size: clamp(.75rem, 3.8vw, 1.4rem); }
.tw-tile[data-v="2048"] { background: #ffcc4d; color: #1a1a1a; font-size: clamp(.75rem, 3.8vw, 1.4rem); box-shadow: 0 0 24px -4px #ffcc4d; }
.tw-tile[data-v="4096"], .tw-tile[data-v="8192"],
.tw-tile[data-v="16384"], .tw-tile[data-v="32768"], .tw-tile[data-v="65536"] {
  background: #12b76a; color: #fff;
  font-size: clamp(.7rem, 3.2vw, 1.2rem);
  box-shadow: 0 0 24px -4px #12b76a;
}
/* 밝은 테마에서는 낮은 숫자 타일이 빈칸과 색이 비슷해진다 — 두 타일을 벌리고, 모든 타일에 실선 테두리를 둘러 경계를 만든다 */
:root[data-theme="light"] .tw-tile { box-shadow: inset 0 0 0 1px rgba(20, 30, 60, .12); }
:root[data-theme="light"] .tw-tile[data-v="2"] { background: #d6def2; }
:root[data-theme="light"] .tw-tile[data-v="4"] { background: #adc0e6; }

/* ==========================================================================
   숫자 슬라이드
   ========================================================================== */

.sp-wrap { position: relative; display: flex; justify-content: center; }
.sp-board {
  position: relative;
  width: min(440px, 100%);
  aspect-ratio: 1;
  padding: var(--pad, 8px);
  border-radius: var(--r-lg);
  background: var(--surface-3);
  --pad: 8px;
  --gap: 6px;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.sp-tile {
  position: absolute;
  appearance: none;
  border: 0;
  left: var(--pad); top: var(--pad);
  width: calc((100% - var(--pad) * 2 - (var(--n) - 1) * var(--gap)) / var(--n));
  height: calc((100% - var(--pad) * 2 - (var(--n) - 1) * var(--gap)) / var(--n));
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text);
  font-size: clamp(.95rem, 4.5vw, 1.7rem);
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transform: translate(
    calc(var(--c) * (100% + var(--gap))),
    calc(var(--r) * (100% + var(--gap)))
  );
  transition: transform .14s cubic-bezier(.25,.9,.35,1), background .15s;
  touch-action: none;
}
.sp-tile:hover { background: var(--surface-2); }
.sp-tile[data-blank="1"] { visibility: hidden; pointer-events: none; }
.sp-tile[data-ok="1"] { background: var(--good-soft); color: var(--good); }

/* ==========================================================================
   라이트 아웃
   ========================================================================== */

.lo-wrap { position: relative; display: flex; justify-content: center; }
.lo-grid {
  display: grid;
  grid-template-columns: repeat(var(--n), 1fr);
  gap: 8px;
  width: min(420px, 100%);
  aspect-ratio: 1;
  padding: 10px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.lo-cell {
  appearance: none;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--field-cell);
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: background .12s, box-shadow .12s, transform .1s;
}
.lo-cell:hover { transform: scale(1.03); }
.lo-cell[data-on="1"] {
  background: radial-gradient(circle at 36% 30%, #ffe7a3, var(--gold) 72%);
  border-color: transparent;
  box-shadow: 0 0 22px -4px var(--gold);
}

/* ==========================================================================
   1 to 50
   ========================================================================== */

.of-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.of-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  grid-template-rows: repeat(5, minmax(0, 1fr));
  gap: 8px;
  width: min(440px, 100%);
  aspect-ratio: 1;
  padding: 10px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.of-cell {
  appearance: none;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  /* 판 위의 칸은 --surface 가 아니라 --field-cell — 판 바탕과 명암비가 확보된 색이다 */
  background: var(--field-cell);
  color: var(--text);
  font-size: clamp(1.1rem, 4.4vw, 1.6rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform .06s;
}
.of-cell:active { transform: scale(.95); }
/* 26 이상 (두 번째 겹) 은 색으로 구분 */
.of-cell[data-layer="2"] {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: color-mix(in oklab, var(--accent) 35%, transparent);
}
.of-cell[data-layer="empty"] { background: transparent; border-color: transparent; cursor: default; }
.of-cell.is-wrong { animation: of-wrong .25s ease; }
@keyframes of-wrong {
  30% { background: var(--bad-soft); transform: translateX(-3px); }
  60% { transform: translateX(3px); }
}
.of-bar { width: min(440px, 100%); }

/* ==========================================================================
   시각 기억력
   ========================================================================== */

.vm-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.vm-lives { display: flex; gap: 6px; }
.vm-life { font-size: 1.2rem; line-height: 1; color: var(--bad); }
.vm-life[data-on="0"] { color: var(--text-mute); opacity: .5; }
.vm-grid {
  display: grid;
  grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr));
  grid-template-rows: repeat(var(--n, 3), minmax(0, 1fr));
  gap: 8px;
  width: min(440px, 100%);
  aspect-ratio: 1;
  padding: 10px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.vm-tile {
  appearance: none;
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field-cell);
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: background .1s;
}
.vm-wrap:not([data-state="input"]) .vm-tile { cursor: default; }
.vm-tile[data-state="lit"],
.vm-tile[data-state="found"] {
  background: var(--accent);
  border-color: transparent;
  box-shadow: 0 0 18px -4px var(--accent);
}
.vm-tile[data-state="wrong"] { background: var(--bad-soft); border-color: var(--bad); }
.vm-tile[data-state="wrong"]::after {
  content: "✕";
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: var(--bad); font-weight: 800; font-size: 1.2rem;
}
/* 기회를 잃었을 때 못 찾은 칸 */
.vm-tile[data-state="missed"] {
  background: color-mix(in oklab, var(--accent) 35%, var(--surface-3));
  border: 2px dashed var(--accent);
}

/* ==========================================================================
   숫자 야구
   ========================================================================== */

.bb-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.bb-field {
  width: min(440px, 100%);
  display: flex; flex-direction: column; gap: 12px;
  padding: 12px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.bb-history {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 4px;
  min-height: 132px; max-height: 240px;
  overflow-y: auto;
}
.bb-row {
  display: grid;
  grid-template-columns: 26px auto minmax(0, 1fr);
  align-items: center; gap: 12px;
  padding: 7px 12px;
  border-radius: var(--r-sm);
  background: var(--surface);
}
.bb-row-n { color: var(--text-mute); font-size: .8rem; font-weight: 700; }
.bb-row-guess { font-size: 1.15rem; font-weight: 800; letter-spacing: .14em; }
.bb-row-res { justify-self: end; font-weight: 750; color: var(--accent); }
.bb-row[data-out="1"] .bb-row-res { color: var(--text-mute); }
.bb-slots { display: flex; gap: 8px; justify-content: center; }
.bb-slot {
  width: 54px; height: 60px;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  border: 2px dashed var(--line);
  background: var(--field-cell);
  font-size: 1.6rem; font-weight: 800;
}
.bb-slot[data-filled="1"] { border-style: solid; border-color: var(--accent); }
/* 1~5 / 6~9·0 두 줄, 지우기는 오른쪽에 두 줄 높이로 */
.bb-pad {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr)) minmax(0, 1.15fr);
  gap: 7px;
  width: min(440px, 100%);
}
.bb-key-erase { grid-column: 6; grid-row: 1 / span 2; height: auto; }
.bb-key {
  appearance: none;
  height: 54px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text);
  font-size: 1.3rem; font-weight: 750;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.bb-key:hover:not(:disabled) { background: var(--surface-3); }
.bb-key:disabled { opacity: .35; cursor: default; }
.bb-ok { width: min(440px, 100%); }

/* ==========================================================================
   다른 색 찾기
   ========================================================================== */

.oc-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.oc-grid {
  display: grid;
  grid-template-columns: repeat(var(--n, 2), minmax(0, 1fr));
  grid-template-rows: repeat(var(--n, 2), minmax(0, 1fr));
  gap: 6px;
  width: min(440px, 100%);
  aspect-ratio: 1;
  padding: 10px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.oc-tile {
  appearance: none;
  border: 0;
  border-radius: var(--r-sm);
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.oc-tile.is-wrong { animation: oc-wrong .25s ease; }
@keyframes oc-wrong {
  30% { transform: translateX(-3px); box-shadow: inset 0 0 0 3px var(--bad); }
  60% { transform: translateX(3px); }
}
.oc-bar { width: min(440px, 100%); }

/* ==========================================================================
   단어 기억력
   ========================================================================== */

.vb-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; }
.vb-field {
  width: min(480px, 100%);
  min-height: 230px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  padding: 20px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  transition: background .12s;
}
.vb-field[data-fb="ok"]  { background: color-mix(in oklab, var(--good) 22%, var(--field-bg)); }
.vb-field[data-fb="bad"] { background: color-mix(in oklab, var(--bad) 22%, var(--field-bg)); }
.vb-lives { display: flex; gap: 6px; }
.vb-life { font-size: 1.2rem; line-height: 1; color: var(--bad); }
.vb-life[data-on="0"] { color: var(--text-mute); opacity: .5; }
.vb-word {
  min-height: 1.3em;
  font-size: clamp(2rem, 7vw, 3rem);
  font-weight: 800;
  letter-spacing: -.02em;
  text-align: center;
}
.vb-choices { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: min(480px, 100%); }
.vb-choice { width: 100%; }
.vb-wrap:not([data-state="playing"]) .vb-choice { pointer-events: none; opacity: .5; }

/* ==========================================================================
   하노이의 탑
   ========================================================================== */

.hn-wrap { position: relative; display: flex; justify-content: center; }
.hn-field {
  --disk-h: 24px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  width: min(620px, 100%);
  padding: 14px 12px 0;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.hn-peg {
  appearance: none;
  position: relative;
  height: calc(var(--disk-h) * (var(--n) + 3) + 16px);
  border: 0;
  border-radius: var(--r-md) var(--r-md) 0 0;
  background: transparent;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.hn-peg:hover { background: color-mix(in oklab, var(--accent) 7%, transparent); }
.hn-peg[data-held="1"] { background: color-mix(in oklab, var(--accent) 12%, transparent); }
/* 기둥 + 받침 */
.hn-pole {
  position: absolute; left: 50%; bottom: 0;
  width: 10px; height: calc(var(--disk-h) * (var(--n) + 1) + 10px);
  transform: translateX(-50%);
  border-radius: 5px 5px 0 0;
  background: var(--text-mute);
}
/* 받침은 기둥 칸 폭에 맞춘다 — 가장 큰 원판보다 넓게 */
.hn-peg::after {
  content: "";
  position: absolute; left: 1%; right: 1%; bottom: 0;
  height: 8px;
  border-radius: 4px;
  background: var(--text-mute);
}
.hn-disk {
  position: absolute; left: 50%;
  bottom: calc(8px + var(--level) * var(--disk-h));
  width: calc(22% + var(--size) / var(--n) * 74%);
  height: calc(var(--disk-h) - 3px);
  transform: translateX(-50%);
  border-radius: 999px;
  background: hsl(var(--hue) 70% 58%);
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, .18);
  transition: bottom .12s;
}
/* 들어 올린 원판은 기둥 위로 */
.hn-disk[data-lifted="1"] {
  bottom: calc(var(--disk-h) * (var(--n) + 1) + 18px);
  box-shadow: 0 0 0 3px var(--accent), 0 8px 18px -6px rgba(0, 0, 0, .5);
}
.hn-peg.is-wrong { animation: hn-wrong .25s ease; }
@keyframes hn-wrong { 30% { transform: translateX(-4px); } 60% { transform: translateX(4px); } }

/* ==========================================================================
   색깔 단어
   ========================================================================== */

.cw-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.cw-field {
  width: min(480px, 100%);
  display: flex; flex-direction: column; gap: 14px;
  padding: 14px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  transition: background .12s;
}
.cw-field[data-fb="bad"] { background: color-mix(in oklab, var(--bad) 28%, var(--field-bg)); }
/* 글자는 테마와 무관하게 어두운 판 위에 — 노랑도 밝은 테마에서 또렷하게 */
.cw-card {
  display: grid; place-items: center;
  min-height: 150px;
  border-radius: var(--r-md);
  /* 두 테마 모두 어두운 카드 (위 주석 참고). 판 바탕(#070a12)과도 경계가 보이도록 조금 밝게 */
  background: #1b2236;
}
.cw-word {
  font-size: clamp(2.6rem, 11vw, 4rem);
  font-weight: 900;
  letter-spacing: .02em;
  line-height: 1;
}
.cw-choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.cw-choice {
  appearance: none;
  min-height: 64px;
  border: 2px solid rgba(0, 0, 0, .18);
  border-radius: var(--r-md);
  color: #10131c;
  font-size: 1.2rem;
  font-weight: 800;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform .06s, filter .1s;
}
.cw-choice:hover { filter: brightness(1.06); }
.cw-choice:active { transform: scale(.97); }
.cw-field[data-fb="bad"] .cw-choice { opacity: .45; cursor: default; }
.cw-wrap:not([data-state="playing"]) .cw-choice { cursor: default; }
.cw-bar { width: min(480px, 100%); }

/* ==========================================================================
   숫자 위치 기억
   ========================================================================== */

.ch-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.ch-lives { display: flex; gap: 6px; }
.ch-life { font-size: 1.2rem; line-height: 1; color: var(--bad); }
.ch-life[data-on="0"] { color: var(--text-mute); opacity: .5; }
.ch-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  grid-template-rows: repeat(var(--rows), minmax(0, 1fr));
  /* 판이 넓어지면 틈을 줄인다 — 칸 자체가 손가락만 해야 하므로 틈에 내줄 자리가 없다 */
  gap: max(3px, calc(6px - (var(--cols) - 8) * 1px));
  width: min(640px, 100%);
  /* 숫자가 늘면 판이 넓어진다 (js/games/lib/chimp.js GRIDS) — 칸 모양이 찌그러지지 않게 비율도 따라간다 */
  aspect-ratio: var(--cols) / var(--rows);
  padding: 10px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  /* 숫자 크기를 판 너비에서 직접 계산하려고 — .ch-cell 의 cqw */
  container-type: inline-size;
}
.ch-cell {
  appearance: none;
  /* 두 자리 수(10~40)가 들어와도 칸이 커지지 않게: 줄바꿈 금지 + 여백 0 + 줄 높이 1.
     예전에는 좁은 화면에서 "10" 이 두 줄로 쪼개져 판 전체가 세로로 늘어났다가,
     1 을 눌러 숫자가 가려지면 다시 줄어들어 기억해 둔 자리가 어긋났다 */
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  padding: 0;
  white-space: nowrap;
  line-height: 1;
  border: 2px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--field-cell);
  color: var(--text);
  /* 칸 너비의 약 절반 — 판 너비(cqw)에서 재므로 판이 넓어져도 두 자리 수가 칸을 넘지 않는다.
     화면 너비(vw)로 재면 같은 11열이라도 휴대폰에서는 넘치고 PC 에서는 쓸데없이 작아진다 */
  font-size: clamp(.8rem, calc(44cqw / var(--cols, 8)), 1.6rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
/* 1 을 누른 뒤: 숫자를 가린 칸 */
.ch-cell[data-state="hidden"] { background: var(--accent); color: transparent; border-color: transparent; }
.ch-cell[data-state="done"] { visibility: hidden; }
.ch-cell[data-state="wrong"] { background: var(--bad-soft); border-color: var(--bad); color: var(--bad); }
.ch-cell[data-state="reveal"] { border-style: dashed; }
.ch-wrap:not([data-state="input"]) .ch-cell { cursor: default; }

/* ==========================================================================
   색 채우기
   ========================================================================== */

.fl-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; }
.fl-board {
  display: grid;
  grid-template-columns: repeat(var(--n), minmax(0, 1fr));
  grid-template-rows: repeat(var(--n), minmax(0, 1fr));
  /* 칸 사이 실금 — 휴대폰처럼 칸이 작을 때 붙어 있는 두 색의 경계를 눈이 잡게 해 준다 */
  gap: 1px;
  width: min(440px, 100%);
  aspect-ratio: 1;
  padding: 6px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  overflow: hidden;
}
.fl-cell {
  position: relative;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .18s;
}
/* 내 영역 — 가운데 점. 밝은 색 칸에서도 보이도록 흰 점에 어두운 테두리를 둘러 둔다 */
.fl-cell[data-own="1"]::after {
  content: "";
  position: absolute; inset: 34%;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .5);
}
.fl-wrap:not([data-state="playing"]) .fl-cell { cursor: default; }
/* 고른 색 테두리가 잘리지 않게 바깥 여백을 둔다 */
.fl-palette { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; width: min(440px, 100%); padding: 3px; }
.fl-color {
  appearance: none;
  height: 48px;
  /* 테두리를 색 위에 겹치지 않는다 — 버튼 색이 판의 칸 색과 정확히 같아 보이게 */
  border: 0;
  border-radius: var(--r-md);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .28);
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform .06s;
}
.fl-color:active { transform: scale(.95); }
/* 지금 내 영역 색 — 눌러도 소용없다. 흐리게 만들면 판의 색과 달라 보이므로 테두리로만 표시한다 */
.fl-color[data-current="1"] {
  cursor: default;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .28), 0 0 0 3px var(--surface), 0 0 0 5px var(--text);
}
.fl-wrap:not([data-state="playing"]) .fl-color { cursor: default; }

/* ==========================================================================
   빠른 암산
   ========================================================================== */

.ma-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.ma-field {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  width: min(440px, 100%);
  padding: 16px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.ma-card {
  display: flex; align-items: baseline; justify-content: center; gap: 12px;
  width: 100%;
  padding: 18px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--field-cell);
  font-size: clamp(1.8rem, 7vw, 2.6rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.ma-q { white-space: nowrap; }
.ma-eq { color: var(--text-mute); }
.ma-ans { min-width: 2.4ch; color: var(--accent); }
.ma-ans[data-empty="1"] { color: var(--text-mute); }
.ma-card.is-good { animation: ma-good .25s ease-out; }
.ma-card.is-bad { animation: ma-bad .3s ease; }
@keyframes ma-good { 40% { background: var(--good-soft); border-color: var(--good); } }
@keyframes ma-bad {
  30% { background: var(--bad-soft); border-color: var(--bad); transform: translateX(-4px); }
  60% { transform: translateX(4px); }
}
.ma-pad { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; width: 100%; }
.ma-key {
  appearance: none;
  height: 52px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--field-cell);
  color: var(--text);
  font-size: 1.3rem; font-weight: 800;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: transform .06s, background .1s;
}
.ma-key:active { transform: scale(.96); background: var(--surface-3); }
.ma-key[data-key="del"] { color: var(--text-dim); }
.ma-key[data-key="0"] { grid-column: span 2; }
.ma-bar { width: min(440px, 100%); }

/* ==========================================================================
   10초 맞추기
   ========================================================================== */

.ts-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.ts-pad {
  display: grid; place-items: center;
  width: 100%;
  min-height: 320px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.ts-wrap[data-state="intro"] .ts-pad, .ts-wrap[data-state="done"] .ts-pad { cursor: default; }
.ts-inner { display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none; }
.ts-time {
  font-size: clamp(3.6rem, 14vw, 6.4rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}
.ts-pad[data-hidden="1"] .ts-time { color: var(--text-mute); }
.ts-note { min-height: 1.4em; font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-dim); }
.ts-pad[data-grade="great"] .ts-note { color: var(--good); }
.ts-pad[data-grade="good"] .ts-note { color: var(--accent); }
.ts-pad[data-grade="off"] .ts-note { color: var(--bad); }
/* 다음 판을 기다리는 동안 — 누르면 시작 */
.ts-pad[data-state="between"] .ts-inner::after {
  content: "▶";
  margin-top: 4px;
  font-size: 1.4rem;
  color: var(--accent);
  animation: ts-ready 1.1s ease-in-out infinite;
}
@keyframes ts-ready { 50% { opacity: .35; transform: scale(.9); } }
.ts-tries { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.ts-try {
  min-width: 92px;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: .85rem; font-weight: 700;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.ts-try[data-state="empty"] { color: var(--text-mute); }

/* ==========================================================================
   블랙 타일
   ========================================================================== */

.bt-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.bt-field {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-template-rows: repeat(4, minmax(0, 1fr));
  gap: 2px;
  width: min(360px, 100%);
  aspect-ratio: 3 / 4;
  padding: 2px;
  border-radius: var(--r-lg);
  background: var(--line);
  overflow: hidden;
}
.bt-tile {
  background: #f7f9fe;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.bt-tile[data-kind="black"] { background: #161a24; }
.bt-tile[data-kind="none"] { background: var(--field-cell); cursor: default; }
:root[data-theme="dark"] .bt-tile[data-kind="black"] { background: #05070c; box-shadow: inset 0 0 0 1px rgba(255,255,255,.06); }
.bt-wrap[data-state="intro"] .bt-tile { background: var(--field-cell); }
.bt-tile.is-wrong { animation: bt-wrong .3s ease; }
@keyframes bt-wrong { 30% { background: var(--bad); } }
.bt-field.is-step { animation: bt-step .07s ease-out; }
@keyframes bt-step { from { transform: translateY(-5%); } }
.bt-bar { width: min(360px, 100%); }

/* ==========================================================================
   10 만들기
   ========================================================================== */

.mk-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.mk-board {
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  grid-template-rows: repeat(var(--rows), minmax(0, 1fr));
  gap: 3px;
  width: min(640px, 100%);
  aspect-ratio: 14 / 10;
  padding: 8px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  touch-action: none;
  cursor: crosshair;
}
.mk-wrap:not([data-state="playing"]) .mk-board { cursor: default; }
.mk-cell {
  display: grid; place-items: center;
  min-width: 0; min-height: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #ff8a7a, #e03131 68%);
  color: #fff;
  font-size: clamp(.68rem, 2.5vw, 1.05rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 1px rgba(0, 0, 0, .28);
  transition: transform .08s;
}
.mk-cell[data-empty="1"] { background: transparent; color: transparent; text-shadow: none; }
.mk-wrap[data-state="intro"] .mk-cell { background: color-mix(in oklab, #e03131 18%, var(--field-cell)); }
.mk-cell[data-sel="1"] { box-shadow: 0 0 0 2px var(--accent); transform: scale(.9); }
.mk-cell[data-sel="1"][data-empty="1"] { box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 40%, transparent); }
.mk-board[data-hit="1"] .mk-cell[data-sel="1"] { box-shadow: 0 0 0 3px var(--good); }
.mk-cell.is-pop { animation: mk-pop .28s ease-out; }
@keyframes mk-pop { from { box-shadow: 0 0 0 4px var(--good); } to { box-shadow: 0 0 0 0 transparent; } }
.mk-bar { width: min(640px, 100%); }

/* ==========================================================================
   파이프 연결
   ========================================================================== */

.pp-wrap { position: relative; display: flex; justify-content: center; }
.pp-grid {
  display: grid;
  grid-template-columns: repeat(var(--n), minmax(0, 1fr));
  grid-template-rows: repeat(var(--n), minmax(0, 1fr));
  gap: 3px;
  width: min(460px, 100%);
  aspect-ratio: 1;
  padding: 8px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.pp-cell {
  position: relative;
  min-width: 0; min-height: 0;
  padding: 0;
  appearance: none;
  border: 0;
  border-radius: 6px;
  background: var(--field-cell);
  cursor: pointer;
  overflow: hidden;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  --water: #0ea5e9;
}
:root[data-theme="dark"] .pp-cell { --water: #38bdf8; }
.pp-pipe {
  position: absolute; inset: 0;
  --pipe: color-mix(in oklab, var(--text-mute) 75%, transparent);
  transition: transform .12s ease-out;
}
.pp-cell[data-wet="1"] .pp-pipe { --pipe: var(--water); }
.pp-arm, .pp-hub { position: absolute; background: var(--pipe); }
.pp-n { left: 37%; right: 37%; top: 0; bottom: 37%; }
.pp-s { left: 37%; right: 37%; top: 37%; bottom: 0; }
.pp-e { top: 37%; bottom: 37%; left: 37%; right: 0; }
.pp-w { top: 37%; bottom: 37%; left: 0; right: 37%; }
.pp-hub { left: 37%; right: 37%; top: 37%; bottom: 37%; }
.pp-hub.is-end { left: 27%; right: 27%; top: 27%; bottom: 27%; border-radius: 50%; }
.pp-hub.is-source {
  left: 18%; right: 18%; top: 18%; bottom: 18%;
  border-radius: 50%;
  background: var(--water);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--water) 30%, transparent);
}
.pp-wrap[data-state="done"] .pp-cell { background: color-mix(in oklab, var(--water) 12%, var(--field-cell)); }

/* ==========================================================================
   노노그램
   ========================================================================== */

.ng-wrap { position: relative; display: flex; justify-content: center; }
.ng-board {
  display: grid;
  grid-template-columns: max-content repeat(var(--n), minmax(0, 1fr));
  width: min(520px, 100%);
  padding: 8px 10px 10px 6px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  --ng-fill: var(--accent);
}
.ng-clue {
  display: flex;
  gap: 5px;
  color: var(--text);
  font-size: 1rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  transition: opacity .15s;
}
.ng-board[data-n="10"] .ng-clue { font-size: .82rem; gap: 4px; }
.ng-col { flex-direction: column; justify-content: flex-end; align-items: center; padding-bottom: 6px; min-height: 1.4em; }
.ng-row { justify-content: flex-end; align-items: center; padding: 0 8px 0 4px; }
.ng-clue[data-done="1"] { opacity: .32; }
.ng-cell {
  aspect-ratio: 1;
  min-width: 0;
  background: var(--field-cell);
  box-shadow: inset 0 0 0 .5px var(--field-grid);
  cursor: pointer;
  display: grid; place-items: center;
}
.ng-cell[data-edge-r="1"] { border-right: 2px solid var(--field-grid); }
.ng-cell[data-edge-b="1"] { border-bottom: 2px solid var(--field-grid); }
.ng-cell[data-s="1"] { background: var(--ng-fill); box-shadow: inset 0 0 0 .5px color-mix(in oklab, var(--ng-fill) 60%, #000); }
/* × — 칸 크기에 맞춰 그린 굵은 대각선 두 줄 (글자 × 는 칸에 비해 너무 작았다).
   손으로 붙인 × 와 줄이 맞아 저절로 붙은 × (data-auto) 는 같은 모양 */
.ng-cell[data-s="2"], .ng-cell[data-auto] {
  --ng-x: color-mix(in oklab, var(--text) 62%, transparent);
  background-image:
    linear-gradient(45deg, transparent 44%, var(--ng-x) 44% 56%, transparent 56%),
    linear-gradient(-45deg, transparent 44%, var(--ng-x) 44% 56%, transparent 56%);
  background-size: 58% 58%;
  background-position: center;
  background-repeat: no-repeat;
}
.ng-wrap:not([data-state="playing"]) .ng-cell { cursor: default; }
.ng-wrap[data-state="done"] { --ng-fill: var(--good); }
.ng-wrap[data-state="done"] .ng-board { --ng-fill: var(--good); }

/* ==========================================================================
   새 그림 찾기
   ========================================================================== */

.ni-wrap { position: relative; display: flex; justify-content: center; }
.ni-grid {
  display: grid;
  /* 칸은 96px 까지만 — 그림이 적은 첫 판에 한 장이 판 절반을 차지하지 않게. 가운데 모은다 */
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 96px));
  justify-content: center;
  /* 판이 넓어지면 틈을 줄인다 — 칸 자체가 손가락만 해야 하므로 틈에 내줄 자리가 없다 */
  gap: max(3px, calc(6px - (var(--cols, 3) - 8) * 1px));
  width: min(520px, 100%);
  min-height: 300px;
  align-content: center;
  padding: 10px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  /* 그림 크기를 판 너비에서 직접 계산하려고 — .ni-cell 의 cqw */
  container-type: inline-size;
}
.ni-cell {
  appearance: none;
  aspect-ratio: 1;
  min-width: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--field-cell);
  font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", sans-serif;
  /* 칸 너비의 약 3/4 — 판 너비(cqw)에서 재므로 휴대폰이든 PC 든 칸에 꽉 차되 넘치지 않는다 */
  font-size: clamp(.7rem, calc(56cqw / var(--cols, 3)), 2.6rem);
  line-height: 1;
  display: grid;
  place-items: center;
  overflow: hidden;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: transform .06s;
}
.ni-cell:active { transform: scale(.94); }
.ni-wrap:not([data-state="playing"]) .ni-cell { cursor: default; }
.ni-cell.is-good { background: var(--good-soft); border-color: var(--good); }
.ni-cell.is-bad { background: var(--bad-soft); border-color: var(--bad); animation: ni-bad .3s ease; }
.ni-cell.is-answer { border-color: var(--good); box-shadow: 0 0 0 3px var(--good); }
@keyframes ni-bad { 30% { transform: translateX(-4px); } 60% { transform: translateX(4px); } }

/* ==========================================================================
   상자 밀기
   ========================================================================== */

.sk-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; }
.sk-grid {
  display: grid;
  grid-template-columns: repeat(var(--n, 8), minmax(0, 1fr));
  gap: 2px;
  width: min(420px, 100%, 56vh);
  aspect-ratio: 1;
  padding: 8px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  touch-action: none;
}
.sk-cell {
  position: relative;
  min-width: 0;
  min-height: 0;
  border-radius: 3px;
  background: var(--field-cell);
}
/* 벽 — 바닥과 확실히 갈라져야 한다. 테마 글자색을 섞어 어두운 테마에서는 밝게, 밝은 테마에서는 어둡게 */
.sk-cell[data-kind="wall"] {
  background: color-mix(in oklab, var(--text) 62%, var(--field-bg));
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--text) 80%, var(--field-bg));
}
/* 목표 — 가운데 빈 고리. 상자가 올라가도 테두리가 비쳐 보인다 */
.sk-cell[data-goal="1"]::before {
  content: "";
  position: absolute;
  inset: 30%;
  border: 2px dashed var(--accent);
  border-radius: 50%;
}
/* 상자 */
.sk-cell[data-box="1"]::after {
  content: "";
  position: absolute;
  inset: 12%;
  border-radius: 4px;
  background: var(--warn);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .35);
}
/* 목표 위에 올라간 상자 */
.sk-cell[data-box="1"][data-goal="1"]::after { background: var(--good); }
/* 나 — 목표 고리(점선 파랑)와 헷갈리지 않게 꽉 찬 다른 색 동그라미로 */
.sk-cell[data-player="1"]::after {
  content: "";
  position: absolute;
  inset: 18%;
  border-radius: 50%;
  background: var(--accent-2);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .35), 0 0 0 2px var(--field-cell);
}
.sk-wrap[data-state="stuck"] .sk-grid { border-color: var(--bad); box-shadow: 0 0 0 4px var(--bad-soft); }

/* ==========================================================================
   엔백
   ========================================================================== */

.nb-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 18px; }
.nb-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  gap: 10px;
  width: min(360px, 100%);
  aspect-ratio: 1;
  padding: 12px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  touch-action: none;
}
.nb-cell {
  min-width: 0;
  min-height: 0;
  border-radius: var(--r-md);
  background: var(--field-cell);
  transition: background-color .07s;
}
.nb-cell[data-on="1"] { background: var(--accent); }
/* 틀린 순간 판 테두리가 한 번 붉어진다 — 소리를 못 쓰므로 눈으로 알려 준다 */
.nb-wrap[data-flash="bad"] .nb-grid { border-color: var(--bad); box-shadow: 0 0 0 4px var(--bad-soft); }

.nb-hit {
  appearance: none;
  width: min(360px, 100%);
  min-height: 62px;
  border: 2px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: 1.15rem;
  font-weight: 800;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.nb-hit[data-state="on"] { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.nb-wrap:not([data-state="playing"]) .nb-hit { cursor: default; opacity: .5; }

/* ==========================================================================
   물병 정렬
   ========================================================================== */

.bs-wrap { position: relative; display: flex; justify-content: center; }
.bs-field {
  display: grid;
  grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  /* 들린 공이 윗줄 병을 파고들지 않게 세로 간격을 넉넉히 */
  gap: 34px 10px;
  justify-items: center;
  width: min(520px, 100%);
  padding: 34px 12px 16px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
}
.bs-tube {
  appearance: none;
  position: relative;
  display: flex;
  flex-direction: column-reverse;   /* 바닥부터 쌓인다 */
  align-items: center;
  justify-content: flex-start;
  gap: 2px;
  width: 100%;
  max-width: 54px;
  padding: 4px;
  /* 공 네 개 높이로 고정 — 비어 있어도 줄어들지 않게. 세로 flex 안에서는
     ::before 로 자리를 잡으면 높이가 "더해져" 병이 두 배가 된다 */
  min-height: calc(4 * (var(--ball, 30px) + 2px) + 8px);
  /* 병 모양 — 위는 열려 있고 아래는 둥글다 */
  border: 3px solid var(--field-line);
  border-top: none;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  background: var(--field-cell);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.bs-tube[data-sel="1"] { border-color: var(--accent); box-shadow: var(--ring); }
.bs-wrap:not([data-state="playing"]) .bs-tube { cursor: default; }
.bs-ball {
  width: var(--ball, 30px);
  height: var(--ball, 30px);
  border-radius: 50%;
  /* 색이 밝든 어둡든 공 경계가 보이게 — 색만으로 구분하지 않는다 */
  box-shadow: inset 0 -3px 6px rgba(0, 0, 0, .3), inset 0 2px 4px rgba(255, 255, 255, .35), 0 0 0 1px rgba(0, 0, 0, .45);
  transition: transform .12s;
}
/* 든 공 — 병 위로 올라온다 */
.bs-ball[data-lift="1"] { transform: translateY(calc(-100% - 12px)); }

@media (max-width: 560px) {
  .bs-field { --ball: 24px; gap: 30px 8px; padding: 30px 8px 12px; }
  .bs-tube { max-width: 40px; padding: 3px; }
}

/* ==========================================================================
   블록 채우기
   ========================================================================== */

.bf-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; }
.bf-board {
  display: grid;
  grid-template-columns: repeat(var(--n), minmax(0, 1fr));
  grid-template-rows: repeat(var(--n), minmax(0, 1fr));
  gap: 3px;
  /* 판과 "놓을 블록" 이 함께 보여야 한다 — 블록이 화면 밖에 있으면 무엇을 놓는지 모른 채 판을 누르게 된다.
     그래서 창 높이에도 맞춰 줄인다 (44vh ≈ 판, 나머지는 제목·블록 자리) */
  width: min(440px, 100%, 44vh);
  aspect-ratio: 1;
  padding: 8px;
  border-radius: var(--r-lg);
  background: var(--field-bg);
  /* 놓을 자리를 손가락으로 끌어 맞추는 동안 화면이 같이 밀리지 않게 */
  touch-action: none;
}
.bf-cell {
  min-width: 0;
  min-height: 0;
  border-radius: 4px;
  background: var(--field-cell);
}
/* 칠해진 칸 — 판 색이 밝든 어둡든 칸 경계가 보이게 안쪽 테두리를 깐다 */
.bf-cell[data-on="1"], .bf-cell[data-ghost="ok"] { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .34); }
/* 놓일 자리 미리보기 — 실제로 놓인 칸과 헷갈리지 않게 반투명 + 흰 테두리 */
.bf-cell[data-ghost="ok"] { opacity: .6; outline: 2px solid var(--text); outline-offset: -2px; }
.bf-cell[data-ghost="bad"] { background: var(--bad); opacity: .45; }
/* 사라지는 줄 */
.bf-cell[data-gone="1"] { background: var(--text) !important; box-shadow: none; }

.bf-tray {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  width: min(440px, 100%, 44vh);
}
.bf-slot {
  appearance: none;
  display: grid;
  place-items: center;
  min-height: 76px;
  padding: 8px;
  border: 2px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.bf-slot[data-sel="1"] { border-color: var(--accent); box-shadow: var(--ring); }
.bf-slot[data-empty="1"] { cursor: default; border-style: dashed; }
/* 어디에도 못 놓는 블록 — 흐리게 해서 왜 끝나는지 눈으로 보이게 */
.bf-slot[data-dead="1"] .bf-mini { opacity: .3; }
.bf-wrap:not([data-state="playing"]) .bf-slot { cursor: default; }

.bf-mini { display: grid; grid-template-columns: repeat(var(--w), 1fr); gap: 2px; }
.bf-dot { width: 15px; height: 15px; border-radius: 3px; }
.bf-dot[data-on="1"] { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .34); }

@media (max-width: 560px) {
  .bf-slot { min-height: 62px; padding: 6px; }
  .bf-dot { width: 11px; height: 11px; }
}

/* ==========================================================================
   단어 소나기
   ========================================================================== */

.wr-wrap { position: relative; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.wr-field {
  position: relative;
  width: 100%;
  height: clamp(260px, 50svh, 420px);
  border-radius: var(--r-lg);
  background: var(--field-bg);
  overflow: hidden;
  touch-action: manipulation;
}
.wr-ground {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 6px;
  background: color-mix(in oklab, var(--bad) 45%, transparent);
}
.wr-ground.is-hit { animation: wr-hit .45s ease-out; }
@keyframes wr-hit { from { height: 22px; background: var(--bad); } }
.wr-drop {
  position: absolute; top: 0; left: 50%;
  padding: 3px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--field-cell);
  color: var(--text);
  font-size: 1.05rem;
  font-weight: 700;
  white-space: nowrap;
  will-change: transform;
}
.wr-drop[data-hit="1"] { border-color: var(--accent); color: var(--accent); }
.wr-drop.is-pop { animation: wr-pop .3s ease-out forwards; }
@keyframes wr-pop { to { opacity: 0; scale: 1.35; border-color: var(--good); color: var(--good); } }
.wr-wrap[data-paused="1"] .wr-drop { visibility: hidden; }
.wr-form { width: min(420px, 100%); margin: 0; }
.wr-input {
  width: 100%;
  height: 48px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font-size: 1.15rem;
  font-weight: 700;
  text-align: center;
}
.wr-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 25%, transparent); }
.wr-input.is-bad { animation: ma-bad .3s ease; border-color: var(--bad); }

/* ==========================================================================
   공통: 플레이 영역(그라운드) 경계
   모든 게임의 "게임이 진행되는 판" 을 같은 테두리·바탕으로 감싼다.
   게임마다 두께·색이 다르면 어디까지가 판인지 매번 새로 읽어야 한다.
   개별 게임 섹션보다 뒤에 둬서 이 규칙이 우선한다.
   ========================================================================== */

/* 틀린 뒤 잠깐 못 누르는 동안 (_shared.js wrongLock) — 판이 흐려진다 */
.game-mount [data-lock="1"] { cursor: not-allowed; }
.game-mount [data-lock="1"] > *,
.game-mount [data-lock="1"] button { opacity: .55; transition: opacity .08s; }

/* 빠르게 연타하면 판 안의 글자·이모지가 드래그 선택돼 파랗게 칠해진다 — 입력칸만 예외 */
.game-mount { user-select: none; -webkit-user-select: none; }
.game-mount input { user-select: text; -webkit-user-select: text; }

/* 색은 base.css 의 --field-* 토큰 (캔버스 게임도 같은 값을 읽는다) */
.cs-pad, .rt-pad, .aim-area, .of-grid, .oc-grid, /* 반응·속도 */
.wm-grid, .ty-stream, .cw-field, .ma-field, .ts-pad, .bt-field,
.nm-wrap, .sq-grid, .vm-grid, .vb-field, .mm-grid, .ch-grid, .nb-grid, /* 기억력 */
.ms-board, .sd-grid, .tw-board, .sp-board, .lo-grid, .bb-field, .hn-field, .fl-board, .sk-grid, /* 퍼즐 */
.mk-board, .pp-grid, .ng-board, .ni-grid, .bf-board, .bs-field, .wr-field,
.stage-wrap {                                   /* 액션 (캔버스) */
  border-width: 3px;
  border-style: solid;
  border-color: var(--field-line);
  box-shadow: 0 0 0 4px var(--field-ring);
}

/* 칸 사이 틈을 눌러 끌어도 페이지가 밀리지 않게 — 연타 중에 화면이 흔들리거나 당겨서 새로고침이 되지 않게.
   두 손가락으로 확대해 누르는 지뢰찾기, 스크롤이 필요한 판(타이핑 글 등)은 넣지 않는다 */
.wm-grid, .of-grid, .oc-grid, .sq-grid, .vm-grid, .ch-grid, .lo-grid, .bt-field, .ni-grid, .mk-board, .ng-board,
.bf-board, .nb-grid, .sk-grid, .cw-field, .aim-area { touch-action: none; }
.sd-cell { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }

/* ==========================================================================
   모바일 조정
   ========================================================================== */

@media (max-width: 560px) {
  .cs-pad { min-height: 260px; }
  .rt-pad { min-height: 280px; }
  .aim-area { min-height: 220px; }
  .ty-stream { font-size: 1.08rem; min-height: 118px; max-height: 118px; }
  .nm-wrap { min-height: 270px; }
  .ts-pad { min-height: 260px; }
  .ma-field { padding: 12px; gap: 10px; }
  .ma-key { height: 46px; }
  .mk-board { padding: 5px; gap: 2px; }
  .pp-grid { padding: 5px; gap: 2px; }
  .ov-box { padding: 20px 16px; }
  .ov-title { font-size: 1.25rem; }
}
