@charset "UTF-8";

/* --------------------------------------------------------------------------
   1. 웹폰트
   -------------------------------------------------------------------------- */

/* 로딩 카운터 숫자 — 교보손글씨 2025 (라틴/숫자 서브셋) */
@font-face {
   font-family: 'Kyobo Handwriting 2025';
   src: url('../fonts/kyobo-handwriting-2025-latin.woff2') format('woff2');
   font-weight: 400;
   font-style: normal;
   font-display: swap;
   unicode-range: U+0020-007E, U+00A0, U+2018-201D, U+2026;
}

/* 한글 카피 — 교보손글씨 2025 (KS X 1001 상용 2350자 서브셋) */
@font-face {
   font-family: 'Kyobo Handwriting 2025';
   src: url('../fonts/kyobo-handwriting-2025-korean.woff2') format('woff2');
   font-weight: 400;
   font-style: normal;
   font-display: swap;
   unicode-range: U+AC00-D7A3;
}

/* 영문 카피 — Amatic SC */
@font-face {
   font-family: 'Amatic SC';
   src: url('../fonts/amatic-sc-400-latin.woff2') format('woff2');
   font-weight: 400;
   font-style: normal;
   font-display: swap;
}
@font-face {
   font-family: 'Amatic SC';
   src: url('../fonts/amatic-sc-700-latin.woff2') format('woff2');
   font-weight: 700;
   font-style: normal;
   font-display: swap;
}

/* 푸터·약관 본문 — 페이퍼로지 5 Medium (SIL OFL). 한글 11,172자 전체를 담아
   약관 새 버전에 어떤 글자가 들어와도 빠지지 않는다. */
@font-face {
   font-family: 'Paperlogy';
   src: url('../fonts/paperlogy-500.woff2') format('woff2');
   font-weight: 500;
   font-style: normal;
   font-display: swap;
}

/* --------------------------------------------------------------------------
   2. 토큰
   -------------------------------------------------------------------------- */

:root {
   /* 색 — 일러스트에서 추출 */
   --c-sky: #f0efef;
   --c-sea: #4dbefe;
   /* 씬 아랫변 아래로 이어 붙이는 바다색 — 아트워크 맨 아랫줄 실측값 rgb(78,190,251) */
   --c-sea-fill: #4ebefb;
   --c-ink: #2b2b29;
   --c-hint: #4fbffd;
   --c-paper: #fcfcfc;

   --font-hand: 'Amatic SC', 'Kyobo Handwriting 2025', 'Bradley Hand', 'Segoe Print', cursive;
   --font-kyobo: 'Kyobo Handwriting 2025', 'Amatic SC', 'Bradley Hand', cursive;
   --font-count: var(--font-kyobo);

   /* 로딩 화면(카운터·라벨)과 인트로 카피(타이틀·리드)에만 쓰는 자간.
      나머지 교보손글씨 문구는 각자의 em 값을 그대로 둔다.
      모바일에서는 아래 미디어쿼리에서 -0.25px 로 완화한다 */
   --ls-kyobo: -0.5px;

   /*
     * 단계별 수면 높이. "뷰포트 높이에 대한 비율" 로 정의한다.
     *
     * 일러스트는 뷰포트 너비에 맞춰 확대되므로, 씬 위치를 씬 높이 기준으로 잡으면
     * 화면 비율이 시안(16:10)에서 벗어날 때 수면과 카피가 어긋난다.
     * 수면을 높이 비율에 고정하면 어떤 화면비에서도 하늘/바다 분할이 시안과 같다.
     *
     * Figma 데스크톱(1440×900) 프레임의 수면 y좌표에서 역산:
     *   0% → -346px   50% → 104px   99% → 288px   100% → 554px
     */
   --water-0: -0.38444;
   --water-50: 0.11556;
   --water-99: 0.32;
   --water-100: 0.61556;

    /* 씬 안에서 수면이 놓인 위치 (662 / 1800) — 일러스트 고정값 */
   --sea-top: 0.36778;

   /*
     * 씬 크기. 그림 비율이 1:1.25 로 고정이라 너비 기준으로만 키우면
     * 넓은 화면에서 세로로 과하게 확대된다. 상한 200vh(=16:10 에서의 125vw)로
     * 묶어 어떤 화면비에서도 같은 비율로 보이게 한다.
     */
   /*
     * 화면 높이 기준. 주소창이 뜨고 지는 만큼 실제 보이는 높이가 달라지는데,
     * vh 는 주소창이 없다고 치고 계산해 배경(dvh 기준)과 어긋난다.
     * 배경 위에 얹는 글·아이콘은 모두 이 값을 써야 같은 자리에 놓인다.
     */
   --vh: 1vh;

   --scene-w: 100vw;
   --scene-h: 125vw;


   /* 현재 씬 위치 — JS 가 갱신 */
   --scene-shift: 0;

   /* 100% 에서 멎었다가 다시 출발하므로, 정지에서 시작해 부드럽게 착지하는 곡선 */
   --ease-reveal: cubic-bezier(0.45, 0, 0.25, 1);

   /*
     * 현무암 이야기의 돌 궤적. Figma 'Desktop - tap -mountain' 기준
     * 돌 1920×1458 @(-240,71) → 화면 중심에서 아래로 38.9vh 떨어진 자리에 꽉 찬다.
     */
   --rock-start-y: 4vh;    /* 산 뒤 (앞면 레이어에 가려 안 보인다) */
   --rock-ridge-y: -9.8vh; /* 능선을 막 넘는 자리 */
   --rock-pop-y: -36vh;    /* 하늘로 튀어오른 자리 */
   --rock-pop-scale: 0.085;

   /*
     * 다 커졌을 때. 돌 크기는 vw, 자리는 vh 라서 그냥 vh 로 주면
     * 화면 비율이 시안(16:10)에서 벗어날 때 윗여백이 사라진다.
     * 돌 윗변이 화면 위에서 7.9%(시안 71/900) 에 오도록 역산한다.
     *   중심오프셋 = 7.9vh + 돌높이/2 − 50vh,  돌높이 = 101.25vw
     */
   --rock-full-y: calc(50.625vw - 42.1vh);

   /* 카피 등장 모션 */
   --rise-distance: 0.5em;
   --rise-duration: 1020ms;

   /*
     * 푸터. 본문 손글씨와 달리 사업자정보·경고문구는 가독성이 우선이라
     * 기기 기본 고딕을 쓴다 (추가 다운로드 0KB).
     */
   --font-sans: 'Paperlogy', 'Pretendard', -apple-system, BlinkMacSystemFont, 'Apple SD Gothic Neo', 'Malgun Gothic', '맑은 고딕', 'Noto Sans KR', sans-serif;
   --c-footer-bar: #17301f;
   --c-footer-bg: #f6f6f6;
   /* 모바일 푸터는 초록 바탕이라 글자를 따로 잡는다 */
   --c-footer-on-bar: #ece6da;
   --c-footer-ink: #1f2950;
   --c-footer-dim: rgba(31, 41, 80, 0.7);
   --c-footer-rule: rgba(31, 41, 80, 0.5);

   /* 약관·방침 문서 페이지 */
   --c-doc-bg: #ffffff;
   --c-doc-ink: #1f2950;
   --c-doc-dim: rgba(31, 41, 80, 0.7);
   --c-doc-tint: rgba(31, 41, 80, 0.1);
   --c-doc-tint-soft: rgba(31, 41, 80, 0.05);
   --c-doc-rule: rgba(31, 41, 80, 0.25);
}

