/* ============================================================
   TrueFRP · 布局
   顶栏 / 画布 / 侧滑抽屉 / 高级抽屉 / 移动端
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  background: var(--ts-paper);
  color: var(--ts-ink);
  font: var(--nm-fs-md) / 1.55 var(--nm-font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overscroll-behavior: none;
}

.nm-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  padding: var(--nm-s2) var(--nm-s3);
  background: var(--ts-ink);
  color: var(--ts-paper);
  border-radius: 0 0 var(--nm-r-md) 0;
}
.nm-skip:focus { left: 0; }

.nm-noscript { padding: var(--nm-s6); }

.nm-app {
  display: grid;
  grid-template-rows: var(--nm-topbar-h) minmax(0, 1fr) var(--nm-footer-h);
  height: 100%;
  min-height: 0;
}

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

.nm-topbar {
  display: flex;
  align-items: center;
  gap: var(--nm-s4);
  padding: 0 var(--nm-s4);
  border-bottom: 1px solid var(--nm-line);
  background: var(--ts-paper);
  position: relative;
  z-index: 20;
}

.nm-brand {
  display: flex;
  align-items: center;
  gap: var(--nm-s2);
  text-decoration: none;
  color: var(--ts-ink);
  flex: none;
}
.nm-brand__logo {
  height: 26px;
  width: auto;
  display: block;
}
.nm-brand__name {
  font-size: var(--nm-fs-lg);
  font-weight: 600;
  letter-spacing: .01em;
}
.nm-brand__cn {
  font-size: var(--nm-fs-sm);
  color: var(--nm-ink-40);
  padding-left: var(--nm-s2);
  border-left: 1px solid var(--nm-line);
}

.nm-nav {
  display: flex;
  align-items: center;
  gap: var(--nm-s1);
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.nm-nav::-webkit-scrollbar { display: none; }

.nm-nav__item {
  flex: none;
  padding: 6px var(--nm-s3);
  border-radius: var(--nm-r-md);
  color: var(--nm-ink-56);
  text-decoration: none;
  font-size: var(--nm-fs-md);
  white-space: nowrap;
  transition: background var(--nm-dur-fast) var(--nm-ease), color var(--nm-dur-fast) var(--nm-ease);
}
.nm-nav__item:hover { background: var(--nm-ink-04); color: var(--ts-ink); }
.nm-nav__item[aria-current="page"] {
  background: var(--nm-ink-08);
  color: var(--ts-ink);
  font-weight: 600;
}

.nm-topbar__right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--nm-s3);
  flex: none;
}

/* 中继带宽水位条（顶栏常驻） */
.nm-watermark {
  display: flex;
  align-items: center;
  gap: var(--nm-s2);
  padding: 4px var(--nm-s3) 4px var(--nm-s2);
  border: 1px solid var(--nm-line);
  border-radius: 999px;
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-56);
}
.nm-watermark__label { letter-spacing: .04em; }
.nm-watermark__track {
  display: block;
  width: 72px;
  height: 5px;
  border-radius: 999px;
  background: var(--nm-ink-08);
  overflow: hidden;
}
.nm-watermark__fill {
  display: block;
  height: 100%;
  background: var(--nm-online);
  border-radius: 999px;
  transition: width var(--nm-dur) var(--nm-ease), background var(--nm-dur) var(--nm-ease);
}
.nm-watermark[data-level="warn"] .nm-watermark__fill { background: var(--nm-warn); }
.nm-watermark[data-level="danger"] .nm-watermark__fill { background: var(--nm-danger); }
.nm-watermark__value {
  font-family: var(--nm-font-mono);
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-70);
  min-width: 58px;
  text-align: right;
}

.nm-mode {
  font-size: var(--nm-fs-xs);
  color: var(--nm-warn);
  border: 1px solid var(--nm-warn);
  background: var(--nm-warn-bg);
  border-radius: 999px;
  padding: 2px var(--nm-s2);
  white-space: nowrap;
}

/* ---------------- 主区 ---------------- */

.nm-main {
  min-height: 0;
  overflow: hidden;
  position: relative;
  outline: none;
}
.nm-view {
  height: 100%;
  min-height: 0;
  overflow: auto;
  padding: var(--nm-s5) var(--nm-s6);
}
.nm-view--flush { padding: 0; overflow: hidden; }

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

.nm-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--nm-s4);
  padding: 0 var(--nm-s4);
  border-top: 1px solid var(--nm-line);
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-40);
  background: var(--nm-surface-2);
}
.nm-footer__brand { color: var(--nm-ink-56); }

/* ---------------- 侧滑抽屉（双击设备详情） ---------------- */

.nm-drawer {
  position: fixed;
  top: var(--nm-topbar-h);
  right: 0;
  bottom: var(--nm-footer-h);
  width: var(--nm-drawer-w);
  max-width: 92vw;
  background: var(--ts-paper);
  border-left: 1px solid var(--nm-line);
  z-index: var(--nm-z-drawer);
  display: flex;
  flex-direction: column;
  min-height: 0;
  transform: translateX(0);
  animation: nm-drawer-in var(--nm-dur) var(--nm-ease);
}
.nm-drawer[hidden] { display: none; }

