<template>
  <div class="page" v-if="machine">
    <!-- Header -->
    <div class="detail-header">
      <div class="header-left">
        <el-button text circle @click="$router.back()">
          <el-icon><ArrowLeft /></el-icon>
        </el-button>
        <div>
          <div class="host-title">
            {{ machine.hostname }}
            <span class="status-badge" :class="machine.is_online ? 'online' : 'offline'">
              {{ machine.is_online ? '在线' : '离线' }}
            </span>
          </div>
          <div class="host-subtitle">
            <span v-if="isAdmin">{{ machine.ip }}</span>
            <span>{{ machine.os_type }}</span>
            <span v-if="machine.os_version">{{ machine.os_version }}</span>
          </div>
        </div>
      </div>
      <div class="header-actions" v-if="isAdmin">
        <el-button text :icon="Edit" @click="openEdit(machine)">编辑</el-button>
        <el-button text type="danger" :icon="Delete" @click="delMachine">删除</el-button>
      </div>
    </div>

    <div class="detail-grid">
      <!-- Basic Info -->
      <div class="card">
        <div class="card-title">基本信息</div>
        <div class="info-list">
          <div class="info-item"><span class="info-label">IP</span><span class="info-value">{{ machine.ip }}</span></div>
          <div class="info-item" v-if="isAdmin"><span class="info-label">MAC</span><span class="info-value">{{ machine.mac || '-' }}</span></div>
          <div class="info-item"><span class="info-label">系统</span><span class="info-value">{{ machine.os_type }} {{ machine.os_version || '' }}</span></div>
          <div class="info-item" v-if="isAdmin"><span class="info-label">SSH 端口</span><span class="info-value">{{ machine.ssh_port || 22 }}</span></div>
          <div class="info-item" v-if="isAdmin"><span class="info-label">备注</span><span class="info-value text-muted">{{ machine.notes || '-' }}</span></div>
        </div>
      </div>

      <!-- System Status -->
      <div class="card" v-if="machine.cpu_info || machine.memory_info || machine.disk_info">
        <div class="card-title">系统状态</div>
        <div class="status-pills">
          <div v-if="machine.cpu_info" class="status-pill">
            <div class="sp-icon cpu">CPU</div>
            <div class="sp-info">
              <div class="sp-title">{{ machine.cpu_info }}</div>
              <div class="sp-bar"><div class="sp-fill" :style="{ width: extractPercent(machine.cpu_info) + '%' }"></div></div>
            </div>
            <div class="sp-num">{{ extractPercent(machine.cpu_info) }}%</div>
          </div>
          <div v-if="machine.memory_info" class="status-pill">
            <div class="sp-icon mem">MEM</div>
            <div class="sp-info">
              <div class="sp-title">{{ machine.memory_info }}</div>
              <div class="sp-bar"><div class="sp-fill" :style="{ width: extractPercent(machine.memory_info) + '%', background: getMemBarColor(extractPercent(machine.memory_info)) }"></div></div>
            </div>
            <div class="sp-num">{{ extractPercent(machine.memory_info) }}%</div>
          </div>
          <div v-if="machine.disk_info" class="status-pill disk-multi">
            <template v-if="parseDisks(machine.disk_info).length <= 1">
              <div class="sp-icon disk">DISK</div>
              <div class="sp-info">
                <div class="sp-title">{{ machine.disk_info }}</div>
                <div class="sp-bar"><div class="sp-fill" :style="{ width: extractPercent(machine.disk_info) + '%', background: getDiskBarColor(extractPercent(machine.disk_info)) }"></div></div>
              </div>
              <div class="sp-num">{{ extractPercent(machine.disk_info) }}%</div>
            </template>
            <template v-else>
              <div class="sp-icon disk">DISK</div>
              <div class="sp-info multi-disk-info">
                <div v-for="(d, idx) in parseDisks(machine.disk_info)" :key="idx" class="detail-disk-item">
                  <span class="dd-mount">{{ d.mount }}</span>
                  <div class="dd-bar-wrap">
                    <div class="dd-bar"><div class="dd-fill" :style="{ width: d.percent + '%', background: getDiskBarColor(d.percent) }"></div></div>
                  </div>
                  <span class="dd-val">{{ d.detail }}</span>
                  <span class="dd-pct">{{ d.percent }}%</span>
                </div>
              </div>
            </template>
          </div>
        </div>
        <div v-if="machine.uptime" class="uptime-line">
          <el-icon><Timer /></el-icon>
          <span>运行时间 {{ machine.uptime }}</span>
        </div>
      </div>

      <!-- SSH Section -->
      <div class="card" v-if="isAdmin">
        <div class="card-title">SSH 系统信息</div>
        <div v-if="machine.cpu_info || machine.memory_info || machine.disk_info || machine.uptime" class="sync-actions">
          <el-tag size="small" effect="plain" round>上次同步 {{ formatTime(machine.ssh_synced_at) }}</el-tag>
        </div>
        <div class="ssh-actions">
          <el-button type="primary" :icon="Refresh" @click="openSSH">获取系统信息</el-button>
        </div>
        <div v-if="sshResult" class="ssh-result">
          <div class="result-grid">
            <div class="result-item"><span class="rl">主机名</span><span class="rv">{{ sshResult.hostname }}</span></div>
            <div class="result-item"><span class="rl">系统版本</span><span class="rv">{{ sshResult.os_version }}</span></div>
            <div class="result-item"><span class="rl">CPU</span><span class="rv">{{ sshResult.cpu }}</span></div>
            <div class="result-item"><span class="rl">内存</span><span class="rv">{{ sshResult.memory }}</span></div>
            <div class="result-item"><span class="rl">磁盘</span><span class="rv">{{ sshResult.disk }}</span></div>
            <div class="result-item"><span class="rl">运行时间</span><span class="rv">{{ sshResult.uptime }}</span></div>
            <div class="result-item full"><span class="rl">监听端口</span><span class="rv">{{ sshResult.listen_ports?.join(', ') }}</span></div>
          </div>
        </div>
      </div>

      <!-- Services -->
      <div class="card">
        <div class="card-title">
          服务列表
          <el-button v-if="isAdmin" size="small" type="primary" :icon="Plus" @click="openServiceEdit()">添加服务</el-button>
        </div>
        <div v-if="services.length" class="service-list">
          <div v-for="s in services" :key="s.id" class="service-row">
            <div class="service-main">
              <div class="service-name">{{ s.name }}</div>
              <div class="service-port">{{ s.port }} / {{ s.protocol }}</div>
            </div>
            <div class="service-target" v-if="isAdmin && s.target_machine_id">
              <el-icon><Right /></el-icon>
              <span>{{ machineMap[s.target_machine_id] || s.target_machine_id }}</span>
              <span v-if="s.target_notes" class="target-note">{{ s.target_notes }}</span>
            </div>
            <div class="service-note" v-if="isAdmin && s.notes">{{ s.notes }}</div>
            <div class="service-actions" v-if="isAdmin">
              <el-button text size="small" :icon="Edit" @click.stop="openServiceEdit(s)">编辑</el-button>
              <el-button text size="small" type="danger" :icon="Delete" @click.stop="delService(s)">删除</el-button>
            </div>
          </div>
        </div>
        <el-empty v-else description="暂无服务" :image-size="80" />
      </div>

      <!-- Offline Stats & Logs -->
      <div class="card" v-if="isAdmin">
        <div class="card-title">离线统计</div>
        <div class="offline-stats">
          <div class="stat-box">
            <div class="stat-num">{{ machine.offline_count || 0 }}</div>
            <div class="stat-label">离线次数</div>
          </div>
          <div class="stat-box">
            <div class="stat-num">{{ formatDuration(machine.total_offline_seconds) }}</div>
            <div class="stat-label">累计离线时长</div>
          </div>
          <div class="stat-box" v-if="machine.last_offline_reason">
            <div class="stat-reason">{{ machine.last_offline_reason }}</div>
            <div class="stat-label">上次离线原因</div>
          </div>
        </div>
        <div v-if="offlineLogs.length" class="offline-logs">
          <div class="log-title">最近离线记录</div>
          <div v-for="log in offlineLogs.slice(0, 5)" :key="log.id" class="log-row">
            <span class="log-time">{{ formatTime(log.started_at) }}</span>
            <span class="log-reason">{{ log.reason || '未知原因' }}</span>
            <span class="log-dur" v-if="log.duration_seconds !== null && log.duration_seconds !== undefined">持续 {{ formatDuration(log.duration_seconds) }}</span>
            <span class="log-dur pending" v-else>未恢复</span>
          </div>
        </div>
      </div>

      <!-- Relationships -->
      <div class="card" v-if="isAdmin">
        <div class="card-title">
          关联关系
          <el-button size="small" type="primary" :icon="Plus" @click="openRelEdit()">添加关系</el-button>
        </div>
        <div v-if="relationships.length" class="rel-list">
          <div v-for="r in relationships" :key="r.id" class="rel-row">
            <div class="rel-arrow">
              <span class="rel-host">{{ r.source_hostname }}</span>
              <el-icon><Right /></el-icon>
              <span class="rel-host">{{ r.target_hostname }}</span>
            </div>
            <div class="rel-meta">
              <el-tag size="small" effect="plain" round>{{ typeText(r.relation_type) }}</el-tag>
              <span v-if="r.source_port" class="rel-port">{{ r.source_port }} → {{ r.target_port || '-' }}</span>
              <span v-if="r.notes" class="rel-note">{{ r.notes }}</span>
            </div>
            <div class="rel-actions">
              <el-button text size="small" :icon="Edit" @click="openRelEdit(r)">编辑</el-button>
              <el-button text size="small" type="danger" :icon="Delete" @click="delRel(r)">删除</el-button>
            </div>
          </div>
        </div>
        <el-empty v-else description="暂无关系" :image-size="80" />
      </div>
    </div>

    <!-- SSH Dialog -->
    <el-dialog v-model="sshDialogVisible" title="SSH 获取系统信息" width="360px" class="modern-dialog">
      <el-form :model="sshForm" label-width="80px">
        <el-form-item label="用户名">
          <el-input v-model="sshForm.username" />
        </el-form-item>
        <el-form-item label="密码">
          <el-input v-model="sshForm.password" type="password" show-password />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="sshDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="sshLoading" @click="fetchSSH">连接</el-button>
      </template>
    </el-dialog>

    <!-- Machine Edit Dialog -->
    <el-dialog v-model="dialogVisible" title="编辑机器" width="480px" class="modern-dialog">
      <el-form :model="editing" label-width="90px">
        <el-form-item label="主机名" required><el-input v-model="editing.hostname" /></el-form-item>
        <el-form-item label="IP" required><el-input v-model="editing.ip" /></el-form-item>
        <el-form-item label="MAC"><el-input v-model="editing.mac" /></el-form-item>
        <el-form-item label="SSH端口"><el-input-number v-model="editing.ssh_port" :min="1" :max="65535" style="width:100%" /></el-form-item>
        <el-form-item label="SSH用户"><el-input v-model="editing.ssh_username" /></el-form-item>
        <el-form-item label="SSH密码"><el-input v-model="editing.ssh_password" type="password" show-password placeholder="输入则更新密码，留空保持不变" /></el-form-item>
        <el-form-item label="系统" required>
          <el-select v-model="editing.os_type" style="width:100%">
            <el-option label="Linux" value="Linux" />
            <el-option label="Windows" value="Windows" />
            <el-option label="macOS" value="macOS" />
            <el-option label="Other" value="Other" />
          </el-select>
        </el-form-item>
        <el-form-item label="系统版本"><el-input v-model="editing.os_version" /></el-form-item>
        <el-form-item label="备注"><el-input v-model="editing.notes" type="textarea" :rows="2" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveMachine">保存</el-button>
      </template>
    </el-dialog>

    <!-- Service Edit Dialog -->
    <el-dialog v-model="serviceDialogVisible" title="编辑服务" width="440px" class="modern-dialog">
      <el-form :model="serviceEditing" label-width="90px">
        <el-form-item label="名称" required><el-input v-model="serviceEditing.name" /></el-form-item>
        <el-form-item label="端口" required><el-input-number v-model="serviceEditing.port" :min="1" :max="65535" style="width:100%" /></el-form-item>
        <el-form-item label="协议">
          <el-select v-model="serviceEditing.protocol" style="width:100%">
            <el-option label="TCP" value="TCP" />
            <el-option label="UDP" value="UDP" />
            <el-option label="HTTP" value="HTTP" />
            <el-option label="HTTPS" value="HTTPS" />
          </el-select>
        </el-form-item>
        <el-form-item label="指向机器">
          <el-select v-model="serviceEditing.target_machine_id" clearable style="width:100%" placeholder="选择目标机器（拓扑连线用）">
            <el-option v-for="m in allMachines.filter(x => x.id != machineId)" :key="m.id" :label="m.hostname" :value="m.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="指向备注">
          <el-input v-model="serviceEditing.target_notes" placeholder="如：反向代理到目标" />
        </el-form-item>
        <el-form-item label="备注"><el-input v-model="serviceEditing.notes" type="textarea" :rows="2" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="serviceDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveService">保存</el-button>
      </template>
    </el-dialog>

    <!-- Relationship Edit Dialog -->
    <el-dialog v-model="relDialogVisible" title="编辑关系" width="440px" class="modern-dialog">
      <el-form :model="relEditing" label-width="100px">
        <el-form-item label="源机器" required>
          <el-select v-model="relEditing.source_machine_id" style="width:100%">
            <el-option v-for="m in allMachines" :key="m.id" :label="m.hostname" :value="m.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="目标机器" required>
          <el-select v-model="relEditing.target_machine_id" style="width:100%">
            <el-option v-for="m in allMachines" :key="m.id" :label="m.hostname" :value="m.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="关系类型" required>
          <el-select v-model="relEditing.relation_type" style="width:100%">
            <el-option label="端口转发" value="port_forward" />
            <el-option label="依赖" value="dependency" />
            <el-option label="主从" value="primary_secondary" />
            <el-option label="自定义" value="custom" />
          </el-select>
        </el-form-item>
        <el-form-item label="源端口"><el-input-number v-model="relEditing.source_port" :min="1" :max="65535" style="width:100%" /></el-form-item>
        <el-form-item label="目标端口"><el-input-number v-model="relEditing.target_port" :min="1" :max="65535" style="width:100%" /></el-form-item>
        <el-form-item label="备注"><el-input v-model="relEditing.notes" type="textarea" :rows="2" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="relDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveRel">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ArrowLeft, Edit, Delete, Plus, Refresh, Right, Timer } from '@element-plus/icons-vue'