/* --------------------------------------------------------------------------
   3. 리셋 / 베이스
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }

/* 인트로가 끝날 때까지 화면을 붙잡아 둔다. 푸터는 첫 화면 아래에 숨어 있다 */
.is-hinted, .is-hinted body { height: auto; min-height: 100%; overflow: visible; }

/* 팝업·이야기가 열려 있는 동안에는 뒤 배경이 따라 움직이지 않게 다시 잠근다 */
.is-gate, .is-gate body, .is-popup, .is-popup body, .is-story, .is-story body, .is-story-closing, .is-story-closing body { overflow: hidden; }
body { margin: 0; overflow: hidden; background-color: var(--c-sky); color: var(--c-ink); font-family: var(--font-hand); word-break: keep-all; -webkit-text-size-adjust: 100%; -webkit-font-smoothing: antialiased; }
img { border: 0; }
p { margin: 0; }

/* 화면에는 숨기고 스크린리더에만 노출 */
.a11y-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; border: 0; clip: rect(0, 0, 0, 0); clip-path: inset(50%); white-space: nowrap; }

/* --------------------------------------------------------------------------
   4. 스테이지
   -------------------------------------------------------------------------- */

.stage { position: relative; height: calc(100 * var(--vh)); overflow: hidden; background-color: var(--c-sky); }

/* --------------------------------------------------------------------------
   5. 배경 씬
   1440×1800 손그림을 뷰포트에 맞춰 확대하고, 진행에 따라 세로로 옮긴다.
   -------------------------------------------------------------------------- */

/* transform 첫 줄은 커스텀 속성/calc 미지원 브라우저용 폴백 */
.scene { position: absolute; top: 0; left: 50%; width: var(--scene-w); height: var(--scene-h); transform: translateX(-50%); transform: translateX(-50%) translateY(calc(var(--scene-shift) * 100%)); will-change: transform; }

/* 세로로 긴 화면에서는 높이 기준으로 확대 (모바일 시안의 720×900 배치와 동일) */
@supports (width: clamp(1px, 2px, 3px)) {
   :root { --scene-w: clamp(85.6vh, 100vw, 160vh); --scene-h: clamp(107vh, 125vw, 200vh); }
}

/* 모바일 주소창 높이 변화 대응 */
@supports (height: 100dvh) {
   :root { --vh: 1dvh; --scene-w: clamp(85.6dvh, 100vw, 160dvh); --scene-h: clamp(107dvh, 125vw, 200dvh); }
}

/*
 * 두들기면 솟아오르는 소주. 배경 씬 위에 겹치므로 씬과 똑같이 배치·이동한다.
 * z-index 1 — 구름·안내 글보다 앞이고, 구름 팝업(2)과 돌 이야기(3) 뒤다.
 * 구름 위를 덮으므로 pointer-events: none 이라야 구름을 계속 누를 수 있다.
 */
.bottle { position: absolute; top: 0; left: 50%; z-index: 1; width: var(--scene-w); height: var(--scene-h); transform: translateX(-50%); transform: translateX(-50%) translateY(calc(var(--scene-shift) * 100%)); pointer-events: none; }

/* 프레임은 1440×1800 캔버스에서 (474,287)~(985,919) 만 잘라낸 것이라 그 자리에 되돌려 놓는다 */
.bottle__art { position: absolute; top: 15.9444%; left: 32.9167%; width: 35.4861%; height: 35.1111%; }

/*
 * 30컷을 모두 겹쳐 두고 보이는 컷만 바꾼다.
 * display/visibility 로 감추면 브라우저가 디코드를 미뤄 첫 재생에서 깜빡이므로
 * 투명도만 0 으로 두어 미리 다 그려 두게 한다.
 */
.bottle__frame { position: absolute; top: 0; left: 0; display: block; width: 100%; height: 100%; opacity: 0; }
.bottle__frame.is-on { opacity: 1; }

/*
 * 씬 아랫변보다 아래를 채우는 바다. 로딩 중 씬이 위로 올라가면 아랫변 밑으로
 * body 배경(하늘색)이 드러나므로 그만큼을 메운다. 그림 맨 아랫단은 12컷 모두
 * 물결이 없는 평평한 바다라, 그 구간을 뜬 타일로 이어도 티가 나지 않는다.
 *
 * 위치는 top 이 아니라 transform 으로 옮긴다. top 은 합성되지 않아
 * .scene 의 1600ms 트랜지션과 따로 놀면서 경계가 찢어진다.
 */
.artwork::before { content: ''; position: absolute; right: 0; left: 0;
                  /* 씬 아랫변에 딱 붙이면 소수 픽셀 반올림으로 1px 틈이 생긴다.
                     1px 겹치되 겹치는 줄은 바다 위 바다라 표가 나지 않는다. */
                  top: calc(var(--scene-h) - 1px); height: 200vh;
                  transform: translateY(calc(var(--scene-shift) * var(--scene-h)));
                  background-color: var(--c-sea-fill);
                  background-image: url('../images/main/charlang-sea-fill.webp?v=2');
                  background-repeat: repeat; background-size: var(--scene-w) auto;
                  will-change: transform; }

/* 씬과 같은 트랜지션이어야 경계가 붙어서 내려온다 */
.is-revealing .artwork::before { transition: transform 1600ms var(--ease-reveal); }

/* 배경 그림 — 12컷 순환 애니메이션이 담긴 한 장 */
.scene__art { position: absolute; top: 0; right: 0; bottom: 0; left: 0; display: block; }
.scene__art img { display: block; width: 100%; height: 100%; object-fit: cover; }

/*
 * 씬 크기에 상한이 있어 넓은 화면에서는 씬이 화면 너비를 다 덮지 못한다.
 * 같은 그림을 좌우로 하나씩 더 두고 가로로 뒤집어, 이음매에서 같은 픽셀이
 * 거울처럼 맞닿게 한다. 수면선이 구조적으로 정확히 이어진다.
 * (뒤집지 않고 그냥 이어 붙이면 그림 양끝의 수면선이 어긋나 위쪽 경계가 튄다.)
 * CSS 배경이 아니라 같은 <img> 라 래스터화 경로도 씬과 같다.
 */
.scene__edge { position: absolute; top: 0; display: block; width: 100%; height: 100%; pointer-events: none; }
.scene__edge img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* 씬 폭이 소수 픽셀이라 딱 붙이면 반올림으로 1px 틈이 벌어져 body 배경이 비친다.
   1px 겹치되, 겹치는 열은 반전이라 씬과 같은 픽셀이므로 표가 나지 않는다. */
.scene__edge--l { right: calc(100% - 1px); transform: scaleX(-1); }
.scene__edge--r { left: calc(100% - 1px); transform: scaleX(-1); }

/* --------------------------------------------------------------------------
   6. 구름 — 뷰포트 기준 배치 (Figma loading-4)
   -------------------------------------------------------------------------- */

.clouds { position: absolute; top: 0; right: 0; bottom: 0; left: 0; pointer-events: none; }

/* 구름은 버튼이다. 컨테이너는 클릭을 통과시키고 구름만 받는다 */
.cloud { position: absolute; margin: 0; padding: 0; border: 0; background: none; -webkit-appearance: none; appearance: none; cursor: pointer; pointer-events: auto; }

/* 모션은 3컷 순환 애니메이션이 맡는다 */
.cloud picture { display: block; width: 100%; height: 100%; }
.cloud img { display: block; width: 100%; height: 100%; }
.cloud:focus { outline: 2px dashed var(--c-sea); outline-offset: 6px; border-radius: 999px; }

