---
// src/components/KnowledgeGraph.astro
// Enhanced interactive visualization of content connections using Cytoscape.js

export interface GraphNode {
  id: string;
  label: string;
  type: 'post' | 'tag' | 'category'; // Node types to distinguish posts from tags
  category?: string;
  tags?: string[];
  url?: string; // URL for linking
  content?: string; // Add content property for post full content
}

export interface GraphEdge {
  source: string;
  target: string;
  type: 'post-tag' | 'post-category' | 'post-post'; // Edge types
  strength?: number;
}

export interface GraphData {
  nodes: GraphNode[];
  edges: GraphEdge[];
}

interface Props {
  graphData: GraphData;
  height?: string; // e.g., '500px'
  initialFilter?: string; // Optional initial filter
}

const { graphData, height = "50vh", initialFilter = "all" } = Astro.props;

// Generate colors based on node types
const nodeTypeColors = {
  'post': '#3B82F6', // Blue for posts
  'tag': '#10B981',  // Green for tags
  'category': '#8B5CF6' // Purple for categories
};

// Generate predefined colors for categories
const predefinedColors = {
  'Kubernetes': '#326CE5', 'Docker': '#2496ED', 'DevOps': '#FF6F61',
  'Homelab': '#06B6D4', 'Networking': '#9333EA', 'Infrastructure': '#10B981',
  'Automation': '#F59E0B', 'Security': '#EF4444', 'Monitoring': '#6366F1',
  'Storage': '#8B5CF6', 'Obsidian': '#7C3AED', 'Tutorial': '#3B82F6',
  'Uncategorized': '#A0AEC0'
};

// Calculate node sizes
const nodeSizes = {};
const minSize = 15; const maxSize = 35;
const degreeMap = new Map();
graphData.nodes.forEach(node => degreeMap.set(node.id, 0));
graphData.edges.forEach(edge => {
  degreeMap.set(edge.source, (degreeMap.get(edge.source) || 0) + 1);
  degreeMap.set(edge.target, (degreeMap.get(edge.target) || 0) + 1);
});
const maxDegree = Math.max(...Array.from(degreeMap.values()), 1);
graphData.nodes.forEach(node => {
  const degree = degreeMap.get(node.id) || 0;
  // Make tags slightly smaller than posts by default
  const baseSize = node.type === 'post' ? minSize : minSize * 0.8;
  const normalizedSize = maxDegree === 0 ? 0.5 : degree / maxDegree;
  nodeSizes[node.id] = baseSize + normalizedSize * (maxSize - minSize);
});

// Count node types for legend
const nodeTypeCounts = {
  post: graphData.nodes.filter(node => node.type === 'post').length,
  tag: graphData.nodes.filter(node => node.type === 'tag').length,
  category: graphData.nodes.filter(node => node.type === 'category').length
};
---

<!-- Include Cytoscape via CDN with is:inline to ensure it loads before the script runs -->
<script src="https://unpkg.com/cytoscape@3.25.0/dist/cytoscape.min.js" is:inline></script>

<div class="graph-container-wrapper" style={`--graph-height: ${height};`}>
  <!-- Instructions overlay - move to be positioned absolutely over the graph -->
  <div class="graph-instructions overlay">
    <details class="instructions-details">
      <summary class="instructions-summary">How to use the Knowledge Graph</summary>
      <div class="instructions-content">
        <p>This Knowledge Graph visualizes connections between blog content:</p>
        <ul>
          <li><span class="node-example post-node"></span> <strong>Posts</strong> - Blog articles (circle nodes)</li>
          <li><span class="node-example tag-node"></span> <strong>Tags</strong> - Content topics (diamond nodes)</li>
        </ul>
        <p>Interactions:</p>
        <ul>
          <li>Click a node to see its connections and details</li>
          <li>Click a tag node to filter posts by that tag</li>
          <li>Click a post node to highlight that specific post</li>
          <li>Use the filter buttons below to focus on specific topics</li>
          <li>Use mouse wheel to zoom in/out and drag to pan</li>
          <li>Click an empty area to reset the view</li>
          <li>In fullscreen mode, click a post to view its full content</li>
        </ul>
      </div>
    </details>
  </div>

  <!-- Loading Animation -->
  <div id="graph-loading" class="graph-loading">
    <div class="loading-spinner">
      <div class="spinner-ring"></div>
      <div class="spinner-ring"></div>
      <div class="spinner-ring"></div>
    </div>
    <div class="loading-text">Initializing Knowledge Graph...</div>
  </div>

  <!-- Cytoscape Container -->
  <div id="knowledge-graph" class="graph-container"></div>

  <!-- Node Details Panel -->
  <div id="node-details" class="node-details">
    <div class="node-details-header">
      <h3 id="node-title" class="node-title">Node Title</h3>
      <button id="close-details" class="close-button" aria-label="Close details">
        <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
      </button>
    </div>
    <div id="node-type" class="node-type">
      <span class="type-value">Type</span>
    </div>
    <div id="node-category" class="node-category">
      <span class="category-label">Category:</span>
      <span class="category-value">Category Name</span>
    </div>
    <div id="node-tags" class="node-tags">
      <span class="tags-label">Tags:</span>
      <div class="tags-container">
        <!-- Tags populated by JS -->
      </div>
    </div>
    <div id="node-connections" class="node-connections">
      <span class="connections-label">Connections:</span>
      <ul class="connections-list">
        <!-- Connections populated by JS -->
      </ul>
    </div>
    <a href="#" id="node-link" class="node-link" target="_self" rel="noopener noreferrer">View Content</a>
  </div>

  <!-- Fullscreen Toggle Button -->
  <button id="fullscreen-toggle" class="fullscreen-toggle" aria-label="Toggle fullscreen">
    <svg id="fullscreen-enter-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <polyline points="15 3 21 3 21 9"></polyline>
      <polyline points="9 21 3 21 3 15"></polyline>
      <line x1="21" y1="3" x2="14" y2="10"></line>
      <line x1="3" y1="21" x2="10" y2="14"></line>
    </svg>
    <svg id="fullscreen-exit-icon" class="hidden" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <polyline points="4 14 10 14 10 20"></polyline>
      <polyline points="20 10 14 10 14 4"></polyline>
      <line x1="14" y1="10" x2="21" y2="3"></line>
      <line x1="3" y1="21" x2="10" y2="14"></line>
    </svg>
  </button>

  <!-- Full Post Content Panel -->
  <div id="full-post-content" class="full-post-content">
    <div class="full-post-header">
      <h2 id="full-post-title" class="full-post-title">Post Title</h2>
      <button id="close-full-post" class="close-button" aria-label="Close post content">
        <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
      </button>
    </div>
    <div class="full-post-metadata">
      <div class="metadata-row">
        <span class="metadata-label">Category:</span>
        <div id="full-post-category" class="full-post-category"></div>
      </div>
      <div class="metadata-row">
        <span class="metadata-label">Tags:</span>
        <div id="full-post-tags" class="full-post-tags"></div>
      </div>
    </div>
    <div id="full-post-container" class="full-post-container">
      <div class="full-post-placeholder">
        <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
          <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
          <polyline points="14 2 14 8 20 8"></polyline>
          <line x1="16" y1="13" x2="8" y2="13"></line>
          <line x1="16" y1="17" x2="8" y2="17"></line>
          <polyline points="10 9 9 9 8 9"></polyline>
        </svg>
        <p>Select a post node to view its content</p>
      </div>
    </div>
    <div class="full-post-footer">
      <a href="#" id="full-post-link" class="full-post-link" target="_blank" rel="noopener noreferrer"> <!-- Changed target to _blank -->
        Read Full Article
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
          <polyline points="15 3 21 3 21 9"></polyline>
          <line x1="10" y1="14" x2="21" y2="3"></line>
        </svg>
      </a>
    </div>
  </div>

  <!-- Graph Controls -->
  <div class="graph-controls">
     <div class="graph-filters">
       <button class="graph-filter active" data-filter="all" style="--filter-color: var(--accent-primary);">All</button>
       <button class="graph-filter" data-filter="posts" style="--filter-color: #3B82F6;">Posts ({nodeTypeCounts.post})</button>
       <button class="graph-filter" data-filter="tags" style="--filter-color: #10B981;">Tags ({nodeTypeCounts.tag})</button>
     </div>
     <div class="graph-actions">
        <button id="zoom-in" class="graph-action" aria-label="Zoom In">
          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
        </button>
        <button id="zoom-out" class="graph-action" aria-label="Zoom Out">
           <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line></svg>
        </button>
        <button id="reset-graph" class="graph-action" aria-label="Reset View">
           <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 2v6h6"></path><path d="M21 12A9 9 0 0 0 6 5.3L3 8"></path><path d="M21 22v-6h-6"></path><path d="M3 12a9 9 0 0 0 15 6.7l3-2.7"></path></svg>
        </button>
     </div>
  </div>
