:root{
  --bg1:#fff4e0; --bg2:#ffe1ec; --ink:#3a2b22;
  --p1:#2f6f5e; --p2:#e0759b;            /* 玩家1/2 制服色（鬼灭风） */
  --hair1:#17171f; --hair2:#3a2747;      /* 头发色 */
  --skin:#ffe3cb; --skin-sh:#e8b58e;
  --collar:#16201d; --tie1:#d23b3b; --tie2:#c64f86;
  --gold:#ffce3a; --danger:#ff5252; --table:#c98a4b; --lid:#9b6b3e;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  font-family:"PingFang SC","Microsoft YaHei","Comic Sans MS",system-ui,sans-serif;
  color:var(--ink);
  background:linear-gradient(135deg,var(--bg1),var(--bg2));
  display:flex;align-items:center;justify-content:center;
  min-height:100vh;overflow:hidden;
}
#app{width:min(960px,96vw);height:min(640px,94vh);position:relative}
.screen{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px}
.hidden{display:none !important}

/* 封面 */
/* 封面整体放大：--ca 是「画」的倍率（两只半脸 + 铃铛 + 电光），--ct 是「字」的倍率。
   为什么要分两个：屏幕是横的（960x640），画是竖的，字又占掉一截高度，
   所以放大到「几乎占满」时，画必须比字多放大一截，才不会有那种小小的、旁边一大片空白的感觉。
   想整体再大一点/小一点：改这两个数就行（画和字会等比跟着变，不会错位）。 */
.cover-card{--ca:1.62;--ct:calc(var(--ca)*.7407);display:flex;flex-direction:column;align-items:center;text-align:center;padding:2px 12px}
/* 铃铛改成自己画的 SVG（原来是 🔔 这个 emoji）。
   为什么换掉：emoji 的字形墨水比它的盒子宽得多 —— 实测这个字形的 advance 有 381px，
   而盒子只有 278px，于是墨水整体被挤到盒子右侧约 60px，看起来就是「铃铛偏右」。
   而且 emoji 字体每台机器都不一样（Windows/macOS 差别很大），换成 SVG 后几何完全可控、
   在任何机器上都居中。盒子仍然保持 148×148，所以构图和电光的坐标一点没变。 */