/* 마우스 클릭에는 초점 테두리를 띄우지 않는다 (지원 브라우저 한정) */
.cloud:focus:not(:focus-visible) { outline: none; }

/* 크기 (데스크톱 1440 기준) */
.cloud--large { width: 29.2969vw; height: 10.8507vw; }
.cloud--medium { width: 18.9887vw; height: 6.5104vw; }
.cloud--small { width: 10.8507vw; height: 4.3403vw; }
.cloud--mini { width: 14.1059vw; height: 4.6115vw; }

/* 자리 (Figma loading-4) */
.cloud--1 { top: calc(6.8889 * var(--vh)); left: 70.625vw; }
.cloud--2 { top: calc(8 * var(--vh)); left: -1.9444vw; }
.cloud--3 { top: calc(1.6667 * var(--vh)); left: 31.6667vw; }
.cloud--4 { top: calc(29.1111 * var(--vh)); left: 12.7083vw; }
.cloud--5 { top: calc(32.5556 * var(--vh)); left: 63.0556vw; }
.cloud--6 { top: calc(21.7778 * var(--vh)); left: 42.9167vw; }
.cloud--7 { top: calc(38.5556 * var(--vh)); left: 80.625vw; }

/* --------------------------------------------------------------------------
   7. 로딩 카운터
   그룹 중심이 프레임 세로 중앙과 일치한다. (Figma 329~571 / 900)
   -------------------------------------------------------------------------- */

.loader { position: absolute; top: 50%; right: 0; left: 0; text-align: center; color: var(--c-paper); opacity: 0; visibility: hidden; transform: translateY(-50%); }
.loader__count { font-family: var(--font-count); font-size: 8.8889vw; font-size: min(8.8889vw, 21vh); line-height: 1.13; letter-spacing: var(--ls-kyobo); }
.loader__label { margin-top: 0.25em; font-family: var(--font-kyobo); font-size: 3vw; font-size: min(3vw, 7vh); line-height: 1.27; letter-spacing: var(--ls-kyobo); }

/* --------------------------------------------------------------------------
   8. 로딩 완료 카피
   타이틀이 먼저 아래에서 떠오르고, 이어서 아래 카피가 한 줄씩 같은 모션으로 따라온다.
   -------------------------------------------------------------------------- */

.reveal { position: absolute; top: 0; right: 0; bottom: 0; left: 0; color: var(--c-ink); text-align: center; pointer-events: none; }
.reveal__title { position: absolute; top: calc(13.5556 * var(--vh)); right: 0; left: 0; margin: 0; font-family: var(--font-kyobo); font-size: 5.5vw; font-size: min(5.5vw, 17vh, 127px); font-weight: 400; line-height: 1.13; letter-spacing: var(--ls-kyobo); }

/* 데스크톱은 한 줄, 모바일에서만 두 줄로 끊는다 */
.reveal__br { display: none; }
.reveal__lead { position: absolute; top: calc(70 * var(--vh)); right: 0; left: 0; font-family: var(--font-kyobo); font-size: 4.4444vw; font-size: min(4.4444vw, 8.28vh, 52px); line-height: 1.2; letter-spacing: var(--ls-kyobo); }
.reveal__line { display: block; }

/* 등장 전 상태 — 살짝 아래에서 투명하게 대기 */
.reveal__title, .reveal__line { opacity: 0; transform: translateY(var(--rise-distance)); }

/* --------------------------------------------------------------------------
   9. 상태
   .is-loading  — 카운터 진행 중
   .is-revealed — 완료 후 카피 노출
   -------------------------------------------------------------------------- */

/* 스크립트가 정확한 값을 넣기 전 첫 페인트용 근사치 — 완성 화면이 스쳐 보이는 것을 막는다 */
/*
 * 첫 페인트 값. JS 가 초기화하며 계산하는 값과 어긋나면 씬이 한 번 튄다.
 *   이동 = 수면0 x 화면높이 / 씬높이 - 수면위치
 * 씬 높이가 상한 200vh 에 걸리는 화면비에서는  -0.38444/2 - 0.36778 = -0.56 로 고정된다.
 */
.is-loading { --scene-shift: -0.56; }

/*
 * 배경 그림이 도착하기 전 바탕색. 로딩 0% 화면은 전부 바다인데 .stage 기본색이
 * 하늘색이라, 그림이 뜨는 순간 회색 -> 파랑으로 한 번 번쩍인다.
 */
.is-loading .stage { background-color: var(--c-sea-fill); }
.is-loading .loader { opacity: 1; visibility: visible; }
.is-loading .clouds { opacity: 0; visibility: hidden; }
.is-revealing .scene { transition: transform 1600ms var(--ease-reveal); }

/* 수면이 내려오기 전에 카운터부터 지운다 — 흰 숫자가 회색 하늘에 걸치지 않도록 */
.is-outro .loader { opacity: 0; visibility: hidden; transition: opacity 700ms ease, visibility 0s 700ms; }

/* 씬이 거의 자리를 잡을 무렵 뜬다 (씬 트랜지션 1600ms 중 800ms 지점) */
.is-revealed .clouds { opacity: 1; visibility: visible; transition: opacity 900ms ease 800ms, visibility 0s 800ms; }
.is-revealed .reveal__title, .is-revealed .reveal__line { opacity: 1; transform: translateY(0); transition: opacity var(--rise-duration) ease, transform var(--rise-duration) var(--ease-reveal); }

/* 타이틀 → 아래 카피 1·2·3행 순차 */
.is-revealed .reveal__title { transition-delay: 1100ms; }
.is-revealed .reveal__line:nth-child(1) { transition-delay: 1560ms; }
.is-revealed .reveal__line:nth-child(2) { transition-delay: 1740ms; }
.is-revealed .reveal__line:nth-child(3) { transition-delay: 1920ms; }

/*
 * 마지막 행까지 다 뜨는 시점은 1920 + 1020 = 2940ms.
 * 거기서 잠시 머문 뒤 main.js 가 .is-quiet 을 붙여 통째로 사라지게 한다.
 */
.is-quiet .reveal { opacity: 0; transition: opacity 1200ms ease; }

/* 안내 문구 — 카피가 다 물러난 뒤 같은 결로 떠오른다 (Figma 4:18 / 40px, #4fbffd) */
.hint { position: absolute; top: calc(27.7089 * var(--vh)); left: 68.09vw; margin: 0; font-family: var(--font-kyobo); font-size: 2.0vw; font-size: min(2.0vw, 3.82vh); line-height: 1.25; letter-spacing: 0.04em; color: var(--c-hint); text-transform: uppercase; white-space: nowrap; opacity: 0; transform: translateX(-50%); pointer-events: none; }
.is-hinted .hint { opacity: 1; transition: opacity var(--rise-duration) ease; }

/* 현무암을 가리키는 안내 (Figma 17:369 글 40px / 17:370 화살표 89×54) */
.peek { position: absolute; top: 0; right: 0; bottom: 0; left: 0; opacity: 0; pointer-events: none; }
.is-hinted .peek { opacity: 1; transition: opacity var(--rise-duration) ease; }
.peek__label { position: absolute; top: calc(44.7211 * var(--vh)); left: 23.0323vw; margin: 0; font-family: var(--font-kyobo); font-size: 2.0vw; font-size: min(2.0vw, 3.82vh); line-height: 1.25; letter-spacing: 0.04em; color: var(--c-ink); text-transform: uppercase; white-space: nowrap; transform: translateX(-50%); }

