/* Pretendard — 900 웨이트를 어느 PC에서나 쓰려고 넣었다.
   CDN이 아니라 파일을 직접 담고 있어 외부 요청이 없고 오프라인에서도 뜬다.
   페이지에 실제로 쓰는 274자만 남긴 서브셋이라 4종 합쳐 84KB다
   (원본 전체 한글은 3.0MB). 카피를 고치면 글자가 빠질 수 있으므로
   서브셋을 다시 만들어야 한다 — 만드는 법은 README의 Fonts 항목 참고.
   라이선스: SIL OFL 1.1, assets/fonts/LICENSE.txt */
@font-face {
  font-family: "Pretendard";
  src: url("assets/fonts/Pretendard-Regular.subset.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  src: url("assets/fonts/Pretendard-SemiBold.subset.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  src: url("assets/fonts/Pretendard-Bold.subset.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  src: url("assets/fonts/Pretendard-Black.subset.woff2") format("woff2");
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

/* 디자인 토큰 — 20260731-www-mgy-kr-source-mirror를 1920px에서 실제로 띄워
   렌더된 값을 재서 옮겼다(css 파일의 선언이 아니라 계산된 결과 기준).
   그쪽도 near-black 팔레트라 색은 우리 것을 유지하고, 임팩트를 만드는 축인
   타입 계단·웨이트·자간·행간·여백만 가져왔다.

   원본 계단 @1920: 180 → 140 → 80 → 64 → 48 → 36 → 28 → 24 → 22
   중요한 건 크기가 아니라 세 규칙이다:
     · 22px 아래로 내려가는 텍스트가 하나도 없다 (그래서 작은 글씨가 안 초라하다)
     · 모든 단계에 음수 자간이 걸린다 (-0.04em → -0.01em, 클수록 더 조인다)
     · 행간은 디스플레이만 1.0~1.15, 나머지는 전부 1.5로 통일
   셋 중 하나만 빠져도 "그냥 큰 글씨"가 된다. */
:root {
  --color-bg: #0a0a0c;
  --color-fg: #f4f1ea;
  --color-muted: #b9b3a6;
  --color-accent: #c9a24b;
  --hero-height: 320vh;

  /* 타입 계단 — 오른쪽 최대값이 원본 실측치 */
  --fs-display: clamp(48px, 11vw, 180px);   /* .hero h1 */
  --fs-statement: clamp(40px, 9vw, 140px);  /* .keyword-line */
  --fs-number: clamp(40px, 6vw, 80px);      /* .count-up */
  --fs-section: clamp(32px, 5vw, 64px);     /* .section-title */
  --fs-h3: clamp(24px, 2.4vw, 36px);        /* H3 */
  --fs-lead: clamp(19px, 1.8vw, 28px);      /* .package-name */
  --fs-body: clamp(16px, 1.4vw, 22px);      /* .hero-subtitle, p */
  --fs-label: clamp(13px, 1vw, 17px);       /* 라벨류 — 원본엔 없는 단계 */

  --fw-black: 900;
  --fw-bold: 700;

  /* 자간 — 크기 단계마다 다르다 */
  --ls-display: -0.04em;
  --ls-title: -0.03em;
  --ls-mid: -0.02em;
  --ls-text: -0.01em;

  /* 행간 */
  --lh-display: 1.05;
  --lh-title: 1.15;
  --lh-text: 1.5;

  /* 여백 스케일 */
  --space-sm: 16px;
  --space-md: 24px;
  --space-lg: 48px;
  --space-xl: 80px;
  --space-2xl: 120px;
  --space-3xl: 160px;

  /* 이징 */
  --ease-fast: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  --ease-smooth: 0.6s cubic-bezier(0.16, 1, 0.3, 1);
  --ease-slow: 1s cubic-bezier(0.16, 1, 0.3, 1);

  /* 원본 프레임(1176x1760) 아래쪽 120px에 KlingAI 워터마크가 구워져 있다.
     잘라낸 뒤의 유효 비율 — script.js의 WATERMARK_CROP과 반드시 같이 움직인다. */
  --frame-w: 1176;
  --frame-h: 1640;

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

* {
  box-sizing: border-box;
}

html {
  background: var(--color-bg);
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-fg);
  font-family: "Pretendard", "Apple SD Gothic Neo", "Malgun Gothic", -apple-system, BlinkMacSystemFont, sans-serif;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--color-accent);
  color: #14100a;
  padding: 0.75rem 1rem;
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus {
  left: 1rem;
  top: 1rem;
}

/* ---------- Hero ---------- */

.hero {
  position: relative;
  height: var(--hero-height);
}

.hero__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  width: 100%;
  overflow: hidden;
  background: #000;
  padding-top: var(--safe-top);
  padding-left: var(--safe-left);
  padding-right: var(--safe-right);
}

/* 세로 화면에서는 스테이지를 꽉 채우고, 아래 미디어쿼리에서 넓은 화면일 때만
   원본 비율(워터마크 잘라낸 1176x1640) 상자로 좁혀 가운데 놓는다. */
.hero__frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* 캔버스가 뜨기 전 잠깐 보이는 포스터. 캔버스는 JS에서 워터마크를 잘라내지만
   이쪽은 CSS로 잘라야 한다 — 상자보다 세로로 길게 잡고 위를 기준으로 붙여
   넘치는 아래(워터마크)가 .hero__frame의 overflow에 잘리게 한다. */
.hero__poster {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: calc(100% * 1760 / var(--frame-h));
  object-fit: cover;
  object-position: center top;
}

.hero__canvas {
  opacity: 0;
  transition: opacity 0.4s ease;
}
.hero__canvas.is-ready {
  opacity: 1;
}
.hero__poster.is-hidden {
  opacity: 0;
  transition: opacity 0.4s ease;
}

.hero__vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.75) 100%),
    linear-gradient(to bottom, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0.05) 28%, rgba(0, 0, 0, 0.1) 60%, rgba(0, 0, 0, 0.85) 100%);
}

