<template>
  <div class="agent-view scanlines">
    <div class="bg-grid"></div>
    <div class="bg-glow"></div>
    <div class="bg-circuit"></div>
    <div class="bg-particles">
      <span v-for="p in bgParticles" :key="p.id" class="bg-particle" :style="p.style"></span>
    </div>

    <div class="view-header">
      <div class="header-title">
        <span class="title-bracket">[</span>
        <span class="title-text">ULTRON COMMAND CENTER</span>
        <span class="title-bracket">]</span>
      </div>
      <div class="header-actions">
        <button class="btn-icon" @click="refreshStats" :class="{ spinning: loading }" title="刷新状态">
          <RefreshCw :size="14" />
        </button>
        <div class="status-bar">
          <span class="status-dot" :class="connectionStatus"></span>
          <span class="status-label">{{ connectionLabel }}</span>
        </div>
      </div>
    </div>

    <div class="command-stage">
      <div class="board-shell holo-card">
        <div class="board-trace trace-1"></div>
        <div class="board-trace trace-2"></div>
        <div class="board-trace trace-3"></div>

        <section class="topology-stage">
          <div class="topology-core-lane">
            <div class="stage-caption">
              <span class="stage-caption-kicker">COMMAND CORE</span>
              <span class="stage-caption-title">战术蓝图主控矩阵</span>
            </div>
            <div
              class="master-chip chip-card topology-master"
              data-testid="agent-chip-master"
              :class="[
                getStatusClass('master'),
                { selected: selectedAgentId === 'master', energized: isAgentEnergized('master') },
              ]"
              @click="selectAgent('master')"
            >
              <div class="chip-shell master-chip-shell">
                <span class="chip-pin pin-top"></span>
                <span class="chip-pin pin-right"></span>
                <span class="chip-pin pin-bottom"></span>
                <span class="chip-pin pin-left"></span>
                <div class="chip-overlay"></div>
                <div class="chip-status-strip">
                  <span class="chip-state-dot" :class="getStatusClass('master')"></span>
                  <span class="chip-state-label">MASTER CORE</span>
                </div>
                <div class="chip-title-row">
                  <div>
                    <div class="chip-code">JRV-PRIME</div>
                    <div class="chip-name">{{ getAgentName('master') }}</div>
                  </div>
                  <div class="chip-runtime">
                    <span class="runtime-tag">{{ activeCommanderSkillId === 'skill_orchestration' ? 'ROUTING' : 'STANDBY' }}</span>
                  </div>
                </div>
                <div class="chip-role">{{ getAgentRole('master') }}</div>
                <div class="chip-desc">{{ getAgentDesc('master') }}</div>
                <div class="chip-footer">
                  <span class="node-stat">
                    <span class="stat-label">调用</span>
                    <span class="stat-val">{{ agentData.master?.callCount || 0 }}</span>
                  </span>
                  <span v-if="agentData.master?.currentTask" class="node-task-tag">{{ agentData.master.currentTask }}</span>
                  <span v-else class="node-idle">总控待命</span>
                </div>

                <div class="route-telemetry" data-testid="route-telemetry">
                  <div class="route-telemetry-header">
                    <span class="route-telemetry-label">ACTIVE ROUTE</span>
                    <span class="route-telemetry-state">{{ activeRouteTelemetry.state }}</span>
                  </div>
                  <div class="route-telemetry-path">
                    <span
                      v-for="segment in activeRouteTelemetry.segments"
                      :key="segment"
                      class="route-segment"
                    >
                      {{ segment }}
                    </span>
                  </div>
                </div>

                <div class="commander-skills embedded-commander-skills" data-testid="commander-skills" @click.stop>
                  <div class="skills-header embedded-skills-header">
                    <div>
                      <div class="skills-eyebrow">COMMANDER MATRIX</div>
                      <div class="skills-title">指挥官技能</div>
                    </div>
                    <div class="skills-badge">{{ activeCommanderSkillId ? 'ENGAGED' : 'STANDBY' }}</div>
                  </div>
                  <div class="skills-grid embedded-skills-grid">
                    <article
                      v-for="skill in commanderSkillsForDisplay"
                      :key="skill.id"
                      :data-testid="`commander-skill-${skill.id}`"
                      class="skill-chip embedded-skill-chip"
                      :class="{ active: skill.active, standby: !skill.active }"
                    >
                      <div class="skill-chip-top">
                        <span class="skill-label">{{ skill.label }}</span>
                        <span class="skill-state">{{ skill.active ? skill.stateLabel : 'STANDBY' }}</span>
                      </div>
                      <div class="skill-title">{{ skill.title }}</div>
                      <div class="skill-description">{{ skill.description }}</div>
                    </article>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div class="topology-trunk" :class="{ energized: !!activeMainAgentId || activeCommanderSkillId === 'skill_orchestration' }">
            <span class="topology-trunk-joint"></span>
            <span class="bus-spine-label">PRIMARY TRUNK</span>
          </div>

          <div class="main-grid-shell">
            <div class="stage-caption bus-caption">
              <span class="stage-caption-kicker">BUS ARRAY</span>
              <span class="stage-caption-title">主 Agent 分层总线</span>
            </div>

            <div class="topology-main-grid">
            <article
              v-for="agentId in MAIN_AGENT_IDS"
              :key="agentId"
              class="topology-column"
              :class="{ expanded: expandedAgentId === agentId }"
            >
              <div class="topology-drop" :class="{ energized: isBranchEnergized(agentId) }">
                <span class="link-joint"></span>
              </div>
              <div
                class="chip-card agent-chip topology-main-chip"
                :data-testid="`agent-chip-${agentId}`"
                :class="[
                  getStatusClass(agentId),
                  { selected: selectedAgentId === agentId, disabled: !localAgents[agentId]?.enabled, energized: isAgentEnergized(agentId) },
                ]"
                @click="selectAgent(agentId)"
              >
                <div class="chip-shell compact">
                  <span class="chip-pin pin-top"></span>
                  <span class="chip-pin pin-right"></span>
                  <span class="chip-pin pin-bottom"></span>
                  <span class="chip-pin pin-left"></span>
                  <div class="chip-overlay"></div>
                  <div class="chip-status-strip">
                    <span class="chip-state-dot" :class="getStatusClass(agentId)"></span>
                    <span class="chip-state-label">{{ getAgentName(agentId) }}</span>
                  </div>
                  <div class="chip-code">{{ getAgentRole(agentId) }}</div>
                  <div class="chip-desc">{{ getAgentDesc(agentId) }}</div>
                  <div class="chip-footer compact-footer">
                    <span class="node-stat">
                      <span class="stat-label">调用</span>
                      <span class="stat-val">{{ agentData[agentId]?.callCount || 0 }}</span>
                    </span>
                    <span v-if="agentData[agentId]?.currentTask" class="node-task-tag">{{ agentData[agentId]?.currentTask }}</span>
                    <span v-else class="node-idle">待机中</span>
                  </div>
                </div>
              </div>

              <div
                class="main-link topology-link-label"
                :data-testid="`bus-link-${agentId}`"
                :class="{ energized: isBranchEnergized(agentId) }"
              >
                <span class="main-link-label">{{ RELATION_LABELS[`master-${agentId}`] }}</span>
              </div>

              <button class="cluster-toggle" @click="toggleCluster(agentId)">
                <span>{{ expandedAgentId === agentId ? '收起子指挥官' : '展开子指挥官' }}</span>
                <span class="toggle-count">{{ getSubCommanders(agentId).length }}</span>
              </button>

              <Transition name="cluster-fade">
                <div v-if="expandedAgentId === agentId" class="sub-cluster topology-sub-cluster">
                  <div
                    v-for="sub in getSubCommanders(agentId)"
                    :key="sub.id"
                    class="sub-node topology-sub-node"
                    :class="getSubCommanderStatus(sub.id)"
                  >
                    <div
                      class="sub-link topology-sub-link"
                      :data-testid="`sub-link-${sub.id}`"
                      :class="{ energized: isBranchEnergized(agentId, sub.id) }"
                    >
                      <span class="link-joint"></span>
                      <span class="sub-link-line"></span>
                      <span class="sub-link-label">{{ sub.relationLabel }}</span>
                    </div>
                    <div class="sub-node-card holo-card" :class="{ energized: isBranchEnergized(agentId, sub.id) }">
                      <div class="sub-node-topline">
                        <span class="sub-name">{{ sub.name }}</span>
                        <span class="sub-badge">{{ sub.toolScopeLabel }}</span>
                      </div>
                      <div class="sub-role">{{ sub.role }}</div>
                      <div class="sub-desc">{{ sub.description }}</div>
                      <div class="sub-footer">
                        <span class="sub-status-dot"></span>
                        <span class="sub-status-text">{{ getSubCommanderTask(sub.id) || getSubCommanderStatusText(sub.id) }}</span>
                      </div>
                    </div>
                  </div>
                </div>
              </Transition>
            </article>
          </div>
          </div>
        </section>
      </div>
    </div>

    <Transition :css="false" @enter="animateIn" @leave="animateOut">
      <div v-if="drawerOpen" class="config-drawer">
        <div class="drawer-header">
          <span class="drawer-title">// AGENT CONFIGURATION</span>
          <button class="btn-close" @click="drawerOpen = false"><X :size="16" /></button>
        </div>
        <div class="drawer-body" v-if="editAgent">
          <div class="form-group">
            <label class="form-label">// AGENT NAME</label>
            <input v-model="editAgent.name" type="text" class="form-input" />
          </div>
          <div class="form-group">
            <label class="form-label">// ROLE</label>
            <input v-model="editAgent.role" type="text" class="form-input" />
          </div>
          <div class="form-group">
            <label class="form-label">// DESCRIPTION</label>
            <textarea v-model="editAgent.description" class="form-textarea" rows="2"></textarea>
          </div>
          <div class="form-group flex-1">
            <label class="form-label">// SYSTEM PROMPT</label>
            <textarea v-model="editAgent.systemPrompt" class="form-textarea code-textarea" rows="10"></textarea>
          </div>
          <div class="form-group">
            <label class="form-label">// STATUS</label>
            <div class="toggle-row">
              <span class="toggle-label" :class="{ dim: editAgent.enabled }">DISABLED</span>
              <button class="toggle-btn" :class="{ active: editAgent.enabled }" @click="editAgent.enabled = !editAgent.enabled">
                <span class="toggle-knob"></span>
              </button>
              <span class="toggle-label" :class="{ dim: !editAgent.enabled }">ENABLED</span>
            </div>
          </div>
          <div class="drawer-actions">
            <button class="btn-secondary" @click="resetConfig">重置</button>
            <button class="btn-primary" @click="saveConfig" :disabled="saving">
              <span v-if="saving" class="btn-loader"></span>
              {{ saving ? '保存中...' : '保存配置' }}
            </button>
          </div>
        </div>
      </div>
    </Transition>

    <Transition :css="false" @enter="fadeIn" @leave="fadeOut">
      <div v-if="drawerOpen" class="drawer-backdrop" @click="drawerOpen = false"></div>
    </Transition>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