@keyframes nm-drawer-in {
  from { transform: translateX(12px); opacity: 0; }
  to   { transform: translateX(0);    opacity: 1; }
}

.nm-drawer__head {
  display: flex;
  align-items: flex-start;
  gap: var(--nm-s3);
  padding: var(--nm-s4);
  border-bottom: 1px solid var(--nm-line);
}
.nm-drawer__icon {
  flex: none;
  width: 36px;
  height: 36px;
  border: 1px solid var(--nm-line);
  border-radius: var(--nm-r-lg);
  display: grid;
  place-items: center;
}
.nm-drawer__icon svg { width: 20px; height: 20px; }
.nm-drawer__title { min-width: 0; flex: 1; }
.nm-drawer__title h2 {
  margin: 0;
  font-size: var(--nm-fs-lg);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nm-drawer__sub {
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-40);
  font-family: var(--nm-font-mono);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nm-drawer__body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: var(--nm-s4);
}
.nm-drawer__foot {
  border-top: 1px solid var(--nm-line);
  padding: var(--nm-s3) var(--nm-s4);
  display: flex;
  gap: var(--nm-s2);
  flex-wrap: wrap;
  background: var(--nm-surface-2);
}

/* ---------------- 拓扑视图 ---------------- */

.nm-topo {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  height: 100%;
  min-height: 0;
}

.nm-topo__toolbar {
  display: flex;
  align-items: center;
  gap: var(--nm-s2);
  flex-wrap: wrap;
  padding: var(--nm-s3) var(--nm-s4);
  border-bottom: 1px solid var(--nm-line);
  background: var(--ts-paper);
}
.nm-topo__toolbar .nm-toolbar__spacer { flex: 1; }

.nm-topo__stage {
  position: relative;
  min-height: 0;
  overflow: hidden;
  background: var(--nm-surface-2);
}

.nm-topo__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  cursor: grab;
  outline: none;
}
.nm-topo__canvas:focus-visible { outline: 2px solid var(--nm-info); outline-offset: -2px; }
.nm-topo__canvas[data-cursor="move"] { cursor: move; }
.nm-topo__canvas[data-cursor="point"] { cursor: pointer; }
.nm-topo__canvas[data-cursor="cut"] { cursor: crosshair; }
/* 群组区域是可拖动的"窗口"：够到四边/四角时要给出对应的缩放光标，
   否则用户只会当它是一块背景色，不知道能拖能缩 */
.nm-topo__canvas[data-cursor="ew"] { cursor: ew-resize; }
.nm-topo__canvas[data-cursor="ns"] { cursor: ns-resize; }
.nm-topo__canvas[data-cursor="nwse"] { cursor: nwse-resize; }
.nm-topo__canvas[data-cursor="nesw"] { cursor: nesw-resize; }
.nm-topo__canvas[data-mode="link"] { cursor: cell; }

/* 画布左上角操作提示：右键菜单是"看不见的手势"，没有提示等于没有这个功能 */
.nm-topo__hint {
  position: absolute;
  left: var(--nm-s4);
  top: var(--nm-s4);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  background: rgba(255, 255, 255, .92);
  border: 1px solid var(--nm-line);
  border-radius: var(--nm-r-md);
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-56);
}
.nm-topo__hint[hidden] { display: none; }
.nm-topo__hint-close {
  border: 0;
  background: transparent;
  padding: 0 2px;
  cursor: pointer;
  color: inherit;
  line-height: 1;
}
.nm-topo__hint-close:hover { color: var(--ts-ink); }

/* 图例（右下角，默认折叠）
   实测展开态固定占 213×181，正好压住右下角的节点 —— 所以默认只留一个「图例」小按钮，
   要看才展开，展开状态记在 localStorage 里。 */
.nm-legendwrap {
  position: absolute;
  right: var(--nm-s4);
  bottom: var(--nm-s4);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--nm-s2);
  pointer-events: auto;
}
.nm-legend__toggle {
  font: inherit;
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-70);
  background: rgba(255, 255, 255, .92);
  border: 1px solid var(--nm-line);
  border-radius: 999px;
  padding: 3px var(--nm-s3);
  cursor: pointer;
}
.nm-legend__toggle:hover { color: var(--ts-ink); border-color: var(--nm-line-strong); }
.nm-legend {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: var(--nm-s3);
  background: rgba(255, 255, 255, .92);
  border: 1px solid var(--nm-line);
  border-radius: var(--nm-r-lg);
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-70);
  max-width: 220px;
}
.nm-legend[hidden] { display: none; }   /* display:flex 会盖掉 [hidden] 的 display:none */
.nm-legend__row { display: flex; align-items: center; gap: var(--nm-s2); }
.nm-legend__line { flex: none; width: 26px; height: 0; border-top-width: 2px; border-top-style: solid; }
.nm-legend__title { color: var(--nm-ink-40); letter-spacing: .06em; }

