/* =============================================================================
 * ERROR_500! 机制试验原型 v1 —— 样式
 *
 * 配色取自现工程 Assets/Shaders/GridBackground.shader 的场景材质：
 * 近黑绿底、暗绿网格、亮绿高亮。目的是让它看上去仍是这个项目的一部分，
 * 而不是另一个外挂工具。
 * ========================================================================== */

:root {
  --bg:        #040806;
  --panel:     #071009;
  --panel-2:   #0a160d;
  --line:      #14351f;
  --grid:      #003511;
  --grid-hi:   #007b37;
  --text:      #8fe89f;
  --text-dim:  #4e8a63;
  --accent:    #00c46a;
  --warn:      #e8c98f;
  --bad:       #e87f7f;
  --good:      #5fd07f;
  --font: "Cascadia Mono", "Consolas", "Sarasa Mono SC", "Microsoft YaHei", monospace;
}

* { box-sizing: border-box; }

/* 界面文字一律不可选：长按选字会触发浏览器的选择手势，在拖拽操作里就是误触。
   输入框和文本域要留出来——那里是真的要选字的 */
#app, #app * { user-select: none; -webkit-user-select: none; }
#app input, #app textarea { user-select: text; -webkit-user-select: text; }

/* 故障告警条。**刻意不做成弹窗。**
   实测：256× 下每 0.30 真实秒就出一个 bug（每秒 3.4 个），而一个弹窗要求点击才能
   继续——那等于每秒钟点三次。而且从出 bug 到整站全挂只要 0.049 真实秒，
   弹窗根本来不及救，它只是在事后报丧。
   所以改成一条**常驻、不挡操作、自己会消失**的横条：
   它挂在画布上方，不抢焦点、不需要关闭，故障修好之后自己收回。 */
/* 可拖拽的服务卡：给一个「抓得住」的提示，不然玩家不会想到它能拖 */
.card.canDrag { cursor: grab; }
.card.canDrag:active, .card.canDrag.dragging { cursor: grabbing; }
.card.canDrag .hd::after {
  content: '⣿'; position: absolute; right: 8px; top: 6px;
  color: var(--text-dim); font-size: 10px; letter-spacing: -2px;
}
.card { position: relative; }
.card.canDrag:hover { border-color: var(--accent); }

#alertBar {
  position: absolute; top: 46px; left: 12px; right: 12px; z-index: 60;
  display: flex; align-items: center; gap: 10px;
  background: linear-gradient(90deg, #3a2417 0%, #2a1a12 100%);
  border: 1px solid #b4763a; border-left: 3px solid #e8a04f;
  border-radius: 3px; padding: 6px 10px;
  font: 12px/1.4 var(--font); color: #ffddb8;
  box-shadow: 0 3px 14px rgba(0,0,0,.5);
  animation: alertIn .18s ease-out;
}
@keyframes alertIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
#alertBar .ab-ico { font-size: 13px; }
#alertBar .ab-txt { flex: 1; min-width: 0; }
#alertBar .ab-txt b { color: #ffb066; }
#alertBar .ab-more { color: #b08a63; }
#alertBar .btn { padding: 3px 9px; font-size: 11px; }
#alertBar .ab-slow { background: #6a4a1e; border-color: #c9924a; color: #ffe6c2; }
#alertBar .ab-slow:hover { background: #7d5722; }

#errBox {
  position: fixed; inset: 0 0 auto 0; z-index: 999; margin: 0;
  background: #3a1717; color: #ffd9d9; border-bottom: 2px solid #e87f7f;
  padding: 10px 14px; font: 12px/1.5 var(--font); white-space: pre-wrap;
  max-height: 45vh; overflow: auto;
}

html, body {
  margin: 0; padding: 0; height: 100%;
  background: var(--bg); color: var(--text);
  font: 12px/1.5 var(--font);
  overflow: hidden;
}

#app { display: flex; height: 100vh; }

/* ==================== 画布区 ==================== */
#stage { position: relative; flex: 1; min-width: 0; }
#canvas { display: block; width: 100%; height: 100%; cursor: crosshair; }

.hidden { display: none !important; }

/* 顶部工具条 */
#topbar {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; align-items: center; gap: 14px;
  padding: 7px 12px;
  background: linear-gradient(#040806ee, #04080699 70%, #04080600);
  pointer-events: none;
}
#topbar .stat { display: flex; flex-direction: column; line-height: 1.15; }
#topbar .stat b { color: var(--accent); font-size: 13px; font-weight: 600; }
#topbar .stat i { color: var(--text-dim); font-style: normal; font-size: 10px; }
#topbar .spacer { flex: 1; }
#topbar .speeds { pointer-events: auto; display: flex; gap: 2px; }
#topbar .btn { pointer-events: auto; }

