/* 生成页面共用的排版脚手架 —— 与组件一样，只允许用 token。
   这是「页面层」，只做容器/网格/间距；不定义任何新的设计值。 */

body {
  /* ★ 一屏固定 812（用户明确要求）。
     视口不够高时**页面本身**可滚（而不是把壳压矮）——
     壳是设计稿 1:1 的产物，压矮会破坏几何。
     壳内的 .mzh-home__scroll 仍只负责内容滚动，两者互不干扰：
     页面滚 = 整体上下移（视口不够时用），壳内滚 = 看 1050 高的内容。 */
  padding: 0 var(--spacing-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--layout-viewport-height);
}

/* ★ 全局 button 重置 —— 缺了会静默出 `2px outset rgb(0,0,0)` 黑边。
   <button> 的 UA 默认样式带 border + background + font，且 **border 参与盒模型**
   （border-box 之外），会把设计稿的 102×110 撑成 106×114。
   「我的」页三个权益卡就中过这个招（肉眼可见的粗黑框 + 渐变底被挤没）。 */
button {
  border: 0;
  padding: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

/* 手机框：宽度取自 token 的页面基准宽。

   ⚠️ 描边用 box-shadow 而不是 border：border 会占掉左右各 1px，
   内容区就变成 373 而不是 375，所有按 375 推导的尺寸（166 卡宽、196 banner…）
   会集体差 1px。用 box-shadow 画外圈，内容区严格 375。

   圆角 + overflow:hidden 是**原型外壳**：让页面像嵌在手机圆角屏幕里。
   真机上页面是全屏的、圆角由设备提供，所以这属"演示用"，不影响任何设计值
   （不会改变元素的量测位置，只裁四个角）。 */
.mzh-phone {
  width: var(--layout-page-width);
  margin: 0 auto;
  background: var(--color-bg-page);
  border-radius: var(--layout-screen-radius);
  overflow: hidden;
  box-shadow: 0 0 0 var(--border-width-default) var(--color-border-light);
  display: flex;
  flex-direction: column;
  /* 悬浮键以本容器为定位参照 */
  position: relative;
}

.mzh-phone__body {
  padding: 0 var(--spacing-md);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
}

/* 区块内的纵向节奏 */
.mzh-phone__stack {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
}

/* ─────────── 首页（设计稿 1887:1170）的纵向节奏 ───────────
   全部由设计稿绝对坐标推导，改 token 即改版式。 */
.mzh-home__media-row {
  display: flex;
  align-items: flex-start;
  gap: var(--home-layout-media-gap);
  padding: 0 var(--home-layout-content-padding-x);
  margin-top: var(--home-layout-gap-master-to-media);
}

.mzh-home__section {
  display: flex;
  flex-direction: column;
  gap: var(--home-layout-card-gap);
  padding: 0 var(--home-layout-content-padding-x);
  margin-top: var(--home-layout-gap-media-to-cases);
}

/* 案例 2 列网格：卡宽取设计稿显式值 166（列间距 11 → 166×2+11=343）；
   行间距仍取设计稿的 12（设计稿 list 高 420 = 204+12+204）。 */
.mzh-home__grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--home-layout-grid-gap);
  row-gap: var(--home-layout-card-gap);
  width: 100%;
}

/* ─────────── 首页（设计稿 1887:1170，内容 1050 > 一屏 812）───────────
   用户要求：内容可滚动，底部标签栏固定不随滚动。

   实现：
   · 手机壳固定一屏高（--layout-viewport-height），overflow:hidden 不让内容外溢
   · 壳内多一个 .mzh-home__scroll 滚动容器，包住导航以下的所有内容
   · TabBar 区 position:absolute 钉在壳底
   · 滚动容器底部留出与 TabBar 等高的内边距，最后一条内容不会被盖住
   ⚠️ 不能用 position:fixed —— 那是相对**视口**，在多页并排预览时会跑到别的位置。 */
.mzh-phone--home {
  height: var(--layout-viewport-height);
  overflow: hidden;
  padding-bottom: 0;
}

.mzh-home__scroll {
  position: relative;
  flex: 1;
  min-height: 0;                 /* flex 子项默认 min-height:auto，不加则不滚动 */
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  /* 底部留白 = TabBar 区高度，让最后一条内容能滚到可见 */
  padding-bottom: var(--home-tabbar-reserved);
  scrollbar-width: none;          /* 隐藏滚动条，原型不需要 */
}