import { RefreshCw, X } from 'lucide-vue-next'
import {
  COMMANDER_SKILLS,
  DEFAULT_AGENTS,
  MAIN_AGENT_ORDER,
  RELATION_LABELS,
  SUB_COMMANDERS_BY_PARENT,
  type Agent,
  type MainAgentId,
  type SubCommander,
} from '@/data/agents'
import { agentApi, type AgentHierarchyStats } from '@/api/agent'

const MAIN_AGENT_IDS = MAIN_AGENT_ORDER as Exclude<MainAgentId, 'master'>[]

const bgParticles = Array.from({ length: 60 }, (_, i) => {
  const d = 3 + Math.random() * 5
  const delay = Math.random() * 4
  const o = 0.25 + Math.random() * 0.5
  const size = 1 + Math.random() * 2.5
  return {
    id: i,
    style: {
      left: `${Math.random() * 98}%`,
      top: `${Math.random() * 95}%`,
      width: `${size}px`,
      height: `${size}px`,
      '--d': `${d}s`,
      '--delay': `${delay}s`,
      '--o': String(o),
      opacity: o,
    },
  }
})

type AgentRuntimeState = { callCount: number; currentTask: string | null; status: string }
type SubCommanderRuntimeState = AgentRuntimeState & { parentId: string }
const cleanupFns: Array<() => void> = []
const selectedAgentId = ref<string | null>(null)
const expandedAgentId = ref<Exclude<MainAgentId, 'master'> | null>('planner')
const drawerOpen = ref(false)
const editAgent = ref<{ name: string; role: string; description: string; systemPrompt: string; enabled: boolean } | null>(null)
const saving = ref(false)
const loading = ref(false)
const connectionStatus = ref<'connected' | 'disconnected'>('disconnected')
const connectionLabel = computed(() => connectionStatus.value === 'connected' ? '实时同步' : '离线模式')

