/* ==========================================================================
   梦宝桌宠（标记: mbDesktopPet20261022 / 立体灵动 mbPetDepth20261022）
   参考 MerZlin/dsh-pet-indesktop 的桌面桌宠：站在屏幕底边、会自己溜达、拖起来会
   悬空 / 松手落地、点一下有反应、右键出菜单。这里是网页版实现（position:fixed 覆盖
   在页面上，不依赖任何库），形象用 /assets/pet/ 下同一角色的五视图。
   与旧「悬浮球」的关系：同一个入口、同一个显隐时机（梦宝收起且不在首页时出现），
   点它仍然打开梦宝；只是从"圆形头像按钮"变成"站在底边的桌宠"。

   尺寸口径（重要）：素材是"角色 + 四周留白"的 535×614 画布（角色本体 512 高，占
   83.4%），走路帧同比例（448 高）。所以 --pet-h 表示**角色本体的可见高度**，
   盒子高度 = 角色高 × 1.199、宽度 = 角色高 × 1.045（＝画布比例，六视图切朝向时不跳）。
   ========================================================================== */

#mbPet {
  --pet-h-user: 161px;                    /* 大小滑轨的连续值（角色本体可见高），JS 内联写入（标记: petMenuRework20261025） */
  --pet-h: var(--pet-h-user);             /* 角色本体可见高度 */
  --pet-bh: calc(var(--pet-h) * 1.199);   /* 含留白的盒子高度 */
  --pet-w: calc(var(--pet-h) * 1.045);    /* 盒子宽度（=画布宽高比，六视图一致） */
  position: fixed;
  left: 0;
  top: 0;
  width: var(--pet-w);
  height: var(--pet-bh);
  z-index: 70;
  transform: translate3d(0, 0, 0);
  will-change: transform;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  contain: layout style;
}
#mbPet[hidden] { display: none !important; }

/* 点击热区＝整只（透明区也算，桌宠本来就是"点身上"）。
   焦点环：站内全局给 button 画的是蓝色 focus ring，套在桌宠上会变成四个蓝框，
   这里全部关掉（桌宠自身有 hover/active 反馈），键盘 Tab 进来时才用一条红色淡框。 */
.mbpet-body {
  position: absolute;
  inset: 0;
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: grab;
  outline: none !important;
  box-shadow: none;
  -webkit-appearance: none;
  appearance: none;
}
.mbpet-body:focus,
.mbpet-body:focus-visible { outline: none !important; box-shadow: none; }
.mbpet-body:active { cursor: grabbing; }
/* 交接动效（petCardMorph20261025）：以脚底中心为缩放原点，「长出来/化开」不会飘 */
.mbpet-body { transform-origin: 50% 88%; }
.mbpet-body:focus-visible::after {
  content: '';
  position: absolute;
  left: 12%;
  right: 12%;
  bottom: 2%;
  top: 6%;
  border: 2px solid rgba(230, 25, 35, .38);
  border-radius: 22px;
  pointer-events: none;
}

/* 站姿容器：负责"落地压扁 / 拖拽倾斜"这类整体形变，呼吸与走路交给里面的 img。
   高度 100%：素材自带的底部留白（约 3.3%）就是脚和地面之间的缝隙，不再另留 7px。 */
.mbpet-imgwrap {
  position: absolute;
  left: 50%;
  bottom: 0;
  height: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  transform: translateX(-50%);
  transform-origin: 50% 100%;
  transition: transform .16s ease-out;
  pointer-events: none;
}
.mbpet-img {
  height: 100%;
  width: auto;
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  transform-origin: 50% 100%;
  backface-visibility: hidden;
  /* 体积感的第一层：贴纸式投影（离地/被拖起时由脚本改写内联值） */
  filter: drop-shadow(0 2px 1px rgba(17, 24, 39, .13));
  animation: mbpet-idle 4.2s ease-in-out infinite;
  transition: filter .18s ease-out;
}
/* 悬浮状态的基础律动：整体慢慢上下浮（±2.5px）+ 极轻的厚度摆动。
   桌宠是"飘"着的，所以这不是呼吸而是浮力；幅度必须小，否则像在蹦。 */
@keyframes mbpet-idle {
  0%, 100% { transform: scaleY(1) translateY(0) rotateY(0deg); }
  35%      { transform: scaleY(1.004) translateY(-2.4px) rotateY(-1.1deg); }
  70%      { transform: scaleY(.998) translateY(1.2px) rotateY(.7deg); }
}

/* 走路：素材是 8 帧"腿在迈"的序列（脚本按 90ms 换帧），这里再叠一层
   两个踏步一循环的上下颠 + 左右甩肩（rotateY = 真 3D 摆动，比 rotate 更像有厚度）。 */