import {
  fetchMachine, updateMachine, deleteMachine,
  fetchServices, createService, updateService, deleteService,
  fetchRelationships, createRelationship, updateRelationship, deleteRelationship,
  sshInfo, syncSSH, fetchMachines, fetchOfflineLogs,
  checkAuth, uiRefreshInterval,
} from '@/api'
import { getAuth } from '@/router'
import { ElMessage, ElMessageBox } from 'element-plus'

const route = useRoute()
const router = useRouter()
const isAdmin = getAuth().is_admin
const machineId = route.params.id

const machine = ref(null)
const services = ref([])
const relationships = ref([])
const allMachines = ref([])
const offlineLogs = ref([])

const dialogVisible = ref(false)
const editing = ref({})
const sshDialogVisible = ref(false)
const sshForm = ref({ username: '', password: '' })
const sshResult = ref(null)
const sshLoading = ref(false)

const serviceDialogVisible = ref(false)
const serviceEditing = ref({})

const relDialogVisible = ref(false)
const relEditing = ref({})

const machineMap = computed(() => {
  const map = {}
  allMachines.value.forEach(m => map[m.id] = m.hostname)
  return map
})

let timer = null

onMounted(async () => {
  await loadMachine()
  await loadServices()
  if (isAdmin) {
    await loadRelationships()
    const res = await fetchMachines()
    allMachines.value = res.data
  }
  await checkAuth()
  const interval = uiRefreshInterval || 10000
  if (interval > 0) {
    timer = setInterval(async () => {
      await loadMachine()
      await loadServices()
      if (isAdmin) {
        await loadRelationships()
      }
    }, interval)
  }
})

