* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  /* 字体按语言切：中文字体里的越南语声调、日文汉字、泰文都会被套成中文字形，很丑 */
  --ui-font: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", sans-serif;
  /* 主色是银不是橙：这故事的道具就是胶带、麻绳和金属，暖橙太「游戏 UI」了。
   * 整套界面压成黑＋银的单色，插画里的暖色自己就跳出来了。
   * --accent-rgb 供 rgba() 调透明度用；想换主题色只改这三行。 */
  --accent: #c6cfdc;         /* 亮银：强调文字、光圈、描边 */
  --accent-dark: #7a8492;    /* 暗银 */
  --accent-lit: #e9eef6;     /* 高光银 */
  --accent-rgb: 198, 207, 220;
  /* 撕口：毛口只在左右两个短边，上下是刀切的直边——胶带是横着从卷上撕的。
   * 齿距刻意不规则，规则的锯齿一眼假。银胶带和黑胶带共用这一条。 */
  --tape-tear: polygon(
    0 0, 100% 0,
    calc(100% - 2px) 9%,  100% 19%, calc(100% - 3px) 27%, calc(100% - 1px) 38%,
    100% 47%, calc(100% - 3px) 56%, calc(100% - 1px) 66%, 100% 77%,
    calc(100% - 2px) 86%, calc(100% - 1px) 94%, 100% 100%,
    0 100%,
    2px 93%, 0 84%, 3px 76%, 1px 66%, 0 56%, 3px 47%, 1px 37%, 0 27%, 2px 17%, 1px 8%
  );
  /* 黑胶带（哑光布基黑）：反光带又宽又钝，和银色那条的硬高光正好是一对。 */
  --tape-black: linear-gradient(180deg,
    #474c5a 0%,    /* 上缘受光的那一道，胶带的轮廓全靠它 */
    #282c36 14%,
    #363b48 28%,   /* 哑光布基的反光带：又宽又钝 */
    #20242d 46%,
    #161920 70%,
    #2d3240 88%,
    #12151b 100%);
  /* ⚠ clip-path 会连 box-shadow 一起裁掉，撕口胶带的投影必须走 drop-shadow */
  --tape-cast: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8)) drop-shadow(0 6px 14px rgba(0, 0, 0, 0.5));
  --danger: #ff5a5a;         /* 结局的红绿是语义色，单色底上反而更打眼，保留 */
  --safe: #55d68a;
  --ink: #f2f4f8;
  --panel: rgba(11, 12, 16, 0.88);
}

html, body {
  height: 100%;
  background: #0d0e12;
  font-family: var(--ui-font);
  color: var(--ink);
  overflow: hidden;
}

/* 按 <html lang> 换字体栈（Lang.set 会写这个属性） */
html[lang="vi"] { --ui-font: "Barlow", "Be Vietnam Pro", "Segoe UI", Roboto, sans-serif; }
html[lang="ja"] { --ui-font: "Hiragino Kaku Gothic ProN", "Yu Gothic", "Noto Sans JP", "Meiryo", sans-serif; }
html[lang="ko"] { --ui-font: "Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", sans-serif; }
html[lang="th"] { --ui-font: "Thonburi", "Leelawadee UI", "Noto Sans Thai", sans-serif; }
html[lang="zh-TW"] { --ui-font: "PingFang TC", "Hiragino Sans CNS", "Microsoft JhengHei", "Noto Sans TC", sans-serif; }
html[lang="en"] { --ui-font: "Barlow", "Segoe UI", Roboto, "Helvetica Neue", sans-serif; }

body {
  display: flex;
  align-items: center;
  justify-content: center;
}

#game {
  /* 立绘参照高度：横屏就是画框本身，竖屏是上面那条 16:9 的画面带 */
  --por-h: 100cqh;
  container-type: size;
  position: relative;
  width: min(100vw, calc(100vh * 16 / 9), 1200px);
  width: min(100vw, calc(100dvh * 16 / 9), 1200px);
  height: min(100vh, calc(100vw * 9 / 16), 675px);
  height: min(100dvh, calc(100vw * 9 / 16), 675px);
  aspect-ratio: 16 / 9;
  background: #1a1c28;
  border-radius: 0;
  overflow: hidden;
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.55);
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
}

.screen {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.hidden { display: none !important; }

/* 冷光很慢地飘。静止的渐变看久了是「一张背景图」，
 * 让它以半分钟为周期挪一点，画面才像在呼吸。
 * 幅度刻意做得很小——察觉不到在动，但盯着会不安。 */
@keyframes coldDrift {
  from { background-position: 10% 4%,  56% 10%, 98% 30%, 96% 98%,  30% 104%, 0 0; }
  to   { background-position: 24% 0%,  42% 20%, 88% 46%, 78% 104%, 46% 96%,  0 0; }
}

@media (prefers-reduced-motion: reduce) {
  #title-screen, #boot-screen, #title-logo::before { animation: none; }
  #logo-img { animation: none; filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.7)); }
}

/* ---------- 标题画面 ---------- */

#title-screen {
  /* 三盏冷光从画面外打进来：左上冰蓝、中上偏紫、右下品红。
   * 都是大范围的柔光，不是色块——「危险」要靠光营造，
   * 一旦变成实心色块就成了配色方案，气氛全没了。 */
  background:
    radial-gradient(ellipse 52% 42% at 8% -4%,   rgba(64, 132, 255, 0.42), transparent 62%),
    radial-gradient(ellipse 44% 38% at 58% 6%,   rgba(150, 72, 255, 0.30), transparent 60%),
    radial-gradient(ellipse 46% 34% at 100% 30%, rgba(120, 60, 255, 0.20), transparent 58%),
    radial-gradient(ellipse 62% 44% at 100% 104%, rgba(255, 40, 110, 0.26), transparent 58%),
    radial-gradient(ellipse 44% 30% at 28% 110%, rgba(40, 90, 235, 0.22), transparent 58%),
    /* 底子压到接近纯黑：光池亮不亮，取决于旁边有多黑 */
    linear-gradient(168deg, #0a0b10 0%, #050609 70%);
  background-size: 150% 150%, 150% 150%, 150% 150%, 150% 150%, 150% 150%, 100% 100%;
  background-position: 10% 4%, 56% 10%, 98% 30%, 96% 98%, 30% 104%, 0 0;
  animation: coldDrift 34s ease-in-out infinite alternate;
  display: flex;
  flex-direction: column;
}

/* 文字和照片左右排：照片能拿到整屏高度，尽量大 */
.title-inner {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 3%;
  text-align: center;
  padding: 3cqh 4% 7cqh;
}

.title-text {
  /* 放宽一点，LOGO 才长得开；上限由下面 #logo-img 卡在「不超过照片」 */
  flex: 0 1 clamp(260px, 42%, 520px);
  min-width: 0;
}

.title-tag {
  color: var(--accent);
  letter-spacing: 0.4em;
  font-size: clamp(13px, 2.4cqh, 20px);   /* ⚠ 这里原本重复写了两条 font-size，后一条把前一条盖掉了 */
  margin-bottom: 0.2cqh;                  /* 贴着 LOGO 一点 */
}

#title-screen h1 {
  font-size: clamp(30px, 8cqh, 66px);
  letter-spacing: 0.18em;
  text-shadow: 0 4px 24px rgba(var(--accent-rgb), 0.35);
}

.subtitle {
  color: #c9c4b8;
  font-size: clamp(15px, 3cqh, 25px);
  margin: 0.2cqh 0 0.4cqh;   /* 下面还跟着署名，间距交给它 */
}

/* 署名：压得很轻，是个落款，不该跟副标题抢注意力 */
.byline {
  color: #85808f;
  font-size: clamp(10px, 1.6cqh, 13px);
  letter-spacing: 0.14em;
  margin-bottom: 1.7cqh;
}

/* ---- 文案长的语言（拉丁/泰文）：字距松一档就散架，收紧 ---- */
.lang-wide .title-tag {
  letter-spacing: 0.18em;
  text-indent: 0.18em;     /* 补掉最后一个字后面那段字距，居中才是真的居中；
                              别用负 margin——那会把盒子撑得比容器还宽 */
}
.lang-wide .byline { letter-spacing: 0.05em; }

/* 同一个毛病遍布全站：0.2em 以上的字距是给中文标题调的，
 * 拉丁字母套上去就变成一个个孤立的字母，读起来费劲也不好看。
 * 凡是会被翻译到的标签，统一收到拉丁排版正常的档位。 */
.lang-wide .btn-main,
.lang-wide .btn-danger,
.lang-wide .btn-sub          { letter-spacing: 0.03em; }
.lang-wide #boot-title       { letter-spacing: 0.13em; text-indent: 0.13em; }
.lang-wide #atlas-toggle .lbl { letter-spacing: 0.12em; text-indent: 0.12em; }
.lang-wide #atlas-label      { letter-spacing: 0.1em; }
.lang-wide .agree-kicker,
.lang-wide .achv-kicker      { letter-spacing: 0.16em; }
.lang-wide .rt-act           { letter-spacing: 0.1em; }
.lang-wide #ending-kind      { letter-spacing: 0.34em; text-indent: 0.34em; }

.title-buttons { display: flex; gap: 10px; justify-content: center; align-items: center; flex-wrap: wrap; }

.btn-main, .btn-sub, .btn-danger, #choices button, .ending-buttons button, #qte-btn {
  font-family: inherit;
  cursor: pointer;
  border: none;
  border-radius: 0;
  transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
}

.btn-main {
  /* 亮面银胶带（铝箔那种），不是布基。两者的区别全在高光：
   *   布基＝网纹＋颗粒，光是散的；
   *   亮面＝一条又窄又硬、接近纯白的高光带，两侧立刻掉进暗部。
   * 所以这里不再叠网格和噪点，改成金属的明暗带 + 几道折痕。
   *
   * 顺带解决「没有橙色显眼」：橙色赢在色相对比（暖 vs 冷黑底），
   * 银色只能拼明度——把高光推到接近纯白，它就是全屏最亮的东西。 */
  position: relative;
  background-image:
    /* 金属明暗带。亮面质感全在这一层的反差上：
     * 高光是两段纯白连在一起（硬边），紧挨着就掉到 #767f8e 的暗部——
     * 反差越大越像抛光金属，过渡越柔越像塑料。
     * 高光压在 30~37% 高度，避开文字中线。 */
    linear-gradient(180deg,
      #ffffff 0%,
      #dfe6ee 7%,
      #858ea0 20%,
      #ffffff 29%,
      #ffffff 37%,
      #99a3b1 47%,
      #67707f 63%,
      #e6ecf3 81%,
      #646d7b 100%);
  color: #0b0d11;
  /* ⚠ 原来这里垫了一道 rgba(255,255,255,.5) 的白，想做「印在金属上」的效果，
   * 但手机上字号只有 13~18px，700 字重的笔画配 1px 白边会被糊掉一圈，
   * 看着就是「对比度不够」。
   *
   * ⚠ 也别反过来加黑色描边：字本来就是近黑的，再套一圈黑只会让笔画糊成一团，
   *   反而更看不清。只留一道极淡的白垫在下方，保住「印在金属上」的感觉就够了。 */
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.22);
  font-size: clamp(13px, 2.1cqh, 18px);
  font-weight: 700;
  padding: 1.45cqh 3.2cqh;
  clip-path: var(--tape-tear);
  /* 投影和冷光晕都走 drop-shadow —— box-shadow 会被上面的 clip-path 裁没 */
  filter: var(--tape-cast) drop-shadow(0 0 10px rgba(206, 219, 240, 0.3));
}

/* 每隔几秒扫过一道反光。金属和塑料最直接的区别就是「光会动」，
 * 静态渐变再亮也只是一块浅灰。停顿远长于扫动，才不会变成会闪的广告。 */
.btn-main::before {
  content: '';
  position: absolute;
  inset: -30% -45%;
  /* 银白的一道。两侧掺极少量冷灰蓝，是金属反射环境冷光的样子，
   * 不是彩色——胶带本身必须是银的。 */
  background: linear-gradient(100deg,
    transparent 34%,
    rgba(198, 214, 236, 0.30) 42%,
    rgba(240, 246, 255, 0.86) 47%,
    rgba(255, 255, 255, 0.97) 50%,
    rgba(236, 242, 250, 0.80) 53%,
    rgba(190, 205, 226, 0.26) 58%,
    transparent 66%);
  transform: translateX(-58%);
  animation: tapeSheen 5.2s ease-in-out infinite;
  pointer-events: none;
  /* 压到文字下面：.btn-main 有 clip-path，本身就是层叠上下文，
   * 所以 -1 只会盖住自己的背景，不会漏到父元素后面去。
   * 不这么做的话那道 62% 的白扫过时会把字冲淡。 */
  z-index: -1;
}

@keyframes tapeSheen {
  0%, 66%  { transform: translateX(-58%); }
  100%     { transform: translateX(58%); }
}

/* 关掉动画偏好时不扫光；静态那版本身也够亮 */
@media (prefers-reduced-motion: reduce) {
  .btn-main::before { animation: none; opacity: 0; }
}

.btn-main:hover {
  transform: translateY(-2px);
  filter: var(--tape-cast) drop-shadow(0 0 16px rgba(214, 228, 250, 0.5)) brightness(1.06);
}

.btn-sub {
  background: rgba(255, 255, 255, 0.1);
  color: var(--ink);
  border: 1px solid rgba(255, 255, 255, 0.25);
  font-size: clamp(12px, 1.9cqh, 16px);
  padding: 1.2cqh 2.6cqh;
}

.btn-sub:hover { background: rgba(255, 255, 255, 0.2); }

/* 红底：给「重新做选择」这种「回去改命」的动作 */
.btn-danger {
  background: var(--danger);
  color: #2a0808;
  font-size: clamp(14px, 2.4cqh, 19px);
  font-weight: 700;
  padding: 1.4cqh 3.6cqh;
}

.btn-danger:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(255, 90, 90, 0.45); }

#ending-index { margin: 0 auto 2cqh; max-width: 640px; }

.index-title { font-size: clamp(12px, 1.9cqh, 15px); color: #9d97a8; margin-bottom: 1cqh; }

#index-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  max-height: 24cqh;
  overflow-y: auto;
  padding-right: 4px;
}

.index-slot {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 0;
  padding: 1cqh 6px;
  font-size: clamp(11px, 1.7cqh, 14px);
  color: #6f6a7c;
}

.index-slot.unlocked { color: var(--ink); border-color: rgba(var(--accent-rgb), 0.5); }
.index-slot.unlocked.good { border-color: rgba(85, 214, 138, 0.6); }

.hint { color: #6f6a7c; font-size: clamp(10px, 1.6cqh, 13px); }

/* ---------- 探索模式 ---------- */

#explore-screen {
  background: #10121a;
  display: flex;
  align-items: center;
  justify-content: center;
}

#map-canvas {
  width: 100%;
  height: auto;
  max-height: 100%;
  image-rendering: pixelated;
  display: block;
}

#hud {
  position: absolute;
  top: 2%;
  left: 1.5%;
  display: flex;
  gap: 8px;
  pointer-events: none;
}

.hud-chip {
  background: var(--panel);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 0;
  padding: 0.9cqh 1.8cqh;
  font-size: clamp(11px, 1.9cqh, 15px);
}

#interact-tip {
  position: absolute;
  transform: translate(-50%, -100%);
  background: var(--accent);
  color: #16181d;
  font-weight: 700;
  font-size: clamp(11px, 1.9cqh, 14px);
  padding: 0.8cqh 1.6cqh;
  border-radius: 0;
  cursor: pointer;
  white-space: nowrap;
  animation: bounce 0.9s ease-in-out infinite;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
}

@keyframes bounce {
  0%, 100% { margin-top: 0; }
  50% { margin-top: -6px; }
}

#touch-controls { display: none; }

@media (pointer: coarse) {
  #touch-controls { display: block; }
}

#dpad {
  position: absolute;
  left: 3%;
  bottom: 4%;
  width: 132px;
  height: 132px;
}

#dpad button, #btn-action {
  position: absolute;
  width: 44px;
  height: 44px;
  border-radius: 0;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(20, 18, 30, 0.65);
  color: var(--ink);
  font-size: 16px;
}

#dpad button[data-dir="up"] { left: 44px; top: 0; }
#dpad button[data-dir="left"] { left: 0; top: 44px; }
#dpad button[data-dir="right"] { left: 88px; top: 44px; }
#dpad button[data-dir="down"] { left: 44px; top: 88px; }

#btn-action {
  right: 4%;
  bottom: 7%;
  width: 64px;
  height: 64px;
  font-size: 14px;
  background: rgba(var(--accent-rgb), 0.8);
  color: #16181d;
  font-weight: 700;
}

/* ---------- 剧情模式 ---------- */

#story-screen { background: #000; }

/* 背景图还没画出来的场景：不摆占位图，直接退回暗色舞台，
 * 立绘和对白照常演。等成品背景丢进 assets/img/ 就自动盖住这层。 */