</div>

<script define:vars={{ graphData, nodeTypeColors, nodeSizes, predefinedColors, initialFilter }}>
  // Initialize the graph when the DOM is ready
  function initializeGraph() {
    // Check if Cytoscape is loaded
    if (typeof cytoscape === 'undefined') {
      console.error("Cytoscape library not loaded. Make sure it's included via the script tag.");
      const loadingEl = document.getElementById('graph-loading');
      if(loadingEl) loadingEl.innerHTML = "<p>Error: Cytoscape library not loaded.</p>";
      return;
    }

    const loadingEl = document.getElementById('graph-loading');
    const nodeDetailsEl = document.getElementById('node-details');
    const closeDetailsBtn = document.getElementById('close-details');
    const graphContainer = document.getElementById('knowledge-graph');
    const graphWrapper = document.querySelector('.graph-container-wrapper');
    const fullscreenToggle = document.getElementById('fullscreen-toggle');
    const fullscreenEnterIcon = document.getElementById('fullscreen-enter-icon');
    const fullscreenExitIcon = document.getElementById('fullscreen-exit-icon');
    const fullPostContent = document.getElementById('full-post-content');
    const closeFullPostBtn = document.getElementById('close-full-post');
    const fullPostTitle = document.getElementById('full-post-title');
    const fullPostContainer = document.getElementById('full-post-container');
    const fullPostCategory = document.getElementById('full-post-category');
    const fullPostTags = document.getElementById('full-post-tags');
    const fullPostLink = document.getElementById('full-post-link');

    if (!graphContainer) {
        console.error("Knowledge graph container not found!");
        return;
    }
    if (!graphData || !graphData.nodes) {
        console.error("Graph data is missing or invalid.");
        if(loadingEl) loadingEl.innerHTML = "<p>Error loading graph data.</p>";
        return;
    }

    // Format data for Cytoscape
    const elements = [];

    // State variables
    let isFullscreen = false;

    // Add nodes with appropriate styling based on type
    graphData.nodes.forEach(node => {
      let nodeColor;

      if (node.type === 'post') {
        // Posts get category color if available
        nodeColor = node.category && predefinedColors[node.category]
          ? predefinedColors[node.category]
          : nodeTypeColors['post'];
      } else {
        // Tags and categories get their type color
        nodeColor = nodeTypeColors[node.type];
      }

      elements.push({
        data: {
          id: node.id,
          label: node.label,
          type: node.type,
          category: node.category || '',
          tags: node.tags || [],
          size: nodeSizes[node.id] || 25,
          color: nodeColor,
          url: node.url || '#',
          content: node.content || '' // Include content data for post nodes
        }
      });
    });

    // Add edges
    graphData.edges.forEach((edge, index) => {
      if (graphData.nodes.some(n => n.id === edge.source) && graphData.nodes.some(n => n.id === edge.target)) {
          elements.push({
            data: {
              id: `e${index}`,
              source: edge.source,
              target: edge.target,
              type: edge.type || 'post-tag',
              weight: edge.strength || 1
            }
          });
      } else {
          console.warn(`Skipping edge e${index} due to missing node: ${edge.source} -> ${edge.target}`);
      }
    });

    // Initialize Cytoscape
    const cy = cytoscape({
      container: graphContainer,
      elements: elements,
      style: [
         // Base node styles
         { selector: 'node', style: {
             'background-color': 'data(color)',
             'label': 'data(label)',
             'width': 'data(size)',
             'height': 'data(size)',
             'font-size': '10px',
             'color': '#E2E8F0',
             'text-valign': 'bottom',
             'text-halign': 'center',
             'text-margin-y': '7px',
             'text-background-opacity': 0.7,
             'text-background-color': '#0F1219',
             'text-background-padding': '3px',
             'text-background-shape': 'roundrectangle',
             'text-max-width': '120px',
             'text-wrap': 'ellipsis',
             'text-overflow-wrap': 'anywhere',
             'border-width': '2px',
             'border-color': '#0F1219',
             'border-opacity': 0.8,
             'z-index': 10,
             'text-outline-width': 1,
             'text-outline-color': '#000',
             'text-outline-opacity': 0.5
         }},
         // Post node specific styles
         { selector: 'node[type="post"]', style: {
             'shape': 'ellipse',
             'border-width': '2px'
         }},
         // Tag node specific styles
         { selector: 'node[type="tag"]', style: {
             'shape': 'diamond',
             'border-width': '1px',
             'border-color': '#10B981',
             'border-opacity': 0.9
         }},
         // Category node specific styles
         { selector: 'node[type="category"]', style: {
             'shape': 'hexagon',
             'border-width': '1px'
         }},
         // Edge styles
         { selector: 'edge', style: {
             'width': 'mapData(weight, 1, 10, 1, 3)',
             'line-color': 'rgba(226, 232, 240, 0.2)',
             'curve-style': 'bezier',
             'opacity': 0.6,
             'z-index': 1
         }},
         // Post-tag edge specific styles
         { selector: 'edge[type="post-tag"]', style: {
             'line-color': 'rgba(16, 185, 129, 0.4)',
             'line-style': 'dashed'
         }},
         // Post-post edge specific styles
         { selector: 'edge[type="post-post"]', style: {
             'line-color': 'rgba(59, 130, 246, 0.4)',
             'line-style': 'solid'
         }},
         // Selection and hover styles
         { selector: '.highlighted', style: { 'background-color': 'data(color)', 'border-color': '#FFFFFF', 'border-width': '3px', 'color': '#FFFFFF', 'text-background-opacity': 0.9, 'opacity': 1, 'z-index': 20 } },
         { selector: '.filtered', style: { 'background-color': 'data(color)', 'border-color': '#FFFFFF', 'border-width': '2px', 'color': '#FFFFFF', 'text-background-opacity': 0.8, 'opacity': 0.8, 'z-index': 15 } },
         { selector: '.faded', style: { 'opacity': 0.15, 'text-opacity': 0.3, 'background-opacity': 0.3, 'z-index': 1 } },
         { selector: 'node:selected', style: { 'border-width': '4px', 'border-color': '#FFFFFF', 'border-opacity': 1, 'background-color': 'data(color)', 'text-opacity': 1, 'color': '#FFFFFF', 'z-index': 30 } },
         { selector: 'edge:selected', style: { 'width': 'mapData(weight, 1, 10, 2, 6)', 'line-color': '#FFFFFF', 'opacity': 1, 'z-index': 30 } }
      ],
      // Update layout for better visualization of post-tag connections
      layout: {
        name: 'cose',
        idealEdgeLength: 80,
        nodeOverlap: 20,
        refresh: 20,
        fit: true,
        padding: 30,
        randomize: false,
        componentSpacing: 100,
        nodeRepulsion: 450000,
        edgeElasticity: 100,
        nestingFactor: 5,
        gravity: 80,
        numIter: 1000,
        initialTemp: 200,
        coolingFactor: 0.95,
        minTemp: 1.0
      },
      zoom: 1, minZoom: 0.1, maxZoom: 3, zoomingEnabled: true, userZoomingEnabled: true, panningEnabled: true, userPanningEnabled: true, boxSelectionEnabled: false,
    });

    // Hide loading screen
    if (loadingEl) {
      setTimeout(() => { loadingEl.classList.add('hidden'); }, 500);
    }

// --- Fullscreen Toggle Functionality ---
    if (fullscreenToggle) {
      fullscreenToggle.addEventListener('click', toggleFullscreen);
    }

    // Toggle fullscreen function
    function toggleFullscreen() {
      isFullscreen = !isFullscreen;

      if (isFullscreen) {
        // Enable fullscreen mode
        graphWrapper.classList.add('fullscreen');
        fullscreenEnterIcon.classList.add('hidden');
        fullscreenExitIcon.classList.remove('hidden');

        // Hide the node details panel if it's visible
        if (nodeDetailsEl) nodeDetailsEl.classList.remove('active');

        // In fullscreen, we adjust the cytoscape layout to fit
        setTimeout(() => {
          cy.resize();
          cy.fit(null, 30);
        }, 300); // Wait for transition to complete
      } else {
        // Disable fullscreen mode
        graphWrapper.classList.remove('fullscreen');
        fullscreenEnterIcon.classList.remove('hidden');
        fullscreenExitIcon.classList.add('hidden');

        // Hide the full post content panel
        if (fullPostContent) {
          fullPostContent.classList.remove('active');
          // Ensure display is set back to none if needed, though CSS handles visibility
          // fullPostContent.style.display = 'none'; 
        }

        // Reset the cytoscape layout
        setTimeout(() => {
          cy.resize();
          cy.fit(null, 30);
        }, 300); // Wait for transition to complete
      }
    }
    // --- Fullscreen Toggle Functionality ---
    if (fullscreenToggle) {
      fullscreenToggle.addEventListener('click', toggleFullscreen);
    }

    // Toggle fullscreen function
    function toggleFullscreen() {
      isFullscreen = !isFullscreen;

      if (isFullscreen) {
        // Enable fullscreen mode
        graphWrapper.classList.add('fullscreen');
        fullscreenEnterIcon.classList.add('hidden');
        fullscreenExitIcon.classList.remove('hidden');

        // Hide the node details panel if it's visible
        if (nodeDetailsEl) nodeDetailsEl.classList.remove('active');

        // In fullscreen, we adjust the cytoscape layout to fit
        setTimeout(() => {
          cy.resize();
          cy.fit(null, 30);
        }, 300); // Wait for transition to complete
      } else {
        // Disable fullscreen mode
        graphWrapper.classList.remove('fullscreen');
        fullscreenEnterIcon.classList.remove('hidden');
        fullscreenExitIcon.classList.add('hidden');

        // Hide the full post content panel
        if (fullPostContent) {
          fullPostContent.classList.remove('active');
        }

        // Reset the cytoscape layout
        setTimeout(() => {
          cy.resize();
          cy.fit(null, 30);
        }, 300); // Wait for transition to complete
      }
    }

    // --- Interactions ---
    let hoverTimeout;
    cy.on('mouseover', 'node', function(e) {
        const node = e.target;
        clearTimeout(hoverTimeout);
        node.addClass('highlighted');
        node.connectedEdges().addClass('highlighted');
        graphContainer.style.cursor = 'pointer';
    });

    cy.on('mouseout', 'node', function(e) {
        const node = e.target;
        hoverTimeout = setTimeout(() => {
            if (!node.selected()) {
                node.removeClass('highlighted');
                node.connectedEdges().removeClass('highlighted');
            }
        }, 100);
        graphContainer.style.cursor = 'default';
    });

    // Node click handler - dispatches to appropriate function based on fullscreen mode
    cy.on('tap', 'node', function(e) {
      const node = e.target;

      if (isFullscreen) {
        handleNodeClickFullscreen(node);
      } else {
        handleNodeClickNormal(node);
      }

      // Common highlight functionality for both modes
      cy.elements().removeClass('highlighted').removeClass('faded');
      node.addClass('highlighted');
      node.neighborhood().addClass('highlighted');
      cy.elements().difference(node.neighborhood().union(node)).addClass('faded');
    });

    // Handle node click in normal mode - shows metadata in sidebar
    function handleNodeClickNormal(node) {
      const nodeData = node.data();

      if (nodeDetailsEl) {
          // Set node title
          document.getElementById('node-title').textContent = nodeData.label;

          // Set node type
          const nodeTypeEl = document.getElementById('node-type').querySelector('.type-value') ||
                             document.getElementById('node-type');
          nodeTypeEl.textContent = nodeData.type.charAt(0).toUpperCase() + nodeData.type.slice(1);
          nodeTypeEl.className = `type-value ${nodeData.type}-type`;

          // Set category if it's a post
          const categorySection = document.getElementById('node-category');
          if (nodeData.type === 'post' && nodeData.category) {
              categorySection.style.display = 'block';
              const categoryEl = categorySection.querySelector('.category-value');
              categoryEl.textContent = nodeData.category;
              // Use category colors
              const catColor = predefinedColors[nodeData.category] || 'var(--text-secondary)';
              categoryEl.style.backgroundColor = `${catColor}33`; // Add alpha
              categoryEl.style.color = catColor;
          } else {
              categorySection.style.display = 'none';
          }

          // Set tags if it's a post
          const tagsSection = document.getElementById('node-tags');
          const tagsContainer = tagsSection.querySelector('.tags-container');

          if (nodeData.type === 'post' && nodeData.tags && nodeData.tags.length > 0) {
              tagsSection.style.display = 'block';
              tagsContainer.innerHTML = '';
              nodeData.tags.forEach(tag => {
                const tagEl = document.createElement('span');
                tagEl.className = 'tag';
                tagEl.textContent = tag;
                tagEl.addEventListener('click', () => {
                  // Find the tag node and trigger its selection
                  const tagNode = cy.getElementById(`tag-${tag}`);
                  if (tagNode.length > 0) {
                    tagNode.trigger('tap');
                  }

                  // Try to find and click tag filter button
                  try {
                    const tagFilterBtn = Array.from(
                      document.querySelectorAll('.tag-filter-btn')
                    ).find(btn => btn.dataset.tag === tag);

                    if (tagFilterBtn) {
                      tagFilterBtn.click();
                    }
                  } catch (e) {
                    console.log('Tag filter button not found');
                  }
                });
                tagsContainer.appendChild(tagEl);
              });
          } else {
              tagsSection.style.display = 'none';
          }

          // Set connections
          const connectionsList = document.getElementById('node-connections').querySelector('.connections-list');
          connectionsList.innerHTML = '';
          const connectedNodes = node.neighborhood('node');
          if (connectedNodes.length > 0) {
            connectedNodes.forEach(connectedNode => {
              const connectedData = connectedNode.data();
              const listItem = document.createElement('li');
              const link = document.createElement('a');
              link.href = '#';
              link.textContent = connectedData.label;
              link.dataset.id = connectedData.id;
              link.addEventListener('click', (evt) => {
                evt.preventDefault();
                cy.$(':selected').unselect();
                const targetNode = cy.getElementById(connectedData.id);
                if (targetNode) {
                    targetNode.select();
                    cy.animate({ center: { eles: targetNode }, zoom: cy.zoom() }, { duration: 300 });
                    targetNode.trigger('tap');
                }
              });
              listItem.appendChild(link);
              connectionsList.appendChild(listItem);
            });
          } else {
            connectionsList.innerHTML = '<li>No connections</li>';
          }

          // Set link text and URL based on node type
          const nodeLink = document.getElementById('node-link');
          if (nodeData.type === 'post') {
            nodeLink.textContent = 'Read Article';
          } else if (nodeData.type === 'tag') {
            nodeLink.textContent = 'Browse Tag';
          } else {
            nodeLink.textContent = 'View Content';
          }
          nodeLink.href = nodeData.url;

          nodeDetailsEl.classList.add('active');
      }

      // If it's a tag node, try to trigger the corresponding tag filter
      if (nodeData.type === 'tag') {
        const tagName = nodeData.label.replace(/^#/, ''); // Remove # prefix if present
        try {
          // Find and click the corresponding tag filter button
          const tagFilterBtn = Array.from(
            document.querySelectorAll('.tag-filter-btn')
          ).find(btn => btn.dataset.tag === tagName);

          if (tagFilterBtn) {
            tagFilterBtn.click();
          }

          // Scroll to the blog section
          const blogSection = document.querySelector('.blog-posts-section');
          if (blogSection) {
            blogSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
          }
        } catch (e) {
          console.log('Tag filter button not found or blog section not found');
        }
      }
    }

    // Handle node click in fullscreen mode - shows full content in side panel
    function handleNodeClickFullscreen(node) {
      const nodeData = node.data();
      console.log('Node clicked in fullscreen mode:', nodeData); // Debug log

      // Only show content for post nodes
      if (nodeData.type === 'post') {
        if (fullPostContent) {
          // Set post title
          fullPostTitle.textContent = nodeData.label;

          // Set post category if available
          if (nodeData.category) {
            const catColor = predefinedColors[nodeData.category] || 'var(--accent-primary)';
            fullPostCategory.textContent = nodeData.category;
            fullPostCategory.style.backgroundColor = `${catColor}33`;
            fullPostCategory.style.color = catColor;
            fullPostCategory.parentElement.style.display = 'flex';
          } else {
            fullPostCategory.parentElement.style.display = 'none';
          }

          // Set post tags if available
          if (nodeData.tags && nodeData.tags.length > 0) {
            fullPostTags.innerHTML = '';
            nodeData.tags.forEach(tag => {
              const tagEl = document.createElement('span');
              tagEl.className = 'post-tag';
              tagEl.textContent = tag;
              fullPostTags.appendChild(tagEl);
            });
            fullPostTags.parentElement.style.display = 'flex';
          } else {
            fullPostTags.parentElement.style.display = 'none';
          }

          // Check if content is available
          console.log('Content available:', !!nodeData.content); // Debug log

          // Display the content or a placeholder
          if (nodeData.content) {
            fullPostContainer.innerHTML = `
              <article class="post-content">
                ${nodeData.content}
              </article>
            `;
          } else {
            // Try to fetch the content if not available
            console.log('Attempting to fetch content from:', nodeData.url);
            fullPostContainer.innerHTML = `
              <div class="loading-content">
                <div class="spinner"></div>
                <p>Loading content...</p>
              </div>
            `;

            // Try to load the content from the post URL
            fetch(nodeData.url)
              .then(response => response.text())
              .then(html => {
                // Extract the post content
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                const articleContent = doc.querySelector('article') ||
                                     doc.querySelector('.content') ||
                                     doc.querySelector('main');

                if (articleContent) {
                  fullPostContainer.innerHTML = `
                    <article class="post-content">
                      ${articleContent.innerHTML}
                    </article>
                  `;
                } else {
                  // If we can't extract content, show the placeholder
                  showContentPlaceholder("Could not load content. Click 'Read Full Article' to view on the blog.");
                }
              })
              .catch(error => {
                console.error('Error fetching content:', error);
                showContentPlaceholder("Error loading content. Click 'Read Full Article' to view on the blog.");
              });
          }

          // Set the article link
          fullPostLink.href = nodeData.url || '#';

          // Make the content panel visible
          fullPostContent.classList.add('active');
          fullPostContent.style.display = 'flex';
        }
      } else {
        // Hide the content panel for non-post nodes
        if (fullPostContent) {
          fullPostContent.classList.remove('active');
          fullPostContent.style.display = 'none';
        }
      }
    }

    // Helper function to show content placeholder
    function showContentPlaceholder() {
      fullPostContainer.innerHTML = `
        <div class="full-post-placeholder">
          <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
            <polyline points="14 2 14 8 20 8"></polyline>
            <line x1="16" y1="13" x2="8" y2="13"></line>
            <line x1="16" y1="17" x2="8" y2="17"></line>
            <polyline points="10 9 9 9 8 9"></polyline>
          </svg>
          <p>Full content preview not available.</p>
        </div>
      `;
    }

    // Helper function to fetch post content if not provided
    // async function fetchPostContent(url) {
    //   if (!url || url === '#') return null;
    //   try {
    //     const response = await fetch(url);
    //     if (!response.ok) return null;
    //     const html = await response.text();
    //     const parser = new DOMParser();
    //     const doc = parser.parseFromString(html, 'text/html');
    //     const articleContent = doc.querySelector('article') || doc.querySelector('.content') || doc.querySelector('main');
    //     return articleContent ? articleContent.innerHTML : null;
    //   } catch (error) {
    //     console.error('Error fetching post content:', error);
    //     return null;
    //   }
    // }

    // Modify background click handler to account for fullscreen mode
    cy.on('tap', function(e) {
      if (e.target === cy) {
        if (nodeDetailsEl) nodeDetailsEl.classList.remove('active');
        if (isFullscreen && fullPostContent) {
          fullPostContent.classList.remove('active');
          fullPostContent.style.display = 'none'; // Ensure display is none
        }
        cy.elements().removeClass('selected highlighted faded');
      }
    });

    if (closeDetailsBtn) {
      closeDetailsBtn.addEventListener('click', () => {
        if (nodeDetailsEl) nodeDetailsEl.classList.remove('active');
        cy.$(':selected').unselect();
        cy.elements().removeClass('highlighted faded');
      });
    }
// Close full post panel button
    if (closeFullPostBtn) {
      closeFullPostBtn.addEventListener('click', () => {
        if (fullPostContent) {
          fullPostContent.classList.remove('active');
          fullPostContent.style.display = 'none'; // Ensure display is none
        }
        cy.$(':selected').unselect();
        cy.elements().removeClass('highlighted faded');
      });
    }

    // Close full post panel button
    if (closeFullPostBtn) {
      closeFullPostBtn.addEventListener('click', () => {
        if (fullPostContent) {
          fullPostContent.classList.remove('active');
        }
        cy.$(':selected').unselect();
        cy.elements().removeClass('highlighted faded');
      });
    }

    // Filter graph by node type
    const filterButtons = document.querySelectorAll('.graph-filter');
    filterButtons.forEach(button => {
      button.addEventListener('click', () => {
        filterButtons.forEach(btn => btn.classList.remove('active'));
        button.classList.add('active');
        const filter = button.dataset.filter;

        if (filter === 'all') {
          cy.elements().removeClass('faded highlighted filtered');
        } else if (filter === 'posts') {
          cy.elements().addClass('faded').removeClass('highlighted filtered');
          const postNodes = cy.nodes().filter(node => node.data('type') === 'post');
          postNodes.removeClass('faded').addClass('filtered');
        } else if (filter === 'tags') {
          cy.elements().addClass('faded').removeClass('highlighted filtered');
          const tagNodes = cy.nodes().filter(node => node.data('type') === 'tag');
          tagNodes.removeClass('faded').addClass('filtered');
        }
      });
    });

    // Zoom controls
    document.getElementById('zoom-in')?.addEventListener('click', () => cy.zoom(cy.zoom() * 1.2));
    document.getElementById('zoom-out')?.addEventListener('click', () => cy.zoom(cy.zoom() / 1.2));
    document.getElementById('reset-graph')?.addEventListener('click', () => {
        cy.fit(null, 30);
        cy.elements().removeClass('faded highlighted filtered');
        const allFilterButton = document.querySelector('.graph-filter[data-filter="all"]');
        if (allFilterButton) allFilterButton.click();
    });

    // Add mouse wheel zoom controls
    cy.on('zoom', function() {
      if (cy.zoom() > 1.5) {
        cy.style().selector('node').style({ 'text-max-width': '150px', 'font-size': '12px' }).update();
      } else {
        cy.style().selector('node').style({ 'text-max-width': '120px', 'font-size': '10px' }).update();
      }
    });

    // Apply initial filter if specified
    if (initialFilter && initialFilter !== 'all') {
      const filterButton = document.querySelector(`.graph-filter[data-filter="${initialFilter}"]`);
      if (filterButton) {
        setTimeout(() => filterButton.click(), 500);
      }
    }

    // Connect search input if it exists
    const searchInput = document.getElementById('search-input');
    if (searchInput) {
      searchInput.addEventListener('input', e => {
        const term = e.target.value.toLowerCase();

        if (!term) {
          // Reset graph view if search is cleared
          cy.elements().removeClass('highlighted faded filtered');
          const allFilterBtn = document.querySelector('.graph-filter[data-filter="all"]');
          if (allFilterBtn) allFilterBtn.click();
          return;
        }

        // Reset previous filters
        cy.elements().addClass('faded').removeClass('highlighted filtered');

        // Find nodes that match the search term
        const matchingNodes = cy.nodes().filter(node => {
          const label = node.data('label').toLowerCase();
          return label.includes(term);
        });

        if (matchingNodes.length) {
          matchingNodes.removeClass('faded').addClass('highlighted');
          matchingNodes.connectedEdges().removeClass('faded');
        }
      });
    }

    // Connect tag filter buttons if they exist
    const tagFilterButtons = document.querySelectorAll('.tag-filter-btn');
    if (tagFilterButtons.length) {
      tagFilterButtons.forEach(btn => {
        btn.addEventListener('click', () => {
          const tagName = btn.dataset.tag;

          if (tagName === 'all') {
            // Reset graph view if "All" is selected
            cy.elements().removeClass('highlighted faded filtered');
            const allFilterBtn = document.querySelector('.graph-filter[data-filter="all"]');
// Listen for ESC key to exit fullscreen
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Escape' && isFullscreen) {
        toggleFullscreen();
      }
    });

    // Update window resize handler to preserve layout in fullscreen mode
    window.addEventListener('resize', () => {
      if (cy) {
        cy.resize();
        if (!isFullscreen) {
          cy.fit(null, 30);
        }
      }
    });
            if (allFilterBtn) allFilterBtn.click();
            return;
          }

          // Find the tag node
          const tagNode = cy.nodes().filter(node =>
            node.data('type') === 'tag' &&
            node.data('label') === tagName
          );

          if (tagNode.length) {
            // Highlight this tag and connected posts in the graph
            cy.elements().addClass('faded').removeClass('highlighted filtered');
            tagNode.removeClass('faded').addClass('highlighted');

            // Get connected posts
            const connectedPosts = tagNode.neighborhood('node[type="post"]');
            connectedPosts.removeClass('faded').addClass('filtered');

            // Highlight connecting edges
            tagNode.connectedEdges().removeClass('faded').addClass('highlighted');
          }
        });
      });
    }

    // Dispatch graphReady event for external listeners
    document.dispatchEvent(new CustomEvent('graphReady', { detail: { cy } }));

    // Listen for ESC key to exit fullscreen
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Escape' && isFullscreen) {
        toggleFullscreen();
      }
    });

    // Update window resize handler to preserve layout in fullscreen mode
    window.addEventListener('resize', () => {
      if (cy) {
        cy.resize();
        if (!isFullscreen) {
          cy.fit(null, 30);
        }
      }
    });
  }

  // Initialize graph on DOMContentLoaded or if already loaded
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initializeGraph);
  } else {
    initializeGraph();
  }