onUnmounted(() => {
  if (timer) clearInterval(timer)
})

async function loadMachine() {
  const res = await fetchMachine(machineId)
  machine.value = res.data.machine
  if (isAdmin) {
    const logsRes = await fetchOfflineLogs(machineId)
    offlineLogs.value = logsRes.data
  }
  // 如果已有同步过的 SSH 信息，直接展示上次结果
  if (machine.value && (machine.value.cpu_info || machine.value.memory_info || machine.value.disk_info || machine.value.uptime)) {
    sshResult.value = {
      hostname: machine.value.hostname,
      os_version: machine.value.os_version,
      cpu: machine.value.cpu_info,
      memory: machine.value.memory_info,
      disk: machine.value.disk_info,
      uptime: machine.value.uptime,
      listen_ports: machine.value.listen_ports ? machine.value.listen_ports.split(',').map(s => s.trim()).filter(Boolean) : []
    }
  } else {
    sshResult.value = null
  }
}

async function loadServices() {
  const res = await fetchServices(machineId)
  services.value = res.data
}

async function loadRelationships() {
  const res = await fetchRelationships()
  const map = {}
  allMachines.value.forEach(m => map[m.id] = m.hostname)
  relationships.value = res.data
    .filter(r => r.source_machine_id == machineId || r.target_machine_id == machineId)
    .map(r => ({
      ...r,
      source_hostname: map[r.source_machine_id] || r.source_machine_id,
      target_hostname: map[r.target_machine_id] || r.target_machine_id
    }))
}

