← back to Dw War Room

src/panels/HudOverlay.ts

898 lines

// ═══════════════════════════════════════════════
// DW War Room 3D — HUD Overlay (Figma Design System)
// Professional glassmorphism command center overlay
// Design tokens: --ds-* CSS custom properties
// Stock Trader UI Kit inspired dark dashboard
// ═══════════════════════════════════════════════

import type { AgentNode, DecisionStats, GovernanceStatus, MeetingState, EscalationAlert, SystemHealth, FeedItem } from '../types';

const PHASE_LABELS: Record<string, string> = {
  caucus: 'Caucus', call_to_order: 'Call to Order', old_business: 'Old Business',
  current_business: 'Current Business', new_business: 'New Business',
  breakout: 'Breakout', minutes: 'Minutes', adjournment: 'Adjournment',
};

// Design token references for dynamic JS styling
// Uses CSS custom property syntax so values resolve at render time
const DS = {
  success: 'var(--ds-success)',
  warning: 'var(--ds-warning)',
  error: 'var(--ds-error)',
  info: 'var(--ds-info)',
  violet: 'var(--ds-violet)',
  cyan: 'var(--ds-cyan)',
  gray100: 'var(--ds-gray-100)',
  gray400: 'var(--ds-gray-400)',
  gray500: 'var(--ds-gray-500)',
};

export class HudOverlay {
  private container: HTMLElement;
  private tooltipTimeout: ReturnType<typeof setTimeout> | null = null;

  constructor(parent: HTMLElement) {
    this.container = document.createElement('div');
    this.container.id = 'war-room-hud';
    this.buildDom();
    parent.appendChild(this.container);
    this.applyStyles();
  }

