/* ============================================================================
   炭火烧烤 · 官网下载页
   ----------------------------------------------------------------------------
   极简设计 + 深色／浅色双主题。

   ## 极简做了什么（以及为什么）

   1. **去掉纯装饰**：首屏的照片背景、光晕、渐变、玻璃模糊、卡片盒子全部删掉。
      视觉重量交给字阶、留白和一条发丝线（hairline）。
   2. **一个元素只承担一个职责**：分隔用线、不用盒子；强调用颜色、不用投影。
   3. **只保留一个强调色**，且只出现在"要你点的地方"。
   4. **照片只在必要时出现**（三张场景图），不加边框与圆角盒子修饰。
   5. **保留一处动效**：首屏手机模型的轻微漂浮。它是页面上唯一的动效 ——
      在极简里，动效越少越要有理由，这一处的理由是"让静态截图显得是活的"。
      尊重 `prefers-reduced-motion`，系统要求减少动效时自动停。

   ## 双主题怎么做的

   - 颜色**只**通过 CSS 变量定义，组件里不出现任何字面量颜色（二维码白底除外，
     那是扫码对比度需要，不是配色）；
   - `:root[data-theme='dark'|'light']` 两组变量；`data-theme` 由 <head> 的内联脚本
     在**首次绘制前**设好，避免"先白后黑"的闪烁；
   - **默认深色**：`:root` 那组就是深色，且**不**做 `prefers-color-scheme` 兜底 ——
     没有 JS（或 JS 被禁用）时也落在深色上。浅色只会在用户显式点过切换后出现；
   - 声明 `color-scheme`，让滚动条、表单控件等系统 UI 跟着变；
   - 两套主题的正文对比度都有断言（见 tools/verify-site.mjs）。
   ========================================================================== */

/* ── 深色（默认） ── */
:root,
:root[data-theme='dark'] {
  color-scheme: dark;
  --bg: #0e0e10;
  --surface: #17171a;
  --text: #f4f4f5;
  --text-2: #a3a3ac;
  --text-3: #8b8b95;
  --line: #26262b;
  --line-strong: #34343b;
  --accent: #ff6a2b;
  --accent-text: #150a03;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  /*
   * 手机模型下方的投影色。
   * 深色底上用纯黑是看不见的，所以这里用一点暖色（炭火橙的低透明度）当"环境反光"，
   * 让悬浮感成立 —— 它是下方很淡的一片，不是描边光晕。
   */
  --phone-shadow: rgba(255, 106, 43, 0.5);
  /*
   * 悬浮在截图**之上**的控件（轮播左右箭头）的底色 / 描边 / 投影。
   *
   * 为什么不能直接复用 --surface 和 --line-strong：手机模型的机身色就是 --surface、
   * 描边色就是 --line-strong —— 箭头压在被压暗的两侧卡片上时，会跟机身边框糊成一团。
   * 所以这里给控件单独一组"比机身再亮一档"的值（实测过：不单独给就基本看不见）。
   */
  --control-bg: #212128;
  --control-line: #43434f;
  --control-shadow: 0 6px 18px -6px rgba(0, 0, 0, 0.8);
}

/* ── 浅色 ── */
:root[data-theme='light'] {
  color-scheme: light;
  --bg: #ffffff;
  --surface: #fafafa;
  --text: #18181b;
  --text-2: #55555e;
  --text-3: #6e6e78;
  --line: #e7e7ea;
  --line-strong: #d4d4d9;
  --accent: #c2410c;
  --accent-text: #ffffff;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  --phone-shadow: rgba(24, 24, 27, 0.42);
  --control-bg: #ffffff;
  --control-line: #cfcfd6;
  --control-shadow: 0 6px 18px -6px rgba(24, 24, 27, 0.3);
}

/*
 * 这里**故意没有** `@media (prefers-color-scheme: light)` 的兜底。
 * 早先有一段"没有 JS 时跟随系统偏好"的规则，它会让浅色系统的访客（以及脚本被拦下的
 * 访客）第一眼看到白色页面 —— 与"下载页默认深色"这条需求直接冲突。
 * 现在没读到 localStorage 里的显式选择，就落在 `:root` 的深色上。
 */

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* 主题切换用一个很短的过渡，避免"啪"地跳色；极简风格里不要更长的动画 */
  transition: background-color 0.18s ease, color 0.18s ease;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

