/* ============================================================
   ZERO DAM — 零号大坝
   视觉语言：明日方舟·终末地 —— 干净未来工业风
     高调米白底 · 炭黑细描边 · 琥珀黄 accent · 危险斜纹
     角括号 · 等宽数字 · 大量 FUI 悬浮文字
   ============================================================ */

:root{
  --paper:#EDEAE4; --paper-2:#E3DFD7; --paper-3:#D6D1C7;
  --ink:#24262A; --ink-2:#3D4045; --ink-3:#6E7178;
  --amber:#F2B705; --amber-dk:#C08E00;
  --teal:#00A896; --teal-lt:#3FD0C9;
  --alert:#D9482B; --ok:#4E9A3E;
  --line:rgba(36,38,42,.22); --line-2:rgba(36,38,42,.10);
  --glass:rgba(237,234,228,.88); --glass-dark:rgba(28,30,33,.80);
  --shadow:0 2px 10px rgba(20,22,26,.14),0 1px 2px rgba(20,22,26,.10);
  --mono:ui-monospace,"SF Mono","Cascadia Mono",Consolas,monospace;
  --sans:"Inter","Segoe UI",-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;
}

*,*::before,*::after{ box-sizing:border-box; margin:0; padding:0; }
[hidden]{ display:none !important; }
.hidden{ display:none !important; }

html,body{
  height:100%; overflow:hidden; background:#0E0F11; color:var(--ink);
  font-family:var(--sans); -webkit-font-smoothing:antialiased;
  overscroll-behavior:none; -webkit-tap-highlight-color:transparent; user-select:none;
}
#app{ position:fixed; inset:0; }
#view{ position:absolute; inset:0; width:100%; height:100%; display:block; touch-action:none; }

/* ===================== FUI 投影层 ===================== */
#fui-layer{ position:absolute; inset:0; pointer-events:none; overflow:hidden; z-index:20; }
.fui{
  position:absolute; left:0; top:0; will-change:transform;
  font:600 10.5px/1.25 var(--mono); letter-spacing:.09em;
  color:#fff; white-space:nowrap; text-transform:uppercase;
  text-shadow:0 0 10px rgba(0,0,0,.85),0 1px 3px rgba(0,0,0,.95);
  transform-origin:0 0; transition:opacity .18s linear;
}
.fui .fui-k{ color:var(--amber); }
.fui .fui-d{ color:rgba(255,255,255,.62); font-weight:500; }
.fui .fui-ln{
  position:absolute; left:100%; top:50%; width:var(--ln,26px); height:1px; margin-left:5px;
  background:linear-gradient(90deg,rgba(255,255,255,.85),rgba(255,255,255,0));
}
.fui .fui-ln::after{
  content:""; position:absolute; right:0; top:-2px; width:4px; height:4px;
  border:1px solid rgba(255,255,255,.85); transform:rotate(45deg);
}
.fui.hostile,.fui.hostile .fui-k{ color:#FF6A4D; }
/* 警戒状态：未察觉（灰白）→ 搜索中（琥珀）→ 交战中（红）
   颜色是玩家最先读到的信息，所以差异要够大。 */
.fui.alert-idle,.fui.alert-idle .fui-k{ color:#C6CCD2; }
.fui.alert-hunt,.fui.alert-hunt .fui-k{ color:var(--amber); }
.fui.alert-fight,.fui.alert-fight .fui-k{ color:#FF4B32; }
/* 刚刚发现玩家：加一圈扩散的光晕，持续约 1.8s */
.fui.spotted .fui-k{ text-shadow:0 0 10px currentColor, 0 0 22px currentColor; }
.fui.spotted::after{
  content:''; position:absolute; left:-8px; top:-6px; right:-8px; bottom:-6px;
  border:1px solid currentColor; border-radius:2px;
  animation:fuiSpotted .9s ease-out infinite;
  pointer-events:none;
}
@keyframes fuiSpotted{
  from{ transform:scale(.86); opacity:.95 }
  to  { transform:scale(1.25); opacity:0 }
}
/* 收到同伴喊话：短暂的琥珀色描边脉冲。
   和 spotted（自己看到的）区分开 —— 玩家能据此判断
   「是他发现了我」还是「有人通知了他」，这对决策很重要。 */
.fui.shouted .fui-k{ text-shadow:0 0 8px currentColor; }
.fui.shouted::after{
  content:''; position:absolute; left:-6px; top:-4px; right:-6px; bottom:-4px;
  border:1px dashed currentColor; border-radius:2px;
  animation:fuiShouted .5s ease-out 2;
  pointer-events:none;
}
@keyframes fuiShouted{
  from{ opacity:.9 } to{ opacity:.15 }
}

/* ============================================================
   撤离倒计时
   ------------------------------------------------------------
   长按撤离的 8 秒是全局最紧张的时刻，需要明确的视觉压迫：
   环形进度 + 大号读秒 + 随进度加快的脉冲。
   ============================================================ */
/* bottom 用 max() 兜住一个最小间距。
   ------------------------------------------------------------
   原来固定 16%，在 1024×700 这种矮视口下只有 112px ——
   环（132px 高）加上下方的「撤离中 / 撤离点名称」两行字，
   会一直顶到技能栏的图标上（实测只剩 12px）。
   max(16%, 180px) 让它在矮屏上至少留出 180px。 */
#extract-hud{
  position:absolute; left:50%; bottom:max(16%,180px); transform:translateX(-50%);
  width:132px; height:132px; pointer-events:none; opacity:0;
  transition:opacity .18s ease;
}
#extract-hud:not(.hidden){ opacity:1; }
#extract-hud svg{ position:absolute; inset:0; width:100%; height:100%; transform:rotate(-90deg); }
#extract-hud .ex-bg{
  fill:none; stroke:rgba(255,255,255,.16); stroke-width:5;
}
#extract-hud .ex-fg{
  fill:none; stroke:var(--amber); stroke-width:5; stroke-linecap:round;
  /* 2πr，r=52 → 326.7 */
  stroke-dasharray:326.7; stroke-dashoffset:326.7;
  transition:stroke-dashoffset .08s linear, stroke .3s ease;
  filter:drop-shadow(0 0 6px rgba(242,183,5,.55));
}
#extract-hud .ex-num{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font:700 40px/1 var(--mono, monospace); color:var(--paper);
  text-shadow:0 0 12px rgba(0,0,0,.75);
}
#extract-hud .ex-label{
  position:absolute; left:0; right:0; bottom:-20px; text-align:center;
  font:600 10px/1 var(--mono, monospace); letter-spacing:.28em;
  color:var(--amber); text-shadow:0 0 8px rgba(0,0,0,.8);
}
#extract-hud .ex-name{
  position:absolute; left:0; right:0; bottom:-36px; text-align:center;
  font:500 11px/1 var(--mono, monospace); letter-spacing:.06em;
  color:rgba(255,255,255,.72); text-shadow:0 0 8px rgba(0,0,0,.8);
}
/* 矮视口：把环缩小。
   ------------------------------------------------------------
   环的视觉高度是 132（圆环）+ 47（下方两行字）= 179px。
   在 1024×700 下，「[F] 长按撤离」提示框底部（约 y=452）到
   技能栏顶部（约 y=600）之间只有 148px —— **装不下**，
   无论 bottom 取多少都会压到其中之一。
   所以只能缩小：96px 环 + 缩小字号后总高约 141px。 */
