/* Komari 状态墙 · StatusWall 2.0
 * 白底 + Solarized 强调色 + 磨砂玻璃卡片。
 * 页面底色是纯白，颜色只来自 Solarized 调色板：底纹是极淡的色雾，
 * yellow/orange/red/green/cyan/blue/violet 只用在状态与数据上。 */

/* ---------------------------------------------------------------- 字体 */

/* IBM Plex Mono（SIL OFL 1.1）latin 子集，随包分发。
   之前只写了 <link rel=preload> 却没有 @font-face，字体实际从未加载，
   数字走的是系统等宽字体，那 130 KB 也白下了。 */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/plex-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/plex-500.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/plex-600.woff2") format("woff2");
}

/* ---------------------------------------------------------------- 调色板 */

:root {
  /* Solarized 底：base3 米白 + base2 蒙版，卡片是米白玻璃，强调色全部来自 Solarized */
  --bg: #fdf6e3;                        /* base3 */
  --veil-a: rgba(253, 246, 227, 0.80);
  --veil-b: rgba(238, 232, 213, 0.62);   /* base2 */
  --wash-1: rgba(38, 139, 210, 0.26);    /* blue */
  --wash-2: rgba(42, 161, 152, 0.22);    /* cyan */
  --wash-3: rgba(108, 113, 196, 0.18);   /* violet */
  --wash-4: rgba(181, 137, 0, 0.20);     /* yellow */
  --card: rgba(255, 253, 246, 0.70);
  --card-2: rgba(255, 252, 242, 0.92);
  --card-line: rgba(151, 133, 96, 0.34);   /* 暖化过的 base1，配米白纸 */
  --card-hi: rgba(255, 255, 255, 0.72);
  --card-glow: rgba(255, 255, 255, 0.42);
  --card-shadow: 0 14px 32px -22px rgba(88, 110, 117, 0.52);
  --track: rgba(151, 133, 96, 0.22);
  --line: rgba(151, 133, 96, 0.30);
  --line-2: rgba(151, 133, 96, 0.15);
  --base-2: #eee8d5;                     /* base2 */
  --ink: #44595f;
  --ink-2: #4e646a;
  --ink-3: #586e75;                      /* base01 */
  --ink-4: #566d73;

  --ok: #859900;
  --warn: #b58900;
  --crit: #dc322f;
  --blue: #268bd2;
  --cyan: #2aa198;
  --violet: #6c71c4;
  --magenta: #d33682;
  --orange: #cb4b16;

  /* 三网条带专用：常态墨绿低彩度，抖动才按黄→橙→红升温 */
  --seg-ok: #96a93a;
  --seg-slow: #d0a72a;
  --seg-bad: #d66a35;
  --seg-loss: #dc322f;
  --seg-none: color-mix(in srgb, var(--ink-4) 16%, transparent);

  --up: #cb4b16;
  --down: #268bd2;
  --cpu: #2aa198;
  --net: #268bd2;

  /* 文字用状态色：白底上对比度 ≥ 4.5:1（图形仍用上面的鲜亮版） */
  --ok-ink: #657700;
  --warn-ink: #86670a;
  --crit-ink: #c92f2c;
  --blue-ink: #1c6da3;
  --up-ink: #b0400f;
  --down-ink: #1c6da3;

  --radius-card: 20px;
  --radius-tile: 16px;
  --radius-chip: 999px;
  --radius-btn: 11px;

  --gap: 20px;
  --card-pad: 20px;
  --pad-x: 24px;

  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Source Han Sans SC", "Microsoft YaHei", sans-serif;
  --font-num: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

html[data-scheme="dark"] {
  /* 深色玻璃：更实的卡面 + 更亮的字，保证小字号可读 */
  --bg: #002b36;
  --veil-a: rgba(0, 43, 54, 0.86);
  --veil-b: rgba(0, 40, 51, 0.74);
  --wash-1: rgba(38, 139, 210, 0.22);
  --wash-2: rgba(42, 161, 152, 0.18);
  --wash-3: rgba(108, 113, 196, 0.16);
  --wash-4: rgba(181, 137, 0, 0.13);
  --card: rgba(9, 56, 68, 0.66);
  --card-2: rgba(9, 56, 68, 0.88);
  --card-line: rgba(147, 161, 161, 0.24);
  --card-hi: rgba(255, 255, 255, 0.07);
  --card-glow: rgba(255, 255, 255, 0.055);
  --card-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.72);
  --track: rgba(147, 161, 161, 0.22);
  --line: rgba(147, 161, 161, 0.26);
  --line-2: rgba(147, 161, 161, 0.14);
  --base-2: rgba(147, 161, 161, 0.18);
  --ink: #d2dedc;
  --ink-2: #c3d0ce;
  --ink-3: #adbebc;
  --ink-4: #90a5a8;

  --ok: #aec32a;
  --warn: #e2b31a;
  --crit: #f4685f;
  --blue: #58b2ee;
  --cyan: #44cdc0;
  --violet: #9a9fe8;
  --magenta: #ef6ba6;
  --orange: #ec7539;

  /* 深色下条带压低一档亮度，别在深底上泛荧光 */
  --seg-ok: #6f8c1f;
  --seg-slow: #c99a12;
  --seg-bad: #e0672b;
  --seg-loss: #f4685f;
  --seg-none: color-mix(in srgb, var(--ink-4) 22%, transparent);
  --up: #ec7539;
  --down: #58b2ee;
  --cpu: #44cdc0;
  --net: #58b2ee;

  --ok-ink: #aec32a;
  --warn-ink: #e2b31a;
  --crit-ink: #f77068;
  --blue-ink: #58b2ee;
  --up-ink: #f0824a;
  --down-ink: #58b2ee;
}

/* ---------------------------------------------------------------- 基础 */

* { box-sizing: border-box; }

/* 触屏：去掉双击缩放带来的 300ms 点击延迟 */
button, .schip, .card { touch-action: manipulation; }

[hidden] { display: none !important; }