p {
  margin: 0;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.wrap {
  width: min(100% - 48px, 1080px);
  margin-inline: auto;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 10px 16px;
  background: var(--accent);
  color: var(--accent-text);
  border-radius: 0 0 8px 0;
}
.skip-link:focus {
  left: 0;
}

/* 阅读进度：一条发丝线，克制但随时可读 */
.progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  transform: scaleX(0);
  transform-origin: left;
  background: var(--accent);
  z-index: 60;
  pointer-events: none;
}

/* ══════════════════════════ 导航 ══════════════════════════ */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  background: var(--bg);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease;
}
.nav.is-stuck {
  border-bottom-color: var(--line);
}
.nav__inner {
  display: flex;
  align-items: center;
  gap: 32px;
  height: 64px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  flex-shrink: 0;
}
.brand__mark {
  display: grid;
  place-items: center;
}
/*
 * 品牌标 = App 图标（一张 PNG，不再是内联 SVG 火焰）。
 * 24px 显示、48px 的源图 —— 2 倍屏上是 2x，够清晰；圆角由图标自己带（生成时就是圆角母版），
 * 所以这里不再叠 CSS 圆角，免得出现"两层圆角"。
 */
.brand__mark img {
  display: block;
  width: 24px;
  height: 24px;
}


.nav__actions {
  display: flex;
  align-items: center;
  gap: 10px;
  /*
   * 把右侧动作区推到容器右边缘。
   * 这行原本挂在被删掉的 .nav__links 上（它当时在中间当"撑杆"），
   * 链接删掉后必须挪到这里，否则按钮会贴到品牌名旁边。
   */
  margin-left: auto;
}

/* 图标按钮：主题切换与移动端菜单共用 */
.icon-btn {
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease;
}
.icon-btn:hover {
  color: var(--text);
  border-color: var(--line-strong);
}
/* 只显示"切过去会变成的那个主题"的图标 */
:root[data-theme='dark'] .icon-sun {
  display: none;
}
:root[data-theme='light'] .icon-moon {
  display: none;
}

/* ══════════════════════════ 按钮 / 链接 ══════════════════════════ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 40px;
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: 8px;
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.btn--lg {
  height: 46px;
  padding: 0 22px;
  font-size: 15px;
}
.btn--primary {
  background: var(--accent);
  color: var(--accent-text);
}
.btn--primary:hover {
  opacity: 0.88;
}
.btn.is-disabled {
  opacity: 0.45;
  pointer-events: none;
}

/* 次级动作（复制链接等）：文字链而非按钮，避免与主按钮抢视线 */
.link-quiet {
  border: 0;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 14px;
  color: var(--text-2);
  cursor: pointer;
  border-bottom: 1px solid var(--line-strong);
  transition: color 0.18s ease, border-color 0.18s ease;
}
.link-quiet:hover {
  color: var(--text);
  border-bottom-color: var(--accent);
}

/* ══════════════════════════ 首屏 ══════════════════════════ */
.hero {
  padding: 152px 0 96px;
  /*
   * 轮播两侧的卡片是"转出去"的，投影会伸到列宽之外（窄屏上会伸到视口外）。
   * 用 overflow-x: clip 而不是 hidden —— clip 不生成滚动容器，
   * 页面不会因此多出一个横向滚动，锚点跳转与 position: fixed 的导航也不受影响。
   */
  overflow-x: clip;
}
.hero__inner {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 64px;
  align-items: center;
}
.hero h1 {
  font-size: clamp(34px, 4.4vw, 54px);
  letter-spacing: -0.035em;
  line-height: 1.12;
  margin-bottom: 22px;
}
.lede {
  font-size: clamp(15.5px, 1.25vw, 17px);
  color: var(--text-2);
  max-width: 34em;
  /*
   * 让浏览器把这段"均匀摊到两行"，而不是出现"只用 / 一个 App。"这种
   * 把完整短语劈开的孤行。不支持的浏览器会忽略，回退成普通断行。
   */
  text-wrap: balance;
}
.lede strong {
  color: var(--text);
  font-weight: 600;
}
.hero__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 34px;
}
.hero__detect {
  margin-top: 18px;
  font-size: 14px;
  color: var(--text-2);
}
.hero__detect:empty {
  display: none;
}
.hero__detect strong {
  color: var(--text);
  font-weight: 600;
}