#mbPet.is-walking .mbpet-img { animation: mbpet-walk .36s ease-in-out infinite; }
#mbPet.is-walking .mbpet-imgwrap { transition: none; }
@keyframes mbpet-walk {
  0%   { transform: translateY(0) rotateY(0deg) scaleY(1); }
  25%  { transform: translateY(-3px) rotateY(4.5deg) scaleY(1.012); }
  50%  { transform: translateY(0) rotateY(0deg) scaleY(1); }
  75%  { transform: translateY(-3px) rotateY(-4.5deg) scaleY(1.012); }
  100% { transform: translateY(0) rotateY(0deg) scaleY(1); }
}

/* 动作视频层（标记: petWalkVideo20261023 / petClipVideo20261023）
   用户 2026-10-23 给的实拍素材（.mov 已抠好 alpha）→ VP9 alpha webm，做动作时叠在
   逐帧图上方整只替换；站定回逐帧图。
   几何口径统一：视频里的角色本体现高 = --pet-h（站姿素材的角色本体 = 盒子高 × 83.4%
   = --pet-h，见 mb-pet.js 的 FEET_INSET），每个片段的具体比例由脚本按片段写在
   --vid-h / --vid-b / --vid-x 上（CLIPS 表里 h/foot/dx 三项），这里只留兜底值。
   没加 .is-vidclip（浏览器不支持 / 素材坏了 / 自动播放被拦）时这一层完全不显示。 */
.mbpet-walkvid {
  position: absolute;
  left: 50%;
  bottom: var(--vid-b, calc(var(--pet-h) * 0.0098));
  height: var(--vid-h, calc(var(--pet-h) * 1.0450));
  margin-left: var(--vid-x, 0px);
  width: auto;
  max-width: none;
  transform: translateX(-50%);
  opacity: 0;
  pointer-events: none;
  backface-visibility: hidden;
  /* 与 .mbpet-img 同款贴纸投影：否则交接那一帧轮廓边缘差一圈阴影，肉眼像"闪一下"；
     退场不做透明度渐变（硬切），避免视频与底图叠两层 ~7 帧（petClipEdgeFrames20261024） */
  filter: drop-shadow(0 2px 1px rgba(17, 24, 39, .13));
  transition: none;
  z-index: 0;            /* 视频在最底层：星芒(1)/气泡(2)/菜单(3) 都要能压在它上面 */
}
/* 视频接管/交还都用"硬切"，不做透明度渐变：渐变那 100~120ms 里静态姿态图会从
   视频的透明区域透出来（用户 2026-10-23 反馈：点「换个姿势」还能看到几帧旧的躺着姿势）。
   视频首帧与逐帧图姿态一致，硬切看不出接缝。 */
/* 丝滑接棒（标记: petClipSilk20261025，取代 petClipHardCut20261025 的硬切）：
   is-vidclip-on：视频（钉在首帧、与底图对齐）在底图上方 .14s 淡入，底图保持不透明垫底；
   is-vidclip：淡入完成后才收底图、视频开播。自然播完时 is-vidout 让视频在底图上方 .14s 淡出。
   重影的根因是"错位叠加"（视频在播/底图在晃），对齐的静帧叠加看不出；只淡上层不淡下层，不会透底。 */
#mbPet.is-vidclip .mbpet-imgwrap,
#mbPet.is-vidclip-on .mbpet-imgwrap { transition: transform .16s ease-out; }
#mbPet.is-vidclip-on .mbpet-walkvid.is-cur { opacity: 1; }
#mbPet.is-vidclip-on:not(.is-vidclip) .mbpet-walkvid.is-cur,
#mbPet.is-vidout .mbpet-walkvid.is-cur { transition: opacity .14s linear; }
/* 淡入期间底图律动定格：carryPose 已把此刻偏移复制到视频，两层保持重合 */
#mbPet.is-vidclip-on .mbpet-img { animation-play-state: paused; }
#mbPet.is-vidclip .mbpet-imgwrap { opacity: 0; transition: none; }
#mbPet.is-vidclip .mbpet-img { animation: none; }

/* 躺平保持期间的呼吸（标记: petLieBreath20261023）
   躺下动作播完后视频停在末帧（keepPose），那一帧是完全静止的、像贴了张图；
   脚本在这时给 #mbPet 加 .is-liehold，这里让它有和站立（mbpet-idle）同节奏的起伏：
   · 缩放中心取"躺着的身体"在视频帧里的中心（≈52% / 68%），否则会围着画框中心转、
     脚和头往两头跑；
   · 幅度：横向 0.4% / 纵向 1.2%（站立是 0.4%），纵向略大才对得上"胸腔起伏"的观感；
   · 4.6s 一轮、ease-in-out，和站立 4.2s 的呼吸节奏接近，切换姿态时不会忽然变速。
   translateX(-50%) 是视频层定位用的，每个关键帧都必须带着，否则整只往右跳半个身位。 */
