/* ==========================================================================
   蒙育优培 · 模块统一边栏（网页端）
   - 仅 ≥900px 显示；手机/平板竖屏完全不影响原页面
   - 由 /_nav/sidebar.js 生成 DOM，本文件只管样式
   - 各模块页只需在 </head> 前引入本文件 + sidebar.js
   ========================================================================== */

:root{
  --hb-w: 236px;          /* 展开宽度 */
  --hb-wc: 62px;          /* 收起后的图标栏宽度 */
  --hb-shift: 0px;        /* 「内容区左边缘」的偏移量：手机端恒为 0，网页端 = 边栏宽度。
                             给**固定定位**元素（底部标签栏 / 弹窗遮罩 / 提示条）当 left 用。
                             为什么需要它，见文末「桌面端修正：fixed 元素跟随内容区」。 */
  --hb-bg1: rgba(8,11,18,.68);   /* 边栏底图上的蒙版（上） */
  --hb-bg2: rgba(7,10,16,.74);   /* 边栏底图上的蒙版（下） */
  /* ↑ 边栏不再是一块孤立的深色板：底色改为「页面底图 bg.jpg 的左段 + 一档更厚的蒙版」，
       比内容区背景暗约 1/3，既能看出是同一张图的延续，又能压住浅色文字。
       想调边栏与内容区的明暗差，就动这两个值（数值越大边栏越暗）。 */
  --hb-line: rgba(255,255,255,.09);
  --hb-ink: #C9D4E2;
  --hb-ink-dim: #9AA6B8;
  --hb-ink-hi: #F4F8FD;
  --hb-glow: #FFD45C;
  --hb-z: 40;             /* 低于各页弹窗(50/99)，弹窗能正常盖住边栏 */
  --hb-ease: cubic-bezier(.2,.7,.3,1);
}

/* ---------- 布局偏移：只在网页端生效 ----------
   注意：必须偏移 <html> 而不是 <body>。
   多个模块页用 body{max-width:520px;margin:0 auto} 做居中，
   直接改 body 的 margin-left 会把居中顶掉、内容变成左对齐。
   偏移 <html> 则内容仍在「边栏右侧的剩余空间」里正常居中。 */
@media (min-width:900px){
  html.hb-sb-ready{ margin-left:var(--hb-w); }
  html.hb-sb-ready.hb-sb-collapsed{ margin-left:var(--hb-wc); }
  html.hb-sb-ready{ scroll-padding-left:var(--hb-w); }
}

/* ---------- 桌面端修正：fixed 元素跟随内容区 ----------
   上面偏移的是 <html>，但 **position:fixed 的元素以「视口」为包含块**，
   根本不受这个 margin 影响 —— 于是出现错位：
     内容区在「边栏右侧的剩余空间」居中，而底部标签栏 / 弹窗 / 提示条
     却在「整个视口」居中，两者中心差 = 边栏宽度的一半。
   实测 1280px：内容区中心 758、固定元素中心 640，**差 118px**（肉眼很明显）。
   本段把三类固定元素拉回内容区。**只覆盖定位**，不动尺寸 / 颜色 / 层级 / 动画。
   <900px 时媒体查询不命中 → 手机端零影响（与修改前逐像素相同）。
   ⚠️ 不要给 .bg-layer / .deco-layer 这类**全屏装饰层**加规则 ——
      它们必须铺满整屏（还要与边栏底图接缝），动了会在 x=边栏宽度 处露缝。 */