@media (max-height:780px){
  #extract-hud{ width:96px; height:96px; bottom:152px; }
  #extract-hud .ex-num{ font-size:30px; }
  #extract-hud .ex-label{ bottom:-17px; font-size:9px; }
  #extract-hud .ex-name{ bottom:-31px; font-size:10px; }
}
/* 最后两秒：转为告警红并加快脉冲 */
#extract-hud.urgent .ex-fg{ stroke:var(--alert); filter:drop-shadow(0 0 9px rgba(217,72,43,.75)); }
#extract-hud.urgent .ex-num{ color:#FFD9CE; }
#extract-hud.urgent{ animation:exPulse .34s ease-in-out infinite; }
@keyframes exPulse{
  0%,100%{ transform:translateX(-50%) scale(1) }
  50%    { transform:translateX(-50%) scale(1.045) }
}
.fui.extract .fui-k{ color:var(--teal-lt); }
.fui.dim{ opacity:.42; }
.fui-box{
  position:absolute; left:0; top:0; pointer-events:none;
  border:1px solid rgba(255,255,255,.55); will-change:transform;
}
.fui-box.searched{ border-color:rgba(255,255,255,.2); border-style:dashed; }
.fui-box .c{ position:absolute; width:7px; height:7px; border:1.5px solid var(--amber); }
.fui-box .c1{ top:-1px; left:-1px; border-right:0; border-bottom:0; }
.fui-box .c2{ top:-1px; right:-1px; border-left:0; border-bottom:0; }
.fui-box .c3{ bottom:-1px; left:-1px; border-right:0; border-top:0; }
.fui-box .c4{ bottom:-1px; right:-1px; border-left:0; border-top:0; }

/* ===================== HUD ===================== */
#hud{ position:absolute; inset:0; pointer-events:none; z-index:30; }
#hud > *{ pointer-events:none; }

.panel{
  position:absolute; background:var(--glass); border:1px solid var(--ink);
  box-shadow:var(--shadow); backdrop-filter:blur(9px); -webkit-backdrop-filter:blur(9px);
}
.panel-hd{
  display:flex; align-items:center; gap:6px; font:700 9.5px/1 var(--mono);
  letter-spacing:.18em; text-transform:uppercase; color:var(--ink); padding:6px 9px;
  border-bottom:1px solid var(--line); background:rgba(36,38,42,.05);
}
.panel-hd .dot{ width:5px; height:5px; background:var(--amber); display:block; }

#compass{
  position:absolute; top:12px; left:50%; transform:translateX(-50%);
  width:min(560px,52vw); height:34px; overflow:hidden; background:var(--glass);
  border:1px solid var(--ink); box-shadow:var(--shadow); backdrop-filter:blur(9px);
}
#compass-track{ position:absolute; inset:0; }
#compass-track i{ position:absolute; top:0; height:100%; width:1px; background:var(--line); }
#compass-track b{
  position:absolute; top:50%; transform:translate(-50%,-50%);
  font:700 10px/1 var(--mono); letter-spacing:.1em; color:var(--ink);
}
#compass-track b.card{ font-size:12px; }
#compass-track b.tick{ color:var(--ink-3); font-weight:500; font-size:9px; }
#compass-needle{
  position:absolute; top:0; bottom:0; left:50%; width:2px; background:var(--amber);
  transform:translateX(-50%); box-shadow:0 0 8px rgba(242,183,5,.9);
}
#compass-readout{
  position:absolute; left:50%; bottom:-19px; transform:translateX(-50%);
  display:flex; align-items:baseline; font:700 12px/1 var(--mono); color:#fff;
  text-shadow:0 1px 4px rgba(0,0,0,.9); white-space:nowrap;
}
#compass-readout i{ font-style:normal; opacity:.7; font-size:9px; }
#compass-readout em{
  font-style:normal; font-size:9px; letter-spacing:.2em; margin-left:9px;
  color:var(--amber); text-transform:uppercase;
}

#squad-panel{ top:12px; left:12px; width:196px; }
#squad-list{ padding:5px; display:flex; flex-direction:column; gap:3px; }
.sq-row{ display:flex; align-items:center; gap:7px; padding:5px 6px; border:1px solid var(--line-2); }
.sq-row.me{ border-color:var(--ink); background:rgba(242,183,5,.16); }
.sq-av{ width:20px; height:20px; border:1px solid var(--ink); display:grid; place-items:center;
  font:800 9px/1 var(--mono); background:var(--paper-3); flex:none; }
.sq-meta{ flex:1; min-width:0; }
.sq-nm{ font:700 11px/1.2 var(--sans); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sq-st{ font:500 8.5px/1.3 var(--mono); letter-spacing:.1em; color:var(--ink-3); text-transform:uppercase; }
.sq-hp{ width:34px; height:4px; background:rgba(36,38,42,.16); flex:none; }
.sq-hp i{ display:block; height:100%; background:var(--ok); }

#radar-panel{ top:12px; right:12px; width:174px; }
#radar{ display:block; width:174px; height:174px; background:rgba(36,38,42,.06); }
/* 撤离窗口 / 可用撤离点两行共用一套排版。
   原来只有 #raid-timer 一个 id 选择器 —— 加第二行时如果继续用 id
   就会产生重复 id（同一页面里第二个 id 选择器只命中第一个元素）。 */
#raid-timer, .raid-row{ display:flex; align-items:center; justify-content:space-between;
  padding:6px 9px; border-top:1px solid var(--line); }