#story-media {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  overflow: hidden;
  background:
    radial-gradient(ellipse 90% 70% at 50% 18%, #2b2f42 0%, transparent 70%),
    linear-gradient(180deg, #171a26 0%, #0d0f16 100%);
}

#story-media.tint-night {
  background:
    radial-gradient(ellipse 90% 70% at 50% 18%, #1c2338 0%, transparent 70%),
    linear-gradient(180deg, #0f1320 0%, #07090f 100%);
}

#story-media.tint-danger {
  background:
    radial-gradient(ellipse 90% 70% at 50% 18%, #2e1d22 0%, transparent 70%),
    linear-gradient(180deg, #1a1116 0%, #0b0709 100%);
}

#story-bg, #story-video {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 调色改由氛围系统统一组合，见文件末尾「场景氛围」 */

#video-note {
  position: absolute;
  left: 50%;
  top: 38%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.65);
  border: 1px dashed rgba(255, 255, 255, 0.45);
  border-radius: 0;
  padding: 2cqh 3cqh;
  font-size: clamp(12px, 2cqh, 16px);
  color: #d8d3c8;
  text-align: center;
  line-height: 1.7;
  max-width: 70%;
}

/* 往下压一截：立绘底部是齐腰截断的，沉到画框外面就不会露出切口。
 * 每侧两层图交替使用，换人时一个缩小淡出、另一个放大淡入，中间不会空一帧。 */
.portrait-slot {
  position: absolute;
  bottom: -8%;
  height: 104%;
  width: auto;
  /* 跟着场景的光走，并且比背景再亮一点点。
   * ⚠ 背景吃了 mood 的 --b 提亮，立绘要是不跟，#grade 再从上面压一层，
   *   人就永远比景暗一截——白天场景里看着就是「两个人都黑」。 */
  filter: brightness(calc(var(--b, 1) * 1.08)) drop-shadow(0 calc(var(--por-h) * 0.009) calc(var(--por-h) * 0.026) rgba(0, 0, 0, 0.5));
  opacity: 1;
  /* 只用透明度过渡：不缩放、不位移，出场/退场/换人/换表情一律淡入淡出。
   * 注意别用 var(--x) 写 opacity——没注册的自定义属性不会走 transition，会直接跳变。 */
  transition: filter 0.3s ease, opacity 0.32s ease;
}

#portrait-right, #portrait-right-b { right: 2%; }
#portrait-left, #portrait-left-b { left: 2%; }

/* 未说话的一侧压暗缩小，说话的一侧保持明亮（立绘永远在对话框下层） */
/* 没说话的那一侧压暗——但别压死：立绘上面还叠着氛围调色和 #grade 的暗角，
 * 三层一起压下去人就只剩剪影了，手机上画面窄、暗角更靠内，尤其明显 */
/* 没说话的那一侧：在场景光的基础上压一档，说话的人才亮得出来 */
.portrait-slot.dim {
  filter: brightness(calc(var(--b, 1) * 0.6)) saturate(0.7) drop-shadow(0 calc(var(--por-h) * 0.009) calc(var(--por-h) * 0.026) rgba(0, 0, 0, 0.5));
}

/* 旁白 / 整幅插画时立绘退场 */
.portrait-slot.off { opacity: 0; pointer-events: none; }

/* 换人 / 换表情：旧的一层淡出，新的一层同时淡入 */
.portrait-slot.swap-out { opacity: 0; }

/* 插画模式：整幅图完整显示（不裁切），四周留黑，缓慢推近；插画本身不套滤镜 */
#story-media.cg-mode { background: #000; }



#story-media.cg-mode #story-bg {
  object-fit: contain;
  animation: cgIn 0.6s ease, cgBreathe 7.5s ease-in-out 0.6s infinite;
}

@keyframes cgIn { from { opacity: 0; } to { opacity: 1; } }

/* 一大一小地起伏，像跟着呼吸 */
@keyframes cgBreathe {
  0%, 100% { transform: scale(1.015); }
  50% { transform: scale(1.075); }
}

/* 第一人称视野：四周收黑，只剩中间看得清，像隔着眼罩缝往外看 */
#story-media.cg-mode::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 58% 74% at 50% 47%,
      transparent 26%, rgba(3, 2, 6, 0.5) 66%, rgba(3, 2, 6, 0.96) 100%),
    radial-gradient(ellipse 92% 40% at 50% 50%, transparent 55%, rgba(3, 2, 6, 0.5) 100%);
  animation: povBreathe 7.5s ease-in-out infinite;
}

@keyframes povBreathe {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.86; transform: scale(1.04); }
}

@media (prefers-reduced-motion: reduce) {
  #story-media.cg-mode #story-bg { animation: cgIn 0.6s ease; }
  #story-media.cg-mode::after { animation: none; }
}

@keyframes portraitIn {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: none; }
}

#dialogue-box {
  position: absolute;
  z-index: 2;
  left: 4%;
  right: 4%;
  bottom: 4%;
  min-height: 24%;
  /* 一行最多约 40 个汉字：字号写在框上，max-width 用 em 就直接等于「几个全角字」。
   * 拉丁字母约 0.5em 宽，同一个 42em 正好是 80 字符左右的经典易读宽度。
   * 竖屏时屏幕本来就窄于这个值，这条自动失效。 */
  font-size: clamp(14px, 2.6cqh, 20px);
  max-width: 42em;
  margin-inline: auto;
  background: var(--panel);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 0;
  padding: 2.6cqh 3cqh 2.2cqh;
  cursor: pointer;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

#speaker-tag {
  position: absolute;
  top: 0;
  left: 3%;
  transform: translateY(-55%);
  background: var(--accent);
  color: #16181d;
  font-weight: 700;
  font-size: clamp(12px, 2cqh, 16px);
  padding: 0.7cqh 2.2cqh;
  border-radius: 0;
}

#dialogue-text {
  font-size: 1em;          /* 跟着对话框走，em 才等于「一个全角字」 */
  line-height: 1.8;
  min-height: 2em;
}

#dialogue-text.narration {
  color: #cfc9bc;
  font-style: italic;
  text-align: center;
}

@keyframes textShake {
  0%, 100% { transform: none; }
  25% { transform: translate(1.6px, -1.2px); }
  50% { transform: translate(-1.6px, 1px); }
  75% { transform: translate(1px, 1.4px); }
}

#dialogue-text.anim-shake { animation: textShake 0.26s infinite; }

@keyframes textTremble {
  0%, 100% { transform: none; }
  50% { transform: translateY(0.8px); }
}

#dialogue-text.anim-tremble { animation: textTremble 0.5s infinite; }

#continue-indicator {
  position: absolute;
  right: 2.5%;
  bottom: 1.4cqh;
  color: var(--accent);
  font-size: clamp(12px, 2cqh, 15px);
  animation: blink 1s infinite;
}

@keyframes blink { 50% { opacity: 0.15; } }

/* 选项：贴着对话框上沿往上堆；画框矮的时候（手机竖屏只有一条 16:9 窄带）
 * 自己变成可滚动，绝不顶出画面 */
#choices {
  position: absolute;
  z-index: 3;
  left: 50%;
  bottom: 30%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 1.4cqh;
  width: min(72%, 620px);
  max-height: 66cqh;
  /* hover 时按钮会右移几像素，容器留一点内边距，否则 overflow-x:hidden 会把右边框切掉 */
  padding: 2px 8px;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

#choices::-webkit-scrollbar { width: 3px; }
#choices::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); border-radius: 0; }

/* 选项跟主按钮同一套光：冷色分光。
 * 但不能做成第二条胶带——选项是要读的正文，底必须够暗。
 * 所以颜色只走两处：极淡的底色washi + 顶边那道虹彩线，
 * 悬停时才亮起来并扫过一道光。 */
#choices button {
  position: relative;
  /* 选项＝一条条贴上去的黑胶带。上面那层极淡的蓝紫红不是「涂色」，
   * 是背景那几盏冷光打在胶带上的反光——所以透明度压得很低。 */
  background:
    linear-gradient(100deg,
      rgba(64, 132, 255, 0.10) 0%,
      rgba(140, 92, 255, 0.06) 46%,
      rgba(255, 72, 128, 0.09) 100%),
    var(--tape-black);
  border: none;
  clip-path: var(--tape-tear);
  filter: var(--tape-cast);
  color: var(--ink);
  font-size: clamp(11px, 2.3cqh, 18px);
  padding: 1.5cqh 2.2cqh;
  border-radius: 0;
  flex: none;
  text-align: left;
  line-height: 1.5;
}

/* 顶边一道分光细线：平时压得很淡，只是让这一行「带电」 */
#choices button::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: linear-gradient(90deg,
    rgba(60, 150, 255, 0.75) 0%,
    rgba(150, 90, 255, 0.6) 46%,
    rgba(255, 70, 120, 0.7) 100%);
  opacity: 0.5;
  transition: opacity 0.18s ease;
  pointer-events: none;
}

/* 悬停时扫过去一道冷光。被 overflow:hidden 裁在按钮里，不会溢出去 */
#choices button::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg,
    transparent 38%,
    rgba(150, 190, 255, 0.18) 47%,
    rgba(255, 255, 255, 0.22) 50%,
    rgba(255, 140, 190, 0.16) 54%,
    transparent 62%);
  transform: translateX(-115%);
  pointer-events: none;
}

#choices button:hover {
  background:
    linear-gradient(100deg,
      rgba(64, 132, 255, 0.22) 0%,
      rgba(140, 92, 255, 0.15) 46%,
      rgba(255, 72, 128, 0.20) 100%),
    var(--tape-black);
  transform: translateX(6px);
  filter: var(--tape-cast) drop-shadow(0 0 14px rgba(120, 135, 255, 0.4)) brightness(1.32);
}
#choices button:hover::before { opacity: 1; }
#choices button:hover::after { transform: translateX(115%); transition: transform 0.62s ease; }

#choices button .choice-key { color: #a9bdf0; font-weight: 700; margin-right: 0.8em; }

/* A/B 那个字母直接用分光渐变填。不支持 background-clip:text 的浏览器
 * 走上面那条纯色，不会变成透明看不见 */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  #choices button .choice-key {
    background: linear-gradient(150deg, #7fb4ff 0%, #b58cff 48%, #ff6f9c 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/* ---------- 场景衔接：下一站的画面直接铺开，上面浮一个可点的动作热区 ---------- */

#transit-card {
  position: absolute;
  z-index: 4;
  inset: 0;
  animation: transitIn 0.5s ease;
  /* 上下压暗一点，让时间条和氛围句读得清，中间保持通透 */
  background:
    linear-gradient(180deg, rgba(6, 5, 10, 0.72) 0%, rgba(6, 5, 10, 0) 26%),
    linear-gradient(0deg, rgba(6, 5, 10, 0.78) 0%, rgba(6, 5, 10, 0) 34%);
}

@keyframes transitIn { from { opacity: 0; } to { opacity: 1; } }

/* 时间 + 地点：像手机状态栏那样贴在左上角，不报幕 */
/* 位置一律用容器百分比：#game 是定死的 16:9 letterbox，vh 在手机竖屏会跑到框外 */
#transit-chip {
  position: absolute;
  top: 5%;
  left: 5%;
  display: flex;
  align-items: baseline;
  gap: 1.2em;
  font-size: clamp(11px, 1.15vw, 16px);
}

#transit-time { color: var(--accent); letter-spacing: 0.22em; font-variant-numeric: tabular-nums; }

#transit-place { color: #cfc9bc; letter-spacing: 0.08em; }
#transit-place::before { content: '📍 '; opacity: 0.75; }

/* 动作热区：坐标由 storyData 的 transit.at 给（默认画面中央偏下） */
#transit-go {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 0.9em;
  min-height: 48px;
  padding: 0.9em 1.6em 0.9em 1.2em;
  max-width: min(84%, 460px);
  background: rgba(12, 10, 18, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 0;
  color: #f2ede2;
  font-family: inherit;
  font-size: clamp(13px, 1.4vw, 20px);
  line-height: 1.35;
  text-align: left;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: transform 0.16s ease, background 0.16s ease, border-color 0.16s ease;
}

#transit-go:hover { background: rgba(20, 16, 28, 0.78); border-color: rgba(var(--accent-rgb), 0.55); }
#transit-go.tapped { transform: translate(-50%, -50%) scale(0.94); background: rgba(var(--accent-rgb), 0.28); }

/* 呼吸的光点，告诉玩家「点这里」 */
.hot-dot,
.hot-ring {
  position: absolute;
  left: 1.55em;
  width: 12px;
  height: 12px;
  border-radius: 0;
}

.hot-dot { background: var(--accent); box-shadow: 0 0 12px rgba(var(--accent-rgb), 0.9); }

.hot-ring {
  border: 2px solid var(--accent);
  animation: hotRing 1.8s ease-out infinite;
}

@keyframes hotRing {
  0% { transform: scale(1); opacity: 0.75; }
  100% { transform: scale(3.4); opacity: 0; }
}

#transit-act { margin-left: 1.6em; }

#transit-flavor {
  position: absolute;
  left: 8%;
  right: 8%;
  bottom: 7%;
  text-align: center;
  color: #a49dae;
  font-size: clamp(11px, 1.15vw, 16px);
  line-height: 1.7;
}

/* 窄屏（手机）：画面被压成一条 16:9 的窄带，热区收紧但保持一根手指点得到 */
@media (max-width: 620px) {
  #transit-go {
    min-height: 44px;
    padding: 0.7em 1.1em 0.7em 1em;
    max-width: 82%;
    gap: 0.5em;
    border-radius: 0;
  }
  .hot-dot, .hot-ring { left: 1.15em; width: 9px; height: 9px; }
  #transit-act { margin-left: 1em; }
  #transit-chip { gap: 0.8em; }
}

#toast-layer {
  position: absolute;
  top: 6%;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
  z-index: 5;
}

.toast {
  background: rgba(20, 18, 30, 0.9);
  border: 1px solid var(--accent);
  color: var(--ink);
  border-radius: 0;
  padding: 0.9cqh 2.4cqh;
  font-size: clamp(12px, 2cqh, 16px);
  animation: toastUp 1.8s ease forwards;
}

.toast.bad { border-color: var(--danger); }

@keyframes toastUp {
  0% { opacity: 0; transform: translateY(10px); }
  12% { opacity: 1; transform: none; }
  80% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-14px); }
}

/* ---------- 小挑战 ---------- */

#minigame-screen {
  background: rgba(6, 6, 12, 0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
}

#qte-box {
  width: min(76%, 560px);
  background: var(--panel);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 0;
  padding: 4cqh 4cqh 3.4cqh;
  text-align: center;
}

#qte-title { font-size: clamp(16px, 3cqh, 24px); font-weight: 700; margin-bottom: 2.6cqh; }

#qte-track {
  position: relative;
  height: 26px;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 0;
  overflow: hidden;
  margin-bottom: 2cqh;
}

#qte-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  background: rgba(85, 214, 138, 0.55);
  border-left: 2px solid var(--safe);
  border-right: 2px solid var(--safe);
}

#qte-marker {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 8px;
  margin-left: -4px;
  background: #fff;
  border-radius: 0;
  box-shadow: 0 0 10px rgba(255, 255, 255, 0.9);
}

#qte-progress-wrap {
  height: 26px;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 0;
  overflow: hidden;
  margin-bottom: 2cqh;
}

#qte-progress {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-lit));
  border-radius: 0;
  transition: width 0.08s linear;
}

#qte-status { min-height: 1.6em; font-size: clamp(13px, 2.3cqh, 18px); margin-bottom: 1.6cqh; color: #cfc9bc; }

#qte-btn {
  background: var(--accent);
  color: #16181d;
  font-size: clamp(15px, 2.8cqh, 22px);
  font-weight: 700;
  padding: 1.6cqh 6cqh;
}

#qte-btn:active { transform: scale(0.94); }

#qte-hint { margin-top: 1.8cqh; color: #8d8798; font-size: clamp(11px, 1.8cqh, 14px); }

/* ---------- 结局：插画占满，文字全部退到四周，中间一律不挡 ---------- */

#ending-screen {
  background:
    radial-gradient(ellipse 54% 40% at 50% 20%, rgba(255, 40, 88, 0.26), transparent 60%),
    radial-gradient(ellipse 46% 38% at 2% 100%, rgba(120, 60, 255, 0.22), transparent 58%),
    radial-gradient(ellipse 46% 38% at 100% 92%, rgba(52, 112, 255, 0.18), transparent 58%),
    #05060a;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

#ending-screen.good {
  background:
    radial-gradient(ellipse at 50% 30%, rgba(255, 190, 90, 0.16), transparent 60%),
    #0c0d14;
}

#ending-card { width: min(80%, 640px); }

#ending-cg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  animation: cgIn 0.8s ease, cgDrift 30s ease-out 0.8s forwards;
}

/* 有插画时：上下各一条很浅的压暗，中间完全干净 */
#ending-screen.has-cg { cursor: pointer; }

#ending-screen.has-cg::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(6, 5, 10, 0.72) 0%, rgba(6, 5, 10, 0) 22%),
    linear-gradient(0deg, rgba(6, 5, 10, 0.82) 0%, rgba(6, 5, 10, 0) 30%);
}

/* 结局名沉到左下角，不要框、不要底板 */
#ending-screen.has-cg #ending-card {
  position: absolute;
  z-index: 2;
  left: 4%;
  right: 34%;
  bottom: 5.5%;
  width: auto;
  margin: 0;
  text-align: left;
}