function openEdit(item) {
  editing.value = { ...item, ssh_port: item.ssh_port || 22, ssh_username: item.ssh_username || '', ssh_password: '' }
  dialogVisible.value = true
}

async function openSSH() {
  // 如果已保存用户名，先尝试用数据库里的凭据自动获取
  if (machine.value.ssh_username) {
    sshLoading.value = true
    try {
      const res = await sshInfo(machineId, { username: machine.value.ssh_username, password: '' })
      sshResult.value = res.data
      await syncSSH(machineId, sshResult.value)
      ElMessage.success('获取并同步成功')
      await loadMachine()
      sshLoading.value = false
      return
    } catch (e) {
      sshLoading.value = false
      // 自动获取失败，继续弹出对话框让用户手动输入
    }
  }
  sshForm.value = {
    username: machine.value.ssh_username || '',
    password: ''
  }
  sshDialogVisible.value = true
}

async function saveMachine() {
  await updateMachine(editing.value.id, editing.value)
  ElMessage.success('保存成功')
  dialogVisible.value = false
  loadMachine()
}

async function delMachine() {
  try {
    await ElMessageBox.confirm('确定删除该机器？', '提示', { type: 'warning' })
    await deleteMachine(machineId)
    ElMessage.success('删除成功')
    router.back()
  } catch (e) {}
}

