/* 第三幕 · 观战（文档 3.3）——画布是主角，HUD 全部贴边压在画布上。
   之前排行榜和详情是常驻侧栏，把画布挤成了页面的一个配件。 */

.arena-stage {
  display: flex;
  justify-content: center;
}

.canvas-wrap {
  position: relative;
  line-height: 0; /* 去掉 canvas 底部的行内间隙 */
  max-width: 100%; /* 跟着画布一起收，否则 HUD 会停在缩放前的位置 */
}

/* HUD 整体不吃鼠标事件，只有里面的控件吃——
   否则压在画布上的这几条会挡住"点鱼看详情"。 */
.hud {
  position: absolute;
  pointer-events: none;
  z-index: 5;
  /* 必须显式恢复行高。HUD 挂在 .canvas-wrap 里，而那个容器为了消掉 canvas
     底部的行内间隙设了 line-height: 0——继承下来的话，HUD 里所有面板的行高
     都是 0，文字会全叠在一起、面板高度算出来是 0。
     （排行榜就这么坏了很久：内容都在，但每一行的高度是 0。.hud-top 之前
     单独修过一次，在自己身上写了 line-height: 1.4；那是在打补丁，
     应该在容器上一次性解决。） */
  line-height: 1.4;
}

.hud button,
.hud select,
.hud input,
.hud label,
.hud .lb-row,
.hud .lb-toggle {
  pointer-events: auto;
}

/* ---- 顶部细条：场地 + 计时 + 击杀 feed ---- */
.hud-top {
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  /* 顶部条不做毛玻璃：它是一条从上往下的渐隐，做了模糊反而会切出一条硬边。 */
  background: linear-gradient(rgba(6, 12, 22, 0.88), rgba(6, 12, 22, 0));
  line-height: 1.4;
}

.hud-clock {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}

/* 击杀 feed 从左下角挪到顶部右侧，逐条淡入淡出 */
.hud-top .event-feed {
  /* 这里原先还有 `position:static; width:auto; max-width:none` 三条，
     是用来顶掉 style.css 里"左下角绝对定位"那版的。那版已经删了，
     这三条就只是在把默认值再写一遍——**留着会让人以为它们在防什么**。 */
  flex: 1;
  align-items: flex-end;
  gap: 3px;
}

/* 给右边的排行榜让出位置。不让的话播报会一直伸到画布右缘，被那块半透明
   面板压住——而播报恰恰是"刚刚发生了什么"，是这一屏最不能被挡住的东西。
   178px 是紧凑态宽度，展开态 236px 由下面那条覆盖。

   **条件写在选择器里，不写在注释里**：只有当同一个 `.canvas-wrap` 里真的
   有排行榜时才让位。原先这条无条件生效，于是"给一个不在那儿的东西留位置"
   在两处复发——`?gallery` 里 430px 的样例框只克隆了 `.hud-top`，播报被挤成
   51px 宽、246px 高，中文一个字一行竖着排；手机上排行榜一展开也是同样的
   结果（351px → 105px）。 */
.canvas-wrap:has(.hud-leaderboard) .hud-top .event-feed {
  margin-right: 188px;
}

/* 排行榜展开时占得更宽，播报要跟着再让一截。 */
.canvas-wrap:has(.hud-leaderboard.expanded) .hud-top .event-feed {
  margin-right: 246px;
}

/* ---- 右侧：可折叠排行榜 ----
   紧凑态只有名次/名字/体型，展开才显示体型条和击杀数。 */
.hud-leaderboard {
  top: 46px;
  right: 10px;
  width: 178px;
  /* HUD 是"压在水面上的一层毛玻璃"：底色半透 + 背景模糊 + 上缘一道内高光。
     不做模糊的话它只是一块半透明色板，水在它后面糊成一片脏色；
     做了模糊，水的运动仍然透得出来，但字是清楚的。 */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.06), transparent 32%),
    rgba(10, 20, 32, 0.72);
  backdrop-filter: blur(8px) saturate(1.1);
  border: 1px solid rgba(120, 170, 210, 0.16);
  border-radius: var(--r-md);
  box-shadow: var(--lift-2);
  overflow: hidden;
  font-size: var(--fs-sm);
  transition: width var(--t-base) var(--ease-out);
}

.lb-toggle {
  width: 100%;
  padding: 6px 9px;
  background: transparent;
  border: none;
  border-bottom: 1px solid #1f3350;
  color: var(--ink-dim);
  font-size: 11px;
  text-align: left;
  border-radius: 0;
}