.btn {
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 3px;
  padding: 3px 9px; font: inherit; cursor: pointer;
}
.btn:hover { border-color: var(--accent); color: var(--accent); }
.btn.on { background: var(--accent); color: #040806; border-color: var(--accent); }
.btn.ghost { background: transparent; }

/* 建造面板 */
#buildBar {
  position: absolute; left: 10px; bottom: 10px; width: 208px;
  background: #040806dd; border: 1px solid var(--line); border-radius: 4px;
  padding: 8px; backdrop-filter: blur(3px);
}
.barTitle { color: var(--text-dim); font-size: 10px; letter-spacing: 2px; margin-bottom: 6px; }
.buildList { display: flex; flex-direction: column; gap: 3px; }
.buildItem {
  display: flex; align-items: center; gap: 7px;
  padding: 4px 6px; border-radius: 3px; cursor: pointer;
  border: 1px solid transparent;
}
.buildItem:hover { background: #0d1f13; }
.buildItem.on { border-color: var(--accent); background: #0d2416; }
.buildItem .dot { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.buildItem .nm { flex: 1; }
.buildItem .cost { color: var(--text-dim); font-size: 10px; }
.buildItem.locked { opacity: .35; cursor: not-allowed; }
.buildCfg { margin-top: 7px; border-top: 1px solid var(--line); padding-top: 6px; }
.buildCfg:empty { display: none; }

/* 建造提示 */
#buildHint {
  position: absolute; pointer-events: none;
  padding: 3px 8px; border-radius: 3px; font-size: 11px;
  background: #040806dd; border: 1px solid var(--accent); color: var(--accent);
  transform: translate(16px, 16px); white-space: nowrap;
}
#buildHint.bad { border-color: var(--bad); color: var(--bad); }

/* 右键菜单 */
#ctxMenu {
  position: absolute; min-width: 132px; z-index: 30;
  background: #071009f2; border: 1px solid var(--line); border-radius: 4px;
  padding: 3px; box-shadow: 0 6px 22px #000a;
}
#ctxMenu button {
  display: block; width: 100%; text-align: left;
  background: none; border: 0; color: var(--text);
  padding: 5px 9px; font: inherit; cursor: pointer; border-radius: 3px;
}
#ctxMenu button:hover { background: var(--line); color: var(--accent); }
#ctxMenu button.danger:hover { background: #3a1717; color: var(--bad); }

/* 事件盒 */
#eventBox {
  position: absolute; right: 10px; bottom: 10px; width: 330px;
  background: #040806dd; border: 1px solid var(--line); border-radius: 4px;
  backdrop-filter: blur(3px);
}
.evHead {
  display: flex; justify-content: space-between; gap: 8px;
  padding: 5px 8px; border-bottom: 1px solid var(--line);
  color: var(--text-dim); font-size: 10px; letter-spacing: 1px;
}
.failSummary { color: var(--bad); letter-spacing: 0; }
.eventLog { max-height: 118px; overflow-y: auto; padding: 4px 8px; }
.evRow { display: flex; gap: 7px; padding: 1px 0; }
.evRow .t { color: var(--text-dim); flex: none; }
.evRow.warn .m { color: var(--warn); }
.evRow.unlock .m { color: var(--accent); }
.evRow.bad .m { color: var(--bad); }

/* ==================== 侧栏 ==================== */
#side {
  width: 400px; flex: none; display: flex; flex-direction: column;
  background: var(--panel); border-left: 1px solid var(--line);
}
#tabs { display: flex; border-bottom: 1px solid var(--line); }
#tabs button {
  flex: 1; background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--text-dim); padding: 9px 0; font: inherit; cursor: pointer;
}
#tabs button:hover { color: var(--text); }
#tabs button.on { color: var(--accent); border-bottom-color: var(--accent); }

.panel { flex: 1; overflow-y: auto; padding: 10px 12px 40px; }

h3 {
  margin: 14px 0 6px; font-size: 11px; letter-spacing: 2px;
  color: var(--text-dim); font-weight: 600; text-transform: none;
  border-bottom: 1px solid var(--line); padding-bottom: 3px;
}
h3:first-child { margin-top: 0; }