  /* ───────────────────────────────────────────
   * DOM Construction — uses safe DOM methods
   * ─────────────────────────────────────────── */
  private buildDom(): void {
    const root = this.container;

    // ── Header ──
    const header = this.el('div', 'hud-header');
    const headerLeft = this.el('div', 'hud-header-left');
    headerLeft.appendChild(this.el('span', 'hud-logo-pulse'));
    const title = this.el('span', 'hud-title');
    title.textContent = 'DW WAR ROOM';
    headerLeft.appendChild(title);
    header.appendChild(headerLeft);

    const statusGroup = this.el('div', 'hud-status-group');
    const statusDot = this.el('span', 'hud-status-dot');
    statusDot.id = 'hud-status-dot';
    statusGroup.appendChild(statusDot);
    const statusText = this.el('span', 'hud-status');
    statusText.id = 'hud-connection';
    statusText.textContent = 'CONNECTING...';
    statusGroup.appendChild(statusText);
    const govMode = this.el('span', 'hud-governance-mode');
    govMode.id = 'hud-gov-mode';
    statusGroup.appendChild(govMode);
    header.appendChild(statusGroup);
    root.appendChild(header);

    // ── Meeting Panel ──
    root.appendChild(this.buildPanel(
      'hud-meeting', 'hud-top-left accent-violet', 'MEETING STATUS',
      'hud-meeting-content', 'No active meeting'
    ));

    // ── Decisions Panel ──
    root.appendChild(this.buildPanel(
      'hud-decisions', 'hud-top-right accent-cyan', 'DECISIONS',
      'hud-decisions-content', 'Loading...'
    ));

    // ── Live Feed Panel ──
    const feedPanel = this.buildPanel(
      'hud-feed', 'hud-bottom-left accent-amber', 'LIVE FEED',
      'hud-feed-content', ''
    );
    // Add feed count badge to title
    const feedTitle = feedPanel.querySelector('.hud-panel-title');
    if (feedTitle) {
      const badge = this.el('span', 'hud-feed-badge');
      badge.id = 'hud-feed-count';
      feedTitle.appendChild(badge);
    }
    // Add scroll class to body
    const feedBody = feedPanel.querySelector('.hud-panel-body');
    if (feedBody) feedBody.classList.add('hud-feed-scroll');
    root.appendChild(feedPanel);

    // ── Escalations Panel ──
    root.appendChild(this.buildPanel(
      'hud-escalations', 'hud-bottom-right accent-red', 'ESCALATIONS',
      'hud-escalations-content', 'None active'
    ));

    // ── System Health Panel ──
    const healthPanel = this.buildPanel(
      'hud-health', 'hud-mid-right accent-emerald', 'SYSTEM HEALTH',
      'hud-health-content', ''
    );
    const healthBody = healthPanel.querySelector('.hud-panel-body')!;
    ['CPU', 'MEMORY', 'SERVICES', 'UPTIME'].forEach(label => {
      const row = this.el('div', 'hud-metric');
      const lbl = this.el('span', 'hud-metric-label');
      lbl.textContent = label;
      row.appendChild(lbl);
      const val = this.el('span', 'hud-metric-value');
      val.id = `hud-${label.toLowerCase()}`;
      val.textContent = '\u2014';
      row.appendChild(val);
      healthBody.appendChild(row);
    });
    root.appendChild(healthPanel);

    // ── Governance Panel ──
    const govPanel = this.buildPanel(
      'hud-governance', 'hud-mid-left accent-blue', 'GOVERNANCE',
      'hud-governance-content', ''
    );
    const govBody = govPanel.querySelector('.hud-panel-body')!;
    const govMetrics = [
      { label: 'MODE', id: 'hud-gov-mode-val' },
      { label: 'PENDING', id: 'hud-gov-pending' },
      { label: 'DELEGATIONS', id: 'hud-gov-delegations' },
      { label: 'ESCALATIONS', id: 'hud-gov-escalations' },
    ];
    govMetrics.forEach(m => {
      const row = this.el('div', 'hud-metric');
      const lbl = this.el('span', 'hud-metric-label');
      lbl.textContent = m.label;
      row.appendChild(lbl);
      const val = this.el('span', 'hud-metric-value');
      val.id = m.id;
      val.textContent = '\u2014';
      row.appendChild(val);
      govBody.appendChild(row);
    });
    root.appendChild(govPanel);

    // ── Agent Tooltip ──
    const tooltip = this.el('div', 'hud-agent-tooltip');
    tooltip.id = 'hud-agent-tooltip';
    tooltip.style.display = 'none';
    ['tooltip-header', 'tooltip-role', 'tooltip-dept', 'tooltip-exec', 'tooltip-status'].forEach(cls => {
      const d = this.el('div', cls);
      d.id = cls;
      tooltip.appendChild(d);
    });
    root.appendChild(tooltip);

    // ── Bottom Bar ──
    const bottomBar = this.el('div', 'hud-bottom-bar');
    const bottomNav = this.el('div', 'hud-bottom-nav');

    const btnData = [
      { id: 'btn-overview', label: 'Overview', icon: '<rect x="1" y="1" width="6" height="6" rx="1"/><rect x="9" y="1" width="6" height="6" rx="1"/><rect x="1" y="9" width="6" height="6" rx="1"/><rect x="9" y="9" width="6" height="6" rx="1"/>' },
      { id: 'btn-meeting', label: 'Meeting', icon: '<circle cx="8" cy="5" r="3"/><path d="M2 15c0-3.3 2.7-6 6-6s6 2.7 6 6"/>' },
      { id: 'btn-agents', label: 'Agents', icon: '<circle cx="5" cy="5" r="2.5"/><circle cx="11" cy="5" r="2.5"/><path d="M1 14c0-2.2 1.8-4 4-4s4 1.8 4 4"/><path d="M7 14c0-2.2 1.8-4 4-4s4 1.8 4 4"/>' },
    ];
    btnData.forEach(b => {
      const btn = document.createElement('button');
      btn.className = 'hud-view-btn';
      btn.id = b.id;
      // Create SVG icon safely via namespace
      const ns = 'http://www.w3.org/2000/svg';
      const svg = document.createElementNS(ns, 'svg');
      svg.setAttribute('width', '13');
      svg.setAttribute('height', '13');
      svg.setAttribute('viewBox', '0 0 16 16');
      svg.setAttribute('fill', 'none');
      svg.setAttribute('stroke', 'currentColor');
      svg.setAttribute('stroke-width', '1.5');
      // Use a temporary container to parse SVG children safely
      const tmp = document.createElementNS(ns, 'svg');
      tmp.innerHTML = b.icon;
      while (tmp.firstChild) svg.appendChild(tmp.firstChild);
      btn.appendChild(svg);
      btn.appendChild(document.createTextNode(b.label));
      bottomNav.appendChild(btn);
    });
    bottomBar.appendChild(bottomNav);

    const bottomInfo = this.el('div', 'hud-bottom-info');
    const agentCount = this.el('span', 'hud-agent-count');
    agentCount.id = 'hud-agent-count';
    bottomInfo.appendChild(agentCount);
    bottomInfo.appendChild(this.el('span', 'hud-bottom-divider'));
    const clock = this.el('span', 'hud-clock');
    clock.id = 'hud-clock';
    bottomInfo.appendChild(clock);
    bottomBar.appendChild(bottomInfo);
    root.appendChild(bottomBar);
  }

