introduce concepts phase 3 (tool modals)
This commit is contained in:
		
							parent
							
								
									202ee5f801
								
							
						
					
					
						commit
						e7800724bb
					
				@ -139,12 +139,14 @@ domains.forEach((domain: any) => {
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<!-- Tool Details Modal stays the same -->
 | 
			
		||||
<div class="modal-overlay" id="modal-overlay" onclick="window.hideToolDetails()"></div>
 | 
			
		||||
<div class="tool-details" id="tool-details">
 | 
			
		||||
<!-- Tool Details Modals - Dual Modal System -->
 | 
			
		||||
<div class="modal-overlay" id="modal-overlay" onclick="window.hideAllToolDetails()"></div>
 | 
			
		||||
 | 
			
		||||
<!-- Primary Modal -->
 | 
			
		||||
<div class="tool-details" id="tool-details-primary">
 | 
			
		||||
  <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem;">
 | 
			
		||||
    <h2 id="tool-name" style="margin: 0;">Tool Name</h2>
 | 
			
		||||
    <button class="btn-icon" onclick="window.hideToolDetails()">
 | 
			
		||||
    <h2 id="tool-name-primary" style="margin: 0;">Tool Name</h2>
 | 
			
		||||
    <button class="btn-icon" onclick="window.hideToolDetails('primary')">
 | 
			
		||||
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
 | 
			
		||||
        <line x1="18" y1="6" x2="6" y2="18"></line>
 | 
			
		||||
        <line x1="6" y1="6" x2="18" y2="18"></line>
 | 
			
		||||
@ -152,15 +154,38 @@ domains.forEach((domain: any) => {
 | 
			
		||||
    </button>
 | 
			
		||||
  </div>
 | 
			
		||||
  
 | 
			
		||||
  <p id="tool-description" class="text-muted"></p>
 | 
			
		||||
  <p id="tool-description-primary" class="text-muted"></p>
 | 
			
		||||
  
 | 
			
		||||
  <div id="tool-badges" style="display: flex; gap: 0.5rem; margin-bottom: 1rem;"></div>
 | 
			
		||||
  <div id="tool-badges-primary" style="display: flex; gap: 0.5rem; margin-bottom: 1rem;"></div>
 | 
			
		||||
  
 | 
			
		||||
  <div id="tool-metadata" style="margin-bottom: 1rem;"></div>
 | 
			
		||||
  <div id="tool-metadata-primary" style="margin-bottom: 1rem;"></div>
 | 
			
		||||
  
 | 
			
		||||
  <div id="tool-tags" style="margin-bottom: 1rem;"></div>
 | 
			
		||||
  <div id="tool-tags-primary" style="margin-bottom: 1rem;"></div>
 | 
			
		||||
  
 | 
			
		||||
  <div id="tool-links" style="display: flex; gap: 0.5rem; flex-direction: column;"></div>
 | 
			
		||||
  <div id="tool-links-primary" style="display: flex; gap: 0.5rem; flex-direction: column;"></div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<!-- Secondary Modal -->
 | 
			
		||||
<div class="tool-details" id="tool-details-secondary">
 | 
			
		||||
  <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem;">
 | 
			
		||||
    <h2 id="tool-name-secondary" style="margin: 0;">Tool Name</h2>
 | 
			
		||||
    <button class="btn-icon" onclick="window.hideToolDetails('secondary')">
 | 
			
		||||
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
 | 
			
		||||
        <line x1="18" y1="6" x2="6" y2="18"></line>
 | 
			
		||||
        <line x1="6" y1="6" x2="18" y2="18"></line>
 | 
			
		||||
      </svg>
 | 
			
		||||
    </button>
 | 
			
		||||
  </div>
 | 
			
		||||
  
 | 
			
		||||
  <p id="tool-description-secondary" class="text-muted"></p>
 | 
			
		||||
  
 | 
			
		||||
  <div id="tool-badges-secondary" style="display: flex; gap: 0.5rem; margin-bottom: 1rem;"></div>
 | 
			
		||||
  
 | 
			
		||||
  <div id="tool-metadata-secondary" style="margin-bottom: 1rem;"></div>
 | 
			
		||||
  
 | 
			
		||||
  <div id="tool-tags-secondary" style="margin-bottom: 1rem;"></div>
 | 
			
		||||
  
 | 
			
		||||
  <div id="tool-links-secondary" style="display: flex; gap: 0.5rem; flex-direction: column;"></div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script define:vars={{ toolsData: tools, domainAgnosticSoftware, domainAgnosticTools }}>
 | 
			
		||||
@ -244,68 +269,131 @@ domains.forEach((domain: any) => {
 | 
			
		||||
  // Make functions globally available
 | 
			
		||||
  window.toggleDomainAgnosticSection = toggleDomainAgnosticSection;
 | 
			
		||||
 | 
			
		||||
  // Tool details functions (unchanged)
 | 
			
		||||
  window.showToolDetails = function(toolName) {
 | 
			
		||||
  // Enhanced modal system for side-by-side display
 | 
			
		||||
  window.showToolDetails = function(toolName, modalType = 'primary') {
 | 
			
		||||
    const tool = toolsData.find(t => t.name === toolName);
 | 
			
		||||
    if (!tool) return;
 | 
			
		||||
    if (!tool) {
 | 
			
		||||
      console.error('Tool not found:', toolName);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    const isMethod = tool.type === 'method';
 | 
			
		||||
    const isConcept = tool.type === 'concept';
 | 
			
		||||
    
 | 
			
		||||
    // Get modal-specific element IDs
 | 
			
		||||
    const elements = {
 | 
			
		||||
      name: document.getElementById(`tool-name-${modalType}`),
 | 
			
		||||
      description: document.getElementById(`tool-description-${modalType}`),
 | 
			
		||||
      badges: document.getElementById(`tool-badges-${modalType}`),
 | 
			
		||||
      metadata: document.getElementById(`tool-metadata-${modalType}`),
 | 
			
		||||
      tags: document.getElementById(`tool-tags-${modalType}`),
 | 
			
		||||
      links: document.getElementById(`tool-links-${modalType}`)
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Check if all elements exist
 | 
			
		||||
    for (const [key, element] of Object.entries(elements)) {
 | 
			
		||||
      if (!element) {
 | 
			
		||||
        console.error(`Element not found: tool-${key}-${modalType}`);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Update modal content
 | 
			
		||||
    const toolNameElement = document.getElementById('tool-name');
 | 
			
		||||
    const iconHtml = tool.icon ? `<span style="margin-right: 0.75rem; font-size: 1.5rem;">${tool.icon}</span>` : '';
 | 
			
		||||
    toolNameElement.innerHTML = `${iconHtml}${tool.name}`;
 | 
			
		||||
    document.getElementById('tool-description').textContent = tool.description;
 | 
			
		||||
    elements.name.innerHTML = `${iconHtml}${tool.name}`;
 | 
			
		||||
    elements.description.textContent = tool.description;
 | 
			
		||||
 | 
			
		||||
    // Badges - Only CC24-Server and Knowledgebase
 | 
			
		||||
    const badgesContainer = document.getElementById('tool-badges');
 | 
			
		||||
    // Badges
 | 
			
		||||
    const hasValidProjectUrl = tool.projectUrl !== undefined && 
 | 
			
		||||
                              tool.projectUrl !== null && 
 | 
			
		||||
                              tool.projectUrl !== "" && 
 | 
			
		||||
                              tool.projectUrl.trim() !== "";
 | 
			
		||||
 | 
			
		||||
    badgesContainer.innerHTML = '';
 | 
			
		||||
    // Only show CC24-Server and Knowledgebase badges
 | 
			
		||||
    if (!isMethod && hasValidProjectUrl) {
 | 
			
		||||
      badgesContainer.innerHTML += '<span class="badge badge-primary">CC24-Server</span>';
 | 
			
		||||
    }
 | 
			
		||||
    if (tool.knowledgebase === true) {
 | 
			
		||||
      badgesContainer.innerHTML += '<span class="badge badge-error">📖</span>';
 | 
			
		||||
    elements.badges.innerHTML = '';
 | 
			
		||||
    if (isConcept) {
 | 
			
		||||
      elements.badges.innerHTML += '<span class="badge" style="background-color: var(--color-concept); color: white;">Konzept</span>';
 | 
			
		||||
    } else if (isMethod) {
 | 
			
		||||
      elements.badges.innerHTML += '<span class="badge" style="background-color: var(--color-method); color: white;">Methode</span>';
 | 
			
		||||
    } else if (hasValidProjectUrl) {
 | 
			
		||||
      elements.badges.innerHTML += '<span class="badge badge-primary">CC24-Server</span>';
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Metadata - safe array handling
 | 
			
		||||
    const metadataContainer = document.getElementById('tool-metadata');
 | 
			
		||||
    if (tool.knowledgebase === true) {
 | 
			
		||||
      elements.badges.innerHTML += '<span class="badge badge-error">📖</span>';
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Metadata
 | 
			
		||||
    const domains = tool.domains || [];
 | 
			
		||||
    const phases = tool.phases || [];
 | 
			
		||||
    const domainsText = domains.length > 0 ? domains.join(', ') : 'Domain-agnostic';
 | 
			
		||||
    const phasesText = phases.join(', ');
 | 
			
		||||
    metadataContainer.innerHTML = `
 | 
			
		||||
      <div style="display: grid; gap: 0.5rem;">
 | 
			
		||||
    
 | 
			
		||||
    let metadataHTML = `<div style="display: grid; gap: 0.5rem;">`;
 | 
			
		||||
    
 | 
			
		||||
    if (!isConcept) {
 | 
			
		||||
      metadataHTML += `
 | 
			
		||||
        <div><strong>Betriebssystem:</strong> ${(tool.platforms || []).join(', ')}</div>
 | 
			
		||||
        <div><strong>Skill Level:</strong> ${tool.skillLevel}</div>
 | 
			
		||||
        <div><strong>Lizenzmodell:</strong> ${tool.license}</div>
 | 
			
		||||
        <div><strong>Deployment:</strong> ${tool.accessType}</div>
 | 
			
		||||
        <div><strong>Einsatzgebiete:</strong> ${domainsText}</div>
 | 
			
		||||
        <div><strong>Ermittlungsphasen:</strong> ${phasesText}</div>
 | 
			
		||||
      </div>
 | 
			
		||||
    `;
 | 
			
		||||
      `;
 | 
			
		||||
    } else {
 | 
			
		||||
      metadataHTML += `<div><strong>Skill Level:</strong> ${tool.skillLevel}</div>`;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Tags - safe array handling
 | 
			
		||||
    const tagsContainer = document.getElementById('tool-tags');
 | 
			
		||||
    metadataHTML += `
 | 
			
		||||
      <div><strong>Einsatzgebiete:</strong> ${domainsText}</div>
 | 
			
		||||
      <div><strong>Ermittlungsphasen:</strong> ${phasesText}</div>
 | 
			
		||||
    </div>`;
 | 
			
		||||
    
 | 
			
		||||
    elements.metadata.innerHTML = metadataHTML;
 | 
			
		||||
    
 | 
			
		||||
    // Tags and Related Concepts
 | 
			
		||||
    const tags = tool.tags || [];
 | 
			
		||||
    tagsContainer.innerHTML = `
 | 
			
		||||
    let tagsHTML = `
 | 
			
		||||
      <div style="display: flex; flex-wrap: wrap; gap: 0.25rem;">
 | 
			
		||||
        ${tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
 | 
			
		||||
      </div>
 | 
			
		||||
    `;
 | 
			
		||||
    
 | 
			
		||||
    // Links
 | 
			
		||||
    const linksContainer = document.getElementById('tool-links');
 | 
			
		||||
    // Related Concepts section - only show in primary modal to avoid infinite loops
 | 
			
		||||
    const relatedConcepts = tool.related_concepts || [];
 | 
			
		||||
    if (relatedConcepts.length > 0 && modalType === 'primary') {
 | 
			
		||||
      const conceptLinks = relatedConcepts.map(conceptName => {
 | 
			
		||||
        const concept = toolsData.find(t => t.name === conceptName && t.type === 'concept');
 | 
			
		||||
        if (concept) {
 | 
			
		||||
          return `<button class="tag" style="cursor: pointer; background-color: var(--color-concept-bg); border: 1px solid var(--color-concept); color: var(--color-concept); transition: var(--transition-fast); margin: 0.125rem;" 
 | 
			
		||||
                    onclick="event.stopPropagation(); window.showToolDetails('${conceptName}', 'secondary')" 
 | 
			
		||||
                    onmouseover="this.style.backgroundColor='var(--color-concept)'; this.style.color='white';"
 | 
			
		||||
                    onmouseout="this.style.backgroundColor='var(--color-concept-bg)'; this.style.color='var(--color-concept)';">
 | 
			
		||||
                    ${conceptName}
 | 
			
		||||
                  </button>`;
 | 
			
		||||
        }
 | 
			
		||||
        return `<span class="tag" style="background-color: var(--color-bg-tertiary); color: var(--color-text-secondary); margin: 0.125rem;">${conceptName}</span>`;
 | 
			
		||||
      }).join('');
 | 
			
		||||
 | 
			
		||||
      tagsHTML += `
 | 
			
		||||
        <div style="margin-top: 1rem;">
 | 
			
		||||
          <strong style="display: block; margin-bottom: 0.5rem; color: var(--color-text);">Verwandte Konzepte:</strong>
 | 
			
		||||
          <div style="display: flex; flex-wrap: wrap; gap: 0.25rem;">
 | 
			
		||||
            ${conceptLinks}
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      `;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    elements.tags.innerHTML = tagsHTML;
 | 
			
		||||
    
 | 
			
		||||
    // Links
 | 
			
		||||
    let linksHTML = '';
 | 
			
		||||
 | 
			
		||||
    if (isMethod) {
 | 
			
		||||
      // For methods, show link to the method description/documentation
 | 
			
		||||
    if (isConcept) {
 | 
			
		||||
      linksHTML += `
 | 
			
		||||
        <a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%; background-color: var(--color-concept); border-color: var(--color-concept);">
 | 
			
		||||
          Mehr erfahren
 | 
			
		||||
        </a>
 | 
			
		||||
      `;
 | 
			
		||||
    } else if (isMethod) {
 | 
			
		||||
      linksHTML += `
 | 
			
		||||
        <a href="${tool.projectUrl || tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%; background-color: var(--color-method); border-color: var(--color-method);">
 | 
			
		||||
          Zur Methode
 | 
			
		||||
@ -315,7 +403,7 @@ domains.forEach((domain: any) => {
 | 
			
		||||
      linksHTML += `
 | 
			
		||||
        <div style="display: flex; gap: 0.5rem;">
 | 
			
		||||
          <a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary" style="flex: 1;">
 | 
			
		||||
            Software-Homepage
 | 
			
		||||
            Homepage
 | 
			
		||||
          </a>
 | 
			
		||||
          <a href="${tool.projectUrl}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="flex: 1;">
 | 
			
		||||
            Zugreifen
 | 
			
		||||
@ -346,19 +434,60 @@ domains.forEach((domain: any) => {
 | 
			
		||||
      `;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    linksContainer.innerHTML = linksHTML;
 | 
			
		||||
    elements.links.innerHTML = linksHTML;
 | 
			
		||||
    
 | 
			
		||||
    // Show modal
 | 
			
		||||
    document.getElementById('modal-overlay').classList.add('active');
 | 
			
		||||
    document.getElementById('tool-details').classList.add('active');
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  window.hideToolDetails = function() {
 | 
			
		||||
    document.getElementById('modal-overlay').classList.remove('active');
 | 
			
		||||
    document.getElementById('tool-details').classList.remove('active');
 | 
			
		||||
    // Show modals and update layout
 | 
			
		||||
    const overlay = document.getElementById('modal-overlay');
 | 
			
		||||
    const primaryModal = document.getElementById('tool-details-primary');
 | 
			
		||||
    const secondaryModal = document.getElementById('tool-details-secondary');
 | 
			
		||||
    
 | 
			
		||||
    if (overlay) overlay.classList.add('active');
 | 
			
		||||
    if (modalType === 'primary' && primaryModal) primaryModal.classList.add('active');
 | 
			
		||||
    if (modalType === 'secondary' && secondaryModal) secondaryModal.classList.add('active');
 | 
			
		||||
    
 | 
			
		||||
    // Check if both modals are now active
 | 
			
		||||
    const primaryActive = primaryModal && primaryModal.classList.contains('active');
 | 
			
		||||
    const secondaryActive = secondaryModal && secondaryModal.classList.contains('active');
 | 
			
		||||
    
 | 
			
		||||
    if (primaryActive && secondaryActive) {
 | 
			
		||||
      document.body.classList.add('modals-side-by-side');
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Listen for view changes to trigger highlighting
 | 
			
		||||
  window.hideToolDetails = function(modalType = 'both') {
 | 
			
		||||
    const overlay = document.getElementById('modal-overlay');
 | 
			
		||||
    const primaryModal = document.getElementById('tool-details-primary');
 | 
			
		||||
    const secondaryModal = document.getElementById('tool-details-secondary');
 | 
			
		||||
    
 | 
			
		||||
    if (modalType === 'both' || modalType === 'all') {
 | 
			
		||||
      if (primaryModal) primaryModal.classList.remove('active');
 | 
			
		||||
      if (secondaryModal) secondaryModal.classList.remove('active');
 | 
			
		||||
      if (overlay) overlay.classList.remove('active');
 | 
			
		||||
      document.body.classList.remove('modals-side-by-side');
 | 
			
		||||
    } else if (modalType === 'primary' && primaryModal) {
 | 
			
		||||
      primaryModal.classList.remove('active');
 | 
			
		||||
    } else if (modalType === 'secondary' && secondaryModal) {
 | 
			
		||||
      secondaryModal.classList.remove('active');
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Check if any modal is still active
 | 
			
		||||
    const primaryActive = primaryModal && primaryModal.classList.contains('active');
 | 
			
		||||
    const secondaryActive = secondaryModal && secondaryModal.classList.contains('active');
 | 
			
		||||
    
 | 
			
		||||
    if (!primaryActive && !secondaryActive) {
 | 
			
		||||
      if (overlay) overlay.classList.remove('active');
 | 
			
		||||
      document.body.classList.remove('modals-side-by-side');
 | 
			
		||||
    } else if (primaryActive !== secondaryActive) {
 | 
			
		||||
      // Only one modal left - remove side-by-side layout
 | 
			
		||||
      document.body.classList.remove('modals-side-by-side');
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  window.hideAllToolDetails = function() {
 | 
			
		||||
    window.hideToolDetails('both');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Keep existing event listeners
 | 
			
		||||
  window.addEventListener('viewChanged', (event) => {
 | 
			
		||||
    const view = event.detail;
 | 
			
		||||
    if (view === 'matrix') {
 | 
			
		||||
@ -366,7 +495,6 @@ domains.forEach((domain: any) => {
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Listen for filter changes to update highlighting
 | 
			
		||||
  window.addEventListener('toolsFiltered', (event) => {
 | 
			
		||||
    const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
 | 
			
		||||
    if (currentView === 'matrix') {
 | 
			
		||||
@ -374,7 +502,6 @@ domains.forEach((domain: any) => {
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Update matrix on filter change
 | 
			
		||||
  window.addEventListener('toolsFiltered', (event) => {
 | 
			
		||||
    const filtered = event.detail;
 | 
			
		||||
    const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
 | 
			
		||||
@ -382,33 +509,24 @@ domains.forEach((domain: any) => {
 | 
			
		||||
    if (currentView === 'matrix') {
 | 
			
		||||
      const selectedPhase = getSelectedPhase();
 | 
			
		||||
      
 | 
			
		||||
      // Get all domain-agnostic phase IDs
 | 
			
		||||
      const domainAgnosticPhaseIds = domainAgnosticSoftware.map(section => section.id);
 | 
			
		||||
      
 | 
			
		||||
      // Check if selected phase is a domain-agnostic phase
 | 
			
		||||
      const isDomainAgnosticPhase = domainAgnosticPhaseIds.includes(selectedPhase);
 | 
			
		||||
      
 | 
			
		||||
      // Handle domain-agnostic sections
 | 
			
		||||
      domainAgnosticSoftware.forEach(sectionData => {
 | 
			
		||||
        const section = document.getElementById(`domain-agnostic-section-${sectionData.id}`);
 | 
			
		||||
        const container = document.getElementById(`domain-agnostic-tools-${sectionData.id}`);
 | 
			
		||||
        
 | 
			
		||||
        if (!section || !container) return;
 | 
			
		||||
        
 | 
			
		||||
      });
 | 
			
		||||
      
 | 
			
		||||
      if (!isDomainAgnosticPhase) {
 | 
			
		||||
        // Show matrix for regular phases
 | 
			
		||||
        document.getElementById('dfir-matrix-section').style.display = 'block';
 | 
			
		||||
        
 | 
			
		||||
        // Clear and update matrix cells with ALL tools (based on domains × phases)
 | 
			
		||||
        document.querySelectorAll('.matrix-cell').forEach(cell => {
 | 
			
		||||
          cell.innerHTML = '';
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        // Re-populate with filtered tools based on domains × phases
 | 
			
		||||
        filtered.forEach(tool => {
 | 
			
		||||
          // Skip concepts - they don't belong in matrix
 | 
			
		||||
          if (tool.type === 'concept') {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
@ -428,8 +546,8 @@ domains.forEach((domain: any) => {
 | 
			
		||||
              if (cell) {
 | 
			
		||||
                const chip = document.createElement('span');
 | 
			
		||||
                const chipClass = isMethod ? 'tool-chip-method' : 
 | 
			
		||||
                                 hasValidProjectUrl ? 'tool-chip-hosted' : 
 | 
			
		||||
                                 tool.license !== 'Proprietary' ? 'tool-chip-oss' : '';
 | 
			
		||||
                                hasValidProjectUrl ? 'tool-chip-hosted' : 
 | 
			
		||||
                                tool.license !== 'Proprietary' ? 'tool-chip-oss' : '';
 | 
			
		||||
                chip.className = `tool-chip ${chipClass}`;
 | 
			
		||||
                chip.setAttribute('title', `${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`);
 | 
			
		||||
                chip.innerHTML = `${tool.name}${tool.knowledgebase === true ? '<span style="margin-left: 0.25rem; font-size: 0.6875rem;">📖</span>' : ''}`;
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,9 @@ tools:
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "SQL Query Fundamentals"
 | 
			
		||||
      - "Hash Functions & Digital Signatures"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -58,6 +61,9 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "Hash Functions & Digital Signatures"
 | 
			
		||||
      - "Regular Expressions (Regex)"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -92,6 +98,7 @@ tools:
 | 
			
		||||
      - reporting
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - collaboration-general
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
@ -162,6 +169,9 @@ tools:
 | 
			
		||||
      - reporting
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "Regular Expressions (Regex)"
 | 
			
		||||
      - "SQL Query Fundamentals"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: server-based
 | 
			
		||||
@ -200,6 +210,7 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -236,6 +247,7 @@ tools:
 | 
			
		||||
      - reporting
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
    accessType: commercial
 | 
			
		||||
@ -269,6 +281,7 @@ tools:
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
    accessType: commercial
 | 
			
		||||
@ -302,6 +315,7 @@ tools:
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Linux
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: server-based
 | 
			
		||||
@ -335,6 +349,7 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: expert
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -371,6 +386,7 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -404,6 +420,7 @@ tools:
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
    accessType: server-based
 | 
			
		||||
@ -444,6 +461,7 @@ tools:
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: server-based
 | 
			
		||||
@ -482,6 +500,7 @@ tools:
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: server-based
 | 
			
		||||
@ -517,6 +536,7 @@ tools:
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Linux
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: expert
 | 
			
		||||
    accessType: server-based
 | 
			
		||||
@ -551,6 +571,7 @@ tools:
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -587,6 +608,8 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: 
 | 
			
		||||
      - "Regular Expressions (Regex)"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: novice
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -619,6 +642,7 @@ tools:
 | 
			
		||||
      - reporting
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: commercial
 | 
			
		||||
@ -657,6 +681,8 @@ tools:
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "SQL Query Fundamentals"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: server-based
 | 
			
		||||
@ -692,6 +718,7 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -728,6 +755,7 @@ tools:
 | 
			
		||||
      - reporting
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - collaboration-general
 | 
			
		||||
    skillLevel: novice
 | 
			
		||||
@ -760,6 +788,7 @@ tools:
 | 
			
		||||
      - reporting
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - collaboration-general
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
@ -794,6 +823,7 @@ tools:
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -834,6 +864,7 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - collaboration-general
 | 
			
		||||
    skillLevel: novice
 | 
			
		||||
@ -888,6 +919,7 @@ tools:
 | 
			
		||||
    accessType: commercial
 | 
			
		||||
    license: Proprietary
 | 
			
		||||
    knowledgebase: false
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - collaboration-general
 | 
			
		||||
  - name: GraphSense
 | 
			
		||||
@ -908,6 +940,7 @@ tools:
 | 
			
		||||
      - reporting
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: server-based
 | 
			
		||||
@ -939,6 +972,8 @@ tools:
 | 
			
		||||
      - data-collection
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "Hash Functions & Digital Signatures"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -969,6 +1004,8 @@ tools:
 | 
			
		||||
      - data-collection
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Linux
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "Hash Functions & Digital Signatures"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: novice
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -999,6 +1036,7 @@ tools:
 | 
			
		||||
      - data-collection
 | 
			
		||||
    platforms:
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1033,6 +1071,8 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "SQL Query Fundamentals"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1067,6 +1107,7 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1100,6 +1141,7 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1146,6 +1188,7 @@ tools:
 | 
			
		||||
    accessType: download
 | 
			
		||||
    license: GPL-3.0
 | 
			
		||||
    knowledgebase: true
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - specific-os
 | 
			
		||||
  - name: dd
 | 
			
		||||
@ -1165,6 +1208,7 @@ tools:
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: built-in
 | 
			
		||||
@ -1195,6 +1239,8 @@ tools:
 | 
			
		||||
      - data-collection
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Linux
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "Hash Functions & Digital Signatures"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1226,6 +1272,7 @@ tools:
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1259,6 +1306,7 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1290,6 +1338,7 @@ tools:
 | 
			
		||||
      - examination
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Linux
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1320,6 +1369,7 @@ tools:
 | 
			
		||||
      - examination
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1352,6 +1402,7 @@ tools:
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: beginner
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1385,6 +1436,7 @@ tools:
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1427,6 +1479,9 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "Regular Expressions (Regex)"
 | 
			
		||||
      - "Hash Functions & Digital Signatures" 
 | 
			
		||||
    accessType: download
 | 
			
		||||
    license: BSD-3-Clause
 | 
			
		||||
    knowledgebase: false
 | 
			
		||||
@ -1448,6 +1503,8 @@ tools:
 | 
			
		||||
      - Windows
 | 
			
		||||
      - Linux
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts:
 | 
			
		||||
      - "Regular Expressions (Regex)"
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: novice
 | 
			
		||||
    accessType: built-in
 | 
			
		||||
@ -1522,6 +1579,7 @@ tools:
 | 
			
		||||
    accessType: download
 | 
			
		||||
    license: Free / Mixed
 | 
			
		||||
    knowledgebase: false
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - specific-os
 | 
			
		||||
  - name: Tsurugi Linux
 | 
			
		||||
@ -1553,6 +1611,7 @@ tools:
 | 
			
		||||
    accessType: download
 | 
			
		||||
    license: GPL / Mixed
 | 
			
		||||
    knowledgebase: false
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - specific-os
 | 
			
		||||
  - name: Parrot Security OS
 | 
			
		||||
@ -1583,6 +1642,7 @@ tools:
 | 
			
		||||
    accessType: download
 | 
			
		||||
    license: GPL-3.0
 | 
			
		||||
    knowledgebase: false
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software:
 | 
			
		||||
      - specific-os
 | 
			
		||||
  - name: Eric Zimmerman Tools
 | 
			
		||||
@ -1601,6 +1661,7 @@ tools:
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1635,6 +1696,7 @@ tools:
 | 
			
		||||
      - Linux
 | 
			
		||||
      - Windows
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1668,6 +1730,7 @@ tools:
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Web
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: expert
 | 
			
		||||
    accessType: commercial
 | 
			
		||||
@ -1699,6 +1762,7 @@ tools:
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: expert
 | 
			
		||||
    accessType: commercial
 | 
			
		||||
@ -1731,6 +1795,7 @@ tools:
 | 
			
		||||
      - reporting
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Windows
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: commercial
 | 
			
		||||
@ -1761,6 +1826,7 @@ tools:
 | 
			
		||||
      - data-collection
 | 
			
		||||
    platforms:
 | 
			
		||||
      - Hardware
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: commercial
 | 
			
		||||
@ -1818,6 +1884,7 @@ tools:
 | 
			
		||||
    phases:
 | 
			
		||||
      - data-collection
 | 
			
		||||
    platforms: []
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: null
 | 
			
		||||
@ -1852,6 +1919,7 @@ tools:
 | 
			
		||||
      - data-collection
 | 
			
		||||
      - examination
 | 
			
		||||
    platforms: []
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: null
 | 
			
		||||
@ -1888,6 +1956,7 @@ tools:
 | 
			
		||||
      - examination
 | 
			
		||||
    platforms:
 | 
			
		||||
      - macOS
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: download
 | 
			
		||||
@ -1920,6 +1989,7 @@ tools:
 | 
			
		||||
      - examination
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms: []
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: null
 | 
			
		||||
@ -1950,6 +2020,7 @@ tools:
 | 
			
		||||
      - examination
 | 
			
		||||
      - analysis
 | 
			
		||||
    platforms: []
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: intermediate
 | 
			
		||||
    accessType: null
 | 
			
		||||
@ -1980,6 +2051,7 @@ tools:
 | 
			
		||||
      - data-collection
 | 
			
		||||
      - examination
 | 
			
		||||
    platforms: []
 | 
			
		||||
    related_concepts: null
 | 
			
		||||
    domain-agnostic-software: null
 | 
			
		||||
    skillLevel: advanced
 | 
			
		||||
    accessType: null
 | 
			
		||||
 | 
			
		||||
@ -627,7 +627,7 @@ input[type="checkbox"] {
 | 
			
		||||
  margin: 0.125rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Tool Details Modal */
 | 
			
		||||
/* Tool Details Modal - Enhanced for dual modals */
 | 
			
		||||
.tool-details {
 | 
			
		||||
  display: none;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
@ -640,10 +640,11 @@ input[type="checkbox"] {
 | 
			
		||||
  padding: 2rem;
 | 
			
		||||
  max-width: 600px;
 | 
			
		||||
  width: 90%;
 | 
			
		||||
  max-height: 80vh;
 | 
			
		||||
  max-height: 100vh;
 | 
			
		||||
  overflow-y: auto;
 | 
			
		||||
  z-index: 1000;
 | 
			
		||||
  box-shadow: var(--shadow-lg);
 | 
			
		||||
  transition: var(--transition-medium);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tool-details.active { display: block; }
 | 
			
		||||
@ -661,6 +662,21 @@ input[type="checkbox"] {
 | 
			
		||||
 | 
			
		||||
.modal-overlay.active { display: block; }
 | 
			
		||||
 | 
			
		||||
/* Side-by-side modal positioning */
 | 
			
		||||
.modals-side-by-side #tool-details-primary.active {
 | 
			
		||||
  left: 25%;
 | 
			
		||||
  transform: translate(-50%, -50%);
 | 
			
		||||
  max-width: 45vw;
 | 
			
		||||
  width: 45vw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.modals-side-by-side #tool-details-secondary.active {
 | 
			
		||||
  left: 75%;
 | 
			
		||||
  transform: translate(-50%, -50%);
 | 
			
		||||
  max-width: 45vw;
 | 
			
		||||
  width: 45vw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Phase Controls */
 | 
			
		||||
.domain-phase-container {
 | 
			
		||||
  display: grid;
 | 
			
		||||
@ -1320,6 +1336,15 @@ footer {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Consolidated Responsive Design */
 | 
			
		||||
@media (width <= 1200px) {
 | 
			
		||||
  .modals-side-by-side #tool-details-primary.active,
 | 
			
		||||
  .modals-side-by-side #tool-details-secondary.active {
 | 
			
		||||
    max-width: 42vw;
 | 
			
		||||
    width: 42vw;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@media (width <= 768px) {
 | 
			
		||||
  .nav-wrapper {
 | 
			
		||||
    padding: 0.75rem;
 | 
			
		||||
@ -1369,6 +1394,21 @@ footer {
 | 
			
		||||
    max-width: 120px;
 | 
			
		||||
    min-height: 50px;
 | 
			
		||||
  }
 | 
			
		||||
  .modals-side-by-side #tool-details-primary.active {
 | 
			
		||||
    top: 25%;
 | 
			
		||||
    left: 50%;
 | 
			
		||||
    max-width: 90vw;
 | 
			
		||||
    width: 90vw;
 | 
			
		||||
    max-height: 35vh;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  .modals-side-by-side #tool-details-secondary.active {
 | 
			
		||||
    top: 75%;
 | 
			
		||||
    left: 50%;
 | 
			
		||||
    max-width: 90vw;
 | 
			
		||||
    width: 90vw;
 | 
			
		||||
    max-height: 35vh;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (width <= 640px) {
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@ const ToolSchema = z.object({
 | 
			
		||||
  statusUrl: z.string().optional().nullable(),
 | 
			
		||||
  accessType: z.string().optional().nullable(),
 | 
			
		||||
  'domain-agnostic-software': z.array(z.string()).optional().nullable(),
 | 
			
		||||
  related_concepts: z.array(z.string()).optional().nullable().default([]),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const ToolsDataSchema = z.object({
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user