/* ==========================================================================
   白膜实测库 · 全站样式
   设计基底：整站是一块「打印台」，模型卡是台面上的白膜。
   零外部依赖：系统字体栈 + 纯 CSS，不加载任何境外资源。
   ========================================================================== */

:root{
  /* 打印台 */
  --bed:        #EFF0EC;
  --bed-deep:   #E2E4DE;
  --bed-line:   #D4D7CF;
  /* 白膜 */
  --shell:      #FBFBF9;
  --shell-2:    #F4F5F1;
  --line:       #DBDDD6;
  /* 墨 */
  --ink:        #1E231F;
  --ink-70:     #4E554E;
  --ink-45:     #868D86;
  /* 判定色：全站唯一的彩色来源 */
  --ok:         #2F6B46;
  --ok-bg:      #E1EDE5;
  --luck:       #8F6510;
  --luck-bg:    #F3E9D2;
  --black:      #9C3A2D;
  --black-bg:   #F1DFDB;

  --sans: -apple-system, BlinkMacSystemFont, "PingFang SC", "HarmonyOS Sans SC",
          "Source Han Sans SC", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --r:   14px;
  --maxw: 1120px;
  /* 吸顶导航高度。首屏现在是两栏版（不从导航底下穿过），这个值暂时没有使用者，
     留着是给"图片通栏出血"那种版式备用的 —— 那时 .plate 会用它做负边距。 */
  --navh: 55px;

  /* 全站颗粒强度（胶片噪点的不透明度）。想更淡就调小，想更"旧"就调大，
     0 到 .85 是可用区间；超过 .6 会开始显脏。 */
  --grain: .26;

  /* 首屏文字组的呼吸感：这 6 个值决定整组文字的上下间距。
     下面是当初挑定的 sp=3「宽松」那一档。 */
  --hero-gap-kicker: 38px;   /* kicker → 大标题 */
  --hero-gap-h1:     30px;   /* 大标题 → 导语 */
  --hero-gap-lead:   48px;   /* 导语 → 按钮 */
  --hero-gap-btns:   40px;   /* 按钮下方的留白（按钮已是文字组最后一项） */
  --hero-lh-h1:      1.28;   /* 大标题行高 */
  --hero-lh-lead:    2.05;   /* 导语行高 */
}

*{ box-sizing: border-box; }

html{ -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 76px; }

body{
  margin: 0;
  background: var(--bed);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.75;
  font-feature-settings: "tnum";
}

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

.wrap{ width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }

/* --------------------------------------------------------------- 顶栏 */
/* 首屏是满屏视频，顶栏整条透明、文字反白，视频从它底下穿过。
   左右两端的对齐线和首屏内容块一致（都是 max(20px, 8vw)）：
   品牌在左与 kicker 平行，三个链接在右与它对称。
   滚过首屏后由脚本加 .nav--solid 切回浅色毛玻璃，否则压在白色内容上会读不清。 */