@media (min-width:900px){
  html.hb-sb-ready{ --hb-shift: var(--hb-w); }
  html.hb-sb-ready.hb-sb-collapsed{ --hb-shift: var(--hb-wc); }

  /* ① 整条铺满的固定条：底部标签栏 / 问卷底部按钮条 / 顶部进度条。
        它们原本是 left:0 + width:100%（或 left:0;right:0），会一直伸到边栏底下；
        改成 left+right 撑满内容区，内部再自行居中。
        ⚠️ 这三者的宽度都由 left/right 决定，所以补 width:auto 是必要的
        （否则 left:偏移 之后 width:100% 会向右溢出边栏宽度那么多）。
        ⚠️ 但**不要把 .sheet 放进来**：/oral/ 的 .sheet 是 fixed（只需 left），
        /reading/ 的 .sheet 是 static —— 对 static 元素 width:auto 会真的生效，
        把弹窗宽度从「撑满 560px」压成「内容自适应」。见下面 ①'。 */
  html.hb-sb-ready .tabbar,
  html.hb-sb-ready .q-nav,
  html.hb-sb-ready .progress-wrap{ left: var(--hb-shift); right: 0; width: auto; }

  /* ①' 底部贴片：/oral/ 的 .sheet 是 fixed（left:0;right:0）→ 挪进内容区即可；
        /reading/ 的 .sheet 是 static（在 .sheet-mask 这个 flex 容器里居中），
        left 对它无效、也不需要——父容器已在 ② 里修正过了。 */
  html.hb-sb-ready .sheet{ left: var(--hb-shift); }

  /* ② 遮罩层 / 居中弹层：自身仍是 inset:0 铺满整屏（背景照旧把边栏一起压暗，观感不变），
        只把「内容盒」右移 —— 里面的弹窗就相对内容区居中。
        ⚠️ 用 border-left 而不是 padding-left：border 不会覆盖各页原有的 padding
        （有的 .mask 自己带 padding:24px、.overlay 带 20px），内容盒正好落在
        各页对称内边距之内，居中位置才精确。实测用 padding-left 会让那类弹窗偏 12px。
        收录范围 = 全站扫出来的所有「全屏遮罩 + 居中内容」：
          .sheet-mask / .loading-mask / .coin-pop（reading）
          .mask（reading 登录页、/scores/、/login/、/oral/）
          .overlay（/yingyu/ 成功弹层）、.modal-overlay（/customers/）
          .splash（/login/ 启动闪屏）
        ⚠️ 不要收录全屏**装饰/背景**层：body::before（品牌首页）、
        .bg-layer / .deco-layer（/survey/）—— 它们必须铺满整屏。 */
  html.hb-sb-ready .sheet-mask,
  html.hb-sb-ready .loading-mask,
  html.hb-sb-ready .coin-pop,
  html.hb-sb-ready .mask,
  html.hb-sb-ready .overlay,
  html.hb-sb-ready .modal-overlay,
  html.hb-sb-ready .splash{ border-left: var(--hb-shift) solid transparent; }

  /* ③ left:50% + translateX(-50%) 的居中提示条：把 50% 的基准一并挪过去，
        新中心 = 50% + 边栏宽度/2。
        !important 是给 /oral/ 的 toast 用的 —— 它的 left 是内联样式写的，
        只有 important 能压过内联。其余同名的类选择器也一并受益。 */
  html.hb-sb-ready #toast,
  html.hb-sb-ready .toast,
  html.hb-sb-ready .done-toast{ left: calc(50% + var(--hb-shift) / 2) !important; }
}

/* ---------- 边栏本体 ---------- */
#hbSidebar{
  position:fixed; top:0; bottom:0; left:0; width:var(--hb-w);
  z-index:var(--hb-z);
  display:none; flex-direction:column;
  background:rgba(8,11,18,.95);        /* 兜底：万一下面那层底图没加载，也不至于透出页面浅背景 */
  border-right:1px solid var(--hb-line);
  box-shadow:1px 0 26px -10px rgba(0,0,0,.62);
  /* 不再用 backdrop-filter：背景已经是底图副本，再加模糊反而与内容区背景对不上 */
  font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
  -webkit-font-smoothing:antialiased;
  color:var(--hb-ink);
  overflow:hidden;
  transition:width .26s var(--hb-ease);
}
/* ---------- 背景层：取页面底图（bg.jpg）的「左侧那一段」 ----------
   铺一份与页面底图**同视口坐标系**的副本：`background-attachment:fixed` 让背景相对
   视口定位（而不是相对本元素），于是它和 `body::before{position:fixed;inset:0}`
   用的是同一套坐标系 —— 在 x=236 那条边界上图案完全续接，看不出接缝。

   ⚠️ 不要图省事改成「边栏透明、直接透出页面底图」：调研发现 /survey/ 页有全屏
      fixed 装饰层（#bgLayer1 / #decoLayer），边栏一透明就会把它们一起显形。
   ⚠️ 别把 background-attachment:fixed 用到**内容区**（iOS 不可控）；这里只用于
      仅桌面端显示的边栏（<900px 时 display:none），安全。
   ⚠️ 换底图时，下面的版本号要和 index.html 里 `bg.jpg?v=` 的那串**同步改**，
      否则边栏与内容区会各显示一个版本的图，边界处会露馅。 */
