:root {
  color-scheme: dark;
  /* 인앱 웹뷰(카카오·인스타·삼성)는 `dvh`/`vh` 가 0 이거나 주소창 높이만 오는 사례가 있다.
     변수는 100dvh 를 쓰되, 지원 안 되는 단위는 앞선 안전망이 남는다.
     JS(engine.js)가 visualViewport/innerHeight 로 px 를 덮어쓰면 그게 이긴다. */
  --app-height: 100%;
  --app-height: 100svh;
  --app-height: 100dvh;
  --ink: #f5efe3;
  --muted: rgba(245, 239, 227, .68);
  --gold: #dfbd79;
  --gold-pale: #f4ddb0;
  --panel: rgba(13, 17, 17, .86);
  --line: rgba(244, 221, 176, .22);
  font-family: "Noto Serif KR", "Nanum Myeongjo", "Batang", "AppleMyungjo", serif;
  background: #0c1111;
}

* { box-sizing: border-box; }
/* `%` 사슬이 끊기지 않게 html/body 에 명시 높이를 준다.
   ⚠ 2026-08-17 — 여기 min-height 가 `max(100%, 100svh, 100lvh)` 였다. lvh 는 **툴바가 숨은
   상태 기준의 최대 높이**라, 툴바가 떠 있는 브라우저(카카오톡 인앱·삼성인터넷)에서는 무대가
   보이는 화면보다 커지고 하단 고정 말풍선이 화면 밖으로 밀려났다. 발주자 원문:
   "카카오톡 링크로 들어가는 브라우저는 위처럼 말풍선 사라져" / "이번엔 모바일에서 밑에 말풍선이 안보여".
   안전망은 **가시 높이를 절대 넘지 않는 단위(svh)까지만** 둔다. lvh 를 되살리지 마라. */
html, body {
  width: 100%;
  height: 100%;
  min-height: 100%;
  min-height: -webkit-fill-available;
  min-height: 100svh;
  margin: 0;
  overflow: hidden;
  background: #0c1111;
}
body { overscroll-behavior: none; touch-action: manipulation; }
button { font: inherit; }
button:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--gold-pale); outline-offset: 3px; }

