'use client';

import { useEffect, useRef } from 'react';
import type { PetPose } from './pet-brain';

/** 身体姿态 = 大脑表情(idle/think/celebrate/sleep) + 运动层姿态(walk/fall/sit=坐边沿/fly=超人飞/morph=超人变身) + 互动(happy=被摸 / brush=刷牙刷字 / rinse=漱口吐泡泡)。 */
export type PetBodyPose = PetPose | 'walk' | 'fall' | 'happy' | 'sit' | 'brush' | 'rinse' | 'fly' | 'morph' | 'climb' | 'magnify';

/**
 * 宠物身体 — Q 版磨牙(程序化 SVG,零资产)。
 *
 * 形象:白胖牙冠 + 双牙根成腿(走路天然摆腿),大眼 + 腮红。
 * 生命感:呼吸 / 随机眨眼 / 瞳孔 rAF 追鼠标;走路摆腿 + 颠步;摔落瞪圆眼;
 * 全部动画包在 prefers-reduced-motion: no-preference 内,无障碍自动降级为静态。
 * 整层可替换:将来换 Rive/Live2D 只动这个文件。
 */
export function PetBody({
  pose,
  glanceSeq,
  facing = 1,
  squashSeq = 0,
  shield = false,
  seated = false,
  size = 64,
}: {
  pose: PetBodyPose;
  glanceSeq: number;
  /** 朝向:1 右 / -1 左(走路时由运动层给)。注意:左右翻转由宿主(widget)在外层做,
   *  这里只用它换算瞳孔的"世界方向 → 脸坐标系"(根 svg 的 transform 留给跳/压扁动画)。 */
  facing?: 1 | -1;
  /** 落地信号(自增):每次 +1 播一遍压扁回弹 */
  squashSeq?: number;
  /** 涂氟护盾 buff(刷牙仪式完成后获得,与姿态正交) */
  shield?: boolean;
  /** 坐在边沿上(与姿态正交):无论说话/思考/被摸,腿都耷拉着晃 */
  seated?: boolean;
  size?: number;
}) {
  const rootRef = useRef<SVGSVGElement>(null);
  const pupilsRef = useRef<SVGGElement>(null);
  const target = useRef({ x: 0, y: 0 });
  const current = useRef({ x: 0, y: 0 });
  const glanceUntil = useRef(0);
  const poseRef = useRef<PetBodyPose>(pose);
  poseRef.current = pose;
  const facingRef = useRef(facing);
  facingRef.current = facing;

  // 张望信号:1s 内瞳孔看向随机方向(idle 防机械感)
  useEffect(() => {
    if (!glanceSeq) return;
    const a = Math.random() * Math.PI * 2;
    target.current = { x: Math.cos(a) * 2.4, y: Math.sin(a) * 1.8 };
    glanceUntil.current = Date.now() + 900;
  }, [glanceSeq]);

  // 落地信号:重触发压扁回弹动画(移除类→强制 reflow→加回,CSS 动画才会重播)
  useEffect(() => {
    if (!squashSeq) return;
    const el = rootRef.current;
    if (!el) return;
    el.classList.remove('pac-pet-squash');
    void el.getBoundingClientRect();
    el.classList.add('pac-pet-squash');
  }, [squashSeq]);

  useEffect(() => {
    const onMove = (e: PointerEvent) => {
      if (Date.now() < glanceUntil.current) return;
      const el = rootRef.current;
      if (!el) return;
      const r = el.getBoundingClientRect();
      const dx = e.clientX - (r.left + r.width / 2);
      const dy = e.clientY - (r.top + r.height / 2);
      const dist = Math.hypot(dx, dy) || 1;
      const k = Math.min(dist / 90, 1);
      target.current = { x: (dx / dist) * 2.6 * k, y: (dy / dist) * 2.0 * k };
    };
    window.addEventListener('pointermove', onMove, { passive: true });

    let raf = 0;
    const loop = () => {
      raf = requestAnimationFrame(loop);
      const p = poseRef.current;
      // 思考望右上;走路看前方;摔落看下;睡觉回中
      const t =
        p === 'think'
          ? { x: 1.6, y: -2.2 }
          : p === 'walk'
            ? { x: 2.2 * facingRef.current, y: 0.4 }
            : p === 'fall'
              ? { x: 0, y: 2.2 }
              : p === 'brush'
                ? { x: 0, y: 2.4 } // 专注看着脚下刷的地方
                : p === 'floss'
                  ? { x: 0, y: -2.4 } // 仰头看头顶的牙线
                  : p === 'fly'
                    ? { x: 2.8 * facingRef.current, y: 0 } // 超人:目光锁定前方
                    : p === 'morph'
                      ? { x: 0, y: -1.8 } // 变身:目光上扬蓄力
                      : p.startsWith('vet_')
                        ? { x: 1.2 * facingRef.current, y: 2.3 } // 牙医:专注盯着手里的活
                        : p === 'magnify'
                          ? { x: 3 * facingRef.current, y: 0.6 } // 放大镜:盯着面前的文字
                          : p === 'sleep'
                      ? { x: 0, y: 0 }
                      : target.current;
      // 身体可能被 scaleX(-1) 翻转:瞳孔目标在"脸坐标系"里要再翻一次,保持看的还是世界方向
      const fx = t.x * facingRef.current;
      current.current.x += (fx - current.current.x) * 0.12;
      current.current.y += (t.y - current.current.y) * 0.12;
      pupilsRef.current?.setAttribute(
        'transform',
        `translate(${current.current.x.toFixed(2)} ${current.current.y.toFixed(2)})`,
      );
    };
    raf = requestAnimationFrame(loop);
    return () => {
      window.removeEventListener('pointermove', onMove);
      cancelAnimationFrame(raf);
    };
  }, []);

  const sleeping = pose === 'sleep';
  const celebrating = pose === 'celebrate';
  const thinking = pose === 'think';
  const walking = pose === 'walk';
  const falling = pose === 'fall';
  const happy = pose === 'happy'; // 被摸:眯眼笑 + 腮红加深 + 冒爱心,不动
  const sitting = pose === 'sit'; // 坐在边沿:双腿前荡(脸部同 idle,瞳孔照常追鼠标)
  const brushing = pose === 'brush'; // 刷牙刷字:坐姿 + 牙刷快速刷洗
  const rinsing = pose === 'rinse'; // 漱口:鼓腮 + 吐泡泡
  const flossing = pose === 'floss'; // 牙线自理:头顶拉线锯冠缝
  const shining = pose === 'shine'; // 闪亮微笑:咧嘴 + 牙面 ding
  const chomping = pose === 'chomp'; // 咬合操:嘴快速张合
  const absorbing = pose === 'absorb'; // 吸入:一批患者被"吸"进来(移交人群时演)
  const flying = pose === 'fly'; // 超人:红披风直线飞
  const morphing = pose === 'morph'; // 超人变身:原地蓄力 + 披风展开 + 光环
  // 牙医组合:统一戴额镜,按步骤换手里的器械
  const vetExam = pose === 'vet_exam';
  const vetScale = pose === 'vet_scale';
  const vetFill = pose === 'vet_fill';
  const vetPolish = pose === 'vet_polish';
  const vetFluoride = pose === 'vet_fluoride';
  const vetMode = vetExam || vetScale || vetFill || vetPolish || vetFluoride;
  const climbing = pose === 'climb'; // 爬下楼:背朝外、悬挂垫脚(看不到脸)
  const magnifying = pose === 'magnify'; // 到达选区:举放大镜照
  const arcEyes = celebrating || happy || shining; // ^^ 眼共用

  return (
    <svg
      ref={rootRef}
      viewBox="0 0 64 64"
      width={size}
      height={size}
      className={[
        'pac-pet',
        celebrating ? 'pac-pet-jump' : '',
        falling ? 'pac-pet-falling' : '',
        happy ? 'pac-pet-wiggle' : '',
        flying ? 'pac-pet-flylean' : '',
        absorbing ? 'pac-pet-absorb' : '',
      ].join(' ')}
      aria-hidden
    >
      <style>{PET_CSS}</style>
      {/* 吸入:三个数字流从右侧被吸进嘴里(移交人群)。⚠️ keyframes 在 PET_CSS 里,
          不在 globals.css —— 宠物的 29 个动画都注入在这个 <style> 里 */}
      {absorbing && (
        <g className="pac-pet-absorb-flow" fill="#0d9488" fontSize="7" fontWeight="700">
          <text x="52" y="30">1</text>
          <text x="56" y="36">0</text>
          <text x="52" y="42">1</text>
        </g>
      )}
      {/* 超人红披风:画在身体之后(置于身后),朝后(facing 由外层翻转)飘动;变身时从领口展开 */}
      {(flying || morphing) && (
        <g className={morphing ? 'pac-pet-cape-unfurl' : 'pac-pet-cape'}>
          <path d="M22 14 C6 16 2 34 8 50 C14 44 18 46 22 50 L24 16 Z" fill="#dc2626" stroke="#b91c1c" strokeWidth="1" />
          <path d="M22 14 C12 18 10 34 13 48" stroke="#f87171" strokeWidth="1" fill="none" opacity="0.7" />
        </g>
      )}
      {/* 超人变身:身后展开的金色蓄力光环 + 火花(置于身体之后) */}
      {morphing && (
        <g>
          <circle className="pac-pet-ring" cx="32" cy="34" r="16" fill="none" stroke="#fbbf24" strokeWidth="2.5" />
          <circle className="pac-pet-ring" cx="32" cy="34" r="16" fill="none" stroke="#fde68a" strokeWidth="2" style={{ animationDelay: '0.35s' }} />
          <path className="pac-pet-spark" fill="#fbbf24" stroke="none" d="M8 20 l1 2.4 2.4 1 -2.4 1 -1 2.4 -1 -2.4 -2.4 -1 2.4 -1 Z" />
          <path className="pac-pet-spark" fill="#fbbf24" stroke="none" d="M55 24 l1 2.4 2.4 1 -2.4 1 -1 2.4 -1 -2.4 -2.4 -1 2.4 -1 Z" style={{ animationDelay: '0.3s' }} />
          <path className="pac-pet-spark" fill="#fde68a" stroke="none" d="M50 6 l0.8 2 2 0.8 -2 0.8 -0.8 2 -0.8 -2 -2 -0.8 2 -0.8 Z" style={{ animationDelay: '0.55s' }} />
        </g>
      )}
      {/* 爬下楼:背朝外、悬挂垫脚(看不到脸)—— 单独的背面身体 */}
      {climbing ? (
        <g className="pac-pet-climb">
          {/* 手臂上举抓住上方边沿(垫脚悬挂) */}
          <g stroke="#ffffff" strokeWidth="3" strokeLinecap="round" fill="none">
            <path className="pac-pet-climb-armL" d="M21 18 Q18 10 21 5" />
            <path className="pac-pet-climb-armR" d="M43 18 Q46 10 43 5" />
          </g>
          <circle cx="21" cy="4.5" r="2.4" fill="#ffffff" stroke="#e2e8f0" strokeWidth="0.8" />
          <circle cx="43" cy="4.5" r="2.4" fill="#ffffff" stroke="#e2e8f0" strokeWidth="0.8" />
          {/* 背面牙身(无脸)+ 中缝 */}
          <path
            d="M32 8 C22 8 15 13 15 24 C15 31 16.5 36 18.5 41 L45.5 41 C47.5 36 49 31 49 24 C49 13 42 8 32 8 Z"
            fill="#f1f5f9"
            stroke="#e2e8f0"
            strokeWidth="1.2"
          />
          <path d="M32 11 L32 40" stroke="#e2e8f0" strokeWidth="1.4" />
          <path d="M24 14 Q22 27 24 39 M40 14 Q42 27 40 39" stroke="#e2e8f0" strokeWidth="0.9" fill="none" opacity="0.7" />
          {/* 牙根小腿:向下垫脚(交替探脚) */}
          <g className="pac-pet-climb-legL">
            <path d="M20 40 C17 47 17 53 21 54 C24 54.5 25 49 24 44 L23 40 Z" fill="#f1f5f9" stroke="#e2e8f0" strokeWidth="1" />
          </g>
          <g className="pac-pet-climb-legR">
            <path d="M44 40 C47 47 47 53 43 54 C40 54.5 39 49 40 44 L41 40 Z" fill="#f1f5f9" stroke="#e2e8f0" strokeWidth="1" />
          </g>
        </g>
      ) : (
        <>
      {/* 身体组:呼吸(静止)/ 颠步(走路)/ 变身蓄力(原地上下颠+微胀) */}
      <g className={walking ? 'pac-pet-walkbob' : morphing ? 'pac-pet-morph' : 'pac-pet-breath'}>
        {/* 牙根小腿(走路交替摆 / 坐&刷&任意坐姿前荡;seated 让说话/思考时也耷拉着) */}
        <g className={walking ? 'pac-pet-leg-l' : sitting || brushing || seated ? 'pac-pet-dangle-l' : ''}>
          <path d="M19 38 C18 45 19 51 23 52.5 C26 53 27.5 48 26.5 43 L25.5 38 Z" fill="#ffffff" stroke="#e2e8f0" strokeWidth="1" />
        </g>
        <g className={walking ? 'pac-pet-leg-r' : sitting || brushing || seated ? 'pac-pet-dangle-r' : ''}>
          <path d="M45 38 C46 45 45 51 41 52.5 C38 53 36.5 48 37.5 43 L38.5 38 Z" fill="#ffffff" stroke="#e2e8f0" strokeWidth="1" />
        </g>
        {/* 牙冠 */}
        <path
          d="M32 6 C21 6 13 12 13 23 C13 30 14.5 35.5 16.5 40.5 L47.5 40.5 C49.5 35.5 51 30 51 23 C51 12 43 6 32 6 Z"
          fill="#ffffff"
          stroke="#e2e8f0"
          strokeWidth="1.2"
        />
        {/* 冠顶咬合面小凹(磨牙特征)+ 左上高光 */}
        <path d="M25 8.5 Q32 12 39 8.5" stroke="#e2e8f0" strokeWidth="1.4" strokeLinecap="round" fill="none" />
        <path d="M18 16 Q19 11 24 9.5" stroke="#f8fafc" strokeWidth="2.4" strokeLinecap="round" fill="none" opacity="0.9" />
        {/* 下缘淡影(立体感) */}
        <path d="M18 38 Q32 43 46 38 L47.5 40.5 L16.5 40.5 Z" fill="#f1f5f9" />
        {/* 眼白 */}
        <circle cx="24" cy="24" r="5.6" fill="#f8fafc" />
        <circle cx="40" cy="24" r="5.6" fill="#f8fafc" />
        {/* 瞳孔(rAF 追鼠标;摔落瞪小圆眼) */}
        {!arcEyes && (
          <g ref={pupilsRef}>
            <circle cx="24" cy="24.5" r={falling ? 1.7 : 2.6} fill="#0f172a" />
            <circle cx="40" cy="24.5" r={falling ? 1.7 : 2.6} fill="#0f172a" />
            <circle cx="25" cy="23.6" r="0.9" fill="#ffffff" />
            <circle cx="41" cy="23.6" r="0.9" fill="#ffffff" />
          </g>
        )}
        {/* 开心眼 ^^(庆祝/被摸) */}
        {arcEyes && (
          <g stroke="#0f172a" strokeWidth="2.2" strokeLinecap="round" fill="none">
            <path d="M19.5 25 Q24 20.5 28.5 25" />
            <path d="M35.5 25 Q40 20.5 44.5 25" />
          </g>
        )}
        {/* 眼皮(眨眼;睡觉常闭) */}
        <g className={sleeping ? '' : 'pac-pet-blink'} style={sleeping ? undefined : { transform: 'scaleY(0)' }}>
          <rect x="17.5" y="18" width="13" height="12" rx="6" fill="#ffffff" />
          <rect x="33.5" y="18" width="13" height="12" rx="6" fill="#ffffff" />
        </g>
        {sleeping && (
          <g stroke="#94a3b8" strokeWidth="1.8" strokeLinecap="round" fill="none">
            <path d="M20 25 Q24 27.5 28 25" />
            <path d="M36 25 Q40 27.5 44 25" />
          </g>
        )}
        {/* 漱口鼓腮:两侧脸颊鼓起 */}
        {rinsing && (
          <g fill="#ffffff" stroke="#e2e8f0" strokeWidth="1">
            <ellipse cx="19" cy="31.5" rx="4.2" ry="3.6" />
            <ellipse cx="45" cy="31.5" rx="4.2" ry="3.6" />
          </g>
        )}
        {/* 嘴:摔落 o / 庆祝&闪亮大笑 / 被摸甜笑 / 漱口抿紧 / 咬合操(双嘴交替) / 平时微笑 */}
        {falling ? (
          <circle cx="32" cy="33" r="2.4" fill="#334155" />
        ) : celebrating || shining ? (
          <path d="M27 31.5 Q32 38 37 31.5 Z" fill="#334155" />
        ) : happy ? (
          <path d="M28 31 Q32 35.5 36 31" stroke="#334155" strokeWidth="1.8" strokeLinecap="round" fill="none" />
        ) : rinsing ? (
          <path d="M30.5 32.5 L33.5 32.5" stroke="#334155" strokeWidth="1.6" strokeLinecap="round" fill="none" />
        ) : absorbing ? (
          // 吸入时张成小圆嘴(像在吸)
          <ellipse cx="32" cy="32.6" rx="2.6" ry="3.2" fill="#334155" />
        ) : chomping ? (
          <g>
            <ellipse className="pac-pet-chomp-open" cx="32" cy="32.5" rx="4" ry="3.2" fill="#334155" />
            <path className="pac-pet-chomp-closed" d="M28.5 32.5 L35.5 32.5" stroke="#334155" strokeWidth="1.8" strokeLinecap="round" />
          </g>
        ) : flying || morphing ? (
          <path d="M28.5 32 Q32 35 35.5 32" stroke="#334155" strokeWidth="2" strokeLinecap="round" fill="none" />
        ) : (
          <path d="M29.5 32 Q32 34.2 34.5 32" stroke="#334155" strokeWidth="1.6" strokeLinecap="round" fill="none" />
        )}
        {/* 腮红(常驻,Q 版灵魂) */}
        <g fill="#fda4af" opacity={celebrating || happy ? 0.9 : 0.55}>
          <ellipse cx="17.5" cy="29.5" rx="3" ry="1.8" />
          <ellipse cx="46.5" cy="29.5" rx="3" ry="1.8" />
        </g>
      </g>
        </>
      )}
      {/* 放大镜:握在身前朝向文字(facing 由外层翻转),镜片带高光 + 轻晃 */}
      {magnifying && (
        <g className="pac-pet-mag">
          <line x1="51" y1="40" x2="46" y2="33" stroke="#92400e" strokeWidth="2.4" strokeLinecap="round" />
          <circle cx="44" cy="29" r="6" fill="#bae6fd" fillOpacity="0.35" stroke="#0ea5e9" strokeWidth="1.8" />
          <path d="M41 27 Q43 25.5 45.5 26" stroke="#ffffff" strokeWidth="1.4" strokeLinecap="round" fill="none" opacity="0.9" />
        </g>
      )}
      {/* 牙医组合:额镜(全程戴)+ 当前步骤的器械 + 特效 */}
      {vetMode && (
        <>
          {/* 额镜:额头反光圆盘(中心孔)+ 头带 */}
          <g>
            <rect x="19" y="9" width="26" height="2" rx="1" fill="#94a3b8" />
            <circle cx="32" cy="6.5" r="4.2" fill="#e2e8f0" stroke="#94a3b8" strokeWidth="1" />
            <circle cx="32" cy="6.5" r="1.7" fill="#475569" />
            <circle cx="30.6" cy="5.2" r="0.9" fill="#ffffff" />
          </g>
          {/* 器械:都握在身前嘴边(~35,38);facing 由外层翻转 */}
          {vetExam && (
            <g stroke="#64748b" strokeWidth="1.6" strokeLinecap="round">
              <line x1="44" y1="50" x2="36" y2="40" />
              <circle cx="35" cy="38.5" r="2.6" fill="#e2e8f0" />
            </g>
          )}
          {vetScale && (
            <>
              <g className="pac-vet-buzz">
                <line x1="45" y1="51" x2="37" y2="41" stroke="#64748b" strokeWidth="2" strokeLinecap="round" />
                <path d="M37 41 L33.5 37.5" stroke="#94a3b8" strokeWidth="1.4" strokeLinecap="round" />
              </g>
              <g fill="#a5f3fc" stroke="#67e8f9" strokeWidth="0.5">
                <circle className="pac-pet-rinse-b" cx="33" cy="36" r="1.3" style={{ animationDelay: '0s' }} />
                <circle className="pac-pet-rinse-b" cx="36" cy="34" r="1.7" style={{ animationDelay: '0.4s' }} />
                <circle className="pac-pet-rinse-b" cx="30" cy="35" r="1.1" style={{ animationDelay: '0.8s' }} />
              </g>
            </>
          )}
          {vetFill && (
            <>
              <line x1="46" y1="51" x2="38" y2="42" stroke="#475569" strokeWidth="3" strokeLinecap="round" />
              <circle className="pac-vet-spin" cx="35.5" cy="39" r="2.4" fill="#cbd5e1" stroke="#64748b" strokeWidth="0.8" />
              <path d="M35.5 36.6 L35.5 41.4 M33.1 39 L37.9 39" stroke="#94a3b8" strokeWidth="0.7" />
              <g fill="#fbbf24">
                <circle className="pac-pet-spark" cx="31" cy="36" r="1" />
                <circle className="pac-pet-spark" cx="39" cy="37" r="0.9" style={{ animationDelay: '0.3s' }} />
              </g>
            </>
          )}
          {vetPolish && (
            <>
              <line x1="46" y1="51" x2="38" y2="42" stroke="#475569" strokeWidth="3" strokeLinecap="round" />
              <path className="pac-vet-spin" d="M33.5 37 L37.5 37 L36.5 40.5 L34.5 40.5 Z" fill="#fca5a5" stroke="#ef4444" strokeWidth="0.6" />
              <g fill="#fde68a" stroke="#fbbf24" strokeWidth="0.5">
                <path className="pac-pet-spark" d="M30 34 l0.8 1.8 1.8 0.8 -1.8 0.8 -0.8 1.8 -0.8 -1.8 -1.8 -0.8 1.8 -0.8 Z" />
                <path className="pac-pet-spark" d="M40 36 l0.7 1.6 1.6 0.7 -1.6 0.7 -0.7 1.6 -0.7 -1.6 -1.6 -0.7 1.6 -0.7 Z" style={{ animationDelay: '0.35s' }} />
              </g>
            </>
          )}
          {vetFluoride && (
            <>
              <line x1="45" y1="51" x2="37" y2="41" stroke="#0032A0" strokeWidth="2" strokeLinecap="round" />
              <ellipse className="pac-vet-buzz" cx="35" cy="39" rx="2.4" ry="1.6" fill="#85A9FA" stroke="#0032A0" strokeWidth="0.6" />
              <g fill="#BACFFD" stroke="#85A9FA" strokeWidth="0.4">
                <circle className="pac-pet-rinse-b" cx="33" cy="36" r="1.1" />
                <circle className="pac-pet-rinse-b" cx="37" cy="35" r="1.4" style={{ animationDelay: '0.5s' }} />
              </g>
            </>
          )}
        </>
      )}
      {/* 思考:头顶冒点点 */}
      {thinking && (
        <g fill="#0032A0">
          <circle className="pac-pet-dot" cx="46" cy="12" r="2" style={{ animationDelay: '0s' }} />
          <circle className="pac-pet-dot" cx="52" cy="8" r="2.6" style={{ animationDelay: '0.2s' }} />
          <circle className="pac-pet-dot" cx="58" cy="3.5" r="3.2" style={{ animationDelay: '0.4s' }} />
        </g>
      )}
      {/* 刷牙刷字:身前牙刷快速刷洗 + 冒小泡泡 */}
      {brushing && (
        <>
          <g className="pac-pet-scrub">
            {/* 刷柄(品牌青) + 刷毛 */}
            <rect x="22" y="50" width="20" height="3.6" rx="1.8" fill="#0032A0" transform="rotate(-8 32 52)" />
            <rect x="38" y="45.5" width="7" height="6" rx="1.2" fill="#ffffff" stroke="#e2e8f0" strokeWidth="0.8" transform="rotate(-8 41 48)" />
          </g>
          <g fill="#a5f3fc" stroke="#67e8f9" strokeWidth="0.5">
            <circle className="pac-pet-bubble" cx="26" cy="46" r="1.6" style={{ animationDelay: '0s' }} />
            <circle className="pac-pet-bubble" cx="34" cy="44" r="2.2" style={{ animationDelay: '0.35s' }} />
            <circle className="pac-pet-bubble" cx="42" cy="46" r="1.3" style={{ animationDelay: '0.7s' }} />
          </g>
        </>
      )}
      {/* 牙线自理:头顶拉一根牙线锯冠缝 */}
      {flossing && (
        <g className="pac-pet-floss">
          <path d="M8 13 Q32 22 56 13" stroke="#85A9FA" strokeWidth="1.6" fill="none" strokeLinecap="round" />
          <circle cx="8" cy="13" r="2.2" fill="#0032A0" />
          <circle cx="56" cy="13" r="2.2" fill="#0032A0" />
        </g>
      )}
      {/* 闪亮微笑:牙面 ding 两颗星 */}
      {shining && (
        <g fill="#fef9c3" stroke="#fbbf24" strokeWidth="0.6">
          <path className="pac-pet-spark" d="M20 13 l1.2 2.6 2.6 1.2 -2.6 1.2 -1.2 2.6 -1.2 -2.6 -2.6 -1.2 2.6 -1.2 Z" />
          <path className="pac-pet-spark" d="M45 10 l1 2.2 2.2 1 -2.2 1 -1 2.2 -1 -2.2 -2.2 -1 2.2 -1 Z" style={{ animationDelay: '0.3s' }} />
        </g>
      )}
      {/* 涂氟护盾 buff:青色光罩 + 微光(与姿态正交,可叠加在任何动作上) */}
      {shield && (
        <g className="pac-pet-shieldfx">
          <circle cx="32" cy="34" r="29" fill="rgba(103,232,249,0.08)" stroke="#67e8f9" strokeWidth="1.4" />
          <path className="pac-pet-spark" fill="#a5f3fc" stroke="none" d="M10 22 l0.9 2 2 0.9 -2 0.9 -0.9 2 -0.9 -2 -2 -0.9 2 -0.9 Z" />
          <path className="pac-pet-spark" fill="#a5f3fc" stroke="none" d="M53 44 l0.9 2 2 0.9 -2 0.9 -0.9 2 -0.9 -2 -2 -0.9 2 -0.9 Z" style={{ animationDelay: '0.55s' }} />
        </g>
      )}
      {/* 漱口:嘴边吐出一串泡泡往上飘 */}
      {rinsing && (
        <g fill="#a5f3fc" stroke="#67e8f9" strokeWidth="0.5">
          <circle className="pac-pet-rinse-b" cx="36" cy="29" r="1.4" style={{ animationDelay: '0s' }} />
          <circle className="pac-pet-rinse-b" cx="40" cy="26" r="2.2" style={{ animationDelay: '0.4s' }} />
          <circle className="pac-pet-rinse-b" cx="44" cy="22" r="1.7" style={{ animationDelay: '0.8s' }} />
          <circle className="pac-pet-rinse-b" cx="47" cy="17" r="2.8" style={{ animationDelay: '1.1s' }} />
        </g>
      )}
      {/* 被摸:头顶冒小爱心 */}
      {happy && (
        <g fill="#fb7185">
          <path className="pac-pet-heart" d="M46 10 c-1.5 -2.6 -5 -1.4 -5 1 c0 2 2.6 3.6 5 5.4 c2.4 -1.8 5 -3.4 5 -5.4 c0 -2.4 -3.5 -3.6 -5 -1 Z" />
          <path className="pac-pet-heart" d="M55 5 c-1 -1.8 -3.4 -1 -3.4 0.7 c0 1.4 1.8 2.4 3.4 3.6 c1.6 -1.2 3.4 -2.2 3.4 -3.6 c0 -1.7 -2.4 -2.5 -3.4 -0.7 Z" style={{ animationDelay: '0.5s' }} />
        </g>
      )}
      {/* 睡觉:Zzz */}
      {sleeping && (
        <g fill="#0032A0" fontWeight={700} fontFamily="ui-sans-serif">
          <text className="pac-pet-z" x="46" y="14" fontSize="9" style={{ animationDelay: '0s' }}>z</text>
          <text className="pac-pet-z" x="52" y="8" fontSize="12" style={{ animationDelay: '0.6s' }}>Z</text>
        </g>
      )}
      {/* 摔落:头顶速度线 */}
      {falling && (
        <g stroke="#94a3b8" strokeWidth="1.6" strokeLinecap="round" opacity="0.8">
          <path d="M22 4 L22 0" />
          <path d="M32 3 L32 -2" />
          <path d="M42 4 L42 0" />
        </g>
      )}
      {/* 庆祝:小星星 */}
      {celebrating && (
        <g fill="#fbbf24">
          <path className="pac-pet-spark" d="M10 12 l1.4 3 3 1.4 -3 1.4 -1.4 3 -1.4 -3 -3 -1.4 3 -1.4 Z" />
          <path className="pac-pet-spark" d="M53 16 l1 2.2 2.2 1 -2.2 1 -1 2.2 -1 -2.2 -2.2 -1 2.2 -1 Z" style={{ animationDelay: '0.25s' }} />
        </g>
      )}
    </svg>
  );
}

