/* 「두 사람의 AI 쇼츠」 — 뷰어(릴스급) · 생성 흐름 공용 스타일
 * 합격선: vault 80 §뷰어 품질 기준 7항목.
 * 원칙 — 애니메이션은 transform/opacity 만 쓴다(레이아웃 애니메이션 금지 → 60fps).
 */

:root {
  --ink: #f4efe7;
  --ink-dim: rgba(244, 239, 231, 0.66);
  --ink-faint: rgba(244, 239, 231, 0.4);
  --bg: #0b0d10;
  --gold: #e8c489;
  --rose: #e6a6ad;
  --line: rgba(244, 239, 231, 0.16);
  --pad: 18px;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --font: 'Pretendard', 'Apple SD Gothic Neo', 'Malgun Gothic', system-ui, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

body.reels {
  overflow: hidden;
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
}

/* ─────────────────────────── 피드 (스크롤 스냅) ─────────────────────────── */

.feed {
  height: 100dvh;
  height: 100svh;
  overflow-y: scroll;
  overflow-x: hidden;
  scroll-snap-type: y mandatory;
  scroll-behavior: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.feed::-webkit-scrollbar { display: none; }

.slide {
  position: relative;
  height: 100dvh;
  height: 100svh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: #000;
  contain: layout paint;
}

/* 9:16 무대 — 세로 화면은 꽉 채우고, 가로/데스크톱은 중앙 세로 레터박스 */
.stage {
  position: relative;
  width: 100%;
  height: 100%;
  /* 폰에서는 항상 화면 폭을 꽉 채운다(가장자리 검은 띠 금지 — 영상은 object-fit:cover 로 잘린다).
     데스크톱에서만 세로 한 칸으로 좁힌다. */
  max-width: min(100%, 520px);
  margin-inline: auto;
  background: #000;
  overflow: hidden;
}

.stage video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: transparent;
  /* 합성 레이어로 올려 스크롤 중 재도색을 줄인다 */
  will-change: transform;
  transform: translateZ(0);
}

/* 포스터 프레임 대역 — 영상 첫 프레임이 그려지기 전까지 이 판이 video 「위」를 덮는다.
   ⚠ video 아래가 아니라 위다. 로딩 중 브라우저가 그리는 기본 재생 글리프(회색 삼각형)와
      빈 영상 회색 판이 단 한 프레임도 새어 나오면 안 된다 — 그래서 덮개를 위에 얹는다.
   서버가 posterUrl 을 주면 그 이미지가 배경으로 얹히고, 없으면 주제색 그라데이션이 그대로 폴백이다. */
.poster {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-color: var(--poster-a, #1b2430);
  background-image:
    radial-gradient(120% 80% at 50% 22%, var(--poster-b, #33455c) 0%, transparent 62%),
    linear-gradient(180deg, var(--poster-a, #1b2430) 0%, #06080b 100%);
  background-size: cover;
  background-position: center;
  opacity: 1;
  transition: opacity 260ms ease;
}
/* 포스터 사진층 — 그라데이션 판 「위」의 별도 층.
   ⚠ 사진을 위 .poster 에 직접 얹으면 안 된다: 받는 동안 그 판이 빈 검정으로 보인다
      (2026-08-16 라이브 검수 [중-1] 순검정 rgb(6,8,11) 8초). 다 받은 뒤에만 data-shown 으로 얹는다. */
.poster-img {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity 240ms ease;
}
.poster-img[data-shown='1'] { opacity: 1; }
/* 사진 위에 아주 옅은 어둠만 얹어 밝기 튐을 막는다 */
.poster-img[data-shown='1']::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.18) 0%, rgba(0,0,0,0.34) 100%);
}
/* 첫 프레임이 그려지면 두 판 다 걷는다.
   재생 중 멈췄을 때는 도로 안 올린다 — 멈춘 마지막 프레임이 그대로 남는 편이 자연스럽고,
   '지금 기다리는 중'은 펄스 로더가 말한다. */
.slide[data-ready='1'] .poster,
.slide[data-ready='1'] .poster-img { opacity: 0; }

/* 로딩 링 — 글자도 아이콘도 없다. 아직 안 그려졌거나 버퍼링 중일 때만 보인다.
   ⚠ 채워진 흰 원은 쓰지 않는다: 밝은 장면(얼굴 클로즈업) 위에서 '코에 찍힌 흰 점'으로 보인다.
      부트 화면과 같은 얇은 링 문법으로 통일하고, 어두운 후광으로 어떤 배경에서도 읽히게 한다. */
.poster-mark {
  position: absolute;
  top: 50%; left: 50%;
  z-index: 3;
  width: 30px;
  height: 30px;
  margin: -15px 0 0 -15px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: rgba(255, 255, 255, 0.92);
  box-shadow: 0 0 16px 5px rgba(0, 0, 0, 0.26);
  pointer-events: none;
  opacity: 0;
}
/* 보일 때만 돌린다(회전 keyframes 는 opacity 를 건드리지 않으므로 여기서 같이 켠다). */
.slide:not([data-ready='1']) .poster-mark,
.slide[data-buffering='1'] .poster-mark {
  opacity: 1;
  animation: spin 900ms linear infinite;
}

/* 하단 그라데이션 오버레이 */
.veil {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 52%;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.28) 42%, rgba(0,0,0,0.78) 100%);
}
.veil--top {
  top: 0; bottom: auto; height: 28%;
  background: linear-gradient(180deg, rgba(0,0,0,0.6) 0%, rgba(0,0,0,0) 100%);
}

.meta {
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  bottom: calc(22px + var(--safe-b));
  pointer-events: none;
  display: grid;
  gap: 6px;
}
/* 좌하단에 남는 것은 「내가 만든 편」 배지 하나뿐 —
   주제 라벨·「하객이 만든 한 편」은 발주자 지시로 화면에서 뺐다(app.js 참조). */
.meta--badge-only {
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
.badge-mine {
  flex: none;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid rgba(232, 196, 137, 0.5);
  background: rgba(232, 196, 137, 0.15);
  color: var(--gold);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-shadow: none;
  white-space: nowrap;
}
.meta .line {
  margin: 0;
  font-size: 14px;
  color: var(--ink-dim);
  line-height: 1.45;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ─────────────────────────── 상단 바 ─────────────────────────── */

.topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  padding-top: var(--safe-t);
  z-index: 30;
  pointer-events: none;
}

.progressbar {
  height: 2.5px;
  background: rgba(255, 255, 255, 0.18);
  overflow: hidden;
}
.progressbar i {
  display: block;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--gold), #fff);
  transform: scaleX(0);
  transform-origin: 0 50%;
  /* 폭이 아니라 transform 을 움직인다 — 레이아웃 재계산 없음 */
  will-change: transform;
}

/* 워드마크가 sr-only 로 빠져 있어도 소리 버튼은 우상단에 그대로 있어야 한다
   (space-between 이면 남은 한 개가 왼쪽으로 붙는다 → flex-end 로 고정). */
.topbar-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 10px var(--pad) 0;
}
/* 릴스 기준: 워드마크는 '있는 듯 없는 듯' — 홈페이지 헤더처럼 읽히면 안 된다. */
.wordmark {
  margin: 0;
  font-size: 12.5px;
  font-weight: 600;
  opacity: 0.7;
  letter-spacing: -0.01em;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.6);
}

