/* Reaction Benchmark — base + 공용 부품. 색은 전부 토큰에서만.
   방향: 계측 장비. 숫자는 고정폭·tabular, 라벨은 작은 대문자, 면은 얇은 격자 위에 앉는다. */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font: var(--text-md)/1.65 var(--font-sans);
  /* 계기판 격자 — 아주 옅게, 배경에만 */
  background-image:
    linear-gradient(var(--color-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--color-grid) 1px, transparent 1px);
  background-size: 64px 64px, 64px 64px;
  background-position: -1px -1px;
}
img, canvas, svg { max-width: 100%; }
/* 모바일 탭 하이라이트 제거 — 탭마다 웹킷 기본 반투명 사각형이 번쩍인다(사장님 제보 2026-08-03).
   피드백은 우리 연출(팝·링·:active)이 담당. :hover 규칙은 전부 (hover: hover) 가드 — 터치에서
   탭 순간 hover 스타일이 번쩍 얹혔다 눌러붙는 것(sticky hover)도 같은 제보의 원인이었다. */
html { -webkit-tap-highlight-color: transparent; }
a { color: var(--color-link); text-decoration: none; }
/* 본문 속 링크는 색만으로 구분되면 안 된다(WCAG 1.4.1) — 밑줄을 기본으로 둔다. */
p a, li a, article a { text-decoration: underline; text-underline-offset: 3px; }
/* 행 전체가 링크인 곳은 밑줄을 끈다(텍스트 속 링크가 아니라 목록 항목이다) */
.test-list a, .records-grid a, .nav-links a, .brand { text-decoration: none; }
@media (hover: hover) { a:hover { text-decoration: underline; } }
:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

/* 디테일 — 드래그 선택은 브랜드 앰버, 스크롤바는 배경 톤에 맞춘다(밝은 기본 스크롤바가 다크 판에서 튐) */
::selection { background: var(--color-primary); color: var(--color-on-primary); }
html { scrollbar-color: var(--color-outline) var(--color-bg); }

h1 { font-size: var(--text-xl); line-height: 1.2; margin: 0 0 var(--space-2); letter-spacing: -.01em; }
h2 { font-size: var(--text-lg); margin: var(--space-5) 0 var(--space-2); letter-spacing: -.01em; }
h3 { font-size: var(--text-md); margin: var(--space-4) 0 var(--space-2); }
p { margin: 0 0 var(--space-3); }
.muted { color: var(--color-text-muted); font-size: var(--text-sm); }
/* 데스크톱에서 내용이 화면 절반에 웅크리지 않게 판을 넓힌다(2026-08-02 개편).
   본문 산문은 아래 article 폭 제한이 따로 지킨다 — 판이 넓다고 줄이 길어지면 안 된다. */
.wrap { max-width: 960px; margin: 0 auto; padding: 0 var(--space-3); }
article > *, main.wrap > p { max-width: 76ch; }

/* 작은 대문자 라벨 — 계측기 눈금판의 글씨 */
.eyebrow {
  font: 600 var(--text-xs)/1 var(--font-mono);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--color-text-muted); margin: 0 0 var(--space-2);
}

/* 가이드 글 발행일·수정일 줄 (build.mjs datesLine이 h1 아래에 넣는다) */
.dates { font: var(--text-xs)/1.4 var(--font-mono); color: var(--color-text-muted); margin: 0 0 var(--space-3); }

/* nav */
.site-head { border-bottom: 1px solid var(--color-outline); background: var(--color-bg); }
.nav { max-width: 960px; margin: 0 auto; padding: var(--space-3);
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3); align-items: center; }
.brand { font: 700 var(--text-md)/1 var(--font-mono); color: var(--color-text); letter-spacing: -.02em;
  display: inline-flex; align-items: center; gap: var(--space-2); }
.brand-mark { width: 22px; height: 22px; }
.brand b { font-weight: 400; color: var(--color-text-muted); }
.nav-links { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-left: auto; }
.nav-links a { color: var(--color-text-muted); font: 500 var(--text-sm)/1 var(--font-mono);
  padding: var(--space-2); border-radius: var(--radius-sm); min-height: 44px;
  display: inline-flex; align-items: center; }
@media (hover: hover) { .nav-links a:hover { color: var(--color-text); background: var(--color-surface-raised); text-decoration: none; } }
.nav-run { color: var(--color-text) !important; font-weight: 700; }
/* ─── 모바일 네비(≤720px) — PC 상단 바를 구겨 넣지 않는다(사장님 2026-08-03 "각 버전에 최적화").
   1줄: 브랜드 + 언어 토글 · 2줄: 가로 스와이프 칩 바(알약 테두리 = 눌린다는 신호,
   끝에 반쯤 걸린 칩 = 더 있다는 신호). JS 0 — 앱들의 상단 카테고리 칩 관습. */
@media (max-width: 720px) {
  .nav { padding: var(--space-2) var(--space-3); row-gap: var(--space-2); }
  .nav-links { flex-wrap: nowrap; overflow-x: auto; margin-left: 0; flex: 1 1 100%;
    order: 3; gap: var(--space-2); scrollbar-width: none; }
  .nav-links::-webkit-scrollbar { display: none; }
  .nav-links a { white-space: nowrap; border: 1px solid var(--color-outline); border-radius: 999px;
    padding: 0 var(--space-3); min-height: 38px; font-size: var(--text-sm); }
  .nav-run { border-color: var(--color-primary) !important; }
  .lang-toggle { margin-left: auto; }
}
/* 언어 토글 — 다른 항목과 같은 줄 높이의 알약. 예전엔 큰 상자라 줄에서 삐죽 튀어나왔다. */
.lang-toggle { border: 1px solid var(--color-outline); border-radius: 999px;
  color: var(--color-text-muted) !important; margin-left: var(--space-2);
  padding: 0 var(--space-3) !important; min-height: 32px !important; align-self: center; }
@media (hover: hover) { .lang-toggle:hover { border-color: var(--color-primary); color: var(--color-text) !important; background: none !important; } }

main.wrap { padding-top: var(--space-5); padding-bottom: var(--space-6); }

/* footer — 브랜드 + 링크 그룹 + SNS 공유. 고정 카본 배경 + 앰버 상단 라인(테마 무관 마감 앵커,
   F1 야간 카드와 같은 계열 — 2026-08-04 사장님 "푸터 색 안 넣어도 되나"). */
.site-foot { background: var(--foot-bg); border-top: 3px solid var(--color-primary);
  padding-top: var(--space-5); padding-bottom: var(--space-6); margin-top: var(--space-6);
  font-size: var(--text-sm); color: var(--foot-muted); }
.foot-brand { display: inline-flex; align-items: center; gap: var(--space-2);
  font: 700 var(--text-md)/1 var(--font-mono); color: var(--foot-text); letter-spacing: -.02em; }
.foot-brand b { font-weight: 400; color: var(--foot-muted); }
.foot-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-4) var(--space-5); margin-top: var(--space-4); }
.foot-col h3 { font: 600 var(--text-xs)/1 var(--font-mono); letter-spacing: .14em;
  text-transform: uppercase; color: var(--foot-muted); margin: 0 0 var(--space-3); }
.foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.foot-col a { color: var(--foot-muted); text-decoration: none; transition: color .15s ease; }
@media (hover: hover) { .foot-col a:hover { color: var(--foot-text); text-decoration: none; } }
/* SNS 원형 버튼 — 플랫폼 로고는 그쪽 브랜드색이 식별 신호라 예외적으로 색을 쓴다 */
.share-circles { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.sc { width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--foot-outline);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer; padding: 0;
  transition: transform .15s ease; }
@media (hover: hover) { .sc:hover { transform: scale(1.1); } }
.sc:active { transform: scale(.95); }
.sc svg { width: 17px; height: 17px; display: block; }
.sc-x { background: var(--brand-x); color: var(--brand-on); }
.sc-fb { background: var(--brand-facebook); color: var(--brand-on); }
.sc-th { background: var(--brand-x); color: var(--brand-on); }
.sc-nv { background: var(--brand-naver); color: var(--brand-on); }
.sc-kakao { background: var(--brand-kakao); color: var(--brand-kakao-text); }
.sc-copy { background: var(--foot-outline); color: var(--foot-text); }
.share-msg { display: block; margin-top: var(--space-2); font: 600 var(--text-xs)/1.4 var(--font-mono);
  color: var(--foot-text); min-height: 1.2em; }
.foot-copy { margin-top: var(--space-5); padding-top: var(--space-3);
  border-top: 1px solid var(--foot-outline); }