#ending-kind {
  letter-spacing: 0.5em;
  color: var(--danger);
  font-size: clamp(10px, 1.7cqh, 14px);
  margin-bottom: 0.6cqh;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.95);
}

#ending-screen.good #ending-kind { color: var(--safe); }

#ending-title {
  font-size: clamp(22px, 4.6cqh, 40px);
  letter-spacing: 0.08em;
  margin-bottom: 0.9cqh;
  text-shadow: 0 3px 22px rgba(0, 0, 0, 0.98), 0 0 46px rgba(0, 0, 0, 0.8);
}

#ending-tip {
  color: #b3ada1;
  font-size: clamp(10px, 1.7cqh, 14px);
  line-height: 1.7;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.95);
}

#ending-stats {
  color: #857f90;
  font-size: clamp(10px, 1.6cqh, 13px);
  margin-top: 0.4cqh;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.95);
}

.ending-buttons { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ============================================================
 * 演出层：大喊 / 发抖 / 闷声 / 不祥 这几种语气的画面效果
 * 台词一出现就整屏演一遍，比单纯改字号明显得多
 * ============================================================ */

#fx-layer {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s ease;
}

/* —— 大喊：整屏震一下 + 暖色闪光 —— */
#story-screen.fx-quake #story-media { animation: quake 0.5s cubic-bezier(.36,.07,.19,.97); }

#story-screen.fx-quake #fx-layer {
  opacity: 1;
  background: radial-gradient(ellipse at 50% 45%, rgba(255, 150, 80, 0.28), transparent 62%);
  animation: quakeFlash 0.5s ease-out;
}

@keyframes quake {
  0%, 100% { transform: none; }
  12% { transform: translate(-9px, 4px) rotate(-0.5deg) scale(1.012); }
  28% { transform: translate(8px, -5px) rotate(0.45deg) scale(1.012); }
  44% { transform: translate(-6px, -3px) rotate(-0.3deg) scale(1.008); }
  62% { transform: translate(4px, 3px) rotate(0.2deg); }
  80% { transform: translate(-2px, -1px); }
}

@keyframes quakeFlash { from { opacity: 1; } to { opacity: 0; } }

/* —— 发抖/惊恐：持续细颤 + 冷色暗角一下一下收紧 —— */
#story-screen.fx-panic #story-media { animation: panicShake 0.13s linear infinite; }

#story-screen.fx-panic #fx-layer {
  opacity: 1;
  background:
    radial-gradient(ellipse 78% 68% at 50% 48%, transparent 34%, rgba(10, 6, 20, 0.86) 100%),
    radial-gradient(ellipse at 50% 50%, rgba(150, 110, 220, 0.1), transparent 55%);
  animation: panicPulse 1.15s ease-in-out infinite;
}

@keyframes panicShake {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(-1.6px, 1px); }
  50% { transform: translate(1.4px, -1.2px); }
  75% { transform: translate(-1px, -0.6px); }
}

@keyframes panicPulse { 0%, 100% { opacity: 0.72; } 50% { opacity: 1; } }

/* —— 闷声：画面失焦压暗，暗角收到最紧——「看不见也叫不出来」 —— */
#story-screen.fx-muffle #story-media {
  filter: blur(1.9px) brightness(0.71) saturate(0.74);
  transform: scale(1.03);
  animation: panicShake 0.16s linear infinite;
}

#story-screen.fx-muffle #fx-layer {
  opacity: 1;
  background: radial-gradient(ellipse 62% 54% at 50% 48%, transparent 12%, rgba(4, 3, 8, 0.94) 92%);
  animation: mufflePulse 1.6s ease-in-out infinite;
}

@keyframes mufflePulse { 0%, 100% { opacity: 0.88; } 50% { opacity: 1; } }

/* —— 不祥：暗角缓缓合拢，色彩抽干 —— */
#story-screen.fx-omen #story-media { filter: saturate(0.42) brightness(0.78); }

#story-screen.fx-omen #fx-layer {
  opacity: 1;
  background: radial-gradient(ellipse 96% 88% at 50% 46%, transparent 24%, rgba(6, 4, 10, 0.9) 100%);
  animation: omenClose 3.2s ease-out forwards;
}

@keyframes omenClose {
  from { opacity: 0; transform: scale(1.3); }
  to { opacity: 1; transform: scale(1); }
}

/* 台词本身也跟着加强 */
#story-screen.fx-quake #dialogue-text { text-shadow: 0 0 18px rgba(var(--accent-rgb), 0.75); } /*KEEPWARM*/
#story-screen.fx-panic #dialogue-text { text-shadow: 0 0 16px rgba(170, 130, 240, 0.6); }
#story-screen.fx-muffle #dialogue-text { text-shadow: 0 0 12px rgba(0, 0, 0, 0.9); }

#story-screen.fx-quake #dialogue-box,
#story-screen.fx-panic #dialogue-box,
#story-screen.fx-muffle #dialogue-box { border-color: rgba(255, 255, 255, 0.3); }

/* 说话人在演出时高亮更狠一点 */
#story-screen.fx-panic .portrait-slot:not(.dim):not(.off),
#story-screen.fx-quake .portrait-slot:not(.dim):not(.off) {
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.6)) brightness(1.06) contrast(1.06);
}

/* 晕动症友好：关掉位移和抖动，只留颜色和暗角 */
@media (prefers-reduced-motion: reduce) {
  #story-screen.fx-quake #story-media,
  #story-screen.fx-panic #story-media,
  #story-screen.fx-muffle #story-media { animation: none; transform: none; }
  #story-screen.fx-panic #fx-layer,
  #story-screen.fx-muffle #fx-layer { animation: none; }
  #dialogue-text.anim-shake, #dialogue-text.anim-tremble { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .portrait-slot { transition: opacity 0.18s ease; }
}

/* ---------- 结局：插画 → 最后那句旁白 → 结局名 → 角落里的按钮 ---------- */

#ending-echo {
  position: absolute;
  z-index: 2;
  left: 8%;
  right: 8%;
  top: 5.5%;
  text-align: center;
  color: #ded8cc;
  font-style: italic;
  font-size: clamp(13px, 2.4cqh, 19px);
  line-height: 2;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.95);
  animation: echoIn 1.6s ease both;
}

@keyframes echoIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* 旁白还挂着的时候，结局卡先不出现；出现时旁白往上让位 */
#ending-screen #ending-card {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.9s ease, transform 0.9s ease;
  pointer-events: none;
}

#ending-screen.show-card #ending-card { opacity: 1; transform: none; pointer-events: auto; }

#ending-screen.show-card #ending-echo { opacity: 0.9; transition: opacity 1s ease; }

/* 按钮：等旁白读完了，才在右下角慢慢淡出来 */
#ending-screen .ending-buttons {
  position: absolute;
  z-index: 3;
  right: 3.5%;
  bottom: 4.5%;
  justify-content: flex-end;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 1.4s ease, transform 1.4s ease;
  pointer-events: none;
}

#ending-screen.show-btns .ending-buttons { opacity: 1; transform: none; pointer-events: auto; }

#ending-screen .ending-buttons button {
  font-size: clamp(11px, 1.8cqh, 15px);
  padding: 1cqh 2.4cqh;
}


@media (max-width: 620px) {
  #ending-screen .ending-buttons { left: 4%; right: 4%; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  #ending-echo { animation: none; }
  #ending-screen #ending-card,
  #ending-screen .ending-buttons { transition: opacity 0.3s ease; transform: none; }
}

/* ---------- 插画不是 16:9 时的留黑处理 + 结局卡的底板 ---------- */

/* 剧情里的插画：同一张图放大模糊垫底 */
#story-media.cg-mode {
  background-image: var(--cg);
  background-size: cover;
  background-position: center;
}

#story-media.cg-mode::before {
  content: '';
  position: absolute;
  inset: 0;
  -webkit-backdrop-filter: blur(34px) brightness(0.32) saturate(0.8);
  backdrop-filter: blur(34px) brightness(0.32) saturate(0.8);
}

/* 结局画面同理 */
#ending-cg-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: blur(34px) brightness(0.32) saturate(0.8);
  transform: scale(1.12);
}

#ending-screen.has-cg #ending-echo {
  text-shadow: 0 2px 20px #000, 0 0 40px rgba(0, 0, 0, 0.9);
}

/* 窄屏：左下角放不下就改成整行贴底，按钮另起一行 */
@media (max-width: 620px) {
  #ending-screen.has-cg #ending-card { right: 4%; bottom: 13%; }
  #ending-echo { top: 4%; }
}

/* ---------- 结局：插画变成一张被放下来的照片 ---------- */

#ending-photo {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 7cqh 5% 22cqh;
  pointer-events: none;
  z-index: 1;
}

#ending-screen.has-cg #ending-photo { display: flex; }

/* 相框裹住照片本身：尺寸由图片决定，图片再按画框（cqw/cqh）限死。
 * 不能用 % —— 图片的 max-width:100% 指的是相框，相框宽度又由图片决定，
 * 循环引用的结果就是相框被拉满、两边留出一大片白边。 */
#photo-frame {
  position: relative;
  display: none;
  padding: 0.9%;
  border-radius: 0;
  background: #efe9dd;                 /* 相纸白边 */
  box-shadow:
    0 26px 70px rgba(0, 0, 0, 0.78),
    0 2px 10px rgba(0, 0, 0, 0.6),
    0 0 0 1px rgba(0, 0, 0, 0.5);
  animation: photoDrop 1.2s cubic-bezier(0.16, 0.9, 0.3, 1) both;
}

#ending-screen.has-cg #photo-frame { display: inline-flex; }

#ending-screen.has-cg #ending-cg {
  position: static;
  display: block;
  width: auto;
  height: auto;
  max-width: 84cqw;
  max-height: 62cqh;      /* 长到快碰上下面的文字就不再放大 */
  object-fit: contain;
  border-radius: 0;
}

@keyframes photoDrop {
  from { opacity: 0; transform: rotate(-4.5deg) scale(1.07) translateY(-6%); }
  to   { opacity: 1; transform: rotate(-1.3deg) scale(1); }
}

/* 照片模式下背景压得更暗，衬托这张“物证” */
#ending-screen.has-cg #ending-cg-bg { filter: blur(40px) brightness(0.2) saturate(0.7); }

#ending-screen.has-cg::after {
  background:
    linear-gradient(180deg, rgba(6, 5, 10, 0.7) 0%, rgba(6, 5, 10, 0) 14%),
    linear-gradient(0deg, rgba(6, 5, 10, 0.86) 0%, rgba(6, 5, 10, 0) 22%);
}

/* 照片要压在遮罩之上，别被压暗 */
#ending-screen.has-cg #ending-cg { z-index: 1; }
#ending-echo { z-index: 3; }

@media (prefers-reduced-motion: reduce) {
  #photo-frame { animation: none; transform: rotate(-1.3deg); }
}

@media (max-width: 620px) {
}

/* ============================================================
 * 开场：竖屏劝导 + 素材预加载
 * ============================================================ */

#boot-screen {
  position: absolute;
  inset: 0;
  z-index: 50;
  background:
    radial-gradient(ellipse 54% 44% at 6% -4%,   rgba(64, 132, 255, 0.36), transparent 62%),
    radial-gradient(ellipse 46% 38% at 72% 4%,   rgba(150, 72, 255, 0.26), transparent 60%),
    radial-gradient(ellipse 60% 44% at 102% 104%, rgba(255, 40, 110, 0.22), transparent 58%),
    linear-gradient(165deg, #0a0b10 0%, #050609 75%);
  background-size: 150% 150%, 150% 150%, 150% 150%, 100% 100%;
  animation: coldDrift 34s ease-in-out infinite alternate;
  display: flex;
  /* safe center：内容比屏幕高时退化成顶部对齐。
   * 用普通的 center，超出的那部分会被推到容器上方，怎么滑都滑不到——
   * 微信/QQ 内置浏览器顶栏底栏一占，「安全开捆！」那个按钮就是这么消失的。 */
  align-items: safe center;
  justify-content: safe center;
  text-align: center;
  overflow-y: auto;
  /* ⚠ 必须显式写 hidden：只要一轴是 auto，另一轴的 visible 就会被算成 auto，
   * 碎碎念那盏灯的光锥（width:200%）会因此撑出一条横向滚动条。 */
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  /* 给刘海、状态栏、底部 home 条留位置 */
  padding:
    calc(6% + env(safe-area-inset-top, 0px)) calc(8% + env(safe-area-inset-right, 0px))
    calc(7% + env(safe-area-inset-bottom, 0px)) calc(8% + env(safe-area-inset-left, 0px));
  transition: opacity 0.5s ease;
}

#boot-screen.gone { opacity: 0; pointer-events: none; }

#boot-gate .rotate-icon {
  font-size: clamp(38px, 9cqh, 64px);
  display: inline-block;
  animation: rotateHint 2.4s ease-in-out infinite;
  margin-bottom: 2cqh;
}

@keyframes rotateHint {
  0%, 45%, 100% { transform: rotate(0deg); }
  60%, 85% { transform: rotate(-90deg); }
}

#boot-gate h2 {
  font-size: clamp(18px, 3.4cqh, 28px);
  letter-spacing: 0.08em;
  margin-bottom: 1.4cqh;
}

#boot-gate p {
  color: #a49dae;
  font-size: clamp(12px, 2cqh, 16px);
  line-height: 1.9;
  margin-bottom: 3cqh;
}

#boot-allow-wrap {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  color: #cfc9bc;
  font-size: clamp(12px, 2cqh, 15px);
  cursor: pointer;
  margin-bottom: 2.6cqh;
  padding: 1cqh 1.6cqh;
  border-radius: 0;
  background: rgba(255, 255, 255, 0.06);
}

#boot-allow { width: 18px; height: 18px; accent-color: var(--accent); cursor: pointer; }

#boot-go:disabled { opacity: 0.35; cursor: not-allowed; transform: none; box-shadow: none; }

#boot-load { width: min(88%, 460px); }

#boot-title {
  font-size: clamp(28px, 6cqh, 48px);
  letter-spacing: 0.28em;
  margin-bottom: 3.4cqh;
  text-shadow: 0 4px 24px rgba(var(--accent-rgb), 0.35);
}

/* 进度条做成一根麻绳：还没读到的那一段是松塌的暗绳，
 * 读过的一段被绷紧、亮起来，绳头上还打着一个结随进度往前走。
 * 纹理全是 CSS 渐变叠出来的，不用图：
 *   斜向重复渐变 = 三股拧在一起的纤维；上亮下暗 = 圆柱体积；
 *   （周期性的勒紧暗带去掉了——看着像被切成一段一段的。） */
#boot-track {
  /* 绳子改用真素材了（assets/img/rope_strip.webp，tools/make_rope.py 生成）。
   * 之前那一版是纯 CSS 渐变叠出来的，能做到「像绳子」，但做不到「是绳子」。
   *
   * 素材只有 16KB，而且是 CSS 里直接引用的 —— 样式表一解析浏览器就去拿了，
   * 比任何 JS 触发的加载都早，正好满足「加载条必须最先出现」。
   *
   * 这一条是「还没走到」的部分：同一根绳，只是压暗压灰当没照到光。
   * ⚠ 不能用 filter 压暗——#boot-bar 是它的子元素，会一起被压。
   *   所以用一层半透明黑叠在图上。 */
  position: relative;
  height: 15px;
  border-radius: 8px;
  background-image:
    linear-gradient(rgba(5, 6, 9, 0.74), rgba(5, 6, 9, 0.74)),
    url("assets/img/rope_strip.webp");
  background-size: auto 100%, auto 100%;
  background-repeat: repeat-x, repeat-x;
  background-position: center, center;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.7);
  margin-bottom: 1.8cqh;
}

#boot-bar {
  position: relative;
  height: 100%;
  width: 0;
  border-radius: 8px;
  /* 已绷紧的那一段：同一张图，不压暗 */
  background-image: url("assets/img/rope_strip.webp");
  background-size: auto 100%;
  background-repeat: repeat-x;
  background-position: center;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.75))
          drop-shadow(0 0 9px rgba(206, 219, 240, 0.28));
  transition: width 0.3s ease;
}

/* 绳头那个结：也是真素材，跟着进度往前爬 */
#boot-bar::after {
  content: '';
  position: absolute;
  right: -11px;
  top: 50%;
  width: 26px;
  height: 26px;
  margin-top: -13px;
  background: url("assets/img/rope_knot.webp") center / contain no-repeat;
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.8));
}

#boot-line {
  color: #cfc9bc;
  transition: opacity 0.26s ease;
  font-size: clamp(12px, 2cqh, 16px);
  min-height: 1.6em;
  letter-spacing: 0.06em;
}

#boot-pct { color: #6f6a7c; font-size: clamp(10px, 1.7cqh, 13px); margin-top: 0.6cqh; }

/* ============================================================
 * 竖屏自适应：画面填满屏幕，插画和立绘一律等比缩放（宁可小，不变形）
 * ============================================================ */

#portrait-hint { display: none; }