table { width: 100%; border-collapse: collapse; }
th, td { text-align: right; padding: 2px 4px; font-variant-numeric: tabular-nums; }
th { color: var(--text-dim); font-weight: normal; font-size: 10px; }
th:first-child, td:first-child { text-align: left; }
tbody tr:hover { background: #0d1f13; }
td.num { color: var(--accent); }
td.bad { color: var(--bad); }
td.dim { color: var(--text-dim); }

/* 负载条 */
.loadbar { display: flex; align-items: center; gap: 5px; }
.loadbar .track {
  flex: 1; height: 6px; background: #0d1f13; border-radius: 3px; overflow: hidden;
  min-width: 40px;
}
.loadbar .fill { height: 100%; background: var(--good); transition: none; }
.loadbar .fill.w { background: var(--warn); }
.loadbar .fill.b { background: var(--bad); }
.loadbar .pct { width: 30px; text-align: right; font-size: 10px; color: var(--text-dim); }

/* 迷你曲线 */
.sparkWrap { position: relative; margin: 3px 0 9px; }
.spark { display: block; width: 100%; height: 46px; }
.sparkHi, .sparkLo {
  position: absolute; right: 2px; font-size: 9px; color: var(--text-dim);
  background: var(--panel); padding: 0 2px;
}
.sparkHi { top: -2px; }
.sparkLo { bottom: -2px; }

/* 解锁进度 */
.progress { height: 8px; background: #0d1f13; border-radius: 4px; overflow: hidden; }
.progress > div { height: 100%; background: var(--accent); }

/* 服务卡 */
.card {
  border: 1px solid var(--line); border-radius: 4px; padding: 7px 9px;
  margin-bottom: 6px; background: var(--panel-2);
}
.card.locked { opacity: .45; }
.card.deployed { border-color: var(--accent); }
.card .hd { display: flex; align-items: baseline; gap: 7px; min-width: 0; }
.card .hd .dot { width: 9px; height: 9px; border-radius: 2px; flex: none; align-self: center; }
/* 名字可以被压缩并省略号，状态永远不缩——状态是更该被看见的那一半 */
.card .hd .nm {
  flex: 1 1 auto; min-width: 0; color: #cfe8d6;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.card .hd .state { flex: 0 0 auto; color: var(--text-dim); font-size: 10px; white-space: nowrap; }
.card .meta { color: var(--text-dim); font-size: 10px; margin-top: 3px; }
.card .desc { color: var(--text-dim); font-size: 10px; margin-top: 4px; }
.card .acts { margin-top: 6px; display: flex; gap: 5px; flex-wrap: wrap; }
.card select {
  background: var(--panel); color: var(--text); border: 1px solid var(--line);
  border-radius: 3px; font: inherit; padding: 2px 4px; flex: 1; min-width: 0;
}

/* 调参 */
.pgroup { margin-bottom: 4px; }
.pgroup > summary {
  cursor: pointer; color: var(--text-dim); padding: 5px 0; letter-spacing: 1px;
  border-bottom: 1px solid var(--line); list-style: none;
}
.pgroup > summary::before { content: "▸ "; color: var(--accent); }
.pgroup[open] > summary::before { content: "▾ "; }
.pgroup > summary::-webkit-details-marker { display: none; }
.prow { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
.prow label { flex: 1; color: var(--text); font-size: 11px; }
.prow input[type=range] { flex: 1.1; min-width: 0; accent-color: var(--accent); }
.prow .val { width: 46px; text-align: right; color: var(--accent); font-size: 11px; }
.prow .hint { display: block; color: var(--text-dim); font-size: 10px; }

.toolRow { display: flex; gap: 5px; flex-wrap: wrap; margin: 6px 0; }
.toolRow .btn { flex: 1; min-width: 0; }

.kv { display: flex; justify-content: space-between; padding: 1px 0; }
.kv span:last-child { color: var(--accent); }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: var(--panel); }
::-webkit-scrollbar-thumb { background: #14351f; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #1d5230; }

/* 物理机的多路负载横排：一行两条，免得五路挤成一条缝 */
.barRow { display: flex; align-items: center; gap: 5px; padding: 1px 0; }
.barRow .bl { flex: none; width: 30px; color: var(--text-dim); font-size: 10px; }
.barRow .loadbar { flex: 1; min-width: 0; }

/* ==================== 节点配置弹窗 ==================== */
#nodeEditor {
  position: absolute; inset: 0; z-index: 40;
  background: #04080699; backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
}
.neBox {
  width: 460px; max-width: 92vw; max-height: 86vh;
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line); border-radius: 6px;
  box-shadow: 0 12px 48px #000c;
}
.neHead {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border-bottom: 1px solid var(--line);
}
.neTitle { flex: 1; color: var(--accent); font-size: 13px; }
.neBody { padding: 6px 14px 18px; overflow-y: auto; }
/* 弹窗里控件比窄栏宽裕，端口滑条要能摆成一行 */
.neBody .portRow { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
.neBody .portRow label { width: 62px; color: var(--text); font-size: 11px; }
.neBody .portRow input[type=range] { flex: 1; accent-color: var(--accent); }
.neBody .portRow .val { width: 30px; text-align: right; color: var(--accent); }