const agentData = reactive<Record<string, AgentRuntimeState>>({})
const subCommanderData = reactive<Record<string, SubCommanderRuntimeState>>({})
const localAgents = reactive<Record<string, Agent>>(Object.fromEntries(DEFAULT_AGENTS.map((a) => [a.id, { ...a }])))
const demoMainAgentId = ref<Exclude<MainAgentId, 'master'> | null>(null)
const demoSubCommanderId = ref<string | null>(null)

let pollInterval: ReturnType<typeof setInterval> | null = null
let demoInterval: ReturnType<typeof setInterval> | null = null

function getSubCommanders(agentId: Exclude<MainAgentId, 'master'>): SubCommander[] {
  return SUB_COMMANDERS_BY_PARENT[agentId]
}

function getStatusClass(agentId: string) {
  const data = agentData[agentId]
  const agent = localAgents[agentId]
  if (!agent?.enabled) return 'disabled'
  if (!data) return 'idle'
  return data.status === 'active' ? 'active' : 'idle'
}

function getAgentName(id: string) {
  return localAgents[id]?.name || DEFAULT_AGENTS.find((a) => a.id === id)?.name || id.toUpperCase()
}

function getAgentRole(id: string) {
  return localAgents[id]?.role || DEFAULT_AGENTS.find((a) => a.id === id)?.role || ''
}

function getAgentDesc(id: string) {
  return localAgents[id]?.description || DEFAULT_AGENTS.find((a) => a.id === id)?.description || ''
}

function getSubCommanderStatus(subId: string) {
  const data = subCommanderData[subId]
  if (!data) return 'idle'
  return data.status === 'active' ? 'active' : data.status === 'disabled' ? 'disabled' : 'idle'
}

function getSubCommanderTask(subId: string) {
  return subCommanderData[subId]?.currentTask || null
}

function getSubCommanderStatusText(subId: string) {
  const status = getSubCommanderStatus(subId)
  if (status === 'active') return '子指挥官处理中'
  if (status === 'disabled') return '当前停用'
  return '待命中'
}

function toggleCluster(agentId: Exclude<MainAgentId, 'master'>) {
  expandedAgentId.value = expandedAgentId.value === agentId ? null : agentId
}

function selectAgent(id: string) {
  const agent = localAgents[id]
  if (!agent) return
  selectedAgentId.value = id
  editAgent.value = {
    name: agent.name,
    role: agent.role,
    description: agent.description,
    systemPrompt: agent.systemPrompt,
    enabled: agent.enabled,
  }
  drawerOpen.value = true
}

function resetConfig() {
  const original = DEFAULT_AGENTS.find((a) => a.id === selectedAgentId.value)
  if (original && editAgent.value) {
    Object.assign(editAgent.value, {
      name: original.name,
      role: original.role,
      description: original.description,
      systemPrompt: original.systemPrompt,
      enabled: original.enabled,
    })
  }
}

async function saveConfig() {
  if (!editAgent.value || !selectedAgentId.value) return
  saving.value = true
  try {
    if (localAgents[selectedAgentId.value]) Object.assign(localAgents[selectedAgentId.value], editAgent.value)
    try {
      await agentApi.updateConfig(selectedAgentId.value, {
        name: editAgent.value.name,
        description: editAgent.value.description,
        system_prompt: editAgent.value.systemPrompt,
        enabled: editAgent.value.enabled,
      })
    } catch {
      // fallback to local only
    }
    drawerOpen.value = false
  } finally {
    saving.value = false
  }
}

function applyFlatStats() {
  agentData.master = { callCount: 47, currentTask: '协调主角色与子指挥官', status: 'active' }
  agentData.planner = { callCount: 12, currentTask: null, status: 'idle' }
  agentData.executor = { callCount: 8, currentTask: '推进执行链路', status: 'active' }
  agentData.librarian = { callCount: 5, currentTask: null, status: 'idle' }
  agentData.analyst = { callCount: 3, currentTask: null, status: 'idle' }

  subCommanderData.planner_scope = { parentId: 'planner', callCount: 6, currentTask: null, status: 'idle' }
  subCommanderData.planner_steps = { parentId: 'planner', callCount: 9, currentTask: '拆解执行步骤', status: 'active' }
  subCommanderData.executor_tasks = { parentId: 'executor', callCount: 8, currentTask: '处理任务动作', status: 'active' }
  subCommanderData.executor_forum = { parentId: 'executor', callCount: 4, currentTask: null, status: 'idle' }
  subCommanderData.librarian_retrieval = { parentId: 'librarian', callCount: 5, currentTask: null, status: 'idle' }
  subCommanderData.librarian_graph = { parentId: 'librarian', callCount: 2, currentTask: null, status: 'idle' }
  subCommanderData.analyst_progress = { parentId: 'analyst', callCount: 2, currentTask: null, status: 'idle' }
  subCommanderData.analyst_insights = { parentId: 'analyst', callCount: 3, currentTask: '生成趋势判断', status: 'active' }
}

function applyHierarchyStats(stats: AgentHierarchyStats) {
  agentData.master = { callCount: 47, currentTask: '协调主角色与子指挥官', status: 'active' }
  for (const main of stats.main_agents) {
    agentData[main.agent_id] = {
      callCount: main.call_count,
      currentTask: main.current_task,
      status: main.status,
    }
    for (const child of main.sub_commanders) {
      subCommanderData[child.agent_id] = {
        parentId: main.agent_id,
        callCount: child.call_count,
        currentTask: child.current_task,
        status: child.status,
      }
    }
  }
}

function getDemoSequence() {
  return MAIN_AGENT_IDS.flatMap((agentId) => {
    const subs = getSubCommanders(agentId)
    return subs.length > 0
      ? subs.map((sub) => ({ mainId: agentId, subId: sub.id }))
      : [{ mainId: agentId, subId: null }]
  })
}

function setDemoPath(mainId: Exclude<MainAgentId, 'master'> | null, subId: string | null) {
  demoMainAgentId.value = mainId
  demoSubCommanderId.value = subId
  if (mainId) {
    expandedAgentId.value = mainId
  }
}