html {
  color-scheme: light;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

html[data-scheme="dark"] { color-scheme: dark; }

@media (pointer: fine) {
  html { overscroll-behavior-y: none; }
  .card:hover {
    border-color: color-mix(in srgb, var(--blue) 26%, var(--card-line));
    box-shadow: 0 20px 40px -24px color-mix(in srgb, var(--ink) 60%, transparent), inset 0 1px 0 var(--card-hi);
    transform: translateY(-1px);
  }
  .card:active { transform: translateY(0); }
  .card:hover .more { color: var(--ink); border-color: var(--line); }
  .more:hover { background: color-mix(in srgb, var(--blue) 12%, transparent); }
  .more:hover svg { transform: translateY(1px); }
  .card[data-expanded="true"] .more:hover svg { transform: translateY(-1px); }
}

html { background: var(--bg); }
body {
  margin: 0;
  min-height: 100dvh;
  color: var(--ink-2);
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* 玻璃后面的 Solarized 色雾 */
body::before {
  content: "";
  position: fixed;
  inset: -15% -8%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(36% 30% at 10% 4%, var(--wash-1), transparent 68%),
    radial-gradient(32% 28% at 90% 2%, var(--wash-2), transparent 66%),
    radial-gradient(38% 32% at 82% 96%, var(--wash-3), transparent 70%),
    radial-gradient(30% 26% at 14% 98%, var(--wash-4), transparent 68%),
    linear-gradient(180deg, var(--veil-a) 0%, var(--veil-b) 100%);
  filter: blur(6px);
}

/* 纸纹：极淡的颗粒叠在色雾上，卡片是半透明的，所以从卡片里也透得出来 */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='.26'/%3E%3C/svg%3E");
  background-size: 200px 200px;
  opacity: 0.55;
  mix-blend-mode: multiply;
}

b, .vv, .nv, .lms, .clock, .tv, .pv, .fp, .dv, .mini-v {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

i { font-style: normal; }

button {
  font: inherit;
  color: inherit;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

a { color: var(--blue-ink); touch-action: manipulation; }

:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
  border-radius: 6px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 20;
  padding: 8px 14px;
  border-radius: var(--radius-btn);
  background: var(--card-2);
  border: 1px solid var(--card-line);
  color: var(--ink);
  text-decoration: none;
  transition: top 140ms ease;
}

.skip:focus-visible { top: 10px; }

.boot-msg { display: block; padding: 24px; color: var(--ink-2); }

#grid { scroll-margin-top: 8px; }
.card { scroll-margin-top: 8px; }

/* ---------------------------------------------------------------- 骨架 */

.deck {
  /* 整页滚动：滚轮/滚动条永远在最外层，鼠标停在哪都能滚 */
  min-height: 100vh;
  min-height: 100dvh;
  max-width: 2240px;
  margin: 0 auto;
  padding: 16px var(--pad-x) 12px;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* ---------------------------------------------------------------- 顶栏 */

.top {
  position: relative;
  /* 顶栏、汇总条、页脚都不许被纵向压缩：窗口矮时只压卡片墙并让它滚动 */
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 9px 14px;
  border-radius: var(--radius-tile);
  background: var(--card);
  border: 1px solid var(--card-line);
  box-shadow: var(--card-shadow), inset 0 1px 0 var(--card-hi);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
}

.brand { display: flex; align-items: center; gap: 9px; min-width: 0; flex: 0 1 auto; }

.mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: 0 0 auto;
  border-radius: 10px;
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn) 22%, transparent);
}

.wordmark { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.wordmark b {
  font-family: var(--font-num);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.10em;
  color: var(--ink);
}
.wordmark i { font-size: 12px; color: var(--ink-3); letter-spacing: 0.08em; }

.site {
  font-size: 12px;
  color: var(--ink-3);
  padding-left: 10px;
  border-left: 1px solid var(--line);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 20ch;
}

.live { display: flex; align-items: center; gap: 7px; margin-left: auto; flex-wrap: nowrap; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 11px;
  border-radius: var(--radius-chip);
  background: var(--card-2);
  border: 1px solid var(--line-2);
  font-family: var(--font-num);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  white-space: nowrap;
}
.pill b { font-weight: 600; }
.pill.up { color: var(--up-ink); }
.pill.down { color: var(--down-ink); }
button.pill {
  font: inherit;
  cursor: pointer;
  transition: background-color 140ms ease, border-color 140ms ease;
}
button.pill:hover { background: var(--card); }
button.pill:active { transform: translateY(1px); }
.pill.warn {
  color: var(--warn-ink);
  border-color: color-mix(in srgb, var(--warn) 34%, transparent);
  background: color-mix(in srgb, var(--warn) 10%, var(--card-2));
  font-family: var(--font-ui);
}

.dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 18%, transparent);
}
/* 圆点只表示“是否全员在线”，告警严重度交给旁边的黄色按钮，避免同一件事两套颜色 */
#onlinePill[data-level="warn"] .dot { background: var(--warn); box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 20%, transparent); }

.tools {
  /* 状态与操作分组：一条发丝线就够了，不用再加框 */
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  padding-left: 13px;
  margin-left: 3px;
  border-left: 1px solid var(--line-2);
}

.link { font-size: 11.5px; color: var(--ink-3); white-space: nowrap; min-width: 4.5em; text-align: right; }
.link[data-kind="live"] { color: var(--ok-ink); }
.link[data-kind="poll"] { color: var(--warn-ink); }
.link[data-kind="down"] { color: var(--crit-ink); }

.clock { font-size: 12.5px; color: var(--ink-2); letter-spacing: 0.02em; white-space: nowrap; }

.icon-btn {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-btn);
  border: 1px solid var(--line-2);
  background: var(--card-2);
  color: var(--ink-2);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
.icon-btn:hover { color: var(--ink); border-color: var(--line); }
.icon-btn .i-moon { display: none; }
html[data-scheme="dark"] .icon-btn .i-sun { display: none; }
html[data-scheme="dark"] .icon-btn .i-moon { display: block; }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 12px;
  border-radius: var(--radius-btn);
  border: 1px solid var(--line-2);
  background: var(--card-2);
  color: var(--ink-2);
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 120ms ease, border-color 120ms ease;
}
.btn:hover { color: var(--ink); border-color: var(--line); }
.btn:active { transform: translateY(0.5px); }
a.btn { text-decoration: none; }
a.btn[hidden] { display: none; }

/* 大屏：更松的间距与更大的数字 */
@media (min-width: 1600px) {
  :root { --gap: 22px; --card-pad: 22px; }
  .vv { font-size: 20px; }
  .nm { font-size: 17px; }
  .tv { font-size: 26px; }
}

/* ---------------------------------------------------------------- 汇总 */

.totals {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0;
  border-radius: var(--radius-tile);
  background: var(--card);
  border: 1px solid var(--card-line);
  box-shadow: var(--card-shadow), inset 0 1px 0 var(--card-hi);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  overflow: hidden;
}
.totals > .tile + .tile { border-left: 1px solid var(--line-2); }

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 13px 16px 12px;
  min-width: 0;
}

