/* ==========================================================
 * 《决战哈姆》PVE 复刻 — 触控交互方式（键鼠 / 触控切换 + 触控浮层）
 * ----------------------------------------------------------
 * 配套脚本：src/js/touch.js
 *
 * 一套与「出战部署 / 已暂停」完全相同的美术语言：
 *   · 平行四边形切角：键鼠 / 触控切换按钮、准星吸附开关都是「切角板 + 切角滑块」
 *   · 配色：奶油 #fffdf8 / 棕描边 #6b3b2a / 粉 #f06aa8 #d8457f / 金 #f2b640
 *   · 选中态统一用金色描边 + 外发光 + 流光
 *
 * 浮层结构（全部由 touch.js 构建）：
 *   #touch-ui
 *     ├─ #tc-stick   左下万向摇杆（底盘 + 摇杆头）
 *     ├─ #tc-aimbtn  右下方块「大圆形」位置的开火按钮（口径最大，透明度高）
 *     ├─ #tc-lock    开火按钮右下方的锁图标（持续开火时醒目发光）
 *     └─ #tc-cluster 环绕开火按钮的道具 / 战意 / 跳跃（触控下三者尺寸一致）
 *
 * 透明度基调：触控按钮一律低不透明度（平时 0.42~0.5，按下 0.8+），
 * 保证不遮挡战场视野，符合 3A 手游 HUD 的「存在但不抢戏」。
 * ========================================================== */

/* ==================== 图层 ====================
 * #ui-layer：HUD / 横幅 / 倒计时 / 增益选取 / 触控浮层共用的定位基准。
 * 屏幕过小时（ui.js 的 layoutScale）整层等比缩放：先把逻辑尺寸放大到
 * 「物理尺寸 ÷ 缩放」，再用 scale 缩回物理尺寸，于是层内所有 absolute/fixed
 * 定位的子元素都按缩放后的坐标系排布，相对位置完全不变。
 * --ui-s 恒为 1 时（桌面尺寸）不产生任何 transform。 */
.ui-layer {
  position: absolute;
  left: 50%; top: 50%;
  width: calc(100% / var(--ui-s, 1));
  height: calc(100% / var(--ui-s, 1));
  z-index: 30;
  transform: translate(-50%, -50%) scale(var(--ui-s, 1));
  transform-origin: center center;
}
/* 仅在真正缩放时加 will-change，避免桌面下白白占一层合成 */
.ui-layer.scaled { will-change: transform; }
/* 弹窗（暂停 / 背包 / 结算 / 出战部署）必须压在 HUD 图层之上 */
#screen-pause, #screen-bag, #screen-result, #screen-select { z-index: 60; }

/* ==================== 键鼠 / 触控 切换按钮 ====================
 * 位置：出战部署底栏「返回大厅」的右侧，与它同一行、同一高度。
 * 形制：外层切角板（棕描边 + 奶油面），内层一条平行四边形轨道 + 平行四边形滑块。
 * 两个标签（键鼠 / 触控）常驻显示，当前状态由滑块压在哪一侧表示。 */
.sel-imode,
.im-switch {
  position: relative;
  padding: 0; margin: 0;
  border: 0; background: none;
  font-family: var(--font);
  cursor: pointer;
  /* 与 .sel-go / .sel-back 同一族切角：左上 + 右下各切一刀 */
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 11px), calc(100% - 11px) 100%, 0 100%);
  filter: drop-shadow(0 3px 8px rgba(120, 70, 10, 0.22));
  transition: transform 0.14s ease, filter 0.14s ease;
}
.sel-imode:hover, .im-switch:hover { transform: translateY(-1px); }
.sel-imode:active, .im-switch:active { transform: translateY(1px); }
.sel-imode:focus-visible, .im-switch:focus-visible {
  outline: none;
  filter: drop-shadow(0 0 0 3px rgba(255, 255, 255, 0.95)) drop-shadow(0 0 0 6px rgba(74, 140, 232, 0.9));
}

.sel-imode { flex: none; margin-left: 12px; }

