/* 预诊 web 页 —— 零框架、桌面优先、基本响应式。CSP default-src 'self'：无内联样式、无外链字体。
   2026-10-16 改版（按 frontend-design 方法）：概念是「分诊台」。全页唯一的饱和色是分诊标记——
   由预诊结论卡片的「归属」一格决定（我方问题 / 三方问题 / 非故障 / 原因待查，外加预诊中），
   列表里是每行最左的竖标，详情里是结论卡片的色条。其余一律墨色、灰、细线，不用阴影，
   免得和分诊色抢注意力。颜色全部走下面的 token，深色模式只换 token。 */
* { box-sizing: border-box; }
:root {
  color-scheme: light;
  --paper: #f2f4f3;        /* 病历纸：冷灰绿，不是常见的暖米色 */
  --surface: #ffffff;
  --surface-2: #f6f8f7;    /* 表头、行内代码、时间线底 */
  --ink: #1c2b2e;
  --muted: #5d6c6f;
  --faint: #8a9799;
  --rule: #d9e0de;
  --rule-soft: #e8edeb;
  --accent: #0b6b66;       /* 手术服青：链接与主按钮 */
  --accent-soft: #e3f0ee;
  --hover: #edf3f1;
  --danger: #b3362b; --danger-soft: #f8e6e3;
  --warn: #8a5300;   --warn-soft: #fbf0dc;
  --ok: #2c7a4b;     --ok-soft: #e2f1e7;
  --code-bg: #16252a; --code-ink: #dce6e3; --code-dim: #7d9094;
  /* 分诊色：只用在分诊标记上 */
  --t-now: #b3362b;      --t-now-soft: #f8e6e3;
  --t-plan: #9a5b00;     --t-plan-soft: #f9eedb;
  --t-decide: #5a48a6;   --t-decide-soft: #ebe8f6;
  --t-fine: #2c7a4b;     --t-fine-soft: #e2f1e7;
  --t-evidence: #4c6470; --t-evidence-soft: #e6ecee;
  --t-pending: #0b6b66;  --t-pending-soft: #e3f0ee;
  --t-off: #8a9799;      --t-off-soft: #eef1f0;
}
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --paper: #0f1719;
    --surface: #162124;
    --surface-2: #1b2a2d;
    --ink: #dce6e3;
    --muted: #96a8aa;
    --faint: #6e8184;
    --rule: #27383b;
    --rule-soft: #203033;
    --accent: #5cb8af;
    --accent-soft: #183a38;
    --hover: #1d2e31;
    --danger: #f08a7e; --danger-soft: #3a1f1c;
    --warn: #e3aa52;   --warn-soft: #36290f;
    --ok: #6cc594;     --ok-soft: #17332a;
    --code-bg: #0b1214; --code-ink: #dce6e3; --code-dim: #6e8184;
    --t-now: #f08a7e;      --t-now-soft: #3a1f1c;
    --t-plan: #e3aa52;     --t-plan-soft: #36290f;
    --t-decide: #aba0ec;   --t-decide-soft: #27223f;
    --t-fine: #6cc594;     --t-fine-soft: #17332a;
    --t-evidence: #9db3bc; --t-evidence-soft: #213035;
    --t-pending: #5cb8af;  --t-pending-soft: #183a38;
    --t-off: #6e8184;      --t-off-soft: #1b2a2d;
  }
}

body { margin: 0; background: var(--paper); color: var(--ink);
  font: 14px/1.6 -apple-system, "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", "Microsoft YaHei", "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.hidden { display: none !important; }
.dim { color: var(--muted); }
.err { color: var(--danger); min-height: 1.2em; }
/* 等宽数字：编号、时间、活计时每秒重写，比例数字会左右抖 */
.num, .el, td.nowrap { font-variant-numeric: tabular-nums; }

/* ——— 顶栏：浅底细线。原来的深蓝条会和分诊色抢第一眼 */
#topbar { display: flex; align-items: center; gap: 14px; padding: 10px 20px; background: var(--surface);
  border-bottom: 1px solid var(--rule); position: sticky; top: 0; z-index: 5; }
#brand { color: var(--ink); font-weight: 650; font-size: 16px; white-space: nowrap; display: inline-flex; align-items: baseline; gap: 8px; }
#brand .brand-sub { color: var(--muted); font-weight: 400; font-size: 12.5px; }
@media (max-width: 720px) { #brand .brand-sub { display: none; } }
#brand:hover { text-decoration: none; }
#search { flex: 1; max-width: 560px; padding: 7px 12px; border: 1px solid var(--rule); border-radius: 8px;
  background: var(--surface-2); color: var(--ink); outline: none; font-size: 13px; }
#search:focus { border-color: var(--accent); background: var(--surface); }
#search::placeholder { color: var(--faint); }
.health { margin-left: auto; font-size: 12px; color: var(--muted); white-space: nowrap; }
.health.bad { color: var(--danger); }
.health .lag { color: var(--warn); }
.who { font-size: 12px; color: var(--muted); white-space: nowrap; }
.logout { background: none; border: 1px solid var(--rule); color: var(--muted); font-size: 12px;
  padding: 4px 10px; border-radius: 6px; cursor: pointer; white-space: nowrap; }