#raid-timer .lbl, .raid-row .lbl{ font:700 8.5px/1 var(--mono); letter-spacing:.16em; color:var(--ink-3); text-transform:uppercase; }
#raid-timer b, .raid-row b{ font:800 15px/1 var(--mono); }
#raid-timer.urgent b, .raid-row.urgent b{ color:var(--alert); animation:blink 1s steps(2) infinite; }
/* 只剩一个撤离点可用时给告警色 —— 这时候走错方向就没退路了 */
.raid-row b.low{ color:var(--alert); }
@keyframes blink{ 50%{ opacity:.3 } }

#crosshair{ position:absolute; left:50%; top:50%; width:0; height:0; }
#crosshair i{ position:absolute; background:#fff; box-shadow:0 0 4px rgba(0,0,0,.95);
  transition:transform .06s linear; }
#crosshair .ch-t,#crosshair .ch-b{ width:1.5px; height:7px; left:-.75px; }
#crosshair .ch-l,#crosshair .ch-r{ width:7px; height:1.5px; top:-.75px; }
#crosshair .ch-t{ bottom:var(--gap,6px); }
#crosshair .ch-b{ top:var(--gap,6px); }
#crosshair .ch-l{ right:var(--gap,6px); }
#crosshair .ch-r{ left:var(--gap,6px); }
#ch-dot{ position:absolute; left:-1.5px; top:-1.5px; width:3px; height:3px; background:var(--amber);
  border-radius:50%; opacity:0; transition:opacity .1s; }
#crosshair.ads #ch-dot{ opacity:1; }

#hitmarker{ position:absolute; left:50%; top:50%; width:0; height:0; opacity:0; }
#hitmarker.on{ opacity:1; animation:hm .22s ease-out; }
#hitmarker i{ position:absolute; width:8px; height:1.5px; background:#fff; box-shadow:0 0 4px rgba(0,0,0,.9); }
#hitmarker i:nth-child(1){ transform:rotate(45deg) translate(9px,0); }
#hitmarker i:nth-child(2){ transform:rotate(-45deg) translate(9px,0); }
#hitmarker i:nth-child(3){ transform:rotate(135deg) translate(9px,0); }
#hitmarker i:nth-child(4){ transform:rotate(-135deg) translate(9px,0); }
#hitmarker.kill i{ background:var(--alert); height:2px; width:11px; }
/* 爆头：琥珀金 + 更长的射线，和普通命中一眼分得开 */
#hitmarker.head i{ background:var(--amber); height:2px; width:13px;
  box-shadow:0 0 6px rgba(232,176,30,.85), 0 0 4px rgba(0,0,0,.9); }
#hitmarker.head.kill i{ background:var(--alert); }
#hitmarker.head.on{ animation:hm .32s cubic-bezier(.2,1.4,.4,1); }
@keyframes hm{ from{ transform:scale(.55) } to{ transform:scale(1.15) } }

#vitals{ position:absolute; left:12px; bottom:12px; width:250px; background:var(--glass);
  border:1px solid var(--ink); box-shadow:var(--shadow); backdrop-filter:blur(9px); padding:9px 10px 8px; }
