Update environment configuration and enhance app functionality: Add detailed comments to the .env file for better clarity, implement a route to reload environment variables dynamically, and ensure the .env file is loaded with force in the app. Remove obsolete build and development scripts to streamline the project structure. Update setup script to create a .env file if it doesn't exist, prompting users to configure necessary values.
This commit is contained in:
14
website/.env
14
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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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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():
|
||||
|
||||
@@ -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
|
||||
|
||||
426
website/static/css/base-styles.css
Normal file
426
website/static/css/base-styles.css
Normal file
@@ -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);
|
||||
}
|
||||
@@ -14,6 +14,55 @@
|
||||
<meta name="keywords" content="systades, wissen, visualisierung, lernen, gedanken, theorie">
|
||||
<meta name="author" content="Systades-Team">
|
||||
|
||||
<!-- Tailwind CSS über CDN -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['Inter', 'ui-sans-serif', 'system-ui', '-apple-system', 'sans-serif'],
|
||||
mono: ['JetBrains Mono', 'ui-monospace', 'monospace']
|
||||
},
|
||||
colors: {
|
||||
primary: {
|
||||
50: '#f5f3ff',
|
||||
100: '#ede9fe',
|
||||
200: '#ddd6fe',
|
||||
300: '#c4b5fd',
|
||||
400: '#a78bfa',
|
||||
500: '#8b5cf6',
|
||||
600: '#7c3aed',
|
||||
700: '#6d28d9',
|
||||
800: '#5b21b6',
|
||||
900: '#4c1d95'
|
||||
},
|
||||
secondary: {
|
||||
50: '#ecfdf5',
|
||||
100: '#d1fae5',
|
||||
200: '#a7f3d0',
|
||||
300: '#6ee7b7',
|
||||
400: '#34d399',
|
||||
500: '#10b981',
|
||||
600: '#059669',
|
||||
700: '#047857',
|
||||
800: '#065f46',
|
||||
900: '#064e3b'
|
||||
},
|
||||
dark: {
|
||||
500: '#374151',
|
||||
600: '#1f2937',
|
||||
700: '#111827',
|
||||
800: '#0e1220',
|
||||
900: '#0a0e19'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
@@ -28,8 +77,8 @@
|
||||
<!-- Basis-Stylesheet -->
|
||||
<link href="{{ url_for('static', filename='style.css') }}" rel="stylesheet">
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<link href="{{ url_for('static', filename='css/main.css') }}" rel="stylesheet">
|
||||
<!-- Base-Styles ausgelagert in eigene Datei -->
|
||||
<link href="{{ url_for('static', filename='css/base-styles.css') }}" rel="stylesheet">
|
||||
|
||||
<!-- Alpine.js -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.12.3/dist/cdn.min.js"></script>
|
||||
@@ -102,437 +151,7 @@
|
||||
// MindMap global verfügbar machen (für Alpine.js und andere nicht-Module Skripte)
|
||||
window.MindMap = MindMap;
|
||||
</script>
|
||||
|
||||
<!-- Globale Stile für konsistentes Glasmorphismus-Design -->
|
||||
<style>
|
||||
/* 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);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Seitenspezifische Styles -->
|
||||
{% block extra_css %}{% endblock %}
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user