/* 운영자 트래픽 제외 상태 표시(head.html의 notrack 스위치) */
.notrack-note { font: 600 var(--text-xs)/1.5 var(--font-mono); color: var(--color-signal-text); }

/* 버튼 4종 — 높이·곡률·크기는 여기서만 정한다 */
/* ★ hidden 속성이 항상 이긴다.
   브라우저 기본 [hidden]{display:none}은 특이도가 0이라, .btn-secondary처럼 display를 정하는
   클래스가 있으면 그쪽이 이긴다. 그래서 startBtn.hidden = true가 화면에 아무 효과가 없었고
   일곱 게임 전부에서 Start 버튼이 플레이 중에도 남아 있었다(2026-08-02, 사장님 신고).
   JS가 hidden을 켜면 반드시 사라져야 한다 — 여기서 못 박는다. */
[hidden] { display: none !important; }

.btn, .btn-secondary, .btn-quiet {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 44px; padding: 0 var(--space-4); border-radius: var(--radius-md);
  font: 600 var(--text-sm)/1 var(--font-mono); letter-spacing: .02em;
  cursor: pointer; border: 1px solid transparent; }
.btn { background: var(--color-primary); color: var(--color-on-primary); }
@media (hover: hover) { .btn:hover { filter: brightness(1.08); } }
.btn-secondary { background: none; border-color: var(--color-outline); color: var(--color-text); }
@media (hover: hover) { .btn-secondary:hover { border-color: var(--color-primary); } }
.btn-quiet { background: none; color: var(--color-text-muted); }
@media (hover: hover) { .btn-quiet:hover { color: var(--color-text); } }

/* 눌림 피드백 — 반응은 release가 아니라 press에서. 터치에는 hover가 없어 이게 유일한 즉시 피드백.
   게임 타일은 제외(pointerdown에서 JS 연출이 이미 즉답 — 이중 피드백 금지). */
.btn:active, .btn-secondary:active, .btn-quiet:active,
.mode-btn:active, .lang-toggle:active { transform: scale(.97); }
.test-list a:active, .daily-card:active, .variant-card:active { transform: scale(.99); }

/* 디테일 — 상호작용 요소는 상태 변화가 뚝 끊기지 않게(색·테두리·눌림만, 레이아웃 속성 금지) */
.test-list a, .record, .daily-card, .variant-card, .btn, .btn-secondary, .btn-quiet, .mode-btn, .tile, .lang-toggle {
  transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .1s ease-out; }

/* 본문 표 — 비교표(순서↔시각 등)에 쓴다. 넘치면 표만 가로 스크롤. */
article table { border-collapse: collapse; width: 100%; margin: var(--space-3) 0;
  font-size: var(--text-sm); display: block; overflow-x: auto; }
article th, article td { border: 1px solid var(--color-outline); padding: var(--space-2) var(--space-3);
  text-align: left; vertical-align: top; }
article th { background: var(--color-surface); font-weight: 600; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* 오류 표시 — 색만으로 전달 금지: 아이콘+테두리 동반 */
.error-note { border: 1px solid var(--color-danger); border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3); font-size: var(--text-sm); }
.error-note::before { content: "⚠ "; }

/* 카드 */
.card { background: var(--color-surface); border: 1px solid var(--color-outline);
  border-radius: var(--radius-lg); padding: var(--space-4); }

/* 홈 히어로 — 이 사이트의 주장을 먼저 말한다.
   넓은 화면에선 주장(왼쪽) + 명판(오른쪽) 2단: 계측기의 스펙 플레이트처럼.
   예전엔 좁은 기둥 하나라 1440px에서 오른쪽 절반이 죽은 공간이었다(2026-08-02 개편). */
.hero { border-bottom: 1px solid var(--color-outline); padding-bottom: var(--space-5); }
.hero .eyebrow { color: var(--color-signal-text); }
.hero h1 { font-size: var(--text-hero); max-width: 16ch; letter-spacing: -.02em; line-height: 1.1; }
.hero-claim { font-size: var(--text-md); color: var(--color-text-muted); max-width: 52ch; }
.hero-cta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4);
  margin-top: var(--space-4); }
/* 설명은 히어로가 아니라 링크 뒤에 산다 — 후킹(버튼)과 방법(조용한 링크)의 자리 구분 */
.hero-how { font: 500 var(--text-xs)/1.4 var(--font-mono); letter-spacing: .04em;
  color: var(--color-text-muted); text-decoration-color: var(--color-outline); }
@media (hover: hover) { .hero-how:hover { color: var(--color-text); } }
.hero-strip { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5);
  margin-top: var(--space-4); font: 500 var(--text-xs)/1.4 var(--font-mono);
  letter-spacing: .08em; text-transform: uppercase; color: var(--color-text-muted); }
.hero-strip b { display: block; font-size: var(--text-lg); letter-spacing: -.02em;
  text-transform: none; color: var(--color-text); font-variant-numeric: tabular-nums; }
@media (min-width: 860px) {
  .hero { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--space-6); align-items: center; }
  .hero > * { grid-column: 1; }
  .hero > .hero-strip { grid-column: 2; grid-row: 1 / span 4; align-self: center;
    flex-direction: column; gap: var(--space-4); margin: 0;
    border-left: 1px solid var(--color-outline); padding-left: var(--space-5); }
  .hero-strip b { font-size: var(--text-xl); }
}

/* 테스트 목록 — 카드 격자가 아니라 계기 목록(순서가 아니라 종류다) */
.test-list { list-style: none; padding: 0; margin: var(--space-4) 0 0;
  border-top: 1px solid var(--color-outline); }
.test-list li { border-bottom: 1px solid var(--color-outline); }
.test-list a { display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: var(--space-3); padding: var(--space-3) var(--space-2); color: var(--color-text); }
@media (hover: hover) { .test-list a:hover { background: var(--color-surface); text-decoration: none; } }
/* 아이콘은 계기 눈금판 타일 — 크기·테두리를 통일해 글리프가 '디자인된 아이콘'으로 읽히게 한다 */
.test-list .t-icon { display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border: 1px solid var(--color-outline); border-radius: var(--radius-md);
  background: var(--color-surface); color: var(--color-signal-text);
  font: 400 var(--text-lg)/1 var(--font-mono); }
.test-list .t-name { font-weight: 600; }
.test-list .t-desc { display: block; color: var(--color-text-muted); font-size: var(--text-sm); font-weight: 400; }
.test-list .t-meta { font: 500 var(--text-xs)/1.6 var(--font-mono); letter-spacing: .06em;
  text-transform: uppercase; color: var(--color-text-muted); text-align: right; white-space: nowrap; }
.test-list .t-meta b { display: block; color: var(--color-data); font-weight: 600; }
@media (max-width: 520px) {
  .test-list a { grid-template-columns: auto 1fr; }
  .test-list .t-meta { grid-column: 2; text-align: left; }
}

/* 버튼 + 설명 한 줄 — 단어 간격에 기대지 않는다(버튼과 글이 붙어 보이던 원인). */
.run-cta { display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-3) var(--space-4); margin: var(--space-4) 0 0; }
.run-cta .muted { max-width: 44ch; }

/* 오늘의 도전 — 하루 한 번의 사건. 앰버 스트라이프가 목록 위에서 오늘을 가리킨다. */
.daily-card { display: grid; grid-template-columns: auto 1fr auto;
  gap: var(--space-3) var(--space-4);
  align-items: center; margin: var(--space-5) 0 calc(-1 * var(--space-2));
  padding: var(--space-4); border: 1px solid var(--color-outline);
  border-left: 3px solid var(--color-primary); border-radius: var(--radius-lg);
  background: var(--color-surface); color: var(--color-text); text-decoration: none !important; }
@media (hover: hover) { .daily-card:hover { border-color: var(--color-primary); } }
.daily-card .eyebrow { margin: 0; color: var(--color-signal-text); }
.daily-main b { display: block; font-size: var(--text-lg); }
.daily-sub { display: block; color: var(--color-text-muted); font-size: var(--text-sm); }
.daily-count { font: 600 var(--text-xs)/1.4 var(--font-mono); letter-spacing: .06em;
  text-transform: uppercase; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
@media (max-width: 520px) {
  .daily-card { grid-template-columns: auto 1fr; }
  .daily-cta { grid-column: 2; }
}
/* 스테이지의 회차 스탬프(데일리 모드) */
.daily-badge { position: absolute; top: var(--space-2); left: var(--space-2); z-index: 1;
  font: 700 var(--text-xs)/1 var(--font-mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--color-signal-text); padding: var(--space-1) var(--space-2);
  border: 1px solid var(--color-outline); border-radius: var(--radius-sm); background: var(--color-bg); }
/* 종합 측정 유형 총평 — 일곱 개를 다 돌았을 때의 한 장 판정 */
.run-type { border: 1px solid var(--color-outline); border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-lg); padding: var(--space-4); margin: var(--space-4) 0; }
.run-type .eyebrow { margin-bottom: var(--space-1); }
.run-type-title { font: 800 var(--text-xl)/1.3 var(--font-sans); margin: 0 0 var(--space-2); }
.run-type .muted { margin: 0; max-width: 60ch; }