/* 切角板面：奶油底 + 粉描边（未切换）；切到触控时整块转成金渐变（与 .sel-go 同款亮起） */
.im-face {
  position: relative;
  display: flex; align-items: center;
  height: 38px;
  padding: 0 4px;
  background: linear-gradient(180deg, #fffcfa, #fff3e6);
  clip-path: inherit;
  box-shadow: inset 0 0 0 2px rgba(255, 196, 220, 0.9);
  transition: background 0.3s ease, box-shadow 0.3s ease;
}
.sel-imode { width: 176px; }
.im-switch .im-face { height: 30px; padding: 0 3px; }
.im-switch { width: 104px; }

/* 平行四边形轨道：两端随滑块位置铺开，中间留出滑块滑行的走廊 */
.im-track {
  position: absolute; left: 8px; right: 8px; top: 9px; bottom: 9px;
  background: linear-gradient(180deg, rgba(107, 59, 42, 0.16), rgba(107, 59, 42, 0.08));
  box-shadow: inset 0 1px 2px rgba(107, 59, 42, 0.18);
  /* 平行四边形：上下边各向右错开 4px —— 与全局的斜切语言一致 */
  clip-path: polygon(4px 0, 100% 0, calc(100% - 4px) 100%, 0 100%);
  transition: background 0.3s ease;
}
.im-switch .im-track { top: 7px; bottom: 7px; left: 7px; right: 7px; }

/* 滑块：金渐变平行四边形；左端 = 键鼠 / 关，右端 = 触控 / 开。
 * 位移距离由 --slide 给出（= 轨道内宽 - 滑块宽），切换时用缓出曲线平滑滑行。 */
.im-thumb {
  position: absolute; left: 9px; top: 7px;
  width: 82px; height: 24px;
  background: linear-gradient(135deg, #fff6d6 0%, #ffd56a 42%, #f2a51e 100%);
  clip-path: polygon(5px 0, 100% 0, calc(100% - 5px) 100%, 0 100%);
  box-shadow: 0 0 0 1.5px #d8457f, 0 3px 7px rgba(120, 40, 70, 0.3);
  /* 高级感来源：先小幅回弹再落位（cubic-bezier 的轻微 overshoot），
   * 同时对背景色与描边做同步过渡，滑块落位时颜色也在变。 */
  transition:
    transform 0.42s cubic-bezier(0.34, 1.42, 0.42, 1),
    box-shadow 0.28s ease,
    background 0.34s ease;
  z-index: 2;
}
.im-switch .im-thumb { width: 56px; height: 18px; left: 8px; top: 6px; clip-path: polygon(4px 0, 100% 0, calc(100% - 4px) 100%, 0 100%); }
/* 滑块面上的高光条：随滑块一起移动，制造「金属贴片」质感 */
.im-thumb-face {
  position: absolute; inset: 2px 6px auto 6px; height: 5px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.15));
  clip-path: polygon(3px 0, 100% 0, calc(100% - 3px) 100%, 0 100%);
  pointer-events: none;
}
/* 位移：--slide 由 CSS 变量算出（见下），触控态 translateX(--slide) */
.sel-imode.on .im-thumb { transform: translateX(var(--slide, 84px)); }
.im-switch.on .im-thumb { transform: translateX(var(--slide, 42px)); }
.sel-imode { --slide: 84px; }
.im-switch { --slide: 43px; }