function startDemoCircuit() {
  if (demoInterval) return
  const sequence = getDemoSequence()
  if (sequence.length === 0) return
  let index = 0
  const applyStep = () => {
    const current = sequence[index % sequence.length]
    setDemoPath(current.mainId, current.subId)
    index += 1
  }
  applyStep()
  demoInterval = setInterval(applyStep, 1600)
}

function stopDemoCircuit() {
  if (demoInterval) {
    clearInterval(demoInterval)
    demoInterval = null
  }
  setDemoPath(null, null)
}

const activeSubCommanderId = computed(() => {
  const realActive = Object.entries(subCommanderData).find(([, data]) => data.status === 'active')?.[0] ?? null
  return connectionStatus.value === 'connected' ? realActive : (demoSubCommanderId.value ?? realActive)
})
const activeMainAgentId = computed<Exclude<MainAgentId, 'master'> | null>(() => {
  if (connectionStatus.value !== 'connected' && demoMainAgentId.value) {
    return demoMainAgentId.value
  }
  const activeMain = MAIN_AGENT_IDS.find((agentId) => agentData[agentId]?.status === 'active')
  if (activeMain) return activeMain
  if (activeSubCommanderId.value) {
    const parentId = subCommanderData[activeSubCommanderId.value]?.parentId
    if (parentId && MAIN_AGENT_IDS.includes(parentId as Exclude<MainAgentId, 'master'>)) {
      return parentId as Exclude<MainAgentId, 'master'>
    }
  }
  return agentData.master?.status === 'active' ? 'planner' : null
})


const activeCommanderSkillId = computed(() => {
  if (activeSubCommanderId.value) {
    return COMMANDER_SKILLS.find((skill) => skill.relatedAgentIds.includes(activeSubCommanderId.value as string))?.id ?? null
  }
  if (activeMainAgentId.value) {
    return COMMANDER_SKILLS.find((skill) => skill.relatedAgentIds.includes(activeMainAgentId.value as string))?.id ?? null
  }
  return agentData.master?.status === 'active' ? 'skill_orchestration' : null
})

const commanderSkillsForDisplay = computed(() => COMMANDER_SKILLS.map((skill) => ({
  ...skill,
  active: skill.id === activeCommanderSkillId.value,
})))

const activeRouteTelemetry = computed(() => {
  const segments = ['JARVIS']

  if (activeMainAgentId.value) {
    segments.push(getAgentName(activeMainAgentId.value))
  }

  if (activeSubCommanderId.value) {
    const activeSub = Object.values(SUB_COMMANDERS_BY_PARENT)
      .flat()
      .find((item) => item.id === activeSubCommanderId.value)
    if (activeSub) {
      segments.push(activeSub.name)
    }
  }

  return {
    segments,
    state: activeCommanderSkillId.value ? 'ENGAGED' : 'STANDBY',
  }
})

function isAgentEnergized(agentId: string) {
  if (agentId === 'master') return agentData.master?.status === 'active' || !!activeMainAgentId.value || !!activeSubCommanderId.value
  if (activeSubCommanderId.value) {
    return agentId === activeMainAgentId.value || agentId === activeSubCommanderId.value
  }
  return agentId === activeMainAgentId.value
}

function isBranchEnergized(parentId: string, subId?: string) {
  if (subId) return activeSubCommanderId.value === subId
  return activeMainAgentId.value === parentId || (agentData.master?.status === 'active' && activeCommanderSkillId.value === 'skill_orchestration' && parentId === 'planner')
}

async function refreshStats() {
  loading.value = true
  try {
    const stats = await agentApi.getHierarchyStats()
    applyHierarchyStats(stats)
    connectionStatus.value = 'connected'
    stopDemoCircuit()
  } catch {
    applyFlatStats()
    connectionStatus.value = 'disconnected'
    startDemoCircuit()
  } finally {
    loading.value = false
  }
}

function runTransition(
  el: Element,
  keyframes: Keyframe[],
  options: KeyframeAnimationOptions,
  done?: () => void,
) {
  const animation = (el as HTMLElement).animate(keyframes, { fill: 'forwards', ...options })
  const finish = () => done?.()
  animation.addEventListener('finish', finish, { once: true })
  cleanupFns.push(() => animation.cancel())
  return animation
}

function animateIn(el: Element, done: () => void) {
  runTransition(
    el,
    [{ opacity: 0, transform: 'translateX(80px)' }, { opacity: 1, transform: 'translateX(0)' }],
    { duration: 350, easing: 'cubic-bezier(0.4, 0, 0.2, 1)' },
    done,
  )
}

function animateOut(el: Element, done: () => void) {
  runTransition(
    el,
    [{ opacity: 1, transform: 'translateX(0)' }, { opacity: 0, transform: 'translateX(80px)' }],
    { duration: 250, easing: 'cubic-bezier(0.4, 0, 1, 1)' },
    done,
  )
}

function fadeIn(el: Element, done: () => void) {
  runTransition(el, [{ opacity: 0 }, { opacity: 1 }], { duration: 250 }, done)
}

function fadeOut(el: Element, done: () => void) {
  runTransition(el, [{ opacity: 1 }, { opacity: 0 }], { duration: 200 }, done)
}

onMounted(async () => {
  await refreshStats()
  pollInterval = setInterval(refreshStats, 5000)
})

onUnmounted(() => {
  if (pollInterval) clearInterval(pollInterval)
  stopDemoCircuit()
  cleanupFns.forEach((cleanup) => cleanup())
})
</script>

