/* ==========================================================================
   MC 纸模型小人（真 3D）
   --------------------------------------------------------------------------
   每个部位是一个 3D 盒子，六个面分别从皮肤贴图上取对应区域。

   这份 CSS 由脚本生成 —— 6 部位 × 6 面 = 36 条规则，
   每条都带贴图坐标与三维偏移，手写几乎必错。

   贴图坐标公式（标准 64×64 布局，fx/fy 是正面左上角）：
     正面 (fx,       fy)
     背面 (fx+w+d,   fy)
     右面 (fx-d,     fy)      角色右侧，正面视角看在观察者左边
     左面 (fx+w,     fy)      角色左侧，正面视角看在观察者右边
     顶面 (fx,       fy-d)
     底面 (fx+w,     fy-d)

   左右肢的位置也按这个来：角色的左臂在观察者**右**边（x=12）。
   写反的话动作会整体镜像，看着就是「姿势全反了」。

   另：从透视容器到每个面之间的所有祖先都要 preserve-3d，少一层就被压平。
   ========================================================================== */

.mc-figs {
	--s: 3;
	--skin: none;
	position: absolute;
	left: 0; top: 0;
	width: 100%; height: 100%;
	z-index: 6;
	pointer-events: none;
	/* 透视**不能**放在这一层：
	   整页只有一个透视原点，跑到页面下半部的小人会从极偏的角度被投影，
	   结果就是「拉得老长」。透视必须跟着每个小人自己走。 */
}

.mc-fig {
	position: absolute;
	left: 0; top: 0;
	width: calc(16 * var(--s) * 1px);
	height: calc(32 * var(--s) * 1px);
	/* 位移由 JS 每帧插值（见 figures.js 的 moveTo），
	   这里**不能**再挂 transition —— 两者会打架：
	   CSS 过渡一旦启动就锁定时长，中途改 --walk 无效；
	   关掉过渡又会让元素跳到终点。抓小人时因此反复出现瞬移。
	   只保留 filter 的过渡（抓取光晕的淡出）。 */
	transition: filter .4s ease;
	will-change: transform;
	cursor: grab;
	pointer-events: auto;
	touch-action: none;
	user-select: none;
	-webkit-tap-highlight-color: transparent;
}

.mc-fig.is-dragging { transition: none; cursor: grabbing; }

.mc-fig::after {
	content: "";
	position: absolute;
	left: 50%;
	bottom: calc(-1 * var(--s) * 1.5px);
	width: calc(13 * var(--s) * 1px);
	height: calc(2.4 * var(--s) * 1px);
	transform: translateX(-50%);
	border-radius: 50%;
	background: radial-gradient(ellipse at center, rgba(0, 0, 0, .55), rgba(0, 0, 0, 0) 72%);
	pointer-events: none;
}

/* 透视舞台：每个小人各自一个透视原点，跟着它移动。
   强度按小人身高算（约 4 倍），这样大小屏幕上的立体感一致，
   不会出现「在手机上被透视拉变形」。 */
.mc-fig .stage {
	position: absolute;
	inset: 0;
	perspective: calc(130 * var(--s) * 1px);
	perspective-origin: 50% 38%;
	transform-style: flat;
}

.mc-fig .body,
.mc-fig .face { position: absolute; inset: 0; transform-style: preserve-3d; }

/* 朝向平滑过渡：走动时按方向连续转，硬切会一顿一顿的 */
.mc-fig .face { transition: transform .28s ease; }

/* 肢体绕顶边中点转（肩膀、胯）；原点在中心就成甩棍子 */
.mc-fig .al, .mc-fig .ar, .mc-fig .gl, .mc-fig .gr { transform-origin: 50% 0; }

.mc-fig i { position: absolute; left: 0; top: 0; transform-style: preserve-3d; }

.mc-fig i b {
	position: absolute;
	display: block;
	background-image: var(--skin);
	background-repeat: no-repeat;
	background-size: calc(64 * var(--s) * 1px) calc(64 * var(--s) * 1px);
	image-rendering: pixelated;
	image-rendering: crisp-edges;
}

/*
 * 贴图挂内层 u：老版左肢要水平翻转，而外层 i 的 transform 被动画占着。
 *
 * background-color 是**不透明兜底**：有些皮肤的手臂底面本身就是半透明的
 * （实测 Cracke_ 的 (48,16) 区域 8/16 透明、Aa_Tong 同样），
 * 那些像素什么都不画，于是直接看到模型内部的背面 —— 手底像破了个洞。
 * 垫一个底色之后，透明处显示的就是这个颜色，不会透出背面。
 *
 * 颜色由 figures.js 按该皮肤实测的平均色写入 --skin-fallback，
 * 所以每个小人的兜底色都跟自己的皮肤相称，不是写死的灰。
 */
