/* 物上饮统一 Web 界面设计规范 V1.0 — OPS 实现
   深邃星空宇宙蓝 + 冷调蓝白 + 半透明玻璃质感 + 克制的蓝紫渐变 + 轻悬浮层次 */

:root {
  --wsy-bg-deep: #07111F;
  --wsy-bg-secondary: #0B1730;
  --wsy-surface-dark: rgba(17, 34, 64, 0.72);
  --wsy-surface-light: rgba(232, 243, 255, 0.82);
  --wsy-primary: #4EA1FF;
  --wsy-primary-hover: #6BB8FF;
  --wsy-indigo: #5B6CFF;
  --wsy-violet: #7A6CF6;
  --wsy-text-primary: #F4F8FF;
  --wsy-text-secondary: #AFC4E4;
  --wsy-text-dark: #14233A;
  --wsy-border: rgba(130, 180, 255, 0.22);
  --wsy-radius-sm: 8px;
  --wsy-radius-md: 12px;
  --wsy-radius-lg: 18px;
  --wsy-radius-xl: 24px;
  --wsy-shadow-float: 0 12px 32px rgba(0, 20, 55, 0.24);
  --wsy-shadow-soft: 0 6px 20px rgba(0, 20, 55, 0.16);
  --wsy-ok: #38C6A3;
  --wsy-info: #4EA1FF;
  --wsy-warn: #E8B44C;
  --wsy-danger: #F06A6A;
  --wsy-muted: #7E93B8;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  min-height: 100%;
}

body {
  font-family: Inter, "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", system-ui, sans-serif;
  background:
    radial-gradient(1200px 600px at 85% -10%, rgba(91, 108, 255, 0.16), transparent 60%),
    radial-gradient(900px 500px at -10% 110%, rgba(78, 161, 255, 0.10), transparent 55%),
    var(--wsy-bg-deep);
  color: var(--wsy-text-primary);
  font-size: 14px;
  line-height: 1.6;
}

a { color: var(--wsy-primary); text-decoration: none; }
a:hover { color: var(--wsy-primary-hover); }
code, .mono { font-family: "Cascadia Mono", Consolas, "JetBrains Mono", monospace; font-size: 12.5px; word-break: break-all; }

/* ---------- App shell: sidebar + topbar ---------- */
.shell { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }
.sidebar {
  background: linear-gradient(180deg, rgba(11, 23, 48, 0.95), rgba(7, 17, 31, 0.98));
  border-right: 1px solid var(--wsy-border);
  padding: 18px 12px;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.brand { display: flex; align-items: center; gap: 10px; padding: 6px 10px 18px; }
.brand .logo {
  width: 34px; height: 34px; border-radius: 10px; flex: none;
  background: linear-gradient(135deg, var(--wsy-primary), var(--wsy-violet));
  display: flex; align-items: center; justify-content: center; font-weight: 700; color: #fff;
}
.brand .name { font-size: 15px; font-weight: 600; letter-spacing: 0.5px; }
.brand .sub { font-size: 11px; color: var(--wsy-text-secondary); }
.nav-group-label { font-size: 11px; color: var(--wsy-muted); padding: 12px 12px 4px; letter-spacing: 1px; }
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; margin: 2px 0; border-radius: var(--wsy-radius-sm);
  color: var(--wsy-text-secondary); font-size: 13.5px; min-height: 38px;
}
.nav a .ico { width: 18px; text-align: center; flex: none; }
.nav a:hover { background: rgba(78, 161, 255, 0.10); color: var(--wsy-text-primary); }
.nav a.active {
  background: linear-gradient(90deg, rgba(78, 161, 255, 0.22), rgba(91, 108, 255, 0.12));
  color: var(--wsy-text-primary); font-weight: 600;
  border-left: 3px solid var(--wsy-primary); padding-left: 9px;
}

.main { display: flex; flex-direction: column; min-width: 0; }
.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 24px; border-bottom: 1px solid var(--wsy-border);
  background: rgba(7, 17, 31, 0.7); backdrop-filter: blur(8px);
  position: sticky; top: 0; z-index: 40;
}
/* The system name never wraps per-character (R1-037): it truncates instead, so
   a narrow top bar can never grow into a multi-line column of单字. */