</script>

<style>
  /* Updated Graph Container Styles */
  .graph-container-wrapper {
    position: relative;
    width: 100%;
    height: var(--graph-height, 50vh);
    min-height: 400px;
    max-height: 800px;
    margin-bottom: 2rem;
    transition: all 0.5s cubic-bezier(0.19, 1, 0.22, 1);
  }

  /* Improved Fullscreen mode styles */
  .graph-container-wrapper.fullscreen {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    max-height: 100vh;
    z-index: 9999;
    margin: 0;
    padding: 0;
    background: var(--bg-primary);
    backdrop-filter: blur(10px);
    display: flex;
    border-radius: 0;
    overflow: hidden;
  }

  .graph-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border-radius: 12px;
    overflow: hidden;
    border: 1px solid var(--card-border);
    background: rgba(15, 23, 42, 0.2);
    backdrop-filter: blur(5px);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
    transition: all 0.3s ease;
  }

  /* Adjust graph container in fullscreen mode */
  .graph-container-wrapper.fullscreen .graph-container {
    position: relative;
    width: 60%;
    height: 100%;
    border-radius: 0;
    margin: 0;
    border: none;
    border-right: 1px solid var(--border-primary);
  }

  #knowledge-graph {
    width: 100%;
    height: 100%;
    z-index: 1;
  }

  /* Overlay instructions - position over the graph instead of taking up space */
  .graph-instructions.overlay {
    position: absolute;
    top: 20px;
    left: 20px;
    width: auto;
    max-width: 350px;
    z-index: 5;
    margin: 0;
  }

  .graph-container-wrapper.fullscreen .graph-instructions.overlay {
    top: 80px;
  }

  .instructions-details {
    background: rgba(15, 23, 42, 0.75);
    border-radius: 8px;
    border: 1px solid var(--border-primary);
    overflow: hidden;
    transition: all 0.3s ease;
    backdrop-filter: blur(5px);
  }

  .instructions-details[open] {
    padding-bottom: 1rem;
  }

  .instructions-summary {
    padding: 0.75rem 1rem;
    cursor: pointer;
    color: var(--text-primary);
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }

  .instructions-summary::before {
    content: "ℹ️";
    font-size: 1rem;
  }

  .instructions-content {
    padding: 0 1rem;
    color: var(--text-secondary);
  }

  .instructions-content ul {
    padding-left: 1.5rem;
    margin: 0.5rem 0 1rem;
  }

  .node-example {
    display: inline-block;
    width: 12px;
    height: 12px;
    margin-right: 0.25rem;
    vertical-align: middle;
  }

  .post-node {
    background-color: #3B82F6;
    border-radius: 50%;
  }

  .tag-node {
    background-color: #10B981;
    transform: rotate(45deg);
  }

  /* Fullscreen Toggle Button */
  .fullscreen-toggle {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    background: rgba(30, 41, 59, 0.7);
    border: 1px solid var(--border-primary);
    color: var(--text-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 6;
    transition: all 0.2s ease;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }

  .fullscreen-toggle:hover {
    background: rgba(30, 41, 59, 0.9);
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
  }

  .graph-container-wrapper.fullscreen .fullscreen-toggle {
    top: 20px;
    right: 20px;
  }

  /* Hide one of the fullscreen icons */
  .hidden {
    display: none;
  }

  /* Full Post Content Panel - Improved styling */
  .full-post-content {
    position: absolute;
    top: 0;
    right: 0;
    width: 0;
    height: 100%;
    overflow: hidden;
    transition: all 0.3s cubic-bezier(0.19, 1, 0.22, 1);
    background: var(--bg-secondary);
    border-radius: 12px;
    opacity: 0;
    z-index: 4;
    border: 1px solid var(--card-border);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
    visibility: hidden;
    display: none;
  }

  /* Full post panel in fullscreen mode */
  .graph-container-wrapper.fullscreen .full-post-content {
    position: relative;
    width: 40%;
    height: 100%;
    background: rgba(15, 23, 42, 0.95);
    backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    opacity: 1;
    visibility: visible;
    border: none;
    border-radius: 0;
    box-shadow: none;
  }

  .graph-container-wrapper.fullscreen .full-post-content.active {
    display: flex;
  }

  .full-post-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1.5rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(15, 23, 42, 0.8);
  }

  .full-post-title {
    font-size: 1.5rem;
    margin: 0;
    color: var(--text-primary);
    font-weight: 600;
    line-height: 1.3;
  }

  .full-post-metadata {
    padding: 1rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    background: rgba(15, 23, 42, 0.6);
  }

  .metadata-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }

  .metadata-label {
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-family: var(--font-mono);
  }

  .full-post-category {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    border-radius: 20px;
    font-size: 0.85rem;
    font-weight: 500;
    font-family: var(--font-mono);
  }

  .full-post-tags {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
  }

  .post-tag {
    background: rgba(16, 185, 129, 0.1);
    color: #10B981;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-size: 0.75rem;
    font-family: var(--font-mono);
    transition: all 0.2s ease;
  }

  .post-tag:hover {
    background: rgba(16, 185, 129, 0.2);
    transform: translateY(-2px);
  }

  .full-post-container {
    flex: 1;
    padding: 1.5rem;
    overflow-y: auto;
    color: var(--text-primary);
    background: var(--bg-secondary);
  }

  .full-post-container::-webkit-scrollbar {
    width: 8px;
  }

  .full-post-container::-webkit-scrollbar-track {
    background: rgba(30, 41, 59, 0.5);
    border-radius: 4px;
  }

  .full-post-container::-webkit-scrollbar-thumb {
    background: rgba(226, 232, 240, 0.1);
    border-radius: 4px;
  }

  .full-post-container::-webkit-scrollbar-thumb:hover {
    background: rgba(226, 232, 240, 0.2);
  }

  .full-post-placeholder {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    text-align: center;
    padding: 2rem;
  }

  .full-post-placeholder svg {
    margin-bottom: 1rem;
    opacity: 0.5;
  }

  .post-content {
    line-height: 1.7;
    font-size: 1rem;
  }

  .post-content h1, .post-content h2, .post-content h3,
  .post-content h4, .post-content h5, .post-content h6 {
    margin-top: 1.5rem;
    margin-bottom: 1rem;
    color: var(--text-primary);
    font-weight: 600;
  }

  .post-content p {
    margin-bottom: 1.25rem;
  }

  .post-content a {
    color: var(--accent-primary);
    text-decoration: none;
    border-bottom: 1px dotted var(--accent-primary);
    transition: all 0.2s ease;
  }

  .post-content a:hover {
    color: var(--accent-secondary);
    border-bottom-style: solid;
  }

  .post-content pre {
    background: rgba(15, 23, 42, 0.6);
    padding: 1rem;
    border-radius: 6px;
    overflow-x: auto;
    margin: 1.5rem 0;
    border: 1px solid var(--border-primary);
  }

  .post-content code {
    font-family: var(--font-mono);
    font-size: 0.9rem;
  }

  .post-content img {
    max-width: 100%;
    height: auto;
    margin: 1.5rem 0;
    border-radius: 6px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
  }

  .post-content blockquote {
    border-left: 4px solid var(--accent-primary);
    padding-left: 1rem;
    margin-left: 0;
    margin-right: 0;
    font-style: italic;
    color: var(--text-secondary);
  }

  .post-content ul, .post-content ol {
    padding-left: 1.5rem;
    margin-bottom: 1.25rem;
  }

  .post-content li {
    margin-bottom: 0.5rem;
  }

  .full-post-footer {
    padding: 1rem;
    background: rgba(15, 23, 42, 0.7);
    border-top: 1px solid rgba(255, 255, 255, 0.05);
  }

  .full-post-link {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1rem;
    background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
    color: var(--bg-primary);
    text-decoration: none;
    font-weight: 500;
    transition: all 0.3s ease;
    border-radius: 6px;
  }

  .full-post-link:hover {
    background: linear-gradient(90deg, var(--accent-secondary), var(--accent-primary));
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(6, 182, 212, 0.3);
  }

  /* Media Queries for Fullscreen */
  @media screen and (max-width: 992px) {
    /* Adjust fullscreen layout for smaller screens */
    .graph-container-wrapper.fullscreen {
      flex-direction: column;
    }

    .graph-container-wrapper.fullscreen .graph-container {
      width: 100%;
      height: 50%;
      margin-right: 0;
    }

    .graph-container-wrapper.fullscreen .full-post-content {
      width: 100%;
      height: 50%;
    }
  }

  @media screen and (max-width: 768px) {
    .node-details {
      width: 85%;
      max-width: 300px;
      left: 50%;
      right: auto;
      transform: translate(-50%, 120%);
      bottom: 20px;
      top: auto;
    }

    .node-details.active {
      transform: translate(-50%, 0);
    }

    .graph-instructions.overlay {
      top: 15px;
      left: 15px;
      max-width: 300px;
    }

    .graph-controls {
      bottom: 10px;
    }

    .graph-filters {
      padding: 0.5rem;
    }

    .graph-filter {
      padding: 0.3rem 0.6rem;
      font-size: 0.75rem;
    }

    .fullscreen-toggle {
      top: 15px;
      right: 15px;
      width: 36px;
      height: 36px;
    }

    .graph-container-wrapper.fullscreen .graph-container {
      height: 40%;
    }

    .graph-container-wrapper.fullscreen .full-post-content {
      height: 60%;
    }

    .full-post-header {
      padding: 1rem;
    }

    .full-post-title {
      font-size: 1.25rem;
    }

    .full-post-metadata {
      padding: 0.75rem 1rem;
    }

    .full-post-container {
      padding: 1rem;
    }
  }

  @media screen and (max-width: 480px) {
    .graph-container-wrapper.fullscreen {
      padding: 0;
    }

    .graph-container-wrapper.fullscreen .graph-container {
      height: 35%;
    }

    .graph-container-wrapper.fullscreen .full-post-content {
      height: 65%;
    }

    .full-post-title {
      font-size: 1.1rem;
    }

    .graph-instructions.overlay {
      max-width: 250px;
    }
  }

  /* Graph Container Styles */
  /* .graph-container-wrapper is defined earlier */
  /* .graph-container is defined earlier */
  /* #knowledge-graph is defined earlier */

  /* Loading Animation */
  .graph-loading {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: rgba(15, 23, 42, 0.7);
    z-index: 10;
    transition: opacity 0.5s ease, visibility 0.5s ease;
    border-radius: 12px;
  }

  .graph-loading.hidden {
    opacity: 0;
    visibility: hidden;
  }

  .loading-spinner {
    position: relative;
    width: 80px;
    height: 80px;
    margin-bottom: 1rem;
  }

  .spinner-ring {
    position: absolute;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    border: 3px solid transparent;
    border-top-color: var(--accent-primary);
    animation: spin 1.5s linear infinite;
  }

  .spinner-ring:nth-child(2) {
    width: calc(100% - 15px);
    height: calc(100% - 15px);
    top: 7.5px;
    left: 7.5px;
    border-top-color: var(--accent-secondary);
    animation-duration: 2s;
    animation-direction: reverse;
  }

  .spinner-ring:nth-child(3) {
    width: calc(100% - 30px);
    height: calc(100% - 30px);
    top: 15px;
    left: 15px;
    border-top-color: var(--accent-tertiary);
    animation-duration: 2.5s;
  }

  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }

  .loading-text {
    color: var(--text-primary);
    font-family: var(--font-mono);
    font-size: 1rem;
    letter-spacing: 0.05em;
  }

  /* Node Details Panel */
  .node-details {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 300px;
    background: var(--bg-secondary);
    border: 1px solid var(--card-border);
    border-radius: 10px;
    padding: 1.5rem;
    z-index: 5;
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
    transform: translateX(120%);
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
    opacity: 0;
    backdrop-filter: blur(10px);
  }

  .node-details.active {
    transform: translateX(0);
    opacity: 1;
  }

  .node-details-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 1rem;
  }

  .node-title {
    font-size: 1.2rem;
    margin: 0;
    color: var(--text-primary);
    font-weight: 600;
    line-height: 1.3;
  }

  .close-button {
    background: none;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    padding: 5px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
  }

  .close-button:hover {
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.1);
  }

  .node-type {
    margin-bottom: 1rem;
  }

  .type-value {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    border-radius: 20px;
    font-size: 0.85rem;
    font-weight: 500;
  }

  .post-type {
    background-color: rgba(59, 130, 246, 0.15);
    color: #3B82F6;
  }

  .tag-type {
    background-color: rgba(16, 185, 129, 0.15);
    color: #10B981;
  }

  .category-type {
    background-color: rgba(139, 92, 246, 0.15);
    color: #8B5CF6;
  }

  .node-category, .node-tags, .node-connections {
    margin-bottom: 1.25rem;
  }

  .category-label, .tags-label, .connections-label {
    display: block;
    color: var(--text-secondary);
    font-size: 0.85rem;
    margin-bottom: 0.5rem;
    font-family: var(--font-mono);
  }

  .category-value {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    border-radius: 20px;
    font-size: 0.85rem;
    font-family: var(--font-mono);
  }

  .tags-container {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  .tag {
    background: rgba(16, 185, 129, 0.1);
    color: #10B981;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-size: 0.75rem;
    cursor: pointer;
    transition: all 0.2s ease;
  }

  .tag:hover {
    background: rgba(16, 185, 129, 0.2);
    transform: translateY(-2px);
  }

  .no-tags {
    color: var(--text-tertiary);
    font-style: italic;
    font-size: 0.8rem;
  }

  .connections-list {
    padding-left: 0;
    list-style: none;
    margin: 0;
    max-height: 150px;
    overflow-y: auto;
  }

  .connections-list li {
    color: var(--text-secondary);
    font-size: 0.9rem;
    margin-bottom: 0.5rem;
  }

  .connections-list a {
    color: var(--accent-primary);
    text-decoration: none;
    transition: color 0.2s ease;
  }

  .connections-list a:hover {
    color: var(--accent-secondary);
    text-decoration: underline;
  }

  .node-link {
    display: block;
    background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
    color: var(--bg-primary);
    font-weight: 500;
    padding: 0.6rem 1.25rem;
    border-radius: 6px;
    text-decoration: none;
    text-align: center;
    transition: all 0.3s ease;
    box-shadow: 0 4px 10px rgba(6, 182, 212, 0.2);
    margin-top: 1rem;
  }

  .node-link:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 15px rgba(6, 182, 212, 0.3);
  }

  /* Graph Controls */
  .graph-controls {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    gap: 1rem;
    z-index: 5;
  }

  .graph-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
    padding: 0.75rem;
    background: rgba(15, 23, 42, 0.7);
    backdrop-filter: blur(10px);
    border-radius: 30px;
    border: 1px solid var(--border-primary);
  }

  .graph-filter {
    background: rgba(226, 232, 240, 0.05);
    color: var(--text-secondary);
    border: 1px solid var(--border-secondary);
    padding: 0.4rem 0.8rem;
    border-radius: 30px;
    font-size: 0.8rem;
    cursor: pointer;
    transition: all 0.2s ease;
    font-family: var(--font-mono);
    position: relative;
    overflow: hidden;
  }

  .graph-filter::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 100%;
    background: var(--filter-color, 'transparent');
    opacity: 0.15;
    transition: width 0.3s ease;
  }

  .graph-filter:hover::before {
    width: 100%;
  }

  .graph-filter:hover {
    color: var(--text-primary);
    border-color: var(--filter-color, rgba(56, 189, 248, 0.4));
    transform: translateY(-2px);
  }

  .graph-filter.active {
    background-color: var(--filter-color, var(--accent-primary));
    color: var(--bg-primary);
    border-color: var(--filter-color, var(--accent-primary));
    font-weight: 600;
  }

  .graph-filter.active::before {
    width: 100%;
    opacity: 0.2;
  }

  .graph-actions {
    display: flex;
    justify-content: center;
    gap: 0.75rem;
  }

  .graph-action {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--bg-secondary);
    border: 1px solid var(--border-primary);
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
  }

  .graph-action:hover {
    color: var(--text-primary);
    background: var(--bg-tertiary);
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  }

  /* Graph Instructions are defined earlier as overlay */
  /* Media Queries are defined earlier */

  /* Styles for rendered post content */
  .post-content {
    line-height: 1.7;
    font-size: 1rem;
    overflow-wrap: break-word;
    word-wrap: break-word;
  }

  .post-content * {
    max-width: 100%;
  }

  .post-content h1, .post-content h2, .post-content h3,
  .post-content h4, .post-content h5, .post-content h6 {
    margin-top: 1.5rem;
    margin-bottom: 1rem;
    color: var(--text-primary);
    font-weight: 600;
    line-height: 1.3;
  }

  .post-content h1 { font-size: 1.875rem; }
  .post-content h2 { font-size: 1.5rem; }
  .post-content h3 { font-size: 1.25rem; }
  .post-content h4 { font-size: 1.125rem; }
  .post-content h5, .post-content h6 { font-size: 1rem; }

  .post-content p {
    margin-bottom: 1.25rem;
  }

  .post-content a {
    color: var(--accent-primary);
    text-decoration: none;
    border-bottom: 1px dotted var(--accent-primary);
    transition: all 0.2s ease;
  }

  .post-content a:hover {
    color: var(--accent-secondary);
    border-bottom-style: solid;
  }

  .post-content pre {
    background: rgba(15, 23, 42, 0.6);
    padding: 1rem;
    border-radius: 6px;
    overflow-x: auto;
    margin: 1.5rem 0;
    border: 1px solid var(--border-primary);
  }

  .post-content code {
    font-family: var(--font-mono);
    font-size: 0.9rem;
    background: rgba(15, 23, 42, 0.4);
    padding: 0.2em 0.4em;
    border-radius: 3px;
  }

  .post-content pre code {
    background: transparent;
    padding: 0;
  }

  .post-content img {
    max-width: 100%;
    height: auto;
    margin: 1.5rem auto;
    border-radius: 6px;
    display: block;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
  }

  .post-content blockquote {
    border-left: 4px solid var(--accent-primary);
    padding-left: 1rem;
    margin-left: 0;
    margin-right: 0;
    font-style: italic;
    color: var(--text-secondary);
  }

  .post-content ul, .post-content ol {
    padding-left: 1.5rem;
    margin-bottom: 1.25rem;
  }

  .post-content li {
    margin-bottom: 0.5rem;
  }

  .post-content table {
    width: 100%;
    border-collapse: collapse;
    margin: 1.5rem 0;
    overflow-x: auto;
    display: block;
  }

  .post-content table th,
  .post-content table td {
    border: 1px solid rgba(255, 255, 255, 0.1);
    padding: 0.5rem;
  }

  .post-content table th {
    background: rgba(30, 41, 59, 0.5);
    font-weight: 600;
  }

  .post-content table tr:nth-child(even) {
    background: rgba(30, 41, 59, 0.3);
  }

  .post-content iframe {
    max-width: 100%;
    margin: 1.5rem 0;
  }

  /* Make iframes responsive */
  .post-content .video-container {
    position: relative;
    padding-bottom: 56.25%; /* 16:9 */
    height: 0;
    overflow: hidden;
    margin: 1.5rem 0;
  }

  .post-content .video-container iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