<style scoped>
.agent-view {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: auto;
  position: relative;
  background:
    radial-gradient(circle at top, rgba(0, 245, 212, 0.07), transparent 34%),
    linear-gradient(180deg, #03050a 0%, #07101a 35%, #03050a 100%);
}

.bg-grid,
.bg-glow,
.bg-circuit,
.bg-particles {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.bg-grid {
  background-image:
    linear-gradient(rgba(0, 245, 212, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 245, 212, 0.04) 1px, transparent 1px);
  background-size: 40px 40px;
}

.bg-glow {
  background:
    radial-gradient(circle at 20% 20%, rgba(0, 245, 212, 0.08), transparent 26%),
    radial-gradient(circle at 80% 14%, rgba(123, 44, 191, 0.08), transparent 22%),
    radial-gradient(circle at 50% 70%, rgba(0, 245, 212, 0.05), transparent 30%);
}

.bg-circuit {
  opacity: 0.5;
  background-image:
    linear-gradient(90deg, transparent 12%, rgba(0, 245, 212, 0.08) 12%, rgba(0, 245, 212, 0.08) 12.4%, transparent 12.4%),
    linear-gradient(transparent 20%, rgba(0, 245, 212, 0.06) 20%, rgba(0, 245, 212, 0.06) 20.5%, transparent 20.5%),
    radial-gradient(circle at 12% 20%, rgba(0, 245, 212, 0.25) 0 2px, transparent 3px),
    radial-gradient(circle at 88% 36%, rgba(0, 245, 212, 0.22) 0 2px, transparent 3px),
    radial-gradient(circle at 58% 68%, rgba(0, 245, 212, 0.18) 0 2px, transparent 3px);
}

.bg-particle {
  position: absolute;
  border-radius: 50%;
  background: var(--accent-cyan);
  box-shadow: 0 0 4px rgba(0,245,212,0.6), 0 0 8px rgba(0,245,212,0.2);
  animation: star-twinkle var(--d, 4s) ease-in-out infinite var(--delay, 0s);
}

@keyframes star-twinkle {
  0%, 100% { opacity: var(--o, 0.4); transform: scale(1); }
  50% { opacity: calc(var(--o, 0.4) * 0.3); transform: scale(0.45); }
}

.view-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 24px;
  border-bottom: 1px solid var(--border-dim);
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(5,8,16,0.72);
  backdrop-filter: blur(8px);
}

.header-title {
  font-family: var(--font-display);
  font-size: 13px;
  letter-spacing: 0.2em;
  color: var(--text-primary);
}

.title-bracket {
  color: var(--accent-cyan);
  opacity: 0.6;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.btn-icon {
  width: 32px;
  height: 32px;
  border-radius: 10px;
  border: 1px solid var(--border-dim);
  background: rgba(255,255,255,0.02);
  color: var(--accent-cyan);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.btn-icon.spinning svg {
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.status-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--border-dim);
  border-radius: 999px;
  background: rgba(255,255,255,0.02);
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  box-shadow: 0 0 8px currentColor;
}

.status-dot.connected {
  background: var(--accent-green);
  color: var(--accent-green);
}

.status-dot.disconnected {
  background: var(--accent-amber);
  color: var(--accent-amber);
}

.status-label {
  font-size: 11px;
  color: var(--text-secondary);
  letter-spacing: 0.08em;
}

.command-stage {
  position: relative;
  z-index: 1;
  padding: 18px 20px 22px;
}

.board-shell {
  position: relative;
  overflow: hidden;
  padding: 18px 18px 20px;
  border-radius: 24px;
  border: 1px solid rgba(0, 245, 212, 0.12);
  background:
    linear-gradient(180deg, rgba(8, 14, 24, 0.95), rgba(3, 8, 16, 0.96)),
    linear-gradient(135deg, rgba(0, 245, 212, 0.03), transparent 35%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 24px 60px rgba(0,0,0,0.32), 0 0 24px rgba(0,245,212,0.05);
}

.board-shell::before,
.board-shell::after {
  content: '';
  position: absolute;
  inset: 14px;
  border: 1px solid rgba(0, 245, 212, 0.07);
  border-radius: 22px;
  pointer-events: none;
}

.board-shell::after {
  inset: auto 28px 28px auto;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  filter: blur(12px);
  background: radial-gradient(circle, rgba(0, 245, 212, 0.16), transparent 70%);
  border: none;
}

.board-trace {
  position: absolute;
  background: linear-gradient(90deg, transparent, rgba(0,245,212,0.12), transparent);
  opacity: 0.6;
}

.trace-1 { top: 96px; left: 10%; width: 22%; height: 1px; }
.trace-2 { top: 240px; right: 8%; width: 18%; height: 1px; }
.trace-3 { bottom: 120px; left: 6%; width: 16%; height: 1px; }

.topology-stage {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.stage-caption {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 auto 12px;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid rgba(0,245,212,0.12);
  background: linear-gradient(90deg, rgba(3,8,16,0.78), rgba(7,14,24,0.9));
  box-shadow: 0 0 18px rgba(0,245,212,0.06);
}

.stage-caption-kicker {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-cyan);
}

.stage-caption-title {
  font-size: 12px;
  letter-spacing: 0.12em;
  color: var(--text-secondary);
}

.bus-caption {
  margin-bottom: 18px;
}

.topology-core-lane {
  display: block;
}

.master-chip-shell {
  min-height: 0;
  background:
    linear-gradient(180deg, rgba(9,15,28,0.2), transparent 28%),
    radial-gradient(circle at top center, rgba(0,245,212,0.08), transparent 40%);
}

.topology-master {
  justify-self: center;
  width: min(720px, 100%);
  margin: 0 auto;
}

.topology-master::before,
.topology-master::after {
  content: '';
  position: absolute;
  pointer-events: none;
}

.topology-master::before {
  inset: -10px 6%;
  border-radius: 32px;
  border: 1px solid rgba(0,245,212,0.08);
  opacity: 0.8;
}

.topology-master::after {
  inset: auto 12% -14px 12%;
  height: 24px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(0,245,212,0.24), transparent 72%);
  filter: blur(10px);
}

.embedded-commander-skills {
  position: relative;
  margin-top: 8px;
  padding: 12px;
  border-radius: 16px;
  border: 1px solid rgba(0,245,212,0.12);
  background:
    linear-gradient(180deg, rgba(8,14,24,0.68), rgba(4,8,16,0.88)),
    repeating-linear-gradient(90deg, rgba(0,245,212,0.03) 0 1px, transparent 1px 18px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.03), 0 0 18px rgba(0,245,212,0.05);
}

.embedded-commander-skills::before {
  content: '';
  position: absolute;
  left: 16px;
  right: 16px;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(0,245,212,0.55), transparent);
}

.embedded-skills-header {
  margin-bottom: 10px;
}

.embedded-skills-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-top: 0;
}

.embedded-skill-chip {
  min-height: 84px;
  padding: 10px;
  background: linear-gradient(180deg, rgba(10,16,28,0.92), rgba(6,10,18,0.98));
}

.embedded-skill-chip .skill-title {
  font-size: 12px;
}

