Merge branch 'embeddings-1' of https://git.cc24.dev/HSMW_CC24/forensic-pathways into embeddings-1
This commit is contained in:
		
						commit
						d3c4d7ccc4
					
				@ -91,119 +91,137 @@ const sortedTags = Object.entries(tagFrequency)
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <!-- Advanced Filters Section -->
 | 
					  <!-- Advanced Filters Section - COLLAPSIBLE -->
 | 
				
			||||||
  <div class="filter-section">
 | 
					  <div class="filter-section">
 | 
				
			||||||
    <div class="filter-card-compact">
 | 
					    <div class="filter-card-compact">
 | 
				
			||||||
      <div class="filter-header-compact">
 | 
					      <div class="filter-header-compact">
 | 
				
			||||||
        <h3>⚙️ Erweiterte Filter</h3>
 | 
					        <h3>⚙️ Erweiterte Filter</h3>
 | 
				
			||||||
        <button class="filter-reset" id="reset-advanced" title="Erweiterte Filter zurücksetzen">
 | 
					        <div class="filter-header-controls">
 | 
				
			||||||
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
 | 
					          <button class="filter-reset" id="reset-advanced" title="Erweiterte Filter zurücksetzen">
 | 
				
			||||||
            <polyline points="1 4 1 10 7 10"/>
 | 
					            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
 | 
				
			||||||
            <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/>
 | 
					              <polyline points="1 4 1 10 7 10"/>
 | 
				
			||||||
          </svg>
 | 
					              <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/>
 | 
				
			||||||
        </button>
 | 
					            </svg>
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					          <button class="collapse-toggle" id="toggle-advanced" data-collapsed="true" title="Erweiterte Filter ein/ausblenden">
 | 
				
			||||||
 | 
					            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
 | 
				
			||||||
 | 
					              <polyline points="6 9 12 15 18 9"></polyline>
 | 
				
			||||||
 | 
					            </svg>
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      <div class="advanced-filters-compact">
 | 
					      <div class="collapsible-content hidden" id="advanced-filters-content">
 | 
				
			||||||
        <div class="filter-grid-compact">
 | 
					        <div class="advanced-filters-compact">
 | 
				
			||||||
          <div class="filter-group">
 | 
					          <div class="filter-grid-compact">
 | 
				
			||||||
            <label class="filter-label">Tool-Typ</label>
 | 
					            <div class="filter-group">
 | 
				
			||||||
            <select id="type-select" class="filter-select">
 | 
					              <label class="filter-label">Tool-Typ</label>
 | 
				
			||||||
              <option value="">Alle Typen</option>
 | 
					              <select id="type-select" class="filter-select">
 | 
				
			||||||
              {toolTypes.map((type: string) => (
 | 
					                <option value="">Alle Typen</option>
 | 
				
			||||||
                <option value={type}>{type}</option>
 | 
					                {toolTypes.map((type: string) => (
 | 
				
			||||||
              ))}
 | 
					                  <option value={type}>{type}</option>
 | 
				
			||||||
            </select>
 | 
					                ))}
 | 
				
			||||||
 | 
					              </select>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="filter-group">
 | 
				
			||||||
 | 
					              <label class="filter-label">Skill Level</label>
 | 
				
			||||||
 | 
					              <select id="skill-select" class="filter-select">
 | 
				
			||||||
 | 
					                <option value="">Alle Level</option>
 | 
				
			||||||
 | 
					                {skillLevels.map((level: string) => (
 | 
				
			||||||
 | 
					                  <option value={level}>{level}</option>
 | 
				
			||||||
 | 
					                ))}
 | 
				
			||||||
 | 
					              </select>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="filter-group">
 | 
				
			||||||
 | 
					              <label class="filter-label">Plattform</label>
 | 
				
			||||||
 | 
					              <select id="platform-select" class="filter-select">
 | 
				
			||||||
 | 
					                <option value="">Alle Plattformen</option>
 | 
				
			||||||
 | 
					                {platforms.map((platform: string) => (
 | 
				
			||||||
 | 
					                  <option value={platform}>{platform}</option>
 | 
				
			||||||
 | 
					                ))}
 | 
				
			||||||
 | 
					              </select>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="filter-group">
 | 
				
			||||||
 | 
					              <label class="filter-label">Lizenztyp</label>
 | 
				
			||||||
 | 
					              <select id="license-select" class="filter-select">
 | 
				
			||||||
 | 
					                <option value="">Alle Lizenzen</option>
 | 
				
			||||||
 | 
					                {licenses.map((license: string) => (
 | 
				
			||||||
 | 
					                  <option value={license}>{license}</option>
 | 
				
			||||||
 | 
					                ))}
 | 
				
			||||||
 | 
					              </select>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="filter-group">
 | 
				
			||||||
 | 
					              <label class="filter-label">Zugangsart</label>
 | 
				
			||||||
 | 
					              <select id="access-select" class="filter-select">
 | 
				
			||||||
 | 
					                <option value="">Alle Zugangsarten</option>
 | 
				
			||||||
 | 
					                {accessTypes.map((access: string) => (
 | 
				
			||||||
 | 
					                  <option value={access}>{access}</option>
 | 
				
			||||||
 | 
					                ))}
 | 
				
			||||||
 | 
					              </select>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div class="filter-group">
 | 
					          <div class="filter-toggles-compact">
 | 
				
			||||||
            <label class="filter-label">Skill Level</label>
 | 
					            <label class="toggle-wrapper">
 | 
				
			||||||
            <select id="skill-select" class="filter-select">
 | 
					              <input type="checkbox" id="hosted-only" />
 | 
				
			||||||
              <option value="">Alle Level</option>
 | 
					              <span class="toggle-label">🟣 Nur CC24-Server Tools</span>
 | 
				
			||||||
              {skillLevels.map((level: string) => (
 | 
					            </label>
 | 
				
			||||||
                <option value={level}>{level}</option>
 | 
					            
 | 
				
			||||||
              ))}
 | 
					            <label class="toggle-wrapper">
 | 
				
			||||||
            </select>
 | 
					              <input type="checkbox" id="knowledgebase-only" />
 | 
				
			||||||
 | 
					              <span class="toggle-label">📖 Nur Tools mit Knowledgebase</span>
 | 
				
			||||||
 | 
					            </label>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
          <div class="filter-group">
 | 
					 | 
				
			||||||
            <label class="filter-label">Plattform</label>
 | 
					 | 
				
			||||||
            <select id="platform-select" class="filter-select">
 | 
					 | 
				
			||||||
              <option value="">Alle Plattformen</option>
 | 
					 | 
				
			||||||
              {platforms.map((platform: string) => (
 | 
					 | 
				
			||||||
                <option value={platform}>{platform}</option>
 | 
					 | 
				
			||||||
              ))}
 | 
					 | 
				
			||||||
            </select>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          <div class="filter-group">
 | 
					 | 
				
			||||||
            <label class="filter-label">Lizenztyp</label>
 | 
					 | 
				
			||||||
            <select id="license-select" class="filter-select">
 | 
					 | 
				
			||||||
              <option value="">Alle Lizenzen</option>
 | 
					 | 
				
			||||||
              {licenses.map((license: string) => (
 | 
					 | 
				
			||||||
                <option value={license}>{license}</option>
 | 
					 | 
				
			||||||
              ))}
 | 
					 | 
				
			||||||
            </select>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          <div class="filter-group">
 | 
					 | 
				
			||||||
            <label class="filter-label">Zugangsart</label>
 | 
					 | 
				
			||||||
            <select id="access-select" class="filter-select">
 | 
					 | 
				
			||||||
              <option value="">Alle Zugangsarten</option>
 | 
					 | 
				
			||||||
              {accessTypes.map((access: string) => (
 | 
					 | 
				
			||||||
                <option value={access}>{access}</option>
 | 
					 | 
				
			||||||
              ))}
 | 
					 | 
				
			||||||
            </select>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div class="filter-toggles-compact">
 | 
					 | 
				
			||||||
          <label class="toggle-wrapper">
 | 
					 | 
				
			||||||
            <input type="checkbox" id="hosted-only" />
 | 
					 | 
				
			||||||
            <span class="toggle-label">🟣 Nur CC24-Server Tools</span>
 | 
					 | 
				
			||||||
          </label>
 | 
					 | 
				
			||||||
          
 | 
					 | 
				
			||||||
          <label class="toggle-wrapper">
 | 
					 | 
				
			||||||
            <input type="checkbox" id="knowledgebase-only" />
 | 
					 | 
				
			||||||
            <span class="toggle-label">📖 Nur Tools mit Knowledgebase</span>
 | 
					 | 
				
			||||||
          </label>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <!-- Tag Filters Section -->
 | 
					  <!-- Tag Filters Section - COLLAPSIBLE -->
 | 
				
			||||||
  <div class="filter-section">
 | 
					  <div class="filter-section">
 | 
				
			||||||
    <div class="filter-card-compact">
 | 
					    <div class="filter-card-compact">
 | 
				
			||||||
      <div class="filter-header-compact">
 | 
					      <div class="filter-header-compact">
 | 
				
			||||||
        <h3>🏷️ Tag-Filter</h3>
 | 
					        <h3>🏷️ Tag-Filter</h3>
 | 
				
			||||||
        <div class="tag-controls">
 | 
					        <div class="filter-header-controls">
 | 
				
			||||||
          <button class="filter-reset" id="reset-tags" title="Tags zurücksetzen">
 | 
					          <button class="filter-reset" id="reset-tags" title="Tags zurücksetzen">
 | 
				
			||||||
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
 | 
					            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
 | 
				
			||||||
              <polyline points="1 4 1 10 7 10"/>
 | 
					              <polyline points="1 4 1 10 7 10"/>
 | 
				
			||||||
              <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/>
 | 
					              <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/>
 | 
				
			||||||
            </svg>
 | 
					            </svg>
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
          <button id="tag-cloud-toggle" class="tag-toggle" data-expanded="false">
 | 
					          <button class="collapse-toggle" id="toggle-tags" data-collapsed="true" title="Tag-Filter ein/ausblenden">
 | 
				
			||||||
            Mehr zeigen
 | 
					            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
 | 
				
			||||||
 | 
					              <polyline points="6 9 12 15 18 9"></polyline>
 | 
				
			||||||
 | 
					            </svg>
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      <div class="tag-section">
 | 
					      <div class="collapsible-content hidden" id="tag-filters-content">
 | 
				
			||||||
        <div class="selected-tags" id="selected-tags"></div>
 | 
					        <div class="tag-section">
 | 
				
			||||||
        <div class="tag-cloud" id="tag-cloud">
 | 
					          <div class="selected-tags" id="selected-tags"></div>
 | 
				
			||||||
          {sortedTags.map((tag, index) => (
 | 
					          <div class="tag-controls">
 | 
				
			||||||
            <button 
 | 
					            <button id="tag-cloud-toggle" class="tag-toggle" data-expanded="false">
 | 
				
			||||||
              class="tag-cloud-item" 
 | 
					              Mehr zeigen
 | 
				
			||||||
              data-tag={tag}
 | 
					 | 
				
			||||||
              data-frequency={tagFrequency[tag]}
 | 
					 | 
				
			||||||
              data-index={index}
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
              {tag}
 | 
					 | 
				
			||||||
              <span class="tag-frequency">({tagFrequency[tag]})</span>
 | 
					 | 
				
			||||||
            </button>
 | 
					            </button>
 | 
				
			||||||
          ))}
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="tag-cloud" id="tag-cloud">
 | 
				
			||||||
 | 
					            {sortedTags.map((tag, index) => (
 | 
				
			||||||
 | 
					              <button 
 | 
				
			||||||
 | 
					                class="tag-cloud-item" 
 | 
				
			||||||
 | 
					                data-tag={tag}
 | 
				
			||||||
 | 
					                data-frequency={tagFrequency[tag]}
 | 
				
			||||||
 | 
					                data-index={index}
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                {tag}
 | 
				
			||||||
 | 
					                <span class="tag-frequency">({tagFrequency[tag]})</span>
 | 
				
			||||||
 | 
					              </button>
 | 
				
			||||||
 | 
					            ))}
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@ -293,7 +311,12 @@ const sortedTags = Object.entries(tagFrequency)
 | 
				
			|||||||
        advanced: document.getElementById('reset-advanced'),
 | 
					        advanced: document.getElementById('reset-advanced'),
 | 
				
			||||||
        tags: document.getElementById('reset-tags'),
 | 
					        tags: document.getElementById('reset-tags'),
 | 
				
			||||||
        all: document.getElementById('reset-all-filters')
 | 
					        all: document.getElementById('reset-all-filters')
 | 
				
			||||||
      }
 | 
					      },
 | 
				
			||||||
 | 
					      // Collapsible elements
 | 
				
			||||||
 | 
					      toggleAdvanced: document.getElementById('toggle-advanced'),
 | 
				
			||||||
 | 
					      toggleTags: document.getElementById('toggle-tags'),
 | 
				
			||||||
 | 
					      advancedContent: document.getElementById('advanced-filters-content'),
 | 
				
			||||||
 | 
					      tagContent: document.getElementById('tag-filters-content')
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Verify critical elements exist
 | 
					    // Verify critical elements exist
 | 
				
			||||||