.mzh-home__scroll::-webkit-scrollbar {
  display: none;
}

/* TabBar 钉在壳底 */
.mzh-phone--home .mzh-home__tabbar-area {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  margin-top: 0;
  z-index: var(--home-tabbar-z);
  flex: none;
}

/* ★ 导航在滚动容器**内**（用户要求随内容一起滚走）。
   它不需要 z-index —— 主功能白卡的负 margin 上提能正常压住它的渐变，
   因为两者同属一个层叠上下文，不会被 overflow 裁掉。
   ⚠️ 但必须给 align-self:stretch —— 放进 flex 容器后导航变成 flex item，
   宽度会按内容塌成 0（实测 w=0 h=0，整页错位 -189）。 */
.mzh-phone--home .mzh-nav {
  position: relative;
  z-index: auto;
  align-self: stretch;
  flex: none;
}

/* TabBar 区 = 标签栏 + 下方 iOS Home Indicator 区。
   ⚠️ 设计稿实测：标签栏下方 1028..1050 是**白色**（不是页面灰），
   而标签栏自己的上圆角缺口处露出的是**页面灰** ——
   所以白底只能加在标签栏之后的那一段，不能给整个容器铺白。 */
.mzh-home__tabbar-area {
  margin-top: var(--home-layout-gap-cases-to-tabbar);
  display: flex;
  flex-direction: column;
}

.mzh-home__home-indicator {
  height: var(--layout-home-indicator);
  background: var(--color-bg-primary);
}

/* 产品教程页的安全区是 34（首页设计稿是 22）—— 两页各按自己的设计稿 */
.mzh-home__home-indicator--safe {
  height: var(--layout-safe-area-bottom);
}

/* ─────────── 产品教程页（设计稿 1861:9407）外壳 ───────────
   页面是固定 812 高：内容在内部滚动，TabBar 区固定在底部并压在内容之上
   （设计稿里内容到 794、TabBar 从 720 起，就是这种叠法）。 */
.mzh-phone--tutorial {
  height: var(--tutorial-page-height);
  overflow: clip;
}

.mzh-page-bg {
  --page-bg-image: var(--tutorial-page-bg-image);
  position: absolute;
  inset: 0;
  background-image: var(--page-bg-image);
  background-size: 100% 100%;
  background-repeat: no-repeat;
  z-index: var(--tutorial-page-bg-z, 0);
}

.mzh-tutorial__scroll {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  /* 让页面内的 cqw（大标题的位置/字号）相对本页宽换算，而不是相对浏览器视口 */
  container-type: inline-size;
}

.mzh-tutorial__content {
  display: flex;
  flex-direction: column;
  gap: var(--tutorial-group-gap-y);
  /* 用 margin 而不是 padding：这样内容框本身就是设计稿里的 343 宽框（x=16） */
  margin: calc(var(--tutorial-content-top) - var(--tutorial-banner-h))
          var(--tutorial-content-pad-x) 0;
  /* 必须给出层叠上下文：banner 带 position:relative，按 CSS 绘制顺序
     「定位元素」会盖过「非定位块级元素」，不压住就会让 banner 渐隐区糊在白卡上。
     设计稿里白卡就是压在 banner 上的。 */
  position: relative;
  z-index: var(--tutorial-content-z);
}

.mzh-phone--tutorial .mzh-nav,
.mzh-phone--tutorial .mzh-home__tabbar-area {
  position: absolute;
  left: 0;
  width: 100%;
  z-index: var(--tutorial-overlay-z, 10);
}

.mzh-phone--tutorial .mzh-nav {
  top: 0;
  pointer-events: none;
}

.mzh-phone--tutorial .mzh-home__tabbar-area {
  bottom: 0;
  margin-top: 0;
}

