/* ==========================================================================
   flipbook.css —— 3D 翻书样式（共享）
   使用方：/flipbook 展示页 · 法律新规详情页 · 法律问答详情页（翻书模式）
   组件骨架类名以 .flipbook- / .leaf / .curl-seg 开头，勿在业务样式里重名。
   ========================================================================== */

/* ==================== 书（对开双页 · 弧形卷曲翻页） ====================
   ★ 尺寸改为按「视口高」反推（2026-09-29 王主任：适配 1920×1080）。
     原先容器钉死 `max-width:1200px` + `aspect-ratio:20/19` → 书高 **1140px**，
     在 1080 高的屏上光书本身就出屏（实测书顶在 609px、控制条底部 1737px，超出首屏 657px），
     且单页 554×1052（1:1.9）又高又窄，不像书页（A4 是 1:1.414）。
     现在两处一起修：
       ① 展开双页比 10/7 → 单页 5:7 = 1:1.4（≈A4），比例协调；
       ② 书宽由视口高算出，扣掉「吸顶头部 + 工具条 + 控制条 + 外边距」的预留量，
          滚到书上时**整本书连同工具条/控制条都在一屏内**（不用再来回滚）。
     实测 1920×1080：书高 870 / 宽 1243；工具条 38 + 书 870 + 控制条 40 + 间距 ≈ 994 ≤ 1016（1080 − 吸顶头部 64）。 */
.flipbook-container {
  --fb-ar: 1.4286;        /* 展开双页宽高比（10:7）—— 改这里等于改书的胖瘦 */
  --fb-reserve: 210px;    /* 视口高里留给 吸顶头部/工具条/控制条/外边距 的量 */
  /* ★ 视口高单位：移动端 `100vh` = **大视口**（含收起的地址栏），比真实可视高**偏大** →
     书被算大、底部控制条被挤出屏幕；而沉浸层是 `fixed; inset:0`（真实可视高），
     两者对不上。`dvh`（动态视口高）跟着地址栏收放，才是移动端该用的；
     老浏览器不认就退回 vh（下面 @supports 覆盖）。 */
  --fb-vh: 100vh;
  /* ★ 只含长度、不含百分比：下面要代入 perspective 的 calc，而 perspective **不接受百分比**
     （一旦非法整条被丢弃 → perspective 变 none → 3D 翻页直接失效）。 */
  --fb-w: min(1440px, calc((var(--fb-vh) - var(--fb-reserve)) * var(--fb-ar)));
  width: min(100%, var(--fb-w));
  margin: 24px auto;
  /* ★ 透视必须随书的大小走：原来写死 2600px，书一旦从 1120 变到 1243/1440，
     3D 翻页的透视强度就跟着漂（书越大越"平"）。按 2600/1120 ≈ 2.32 倍书宽等比缩放。 */
  perspective: calc(var(--fb-w) * 2.32);
}
@supports (height: 100dvh) {
  .flipbook-container { --fb-vh: 100dvh; }
}

/* 书的外框 */
.flipbook-book {
  position: relative;
  width: 100%;
  aspect-ratio: 10 / 7;
  transform-style: preserve-3d;
  background: #2a2a2a;
  border-radius: 10px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.35);
  touch-action: none;      /* 允许在书页上拖拽而不触发页面滚动 */
  cursor: grab;
  /* 书页是"仿真纸张"：文字不可选取、长按不弹拷贝/搜索菜单 ——
     选中蓝色高亮和系统菜单会破坏翻书的沉浸感，也会和拖拽翻页手势打架 */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;   /* iOS 长按弹「拷贝/搜索」的开关 */
}
.flipbook-book:active { cursor: grabbing; }

/* 书脊（中间弧形阴影：凹陷感） */
.flipbook-spine {
  position: absolute;
  top: 0;
  left: 50%;
  width: 64px;
  height: 100%;
  transform: translateX(-50%);
  background:
    radial-gradient(ellipse 60% 100% at 50% 50%,
      rgba(0,0,0,0.34) 0%,
      rgba(0,0,0,0.16) 45%,
      rgba(0,0,0,0) 75%);
  pointer-events: none;
  z-index: 50;
}
/* 翻页进行中：书脊投影加深 + 整书阴影微增（JS 在翻页开始/结束时切 is-flipping），
   让"正在翻"在视觉上有整本书的重量感，而不是只有纸在动 */