.vital-row{ display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.vital-row:last-of-type{ margin-bottom:0; }
.vital-lbl{ font:800 9px/1 var(--mono); letter-spacing:.14em; color:var(--ink-3); width:18px; flex:none; }
.vital-bar{ flex:1; height:9px; background:rgba(36,38,42,.14); position:relative;
  overflow:hidden; border:1px solid var(--line); }
.vital-bar.sm{ height:5px; }
.vital-fill{ position:absolute; inset:0 auto 0 0; width:100%; transition:width .16s cubic-bezier(.2,.8,.3,1); }
.vital-fill.hp{ background:linear-gradient(90deg,var(--ok),#6FBF5B); }
.vital-fill.ar{ background:linear-gradient(90deg,#2E7FB8,#59B7E8); }
.vital-fill.st{ background:linear-gradient(90deg,var(--amber-dk),var(--amber)); }
.vital-ghost{ position:absolute; inset:0 auto 0 0; width:100%; background:rgba(217,72,43,.55);
  transition:width .55s ease .18s; }
.vital-row b{ font:800 13px/1 var(--mono); width:32px; text-align:right; flex:none;
  font-variant-numeric:tabular-nums; }
#status-chips{ display:flex; gap:4px; flex-wrap:wrap; margin-top:7px; }
.chip{ font:700 8.5px/1 var(--mono); letter-spacing:.1em; padding:3px 6px; border:1px solid var(--ink);
  background:rgba(242,183,5,.28); text-transform:uppercase; }
.chip.bad{ background:rgba(217,72,43,.3); border-color:var(--alert); color:#7a2314; }

#weapon-widget{ position:absolute; right:12px; bottom:12px; width:214px; background:var(--glass);
  border:1px solid var(--ink); box-shadow:var(--shadow); backdrop-filter:blur(9px); padding:8px 10px 10px; }
.wp-name{ display:flex; align-items:baseline; justify-content:space-between; margin-bottom:3px; }
.wp-name span{ font:800 15px/1 var(--sans); }
.wp-name em{ font:700 8.5px/1 var(--mono); font-style:normal; letter-spacing:.14em; color:var(--ink-3); }
.wp-ammo{ display:flex; align-items:baseline; gap:3px; }
.wp-ammo b{ font:800 30px/1 var(--mono); font-variant-numeric:tabular-nums; }
.wp-ammo b.low{ color:var(--alert); }
.wp-ammo span,.wp-ammo i{ font:600 13px/1 var(--mono); color:var(--ink-3); font-style:normal; }
.wp-attach{ display:flex; gap:3px; flex-wrap:wrap; margin-top:6px; }
.wp-attach i{ font:600 8px/1 var(--mono); font-style:normal; letter-spacing:.08em; padding:2.5px 5px;
  border:1px solid var(--line); color:var(--ink-3); text-transform:uppercase; }
.wp-reload{ height:2px; background:rgba(36,38,42,.15); margin-top:7px; overflow:hidden; }
.wp-reload i{ display:block; height:100%; width:0; background:var(--amber); }

#abilities{ position:absolute; left:50%; bottom:12px; transform:translateX(-50%);
  display:flex; gap:10px; align-items:flex-end; }
.ab{ display:flex; flex-direction:column; align-items:center; gap:4px; }
.ab-ring{ position:relative; width:44px; height:44px; background:var(--glass); border:1px solid var(--ink);
  box-shadow:var(--shadow); display:grid; place-items:center; backdrop-filter:blur(9px); }
.ab-ring svg{ position:absolute; inset:-1px; width:46px; height:46px; transform:rotate(-90deg); }
.ab-ring svg circle{ fill:none; stroke-width:3; }
.ab-ring .tr{ stroke:rgba(36,38,42,.14); }
.ab-ring .pr{ stroke:var(--amber); stroke-dasharray:119.4; stroke-dashoffset:0;
  transition:stroke-dashoffset .1s linear; }
.ab-ring span{ font:800 13px/1 var(--mono); color:var(--ink); position:relative; z-index:1; }
.ab.ready .ab-ring{ background:var(--amber); border-color:var(--amber-dk); }
.ab.core .ab-ring{ width:52px; height:52px; }
.ab.core .ab-ring svg{ width:54px; height:54px; }
.ab-name{ font:700 8px/1 var(--mono); letter-spacing:.12em; color:#fff;
  text-shadow:0 1px 3px rgba(0,0,0,.9); text-transform:uppercase; }

#killfeed{ position:absolute; right:12px; top:262px; width:250px; display:flex;
  flex-direction:column; gap:3px; align-items:flex-end; }
.kf{ display:flex; align-items:center; gap:6px; padding:4px 8px; background:var(--glass);
  border:1px solid var(--ink); border-right-width:3px; font:700 10px/1 var(--mono);
  box-shadow:var(--shadow); animation:kfIn .2s ease-out; }
.kf.mine{ border-right-color:var(--amber); }
.kf.victim{ border-right-color:var(--alert); }
.kf .kf-w{ color:var(--ink-3); font-weight:500; }
@keyframes kfIn{ from{ opacity:0; transform:translateX(14px) } }

#prompt{ position:absolute; left:50%; top:calc(50% + 58px); transform:translateX(-50%);
  display:flex; align-items:center; gap:9px; padding:7px 12px; background:var(--glass);
  border:1px solid var(--ink); box-shadow:var(--shadow); backdrop-filter:blur(9px); min-width:210px; }
.prompt-key{ width:26px; height:26px; display:grid; place-items:center; flex:none; border:1px solid var(--ink);
  background:var(--paper-3); font:800 12px/1 var(--mono); }
.prompt-txt{ flex:1; min-width:0; }
.prompt-txt b{ display:block; font:700 12px/1.2 var(--sans); }
.prompt-txt span{ display:block; font:600 8.5px/1.3 var(--mono); letter-spacing:.1em;
  color:var(--ink-3); text-transform:uppercase; }
.prompt-prog{ position:absolute; left:0; right:0; bottom:-1px; height:2px;
  background:rgba(36,38,42,.15); overflow:hidden; }
.prompt-prog i{ display:block; height:100%; width:0; background:var(--amber); }

#banner{ position:absolute; left:50%; top:23%; transform:translateX(-50%); display:flex;
  flex-direction:column; align-items:center; gap:5px; }
.bn{ padding:7px 20px; background:var(--glass-dark); border-left:3px solid var(--amber); color:#fff;
  font:700 13px/1.2 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  animation:bnIn .28s cubic-bezier(.2,.8,.3,1); backdrop-filter:blur(9px); }
.bn.warn{ border-left-color:var(--alert); }
.bn.good{ border-left-color:var(--teal-lt); }
.bn small{ display:block; font:600 9.5px/1.5 var(--mono); letter-spacing:.1em;
  color:rgba(255,255,255,.66); text-transform:none; margin-top:2px; }
@keyframes bnIn{ from{ opacity:0; transform:translateY(-8px) } }

#dmg-dirs{ position:absolute; left:50%; top:50%; width:0; height:0; }
/* 受击方向指示。
   ------------------------------------------------------------
   原来 72px、3px 弧、无辉光 —— 在明亮的户外地面上几乎看不见，
   而这个元素恰恰要在交火、画面最乱的时候被一眼捕捉到。
   放大到 92px、加粗到 5px，并加一层 drop-shadow
   （和撤离进度环用的是同一种处理）。 */
/* 受击方向指示
   ------------------------------------------------------------
   元素是 92×92 的圆环，只画了 border-top —— 所以「正上方」就是
   指示方向，靠 transform:rotate() 转到目标方位。left/top 各 -46px
   让它正好以屏幕中心为圆心，transform-origin 默认即中心。

   **这里不要加 animation**：旋转和淡出现在都由
   HUD.updateDamageDirs() 每帧写内联样式（指示器要跟着视角转），
   而 CSS 动画优先级高于内联样式，会把每帧的写入全部盖掉 ——
   加回旧版的 dmgOut .8s 就会退化成「不跟视角」。 */
.dmg-dir{ position:absolute; left:-46px; top:-46px; width:92px; height:92px;
  border:5px solid transparent; border-top-color:rgba(217,72,43,.95); border-radius:50%;
  filter:drop-shadow(0 0 7px rgba(217,72,43,.75));
  opacity:0; will-change:transform,opacity; }

/* ===================== 全屏界面 ===================== */
.screen{ position:absolute; inset:0; z-index:60; display:none; background:var(--paper);
  color:var(--ink); overflow:auto; }
.screen.active{ display:flex; flex-direction:column; }
.screen::before{
  content:""; position:absolute; inset:0; pointer-events:none; opacity:.5;
  background:
    linear-gradient(90deg,rgba(36,38,42,.045) 1px,transparent 1px) 0 0/56px 56px,
    linear-gradient(0deg,rgba(36,38,42,.045) 1px,transparent 1px) 0 0/56px 56px;
}

#scr-boot{ align-items:center; justify-content:center; }
.boot-wrap{ text-align:center; position:relative; z-index:1; }
/* 启动屏是第一眼印象，但原来的尺寸在 1400px 视口里偏小
   （标题只占 26% 宽，四周大片空白）。整体放大到与屏幕相称，
   进度条用 min() 兜住窄屏。 */
.boot-logo{ width:128px; height:128px; margin:0 auto 22px; color:var(--ink); }
.boot-logo svg{ width:100%; height:100%; }
.boot-title{ font:900 64px/1 var(--sans); letter-spacing:.3em; margin-left:.3em; }
.boot-sub{ font:600 14px/1 var(--mono); letter-spacing:.7em; margin-left:.7em; color:var(--ink-3); margin-top:14px; }
.boot-bar{ width:min(420px,76vw); height:4px; background:rgba(36,38,42,.14); margin:38px auto 15px; overflow:hidden; }
.boot-bar i{ display:block; height:100%; width:0; background:var(--amber); transition:width .25s ease; }
.boot-status{ font:600 11px/1 var(--mono); letter-spacing:.18em; color:var(--ink-3); text-transform:uppercase; }

#scr-prep{ padding:0; }
.scr-hd{ display:flex; align-items:flex-end; justify-content:space-between; gap:16px;
  padding:18px 22px 14px; border-bottom:1px solid var(--line); position:relative; z-index:1;
  background:linear-gradient(180deg,rgba(242,183,5,.10),transparent); }
.scr-hd.compact{ padding:14px 18px 11px; }
.scr-hd-l .tag{ display:inline-block; font:700 9px/1 var(--mono); letter-spacing:.24em;
  padding:4px 8px; background:var(--ink); color:var(--paper); text-transform:uppercase; }
.scr-hd-l h2{ font:800 24px/1.15 var(--sans); margin-top:9px; }
.scr-hd-r{ display:flex; gap:9px; }
.stat-chip{ border:1px solid var(--ink); padding:6px 11px; background:var(--paper-2); min-width:96px; }
.stat-chip span{ display:block; font:700 8px/1 var(--mono); letter-spacing:.18em; color:var(--ink-3); text-transform:uppercase; }
.stat-chip b{ display:block; font:800 17px/1.25 var(--mono); font-variant-numeric:tabular-nums; }

.prep-grid{ flex:1; display:grid; grid-template-columns:250px 1fr 288px; min-height:0; position:relative; z-index:1; }
.prep-col{ border-right:1px solid var(--line); padding:14px; overflow:auto; min-height:0; }
.prep-col:last-child{ border-right:0; }
.col-hd{ display:flex; align-items:center; gap:7px; font:700 9.5px/1 var(--mono);
  letter-spacing:.2em; color:var(--ink-3); text-transform:uppercase; margin-bottom:9px; }
.col-hd i{ width:12px; height:2px; background:var(--amber); display:block; }
.col-hd.mt{ margin-top:18px; }

.op-list{ display:flex; flex-direction:column; gap:6px; }
.op-card{ display:flex; gap:10px; padding:9px; border:1px solid var(--line); background:var(--paper-2);
  cursor:pointer; transition:.13s; align-items:center; }
.op-card:hover{ border-color:var(--ink); background:var(--paper-3); }
.op-card.sel{ border-color:var(--ink); background:var(--paper); box-shadow:inset 3px 0 0 var(--amber); }
.op-portrait{ width:42px; height:42px; flex:none; border:1px solid var(--ink); display:grid;
  place-items:center; font:900 15px/1 var(--mono); background:var(--paper-3); }
.op-info{ min-width:0; flex:1; }
.op-info b{ display:block; font:800 13px/1.2 var(--sans); }
.op-info span{ display:block; font:600 8.5px/1.35 var(--mono); letter-spacing:.1em;
  color:var(--ink-3); text-transform:uppercase; }

.op-detail{ font-size:12px; }
.op-hero{ border:1px solid var(--ink); padding:12px; background:var(--paper-2); margin-bottom:12px; }
.op-hero h3{ font:800 19px/1.1 var(--sans); }
.op-hero .en{ font:700 9px/1 var(--mono); letter-spacing:.2em; color:var(--ink-3);
  text-transform:uppercase; margin-top:4px; }
.op-hero p{ font:500 11.5px/1.6 var(--sans); margin-top:9px; color:var(--ink-2); }
.skill{ border:1px solid var(--line); border-left:3px solid var(--amber); padding:9px 10px;
  margin-bottom:7px; background:var(--paper-2); }
.skill b{ display:block; font:700 12px/1.2 var(--sans); }
.skill .k{ font:700 8.5px/1 var(--mono); letter-spacing:.14em; color:var(--ink-3);
  text-transform:uppercase; margin-bottom:4px; }
.skill p{ font:500 11px/1.55 var(--sans); color:var(--ink-2); }
.skill.ult{ border-left-color:var(--alert); }
.skill.passive{ border-left-color:var(--teal); }
.stat-mini{ display:flex; gap:8px; margin-top:9px; }
.stat-mini div{ flex:1; border:1px solid var(--line); padding:5px 7px; text-align:center; background:var(--paper-2); }
.stat-mini span{ display:block; font:700 7.5px/1 var(--mono); letter-spacing:.14em; color:var(--ink-3); text-transform:uppercase; }
.stat-mini b{ display:block; font:800 14px/1.3 var(--mono); }

.loadout{ display:grid; grid-template-columns:1fr 1fr; gap:7px; }
.slot{ border:1px solid var(--line); background:var(--paper-2); padding:8px 9px; min-height:56px;
  cursor:pointer; transition:.13s; position:relative; }
.slot:hover{ border-color:var(--ink); }
.slot.filled{ border-color:var(--ink); background:var(--paper); }
.slot .sl-k{ font:700 8px/1 var(--mono); letter-spacing:.18em; color:var(--ink-3); text-transform:uppercase; }
.slot .sl-v{ font:700 12.5px/1.3 var(--sans); margin-top:4px; }
.slot .sl-s{ font:600 9px/1.3 var(--mono); color:var(--ink-3); margin-top:2px; }
.slot .sl-x{ position:absolute; top:5px; right:6px; font:700 12px/1 var(--mono); color:var(--ink-3); }
.slot .sl-x:hover{ color:var(--alert); }
.slot.empty .sl-v{ color:var(--ink-3); font-weight:500; font-style:italic; }

.grid-inv{ display:grid; grid-template-columns:repeat(auto-fill,minmax(74px,1fr)); gap:5px; }
.cell{ aspect-ratio:1; border:1px solid var(--line); background:var(--paper-2); cursor:pointer;
  position:relative; padding:5px; display:flex; flex-direction:column; justify-content:space-between;
  transition:.11s; overflow:hidden; }
.cell:hover{ border-color:var(--ink); transform:translateY(-1px); }
.cell.r1{ border-left:3px solid var(--ink-3); }
.cell.r2{ border-left:3px solid #3E7CB1; }
.cell.r3{ border-left:3px solid #7A54B8; }
.cell.r4{ border-left:3px solid var(--amber); }
.cell.r5{ border-left:3px solid var(--alert); }
.cell .cl-n{ font:700 10px/1.25 var(--sans); }
.cell .cl-v{ font:700 10px/1 var(--mono); color:var(--ink-3); font-variant-numeric:tabular-nums; }
.cell .cl-q{ position:absolute; top:4px; right:5px; font:800 10px/1 var(--mono); }
.cell.empty{ background:repeating-linear-gradient(45deg,rgba(36,38,42,.03) 0 4px,transparent 4px 8px); }

.item-detail{ border:1px solid var(--line); background:var(--paper-2); padding:12px; min-height:180px; }
.item-detail h4{ font:800 15px/1.2 var(--sans); }
.item-detail .rar{ font:700 9px/1 var(--mono); letter-spacing:.18em; text-transform:uppercase; margin-top:5px; }
.item-detail .desc{ font:500 11.5px/1.65 var(--sans); color:var(--ink-2); margin-top:10px; }
.item-detail dl{ margin-top:10px; display:grid; grid-template-columns:auto 1fr; gap:3px 10px;
  font:600 11px/1.5 var(--mono); }
.item-detail dt{ color:var(--ink-3); }
.item-detail dd{ text-align:right; font-variant-numeric:tabular-nums; }

.scr-ft{ display:flex; align-items:center; gap:12px; padding:13px 22px; border-top:1px solid var(--line);
  background:var(--paper-2); position:relative; z-index:1; }
.scr-ft .spacer{ flex:1; }
.cost-readout{ font:700 11px/1 var(--mono); letter-spacing:.15em; color:var(--ink-3); text-transform:uppercase; }
.cost-readout b{ color:var(--ink); font-size:15px; margin-left:5px; }

.btn{ font:800 12px/1 var(--sans); letter-spacing:.1em; padding:11px 24px; border:1px solid var(--ink);
  background:var(--paper); color:var(--ink); cursor:pointer; transition:.13s; text-transform:uppercase; }
.btn:hover{ background:var(--paper-3); }
.btn.primary{ background:var(--ink); color:var(--paper); }
.btn.primary:hover{ background:var(--amber); color:var(--ink); border-color:var(--amber-dk); }
.btn.ghost{ background:transparent; }
.btn:disabled{ opacity:.38; cursor:not-allowed; }

#scr-result{ align-items:center; justify-content:center; }
/* 结算内容原来固定 760px 宽 —— 在 1400px 视口里只占 54%，
   两侧留出大片空白，和铺满三栏的载入屏完成度差很多。
   放宽到 1040px 并把字号层级整体提一档。 */
.result-wrap{ width:min(1040px,92vw); padding:32px; position:relative; z-index:1; }
.result-badge{ display:inline-block; font:800 11px/1 var(--mono); letter-spacing:.28em; padding:7px 15px;
  background:var(--ok); color:#fff; text-transform:uppercase; }
.result-badge.fail{ background:var(--alert); }
.result-wrap h2{ font:900 46px/1.1 var(--sans); margin-top:18px; }
.result-sub{ font:500 13px/1.5 var(--sans); color:var(--ink-3); margin-top:7px; }
/* minmax 从 140 降到 122：1024 视口下 result-wrap 可用宽度只有 878px，
   6 列需要 6×140+5×11 = 895 > 878，会掉成 5+1 两行（最后一项孤零零）。
   122 时只需 6×122+55 = 787，同一行放得下。 */
.result-stats{ display:grid; grid-template-columns:repeat(auto-fit,minmax(122px,1fr)); gap:11px; margin:26px 0; }
.rs{ border:1px solid var(--line); background:var(--paper-2); padding:13px; }
.rs span{ display:block; font:700 8px/1 var(--mono); letter-spacing:.16em; color:var(--ink-3); text-transform:uppercase; }
.rs b{ display:block; font:800 26px/1.25 var(--mono); font-variant-numeric:tabular-nums; }
.rs b.amber{ color:var(--amber-dk); }
.result-actions{ display:flex; gap:10px; margin-top:24px; }

#pause{ background:rgba(14,15,17,.55); backdrop-filter:blur(11px); align-items:center; justify-content:center; }
.pause-box{ background:var(--paper); border:1px solid var(--ink); padding:30px 34px; width:min(560px,92vw);
  box-shadow:0 20px 60px rgba(0,0,0,.4); }
.pause-box h2{ font:900 27px/1 var(--sans); letter-spacing:.05em; }
.pause-box .dim{ font:500 12px/1.5 var(--sans); color:var(--ink-3); margin-top:7px; }
.pause-actions{ display:flex; gap:10px; margin:20px 0; }
.pause-help{ display:grid; grid-template-columns:1fr 1fr 1fr; gap:6px 14px; border-top:1px solid var(--line); padding-top:15px; }
.pause-help div{ font:500 11px/1.5 var(--sans); color:var(--ink-2); }
.pause-help kbd{ display:inline-block; font:700 9.5px/1 var(--mono); padding:3px 6px; border:1px solid var(--ink);
  background:var(--paper-2); margin-right:5px; }

#inventory{ background:rgba(14,15,17,.55); backdrop-filter:blur(11px); align-items:center; justify-content:center; }
.inv-wrap{ width:min(900px,94vw); max-height:88vh; display:flex; flex-direction:column; background:var(--paper);
  border:1px solid var(--ink); box-shadow:0 20px 60px rgba(0,0,0,.4); }
.inv-body{ flex:1; display:grid; grid-template-columns:1fr 254px; min-height:0; }
.inv-body > div{ padding:14px; overflow:auto; min-height:0; }
.inv-side{ border-left:1px solid var(--line); }
.dim{ color:var(--ink-3); font-size:12px; }

#fatal{ position:absolute; inset:0; z-index:200; background:rgba(14,15,17,.94); display:grid; place-items:center; }
.fatal-box{ background:var(--paper); border:1px solid var(--alert); padding:24px; max-width:min(700px,90vw); }
.fatal-box h2{ font:900 19px/1 var(--sans); color:var(--alert); margin-bottom:12px; }
.fatal-box pre{ font:500 11px/1.6 var(--mono); white-space:pre-wrap; word-break:break-word;
  max-height:46vh; overflow:auto; }

::-webkit-scrollbar{ width:9px; height:9px; }
::-webkit-scrollbar-track{ background:rgba(36,38,42,.06); }
::-webkit-scrollbar-thumb{ background:rgba(36,38,42,.3); }

/* 窄屏：三栏改为上下堆叠。
   ------------------------------------------------------------
   原来只改了列数，但 .prep-col 带 overflow:auto 是为了让
   **三栏各自独立滚动**（三栏并排时是对的）。改成单列之后，
   三行平分容器高度，每栏只剩三分之一，里面的内容被压扁、
  裁切、相互重叠（1024×700 下很明显）。

   正确做法：让每栏按内容自然撑开（grid-auto-rows:min-content +
   overflow:visible），改由整个网格统一纵向滚动。 */
@media (max-width:1180px){
  .prep-grid{
    grid-template-columns:1fr;
    grid-auto-rows:min-content;
    overflow-y:auto; overflow-x:hidden;
  }
  .prep-col{ border-right:0; border-bottom:1px solid var(--line); overflow:visible; min-height:0; }
  .prep-col:last-child{ border-bottom:0; }
}

/* ============================================================
   区域提示（进入新区域时短暂出现）
   ------------------------------------------------------------
   zoneName() 一直存在，但只用在死亡结算里 —— 玩家在局内
   看不到自己身处哪个区域。补一个浮空标签：左侧竖条 + 区域名 +
   英文副标，出现时从左侧滑入，几秒后淡出。
   ============================================================ */
#zone-label{
  position:absolute; left:3.2%; top:31%;
  display:flex; align-items:stretch; gap:9px;
  opacity:0; transform:translateX(-14px);
  transition:opacity .35s ease, transform .35s cubic-bezier(.2,.8,.25,1);
  pointer-events:none;
}
#zone-label.show{ opacity:1; transform:translateX(0); }
#zone-label .zl-bar{
  width:3px; background:linear-gradient(180deg,var(--teal),rgba(0,168,150,.15));
  border-radius:2px;
}
#zone-label .zl-txt{ display:flex; flex-direction:column; gap:2px; }
#zone-label b{
  font-size:19px; letter-spacing:2px; font-weight:700;
  color:#F2F6F8; text-shadow:0 1px 6px rgba(0,0,0,.55);
}
#zone-label i{
  font-style:normal; font-size:9px; letter-spacing:1.6px;
  color:var(--teal); opacity:.9;
}
#zone-label.show b{ animation:zlIn .5s ease-out; }
@keyframes zlIn{
  from{ letter-spacing:7px; opacity:.25 }
  to  { letter-spacing:2px; opacity:1 }
}
/* ============================================================
   指针锁定兜底提示
   ------------------------------------------------------------
   浏览器在 Esc 退出指针锁定后有约 1.25 秒冷却期。若玩家在这段时间内
   点「继续」，requestPointerLock() 会失败 —— 而那时暂停菜单已经隐藏，
   玩家看到的是「菜单没了、鼠标也不能转」，感觉就是游戏卡死。

   这一层在锁定失败时接管：铺满画面、捕获点击、提示玩家点一下。
   点击是合法的用户手势，此时冷却期也已过去，必定能锁上。
   ============================================================ */