/* 결과 패널의 데일리 블록 */
.daily-result { border: 1px solid var(--color-outline); border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-md); padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm); color: var(--color-text-muted); }

/* 업적 토스트(결과 화면) + 홈 마일스톤 배지 줄 */
.ach-toast { border: 1px solid var(--color-outline); border-left: 3px solid var(--color-success);
  border-radius: var(--radius-md); padding: var(--space-2) var(--space-3);
  font: 600 var(--text-sm)/1.5 var(--font-sans); color: var(--color-text);
  animation: tile-pop 200ms cubic-bezier(.34, 1.56, .64, 1); }
.ach-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  margin-top: var(--space-3); }
.ach-label { font: 600 var(--text-xs)/1 var(--font-mono); letter-spacing: .12em;
  text-transform: uppercase; color: var(--color-text-muted); margin-right: var(--space-1); }
.ach-chip { display: inline-flex; align-items: center; gap: var(--space-1);
  border: 1px solid var(--color-outline); border-radius: 999px;
  padding: var(--space-1) var(--space-3); font-size: var(--text-xs);
  color: var(--color-text-muted); opacity: .45; }
.ach-chip.is-won { opacity: 1; color: var(--color-text); border-color: var(--color-primary); }
.ach-chip.is-won .ach-glyph { color: var(--color-signal-text); }
.daily-result b { color: var(--color-signal-text); font-family: var(--font-mono); }
/* 데일리 결과 글리프 줄 — 공유되는 모양 그대로 보여준다 */
.daily-grid { display: inline-block; margin-top: var(--space-1);
  font: 600 var(--text-md)/1.4 var(--font-mono); letter-spacing: .1em; color: var(--color-text); }

/* 테스트 스테이지 — 계측 패널 */
.test-stage { position: relative; background: var(--color-surface);
  border: 1px solid var(--color-outline); border-radius: var(--radius-lg);
  min-height: 360px; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: var(--space-3); text-align: center;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
  cursor: pointer; padding: var(--space-4); overflow: hidden; }
/* 스테이지 색에는 전환을 걸지 않는다.
   반응속도 자극이 120ms에 걸쳐 서서히 나타나면 "언제 초록이 됐는가"가 흐려지고
   그 시간이 측정값에 얹힌다 — 측정 도구에서 눈요기보다 즉시성이 먼저다(2026-08-02). */
.test-stage .stage-msg { font: 700 var(--text-xl)/1.2 var(--font-sans); margin: 0; max-width: 100%; overflow-wrap: anywhere; }
/* 외워야 할 숫자 — 고정폭으로, 화면 폭에 맞춰 줄어든다.
   고정 크기로 두면 16자리부터 좁은 화면에서 잘려 나갔다(2026-08-02 실측). */
.test-stage .stage-msg.is-digits {
  font: 800 clamp(1.4rem, 7vw, 2.2rem)/1.2 var(--font-mono);
  font-variant-numeric: tabular-nums; letter-spacing: .06em; }
.test-stage .stage-sub { color: var(--color-text-muted); font: 500 var(--text-xs)/1 var(--font-mono);
  letter-spacing: .12em; text-transform: uppercase; margin: 0; }
/* 계측 프레임 — 뷰파인더식 모서리 눈금. 빈 상자가 아니라 측정 시야라는 뜻을 준다.
   재생 중(is-wait/is-go)에는 배경이 신호색이 되므로 눈금을 치운다. */
.test-stage::before { content: ""; position: absolute; inset: 10px; pointer-events: none;
  background:
    linear-gradient(var(--color-text-muted), var(--color-text-muted)) top left / 14px 1px,
    linear-gradient(var(--color-text-muted), var(--color-text-muted)) top left / 1px 14px,
    linear-gradient(var(--color-text-muted), var(--color-text-muted)) top right / 14px 1px,
    linear-gradient(var(--color-text-muted), var(--color-text-muted)) top right / 1px 14px,
    linear-gradient(var(--color-text-muted), var(--color-text-muted)) bottom left / 14px 1px,
    linear-gradient(var(--color-text-muted), var(--color-text-muted)) bottom left / 1px 14px,
    linear-gradient(var(--color-text-muted), var(--color-text-muted)) bottom right / 14px 1px,
    linear-gradient(var(--color-text-muted), var(--color-text-muted)) bottom right / 1px 14px;
  background-repeat: no-repeat; opacity: .5; }
.test-stage.is-wait { background: var(--color-stage-wait); border-color: var(--color-stage-wait); }
.test-stage.is-go { background: var(--color-stage-go); border-color: var(--color-stage-go); }
.test-stage.is-wait::before, .test-stage.is-go::before { content: none; }
.test-stage.is-wait .stage-msg, .test-stage.is-go .stage-msg,
.test-stage.is-wait .stage-sub, .test-stage.is-go .stage-sub { color: var(--color-on-stage); }
.test-stage > .btn, .test-stage > .btn-secondary { position: relative; z-index: 1; }

/* 시작 전 화면(pre-start) — 명세 2026-08-12-prestart-spec.md.
   측정 시작 전에만 보인다(Start의 hidden을 따라간다). 도형은 전부 CSS — 이미지 자산 0. */
.stage-prestart { position: relative; z-index: 1; display: flex; flex-direction: column;
  align-items: center; gap: var(--space-3); margin-bottom: var(--space-4); }
.stage-prestart[hidden] { display: none; }
.stage-rival { margin: 0; color: var(--color-signal-text);
  font: 700 var(--text-md)/1.35 var(--font-sans); text-align: center; max-width: 30ch;
  letter-spacing: -.01em; }
.stage-best { margin: 0; color: var(--color-text-muted);
  font: 600 var(--text-xs)/1 var(--font-mono); letter-spacing: .04em; }

.stage-preview { display: flex; align-items: center; justify-content: center; gap: var(--space-3); }

/* 숫자가 보였다 가려지는 데모 — 이 게임이 실제로 하는 일이다.
   3.2초 주기: 보임 → 가려짐 → 쉼. 측정 전 화면이라 기록에 닿지 않는다(Start를 누르면 사라진다). */
@keyframes pv-flash {
  0%, 34% { opacity: 1; }
  40%, 88% { opacity: 0; }
  94%, 100% { opacity: 1; }
}
/* 침팬지 — 실제 타일 크기로. 켜진 상태의 재질(깊이·테두리 강조)까지 준다. */
.pv-tiles .pv-tile { width: clamp(52px, 15vw, 76px); aspect-ratio: 1; border-radius: var(--radius-md);
  background: var(--color-surface-raised); border: 2px solid var(--color-outline);
  box-shadow: 0 6px 14px var(--f1-socket);
  display: flex; align-items: center; justify-content: center; }
.pv-tiles .pv-tile span { color: var(--color-primary);
  font: 700 var(--text-xl)/1 var(--font-mono);
  animation: pv-flash 3.2s cubic-bezier(.4, 0, .2, 1) infinite; animation-delay: calc(var(--i) * 90ms); }
/* 숫자 기억 — 한 줄로 크게. 같은 데모(보였다 사라진다). */
.pv-digits { gap: var(--space-2); }
.pv-digits .pv-digit { min-width: clamp(30px, 9vw, 44px); padding: var(--space-2) 0;
  border-bottom: 3px solid var(--color-outline); display: flex; justify-content: center; }
.pv-digits .pv-digit span { color: var(--color-primary);
  font: 700 var(--text-2xl, var(--text-xl))/1 var(--font-mono);
  animation: pv-flash 3.2s cubic-bezier(.4, 0, .2, 1) infinite; animation-delay: calc(var(--i) * 90ms); }

/* 줄이기 신호 존중 — 깜빡임을 멈추고 숫자를 계속 보여준다(정보는 남기고 모션만 뺀다). */
@media (prefers-reduced-motion: reduce) {
  .pv-tiles .pv-tile span, .pv-digits .pv-digit span { animation: none; opacity: 1; }
}
/* 스테이지 아래 도구 줄 — 판 안에는 게임만. 왼쪽 난이도, 오른쪽 다시하기·소리.
   스테이지에 바짝 붙인다 — 컨트롤은 영향을 주는 대상 곁에(grouping, 2026-08-04). */