  /** Helper: create element with class(es) */
  private el(tag: string, className: string): HTMLElement {
    const e = document.createElement(tag);
    e.className = className;
    return e;
  }

  /** Helper: build a standard glass panel */
  private buildPanel(id: string, classes: string, title: string, bodyId: string, bodyText: string): HTMLElement {
    const panel = this.el('div', `hud-panel ${classes}`);
    panel.id = id;
    const titleEl = this.el('div', 'hud-panel-title');
    titleEl.textContent = title;
    panel.appendChild(titleEl);
    const body = this.el('div', 'hud-panel-body');
    body.id = bodyId;
    if (bodyText) body.textContent = bodyText;
    panel.appendChild(body);
    return panel;
  }

  /* ───────────────────────────────────────────
   * Data Update Methods
   * ─────────────────────────────────────────── */

  updateConnection(govConnected: boolean, brConnected: boolean): void {
    const el = document.getElementById('hud-connection');
    const dot = document.getElementById('hud-status-dot');
    if (!el) return;
    if (govConnected && brConnected) {
      el.textContent = 'ALL SYSTEMS ONLINE';
      el.style.color = DS.success;
      if (dot) { dot.className = 'hud-status-dot dot-success'; }
    } else if (govConnected || brConnected) {
      el.textContent = 'PARTIAL CONNECTION';
      el.style.color = DS.warning;
      if (dot) { dot.className = 'hud-status-dot dot-warning'; }
    } else {
      el.textContent = 'DISCONNECTED';
      el.style.color = DS.error;
      if (dot) { dot.className = 'hud-status-dot dot-error'; }
    }
  }

  updateMeeting(state: MeetingState): void {
    const el = document.getElementById('hud-meeting-content');
    if (!el) return;
    if (!state.active) {
      el.textContent = 'No active meeting';
      el.style.color = DS.gray500;
      return;
    }
    const phaseLabel = PHASE_LABELS[state.phase || ''] || state.phase || '\u2014';
    el.textContent = '';

    const typeDiv = document.createElement('div');
    typeDiv.style.cssText = `color:${DS.violet};font-weight:700;font-size:13px`;
    typeDiv.textContent = (state.type || '').toUpperCase();
    el.appendChild(typeDiv);

    const phaseDiv = document.createElement('div');
    phaseDiv.style.marginTop = '4px';
    phaseDiv.textContent = 'Phase: ';
    const phaseSpan = document.createElement('span');
    phaseSpan.style.color = DS.cyan;
    phaseSpan.textContent = phaseLabel;
    phaseDiv.appendChild(phaseSpan);
    el.appendChild(phaseDiv);

    const statusDiv = document.createElement('div');
    statusDiv.textContent = 'Status: ';
    const statusSpan = document.createElement('span');
    statusSpan.style.color = state.status === 'active' ? DS.success : DS.warning;
    statusSpan.textContent = (state.status || 'active').toUpperCase();
    statusDiv.appendChild(statusSpan);
    el.appendChild(statusDiv);

    const msgDiv = document.createElement('div');
    msgDiv.style.cssText = `font-size:9px;color:${DS.gray500};margin-top:4px`;
    msgDiv.textContent = `${state.messages.length} message${state.messages.length !== 1 ? 's' : ''}`;
    el.appendChild(msgDiv);
  }

  updateDecisions(stats: DecisionStats): void {
    const el = document.getElementById('hud-decisions-content');
    if (!el) return;
    const p = stats.pending || 0;
    const a = stats.approved || 0;
    const r = stats.rejected || 0;
    const d = stats.deferred || 0;
    const t = stats.total || (p + a + r + d);

    el.textContent = '';

    const grid = document.createElement('div');
    grid.className = 'decision-grid';

    const statData = [
      { val: p, color: DS.warning, label: 'Pending' },
      { val: a, color: DS.success, label: 'Approved' },
      { val: r, color: DS.error, label: 'Rejected' },
      { val: d, color: DS.gray500, label: 'Deferred' },
    ];

    statData.forEach(s => {
      const cell = document.createElement('div');
      cell.className = 'decision-stat';
      const count = document.createElement('span');
      count.className = 'decision-count';
      count.style.color = s.color;
      count.textContent = String(s.val);
      const label = document.createElement('span');
      label.className = 'decision-label';
      label.textContent = s.label;
      cell.appendChild(count);
      cell.appendChild(label);
      grid.appendChild(cell);
    });
    el.appendChild(grid);

    const totalDiv = document.createElement('div');
    totalDiv.className = 'decision-total';
    totalDiv.textContent = 'Total Decisions: ';
    const totalSpan = document.createElement('span');
    totalSpan.style.cssText = `color:${DS.cyan};font-weight:700`;
    totalSpan.textContent = String(t);
    totalDiv.appendChild(totalSpan);
    el.appendChild(totalDiv);
  }