#lock-hint{
  position:fixed; inset:0; z-index:60;
  display:flex; align-items:center; justify-content:center;
  background:rgba(12,14,16,.55); backdrop-filter:blur(3px);
  cursor:pointer;
}
#lock-hint.hidden{ display:none; }
#lock-hint .lh-box{
  display:flex; flex-direction:column; align-items:center; gap:8px;
  padding:22px 34px; background:var(--paper); border:1px solid var(--ink);
  box-shadow:0 8px 40px rgba(0,0,0,.45);
  animation:lhIn .22s cubic-bezier(.2,.8,.3,1);
}
#lock-hint b{
  font:800 20px/1 var(--sans); letter-spacing:.14em; color:var(--ink);
}
#lock-hint span{
  font:600 10.5px/1.5 var(--mono); letter-spacing:.1em; color:var(--ink-3);
}
@keyframes lhIn{ from{ opacity:0; transform:translateY(6px) } }
/* ============================================================
   死亡状态的全屏提示
   ------------------------------------------------------------
   玩家倒下后 controller.update() 会忽略全部输入（移动/视角/开火），
   直到 3.2 秒后结算。原来只有中央一行小字，玩家容易误以为游戏卡死。

   这一层红色渐晕让「我死了」一眼可见：
   中间相对通透（保留视野），四角压暗并染红。
   ============================================================ */