.topbar .sys {
  font-weight: 600; font-size: 14px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0; flex: 0 1 auto;
}
.topbar .sys .sys-short { display: none; }
.env-badge {
  font-size: 11px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--wsy-border);
  color: var(--wsy-text-secondary); white-space: nowrap;
}
.env-badge.bootstrap { color: var(--wsy-warn); border-color: rgba(232, 180, 76, 0.5); background: rgba(232, 180, 76, 0.08); }
.env-badge.recovery { color: var(--wsy-danger); border-color: rgba(240, 106, 106, 0.5); background: rgba(240, 106, 106, 0.08); }
.topbar .spacer { flex: 1; }
.topbar .user { font-size: 13px; color: var(--wsy-text-secondary); display: flex; align-items: center; gap: 8px; }
.topbar .menu-btn.btn { display: none; }

.content { padding: 22px 24px 60px; max-width: 1500px; width: 100%; }
.page-title { font-size: 24px; font-weight: 650; margin-bottom: 4px; }
.page-sub { color: var(--wsy-text-secondary); font-size: 13px; margin-bottom: 20px; }
.page-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 18px; }

/* ---------- Cards ---------- */
.card {
  background: var(--wsy-surface-dark);
  border: 1px solid var(--wsy-border);
  border-radius: var(--wsy-radius-lg);
  box-shadow: var(--wsy-shadow-soft);
  padding: 18px 20px;
  margin-bottom: 16px;
}
.card h2 { font-size: 17px; margin-bottom: 12px; font-weight: 600; }
.card h3 { font-size: 14.5px; margin: 14px 0 8px; font-weight: 600; color: var(--wsy-text-secondary); }
.metric-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; margin-bottom: 18px; }
.metric {
  background: var(--wsy-surface-dark); border: 1px solid var(--wsy-border);
  border-radius: var(--wsy-radius-md); padding: 14px 16px; box-shadow: var(--wsy-shadow-soft);
}
.metric .label { font-size: 12px; color: var(--wsy-text-secondary); }
.metric .value { font-size: 30px; font-weight: 700; margin-top: 2px; }
.metric .hint { font-size: 11.5px; color: var(--wsy-muted); }

/* ---------- Status badges: 颜色 + 文字 (+ 图标) ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2.5px 10px; border-radius: 999px; font-size: 12px; font-weight: 600;
  border: 1px solid transparent; white-space: nowrap;
}
.badge::before { content: "●"; font-size: 9px; }
.badge.ok { color: var(--wsy-ok); background: rgba(56, 198, 163, 0.10); border-color: rgba(56, 198, 163, 0.35); }
.badge.info { color: var(--wsy-info); background: rgba(78, 161, 255, 0.10); border-color: rgba(78, 161, 255, 0.35); }
.badge.warn { color: var(--wsy-warn); background: rgba(232, 180, 76, 0.10); border-color: rgba(232, 180, 76, 0.35); }
.badge.danger { color: var(--wsy-danger); background: rgba(240, 106, 106, 0.10); border-color: rgba(240, 106, 106, 0.35); }
.badge.muted { color: var(--wsy-muted); background: rgba(126, 147, 184, 0.10); border-color: rgba(126, 147, 184, 0.35); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 36px; padding: 7px 16px; border-radius: var(--wsy-radius-sm);
  font-size: 13px; font-weight: 600; cursor: pointer; border: 1px solid var(--wsy-border);
  background: rgba(78, 161, 255, 0.08); color: var(--wsy-text-primary);
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
  text-decoration: none;
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--wsy-shadow-soft); background: rgba(78, 161, 255, 0.16); color: var(--wsy-text-primary); }
.btn.primary {
  background: linear-gradient(135deg, rgba(78, 161, 255, 0.9), rgba(91, 108, 255, 0.9));
  border-color: rgba(107, 184, 255, 0.6); color: #fff;
}
.btn.primary:hover { background: linear-gradient(135deg, var(--wsy-primary-hover), var(--wsy-indigo)); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--wsy-text-secondary); }
.btn.ghost:hover { color: var(--wsy-text-primary); background: rgba(78, 161, 255, 0.08); }
.btn.danger {
  background: rgba(240, 106, 106, 0.12); border-color: rgba(240, 106, 106, 0.45); color: var(--wsy-danger);
}
.btn.danger:hover { background: rgba(240, 106, 106, 0.22); }
.btn[disabled], .btn.disabled {
  opacity: 0.45; cursor: not-allowed; transform: none !important; box-shadow: none !important;
}
.btn.sm { min-height: 30px; padding: 4px 10px; font-size: 12px; }

/* ---------- Tables ---------- */
.table-wrap { overflow-x: auto; border-radius: var(--wsy-radius-md); border: 1px solid var(--wsy-border); }
table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 640px; background: rgba(11, 23, 48, 0.5); }
th {
  text-align: left; font-size: 12px; color: var(--wsy-text-secondary); font-weight: 600;
  padding: 10px 14px; border-bottom: 1px solid var(--wsy-border); white-space: nowrap;
  background: rgba(11, 23, 48, 0.8);
}
td { padding: 10px 14px; border-bottom: 1px solid rgba(130, 180, 255, 0.10); vertical-align: middle; }
tr:last-child td { border-bottom: none; }
tr:hover td { background: rgba(78, 161, 255, 0.05); }
td.actions { text-align: right; white-space: nowrap; }