/* 소리 버튼 — 글자 없는 원형 아이콘(릴스식) */
.sound {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: none;
  background: rgba(0, 0, 0, 0.34);
  backdrop-filter: blur(8px);
  color: var(--ink);
  border-radius: 50%;
  font: inherit;
  cursor: pointer;
  transition: transform 140ms ease, background 140ms ease;
}
.sound:active { transform: scale(0.94); }
.sound-icon { display: block; }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
/* aria-pressed=false = 음소거 상태 → 빗금, 파동 없음 */
.sound[aria-pressed='false'] .sound-waves,
.sound[aria-pressed='true'] .sound-slash { display: none; }

/* 음소거 토글 중앙 피드백 — 릴스처럼 크게 떴다가 0.6초에 사라진다 */
.mute-pop {
  position: fixed;
  top: 50%; left: 50%;
  z-index: 27;
  width: 88px;
  height: 88px;
  margin: -44px 0 0 -44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, 0.46);
  backdrop-filter: blur(10px);
  color: #fff;
  pointer-events: none;
  animation: mute-pop 620ms ease both;
}
.mute-pop[data-muted='0'] .sound-slash { display: none; }
.mute-pop[data-muted='1'] .sound-waves { display: none; }
@keyframes mute-pop {
  0% { opacity: 0; transform: scale(0.82); }
  18% { opacity: 1; transform: scale(1); }
  70% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.04); }
}