/* 화면 맨 아래 가운데. 현무암과 같은 이야기를 여는 버튼이라 hint/peek 과 함께 뜬다.
   z-index 2 — 병(1) 위에 올려 가리지 않게 하고, 구름 팝업(2, DOM 상 뒤)과
   돌 이야기(3) 에는 그대로 덮인다. */
/* 누름 영역은 바다 전체다. 수면(--water-100, 화면 높이 대비 비율)부터 화면 아래까지 덮는다.
   산 누름 영역(.rock)은 아랫변이 곧 수면선이라 서로 겹치지 않는다.
   글과 손 그림은 원래 자리(아래 가운데)에 그대로 두려고 flex-end 로 붙인다.
   두 번 눌러야 열리므로 두드림 확대는 막는다 */
.knock { position: absolute; z-index: 2; top: calc(var(--water-100) * 100 * var(--vh)); right: 0; bottom: 0; left: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; margin: 0; padding: 23px 24px; box-sizing: border-box; font-family: var(--font-kyobo); font-size: 2.3vw; font-size: min(2.3vw, 4.39vh, 33px); line-height: 1.25; letter-spacing: 0.04em; color: var(--c-paper); background: none; border: 0; -webkit-appearance: none; appearance: none; white-space: nowrap; cursor: pointer; opacity: 0; pointer-events: none; -webkit-user-select: none; user-select: none; touch-action: manipulation; }

/* 두드리는 손 — 18컷 1.548초 루프. 글자와 박자를 맞추려고 JS 가 컷을 넘긴다 */
.knock__br { display: none; }
.knock__hand { position: relative; display: block; width: 88px; height: 100px; }
.knock__frame { position: absolute; top: 0; left: 0; display: block; width: 100%; height: 100%; opacity: 0; }
.knock__frame.is-on { opacity: 1; }
.is-hinted .knock { opacity: 1; pointer-events: auto; transition: opacity var(--rise-duration) ease; }

/* 누르고 나면 물러난다 (.is-hinted .knock 과 특이도가 같아 순서로 이긴다) */
.is-rising .knock { opacity: 0; pointer-events: none; transition: opacity 520ms ease; }

/* 소주가 다 떠오른 뒤 두들겨보라던 자리에 들어온다 */
.meet { position: absolute; z-index: 2; bottom: calc(3.5 * var(--vh) + 8px + env(safe-area-inset-bottom, 0px)); left: 50%; margin: 0; padding: 0.4em 0.9em; font-family: var(--font-kyobo); font-size: 2.6vw; font-size: min(2.6vw, 4.96vh, 37px); line-height: 1.25; letter-spacing: 0.04em; color: var(--c-paper); white-space: nowrap; opacity: 0; transform: translateX(-50%); pointer-events: none; }
.is-afloat .meet { opacity: 1; transition: opacity var(--rise-duration) ease; }
/* 버튼 박스가 바다 전체라 테두리를 그 위에 그리면 화면 절반을 두른다. 글자에만 그린다 */
.knock:focus { outline: none; }
.knock:focus .knock__inner { outline: 2px dashed var(--c-paper); outline-offset: 6px; border-radius: 999px; }
.knock:focus:not(:focus-visible) .knock__inner { outline: none; }
.peek__arrow { position: absolute; top: calc(46.6667 * var(--vh)); left: 29.9861vw; display: block; width: 6.1806vw; width: min(6.1806vw, 11.8vh); height: auto; }

/*
 * 눌러보라는 신호. 빠르게 두 번 톡톡 튀고 한참 쉰다.
 * 바깥 요소는 중앙 정렬과 등장 이동에 transform 을 이미 쓰므로,
 * 튀는 동작은 안쪽 요소가 따로 맡는다.
 */
@keyframes nudge {
   0% { transform: translateY(0); }
   4% { transform: translateY(calc(var(--nudge, 0.05em) * -1)); }
   9% { transform: translateY(0); }
   13% { transform: translateY(calc(var(--nudge, 0.05em) * -1)); }
   18% { transform: translateY(0); }
   100% { transform: translateY(0); }
}

/* 튀는 높이. 글은 제 글자 크기(40px) 기준, 화살표는 제 높이(54px) 기준이라
   0.05em = 2px, 3.7% = 2px 로 이동량이 같다. 모바일에서도 둘 다 절반이 된다 */
.hint__inner, .peek__inner, .knock__inner { display: inline-block; --nudge: 0.05em; }

/*
 * 똑 · 똑 — 손이 두드리는 순간(9번 컷 688ms, 12번 컷 946ms)에 맞춰
 * interactions.js 가 글자마다 이 결을 한 번씩 걸어 준다.
 */
@keyframes knock-hop {
   0% { transform: translateY(0); }
   40% { transform: translateY(calc(var(--nudge, 0.05em) * -1)); }
   100% { transform: translateY(0); }
}
.knock__tok { display: inline-block; }
.knock__tok.is-tap { animation: knock-hop 240ms ease-in-out; }

/* 글이 다 뜬 뒤에 시작한다 */
/* 구름 안내가 먼저 튀고, 0.6초 뒤 현무암 안내가 이어받는다.
   주기가 같아 한 번 벌려 두면 계속 번갈아 튄다 */
.is-hinted .hint__inner { animation: nudge 2.4s ease-in-out 1.3s infinite; }
.is-hinted .peek__inner, .is-hinted .peek__arrow { animation: nudge 2.4s ease-in-out 1.9s infinite; }
.peek__arrow { --nudge: 3.7%; }

/* 현무암 누름 영역 — 배경에 그려져 있어 씬 좌표(226~1133, 489~662)에 맞춰 얹는다 */
.rock { position: absolute; top: 27.17%; left: 15.69%; width: 63.06%; height: 9.61%; margin: 0; padding: 0; border: 0; background: none; -webkit-appearance: none; appearance: none; cursor: pointer; visibility: hidden; }
.is-hinted .rock { visibility: visible; }
.rock:focus { outline: 2px dashed var(--c-ink); outline-offset: 4px; }
.rock:focus:not(:focus-visible) { outline: none; }

/* --------------------------------------------------------------------------
   10. 현무암 이야기
   돌이 현무암에서 튀어올랐다가 화면을 채우며 커진다. 닫을 때는 그 반대.
   덮개가 화면 전체를 덮으므로 뒤의 구름은 눌리지 않는다.
   -------------------------------------------------------------------------- */

.story { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 3; overflow: hidden; }

/* 돌 1920×1458 을 1440 기준 비율로 (다 커졌을 때 화면을 덮는다) */
.story__rock { position: absolute; top: 50%; left: 50%; z-index: 1; width: 133.3333vw; height: auto; transform: translate(-50%, calc(-50% + var(--rock-start-y))) scale(0.055); }
@keyframes rock-rise {
   0% { transform: translate(-50%, calc(-50% + var(--rock-start-y))) scale(0.055); opacity: 1; z-index: 1; animation-timing-function: cubic-bezier(0.35, 0, 0.5, 1); }
   12% { transform: translate(-50%, calc(-50% + var(--rock-ridge-y))) scale(0.06); opacity: 1; z-index: 1; animation-timing-function: cubic-bezier(0.25, 0.7, 0.35, 1); }
   15% { z-index: 3; }
   31.25% { transform: translate(-50%, calc(-50% + var(--rock-pop-y))) scale(var(--rock-pop-scale)); opacity: 1; z-index: 3; }
   56.25% { transform: translate(-50%, calc(-50% + var(--rock-pop-y))) scale(var(--rock-pop-scale)); opacity: 1; z-index: 3; animation-timing-function: cubic-bezier(0.6, 0, 0.3, 1); }
   100% { transform: translate(-50%, calc(-50% + var(--rock-full-y))) scale(1); opacity: 1; z-index: 3; }
}

