/* ============================================================================
 * fig_tunnel.css —— ★★ 隧道纵切色块图的外观
 *
 *   ★★ 为什么单独一个文件（2026-10-14 从 dark.css 里搬出来的）：
 *     这套 `.tun-*` 规则原来写在 `dark.css` 里，但它们**没有 `body.skin-dark`
 *     前缀** —— 也就是说**不管什么皮肤都在生效**。
 *     而里面却硬编码了一堆**深藏青**（#16233A / #0F1B2E / #3A4F73 …）。
 *
 *   ★★★ 结果（一号位 2026-10-14 发现）：
 *       他要求"**全系浅色，不要深色**"，我把 `skin-dark` 去掉之后，
 *       这张图上就出现**五块黑斑** ——
 *       因为它们根本不是"深色皮肤"管的，是**写死的深色**。
 *
 *   ★ 修法：**把颜色全部换成变量**（`var(--bg-card)` / `var(--line)` …），
 *     这样它跟着皮肤走 —— 浅色下就是浅色，将来真要深色也不用改这里。
 *
 *   ★ 布局规则一个字没动（那是老系统最值钱的视图，见 99 号 §三）：
 *       横坐标 = 桩号 ÷ 结构物长度（真实比例）
 *       比例会重叠 → 退化成等距顺排；再放不下 → 横向滚动
 *       每根竖条固定 5 格（拱顶/左腰/右腰/左墙/右墙），缺位补"空"格、等高不瓜分
 *     ★ 竖条高度按"最多测点的断面"统一，各断面才视觉可比 ——
 *       否则 2 个测点的断面画得矮、5 个的画得高，一眼看不出"谁配得不全"。
 * ========================================================================== */

/* ---------------------------------------------------------------- 工具条 / 外框 */
.tun-toolbar {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-bottom: 8px;
}
.tun-wrap { position: relative; padding: 0 26px; }

/* 起终点竖排红字（老系统口径：浮在框外两侧、不占横向空间） */
.tun-cap {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  writing-mode: vertical-rl; text-orientation: upright;
  color: #C0392B; font-size: 13px; letter-spacing: 4px; user-select: none;
}
.tun-cap.cap-l { left: 0; }
.tun-cap.cap-r { right: 0; }

/* 隧洞外框
 *
 * ★★★ V1.7.1（一号位 2026-10-23 03:46）：**换成真正的"隧道剖切图"**。
 *   以前的底纹是 45° 斜线渐变（`repeating-linear-gradient`）——
 *   那只是个"阴影线"示意，不是剖面图；他要的是拿他给的那张钢笔细线剖切图当底板。
 *   → 斜线渐变删掉，改由 JS 画的 `<svg class="tun-bg">` 承担（围岩 + 顶底衬砌框）。
 *
 * ★ 边框也一起去掉：他说「剖切面两头两端**全部切干净**」——
 *   留 2px 外框就会在左右两端各画一条竖线，等于给了个"封口"，跟要求相反。
 *   （`.tun-scroll` 的边框宽度在 fig_tunnel.js 里已经从 4px 改成 0，两处必须同步。）
 */
.tun-scroll {
  box-sizing: border-box;
  width: 100%; overflow-x: auto; overflow-y: hidden;
  border: 0; border-radius: 4px;
  background: transparent;
}
.tun-canvas { position: relative; min-width: 100%; }

/* 剖面图底板（JS 生成）—— 在最底层，断面框压在上面 */
.tun-bg { position: absolute; left: 0; top: 0; z-index: 0; pointer-events: none; }
.tun-sec { z-index: 1; }

/* 一根竖条 = 一个断面 */
.tun-sec {
  position: absolute; top: 8px; display: flex; flex-direction: column; gap: 3px;
  border: 2px solid var(--brand); border-radius: 3px; padding: 3px;
  background: var(--bg-card);
}

/* ★ 断面标签是【断面布置图】的入口（不是色块）——老系统的分工，
   点标签看"怎么装的"，点色块看"这个点怎么样"，两个问题不同。 */
