/* ==========================================================================
   梦宝桌宠（标记: 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: 161px;                         /* 角色本体可见高度 */
  --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; }
#mbPet[data-size="s"] { --pet-h: 121px; }
#mbPet[data-size="m"] { --pet-h: 161px; }
#mbPet[data-size="l"] { --pet-h: 203px; }

/* 点击热区＝整只（透明区也算，桌宠本来就是"点身上"）。
   焦点环：站内全局给 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; }
.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 反馈：点「换个姿势」还能看到几帧旧的躺着姿势）。
   视频首帧与逐帧图姿态一致，硬切看不出接缝。 */
/* is-vidclip-on：视频先显示（底图还盖在下面，两者同姿态）；is-vidclip：再收底图。
   分两步是为了不出现"底图没了、视频还没上屏"的空白帧。 */
#mbPet.is-vidclip .mbpet-imgwrap,
#mbPet.is-vidclip-on .mbpet-imgwrap { transition: transform .16s ease-out; }
#mbPet.is-vidclip .mbpet-walkvid.is-cur,
#mbPet.is-vidclip-on .mbpet-walkvid.is-cur { opacity: 1; transition: none; }
#mbPet.is-vidclip .mbpet-imgwrap { opacity: 0; }
/* 走路首帧是侧身，比正面底图窄一圈：底图在视频下面 .2s 淡出，边缘不"啪"地缩一下（petClipSeamless20261024） */
#mbPet.is-vidfade.is-vidclip .mbpet-imgwrap { transition: opacity .2s linear, transform .16s ease-out; }

/* 躺平保持期间的呼吸（标记: 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; }

/* 反馈动作：都在 .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 圆角 / 轻阴影），夜间反色 */
.mbpet-menu {
  position: absolute;
  right: 0;
  bottom: calc(86.6% + 6px);
  min-width: 152px;
  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; }

/* 手机端：站在 Dock 上面（脚本算地面高度时也会加 Dock 高度），整体小一号。
   注意要连 [data-size] 一起覆盖——属性选择器 (0,2,0) 比 #mbPet (0,1,0) 权重高，
   只写 #mbPet 的话三档尺寸在手机上都不生效。 */
@media (max-width: 430px) {
  #mbPet[data-size="m"] { --pet-h: 113px; }
  #mbPet[data-size="s"] { --pet-h: 92px; }
  #mbPet[data-size="l"] { --pet-h: 136px; }
  .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 { 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; }
}