#mbPet.is-liehold .mbpet-walkvid.is-cur {
  transform-origin: 52% 68%;
  animation: mbpet-liebreath 4.6s ease-in-out infinite;
}
@keyframes mbpet-liebreath {
  0%, 100% { transform: translateX(-50%) translateY(0) scale(1, 1); }
  42%      { transform: translateX(-50%) translateY(-1.4px) scale(1.006, 1.009); }
  68%      { transform: translateX(-50%) translateY(0.5px) scale(1.004, 1.005); }
}

/* 被拎着 / 掉下来：手脚乱蹬（脚本快速换走路帧＝在空中扑腾）+ 全身发抖 + 汗珠。
   参考真桌宠的"悬空挣扎"，比单纯倾斜有戏。 */
#mbPet.is-dragging .mbpet-img,
#mbPet.is-falling .mbpet-img { animation: mbpet-dangle 1.1s ease-in-out infinite; }
#mbPet.is-falling .mbpet-img { animation: mbpet-panic .16s steps(2, end) infinite; }
@keyframes mbpet-dangle {
  0%, 100% { transform: rotateY(-3deg) scale(.99); }
  50% { transform: rotateY(3deg) scale(.99); }
}
@keyframes mbpet-panic {
  0% { transform: rotate(-2.6deg) translateX(-1.5px) scale(1.01); }
  50% { transform: rotate(2.6deg) translateX(1.5px) scale(1.01); }
  100% { transform: rotate(-2.6deg) translateX(-1.5px) scale(1.01); }
}
#mbPet .mbpet-sweat { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .12s; }
#mbPet.is-dragging .mbpet-sweat,
#mbPet.is-falling .mbpet-sweat { opacity: 1; }
.mbpet-sweat i {
  position: absolute;
  width: 7px;
  height: 10px;
  border-radius: 60% 60% 55% 55% / 70% 70% 40% 40%;
  background: linear-gradient(180deg, #dff1ff 0%, #9ed0f5 55%, #6fb5e8 100%);
  box-shadow: 0 0 0 1px rgba(58, 120, 170, .25);
  opacity: 0;
  transform: scale(.6);
}
#mbPet.is-falling .mbpet-sweat i,
#mbPet.is-dragging .mbpet-sweat i { animation: mbpet-sweat 1.05s ease-out infinite; }
.mbpet-sweat i:nth-child(1) { left: 8%; top: 22%; animation-delay: 0s; }
.mbpet-sweat i:nth-child(2) { right: 6%; top: 30%; animation-delay: .34s; }
.mbpet-sweat i:nth-child(3) { left: 26%; top: 12%; animation-delay: .68s; }
@keyframes mbpet-sweat {
  0% { opacity: 0; transform: translate(0, 0) scale(.5) rotate(0deg); }
  25% { opacity: .95; }
  100% { opacity: 0; transform: translate(-13px, -26px) scale(1) rotate(-14deg); }
}
/* 左/右侧身时汗珠别糊在脸上 */
#mbPet[data-facing="left"] .mbpet-sweat i:nth-child(1) { left: 52%; }
#mbPet[data-facing="left"] .mbpet-sweat i:nth-child(2) { right: 4%; top: 26%; }
#mbPet[data-facing="right"] .mbpet-sweat i:nth-child(1) { left: 4%; }
#mbPet[data-facing="right"] .mbpet-sweat i:nth-child(3) { left: 48%; }

/* 落地压扁 + 尘土（闷响一下就有了重量） */
#mbPet.is-land .mbpet-imgwrap { animation: mbpet-land .26s cubic-bezier(.2, .7, .3, 1); }
@keyframes mbpet-land {
  0% { transform: translateX(-50%) scale(1.09, .86); }
  48% { transform: translateX(-50%) scale(.97, 1.05); }
  72% { transform: translateX(-50%) scale(1.02, .98); }
  100% { transform: translateX(-50%) scale(1, 1); }
}
#mbPet .mbpet-dust { position: absolute; left: 50%; bottom: 2px; width: 0; height: 0; pointer-events: none; }
.mbpet-dust i {
  position: absolute;
  left: -5px;
  bottom: 0;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, rgba(146, 152, 166, .55), rgba(146, 152, 166, .12) 70%);
  opacity: 0;
  transform: translate(0, 0) scale(.4);
}
#mbPet.is-land .mbpet-dust i { animation: mbpet-dust .42s ease-out; }
.mbpet-dust i:nth-child(1) { animation-delay: 0s; }
.mbpet-dust i:nth-child(2) { animation-delay: .04s; }
.mbpet-dust i:nth-child(3) { animation-delay: .02s; }
.mbpet-dust i:nth-child(4) { animation-delay: .06s; }
@keyframes mbpet-dust {
  0% { opacity: .85; transform: translate(0, 0) scale(.5); }
  100% { opacity: 0; transform: translate(var(--dx, -18px), -3px) scale(2.1); }
}
.mbpet-dust i:nth-child(1) { --dx: -22px; }
.mbpet-dust i:nth-child(2) { --dx: 22px; }
.mbpet-dust i:nth-child(3) { --dx: -11px; }
.mbpet-dust i:nth-child(4) { --dx: 12px; }