  updateEscalations(alerts: EscalationAlert[]): void {
    const el = document.getElementById('hud-escalations-content');
    if (!el) return;
    el.textContent = '';

    if (alerts.length === 0) {
      const span = document.createElement('span');
      span.style.color = DS.success;
      span.textContent = 'None active';
      el.appendChild(span);
      return;
    }

    const header = document.createElement('div');
    header.className = 'escalation-header';
    header.textContent = `${alerts.length} ACTIVE`;
    el.appendChild(header);

    alerts.slice(0, 4).forEach(a => {
      const row = document.createElement('div');
      row.className = 'escalation-row';
      const hours = document.createElement('span');
      hours.className = 'escalation-hours';
      hours.textContent = `${a.hours_elapsed.toFixed(1)}h`;
      row.appendChild(hours);
      row.appendChild(document.createTextNode(' \u2014 '));
      const type = document.createElement('span');
      type.style.color = DS.gray100;
      type.textContent = a.escalation_type;
      row.appendChild(type);
      if (a.action_taken) {
        const action = document.createElement('span');
        action.className = 'escalation-action';
        action.textContent = `[${a.action_taken}]`;
        row.appendChild(action);
      }
      el.appendChild(row);
    });
  }

  updateSystemHealth(health: SystemHealth): void {
    const cpu = document.getElementById('hud-cpu');
    const mem = document.getElementById('hud-memory');
    const svc = document.getElementById('hud-services');
    const up = document.getElementById('hud-uptime');
    if (cpu) {
      cpu.textContent = health.cpu;
      cpu.style.color = parseFloat(health.cpu) > 80 ? DS.error : parseFloat(health.cpu) > 50 ? DS.warning : DS.success;
    }
    if (mem) {
      mem.textContent = health.memory;
      mem.style.color = parseFloat(health.memory) > 80 ? DS.error : parseFloat(health.memory) > 50 ? DS.warning : DS.success;
    }
    if (svc) {
      svc.textContent = String(health.services);
      svc.style.color = DS.info;
    }
    if (up) {
      up.textContent = health.uptime;
      up.style.color = DS.gray400;
    }
  }

  updateGovernance(status: GovernanceStatus): void {
    const mode = document.getElementById('hud-gov-mode-val');
    const pending = document.getElementById('hud-gov-pending');
    const delegations = document.getElementById('hud-gov-delegations');
    const escalations = document.getElementById('hud-gov-escalations');
    const headerMode = document.getElementById('hud-gov-mode');

    const gm = status.governance_mode || 'unknown';
    if (mode) {
      mode.textContent = gm.toUpperCase();
      mode.style.color = gm === 'autonomous' ? DS.success : DS.warning;
    }
    if (pending) {
      const pd = status.pending_decisions ?? 0;
      pending.textContent = String(pd);
      pending.style.color = pd > 5 ? DS.error : pd > 0 ? DS.warning : DS.success;
    }
    if (delegations) {
      delegations.textContent = String(status.active_delegations ?? 0);
      delegations.style.color = DS.info;
    }
    if (escalations) {
      const ae = status.active_escalations ?? 0;
      escalations.textContent = String(ae);
      escalations.style.color = ae > 0 ? DS.error : DS.success;
    }
    if (headerMode) {
      headerMode.textContent = gm.toUpperCase();
      headerMode.style.color = gm === 'autonomous' ? DS.success : DS.warning;
    }
  }

  updateAgentCount(total: number, speaking: number): void {
    const el = document.getElementById('hud-agent-count');
    if (!el) return;
    el.textContent = '';
    const count = document.createElement('span');
    count.style.color = DS.cyan;
    count.textContent = String(total);
    el.appendChild(count);
    el.appendChild(document.createTextNode(' agents'));
    if (speaking > 0) {
      const sp = document.createElement('span');
      sp.style.color = DS.success;
      sp.textContent = ` (${speaking} speaking)`;
      el.appendChild(sp);
    }
  }