#hud.dead::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:40;
  background:
    radial-gradient(ellipse at 50% 50%,
      rgba(120,10,10,0) 26%,
      rgba(120,10,10,.30) 62%,
      rgba(86,6,6,.72) 100%);
  animation:deadIn .55s ease-out;
}
@keyframes deadIn{ from{ opacity:0 } }
/* ============================================================
   静音常驻指示
   ------------------------------------------------------------
   按 M 静音后只在横幅上提示 3 秒，很容易错过 ——
   玩家随后会以为「游戏坏了、没声音」。
   这个角标会一直挂在准星下方，直到取消静音。
   ============================================================ */
#mute-badge{
  position:absolute; left:50%; top:64%; transform:translateX(-50%);
  display:flex; align-items:center; gap:9px;
  padding:7px 14px; background:rgba(36,38,42,.82);
  border-left:3px solid var(--alert);
  pointer-events:none; z-index:45;
  animation:mbIn .2s ease-out;
}
#mute-badge.hidden{ display:none; }
#mute-badge i{
  width:8px; height:8px; border-radius:50%;
  background:var(--alert); box-shadow:0 0 7px var(--alert);
  animation:mbPulse 1.4s ease-in-out infinite;
}
#mute-badge span{ font:800 12px/1 var(--sans); letter-spacing:.12em; color:#fff; }
#mute-badge b{ font:600 9.5px/1 var(--mono); letter-spacing:.1em; color:rgba(255,255,255,.62); }
@keyframes mbIn{ from{ opacity:0; transform:translateX(-50%) translateY(-5px) } }
@keyframes mbPulse{ 50%{ opacity:.35 } }
/* ============================================================
   联机：大厅 / 局内信息 / 结算
   ============================================================ */