/* ============================================================
 * 竖屏：上半屏是「画面区」——严格 16:9，插画和立绘一律原比例，绝不因竖屏变形；
 *       下半屏是「文字区」——对话框、选项、按钮吃满竖屏剩下的空间，字大、好点。
 * ============================================================ */
@media (max-aspect-ratio: 1/1) {
  /* 画面区 = 一块严格 16:9；文字区 = 固定一段高度；两块作为整体在屏幕上居中。
   * ⚠ 这几个量定义在 :root 而不是 #game 上：#game 照常继承，
   *   但画框**外面**的元素（左上角那两颗 HUD）也要靠 --stack-top 才知道黑边有多高。 */
  :root {
    --art-h: calc(100vw * 9 / 16);
    --text-h: 34vh;
    --text-h: 34dvh;
    --gap: 1.6vh;
    --gap: 1.6dvh;
    --stack-top: calc((100vh - var(--art-h) - var(--gap) - var(--text-h)) / 2);
    --stack-top: calc((100dvh - var(--art-h) - var(--gap) - var(--text-h)) / 2);
  }
  #game {
    --por-h: var(--art-h);        /* 竖屏：立绘只有画面带那么高，阴影得按它算 */
    width: 100vw;
    height: 100vh;
    height: 100dvh;
    max-width: none;
    max-height: none;
    aspect-ratio: auto;
    border-radius: 0;
    box-shadow: none;
  }

  /* —— 画面区：插画和立绘一律原比例铺满它，绝不因竖屏变形 —— */
  #story-media, #fx-layer {
    top: var(--stack-top);
    bottom: auto;
    height: var(--art-h);
  }

  /* —— 文字区：吃满竖屏留出来的空间，字大、按钮好点 —— */
  #dialogue-box {
    top: calc(var(--stack-top) + var(--art-h) + var(--gap));
    bottom: auto;
    height: var(--text-h);
    left: 3.5%;
    right: 3.5%;
    min-height: 0;
    padding: 3.2vh 5%;
    padding: 3.2dvh 5%;
  }

  #dialogue-text { font-size: clamp(15px, 2.3vh, 23px); line-height: 1.95; }
  #speaker-tag { font-size: clamp(12px, 1.9vh, 18px); padding: 0.7vh 3vw; }
  #continue-indicator { font-size: clamp(13px, 2vh, 18px); right: 5%; bottom: 1.6vh; }

  /* 选项：整块占住文字区，按钮撑开到一根拇指点得准 */
  #choices {
    top: calc(var(--stack-top) + var(--art-h) + var(--gap));
    bottom: auto;
    height: var(--text-h);
    left: 3.5%;
    right: 3.5%;
    width: auto;
    transform: none;
    max-height: none;
    justify-content: center;
    gap: 1.3vh;
    gap: 1.3dvh;
    overflow-y: auto;
    overflow-x: hidden;
  }

  #choices button {
    font-size: clamp(14px, 2.05vh, 21px);
    font-size: clamp(14px, 2.05dvh, 21px);
    padding: 1.9vh 5%;
    padding: 1.9dvh 5%;
    border-radius: 0;
  }

  /* 竖屏里选项和对话框占同一块地方：选项一出来，名牌、箭头、正文一起收掉，
   * 只留对话框当底板——不然上一句旁白会从选项缝里透出来 */
  #story-screen.choosing #speaker-tag,
  #story-screen.choosing #continue-indicator,
  #story-screen.choosing #dialogue-text { display: none; }

  /* 转场：地点信息压在画面上，动作热区放到文字区中央 */
  #transit-chip { top: 2vh; font-size: clamp(11px, 1.7vh, 15px); }
  #transit-flavor {
    top: calc(var(--stack-top) + var(--art-h) + var(--gap) + 1.5vh);
    top: calc(var(--stack-top) + var(--art-h) + var(--gap) + 1.5dvh);
    bottom: auto;
    left: 6%;
    right: 6%;
    font-size: clamp(12px, 1.9vh, 17px);
    font-size: clamp(12px, 1.9dvh, 17px);
  }
  #transit-go {
    left: 50% !important;
    top: calc(var(--stack-top) + var(--art-h) + var(--gap) + var(--text-h) - 9vh) !important;
    top: calc(var(--stack-top) + var(--art-h) + var(--gap) + var(--text-h) - 9dvh) !important;
    transform: translateX(-50%);
    width: 86%;
    max-width: 86%;
    min-height: 7vh;
    min-height: 7dvh;
    font-size: clamp(14px, 2.1vh, 20px);
    font-size: clamp(14px, 2.1dvh, 20px);
    justify-content: center;
  }
  #transit-go.tapped { transform: translateX(-50%) scale(0.95); }

  /* 结局：照片原比例摆在上半屏，文字按钮在下面 */
  #ending-photo { padding: 7vh 4% 26vh; align-items: center; }
  #ending-screen.has-cg #ending-cg { max-width: 92cqw; max-height: 46cqh; }
  #ending-echo { top: 2vh; font-size: clamp(12px, 1.9vh, 17px); }
  #ending-screen.has-cg #ending-card { left: 5%; right: 5%; bottom: 12vh; }
  #ending-title { font-size: clamp(20px, 3.4vh, 34px); }
  #ending-screen .ending-buttons { left: 5%; right: 5%; bottom: 3vh; justify-content: center; }
  #ending-screen .ending-buttons button { font-size: clamp(13px, 2vh, 18px); padding: 1.7vh 6vw; }
}

/* ============================================================
 * 主页右侧：这一天的路线（成就式线路图）
 * ============================================================ */

/* 迷途旅程：平时完全不占画面高度，点底部箭头才从下面拉起来 */
#atlas-toggle {
  position: absolute;
  z-index: 29;
  left: 50%;
  bottom: 1.6cqh;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1em;
  padding: 1cqh 2cqh;
  border: none;
  background: none;
  color: #e6dfd2;
  font-family: inherit;
  cursor: pointer;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.9);
  transition: color 0.16s ease, transform 0.16s ease;
  animation: atlasFloat 2.4s ease-in-out infinite;
}

#atlas-toggle .lbl {
  font-size: clamp(13px, 2.4cqh, 21px);
  font-weight: 700;
  letter-spacing: 0.22em;
  text-indent: 0.22em;      /* 字间距造成的偏移补回来，箭头才和文字真正对齐 */
}

#atlas-toggle .arw {
  font-size: clamp(20px, 3.6cqh, 32px);
  line-height: 0.7;
  color: var(--accent);
}

#atlas-toggle:hover { color: #fff; }
#atlas-toggle.hidden { display: none !important; }

/* 冷光很慢地飘。静止的渐变看久了是「一张背景图」，
 * 让它以半分钟为周期挪一点，画面才像在呼吸。
 * 幅度刻意做得很小——察觉不到在动，但盯着会不安。 */
@keyframes coldDrift {
  from { background-position: 10% 4%,  56% 10%, 98% 30%, 96% 98%,  30% 104%, 0 0; }
  to   { background-position: 24% 0%,  42% 20%, 88% 46%, 78% 104%, 46% 96%,  0 0; }
}

@media (prefers-reduced-motion: reduce) {
  #title-screen, #boot-screen, #title-logo::before { animation: none; }
  #logo-img { animation: none; filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.7)); }
}

/* 整块（文字 + 箭头）一起上下浮动 */
@keyframes atlasFloat {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50% { transform: translateX(-50%) translateY(5px); }
}

/* 第一次回到首页：跳得更明显一点 */
#atlas-toggle.nudge { animation: atlasNudge 1.05s cubic-bezier(0.3, 0.9, 0.4, 1) 4; }

@keyframes atlasNudge {
  0%, 100% { transform: translateX(-50%) translateY(0) scale(1); }
  30% { transform: translateX(-50%) translateY(-12px) scale(1.09); }
  55% { transform: translateX(-50%) translateY(0) scale(1); }
  72% { transform: translateX(-50%) translateY(-5px) scale(1.03); }
}

@media (prefers-reduced-motion: reduce) {
  #atlas-toggle, #atlas-toggle.nudge { animation: none; }
}


#atlas-scrim {
  position: absolute;
  inset: 0;
  z-index: 30;
  background: rgba(4, 4, 8, 0.55);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

#atlas {
  position: absolute;
  z-index: 31;
  left: 0;
  right: 0;
  bottom: 0;
  height: 76cqh;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, #1b1e2c, #101219);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 0;
  box-shadow: 0 -18px 50px rgba(0, 0, 0, 0.6);
  transition: transform 0.42s cubic-bezier(0.22, 0.85, 0.3, 1);
}

#atlas.closed { transform: translateY(101%); }

#btn-atlas-close {
  border: none;
  background: rgba(255, 255, 255, 0.1);
  color: var(--ink);
  border-radius: 0;
  width: 2.2em;
  height: 2.2em;
  font-size: clamp(13px, 2.1cqh, 18px);
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
}

#btn-atlas-close:hover { background: rgba(255, 255, 255, 0.2); }

#atlas-top {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.9em;
  padding: 2cqh 5% 1.2cqh;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

#atlas-label {
  font-size: clamp(12px, 2cqh, 16px);
  letter-spacing: 0.22em;
  color: #e6e0d4;
}

#atlas-count { margin-left: auto; color: #7d7789; font-size: clamp(10px, 1.6cqh, 13px); }

#atlas-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 0 5% 1.2cqh;
  scrollbar-width: thin;
}

#atlas-body::-webkit-scrollbar { width: 4px; }
#atlas-body::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.14); border-radius: 0; }

/* 幕标题：一条横线上挂个标签 */
.rt-act {
  display: flex;
  align-items: center;
  gap: 0.8em;
  margin: 1.6cqh 0 0.8cqh;
  color: var(--accent);
  font-size: clamp(9px, 1.45cqh, 12px);
  letter-spacing: 0.28em;
}
.rt-act:first-child { margin-top: 0.4cqh; }
.rt-act::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, rgba(var(--accent-rgb), 0.45), transparent);
}
.rt-act.locked { color: #55505f; }

/* 一站 = 线上的一个点 */
.rt-stop {
  position: relative;
  display: flex;
  gap: 0.9em;
  padding: 0.45cqh 0;
  border-radius: 0;
}

/* 竖着的那根线 */
.rt-stop::before {
  content: '';
  position: absolute;
  left: 5px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: rgba(255, 255, 255, 0.1);
}
.rt-stop:last-child::before { bottom: 50%; }

.rt-dot {
  position: relative;
  z-index: 1;
  flex: none;
  width: 12px;
  height: 12px;
  margin-top: 0.35em;
  border-radius: 0;
  background: #14161f;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.18);
}

.rt-stop.open .rt-dot {
  background: var(--accent);
  box-shadow: inset 0 0 0 2px var(--accent), 0 0 12px rgba(var(--accent-rgb), 0.55);
}

.rt-stop.open::before { background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.5), rgba(var(--accent-rgb), 0.18)); }

.rt-stop.next .rt-dot { box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.34); animation: rtPulse 2s ease-in-out infinite; }

@keyframes rtPulse { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }

.rt-stop.dark { opacity: 0.45; }
.rt-stop.dark .rt-dot { width: 8px; height: 8px; margin-left: 2px; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.07); }
.rt-stop.dark .rt-main { height: 1.4em; }

.rt-main { flex: 1; min-width: 0; }

.rt-name { display: flex; align-items: baseline; gap: 0.6em; flex-wrap: wrap; }

.rt-no {
  color: var(--accent);
  font-weight: 700;
  font-size: clamp(9px, 1.5cqh, 12px);
  letter-spacing: 0.06em;
  opacity: 0.85;
}

