diff --git a/website/.env b/website/.env
index a44a6ea..a0ab5ba 100644
--- a/website/.env
+++ b/website/.env
@@ -1 +1,13 @@
-OPENAI_API_KEY=sk-placeholder
+# MindMap Umgebungsvariablen
+# Kopiere diese Datei zu .env und passe die Werte an
+
+# Flask
+SECRET_KEY=dein-geheimer-schluessel-hier
+
+# OpenAI API
+OPENAI_API_KEY=sk-dein-openai-api-schluessel-hier
+
+# Datenbank
+# Bei Bedarf kann hier eine andere Datenbank-URL angegeben werden
+# Der Pfad wird relativ zum Projektverzeichnis angegeben
+# SQLALCHEMY_DATABASE_URI=sqlite:////absoluter/pfad/zu/database/systades.db OPENAI_API_KEY=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
diff --git a/website/app.py b/website/app.py
index 8cd9d24..5ee97eb 100755
--- a/website/app.py
+++ b/website/app.py
@@ -26,7 +26,7 @@ from models import (
)
# Lade .env-Datei
-load_dotenv()
+load_dotenv(force=True) # force=True erzwingt die Synchronisierung
# Bestimme den absoluten Pfad zur Datenbank
basedir = os.path.abspath(os.path.dirname(__file__))
@@ -1126,6 +1126,31 @@ def dummy_network_bg():
"""Leere Antwort für die nicht mehr verwendeten Netzwerk-Hintergrundbilder."""
return '', 200
+# Route zum expliziten Neu-Laden der Umgebungsvariablen
+@app.route('/admin/reload-env', methods=['POST'])
+@admin_required
+def reload_env():
+ """Lädt die Umgebungsvariablen aus der .env-Datei neu."""
+ try:
+ # Erzwinge das Neuladen der .env-Datei
+ load_dotenv(override=True, force=True)
+
+ # Aktualisiere OpenAI API-Key
+ openai.api_key = os.environ.get('OPENAI_API_KEY')
+
+ # Weitere Umgebungsvariablen hier aktualisieren, falls nötig
+ app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', app.config['SECRET_KEY'])
+
+ return jsonify({
+ 'success': True,
+ 'message': 'Umgebungsvariablen wurden erfolgreich neu geladen.'
+ })
+ except Exception as e:
+ return jsonify({
+ 'success': False,
+ 'message': f'Fehler beim Neuladen der Umgebungsvariablen: {str(e)}'
+ }), 500
+
# Flask starten
if __name__ == '__main__':
with app.app_context():
diff --git a/website/build_css.py b/website/build_css.py
deleted file mode 100755
index 96fae31..0000000
--- a/website/build_css.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env python3
-import os
-import subprocess
-import shutil
-import platform
-import tempfile
-import zipfile
-import requests
-from pathlib import Path
-
-def download_tailwind_cli():
- """Download the standalone Tailwind CLI for the current platform"""
- # Get current system info
- system = platform.system().lower()
- arch = platform.machine().lower()
-
- # Map to tailwind downloadable platform
- if system == "linux":
- platform_name = "linux"
- elif system == "darwin":
- platform_name = "macos"
- elif system == "windows":
- platform_name = "windows"
- else:
- raise Exception(f"Unsupported platform: {system}")
-
- # Map architecture
- if "arm" in arch or "aarch" in arch:
- arch_name = "arm64"
- elif "x86_64" in arch or "amd64" in arch or "x64" in arch:
- arch_name = "x64"
- else:
- # Default to x64 for other architectures
- arch_name = "x64"
-
- # URL for the binary
- url = f"https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-{platform_name}-{arch_name}"
- if system == "windows":
- url += ".exe"
-
- # Download location
- bin_dir = Path("bin")
- bin_dir.mkdir(exist_ok=True)
- tailwind_bin = bin_dir / f"tailwindcss{'.exe' if system == 'windows' else ''}"
-
- # Download if not exists
- if not tailwind_bin.exists():
- print(f"Downloading Tailwind CLI from {url}...")
- response = requests.get(url, stream=True)
- response.raise_for_status()
-
- with open(tailwind_bin, 'wb') as f:
- for chunk in response.iter_content(chunk_size=8192):
- f.write(chunk)
-
- # Make executable on Unix
- if system != "windows":
- os.chmod(tailwind_bin, 0o755)
-
- return str(tailwind_bin)
-
-def build_css(watch=False):
- """Build CSS using Tailwind CLI"""
- base_dir = Path(__file__).parent
- input_file = base_dir / "static" / "css" / "src" / "input.css"
- output_file = base_dir / "static" / "css" / "main.css"
-
- tailwind_bin = download_tailwind_cli()
-
- config_file = base_dir / "tailwind.config.js"
-
- # Prepare command
- cmd = [
- tailwind_bin,
- "-i", str(input_file),
- "-o", str(output_file),
- "-c", str(config_file)
- ]
-
- if watch:
- cmd.append("--watch")
-
- print(f"Running: {' '.join(cmd)}")
-
- # Run the command
- if watch:
- process = subprocess.Popen(cmd)
- try:
- process.wait()
- except KeyboardInterrupt:
- process.terminate()
- print("\nBuild process terminated")
- else:
- subprocess.run(cmd, check=True)
- print(f"CSS built successfully: {output_file}")
-
-if __name__ == "__main__":
- import argparse
-
- parser = argparse.ArgumentParser(description="Build Tailwind CSS")
- parser.add_argument("--watch", action="store_true", help="Watch for changes")
- args = parser.parse_args()
-
- build_css(watch=args.watch)
\ No newline at end of file
diff --git a/website/dev.py b/website/dev.py
deleted file mode 100755
index 058c558..0000000
--- a/website/dev.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python3
-import os
-import sys
-import subprocess
-import threading
-import time
-from pathlib import Path
-
-def run_flask():
- """Run the Flask development server"""
- env = os.environ.copy()
- env["FLASK_ENV"] = "development"
- env["FLASK_DEBUG"] = "1"
-
- # Import and run the Flask app
- from run import app
- app.run(debug=True, use_reloader=False)
-
-def run_tailwind_watch():
- """Run the Tailwind CSS watcher"""
- # Import the build_css function from build_css.py
- from build_css import build_css
- build_css(watch=True)
-
-def main():
- """Run both the Flask server and Tailwind CSS watcher"""
- print("Starting development environment...")
-
- # Start Tailwind watcher in a separate thread
- tailwind_thread = threading.Thread(target=run_tailwind_watch, daemon=True)
- tailwind_thread.start()
-
- # Give Tailwind a moment to start
- time.sleep(1)
-
- # Run Flask in the main thread
- print("Starting Flask development server...")
- run_flask()
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/website/run.py b/website/run.py
index 174d8db..7657b40 100755
--- a/website/run.py
+++ b/website/run.py
@@ -2,10 +2,19 @@
import os
import sys
from pathlib import Path
+from dotenv import load_dotenv
from init_db import init_database
from app import app
if __name__ == "__main__":
+ # Lade .env-Datei explizit
+ env_path = Path(__file__).parent / ".env"
+ if env_path.exists():
+ print(f"Lade Umgebungsvariablen aus {env_path}")
+ load_dotenv(dotenv_path=env_path, override=True, force=True)
+ else:
+ print("Warnung: .env-Datei nicht gefunden!")
+
# Check if CSS file exists, build it if it doesn't
css_file = Path(__file__).parent / "static" / "css" / "main.css"
if not css_file.exists():
diff --git a/website/setup.sh b/website/setup.sh
index 10d32ea..32dcdf1 100755
--- a/website/setup.sh
+++ b/website/setup.sh
@@ -4,6 +4,7 @@
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
+YELLOW='\033[0;33m'
NC='\033[0m' # No Color
echo -e "${GREEN}==== MindMap Projekt Setup ====${NC}"
@@ -15,6 +16,17 @@ mkdir -p static/img
mkdir -p static/js
mkdir -p bin
+# Überprüfe, ob .env-Datei existiert und erstelle sie, wenn nicht
+echo -e "${BLUE}Überprüfe .env-Datei...${NC}"
+if [ ! -f ".env" ]; then
+ echo -e "${YELLOW}Keine .env-Datei gefunden. Erstelle neue .env-Datei aus example.env...${NC}"
+ cp example.env .env
+ echo -e "${YELLOW}Bitte bearbeiten Sie die .env-Datei und setzen Sie die erforderlichen Werte.${NC}"
+ echo -e "${YELLOW}Insbesondere müssen Sie einen gültigen API-Schlüssel für OpenAI setzen.${NC}"
+else
+ echo -e "${GREEN}.env-Datei existiert bereits.${NC}"
+fi
+
# Python-Abhängigkeiten installieren
echo -e "${BLUE}Installiere Python-Abhängigkeiten...${NC}"
pip install -r requirements.txt
diff --git a/website/static/css/base-styles.css b/website/static/css/base-styles.css
new file mode 100644
index 0000000..f7c70e9
--- /dev/null
+++ b/website/static/css/base-styles.css
@@ -0,0 +1,426 @@
+/* Globale Variablen */
+:root {
+ --dark-bg: #0e1220;
+ --dark-card-bg: rgba(24, 28, 45, 0.8);
+ --dark-element-bg: rgba(24, 28, 45, 0.8);
+ --light-bg: #f0f4f8;
+ --light-card-bg: rgba(255, 255, 255, 0.85);
+ --accent-color: #b38fff;
+ --accent-gradient: linear-gradient(135deg, #b38fff, #58a9ff);
+ --accent-gradient-hover: linear-gradient(135deg, #c7a8ff, #70b5ff);
+ --blur-amount: 20px;
+ --border-radius: 28px;
+ --card-border-radius: 24px;
+ --button-radius: 18px;
+ --nav-item-radius: 14px;
+}
+
+/* Dark Mode Einstellungen */
+html.dark {
+ color-scheme: dark;
+}
+
+/* Base Styles */
+html, body {
+ background-color: var(--dark-bg) !important;
+ min-height: 100vh;
+ width: 100%;
+ color: #ffffff;
+ margin: 0;
+ padding: 0;
+ font-family: 'Inter', system-ui, -apple-system, sans-serif;
+ overflow-x: hidden;
+ transition: background-color 0.5s ease, color 0.5s ease;
+}
+
+/* Sicherstellen, dass der dunkle Hintergrund die gesamte Seite abdeckt */
+#app-container, .container, main, .mx-auto, .py-12, #content-wrapper {
+ background-color: transparent !important;
+ width: 100%;
+}
+
+/* Light Mode Einstellungen */
+html.light, html.light body {
+ background-color: var(--light-bg) !important;
+ color: #1a202c;
+}
+
+/* Große Headings mit verbesserten Stilen */
+h1.hero-heading {
+ font-size: clamp(2.5rem, 8vw, 5rem);
+ line-height: 1.1;
+ font-weight: 800;
+ letter-spacing: -0.03em;
+ margin-bottom: 1.5rem;
+}
+
+h2.section-heading {
+ font-size: clamp(1.75rem, 5vw, 3rem);
+ line-height: 1.2;
+ font-weight: 700;
+ letter-spacing: -0.02em;
+ margin-bottom: 1.25rem;
+}
+
+/* Verbesserte Glasmorphismus-Stile */
+.glass-morphism {
+ background: var(--dark-card-bg);
+ backdrop-filter: blur(var(--blur-amount));
+ -webkit-backdrop-filter: blur(var(--blur-amount));
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ border-radius: var(--card-border-radius);
+ box-shadow: 0 12px 36px rgba(0, 0, 0, 0.35);
+ transition: all 0.3s ease;
+}
+
+.glass-morphism:hover {
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.45);
+ transform: translateY(-2px);
+}
+
+.glass-morphism-light {
+ background: var(--light-card-bg);
+ backdrop-filter: blur(var(--blur-amount));
+ -webkit-backdrop-filter: blur(var(--blur-amount));
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ border-radius: var(--card-border-radius);
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12);
+ transition: all 0.3s ease;
+}
+
+.glass-morphism-light:hover {
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18);
+ transform: translateY(-2px);
+}
+
+/* Verbesserte Navbar-Styles */
+.glass-navbar-dark {
+ background: rgba(14, 18, 32, 0.85);
+ backdrop-filter: blur(15px);
+ -webkit-backdrop-filter: blur(15px);
+ border-color: rgba(255, 255, 255, 0.1);
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
+ border-radius: 0 0 20px 20px;
+}
+
+.glass-navbar-light {
+ background: rgba(255, 255, 255, 0.85);
+ backdrop-filter: blur(15px);
+ -webkit-backdrop-filter: blur(15px);
+ border-color: rgba(0, 0, 0, 0.05);
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
+ border-radius: 0 0 20px 20px;
+}
+
+/* Verbesserte Button-Stile mit besserer Lesbarkeit und stärkeren Farbverläufen */
+.btn, button, .button, [type="button"], [type="submit"] {
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ border-radius: var(--button-radius);
+ padding: 0.75rem 1.5rem;
+ font-weight: 600;
+ letter-spacing: 0.4px;
+ color: rgba(255, 255, 255, 1);
+ background: linear-gradient(135deg, rgba(99, 102, 241, 0.8), rgba(168, 85, 247, 0.8));
+ border: 1px solid rgba(255, 255, 255, 0.15);
+ box-shadow: 0 6px 14px rgba(0, 0, 0, 0.2);
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
+ backdrop-filter: blur(15px);
+ -webkit-backdrop-filter: blur(15px);
+ position: relative;
+ overflow: hidden;
+ outline: none;
+}
+
+.btn:hover, button:hover, .button:hover, [type="button"]:hover, [type="submit"]:hover {
+ background: linear-gradient(135deg, rgba(129, 140, 248, 0.9), rgba(192, 132, 252, 0.9));
+ transform: translateY(-3px);
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ box-shadow: 0 8px 22px rgba(0, 0, 0, 0.25), 0 0 12px rgba(179, 143, 255, 0.35);
+ color: white;
+}
+
+.btn:active, button:active, .button:active, [type="button"]:active, [type="submit"]:active {
+ transform: translateY(1px);
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2);
+}
+
+/* Navigation Stile mit verbesserten Farbverläufen */
+.nav-link {
+ transition: all 0.25s ease;
+ border-radius: var(--nav-item-radius);
+ padding: 0.625rem 1rem;
+ font-weight: 500;
+ letter-spacing: 0.3px;
+ color: rgba(255, 255, 255, 0.9);
+ position: relative;
+ overflow: visible;
+}
+
+.nav-link:hover {
+ background: rgba(179, 143, 255, 0.2);
+ color: white;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+.nav-link-active {
+ background: linear-gradient(135deg, rgba(124, 58, 237, 0.3), rgba(139, 92, 246, 0.3));
+ color: white;
+ font-weight: 600;
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
+}
+
+.nav-link-active::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 10%;
+ width: 80%;
+ height: 2px;
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent);
+}
+
+/* Light-Mode Navigation Stile */
+.nav-link-light {
+ color: rgba(26, 32, 44, 0.85);
+}
+
+.nav-link-light:hover {
+ background: rgba(179, 143, 255, 0.15);
+ color: rgba(26, 32, 44, 1);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+}
+
+.nav-link-light-active {
+ background: linear-gradient(135deg, rgba(124, 58, 237, 0.2), rgba(139, 92, 246, 0.2));
+ color: rgba(26, 32, 44, 1);
+ font-weight: 600;
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
+}
+
+.nav-link-light-active::after {
+ background: linear-gradient(90deg, transparent, rgba(26, 32, 44, 0.5), transparent);
+}
+
+/* Entfernung von Gradient-Hintergrund überall */
+.gradient-bg, .purple-gradient, .gradient-purple-bg {
+ background: var(--dark-bg) !important;
+ background-image: none !important;
+}
+
+/* Verbesserte Light-Mode-Stile für Buttons */
+html.light .btn, html.light button, html.light .button,
+html.light [type="button"], html.light [type="submit"] {
+ background: linear-gradient(135deg, rgba(124, 58, 237, 0.7), rgba(139, 92, 246, 0.7));
+ color: #ffffff;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+ text-shadow: none;
+}
+
+html.light .btn:hover, html.light button:hover, html.light .button:hover,
+html.light [type="button"]:hover, html.light [type="submit"]:hover {
+ background: linear-gradient(135deg, rgba(139, 92, 246, 0.85), rgba(168, 85, 247, 0.85));
+ color: #ffffff;
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ box-shadow: 0 8px 22px rgba(0, 0, 0, 0.12), 0 0 12px rgba(179, 143, 255, 0.2);
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+}
+
+/* Verbesserte Buttons mit Glasmorphismus */
+.btn-primary {
+ background: linear-gradient(135deg, rgba(179, 143, 255, 0.8), rgba(88, 169, 255, 0.8));
+ backdrop-filter: blur(var(--blur-amount));
+ -webkit-backdrop-filter: blur(var(--blur-amount));
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ border-radius: var(--button-radius);
+ color: white !important;
+ font-weight: 600;
+ padding: 0.75rem 1.5rem;
+ transition: all 0.3s ease;
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
+}
+
+.btn-primary:hover {
+ transform: translateY(-3px);
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
+ background: linear-gradient(135deg, rgba(190, 160, 255, 0.9), rgba(100, 180, 255, 0.9));
+}
+
+.btn-secondary {
+ background: rgba(32, 36, 55, 0.8);
+ backdrop-filter: blur(var(--blur-amount));
+ -webkit-backdrop-filter: blur(var(--blur-amount));
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: var(--button-radius);
+ color: white;
+ font-weight: 500;
+ padding: 0.75rem 1.5rem;
+ transition: all 0.3s ease;
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
+}
+
+.btn-secondary:hover {
+ transform: translateY(-3px);
+ box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3);
+ background: rgba(38, 42, 65, 0.9);
+ border: 1px solid rgba(255, 255, 255, 0.15);
+}
+
+/* Steuerungsbutton-Stil */
+.control-btn {
+ padding: 0.5rem 1rem;
+ background: rgba(32, 36, 55, 0.8);
+ color: rgba(255, 255, 255, 0.9);
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ border-radius: 14px;
+ font-size: 0.875rem;
+ font-weight: 500;
+ transition: all 0.25s ease;
+ backdrop-filter: blur(15px);
+ -webkit-backdrop-filter: blur(15px);
+}
+
+.control-btn:hover {
+ background: rgba(38, 42, 65, 0.9);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ transform: translateY(-2px);
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
+}
+
+/* Verbesserter Farbverlauf-Text */
+.gradient-text {
+ background: linear-gradient(135deg, rgba(200, 170, 255, 1), rgba(100, 180, 255, 1));
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ font-weight: 700;
+ letter-spacing: -0.02em;
+ text-shadow: 0 2px 10px rgba(179, 143, 255, 0.3);
+ filter: drop-shadow(0 2px 6px rgba(179, 143, 255, 0.3));
+}
+
+/* Globaler Hintergrund */
+.full-page-bg {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ background-color: var(--dark-bg);
+ z-index: -10;
+}
+
+html.light .full-page-bg {
+ background-color: var(--light-bg);
+}
+
+/* Animationen für Hintergrundeffekte */
+@keyframes float {
+ 0% { transform: translateY(0); }
+ 50% { transform: translateY(-12px); }
+ 100% { transform: translateY(0); }
+}
+
+@keyframes pulse {
+ 0% { opacity: 0.7; transform: scale(1); }
+ 50% { opacity: 1; transform: scale(1.05); }
+ 100% { opacity: 0.7; transform: scale(1); }
+}
+
+.animate-float {
+ animation: float 6s ease-in-out infinite;
+}
+
+.animate-pulse {
+ animation: pulse 3s ease-in-out infinite;
+}
+
+/* Verbesserter Container für konsistente Layouts */
+.page-container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 2rem 1rem;
+}
+
+/* Dark Mode Toggle Stile */
+.dot {
+ transform: translateX(0);
+ transition: transform 0.3s ease-in-out, background-color 0.3s ease;
+}
+
+input:checked ~ .dot {
+ transform: translateX(100%);
+ background-color: #58a9ff;
+}
+
+input:checked ~ .block {
+ background-color: rgba(88, 169, 255, 0.4);
+}
+
+/* Feature Cards mit Glasmorphismus und Farbverlauf */
+.feature-card {
+ border-radius: var(--card-border-radius);
+ padding: 2rem;
+ transition: all 0.3s ease;
+ background: linear-gradient(145deg, rgba(32, 36, 55, 0.7), rgba(24, 28, 45, 0.9));
+ backdrop-filter: blur(var(--blur-amount));
+ -webkit-backdrop-filter: blur(var(--blur-amount));
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
+}
+
+.feature-card:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(255, 255, 255, 0.15);
+ background: linear-gradient(145deg, rgba(40, 44, 65, 0.8), rgba(28, 32, 50, 0.95));
+}
+
+html.light .feature-card {
+ background: linear-gradient(145deg, rgba(255, 255, 255, 0.8), rgba(240, 240, 250, 0.9));
+ border: 1px solid rgba(0, 0, 0, 0.05);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
+}
+
+html.light .feature-card:hover {
+ background: linear-gradient(145deg, rgba(255, 255, 255, 0.9), rgba(245, 245, 255, 0.95));
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
+}
+
+.feature-card .icon {
+ width: 60px;
+ height: 60px;
+ border-radius: 18px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1.5rem;
+ margin-bottom: 1.25rem;
+ background: linear-gradient(135deg, rgba(124, 58, 237, 0.8), rgba(139, 92, 246, 0.6));
+ color: white;
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
+}
+
+.feature-card h3 {
+ font-size: 1.25rem;
+ font-weight: 600;
+ margin-bottom: 0.75rem;
+ color: rgba(255, 255, 255, 0.95);
+}
+
+html.light .feature-card h3 {
+ color: rgba(26, 32, 44, 0.95);
+}
+
+.feature-card p {
+ color: rgba(255, 255, 255, 0.75);
+ line-height: 1.6;
+}
+
+html.light .feature-card p {
+ color: rgba(26, 32, 44, 0.75);
+}
\ No newline at end of file
diff --git a/website/templates/base.html b/website/templates/base.html
index 445af5f..84afdac 100644
--- a/website/templates/base.html
+++ b/website/templates/base.html
@@ -14,6 +14,55 @@
+
+
+
+
@@ -28,8 +77,8 @@
-
-
+
+
@@ -102,437 +151,7 @@
// MindMap global verfügbar machen (für Alpine.js und andere nicht-Module Skripte)
window.MindMap = MindMap;
-
-
-
-
{% block extra_css %}{% endblock %}