.tk { font-size: 10.5px; color: var(--ink-3); letter-spacing: 0.055em; }

.tv {
  display: flex;
  align-items: baseline;
  gap: 3px;
  font-size: 24px;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.tv .u { font-size: 10px; color: var(--ink-3); font-family: var(--font-ui); letter-spacing: 0.02em; }
.tv[data-tone="up"], .tv[data-tone="down"] { color: var(--ink); }
.tv[data-tone="ok"] { color: var(--ok-ink); }
.tv[data-tone="warn"] { color: var(--warn-ink); }
.tv[data-tone="crit"] { color: var(--crit-ink); }

/* 说明行沉到格子底部：有条和无条的格子底边才会齐 */
.ts {
  margin-top: auto;
  font-size: 10.5px;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tile .track { height: 4px; margin-top: 8px; }

.track {
  position: relative;
  height: 5px;
  margin-top: 7px;
  border-radius: 99px;
  background: var(--track);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-4) 22%, transparent);
  overflow: hidden;
  color: var(--ink-3);
}
.track i {
  display: block;
  height: 100%;
  width: calc(var(--p, 0) * 100%);
  border-radius: 99px;
  background: currentColor;
  transition: width 420ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.track[data-level="ok"] { color: var(--ok); }
.track[data-level="warn"] { color: var(--warn); }
.track[data-level="crit"] { color: var(--crit); }
.track[data-level="off"] { color: var(--ink-4); }
.track[data-level="off"] i { opacity: 0.3; }

/* ---------------------------------------------------------------- 卡片网格 */

.wall {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* 卡片按内容自然高度排，同一行等高；机器少时不再被拉高、内部空出大段留白 */
  grid-auto-rows: auto;
  align-content: start;
  gap: var(--gap);
  flex: 1 1 auto;
  /* 首屏放得下时填满高度；放不下时整页滚动，卡片本身不被压扁 */
  min-height: min-content;
}

/* 列数由 JS 按断点给出，属性选择器压过上面的默认 4 列。 */
.grid[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid[data-cols="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid[data-cols="1"] { grid-template-columns: minmax(0, 720px); justify-content: center; }

/* 页面滚动条：和卡片一个语言，细、暖、悬停才明显 */
html {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--ink-4) 45%, transparent) transparent;
}
html::-webkit-scrollbar { width: 11px; }
html::-webkit-scrollbar-track { background: transparent; }
html::-webkit-scrollbar-thumb {
  border: 3px solid transparent;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ink-4) 45%, transparent);
  background-clip: content-box;
}
html::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--ink-4) 68%, transparent);
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 11px;
  min-height: 0;
  padding: var(--card-pad);
  border-radius: var(--radius-card);
  background: var(--card);
  border: 1px solid var(--card-line);
  border-bottom-color: color-mix(in srgb, var(--card-line) 82%, var(--ink-3));
  box-shadow: var(--card-shadow), inset 0 1px 0 var(--card-hi);
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  transition:
    border-color 160ms ease,
    background-color 160ms ease,
    box-shadow 180ms ease,
    transform 140ms ease;
}
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(115% 62% at 16% -12%, var(--card-glow), transparent 62%);
}
.card:focus-within { border-color: color-mix(in srgb, var(--blue) 42%, var(--card-line)); }

.card:hover { border-color: color-mix(in srgb, var(--blue) 26%, var(--card-line)); }

.card[data-status="offline"] {
  /* 离线：压暗 + 红细线即可。斜纹会让数字显得脏，也会和条形图抢纹理 */
  background: color-mix(in srgb, var(--card) 92%, var(--base-2));
}
.card[data-status="offline"] .vv,
.card[data-status="offline"] .net-sub { color: var(--ink-3); }
.card[data-status="offline"] .nm { color: var(--ink-3); }

.card[data-alert="1"] { border-color: color-mix(in srgb, var(--warn) 40%, var(--card-line)); }
.card[data-alert="1"] .led { background: var(--warn); box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 18%, transparent); }
.card[data-alert="2"] { border-color: color-mix(in srgb, var(--crit) 44%, var(--card-line)); }
.card[data-alert="2"] .led { background: var(--crit); box-shadow: 0 0 0 3px color-mix(in srgb, var(--crit) 20%, transparent); }

.card[data-expanded="true"] {
  grid-column: 1 / -1;
  align-self: start;
  background: var(--card-2);
  display: grid;
  grid-template-columns: minmax(300px, 420px) minmax(0, 1fr);
  grid-template-rows: auto auto auto auto auto;
  grid-template-areas:
    "head detail"
    "vitals detail"
    "net detail"
    "pings detail"
    "fin detail";
  column-gap: 26px;
  row-gap: 10px;
  align-items: start;
}

.card[data-expanded="true"] > .card-head { grid-area: head; }
.card[data-expanded="true"] > .vitals { grid-area: vitals; }
.card[data-expanded="true"] > .net { grid-area: net; }
.card[data-expanded="true"] > .pings { grid-area: pings; }
.card[data-expanded="true"] > .fin { grid-area: fin; }

.card[data-expanded="true"] > .card-detail {
  grid-area: detail;
  margin: 0;
  padding: 2px 0 2px 24px;
  border-top: 0;
  border-left: 1px solid var(--line);
  align-self: stretch;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: 12px;
}

.card[data-expanded="true"] > .card-detail {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 12px;
}
.card[data-expanded="true"] > .card-detail > .dkv,
.card[data-expanded="true"] > .card-detail > .minis { width: 100%; }
.card[data-expanded="true"] > .card-detail > .dkv { flex: 0 0 auto; }
.card[data-expanded="true"] > .card-detail > .minis { flex: 1 1 auto; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: stretch; }
.card[data-expanded="true"] > .card-detail > .detail-note { flex: 0 0 auto; }
.card[data-expanded="true"] .mini { display: flex; flex-direction: column; }
.card[data-expanded="true"] .mini-plot { flex: 1 1 auto; height: auto; min-height: 38px; }
.card[data-expanded="true"] .dkv .dl[data-long="1"] { grid-column: span 2; }

/* 展开某台时：其它卡片保持展开前的高度，展开的卡片按内容长高，超出就滚动 */
#grid[data-open="1"] {
  grid-template-rows: none;
  grid-auto-rows: minmax(var(--card-min, 220px), auto);
  align-content: start;
}