.hero__device {
  display: grid;
  place-items: center;
}

/* ══════════════════ 首屏：三张真实截图的 3D 轮播 ══════════════════
 *
 * 形态是 coverflow：中间一张正对镜头，左右两张各自向外平移、后退并侧转。
 * 三个"为什么"记在这里，改的时候不容易改坏：
 *
 * ① 为什么三张卡片叠在**同一个 grid 格子**里（grid-area: 1/1），而不是
 *    position: absolute：这样舞台高度由最高的一张自然撑开。写死高度在窄屏上
 *    会把手机压变形，而绝对定位会让容器高度塌成 0。
 * ② 为什么 perspective 放在**舞台**上而不是每张卡片上：三张共用一个视点，
 *    透视才一致；每张各设一个 perspective 等于三个消失点，看着是"三张各自歪"。
 * ③ 为什么两侧的卡片用 opacity 压暗而不是加遮罩：投影已经交给 .phone 的
 *    box-shadow 了，再叠一层遮罩会让深色主题下的边缘发灰。
 */
.shots {
  position: relative;
  /* z-index:0 建立层叠上下文：卡片各自的 z-index 只在本轮播内比较，
     不会跟导航栏、进度条这些页面级元素相互影响 */
  z-index: 0;
  width: min(268px, 62vw);
  /* 给绝对定位的说明文字留出位置（机身下方 14px + 一行字）。
     用 margin 而不是 padding：padding 会把 top:50% 的中心线推低。 */
  margin-bottom: 40px;
}

.shots__stage {
  display: grid;
  /*
   * 列宽钉成 100%（= .shots 的宽度）。
   * 不写这行的话，auto 列会被截图的**固有宽度**（780px）撑开 ——
   * 网格轨道先按 min-content 取尺寸，而图片在百分比宽度下算 min-content 时
   * 要回退到固有宽度，于是整个舞台高到 1700+px，手机模型里的图被拉出框外。
   */
  grid-template-columns: 100%;
  perspective: 1200px;
  perspective-origin: 50% 42%;
  transform-style: preserve-3d;
}

/*
 * 初始位置**写在 HTML 的 data-pos 上**（0 / -1 / 1），不是等 JS 来画：
 * 页面没有 JS 时三张图仍然是正常的 coverflow，也不会出现"先叠在一起再散开"的一帧。
 * JS 只负责在切换时改写这三个值。
 */
.shot {
  grid-area: 1 / 1;
  /* 说明文字以自己为定位基准（top:100% 落在机身下方） */
  position: relative;
  /* min-width:0：网格项默认的 min-width:auto 会拒绝收缩到内容宽度以下 */
  min-width: 0;
  margin: 0;
  transform-origin: 50% 50%;
  /* 只动 transform / opacity：过渡期间不触发重排，旁边的标题与按钮不会跟着抖 */
  transition: transform 0.72s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.5s ease;
  will-change: transform, opacity;
}
.shot[data-pos='0'] {
  transform: translate3d(0, 0, 0) rotateY(0deg) scale(1);
  opacity: 1;
  z-index: 3;
}
.shot[data-pos='-1'] {
  transform: translate3d(-58%, 0, -130px) rotateY(26deg) scale(0.84);
  opacity: 0.5;
  z-index: 2;
}
.shot[data-pos='1'] {
  transform: translate3d(58%, 0, -130px) rotateY(-26deg) scale(0.84);
  opacity: 0.5;
  z-index: 2;
}

/*
 * 每张图的说明只在自己转到正面时显形。
 *
 * 用绝对定位"挂"在机身下方（top:100%），而不是留在文档流里：
 *   ① 舞台高度就只剩机身高度，左右两个箭头用 top:50% 才是**机身的垂直中心**，
 *      否则会连同说明文字一起被算进去、整体偏下十几像素；
 *   ② 三个说明文字互相叠在同一位置，切换时是原地淡入淡出，不会把下方的标题推来推去。
 * 占位交给 .shots 的 margin-bottom（见上），不是 padding —— padding 同样会把
 * 箭头的中心线推低。
 */