.lb-rows {
  display: flex;
  flex-direction: column;
}

/* 点任意一行 = 镜头切到那条鱼（把已有的 cameraTarget 能力暴露成 UI） */
.lb-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 4px var(--sp-2);
  color: #a9bcd6;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out);
}

.lb-row:hover { background: rgba(255, 255, 255, 0.07); }

/* 前三名给一点金属感的名次色。排行榜的第一职责是"我第几"，
   第二职责是"谁在前面"——后者靠颜色比靠读数字快。 */
.lb-row:nth-child(1) .lb-rank { color: #f0cf7a; }
.lb-row:nth-child(2) .lb-rank { color: #c6d2df; }
.lb-row:nth-child(3) .lb-rank { color: #cc9a6a; }

.lb-rank { width: 1.2em; color: var(--ink-faint); flex-shrink: 0; }
.lb-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-size { font-family: "SFMono-Regular", Consolas, monospace; color: var(--ink); flex-shrink: 0; }
.lb-respawn { color: var(--bad); }
.lb-empty { padding: 8px 9px; color: var(--ink-faint); }

.lb-bar {
  display: none;
  width: 42px;
  height: 5px;
  background: #16233a;
  border-radius: var(--r-xs);
  overflow: hidden;
  flex-shrink: 0;
}

.lb-fill { display: block; height: 100%; background: var(--glow); }
.lb-extra { display: none; font-size: 10px; color: var(--ink-faint); flex-shrink: 0; }

/* 我这一行：粉底 + 左缘一道竖条。**满屏八行里一眼找到自己**是这个面板
   最要紧的事，所以它值得比 hover 更强的处理。 */
.lb-row.lb-you {
  background: linear-gradient(90deg, rgba(204, 79, 176, 0.24), rgba(204, 79, 176, 0.08));
}
.lb-row.lb-you::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--accent-bright);
}
.lb-row.lb-you .lb-name { color: var(--accent-bright); font-weight: 600; }
.lb-row.lb-you .lb-rank { color: var(--accent-bright); }

/* 体型条：加一点内发光，让它看起来是"充能"而不是一根静止的色块。 */
.lb-fill {
  box-shadow: 0 0 6px color-mix(in srgb, var(--glow) 55%, transparent);
  transition: width var(--t-slow) var(--ease-swim);
}

/* 死亡等待的那一行整体压暗——它此刻不在场上。 */
.lb-row:has(.lb-respawn) { opacity: 0.55; }
.lb-row.lb-dead { opacity: 0.5; }

.hud-leaderboard.expanded { width: 236px; }
.hud-leaderboard.expanded .lb-bar,
.hud-leaderboard.expanded .lb-extra { display: block; }

/* 静音键：常态很淡，静音时变红——"现在是静的"必须一眼看得出来，
   否则玩家会以为音频坏了。 */
.mute-btn {
  padding: 4px 8px;
  font-size: 14px;
  line-height: 1;
  background: transparent;
  border-color: #2c4468;
  color: var(--ink-dim);
}

.mute-btn:hover { border-color: #3a5a88; }
.mute-btn.muted { color: var(--bad); border-color: #7a3a3a; }

/* ---- 底部操作条：神谕在拇指区 ---- */
.hud-bottom {
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 12px;
  background: linear-gradient(rgba(6, 12, 22, 0), rgba(6, 12, 22, 0.88));
}

.hud-bottom .oracle-bar {
  margin: 0;
  background: transparent;
  border: none;
  padding: 0;
}

.hud-bottom .oracle-btn { padding: 5px 9px; font-size: 14px; }

.hud-right {
  display: flex;
  align-items: center;
  gap: 6px;
}

.hud-right button,
.hud-right select {
  padding: 4px 9px;
  font-size: 11px;
  flex: 0 0 auto;
}

/* ---- 点击鱼弹出的浮层小卡（取代常驻侧栏详情面板）----
   锚定一次，不追踪——追踪会让卡片跟着鱼满屏跑，读都读不了。 */
.fish-card {
  position: fixed;
  z-index: 60;
  width: 224px;
  padding: var(--sp-3);
  /* 和 HUD 同一套毛玻璃：它压在画布上，背后有水在动。 */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.055), transparent 34%),
    rgba(10, 20, 32, 0.88);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(120, 170, 210, 0.18);
  border-radius: var(--r-md);
  box-shadow: var(--lift-2);
  font-size: var(--fs-sm);
  color: #a9bcd6;
  line-height: 1.5;
  animation: feed-in var(--t-fast) var(--ease-out);
}

/* 三维条。和占卜屏的预览同一套表达——卡片是"扫一眼判断这条鱼什么路数"
   的东西，三个并排的数字要读要比，三条并排的柱子扫一眼就够。 */
.fc-size { margin: 4px 0 5px; }
.fc-size strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.fc-bars { display: grid; gap: 3px; margin-bottom: var(--sp-2); }
.fc-bar {
  display: grid;
  grid-template-columns: 26px 1fr 26px;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-xs);
}
.fc-bl { color: var(--ink-dim); }
.fc-bt { height: 5px; border-radius: var(--r-pill); background: rgba(255,255,255,0.08); overflow: hidden; }
.fc-bf { display: block; height: 100%; border-radius: var(--r-pill); }
.fc-bf.forage { background: var(--stat-forage); }
.fc-bf.fear { background: var(--stat-fear); }
.fc-bf.hunt { background: var(--stat-hunt); }
.fc-bv {
  text-align: right;
  color: var(--ink);
  font-family: "SFMono-Regular", Consolas, monospace;
  font-variant-numeric: tabular-nums;
}