.rt-stop.next .rt-no { color: #6f6a7c; }
.rt-name > span:not(.rt-no) { font-size: clamp(11px, 1.8cqh, 15px); color: #cfc9bc; }
.rt-stop.next .rt-name > span { color: #6f6a7c; font-style: italic; }

.rt-fork {
  font-size: clamp(9px, 1.4cqh, 11px);
  color: #8d8798;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 0;
  padding: 0.1em 0.7em;
}

.rt-stop.clickable { cursor: pointer; transition: background 0.15s ease; }
.rt-stop.clickable:hover { background: rgba(255, 255, 255, 0.05); }

/* 「从这一场重玩」——摆在行尾那块空地上。
 * ⚠ 不能只靠 cursor:pointer / :hover / title 来表达「这一行能点」：
 *   这三样手机上一样都没有，等于对竖屏玩家完全没有提示。 */
.rt-replay {
  flex: none;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid rgba(var(--accent-rgb), 0.34);
  border-radius: 0;
  background: rgba(var(--accent-rgb), 0.07);
  color: var(--accent);
  cursor: pointer;
  opacity: 0.72;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.15s ease, background 0.15s ease, transform 0.15s ease;
}
.rt-replay svg { width: 16px; height: 16px; fill: currentColor; display: block; }
.rt-replay:hover {
  opacity: 1;
  background: rgba(var(--accent-rgb), 0.2);
  border-color: rgba(var(--accent-rgb), 0.7);
}
.rt-replay:active { transform: scale(0.92); }
.rt-stop.clickable:hover .rt-replay { opacity: 1; }

@media (max-aspect-ratio: 1/1) {
  /* 竖屏：拇指点得准才算数，撑到 40px，并且一直保持全亮（没有 hover 可依赖） */
  .rt-replay { width: 40px; height: 40px; opacity: 1; }
  .rt-replay svg { width: 19px; height: 19px; }
}

/* 岔路尽头的结局：缩略图 + 名字，没解锁就是 ？？？ */
.rt-ends { display: flex; flex-wrap: wrap; gap: 6px; margin: 0.5cqh 0 0.2cqh; }

.rt-end {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  max-width: 100%;
  padding: 3px 0.8em 3px 3px;
  border-radius: 0;
  border: 1px solid rgba(255, 90, 90, 0.3);
  background: rgba(255, 90, 90, 0.07);
  color: #e2b3b3;
  font-family: inherit;
  font-size: clamp(9px, 1.5cqh, 12px);
  cursor: pointer;
  text-align: left;
  transition: transform 0.14s ease, background 0.14s ease;
}

.rt-end.good { border-color: rgba(85, 214, 138, 0.42); background: rgba(85, 214, 138, 0.09); color: #b0e6c3; }
.rt-end.got:hover { transform: translateX(3px); background: rgba(255, 90, 90, 0.18); }
.rt-end.good.got:hover { background: rgba(85, 214, 138, 0.2); }

.rt-end.locked {
  border-color: rgba(255, 255, 255, 0.09);
  background: rgba(0, 0, 0, 0.55);
  color: #4e4959;
  cursor: default;
  letter-spacing: 0.2em;
}

.rt-thumb {
  flex: none;
  width: clamp(34px, 5cqh, 44px);
  aspect-ratio: 4 / 3;
  height: auto;
  border-radius: 0;
  background: #0a0a10 center/cover no-repeat;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}

.rt-end.locked .rt-thumb { background: repeating-linear-gradient(45deg, #0c0c12 0 6px, #101018 6px 12px); }

.rt-endname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 竖屏：标题在上、路线在下 */
@media (max-aspect-ratio: 1/1) {
  #title-screen { flex-direction: column; }
  /* 左上角那排（语言 + 音乐）是绝对定位的，标题得让开它，不然「绑架主题 ADV」会被压住 */
  .title-inner { flex: none; padding: calc(8vh + env(safe-area-inset-top, 0px)) 6% 1.5cqh; }
  #title-screen h1 { font-size: clamp(34px, 7cqh, 60px); }
  .subtitle { margin: 1cqh 0 0.6cqh; }
  .byline { margin-bottom: 2cqh; }

  /* 竖屏一律排成规整的方块，不分语言：
   *   第一行＝胶带铺满整宽，第二行＝其余按钮平分，两行等宽。
   * 本来只给长文案语言用（英语三个按钮要 420px，窄机只有 280 出头），
   * 但有存档时中文也是四个按钮，同样塞不下、同样会乱折行。
   * 而且胶带铺满一整行更像「贴上去封住屏幕的那一条」，比缩成一小块好看。 */
  .title-buttons { width: 100%; }
  .title-buttons .btn-main { flex: 1 1 100%; justify-content: center; }
  .title-buttons .btn-sub { flex: 1 1 auto; }
  .title-inner .hint { display: none; }
  #atlas { height: 80vh; }
  /* 竖屏：不再钉在屏幕最底下（照片和它中间会空一大片），
   * 改成跟在照片墙后面正常排下来——就在照片下面一点。
   * 那层由下往上的暗色渐变也去掉了，纯文字+箭头更干净。 */
  #atlas-toggle {
    position: static;
    transform: none;
    margin: 2.4vh auto 0;
    margin: 2.4dvh auto 0;
    padding: 0.6vh 6vw 1vh;
    padding: 0.6dvh 6vw 1dvh;
    background: none;
  }
  #atlas-toggle .lbl { font-size: 19px; letter-spacing: 0.26em; text-indent: 0.26em; }
  #atlas-toggle .arw { font-size: 32px; }

  /* 静态排版下不能再用 translateX 居中，浮动动画换成纯上下 */
  #atlas-toggle,
  #atlas-toggle.nudge { animation-name: atlasFloatFlow; }
  #atlas-toggle.nudge { animation: atlasNudgeFlow 1.05s cubic-bezier(0.3, 0.9, 0.4, 1) 4; }
}

/* 转场热区：亮起来之前点不动，一圈进度转完才算「可以走了」 */
#transit-go.arming {
  pointer-events: none;
  opacity: 0.55;
  border-color: rgba(255, 255, 255, 0.14);
}

#transit-go.arming .hot-ring { animation: none; opacity: 0; }

#transit-go.arming .hot-dot {
  background: transparent;
  box-shadow: none;
  border: 2px solid rgba(255, 255, 255, 0.22);
  animation: armFill 0.9s linear forwards;
}

@keyframes armFill {
  from { border-color: rgba(255, 255, 255, 0.16); transform: scale(0.7); }
  to { border-color: var(--accent); transform: scale(1); }
}

#transit-go::after {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: 0;
  pointer-events: none;
  background: conic-gradient(var(--accent) var(--arm, 0turn), transparent 0);
  -webkit-mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  padding: 2px;
  opacity: 0;
}

#transit-go.arming::after { opacity: 0.9; animation: armSweep 0.9s linear forwards; }

@keyframes armSweep { from { --arm: 0turn; } to { --arm: 1turn; } }

@property --arm { syntax: '<angle>'; initial-value: 0turn; inherits: false; }

/* 还没踏进过的那一幕：标题也是暗的 */
.rt-act.locked { color: #55505f; }
.rt-act.locked::after { background: linear-gradient(90deg, rgba(255, 255, 255, 0.12), transparent); }

/* ============================================================
 * 首页照片墙：背后几张摆好就不动，只有最上面那张的两个图层在交叉淡入淡出
 * ============================================================ */

#photowall-wrap {
  flex: 1;
  min-width: 0;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

#photowall {
  position: relative;
  z-index: 1;
  isolation: isolate;          /* 把卡片的 z-index 关在自己这一层，别盖住抽屉 */
  width: min(100%, 720px);
  max-height: 100%;
  aspect-ratio: 4 / 3;
  flex: none;
}

.pw-card {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 86%;
  height: 86%;
  padding: 1.5%;
  border: none;
  border-radius: 0;
  background: #efe9dd;
  overflow: hidden;
  font-family: inherit;
  box-shadow: 0 14px 30px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(0, 0, 0, 0.45);
  transform:
    translate(var(--x, 0), var(--y, 0))
    rotate(var(--r, 0deg))
    scale(var(--s, 1));
}

/* 背后几张：纯装饰，摆好之后再也不动（不重排、不改层级、不动阴影） */
.pw-back { pointer-events: none; }

.pw-front {
  cursor: pointer;
  box-shadow: 0 22px 44px rgba(0, 0, 0, 0.66), 0 0 0 1px rgba(0, 0, 0, 0.45);
  transition: transform 0.2s ease;
}

.pw-front:not(.blind):hover {
  transform:
    translate(var(--x), calc(var(--y) - 1.4%))
    rotate(var(--r))
    scale(calc(var(--s) * 1.02));
}

.pw-front.blind { cursor: default; }

.pw-card img {
  position: absolute;
  inset: 1.5%;
  width: 97%;
  height: 97%;
  object-fit: cover;
  border-radius: 0;
  display: block;
}

/* 最上面那张的两个图层：轮换时只切 opacity，交给合成器，稳 */
.pw-layer {
  opacity: 0;
  transition: opacity 0.75s ease;
  will-change: opacity;
}

.pw-layer.on { opacity: 1; }

/* 还没解锁：深黑重模糊，看得出「有好几张、不一样」，但认不出任何内容 */
/* 没解锁：只透一点点轮廓和色调——看得出「有内容」，但认不出是谁在做什么 */
.pw-card img.blind { filter: blur(15px) brightness(0.34) saturate(0.5) contrast(1.1); transform: scale(1.14); }

/* 越往下压得越暗 */
.pw-card::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: rgba(6, 5, 10, var(--dim, 0));
}


/* 首次进场：一张一张落下来（只在开场跑一次） */
@keyframes pwDrop {
  from {
    opacity: 0;
    transform:
      translate(calc(var(--x) + 6%), calc(var(--y) - 22%))
      rotate(calc(var(--r) - 10deg))
      scale(calc(var(--s) * 1.06));
  }
  to { opacity: 1; }
}

.pw-card { animation: pwDrop 0.7s cubic-bezier(0.2, 0.9, 0.25, 1) both; }

@media (prefers-reduced-motion: reduce) {
  .pw-card { animation: none; }
  .pw-layer { transition: opacity 0.3s ease; }
}

@media (max-aspect-ratio: 1/1) {
  /* 顶部留够：左上角那排（语言 + 音乐）是绝对定位的，不让位就会压住「绑架主题 ADV」。
   * 底部不用再留 9vh——迷途旅程现在跟在照片后面正常排，不再钉在屏幕底。 */
  .title-inner {
    flex-direction: column;
    gap: 2vh;
    gap: 2dvh;
    padding: calc(8.5vh + env(safe-area-inset-top, 0px)) 5% 2vh;
    padding: calc(8.5dvh + env(safe-area-inset-top, 0px)) 5% 2dvh;
  }
  .title-text { flex: none; width: 100%; }
  #photowall-wrap { width: 100%; height: auto; flex: 1; min-height: 0; }
  #photowall { width: min(94%, 420px); }
}

/* ---------- 开始前的内容与年龄声明 ---------- */

#boot-agree { width: min(92%, 620px); text-align: left; }

.agree-kicker {
  color: var(--accent);
  letter-spacing: 0.4em;
  font-size: clamp(10px, 1.6cqh, 13px);
  text-align: center;
  margin-bottom: 1cqh;
}

#boot-agree h2 {
  font-size: clamp(18px, 3.2cqh, 27px);
  letter-spacing: 0.1em;
  text-align: center;
  margin-bottom: 2.4cqh;
}

.agree-body {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-left: 3px solid var(--danger);
  border-radius: 0;
  padding: 2.4cqh 3cqh;
  margin-bottom: 2.6cqh;
}

.agree-body p {
  color: #ded8cc;
  font-size: clamp(12px, 2cqh, 16px);
  line-height: 1.9;
  margin-bottom: 1.4cqh;
}

.agree-body ul { list-style: none; display: flex; flex-direction: column; gap: 1cqh; }

.agree-body li {
  position: relative;
  padding-left: 1.5em;
  color: #b8b2a6;
  font-size: clamp(11px, 1.9cqh, 15px);
  line-height: 1.8;
}

.agree-body li::before {
  content: '·';
  position: absolute;
  left: 0.4em;
  color: var(--danger);
  font-weight: 700;
}

.agree-body b { color: #f2ede2; }

#agree-check-wrap {
  display: flex;
  align-items: flex-start;
  gap: 0.7em;
  color: #cfc9bc;
  font-size: clamp(11px, 1.9cqh, 15px);
  line-height: 1.6;
  cursor: pointer;
  padding: 1.4cqh 2cqh;
  border-radius: 0;
  background: rgba(255, 255, 255, 0.06);
  margin-bottom: 2.4cqh;
}

#agree-check { width: 20px; height: 20px; flex: none; accent-color: var(--accent); cursor: pointer; margin-top: 0.1em; }

#agree-go {
  display: block;
  margin: 0 auto;
  letter-spacing: 0.08em;
}

#agree-go:disabled { opacity: 0.32; cursor: not-allowed; transform: none; box-shadow: none; }

@media (max-aspect-ratio: 1/1) {
  #boot-agree { width: 100%; }
  .agree-body { padding: 2vh 4vw; }
  .agree-body p { font-size: clamp(13px, 1.9vh, 17px); }
  .agree-body li { font-size: clamp(12px, 1.7vh, 15px); }
  #agree-check-wrap { font-size: clamp(12px, 1.7vh, 15px); }
}

/* ---------- 首页右上角：作者的 X 主页 ---------- */

/* 排在首页按钮行的最后一个 */
#x-link {
  /* 高度和 .btn-sub 对齐：用同一套字号+内边距算出来，别用 stretch。
   * ⚠ 这排按钮会换行，stretch 会让独占一行的 X 撑满整行剩余高度（实测 300px）。 */
  flex: none;
  align-self: center;
  font-size: clamp(12px, 1.9cqh, 16px);
  line-height: 1.2;
  padding: 1.2cqh;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0;
  background: #000;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.14);
  transition: transform 0.16s ease, box-shadow 0.16s ease;
  -webkit-tap-highlight-color: transparent;
}

#x-link:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.3);
}

#x-link svg { width: 1.2em; height: 1.2em; fill: #fff; display: block; }



/* ============================================================
 * 成就：达成横幅 + 成就面板
 * ============================================================ */

#achv-toasts {
  position: absolute;
  z-index: 60;
  top: 3cqh;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 1cqh;
  pointer-events: none;
  width: min(88%, 460px);
}

.achv-toast {
  display: flex;
  align-items: center;
  gap: 1em;
  padding: 1.4cqh 2cqh 1.4cqh 1.4cqh;
  border-radius: 0;
  background: linear-gradient(135deg, rgba(38, 28, 16, 0.97), rgba(16, 14, 22, 0.97));
  border: 1px solid rgba(var(--accent-rgb), 0.5);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(0, 0, 0, 0.4);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  animation: achvIn 0.55s cubic-bezier(0.2, 0.9, 0.25, 1) both;
}

@keyframes achvIn {
  from { opacity: 0; transform: translateY(-18px) scale(0.96); }
  to { opacity: 1; }
}

.achv-toast.out { animation: achvOut 0.6s ease forwards; }

@keyframes achvOut {
  to { opacity: 0; transform: translateY(-14px); }
}

.achv-thumb {
  flex: none;
  width: clamp(46px, 9cqh, 72px);
  aspect-ratio: 4 / 3;
  border-radius: 0;
  background: #0a0a10 center/cover no-repeat;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16);
}

.achv-text { min-width: 0; }

.achv-kicker {
  color: var(--accent);
  font-size: clamp(9px, 1.5cqh, 12px);
  letter-spacing: 0.26em;
  margin-bottom: 0.25em;
}

.achv-name {
  /* 解锁的那一行是 <button>，按钮不继承 color，不写死就会变成浏览器默认的深色字 */
  color: var(--ink);
  font-size: clamp(13px, 2.2cqh, 18px);
  font-weight: 700;
  letter-spacing: 0.06em;
  margin-bottom: 0.2em;
}

.achv-desc {
  color: #a49dae;
  font-size: clamp(10px, 1.6cqh, 13px);
  line-height: 1.6;
}

/* ---- 面板 ---- */

#achv-panel {
  position: absolute;
  inset: 0;
  z-index: 55;
  background: rgba(4, 4, 8, 0.82);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4cqh 4%;
}

#achv-card {
  position: relative;      /* 「生成你的专属迷途」是悬浮的，得有个定位祖先 */
  width: min(92%, 620px);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  background: linear-gradient(170deg, #1c1f2e, #12141d);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 0;
  overflow: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.7);
}

#achv-top {
  flex: none;
  display: flex;
  align-items: center;
  gap: 1em;
  padding: 2.2cqh 3.4cqh;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  font-size: clamp(13px, 2.2cqh, 18px);
  letter-spacing: 0.1em;
}

#achv-count { margin-left: auto; color: var(--accent); font-size: clamp(11px, 1.8cqh, 15px); }
#achv-top .btn-sub { padding: 0.8cqh 2.2cqh; font-size: clamp(11px, 1.8cqh, 14px); }

#achv-body {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 1.6cqh 3.4cqh 2.6cqh;
  display: flex;
  flex-direction: column;
  gap: 1.2cqh;
}

.achv-row {
  display: flex;
  align-items: center;
  gap: 1em;
  padding: 1.2cqh;
  border-radius: 0;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  opacity: 0.5;
}

.achv-row.got {
  opacity: 1;
  border-color: rgba(var(--accent-rgb), 0.42);
  background: rgba(var(--accent-rgb), 0.08);
}

.achv-row:not(.got) .achv-thumb {
  background: repeating-linear-gradient(45deg, #0c0c12 0 6px, #12121a 6px 12px);
}

.achv-row:not(.got) .achv-name { color: #55505f; letter-spacing: 0.28em; }

@media (max-aspect-ratio: 1/1) {
  #achv-toasts { top: 2vh; width: 92%; }
  .achv-toast { padding: 1.4vh 3vw 1.4vh 2vw; }
  .achv-thumb { width: 56px; }
  .achv-kicker { font-size: 10px; }
  .achv-name { font-size: 15px; }
  .achv-desc { font-size: 11px; }
  #achv-panel { padding: 4vh 4%; }
  #achv-top { padding: 2vh 4vw; font-size: 15px; }
  #achv-body { padding: 1.5vh 4vw 2.5vh; gap: 1.2vh; }
  .achv-row { padding: 1.2vh 2vw; }
}

/* ---------- 成就说明 + 附赠图大图（相纸效果，不带水印） ---------- */

#achv-note {
  flex: none;
  padding: 1.2cqh 3.4cqh 0;
  color: #7d7789;
  font-size: clamp(10px, 1.55cqh, 13px);
  line-height: 1.7;
}

.achv-row.got { cursor: pointer; font-family: inherit; color: inherit; text-align: left; }
.achv-row.got:hover { background: rgba(var(--accent-rgb), 0.15); transform: translateX(2px); }
.achv-row { transition: background 0.15s ease, transform 0.15s ease; }

#gift-view {
  position: absolute;
  inset: 0;
  z-index: 70;
  background: rgba(3, 3, 6, 0.92);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2cqh;
  padding: 6cqh 5% 4cqh;
  cursor: zoom-out;
}

#gift-frame {
  display: flex;
  max-width: 100%;
  max-height: 100%;
  min-width: 0;
  min-height: 0;
  padding: 0.9%;
  border-radius: 0;
  background: #efe9dd;
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.82),
    0 2px 10px rgba(0, 0, 0, 0.6),
    0 0 0 1px rgba(0, 0, 0, 0.5);
  transform: rotate(-1.1deg);
  animation: giftIn 0.5s cubic-bezier(0.16, 0.9, 0.3, 1) both;
}

@keyframes giftIn {
  from { opacity: 0; transform: rotate(-4deg) scale(1.06); }
  to { opacity: 1; transform: rotate(-1.1deg) scale(1); }
}

#gift-img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  min-width: 0;
  min-height: 0;
  object-fit: contain;
  border-radius: 0;
}

#gift-name {
  flex: none;
  color: #ded8cc;
  font-size: clamp(12px, 2cqh, 17px);
  letter-spacing: 0.12em;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.9);
}

#btn-gift-close { flex: none; cursor: pointer; }

@media (max-aspect-ratio: 1/1) {
  #achv-note { padding: 1.2vh 4vw 0; font-size: 12px; }
  #gift-view { padding: 5vh 4% 4vh; gap: 2vh; }
  #gift-name { font-size: 14px; }
}

/* ---------- 碎碎念 ---------- */

#notes-panel {
  position: absolute;
  inset: 0;
  z-index: 56;
  background: rgba(4, 4, 8, 0.85);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4cqh 4%;
}

#notes-card {
  width: min(92%, 660px);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  background: linear-gradient(170deg, #1c1f2e, #12141d);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 0;
  overflow: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.7);
}

#notes-top {
  flex: none;
  display: flex;
  align-items: center;
  padding: 2.2cqh 3.4cqh;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  font-size: clamp(13px, 2.2cqh, 18px);
  letter-spacing: 0.16em;
}

#notes-top .btn-sub { margin-left: auto; padding: 0.8cqh 2.2cqh; font-size: clamp(11px, 1.8cqh, 14px); }

#notes-body {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 2.4cqh 3.4cqh 3cqh;
  background: none;
  border: none;
  border-radius: 0;
  margin: 0;
}

@media (max-aspect-ratio: 1/1) {
  #notes-panel { padding: 4vh 4%; }
  #notes-top { padding: 2vh 4vw; font-size: 15px; }
  #notes-body { padding: 2vh 4vw 2.5vh; }
}

/* ---------- 左上角语言选择 ---------- */

/* 左上角：语言 + 音乐开关并排（音乐原来在标题按钮里，和「碎碎念」挤在一起太杂） */
#lang-pick {
  position: absolute;
  z-index: 12;
  top: max(2.4cqh, env(safe-area-inset-top, 0px));
  left: max(2.4%, env(safe-area-inset-left, 0px));
  display: flex;
  align-items: stretch;
  gap: 6px;
}
#lang-pick #btn-bgm { height: auto; width: clamp(30px, 4.6cqh, 38px); }

#lang-btn {
  display: flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.7cqh 1.6cqh;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 0;
  background: rgba(10, 11, 18, 0.55);
  color: #cfc9bc;
  font-family: inherit;
  font-size: clamp(10px, 1.6cqh, 13px);
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background 0.15s ease;
}

#lang-btn:hover { background: rgba(24, 26, 38, 0.85); }

/* 「文A」图标：比地球仪直观——一个汉字一个拉丁字母，就是「换语言」 */
.lang-ico {
  display: inline-flex;
  align-items: baseline;
  gap: 0.1em;
  color: var(--ink);
  font-weight: 700;
  font-size: 1.25em;
  line-height: 1;
}
.lang-ico i { font-style: normal; font-size: 0.78em; color: var(--accent); }