.shot__cap {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 14px);
  text-align: center;
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--text-2);
  opacity: 0;
  transition: opacity 0.5s ease;
}
.shot[data-pos='0'] .shot__cap {
  opacity: 1;
}

/* 手机模型：细边框 + 漂浮动效 */
.phone {
  /* position + z-index:0 建立层叠上下文，让下方的投影 ::after 待在机身背后，
     同时又不会被祖先元素的背景盖住 */
  position: relative;
  z-index: 0;
  margin: 0;
  width: min(268px, 62vw);
  border: 1px solid var(--line-strong);
  border-radius: 28px;
  padding: 8px;
  background: var(--surface);
  /* 基础投影：动画接管后每一帧都会重写它，这里只是无动画时的兜底 */
  box-shadow: 0 10px 20px -8px var(--phone-shadow);
}
.phone img {
  border-radius: 20px;
  width: 100%;
  /*
   * height:auto 不能省。
   * 截图标签上写了 width/height（780×1688），浏览器会把它当成**表现性提示**
   * 落成 `height:1688px`；只覆盖宽度的话，高度还是 1688px —— 手机模型里会伸出一张
   * 竖得离谱的图（真实踩过：舞台被撑到 1745px 高）。
   * 保留属性是有意的：它给浏览器正确的宽高比，图没加载完也不会跳动。
   */
  height: auto;
}
/* 轮播里的手机宽度由卡片决定（卡片的宽度又由 .shots 决定），
   这样三张图永远等宽，不会因为某张截图的原始尺寸不同而参差 */
.shot .phone {
  width: 100%;
}

/*
 * 让静态截图"活"起来的那处动效 —— 三张轮播图**每张都有**（需求原文：
 * "每张图展示都有浮动效果"），不是只让正面那张浮。
 *
 * 好看的关键不在位移大小，而在**三个动作一起做**：
 *   ① 垂直位移 ±5px —— 主体；
 *   ② 极小的旋转 ±0.5° —— 边缘透视一直在微变，眼睛才会把它读成三维物体，
 *      只做平移会像"图片在上下滑动"；
 *   ③ 极小的缩放 1 → 1.008 —— 配合远近，升起时略微变大。
 *
 * 周期 9s、ease-in-out：慢到不抢注意力，又能被余光感知。
 * 只动 transform，不动布局 —— 不会引起重排，也不会让旁边文字跟着抖。
 */
.phone--float {
  animation: phone-float 9s cubic-bezier(0.45, 0, 0.55, 1) infinite;
  will-change: transform;
}
/*
 * 影子：漂浮感的另一半。机身升起时影子**更大更淡**、落下时更小更实 ——
 * 这是人眼判断"离地多高"的依据。
 *
 * 实现上直接动画机身自己的 box-shadow，而不是用 ::after 加一层伪元素：
 * 伪元素要靠 z-index:-1 待在机身背后，而机身为了别的目的已经建立了层叠上下文，
 * 结果那层影子实测**根本没被绘制**（调色再浓也看不见）。box-shadow 没有这个问题，
 * 代价是每帧重绘 —— 现在是三台（轮播里每张一次）。三台的投影本来就要各自跟着
 * 自己的机身走，所以这个代价换的是对的观感；真要再省，只能改成"只给正面那张开"，
 * 代价是另外两张会像是贴纸。
 */
@keyframes phone-float {
  0%,
  100% {
    transform: translate3d(0, 5px, 0) rotate(-0.5deg) scale(1);
    box-shadow: 0 10px 20px -8px var(--phone-shadow);
  }
  50% {
    transform: translate3d(0, -5px, 0) rotate(0.5deg) scale(1.008);
    box-shadow: 0 22px 34px -10px var(--phone-shadow);
  }
}

/*
 * 三台手机错开相位（-3s / -6s）。
 * 三张图若同起同落，整块区域会像"一个东西在呼吸"，反而假；错开之后每台各自浮动，
 * 才像三台真机摆在一起。9s 周期下 -3s 正好是三分之一，相位均匀。
 */
.shot:nth-child(2) .phone--float {
  animation-delay: -3s;
}
.shot:nth-child(3) .phone--float {
  animation-delay: -6s;
}