async function fetchSSH() {
  sshLoading.value = true
  try {
    const res = await sshInfo(machineId, sshForm.value)
    sshResult.value = res.data
    sshDialogVisible.value = false
    await syncSSH(machineId, sshResult.value)
    ElMessage.success('获取并同步成功')
    await loadMachine()
  } catch (e) {}
  sshLoading.value = false
}

function openServiceEdit(row) {
  serviceEditing.value = row
    ? { ...row, target_machine_id: row.target_machine_id || null, target_notes: row.target_notes || '' }
    : { name: '', port: 80, protocol: 'TCP', notes: '', target_machine_id: null, target_notes: '' }
  serviceDialogVisible.value = true
}

async function saveService() {
  const data = { ...serviceEditing.value }
  if (data.id) {
    await updateService(data.id, data)
  } else {
    await createService(machineId, data)
  }
  ElMessage.success('保存成功')
  serviceDialogVisible.value = false
  loadServices()
}

async function delService(row) {
  try {
    await ElMessageBox.confirm('确定删除该服务？', '提示', { type: 'warning' })
    await deleteService(row.id)
    ElMessage.success('删除成功')
    loadServices()
  } catch (e) {}
}

function openRelEdit(row) {
  relEditing.value = row
    ? { ...row }
    : { source_machine_id: Number(machineId), target_machine_id: null, relation_type: 'dependency', source_port: null, target_port: null, notes: '' }
  relDialogVisible.value = true
}