/* ─────────────────────────── 힌트 · 배지 ─────────────────────────── */

.hint {
  position: fixed;
  left: 50%;
  bottom: calc(96px + var(--safe-b));
  transform: translateX(-50%);
  z-index: 25;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  font-size: 13px;
  letter-spacing: -0.01em;
  pointer-events: none;
  animation: hint-in 320ms ease both;
}
.hint[data-leaving] { animation: hint-out 260ms ease both; }
.hint-arrow {
  width: 9px; height: 9px;
  border-left: 2px solid var(--gold);
  border-top: 2px solid var(--gold);
  transform: rotate(45deg);
  animation: nudge 1.5s ease-in-out infinite;
}
@keyframes nudge {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: 0.6; }
  50% { transform: rotate(45deg) translate(2px, 2px); opacity: 1; }
}
@keyframes hint-in { from { opacity: 0; transform: translateX(-50%) translateY(8px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
@keyframes hint-out { to { opacity: 0; transform: translateX(-50%) translateY(-6px); } }

.paused-badge {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  z-index: 26;
  padding: 10px 18px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  font-size: 13px;
  letter-spacing: 0.04em;
  pointer-events: none;
}

/* ─────────────────────────── 마지막 유도 슬라이드 ─────────────────────────── */

.slide--outro {
  background: radial-gradient(120% 90% at 50% 18%, #1a1f28 0%, #08090c 68%);
}
.outro {
  max-width: 380px;
  padding: 0 26px calc(30px + var(--safe-b));
  text-align: center;
  display: grid;
  gap: 14px;
  justify-items: center;
}
.outro .eyebrow {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.16em;
  color: var(--gold);
}
/* 한국어 줄바꿈: 어절 단위로 끊는다 — 「이야/기예요」처럼 단어 중간이 갈리면 안 된다
   (2026-08-16 라이브 검수 [소-1]). */
.outro h2 {
  margin: 0;
  font-size: 21px;
  line-height: 1.5;
  font-weight: 700;
  letter-spacing: -0.01em;
  word-break: keep-all;
  overflow-wrap: break-word;
}
.outro p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.72;
  color: var(--ink-dim);
  word-break: keep-all;
  overflow-wrap: break-word;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 22px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: transform 140ms ease, opacity 140ms ease;
}
.btn:active { transform: scale(0.98); }
.btn--primary {
  background: linear-gradient(135deg, var(--gold), var(--rose));
  border-color: transparent;
  color: #23180f;
}
.btn--quiet { color: var(--ink-dim); }
.btn[disabled] { opacity: 0.5; pointer-events: none; }

/* ─────────────────────────── 부트 · 빈 상태 ─────────────────────────── */

/* ⚠ `[hidden]` 의 display:none 은 특이도가 0 이라 아래 display:grid 에 진다.
   이 한 줄을 빼면 다 숨긴 오버레이가 화면 전체를 덮은 채로 남아 **스와이프·탭을 전부 삼킨다**
   (2026-08-16 실측: 스크롤 0 고정 + 탭이 숨은 버튼을 눌러 게임으로 이동). */
.boot[hidden], .empty[hidden], .hint[hidden], .paused-badge[hidden], .mute-pop[hidden] { display: none !important; }

.boot, .empty {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  text-align: center;
  padding: 0 30px;
  background: radial-gradient(120% 90% at 50% 20%, #171c24 0%, #08090c 70%);
}
.boot p { margin: 0; color: var(--ink-dim); font-size: 14px; }
.boot-mark {
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 1.5px solid rgba(232, 196, 137, 0.35);
  border-top-color: var(--gold);
  animation: spin 900ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.empty .eyebrow { margin: 0; font-size: 12px; letter-spacing: 0.16em; color: var(--gold); }
.empty h2 { margin: 0; font-size: 22px; line-height: 1.5; font-weight: 700; }
.empty-copy { margin: 0; font-size: 14.5px; line-height: 1.75; color: var(--ink-dim); }
.empty-actions { margin-top: 8px; display: grid; gap: 10px; justify-items: center; }

/* ─────────────────────────── 움직임 최소화 존중 ─────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .feed { scroll-behavior: auto; }
  .poster-mark { animation: none; }
  .hint-arrow { animation: none; }
  /* 페이드 없이 그냥 잠깐 보였다 사라진다(표시 자체는 유지) */
  .mute-pop { animation: none; opacity: 1; transform: none; }
}