.flipbook-book { transition: box-shadow .35s ease; }
.flipbook-book.is-flipping { box-shadow: 0 26px 62px rgba(0, 0, 0, 0.46); }
.flipbook-book.is-flipping .flipbook-spine {
  background:
    radial-gradient(ellipse 78% 100% at 50% 50%,
      rgba(0,0,0,0.46) 0%,
      rgba(0,0,0,0.24) 45%,
      rgba(0,0,0,0) 78%);
}

/* 翻页纸投到下层页上的动态影条（flipbook-core.js 逐帧更新位置与浓度）：
   z=150 —— 介于已翻纸(100+)与未翻纸(200-)之间，只压在页面内容上、不压翻页纸。 */
.flipbook-cast-shadow {
  position: absolute;
  top: 0;
  left: 20%;
  width: 60%;
  height: 100%;
  background: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.32) 50%, rgba(0,0,0,0) 100%);
  opacity: 0;
  pointer-events: none;
  z-index: 150;
  will-change: transform, opacity;
}

/* 左侧硬封面（底层装饰）
   ★ 只在「书还没翻开」时露出（flipbook-core.js 的 syncCover 控制 display）。
     翻开第一张纸之后左半页永远是 currentLeaf−1 的背面，硬封面不该再露面 ——
     一旦某张纸缺失，露出来的必须是下面那层白纸底，而不是深蓝封面。 */
.flipbook-cover-left {
  position: absolute;
  top: 6px;
  left: 6px;
  width: calc(50% - 8px);
  height: calc(100% - 12px);
  background: linear-gradient(135deg, #0e2b45, #1d4e7a);
  border-radius: 4px 0 0 4px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #b8945a;
  z-index: 2;
  overflow: hidden;
}
.flipbook-cover-left .cover-title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 2px;
  writing-mode: vertical-rl;
  text-align: center;
}
.flipbook-cover-left .cover-sub {
  margin-top: 16px;
  font-size: 13px;
  opacity: 0.8;
}

/* 纸底：铺在硬封面之上、所有书页之下（inset 与 .flipbook-leaves 对齐）
   ★ 兜底用：万一某张纸因任何原因不在树上，露出来的是「一张白纸」，
     而不是深蓝硬封面或黑书框 —— 有碍观感的可能性归零。 */
.flipbook-paper-under {
  position: absolute;
  inset: 6px;
  background: #fdfcf7;
  border-radius: 3px;
  z-index: 1;
  pointer-events: none;
}

/* 纸张容器
   ★ z-index 必须显式给：它带 transform-style:preserve-3d（自成层叠上下文），
     若保持 auto 就会被上面的 .flipbook-paper-under 整层盖住。 */
.flipbook-leaves {
  position: absolute;
  inset: 6px;
  z-index: 3;
  transform-style: preserve-3d;
}

/* 单张纸（整体绕书脊旋转 + 内部分段卷曲）
   ★ 动画由 JS 的 requestAnimationFrame 逐帧驱动（flipbook-core.js），
     这里**不能**再挂 transition —— rAF 每帧都写 transform，transition 会
     "追帧"造成延迟抖动；卷曲路径必须每帧真实求值，插值会把它拍平。 */
.leaf {
  position: absolute;
  top: 0;
  left: 50%;
  width: 50%;
  height: 100%;
  transform-origin: left center;
  transform-style: preserve-3d;
  z-index: 1;
}

/* 卷曲分段（铰链）：等宽、不裁剪，保证正反面 3D 生效。同 .leaf：不加 transition */
.curl-seg {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% / var(--n));
  height: 100%;
  transform-origin: left center;
  transform-style: preserve-3d;
}

/* 分段的正/反面：仅分段宽，裁剪出属于自己的条带 */
.seg-face {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  background: #fdfcf7;
  overflow: hidden;
  /* 右缘补 1px 底色，填补分段亚像素缝隙（不复制内容） */
  box-shadow: 1px 0 0 0 #fdfcf7;
}
.seg-face.back { transform: rotateY(180deg); }
/* 卷曲明暗：按**每段自己的法线朝向**给浓度（JS 逐段写 --shadeF/--shadeB）——
   ★ 不能用「每段右缘变暗」的渐变：24 个分段会把它重复 24 次，
     形成周期性竖条纹。正确形态：浓度随段在弧上的位置单调变化，
     front 面越靠纸尖越暗（斜对光），back 面相反（镜像）。 */