@ -307,6 +330,52 @@ const sortedTags = Object.entries(tagFrequency)
 | 
				
			|||||||
    let selectedPhase = '';
 | 
					    let selectedPhase = '';
 | 
				
			||||||
    let isTagCloudExpanded = false;
 | 
					    let isTagCloudExpanded = false;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    // Collapsible functionality
 | 
				
			||||||
 | 
					    function toggleCollapsible(toggleBtn, content, storageKey) {
 | 
				
			||||||
 | 
					      const isCollapsed = toggleBtn.getAttribute('data-collapsed') === 'true';
 | 
				
			||||||
 | 
					      const newState = !isCollapsed;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      toggleBtn.setAttribute('data-collapsed', newState.toString());
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (newState) {
 | 
				
			||||||
 | 
					        // Collapse
 | 
				
			||||||
 | 
					        content.classList.add('hidden');
 | 
				
			||||||
 | 
					        toggleBtn.style.transform = 'rotate(0deg)';
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        // Expand
 | 
				
			||||||
 | 
					        content.classList.remove('hidden');
 | 
				
			||||||
 | 
					        toggleBtn.style.transform = 'rotate(180deg)';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      // Store state in sessionStorage
 | 
				
			||||||
 | 
					      sessionStorage.setItem(storageKey, newState.toString());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Initialize collapsible sections (collapsed by default)
 | 
				
			||||||
 | 
					    function initializeCollapsible() {
 | 
				
			||||||
 | 
					      // Advanced filters
 | 
				
			||||||
 | 
					      const advancedCollapsed = sessionStorage.getItem('advanced-collapsed') !== 'false';
 | 
				
			||||||
 | 
					      elements.toggleAdvanced.setAttribute('data-collapsed', advancedCollapsed.toString());
 | 
				
			||||||
 | 
					      if (advancedCollapsed) {
 | 
				
			||||||
 | 
					        elements.advancedContent.classList.add('hidden');
 | 
				
			||||||
 | 
					        elements.toggleAdvanced.style.transform = 'rotate(0deg)';
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        elements.advancedContent.classList.remove('hidden');
 | 
				
			||||||
 | 
					        elements.toggleAdvanced.style.transform = 'rotate(180deg)';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      // Tag filters
 | 
				
			||||||
 | 
					      const tagsCollapsed = sessionStorage.getItem('tags-collapsed') !== 'false';
 | 
				
			||||||
 | 
					      elements.toggleTags.setAttribute('data-collapsed', tagsCollapsed.toString());
 | 
				
			||||||
 | 
					      if (tagsCollapsed) {
 | 
				
			||||||
 | 
					        elements.tagContent.classList.add('hidden');
 | 
				
			||||||
 | 
					        elements.toggleTags.style.transform = 'rotate(0deg)';
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        elements.tagContent.classList.remove('hidden');
 | 
				
			||||||
 | 
					        elements.toggleTags.style.transform = 'rotate(180deg)';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    // Helper function to check if tool is hosted
 | 
					    // Helper function to check if tool is hosted
 | 
				
			||||||
    function isToolHosted(tool) {
 | 
					    function isToolHosted(tool) {
 | 
				
			||||||
      return tool.projectUrl !== undefined && 
 | 
					      return tool.projectUrl !== undefined && 
 | 
				
			||||||
@ -418,18 +487,23 @@ const sortedTags = Object.entries(tagFrequency)
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Add/remove tags
 | 
					    // Add/remove tags - FIXED: Update ALL matching elements
 | 
				
			||||||
    function addTag(tag) {
 | 
					    function addTag(tag) {
 | 
				
			||||||
      selectedTags.add(tag);
 | 
					      selectedTags.add(tag);
 | 
				
			||||||
      document.querySelector(`[data-tag="${tag}"]`).classList.add('active');
 | 
					      // FIXED: Use querySelectorAll to update ALL matching tag elements
 | 
				
			||||||
 | 
					      document.querySelectorAll(`[data-tag="${tag}"]`).forEach(element => {
 | 
				
			||||||
 | 
					        element.classList.add('active');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
      updateSelectedTags();
 | 
					      updateSelectedTags();
 | 
				
			||||||
      filterTools();
 | 
					      filterTools();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    function removeTag(tag) {
 | 
					    function removeTag(tag) {
 | 
				
			||||||
      selectedTags.delete(tag);
 | 
					      selectedTags.delete(tag);
 | 
				
			||||||
      const tagElement = document.querySelector(`[data-tag="${tag}"]`);
 | 
					      // FIXED: Use querySelectorAll to update ALL matching tag elements
 | 
				
			||||||
      if (tagElement) tagElement.classList.remove('active');
 | 
					      document.querySelectorAll(`[data-tag="${tag}"]`).forEach(element => {
 | 
				
			||||||
 | 
					        element.classList.remove('active');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
      updateSelectedTags();
 | 
					      updateSelectedTags();
 | 
				
			||||||
      filterTools();
 | 
					      filterTools();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -553,7 +627,10 @@ const sortedTags = Object.entries(tagFrequency)
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    function resetTags() {
 | 
					    function resetTags() {
 | 
				
			||||||
      selectedTags.clear();
 | 
					      selectedTags.clear();
 | 
				
			||||||
      elements.tagCloudItems.forEach(item => item.classList.remove('active'));
 | 
					      // FIXED: Update ALL tag elements
 | 
				
			||||||
 | 
					      document.querySelectorAll('.tag-cloud-item').forEach(item => {
 | 
				
			||||||
 | 
					        item.classList.remove('active');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
      updateSelectedTags();
 | 
					      updateSelectedTags();
 | 
				
			||||||
      filterTools();
 | 
					      filterTools();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -630,11 +707,21 @@ const sortedTags = Object.entries(tagFrequency)
 | 
				
			|||||||
    elements.resetButtons.tags.addEventListener('click', resetTags);
 | 
					    elements.resetButtons.tags.addEventListener('click', resetTags);
 | 
				
			||||||
    elements.resetButtons.all.addEventListener('click', resetAllFilters);
 | 
					    elements.resetButtons.all.addEventListener('click', resetAllFilters);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    // Collapsible toggle listeners
 | 
				
			||||||
 | 
					    elements.toggleAdvanced.addEventListener('click', () => {
 | 
				
			||||||
 | 
					      toggleCollapsible(elements.toggleAdvanced, elements.advancedContent, 'advanced-collapsed');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    elements.toggleTags.addEventListener('click', () => {
 | 
				
			||||||
 | 
					      toggleCollapsible(elements.toggleTags, elements.tagContent, 'tags-collapsed');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    // Expose functions globally for backwards compatibility
 | 
					    // Expose functions globally for backwards compatibility
 | 
				
			||||||
    window.clearTagFilters = resetTags;
 | 
					    window.clearTagFilters = resetTags;
 | 
				
			||||||
    window.clearAllFilters = resetAllFilters;
 | 
					    window.clearAllFilters = resetAllFilters;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Initialize
 | 
					    // Initialize
 | 
				
			||||||
 | 
					    initializeCollapsible();
 | 
				
			||||||
    initTagCloud();
 | 
					    initTagCloud();
 | 
				
			||||||
    filterTagCloud();
 | 
					    filterTagCloud();
 | 
				
			||||||
    updateSelectedTags();
 | 
					    updateSelectedTags();
 | 
				
			||||||
 | 
				
			|||||||
@ -1263,6 +1263,12 @@ input[type="checkbox"] {
 | 
				
			|||||||
  gap: 0.5rem; 
 | 
					  gap: 0.5rem; 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.filter-header-controls {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  gap: 0.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Search Components */
 | 
					/* Search Components */
 | 
				
			||||||
.search-wrapper { 
 | 
					.search-wrapper { 
 | 
				
			||||||
  position: relative; 
 | 
					  position: relative; 
 | 
				
			||||||
@ -1315,6 +1321,64 @@ input[type="checkbox"] {
 | 
				
			|||||||
  color: var(--color-text);
 | 
					  color: var(--color-text);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.collapse-toggle {
 | 
				
			||||||
 | 
					  background: none;
 | 
				
			||||||
 | 
					  border: 1px solid var(--color-border);
 | 
				
			||||||
 | 
					  border-radius: 0.375rem;
 | 
				
			||||||
 | 
					  color: var(--color-text-secondary);
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  padding: 0.375rem;
 | 
				
			||||||
 | 
					  transition: var(--transition-fast);
 | 
				
			||||||
 | 
					  display: inline-flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  width: 32px;
 | 
				
			||||||
 | 
					  height: 32px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.collapse-toggle:hover {
 | 
				
			||||||
 | 
					  background-color: var(--color-bg-secondary);
 | 
				
			||||||
 | 
					  border-color: var(--color-primary);
 | 
				
			||||||
 | 
					  color: var(--color-text);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.collapse-toggle svg {
 | 
				
			||||||
 | 
					  transition: transform var(--transition-medium);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* When expanded, rotate the chevron */
 | 
				
			||||||
 | 
					.collapse-toggle[data-collapsed="false"] svg {
 | 
				
			||||||
 | 
					  transform: rotate(180deg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Collapsible Content */
 | 
				
			||||||
 | 
					.collapsible-content {
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  transition: all var(--transition-medium);
 | 
				
			||||||
 | 
					  opacity: 1;
 | 
				
			||||||
 | 
					  max-height: 1000px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.collapsible-content.hidden {
 | 
				
			||||||
 | 
					  opacity: 0;
 | 
				
			||||||
 | 
					  max-height: 0;
 | 
				
			||||||
 | 
					  padding-top: 0;
 | 
				
			||||||
 | 
					  padding-bottom: 0;
 | 
				
			||||||
 | 
					  margin-top: 0;
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Smooth animation for expanding content */
 | 
				
			||||||
 | 
					.collapsible-content:not(.hidden) {
 | 
				
			||||||
 | 
					  animation: expandContent 0.3s ease-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Content spacing when expanded */
 | 
				
			||||||
 | 
					.collapsible-content:not(.hidden) .advanced-filters-compact,
 | 
				
			||||||
 | 
					.collapsible-content:not(.hidden) .tag-section {
 | 
				
			||||||
 | 
					  padding-top: 0.75rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Filter Grids & Groups */
 | 
					/* Filter Grids & Groups */
 | 
				
			||||||
.filter-grid-compact { 
 | 
					.filter-grid-compact { 
 | 
				
			||||||
  display: grid; 
 | 
					  display: grid; 
 | 
				
			||||||
@ -1429,11 +1493,9 @@ input[type="checkbox"] {
 | 
				
			|||||||
  user-select: none;
 | 
					  user-select: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Tag System */
 | 
					.tag-section .tag-controls {
 | 
				
			||||||
.tag-section {
 | 
					  order: -1; 
 | 
				
			||||||
  display: flex;
 | 
					  margin-bottom: 0.75rem;
 | 
				
			||||||
  flex-direction: column;
 | 
					 | 
				
			||||||
  gap: 1rem;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.selected-tags { 
 | 
					.selected-tags { 
 | 
				
			||||||
@ -1574,6 +1636,14 @@ input[type="checkbox"] {
 | 
				
			|||||||
  transition: var(--transition-fast); 
 | 
					  transition: var(--transition-fast); 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.filter-reset {
 | 
				
			||||||
 | 
					  width: 32px;
 | 
				
			||||||
 | 
					  height: 32px;
 | 
				
			||||||
 | 
					  display: inline-flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.filter-reset:hover { 
 | 
					.filter-reset:hover { 
 | 
				
			||||||
  background-color: var(--color-bg-secondary); 
 | 
					  background-color: var(--color-bg-secondary); 
 | 
				
			||||||
  border-color: var(--color-warning); 
 | 
					  border-color: var(--color-warning); 
 | 
				
			||||||
@ -1591,13 +1661,6 @@ input[type="checkbox"] {
 | 
				
			|||||||
  opacity: 0.9;
 | 
					  opacity: 0.9;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Tag Controls */
 | 
					 | 
				
			||||||
.tag-controls { 
 | 
					 | 
				
			||||||
  display: flex; 
 | 
					 | 
				
			||||||
  align-items: center; 
 | 
					 | 
				
			||||||
  gap: 0.75rem; 
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.tag-toggle { 
 | 
					.tag-toggle { 
 | 
				
			||||||
  padding: 0.375rem 0.75rem; 
 | 
					  padding: 0.375rem 0.75rem; 
 | 
				
			||||||
  border: 1px solid var(--color-border); 
 | 
					  border: 1px solid var(--color-border); 
 | 
				
			||||||
@ -2391,6 +2454,17 @@ footer {
 | 
				
			|||||||
  to { opacity: 1; }
 | 
					  to { opacity: 1; }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@keyframes expandContent {
 | 
				
			||||||
 | 
					  from {
 | 
				
			||||||
 | 
					    opacity: 0;
 | 
				
			||||||
 | 
					    transform: translateY(-10px);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  to {
 | 
				
			||||||
 | 
					    opacity: 1;
 | 
				
			||||||
 | 
					    transform: translateY(0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@keyframes fadeInUp {
 | 
					@keyframes fadeInUp {
 | 
				
			||||||
  from {
 | 
					  from {
 | 
				
			||||||
    opacity: 0;
 | 
					    opacity: 0;
 | 
				
			||||||
@ -3385,6 +3459,23 @@ footer {
 | 
				
			|||||||
  .view-toggle {
 | 
					  .view-toggle {
 | 
				
			||||||
    justify-content: center;
 | 
					    justify-content: center;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .filter-header-controls {
 | 
				
			||||||
 | 
					    gap: 0.375rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .collapse-toggle,
 | 
				
			||||||
 | 
					  .filter-reset {
 | 
				
			||||||
 | 
					    width: 28px;
 | 
				
			||||||
 | 
					    height: 28px;
 | 
				
			||||||
 | 
					    padding: 0.25rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .collapse-toggle svg,
 | 
				
			||||||
 | 
					  .filter-reset svg {
 | 
				
			||||||
 | 
					    width: 14px;
 | 
				
			||||||
 | 
					    height: 14px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media (width <= 640px) {
 | 
					@media (width <= 640px) {
 | 
				
			||||||
@ -3519,6 +3610,21 @@ footer {
 | 
				
			|||||||
  .filter-card-compact {
 | 
					  .filter-card-compact {
 | 
				
			||||||
    padding: 0.5rem;
 | 
					    padding: 0.5rem;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .filter-header-compact {
 | 
				
			||||||
 | 
					    flex-wrap: wrap;
 | 
				
			||||||
 | 
					    gap: 0.5rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .filter-header-compact h3 {
 | 
				
			||||||
 | 
					    flex: 1 1 100%;
 | 
				
			||||||
 | 
					    margin-bottom: 0.25rem;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .filter-header-controls {
 | 
				
			||||||
 | 
					    flex: 1 1 100%;
 | 
				
			||||||
 | 
					    justify-content: flex-end;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user