  addFeedMessage(agentName: string, message: string, type?: string): void {
    const el = document.getElementById('hud-feed-content');
    if (!el) return;

    const div = document.createElement('div');
    div.className = 'feed-item';
    const typeColor = type === 'error' ? DS.error : type === 'warning' ? DS.warning : DS.violet;
    const time = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', timeZone: 'America/Los_Angeles' });

    const timeSpan = document.createElement('span');
    timeSpan.className = 'feed-time';
    timeSpan.textContent = time;
    div.appendChild(timeSpan);

    const nameSpan = document.createElement('span');
    nameSpan.style.cssText = `color:${typeColor};font-weight:600`;
    nameSpan.textContent = agentName;
    div.appendChild(nameSpan);

    const msgSpan = document.createElement('span');
    msgSpan.style.color = DS.gray400;
    msgSpan.textContent = `: ${message.slice(0, 100)}`;
    div.appendChild(msgSpan);

    el.appendChild(div);
    el.scrollTop = el.scrollHeight;

    // Update count badge
    const badge = document.getElementById('hud-feed-count');
    if (badge) badge.textContent = String(el.children.length);

    // Keep max 30 messages
    while (el.children.length > 30) {
      el.removeChild(el.firstChild!);
    }
  }

  // Bulk load feed items from API
  loadFeed(items: FeedItem[]): void {
    const el = document.getElementById('hud-feed-content');
    if (!el) return;
    if (el.children.length > 0) return;
    items.slice(-15).forEach(item => {
      this.addFeedMessage(item.agent_name, item.action, item.type);
    });
  }

  // Show agent detail tooltip at screen position
  showAgentTooltip(agent: AgentNode, screenX: number, screenY: number): void {
    const tooltip = document.getElementById('hud-agent-tooltip');
    if (!tooltip) return;

    if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout);

    const header = document.getElementById('tooltip-header');
    const role = document.getElementById('tooltip-role');
    const dept = document.getElementById('tooltip-dept');
    const exec = document.getElementById('tooltip-exec');
    const status = document.getElementById('tooltip-status');

    if (header) {
      header.textContent = agent.name;
      header.style.color = agent.color;
    }
    if (role) role.textContent = agent.role;
    if (dept) dept.textContent = `Dept: ${agent.dept}`;
    if (exec) exec.textContent = `Reports to: ${agent.exec.toUpperCase()}`;
    if (status) {
      status.textContent = agent.speaking ? 'SPEAKING' : 'IDLE';
      status.style.color = agent.speaking ? DS.success : DS.gray500;
    }

    const maxX = window.innerWidth - 200;
    const maxY = window.innerHeight - 140;
    tooltip.style.left = `${Math.min(screenX + 15, maxX)}px`;
    tooltip.style.top = `${Math.min(screenY - 20, maxY)}px`;
    tooltip.style.display = 'block';