.hero__grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: repeating-radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.6) 0, transparent 1px),
    repeating-radial-gradient(circle at 3px 4px, rgba(255, 255, 255, 0.4) 0, transparent 1px);
  background-size: 5px 5px, 7px 7px;
}

.hero__content {
  /* 액자 밖, 스테이지 전체를 덮는 오버레이. 화면 폭 전체를 쓰므로 카피가
     액자 크기에 갇히지 않고 vw 스케일로 커진다. */
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  pointer-events: none;
  padding: 0 clamp(1.5rem, 5vw, 7rem) calc(var(--space-xl) + var(--safe-bottom));
}

.hero__content > * {
  pointer-events: auto;
}

.hero__eyebrow {
  margin: 0 0 var(--space-md);
  font-size: var(--fs-label);
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--color-accent);
  font-weight: var(--fw-bold);
}

/* 헤드라인은 붓글씨 이미지다. 글자 크기 대신 폭으로 스케일을 잡고,
   원본 비율(1163x575)은 aspect-ratio가 아니라 width/height 속성이 지킨다. */
.hero__headline {
  margin: 0 0 var(--space-md);
  line-height: 0;
}

.hero__headline img {
  display: block;
  width: clamp(17rem, 46vw, 62rem);
  height: auto;
  /* 검은 배경에서 획이 떠 보이도록 아주 옅은 글로우만 준다 */
  filter: drop-shadow(0 4px 34px rgba(0, 0, 0, 0.85));
}

.hero__sub {
  margin: 0 0 var(--space-lg);
  font-size: var(--fs-lead);
  line-height: var(--lh-text);
  letter-spacing: var(--ls-mid);
  font-weight: var(--fw-bold);
  color: var(--color-fg);
  max-width: 46rem;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.8);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

/* ---------- 세로 화면: 히어로 카피 퇴장 ---------- */
/* 카피가 영상을 덮는 화면에서만 켠다 — 액자 미디어쿼리(min-aspect-ratio: 1176/1496)의
   정확한 여집합이라 넓은 화면에서는 이 블록 자체가 적용되지 않는다.
   진행도(--hx-*)는 script.js 가 넣는다. 0 = 제자리, 1 = 완전히 빠짐.
   도너: 한화 kv-title-char-rise 의 translateY(105%)·Quint.easeOut 을 뒤집은 것. */