.seg-face::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: #000;
  opacity: 0;
}
.seg-face.front::after { opacity: var(--shadeF, 0); }
.seg-face.back::after  { opacity: var(--shadeB, 0); }

/* 内层条带：整页宽，位移到本段位置 */
.strip {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% * var(--n));
  height: 100%;
}
.seg-face.front .strip { transform: translateX(calc(var(--seg) * -100% / var(--n))); }
/* ★ back 面位移必须补偿 face 自身的 rotateY(180)：
   back face 净旋转 = 叶子 rotateY(-180) ∘ face rotateY(180) = 0（内容不镜像），
   但 face 旋转对**位置**的映射仍在：face 本地点 q → 纸坐标 (seg+1)·w − q。
   解得条带位移 T = (seg + 1 − n)·段宽（全为负或零，seg=n−1 时为 0）。 */
.seg-face.back .strip  { transform: translateX(calc((var(--seg) + 1 - var(--n)) * 100% / var(--n))); }

/* ==================== 书页内容版式（通用） ====================
   字号按「半页宽度、长时间阅读」定：桌面正文 16px / 行高 1.9，
   比普通网页正文略大——书页是纸面阅读场景，字小了吃力。 */
.flipbook-content {
  font-family: inherit;
  line-height: 1.8;
  color: #2c2c2c;
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 20px 28px 16px;
  box-sizing: border-box;
}
.flipbook-content h1 {
  font-size: 22px;
  color: var(--navy, #0e2b45);
  margin-bottom: 12px;
  border-bottom: 2px solid var(--gold, #b8945a);
  padding-bottom: 8px;
}
/* ★ 翻书正文基准字号 = 17px（2026-09-29 王主任统一口径）。
   这一条同时服务三处：问答页「前言 / 编制说明」那几段（collectQaBlocks() 会把
   `.qa-doc-intro` 外壳丢掉、只搬它的 children，所以前言段在书里就是这里的
   无类 <p>，第 429 行那条 `.flipbook-content .qa-doc-intro p` 因此命中不到）、
   以及各正文段落。基准从 16px 提到 17px，与 `.qa-entry-at` / `.qa-fact-b`
   以及问答页正文完全同值。 */
.flipbook-content p {
  margin-bottom: 12px;
  text-align: justify;
  font-size: 17px;
  line-height: 1.95;
}
.flipbook-content ul {
  margin-left: 18px;
  margin-bottom: 12px;
}
.flipbook-content li {
  margin-bottom: 6px;
  font-size: 17px;
  line-height: 1.9;
}
.flipbook-page-num {
  margin-top: auto;
  font-size: 11.5px;
  color: #aaa;
  text-align: center;
  padding-top: 8px;
}
/* 页眉：本页所属章节标题（法规的编/章、问答的册/章）。压在正文之上的一条细线标题
   ★ 王主任 2026-09-29 定：黑体、比正文大两号。
     黑体是「无衬线 + 笔画粗」，与正文的衬线体形成层级；再配 font-weight 兜住
     没有装 SimHei 的机型（安卓/部分 Mac 回落雅黑/思源，不加粗会看着和正文一样轻）。
   ★ 2026-09-29 追改：正文基准由 16px 提到 17px，页眉按同一规则 18px → 19px。
     若只提正文不提页眉，页眉（尤其手机端原来那条 17.5px）会塌到与正文同级，
     层级在视觉上就没了 —— 这是"统一正文字号"的必要连带。 */
.flipbook-page-head {
  font-family: "SimHei", "Heiti SC", "Microsoft YaHei", sans-serif;
  font-weight: 700;
  font-size: 19px;
  line-height: 1.5;
  color: #8a7a5c;
  letter-spacing: .02em;
  padding-bottom: 6px;
  margin-bottom: 10px;
  border-bottom: 1px solid rgba(184, 148, 90, 0.35);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ==================== 扉页（封面页） ====================
   结构见 flipbook-core.js 的 faceHtml：leaf0.front，带 .flipbook-cover-page。
   ★ 居中：水平靠此处的 text-align（必须显式写，否则被 .flipbook-content p 的
     justify 盖掉 —— 单行 justify 等于左对齐，扉页副标题就是这么歪的）；
     垂直靠 .flipbook-content 的内联 justify-content:center，但页码的
     margin-top:auto 会把上方文字顶到页顶 → 这里把页码改成绝对定位钉在页脚，
     标题+副标题才真正作为一个整体垂直居中。
   ★ 字号（王主任 2026-09-29）：标题 24px；副标题 = 正文 + 2。
     正文基准 16px → 17px 之后副标题同步 18px → 19px ——
     fb-typecheck 探针把「副标题 = 正文 + 2」写成了断言，只提正文不提副标题会直接 FAIL。
     并把原来的浅灰 #888 压深一档，避免"灰色小字"看不清。 */
.flipbook-cover-page { position: relative; }
.flipbook-cover-page h1,
.flipbook-cover-page p { text-align: center; }
.flipbook-cover-page h1 {
  font-size: 24px;
  letter-spacing: .04em;
  margin-bottom: 18px;
}
.flipbook-cover-page p {
  font-size: 19px;
  color: #5f5f5f;
  letter-spacing: .02em;
  line-height: 1.7;
  margin-bottom: 0;
}
.flipbook-cover-page .flipbook-page-num {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 14px;
  margin-top: 0;
  padding-top: 0;
}

/* ==================== 控制按钮 ==================== */
.flipbook-controls {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  margin-top: 24px;
  flex-wrap: wrap;
}
.flipbook-btn {
  padding: 10px 26px;
  background: var(--navy, #0e2b45);
  color: #fff;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 15px;
  transition: all 0.3s ease;
}
.flipbook-btn:hover:not(:disabled) {
  background: var(--navy-3, #1d4e7a);
  transform: translateY(-2px);
}
.flipbook-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
/* 音效开关：次级样式，与翻页按钮区分层级 */
.flipbook-btn--sound { background: var(--navy-3, #1d4e7a); min-width: 96px; }
.flipbook-btn--sound.is-off { opacity: .55; }
.flipbook-page-ind { font-size: 14px; color: var(--ink-3, #888); min-width: 88px; text-align: center; }

/* ==================== 详情页「浏览方式」切换与翻书容器 ==================== */
.detail-view-toggle {
  display: inline-flex;
  gap: 0;
  margin-top: 16px;
  border: 1px solid var(--navy, #0e2b45);
  border-radius: 8px;
  overflow: hidden;
}
.detail-view-toggle button {
  padding: 9px 22px;
  border: none;
  background: transparent;
  color: var(--navy, #0e2b45);
  font-size: 14px;
  cursor: pointer;
  transition: background .2s ease, color .2s ease;
}
.detail-view-toggle button.is-active {
  background: var(--navy, #0e2b45);
  color: #fff;
}
.detail-view-toggle button:not(.is-active):hover { background: rgba(14, 43, 69, 0.08); }

/* 翻书模式的容器与工具条 */
.detail-flipbook { display: block; }
.detail-flipbook .flipbook-container { margin: 22px auto; }
.detail-flipbook-toolbar {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 4px;
}
/* 章节跳转下拉（法规大部头没有它没法用） */
.detail-flipbook-toolbar select {
  padding: 9px 12px;
  border: 1px solid var(--line, #d7dce4);
  border-radius: 6px;
  background: #fff;
  color: var(--ink, #2c2c2c);
  font-size: 14px;
  max-width: 320px;
}

/* ==================== 书页内的业务内容（法条 / 问答） ====================
   业务内容类（.law-article / .qa-entry …）由 style.css 全局定义，书页内直接生效；
   这里只做「书页语境」的必要覆盖：半页宽度下收紧字号与内边距，
   并把块间距补上（原父容器是 grid gap，书页里是普通流）。 */
.flipbook-content .law-article {
  margin-bottom: 12px;
  padding: 13px 16px;
  font-size: 16px;
  line-height: 1.9;
  box-shadow: none;            /* 书页里不再要悬浮阴影（hover 也压掉，纸是平的） */
}
.flipbook-content .law-article:hover { box-shadow: none; background: inherit; }
/* ★ 法条正文在书页里：16px → 17px（2026-09-29 统一口径）。
   书页里 `.flipbook-content p` 那条 17px 会被本条的父子两级选择器（0,2,1）盖过，
   所以法规正文必须在这里单独写一遍；手机端还有一处（见文件末尾媒体查询）。 */
.flipbook-content .law-article p { font-size: 17px; line-height: 1.95; margin-bottom: .55em; }
.flipbook-content .law-article .law-cite-btn { display: none; }  /* 引用按钮在书页无意义 */
.flipbook-content .qa-entry {
  margin-bottom: 14px;
  padding: 13px 16px;
  box-shadow: none;
  font-size: 16px;
}
.flipbook-content .qa-entry:hover { box-shadow: none; background: inherit; }
.flipbook-content .qa-entry .qa-entry-at { font-size: 17px; line-height: 1.95; }
.flipbook-content .qa-entry .qa-entry-q { font-size: 17px; line-height: 1.7; }
/* ★ 章节标题（第 N 章 / 附录）：17.5px → 19px（2026-09-29）。
   正文基准提到 17px 后，17.5px 只剩 0.5px 差，章标题在视觉上塌成了正文
   （滚动视图那边 `.qa-chapter` 本来就是 19px，这里跟上，两处同值）。 */
.flipbook-content .qa-chapter { font-size: 19px; margin: 4px 0 10px; }
.flipbook-content .qa-fact { padding: 10px 12px; }
/* ★ 框内字号（2026-09-29 王主任「这部分太小了」）：正文与「答」同级 17px、标签 15px。
   与 `style.css` 全局那份同值 —— 书页内外一个样，别再各写一个数。
   手机端无需再写一遍：这两条是两段类名（0,2,0），已高于 `style.css` 的单类名（0,1,0），
   且手机媒体查询里没有任何 `.qa-fact-*` 规则会盖它们。 */
.flipbook-content .qa-fact-h { font-size: 15px; }
.flipbook-content .qa-fact-b { font-size: 17px; line-height: 1.85; }
.flipbook-content .qa-table { font-size: 14px; }
/* ★★ 书页里表头必须**允许折行**。
   全局 `.qa-table thead th { white-space: nowrap }` 是给**滚动视图**的宽屏表格定的
   （表头不折行才整齐）。但手机书页的正文列只有 311px：`nowrap` 的表头把整张表顶到
   423px（超右 112px），而书页上横向拖拽是**翻页手势** —— 表格壳上那条
   `overflow-x: auto` 在这里等于失效，溢出部分根本滚不到（王主任 2026-09-29
   /qa/0 的信访法规表）。放开折行 → 表格自己收进纸宽，一个像素都不溢出。 */
.flipbook-content .qa-table th { white-space: normal; }
/* 上面第 245 行那条 `.flipbook-content p` 命中不到这里（它被 collectQaBlocks() 剥掉了外壳），
   但这条仍然保留：一旦将来 collectQaBlocks 改成整块搬 `.qa-doc-intro`，它就是生效的兜底。
   ★ 2026-09-29 同步到正文基准 17px，免得两条规则各说一个数。 */
.flipbook-content .qa-doc-intro p { font-size: 17px; line-height: 1.95; }

/* ==================== 测量容器（切页引擎离屏用量） ==================== */
.fb-measure {
  position: absolute !important;
  left: -99999px;
  top: 0;
  visibility: hidden !important;
  pointer-events: none;
  z-index: -1;
}

/* ==================== 手机端：单页模式 ==================== */
@media (max-width: 768px) {
  /* ★ 手机端必须还原成整幅宽：上面那套「按视口高反推宽度」是给桌面横屏的，
     手机上（尤其横屏 100vh 很小）会把书压得很小。手机走 aspect-ratio: 3/4 单页。 */
  .flipbook-container { width: 100%; max-width: none; perspective: 1800px; }
  .flipbook-book { aspect-ratio: 3 / 4; }
  .flipbook-spine { display: none; }
  .flipbook-cover-left { display: none; }
  .flipbook-leaves { inset: 4px; }
  .flipbook-paper-under { inset: 4px; }
  .leaf {
    left: 0;
    width: 100%;
    transform-origin: left center;
  }
  .flipbook-content { padding: 16px 18px 12px; }
  .flipbook-content h1 { font-size: 19px; }
  /* ★ 2026-09-29 统一口径：15.5px → 17px（与桌面那条同值，手机不再自降一档）。
     `p` 服务问答页「前言 / 编制说明」那几段（书里是无类 <p>）；`li` 同步，
     免得列表项比正文小一号。 */
  .flipbook-content p, .flipbook-content li { font-size: 17px; }
  /* ★ 法条正文：15.5px → 17px（与桌面、与滚动视图两处同值） */
  .flipbook-content .law-article p { font-size: 17px; }
  /* ★★★ 手机端「答」正文：选择器的**段数（权重）必须与桌面那条一致**，否则这条是死规则。
     桌面写的是 `.flipbook-content .qa-entry .qa-entry-at`（三段类名 = 0,3,0），
     这里原来只写两段（`.flipbook-content .qa-entry-at` = 0,2,0）→ 权重更低，
     永远被桌面那条 `font-size: 16px` 压住 —— 那个 15px 从上线起就没生效过。
     现值对齐「问」正文的字号（手机上 .qa-entry-qt 继承 .qa-entry-q = 17px），
     使手机翻书内「问 / 答」正文字号一致。
     ★ 只写 font-size：line-height 仍由桌面那条的 1.95 提供，字体、颜色、对齐一律未动。 */
  .flipbook-content .qa-entry .qa-entry-at { font-size: 17px; }
  /* 手机端正文 17px → 页眉大两号 = 19px（与桌面那份同值；原来 17.5px 是配 15.5px 正文的） */
  .flipbook-page-head { font-size: 19px; }
  /* 扉页：手机端同步放大（媒体查询在文件末尾，同权重会盖掉桌面那份，必须在这里再给） */
  .flipbook-cover-page h1 { font-size: 22px; }
  .flipbook-cover-page p { font-size: 19px; }
  .flipbook-btn { padding: 9px 20px; font-size: 14px; }
  .detail-view-toggle button { padding: 8px 16px; }
  .detail-flipbook-toolbar select { width: 62vw; max-width: 62vw; }
  /* ★★ 工具条里**宽度随内容变化**的两处必须钉死（王主任 2026-09-29 手机纵向溢出根因）：
     ① 跳转下拉：`buildJumpSelect` 在**分页之后**才把章节填进去 → select 由 102px 长到 62vw；
     ② 页码指示器：「已读 0 / 109 页」比「已读 0 / 51 页」宽（88 → 97px）。
     两处一长，工具条就由**一行变两行**（38px → 89px）、书区矮 51px —— 而切页引擎是在
     **填下拉之前**量的尺寸：按 701px 高的纸分页，真实纸只有 650px，每页最多多排 43px，
     末块压过页码（`/qa/0` 那 8 处纵向溢出）。
     ★ 只在沉浸/全屏态受影响：内联态与桌面态的纸高由 `aspect-ratio` 反推，与工具条无关。 */
  .flipbook-page-ind { width: 112px; min-width: 112px; white-space: nowrap; }
}

/* ==========================================================================
   全屏阅读（王主任 2026-09-29）
   --------------------------------------------------------------------------
   翻书「页面多大」这个问题，不在数字上解，而在「给足空间」上解：
   全屏之后浏览器外壳、站点吸顶头部、正文头都不再抢占屏幕，
   书的可用高度＝整屏高 —— 于是「按视口高反推书宽」那套规则自动给出最大且完整的书，
   换任何分辨率都不用再逐档调参。

   JS（detail-flipbook.js 的全屏子系统）维护三种状态，CSS 只认下面两个类：
     native    —— 原生全屏，元素命中 :fullscreen（浏览器已接管定位与背景）
     immersive —— 降级覆盖层：.detail-flipbook.is-immersive
                  用于 iOS Safari、非安全上下文、iframe 未授权、权限策略拒绝等
     none      —— 内联翻书（原形态，保持完全可用）
   ★ immersive 与 native 的**布局规则必须一致**，否则"降级后不一样"就成了新缺陷，
     所以下面凡是尺寸/排版规则都写成成对选择器。
   ========================================================================== */
.detail-flipbook:fullscreen,
.detail-flipbook.is-immersive {
  display: flex;
  flex-direction: column;
  justify-content: center;      /* 书 + 工具条 + 控制条 整体垂直居中 */
  align-items: center;
  gap: 10px;
  box-sizing: border-box;
  padding: 12px 16px;
  overflow: auto;               /* 兜底：极端窄/矮屏宁可出滚动条，也不裁内容 */
  /* 暖色微渐变：白书浮起来，且与品牌金/藏青同调（深色背景会让纸页显得脏） */
  background: radial-gradient(120% 130% at 50% 36%, #fdfbf6 0%, #eae1d2 100%);
}
/* 沉浸层要自己盖住整屏并锁住下层滚动（原生全屏由浏览器负责，不需要这两条） */
html.fb-immersive,
html.fb-immersive body { overflow: hidden; }
.detail-flipbook.is-immersive {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  z-index: 9000;                /* 高于 .site-header 的 z-index:100 */
}
/* 全屏里没有吸顶头部要预留 → --fb-reserve 从 210 收到 150（只留给工具条+控制条+间距），
   书因此比内联时更大。★ 必须写在 .flipbook-container 这一级，它自己的声明会盖掉继承值。 */
.detail-flipbook:fullscreen .flipbook-container,
.detail-flipbook.is-immersive .flipbook-container {
  --fb-reserve: 150px;
  flex: 0 0 auto;
  margin: 0 auto;
}
.detail-flipbook:fullscreen .detail-flipbook-toolbar,
.detail-flipbook.is-immersive .detail-flipbook-toolbar,
.detail-flipbook:fullscreen .flipbook-controls,
.detail-flipbook.is-immersive .flipbook-controls {
  flex: 0 0 auto;
  margin-top: 0;
}

/* 进入/退出全屏的视觉过渡。
   ★ 只做 opacity —— 尺寸类属性（width/height/aspect-ratio）一旦进动画，
     切页引擎会在动画中途按"过渡中的尺寸"分页，等于白算；而且逐帧写入与
     transition 抢帧会抖（同 .leaf 不加 transition 的道理）。 */
@keyframes fb-fs-in { from { opacity: 0; } to { opacity: 1; } }
.detail-flipbook.is-fs-in { animation: fb-fs-in .34s ease both; }
@media (prefers-reduced-motion: reduce) { .detail-flipbook.is-fs-in { animation: none; } }

/* 工具条右侧的「全屏 / 退出全屏」按钮 */
.detail-flipbook-toolbar .df-fs {
  padding: 9px 16px;
  min-width: 96px;
  border: 1px solid var(--navy, #0e2b45);
  border-radius: 6px;
  background: transparent;
  color: var(--navy, #0e2b45);
  font-size: 14px;
  cursor: pointer;
  transition: background .2s ease, color .2s ease;
}
.detail-flipbook-toolbar .df-fs:hover { background: rgba(14, 43, 69, .08); }
.detail-flipbook-toolbar .df-fs[aria-pressed="true"] {
  background: var(--navy, #0e2b45);
  color: #fff;
}

/* 降级提示（只在真的走了覆盖层、且每个会话第一次时出现） */
.df-toast {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translate(-50%, 8px);
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(14, 43, 69, .9);
  color: #fff;
  font-size: 13px;
  line-height: 1.4;
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease, transform .22s ease;
  z-index: 20;
}
.df-toast.is-on { opacity: 1; transform: translate(-50%, 0); }

/* ==========================================================================
   手机端全屏：单页 · **竖向自适应**（王主任 2026-09-29）
   --------------------------------------------------------------------------
   问题：手机竖屏打开翻书（窄屏进翻书即全屏）时，纸上下各留一大片空白。
   旧做法给纸钉了 `aspect-ratio: 3/4`（0.75）再让宽度 = 100%。
   可是 0.75 的纸放进 375×812：宽 355 → 高只有 473，**只占屏高 58%**，
   上留白 195 + 下留白 143（其中工具条 89、控制条 37 是真控件，纯空白约 212）。
   ★ 这在数学上无解：「填满宽」与「填满高」在固定比例下必然二选一 ——
     要填满高，纸宽得 812×0.75 = 609px，超出手机视口 62%。

   办法：**放弃固定宽高比，让纸高由布局决定**，把工具条与控制条之间的空档全给书。
     .flipbook-container  吃掉中间全部高度（flex:1 1 auto）
     .flipbook-book       高度跟着容器走，宽度 = min(100%, 可用高 × 0.8)
   比例上限 0.8（王主任拍板）：宽高比一旦超过 0.8（折叠屏展开 / 小平板这类
   "宽而矮"的视口会把纸拉成接近方形甚至横的），就**只收窄、不再加高**，
   退回水平居中留白 —— 宁可两侧留白，也不给一张横着的"书页"。
   横屏手机（宽 >768px）走的是桌面双页逻辑，不进这段（王主任：横屏用双页）。

   实测 375×812：纸 355×670，竖向占比 ≈ 99%，比例 0.53。
   ★ 字号 / 行高 / 内边距一律不动 —— 纸变高只是每页多排几行，可读性不受影响。
   ★ 纸的尺寸是切页引擎从真实 DOM 量的（detail-flipbook.js `pageDims()`），
     CSS 改完 JS 自动跟着变；但 **必须先把旧书撤掉再量**（见 buildBook 里 destroy 的位置），
     否则旧书与测量探针在弹性列里平分高度，会量出一张偏小的纸（→ 分页偏多、页页半空）。
   ========================================================================== */
@media (max-width: 768px) {
  /* 工具条 / 控制条不参与伸缩：贴顶、贴底，中间空档全留给书 */
  .detail-flipbook:fullscreen .detail-flipbook-toolbar,
  .detail-flipbook.is-immersive .detail-flipbook-toolbar,
  .detail-flipbook:fullscreen .flipbook-controls,
  .detail-flipbook.is-immersive .flipbook-controls {
    flex: 0 0 auto;
    margin: 0;
  }
  .detail-flipbook:fullscreen .flipbook-container,
  .detail-flipbook.is-immersive .flipbook-container {
    --fb-reserve: 160px;         /* 只给回退公式用（精确值由 cqh 提供，见下） */
    display: flex;               /* ★ 书要当弹性子项才能"吃满"中间的高度 */
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;               /* 弹性子项默认 min-height:auto 会顶破容器 */
    width: 100%;
    max-width: none;
    margin: 0;
    align-items: center;         /* 上限生效时把纸水平居中，两侧留白对称 */
    /* ★ 容器查询：让下面的 `cqh` 拿到"容器真实可用高"。
       `contain: size` 只影响自身的尺寸来源 —— 本容器的高由外层 flex 定，与内容无关，
       所以不影响 3D（同 .leaf 的 transform 无关）。 */
    container-type: size;
  }
  .detail-flipbook:fullscreen .flipbook-book,
  .detail-flipbook.is-immersive .flipbook-book {
    flex: 1 1 auto;
    min-height: 0;
    aspect-ratio: auto;          /* ★ 撤掉 3/4：留着它，高度会被比例反算回去、填不满 */
    /* ★ 宽度 = min(全宽, 可用高 × 0.8)。两条同权重，后一条能解析就赢；
       `cqh` 不被支持时整条作废，自动退回上面那条按视口高估算的式子。 */
    width: min(100%, calc((var(--fb-vh) - var(--fb-reserve)) * 0.8));
    width: min(100%, 80cqh);
    margin: 0 auto;
  }
  .detail-flipbook:fullscreen,
  .detail-flipbook.is-immersive { padding: 8px 10px; gap: 6px; }
  /* 单独一条：不支持 env() 的老浏览器会丢掉这条，但保住上面那个 padding */
  .detail-flipbook:fullscreen,
  .detail-flipbook.is-immersive {
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));   /* iPhone Home 指示条 */
  }
  .detail-flipbook-toolbar .df-fs { padding: 8px 12px; min-width: 0; }
}

/* ★ 沉浸覆盖层的**出口**（2026-09-29 修）：
   覆盖层是 z-index:9000 的整屏元素，页面头部那个「翻书｜滚动」切换按钮会被它整个盖住
   —— 实测命中测试打到的是一张书页（`elementFromPoint` → H1），点不动。
   于是沉浸态下退出路只剩工具条里的「退出全屏」一个（手机上又没有 Esc）。
   把切换按钮一并抬进全屏层：固定在顶部居中、z-index 高于覆盖层、给个纸色底保证可读。
   （原生全屏时该按钮在 box 之外，浏览器只渲染全屏元素，所以这条只对沉浸态生效。） */
html.fb-immersive .detail-view-toggle {
  position: fixed;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  z-index: 9100;
  background: #fdfcf7;
}
