/* 产品页：左侧常驻手机、右侧逐段讲解，滚动到哪一段就换到哪一屏。
   双栏尺寸沿用讲解分镜页的那一套；屏内是小程序在微信开发者工具里跑出来的真实截屏
   （iPhone 12/13，390 × 844），机身宽度按这个比例定，整机才放得进一屏。

   ── 机身：真机模板 ────────────────────────────────
   机身不再用 CSS 画，改用 product-shots/iphone-frame.webp。
   模板是一台 iPhone 16 Pro：屏幕区 1206 × 2622px，比例 0.45995 = 402/874pt，
   屏幕区与机身外全透明，灵动岛、摄像头、侧边按键与机身反光都在图里。

   用法是「截屏在下、模板压在上」：模板的屏幕区透明，所以界面从下面透出来，
   而灵动岛与机身边框盖在界面之上——这才是真机的层次，也省掉自己画岛。

   从原图量出的几何（相对整幅图，缩放后不变，所以 CSS 直接用百分比）：
     图幅比例   1350 / 2760
     屏幕 left   5.3333%   top 2.5%   width 89.3333%   height 95%
     内角圆角   屏幕高度 × 7.4%（原图约 200px；取略小值，保证截屏被收在开口以内）
   机身高度由屏幕高度反推：屏幕占整幅图高的 95%，故机身高 = --screen-h / .95
   */

:root {
  /* 机身之外的暗色底与截屏同源，图未加载时不会先闪出一块亮的 */
  --app-bg: #0a0c10;
  /* 吸顶位置让开固定页眉；屏幕高度按它算，两处必须同源 */
  --stick-top: 88px;
  /* 屏幕高度只在这里定义一次：机身边框与两处圆角都按它换算，
     窄屏改的也是这一个值（见文件末尾的媒体查询）。
     整机必须完整落在一屏里：视口 − 吸顶位置 − 机身边框与下方留白；757px 是设计上限，不再放大。 */
  --screen-h: min(757px, calc(100svh - var(--stick-top) - 56px));
}

.product-lead { color: var(--muted); }

/* ── 「打开网页版」 ───────────────────────────────────────────
   首屏导语下面一块，只有一个实心按钮：按钮上写的就是它做的事，不必再配一行
   说明。比例与交互取自 Notion 官网的主动作；KeyMoment 的青色仍留给品牌与
   信息层级。 */