@media (max-aspect-ratio: 1176/1496) {
  .hero__eyebrow,
  .hero__headline,
  .hero__sub,
  .hero__actions {
    will-change: transform, opacity;
  }

  .hero__actions {
    transform: translateY(calc(var(--hx-actions, 0) * -105%));
    opacity: calc(1 - var(--hx-actions, 0));
  }

  .hero__sub {
    transform: translateY(calc(var(--hx-sub, 0) * -105%));
    opacity: calc(1 - var(--hx-sub, 0));
  }

  .hero__headline {
    transform: translateY(calc(var(--hx-head, 0) * -105%));
    opacity: calc(1 - var(--hx-head, 0));
  }

  .hero__eyebrow {
    transform: translateY(calc(var(--hx-eyebrow, 0) * -105%));
    opacity: calc(1 - var(--hx-eyebrow, 0));
  }

  /* 다 빠진 뒤에는 안 보이는 버튼이 탭을 먹지 않게 한다 */
  .hero__content.is-copy-gone > * {
    pointer-events: none;
  }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 1.05rem 2rem;
  border-radius: 999px;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-text);
  font-weight: var(--fw-bold);
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.2s ease, background 0.2s ease, border-color 0.2s ease;
}
.btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}
.btn--primary {
  background: var(--color-accent);
  color: #14100a;
}
.btn--primary:hover {
  transform: translateY(-2px);
}
.btn--ghost {
  background: rgba(255, 255, 255, 0.06);
  color: var(--color-fg);
  border-color: rgba(244, 241, 234, 0.35);
  backdrop-filter: blur(6px);
}
.btn--ghost:hover {
  border-color: var(--color-fg);
  transform: translateY(-2px);
}

/* ---------- 히어로 다음 본문 ---------- */

/* 음수 margin으로 히어로 마지막 100vh와 겹쳐 둔다. 전환 효과는 이 겹친
   구간에서 .page를 "드러내는" 방식으로 동작하고, 전환이 끝나는 지점이
   마침 .page의 첫 줄이 화면 맨 위에 닿는 순간이라 이후 스크롤이 자연스럽다. */
.page {
  position: relative;
  z-index: 3;
  margin-top: -100vh;
  min-height: 100vh;
  background: var(--color-bg);
}

.section__eyebrow {
  margin: 0 0 var(--space-md);
  font-size: var(--fs-label);
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--color-accent);
  font-weight: var(--fw-bold);
}

.section__title {
  margin: 0 0 var(--space-xl);
  font-size: var(--fs-section);
  line-height: var(--lh-title);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-title);
}

/* ---------- 시놉시스 ---------- */

.synopsis {
  padding: clamp(6rem, 14vh, 11rem) clamp(1.5rem, 6vw, 8rem);
  max-width: 78rem;
}

.synopsis__lead {
  margin: 0 0 var(--space-xl);
  font-size: var(--fs-statement);
  line-height: 1.1;
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-display);
  word-break: keep-all;
}

.synopsis__body {
  margin: 0;
  max-width: 46rem;
  color: var(--color-muted);
  font-size: var(--fs-body);
  line-height: var(--lh-text);
  letter-spacing: var(--ls-text);
  word-break: keep-all;
}

/* ---------- 등장인물 ---------- */

.cast {
  padding: clamp(4rem, 10vh, 8rem) clamp(1.5rem, 6vw, 8rem);
  border-top: 1px solid rgba(244, 241, 234, 0.08);
}

.cast__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1px;
  max-width: 90rem;
  background: rgba(244, 241, 234, 0.1);
  border: 1px solid rgba(244, 241, 234, 0.1);
}

.cast__card {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding: 2.6rem 1.6rem 1.9rem;
  background: #0c0c0f;
  height: clamp(21rem, 44vh, 31rem);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* 인물 사진(ima2 생성, 2:3). 얼굴이 잘리지 않게 위쪽 기준으로 크롭한다. */
.cast__card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background-size: cover;
  background-position: center top;
  filter: saturate(0.85) contrast(1.04);
  transition: transform 0.7s ease;
}

.cast__card:hover::before {
  transform: scale(1.045);
}

/* 아래쪽 스크림 — 이름·설명이 사진 위에서도 읽히게 */
.cast__card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to bottom,
    rgba(10, 10, 12, 0.3) 0%,
    rgba(10, 10, 12, 0) 26%,
    rgba(10, 10, 12, 0.72) 58%,
    rgba(10, 10, 12, 0.96) 100%);
}

.cast__card--1::before { background-image: url("assets/cast/seorihan.jpg"); }
.cast__card--2::before { background-image: url("assets/cast/baekyeon.jpg"); }
.cast__card--3::before { background-image: url("assets/cast/domungyeong.jpg"); }
.cast__card--4::before { background-image: url("assets/cast/muyeong.jpg"); }