.mp-wrap, .mpr-wrap{
  margin:auto; width:min(980px,92vw); padding:34px 0 44px;
  display:flex; flex-direction:column; gap:22px;
}
.mp-hd h2{ font:800 42px/1.05 var(--sans); letter-spacing:.02em; color:var(--ink); margin:0; }
.mp-hd p{ margin:8px 0 0; font:600 12px/1 var(--mono); letter-spacing:.12em; color:var(--ink-3); }

.mp-grid{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:18px; }
@media (max-width:820px){ .mp-grid{ grid-template-columns:1fr } }

.mp-card{
  background:var(--paper-2,#F5F3EE); border:1px solid rgba(36,38,42,.16);
  padding:20px 20px 22px; display:flex; flex-direction:column; gap:9px;
}
.mp-card h3{
  margin:0 0 6px; font:800 13px/1 var(--mono); letter-spacing:.16em;
  text-transform:uppercase; color:var(--ink-3);
  display:flex; align-items:center; gap:10px;
}
.mp-card h3 b{ font:800 17px/1 var(--mono); letter-spacing:.1em; color:var(--ink); }

.mp-lb{
  font:700 10px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-3); margin-top:4px; display:flex; gap:8px; align-items:baseline;
}
.mp-lb em{ font-style:normal; letter-spacing:.04em; color:var(--ink-3); opacity:.7; }