/* 跳一下（点击 / 逗它） */
#mbPet.is-hop .mbpet-img { animation: mbpet-hop .5s cubic-bezier(.25, .8, .3, 1); }
@keyframes mbpet-hop {
  0% { transform: translateY(0) scale(1, 1); }
  16% { transform: translateY(0) scale(1.07, .91); }
  48% { transform: translateY(-24px) scale(.97, 1.04) rotateY(6deg); }
  78% { transform: translateY(0) scale(1.06, .93) rotateY(-3deg); }
  100% { transform: translateY(0) scale(1, 1) rotateY(0deg); }
}

/* 伸个懒腰 */
#mbPet.is-stretch .mbpet-img { animation: mbpet-stretch .78s ease-in-out; }
@keyframes mbpet-stretch {
  0%, 100% { transform: scale(1, 1); }
  40% { transform: scale(.96, 1.06) translateY(-3px) rotateY(-2deg); }
  70% { transform: scale(1.01, .99) rotateY(2deg); }
}

/* 点头：下巴下去 → 回弹 → 再点一下，带一点压缩，比纯转图有重量 */
#mbPet.is-nod .mbpet-img { animation: mbpet-nod 1.1s cubic-bezier(.3, .7, .3, 1); }
@keyframes mbpet-nod {
  0%, 100% { transform: translateY(0) scale(1, 1) rotate(0deg); }
  14% { transform: translateY(3px) scale(1.02, .96) rotate(1.4deg); }
  30% { transform: translateY(-1px) scale(.99, 1.01) rotate(-.6deg); }
  46% { transform: translateY(3px) scale(1.02, .96) rotate(1.2deg); }
  62% { transform: translateY(-1px) scale(1, 1) rotate(-.4deg); }
  80% { transform: translateY(1px) scale(1.01, .99) rotate(.5deg); }
}

/* 转身：半蹲蓄力 → 跳起来在空中转一整圈（rotateY = 真 3D，转到 180° 脚本换背面帧）
   → 落地压一下回弹。转身时把背面朝向放开（默认 hidden 会在 90°~270° 把图藏掉）。 */
#mbPet.is-spin .mbpet-img {
  animation: mbpet-spin 1.08s cubic-bezier(.33, .06, .2, .98);
  backface-visibility: visible;
}
#mbPet.is-spin .mbpet-imgwrap .mbpet-face { opacity: 0; }
@keyframes mbpet-spin {
  0%   { transform: translateY(0)     scale(1, 1)       rotateY(0deg); }
  13%  { transform: translateY(4px)   scale(1.10, .80)  rotateY(0deg); }   /* 半蹲蓄力 */
  20%  { transform: translateY(5px)   scale(1.12, .78)  rotateY(0deg); }   /* 压到最低 */
  27%  { transform: translateY(-12px) scale(.94, 1.10)  rotateY(12deg); }  /* 弹起拉伸 */
  40%  { transform: translateY(-34px) scale(1, 1)       rotateY(120deg); }
  54%  { transform: translateY(-40px) scale(1, 1)       rotateY(180deg); }
  68%  { transform: translateY(-30px) scale(1, 1)       rotateY(300deg); }
  77%  { transform: translateY(0)     scale(1.09, .84)  rotateY(360deg); } /* 落地压 */
  87%  { transform: translateY(-2px)  scale(.97, 1.04)  rotateY(360deg); }
  100% { transform: translateY(0)     scale(1, 1)       rotateY(360deg); }
}