.embedded-skill-chip .skill-description {
  font-size: 10px;
  line-height: 1.45;
}

.topology-trunk {
  position: relative;
  width: 4px;
  height: 70px;
  margin: -4px auto 0;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(0,245,212,0.15), rgba(0,245,212,0.7), rgba(0,245,212,0.12));
  box-shadow: 0 0 16px rgba(0,245,212,0.12);
}

.main-grid-shell {
  position: relative;
  padding: 20px 18px 10px;
  border-radius: 24px;
  border: 1px solid rgba(0,245,212,0.08);
  background:
    linear-gradient(180deg, rgba(4,9,18,0.84), rgba(3,7,14,0.95)),
    radial-gradient(circle at top center, rgba(0,245,212,0.08), transparent 42%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.03), 0 20px 44px rgba(0,0,0,0.22);
}

.main-grid-shell::before,
.main-grid-shell::after {
  content: '';
  position: absolute;
  pointer-events: none;
}

.main-grid-shell::before {
  inset: 12px;
  border-radius: 20px;
  border: 1px solid rgba(0,245,212,0.06);
}

.main-grid-shell::after {
  left: 24px;
  right: 24px;
  top: 62px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(0,245,212,0.3), transparent);
}

.topology-trunk::before,
.topology-trunk::after,
.topology-drop::before,
.topology-drop::after,
.topology-sub-link .sub-link-line::before,
.topology-sub-link .sub-link-line::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.topology-trunk-joint {
  position: absolute;
  left: 50%;
  bottom: -8px;
  width: 14px;
  height: 14px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: rgba(0,245,212,0.78);
  box-shadow: 0 0 18px rgba(0,245,212,0.55), 0 0 34px rgba(0,245,212,0.22);
}

.topology-trunk.energized::before,
.topology-drop.energized::before,
.topology-sub-link.energized .sub-link-line::before {
  border-radius: inherit;
  background: linear-gradient(180deg, transparent 0%, rgba(255,255,255,0.2) 20%, rgba(130,255,245,0.98) 42%, rgba(0,245,212,1) 50%, rgba(130,255,245,0.98) 58%, rgba(255,255,255,0.14) 78%, transparent 100%);
  animation: current-vertical 1.15s linear infinite;
}

.topology-trunk.energized::after,
.topology-drop.energized::after,
.topology-sub-link.energized .sub-link-line::after {
  border-radius: inherit;
  background: linear-gradient(180deg, transparent 0%, rgba(0,245,212,0.08) 20%, rgba(0,245,212,0.5) 50%, rgba(0,245,212,0.08) 80%, transparent 100%);
  filter: blur(6px);
  animation: current-trail-vertical 1.15s linear infinite;
}

.topology-main-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(190px, 1fr));
  gap: 14px;
  align-items: start;
}

.topology-main-grid::after {
  content: '';
  position: absolute;
  left: 8%;
  right: 8%;
  top: 10px;
  height: 44px;
  border: 1px solid rgba(0,245,212,0.06);
  border-bottom: none;
  border-radius: 20px 20px 0 0;
  pointer-events: none;
}

.topology-main-grid::before {
  content: '';
  position: absolute;
  left: 12.5%;
  right: 12.5%;
  top: 10px;
  height: 3px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(0,245,212,0.18), rgba(0,245,212,0.68), rgba(0,245,212,0.18));
  box-shadow: 0 0 18px rgba(0,245,212,0.12);
}

.topology-column {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
}

.topology-drop {
  position: relative;
  width: 3px;
  height: 46px;
  margin: 0 auto;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(0,245,212,0.6), rgba(0,245,212,0.08));
}

.topology-drop .link-joint {
  position: absolute;
  left: 50%;
  top: -6px;
  transform: translateX(-50%);
}

.topology-main-chip {
  width: 100%;
}

.topology-link-label {
  justify-content: center;
  min-height: 18px;
}

.topology-link-label.energized .main-link-label {
  color: var(--accent-cyan);
  text-shadow: 0 0 10px rgba(0,245,212,0.35);
}

.topology-sub-cluster {
  display: grid;
  gap: 12px;
}

.topology-sub-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.topology-sub-link {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.topology-sub-link .link-joint {
  width: 9px;
  height: 9px;
}

.topology-sub-link .sub-link-line {
  width: 3px;
  min-width: 3px;
  min-height: 42px;
  height: 42px;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(0,245,212,0.6), rgba(0,245,212,0.08));
}

.topology-sub-link .sub-link-label {
  text-align: center;
  white-space: normal;
}

.topology-skills-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.chip-card {
  position: relative;
  border-radius: 20px;
  border: 1px solid rgba(0, 245, 212, 0.16);
  background:
    linear-gradient(180deg, rgba(9, 14, 26, 0.95), rgba(5, 9, 16, 0.98)),
    linear-gradient(135deg, rgba(255,255,255,0.02), transparent 55%);
  overflow: hidden;
  transition: transform var(--transition-mid), border-color var(--transition-mid), box-shadow var(--transition-mid);
}

.chip-card:hover {
  transform: translateY(-2px);
  border-color: rgba(0, 245, 212, 0.28);
  box-shadow: 0 14px 34px rgba(0,0,0,0.24), 0 0 18px rgba(0,245,212,0.08);
}

.chip-card.selected,
.chip-card.energized {
  border-color: rgba(0, 245, 212, 0.46);
  box-shadow: 0 0 0 1px rgba(0,245,212,0.18) inset, 0 0 24px rgba(0,245,212,0.15);
}

.chip-card.energized {
  box-shadow:
    0 0 0 1px rgba(0,245,212,0.22) inset,
    0 0 18px rgba(0,245,212,0.18),
    0 0 42px rgba(0,245,212,0.16),
    0 0 70px rgba(0,245,212,0.07);
}

.chip-card.disabled {
  opacity: 0.48;
  filter: saturate(0.5);
}

