/* ── 字体（v0.2.4 子集化）─────────────────────────────────────────
   源字体 ChillZhuoKai_R.otf 18.98 MB → 子集 WOFF2 0.80 MB。
   只保留本项目实际用到的 1577 字（渲染用字 879 + 全项目文案余量），
   换文案后必须重跑子集化脚本，否则新字会静默回落系统楷体。
   WOFF2 支持起始 = Chrome 36，远低于本项目兼容底线（JS 55 / CSS 79），
   因此不再需要 .woff / .ttf 兜底，源 OTF 也不进包。 */
@font-face {
  font-family: "Chill ZhuoKai";
  src: url("./assets/font/ChillZhuoKai_subset.woff2") format("woff2");
  font-display: swap;
  font-weight: 400;
  font-style: normal;
}

:root {
  --paper: #ececea;
  --paper-deep: #d9dad8;
  --paper-dialogue: rgba(248, 248, 246, 0.98);
  --ink: #242523;
  --ink-soft: #626460;
  --line: rgba(36, 37, 35, 0.72);
  --font-main: "Chill ZhuoKai", "KaiTi", "STKaiti", "Kaiti SC", serif;

  /* ── 安全区（v0.2.3）───────────────────────────────────────────────
     集中成变量，一处兜底、处处安全。
     不认识 env()/constant() 的内核 → 两个 @supports 都为假 → 变量保持 0px，
     调用点退化成普通数值，绝不会再出现「整条声明被丢弃」。
     只取上下：书页是居中的 9:16 竖版，横屏时左右离屏幕边缘还很远，
     加 --sal/--sar 反而会在横屏多出一截内缩。 */
  --sat: 0px;
  --sab: 0px;
}

/* iOS 11.0–11.2：只认 constant() */
@supports (padding-top: constant(safe-area-inset-top)) {
  :root {
    --sat: constant(safe-area-inset-top);
    --sab: constant(safe-area-inset-bottom);
  }
}

/* iOS 11.2+ / Chrome 69+：标准写法 */
@supports (padding-top: env(safe-area-inset-top)) {
  :root {
    --sat: env(safe-area-inset-top);
    --sab: env(safe-area-inset-bottom);
  }
}

* { margin: 0; padding: 0; box-sizing: border-box; }
[hidden] { display: none !important; }

html, body {
  height: 100%;
  background: #1d1c19;
  color: var(--ink);
  font-family: var(--font-main);
  -webkit-tap-highlight-color: transparent;
}

button { font: inherit; }

/* ══════════════════════════════════════════════════════════════════
   旧内核兼容说明（v2.2.1）
   浏览器遇到不认识的单位/属性会【整条丢弃声明】，不会回退到上一个值。
   因此凡是 Chrome 87+/88+/108+ 才支持的写法，一律先写兼容值、再写新值，
   让新旧内核各自取到能用的那一条。
   ══════════════════════════════════════════════════════════════════ */

.stage {
  position: relative;
  /* 兼容值：vh —— 所有内核都认（WebView 内视口固定，等同于 dvh） */
  width: min(100vw, calc(100vh * 9 / 16));
  height: 100vh;
  /* 新内核值：dvh —— 贴合动态视口（Chrome 108+ / iOS 15.4+），上一代静默忽略 */
  width: min(100vw, calc(100dvh * 9 / 16));
  height: 100dvh;
  max-width: 540px;
  margin: 0 auto;
  overflow: hidden;
  background: var(--paper) url("./assets/art/UI_页面底面.png") center / cover;
  box-shadow: 0 0 40px rgba(0, 0, 0, 0.5);
}

.page-frame {
  position: absolute;
  /* inset 是 Chrome 87+，这里写全展开的等效值 */
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 60;
  background: url("./assets/art/UI_边框.png") center / 100% 100% no-repeat;
  pointer-events: none;
}

.screen {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: none;
  flex-direction: column;
  background: var(--paper) url("./assets/art/UI_页面底面.png") center / cover;
}
.screen.is-active { display: flex; animation: screen-in 280ms ease-out; }

@keyframes screen-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.slip-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 52px;
  padding: 10px 18px;
  border: 1px solid var(--line);
  border-radius: 1px;
  background: rgba(236, 237, 234, 0.94);
  color: var(--ink);
  /* 兜底：clamp() 是 Chrome 79+，老内核整条丢弃 */
  font-size: 18px;
  font-size: clamp(18px, 4.2vw, 22px);
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-indent: 0.18em;
  cursor: pointer;
  transition: background-color 140ms, border-color 140ms, transform 120ms;
}
.slip-button:hover,
.slip-button:focus-visible {
  border-color: var(--ink);
  background: rgba(211, 213, 210, 0.96);
  outline: none;
}
.slip-button:active { transform: translateY(1px); }
.slip-button:disabled {
  color: rgba(98, 95, 87, 0.45);
  border-color: rgba(36, 35, 31, 0.22);
  cursor: default;
  transform: none;
}