.nav{
  position: sticky; top: 0; z-index: 40;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color .25s ease, border-color .25s ease;
}
.nav__in{
  max-width: none; margin: 0;
  padding: 12px max(20px, 8vw);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.nav .brand{ color: #fff; }
.nav .brand__mark{
  border-color: rgba(255,255,255,.85);
  background: repeating-linear-gradient(180deg, rgba(255,255,255,.92) 0 3px, rgba(255,255,255,.3) 3px 4px);
}
.nav .nav__links a{ color: rgba(255,255,255,.82); }
/* 只给有鼠标的设备：手机没有悬停，点一下会把悬停态"粘"在元素上 */
@media (hover: hover){ .nav .nav__links a:hover{ color: #fff; } }
.nav .nav__links a[aria-current]{ color: #fff; border-bottom-color: #fff; }

/* 滚过首屏后的实底状态（必须排在透明态之后：同权重时后者生效） */
.nav--solid{
  background: rgba(239,240,236,.78);
  -webkit-backdrop-filter: saturate(1.4) blur(10px);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom-color: rgba(212,215,207,.6);
}
.nav--solid .brand{ color: var(--ink); }
.nav--solid .brand__mark{
  border-color: var(--ink);
  background: repeating-linear-gradient(180deg, var(--shell) 0 3px, #CFD2CA 3px 4px);
}
.nav--solid .nav__links a{ color: var(--ink-70); }
@media (hover: hover){ .nav--solid .nav__links a:hover{ color: var(--ink); } }
.nav--solid .nav__links a[aria-current]{ color: var(--ink); border-bottom-color: var(--ink); }

.brand{ display: flex; align-items: center; gap: 10px; text-decoration: none; font-weight: 700; letter-spacing: .01em; transition: color .25s ease; }
/* 品牌标记 = 三条层纹，FDM 的签名特征 */
.brand__mark{
  width: 22px; height: 22px; border-radius: 5px; flex: none;
  transition: border-color .25s ease, background .25s ease;
}
.nav__links{ display: flex; gap: 22px; font-size: 14.5px; }
.nav__links a{ text-decoration: none; padding: 2px 0; border-bottom: 1.5px solid transparent;
  transition: color .25s ease, border-color .25s ease; }
/* 顶栏高亮：单页版用 aria-current="location"（页内定位），旧页用 "page"，一并覆盖 */
.nav__links a[aria-current]{ font-weight: 600; }

/* --------------------------------------------------------------- 首屏打印台 */
/* 整块台面上提一个导航的高度：首屏视频因此顶到浏览器最上沿（y=0），
   吸顶导航是 sticky + z-index:40，会浮在视频之上、从它底下穿过 —— 和 Loadex 一致
   （那边视频的 box 就是 0,0 铺满整屏）。 */
.plate{
  margin-top: calc(var(--navh) * -1);
  background:
    linear-gradient(var(--bed-line) 1px, transparent 1px) 0 0 / 100% 28px,
    linear-gradient(90deg, var(--bed-line) 1px, transparent 1px) 0 0 / 28px 100%,
    var(--bed-deep);
  border-bottom: 1px solid var(--line);
  position: relative;
  overflow: hidden;
}
.plate::after{
  /* 台面边缘的轻微暗角，让网格不至于平铺到边 */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(120% 80% at 50% 30%, rgba(255,255,255,.55), rgba(255,255,255,0) 70%);
}
.plate > *{ position: relative; z-index: 1; }
/* --------------------------------------------------------------- 首屏 */
/* 满屏视频首屏（100vh）：视频铺底，文案压在左侧中部。
   比例照搬 Loadex 的 home-banner-section —— 首屏正好一屏、内容块约占视口宽 43%、垂直居中，
   等于把整个第一屏让给视频；下面「最近打过的」自然落到折线以下。 */
.hero{ padding: 0; }

.hero__stage{
  position: relative;
  height: 100vh;
  height: 100svh;          /* 手机地址栏场景用 svh；老内核退回上一行 */
  overflow: hidden;        /* 视频放大时不越界 */
}

/* 背景视频：铺满整屏。底部留一小段羽化（只吃最后 12%），
   和下面的台面网格柔和交接，同时不影响"满屏"的观感。 */
.hero__media{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 45%;
  background: #0d1210;     /* 视频是暗调：解码前先铺深色，不闪白 */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 88%, transparent 100%);
  -webkit-mask-composite: source-over;
  mask-image: linear-gradient(to bottom, #000 0%, #000 88%, transparent 100%);
  mask-composite: add;
}

/* 压暗罩：实测这段视频顶部偏亮，白字直接压上去会糊。
   一层自上而下（保导航与标题）+ 一层自左向右（保左侧文字区）。
   和视频共用同一条底部羽化，否则会在下沿留一道暗边。 */
.hero__scrim{
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(10,14,12,.55) 0%, rgba(10,14,12,.26) 30%, rgba(10,14,12,.44) 100%),
    linear-gradient(90deg, rgba(10,14,12,.42) 0%, rgba(10,14,12,.18) 45%, rgba(10,14,12,0) 72%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 88%, transparent 100%);
  -webkit-mask-composite: source-over;
  mask-image: linear-gradient(to bottom, #000 0%, #000 88%, transparent 100%);
  mask-composite: add;
}

/* 叠字层：铺满首屏，内容垂直居中。
   左边距按视口百分比给（Loadex 的内容块左缘在 8.2% 处），比全站 1120px 栅格再靠左一点；
   只影响首屏，下面各区块的对齐线不动。 */
.hero__over{
  position: absolute; inset: 0; z-index: 2;
  display: flex; align-items: center;
  pointer-events: none;
}
.hero__over > .wrap{
  width: 100%; max-width: none;
  padding-left: max(20px, 8vw);
  padding-right: 20px;
}
/* 内容块：约视口宽的 43%（Loadex 是 616/1416），和它一样居中放置 */
.hero__group{ position: relative; max-width: 620px; pointer-events: auto; }

/* 文字压在暗视频上 → 全部反白，并给半透明底或描边保证可读 */
.hero__kicker{
  display: inline-block; font-size: 13px; color: rgba(255,255,255,.94);
  background: rgba(12,16,14,.45); border: 1px solid rgba(255,255,255,.28);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  padding: 4px 11px; border-radius: 999px; margin-bottom: var(--hero-gap-kicker);
}
.hero h1{
  margin: 0 0 var(--hero-gap-h1);
  font-size: clamp(32px, 6.4vw, 62px);
  line-height: var(--hero-lh-h1);
  letter-spacing: -.02em;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 2px 22px rgba(0,0,0,.3);
}
.hero__lead{
  margin: 0 0 var(--hero-gap-lead); max-width: 32em;
  font-size: clamp(15px, 3.4vw, 17px);
  line-height: var(--hero-lh-lead);
  color: rgba(255,255,255,.9);
  text-shadow: 0 1px 14px rgba(0,0,0,.28);
}
.hero__btns{ display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: var(--hero-gap-btns); }

/* 视频上的按钮要反过来：主按钮白底深字、次按钮透明 + 白描边。
   （下面各区块的按钮仍是深底浅字，所以这里限定在 .hero__over 里） */
.hero__over .btn{ background: #fff; color: var(--ink); border-color: #fff; }
.hero__over .btn--ghost{ background: transparent; color: #fff; border-color: rgba(255,255,255,.72); }
@media (hover: hover){ .hero__over .btn--ghost:hover{ background: rgba(255,255,255,.16); opacity: 1; } }

/* --------------------------------------------------------------- 按钮 */
.btn{
  display: inline-flex; align-items: center; justify-content: center;
  padding: 13px 22px; border-radius: 10px;
  font: inherit; font-weight: 600; font-size: 15.5px;
  text-decoration: none; cursor: pointer;
  border: 1.5px solid var(--ink);
  background: var(--ink); color: var(--shell);
  transition: opacity .15s ease;
}
.btn--ghost{ background: transparent; color: var(--ink); }
/* 只给有鼠标的设备：手机没有悬停，点一下会把悬停态"粘"在元素上 */
@media (hover: hover){
  .btn:hover{ opacity: .86; }
  .btn--ghost:hover{ background: rgba(30,35,31,.06); opacity: 1; }
}
.btn--wide{ width: 100%; }
.btn--sm{ padding: 9px 15px; font-size: 14px; border-radius: 8px; }
.btn[disabled]{ opacity: .4; cursor: not-allowed; }

:focus-visible{ outline: 2.5px solid var(--ink); outline-offset: 2px; }

/* --------------------------------------------------------------- 首页缩略图
   .peek 本身不限宽，所以卡片带会铺满整个屏幕；标题单独用 .wrap 锁在文字列里。
   （不用 100vw：那会把滚动条宽度算进去，多出一条横向滚动。） */
.peek{ padding: 0 0 48px; }
.peek__head{
  /* 限宽 + 居中，但左右不加内边距 —— 其余区块被 .section 的 padding 覆盖后
     也是没有内边距的，这样两边标题才落在同一条左边线上。 */
  width: 100%; max-width: var(--maxw); margin-inline: auto; margin-bottom: 16px;
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px;
}
.peek__head h2{ font-size: 18px; margin: 0; }
.peek__head a{ font-size: 14px; color: var(--ink-70); }
/* 跑马灯：一份卡片总宽超过容器，所以套一层裁剪轨道。
   左右两端做了一点羽化，卡片进出不是硬切边。 */
.peek__rail{
  overflow: hidden;
  /* 比 1120 的文字列宽出来一点，但不是满屏：每边多 --peek-bleed。
     想更宽/更窄只改这一个数（100% 那层是给手机兜底的，窄屏自然就满宽了）。 */
  --peek-bleed: 80px;
  width: min(calc(var(--maxw) + var(--peek-bleed) * 2), 100%);
  /* 上下留这么多空白是给卡片投影用的：rail 裁掉了溢出，不留就被削平。
     悬停时投影往下伸得最远（18px 偏移 + 34px 模糊 = 52px），所以下边留够 56px。
     负 margin 把多出来的高度抵掉，区块总高度和以前一样。 */
  margin: -18px auto -44px;   /* 左右 auto：带子居中（写在 padding 前面不影响，但别被下面的 margin 简写盖掉） */
  padding: 26px 0 56px;
  /* 两端羽化：卡片进出是渐隐的，不是被切一刀。约等于四分之一张卡片宽。 */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 72px, #000 calc(100% - 72px), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 72px, #000 calc(100% - 72px), transparent 100%);
}
.peek__track{
  display: flex; align-items: flex-start; width: max-content;
  animation: peekDrift 70s linear infinite;
}
/* 鼠标移上来、或者键盘 Tab 到某张卡，就先停住，方便点开 */
@media (hover: hover){ .peek__rail:hover .peek__track{ animation-play-state: paused; } }
.peek__rail:focus-within .peek__track{ animation-play-state: paused; }
/* 手机没有悬停：手指按住卡片带就停（.is-held 由 index.html 的触摸脚本挂上） */
.peek__rail.is-held .peek__track{ animation-play-state: paused; }
/* 轨道里装的是「两份一模一样的卡片」，所以平移一半正好无缝接回起点。
   卡片间距用 margin-right 而不是 gap —— 用 gap 的话平移量会差半个间距，接缝会跳。 */
@keyframes peekDrift{ from{ transform: translateX(0); } to{ transform: translateX(-50%); } }

/* 卡片造型：竖长比例 + 大圆角（比参考图收一点）+ 很淡的一层投影。
   底色、描边、文字色全部沿用站内变量，不引入新颜色。 */
.thumb{
  flex: none; width: 320px; margin-right: 24px;
  aspect-ratio: 4 / 5;
  display: flex; flex-direction: column; overflow: hidden;
  padding: 0; font: inherit; color: inherit; text-align: left; cursor: pointer;
  background: var(--shell); border: 1px solid var(--line);
  border-radius: 20px;
  box-shadow: 0 1px 3px rgba(30,35,31,.05), 0 10px 24px rgba(30,35,31,.07);
  transition: transform .22s ease, box-shadow .22s ease, border-color .22s ease;
}
/* 悬停：轻轻抬起一点，投影略深，颜色仍然克制 */
@media (hover: hover){
  .thumb:hover{
    transform: translateY(-4px);
    border-color: var(--bed-line);
    box-shadow: 0 2px 6px rgba(30,35,31,.06), 0 18px 34px rgba(30,35,31,.11);
  }
}
.thumb:focus-visible{ outline: 2.5px solid var(--ink); outline-offset: 3px; }
/* 卡片是竖长的，里面的图区就让它撑满剩余高度 */
.thumb .shot{ flex: 1; aspect-ratio: auto; }

/* 手机：卡片窄一点，一屏露出两张多，滚动感更明显 */
@media (max-width: 640px){
  .thumb{ width: 232px; margin-right: 16px; border-radius: 18px; }
  /* 手机上一屏才三百多像素宽，72px 的羽化会吃掉太多，收一半 */
  .peek__rail{
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 36px, #000 calc(100% - 36px), transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 36px, #000 calc(100% - 36px), transparent 100%);
  }
}
.thumb__body{ padding: 12px 14px 14px; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.thumb__name{ font-weight: 700; }
.thumb__id{ font-family: var(--mono); font-size: 12.5px; color: var(--ink-45); }

/* --------------------------------------------------------------- 照片位 / 层纹占位 */
/* 占位图用 CSS 画的 FDM 层纹。data.js 里填 photo 字段后自动换成真实照片。 */
.shot{ aspect-ratio: 4 / 3; background: var(--shell-2); position: relative; }
/* aspect-ratio 兜底：老 webview 用 padding-top 撑出 4:3 */
@supports not (aspect-ratio: 4 / 3){
  .shot{ height: 0; padding-top: 75%; }
  .shot img, .shot .shot__ph{ position: absolute; inset: 0; }
}
.shot img{ width: 100%; height: 100%; object-fit: cover; }
.shot__ph{
  width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; text-align: center;
  background: repeating-linear-gradient(180deg, #F6F6F3 0 5px, #E9EAE5 5px 7px);
  color: var(--ink-45); font-size: 12.5px;
}
.shot__ph b{ color: var(--ink-70); font-size: 13.5px; font-weight: 600; }

/* --------------------------------------------------------------- 通用区块 */
.section{ padding: 40px 0; }
.section--tight{ padding: 28px 0; }
.section h2{ font-size: clamp(21px, 5vw, 26px); margin: 0 0 8px; letter-spacing: -.01em; }
.section__sub{ color: var(--ink-70); margin: 0 0 22px; font-size: 15px; max-width: 40em; }

.panel{
  background: var(--shell); border: 1px solid var(--line);
  border-radius: var(--r); padding: 20px;
}

/* --------------------------------------------------------------- 评级规则 */
.rules{ display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.rule{ display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: baseline; }
.rule__count{
  font-family: var(--mono); font-size: 15px; font-weight: 700;
  padding: 2px 9px; border-radius: 6px; white-space: nowrap;
}
.rule--ok .rule__count{ background: var(--ok-bg); color: var(--ok); }
.rule--luck .rule__count{ background: var(--luck-bg); color: var(--luck); }
.rule--black .rule__count{ background: var(--black-bg); color: var(--black); }
.rule--note .rule__count{ background: var(--shell-2); color: var(--ink-70); }
.rule p{ margin: 0; font-size: 15px; }

/* --------------------------------------------------------------- 筛选 */
.tabs{
  display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px;
  margin-bottom: 22px; -webkit-overflow-scrolling: touch;
}
/* 筛选条现在紧跟榜单标题下的「累计实测」小字（原来它自己是一个区块的开头，
   区块本身带了上间距）。补一点距离，别和小字贴死。 */
#board .tabs{ margin-top: 18px; }
.tab{
  flex: none; cursor: pointer; font: inherit; font-size: 14.5px;
  padding: 8px 15px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--shell); color: var(--ink-70);
}
.tab b{ font-family: var(--mono); font-weight: 600; margin-left: 5px; color: var(--ink-45); }
.tab[aria-pressed="true"]{ background: var(--ink); border-color: var(--ink); color: var(--shell); }
.tab[aria-pressed="true"] b{ color: rgba(251,251,249,.65); }

/* --------------------------------------------------------------- 时长对比图 */
.chart{ display: grid; gap: 14px; }
.chart__row{ display: grid; gap: 6px; }
.chart__top{ display: flex; justify-content: space-between; align-items: baseline; gap: 10px; font-size: 14px; }
.chart__time{ font-family: var(--mono); font-size: 13px; color: var(--ink-70); }
.chart__track{ height: 10px; background: var(--shell-2); border-radius: 999px; overflow: hidden; }
.chart__bar{ height: 100%; border-radius: 999px; }
.chart__bar--ok{ background: var(--ok); }
.chart__bar--luck{ background: var(--luck); }
.chart__bar--black{ background: var(--black); }
.chart__foot{ margin: 16px 0 0; font-size: 13px; color: var(--ink-45); }

/* --------------------------------------------------------------- 模型卡 */
.grid{ display: grid; gap: 18px; grid-template-columns: 1fr; }

.card{
  background: var(--shell); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden;
  display: flex; flex-direction: column;
  scroll-margin-top: 80px;
}
.card:target{ border-color: var(--ink); box-shadow: 0 0 0 3px rgba(30,35,31,.12); }
.card--black{ background: var(--shell-2); }

.card__shot{ position: relative; }
.card__id{
  position: absolute; left: 10px; top: 10px;
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  background: rgba(30,35,31,.86); color: var(--shell);
  padding: 3px 8px; border-radius: 6px;
}
.card__body{ padding: 16px; display: flex; flex-direction: column; gap: 14px; flex: 1; }

.card__head{ display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.card__name{ margin: 0; font-size: 20px; letter-spacing: -.01em; }
.card__origin{ font-size: 13px; color: var(--ink-45); margin-top: 2px; }

.badge{
  flex: none; font-size: 13px; font-weight: 600;
  padding: 4px 10px; border-radius: 7px; white-space: nowrap;
}
.badge--ok{ background: var(--ok-bg); color: var(--ok); }
.badge--luck{ background: var(--luck-bg); color: var(--luck); }
.badge--black{ background: var(--black-bg); color: var(--black); }

/* 两次实测：两个方块，成=实心，败=打叉。成功率的图形化表达。 */
.runs{ display: flex; align-items: center; gap: 9px; }
.runs__label{ font-size: 13.5px; color: var(--ink-70); }
.runs__box{
  width: 26px; height: 26px; border-radius: 7px;
  border: 1.5px solid var(--line); background: var(--shell-2);
  display: grid; place-items: center;
  font-size: 14px; font-weight: 700; color: var(--ink-45);
}
.runs__box--pass{ background: var(--ok); border-color: var(--ok); color: #fff; }
.runs__box--fail{ background: var(--black-bg); border-color: var(--black); color: var(--black); }
.runs__score{ font-family: var(--mono); font-size: 14px; color: var(--ink-70); margin-left: 2px; }

.specs{ margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: 14.5px; }
.specs dt{ color: var(--ink-45); }
.specs dd{ margin: 0; }

.flag{
  border-left: 3px solid var(--line); padding: 2px 0 2px 12px;
  font-size: 14.5px;
}
.flag--bad{ border-left-color: var(--black); }
.flag__label{ display: block; font-size: 12.5px; color: var(--ink-45); margin-bottom: 1px; }

.memo{
  background: var(--shell-2); border-radius: 10px; padding: 12px 14px;
  font-size: 14.5px; line-height: 1.7;
}
.memo__label{ display: block; font-size: 12.5px; color: var(--ink-45); margin-bottom: 3px; }

.card__foot{ margin-top: auto; padding-top: 2px; }
.sold-out{
  text-align: center; font-size: 14.5px; color: var(--black);
  background: var(--black-bg); border-radius: 10px; padding: 12px;
}

/* --------------------------------------------------------------- 弹窗 */
.modal[hidden]{ display: none; }
.modal{
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: flex-end; justify-content: center;
  background: rgba(30,35,31,.42);
  padding: 0;
}
.modal__box{
  background: var(--bed); width: 100%; max-width: 520px;
  max-height: 92vh; overflow-y: auto;
  border-radius: 18px 18px 0 0;
  border: 1px solid var(--line);
  animation: rise .22s ease-out;
}
@keyframes rise{ from{ transform: translateY(18px); opacity: .6; } to{ transform: none; opacity: 1; } }

.modal__head{
  /* z-index：往下滚时选中的档位卡（position: relative）不会盖到吸顶的标题栏上 */
  position: sticky; top: 0; z-index: 2; background: var(--bed);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 18px 12px; border-bottom: 1px solid var(--line);
}
.modal__head h3{ margin: 0; font-size: 17px; }
.modal__head p{ margin: 2px 0 0; font-size: 13px; color: var(--ink-45); font-family: var(--mono); }
.modal__close{
  border: 1px solid var(--line); background: var(--shell); color: var(--ink);
  width: 34px; height: 34px; border-radius: 9px; font-size: 17px; cursor: pointer; flex: none;
}
.modal__body{ padding: 18px; display: grid; gap: 18px; }

/* 打印信息弹窗：沿用下单弹窗的壳。左边一张实拍图，右边参数挨着图排。 */
.modal--spec .modal__box{ max-width: 640px; }
.spec-panel{ display: grid; grid-template-columns: 208px 1fr; gap: 20px; align-items: start; }
.spec-shot{
  border: 1px solid var(--line); border-radius: 14px; overflow: hidden;
  background: var(--shell-2);
}
.spec-shot .shot{ aspect-ratio: 4 / 5; }
.spec-info{ display: grid; gap: 14px; min-width: 0; }
.spec-lead{ display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.spec-lead .hint{ margin: 0; }
/* 窄屏（手机）图和信息上下排，图不占满整宽 */
@media (max-width: 560px){
  .spec-panel{ grid-template-columns: 1fr; }
  .spec-shot{ max-width: 200px; }
}

.field > span{ display: block; font-size: 14px; margin-bottom: 7px; font-weight: 600; }
.field input, .field textarea{
  width: 100%; font: inherit; font-size: 16px;
  padding: 12px 13px; border-radius: 10px;
  border: 1.5px solid var(--line); background: var(--shell); color: var(--ink);
}
.field input:focus, .field textarea:focus{ border-color: var(--ink); outline: none; }
.field textarea{ resize: vertical; min-height: 76px; }
.hint{ font-size: 13px; color: var(--ink-45); margin: 7px 0 0; }
.error{ font-size: 13.5px; color: var(--black); margin: 7px 0 0; }
.error[hidden]{ display: none; }
.field--bad input{ border-color: var(--black); }

/* 档位选择 */
.tiers{ display: grid; gap: 10px; }
.tier{ display: block; cursor: pointer; position: relative; }
/* 隐藏的选项框只是状态容器，给它 1px 的盒子：
   否则会继承 .field input 的 width:100%，在手机上撑出 5px 横向滚动 */
.tier input{ position: absolute; opacity: 0; pointer-events: none; width: 1px; height: 1px; margin: 0; padding: 0; border: 0; }
.tier__box{
  border: 1.5px solid var(--line); background: var(--shell);
  border-radius: 12px; padding: 13px 15px;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
}
.tier input:checked + .tier__box{ border-color: var(--ink); background: #fff; }
.tier input:focus-visible + .tier__box{ outline: 2.5px solid var(--ink); outline-offset: 2px; }
.tier__name{ font-weight: 700; }
.tier__desc{ font-size: 13.5px; color: var(--ink-70); margin-top: 2px; }
.tier__price{ font-family: var(--mono); font-weight: 700; white-space: nowrap; }

/* 订单号结果 */
.order__code{
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--shell); border: 1.5px dashed var(--ink); border-radius: 12px;
  padding: 14px 16px; margin-bottom: 16px;
}
.order__code b{ font-family: var(--mono); font-size: 21px; letter-spacing: .04em; }
.steps-pay{ margin: 0 0 4px; padding-left: 1.25em; font-size: 14.5px; }
.steps-pay li{ margin-bottom: 7px; }
.wechat{ font-family: var(--mono); font-weight: 700; background: var(--shell-2); padding: 1px 6px; border-radius: 5px; }

/* --------------------------------------------------------------- 投稿页 */
.flow{ display: grid; gap: 12px; counter-reset: step; list-style: none; margin: 0; padding: 0; }
.flow li{
  background: var(--shell); border: 1px solid var(--line); border-radius: 12px;
  padding: 14px 16px 14px 54px; position: relative;
}
.flow li::before{
  counter-increment: step; content: counter(step);
  position: absolute; left: 16px; top: 14px;
  width: 26px; height: 26px; border-radius: 8px;
  background: var(--ink); color: var(--shell);
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 13px; font-weight: 700;
}
.flow b{ display: block; }
.flow span{ font-size: 14px; color: var(--ink-70); }

.readme{ display: grid; gap: 14px; margin: 0; }
.readme > div{ border-top: 1px solid var(--line); padding-top: 14px; }
.readme > div:first-child{ border-top: 0; padding-top: 0; }
.readme dt{ font-weight: 700; margin-bottom: 4px; }
.readme dd{ margin: 0; font-size: 14.5px; color: var(--ink-70); }
.licenses{ display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
.licenses span{
  font-size: 13px; background: var(--shell-2); border: 1px solid var(--line);
  padding: 4px 10px; border-radius: 999px; color: var(--ink);
}

.counters{ display: grid; gap: 12px; }
.counter{
  background: var(--shell); border: 1px solid var(--line); border-radius: 12px;
  padding: 16px 18px; display: flex; align-items: center; gap: 16px;
}
.counter__num{ font-size: 40px; font-weight: 800; line-height: 1; letter-spacing: -.03em; flex: none; }
.counter__txt b{ display: block; font-size: 15px; }
.counter__txt span{ font-size: 13.5px; color: var(--ink-70); }

.redline{ background: var(--black-bg); border: 1px solid rgba(156,58,45,.3); }
.redline h2{ color: var(--black); }
.redline p{ font-size: 14.5px; margin: 0 0 10px; }
.redline p:last-child{ margin-bottom: 0; }

/* Tally 表单占位 */
.formbox{ min-height: 460px; border-radius: var(--r); overflow: hidden; border: 1px solid var(--line); background: var(--shell); }
.formbox iframe{ width: 100%; min-height: 460px; border: 0; display: block; }
.subform{ display: grid; gap: 18px; }
.loading{
  min-height: 460px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 16px; color: var(--ink-45); font-size: 14px;
}
/* 加载动画 = 喷头逐层堆积，和 3D 打印同一个动作 */
.loading__stack{ display: flex; flex-direction: column-reverse; gap: 3px; }
.loading__stack i{
  display: block; width: 46px; height: 5px; border-radius: 2px; background: var(--line);
  animation: layer 1.5s ease-in-out infinite;
}
.loading__stack i:nth-child(2){ animation-delay: .18s; }
.loading__stack i:nth-child(3){ animation-delay: .36s; }
.loading__stack i:nth-child(4){ animation-delay: .54s; }
.loading__stack i:nth-child(5){ animation-delay: .72s; }
@keyframes layer{ 0%,100%{ background: var(--line); } 45%{ background: var(--ink); } }

.legal{ font-size: 14px; color: var(--ink-70); }
.legal p{ margin: 0 0 10px; }
.legal p:last-child{ margin-bottom: 0; }

/* --------------------------------------------------------------- 预览横幅
   站长开了「预览普通用户视角」时常驻在顶部，点一下就退出。
   放在 styles.css 而不是 pages.css：首页也要显示它，而首页不加载 pages.css。 */
.lc-preview{
  position: fixed; left: 50%; top: 68px; transform: translateX(-50%);
  z-index: 260;
  display: flex; align-items: center; gap: 12px;
  max-width: min(640px, calc(100vw - 32px));
  padding: 9px 14px; border-radius: 999px;
  font-size: 13.5px; line-height: 1.4;
  color: var(--shell); background: rgba(30,35,31,.92);
  box-shadow: 0 10px 30px rgba(30,35,31,.22);
}
.lc-preview b{ color: #fff; }
.lc-preview button{
  flex: none; font: inherit; font-size: 12.5px;
  padding: 5px 12px; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(251,251,249,.45);
  background: transparent; color: var(--shell);
}
@media (hover: hover){ .lc-preview button:hover{ background: rgba(251,251,249,.16); } }

/* --------------------------------------------------------------- 页脚 */
.foot{
  border-top: 1px solid var(--line); margin-top: 24px;
  padding: 28px 0 40px; font-size: 14px; color: var(--ink-70);
}
.foot__links{ display: flex; gap: 16px; margin-bottom: 12px; }
.foot__links a{ color: var(--ink); }

/* --------------------------------------------------------------- 响应式 */
@media (min-width: 700px){
  .peek__grid{ grid-template-columns: repeat(3, 1fr); }
  .modal{ align-items: center; padding: 24px; }
  .modal__box{ border-radius: 18px; }
  .counters{ grid-template-columns: 1fr 1fr; }
  .flow{ grid-template-columns: 1fr 1fr; }
}

@media (min-width: 1000px){
  .grid{ grid-template-columns: repeat(3, 1fr); }
}

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  *, *::before, *::after{ animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  /* 跑马灯必须停在「原位置」：上面那条全局规则会把动画压缩成瞬时播一次，
     轨道就停在 -50% 那一份复制卡上 —— 那是 aria-hidden、Tab 不到的，
     键盘用户会一个卡片都点不到。所以这里显式把动画整个关掉。 */
  .peek__track{ animation: none; }
  .thumb:hover{ transform: none; }
}

/* hidden 属性优先：任何带 hidden 的元素一律不显示 */
[hidden]{ display: none !important; }

/* 选中标记：单选圆点 / 勾选对勾。只用墨色，不引入新颜色 */
.tier__box::before{
  content: "";
  flex: none;
  width: 20px; height: 20px;
  margin-top: 2px;
  border: 1.5px solid var(--line);
  background: var(--shell);
}
.tier input[type="radio"] + .tier__box::before{ border-radius: 50%; }
.tier input[type="checkbox"] + .tier__box::before{ border-radius: 6px; }

.tier input:checked + .tier__box::before{
  border-color: var(--ink);
  background: var(--ink);
  box-shadow: inset 0 0 0 4px var(--shell);
}
.tier input[type="checkbox"]:checked + .tier__box::before{
  box-shadow: none;
  background: var(--ink) no-repeat center / 12px 12px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5' fill='none' stroke='%23FBFBF9' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* 用户服务协议：投稿区勾选框里的链接 + 弹窗正文 */
.terms-link{ color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
/* 注册时是从登录卡（z-index 100）里点开的，协议得盖在登录卡上面 */
.modal--terms{ z-index: 130; }
.modal--terms .modal__box{ max-width: 680px; }
.terms{ font-size: 14.5px; line-height: 1.8; color: var(--ink-70); }
.terms p{ margin: 0 0 10px; }
.terms p:first-child{ font-size: 13px; color: var(--ink-45); }
.terms b{ color: var(--ink); font-weight: 700; }
.terms h4{ margin: 20px 0 8px; font-size: 15.5px; color: var(--ink); }
.terms ul{ margin: 0 0 10px; padding-left: 1.3em; }
.terms li{ margin-bottom: 6px; }
.terms li::marker{ color: var(--ink-45); }

/* 微信二维码展示 */
.qr{ display: block; width: 180px; margin: 10px auto 0; border-radius: 12px; border: 1.5px solid var(--line); }
.qr-cap{ text-align: center; }

/* --------------------------------------------------------------- 首屏响应式 */
/* 首屏是满屏视频 + 左侧内容块，窄屏沿用同一套（视频照样铺满 100svh、文字照样反白），
   所以这里不需要任何覆盖规则。窄屏唯一的变化来自 .hero__stage 的 100svh：
   地址栏收起时高度跟着变，不会出现"视频比屏幕矮一截"。 */

/* --------------------------------------------------------------- 单页版 */
/* 首页 / 实测榜 / 投稿 三块之间的接缝：一条细线，代替原先的换页动作 */
.seam{
  height: 1px; background: var(--line);
  max-width: var(--maxw); margin: 0 auto;
}

/* --------------------------------------------------------------- 出现动画 */
/* 全局入场效果，配方照抄 deepseek.com：
   initial{opacity:0, y:40} → whileInView{opacity:1, y:0}，
   duration .6s，ease cubic-bezier(.44,0,.56,1)，viewport once（只播一次、不反向）。
   初始隐藏态由脚本自己挂 .is-reveal —— 没有 JS 或老内核时页面照常全部可见，不会白屏。 */

/* 1) 初始隐藏态：故意不带过渡。挂上时是"直接隐藏"，
      不会从可见状态倒着淡出（那是刷新时一闪的元凶）。 */
.is-reveal{ opacity: 0; transform: translateY(40px); }

/* 2) 隐藏态真正画出一帧之后，脚本才挂 .is-armed 打开过渡。
      顺序很关键：过渡必须在"隐藏态已绘制"之后才存在，动画才看得见。 */
.is-reveal.is-armed{
  transition: opacity .6s cubic-bezier(.44,0,.56,1),
              transform .6s cubic-bezier(.44,0,.56,1);
}

/* 3) 进入视口 → 淡入归位 */
.is-reveal.is-in{ opacity: 1; transform: translateY(0); }

/* 4) 锚点跳转时用：先瞬间就位再滚，避免"边滚边往上飘 40px"导致落点偏移。
      必须排在 .is-armed 之后，同权重时后者生效。 */
.is-reveal.is-instant{ transition: none; }

/* 系统开了"减弱动态效果"就不动：直接显示 */
@media (prefers-reduced-motion: reduce){
  .is-reveal{ opacity: 1; transform: none; transition: none; }
}

/* --------------------------------------------------------------- 颗粒质感 */
/* 全站叠一层极淡的胶片颗粒。噪点用 SVG feTurbulence 现场生成（data-URI），零请求。
   只用 multiply 压暗、不引入新颜色，所以「墨 + 台面灰 + 判定色」的骨架不受影响。
   强度集中在 --grain 一个变量里（见 :root）。
   动效走 transform（合成层），不触发重排重绘；6 步跳变看起来就是胶片在走。 */
.grain{
  position:fixed; inset:-60%;              /* 比视口大一圈，位移时四边不会露出来 */
  z-index:999; pointer-events:none;        /* 只做视觉层，绝不拦点击 */
  mix-blend-mode:multiply;
  opacity:var(--grain);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.62'/%3E%3C/svg%3E");
  background-size:180px 180px;
  animation:grainShift .9s steps(6) infinite;
  will-change:transform;
}
@keyframes grainShift{
  0%  { transform:translate3d(0, 0, 0); }
  16% { transform:translate3d(-3%, -2%, 0); }
  33% { transform:translate3d(2%, -3%, 0); }
  50% { transform:translate3d(-2%, 3%, 0); }
  66% { transform:translate3d(3%, 1%, 0); }
  83% { transform:translate3d(-1%, -3%, 0); }
  100%{ transform:translate3d(0, 0, 0); }
}

/* 系统开了「减弱动态效果」：留下质感，但颗粒不晃 */
@media (prefers-reduced-motion: reduce){
  .grain{ animation:none; }
}

/* 手机屏幕小、像素密，同样的强度看起来更明显，压一档免得显脏 */
@media (max-width: 699px){
  :root{ --grain: .2; }
}

/* ==========================================================================
   手机 / 平板适配
   ⚠️ 这一段的规则全部包在「窄屏」或「触屏」媒体查询里，电脑端（≥1000px、有鼠标）
      一条都不命中 —— 改电脑端样式请改上面的默认值，别动这里。
   断点：999.98px 以下 = 平板和手机（含横屏手机）；640px 以下 = 竖屏手机。
   ========================================================================== */

/* 顶栏的菜单按钮：只有窄屏才露出来（按钮由 app.js 插进来，没 JS 时链接照常显示） */
.nav__toggle{ display: none; }

@media (max-width: 999.98px){
  /* 统一的左右留白。iPhone 横屏有刘海，取刘海和留白里大的那个 */
  :root{ --gutter: clamp(16px, 5vw, 24px); }

  /* .section / .page 的 padding 简写把 .wrap 的左右内边距盖成了 0，
     电脑上有 1120 的居中栏不显，窄屏上文字就直接贴着屏幕边了 */
  .wrap.section,
  .foot .wrap,
  .peek__head{
    padding-left:  max(var(--gutter), env(safe-area-inset-left, 0px));
    padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
  }
  .foot{ padding-bottom: calc(40px + env(safe-area-inset-bottom, 0px)); }

  /* 长串（网盘链接、编号、邮箱）在窄屏上允许断开，不撑出横向滚动 */
  body{ overflow-wrap: break-word; }
  .specs dt{ white-space: nowrap; }
  .specs dd{ min-width: 0; overflow-wrap: anywhere; }

  /* 首屏：从「绝对定位盖在 100svh 上」改成「内容撑高、最少一屏」。
     横屏手机只有三四百像素高，原来的写法文字组会被裁掉一截。
     上边让出顶栏的高度，文字永远不会钻到顶栏底下。 */
  .hero__stage{ height: auto; min-height: 100vh; min-height: 100svh; display: flex; flex-direction: column; }
  .hero__over{
    position: relative; inset: auto; flex: 1 0 auto;
    padding: calc(var(--navh) + 20px) 0 calc(max(48px, 9svh) + env(safe-area-inset-bottom, 0px));
  }
  /* 导语是全角空格隔开的短句：只在空格处换行，不把「实测完 / 再告诉你」劈开 */
  .hero__lead{ word-break: keep-all; }

  /* 筛选条是横向滑的：让它滑到屏幕边，最后一个不在留白处被切一刀 */
  .tabs{
    margin-left: calc(var(--gutter) * -1); margin-right: calc(var(--gutter) * -1);
    padding-left: var(--gutter); padding-right: var(--gutter);
  }

  /* 平板竖屏实测榜一行两张，比一张铺满 700px 宽好扫 */
  .grid{ grid-template-columns: repeat(2, 1fr); }

  /* 弹窗/登录卡开着时，背景页不跟着手指滚（iOS 只锁 body 不够） */
  html:has(.modal:not([hidden])),
  html:has(.lc-veil.is-on){ overflow: hidden; }
  .modal{ overscroll-behavior: contain; }
  .modal__box{ overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }

}

/* 竖屏：横向视频被 cover 裁成窄长条，默认居中会把右边坐着的人整个裁掉。
   往右挪到 78%，人物整段循环都在画面里。 */
@media (max-width: 999.98px) and (orientation: portrait){
  .hero__media{ object-position: 78% 50%; }
}

@media (max-width: 699.98px){
  .grid{ grid-template-columns: 1fr; }

  /* 弹窗在手机上是底部抽屉：高度按「弹窗层」算而不是 vh ——
     iOS 的 vh 含地址栏，抽屉顶上的关闭按钮会被顶出屏幕 */
  .modal__box{
    max-height: calc(100% - 12px - env(safe-area-inset-top, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .modal__head{ padding: 12px 14px 12px 18px; }
  .modal__close{ width: 44px; height: 44px; border-radius: 12px; font-size: 18px; }
  .modal{ touch-action: none; }          /* 点在暗处拖不动背景页 */
  .modal__box{ touch-action: pan-y; }
  /* 下单弹窗内容比抽屉高：「生成订单号」吸在抽屉底部，
     软键盘弹出时抽屉跟着可视区域缩（见 index.html 的 visualViewport 脚本），按钮始终够得着 */
  #makeOrder{
    position: sticky; bottom: 12px; z-index: 1;
    box-shadow: 0 0 0 12px var(--bed), 0 -12px 10px var(--bed);
  }
  .spec-shot{ max-width: 168px; }
}

@media (max-width: 640px){
  /* ---- 顶栏：链接收进菜单 ---- */
  .nav__in{
    position: relative;
    padding: 6px max(var(--gutter), env(safe-area-inset-right, 0px)) 6px max(var(--gutter), env(safe-area-inset-left, 0px));
  }
  .nav--menu .nav__toggle{
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin-right: -10px; padding: 0;
    border: 0; border-radius: 12px; background: transparent; cursor: pointer;
    color: #fff; -webkit-tap-highlight-color: transparent;
  }
  .nav--solid .nav__toggle,
  .nav--open .nav__toggle{ color: var(--ink); }
  /* 三条线 = 品牌标记同款「层纹」；展开时中间那条收掉、上下两条转成 × */
  .nav__toggle span,
  .nav__toggle span::before,
  .nav__toggle span::after{
    display: block; width: 20px; height: 2px; border-radius: 2px;
    background: currentColor; transition: transform .22s ease, opacity .22s ease;
  }
  .nav__toggle span{ position: relative; }
  .nav__toggle span::before,
  .nav__toggle span::after{ content: ""; position: absolute; left: 0; }
  .nav__toggle span::before{ top: -6px; }
  .nav__toggle span::after{ top: 6px; }
  .nav--open .nav__toggle span{ background: transparent; }
  .nav--open .nav__toggle span::before{ transform: translateY(6px) rotate(45deg); background: var(--ink); }
  .nav--open .nav__toggle span::after{ transform: translateY(-6px) rotate(-45deg); background: var(--ink); }

  /* 菜单打开时顶栏切到实底，和下面的面板连成一整块 */
  .nav.nav--open{ background: rgba(239,240,236,.98); border-bottom-color: var(--line); }
  .nav--open .brand{ color: var(--ink); }
  .nav--open .brand__mark{
    border-color: var(--ink);
    background: repeating-linear-gradient(180deg, var(--shell) 0 3px, #CFD2CA 3px 4px);
  }

  .nav--menu .nav__links{
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; gap: 0;
    padding: 4px max(var(--gutter), env(safe-area-inset-right, 0px)) 12px max(var(--gutter), env(safe-area-inset-left, 0px));
    max-height: calc(100svh - var(--navh)); overflow-y: auto; overscroll-behavior: contain;
    background: rgba(239,240,236,.98);
    border-bottom: 1px solid var(--line);
    /* 面板下方整屏压暗；clip-path 只放出下半截阴影，别把顶栏也压暗 */
    box-shadow: 0 0 0 100vh rgba(30,35,31,.28);
    clip-path: inset(0 0 -100vh 0);
    visibility: hidden; opacity: 0; transform: translateY(-6px);
    transition: opacity .2s ease, transform .2s ease, visibility 0s linear .2s;
  }
  .nav--open .nav__links{
    visibility: visible; opacity: 1; transform: none;
    transition: opacity .2s ease, transform .2s ease;
  }
  .nav.nav--menu .nav__links a{
    display: flex; align-items: center; min-height: 50px; padding: 0 2px;
    font-size: 16px; color: var(--ink-70);
    border-bottom: 1px solid var(--line);
    -webkit-tap-highlight-color: transparent;
  }
  .nav.nav--menu .nav__links a:last-child{ border-bottom: 0; }
  .nav.nav--menu .nav__links a[aria-current]{ color: var(--ink); border-bottom-color: var(--line); }
  .nav.nav--menu .nav__links a[aria-current]::after{
    content: ""; width: 6px; height: 6px; margin-left: 10px; border-radius: 50%; background: var(--ink);
  }

  /* ---- 首屏：间距和行高收紧，标题按 320–430 宽自适应 ---- */
  :root{
    --hero-gap-kicker: 18px;
    --hero-gap-h1:     16px;
    --hero-gap-lead:   28px;
    --hero-gap-btns:   24px;
    --hero-lh-lead:    1.8;
  }
  .hero__over > .wrap{
    padding-left:  max(var(--gutter), env(safe-area-inset-left, 0px));
    padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
  }
  .hero h1{ font-size: clamp(28px, 8.8vw, 38px); }
  .hero__lead{ font-size: 15px; }
  .hero__btns .btn{ min-width: 124px; }
  /* 文字铺满整宽了，左浓右淡的那层压暗管不到右半边：换成整体均匀一些的压暗 */
  .hero__scrim{
    background:
      linear-gradient(180deg, rgba(10,14,12,.6) 0%, rgba(10,14,12,.36) 34%, rgba(10,14,12,.5) 100%),
      linear-gradient(90deg, rgba(10,14,12,.3) 0%, rgba(10,14,12,.14) 100%);
  }

  /* ---- 触屏点击目标不小于 44px ---- */
  .tab{ min-height: 44px; }
  .peek__head{ flex-wrap: wrap; row-gap: 4px; }
  .peek__head a{ display: inline-flex; align-items: center; min-height: 44px; margin: -12px 0; }
  .foot__links a{ display: inline-flex; align-items: center; min-height: 44px; }
  .foot__links{ margin-bottom: 4px; }
  .order__code b{ font-size: 19px; }
}

/* 横屏手机：只有三四百像素高，首屏文字组整体收一档 */
@media (max-width: 999.98px) and (max-height: 500px){
  :root{
    --hero-gap-kicker: 14px;
    --hero-gap-h1:     12px;
    --hero-gap-lead:   20px;
    --hero-gap-btns:   8px;
    --hero-lh-lead:    1.7;
  }
  .hero h1{ font-size: clamp(26px, 7.5vh, 34px); }
}

/* 触屏：按下有反馈；卡片带交给手指（纵向滑动仍交给页面滚动） */
@media (hover: none){
  .btn:active{ opacity: .86; }
  .thumb{ -webkit-tap-highlight-color: transparent; }
  .thumb:active{ transform: scale(.98); }
}
/* 手机：颗粒照样有，但不再每秒抖 6 次 —— 那是一整屏的混合图层一直在重画，低端机费电、发卡 */
@media (max-width: 999.98px) and (pointer: coarse){
  .grain{ animation: none; will-change: auto; }
}
@media (pointer: coarse){
  .peek__rail{ touch-action: pan-y; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
}