.fish-card[hidden] { display: none; }

.fc-name { color: var(--ink); font-weight: 600; font-size: 13px; }
.fc-ghost { margin-left: 5px; font-size: 10px; color: var(--other); }
/* 当前主导行为，数据源和死亡判词同源，所以两处说的是同一件事 */
.fc-doing { color: var(--glow); margin-bottom: 3px; }
.fc-stats { font-family: "SFMono-Regular", Consolas, monospace; font-size: 10.5px; }
.fc-affixes { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }

.fc-affix {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  border: 1px solid;
}

.fc-affix.positive { color: var(--good); border-color: #3a8f5a; }
.fc-affix.negative { color: var(--bad); border-color: #a04848; }
/* 有得有失：紫。不能跟"纯扣分"的红混在一起，那会让玩家以为自己吃了亏。 */
.fc-affix.tradeoff { color: #c9a7f0; border-color: #6b4fa0; }
.fc-set { margin-top: 5px; color: #f0d090; font-size: 11px; }

/* ---- HUD 里的控件统一成"水下按钮" ----
   之前每个按钮各写各的底色和描边，压在动着的水上显得很杂。
   统一成半透玻璃 + 极淡描边，hover 时才亮起来。 */
.hud button:not(.lb-toggle):not(.lb-row),
.hud select {
  background: rgba(10, 22, 36, 0.66);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(120, 170, 210, 0.18);
  border-radius: var(--r-sm);
  color: var(--ink-dim);
  transition:
    color var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    background var(--t-fast) var(--ease-out);
}

.hud button:not(.lb-toggle):not(.lb-row):hover:not(:disabled),
.hud select:hover {
  color: var(--ink);
  border-color: rgba(126, 232, 224, 0.42);
  background: rgba(16, 34, 52, 0.8);
}

.hud button:disabled { opacity: 0.4; }

/* 神谕按钮：待命时是暗的，就绪时透出一点荧光——
   "现在能不能用"必须不用读文字就知道。
   选择器要压过上面那条 `.hud button:not(...):not(...)`（权重 0,3,1），
   所以这里也挂在 .hud 下面并多带一个 :not。 */
.hud .oracle-btn:not(:disabled):not(.x) {
  color: var(--glow);
  border-color: rgba(126, 232, 224, 0.32);
}
.hud .oracle-btn:not(:disabled):hover {
  color: #eafffd;
  border-color: var(--glow);
  background: rgba(126, 232, 224, 0.12);
}
.hud .oracle-btn.armed:not(.x) {
  background: rgba(126, 232, 224, 0.2);
  border-color: var(--glow);
  color: #eafffd;
  box-shadow: 0 0 14px rgba(126, 232, 224, 0.35);
}

/* 放弃是不可逆的，给它一点危险色——但只在 hover 时，
   常态压着，免得它比"暂停"还抢眼。 */
.hud #give-up-btn:hover:not(.x) {
  color: var(--bad);
  border-color: rgba(240, 160, 160, 0.45);
}

/* 跳过是排位专用的正向出口，用系统金。 */
.hud .skip-btn:not(.x) {
  color: var(--other);
  border-color: rgba(232, 184, 75, 0.38);
}
.hud .skip-btn:not(.x):hover { background: rgba(232, 184, 75, 0.14); color: #ffd98a; }

/* 计时器：最后 30 秒开始呼吸变红。**时间快到了**是这一屏最要紧的信息之一，
   而一行小字不会有人一直盯着。 */
.hud-clock.urgent {
  color: #ff9a9a;
  animation: clock-urgent 1s ease-in-out infinite;
}
@keyframes clock-urgent {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}
@media (prefers-reduced-motion: reduce) {
  .hud-clock.urgent { animation: none; }
}

/* ===================================================================
   窄屏：HUD 从"压在画布上"改成"排在画布下面"
   ===================================================================
   HUD 是按 960×600 的画布设计的：排行榜 178×223、底栏满宽。画布现在会
   跟着视口等比缩，到 375px 宽的手机上只剩 351×220——**这时候排行榜一块
   就盖掉了半个缸的宽度，八行还从缸底漏到页面外面去**（实测 lb.bottom
   超出画布 260px，行 6/7/8 悬在黑底上）。

   叠加式 HUD 的前提是"底下的画面足够大，遮一点无所谓"。这个前提在手机
   上不成立，所以换成堆叠：水面归水面，控件排到下面去。
   这和播报当初从左下角挪进顶栏是同一类处置——位置服从可用空间，
   不服从"原本设计成什么样"。 */
@media (max-width: 768px) {
  .canvas-wrap {
    /* 之前是 0，用来消掉 canvas 底部的行内间隙。这里要让后面的兄弟元素
       正常排版，必须显式恢复。 */
    line-height: normal;
    width: 100%;
  }

  .hud-leaderboard,
  .hud-bottom {
    position: static;
    width: auto;
    margin-top: var(--sp-2);
    /* 不再压在水面上，就不需要毛玻璃和渐隐了——那两样是为了"透出后面的
       水"，背后已经没有水了。 */
    backdrop-filter: none;
  }

  .hud-bottom {
    background: rgba(10, 20, 32, 0.72);
    border: 1px solid rgba(120, 170, 210, 0.14);
    border-radius: var(--r-sm);
    /* 控件在窄屏上排不下一行，允许换行，别挤成一条 */
    flex-wrap: wrap;
    justify-content: flex-start;
  }

  .hud-leaderboard { border-radius: var(--r-sm); }

  /* 移出画布之后 HUD 是真的要点的，不能再整体不吃事件。 */
  .hud-leaderboard,
  .hud-bottom { pointer-events: auto; }

  /* 顶栏留在画布上：它只有一条，且"第几分钟、几条鱼"要和画面一起看。 */
  .hud-top {
    position: absolute;
    flex-wrap: wrap;
    row-gap: var(--sp-1);
  }

  /* 播报的 `margin-right` 是给压在右上角的排行榜让位的。排行榜已经挪到画布
     下面了，这里留着就是白让——351px 宽的画布减掉 188 再减掉场地标签和计时，
     只剩三十来像素，**中文就会一个字一行竖着排下来**。
     （FIXLOG 里"用/它/出/战 竖排 + 横向滚动条"是同一个成因：给一个已经
     不在那儿的东西留位置。）

     **两条让位规则都要点名地清掉。** 这里原先只写了 `.hud-top .event-feed`
     （0,2,0），压不过展开态那条 `.canvas-wrap:has(.hud-leaderboard.expanded)
     …`（0,4,0）——所以手机上只要玩家把排行榜展开，上面说的竖排就原样回来。
     选择器写不到位的"修好了"，和没修一样。 */
  .canvas-wrap:has(.hud-leaderboard) .hud-top .event-feed,
  .canvas-wrap:has(.hud-leaderboard.expanded) .hud-top .event-feed {
    margin-right: 0;
  }

  .hud-top .event-feed {
    flex-basis: 100%;
    align-items: flex-start;
  }
}

/* 正在看的那条鱼。**点了一行切过去，那一行得说自己被选中了**——八行长得
   几乎一样，没有标记的话玩家马上就忘了自己点的是谁。
   （下拉框也显示当前目标，但比赛时眼睛在排行榜上，不在下拉框上。）

   用左缘一道亮边 + 一点底色，不用整行反白：这一行同时还可能是"我的鱼"
   （.lb-you，粉色）或"已阵亡"（.lb-dead，压暗），三种状态要能叠着看。 */
.lb-row.lb-watching {
  background: rgba(126, 232, 224, 0.1);
  box-shadow: inset 2px 0 0 var(--glow);
}