.tun-tag {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  /* ★★★ V1.5.1（P-19）：改成【两行】—— 一号位 00:23「打个回车，
     就是『断面1：』然后回车『K0+1』，别让这个小字比我断面的整个蓝框框还要宽」。
     ★ 所以这里不能 nowrap（否则长桩号会撑宽、挤到邻居），改成按两段自己折。 */
  white-space: normal; text-align: center;
  font-size: 12px; line-height: 1.15; color: var(--brand-text); padding-top: 3px;
  cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px;
  background: none; border: 0;
  /* ★ 宽度上限 = 断面包的宽度，超出就由 JS 算的 wMin 兜住（而不是压到邻居身上） */
  max-width: 56px;
}
/* 两段各自成一行的容器：不换行、各自居中 */
.tun-tag .tun-tag-n,
.tun-tag .tun-tag-s { display: block; white-space: nowrap; }
.tun-tag .tun-tag-s { font-weight: 500; }
/* ★ 原来是 `color:#fff` —— 那是为深底写的。浅底上白字**看不见**。 */
.tun-tag:hover { color: var(--brand-dark); text-decoration: underline solid; }

/* 一格 = 一个测点。竖排文字（老系统同款），因为格子窄而位置名很长。 */
.tun-cell {
  width: 38px; min-height: 32px; border-radius: 3px;
  display: flex; align-items: center; justify-content: center;
  font-size: 11.5px; line-height: 1.1;
  /* ★ 格子底色是绿/黄/红/灰（饱和色）。绿/红/灰底用白字；
   *   黄底上白字看不清 → c-warn1 单独用暗金字（见下）。 */
  color: #fff; cursor: pointer;
  writing-mode: vertical-lr; letter-spacing: 1px; user-select: none; border: 0;
  padding: 0;
}
.tun-cell:hover { outline: 2px solid var(--brand); outline-offset: -1px; }
/* ★★★ 状态色口径（V1.9.2 定）：**绿=正常 / 黄=一级 / 红=二级 / 灰=无法判断** */
/* ★★★ V1.9.2：4 色统一（绿/黄/红/灰），**色块和圆点用同一套变量**
 *
 *   ★ 一级改黄后有个硬约束：**白字在黄底上只有 1.7:1，等于看不见**（WCAG 要 4.5）。
 *     所以一级色块的文字必须换成**深琥珀**（对比度 5.6:1）。
 *     绿/红/灰底上的白字保持不动（本来就够）。
 */