.stage-tools { display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); margin-top: var(--space-1); min-height: 40px; }
.stage-tools-side { display: flex; align-items: center; gap: var(--space-2); }
.stage-tools-side:last-child { margin-left: auto; }
.stage-tool { width: 40px; min-height: 40px; padding: 0; font-size: var(--text-lg);
  color: var(--color-text-muted); position: relative; }
@media (hover: hover) { .stage-tool:hover { color: var(--color-text); } }
/* 소리 끔 상태는 사선+흐림 (컬러 이모지 🔊는 흑백 글리프 통일 원칙에 어긋나 쓰지 않는다) */
.sound-toggle.is-off { opacity: .55; }
.sound-toggle.is-off::after { content: ''; position: absolute; left: 9px; right: 9px;
  top: 50%; height: 2px; background: currentColor; transform: rotate(-45deg); }
/* 소리 설정 패널 — ♪ 아래에 떠서 효과음·배경 음악을 각각 조절 */
.stage-tools-side { position: relative; }
.sound-panel { position: absolute; top: 44px; right: 0; z-index: 5;
  background: var(--color-surface); border: 1px solid var(--color-outline);
  border-radius: var(--radius-md); padding: var(--space-3); display: grid; gap: var(--space-2);
  box-shadow: var(--shadow-pop); }
/* 팝오버 등장 — 트리거(♪) 쪽에서 자라난다(공간적 연결). 닫힘은 즉답(비대칭 타이밍).
   @starting-style 미지원 브라우저는 지금처럼 즉시 표시(점진 향상). */
@media (prefers-reduced-motion: no-preference) {
  .sound-panel { transform-origin: top right;
    transition: opacity .16s ease-out, transform .16s ease-out; }
  @starting-style { .sound-panel { opacity: 0; transform: scale(.95); } }
}
.sound-row { display: grid; grid-template-columns: auto 64px 110px; align-items: center;
  gap: var(--space-2); font: 500 var(--text-xs)/1 var(--font-mono); color: var(--color-text);
  white-space: nowrap; cursor: pointer; }
.sound-row input[type="range"] { width: 110px; accent-color: var(--color-primary); }
.sound-row input[type="checkbox"] { accent-color: var(--color-primary); width: 16px; height: 16px; }

/* 에임 타깃 — 크기는 난이도가 인라인으로 정한다(보통 48px) */
.aim-target { position: absolute; width: 48px; height: 48px; border-radius: 50%;
  background: var(--color-primary); border: 2px solid var(--color-on-primary); cursor: crosshair; }

/* 난이도 선택 — 도구 줄 왼쪽에 산다. 데일리·종합 측정 중에는 아예 만들지 않는다(page.js). */
.mode-select { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.mode-btn { min-height: 36px; padding: 0 var(--space-3); border-radius: var(--radius-md);
  font: 600 var(--text-xs)/1 var(--font-mono); letter-spacing: .04em;
  background: none; border: 1px solid var(--color-outline); color: var(--color-text-muted); cursor: pointer; }
@media (hover: hover) { .mode-btn:hover { color: var(--color-text); border-color: var(--color-primary); } }
.mode-btn[aria-pressed="true"] { color: var(--color-signal-text); border-color: var(--color-primary);
  background: var(--color-bg); font-weight: 700; }

/* 격자(순서·색) */
/* 칸 크기는 src/js/lib/grid.js가 --cols/--tile로 정한다(SSOT).
   여기서 min-width로 따로 바닥을 깔면 트랙보다 타일이 커져 서로 겹친다 — 실제로 겪었다. */
.tile-grid { display: grid; gap: var(--space-2); margin: 0 auto;
  grid-template-columns: repeat(var(--cols, 3), var(--tile, 44px)); }
.tile { width: var(--tile, 44px); height: var(--tile, 44px); border-radius: var(--radius-md);
  background: var(--color-surface-raised); border: 1px solid var(--color-outline);
  cursor: pointer; position: relative; }
.tile.is-lit { background: var(--color-primary); border-color: var(--color-on-primary); }
@keyframes tile-pop { from { transform: scale(.82); } }
@keyframes tile-shake { 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
/* 정답 탭 손맛 — 얇은 링 하나가 퍼지고 끝(transform/opacity만 애니메이트, 무끊김 원칙).
   번쩍이는 색 반전 대신 미니멀한 파동으로 "맞았다"를 준다. */
@keyframes hit-ring { from { transform: scale(.92); opacity: .9; } to { transform: scale(1.18); opacity: 0; } }
.tile.is-hit { animation: tile-pop 160ms cubic-bezier(.34, 1.56, .64, 1); }
.tile.is-hit::before { content: ""; position: absolute; inset: -3px; border-radius: inherit;
  border: 2px solid var(--color-primary); pointer-events: none;
  animation: hit-ring 340ms ease-out forwards; }
/* 침팬지: 맞힌 칸은 조용히 물러난다 — 표식을 얹는 대신 무대에서 빠지는 쪽이 차분하다 */
.tile.is-done { opacity: .22; transition: opacity 160ms ease-out; }
.tile.is-answer { animation: tile-pop 120ms ease-out; }
.tile.is-wrong { animation: tile-shake 160ms ease-in-out; }
/* 정답 표식(✓) — 색만으로 알리지 않기 위한 접근성 장치. 톤은 낮춘다(번쩍임 금지). */
.tile.is-answer { outline: 2px solid var(--color-success); outline-offset: -2px; position: relative; }
.tile.is-answer::after { content: "✓"; position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center; color: var(--color-success); opacity: .9;
  font: 600 var(--text-sm)/1 var(--font-mono); }
.tile.is-wrong { outline: 2px solid var(--color-danger); outline-offset: -2px; }

/* ─── 침팬지 스테이지 연출(2026-08-03) — 판의 세 박자: 숫자 깔림·가림·판 통과.
   transform만 쓴다: 시간제 노출(0.65초)에서 opacity 연출은 숫자 판독 시간을 깎는다.
   깔림은 전 타일 동시 팝 — 순서대로 시차를 주면 순서 정보가 시간축으로 새서 과제가 쉬워진다(측정 동등성). */
/* 2차(같은 날): "티가 잘 안 난다"(사장님) — 전부 크고 길게. 1차의 소심한 수치(스케일 .86~1.07,
   170~320ms)는 44px 타일에서 안 읽혔다. 시간제 모드만 짧게 유지(판독 시간 보호). */
@media (prefers-reduced-motion: no-preference) {
  .tile.is-enter { animation: tile-enter 280ms cubic-bezier(.34, 1.56, .64, 1); }
  .tile-grid.is-timed .tile.is-enter { animation-duration: 120ms; }
  .tile.is-mask { animation: tile-mask 300ms ease-in-out; } /* 세로 블링크 — "닫혔다"가 보인다 */
  .tile-grid.is-clear { animation: grid-clear 420ms cubic-bezier(.2, .9, .3, 1.4); }
  .tile-grid.is-clear .tile.is-done { animation: tile-clear-pop 420ms ease-out; }
}
@keyframes tile-enter { from { transform: scale(.45); } 62% { transform: scale(1.12); } }
@keyframes tile-mask { 45% { transform: scaleY(.08); } }
@keyframes grid-clear { 30% { transform: translateY(-6px) scale(1.03); } 60% { transform: translateY(0) scale(.99); } }
@keyframes tile-clear-pop { 25% { opacity: .75; transform: scale(1.22); } 100% { opacity: .22; } }

/* ─── 타자 스테이지 — 한국 타자연습 정석 2줄 대응: 제시문 배너 + 바로 아래 보이는 입력줄.
   숨은 입력(1px·투명, Monkeytype식)은 한글 IME에서 공식 고장이라 폐기(research-2026-08-03-typing-ux.md).
   치는 글자가 입력줄에 그대로 보여 조용한 죽음이 구조적으로 불가능하다. */
.type-line { position: relative; font: 600 var(--text-lg)/1.8 var(--font-sans); max-width: 44ch;
  margin: var(--space-4) auto 0; padding: var(--space-3) var(--space-4);
  background: var(--color-surface-raised); border: 1px solid var(--color-outline);
  border-radius: var(--radius-md); text-align: left; user-select: none;
  color: var(--color-text-muted); }
.type-line .t-ok { color: var(--color-text); }
.type-line .t-bad { color: var(--color-danger); text-decoration: underline; text-underline-offset: 3px; }
/* IME 조합 중 글자 — 판정 전이지만 "입력이 들어오고 있다"를 즉시 보여준다 */
.type-line .t-composing { color: var(--color-text); border-bottom: 2px dotted var(--color-primary); }
/* 미끄러지는 캐럿 — 현재 글자 위치로 transition(프리미엄 감의 절반은 이 장치 하나).
   이동은 left/top이 아니라 transform으로 — 키 입력마다 움직이는 최고 빈도 지점이라
   레이아웃 속성 애니메이션은 금물(컴포지터 전용, 2026-08-04 애니메이션 감사). */
.type-caret { position: absolute; left: 0; top: 0; width: 2px; background: var(--color-primary); pointer-events: none; }
@media (prefers-reduced-motion: no-preference) {
  .type-caret { transition: transform 80ms ease-out; animation: caret-blink 1.1s step-end infinite; }
}
@keyframes caret-blink { 50% { opacity: .25; } }
/* 유령 페이스 캐럿 — 최고 기록 속도가 달리는 청록 바 + ▾ 표식(깜빡임 없음 — 진짜 캐럿과 구분).
   1차(회색 점선만)는 "버그 같다" 판정(사장님) — 표식 없는 유령은 유령이 아니라 얼룩이다. */
.type-ghost { background: none; border-left: 2px solid var(--color-data); width: 0; opacity: .6; animation: none; }
.type-ghost::before { content: "▾"; position: absolute; top: -1em; left: -0.34em;
  color: var(--color-data); font-size: .72em; line-height: 1; opacity: .95; }
@media (prefers-reduced-motion: no-preference) {
  .type-ghost { transition: transform .24s linear; }
}
/* 순위판 난이도 탭 — 난이도마다 별도 보드(사장님 2026-08-04). 누른 탭만 강조 */
.rank-tabs { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: var(--space-1) 0 var(--space-2); }
.rank-tab { font: 600 var(--text-xs)/1 var(--font-mono); padding: 4px 10px;
  border: 1px solid var(--color-outline); border-radius: var(--radius-sm);
  background: none; color: var(--color-text-muted); cursor: pointer;
  transition: border-color .15s ease, color .15s ease, transform .1s ease-out; }
@media (hover: hover) { .rank-tab:hover { color: var(--color-text); } }
.rank-tab:active { transform: scale(.97); }
.rank-tab[aria-pressed="true"] { border-color: var(--color-primary); color: var(--color-text); font-weight: 700; }

/* 허브의 게임별 순위판 그리드 — rank-box 부품 재사용, 폭 제한만 해제 */
.boards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: var(--space-3); margin-top: var(--space-3); }
.boards-grid .rank-box { margin-top: 0; max-width: none; }

/* 결과 타수-시간 그래프 — 이번 판 곡선 + 최고 기록 점선 */
.typing-graph { margin: var(--space-3) 0 0; }
.typing-graph svg { width: 100%; max-width: 320px; height: 64px; display: block; }
.typing-graph .g-pace { stroke: var(--color-data); stroke-width: 2; fill: none; }
.typing-graph .g-best { stroke: var(--color-outline); stroke-width: 1.5; stroke-dasharray: 5 4; }
.typing-graph figcaption { font: var(--text-xs)/1.5 var(--font-mono); color: var(--color-text-muted);
  margin-top: 2px; }

/* 입력줄 — 밑줄형(한컴 계열). 포커스는 밑줄 색으로 말한다(기본 outline도 유지). */
.type-input { display: block; width: 100%; max-width: 44ch; margin: var(--space-3) auto 0;
  padding: var(--space-2) 2px; font: 500 var(--text-lg)/1.5 var(--font-sans);
  color: var(--color-text); background: none; border: 0; border-radius: 0;
  border-bottom: 2px solid var(--color-outline); }
.type-input:focus { border-bottom-color: var(--color-primary); }
/* 다음 문장 미리보기 — 전환이 끊기지 않게 반 박자 먼저 보여준다 */
.type-next { font: var(--text-sm)/1.6 var(--font-sans); color: var(--color-text-muted);
  max-width: 44ch; margin: var(--space-3) auto 0; text-align: left; opacity: .65; }

/* 에임 명중 링 — 타깃이 사라진 자리에서 파동 하나 */
.hit-ring { position: absolute; border-radius: 50%; border: 2px solid var(--color-primary);
  pointer-events: none; animation: hit-ring 340ms ease-out forwards; }
.tile.is-lit::after { content: attr(data-step); position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--color-on-primary); font: 700 var(--text-md)/1 var(--font-mono); }