/* 主界面 */
.screen--menu { justify-content: space-between; }
.menu-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 100%;
  padding: calc(24px + var(--sat)) 36px calc(24px + var(--sab));
}
.menu-visual {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.menu-visual img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.menu-nav {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  margin-bottom: 20px;
}
/* flex gap 是 Chrome 84+，旧内核不认；改用相邻兄弟外边距等效还原 */
.menu-nav > .slip-button + .slip-button { margin-top: 12px; }
/* 剧情画面：纸纹常驻，一次只显示一个场景、人物或道具 */
.screen--game { background: var(--paper-deep); }
.scene {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow: hidden;
  background: var(--paper) url("./assets/art/UI_页面底面.png") center / cover;
}
.visual-image {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-position: center center;
  opacity: 0;
  transition: opacity 260ms ease-out;
  pointer-events: none;
}
.visual-image.is-visible { opacity: 1; }
.visual-image[data-fit="cover"] { object-fit: cover; }
.visual-image[data-fit="contain"] { object-fit: contain; }
.scene[data-tone="night"] .visual-image { filter: brightness(0.78) grayscale(0.1); }
.scene[data-tone="cold"] .visual-image { filter: brightness(0.9) grayscale(0.12); }
.scene[data-tone="warm"] .visual-image { filter: grayscale(0.03) brightness(1.02); }

.scene-fx { position: absolute; top: 0; right: 0; bottom: 0; left: 0; pointer-events: none; }
.scene-fx[data-fx="fog"],
.scene-fx[data-fx="heavy-fog"] {
  background:
    radial-gradient(58% 24% at 28% 78%, rgba(236, 237, 234, 0.38), transparent 72%),
    radial-gradient(52% 23% at 74% 66%, rgba(236, 237, 234, 0.3), transparent 72%);
  animation: fx-drift 9s ease-in-out infinite alternate;
}
.scene-fx[data-fx="smoke"] {
  background: radial-gradient(35% 30% at 50% 69%, rgba(236, 237, 234, 0.42), transparent 72%);
  animation: fx-drift 6s ease-in-out infinite alternate;
}
.scene-fx[data-fx="falling"] { background: radial-gradient(70% 40% at 50% 40%, rgba(36, 35, 31, 0.15), transparent 75%); }
.scene-fx[data-fx="memory"] {
  background: linear-gradient(180deg, rgba(236, 237, 234, 0.02), rgba(36, 35, 31, 0.22));
  animation: fx-memory 1.6s ease-in-out infinite alternate;
}
.scene-fx[data-fx="ink"] { background: radial-gradient(80% 60% at 50% 50%, transparent 55%, rgba(36, 35, 31, 0.2)); }
@keyframes fx-drift { from { transform: translateX(-2.5%); } to { transform: translateX(2.5%); } }
@keyframes fx-memory { from { opacity: 0.5; } to { opacity: 1; } }

.game-topbar {
  position: absolute;
  top: calc(18px + var(--sat));
  left: 18px;
  right: 18px;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 5px 8px 0;
}
.game-topbar__right { display: flex; align-items: center; }
.game-topbar__right > * + * { margin-left: 8px; }
.topbar-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 4px 10px;
  border: 1px solid rgba(36, 35, 31, 0.38);
  border-radius: 1px;
  background: rgba(236, 237, 234, 0.82);
  color: var(--ink-soft);
  /* 兜底：clamp() 是 Chrome 79+，老内核整条丢弃 */
  font-size: 15px;
  font-size: clamp(15px, 3.6vw, 18px);
  letter-spacing: 0.1em;
  cursor: pointer;
}
.topbar-button:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }
.topbar-button:disabled { opacity: 0.42; cursor: default; }
.save-flash {
  padding: 3px 8px;
  border: 1px solid rgba(36, 35, 31, 0.3);
  background: rgba(236, 237, 234, 0.82);
  color: var(--ink-soft);
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  animation: save-flash 1.4s ease-out forwards;
}
@keyframes save-flash {
  0% { opacity: 0; transform: translateY(-3px); }
  12%, 78% { opacity: 1; transform: none; }
  100% { opacity: 0; }
}