/* ---------- Forms ---------- */
.field { margin-bottom: 14px; }
.field label { display: block; font-size: 12.5px; color: var(--wsy-text-secondary); margin-bottom: 5px; font-weight: 600; }
.field .req { color: var(--wsy-danger); margin-left: 3px; }
.field input, .field select, .field textarea {
  width: 100%; min-height: 38px; padding: 8px 12px;
  border-radius: var(--wsy-radius-sm); border: 1px solid var(--wsy-border);
  background: rgba(7, 17, 31, 0.6); color: var(--wsy-text-primary); font-size: 13.5px;
  font-family: inherit;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--wsy-primary); box-shadow: 0 0 0 3px rgba(78, 161, 255, 0.15);
}
.field .error { color: var(--wsy-danger); font-size: 12px; margin-top: 4px; }
.form-note { font-size: 12px; color: var(--wsy-muted); margin: 8px 0; }

/* ---------- Drawer ---------- */
.drawer-backdrop {
  position: fixed; inset: 0; background: rgba(3, 8, 16, 0.55); z-index: 60;
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(560px, 96vw); z-index: 61;
  background: linear-gradient(180deg, #0B1730, #081221);
  border-left: 1px solid var(--wsy-border); box-shadow: var(--wsy-shadow-float);
  transform: translateX(102%); transition: transform 0.22s ease;
  display: flex; flex-direction: column;
}
.drawer.open { transform: translateX(0); }
.drawer-backdrop.open { opacity: 1; pointer-events: auto; }
.drawer .drawer-head {
  display: flex; align-items: center; gap: 10px; padding: 16px 20px;
  border-bottom: 1px solid var(--wsy-border);
}
.drawer .drawer-head h2 { font-size: 16px; flex: 1; }
.drawer .drawer-body { padding: 18px 20px 40px; overflow-y: auto; }

/* ---------- Modal ---------- */
.modal-backdrop {
  position: fixed; inset: 0; background: rgba(3, 8, 16, 0.6); z-index: 70;
  display: none; align-items: center; justify-content: center; padding: 16px;
}
.modal-backdrop.open { display: flex; }
.modal {
  width: min(520px, 100%); background: linear-gradient(180deg, #0D1B38, #0A1528);
  border: 1px solid var(--wsy-border); border-radius: var(--wsy-radius-lg);
  box-shadow: var(--wsy-shadow-float); padding: 20px 22px; max-height: 90vh; overflow-y: auto;
}
.modal h2 { font-size: 16px; margin-bottom: 10px; }
.modal .risk-list { margin: 10px 0; padding-left: 0; list-style: none; font-size: 13px; }
.modal .risk-list li { padding: 4px 0; display: flex; gap: 8px; }
.modal .risk-list .k { color: var(--wsy-text-secondary); flex: none; width: 92px; }
.modal .modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }

/* ---------- Toast ---------- */
#toasts { position: fixed; bottom: 18px; right: 18px; z-index: 90; display: flex; flex-direction: column; gap: 8px; max-width: min(420px, 92vw); }
.toast {
  background: rgba(13, 27, 56, 0.95); border: 1px solid var(--wsy-border);
  border-radius: var(--wsy-radius-md); padding: 12px 16px; font-size: 13px;
  box-shadow: var(--wsy-shadow-float); animation: toast-in 0.2s ease;
}
.toast.ok { border-color: rgba(56, 198, 163, 0.5); }
.toast.error { border-color: rgba(240, 106, 106, 0.5); }
@keyframes toast-in { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------- States ---------- */
.empty, .error-state {
  padding: 34px 20px; text-align: center; color: var(--wsy-text-secondary);
  border: 1px dashed var(--wsy-border); border-radius: var(--wsy-radius-md); font-size: 13px;
}
.error-state { color: var(--wsy-danger); border-color: rgba(240, 106, 106, 0.4); }
.skeleton { background: linear-gradient(90deg, rgba(130,180,255,0.06), rgba(130,180,255,0.14), rgba(130,180,255,0.06)); background-size: 200% 100%; animation: sk 1.4s infinite; border-radius: var(--wsy-radius-sm); min-height: 16px; }
@keyframes sk { from { background-position: 200% 0; } to { background-position: -200% 0; } }

.blocked-banner {
  border: 1px solid rgba(240, 106, 106, 0.45); background: rgba(240, 106, 106, 0.08);
  color: #FFC9C9; border-radius: var(--wsy-radius-md); padding: 12px 16px; margin-bottom: 14px; font-size: 13px;
}
.notice-banner {
  border: 1px solid rgba(232, 180, 76, 0.45); background: rgba(232, 180, 76, 0.08);
  color: #F7DFAE; border-radius: var(--wsy-radius-md); padding: 12px 16px; margin-bottom: 14px; font-size: 13px;
}

/* ---------- App overview cards ---------- */
.app-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 16px; }
.app-card {
  background: var(--wsy-surface-dark); border: 1px solid var(--wsy-border);
  border-radius: var(--wsy-radius-lg); box-shadow: var(--wsy-shadow-soft); padding: 16px 18px;
  display: flex; flex-direction: column; gap: 10px;
}
.app-card .head { display: flex; align-items: center; gap: 10px; }
.app-card .head .title { font-size: 15.5px; font-weight: 650; flex: 1; min-width: 0; }
.app-card .appid { font-size: 11.5px; color: var(--wsy-muted); }
.app-card .statuses { display: flex; flex-wrap: wrap; gap: 6px; }
.app-card .kv { font-size: 12.5px; color: var(--wsy-text-secondary); display: flex; gap: 6px; }
.app-card .kv .v { color: var(--wsy-text-primary); }
.app-card .ops { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }

/* ---------- Detail lists ---------- */
.dl { display: grid; grid-template-columns: 130px 1fr; row-gap: 7px; font-size: 13px; }
.dl dt { color: var(--wsy-text-secondary); }
.dl dd { word-break: break-word; }

/* ---------- Timeline ---------- */
.timeline { list-style: none; }
.timeline li { position: relative; padding: 0 0 14px 22px; border-left: 2px solid rgba(130, 180, 255, 0.2); margin-left: 6px; }
.timeline li::before {
  content: ""; position: absolute; left: -6px; top: 3px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--wsy-primary); box-shadow: 0 0 0 3px rgba(78, 161, 255, 0.15);
}
.timeline li.failure::before { background: var(--wsy-danger); box-shadow: 0 0 0 3px rgba(240, 106, 106, 0.15); }
.timeline .t-time { font-size: 11.5px; color: var(--wsy-muted); }
.timeline .t-title { font-size: 13px; }