/* 转身特效：一圈扩散光环（b）+ 8 条向外飞的星芒（i），只在 is-spin 期间跑 */
.mbpet-fx {
  position: absolute;
  left: 50%;
  bottom: 44%;
  width: 0;
  height: 0;
  pointer-events: none;
  z-index: 1;            /* 抬到视频层(0)之上，转身时星芒才看得见 */
}
.mbpet-fx b {
  position: absolute;
  left: 0;
  top: 0;
  width: 62px;
  height: 62px;
  margin: -31px 0 0 -31px;
  border-radius: 50%;
  border: 2px solid rgba(96, 165, 250, .8);
  box-shadow: 0 0 16px rgba(99, 155, 245, .55), inset 0 0 12px rgba(147, 197, 253, .45);
  opacity: 0;
}
.mbpet-fx i {
  position: absolute;
  left: -1.5px;
  top: -10px;
  width: 4px;
  height: 15px;
  border-radius: 4px;
  background: linear-gradient(180deg, #fff, #fbbf24);
  box-shadow: 0 0 7px rgba(251, 191, 36, .75);
  opacity: 0;
  transform-origin: 50% 100%;
}
.mbpet-fx i:nth-child(2) { --a: 0deg;   --r: 62px; --d: 0s; }
.mbpet-fx i:nth-child(3) { --a: 45deg;  --r: 70px; --d: .02s; }
.mbpet-fx i:nth-child(4) { --a: 90deg;  --r: 58px; --d: .05s; }
.mbpet-fx i:nth-child(5) { --a: 135deg; --r: 74px; --d: .01s; }
.mbpet-fx i:nth-child(6) { --a: 180deg; --r: 62px; --d: .04s; }
.mbpet-fx i:nth-child(7) { --a: 225deg; --r: 70px; --d: 0s; }
.mbpet-fx i:nth-child(8) { --a: 270deg; --r: 58px; --d: .03s; }
.mbpet-fx i:nth-child(9) { --a: 315deg; --r: 74px; --d: .02s; }
#mbPet.is-spin .mbpet-fx b { animation: mbpet-ring .9s ease-out both; }
#mbPet.is-spin .mbpet-fx i { animation: mbpet-spark .8s ease-out both; animation-delay: var(--d); }
@keyframes mbpet-ring {
  0%   { opacity: 0; transform: scale(.3); }
  22%  { opacity: .95; }
  100% { opacity: 0; transform: scale(1.9); }
}
@keyframes mbpet-spark {
  0%   { opacity: 0; transform: rotate(var(--a)) translateY(-10px) scale(.5); }
  22%  { opacity: 1; }
  100% { opacity: 0; transform: rotate(var(--a)) translateY(calc(-1 * var(--r))) scale(.35); }
}

/* 地面投影：两层——外面那层是"环境暗角"（很淡、很宽，给角色一个落脚的地面），
   里面那层是接地椭圆。离地越高越小越淡（拖起来时由脚本写内联值）。 */
.mbpet-shadow {
  position: absolute;
  left: 50%;
  bottom: 1px;
  width: 74%;
  height: 11px;
  margin-left: -37%;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(16, 24, 40, .32) 0%, rgba(16, 24, 40, .17) 46%, rgba(16, 24, 40, 0) 74%);
  transform: scale(1, 1);
  transform-origin: 50% 50%;
  transition: transform .12s linear, opacity .12s linear;
  pointer-events: none;
}
/* 深色底上深色影子看不见：再垫一层极淡白光当"地面反光"。
   白底上白光≈看不见，正好两边都不出错。 */
.mbpet-shadow::after {
  content: '';
  position: absolute;
  left: -18%;
  right: -18%;
  top: -70%;
  bottom: -40%;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(255, 255, 255, .16) 0%, rgba(255, 255, 255, .07) 42%, rgba(255, 255, 255, 0) 72%);
  pointer-events: none;
}
.mbpet-shadow::before {
  content: '';
  position: absolute;
  left: -34%;
  right: -34%;
  top: -260%;
  bottom: -180%;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(16, 24, 40, .10) 0%, rgba(16, 24, 40, .04) 45%, rgba(16, 24, 40, 0) 72%);
}
body.night-mode .mbpet-shadow {
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, .58) 0%, rgba(0, 0, 0, .3) 46%, rgba(0, 0, 0, 0) 74%);
}
body.night-mode /* 深色底上深色影子看不见：再垫一层极淡白光当"地面反光"。
   白底上白光≈看不见，正好两边都不出错。 */
.mbpet-shadow::after {
  content: '';
  position: absolute;
  left: -18%;
  right: -18%;
  top: -70%;
  bottom: -40%;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(255, 255, 255, .16) 0%, rgba(255, 255, 255, .07) 42%, rgba(255, 255, 255, 0) 72%);
  pointer-events: none;
}
.mbpet-shadow::before {
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, .22) 0%, rgba(0, 0, 0, .08) 45%, rgba(0, 0, 0, 0) 72%);
}

