@charset "utf-8";

/* ============================================================================
   奇遇动物城 官网 · 移动端长页
   设计源：Figma 38:722（qie-1、首页.psd 移动版）—— 750 宽 × 6737 高的整页设计画布，
   纵向依次为 头图 / 下一站是动物城 / 谁是你的新室友 / 奇遇，无限可能 / 动物城头条 / 底部信息。

   适配模型：1 设计 px = --u = 100/750 vw。页面内所有尺寸与坐标都写成 calc(设计px * var(--u))，
   设计稿的像素值原样保留在代码里，便于逐条对回 Figma。不用 CSS scale，不用固定 px 宽度。

   文字：设计稿标注 Inter Regular，但正文内容是中文、Inter 无中文字形；
   现按业务方提供的「资源圆体 CN Bold」渲染（见下方 @font-face，与 PC 端同一份字库），
   系统黑体只作兜底；字距只落设计显式给出的那一处（公众号说明 -0.8px）。
   ========================================================================== */
:root {
  --u: 0.13333333vw; /* 1 设计 px */
  --ease-out: cubic-bezier(.22, 1, .36, 1);
}

/* ── 正文字体：资源圆体 CN Bold（用户提供的字体包） ─────────────────────
   页面上所有由 CSS 渲染的文字都走它；标题 / 按钮 / 标语那些是设计切图，本来就带字形。
   字库按本站文案 + GB2312 常用字裁过子集（原包 13.9MB → 1.1MB），运营改文案也不会缺字；
   font-display: swap 保证字体没到位时先用系统字显示，不留空白。 */