.mc-fig i u {
	position: absolute;
	inset: 0;
	display: block;
	background-image: var(--skin);
	background-repeat: no-repeat;
	background-size: calc(64 * var(--s) * 1px) calc(64 * var(--s) * 1px);
	image-rendering: pixelated;
	image-rendering: crisp-edges;
	/*
	 * 这里**故意不设 background-color** 兜底。
	 *
	 * 垫过一层「整张皮肤平均色」的兜底，结果 Steve 的手臂底面透出偏蓝的色块
	 * （平均色被青衣蓝裤带偏），补丁比原来的破洞还显眼。
	 *
	 * 现在透明像素由 figures.js 的 repairSkin() 事先按**最近的邻近像素**补掉，
	 * 补完烤成 data URL 顶替原图，所以这里不需要、也不该再猜颜色。
	 */
}


/* ---- h（8×8×8，正面贴图 8,8）---- */
.mc-fig .h {
	width: calc(8 * var(--s) * 1px);
	height: calc(8 * var(--s) * 1px);
	/* --tx/--ty 供动作关键帧复用，避免两处各写一份而写岔 */
	--tx: calc(4 * var(--s) * 1px);
	/* 下移 0.5：让头的底面落进身体内部，两边不再共面（见上方「相邻部件的接缝」） */
	--ty: calc(.5 * var(--s) * 1px);
	transform: translate3d(calc(4 * var(--s) * 1px), calc(.5 * var(--s) * 1px), 0);
}
.mc-fig .h .f { width: calc(8 * var(--s) * 1px); height: calc(8 * var(--s) * 1px); transform: translateZ(calc(4.0 * var(--s) * 1px)); }
.mc-fig .h .f u { background-position: calc(-8 * var(--s) * 1px) calc(-8 * var(--s) * 1px); }
.mc-fig .h .k { width: calc(8 * var(--s) * 1px); height: calc(8 * var(--s) * 1px); transform: rotateY(180deg) translateZ(calc(4.0 * var(--s) * 1px)); }
.mc-fig .h .k u { background-position: calc(-24 * var(--s) * 1px) calc(-8 * var(--s) * 1px); }
.mc-fig .h .r { width: calc(8 * var(--s) * 1px); height: calc(8 * var(--s) * 1px); transform: rotateY(-90deg) translateZ(calc(4.0 * var(--s) * 1px)); }
.mc-fig .h .r u { background-position: 0 calc(-8 * var(--s) * 1px); }
.mc-fig .h .l { width: calc(8 * var(--s) * 1px); height: calc(8 * var(--s) * 1px); transform: rotateY(90deg) translateZ(calc(4.0 * var(--s) * 1px)); }
.mc-fig .h .l u { background-position: calc(-16 * var(--s) * 1px) calc(-8 * var(--s) * 1px); }
.mc-fig .h .u { width: calc(8 * var(--s) * 1px); height: calc(8 * var(--s) * 1px); transform: rotateX(90deg) translateZ(calc(4.0 * var(--s) * 1px)); }
.mc-fig .h .u u { background-position: calc(-8 * var(--s) * 1px) 0; }
.mc-fig .h .dd { width: calc(8 * var(--s) * 1px); height: calc(8 * var(--s) * 1px); transform: rotateX(-90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .h .dd u { background-position: calc(-16 * var(--s) * 1px) 0; }

/* ---- b（8×12×4，正面贴图 20,20）---- */
.mc-fig .b {
	width: calc(8 * var(--s) * 1px);
	height: calc(12 * var(--s) * 1px);
	/* --tx/--ty 供动作关键帧复用，避免两处各写一份而写岔 */
	--tx: calc(4 * var(--s) * 1px);
	--ty: calc(8 * var(--s) * 1px);
	transform: translate3d(calc(4 * var(--s) * 1px), calc(8 * var(--s) * 1px), 0);
}
.mc-fig .b .f { width: calc(8 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .b .f u { background-position: calc(-20 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .b .k { width: calc(8 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(180deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .b .k u { background-position: calc(-32 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .b .r { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); left: calc(2.0 * var(--s) * 1px); transform: rotateY(-90deg) translateZ(calc(4.0 * var(--s) * 1px)); }
.mc-fig .b .r u { background-position: calc(-16 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .b .l { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); left: calc(2.0 * var(--s) * 1px); transform: rotateY(90deg) translateZ(calc(4.0 * var(--s) * 1px)); }
.mc-fig .b .l u { background-position: calc(-28 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .b .u { width: calc(8 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .b .u u { background-position: calc(-20 * var(--s) * 1px) calc(-16 * var(--s) * 1px); }
.mc-fig .b .dd { width: calc(8 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(-90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .b .dd u { background-position: calc(-28 * var(--s) * 1px) calc(-16 * var(--s) * 1px); }

/* ---- al（4×12×4，正面贴图 36,52）---- */
.mc-fig .al {
	width: calc(4 * var(--s) * 1px);
	height: calc(12 * var(--s) * 1px);
	/* --tx/--ty 供动作关键帧复用，避免两处各写一份而写岔 */
	--tx: calc(12 * var(--s) * 1px);
	--ty: calc(8 * var(--s) * 1px);
	transform: translate3d(calc(12 * var(--s) * 1px), calc(8 * var(--s) * 1px), 0);
}
.mc-fig .al .f { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .al .f u { background-position: calc(-36 * var(--s) * 1px) calc(-52 * var(--s) * 1px); }
.mc-fig .al .k { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(180deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .al .k u { background-position: calc(-44 * var(--s) * 1px) calc(-52 * var(--s) * 1px); }
.mc-fig .al .r { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(-90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .al .r u { background-position: calc(-32 * var(--s) * 1px) calc(-52 * var(--s) * 1px); }
.mc-fig .al .l { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .al .l u { background-position: calc(-40 * var(--s) * 1px) calc(-52 * var(--s) * 1px); }
.mc-fig .al .u { width: calc(4 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .al .u u { background-position: calc(-36 * var(--s) * 1px) calc(-48 * var(--s) * 1px); }
.mc-fig .al .dd { width: calc(4 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(-90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .al .dd u { background-position: calc(-40 * var(--s) * 1px) calc(-48 * var(--s) * 1px); }

/* ---- ar（4×12×4，正面贴图 44,20）---- */
.mc-fig .ar {
	width: calc(4 * var(--s) * 1px);
	height: calc(12 * var(--s) * 1px);
	/* --tx/--ty 供动作关键帧复用，避免两处各写一份而写岔 */
	--tx: 0;
	--ty: calc(8 * var(--s) * 1px);
	transform: translate3d(0, calc(8 * var(--s) * 1px), 0);
}
.mc-fig .ar .f { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .ar .f u { background-position: calc(-44 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .ar .k { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(180deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .ar .k u { background-position: calc(-52 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .ar .r { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(-90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .ar .r u { background-position: calc(-40 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .ar .l { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .ar .l u { background-position: calc(-48 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .ar .u { width: calc(4 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .ar .u u { background-position: calc(-44 * var(--s) * 1px) calc(-16 * var(--s) * 1px); }
.mc-fig .ar .dd { width: calc(4 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(-90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .ar .dd u { background-position: calc(-48 * var(--s) * 1px) calc(-16 * var(--s) * 1px); }

/* ---- gl（4×12×4，正面贴图 20,52）---- */
.mc-fig .gl {
	width: calc(4 * var(--s) * 1px);
	height: calc(12 * var(--s) * 1px);
	/* --tx/--ty 供动作关键帧复用，避免两处各写一份而写岔 */
	--tx: calc(8 * var(--s) * 1px);
	/* 上移 0.5：让腿的顶面落进身体内部，接缝处不再共面 */
	--ty: calc(19.5 * var(--s) * 1px);
	transform: translate3d(calc(8 * var(--s) * 1px), calc(19.5 * var(--s) * 1px), 0);
}
.mc-fig .gl .f { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .gl .f u { background-position: calc(-20 * var(--s) * 1px) calc(-52 * var(--s) * 1px); }
.mc-fig .gl .k { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(180deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .gl .k u { background-position: calc(-28 * var(--s) * 1px) calc(-52 * var(--s) * 1px); }
.mc-fig .gl .r { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(-90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .gl .r u { background-position: calc(-16 * var(--s) * 1px) calc(-52 * var(--s) * 1px); }
.mc-fig .gl .l { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .gl .l u { background-position: calc(-24 * var(--s) * 1px) calc(-52 * var(--s) * 1px); }
.mc-fig .gl .u { width: calc(4 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .gl .u u { background-position: calc(-20 * var(--s) * 1px) calc(-48 * var(--s) * 1px); }
.mc-fig .gl .dd { width: calc(4 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(-90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .gl .dd u { background-position: calc(-24 * var(--s) * 1px) calc(-48 * var(--s) * 1px); }

/* ---- gr（4×12×4，正面贴图 4,20）---- */
.mc-fig .gr {
	width: calc(4 * var(--s) * 1px);
	height: calc(12 * var(--s) * 1px);
	/* --tx/--ty 供动作关键帧复用，避免两处各写一份而写岔 */
	--tx: calc(4 * var(--s) * 1px);
	/* 上移 0.5：让腿的顶面落进身体内部，接缝处不再共面 */
	--ty: calc(19.5 * var(--s) * 1px);
	transform: translate3d(calc(4 * var(--s) * 1px), calc(19.5 * var(--s) * 1px), 0);
}
.mc-fig .gr .f { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .gr .f u { background-position: calc(-4 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .gr .k { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(180deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .gr .k u { background-position: calc(-12 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .gr .r { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(-90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .gr .r u { background-position: 0 calc(-20 * var(--s) * 1px); }
.mc-fig .gr .l { width: calc(4 * var(--s) * 1px); height: calc(12 * var(--s) * 1px); transform: rotateY(90deg) translateZ(calc(2.0 * var(--s) * 1px)); }
.mc-fig .gr .l u { background-position: calc(-8 * var(--s) * 1px) calc(-20 * var(--s) * 1px); }
.mc-fig .gr .u { width: calc(4 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .gr .u u { background-position: calc(-4 * var(--s) * 1px) calc(-16 * var(--s) * 1px); }
.mc-fig .gr .dd { width: calc(4 * var(--s) * 1px); height: calc(4 * var(--s) * 1px); top: calc(4.0 * var(--s) * 1px); transform: rotateX(-90deg) translateZ(calc(6.0 * var(--s) * 1px)); }
.mc-fig .gr .dd u { background-position: calc(-8 * var(--s) * 1px) calc(-16 * var(--s) * 1px); }

/* ==========================================================================
   动作：MC 的走路是绕 X 轴前后摆（像钟摆），不是平面内左右晃
   --------------------------------------------------------------------------
   注意：肢体的基础位置靠 transform: translate3d 定，
   而动画的 transform 会**整个覆盖**它 —— 所以关键帧里必须把
   translate3d(var(--tx), var(--ty), 0) 一起写上，否则动画一开始肢体就跳回原点。
   --tx/--ty 在各自的部位规则里已定义，这里只引用，避免两处各写一份而写岔。
   ========================================================================== */

/*
 * 两套独立的摆动关键帧，方向各自写死。
 *
 * 原来第二组是靠 animation 简写里的 `reverse` 关键字来反相，
 * 但简写里的方向关键字容易被漏解析（实测两臂同相、看着像同手同脚），
 * 所以改成两套 keyframes：一套前一套后，不依赖任何关键字。
 */
@keyframes mc-fig-swing-a {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(34deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(-34deg); }
}
@keyframes mc-fig-swing-b {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(-34deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(34deg); }
}
@keyframes mc-fig-bob {
	0%, 100% { transform: translateY(0); }
	50%      { transform: translateY(calc(-1 * var(--s) * .7px)); }
}

/*
 * 走路：对角同相。
 *
 * 人走路是「对侧摆动」—— 左臂往前时，右腿也往前。
 * 角色左臂是 .al、右腿是 .gr，所以这两个同相，
 * 另外一对（.ar 右臂 / .gl 左腿）反相。
 * 写成同侧配对（.al 配 .gl）就会变成「同手同脚」。
 */
.mc-fig.is-walking .al,
.mc-fig.is-walking .gr { animation: mc-fig-swing-a .46s ease-in-out infinite !important; }
.mc-fig.is-walking .ar,
.mc-fig.is-walking .gl { animation: mc-fig-swing-b .46s ease-in-out infinite !important; }

/* 走路时身体前倾一点 + 轻微左右扭，像真的在迈步 */
@keyframes mc-fig-lean-walk {
	0%, 100% { transform: translateY(0) rotateX(5deg) rotateY(-3deg); }
	50%      { transform: translateY(calc(-1 * var(--s) * .7px)) rotateX(5deg) rotateY(3deg); }
}
.mc-fig.is-walking .body {
	animation: mc-fig-lean-walk .46s ease-in-out infinite;
	transform-origin: 50% 100%;
}

/* 头跟着迈步轻微点动 */
@keyframes mc-fig-head-bob {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(4deg); }
}
.mc-fig.is-walking .h { animation: mc-fig-head-bob .46s ease-in-out infinite; }

@keyframes mc-fig-jump {
	0%   { transform: translateY(0); }
	45%  { transform: translateY(calc(-1 * var(--s) * 5px)); }
	100% { transform: translateY(0); }
}
.mc-fig.is-jumping .body { animation: mc-fig-jump .62s cubic-bezier(.3, .7, .4, 1) !important; }

/* 扯照片：双手前伸（绕 X 轴转到身前），身子后仰 */
/* 拨弄照片：双手往**前**伸出去够照片（同样，负角是往后，写反了就成了背手） */
@keyframes mc-fig-pull {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(84deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(94deg); }
}
.mc-fig.is-pulling .al,
.mc-fig.is-pulling .ar { animation: mc-fig-pull .5s ease-in-out infinite !important; }

/* 扯东西时身体往后仰使劲：前倾是正角，所以后仰要用负角 */
@keyframes mc-fig-lean {
	0%, 100% { transform: translateY(0) rotateX(-4deg); }
	50%      { transform: translateY(calc(-1 * var(--s) * .5px)) rotateX(-9deg); }
}
.mc-fig.is-pulling .body { animation: mc-fig-lean .5s ease-in-out infinite !important; }

/* 站立时的个性动作 */
/*
 * 打招呼：手臂往**前**抬起来挥。
 *
 * CSS 里 Y 轴向下、Z 轴朝观察者，所以 rotateX(正角) 是把肢体往前抬，
 * 负角是往后甩。这里曾经写成负角，结果「打招呼」变成把手甩到背后去了。
 */
@keyframes mc-fig-wave {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(4deg) rotateZ(-8deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(150deg) rotateZ(-8deg); }
}
.mc-fig.p1 .al { animation: mc-fig-wave 1.7s ease-in-out infinite; }

/* p5 的待机：还没被看见时左臂举一下又放下 —— 和 p1 用的不是同一条手臂 */
@keyframes mc-fig-wave-b {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(4deg) rotateZ(16deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(150deg) rotateZ(16deg); }
}
.mc-fig.p5 .ar { animation: mc-fig-wave-b 1.7s ease-in-out infinite; }

@keyframes mc-fig-split {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(18deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(-18deg); }
}
@keyframes mc-fig-split-b {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(-18deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(18deg); }
}
.mc-fig.p2 .al { animation: mc-fig-split 1.9s ease-in-out infinite; }
.mc-fig.p2 .ar { animation: mc-fig-split-b 1.9s ease-in-out infinite; }

@keyframes mc-fig-hip {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateZ(-22deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateZ(-34deg); }
}
@keyframes mc-fig-hip-b {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateZ(34deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateZ(22deg); }
}
.mc-fig.p3 .al { animation: mc-fig-hip 2.4s ease-in-out infinite; }
.mc-fig.p3 .ar { animation: mc-fig-hip-b 2.4s ease-in-out infinite; }

/* 只左右轻微晃，不带任何上下位移 —— 站着的时候重心不该移动 */
@keyframes mc-fig-sway {
	0%, 100% { transform: rotateZ(-1.5deg); }
	50%      { transform: rotateZ(1.5deg); }
}
.mc-fig.p3 .body { animation: mc-fig-sway 2.4s ease-in-out infinite; transform-origin: 50% 100%; }

@keyframes mc-fig-struggle {
	0%, 100% { transform: translateY(0) rotateZ(-5deg); }
	25%      { transform: translateY(calc(-1 * var(--s) * .5px)) rotateZ(6deg); }
	50%      { transform: translateY(calc(var(--s) * .4px)) rotateZ(-4deg); }
	75%      { transform: translateY(calc(-1 * var(--s) * .4px)) rotateZ(5deg); }
}
.mc-fig.is-grabbed .body { animation: mc-fig-struggle .26s ease-in-out infinite !important; }

.mc-fig.is-grabbed { filter: drop-shadow(0 0 10px rgba(134, 213, 98, .55)); }
.mc-fig.is-grabbed span { background-color: var(--mc-green-4); border-color: #244f18; color: #fff; }
.mc-fig.is-grabbed .face { scale: 1.06; }

.mc-fig.is-dragging, .mc-fig.is-dragging * { animation-play-state: paused !important; }

.mc-fig span {
	position: absolute;
	left: 50%;
	top: calc(-1 * var(--s) * 7px);
	transform: translateX(-50%);
	padding: 1px 6px;
	font-size: 10px;
	line-height: 1.5;
	white-space: nowrap;
	color: var(--mc-off-white);
	background-color: rgba(0, 0, 0, .55);
	border: 1px solid rgba(255, 246, 232, .12);
	pointer-events: none;
	transform-style: flat;   /* 名牌不参与 3D，否则跟着转就看不清 */
}

@media (prefers-reduced-motion: reduce) { .mc-fig, .mc-fig * { animation: none !important; } }
@media screen and (max-width: 47.99em) { .mc-figs { --s: 2; } }


/* ==========================================================================
   头部底面为什么往里收 2 像素
   --------------------------------------------------------------------------
   头是 8 深、身体只有 4 深，所以头的底面在身体前方**探出 2 个皮肤像素**。
   视角又略俯（perspective-origin 在 38% 高度），于是正好看到那条探出的边 ——
   实测它在下巴处留下一道 2 像素的亮线：
       y=115 头部正面（浅肤色） / y=118~119 底面边缘（浅色） / y=121+ 身体（深色）
   一浅一深，看着就像下巴裂了缝。

   把底面沿自身法线往里收 2 像素（translateZ 4.0 → 2.0）之后，
   它退进头内部、探出的边不再可见，接缝处直接与深色的身体相接。

   收 2 像素而不是直接 display:none：点头角度较大时仍需要一块底面挡着，
   否则会直接看到头壳内部的背面。
   ========================================================================== */

/* ==========================================================================
   相邻部件的接缝
   --------------------------------------------------------------------------
   头和身体、身体和腿原本是**严丝合缝挨着**的：
       头的底面在 y=8、身体的顶面也在 y=8
       身体的底面在 y=20、腿的顶面也在 y=20
   两个面完全共面 → z-fighting → 有时露肤色、有时露衣服，看着像「透」。

   试过把内部面往里缩 0.4 像素：共面是破了，但**在部件内部留了一道缝**，
   头一转动缝就张开，下巴看着跟头脱开了。

   正确做法是让相邻部件**互相重叠**：
       头整体下移 0.5  → 头的底面落进身体内部，被身体的面挡住
       腿整体上移 0.5  → 腿的顶面落进身体内部
   既不共面、也不留缝；转动时的楔形缝也藏在重叠里。
   ========================================================================== */

/* ==========================================================================
   打招呼
   --------------------------------------------------------------------------
   规则：**没被用户看见之前，小人一动不动**。

   出生时带 .is-dormant（下面那条规则会把所有动画掐掉），
   直到 IntersectionObserver 报告「进入视口」才解除，并播一段招呼。
   招呼播完才交给自动活动逻辑 —— 也就是「先打招呼，再开始乱跑」。
   之后 act() 还会时不时再补一次招呼（只在被看见时）。

   每段约 4.2 秒，要和 figures.js 的 GREET_MS（4200）对齐：
   短了小人会先僵一会儿才继续走，长了会被硬切断。


   【防止穿模的硬约束】
   --------------------------------------------------------------------------
   手臂末端在屏幕上的 x 坐标，只由 rotateZ 决定：

       手臂挂在原点（肩）下方，末端局部坐标 (0, 12)，
       经 rotateZ(θ) 后  →  x 偏移 = −12 · sinθ

   代入各自的位置：
       .ar（观察者左侧那条，占 x 0~4，肩中心 x=2）
           x_末端 = 2 − 12·sinθ
       .al（观察者右侧那条，占 x 12~16，肩中心 x=14）
           x_末端 = 14 − 12·sinθ

   头部与躯干占 x 4~12，所以安全条件是：

       .ar  必须 rotateZ ≥ +12°    否则末端扫进头部 ❌
       .al  必须 rotateZ ≤ −12°    镜像同理

   rotateX 绕的是 x 轴，不改变 x，所以这个约束与抬臂高度无关 —— 
   只要 rotateZ 满足上式，抬到任何高度都不会穿模。

   正是这条约束让原来的两个招呼翻了车：
       g4 敬礼   用了 rotateZ(−38deg) → x = 2 + 7.4 = 9.4，正好插进头部
       g2 鞠躬   把 rotateX(46deg) 加在 .body 上，而 .body 包着全部六个部位
                 （含腿），整个小人像块板子一样前倾，腿跟着扫出去 ——
                 既不是鞠躬，姿势也会顶到东西

   下面的角度全部按上式验算过。
   ========================================================================== */

.mc-fig.is-dormant,
.mc-fig.is-dormant * {
	animation: none !important;
}

/*
 * 头的旋转原点挪到**脖子**（自身底边中点）。
 * 默认在中心的话，点头时头部的下沿会转进躯干里 ——
 * 原点在底边就只是「绕着脖子低头」，不会下沉。
 */
.mc-fig .h { transform-origin: 50% 100%; }

/* ---- g1 挥手（PhineasZ）：右臂抬到前上方，朝**外侧**摆 ---- */
@keyframes mc-greet-wave {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(150deg) rotateZ(14deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(150deg) rotateZ(40deg); }
}
.mc-fig.is-greeting.g1 .ar { animation: mc-greet-wave .52s ease-in-out 8 !important; }
/* x_末端 = 2 − 12·sin(14°~40°) = −0.9 ~ −5.7  ✅ 全在躯干外侧 */

/* ---- g2 作揖（Cracke_）：双臂往前伸，配合低头致意 ---- */
/*
 * 不再用「整体前倾」当鞠躬：.body 包着腿，一转整个小人就倒了。
 * 双臂绕肩往前（rotateX ≈ 70~86°）落在身体**前方**（+z），
 * 有 preserve-3d 做深度排序，是「挡在前面」而不是「插进身体」。
 * 再加一点向外的 rotateZ，双手不会在中间交叉。
 */
@keyframes mc-greet-zuoyi-ar {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(68deg) rotateZ(14deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(86deg) rotateZ(14deg); }
}
@keyframes mc-greet-zuoyi-al {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(68deg) rotateZ(-14deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(86deg) rotateZ(-14deg); }
}
.mc-fig.is-greeting.g2 .ar { animation: mc-greet-zuoyi-ar .7s ease-in-out 6 !important; }
.mc-fig.is-greeting.g2 .al { animation: mc-greet-zuoyi-al .7s ease-in-out 6 !important; }

/*
 * 点头。
 *
 * 头绕脖子（自身底边中点）前倾时，底面的前缘会抬起 4·sin(θ) 个皮肤像素，
 * 把头的**底面翻出来** —— 那是脖子肤色，而身后的身体顶面是深色，
 * 一浅一深，看着就像下巴裂了一条亮缝。
 *
 * 两个措施：
 *   1. 角度收小（原来 20°/15°，底面翻得很明显）
 *   2. 同时**向下平移** 4·sin(θ) 作为补偿，让头是「沉一下」而不是「翻开底面」
 * 位移量按同一个公式算，所以角度改了要跟着改。
 */
@keyframes mc-greet-nod-slow {
	0%, 30%  { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg); }
	48%      { transform: translate3d(var(--tx), calc(var(--ty) + .63 * var(--s) * 1px), 0) rotateX(9deg); }
	66%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg); }
	84%      { transform: translate3d(var(--tx), calc(var(--ty) + .42 * var(--s) * 1px), 0) rotateX(6deg); }
	100%     { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg); }
}
.mc-fig.is-greeting.g2 .h { animation: mc-greet-nod-slow 4.2s ease-in-out 1 !important; }

/* ---- g3 双手高举（Aa_Tong）：双臂抬起，一起朝外张合 ---- */
@keyframes mc-greet-bothup-ar {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(156deg) rotateZ(24deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(156deg) rotateZ(46deg); }
}
@keyframes mc-greet-bothup-al {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(156deg) rotateZ(-24deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(156deg) rotateZ(-46deg); }
}
.mc-fig.is-greeting.g3 .ar { animation: mc-greet-bothup-ar .58s ease-in-out 7 !important; }
.mc-fig.is-greeting.g3 .al { animation: mc-greet-bothup-al .58s ease-in-out 7 !important; }
/* x_末端：.ar → −2.9 ~ −6.6   .al → 18.9 ~ 22.6  ✅ 都在外侧 */

/* ---- g4 举手致意（Yadiel_）：右臂抬到前上方朝外挥，配合点头 ---- */
@keyframes mc-greet-salute {
	0%   { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg) rotateZ(14deg); }
	18%  { transform: translate3d(var(--tx), var(--ty), 0) rotateX(146deg) rotateZ(22deg); }
	38%  { transform: translate3d(var(--tx), var(--ty), 0) rotateX(146deg) rotateZ(40deg); }
	58%  { transform: translate3d(var(--tx), var(--ty), 0) rotateX(146deg) rotateZ(22deg); }
	78%  { transform: translate3d(var(--tx), var(--ty), 0) rotateX(146deg) rotateZ(40deg); }
	100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg) rotateZ(14deg); }
}
.mc-fig.is-greeting.g4 .ar { animation: mc-greet-salute 4.2s ease-in-out 1 !important; }
/* x_末端 = 2 − 12·sin(14°~40°) = −0.9 ~ −5.7  ✅ 全程在头部外侧（原来是 +9.4，插进头部） */

@keyframes mc-greet-nod {
	0%, 34%  { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg); }
	46%      { transform: translate3d(var(--tx), calc(var(--ty) + .49 * var(--s) * 1px), 0) rotateX(7deg); }
	58%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg); }
	70%      { transform: translate3d(var(--tx), calc(var(--ty) + .35 * var(--s) * 1px), 0) rotateX(5deg); }
	82%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg); }
	100%     { transform: translate3d(var(--tx), var(--ty), 0) rotateX(0deg); }
}
.mc-fig.is-greeting.g4 .h { animation: mc-greet-nod 4.2s ease-in-out 1 !important; }

/* ---- g5 双手交替上下挥动（Vanish）：一只手举起时另一只放下，像欢呼 ---- */
@keyframes mc-greet-cheer-ar {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(18deg) rotateZ(30deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(152deg) rotateZ(30deg); }
}
@keyframes mc-greet-cheer-al {
	0%, 100% { transform: translate3d(var(--tx), var(--ty), 0) rotateX(152deg) rotateZ(-30deg); }
	50%      { transform: translate3d(var(--tx), var(--ty), 0) rotateX(18deg) rotateZ(-30deg); }
}
.mc-fig.is-greeting.g5 .ar { animation: mc-greet-cheer-ar .52s ease-in-out 8 !important; }
.mc-fig.is-greeting.g5 .al { animation: mc-greet-cheer-al .52s ease-in-out 8 !important; }
/* x_末端：.ar → 2−12·sin30 = −4    .al → 14+12·sin30 = 20   ✅ 都在躯干外侧 */

/* ==========================================================================
   对话气泡
   --------------------------------------------------------------------------
   小人打招呼时在头顶冒一句问候。

   几个要点：
     · 气泡是 .mc-fig 的子元素，所以自动跟着小人走，不用每帧同步坐标。
     · 让开名牌：名牌在 top: -7*--s 处，气泡再往上抬 26px。
     · --bub-dy 是**防撞位移**：同时有几句话要显示时，
       后来的那个整体上移一行，避免两个气泡叠在一起。
       位移用 transform 做，不动 bottom —— bottom 改了会触发布局重算，
       而 transform 只走合成，几帧之内挪开也不掉帧。
     · pointer-events: none —— 气泡绝不能挡住拖小人。
   ========================================================================== */

.mc-fig .mc-bubble {
	position: absolute;
	left: 50%;
	bottom: calc(100% + 26px);
	transform: translate(-50%, var(--bub-dy, 0px));

	width: max-content;
	max-width: calc(150 * var(--s) * 1px);
	padding: calc(4 * var(--s) / 2px) calc(7 * var(--s) / 2px);

	font-size: calc(4.2 * var(--s) * 1px);
	line-height: 1.5;
	text-align: left;
	white-space: normal;
	overflow-wrap: break-word;

	color: #2b251d;
	background: #f4efe3;
	border: 1px solid rgba(0, 0, 0, .38);
	border-radius: 3px;
	box-shadow: 0 6px 16px rgba(0, 0, 0, .5), 0 1px 0 rgba(255, 255, 255, .7) inset;

	pointer-events: none;
	opacity: 0;
	transition: opacity .2s ease, transform .2s ease;
	transform-style: flat;   /* 不参与 3D，否则会跟着头部一起转 */
	z-index: 70;
}

.mc-fig .mc-bubble.is-on {
	opacity: 1;
}

/* 小尾巴：一个转了 45° 的方块，正好接在气泡下沿 */
.mc-fig .mc-bubble::after {
	content: "";
	position: absolute;
	left: 50%;
	bottom: -4px;
	width: 7px;
	height: 7px;
	margin-left: -4px;
	background: #f4efe3;
	border-right: 1px solid rgba(0, 0, 0, .38);
	border-bottom: 1px solid rgba(0, 0, 0, .38);
	transform: rotate(45deg);
}

/* 名字标签在气泡显示时让开一点，别和气泡的下沿挤在一起 */
.mc-fig.is-greeting span {
	opacity: .55;
}