/* ---------- Login ---------- */
.login-wrap { display: grid; grid-template-columns: 40% 60%; min-height: 100vh; }
.login-left { display: flex; flex-direction: column; justify-content: center; padding: 6vh 6vw; }
.login-card {
  background: var(--wsy-surface-dark); border: 1px solid var(--wsy-border);
  border-radius: var(--wsy-radius-xl); box-shadow: var(--wsy-shadow-float); padding: 30px 28px; max-width: 420px;
}
.login-right {
  position: relative; overflow: hidden;
  background:
    radial-gradient(600px 400px at 30% 30%, rgba(91, 108, 255, 0.35), transparent 60%),
    radial-gradient(700px 500px at 75% 70%, rgba(78, 161, 255, 0.25), transparent 60%),
    linear-gradient(160deg, #0B1730, #07111F);
  display: flex; align-items: center; justify-content: center;
}
.login-right .slogan { text-align: center; padding: 0 40px; }
.login-right .slogan h1 { font-size: 30px; font-weight: 700; letter-spacing: 1px; margin-bottom: 12px; }
.login-right .slogan p { color: var(--wsy-text-secondary); font-size: 14px; }
.stars { position: absolute; inset: 0; background-image:
  radial-gradient(1.5px 1.5px at 20% 30%, rgba(255,255,255,0.7), transparent),
  radial-gradient(1px 1px at 60% 20%, rgba(255,255,255,0.5), transparent),
  radial-gradient(1.2px 1.2px at 80% 60%, rgba(255,255,255,0.6), transparent),
  radial-gradient(1px 1px at 35% 75%, rgba(255,255,255,0.5), transparent),
  radial-gradient(1.4px 1.4px at 50% 50%, rgba(255,255,255,0.45), transparent);
  animation: drift 60s linear infinite alternate; }
@keyframes drift { from { transform: translateY(0); } to { transform: translateY(-24px); } }

/* ---------- Tabs / filters ---------- */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--wsy-border); margin-bottom: 16px; overflow-x: auto; }
.tabs a { padding: 8px 16px; font-size: 13px; color: var(--wsy-text-secondary); border-bottom: 2px solid transparent; white-space: nowrap; }
.tabs a.active { color: var(--wsy-text-primary); border-bottom-color: var(--wsy-primary); font-weight: 600; }
.filterbar { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; align-items: center; }
.filterbar select, .filterbar input { min-height: 34px; padding: 5px 10px; border-radius: var(--wsy-radius-sm); border: 1px solid var(--wsy-border); background: rgba(7, 17, 31, 0.6); color: var(--wsy-text-primary); font-size: 13px; }

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
  .shell { grid-template-columns: 200px 1fr; }
  .content { padding: 18px 16px 60px; }
}

