/* 《台儿庄：血战滕县》HUD 样式。
   线性关卡对标 COD《战争世界》单人战役（docs/Data_HudLinearLevel.md）：目标通知在左上、
   弹药与手榴弹数在右下且几秒不交互就隐掉、没有姿态图标，中央只留即时反馈。 */

:root {
  --ink: #0d0c0a;
  --paper: #e6dfcd;
  --dim: rgba(230, 223, 205, 0.62);
  --ours: #9dc0e4;
  --theirs: #d6604a;
  --warn: #e0b062;
}

html, body {
  margin: 0; height: 100%; background: #000; overflow: hidden;
  font-family: "Noto Serif SC", "Songti SC", serif;
  color: var(--paper);
  -webkit-font-smoothing: antialiased;
}
canvas#view { display: block; width: 100vw; height: 100vh; }

#hud {
  position: fixed; inset: 0; pointer-events: none;
  font-size: 14px; line-height: 1.5;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
  --hud-edge-x: max(20px, 2.6vw, env(safe-area-inset-right));
  --hud-edge-bottom: max(24px, 4.5vh, env(safe-area-inset-bottom));
}

/* 压制：径向暗角 + 轻微去色。ER2 的压制表现就是这个。 */
.hudSuppress {
  position: absolute; inset: 0; opacity: 0;
  transition: opacity 0.18s linear;
  background: radial-gradient(ellipse at center,
    rgba(0,0,0,0) 34%, rgba(6,6,8,0.55) 72%, rgba(4,4,6,0.9) 100%);
}
/* Imagegen 血污只覆盖周边，中央保持清楚。父层接伤害/血量，子层独立搏动。 */
.hudDamage {
  position: absolute; inset: 0; opacity: 0;
  pointer-events: none; overflow: hidden;
  --blood-clear: 92%; --blood-size: 132%; --blood-pulse: 1.1s;
  transition: opacity 0.09s linear;
  background: radial-gradient(ellipse closest-side at center,
    transparent var(--blood-clear),
    rgba(25,0,3,0.08) calc(var(--blood-clear) + 18%),
    rgba(16,0,2,0.24) 125%);
}
.hudDamage::before {
  content: ""; position: absolute; inset: 0;
  background: url("./Texture/Hud/Texture_HudPeripheralBlood_Publish9080eae7da15a0c1e79d1110.png?v=20261013HudBlend1") center / var(--blood-size) var(--blood-size) no-repeat;
  opacity: 0.88;
  filter: blur(clamp(0.6px, 0.15vh, 1.8px));
}
/* A fixed peripheral-focus blur is cached; only opacity animates with the heartbeat. */
.hudDamage.low::before { animation: hudPulse var(--blood-pulse) ease-in-out infinite; }

/*
 * 近距离白刃击杀的镜头溅血。两张真透明的局部泼溅在每次击杀时随机切换，中央视野保持透明；
 * 它有自己的短计时，绝不借 hudDamage 的血量/受伤状态。
 */
.hudMeleeKillBlood {
  position: absolute; inset: -2.5%; z-index: 8;
  pointer-events: none; opacity: 0; visibility: hidden;
  background: url("./Texture/Hud/Texture_HudMeleeKillBloodRightBurst_Publish340d4394a59033998c83319c.png?v=20260914d") center / 100% 100% no-repeat;
  mix-blend-mode: normal;
  transform: scale(1); transform-origin: center;
  will-change: opacity, transform;
}
.hudMeleeKillBlood.on { visibility: visible; }
.hudStoryBlood {
  position: absolute; inset: 0; z-index: 8; pointer-events: none;
  opacity: 0; visibility: hidden;
  background:
    url("./Texture/Hud/Texture_HudMeleeKillBloodRightBurst_Publish340d4394a59033998c83319c.png?v=20260914d") center / 100% 100% no-repeat,
    url("./Texture/Hud/Texture_HudCriticalBlood_Publish0e12f2bf01b8d2be2a72a437.png?v=20260928") center / 110% 110% no-repeat,
    radial-gradient(ellipse at 45% 48%, rgba(125,5,8,.18), rgba(89,0,4,.72));
}
.hudStoryBlood.on { visibility: visible; }
/* 01–02 storyboard lens layers (Script_Hud.SetLens, curves in Data_OpeningLens): mud on the lens
   (SB03/SB03A; Lovart mask baked to RGBA, alpha from luminance) and the butt strike's white flash (SB04).
   The mud image is set from JS the first time it is needed, so 03+ never loads it. */
.hudLensMud {
  position: absolute; inset: 0; z-index: 8; pointer-events: none;
  opacity: 0; visibility: hidden;
  background: center / 100% 100% no-repeat;
}
.hudLensMud.on { visibility: visible; }
.hudLensFlash {
  position: absolute; inset: 0; z-index: 9; pointer-events: none;
  opacity: 0; visibility: hidden; background: #fffdf6;
}
.hudLensFlash.on { visibility: visible; }
.hudHealthWarning {
  /* Injury is visible through the selected blood mask and contextual bandage prompt.
     Keep the urgent text as an accessible live status without a second HUD warning panel. */
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; opacity: 0;
}
.hudHealthWarning.on { opacity: 1; }
@keyframes hudPulse {
  0%, 100% { opacity: 0.62; }
  18%      { opacity: 1; }
  34%      { opacity: 0.76; }
  48%      { opacity: 0.93; }
  72%      { opacity: 0.62; }
}

/* 来弹指示（对标 COD）：以准心为圆心的一段收尖红弧，正中朝来弹方向一个小尖。
   几何在 Script_Hud.HitDirArcPath，转身只旋转。实际撞上玩家碰撞体的来弹为红色；
   只有从身边掠过的近失弹为白色，背后压一层暗影保证在沙地和天空上都读得出。 */