.cast__hanja {
  position: absolute;
  top: 1.3rem;
  right: 1.4rem;
  font-size: 1.9rem;
  line-height: 1;
  font-weight: 700;
  color: rgba(201, 162, 75, 0.72);
  letter-spacing: 0.05em;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.8);
}

.cast__name {
  margin: 0 0 0.5rem;
  font-size: var(--fs-h3);
  font-weight: var(--fw-black);
  line-height: var(--lh-title);
  letter-spacing: var(--ls-title);
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.7);
}

.cast__role {
  margin: 0 0 var(--space-sm);
  font-size: var(--fs-label);
  letter-spacing: 0.24em;
  color: var(--color-accent);
  font-weight: var(--fw-bold);
}

.cast__line {
  margin: 0;
  color: var(--color-muted);
  font-size: var(--fs-body);
  line-height: var(--lh-text);
  letter-spacing: var(--ls-text);
  word-break: keep-all;
}

/* ---------- 스틸 ---------- */

/* 세로 스크롤을 가로 이동으로 바꾸는 핀 구간.
   .stills__pin의 남는 높이만큼 .stills__sticky가 붙어 있고, 그 사이의
   스크롤 진행도를 script.js가 .stills__track의 translateX로 바꾼다. */
.stills {
  border-top: 1px solid rgba(244, 241, 234, 0.08);
}

.stills__pin {
  height: 320vh;
}

.stills__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(1.4rem, 4vh, 3rem);
  overflow: hidden;
}

.stills__head {
  padding: 0 clamp(1.5rem, 6vw, 8rem);
  flex: 0 0 auto;
}

.stills__head .section__title {
  margin-bottom: 0;
}

.stills__track {
  display: flex;
  gap: clamp(0.6rem, 1.4vw, 1.4rem);
  padding: 0 clamp(1.5rem, 6vw, 8rem);
  will-change: transform;
  flex: 0 0 auto;
  /* 세로 플렉스(.stills__sticky) 안에서는 기본이 stretch라 트랙이 화면 너비로
     줄어든다. 그러면 이동 거리(scrollWidth - 화면너비)가 0이 돼 핀이 안 먹는다.
     실제 내용 너비를 갖도록 max-content로 고정한다. */
  width: max-content;
  align-self: flex-start;
}

/* 칸(슬롯)은 폭이 고정이다 — 여기가 흔들리면 트랙 전체 폭이 바뀌어
   핀 이동 거리 계산이 매 프레임 달라진다. 실제로 벌어지는 건 안쪽의
   .stills__shot이고, 그것은 absolute라 레이아웃에 영향을 주지 않는다. */
.stills__item {
  --f: 0;          /* 화면 중앙에 가까울수록 1 (script.js가 넣는다) */
  --expand: 48%;   /* 중앙에서 좌우로 벌어지는 총량 */
  margin: 0;
  flex: 0 0 auto;
  position: relative;
  /* 최대폭이 작으면 초광폭 화면(3440)에서 10칸이 화면에 다 들어가버려
     이동 거리(scrollWidth - 화면너비)가 0이 되고 핀이 무의미해진다.
     10칸 합이 항상 화면보다 넓도록 최대폭을 잡는다. */
  width: clamp(11rem, 19vw, 26rem);
  aspect-ratio: var(--frame-w) / var(--frame-h);
  max-height: 58vh;
  z-index: 1;
}

.stills__item.is-focus {
  z-index: 3;
}

/* 한화 kv-img-expand-scale 실측 이식:
   좌우 gutter만큼 들어가 있던 이미지가 width 100%로 벌어지면서
   이미지 자체는 scale 1.25까지 확대되고 dim이 걷힌다(scrub 0.01). */
.stills__shot {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--f) * var(--expand) / -2);
  width: calc(100% + var(--f) * var(--expand));
  overflow: hidden;
  background: #000;
  box-shadow: 0 0 calc(var(--f) * 90px) rgba(0, 0, 0, calc(var(--f) * 0.85));
}

.stills__shot img {
  width: 100%;
  /* 워터마크가 있는 아래쪽이 상자 밖으로 밀려나 잘린다 */
  height: calc(100% * 1760 / var(--frame-h));
  object-fit: cover;
  object-position: center top;
  display: block;
  transform: scale(calc(1 + var(--f) * 0.25));
  transform-origin: center top;
  filter: brightness(calc(0.58 + var(--f) * 0.5)) saturate(calc(0.82 + var(--f) * 0.22));
}