#lang-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  left: 0;
  min-width: 168px;
  padding: 6px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 0;
  background: rgba(16, 17, 26, 0.97);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.6);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

#lang-menu button {
  display: block;
  width: 100%;
  padding: 0.8cqh 1.2cqh;
  border: none;
  border-radius: 0;
  background: none;
  color: #cfc9bc;
  font-family: inherit;
  font-size: clamp(10px, 1.6cqh, 13px);
  text-align: left;
  cursor: pointer;
}

#lang-menu button:hover { background: rgba(255, 255, 255, 0.08); }
#lang-menu button.on { color: var(--accent); font-weight: 700; }

.lang-note {
  margin: 6px 4px 2px;
  color: #6f6a7c;
  font-size: clamp(9px, 1.4cqh, 11px);
  line-height: 1.6;
}

@media (max-aspect-ratio: 1/1) {
  #lang-pick { top: 2vh; left: 4%; }
  #lang-btn { font-size: 12px; padding: 1vh 3vw; }
  #lang-menu button { font-size: 13px; padding: 1.2vh 3vw; }
}

/* ============================================================
 * 冷硬版式：方角 + 细线 + 切角。
 * 圆角全部收掉之后，靠「切角」「细边框」「字距」重新做出锋利感。
 * ============================================================ */

/* 主按钮：右下切角，像证物标签 */
/* ⚠ 主按钮的撕口 clip-path 写在上面，这里不能再覆盖一次切角 */
.btn-danger {
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 0.8em), calc(100% - 0.8em) 100%, 0 100%);
}
.btn-main, .btn-danger { letter-spacing: 0.14em; }

/* 次按钮：只留细边，去掉底色的柔软感 */
.btn-sub {
  /* 次按钮＝黑胶带。和主按钮同一卷货、不同颜色：
   * 银色是亮面（硬高光），黑色是哑光布基（宽而钝的反光带），
   * 层级差自然就出来了，不用再靠描边。 */
  background: var(--tape-black);
  border: none;
  clip-path: var(--tape-tear);
  color: #ccd2de;
  letter-spacing: 0.14em;
  filter: var(--tape-cast);
}

.btn-sub:hover {
  color: var(--ink);
  filter: var(--tape-cast) drop-shadow(0 0 10px rgba(150, 175, 255, 0.35)) brightness(1.4);
}

/* 选项：左侧一道实心竖条当序号轨，方方正正 */
#choices button {
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-left: 3px solid rgba(255, 255, 255, 0.3);
  background: rgba(10, 9, 16, 0.9);
  transition: border-color 0.14s ease, background 0.14s ease, transform 0.14s ease;
}

#choices button:hover {
  border-left-color: var(--accent);
  background: rgba(24, 18, 14, 0.94);
  transform: translateX(4px);
}

/* 说话人名牌：方牌，不是药丸 */
#speaker-tag {
  transform: translateY(-52%);
  padding: 0.6cqh 1.8cqh;
  letter-spacing: 0.1em;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0.6em 100%);
  padding-left: 2.4cqh;
}

/* 对话框：直角 + 顶部一道细高光 */
#dialogue-box {
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09);
}

/* 面板类：直角卡片 + 细边 */
#achv-card, #notes-card, #atlas {
  border: 1px solid rgba(255, 255, 255, 0.16);
}

/* 结局收集卡 / 成就行：切掉右上角 */
.rt-end, .achv-row {
  clip-path: polygon(0 0, calc(100% - 0.55em) 0, 100% 0.55em, 100% 100%, 0 100%);
}

/* 语言按钮和菜单 */
#lang-btn { border: 1px solid rgba(255, 255, 255, 0.22); letter-spacing: 0.08em; }
#lang-menu { border: 1px solid rgba(255, 255, 255, 0.18); }

/* X 图标：方块 */
#x-link { border-radius: 0; }

/* 转场热区：细方框 + 切角，不再是胶囊 */
#transit-go {
  border: 1px solid rgba(255, 255, 255, 0.26);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 0.7em), calc(100% - 0.7em) 100%, 0 100%);
}

/* 照片：相纸边留一点点，但四角是直的 */
.pw-card, #photo-frame, #gift-frame { border-radius: 0; }

/* 成就横幅：左侧一道橙色实心条 */
.achv-toast {
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-left: 3px solid var(--accent);
}

/* 内容提示那一块：左侧红条已经有了，去掉圆角后补一道上下细线 */
.agree-body {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  border-right: none;
}

/* 真正该是圆的东西：路线上的站点、转场热区的光点 */
.rt-dot, .hot-dot, .hot-ring { border-radius: 50%; }

/* ============================================================
 * 场景氛围：每个背景一套「光」（哪张背景配哪套，见 js/mood.js）
 *
 * 三层叠出来的效果：
 *   #story-bg  底图调色（--b 亮度 / --c 对比 / --s 饱和 / --h 色相，
 *              和 tint 的 --tb/--tc/--ts/--th 相乘，所以「地点」和「时段/出事」可以叠加）
 *   #ambience  环境光，压在背景上、立绘**下** —— 人是站在光里，不是贴在图上
 *   #grade     统一调色 + 暗角，盖在立绘之上，把人和景压进同一种光
 *
 * 动的东西一律只动 transform / opacity，不动 filter，手机上才不掉帧。
 * ============================================================ */

#story-media {
  isolation: isolate;      /* 把混合模式关在画面区里，别去和 UI 混色 */
  --b: 1; --c: 1; --s: 1; --h: 0deg;
  --tb: 1; --tc: 1; --ts: 1; --th: 0deg;
  --amb: none;
  --amb-o: 1;
  --amb-blend: screen;
  --mv: none;              /* 环境光里那道会动的东西 */
  --mv-bg: none;
  --vig: 0.45;             /* 暗角浓度 */
  --air: transparent;      /* 盖在立绘上的色调 */
}

#story-bg {
  z-index: 0;
  filter:
    brightness(calc(var(--b) * var(--tb)))
    contrast(calc(var(--c) * var(--tc)))
    saturate(calc(var(--s) * var(--ts)))
    hue-rotate(calc(var(--h) + var(--th)));
  transition: filter 0.55s ease;
}

#ambience {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: hidden;
  background: var(--amb);
  opacity: var(--amb-o);
  mix-blend-mode: var(--amb-blend);
  transition: opacity 0.5s ease;
}

#ambience i {
  position: absolute;
  inset: -30%;
  display: block;
  background: var(--mv-bg);
  animation: var(--mv);
  will-change: transform, opacity;
}

.portrait-slot { z-index: 2; }

#grade {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  --vig-core: 50%;
  --vig-mid: 79%;
  background:
    linear-gradient(var(--air), var(--air)),
    radial-gradient(ellipse 90% 94% at 50% 46%,
      transparent var(--vig-core),
      rgba(4, 4, 9, calc(var(--vig) * 0.4)) var(--vig-mid),
      rgba(4, 4, 9, var(--vig)) 100%);
  transition: background 0.55s ease;
}

/* 插画铺满时不套环境光——插画自带完整的光，再压一层就脏了 */
#story-media.cg-mode #ambience,
#story-media.cg-mode #grade,
#story-media.no-mood #ambience,
#story-media.no-mood #grade { display: none; }

#story-media.cg-mode #story-bg { filter: none; }

/* ---------- 时段 / 出事：和地点的光相乘 ---------- */

#story-media.tint-night {
  --tb: 0.94; --ts: 0.92; --th: -8deg;
  --vig: 0.4;
  --air: rgba(24, 34, 66, 0.1);
}

#story-media.tint-danger {
  --tb: 1; --tc: 1.04; --ts: 0.95;
  --vig: 0.44;
  --air: rgba(48, 10, 14, 0.1);
}

/* ---------- 各地点的光 ---------- */

/* 训练馆 · 正午顶光，空气里全是浮尘 */
#story-media.mood-noon {
  --b: 1.06; --c: 1.02; --s: 1.05; --vig: 0.34;
  --amb: linear-gradient(180deg, rgba(255, 238, 198, 0.26) 0%, transparent 52%);
  --mv-bg: repeating-linear-gradient(102deg,
    rgba(255, 244, 214, 0.05) 0 6%, transparent 6% 26%);
  --mv: dustDrift 26s linear infinite;
  --air: rgba(255, 226, 170, 0.05);
}

/* 宿舍 · 午后从窗口斜进来的暖黄 */
#story-media.mood-afternoon {
  --b: 1.04; --s: 1.08; --h: 4deg; --vig: 0.34;
  --amb: radial-gradient(ellipse 62% 86% at 80% 6%, rgba(255, 206, 130, 0.32), transparent 62%);
  --air: rgba(255, 198, 128, 0.06);
}

/* 户外白天 · 通透 */
#story-media.mood-daylight {
  --b: 1.05; --c: 1.03; --s: 1.06; --vig: 0.3;
  --amb: linear-gradient(180deg, rgba(214, 236, 255, 0.2) 0%, transparent 46%);
}

/* 旧馆大厅 · 高窗打下来的冷光柱，灰尘在里面翻 */
#story-media.mood-dusty {
  --b: 1.0; --c: 1.04; --s: 0.88; --h: -5deg; --vig: 0.42;
  --amb: linear-gradient(168deg, rgba(206, 224, 255, 0.22) 0%, transparent 44%);
  --mv-bg: repeating-linear-gradient(98deg,
    rgba(222, 235, 255, 0.05) 0 5%, transparent 5% 28%);
  --mv: dustDrift 34s linear infinite;
  --air: rgba(120, 140, 180, 0.05);
}

/* 旧馆侧门 · 背光的窄缝，只有一道光进得来 */
#story-media.mood-shade {
  --b: 1.0; --c: 1.03; --s: 0.86; --h: -6deg; --vig: 0.4;
  --amb: linear-gradient(96deg, rgba(190, 214, 246, 0.24) 0%, transparent 26%);
  --air: rgba(30, 42, 62, 0.14);
}

/* 暗房 · 只有那盏红灯，一呼一吸 */
#story-media.mood-darkroom {
  --b: 0.98; --c: 1.06; --s: 1.14; --h: -10deg; --vig: 0.44;
  --amb: radial-gradient(ellipse 74% 70% at 50% 34%, rgba(255, 46, 42, 0.4), transparent 68%);
  --mv-bg: radial-gradient(ellipse 60% 56% at 50% 38%, rgba(255, 70, 50, 0.3), transparent 70%);
  --mv: redPulse 4.2s ease-in-out infinite;
  --air: rgba(70, 8, 10, 0.2);
}

/* 公交 · 车窗外的光一道一道刷过来 */
#story-media.mood-commute {
  --b: 0.98; --s: 0.96; --vig: 0.46;
  --amb: linear-gradient(180deg, rgba(226, 238, 255, 0.14) 0%, transparent 40%);
  --mv-bg: linear-gradient(100deg, transparent 0%, rgba(255, 250, 232, 0.16) 46%, transparent 62%);
  --mv: sweep 5.2s linear infinite;
}

/* 东岸球场 · 烈日，白得发硬 */
#story-media.mood-blaze {
  --b: 1.1; --c: 1.13; --s: 1.14; --h: 3deg; --vig: 0.28;
  --amb: radial-gradient(ellipse 70% 50% at 50% 0%, rgba(255, 248, 214, 0.34), transparent 62%);
  --mv-bg: radial-gradient(ellipse 90% 60% at 50% 8%, rgba(255, 252, 226, 0.14), transparent 70%);
  --mv: heat 6.5s ease-in-out infinite;
  --air: rgba(255, 240, 196, 0.05);
}

/* 更衣区 · 荧光灯，冷白，偶尔抽一下 */
#story-media.mood-fluoro {
  --b: 1.03; --c: 1.03; --s: 0.82; --h: -8deg; --vig: 0.42;
  --amb: linear-gradient(180deg, rgba(216, 240, 255, 0.24) 0%, transparent 34%);
  --mv-bg: linear-gradient(180deg, rgba(220, 242, 255, 0.12) 0%, transparent 40%);
  --mv: flicker 7s steps(1, end) infinite;
  --air: rgba(80, 110, 140, 0.06);
}

/* 拍照区 · 闪光灯每隔一会儿炸一下 */
#story-media.mood-flash {
  --b: 0.98; --c: 1.06; --s: 0.94; --vig: 0.44;
  --amb: radial-gradient(ellipse 60% 60% at 50% 30%, rgba(210, 228, 255, 0.18), transparent 66%);
  --mv-bg: radial-gradient(ellipse 80% 70% at 50% 34%, rgba(255, 255, 255, 0.55), transparent 62%);
  --mv: flashPop 8.5s ease-out infinite;
}

/* 恢复室 · 均匀冷白，什么颜色都被抽走了 */
#story-media.mood-clinic {
  --b: 1.06; --c: 0.97; --s: 0.7; --h: -9deg; --vig: 0.4;
  --amb: linear-gradient(180deg, rgba(226, 244, 255, 0.2) 0%, transparent 50%);
  --air: rgba(150, 176, 196, 0.07);
}

/* 车里 · 街灯一道道从脸上扫过去 */
#story-media.mood-car {
  --b: 0.98; --c: 1.04; --s: 0.92; --h: -7deg; --vig: 0.42;
  --amb: radial-gradient(ellipse 80% 60% at 50% 20%, rgba(120, 150, 200, 0.16), transparent 70%);
  --mv-bg: linear-gradient(94deg, transparent 0%, rgba(255, 232, 190, 0.22) 44%, transparent 58%);
  --mv: sweep 3.6s linear infinite;
  --air: rgba(14, 20, 36, 0.16);
}

/* 地下车库 · 冷绿荧光，灯管接触不良 */
#story-media.mood-garage {
  --b: 0.95; --c: 1.05; --s: 0.8; --h: -14deg; --vig: 0.44;
  --amb: linear-gradient(180deg, rgba(180, 255, 220, 0.16) 0%, transparent 42%);
  --mv-bg: linear-gradient(180deg, rgba(190, 255, 226, 0.16) 0%, transparent 46%);
  --mv: flicker 4.4s steps(1, end) infinite;
  --air: rgba(10, 28, 24, 0.2);
}

/* 电梯 · 顶上一块方光，四面压死 */
#story-media.mood-elevator {
  --b: 1.02; --c: 1.02; --s: 0.82; --h: -6deg; --vig: 0.46;
  --amb: linear-gradient(180deg, rgba(224, 240, 255, 0.26) 0%, transparent 26%);
  --air: rgba(18, 24, 34, 0.16);
}

/* 饭店大堂 / 餐厅 · 暖橙，这一天里最松弛的光 */
#story-media.mood-warmroom {
  --b: 1.03; --c: 1.01; --s: 1.1; --h: 6deg; --vig: 0.36;
  --amb: radial-gradient(ellipse 78% 56% at 50% 8%, rgba(255, 178, 96, 0.28), transparent 62%);
  --air: rgba(255, 176, 96, 0.06);
}

/* 酒店健身房 · 夜里的冷蓝 */
#story-media.mood-coldgym {
  --b: 0.99; --c: 1.02; --s: 0.86; --h: -11deg; --vig: 0.4;
  --amb: linear-gradient(180deg, rgba(180, 214, 255, 0.2) 0%, transparent 44%);
  --air: rgba(20, 34, 56, 0.14);
}

/* 包间 · 暖，但门一关就是个盒子 */
#story-media.mood-vip {
  --b: 1.02; --c: 1.02; --s: 1.05; --h: 5deg; --vig: 0.42;
  --amb: radial-gradient(ellipse 56% 46% at 50% 6%, rgba(255, 190, 120, 0.3), transparent 60%);
  --air: rgba(40, 24, 14, 0.14);
}

/* 江边 · 冷蓝，水面一直在晃 */
#story-media.mood-water {
  --b: 1.0; --c: 1.02; --s: 0.95; --h: -12deg; --vig: 0.38;
  --amb: linear-gradient(180deg, rgba(150, 196, 255, 0.16) 0%, transparent 38%);
  --mv-bg: linear-gradient(180deg,
    transparent 48%, rgba(158, 206, 255, 0.1) 60%, rgba(158, 206, 255, 0.04) 70%, transparent 82%);
  --mv: shimmer 11s ease-in-out infinite;
  --air: rgba(18, 34, 62, 0.12);
}

/* 路边接人 · 黄昏，橙压着紫 */
#story-media.mood-dusk {
  --b: 1.0; --s: 1.12; --h: 9deg; --vig: 0.4;
  --amb:
    linear-gradient(180deg, rgba(255, 170, 110, 0.22) 0%, transparent 44%),
    linear-gradient(0deg, rgba(96, 78, 150, 0.18) 0%, transparent 40%);
  --air: rgba(90, 60, 90, 0.08);
}

/* 兜底：没配光的场景保持原样，只给一点点暗角 */
#story-media.mood-plain { --vig: 0.32; }