.hudHitDirs {
  position: absolute; left: 50%; top: 50%;
  width: max(180px, 76vmin); aspect-ratio: 1;
  transform: translate(-50%, -50%);
  pointer-events: none; overflow: visible; z-index: 6;
}
.hudHitArc { fill: url(#hudHitFillHit); }
.hudHitGlow { fill: url(#hudHitFillHit); opacity: 0.4; }
.hudHitDir.near .hudHitArc { fill: url(#hudHitFillNear); }
.hudHitDir.near .hudHitGlow { fill: url(#hudHitShade); opacity: 0.45; }
@media (prefers-reduced-motion: reduce) {
  .hudDamage.low::before { animation: none; opacity: 1; }
  .hudMeleeKillBlood { transform: none !important; }
}

/* 帧率默认固定在左上；目标通知下移一行，避免二者重叠。 */
.hudFps {
  position: absolute; top: 10px; left: 10px;
  font: 600 10px/1 ui-monospace, "Consolas", monospace;
  letter-spacing: 0.08em; color: rgba(230,223,205,0.42);
  text-shadow: 0 1px 2px rgba(0,0,0,0.6);
  font-variant-numeric: tabular-nums; pointer-events: none;
}
.hudFps.low { color: rgba(224,176,98,0.72); }

/* Selected B: one small objective, a target symbol and a faint rule. Updates still fade out. */
.hudTop {
  position: absolute; top: max(42px, 7.5vh); left: max(20px, 4vw, env(safe-area-inset-left));
  width: min(460px, calc(100vw - 80px));
  display: flex; flex-direction: column; align-items: flex-start;
  font-family: var(--ui-font);
}
.hudPhase {
  display: none;
}
.hudObjective {
  min-width: 0; max-width: 100%; box-sizing: border-box;
  display: grid; grid-template-columns: 1.25em minmax(0, 1fr); align-items: center; column-gap: 0.6em;
  min-width: min(200px, 100%); padding: 0 8px 8px 0;
  background: none; border: 0; border-bottom: 1px solid rgba(242,237,218,0.2); filter: none; opacity: 0;
  font-size: clamp(14px, 2.15vh, 22px);
}
.hudObjective .objectiveSymbol {
  width: 1.25em; height: 1.25em; fill: none; stroke: currentColor; stroke-width: 1.8;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.7));
}
.hudObjective .o {
  max-width: 100%; font-size: inherit; line-height: 1.25;
  color: rgba(242,237,218,0.98); font-weight: 600; letter-spacing: 0;
  -webkit-text-stroke: 0; text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}
.hudObjective .o { text-wrap: balance; }
.hudObjective .objectiveUpdate {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.hudForceStatus {
  position: absolute; top: 32px; right: 28px; max-width: min(300px, 44vw);
  padding: 0; opacity: 0;
  font: 400 10px/1.35 var(--ui-font);
  letter-spacing: 0; text-align: right; color: rgba(205,202,194,0.5);
  background: none; border: 0; text-shadow: 0 1px 2px rgba(0,0,0,0.82);
}
.hudForceStatus.flash { animation: hudPoolFlash 3.4s ease-out both; }
@keyframes hudPoolFlash {
  0% { opacity: 0; }
  10% { opacity: 1; }
  72% { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes hudObjectiveChanged {
  0% { opacity: 0; }
  7% { opacity: 1; }
  82% { opacity: 1; }
  100% { opacity: 0; }
}
.hudObjective.changed { animation: hudObjectiveChanged 6.4s ease-out both; }

/* 右下偏上：只有出现伤情、屏息或命令时才亮，且几秒不变就隐掉（Data_Tuning_Hud.IDLE_FADE.stateS）。
   `.on` 是「有东西可写」，`.awake` 是「刚变过」，两者都在才亮。淡入快、淡出慢，与弹药块同一手感。 */
.hudState {
  position: absolute; right: var(--hud-edge-x); bottom: calc(var(--hud-edge-bottom) + 11vh);
  display: flex; justify-content: flex-end; gap: 9px; max-width: 360px;
  padding: 0; font: 700 11px/1.4 var(--ui-font);
  color: rgba(224,223,217,0.9); opacity: 0; transition: opacity 0.6s ease;
  -webkit-text-stroke: 0.7px rgba(0,0,0,0.92); paint-order: stroke fill;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.9);
}
.hudState.on.awake { opacity: 1; transition: opacity 0.12s ease; }
.hudState .b { color: #d6604a; }
.hudState .w { color: var(--warn); }
.hudState .h { color: var(--ours); }
.hudState .c { color: var(--paper); }
/* B/D mockup: avoid duplicating blood + the actionable B prompt with an injury inventory row. */
.hudState .b, .hudState .w, .hudState .g {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* 2026-10-13 selected B: grenade silhouettes, a fine separator, then a weapon-name/ammo column.
   2026-10-14: restore the original UI labels and compact monospace numerals with soft shadows.
   整块只在交互后亮几秒（IDLE_FADE.combatS，由 Script_Hud 拨 `.awake`），
   空膛 / 低弹钉住不淡；淡入 0.12 s、淡出 0.6 s。 */
.hudCombat {
  position: absolute; right: var(--hud-edge-x); bottom: var(--hud-edge-bottom);
  display: flex; flex-direction: column; align-items: flex-end;
  color: #f2edda; font-family: var(--ui-font);
  opacity: 0; transition: opacity 0.6s ease;
  -webkit-text-stroke: 0;
  text-shadow: 0 1px 3px rgba(0,0,0,0.82);
}
.hudCombat.awake { opacity: 1; transition: opacity 0.12s ease; }
.combatReadout { display: flex; flex-direction: column; align-items: flex-start; gap: 0.2vh; }
.combatWeapon {
  min-height: 1.15em; padding: 0 1px 2px; text-align: left;
  color: #f2edda; font-size: 11px; font-weight: 700; line-height: 1.15; letter-spacing: 0.1em;
}
.combatMain { display: flex; align-items: flex-end; gap: clamp(9px, 1.5vh, 18px); }
.combatAmmo { display: flex; align-items: baseline; }
.ammoCurrent { font: 700 38px/1 "Cascadia Mono", Consolas, monospace; font-variant-numeric: lining-nums tabular-nums; letter-spacing: -0.04em; }
.ammoDivider {
  margin: 0 0.22em 0 0.3em; color: #f2edda;
  font: 400 18px/1 "Cascadia Mono", Consolas, monospace;
}
.ammoReserve { color: #f2edda; font: 700 18px/1 "Cascadia Mono", Consolas, monospace; font-variant-numeric: lining-nums tabular-nums; }
.hudCombat.lowAmmo .ammoCurrent { color: #df252c; }
.hudCombat.emptyAmmo .ammoCurrent { color: #df252c; animation: hudAmmoPulse 0.9s ease-in-out infinite; }
@keyframes hudAmmoPulse { 50% { opacity: 0.48; } }
.combatEquipment {
  display: flex; align-items: flex-end; gap: 9px;
  padding: 0 clamp(9px, 1.4vh, 17px) 0 0; border-right: 1px solid rgba(242,237,218,0.72);
  color: #f2edda;
}
.equipment { display: flex; align-items: center; gap: 4px; }
.equipment svg {
  width: 20px; height: 20px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.7));
}
.equipment b { font: 700 15px/1 "Cascadia Mono", Consolas, monospace; }
.grenadeStack { display: flex; align-items: flex-end; gap: clamp(3px, 0.55vh, 6px); }
.equipment .grenadeStack svg { display: none; width: clamp(16px, 2.5vh, 31px); height: clamp(34px, 5.5vh, 66px); stroke-width: 1.35; }
.grenade[data-count="0"] .grenadeStack svg:first-child,
.grenade[data-count="1"] .grenadeStack svg:first-child,
.grenade[data-count="2"] .grenadeStack svg:nth-child(-n+2),
.grenade[data-count="3"] .grenadeStack svg:nth-child(-n+3),
.grenade[data-count="4"] .grenadeStack svg:nth-child(-n+4),
.grenade.overflow .grenadeStack svg:first-child { display: block; }
.grenade:not(.overflow) b { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.grenade.overflow b::before { content: "×"; margin-right: 2px; }
/* 空的格子整个不画（集束 / 迫击炮平时都是 0，摆一排灰 0 只是噪音）；
   手榴弹是 COD 里常驻的那一格，打光了压暗留着 —— 「没弹了」本身是信息。 */
.equipment.empty { display: none; }
.equipment.grenade.empty { display: flex; opacity: 0.3; }

/* 字幕：与 logo 同款的思源宋体 Black（--ui-story-font，打包在 Font/Font_TitleText.woff2，
   不再依赖国内不通的 Google Fonts）。 */
.hudSubtitle {
  position: absolute; left: 50%; bottom: 90px; transform: translateX(-50%);
  max-width: 56%; text-align: center; opacity: 0;
  transition: opacity 0.3s ease; font-size: 16px; font-family: var(--ui-story-font);
}
.hudSubtitle.on { opacity: 1; }
.hudSubtitle .who { color: var(--warn); margin-right: 10px; }
.hudSubtitle .narr { color: var(--dim); font-style: italic; }
.hudSubtitle .subtitleLine + .subtitleLine { margin-top: 6px; }
/* 同时说话分主次：主讲（要玩家照做的那句）排最下、字大全亮；旁白排上面、
   小一号压暗，像隔着人听见的；说话人远（SUBTITLE_DEPTH.farM）整行再暗一档。
   旁白用不透明的暗色而不是半透明：半透明字会把底下的黑描边透出来，发脏。 */
.hudSubtitle .subtitleLine.lead { font-size: 1.12em; }
.hudSubtitle .subtitleLine.aside { font-size: 0.8em; }
.hudSubtitle .subtitleLine.aside .txt { color: #b4ac99; }
.hudSubtitle .subtitleLine.aside .who { color: #a8844c; }
.hudSubtitle .subtitleLine.aside + .subtitleLine.lead { margin-top: 8px; }
.hudSubtitle .subtitleLine.far { opacity: 0.6; }

.hudHint {
  position: absolute; left: 50%; bottom: 62px; transform: translateX(-50%);
  font-size: 13px; color: var(--dim); opacity: 0; transition: opacity 0.3s ease;
  border: 1px solid rgba(230,223,205,0.16); padding: 3px 12px; border-radius: 2px;
  background: rgba(10,10,9,0.42);
}
.hudHint.on { opacity: 1; }

/* 情境操作提示：只由真实可执行状态驱动，常驻；一次性反馈仍走上面的 hudHint。
   对标 COD WWII：准星正下方居中（--y 由 Script_Hud.SetCrosshair 按散布写，
   识别卡排在它下面），一行「键帽 + 一句动作」，米白字配柔和黑影、没有底板；
   拾枪时下面再画那把枪的剪影（Data_HudWeaponIcons）。打空了的「装弹」整行转红。
   字体是 logo 同款思源宋体 Black（--ui-story-font）。字号跟视口高度走，
   9-13 用户定为 clamp(20px, 3vh, 34px) 的 40%，随后再放大 20%（即 48%）：900 高约 13 px，1080 高约 15.6 px。 */
.hudActions {
  position: absolute; left: 50%; top: 50%; transform: translateX(-50%);
  margin-top: var(--y, 44px);
  display: flex; flex-direction: column; align-items: center; gap: 0.3em;
  font: 900 clamp(9.6px, 1.44vh, 16.32px)/1.2 var(--ui-story-font);
  z-index: 2; opacity: 0; transition: opacity 0.16s linear;
  white-space: nowrap; pointer-events: none;
}
.hudActions.on { opacity: 1; }
.hudActions.bandageOnly { font-size: clamp(11px, 2vh, 22px); }
.hudActions.bandageOnly .hudAction kbd { font-size: .9em; min-width: 1.5em; height: 1.5em; border-radius: .15em; }
.hudAction {
  --c: #ece3cc;
  display: flex; flex-direction: column; align-items: center; gap: 0.2em;
  color: var(--c); letter-spacing: 0.02em;
  text-shadow: 0 0 3px rgba(0,0,0,0.9), 0 1px 1px rgba(0,0,0,0.9);
}
.hudAction.reload { --c: #e8505b; }
.actionLine { display: flex; align-items: center; gap: 0.28em; }
/* 键帽：实心、与字同色，字母挖成深色；多字键（左键、1 / 2）自动加宽。 */
.hudAction kbd {
  display: inline-flex; align-items: center; justify-content: center;
  box-sizing: border-box; min-width: 1.3em; height: 1.3em; padding: 0 0.3em;
  border-radius: 0.25em; background: var(--c); color: #15130f;
  font: 900 0.8em/1 var(--ui-story-font); letter-spacing: 0; text-shadow: none;
  box-shadow: 0 0 3px rgba(0,0,0,0.6);
}
.actionWeapon { display: block; height: auto; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.85)); }

/* 按住型交互的进度环（按住止血 / 拆门板 / 撕短褂）。
   在准星正下方一点点：视线不用离开准星，也不压住下面的字幕行。
   环走满 = 完成；松手后 .fading 让它变灰往回退——玩家要能读出"我松手了，
   但还没退干净，按回去还来得及"，不然这一档看起来就是卡住。 */
.hudInteractRing {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, 46px);
  width: 44px; height: 44px; z-index: 3; opacity: 0;
  transition: opacity 0.12s linear; pointer-events: none;
}
.hudInteractRing.on { opacity: 1; }
.hudInteractRing svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.hudInteractRing circle { fill: none; stroke-width: 3; stroke-linecap: round; }
.hudInteractRing .ringBase { stroke: rgba(230,223,205,0.18); }
.hudInteractRing .ringFill { stroke: var(--warn); transition: stroke-dashoffset 0.05s linear; }
/* 长按确认（撕短褂 / 剪线）是不可逆的决定，用告警色与它区分开 */
.hudInteractRing.confirm .ringFill { stroke: #e18a71; }
.hudInteractRing.fading .ringFill { stroke: rgba(230,223,205,0.42); }
.hudInteractRing .ringLabel {
  position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  margin-top: 5px; white-space: nowrap; font-size: 12px; color: rgba(230,223,205,0.78);
  text-shadow: 0 1px 3px rgba(0,0,0,0.7);
}

/* 负重条：抬着什么、抬稳没有。贴在右下武器区上方——「手上是什么」本来就该在同一栏。
   bottom 排在 .hudState（流血/受伤/压制那一行）之上，两条不许叠 ——
   抬着担架挨枪子正是它们同时出现的时候。 */
.hudCarry {
  position: absolute; right: 18px; bottom: 194px; z-index: 3;
  display: flex; align-items: center; gap: 9px;
  padding: 6px 12px 6px 9px; opacity: 0; transition: opacity 0.16s linear;
  border: 1px solid rgba(230,223,205,0.24); border-left: 2px solid var(--warn);
  background: rgba(10,10,9,0.62);
}
.hudCarry.on { opacity: 1; }
.hudCarry .carryIco { display: flex; width: 22px; height: 22px; color: var(--warn); }
.hudCarry .carryIco svg {
  width: 100%; height: 100%; fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.hudCarry .carryText { display: flex; flex-direction: column; line-height: 1.3; }
.hudCarry .carryText b { color: var(--paper); font-size: 14px; font-weight: 600; }
.hudCarry .carryText i { color: var(--dim); font-size: 11px; font-style: normal; }
.hudCarry .carryBar {
  position: absolute; left: 0; bottom: 0; width: 100%; height: 2px;
  background: rgba(230,223,205,0.12);
}
.hudCarry .carryBar u { display: block; height: 100%; background: var(--warn); }
/* 举起 / 放下那两段是过渡态，条在走；抬稳了就满格不闪 */
.hudCarry.lift .carryBar u, .hudCarry.release .carryBar u { transition: width 0.06s linear; }

/* 负重时的武器 UI 禁用态：弹药、装备格、武器名一起压暗——这会儿一个都用不上。
   准星由装配层收掉（SetCrosshair 的 visible），不在这里做。 */
#hud.carrying .combatWeapon, #hud.carrying .combatAmmo,
#hud.carrying .combatEquipment { opacity: 0.3; filter: grayscale(0.8); }

/* 架设机枪面板。摆在准星**下方**、字幕上方：过热要在瞄准的同时读得到，
   放到屏幕角落等于没有（第五关唯一的教学界面就是这条热条）。
   与白刃 QTE 同一块视野，但两者不会同时出现（架着枪拼不了刺刀）。 */
.hudEmplacement {
  position: absolute; right: 32px; bottom: 176px; z-index: 6;
  width: min(272px, calc(100vw - 40px)); box-sizing: border-box;
  opacity: 0; transition: opacity 0.2s linear;
  padding: 8px 0; border: 0;
  background: linear-gradient(90deg, transparent, rgba(10,10,9,.16));
  text-shadow: 0 1px 3px #000;
  font-size: 12px; letter-spacing: 0.04em;
}
.hudEmplacement.on { opacity: 1; }
/* 热条：底槽 + 走条 + 一根警戒线。警戒线常驻——玩家要看得见"还剩多少余量"，
   不是等它红了才知道自己压太久。 */
.empHeat {
  position: relative; height: 2px; margin: 9px 0 0;
  background: rgba(230,223,205,0.14); overflow: hidden;
}
.empHeat u { display: block; height: 100%; width: 0; background: rgba(228,221,203,.75); transition: width 0.08s linear; }
.empHeat .empHeatWarn {
  position: absolute; top: -1px; bottom: -1px; width: 1px;
  background: rgba(230,223,205,0.55); text-decoration: none;
}
.hudEmplacement.heat-warm .empHeat u { background: #c9b168; }
.hudEmplacement.heat-hot .empHeat u { background: var(--warn); }
.hudEmplacement.heat-overheat { border-top-color: var(--theirs); }
.hudEmplacement.heat-overheat .empHeat u { background: var(--theirs); animation: empPulse 1.2s ease-in-out infinite; }
@keyframes empPulse { 50% { opacity: 0.45; } }
/* 小卡的排障进度：单独一条细线，不去占准星那个 F 交互环 */
.empJam { height: 2px; margin-top: 2px; background: transparent; }
.hudEmplacement.jam .empJam { background: rgba(230,223,205,0.14); }
.empJam u { display: block; height: 100%; width: 0; background: var(--paper); }
.empBottom { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-top: 5px; }
.empPrompt { color: var(--warn); font-style: normal; font-size: 12px; }
.hudEmplacement.jam .empPrompt, .hudEmplacement.dead .empPrompt,
.hudEmplacement.ammoEmpty .empPrompt { color: var(--theirs); }
.empExit { color: rgba(230,223,205,0.52); font-size: 11px; white-space: nowrap; }
.hudEmplacement.dead { border-top-color: var(--theirs); }
.hudEmplacement.dead .empHeat u { background: rgba(230,223,205,0.22); animation: none; }
/* 架着机枪时右下弹药读数换成机枪的（枪名/发数/低弹/空膛与步枪同一套），
   只把这会儿扔不出去的投掷物压暗 */
#hud.emplaced .combatEquipment { opacity: 0.3; filter: grayscale(0.8); }

/* 报码纸（终章亲手发报）。右下、负重条那一栏 —— 与「手上是什么」同一列。
   不摆到准星附近：那块地方归机枪热条与白刃 QTE，而发报根本不用瞄准。
   **不压暗武器 UI**：发报不占手，玩家随时能还手（§7「不夺控制权」）。 */
.hudTelegraph {
  position: absolute; right: 18px; bottom: 194px; z-index: 4;
  width: 152px; box-sizing: border-box;
  padding: 6px 9px 5px; opacity: 0; transition: opacity 0.16s linear;
  border: 1px solid rgba(230,223,205,0.24); border-left: 2px solid var(--ours);
  background: rgba(10,10,9,0.62);
  font-size: 11px; letter-spacing: 0.04em;
}
.hudTelegraph.on { opacity: 1; }
.tgTop { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.tgLabel { color: var(--paper); font-size: 12px; font-weight: 600; }
.tgCount { color: rgba(230,223,205,0.72); font: 600 11px/1 ui-monospace, Consolas, monospace; }
/* 一组一行。等宽字体是硬要求：四位一组的电码要能一眼竖着对齐着数。 */
.tgPaper {
  margin: 5px 0 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: 1px;
}
.tgGroup {
  display: flex; align-items: center; gap: 6px;
  color: rgba(230,223,205,0.82); font: 600 12px/1.45 ui-monospace, Consolas, monospace;
}
.tgGroup b { font-weight: 600; }
/* 勾：没发的是一个空框，发了的画一道横杠把那组划掉 —— 真的报务员就是这么销的。 */
.tgGroup .tgTick {
  width: 8px; height: 8px; box-sizing: border-box; flex: 0 0 auto;
  border: 1px solid rgba(230,223,205,0.34); text-decoration: none;
}
.tgGroup.sent { color: rgba(230,223,205,0.40); text-decoration: line-through; }
.tgGroup.sent .tgTick { border-color: var(--ours); background: var(--ours); }
.tgGroup.active { color: var(--paper); }
.tgGroup.active .tgTick { border-color: var(--paper); animation: tgKey 0.28s linear infinite; }
@keyframes tgKey { 50% { background: rgba(230,223,205,0.55); } }
/* 细条只画**这一组**那两三声「嗒」，不是整封的进度（整封看纸上勾了几组）。 */
.tgBar { height: 2px; margin-top: 5px; background: rgba(230,223,205,0.12); }
.tgBar u { display: block; height: 100%; width: 0; background: var(--paper); }
.tgBottom { margin-top: 4px; }
.tgPrompt { color: rgba(230,223,205,0.62); font-style: normal; font-size: 11px; }
/* 接头松了：整块换成警示色，提示语跟着变成「按住接回接头」。 */
.hudTelegraph.broken { border-left-color: var(--theirs); }
.hudTelegraph.broken .tgPrompt { color: var(--theirs); }
/* 报码纸与负重条同一格；抬着东西发不了报，两者不会同时出现，但真撞上时
   让负重条压在上面（它是更急的信息）。 */
#hud.carrying .hudTelegraph { opacity: 0; }

/* 白刃抵抗：侧下方显示武器控制进度与剩余时间；
   中央视野留给双手、交叉的武器与敌人。 */
.hudMeleeQte {
  position: absolute; left: 50%; top: 54%; z-index: 34;
  width: min(520px, calc(100vw - 34px)); box-sizing: border-box;
  transform: translate(-50%, -50%) scale(0.96); opacity: 0;
  padding: 18px 24px 15px; text-align: center;
  font-family: var(--ui-font);
  background: linear-gradient(115deg, rgba(8,9,10,0.90), rgba(23,18,13,0.82));
  border: 1px solid rgba(230,223,205,0.28);
  border-top: 2px solid rgba(224,176,98,0.88);
  box-shadow: 0 18px 60px rgba(0,0,0,0.48);
  transition: opacity 0.10s ease, transform 0.12s ease;
}
.hudMeleeQte.on { opacity: 1; transform: translate(-50%, -50%) scale(1); }

.mqSlow { color: rgba(230,223,205,0.48); font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase; }
.mqTitle { margin-top: 3px; color: var(--warn); font: 700 20px/1.35 "Noto Serif SC", serif; letter-spacing: 0.10em; }

.mqPrompt { min-height: 23px; margin-top: 4px; color: rgba(230,223,205,0.86); font-size: 13px; }
.mqKeys { min-height: 50px; display: flex; align-items: center; justify-content: center; gap: 9px; margin: 7px 0 9px; }
.mqKeys span { color: rgba(230,223,205,0.30); }
.mqKeys kbd {
  display: grid; place-items: center; min-width: 42px; height: 42px; padding: 0 8px;
  box-sizing: border-box; border: 1px solid rgba(230,223,205,0.38); border-radius: 3px;
  color: var(--paper); background: rgba(230,223,205,0.06);
  font: 700 18px/1 ui-monospace, Consolas, monospace;
}
.mqKeys kbd.expected { border-color: var(--warn); box-shadow: 0 0 18px rgba(224,176,98,0.25); animation: mqKey 0.55s ease-in-out infinite; }
.mqKeys kbd.done { color: rgba(157,192,228,0.92); border-color: rgba(157,192,228,0.62); }
@keyframes mqKey { 50% { transform: scale(1.08); background: rgba(224,176,98,0.14); } }
.mqProgress, .mqTimeline { position: relative; overflow: hidden; background: rgba(230,223,205,0.12); }
.mqProgress { height: 6px; }
.mqTimeline { height: 3px; margin-top: 7px; overflow: visible; }
.mqProgress i, .mqTimeline i { display: block; height: 100%; background: var(--warn); transition: width 0.06s linear; }
.mqTimeline i { background: rgba(230,223,205,0.74); }
.mqTimeline b { position: absolute; top: -3px; height: 9px; background: rgba(224,176,98,0.46); border-inline: 1px solid var(--warn); }
.mqResult { height: 20px; margin-top: 5px; color: rgba(230,223,205,0.65); font: 700 12px/20px ui-monospace, Consolas, monospace; letter-spacing: 0.12em; }
.mqAssist { color: rgba(230,223,205,0.38); font-size: 10px; }
.hudMeleeQte.success .mqResult { color: var(--ours); }
.hudMeleeQte.fail .mqResult, .hudMeleeQte.wrong .mqResult { color: var(--theirs); }
.hudMeleeQte.wrong { animation: mqWrong 0.14s linear; }
@keyframes mqWrong { 50% { transform: translate(calc(-50% + 8px), -50%); } }

/* 史实注记 */
.hudNote {
  position: absolute; right: 20px; top: 70px; width: 310px;
  background: rgba(10,10,9,0.80); border-left: 2px solid var(--warn);
  padding: 12px 14px; opacity: 0; transform: translateX(12px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}
.hudNote.on { opacity: 1; transform: translateX(0); }
.hudNote .nTier {
  font-size: 11px; color: var(--warn); letter-spacing: 0.14em; margin-bottom: 3px;
}
.hudNote .nTitle { font-size: 15px; font-weight: 600; margin-bottom: 6px; }
.hudNote .nBody { font-size: 12.5px; line-height: 1.75; color: var(--dim); }

/* 命令表（按住 Tab） */
.hudOrders {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(0.94);
  display: none; grid-template-columns: repeat(3, 1fr); gap: 8px 18px;
  background: rgba(8,8,7,0.72); padding: 18px 26px; border: 1px solid rgba(230,223,205,0.12);
}
.hudOrders.on { display: grid; }
.hudOrderRow { display: flex; align-items: baseline; gap: 8px; }
.hudOrderRow b { color: var(--warn); font-size: 13px; }

/* HUD 各层的叠放次序。
   【2026-08-20】以前**一层都没设 z-index**（实测 computed 全是 auto），
   叠放次序＝Hud.Build() 的 DOM 建序，于是 markers(第 9 个) < brief(13) < title(14)：
   功能层在最底下、演出层盖在它上面，纯属建序的巧合而不是设计。
   写成显式的三档，以后往 Build() 里插一个元素不会再默默改变谁压谁。 */
.hudMarkers { z-index: 1; }
.hudGrenadeWarnings { z-index: 2; }
.hudBrief, .hudTitle { z-index: 3; }
.hudDeathCard { z-index: 5; }

/* 开场演出（简报 / 章节卡）在的时候，把功能层压到 18%。
   两者本来就不该同时满不透明地占中间那块地方。 */
/* 开场那几秒**硬关**方向指示器，不是调暗。
   调暗（原来是 0.18）的问题是：重叠面积一个像素都不少，指示器变成压在
   考据过的开场白底下的一层脏纹理 —— 既没导航成，还把导航和旁白一起毁了。
   实测原值下简报与指示器重叠 97774 px²、连续 7 秒。
   要么完整、要么不在。照抄阵亡卡那条先例（第 173 行），不引入新概念。
   那几秒功能层本来也没有决策价值：玩家站在出生点、目标在正前方、
   剧本正让班长说「跟着走」，此刻唯一要做的事就是跟上。 */
#hud.staging .hudMarkers, #hud.staging .hudMissionGuide, #hud.staging .hudActions,
#hud.staging .hudInteractRing, #hud.staging .hudCarry,
#hud.staging .hudCombat, #hud.staging .hudState,
#hud.staging .hudTarget { opacity: 0; }
.hudMarkers { transition: opacity 0.4s ease; }

/* 近弹警告：屏内钉在活手榴弹上，屏外贴边。没有秒数倒计时——引信只用来驱动
   最后一秒的红色脉冲，给玩家“马上离开”的紧迫度，不把内部精确数值白送出来。 */
.hudGrenadeWarnings { position: absolute; inset: 0; }
.hudGrenadeWarning {
  position: absolute; transform: translate(-50%, -50%) scale(0.8);
  width: 46px; height: 46px; pointer-events: none;
  color: #e75243; font: 600 12px/1.2 var(--ui-font);
  white-space: nowrap;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.95));
}
.hudGrenadeWarning .ico {
  position: relative; display: grid; place-items: center;
  width: 46px; height: 46px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(88,9,5,0.48), rgba(88,9,5,0) 70%);
}
.hudGrenadeWarning .ico::before {
  content: ""; position: absolute; inset: 3px;
  border: 2px solid currentColor; border-bottom-color: transparent; border-radius: 50%;
  opacity: 0.8;
}
.hudGrenadeWarning .ico i {
  display: block; width: 30px; height: 30px; background: currentColor;
  mask: url("./Texture/Icon_GrenadeWarning_Publish39d3982761281c9293f50778.png?v=20260928") center / contain no-repeat;
}
.hudGrenadeWarning .direction {
  position: absolute; inset: 0; transform: rotate(var(--grenade-direction, 0deg));
}
.hudGrenadeWarning .direction::after {
  content: ""; position: absolute; left: 18px; bottom: -3px;
  width: 0; height: 0; border-left: 5px solid transparent;
  border-right: 5px solid transparent; border-top: 6px solid #fff5e8;
}
.hudGrenadeWarning .txt {
  position: absolute; top: 48px; left: 50%; transform: translateX(-50%);
  display: none; align-items: center; gap: 6px; color: #fff5e8;
  text-shadow: 0 1px 3px #000;
}
.hudGrenadeWarning .txt kbd {
  display: grid; place-items: center; min-width: 20px; height: 20px;
  border: 1px solid rgba(255,245,232,0.85); border-radius: 2px;
  background: rgba(15,12,10,0.6); font: 600 13px/1 Arial, sans-serif;
}
.hudGrenadeWarning.returnable .txt { display: flex; }
.hudGrenadeWarning.lethal { color: #ff5746; }
.hudGrenadeWarning.urgent .ico { animation: hudGrenadePulse 0.42s ease-in-out infinite; }
@keyframes hudGrenadePulse {
  0%, 100% { opacity: 0.7; transform: scale(0.95); }
  50% { opacity: 1; transform: scale(1.08); }
}
@media (prefers-reduced-motion: reduce) {
  .hudGrenadeWarning.urgent .ico { animation: none; color: #ffb0a4; }
}

/* 占领点图标 */
.hudMarkers { position: absolute; inset: 0; }
.hudMissionGuide { position:absolute; left:0; top:0; width:0; height:0; z-index:2; pointer-events:none; color:#eee4b0; text-shadow:0 1px 2px #000,1px 0 2px #000,-1px 0 2px #000; font-weight:600; transition:opacity .2s; }
.hudMissionGuide[hidden] { display:none; }
.hudMissionGuide.leader { color:#f2edda; }
.hudMissionGuide .guideAction,.hudMissionGuide .guideDetail { position:absolute; left:0; width:190px; text-align:center; transform:translateX(-50%); white-space:nowrap; }
.hudMissionGuide .guideAction { bottom:15px; font-size:14px; letter-spacing:1px; }
.hudMissionGuide .guideDetail { top:15px; font-size:12px; color:#eeeee4; }
.hudMissionGuide.leader .guideAction { position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); }
.hudMissionGuide.leader .guideDetail { top:auto; bottom:20px; font-size:clamp(12px,1.85vh,19px); font-weight:500; }
.hudMissionGuide .guideDiamond { position:absolute; left:-6px; top:-6px; width:10px; height:10px; border:2px solid currentColor; transform:rotate(45deg); box-shadow:0 0 2px #000,inset 0 0 2px #000; }
.hudMissionGuide .guideArrow { display:none; position:absolute; left:-5px; top:-5px; width:9px; height:9px; border-left:2px solid currentColor; border-top:2px solid currentColor; transform:rotate(calc(var(--guide-angle) + 45deg)); }
.hudMissionGuide.offscreen .guideDiamond { display:none; }
.hudMissionGuide.offscreen .guideArrow { display:block; }
.hudMissionGuide.near .guideDetail { opacity:0; }
.hudMarker {
  /* 位置由 Script_Hud.UpdateMarkers 每帧写 transform（含 -50% 居中）；
     will-change 让它独占合成层，挪动时不触发布局与重绘。 */
  position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); will-change: transform;
  display: flex; flex-direction: column; align-items: center; font-size: 11px;
  opacity: 0.9;
}
.hudMarker .ico { font-size: 13px; }
.hudMarker.ours { color: var(--ours); }
.hudMarker.theirs { color: var(--theirs); }
.hudMarker.fight { color: var(--warn); }
.hudMarker .bar {
  width: 42px; height: 2px; background: rgba(255,255,255,0.18); margin-top: 2px; display: block;
}
.hudMarker .bar i { display: block; height: 100%; background: currentColor; }

.hudMinimap {
  position: absolute; left: 18px; bottom: 18px; width: 190px; height: 190px;
  display: none; border: 1px solid rgba(230,223,205,0.14); opacity: 0.9;
}
.hudMinimap.on { display: block; }

@media (max-width: 700px) {
  .hudTop {
    top: max(14px, calc(env(safe-area-inset-top) + 8px)); left: 8px;
    width: min(76vw, 350px);
  }
  .hudObjective { width: 100%; }
  .hudObjective .o { font-size: 14px; }
  .hudForceStatus { top: max(30px, calc(env(safe-area-inset-top) + 20px)); right: 10px; font-size: 9px; }
  .hudMinimap { left: 10px; bottom: max(10px, env(safe-area-inset-bottom)); width: 124px; height: 124px; }
  .hudCombat { right: 10px; bottom: max(10px, env(safe-area-inset-bottom)); }
  .ammoCurrent { font-size: 30px; }
  .ammoReserve, .ammoDivider { font-size: 18px; }
  .combatWeapon { font-size: 12px; }
  .combatMain { gap: 9px; }
  .combatEquipment { gap: 6px; padding-right: 9px; }
  .equipment .grenadeStack svg { width: 15px; height: 32px; }
  .hudState { right: 10px; bottom: calc(max(10px, env(safe-area-inset-bottom)) + 74px); max-width: 230px; }
  .hudCarry { right: 10px; bottom: calc(max(10px, env(safe-area-inset-bottom)) + 170px); }
  .hudTelegraph { right: 10px; bottom: calc(max(10px, env(safe-area-inset-bottom)) + 170px); width: 132px; }
  .hudInteractRing { transform: translate(-50%, 38px); }
  .hudSubtitle { bottom: 78px; max-width: calc(100vw - 42px); font-size: 14px; }
  .hudHint { bottom: 50px; }
}

/* 阵亡：第一人称镜头在 Canvas 里倒地，这一层只做半透明去色与生平。
   不再用不透明黑底；战场必须一直看得见，死亡才仍然发生在同一个地方。 */
.hudDeathCard {
  position: absolute; inset: 0; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 9vh 5vw 0; opacity: 0; pointer-events: none;
  color: #eee9dd; background: rgba(5, 7, 9, 0.42);
  backdrop-filter: grayscale(0.92) saturate(0.38) contrast(0.94) brightness(0.82);
  -webkit-backdrop-filter: grayscale(0.92) saturate(0.38) contrast(0.94) brightness(0.82);
  /* 没在显示时整层不绘制：opacity:0 的 backdrop-filter 合成器照样每帧滤一遍全屏。
     visibility 延到淡出结束才切，淡入淡出的 0.32 s 不变。 */
  visibility: hidden;
  transition: opacity 0.32s ease, visibility 0s linear 0.32s;
}
.hudDeathCard.on { opacity: 1; visibility: visible; transition: opacity 0.32s ease, visibility 0s; }
.hudDeathCard::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background:
    linear-gradient(180deg, rgba(5,7,9,0.05) 0%, rgba(5,7,9,0.01) 42%, rgba(5,7,9,0.28) 100%),
    radial-gradient(ellipse at center, rgba(0,0,0,0) 38%, rgba(0,0,0,0.20) 100%);
}
.hudDeathCard .dcBiography {
  position: relative; z-index: 1; width: min(760px, 86vw);
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
}
.hudDeathCard .dcKicker {
  margin-bottom: 10px; color: rgba(224,176,98,0.92);
  font-size: 12px; letter-spacing: 0.42em;
}
.hudDeathCard .dcName {
  font-size: clamp(64px, 6.5vw, 112px); letter-spacing: 0.18em;
  text-indent: 0.18em; font-weight: 700; line-height: 1.08;
}
.hudDeathCard .dcRule {
  width: min(560px, 72vw); height: 1px; margin: 24px 0 17px;
  background: linear-gradient(90deg, rgba(238,233,221,0), rgba(238,233,221,0.52), rgba(238,233,221,0));
}
.hudDeathCard .dcOrigin {
  margin-top: 7px; font-size: 17px; color: rgba(238,233,221,0.72); letter-spacing: 0.18em;
  text-indent: 0.18em;
}
.hudDeathCard .dcYears {
  font-size: 23.1px; font-weight: 600; color: rgba(238,233,221,0.84); letter-spacing: 0.22em;
  text-indent: 0.22em;
}
.hudDeathCard .dcUnit {
  margin-top: 17px; font-size: 14px; color: rgba(238,233,221,0.52); letter-spacing: 0.18em;
  text-indent: 0.18em;
}

/* 阵亡时功能 HUD 退场，底下 Canvas 与环境仍然活着。 */
#hud.deathCardOn > *:not(.hudDeathCard) { opacity: 0 !important; transition: opacity 0.3s ease; }

@media (max-width: 640px) {
  .hudMeleeQte { top: 49%; padding: 14px 15px 12px; }
  .mqTitle { font-size: 17px; }
  .mqKeys kbd { min-width: 38px; height: 38px; font-size: 16px; }
  .hudDeathCard { padding: 7vh 7vw 0; }
  .hudDeathCard .dcName { font-size: 58px; }
  .hudDeathCard .dcYears { font-size: 21px; }
  .hudDeathCard .dcOrigin { font-size: 15px; }
}
/* 剧本拍（第一关屋内伏击）：HUD 全部让位，只留字幕、提示环与满屏的受伤／血。
   与下面的 .cinematic 分两档：过场那一档连字幕都归过场自己画，这一档要留字幕。
   阵亡卡不在让位名单里 —— 这一拍里死掉时它必须盖上来。 */
#hud.cinematicBeat > *:not(.hudSubtitle):not(.hudCinematicPrompt):not(.hudDamage):not(.hudMeleeKillBlood):not(.hudStoryBlood):not(.hudLensMud):not(.hudLensFlash):not(.hudDeathCard):not(.csRoot):not(.previewTerminal) {
  opacity: 0 !important; transition: none !important;
}

/* 剧本提示环：半透明的圈 + 中间一个键面字，钉在压上来那把枪上（left/top 由 HUD 写）。
   一次只有一个，三种读法共用同一个环：
     press     弧从满到空 —— 漏完就是刀捅进来了
     mash      弧从空到满 —— 连按把「我方控制」推上去，每次有效按键脉冲一下
     finisher  换色换字 —— 这一下捅回去
   不做标题、不做进度条、不做时间轴：玩家这会儿在看那把刀，不是在看仪表。 */
.hudCinematicPrompt {
  position: absolute; left: 50%; top: 54%; width: 105px; height: 105px;
  transform: translate(-50%, -50%); z-index: 36; opacity: 0;
  transition: opacity 0.12s linear; pointer-events: none; --cpPulse: 0;
}
.hudCinematicPrompt.on { opacity: 1; }
.hudCinematicPrompt svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.hudCinematicPrompt circle { fill: none; stroke-width: 4; stroke-linecap: round; }
.hudCinematicPrompt .cpBase { stroke: rgba(8,8,9,0.46); }
.hudCinematicPrompt .cpArc { stroke: rgba(230,223,205,0.92); transition: stroke-dashoffset 0.05s linear; }
.hudCinematicPrompt.mash .cpArc { stroke: var(--warn); }
.hudCinematicPrompt.finisher .cpArc { stroke: #d8604a; }
.hudCinematicPrompt .cpKey {
  position: absolute; inset: 0; display: grid; place-items: center;
  font: 700 34px/1 var(--ui-font); color: var(--paper);
  text-shadow: 0 2px 10px rgba(0,0,0,0.85), 0 0 3px rgba(0,0,0,0.9);
  transform: scale(calc(1 + var(--cpPulse) * 0.14));
}
.hudCinematicPrompt.finisher .cpKey { font-size: 22px; color: #f0d6cb; }
/* 按键那一下要有东西动：连按时中心字跳一下，等按键时环自己轻微呼吸。 */
.hudCinematicPrompt.press .cpArc, .hudCinematicPrompt.finisher .cpArc { animation: cpBreath 1.1s ease-in-out infinite; }
@keyframes cpBreath { 50% { opacity: 0.62; } }
@media (prefers-reduced-motion: reduce) {
  .hudCinematicPrompt .cpArc { animation: none !important; }
  .hudCinematicPrompt .cpKey { transform: none; }
}
@media (max-width: 640px) {
  .hudCinematicPrompt { width: 81px; height: 81px; }
  .hudCinematicPrompt .cpKey { font-size: 26px; }
  .hudCinematicPrompt.finisher .cpKey { font-size: 16px; }
}

/* 过场期间：HUD 全部让位，只留过场自己的字幕层（.csRoot 也挂在 #hud 下） */
#hud.cinematic > *:not(.csRoot):not(.previewTerminal) { opacity: 0 !important; transition: none !important; }
.previewTerminal {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 12px;
  pointer-events: none; text-align: center; color: var(--paper);
  background: radial-gradient(ellipse at center, rgba(8,8,10,0.16), rgba(8,8,10,0.66));
  opacity: 0; transition: opacity 0.35s ease; z-index: 20;
}
.previewTerminal.on { opacity: 1; }
.previewTerminal .title { font-size: clamp(22px, 3vw, 40px); letter-spacing: 0.28em; }
.previewTerminal .task { color: var(--warn); font-size: clamp(15px, 1.5vw, 22px); letter-spacing: 0.16em; }
.previewTerminal .note { color: var(--dim); font-size: 12px; letter-spacing: 0.12em; }

/* 阶段开场 */
.hudBrief {
  position: absolute; left: 8%; top: 34%; max-width: 46%;
  opacity: 0; transition: opacity 0.6s ease;
}
.hudBrief.on { opacity: 1; }
.hudBrief .bTitle {
  font-size: 13px; color: var(--warn); letter-spacing: 0.2em; margin-bottom: 10px;
}
.hudBrief .bLine { font-size: 17px; line-height: 2.0; }

/* 加载 */
/* 加载画面。版式参考 Notion「加载界面｜战前报纸剪报方案与史料库」：
   黑底；左上标题与日期；右侧一张战前报纸剪报（Script_BootPaper，每次开机随机一张）；
   左下「史料摘录 | 《报名》 日期」+ 简述；底部居中「进 城」、步骤行与进度条。
   进度条仍在底部并加粗：它是这张画面上唯一"还要等多久"的信息。 */
#boot {
  position: fixed; inset: 0; background: var(--ui-black); font-family: var(--ui-font); color: var(--paper);
  z-index: 10; overflow: hidden;
}
#boot.gone { display: none; }
/* 报纸图是「纸 + 一圈黑边」的紧裁图，横幅 / 近方 / 竖幅三种宽高比都有：按高度与宽度两头封顶、比例自动保持。
   外层 #bootPaperWrap 管位置、拖拽倾斜（变量由 Script_BootPaper 写）和 lighten 混合 —— 图边的黑与页面黑融成一片，
   不留方框边；混合挂在外层；内层 surface 同步漂移 img 与后台绘制的 PBR canvas。
   松手回正是 CSS 过渡（合成线程），主线程被建关卡堵住时也回得动；拖的时候 .dragging 关掉过渡，跟手。 */
#bootPaperWrap {
  position: absolute; left: 63vw; top: 46%; width: max-content; height: max-content;
  transform: translate(-50%, -50%) perspective(var(--bootPaperPerspective, 1500px))
    rotateX(var(--bootPaperPitch, 0deg)) rotateY(var(--bootPaperYaw, 0deg));
  transition: transform var(--bootPaperReturn, 0.9s) cubic-bezier(0.2, 0.8, 0.2, 1);
  mix-blend-mode: lighten; cursor: grab; touch-action: none; user-select: none;
  will-change: transform;
}
#bootPaperWrap.dragging { transition: none; cursor: grabbing; }
#bootPaperSurface { position: relative; animation: bootPaperDrift 70s ease-in-out infinite alternate; }
#bootPaper {
  display: block; width: auto; height: auto; max-width: 62vw; max-height: 82vh;
  opacity: 0; transition: opacity 1.1s ease; pointer-events: none; user-select: none;
}
#bootPaper.on { opacity: 1; }
.bootPaperPbr {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; opacity: 0; transition: opacity 0.35s ease;
}
#bootPaper.on + .bootPaperPbr.ready { opacity: 1; }
/* 纸极缓地漂近一点点，像镜头在慢推；只动 transform，不触发布局。 */
@keyframes bootPaperDrift {
  from { transform: scale(1); }
  to { transform: scale(1.04); }
}
@media (prefers-reduced-motion: reduce) { #bootPaperSurface { animation: none; } }
#bootHead {
  position: absolute; left: 4vw; right: 4vw; top: 4vh; text-align: left; pointer-events: none;
}
#bootTitle {
  font-family: var(--ui-title-font);
  font-size: clamp(28px, 2.65vw, 42px); font-weight: 700; color: var(--ui-bright); letter-spacing: 0.07em;
}
#bootSub { font-size: 12.5px; color: var(--dim); letter-spacing: 0.07em; margin-top: 10px; }

/* 史料说明：贴左下。第一行金色「史料摘录 | 《报名》」+ 日期，第二行简述。 */
#bootCard {
  position: absolute; left: 4vw; bottom: 132px; max-width: min(34vw, 420px);
  pointer-events: none;
}
#bootPaperName {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 10px;
  font-size: 16px; color: var(--paper); letter-spacing: 0.04em;
}
#bootPaperName .kicker, #bootPaperName b { font-weight: 700; color: var(--ui-gold); }
#bootPaperName i { width: 1px; height: 0.95em; background: rgba(230,223,205,0.4); align-self: center; }
#bootPaperName .date { color: var(--paper); }
#bootPaperNote {
  font-size: 13px; line-height: 1.75; color: var(--dim); margin-top: 8px; letter-spacing: 0.03em;
}
/* 竖屏 / 窄屏：纸放大顶在上半屏，说明压在纸下方，不与纸叠字。 */
@media (max-aspect-ratio: 1/1) {
  #bootPaperWrap { left: 50vw; top: 40%; }
  #bootPaper { max-width: 96vw; max-height: 58vh; }
  #bootCard { max-width: 88vw; bottom: 150px; }
}
#bootFoot {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding-bottom: 26px;
}
#bootStep {
  font-size: 12px; color: var(--dim); min-height: 1.4em; letter-spacing: 0.08em;
}
#bootBar {
  width: min(74vw, 760px); height: 6px;
  background: rgba(230,223,205,0.12); border: 1px solid rgba(230,223,205,0.16);
}
#bootBar i {
  display: block; height: 100%; width: 0; background: var(--warn);
  transition: width 0.2s ease;
}
#bootStart {
  pointer-events: auto; cursor: pointer;
  border: 1px solid rgba(230,223,205,0.3); background: var(--ui-selection); color: var(--paper);
  font: inherit; font-size: 17px; font-weight: 700; letter-spacing: 0.08em; padding: 9px 34px;
}
#bootStart[disabled] { opacity: 0.3; cursor: default; }
#bootStart:not([disabled]):hover { background: var(--ui-selection); color: var(--ui-gold); border-color: var(--ui-gold); }
/* `#bootPreview`（序章预览链接）2026-09-07 随加载画面上的入口一起摘掉，见 index.html。 */

/* 章节卡：阶段开场那一行大字 */
.hudTitle {
  position: absolute; left: 0; right: 0; top: 38%;
  text-align: center; opacity: 0; transition: opacity 0.7s ease;
}
.hudTitle.on { opacity: 1; }
.hudTitle .tMain { font-size: 40px; letter-spacing: 0.30em; }
.hudTitle .tSub {
  margin-top: 12px; font-size: 13px; color: var(--dim); letter-spacing: 0.22em;
}

/* 喊话：比普通台词重一档 */
.hudSubtitle.shout .txt { font-weight: 600; letter-spacing: 0.04em; }
.hudSubtitle.shout .who { color: #e8c07a; }

/* 尾声：一行一行浮出来。不打歼敌数 —— 那是宣传口径。 */
.hudEpilogue {
  position: absolute; inset: 0; background: rgba(6, 6, 8, 0.94);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; opacity: 0; transition: opacity 1.4s ease;
}
.hudEpilogue.on { opacity: 1; }
.hudEpilogue .eLine { font-size: 17px; line-height: 2.1; letter-spacing: 0.08em; }
.hudEpilogue .eGap { height: 14px; }

/* 投弹蓄力条 */
.hudCook {
  position: absolute; left: 50%; bottom: 46px; transform: translateX(-50%);
  height: 3px; background: var(--warn); opacity: 0; transition: opacity 0.12s linear;
}
.hudCook.on { opacity: 0.9; }

/* 标准 FPS 动态准心：固定屏幕中心；腰射常驻，开镜隐藏。
   **缝（--gap）是真实散布角投影出来的像素**（见 Script_Hud.CrosshairGeometry），
   不是手感常数：跑起来它就该撑开到盖住半个人，那才是当时真实的落点范围。
   线本身要在乱糟糟的砖墙上读得出来 —— 骨白线 + 一圈硬黑描边，
   靠 box-shadow 铺描边而不是 filter：filter 会把 2 px 的线糊成一团灰。
   枪体动画与后坐可以动，但 HUD 瞄准基准绝不能跟着视图模型漂移。 */
.hudCrosshair {
  position: absolute; left: 50%; top: 50%; width: 0; height: 0;
  z-index: 3; opacity: 0; color: rgba(244, 241, 231, 0.98);
  --arm: 10px; --thick: 2px;
  transition: opacity 0.08s linear;
}
.hudCrosshair.on { opacity: 0.96; }
.hudCrosshair.sprint { opacity: 0.72; }
.hudCrosshair .arm, .hudCrosshair .dot {
  position: absolute; display: block; box-sizing: border-box; background: currentColor;
  box-shadow: 0 0 0 1px rgba(6, 6, 8, 0.72), 0 1px 2px rgba(0, 0, 0, 0.55);
}
.hudCrosshair .left, .hudCrosshair .right {
  top: calc(var(--thick) / -2); width: var(--arm); height: var(--thick);
}
.hudCrosshair .left  { right: var(--gap, 12px); }
.hudCrosshair .right { left:  var(--gap, 12px); }
.hudCrosshair .up, .hudCrosshair .down {
  left: calc(var(--thick) / -2); width: var(--thick); height: var(--arm);
}
.hudCrosshair .up   { bottom: var(--gap, 12px); }
.hudCrosshair .down { top:    var(--gap, 12px); }
.hudCrosshair .dot {
  left: -1.5px; top: -1.5px; width: 3px; height: 3px; border-radius: 50%;
}
/* 冲刺时中心点收掉：那一段按下扳机什么也不会发生，不该留一个"这里能打中"的点。 */
.hudCrosshair.sprint .dot { opacity: 0; }
/* 投弹专用圆弧准心：按住 G/H 或投掷物槽左键时盖住枪械的四臂准心。
   256 px 透明源图在 720p HUD 上显示为 64 px，保留约 48 px 的实际圆弧直径。 */
.hudCrosshair.grenade::before {
  content: "";
  position: absolute; left: -32px; top: -32px; width: 64px; height: 64px;
  background: url("./Texture/Icon_GrenadeReticle_Publish1acc3b510f9ebcdb3f346391.png") center / contain no-repeat;
}
.hudCrosshair.grenade .arm, .hudCrosshair.grenade .dot { opacity: 0; }
/* 指着自己人：整个准心转蓝（见 Script_Hud.SetTarget 的账，只给自己人上色）。 */
.hudCrosshair.friendly { color: var(--ours); }

/* 目标识别卡：准心正下方，跟着散布让开（--y 由 Script_Hud.SetCrosshair 写）。
   两行字 —— 敌人是番号/兵种 + 枪与距离，自己人是姓名 + 岁数与距离。
   血条只有体验档才有（DIFFICULTY.targetInfo）。

   **没有底板**。原来这里垫着一条竖向渐变的暗带，它是照 COD 的名牌抄来的，
   但 COD 的画面亮而干净，我们的画面本来就是灰土加雾 —— 一条 0.42 的黑带压在屏幕正中
   反而成了整幅画面上最像"UI 控件"的东西，人一动它就跟着飘。
   现在只靠字自己的描边扛读性：两层黑影（一层实、一层散）在雪地、墙面、天空上都读得出，
   而且不遮任何东西。字体与准星下的提示、字幕一致，用 logo 同款思源宋体 Black。 */
.hudTarget {
  position: absolute; left: 50%; top: 50%; z-index: 3;
  transform: translate(-50%, 0); margin-top: var(--y, 46px);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 96px; padding: 3px 10px 4px; opacity: 0;
  font-family: var(--ui-story-font);
  text-align: center; white-space: nowrap; pointer-events: none;
  transition: opacity 0.1s linear;
  text-shadow: 0 1px 2px rgba(0,0,0,0.95), 0 0 6px rgba(0,0,0,0.78);
}
.hudTarget.on { opacity: 1; }
.hudTarget .tTitle {
  font-size: 13px; font-weight: 600; letter-spacing: 0.06em; color: var(--paper);
}
.hudTarget .tMeta {
  font-size: 10px; letter-spacing: 0.08em; color: rgba(230,223,205,0.66);
  font-variant-numeric: tabular-nums;
}
.hudTarget.theirs .tTitle { color: var(--theirs); }
.hudTarget.ours   .tTitle { color: var(--ours); }
/* 尸体：不给阵营色，字压暗。它是一条线索（还有枪、还有桥夹），不是一个目标。 */
.hudTarget.corpse .tTitle { color: rgba(230,223,205,0.62); font-weight: 500; }
.hudTarget .tBar {
  width: 62px; height: 2px; margin-top: 1px; background: rgba(12,12,14,0.72);
}
.hudTarget .tBar i { display: block; height: 100%; background: currentColor; }
.hudTarget.theirs .tBar i { background: var(--theirs); }
.hudTarget.ours   .tBar i { background: var(--ours); }

/* 命中记号 —— 屏幕正中四道短撇。
   它叠在准心上仍必须小、暗、短命，不能盖住跑动和腰射的方向反馈。
   四道撇按 45° 斜角排，靠 --spread 往外弹一下；命中是红色，击杀是干血红且更长。 */
.hudHitmark {
  position: absolute; left: 50%; top: 50%; width: 34px; height: 34px;
  margin: -17px 0 0 -17px; z-index: 4; isolation: isolate;
  opacity: 0; --spread: 5px; --len: 9px; --mk: rgba(239, 83, 70, 1);
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.9));
}
.hudHitmark .t {
  position: absolute; left: 17px; top: 16px; display: block;
  width: var(--len); height: 2px; background: var(--mk);
  transform-origin: 0 50%;
}
.hudHitmark .t:nth-child(1) { transform: rotate(45deg)   translateX(var(--spread)); }
.hudHitmark .t:nth-child(2) { transform: rotate(135deg)  translateX(var(--spread)); }
.hudHitmark .t:nth-child(3) { transform: rotate(-135deg) translateX(var(--spread)); }
.hudHitmark .t:nth-child(4) { transform: rotate(-45deg)  translateX(var(--spread)); }
/* 击杀：更长、干血红。不做旋转/放大动画 —— 那是连杀播报的语汇，不是这个游戏的。 */
.hudHitmark.kill { --len: 13px; --mk: rgba(204, 66, 48, 1); }
.meleeLab{--mlMaxHeight:calc(100dvh - 36px);position:fixed;left:18px;top:18px;z-index:38;box-sizing:border-box;width:300px;max-width:calc(50vw - 36px);max-height:var(--mlMaxHeight);overflow:auto;background:rgba(19,25,27,.93);color:#e9e6d9;border:1px solid #788280;border-top:3px solid #c5af72;padding:16px;font:13px/1.55 system-ui,sans-serif;box-shadow:0 10px 38px #0007;pointer-events:auto}
.meleeLab[hidden]{display:none}.mlHeading{display:flex;flex-wrap:wrap;gap:4px 10px;justify-content:space-between;align-items:baseline;margin-bottom:12px}.mlHeading b{font-size:18px}.mlHeading span{font-size:11px;color:#b2b9b2}.meleeLab label{display:block;color:#adb6ae;font-size:11px}.meleeLab select{width:100%;background:#273034;color:#f7f1df;border:1px solid #65706c;padding:8px;margin:5px 0 10px}.mlButtons{display:flex;gap:7px}.meleeLab button{background:#c7b276;color:#172020;border:0;padding:8px 10px;cursor:pointer;flex:1}.meleeLab button:focus-visible,.meleeLab select:focus-visible{outline:2px solid #fff}.mlTip{color:#e0d3af;margin:12px 0}.mlControls{font-size:12px;color:#b9c2c0;border-top:1px solid #54615a;padding-top:10px}.mlControls small{color:#d8c181}.mlStatus{display:block;color:#cdd9ad;margin-bottom:8px}.mlMeters,.mlTargets,.mlLog{white-space:pre-line;font-variant-numeric:tabular-nums}.mlMeters{padding:9px;background:#ffffff09}.mlTargets{font-size:11px;margin:9px 0;color:#b8c7cb}.mlLog{font-size:11px;color:#a9b4ad}.meleeLab details{border-top:1px solid #52615b;padding-top:8px;margin-top:8px}.meleeLab summary{cursor:pointer}.hudMeleeQte{width:340px;top:64%;padding:12px 18px}.hudMeleeQte .mqSlow{font-size:10px}.hudMeleeQte .mqTitle{font-size:22px}.hudMeleeQte .mqProgress{position:relative}.hudMeleeQte .mqProgress:before{content:'敌方';position:absolute;left:0;top:9px;font-size:10px}.hudMeleeQte .mqProgress:after{content:'我方';position:absolute;right:0;top:9px;font-size:10px}.hudMeleeQte .mqTimeline{margin-top:25px}
@media(max-width:760px){.meleeLab{--mlMaxHeight:45dvh;top:10px;left:8px;width:220px;max-width:calc(50vw - 20px);padding:10px;font-size:11px}.mlHeading b{font-size:14px}.mlControls{font-size:10px}.hudMeleeQte{width:280px;top:65%}}

.hudMeleeQte{top:auto;bottom:18px;transform:translateX(-50%);width:310px;padding:10px 14px}.hudMeleeQte .mqSlow{margin-bottom:2px}.hudMeleeQte .mqTitle{font-size:18px}.hudMeleeQte .mqKeys{margin:4px 0}.hudMeleeQte kbd{width:34px;height:34px;line-height:34px;font-size:20px}.hudMeleeQte .mqTimeline{margin-top:15px}.hudMeleeQte .mqProgress:before,.hudMeleeQte .mqProgress:after{display:none}

.hudMeleeQte,.hudMeleeQte.on{left:22px;top:auto;bottom:22px;transform:none;width:280px}
@media(max-width:760px){.hudMeleeQte,.hudMeleeQte.on{left:8px;bottom:8px;width:220px;padding:8px}.hudMeleeQte .mqTitle{font-size:16px}.hudMeleeQte .mqPrompt{font-size:11px}.hudMeleeQte .mqKeys{min-height:35px}}
.meleeLabActive .hudMarkers,.meleeLabActive .hudForceStatus,.meleeLabActive .hudTop{display:none}
.hudMeleeQte .mqProgress{overflow:visible;background:linear-gradient(90deg,rgba(119,170,184,.45),rgba(199,99,72,.40))}
.hudMeleeQte .mqProgress i{position:absolute;top:-3px;width:12px;height:12px;border-radius:50%;transform:translateX(-50%);background:var(--warn);box-shadow:0 0 5px #0008;transition:left .04s linear}

/* Keep the left control panel above the resistance HUD during a bind. */
.meleeLabActive:has(.hudMeleeQte.on) .meleeLab{max-height:min(var(--mlMaxHeight),calc(100dvh - 290px))}

/* Mounted weapon heat sits above the shared ammunition readout. */
.hudEmplacement.heat-cool .empHeat {opacity:.28}
.hudEmplacement .empPrompt:empty {display:none}
.hudEmplacement .empExit {margin-left:auto;opacity:.75}

/* 断肢测试场（?gore=1）的左上角面板。版式照 .meleeLab 抄一份，只换类名与配色。 */
.goreLab{--glMaxHeight:calc(100dvh - 36px);position:fixed;left:18px;top:18px;z-index:38;box-sizing:border-box;width:308px;max-width:calc(50vw - 36px);max-height:var(--glMaxHeight);overflow:auto;background:rgba(19,25,27,.93);color:#e9e6d9;border:1px solid #788280;border-top:3px solid #b4645c;padding:16px;font:13px/1.55 system-ui,sans-serif;box-shadow:0 10px 38px #0007;pointer-events:auto}
.goreLab[hidden]{display:none}.glHeading{display:flex;flex-wrap:wrap;gap:4px 10px;justify-content:space-between;align-items:baseline;margin-bottom:12px}.glHeading b{font-size:18px}.glHeading span{font-size:11px;color:#b2b9b2}.glButtons{display:flex;gap:7px;margin-bottom:7px}.goreLab button{background:#c7b276;color:#172020;border:0;padding:8px 10px;cursor:pointer;flex:1}.goreLab button:focus-visible{outline:2px solid #fff}.glLimbLabel{color:#adb6ae;font-size:11px;margin:10px 0 5px}.glLimbs{display:grid;grid-template-columns:repeat(4,1fr);gap:5px}.goreLab .glLimb{background:#3c4a4c;color:#e9e6d9;font-size:11px;padding:6px 2px}.glStatus{display:block;color:#cdd9ad;margin:12px 0 8px}.glMeters,.glPosts{white-space:pre-line;font-variant-numeric:tabular-nums}.glMeters{padding:9px;background:#ffffff09}.glPosts{font-size:11px;margin:9px 0;color:#b8c7cb}.glControls{font-size:12px;color:#b9c2c0;border-top:1px solid #54615a;padding-top:10px;margin-bottom:0}
.goreLabActive .hudMarkers,.goreLabActive .hudForceStatus,.goreLabActive .hudTop{display:none}
/* 炮击扬尘测试场面板（?impacts=1）：取设置页口径 —— 深色渐变底、象牙字、橄榄细线、金色左边选中条、衬线标题、直角控件。 */
.shellImpactLab{position:fixed;left:14px;top:14px;z-index:38;box-sizing:border-box;width:318px;max-width:calc(50vw - 28px);max-height:calc(100dvh - 28px);overflow:auto;padding:0 0 12px;color:#deddd2;background:linear-gradient(180deg,rgba(21,24,22,.95),rgba(12,15,14,.93));border:1px solid #c1bdab40;border-left:2px solid #edca83;font:12.5px/1.5 var(--ui-font,system-ui,sans-serif);box-shadow:0 10px 38px #0008;pointer-events:auto;scrollbar-width:thin;scrollbar-color:#8a8e8070 transparent}
.shellImpactLab[hidden]{display:none}
.shellImpactLab .siHead{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 10px;padding:14px 16px 10px;border-bottom:1px solid #c1bdab30}
.shellImpactLab .siHead b{font:900 18px/1.2 var(--ui-story-font,serif);letter-spacing:.06em;color:#eeeee7}
.shellImpactLab .siHead span{font-size:11px;letter-spacing:.14em;color:#a7a89e}
.shellImpactLab .siCollapse{margin-left:auto;background:transparent;border:1px solid #c1bdab40;color:#b9b9ad;padding:3px 9px;font-size:11px;cursor:pointer}
.shellImpactLab.collapsed{width:auto}.shellImpactLab.collapsed .siBody{display:none}.shellImpactLab.collapsed .siHead{border-bottom:0}
.shellImpactLab .siBody{padding:0 16px}
.shellImpactLab h3{margin:16px 0 6px;font:700 11px/1.3 var(--ui-font,sans-serif);letter-spacing:.2em;color:#b8b49f;text-transform:none;padding-bottom:4px;border-bottom:1px solid #c1bdab30}
.shellImpactLab .siList{display:flex;flex-direction:column}
.shellImpactLab .siGrid{display:grid;grid-template-columns:1fr 1fr;column-gap:10px}
.shellImpactLab .siGrid .siPick{grid-column:1/-1}
.shellImpactLab .siRow{display:flex;justify-content:space-between;align-items:baseline;gap:10px;width:100%;box-sizing:border-box;text-align:left;background:transparent;color:#d3d2c6;border:0;border-left:2px solid transparent;border-bottom:1px solid #c1bdab18;padding:3px 8px;cursor:pointer;font:inherit;line-height:1.4}
.shellImpactLab .siRow:hover{background:#d8d4c312}
.shellImpactLab .siRow.selected{border-left-color:#edca83;background:linear-gradient(90deg,#d8d4c324,#bbb7a906);color:#edca83}
.shellImpactLab .siMeta{font-size:11px;color:#a7a89e;font-variant-numeric:tabular-nums;white-space:nowrap}
.shellImpactLab .siRow.selected .siMeta{color:#cdb77b}
.shellImpactLab .siButtons{display:flex;gap:6px;margin:6px 0}
.shellImpactLab .siWrap{flex-wrap:wrap}
.shellImpactLab .siBtn{flex:1 1 0;min-width:0;background:#13140b44;color:#d3d2c6;border:1px solid #c1bdab40;padding:7px 6px;cursor:pointer;font:inherit;letter-spacing:.04em}
.shellImpactLab .siBtn:hover{border-color:#cdb77b88;color:#e6cb91}
.shellImpactLab .siBtn.active{color:#edca83;border-color:#cdb77b;background:linear-gradient(90deg,#d8d4c324,#bbb7a906)}
.shellImpactLab .siFire{color:#13140b;background:#d9bb7b;border-color:#d9bb7b;font-weight:700}
.shellImpactLab .siFire:hover{background:#edca83;color:#13140b}
.shellImpactLab .siSwitch{display:block;width:100%;text-align:left;background:transparent;border:1px solid #c1bdab40;color:#a7a89e;padding:6px 8px;margin:6px 0;cursor:pointer;font:inherit;font-size:11.5px}
.shellImpactLab .siSwitch::before{content:"";display:inline-block;width:5px;height:5px;margin:0 9px 2px 0;background:currentColor}
.shellImpactLab .siSwitch[aria-checked="true"]{color:#e6cb91;border-color:#cdb77b88}
.shellImpactLab button:focus-visible{outline:1px solid #edca83;outline-offset:2px}
.shellImpactLab .siTargetRead{display:block;margin:6px 0 0;font-size:11px;color:#a7a89e;font-variant-numeric:tabular-nums}
.shellImpactLab .siHint{margin:4px 0 0;font-size:11px;color:#a7a89e}
.shellImpactLab .siRead{white-space:pre-line;font-size:11.5px;color:#cfd0c4;font-variant-numeric:tabular-nums;padding:7px 9px;background:#ffffff08;border-left:1px solid #c1bdab30}
.shellImpactActive .hudMarkers,.shellImpactActive .hudForceStatus,.shellImpactActive .hudTop{display:none}
/* 自由观察相机时去掉第一人称的准星、弹药 / 状态读数与开场简报，画面只剩场景（落点提示 hudHint 保留）。 */
.shellImpactFree .hudCrosshair,.shellImpactFree .hudState,.shellImpactFree .hudCombat,.shellImpactFree .hudMinimap,.shellImpactFree .hudBrief,.shellImpactFree .hudSubtitle,.shellImpactFree .hudActions,.shellImpactFree .hudTarget{display:none!important}
.shellImpactLab.hiddenPanel{display:none}
@media(max-width:760px){.shellImpactLab{width:236px;max-width:calc(50vw - 18px);left:8px;top:8px;font-size:11px}.shellImpactLab .siHead b{font-size:15px}}
@media(max-width:760px){.goreLab{--glMaxHeight:52dvh;top:10px;left:8px;width:228px;max-width:calc(50vw - 20px);padding:10px;font-size:11px}.glHeading b{font-size:14px}.glLimbs{grid-template-columns:repeat(3,1fr)}}

/* Soft mission boundary: full viewport, readable battlefield, input passes through. */
.hudMissionReturn { position:absolute; inset:0; z-index:18; pointer-events:none;
  display:flex; align-items:center; justify-content:center; opacity:0; visibility:hidden;
  background:radial-gradient(ellipse at center,rgba(15,12,10,.08) 20%,rgba(38,19,12,.55) 72%,rgba(64,26,13,.8));
  transition:opacity .35s ease,visibility .35s; color:#f5eddd; text-align:center; }
.hudMissionReturn.on {opacity:1;visibility:visible;}
.hudMissionReturn.urgent {background:radial-gradient(ellipse at center,rgba(18,9,7,.13) 20%,rgba(60,17,10,.62) 72%,rgba(94,24,13,.86));}
/* Compact in-combat command: keep the centre and return path readable. */
.missionReturnPanel {box-sizing:border-box;width:min(560px,90vw);padding:18px 24px;transform:translateY(-17vh);
  font-family:var(--ui-font,sans-serif);
  background:linear-gradient(90deg,transparent,rgba(15,13,10,.48) 22%,rgba(15,13,10,.48) 78%,transparent);
  text-shadow:0 2px 5px #000;}
.missionReturnTitle {font-size:clamp(24px,3vw,34px);font-weight:700;letter-spacing:.08em;line-height:1.25;}
.urgent .missionReturnTitle {color:#f1be9c;}
.missionReturnDetail {font-size:14px;line-height:1.5;margin-top:8px;color:#e3d8c7;}
.missionReturnBearing {display:flex;align-items:center;justify-content:center;gap:10px;margin-top:12px;}
.missionReturnArrow {font-size:25px;line-height:1;width:28px;color:#e5bd80;}
.missionReturnTarget {font-size:15px;line-height:1.5;}
@media (prefers-reduced-motion:reduce) {.hudMissionReturn {transition:none;}}
/* 任务走廊出界倒计时（docs/Data_FirstLevelGuidance20260928.md §3.3）：顶部正中一行，字样同目标通知
   （粗体、硬黑描边、无底板），叠在回头警告的暗角之上、避开它屏幕中上的方向面板；最后几秒转红。不接指针。 */
.hudMissionArea { position:absolute; top:12vh; left:50%; transform:translateX(-50%); z-index:19; pointer-events:none;
  max-width:calc(100vw - 32px); white-space:nowrap; opacity:0; visibility:hidden; transition:opacity .25s ease,visibility .25s;
  font-family:var(--ui-font); font-size:20px; font-weight:700; line-height:1.2; letter-spacing:.04em; color:rgba(236,230,218,.98);
  -webkit-text-stroke:1px rgba(0,0,0,.96); paint-order:stroke fill; text-shadow:1px 1px 0 rgba(0,0,0,.9); }
.hudMissionArea.on {opacity:1;visibility:visible;}
.hudMissionArea.urgent {color:#f2a489;}
@media (max-width:760px) {.hudMissionArea {font-size:16px; white-space:normal; text-align:center;}}
@media (prefers-reduced-motion:reduce) {.hudMissionArea {transition:none;}}

/* Keep the required QTE key inside the combat sightline, clear of the crosshair. */
.hudMeleeQte,.hudMeleeQte.on { left:50%; bottom:17%; top:auto; transform:translateX(-50%); width:min(280px,calc(100vw - 24px)); }
.hudMeleeQte .mqKeys { min-height:60px; margin:8px 0; }
.hudMeleeQte .mqKeys kbd { width:54px; height:54px; font-size:30px; line-height:1; }
.hudMeleeQte.input .mqKeys kbd.expected { animation:mqUrgentKey .65s ease-in-out infinite; }
@keyframes mqUrgentKey {
  0%,100% { background:rgba(224,176,98,.12); box-shadow:0 0 8px rgba(224,176,98,.25); }
  50% { transform:scale(1.12); color:#fff; background:rgba(224,176,98,.48); box-shadow:0 0 24px rgba(224,176,98,.65); }
}
@media(prefers-reduced-motion:reduce) { .hudMeleeQte.input .mqKeys kbd.expected { animation:none; background:rgba(224,176,98,.4); } }
/* 人物战场反应测试场（?reactions=1）：沿用 .shellImpactLab 的整套样式，只补方位九宫格与距离一排。 */
.battleReactionLab .brCompass{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;margin:6px 0}
.battleReactionLab .brCompass .siBtn{padding:6px 2px}
.battleReactionLab .brDistances .siBtn{flex:1 1 22%;padding:5px 2px}