.logout:hover { color: var(--ink); border-color: var(--faint); }

#tabs { display: flex; gap: 2px; padding: 0 20px; background: var(--surface); border-bottom: 1px solid var(--rule); }
#tabs a { color: var(--muted); padding: 9px 12px 8px; font-size: 13.5px; border-bottom: 2px solid transparent; }
#tabs a:hover { color: var(--ink); text-decoration: none; }
#tabs a.active { color: var(--ink); font-weight: 600; border-bottom-color: var(--accent); }

.warn { background: var(--warn-soft); color: var(--warn); padding: 7px 20px; font-size: 13px; border-bottom: 1px solid var(--rule); }

main { max-width: 1180px; margin: 20px auto 40px; padding: 0 16px; }
/* 详情页容器宽度 = 正文行长（44em × 15px = 660px）+ 面板内边距 24×2 + 边框 + main 内边距 16×2。
   算式对齐是有意的：行长限制只管文字，容器却比行长宽 200 多像素的话，内容全挤在左边、
   右边空出一条白带，看着像渲染坏了——2026-08-28 用户指出。宽屏下那条空档现在交给
   右侧的话题聊天栏（见「详情两栏」），窄屏仍是这个宽度。 */
main.narrow { max-width: 742px; }

/* ——— 按钮与工具条 */
.toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.toolbar label { display: flex; align-items: center; gap: 5px; color: var(--muted); cursor: pointer; }
.toolbar .spacer { flex: 1; }
.toolbar select { padding: 5px 8px; border: 1px solid var(--rule); border-radius: 7px; background: var(--surface);
  color: var(--ink); font-size: 13px; }
/* execCommand 兜底用的临时 textarea：CSP 禁内联样式，只能靠 class 移出视野 */
.offscreen { position: fixed; top: 0; left: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
button { padding: 6px 13px; border: 1px solid var(--rule); border-radius: 7px; background: var(--surface);
  color: var(--ink); cursor: pointer; font: inherit; font-size: 13px; line-height: 1.4; }
button:hover { border-color: var(--accent); color: var(--accent); }
a.btn { display: inline-block; padding: 6px 13px; border: 1px solid var(--rule); border-radius: 7px;
  background: var(--surface); color: var(--ink); font-size: 13px; line-height: 1.4; text-decoration: none; }
a.btn:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
button.primary, a.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--surface); }
a.btn.primary:hover, button.primary:hover { color: var(--surface); opacity: .88; }
button:disabled { opacity: .5; cursor: default; }

/* ——— 分诊标记：全页唯一的饱和色，按归属分四类（我方问题 / 三方问题 / 非故障 / 原因待查）。
   列表里每行已有一道分诊色竖标，标记本身只做淡底色块，不再自带色条——同一个意思编码两遍是噪音 */
.tri { display: inline-flex; align-items: center; gap: 6px; padding: 1px 8px; border-radius: 6px;
  font-size: 12.5px; font-weight: 600; white-space: nowrap; color: var(--tc); background: var(--tc-soft); line-height: 1.6; }
.tri .el { font-weight: 400; opacity: .8; }
/* 归属四类：我方问题最该先看（红），三方问题（琥珀），非故障（绿），原因待查（石板灰） */
.tri-ours { --tc: var(--t-now); --tc-soft: var(--t-now-soft); }
.tri-third { --tc: var(--t-plan); --tc-soft: var(--t-plan-soft); }
.tri-nonfault { --tc: var(--t-fine); --tc-soft: var(--t-fine-soft); }
.tri-unknown { --tc: var(--t-evidence); --tc-soft: var(--t-evidence-soft); }
.tri-pending { --tc: var(--t-pending); --tc-soft: var(--t-pending-soft); }
.tri-failed { --tc: var(--t-now); --tc-soft: var(--t-now-soft); }
.tri-off, .tri-other { --tc: var(--t-off); --tc-soft: var(--t-off-soft); }

/* ——— 话题列表 */
.tablewrap { overflow-x: auto; background: var(--surface); border: 1px solid var(--rule); border-radius: 10px; }
table { border-collapse: collapse; width: 100%; min-width: 960px; }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--rule-soft); vertical-align: top; }
th { font-size: 12px; color: var(--muted); font-weight: 600; white-space: nowrap; background: var(--surface-2);
  border-bottom-color: var(--rule); }