/* 가운데 칸에만 금색 테두리가 그어진다 */
.stills__shot::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border: 1px solid rgba(201, 162, 75, calc(var(--f) * 0.8));
}

/* 가로 진행 레일 */
.stills__rail {
  margin: 0 clamp(1.5rem, 6vw, 8rem);
  height: 2px;
  background: rgba(244, 241, 234, 0.14);
  flex: 0 0 auto;
}

.stills__rail span {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--color-accent);
}

/* ---------- 공개일 ---------- */

.release {
  position: relative;
  overflow: hidden;
  padding: clamp(5rem, 12vh, 9rem) clamp(1.5rem, 6vw, 8rem) clamp(6rem, 14vh, 10rem);
  border-top: 1px solid rgba(244, 241, 234, 0.08);
  text-align: center;
}

/* 날짜 뒤에서 퍼지는 충격파 고리 — 섹션이 들어올 때 한 번 */
.release__pulse {
  position: absolute;
  top: 30%;
  left: 50%;
  width: min(70rem, 120vw);
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  border: 1px solid rgba(201, 162, 75, 0.55);
  opacity: 0;
  scale: 0.15;
  pointer-events: none;
}

.release.is-in .release__pulse {
  animation: release-pulse 2.6s cubic-bezier(0.16, 0.8, 0.3, 1) 0.25s both;
}

@keyframes release-pulse {
  0%   { opacity: 0;    scale: 0.15; }
  18%  { opacity: 0.85; }
  100% { opacity: 0;    scale: 1; }
}

.release .section__eyebrow {
  margin-bottom: 1.6rem;
}

.release__date {
  margin: 0 0 var(--space-md);
  font-size: var(--fs-statement);
  line-height: var(--lh-display);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-display);
  font-variant-numeric: tabular-nums;
}

.release__dow {
  font-size: 0.34em;
  letter-spacing: 0.28em;
  color: var(--color-accent);
  vertical-align: 0.9em;
  margin-left: 0.4em;
}

.release__time {
  margin: 0 0 var(--space-xl);
  color: var(--color-muted);
  font-size: var(--fs-lead);
  line-height: var(--lh-text);
  letter-spacing: var(--ls-mid);
}

.countdown {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: clamp(1.2rem, 4vw, 3.2rem);
  margin-bottom: 3.4rem;
}

.countdown__unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  min-width: 4.2rem;
}

.countdown__unit strong {
  font-size: var(--fs-number);
  font-weight: var(--fw-black);
  line-height: 1;
  letter-spacing: var(--ls-display);
  font-variant-numeric: tabular-nums;
  color: var(--color-fg);
}

.countdown__unit span {
  font-size: var(--fs-label);
  letter-spacing: 0.24em;
  font-weight: var(--fw-bold);
  color: var(--color-muted);
}

.notify {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.7rem;
  max-width: 34rem;
  margin: 0 auto;
}

.notify__input {
  flex: 1 1 16rem;
  min-width: 0;
  font: inherit;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-text);
  color: var(--color-fg);
  background: rgba(244, 241, 234, 0.05);
  border: 1px solid rgba(244, 241, 234, 0.28);
  border-radius: 999px;
  padding: 0.9rem 1.4rem;
}

.notify__input::placeholder {
  color: rgba(185, 179, 166, 0.7);
}

.notify__input:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.notify__note {
  flex: 1 0 100%;
  margin: 0.9rem 0 0;
  font-size: 0.78rem;
  line-height: 1.7;
  color: rgba(185, 179, 166, 0.75);
}