/* 弧形背景面板（旧版 P01 用；新版首页已不再使用，保留以免影响 P01） */
.mzh-phone__panel {
  position: relative;
  --panel-image: none;
  margin-top: calc(var(--banner-panel-raise) * -1);
  background-image:
    var(--panel-image),
    linear-gradient(180deg,
      var(--panel-image-bottom-color) 0,
      var(--color-bg-brand-extend) var(--panel-edge-fade),
      var(--color-bg-brand-extend) 100%);
  background-repeat: no-repeat, no-repeat;
  background-size: 100% auto,
                   100% max(0px, calc(100% - var(--panel-image-height) + var(--panel-fill-overlap)));
  background-position: top left, bottom left;
  border-radius: var(--panel-radius);
  padding: var(--panel-padding-top) var(--panel-padding-x) var(--panel-padding-bottom);
  display: flex;
  flex-direction: column;
  gap: var(--panel-gap);
}

.mzh-phone__panel .mzh-section-header__title {
  color: var(--color-text-inverse);
}

.mzh-phone__grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--spacing-md);
}

/* ─────────── 免费预约页（设计稿 1868:11652）外壳 ───────────
   主视觉是 375×812 的整页背景层 + 压在上面的表单/按钮/规则；
   导航是毛玻璃固定层，TabBar 固定；内容在内部滚动。 */
.mzh-phone--booking {
  height: var(--booking-page-height);
  overflow: clip;
  /* 滚出主视觉后露出渐变末色，不让下面变白 */
  background: var(--color-bg-booking-page);
}

.mzh-booking__scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

.mzh-booking__scroll-inner {
  position: relative;
  /* 按钮在设计稿里位于 y=622：用上内距把流式内容推到那个位置 */
  padding-top: var(--booking-btn-y);
  /* 底部留出 TabBar 高度，保证规则文字能滚出来读完 */
  padding-bottom: var(--tab-bar-area-height);
}

.mzh-booking__cta {
  display: flex;
  margin: 0 var(--booking-btn-x);
  /* banner/主视觉是绝对定位层，静态元素会被它盖住 —— 必须显式抬起来 */
  position: relative;
  z-index: var(--booking-overlay-z);
}

/* 规则块由生成器放在流里，这里补上它与按钮之间的间距 */
.mzh-phone--booking mzh-rules {
  margin-top: var(--booking-rules-gap-y);
  position: relative;
  z-index: var(--booking-overlay-z);
}

.mzh-phone--booking .mzh-nav,
.mzh-phone--booking .mzh-home__tabbar-area {
  position: absolute;
  left: 0;
  width: 100%;
  z-index: var(--booking-overlay-z);
}

.mzh-phone--booking .mzh-nav {
  top: 0;
}

.mzh-phone--booking .mzh-home__tabbar-area {
  bottom: 0;
  margin-top: 0;
}

/* ─────────── 我的页（设计稿 1871:16589）外壳 ─────────── */
.mzh-phone--mine {
  height: var(--mine-page-height);
  overflow: clip;
  background: var(--color-bg-mine-page);
}

.mzh-phone--mine .mzh-member-card,
.mzh-phone--mine .mzh-icon-menu,
.mzh-phone--mine .mzh-nav,
.mzh-phone--mine .mzh-home__tabbar-area {
  z-index: var(--booking-overlay-z);
}

.mzh-phone--mine .mzh-member-mall {
  position: absolute;
  z-index: var(--booking-overlay-z);
}

.mzh-phone--mine .mzh-nav {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  pointer-events: none;
}

.mzh-phone--mine .mzh-home__tabbar-area {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  margin-top: 0;
}

/* 头像与问候 */
.mzh-mine__avatar {
  position: absolute;
  left: var(--mine-avatar-x);
  top: var(--mine-avatar-y);
  width: var(--mine-avatar-size);
  height: var(--mine-avatar-size);
  display: block;
  z-index: var(--booking-overlay-z);
}

.mzh-mine__hello,
.mzh-mine__name {
  position: absolute;
  z-index: var(--booking-overlay-z);
  white-space: nowrap;
}

.mzh-mine__hello {
  left: var(--mine-hello-x);
  top: var(--mine-hello-y);
  font-size: var(--mine-hello-size);
  line-height: var(--mine-hello-size);
  /* 设计稿 1871:16684 是 PingFang SC **Light**（300）。本项目规范只定 400/500/600
     （R15：600 只给 Hero），不为此新增字重档 —— 落到最接近的 400。 */
  font-weight: var(--typography-weight-regular);
  color: var(--color-text-inverse);
}