.mp-in{
  font:700 15px/1 var(--mono); letter-spacing:.06em;
  padding:11px 12px; background:var(--paper); color:var(--ink);
  border:1px solid rgba(36,38,42,.28); outline:none; width:100%;
}
.mp-in:focus{ border-color:var(--ink); }

.mp-status{
  min-height:16px; font:600 11px/1.5 var(--mono); letter-spacing:.06em;
  color:var(--ink-3); margin-top:4px;
}
.mp-status.err{ color:var(--alert); }
.mp-status.ok{ color:#2E7D32; }

.mp-players{ display:flex; flex-direction:column; gap:6px; min-height:120px; }
.mp-p{
  display:flex; align-items:center; gap:10px; padding:9px 11px;
  background:var(--paper); border-left:3px solid var(--ink-3);
}
.mp-p.me{ border-left-color:var(--accent,#F2B705); background:rgba(242,183,5,.10); }
.mp-p .sw{ width:11px; height:11px; flex:none; }
.mp-p .nm{ font:700 13px/1 var(--sans); color:var(--ink); }
.mp-p .tag{ font:700 9px/1 var(--mono); letter-spacing:.12em; color:var(--ink-3); margin-left:auto; }

.mp-hint{ margin:2px 0 0; font:600 10.5px/1.6 var(--mono); color:var(--ink-3); letter-spacing:.04em; }

/* ---------------- 局内信息 ---------------- */
#mp-hud{
  position:absolute; left:16px; top:96px; z-index:30;
  display:flex; flex-direction:column; gap:4px; pointer-events:none;
  background:rgba(237,234,228,.86); border-left:3px solid var(--ink);
  padding:9px 12px 10px; min-width:132px;
}
#mp-hud.hidden{ display:none; }
.mp-row{ display:flex; align-items:baseline; gap:7px; }
.mp-k{ font:700 8.5px/1 var(--mono); letter-spacing:.16em; color:var(--ink-3); text-transform:uppercase; }
.mp-row b{ font:800 14px/1 var(--mono); color:var(--ink); }
.mp-row i{ font:700 8.5px/1 var(--mono); font-style:normal; color:var(--ink-3); }

#mp-hud-board{ margin-top:6px; display:flex; flex-direction:column; gap:3px; }
#mp-hud-board .mb{
  display:flex; align-items:center; gap:7px;
  font:700 10.5px/1.3 var(--mono); color:var(--ink-2,#4A4D52);
}
#mp-hud-board .mb .sw{ width:8px; height:8px; flex:none; }
#mp-hud-board .mb .k{ margin-left:auto; color:var(--ink); font-weight:800; }

/* ---------------- 结算 ---------------- */
.mpr-wrap h2{ font:800 44px/1 var(--sans); text-align:center; color:var(--ink); margin:0 0 6px; }
.mpr-board{ display:flex; flex-direction:column; gap:7px; }
.mpr-b{
  display:flex; align-items:center; gap:14px; padding:13px 16px;
  background:var(--paper-2,#F5F3EE); border-left:4px solid var(--ink-3);
}
.mpr-b.me{ background:rgba(242,183,5,.14); border-left-color:var(--accent,#F2B705); }
.mpr-b .rk{ font:800 20px/1 var(--mono); color:var(--ink-3); width:30px; }
.mpr-b .sw{ width:12px; height:12px; }
.mpr-b .nm{ font:700 17px/1 var(--sans); color:var(--ink); }
.mpr-b .sc{ margin-left:auto; font:800 19px/1 var(--mono); color:var(--ink); }
.mpr-b .dt{ font:600 11px/1 var(--mono); color:var(--ink-3); width:64px; text-align:right; }
.mpr-ft{ display:flex; gap:12px; justify-content:center; margin-top:10px; }
/* 联机模式下雷达面板只保留雷达本身。
   「撤离窗口」「可用撤离点」是搜打撤的概念，PvP 局里显示它们
   会让玩家以为这一局也能撤离。剩余时间由 #mp-hud 负责。 */
#radar-panel.mp #raid-timer,
#radar-panel.mp .ex-count-row{ display:none; }