.narration-box,
.dialogue-box {
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: calc(3.5% + var(--sab));
  z-index: 20;
  display: flex;
  align-items: center;
  height: auto;
  min-height: 120px;
  max-height: 30vh;
  padding: 18px 22px;
  /* 兜底：clamp() 是 Chrome 79+，老内核整条丢弃 */
  font-size: 18px;
  font-size: clamp(18px, 4.2vw, 22px);
  line-height: 1.6;
  border-radius: 1px;
  cursor: pointer;
  animation: text-in 200ms ease-out;
}
.narration-box > p,
.dialogue-box > p {
  width: 100%;
  max-height: calc(30vh - 36px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.narration-box {
  border: 1px solid rgba(236, 237, 234, 0.46);
  background: rgba(27, 26, 23, 0.84);
  box-shadow: 0 2px 12px rgba(20, 18, 15, 0.34);
  color: #f4f4f1;
  letter-spacing: 0.06em;
}
.dialogue-box {
  border: 1px solid rgba(36, 35, 31, 0.72);
  background: var(--paper-dialogue);
  box-shadow: 0 3px 16px rgba(20, 18, 15, 0.3);
  color: var(--ink);
  letter-spacing: 0.05em;
}

.speaker-tag {
  position: absolute;
  top: -18px;
  right: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  max-width: calc(100% - 28px);
  white-space: nowrap;
  min-height: 36px;
  padding: 4px 14px;
  border: 1px solid rgba(36, 35, 31, 0.72);
  border-radius: 1px;
  background: rgba(248, 248, 246, 0.98);
  color: var(--ink);
  /* 兜底：clamp() 是 Chrome 79+，老内核整条丢弃 */
  font-size: 18px;
  font-size: clamp(18px, 4.2vw, 22px);
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-indent: 0.08em;
}
/* flex gap 是 Chrome 84+，旧内核不认；改用相邻兄弟外边距等效还原 */
.speaker-tag > * + * { margin-left: 5px; }
.speaker-tag--player {
  top: -38px;
  right: auto;
  left: 14px;
  width: 94px;
  height: 52px;
  min-height: 0;
  padding: 2px 8px;
  border: 0;
  background: transparent;
}
.speaker-rattle { flex: 0 0 auto; width: 19px; height: 19px; fill: currentColor; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.speaker-rattle .drum-face { fill: none; }

@keyframes text-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

.continue-mark {
  position: absolute;
  right: 14px;
  bottom: 14px;
  color: #eeeeec;
  opacity: 0.45;
  font: 36px/1 Arial, sans-serif;
  transform: scaleY(0.65);
  transform-origin: center;
  animation: continue-breathe 2s ease-in-out infinite;
  pointer-events: none;
  user-select: none;
}
.dialogue-box .continue-mark { color: #4d4f4b; }
@keyframes continue-breathe {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .continue-mark { animation: none; opacity: 0.75; }
}

.choice-layer {
  position: absolute;
  left: 22px;
  right: 22px;
  bottom: 20%;
  z-index: 25;
  display: flex;
  justify-content: center;
  pointer-events: none;
}
.choice-list {
  display: flex;
  flex-direction: column;
  width: 64%;
  pointer-events: auto;
  animation: text-in 240ms ease-out;
}
.choice-list > * + * { margin-top: 12px; }
.choice-button {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 10px 18px;
  border: 1px solid var(--line);
  border-radius: 1px;
  background: rgba(236, 237, 234, 0.94);
  color: var(--ink);
  /* 兜底：clamp() 是 Chrome 79+，老内核整条丢弃 */
  font-size: 18px;
  font-size: clamp(18px, 4.2vw, 22px);
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-indent: 0.18em;
  cursor: pointer;
  transition: background-color 140ms, transform 120ms;
}
.choice-button:hover,
.choice-button:focus-visible {
  border-color: var(--ink);
  background: rgba(211, 213, 210, 0.96);
  outline: none;
}
.choice-button:active { transform: translateY(1px); }
.choice-button--primary::before {
  content: "";
  position: absolute;
  left: 9px;
  top: 50%;
  width: 7px;
  height: 2px;
  background: var(--ink);
  transform: translateY(-50%);
}

/* 过往文字 */
.history-layer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 55;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(32px + var(--sat)) 27px calc(32px + var(--sab));
  background: rgba(29, 28, 25, 0.62);
}
.history-panel {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 82%;
  padding: 17px;
  border: 2px solid rgba(236, 237, 234, 0.72);
  outline: 1px solid rgba(236, 237, 234, 0.4);
  outline-offset: -6px;
  background: rgba(27, 26, 23, 0.96);
  color: #f4f4f1;
}
.history-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 3px 12px;
  border-bottom: 1px solid rgba(236, 237, 234, 0.35);
}
.history-header h2 { font-size: 1.35rem; font-weight: 400; letter-spacing: 0.4em; text-indent: 0.4em; }
.history-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 10px 5px 4px;
  scrollbar-color: rgba(236, 237, 234, 0.55) transparent;
}
.history-item { padding: 9px 5px; border-bottom: 1px dashed rgba(236, 237, 234, 0.22); }
.history-item--dialogue { padding-left: 17px; }
.history-speaker { margin-bottom: 3px; color: #c8cac6; font-size: 0.76rem; letter-spacing: 0.2em; }
.history-text { color: #f4f4f1; font-size: 0.92rem; line-height: 1.75; letter-spacing: 0.04em; }
.history-empty { padding-top: 36px; color: #c8cac6; text-align: center; letter-spacing: 0.12em; }

.return-confirm-layer {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(29, 28, 25, 0.62);
}
.return-confirm-card {
  width: 100%;
  max-width: 400px;
  padding: 24px 22px;
  border: 2px solid var(--ink);
  outline: 1px solid var(--line);
  outline-offset: -6px;
  background: var(--paper-dialogue);
  color: var(--ink);
}
.return-confirm-card h2 { margin-bottom: 12px; font-size: 24px; font-weight: 400; }
.return-confirm-card p { font-size: 18px; line-height: 1.6; }
.return-confirm-actions { display: flex; margin-top: 22px; }
.return-confirm-actions .slip-button { flex: 1; min-height: 44px; padding: 8px 4px; font-size: 18px; }
.return-confirm-actions > * + * { margin-left: 12px; }
.return-confirm-actions button:focus { outline: 2px solid var(--ink); outline-offset: 3px; }

/* 结局抽签 */
.ending-layer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: var(--paper) url("./assets/art/UI_页面底面.png") center / cover;
  animation: screen-in 320ms ease-out;
}
.fortune-tube { width: 46%; max-width: 240px; }
.fortune-tube img { display: block; width: 100%; }
.fortune-tube.is-shaking { animation: tube-shake 1.65s ease-in-out; }
@keyframes tube-shake {
  0%, 100% { transform: rotate(0); }
  15% { transform: rotate(-4deg) translateY(-2px); }
  30% { transform: rotate(3.5deg); }
  45% { transform: rotate(-3deg) translateY(-3px); }
  60% { transform: rotate(2.5deg); }
  75% { transform: rotate(-1.5deg); }
  88% { transform: rotate(1deg); }
}
.ending-result {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: none;
  height: 100%;
}
.ending-book {
  width: 100%;
  /* 兜底：min() 是 Chrome 79+，等价拆成 height + max-height */
  height: 44vh;
  max-height: 380px;
  height: min(44vh, 380px);
  height: min(44dvh, 380px);
  padding: 10px;
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: 0 4px 18px rgba(36, 35, 31, 0.2);
  animation: text-in 380ms ease-out;
}
.ending-book img { display: block; width: 100%; height: 100%; object-fit: contain; }
.ending-slip,
.fortune-sign {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  /* 兜底：min() 是 Chrome 79+，等价拆成 height + max-height */
  height: 61vh;
  max-height: 520px;
  height: min(61vh, 520px);
  height: min(61dvh, 520px);
  background: transparent;
  writing-mode: vertical-rl;
}
.ending-slip {
  margin-top: -10px;
  transform: translateY(12px) rotate(8deg);
  filter: drop-shadow(0 5px 4px rgba(24, 24, 22, 0.17));
  animation: slip-drop 480ms ease-out 180ms backwards;
}
.ending-result--sign-only .ending-slip {
  width: 72px;
  /* 兜底：min() 是 Chrome 79+，等价拆成 height + max-height */
  height: 61vh;
  max-height: 520px;
  height: min(61vh, 520px);
  height: min(61dvh, 520px);
  margin-top: 10px;
}
.ending-slip-image,
.fortune-sign__image {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.ending-slip-title,
.fortune-sign__title {
  position: relative;
  z-index: 1;
  margin-top: 38%;
  color: var(--ink);
  /* 兜底：clamp() 是 Chrome 79+，老内核整条丢弃 */
  font-size: 16px;
  font-size: clamp(16px, 3.8vw, 20px);
  line-height: 1.15;
  letter-spacing: 0.18em;
  text-indent: 0.18em;
}
.ending-result:not(.ending-result--sign-only) .ending-slip {
  position: absolute;
  right: 12%;
  bottom: 46%;
  z-index: 3;
  width: 43px;
  height: 228px;
  margin: 0;
}
.ending-result:not(.ending-result--sign-only) .ending-slip-title { margin-top: 42%; font-size: 12px; }
@keyframes slip-drop {
  from { opacity: 0; transform: translateY(-32px) rotate(8deg); }
  to { opacity: 1; transform: translateY(12px) rotate(8deg); }
}
.ending-actions {
  position: absolute;
  left: 50%;
  bottom: 5.5%;
  z-index: 5;
  width: 70%;
  margin: 0;
  transform: translateX(-50%);
  animation: text-in 280ms ease-out 520ms backwards;
}
.ending-result:not(.ending-result--sign-only) .ending-book {
  position: absolute;
  top: 7%;
  right: 7%;
  bottom: 7%;
  left: 7%;
  z-index: 1;
  width: auto;
  height: auto;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: 0 4px 18px rgba(36, 35, 31, 0.16);
}
.ending-result:not(.ending-result--sign-only) .ending-book img { object-fit: cover; }
.ending-result:not(.ending-result--sign-only) .ending-actions {
  left: 50%;
  bottom: 5.5%;
  width: 70%;
}

/* 结局图鉴 */
.screen--gallery { padding: calc(20px + var(--sat)) 22px calc(20px + var(--sab)); }
.gallery-header { margin-bottom: 14px; text-align: center; }
.gallery-header h2 { font-size: 1.6rem; font-weight: 400; letter-spacing: 0.4em; text-indent: 0.4em; }
.gallery-count { margin-top: 4px; color: var(--ink-soft); font-size: 0.75rem; letter-spacing: 0.2em; }
.gallery-grid {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-content: start;
  /* gap 简写是 Chrome 66+；Chrome 57–65 走 grid-gap（双写） */
  grid-gap: 14px;
  gap: 14px;
  min-height: 0;
  padding: 2px;
  overflow-y: auto;
}
.gallery-item {
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 1px;
  background: rgba(236, 237, 234, 0.52);
  color: var(--ink);
  text-align: center;
  cursor: pointer;
}
.gallery-item:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }
.gallery-item img { display: block; width: 100%; }
.gallery-item-title { margin-top: 6px; color: var(--ink); font-size: 0.88rem; letter-spacing: 0.2em; }
.gallery-item.is-locked { cursor: default; opacity: 0.64; }
.gallery-locked-face {
  display: flex;
  align-items: center;
  justify-content: center;
  /* aspect-ratio 是 Chrome 88+；旧内核退化为固定最小高度，保证格子不塌 */
  min-height: 168px;
  aspect-ratio: 3 / 4;
  border: 1px dashed rgba(36, 35, 31, 0.35);
  color: var(--ink-soft);
  font-size: 1rem;
  letter-spacing: 0.3em;
}
.fortune-sign--gallery {
  width: 42px;
  height: 150px;
  margin: 4px auto;
}
.fortune-sign { transform: translateY(5px) rotate(9deg); filter: drop-shadow(0 3px 3px rgba(24, 24, 22, 0.14)); }
.fortune-sign--gallery .fortune-sign__title { margin-top: 44%; font-size: 0.72rem; }
.gallery-back { width: 46%; margin-top: 14px; align-self: center; }
.gallery-detail {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(29, 28, 25, 0.6);
  animation: screen-in 200ms ease-out;
}
.gallery-detail-card {
  width: 78%;
  padding: 14px;
  border: 1px solid var(--line);
  background: var(--paper) url("./assets/art/UI_页面底面.png") center / cover;
  text-align: center;
}
.gallery-detail-card > img { display: block; width: 100%; }
.gallery-detail-title { margin: 10px 0 12px; color: var(--ink); font-size: 1.1rem; letter-spacing: 0.35em; text-indent: 0.35em; }
.gallery-detail-sign { display: flex; justify-content: center; margin-bottom: 17px; }
.fortune-sign--detail { width: 64px; height: 60vh; max-height: 500px; height: min(60vh, 500px); height: min(60dvh, 500px); }

@media (max-height: 700px) {
  .ending-result--sign-only .ending-slip { height: 420px; }
  .fortune-sign--detail { height: 400px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ═══ 《山神》v0.1 覆盖层：保留 v2.2.1 兼容声明，替换视觉与结局结构 ═══ */
.stage {
  width: min(100vw, calc(100vh * 9 / 16));
  height: 100vh;
  width: min(100vw, calc(100dvh * 9 / 16));
  height: 100dvh;
  max-width: 540px;
  margin: 0 auto;
  background: #ececea;
}
.page-paper {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  z-index: 0;
  background: #ececea url("./assets/art/UI_页面底面.png") center / 100% 100% no-repeat;
  pointer-events: none;
}
.page-frame { background-image: url("./assets/art/UI_边框.png"); }
.screen,
.scene,
.gallery-detail-card { background: transparent; }
.screen { z-index: 1; }

.menu-inner {
  padding-top: calc(28px + var(--sat));
  padding-right: 36px;
  padding-bottom: calc(24px + var(--sab));
  padding-left: 36px;
}
.menu-visual { opacity: 0.9; }
.menu-visual::after {
  content: "";
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  background: linear-gradient(180deg, rgba(236,236,234,0.08) 30%, rgba(236,236,234,0.92) 78%);
}
.menu-title {
  position: absolute;
  top: 9%; left: 10%;
  z-index: 3;
  color: var(--ink);
  text-shadow: 0 1px 0 rgba(255,255,255,0.55);
}
.menu-title p { font-size: clamp(18px, 4vw, 23px); letter-spacing: 0.45em; }
.menu-title h1 { margin-top: 8px; font-size: clamp(48px, 13vw, 76px); font-weight: 400; letter-spacing: 0.28em; }
.menu-title span { display: block; margin-top: 7px; font-size: 12px; letter-spacing: 0.16em; }
.menu-nav { padding: 14px; border: 1px solid rgba(36,37,35,0.52); background: rgba(236,236,234,0.76); }

.game-topbar {
  top: calc(18px + var(--sat));
  left: 18px;
  right: 18px;
}
.topbar-button--image {
  position: relative;
  width: 60px;
  min-width: 60px;
  height: 40px;
  padding: 0;
  border: 0;
  background: transparent;
}
.topbar-button--image.topbar-button--skip { width: 116px; min-width: 116px; }
.topbar-button--image img { display: block; width: 100%; height: auto; object-fit: contain; }
.topbar-button--image span {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.narration-box,
.dialogue-box {
  min-height: 116px;
  max-height: 30vh;
  padding: 18px 22px;
  overflow: visible;
  /* 兜底：clamp() 是 Chrome 79+，老内核整条丢弃 */
  font-size: 18px;
  font-size: clamp(18px, 4.2vw, 22px);
  line-height: 1.6;
}
.narration-box { background: rgba(27,26,23,0.92); border-color: rgba(236,237,234,0.55); color: #f4f4f1; }
.dialogue-box { background: var(--paper-dialogue); border-color: rgba(36,35,31,0.72); color: var(--ink); }
.narration-box > p,
.dialogue-box > p { max-height: calc(30vh - 36px); overflow-y: auto; }
.speaker-tag { z-index: 1; }
.speaker-tag--player { width: 94px; max-width: calc(100% - 28px); }
.choice-layer { padding-bottom: calc(24px + var(--sab)); }
.choice-list { max-height: 66vh; overflow-y: auto; }

.inventory-layer {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  z-index: 54;
  display: flex; align-items: center; justify-content: center;
  padding: 28px;
  background: rgba(29,28,25,0.58);
}
.inventory-card {
  width: 88%; max-height: 72%; overflow-y: auto;
  padding: 24px 22px;
  border: 2px solid var(--ink);
  outline: 1px solid rgba(36,37,35,0.48);
  outline-offset: -7px;
  background: #ececea url("./assets/art/UI_页面底面.png") center / cover;
}
.inventory-card h2 { margin-bottom: 14px; text-align: center; font-size: 1.45rem; font-weight: 400; letter-spacing: 0.4em; text-indent: 0.4em; }
.inventory-card ul { margin: 0 0 18px; padding: 8px 8px 8px 2.2em; font-size: 1.05rem; line-height: 1.9; }

.ending-layer { background: #ececea url("./assets/art/UI_页面底面.png") center / 100% 100% no-repeat; }
.ending-result { width: 100%; height: 100%; }
.ending-book-image {
  position: absolute;
  top: 6%; right: 6%; bottom: 7%; left: 6%;
  display: block;
  width: 88%; height: 87%;
  object-fit: cover;
  box-shadow: 0 5px 20px rgba(24,24,22,0.18);
}
.ending-title-plaque {
  position: absolute;
  left: 50%; bottom: 14%;
  z-index: 3;
  min-width: 46%;
  padding: 8px 20px;
  transform: translateX(-50%);
  border: 1px solid rgba(36,37,35,0.72);
  background: rgba(236,236,234,0.94);
  text-align: center;
  /* 兜底：clamp() 是 Chrome 79+，老内核整条丢弃 */
  font-size: 22px;
  font-size: clamp(22px, 5vw, 30px);
  letter-spacing: 0.32em;
  text-indent: 0.32em;
  box-shadow: 0 3px 7px rgba(24,24,22,0.15);
}
.ending-new-achievements {
  position: absolute;
  top: 8%; right: 8%;
  z-index: 4;
  max-width: 48%;
  padding: 8px 12px;
  border: 1px solid rgba(36,37,35,0.55);
  background: rgba(236,236,234,0.9);
  text-align: center;
}
.ending-new-achievements p { margin-bottom: 4px; font-size: 0.78rem; color: var(--ink-soft); letter-spacing: 0.2em; }
.ending-new-achievements strong { display: block; font-size: 0.96rem; font-weight: 400; letter-spacing: 0.18em; }
.ending-result .ending-actions { bottom: calc(7% + var(--sab)); width: 62%; }

.screen--gallery {
  padding-top: calc(20px + var(--sat));
  padding-right: 22px;
  padding-bottom: calc(20px + var(--sab));
  padding-left: 22px;
}
.gallery-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 2px 4px 12px; }
.gallery-section-title { margin: 8px 0 12px; font-size: 1.05rem; font-weight: 400; letter-spacing: 0.34em; text-indent: 0.34em; text-align: center; }
.gallery-grid { overflow: visible; min-height: auto; }
.gallery-item img { aspect-ratio: 9 / 16; object-fit: cover; }
.achievement-grid { display: grid; grid-template-columns: 1fr; grid-gap: 10px; gap: 10px; }
.achievement-card { padding: 14px; border: 1px solid var(--line); background: rgba(236,236,234,0.64); text-align: center; }
.achievement-card h4 { margin-bottom: 5px; font-size: 1.02rem; font-weight: 400; letter-spacing: 0.24em; }
.achievement-card p { color: var(--ink-soft); font-size: 0.84rem; line-height: 1.55; }
.achievement-card.is-locked { opacity: 0.58; }
.gallery-detail-card > img { max-height: 68vh; object-fit: contain; }

/* v0.2：正式素材坐标、逐句对白与手动可停的自动播放。 */
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; }
.menu-inner { padding: 0; }
.menu-visual { opacity: 1; }
.menu-visual::after { display: none; }
.menu-visual img { object-fit: fill; }
.menu-nav { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: 0; padding: 0; border: 0; background: transparent; pointer-events: none; }
.menu-art-button { position: absolute; left: 9.63%; width: 46.019%; height: 8.021%; padding: 0; border: 0; background: transparent; cursor: pointer; pointer-events: auto; }
.menu-art-button svg { display: block; width: 100%; height: 100%; }
#btn-new { top: 67.083%; }
#btn-continue { top: 75.677%; height: 7.969%; }
#btn-gallery { top: 84.323%; height: 7.969%; }
.menu-art-button:disabled { opacity: 0.45; cursor: default; }
.menu-art-button:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.menu-art-button:active { transform: translateY(1px); }
.topbar-button--image svg { display: block; width: 100%; height: 100%; }
.scene-overlays { position: absolute; top: 0; right: 0; bottom: 0; left: 0; pointer-events: none; }
.scene[data-black="true"] { background: #111; }
.scene-fx[data-fx="none"] { opacity: 0; }
.scene-fx[data-fx="fade-black"] { background: #000; transition: opacity 1.8s ease-in-out; }
.scene-fx[data-fx="black-cut"] { background: #000; animation: black-cut 650ms ease-out both; }
@keyframes black-cut { from { opacity: 1; } to { opacity: 0; } }
.narration-box, .dialogue-box { bottom: calc(9% + var(--sab)); }
.speaker-tag--player { top: -55px; left: 12px; width: 52px; height: 70px; padding: 0; border: 0; background: transparent; }
.speaker-tag--player .speaker-rattle { display: block; width: 100%; height: 100%; }
.speaker-rattle svg { display: block; width: 100%; height: 100%; }
.speaker-tag:not(.speaker-tag--player) { max-width: calc(100% - 28px); }
.advance-controls { position: absolute; right: 7%; bottom: calc(3.7% + var(--sab)); z-index: 22; display: flex; align-items: center; }
.auto-button { min-height: 36px; min-width: 82px; padding: 5px 10px; border: 1px solid var(--line); background: rgba(248,248,246,0.95); color: var(--ink); font-size: 14px; line-height: 1.4; cursor: pointer; }
.auto-button[aria-pressed="true"] { background: #242523; color: #f4f4f1; }
.auto-button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.ending-book-image { top: 6%; right: 6%; bottom: 7%; left: 6%; object-fit: contain; box-shadow: none; }
.ending-new-achievements { top: 10%; right: 10%; left: 10%; max-width: none; }
.ending-actions { animation: none; }
.game-topbar { z-index: 41; }
@media (max-width: 360px) {
  .game-topbar { left: 10px; right: 10px; padding-left: 5px; padding-right: 5px; }
  .game-topbar__right > * + * { margin-left: 5px; }
  .topbar-button--image { width: 52px; min-width: 52px; }
  .topbar-button--image.topbar-button--skip { width: 104px; min-width: 104px; }
  .save-flash { position: absolute; top: 48px; right: 4px; }
}

/* ══════════════════════════════════════════════════════════════════
   v0.2.3 兼容兜底层
   上面那些 min() / clamp() / aspect-ratio 在老内核里是「整个值非法 → 丢掉整条
   声明」。这里给出等价替代。条件全部用 @supports not 写，现代内核一条都不匹配，
   渲染结果与修正前逐像素一致（已用无头 Chrome 逐像素验证）。
   ══════════════════════════════════════════════════════════════════ */

/* ① min() 是 Chrome 79+。丢了之后 .stage 会连 width 一起失效 → 书页被拉满容器。
   等价还原 min(100vw, calc(100vh * 9 / 16)) 再叠原有的 max-width: 540px：
     width 取竖版比例宽，max-width 先按视口宽封顶，≥540px 时再收到 540px。 */
@supports not (width: min(1px, 1px)) {
  .stage {
    width: calc(100vh * 9 / 16);
    max-width: 100%;
  }
}
@media (min-width: 540px) {
  @supports not (width: min(1px, 1px)) {
    .stage { max-width: 540px; }
  }
}

/* ② aspect-ratio 是 Chrome 88+。图鉴未解锁格子会从 3:4 塌成内容高度。
   等价高度 = 格子内容宽 × 4/3，格子内容宽 = (书页宽 - 106px) / 2。
   那 106px 是「书页内 → 格子内容」的全部横向留白，逐项是：
     书页左右内边距        22 × 2 = 44
     图鉴滚动容器内边距     4 × 2 =  8
     网格内边距             2 × 2 =  4
     列间距                     = 14
     两列格子的内边距+边框 18 × 2 = 36
   实测校准（无头 Chrome，视口 500 宽）：face 宽 197，(500-106)/2 = 197 ✓
     高度 197 × 4/3 = 262.67，aspect-ratio 版本实测 262.66（取整差 0.01）✓
   老内核连 min() 都没有，所以不能照抄 min(100vw, calc(100vh*9/16), 540px)，
   改成按「谁在限宽」分三档，档位边界与 .stage 的兜底取值一一对应：
     ① 视口比 9:16 更窄 → 宽度受限，书页宽 = 100vw
     ② 否则且视口高 < 960px → 高度受限，书页宽 = 100vh × 9/16
     ③ 视口高 ≥ 960px 且宽 ≥ 540px → 撞到 540px 上限
   （③ 必须宽高同时判：只判高的话，窄而高的屏会被误判成撞上限） */
@supports not (aspect-ratio: 3 / 4) {
  .gallery-locked-face {
    min-height: calc((100vh * 9 / 16 - 106px) * 2 / 3);
  }
}
@media (max-aspect-ratio: 9 / 16) {
  @supports not (aspect-ratio: 3 / 4) {
    .gallery-locked-face {
      min-height: calc((100vw - 106px) * 2 / 3);
    }
  }
}
@media (min-height: 960px) and (min-width: 540px) {
  @supports not (aspect-ratio: 3 / 4) {
    .gallery-locked-face {
      min-height: calc((540px - 106px) * 2 / 3);
    }
  }
}
/* 注：.gallery-item img 上那条 aspect-ratio: 9 / 16 不需要兜底 ——
   结局图统一 1080×1920，丢了之后按固有比例渲染，高度与 9:16 完全一致。 */

/* ③ clamp() 是 Chrome 79+。原始代码虽然给了固定值兜底，但 clamp(min, vw, max)
   的取值随视口宽度变化，写死像素只在某一个宽度下才刚好相等（18px 只在 ≤428px
   时对，500px 宽时 clamp 给的是 21px）。所以这里做**精确重建**：
     base 用 vw，再在 min/vw 与 max/vw 两个换挡点之外夹住。
   换挡点是算出来的（下界 ÷ vw系数、上界 ÷ vw系数），不是估的，
   因此任何视口宽度都对得上。 */
@supports not (width: clamp(1px, 1px, 1px)) {
    .slip-button           { font-size: 4.2vw; }
    .topbar-button         { font-size: 3.6vw; }
    .dialogue-box          { font-size: 4.2vw; }
    .speaker-tag           { font-size: 4.2vw; }
    .choice-button         { font-size: 4.2vw; }
    .fortune-sign__title   { font-size: 3.8vw; }
    .ending-title-plaque   { font-size: 5vw; }
    .menu-title p          { font-size: 4vw; }
    .menu-title h1         { font-size: 13vw; }
}
@media (max-width: 369px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .menu-title h1         { font-size: 48px; }
  }
}
@media (max-width: 416px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .topbar-button         { font-size: 15px; }
  }
}
@media (max-width: 421px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .fortune-sign__title   { font-size: 16px; }
  }
}
@media (max-width: 428px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .slip-button           { font-size: 18px; }
    .dialogue-box          { font-size: 18px; }
    .speaker-tag           { font-size: 18px; }
    .choice-button         { font-size: 18px; }
  }
}
@media (max-width: 440px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .ending-title-plaque   { font-size: 22px; }
  }
}
@media (max-width: 449px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .menu-title p          { font-size: 18px; }
  }
}
@media (min-width: 500px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .topbar-button         { font-size: 18px; }
  }
}
@media (min-width: 524px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .slip-button           { font-size: 22px; }
    .dialogue-box          { font-size: 22px; }
    .speaker-tag           { font-size: 22px; }
    .choice-button         { font-size: 22px; }
  }
}
@media (min-width: 527px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .fortune-sign__title   { font-size: 20px; }
  }
}
@media (min-width: 575px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .menu-title p          { font-size: 23px; }
  }
}
@media (min-width: 585px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .menu-title h1         { font-size: 76px; }
  }
}
@media (min-width: 600px) {
  @supports not (width: clamp(1px, 1px, 1px)) {
    .ending-title-plaque   { font-size: 30px; }
  }
}

/* ④ display: grid 是 Chrome 57+。低于此值整个网格布局不存在，
   图鉴会从「两列等宽」塌成「按内容宽度硬挤一行」（实测挤成 4 列、格子缩水）。
   用 inline-block 还原两列：列宽 50% - 7px，奇数项右侧留 14px，
   两列合计 (50%-7) + 14 + (50%-7) = 100%，列间距与 grid 完全一致。
   行间距用 margin-bottom 还原 grid 的 row-gap: 14px。
   单一列的成就网格同理，退化成 block + 相邻兄弟外边距。
   （.gallery-grid 的子元素全部由 JS 逐个 append，元素之间没有空白文本节点，
     所以 inline-block 不会额外吃掉空白字符的宽度；这点已核对 app.js。） */
@supports not (display: grid) {
  .gallery-grid { display: block; }
  .gallery-item {
    display: inline-block;
    width: calc(50% - 7px);
    vertical-align: top;
    margin-bottom: 14px;
  }
  .gallery-item:nth-child(2n+1) { margin-right: 14px; }

  .achievement-grid { display: block; }
  .achievement-card + .achievement-card { margin-top: 10px; }
}