@media (max-width: 768px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; left: 0; top: 0; bottom: 0; width: min(280px, 84vw); z-index: 80;
    transform: translateX(-102%); transition: transform 0.22s ease; height: 100vh;
  }
  .sidebar.open { transform: translateX(0); }
  .topbar .menu-btn.btn { display: inline-flex; }
  .login-wrap { grid-template-columns: 1fr; }
  .login-right { display: none; }
  .table-wrap table { min-width: 560px; }
  .app-grid { grid-template-columns: 1fr; }
  .dl { grid-template-columns: 110px 1fr; }
}

@media (max-width: 480px) {
  .content { padding: 14px 10px 70px; }
  .page-title { font-size: 20px; }
  .metric .value { font-size: 24px; }
  .badge { white-space: normal; text-align: left; }
  .dl { grid-template-columns: 1fr; row-gap: 2px; }
  .dl dt { margin-top: 8px; }
  .btn { min-height: 44px; }
  .btn.sm { min-height: 44px; }
  .nav a { min-height: 44px; }
  .drawer { width: 100vw; }
  .topbar .user .uname { display: none; }

  /* R1-037 — the top bar stays ONE compact row of full-size touch targets.
     The long system name is swapped for the short mark, and the env badge is
     pushed onto its own wrapped line so it can never squeeze its siblings. */
  .topbar { padding: 6px 10px; gap: 8px; flex-wrap: wrap; row-gap: 4px; }
  .topbar .sys .sys-full { display: none; }
  .topbar .sys .sys-short { display: inline; }
  .topbar .env-badge { order: 5; flex: 1 0 100%; text-align: center; padding: 2px 10px; }
  /* Icon-only ghost buttons need a real 44×44 box, not just min-height. */
  .topbar .btn, .topbar button, .topbar a.btn {
    min-width: 44px; min-height: 44px; padding: 7px 10px;
  }
}

@media (max-width: 360px) {
  /* Smallest supported width: drop the env badge entirely — the content area
     already carries the Bootstrap / recovery-mode banner. */
  .topbar { flex-wrap: nowrap; }
  .topbar .env-badge { display: none; }
  .content { padding: 12px 8px 70px; }
}