/* 입력 */
.field { display: flex; gap: var(--space-2); justify-content: center; flex-wrap: wrap; max-width: 100%; }
.field input { background: var(--color-bg); color: var(--color-text);
  border: 1px solid var(--color-outline); border-radius: var(--radius-md);
  min-height: 44px; padding: 0 var(--space-3);
  font: 700 var(--text-xl)/1 var(--font-mono); font-variant-numeric: tabular-nums;
  width: min(12ch, 100%); text-align: center; letter-spacing: .08em; }

/* 결과 판독부 */
#result { margin-top: var(--space-4); }
.readout { border-color: var(--color-outline); }
.result-value { font: 800 var(--text-readout)/1 var(--font-mono);
  font-variant-numeric: tabular-nums; letter-spacing: -.03em; margin: 0; }
.result-pct { color: var(--color-text-muted); margin: var(--space-2) 0 var(--space-3);
  font-size: var(--text-sm); }
.result-pct b { color: var(--color-data); font-family: var(--font-mono);
  font-variant-numeric: tabular-nums; }
.result-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: var(--space-4) 0 var(--space-3); }
/* 한 줄 판정 — 점수 밑의 펀치라인. 큰 숫자(고정폭) 다음에 오는 사람 말이라 산세리프로 구분한다. */
.verdict { font: 600 var(--text-md)/1.5 var(--font-sans); color: var(--color-text);
  margin: var(--space-2) 0 0; max-width: 52ch;
  white-space: pre-line; /* page.js가 문장 사이에 \n을 넣는다 — 문장 단위 두 줄 표시(사장님 지적: 중간 끊김 가독성) */ }
/* 상황 부제(도박·신기록 격려·재시도·새벽) — 티어 멘트를 대체하지 않고 아래 작은 줄로 얹는다 */
.verdict-sub { font: var(--text-sm)/1.5 var(--font-sans); color: var(--color-text-muted);
  margin: 4px 0 0; max-width: 52ch; }
/* 등급명 배지 — 판정 문장 위의 한 단어 해석층(신기록 .badge와 같은 칩 결, 색만 링크 계열로 구분) */
.tier-chip { display: inline-block; border: 1px solid var(--color-link); color: var(--color-link);
  border-radius: var(--radius-sm); margin: var(--space-2) 0 0; padding: 2px var(--space-2);
  font: 700 var(--text-xs)/1.4 var(--font-mono); letter-spacing: .1em; }
/* 한국어는 단어(어절) 단위로만 줄을 꺾는다 — 기본값은 "골든타/임"처럼 아무 글자에서나 자른다. */
:root:lang(ko) { word-break: keep-all; overflow-wrap: break-word; }
/* 데일리 리더보드 — 계기판 전광판. 순위·점수는 고정폭, 이름과 점수는 점선 리더로 잇는다.
   메달색(금=신호 앰버·은·동)은 Pro Max 리더보드 관례를 토큰으로 이식(--rank-*). */
.rank-box { margin-top: var(--space-4); border: 1px solid var(--color-outline);
  border-radius: var(--radius-lg); padding: var(--space-3) var(--space-4) var(--space-4);
  background: var(--color-surface); max-width: 38ch; }
.rank-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); }
.rank-title { margin: 0; font: 700 var(--text-xs)/1.6 var(--font-mono); color: var(--color-signal-text);
  text-transform: uppercase; letter-spacing: .08em; }
.rank-title a { color: inherit; text-decoration: none; }
@media (hover: hover) { .rank-title a:hover { text-decoration: underline; } }
.rank-more { display: inline-block; margin-top: var(--space-3);
  font: 600 var(--text-sm)/1.4 var(--font-mono); color: var(--color-link); text-decoration: none; }
@media (hover: hover) { .rank-more:hover { text-decoration: underline; } }
.rank-total { font: 600 var(--text-xs)/1.6 var(--font-mono); color: var(--color-text-muted);
  font-variant-numeric: tabular-nums; }
.rank-list { list-style: none; margin: var(--space-3) 0 0; padding: 0; }
.rank-list li { display: flex; align-items: baseline; gap: var(--space-2);
  padding: 6px 0; font: var(--text-sm)/1.5 var(--font-mono); font-variant-numeric: tabular-nums; }