/** 动画全包在 reduced-motion 守卫内 — 用户要求减弱动效时自动退化为静态形象。 */
const PET_CSS = `
@media (prefers-reduced-motion: no-preference) {
  .pac-pet-breath { transform-origin: 32px 53px; animation: pacPetBreath 3.4s ease-in-out infinite; }
  .pac-pet-walkbob { transform-origin: 32px 53px; animation: pacPetWalkBob 0.4s ease-in-out infinite; }
  .pac-pet-leg-l { transform-box: fill-box; transform-origin: top center; animation: pacPetLeg 0.4s ease-in-out infinite; }
  .pac-pet-leg-r { transform-box: fill-box; transform-origin: top center; animation: pacPetLeg 0.4s ease-in-out infinite reverse; }
  .pac-pet-dangle-l { transform-box: fill-box; transform-origin: top center; animation: pacPetDangle 1.7s ease-in-out infinite; }
  .pac-pet-dangle-r { transform-box: fill-box; transform-origin: top center; animation: pacPetDangle 1.7s ease-in-out infinite reverse; }
  .pac-pet-scrub { animation: pacPetScrub 0.24s ease-in-out infinite; }
  .pac-pet-bubble { animation: pacPetBubble 1.1s ease-in-out infinite; }
  .pac-pet-rinse-b { animation: pacPetRinse 1.6s ease-out infinite; }
  .pac-pet-floss { animation: pacPetFloss 0.5s ease-in-out infinite; }
  .pac-pet-absorb { animation: pacPetAbsorb 0.8s ease-in-out infinite; }
  .pac-pet-absorb-flow text { animation: pacPetAbsorbFlow 0.9s ease-in infinite; }
  .pac-pet-absorb-flow text:nth-child(2) { animation-delay: 0.3s; }
  .pac-pet-absorb-flow text:nth-child(3) { animation-delay: 0.6s; }
  .pac-pet-chomp-open { animation: pacPetChomp 0.5s steps(1) infinite; }
  .pac-pet-chomp-closed { animation: pacPetChomp 0.5s steps(1) infinite; animation-delay: -0.25s; }
  .pac-pet-shieldfx { animation: pacPetShield 2.2s ease-in-out infinite; transform-origin: 32px 34px; }
  .pac-pet-blink { transform-origin: 32px 18px; animation: pacPetBlink 4.7s infinite; }
  .pac-pet-jump { animation: pacPetJump 0.9s ease-in-out 2; }
  .pac-pet-wiggle { animation: pacPetWiggle 0.7s ease-in-out infinite; }
  .pac-pet-heart { animation: pacPetHeart 1.4s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
  .pac-pet-squash { animation: pacPetSquash 0.26s ease-out 1; }
  .pac-pet-falling { animation: pacPetFlail 0.5s ease-in-out infinite; }
  .pac-pet-flylean { animation: pacPetFlyLean 0.5s ease-in-out infinite; }
  .pac-pet-cape { transform-box: fill-box; transform-origin: 22px 16px; animation: pacPetCape 0.4s ease-in-out infinite; }
  .pac-pet-cape-unfurl { transform-box: fill-box; transform-origin: 23px 15px; animation: pacPetCapeUnfurl 0.5s ease-out 1, pacPetCape 0.4s ease-in-out 0.5s infinite; }
  .pac-pet-morph { transform-origin: 32px 53px; animation: pacPetMorph 0.45s ease-in-out infinite; }
  .pac-pet-ring { transform-box: fill-box; transform-origin: center; animation: pacPetRing 0.7s ease-out infinite; }
  .pac-vet-buzz { transform-box: fill-box; transform-origin: center; animation: pacVetBuzz 0.09s linear infinite; }
  .pac-vet-spin { transform-box: fill-box; transform-origin: center; animation: pacVetSpin 0.18s linear infinite; }
  .pac-pet-climb { transform-origin: 32px 30px; animation: pacPetClimb 0.62s ease-in-out infinite; }
  .pac-pet-climb-armL { transform-box: fill-box; transform-origin: bottom center; animation: pacPetClimbLimb 0.62s ease-in-out infinite; }
  .pac-pet-climb-armR { transform-box: fill-box; transform-origin: bottom center; animation: pacPetClimbLimb 0.62s ease-in-out infinite reverse; }
  .pac-pet-climb-legL { transform-box: fill-box; transform-origin: top center; animation: pacPetClimbLimb 0.62s ease-in-out infinite reverse; }
  .pac-pet-climb-legR { transform-box: fill-box; transform-origin: top center; animation: pacPetClimbLimb 0.62s ease-in-out infinite; }
  .pac-pet-mag { transform-box: fill-box; transform-origin: 51px 40px; animation: pacPetMag 1.6s ease-in-out infinite; }
  .pac-pet-dot { animation: pacPetDot 1.2s ease-in-out infinite; }
  .pac-pet-z { animation: pacPetZ 1.8s ease-in-out infinite; }
  .pac-pet-spark { animation: pacPetSpark 1.1s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
}
@keyframes pacPetBreath { 0%,100% { transform: scaleY(1); } 50% { transform: scaleY(0.962); } }
@keyframes pacPetWalkBob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
@keyframes pacPetLeg { 0%,100% { transform: rotate(-13deg); } 50% { transform: rotate(13deg); } }
@keyframes pacPetDangle { 0%,100% { transform: rotate(16deg); } 50% { transform: rotate(-7deg); } }
@keyframes pacPetScrub { 0%,100% { transform: translateX(-3.5px); } 50% { transform: translateX(3.5px); } }
@keyframes pacPetBubble { 0% { opacity: 0; transform: translateY(2px) scale(0.6); } 40% { opacity: 1; } 100% { opacity: 0; transform: translateY(-6px) scale(1.05); } }
@keyframes pacPetRinse { 0% { opacity: 0; transform: translateY(3px) scale(0.5); } 30% { opacity: 1; } 100% { opacity: 0; transform: translateY(-12px) scale(1.15); } }
@keyframes pacPetFloss { 0%,100% { transform: translateY(0); } 50% { transform: translateY(3px); } }
@keyframes pacPetChomp { 0%,49.9% { opacity: 1; } 50%,100% { opacity: 0; } }
/* 吸入:身体轻微前倾 + 数字流被吸向嘴部 */
@keyframes pacPetAbsorb { 0%,100% { transform: scale(1); } 45% { transform: scale(1.04) translateX(1px); } }
@keyframes pacPetAbsorbFlow {
  0%   { opacity: 0; transform: translateX(10px) scale(1); }
  25%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(-20px) scale(0.4); }
}
@keyframes pacPetShield { 0%,100% { opacity: 0.55; transform: scale(0.985); } 50% { opacity: 0.95; transform: scale(1.015); } }
@keyframes pacPetBlink { 0%,91%,97%,100% { transform: scaleY(0); } 93.5% { transform: scaleY(1); } }
@keyframes pacPetJump { 0%,100% { transform: translateY(0); } 35% { transform: translateY(-7px); } 55% { transform: translateY(0); } 70% { transform: translateY(-3px); } }
@keyframes pacPetWiggle { 0%,100% { transform: rotate(-2.5deg); } 50% { transform: rotate(2.5deg); } }
@keyframes pacPetHeart { 0% { opacity: 0; transform: translateY(2px) scale(0.7); } 35% { opacity: 1; transform: translateY(-1px) scale(1); } 100% { opacity: 0; transform: translateY(-5px) scale(0.9); } }
@keyframes pacPetSquash { 0% { transform: scaleY(0.78) scaleX(1.12); } 100% { transform: scaleY(1) scaleX(1); } }
@keyframes pacPetFlail { 0%,100% { transform: rotate(-4deg); } 50% { transform: rotate(4deg); } }
@keyframes pacPetFlyLean { 0%,100% { transform: rotate(-16deg); } 50% { transform: rotate(-12deg); } }
@keyframes pacPetCape { 0%,100% { transform: skewY(-6deg) scaleX(1); } 50% { transform: skewY(6deg) scaleX(1.08); } }
@keyframes pacPetCapeUnfurl { 0% { transform: scale(0.1) rotate(-30deg); opacity: 0; } 60% { opacity: 1; } 100% { transform: scale(1) rotate(0deg); opacity: 1; } }
@keyframes pacPetMorph { 0%,100% { transform: translateY(0) scale(1); } 50% { transform: translateY(-3px) scale(1.07); } }
@keyframes pacPetRing { 0% { opacity: 0.85; transform: scale(0.3); } 100% { opacity: 0; transform: scale(1.7); } }
@keyframes pacVetBuzz { 0% { transform: translate(0.6px, 0); } 50% { transform: translate(-0.6px, 0.4px); } 100% { transform: translate(0.6px, 0); } }
@keyframes pacVetSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes pacPetClimb { 0%,100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-1.6px) rotate(2deg); } }
@keyframes pacPetClimbLimb { 0%,100% { transform: rotate(-9deg); } 50% { transform: rotate(9deg); } }
@keyframes pacPetMag { 0%,100% { transform: translate(0,0) rotate(0deg); } 50% { transform: translate(1.5px,-1px) rotate(-5deg); } }
@keyframes pacPetDot { 0%,100% { opacity: 0.25; } 50% { opacity: 1; } }
@keyframes pacPetZ { 0% { opacity: 0; transform: translateY(3px); } 40% { opacity: 1; } 100% { opacity: 0; transform: translateY(-4px); } }
@keyframes pacPetSpark { 0%,100% { opacity: 0.2; transform: scale(0.7); } 50% { opacity: 1; transform: scale(1.15); } }
`;