.chip-shell {
  position: relative;
  min-height: 212px;
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.chip-shell.compact {
  min-height: 168px;
}

.topology-main-chip .chip-shell.compact {
  min-height: 182px;
  padding-top: 20px;
}

.chip-pin {
  position: absolute;
  opacity: 0.45;
}

.pin-top,
.pin-bottom {
  left: 24px;
  right: 24px;
  height: 8px;
  background: repeating-linear-gradient(90deg, rgba(0,245,212,0.2) 0 10px, transparent 10px 18px);
}

.pin-top { top: 0; }
.pin-bottom { bottom: 0; }

.pin-left,
.pin-right {
  top: 24px;
  bottom: 24px;
  width: 8px;
  background: repeating-linear-gradient(180deg, rgba(0,245,212,0.2) 0 10px, transparent 10px 18px);
}

.pin-left { left: 0; }
.pin-right { right: 0; }

.chip-overlay {
  position: absolute;
  inset: 12px;
  border-radius: 18px;
  border: 1px solid rgba(0, 245, 212, 0.08);
  background:
    linear-gradient(135deg, rgba(255,255,255,0.04), transparent 34%),
    linear-gradient(180deg, transparent, rgba(0,245,212,0.04));
  pointer-events: none;
}

.chip-overlay::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(120deg, transparent 10%, rgba(0,245,212,0.15) 45%, transparent 70%);
  transform: translateX(-120%);
  animation: chip-scan 6s linear infinite;
}

@keyframes chip-scan {
  to { transform: translateX(120%); }
}

@keyframes node-flicker {
  0%, 100% {
    transform: scale(1);
    opacity: 0.92;
  }
  50% {
    transform: scale(1.22);
    opacity: 1;
  }
}

.chip-status-strip,
.chip-title-row,
.chip-footer,
.skills-header,
.skill-chip-top,
.sub-node-topline,
.sub-footer,
.drawer-header,
.toggle-row,
.drawer-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.chip-state-dot,
.sub-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 10px currentColor;
}

.chip-state-dot.active,
.sub-node.active .sub-status-dot { color: var(--accent-green); }
.chip-state-dot.idle,
.sub-node.idle .sub-status-dot { color: var(--accent-cyan); }
.chip-state-dot.disabled,
.sub-node.disabled .sub-status-dot { color: var(--text-dim); }

.chip-state-label,
.skills-eyebrow,
.skill-label,
.sub-name,
.drawer-title {
  font-family: var(--font-display);
  letter-spacing: 0.16em;
}

.chip-state-label,
.skills-eyebrow,
.skill-label {
  font-size: 11px;
  color: var(--accent-cyan);
}

.chip-code,
.runtime-tag,
.skills-badge,
.skill-state,
.main-link-label,
.sub-link-label,
.sub-badge,
.node-task-tag,
.node-idle,
.toggle-count {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.chip-code {
  color: var(--text-dim);
}

.chip-name,
.skills-title,
.skill-title {
  color: var(--text-primary);
  font-weight: 700;
}

.chip-name {
  font-size: 22px;
  letter-spacing: 0.08em;
}

.skills-title {
  font-size: 16px;
}

.chip-role,
.skill-state,
.sub-role {
  color: var(--accent-purple);
}

.chip-desc,
.skill-description,
.sub-desc {
  color: var(--text-secondary);
  line-height: 1.65;
}

.runtime-tag,
.skills-badge,
.skill-state,
.sub-badge,
.node-task-tag,
.node-idle,
.toggle-count {
  padding: 4px 8px;
  border-radius: 999px;
}

.runtime-tag,
.skills-badge,
.node-task-tag {
  background: rgba(0,245,212,0.1);
  color: var(--accent-cyan);
}

.node-idle {
  background: rgba(255,255,255,0.04);
  color: var(--text-dim);
}

.node-stat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border-radius: 999px;
  background: rgba(255,255,255,0.04);
  color: var(--text-secondary);
  font-size: 11px;
}

.stat-label { color: var(--text-dim); }
.stat-val { color: var(--accent-cyan); }

.route-telemetry {
  position: relative;
  padding: 12px 14px;
  border-radius: 16px;
  border: 1px solid rgba(0,245,212,0.14);
  background:
    linear-gradient(180deg, rgba(7,12,22,0.92), rgba(4,8,16,0.98)),
    radial-gradient(circle at left center, rgba(0,245,212,0.08), transparent 45%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.03), 0 0 18px rgba(0,245,212,0.06);
}

.route-telemetry::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, transparent 0%, rgba(0,245,212,0.08) 30%, transparent 70%);
  transform: translateX(-100%);
  animation: telemetry-scan 4s linear infinite;
  pointer-events: none;
}

.route-telemetry-header,
.route-telemetry-path {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.route-telemetry-header {
  justify-content: space-between;
  margin-bottom: 8px;
}

.route-telemetry-label,
.route-telemetry-state {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.route-telemetry-label {
  color: var(--text-dim);
}

.route-telemetry-state {
  padding: 4px 8px;
  border-radius: 999px;
  color: var(--accent-cyan);
  background: rgba(0,245,212,0.1);
}

.route-segment {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid rgba(0,245,212,0.12);
  background: rgba(255,255,255,0.03);
  color: var(--text-primary);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.route-segment:not(:last-child)::after {
  content: '→';
  position: relative;
  right: -4px;
  color: rgba(0,245,212,0.72);
}

@keyframes telemetry-scan {
  to { transform: translateX(100%); }
}

.commander-skills {
  padding: 18px;
  border-radius: 24px;
  border: 1px solid rgba(0, 245, 212, 0.12);
  background: linear-gradient(180deg, rgba(8, 14, 24, 0.9), rgba(4, 8, 16, 0.96));
}

.skills-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 16px;
}

.skill-chip {
  position: relative;
  min-height: 118px;
  border-radius: 18px;
  border: 1px solid rgba(0,245,212,0.1);
  background: linear-gradient(180deg, rgba(9,16,28,0.9), rgba(6,10,18,0.96));
  padding: 14px;
  overflow: hidden;
}

.skill-chip::before,
.main-link-line::before,
.sub-link-line::before,
.bus-spine::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.skill-chip::before {
  background: linear-gradient(120deg, transparent 0%, rgba(0,245,212,0.08) 45%, transparent 65%);
  transform: translateX(-140%);
}

.skill-chip.active {
  border-color: rgba(0,245,212,0.4);
  box-shadow: 0 0 22px rgba(0,245,212,0.12), inset 0 0 0 1px rgba(0,245,212,0.12);
}

.skill-chip.active::before {
  animation: skill-sweep 2.8s linear infinite;
}

@keyframes skill-sweep {
  to { transform: translateX(140%); }
}


.link-joint {
  width: 8px;
  height: 8px;
  min-width: 8px;
  border-radius: 50%;
  background: rgba(0,245,212,0.65);
  box-shadow: 0 0 10px rgba(0,245,212,0.35);
}

.pcb-link.energized .link-joint {
  background: #9ffef4;
  box-shadow: 0 0 12px rgba(159,254,244,0.9), 0 0 24px rgba(0,245,212,0.55), 0 0 40px rgba(0,245,212,0.28);
  animation: node-flicker 0.9s ease-in-out infinite;
}

.main-link-line,
.sub-link-line {
  position: relative;
  flex: 1;
  overflow: hidden;
}

.main-link-line {
  height: 3px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(0,245,212,0.6), rgba(0,245,212,0.08));
}

.sub-link-line {
  width: 3px;
  min-width: 3px;
  min-height: 34px;
  background: linear-gradient(180deg, rgba(0,245,212,0.6), rgba(0,245,212,0.08));
}

.main-link-label,
.sub-link-label {
  color: var(--text-dim);
  white-space: nowrap;
}

.agent-chip .chip-name {
  font-size: 22px;
}

.compact-footer {
  margin-top: auto;
  align-items: flex-start;
  flex-wrap: wrap;
}

.cluster-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  border: 1px solid rgba(0,245,212,0.12);
  border-radius: 12px;
  padding: 10px 12px;
  background: rgba(5,10,18,0.72);
  color: var(--text-secondary);
  font-size: 11px;
  letter-spacing: 0.08em;
}