/* 指针悬停或键盘聚焦时暂停：屏幕里是真实界面，想细看时不应该还在动 */
.phone--float:hover,
.phone--float:focus-within {
  animation-play-state: paused;
}

/* ── 左右箭头：贴着机身两侧、与机身垂直居中 ──
 *
 * 为什么是"压在两旁"而不是"排在下面一行"：
 *   首屏右下角的空间本来就窄，控件排在下面会把视线从截图上拉走；贴在两侧时，
 *   眼睛不用离开手机就能点到。两侧的卡片是压暗的，箭头用不透明底色浮在它们之上，
 *   层级一眼可辨（z-index 高于卡片）。
 *
 * 为什么是圆形 + 描边 + 实底：
 *   圆形与手机模型的圆角是一套语言；实底是为了在任何一张截图（有深有浅）上方
 *   都能看清 —— 透明底放在明亮截图上会糊掉。
 */
.shots__arrow {
  position: absolute;
  top: 50%;
  /* translateY(-50%) 让按钮的**中心**落在机身中线上；只有配合上面两条
     （说明文字绝对定位、占位用 margin）这里的 50% 才等于机身中心 */
  transform: translateY(-50%);
  z-index: 4; /* 高于三张卡片（正面 3 / 两侧 2） */
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--control-line);
  border-radius: 999px;
  background: var(--control-bg);
  color: var(--text-2);
  cursor: pointer;
  /*
   * 两段投影：
   *   ① 一圈与页面同色的"抠边"（0 0 0 4px --bg）—— 箭头压在被压暗的两侧卡片上时，
   *      这一圈把按钮从卡片内容里"抠"出来，不只靠描边分辨；
   *   ② 一层很淡的下投影，让按钮像浮在卡片之上。
   * 顺序不能反：写在前面的一层画在上面。
   */
  box-shadow: 0 0 0 4px var(--bg), var(--control-shadow);
  transition: color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
/* 外侧各退出半个按钮 + 一点空隙：既不压住正面那张，又离机身足够近 */
.shots__arrow--prev {
  left: -52px;
}
.shots__arrow--next {
  right: -52px;
}
.shots__arrow:hover {
  color: var(--text);
  border-color: var(--accent);
  /* 悬停时向外轻推 2px：方向感由位移给，不是只换个颜色 */
  transform: translateY(-50%) scale(1.06);
}
.shots__arrow--prev:hover {
  transform: translateY(-50%) translateX(-2px) scale(1.06);
}
.shots__arrow--next:hover {
  transform: translateY(-50%) translateX(2px) scale(1.06);
}
.shots__arrow:active {
  transform: translateY(-50%) scale(0.96);
}
/* 没有 JS 时收起：点不动的按钮摆在那里，只会让人以为页面坏了 */
.shots:not(.is-live) .shots__arrow {
  display: none;
}

/* ══════════════════════════ 区块 ══════════════════════════ */
.section {
  padding: 104px 0;
  border-top: 1px solid var(--line);
}
/* 最后一个区块下面只有页脚，下留白收薄；留白过厚会显得页面尾部空荡 */
.section:last-of-type {
  padding-bottom: 56px;
}
.section__head {
  max-width: 640px;
  margin-bottom: 56px;
}
.section__head h2 {
  font-size: clamp(25px, 2.6vw, 34px);
  text-wrap: balance;
}
.section__sub {
  margin-top: 14px;
  color: var(--text-2);
  font-size: 16px;
}

/* ── 三种角色：文字 + 国内场景配图 + 真实界面截图 ──
   不加卡片盒子，只用发丝线分区；界面截图放成小图并带中文说明，
   既证明"这是真实在跑的应用"，也避免把小图放大成视觉噪声。 */
.role {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 56px;
  align-items: start;
  padding: 56px 0;
  border-top: 1px solid var(--line);
}
.role:first-of-type {
  border-top: 0;
  padding-top: 0;
}
/*
 * 最后一块不需要下内边距：它下面没有同类内容要分隔。留着的话，
 * 它会和区块容器的下留白叠在一起（56 + 104 = 160px），页面底部就显得"没写完"。
 */