async function saveRel() {
  const data = { ...relEditing.value }
  if (data.id) {
    await updateRelationship(data.id, data)
  } else {
    await createRelationship(data)
  }
  ElMessage.success('保存成功')
  relDialogVisible.value = false
  loadRelationships()
}

async function delRel(row) {
  try {
    await ElMessageBox.confirm('确定删除该关系？', '提示', { type: 'warning' })
    await deleteRelationship(row.id)
    ElMessage.success('删除成功')
    loadRelationships()
  } catch (e) {}
}

function typeText(t) {
  const map = { port_forward: '端口转发', dependency: '依赖', primary_secondary: '主从', custom: '自定义' }
  return map[t] || t
}

function extractPercent(str) {
  if (!str) return 0
  const m = str.match(/\((\d+)%\)/) || str.match(/(\d+(?:\.\d+)?)%/)
  if (m) {
    const v = parseFloat(m[1])
    return isNaN(v) ? 0 : Math.min(100, Math.max(0, Math.round(v)))
  }
  return 0
}

function getMemBarColor(v) {
  if (v >= 90) return '#f87171'
  if (v >= 70) return '#fbbf24'
  return '#34d399'
}
function getDiskBarColor(v) {
  if (v >= 90) return '#f87171'
  if (v >= 80) return '#fbbf24'
  return '#60a5fa'
}

function parseDisks(str) {
  if (!str) return []
  const disks = []
  const regex = /(\S+)\s+([\d\.]+[KMGT]?\/[\d\.]+[KMGT]?)\s+\((\d+)%\)/g
  let m
  while ((m = regex.exec(str)) !== null) {
    disks.push({ mount: m[1], detail: m[2], percent: parseInt(m[3], 10) })
  }
  if (disks.length > 0) {
    return disks
  }
  // fallback: single disk old format
  const pct = extractPercent(str)
  const det = extractDetail(str)
  if (det) {
    return [{ mount: '', detail: det, percent: pct }]
  }
  return []
}

function formatTime(t) {
  if (!t) return '-'
  const d = new Date(t)
  if (isNaN(d.getTime())) return t
  const pad = n => String(n).padStart(2, '0')
  return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
}

function formatDuration(seconds) {
  if (!seconds && seconds !== 0) return '-'
  const s = Number(seconds)
  if (s < 60) return `${s}秒`
  if (s < 3600) return `${Math.floor(s / 60)}分${s % 60}秒`
  const h = Math.floor(s / 3600)
  const m = Math.floor((s % 3600) / 60)
  const sec = s % 60
  if (h < 24) return `${h}时${m}分`
  const d = Math.floor(h / 24)
  const hr = h % 24
  return `${d}天${hr}时${m}分`
}
</script>