.tun-cell.c-ok    { background: var(--ok); }
.tun-cell.c-warn1 { background: var(--warn1); color: #4A3A00; }   /* 黄底 → 暗金字（V2.0 去橙，别用棕） */
.tun-cell.c-warn2 { background: var(--warn2); }
.tun-cell.c-na    { background: var(--na); }
/* 空位 = 最不该被注意的东西 → 透明底 + 浅灰虚线（浅色下用 --empty-line） */
.tun-cell.c-empty {
  background: transparent; border: 1px dashed var(--empty-line); color: var(--ink-3);
  cursor: default;
}
.tun-cell.c-empty:hover { outline: none; }

/* 比例尺（老系统已知缺陷 #12：顺排时桩号比例丢失 →
   新版折中办法：顺排时在底部画一条【等距刻度】，至少把桩号数字留在眼前） */
.tun-scale {
  position: relative; height: 34px; margin-top: 24px;
  border-top: 1px dashed var(--empty-line);
}
.tun-scale span {
  position: absolute; top: 4px; transform: translateX(-50%);
  font-size: 10.5px; color: var(--ink-3); white-space: nowrap;
}

/* 盯盘页的统计行 / 图例（原来带 `body.skin-dark` 前缀，现在不分皮肤） */
.stat-line { font-size: 13px; }
.legend { color: var(--ink-2); }

/* ---------------------------------------------------------------- 手机：① 结构物横屏看 */
/* ★★ 一号位口径（34 号 §七）：① 结构物「**横屏看**（转成长条，显示隧道断面）」。
   落地办法：竖屏时给一个明显的"请横屏"提示条 + 允许整块横向滚动；
   横屏后自动按可用宽度重算比例（fig_tunnel.js 监听 resize/orientationchange 重画）。 */
.rotate-tip {
  display: none; padding: 8px 10px; margin-bottom: 8px; border-radius: 6px;
  background: var(--bg-soft); color: var(--warn1-ink); font-size: 12.5px;
}
@media (max-width: 820px) and (orientation: portrait) {
  .rotate-tip { display: block; }
  /* 竖屏下让长条尽量占满：两侧留白收掉 */
  .tun-wrap { padding: 0 16px; }
  .tun-cell { width: 30px; min-height: 28px; font-size: 10.5px; padding-right: 11px; }
  /* ★ 窄屏格子只有 28px 高，7px 的点放 3 个会溢出 → 缩回 5px */
  .tun-dot { width: 5px; height: 5px; }
  .tun-dots { gap: 3px; right: 3px; }
}
@media (max-width: 820px) and (orientation: landscape) {
  .tun-wrap { padding: 0 14px; }
  .tun-cell { width: 32px; min-height: 30px; padding-right: 13px; }
  .tun-dot { width: 6px; height: 6px; }
  .tun-dots { gap: 4px; right: 3px; }
  /* 横屏时把盯盘页的纵向留白压掉，一屏尽量多放（手机上纵向本来就少） */
  .pane { padding: 8px; }
  .card { padding: 8px 10px; margin-bottom: 8px; }
}

/* ---------------------------------------------------------------- ★★★ V1.9.0 色块上的圆点
 *
 * 一号位 2026-10-23 11:19：「每个色块上面……内部可以内嵌几个不同颜色的小圆点，
 * 这个小圆点表示**出现过的报警的类型**」。
 *
 * ★★ 圆点的三条硬规矩（docs/118 §3.2）：
 *   ① **不带时间、不带次数、不带新鲜度** —— 一旦带时间，用户又要开始"逐次判断"，设计破功
 *   ② **圆点不可点**（太小必点瓢），点色块本体进历史
 *   ③ **它是欠账**：该类区间全部处置完，这个点才消失
 */
.tun-cell { position: relative; }
/* ★★★ V1.9.0 post-fix（一号位 2026-10-23 18:13）
 *   「把这三个点从底下转移到了右边，和左边其实理论上一样……
 *    让三个点竖着排列，跟测点位置这个字一样高，显得协调一点。」
 *
 *   ★ 右侧竖排 + 垂直居中（与"拱顶/左腰"那两个字等高）。
 *   ★★ 3 个点 = 灰 / 黄 / 红（绿就是格子底色，不是点）—— 点只有 3 种，塞得下。
 *   ★ 点的**顺序 = 新鲜度**：最上面那点是"最近一次故障的类型"。
 *     颜色给严重度、顺序给时间序，两个维度正交，用户一眼扫过去自己判断先看哪个。
 */
.tun-dots {
  /* ★★★ V1.9.0 post-fix（一号位 2026-10-24 12:51）
   *   「只有一个灰点的时候，它应该出现在啥位置呢？你自己分析一下。」
   *
   *   ★ 答案：第 1 位（最上面）。但实测发现**3 个槽横着叠在一起、点还压在文字上**。
   *   ★★ 根因是 `writing-mode` 的坑：
   *     格子 `.tun-cell` 是 **`writing-mode: vertical-lr`**（为了让"拱顶"竖排），
   *     而在竖排书写模式下 **`flex-direction: column` 的主轴是"水平"的**（block 轴转 90°）
   *     → 三个点被**横向**排开、全部落在同一个 top 上 → 看起来叠成一个、还压到字上。
   *   ★ 修法：给容器**显式恢复横排书写模式**，让 column 重新等于"从上到下"。
   *     （这是唯一只需要动一行就能修的地方，不要去改格子的 writing-mode —— 那会把文字排乱。）
   */
  writing-mode: horizontal-tb;
  text-orientation: mixed;
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; align-items: center;
  gap: 5px; pointer-events: none;      /* ★ 规矩②：点不中，也不许点 */
}
/* ★ 文字要给点让位，否则"拱顶"会顶到点上 */
.tun-cell { padding-right: 15px; }
.tun-dot {
  /* ★★★ 2026-10-31 20:11（一号位：「这三个点有点小，加大一点，离彼此远一点，更显眼」）
   *   5px → **7px**（+40%），配合 gap 3→5px；视觉外径从 ~9px 变成 ~11px。
   *   ★ 桌面格子高 40px，3 个点占 3×7+2×5 = 31px，放得下；
   *   ★ 窄屏格子只有 28px，所以在下面的 @media 里单独缩回去（否则会溢出）。 */
  display: block; width: 7px; height: 7px; border-radius: 50%;
  /* ★★★ V1.9.2（一号位 2026-10-24 13:19 要求"圆点和色块颜色统一"之后的**必然副作用**）：
   *
   *   ★ 一旦统一，**同色的点在自己的色块上就隐身了** ——
   *     黄块（一级）+ 黄点 → 只剩一圈白边，看着像个空心圈，不知道是什么；
   *     红块 + 红点同理。而"当前一级报警 + 一级有未清账"是**很常见**的场景。
   *
   *   ★ 修法：**双描边** —— 内圈白 + 外圈半透明黑。
   *     白圈负责在深色底（绿/红/灰）上咬住轮廓，
   *     黑外圈负责在浅色底（**黄**）上咬住轮廓，
   *     两者叠加后：无论点色和底色是否相同，都能看出"这里有一个点"。
   *   ★ 视觉外径 5 + 1 + 1 = 7px，格子右侧留了 11px，不会压到文字。
   */
  /* ★★★ 2026-10-31 20:27：改成**面档鲜色**之后，同色底上更容易糊在一起，
   *   所以描边同时加强（白 1.2 + 黑 2.2）—— 保证黄点坐在黄块上、红点坐在红块上
   *   也仍然看得出"这里有一个点"。视觉外径 7 + 2×2.2 ≈ 11.4px。 */
  box-shadow: 0 0 0 1.2px rgba(255, 255, 255, .96),
              0 0 0 2.2px rgba(0, 0, 0, .42);
}
/* 只有 3 类。★ 灰用**深一点的灰**（#7B8189），浅灰在深绿底上像脏点 */
/* ★★★ V1.9.0 post-fix（一号位 2026-10-24 12:51）
 *   「在没有出现过红色和黄色报警的情况下，出现了灰色报警，**那时候它应该出现在啥位置呢**？」
 *
 *   ★ 答案：**第 1 位（最上面）** —— 它是"最近一次报警"，位置本来就在表达新旧。
 *   ★★ 我原来的实现是"容器垂直居中"，只有 1 个点时它**飘在格子正中间**，
 *     看上去像"排在队列中间"，跟"最新"的语义打架。
 *   → 改成**固定 3 个槽位**：从上往下填，有内容就亮，没内容用 `visibility:hidden` **占位**。
 *     这样第几位永远是第几位，1 个点也能看出"它在第 1 位"。
 */
/* ★ 隐形占位：某一类没有时**仍然占着它那一格**，位置永远不动（2026-10-31 恢复）。
 *   理由见 `fig_tunnel.js` 的 `DOT_SLOT` —— 只有两个点时不许把剩下的两个居中。 */
.tun-dot.d-empty { visibility: hidden; }   /* 占位但完全不显示（含描边） */
/* ★★★ V1.9.2：圆点与色块**同一色系**，但圆点用「墨」档（比面深一档）。
 *
 *   ★ 为什么不用一模一样的色值：试过 —— **同色的点在自家色块上直接隐身**
 *     （黄块+黄点只剩一圈白边，看着像个空心圈；红块+红点同理）。
 *     而"当前一级报警 + 一级有未清账"是很常见的场景。
 *   ★★ 所以：**面（色块）用亮档、墨（圆点）用深档** —— 语义还是同一个颜色，
 *     但点在任何底色上都咬得住，不会消失。这就是一号位说的"色值区别不大"。
 */
.tun-dot.d-na    { background: #9CA3AF; }          /* 亮灰：★ 2026-10-31 提亮（原 #4B5563 在彩色块上几乎看不见） */
.tun-dot.d-warn1 { background: var(--warn1); }     /* 鲜黄：★ 2026-10-31 改面档（原暗金 #8A6A00 太闷） */
.tun-dot.d-warn2 { background: var(--warn2); }     /* 鲜红：★ 同上（原 #A31616 偏暗） */
