@@ -266,6 +278,201 @@ domains.forEach((domain: any) => {
}
}
+ // ===== SHARING FUNCTIONALITY =====
+
+ // Create tool slug from name (same logic as ShareButton.astro)
+ function createToolSlug(toolName) {
+ return toolName.toLowerCase()
+ .replace(/[^a-z0-9\s-]/g, '') // Remove special characters
+ .replace(/\s+/g, '-') // Replace spaces with hyphens
+ .replace(/-+/g, '-') // Remove duplicate hyphens
+ .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
+ }
+
+ // Find tool by name or slug
+ function findTool(identifier) {
+ return toolsData.find(tool =>
+ tool.name === identifier ||
+ createToolSlug(tool.name) === identifier.toLowerCase()
+ );
+ }
+
+ // Generate share URLs
+ function generateShareURL(toolName, view, modal = null) {
+ const toolSlug = createToolSlug(toolName);
+ const baseUrl = window.location.origin + window.location.pathname;
+ const params = new URLSearchParams();
+ params.set('tool', toolSlug);
+ params.set('view', view);
+ if (modal) {
+ params.set('modal', modal);
+ }
+ return `${baseUrl}?${params.toString()}`;
+ }
+
+ // Copy to clipboard with feedback
+ async function copyToClipboard(text, button) {
+ try {
+ await navigator.clipboard.writeText(text);
+
+ // Show feedback
+ const originalHTML = button.innerHTML;
+ button.innerHTML = '
Kopiert!';
+ button.style.color = 'var(--color-accent)';
+
+ setTimeout(() => {
+ button.innerHTML = originalHTML;
+ button.style.color = '';
+ }, 2000);
+ } catch (err) {
+ // Fallback for older browsers
+ const textArea = document.createElement('textarea');
+ textArea.value = text;
+ document.body.appendChild(textArea);
+ textArea.select();
+ document.execCommand('copy');
+ document.body.removeChild(textArea);
+
+ // Show feedback
+ const originalHTML = button.innerHTML;
+ button.innerHTML = 'Kopiert!';
+ setTimeout(() => {
+ button.innerHTML = originalHTML;
+ }, 2000);
+ }
+ }
+
+ // Show share dialog
+ window.showShareDialog = function(shareButton) {
+ const toolName = shareButton.getAttribute('data-tool-name');
+ const context = shareButton.getAttribute('data-context');
+
+ // Create modal backdrop
+ let backdrop = document.getElementById('share-modal-backdrop');
+ if (!backdrop) {
+ backdrop = document.createElement('div');
+ backdrop.id = 'share-modal-backdrop';
+ backdrop.style.cssText = `
+ position: fixed; top: 0; left: 0; right: 0; bottom: 0;
+ background: rgba(0, 0, 0, 0.5); z-index: 9999;
+ display: flex; align-items: center; justify-content: center;
+ opacity: 0; transition: opacity 0.2s ease;
+ `;
+ document.body.appendChild(backdrop);
+ }
+
+ // Create share dialog
+ const dialog = document.createElement('div');
+ dialog.style.cssText = `
+ background: var(--color-bg); border: 1px solid var(--color-border);
+ border-radius: 0.75rem; padding: 1.5rem; max-width: 400px; width: 90%;
+ box-shadow: var(--shadow-lg); transform: scale(0.9); transition: transform 0.2s ease;
+ `;
+
+ dialog.innerHTML = `
+
+ `;
+
+ backdrop.appendChild(dialog);
+
+ // Show with animation
+ requestAnimationFrame(() => {
+ backdrop.style.opacity = '1';
+ dialog.style.transform = 'scale(1)';
+ });
+
+ // Event handlers
+ const closeDialog = () => {
+ backdrop.style.opacity = '0';
+ dialog.style.transform = 'scale(0.9)';
+ setTimeout(() => {
+ if (backdrop.parentNode) {
+ document.body.removeChild(backdrop);
+ }
+ }, 200);
+ };
+
+ backdrop.addEventListener('click', (e) => {
+ if (e.target === backdrop) closeDialog();
+ });
+
+ document.getElementById('close-share-dialog').addEventListener('click', closeDialog);
+
+ // Share option handlers
+ dialog.querySelectorAll('.share-option-btn').forEach(btn => {
+ btn.addEventListener('mouseover', () => {
+ btn.style.backgroundColor = 'var(--color-bg-secondary)';
+ btn.style.borderColor = 'var(--color-primary)';
+ });
+
+ btn.addEventListener('mouseout', () => {
+ btn.style.backgroundColor = 'var(--color-bg)';
+ btn.style.borderColor = 'var(--color-border)';
+ });
+
+ btn.addEventListener('click', () => {
+ const url = btn.getAttribute('data-url');
+ copyToClipboard(url, btn);
+ });
+ });
+ };
+
// Make functions globally available
window.toggleDomainAgnosticSection = toggleDomainAgnosticSection;
@@ -372,10 +579,23 @@ domains.forEach((domain: any) => {
return `
`;
}).join('');
+ // Check if mobile device
+ const isMobile = window.innerWidth <= 768;
+ const collapseOnMobile = isMobile && relatedConcepts.length > 2;
+
tagsHTML += `
-
Verwandte Konzepte:
-
+
+ Verwandte Konzepte:
+ ${collapseOnMobile ? `
+
+ ` : ''}
+
+
${conceptLinks}
@@ -436,6 +656,30 @@ domains.forEach((domain: any) => {
elements.links.innerHTML = linksHTML;
+ // ===== POPULATE SHARE BUTTON =====
+ const shareButtonContainer = document.getElementById(`share-button-${modalType}`);
+ if (shareButtonContainer) {
+ const toolSlug = createToolSlug(tool.name);
+ shareButtonContainer.innerHTML = `
+
+ `;
+ shareButtonContainer.style.display = 'block';
+ }
+
// Show modals and update layout
const overlay = document.getElementById('modal-overlay');
const primaryModal = document.getElementById('tool-details-primary');
@@ -460,14 +704,28 @@ domains.forEach((domain: any) => {
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 (primaryModal) {
+ primaryModal.classList.remove('active');
+ // Hide share button
+ const shareButtonPrimary = document.getElementById('share-button-primary');
+ if (shareButtonPrimary) shareButtonPrimary.style.display = 'none';
+ }
+ if (secondaryModal) {
+ secondaryModal.classList.remove('active');
+ // Hide share button
+ const shareButtonSecondary = document.getElementById('share-button-secondary');
+ if (shareButtonSecondary) shareButtonSecondary.style.display = 'none';
+ }
if (overlay) overlay.classList.remove('active');
document.body.classList.remove('modals-side-by-side');
} else if (modalType === 'primary' && primaryModal) {
primaryModal.classList.remove('active');
+ const shareButtonPrimary = document.getElementById('share-button-primary');
+ if (shareButtonPrimary) shareButtonPrimary.style.display = 'none';
} else if (modalType === 'secondary' && secondaryModal) {
secondaryModal.classList.remove('active');
+ const shareButtonSecondary = document.getElementById('share-button-secondary');
+ if (shareButtonSecondary) shareButtonSecondary.style.display = 'none';
}
// Check if any modal is still active
diff --git a/src/data/tools.yaml.example b/src/data/tools.yaml.example
new file mode 100644
index 0000000..b3198e8
--- /dev/null
+++ b/src/data/tools.yaml.example
@@ -0,0 +1,206 @@
+# This is a minimal example file of the real knowledgebase in ./src/data/tools.yaml
+ - name: Rapid Incident Response Triage on macOS
+ icon: 📋
+ type: method
+ description: >-
+ Spezialisierte Methodik für die schnelle Incident Response auf
+ macOS-Systemen mit Fokus auf die Sammlung kritischer forensischer
+ Artefakte in unter einer Stunde. Adressiert die Lücke zwischen
+ Windows-zentrierten IR-Prozessen und macOS-spezifischen
+ Sicherheitsarchitekturen. Nutzt Tools wie Aftermath für effiziente
+ Datensammlung ohne zeitaufwändige Full-Disk-Images. Besonders wertvoll für
+ Unternehmensumgebungen mit gemischten Betriebssystem-Landschaften.
+ domains:
+ - incident-response
+ - law-enforcement
+ - malware-analysis
+ phases:
+ - data-collection
+ - examination
+ platforms: []
+ related_concepts: null
+ domain-agnostic-software: null
+ skillLevel: intermediate
+ accessType: null
+ url: >-
+ https://www.sans.org/white-papers/rapid-incident-response-on-macos-actionable-insights-under-hour/
+ projectUrl: null
+ license: null
+ knowledgebase: null
+ tags:
+ - macos
+ - rapid-response
+ - triage
+ - incident-response
+ - aftermath
+ - enterprise
+ - methodology
+ - apple
+ - name: Aftermath
+ icon: 📦
+ type: software
+ description: >-
+ Jamf's Open-Source-Tool für die schnelle Sammlung forensischer Artefakte
+ auf macOS-Systemen. Sammelt kritische Daten wie Prozessinformationen,
+ Netzwerkverbindungen, Dateisystem-Metadaten und Systemkonfigurationen ohne
+ Full-Disk-Imaging. Speziell entwickelt für die Rapid-Response-Triage in
+ Enterprise-Umgebungen mit macOS-Geräten. Normalisiert Zeitstempel und
+ erstellt durchsuchbare Ausgabeformate für effiziente Analyse.
+ domains:
+ - incident-response
+ - law-enforcement
+ - malware-analysis
+ phases:
+ - data-collection
+ - examination
+ platforms:
+ - macOS
+ related_concepts: null
+ domain-agnostic-software: null
+ skillLevel: intermediate
+ accessType: download
+ url: https://github.com/jamf/aftermath/
+ projectUrl: ''
+ license: Apache 2.0
+ knowledgebase: false
+ tags:
+ - macos
+ - incident-response
+ - triage
+ - artifact-collection
+ - rapid-response
+ - jamf
+ - enterprise
+ - commandline
+ - name: Regular Expressions (Regex)
+ icon: 🔤
+ type: concept
+ description: >-
+ Pattern matching language for searching, extracting, and manipulating
+ text. Essential for log analysis, malware signature creation, and data
+ extraction from unstructured sources. Forms the backbone of many forensic
+ tools and custom scripts.
+ domains:
+ - incident-response
+ - malware-analysis
+ - network-forensics
+ - fraud-investigation
+ phases:
+ - examination
+ - analysis
+ platforms: []
+ related_concepts: null
+ domain-agnostic-software: null
+ skillLevel: intermediate
+ accessType: null
+ url: https://regexr.com/
+ projectUrl: null
+ license: null
+ knowledgebase: true
+ tags:
+ - pattern-matching
+ - text-processing
+ - log-analysis
+ - string-manipulation
+ - search-algorithms
+ - name: SQL Query Fundamentals
+ icon: 🗃️
+ type: concept
+ description: >-
+ Structured Query Language for database interrogation and analysis.
+ Critical for examining application databases, SQLite artifacts from
+ mobile devices, and browser history databases. Enables complex
+ correlation and filtering of large datasets.
+ domains:
+ - incident-response
+ - mobile-forensics
+ - fraud-investigation
+ - cloud-forensics
+ phases:
+ - examination
+ - analysis
+ platforms: []
+ related_concepts: null
+ domain-agnostic-software: null
+ skillLevel: intermediate
+ accessType: null
+ url: https://www.w3schools.com/sql/
+ projectUrl: null
+ license: null
+ knowledgebase: false
+ tags:
+ - database-analysis
+ - query-language
+ - data-correlation
+ - mobile-artifacts
+ - browser-forensics
+ - name: Hash Functions & Digital Signatures
+ icon: 🔐
+ type: concept
+ description: >-
+ Cryptographic principles for data integrity verification and
+ authentication. Fundamental for evidence preservation, malware
+ identification, and establishing chain of custody. Understanding of MD5,
+ SHA, and digital signature validation.
+ domains:
+ - incident-response
+ - law-enforcement
+ - malware-analysis
+ - cloud-forensics
+ phases:
+ - data-collection
+ - examination
+ platforms: []
+ related_concepts: null
+ domain-agnostic-software: null
+ skillLevel: advanced
+ accessType: null
+ url: https://en.wikipedia.org/wiki/Cryptographic_hash_function
+ projectUrl: null
+ license: null
+ knowledgebase: false
+ tags:
+ - cryptography
+ - data-integrity
+ - evidence-preservation
+ - malware-identification
+ - chain-of-custody
+domains:
+ - id: incident-response
+ name: Incident Response & Breach-Untersuchung
+ - id: law-enforcement
+ name: Strafverfolgung & Kriminalermittlung
+ - id: malware-analysis
+ name: Malware-Analyse & Reverse Engineering
+ - id: fraud-investigation
+ name: Betrugs- & Finanzkriminalität
+ - id: network-forensics
+ name: Netzwerk-Forensik & Traffic-Analyse
+ - id: mobile-forensics
+ name: Mobile Geräte & App-Forensik
+ - id: cloud-forensics
+ name: Cloud & Virtuelle Umgebungen
+ - id: ics-forensics
+ name: Industrielle Kontrollsysteme (ICS/SCADA)
+phases:
+ - id: data-collection
+ name: Datensammlung
+ description: Imaging, Acquisition, Remote Collection Tools
+ - id: examination
+ name: Auswertung
+ description: Parsing, Extraction, Initial Analysis Tools
+ - id: analysis
+ name: Analyse
+ description: Deep Analysis, Correlation, Visualization Tools
+ - id: reporting
+ name: Bericht & Präsentation
+ description: >-
+ Documentation, Visualization, Presentation Tools (z.B. QGIS für Geodaten,
+ Timeline-Tools)
+domain-agnostic-software:
+ - id: collaboration-general
+ name: Übergreifend & Kollaboration
+ description: Cross-cutting tools and collaboration platforms
+ - id: specific-os
+ name: Betriebssysteme
+ description: Operating Systems which focus on forensics
diff --git a/src/pages/index.astro b/src/pages/index.astro
index f16970f..d9b0c4f 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -93,15 +93,31 @@ const tools = data.tools;
\ No newline at end of file
diff --git a/src/styles/global.css b/src/styles/global.css
index 560042b..c69d515 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -240,6 +240,25 @@ nav {
background-color: var(--color-bg-tertiary);
}
+/* Icon Button */
+.btn-icon {
+ background: none;
+ border: none;
+ color: var(--color-text-secondary);
+ cursor: pointer;
+ padding: 0.25rem;
+ border-radius: 0.25rem;
+ transition: var(--transition-fast);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.btn-icon:hover {
+ color: var(--color-text);
+ background-color: var(--color-bg-secondary);
+}
+
.btn-accent {
background-color: var(--color-accent);
color: white;
@@ -392,6 +411,8 @@ input[type="checkbox"] {
line-height: 1;
}
+
+
.metadata-item {
display: flex;
align-items: center;
@@ -647,7 +668,7 @@ input[type="checkbox"] {
padding: 2rem;
max-width: 600px;
width: 90%;
- max-height: 100vh;
+ max-height: 85vh;
overflow-y: auto;
z-index: 1000;
box-shadow: var(--shadow-lg);
@@ -1197,6 +1218,13 @@ Collaboration Section Collapse */
margin-bottom: 0.75rem;
}
+/* Enhanced highlight flash for different contexts */
+.tool-card.highlight-flash,
+.tool-chip.highlight-flash,
+.tool-recommendation.highlight-flash {
+ animation: highlight-flash 2s ease-out;
+}
+
.pros-cons-section {
animation: fadeIn 0.4s ease-in;
}
@@ -1309,11 +1337,76 @@ footer {
}
}
-@keyframes highlight-flash {
- 0% { background-color: rgb(37 99 235 / 10%); }
- 100% { background-color: transparent; }
-}
+/*Perfect! Here's the absolutely brutal, eye-melting version:*/
+@keyframes highlight-flash {
+ 0% {
+ background-color: rgb(57 255 20 / 60%);
+ box-shadow: 0 0 0 8px rgb(255 20 147 / 50%), 0 0 20px rgb(57 255 20 / 80%);
+ transform: scale(1.12) rotate(2deg);
+ border: 3px solid rgb(255 255 0);
+ }
+ 12.5% {
+ background-color: rgb(255 20 147 / 70%);
+ box-shadow: 0 0 0 15px rgb(0 191 255 / 60%), 0 0 30px rgb(255 20 147 / 90%);
+ transform: scale(1.18) rotate(-3deg);
+ border: 3px solid rgb(57 255 20);
+ }
+ 25% {
+ background-color: rgb(0 191 255 / 65%);
+ box-shadow: 0 0 0 12px rgb(191 0 255 / 55%), 0 0 25px rgb(0 191 255 / 85%);
+ transform: scale(1.15) rotate(1deg);
+ border: 3px solid rgb(255 20 147);
+ }
+ 37.5% {
+ background-color: rgb(191 0 255 / 75%);
+ box-shadow: 0 0 0 18px rgb(255 255 0 / 65%), 0 0 35px rgb(191 0 255 / 95%);
+ transform: scale(1.20) rotate(-2deg);
+ border: 3px solid rgb(0 191 255);
+ }
+ 50% {
+ background-color: rgb(255 255 0 / 80%);
+ box-shadow: 0 0 0 10px rgb(57 255 20 / 70%), 0 0 40px rgb(255 255 0 / 100%);
+ transform: scale(1.16) rotate(3deg);
+ border: 3px solid rgb(191 0 255);
+ }
+ 62.5% {
+ background-color: rgb(255 69 0 / 70%);
+ box-shadow: 0 0 0 16px rgb(255 20 147 / 60%), 0 0 30px rgb(255 69 0 / 90%);
+ transform: scale(1.22) rotate(-1deg);
+ border: 3px solid rgb(255 255 0);
+ }
+ 75% {
+ background-color: rgb(255 20 147 / 65%);
+ box-shadow: 0 0 0 14px rgb(0 191 255 / 50%), 0 0 45px rgb(255 20 147 / 85%);
+ transform: scale(1.14) rotate(2deg);
+ border: 3px solid rgb(57 255 20);
+ }
+ 87.5% {
+ background-color: rgb(57 255 20 / 75%);
+ box-shadow: 0 0 0 20px rgb(191 0 255 / 65%), 0 0 35px rgb(57 255 20 / 95%);
+ transform: scale(1.25) rotate(-3deg);
+ border: 3px solid rgb(255 69 0);
+ }
+ 100% {
+ background-color: transparent;
+ box-shadow: none;
+ transform: scale(1) rotate(0deg);
+ border: none;
+ }
+}
+/*
+This monstrosity includes:
+
+Neon rainbow cycling: Bright green → Hot pink → Electric blue → Neon purple → Nuclear yellow → Orange-red
+Double shadows: Inner colored shadow + outer glow effect
+Aggressive scaling: Up to 1.25x size
+Rotation wobble: Cards wiggle back and forth
+Strobing borders: Bright colored borders that change with each keyframe
+8 keyframes: More frequent color/effect changes
+Higher opacity: More saturated colors (up to 100% on yellow)
+
+This will literally assault the user's retinas. They'll need sunglasses to look at their shared tools! 🌈💥👁️🗨️*/
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
@@ -1404,6 +1497,12 @@ footer {
width: 90vw;
max-height: 35vh;
}
+ .tool-details {
+ max-height: 80vh;
+ padding: 1.5rem;
+ width: 95%;
+ max-width: none;
+ }
}
@media (width <= 640px) {
@@ -1488,6 +1587,11 @@ footer {
font-size: 0.75rem;
padding: 0.25rem 0.375rem;
}
+ .tool-details {
+ max-height: 75vh;
+ padding: 1rem;
+ border-radius: 0.25rem;
+ }
}
@@ -1577,4 +1681,35 @@ footer {
border: none;
border-top: 1px solid var(--color-border);
margin: 2rem 0;
+}
+
+/* Share Button Styles */
+.share-btn {
+ background: none;
+ border: none;
+ color: var(--color-text-secondary);
+ cursor: pointer;
+ padding: 0.25rem;
+ border-radius: 0.25rem;
+ transition: var(--transition-fast);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.share-btn:hover {
+ color: var(--color-primary);
+ background-color: var(--color-bg-secondary);
+}
+
+.share-btn--small {
+ padding: 0.125rem;
+}
+
+.share-btn--medium {
+ padding: 0.375rem;
+}
+
+.share-btn svg {
+ flex-shrink: 0;
}
\ No newline at end of file