/* 卡片头 */

.card-head { display: flex; align-items: flex-start; gap: 10px; min-width: 0; }

.led {
  width: 8px;
  height: 8px;
  margin-top: 6px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 16%, transparent);
}
.card[data-status="offline"] .led { background: var(--crit); box-shadow: 0 0 0 3px color-mix(in srgb, var(--crit) 16%, transparent); }

/* 状态条：只有异常卡才出现，正常卡保持干净；不占布局（绝对定位） */
.card::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  pointer-events: none;
  opacity: 0;

}
/* 离线卡一定显示红线；alert 的琥珀线只给"在线但异常"的卡 */
.card[data-status="offline"]::after { opacity: 1; background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--crit) 80%, transparent) 14%, color-mix(in srgb, var(--crit) 80%, transparent) 86%, transparent); }
.card[data-alert="1"]:not([data-status="offline"])::after { opacity: 1; background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--warn) 80%, transparent) 14%, color-mix(in srgb, var(--warn) 80%, transparent) 86%, transparent); }
.card[data-alert="2"]:not([data-status="offline"])::after { opacity: 1; background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--crit) 80%, transparent) 14%, color-mix(in srgb, var(--crit) 80%, transparent) 86%, transparent); }

/* 名字旁的离线/告警文字胶囊：颜色之外的第二重信号 */
.st-chip {
  flex: 0 0 auto;
  font-size: 10px;
  line-height: 1;
  padding: 3px 5px;
  border-radius: 5px;
  letter-spacing: 0.02em;
  border: 1px solid currentColor;
  color: var(--ink-3);
  background: transparent;
}
.st-chip[data-kind="offline"] { color: var(--crit-ink); }
.st-chip[data-kind="warn"] { color: var(--warn-ink); }
.st-chip[data-kind="crit"] { color: var(--crit-ink); }

/* 点「N 台需关注」→ 滚到第一台异常机器，短暂描边 */
.card.flash { outline: 2px solid var(--warn-ink); outline-offset: 2px; }

.card-id { min-width: 0; flex: 1 1 auto; }