.rank-list li + li { border-top: 1px solid var(--color-grid); }
.rank-no { min-width: 2ch; text-align: right; font-weight: 700; color: var(--color-text-muted); }
/* 닉네임은 전부 보인다 — 8자 제한(한글 모노폭 ≈ 16ch)이 18ch 안에 항상 들어온다.
   말줄임은 제한이 12자였던 시절의 옛 기록용 안전망일 뿐이다(사장님 "풀네임" 2026-08-03). */
.rank-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 18ch; }
.rank-list li i { flex: 1; border-bottom: 1px dotted var(--color-grid); transform: translateY(-4px); }
.rank-list li b { font-weight: 600; }
.rank-list li:nth-child(1) .rank-no, .rank-list li.is-first b { color: var(--rank-gold); }
.rank-list li:nth-child(2) .rank-no { color: var(--rank-silver); }
.rank-list li:nth-child(3) .rank-no { color: var(--rank-bronze); }
.rank-list li.is-ghost { color: var(--color-text-muted); opacity: .5; }
.rank-list li.is-ghost .rank-no { color: inherit; }
.rank-note { margin: var(--space-2) 0 0; font: var(--text-sm)/1.5 var(--font-sans); color: var(--color-text-muted); }
.rank-note.is-you { color: var(--color-signal-text); font: 700 var(--text-sm)/1.5 var(--font-mono); }
.rank-form { justify-content: flex-start; margin-top: var(--space-3); }
.home-rank { margin: var(--space-3) 0 var(--space-2); max-width: none; }
/* 행 등장 — 8px 떠오름 + 50ms 스태거(툴킷 모션 규칙: transform/opacity만·감속 이징·reduced-motion 존중) */
@media (prefers-reduced-motion: no-preference) {
  .rank-list li { animation: rank-in .4s cubic-bezier(.2, .7, .3, 1) backwards; }
  .rank-list li:nth-child(2) { animation-delay: .05s; }
  .rank-list li:nth-child(3) { animation-delay: .1s; }
  .rank-list li:nth-child(4) { animation-delay: .15s; }
  .rank-list li:nth-child(5) { animation-delay: .2s; }
}
@keyframes rank-in { from { opacity: 0; transform: translateY(8px); } }

/* ─── 결과 보상 연출(2026-08-03) — transform/opacity만, reduced-motion 존중 ─── */
#result { position: relative; }
.rb-mascot { position: absolute; top: var(--space-3); right: var(--space-4);
  width: 72px; height: 72px; pointer-events: none; } /* 얼굴 마크판 — 풀바디는 AI 아트로 재도전(사장님 퀄 판정) */
.rb-mascot svg { width: 100%; height: 100%; display: block; }
.rb-mascot[data-mood="smug"] svg { transform: rotate(-6deg); }
@media (prefers-reduced-motion: no-preference) {
  /* 1차는 "빨라서 효과가 있는지도 모르겠다"(사장님) — 전부 길고 크게.
     2차(같은 날): 등장 후에도 상시 미세 모션 — 멈춘 마스코트는 스티커지 캐릭터가 아니다. */
  .rb-mascot svg { transform-origin: 50% 92%; } /* 스쿼시&스트레치의 축 = 발바닥 */
  .rb-mascot .m-eyes { transform-box: fill-box; transform-origin: 50% 50%;
    animation: mascot-blink 3.4s ease-in-out infinite; } /* 깜빡임 — 살아 있음의 최소 신호 */
  .rb-mascot[data-mood="wow"] svg { animation: mascot-pop .8s cubic-bezier(.2, .9, .3, 1.45), mascot-bounce 1.7s .9s cubic-bezier(.4, 0, .3, 1) infinite; }
  .rb-mascot[data-mood="wow"] .m-banana { transform-box: fill-box; transform-origin: 50% 95%;
    animation: banana-wave 1s .35s cubic-bezier(.4, 0, .3, 1.3) 3; }
  .rb-mascot[data-mood="smug"] svg { animation: mascot-tilt .7s ease-out, mascot-sway 3.2s .8s ease-in-out infinite; }
  .rb-mascot[data-mood="base"] svg { animation: mascot-breathe 3s ease-in-out infinite; }
  /* 결과 요소 순차 등장 — 14px 떠오름, 스태거 ≤6 */
  #result.is-reveal > * { animation: result-rise .5s cubic-bezier(.2, .7, .3, 1) backwards; }
  #result.is-reveal > :nth-child(2) { animation-delay: .07s; }
  #result.is-reveal > :nth-child(3) { animation-delay: .14s; }
  #result.is-reveal > :nth-child(4) { animation-delay: .21s; }
  #result.is-reveal > :nth-child(5) { animation-delay: .28s; }
  #result.is-reveal > :nth-child(6) { animation-delay: .35s; }
  .badge { animation: badge-pop .65s cubic-bezier(.2, .9, .3, 1.6); }
}
@keyframes mascot-pop { 0% { transform: scale(.3); } 55% { transform: scale(1.25); } 100% { transform: scale(1); } }
@keyframes mascot-tilt { from { transform: rotate(14deg); } to { transform: rotate(-6deg); } }
/* 스쿼시&스트레치 바운스 — 착지에서 눌리고 뜰 때 늘어난다(애니메이션 기본기, 밋밋한 상하이동 금지) */
@keyframes mascot-bounce {
  0%, 100% { transform: translateY(0) scale(1, 1); }
  28% { transform: translateY(-9px) scale(.97, 1.05); }
  46% { transform: translateY(0) scale(1.07, .9); }
  62% { transform: translateY(-4px) scale(.99, 1.02); }
  76% { transform: translateY(0) scale(1.03, .96); }
}
@keyframes mascot-sway { 0%, 100% { transform: rotate(-7deg) translateX(0); } 50% { transform: rotate(-1deg) translateX(1.5px); } }
@keyframes mascot-breathe { 0%, 100% { transform: translateY(0) scale(1); } 50% { transform: translateY(-2.5px) scale(1.025, 1.035); } }
@keyframes banana-wave { 0%, 100% { transform: rotate(0); } 45% { transform: rotate(-26deg); } 70% { transform: rotate(6deg); } }
@keyframes mascot-blink { 0%, 91%, 100% { transform: scaleY(1); } 94.5% { transform: scaleY(.08); } 98% { transform: scaleY(1); } }
@keyframes result-rise { from { opacity: 0; transform: translateY(14px); } }
@keyframes badge-pop { from { transform: scale(.3); } 55% { transform: scale(1.3); } to { transform: scale(1); } }
/* 신기록 스파크 — 앰버 점 12개가 크게 흩어지며 사라진다(1회성, blur 없음) */
#result-value { position: relative; }
.spark-burst { position: absolute; left: 1.2em; top: .5em; width: 0; height: 0; pointer-events: none; }
.spark-burst i { position: absolute; width: 9px; height: 9px; border-radius: 50%;
  background: var(--color-primary); animation: spark-fly 1.05s cubic-bezier(.2, .7, .4, 1) forwards; }
@keyframes spark-fly { from { opacity: 1; transform: translate(0, 0) scale(1.1); }
  to { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(.15); } }
@media (max-width: 520px) { .rb-mascot { width: 56px; height: 56px; } }
/* 등급 구간 — 분포에서 유도한 값이라 백분위가 있을 때만 나온다.
   색만으로 뜻을 전하지 않게 글자를 함께 쓴다. */
.band { display: inline-block; vertical-align: middle; margin-left: var(--space-2);
  border: 1px solid var(--color-outline); border-radius: var(--radius-sm);
  padding: 2px var(--space-2); font: 700 var(--text-xs)/1.4 var(--font-mono);
  letter-spacing: .08em; color: var(--color-text-muted); cursor: help; }
.band-top, .band-strong { color: var(--color-data); border-color: var(--color-data); }
@keyframes stamp { from { transform: scale(1.7); opacity: 0; } }
.badge { animation: stamp 220ms ease-out; display: inline-block; vertical-align: middle; border: 1px solid var(--color-success);
  color: var(--color-success); border-radius: var(--radius-sm); margin-left: var(--space-2);
  padding: 2px var(--space-2); font: 700 var(--text-xs)/1.4 var(--font-mono); letter-spacing: .1em; }