.role:last-of-type {
  padding-bottom: 0;
}
.role--flip .role__body {
  order: 2;
}
.role__index {
  font-size: 12.5px;
  letter-spacing: 0.1em;
  color: var(--text-3);
  margin-bottom: 12px;
}
.role h3 {
  font-size: clamp(20px, 2vw, 24px);
  margin-bottom: 14px;
}
.role__lead {
  color: var(--text-2);
  margin-bottom: 22px;
}
.steps {
  list-style: none;
  counter-reset: step;
  padding: 0;
  margin: 0 0 20px;
  display: grid;
  gap: 12px;
}
.steps li {
  position: relative;
  padding-left: 26px;
  color: var(--text-2);
  font-size: 14.8px;
}
.steps li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0.42em;
  font-size: 12px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.steps b {
  color: var(--text);
  font-weight: 600;
  margin-right: 8px;
}
.role__media {
  display: grid;
  gap: 18px;
}
.role__photo {
  margin: 0;
  border-radius: 4px;
  overflow: hidden;
}
.role__photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: center 45%;
}

/* ══════════════════════════ 首屏下载控件 ══════════════════════════
   一个分段按钮：左边直接下载、右边下拉切换平台。
   指针移到控件上（或键盘聚焦进来）时，右侧浮出扫码入口 ——
   这样"知道自己是啥系统的"和"想先在手机上试的"两类人都不用离开首屏。 */
.dlc {
  position: relative;
  display: inline-flex;
  align-items: stretch;
}
/* 左半：主按钮，右侧直角与下拉键拼在一起 */
.dlc__main {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
.dlc__caret {
  display: grid;
  place-items: center;
  width: 38px;
  padding: 0;
  border: 0;
  border-left: 1px solid rgba(0, 0, 0, 0.16);
  border-radius: 0 8px 8px 0;
  background: var(--accent);
  color: var(--accent-text);
  cursor: pointer;
}
.dlc__caret:hover {
  opacity: 0.88;
}

/* 下拉菜单：发丝线 + 纯色底，不用投影 */
.dlc__menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 6;
  min-width: 208px;
  padding: 6px;
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: 10px;
}
.dlc__menu[hidden] {
  display: none;
}
.dlc__menu button {
  /* button 需要显式重置：否则会带上浏览器默认的边框、底色与居中文字 */
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: 6px;
  background: none;
  font-family: inherit;
  font-size: 14.5px;
  color: var(--text-2);
  text-align: left;
  cursor: pointer;
}
.dlc__menu button em {
  font-style: normal;
  font-size: 12.4px;
  color: var(--text-3);
}
.dlc__menu button:hover,
.dlc__menu button:focus-visible {
  background: var(--surface);
  color: var(--text);
}
/* 当前选中的平台：用勾号而不是背景块，保持克制 */
.dlc__menu button[aria-current='true'] {
  color: var(--text);
}
.dlc__menu button[aria-current='true'] span::after {
  content: '✓';
  margin-left: 6px;
  color: var(--accent);
}

/* 扫码入口：浮在控件右侧，避免和下拉菜单抢位置 */
.dlc__qr {
  position: absolute;
  /*
   * 放在按钮**下方**而不是右侧：
   * 右侧居中会向上盖住首屏那段说明文字，下方是空白区，展开时不打扰任何已有内容。
   * 下拉菜单也在下方 —— 两者互斥（菜单展开时二维码隐藏），不会叠在一起。
   */
  top: calc(100% + 10px);
  left: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px 10px 10px;
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.16s ease, visibility 0.16s ease;
  z-index: 5;
}
/*
 * 用 :hover 与 :focus-within 一起触发。
 * 只写 :hover 的话键盘用户永远看不到二维码（聚焦不等于悬停）。
 */