.mzh-mine__name {
  left: var(--mine-hello-x);
  top: var(--mine-name-y);
  font-size: var(--mine-name-size);
  line-height: var(--typography-headline-line-height);
  font-weight: var(--typography-weight-semibold); /* hero */
  color: var(--color-text-inverse);
}

/* ─────────── 服务案例页（设计稿 1861:9770）外壳 ─────────── */
.mzh-phone--case {
  height: var(--layout-viewport-height);
  /* ★ 壳固定一屏 + 壳内滚动（2026-09-30 用户要求「案例页可以滑动」）：
     第三行卡片 y626..830 超出 812 被裁掉 18px。改成壳内滚动容器。 */
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-bg-page);
}

/* 案例列表的滚动容器：包住导航 + 分类 + 列表 */
.mzh-case-scroll {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.mzh-case-scroll::-webkit-scrollbar {
  display: none;
}

/* ★ 底部留白（TabBar 58 + 系统区 34）。
   ⚠️ 本页所有内容层（bg/caseNav/caseList/nav）全是 position:absolute ——
   它们脱离正常流，容器里没有任何正常流子元素；手册「::after 留白」
   必须出现在内容**下方**才有效，直接 height:92 会贴在顶部 y0、完全无效。
   正确算法：把伪元素高度撑满「内容底 + TabBar 预留」——
   list-y 194 + list-h 636 = 内容底 830（第三行卡超出 812 的部分），
   + 92 预留 = 922 = scrollHeight。
   滚到底时卡6底 830 落在视口 y830−110 = 720 = TabBar 顶，恰好不被遮住。 */
.mzh-case-scroll::after {
  content: "";
  display: block;
  height: calc(var(--case-list-list-y) + var(--case-list-list-h) + var(--case-list-tabbar-reserved));
}

/* ★ 导航保持 absolute —— containing block 变为 .mzh-case-scroll（position:relative），
   仍锚在滚动容器顶部 y0，且 absolute 子级会随内容一起滚走（与首页「导航随内容滚」同模式）。
   状态栏与胶囊是它的绝对定位子级，相对它自己定位，不受影响。
   pointer-events:none —— 导航空白区不吞滚动手势（本页导航无按钮）。 */
.mzh-phone--case .mzh-nav {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  pointer-events: none;
}

.mzh-case__bg {
  position: absolute;
  inset: 0;
  width: var(--case-list-bg-w);
  height: var(--case-list-bg-h);
  display: block;
  z-index: 0;
}

/* ★ 层叠：滚动容器内的定位层（nav / caseNav / caseList）要高于背景图。
   tabbar-area 用壳级更高 z（home-tabbar-z），保证 TabBar 压在内容上。 */
.mzh-phone--case .mzh-case-nav,
.mzh-phone--case .mzh-case-list,
.mzh-phone--case .mzh-nav {
  z-index: var(--booking-overlay-z);
}

.mzh-phone--case .mzh-home__tabbar-area {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  margin-top: 0;
  z-index: var(--home-tabbar-z);
}

/* ─────────── 附近门店页（设计稿 1868:12000）外壳 ─────────── */
.mzh-phone--store {
  height: var(--layout-viewport-height);
  display: block;
  overflow: hidden;
  background: var(--color-bg-page);
}

.mzh-phone--store-detail {
  height: var(--layout-viewport-height);
  overflow: hidden;
  background: var(--color-bg-page);
}

.mzh-phone--messages { height: var(--layout-viewport-height); overflow-y: auto; scrollbar-width: none; }
.mzh-messages__bg { position: absolute; inset: 0; width: var(--layout-page-width); height: var(--layout-viewport-height); pointer-events: none; }
.mzh-messages__list { position: relative; display: flex; flex-direction: column; gap: var(--spacing-md); margin: var(--spacing-md) var(--spacing-lg) 0; padding-bottom: var(--spacing-lg); }

.mzh-store__bg {
  position: absolute;
  inset: 0;
  width: var(--store-bg-w);
  height: var(--store-bg-h);
  display: block;
  z-index: 0;
}

/* 顶部栏：绝对定位贴壳顶；pointer-events:none 不吃滚动手势
   （返回键在组件里自己声明 pointer-events:auto） */
.mzh-phone--store .mzh-nav {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  pointer-events: none;
}

/* 层叠：顶部栏 / 分类行 / 门店列表 都要高于背景图 */
.mzh-phone--store .mzh-nav,
.mzh-phone--store .mzh-case-nav,
.mzh-phone--store .mzh-store-list {
  z-index: var(--store-overlay-z);
}

/* 页面说明过去渲染在这里（.mzh-page-note），按用户要求已删除 ——
   同样的话现在只写在生成 HTML 的注释里，不占页面顶部。 */
.mzh-phone--points { height: var(--layout-viewport-height); overflow-y: auto; scrollbar-width: none; }
.mzh-points__bg { position: absolute; inset: 0; width: var(--layout-page-width); height: var(--layout-viewport-height); }
.mzh-points__summary { position: relative; height: var(--points-page-hero-h); flex: none; color: var(--color-action-on-primary); }
.mzh-points__summary > strong { position: absolute; left: var(--spacing-lg); top: var(--points-page-balance-y); font-size: var(--points-page-balance-size); line-height: var(--points-page-balance-line); font-weight: var(--typography-weight-semibold); /* hero */ }
.mzh-points__summary > span { position: absolute; left: var(--points-page-unit-x); top: var(--points-page-unit-y); font-size: var(--typography-caption-font-size); line-height: var(--typography-caption-line-height); }
.mzh-points__art { position: absolute; left: var(--points-page-art-x); top: var(--points-page-art-y); width: var(--points-page-art-crop); height: var(--points-page-art-crop); overflow: hidden; }
.mzh-points__art mzh-image { position: absolute; left: var(--points-page-art-offset); top: var(--points-page-art-offset); width: var(--points-page-art-size); height: var(--points-page-art-size); box-shadow: var(--points-page-art-shadow); }
.mzh-points__panel { position: relative; flex: none; min-height: var(--points-page-panel-h); background: var(--color-bg-primary); border-radius: var(--radius-3xl) var(--radius-3xl) 0 0; padding: var(--spacing-2xl) var(--spacing-lg); }
.mzh-points__list { display: flex; flex-direction: column; gap: var(--spacing-md); }


.mzh-points__art mzh-image { border-radius: 0; background: transparent; overflow: visible; }

/* 编辑个人信息：复用绿色背景、Nav、Avatar、FormRow 与 Divider。 */
.mzh-mine__avatar > img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-full); }
.mzh-phone--profile { height: var(--mine-page-height); }
.mzh-profile__card { position: absolute; left: var(--profile-page-card-x); top: var(--profile-page-card-y); width: var(--profile-page-card-w); height: var(--profile-page-card-h); }
.mzh-profile__panel { position: absolute; left: var(--profile-page-panel-x); top: var(--profile-page-panel-y); width: var(--profile-page-panel-w); height: var(--profile-page-panel-h); background: var(--color-bg-primary); border-radius: var(--radius-3xl) var(--radius-xs) var(--radius-3xl) var(--radius-xs); }
.mzh-profile__fields { position: absolute; top: var(--profile-page-fields-top); left: var(--spacing-lg); width: var(--profile-page-fields-w); display: flex; flex-direction: column; gap: var(--spacing-lg); padding: var(--spacing-md) 0; }
.mzh-profile__avatar { position: absolute; left: var(--profile-page-avatar-x); top: 0; width: var(--profile-page-avatar-size); height: var(--profile-page-avatar-size); background: transparent; }
.mzh-profile__camera { position: absolute; left: var(--profile-page-camera-x); top: var(--profile-page-camera-y); }
.mzh-profile__feedback { position: absolute; top: var(--profile-page-card-h); left: var(--spacing-lg); width: var(--profile-page-fields-w); color: var(--color-text-primary); background: var(--color-bg-primary); padding: var(--spacing-sm); border-radius: var(--radius-md); font-size: var(--typography-body-font-size); line-height: var(--typography-body-line-height); }

.mzh-phone--warranty { height: var(--mine-page-height); }
.mzh-warranty__bg { position: absolute; left: 0; top: 0; }
.mzh-warranty__list { position: absolute; top: var(--warranty-page-list-top); left: var(--spacing-lg); width: var(--warranty-card-width); display: flex; flex-direction: column; gap: var(--warranty-page-list-gap); }