tr:last-child td { border-bottom: none; }
tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--hover); }
/* 每行最左一道分诊色竖标：扫一列颜色就知道今天哪些要动手 */
tbody tr.row td:first-child { box-shadow: inset 3px 0 0 var(--tc, transparent); }
/* 按天分隔行：不是话题行，别给点击手势和 hover 反馈 */
tbody tr.daysep, tbody tr.daysep:hover { cursor: default; background: var(--paper); }
tbody tr.daysep td { padding: 6px 12px; font-size: 12px; font-weight: 600; color: var(--muted); border-bottom-color: var(--rule); }
td.title { width: 100%; max-width: 0; }
td.title .t { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 第二行：预诊结论卡片的「现象」——比原始标题干净，扫列表时先读它 */
td.title .ph { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted);
  font-size: 12.5px; margin-top: 1px; }
td.nowrap, th.nowrap { white-space: nowrap; }
td.no { color: var(--muted); }
/* 诊断中：用主色提示「有工人在跑」，计时数字见 .el 的等宽规则 */
td.diag .diag-run { color: var(--accent); }
td.owner { color: var(--muted); font-size: 13px; }

.badge { display: inline-block; padding: 1px 9px; border-radius: 6px; font-size: 12px; white-space: nowrap; }
/* meta-line 里的「报告可能滞后」提示：行内、琥珀色。不用 .warn——那是整条横幅的样式。
   也不用 .err：红色会让人以为要立刻处理。 */
.stale { color: var(--warn); }
.badge .el { opacity: .72; }
.st-outofscope { background: var(--t-off-soft); color: var(--t-off); }
.st-pending { background: var(--t-pending-soft); color: var(--t-pending); }
.st-claimed { background: var(--accent); color: var(--surface); }
.st-done { background: var(--ok-soft); color: var(--ok); }
.st-done_rerunning { background: var(--surface); color: var(--ok); border: 1px solid var(--ok); }
.st-failed { background: var(--danger-soft); color: var(--danger); }
/* 话题状态用灰字：琥珀色的「进行中」满屏都是，会和分诊色抢注意力 */
.ist-open { color: var(--muted); }
.ist-resolved { color: var(--ok); }

.more { text-align: center; margin: 16px 0; }