.game {
  position: relative;
  width: 100%;
  /* 높이의 정본은 JS 실측 px(engine.js 가 visualViewport.height 로 --app-height 를 덮어쓴다).
     아래 사슬은 JS 전 폴백. ⚠ lvh·max(...) 금지 — 위 html/body 주석의 사고 기록 참조. */
  height: 100%;
  height: 100svh;
  height: 100dvh;
  height: var(--app-height);
  min-height: 480px;
  min-height: 100%;
  min-height: -webkit-fill-available;
  min-height: 100svh;
  overflow: hidden;
  isolation: isolate;
  color: var(--ink);
  background: #12191a;
  transition: background-color .8s ease, color .8s ease;
  /* 2026-08-17 발주자 지적 — "모바일에서 외부앱에서 누르고 있으면 복사하기가 떠".
     게임 화면은 글을 고르는 곳이 아니다: 길게 눌러도 선택/복사 메뉴가 뜨지 않게 한다.
     (q1 hold→tap 전환과 같은 회전. 입력창이 생기면 그 요소에서만 다시 풀 것.) */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
/* 입력창(도전 닉네임 등)만은 글 선택이 도로 된다 */
.game input, .game textarea, .joseon-challenge input {
  -webkit-user-select: text;
  user-select: text;
}

.backdrop, .backdrop::before, .backdrop::after {
  position: absolute;
  inset: 0;
}
.backdrop {
  z-index: -4;
  overflow: hidden;
  background:
    radial-gradient(circle at 70% 18%, rgba(230, 195, 126, .24), transparent 24%),
    linear-gradient(165deg, #31484b, #152224 55%, #090e0f);
  transition: background 1s ease, filter 1s ease;
}
.backdrop::before {
  content: "";
  background:
    linear-gradient(90deg, transparent 48%, rgba(238, 215, 166, .12) 49%, transparent 50%) 0 0 / 24% 100%,
    linear-gradient(0deg, rgba(6, 10, 10, .86) 0 13%, transparent 13% 100%);
  opacity: .65;
}
.backdrop::after {
  content: "";
  background: linear-gradient(180deg, rgba(5, 8, 9, .18), transparent 36%, rgba(4, 7, 8, .82));
}
.backdrop[data-family="joseon"] {
  background:
    radial-gradient(circle at 66% 16%, rgba(224, 171, 88, .20), transparent 23%),
    linear-gradient(165deg, #465042, #202b26 56%, #0c1211);
}
.backdrop[data-family="modern"] {
  background:
    radial-gradient(circle at 60% 19%, rgba(245, 207, 137, .28), transparent 20%),
    radial-gradient(circle at 25% 30%, rgba(115, 166, 171, .22), transparent 22%),
    linear-gradient(165deg, #314c50, #17272a 56%, #090f10);
}
.backdrop[data-background*="rainy"]::before {
  background: repeating-linear-gradient(102deg, transparent 0 17px, rgba(206, 226, 219, .09) 18px 19px, transparent 20px 34px);
  animation: rain 1.2s linear infinite;
}
.backdrop[data-background*="cave"] { filter: saturate(.68) brightness(.64); }
.backdrop[data-background*="boat"], .backdrop[data-background*="river"], .backdrop[data-background*="stream"] {
  background:
    radial-gradient(ellipse at 66% 15%, rgba(250, 231, 177, .36) 0 4%, transparent 5% 100%),
    linear-gradient(172deg, #263b3e 0 48%, #142829 49% 64%, #071415 65%);
}
.backdrop[data-background*="wedding"], .backdrop[data-background*="invitation"] {
  background:
    radial-gradient(circle at 50% 22%, rgba(255, 243, 218, .72), transparent 22%),
    linear-gradient(145deg, #4b544d, #9d8467 45%, #302b29);
}
.backdrop[data-background="blackout"] { background: #050606; }
.horizon {
  position: absolute;
  width: 120%;
  height: 35%;
  left: -10%;
  bottom: 12%;
  border-radius: 50% 50% 0 0;
  background: linear-gradient(180deg, rgba(5, 9, 9, .05), rgba(5, 9, 9, .62));
  transform: perspective(360px) rotateX(64deg);
  transform-origin: bottom;
}
.light-path {
  position: absolute;
  left: 50%;
  bottom: -8%;
  width: 35%;
  height: 58%;
  transform: translateX(-50%) perspective(280px) rotateX(58deg);
  background: linear-gradient(90deg, transparent, rgba(225, 197, 133, .12), transparent);
  filter: blur(8px);
}
.grain {
  position: absolute;
  inset: 0;
  opacity: .10;
  background-image: radial-gradient(rgba(255,255,255,.55) .5px, transparent .7px);
  background-size: 5px 5px;
  mix-blend-mode: soft-light;
}

.game-header {
  position: absolute;
  z-index: 12;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: max(18px, env(safe-area-inset-top)) 18px 0;
  pointer-events: none;
}
.game-header p { margin: 0 0 4px; color: var(--gold-pale); font-size: 10px; letter-spacing: .26em; }
.game-header h1 { margin: 0; font-size: 14px; font-weight: 500; letter-spacing: .05em; }
.game-header button {
  pointer-events: auto;
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid rgba(255,255,255,.15);
  border-radius: 999px;
  color: rgba(255,255,255,.7);
  background: rgba(5,9,10,.45); /* blur 제거 보상 — 2026-08-17 WebView 검은 판 결함, cinematic-v2 .menu-sheet 주석 */
  font-family: system-ui, sans-serif;
  font-size: 11px;
}
.story-progress {
  position: absolute;
  z-index: 12;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: rgba(255,255,255,.07);
}
.story-progress i { display: block; width: var(--progress, 0%); height: 100%; background: linear-gradient(90deg, #88734c, #f1d79f); transition: width .7s ease; }
.memory-status {
  position: absolute;
  z-index: 12;
  right: 18px;
  top: max(70px, calc(env(safe-area-inset-top) + 53px));
  display: flex;
  gap: 8px;
}
.memory-mark {
  width: 9px;
  height: 9px;
  border: 1px solid rgba(244,221,176,.35);
  border-radius: 50%;
  background: rgba(6,9,10,.35);
  transition: .5s ease;
}
.memory-mark.found { border-color: #f5d895; background: #f5d895; box-shadow: 0 0 14px #f1c96c; }

.character-stage {
  position: absolute;
  z-index: 2;
  inset: 12% 0 29%;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: min(4vw, 24px);
  padding: 0 8%;
  pointer-events: none;
}
.stage-figure {
  position: relative;
  width: min(36vw, 180px);
  height: min(53vh, 430px);
  opacity: .58;
  filter: brightness(.65) saturate(.6);
  transform: translateY(8px) scale(.96);
  transition: opacity .45s ease, filter .45s ease, transform .45s ease;
}
.stage-figure[data-speaking="true"] { opacity: .96; filter: brightness(1.06) saturate(.82); transform: translateY(0) scale(1); }
.silhouette { position: absolute; inset: 0; filter: drop-shadow(0 16px 24px rgba(0,0,0,.36)); }
.silhouette-head {
  position: absolute;
  left: 50%;
  top: 5%;
  width: 42%;
  aspect-ratio: .84;
  transform: translateX(calc(-50% + var(--gaze-x) * 5px));
  border-radius: 52% 48% 46% 50%;
  background: linear-gradient(145deg, rgba(223,211,186,.75), rgba(69,79,75,.92));
}
.silhouette-body {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 88%;
  height: 76%;
  transform: translateX(-50%);
  border-radius: 45% 45% 12% 12% / 22% 22% 5% 5%;
  background: linear-gradient(120deg, rgba(96,111,104,.92), rgba(22,29,28,.98));
}
.stage-figure[data-who="dahee"] .silhouette-body { background: linear-gradient(120deg, rgba(167,118,111,.9), rgba(52,45,48,.98)); }
.stage-figure[data-costume="hanbok"] .silhouette-body { width: 104%; clip-path: polygon(30% 0,70% 0,100% 100%,0 100%); }
.stage-figure[data-costume="guard"] .silhouette-head::after {
  content: ""; position: absolute; left: -25%; right: -25%; top: -12%; height: 22%; border-radius: 50%; background: #1b2322;
}
.stage-name {
  position: absolute;
  left: 50%;
  bottom: 3%;
  transform: translateX(-50%);
  padding: 4px 10px;
  border-radius: 99px;
  color: rgba(255,255,255,.58);
  background: rgba(5,8,9,.35);
  font-size: 10px;
  letter-spacing: .1em;
  white-space: nowrap;
}

.text-panel {
  position: absolute;
  z-index: 10;
  left: 14px;
  right: 14px;
  bottom: max(14px, env(safe-area-inset-bottom));
  min-height: 88px;
  padding: 14px 18px 20px;
  border: 1px solid var(--line);
  border-radius: 4px 20px 4px 20px;
  background: linear-gradient(145deg, rgba(20,25,24,.93), rgba(7,11,12,.91));
  box-shadow: 0 18px 48px rgba(0,0,0,.34), inset 0 1px rgba(255,255,255,.04);
  /* 블러 없음 — wire-runtime.css 의 카드 규칙 주석 참조(2026-08-11 반짝임 판정). */
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.text-panel::before, .text-panel::after {
  content: "";
  position: absolute;
  width: 26px;
  height: 26px;
  border-color: rgba(225,192,124,.42);
}
.text-panel::before { left: 7px; top: 7px; border-left: 1px solid; border-top: 1px solid; }
.text-panel::after { right: 7px; bottom: 7px; border-right: 1px solid; border-bottom: 1px solid; }
.speaker { min-height: 17px; margin: 0 0 10px; color: var(--gold-pale); font-size: 13px; font-weight: 700; letter-spacing: .13em; }
.story-text { margin: 0; color: var(--ink); font-size: clamp(16px, 4.25vw, 20px); line-height: 1.75; word-break: keep-all; }
.text-panel.narration .story-text { color: rgba(247,241,228,.82); font-style: italic; }
.text-panel.memory { border-color: rgba(244,210,135,.52); box-shadow: 0 0 42px rgba(222,174,76,.14); }
.text-panel.quest .story-text { color: #f6dfac; text-align: center; font-style: normal; letter-spacing: .03em; }
.text-panel.ending .story-text { text-align: center; font-size: clamp(17px, 4.6vw, 22px); line-height: 1.9; }
.next-hint {
  position: absolute;
  right: 22px;
  bottom: 16px;
  width: 8px;
  height: 8px;
  border-right: 1px solid var(--gold);
  border-bottom: 1px solid var(--gold);
  transform: rotate(45deg);
  opacity: 0;
}
.next-hint.visible { opacity: 1; animation: breathe 1.5s ease-in-out infinite; }
.game[data-cg-response="loading"] .next-hint,
.game[data-cg-response="playing"] .next-hint { opacity: 0 !important; }

.choices {
  position: absolute;
  z-index: 15;
  left: 14px;
  right: 14px;
  bottom: max(18px, env(safe-area-inset-bottom));
  display: none;
  gap: 10px;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: rgba(9,13,14,.94);
}
.choices.visible { display: grid; }
.choice-title { margin: 0 4px 9px; color: var(--gold-pale); font-size: 13px; letter-spacing: .08em; }
.choice-button {
  width: 100%;
  min-height: 56px;
  padding: 13px 16px;
  border: 1px solid rgba(237,215,170,.25);
  border-radius: 5px 14px 5px 14px;
  color: var(--ink);
  background: rgba(255,255,255,.035);
  text-align: left;
  line-height: 1.5;
  -webkit-tap-highlight-color: transparent;
}
.choice-button:active { background: rgba(239,211,153,.12); }

.minigame-layer, .special-layer {
  position: absolute;
  z-index: 30;
  inset: 0;
  display: none;
  background: linear-gradient(180deg, #0a0f10, #0c1414);
}
.minigame-layer.visible, .special-layer.visible { display: block; }
.minigame-shell {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  width: 100%;
  height: 100%;
  padding: max(20px, env(safe-area-inset-top)) 16px max(18px, env(safe-area-inset-bottom));
}
.minigame-head { padding: 6px 6px 14px; }
.minigame-head .eyebrow { margin: 0 0 4px; color: var(--gold); font-size: 10px; letter-spacing: .24em; }
.minigame-head h2 { margin: 0 0 8px; font-size: 23px; font-weight: 500; }
.minigame-head p:last-child { margin: 0; color: var(--muted); font-family: system-ui, sans-serif; font-size: 13px; line-height: 1.55; }
.minigame-play { min-width: 0; min-height: 0; overflow: hidden; }
.skip-scene {
  justify-self: center;
  visibility: hidden;
  opacity: 0;
  min-height: 42px;
  margin-top: 10px;
  padding: 8px 18px;
  border: 0;
  color: rgba(245,239,227,.58);
  background: transparent;
  font-size: 12px;
  text-decoration: underline;
  text-underline-offset: 4px;
  transition: opacity .5s ease;
}
.skip-scene.is-visible { visibility: visible; opacity: 1; }

.palm-scene { position: relative; height: 100%; display: grid; grid-template-rows: auto 1fr auto auto; align-items: center; }
.lantern-row { display: flex; justify-content: center; gap: 22px; padding: 8px 0 4px; }
.lantern-row i { width: 13px; height: 18px; border: 1px solid rgba(225,190,119,.24); border-radius: 45% 45% 35% 35%; background: #202322; }
.lantern-row i.lit { background: #ffd98e; box-shadow: 0 0 18px #f0ad47, 0 0 38px rgba(240,173,71,.45); }
.trace-letter, .glow-letter {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: "Malgun Gothic", sans-serif;
  font-size: min(38vw, 165px);
  font-weight: 800;
  color: transparent;
  -webkit-text-stroke: 2px rgba(250,225,178,.22);
}
.trace-canvas { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; }
.glow-letter { opacity: 0; color: #ffe6a6; -webkit-text-stroke: 0; text-shadow: 0 0 20px #ffc65c, 0 0 45px #f6a532; }
.glow-letter.flash { animation: letterFlash .9s ease; }
.trace-field.complete { filter: drop-shadow(0 0 26px rgba(239,182,73,.38)); }
.letter-progress { margin: 6px 0; text-align: center; color: rgba(255,255,255,.42); letter-spacing: .3em; }
.letter-progress b { color: #ffe1a1; font-size: 1.25em; }
.wrong-words { display: flex; justify-content: center; gap: 7px; }
.wrong-words button { padding: 6px 10px; border: 1px solid rgba(255,255,255,.10); border-radius: 999px; color: rgba(255,255,255,.44); background: transparent; font-family: system-ui, sans-serif; font-size: 11px; }
.minigame-dialogue { position: absolute; left: 10px; right: 10px; bottom: 36px; min-height: 32px; margin: 0; color: #f4dfb5; text-align: center; font-size: 13px; }

.river-game { position: relative; height: 100%; min-height: 370px; overflow: hidden; border-radius: 22px; background: linear-gradient(90deg, #0a1b20, #18383d 48%, #0b2228); touch-action: none; }
.river-game::before { content: ""; position: absolute; inset: 0; background: repeating-radial-gradient(ellipse at 50% 100%, transparent 0 18px, rgba(208,229,219,.08) 19px 21px); }
.river-moon { position: absolute; left: 50%; top: 4%; width: 54px; height: 54px; border-radius: 50%; transform: translateX(-50%); background: #f4e8c9; box-shadow: 0 0 35px rgba(244,232,201,.3); transition: 1s ease; }
.river-track { position: absolute; inset: 10% 0 13%; }
.moon-shard { position: absolute; left: var(--x); top: calc(13% + var(--index, 0) * 15%); width: 22px; height: 13px; border-radius: 50%; background: #f8e9ba; box-shadow: 0 0 14px rgba(255,226,151,.65); transform: translateX(-50%) rotate(18deg); transition: .5s ease; }
.moon-shard[data-index="0"] { top: 18%; }.moon-shard[data-index="1"] { top: 34%; }.moon-shard[data-index="2"] { top: 50%; }.moon-shard[data-index="3"] { top: 66%; }.moon-shard[data-index="4"] { top: 80%; }
.moon-shard.collected { opacity: 0; transform: translateX(-50%) scale(2); }
.river-obstacle { position: absolute; left: var(--x); top: var(--y); width: 44px; height: 8px; border-radius: 50%; background: #25312d; transform: rotate(-22deg); opacity: .75; }
.boat { position: absolute; left: 50%; bottom: 13%; width: 76px; height: 43px; transform: translateX(-50%); transition: left .08s linear, transform .4s ease; }
.boat::before { content: ""; position: absolute; inset: 17px 0 0; border-radius: 0 0 50% 50%; background: #7c5b3b; box-shadow: inset 0 5px #b98a59; }
.boat span { position: absolute; top: 1px; color: #d7c6aa; font-size: 31px; }.boat span:first-child { left: 9px; }.boat span:last-child { right: 9px; }
.river-game.tilting .boat { transform: translateX(-50%) rotate(13deg); }
.river-game.soft-collision .boat { opacity: .55; transform: translateX(-50%) rotate(-7deg); }
.balance-panel { position: absolute; left: 50%; top: 50%; display: none; width: 82%; justify-content: space-between; transform: translate(-50%,-50%); }
.balance-panel.visible { display: flex; }
.balance-panel button { width: 78px; height: 78px; border: 1px solid rgba(245,224,179,.4); border-radius: 50%; color: #f1ddba; background: rgba(9,20,22,.82); }
.balance-panel button.pressed { background: rgba(226,188,111,.32); }
.river-count { position: absolute; right: 14px; top: 10px; margin: 0; color: rgba(255,255,255,.6); font-family: system-ui, sans-serif; font-size: 11px; }
.boat-dialogue { position: absolute; left: 14px; right: 14px; bottom: 12px; min-height: 34px; padding: 8px 10px; border-radius: 9px; color: #f7e8c8; background: rgba(5,10,11,.58); text-align: center; font-size: 12px; }
.boat-dialogue:empty { opacity: 0; }
.river-game.moon-complete .river-moon { top: 38%; width: 98px; height: 28px; border-radius: 50%; filter: blur(2px); box-shadow: 0 0 45px #f1d79b; }

.pattern-game { position: relative; height: 100%; min-height: 390px; overflow: hidden; border-radius: 22px; background: radial-gradient(circle at 50% 45%, #332d24, #161817 68%); touch-action: none; }
.pattern-target { position: absolute; left: 50%; top: 45%; width: min(65vw, 260px); aspect-ratio: 1; transform: translate(-50%,-50%); border: 1px dashed rgba(238,210,153,.26); border-radius: 50%; }
.pattern-target::before, .pattern-target::after { content: ""; position: absolute; inset: 23%; border: 3px solid rgba(222,184,112,.14); border-radius: 50%; transform: rotate(45deg) skew(8deg); }
.pattern-target::after { transform: rotate(-45deg) skew(-8deg); }
.pattern-target span { position: absolute; color: rgba(236,206,144,.32); font-size: 25px; }.pattern-target span:nth-of-type(1){left:18%;top:50%}.pattern-target span:nth-of-type(2){left:48%;top:13%}.pattern-target span:nth-of-type(3){right:14%;bottom:22%}
.piece-tray { position: absolute; inset: 0; }
.pattern-piece { position: absolute; width: 49px; height: 55px; border: 1px solid rgba(250,224,166,.34); clip-path: polygon(50% 0, 100% 80%, 50% 100%, 0 80%); transform: translate(-50%,-50%) rotate(var(--angle)); background: linear-gradient(135deg, #a67b3f, #e0b967 48%, #70502e); box-shadow: 0 7px 14px rgba(0,0,0,.32); touch-action: none; }
.pattern-piece::after { content: ""; position: absolute; left: 47%; top: 6px; bottom: 6px; border-left: 2px solid rgba(70,44,19,.55); transform: rotate(16deg); }
.pattern-piece.placed { pointer-events: none; box-shadow: 0 0 18px rgba(240,201,118,.28); }
.pattern-count { position: absolute; left: 0; right: 0; bottom: 7px; margin: 0; color: rgba(255,255,255,.55); text-align: center; font-family: system-ui, sans-serif; font-size: 11px; }
.pattern-game.complete .pattern-target { box-shadow: 0 0 55px rgba(224,181,93,.33); border-color: #dcb56f; }

.ring-pair-game { position: relative; height: 100%; min-height: 380px; overflow: hidden; border-radius: 22px; background: radial-gradient(circle at 50% 42%, #393128, #141615 72%); }
.ring-options { height: 100%; display: grid; grid-template-columns: repeat(3, 1fr); align-items: center; gap: 7px; padding: 4px; }
.ring-options.hidden { display: none; }
.ring-options button { min-width: 0; height: 50%; display: flex; justify-content: center; align-items: center; gap: 3px; overflow: hidden; padding: 4px; border: 1px solid rgba(243,221,177,.18); border-radius: 45% 45% 12px 12px; background: rgba(255,255,255,.025); }
.ring-options button.quiet-miss { opacity: .45; }.ring-options button.chosen { border-color: #e6c37c; box-shadow: 0 0 25px rgba(230,195,124,.22); }
.ring { position: relative; display: inline-block; width: 40px; height: 58px; border: 7px solid; border-radius: 50%; transform: rotate(-12deg); }
.ring.silver { border-color: #e2e3dd; box-shadow: inset 3px 0 4px #6e7374, 2px 0 3px rgba(255,255,255,.35); }
.ring.rose { border-color: #c98c82; box-shadow: inset 3px 0 4px #754a49, 2px 0 3px rgba(255,210,199,.32); }
.ring.crossed::before, .ring.crossed::after { content: ""; position: absolute; left: -7px; right: -7px; top: 20px; height: 7px; border-radius: 7px; background: currentColor; transform: rotate(24deg); box-shadow: 0 0 3px rgba(255,255,255,.4); }
.ring.crossed::after { transform: rotate(-24deg); background: repeating-linear-gradient(90deg, currentColor 0 3px, rgba(255,255,255,.85) 4px 5px); }
.ring.reverse { transform: rotate(12deg); }
.ring-hands { position: relative; display: none; height: 100%; }
.ring-hands.visible { display: block; }
.ring-hands p { position: absolute; left: 0; right: 0; bottom: 12px; color: rgba(255,255,255,.56); text-align: center; font-family: system-ui,sans-serif; font-size: 12px; }
.hand { position: absolute; width: 118px; height: 200px; border-radius: 50% 50% 38% 38%; background: linear-gradient(135deg,#d2a085,#966956); box-shadow: 0 15px 30px rgba(0,0,0,.28); }
.dahee-hand { left: 60%; top: 18%; transform: rotate(18deg); }.minui-hand { left: 8%; top: 52%; transform: rotate(-68deg); touch-action: none; }
.hand .ring { position: absolute; left: 38px; top: 20px; transform: scale(.54); transform-origin: top left; }
.finger-target { position: absolute; left: 59%; top: 31%; width: 58px; height: 58px; border: 1px dashed rgba(244,216,160,.45); border-radius: 50%; }
.minui-hand.joined { left: 53% !important; top: 26% !important; transition: .4s ease; }.ring-pair-game.complete { box-shadow: inset 0 0 80px rgba(226,183,100,.2); }

.special-layer { background: radial-gradient(circle at 50% 35%, #27312f, #090d0e 72%); overflow: auto; }
.quiet-ending { background: #090b0b; cursor: pointer; }
.quiet-pulse { position: absolute; left: 50%; top: 50%; width: 3px; height: 3px; border-radius: 50%; background: rgba(237,220,181,.42); box-shadow: 0 0 32px 10px rgba(237,220,181,.08); animation: quietPulse 2.4s ease-in-out infinite; }
.invitation-card, .credits-card { width: min(100%, 520px); min-height: 100%; margin: auto; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: max(32px, env(safe-area-inset-top)) 24px max(24px, env(safe-area-inset-bottom)); text-align: center; }
.invitation-card::before { content: ""; position: absolute; inset: 14px; border: 1px solid rgba(230,203,150,.24); border-radius: 50% 50% 8px 8px / 12% 12% 8px 8px; pointer-events: none; }
.invitation-kicker { max-width: 340px; margin: 0 0 18px; color: rgba(246,239,224,.65); font-size: 12px; line-height: 1.75; word-break: keep-all; }
.double-ring { position: relative; width: 88px; height: 43px; margin: 3px 0 18px; }.double-ring i { position: absolute; width: 42px; height: 42px; border: 2px solid #d9d7d0; border-radius: 50%; }.double-ring i:first-child { left: 13px; }.double-ring i:last-child { right: 13px; border-color: #c98e81; }
.couple { display: flex; align-items: center; gap: 14px; margin: 0 0 24px; font-size: 13px; }.couple span { display: grid; gap: 5px; color: rgba(255,255,255,.55); }.couple b { color: #fff8e9; font-size: 22px; font-weight: 500; letter-spacing: .12em; }.couple > i { width: 1px; height: 35px; background: rgba(225,197,142,.35); }
.invitation-card time { color: #fff7e8; font-size: 18px; line-height: 1.55; letter-spacing: .1em; }.invitation-card time b { color: var(--gold-pale); font-size: 24px; font-weight: 500; }
.invitation-card address { margin: 8px 0 19px; color: rgba(255,255,255,.76); font-style: normal; font-size: 14px; }
.final-narration { max-width: 350px; margin: 0 0 19px; color: rgba(249,241,225,.86); font-size: 14px; line-height: 1.8; word-break: keep-all; }.final-narration span { display: block; margin-bottom: 5px; color: var(--gold); font-size: 10px; letter-spacing: .15em; }
.invitation-actions { width: 100%; max-width: 360px; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }.invitation-actions button { min-height: 44px; padding: 8px; border: 1px solid rgba(239,216,169,.23); border-radius: 4px 11px 4px 11px; color: rgba(255,249,237,.78); background: rgba(255,255,255,.035); font-family: system-ui,sans-serif; font-size: 12px; }
.credits-touch { margin-top: 13px; width: 46px; height: 28px; border: 0; background: transparent; }.credits-touch i { display: block; width: 9px; height: 9px; margin: auto; border-right: 1px solid var(--gold); border-bottom: 1px solid var(--gold); transform: rotate(45deg); animation: breathe 1.5s ease-in-out infinite; }
.credits-card { gap: 24px; }.credits-card > p { max-width: 340px; margin: 0; color: rgba(255,255,255,.62); font-size: 14px; line-height: 1.8; }/* ⚠ 2026-08-13 독립 검수 E: 「반지 문양이 월식으로 깨져 있다」. 사실이었다.
   전에는 `box-shadow: 20px 0 0 -1px #18201f` 로 **불투명 원판을 얹어** 겹치는 부분을
   파내고 있었는데, 그 `#18201f` 가 뒷배경 색을 손으로 베낀 값이었다.
   배경이 그라데이션으로 바뀌자 원판만 남아 한쪽 반지가 먹힌 것처럼 보였다.
   ⚠ **배경색을 값으로 베껴 무언가를 가리지 마라.** 배경이 바뀌면 조용히 깨진다.
   두 개의 테두리 원으로 그린다 — 무엇 위에 놓여도 두 반지로 읽힌다. */
.credit-rings { position: relative; width: 92px; height: 72px; }
.credit-rings::before, .credit-rings::after { content: ''; position: absolute; top: 0; width: 72px; height: 72px; border-radius: 50%; }
.credit-rings::before { left: 0; border: 1px solid #e1d2b2; }
.credit-rings::after { left: 20px; border: 1px solid #bc877d; }.credits-card dl { width: min(280px,80vw); margin: 0; }.credits-card dl div { display: flex; justify-content: space-between; padding: 13px 0; border-bottom: 1px solid rgba(255,255,255,.11); }/* ⚠ 2026-08-14 — 크레딧 뒷벽의 어둠막을 글자 칸 크기로 줄였다(`cinematic-v2.css` 의 `.credits-layer`).
   막이 얇아진 만큼 **글자가 자기 대비를 가져야 한다** — 뒤는 창빛이 드는 밝은 예식 홀이다.
   그림자를 빼면 위 두 줄이 흰 벽에 묻힌다. 두 파일은 한 쌍이다. */
.credits-card dt { color: rgba(255,255,255,.62); text-shadow: 0 1px 6px rgba(0,0,0,.72); }.credits-card dd { margin: 0; color: #fff0d4; font-size: 18px; letter-spacing: .12em; text-shadow: 0 1px 7px rgba(0,0,0,.78); }/* 어둠은 **글자 칸에만** 준다 — 화면 전체를 덮으면 홀이 죽고(2026-08-14 검수 D),
   아무 데도 안 주면 크림색 글자가 크림색 벽에 묻힌다(막을 걷어 낸 직후 실제로 그랬다).
   그래서 이름 두 줄 뒤에만 둥근 유리판을 깐다. */
.credits-card dl { position: relative; }
/* ⚠ 두 번 물렸다. ① `inset: -14px -22px` + `border-radius` → **회색 상자**. 그림 위에 UI 판을
   붙인 꼴이었다. ② 크게 잡고 원형으로 번지게 → 이번엔 벽에 **검은 구름**이 떴다.
   벽이 평평해서 둥근 얼룩은 물체로 읽힌다.
   ③ 그래서 **가로 전폭 띠**로 간다. 세로로만 사라지는 띠는 눈이 「벽에 드리운 그늘」로 읽는다 —
      가장자리가 어디서 끝나는지 보이지 않는 것이 핵심이다. 폭을 좁히지 마라. */
.credits-card dl::before { content: ''; position: absolute; inset: -80px -50vw; z-index: -1; background: linear-gradient(180deg,rgba(6,10,11,0) 0%,rgba(6,10,11,.30) 26%,rgba(6,10,11,.48) 50%,rgba(6,10,11,.30) 74%,rgba(6,10,11,0) 100%); }
.credits-card dl div { border-bottom-color: rgba(255,255,255,.26); }.credits-card > p { text-shadow: 0 1px 6px rgba(0,0,0,.7); }.credit-rings::before, .credit-rings::after { filter: drop-shadow(0 1px 4px rgba(0,0,0,.6)); }/* ⚠ 2026-08-13 — `.back-to-invitation` 은 2026-08-13 에 총괄이 넣고 **CSS 를 안 준** 버튼이다.
   나머지 둘이 금색 테두리 알약인데 혼자 브라우저 기본 회색 상자로 서 있었다.
   검수 E 가 화면에서 잡았다. 버튼을 만들면 그 버튼의 옷도 같이 만들어라. */
/* 알약 셋은 밝아진 홀 위에 선다 — `background: transparent` 면 테두리만 남아 사라진다.
   옅은 어둠 채움 + 흐림으로 유리처럼 앉힌다(final-invitation 의 버튼과 같은 문법). */
.restart-story, .back-to-invitation { min-height: 44px; padding: 8px 24px; border: 1px solid rgba(231,205,153,.34); border-radius: 999px; color: rgba(255,255,255,.82); background: rgba(6,10,11,.6); text-shadow: 0 1px 5px rgba(0,0,0,.7); }
/* 하객이 나중에 다시 찾아오는 문이다 — 「처음부터」보다 눈에 먼저 들어와야 한다. */
.back-to-invitation { border-color: rgba(231,205,153,.52); color: #fff0d4; }
/* 엔딩 보상 문 — 끝까지 본 하객만 받는 1회 생성권이라 넷 중 가장 먼저 눈에 들어와야 한다.
   알약 문법은 형제들과 같게, 채움만 금빛 한 겹 얹어 「보상」임을 알린다. */
.shorts-enter { min-height: 44px; padding: 8px 24px; border: 1px solid rgba(231,205,153,.62); border-radius: 999px; color: #fff4dc; background: linear-gradient(180deg, rgba(120,88,42,.55), rgba(6,10,11,.65)); text-shadow: 0 1px 5px rgba(0,0,0,.7); cursor: pointer; }
.shorts-enter:hover { border-color: rgba(244,221,176,.75); }

.era-shift::after { content: ""; position: absolute; z-index: 80; inset: 0; pointer-events: none; background: #f2e6cf; animation: eraShift 1.05s ease both; }

@keyframes rain { to { transform: translate(-24px, 50px); } }
@keyframes breathe { 0%,100% { transform: translateY(-2px) rotate(45deg); opacity: .25; } 50% { transform: translateY(3px) rotate(45deg); opacity: 1; } }
@keyframes letterFlash { 0% { opacity: 0; transform: scale(.8); } 35% { opacity: 1; } 100% { opacity: 0; transform: scale(1.08); } }
@keyframes quietPulse { 0%,100% { opacity: .2; transform: scale(.8); } 50% { opacity: .8; transform: scale(1.3); } }
@keyframes eraShift { 0% { opacity: 0; } 28% { opacity: .85; } 100% { opacity: 0; } }

@media (min-width: 700px) {
  .game { width: min(100%, 520px); margin: 0 auto; box-shadow: 0 0 80px rgba(0,0,0,.5); }
  body { background: #050808; }
  .text-panel, .choices { left: 22px; right: 22px; }
}

@media (max-height: 680px) {
  .text-panel { min-height: 72px; padding: 10px 14px 16px; }
  .story-text { font-size: 15px; line-height: 1.62; }
}
@media (max-height: 620px) {
  .character-stage { inset: 11% 0 31%; }
  .minigame-head { padding-bottom: 6px; }.minigame-head h2 { font-size: 19px; margin-bottom: 3px; }
  .trace-field { height: min(30vh, 230px); width: min(54vw, 220px); }
}

/* ⚠ 2026-08-14 W8 — 예전 `* { animation-duration:.001ms; animation-iteration-count:1 }` 는
   삼성 절전/「애니메이션 제거」가 보고하는 reduce 한 방에 **등불 호흡·물빛까지** 죽였다.
   헤드리스는 늘 no-preference 라 이 상태를 본 적이 없다. reduce 의 목적은 전정기관 자극
   (큰 이동·회전·줌·시차) 을 없애는 것이지 화면을 정지 이미지로 만드는 것이 아니다.
   이동 계열은 아래·각 파일의 개별 블록이 끈다. 밝기·불투명도 빛은 산다. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  .bg-image,
  .ambient-particles i,
  .water-plane,
  .stage-figure,
  .next-hint::before,
  .game.hpunch :is(.backdrop, .character-stage),
  .game.is-bad-ending .bg-image {
    animation: none !important;
  }
}

/* ── 진입 로딩 게이트(2026-08-16) ────────────────────────────────────────────────
   왜 있나 — 「처음부터」를 누른 뒤 첫 대사까지가 **검은 화면 + 탭 무반응**이었다.
   (실측 live-repro-20260816: 3Mbps/300ms 11.9초 · 700kbps/200ms 46.1초, 그 동안 탭 4번이 전부 삼켜짐.)
   기다림 자체를 없앨 수 없으면 **보이게** 한다. 이 층이 하는 일은 세 가지뿐이다.
     ① 탭 직후 1초 안에 뜬다(스타일이 이미 받아져 있으므로 네트워크를 안 탄다).
     ② 진행률이 단조 증가로 움직인다(숫자·막대).
     ③ 등불이 계속 숨을 쉰다 — 멈춘 화면으로 안 보이게.
   z-index 는 타이틀(.start-layer = 100) 위. 아이리스가 도는 동안에도 이 층이 위에 남는다. */
.entry-gate {
  position: absolute; z-index: 140; inset: 0;
  display: grid; place-items: center;
  padding: 8vh 10vw calc(8vh + env(safe-area-inset-bottom, 0px));
  color: #f3e7d2; background: radial-gradient(120% 90% at 50% 42%, #16232a 0%, #0a1114 62%, #060b0d 100%);
  text-align: center;
  opacity: 0; transition: opacity 220ms ease;
}
.entry-gate[hidden] { display: none; }
.entry-gate[data-state="on"] { opacity: 1; }
/* ⚠ 닫히는 중(off)에는 탭을 통과시켜라 — 페이드 240ms 동안 투명한 게이트가
   hit-test 에 남아, 카드가 뜨자마자 누른 탭을 삼켰다 (2026-08-17 실기기 결함:
   「날짜 누르고 대사가 안 떠」. 증거 artifacts/firstline-bug-20260817). */
.entry-gate[data-state="off"] { pointer-events: none; }
.entry-gate-inner { display: grid; justify-items: center; gap: 18px; width: min(320px, 78vw); }
/* 등불 셋 — 화풍(타이틀의 청사초롱 밤)에 맞춘 순수 CSS 광원. 이미지 요청을 만들지 않는다. */
.entry-gate-lamp { display: flex; gap: 14px; }
.entry-gate-lamp i {
  width: 12px; height: 16px; border-radius: 46% 46% 40% 40% / 40% 40% 60% 60%;
  background: radial-gradient(60% 60% at 50% 35%, #ffe6ac 0%, #e5b45f 55%, rgba(196,132,52,.35) 100%);
  box-shadow: 0 0 16px 2px rgba(233,178,94,.42);
  animation: entryGateLamp 1.5s ease-in-out infinite;
}
.entry-gate-lamp i:nth-child(2) { animation-delay: .25s; }
.entry-gate-lamp i:nth-child(3) { animation-delay: .5s; }
@keyframes entryGateLamp {
  0%, 100% { opacity: .28; transform: translateY(1px) scale(.94); }
  45%      { opacity: 1;   transform: translateY(-2px) scale(1.06); }
}
.entry-gate-label {
  margin: 0; font-size: 14px; letter-spacing: .12em; color: #ecd9b6;
  text-shadow: 0 2px 12px rgba(0,0,0,.85);
}
.entry-gate-bar {
  position: relative; width: 100%; height: 3px; overflow: hidden;
  border-radius: 999px; background: rgba(236,217,182,.16);
}
.entry-gate-bar > i {
  display: block; width: 0; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, rgba(229,180,95,.75), #ffe6ac);
  box-shadow: 0 0 10px rgba(233,178,94,.55);
  transition: width 180ms linear;
}
.entry-gate-pct { margin: 0; font: 400 11px/1 system-ui, sans-serif; letter-spacing: .22em; color: rgba(243,231,210,.62); }
/* 절전 모드 — 위치가 움직이는 연출은 끄고 **빛의 숨만** 남긴다. 진행률(막대·숫자)은 그대로 돈다. */
@media (prefers-reduced-motion: reduce) {
  .entry-gate { transition: none; }
  .entry-gate-lamp i { animation: entryGateLampQuiet 2.2s ease-in-out infinite; }
  .entry-gate-bar > i { transition: none; }
}
@keyframes entryGateLampQuiet { 0%, 100% { opacity: .34; } 50% { opacity: 1; } }

/* 2026-08-17 하단 UI 핫픽스 — 상시 텍스트는 없애고 우하단 메뉴 손잡이 하나만 둔다. */
.game .bottom-bar {
  position: absolute; z-index: 21; left: auto; right: max(12px, env(safe-area-inset-right));
  bottom: max(8px, var(--safe-bottom)); width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center; margin: 0; padding: 0;
  background: none; border: 0; transition: opacity 220ms ease;
}
.game .bottom-bar .bar-button {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0; border: 1px solid rgba(229,181,87,.20);
  border-radius: 50%; background: rgba(6,10,11,.18); color: rgba(244,238,226,.58);
  font: 500 18px/1 system-ui,sans-serif; text-shadow: 0 1px 6px rgba(0,0,0,.85);
  cursor: pointer;
}
.game .bottom-bar .bar-button::before { content: ""; position: absolute; inset: -3px; }
.game .bottom-bar .bar-icon { color: rgba(229,181,87,.68); font-size: 20px; line-height: 1; }
.game:has(#start-layer[hidden]) .corner-hud > .sound-control { display: none; }