.product-entry {
  display: flex; align-items: center;
  margin-top: 28px;
}
.product-entry[hidden] { display: none; }
.product-entry-btn {
  display: inline-flex; align-items: center; justify-content: center;
  box-sizing: border-box; height: 38px; padding: 0 15px;
  border: 1px solid transparent; border-radius: 8px;
  background: #0075de; color: #fff;
  font-size: 16px; font-weight: 500; line-height: 24px;
  letter-spacing: 0; text-decoration: none;
  transition: background-color 200ms cubic-bezier(.42, 0, 1, 1);
}
@media (hover: hover) and (pointer: fine) {
  .product-entry-btn:hover { background: #0068c9; }
}
.product-entry-btn:active { background: #005bb6; }
.product-entry-btn:focus-visible {
  outline: none; box-shadow: 0 0 0 3px rgba(0, 117, 222, .38);
}

/* ── 双栏 ─────────────────────────────────────────────── */

.tour {
  display: grid; gap: 44px;
  /* 双栏整体居中：左栏贴着版心左边界时，右侧文字排到 48ch 就停，
     整块看上去压在左边。1180 是机身与讲解两栏都排得开的宽度。 */
  max-width: 1120px; margin: 12vh auto 0;
  grid-template-columns: minmax(340px, 400px) minmax(0, 1fr);
}
/* 吸顶的必须是网格项里的那一层，不能是网格项本身：网格项被拉伸到整行高，
   它的高度就等于自己的包含块，可移动的余量为零，一滑就跟着走。
   .tour-stage 负责占满整行，.tour-stick 在它内部吸顶，行程 = 整行高 − 机身高。
   吸顶位置让开固定页眉。 */
.tour-stick { position: sticky; top: var(--stick-top); }

.phone {
  position: relative;
  /* 宽度由 aspect-ratio 从高度算出，改高度时不必同时改宽度 */
  max-width: 100%; margin: 0 auto;
  /* 机身高度由屏幕高度反推：屏幕占整幅图高的 95% */
  height: calc(var(--screen-h) / .95);
  aspect-ratio: 1350 / 2760;
  /* 模板带 alpha，投影必须跟着轮廓走；box-shadow 画的是矩形，会在机身外露出四个角 */
  filter: drop-shadow(0 26px 40px rgba(0, 0, 0, .66));
  /* 视角随指针平移：JS 直接写 transform，过渡负责阻尼 */
  transition: transform 320ms var(--ease-out);
}
.phone-screen {
  /* 贴在模板的屏幕开口上；百分比相对整幅图，所以机身缩放时开口始终对齐 */
  position: absolute; z-index: 1; overflow: hidden;
  left: 5.3333%; top: 2.5%; width: 89.3333%; height: 95%;
  border-radius: calc(var(--screen-h) * .074);
  background: var(--app-bg);
}
/* 模板压在截屏之上：屏幕区透明，界面从下面透出来，灵动岛与机身边框盖在界面上 */
.phone::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: url("/product-shots/iphone-frame.webp?v=1") center / 100% 100% no-repeat;
}

.screen {
  /* contain 而不是 cover：屏幕比例与截屏一致，contain 只是多一道保险——
     哪怕差一两个像素也宁可留白，不裁掉界面两侧。 */
  position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain;
  opacity: 0; visibility: hidden;
  /* 换屏不是硬切：新的一屏一边淡入一边往上落位，位移比淡入慢一档，落定才停。
     visibility 用 0s 的延迟收尾，淡出走完之前不许它消失。 */
  transform: translate3d(0, 12px, 0) scale(1.015);
  transition: opacity 380ms var(--ease-out), transform 560ms var(--ease-out),
    visibility 0s linear 560ms;
}
.screen.is-on {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity 380ms var(--ease-out), transform 560ms var(--ease-out), visibility 0s;
}

.screen-demo { background: var(--app-bg); }
.demo-video { display: block; width: 100%; height: 100%; object-fit: contain; }
.demo-toggle {
  position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; padding: 0;
  border: 0; border-radius: inherit; cursor: pointer; color: #fff; background: transparent;
}
.demo-toggle:focus-visible { outline: 2px solid var(--brand); outline-offset: -5px; }
.demo-play-icon {
  position: absolute; left: 50%; top: 50%; width: 54px; height: 54px;
  border: 1px solid rgba(255, 255, 255, .38); border-radius: 50%;
  background: rgba(5, 10, 15, .68); box-shadow: 0 12px 28px rgba(0, 0, 0, .36);
  transform: translate(-50%, -50%); transition: opacity 180ms var(--ease-out);
}
.demo-play-icon::before {
  content: ""; position: absolute; left: 22px; top: 17px;
  border-top: 10px solid transparent; border-bottom: 10px solid transparent;
  border-left: 16px solid currentColor;
}
.demo-toggle[aria-pressed="true"] .demo-play-icon { opacity: 0; }
.demo-toggle[aria-pressed="true"]:hover .demo-play-icon,
.demo-toggle[aria-pressed="true"]:focus-visible .demo-play-icon { opacity: 1; }
.demo-toggle[aria-pressed="true"] .demo-play-icon::before {
  left: 20px; top: 18px; width: 5px; height: 18px; border: 0;
  background: currentColor; box-shadow: 9px 0 currentColor;
}
.demo-toggle.is-loading .demo-play-icon { opacity: 1; }
.demo-toggle.is-loading .demo-play-icon::before {
  left: 50%; top: 50%; width: 20px; height: 20px;
  border: 2px solid rgba(255, 255, 255, .28); border-top-color: currentColor;
  border-radius: 50%; background: transparent; box-shadow: none;
  transform: translate(-50%, -50%); animation: demo-loading-spin 720ms linear infinite;
}
@keyframes demo-loading-spin { to { transform: translate(-50%, -50%) rotate(1turn); } }

/* 手机端才出现的展台分页、功能章节标题与最终扫码入口。桌面继续使用双栏同步导览。 */
.phone-gallery-pagination,
.mobile-tour-copy-heading,
.mobile-product-qr { display: none; }

/* ── 最后一屏：小程序码 ────────────────────────────
   前六屏是小程序跑出来的截屏，这一屏是进入口，直接在机身里排。
   尺寸一律用 em，字号由 .screen-qr 的 font-size 按屏高给出，
   机身随视口缩放时整屏等比跟着缩——写死 px 会在矮屏上顶出屏幕开口。 */
.screen-qr {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .9em; padding: 2em 1.6em; text-align: center;
  font-size: calc(var(--screen-h) * .026);
  background: radial-gradient(120% 70% at 50% 22%, rgba(124, 166, 255, .12), transparent 62%),
    var(--app-bg);
}
.screen-qr .qr-mark { width: 2.1em; height: 2.1em; opacity: .78; margin-bottom: .5em; }
/* 码本身必须落在白底上：微信的识别对反色码并不稳，暗底直接贴图会连边距一起吃掉 */
.qr-card {
  width: 74%; padding: .7em; border-radius: 1.1em;
  background: #fff; box-shadow: 0 .8em 2em rgba(0, 0, 0, .45);
}
.qr-code { display: block; width: 100%; height: auto; }
.qr-title {
  margin: .6em 0 0; font-size: 1.32em; font-weight: 650; letter-spacing: .01em;
  color: rgba(241, 248, 250, .92);
}
.qr-note { margin: 0; font-size: 1em; line-height: 1.5; color: rgba(241, 248, 250, .5); }
/* 屏内的品牌字与页眉同一套写法（Key 浅色微斜、Moment 品牌青）：
   只把 flex 换成 inline-flex、字号改为继承，好落在这一行文字里。 */
.qr-note .brand-wordmark { display: inline-flex; font-size: 1em; }


/* ── 机身：真机模板 ────────────────────────────────
   机身不再用 CSS 画，改用 product-shots/web/macbook-frame.webp。
   模板是一台 MacBook Pro：屏幕开口 3456 × 2234px，比例 1.547（MBP14 为 3024/1964 = 1.540），
   屏幕区与机身外全透明，刘海、摄像头、下巴、底座与开合凹口都在图里。

   与手机页同一套层次：截屏在下（z-index 1），模板压在上（z-index 2）。
   `.laptop-display` 收成 display: contents，让屏幕层直接以 .laptop 为定位基准；
   自己画的摄像头、底座、凹口三件全部关掉——模板里都有。

   从原图量出的几何（相对整幅图，缩放后不变）：
     图幅比例   4260 / 2840 = 1.5
     开口 left   9.4366%   top 10.6690%   width 81.1268%   height 78.6620%
     开口圆角   开口高度 × 1.656%

   截屏是 1600 × 1000（16:10 = 1.6），比开口略宽一点，contain 之后上下各留 1.65%
   的黑边——宁可留白，也不裁掉三栏工作台的左右两侧。 */

.laptop {
  position: relative;
  aspect-ratio: 4260 / 2840;
  /* 整机必须完整落在一屏里：高度 = 宽度 / 1.5，由可用高度反推宽度上限，再与栏宽取小 */
  width: min(100%, calc((100svh - var(--stick-top) - 96px) * 1.5));
  margin: 0 auto;
  /* 模板带 alpha，投影得跟着轮廓走 */
  filter: drop-shadow(0 26px 40px rgba(0, 0, 0, .7));
  /* 视角随指针平移：JS 直接写 transform，过渡负责阻尼 */
  transition: transform 320ms var(--ease-out);
}
/* 这一层不再承担任何绘制，摘出盒树，让屏幕层以 .laptop 定位 */
.laptop-display { display: contents; }
.laptop-screen {
  position: absolute; z-index: 1; overflow: hidden;
  left: 9.4366%; top: 10.6690%; width: 81.1268%; height: 78.6620%;
  /* 圆角要圆不要椭圆：百分比的横向按盒宽解析、纵向按盒高，所以两个方向分开写（都等于 37px） */
  border-radius: 1.071% / 1.656%;
  background: var(--app-bg);
}
/* 模板压在截屏之上：屏幕区透明，界面从下面透出来，刘海与机身边框盖在界面上 */
.laptop::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: url("/product-shots/web/macbook-frame.webp?v=1") center / 100% 100% no-repeat;
}
/* 摄像头、底座、开合凹口都画在模板里了 */
.laptop-camera, .laptop-base, .laptop-notch { display: none; }