/* 手机：表格改成一条条块，不再横向滚动。三行：分诊+编号+时间 / 标题 / 现象 */
@media (max-width: 720px) {
  .tablewrap.issues { overflow: visible; }
  .tablewrap.issues table { min-width: 0; }
  .tablewrap.issues thead { display: none; }
  .tablewrap.issues tbody tr.row { display: grid; grid-template-columns: auto auto 1fr auto; column-gap: 8px;
    padding: 10px 12px 10px 14px; border-bottom: 1px solid var(--rule-soft); box-shadow: inset 3px 0 0 var(--tc, transparent); }
  .tablewrap.issues tbody tr.row td { padding: 0; border: none; box-shadow: none; }
  .tablewrap.issues td.tri-cell { grid-row: 1; grid-column: 1; }
  .tablewrap.issues td.no { grid-row: 1; grid-column: 2; align-self: center; }
  .tablewrap.issues td.reply { grid-row: 1; grid-column: 4; align-self: center; font-size: 12px; }
  .tablewrap.issues td.title { grid-row: 2; grid-column: 1 / -1; max-width: none; width: auto; margin-top: 6px; }
  .tablewrap.issues td.title .t { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
  .tablewrap.issues td.title .ph { white-space: normal; }
  .tablewrap.issues td.chan, .tablewrap.issues td.owner, .tablewrap.issues td.ist, .tablewrap.issues td.created, .tablewrap.issues td.diag { display: none; }
  .tablewrap.issues tbody tr.daysep { display: block; }
  .tablewrap.issues tbody tr.daysep td { display: block; }
}

/* ——— 面板 */
.card { background: var(--surface); border: 1px solid var(--rule); border-radius: 10px; padding: 20px 24px; margin-bottom: 16px; }
.card h3 { margin: 0 0 10px; font-size: 15px; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* 「预诊」是分区标签，不是标题——真正的标题是报告自己的 h1。降成安静的小标签，标题位让给 h1。 */
.card-head h3 { font-size: 12.5px; font-weight: 600; color: var(--muted); margin: 0 0 10px; }
.card .toolbar { margin-top: 14px; margin-bottom: 0; }
.meta-line { color: var(--muted); font-size: 13px; margin: 6px 0 14px; display: flex; gap: 6px 16px; flex-wrap: wrap; }
/* 与标题同排的元信息：margin-right:auto 吃掉剩余空间，让它贴着标题走、按钮顶到右边 */
.card-head .meta-line.inline { margin: 0 auto 10px 0; min-width: 0; }
/* 窄屏时该被压缩的是中间的元信息，不是标题和按钮——不锁死的话「预诊」会被挤成竖排两字 */
.card-head h3, .card-head > button { flex: 0 0 auto; }
@media (max-width: 700px) {
  .card-head { flex-wrap: wrap; }
  .card-head .meta-line.inline { order: 3; flex-basis: 100%; margin: 0 0 10px; }
}

/* ——— 详情页头：编号放大当锚点，分诊标记紧跟其后；完整标题保留（客户邮箱是客服对号用的） */
.iss-hero { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.iss-no { font-size: 30px; font-weight: 650; line-height: 1.1; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.iss-hero .tri { font-size: 13px; padding: 2px 10px; }
.iss-state { font-size: 13px; }
.iss-title { margin: 10px 0 0; font-size: 17px; font-weight: 600; line-height: 1.5; word-break: break-word; }

.banner { padding: 8px 12px; border-radius: 8px; margin: 10px 0; font-size: 13px; }
.banner.info { background: var(--accent-soft); color: var(--accent); }
.banner.bad { background: var(--danger-soft); color: var(--danger); }
.banner.warnb { background: var(--warn-soft); color: var(--warn); }

/* ——— 话题聊天（详情页右栏 / 窄屏在页尾） */
.timeline { max-height: 420px; overflow-y: auto; border: 1px solid var(--rule-soft); border-radius: 8px; padding: 4px 14px;
  background: var(--surface-2); }
.msg { padding: 9px 0; border-bottom: 1px solid var(--rule-soft); }
.msg:last-child { border-bottom: none; }
.msg .who { color: var(--ink); font-weight: 600; margin-right: 8px; font-size: 13px; }
.msg .when { color: var(--faint); font-size: 12px; font-variant-numeric: tabular-nums; }
.msg .body { white-space: pre-wrap; word-break: break-word; margin-top: 2px; }
/* 话题消息按 markdown 渲染（同一套 .report 解析），排版收紧到侧栏：字号、段距、列表缩进都比报告小一号 */
.msg .body .chat-md { font-size: 14px; line-height: 1.6; word-break: break-word; overflow-wrap: anywhere; }
.msg .body .chat-md p, .msg .body .chat-md ul, .msg .body .chat-md ol { margin: 0 0 6px; }
.msg .body .chat-md > :last-child { margin-bottom: 0; }
.msg .body .chat-md ul, .msg .body .chat-md ol { padding-left: 1.4em; }
.msg .body .chat-md li + li { margin-top: 2px; }
.msg .body .chat-md h1, .msg .body .chat-md h2, .msg .body .chat-md h3 { font-size: 14.5px; margin: 8px 0 4px; }
.msg .body .chat-md code { font-size: 12.5px; }
.msg .body .chat-md .codeblock { margin: 0 0 6px; }
.msg .body .chat-md pre { padding: 24px 12px 10px; font-size: 12.5px; }
.msg .body .chat-md a { word-break: break-all; }
.msg .body .chat-md blockquote.quote { margin: 0 0 6px; padding: 2px 0 2px 10px; border-left: 3px solid var(--rule); color: var(--muted); }
.msg.deleted .body { color: var(--faint); }
/* 预诊覆盖到哪一刻：此后的消息预诊没看到，值班人要自己补读——这是判断报告是否过时的分界 */
.msg-sep { display: flex; align-items: center; gap: 10px; margin: 8px 0 2px; color: var(--accent); font-size: 12px; font-weight: 600; }
.msg-sep::before, .msg-sep::after { content: ""; flex: 1; height: 1px; background: var(--accent); opacity: .45; }
.msg.after .body { color: var(--ink); }

/* ——— 详情两栏（≥1200px）：左栏是结论与报告（行长不变），右栏是随页停住的话题聊天。
   右栏放的是与报告平行的另一份信息（群里实际说了什么），不是目录；窄屏回到单栏、聊天排在页尾。 */
main.detail { max-width: 742px; }
@media (min-width: 1200px) {
  main.detail { max-width: 1180px; display: grid; grid-template-columns: 742px minmax(0, 1fr); column-gap: 24px; align-items: start; }
  main.detail > .rail { position: sticky; top: 66px; max-height: calc(100vh - 86px); display: flex; flex-direction: column;
    margin-bottom: 0; padding: 16px 0 0; }
  main.detail > .rail h3 { padding: 0 18px; }
  main.detail > .rail .timeline { max-height: none; flex: 1 1 auto; min-height: 0; border: none; border-top: 1px solid var(--rule-soft);
    border-radius: 0 0 10px 10px; padding: 0 18px; }
}

/* ——— 预诊报告排版 ———
   全站唯一的长文区域，按长文排：① 层级靠字号拉开；② 行长按中文算，每行 35~45 字；
   ③ 只留下边距，避免和标题的下边距叠加。行长限制只加在文字元素上——表格和代码块该占满面板。 */
.report { font-size: 15px; line-height: 1.6; word-break: break-all; }
.report p, .report ul, .report ol, .report h1, .report h2, .report h3, .report blockquote { max-width: 44em; }
.report > :first-child { margin-top: 0; }
/* 标题一律不画线，分段靠留白；上边距远大于下边距：空白属于它引出的那一节 */
.report h1 { font-size: 24px; font-weight: 650; line-height: 1.35; margin: 0 0 20px; letter-spacing: -.01em; }
.report h2 { font-size: 19px; font-weight: 600; line-height: 1.45; margin: 38px 0 14px; }
.report h3 { font-size: 16.5px; font-weight: 600; margin: 30px 0 10px; color: var(--ink); }
.report p { margin: 0 0 16px; }
.report ul, .report ol { margin: 0 0 16px; padding-left: 1.5em; }
.report li + li { margin-top: 8px; }
.report li > ul, .report li > ol { margin: 6px 0 0; }
/* 代码块：软换行不横滚（多是要整段抄走的 SQL / ES 查询）；顶部 30px 空带放语言名和复制按钮 */
.report .codeblock { position: relative; margin: 0 0 16px; }
.report pre { margin: 0; background: var(--code-bg); color: var(--code-ink); padding: 32px 16px 14px;
  border-radius: 8px; font-size: 13px; line-height: 1.65; white-space: pre-wrap; overflow-wrap: anywhere; }
.report pre[data-lang]::before { content: attr(data-lang); position: absolute; top: 9px; left: 16px;
  font-size: 11.5px; color: var(--code-dim); }
.report .copybtn { position: absolute; top: 5px; right: 6px; padding: 3px 10px; font-size: 11.5px;
  line-height: 1.6; color: var(--code-dim); background: transparent; border: 1px solid #2c3d42; border-radius: 6px; }
.report .copybtn:hover { color: var(--code-ink); border-color: var(--code-dim); }
.report code { background: var(--surface-2); border: 1px solid var(--rule-soft); padding: 1px 5px; border-radius: 4px; font-size: 13.5px; }
.report pre code { background: none; border: none; padding: 0; font-size: inherit; }

/* 结论卡片 = 分诊单：报告里最先被看的六行，用来「扫」不是「读」。
   整块向左外扩 12px 让内文落回与 h1/正文同一条对齐线；左侧色条随「建议」变成分诊色（app.js 加 tri-*）。 */
.report blockquote.sum { margin: 0 -12px 26px; padding: 16px 18px 16px 9px; border-left: 4px solid var(--tc, var(--accent));
  background: var(--tc-soft, var(--accent-soft)); border-radius: 0 8px 8px 0;
  display: grid; grid-template-columns: max-content 1fr; column-gap: 18px; row-gap: 9px; }
.report blockquote.sum .k { color: var(--muted); font-size: 13.5px; }
.report blockquote.sum .v { color: var(--ink); }
.report blockquote.sum .bq-row { grid-column: 1 / -1; }
.report blockquote.sum strong { font-weight: 600; }
/* 代码快照过期之类的告警横幅同样是引用块，但它不是结论——单独给琥珀色 */
.report blockquote.note { margin: 0 -12px 18px; padding: 11px 16px 11px 9px; border-left: 4px solid var(--warn);
  background: var(--warn-soft); color: var(--warn); border-radius: 0 8px 8px 0; }
.report blockquote.note .bq-row + .bq-row { margin-top: 5px; }

/* ——— 报告「时间线」时间轴（2026-10-16 选定：间隔标注 + 每行归属标签，app.js enhanceTimeline）
   时刻 | 轨道 | 标签 + 事件。相邻两件事隔多久写在线上，超过 1 小时用琥珀色虚线；顶部写全程与最长一段。
   标签说的是「这件事发生在哪一方」，不是「这一步出了错」，颜色与列表页归属一致。 */
.report .tlx { max-width: 44em; margin: 0 0 16px; }
.report .tlx-sum { display: flex; flex-wrap: wrap; gap: 4px 16px; align-items: center; font-size: 13px; color: var(--muted); margin: 0 0 10px;
  font-variant-numeric: tabular-nums; }
.report .tlx-sum b { color: var(--ink); font-weight: 650; }
.report .tlx-legend { display: inline-flex; gap: 8px; margin-left: auto; }
.report .tlx-tag { display: inline-block; font-size: 12px; font-weight: 600; line-height: 1.6; padding: 0 6px; border-radius: 5px;
  color: var(--tc); background: var(--tc-soft); white-space: nowrap; }
.report .tlx .ours { --tc: var(--t-now); --tc-soft: var(--t-now-soft); }
.report .tlx .third { --tc: var(--t-plan); --tc-soft: var(--t-plan-soft); }
.report .tlx .chat { --tc: var(--t-evidence); --tc-soft: var(--t-evidence-soft); }
.report ul.tlx-list { list-style: none; margin: 0; padding: 0; max-width: none; }
.report .tlx-list > li { margin: 0; display: grid; grid-template-columns: 60px 18px minmax(0, 1fr); column-gap: 8px; }
.report .tlx-list > li + li { margin-top: 0; }
.report .tlx-list .t { color: var(--muted); font-size: 13.5px; padding-top: 2px; text-align: right; font-variant-numeric: tabular-nums; }
.report .tlx-list .rail { position: relative; }
/* 线和圆圈都按轨道列的正中定位：伪元素不吃全局 border-box，圆圈带边框实宽 13px，用 left 固定像素会偏 2px */
.report .tlx-list .rail::before { content: ""; position: absolute; left: 50%; transform: translateX(-50%); top: 0; bottom: 0; width: 1px; background: var(--rule); }
.report .tlx-list li.first .rail::before { top: 11px; }
.report .tlx-list li.last .rail::before { bottom: calc(100% - 11px); }
.report .tlx-list li.tlx-ev .rail::after { content: ""; position: absolute; left: 50%; transform: translateX(-50%); top: 7px; width: 13px; height: 13px; box-sizing: border-box; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--tc, var(--accent)); }
.report .tlx-list .x { padding-bottom: 11px; min-width: 0; }
.report .tlx-list .x > .tlx-tag { margin-right: 6px; vertical-align: 1px; }
.report .tlx-list li.tlx-day { font-size: 12.5px; font-weight: 600; color: var(--muted); }
.report .tlx-list li.tlx-day .d { padding: 2px 0 6px; text-align: right; color: var(--ink); line-height: 1.35; }
.report .tlx-list li.tlx-day.head .rail::before { display: none; }
.report .tlx-list li.tlx-gap { font-size: 12px; color: var(--faint); font-variant-numeric: tabular-nums; }
.report .tlx-list li.tlx-gap .g { padding: 0 0 8px; }
.report .tlx-list li.tlx-gap.long { color: var(--warn); font-weight: 600; }
.report .tlx-list li.tlx-gap.long .rail::before, .report .tlx-list li.tlx-day.long .rail::before { width: 0; background: none; border-left: 2px dashed var(--warn); }
.report .tlx-list li.tlx-gap.long .g { padding: 2px 0 10px; }
/* 时间轴里的证据编号收成灰色小字（仍可点开证据弹层），不再是一排彩色小按钮 */
.report .tlx-list button.eref { background: none; border: none; color: var(--faint); font-size: 12px; padding: 0 2px; margin: 0; }
.report .tlx-list button.eref:hover { color: var(--accent); text-decoration: underline; }
@media (max-width: 480px) {
  .report .tlx-list > li { grid-template-columns: 52px 16px minmax(0, 1fr); column-gap: 6px; }
  .report .tlx-list li.tlx-day .d { font-size: 11.5px; }
  .report .tlx-legend { margin-left: 0; }
}

/* ——— 根因 / 影响范围：结论框 + 判断标签（2026-10-16）。
   结论框借用 accent 浅底，与顶部按归属着色的结论卡片区分开；四个标签用已有的语义色，不另起新色。 */
.report .fd-call { max-width: 44em; border-left: 3px solid var(--accent); background: var(--accent-soft);
  border-radius: 0 8px 8px 0; padding: 10px 14px; margin: 2px 0 14px; }
.report .fd-call .k { display: block; font-size: 12.5px; font-weight: 600; color: var(--accent); margin-bottom: 2px; }
.report .fd-call .b { font-weight: 600; color: var(--ink); }
.report .fd-call .b strong { font-weight: inherit; }
.report ul.fd-list, .report ol.fd-list { list-style: none; padding-left: 0; }
.report .fd-list > li { display: grid; grid-template-columns: 52px minmax(0, 1fr); column-gap: 10px; }
.report .fd-list > li + li { margin-top: 9px; }
.report .fd-lab { justify-self: start; height: fit-content; margin-top: 3px; font-size: 12px; font-weight: 600; line-height: 1.6;
  padding: 0 6px; border-radius: 5px; white-space: nowrap; }
.report .fd-lab.fact { color: var(--ok); background: var(--ok-soft); }
.report .fd-lab.guess { color: var(--t-decide); background: var(--t-decide-soft); }
.report .fd-lab.out { color: var(--muted); background: var(--t-off-soft); }
.report .fd-lab.gap { color: var(--warn); background: var(--warn-soft); }
.report .fd-txt { min-width: 0; }
.report .fd-txt strong { font-weight: 650; }
/* 已排除整条压暗一档：读的人可以跳过，粗体的假设名保留墨色 */
.report .fd-list > li.out .fd-txt { color: var(--muted); }
.report .fd-list > li.out .fd-txt strong { color: var(--ink); }
@media (max-width: 480px) { .report .fd-list > li { grid-template-columns: 46px minmax(0, 1fr); column-gap: 8px; } }

/* ——— 实体芯片：类型名灰色小字 + 编号等宽，整块不断行（.report 的 break-all 会把长编号拦腰截断） */
.report .ent { word-break: normal; background: var(--surface-2); border: 1px solid var(--rule);
  border-radius: 5px; padding: 0 5px; margin: 0 1px; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.report .ent-h, .report .ent .v { white-space: nowrap; }
.report .ent i { font-style: normal; font-size: .8em; color: var(--muted); font-weight: 400; }
.report .ent .v { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: .87em; font-weight: 500;
  color: var(--ink); font-variant-numeric: tabular-nums; }
.report .ent .sep { color: var(--muted); font-weight: 400; }
.report .tm { white-space: nowrap; word-break: normal; }

/* 报告里的表格：逐条覆盖话题列表那套（min-width:960px、行可点、hover 变色） */
.report .tablewrap-md { overflow-x: auto; margin: 0 -12px 16px; }
.report table { min-width: 0; width: 100%; border-collapse: collapse; font-size: 14px; line-height: 1.7; }
.report th code, .report td code { font-size: 13px; padding: 1px 4px; }
.report th, .report td { border: 1px solid var(--rule); padding: 8px 10px; text-align: left; vertical-align: top; white-space: normal; }
.report th { background: var(--surface-2); font-weight: 600; color: var(--ink); font-size: 14px; }
.report tbody tr { cursor: default; }
.report tbody tr:hover { background: none; }

details.proc { margin-top: 8px; border-top: 1px solid var(--rule-soft); padding-top: 12px; }
details.proc summary { cursor: pointer; color: var(--accent); }
details.proc .report { margin-top: 10px; }

.runs { margin-top: 18px; border-top: 1px solid var(--rule-soft); padding-top: 12px; }
.runs h3 { font-size: 12.5px; font-weight: 600; color: var(--muted); }
.runrow { font-size: 12.5px; color: var(--muted); padding: 5px 0; border-top: 1px solid var(--rule-soft); font-variant-numeric: tabular-nums; }
.runrow:first-of-type { border-top: none; }
.res-row { padding: 6px 0; border-top: 1px solid var(--rule-soft); }
.res-row:first-of-type { border-top: none; }
.res-row b { color: var(--muted); font-weight: 600; margin-right: 6px; }

/* ——— 登录 */
/* 2026-10-17 改版：原来是半透明遮罩 + 浮卡，顶栏从底下透出来像没加载完，空的报错行还在标题下撑出一大块白。
   现在未登录时整页就是登录页（body.locked 藏掉外壳），水平居中一栏，不用卡片。
   起初左对齐，宽屏下右边空一大片、像没排完——同日用户要求改居中。
   主按钮用站内青色而不是 GitLab 橙——饱和色只留给分诊标记，GitLab 靠单色图标认。 */
body.locked > :not(#login) { display: none !important; }
.login { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column;
  padding: 0 20px; text-align: center; }
/* 垂直方向略高于正中（底部多留 8vh），几何正中看着偏下 */
.login-body { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 16px;
  width: min(360px, 100%); margin: 0 auto; padding: 48px 0 8vh; }
.login-mark { margin: 0; font-size: 44px; font-weight: 700; letter-spacing: .04em; line-height: 1.1; }
.login-desc { margin: -8px 0 4px; color: var(--muted); font-size: 14.5px; }
.login .err { margin: 0; min-height: 0; font-size: 13px; }
.login .err:empty { display: none; }
.gl-btn { display: flex; align-items: center; justify-content: center; gap: 8px; background: var(--accent); color: var(--surface);
  font-weight: 600; padding: 11px 16px; border-radius: 8px; font-size: 14px; }
.gl-btn:hover { opacity: .88; text-decoration: none; }
.gl-ico { width: 17px; height: 17px; flex: none; }
#break-glass { border-top: 1px solid var(--rule); padding-top: 14px; margin-top: 4px; }
#break-glass summary { font-size: 13px; color: var(--muted); cursor: pointer; width: fit-content; margin: 0 auto; }
#break-glass summary:hover { color: var(--ink); }
.login form { display: flex; gap: 8px; margin-top: 12px; }
.login input { flex: 1; min-width: 0; text-align: left; padding: 8px 12px; border: 1px solid var(--rule); border-radius: 8px; font-size: 14px;
  background: var(--surface); color: var(--ink); }
.login input:focus { border-color: var(--accent); outline: none; }
.login-foot { margin: 0; padding: 16px 0 max(16px, env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--rule-soft);
  color: var(--faint); font-size: 12px; }

@media (max-width: 720px) {
  #topbar { flex-wrap: wrap; padding: 10px 16px; }
  #tabs { padding: 0 16px; }
  .health { margin-left: 0; width: 100%; white-space: normal; }
  main { margin-top: 12px; }
  .card { padding: 16px; }
  .iss-no { font-size: 26px; }
}

/* ——— 证据引用弹层：正文里的 [E2] 是句尾小标签，不做实心按钮 */
.report button.eref { display: inline; padding: 0 5px; margin: 0 1px; border: 1px solid var(--rule); border-radius: 4px;
  background: var(--accent-soft); color: var(--accent); font: inherit; font-size: .86em; line-height: 1.5; cursor: pointer; vertical-align: baseline; }
.report button.eref:hover { border-color: var(--accent); }
.report .eref-def { color: var(--muted); font-weight: 600; }
/* 从弹层「定位」过来时给原条目闪一下底色 */
.report li.flash { background: var(--warn-soft); border-radius: 4px; transition: background .5s; }

/* ——— 证据引用（2026-10-16「甲＋丙」）：来源标签 + 加粗发现 + 补充；出处折成一行，点开是「名目 / 原文」两列 */
.report .ev-kind { display: inline-block; font-size: 12px; font-weight: 600; line-height: 1.6; padding: 0 6px; border-radius: 5px;
  color: var(--muted); background: var(--surface-2); border: 1px solid var(--rule); white-space: nowrap; margin: 0 4px; vertical-align: 1px; }
/* 证据里的行内代码先在空格、标点处换行，实在放不下才拦腰折（.report 默认 break-all 会把 hostex_server 折成两截） */
.report .ev, .report .ev code { word-break: normal; overflow-wrap: anywhere; }
.report .ev-blk { display: inline-block; max-width: 100%; overflow-x: auto; white-space: pre; word-break: normal; vertical-align: bottom; }
.report ul.ev-list { list-style: none; padding-left: 0; }
.report ul.ev-list > li + li { margin-top: 14px; }
.report li.ev-new { display: grid; grid-template-columns: 34px minmax(0, 1fr); column-gap: 8px; }
.report li.ev-new > .eref-def { padding-top: 1px; }
.report .ev-main { min-width: 0; }
.report .ev-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.report .ev-head .ev-kind { margin: 0; }
.report .ev-find { font-weight: 650; }
.report .ev-kib { font-size: 12.5px; white-space: nowrap; }
.report .ev-detail { margin-top: 2px; }
.report details.ev-fold { margin-top: 5px; }
.report details.ev-fold > summary { list-style: none; cursor: pointer; display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 8px;
  align-items: baseline; font-size: 12.5px; color: var(--faint); padding: 3px 8px; border: 1px dashed var(--rule); border-radius: 6px; }
.report details.ev-fold > summary::-webkit-details-marker { display: none; }
.report details.ev-fold > summary:hover { border-color: var(--accent); color: var(--muted); }
.report details.ev-fold .lead { color: var(--accent); white-space: nowrap; }
.report details.ev-fold .lead::before { content: "▸ "; }
.report details.ev-fold[open] .lead::before { content: "▾ "; }
.report details.ev-fold .peek { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; word-break: normal; }
.report details.ev-fold[open] > summary { border-style: solid; border-color: var(--rule-soft); background: var(--surface-2);
  border-radius: 6px 6px 0 0; }
.report details.ev-fold[open] .peek { visibility: hidden; }
.report dl.ev-src { margin: 0; display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 2px 10px; font-size: 12.5px;
  background: var(--surface-2); border: 1px solid var(--rule-soft); border-top: none; border-radius: 0 0 7px 7px; padding: 6px 10px 8px; }
.report dl.ev-src dt { color: var(--faint); white-space: nowrap; }
.report dl.ev-src dd { margin: 0; min-width: 0; font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; color: var(--ink);
  overflow-x: auto; white-space: pre; word-break: normal; }
.report dl.ev-src dd.ev-multi { white-space: normal; overflow-wrap: anywhere; overflow-x: visible; }
.report dl.ev-src dd code { background: none; border: none; padding: 0; font-size: inherit; }
.report dl.ev-src dd.ev-code { grid-column: 1 / -1; white-space: normal; font-family: inherit; }
.report dl.ev-src dd.ev-code .codeblock { margin: 2px 0 0; }
.report .ev-all { float: right; margin-top: 4px; font: inherit; font-size: 13px; font-weight: 400; color: var(--accent);
  background: none; border: none; padding: 0; cursor: pointer; }
.eref-body .ev-pop .eref-def { display: none; }
@media (prefers-reduced-motion: reduce) { .report li.flash { transition: none; } }

dialog.eref-dlg { width: min(760px, calc(100vw - 32px)); max-height: min(82vh, 760px); padding: 0;
  border: 1px solid var(--rule); border-radius: 12px; color: var(--ink); background: var(--surface); }
dialog.eref-dlg[open] { display: flex; flex-direction: column; }
dialog.eref-dlg::backdrop { background: rgba(10, 20, 22, .45); }
.eref-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 18px; border-bottom: 1px solid var(--rule); }
.eref-title { font-weight: 600; font-size: 15px; }
.eref-body { padding: 16px 18px 6px; overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.eref-body .report p, .eref-body .report ul, .eref-body .report ol { max-width: none; }
.eref-foot { display: flex; justify-content: flex-end; padding: 10px 18px; border-top: 1px solid var(--rule); }

/* ——— 告警事件 */
.sev-critical { background: var(--danger-soft); color: var(--danger); }
.sev-warning { background: var(--warn-soft); color: var(--warn); }
.sev-info { background: var(--accent-soft); color: var(--accent); }
.inc-open { color: var(--warn); }
.inc-resolved { color: var(--ok); }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; font-size: 13px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }
pre.raw { background: var(--surface-2); border: 1px solid var(--rule); border-radius: 8px; padding: 10px; font-size: 12px;
  overflow: auto; max-height: 320px; white-space: pre-wrap; word-break: break-all; color: var(--ink); }
/* 告警事件表的「结论」列：和「标题」列都用 width:100% 会相争，给它独立配比 */
td.concl, th.concl { width: 34%; max-width: 0; }
td.concl .t { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