/* 两个选项标签：滑块压住的一侧亮起（深棕金字），另一侧压暗 */
.im-opt {
  position: absolute; top: 0; bottom: 0;
  width: 66px;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 900; letter-spacing: 2px;
  color: #b09070;
  transition: color 0.28s ease, text-shadow 0.28s ease;
  z-index: 3;
  pointer-events: none;
}
.im-opt-km { left: 8px; }
.im-opt-tc { right: 8px; }
.im-switch .im-opt { width: 44px; font-size: 12px; letter-spacing: 1px; }
.im-switch .im-opt-km { left: 6px; }
.im-switch .im-opt-tc { right: 6px; }
.sel-imode:not(.on) .im-opt-km,
.sel-imode.on .im-opt-tc,
.im-switch:not(.on) .im-opt-km,
.im-switch.on .im-opt-tc { color: #5a3322; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.9); }

/* 触控态：整块切角板变成金渐变（与「进入战场」同款亮起），表示当前操作方式已改变 */
.sel-imode.on .im-face {
  background: linear-gradient(180deg, #ffe9a6 0%, #f7bf46 52%, #de9a1c 100%);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.55);
}
.sel-imode.on .im-track { background: linear-gradient(180deg, rgba(120, 70, 10, 0.22), rgba(120, 70, 10, 0.1)); }
.sel-imode.on .im-thumb {
  background: linear-gradient(135deg, #fffdf3 0%, #ffffff 45%, #ffeec4 100%);
  box-shadow: 0 0 0 1.5px #c8901e, 0 3px 8px rgba(120, 40, 70, 0.34);
}
.sel-imode.on .im-opt { color: #8a5a10; }
.sel-imode.on .im-opt-tc { color: #3a2408; text-shadow: 0 1px 0 rgba(255, 250, 230, 0.95); }
/* 触控态下扫过按钮的一道光，强调「已切到触控」 */
.sel-imode.on .im-face::after {
  content: ""; position: absolute; inset: 0;
  pointer-events: none;
  background: linear-gradient(104deg, rgba(255, 255, 255, 0) 34%, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0) 66%);
  transform: translateX(-120%);
  animation: goSheen 3.4s ease-in-out infinite;
  clip-path: inherit;
  mix-blend-mode: screen;
}

/* 准星吸附开关：与上面同一套切角语言，尺寸收在设置卡片里 */
.im-switch .im-thumb-face { inset: 2px 5px auto 5px; height: 4px; }
.im-switch.on .im-thumb {
  background: linear-gradient(135deg, #fff6d6 0%, #ffd56a 42%, #f2a51e 100%);
  box-shadow: 0 0 0 1.5px #d8457f, 0 0 10px rgba(255, 201, 60, 0.75);
}
.im-switch.off .im-thumb { background: linear-gradient(135deg, #f4ece2 0%, #ded2c4 45%, #c8b8a6 100%); box-shadow: 0 0 0 1.5px #a4806a, 0 2px 5px rgba(90, 60, 40, 0.25); }
/* 已开启：加一圈呼吸外发光，提示「吸附正在生效」 */
.im-switch.on .im-face { box-shadow: inset 0 0 0 2px rgba(242, 182, 64, 0.85), 0 0 12px rgba(255, 201, 60, 0.45); }

/* 设置卡片里的开关行：与滑块行同一套栅格，开关占中列、状态字占右列。
 * 开关铺满中列（与上下两条滑轨同宽），视觉节奏与滑块行对齐 ——
 * 曾经固定 104px 宽，夹在两条整列宽的滑轨之间显得局促、像个小标签。
 * 滑块宽度与位移按中列宽度用百分比推导，任何卡片宽度下都左右各占一半。 */
.pw-toggle-row .pw-toggle-wrap { display: flex; align-items: center; }
.pw-toggle-row .pw-slider-val { background: rgba(255, 255, 255, 0.9); }
.pw-toggle-row .im-switch { width: 100%; max-width: 220px; }
.pw-toggle-row .im-switch .im-face { height: 32px; }
.pw-toggle-row .im-switch .im-track { top: 8px; bottom: 8px; }
/* 滑块占轨道一半（轨道 = 开关宽 − 两侧各 7px 内缩），开态位移恰好半条轨道 */
.pw-toggle-row .im-switch .im-thumb {
  top: 6px; height: 20px;
  width: calc(50% - 7px);
}
.pw-toggle-row .im-switch.on .im-thumb { transform: translateX(calc(100% - 2px)); }
.pw-toggle-row .im-switch .im-opt { width: calc(50% - 7px); font-size: 12.5px; letter-spacing: 2px; }
.pw-toggle-row .im-switch .im-opt-km { left: 7px; }
.pw-toggle-row .im-switch .im-opt-tc { right: 7px; }

/* ==================== 触控几何变量 ====================
 * 全部定义在 #ui-layer 上 —— 它是「触控浮层」与「增益选取区」共同的那一级父节点。
 *
 * 为什么必须放在共同父级：CSS 自定义属性沿 DOM 向下继承，`calc()` 在「使用它的
 * 元素」上解析。曾经把这些变量写在 .touch-ui 上，而 .buff-picker 是 .touch-ui 的
 * 兄弟节点，`var(--fire)` 在那里取不到值，只能吃兜底值 —— 增益区的底距因此恒等于
 * 「30 + 120 + 10 = 160px」，与开火按钮的实际尺寸完全脱钩（实测 820×1180 时按钮
 * 顶边已经顶到增益卡上）。定义在共同父级后，两侧引用的是同一套尺寸，不会失配。
 *
 * 结构关系：
 *   #ui-layer            ← 变量定义处 + 全局缩放（--ui-s）
 *     ├─ #hud / #banner / #countdown
 *     ├─ #buff-picker    ← 用到 --pad-b / --fire / --arc-gap / --stick
 *     └─ #touch-ui       ← 用到全部触控变量
 */
.ui-layer {
  /* 开火按钮：口径最大（触控下它是主操作） */
  --fire: min(clamp(96px, 17.5vh, 138px), 27vw);
  /* 环绕按钮（道具 / 战意 / 跳跃）：触控下三者严格同尺寸 */
  --side: min(clamp(60px, 11vh, 84px), 16vw);
  /* 锁图标 */
  --lock: min(clamp(46px, 8.2vh, 60px), 13vw);
  /* 弧半径与走廊间隙：按钮外缘之间恒留 --arc-gap。
   * 半径必须含自身的 --side/2 —— 按钮的包围盒在弧上占去这一半，
   * 只按「两圆心距」取值会让按钮内侧切进开火按钮的圆里。 */
  --arc-gap: 24px;
  --r: calc(var(--fire) * 0.5 + var(--side) * 0.5 + var(--arc-gap));
  /* 右下角排布：锁图标嵌在角上，开火按钮把这一角让出来。
   * 注意 right / bottom 是「距屏幕右下角的距离」，**加大**偏移是向屏幕内侧移动 ——
   * 所以要让锁落在开火按钮的右下方，必须让开火按钮的内缩更大，把角空出来：
   *   --pad-* = 锁的直径 + 角上留白 + 间隙
   * 曾经把锁写成 pad + fire*0.55（比开火按钮的内缩还大），锁被推进开火按钮的
   * 包围盒里，实测两者完全重叠。 */
  --lock-pad: clamp(8px, 1.2vh, 20px);
  --pad-gap: clamp(6px, 1vh, 14px);
  --pad-r: calc(var(--lock) + var(--lock-pad) + var(--pad-gap));
  --pad-b: calc(var(--lock) + var(--lock-pad) + var(--pad-gap));
  /* 摇杆 */
  --stick: clamp(118px, 22vh, 168px);
  --stick-b: clamp(18px, 4.2vh, 46px);
  --stick-l: clamp(16px, 3vw, 46px);
}

/* ==================== 触控浮层 ==================== */
.touch-ui {
  position: absolute; inset: 0;
  /* 浮层自身不吃事件：滑屏移动视角、点击游戏世界都照常，
   * 只有具体的摇杆 / 按钮（.tc-hit）才接管指针 */
  pointer-events: none;
  z-index: 26;
  touch-action: none;
  -webkit-user-select: none; user-select: none;
}
.touch-ui.hidden { display: none; }
.touch-ui .tc-hit { pointer-events: auto; }

/* 触控模式下的通用收敛：所有键位提示一律不再显示
 * （B 背包 / Q 武器槽 / E 道具 / C 战意 / Space 跳跃 / 1·2·3 增益 / F 确定） */
body.touch-mode .key-tag,
body.touch-mode .wslot-key,
body.touch-mode .bp-ok-key,
body.touch-mode .bp-key { display: none !important; }

/* 键鼠模式右下角的 道具 / 战意 / 跳跃 圆钮（.hud-br）：触控模式下由触控浮层的
 * 同名按钮接管（环绕开火按钮排布、三者等大）。两套同时显示会叠在一起 ——
 * 实测键鼠的「跳跃」钮恰好压在锁图标上。这里整组收起，键鼠模式不受影响。 */
body.touch-mode .hud-br { display: none !important; }
/* 增益选取区：触控模式下整体停在「按钮行 / 摇杆 / 底部血条」三者的上方。
 *
 * 底距取四个上沿量的最大值（单位统一为逻辑像素，与 #ui-layer 的坐标系一致）：
 *   ① 开火按钮的顶边（含右下角内缩与锁图标让出的那一角）→ 右侧按钮组最高点
 *   ② 环绕按钮在弧顶（跳跃，θ=90°）的外缘 → 比开火按钮顶边更高，必须算进来
 *   ③ 摇杆顶边 → 左侧最高点
 *   ④ 底部能量条 / 血条的顶边（底 16~22px + 两条共约 37px + 8px 余量）
 * 再加 --arc-gap 作为按钮与增益卡之间的视觉呼吸。
 * 这样任何断点上按钮怎么放大都不会压住增益卡。 */
body.touch-mode .buff-picker {
  bottom: max(
    calc(var(--pad-b) + var(--fire) + var(--fire) * 0.5 + var(--side) * 0.5 + var(--arc-gap) + 8px),
    calc(var(--stick-b) + var(--stick) + 8px),
    /* 底兜底：至少停在底部能量条 / 血条上方。血条底 16~22px，两条共约 37px，
     * 再留 30px 呼吸 —— 矮屏上「按钮行」「摇杆」两项可能因 --lock-pad 收窄而
     * 算出比它还小的值，这条保证增益区不会掉到底部条上。 */
    calc(22px + 37px + 30px)
  );
}

/* 触控模式下 561~720px 高度段：顶部三块必须再上收一档。
 *
 * 这一段高度上「倒计时 + 增益区 + 按钮行 + 底部血条」的纵向需求总和会超过屏高：
 * 实测 1390×632 时按钮行顶边已到 y=333，增益区（--bxs=0.632 → 高 134px）
 * 底边与它重合 → 顶端被顶到 y=199，压住倒计时（底边 212），重叠 2704px²。
 * 键鼠模式没有按钮行，不受影响，所以这条规则只在触控模式下生效。
 *
 * 上移量受 `.hud-top`（波次 + 计时器）的下沿约束：它在所有断点上底边都是 73px，
 * 横幅必须停在 73 + 8 = 81px 以下，因此取 84px —— 曾经写 72px 会直接压住
 * 波次读数（探针报 top_ban=160）。倒计时紧随其后（84 + 28 + 8 = 120px），
 * 底边由 212px 降到 172px，让出的 40px 把增益区送回倒计时下方。
 * 校验（1390×632）：倒计时底 172；增益区底 632−311=321 → 顶端 187 > 172 ✓ */
@media (min-height: 561px) and (max-height: 720px) {
  body.touch-mode .banner { top: 84px; }
  body.touch-mode .countdown { top: 120px; }
  body.touch-mode.boss-multi .banner { top: 140px; }
  body.touch-mode.boss-multi .countdown { top: 184px; }
}
/* 触控模式下按 Esc / Enter 之类的提示一并收起（手机上这些键不存在） */
body.touch-mode .pw-hint,
body.touch-mode .sel-hint { display: none !important; }
/* 增益选取区：.buff-picker 以 bottom 定位，收起最后一行 1/2/3 后整块高度变矮，
 * 底边固定 → 图标与名称自然整体下移，无需额外位移（多写一条会双重偏移）。 */
/* 大厅设置弹窗：键鼠操作说明换成触控操作说明 */
body.touch-mode .ctrl-grid.ctrl-km { display: none; }
body.touch-mode .ctrl-grid.ctrl-tc { display: grid; }

/* ---------- 万向虚拟摇杆（左下） ----------
 * 尺寸与两个内缩都来自 #ui-layer 的 --stick / --stick-l / --stick-b
 * （增益选取区要用 --stick-b 把底距顶到摇杆上方，所以不能再定义在这里）。 */
.tc-stick {
  position: absolute;
  left: var(--stick-l);
  bottom: var(--stick-b);
  width: var(--stick); height: var(--stick);
  /* 摇杆外围的「清空区」不截获手势：滑到这里也能转向视角 */
  pointer-events: none;
}
.tc-stick-base {
  position: absolute; inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, rgba(20, 26, 38, 0.3) 0%, rgba(20, 26, 38, 0.16) 62%, rgba(20, 26, 38, 0.05) 100%);
  border: 2px solid rgba(255, 255, 255, 0.34);
  box-shadow: inset 0 0 22px rgba(0, 0, 0, 0.22);
  /* 极高透明度：只作为位置的暗示，不遮挡地面 */
  opacity: 0.4;
  transition: opacity 0.2s ease;
}
/* 底盘上的十字刻度：四个方向各一道短刻度，弱化「一块圆饼」的观感 */
.tc-stick-base::before,
.tc-stick-base::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  background: rgba(255, 255, 255, 0.32);
  transform: translate(-50%, -50%);
}
.tc-stick-base::before { width: 2px; height: 62%; }
.tc-stick-base::after { width: 62%; height: 2px; }
.tc-stick.active .tc-stick-base { opacity: 0.72; }
.tc-stick.active .tc-stick-base { box-shadow: inset 0 0 22px rgba(0, 0, 0, 0.22), 0 0 18px rgba(255, 255, 255, 0.18); }

/* 摇杆头：可抓取的那一小块（只有它吃指针事件，见 touch.js 的判定） */
.tc-stick-knob {
  position: absolute; left: 50%; top: 50%;
  width: 46%; height: 46%;
  margin: calc(-23%) 0 0 calc(-23%);
  border-radius: 50%;
  background:
    radial-gradient(circle at 40% 32%, rgba(255, 255, 255, 0.92) 0%, rgba(255, 255, 255, 0.52) 46%, rgba(214, 232, 246, 0.34) 100%);
  border: 2px solid rgba(255, 255, 255, 0.72);
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.28);
  opacity: 0.5;
  transition: opacity 0.18s ease, box-shadow 0.18s ease;
  will-change: transform;
}
/* 抓取范围比看得见的摇杆头大一圈，手感更稳 */
.tc-stick-knob::after {
  content: ""; position: absolute; inset: -34%;
  border-radius: 50%;
}
.tc-stick.active .tc-stick-knob {
  opacity: 0.95;
  box-shadow: 0 3px 14px rgba(0, 0, 0, 0.34), 0 0 16px rgba(120, 210, 255, 0.55);
}

/* ---------- 开火按钮（右下，口径最大） ----------
 * --fire / --pad-r / --pad-b 全部继承自 .touch-ui（见上方说明）。 */
.tc-fire {
  position: absolute;
  right: var(--pad-r);
  bottom: var(--pad-b);
  width: var(--fire); height: var(--fire);
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.66);
  background:
    radial-gradient(circle at 42% 32%, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.12) 46%, rgba(255, 255, 255, 0) 72%),
    radial-gradient(circle at 50% 50%, rgba(255, 92, 114, 0.5) 0%, rgba(200, 40, 66, 0.42) 68%, rgba(120, 16, 34, 0.36) 100%);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.32), inset 0 0 24px rgba(255, 255, 255, 0.12);
  display: flex; align-items: center; justify-content: center;
  opacity: 0.78;
  transition: transform 0.12s ease, box-shadow 0.2s ease, opacity 0.2s ease, filter 0.2s ease;
  will-change: transform;
}
/* 内圈细描边，让按钮边缘更「利落」 */
.tc-fire::before {
  content: ""; position: absolute; inset: 7px;
  border-radius: 50%;
  border: 1px dashed rgba(255, 255, 255, 0.34);
  pointer-events: none;
}
/* 口径图标：准星 + 中心点（自绘，不用字体图标） */
.tc-fire-ic {
  position: relative;
  width: 46%; height: 46%;
  pointer-events: none;
}
.tc-fire-ic::before {
  content: ""; position: absolute; inset: 0;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.92);
  box-shadow: 0 0 12px rgba(255, 140, 160, 0.6);
}
.tc-fire-ic::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 8px rgba(255, 255, 255, 0.9);
}
.tc-fire.down {
  transform: scale(0.94);
  opacity: 0.96;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.36), inset 0 0 30px rgba(255, 255, 255, 0.22);
}
/* 拖拽到锁图标上：按钮切换到「待锁定」的青色荧光 */
.tc-fire.near-lock {
  border-color: rgba(140, 240, 255, 0.95);
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.34), 0 0 22px rgba(90, 220, 255, 0.7);
}
/* 已锁定：持续开火状态，按钮描边转为常亮金红并持续脉动 */
.tc-fire.locked {
  opacity: 1;
  border-color: #ffd76a;
  box-shadow: 0 0 26px rgba(255, 190, 60, 0.85), inset 0 0 26px rgba(255, 214, 120, 0.3);
  animation: tcFireHold 1.1s ease-in-out infinite;
}
@keyframes tcFireHold {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.035); }
}