@keyframes dustDrift {
  from { transform: translate3d(-12%, -6%, 0); }
  to { transform: translate3d(12%, 6%, 0); }
}
@keyframes redPulse {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}
@keyframes sweep {
  from { transform: translate3d(-70%, 0, 0); }
  to { transform: translate3d(70%, 0, 0); }
}
@keyframes shimmer {
  0%, 100% { transform: translate3d(0, -1.5%, 0); opacity: 0.7; }
  50% { transform: translate3d(0, 1.5%, 0); opacity: 1; }
}
@keyframes heat {
  0%, 100% { opacity: 0.5; transform: translate3d(0, 0, 0); }
  50% { opacity: 1; transform: translate3d(0, -1%, 0); }
}
/* 灯管接触不良：绝大部分时间是亮的，偶尔连抽两下 */
@keyframes flicker {
  0%, 86%, 100% { opacity: 1; }
  87% { opacity: 0.25; }
  88% { opacity: 1; }
  91% { opacity: 0.4; }
  92% { opacity: 1; }
}
/* 闪光灯：长时间黑，突然一下 */
@keyframes flashPop {
  0%, 92%, 100% { opacity: 0; }
  93% { opacity: 1; }
  97% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  #ambience i { animation: none; }
}

/* ============================================================
 * 定格：关键道具 / 人物状态的特写先独占画面。
 * 读秒读完之前点不动 —— 逼玩家真的看一眼，而不是一路连点冲过去。
 * 图本身走 cg-mode（原比例居中、同图放大模糊垫底、缓慢推近），这里只管上面那层字和读秒。
 * ============================================================ */

#moment {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
}

#moment.hidden { display: none; }

#moment-label {
  /* 靠左下角，像证物照下面那行注脚——居中会正好压在画面主体上 */
  position: absolute;
  left: 4.5%;
  bottom: 5.5cqh;
  padding: 1cqh 2.4cqh;
  max-width: 62%;
  background: rgba(6, 5, 10, 0.78);
  border-left: 3px solid var(--accent);
  color: #f4f0e8;
  font-size: clamp(11px, 2cqh, 17px);
  letter-spacing: 0.16em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.9);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: 0;
  animation: moLabel 0.7s ease 0.35s forwards;
}

@keyframes moLabel {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 读秒圈：转完一圈才可以点 */
#moment-go {
  position: absolute;
  right: 5%;
  bottom: 5cqh;
  width: clamp(34px, 6cqh, 52px);
  height: clamp(34px, 6cqh, 52px);
  padding: 0;
  border: none;
  background: none;
  cursor: default;
  pointer-events: none;
}

.mo-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.16);
}

.mo-ring::after {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  background: conic-gradient(var(--accent) var(--p, 0%), transparent 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
}

.mo-tip {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  font-size: clamp(13px, 2.2cqh, 18px);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.mo-tip::before { content: '▼'; }

/* 读完秒：圈填满、箭头亮起来、开始呼吸，示意可以点了 */
#moment.ready .mo-tip { opacity: 1; animation: moBreathe 1.5s ease-in-out infinite; }
#moment.ready .mo-ring { border-color: rgba(var(--accent-rgb), 0.5); }
#moment.ready #moment-label { animation: moLabel 0.7s ease 0.35s forwards, moFade 0.6s ease forwards; }

@keyframes moBreathe {
  0%, 100% { transform: translateY(0); opacity: 1; }
  50% { transform: translateY(3px); opacity: 0.6; }
}

@keyframes moFade { to { opacity: 0.35; } }

@media (max-aspect-ratio: 1/1) {
  #moment-label {
    bottom: auto;
    top: calc(var(--stack-top) + var(--art-h) - 7vh);
    top: calc(var(--stack-top) + var(--art-h) - 7dvh);
    left: 3.5%;
    max-width: 74%;
    font-size: clamp(12px, 1.9vh, 16px);
    font-size: clamp(12px, 1.9dvh, 16px);
  }
  #moment-go {
    bottom: auto;
    top: calc(var(--stack-top) + var(--art-h) - 9vh);
    top: calc(var(--stack-top) + var(--art-h) - 9dvh);
    right: 4%;
    width: 40px;
    height: 40px;
  }
}

@media (prefers-reduced-motion: reduce) {
  #moment-label { animation: none; opacity: 1; }
  #moment.ready .mo-tip { animation: none; }
}

/* ---------- 定格的展示方式：和结局插画不同，这里要「看清楚」 ----------
 * 结局那套是第一人称视角（重暗角 + 呼吸起伏），压在道具特写上会把细节吃掉。
 * 定格改成：暗角收到很轻、几乎不裁切，配一个从头到尾极缓慢的推近。 */

#story-media.cg-mode.moment-mode::after {
  background:
    radial-gradient(ellipse 88% 94% at 50% 48%, transparent 64%, rgba(3, 2, 6, 0.4) 100%);
  animation: none;
}

/* 垫底那层也别压那么暗——定格图是 16:9，两侧几乎不留边 */
#story-media.cg-mode.moment-mode::before {
  -webkit-backdrop-filter: blur(30px) brightness(0.5) saturate(0.9);
  backdrop-filter: blur(30px) brightness(0.5) saturate(0.9);
}

#story-media.cg-mode.moment-mode #story-bg {
  animation: cgIn 0.75s ease, momentPush 22s ease-out 0.75s forwards;
}

/* 极慢推近：看得出在动，但不会让人晕 */
@keyframes momentPush {
  from { transform: scale(1); }
  to { transform: scale(1.05); }
}

@media (prefers-reduced-motion: reduce) {
  #story-media.cg-mode.moment-mode #story-bg { animation: cgIn 0.75s ease; }
}

/* ---------- 首页音乐开关：和 X 图标做成一对，方方正正 ---------- */

#btn-bgm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(30px, 5cqh, 40px);
  height: clamp(30px, 5cqh, 40px);
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 0;
  background: rgba(10, 11, 18, 0.55);
  color: #cfc9bc;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

#btn-bgm svg { width: 58%; height: 58%; fill: currentColor; }
#btn-bgm .ico-off { display: none; }
#btn-bgm.off .ico-on { display: none; }
#btn-bgm.off .ico-off { display: block; }
#btn-bgm.off { color: #6b6675; }
#btn-bgm:hover { color: var(--accent); border-color: rgba(var(--accent-rgb), 0.5); }

/* ============================================================
 * 防长按存图（iOS 专治）
 * iOS Safari 的「保存到照片」菜单不走 contextmenu 事件，JS 拦不住；
 * 它认的是 -webkit-touch-callout，而且只对 <img> 这类可命中的元素弹。
 * 所以两手一起上：关掉 callout，再让图片本身不接收指针事件——
 * 长按落到底下的 div 上，系统就没有「这是一张图」可认了。
 * ⚠ 这挡的是「顺手保存」。图片 URL 还是明文的，会用开发者工具的人照样拿得到；
 *   真要防得把水印烧进图里。
 * ============================================================ */

#game, #game * {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

#story-bg, #story-video, .portrait-slot, #ending-cg, #ending-cg-bg,
.pw-card img, #gift-img, #ambience, #grade, #fx-layer {
  pointer-events: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
}

@media (max-aspect-ratio: 1/1) {
  #boot-screen {
    padding: calc(9vh + env(safe-area-inset-top, 0px)) 6vw
      calc(11vh + env(safe-area-inset-bottom, 0px)) 6vw;
    padding: calc(9dvh + env(safe-area-inset-top, 0px)) 6vw
      calc(11dvh + env(safe-area-inset-bottom, 0px)) 6vw;
  }
  /* 内置浏览器的底栏会盖住最后一个按钮，单独再垫一段 */
  #boot-agree { padding-bottom: 3vh; }
  #agree-go, #boot-go { margin-bottom: 2vh; }
}

@media (max-aspect-ratio: 1/1) {
  /* 竖屏的画面区又扁又宽，立绘就贴在左右两侧——暗角必须收得比横屏更靠外，
   * 不然两个人正好站在压暗的区域里，看着就是「都黑」 */
  #grade { --vig-core: 66%; --vig-mid: 88%; }
}

/* 竖屏下「迷途旅程」跟着照片排下来，居中靠 margin auto，动画就不能再带 translateX */
@keyframes atlasFloatFlow {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(5px); }
}
@keyframes atlasNudgeFlow {
  0%, 100% { transform: translateY(0) scale(1); }
  30% { transform: translateY(-12px) scale(1.09); }
  55% { transform: translateY(0) scale(1); }
  72% { transform: translateY(-5px) scale(1.03); }
}

/* ---------- 首页 LOGO：中文一张、其余语言一张；图没放就退回文字 ---------- */

#title-logo { line-height: 1; }

/* ────────── LOGO 上方那盏来回摇的灯 ──────────
 * 一颗吊着的裸灯泡在 LOGO 上方轻轻摆，光池跟着扫过来扫过去。
 * 三件事必须同时发生，缺一件就假：
 *   ① 光池摆动 —— transform-origin 定在元素上方，rotate 就是钟摆；
 *   ② 亮度跟着变 —— 摆到正中离得最近最亮，两端最暗；
 *   ③ LOGO 自己的投影朝反方向甩 —— 光在左，影子就在右。
 * 三个动画同周期 6.2s，ease-in-out + alternate 才有钟摆两端「顿一下」的手感。
 * ────────────────────────────────────────── */
#title-logo {
  position: relative;
  isolation: isolate;   /* 让下面 z-index:-1 的光池只压在自己身上 */
}

#title-logo::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: 50%;
  top: -85%;
  width: 200%;
  height: 280%;
  margin-left: -100%;
  /* 灯泡打下来的光池：芯是冷白，边缘化进蓝紫。
   * ⚠ 椭圆必须整个落在这个盒子里——只要有一边碰到盒子边缘，
   *   就会被裁出一条直的硬边，看起来像贴了个梯形色块。
   *   这里圆心在 34%、半径 30%，纵向占 4%~64%，四边都留了余量。 */
  background:
    radial-gradient(ellipse 20% 30% at 50% 34%,
      rgba(228, 241, 255, 0.36) 0%,
      rgba(152, 182, 255, 0.22) 30%,
      rgba(142, 92, 255, 0.12) 56%,
      transparent 76%);
  transform-origin: 50% 2%;
  animation: bulbSwing 6.2s ease-in-out infinite alternate,
             bulbGlow  6.2s ease-in-out infinite;
  pointer-events: none;
}

@keyframes bulbSwing {
  from { transform: rotate(-8.5deg); }
  to   { transform: rotate(8.5deg); }
}
@keyframes bulbGlow {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1; }
}

#logo-img {
  /* 视觉权重仅次于照片：这是首页的主角，不能比按钮还小 */
  display: block;
  width: auto;
  /* 横屏：宽度可以到左栏满，但别超过右边那张照片（约 610 宽） */
  max-width: min(100%, 540px);
  max-height: clamp(64px, 24cqh, 178px);
  margin: 0 auto;
  animation: logoLit 6.2s ease-in-out infinite alternate;
}

/* 影子甩到光的反面，受光那侧带一点冷色边光 */
@keyframes logoLit {
  from {
    filter: drop-shadow(7px 9px 16px rgba(0, 0, 0, 0.78))
            drop-shadow(-3px -3px 12px rgba(150, 190, 255, 0.42));
  }
  to {
    filter: drop-shadow(-7px 9px 16px rgba(0, 0, 0, 0.78))
            drop-shadow(3px -3px 12px rgba(180, 150, 255, 0.42));
  }
}

#logo-img.hidden { display: none; }
#title-logo.has-logo .logo-text { display: none; }

@media (max-aspect-ratio: 1/1) {
  /* 竖屏：宽度和照片墙取齐 */
  #logo-img { max-width: min(94%, 420px); max-height: 16vh; }
}

/* ---------- 按钮手感：悬停轻抬、按下沉一下，配合合成的闷响 ---------- */

.btn-main, .btn-sub, .btn-danger, #choices button,
.ending-buttons button, #lang-btn, #btn-bgm, #x-link, .achv-row.got {
  transition: transform 0.09s cubic-bezier(0.3, 0.8, 0.4, 1),
              filter 0.16s ease, background 0.16s ease,
              border-color 0.16s ease, box-shadow 0.16s ease;
}

/* 只给真鼠标：触屏上 hover 会黏住不放 */
@media (hover: hover) {
  .btn-main:hover, .btn-danger:hover { filter: brightness(1.08); }
  .btn-sub:hover, #lang-btn:hover, #btn-bgm:hover {
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
  }
  #x-link:hover { filter: brightness(1.15); }
}

/* 按下去：整块沉 1px 再压暗一点，松手弹回——和那记闷响对上 */
.btn-main:active, .btn-sub:active, .btn-danger:active,
#choices button:active, .ending-buttons button:active,
#lang-btn:active, #btn-bgm:active, #x-link:active, .achv-row.got:active {
  transform: translateY(1px) scale(0.985);
  filter: brightness(0.9);
}

#choices button:active { transform: translateX(4px) translateY(1px) scale(0.99); }

/* 转场热区和定格那颗按钮本来就有自己的按下动效（.tapped），别叠上通用的那套。
 * ⚠ 但绝不能写 transform: none —— #transit-go 的居中就是靠 translate(-50%,-50%) 做的
 *   （竖屏是 translateX(-50%)），清掉 transform 等于当场取消居中，
 *   一按就往右下滑掉半个身位，松手再滑回来。而且它本来就不在上面那条
 *   通用 :active 的选择器列表里，压根不需要中和 transform。 */
#transit-go:active, #moment-go:active { filter: none; }

@media (prefers-reduced-motion: reduce) {
  .btn-main:active, .btn-sub:active, .btn-danger:active,
  #choices button:active, .ending-buttons button:active { transform: none; }
}

/* ---------- 竖屏：所有贴边的控件都往里收，别蹭到屏幕边和系统 UI ---------- */

@media (max-aspect-ratio: 1/1) {
  /* 左上角的语言 + 音乐：离边至少一指宽，刘海/状态栏再往下让 */
  #lang-pick {
    top: calc(2.2vh + env(safe-area-inset-top, 0px));
    top: calc(2.2dvh + env(safe-area-inset-top, 0px));
    left: calc(5% + env(safe-area-inset-left, 0px));
    gap: 8px;
  }
  #lang-btn { padding: 1vh 3.5vw; font-size: 13px; }
  #lang-pick #btn-bgm { width: 40px; }
  #lang-menu { left: 0; min-width: 46vw; }

  /* 标题区跟着让开更多，免得被上面那排压住 */
  .title-inner { padding-top: calc(9.5vh + env(safe-area-inset-top, 0px)); }

  /* 迷途旅程：跟在照片后面，但上下都留出呼吸，不贴屏幕底 */
  #atlas-toggle {
    margin: 3.2vh auto calc(4vh + env(safe-area-inset-bottom, 0px));
    margin: 3.2dvh auto calc(4dvh + env(safe-area-inset-bottom, 0px));
    padding: 0.6vh 8vw 1vh;
    padding: 0.6dvh 8vw 1dvh;
  }

  /* 抽屉拉起来时，里面的内容也别顶到底部 home 条 */
  #atlas-body { padding-bottom: calc(3vh + env(safe-area-inset-bottom, 0px)); }
}

/* ---------- 左上角那一组：语言 / 音乐 / 碎碎念 用同一套外观 ---------- */

#lang-pick #btn-notes {
  display: flex;
  align-items: center;
  padding: 0.7cqh 1.6cqh;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 0;
  background: rgba(10, 11, 18, 0.55);
  color: #cfc9bc;
  font-family: inherit;
  font-size: clamp(10px, 1.6cqh, 13px);
  letter-spacing: 0.08em;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background 0.15s ease, color 0.15s ease;
}
#lang-pick #btn-notes:hover { color: var(--accent); background: rgba(24, 26, 38, 0.85); }

@media (max-aspect-ratio: 1/1) {
  /* 顶上这三个再往下让一截，离状态栏/刘海远一点 */
  #lang-pick {
    top: calc(4.5vh + env(safe-area-inset-top, 0px));
    top: calc(4.5dvh + env(safe-area-inset-top, 0px));
    left: calc(6% + env(safe-area-inset-left, 0px));
  }
  #lang-pick #btn-notes { padding: 1vh 3.2vw; font-size: 13px; }
  /* 标题区跟着再让 */
  .title-inner { padding-top: calc(12vh + env(safe-area-inset-top, 0px)); }
}

/* ============================================================
 * 矮屏兜底（竖屏且高度 ≤ 720px：老安卓 360×640、小屏 iPhone）
 *
 * 首页是「不滚动」的一屏，竖向预算本来就紧：中文在 640px 上刚好压线，
 * 而英语/越南语/泰语的按钮要占两行，比中文多吃 36~53px，「迷途旅程」就被切出屏幕了。
 * 这里只动留白，不动 LOGO 和照片墙——那两个是主体，缩了就难看。
 * ⚠ 不能减 .title-inner 的 padding-top：那是给左上角那排按钮让的位，减了会被压住。
 * ============================================================ */