/* 산 뒤에서 0.19초 올라와 능선을 넘고, 0.5초에 하늘까지 솟은 뒤
   0.4초 머물고 0.7초에 걸쳐 커진다 */
.is-story .story__rock { animation: rock-rise 1600ms both; }

/*
 * 닫을 때는 같은 궤적을 되감는다.
 * animation-direction 만 reverse 로 바꾸면 브라우저가 같은 애니메이션으로 보고
 * 새로 시작하지 않아 끝 상태로 튀므로, 이름이 다른 키프레임을 따로 둔다.
 */
@keyframes rock-sink {
   0% { transform: translate(-50%, calc(-50% + var(--rock-full-y))) scale(1); opacity: 1; z-index: 3; animation-timing-function: cubic-bezier(0.7, 0, 0.4, 1); }
   62% { transform: translate(-50%, calc(-50% + var(--rock-pop-y))) scale(var(--rock-pop-scale)); opacity: 1; z-index: 3; animation-timing-function: cubic-bezier(0.7, 0.2, 0.8, 1); }
   63% { z-index: 1; }
   88% { transform: translate(-50%, calc(-50% + var(--rock-ridge-y))) scale(0.06); opacity: 1; z-index: 1; }
   100% { transform: translate(-50%, calc(-50% + var(--rock-start-y))) scale(0.055); opacity: 1; z-index: 1; }
}
.is-story-closing .story__rock { animation: rock-sink 900ms both; }

/*
 * 산 앞면은 돌이 능선을 넘을 때(rock-rise 15%)까지만 필요하다. 그 뒤로도 남겨 두면
 * 병이 z-index 4 에서 1 로 내려오는 900ms 에 산이 병 앞으로 튀어나온다.
 * 배경 프레임의 산과 같은 픽셀이라 사라져도 티가 나지 않는다.
 */
@keyframes story-front-out {
   0% { opacity: 1; }
   20% { opacity: 1; }
   26% { opacity: 0; }
   100% { opacity: 0; }
}
.is-story .story__front { animation: story-front-out 1600ms both; }

/* 닫을 때는 돌이 다시 능선 아래로 내려가기 전에 돌아온다 (rock-sink 63%) */
@keyframes story-front-in {
   0% { opacity: 0; }
   56% { opacity: 0; }
   62% { opacity: 1; }
   100% { opacity: 1; }
}
.is-story-closing .story__front { animation: story-front-in 900ms both; }

/*
 * 커지기 전의 돌은 병 뒤에 있어야 한다. .story 가 z-index 3 으로 독립 스택이라
 * 병(1)을 그 자식들 사이에 끼워 넣을 수 없으므로, 병 쪽 z-index 를 돌 궤적에
 * 맞춰 같이 넘긴다. 56.25% = 900ms 로 rock-rise 가 커지기 시작하는 지점이다.
 * 이야기 본문(.story__body)은 1300ms 에 떠오르므로 이미 병이 내려간 뒤다.
 */
@keyframes bottle-over-rock {
   /* step-end: 값을 보간하지 않고 끊어서 넘긴다. 보간하면 z 가 잠깐 3 을 지나는데
      .story 와 값이 같아 DOM 순서상 story 가 이기면서 병이 한 프레임 숨는다 */
   0% { z-index: 4; animation-timing-function: step-end; }
   56.25% { z-index: 1; animation-timing-function: step-end; }
   100% { z-index: 1; }
}
.is-story .bottle { animation: bottle-over-rock 1600ms both; }

/*
 * 닫을 때. 산 앞면이 떠오르기 시작하는 56% 보다 먼저(50%) 병을 앞으로 올린다.
 * 62% 에 올리면 56~62% 구간에서 산이 병 위에 잠깐 나타난다.
 */
@keyframes bottle-under-rock {
   0% { z-index: 1; animation-timing-function: step-end; }
   50% { z-index: 4; animation-timing-function: step-end; }
   100% { z-index: 4; }
}
.is-story-closing .bottle { animation: bottle-under-rock 900ms both; }

/*
 * 산 앞면. 배경 프레임의 산과 같은 픽셀을 같은 자리에 겹쳐 두어
 * 평소에는 티가 안 나고, 돌이 지나갈 때만 가려 준다.
 * 씬과 똑같이 배치·이동해야 어긋나지 않으므로 .scene 의 규칙을 그대로 쓴다.
 */
.story__front { position: absolute; top: 0; left: 50%; z-index: 2; width: var(--scene-w); height: var(--scene-h); transform: translateX(-50%); transform: translateX(-50%) translateY(calc(var(--scene-shift) * 100%)); pointer-events: none; }

/* 오려낸 산 조각을 씬 좌표(336, 485) 자리에 놓는다 */
.story__front img { position: absolute; top: 26.9444%; left: 23.3333%; display: block; width: 53.4028%; height: auto; }
.story__body { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 4; opacity: 0; transition: opacity 240ms ease; }
.is-story .story__body { opacity: 1; transition: opacity 420ms ease 1300ms; }

/* 이야기가 열리면 안내 문구는 비켜준다 */
.is-story .hint, .is-story .peek, .is-story .knock, .is-story .meet { opacity: 0; transition: opacity 240ms ease; }
.is-story .knock { pointer-events: none; }
.is-story-closing .story__body { opacity: 0; transition: opacity 200ms ease; }

/* 글 (433,235) 573×405 → 가운데, 위에서 26.1vh */
.story__text { position: absolute; top: calc(26.1111 * var(--vh)); left: 50%; margin: 0; transform: translateX(-50%); font-family: var(--font-kyobo); font-size: 4.4444vw; font-size: min(4.4444vw, 7.11vh); font-weight: 400; line-height: 1.27; letter-spacing: 0.02em; color: var(--c-paper); text-align: center; }
.story__line { display: block; white-space: nowrap; }
.story__line--gap { height: 0.8em; }

/* 뒤로가기 (675,675) 90×90 */
.story__back { position: absolute; top: calc(75 * var(--vh)); left: 50%; width: 6.25vw; width: min(6.25vw, 10vh); margin: 0; padding: 0; border: 0; background: none; -webkit-appearance: none; appearance: none; cursor: pointer; transform: translateX(-50%); }
.story__back img { display: block; width: 100%; height: auto; }
.story__back:focus { outline: 2px dashed var(--c-paper); outline-offset: 6px; border-radius: 999px; }
.story__back:focus:not(:focus-visible) { outline: none; }

/* --------------------------------------------------------------------------
   11. 구름 팝업
   Figma 'Desktop - cloud' 기준. 구름 933×706 @(254,97) 이 화면 정중앙에 놓이고,
   글과 뒤로가기는 구름 안에서의 비율로 자리를 잡아 크기가 변해도 함께 따라간다.
   -------------------------------------------------------------------------- */

.popup { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 2; }

/* 뒤 구름을 못 누르게 막고, 눌리면 닫힌다 */
.popup__scrim { position: absolute; top: 0; right: 0; bottom: 0; left: 0; cursor: pointer; }

/* 구름 비율 933:706. 가로가 넉넉하면 vw, 화면이 납작하면 vh 로 맞춘다 */
.popup__panel { position: absolute; top: 50%; left: 50%; width: 64.7917vw; width: min(64.7917vw, 103.6vh); height: 49.0278vw; height: min(49.0278vw, 78.4vh); }
.popup__cloud { display: block; width: 100%; height: 100%; }