#hbSidebar::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:
    radial-gradient(120% 100% at 18% 0%,rgba(255,212,92,.10) 0%,rgba(255,212,92,0) 68%),
    linear-gradient(180deg,var(--hb-bg1) 0%,var(--hb-bg2) 100%),
    url("/bg.jpg?v=c9ac3ec4");   /* 必须写绝对路径：本文件在 /_nav/ 下，相对路径会变成 /_nav/bg.jpg */
  background-size:100% 190px, cover, cover;
  background-position:0 0, center center, center center;
  background-repeat:no-repeat, no-repeat, no-repeat;
  background-attachment:scroll, scroll, fixed;
}
@media (min-width:900px){ #hbSidebar{ display:flex; } }
html.hb-sb-collapsed #hbSidebar{ width:var(--hb-wc); }

/* ---------- 顶部品牌区 ---------- */
.hb-top{
  display:flex;align-items:center;gap:8px;flex:none;
  padding:18px 14px 15px;position:relative;
  border-bottom:1px solid var(--hb-line);
}
.hb-brand{display:flex;align-items:center;gap:9px;text-decoration:none;min-width:0;flex:1}
.hb-logo{width:124px;height:auto;flex:none;
  filter:drop-shadow(0 0 16px rgba(255,212,92,.52))}
.hb-toggle{
  flex:none;width:28px;height:28px;border-radius:9px;cursor:pointer;
  border:1px solid var(--hb-line);background:rgba(255,255,255,.05);color:var(--hb-ink-dim);
  display:flex;align-items:center;justify-content:center;padding:0;
  transition:background .18s var(--hb-ease),color .18s var(--hb-ease),border-color .18s var(--hb-ease);
}
.hb-toggle:hover{background:rgba(255,212,92,.16);color:var(--hb-glow);border-color:rgba(255,212,92,.38)}
.hb-toggle svg{width:14px;height:14px;transition:transform .26s var(--hb-ease)}
html.hb-sb-collapsed .hb-toggle svg{transform:rotate(180deg)}

/* ---------- 导航区 ---------- */
.hb-nav{
  flex:1;overflow-y:auto;overflow-x:hidden;
  padding:16px 12px 18px;
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.18) transparent;
  -webkit-mask-image:linear-gradient(180deg,#000 0,#000 calc(100% - 18px),transparent 100%);
  mask-image:linear-gradient(180deg,#000 0,#000 calc(100% - 18px),transparent 100%);
}
.hb-nav::-webkit-scrollbar{width:6px}
.hb-nav::-webkit-scrollbar-thumb{background:rgba(255,255,255,.16);border-radius:3px}

/* 分组：组与组之间留出明显间隔 + 一条细分隔线 */
.hb-grp{position:relative;margin-top:20px;padding-top:16px}
.hb-grp:first-child{margin-top:0;padding-top:0}
.hb-grp + .hb-grp::before{
  content:"";position:absolute;top:0;left:12px;right:12px;height:1px;
  background:linear-gradient(90deg,rgba(255,255,255,.13) 0%,rgba(255,255,255,.05) 65%,rgba(255,255,255,0) 100%);
}

/* 分组标题：彩点 + 文字 + 渐隐细线 */
.hb-glbl{
  display:flex;align-items:center;gap:9px;
  font-size:11.5px;font-weight:600;letter-spacing:.12em;
  -webkit-text-stroke:.3px currentColor;   /* 600 已是 PingFang SC 上限，再粗只能靠描边 */
  color:var(--hb-ink-dim);padding:0 12px 11px;white-space:nowrap;
  transition:color .2s var(--hb-ease);
}
.hb-grp:hover .hb-glbl{color:var(--hb-ink)}
.hb-glbl::after{
  content:"";flex:1;height:1px;min-width:8px;
  background:linear-gradient(90deg,rgba(255,255,255,.16),rgba(255,255,255,0));
}
.hb-dot{
  display:inline-block;width:6px;height:6px;border-radius:50%;flex:none;
  box-shadow:0 0 8px 1px currentColor;
}

/* 菜单项 */
.hb-item{
  display:flex;align-items:center;gap:11px;
  padding:10px 12px;margin-bottom:3px;
  border-radius:11px;text-decoration:none;color:var(--hb-ink);
  font-size:14px;font-weight:600;line-height:1.4;letter-spacing:.01em;
  white-space:nowrap;position:relative;
  transition:background .2s var(--hb-ease),color .2s var(--hb-ease),transform .2s var(--hb-ease);
  /* 入场动画：左滑淡入，由 JS 给的 --i 做错峰 */
  animation:hbIn .42s var(--hb-ease) backwards;  /* 用 backwards：结束后释放 transform，否则 hover 位移会被动画锁死 */
  animation-delay:calc(var(--i, 0) * 26ms + 60ms);
}
@keyframes hbIn{
  from{opacity:0;transform:translateX(-8px)}
  to{opacity:1;transform:none}
}
.hb-item:hover{
  background:rgba(255,255,255,.075);
  color:var(--hb-ink-hi);
  transform:translateX(2px);
}
.hb-item:active{transform:translateX(2px) scale(.985)}
/* 当前项：淡黄渐变底 + 左侧光条（带呼吸） */
.hb-item.hb-cur{
  color:var(--hb-glow);
  /* 注意：PingFang SC 最重只有 600，写 700 会被回退成 600。当前项靠颜色+底色区分，不再叠字重 */
  background-image:linear-gradient(90deg,rgba(255,212,92,.20) 0%,rgba(255,212,92,.05) 72%,rgba(255,212,92,0) 100%);
}
.hb-item.hb-cur::before{
  content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:3px;height:18px;border-radius:0 3px 3px 0;background:var(--hb-glow);
  box-shadow:0 0 10px 1px rgba(255,212,92,.85);
  animation:hbPulse 2.6s ease-in-out infinite;
}
@keyframes hbPulse{
  0%,100%{box-shadow:0 0 8px 0 rgba(255,212,92,.65)}
  50%    {box-shadow:0 0 14px 2px rgba(255,212,92,1)}
}

/* 图标 */
.hb-ic{flex:none;width:20px;height:20px;display:flex;align-items:center;justify-content:center;
  transition:transform .2s var(--hb-ease),color .2s var(--hb-ease)}
.hb-ic svg{width:18px;height:18px;display:block}
.hb-item:hover .hb-ic{transform:scale(1.1)}
.hb-item.hb-cur .hb-ic{filter:drop-shadow(0 0 6px rgba(255,212,92,.55))}
.hb-t{overflow:hidden;text-overflow:ellipsis}

/* ---------- 收起态 ---------- */
html.hb-sb-collapsed .hb-brand-t,
html.hb-sb-collapsed .hb-lbl,
html.hb-sb-collapsed .hb-t{display:none}
html.hb-sb-collapsed .hb-top{padding:18px 0 15px;justify-content:center}
html.hb-sb-collapsed .hb-brand{display:none}
html.hb-sb-collapsed .hb-nav{padding:14px 0 18px}
html.hb-sb-collapsed .hb-grp{margin-top:16px;padding-top:14px}
html.hb-sb-collapsed .hb-grp + .hb-grp::before{left:16px;right:16px}
html.hb-sb-collapsed .hb-item{justify-content:center;padding:12px 0;border-radius:0;margin-bottom:0}
html.hb-sb-collapsed .hb-item:hover{transform:none;background:rgba(255,255,255,.075)}
html.hb-sb-collapsed .hb-glbl{display:flex;justify-content:center;padding:0 0 10px}
html.hb-sb-collapsed .hb-glbl::after{display:none}
html.hb-sb-collapsed .hb-item.hb-cur::before{display:none}
html.hb-sb-collapsed .hb-item.hb-cur{background-image:none;background-color:rgba(255,212,92,.14)}

/* ---------- 底部 ---------- */
.hb-foot{
  flex:none;padding:12px 12px 16px;position:relative;
  border-top:1px solid var(--hb-line);
}
/* 底栏上方一层暗色渐隐，滚动到底时更干净 */
.hb-foot::before{
  content:"";position:absolute;left:0;right:0;top:-24px;height:24px;pointer-events:none;
  background:linear-gradient(180deg,rgba(9,12,19,0),rgba(9,12,19,.55));
}
html.hb-sb-collapsed .hb-foot{padding:12px 0 16px}

/* ---------- 收起态悬停提示 ---------- */
html.hb-sb-collapsed .hb-item{position:relative}
html.hb-sb-collapsed .hb-item:hover::after{
  content:attr(data-t);
  position:absolute;left:calc(100% + 10px);top:50%;transform:translateY(-50%);
  background:rgba(20,26,38,.97);color:#F0F4FA;font-size:12.5px;font-weight:500;
  padding:6px 11px;border-radius:9px;white-space:nowrap;
  border:1px solid rgba(255,255,255,.13);box-shadow:0 10px 26px -8px rgba(0,0,0,.85);
  z-index:5;pointer-events:none;
  animation:hbTip .16s var(--hb-ease) both;
}
@keyframes hbTip{from{opacity:0;transform:translateY(-50%) translateX(-4px)}to{opacity:1;transform:translateY(-50%)}}

/* ---------- 矮屏自适应：笔记本常见视口高 700~840px ----------
   字号保持 14px 不变（用户要求字大），只自动收紧内边距与组间距，
   尽量让 12 个模块一屏放得下，少滚动。 */
@media (min-width:900px) and (max-height:840px){
  .hb-top{padding:14px 14px 12px}
  .hb-nav{padding:12px 12px 14px}
  .hb-grp{margin-top:15px;padding-top:12px}
  .hb-item{padding:8px 12px;margin-bottom:2px}
  .hb-foot{padding:10px 12px 12px}
  .hb-glbl{padding-bottom:9px}
}

/* ==========================================================================
   模块间整页过渡（自然过渡）
   两条通道，由「注入块内联脚本里的同一个判定」互斥控制，绝不会叠加：
     A 通道  Chromium 126+ → 跨文档 View Transitions，浏览器原生接管，无白屏
             内联脚本会给 <html> 加 .hb-vt 并注入 @view-transition
     B 通道  其余浏览器     → 点链接时 JS 加 .hb-page-leaving 播退场，
                             新页面随 HTML 一起播 hbPageIn 入场
   ========================================================================== */

/* ---- A：跨文档视图过渡的动画（不支持的浏览器会忽略这些伪元素规则） ----
   镜头感设计：
     旧页「向纵深退去」→ 放大 + 模糊 + 压暗，但**始终保持不透明**。
       这一点是关键：它永远垫在新页下方，所以交叉期间绝不会透出画布底色。
     新页「从前方浮出」→ 由略小 + 更模糊 + 半透明，缩放至清晰，带一点高光过曝感。 */
::view-transition-old(root){
  animation:hbVtOut .57s cubic-bezier(.4,0,.3,1) both;
}
::view-transition-new(root){
  animation:hbVtIn .70s cubic-bezier(.16,.84,.28,1) both;
}
@keyframes hbVtOut{
  from{ opacity:1; transform:scale(1);    filter:blur(0)    brightness(1) }
  to  { opacity:1; transform:scale(1.07); filter:blur(15px) brightness(.70) }
}
@keyframes hbVtIn{
  from{ opacity:0; transform:scale(.945); filter:blur(13px) brightness(1.10) }
  55% { opacity:1 }
  to  { opacity:1; transform:scale(1);    filter:blur(0)    brightness(1) }
}
/* 已经交给浏览器做过渡了，页面自身不能再播入场，否则会「双重淡入」且快照拍到空白帧 */
html.hb-vt body{ animation:none !important; }

/* 边栏单独成组：内容区在缩放模糊地切换时，导航栏保持稳定（像原生 App 的转场）。
   元素只在一侧存在时（如品牌首页没有边栏），浏览器按"空快照"处理，不会中断整场过渡。 */
#hbSidebar{ view-transition-name:hb-sidebar; }
::view-transition-group(hb-sidebar){ animation-duration:.60s; }
::view-transition-old(hb-sidebar),
::view-transition-new(hb-sidebar){ animation-duration:.60s; }

/* ---- B-1：新页面入场（随 HTML 一起加载，首帧即生效，不会闪白） ----
   与 A 通道同一套镜头语言：从「略小 + 模糊 + 半透明 + 下沉一点」缩放到清晰。
   两个刻意的取值：
   ① 起点用 .42 而不是 0。body 一旦全透明，画布就会露出浏览器默认底色（多为纯白），
      实测 /ceping/ /reading/ 系列画布就是 #FFFFFF，深色页会「白闪」一下。
      从 .42 起步保住了淡入感，又不会闪底。
   ② 用 backwards 而不是 both。both 会在动画结束后继续把 transform 锁在最后一帧，
      既影响页面自身的 position:fixed 元素，也会锁死后续动效。 */
html.hb-sb-ready body{
  animation:hbPageIn .68s cubic-bezier(.16,.84,.28,1) backwards;
}
@keyframes hbPageIn{
  from{ opacity:.42; transform:scale(.955) translateY(14px); filter:blur(12px) brightness(1.06) }
  to  { opacity:1;   transform:none;                        filter:blur(0)    brightness(1) }
}

/* ---- B-2：离场（JS 加类触发，动画一结束立刻跳转） ----
   向纵深退去：放大 + 模糊 + 压暗 + 淡出。终点留 .45 不透明度 ——
   完全淡到 0 会先露出画布底色，万一下一页加载慢就会干等在一片白上。 */
html.hb-page-leaving body{
  animation:hbPageOut .34s cubic-bezier(.42,0,.72,.18) both !important;
  pointer-events:none;
}
@keyframes hbPageOut{
  from{ opacity:1;   transform:none;                         filter:blur(0)    brightness(1) }
  to  { opacity:.45; transform:scale(1.05) translateY(-9px); filter:blur(10px) brightness(.82) }
}

/* 浏览器前进/后退经 bfcache 回到本页时，不重播入场（否则会「闪一下」） */
html.hb-no-anim body{ animation:none !important; }

/* ---- 手机端只做淡入，不做位移 ----
   移动端 body 上一旦有 transform，其内部 position:fixed 元素会改用 body 作为定位基准，
   动画期间容易看到吸顶头 / 底部条抖动。淡入没有这个副作用，观感也够。 */
@media (max-width:899px){
  html.hb-sb-ready body{ animation:hbPageInM .44s var(--hb-ease) backwards; }
  html.hb-page-leaving body{ animation:hbPageOutM .24s cubic-bezier(.42,0,.72,.2) both !important; }
}
@keyframes hbPageInM{ from{opacity:.42} to{opacity:1} }
@keyframes hbPageOutM{ from{opacity:1}  to{opacity:.12} }

/* ---------- 无障碍 / 打印 ---------- */
@media (prefers-reduced-motion:reduce){
  #hbSidebar, #hbSidebar *{animation:none !important;transition:none !important}
  .hb-item{opacity:1 !important;transform:none !important}
  html.hb-sb-ready body,
  html.hb-page-leaving body{animation:none !important}
}
@media print{
  #hbSidebar{display:none !important}
  /* 打印没有边栏，偏移与 fixed 修正要一并归零 */
  html.hb-sb-ready{margin-left:0 !important; --hb-shift:0px !important}
  html.hb-sb-ready body,
  html.hb-page-leaving body{animation:none !important}
}