@media (max-aspect-ratio: 1/1) and (max-height: 720px) {
  .title-inner { padding-bottom: 0.6cqh; }
  .byline { margin-bottom: 1cqh; }
  .title-buttons { gap: 6px; }
  #atlas-toggle { margin: 1.2vh auto calc(1.4vh + env(safe-area-inset-bottom, 0px)); }
  .subtitle { margin: 0.6cqh 0 0.4cqh; }
  /* 按钮排成两行以后，所有语言都要再匀一点出来（原来只给长文案语言，
   * 但有存档时中文/日文也是两行，一样会把「迷途旅程」顶出屏幕） */
  .title-buttons .btn-main,
  .title-buttons .btn-sub { padding-top: 0.85cqh; padding-bottom: 0.85cqh; }
  /* 矮屏上 LOGO 也得让一点，不然上面省下来的又被它吃回去 */
  #logo-img { max-height: 14vh; }
}

/* ============================================================
 * 竖屏的「迷途旅程」重做
 *
 * 之前的问题（四条一起犯）：
 *   ① 不明显 —— 主色从橙改银之后，那个 ⌄ 和 #e6dfd2 的字都和近黑背景糊在一起；
 *   ② 像标题不像按钮 —— 无底色 + 0.26em 的字距，读起来就是一行装饰性大字；
 *   ③ 箭头等于没有 —— ⌄ 这个字形又细又飘，32px 也撑不起来；
 *   ④ 太靠下 —— margin 3.2vh/4vh 把它推到贴近屏幕底。
 *
 * 解法：并进胶带那套设计语言。黑胶带条＝可按，和「成就/继续游戏」同一卷货；
 * 箭头改成用边框画的粗人字尖并自己点头，"下面还有东西"这句话才说得出口。
 * ============================================================ */

@media (max-aspect-ratio: 1/1) {
  #atlas-toggle {
    position: static;
    transform: none;
    /* 就跟在照片下面一点，不再掉到屏幕底 */
    margin: 1.6vh auto calc(2.6vh + env(safe-area-inset-bottom, 0px));
    margin: 1.6dvh auto calc(2.6dvh + env(safe-area-inset-bottom, 0px));
    padding: 1.5vh 7vw;
    padding: 1.5dvh 7vw;
    /* 和其余次级控件同一卷黑胶带 */
    background: var(--tape-black);
    clip-path: var(--tape-tear);
    filter: var(--tape-cast);
    /* 整条不再飘——飘的交给箭头，两个都动会显得毛躁 */
    animation: none;
    flex-direction: row;
    align-items: center;
    gap: 0.75em;
    color: var(--ink);
    text-shadow: none;
  }

  #atlas-toggle .lbl {
    font-size: 17px;
    letter-spacing: 0.14em;   /* 0.26em 太散，是它把这行字变成了标题 */
    text-indent: 0.14em;
  }

  /* ⌄ 字形太细，用边框画一个实心的人字尖顶上。
   * font-size:0 把原来的字符藏掉，保留在 DOM 里是为了不动 index.html。 */
  #atlas-toggle .arw {
    display: inline-block;
    width: 10px;
    height: 10px;
    margin-top: -5px;         /* 视觉居中：旋转 45° 后重心偏下 */
    border: solid var(--ink);
    border-width: 0 2.5px 2.5px 0;
    /* ⚠ 这个 rotate 必须写在基础规则里，不能只放在 keyframes。
     * 只放 keyframes 的话，动画一停（点击后整条被 hidden 再显示的那一瞬、
     * 或 prefers-reduced-motion 直接 animation:none），
     * 它就退回没旋转的直角，看起来就是「箭头角度漂移了」。 */
    transform: rotate(45deg);
    font-size: 0;
    line-height: 0;
    color: transparent;
    animation: atlasChevron 1.6s ease-in-out infinite;
  }

  /* 首次可用时的提醒动画还留着，但别再让整条飘 */
  #atlas-toggle.nudge { animation: atlasNudgeFlow 1.05s cubic-bezier(0.3, 0.9, 0.4, 1) 4; }

  #atlas-toggle:active { filter: var(--tape-cast) brightness(1.35); }
}

/* 点头：45° 之后，往右下平移在视觉上就是正下方 */
@keyframes atlasChevron {
  0%, 100% { transform: rotate(45deg) translate(0, 0); }
  50%      { transform: rotate(45deg) translate(3px, 3px); }
}

@media (prefers-reduced-motion: reduce) {
  #atlas-toggle .arw { animation: none; }
}

/* 矮屏：胶带条本身有高度了，留白再收一档（这条必须排在上面之后才压得住） */
@media (max-aspect-ratio: 1/1) and (max-height: 720px) {
  #atlas-toggle {
    margin: 1vh auto calc(1.4vh + env(safe-area-inset-bottom, 0px));
    margin: 1dvh auto calc(1.4dvh + env(safe-area-inset-bottom, 0px));
    padding: 1.2vh 7vw;
    padding: 1.2dvh 7vw;
  }
  #atlas-toggle .lbl { font-size: 15px; }
}

/* ============================================================
 * 碎碎念（首次进入那一版）：跟首页同一盏摇曳的灯
 * 把 LOGO 也摆上去 —— 这是玩家点「安全开捆！」之后见到的第一屏，
 * 该有点仪式感，而不是一段光秃秃的文字。
 * ============================================================ */

#notes-logo-wrap {
  position: relative;
  isolation: isolate;
  /* ⚠ 必须收缩到 LOGO 本身：光锥是它宽度的 200%，
   * 铺满整栏的话横向要多撑出 300 多 px，把整屏顶出滚动条。 */
  width: fit-content;
  margin: 0 auto 1.1cqh;
}

/* 光锥：和 #title-logo::before 同一套参数，连摆动周期都对齐 */
#notes-logo-wrap::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: 50%;
  top: -85%;
  width: 200%;
  height: 280%;
  margin-left: -100%;
  background:
    radial-gradient(ellipse 20% 30% at 50% 34%,
      rgba(228, 241, 255, 0.34) 0%,
      rgba(152, 182, 255, 0.20) 30%,
      rgba(142, 92, 255, 0.11) 56%,
      transparent 76%);
  transform-origin: 50% 2%;
  animation: bulbSwing 6.2s ease-in-out infinite alternate,
             bulbGlow  6.2s ease-in-out infinite;
  pointer-events: none;
}

#notes-logo {
  display: block;
  width: auto;
  max-width: min(78%, 360px);
  max-height: clamp(46px, 14cqh, 108px);
  margin: 0 auto;
  animation: logoLit 6.2s ease-in-out infinite alternate;
}
#notes-logo.hidden { display: none; }

/* 标题这一行也跟着亮起来一点，和 LOGO 是一组 */
#boot-notes .agree-kicker {
  color: var(--ink);
  font-size: clamp(15px, 2.8cqh, 22px);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-indent: 0.16em;
  margin-bottom: 1cqh;
  text-shadow: 0 2px 18px rgba(150, 180, 255, 0.35);
}

@media (max-aspect-ratio: 1/1) {
  #notes-logo { max-width: min(72%, 300px); max-height: 11vh; }
  #notes-logo-wrap { margin-bottom: 1.2vh; }
  #boot-notes .agree-kicker { font-size: 17px; }
}

@media (prefers-reduced-motion: reduce) {
  #notes-logo-wrap::before, #notes-logo { animation: none; }
}

/* ---------- 碎碎念首屏：排版收进一个能读的栏宽 ----------
 * 之前整段跟着屏幕铺满，1400px 宽的屏上一行 90 多字，而且居中——
 * 居中的长段落每行起点都在跳，是最难读的排法。
 * 收成定宽左对齐，行高放松，整块反而更矮、更透气。 */

#boot-notes {
  width: min(92%, 880px);
}

#boot-notes .agree-intro {
  max-width: 62ch;          /* 排版上最舒服的行长 */
  margin: 0 auto 1.6cqh;
  text-align: left;
  font-size: clamp(12px, 1.85cqh, 15px);
  line-height: 1.85;
}

#boot-notes .agree-intro p + p { margin-top: 0.85em; }

/* 结尾那句「玩得愉快！」自己站一行居中，当收束 */
#boot-notes .agree-intro p:last-child {
  text-align: center;
  margin-top: 1em;
  color: var(--ink);
}

@media (max-aspect-ratio: 1/1) {
  #boot-notes { width: 100%; }
  #boot-notes .agree-intro {
    max-width: none;
    font-size: clamp(12px, 1.6vh, 15px);
    font-size: clamp(12px, 1.6dvh, 15px);
    line-height: 1.8;
  }
}

/* ============================================================
 * 加载页的 LOGO：没加载出来就整个不显示，不放任何占位文字
 * ============================================================ */

#boot-logo {
  display: block;
  width: auto;
  max-width: min(72%, 380px);
  max-height: clamp(52px, 16cqh, 130px);
  margin: 0 auto 3cqh;
  filter: drop-shadow(0 6px 26px rgba(150, 190, 255, 0.35));
}
#boot-logo.hidden { display: none; }

@media (max-aspect-ratio: 1/1) {
  #boot-logo { max-width: 66%; max-height: 12vh; margin-bottom: 2.4vh; }
}

/* ============================================================
 * 「生成你的专属迷途」
 * ============================================================ */

/* ⚠ 这颗按钮原来是「列表最后一个块级元素」，排在滚动区下面。
 * 结果就是：列表越长它越靠下，手机上正好落在浏览器底栏/home 条那一带，点不到；
 * 电脑上也得先把整个列表滚到底才看得见。
 * 改成**悬浮**：绝对定位钉在面板右下角，列表照常滚，它一直在那儿。
 * 右侧本来就是空的（每一行都是左对齐的站点名 + 结局标签），飘在那里不压任何内容。 */
#btn-share-achv,
#btn-share-atlas {
  position: absolute;
  z-index: 4;
  right: 3.4cqh;
  bottom: 3cqh;
  margin: 0;
  flex: none;
  width: auto;
  font-size: clamp(12px, 1.85cqh, 16px);
  padding: 1.15cqh 2.6cqh;
  /* 悬在滚动内容之上，得自己带一层影子才「浮」得起来；
   * clip-path 会把 box-shadow 剪掉，所以只能用 drop-shadow（见 .btn-main） */
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.75));
}

/* 悬浮以后要给滚动区垫出一块，免得最后一行被压在按钮底下读不到 */
#atlas-body { padding-bottom: 9cqh; }
#achv-body { padding-bottom: 9cqh; }

#share-view {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2cqh;
  padding: 3cqh 4%;
  background: rgba(4, 5, 8, 0.94);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
#share-view.hidden { display: none; }

/* 长图很高，给它一个可滚动的框，别把按钮顶出屏幕 */
#share-frame {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.7);
}
#share-frame img {
  display: block;
  width: auto;
  max-width: min(88vw, 380px);
}

/* 生成期间先占住位置，不然按钮会往上跳一下 */
#share-view.busy #share-frame {
  min-height: 40cqh;
  min-width: min(60vw, 240px);
  background: repeating-linear-gradient(114deg,
    rgba(255, 255, 255, 0.04) 0 8px, rgba(255, 255, 255, 0.01) 8px 16px);
}

#share-btns {
  display: flex;
  gap: 10px;
  align-items: stretch;
  flex: none;
  flex-wrap: wrap;
  justify-content: center;
  max-width: 100%;
}
#share-btns .btn-main, #share-btns .btn-sub {
  margin: 0;
  white-space: nowrap;      /* 「保存 / 分享」断成两行很难看 */
  padding: 1.1cqh 2.4cqh;
  font-size: clamp(12px, 1.8cqh, 15px);
}

@media (max-aspect-ratio: 1/1) {
  #share-frame img { max-width: min(84vw, 340px); }
  /* ⚠ 竖屏抽屉是贴着屏幕底的，底边那一条会被 home 条 / 浏览器底栏吃掉，
   * 所以悬浮位置必须再往上抬一个 safe-area，否则照样点不到。 */
  #btn-share-atlas, #btn-share-achv {
    right: 4vw;
    bottom: calc(2.6vh + env(safe-area-inset-bottom, 0px));
    bottom: calc(2.6dvh + env(safe-area-inset-bottom, 0px));
    padding: 1.25vh 5vw;
    padding: 1.25dvh 5vw;
    font-size: clamp(12px, 1.75vh, 15px);
  }
  #atlas-body {
    padding-bottom: calc(9vh + env(safe-area-inset-bottom, 0px));
    padding-bottom: calc(9dvh + env(safe-area-inset-bottom, 0px));
  }
  #achv-body { padding-bottom: 9vh; padding-bottom: 9dvh; }
}

.share-err {
  padding: 6cqh 8%;
  text-align: center;
  color: var(--danger);
  font-size: clamp(13px, 2cqh, 17px);
  line-height: 1.9;
}
.share-err span { color: #8d95a2; font-size: 0.8em; word-break: break-all; }

/* ============================================================
 * 游戏内 HUD：左上角的声音 / 回首页
 *
 * 定位的全部难点就一句话：**必须待在画面外**。
 * 所以它不在 #game 里（那是个 overflow:hidden 的画框，进去就只能压着画），
 * 而是 fixed 在页面上，再用和 #game 一模一样的尺寸公式反推出画框的位置，
 * 贴着画框顶边的**外侧**摆。
 *
 *   画框宽 = min(100vw, 100dvh*16/9, 1200px)
 *   画框高 = min(100dvh, 100vw*9/16, 675px)
 *   上留白 = (100dvh - 画框高) / 2      ← HUD 就住在这条留白里
 *
 * 留白不够高（视口正好接近 16:9）时 max() 会把它按回视口顶端，
 * 那种极端比例下顶多蹭掉画面最上面十几像素，是唯一的退让。
 *
 * ⚠ 名字必须叫 #game-hud，不能叫 #hud —— 文件上面还留着一条早年
 *   探索地图模式的 `#hud { pointer-events: none }`（那个界面已经下线，
 *   规则还在）。同名的话那句 pointer-events 会继承下来，按钮看得见、
 *   点不动，而且 elementFromPoint 之外查不出来。
 * ============================================================ */

#game-hud {
  --hud-gw: min(100vw, calc(100dvh * 16 / 9), 1200px);
  --hud-gh: min(100dvh, calc(100vw * 9 / 16), 675px);
  position: fixed;
  z-index: 45;
  pointer-events: auto;   /* 显式写死：这东西的全部意义就是能点 */
  display: flex;
  gap: 8px;
  left: max(8px, calc((100vw - var(--hud-gw)) / 2));
  top: max(8px, calc((100dvh - var(--hud-gh)) / 2 - 44px));
  animation: hudIn 0.5s ease both;
}
#game-hud.hidden { display: none; }

@keyframes hudIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; } }

#game-hud button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 0;
  background: rgba(10, 11, 18, 0.62);
  color: #b9b3a6;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}

#game-hud button svg { width: 19px; height: 19px; fill: currentColor; display: block; }
#game-hud button:hover {
  color: var(--accent);
  background: rgba(24, 26, 38, 0.9);
  border-color: rgba(var(--accent-rgb), 0.5);
}
#game-hud button:active { transform: scale(0.94); }

/* 静音状态沿用 #btn-bgm 那套：容器加 .off，两个图标互换 */
#game-hud-bgm .ico-off { display: none; }
#game-hud-bgm.off .ico-on { display: none; }
#game-hud-bgm.off .ico-off { display: block; }
#game-hud-bgm.off { color: #6d6a75; }

/* 又扁又宽的窗口（比 16:9 还宽、还不到 764px 高）：画框顶上的留白只剩十几像素，
 * 硬塞会压到画面。这种比例下**左右**的留白反而很宽，改成竖着排、挪进左边那条。 */
@media (min-aspect-ratio: 16/9) and (max-height: 764px) {
  #game-hud {
    flex-direction: column;
    gap: 6px;
    top: max(8px, calc((100dvh - var(--hud-gh)) / 2 + 8px));
    left: max(6px, calc((100vw - var(--hud-gw)) / 2 - 42px));
  }
}

@media (max-aspect-ratio: 1/1) {
  /* 竖屏：画框就是整块屏幕，但画面只占中间那条 16:9 的带子，
   * 上面那截黑边（--stack-top 高）本来就是空的，HUD 正好住进去。 */
  #game-hud {
    left: 4vw;
    top: max(calc(env(safe-area-inset-top, 0px) + 10px),
             calc(var(--stack-top) - 50px));   /* 38px 的按钮 + 12px 空隙 */
    gap: 10px;
  }
  #game-hud button { width: 38px; height: 38px; }
  #game-hud button svg { width: 21px; height: 21px; }
}

/* 全屏按钮：外观跟左上角那组一致（图标切换沿用 #btn-bgm 的 on/off 机制） */
#btn-fs {
  display: flex;
  align-items: center;
  padding: 0.7cqh 1.2cqh;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 0;
  background: rgba(10, 11, 18, 0.55);
  color: #cfc9bc;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: color 0.15s ease, background 0.15s ease;
}
#btn-fs svg { width: 18px; height: 18px; fill: currentColor; display: block; }
#btn-fs .ico-off { display: none; }
#btn-fs.off .ico-on { display: none; }
#btn-fs.off .ico-off { display: block; }
#btn-fs:hover { color: var(--accent); background: rgba(24, 26, 38, 0.85); }
#btn-fs.hidden { display: none; }

@media (max-aspect-ratio: 1/1) {
  #btn-fs { padding: 1vh 3vw; }
  #btn-fs svg { width: 16px; height: 16px; }
}