/* 구름 안 (367,365) 705×162 → 가운데 정렬.
   top 이 아니라 세로 중앙 기준이라야 한 줄이든 두 줄이든 같은 자리에 놓인다.
   (top 기준이면 두 줄일 때 아래로만 늘어나 무게중심이 내려간다) */
.popup__text { position: absolute; top: 48%; left: 50%; width: 80%; margin: 0; transform: translate(-50%, -50%); font-family: var(--font-hand); font-size: 4.4444vw; font-size: min(4.4444vw, 7.11vh); font-weight: 400; line-height: 1.27; letter-spacing: 0.02em; color: var(--c-ink); text-align: center; }

/* 한글은 글자폭이 넓어 영문 기준 크기로는 텍스트박스를 넘는다.
   영문 최장 메시지와 같은 폭이 되도록 0.81배. */
.popup__text.is-ko { font-family: var(--font-kyobo); font-size: 3.6vw; font-size: min(3.6vw, 5.75vh); }
.popup__line { display: block; white-space: nowrap; }

/* 구름 안 (675,567) 90×90 → 가운데 정렬, 위에서 66.57% */
.popup__back { position: absolute; top: 66.57%; left: 50%; width: 6.25vw; width: min(6.25vw, 10vh); margin: 0; padding: 0; border: 0; background: none; -webkit-appearance: none; appearance: none; cursor: pointer; transform: translateX(-50%); }
.popup__back img { display: block; width: 100%; height: auto; }
.popup__back:focus { outline: 2px dashed var(--c-sea); outline-offset: 6px; border-radius: 999px; }
.popup__back:focus:not(:focus-visible) { outline: none; }

/* 열릴 때 살짝 떠오른다 */
/* 전환을 기본 규칙에 두어야 열릴 때와 닫힐 때 모두 걸린다.
   .is-popup 쪽에만 두면 클래스가 빠지는 순간 되돌아갈 전환이 없어 뚝 끊긴다 */
.popup__scrim { opacity: 0; transition: opacity 320ms ease; }
.popup__panel { opacity: 0; transform: translate(-50%, calc(-50% + 0.6em)); transition: opacity 380ms ease, transform 460ms var(--ease-reveal); }
.is-popup .popup__scrim { opacity: 1; }
.is-popup .popup__panel { opacity: 1; transform: translate(-50%, -50%); }

/* --------------------------------------------------------------------------
   12. 공용 푸터 (includes/footer.php)
   첫 화면 아래에 놓여, 인트로가 끝난 뒤 스크롤로 만난다.
   -------------------------------------------------------------------------- */

.site-footer { padding: 0 20px; background-color: var(--c-footer-bg); color: var(--c-footer-dim); font-family: var(--font-sans); font-size: 14px; line-height: 1.75; letter-spacing: -0.01em; word-break: keep-all; }
.site-footer__inner { display: flex; flex-wrap: wrap; width:1200px; max-width: 100%; margin: 0 auto; padding: 32px 0; }

/* address 는 기본이 이탤릭이라 되돌린다 */
.site-footer__col { flex: 1 1 260px; min-width: 0; padding: 0 26px; border-left: 1px solid var(--c-footer-rule); font-style: normal; }
.site-footer__col:first-child { padding-left: 0; border-left: 0; }
.site-footer__list { display: flex; flex-wrap: wrap; margin: 0; padding: 0; list-style: none; }

/* 항목 사이 세로줄. 글자가 아니라 테두리라 스크린리더가 읽지 않는다 */
.site-footer__item { position: relative; margin-right: 6px; padding-right: 6px; letter-spacing: -0.8px; }
.site-footer__item::after { content: ''; position: absolute; top: 0.42em; right: 0; width: 1px; height: 0.95em; background-color: var(--c-footer-rule); }
.site-footer__item:last-child { margin-right: 0; padding-right: 0; }
.site-footer__item:last-child::after { display: none; }

/* 밑줄 대신 굵기로 구분한다 (시안에 밑줄이 없다) */
.site-footer__link { color: var(--c-footer-ink); font-weight: 500; text-decoration: none; }
.site-footer__link:hover, .site-footer__link:focus { text-decoration: underline; }
.site-footer__link:focus { outline: 2px dashed currentColor; outline-offset: 3px; }
.site-footer__link:focus:not(:focus-visible) { outline: none; }
.site-footer__warning { margin: 0; }

/* --------------------------------------------------------------------------
   바다에 이어지는 변형 — 첫 화면 전용 ($footerOnSea)
   스테이지 아랫단이 그대로 아래로 흐르도록 같은 색·같은 결을 쓴다.
   -------------------------------------------------------------------------- */

.site-footer--sea { border-top: 1px solid rgba(255, 255, 255, 0.5); background-color: var(--c-sea-fill); background-image: url('../images/main/charlang-sea-fill.webp?v=2'); background-repeat: repeat; background-size: var(--scene-w) auto; color: rgba(255, 255, 255, 0.8); }