.notify__note.is-done {
  color: var(--color-accent);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- 푸터 ---------- */

.footer {
  position: relative;
  z-index: 3;
  background: #08080a;
  border-top: 1px solid rgba(244, 241, 234, 0.08);
  padding: 3.4rem clamp(1.5rem, 6vw, 8rem) calc(3.4rem + var(--safe-bottom));
  text-align: center;
}

.footer__title {
  margin: 0 0 var(--space-sm);
  font-size: var(--fs-h3);
  letter-spacing: 0.16em;
  font-weight: var(--fw-black);
}

.footer__meta {
  margin: 0 0 var(--space-sm);
  font-size: var(--fs-label);
  letter-spacing: 0.08em;
  color: var(--color-muted);
}

.footer__note {
  margin: 0;
  font-size: 0.74rem;
  line-height: 1.7;
  color: rgba(185, 179, 166, 0.55);
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .btn,
  .hero__canvas,
  .hero__poster {
    transition: none;
  }
}

/* 가로로 넓은 화면: 세로로 긴 원본 비율(워터마크 잘라낸 1176x1640) 그대로의
   박스를 화면 가운데 두고, 남는 좌우는 스테이지 배경(검정)을 그대로 노출한다.
   사진을 억지로 늘리거나(왜곡) 자르지(인물 손실) 않는 방식 — 박스 폭은
   뷰포트 높이에서 비율로 계산되므로 크롭이 필요 없다.
   카피는 이 상자 밖(.hero__content)에 있어서 화면 전체 폭을 쓴다. */
@media (min-aspect-ratio: 1176/1496) {
  .hero__stage {
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .hero__frame {
    position: relative;
    inset: auto;
    height: 100%;
    aspect-ratio: var(--frame-w) / var(--frame-h);
    max-width: 100%;
  }
}

@media (min-width: 1024px) {
  .hero__eyebrow {
    white-space: nowrap;
  }
  .hero__headline br {
    display: block;
  }
  .hero__headline,
  .hero__eyebrow {
    word-break: keep-all;
    overflow-wrap: normal;
  }
}

@media (max-width: 640px) {
  :root {
    --hero-height: 300vh;
  }
  .hero__content {
    padding-bottom: calc(6rem + var(--safe-bottom));
  }
  .hero__actions {
    flex-direction: column;
    align-items: stretch;
  }
}

/* ==========================================================================
   모바일: 섹션을 화면에 꽉 채운다
   실측 문제(402x874): 시놉시스 568px(65%) · 공개일 719px(82%) · 푸터 229px(26%)
   는 화면을 못 채우고, 등장인물 2001px(229%)은 넘치고, 스틸 이미지는 176x245px
   (28%)라 위아래가 검은 여백이었다. 원인이 서로 달라 세 처방을 함께 쓴다.
   ========================================================================== */

@media (max-width: 640px) {

  /* ── ① 부족한 섹션을 화면 높이로 채운다 ────────────────────────────
     vh 가 아니라 svh 를 쓴다 — 모바일 브라우저는 주소창이 접혔다 펴지면서
     100vh 가 실제 화면보다 커져 아래가 잘린다. svh(작은 뷰포트)면 주소창이
     펴진 상태 기준이라 어떤 상태에서도 안 잘린다.
     클론 실측 채택 현황: 100svh — one x22, arth x12, ion-catalog x12,
     centreville x11 / 100dvh — i-park x12, w.co.kr x11, cw-thehue x9 */
  .synopsis,
  .cast,
  .release,
  .footer {
    min-height: 100vh;          /* svh 미지원 브라우저용 폴백 */
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .stills__sticky {
    height: 100vh;
    height: 100svh;
  }

  /* ── ② 등장인물: 세로로 쌓지 말고 가로 레일로 눕힌다 ────────────────
     도너 실측 — 한화 mobile-category-swiper: 모바일에서 계열사 버튼이 가로
     스와이퍼 레일이 되고 slidesPerView 'auto', spaceBetween 모바일 8px,
     스크롤바를 실제 UI 로 노출한다. 라이브러리 없이 CSS 스크롤 스냅으로 옮긴다.
     결과: 2001px 4장 세로 쌓기 → 한 화면 안에서 옆으로 넘기기 (카드는 오히려 커짐) */
  .cast__grid {
    display: flex;
    grid-template-columns: none;
    gap: 8px;                    /* 한화 실측 모바일 spaceBetween */
    background: transparent;
    border: 0;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-left: clamp(1.5rem, 6vw, 8rem);
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 0.9rem;
    /* 좌우 끝까지 흘러가되 첫 칸은 본문 여백에 맞춰 선다 */
    margin-inline: calc(-1 * clamp(1.5rem, 6vw, 8rem));
    padding-inline: clamp(1.5rem, 6vw, 8rem);
  }

  .cast__card {
    flex: 0 0 76%;               /* 한 화면에 1.3장 — "옆에 더 있다"가 보인다 */
    height: auto;
    aspect-ratio: 1024 / 1536;   /* 인물 사진 원본 비율 */
    max-height: 62svh;
    scroll-snap-align: center;
    border: 1px solid rgba(244, 241, 234, 0.1);
  }

  /* ── ③ 스틸: 썸네일 줄이 아니라 한 장이 화면을 채우고 크로스페이드 ──
     도너 실측 — 한화에어로 kv-swiper-fade: effect 'fade' + crossFade,
     활성 슬라이드 scale 1 / 비활성 scale 1.2 (Linear.easeInOut).
     여기서는 슬라이드 전환이 아니라 핀 스크롤에 물린 연속 크로스페이드로 쓴다.
     script.js 의 updateStillsStack() 이 칸마다 --v(0~1)를 넣는다. */
  .stills__track {
    position: relative;
    display: block;
    width: 100%;
    height: 62svh;
    padding: 0;
    transform: none !important;  /* 가로 이동은 모바일에서 쓰지 않는다 */
  }

  .stills__item {
    position: absolute;
    inset: 0;
    width: 100%;
    max-height: none;
    aspect-ratio: auto;
    opacity: var(--v, 0);
    --f: 0;                      /* 데스크톱의 중앙 확장 연출은 끈다 */
  }

  .stills__shot {
    left: 0;
    width: 100%;
    box-shadow: none;
    /* 활성 1 / 비활성 1.2 — 한화에어로 실측 scale 값 */
    transform: scale(calc(1.2 - var(--v, 0) * 0.2));
    transform-origin: center center;
  }

  .stills__shot img {
    filter: brightness(calc(0.72 + var(--v, 0) * 0.34)) saturate(calc(0.85 + var(--v, 0) * 0.15));
    transform: none;
  }

  .stills__shot::after {
    border-color: rgba(201, 162, 75, calc(var(--v, 0) * 0.5));
  }
}

/* ==========================================================================
   섹션 인터랙션
   진입 감지는 script.js의 IntersectionObserver가 .is-in을 붙이는 것으로,
   스크롤에 따라 연속으로 변하는 값(글자 밝기·가로 이동)은 rAF로 처리한다.
   움직임 축소 설정에서는 맨 아래 블록이 전부 최종 상태로 고정한다.
   ========================================================================== */

/* ---------- 상단 진행바 ---------- */

.scrollbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 30;
  background: rgba(244, 241, 234, 0.08);
  pointer-events: none;
}

.scrollbar span {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(to right, rgba(201, 162, 75, 0.4), var(--color-accent));
}

/* ---------- 공통 진입 효과 ---------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(1.6rem);
  transition: opacity 0.9s cubic-bezier(0.16, 0.8, 0.3, 1),
              transform 0.9s cubic-bezier(0.16, 0.8, 0.3, 1);
}

[data-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* ---------- 시놉시스 ---------- */

/* 마스크 뒤에서 한 줄씩 솟아오른다 */
.synopsis__lead .mask {
  display: block;
  overflow: hidden;
}

.synopsis__lead .mask > span {
  display: block;
  transform: translateY(110%);
  transition: transform 1.1s cubic-bezier(0.16, 0.85, 0.25, 1);
}

.synopsis__lead .mask.is-in > span {
  transform: none;
}

.synopsis__lead .mask:nth-child(2) > span {
  transition-delay: 0.14s;
}

/* 본문은 스크롤에 맞춰 글자가 하나씩 밝아진다 */
.synopsis__body .ch {
  color: rgba(185, 179, 166, 0.16);
  transition: color 0.45s ease;
}

.synopsis__body .ch.is-lit {
  color: var(--color-muted);
}

/* ---------- 등장인물 ---------- */

[data-reveal-card] {
  opacity: 0;
  transform: translateY(3rem) scale(0.97);
  transition: opacity 0.9s cubic-bezier(0.16, 0.8, 0.3, 1),
              transform 0.9s cubic-bezier(0.16, 0.8, 0.3, 1),
              flex-grow 0.6s cubic-bezier(0.16, 0.8, 0.3, 1),
              filter 0.5s ease;
}

[data-reveal-card].is-in {
  opacity: 1;
  transform: none;
}

/* 호버하면 그 카드가 펼쳐지고 나머지는 물러난다 (마우스 있는 화면에서만) */
@media (hover: hover) and (min-width: 641px) {
  .cast__grid {
    display: flex;
  }
  .cast__card {
    flex: 1 1 0;
    min-width: 0;
  }
  .cast__grid:hover .cast__card {
    flex-grow: 0.82;
    filter: brightness(0.55) saturate(0.75);
  }
  .cast__grid .cast__card:hover {
    flex-grow: 1.7;
    filter: brightness(1.06) saturate(1);
  }
  .cast__card:hover .cast__hanja {
    color: rgba(201, 162, 75, 1);
  }
  /* 펼쳐진 카드 아래쪽에 금색 선이 그어진다 */
  .cast__card .cast__body::before {
    content: "";
    display: block;
    width: 0;
    height: 2px;
    margin-bottom: 1rem;
    background: var(--color-accent);
    transition: width 0.6s cubic-bezier(0.16, 0.8, 0.3, 1) 0.05s;
  }
  .cast__card:hover .cast__body::before {
    width: 3.4rem;
  }
}

.cast__hanja {
  transition: color 0.5s ease;
}

/* ---------- 공개일 ---------- */

[data-reveal-date] {
  opacity: 0;
  transform: scale(1.28);
  filter: blur(10px);
  transition: opacity 1.1s cubic-bezier(0.16, 0.8, 0.3, 1),
              transform 1.1s cubic-bezier(0.16, 0.8, 0.3, 1),
              filter 1.1s cubic-bezier(0.16, 0.8, 0.3, 1);
}

[data-reveal-date].is-in {
  opacity: 1;
  transform: none;
  filter: none;
}

/* 숫자가 바뀔 때마다 위로 굴러 올라온다 */
.countdown__unit strong {
  display: block;
  will-change: transform;
}

.countdown__unit strong.is-tick {
  animation: cd-roll 0.42s cubic-bezier(0.16, 0.8, 0.3, 1);
}

@keyframes cd-roll {
  0%   { transform: translateY(0.42em);  opacity: 0; color: var(--color-accent); }
  60%  { opacity: 1; }
  100% { transform: none; opacity: 1; }
}

/* ---------- 움직임 축소 설정: 전부 최종 상태로 고정 ---------- */

@media (prefers-reduced-motion: reduce) {
  [data-reveal],
  [data-reveal-card],
  [data-reveal-date] {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
  .synopsis__lead .mask > span {
    transform: none;
    transition: none;
  }
  .synopsis__body .ch {
    color: var(--color-muted);
    transition: none;
  }
  .countdown__unit strong.is-tick {
    animation: none;
  }
  .release.is-in .release__pulse {
    animation: none;
  }
  .stills__pin {
    height: auto;
  }
  .stills__sticky {
    position: static;
    height: auto;
    padding: clamp(4rem, 10vh, 8rem) 0;
  }
  .stills__track {
    overflow-x: auto;
    transform: none !important;
    position: static;
    height: auto;
    display: flex;
  }
  /* 확장 연출·크로스페이드를 끄고 모든 칸을 같은 밝기로 고정한다 */
  .stills__item {
    --f: 0;
    --v: 1;
    position: relative;
    inset: auto;
    opacity: 1;
  }
  .stills__shot img {
    transform: none;
    filter: brightness(0.92) saturate(1);
  }
  .stills__shot {
    transform: none;
  }
  /* 가로 레일도 스냅 없이 평범한 스크롤로 */
  .cast__grid {
    scroll-snap-type: none;
  }
}

/* ==========================================================================
   히어로 → 본문 전환 — 화이트 임팩트 플래시
   프레임 180에서 주먹이 터지는 지점(52% 46%)에 맞춰 흰빛이 번져 화면을
   삼켰다가 걷힌다. 빛이 가장 짙을 때 그 아래에서 본문이 이미 나타나 있어
   이음매가 보이지 않는다.
   script.js가 프레임 180~210 구간을 두 값으로 흘려보낸다:
     --t     0→1    전환 진행도(선형)
     --flash 0→1→0  가운데서 정점을 찍는 삼각형 곡선
   ========================================================================== */

:root {
  --t: 0;
  --flash: 0;
}

.fx-flash {
  position: fixed;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  opacity: var(--flash);
  background:
    radial-gradient(circle at 52% 46%,
      rgba(255, 255, 255, 1) 0%,
      rgba(255, 255, 255, 0.98) 35%,
      rgba(255, 252, 240, 0.9) 60%,
      rgba(255, 246, 214, 0.75) 100%);
}

.page {
  opacity: clamp(0, calc((var(--t) - 0.3) / 0.25), 1);
}