    this.tooltipTimeout = setTimeout(() => {
      tooltip.style.display = 'none';
    }, 5000);
  }

  hideAgentTooltip(): void {
    const tooltip = document.getElementById('hud-agent-tooltip');
    if (tooltip) tooltip.style.display = 'none';
    if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout);
  }

  updateClock(): void {
    const el = document.getElementById('hud-clock');
    if (!el) return;
    const now = new Date();
    const pt = new Date(now.toLocaleString('en-US', { timeZone: 'America/Los_Angeles' }));
    el.textContent = pt.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit' }) + ' PT';
  }

  /* ───────────────────────────────────────────
   * Design System Stylesheet
   * ─────────────────────────────────────────── */
  private applyStyles(): void {
    const style = document.createElement('style');
    style.textContent = `
      /* ═══ Design System Tokens ═══ */
      :root {
        /* Typography */
        --ds-font: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

        /* Gray palette (Slate scale) */
        --ds-gray-50: #f8fafc;
        --ds-gray-100: #f1f5f9;
        --ds-gray-200: #e2e8f0;
        --ds-gray-300: #cbd5e1;
        --ds-gray-400: #94a3b8;
        --ds-gray-500: #64748b;
        --ds-gray-600: #475569;
        --ds-gray-700: #334155;
        --ds-gray-800: #1e293b;
        --ds-gray-900: #0f172a;

        /* Accent colors */
        --ds-violet: #8b5cf6;
        --ds-indigo: #6366f1;
        --ds-cyan: #06b6d4;
        --ds-blue: #3b82f6;
        --ds-emerald: #10b981;
        --ds-amber: #f59e0b;

        /* Semantic colors */
        --ds-success: #10b981;
        --ds-warning: #f59e0b;
        --ds-error: #ef4444;
        --ds-info: #3b82f6;

        /* Glass surfaces */
        --ds-glass: rgba(10, 14, 28, 0.72);
        --ds-glass-strong: rgba(8, 11, 22, 0.88);
        --ds-glass-subtle: rgba(15, 20, 38, 0.5);

        /* Blur */
        --ds-blur-sm: blur(8px);
        --ds-blur: blur(16px);
        --ds-blur-lg: blur(24px);

        /* Borders */
        --ds-border: rgba(148, 163, 184, 0.06);
        --ds-border-strong: rgba(148, 163, 184, 0.12);
        --ds-border-interactive: rgba(99, 102, 241, 0.25);

        /* Radius */
        --ds-radius-sm: 6px;
        --ds-radius-md: 10px;
        --ds-radius-lg: 14px;
        --ds-radius-full: 9999px;

        /* Shadows */
        --ds-shadow-sm: 0 2px 8px rgba(0,0,0,0.3);
        --ds-shadow-md: 0 4px 16px rgba(0,0,0,0.4);
        --ds-shadow-lg: 0 8px 32px rgba(0,0,0,0.5);
        --ds-shadow-glow-violet: 0 0 20px rgba(139,92,246,0.15);
        --ds-shadow-glow-cyan: 0 0 20px rgba(6,182,212,0.12);

        /* Transitions */
        --ds-ease: cubic-bezier(0.4, 0, 0.2, 1);
        --ds-duration-fast: 150ms;
        --ds-duration-normal: 250ms;
      }

      /* ═══ HUD Container ═══ */
      #war-room-hud {
        position: absolute; top: 0; left: 0; width: 100%; height: 100%;
        pointer-events: none;
        font-family: var(--ds-font);
        color: var(--ds-gray-100);
        z-index: 10;
      }

      /* ═══ Header Bar ═══ */
      .hud-header {
        position: absolute; top: 0; left: 0; right: 0;
        display: flex; justify-content: space-between; align-items: center;
        padding: 14px 24px;
        background: linear-gradient(180deg, rgba(5,5,16,0.95) 0%, rgba(5,5,16,0.6) 70%, transparent 100%);
      }
      .hud-header-left {
        display: flex; align-items: center; gap: 10px;
      }
      .hud-logo-pulse {
        width: 8px; height: 8px; border-radius: var(--ds-radius-full);
        background: var(--ds-violet);
        box-shadow: 0 0 8px rgba(139,92,246,0.6), 0 0 16px rgba(139,92,246,0.3);
        animation: logoPulse 2.5s ease-in-out infinite;
      }
      @keyframes logoPulse {
        0%, 100% { opacity: 1; box-shadow: 0 0 8px rgba(139,92,246,0.6), 0 0 16px rgba(139,92,246,0.3); }
        50% { opacity: 0.7; box-shadow: 0 0 4px rgba(139,92,246,0.3), 0 0 8px rgba(139,92,246,0.15); }
      }
      .hud-title {
        font-size: 13px; font-weight: 800; letter-spacing: 2.5px;
        background: linear-gradient(135deg, var(--ds-violet), var(--ds-cyan));
        -webkit-background-clip: text; -webkit-text-fill-color: transparent;
        background-clip: text;
      }
      .hud-status-group {
        display: flex; gap: 10px; align-items: center;
      }
      .hud-status-dot {
        width: 6px; height: 6px; border-radius: var(--ds-radius-full);
        background: var(--ds-warning);
        animation: dotPulse 1.5s ease-in-out infinite;
      }
      .hud-status-dot.dot-success { background: var(--ds-success); animation: none; }
      .hud-status-dot.dot-warning { background: var(--ds-warning); }
      .hud-status-dot.dot-error { background: var(--ds-error); }
      @keyframes dotPulse {
        0%, 100% { opacity: 1; }
        50% { opacity: 0.4; }
      }
      .hud-status {
        font-size: 10px; font-weight: 700; letter-spacing: 0.5px;
        color: var(--ds-warning);
      }
      .hud-governance-mode {
        font-size: 9px; font-weight: 600;
        padding: 2px 8px; border-radius: var(--ds-radius-full);
        background: rgba(139,92,246,0.1);
        border: 1px solid rgba(139,92,246,0.2);
      }

      /* ═══ Glass Panels ═══ */
      .hud-panel {
        position: absolute;
        padding: 16px 20px;
        background: var(--ds-glass-strong);
        backdrop-filter: var(--ds-blur);
        -webkit-backdrop-filter: var(--ds-blur);
        border: 1px solid var(--ds-border-strong);
        border-radius: var(--ds-radius-lg);
        min-width: 240px;
        font-size: 13px;
        box-shadow: var(--ds-shadow-lg), inset 0 1px 0 rgba(255,255,255,0.03);
        transition: border-color var(--ds-duration-normal) var(--ds-ease),
                    box-shadow var(--ds-duration-normal) var(--ds-ease);
        overflow: hidden;
      }
      /* Colored accent bar (left edge) via pseudo-element */
      .hud-panel::before {
        content: '';
        position: absolute; left: 0; top: 0; bottom: 0;
        width: 3px; border-radius: 3px 0 0 3px;
        background: var(--ds-violet);
        opacity: 0.8;
      }
      .hud-panel.accent-violet::before { background: var(--ds-violet); }
      .hud-panel.accent-cyan::before { background: var(--ds-cyan); }
      .hud-panel.accent-amber::before { background: var(--ds-amber); }
      .hud-panel.accent-red::before { background: var(--ds-error); }
      .hud-panel.accent-emerald::before { background: var(--ds-emerald); }
      .hud-panel.accent-blue::before { background: var(--ds-blue); }

      .hud-panel-title {
        font-size: 11px; font-weight: 700;
        color: var(--ds-gray-400);
        letter-spacing: 1.5px;
        margin-bottom: 12px;
        display: flex; align-items: center; gap: 6px;
      }
      .hud-panel-body {
        color: var(--ds-gray-300);
      }

      /* ═══ Panel Positions ═══ */
      .hud-top-left { top: 56px; left: 16px; }
      .hud-top-right { top: 56px; right: 16px; }
      .hud-bottom-left { bottom: 64px; left: 16px; max-width: 320px; }
      .hud-bottom-right { bottom: 64px; right: 16px; }
      .hud-mid-right { top: 210px; right: 16px; }
      .hud-mid-left { top: 210px; left: 16px; }

      /* ═══ Feed ═══ */
      .hud-feed-scroll { max-height: 220px; overflow-y: auto; pointer-events: all; }
      .hud-feed-scroll::-webkit-scrollbar { width: 3px; }
      .hud-feed-scroll::-webkit-scrollbar-track { background: transparent; }
      .hud-feed-scroll::-webkit-scrollbar-thumb { background: rgba(148,163,184,0.15); border-radius: 2px; }
      .hud-feed-badge {
        font-size: 10px; font-weight: 600;
        padding: 2px 8px; border-radius: var(--ds-radius-full);
        background: rgba(139,92,246,0.15);
        color: var(--ds-violet);
        margin-left: 4px;
      }
      .feed-item {
        padding: 5px 0;
        border-bottom: 1px solid var(--ds-border);
        font-size: 12px; line-height: 1.5;
      }
      .feed-item:last-child { border-bottom: none; }
      .feed-time {
        color: var(--ds-gray-500);
        font-size: 10px; margin-right: 6px;
        font-variant-numeric: tabular-nums;
      }

      /* ═══ Metrics ═══ */
      .hud-metric {
        display: flex; justify-content: space-between; align-items: center;
        padding: 4px 0;
        border-bottom: 1px solid var(--ds-border);
      }
      .hud-metric:last-child { border-bottom: none; }
      .hud-metric-label {
        font-size: 11px; color: var(--ds-gray-400);
        letter-spacing: 0.5px; font-weight: 500;
      }
      .hud-metric-value {
        font-size: 18px; font-weight: 700;
        color: var(--ds-gray-100);
        font-variant-numeric: tabular-nums;
      }

      /* ═══ Decisions Grid ═══ */
      .decision-grid {
        display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
      }
      .decision-stat {
        display: flex; flex-direction: column; align-items: center;
        padding: 6px 4px;
        background: rgba(255,255,255,0.02);
        border-radius: var(--ds-radius-sm);
        border: 1px solid var(--ds-border);
        transition: background var(--ds-duration-fast) var(--ds-ease);
      }
      .decision-count {
        font-size: 26px; font-weight: 800;
        font-variant-numeric: tabular-nums;
        line-height: 1.2;
      }
      .decision-label {
        font-size: 11px; color: var(--ds-gray-400);
        letter-spacing: 0.5px; margin-top: 2px;
      }
      .decision-total {
        margin-top: 8px; font-size: 12px;
        color: var(--ds-gray-400);
        border-top: 1px solid var(--ds-border-strong);
        padding-top: 6px;
      }

      /* ═══ Escalations ═══ */
      .escalation-header {
        font-size: 12px; color: var(--ds-error);
        font-weight: 700; margin-bottom: 8px;
        display: flex; align-items: center; gap: 5px;
      }
      .escalation-header::before {
        content: '';
        width: 6px; height: 6px; border-radius: var(--ds-radius-full);
        background: var(--ds-error);
        animation: dotPulse 1s ease-in-out infinite;
      }
      .escalation-row {
        padding: 5px 0;
        border-bottom: 1px solid var(--ds-border);
        font-size: 12px;
      }
      .escalation-row:last-child { border-bottom: none; }
      .escalation-hours {
        color: var(--ds-error); font-weight: 600;
      }
      .escalation-action {
        color: var(--ds-success);
        font-size: 9px; margin-left: 4px;
      }

      /* ═══ Agent Tooltip ═══ */
      .hud-agent-tooltip {
        position: absolute;
        padding: 14px 18px;
        background: var(--ds-glass-strong);
        backdrop-filter: var(--ds-blur-lg);
        -webkit-backdrop-filter: var(--ds-blur-lg);
        border: 1px solid var(--ds-border-interactive);
        border-radius: var(--ds-radius-lg);
        min-width: 190px;
        pointer-events: none; z-index: 20;
        box-shadow: var(--ds-shadow-lg), var(--ds-shadow-glow-violet);
      }
      .tooltip-header { font-size: 14px; font-weight: 700; margin-bottom: 6px; }
      .tooltip-role { font-size: 11px; color: var(--ds-gray-400); margin-bottom: 3px; }
      .tooltip-dept { font-size: 10px; color: var(--ds-gray-500); }
      .tooltip-exec { font-size: 10px; color: var(--ds-gray-500); }
      .tooltip-status { font-size: 10px; font-weight: 600; margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--ds-border); }

      /* ═══ Bottom Bar ═══ */
      .hud-bottom-bar {
        position: absolute; bottom: 0; left: 0; right: 0;
        display: flex; justify-content: space-between; align-items: center;
        padding: 10px 24px;
        background: linear-gradient(0deg, rgba(5,5,16,0.95) 0%, rgba(5,5,16,0.6) 70%, transparent 100%);
      }
      .hud-bottom-nav {
        display: flex; gap: 6px;
      }
      .hud-view-btn {
        pointer-events: all;
        display: flex; align-items: center; gap: 6px;
        padding: 6px 14px; border-radius: var(--ds-radius-md);
        border: 1px solid var(--ds-border-strong);
        background: var(--ds-glass);
        backdrop-filter: var(--ds-blur-sm);
        -webkit-backdrop-filter: var(--ds-blur-sm);
        color: var(--ds-gray-300); font-size: 12px; font-weight: 600;
        cursor: pointer; font-family: inherit;
        transition: all var(--ds-duration-fast) var(--ds-ease);
        letter-spacing: 0.3px;
      }
      .hud-view-btn svg {
        width: 13px; height: 13px; opacity: 0.7;
        transition: opacity var(--ds-duration-fast) var(--ds-ease);
      }
      .hud-view-btn:hover {
        border-color: var(--ds-border-interactive);
        color: var(--ds-gray-100);
        background: rgba(99,102,241,0.08);
        box-shadow: var(--ds-shadow-sm), 0 0 12px rgba(99,102,241,0.1);
      }
      .hud-view-btn:hover svg { opacity: 1; }
      .hud-view-btn:active {
        transform: scale(0.97);
      }

      .hud-bottom-info {
        display: flex; align-items: center; gap: 12px;
      }
      .hud-agent-count {
        font-size: 12px; color: var(--ds-gray-400);
      }
      .hud-bottom-divider {
        width: 1px; height: 12px;
        background: var(--ds-border-strong);
      }
      .hud-clock {
        font-size: 13px; color: var(--ds-gray-400);
        font-variant-numeric: tabular-nums;
        font-weight: 500;
        letter-spacing: 0.3px;
      }
    `;
    document.head.appendChild(style);
  }
}