.site-footer--sea .site-footer__link { color: #ffffff; }

.site-footer--sea .site-footer__col { border-left-color: rgba(255, 255, 255, 0.35); }

.site-footer--sea .site-footer__item::after { background-color: #ffffff; }

/* --------------------------------------------------------------------------
   13. 연령 확인 (index.php)
   확인을 마칠 때까지 첫 화면 연출을 붙잡아 둔다.
   -------------------------------------------------------------------------- */

.agegate { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 10; display: flex; align-items: center; justify-content: center; padding: 20px; background-color: rgba(17, 22, 40, 0.55); }

/* 확인을 마쳤거나(세션 기억) JS 가 지운 뒤에는 보이지 않는다 */
html:not(.is-gate) .agegate { display: none; }

.agegate[hidden] { display: none; }

/* 열릴 때 여기에 포커스를 준다. 창 자체가 이미 눈에 띄므로 테두리는 그리지 않는다 */
.agegate__panel:focus { outline: none; }

.agegate__panel { width: 100%; max-width: 520px; padding: 46px 32px 34px; border-radius: 12px; background-color: #ffffff; color: var(--c-doc-ink); font-family: var(--font-sans); text-align: center; }

.agegate__title { margin: 0 0 12px; font-size: 38px; font-weight: 700; letter-spacing: -0.02em; }

.agegate__lead { margin: 0 0 32px; font-size: 21px; font-weight: 700; letter-spacing: -0.02em; }

/* gap 미지원 브라우저를 위해 여백은 버튼 쪽 margin 으로 준다 */
.agegate__actions { display: flex; justify-content: center; margin: 0 0 26px; }

.agegate__btn { flex: 0 1 190px; padding: 17px 10px; border: 1px solid var(--c-doc-ink); border-radius: 8px; font-family: inherit; font-size: 18px; font-weight: 700; line-height: 1.2; letter-spacing: 0.02em; cursor: pointer; -webkit-appearance: none; appearance: none; transition: background-color 160ms ease, color 160ms ease; }

.agegate__btn + .agegate__btn { margin-left: 16px; }

.agegate__btn--yes { background-color: var(--c-doc-ink); color: #ffffff; }

.agegate__btn--no { border-color: var(--c-doc-rule); background-color: transparent; color: var(--c-doc-ink); }

.agegate__btn--no:hover { background-color: var(--c-doc-tint-soft); }

.agegate__btn:focus { outline: 2px solid var(--c-doc-ink); outline-offset: 3px; }

.agegate__btn:focus:not(:focus-visible) { outline: none; }

.agegate__warning { margin: 0; color: var(--c-doc-dim); font-size: 13px; line-height: 1.7; }

/* --------------------------------------------------------------------------
   14. 약관·방침 문서 페이지 (policy/)
   첫 화면 연출이 없는 일반 문서라, 처음부터 스크롤되고 본문은 고딕이다.
   -------------------------------------------------------------------------- */

.is-doc, .is-doc body { height: auto; min-height: 100%; overflow: visible; }
.is-doc body { background-color: var(--c-doc-bg); color: var(--c-doc-ink); font-family: var(--font-sans); }
.policy__inner { max-width: 860px; margin: 0 auto; padding: 64px 5vw 72px; }
.policy__title { margin: 0 0 22px; font-size: 30px; font-weight: 700; letter-spacing: -0.02em; }
.policy__meta { display: flex; flex-wrap: wrap; align-items: center; padding-bottom: 20px; border-bottom: 1px solid var(--c-doc-rule); }
.policy__date { margin: 0 24px 0 0; color: var(--c-doc-dim); font-size: 14px; }
.policy__picker { display: flex; align-items: center; margin: 0; }
.policy__picker-label { margin-right: 8px; color: var(--c-doc-dim); font-size: 14px; }
.policy__select { padding: 6px 10px; border: 1px solid var(--c-doc-rule); border-radius: 4px; background-color: #fff; color: inherit; font-family: inherit; font-size: 14px; }
.policy__go { margin-left: 8px; padding: 6px 12px; border: 1px solid var(--c-doc-rule); border-radius: 4px; background-color: #fff; color: inherit; font-family: inherit; font-size: 14px; cursor: pointer; }
.policy__notice { margin: 22px 0 0; padding: 12px 16px; border-radius: 6px; background-color: #fbf1dd; font-size: 14px; }
.policy__body { margin-top: 30px; font-size: 15px; line-height: 1.85; }
.policy__body h2 { margin: 34px 0 10px; font-size: 18px; font-weight: 700; }
.policy__body h2:first-child { margin-top: 0; }
.policy__body p { margin: 0 0 12px; }
.policy__todo { padding: 14px 16px; border: 1px dashed #c04a3c; border-radius: 6px; color: #a2382c; }
.policy__empty { margin: 24px 0 0; color: var(--c-doc-dim); }
.policy__back { margin: 52px 0 0; font-size: 15px; text-align: center; }

.policy__back-link { display: inline-block; min-width: 200px; padding: 17px 44px; border: 1px solid var(--c-doc-ink); border-radius: 8px; color: var(--c-doc-ink); font-size: 17px; text-decoration: none; transition: background-color 160ms ease; }

.policy__back-link:hover { background-color: var(--c-doc-tint-soft); }

.policy__back-link:focus { outline: 2px solid var(--c-doc-ink); outline-offset: 2px; }

.policy__back-link:focus:not(:focus-visible) { outline: none; }

/* 목차 — 각 절로 바로 뛴다 */
.policy__toc { margin: 26px 0 34px; padding: 20px 24px; border-radius: 8px; background-color: var(--c-doc-tint); }
.policy__toc-list { margin: 0; padding: 0; list-style: none; }
.policy__toc-list li { margin: 0 0 6px; }
.policy__toc-list li:last-child { margin-bottom: 0; }
.policy__num { display: inline-block; min-width: 2.1em; color: var(--c-doc-dim); font-variant-numeric: tabular-nums; }
.policy__body h2 .policy__num { color: inherit; }

/* 본문 목록. 가나다 번호는 구형 브라우저에서 숫자로 떨어진다 */
.policy__list { margin: 12px 0; padding-left: 1.9em; }
.policy__list li { margin: 0 0 8px; }
.policy__list--ko { list-style-type: decimal; list-style-type: hangul; }
.policy__list--num { list-style-type: decimal; }
.policy__list .policy__list { margin: 8px 0 4px; }

/* 표 — 좁은 화면에서는 표만 가로로 밀린다 (페이지 전체가 밀리면 안 된다) */
.policy__table-wrap { margin: 16px 0 20px; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.policy__table { width: 100%; min-width: 520px; border-collapse: collapse; font-size: 14px; }
.policy__table th, .policy__table td { padding: 10px 12px; border: 1px solid var(--c-doc-rule); text-align: left; vertical-align: top; }
.policy__table thead th { background-color: var(--c-doc-tint); font-weight: 700; }
.policy__table tbody th { background-color: var(--c-doc-tint-soft); font-weight: 700; }
.policy__link { color: inherit; }

/* --------------------------------------------------------------------------
   15. 좁은 화면 푸터 — 세 단이 한 줄에 들어가지 않는 폭부터 세로로 쌓는다
   -------------------------------------------------------------------------- */

@media (max-width: 1024px) {
   .site-footer__inner { display: block; }
   .site-footer__col { padding: 0; border-left: 0; }
   .site-footer__col + .site-footer__col { margin-top: 16px; }
}

/* --------------------------------------------------------------------------
   16. 모바일 (Figma 390×844)
   -------------------------------------------------------------------------- */

@media (max-width: 768px) {
    /* Figma 모바일(390×844) 프레임의 수면 y좌표: -153 / 64 / 169 / 418 */
   :root {
      /* 모바일은 덜 좁힌다 */
      --ls-kyobo: -0.25px;

      --water-0: -0.18128;
      --water-50: 0.07583;
      --water-99: 0.20024;
      --water-100: 0.49526;
   }

   /* 모바일에서만 병을 키우고 내린다. 아랫변(50% 100%) 기준이라 위로만 커진다 */
   .bottle__art { transform: translateY(26%) scale(1.26); transform-origin: 50% 100%; }
   .cloud--large { width: 54.0865vw; width: min(54.0865vw, 24.99vh); height: 20.0321vw; height: min(20.0321vw, 9.26vh); }
   .cloud--medium { width: 35.0561vw; width: min(35.0561vw, 16.2vh); height: 12.0192vw; height: min(12.0192vw, 5.55vh); }
   .cloud--small { width: 20.0321vw; width: min(20.0321vw, 9.26vh); height: 8.0128vw; height: min(8.0128vw, 3.7vh); }
   .cloud--mini { width: 26.0417vw; width: min(26.0417vw, 12.03vh); height: 8.5136vw; height: min(8.5136vw, 3.93vh); }
   .cloud--1 { top: calc(1.8957 * var(--vh)); left: -10.5128vw; }
   .cloud--2 { top: calc(4.8578 * var(--vh)); left: 66.1538vw; }
   .cloud--3 { top: calc(13.0332 * var(--vh)); left: 12.3077vw; }
   .cloud--4 { top: calc(20.7346 * var(--vh)); left: 55.8974vw; }
   .cloud--5 { top: calc(29.6209 * var(--vh)); left: 37.4359vw; }
   .cloud--6 { top: calc(25.7109 * var(--vh)); left: -3.3333vw; }
   .cloud--7 { top: calc(33.2938 * var(--vh)); left: 71.0256vw; }
   .loader__count { font-size: 68px; }
   .loader__label { font-size: 32px; }

   /* 한글 카피는 글자폭이 넓어(1자 = 1em) 영문 기준 크기로는 넘친다.
      영문 카피와 같은 좌우 여백이 나오도록 축소한 값. */
   .reveal__title { top: calc(14 * var(--vh)); font-size: 42px; line-height: 1.2; }
   .reveal__br { display: inline; }
   .reveal__lead { top: calc(70.0237 * var(--vh)); font-size: 32px; }
   .hint { top: calc(17 * var(--vh)); left: 73.3333vw; font-size: 20px; }
   .knock { font-size: 30px; }
   .knock__br { display: inline; }
   .knock__hand { width: 62px; height: 70px; }
   .meet { font-size: 30px; }

   /* 한글 카피는 화살표 왼쪽 가용 폭(390px 기준 81px)에 한 줄로 들어가지 않는다.
      폭을 최장 줄에 맞춰 고정해 "안을 / 들여다볼까요?" 두 줄로 끊는다. */
   .peek__label { top: calc(33.1896 * var(--vh)); left: 16vw; font-size: 20px; width: 96px; white-space: normal; text-align: center; }
   .peek__arrow { top: calc(35.2630 * var(--vh)); left: 30vw; width: 11.4103vw; width: min(11.4103vw, 10.3vh); }

   /* 씬 높이가 하한 107dvh 에 걸리므로 -0.18128/1.07 - 0.36778 = -0.5372 */
   .is-loading { --scene-shift: -0.5372; }

   /* 데스크톱의 4vh 는 모바일에서 수면 아래라 돌이 그대로 보인다. 산 앞면 뒤로 올린다 */
   :root { --rock-pop-y: -30vh; --rock-full-y: calc(93.4vw - 22.16vh); --rock-start-y: -6vh; }
   .story__rock { width: 246.1538vw; }
   .story__text { top: calc(37.5592 * var(--vh)); font-size: 32px; font-size: min(32px, 8.2051vw, 3.79vh); }
   .story__back { top: calc(63.6256 * var(--vh)); width: 11.5385vw; width: min(11.5385vw, 5.33vh); }
   .popup__panel { width: 114.359vw; width: min(114.359vw, 52.84vh); height: 86.667vw; height: min(86.667vw, 40.05vh); }
   .popup__text { font-size: 32px; font-size: min(32px, 8.2051vw, 3.79vh); }
   .popup__text.is-ko { font-size: 25.9px; font-size: min(25.9px, 6.64vw, 3.07vh); }
   .popup__back { width: 11.5385vw; width: min(11.5385vw, 5.33vh); }
   .agegate__panel { padding: 34px 22px 26px; }
   .agegate__title { margin-bottom: 10px; font-size: 28px; }
   .agegate__lead { margin-bottom: 24px; font-size: 17px; }
   .agegate__btn { padding: 15px 10px; font-size: 16px; }
   .agegate__btn + .agegate__btn { margin-left: 10px; }
   .agegate__warning { font-size: 11.5px; }
   .sound { top: calc(12px + env(safe-area-inset-top, 0px)); right: calc(12px + env(safe-area-inset-right, 0px)); width: 40px; height: 40px; }
   .sound__icon { width: 22px; height: 22px; }
   .site-footer { padding: 0 24px; font-size: 13px; }
   .site-footer__inner { padding: 20px 0; }
   .policy__inner { padding: 40px 20px 52px; }
   .policy__title { margin-bottom: 18px; font-size: 23px; }
   .policy__meta { display: block; }
   .policy__date { margin: 0 0 10px; }
   .policy__body { font-size: 14px; line-height: 1.6; }
   .policy__body h2 { margin-top: 28px; font-size: 16px; }
   .policy__toc { padding: 16px 18px; }
   .policy__list { padding-left: 1.6em; }
   .policy__table { min-width: 460px; font-size: 13px; }
}

/* --------------------------------------------------------------------------
   17. 모션 최소화 설정 존중
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
   .cloud img { animation: none; }
   .is-revealing .scene, .is-revealing .artwork::before { transition-duration: 1ms; }
   .reveal__title, .reveal__line { transform: none; }
   .loader, .is-revealed .clouds { transition-duration: 1ms; transition-delay: 0s; }
   .is-revealed .reveal__title, .is-revealed .reveal__line { transition-duration: 1ms; transition-delay: 0s; }
   .is-quiet .reveal { transition-duration: 1ms; }
   .is-hinted .hint, .is-hinted .peek { transition-duration: 1ms; }
   .is-hinted .hint__inner, .is-hinted .peek__inner, .is-hinted .peek__arrow, .knock__tok.is-tap { animation: none; }
   .is-popup .popup__panel, .is-popup .popup__scrim { transition-duration: 1ms; }

   .is-story .story__rock, .is-story-closing .story__rock,
   .is-story .bottle, .is-story-closing .bottle,
   .is-story .story__front, .is-story-closing .story__front { animation-duration: 1ms; }
   .is-story .story__body, .is-story-closing .story__body { transition-duration: 1ms; transition-delay: 0s; }
}

/* --------------------------------------------------------------------------
   18. 쿠키 동의 플로팅 버튼 (OneTrust, GTM 으로 주입)
   한맥(hanmac.miraepmp.co.kr)과 같은 크기·투명도. 평소엔 60% 크기에 반투명,
   손을 올리거나 포커스하면 원래 크기로. 셀렉터는 SDK 가 만드는 표준 ID 라 바꿀 수 없다.
   -------------------------------------------------------------------------- */

#ot-sdk-btn-floating,
.ot-floating-button { opacity: 0.7 !important; transform: scale(0.6) !important; transform-origin: bottom left !important; transition: opacity 0.3s ease, transform 0.3s ease !important; }
#ot-sdk-btn-floating:hover,
#ot-sdk-btn-floating:focus,
#ot-sdk-btn-floating:focus-within,
.ot-floating-button:hover,
.ot-floating-button:focus,
.ot-floating-button:focus-within { opacity: 1 !important; transform: scale(1) !important; }

/* 모바일은 손을 올릴 일이 없으니 눌러도 작은 채로 둔다 (한맥과 동일) */
@media (max-width: 768px) {
   #ot-sdk-btn-floating:hover,
   #ot-sdk-btn-floating:focus,
   #ot-sdk-btn-floating:focus-within,
   .ot-floating-button:hover,
   .ot-floating-button:focus,
   .ot-floating-button:focus-within { transform: scale(0.6) !important; }
}

/* --------------------------------------------------------------------------
   19. 소리 켜고 끄기 (index.php, audio.js)
   우측 상단 동그란 버튼. 연령확인 창이 떠 있는 동안은 감춘다.
   구름·팝업·돌 이야기 위에 있어야 언제든 끌 수 있으므로 z-index 를 그 위(4)로 둔다.
   -------------------------------------------------------------------------- */

.sound { position: fixed; z-index: 4; top: calc(16px + env(safe-area-inset-top, 0px)); right: calc(16px + env(safe-area-inset-right, 0px)); display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin: 0; padding: 0; border: 0; border-radius: 50%; background: rgba(252, 252, 252, 0.88); color: var(--c-ink); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12); cursor: pointer; -webkit-appearance: none; appearance: none; -webkit-tap-highlight-color: transparent; transition: background-color 160ms ease, transform 160ms ease; }
.sound:hover { background: var(--c-paper); }
.sound:active { transform: scale(0.94); }
.sound:focus { outline: 2px dashed var(--c-ink); outline-offset: 3px; }
.sound:focus:not(:focus-visible) { outline: none; }
.is-gate .sound { display: none; }

.sound__icon { display: block; width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.sound__body { fill: currentColor; stroke: currentColor; stroke-width: 1; }
.sound__x { display: none; }

/* 꺼진 상태: 물결 대신 X */
.is-muted .sound__wave { display: none; }
.is-muted .sound__x { display: block; }
.is-muted .sound { color: rgba(43, 43, 41, 0.55); }
