/* 미완성 퍼즐 : 스무 살의 조각 — 케이주 플로우
   좌표계: 디자인 원본 500 x 1080px.
   #viewport(fixed, 100%, max 500px)가 컨테이너. 1 디자인px = var(--u) = 0.2cqw.
   모든 수치는 calc(디자인px * var(--u))로 작성 — Figma px 값 그대로 유지.
   세로 부족 시 스테이지 가운데 기준 상하 대칭 크롭: --crop (순수 CSS, JS 없음). */

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  background: #111;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  font-family: "Pretendard Variable", Pretendard, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
  word-break: keep-all; /* 한국어 어절 단위 줄바꿈 — 전역 기본 */
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

#viewport {
  --u: 0.2cqw; /* 스테이지 밖(개발 바)에서도 같은 단위를 쓰기 위해 */
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 500px;
  height: 100%;
  overflow: hidden;
  container-type: size;
  touch-action: manipulation;
}

/* 스테이지 = 화면 전체(100cqw x 100cqh).
   좌표계(프레임) = 500 x --frame-h. 아트 박스는 --crop 만큼 위로 올라가 가운데 기준 상하 크롭.
   (세로가 남으면 음수 크롭 = 레터박스)

   배경 아트는 두 종류다:
   - 방/락커룸/연습실/골목길/버스/옥상 = 500 x 1500 (프레임보다 210씩 김 → .bg-art-tall)
   - 인트로/아웃트로/글리치 등 = 500 x 1080 (프레임과 같음)
   긴 배경은 프레임 가운데에 맞춰 위아래로 흘러넘친다. main.js가 현재 씬의 배경 종류에 따라
   #stage에 .bg-tall을 토글하고, 그 값(--bg-bleed)으로 검정 그라데이션 위치와 상하단 UI 기준을 잡는다. */
#stage {
  --u: 0.2cqw;                /* 1 디자인px */
  --frame-h: 1080;            /* 시안 프레임(좌표계) 세로 디자인px */
  --bg-h: 1500;               /* 가장 긴 배경 아트 세로 디자인px */
  --bg-over: calc((var(--bg-h) - var(--frame-h)) * var(--u) / 2);  /* 긴 배경이 프레임 위/아래로 넘치는 양 */
  --bg-bleed: 0px;            /* 지금 켜져 있는 배경이 실제로 넘치는 양 (.bg-tall에서 --bg-over) */
  --crop: calc((var(--frame-h) * var(--u) - 100cqh) / 2);
  /* UI 보정: 아트가 화면 밖으로 나갔으면(크롭) 그만큼 UI를 안으로 되돌리고,
     아트가 프레임 밖까지 이어지면(긴 배경) 그만큼 UI를 화면 끝까지 내보낸다.
     짧은 배경(bleed 0)일 땐 예전과 같은 max(0px, --crop). */
  --ui-inset: max(calc(-1 * var(--bg-bleed)), var(--crop));
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #000; /* 아트보다 화면이 길면 검은 레터박스 */
}
#stage.bg-tall { --bg-bleed: var(--bg-over); }

/* ---------- 배경 레이어 (--bg-h 디자인px — 프레임 가운데 정렬) ---------- */
#bg-layer {
  position: absolute;
  left: 0; right: 0;
  top: calc(-1 * var(--crop) - var(--bg-over));
  height: calc(var(--bg-h) * var(--u));
  overflow: hidden; /* 흔들림 연출로 확대된 배경이 레터박스 밖으로 새지 않게 */
}
/* 레터박스일 때(아트 아래위로 여백이 남을 때) 아트 상하단을 검정으로 자연스럽게 페이드.
   기준선은 지금 켜져 있는 배경의 실제 끝 — 긴 배경이면 #bg-layer 끝, 짧은 배경이면 프레임 끝.
   밴드 높이 = min(50px, 레터박스 크기) — 크롭 상황에선 0이 되어 안 보임 */
#bg-layer::before,
#bg-layer::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: clamp(0px, calc(-1 * (var(--crop) + var(--bg-bleed))), calc(50 * var(--u)));
  z-index: 5;
  pointer-events: none;
}
#bg-layer::before { top: calc(var(--bg-over) - var(--bg-bleed)); background: linear-gradient(#000, transparent); }
#bg-layer::after { bottom: calc(var(--bg-over) - var(--bg-bleed)); background: linear-gradient(transparent, #000); }
/* 기본은 프레임 높이(1080) 아트 — #bg-layer 가운데에 놓인다.
   .bg-art-tall(1500 아트)과 딤/암전 같은 전면 오버레이만 레이어 전체를 채운다. */
#bg-layer .bg {
  position: absolute;
  left: 0; right: 0;
  top: var(--bg-over);
  width: 100%;
  height: calc(var(--frame-h) * var(--u));
  object-fit: cover;
  display: none;
}
#bg-layer .bg.bg-art-tall,
#bg-layer .bg.bg-overlay { top: 0; height: 100%; }
#bg-layer .bg.on { display: block; }

#bg-white { background: #fff; }

/* 눈꺼풀 원형 마스크 — --eye가 세로 반지름(0 = 완전히 감음) */
@property --eye {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}
#bg-vignette {
  --eye: calc(179 * var(--u));
  background:
    radial-gradient(ellipse calc(315 * var(--u)) var(--eye) at 50% 50%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 1) 100%),
    rgba(0, 0, 0, 0.5);
}
/* 눈 감김 — 앞 2번은 톡톡 빠르게, 마지막 한 번만 스르륵 천천히 감긴다 */
#bg-vignette.blink { animation: blink 4.2s linear forwards; }
@keyframes blink {
  0%, 12%   { --eye: calc(179 * var(--u)); }   /* 깜빡임 1 — 감김 84ms */
  14%, 16%  { --eye: 0px; }
  18%, 30%  { --eye: calc(179 * var(--u)); }   /* 깜빡임 2 */
  32%, 34%  { --eye: 0px; }
  36%       { --eye: calc(179 * var(--u)); }
  50%       { --eye: calc(179 * var(--u)); animation-timing-function: ease-in-out; }
  88%, 100% { --eye: 0px; }                    /* 마지막만 스르륵 1.6s */
}

/* 눈이 완전히 감기는 구간에서 문구도 같이 사라짐 (blink와 같은 4.2s 타임라인) */
.scene[data-scene="intro-sleep"] .caption-center {
  animation: sleep-caption-out 4.2s ease-in forwards;
}
@keyframes sleep-caption-out {
  0%, 42%   { opacity: 1; }
  72%, 100% { opacity: 0; }  /* 눈이 다 감기기(88%) 전에 거의 사라져 있게 */
}

/* 잠들며 배경이 살짝 흔들리며 흐려짐 */
#bg-layer .bg.sleep { animation: sleep-daze 4.2s ease-in forwards; }
@keyframes sleep-daze {
  0%   { filter: blur(0px); transform: translate(0, 0) scale(1); }
  25%  { filter: blur(calc(2 * var(--u))); transform: translate(calc(-3 * var(--u)), calc(2 * var(--u))) scale(1.01); }
  50%  { filter: blur(calc(5 * var(--u))); transform: translate(calc(4 * var(--u)), calc(-3 * var(--u))) scale(1.02); }
  75%  { filter: blur(calc(9 * var(--u))); transform: translate(calc(-4 * var(--u)), calc(3 * var(--u))) scale(1.03); }
  100% { filter: blur(calc(14 * var(--u))); transform: translate(0, 0) scale(1.04); }
}

#bg-dim { background: rgba(0, 0, 0, 0.5); }
#bg-dim.blur { backdrop-filter: blur(calc(10 * var(--u))); }

/* ---------- 화면 레이어 ----------
   #art-box = 시안 프레임 박스. 그 안의 모든 좌표는 디자인 500×1080 그대로.
   (#bg-layer는 긴 배경 때문에 이보다 위아래로 --bg-over씩 크다.) */
#art-box {
  position: absolute;
  left: 0; right: 0;
  top: calc(-1 * var(--crop));
  height: calc(var(--frame-h) * var(--u));
}
.scene { position: absolute; inset: 0; display: none; }
/* 게임 씬(인트로~아웃트로 쪽지)만 텍스트 선택·이미지 드래그·길게 눌러 나오는 메뉴 차단.
   랜딩·결과는 예외. 퍼즐 조각은 자체 포인터 드래그라 이 규칙에 영향받지 않는다. */
#scene-layer {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
#scene-layer img { -webkit-user-drag: none; }
.scene-scroll {
  -webkit-user-select: auto;
  user-select: auto;
  -webkit-touch-callout: default;
}
.scene-scroll img { -webkit-user-drag: auto; }
.scene.on { display: block; }