/* 坐标/状态浮层（左下角） */
.nm-statusbar {
  position: absolute;
  left: var(--nm-s4);
  bottom: var(--nm-s4);
  display: flex;
  gap: var(--nm-s2);
  align-items: center;
  flex-wrap: wrap;
  max-width: calc(100% - 140px);
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-56);
  pointer-events: none;
}
.nm-statusbar > * {
  background: rgba(255, 255, 255, .92);
  border: 1px solid var(--nm-line);
  border-radius: 999px;
  padding: 2px var(--nm-s2);
  font-family: var(--nm-font-mono);
}
/* 重点：异常项上色，次要项降级（六个同权重数字等于没有重点） */
.nm-statusbar__item--muted { color: var(--nm-ink-40); }
.nm-statusbar__item--warn { color: var(--nm-warn); border-color: var(--nm-warn); font-weight: 600; }
.nm-statusbar__item--alert { color: var(--nm-danger); border-color: var(--nm-danger); font-weight: 600; }

/* 屏幕阅读器平行结构（04 文档第 9 节） */
.nm-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* 高级抽屉（按需展开，不占主界面） */
.nm-adv {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 340px;
  max-width: 90vw;
  background: var(--ts-paper);
  border-left: 1px solid var(--nm-line);
  overflow: auto;
  z-index: 10;
  animation: nm-adv-in var(--nm-dur) var(--nm-ease);
}
.nm-adv[hidden] { display: none; }
@keyframes nm-adv-in {
  from { transform: translateX(14px); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}
.nm-adv__section { padding: var(--nm-s4); border-bottom: 1px solid var(--nm-line); }
.nm-adv__section:last-child { border-bottom: 0; }
.nm-adv__title {
  margin: 0 0 var(--nm-s3);
  font-size: var(--nm-fs-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--nm-ink-40);
  font-weight: 600;
}

/* 只读概览水印（移动端拓扑降级） */
.nm-topo__stage[data-readonly="true"]::after {
  content: "只读概览";
  position: absolute;
  top: var(--nm-s3);
  left: var(--nm-s4);
  font-size: var(--nm-fs-xs);
  color: var(--nm-ink-40);
  border: 1px dashed var(--nm-line-strong);
  border-radius: 999px;
  padding: 2px var(--nm-s3);
  pointer-events: none;
}

/* 移动端分组卡片列表 */
.nm-mobilelist { display: none; padding: var(--nm-s4); }
.nm-mobilelist__group { margin-bottom: var(--nm-s5); }

/* ---------------- 移动端适配（04 文档第 8 节） ---------------- */

@media (max-width: 860px) {
  :root { --nm-topbar-h: 52px; }

  .nm-view { padding: var(--nm-s4) var(--nm-s3); }

  .nm-nav {
    position: absolute;
    top: var(--nm-topbar-h);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--ts-paper);
    border-bottom: 1px solid var(--nm-line);
    padding: var(--nm-s2);
    display: none;
    max-height: 70vh;
    overflow: auto;
  }
  .nm-nav[data-open="true"] { display: flex; }
  .nm-nav__item { padding: 10px var(--nm-s3); border-radius: var(--nm-r-md); }

  .nm-brand__cn { display: none; }

  .nm-topo__stage { min-height: 46vh; }
  .nm-legend { display: none; }
  .nm-adv { width: 100%; max-width: 100%; }
  .nm-drawer { width: 100%; max-width: 100%; top: var(--nm-topbar-h); }
  .nm-footer { font-size: 10px; }
  .nm-watermark__track { width: 44px; }
  .nm-watermark__value { min-width: 44px; }
}

@media (max-width: 860px) {
  .nm-mobilelist { display: block; }
  .nm-topo__toolbar .nm-desktop-only { display: none; }
}

@media (min-width: 861px) {
  .nm-topo__toolbar .nm-mobile-only { display: none; }
}

/* 窄屏：拓扑降级只读，主视图为分组卡片列表 */
@media (max-width: 860px) {
  .nm-topo {
    grid-template-rows: auto auto minmax(0, 1fr);
    height: auto;
    min-height: 100%;
  }
  .nm-topo__stage { order: 3; }
}

@media (prefers-reduced-motion: reduce) {
  .nm-drawer, .nm-adv { animation: none; }
  * { transition-duration: 1ms !important; }
}

/* ═══════════════════════════════════════════════════════════════════
   全局：[hidden] 必须真的隐藏
   组件里只要给元素写了 display:grid/flex，浏览器 UA 的 [hidden]{display:none}
   就会被覆盖 —— 表现为"设了 hidden 却一直显示"（用户菜单、提示框都踩过）。
   这里统一兜底，新增组件不必再各自补规则。
   ═══════════════════════════════════════════════════════════════════ */
[hidden] { display: none !important; }