.meta-line { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.history { list-style: none; padding: 0; margin: 0; font: 400 var(--text-sm)/1 var(--font-mono);
  font-variant-numeric: tabular-nums; color: var(--color-text-muted); }
.history li { padding: var(--space-2) 0; border-bottom: 1px solid var(--color-outline); }

/* 라운드 상세 — 중앙값이 어디서 나왔는지 */
.rounds { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  margin: var(--space-3) 0 var(--space-2); }
.rounds-label { font: 600 var(--text-xs)/1 var(--font-mono); letter-spacing: .16em;
  text-transform: uppercase; color: var(--color-text-muted); }
.round-chip { font: 500 var(--text-xs)/1 var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--color-text-muted); border: 1px solid var(--color-outline);
  border-radius: var(--radius-sm); padding: var(--space-1) var(--space-2); }
.round-chip.is-median { color: var(--color-text); border-color: var(--color-primary); font-weight: 700; }
.round-spread { font: 500 var(--text-xs)/1 var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--color-text-muted); margin-left: auto; }

/* 순위 행 기기 표시 — 터치/마우스 유불리 맥락(사장님 2026-08-04). 옛 기록은 표시 없음 */
.rank-dev { margin-left: 6px; flex: none; display: inline-flex; align-items: center; color: var(--color-text-muted); opacity: .75; cursor: help; }
.dev-ic { vertical-align: -.12em; } /* 부제 등 텍스트 흐름 속 정렬 — 보드 행은 flex라 무해 */

/* 단어 기억 — 단어는 판독 대상이라 크게, 판정 버튼 2개는 엄지 폭으로 */
.stage-msg.is-word { font-size: var(--text-xl); letter-spacing: .01em; }
.verbal-btns { display: flex; gap: var(--space-3); justify-content: center; }
.verbal-btns .btn { min-width: 128px; }

/* 숫자 기억 오답 대조 — 정답/내 입력 겹줄, 틀린 자리만 빨간 취소선 */
.digit-diff { display: inline-grid; grid-template-columns: auto auto;
  gap: 2px var(--space-3); align-items: baseline; text-align: left; margin-top: var(--space-1); }
.digit-diff-label { font: 600 var(--text-xs)/1.4 var(--font-mono); letter-spacing: .12em;
  text-transform: uppercase; color: var(--color-text-muted); }
.digit-diff-digits { font: 700 var(--text-md)/1.4 var(--font-mono); letter-spacing: .14em;
  font-variant-numeric: tabular-nums; color: var(--color-text); }
.digit-diff-digits .is-off { color: var(--color-danger);
  text-decoration: line-through; text-decoration-thickness: 2px; }

/* 다음 테스트 고리 */
.next-up { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  margin: var(--space-4) 0 0; padding-top: var(--space-3); border-top: 1px solid var(--color-outline); }
.next-up .eyebrow { margin: 0; }
.next-link { text-decoration: none !important; }

/* 홈 — 내 기록 */
#records { margin-top: var(--space-6); }
.records-head { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; }
.records-head h2 { margin: 0; }
.records-streak { font: 600 var(--text-xs)/1 var(--font-mono); letter-spacing: .1em;
  text-transform: uppercase; color: var(--color-signal-text); margin: 0; }
.records-grid { list-style: none; padding: 0; margin: var(--space-3) 0 var(--space-2);
  display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--space-2); }
.record { display: flex; flex-direction: column; gap: var(--space-1);
  border: 1px solid var(--color-outline); border-radius: var(--radius-md);
  padding: var(--space-3); color: var(--color-text); }
@media (hover: hover) { .record:hover { border-color: var(--color-primary); text-decoration: none; } }
.record-name { font-size: var(--text-sm); color: var(--color-text-muted); }
.record-value { font: 700 var(--text-lg)/1 var(--font-mono); font-variant-numeric: tabular-nums; }
.record-value.is-empty { color: var(--color-text-muted); font-size: var(--text-sm); font-weight: 400; }

/* 시그니처: 분포 곡선 — 결과 화면의 주인공답게 굵고 또렷하게(2026-08-03 개편).
   창 크기가 바뀌어 SVG가 늘어나도 선 굵기는 유지된다(vector-effect). */
.curve-wrap { margin: var(--space-3) 0 var(--space-2); }
.curve { width: 100%; height: 132px; display: block; }
.curve-line, .curve-axis, .curve-tick, .curve-you { vector-effect: non-scaling-stroke; }
.curve-line { fill: none; stroke: var(--color-data); stroke-width: 2.5; stroke-linejoin: round; }
.curve-area { fill: var(--color-data-fill); stroke: none; }
.curve-axis { stroke: var(--color-outline); stroke-width: 1; }
.curve-tick { stroke: var(--color-text-muted); stroke-width: 1.5; }
.curve-dot { fill: var(--color-data); opacity: .8; }
.curve-you { stroke: var(--color-primary); stroke-width: 2.5; }
.curve-you-dot { fill: var(--color-primary); stroke: var(--color-surface); stroke-width: 2; }
.curve-you-label, .curve-label { fill: var(--color-text-muted);
  font: 700 11px var(--font-mono); letter-spacing: .08em; text-transform: uppercase; }
.curve-you-label { fill: var(--color-primary); }
.curve-caption { color: var(--color-text-muted); font-size: var(--text-xs);
  font-family: var(--font-mono); margin: 0; }

/* 본문 아티클 */
article { margin-top: var(--space-6); border-top: 1px solid var(--color-outline); padding-top: var(--space-4); }
article ul { padding-left: var(--space-4); }
/* 산문 목록 — article 밖(홈 등)에서도 아티클과 같은 들여쓰기·간격을 쓴다 */
.prose-list { padding-left: var(--space-4); color: var(--color-text-muted); }
.prose-list li + li, .prose-list ul { margin-top: var(--space-2); }
article h2:first-of-type { margin-top: var(--space-3); }

.lives { font-size: var(--text-md); }

/* 도전장 — 스테이지 배너·대결 비교·보내기 박스 (명세: 2026-08-04-duel-spec.md) */
.duel-banner { border: 1px solid var(--color-outline); border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-lg); background: var(--color-surface);
  padding: var(--space-3) var(--space-4); margin-bottom: var(--space-3);
  display: flex; flex-direction: column; gap: var(--space-1); }
.duel-banner .eyebrow { margin: 0; }
.duel-banner b { font: 700 var(--text-lg)/1.5 var(--font-mono); }
.duel-banner .muted { margin: 0; font-size: var(--text-sm); }

.duel-box { border: 1px solid var(--color-outline); border-radius: var(--radius-lg);
  background: var(--color-surface); padding: var(--space-4); margin-bottom: var(--space-4);
  text-align: center; }
.duel-stamp { margin: 0 0 var(--space-3); font: 800 var(--text-hero)/1.1 var(--font-mono);
  letter-spacing: .12em; text-transform: uppercase; }
.duel-stamp.is-win { color: var(--color-success); }
.duel-stamp.is-lose { color: var(--color-danger); }
.duel-stamp.is-draw { color: var(--color-text-muted); }
@media (prefers-reduced-motion: no-preference) {
  /* 도장이 위에서 크게 찍힌다 — 오버슈트로 눌린 뒤 제자리(모션 규칙: 처음부터 크게) */
  .duel-stamp { animation: duel-stamp .45s cubic-bezier(.2, 1.55, .4, 1) both; }
}
@keyframes duel-stamp { 0% { transform: scale(2.4) rotate(-6deg); opacity: 0; }
  62% { transform: scale(.94) rotate(1deg); opacity: 1; } 100% { transform: scale(1) rotate(0deg); } }
.duel-rows { display: flex; flex-direction: column; gap: var(--space-2); max-width: 26ch; margin: 0 auto; }
.duel-row { display: flex; justify-content: space-between; gap: var(--space-3); margin: 0;
  font: 600 var(--text-md)/1.5 var(--font-mono); color: var(--color-text-muted); }
.duel-row b { font-variant-numeric: tabular-nums; }
.duel-row.is-ahead { color: var(--color-text); }
.duel-row.is-ahead b { color: var(--color-success); }
.duel-more { display: inline-block; margin-top: var(--space-3);
  font: 600 var(--text-sm)/1.4 var(--font-mono); color: var(--color-link); text-decoration: none; }
@media (hover: hover) { .duel-more:hover { text-decoration: underline; } }

.duel-send { margin-top: var(--space-4); border: 1px solid var(--color-outline);
  border-radius: var(--radius-lg); padding: var(--space-3) var(--space-4) var(--space-4);
  background: var(--color-surface); max-width: 38ch; }
.duel-send-title { margin: 0; font: 700 var(--text-xs)/1.6 var(--font-mono);
  color: var(--color-signal-text); text-transform: uppercase; letter-spacing: .08em; }