<style scoped>
.detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  gap: 12px;
}
.header-left {
  display: flex;
  align-items: center;
  gap: 12px;
}
.host-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 20px;
  font-weight: 700;
}
.status-badge {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 600;
}
.status-badge.online { background: rgba(34,197,94,0.12); color: #15803d; }
.status-badge.offline { background: rgba(239,68,68,0.10); color: #b91c1c; }
html.dark .status-badge.online { background: rgba(52,211,153,0.15); color: #34d399; }
html.dark .status-badge.offline { background: rgba(248,113,113,0.15); color: #f87171; }
.host-subtitle {
  margin-top: 4px;
  font-size: 13px;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 8px;
}
.host-subtitle span + span::before {
  content: '·';
  margin-right: 8px;
  color: var(--text-muted);
}

.detail-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.detail-grid > .card {
  margin-bottom: 0;
}
@media (max-width: 900px) {
  .detail-grid { grid-template-columns: 1fr; }
}

.info-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.info-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 10px;
  background: var(--surface-hover);
  border-radius: 8px;
  font-size: 13px;
  transition: background .2s ease;
}
.info-label { color: var(--text-secondary); }
.info-value { font-weight: 500; color: var(--text); }
.text-muted { color: var(--text-muted); }

.status-pills {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.status-pill {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  background: var(--surface-hover);
  border-radius: 10px;
  transition: background .2s ease;
}
.sp-icon {
  width: 36px; height: 36px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; color: #fff;
  flex-shrink: 0;
}
.sp-icon.cpu { background: linear-gradient(135deg, #3b82f6, #60a5fa); }
.sp-icon.mem { background: linear-gradient(135deg, #22c55e, #4ade80); }
.sp-icon.disk { background: linear-gradient(135deg, #f59e0b, #fbbf24); }
.sp-info { flex: 1; min-width: 0; }
.sp-title { font-size: 12px; color: var(--text-secondary); margin-bottom: 6px; }
.sp-bar { height: 5px; background: var(--border-strong); border-radius: 3px; overflow: hidden; }
.sp-fill { height: 100%; border-radius: 3px; background: #3b82f6; transition: width .3s ease; }
.sp-num { font-size: 14px; font-weight: 700; color: var(--text); min-width: 36px; text-align: right; }

.status-pill.disk-multi { flex-wrap: wrap; }
.multi-disk-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  max-height: 220px;
  overflow-y: auto;
}
.detail-disk-item {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
}
.dd-mount {
  min-width: 50px;
  color: var(--text-secondary);
  font-weight: 500;
}
.dd-bar-wrap {
  flex: 1;
  min-width: 80px;
}
.dd-bar {
  height: 5px;
  background: var(--border-strong);
  border-radius: 3px;
  overflow: hidden;
}
.dd-fill { height: 100%; border-radius: 3px; }
.dd-val { white-space: nowrap; color: var(--text-secondary); }
.dd-pct { min-width: 32px; text-align: right; font-weight: 700; color: var(--text); }

.uptime-line {
  margin-top: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-secondary);
  padding: 8px 10px;
  background: var(--surface-hover);
  border-radius: 8px;
  transition: background .2s ease;
}

.sync-actions {
  margin-bottom: 10px;
}
.ssh-actions {
  margin-bottom: 12px;
}
.ssh-result {
  background: var(--surface-hover);
  border-radius: 10px;
  padding: 12px;
  transition: background .2s ease;
}
.result-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.result-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.result-item.full { grid-column: 1 / -1; }
.rl { font-size: 11px; color: var(--text-muted); }
.rv { font-size: 13px; color: var(--text); font-weight: 500; }

.service-list,
.rel-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.service-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: var(--surface-hover);
  border-radius: 10px;
  flex-wrap: wrap;
  transition: background .2s ease;
}
.service-main {
  display: flex;
  align-items: center;
  gap: 10px;
}
.service-name {
  font-weight: 600;
  font-size: 14px;
}
.service-port {
  font-size: 12px;
  color: var(--text-muted);
  background: var(--surface);
  padding: 1px 6px;
  border-radius: 4px;
  border: 1px solid var(--border);
}
.service-target {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--primary);
}
.target-note {
  color: var(--text-muted);
}
.service-note {
  font-size: 12px;
  color: var(--text-secondary);
  flex: 1 1 100%;
}
.service-actions {
  display: flex;
  gap: 6px;
}

.rel-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: var(--surface-hover);
  border-radius: 10px;
  flex-wrap: wrap;
  transition: background .2s ease;
}
.rel-arrow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}
.rel-host {
  font-weight: 600;
}
.rel-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
}
.rel-port {
  background: var(--surface);
  padding: 1px 6px;
  border-radius: 4px;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
.rel-note {
  color: var(--text-muted);
}
.rel-actions {
  display: flex;
  gap: 6px;
}

.offline-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.stat-box {
  background: var(--surface-hover);
  border-radius: 10px;
  padding: 12px;
  text-align: center;
}
.stat-num {
  font-size: 20px;
  font-weight: 700;
  color: var(--text);
}
.stat-reason {
  font-size: 13px;
  font-weight: 600;
  color: var(--danger);
  word-break: break-all;
}
.stat-label {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 4px;
}

.offline-logs {
  background: var(--surface-hover);
  border-radius: 10px;
  padding: 12px;
}
.log-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 10px;
}
.log-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
}
.log-row:last-child {
  border-bottom: none;
}
.log-time {
  color: var(--text-muted);
  min-width: 140px;
}
.log-reason {
  flex: 1;
  color: var(--text-secondary);
}
.log-dur {
  color: var(--text);
  font-weight: 500;
}
.log-dur.pending {
  color: var(--warning);
}
</style>