.card-name { display: flex; align-items: center; gap: 6px; min-width: 0; }
.flag { font-size: 13px; line-height: 1; flex: 0 0 auto; }
.nm {
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.chip {
  /* 名字优先：空间不够时先压标签，而不是先切机器名 */
  flex: 0 3 auto;
  min-width: 0;
  font-size: 10.5px;
  line-height: 1;
  letter-spacing: 0.02em;
  padding: 3px 6px;
  border-radius: 5px;
  color: var(--ink-3);
  background: color-mix(in srgb, var(--ink-4) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--ink-4) 15%, transparent);
  white-space: nowrap;
  max-width: 14ch;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 第二行的小件永远是完整的一块，空间不够就整块换行，不拆字 */
.card-sub > * { white-space: nowrap; }
.sub-tag { display: none; color: var(--ink-3); }




.card-sub {
  margin-top: 3px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 8px;
  min-width: 0;
  font-size: 12px;
  color: var(--ink-3);
}
/* 系统名可省略；核心数、负载、在线时长始终完整，在线时长靠右 */
.card-sub > [data-f="subOS"] {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.card-sub > [data-f="subCore"],
.card-sub > [data-f="subLoad"] {
  flex: 0 0 auto;
  white-space: nowrap;
  /* 数值刻度和系统名分开：同一行里一眼分得清哪段是数据 */
  font-family: var(--font-num);
  font-size: 11px;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}
.card-sub > [data-f="upT"] { flex: 0 0 auto; white-space: nowrap; margin-left: auto; padding-left: 6px; }

.more {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  margin: -5px -5px 0 0;
  border-radius: 9px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  transition: color 120ms ease, background-color 120ms ease;
}
.more:hover { color: var(--ink); background: var(--line-2); }
.more svg { transition: transform 200ms ease; }
.card[data-expanded="true"] .more svg { transform: rotate(180deg); }
.card[data-expanded="true"] > .card-detail { animation: detail-in 220ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
@keyframes detail-in {
  from { opacity: 0; transform: translateY(-5px); }
  to { opacity: 1; transform: none; }
}

/* 三个核心指标 */

.vitals { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }

.vital { min-width: 0; }
.vl {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  font-size: 11px;
  color: var(--ink-3);
  letter-spacing: 0.05em;
}
.vl > span:first-child { flex: 0 0 auto; }
.vv {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: 1px;
  font-size: 19px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.2;
  white-space: nowrap;
}
.vv i { font-family: var(--font-ui); font-size: 10px; font-weight: 400; color: var(--ink-3); letter-spacing: 0.02em; margin-left: -1px; }
.vv b[data-level="warn"] { color: var(--warn-ink); }
.vv b[data-level="crit"] { color: var(--crit-ink); }

.vd {
  display: block;
  margin-top: 6px;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  font-style: normal;
  color: var(--ink-3);
}
.vital:hover .vd { color: var(--ink-2); }

/* 网络 */

.net { display: flex; flex-direction: column; gap: 6px; }

.net-sub { font-size: 12px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 详情：逐小时趋势 */

.minis-cap {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding-bottom: 2px;
  font-size: 10.5px;
  color: var(--ink-3);
}
.minis-cap > :last-child { color: var(--ink-4); }

/* 三网 */

.pings { display: flex; flex-direction: column; gap: 8px; }

.lane { display: flex; align-items: center; gap: 12px; min-width: 0; color: var(--ink-3); }
.lane-head { display: flex; align-items: baseline; gap: 5px; min-width: 0; flex: 0 0 auto; }
.lk { flex: 0 0 12px; font-size: 11px; color: var(--ink-2); text-align: center; }
.lms { flex: 0 0 auto; min-width: 22px; text-align: right; font-size: 13px; font-weight: 500; color: var(--ink); }
.lu { flex: 0 0 auto; margin-left: -1px; font-size: 10px; color: var(--ink-3); letter-spacing: 0.02em; }
.lloss {
  flex: 0 0 auto;
  min-width: 34px;
  border-radius: 999px;
  padding: 0 4px;
  font-family: var(--font-num);
  font-size: 10.5px;
  color: var(--ink-3);
  text-align: right;
  white-space: nowrap;
}

/* 24 格状态条：等高圆角小格，颜色只回答一个问题——这段时间这条线路好不好 */
.lbars {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  align-items: stretch;
  gap: 2px;
  height: 14px;
  min-width: 40px;
  /* 横向拖动留给「按住看某一刻」，上下滑仍然滚动页面 */
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
}
.lbars i {
  flex: 1 1 0;
  min-width: 2px;
  border-radius: 2.5px;
  background: var(--c, var(--seg-none));
  transition: background-color 300ms ease, opacity 200ms ease;
}

/* 延迟数字默认就是墨色；只有丢包真的严重时才染红，别让 1% 的小抖动抢戏 */
.lane[data-level="crit"] .lms { color: var(--crit-ink); }
.lane[data-level="off"] .lms { color: var(--ink-4); }
.lane[data-level="off"] .lu { display: none; }
.lane[data-empty="1"] .lbars i { background: var(--seg-none); }

/* 财务：一条发丝线把它和上面的信号区隔开，卡片读起来是三段 */

.fin {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 0;
  padding-top: 8px;
  border-top: 1px solid var(--line-2);
}

.fin-main { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.fp { font-size: 14.5px; font-weight: 500; color: var(--ink); white-space: nowrap; }
.fin-main .u { font-family: var(--font-ui); font-size: 10.5px; color: var(--ink-3); white-space: nowrap; }
.fdays { font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }
.fdays[data-level="warn"] { color: var(--warn-ink); }
.fdays[data-level="crit"] { color: var(--crit-ink); }

.fin-sub { font-size: 11px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------------------------------------------------------------- 展开详情 */

.card-detail {
  margin-top: 2px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 12px 22px;
  align-items: flex-start;
}

.dkv {
  flex: 1 1 560px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 7px 18px;
  min-width: 0;
}

.dl { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dk { font-size: 10.5px; color: var(--ink-3); }
.dv { font-size: 12px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.detail-note {
  flex: 1 1 100%;
  font-size: 11.5px;
  color: var(--ink-2);
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--line-2);
  white-space: normal;
}
/* 节点消息用告警色；写成 class 而不是 style 属性，严格 CSP 下也不会掉样式 */
.detail-note.warn {
  /* 用文字色而不是图形色：--warn 在灰底上只有 2.67:1 */
  color: var(--warn-ink);
  background: var(--card-2);
  border-left: 2px solid color-mix(in srgb, var(--warn-ink) 55%, transparent);
}

.minis { flex: 1 1 420px; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.mini { min-width: 0; }
.mini-h { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; font-size: 10.5px; color: var(--ink-3); }
.mini-v { font-size: 10.5px; color: var(--ink-2); }
.mini-plot { position: relative; height: 34px; margin-top: 3px; }
.mini-plot svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.mini-line { fill: none; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.mini-area { stroke: none; }

.schip[aria-current="true"] {
  border-color: color-mix(in srgb, var(--blue) 46%, var(--card-line));
  background: color-mix(in srgb, var(--blue) 10%, var(--card));
  color: var(--ink);
}

/* ---------------------------------------------------------------- 失败态 */

.fail {
  text-wrap: balance;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  border-radius: var(--radius-tile);
  background: color-mix(in srgb, var(--crit) 8%, var(--card-2));
  border: 1px solid color-mix(in srgb, var(--crit) 30%, transparent);
}
.fail p { margin: 0; font-size: 12.5px; color: var(--ink-2); }

/* 空状态不是错误：全部节点被隐藏 / 站点还没有节点时用中性的奶油底，
   在卡片墙里居中，别用告警红吓人 */
.fail[data-kind="empty"] {
  flex-direction: column;
  justify-content: center;
  gap: 7px;
  align-self: center;
  margin-block: auto;
  width: min(100%, 620px);
  padding: 30px 32px;
  text-align: center;
  background: color-mix(in srgb, var(--ink-4) 7%, var(--card-2));
  border-color: var(--line);
}
.fail[data-kind="empty"] p { font-size: 13px; color: var(--ink-3); }

/* ---------------------------------------------------------------- 页脚 */

.foot {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 11.5px;
  color: var(--ink-2);
  padding: 0 4px;
  min-height: 16px;
}
.fmid { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fright { flex: 0 0 auto; white-space: nowrap; display: flex; align-items: center; gap: 10px; }
.ficp {
  flex: 0 0 auto;
  color: var(--ink-3);
  text-decoration: none;
  border-bottom: 1px dotted color-mix(in srgb, var(--ink-4) 40%, transparent);
  padding: 1px 2px;
  border-radius: 4px;
}
a.ficp:hover { color: var(--ink-2); border-bottom-color: var(--ink-3); }
.flk {
  border: 0;
  background: none;
  font: inherit;
  color: var(--ink-3);
  padding: 1px 2px;
  border-radius: 5px;
  cursor: pointer;
  border-bottom: 1px dotted color-mix(in srgb, var(--ink-4) 45%, transparent);
  transition: color 140ms ease, border-color 140ms ease;
}
.flk:hover { color: var(--ink); border-bottom-color: color-mix(in srgb, var(--ink) 55%, transparent); }
.flk[data-on="1"] { color: var(--blue-ink); border-bottom-color: color-mix(in srgb, var(--blue) 55%, transparent); }
.flk:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* ---------------------------------------------------------------- 入场 */

@keyframes rise-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

@keyframes draw-in {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}

.deck[data-state="boot"] .top,
.deck[data-state="boot"] .totals,
.deck[data-state="boot"] .grid { opacity: 0; }

.deck[data-state="ready"] .top { animation: rise-in 420ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
.top::after {
  content: "";
  position: absolute;
  left: 18px;
  right: 18px;
  bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--line) 14%, var(--line) 86%, transparent);
  pointer-events: none;
}
.deck[data-state="ready"] .totals { animation: rise-in 420ms cubic-bezier(0.22, 0.61, 0.36, 1) 60ms both; }
.deck[data-state="ready"] .wall { animation: rise-in 460ms cubic-bezier(0.22, 0.61, 0.36, 1) 40ms both; }

/* 数据到位的那个瞬间：三条状态条从左往右刷出来，三条线依次 70ms */
.grid[data-grow] .lbars { animation: lbars-grow 560ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
.grid[data-grow] .lane:nth-child(2) .lbars { animation-delay: 70ms; }
.grid[data-grow] .lane:nth-child(3) .lbars { animation-delay: 140ms; }
@keyframes lbars-grow {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}


@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.001ms !important;
  }
  .deck[data-state="boot"] .top,
  .deck[data-state="boot"] .totals,
  .deck[data-state="boot"] .grid { opacity: 1; }
}

/* ---------------------------------------------------------------- 窄屏 */

@media (max-width: 1599px) {
  .deck { padding: 12px 14px 8px; --gap: 11px; --pad-x: 14px; }
  .tv { font-size: 19.5px; }
  .vv { font-size: 16px; }
}

@media (max-width: 1439px) {
  .card-name .chip.t2 { display: none; }
}

/* 中等宽度：卡片变窄，标签从名字后面挪到第二行，机器名不再被挤成省略号 */
@media (min-width: 768px) and (max-width: 1599px) {
  .card-name .chip.tag { display: none; }
  .card-sub .sub-tag { display: inline; }
}

/* 1280–1339 是四列里最窄的一档：单栏只有 78px，
   11px 的「4.2 / 8.0 GB」会多出 6px 被省略号截断，收 1px 刚好放得下 */
@media (min-width: 1280px) and (max-width: 1339px) {
  .vd { font-size: 10px; }
}

/* 1024–1599：始终一行 4 张，卡片收紧一档（信号条变矮、留白变小），8 台尽量一屏放下 */
@media (min-width: 1024px) and (max-width: 1599px) {
  .deck { --card-pad: 13px; }
  .card { gap: 8px; }
  .vitals { gap: 9px; }
  .vv { font-size: 15px; }
  .pings { gap: 5px; }
  .lbars { height: 12px; }
  .fin { padding-top: 6px; }
}

/* 宽但矮的窗口（如 1600×900、1680×1050）同样收紧，两行卡片放得进一屏 */
@media (min-width: 1600px) and (max-height: 1060px) {
  .deck { --card-pad: 15px; }
  .card { gap: 8px; }
  .pings { gap: 5px; }
  .lbars { height: 13px; }
  .fin { padding-top: 6px; }
}

/* 1024–1279 是四列里最窄的一档：数值和「已用 / 总量」再收一号 */
@media (min-width: 1024px) and (max-width: 1279px) {
  .deck { --card-pad: 11px; }
  .vitals { gap: 7px; }
  .vv { font-size: 14px; }
  .vd { font-size: 9.5px; letter-spacing: -0.02em; }
  .vl { font-size: 10px; }
  .nm { font-size: 14px; letter-spacing: 0; }
  .card-name { gap: 4px; }
  .card-head { gap: 6px; }
  .pin, .more { width: 26px; height: 26px; margin: -4px -4px 0 0; }
  .card-sub { font-size: 10.5px; gap: 0 6px; }
  /* 在线时长跟在负载后面，不再单独甩到第三行 */
  .card-sub > [data-f="upT"] { margin-left: 0; padding-left: 0; }
  /* 三栏各只有 60 多像素：标签放到数字上方 */
  .vl { flex-direction: column; align-items: flex-start; gap: 0; }
  .vv { margin-left: 0; }
  .net-sub { font-size: 11px; }
}

@media (max-width: 1099px) {
  .site, .link { display: none; }
}

@media (max-width: 1023px) {
  /* 汇总条改成 3 列：仍然是同一块账本，只换成发丝线分格 */
  .totals { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; }
  .totals > .tile:nth-child(n + 4) { border-top: 1px solid var(--line-2); }
  .totals > .tile:nth-child(3n + 1) { border-left: 0; }
}

@media (max-width: 1023px) {
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: minmax(186px, auto); }
  /* 平板宽度：按钮只留图标，品牌与状态不打架 */
  #sortBtn { padding: 0 9px; gap: 0; }
  #sortBtn #sortLabel, #sortBtn svg:last-child { display: none; }
  #refreshBtn { padding: 0 9px; gap: 0; }
  #refreshBtn .btn-t { display: none; }
  /* 后台入口保留文字：只剩锁图标时认不出来 */
  #adminBtn { padding: 0 10px; gap: 4px; }
  .fleft { display: none; }
}

@media (max-width: 900px) {
  .card[data-expanded="true"] { display: flex; flex-direction: column; align-items: stretch; }
  .card[data-expanded="true"] > .card-detail {
    border-left: 0;
    border-top: 1px solid var(--line);
    padding: 12px 0 0;
  }
  .card[data-expanded="true"] .minis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
  /* 手机上让整页滚动（地址栏可收起），桌面端整屏不滚、只有卡片墙滚动 */
  .deck { padding: 10px 12px 8px; --gap: 9px; --pad-x: 12px; }
  .top { padding: 7px 9px; gap: 6px; border-radius: 13px; }
  .brand { gap: 7px; }
  .mark { width: 28px; height: 28px; border-radius: 9px; }
  .mark svg { width: 19px; height: 19px; }
  .wordmark b { font-size: 12px; letter-spacing: 0.05em; }
  .wordmark i { display: none; }
  .clock { display: none; }
  /* 实时上下行在汇总条里已经有了，顶栏让位给品牌 */
  .pill.up, .pill.down { display: none; }
  .live { gap: 5px; }
  .pill { height: 26px; padding: 0 8px; font-size: 11px; gap: 5px; }
  .totals { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .tile { padding: 10px 11px 10px; }
  .tk { font-size: 10px; }
  .tv { font-size: 16px; }
  .ts { font-size: 10px; }
  .tile .track { margin-top: 6px; }
  .grid { grid-template-columns: 1fr; grid-auto-rows: auto; gap: 8px; }
  .card { gap: 6px; padding: 10px 12px 9px; border-radius: 15px; }
  /* 手机上系统名和核数让位；负载和在线时长仍然一行可见，不藏进详情 */
  .card-sub { margin-top: 2px; font-size: 11px; gap: 0 6px; }
  .card-sub > [data-f="subOS"], .card-sub > [data-f="subCore"] { display: none; }
  .card-sub > [data-f="subLoad"], .card-sub > [data-f="upT"] { font-size: 10.5px; }
  /* 在线时长紧跟负载，不再被推到中间偏右 */
  .card-sub > [data-f="upT"] { margin-left: 0; padding-left: 0; }
  .nm { font-size: 14px; }
  /* 三栏各只有一百来像素：标签放到数字上方，数字和下一栏的标签不再贴在一起 */
  .vitals { gap: 14px; }
  .vl { flex-direction: column; align-items: flex-start; gap: 1px; }
  .vv { margin-left: 0; font-size: 16px; }
  /* 品牌字让位后，左上角显示站点名，顶栏不再空一大块 */
  .site { display: block; padding-left: 0; border-left: 0; font-size: 13px; font-weight: 600; color: var(--ink-2); max-width: 11ch; }
  /* 有「N 台需关注」时顶栏放不下站点名：让给告警，别挤成「D…」 */
  .top:has(#headAlertWrap:not([hidden])) .site { display: none; }
  .pings { gap: 6px; }
  .lane { gap: 8px; }
  .lbars { height: 13px; }
  .vital .track { margin-top: 5px; }
  .vd { margin-top: 4px; }
  /* 详情里的趋势图在窄屏必须整行，两列会把「现/峰」挤到换行 */
  .card[data-expanded="true"] > .card-detail > .minis { grid-template-columns: 1fr; gap: 8px; }
  .card[data-expanded="true"] .mini-plot { min-height: 44px; }
  .mini-h { font-size: 11px; }
  .fin { gap: 2px; }
  .fin-sub { font-size: 10px; }
  .foot { font-size: 10px; }
  .fleft { display: none; }
}

@media (max-width: 560px) {
  /* 极窄屏：排序让位，卡片本来就按权重一列排下来 */
  #sortBtn { display: none; }
}

@media (max-width: 420px) {
  .vitals { gap: 12px; }
  .tv { font-size: 15px; }
}

/* ---------------------------------------------------------------- 矮屏 */





/* 极矮窗口（半屏窗口）：进一步压缩，卡片内容仍然完整不重叠 */
@media (max-height: 900px) {
}

@media (min-width: 768px) and (max-height: 760px) {
  .deck { --gap: 14px; padding: 12px 18px 6px; --pad-x: 18px; }
  .card { gap: 10px; }
  .tile { padding: 11px 14px 11px; }
  .foot { min-height: 14px; }
}





/* 手机首屏总览条：8 台一屏可见，点击跳到对应卡片 */
.strip { display: none; }

@media (max-width: 767px) {
  .strip {
    /* 单行横向滚动：8 台只占一行，首屏把高度让给卡片 */
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    margin-top: 8px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* 两端渐隐，暗示还能滑 */
    mask-image: linear-gradient(90deg, transparent 0, #000 12px, #000 calc(100% - 22px), transparent 100%);
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 12px, #000 calc(100% - 22px), transparent 100%);
    padding: 1px 2px 2px;
  }
  .strip::-webkit-scrollbar { display: none; }
  .schip { scroll-snap-align: start; flex: 0 0 auto; }
  .schip {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    padding: 4px 7px;
    border-radius: 999px;
    background: var(--card);
    border: 1px solid var(--card-line);
    box-shadow: var(--card-shadow);
    -webkit-backdrop-filter: blur(14px) saturate(150%);
    backdrop-filter: blur(14px) saturate(150%);
    font-size: 10px;
    color: var(--ink-2);
    text-decoration: none;
  }
  /* 卡片头的圆点带 margin-top 去对齐机器名，这里要清掉，否则圆点比文字低半行 */
  .schip .led { width: 6px; height: 6px; margin: 0; flex: 0 0 auto; background: var(--ok); border-radius: 999px; box-shadow: none; }
  /* 名字和数字两种字体：统一行高，三者在胶囊里按中线对齐 */
  .schip .snm, .schip b { line-height: 1.2; }
  .schip[data-status="offline"] .led { background: var(--crit); }
  .schip .snm {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .schip b {
    font-family: var(--font-num);
    font-size: 10px;
    font-weight: 500;
    color: var(--ink);
    flex: 0 0 auto;
  }
  .schip[data-status="offline"] { color: var(--ink-3); }
}

/* ---------------------------------------------------------------- 交互层 */

/* 三网：三行的条对齐成同一组 24 格，才能横着对比同一时刻 */
.lane {
  display: grid;
  grid-template-columns: 110px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
}
.lane-head { min-width: 0; overflow: hidden; flex: none; }
.lbars i.cur { outline: 1px solid color-mix(in srgb, var(--ink) 35%, transparent); outline-offset: 1px; }
.pings { position: relative; }
.pings[data-x] .lbars i:not(.cur) { opacity: 0.2; }
.xhair {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  display: none;
  background: color-mix(in srgb, var(--ink-3) 60%, transparent);
  pointer-events: none;
}
.pings[data-x] .xhair { display: block; }

/* 悬浮提示 */
.tip {
  position: fixed;
  z-index: 90;
  top: 0;
  left: 0;
  max-width: 260px;
  padding: 7px 10px 8px;
  border-radius: 11px;
  background: var(--card-2);
  border: 1px solid var(--card-line);
  box-shadow: 0 18px 34px -22px rgba(88, 110, 117, 0.75);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--ink-2);
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 110ms ease, visibility 0s linear 130ms;
}
html[data-scheme="dark"] .tip { background: #063542; border-color: rgba(147, 161, 161, 0.34); box-shadow: 0 18px 34px -20px rgba(0, 0, 0, 0.8); }
.tip[data-show="1"] { opacity: 1; visibility: visible; transition: opacity 110ms ease, visibility 0s; }
.tip-h {
  display: block;
  margin-bottom: 2px;
  font-family: var(--font-num);
  font-size: 10.5px;
  letter-spacing: 0.02em;
  color: var(--ink-3);
}
.tip-r { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
.tip-k { color: var(--ink-3); }
.tip-v { font-family: var(--font-num); font-weight: 500; color: var(--ink); white-space: nowrap; }

/* 卡片悬停：抬起 1px + 阴影加深，箭头跟着变亮 */
/* 悬停抬升只在真有指针的设备上生效：触屏点完不会一直"浮"着 */
@media (hover: hover) {
  .card { transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; }
  .card[data-expanded="true"]:hover { transform: none; }
  .card:hover .more { color: var(--ink); border-color: color-mix(in srgb, var(--blue) 34%, var(--card-line)); }
}

/* 没有 hover 的设备（大平板、横屏手机）：置顶星必须可见，否则是个看不见的按钮 */
/* 详情底部的「收起明细」：桌面上有箭头就够了，只在触屏上出现 */
.detail-close { display: none; }

@media (hover: none) {
  .card .pin { opacity: 1; }
  .detail-close { display: flex; justify-content: center; width: 100%; height: 36px; margin-top: 4px; }
  /* 触屏上展开只靠这个箭头：做成看得出是按钮的样子，命中区域放大到 36px */
  .more {
    width: 36px;
    height: 36px;
    margin: -8px -8px 0 0;
    border-color: var(--line-2);
    background: color-mix(in srgb, var(--card-2) 70%, transparent);
    color: var(--ink-2);
  }
  .pin { width: 36px; height: 36px; margin: -8px 0 0 0; }
}

/* 打印：只留卡片本身 */
@media print {
  .top, .totop, .toast, .tip, .strip, .tools, .foot .flk { display: none !important; }
  html, body { background: #fff; color: #000; }
  body::before, body::after { display: none; }
  .deck { max-width: none; padding: 0; }
  .grid { display: block; }
  .card { break-inside: avoid; box-shadow: none; backdrop-filter: none; border: 1px solid #999; margin-bottom: 10px; }
}

/* Windows 高对比度：背景色会被系统抹掉，靠背景画的状态得换成前景色 */
@media (forced-colors: active) {
  .led, .schip .led, .lbars i, .track i { background: CanvasText; }
  .card { border: 1px solid CanvasText; }
  .card[data-status="offline"] { border-style: dashed; }
  .card[data-alert="1"] .led { outline: 2px solid CanvasText; }
}

/* 进度条平滑过渡，刷新时是滑过去而不是跳过去 */
/* 进度条走的是 width，不是 transform：这条必须包含 width，否则条会直接跳 */
.track i { transition: width 480ms cubic-bezier(0.22, 0.61, 0.36, 1), background-color 200ms ease; }

/* 在线圆点：缓慢呼吸外圈 */
.pill .dot { position: relative; }
.pill .dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1px solid currentColor;
  opacity: 0;
  animation: dot-ping 2.6s ease-out infinite;
}
@keyframes dot-ping {
  0% { opacity: 0.5; transform: scale(0.7); }
  70% { opacity: 0; transform: scale(1.5); }
  100% { opacity: 0; transform: scale(1.5); }
}

/* 刷新中 */
.btn.busy svg { animation: spin 900ms linear infinite; }
.btn.busy { color: var(--ink-3); }
@keyframes spin { to { transform: rotate(360deg); } }

/* 回到顶部 */
.totop {
  position: fixed;
  right: 22px;
  bottom: 52px;
  z-index: 40;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--card-line);
  background: var(--card-2);
  color: var(--ink-2);
  box-shadow: 0 14px 28px -18px rgba(88, 110, 117, 0.7);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  cursor: pointer;
  transition: color 140ms ease, border-color 140ms ease, background-color 140ms ease;
  animation: pop-in 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes pop-in { from { opacity: 0; transform: translateY(6px) scale(0.94); } to { opacity: 1; transform: none; } }
.totop:hover { color: var(--ink); border-color: color-mix(in srgb, var(--blue) 34%, var(--card-line)); }
.totop:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* 页脚「几秒前」 */
.foot .ago { color: var(--ink-2); }

@media (prefers-reduced-motion: reduce) {
  .pill .dot::after { animation: none; }
  .card:hover { transform: none; }
}

/* 宽屏：左右留白阶梯放大，卡片不贴着窗口边 */
@media (max-width: 430px) {
  /* 极窄屏：刷新只留图标；后台入口留文字、去掉锁图标；品牌只留图标，不再被挤成「KO」 */
  #refreshBtn { padding: 0 10px; gap: 0; }
  #refreshBtn .btn-t { display: none; }
  #adminBtn { padding: 0 9px; gap: 0; }
  #adminBtn svg { display: none; }
  .wordmark { display: none; }
}

/* 320–359（老款小屏）：品牌图标也让位，按钮间距再收，「登录」不被挤出顶栏 */
@media (max-width: 359px) {
  .brand { display: none; }
  .tools { gap: 4px; padding-left: 6px; }
  .live { gap: 4px; }
  .live .pill { padding-left: 7px; padding-right: 7px; }
}

@media (min-width: 1200px) { .deck { --pad-x: 34px; } }
@media (min-width: 1600px) { .deck { --pad-x: 44px; } }

/* ---------------------------------------------------------------- 置顶 / 排序 / 轻提示 */

.pin {
  /* 和右侧的收起键同一套盒子：30×30、同样的 -5px 上移，
     两个图标的中心因此落在同一条横线上（星与箭头不再一高一低） */
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  margin: -5px 0 0;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 9px;
  border: 1px solid transparent;
  background: none;
  color: var(--ink-4);
  cursor: pointer;
  opacity: 0;
  transition: opacity 140ms ease, color 140ms ease, background-color 140ms ease;
}
.pin svg { fill: none; stroke: currentColor; }
.card:hover .pin,
.card:focus-within .pin,
.pin[aria-pressed="true"] { opacity: 1; }
.pin:hover { color: var(--warn-ink); background: color-mix(in srgb, var(--warn) 12%, transparent); }
.pin[aria-pressed="true"] { color: var(--warn); }
.pin[aria-pressed="true"] svg { fill: color-mix(in srgb, var(--warn) 22%, transparent); }
.pin:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

.btn.sort { gap: 4px; padding-right: 8px; }
.btn.sort[data-on="1"] { color: var(--ink); border-color: color-mix(in srgb, var(--blue) 34%, var(--card-line)); }

.toast {
  position: fixed;
  left: 50%;
  bottom: 42px;
  z-index: 95;
  margin: 0;
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--card-line);
  background: var(--card-2);
  box-shadow: 0 16px 32px -22px rgba(88, 110, 117, 0.8);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  font-size: 12px;
  color: var(--ink-2);
  max-width: min(92vw, 560px);
  white-space: normal;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, 6px);
  transition: opacity 160ms ease, transform 160ms ease;
}
.toast[data-show="1"] { opacity: 1; transform: translate(-50%, 0); }
html[data-scheme="dark"] .toast { background: #063542; }

/* 详情里的三网统计 */
.pstats { display: flex; flex-direction: column; gap: 2px; margin-top: 10px; }
.pstats-cap { font-size: 10.5px; color: var(--ink-3); }
.pst { display: flex; align-items: baseline; gap: 10px; font-size: 11.5px; }
.pst-k { flex: 0 0 14px; color: var(--ink-2); text-align: center; }
.pst-v { font-family: var(--font-num); color: var(--ink); }
.pst-n { color: var(--ink-3); }

@media (max-width: 767px) {
  .pin { opacity: 1; }
  .toast { bottom: 18px; }
}

/* 丢包统一用文字颜色表达轻重，不再有的带框有的不带 */
.lloss[data-lv="crit"] { color: var(--crit-ink); font-weight: 600; }
.lloss[data-lv="warn"] { color: var(--warn-ink); }


.lbars i[data-none="1"] { background: var(--seg-none); }