.cover-bell{width:calc(148px*var(--ca));height:calc(148px*var(--ca));filter:drop-shadow(0 calc(6px*var(--ca)) calc(3px*var(--ca)) rgba(0,0,0,.18));transform-origin:top center;animation:bellSwing 2.4s ease-in-out infinite}
.cover-bell>svg{display:block;width:100%;height:100%;overflow:visible}
@keyframes bellSwing{0%,100%{transform:rotate(-9deg)}50%{transform:rotate(9deg)}}
.cover-title{font-size:calc(58px*var(--ct));margin:calc(2px*var(--ct)) 0 0;color:#d8432f;text-shadow:calc(3px*var(--ct)) calc(3px*var(--ct)) 0 #ffd28a;letter-spacing:calc(6px*var(--ct))}
.cover-sub{font-size:calc(18px*var(--ct));color:#b07a4a;letter-spacing:calc(4px*var(--ct));margin:calc(2px*var(--ct)) 0 calc(6px*var(--ct))}
/* 封面：铃铛左右各一个「半张脸 + 半个身子」的怒气角色，互相瞪着 —— 出对战感。
   盒子 130 宽、角色放在 left:13（角色本身 104 宽），所以角色正中线 = 65px；
   clip-path 从 65px 处竖切一刀 → 正好切在脸的正中间，只露朝铃铛的那半边。
   右边那个用 scaleX(-1) 做镜像，共用同一套几何，保证左右完全对称。 */
.cover-vs{position:relative;display:flex;align-items:flex-end;justify-content:center;gap:calc(78px*var(--ca))}
/* 盒子 130 宽，clip-path 从中线切一刀只留靠铃铛的那半张脸，
   被切掉的 65px 用负外边距推到容器外 —— 于是 .cover-vs 的左右边缘
   就是两张脸的中线，画面横着铺满，不再白白空掉 130px。 */
.cover-fighter{position:relative;width:calc(130px*var(--ca));height:calc(170px*var(--ca));clip-path:inset(0 0 0 calc(65px*var(--ca)))}
.cover-fighter.left{margin-left:calc(-65px*var(--ca))}
.cover-fighter.right{margin-right:calc(-65px*var(--ca))}
.cover-fighter.right{transform:scaleX(-1)}
.cover-fighter .char{position:absolute;left:calc(13px*var(--ca));bottom:0;transform-origin:bottom left;animation:coverLean 2.8s ease-in-out infinite}
.cover-fighter.right .char{animation-delay:-1.4s}   /* 错开半拍：像两个人你推我一下、我推你一下 */
@keyframes coverLean{0%,100%{transform:translateX(0) scale(var(--ca,1))}50%{transform:translateX(calc(6px*var(--ca))) scale(var(--ca,1))}}
/* 漫画里的怒气标记（💢），不是加号 */
.cover-vein{position:absolute;left:calc(96px*var(--ca));top:calc(5px*var(--ca));font-size:calc(22px*var(--ca));line-height:1;z-index:6;filter:drop-shadow(0 1px 1px rgba(120,0,0,.35))}
.cover-vs .cover-bell{margin-bottom:calc(12px*var(--ca))}
/* 两人眼中迸出的电光，在正中线对撞 —— 参考「电光对峙」氛围图。
   要点是「雾状电流」而不是硬折线：每股都由 4 层叠出来
   （高斯模糊的彩色外晕 → 有颜色的电流本体 → 亮层 → 会流动的白热芯），
   还带细须分叉和散落的火花点，越靠近碰撞点越白。
   左蓝右红；坐标固定在 viewBox 360×170（正好等于 .cover-vs 的实际尺寸），
   y=54 永远压住两人的眼睛，x=78 / 282 是眼睛、x=180 是正中线。
   这条 SVG 由 tools/gen-fx.js 生成，改形状请改脚本再跑一次，不要手改。 */
/* 电光层：左/右各往外撑 65px（= 被裁掉的那半张脸），
   这样 SVG 的 482 宽坐标系和原构图 1:1 对齐，电光起点仍然钉在瞳孔上。
   高度跟着 .cover-vs，preserveAspectRatio="none" 下 x/y 缩放比一致 → 不变形。 */
.cover-fx{position:absolute;left:calc(-65px*var(--ca));right:calc(-65px*var(--ca));top:0;bottom:0;width:auto;height:auto;z-index:9;pointer-events:none;overflow:visible}
.cover-fx path{fill:none;stroke-linecap:round;stroke-linejoin:round}
/* 闪电粗细。Mia 反馈「太粗了」——整组按 ~0.62 等比收细，层与层的粗细比例保持不变，
   否则会破坏「外晕 ≫ 电流本体 ≫ 白热芯」这个层次，变成一堆等粗面条。 */
.cover-fx .f-haze{stroke-width:3.3;opacity:.24;filter:url(#fxHaze)}
.cover-fx .f-haze-b{stroke-width:1.45;opacity:.24;filter:url(#fxHaze)}
.cover-fx .f-mid{stroke-width:1.35;opacity:.95;filter:url(#fxHazeS)}
.cover-fx .f-mid-b{stroke-width:.78;opacity:.85;filter:url(#fxHazeS)}
.cover-fx .f-bright{stroke-width:1.1;opacity:1;filter:url(#fxSoft);animation:fxFlicker .55s steps(2,end) infinite}
.cover-fx .f-hair{stroke-width:.62;opacity:.75;filter:url(#fxSoft)}
.cover-fx .f-core{stroke-width:.53;stroke-dasharray:15 10;animation:fxFlow .42s linear infinite}
.cover-fx .f-surge{stroke-width:1;opacity:.9;stroke-dasharray:26 170;animation:fxSurge 1.7s linear infinite}
.cover-fx .fx-side.left .f-haze,.cover-fx .fx-side.left .f-haze-b{stroke:#2f6fe0}
.cover-fx .fx-side.left .f-mid,.cover-fx .fx-side.left .f-mid-b{stroke:url(#gBlueMid)}
.cover-fx .fx-side.left .f-bright{stroke:#4fa0ff}
.cover-fx .fx-side.left .f-hair{stroke:#7fc0ff}
.cover-fx .fx-side.left .f-core{stroke:url(#gBlueCore)}
.cover-fx .fx-side.right .f-haze,.cover-fx .fx-side.right .f-haze-b{stroke:#d8342a}
.cover-fx .fx-side.right .f-mid,.cover-fx .fx-side.right .f-mid-b{stroke:url(#gRedMid)}
.cover-fx .fx-side.right .f-bright{stroke:#ff7050}
.cover-fx .fx-side.right .f-hair{stroke:#ff9a80}
.cover-fx .fx-side.right .f-core{stroke:url(#gRedCore)}
.cover-fx .f-crackle{stroke-width:.68;stroke-dasharray:5 4;opacity:.8;filter:url(#fxSoft);animation:fxCrackle .3s steps(3,end) infinite}
.cover-fx .fx-side.left .f-crackle{stroke:#cfe6ff}
.cover-fx .fx-side.right .f-crackle{stroke:#ffd8c8}
.cover-fx .f-surge{stroke:#fff}
@keyframes fxCrackle{0%{opacity:.75}50%{opacity:1}100%{opacity:.6}}
.cover-fx .fx-dot{stroke:none;animation:fxTwinkle 1.5s ease-in-out infinite}
.cover-fx .fx-side.left .fx-dot{fill:#cfe6ff}
.cover-fx .fx-side.right .fx-dot{fill:#ffd6c8}
.cover-fx .fx-sparks circle{fill:#fff;stroke:none;animation:fxTwinkle 1.1s ease-in-out infinite}
/* 中央爆闪：白色光心 + 四射光刺 + 火花（落在两眼中线、铃铛顶上） */
.cover-fx .fx-burst{transform-box:fill-box;transform-origin:50% 50%;animation:fxBurstPulse .66s ease-in-out infinite}
.cover-fx .fx-coreball{filter:drop-shadow(0 0 5px #fff) drop-shadow(0 0 13px #bcd6ff)}
@keyframes fxFlow{to{stroke-dashoffset:-25}}
@keyframes fxSurge{to{stroke-dashoffset:-196}}
@keyframes fxFlicker{0%,100%{opacity:.95}45%{opacity:.55}}
@keyframes fxTwinkle{0%,100%{opacity:.2}50%{opacity:1}}
@keyframes fxBurstPulse{0%,100%{transform:scale(.9);opacity:.9}50%{transform:scale(1.1);opacity:1}}
/* 封面专用怒气表情：眉毛压到眼睛上 + 眯眼 + 瞳孔狠瞪着对面 + 板着脸（嘴抿成一条直线） */
.cover-fighter .char .brow{top:18px;width:20px;height:7px}
.cover-fighter .char .brow.l{left:7px;transform:rotate(30deg)}
.cover-fighter .char .brow.r{right:7px;transform:rotate(-30deg)}
.cover-fighter .char .eye{width:23px;height:21px;border-top-width:5px;box-shadow:inset 0 -4px 3px rgba(0,0,0,.1),inset 0 9px 0 -2px rgba(0,0,0,.36)}
.cover-fighter .char .pupil{width:12px;height:14px;left:68%;top:58%}
.cover-fighter .char .mouth{width:15px;height:0;bottom:6px;border:0;border-bottom:3.5px solid #8a3a22;border-radius:0;background:none}
.cover-rule{font-size:calc(18px*var(--ct));font-weight:800;color:#5a3b22;background:#fff;border:calc(3px*var(--ct)) solid #ffd0a0;border-radius:calc(16px*var(--ct));padding:calc(7px*var(--ct)) calc(16px*var(--ct));margin:calc(4px*var(--ct)) 0 calc(10px*var(--ct));box-shadow:0 calc(6px*var(--ct)) 0 #f0c89a}
.start-btn{font-size:calc(20px*var(--ct));font-weight:800;color:#fff;background:linear-gradient(180deg,#ff8a5b,#ff6b3d);border:none;border-radius:calc(18px*var(--ct));padding:calc(11px*var(--ct)) calc(34px*var(--ct));cursor:pointer;box-shadow:0 calc(6px*var(--ct)) 0 #d8502a;transition:transform .1s,box-shadow .1s}
.start-btn:active{transform:translateY(3px);box-shadow:0 3px 0 #d8502a}

/* -------- 菜单 -------- */
/* 菜单在小屏上会超过一屏（标题 + 账号 + 三种模式 + 无尽 + 声音/难度 + 玩法）
   → 允许它自己滚动。⚠️ 这里必须用 .menu-card{margin:auto} 而不是靠 .screen 的
   justify-content:center：内容比容器高时 auto 外边距会自动归零、卡片从顶部排下来，
   标题才滚得到；用 center 则顶部被切掉、而且滚不上去（经典 flex 居中坑）。 */
#menu{overflow-y:auto;overflow-x:hidden;justify-content:flex-start}
#menu .menu-card{margin:auto}
.menu-card{
  background:#fff;border-radius:26px;padding:26px 30px;width:min(620px,92vw);
  box-shadow:0 16px 40px rgba(180,120,60,.25);text-align:center;
}
.menu-card h1{font-size:40px;letter-spacing:2px}
.sub{color:#a07a5c;margin:4px 0 18px}
.modes{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-bottom:10px}
.mode-btn{
  cursor:pointer;border:none;border-radius:18px;padding:18px 14px;width:150px;
  background:linear-gradient(180deg,#fff,#fff3da);box-shadow:0 6px 0 #e9c98f;
  font-size:16px;font-weight:700;color:var(--ink);transition:transform .08s;
  display:flex;flex-direction:column;align-items:center;gap:6px;
}
.mode-btn span{font-size:15px}
.mode-btn:hover{transform:translateY(-3px)}
.mode-btn:active{transform:translateY(3px);box-shadow:0 2px 0 #e9c98f}
/* 无尽模式：单独站一行、更宽更烫手一点（它是"挑战"不是普通对局） */
.endless-btn{
  width:100%;flex-direction:row;gap:10px;margin-top:12px;
  background:linear-gradient(180deg,#ffd08a,#ffab52);box-shadow:0 6px 0 #d3801f;
  color:#5a2c00;font-size:17px;
}
.endless-btn span{font-size:16px}
.endless-btn:hover{transform:translateY(-3px)}
.endless-btn:active{transform:translateY(3px);box-shadow:0 2px 0 #d3801f}
#online-setup{margin:6px 0 4px}
.tip{font-size:13px;color:#8a6a4c;margin-bottom:8px}
.online-row{display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
.online-row input{padding:9px 12px;border:2px solid #e6c79a;border-radius:12px;font-size:15px;width:140px;text-align:center}
.online-row button,.go-btns button,#btn-back,.mode-btn{
  cursor:pointer;
}
.online-row button,#btn-back,#btn-again,#btn-menu,#btn-music{
  background:var(--p1);color:#fff;border:none;border-radius:12px;padding:9px 16px;font-weight:700;font-size:14px;
}
.online-row button:hover,#btn-back:hover,#btn-again:hover,#btn-menu:hover,#btn-music:hover{filter:brightness(1.07)}
#online-msg{font-size:13px;color:var(--danger);min-height:18px;margin-top:8px;font-weight:700}
.rules{margin-top:16px;text-align:left;background:#fffaf0;border-radius:16px;padding:14px 18px;font-size:13.5px;line-height:1.7}
.rules h3{font-size:15px;margin-bottom:6px}
.rules ul{padding-left:18px}
.rules b{color:var(--danger)}
/* 声音选择 */
.voice-row{margin-top:14px;display:flex;align-items:center;justify-content:center;gap:8px;flex-wrap:wrap}
.voice-label{font-size:14px;font-weight:700;color:#8a5a3c}
.opt-btn{font-family:inherit;font-size:14px;font-weight:700;color:#8a5a3c;background:#fff;border:2px solid #f0cfa0;border-radius:20px;padding:5px 16px;cursor:pointer;transition:all .12s;min-width:42px}
.opt-btn:hover{transform:translateY(-2px)}
.opt-btn.active{background:var(--gold);border-color:#e0a800;color:#5a3a12;box-shadow:0 3px 0 #e0a800}
/* 账号：名字框在封面上（先写名字 = 登录，再点开始游戏）；右边挂自己那条最高连胜。
   尺寸跟封面的 --ct 一起缩放，不然封面缩小了名字框还老大一个。 */
.cover-user{position:relative;display:flex;align-items:center;justify-content:center;gap:calc(8px*var(--ct));flex-wrap:wrap;margin:calc(2px*var(--ct)) 0 calc(15px*var(--ct))}
.cover-user-label{font-size:calc(15px*var(--ct));font-weight:800;color:#8a5a3c}
.cover-user input{font-family:inherit;font-weight:800;font-size:calc(16px*var(--ct));color:#8a5a3c;text-align:center;
  width:calc(150px*var(--ct));padding:calc(7px*var(--ct)) calc(12px*var(--ct));
  border:calc(3px*var(--ct)) solid #eed3a8;border-radius:calc(14px*var(--ct));background:#fffdf6}
.cover-user input::placeholder{color:#c9b193;font-weight:700}
.cover-user input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 calc(3px*var(--ct)) rgba(255,196,88,.42)}
.name-best{font-size:calc(13px*var(--ct));font-weight:800;color:#c9631c;background:#fff3dd;
  border:calc(2px*var(--ct)) solid #ffe0b0;border-radius:calc(14px*var(--ct));padding:calc(4px*var(--ct)) calc(12px*var(--ct));white-space:nowrap}
/* 没写名字就点开始 → 框抖一下、红星提示（文案见 warnNeedName()） */
.cover-user.need input{border-color:#ff6b5b;box-shadow:0 0 0 calc(3px*var(--ct)) rgba(255,107,91,.32)}
.name-best.warn{color:#d8432f;background:#ffeceb;border-color:#ffc9c4}
.cover-user.shake{animation:nameShake .4s}
@keyframes nameShake{0%,100%{transform:translateX(0)}18%{transform:translateX(calc(-8px*var(--ct)))}36%{transform:translateX(calc(7px*var(--ct)))}54%{transform:translateX(calc(-5px*var(--ct)))}72%{transform:translateX(calc(3px*var(--ct)))}}
.name-board{margin:2px 0 10px;font-size:12.5px;color:#8a6a4c;text-align:center;line-height:1.7}
.name-board b{color:#c9631c}

/* -------- 状态栏 -------- */
#status{width:min(820px,94vw);text-align:center}
#turn-banner{font-size:26px;font-weight:800}
#hint{font-size:15px;color:#8a6a4c;margin:4px 0 8px;min-height:20px}
#timer-wrap{height:14px;background:#ffe3c2;border-radius:10px;overflow:hidden;width:100%}
#timer-bar{height:100%;width:100%;background:linear-gradient(90deg,#7be07b,#ffd24a);transition:width .08s linear}
#timer-bar.danger{background:linear-gradient(90deg,#ff8a5b,var(--danger))}
/* -------- 无尽模式的「连胜 combo」条（只在无尽模式显示） -------- */
#combo-badge{
  display:inline-block;margin:2px 0 6px;padding:3px 18px;border-radius:20px;
  font-weight:900;font-size:16px;color:#fff;letter-spacing:.5px;
  background:linear-gradient(180deg,#ff9a3c,#ff5e2b);
  box-shadow:0 4px 0 #c93f16,0 0 18px rgba(255,120,40,.5);
  transform-origin:50% 50%;
}
#combo-badge b{font-size:22px;margin-left:3px;vertical-align:-1px}
/* 难度爬升的小字（⚙ 难度 3/5 · 每步 1.5s）：跟在连胜数后面，不抢眼但要看得见 */
#combo-lv{font-style:normal;font-size:12.5px;font-weight:800;opacity:.94;margin-left:9px;letter-spacing:.2px;vertical-align:1px}
@keyframes comboPop{0%{transform:scale(1)}35%{transform:scale(1.32) rotate(-3deg)}100%{transform:scale(1)}}
#combo-badge.pop,#combo-badge.lvup{animation:comboPop .45s cubic-bezier(.34,1.56,.5,1)}
/* 无尽模式里「/ 5」的封顶没意义（电脑永远打不倒）——藏掉它，数字改用连胜数 */
.mode-endless .badge-cap{display:none}
.mode-endless #player-1 .slap-badge::before{content:"🔥 "}
#go-sub b{color:#e2601c;font-size:120%}

/* -------- 房间背景（在角色身后） -------- */
.room{position:absolute;inset:0;z-index:0;overflow:hidden;border-radius:18px}
.room svg{position:absolute;inset:0;width:100%;height:100%;display:block}
/* 房间里的元素都在背景之上；但浮层（回放标签/认输台词/认输按钮）必须能自己 absolute 定位 */
#game > *:not(.room):not(#replay-tag):not(#yield-shout):not(#speech):not(#btn-surrender){position:relative;z-index:1}
#status{background:rgba(255,255,255,.5);border-radius:16px;padding:8px 16px;box-shadow:0 4px 0 rgba(200,150,90,.18)}

/* -------- 竞技场 -------- */
.arena{
  display:flex;align-items:flex-end;justify-content:space-between;gap:10px;
  width:min(860px,96vw);height:360px;
}
.side{flex:1;display:flex;justify-content:center;align-items:flex-end;height:100%;position:relative;z-index:1}
.side.active .player{transform:scale(1.06)}
.side.active .name{color:var(--danger);font-weight:800}
.player{position:relative;bottom:-14px;display:flex;flex-direction:column;align-items:center;transition:transform .15s}
.chair{width:80px;height:16px;background:#8a5a32;border-radius:6px;margin-top:-9px;box-shadow:0 10px 0 #6e4626}

/* ===== 卡通小人（少年漫画风，正面朝向玩家） ===== */
.char{position:relative;width:104px;height:154px;filter:drop-shadow(0 6px 5px rgba(0,0,0,.22))}
.char::after{content:"";position:absolute;bottom:0;left:50%;transform:translateX(-50%);width:80px;height:13px;background:rgba(0,0,0,.2);border-radius:50%;filter:blur(2px);z-index:0}
/* 头：尖下巴的漫画脸（正面） */
.head{position:absolute;top:2px;left:23px;width:58px;height:62px;border-radius:52% 52% 46% 46% / 58% 58% 42% 42%;background:radial-gradient(circle at 38% 30%,#fff4e8,var(--skin) 60%,var(--skin-sh));border:2.5px solid #20140d;box-shadow:inset -5px -6px 0 rgba(150,90,50,.2),inset 5px 5px 0 rgba(255,255,255,.45);z-index:3}
/* 头发：少年漫画风“头盔+刘海”，盖住整个脑袋（顶+两侧），中间留脸；
   相对 head 居中（head 宽58，hair 宽62 → left:-2 正好左右各多 2px 包裹），不再偏右 */
.hair{position:absolute;top:-4px;left:-3px;width:64px;height:72px;background:linear-gradient(180deg,#3a3a22 0%,#26261c 34%,var(--hair1) 100%);border:2.5px solid #000;border-radius:52% 52% 44% 44% / 46% 46% 26% 26%;z-index:1;clip-path:polygon(0% 0%,100% 0%,100% 86%,88% 93%,86% 44%,74% 32%,50% 28%,26% 32%,14% 44%,12% 93%,0% 86%)}
.char.p2 .hair{background:linear-gradient(180deg,#5a4470,var(--hair2))}
/* 呆毛（ahoge）玩家1：放 char 上（避免被 hair 的 clip-path 裁掉），居中在头顶 */
.char.p1::before{content:"";position:absolute;top:-14px;left:50%;transform:translateX(-50%) rotate(8deg);width:9px;height:24px;background:var(--hair1);border:2.5px solid #000;border-radius:60% 60% 40% 40%;clip-path:polygon(0 100%,25% 0,75% 0,100% 100%);z-index:4}
/* 侧发尾 玩家2：放在 head 上（不被 hair 裁切），左侧一缕，和玩家1 区分 */
.char.p2 .head::before{content:"";position:absolute;top:26px;left:-9px;width:14px;height:40px;background:var(--hair2);border:2.5px solid #000;border-radius:50% 42% 42% 50%;transform:rotate(-12deg);clip-path:polygon(0 0,100% 14%,84% 100%,0 86%);z-index:1}
/* 大眼睛：粗上眼睑 + 彩色虹膜 + 双高光（日漫标志，正面看人） */
.eye{position:absolute;top:25px;width:21px;height:27px;border-radius:50% 50% 48% 48%;background:#fff;border:2.5px solid #160e08;z-index:3;overflow:hidden;box-shadow:inset 0 -5px 3px rgba(0,0,0,.14),inset 0 6px 0 -3px rgba(0,0,0,.28);transition:all .12s}
.eye.l{left:7px}.eye.r{right:7px}
.pupil{position:absolute;left:50%;top:56%;transform:translate(-50%,-50%);width:16px;height:18px;border-radius:50%;background:radial-gradient(circle at 46% 30%,#aee6ff,#1f6fb0 70%,#0d3f6e);box-shadow:0 0 0 1.5px rgba(0,0,0,.3)}
.pupil::after{content:"";position:absolute;top:2px;left:3px;width:7px;height:7px;border-radius:50%;background:#fff;box-shadow:4px 6px 0 -1px rgba(255,255,255,.8)}
.char.p2 .pupil{background:radial-gradient(circle at 46% 30%,#ffd0ef,#c64f9e 70%,#7a1f5e)}
/* 粗斜眉（少年漫画的坚毅感） */
.brow{position:absolute;top:17px;width:17px;height:6px;border-radius:4px;background:#160e08;z-index:3;transition:all .12s}
.brow.l{left:6px;transform:rotate(15deg)}.brow.r{right:6px;transform:rotate(-15deg)}
/* 玩家1 红色圆耳环（鬼灭风） */
.char.p1 .head::before,.char.p1 .head::after{content:"";position:absolute;top:44px;width:9px;height:9px;border-radius:50%;background:var(--tie1);border:2px solid #7a1f1f;z-index:1}
.char.p1 .head::before{left:-7px}.char.p1 .head::after{right:-7px}
.nose{position:absolute;top:37px;left:50%;transform:translateX(-50%);width:5px;height:4px;border-radius:50%;background:#d9a079;z-index:3}
.blush{position:absolute;top:39px;width:13px;height:9px;border-radius:50%;background:rgba(255,105,140,.55);z-index:3}
.blush.l{left:2px}.blush.r{right:2px}
.mouth{position:absolute;bottom:9px;left:50%;transform:translateX(-50%);width:13px;height:5px;border-bottom:2.5px solid #9c4a2c;border-radius:0 0 11px 11px;z-index:3;transition:all .12s}
/* 身体：日式制服 + V领 + 领结 */
.body{position:absolute;top:60px;left:13px;width:78px;height:66px;border-radius:26px 26px 22px 22px;background:linear-gradient(160deg,rgba(255,255,255,.32),rgba(0,0,0,.14)),var(--p1);border:2.5px solid #20140d;box-shadow:inset -8px -10px 0 rgba(0,0,0,.18),inset 7px 7px 0 rgba(255,255,255,.26);z-index:2;overflow:hidden}
.char.p2 .body{background:linear-gradient(160deg,rgba(255,255,255,.32),rgba(0,0,0,.14)),var(--p2)}
.body::before{content:"";position:absolute;top:1px;left:50%;transform:translateX(-50%);width:0;height:0;border-left:23px solid transparent;border-right:23px solid transparent;border-top:27px solid var(--collar)}
.tie{position:absolute;top:2px;left:50%;transform:translateX(-50%);width:20px;height:56px;z-index:3;background:var(--tie1);clip-path:polygon(35% 0,65% 0,60% 12%,84% 40%,50% 100%,16% 40%,40% 12%)}
.char.p2 .tie{background:var(--tie2)}
.arm{position:absolute;top:68px;width:17px;height:48px;border-radius:9px;background:radial-gradient(circle at 35% 30%,#fff4e8,var(--skin) 60%,var(--skin-sh));border:2.5px solid #20140d;box-shadow:inset -2px -3px 0 rgba(150,90,50,.18);z-index:4}
.arm.left{left:-8px;transform-origin:top center}
.arm.right{right:-8px;transform-origin:top center}
.leg{position:absolute;top:124px;width:19px;height:17px;border-radius:8px 8px 6px 6px;background:radial-gradient(circle at 35% 30%,#fff4e8,var(--skin));border:2.5px solid #20140d;z-index:1}
.leg.left{left:24px}.leg.right{right:24px}
/* 被扇时的尖叫表情：嘴张大成 O、眼睛瞪圆、眉毛上挑。
   ⚠️ bottom 别写大：头只有 62 高，鼻子在 y39..43。
   原来写 bottom:7px + height:18px → 嘴的顶边正好落在 y39，横向又居中，
   于是那个深红色的 O 就**盖在鼻子上**，看着像"鼻子中间一个红圈"。
   前四巴掌看不太出来是因为上面还压着一张红手掌印（z-index:5）挡住了；
   最后一巴掌原来没有手掌印，这个红圈就露出来了。
   现在把嘴放回鼻子底下（y46..60），正常位置。 */
.char.screaming .mouth{width:15px;height:14px;border:2.5px solid #9c4a2c;background:#7a2b2b;border-radius:50%;bottom:4px}
.char.screaming .eye{width:23px;height:29px}
.char.screaming .brow{top:13px}
/* 红手掌印 —— 要一眼看出是「手指 + 手掌」，不是一坨红。
   做法：4 根手指 + 拇指 + 掌心，每块的 fill 和 stroke 用同一个红，
   叠起来就没有内部接缝，读出来是一整只手；手指之间留约 2px 缝才分得开。
   半透明（.72）是故意的：让眼睛和鼻子从印子底下透出来，不然整张脸会被糊掉。
   位置也挪到了脸颊（原来压在鼻子正中间）。
   印在哪半边脸有讲究：打玩家1 的人站在右边 → 印子落在他脸的右半边；打玩家2 的人在左边 → 落在左半边。 */
.redmark{position:absolute;top:20px;left:24px;width:40px;height:45px;opacity:0;transform:scale(.4) rotate(-12deg);transition:opacity .2s,transform .2s;z-index:5}
.char.has-redmark .redmark{opacity:.72;transform:scale(1) rotate(-12deg)}
.char.p1 .redmark{left:auto;right:24px;transform:scale(.4) rotate(12deg)}
.char.p1.has-redmark .redmark{transform:scale(1) rotate(12deg)}
.redmark svg{width:100%;height:100%;display:block;filter:drop-shadow(0 1px 1px rgba(170,0,0,.3))}
.bubble{position:absolute;top:-34px;left:50%;transform:translateX(-50%) scale(0);background:#fff;border:3px solid #ffb3c8;border-radius:14px;padding:2px 10px;font-weight:800;color:var(--danger);opacity:0;transition:transform .15s,opacity .15s;z-index:6;white-space:nowrap}
.char.has-redmark .bubble{transform:translateX(-50%) scale(1);opacity:1}
.name{margin-top:1px;font-weight:700;font-size:14px;line-height:1.1}
.slap-badge{margin-top:1px;background:#fff;border:2px solid #ffd0a0;border-radius:20px;padding:2px 11px;font-weight:800;font-size:13px;color:#c0392b;line-height:1.1}

/* 桌子 + 铃铛 + 盖子 */
.center{flex:0 0 220px;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;position:relative;height:100%;z-index:0}
.table{position:relative;width:170px;height:150px;display:flex;align-items:flex-end;justify-content:center}
.table::before{content:"";position:absolute;bottom:0;width:170px;height:34px;background:var(--table);border-radius:8px;box-shadow:0 12px 0 #9a6838}
.bell{position:absolute;bottom:30px;font-size:62px;z-index:1;filter:drop-shadow(0 4px 2px rgba(0,0,0,.2))}
.lid{position:absolute;bottom:26px;width:120px;height:64px;background:linear-gradient(180deg,#c8915a,var(--lid));border-radius:60px 60px 10px 10px;border:3px solid #6e4626;z-index:2;transition:transform .25s ease,opacity .25s;transform-origin:bottom center}
.lid::after{content:"";position:absolute;top:-10px;left:50%;transform:translateX(-50%);width:18px;height:14px;border-radius:8px 8px 0 0;background:#6e4626}
.table.lid-open .lid{transform:translateY(-78px) rotate(-8deg);opacity:.92}

/* 门（最终巴掌：被扇飞撞出洞） */
.door{position:absolute;bottom:8px;left:50%;transform:translateX(-50%);width:186px;height:272px;background:linear-gradient(180deg,#d2a86e,#a9763f);border:4px solid #6e4626;border-radius:14px;box-shadow:inset 0 0 0 7px rgba(255,255,255,.14),0 10px 20px rgba(0,0,0,.25);z-index:0}
.door::before{content:"";position:absolute;top:156px;right:22px;width:17px;height:17px;border-radius:50%;background:#ffe08a;border:2.5px solid #6e4626}
.door .hole{position:absolute;top:106px;left:50%;transform:translate(-50%,-50%) scale(0);width:126px;height:126px;background:#2b1d13;clip-path:polygon(50% 0,60% 14%,78% 6%,72% 24%,94% 18%,80% 36%,100% 50%,80% 64%,94% 82%,72% 76%,78% 94%,60% 86%,50% 100%,40% 86%,22% 94%,28% 76%,6% 82%,20% 64%,0% 50%,20% 36%,6% 18%,28% 24%,22% 6%,40% 14%);transition:transform .12s ease-out;z-index:2;box-shadow:inset 0 0 0 5px rgba(0,0,0,.5),0 0 0 4px rgba(110,70,38,.7)}
.door.broken .hole{transform:translate(-50%,-50%) scale(1)}
.door .crack{position:absolute;top:106px;left:50%;width:252px;height:252px;background:rgba(255,255,255,.92);clip-path:polygon(50% 0,60% 14%,78% 6%,72% 24%,94% 18%,80% 36%,100% 50%,80% 64%,94% 82%,72% 76%,78% 94%,60% 86%,50% 100%,40% 86%,22% 94%,28% 76%,6% 82%,20% 64%,0% 50%,20% 36%,6% 18%,28% 24%,22% 6%,40% 14%);transform:translate(-50%,-50%) scale(0);opacity:0;z-index:3}
.door.broken .crack{animation:crackBurst .5s ease-out forwards}
@keyframes crackBurst{0%{transform:translate(-50%,-50%) scale(0);opacity:.95}100%{transform:translate(-50%,-50%) scale(1);opacity:0}}

/* 动画：飞出 / 爬回 */
.char.fly{animation:flyOut .5s ease forwards}
@keyframes flyOut{0%{transform:translate(0,0) rotate(0)}100%{transform:translate(var(--fx,40px),-120px) rotate(40deg)}}
.char.climb{animation:climbBack .6s ease}
@keyframes climbBack{0%{transform:translate(var(--fx,40px),-120px) rotate(40deg)}100%{transform:translate(0,0) rotate(0)}}
/* 撞门穿洞：最后一巴掌的输家被打得**横着飞向中间那扇门**，
   脑袋正正撞进洞口（洞就是他撞出来的），再从洞里钻出去（一边穿一边缩小、淡出）。
   --fx / --fy 由 JS 量出来（脑袋中心 → 洞口中心），transform-origin 钉在脑袋中心，
   所以后半段的旋转和缩小都绕着脑袋转，脑袋始终卡在洞口里 —— 这才是「人从洞里穿出去」。
   改这一条之前是 `translate(var(--fx,200px),-150px) rotate(540deg)`：
   y 固定 -150px，人是**从洞的上方**飞出去的，看着像在洞上面凭空钻走，不像撞门。
   60%~76% 之间有个 -18px 的小上抛弧，读起来才像"被打飞出去"而不是平移。 */
@keyframes throughDoor{
  0%  {transform:translate(0,0) rotate(0) scale(1);opacity:1}
  56% {transform:translate(calc(var(--fx,0px) * .56),calc(var(--fy,0px) * .56 - 22px)) rotate(-24deg) scale(1.04);opacity:1}
  76% {transform:translate(var(--fx,0px),var(--fy,0px)) rotate(-6deg) scale(.98);opacity:1}
  86% {transform:translate(calc(var(--fx,0px) * 1.06),calc(var(--fy,0px) * 1.06)) rotate(0deg) scale(.70);opacity:1}
  100%{transform:translate(calc(var(--fx,0px) * 1.10),calc(var(--fy,0px) * 1.10)) rotate(4deg) scale(.34);opacity:0}
}
.char.final-out{transform-origin:52px 33px;animation:throughDoor .62s cubic-bezier(.35,.03,.62,1) forwards;z-index:40}
/* 撞穿门之后：输家整个人「穿」进门里，藏掉。visibility:hidden 比 opacity 稳，
   因为身上还挂着一堆 fill-mode:forwards 的动画，它们会把 opacity 顶回最后一帧。 */
.char.gone{visibility:hidden;opacity:0 !important}
/* 最终巴掌：赢家先整个人跳到中央桌子上（从侧边横移到桌子上方），再蓄力，再大手扇出。
   Mia 反馈「蓄力和超级大手都没看见」——原因有两个：
   ① 原来蓄力只有 0.3 秒、只是轻轻蹲一下，一闪就过去了；② 根本就没画手，只有一根放大的胳膊。
   所以这里把蓄力拉长到 0.9 秒（蹲下去 + 左右发抖），并让手掌在蓄力时就长出来。
   后来又补一条：Mia 说「扇巴掌的人不需要变得那么矮，就是 normal height」——
   于是把蹲的幅度收小（纵向 0.78 → 0.88），并且蓄力末尾自己站起来，
   出手那一刻是正常身高（最后一帧 scale(1,1)，正好接住 finalLunge 的第一帧）。 */
.char.on0{--tx:205px;--ty:44px}
.char.on1{--tx:-205px;--ty:44px}
.char.on-table{animation:climbTable .46s cubic-bezier(.34,1.5,.5,1) forwards}
@keyframes climbTable{0%{transform:translate(0,0)}45%{transform:translate(var(--tx),calc(var(--ty) - 110px))}100%{transform:translate(var(--tx),var(--ty))}}
.char.charge{animation:chargeUp .9s ease forwards}
@keyframes chargeUp{
  0%  {transform:translate(var(--tx),var(--ty)) scale(1,1)}
  18% {transform:translate(var(--tx),calc(var(--ty) + 15px)) scale(1.09,.89)}
  34% {transform:translate(calc(var(--tx) - 4px),calc(var(--ty) + 15px)) scale(1.09,.89)}
  50% {transform:translate(calc(var(--tx) + 4px),calc(var(--ty) + 16px)) scale(1.10,.88)}
  66% {transform:translate(calc(var(--tx) - 4px),calc(var(--ty) + 15px)) scale(1.10,.88)}
  84% {transform:translate(var(--tx),calc(var(--ty) + 5px)) scale(1.04,.96)}   /* 起身 */
  100%{transform:translate(var(--tx),var(--ty)) scale(1,1)}                     /* 站直：正常身高 */
}
/* 出手：憋完整个人朝对手那边扑出去（--lunge 指向对手那一侧）。
   起点接住 chargeUp 的最后一帧（站直），只朝对手压一点身，不再把自己压成小矮人。 */
.char.final-arm{animation:finalLunge .9s cubic-bezier(.25,1.1,.5,1) forwards}
.char.win0.final-arm{--lunge:78px}
.char.win1.final-arm{--lunge:-78px}
@keyframes finalLunge{
  0%  {transform:translate(var(--tx),var(--ty)) scale(1,1)}
  26% {transform:translate(calc(var(--tx) + var(--lunge)),calc(var(--ty) - 6px)) scale(.99,1.03)}
  56% {transform:translate(calc(var(--tx) + var(--lunge)),calc(var(--ty) - 6px)) scale(.99,1.03)}
  100%{transform:translate(var(--tx),var(--ty)) scale(1,1)}
}
.arena.impact{animation:arenaShake .36s ease}
@keyframes arenaShake{0%,100%{transform:translate(0,0)}20%{transform:translate(-8px,3px)}40%{transform:translate(8px,-3px)}60%{transform:translate(-6px,2px)}80%{transform:translate(5px,-2px)}}

/* 扇人者伸手去打（不用悬空扇）：赢家用手臂伸向对手挥一下 */
.char.win0 .arm.right{transform-origin:top center;animation:swipeR .42s ease}
.char.win1 .arm.left{transform-origin:top center;animation:swipeL .42s ease}
@keyframes swipeR{0%{transform:rotate(0) translateX(0)}30%{transform:rotate(-78deg) translateX(10px)}55%{transform:rotate(-64deg) translateX(14px)}100%{transform:rotate(0)}}
@keyframes swipeL{0%{transform:rotate(0) translateX(0)}30%{transform:rotate(78deg) translateX(-10px)}55%{transform:rotate(64deg) translateX(-14px)}100%{transform:rotate(0)}}
/* 手掌：平时藏起来（scale 0），只有"出手的那只手"在蓄力/出手时才长出来 */
.arm .palm{position:absolute;left:50%;top:100%;width:44px;height:50px;margin-top:-9px;pointer-events:none;opacity:0;transform:translateX(-50%) scale(0);transform-origin:top center;transition:opacity .18s ease,transform .18s ease}
.char.win0.charge .arm.right .palm,.char.win0.final-arm .arm.right .palm,
.char.win1.charge .arm.left .palm,.char.win1.final-arm .arm.left .palm{opacity:1;transform:translateX(-50%) scale(1)}
/* 最终巴掌：跳上桌后自己的大手（手臂放大 2.05 倍 + 手掌）扇出 */
.char.win0.final-arm .arm.right{animation:swipeRbig .9s ease forwards}
.char.win1.final-arm .arm.left{animation:swipeLbig .9s ease forwards}
@keyframes swipeRbig{0%{transform:rotate(0) scale(1)}30%{transform:rotate(-84deg) scale(2.05) translateX(18px)}58%{transform:rotate(-72deg) scale(2.05) translateX(24px)}100%{transform:rotate(0) scale(1)}}
@keyframes swipeLbig{0%{transform:rotate(0) scale(1)}30%{transform:rotate(84deg) scale(2.05) translateX(-18px)}58%{transform:rotate(72deg) scale(2.05) translateX(-24px)}100%{transform:rotate(0) scale(1)}}

/* 小效果 */
.table.flash{animation:flash .25s}
@keyframes flash{0%,100%{filter:none}50%{filter:brightness(1.4)}}
.lid.shake{animation:shake .2s}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-6px)}75%{transform:translateX(6px)}}

#log{height:22px;font-size:14px;color:#8a6a4c;font-weight:700;min-height:22px}
#controls{display:flex;gap:16px;font-size:14px;color:#6e5238;flex-wrap:wrap;justify-content:center}
#controls b{display:inline-block;background:#fff;border:2px solid #ffd0a0;border-radius:8px;padding:1px 8px;margin-right:3px}
/* 两人同设备：一人一组按键卡片，避免换行时两组混在一起 */
#controls .ctl-group{display:flex;align-items:center;gap:6px;background:#fff7ea;border:2px solid #ffe1c2;border-radius:12px;padding:5px 10px}
#controls .ctl-group em{font-style:normal;font-weight:800;color:#8a5a3c;white-space:nowrap}
#controls .ctl-group b{margin-right:0}
#btn-back{margin-top:4px}

/* 认输按钮（好友联机 / 跟电脑打）：点一下就生效（不要点两次，关键时刻别让人分心） */
#btn-surrender{position:absolute;top:12px;left:14px;z-index:60;background:#fff;color:#c0392b;border:2.5px solid #ffb3c8;border-radius:999px;padding:8px 16px;font-family:inherit;font-weight:800;font-size:14px;cursor:pointer;box-shadow:0 5px 14px rgba(0,0,0,.16)}
#btn-surrender:hover{background:#fff5f8}

/* ===== 认输：从椅子上下来 → 跪在地上 → 给赢家磕头 ===== */
.char.kowtow{transform-origin:bottom center;animation:kowtow 2.6s ease-in-out forwards;z-index:20}
@keyframes kowtow{
  0%  {transform:translate(0,0) scale(1,1) rotate(0)}
  12% {transform:translate(0,16px) scale(.95,.86) rotate(0)}
  24% {transform:translate(0,26px) scale(.9,.72) rotate(0)}
  34% {transform:translate(0,24px) scale(.88,.68) rotate(var(--bow,28deg))}
  44% {transform:translate(0,26px) scale(.9,.72) rotate(0)}
  54% {transform:translate(0,24px) scale(.88,.68) rotate(var(--bow,28deg))}
  64% {transform:translate(0,26px) scale(.9,.72) rotate(0)}
  74% {transform:translate(0,24px) scale(.88,.68) rotate(var(--bow,28deg))}
  88% {transform:translate(0,26px) scale(.9,.72) rotate(0)}
  100%{transform:translate(0,26px) scale(.9,.72) rotate(var(--bow,28deg))}
}
/* 认输台词（大喊）：做成「带尖角的气泡」，尖角朝着认输的那个人，
   所以一眼就知道这句话是谁说的 —— 不再是悬在正中间的无主句。
   几何：两人脑袋在 #game 里的位置是 26%（左）/ 74%（右），
   气泡就锚在那儿，尖角离锚边 34px、正对脑袋顶；
   左右两个版本共用同一套数字，只是把 left/right 换一下。
   尖角用两个三角形叠出来（外金框 .ys 会被压掉一条缝）：
   ::before 是金色大三角 = 描边，::after 是白色小三角 = 填色，
   两者都比气泡底边高 4px，好盖住边框、接缝才连得上。 */
#yield-shout{--ys-tail:34px;position:absolute;bottom:55%;z-index:120;background:#fff;border:4px solid var(--gold);border-radius:22px;padding:13px 26px;text-align:center;box-shadow:0 14px 34px rgba(0,0,0,.3);max-width:min(560px,88vw);pointer-events:none}
#yield-shout.ys-left{left:calc(26% - var(--ys-tail));right:auto;transform-origin:var(--ys-tail) 100%}
#yield-shout.ys-right{right:calc(26% - var(--ys-tail));left:auto;transform-origin:calc(100% - var(--ys-tail)) 100%}
#yield-shout::before,#yield-shout::after{content:"";position:absolute;top:calc(100% - 4px);width:0;height:0;border-style:solid;border-color:transparent}
#yield-shout::before{border-width:24px;border-top-color:var(--gold)}
#yield-shout::after{border-width:16px;border-top-color:#fff}
#yield-shout.ys-left::before{left:calc(var(--ys-tail) - 24px)}
#yield-shout.ys-left::after{left:calc(var(--ys-tail) - 16px)}
#yield-shout.ys-right::before{right:calc(var(--ys-tail) - 24px)}
#yield-shout.ys-right::after{right:calc(var(--ys-tail) - 16px)}
/* 气泡是从说话者头顶「弹」出来的：缩放原点定在尖角上 */
#yield-shout.show{animation:yieldPop .34s ease both}
@keyframes yieldPop{0%{transform:scale(.7);opacity:0}100%{transform:scale(1);opacity:1}}
#yield-shout .ys-who{font-size:15px;font-weight:800;color:#c0392b;margin-bottom:5px}
#yield-shout .ys-line{font-size:21px;font-weight:800;color:#5a3b22;letter-spacing:1px;line-height:1.4}

/* ===== 最后一巴掌之后的小剧场：输家穿进门里、只剩一张脸卡在洞口求饶 → 赢家哈哈大笑 + 点头 ===== */

/* 门里那张脸。.peek 跟 .door .hole 共用同一套尺寸和同一个星形 clip-path：
   脸是被洞口裁出来的，所以看着是「从洞里露出来」，而不是贴在门上。
   洞口底子很暗（#241710），所以爆炸头除了暖色描边、再加一圈外发光，
   否则深色头发糊在深色洞里，什么都看不见。 */
.peek{position:absolute;top:106px;left:50%;width:126px;height:126px;transform:translate(-50%,-50%) scale(0);transform-origin:50% 50%;opacity:0;z-index:4;pointer-events:none;
  clip-path:polygon(50% 0,60% 14%,78% 6%,72% 24%,94% 18%,80% 36%,100% 50%,80% 64%,94% 82%,72% 76%,78% 94%,60% 86%,50% 100%,40% 86%,22% 94%,28% 76%,6% 82%,20% 64%,0% 50%,20% 36%,6% 18%,28% 24%,22% 6%,40% 14%)}
/* 洞口内圈压一圈暗影，脸像是嵌在洞里、往里陷了一点 */
.peek::after{content:"";position:absolute;inset:0;box-shadow:inset 0 0 0 5px rgba(0,0,0,.45),inset 0 0 16px rgba(0,0,0,.5)}
.door.show-peek .peek{animation:peekPop .5s cubic-bezier(.34,1.56,.5,1) forwards}
@keyframes peekPop{0%{transform:translate(-50%,-50%) scale(.3);opacity:0}55%{opacity:1}100%{transform:translate(-50%,-50%) scale(1);opacity:1}}
/* 只留脑袋：身体 / 胳膊 / 腿 / 红掌印 / 气泡全藏掉，再把脑袋放大到塞满洞口。
   transform-origin 定在脑袋中心（104×154 的盒子里，脑袋中心在 52,33），
   这样缩放不会把脸挪偏；left/top 让脑袋中心正好落在洞口正中间（63,63）。
   头发就用角色自己那顶（.hair，p1 深棕 / p2 紫），Mia 说不要那个夸张的爆炸头了。 */
.peek .char{position:absolute;left:11px;top:30px;transform-origin:52px 33px;transform:scale(1.32);filter:none}
.peek .char::after{display:none}
.peek .char.p1::before{display:none}
.peek .char>.body,.peek .char>.arm,.peek .char>.leg,.peek .char>.redmark,.peek .char>.bubble{display:none}
.peek .char .head::before,.peek .char .head::after{display:none}
/* 洞口底子很暗（#2b1d13），头发原色（#3a3a22→#17171f）几乎整块糊进去，
   所以门里这顶头发提亮一档：上面偏橄榄、下面偏深棕，脸被头发包住的轮廓才看得出来。 */
.peek .char .hair{background:linear-gradient(180deg,#6f6743 0%,#4c4830 38%,#33301f 100%)}
.peek .char.p2 .hair{background:linear-gradient(180deg,#9b7fb4 0%,#6e5589 38%,#4a3a5e 100%)}
/* 两颗眼泪，左右各一颗、错开半拍往下滚（优先级要压过下面的 .char.plead .cry） */
.peek .char.plead .cry.r{left:auto;right:6px;animation-delay:.5s}
/* 求饶脸：八字眉（眉尾往下挂）+ 泪眼 + 瘪着的嘴，配一颗往下滚的眼泪 */
.cry{display:none}
.char.plead .brow{top:21px;height:6px}
.char.plead .brow.l{transform:rotate(-28deg)}
.char.plead .brow.r{transform:rotate(28deg)}
.char.plead .eye{height:24px;border-top-width:4px}
.char.plead .pupil{width:13px;height:15px;top:60%}
.char.plead .mouth{width:14px;height:11px;border:0;background:#9c4a2c;border-radius:50% 50% 44% 44%;bottom:4px}
.char.plead .cry{display:block;position:absolute;top:50px;left:6px;width:8px;height:11px;background:#7fd2ff;border-radius:50% 50% 50% 50%/62% 62% 38% 38%;box-shadow:0 0 0 1.5px rgba(30,90,140,.3);animation:cryFall 1.15s ease-in infinite}
@keyframes cryFall{0%{transform:translateY(0) scale(.6);opacity:0}22%{transform:translateY(0) scale(1);opacity:1}100%{transform:translateY(17px) scale(.85);opacity:0}}
/* 赢家的哈哈大笑：眼睛变成两道弯弯的「^ ^」，嘴巴张成大笑，牙露一条白 */
.char.laugh .eye{top:30px;height:12px;background:transparent;border:0;border-top:5px solid #160e08;border-radius:60% 60% 0 0/100% 100% 0 0;box-shadow:none}
.char.laugh .pupil{display:none}
.char.laugh .brow{top:12px;height:5px}
.char.laugh .brow.l{transform:rotate(-16deg)}
.char.laugh .brow.r{transform:rotate(16deg)}
.char.laugh .mouth{width:28px;height:20px;border:0;background:#7a2a1a;border-radius:9px 9px 15px 15px;bottom:3px;overflow:hidden}
.char.laugh .mouth::after{content:"";position:absolute;left:0;right:0;top:0;height:6px;background:#fff}
/* 哈哈大笑时脑袋一点一点 */
.char.nod .head{animation:nodHead .92s ease-in-out infinite}
@keyframes nodHead{
  0%,100%{transform:rotate(0) translateY(0)}
  22%{transform:rotate(-6deg) translateY(-3px)}
  48%{transform:rotate(5deg) translateY(2px)}
  74%{transform:rotate(-4deg) translateY(-2px)}
}
/* 说话气泡（求饶 / 哈哈 共用）：尖角正对着说话的人，位置由 JS 实测设定 */
#speech{position:absolute;z-index:120;background:#fff;border:4px solid var(--gold);border-radius:22px;padding:12px 26px;text-align:center;box-shadow:0 14px 34px rgba(0,0,0,.3);max-width:min(620px,86vw);pointer-events:none;transform:translateX(-50%);transform-origin:50% 100%}
#speech::before,#speech::after{content:"";position:absolute;top:calc(100% - 4px);width:0;height:0;border-style:solid;border-color:transparent}
#speech::before{border-width:24px;border-top-color:var(--gold);left:calc(50% + var(--sp-tail,0px) - 24px)}
#speech::after{border-width:16px;border-top-color:#fff;left:calc(50% + var(--sp-tail,0px) - 16px)}
#speech.show{animation:speechPop .34s ease both}
@keyframes speechPop{0%{transform:translateX(-50%) scale(.7);opacity:0}100%{transform:translateX(-50%) scale(1);opacity:1}}
#speech .sp-line{font-size:22px;font-weight:800;color:#5a3b22;letter-spacing:1px;line-height:1.4}
#speech.plead{border-color:#7fbcf5}
#speech.plead::before{border-top-color:#7fbcf5}
#speech.plead .sp-line{color:#2a5f92}

/* 慢动作回放（最后一巴掌）：把竞技场推近 + 慢动作重演那一击 */
.arena{transition:transform .45s ease}
.arena.replay{transform:scale(1.16);transform-origin:50% 62%}
.arena.replay.impact{animation:arenaShakeZoom .36s ease}
@keyframes arenaShakeZoom{0%,100%{transform:scale(1.16) translate(0,0)}20%{transform:scale(1.16) translate(-7px,3px)}40%{transform:scale(1.16) translate(7px,-3px)}60%{transform:scale(1.16) translate(-5px,2px)}80%{transform:scale(1.16) translate(4px,-2px)}}
/* 慢动作回放里同一段「撞门穿洞」，只是拉长到 1.05s（关键帧和 final-out 共用 throughDoor） */
.char.replay-fly{transform-origin:52px 33px;animation:throughDoor 1.05s cubic-bezier(.35,.03,.62,1) forwards;z-index:40}
#replay-tag{position:absolute;top:12px;right:14px;z-index:60;background:rgba(24,12,6,.86);color:#ffe8a3;border:2px solid #ffce3a;border-radius:999px;padding:6px 16px;font-weight:800;font-size:14px;letter-spacing:1px;box-shadow:0 6px 16px rgba(0,0,0,.3);animation:replayBlink 1s steps(2,end) infinite}
@keyframes replayBlink{0%,100%{opacity:1}50%{opacity:.5}}
/* 结束遮罩 */
.overlay{position:absolute;inset:0;background:rgba(40,25,15,.55);display:flex;align-items:center;justify-content:center;z-index:100}
.overlay .card{background:#fff;border-radius:24px;padding:30px 40px;text-align:center;box-shadow:0 20px 50px rgba(0,0,0,.3);animation:pop .3s ease}
@keyframes pop{0%{transform:scale(.7);opacity:0}100%{transform:scale(1);opacity:1}}
.trophy{font-size:54px}
#go-title{font-size:30px;margin:6px 0}
#go-sub{color:#8a6a4c;margin-bottom:16px}
.go-btns{display:flex;gap:12px;justify-content:center}

/* ==================== 右上角语言开关（双语版专属） ====================
   压在四个 .screen 之上（z-index 60）；中文/EN 是"当前语言"高亮。 */
#lang-switch{position:absolute;top:9px;right:11px;z-index:60;display:flex;align-items:center;gap:3px;
  font-size:13px;font-weight:800;user-select:none;background:rgba(255,255,255,.9);
  border:2px solid #ffd0a0;border-radius:14px;padding:3px 6px;box-shadow:0 3px 0 rgba(200,150,90,.22)}
#lang-switch button{font-family:inherit;font-size:13px;font-weight:800;color:#8a5a3c;background:none;
  border:none;border-radius:10px;padding:3px 9px;cursor:pointer;line-height:1.25}
#lang-switch button:hover{background:#fff3dd}
#lang-switch button.active{background:var(--gold);color:#5a3a12;box-shadow:0 2px 0 #e0a800}
#lang-switch .ls-sep{color:#dcbb96;font-weight:700}
@media (max-width:560px){#lang-switch{top:6px;right:7px;font-size:12px;padding:2px 5px}
  #lang-switch button{font-size:12px;padding:2px 7px}}