/* ── 双栏：网页版 ──────────────────────────────────────
   笔记本是横的，手机是竖的：两页的栏宽因此正好对调。
   机身占大头才看得清屏内的三栏工作台，讲解收窄到一栏字。 */

.tour.is-wide {
  max-width: 1400px;
  grid-template-columns: minmax(0, 1.62fr) minmax(280px, 1fr);
}
.tour.is-wide .tour-steps { padding-bottom: 26vh; }
.tour.is-wide .tour-step { max-width: 460px; }

/* 解说控制始终跟随视口，自动导览滚动时仍可暂停、静音或重播当前卡片。 */
.product-narration-tools {
  position: fixed; z-index: 12; right: max(24px, calc((100vw - 1400px) / 2)); bottom: 24px;
  display: flex; align-items: center; gap: 6px; padding: 6px;
  border: 1px solid rgba(241, 248, 250, .1); border-radius: 12px;
  background: rgba(8, 13, 18, .88); backdrop-filter: blur(16px);
}
.product-narration-play,
.product-narration-icon-button {
  display: inline-flex; align-items: center; justify-content: center; height: 40px;
  border: 0; color: rgba(241, 248, 250, .72); background: transparent; cursor: pointer;
  transition: color 180ms var(--ease-out), background 180ms var(--ease-out);
}
.product-narration-play { gap: 8px; padding: 0 12px; font: 500 13px/1 var(--font-sans); }
.product-narration-sound { position: relative; display: flex; }
.product-narration-icon-button { width: 40px; padding: 0; border-radius: 8px; }
.product-sound-hint {
  position: absolute; right: -40px; bottom: calc(100% + 12px); width: max-content; max-width: min(260px, calc(100vw - 28px));
  padding: 9px 12px; border: 1px solid rgba(115, 232, 255, .2); border-radius: 9px;
  color: rgba(241, 248, 250, .9); background: rgba(8, 13, 18, .96); box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
  font: 500 12px/1.4 var(--font-sans); white-space: nowrap;
}
.product-sound-hint::after {
  position: absolute; top: 100%; right: 56px; width: 7px; height: 7px; content: "";
  border-right: 1px solid rgba(115, 232, 255, .2); border-bottom: 1px solid rgba(115, 232, 255, .2);
  background: rgba(8, 13, 18, .96); transform: translate(-50%, -50%) rotate(45deg);
}
.product-sound-hint[hidden] { display: none; }
.product-narration-play:hover,
.product-narration-icon-button:hover { color: var(--white); background: rgba(241, 248, 250, .06); }
.product-narration-play:focus-visible,
.product-narration-icon-button:focus-visible { outline: 1px solid var(--cyan); outline-offset: -2px; }
.product-narration-icon { display: grid; place-items: center; width: 20px; height: 20px; }
.product-narration-icon svg,
svg.product-narration-icon {
  width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.product-narration-play [data-icon="play"] { fill: currentColor; stroke: none; }
.product-narration-play [data-icon="pause"],
.product-narration-play[data-audio-state="playing"] [data-icon="play"],
.product-narration-play[data-audio-state="pending"] [data-icon="play"] { display: none; }
.product-narration-play[data-audio-state="playing"] [data-icon="pause"],
.product-narration-play[data-audio-state="pending"] [data-icon="pause"] { display: block; }
[data-deck-mute] [data-icon="muted"],
[data-deck-mute][data-mute-state="muted"] [data-icon="audible"] { display: none; }
[data-deck-mute][data-mute-state="muted"] [data-icon="muted"] { display: block; }
html[lang="en"] .product-narration-tools { display: none; }

/* ── 右栏 ─────────────────────────────────────────────── */

.tour-steps {
  display: grid; gap: 20vh; margin: 0; list-style: none;
  /* 末尾留一段：吸顶行程止于整节底边，不留白的话最后一段还没读完手机就开始上移 */
  padding: 0 0 34vh;
}
/* 右栏是一列功能条目，不是六大段文章：条目名 + 一行说明常驻，细节只在读到
   这一条时显形。名字与说明的位置不随展开改变——细节块始终占位，只切换可见性，
   滚动时整列不会上下弹。 */
.tour-steps { display: grid; gap: 12vh; margin: 0; list-style: none; padding: 0 0 30vh; }

/* 卡片解剖照 Notion 产品页的功能卡：卡面上只有两层文字——一枚小而安静的
   类别标签，压一句加粗的陈述——没有第三层和它们抢。映到这里：条目名（比赛库）
   降成标签，一行说明升成标题；正文与要点收在下面，明度低一档，不进第一眼。 */
.tour-step {
  /* 面板贴着内容走，不摊满整栏 */
  max-width: 520px; padding: 30px 34px 28px; border-radius: 20px;
  /* 不在读的条目一点面也不画。细节块为了不让整列上下弹一直占着位，
     它若还带底色和边框，右栏就排成一列半空的方盒子——收起时只留标签与标题
     浮在暗底上，读起来才是一列条目而不是一列容器。 */
  background: transparent;
  /* 退场一律更快更简单（只改色、不位移），入场慢而带位移——这一快一慢正是苹果那套手感。 */
  transition: background 240ms var(--ease-out);
}
.tour-step.is-live {
  /* 卡面是纯平的一块浅色填充：无边框、无渐变、无投影。Notion 的卡在白底上
     就是一块 #f6f5f4，分离感全靠填充与底色的对比；暗底上的等价物是 4% 的白。
     之前叠的青色渐变、内高光、外阴影都属于装饰，先于内容被看见。 */
  background: rgba(241, 248, 250, .042);
  transition: background 620ms var(--ease-reveal);
}

/* 条目名 = 类别标签：小、稳、品牌青。它管「这是哪一块」，不抢标题的活。 */
.step-name {
  font-size: 12px; font-weight: 600; letter-spacing: .14em;
  color: rgba(241, 248, 250, .3); transition: color 240ms var(--ease-out);
}
.tour-step.is-live .step-name { color: rgba(115, 232, 255, .8); transition: color 560ms var(--ease-reveal); }

/* 一行说明 = 卡片标题：整张卡唯一的重音。字号只到 24px——42px 的名词换成
   陈述句会占满两行，重心反而散了。 */
.step-line {
  max-width: 26ch; margin-top: 14px;
  font-size: clamp(20px, 1.65vw, 24px); font-weight: 650; line-height: 1.4;
  letter-spacing: -.012em;
  color: rgba(241, 248, 250, .3); transition: color 240ms var(--ease-out);
}
.tour-step.is-live .step-line { color: var(--white); transition: color 560ms var(--ease-reveal) 60ms; }

/* 细节常驻占位，只切换可见性：收起时若真的塌掉，滚动中整列会上下弹。
   隐藏期间 visibility 收尾，淡出走完之前不许它消失。 */
.step-detail {
  visibility: hidden;
  transition: visibility 0s linear 260ms;
}
.tour-step.is-live .step-detail { visibility: visible; transition: visibility 0s; }

/* 正文与小字各自入场，依次错开：一段文字是一句一句到位的，不是整块闪出来 */
.step-body,
.step-facts {
  opacity: 0; transform: translate3d(0, 9px, 0); will-change: opacity, transform;
  transition: opacity 240ms var(--ease-out), transform 240ms var(--ease-out);
}
.tour-step.is-live .step-body {
  opacity: 1; transform: none;
  transition: opacity 620ms var(--ease-reveal) 120ms, transform 760ms var(--ease-reveal) 120ms;
}
.tour-step.is-live .step-facts {
  opacity: 1; transform: none;
  transition: opacity 620ms var(--ease-reveal) 220ms, transform 760ms var(--ease-reveal) 220ms;
}

.step-body {
  max-width: 430px; margin-top: 16px; color: var(--muted);
}
/* 三个要点排成一条规格行：上方一条发丝线把它和正文分开，词与词只靠间距，
   不加胶囊也不加分隔点——边框和点在暗底上都是先被看见的杂物。 */
.step-facts {
  display: flex; flex-wrap: wrap; gap: 6px 26px;
  max-width: 430px; margin: 20px 0 0; padding: 14px 0 0; list-style: none;
  border-top: 1px solid rgba(241, 248, 250, .08);
}
.step-facts li { color: rgba(241, 248, 250, .52); white-space: nowrap; }

@media (max-width: 1040px) {
  /* 单栏时 --stick-top 的含义换成「页眉实高」：这一档页眉是单行，实测 78px。
     吸顶层自己再用内边距把机身推下去，遮罩因此能盖住页眉底边到机身之间那条缝。 */
  :root { --stick-top: 78px; }
  /* 单栏时改回块级：网格单列会把左栏关进自己那一行，吸顶只剩一行的活动范围。 */
  .tour { display: block; }
  /* 单栏时 .tour-stage 只有机身那么高，吸顶层的包含块必须换成整节：
     用 display: contents 把这层从盒树里摘掉，.tour-stick 直接成为 .tour 的孩子。 */
  .tour-stage { display: contents; }
  .tour-stick {
    /* 顶边压进页眉 12px：页眉自身的背景到底边已经淡成透明，不压进去会漏出一条正在滚动的文字 */
    top: calc(var(--stick-top) - 12px); z-index: 5;
    padding: 24px 0 12px; background: linear-gradient(180deg, var(--ink) 88%, transparent);
  }
  /* 讲解条滚到固定页眉后方时，遮罩还要向吸顶盒上方延伸一小段；
     否则 320px 窄屏在换到最后一项时，上一项标题会从页眉与截图之间漏出来。 */
  .tour-stick::before {
    content: ""; position: absolute; inset: -24px 0 auto; height: 24px;
    background: var(--ink); pointer-events: none;
  }
  /* 机身高度不取固定比例，而是「视口减去必须留出的部分」：
     页眉 + 吸顶层上下内边距与机身边框（合计 48px）+ 给下面讲解条留的整整 280px，
     剩下多少才是屏幕。这样 844 高的手机与 667 高的手机都能把一条讲解完整放在机身下面。 */
  :root { --screen-h: clamp(190px, calc(100svh - var(--stick-top) - 328px), 520px); }
  /* 单栏时笔记本按同一条思路收：视口减去页眉、吸顶层留白与下面那条讲解的 280px */
  /* 笔记本同理：竖排后要给下面留出整整一条讲解。
     机身高 = 宽 / 1.5（模板图幅比例），band = 视口 − 页眉 − 吸顶层上边距 24 − 机身高，
     要 band ≥ 320 就得减掉 24 + 320 = 344，再乘回 1.5 得到宽度上限。
     双栏时不能这么减——那一档讲解在右栏，减了只会把机身白白缩小。 */
  .laptop { width: min(100%, calc((100svh - var(--stick-top) - 344px) * 1.5)); }
  /* 单栏时两页共用一套栅格，宽栏的比例设定不再适用 */
  .tour.is-wide { max-width: none; grid-template-columns: none; }
  .tour-steps { gap: 3vh; margin-top: 20px; }
  .tour-step { padding: 22px 20px; }
}

@media (max-width: 720px) {
  /* 720 以下页眉换成两行（品牌一行、六个导航一行），实测 101px */
  :root { --stick-top: 101px; }
  .tour-stage { display: block; }
  .tour-stick {
    position: relative; top: auto; z-index: auto;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    box-sizing: border-box; min-height: calc(100svh - var(--stick-top));
    padding: 20px 0 24px; background: none;
  }
  .tour-stick::before { display: none; }
  .phone {
    width: auto; max-width: 100%;
    height: clamp(340px, calc(100svh - var(--stick-top) - 100px), 450px);
    aspect-ratio: 1350 / 2760; overflow: visible; border-radius: 0;
    filter: drop-shadow(0 22px 36px rgba(0, 0, 0, .62));
  }
  .phone-screen {
    left: 5.3333%; top: 2.5%; width: 89.3333%; height: 95%;
    border: 0; border-radius: 16.1% / 7.4%; box-shadow: none;
  }
  .phone::after { display: block; }
  .phone .screen { object-fit: contain; object-position: center; }
  .phone { touch-action: pan-y; }

  .phone-gallery-pagination {
    display: flex; align-items: center; justify-content: center;
    margin-top: 8px;
  }
  .phone-gallery-pagination button {
    display: grid; place-items: center; width: 38px; height: 38px; padding: 0;
    border: 0; background: none; cursor: pointer;
  }
  .phone-gallery-pagination button span {
    display: block; width: 6px; height: 6px; border-radius: 50%;
    background: rgba(241, 248, 250, .24);
    transition: width 240ms var(--ease-out), border-radius 240ms var(--ease-out),
      background 240ms var(--ease-out);
  }
  .phone-gallery-pagination button[aria-pressed="true"] span {
    width: 18px; border-radius: 999px; background: var(--cyan);
  }
  .phone-gallery-pagination button:focus-visible { outline: 1px solid var(--cyan); outline-offset: -5px; }

  .mobile-tour-copy-heading {
    display: block; margin: 96px 0 0; padding: 0 0 30px;
    border-bottom: 1px solid rgba(241, 248, 250, .12);
  }
  .mobile-tour-copy-heading h2 { margin: 12px 0 0; color: var(--white); }
  html[lang="zh-CN"] .mobile-tour-copy-heading [lang="en"],
  html[lang="en"] .mobile-tour-copy-heading [lang="zh-CN"] { display: none; }
  .tour-steps { gap: 0; margin-top: 0; padding-bottom: 14vh; }
  .tour-step,
  .tour-step.is-live {
    max-width: none; padding: 38px 0 42px; border-radius: 0;
    border-bottom: 1px solid rgba(241, 248, 250, .1); background: transparent;
  }
  .step-detail { visibility: visible; transition: none; }
  .step-body,
  .step-facts { opacity: 1; transform: none; transition: none; }
  .step-name,
  .tour-step.is-live .step-name { color: rgba(115, 232, 255, .82); }
  .step-line,
  .tour-step.is-live .step-line {
    max-width: 24ch; margin-top: 12px; color: var(--white); font-size: 22px; line-height: 1.38;
  }
  .step-body { max-width: 34ch; margin-top: 16px; }
  .step-facts { max-width: none; margin-top: 22px; padding-top: 14px; gap: 8px 22px; }
  .step-facts li { white-space: normal; }

  .tour-step[data-step="qr"] {
    margin-top: 64px; padding: 34px 22px 30px; border: 1px solid rgba(241, 248, 250, .1);
    border-radius: 20px; background: rgba(241, 248, 250, .035);
  }
  .mobile-product-qr {
    display: block; box-sizing: border-box; width: min(56vw, 180px);
    margin: 26px auto 28px; padding: 11px; border-radius: 18px; background: #fff;
  }
  .mobile-product-qr img { display: block; width: 100%; height: auto; }
  .product-narration-tools { right: 14px; bottom: 14px; }
  .product-narration-play { width: 40px; padding: 0; font-size: 0; }
  .tour-steps { padding-bottom: 120px; }
}

@media (prefers-reduced-motion: reduce) {
  /* 减少动态效果：留下淡入淡出这类帮助理解的过渡，去掉位移、视角与漂移 */
  .screen { transition: opacity 200ms var(--ease-out), visibility 0s linear 200ms; transform: none; }
  .screen.is-on { transition: opacity 200ms var(--ease-out), visibility 0s; }
  .step-detail { transition: visibility 0s linear 200ms; }
  .step-body, .step-facts, .tour-step.is-live .step-body, .tour-step.is-live .step-facts {
    transform: none; transition: opacity 200ms var(--ease-out);
  }
  .phone, .laptop { transition: none; }
  .demo-toggle.is-loading .demo-play-icon::before { animation: none; }
}