/* 气泡：桌宠自己冒的短句 / 点开梦宝时的"来啦" */
.mbpet-bubble {
  position: absolute;
  left: 50%;
  bottom: calc(86.6% - 2px);
  /* width:max-content 才能突破盒子的窄宽度（绝对定位的收缩宽度会被包含块卡住，
     否则「我在这儿～」会被折成两行）；长句再由 max-width 折行。 */
  width: max-content;
  max-width: 208px;
  box-sizing: border-box;
  padding: 7px 11px;
  border: 1px solid #e4e6ea;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 8px 22px rgba(16, 24, 40, .13);
  color: #2a2d33;
  font-size: 12.5px;
  line-height: 1.5;
  text-align: center;
  white-space: normal;
  word-break: break-word;
  opacity: 0;
  transform: translate(-50%, 5px) scale(.96);
  transform-origin: 50% 100%;
  transition: opacity .16s ease, transform .16s ease;
  pointer-events: none;
  z-index: 2;
}
.mbpet-bubble::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -5px;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  background: inherit;
  border-right: 1px solid #e4e6ea;
  border-bottom: 1px solid #e4e6ea;
  transform: rotate(45deg);
}
.mbpet-bubble.is-on { opacity: 1; transform: translate(-50%, 0) scale(1); }
body.night-mode .mbpet-bubble {
  background: #24262c;
  border-color: #35373f;
  color: #e9eaee;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .5);
}
body.night-mode .mbpet-bubble[data-tone]::before { filter: brightness(1.08) saturate(1.05); }
body.night-mode .mbpet-bubble::after { border-color: #35373f; }

/* ==========================================================================
   任务提示（标记: petHerald20261023）
   桌宠当"状态指示灯"：气泡按语气换左边一条色带（不改字号、不重排），
   再配一个 1.5 秒的极轻反馈动作。全部用 transform / opacity，不碰布局。
   ========================================================================== */
.mbpet-bubble[data-tone] { padding-left: 14px; }
.mbpet-bubble[data-tone]::before {
  content: '';
  position: absolute;
  left: 5px;
  top: 7px;
  bottom: 7px;
  width: 3px;
  border-radius: 2px;
  background: #9aa3af;
}
.mbpet-bubble[data-tone="queued"]::before { background: #94a3b8; }
.mbpet-bubble[data-tone="running"]::before { background: #4f8ef7; }
.mbpet-bubble[data-tone="done"]::before { background: #22a06b; }
.mbpet-bubble[data-tone="failed"]::before { background: #e0524d; }

/* 播报可应答（标记: petBubbleAction20261026）：完成/失败气泡句尾的「去看看」小按钮。
   气泡本体 pointer-events:none（点文字要穿到桌宠身上），按钮单独放开可点；
   有按钮时气泡改纵向排（文字一行、按钮一行），不然按钮混进折行里很难看。 */
.mbpet-bubble.has-act {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding-top: 8px;
  padding-bottom: 9px;
}
.mbpet-bubble-act {
  appearance: none;
  pointer-events: auto;
  flex: 0 0 auto;
  border: 0;
  border-radius: 999px;
  padding: 3px 12px 4px;
  background: #d92b2b;
  color: #fff;
  font: inherit;
  font-size: 11.5px;
  line-height: 1.4;
  letter-spacing: .04em;
  cursor: pointer;
  transition: filter .15s ease, transform .12s ease;
}
.mbpet-bubble-act:hover { filter: brightness(1.1); }
.mbpet-bubble-act:active { transform: scale(.95); }
.mbpet-bubble-act:focus-visible { outline: 2px solid #f3a5a2; outline-offset: 1px; }
body.night-mode .mbpet-bubble-act { background: #e2504b; }

/* 反馈动作：都在 .mbpet-img 上「叠加」跑一次，不改它已有的 idle 呼吸
   （idle 是 infinite，用 animation-name 覆盖之后结束就回到 idle）。 */
#mbPet.is-herald-queued .mbpet-img { animation: mbpet-herald-nudge .5s ease-out; }
#mbPet.is-herald-running .mbpet-img { animation: mbpet-herald-bob 1.4s ease-in-out; }
#mbPet.is-herald-done .mbpet-img { animation: mbpet-herald-cheer .9s cubic-bezier(.2,.8,.3,1); }
#mbPet.is-herald-failed .mbpet-img { animation: mbpet-herald-shake .5s ease-in-out; }

@keyframes mbpet-herald-nudge {
  0% { transform: translateY(0); }
  35% { transform: translateY(-4px); }
  100% { transform: translateY(0); }
}
@keyframes mbpet-herald-bob {
  0%, 100% { transform: translateY(0); }
  25% { transform: translateY(-3px); }
  60% { transform: translateY(1px); }
}
@keyframes mbpet-herald-cheer {
  0% { transform: translateY(0) scale(1); }
  30% { transform: translateY(-9px) scale(1.02, .98); }
  60% { transform: translateY(-2px) scale(.99, 1.01); }
  100% { transform: translateY(0) scale(1); }
}
@keyframes mbpet-herald-shake {
  0%, 100% { transform: translateX(0) rotate(0); }
  20% { transform: translateX(-3px) rotate(-1.2deg); }
  45% { transform: translateX(3px) rotate(1.2deg); }
  70% { transform: translateX(-2px) rotate(-.6deg); }
}

/* 右键菜单：与站内菜单同一套表面（白卡 / 1px 描边 / 12px 圆角 / 轻阴影），夜间反色。
   不再固定在桌宠头顶（标记: petMenuRework20261025）：JS 在打开时按视口空间把菜单
   贴到桌宠左手边或右手边（默认右手边、顶边对齐桌宠头部），这里只给一个中性起点。 */
.mbpet-menu {
  position: absolute;
  left: 0;
  top: 0;
  min-width: 190px;
  padding: 6px;
  border: 1px solid #e6e8ec;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 16px 38px rgba(16, 24, 40, .2);
  z-index: 3;
  animation: mbpet-menu-in .13s ease-out;
}
.mbpet-menu[hidden] { display: none !important; }
/* 2026-10-24 用户要求删掉菜单底部那行构建号小字（调试信息，占位又像乱码）；
   要查当前版本用控制台 MbPet.version，脚本文件仍用 ?v=构建号 防缓存。 */
@keyframes mbpet-menu-in {
  from { opacity: 0; transform: translateY(4px) scale(.98); }
  to { opacity: 1; transform: none; }
}
.mbpet-menu button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 32px;
  padding: 0 10px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: #33363c;
  font-size: 12.5px;
  line-height: 1;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.mbpet-menu button:hover,
.mbpet-menu button:focus-visible { background: #f3f4f6; outline: none; }
.mbpet-menu .mbpet-menu-key { margin-left: auto; color: #9aa0aa; font-size: 11px; }
.mbpet-menu .mbpet-sep { height: 1px; margin: 5px 6px; background: #eef0f3; }
body.night-mode .mbpet-menu {
  background: #24262c;
  border-color: #35373f;
  box-shadow: 0 16px 38px rgba(0, 0, 0, .55);
}
body.night-mode .mbpet-menu button { color: #e6e7eb; }
body.night-mode .mbpet-menu button:hover,
body.night-mode .mbpet-menu button:focus-visible { background: #2f323a; }
body.night-mode .mbpet-menu .mbpet-sep { background: #33353d; }

/* 动作二级菜单（标记: petMenuRework20261025）：悬浮/点按「动作」展开；
   默认朝右弹，菜单贴视口右缘时由 JS 加 .flip 翻到左边。 */
.mbpet-sub { position: relative; }
.mbpet-sub > button::after {
  content: '›';
  margin-left: auto;
  color: #9aa0aa;
  font-size: 14px;
  line-height: 1;
}
.mbpet-submenu {
  position: absolute;
  top: -6px;
  left: calc(100% + 6px);
  min-width: 112px;
  padding: 6px;
  border: 1px solid #e6e8ec;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 16px 38px rgba(16, 24, 40, .2);
  z-index: 4;
  animation: mbpet-menu-in .13s ease-out;
}
.mbpet-submenu[hidden] { display: none !important; }
.mbpet-submenu.flip { left: auto; right: calc(100% + 6px); }
/* 跨缝桥：一级行与二级菜单之间那 6px 空隙也能走过去不收起 */
.mbpet-submenu::before { content: ''; position: absolute; top: 0; bottom: 0; left: -8px; width: 8px; }
.mbpet-submenu.flip::before { left: auto; right: -8px; }

/* 大小滑轨（标记: petMenuRework20261025）：行内 label + range + 百分比，
   轨道已走过的部分用品牌红填充（--fill 由 JS 按 0~100% 写入）。 */
.mbpet-size-row {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 10px;
  color: #33363c;
  font-size: 12.5px;
  line-height: 1;
  white-space: nowrap;
}
.mbpet-size-row input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  flex: 1;
  min-width: 0;
  height: 16px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}
.mbpet-size-row input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, #e61923 0 var(--fill, 50%), #e8eaee var(--fill, 50%) 100%);
}
.mbpet-size-row input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  margin-top: -5px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #e61923;
  box-shadow: 0 1px 4px rgba(16, 24, 40, .25);
}
.mbpet-size-row input[type="range"]::-moz-range-track { height: 4px; border-radius: 2px; background: #e8eaee; }
.mbpet-size-row input[type="range"]::-moz-range-progress { height: 4px; border-radius: 2px; background: #e61923; }
.mbpet-size-row input[type="range"]::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #e61923;
  box-shadow: 0 1px 4px rgba(16, 24, 40, .25);
}
.mbpet-size-val { min-width: 34px; text-align: right; color: #9aa0aa; font-size: 11px; }
body.night-mode .mbpet-submenu {
  background: #24262c;
  border-color: #35373f;
  box-shadow: 0 16px 38px rgba(0, 0, 0, .55);
}
body.night-mode .mbpet-sub > button::after { color: #8b909b; }
body.night-mode .mbpet-size-row { color: #e6e7eb; }
body.night-mode .mbpet-size-row input[type="range"]::-webkit-slider-runnable-track {
  background: linear-gradient(90deg, #e61923 0 var(--fill, 50%), #3a3d46 var(--fill, 50%) 100%);
}
body.night-mode .mbpet-size-row input[type="range"]::-moz-range-track { background: #3a3d46; }

/* 手机端：站在 Dock 上面（脚本算地面高度时也会加 Dock 高度），整体小一号。
   大小改为滑轨连续值（--pet-h-user 内联写入），手机端整体乘 0.7 缩一档
   （旧三档 121/161/203 在手机上是 92/113/136，比值≈0.7）。 */
@media (max-width: 430px) {
  #mbPet { --pet-h: calc(var(--pet-h-user) * 0.7); }
  .mbpet-bubble { font-size: 12px; max-width: 168px; }
}

/* 系统开了"减少动态"：不呼吸、不颠、不跳、不抖，位置变化直接落位 */
@media (prefers-reduced-motion: reduce) {
  #mbPet .mbpet-img { animation: none !important; }
  #mbPet.is-walking .mbpet-img,
  #mbPet.is-dragging .mbpet-img,
  #mbPet.is-falling .mbpet-img,
  #mbPet.is-hop .mbpet-img,
  #mbPet.is-nod .mbpet-img,
  #mbPet.is-spin .mbpet-img,
  #mbPet.is-stretch .mbpet-img { animation: none !important; }
  #mbPet.is-land .mbpet-imgwrap { animation: none !important; }
  #mbPet.is-liehold .mbpet-walkvid.is-cur { animation: none !important; }
  .mbpet-sweat i, .mbpet-dust i, .mbpet-fx b, .mbpet-fx i { animation: none !important; opacity: 0 !important; }
  .mbpet-bubble, .mbpet-menu, .mbpet-submenu { transition: none !important; animation: none !important; }
  /* 任务提示：动作全关，但气泡左侧那条语气色带保留（那是信息，不是动效） */
  #mbPet.is-herald-queued .mbpet-img,
  #mbPet.is-herald-running .mbpet-img,
  #mbPet.is-herald-done .mbpet-img,
  #mbPet.is-herald-failed .mbpet-img { animation: none !important; }
}


/* ==========================================================================
   悬浮三姿态 + 注视跟随（标记: petHoverPoses20261022）
   ========================================================================== */

/* 姿态切换的淡入层：新姿态先盖在上面淡进来（240ms），再换底图，切换不"啪"地跳 */
#mbPet .mbpet-img-alt {
  position: absolute;
  left: 50%;
  bottom: 0;
  height: 100%;
  width: auto;
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity .22s ease-out;
  pointer-events: none;
  z-index: 1;
}
#mbPet .mbpet-img-alt.is-on { opacity: 1; }

/* DOM 眼睛：位置由脚本按姿态写 left/top（归一化坐标），位移由 --ex/--ey 驱动。
   尺寸按角色可见高度算：原画 1024 高时眼珠约 38×95px ⇒ 0.037 / 0.093。 */
#mbPet .mbpet-face {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity .18s ease-out;
}
#mbPet[data-eyes="on"] .mbpet-face { opacity: 1; }
#mbPet .mbpet-eye {
  position: absolute;
  width: calc(var(--pet-h) * 0.0415);   /* 按 3D 静帧的眼睛实测（原 0.0371）标记: petStaticRender20261023 */
  height: calc(var(--pet-h) * 0.1014);  /* 同上（原 0.0928） */
  border-radius: 50%;
  background: radial-gradient(ellipse at 38% 28%, #4d525a 0%, #2a2e34 46%, #14171b 100%);
  box-shadow: 0 0 0 calc(var(--pet-h) * 0.0045) rgba(12, 14, 18, .82);
  transform: translate(-50%, -50%) translate(var(--ex, 0px), var(--ey, 0px));
  will-change: transform;
}

/* 注视时不要在 60fps 写 transform 的同时还挂 transition（会拖出拖影） */
#mbPet.is-looking .mbpet-imgwrap { transition: none; }

/* 减少动态：姿态淡入、悬浮律动、眼睛位移全部关掉（位置照常） */
@media (prefers-reduced-motion: reduce) {
  #mbPet .mbpet-img-alt { transition: none !important; }
  #mbPet .mbpet-eye { transform: translate(-50%, -50%) !important; }
  #mbPet .mbpet-face { transition: none !important; }
}