@font-face {
  font-family: 'Resource Han Rounded CN';
  src: url('../font/resource-han-rounded-cn-bold.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
a { text-decoration: none; color: inherit; }
html, body { width: 100%; overflow-x: hidden; }
/* 移动端不露系统滚动条：真机上它本来就自动隐藏，桌面预览里那条侧边灰条纯属干扰。
   只是不画滚动条，滚动本身照常。 */
html { scrollbar-width: none; -ms-overflow-style: none; }
html::-webkit-scrollbar, body::-webkit-scrollbar { width: 0; height: 0; display: none; }
body {
  position: relative;
  font-family: 'Resource Han Rounded CN', "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  background: #fbeee4;
  -webkit-text-size-adjust: 100%;
}
/* 整页当成「界面」而不是「文章」：双击或长按不再选中文字、不再弹出蓝色选区，
   点按也不留系统的高亮方块；输入框里照常可以选中和编辑 */
body {
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
input, textarea, [contenteditable] {
  -webkit-user-select: text;
  user-select: text;
}
/* 点过的链接 / 按钮不画浏览器默认的焦点框：点开一条资讯再按 Esc 关弹框（或任何键盘操作）后，
   刚点过的那一项会被系统描上一圈黑框。全站可点元素都有自己的悬停 / 按下反馈，不再叠这层描边 */
:focus, :focus-visible { outline: none; }
img { display: block; max-width: none; }
button { border: 0; background: none; font: inherit; color: inherit; }
[hidden] { display: none !important; }

/* 仅供读屏与搜索引擎，不参与视觉 */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================================
   长页画布
   ========================================================================== */
#m-root {
  position: relative;
  width: 100%;
  height: calc(6294 * var(--u)); /* 页脚中英文统一后，整页高度也统一 */
  overflow: hidden; /* 设计里背景与角色本来就跨屏出血，超出画布的部分裁掉 */
}

/* 每屏＝画布上的一段，内部一律设计稿 1:1 坐标。刻意不裁剪，靠 DOM 先后顺序自然叠压。 */
.m-sec { position: absolute; left: 0; width: 100%; }
.m-sec > * { position: absolute; }
/* 「整块即一张图」的容器才让图撑满 —— 限定 :only-child，避免一容器两图时把小图拉大 */
.m-sec > div > img:only-child,
.m-sec > a > img:only-child,
.m-sec > button > img:only-child { width: 100%; height: 100%; }

#hero     { top: 0;                     height: calc(1287 * var(--u)); }
#map      { top: calc(1287 * var(--u)); height: calc(1126 * var(--u)); }
#friend   { top: calc(2413 * var(--u)); height: calc(1365 * var(--u)); }
#gameplay { top: calc(3778 * var(--u)); height: calc(790 * var(--u)); }
#news     { top: calc(4568 * var(--u)); height: calc(1306 * var(--u)); }
#footer   { top: calc(5874 * var(--u)); height: calc(420 * var(--u)); }

/* ============================================================================
   导航栏（吸顶常驻，坐标是视口坐标）
   ========================================================================== */
.m-nav {
  position: fixed;
  left: 0; top: 0;
  width: 100%;
  height: calc(91 * var(--u));
  z-index: 100;
  /* 与导航底图上缘同色：底图不透明，这层平时看不见；
     它是给刘海屏顶部状态栏取色用的（新版 Safari 取贴顶固定元素的底色，见 m/index.html 的 theme-color 说明） */
  background-color: #008ee4;
}
.m-nav > * { position: absolute; }
.m-nav__bg { left: 0; top: 0; width: 100%; height: calc(91 * var(--u)); }
.m-nav__logo { left: calc(51 * var(--u)); top: calc(8 * var(--u)); width: calc(130 * var(--u)); height: calc(67 * var(--u)); }
.m-nav__logo img { width: 100%; height: 100%; filter: drop-shadow(0 2px 2px rgba(4, 0, 0, .25)); }

/* 右侧三个图标「音乐 · 语言 · 分享」等间距排开，音乐在最左（语言按钮落位见 i18n_mobile.css） */
.m-nav__bgm { left: calc(529 * var(--u)); top: calc(22 * var(--u)); width: calc(38 * var(--u)); height: calc(41 * var(--u)); }
/* 两枚图标同位重叠，按开关状态切换显示。落点按**图形可见范围**的中心对齐，不照搬设计给的偏移：
   两张切图的透明边不一样，照设计落时播放态的图形中心在 (547.5, 40)、关闭态在 (544, 44)，
   一开音乐图标就往右上跳一下。两枚统一落到 (544, 44)，与语言、分享两个图标同一条水平线。 */
.m-nav__bgm-off { position: absolute; left: 0;                    top: calc(4 * var(--u)); width: calc(30 * var(--u)); height: calc(37 * var(--u)); }
.m-nav__bgm-on  { position: absolute; left: calc(0.5 * var(--u)); top: calc(4 * var(--u)); width: calc(29 * var(--u)); height: calc(37 * var(--u)); }
.m-nav__bgm .m-nav__bgm-on { display: none; }
.m-nav__bgm[aria-pressed="true"] .m-nav__bgm-off { display: none; }
.m-nav__bgm[aria-pressed="true"] .m-nav__bgm-on { display: block; }

.m-nav__share-btn { left: calc(673 * var(--u)); top: calc(26 * var(--u)); width: calc(28 * var(--u)); height: calc(37 * var(--u)); }
.m-nav__share-btn img { width: 100%; height: 100%; }

/* 分享面板：默认收起，整组从右侧滑出。

   横屏（以及任何矮视口）下的适配：面板内部尺寸全部是 --u 的倍数，而 --u 只跟宽度走，
   手机横过来宽度翻倍 → 面板也跟着翻倍，576 设计px 高的面板在 393px 高的屏幕里放不下，
   下面几个渠道会掉到屏幕外，且面板是固定定位、滚不到 —— 就是「横屏看不全社媒」。
   这里把面板自己的 --u 改成「按宽算」和「按高算」取小者：竖屏取前者（与原来完全一致），
   矮屏取后者、整组等比缩到放得下。
   缩小后子元素的 left/top 也会跟着缩，面板会往左上跑，所以用 left/top 把这部分差值补回去：
   两条式子在竖屏都恰好等于 0，竖屏不受任何影响。 */
.m-share {
  position: absolute;
  --u: min(0.13333333vw, 0.12vh);
  left: calc(100vw - 750 * var(--u));
  /* 常数 = 面板的设计上沿（贴着导航栏底边 91）：横屏时 --u 变小，这一式把面板锚回同一位置 */
  top: calc(91 * 0.13333333vw - 91 * var(--u));
  width: 100%; height: 0;
  opacity: 0;
  visibility: hidden;
  transform: translateX(calc(120 * var(--u)));
  transition: opacity .28s var(--ease-out), transform .32s var(--ease-out), visibility .32s;
}
.m-share.is-open { opacity: 1; visibility: visible; transform: none; }
.m-share > * { position: absolute; }
/* 面板上沿贴住导航栏底边（导航高 91）：原来从 95 起，与导航之间空着 4 */
.m-share__panel { left: calc(631 * var(--u)); top: calc(91 * var(--u)); width: calc(119 * var(--u)); height: calc(576 * var(--u)); }
.m-share__item img { width: 100%; height: 100%; }
/* 图标本身很扁（最矮的只有 30 设计px），把点按区域上下撑开到够点；
   用 --u 写，横屏缩小后依然够得着，竖屏也不会和相邻渠道的热区粘连 */
.m-share__item::after { content: ''; position: absolute; inset: calc(-8 * var(--u)) calc(-6 * var(--u)); }
.m-share__item--xhs       { left: calc(651 * var(--u)); top: calc(124 * var(--u)); width: calc(81 * var(--u)); height: calc(30 * var(--u)); }
.m-share__item--douyin    { left: calc(672 * var(--u)); top: calc(188 * var(--u)); width: calc(37 * var(--u)); height: calc(41 * var(--u)); }
.m-share__item--channel-x { left: calc(675 * var(--u)); top: calc(262 * var(--u)); width: calc(33 * var(--u)); height: calc(39 * var(--u)); }
.m-share__item--qq        { left: calc(674 * var(--u)); top: calc(334 * var(--u)); width: calc(35 * var(--u)); height: calc(38 * var(--u)); }
.m-share__item--bilibili  { left: calc(672 * var(--u)); top: calc(404 * var(--u)); width: calc(37 * var(--u)); height: calc(34 * var(--u)); }
.m-share__item--wechat    { left: calc(670 * var(--u)); top: calc(471 * var(--u)); width: calc(42 * var(--u)); height: calc(35 * var(--u)); }
.m-share__item--tap       { left: calc(661 * var(--u)); top: calc(538 * var(--u)); width: calc(60 * var(--u)); height: calc(33 * var(--u)); }
.m-share__item--weibo     { left: calc(671 * var(--u)); top: calc(603 * var(--u)); width: calc(42 * var(--u)); height: calc(35 * var(--u)); }

/* ── 横屏提示 ────────────────────────────────────────────────────────
   整站是按竖屏设计的，横过来所有固定浮层都放不下。这里在横屏时整屏盖一层黑底 +
   一个来回转的手机图标（按需求不放文案），把人引导回竖屏。

   两个显示条件缺一不可：
   1) orientation: landscape —— 真的横过来了；
   2) min-aspect-ratio: 12/10 —— 画面明显宽于高才算。平板、接近方形的视口不该被盖住。
   另外填表时不显示：安卓上输入法弹起会把视口高度压掉一截、被判成横屏，
   正打字时突然黑屏是更糟的体验（这一层由业务 JS 在输入框获得焦点时开关）。
   ------------------------------------------------------------------- */
.m-orient {
  display: none;
  position: fixed;
  left: 0; top: 0; right: 0; bottom: 0;
  background: #000;
  z-index: 9997; /* 压过预约弹窗、资讯弹框等所有浮层 */
}
@media all and (orientation: landscape) and (min-aspect-ratio: 12/10) {
  .m-orient { display: block; }
}
.is-inputing .m-orient { display: none; }

/* 居中和旋转分成两层做：两者都要用 transform，合在一个元素上会互相覆盖 */
.m-orient__content {
  position: absolute;
  left: 0; top: 50%;
  width: 100%;
  transform: translateY(-50%);
  text-align: center;
}
/* 图标起手就是横放的（rotate(90deg)），动画里转正再转回去，演示「把手机转回竖屏」 */
.m-orient__icon {
  display: inline-block;
  width: 67px; height: 109px;
  transform: rotate(90deg);
  animation: m-orient-rotate 1.5s ease-in-out infinite;
}
@keyframes m-orient-rotate {
  10%      { transform: rotate(90deg); }
  50%, 60% { transform: rotate(0deg); }
  90%      { transform: rotate(90deg); }
  100%     { transform: rotate(90deg); }
}

/* 公众号二维码：点微信图标在它左侧弹出 */
.m-qr {
  position: absolute;
  left: 0; top: 0;
  width: 100%; height: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity .22s var(--ease-out), visibility .22s;
}
.m-qr.is-open { opacity: 1; visibility: visible; }
.m-qr > * { position: absolute; }
.m-qr__card { left: calc(513 * var(--u)); top: calc(414 * var(--u)); width: calc(148 * var(--u)); height: calc(150 * var(--u)); }
.m-qr__code { left: calc(520 * var(--u)); top: calc(421 * var(--u)); width: calc(119 * var(--u)); height: calc(119 * var(--u)); }
/* 两张卡（微信 / QQ 群）除竖向落点外完全一样：各自对齐自己那枚图标的中线 —— 
   微信图标在 471、QQ 图标在 334，卡高 150，所以卡顶分别落在 414 与 278。 */
.m-qr--qq .m-qr__card    { top: calc(278 * var(--u)); }
.m-qr--qq .m-qr__code    { top: calc(285 * var(--u)); }
.m-qr--qq .m-qr__caption { top: calc(403 * var(--u)); }
.m-qr__caption {
  left: calc(581 * var(--u)); top: calc(539 * var(--u));
  transform: translateX(-50%);
  font-size: calc(16 * var(--u));
  line-height: calc(16.129 * var(--u));
  letter-spacing: calc(-0.8 * var(--u));
  color: #fd7fa0;
  white-space: nowrap;
}

/* ============================================================================
   第 1 屏 · 头图
   ========================================================================== */
/* KV 按设计原位：(-1606,-398) 4449×2830，左右出血由 #m-root 裁掉 */
.m-hero__kv {
  left: calc(-1606 * var(--u)); top: calc(-398 * var(--u));
  width: calc(4449 * var(--u)); height: calc(2830 * var(--u));
  background-size: 100% 100%;
  background-repeat: no-repeat;
  pointer-events: none;
}
/* KV 动图：整块盖住静态 KV。静态 KV 那张按 4449×2830 大幅外扩铺，真正露出来的只有
   头图这一屏（750×1287），视频就按这一屏给，cover 裁掉的是竖版素材下沿约 3%。
   起手透明，首帧真的画出来（playing）才淡入——否则解码前那一下黑场会闪。 */
.m-hero__kv-video {
  left: 0; top: 0;
  /* 高度给到 1350 而不是头图那一屏的 1287：静态 KV 是张大幅外扩的底图，
     它在头图下沿之外还会从第 2 屏背景的斜切透明边里透出来一条
     （第 2 屏背景要到设计 y=1344 才完全不透明）。动图只铺到 1287 的话，
     那条缝里露的还是静态 KV，和上面的动图对不上——所以一路盖到 1344 之下。
     1350 仍在素材自身比例内，横向只裁掉约 9 设计 px，取景几乎不变。 */
  width: 100%; height: calc(1350 * var(--u));
  object-fit: cover;
  object-position: center top;
  pointer-events: none;
  opacity: 0;
  transition: opacity .45s ease;
}
.m-hero__kv-video.is-playing { opacity: 1; }

.m-hero__slogan { left: calc(83 * var(--u));  top: calc(120 * var(--u));  width: calc(610 * var(--u)); height: calc(293 * var(--u)); pointer-events: none; }
.m-hero__play   { left: calc(316 * var(--u)); top: calc(442 * var(--u));  width: calc(114 * var(--u)); height: calc(111 * var(--u)); }
/* 头图只放「立即预约」一颗按钮：按切图自身尺寸落位（492×128），横向居中、
   竖向中心与换图前保持一致；英文版按钮仍是旧尺寸切图，落点在 i18n_mobile.css 里单独给 */
.m-hero__btn--cta { left: calc(129 * var(--u)); top: calc(1145.5 * var(--u)); width: calc(492 * var(--u)); height: calc(128 * var(--u)); }
.m-hero__btn:active img, .m-hero__play:active img { transform: scale(.96); }

/* ============================================================================
   第 2 屏 · 下一站是动物城
   ========================================================================== */
.m-s1__bg       { left: 0;                    top: 0;                    width: calc(750 * var(--u)); height: calc(1641 * var(--u)); pointer-events: none; }
.m-s1__polaroid { left: calc(57 * var(--u));  top: calc(214 * var(--u)); width: calc(631 * var(--u)); height: calc(445 * var(--u)); pointer-events: none; }
.m-s1__title    { left: calc(81 * var(--u));  top: calc(103 * var(--u)); width: calc(607 * var(--u)); height: calc(124 * var(--u)); pointer-events: none; }
.m-s1__char     { left: calc(46 * var(--u));  top: calc(185 * var(--u)); width: calc(678 * var(--u)); height: calc(685 * var(--u)); pointer-events: none; }
/* 景点卡轮播：与 PC 共用同一套整切图，一屏只露一张，切换用淡入淡出 */
.m-s1__card { left: calc(49 * var(--u)); top: calc(606 * var(--u)); width: calc(664 * var(--u)); height: calc(472 * var(--u)); overflow: hidden; z-index: 0; }
.m-s1__card .swiper-slide { width: 100%; height: 100%; }
.m-s1__card .swiper-slide img { display: block; width: 100%; height: 100%; object-fit: contain; }
.m-s1__arrow--left  { left: calc(53 * var(--u));  top: calc(755 * var(--u)); width: calc(48 * var(--u)); height: calc(48 * var(--u)); }
.m-s1__arrow--right { left: calc(650 * var(--u)); top: calc(754 * var(--u)); width: calc(49 * var(--u)); height: calc(49 * var(--u)); }
.m-s1__arrow:active img { transform: scale(.9); }

/* ============================================================================
   第 3 屏 · 谁是你的新室友
   —— 整屏跟着选中的室友换肤，七块素材全部随人替换；
      介绍 / 立绘 / 装饰这三块每位的落位与尺寸都不同，坐标表在 js/home_mobile.js 的 S2_LAYOUT。
   ========================================================================== */
.m-s2__bg    { left: calc(-509 * var(--u)); top: 0;                     width: calc(1891 * var(--u)); height: calc(1627 * var(--u)); pointer-events: none; }
.m-s2__title { left: calc(71 * var(--u));   top: calc(95 * var(--u));   width: calc(621 * var(--u));  height: calc(176 * var(--u)); pointer-events: none; }
.m-s2__deco  { left: calc(55 * var(--u));   top: calc(453 * var(--u));  width: calc(689 * var(--u));  height: calc(685 * var(--u)); pointer-events: none; }
.m-s2__paw   { left: calc(71 * var(--u));   top: calc(697 * var(--u));  width: calc(92 * var(--u));   height: calc(82 * var(--u)); pointer-events: none; }
/* 介绍 / 立绘 / 名字整组一起淡出下沉、换完再浮起：透明度挂在这一层，组内三块仍互相遮挡，
   不会在半透明那几帧互相透出来（PC 端踩过这个坑）。容器不占位，三块各自按设计坐标定位。 */
.m-s2__detail {
  left: 0; top: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  transition: opacity .5s var(--ease-out), transform .5s var(--ease-out);
}
.m-s2__detail.is-swapping {
  opacity: 0;
  transform: translateY(calc(26 * var(--u)));
  transition: opacity .2s var(--ease-out), transform .28s var(--ease-out);
}
.m-s2__detail > div { position: absolute; }
.m-s2__detail > div > img:only-child { width: 100%; height: 100%; }
.m-s2__intro { left: calc(108 * var(--u)); top: calc(278 * var(--u));  width: calc(532 * var(--u)); height: calc(463 * var(--u)); }
.m-s2__char  { left: calc(126 * var(--u)); top: calc(701 * var(--u));  width: calc(536 * var(--u)); height: calc(993 * var(--u)); }
.m-s2__name  { left: calc(526 * var(--u)); top: calc(1103 * var(--u)); width: calc(186 * var(--u)); height: calc(144 * var(--u)); }
.m-s2__arrow--left  { left: calc(20 * var(--u));  top: calc(844 * var(--u)); width: calc(55 * var(--u)); height: calc(75 * var(--u)); z-index: 3; }
.m-s2__arrow--right { left: calc(679 * var(--u)); top: calc(843 * var(--u)); width: calc(55 * var(--u)); height: calc(76 * var(--u)); z-index: 3; }
.m-s2__arrow:active img { transform: scale(.9); }

/* ============================================================================
   第 4 屏 · 奇遇，无限可能
   ========================================================================== */
.m-s3__bg    { left: calc(-348 * var(--u)); top: 0;                    width: calc(1490 * var(--u)); height: calc(2096 * var(--u)); pointer-events: none; }
.m-s3__title { left: calc(90 * var(--u));   top: calc(139 * var(--u)); width: calc(585 * var(--u));  height: calc(125 * var(--u)); pointer-events: none; z-index: 3; }
/* 场景轮播：每张卡 = 相框 + 照片，整张一起滑（与 PC 一致）。
   轮播区横跨整屏宽，卡片从屏幕边缘滑入滑出；卡片静止时的落位与设计一致：
   相框 (53,265) 640×450，照片 (67,280) 619×420，二者都换算成相对轮播区（top 265）的坐标。
   设计里相框画在照片之下，卡内照同样顺序叠。 */
.m-s3__swiper { left: 0; top: calc(265 * var(--u)); width: calc(750 * var(--u)); height: calc(450 * var(--u)); overflow: hidden; }
.m-s3__card-frame { position: absolute; left: calc(53 * var(--u)); top: 0; width: calc(640 * var(--u)); height: calc(450 * var(--u)); }
.m-s3__card-photo { position: absolute; left: calc(67 * var(--u)); top: calc(15 * var(--u)); width: calc(619 * var(--u)); height: calc(420 * var(--u)); }
/* 相框素材的配置锚点，只供脚本取图，不显示 */
.m-s3__frame-ref { display: none !important; }
/* 轮播点：整行按图数生成并居中（设计给的整条点阵写死了当时的图数，图数一变就对不上），
   未选中那颗从设计整条里裁出的单点重复摆，选中那颗覆在当前位上滑动。 */
.m-s3__dots { left: 0; top: calc(748 * var(--u)); width: 100%; height: calc(26 * var(--u)); pointer-events: none; }
.m-s3__dots .m-dot-off {
  position: absolute; top: 0;
  width: calc(22 * var(--u)); height: calc(26 * var(--u));
  transform: translateX(-50%);
  z-index: 1;
}
/* 当前态那颗比未选中的大一圈、会压到相邻两颗上，必须恒在最上层 ——
   未选中那几颗是按图数复制出来的，DOM 顺序排在它后面，只靠先后叠压会被盖住 */
.m-s3__dots .m-dot-on {
  position: absolute; top: calc(-10 * var(--u));
  width: calc(45 * var(--u)); height: calc(43 * var(--u));
  transform: translateX(-50%);
  transition: left .25s var(--ease-out);
  z-index: 2;
}

/* ============================================================================
   第 5 屏 · 动物城头条
   ========================================================================== */
.m-s4__bg    { left: calc(-700 * var(--u)); top: 0;                    width: calc(2246 * var(--u)); height: calc(1949 * var(--u)); pointer-events: none; }
.m-s4__panel { left: calc(41 * var(--u));   top: calc(818 * var(--u)); width: calc(707 * var(--u));  height: calc(1005 * var(--u)); pointer-events: none; }
.m-s4__frame { left: calc(8 * var(--u));    top: calc(252 * var(--u)); width: calc(721 * var(--u));  height: calc(610 * var(--u)); pointer-events: none; }
.m-s4__title { left: calc(101 * var(--u));  top: calc(149 * var(--u)); width: calc(553 * var(--u));  height: calc(143 * var(--u)); pointer-events: none; z-index: 4; }
.m-s4__gallery { left: calc(32 * var(--u)); top: calc(273 * var(--u)); width: calc(659 * var(--u)); height: calc(477 * var(--u)); overflow: hidden; z-index: 2; }
/* 轮播区按相框窗口裁切：资讯图（659×477）里的画面是一块转了 3.566° 的矩形（632.95×438.49，居中，
   四角透明），裁切多边形就是这块矩形四周外扩 0.5px（留住边缘抗锯齿）。
   翻页时图片沿这个倾斜方向平移（见 home_mobile.js 资讯轮播），进出场的图不会从相框斜边外露出来 */
.m-s4__gallery { clip-path: polygon(-0.08% 8.15%, 95.93% -0.11%, 100.08% 91.85%, 4.07% 100.11%); }
.m-s4__gallery .swiper-slide img { width: 100%; height: 100%; }
.m-s4__gallery .swiper-slide { cursor: pointer; }
/* 整条点阵不挡住底下的画面，只有圆点本身接收点按（点它直接跳到对应那张） */
.m-s4__dots { left: 0; top: calc(748 * var(--u)); width: 100%; height: calc(24 * var(--u)); pointer-events: none; z-index: 3; }
.m-s4__dots .m-dot-off {
  position: absolute; top: 0;
  width: calc(15 * var(--u)); height: calc(24 * var(--u));
  transform: translateX(-50%);
  z-index: 1;
  pointer-events: auto;
  cursor: pointer;
}
/* 圆点只有 15×24 设计px，太小点不中：把点按范围四周撑开一圈，视觉不变。
   撑开量小于圆点间距（34），相邻两颗的热区不会叠在一起 */
.m-s4__dots .m-dot-off::after { content: ''; position: absolute; inset: calc(-12 * var(--u)) calc(-9 * var(--u)); }
.m-s4__dots .m-dot-on {
  position: absolute; top: calc(-1 * var(--u));
  width: calc(27 * var(--u)); height: calc(26 * var(--u));
  transform: translateX(-50%);
  transition: left .25s var(--ease-out);
  z-index: 2;
}

/* 分类栏 */
/* 胶囊底与分类文字取同一条中线：文字行框中心落在 896.3，胶囊高 51，
   几何居中是 top 871（设计给的 858 偏高约 13px，文字下缘会露出胶囊外）；
   按业务方要求再上移 4，落在 867 */
.m-s4__tab-pill {
  left: calc(109 * var(--u)); top: calc(867 * var(--u));
  width: calc(125 * var(--u)); height: calc(51 * var(--u));
  transition: left .25s var(--ease-out), width .25s var(--ease-out);
  pointer-events: none;
  z-index: 2;
}
.m-s4__tab {
  top: calc(875 * var(--u));
  transform: translateX(-50%);
  font-size: calc(24 * var(--u));
  line-height: calc(42.638 * var(--u));
  white-space: nowrap;
  color: #774940;
  transition: color .2s ease;
  z-index: 3;
}
.m-s4__tab.is-active { color: #fff; }
.m-s4__tab--latest { left: calc(172 * var(--u)); }
.m-s4__tab--news   { left: calc(294 * var(--u)); }
.m-s4__tab--notice { left: calc(417 * var(--u)); }
.m-s4__more {
  left: calc(623 * var(--u)); top: calc(875 * var(--u));
  transform: translateX(-50%);
  font-size: calc(24 * var(--u));
  line-height: calc(42.638 * var(--u));
  white-space: nowrap;
  color: #774940;
  z-index: 3;
}

/* 资讯列表：4 条按设计稿逐条定位 */
.m-s4__list { left: 0; top: 0; width: 100%; height: calc(1306 * var(--u)); pointer-events: none; z-index: 3; }
.m-s4-row {
  position: absolute;
  left: calc(108 * var(--u));
  width: calc(545 * var(--u));
  pointer-events: auto;
}
.m-s4-row--1 { top: calc(927 * var(--u));  height: calc(75 * var(--u)); }
.m-s4-row--2 { top: calc(1018 * var(--u)); height: calc(74 * var(--u)); }
.m-s4-row--3 { top: calc(1110 * var(--u)); height: calc(74 * var(--u)); }
.m-s4-row--4 { top: calc(1200 * var(--u)); height: calc(75 * var(--u)); }
.m-s4-row__bg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; opacity: .68; }
.m-s4-row__cat,
.m-s4-row__title,
.m-s4-row__date {
  position: absolute;
  line-height: calc(37.122 * var(--u));
  white-space: nowrap;
}
/* 条目内的文字整组比设计坐标上提 7：原来字底几乎贴着白卡底边（上方留白约 15、下方不到 1），
   上提后上下留白各约 8，文字在卡片里居中 */
.m-s4-row__cat   { left: calc(19 * var(--u));  top: 0;  font-size: calc(18 * var(--u)); color: #774940; }
.m-s4-row__title {
  left: calc(55 * var(--u)); top: calc(30 * var(--u));
  width: calc(370 * var(--u));
  font-size: calc(24 * var(--u));
  color: #774940;
  overflow: hidden;
  text-overflow: ellipsis;
}
.m-s4-row__date  { left: calc(430 * var(--u)); top: calc(37 * var(--u)); font-size: calc(18 * var(--u)); color: #d2a358; }
/* 书签图标与标题文字取同一条中线：标题行框中心落在 48.5，图标高 21，top 取 38 */
.m-s4-row__bullet { position: absolute; left: calc(17 * var(--u)); top: calc(38 * var(--u)); width: calc(17 * var(--u)); height: calc(21 * var(--u)); }

/* ============================================================================
   第 6 屏 · 底部信息
   ========================================================================== */
.m-s5__bg     { left: calc(-357 * var(--u)); top: 0;                    width: calc(1503 * var(--u)); height: calc(1666 * var(--u)); pointer-events: none; }
/* 底部信息整块一起从正下方升起（背景不跟着动），容器只负责整组入场，不占位 */
.m-s5__info { left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; }
.m-s5__info > * { position: absolute; }
.m-s5__info > div > img:only-child,
.m-s5__info > a > img:only-child { width: 100%; height: 100%; }
.m-s5__links, .m-s5__badge { pointer-events: auto; }
.m-s5__lilith { left: calc(217 * var(--u));  top: calc(129 * var(--u)); width: calc(309 * var(--u));  height: calc(111 * var(--u)); pointer-events: none; }
.m-s5__links {
  left: calc(377 * var(--u)); top: calc(279 * var(--u));
  transform: translateX(-50%);
  font-size: calc(24 * var(--u));
  line-height: calc(42.556 * var(--u));
  color: #fff;
  text-align: center;
  white-space: pre;
}
.m-s5__links a:active { opacity: .7; }
.m-s5__legal {
  left: calc(374 * var(--u)); top: calc(386 * var(--u));
  transform: translateX(-50%);
  width: calc(634 * var(--u));
  font-size: calc(18 * var(--u));
  line-height: calc(36 * var(--u));
  color: #bebebe;
  text-align: center;
  white-space: pre-line;
}
.m-s5__badge--2 { left: calc(119 * var(--u)); top: calc(756 * var(--u)); width: calc(201 * var(--u)); height: calc(77 * var(--u)); }
.m-s5__badge--1 { left: calc(346 * var(--u)); top: calc(755 * var(--u)); width: calc(201 * var(--u)); height: calc(76 * var(--u)); }
.m-s5__rating   { left: calc(572 * var(--u)); top: calc(755 * var(--u)); width: calc(60 * var(--u));  height: calc(76 * var(--u)); pointer-events: none; }
.m-s5__badge:active { opacity: .8; }

/* ============================================================================
   跨屏装饰：设计里这两个角色叠在所有区块之上
   ========================================================================== */
.m-deco { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; z-index: 5; }
.m-deco > div { position: absolute; }
.m-deco > div > img { width: 100%; height: 100%; }
.m-deco__boy  { left: calc(-66 * var(--u));  top: calc(2305 * var(--u)); width: calc(227 * var(--u)); height: calc(264 * var(--u)); }
.m-deco__girl { left: calc(567 * var(--u)); top: calc(4504 * var(--u)); width: calc(262 * var(--u)); height: calc(201 * var(--u)); }

@keyframes mFloatY {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(calc(-18 * var(--u))); }
}
.m-deco__boy  { animation: mFloatY 5.6s ease-in-out infinite; }
.m-deco__girl { animation: mFloatY 6.8s ease-in-out infinite .9s; }

/* ============================================================================
   宣传片浮层
   ========================================================================== */
.m-video-modal { position: fixed; inset: 0; z-index: 2000; display: flex; align-items: center; justify-content: center; }
.m-video-modal__mask { position: absolute; inset: 0; background: rgba(0, 0, 0, .82); }
.m-video-modal__box { position: relative; width: 92vw; }
.m-video-modal__player { width: 100%; max-height: 70vh; background: #000; border-radius: calc(16 * var(--u)); }
.m-video-modal__close {
  position: absolute;
  right: 0; top: calc(-56 * var(--u));
  width: calc(56 * var(--u)); height: calc(56 * var(--u));
  font-size: calc(40 * var(--u));
  line-height: 1;
  color: #fff;
}

/* ============================================================================
   滚动入场：元素进入视野下缘 18% 以内才浮现，完全离开视野后复位
   ========================================================================== */
.m-anim .m-anim-el {
  transition: opacity .5s var(--ease-out), transform .6s var(--ease-out);
  transition-delay: calc(var(--d, 0) * 55ms);
}
.m-anim .m-anim-el:not(.is-in) { opacity: 0; will-change: opacity, transform; }
.m-anim .m-s1__title:not(.is-in),
.m-anim .m-s2__title:not(.is-in),
.m-anim .m-s3__title:not(.is-in),
.m-anim .m-s4__title:not(.is-in) { transform: translateY(calc(-30 * var(--u))); }
.m-anim .m-hero__slogan:not(.is-in),
.m-anim .m-s1__polaroid:not(.is-in),
.m-anim .m-s1__char:not(.is-in),
.m-anim .m-s1__card:not(.is-in),
.m-anim .m-hero__btn--cta:not(.is-in),
.m-anim .m-s3__swiper:not(.is-in),
.m-anim .m-s4__frame:not(.is-in),
.m-anim .m-s4__gallery:not(.is-in),
.m-anim .m-s4__panel:not(.is-in),
.m-anim .m-s4__list:not(.is-in) { transform: translateY(calc(40 * var(--u))); }
/* 底部信息：整块从正下方升起，位移比别处大一点，让「从下面上来」这件事看得出来 */
.m-anim .m-s5__info:not(.is-in) { transform: translateY(calc(72 * var(--u))); }
.m-anim .m-s5__info { transition: opacity .56s var(--ease-out), transform .72s var(--ease-out); }

.m-anim .m-s1__title, .m-anim .m-s2__title,
.m-anim .m-s3__title, .m-anim .m-s4__title,
.m-anim .m-hero__slogan { --d: 0; }
.m-anim .m-s1__char, .m-anim .m-s1__polaroid,
.m-anim .m-s3__swiper,
.m-anim .m-s4__frame, .m-anim .m-s4__gallery,
.m-anim .m-hero__btn--cta { --d: 1; }
/* 资讯条与它脚下的白底框同一档延时、同一个触发点（触发同步在 home_mobile.js 的
   ANIM_PAIRS 里做），信息与底框一起出现 */
.m-anim .m-s1__card, .m-anim .m-s4__panel, .m-anim .m-s4__list { --d: 2; }

@media (prefers-reduced-motion: reduce) {
  .m-deco__boy, .m-deco__girl { animation: none !important; }
  .m-anim .m-anim-el { transition: none !important; }
}

/* ============================================================================
   预约弹窗 —— 表单态 + 成功态（DOM 与 class 跟 PC 端完全一致）
   表单态按手机专用设计稿（Figma 164:501）摆放，见本段末尾「表单态」覆盖块；
   成功态沿用下面的竖向文档流排（设计稿只有 PC 版 43:2）。
   ========================================================================== */
/* 弹窗整体尺寸同样只跟宽度走（卡片高 629 设计px），横屏时会被撑到比屏幕还高，
   关闭按钮直接跑到屏幕上方外面 —— 就是「横屏关不掉预约弹窗」。
   同上，--u 取「按宽算」和「按高算」的小者：竖屏不变，矮屏整张卡等比缩到放得下。
   卡片是靠弹性布局居中的、不是按 --u 定位，所以缩放后自动仍然居中。 */
.rsv {
  position: fixed;
  --u: min(0.13333333vw, 0.1494vh);
  inset: 0;
  z-index: 2100;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rsv__mask { position: absolute; inset: 0; background: rgba(20, 8, 12, .62); }
.rsv__card--done {
  /* 底图是 990×791 的整图，卡片高度必须按这个比例定死（690 / 1.252），
     否则内容一多一少就把底图拉扁或压瘪；内容整体居中放 */
  height: calc(551 * var(--u));
  justify-content: center;
}
.rsv__card {
  position: relative;
  width: calc(690 * var(--u));
  padding: calc(40 * var(--u)) calc(55 * var(--u)) calc(48 * var(--u));
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* 只有「按钮 / 链接里那张图」才撑满容器；卡片的直接子图（底板 / 烟花 / 标题 / 虚线）
   各有各的落位尺寸，别被这条通配压掉 */
.rsv__card button > img,
.rsv__card a > img,
.rsv__card .rsv__social > img { width: 100%; height: 100%; }
.rsv__bg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; }
/* 关闭按钮的图形烧在底板切图里，底板被拉伸后它跟着走，所以热区用百分比跟随 */
.rsv__close { position: absolute; left: 87.4%; top: 0.6%; width: 7.2%; height: calc(70 * var(--u)); z-index: 3; }
.rsv__title { position: relative; width: calc(300 * var(--u)); height: calc(74 * var(--u)); flex: none; }

.rsv__plats {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  margin-top: calc(34 * var(--u));
}
.rsv__plat {
  display: flex;
  align-items: center;
  gap: calc(12 * var(--u));
  font-size: calc(28 * var(--u));
  line-height: 1.4;
  color: #6b3f00;
  white-space: nowrap;
}
.rsv__plat-input, .rsv__agree-input { position: absolute; opacity: 0; width: 0; height: 0; }
.rsv__radio, .rsv__check {
  flex: none;
  width: calc(26 * var(--u));
  height: calc(25 * var(--u));
  background: url('../img/common/rsv/radio_off.webp') center / 100% 100% no-repeat;
}
.rsv__plat-input:checked + .rsv__radio,
.rsv__agree-input:checked + .rsv__check { background-image: url('../img/common/rsv/radio_on.webp'); }
.rsv__check { background-image: url('../img/common/rsv/check_off.webp'); }

.rsv__field { position: relative; height: calc(84 * var(--u)); flex: none; }
.rsv__field--email { width: 100%; margin-top: calc(30 * var(--u)); }
/* 验证码框与「获取验证码」并排：后者用负 margin 提回同一行 */
.rsv__field--code { width: 58%; align-self: flex-start; margin-top: calc(26 * var(--u)); }
.rsv__field-bg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; }
.rsv__field input {
  position: absolute;
  left: calc(38 * var(--u));
  top: 0;
  width: calc(100% - 60 * var(--u));
  height: 100%;
  border: 0;
  background: none;
  font: inherit;
  font-size: calc(28 * var(--u));
  color: #6b3f00;
  outline: none;
}
.rsv__field input::placeholder { color: #7b7b7b; }

.rsv__getcode {
  position: relative;
  align-self: flex-end;
  width: 38%;
  height: calc(84 * var(--u));
  margin-top: calc(-84 * var(--u));
  flex: none;
}
.rsv__getcode-text {
  position: absolute;
  left: 0; top: 0;
  width: 100%; height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(26 * var(--u));
  color: #fff;
  white-space: nowrap;
}
.rsv__getcode[disabled] { filter: grayscale(.35) brightness(.95); }

/* 勾选文案各语言长短差很多（简中还带年龄声明），写死不换行会顶出卡片，
   所以按卡片内可用宽度自然折行；折行后勾选框对齐第一行。 */
.rsv__agree {
  position: relative;
  align-self: flex-start;
  display: flex;
  align-items: flex-start;
  gap: calc(14 * var(--u));
  margin-top: calc(30 * var(--u));
  font-size: calc(24 * var(--u));
  line-height: 1.4;
  color: #bba586;
}
/* 勾选文案里的「用户协议」「隐私政策」是真链接（地址在 config 的 rsvAgreeLabel 富文本里）：
   带下划线让人看出来能点；手机上再把点按区域上下各撑开一点，免得太细点不中。 */
.rsv__agree-link {
  position: relative;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: calc(2 * var(--u));
}
.rsv__agree-link::after { content: ''; position: absolute; inset: calc(-14 * var(--u)) calc(-4 * var(--u)); }

.rsv__submit {
  position: relative;
  width: calc(420 * var(--u));
  height: calc(77 * var(--u));
  margin-top: calc(30 * var(--u));
  flex: none;
}
.rsv__submit:active img, .rsv__getcode:active img { transform: scale(.97); }
.rsv__tip {
  position: relative;
  width: 100%;
  margin-top: calc(14 * var(--u));
  text-align: center;
  font-size: calc(22 * var(--u));
  line-height: 1.4;
  color: #e0557a;
}

/* ── 表单态（Figma 164:501，手机专用弹窗） ─────────────────────────────
   卡片用设计给的整张卡片图（白卡 + 右上角关闭叉 + 四周烟花）按原尺寸 779×629 显示，不再拉伸；
   卡片图左上角为原点，控件按设计坐标绝对定位（设计 x+15、y−320）。
   字体沿用站点圆体，字号 / 行高 / 颜色照设计：平台与输入框 20.304、同意条款 15、
   获取验证码按钮默认文字 17.367（英文折两行），「获取中 / 已发送」两态 20.304。 */
.rsv .rsv__card--form {
  display: block;
  /* 卡片图比屏幕宽（779），设计里两侧各探出屏幕约 15；不许被外层居中布局压窄，否则底图会被横向挤扁 */
  flex: none;
  width: calc(779 * var(--u));
  height: calc(629 * var(--u));
  padding: 0;
}
.rsv__card--form > * { position: absolute; margin: 0; }
.rsv__card--form .rsv__bg { left: 0; top: 0; width: 100%; height: 100%; }
/* 关闭叉在卡片图里，热区盖在它上面 */
.rsv__card--form .rsv__close { left: calc(618 * var(--u)); top: calc(37 * var(--u)); width: calc(72 * var(--u)); height: calc(72 * var(--u)); }
/* 中文标题是两行（大字 + 小英文）的方形切图，按原比例放大到与英文标题相近的字面大小，居中在同一位置 */
.rsv__card--form .rsv__title { position: absolute; left: calc(264.5 * var(--u)); top: calc(83 * var(--u)); width: calc(251 * var(--u)); height: calc(62 * var(--u)); }

.rsv__card--form .rsv__plats { left: 0; top: 0; width: 100%; height: 0; display: block; }
.rsv__card--form .rsv__plat { position: absolute; top: calc(173 * var(--u)); gap: calc(7 * var(--u)); font-size: calc(20.304 * var(--u)); line-height: calc(30.456 * var(--u)); }
.rsv__card--form .rsv__plat--android { left: calc(180 * var(--u)); }
.rsv__card--form .rsv__plat--ios     { left: calc(365 * var(--u)); }
.rsv__card--form .rsv__plat--pc      { left: calc(508 * var(--u)); }
.rsv__card--form .rsv__radio { width: calc(19 * var(--u)); height: calc(19 * var(--u)); background-image: url('../img/m/common/rsv/radio_off.webp'); }
.rsv__card--form .rsv__plat-input:checked + .rsv__radio { background-image: url('../img/m/common/rsv/radio_on.webp'); }
.rsv__card--form .rsv__check { width: calc(20 * var(--u)); height: calc(19 * var(--u)); margin-top: calc(6 * var(--u)); background-image: url('../img/m/common/rsv/check_off.webp'); }
.rsv__card--form .rsv__agree-input:checked + .rsv__check { background-image: url('../img/m/common/rsv/radio_on.webp'); }

.rsv__card--form .rsv__field--email { position: absolute; left: calc(134 * var(--u)); top: calc(215 * var(--u)); width: calc(514 * var(--u)); height: calc(57 * var(--u)); }
.rsv__card--form .rsv__field--code  { position: absolute; left: calc(134 * var(--u)); top: calc(295 * var(--u)); width: calc(325 * var(--u)); height: calc(57 * var(--u)); }
.rsv__card--form .rsv__field input { left: calc(50 * var(--u)); width: calc(100% - 70 * var(--u)); font-size: calc(20.304 * var(--u)); }

.rsv__card--form .rsv__getcode { position: absolute; left: calc(482 * var(--u)); top: calc(294 * var(--u)); width: calc(165 * var(--u)); height: calc(57 * var(--u)); }
.rsv__card--form .rsv__getcode-text { padding: 0 calc(9 * var(--u)); font-size: calc(17.367 * var(--u)); line-height: calc(17 * var(--u)); text-align: center; white-space: normal; }
.rsv__card--form .rsv__getcode[disabled] .rsv__getcode-text { font-size: calc(20.304 * var(--u)); line-height: calc(20 * var(--u)); }

/* 勾选文案竖向居中在验证码那一行（底 352）和「立即预约」按钮（顶 444）之间：以中线 398 为准上下对半，中英文行数不同也都居中 */
.rsv__card--form .rsv__agree { position: absolute; left: calc(134 * var(--u)); top: calc(398 * var(--u)); transform: translateY(-50%); width: calc(514 * var(--u)); gap: calc(11 * var(--u)); font-size: calc(15 * var(--u)); line-height: calc(30.456 * var(--u)); }
.rsv__card--form .rsv__submit { position: absolute; left: calc(227 * var(--u)); top: calc(444 * var(--u)); width: calc(325 * var(--u)); height: calc(59 * var(--u)); }
/* 错误提示放在按钮下方、白卡底边以内（白卡在卡片图里 x 84~693、y 61~537） */
.rsv__card--form .rsv__tip { position: absolute; left: calc(84 * var(--u)); top: calc(506 * var(--u)); width: calc(609 * var(--u)); font-size: calc(20.304 * var(--u)); line-height: calc(30 * var(--u)); }

/* ── 成功态 ─────────────────────────────────────────────────────────── */
/* 卡片按底图比例固定高度后，文案与图标之间按固定间距排，整体由卡片居中 */
.rsv__note { position: relative; width: 100%; margin-top: calc(40 * var(--u)); }
/* 设计原有两句提示，第二句（奖励发放说明）按业务方要求去掉，剩下一句随卡片整体居中 */
.rsv__note-1 {
  text-align: center;
  font-size: calc(26 * var(--u));
  line-height: 1.5;
  letter-spacing: calc(-0.867 * var(--u));
  color: #888;
  white-space: nowrap;
}
/* 虚线切图比落位框宽，按设计的 object-cover 取中段 */
.rsv__dash {
  position: absolute;
  top: calc(18 * var(--u));
  width: calc(88 * var(--u));
  height: calc(6 * var(--u));
  object-fit: cover;
}
.rsv__dash--l { left: 0; }
.rsv__dash--r { right: 0; }

.rsv__socials {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: calc(26 * var(--u)) calc(30 * var(--u));
  width: 100%;
  margin-top: calc(35 * var(--u));
}
.rsv__social { position: relative; flex: none; }
/* 海外版那 6 个渠道默认收起，切到外文版才显示（css/i18n_mobile.css） */
.rsv__social.is-global { display: none; }
.rsv__social--xhs       { width: calc(122 * var(--u)); height: calc(43 * var(--u)); }
.rsv__social--tap       { width: calc(90 * var(--u));  height: calc(47 * var(--u)); }
.rsv__social--bilibili  { width: calc(54 * var(--u));  height: calc(49 * var(--u)); }
.rsv__social--wechat    { width: calc(61 * var(--u));  height: calc(51 * var(--u)); }
.rsv__social--qq        { width: calc(52 * var(--u));  height: calc(55 * var(--u)); }
.rsv__social--douyin    { width: calc(53 * var(--u));  height: calc(61 * var(--u)); }
.rsv__social--channel-x { width: calc(48 * var(--u));  height: calc(57 * var(--u)); }
.rsv__social--weibo     { width: calc(62 * var(--u));  height: calc(50 * var(--u)); }

/* ============================================================================
   触屏特效：手指点到哪就在哪放一段星星爆开的逐帧动画
   整层不接收点击（pointer-events: none），压在最上面也不挡任何操作。
   ========================================================================== */
.tapfx {
  position: fixed;
  inset: 0;
  z-index: 3000;
  overflow: hidden;
  pointer-events: none;
}
.tapfx__item {
  position: absolute;
  width: calc(190 * var(--u));
  height: calc(190 * var(--u));
  margin: calc(-95 * var(--u)) 0 0 calc(-95 * var(--u)); /* 以落点为中心 */
  background-repeat: no-repeat;
  will-change: background-position, opacity;
}

/* ============================================================================
   加载页（Figma 50:92）：进站时盖住整屏，中间的小物件循环切换，
   「加载中…」的点持续跳动；页面资源加载完自动淡出。
   卡片按设计 336×336 的画布 1:1 摆，--ld-u 就是 1 个设计 px。
   ========================================================================== */
.loading {
  /* 1 个设计 px：手机上卡片按 380 设计宽摆（336 × 1.131），文字才读得清 */
  --ld-u: calc(1.131 * var(--u));
  position: fixed;
  inset: 0;
  z-index: 4000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fab6d6; /* 背景图解码完成前的兜底底色，取自背景图均值 */
  transition: opacity .45s ease, visibility .45s;
}
.loading.is-done { opacity: 0; visibility: hidden; pointer-events: none; }
.loading__bg {
  position: absolute;
  inset: 0;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.loading__card {
  position: relative;
  width: calc(336 * var(--ld-u));
  height: calc(336 * var(--ld-u));
}
.loading__card-bg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
.loading__items { position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
/* 每个小物件的落位与尺寸都不同，按设计逐个摆；配置里多加的用居中兜底 */
.loading__item {
  position: absolute;
  left: 50%; top: 45%;
  width: calc(150 * var(--ld-u));
  height: calc(150 * var(--ld-u));
  margin: calc(-75 * var(--ld-u)) 0 0 calc(-75 * var(--ld-u));
  opacity: 0;
  transform: scale(.86);
  transition: opacity .22s ease, transform .28s cubic-bezier(.25, 1.18, .4, 1);
}
.loading__item.is-on { opacity: 1; transform: none; }
.loading__item img { width: 100%; height: 100%; }
.loading__item--1 { left: calc(84 * var(--ld-u)); top: calc(92 * var(--ld-u)); width: calc(167 * var(--ld-u)); height: calc(128 * var(--ld-u)); }
.loading__item--2 { left: calc(83 * var(--ld-u)); top: calc(88 * var(--ld-u)); width: calc(168 * var(--ld-u)); height: calc(132 * var(--ld-u)); }
.loading__item--3 { left: calc(87 * var(--ld-u)); top: calc(95 * var(--ld-u)); width: calc(160 * var(--ld-u)); height: calc(125 * var(--ld-u)); }
.loading__item--4 { left: calc(94 * var(--ld-u)); top: calc(68 * var(--ld-u)); width: calc(148 * var(--ld-u)); height: calc(152 * var(--ld-u)); }
.loading__item--5 { left: calc(103 * var(--ld-u)); top: calc(87 * var(--ld-u)); width: calc(129 * var(--ld-u)); height: calc(133 * var(--ld-u)); }
.loading__item--6 { left: calc(108 * var(--ld-u)); top: calc(127 * var(--ld-u)); width: calc(119 * var(--ld-u)); height: calc(93 * var(--ld-u)); }
.loading__item--7 { left: calc(91 * var(--ld-u)); top: calc(67 * var(--ld-u)); width: calc(153 * var(--ld-u)); height: calc(153 * var(--ld-u)); }
.loading__item--8 { left: calc(99 * var(--ld-u)); top: calc(69 * var(--ld-u)); width: calc(137 * var(--ld-u)); height: calc(151 * var(--ld-u)); }
.loading__item--9 { left: calc(90 * var(--ld-u)); top: calc(80 * var(--ld-u)); width: calc(155 * var(--ld-u)); height: calc(140 * var(--ld-u)); }
.loading__item--10 { left: calc(104 * var(--ld-u)); top: calc(71 * var(--ld-u)); width: calc(127 * var(--ld-u)); height: calc(149 * var(--ld-u)); }
.loading__item--11 { left: calc(100 * var(--ld-u)); top: calc(75 * var(--ld-u)); width: calc(135 * var(--ld-u)); height: calc(145 * var(--ld-u)); }
.loading__item--12 { left: calc(84 * var(--ld-u)); top: calc(112 * var(--ld-u)); width: calc(165 * var(--ld-u)); height: calc(108 * var(--ld-u)); }
.loading__item--13 { left: calc(96 * var(--ld-u)); top: calc(71 * var(--ld-u)); width: calc(143 * var(--ld-u)); height: calc(149 * var(--ld-u)); }
.loading__item--14 { left: calc(96 * var(--ld-u)); top: calc(80 * var(--ld-u)); width: calc(141 * var(--ld-u)); height: calc(140 * var(--ld-u)); }
.loading__item--15 { left: calc(95 * var(--ld-u)); top: calc(63 * var(--ld-u)); width: calc(144 * var(--ld-u)); height: calc(157 * var(--ld-u)); }
.loading__item--16 { left: calc(95 * var(--ld-u)); top: calc(80 * var(--ld-u)); width: calc(144 * var(--ld-u)); height: calc(140 * var(--ld-u)); }
.loading__item--1, .loading__item--2, .loading__item--3, .loading__item--4,
.loading__item--5, .loading__item--6, .loading__item--7, .loading__item--8,
.loading__item--9, .loading__item--10, .loading__item--11, .loading__item--12,
.loading__item--13, .loading__item--14, .loading__item--15, .loading__item--16 { margin: 0; }

.loading__label {
  position: absolute;
  left: calc(173 * var(--ld-u));
  top: calc(237 * var(--ld-u));
  transform: translateX(-50%);
  font-size: calc(33.333 * var(--ld-u));
  line-height: calc(56.741 * var(--ld-u));
  letter-spacing: calc(-1.667 * var(--ld-u));
  color: #f80ca3;
  white-space: nowrap;
}
/* 「…」持续跳动：三颗点依次亮起 */
@keyframes ldDot { 0%, 70%, 100% { opacity: .2; } 35% { opacity: 1; } }
.loading__dot { font-style: normal; animation: ldDot 1.2s ease-in-out infinite; }
.loading__dot:nth-of-type(2) { animation-delay: .18s; }
.loading__dot:nth-of-type(3) { animation-delay: .36s; }

@media (prefers-reduced-motion: reduce) {
  .loading__item { transition: none; }
  .loading__dot { animation: none; opacity: 1; }
}

/* ============================================================================
   按下反馈：手指按住时元素要往下压一档，点击感才实
   ========================================================================== */
.m-nav__logo:active img,
.m-nav__share-btn:active img,
.m-nav__bgm:active img { transform: scale(.9); }
.m-share__item:active img { transform: scale(.86); }
.m-s4__tab:active  { transform: translateX(-50%) scale(.92); }
.m-s4__more:active { transform: translateX(-50%) scale(.92); }
.m-s4-row:active   { transform: scale(.985); opacity: .85; }
.m-s5__lilith:active img { transform: scale(.96); }
.rsv__social:active img { transform: scale(.88); }
.rsv__plat:active .rsv__radio,
.rsv__agree:active .rsv__check { transform: scale(.84); }

/* ── 加载页 → 页面的衔接 ─────────────────────────────────────────────
   加载页盖着时页面先不显形；它开始淡出的同时页面渐显，首屏内容随后落位。 */
#m-root, .m-nav { transition: none; }
html.is-loading #m-root,
html.is-loading .m-nav { opacity: 0; transition: none; }