.dlc:hover .dlc__qr,
.dlc:focus-within .dlc__qr {
  opacity: 1;
  visibility: visible;
}
/* 下拉菜单展开时把二维码收起来，避免两个浮层叠在一起 */
.dlc.is-menu-open .dlc__qr {
  opacity: 0;
  visibility: hidden;
}
.dlc__qr img {
  width: 112px;
  height: 112px;
  padding: 5px;
  background: #ffffff; /* 扫码对比度需要，不是配色 */
  border-radius: 4px;
  flex-shrink: 0;
}
.dlc__qr-text {
  /* min-width 是关键：没有它，flex 会把文字块压到极限窄，
     地址就会被拆成一列单字（第一版就是这样） */
  min-width: 168px;
  max-width: 208px;
}
.dlc__qr p {
  font-size: 13px;
  color: var(--text-2);
  white-space: nowrap;
}
.dlc__qr-url {
  display: block;
  margin-top: 6px;
  overflow-wrap: anywhere;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.6px;
  color: var(--text-3);
  word-break: break-all;
}

/*
 * 下拉菜单展开时把下方的提示文字隐去。
 * 菜单是浮层（absolute），会盖住紧跟其后的识别提示 —— 不处理的话
 * 会出现"菜单压着半句提示、右边还露着字"的观感。淡出比直接消失自然。
 */
/*
 * 提示文字是 .hero__actions 的**后续兄弟**，所以走 :has() + ~ 这条路：
 * 只要控件处于 hover / 聚焦 / 菜单展开，就把下方提示淡出，避免浮层压字。
 * （不要指向 hero__copy 那个类 —— 它早就随清理空类删掉了，写了也匹配不到。）
 * 老浏览器不支持 :has() 时只是提示不被淡出，功能不受影响。
 */
.hero__actions:has(.dlc:hover) ~ .hero__detect,
.hero__actions:has(.dlc:focus-within) ~ .hero__detect,
.hero__actions:has(.dlc.is-menu-open) ~ .hero__detect {
  opacity: 0;
}
.hero__detect {
  transition: opacity 0.12s ease;
}

/* 首屏的状态提示（识别结果 / 离线） */
.hero__offline {
  margin-top: 10px;
  font-size: 13.6px;
  color: var(--text-2);
}
.hero__offline[hidden] {
  display: none;
}

/* ══════════════════════════ 页脚 ══════════════════════════ */
.footer {
  border-top: 1px solid var(--line);
  /* 只剩版权与素材署名一行，上内边距不必再撑那么高 */
  padding: 28px 0;
}
.footer__bottom {
  /* 页脚只剩版权一行，居中显示 */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  text-align: center;
  color: var(--text-3);
  font-size: 12.6px;
}

/* ══════════════════════════ 回到顶部 ══════════════════════════ */
.to-top {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 55;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg);
  color: var(--text-2);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  box-shadow: var(--shadow);
}
.to-top[hidden] {
  display: none;
}
.to-top:hover {
  color: var(--text);
  border-color: var(--line-strong);
}

/* ══════════════════════════ 响应式 ══════════════════════════ */
@media (max-width: 1000px) {
  .hero {
    padding-top: 128px;
  }
  .hero__inner {
    grid-template-columns: 1fr;
    gap: 56px;
  }
  /*
   * 单列时轮播居中（原来是 start）。
   * 3D 轮播的左右两张是向外散开的，靠左对齐会让左边那张直接顶出视口；
   * 居中之后两侧对称地探出去，才是 coverflow 该有的样子。
   */
  .hero__device {
    justify-content: center;
  }
  .role,
  .role--flip {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .role--flip .role__body {
    order: 0;
  }
  }

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

@media (max-width: 620px) {
  .wrap {
    width: min(100% - 32px, 1080px);
  }
  .section {
    padding: 72px 0;
  }
  .hero {
    padding: 112px 0 64px;
  }
  .hero__actions .btn--primary {
    flex: 1;
  }
  .to-top span {
    display: none;
  }
  .to-top {
    width: 38px;
    padding: 0;
    justify-content: center;
  }
  }

/* 尊重系统的"减少动态效果"：手机的漂浮动画在这里被一并关掉 */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}


/* ══════════════════════════ 语言切换 ══════════════════════════
 * 与主题按钮同高、同边框；文字按钮而不是图标，避免用户猜“EN”是干嘛的。
 * 62px 足够容纳“中文”与“EN”，且在窄屏上不会挤压品牌与主题按钮。
 */
.lang-btn {
  height: 36px;
  min-width: 52px;
  padding: 0 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: transparent;
  color: var(--text-2);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease;
}
.lang-btn:hover {
  color: var(--text);
  border-color: var(--line-strong);
}