/* ---------- 锁图标（开火按钮右下方） ---------- */
/* 锁图标：开火按钮的**右下方**，即屏幕右下角那一小块空档。
 * 只留 --lock-pad 的角上留白；开火按钮的 --pad-* 已经把这一角让了出来，
 * 所以这里不需要再叠加任何与 --fire 相关的偏移（叠了就会推回开火按钮里）。 */
.tc-lock {
  position: absolute;
  right: var(--lock-pad);
  bottom: var(--lock-pad);
  width: var(--lock); height: var(--lock);
  border-radius: 50%;
  background: radial-gradient(circle at 44% 34%, rgba(255, 255, 255, 0.26), rgba(20, 26, 38, 0.42) 74%);
  border: 2px solid rgba(255, 255, 255, 0.5);
  display: flex; align-items: center; justify-content: center;
  opacity: 0.62;
  transition: opacity 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.14s ease;
}
.tc-lock:hover { opacity: 0.85; }
/* 锁体 + 锁梁（纯 CSS 自绘） */
.tc-lock-ic {
  position: relative;
  width: 17px; height: 14px;
  margin-top: 5px;
  border-radius: 2px;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
  transition: background 0.2s ease;
}
.tc-lock-ic::after {
  content: ""; position: absolute; left: 50%; bottom: 100%;
  width: 11px; height: 9px;
  margin-left: -5.5px;
  border: 2.5px solid #fff;
  border-bottom: none;
  border-radius: 6px 6px 0 0;
  transition: border-color 0.2s ease;
}
/* 钥匙孔 */
.tc-lock-ic::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 4px; height: 6px; margin: -3px 0 0 -2px;
  border-radius: 2px;
  background: rgba(20, 26, 38, 0.72);
}
/* 悬停高亮（拖拽开火按钮靠近时由 JS 加 .hover） */
.tc-lock.hover {
  opacity: 1;
  border-color: rgba(140, 240, 255, 0.95);
  transform: scale(1.08);
  box-shadow: 0 0 18px rgba(90, 220, 255, 0.7);
}
.tc-lock.hover .tc-lock-ic, .tc-lock.hover .tc-lock-ic::after { background: #e6ffff; border-color: #e6ffff; }
/* 已锁定：醒目发光 —— 外层脉冲光圈 + 锁体转金 + 常亮描边 */
.tc-lock.locked {
  opacity: 1;
  border-color: #ffe08a;
  background: radial-gradient(circle at 44% 34%, rgba(255, 240, 190, 0.55), rgba(190, 120, 20, 0.5) 74%);
  box-shadow: 0 0 22px rgba(255, 200, 60, 0.9), 0 0 46px rgba(255, 180, 40, 0.5), inset 0 0 14px rgba(255, 236, 170, 0.6);
  animation: tcLockGlow 1.3s ease-in-out infinite;
}
.tc-lock.locked .tc-lock-ic { background: #fff6d6; }
.tc-lock.locked .tc-lock-ic::after { border-color: #fff6d6; }
.tc-lock.locked .tc-lock-ic::before { background: #8a5a10; }
@keyframes tcLockGlow {
  0%, 100% { box-shadow: 0 0 18px rgba(255, 200, 60, 0.75), 0 0 34px rgba(255, 180, 40, 0.35), inset 0 0 12px rgba(255, 236, 170, 0.5); }
  50% { box-shadow: 0 0 30px rgba(255, 214, 106, 1), 0 0 60px rgba(255, 190, 60, 0.65), inset 0 0 18px rgba(255, 246, 214, 0.85); }
}
/* 锁定态向外扩散的光环 */
.tc-lock.locked::after {
  content: ""; position: absolute; inset: -6px;
  border-radius: 50%;
  border: 2px solid rgba(255, 214, 106, 0.85);
  animation: tcLockRing 1.3s ease-out infinite;
  pointer-events: none;
}
@keyframes tcLockRing {
  0% { transform: scale(0.86); opacity: 0.9; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* ---------- 环绕开火按钮的三枚按钮（道具 / 战意 / 跳跃） ----------
 * 触控模式下三者尺寸完全一致（--side），沿开火按钮外圈等角排列：
 * 与「开火按钮中心 → 屏幕右下角」的连线夹角为 96° / 140° / 184°，
 * 于是 跳跃 落在开火按钮正上方，道具 / 战意 依次向左下铺开成一道弧。 */
.tc-cluster {
  position: absolute;
  right: calc(var(--pad-r) + var(--fire) / 2);
  bottom: calc(var(--pad-b) + var(--fire) / 2);
  width: 0; height: 0;
  pointer-events: none;
}
/* 环绕按钮：以所在簇的 0×0 锚点（= 开火按钮圆心）为原点，
 * 沿 --ax / --ay 单位方向推到 --r 半径上，再各减去自身一半尺寸居中对齐。
 * 全部用 calc 在元素自身解析，不依赖容器的宽高。 */
.tc-side {
  position: absolute;
  /* 定位完全落在元素自身的 calc 里：锚点在簇的 0×0 原点（开火按钮圆心），
   * 先按 --ax/--ay 推到半径 --r 上，再各回退自身一半尺寸完成居中。
   * 不依赖容器尺寸，也不用百分比 —— 容器是 0 高 0 宽。 */
  left: calc(50% + var(--ax, 0) * var(--r) - var(--side) / 2);
  top: calc(50% + var(--ay, 0) * var(--r) - var(--side) / 2);
  width: var(--side); height: var(--side);
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.5);
  background: radial-gradient(circle at 42% 32%, rgba(255, 255, 255, 0.24), rgba(20, 26, 38, 0.4) 76%);
  display: flex; align-items: center; justify-content: center;
  /* 与摇杆同一档的透明度：看得见、不挡路 */
  opacity: 0.44;
  transition: opacity 0.18s ease, transform 0.12s ease, box-shadow 0.2s ease, border-color 0.2s ease;
  will-change: transform;
}
.tc-side.down { opacity: 0.92; transform: scale(0.92); }
.tc-side.disabled { opacity: 0.2; }
/* 道具：金色描边（与键鼠模式的 .item-btn 一致） */
.tc-side.tc-item { border-color: rgba(255, 204, 68, 0.85); box-shadow: 0 0 10px rgba(255, 200, 70, 0.3); }
/* 战意波动：青色描边；能量满时与键鼠模式一样呼吸提示 */
.tc-side.tc-skill.ready {
  opacity: 0.8;
  border-color: var(--cyan, #4fd4e8);
  box-shadow: 0 0 16px rgba(80, 220, 250, 0.75);
  animation: skillReady 1.1s ease-in-out infinite;
}
.tc-side.tc-skill.active { opacity: 1; border-color: #fff; background: radial-gradient(circle at 42% 32%, rgba(120, 220, 245, 0.5), rgba(30, 120, 150, 0.45) 76%); }
/* 图标：直接复用键鼠模式那几套 CSS 图形（.ri-bolt / .ri-jump），尺寸随按钮走 */
.tc-side .ri-bolt { width: 34%; height: 50%; }
.tc-side .ri-jump { width: 38%; height: 42%; }
.tc-side canvas { width: 62%; height: 62%; }
/* 道具数量角标 */
.tc-badge {
  position: absolute; top: -3px; right: -3px;
  min-width: 18px; height: 18px;
  padding: 0 3px;
  background: var(--danger, #ff4d6a);
  border: 2px solid #fff;
  border-radius: 10px;
  font-size: 11px; font-weight: 900; line-height: 14px; text-align: center;
  color: #fff;
  opacity: 0.9;
}

/* ---------- 触控下的其他收敛 ---------- */
/* 触控模式：准星下方的弹药读数略放大（手机屏幕远）、边缘指示箭头更醒目 */
body.touch-mode .ch-ammo { font-size: 15px; }
/* 触控模式：屏幕比例紧张时收起「按 Esc 继续行动」这类提示（由 responsive.css 处理） */

/* 低端设备 / 用户偏好：关掉脉动与流光 */
@media (prefers-reduced-motion: reduce) {
  .tc-fire.locked, .tc-lock.locked, .tc-lock.locked::after,
  .sel-imode.on .im-face::after, .tc-side.tc-skill.ready { animation: none; }
  .im-thumb { transition: transform 0.12s ease; }
}

/* ==================== 窄屏 / 矮屏收敛 ====================
 * 触控浮层的响应：矮屏时按钮整体收小。
 *
 * 所有覆盖一律写在 #ui-layer 上（与变量的定义处同级）——「增益选取区底距」
 * 依赖 --fire / --side / --stick，只有两边读到同一套值，增益区才会始终
 * 停在按钮行与摇杆的上方。若把覆盖写到叶子元素（.tc-fire / .tc-side）上，
 * 元素自身尺寸与 --r 会来自两套值，弧线立刻错位（实测过：开火按钮缩到 84px，
 * 弧仍按 96px 算，按钮切进开火按钮的圆里）。 */
@media (max-height: 560px) {
  .ui-layer {
    --stick: min(128px, 30vh);
    --stick-b: 14px;
    --fire: min(clamp(84px, 20vh, 116px), 24vw);
    --side: min(clamp(54px, 13vh, 72px), 15vw);
    --lock: min(clamp(40px, 9vh, 50px), 12vw);
    --arc-gap: 20px;
    --lock-pad: 8px;
  }
}
@media (max-width: 560px) {
  /* 竖屏窄机：按钮组贴边，摇杆缩到左下角 */
  .ui-layer {
    --fire: min(clamp(88px, 16vh, 118px), 26vw);
    --side: min(clamp(56px, 10vh, 76px), 17vw);
    --arc-gap: 18px;
  }
}
/* 极窄竖屏：底部血条被 .hud-bottom 收窄，触控按钮相应再收一档 */
@media (max-width: 430px) {
  .ui-layer {
    --side: min(clamp(50px, 9vh, 66px), 16vw);
    --arc-gap: 14px;
    --stick: min(clamp(104px, 18vh, 140px), 40vw);
  }
}

/* 极矮横屏（≤ 440px，手机横握）：纵向预算已被压缩到极限。
 *
 * 这一段上「顶部横幅 + 倒计时」与「增益区 + 触控按钮行」的纵向需求之和会超过
 * 屏高（逻辑高 480px）。实测 844×390 / 960×430 / 667×375 三档都差约 10~17px，
 * 增益区顶端会切进倒计时底边（探针报 cd_pk=1044 / 180 / 174）。
 * 三条同时收紧，把差量补回来：
 *   ① 按钮组的走廊与角上留白各收 4~8px（--arc-gap / --lock-pad / --pad-gap）；
 *   ② 摇杆缩到 100~130px；
 *   ③ 触控模式顶部三块再上提一档（横幅 66 / 倒计时 100，间距 10px）。
 * 横幅 66px 仍高于 .hud-top 的下沿（逻辑约 58px），不会压住波次读数。
 * 校验（844×390，--ui-s=0.8125 → 逻辑高 480）：
 *   倒计时底 100+36=136；按钮行顶 48+84+42+27+12+8=221
 *   → 增益区顶端 480−221−106=153 > 136 ✓（余量 17px） */
@media (max-height: 440px) {
  .ui-layer {
    --arc-gap: 12px;
    --lock-pad: 4px;
    --pad-gap: 4px;
    --stick: min(clamp(100px, 26vh, 130px), 34vw);
  }
  body.touch-mode .banner { top: 66px; }
  body.touch-mode .countdown { top: 100px; }
  body.touch-mode.boss-multi .banner { top: 122px; }
  body.touch-mode.boss-multi .countdown { top: 156px; }
}