/* Loading indicator styles */
  .loading-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--text-secondary);
  }

  .spinner {
    width: 40px;
    height: 40px;
    border: 3px solid rgba(59, 130, 246, 0.3);
    border-radius: 50%;
    border-top-color: var(--accent-primary, #3b82f6);
    animation: spin 1s linear infinite;
    margin-bottom: 1rem;
  }

  @keyframes spin {
    to { transform: rotate(360deg); }
  }
/* Fullscreen mode styles */
  .graph-container-wrapper.fullscreen {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    max-height: 100vh;
    z-index: 9999;
    margin: 0;
    padding: 20px;
    background: var(--bg-primary);
    backdrop-filter: blur(10px);
    display: flex;
    border-radius: 0;
    transition: all 0.5s cubic-bezier(0.19, 1, 0.22, 1);
  }

  /* Adjust graph container in fullscreen mode */
  .graph-container-wrapper.fullscreen .graph-container {
    position: relative;
    width: 60%;
    height: 100%;
    border-radius: 12px;
    margin-right: 20px;
  }

  /* Fullscreen Toggle Button */
  .fullscreen-toggle {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    background: rgba(30, 41, 59, 0.7);
    border: 1px solid var(--border-primary);
    color: var(--text-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 4;
    transition: all 0.2s ease;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }

  .fullscreen-toggle:hover {
    background: rgba(30, 41, 59, 0.9);
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
  }

  .graph-container-wrapper.fullscreen .fullscreen-toggle {
    top: 25px;
    right: 25px;
  }

  /* Hide one of the fullscreen icons */
  .hidden {
    display: none;
  }

  /* Full Post Content Panel */
  .full-post-content {
    position: absolute;
    top: 0;
    right: 0;
    width: 0;
    height: 100%;
    overflow: hidden;
    transition: all 0.3s cubic-bezier(0.19, 1, 0.22, 1);
    background: var(--bg-secondary);
    border-radius: 12px;
    opacity: 0;
    z-index: 4;
    border: 1px solid var(--card-border);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
    visibility: hidden;
    display: none;
  }

  /* Full post panel in fullscreen mode */
  .graph-container-wrapper.fullscreen .full-post-content {
    position: relative;
    width: 40%;
    height: 100%;
    background: rgba(30, 41, 59, 0.7);
    backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    opacity: 1;
    visibility: visible;
  }

  .graph-container-wrapper.fullscreen .full-post-content.active {
    display: flex;
  }

  .full-post-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 1.5rem;
    border-bottom: 1px solid var(--border-primary);
  }

  .full-post-title {
    font-size: 1.5rem;
    margin: 0;
    color: var(--text-primary);
    font-weight: 600;
    line-height: 1.3;
  }

  .full-post-metadata {
    padding: 1rem 1.5rem;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: center;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  }

  .full-post-category {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    border-radius: 20px;
    font-size: 0.85rem;
    font-weight: 500;
    font-family: var(--font-mono);
  }

  .full-post-tags {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
  }

  .post-tag {
    background: rgba(16, 185, 129, 0.1);
    color: #10B981;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-size: 0.75rem;
    font-family: var(--font-mono);
  }

  .full-post-container {
    flex: 1;
    padding: 1.5rem;
    overflow-y: auto;
    color: var(--text-primary);
  }

  .full-post-container::-webkit-scrollbar {
    width: 8px;
  }

  .full-post-container::-webkit-scrollbar-track {
    background: rgba(30, 41, 59, 0.5);
    border-radius: 4px;
  }

  .full-post-container::-webkit-scrollbar-thumb {
    background: rgba(226, 232, 240, 0.1);
    border-radius: 4px;
  }

  .full-post-container::-webkit-scrollbar-thumb:hover {
    background: rgba(226, 232, 240, 0.2);
  }

  .full-post-placeholder {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    text-align: center;
    padding: 2rem;
  }

  .full-post-placeholder svg {
    margin-bottom: 1rem;
    opacity: 0.5;
  }

  .post-content {
    line-height: 1.7;
    font-size: 1rem;
  }

  .post-content h1, .post-content h2, .post-content h3,
  .post-content h4, .post-content h5, .post-content h6 {
    margin-top: 1.5rem;
    margin-bottom: 1rem;
    color: var(--text-primary);
    font-weight: 600;
  }

  .post-content p {
    margin-bottom: 1.25rem;
  }

  .post-content a {
    color: var(--accent-primary);
    text-decoration: none;
    border-bottom: 1px dotted var(--accent-primary);
    transition: all 0.2s ease;
  }

  .post-content a:hover {
    color: var(--accent-secondary);
    border-bottom-style: solid;
  }

  .post-content pre {
    background: rgba(15, 23, 42, 0.6);
    padding: 1rem;
    border-radius: 6px;
    overflow-x: auto;
    margin: 1.5rem 0;
    border: 1px solid var(--border-primary);
  }

  .post-content code {
    font-family: var(--font-mono);
    font-size: 0.9rem;
  }

  .post-content img {
    max-width: 100%;
    height: auto;
    margin: 1.5rem 0;
    border-radius: 6px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
  }

  .post-content blockquote {
    border-left: 4px solid var(--accent-primary);
    padding-left: 1rem;
    margin-left: 0;
    margin-right: 0;
    font-style: italic;
    color: var(--text-secondary);
  }

  .post-content ul, .post-content ol {
    padding-left: 1.5rem;
    margin-bottom: 1.25rem;
  }

  .post-content li {
    margin-bottom: 0.5rem;
  }

  .full-post-link {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1rem;
    background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
    color: var(--bg-primary);
    text-decoration: none;
    font-weight: 500;
    transition: all 0.3s ease;
  }

  .full-post-link:hover {
    background: linear-gradient(90deg, var(--accent-secondary), var(--accent-primary));
  }

  /* Media Queries */
  @media screen and (max-width: 992px) {
    /* Adjust fullscreen layout for smaller screens */
    .graph-container-wrapper.fullscreen {
      flex-direction: column;
      padding: 15px;
    }

    .graph-container-wrapper.fullscreen .graph-container {
      width: 100%;
      height: 50%;
      margin-right: 0;
      margin-bottom: 15px;
    }

    .graph-container-wrapper.fullscreen .full-post-content {
      width: 100%;
      height: 50%;
    }
  }

  @media screen and (max-width: 768px) {
    .fullscreen-toggle {
      top: 15px;
      right: 15px;
      width: 36px;
      height: 36px;
    }

    .graph-container-wrapper.fullscreen .graph-container {
      height: 40%;
    }

    .graph-container-wrapper.fullscreen .full-post-content {
      height: 60%;
    }

    .full-post-header {
      padding: 1rem;
    }

    .full-post-title {
      font-size: 1.25rem;
    }

    .full-post-metadata {
      padding: 0.75rem 1rem;
    }

    .full-post-container {
      padding: 1rem;
    }
  }

  @media screen and (max-width: 480px) {
    .graph-container-wrapper.fullscreen {
      padding: 10px;
    }

    .graph-container-wrapper.fullscreen .graph-container {
      height: 35%;
    }

    .graph-container-wrapper.fullscreen .full-post-content {
      height: 65%;
    }

    .full-post-title {
      font-size: 1.1rem;
    }
  }
</style>