.duel-send .muted { margin: var(--space-1) 0 var(--space-3); font-size: var(--text-sm); }
.duel-send-row { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.btn-kakao { background: var(--brand-kakao); color: var(--brand-kakao-text); }
.btn-kakao svg { width: 18px; height: 18px; flex: none; }
@media (hover: hover) { .btn-kakao:hover { filter: brightness(.96); } }
.duel-send-row input { flex: 1 1 12ch; min-width: 0; }
.duel-send-note { display: block; margin-top: var(--space-2);
  font: 600 var(--text-sm)/1.5 var(--font-mono); color: var(--color-success); }
.duel-rematch-go { align-self: flex-start; margin-top: var(--space-2); }

/* F1 변형 — 신호등 5등(점등=빨강). 전환 금지: 소등이 측정 자극이다 */
.f1-lights { display: flex; gap: var(--space-2); justify-content: center; margin-bottom: var(--space-3); }
.f1-light { width: clamp(28px, 8vw, 48px); aspect-ratio: 1; border-radius: 50%;
  background: var(--color-bg); border: 2px solid var(--color-outline); }
.f1-light.is-on { background: var(--color-danger); border-color: var(--color-danger); }

/* F1 변형 스테이지 — 야간 그리드. 색 전환 금지 원칙 그대로(소등이 측정 자극). */
.f1-stage { background: var(--f1-track); border-color: var(--f1-gantry); }
.f1-stage .stage-msg { color: var(--f1-text); }
.f1-stage .stage-sub { color: var(--f1-text); opacity: .55; }
/* 체커 스트립 — 스테이지 하단(코너 마크 ::before와 공존하도록 ::after 사용) */
.f1-stage::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 14px;
  background: repeating-conic-gradient(var(--f1-check) 0% 25%, transparent 0% 50%) 0 0 / 14px 14px;
  pointer-events: none; }
/* 신호등 거치대 — 하우징에 담긴 5등. 켜지면 레이싱 레드 + 글로우(1차부터 크게) */
.f1-stage .f1-lights { background: var(--f1-gantry); border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4); gap: var(--space-3); }
.f1-stage .f1-light { width: clamp(34px, 9vw, 58px); background: var(--f1-light-off); border: 0; }
.f1-stage .f1-light.is-on { background: var(--f1-red);
  box-shadow: 0 0 22px 6px var(--f1-red-glow), inset 0 0 10px 2px var(--f1-red-glow); }

/* 홈 변형 카드 — 세트(8종) 밖의 테마 변형 진입로. F1 야간 룩, v6 확정(머신 실루엣+광 트레일).
   v1~v5 불꽃 계열 규칙은 2026-08-04 애니메이션 감사에서 삭제(죽은 규칙 정리). */
.variant-card { display: block; margin-top: var(--space-3); text-decoration: none;
  position: relative; overflow: visible; }
.variant-body { display: flex; align-items: center; gap: var(--space-3); position: relative;
  padding: var(--space-3) var(--space-4); padding-right: 200px; background: var(--f1-track);
  border-radius: var(--radius-lg); overflow: hidden; }
.variant-card .vlights { display: flex; gap: 6px; flex: none; }
.variant-card .vlights span { width: 14px; height: 14px; border-radius: 50%;
  background: var(--f1-red); box-shadow: 0 0 8px 2px var(--f1-red-glow); }
.variant-card b { color: var(--f1-text); font: 700 var(--text-md)/1.4 var(--font-sans); display: block; }
.variant-card .variant-sub { color: var(--f1-text); opacity: .6; font: 500 var(--text-sm)/1.5 var(--font-sans); }
.variant-card .eyebrow { margin: 0; }
@media (hover: hover) { .variant-card:hover b { text-decoration: underline; } }

/* 데일리 완료 카드 — 연속 출석 표시 + "다음 추천"(별개 행동 — 도전은 하루 한 게임) */
.daily-streak { font-weight: 700; }
.daily-upnext-label { display: block; font: 600 var(--text-xs)/1.6 var(--font-mono);
  color: var(--color-text-muted); text-transform: uppercase; letter-spacing: .08em; }
.daily-cta .daily-upnext { text-decoration: none; }
div.daily-card { cursor: default; }

/* 데일리 완료 카드 CTA — 라벨/버튼/카운트다운을 세로 스택으로(인라인 흐름이면 좁은 화면에서
   카운트다운이 버튼 옆에 붙어 두 동강 난다 — 사장님 모바일 실측 2026-08-04) */
.daily-cta { display: flex; flex-direction: column; align-items: flex-end;
  justify-content: center; gap: var(--space-1); }
@media (max-width: 520px) { .daily-cta { align-items: flex-start; margin-top: var(--space-2); } }

/* F1 5쌍 갠트리 — 기둥(등 2개)이 한 단위로 켜진다(실제 절차의 "five pairs") */
.f1-stage .f1-col { display: flex; flex-direction: column; gap: 6px; }
.f1-stage .f1-col .f1-light { width: clamp(26px, 7vw, 44px); }
.f1-stage .f1-col.is-on .f1-light { background: var(--f1-red);
  box-shadow: 0 0 18px 5px var(--f1-red-glow), inset 0 0 8px 2px var(--f1-red-glow); }
/* 소등 순간 대형 GO — 즉시 등장(전환 금지 원칙 유지), 초록 글로우만 */
.f1-stage .stage-msg.is-go-big { font-size: var(--text-hero); font-weight: 800;
  color: var(--color-stage-go); text-shadow: 0 0 28px var(--color-stage-go); letter-spacing: .04em; }

/* F1 페이지 머리 — 레이싱 레드 바 + 체커 깃발 칩(본문 결은 그대로, 머리만 테마) */
.f1-title { border-left: 6px solid var(--f1-red); padding-left: var(--space-3); }
.f1-title::after { content: ""; display: inline-block; width: 22px; height: 15px; margin-left: 10px;
  background: repeating-conic-gradient(var(--color-text) 0% 25%, transparent 0% 50%) 0 0 / 8px 8px;
  border: 1px solid var(--color-outline); }
/* F1 스테이지의 버튼 = 레이싱 레드 + 글로우(야간 스테이지 위 주황 이질감 제거) */
.f1-stage .btn { background: var(--f1-red); color: var(--f1-text);
  box-shadow: 0 0 18px 2px var(--f1-red-glow); }

/* F1 신호등 실물감 — 등이 소켓에 파묻히고(안쪽 그림자), 켜지면 전구처럼 중심이 뜨겁다 */
.f1-stage .f1-lights { border-radius: 14px;
  box-shadow: inset 0 -5px 12px var(--f1-socket), 0 8px 22px var(--f1-socket); }
.f1-stage .f1-col .f1-light {
  background: radial-gradient(circle at 50% 32%, var(--f1-light-off), var(--f1-gantry) 78%);
  box-shadow: inset 0 3px 7px var(--f1-socket); }
.f1-stage .f1-col.is-on .f1-light {
  background: radial-gradient(circle at 50% 32%, var(--f1-red-hot), var(--f1-red) 72%);
  box-shadow: 0 0 18px 5px var(--f1-red-glow), inset 0 2px 5px var(--f1-socket); }

/* 카드 아트 — 광 트레일 3줄 + 머신 실루엣. SVG 그라디언트 색은 아래 stop 클래스가 SSOT */
.variant-flames { position: absolute; right: 6px; bottom: 4px; width: 320px; height: auto;
  z-index: 1; pointer-events: none; }
.vf-stop-red { stop-color: var(--f1-red); }
.vf-stop-org { stop-color: var(--f1-flame); }
.vf-stop-hot { stop-color: var(--f1-flame-hot); }
.f1-wheel { fill: var(--f1-light-off); }
@media (prefers-reduced-motion: no-preference) {
  .f1-streaks rect { animation: f1-streak 1.4s ease-in-out infinite; }
  .f1-streaks rect:nth-child(2) { animation-delay: .45s; }
  .f1-streaks rect:nth-child(3) { animation-delay: .9s; }
  .f1-car { animation: f1-bob 1.1s ease-in-out infinite alternate; }
}
@keyframes f1-streak { 0% { transform: translateX(-26px); opacity: 0; } 35% { opacity: 1; } 100% { transform: translateX(16px); opacity: 0; } }
@keyframes f1-bob { from { transform: translateY(0); } to { transform: translateY(-1.5px); } }
@media (max-width: 640px) {
  .variant-body { flex-direction: column; align-items: flex-start; gap: var(--space-2);
    padding-right: var(--space-4); padding-bottom: 78px; }
  .variant-flames { width: 210px; right: 8px; bottom: 8px; }
}