.toggle-count {
  background: rgba(0,245,212,0.08);
  color: var(--accent-cyan);
}

.sub-cluster {
  display: grid;
  gap: 12px;
}

.sub-node {
  display: flex;
  gap: 10px;
  align-items: stretch;
}

.sub-node-card {
  flex: 1;
  border-radius: 16px;
  border: 1px solid rgba(0,245,212,0.1);
  background: rgba(10,14,24,0.9);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sub-node-card.energized,
.sub-node.active .sub-node-card {
  border-color: rgba(0,245,212,0.3);
  box-shadow: 0 0 18px rgba(0,245,212,0.1);
}

.sub-node.disabled .sub-node-card {
  opacity: 0.5;
}

.sub-name { color: var(--accent-cyan); font-size: 11px; }
.sub-badge { background: rgba(123, 44, 191, 0.14); color: var(--accent-purple); }
.sub-role { font-size: 12px; font-weight: 600; }
.sub-footer { font-size: 11px; color: var(--text-dim); margin-top: auto; justify-content: flex-start; }

.cluster-fade-enter-active,
.cluster-fade-leave-active {
  transition: opacity 0.22s ease, transform 0.22s ease;
}

.cluster-fade-enter-from,
.cluster-fade-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}

.config-drawer {
  position: fixed;
  top: 0;
  right: 0;
  width: min(420px, 100%);
  height: 100%;
  background: linear-gradient(180deg, rgba(9, 13, 23, 0.98), rgba(5, 8, 16, 0.98));
  border-left: 1px solid rgba(0,245,212,0.14);
  z-index: 30;
  display: flex;
  flex-direction: column;
}

.drawer-header {
  padding: 18px 18px 14px;
  border-bottom: 1px solid var(--border-dim);
}

.drawer-title {
  font-size: 12px;
  color: var(--accent-cyan);
}

.btn-close {
  width: 32px;
  height: 32px;
  border-radius: 10px;
  border: 1px solid var(--border-dim);
  background: transparent;
  color: var(--text-secondary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.drawer-body {
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 0;
  flex: 1;
}

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

.flex-1 {
  flex: 1;
}

.form-label {
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--text-dim);
}

.form-input,
.form-textarea {
  width: 100%;
  border-radius: 12px;
  border: 1px solid var(--border-dim);
  background: rgba(255,255,255,0.03);
  color: var(--text-primary);
  padding: 10px 12px;
}

.code-textarea {
  font-family: var(--font-mono);
}

.toggle-label {
  font-size: 11px;
  color: var(--text-secondary);
}

.toggle-label.dim {
  opacity: 0.45;
}

.toggle-btn {
  width: 50px;
  height: 28px;
  border-radius: 999px;
  border: 1px solid var(--border-dim);
  background: rgba(255,255,255,0.04);
  position: relative;
}

.toggle-btn.active {
  background: rgba(0,245,212,0.12);
  border-color: rgba(0,245,212,0.2);
}

.toggle-knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  background: var(--text-primary);
  transition: transform 0.2s ease;
}

.toggle-btn.active .toggle-knob {
  transform: translateX(22px);
  background: var(--accent-cyan);
}

.btn-secondary,
.btn-primary {
  border-radius: 12px;
  padding: 10px 14px;
  border: 1px solid var(--border-dim);
}

.btn-secondary {
  background: rgba(255,255,255,0.03);
  color: var(--text-secondary);
}

.btn-primary {
  background: rgba(0,245,212,0.12);
  border-color: rgba(0,245,212,0.24);
  color: var(--accent-cyan);
}

.btn-loader {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 999px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  animation: spin 0.9s linear infinite;
  margin-right: 6px;
}

.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.45);
  z-index: 20;
}

@media (max-width: 1400px) {
  .command-stage { padding: 20px 18px 28px; }
  .topology-main-grid {
    grid-template-columns: repeat(2, minmax(240px, 1fr));
  }
}

@media (max-width: 1100px) {
  .embedded-skills-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 860px) {
  .view-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .header-actions {
    width: 100%;
    justify-content: space-between;
  }

  .command-stage {
    padding: 16px 14px 26px;
  }

  .board-shell {
    padding: 16px;
  }

  .topology-main-grid,
  .embedded-skills-grid {
    grid-template-columns: 1fr;
  }

  .topology-main-grid::before {
    left: 50%;
    right: auto;
    top: 0;
    width: 3px;
    height: calc(100% - 12px);
    transform: translateX(-50%);
    background: linear-gradient(180deg, rgba(0,245,212,0.18), rgba(0,245,212,0.68), rgba(0,245,212,0.18));
  }
}

@media (prefers-reduced-motion: reduce) {
  .bg-particle,
  .chip-overlay::after,
  .skill-chip.active::before,
  .bus-spine.energized::before,
  .main-link.energized .main-link-line::before,
  .sub-link.energized .sub-link-line::before {
    animation: none !important;
  }
}
</style>