/* ---------- 헤더 ---------- */
#hud {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: calc(65 * var(--u));
  background: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(calc(20 * var(--u)));
  z-index: 30;
}
.hud-logo {
  position: absolute;
  left: calc(194.84 * var(--u)); top: calc(20.38 * var(--u));
  width: calc(110 * var(--u)); height: calc(23.65 * var(--u));
  object-fit: cover;
}
/* 버튼은 터치 영역(56x65), 아이콘은 원본 크기 그대로 가운데 */
.hud-back,
.hud-sound {
  position: absolute;
  top: 0;
  width: calc(62 * var(--u));
  height: calc(62 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
}
.hud-sound {
  right: 0;
}

.hud-back img { width: calc(42 * var(--u)); height: calc(42 * var(--u)); display: block; }
.hud-sound img { width: calc(33 * var(--u)); height: calc(28 * var(--u)); display: block; }

/* ---------- 독백 말풍선 ---------- */
/* intro-mv 말풍선 — 배경이 긴 아트에서 영상으로 바뀌어 --ui-inset 이 0(프레임 하단)이 됐다.
   긴 배경 씬들은 실제로 --crop(화면 하단)에 붙으므로 같은 기준을 준다 */
.scene[data-scene="intro-mv"] .bubble-wrap { bottom: var(--crop); }

/* intro-mv 배경 영상 — 프레임 전체를 덮고 남는 자리는 스테이지 검정이 받는다 */
.mv-bg {
  position: absolute;
  top: calc(65 * var(--u));   /* 헤더(#hud) 높이 */
  left: 0;
  width: 100%;
  height: calc(100% - 65 * var(--u));
  object-fit: contain;
  background: #000;
}

.bubble-wrap {
  position: absolute;
  left: 0; right: 0;
  bottom: var(--ui-inset); /* 레터박스=아트 하단, 크롭=화면 하단 */
  padding: 0 calc(30 * var(--u)) calc(40 * var(--u));
  transition: opacity 0.4s ease;
  z-index: 6; /* 배경 하단 페이드(5) 위 */
}
/* 순서 연출 대기 상태 (먼저 나올 쪽이 끝날 때까지 숨김) */
.bubble-wrap.hold,
.caption-center.hold { opacity: 0; }
.caption-center { transition: opacity 0.4s ease; }
.bubble {
  height: calc(140 * var(--u));
  background: #fff;
  border: calc(2 * var(--u)) solid #1b2b38;
  filter: drop-shadow(0 calc(4 * var(--u)) 0 #1b2b38);
  opacity: 0.9;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(8 * var(--u));
  padding: calc(32 * var(--u)) calc(16 * var(--u)) calc(18 * var(--u));
}
.bubble-text {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  font-size: calc(22 * var(--u));
  font-weight: 600;
  line-height: 1.4;
  color: #1b2b38;
  text-align: center;
  width: 100%;
}
.bubble-arrow {
  display: flex;
  justify-content: flex-end;
  padding-right: calc(8 * var(--u));
  width: 100%;
  flex-shrink: 0;
}
.bubble-arrow img {
  width: calc(16 * var(--u)); height: calc(9.6 * var(--u));
  display: block;
  animation: bob 1.2s ease-in-out infinite;
}
@keyframes bob { 50% { transform: translateY(calc(3 * var(--u))); } }
/* 퍼즐 부유 모션 — transform(rotate/센터링)과 충돌하지 않게 margin으로 이동 */
@keyframes floaty { 50% { margin-top: calc(8 * var(--u)); } }

/* 중앙 캡션 단어 페이드인 */
.w { opacity: 0; transition: opacity 0.45s ease; }
.w.in { opacity: 1; }

/* 시스템(다크) 말풍선 — 성공 화면 */
.bubble-dark {
  background: #1b2b38;
  border-color: #fff;
  filter: drop-shadow(calc(4 * var(--u)) calc(4 * var(--u)) 0 #fff);
  opacity: 0.95;
  padding: calc(20 * var(--u)) calc(16 * var(--u)) calc(18 * var(--u));
  justify-content: center;
}
.bubble-dark .bubble-text { color: #fff; }
.bubble-dark .bubble-arrow img { filter: invert(1); }
.bubble-dots { display: flex; gap: calc(6 * var(--u)); width: 100%; flex-shrink: 0; }
.bubble-dots i {
  width: calc(6 * var(--u)); height: calc(6 * var(--u));
  border-radius: 50%;
  background: rgba(27, 43, 56, 0.7);
  opacity: 0.5;
  animation: bubble-dot 1.2s infinite;
}
.bubble-dots i:nth-child(2) { animation-delay: 0.2s; }
.bubble-dots i:nth-child(3) { animation-delay: 0.4s; }
@keyframes bubble-dot { 30% { opacity: 1; } 60%, 100% { opacity: 0.5; } }
.bubble-dark .bubble-dots i { background: rgba(255, 255, 255, 0.7); }
/* 흰 말풍선에 dots가 있으면(아웃트로 시스템 문구) 상단 여백 확보 */
.bubble:not(.bubble-dark) .bubble-dots { margin-top: calc(-12 * var(--u)); }

/* ---------- 캡션 ---------- */
.caption-center {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  font-size: calc(26 * var(--u));
  font-weight: 500;
  line-height: 1.3;
  color: #fff;
  text-align: center;
  white-space: nowrap;
  text-shadow: 0 0 calc(8 * var(--u)) rgba(27, 43, 56, 0.5);
}
/* ---------- 아티스트 대사 박스 (하단) ----------
   예전엔 화면 가운데 캡션 밴드였다. 시안 개편으로 하단 박스 + 인물 사진으로 바뀌면서
   시스템 말풍선과 같은 자리를 쓰게 됐다 — 그래서 한 씬에 둘을 같이 두지 않고 씬을 나눈다.
   보이스가 함께 나오므로 타이핑 사운드가 붙는 data-type 대신 data-type="fade"(무음)를 쓴다. */
.bubble-wrap.artist {
  padding: 0 0 calc(40 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
}
/* 사진은 박스 왼쪽으로 83 겹쳐 올라탄다 (테두리 2px는 에셋에 포함) */
.artist-face {
  position: relative;
  z-index: 2;
  flex-shrink: 0;
  width: calc(100 * var(--u));
  height: calc(100 * var(--u));
  margin-right: calc(-83 * var(--u));
  object-fit: cover;
  display: block;
}
.artist-box {
  position: relative;
  z-index: 1;
  flex-shrink: 0;
  width: calc(420 * var(--u));
  height: calc(140 * var(--u));
  border: calc(2 * var(--u)) solid #1b2b38;
  box-shadow: calc(4 * var(--u)) calc(4 * var(--u)) 0 #1b2b38;
  background: linear-gradient(180deg, #a1cbed 0%, rgba(208, 234, 255, 0.9) 100%);
  padding: calc(18 * var(--u)) calc(16 * var(--u)) calc(16 * var(--u)) calc(105 * var(--u));
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* 안쪽 얇은 테두리 (405 x 125, 가운데) */
.artist-box::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: calc(405 * var(--u));
  height: calc(125 * var(--u));
  border: calc(2 * var(--u)) solid #84b6df;
  pointer-events: none;
}
.artist-box .bubble-text {
  flex: none;
  height: calc(100 * var(--u));
  margin-bottom: calc(-9.6 * var(--u));
  font-size: calc(21 * var(--u));
  color: #1b2b38;
  text-align: left;   /* 시스템 말풍선(가운데)과 달리 아티스트 대사는 왼쪽 정렬 */
}
/* 이름표 — 시안은 4.23° 기울어진 알약. 이름 길이에 따라 폭이 늘어난다 */
.artist-name {
  position: absolute;
  left: calc(301 * var(--u));
  top: calc(-17 * var(--u));
  height: calc(36 * var(--u));
  display: inline-flex;
  align-items: center;
  gap: calc(6 * var(--u));
  padding: 0 calc(22 * var(--u)) 0 calc(17 * var(--u));
  background: #1b2b38;
  border-radius: calc(18 * var(--u)) calc(15.5 * var(--u)) calc(18 * var(--u)) calc(18 * var(--u));
  transform: rotate(4.23deg);
  white-space: nowrap;
}
.artist-name img {
  width: calc(11.69 * var(--u));
  height: calc(13.07 * var(--u));
  display: block;
}
.artist-name b {
  font-size: calc(18 * var(--u));
  font-weight: 600;
  color: #fff;
}

/* ---------- 인트로 사물 ---------- */
/* 회중시계 모션 (webm, 검정 배경 위 2초). 저전력 모드 등으로 재생이 막히면 poster가 그대로 보인다 */
.watch-video {
  position: absolute;
  left: calc(63 * var(--u)); top: calc(296 * var(--u));
  width: calc(401 * var(--u)); height: calc(498 * var(--u));

}
.watch-video video,
.watch-video img {
  display: block;
  position: absolute;
  inset: 0;
  object-fit: contain;
  pointer-events: none;
  width: 100%;
  height: 100%;
}

/* ---------- Click 인디케이터 ---------- */
.click-indicator {
  position: absolute;
  left: calc(394.4 * var(--u)); top: calc(556.08 * var(--u));
  display: flex;
  flex-direction: column;
  gap: calc(5 * var(--u));
  align-items: center;
  pointer-events: none;
}
.click-indicator span {
  font-size: calc(22 * var(--u));
  font-weight: 600;
  color: #fff;
  text-shadow: 0 0 calc(4 * var(--u)) rgba(0, 0, 0, 0.7);
}
.click-indicator img {
  width: calc(24 * var(--u)); height: calc(62 * var(--u));
  transform: rotate(180deg);
}

/* ---------- 미션 포스터 ---------- */
.mission-poster {
  position: absolute;
  left: 50%; top: calc(314.4 * var(--u));
  transform: translateX(-50%);
  width: calc(382.76 * var(--u)); height: calc(516.41 * var(--u));
}

/* ---------- 하단 액션 버튼 ---------- */
.action-wrap {
  position: absolute;
  left: 0; right: 0; bottom: var(--ui-inset);
  padding: 0 calc(30 * var(--u)) calc(40 * var(--u));
  filter: drop-shadow(0 0 calc(10 * var(--u)) rgba(255, 255, 255, 0.5));
}
.action-wrap.wide { padding: 0 calc(40 * var(--u)) calc(40 * var(--u)); }
.action-btn {
  width: 100%;
  height: calc(80 * var(--u));
  background: #fff;
  border: calc(2 * var(--u)) solid #1b2b38;
  border-radius: calc(12 * var(--u));
  filter: drop-shadow(0 calc(4 * var(--u)) 0 #1b2b38);
  font-size: calc(22 * var(--u));
  font-weight: 600;
  color: #1b2b38;
}
.action-btn:active { transform: translateY(calc(2 * var(--u))); }

/* ---------- 핫스팟 (좌표는 HTML의 --x/--y/--w/--h 커스텀 프로퍼티, 디자인px) ---------- */
.hotspot {
  position: absolute;
  z-index: 5;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
}
/* ---------- 퍼즐 진행도 (와이드 세그먼트 바 — 채움 = 현재 멤버 번호) ---------- */
.progress-wrap {
  position: absolute;
  left: calc(30 * var(--u)); right: calc(30 * var(--u));
  /* #bg-layer 안에 있어(딤과 함께 흐려지도록) 프레임 상단까지 --bg-over 만큼 되돌린다 */
  top: calc(89 * var(--u) + var(--ui-inset) + var(--bg-over));
  display: flex;
  gap: calc(10 * var(--u));
  pointer-events: none;
}
.progress-pill { display: contents; }
.progress-seg {
  flex: 1;
  height: calc(7 * var(--u));
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.3);
}
.progress-seg.fill { background: #fff; }

/* ---------- 정답/힌트 바 ---------- */
.answer-bar {
  position: absolute;
  left: 0; right: 0; bottom: var(--ui-inset);
  padding: 0 calc(30 * var(--u)) calc(40 * var(--u));
  display: flex;
  gap: calc(12 * var(--u));
  align-items: center;
  z-index: 6;
}
.answer-bar.behind { z-index: 1; }
.bar-input {
  flex: 1;
  padding: calc(20 * var(--u));
  border: calc(2 * var(--u)) solid #1b2b38;
  border-radius: calc(20 * var(--u));
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(calc(10 * var(--u)));
  box-shadow: 0 calc(4 * var(--u)) 0 #1b2b38;
  font-size: calc(22 * var(--u));
  font-weight: 600;
  letter-spacing: calc(-0.44 * var(--u));
  color: rgba(255, 255, 255, 0.5);
  text-align: left;
  line-height: 1.3;
}
.bar-hint {
  width: calc(76 * var(--u));
  height: calc(73 * var(--u));
  border: calc(2 * var(--u)) solid #1b2b38;
  border-radius: calc(20 * var(--u));
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(calc(10 * var(--u)));
  box-shadow: 0 calc(4 * var(--u)) 0 #1b2b38;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(6 * var(--u));
  padding-top: calc(4 * var(--u));
}
.bar-hint img { width: calc(25.67 * var(--u)); height: calc(14 * var(--u)); }
.bar-hint span {
  font-size: calc(16 * var(--u));
  font-weight: 600;
  letter-spacing: calc(-0.32 * var(--u));
  color: #fff;
  line-height: 1.3;
}

/* ---------- 딤 패널 (사물 상세 / 팝업 공통) ---------- */
.dim-panel {
  position: fixed;
  inset: 0;
  /*top: calc(65 * var(--u) + var(--ui-inset));*/
  /*bottom: var(--ui-inset);*/
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(calc(5 * var(--u)));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 calc(40 * var(--u));
  z-index: 10;
}

/* ---------- 사물 상세 ---------- */
.detail-obj {
  width: calc(420.5 * var(--u));
  height: calc(334 * var(--u));
}
/* 글로우는 drop-shadow — 투명 이미지의 실루엣을 따라감 (box-shadow는 사각 박스에 뜸) */
.detail-obj img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  filter: drop-shadow(0 0 calc(20 * var(--u)) rgba(255, 255, 255, 0.75));
}
.detail-close {
  padding-top: calc(32 * var(--u));
  font-size: calc(24 * var(--u));
  font-weight: 600;
  letter-spacing: calc(-0.48 * var(--u));
  color: #fff;
}

/* ---------- 팝업 ---------- */
.popup {
  position: relative;
  width: 100%;
  border-radius: calc(20 * var(--u));
  background: #e3e4e1 var(--img-paper) center / cover;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: calc(32 * var(--u)) calc(28 * var(--u)) calc(30 * var(--u));
}
.popup-mission { padding: calc(40 * var(--u)) calc(28 * var(--u)); }
.popup-close {
  position: absolute;
  top: 0; right: 0;
  width: calc(62 * var(--u)); height: calc(70 * var(--u));
  display: flex;
  align-items: center;
  padding: calc(10 * var(--u));
  z-index: 2;
}
.popup-close img { width: calc(32 * var(--u)); height: calc(32 * var(--u)); }
.popup-star { position: absolute; pointer-events: none; }
.star-a { left: 11.39%; top: 12.47%; width: 10.11%; }
.star-b { left: 83.97%; top: 53.83%; width: 9.58%; }
.popup-pill {
  border: calc(1.5 * var(--u)) solid #1b2b38;
  border-radius: 999px;
  background: rgba(27, 43, 56, 0.1);
  padding: calc(10 * var(--u)) calc(20 * var(--u));
  font-size: calc(16 * var(--u));
  font-weight: 700;
  color: #1b2b38;
  line-height: 1.2;
}
.popup-title {
  margin-top: calc(20 * var(--u));
  font-size: calc(28 * var(--u));
  font-weight: 700;
  line-height: 1.3;
  color: #1b2b38;
  text-align: center;
}
/* 미션 팝업 본문형 (2차 디자인: MISSION n 필 + 서술형 본문) */
.popup-title.mission-desc {
  font-size: calc(22 * var(--u));
  line-height: 1.4;
}
.popup-note {
  margin-top: calc(12 * var(--u));
  font-size: calc(16 * var(--u));
  font-weight: 500;
  color: rgba(27, 43, 56, 0.6);
  text-align: center;
}
.popup-sub {
  margin-top: calc(18 * var(--u));
  font-size: calc(18 * var(--u));
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: calc(-0.72 * var(--u));
  color: #1b2b38;
  text-align: center;
}
.popup-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(10 * var(--u));
}
.popup-icon { width: calc(24 * var(--u)); height: calc(24 * var(--u)); object-fit: contain; }
.popup-title-sm {
  font-size: calc(24 * var(--u));
  font-weight: 700;
  line-height: 1.2;
  color: #1b2b38;
}
.popup-body {
  font-size: calc(20 * var(--u));
  font-weight: 500;
  color: #1b2b38;
  text-align: center;
}
.hint-body { padding: calc(24 * var(--u)) 0 calc(10 * var(--u)); line-height: 1.6; }
.answer-desc { padding-top: calc(18 * var(--u)); line-height: 1.5; }

/* 정답 입력 폼 */
.answer-row {
  margin-top: calc(18 * var(--u));
  width: 100%;
  height: calc(72 * var(--u));
  border: calc(2 * var(--u)) solid #1b2b38;
  border-radius: calc(16 * var(--u));
  background: rgba(27, 43, 56, 0.1);
  backdrop-filter: blur(calc(2 * var(--u)));
  display: flex;
  align-items: center;
  gap: calc(10 * var(--u));
  padding: calc(16 * var(--u)) calc(16 * var(--u)) calc(16 * var(--u)) calc(20 * var(--u));
}
.answer-row input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  outline: none;
  font: inherit;
  /* 16px 미만이면 iOS Safari가 포커스 시 자동 줌 → 하한선 고정 */
  font-size: max(16px, calc(22 * var(--u)));
  font-weight: 600;
  color: #1b2b38;
  line-height: 1.3;
}
.answer-row input::placeholder { color: rgba(27, 43, 56, 0.3); }
.answer-row button {
  background: rgba(27, 43, 56, 0.2);
  border-radius: calc(8 * var(--u));
  padding: calc(7 * var(--u)) calc(16 * var(--u)) calc(8 * var(--u));
  font-size: calc(17 * var(--u));
  font-weight: 600;
  letter-spacing: calc(-0.34 * var(--u));
  color: #1b2b38;
  line-height: 1.3;
}
.answer-row.shake { animation: shake 0.4s; }
@keyframes shake {
  20%, 60% { transform: translateX(calc(-8 * var(--u))); }
  40%, 80% { transform: translateX(calc(8 * var(--u))); }
}

/* ---------- 문 / 퍼즐 ---------- */
.door-img {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: calc(332.4 * var(--u)); height: calc(530 * var(--u));
  object-fit: cover;
  filter: drop-shadow(0 calc(8 * var(--u)) calc(20 * var(--u)) rgba(0, 0, 0, 0.5));
}
.door-open-img {
  position: absolute;
  left: calc(-75 * var(--u)); top: calc(283.93 * var(--u));
  width: calc(512.45 * var(--u)); height: calc(530 * var(--u));
  filter: drop-shadow(0 calc(8 * var(--u)) calc(20 * var(--u)) rgba(0, 0, 0, 0.5));
}
.puzzle-img {
  position: absolute;
  left: calc(217 * var(--u)); top: calc(485 * var(--u));
  width: calc(143 * var(--u)); height: calc(131 * var(--u));
  object-fit: cover;
  animation: floaty 1.6s ease-in-out infinite;
}

/* ---------- 발견 오브젝트 (민제 사물함 / 계훈 녹음기·퍼즐) ---------- */
.cabinet-img {
  position: absolute;
  left: 0; top: calc(337.02 * var(--u));
  width: calc(500 * var(--u)); height: calc(405.71 * var(--u));
}
/* 닫힌 사물함 (문제페이지_민제_5) — 누르면 열린 화면으로 간다. 시안 실측 35.5, 391, 416 x 308.
   열린 사물함은 문이 밖으로 열려 박스가 더 크다(.cabinet-img) — 같은 좌표를 쓰면 안 맞는다. */
.cabinet-closed {
  position: absolute;
  left: calc(35.5 * var(--u)); top: calc(391 * var(--u));
  width: calc(416 * var(--u)); height: calc(308 * var(--u));
}
.cabinet-closed img { width: 100%; height: 100%; display: block; }
/* 계훈 발견 씬: 캠코더 뒤에 퍼즐이 숨어 있고, 캠코더를 누르면 왼쪽으로 비켜나며 퍼즐이 드러난다 */
.puzzle-kh {
  position: absolute;
  left: 50%; top: calc(429.65 * var(--u));
  transform: translateX(-50%);
  width: calc(235 * var(--u)); height: calc(220 * var(--u));
  filter: drop-shadow(0 0 calc(20 * var(--u)) rgba(161, 203, 237, 0.7));
}
.recorder-img img { width: 100%; height: 100%; display: block; }
.recorder-img {
  position: absolute;
  left: 50%; top: calc(397.61 * var(--u));
  transform: translateX(-50%);
  width: calc(300 * var(--u)); height: calc(251.575 * var(--u));
  z-index: 2;
  transition: transform 0.7s cubic-bezier(0.4, 0, 0.2, 1), top 0.7s cubic-bezier(0.4, 0, 0.2, 1);
}
/* 비켜난 상태 (클릭 후 / 이후 씬) */
.scene.revealed .recorder-img,
.recorder-img.aside {
  top: calc(417.57 * var(--u));
  transform: translateX(calc(-50% - 253.52 * var(--u)));
}

/* ---------- 토스트 (퍼즐 획득) ---------- */
.toast-wrap {
  position: absolute;
  left: 0; right: 0; top: 50%;
  transform: translateY(-50%);
  display: flex;
  justify-content: center;
  z-index: 5;
}
/* 플로우 2+: 상단 고정 + 밝은 토스트 */
.toast-wrap.top {
  top: calc(65 * var(--u) + var(--ui-inset));
  transform: none;
  padding-top: calc(28 * var(--u));
}
.toast.light {
  background: rgba(255, 255, 255, 0.3);
}
.toast {
  display: flex;
  align-items: center;
  gap: calc(12 * var(--u));
  width: calc(390 * var(--u));
  padding: calc(20 * var(--u)) calc(28 * var(--u))calc(20 * var(--u)) calc(24 * var(--u));
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(calc(25 * var(--u)));
}
.toast-left {
  display: flex;
  align-items: center;
  gap: calc(10 * var(--u));
  width: calc(236 * var(--u));
}
.toast-left img { width: calc(22 * var(--u)); height: calc(23 * var(--u)); }
.toast-left span {
  font-size: calc(18 * var(--u));
  font-weight: 500;
  color: #fff;
  line-height: 1.3;
  white-space: nowrap;
}
.toast b {
  width: calc(36 * var(--u));
  font-size: calc(18 * var(--u));
  font-weight: 700;
  color: #fff;
  text-align: center;
  line-height: 1.3;
  margin-left: auto;
}

/* ---------- 아웃트로 배경 (그라데이션 + 노이즈) ---------- */
.particles-img {
  position: absolute;
  left: calc(30.11 * var(--u)); top: calc(117 * var(--u));
  width: calc(456 * var(--u)); height: calc(746.44 * var(--u));
  pointer-events: none;
}

/* ---------- 동화: 카메라 갤러리 (가로 스크롤) ---------- */
.gallery {
  width: calc(500 * var(--u));
  /* 슬라이드 300 + 상하 여백. 스크롤 컨테이너는 넘치는 부분을 잘라내므로
     활성 슬라이드의 흰 오라(drop-shadow)가 잘리지 않을 만큼 세로 여유를 둔다 (사파리에서 특히 티남) */
  height: calc(372 * var(--u));
  display: flex;
  gap: calc(4 * var(--u));
  align-items: center;
  overflow-x: auto;
  padding: calc(34 * var(--u)) calc(40 * var(--u)) calc(38 * var(--u)) calc(30 * var(--u));
  flex-shrink: 0;
  scrollbar-width: none;
  /* 스냅은 JS 가 부드럽게 처리한다 (CSS scroll-snap 은 드래그 중 끼어들어 튄다) */
  touch-action: none;
  cursor: grab;
}
.gallery.dragging { cursor: grabbing; }
.gallery::-webkit-scrollbar { width: 0; height: 0; display: none; }
.g-slide {
  width: calc(400 * var(--u));
  height: calc(300 * var(--u));
  background: #090909;
  border-radius: calc(24 * var(--u));
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: calc(20 * var(--u)) 0 calc(32 * var(--u));
  flex-shrink: 0;
  transition: box-shadow 0.25s ease;
}
/* 가운데 온 슬라이드에만 흰 오라.
   drop-shadow 는 사파리가 스크롤 컨테이너 안에서 스크롤 중에 잘라먹는다(합성 레이어 경계).
   슬라이드가 불투명한 라운드 박스라 box-shadow 로 같은 그림이 나오고 렌더도 안정적이다. */
.g-slide.active { box-shadow: 0 0 calc(14 * var(--u)) calc(2 * var(--u)) rgba(255, 255, 255, 0.7); }
.g-photo {
  width: calc(360 * var(--u));
  height: calc(220 * var(--u));
  border-radius: calc(12 * var(--u));
  object-fit: cover;
}
.g-icons {
  width: calc(360 * var(--u));
  display: flex;
  justify-content: space-between;
  padding: calc(18 * var(--u)) calc(20 * var(--u)) calc(16 * var(--u));
}
.g-icons img { width: calc(24 * var(--u)); height: calc(24 * var(--u)); }

/* 주왕: 휴대폰 메시지 — 화면(카드)만 export한 이미지. 라운드/글로우는 CSS */
.detail-obj.phone-obj {
  width: calc(420 * var(--u));
  height: calc(333 * var(--u));
}
/*.detail-obj.phone-obj img { border-radius: calc(30 * var(--u)); }*/

/* 노선도: 이미지 2장 겹침 */
.detail-obj.stack { position: relative; }
.detail-obj.stack .over { position: absolute; inset: 0; }

/* ---------- 발견 오브젝트 (동화/주왕/동현) ---------- */
/* 동화 가로등 발견/클리어 — 좌우가 화면 밖으로 넘치는 큰 아트 (양옆은 #stage가 잘라냄) */
.lamp-found-img {
  position: absolute;
  left: calc(-90.95 * var(--u)); top: calc(264.12 * var(--u));
  width: calc(680.25 * var(--u)); height: calc(551.77 * var(--u));
}
.busstop-img {
  position: absolute;
  left: 50%; top: calc(290 * var(--u));
  transform: translateX(-50%);
  width: calc(480 * var(--u)); height: calc(480 * var(--u));
}
/* 동현 발견/클리어 — 비행기는 클리어 씬에서 왼쪽으로 비켜나고 퍼즐 조각이 드러난다 */
.puzzle-dg {
  position: absolute;
  left: calc(120 * var(--u)); top: calc(430.11 * var(--u));
  width: calc(220 * var(--u)); height: calc(220 * var(--u));
  filter: drop-shadow(0 0 calc(20 * var(--u)) rgba(161, 203, 237, 0.7));
}
/* 주왕 발견 — 버스를 누르면 왼쪽으로 완전히 빠져나가고 뒤의 정류장·퍼즐이 드러난다.
   시안(문제페이지_주왕_5) 실측: 뒷면이 x 484 에서 끝나고 앞부분은 화면 밖으로 나가 있다
   (원본 1623 x 679 를 829.5 x 347 로, left -345.5). */
.bus-lg {
  position: absolute;
  left: calc(-397 * var(--u));
  top: calc(360 * var(--u));
  width: calc(890 * var(--u));
  height: auto;
  z-index: 2;
  transition: left 1.1s cubic-bezier(0.4, 0, 0.2, 1);
}
.bus-lg img { width: 100%; height:auto; display: block; }
/* 오른쪽 끝(-860 + 829.5 = -30.5)이 화면 왼쪽 밖 — 차체가 한 대분 다 빠져나간다 */
.scene.revealed .bus-lg { left: calc(-900 * var(--u)); }

.plane-lg {
  position: absolute;
  left: calc(96 * var(--u)); top: calc(444.5 * var(--u));
  width: calc(308 * var(--u)); height: calc(255 * var(--u));
  z-index: 2;
  transition: left 0.7s cubic-bezier(0.4, 0, 0.2, 1), top 0.7s cubic-bezier(0.4, 0, 0.2, 1);
}
.plane-lg img { width: 100%; height: 100%; display: block; }
/* 비켜난 상태 (클릭 후 / 클리어 씬) */
.scene.revealed .plane-lg,
.plane-lg.aside {
  left: calc(-123.95 * var(--u)); top: calc(317.5 * var(--u));
}


/* ---------- 아웃트로: 회중시계 / 선택지 / 엔딩 ---------- */
/* 시안 프레임(500 x 524 @ y240) 그대로 — 본체+바늘을 한 장으로 합친 v3 를 쓴다.
   전에는 본체·바늘 두 장을 object-fit: cover 로 겹쳐 놨는데, 캔버스 크기가 서로 달라
   박스 비율을 건드리면 바늘이 어긋났고 cover 가 고리(bail)를 잘라내고 있었다. */
.clock-obj {
  position: absolute;
  left: 0; top: calc(240 * var(--u));
  width: calc(500 * var(--u)); height: calc(524 * var(--u));
  filter: drop-shadow(0 0 calc(20 * var(--u)) rgba(255, 255, 255, 0.45));
}
.clock-obj img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }

.choice-title {
  font-size: calc(30 * var(--u));
  font-weight: 600;
  line-height: 1.4;
  color: #fff;
  text-align: center;
  text-shadow: 0 0 calc(4 * var(--u)) rgba(255, 255, 255, 0.7);
}
.choice-title.center {
  position: absolute;
  left: calc(40 * var(--u)); right: calc(40 * var(--u));
  top: 50%;
  transform: translateY(-50%);
}
.choice-list {
  position: absolute;
  left: calc(40 * var(--u)); right: calc(40 * var(--u));
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: calc(48 * var(--u));
  align-items: center;
}
.choice-options {
  display: flex;
  flex-direction: column;
  gap: calc(12 * var(--u));
  width: 100%;
}
.choice-btn {
  height: calc(82 * var(--u));
  border-radius: calc(16 * var(--u));
  background: rgba(255, 255, 255, 0.2);
  border: calc(2 * var(--u)) solid rgba(255, 255, 255, 0.2);
  padding: calc(4 * var(--u)) calc(20 * var(--u));
  font-size: calc(21 * var(--u));
  font-weight: 600;
  color: #fff;
  line-height: 1.3;
}
.choice-btn:active { background: rgba(255, 255, 255, 0.35); }
.choice-btn.selected {
  background: rgba(255, 255, 255, 0.45);
  border-color: rgba(255, 255, 255, 0.9);
}

.ending-glow {
  position: absolute;
  left: 50%; top: calc(50% + 32.5 * var(--u));
  transform: translate(-50%, -50%);
  width: calc(420 * var(--u)); height: calc(217.35 * var(--u));
  display: flex;
  align-items: center;
  justify-content: center;
}
.ending-glow img {
  position: absolute;
  left: -11.9%; top: -23%;
  width: 123.8%; height: 146%;
}
.ending-glow p {
  position: relative;
  font-size: calc(24 * var(--u));
  font-weight: 600;
  line-height: 1.4;
  color: #1b2b38;
  text-align: center;
}

/* ---------- 아웃트로: 퍼즐 드래그 ---------- */
.puzzle-title {
  position: absolute;
  left: calc(40 * var(--u)); right: calc(40 * var(--u));
  top: calc(206 * var(--u));   /* 3차 검수: 안내 문구·퍼즐판·조각 제자리를 다 같이 10 아래로 */
  font-size: calc(30 * var(--u));
  font-weight: 700;
  line-height: 1.3;
  color: #fff;
  text-align: center;
  text-shadow: 0 0 calc(4 * var(--u)) #9DD3FF;

}
.o-board {
  position: absolute;
  left: calc(65 * var(--u)); top: calc(287 * var(--u));   /* 3차 검수: +10 (puzzle-title 과 같이 이동) */
  width: calc(370 * var(--u));
  filter: drop-shadow(0 calc(4 * var(--u)) calc(20 * var(--u)) #091527);
}
/* 쪽지판 박스 = 쪽지 6장의 3x2 그리드. 쪽지마다 좌표를 주지 않으므로
   판을 옮길 땐 이 박스의 left/top만 고치면 쪽지가 따라온다.
   좌우 여백은 space-between 이 나눠 갖는다(디자인 열 간격 약 0.5). */
.o-notes {
  position: absolute;
  left: calc(76 * var(--u)); top: calc(309.79 * var(--u));   /* 3차 검수: 앞면(.o-board)과 같이 +10 — 플립 앞뒤 세로 중심을 맞춰 둔다 */
  width: calc(348 * var(--u)); height: calc(342.5 * var(--u));
  box-sizing: border-box;
  padding: calc(58.52 * var(--u)) calc(17.6 * var(--u)) 0;
  display: grid;
  grid-template-columns: repeat(3, calc(103.92 * var(--u)));
  grid-auto-rows: calc(103.92 * var(--u));
  justify-content: space-between;
  align-content: start;
  row-gap: calc(18.73 * var(--u));
}
.o-note-board {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  filter: drop-shadow(0 calc(4 * var(--u)) calc(20 * var(--u)) #091527);
}
/* o-choice 에서는 그리드 칸 자체가 탭 영역이고 쪽지는 그 안에 든다.
   o-notes(발견)와 쪽지 그림이 같아서 고를 수 있다는 신호가 없다 —
   글로우가 한 장씩 차례로 번지며 클릭을 유도한다. 위치는 건드리지 않는다.
   투명 이미지라 box-shadow 대신 drop-shadow (실루엣을 따라간다).
   확대(scale)는 안쪽 .o-note 가 맡으므로 서로 안 겹친다. */
.o-note-pick {
  position: relative;
  animation: note-glow 2.2s ease-in-out infinite;
}
/* 두 겹 — 밝은 심지 + 넓게 퍼지는 halo. 반경만 키우면 흐려지기만 해서 두 개로 겹친다.
   보간되려면 0%/50% 의 filter 함수 개수가 같아야 한다 */
@keyframes note-glow {
  0%, 100% {
    filter: drop-shadow(0 0 0 rgba(255, 245, 214, 0))
            drop-shadow(0 0 0 rgba(255, 245, 214, 0));
  }
  50% {
    filter: drop-shadow(0 0 calc(6 * var(--u)) rgba(255, 245, 214, 1))
            drop-shadow(0 0 calc(16 * var(--u)) rgba(255, 236, 176, 0.75));
  }
}
.o-note-pick:nth-child(3) { animation-delay: 0.2s; }   /* 1번째 자식은 쪽지판 */
.o-note-pick:nth-child(4) { animation-delay: 0.4s; }
.o-note-pick:nth-child(5) { animation-delay: 0.6s; }
.o-note-pick:nth-child(6) { animation-delay: 0.8s; }
.o-note-pick:nth-child(7) { animation-delay: 1s; }
.o-note {
  width: 100%; height: 100%;
  display: block;
  pointer-events: none;
  filter: drop-shadow(0 calc(1 * var(--u)) calc(4 * var(--u)) rgba(39, 70, 114, 0.5));
  transition: transform 0.25s ease-out;
}
/* 고른 쪽지만 커지면서 암전으로 넘어간다 — 옆 칸 위로 올라오도록 칸에 z-index */
.o-note.picked { transform: scale(1.5); }
/* 고른 뒤에는 글로우를 멈춘다 — 확대 연출만 남는다 */
.o-note-pick.selected { z-index: 10; animation: none; }
/* 트레이는 다른 하단 UI와 같이 화면 하단 기준 */
/* 3차 검수: 화면 최하단 고정 밴드 (디자인 스토리페이지_아웃트로_5 — 폭 500 전체, h240, 상단만 라운드) */
.p-tray {
  position: absolute;
  left: 0; right: 0;
  bottom: var(--ui-inset);   /* 레터박스=아트 하단, 크롭=화면 하단 (.bubble-wrap 과 같은 기준) */
  height: calc(240 * var(--u));
  border-radius: calc(20 * var(--u)) calc(20 * var(--u)) 0 0;
  background: rgba(255, 255, 255, 0.2);
  border-top: 1px solid rgba(255, 255, 255, 0.35);
}
.p-piece {
  position: absolute;
  left: calc(var(--px) * var(--u));
  top: calc(var(--py) * var(--u));
  width: calc(var(--pw) * var(--u));
  height: calc(var(--ph) * var(--u));
  touch-action: none;
  cursor: grab;
  z-index: 6;
}
/* 트레이에 놓여 있는 상태 — 트레이와 같이 화면 하단 기준 */
.p-piece.rest { top: auto; bottom: calc(var(--pb) * var(--u) + var(--ui-inset)); }
/* 드래그 중엔 transform 으로만 움직이고(잔상 방지) 자체 레이어로 띄운다 */
.p-piece.dragging {
  z-index: 7;
  filter: drop-shadow(0 calc(6 * var(--u)) calc(10 * var(--u)) rgba(0, 0, 0, 0.4));
  will-change: transform;
}
/* 제자리에 놓이면 퍼즐판 스케일(트레이보다 약 8.6% 큼)로 */
.p-piece.placed {
  cursor: default;
  width: calc(var(--tw) * var(--u));
  height: calc(var(--th) * var(--u));
}

/* ---------- 결과 페이지 (자체 스크롤) ---------- */
.scene-scroll {
  /* 결과 페이지만 아트 박스를 벗어나 화면 전체를 덮는다 */
  top: var(--crop); bottom: var(--crop);
  overflow-y: auto;
  scrollbar-width: none;
  z-index: 20;
  background: #a1cbed;
}
.scene-scroll::-webkit-scrollbar { width: 0; height: 0; display: none; }
.r-top {
  /* 헤더(65) 아래부터 디자인 좌표 그대로 — 배경 이미지도 같은 만큼 내려 붙인다 */
  background: #b7d3e9 var(--img-result-top) center 0 / 100% auto repeat-y;
  /* 하단 여백은 종이 배경이 끝나는 곳(디자인 페이지 y960)까지 — 찢어진 경계가 이 위에 겹친다 */
  padding: calc(105 * var(--u)) calc(30 * var(--u)) calc(150 * var(--u));
}
.r-title {
  font-size: calc(28 * var(--u));
  font-weight: 500;
  line-height: 1.4;
  color: #1b2b38;
  text-align: center;
}
.r-title b {
  font-weight: 700;
}
/* 결과 카드 = 420 x 505.6 (에셋 840 x 1010, 2배) */
/* 카드 래퍼 — 사진 클릭 영역을 카드 좌표로 올리려고 둔다 */
.r-letter-wrap {
  position: relative;
  width: calc(420 * var(--u));
  margin: calc(24 * var(--u)) auto 0;
}
/* 사진(폴라로이드) 자리 — 카드 아트 실측은 (240,28) 148x212 인데
   누르기 쉽게 상하좌우로 20%씩 넓혔다. 위쪽은 카드 밖으로 나가지 않게 0 에서 자른다. */
.r-video-hit {
  position: absolute;
  left: calc(210 * var(--u)); top: 0;
  width: calc(208 * var(--u)); height: calc(283 * var(--u));
  background: none;
  cursor: pointer;
}
/* Click! 배지 — 시안 SVG(알약 91x39 + 아래 꼬리 + 그림자) 를 값 그대로 옮겨 CSS 로 그린다.
   SVG 를 <img> 로 넣으면 그림자가 이미지 박스에 잘리고 텍스트도 패스로 박힌다.
   가운데 정렬은 translate, 바운싱은 transform 으로 나눠 서로 안 덮어쓴다. */
.r-video-cta {
  position: absolute;
  left: 50%; top: calc(-11 * var(--u));
  translate: -50% 0;
  width: calc(91 * var(--u)); height: calc(39 * var(--u));
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px;
  background: #192734;
  font-size: calc(19 * var(--u)); font-weight: 700;
  line-height: 1;
  color: #fff;
  /* 시안 필터: 오프셋 0, blur 4, #454340 50% — 꼬리까지 한 번에 먹는다 */
  filter: drop-shadow(0 0 calc(4 * var(--u)) rgba(69, 67, 63, 0.5));
  pointer-events: none;
  animation: r-cta-bounce 1.1s linear infinite;   /* 구간별 이진은 keyframes 안에서 준다 */
}
/* 사진을 가리키는 꼬리 (SVG 기준 x47.6~59.4, y44~54.5 — 알약 밑으로 7.5 내려온다) */
.r-video-cta::after {
  content: "";
  position: absolute;
  left: 50%; top: 100%;
  translate: -50% 0;
  margin-top: calc(-3 * var(--u));
  width: calc(12 * var(--u)); height: calc(10.5 * var(--u));
  background: #192734;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}
/* 클릭 유도 바운싱 — 1.1s 중 앞 0.5s 만 한 번 튀고, 나머지 0.6s 는 위에서 쉰다.
   내려갈 땐 가속(ease-in), 올라올 땐 감속(ease-out). */
@keyframes r-cta-bounce {
  0%   { transform: translateY(0);                  animation-timing-function: cubic-bezier(0.4, 0, 0.75, 0.3); }
  18%  { transform: translateY(calc(7 * var(--u))); animation-timing-function: cubic-bezier(0.25, 0.8, 0.4, 1); }
  45%,
  100% { transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .r-video-cta { animation: none; }
}

/* ---------- 결과 영상 팔업 (9:16) ---------- */
.r-video-pop {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(15, 28, 40, 0.88);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(24 * var(--u));
  padding: calc(40 * var(--u)) calc(30 * var(--u));
}
.r-video-box {
  position: relative;
  width: calc(368 * var(--u));
  max-width: 100%;
  aspect-ratio: 9 / 16;
  max-height: calc(100% - 80 * var(--u));
  border: calc(3 * var(--u)) solid rgba(255, 255, 255, 0.6);   /* 시안 */
  border-radius: calc(20 * var(--u));
  overflow: hidden;
  background: #000;
}
.r-video-box video {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* 클릭 영역은 영상 전체. 가운데 원은 현재 상태를 알리는 표시일 뿐이다 —
   재생 중에는 0.2초만 비치고 사라지고, 멈춰 있으면 계속 보인다. */
.r-video-toggle {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  background: none;
  cursor: pointer;
}
.r-video-toggle::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: calc(88 * var(--u)); height: calc(88 * var(--u));
  border-radius: 50%;
  background: rgba(27, 43, 56, 0.55) no-repeat center / calc(30 * var(--u)) calc(34 * var(--u));
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 34'%3E%3Cpath d='M0 0l30 17L0 34z' fill='%23fff'/%3E%3C/svg%3E");
  transition: opacity 0.25s;
}
.r-video-pop.playing .r-video-toggle::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 34'%3E%3Crect x='3' width='8' height='34' fill='%23fff'/%3E%3Crect x='19' width='8' height='34' fill='%23fff'/%3E%3C/svg%3E");
}
.r-video-pop.ui-hidden .r-video-toggle::before { opacity: 0; }
.r-video-toggle:focus-visible::before { opacity: 1; }
.r-video-close {
  font-size: calc(24 * var(--u)); font-weight: 600;
  color: #fff;
  cursor: pointer;
}

.r-letter {
  display: block;
  width: calc(420 * var(--u));
  height: calc(580 * var(--u));
  /* 카드 아트가 투명 없는 직사각이라 box-shadow 로 같은 그림.
     스크롤 컨테이너(.scene-scroll) 안에서 drop-shadow 는 사파리가 스크롤 중 잘라낸다 */
  box-shadow: 0 calc(6 * var(--u)) calc(18 * var(--u)) rgba(27, 43, 56, 0.28);
  -webkit-touch-callout: default; /* 꾹 눌러 저장 허용 */
}
/* 카드 합성 전 — 투명 placeholder 위에 스켈레톤만 보인다.
   하이라이트 띠가 왼쪽 바깥 → 오른쪽 바깥으로 한 번 지나간다(양 끝에서 완전히 벗어나 이음매 없음) */
.r-letter.loading {
  background-color: #e3e9f0;
  background-image: linear-gradient(105deg, transparent 40%, rgba(255, 255, 255, 0.7) 50%, transparent 60%);
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: r-skeleton 1.4s linear infinite;
}
@keyframes r-skeleton {
  from { background-position: 150% 0; }
  to   { background-position: -50% 0; }
}
.r-save-tip {
  margin-top: calc(16 * var(--u));
  font-size: calc(18 * var(--u));
  font-weight: 500;
  color: #1b2b38;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: .5em;
}
.r-save-tip small {
  font-size: 0.5em;
}
.r-dark {
  /* 배경 이미지의 찢어진 상단은 투명 — 위쪽 종이 위에 94px 겹쳐 올린다.
     이미지(1500 높이 2498)가 끝나는 지점부터는 .scene-scroll의 하늘색이 그대로 보인다.
     시안에서 그 경계는 추천 카드 뒤(카드 위에서 136 지점)를 지나간다 — 리스트와 하단 버튼
     사이에 걸리면 이음매가 그대로 보이므로, 이미지 상단에서 첫 문구까지의 거리(268)를
     시안 그대로 맞춰 둔다. 여기를 줄이면 경계가 카드 아래로 내려가 다시 어긋난다. */
  margin-top: calc(-94 * var(--u));
  background: var(--img-result-dark) top center / 100% auto no-repeat;
  /* 하단 60 — 추천 영역을 통째로 뺀 뒤 SNS 목록 아래 여백 (2026-09-17, 인혜) */
  padding: calc(160 * var(--u)) calc(30 * var(--u)) calc(60 * var(--u));
  text-align: center;
}
.r-eyebrow {
  display: inline-block;
  height: calc(41 * var(--u));
  padding: 0 calc(20 * var(--u));
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  font-size: calc(17 * var(--u));
  font-weight: 600;
  line-height: calc(41 * var(--u));
  color: rgba(255, 255, 255, 0.9);
}
.r-heading {
  margin-top: calc(16 * var(--u));
  font-size: calc(28 * var(--u));
  font-weight: 500;
  line-height: 1.4;
  color: #fff;
}
.r-heading b { font-weight: 700; }
.r-mv {
  display: block;
  width: calc(400 * var(--u));
  margin: calc(20 * var(--u)) auto 0;
}
.r-mv img { width: 100%; display: block; border-radius: calc(10 * var(--u)); }

/* 이벤트 안내 */
.r-event-pill {
  display: block;
  margin: calc(80 * var(--u)) auto 0;
  width: calc(122 * var(--u)); height: calc(50.2 * var(--u));
}
.r-event-copy {
  margin-top: calc(20 * var(--u));
  font-size: calc(28 * var(--u));
  font-weight: 500;
  line-height: 1.4;
  color: #fff;
}
.r-event-copy b {
  font-weight: 700;
}
/* 폴라로이드 6장 — 시안 에셋이 페이지 폭(500) 기준이라 .r-dark의 좌우 여백(30)을 넘어 전폭으로 깐다 */
.r-event-thumb {
  display: block;
  margin: calc(20 * var(--u)) calc(-30 * var(--u)) 0;
  width: calc(500 * var(--u));
  height: auto;
}
.r-event-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(420 * var(--u)); height: calc(80 * var(--u));
  margin: calc(20 * var(--u)) auto 0;
  border-radius: calc(12 * var(--u));
  background: #fff;
  font-size: calc(24 * var(--u));
  font-weight: 700;
  color: #1b2b38;
}

.r-share { margin-top: calc(60 * var(--u)); }
.r-share-title { font-size: calc(22 * var(--u)); font-weight: 700; color: #fff;
  display: flex; align-items: center; justify-content: center; gap: calc(8 * var(--u)); }
.r-share-count { font-weight: 500; color: rgba(255, 255, 255, 0.7); font-size: calc(20 * var(--u));
  display: flex; align-items: center; justify-content: center; gap: calc(4 * var(--u));   opacity: 0.6;
}
.r-share-count b { font-weight: inherit; }
.r-share-count img {
  width: calc(22 * var(--u)); height: calc(22 * var(--u));
  vertical-align: calc(-5 * var(--u));
  filter: brightness(0) invert(1);   /* 다크 섹션에서는 흰색 */
}
.r-share-icons {
  margin-top: calc(16 * var(--u));
  display: flex;
  justify-content: center;
  gap: calc(16 * var(--u));
}
/* 링크 복사만 <a>라 button 선택자에서 빠져 있었다 — 셋 다 같은 68x68 */
.r-share-icons button,
.r-share-icons a { display: block; width: calc(68 * var(--u)); height: calc(68 * var(--u)); }
.r-share-icons img { display: block; width: 100%; height: 100%; }
.r-share-icons button.copied,
.r-share-icons a.copied { border-radius: 50%; outline: calc(3 * var(--u)) solid rgba(255, 255, 255, 0.6); }
.r-restart {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(8 * var(--u));
  width: calc(220 * var(--u)); height: calc(80 * var(--u));
  margin: calc(60 * var(--u)) auto 0;
  border-radius: calc(12 * var(--u));
  background: #fff;
  font-size: calc(24 * var(--u));
  font-weight: 700;
  color: #1b2b38;
}
.r-restart img {
  display: block;
  width: calc(22 * var(--u)); height: calc(22 * var(--u));
}

  /* SNS 리스트는 구분선이 화면 전체 너비 — 텍스트만 32 안쪽 */
.r-sns { margin: calc(80 * var(--u)) calc(-30 * var(--u)) 0; padding: 0 calc(32 * var(--u)); text-align: left; }
.r-sns-logo { display: block; width: calc(140 * var(--u)); height: calc(30 * var(--u)); object-fit: contain; object-position: left; }
.r-sns-sub { margin-top: calc(6 * var(--u)); font-size: calc(25 * var(--u)); font-weight: 600; line-height: calc(35 * var(--u)); color: #fff; }
.r-sns-row {
  margin: 0 calc(-32 * var(--u));
  padding: 0 calc(32 * var(--u));
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: calc(85.33 * var(--u));
  border-bottom: 1px solid rgba(255, 255, 255, 0.2);
  font-size: calc(22 * var(--u));
  font-weight: 500;
  color: #fff;
  text-decoration: none;
}
.r-sns-row:first-of-type { margin-top: calc(16 * var(--u)); border-top: 1px solid rgba(255, 255, 255, 0.2); }
.r-sns-row span img { width: calc(32 * var(--u)); height: calc(32 * var(--u)); }
.r-reco { margin: calc(34.7 * var(--u)) calc(-30 * var(--u)) 0; padding: 0 calc(30 * var(--u)); text-align: left; }
.r-reco-title { font-size: calc(22 * var(--u)); font-weight: 800; color: #fff; }
.r-reco-cards {
  margin: calc(8 * var(--u)) calc(-30 * var(--u)) 0;
  padding: 0 calc(30 * var(--u));
  display: flex;
  gap: calc(26.5 * var(--u));
  overflow-x: auto;
  scrollbar-width: none;
}
.r-reco-cards::-webkit-scrollbar { width: 0; height: 0; display: none; }
.r-card {
  flex-shrink: 0;
  width: calc(173.4 * var(--u));
  display: block;
  text-decoration: none;
}
.r-card-thumb {
  display: block;
  width: 100%; height: calc(176 * var(--u));
  background: #e7e7e7;
  border: calc(5 * var(--u)) solid #1b2b38;
  border-bottom: none;
  object-fit: cover;
}
.r-card p {
  background: #fff;
  border: calc(5 * var(--u)) solid #1b2b38;
  border-top: none;
  padding: calc(9 * var(--u)) calc(8 * var(--u));
  font-size: calc(16 * var(--u));
  font-weight: 700;
  color: #1b2b38;
  text-align: center;
  /* CMS 제목 길이는 제각각 — 카드 높이가 흔들리지 않게 한 줄로 자른다 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.r-more {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(240 * var(--u)); height: calc(64 * var(--u));
  margin: calc(51 * var(--u)) auto 0;
  border-radius: 999px;
  background: #fff;
  font-size: calc(20 * var(--u));
  font-weight: 700;
  color: #1b2b38;
  text-decoration: none;
}

/* ---------- 전환 ----------
   씬 자체는 컷 전환(껌뻑임 없음). 배경이 이어지는 구간은 그대로 연결되고,
   오버레이(딤 패널/토스트/액션 버튼)만 가볍게 등장. */
.dim-panel { animation: fade 0.2s ease; }
.toast { animation: pop 0.25s ease; }
.action-wrap { animation: fade 0.3s ease; }
@keyframes fade { from { opacity: 0; } }
@keyframes pop { from { opacity: 0; transform: scale(0.92); } }

/* hidden 속성이 클래스 display에 지지 않도록 */
.progress-wrap[hidden] { display: none; }

/* ---------- 개발용 스테이지 점프 바 (배포 시 index.html에서 두 요소만 지우면 끝) ---------- */
#debug-toggle {
  position: absolute;
  right: calc(6 * var(--u)); bottom: calc(6 * var(--u));
  width: calc(60 * var(--u)); height: calc(60 * var(--u));
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: calc(26 * var(--u));
  line-height: 1;
  z-index: 90;
}
#debug-bar[hidden], #debug-toggle[hidden] { display: none; }
#debug-bar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  flex-wrap: wrap;
  gap: calc(4 * var(--u));
  padding: calc(6 * var(--u)) calc(70 * var(--u)) calc(6 * var(--u)) calc(6 * var(--u));
  background: rgba(0, 0, 0, 0.7);
  z-index: 90;
}
#debug-bar button {
  padding: calc(6 * var(--u)) calc(10 * var(--u));
  border-radius: calc(6 * var(--u));
  background: rgba(255, 255, 255, 0.18);
  color: #fff;
  font-size: calc(15 * var(--u));
  font-weight: 600;
}
#debug-bar button:active { background: rgba(255, 255, 255, 0.35); }
/* 사운드 상태 readout — 폰에서 소리가 죽었을 때 현장 확인용 */
#debug-sound {
  flex-basis: 100%;
  color: #9fe3b0;
  font-size: calc(13 * var(--u));
  line-height: 1.4;
  word-break: break-all;
}

/* ---------- 암전 전환 ---------- */
/* 기본 씬 전환은 컷. 쪽지를 고른 순간처럼 명시된 곳에서만 0.3초 fade to black */
#fade-black {
  position: absolute;
  inset: 0;
  z-index: 60;
  background: #000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s linear;
}
#fade-black.on { opacity: 1; }

/* ---------- 인트로 페이지 (닉네임 입력) ---------- */
/* 인트로 헤더는 로고만 (디자인) */
#stage.on-intro .hud-back, #stage.on-intro .hud-sound { display: none; }

/* 언어 전환 (Figma 3026:339 / 3026:671) — 인트로에서만, 사운드 버튼 자리 */
.hud-lang {
  position: absolute;
  top: 0; right: 0;
  /* 안쪽 26 고정 — ENGLISH(42)는 아이콘 기준 가운데로 넘친다(시안 x -8) */
  width: calc(54 * var(--u)); height: calc(65 * var(--u));
  box-sizing: border-box;
  padding: 0 calc(20 * var(--u)) 0 calc(8 * var(--u));
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(2 * var(--u));
  opacity: 0.8;
  color: #fff;
  font-size: calc(10 * var(--u));
  font-weight: 700;
  line-height: normal;
  letter-spacing: 0;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}
#stage.on-intro .hud-lang { display: flex; }
.hud-lang-icon {
  position: relative;
  width: calc(22 * var(--u)); height: calc(22 * var(--u));
}
/* 선 두께만큼 밖으로 나간 23.5 아트보드 — 시안 inset -3.41% */
.hud-lang-icon img { position: absolute; inset: -3.41%; width: 106.82%; height: 106.82%; display: block; }

/* 인트로는 스토리(아트 박스)와 별개 페이지 — 화면 전체를 쓰고 위에서부터 채운다.
   배경 아트는 상단 정렬(비율 그대로), 아트 밖 여백은 같은 파란색. */
#stage.on-intro { background: #9cc3e6; }
#page-intro {
  position: absolute;
  inset: 0;
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-width: none;
  top: calc(-44 * var(--u));
}
#page-intro::-webkit-scrollbar { width: 0; display: none; }
/* .l-content 가 흐름 배치라 콘텐츠가 직접 스크롤 높이를 만든다 (예전 ::after 스페이서 1004 대체) */
/* 배경 시안이 '인트로 페이지+수정'(Figma 3001:13168) 500 x 1250 으로 다시 그려졌다.
   전 시안(500x1500)은 y294 부터 보여 주려고 -230 을 밀어 놨는데, 새 시안은 프레임 좌표가
   그대로 페이지 좌표라 오프셋이 필요 없다. 콘텐츠 끝(::after 스페이서 y1004)보다 길어 다 덮는다. */
#page-intro .l-bg {
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0%;
}

/* 퍼즐판 두 장 — 배경에 구워 넣지 않고 따로 움직인다.
   좌표는 Figma 프레임 실측에서 export 블리드(그림자 20px)를 뺀 값:
     Card L 프레임 (-81.02, 25) 349.33 x 361.32  -> 이미지 (-101.11, 4.91) 389.5 x 401.5
     Card R 프레임 (267.29, 147.15) 332.47 x 343.47 -> 이미지 (247.28, 127.13) 372.5 x 383.5
   L 은 왼쪽 화면 밖에서, R 은 오른쪽 화면 밖에서 제자리로 들어온다(0.9s).
   들어온 뒤 4장이 0.5초씩 바뀐다 — 페이드 없이 steps 로 딱딱 끊는다. */
.l-card {
  position: absolute;
  z-index: 0;
  pointer-events: none;
}
.l-card img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  opacity: 0;
  /* 4장 x 0.8초 = 3.2초 주기. 슬라이드(1.35s)가 끝난 뒤부터 돈다.
     한 장 노출 시간을 바꿀 때는 주기(= 노출 x 4)와 아래 delay 를 같이 옮겨야 한다 —
     키프레임의 25% 는 1/4 지점이라 그대로 둔다. */
  animation: l-card-roll 3.2s steps(1, end) 1.35s infinite;
}
/* 슬라이드가 도는 동안에는 1번 판이 보여야 한다 — backwards fill 로 delay 구간에 0% 값(opacity 1)을 쓴다 */
.l-card img:nth-child(1) { animation-delay: 1.35s; animation-fill-mode: backwards; }
.l-card img:nth-child(2) { animation-delay: 2.15s; }
.l-card img:nth-child(3) { animation-delay: 2.95s; }
.l-card img:nth-child(4) { animation-delay: 3.75s; }
@keyframes l-card-roll {
  0%   { opacity: 1; }
  25%  { opacity: 0; }
  100% { opacity: 0; }
}
.l-card-l {
  left: calc(-101.11 * var(--u)); top: calc(4.91 * var(--u));
  width: calc(389.5 * var(--u)); height: calc(401.5 * var(--u));
  animation: l-card-in-l 1.35s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.l-card-r {
  left: calc(247.28 * var(--u)); top: calc(127.13 * var(--u));
  width: calc(372.5 * var(--u)); height: calc(383.5 * var(--u));
  animation: l-card-in-r 1.35s cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* -120% / 100% 면 제자리 기준으로 판이 화면 바깥에 완전히 나가 있다 */
@keyframes l-card-in-l {
  from { transform: translateX(-120%); }
  to   { transform: none; }
}
@keyframes l-card-in-r {
  from { transform: translateX(100%); }
  to   { transform: none; }
}
/* 가운데 컨텐츠 — 위에서부터 차례로 fade in up. 첫 요소(제목)가 0.5초, 이후 0.12초씩 밀린다.
   .l-form 은 안의 입력칸·시작버튼을 따로 띄워 계단이 끊기지 않게 한다. */
.l-title,
.l-form .l-input,
.l-form .l-start,
.l-count,
.l-share {
  animation: l-fade-up 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.l-title            { animation-delay: 0.5s; }
.l-form .l-input    { animation-delay: 0.62s; }
.l-form .l-start    { animation-delay: 0.74s; }
.l-count            { animation-delay: 0.86s; }
.l-share            { animation-delay: 0.98s; }
@keyframes l-fade-up {
  from { opacity: 0; transform: translateY(calc(24 * var(--u))); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .l-card-l, .l-card-r { animation: none; }
  .l-card img { animation: none; }
  .l-card img:nth-child(1) { opacity: 1; }
  .l-title, .l-form .l-input, .l-form .l-start, .l-count, .l-share { animation: none; }
}

/* 제목~공유 묶음. 절대 배치를 흐름으로 바꿨다 — 간격만 유지하면 제목 위치를 옮겨도
   아래가 따라 내려간다. 값은 절대 배치 시절 실측(제목 146 / 폼 502.3 / 수 713.3 / 공유 817.3)의 차이다. */
.l-content {
  position: relative;
  padding-bottom: calc(100 * var(--u));   /* 예전 스페이서(1004) 끝자리 만큼 */
}
.l-title {
  display: block;
  margin: calc(146 * var(--u)) auto 0;
  width: calc(500 * var(--u)); height: auto;
}
.l-form {
  position: relative;
  margin-top: calc(52 * var(--u));
}
.l-input {
  display: block;
  width: calc(352 * var(--u)); height: calc(68 * var(--u));
  margin: 0 auto;
  border: none;
  outline: none;
  border-radius: calc(14 * var(--u));
  background: rgba(255, 255, 255, 0.85);
  font: inherit;
  font-size: max(16px, calc(22 * var(--u)));
  font-weight: 500;
  color: #1b2b38;
  text-align: center;
}
.l-input::placeholder { color: rgba(27, 43, 56, 0.5); }
.l-start {
  display: block;
  width: calc(420 * var(--u)); height: calc(82 * var(--u));
  margin: calc(16 * var(--u)) auto 0;
  border-radius: calc(10 * var(--u));
  background: rgba(27, 43, 56, 0.7);
  font-size: calc(26 * var(--u));
  font-weight: 700;
  color: rgba(255, 255, 255, 0.75);
  transition: background 0.2s, color 0.2s;
}
/* 이름이 입력되면 활성화 — 인풋 텍스트/버튼 오퍼시티 100% */
.l-form.active .l-start { background: #1b2b38; color: #fff; }

.l-count {
  position: relative;
  margin-top: calc(45 * var(--u));
  text-align: center;
  color: #1b2b38;
}
.l-count-label { font-size: calc(24 * var(--u)); font-weight: 600; line-height: calc(29 * var(--u)); }
.l-count-num {
  margin-top: calc(8 * var(--u));
  font-size: calc(40 * var(--u));
  font-weight: 800;
  line-height: calc(40 * var(--u));
  letter-spacing: calc(-0.5 * var(--u));
}
.l-share {
  position: relative;
  margin: calc(27 * var(--u)) calc(24 * var(--u)) 0;
  border-top: 1px solid rgba(27, 43, 56, 0.6);
  text-align: center;
  color: #1b2b38;
}
.l-share-title {
  margin-top: calc(40 * var(--u));
  font-size: calc(24 * var(--u));
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
}
.l-share-count {
  margin-left: calc(8 * var(--u));
  font-size: calc(20 * var(--u));
  font-weight: 500;
  color: #1f2f3d;
  display: flex;
  align-items: center;
  opacity: .6;
}
.l-share-count b { font-weight: inherit; }
.l-share-count img {
  width: calc(20 * var(--u)); height: calc(20 * var(--u));
  margin-right: calc(4 * var(--u));
}
.l-share-icons {
  margin-top: calc(16 * var(--u));
  display: flex;
  justify-content: center;
  gap: calc(14 * var(--u));
}
.l-share-icons button,
.l-share-icons a { width: calc(68 * var(--u)); height: calc(68 * var(--u)); }
.l-share-icons img { display: block; width: 100%; height: 100%; }
.l-share-icons button.copied { border-radius: 50%; outline: calc(3 * var(--u)) solid rgba(27, 43, 56, 0.4); }

/* BGM 팝업 */
.l-bgm {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: rgba(0, 0, 0, 0.6);
}
/* 디자인 420 x 312. 카드 바탕은 공용 종이 텍스처(--img-paper) — 팝업 전용 이미지를 따로 두지 않는다 */
.l-bgm-card {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: calc(420 * var(--u)); height: calc(312 * var(--u));
  padding: calc(40 * var(--u)) calc(30 * var(--u)) calc(34 * var(--u));
  display: flex; flex-direction: column; align-items: center;
  gap: calc(24 * var(--u));
  border-radius: calc(20 * var(--u));
  background: var(--img-paper) center / cover no-repeat;
  box-shadow: 0 calc(4 * var(--u)) calc(16 * var(--u)) rgba(0, 0, 0, 0.2);
  overflow: hidden;
}
/* 텍스트 뒤 별 장식 (디자인 362.8 x 104.6 @ 30, 24) */
.l-bgm-deco {
  position: absolute;
  left: calc(30 * var(--u)); top: calc(24 * var(--u));
  width: calc(362.8 * var(--u)); height: calc(104.6 * var(--u));
  pointer-events: none;
}
.l-bgm-head {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  gap: calc(4 * var(--u));
  width: 100%;
}
.l-bgm-icon { width: calc(76 * var(--u)); height: calc(76 * var(--u)); }
.l-bgm-copy {
  width: 100%;
  font-size: calc(24 * var(--u)); font-weight: 500;
  line-height: calc(34 * var(--u));
  color: #1b2b38; text-align: center;
}
.l-bgm-copy b { font-weight: 700; }
.l-bgm-btns {
  position: relative;
  display: flex; gap: calc(12 * var(--u));
  width: 100%;
}
.l-bgm-btn {
  /* 디자인 높이 66 (= 20 + 26 + 20). 테두리는 Figma 기준 안쪽이라 padding 대신 높이로 잡는다 */
  flex: 1 0 0; min-width: 0;
  height: calc(66 * var(--u));
  display: flex; align-items: center; justify-content: center;
  padding: 0 calc(10 * var(--u));
  border: calc(1.5 * var(--u)) solid #1b2b38;
  border-radius: calc(8 * var(--u));
  font-family: inherit; font-size: calc(20 * var(--u)); font-weight: 600;
  line-height: 1.3; white-space: nowrap;
  color: #1b2b38; text-align: center;
  cursor: pointer;
}
.l-bgm-btn.mute { background: rgba(27, 43, 56, 0.1); }
.l-bgm-btn.play { background: rgba(137, 183, 224, 0.5); }

/* 뒤로가기 경고 팝업 — BGM 팝업과 같은 카드(아이콘 자리에 제목 한 줄). 디자인 420 x 272 */
.l-bgm-card.exit { height: calc(272 * var(--u)); }
.l-bgm-card.exit .l-bgm-head { gap: calc(8 * var(--u)); }
.exit-title {
  font-size: calc(24 * var(--u)); font-weight: 700;
  line-height: calc(34 * var(--u));
  color: #1b2b38; text-align: center;
}

/* 문구가 다 나온 뒤에 나타나는 요소 (디자인 주석: "멤버 목소리/텍스트 노출 후 버튼 노출") */
.after-type { visibility: hidden; }
.scene.typed .after-type { visibility: visible; }

/* 아웃트로 — HIDDEN MISSION 카드 (디자인 383 x 307 @ 58.5, 419) */
.hidden-mission {
  position: absolute;
  left: calc(58.5 * var(--u)); top: calc(424 * var(--u));
  width: calc(383 * var(--u)); height: calc(301.3 * var(--u));
  z-index: 6;
}

/* 아웃트로 ERROR 패널 — Figma 2950:30461(국문)/2980:26512(영문) 컷아웃.
   좌표·크기는 시안 실측(48.5, 362.5, 403 x 290), 라운드 15.
   그림자는 시안에 없어 CSS 로 넣는다 — 이미지에 알파가 있으니 box-shadow(사각)가 아니라
   drop-shadow 라야 라운드 모서리를 따라간다. */
.o-error-msg {
  position: absolute;
  left: calc(48.5 * var(--u)); top: calc(362.5 * var(--u));
  width: calc(403 * var(--u)); height: calc(290 * var(--u));
  filter: drop-shadow(0 calc(6 * var(--u)) calc(16 * var(--u)) rgba(0, 0, 0, 0.5));
  z-index: 6;
}

/* ---------- 아웃트로 연출 (디자인 주석) ---------- */
/* "퍼즐판이 뒤집히는 모션 연출" */
/* 앞면 = 퍼즐판, 뒷면 = 쪽지판. 판 자체가 반 바퀴 돌며 뒷면이 드러난다 */
.scene[data-scene="o-flip"] { perspective: calc(1400 * var(--u)); }
.o-flip-wrap { position: absolute; inset: 0; transform-style: preserve-3d; }
.o-flip-face { position: absolute; inset: 0; backface-visibility: hidden; transform-style: preserve-3d; }
.o-flip-face.back { transform: rotateY(180deg); }
/* 천천히, 묵직하게 — 2.2s의 2/3 */
.scene[data-scene="o-flip"].on .o-flip-wrap {
  /* easeInOutBack — 살짝 뒤로 당겼다가 돌고, 끝에서 한 번 넘겼다 제자리 */
  animation: board-flip 1.47s cubic-bezier(0.68, -0.6, 0.32, 1.6) both;
}
@keyframes board-flip {
  from { transform: rotateY(0deg); }
  to   { transform: rotateY(180deg); }
}

/* "알람 소리 & 떨리는 모션" + "눈 깜박이듯 화면 전체 깜박이더니 F.I" — 오디오는 미제공 */
/* 알람 소리가 먼저 울리고 0.5초 뒤 흔들림 시작 (문구도 같은 지연) */
/* "에러 팝업 전 화면이 지지직" (2026-09-17, 민서)
   이전 씬 배경(bg-outro)을 아래 깔고 글리치 스틸을 끊어 낸다 — 페이드가 아니라 steps 로
   딱딱 끊어야 신호가 튀는 느낌이 난다. 1.05s 동안 컷 + 좌우 찢김 + RGB 분리 + 주사선.

   트리거는 #stage[data-scene] 이 아니라 .on 이다 — main.js 가 씬마다 className 을 리셋하고
   .on 을 다시 붙이므로 재진입 때 애니메이션이 처음부터 다시 돈다(data-scene 훅은 한 번 끝나면
   안 되돌아온다).

   [ERROR] 패널은 이 연출에 섞지 않는다 — 끝난 뒤 따로 들어온다(error-panel-in). */
@keyframes glitch-cut {
  0%,  5%   { opacity: 0; }
  6%,  9%   { opacity: 1; }
  10%, 13%  { opacity: 0; }
  14%, 16%  { opacity: 1; }
  17%, 24%  { opacity: 0; }
  25%, 29%  { opacity: 1; }
  30%, 32%  { opacity: 0; }
  33%, 43%  { opacity: 1; }
  44%, 47%  { opacity: 0; }
  48%, 55%  { opacity: 1; }
  56%, 58%  { opacity: 0; }
  59%, 72%  { opacity: 1; }
  73%, 75%  { opacity: 0; }
  76%, 100% { opacity: 1; }
}
/* 프레임이 좌우로 찢기고 세로로 눌린다 — 아날로그 신호가 흔들리는 모양 */
@keyframes glitch-skew {
  0%, 5%    { transform: none; }
  6%        { transform: translateX(calc(-9 * var(--u))) scaleX(1.035); }
  10%       { transform: translateX(calc(6 * var(--u))) scaleY(0.99); }
  14%       { transform: translateX(calc(-4 * var(--u))) scaleX(1.02); }
  17%, 24%  { transform: none; }
  25%       { transform: translateX(calc(7 * var(--u))) scaleY(1.015); }
  30%       { transform: translateX(calc(-6 * var(--u))); }
  33%       { transform: translateX(calc(2 * var(--u))) scaleX(1.01); }
  44%       { transform: translateX(calc(-7 * var(--u))) scaleY(0.985); }
  48%       { transform: translateX(calc(3 * var(--u))); }
  56%       { transform: translateX(calc(-3 * var(--u))) scaleX(1.015); }
  59%, 72%  { transform: none; }
  73%       { transform: translateX(calc(4 * var(--u))); }
  76%, 100% { transform: none; }
}
/* 색이 어긋나 번지는 구간 — 컷이 붙는 순간에만 짧게 */
@keyframes glitch-rgb {
  0%, 5%, 17%, 24%, 59%, 72%, 76%, 100% { filter: none; }
  6%, 10%  { filter: drop-shadow(calc(4 * var(--u)) 0 0 rgba(255, 0, 64, 0.75)) drop-shadow(calc(-4 * var(--u)) 0 0 rgba(0, 224, 255, 0.75)); }
  14%      { filter: drop-shadow(calc(-3 * var(--u)) 0 0 rgba(255, 0, 64, 0.6)) drop-shadow(calc(3 * var(--u)) 0 0 rgba(0, 224, 255, 0.6)) contrast(1.4); }
  25%, 30% { filter: drop-shadow(calc(-5 * var(--u)) 0 0 rgba(255, 0, 64, 0.7)) drop-shadow(calc(5 * var(--u)) 0 0 rgba(0, 224, 255, 0.7)); }
  33%      { filter: invert(1) hue-rotate(90deg); }
  44%, 48% { filter: drop-shadow(calc(3 * var(--u)) 0 0 rgba(255, 0, 64, 0.65)) drop-shadow(calc(-3 * var(--u)) 0 0 rgba(0, 224, 255, 0.65)) saturate(1.6); }
  56%      { filter: invert(1); }
  73%      { filter: drop-shadow(calc(-2 * var(--u)) 0 0 rgba(255, 0, 64, 0.5)) drop-shadow(calc(2 * var(--u)) 0 0 rgba(0, 224, 255, 0.5)); }
}
#bg-glitch.on {
  animation:
    glitch-cut  1.05s steps(1, end) both,
    glitch-skew 1.05s steps(1, end) both,
    glitch-rgb  1.05s steps(1, end) both;
}
/* [ERROR] 패널은 지지직이 다 끝난 뒤에 나온다 (2026-09-17 요청).
   그래서 배경은 패널이 구워지지 않은 bg-glitch-v4 를 쓴다 — v2 에는 국문 패널이 박혀 있어
   이펙트 중에 패널이 먼저 보이고, 영문에서는 국문 문구가 비쳤다.
   등장도 페이드가 아니라 한 번 깜박이고 붙는 컷. */
.scene[data-scene="o-error"].on .o-error-msg {
  animation: error-panel-in 0.28s steps(1, end) 1.05s both;
}
@keyframes error-panel-in {
  0%        { opacity: 0; }
  25%, 44%  { opacity: 1; }
  45%, 59%  { opacity: 0; }
  60%, 100% { opacity: 1; }
}
/* 주사선 + 화면 전체 플래시 — 신호가 튀는 동안만 위로 흐른다 */
.scene[data-scene="o-error"].on::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 7;
  pointer-events: none;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, 0.11) 0,
      rgba(255, 255, 255, 0.11) calc(1 * var(--u)),
      transparent calc(1 * var(--u)),
      transparent calc(4 * var(--u))
    );
  animation: glitch-scan 1.05s steps(1, end) both;
}
@keyframes glitch-scan {
  0%, 5%    { opacity: 0; transform: translateY(0); }
  6%        { opacity: 1; transform: translateY(calc(-30 * var(--u))); }
  10%       { opacity: 0.7; transform: translateY(calc(40 * var(--u))); }
  14%       { opacity: 1; transform: translateY(calc(-12 * var(--u))); }
  17%, 24%  { opacity: 0; transform: translateY(0); }
  25%       { opacity: 1; transform: translateY(calc(26 * var(--u))); }
  33%       { opacity: 0.8; transform: translateY(calc(-20 * var(--u))); }
  44%       { opacity: 1; transform: translateY(calc(14 * var(--u))); }
  56%       { opacity: 0.8; transform: translateY(calc(-8 * var(--u))); }
  59%, 100% { opacity: 0; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  #bg-glitch.on,
  .scene[data-scene="o-error"].on .o-error-msg,
  .scene[data-scene="o-error"].on::before { animation: none; opacity: 1; }
  .scene[data-scene="o-error"].on::before { display: none; }
}

#stage[data-scene="o-alarm"] #bg-layer { animation: alarm-shake 0.9s linear 0.5s 3; }
@keyframes alarm-shake {
  0%, 100% { transform: translate(0, 0); }
  10% { transform: translate(calc(-3 * var(--u)), calc(2 * var(--u))); }
  20% { transform: translate(calc(3 * var(--u)), calc(-2 * var(--u))); }
  30% { transform: translate(calc(-2 * var(--u)), calc(-2 * var(--u))); }
  40% { transform: translate(calc(2 * var(--u)), calc(2 * var(--u))); }
  50% { transform: translate(0, 0); }
}
.scene[data-scene="o-alarm"].on::before {
  content: "";
  position: absolute;
  inset: 0;
  background: #000;
  z-index: 4;
  pointer-events: none;
  animation: alarm-blink 1.6s ease-out forwards;
}
@keyframes alarm-blink {
  0%, 6%   { opacity: 1; }
  12%, 18% { opacity: 0; }
  24%, 30% { opacity: 1; }
  36%      { opacity: 0; }
  48%      { opacity: 1; }
  100%     { opacity: 0; }
}

/* ---------- 영문판 ----------
   영문 로고(BANGGOOSO)는 국문 로고보다 가로로 길다(6.65:1 vs 4.98:1).
   cover 로 두면 양옆이 잘리므로 폭을 늘리고 contain 으로 바꾼다. 중앙 정렬 유지(250 - 157/2). */
/* 아티스트 대사 행간 — 영문 시안은 27px(국문 29.4px).
   실측: 케이주·민제·동현·주왕·계훈 5화면 전부 줄간격 27px, 글자 크기는 21px 그대로.
   3줄 기준 블록이 81px라 100px 박스 안에서 중앙 정렬되고, 4줄(계훈)이면
   시안과 똑같이 위아래로 4px씩 넘친다. */
.gl306.en .artist-box .bubble-text { line-height: 1.4; }

/* ---------- 2026-09-16 영문 검수 반영 ---------- */
/* 말풍선: 영문은 줄이 더 늘어나 박스를 넘친다 — 140 -> 160, 안쪽 라인 405x125 -> 405x145 */
.gl306.en .artist-box { height: calc(160 * var(--u)); }
.gl306.en .artist-box::before { height: calc(145 * var(--u)); }
.gl306.en .artist-box .bubble-text { height: calc(120 * var(--u)); }
/* 동화 첫 화면(dh-intro)만 네 줄이라 한 단계 줄인다 */
.gl306.en .scene[data-scene="dh-intro"] .artist-box .bubble-text { font-size: calc(20 * var(--u)); }
/* 이름표: Donghyeon 처럼 긴 이름이 박스 밖으로 나가지 않게 오른쪽 기준으로 잡는다 */
.gl306.en .artist-name { left: auto; right: calc(9 * var(--u)); }
/* 아웃트로 퍼즐판 안내 문구 semibold */
.gl306.en .puzzle-title { font-weight: 600; }
/* 자명종 영상: 영문은 433x538 (국문 401x498) — 가운데를 유지해 위치도 같이 옮긴다 */
.gl306.en .watch-video {
  left: calc(47 * var(--u)); top: calc(276 * var(--u));
  width: calc(433 * var(--u)); height: calc(538 * var(--u));
}
/* 결과 최상단·이벤트 문구 28 -> 26 */
.gl306.en .r-title,
.gl306.en .r-event-copy { font-size: calc(26 * var(--u)); }

/* 영문 타이틀은 아트 크기·여백이 국문과 달라 시안(2939:23776) 실측값으로 따로 잡는다 */
/* 영문 제목도 국문과 같은 만큼(+43) 내렸다 — 배경 아트와 겹쳤다 (2026-09-17) */
/*.gl306.en .l-title {*/
/*  margin-top: calc(157 * var(--u));*/
/*}*/
.gl306.en .hud-logo {
  left: calc(171.5 * var(--u));
  width: calc(157 * var(--u));
  object-fit: contain;
}
