Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e3d20612f4 | |||
| b21ade22f3 | |||
| 64e1959a1b | |||
| 9315cc6743 | |||
| c709b025c0 | |||
| 5793cb156f | |||
| fe0a36f9aa | |||
| 6141442f1c | |||
| 9bf1377dd7 | |||
| 14af9e560d | |||
| 545f49778f | |||
| 53bc194870 | |||
| f2f36ec989 | |||
| 8e034f30ef | |||
| 1af6ae3854 | |||
| f1e3320ce0 | |||
| 68e9738c4a | |||
| 0d88fa0cdb | |||
| f676add4fb | |||
| d259836ac9 | |||
| ed6066357a | |||
| e1ef6af9a9 | |||
| 15808b533d | |||
| 35929cc932 | |||
| 4eee1273ed | |||
| 7d3727da6e | |||
| 3aec3e58d6 | |||
| 318c05d2de | |||
| de29ddd5bd | |||
| 2362bd4b8a | |||
| 8bd4a1cbec | |||
| 5905b39e0f | |||
| da11f827f1 | |||
| 0309454f00 | |||
| 0ecc994df4 | |||
| 00cc9635ae | |||
| b1c67f31c4 | |||
| 581e726f78 | |||
| c718f15f09 | |||
| a8caee15f9 | |||
| 17002ad833 | |||
| 89c3ddcef9 | |||
| 4055d37adf | |||
| 6fb4f97742 | |||
| b58d7f33f0 | |||
| a6c2e8681d | |||
| 5e75a7c2d6 | |||
| f8d30f86cc | |||
| b7c26b5229 | |||
| 68f35123af | |||
| 1f0f9abc2e | |||
| 40c67c99f3 | |||
| 371c3da66c | |||
| 73f47b161c | |||
| 44a88dcfad | |||
| 73968dfbd6 | |||
| aa30e33805 | |||
| f96993bb3b | |||
| 967ffbb563 | |||
| e23524b6bd | |||
| 197537e0a5 | |||
| 8ff96d2583 | |||
| 8a35cceefa | |||
| bf482ccdea | |||
| 865c6ac188 |
BIN
Dekra WebSite/images/LKW1.png
Normal file
|
After Width: | Height: | Size: 3.9 MiB |
1497
Dekra WebSite/truck-country-dekra-ci_1.html
Normal file
BIN
Dekra WebSite/videos/Warm_summer_country_202602231631_09uyk.mp4
Normal file
10
Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM webdevops/php-nginx:8.2-alpine
|
||||
|
||||
ENV WEB_DOCUMENT_ROOT=/app
|
||||
COPY ["Profice WebSite/", "/app/"]
|
||||
|
||||
COPY vhost.conf /opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
|
||||
|
||||
RUN chown -R application:application /app && chmod -R 755 /app
|
||||
|
||||
EXPOSE 80
|
||||
@@ -1 +0,0 @@
|
||||
Options -Indexes
|
||||
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 534 KiB |
|
Before Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 356 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 525 KiB |
|
Before Width: | Height: | Size: 161 KiB |
|
Before Width: | Height: | Size: 411 KiB |
|
Before Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 544 KiB |
|
Before Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 478 KiB |
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 378 KiB |
|
Before Width: | Height: | Size: 378 KiB |
|
Before Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 505 KiB |
|
Before Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 379 KiB |
|
Before Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 327 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 328 KiB |
|
Before Width: | Height: | Size: 936 KiB |
|
Before Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 949 KiB |
|
Before Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 1023 KiB |
|
Before Width: | Height: | Size: 328 KiB |
|
Before Width: | Height: | Size: 944 KiB |
|
Before Width: | Height: | Size: 958 KiB |
|
Before Width: | Height: | Size: 326 KiB |
|
Before Width: | Height: | Size: 879 KiB |
|
Before Width: | Height: | Size: 299 KiB |
|
Before Width: | Height: | Size: 1006 KiB |
|
Before Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 916 KiB |
|
Before Width: | Height: | Size: 296 KiB |
@@ -1,257 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profice - Digitale Lösungen</title>
|
||||
<link rel="stylesheet" href="style/design.css">
|
||||
<link rel="stylesheet" href="style/cursor.css">
|
||||
<link rel="stylesheet" href="style/cookie-consent.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="top-banner dark-theme">
|
||||
<div class="top-banner-left">
|
||||
<div class="banner-left">
|
||||
<button class="menu-toggle" id="menuToggle" aria-label="Menü">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
|
||||
<a href="index.html" class="logo-link">
|
||||
<img src="images/logo/logo-01-complete.png" alt="Profice Logo" class="logo" loading="lazy">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="top-banner-center">
|
||||
<nav class="main-nav">
|
||||
<a href="#hero-section" class="nav-link">Startseite</a>
|
||||
<a href="#enterprise" class="nav-link">Unternehmen</a>
|
||||
<a href="#pricing" class="nav-link">Preise</a>
|
||||
<a href="#services" class="nav-link">Lösungen</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="top-banner-right">
|
||||
<button id="cursorToggle" aria-label="Cursor umschalten" title="Benutzerdefinierten Cursor umschalten">
|
||||
<img src="images/additional/cursor.png" alt="Standard Cursor" class="cursor-icon">
|
||||
</button>
|
||||
<button id="loginBtn" class="login-btn" aria-label="Anmelden" title="Anmelden">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
||||
<polyline points="10 17 15 12 10 7"></polyline>
|
||||
<line x1="15" y1="12" x2="3" y2="12"></line>
|
||||
</svg>
|
||||
Anmelden
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<nav class="slide-menu" id="slideMenu">
|
||||
<a href="index.html" class="active">Startseite</a>
|
||||
<a href="sites/offers.html">Kontakt & Anfrage</a>
|
||||
<a href="sites/leads.html">Leads Dashboard</a>
|
||||
</nav>
|
||||
|
||||
<div class="overlay" id="overlay"></div>
|
||||
|
||||
<main class="home-content">
|
||||
|
||||
<section id="hero-section" class="hero-section">
|
||||
<div class="hero-text">
|
||||
<h1>Transformieren Sie Ihr Unternehmen digital</h1>
|
||||
<p>Maßgeschneiderte Lösungen für Web, KI-Integration und Prozessautomatisierung. Wir bringen Ihre Vision in die digitale Realität.</p>
|
||||
<div class="hero-buttons">
|
||||
<a href="sites/offers.html" class="cta-btn primary">Projekt starten</a>
|
||||
<a href="#services" class="cta-btn secondary">Mehr erfahren</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-image-placeholder">
|
||||
<span>[Bild: Digitale Transformation Illustration]</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="enterprise" class="enterprise-section">
|
||||
<h2 class="section-title">Unternehmenslösungen</h2>
|
||||
<div class="enterprise-content">
|
||||
<p>Maßgeschneiderte Lösungen für große Unternehmen mit komplexen Anforderungen.</p>
|
||||
<div class="enterprise-features">
|
||||
<div class="feature-item">
|
||||
<h3>Skalierbarkeit</h3>
|
||||
<p>Lösungen, die mit Ihrem Unternehmen wachsen</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<h3>Sicherheit</h3>
|
||||
<p>Unternehmenssicherheit und Compliance</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<h3>Integration</h3>
|
||||
<p>Nahtlose Integration mit bestehenden Systemen</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="pricing" class="pricing-section">
|
||||
<h2 class="section-title">Preise</h2>
|
||||
<div class="pricing-grid">
|
||||
<div class="pricing-card">
|
||||
<h3>Starter</h3>
|
||||
<div class="price">€999</div>
|
||||
<p>Perfekt für kleine Unternehmen</p>
|
||||
<ul>
|
||||
<li>Webentwicklung</li>
|
||||
<li>Grundlegende KI-Integration</li>
|
||||
<li>3 Monate Support</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pricing-card featured">
|
||||
<h3>Professional</h3>
|
||||
<div class="price">€2.499</div>
|
||||
<p>Ideal für wachsende Unternehmen</p>
|
||||
<ul>
|
||||
<li>Erweiterte Webentwicklung</li>
|
||||
<li>KI & Automatisierung</li>
|
||||
<li>6 Monate Support</li>
|
||||
<li>SEO Optimierung</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pricing-card">
|
||||
<h3>Unternehmen</h3>
|
||||
<div class="price">Individuell</div>
|
||||
<p>Für große Unternehmen</p>
|
||||
<ul>
|
||||
<li>Volle Unternehmenslösungen</li>
|
||||
<li>Custom KI-Entwicklung</li>
|
||||
<li>12 Monate Support</li>
|
||||
<li>Dediziertes Team</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="services" class="services-section">
|
||||
<h2 class="section-title">Unsere Expertise</h2>
|
||||
<div class="services-grid">
|
||||
|
||||
<div class="service-card">
|
||||
<div class="service-icon">
|
||||
🌐
|
||||
</div>
|
||||
<h3>Webentwicklung</h3>
|
||||
<p>Moderne, responsive Webseiten, die konvertieren und Ihre Marke perfekt repräsentieren.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-card">
|
||||
<div class="service-icon">
|
||||
🤖
|
||||
</div>
|
||||
<h3>KI Integration</h3>
|
||||
<p>Nutzen Sie die Kraft künstlicher Intelligenz, um Ihre Daten besser zu verstehen und Prozesse zu optimieren.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-card">
|
||||
<div class="service-icon">
|
||||
⚙️
|
||||
</div>
|
||||
<h3>Automatisierung</h3>
|
||||
<p>Sparen Sie Zeit und Ressourcen durch intelligente Workflow-Automatisierungen.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="info-section">
|
||||
<div class="info-container">
|
||||
<div class="info-content">
|
||||
<h2>Warum Profice?</h2>
|
||||
<p>Wir verbinden technologische Exzellenz mit tiefgreifendem Geschäftsverständnis. Unser Ziel ist nicht nur die Lieferung von Software, sondern die Schaffung von echtem Mehrwert für Ihr Unternehmen.</p>
|
||||
<ul class="info-list">
|
||||
<li>Individuelle Beratung</li>
|
||||
<li>Transparente Prozesse</li>
|
||||
<li>Zukunftssichere Technologien</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="info-image-placeholder">
|
||||
<span>[Bild: Team bei der Arbeit]</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<!-- Cookie Consent Banner -->
|
||||
<div id="cookieBanner" class="cookie-banner" role="dialog" aria-labelledby="cookieTitle" aria-describedby="cookieDescription">
|
||||
<div class="cookie-banner-content">
|
||||
<div class="cookie-text">
|
||||
<h3 id="cookieTitle">Cookie-Einstellungen</h3>
|
||||
<p id="cookieDescription">
|
||||
Wir verwenden Cookies, um Ihre Erfahrung zu verbessern und unsere Website zu analysieren.
|
||||
Durch die Nutzung unserer Website stimmen Sie unserem <a href="#privacy">Datenschutz</a> zu.
|
||||
</p>
|
||||
</div>
|
||||
<div class="cookie-buttons">
|
||||
<button id="cookieAcceptAll" class="cookie-btn cookie-btn-primary">Alle akzeptieren</button>
|
||||
<button id="cookieRejectAll" class="cookie-btn cookie-btn-secondary">Alle ablehnen</button>
|
||||
<button id="cookieSettings" class="cookie-btn cookie-btn-settings">Einstellungen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Cookie Settings Modal -->
|
||||
<div id="cookieModal" class="cookie-modal" role="dialog" aria-labelledby="cookieModalTitle" aria-modal="true">
|
||||
<div class="cookie-modal-content">
|
||||
<div class="cookie-modal-header">
|
||||
<h2 id="cookieModalTitle">Cookie-Einstellungen</h2>
|
||||
<button id="cookieModalClose" class="cookie-modal-close" aria-label="Schließen">×</button>
|
||||
</div>
|
||||
|
||||
<div class="cookie-option">
|
||||
<div class="cookie-option-header">
|
||||
<h3 class="cookie-option-title">Notwendige Cookies</h3>
|
||||
<div id="cookie-toggle-necessary" class="cookie-toggle active disabled" role="switch" aria-checked="true" aria-disabled="true">
|
||||
<div class="cookie-toggle-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="cookie-option-description">
|
||||
Diese Cookies sind für die Funktionsweise der Website unerlässlich und können nicht in Ihren Browsern deaktiviert werden.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cookie-option">
|
||||
<div class="cookie-option-header">
|
||||
<h3 class="cookie-option-title">Analyse-Cookies</h3>
|
||||
<div id="cookie-toggle-analytics" class="cookie-toggle" role="switch" aria-checked="false">
|
||||
<div class="cookie-toggle-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="cookie-option-description">
|
||||
Diese Cookies helfen uns zu verstehen, wie Besucher mit unserer Website interagieren, indem sie Informationen anonym sammeln und melden.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cookie-option">
|
||||
<div class="cookie-option-header">
|
||||
<h3 class="cookie-option-title">Marketing-Cookies</h3>
|
||||
<div id="cookie-toggle-marketing" class="cookie-toggle" role="switch" aria-checked="false">
|
||||
<div class="cookie-toggle-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="cookie-option-description">
|
||||
Diese Cookies werden verwendet, um Besucher über Websites hinweg zu verfolgen, um relevante Anzeigen zu zeigen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cookie-modal-footer">
|
||||
<button id="cookieSavePreferences" class="cookie-btn cookie-btn-primary">Einstellungen speichern</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/script.js" defer></script>
|
||||
<script src="scripts/cookie-consent.js" defer></script>
|
||||
<script src="scripts/cursor.js" defer></script>
|
||||
<script src="scripts/scroll-header.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,637 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Profice Web API Handler - Centralized Configuration
|
||||
* ALL SENSITIVE DATA STORED HERE - NOT VISIBLE TO CLIENT
|
||||
* Handles webhooks, API, tokens, cookie consent, tracking
|
||||
*/
|
||||
|
||||
// ==========================================
|
||||
// SECURITY HEADERS
|
||||
// ==========================================
|
||||
header('Content-Type: application/json');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
header('X-Frame-Options: DENY');
|
||||
header('X-XSS-Protection: 1; mode=block');
|
||||
header('Referrer-Policy: strict-origin-when-cross-origin');
|
||||
|
||||
// CORS - Restrict to your domain in production
|
||||
$allowedOrigins = [
|
||||
'https://profice.de',
|
||||
'https://www.profice.de',
|
||||
'http://localhost',
|
||||
'http://127.0.0.1'
|
||||
];
|
||||
|
||||
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
|
||||
if (in_array($origin, $allowedOrigins)) {
|
||||
header("Access-Control-Allow-Origin: $origin");
|
||||
} else {
|
||||
header('Access-Control-Allow-Origin: *'); // Development fallback
|
||||
}
|
||||
|
||||
header('Access-Control-Allow-Methods: POST, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type');
|
||||
header('Access-Control-Max-Age: 86400');
|
||||
|
||||
// Handle preflight OPTIONS request
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||||
http_response_code(200);
|
||||
exit();
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// SENSITIVE CONFIGURATION - HIDDEN FROM CLIENT
|
||||
// ==========================================
|
||||
|
||||
// Environment
|
||||
define('USE_PRODUCTION', false); // Use test webhook for debugging
|
||||
define('DEBUG_MODE', true); // Enable debug to see errors
|
||||
|
||||
// N8N Webhooks
|
||||
define('WEBHOOK_TEST', 'https://n8n.profice.de/webhook-test/d94ef798-3f43-46dd-8207-1e335e64518f');
|
||||
define('WEBHOOK_PROD', 'https://n8n.profice.de/webhook/d94ef798-3f43-46dd-8207-1e335e64518f');
|
||||
define('WEBHOOK_URL', USE_PRODUCTION ? WEBHOOK_PROD : WEBHOOK_TEST);
|
||||
|
||||
// Google Analytics
|
||||
define('GA_MEASUREMENT_ID', 'G-XXXXXXXXXX'); // Replace with your actual ID
|
||||
define('GA_API_SECRET', ''); // For server-side tracking
|
||||
|
||||
// Google Tag Manager
|
||||
define('GTM_CONTAINER_ID', 'GTM-XXXXXXX'); // Replace with your actual ID
|
||||
|
||||
// Facebook Pixel
|
||||
define('FB_PIXEL_ID', ''); // Replace with your actual ID
|
||||
define('FB_ACCESS_TOKEN', ''); // For Conversions API
|
||||
|
||||
// Google Ads
|
||||
define('GADS_CONVERSION_ID', 'AW-XXXXXXXXXX');
|
||||
define('GADS_CONVERSION_LABEL', '');
|
||||
|
||||
// LinkedIn Insight
|
||||
define('LINKEDIN_PARTNER_ID', '');
|
||||
|
||||
// API Keys
|
||||
define('API_SECRET_KEY', 'your-secret-key-here'); // For API authentication
|
||||
|
||||
// Rate Limiting
|
||||
define('RATE_LIMIT_REQUESTS', 100);
|
||||
define('RATE_LIMIT_WINDOW', 3600); // 1 hour
|
||||
|
||||
// ==========================================
|
||||
// HELPER FUNCTIONS
|
||||
// ==========================================
|
||||
|
||||
function sendResponse($success, $message, $data = null, $statusCode = 200) {
|
||||
http_response_code($statusCode);
|
||||
$response = [
|
||||
'success' => $success,
|
||||
'message' => $message,
|
||||
'timestamp' => date('c')
|
||||
];
|
||||
|
||||
// Only include data if not null and not in production (security)
|
||||
if ($data !== null && (!USE_PRODUCTION || DEBUG_MODE)) {
|
||||
$response['data'] = $data;
|
||||
} elseif ($data !== null && $success) {
|
||||
// In production, only return safe data
|
||||
$response['data'] = filterSafeData($data);
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
exit();
|
||||
}
|
||||
|
||||
function filterSafeData($data) {
|
||||
// Remove sensitive fields from response
|
||||
$sensitiveFields = ['webhook_url', 'ip_address', 'user_agent', 'http_code', 'error'];
|
||||
|
||||
if (is_array($data)) {
|
||||
foreach ($sensitiveFields as $field) {
|
||||
unset($data[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function getClientIP() {
|
||||
$ipKeys = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'];
|
||||
|
||||
foreach ($ipKeys as $key) {
|
||||
if (array_key_exists($key, $_SERVER)) {
|
||||
foreach (explode(',', $_SERVER[$key]) as $ip) {
|
||||
$ip = trim($ip);
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
||||
}
|
||||
|
||||
function sanitizeInput($input) {
|
||||
if (is_array($input)) {
|
||||
return array_map('sanitizeInput', $input);
|
||||
}
|
||||
return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
function validateCSRFToken($token) {
|
||||
// Implement CSRF validation if needed
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkRateLimit($ip) {
|
||||
$rateLimitFile = __DIR__ . '/rate_limits.json';
|
||||
$limits = [];
|
||||
|
||||
if (file_exists($rateLimitFile)) {
|
||||
$limits = json_decode(file_get_contents($rateLimitFile), true) ?: [];
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$windowStart = $now - RATE_LIMIT_WINDOW;
|
||||
|
||||
// Clean old entries
|
||||
$limits = array_filter($limits, function($entry) use ($windowStart) {
|
||||
return $entry['time'] > $windowStart;
|
||||
});
|
||||
|
||||
// Count requests from this IP
|
||||
$ipRequests = array_filter($limits, function($entry) use ($ip) {
|
||||
return $entry['ip'] === $ip;
|
||||
});
|
||||
|
||||
if (count($ipRequests) >= RATE_LIMIT_REQUESTS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add new request
|
||||
$limits[] = ['ip' => $ip, 'time' => $now];
|
||||
file_put_contents($rateLimitFile, json_encode($limits));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// WEBHOOK FUNCTIONS
|
||||
// ==========================================
|
||||
|
||||
function sendToWebhook($data, $webhookUrl = null) {
|
||||
$url = $webhookUrl ?? WEBHOOK_URL;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode($data),
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-Type: application/json',
|
||||
'User-Agent: Profice-Web-API/2.0'
|
||||
],
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_SSL_VERIFYPEER => !DEBUG_MODE, // Disable for debugging
|
||||
CURLOPT_FOLLOWLOCATION => true
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($error) {
|
||||
error_log("Webhook Error: " . $error);
|
||||
return ['success' => false, 'error' => $error, 'response' => $response];
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => $httpCode >= 200 && $httpCode < 300,
|
||||
'http_code' => $httpCode,
|
||||
'response' => $response,
|
||||
'error' => $error
|
||||
];
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// TRACKING FUNCTIONS - SERVER SIDE
|
||||
// ==========================================
|
||||
|
||||
function getTrackingConfig() {
|
||||
// Return tracking configuration for client
|
||||
// IDs are loaded from server, not exposed in JS
|
||||
return [
|
||||
'analytics_enabled' => !empty(GA_MEASUREMENT_ID) && GA_MEASUREMENT_ID !== 'G-XXXXXXXXXX',
|
||||
'gtm_enabled' => !empty(GTM_CONTAINER_ID) && GTM_CONTAINER_ID !== 'GTM-XXXXXXX',
|
||||
'fb_enabled' => !empty(FB_PIXEL_ID),
|
||||
'gads_enabled' => !empty(GADS_CONVERSION_ID) && GADS_CONVERSION_ID !== 'AW-XXXXXXXXXX',
|
||||
'linkedin_enabled' => !empty(LINKEDIN_PARTNER_ID)
|
||||
];
|
||||
}
|
||||
|
||||
function loadTrackingScripts($preferences) {
|
||||
$scripts = [];
|
||||
|
||||
// Google Analytics
|
||||
if ($preferences['analytics'] && !empty(GA_MEASUREMENT_ID) && GA_MEASUREMENT_ID !== 'G-XXXXXXXXXX') {
|
||||
$scripts['ga'] = [
|
||||
'type' => 'analytics',
|
||||
'src' => 'https://www.googletagmanager.com/gtag/js?id=' . GA_MEASUREMENT_ID,
|
||||
'config' => [
|
||||
'id' => GA_MEASUREMENT_ID
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// Google Tag Manager
|
||||
if ($preferences['analytics'] && !empty(GTM_CONTAINER_ID) && GTM_CONTAINER_ID !== 'GTM-XXXXXXX') {
|
||||
$scripts['gtm'] = [
|
||||
'type' => 'gtm',
|
||||
'src' => 'https://www.googletagmanager.com/gtm.js?id=' . GTM_CONTAINER_ID,
|
||||
'config' => [
|
||||
'id' => GTM_CONTAINER_ID
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// Facebook Pixel
|
||||
if ($preferences['marketing'] && !empty(FB_PIXEL_ID)) {
|
||||
$scripts['fb'] = [
|
||||
'type' => 'pixel',
|
||||
'src' => 'https://connect.facebook.net/en_US/fbevents.js',
|
||||
'config' => [
|
||||
'pixel_id' => FB_PIXEL_ID
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// Google Ads
|
||||
if ($preferences['marketing'] && !empty(GADS_CONVERSION_ID) && GADS_CONVERSION_ID !== 'AW-XXXXXXXXXX') {
|
||||
$scripts['gads'] = [
|
||||
'type' => 'conversion',
|
||||
'src' => 'https://www.googletagmanager.com/gtag/js?id=' . GADS_CONVERSION_ID,
|
||||
'config' => [
|
||||
'conversion_id' => GADS_CONVERSION_ID,
|
||||
'conversion_label' => GADS_CONVERSION_LABEL
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// LinkedIn
|
||||
if ($preferences['marketing'] && !empty(LINKEDIN_PARTNER_ID)) {
|
||||
$scripts['linkedin'] = [
|
||||
'type' => 'insight',
|
||||
'src' => 'https://snap.licdn.com/li.lms-analytics/insight.min.js',
|
||||
'config' => [
|
||||
'partner_id' => LINKEDIN_PARTNER_ID
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return $scripts;
|
||||
}
|
||||
|
||||
function sendEventToGA($data) {
|
||||
if (empty(GA_MEASUREMENT_ID) || GA_MEASUREMENT_ID === 'G-XXXXXXXXXX') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$postData = [
|
||||
'client_id' => $data['client_id'] ?? uniqid(),
|
||||
'user_id' => $data['user_id'] ?? null,
|
||||
'events' => [
|
||||
[
|
||||
'name' => $data['event_name'],
|
||||
'params' => $data['params'] ?? []
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$url = 'https://www.google-analytics.com/mp/collect';
|
||||
$url .= '?measurement_id=' . GA_MEASUREMENT_ID;
|
||||
$url .= '&api_secret=' . GA_API_SECRET;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode($postData),
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
||||
CURLOPT_TIMEOUT => 10
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
return $httpCode >= 200 && $httpCode < 300;
|
||||
}
|
||||
|
||||
function sendEventToFB($data) {
|
||||
if (empty(FB_PIXEL_ID) || empty(FB_ACCESS_TOKEN)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$postData = [
|
||||
'data' => [
|
||||
[
|
||||
'event_name' => $data['event_name'],
|
||||
'event_time' => time(),
|
||||
'action_source' => 'website',
|
||||
'user_data' => $data['user_data'] ?? [],
|
||||
'custom_data' => $data['custom_data'] ?? []
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$url = 'https://graph.facebook.com/v18.0/' . FB_PIXEL_ID . '/events';
|
||||
$url .= '?access_token=' . FB_ACCESS_TOKEN;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode($postData),
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
||||
CURLOPT_TIMEOUT => 10
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
return $httpCode >= 200 && $httpCode < 300;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// STORAGE FUNCTIONS
|
||||
// ==========================================
|
||||
|
||||
function storeLead($data) {
|
||||
$leadFile = __DIR__ . '/data/leads.json';
|
||||
$dir = dirname($leadFile);
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
}
|
||||
|
||||
$leads = [];
|
||||
if (file_exists($leadFile)) {
|
||||
$leads = json_decode(file_get_contents($leadFile), true) ?: [];
|
||||
}
|
||||
|
||||
$lead = [
|
||||
'id' => uniqid('lead_', true),
|
||||
'datum' => date('d.m.Y'),
|
||||
'dienstleistung' => $data['service'] ?? 'Allgemein',
|
||||
'status' => 'open',
|
||||
'statusText' => 'Offen',
|
||||
'description' => $data['description'] ?? '',
|
||||
'name' => $data['name'] ?? '',
|
||||
'contact' => $data['contact'] ?? '',
|
||||
'organisation' => $data['organisation'] ?? '',
|
||||
'timestamp' => date('c'),
|
||||
'ip_address' => getClientIP()
|
||||
];
|
||||
|
||||
array_unshift($leads, $lead);
|
||||
$leads = array_slice($leads, 0, 100);
|
||||
|
||||
file_put_contents($leadFile, json_encode($leads, JSON_PRETTY_PRINT));
|
||||
return $lead['id'];
|
||||
}
|
||||
|
||||
function storeCookieConsent($data) {
|
||||
$consentFile = __DIR__ . '/data/cookie_consent.json';
|
||||
$dir = dirname($consentFile);
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
}
|
||||
|
||||
$consents = [];
|
||||
if (file_exists($consentFile)) {
|
||||
$consents = json_decode(file_get_contents($consentFile), true) ?: [];
|
||||
}
|
||||
|
||||
$consent = [
|
||||
'id' => uniqid('consent_', true),
|
||||
'timestamp' => date('c'),
|
||||
'preferences' => $data['preferences'] ?? [],
|
||||
'ip_address' => getClientIP(),
|
||||
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? ''
|
||||
];
|
||||
|
||||
array_unshift($consents, $consent);
|
||||
$consents = array_slice($consents, 0, 1000);
|
||||
|
||||
file_put_contents($consentFile, json_encode($consents, JSON_PRETTY_PRINT));
|
||||
return $consent['id'];
|
||||
}
|
||||
|
||||
function getCookieConsent() {
|
||||
$consentFile = __DIR__ . '/data/cookie_consent.json';
|
||||
|
||||
if (!file_exists($consentFile)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$consents = json_decode(file_get_contents($consentFile), true) ?: [];
|
||||
return $consents[0] ?? null;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// REQUEST HANDLERS
|
||||
// ==========================================
|
||||
|
||||
function handleContactForm($data) {
|
||||
$required = ['name', 'contact'];
|
||||
foreach ($required as $field) {
|
||||
if (empty($data[$field])) {
|
||||
sendResponse(false, "Pflichtfeld fehlt: {$field}", null, 400);
|
||||
}
|
||||
}
|
||||
|
||||
$formData = [
|
||||
'name' => sanitizeInput($data['name']),
|
||||
'organisation' => sanitizeInput($data['organisation'] ?? ''),
|
||||
'contact' => sanitizeInput($data['contact']),
|
||||
'service' => sanitizeInput($data['service'] ?? ''),
|
||||
'budget' => sanitizeInput($data['budget'] ?? ''),
|
||||
'description' => sanitizeInput($data['description'] ?? ''),
|
||||
'timestamp' => date('c'),
|
||||
'source' => 'contact_form',
|
||||
'form_type' => 'offer',
|
||||
'ip_address' => getClientIP()
|
||||
];
|
||||
|
||||
// Store lead locally first
|
||||
$leadId = storeLead($formData);
|
||||
|
||||
// Send to webhook
|
||||
$webhookResult = sendToWebhook($formData);
|
||||
|
||||
// Always return success to user, but include webhook info in debug mode
|
||||
$debugData = DEBUG_MODE ? [
|
||||
'lead_id' => $leadId,
|
||||
'webhook_result' => $webhookResult,
|
||||
'webhook_url' => WEBHOOK_URL,
|
||||
'form_data' => $formData
|
||||
] : null;
|
||||
|
||||
if ($webhookResult['success']) {
|
||||
sendResponse(true, 'Formular erfolgreich gesendet', $debugData);
|
||||
} else {
|
||||
// Still return success to user but log the webhook error
|
||||
error_log('Webhook failed but form was stored locally: ' . json_encode($webhookResult));
|
||||
sendResponse(true, 'Formular erfolgreich gesendet (Webhook-Fehler protokolliert)', $debugData);
|
||||
}
|
||||
}
|
||||
|
||||
function handleLoginForm($data) {
|
||||
$required = ['email', 'password'];
|
||||
foreach ($required as $field) {
|
||||
if (empty($data[$field])) {
|
||||
sendResponse(false, "Pflichtfeld fehlt: {$field}", null, 400);
|
||||
}
|
||||
}
|
||||
|
||||
// Add your login logic here
|
||||
sendResponse(true, 'Login erfolgreich');
|
||||
}
|
||||
|
||||
function handleRegisterForm($data) {
|
||||
$required = ['name', 'email', 'password'];
|
||||
foreach ($required as $field) {
|
||||
if (empty($data[$field])) {
|
||||
sendResponse(false, "Pflichtfeld fehlt: {$field}", null, 400);
|
||||
}
|
||||
}
|
||||
|
||||
// Add your registration logic here
|
||||
sendResponse(true, 'Registrierung erfolgreich');
|
||||
}
|
||||
|
||||
function handleLeadForm($data) {
|
||||
// Handle lead form submissions
|
||||
$leadId = storeLead($data);
|
||||
sendResponse(true, 'Lead gespeichert', ['lead_id' => $leadId]);
|
||||
}
|
||||
|
||||
function handleCookieConsent($data) {
|
||||
$preferences = $data['preferences'] ?? [];
|
||||
$consentId = storeCookieConsent(['preferences' => $preferences]);
|
||||
|
||||
// Load tracking scripts based on preferences
|
||||
$scripts = loadTrackingScripts($preferences);
|
||||
|
||||
sendResponse(true, 'Cookie-Einstellungen gespeichert', [
|
||||
'consent_id' => $consentId,
|
||||
'scripts' => $scripts
|
||||
]);
|
||||
}
|
||||
|
||||
function handleGetCookieConsent($data) {
|
||||
$consent = getCookieConsent();
|
||||
if ($consent) {
|
||||
sendResponse(true, 'Cookie-Einstellungen gefunden', $consent);
|
||||
} else {
|
||||
sendResponse(false, 'Keine Cookie-Einstellungen gefunden', null, 404);
|
||||
}
|
||||
}
|
||||
|
||||
function handleGetTrackingConfig($data) {
|
||||
$config = getTrackingConfig();
|
||||
sendResponse(true, 'Tracking-Konfiguration', $config);
|
||||
}
|
||||
|
||||
function handleTrackEvent($data) {
|
||||
$eventName = $data['event_name'] ?? '';
|
||||
$eventData = $data['event_data'] ?? [];
|
||||
|
||||
// Send to Google Analytics
|
||||
$gaSuccess = sendEventToGA([
|
||||
'event_name' => $eventName,
|
||||
'params' => $eventData
|
||||
]);
|
||||
|
||||
// Send to Facebook
|
||||
$fbSuccess = sendEventToFB([
|
||||
'event_name' => $eventName,
|
||||
'custom_data' => $eventData
|
||||
]);
|
||||
|
||||
sendResponse(true, 'Event gesendet', [
|
||||
'ga_success' => $gaSuccess,
|
||||
'fb_success' => $fbSuccess
|
||||
]);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// MAIN REQUEST HANDLER
|
||||
// ==========================================
|
||||
|
||||
// Validate request method
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
sendResponse(false, 'Nur POST-Anfragen erlaubt', null, 405);
|
||||
}
|
||||
|
||||
// Rate limiting
|
||||
$clientIP = getClientIP();
|
||||
if (!checkRateLimit($clientIP)) {
|
||||
sendResponse(false, 'Zu viele Anfragen. Bitte später erneut versuchen.', null, 429);
|
||||
}
|
||||
|
||||
// Get JSON input
|
||||
$jsonInput = file_get_contents('php://input');
|
||||
$data = json_decode($jsonInput, true);
|
||||
|
||||
if (!$data) {
|
||||
$data = $_POST;
|
||||
}
|
||||
|
||||
if (!$data || empty($data)) {
|
||||
sendResponse(false, 'Keine Daten empfangen', null, 400);
|
||||
}
|
||||
|
||||
$requestType = $data['type'] ?? 'contact';
|
||||
|
||||
try {
|
||||
switch ($requestType) {
|
||||
case 'contact':
|
||||
handleContactForm($data);
|
||||
break;
|
||||
case 'login':
|
||||
handleLoginForm($data);
|
||||
break;
|
||||
case 'register':
|
||||
handleRegisterForm($data);
|
||||
break;
|
||||
case 'lead':
|
||||
handleLeadForm($data);
|
||||
break;
|
||||
case 'cookie_consent':
|
||||
handleCookieConsent($data);
|
||||
break;
|
||||
case 'get_cookie_consent':
|
||||
handleGetCookieConsent($data);
|
||||
break;
|
||||
case 'get_tracking_config':
|
||||
handleGetTrackingConfig($data);
|
||||
break;
|
||||
case 'track_event':
|
||||
handleTrackEvent($data);
|
||||
break;
|
||||
default:
|
||||
sendResponse(false, 'Ungültiger Anfragetyp', null, 400);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log('API Error: ' . $e->getMessage());
|
||||
error_log('Stack trace: ' . $e->getTraceAsString());
|
||||
sendResponse(false, 'Interner Serverfehler', null, 500);
|
||||
}
|
||||
?>
|
||||
@@ -1,423 +0,0 @@
|
||||
/**
|
||||
* Cookie Consent Management System
|
||||
* All sensitive data (tracking IDs, URLs) are loaded from server-side PHP
|
||||
* Includes fallback for local file access (no server)
|
||||
*
|
||||
* @version 2.1.0
|
||||
*/
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// ==========================================
|
||||
// CONFIGURATION
|
||||
// ==========================================
|
||||
|
||||
const cookieCategories = ['necessary', 'analytics', 'marketing'];
|
||||
const API_ENDPOINT = 'scripts/add/send.php';
|
||||
|
||||
// Detect if running from file:// protocol (no server)
|
||||
const isLocalFile = window.location.protocol === 'file:';
|
||||
|
||||
let consentState = {
|
||||
hasConsented: false,
|
||||
preferences: {}
|
||||
};
|
||||
|
||||
let previousPreferences = {};
|
||||
let trackingScripts = {};
|
||||
|
||||
// ==========================================
|
||||
// DATALAYER INTEGRATION
|
||||
// ==========================================
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
function pushConsentToDataLayer(preferences) {
|
||||
window.dataLayer.push({
|
||||
'event': 'consent_update',
|
||||
'consent': {
|
||||
'analytics_storage': preferences.analytics ? 'granted' : 'denied',
|
||||
'ad_storage': preferences.marketing ? 'granted' : 'denied',
|
||||
'functionality_storage': preferences.necessary ? 'granted' : 'denied',
|
||||
'personalization_storage': preferences.marketing ? 'granted' : 'denied',
|
||||
'security_storage': 'granted'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setDefaultConsent() {
|
||||
window.dataLayer.push({
|
||||
'event': 'consent_default',
|
||||
'consent': {
|
||||
'analytics_storage': 'denied',
|
||||
'ad_storage': 'denied',
|
||||
'functionality_storage': 'granted',
|
||||
'personalization_storage': 'denied',
|
||||
'security_storage': 'granted',
|
||||
'wait_for_update': 500
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// STORAGE (API + LOCALSTORAGE FALLBACK)
|
||||
// ==========================================
|
||||
|
||||
async function saveConsentToStorage(preferences) {
|
||||
// Always save to localStorage as backup
|
||||
const consentData = {
|
||||
hasConsented: true,
|
||||
preferences: preferences,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
localStorage.setItem('cookieConsent', JSON.stringify(consentData));
|
||||
|
||||
// Try API if not local file
|
||||
if (!isLocalFile) {
|
||||
try {
|
||||
const response = await fetch(API_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ type: 'cookie_consent', preferences })
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success && result.data && result.data.scripts) {
|
||||
trackingScripts = result.data.scripts;
|
||||
}
|
||||
return result.success;
|
||||
} catch (e) {
|
||||
// API failed, localStorage already saved
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function getConsentFromStorage() {
|
||||
// Try localStorage first (faster)
|
||||
const localConsent = localStorage.getItem('cookieConsent');
|
||||
if (localConsent) {
|
||||
try {
|
||||
return JSON.parse(localConsent);
|
||||
} catch (e) {
|
||||
localStorage.removeItem('cookieConsent');
|
||||
}
|
||||
}
|
||||
|
||||
// Try API if not local file
|
||||
if (!isLocalFile) {
|
||||
try {
|
||||
const response = await fetch(API_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ type: 'get_cookie_consent' })
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success && result.data) {
|
||||
if (result.data.scripts) {
|
||||
trackingScripts = result.data.scripts;
|
||||
}
|
||||
// Cache in localStorage
|
||||
localStorage.setItem('cookieConsent', JSON.stringify(result.data));
|
||||
return result.data;
|
||||
}
|
||||
} catch (e) {
|
||||
// API unavailable
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// SCRIPT LOADING
|
||||
// ==========================================
|
||||
|
||||
function loadTrackingScripts() {
|
||||
if (!trackingScripts || Object.keys(trackingScripts).length === 0) return;
|
||||
|
||||
if (trackingScripts.ga && consentState.preferences.analytics) {
|
||||
loadGoogleAnalytics(trackingScripts.ga);
|
||||
}
|
||||
if (trackingScripts.gtm && consentState.preferences.analytics) {
|
||||
loadGTM(trackingScripts.gtm);
|
||||
}
|
||||
if (trackingScripts.fb && consentState.preferences.marketing) {
|
||||
loadFacebookPixel(trackingScripts.fb);
|
||||
}
|
||||
if (trackingScripts.gads && consentState.preferences.marketing) {
|
||||
loadGoogleAds(trackingScripts.gads);
|
||||
}
|
||||
if (trackingScripts.linkedin && consentState.preferences.marketing) {
|
||||
loadLinkedIn(trackingScripts.linkedin);
|
||||
}
|
||||
}
|
||||
|
||||
function loadScript(src, callback) {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.async = true;
|
||||
if (callback) script.onload = callback;
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
function loadGoogleAnalytics(config) {
|
||||
if (!config.src || !config.config || !config.config.id) return;
|
||||
loadScript(config.src, function() {
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
window.gtag = gtag;
|
||||
gtag('js', new Date());
|
||||
gtag('config', config.config.id);
|
||||
});
|
||||
}
|
||||
|
||||
function loadGTM(config) {
|
||||
if (!config.id) return;
|
||||
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer',config.id);
|
||||
}
|
||||
|
||||
function loadFacebookPixel(config) {
|
||||
if (!config.id) return;
|
||||
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
||||
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
|
||||
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
|
||||
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
|
||||
document,'script','https://connect.facebook.net/en_US/fbevents.js');
|
||||
fbq('init', config.id);
|
||||
fbq('track', 'PageView');
|
||||
}
|
||||
|
||||
function loadGoogleAds(config) {
|
||||
if (!config.id) return;
|
||||
loadScript('https://www.googletagmanager.com/gtag/js?id=' + config.id, function() {
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', config.id);
|
||||
});
|
||||
}
|
||||
|
||||
function loadLinkedIn(config) {
|
||||
if (!config.id) return;
|
||||
window._linkedin_partner_id = config.id;
|
||||
window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
|
||||
window._linkedin_data_partner_ids.push(config.id);
|
||||
loadScript('https://snap.licdn.com/li.lms-analytics/insight.min.js');
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// COOKIE DELETION
|
||||
// ==========================================
|
||||
|
||||
const cookiePatterns = {
|
||||
analytics: ['_ga', '_gid', '_gat', '__utma', '__utmb', '__utmc', '__utmz'],
|
||||
marketing: ['_fbp', '_fbc', 'fr', '_gcl_au', '_gcl_aw', 'IDE', 'DSID', 'NID']
|
||||
};
|
||||
|
||||
function deleteCookie(name) {
|
||||
const paths = ['/', window.location.pathname];
|
||||
const domains = ['', window.location.hostname, '.' + window.location.hostname];
|
||||
|
||||
paths.forEach(path => {
|
||||
domains.forEach(domain => {
|
||||
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}${domain ? '; domain=' + domain : ''}`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function deleteCookiesForCategory(category) {
|
||||
const patterns = cookiePatterns[category] || [];
|
||||
const allCookies = document.cookie.split(';');
|
||||
|
||||
allCookies.forEach(cookie => {
|
||||
const cookieName = cookie.split('=')[0].trim();
|
||||
patterns.forEach(pattern => {
|
||||
if (cookieName.startsWith(pattern)) {
|
||||
deleteCookie(cookieName);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handlePreferenceChanges(newPreferences) {
|
||||
Object.keys(cookiePatterns).forEach(category => {
|
||||
if (previousPreferences[category] === true && newPreferences[category] === false) {
|
||||
deleteCookiesForCategory(category);
|
||||
window.dataLayer.push({ 'event': 'consent_revoked', 'consent_category': category });
|
||||
}
|
||||
});
|
||||
previousPreferences = { ...newPreferences };
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// DOM ELEMENTS
|
||||
// ==========================================
|
||||
|
||||
const cookieBanner = document.getElementById('cookieBanner');
|
||||
const cookieModal = document.getElementById('cookieModal');
|
||||
const acceptAllBtn = document.getElementById('cookieAcceptAll');
|
||||
const rejectAllBtn = document.getElementById('cookieRejectAll');
|
||||
const settingsBtn = document.getElementById('cookieSettings');
|
||||
const modalCloseBtn = document.getElementById('cookieModalClose');
|
||||
const savePreferencesBtn = document.getElementById('cookieSavePreferences');
|
||||
|
||||
// ==========================================
|
||||
// CORE FUNCTIONS
|
||||
// ==========================================
|
||||
|
||||
async function initCookieConsent() {
|
||||
setDefaultConsent();
|
||||
|
||||
const savedConsent = await getConsentFromStorage();
|
||||
|
||||
if (savedConsent && savedConsent.hasConsented) {
|
||||
consentState = {
|
||||
hasConsented: true,
|
||||
preferences: savedConsent.preferences || {}
|
||||
};
|
||||
previousPreferences = { ...consentState.preferences };
|
||||
applyConsentPreferences();
|
||||
return;
|
||||
}
|
||||
|
||||
// Show banner after short delay
|
||||
setTimeout(() => {
|
||||
if (cookieBanner) cookieBanner.classList.add('show');
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function applyConsentPreferences() {
|
||||
pushConsentToDataLayer(consentState.preferences);
|
||||
loadTrackingScripts();
|
||||
window.dispatchEvent(new CustomEvent('cookieConsentUpdated', { detail: consentState.preferences }));
|
||||
}
|
||||
|
||||
async function saveConsent(preferences) {
|
||||
handlePreferenceChanges(preferences);
|
||||
await saveConsentToStorage(preferences);
|
||||
|
||||
consentState = {
|
||||
hasConsented: true,
|
||||
preferences: preferences,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
|
||||
applyConsentPreferences();
|
||||
}
|
||||
|
||||
function hideBanner() {
|
||||
if (cookieBanner) cookieBanner.classList.remove('show');
|
||||
}
|
||||
|
||||
function showSettingsModal() {
|
||||
if (cookieModal) {
|
||||
cookieModal.classList.add('show');
|
||||
populateSettingsModal();
|
||||
}
|
||||
}
|
||||
|
||||
function hideSettingsModal() {
|
||||
if (cookieModal) cookieModal.classList.remove('show');
|
||||
}
|
||||
|
||||
function populateSettingsModal() {
|
||||
cookieCategories.forEach(key => {
|
||||
const toggle = document.getElementById(`cookie-toggle-${key}`);
|
||||
if (!toggle) return;
|
||||
|
||||
const isEnabled = consentState.preferences[key] || false;
|
||||
const isRequired = key === 'necessary';
|
||||
|
||||
if (isRequired) {
|
||||
toggle.classList.add('active', 'disabled');
|
||||
toggle.setAttribute('aria-checked', 'true');
|
||||
toggle.setAttribute('aria-disabled', 'true');
|
||||
} else {
|
||||
toggle.classList.toggle('active', isEnabled);
|
||||
toggle.setAttribute('aria-checked', isEnabled ? 'true' : 'false');
|
||||
toggle.onclick = () => {
|
||||
toggle.classList.toggle('active');
|
||||
toggle.setAttribute('aria-checked', toggle.classList.contains('active') ? 'true' : 'false');
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getModalPreferences() {
|
||||
const preferences = {};
|
||||
cookieCategories.forEach(key => {
|
||||
const toggle = document.getElementById(`cookie-toggle-${key}`);
|
||||
preferences[key] = key === 'necessary' ? true : (toggle ? toggle.classList.contains('active') : false);
|
||||
});
|
||||
return preferences;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// EVENT LISTENERS
|
||||
// ==========================================
|
||||
|
||||
if (acceptAllBtn) {
|
||||
acceptAllBtn.addEventListener('click', () => {
|
||||
const preferences = {};
|
||||
cookieCategories.forEach(key => preferences[key] = true);
|
||||
saveConsent(preferences);
|
||||
hideBanner();
|
||||
});
|
||||
}
|
||||
|
||||
if (rejectAllBtn) {
|
||||
rejectAllBtn.addEventListener('click', () => {
|
||||
saveConsent({ necessary: true, analytics: false, marketing: false });
|
||||
hideBanner();
|
||||
});
|
||||
}
|
||||
|
||||
if (settingsBtn) {
|
||||
settingsBtn.addEventListener('click', showSettingsModal);
|
||||
}
|
||||
|
||||
if (modalCloseBtn) {
|
||||
modalCloseBtn.addEventListener('click', hideSettingsModal);
|
||||
}
|
||||
|
||||
if (savePreferencesBtn) {
|
||||
savePreferencesBtn.addEventListener('click', () => {
|
||||
saveConsent(getModalPreferences());
|
||||
hideSettingsModal();
|
||||
hideBanner();
|
||||
});
|
||||
}
|
||||
|
||||
if (cookieModal) {
|
||||
cookieModal.addEventListener('click', (e) => {
|
||||
if (e.target === cookieModal) hideSettingsModal();
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && cookieModal && cookieModal.classList.contains('show')) {
|
||||
hideSettingsModal();
|
||||
}
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// PUBLIC API
|
||||
// ==========================================
|
||||
|
||||
window.CookieConsent = {
|
||||
getConsent: () => consentState,
|
||||
hasConsent: (category) => consentState.preferences[category] === true,
|
||||
updateConsent: saveConsent,
|
||||
showSettings: showSettingsModal
|
||||
};
|
||||
|
||||
// ==========================================
|
||||
// INITIALIZE
|
||||
// ==========================================
|
||||
|
||||
initCookieConsent();
|
||||
});
|
||||
@@ -1,210 +0,0 @@
|
||||
// cursor.js
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
if (window.matchMedia("(pointer: coarse)").matches) return;
|
||||
|
||||
// --- SETTINGS ---
|
||||
const CONFIG = {
|
||||
tentacleCount: 8,
|
||||
triggerDist: 10,
|
||||
maxLength: 300,
|
||||
connectionDist: 150,
|
||||
thickness: 1,
|
||||
color: "rgba(20, 20, 20, 1)",
|
||||
prediction: 3.5
|
||||
};
|
||||
|
||||
|
||||
const toggleBtn = document.getElementById('cursorToggle');
|
||||
const body = document.body;
|
||||
|
||||
// Default to system cursor (disabled custom cursor)
|
||||
let isCursorDisabled = localStorage.getItem('venomCursorDisabled') !== 'false';
|
||||
|
||||
function updateCursorState() {
|
||||
if (isCursorDisabled) {
|
||||
// System cursor (default) - show spidy icon
|
||||
body.classList.add('system-cursor');
|
||||
if (toggleBtn) {
|
||||
toggleBtn.classList.remove('active');
|
||||
const icon = toggleBtn.querySelector('.cursor-icon');
|
||||
if (icon) {
|
||||
// Check if we're on a page in the sites/ folder
|
||||
const currentPath = window.location.pathname;
|
||||
const isInSitesFolder = currentPath.includes('/sites/');
|
||||
const imagePath = isInSitesFolder ? '../images/additional/spidy.png' : 'images/additional/spidy.png';
|
||||
icon.src = imagePath;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Custom cursor (secondary) - show cursor icon
|
||||
body.classList.remove('system-cursor');
|
||||
if (toggleBtn) {
|
||||
toggleBtn.classList.add('active');
|
||||
const icon = toggleBtn.querySelector('.cursor-icon');
|
||||
if (icon) {
|
||||
// Check if we're on a page in the sites/ folder
|
||||
const currentPath = window.location.pathname;
|
||||
const isInSitesFolder = currentPath.includes('/sites/');
|
||||
const imagePath = isInSitesFolder ? '../images/additional/cursor.png' : 'images/additional/cursor.png';
|
||||
icon.src = imagePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateCursorState();
|
||||
|
||||
if (toggleBtn) {
|
||||
toggleBtn.addEventListener('click', () => {
|
||||
isCursorDisabled = !isCursorDisabled;
|
||||
localStorage.setItem('venomCursorDisabled', isCursorDisabled);
|
||||
updateCursorState();
|
||||
});
|
||||
}
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.id = "venom-cursor";
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
const width = window.innerWidth;
|
||||
const height = window.innerHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const tentacles = [];
|
||||
const mouse = { x: 0, y: 0 };
|
||||
const oldMouse = { x: 0, y: 0 };
|
||||
|
||||
document.addEventListener("mousemove", (e) => {
|
||||
mouse.x = e.clientX;
|
||||
mouse.y = e.clientY;
|
||||
});
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
});
|
||||
|
||||
class Tentacle {
|
||||
constructor(mx, my, targetX, targetY) {
|
||||
this.dead = false;
|
||||
this.anchor = { x: targetX, y: targetY };
|
||||
this.currentDist = 0; // For calculating connection opacity
|
||||
}
|
||||
|
||||
update(currentMouse) {
|
||||
const dx = currentMouse.x - this.anchor.x;
|
||||
const dy = currentMouse.y - this.anchor.y;
|
||||
this.currentDist = Math.sqrt(dx*dx + dy*dy);
|
||||
|
||||
if (this.currentDist > CONFIG.maxLength) {
|
||||
this.dead = true;
|
||||
}
|
||||
}
|
||||
|
||||
draw(ctx, currentMouse) {
|
||||
if (this.dead) return;
|
||||
|
||||
// Tension (0..1)
|
||||
const tension = Math.min(this.currentDist / CONFIG.maxLength, 1);
|
||||
const dynamicThickness = CONFIG.thickness * (1 - tension * 0.9);
|
||||
|
||||
// Draw main line (Cursor -> Anchor)
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(currentMouse.x, currentMouse.y);
|
||||
ctx.lineTo(this.anchor.x, this.anchor.y);
|
||||
|
||||
ctx.lineWidth = Math.max(0.2, dynamicThickness);
|
||||
ctx.strokeStyle = CONFIG.color;
|
||||
ctx.lineCap = "butt";
|
||||
ctx.stroke();
|
||||
|
||||
// Draw anchor point
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.anchor.x, this.anchor.y, 1.5 * (1 - tension), 0, Math.PI * 2);
|
||||
ctx.fillStyle = CONFIG.color;
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
// 1. Create new tentacles on movement
|
||||
const distMoved = Math.hypot(mouse.x - oldMouse.x, mouse.y - oldMouse.y);
|
||||
|
||||
if (distMoved > CONFIG.triggerDist) {
|
||||
const vx = mouse.x - oldMouse.x;
|
||||
const vy = mouse.y - oldMouse.y;
|
||||
|
||||
// "Spread" of shots increased slightly for better geometry
|
||||
const targetX = mouse.x + vx * CONFIG.prediction + (Math.random() - 0.5) * 60;
|
||||
const targetY = mouse.y + vy * CONFIG.prediction + (Math.random() - 0.5) * 60;
|
||||
|
||||
tentacles.push(new Tentacle(mouse.x, mouse.y, targetX, targetY));
|
||||
oldMouse.x = mouse.x;
|
||||
oldMouse.y = mouse.y;
|
||||
}
|
||||
|
||||
// Remove old ones (FIFO)
|
||||
if (tentacles.length > CONFIG.tentacleCount) {
|
||||
tentacles.shift();
|
||||
}
|
||||
|
||||
// 2. Draw main tentacles
|
||||
for (let i = tentacles.length - 1; i >= 0; i--) {
|
||||
const t = tentacles[i];
|
||||
t.update(mouse);
|
||||
if (t.dead) {
|
||||
tentacles.splice(i, 1);
|
||||
} else {
|
||||
t.draw(ctx, mouse);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. DRAW CONNECTIONS BETWEEN ANCHORS (New logic)
|
||||
// Iterate through all pairs of active tentacles
|
||||
ctx.beginPath(); // Begin common path for optimization
|
||||
ctx.lineWidth = 0.5; // Connections are always thin
|
||||
|
||||
for (let i = 0; i < tentacles.length; i++) {
|
||||
for (let j = i + 1; j < tentacles.length; j++) {
|
||||
const t1 = tentacles[i];
|
||||
const t2 = tentacles[j];
|
||||
|
||||
// Calculate distance between ends of two tentacles
|
||||
const dx = t1.anchor.x - t2.anchor.x;
|
||||
const dy = t1.anchor.y - t2.anchor.y;
|
||||
const dist = Math.sqrt(dx*dx + dy*dy);
|
||||
|
||||
// If they are close to each other — connect
|
||||
if (dist < CONFIG.connectionDist) {
|
||||
// Opacity depends on how far apart they are
|
||||
// And how much the tentacles themselves are stretched
|
||||
const alpha = (1 - dist / CONFIG.connectionDist) * 0.6;
|
||||
|
||||
ctx.beginPath(); // New path for each to control opacity
|
||||
ctx.strokeStyle = `rgba(20, 20, 20, ${alpha})`;
|
||||
ctx.moveTo(t1.anchor.x, t1.anchor.y);
|
||||
ctx.lineTo(t2.anchor.x, t2.anchor.y);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Cursor (Rhombus)
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = CONFIG.color;
|
||||
ctx.moveTo(mouse.x, mouse.y - 5);
|
||||
ctx.lineTo(mouse.x + 5, mouse.y);
|
||||
ctx.lineTo(mouse.x, mouse.y + 5);
|
||||
ctx.lineTo(mouse.x - 5, mouse.y);
|
||||
ctx.fill();
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
render();
|
||||
});
|
||||
@@ -1,75 +0,0 @@
|
||||
// leads.js
|
||||
|
||||
// ==========================================
|
||||
// 1. MENU TOGGLE
|
||||
// ==========================================
|
||||
const menuToggle = document.getElementById('menuToggle');
|
||||
const slideMenu = document.getElementById('slideMenu');
|
||||
const overlay = document.getElementById('overlay');
|
||||
|
||||
if (menuToggle && slideMenu && overlay) {
|
||||
function toggleMenu() {
|
||||
menuToggle.classList.toggle('active');
|
||||
slideMenu.classList.toggle('active');
|
||||
overlay.classList.toggle('active');
|
||||
}
|
||||
|
||||
menuToggle.addEventListener('click', toggleMenu);
|
||||
overlay.addEventListener('click', toggleMenu);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 2. LEADS TABLE LOGIC
|
||||
// ==========================================
|
||||
|
||||
function getLeads() {
|
||||
const storedLeads = localStorage.getItem('myLeads');
|
||||
if (storedLeads) {
|
||||
return JSON.parse(storedLeads);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function populateLeadsTable() {
|
||||
const tableBody = document.getElementById('leadsTableBody');
|
||||
const leadsData = getLeads();
|
||||
|
||||
if (!tableBody) return;
|
||||
|
||||
if (leadsData.length === 0) {
|
||||
tableBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="4" class="empty-state">
|
||||
<p>Keine Anfragen vorhanden</p>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
tableBody.innerHTML = leadsData.map(lead => `
|
||||
<tr>
|
||||
<td>${lead.datum}</td>
|
||||
<td>${lead.dienstleistung}</td>
|
||||
<td>
|
||||
<span class="status-badge ${lead.status}">${lead.statusText}</span>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="action-btn" data-id="${lead.id}">Details ansehen</a>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
|
||||
document.querySelectorAll('.action-btn').forEach(btn => {
|
||||
btn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const leadId = this.getAttribute('data-id');
|
||||
|
||||
// Redirect to lead details page
|
||||
window.location.href = `lead-details.html?id=${leadId}`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', populateLeadsTable);
|
||||
@@ -1,217 +0,0 @@
|
||||
// login.js
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const loginForm = document.getElementById('loginForm');
|
||||
const loginBtn = document.getElementById('loginSubmit');
|
||||
const successMessage = document.getElementById('successMessage');
|
||||
const errorMessage = document.getElementById('errorMessage');
|
||||
const errorText = document.getElementById('errorText');
|
||||
const registerBtn = document.getElementById('registerBtn');
|
||||
|
||||
// Register button functionality
|
||||
if (registerBtn) {
|
||||
registerBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = 'register.html';
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user is already logged in
|
||||
checkExistingSession();
|
||||
|
||||
// Login form submission
|
||||
if (loginForm) {
|
||||
loginForm.addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const email = document.getElementById('email').value;
|
||||
const password = document.getElementById('password').value;
|
||||
const remember = document.getElementById('remember').checked;
|
||||
|
||||
// Simple validation
|
||||
if (!email || !password) {
|
||||
showError('Bitte füllen Sie alle Felder aus.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Email validation
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(email)) {
|
||||
showError('Bitte geben Sie eine gültige E-Mail-Adresse ein.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
setLoadingState(true);
|
||||
hideMessages();
|
||||
|
||||
// Send login data to PHP API
|
||||
const loginData = {
|
||||
type: 'login',
|
||||
email: email,
|
||||
password: password,
|
||||
remember: remember
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('../scripts/add/send.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(loginData)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// Store session (for demo purposes - in real app, this would come from server)
|
||||
const sessionData = {
|
||||
user: { email: email },
|
||||
loginTime: new Date().toISOString(),
|
||||
remember: remember
|
||||
};
|
||||
|
||||
if (remember) {
|
||||
localStorage.setItem('userSession', JSON.stringify(sessionData));
|
||||
} else {
|
||||
sessionStorage.setItem('userSession', JSON.stringify(sessionData));
|
||||
}
|
||||
|
||||
// Show success message
|
||||
showSuccess('Anmeldung erfolgreich! Sie werden weitergeleitet...');
|
||||
|
||||
// Redirect after delay
|
||||
setTimeout(() => {
|
||||
window.location.href = '../index.html';
|
||||
}, 2000);
|
||||
} else {
|
||||
showError('Anmeldung fehlgeschlagen: ' + result.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
showError('Netzwerkfehler bei der Anmeldung. Bitte versuchen Sie es später erneut.');
|
||||
}
|
||||
|
||||
setLoadingState(false);
|
||||
});
|
||||
}
|
||||
|
||||
// Loading state management
|
||||
function setLoadingState(loading) {
|
||||
if (loginBtn) {
|
||||
const btnText = loginBtn.querySelector('.btn-text');
|
||||
const btnLoading = loginBtn.querySelector('.btn-loading');
|
||||
|
||||
if (loading) {
|
||||
loginBtn.disabled = true;
|
||||
if (btnText) btnText.style.display = 'none';
|
||||
if (btnLoading) btnLoading.style.display = 'inline-block';
|
||||
} else {
|
||||
loginBtn.disabled = false;
|
||||
if (btnText) btnText.style.display = 'inline-block';
|
||||
if (btnLoading) btnLoading.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Message display functions
|
||||
function showSuccess(message) {
|
||||
if (successMessage) {
|
||||
const messageElement = successMessage.querySelector('p');
|
||||
if (messageElement) {
|
||||
messageElement.textContent = message;
|
||||
}
|
||||
successMessage.classList.add('show');
|
||||
}
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
if (errorMessage && errorText) {
|
||||
errorText.textContent = message;
|
||||
errorMessage.classList.add('show');
|
||||
|
||||
// Hide after 5 seconds
|
||||
setTimeout(() => {
|
||||
errorMessage.classList.remove('show');
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
function hideMessages() {
|
||||
if (successMessage) successMessage.classList.remove('show');
|
||||
if (errorMessage) errorMessage.classList.remove('show');
|
||||
}
|
||||
});
|
||||
|
||||
// Check existing session - DISABLED auto-redirect
|
||||
function checkExistingSession() {
|
||||
const sessionData = localStorage.getItem('userSession') || sessionStorage.getItem('userSession');
|
||||
|
||||
if (sessionData) {
|
||||
try {
|
||||
const session = JSON.parse(sessionData);
|
||||
const loginTime = new Date(session.loginTime);
|
||||
const now = new Date();
|
||||
const sessionAge = (now - loginTime) / (1000 * 60 * 60); // hours
|
||||
|
||||
// Auto-logout after 24 hours
|
||||
if (sessionAge < 24) {
|
||||
// User is still logged in - just log it, don't redirect
|
||||
console.log('User already logged in');
|
||||
// DISABLED: window.location.href = '../index.html';
|
||||
} else {
|
||||
// Session expired, remove it
|
||||
console.log('Session expired, removing...');
|
||||
localStorage.removeItem('userSession');
|
||||
sessionStorage.removeItem('userSession');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Session parsing error:', error);
|
||||
localStorage.removeItem('userSession');
|
||||
sessionStorage.removeItem('userSession');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Logout function (can be called from other pages)
|
||||
function logout() {
|
||||
localStorage.removeItem('userSession');
|
||||
sessionStorage.removeItem('userSession');
|
||||
window.location.href = 'sites/login.html';
|
||||
}
|
||||
|
||||
// Get current user (can be called from other pages)
|
||||
function getCurrentUser() {
|
||||
const sessionData = localStorage.getItem('userSession') || sessionStorage.getItem('userSession');
|
||||
|
||||
if (sessionData) {
|
||||
try {
|
||||
const session = JSON.parse(sessionData);
|
||||
const loginTime = new Date(session.loginTime);
|
||||
const now = new Date();
|
||||
const sessionAge = (now - loginTime) / (1000 * 60 * 60); // hours
|
||||
|
||||
if (sessionAge < 24) {
|
||||
return session.user;
|
||||
} else {
|
||||
// Session expired
|
||||
localStorage.removeItem('userSession');
|
||||
sessionStorage.removeItem('userSession');
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Session parsing error:', error);
|
||||
localStorage.removeItem('userSession');
|
||||
sessionStorage.removeItem('userSession');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if user is logged in (can be called from other pages)
|
||||
function isLoggedIn() {
|
||||
return getCurrentUser() !== null;
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
// register.js
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const registerForm = document.getElementById('registerForm');
|
||||
const registerBtn = document.getElementById('registerSubmit');
|
||||
const successMessage = document.getElementById('successMessage');
|
||||
const errorMessage = document.getElementById('errorMessage');
|
||||
const errorText = document.getElementById('errorText');
|
||||
const passwordInput = document.getElementById('password');
|
||||
const confirmPasswordInput = document.getElementById('confirmPassword');
|
||||
const passwordStrength = document.getElementById('passwordStrength');
|
||||
|
||||
// Check if user is already logged in
|
||||
checkExistingSession();
|
||||
|
||||
// Password strength checker
|
||||
if (passwordInput && passwordStrength) {
|
||||
passwordInput.addEventListener('input', function() {
|
||||
const password = this.value;
|
||||
const strength = checkPasswordStrength(password);
|
||||
updatePasswordStrength(strength);
|
||||
});
|
||||
}
|
||||
|
||||
// Password confirmation checker
|
||||
if (confirmPasswordInput && passwordInput) {
|
||||
confirmPasswordInput.addEventListener('input', function() {
|
||||
const password = passwordInput.value;
|
||||
const confirmPassword = this.value;
|
||||
|
||||
if (confirmPassword && password !== confirmPassword) {
|
||||
this.setCustomValidity('Passwörter stimmen nicht überein');
|
||||
} else {
|
||||
this.setCustomValidity('');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Registration form submission
|
||||
if (registerForm) {
|
||||
registerForm.addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Get form data
|
||||
const formData = {
|
||||
type: 'register',
|
||||
name: `${document.getElementById('firstName').value} ${document.getElementById('lastName').value}`,
|
||||
email: document.getElementById('email').value,
|
||||
phone: document.getElementById('phone').value,
|
||||
company: document.getElementById('company').value,
|
||||
password: passwordInput.value,
|
||||
confirmPassword: confirmPasswordInput.value,
|
||||
terms: document.getElementById('terms').checked,
|
||||
newsletter: document.getElementById('newsletter').checked,
|
||||
registrationTime: new Date().toISOString()
|
||||
};
|
||||
|
||||
// Validation
|
||||
const validation = validateRegistrationForm(formData);
|
||||
if (!validation.valid) {
|
||||
showError(validation.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
setLoadingState(true);
|
||||
hideMessages();
|
||||
|
||||
// Send registration data to PHP API
|
||||
try {
|
||||
const response = await fetch('../scripts/add/send.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(formData)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// Store user data (for demo purposes)
|
||||
const userData = {
|
||||
firstName: document.getElementById('firstName').value,
|
||||
lastName: document.getElementById('lastName').value,
|
||||
email: formData.email,
|
||||
phone: formData.phone,
|
||||
company: formData.company,
|
||||
registrationTime: formData.registrationTime,
|
||||
newsletter: formData.newsletter
|
||||
};
|
||||
|
||||
// Store in localStorage (for demo purposes)
|
||||
localStorage.setItem('userData', JSON.stringify(userData));
|
||||
localStorage.setItem('userRegistered', 'true');
|
||||
|
||||
// Show success message
|
||||
showSuccess('Registrierung erfolgreich! Sie werden weitergeleitet...');
|
||||
|
||||
// Redirect after delay
|
||||
setTimeout(() => {
|
||||
window.location.href = '../index.html';
|
||||
}, 2000);
|
||||
} else {
|
||||
showError('Registrierung fehlgeschlagen: ' + result.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Registration error:', error);
|
||||
showError('Netzwerkfehler bei der Registrierung. Bitte versuchen Sie es später erneut.');
|
||||
}
|
||||
|
||||
setLoadingState(false);
|
||||
});
|
||||
}
|
||||
|
||||
// Password strength checker function
|
||||
function checkPasswordStrength(password) {
|
||||
let strength = 0;
|
||||
|
||||
// Length check
|
||||
if (password.length >= 8) strength++;
|
||||
if (password.length >= 12) strength++;
|
||||
|
||||
// Character variety checks
|
||||
if (/[a-z]/.test(password)) strength++; // lowercase
|
||||
if (/[A-Z]/.test(password)) strength++; // uppercase
|
||||
if (/[0-9]/.test(password)) strength++; // numbers
|
||||
if (/[^a-zA-Z0-9]/.test(password)) strength++; // special characters
|
||||
|
||||
return strength;
|
||||
}
|
||||
|
||||
// Update password strength indicator
|
||||
function updatePasswordStrength(strength) {
|
||||
const strengthBar = passwordStrength.querySelector('.strength-bar');
|
||||
const strengthText = passwordStrength.querySelector('.strength-text');
|
||||
|
||||
// Remove all strength classes
|
||||
passwordStrength.classList.remove('strength-weak', 'strength-medium', 'strength-strong');
|
||||
|
||||
if (strength <= 2) {
|
||||
passwordStrength.classList.add('strength-weak');
|
||||
strengthText.textContent = 'Schwach';
|
||||
} else if (strength <= 4) {
|
||||
passwordStrength.classList.add('strength-medium');
|
||||
strengthText.textContent = 'Mittel';
|
||||
} else {
|
||||
passwordStrength.classList.add('strength-strong');
|
||||
strengthText.textContent = 'Stark';
|
||||
}
|
||||
}
|
||||
|
||||
// Form validation
|
||||
function validateRegistrationForm(data) {
|
||||
// Required fields check
|
||||
if (!data.firstName || !data.lastName || !data.email || !data.password) {
|
||||
return { valid: false, message: 'Bitte füllen Sie alle Pflichtfelder aus.' };
|
||||
}
|
||||
|
||||
// Name validation
|
||||
if (data.firstName.length < 2 || data.lastName.length < 2) {
|
||||
return { valid: false, message: 'Vorname und Nachname müssen mindestens 2 Zeichen lang sein.' };
|
||||
}
|
||||
|
||||
// Email validation
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(data.email)) {
|
||||
return { valid: false, message: 'Bitte geben Sie eine gültige E-Mail-Adresse ein.' };
|
||||
}
|
||||
|
||||
// Password validation
|
||||
if (data.password.length < 8) {
|
||||
return { valid: false, message: 'Das Passwort muss mindestens 8 Zeichen lang sein.' };
|
||||
}
|
||||
|
||||
// Password confirmation
|
||||
if (data.password !== data.confirmPassword) {
|
||||
return { valid: false, message: 'Die Passwörter stimmen nicht überein.' };
|
||||
}
|
||||
|
||||
// Terms acceptance
|
||||
if (!data.terms) {
|
||||
return { valid: false, message: 'Sie müssen die Nutzungsbedingungen akzeptieren.' };
|
||||
}
|
||||
|
||||
// Phone validation (if provided)
|
||||
if (data.phone) {
|
||||
const phoneRegex = /^[\d\s\-\+\(\)]+$/;
|
||||
if (!phoneRegex.test(data.phone)) {
|
||||
return { valid: false, message: 'Bitte geben Sie eine gültige Telefonnummer ein.' };
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: true, message: 'Validierung erfolgreich' };
|
||||
}
|
||||
|
||||
// Loading state management
|
||||
function setLoadingState(loading) {
|
||||
if (registerBtn) {
|
||||
const btnText = registerBtn.querySelector('.btn-text');
|
||||
const btnLoading = registerBtn.querySelector('.btn-loading');
|
||||
|
||||
if (loading) {
|
||||
registerBtn.disabled = true;
|
||||
if (btnText) btnText.style.display = 'none';
|
||||
if (btnLoading) btnLoading.style.display = 'inline-block';
|
||||
} else {
|
||||
registerBtn.disabled = false;
|
||||
if (btnText) btnText.style.display = 'inline-block';
|
||||
if (btnLoading) btnLoading.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Message display functions
|
||||
function showSuccess(message) {
|
||||
if (successMessage) {
|
||||
const messageElement = successMessage.querySelector('p');
|
||||
if (messageElement) {
|
||||
messageElement.textContent = message;
|
||||
}
|
||||
successMessage.classList.add('show');
|
||||
}
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
if (errorMessage && errorText) {
|
||||
errorText.textContent = message;
|
||||
errorMessage.classList.add('show');
|
||||
|
||||
// Hide after 5 seconds
|
||||
setTimeout(() => {
|
||||
errorMessage.classList.remove('show');
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
function hideMessages() {
|
||||
if (successMessage) successMessage.classList.remove('show');
|
||||
if (errorMessage) errorMessage.classList.remove('show');
|
||||
}
|
||||
});
|
||||
|
||||
// Check existing session (same as login.js) - DISABLED auto-redirect
|
||||
function checkExistingSession() {
|
||||
const sessionData = localStorage.getItem('userSession') || sessionStorage.getItem('userSession');
|
||||
|
||||
if (sessionData) {
|
||||
try {
|
||||
const session = JSON.parse(sessionData);
|
||||
const loginTime = new Date(session.loginTime);
|
||||
const now = new Date();
|
||||
const sessionAge = (now - loginTime) / (1000 * 60 * 60); // hours
|
||||
|
||||
// Auto-logout after 24 hours
|
||||
if (sessionAge < 24) {
|
||||
// User is still logged in - just log it, don't redirect
|
||||
console.log('User already logged in');
|
||||
// DISABLED: window.location.href = '../index.html';
|
||||
} else {
|
||||
// Session expired, remove it
|
||||
console.log('Session expired, removing...');
|
||||
localStorage.removeItem('userSession');
|
||||
sessionStorage.removeItem('userSession');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Session parsing error:', error);
|
||||
localStorage.removeItem('userSession');
|
||||
sessionStorage.removeItem('userSession');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/**
|
||||
* Main Script - Profice Website
|
||||
* All API calls go through server-side PHP
|
||||
* Includes fallback for local file access (no server)
|
||||
*
|
||||
* @version 2.1.0
|
||||
*/
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
|
||||
const API_ENDPOINT = 'scripts/add/send.php';
|
||||
const isLocalFile = window.location.protocol === 'file:';
|
||||
|
||||
// ==========================================
|
||||
// 1. SMOOTH SCROLLING
|
||||
// ==========================================
|
||||
|
||||
function initSmoothScrolling() {
|
||||
document.querySelectorAll('a[href^="#"]').forEach(link => {
|
||||
link.addEventListener('click', function(e) {
|
||||
const targetId = this.getAttribute('href');
|
||||
if (targetId === '#') return;
|
||||
|
||||
const targetElement = document.querySelector(targetId);
|
||||
if (targetElement) {
|
||||
e.preventDefault();
|
||||
const header = document.querySelector('.top-banner');
|
||||
const headerHeight = header ? header.offsetHeight : 90;
|
||||
|
||||
window.scrollTo({
|
||||
top: targetElement.offsetTop - headerHeight - 20,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
|
||||
history.pushState(null, null, targetId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initSmoothScrolling();
|
||||
|
||||
// ==========================================
|
||||
// 2. MENU TOGGLE
|
||||
// ==========================================
|
||||
|
||||
const menuToggle = document.getElementById('menuToggle');
|
||||
const slideMenu = document.getElementById('slideMenu');
|
||||
const overlay = document.getElementById('overlay');
|
||||
|
||||
if (menuToggle && slideMenu && overlay) {
|
||||
const toggleMenu = () => {
|
||||
menuToggle.classList.toggle('active');
|
||||
slideMenu.classList.toggle('active');
|
||||
overlay.classList.toggle('active');
|
||||
};
|
||||
menuToggle.addEventListener('click', toggleMenu);
|
||||
overlay.addEventListener('click', toggleMenu);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 3. LOGIN BUTTON
|
||||
// ==========================================
|
||||
|
||||
const loginBtn = document.getElementById('loginBtn');
|
||||
if (loginBtn) {
|
||||
const currentPath = window.location.pathname;
|
||||
let loginPath = 'sites/login.html';
|
||||
|
||||
if (currentPath.includes('/sites/')) {
|
||||
loginPath = currentPath.includes('login.html') ? 'register.html' : 'login.html';
|
||||
}
|
||||
|
||||
loginBtn.onclick = (e) => {
|
||||
e.preventDefault();
|
||||
window.location.href = loginPath;
|
||||
};
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 4. FORM SUBMISSION
|
||||
// ==========================================
|
||||
|
||||
const contactForm = document.getElementById('contactForm');
|
||||
const successMessage = document.getElementById('successMessage');
|
||||
|
||||
if (contactForm) {
|
||||
contactForm.addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const getValue = (id) => {
|
||||
const el = document.getElementById(id);
|
||||
return el ? el.value : '';
|
||||
};
|
||||
|
||||
const serviceSelect = document.getElementById('service');
|
||||
const selectedServiceText = serviceSelect ?
|
||||
serviceSelect.options[serviceSelect.selectedIndex].text : 'Dienstleistung';
|
||||
|
||||
const formData = {
|
||||
type: 'contact',
|
||||
name: getValue('name'),
|
||||
organisation: getValue('organisation'),
|
||||
contact: getValue('contact'),
|
||||
service: getValue('service'),
|
||||
budget: getValue('budget'),
|
||||
description: getValue('description')
|
||||
};
|
||||
|
||||
// Always store locally for dashboard
|
||||
try {
|
||||
const localLead = {
|
||||
id: Date.now(),
|
||||
datum: new Date().toLocaleDateString('de-DE'),
|
||||
dienstleistung: selectedServiceText,
|
||||
status: 'open',
|
||||
statusText: 'Offen',
|
||||
description: formData.description
|
||||
};
|
||||
const existingLeads = JSON.parse(localStorage.getItem('myLeads') || '[]');
|
||||
existingLeads.unshift(localLead);
|
||||
localStorage.setItem('myLeads', JSON.stringify(existingLeads.slice(0, 100)));
|
||||
} catch (err) {}
|
||||
|
||||
// Send to API if not local file
|
||||
if (!isLocalFile) {
|
||||
try {
|
||||
const response = await fetch(API_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(formData)
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (!result.success) {
|
||||
alert('Fehler beim Senden: ' + (result.message || 'Unbekannter Fehler'));
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
alert('Netzwerkfehler beim Senden des Formulars');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Show success
|
||||
contactForm.style.display = 'none';
|
||||
if (successMessage) successMessage.classList.add('show');
|
||||
contactForm.reset();
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,83 +0,0 @@
|
||||
// scroll-header.js
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const topBanner = document.querySelector('.top-banner');
|
||||
const slideMenu = document.querySelector('.slide-menu');
|
||||
|
||||
if (!topBanner) return;
|
||||
|
||||
// Scroll threshold to trigger the shrink effect
|
||||
const scrollThreshold = 50;
|
||||
let isScrolled = false;
|
||||
let isTransitioning = false;
|
||||
let lastScrollY = 0;
|
||||
let scrollDirection = 'down';
|
||||
|
||||
function updateHeaderState(scrolled) {
|
||||
if (isTransitioning) return;
|
||||
|
||||
if (scrolled && !isScrolled) {
|
||||
isTransitioning = true;
|
||||
topBanner.classList.add('scrolled');
|
||||
isScrolled = true;
|
||||
|
||||
if (slideMenu) {
|
||||
slideMenu.style.top = '80px';
|
||||
}
|
||||
|
||||
// Reset transition flag after animation completes
|
||||
setTimeout(() => {
|
||||
isTransitioning = false;
|
||||
}, 250);
|
||||
|
||||
} else if (!scrolled && isScrolled) {
|
||||
isTransitioning = true;
|
||||
topBanner.classList.remove('scrolled');
|
||||
isScrolled = false;
|
||||
|
||||
if (slideMenu) {
|
||||
slideMenu.style.top = '110px';
|
||||
}
|
||||
|
||||
// Reset transition flag after animation completes
|
||||
setTimeout(() => {
|
||||
isTransitioning = false;
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
|
||||
function handleScroll() {
|
||||
const currentScrollY = window.pageYOffset || document.documentElement.scrollTop;
|
||||
|
||||
// Detect scroll direction
|
||||
if (currentScrollY > lastScrollY) {
|
||||
scrollDirection = 'down';
|
||||
} else if (currentScrollY < lastScrollY) {
|
||||
scrollDirection = 'up';
|
||||
}
|
||||
|
||||
// Only update when crossing threshold in the right direction
|
||||
if (scrollDirection === 'down' && currentScrollY > scrollThreshold && !isScrolled) {
|
||||
updateHeaderState(true);
|
||||
} else if (scrollDirection === 'up' && currentScrollY <= scrollThreshold && isScrolled) {
|
||||
updateHeaderState(false);
|
||||
}
|
||||
|
||||
lastScrollY = currentScrollY;
|
||||
}
|
||||
|
||||
// Use requestAnimationFrame for smooth scroll handling
|
||||
let ticking = false;
|
||||
function requestTick() {
|
||||
if (!ticking) {
|
||||
requestAnimationFrame(handleScroll);
|
||||
ticking = true;
|
||||
setTimeout(() => { ticking = false; }, 16); // ~60fps
|
||||
}
|
||||
}
|
||||
|
||||
// Optimized scroll event listener
|
||||
window.addEventListener('scroll', requestTick, { passive: true, capture: false });
|
||||
|
||||
// Initial check
|
||||
handleScroll();
|
||||
});
|
||||
@@ -1,213 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profice - Automatisierung</title>
|
||||
<link rel="stylesheet" href="../style/design.css">
|
||||
<link rel="stylesheet" href="../style/service.css">
|
||||
<link rel="stylesheet" href="../style/cursor.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Top Banner -->
|
||||
<header class="top-banner dark-theme">
|
||||
<div class="top-banner-left">
|
||||
<div class="banner-left">
|
||||
<button class="menu-toggle" id="menuToggle" aria-label="Menu">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<a href="../index.html" class="logo-link">
|
||||
<img src="../images/logo/logo-01-complete.png" alt="Profice Logo" class="logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-center">
|
||||
<nav class="main-nav">
|
||||
<a href="../index.html#hero-section" class="nav-link">Home</a>
|
||||
<a href="../index.html#enterprise" class="nav-link">Enterprise</a>
|
||||
<a href="../index.html#pricing" class="nav-link">Pricing</a>
|
||||
<a href="../index.html#services" class="nav-link">Lösungen</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="top-banner-right">
|
||||
<button id="cursorToggle" aria-label="Toggle Cursor" title="Toggle Custom Cursor">
|
||||
<img src="../images/additional/cursor.png" alt="Default Cursor" class="cursor-icon">
|
||||
</button>
|
||||
<button id="loginBtn" class="login-btn" aria-label="Log in" title="Log in">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
||||
<polyline points="10 17 15 12 10 7"></polyline>
|
||||
<line x1="15" y1="12" x2="3" y2="12"></line>
|
||||
</svg>
|
||||
Log in
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Slide Menu -->
|
||||
<nav class="slide-menu" id="slideMenu">
|
||||
<a href="../index.html">Startseite</a>
|
||||
<a href="offers.html" class="active">Kontakt & Anfrage</a>
|
||||
<a href="leads.html">Leads Dashboard</a>
|
||||
</nav>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay" id="overlay"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<div class="service-container">
|
||||
<!-- Service Header -->
|
||||
<div class="service-header">
|
||||
<div class="service-icon">⚙️</div>
|
||||
<h1 class="service-title">Automatisierung</h1>
|
||||
<p class="service-subtitle">Sparen Sie Zeit und Ressourcen durch intelligente Workflow-Automatisierungen</p>
|
||||
</div>
|
||||
|
||||
<!-- Service Description -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Unsere Automatisierungslösungen</h2>
|
||||
<p class="section-text">
|
||||
Wir automatisieren Ihre Geschäftsprozesse, um Effizienz zu steigern und menschliche Fehler zu reduzieren.
|
||||
Von einfachen wiederkehrenden Aufgaben bis zu komplexen Workflow-Integrationen - wir finden die optimale Lösung.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Service Features -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Was wir automatisieren können</h2>
|
||||
<div class="features-grid">
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📧</div>
|
||||
<h3>E-Mail-Automatisierung</h3>
|
||||
<p>Automatische Antwortverwaltung und E-Mail-Kampagnen</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📄</div>
|
||||
<h3>Datenverarbeitung</h3>
|
||||
<p>Automatische Datenmigration und -bereinigung</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📋</div>
|
||||
<h3>Report-Generierung</h3>
|
||||
<p>Automatische Erstellung von Berichten und Analysen</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🔄</div>
|
||||
<h3>Workflow-Integration</h3>
|
||||
<p>Verbindung verschiedener Systeme für nahtlose Prozesse</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📊</div>
|
||||
<h3>Monitoring</h3>
|
||||
<p>Automatische Systemüberwachung und Alarmierung</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🎯</div>
|
||||
<h3>Task-Management</h3>
|
||||
<p>Intelligente Aufgabenverteilung und -verfolgung</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Unser Automatisierungsprozess</h2>
|
||||
<div class="process-timeline">
|
||||
<div class="process-item">
|
||||
<div class="process-number">1</div>
|
||||
<div class="process-content">
|
||||
<h3>Prozessanalyse</h3>
|
||||
<p>Identifizierung von Automatisierungspotenzialen</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">2</div>
|
||||
<div class="process-content">
|
||||
<h3>Lösungsdesign</h3>
|
||||
<p>Entwicklung maßgeschneiderter Automatisierungslösungen</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">3</div>
|
||||
<div class="process-content">
|
||||
<h3>Implementierung</h3>
|
||||
<p>Setup und Konfiguration der Automatisierungstools</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">4</div>
|
||||
<div class="process-content">
|
||||
<h3>Testing</h3>
|
||||
<p>Gewissenhafte Tests vor der Live-Schaltung</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">5</div>
|
||||
<div class="process-content">
|
||||
<h3>Monitoring</h3>
|
||||
<p>Laufende Überwachung und Optimierung</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Technologies -->
|
||||
<section class="section">
|
||||
<h2 class="section-title">Automatisierungstechnologien</h2>
|
||||
<div class="tech-grid">
|
||||
<div class="tech-item">Zapier</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Benefits -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Ihre Vorteile</h2>
|
||||
<div class="benefits-grid">
|
||||
<div class="benefit-item">
|
||||
<div class="benefit-icon">⏰️</div>
|
||||
<h3>Zeitersparnis</h3>
|
||||
<p>Bis zu 80% Zeitersparnis bei wiederkehrenden Aufgaben</p>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<div class="benefit-icon">🎯</div>
|
||||
<h3>Qualitätssteigerung</h3>
|
||||
<p>Reduzierung menschlicher Fehler und konsistente Ergebnisse</p>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<div class="benefit-icon">💰</div>
|
||||
<h3>Kostensenkung</h3>
|
||||
<p>Optimierung von Ressourcen und Betriebskosten</p>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<div class="benefit-icon">📈</div>
|
||||
<h3>Skalierbarkeit</div>
|
||||
<p>Einfache Handhabung wachsender Geschäftsanforderungen</p>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<div class="benefit-icon">😊</div>
|
||||
<h3>Mitarbeiterzufriedenheit</h3>
|
||||
<p>Fokus auf kreative und strategische Aufgaben</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Bereit für mehr Effizienz?</h2>
|
||||
<p class="section-text">Lassen Sie uns Ihre Prozesse analysieren und Potenziale identifizieren.</p>
|
||||
<div class="cta-buttons">
|
||||
<a href="offers.html?service=automatisation" class="cta-btn primary">Automatisierungs-Analyse</a>
|
||||
<a href="offers.html" class="cta-btn secondary">Mehr erfahren</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="../scripts/script.js"></script>
|
||||
<script src="../scripts/cursor.js"></script>
|
||||
<script src="../scripts/scroll-header.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,217 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profice - KI Integration</title>
|
||||
<link rel="stylesheet" href="../style/design.css">
|
||||
<link rel="stylesheet" href="../style/service.css">
|
||||
<link rel="stylesheet" href="../style/cursor.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Top Banner -->
|
||||
<header class="top-banner dark-theme">
|
||||
<div class="top-banner-left">
|
||||
<div class="banner-left">
|
||||
<button class="menu-toggle" id="menuToggle" aria-label="Menu">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<a href="../index.html" class="logo-link">
|
||||
<img src="../images/logo/logo-01-complete.png" alt="Profice Logo" class="logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-center">
|
||||
<nav class="main-nav">
|
||||
<a href="../index.html#hero-section" class="nav-link">Home</a>
|
||||
<a href="../index.html#enterprise" class="nav-link">Enterprise</a>
|
||||
<a href="../index.html#pricing" class="nav-link">Pricing</a>
|
||||
<a href="../index.html#services" class="nav-link">Lösungen</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="top-banner-right">
|
||||
<button id="cursorToggle" aria-label="Toggle Cursor" title="Toggle Custom Cursor">
|
||||
<img src="../images/additional/cursor.png" alt="Default Cursor" class="cursor-icon">
|
||||
</button>
|
||||
<button id="loginBtn" class="login-btn" aria-label="Log in" title="Log in">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
||||
<polyline points="10 17 15 12 10 7"></polyline>
|
||||
<line x1="15" y1="12" x2="3" y2="12"></line>
|
||||
</svg>
|
||||
Log in
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Slide Menu -->
|
||||
<nav class="slide-menu" id="slideMenu">
|
||||
<a href="../index.html">Startseite</a>
|
||||
<a href="offers.html" class="active">Kontakt & Anfrage</a>
|
||||
<a href="leads.html">Leads Dashboard</a>
|
||||
</nav>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay" id="overlay"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<div class="service-container">
|
||||
<!-- Service Header -->
|
||||
<div class="service-header">
|
||||
<div class="service-icon">🤖</div>
|
||||
<h1 class="service-title">KI Integration</h1>
|
||||
<p class="service-subtitle">Nutzen Sie die Kraft künstlicher Intelligenz, um Ihre Daten besser zu verstehen und Prozesse zu optimieren</p>
|
||||
</div>
|
||||
|
||||
<!-- Service Description -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Unsere KI-Dienstleistungen</h2>
|
||||
<p class="section-text">
|
||||
Wir integrieren künstliche Intelligenz in Ihre Geschäftsprozesse, um Effizienz zu steigern und neue Möglichkeiten zu erschließen.
|
||||
Von der Datenanalyse über automatisierte Prozesse bis zu intelligenten Chatbots - wir machen KI für Sie nutzbar.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Service Features -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Was wir bieten</h2>
|
||||
<div class="features-grid">
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📊</div>
|
||||
<h3>Datenanalyse</h3>
|
||||
<p>Intelligente Auswertung Ihrer Geschäftsdaten für bessere Entscheidungen</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🤖</div>
|
||||
<h3>Chatbots</h3>
|
||||
<p>24/7 Kundenbetreuung und automatisierte Kommunikation</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">⚙️</div>
|
||||
<h3>Prozessautomatisierung</h3>
|
||||
<p>Automatisierung wiederkehrender Aufgaben zur Effizienzsteigerung</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🔍</div>
|
||||
<h3>Bilderkennung</h3>
|
||||
<p>Automatische Analyse von Bildern und Dokumenten</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📈</div>
|
||||
<h3>Vorhersagemodelle</h3>
|
||||
<p>Prognosen für Trends und Geschäftsentwicklungen</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🎯</div>
|
||||
<h3>Personalisierung</h3>
|
||||
<p>Individuelle KI-Lösungen für Ihre spezifischen Bedürfnisse</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Unser KI-Integrationsprozess</h2>
|
||||
<div class="process-timeline">
|
||||
<div class="process-item">
|
||||
<div class="process-number">1</div>
|
||||
<div class="process-content">
|
||||
<h3>Analyse & Potenzial</h3>
|
||||
<p>Identifizierung von KI-Einsatzmöglichkeiten in Ihrem Unternehmen</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">2</div>
|
||||
<div class="process-content">
|
||||
<h3>Datenstrategie</h3>
|
||||
<p>Planung der Datenerfassung und -verarbeitung</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">3</div>
|
||||
<div class="process-content">
|
||||
<h3>Modellentwicklung</h3>
|
||||
<p>Training oder Auswahl passender KI-Modelle</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">4</div>
|
||||
<div class="process-content">
|
||||
<h3>Integration</h3>
|
||||
<p>Nahtlose Anbindung an Ihre bestehenden Systeme</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">5</div>
|
||||
<div class="process-content">
|
||||
<h3>Optimierung</h3>
|
||||
<p>Kontinuierliche Verbesserung der KI-Modelle</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Technologies -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">KI-Technologien</h2>
|
||||
<div class="tech-grid">
|
||||
<div class="tech-item">TensorFlow</div>
|
||||
<div class="tech-item">PyTorch</div>
|
||||
<div class="tech-item">Scikit-learn</div>
|
||||
<div class="tech-item">OpenAI API</div>
|
||||
<div class="tech-item">Google Cloud AI</div>
|
||||
<div class="tech-item">Azure ML</div>
|
||||
<div class="tech-item">AWS SageMaker</div>
|
||||
<div class="tech-item">Hugging Face</div>
|
||||
<div class="tech-item">LangChain</div>
|
||||
<div class="tech-item">Dialogflow</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Use Cases -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Anwendungsfälle</h2>
|
||||
<div class="use-cases-grid">
|
||||
<div class="use-case-item">
|
||||
<h3>Kundenservice</h3>
|
||||
<p>Intelligente Chatbots für 24/7 Unterstützung</p>
|
||||
</div>
|
||||
<div class="use-case-item">
|
||||
<h3>Vertrieb</h3>
|
||||
<p>Predictive Lead Scoring und Verkaufsoptimierung</p>
|
||||
</div>
|
||||
<div class="use-case-item">
|
||||
<h3>Marketing</h3>
|
||||
<p>Personalisierte Kampagnen und Content-Optimierung</p>
|
||||
</div>
|
||||
<div class="use-case-item">
|
||||
<h3>Finanzen</h3>
|
||||
<p>Betrugsprüfung und Risikoanalyse</p>
|
||||
</div>
|
||||
<div class="use-case-item">
|
||||
<h3>Produktion</h3>
|
||||
<p>Qualitätssicherung und Predictive Maintenance</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Bereit für KI in Ihrem Unternehmen?</h2>
|
||||
<p class="section-text">Lassen Sie uns die Potenziale für Ihr Unternehmen analysieren.</p>
|
||||
<div class="cta-buttons">
|
||||
<a href="offers.html?service=ki-integration" class="cta-btn primary">KI-Analyse anfordern</a>
|
||||
<a href="offers.html" class="cta-btn secondary">Mehr erfahren</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="../scripts/script.js"></script>
|
||||
<script src="../scripts/cursor.js"></script>
|
||||
<script src="../scripts/scroll-header.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,117 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profice - Leads Dashboard</title>
|
||||
<link rel="stylesheet" href="../style/design.css">
|
||||
<link rel="stylesheet" href="../style/leads.css">
|
||||
<link rel="stylesheet" href="../style/cursor.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Top Banner -->
|
||||
<header class="top-banner dark-theme">
|
||||
<div class="top-banner-left">
|
||||
<div class="banner-left">
|
||||
<button class="menu-toggle" id="menuToggle" aria-label="Menü">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<a href="../index.html" class="logo-link">
|
||||
<img src="../images/logo/logo-01-complete.png" alt="Profice Logo" class="logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-center">
|
||||
<nav class="main-nav">
|
||||
<a href="../index.html#hero-section" class="nav-link">Startseite</a>
|
||||
<a href="../index.html#enterprise" class="nav-link">Unternehmen</a>
|
||||
<a href="../index.html#pricing" class="nav-link">Preise</a>
|
||||
<a href="../index.html#services" class="nav-link">Lösungen</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="top-banner-right">
|
||||
<button id="cursorToggle" aria-label="Cursor umschalten" title="Benutzerdefinierten Cursor umschalten">
|
||||
<img src="../images/additional/cursor.png" alt="Standard Cursor" class="cursor-icon">
|
||||
</button>
|
||||
<button id="loginBtn" class="login-btn" aria-label="Anmelden" title="Anmelden">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
||||
<polyline points="10 17 15 12 10 7"></polyline>
|
||||
<line x1="15" y1="12" x2="3" y2="12"></line>
|
||||
</svg>
|
||||
Anmelden
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Slide Menu -->
|
||||
<nav class="slide-menu" id="slideMenu">
|
||||
<a href="../index.html">Startseite</a>
|
||||
<a href="offers.html">Kontakt & Anfrage</a>
|
||||
<a href="leads.html" class="active">Leads Dashboard</a>
|
||||
</nav>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay" id="overlay"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content leads-content">
|
||||
<!-- Leads Widget -->
|
||||
<div class="dashboard-container">
|
||||
<h2 class="dashboard-title">Meine Anfragen</h2>
|
||||
<p class="dashboard-subtitle">Übersicht Ihrer aktuellen Projektanfragen</p>
|
||||
|
||||
<div class="leads-table-wrapper">
|
||||
<table class="leads-table" id="leadsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Dienstleistung</th>
|
||||
<th>Status</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="leadsTableBody">
|
||||
<!-- Populated by leads.js -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Other Offers Section -->
|
||||
<div class="dashboard-container offers-section">
|
||||
<h2 class="dashboard-title">Andere Angebote von uns</h2>
|
||||
<p class="dashboard-subtitle">Entdecken Sie weitere Dienstleistungen</p>
|
||||
|
||||
<div class="offers-grid">
|
||||
<div class="offer-card">
|
||||
<div class="offer-icon">🔍</div>
|
||||
<h3 class="offer-title">SEO Optimierung</h3>
|
||||
<p class="offer-description">Verbessern Sie Ihre Sichtbarkeit in Suchmaschinen und erreichen Sie mehr Kunden online.</p>
|
||||
<a href="details.html?service=seo-optimierung" class="offer-btn">Details ansehen</a>
|
||||
</div>
|
||||
|
||||
<div class="offer-card">
|
||||
<div class="offer-icon">☁️</div>
|
||||
<h3 class="offer-title">Cloud Migration</h3>
|
||||
<p class="offer-description">Modernisieren Sie Ihre IT-Infrastruktur mit sicheren und skalierbaren Cloud-Lösungen.</p>
|
||||
<a href="details.html?service=cloud-migration" class="offer-btn">Details ansehen</a>
|
||||
</div>
|
||||
|
||||
<div class="offer-card">
|
||||
<div class="offer-icon">📊</div>
|
||||
<h3 class="offer-title">Datenanalyse</h3>
|
||||
<p class="offer-description">Gewinnen Sie wertvolle Einblicke aus Ihren Daten mit unseren Analyse-Lösungen.</p>
|
||||
<a href="details.html?service=datenanalyse" class="offer-btn">Details ansehen</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="../scripts/leads.js"></script>
|
||||
<script src="../scripts/cursor.js"></script>
|
||||
<script src="../scripts/scroll-header.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,138 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profice - Anmeldung</title>
|
||||
<link rel="stylesheet" href="../style/design.css">
|
||||
<link rel="stylesheet" href="../style/login.css">
|
||||
<link rel="stylesheet" href="../style/cursor.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Top Banner -->
|
||||
<header class="top-banner dark-theme">
|
||||
<div class="top-banner-left">
|
||||
<div class="banner-left">
|
||||
<button class="menu-toggle" id="menuToggle" aria-label="Menü">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<a href="../index.html" class="logo-link">
|
||||
<img src="../images/logo/logo-01-complete.png" alt="Profice Logo" class="logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-center">
|
||||
<nav class="main-nav">
|
||||
<a href="../index.html#hero-section" class="nav-link">Startseite</a>
|
||||
<a href="../index.html#enterprise" class="nav-link">Unternehmen</a>
|
||||
<a href="../index.html#pricing" class="nav-link">Preise</a>
|
||||
<a href="../index.html#services" class="nav-link">Lösungen</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="top-banner-right">
|
||||
<button id="cursorToggle" aria-label="Cursor umschalten" title="Benutzerdefinierten Cursor umschalten">
|
||||
<img src="../images/additional/cursor.png" alt="Standard Cursor" class="cursor-icon">
|
||||
</button>
|
||||
<button id="registerBtn" class="login-btn register" aria-label="Registrieren" title="Registrieren">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="8.5" cy="7" r="4"></circle>
|
||||
<line x1="20" y1="8" x2="20" y2="14"></line>
|
||||
<line x1="23" y1="11" x2="17" y2="11"></line>
|
||||
</svg>
|
||||
Registrieren
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Slide Menu -->
|
||||
<nav class="slide-menu" id="slideMenu">
|
||||
<a href="../index.html">Startseite</a>
|
||||
<a href="offers.html">Kontakt & Anfrage</a>
|
||||
<a href="leads.html">Leads Dashboard</a>
|
||||
</nav>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay" id="overlay"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content login-content">
|
||||
<div class="login-container">
|
||||
<div class="login-header">
|
||||
<div class="login-icon">🔐</div>
|
||||
<h1 class="login-title">Willkommen zurück</h1>
|
||||
<p class="login-subtitle">Melden Sie sich an, um auf Ihr Konto zuzugreifen</p>
|
||||
</div>
|
||||
|
||||
<form id="loginForm" class="login-form">
|
||||
<div class="form-group">
|
||||
<label for="email">E-Mail</label>
|
||||
<input type="email" id="email" name="email" required placeholder="ihre@email.de">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Passwort</label>
|
||||
<input type="password" id="password" name="password" required placeholder="Passwort">
|
||||
</div>
|
||||
|
||||
<div class="form-options">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="remember" name="remember">
|
||||
<span class="checkbox-custom"></span>
|
||||
Angemeldet bleiben
|
||||
</label>
|
||||
<a href="#" class="forgot-password">Passwort vergessen?</a>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="login-btn-submit" id="loginSubmit">
|
||||
<span class="btn-text">Anmelden</span>
|
||||
<span class="btn-loading" style="display: none;">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
|
||||
<polyline points="22 6 12 16 2 6"></polyline>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="login-divider">
|
||||
<span>oder</span>
|
||||
</div>
|
||||
|
||||
<div class="social-login">
|
||||
<button type="button" class="social-btn google-btn">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c-.82 2.33-2.85 4.08-5.92 4.08-.57 0-1.11-.08-1.63-.24V14.6c.52.16 1.06.24 1.63.24 3.07 0 5.52-2.51 5.52-5.52 0-.1 0-.2-.01-.3-.57-2.53-2.11-4.52-4.52-4.52zM12 23c-1.61 0-3.09-.59-4.23-1.57l.01-.02V18.6l-.01.02c1.14-.98 2.62-1.57 4.23-1.57 3.07 0 5.52 2.51 5.52 5.52 0 .1 0 .2-.01.3z"/>
|
||||
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
|
||||
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.46l-2.85 2.22c-.81-.62-1.79-1.11-2.85-1.36-.52-.16-1.06-.24-1.63-.24-3.07 0-5.52 2.51-5.52 5.52 0 .1 0 .2.01.3.57 2.53 2.11 4.52 4.52 4.52z"/>
|
||||
</svg>
|
||||
Mit Google anmelden
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="login-footer">
|
||||
<p>Noch kein Konto? <a href="register.html">Jetzt registrieren</a></p>
|
||||
</div>
|
||||
|
||||
<div class="success-message" id="successMessage">
|
||||
<div class="success-icon">✅</div>
|
||||
<h3>Erfolgreich angemeldet!</h3>
|
||||
<p>Sie werden weitergeleitet...</p>
|
||||
</div>
|
||||
|
||||
<div class="error-message" id="errorMessage">
|
||||
<div class="error-icon">❌</div>
|
||||
<h3>Anmeldung fehlgeschlagen</h3>
|
||||
<p id="errorText">Bitte überprüfen Sie Ihre Anmeldedaten.</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="../scripts/script.js"></script>
|
||||
<script src="../scripts/cursor.js"></script>
|
||||
<script src="../scripts/scroll-header.js"></script>
|
||||
<script src="../scripts/login.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,114 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profice</title>
|
||||
<link rel="stylesheet" href="../style/design.css">
|
||||
<link rel="stylesheet" href="../style/cursor.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Top Banner -->
|
||||
<header class="top-banner dark-theme">
|
||||
<div class="top-banner-left">
|
||||
<div class="banner-left">
|
||||
<button class="menu-toggle" id="menuToggle" aria-label="Menü">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<a href="../index.html" class="logo-link">
|
||||
<img src="../images/logo/logo-01-complete.png" alt="Profice Logo" class="logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-center">
|
||||
<nav class="main-nav">
|
||||
<a href="../index.html#hero-section" class="nav-link">Startseite</a>
|
||||
<a href="../index.html#enterprise" class="nav-link">Unternehmen</a>
|
||||
<a href="../index.html#pricing" class="nav-link">Preise</a>
|
||||
<a href="../index.html#services" class="nav-link">Lösungen</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="top-banner-right">
|
||||
<button id="cursorToggle" aria-label="Cursor umschalten" title="Benutzerdefinierten Cursor umschalten">
|
||||
<img src="../images/additional/cursor.png" alt="Standard Cursor" class="cursor-icon">
|
||||
</button>
|
||||
<button id="loginBtn" class="login-btn" aria-label="Anmelden" title="Anmelden">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
||||
<polyline points="10 17 15 12 10 7"></polyline>
|
||||
<line x1="15" y1="12" x2="3" y2="12"></line>
|
||||
</svg>
|
||||
Anmelden
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Slide Menu -->
|
||||
<nav class="slide-menu" id="slideMenu">
|
||||
<a href="../index.html">Startseite</a>
|
||||
<a href="offers.html" class="active">Kontakt & Anfrage</a>
|
||||
<a href="leads.html">Leads Dashboard</a>
|
||||
</nav>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay" id="overlay"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<div class="form-container">
|
||||
<h2 class="form-title">Kontaktieren Sie uns</h2>
|
||||
|
||||
<form id="contactForm">
|
||||
<div class="form-group">
|
||||
<label for="name">Name *</label>
|
||||
<input type="text" id="name" name="name" required placeholder="Ihr vollständiger Name">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="organisation">Organisation</label>
|
||||
<input type="text" id="organisation" name="organisation" placeholder="Firmenname (optional)">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="contact">E-Mail oder Telefonnummer *</label>
|
||||
<input type="text" id="contact" name="contact" required placeholder="email@beispiel.de oder +49 123 456789">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="service">Gewünschte Dienstleistung *</label>
|
||||
<select id="service" name="service" required>
|
||||
<option value="" disabled selected>Bitte wählen...</option>
|
||||
<option value="website">Website</option>
|
||||
<option value="ki-integration">KI Integration</option>
|
||||
<option value="automatisation">Automatisation</option>
|
||||
<option value="unabhaengige-wahl">Unabhängige Wahl</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="budget">Budget (€)</label>
|
||||
<input type="text" id="budget" name="budget" placeholder="z.B. 5000 - 10000">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Beschreibung *</label>
|
||||
<textarea id="description" name="description" required placeholder="Beschreiben Sie Ihr Projekt oder Ihre Anfrage..."></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="submit-btn">Anfrage senden</button>
|
||||
</form>
|
||||
|
||||
<div class="success-message" id="successMessage">
|
||||
<h3>Vielen Dank!</h3>
|
||||
<p>Ihre Anfrage wurde erfolgreich gesendet. Wir melden uns bald bei Ihnen.</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="../scripts/script.js"></script>
|
||||
<script src="../scripts/cursor.js"></script>
|
||||
<script src="../scripts/scroll-header.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,174 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Registrierung - Profice</title>
|
||||
<link rel="stylesheet" href="../style/design.css">
|
||||
<link rel="stylesheet" href="../style/cursor.css">
|
||||
<link rel="stylesheet" href="../style/login.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Top Banner -->
|
||||
<header class="top-banner dark-theme">
|
||||
<div class="top-banner-left">
|
||||
<div class="banner-left">
|
||||
<button class="menu-toggle" id="menuToggle" aria-label="Menü">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<a href="../index.html" class="logo-link">
|
||||
<img src="../images/logo/logo-01-complete.png" alt="Profice Logo" class="logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-center">
|
||||
<nav class="main-nav">
|
||||
<a href="../index.html#hero-section" class="nav-link">Startseite</a>
|
||||
<a href="../index.html#enterprise" class="nav-link">Unternehmen</a>
|
||||
<a href="../index.html#pricing" class="nav-link">Preise</a>
|
||||
<a href="../index.html#services" class="nav-link">Lösungen</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="top-banner-right">
|
||||
<button id="cursorToggle" aria-label="Cursor umschalten" title="Benutzerdefinierten Cursor umschalten">
|
||||
<img src="../images/additional/cursor.png" alt="Standard Cursor" class="cursor-icon">
|
||||
</button>
|
||||
<button id="loginBtn" class="login-btn" aria-label="Anmelden" title="Anmelden">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
||||
<polyline points="10 17 15 12 10 7"></polyline>
|
||||
<line x1="15" y1="12" x2="3" y2="12"></line>
|
||||
</svg>
|
||||
Anmelden
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Slide Menu -->
|
||||
<nav class="slide-menu" id="slideMenu">
|
||||
<a href="../index.html">Startseite</a>
|
||||
<a href="offers.html">Kontakt & Anfrage</a>
|
||||
<a href="leads.html">Leads Dashboard</a>
|
||||
</nav>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay" id="overlay"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content login-content">
|
||||
<div class="login-container">
|
||||
<div class="login-header">
|
||||
<div class="login-icon">👤</div>
|
||||
<h1 class="login-title">Konto erstellen</h1>
|
||||
<p class="login-subtitle">Registrieren Sie sich, um auf alle Funktionen zuzugreifen</p>
|
||||
</div>
|
||||
|
||||
<form id="registerForm" class="login-form">
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="firstName">Vorname *</label>
|
||||
<input type="text" id="firstName" name="firstName" required placeholder="Max">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastName">Nachname *</label>
|
||||
<input type="text" id="lastName" name="lastName" required placeholder="Mustermann">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="email">E-Mail *</label>
|
||||
<input type="email" id="email" name="email" required placeholder="ihre@email.de">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="phone">Telefonnummer</label>
|
||||
<input type="tel" id="phone" name="phone" placeholder="+49 123 456789">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="company">Unternehmen</label>
|
||||
<input type="text" id="company" name="company" placeholder="Firmenname (optional)">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Passwort *</label>
|
||||
<input type="password" id="password" name="password" required placeholder="Mindestens 8 Zeichen">
|
||||
<div class="password-strength" id="passwordStrength">
|
||||
<div class="strength-bar"></div>
|
||||
<span class="strength-text">Passwortstärke</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="confirmPassword">Passwort bestätigen *</label>
|
||||
<input type="password" id="confirmPassword" name="confirmPassword" required placeholder="Passwort wiederholen">
|
||||
</div>
|
||||
|
||||
<div class="form-options">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="terms" name="terms" required>
|
||||
<span class="checkbox-custom"></span>
|
||||
Ich stimme den <a href="#" class="terms-link">Nutzungsbedingungen</a> und <a href="#" class="terms-link">Datenschutzrichtlinien</a> zu *
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-options">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="newsletter" name="newsletter">
|
||||
<span class="checkbox-custom"></span>
|
||||
Ich möchte den Newsletter erhalten
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="login-btn-submit" id="registerSubmit">
|
||||
<span class="btn-text">Konto erstellen</span>
|
||||
<span class="btn-loading" style="display: none;">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
|
||||
<polyline points="22 6 12 16 2 6"></polyline>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="login-divider">
|
||||
<span>oder</span>
|
||||
</div>
|
||||
|
||||
<div class="social-login">
|
||||
<button type="button" class="social-btn google-btn">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c-.82 2.33-2.85 4.08-5.92 4.08-.57 0-1.11-.08-1.63-.24V14.6c.52.16 1.06.24 1.63.24 3.07 0 5.52-2.51 5.52-5.52 0-.1 0-.2-.01-.3-.57-2.53-2.11-4.52-4.52-4.52zM12 23c-1.61 0-3.09-.59-4.23-1.57l.01-.02V18.6l-.01.02c1.14-.98 2.62-1.57 4.23-1.57 3.07 0 5.52 2.51 5.52 5.52 0 .1 0 .2-.01.3z"/>
|
||||
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
|
||||
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.46l-2.85 2.22c-.81-.62-1.79-1.11-2.85-1.36-.52-.16-1.06-.24-1.63-.24-3.07 0-5.52 2.51-5.52 5.52 0 .1 0 .2.01.3.57 2.53 2.11 4.52 4.52 4.52z"/>
|
||||
</svg>
|
||||
Mit Google registrieren
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="login-footer">
|
||||
<p>Bereits ein Konto? <a href="login.html">Jetzt anmelden</a></p>
|
||||
</div>
|
||||
|
||||
<div class="success-message" id="successMessage">
|
||||
<div class="success-icon">✅</div>
|
||||
<h3>Registrierung erfolgreich!</h3>
|
||||
<p>Ihr Konto wurde erstellt. Sie werden weitergeleitet...</p>
|
||||
</div>
|
||||
|
||||
<div class="error-message" id="errorMessage">
|
||||
<div class="error-icon">❌</div>
|
||||
<h3>Registrierung fehlgeschlagen</h3>
|
||||
<p id="errorText">Bitte überprüfen Sie Ihre Eingaben.</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="../scripts/script.js"></script>
|
||||
<script src="../scripts/cursor.js"></script>
|
||||
<script src="../scripts/scroll-header.js"></script>
|
||||
<script src="../scripts/register.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,191 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profice - Website Entwicklung</title>
|
||||
<link rel="stylesheet" href="../style/design.css">
|
||||
<link rel="stylesheet" href="../style/service.css">
|
||||
<link rel="stylesheet" href="../style/cursor.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Top Banner -->
|
||||
<header class="top-banner dark-theme">
|
||||
<div class="top-banner-left">
|
||||
<div class="banner-left">
|
||||
<button class="menu-toggle" id="menuToggle" aria-label="Menu">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<a href="../index.html" class="logo-link">
|
||||
<img src="../images/logo/logo-01-complete.png" alt="Profice Logo" class="logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-banner-center">
|
||||
<nav class="main-nav">
|
||||
<a href="../index.html#hero-section" class="nav-link">Home</a>
|
||||
<a href="../index.html#enterprise" class="nav-link">Enterprise</a>
|
||||
<a href="../index.html#pricing" class="nav-link">Pricing</a>
|
||||
<a href="../index.html#services" class="nav-link">Lösungen</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="top-banner-right">
|
||||
<button id="cursorToggle" aria-label="Toggle Cursor" title="Toggle Custom Cursor">
|
||||
<img src="../images/additional/cursor.png" alt="Default Cursor" class="cursor-icon">
|
||||
</button>
|
||||
<button id="loginBtn" class="login-btn" aria-label="Log in" title="Log in">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
||||
<polyline points="10 17 15 12 10 7"></polyline>
|
||||
<line x1="15" y1="12" x2="3" y2="12"></line>
|
||||
</svg>
|
||||
Log in
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Slide Menu -->
|
||||
<nav class="slide-menu" id="slideMenu">
|
||||
<a href="../index.html">Startseite</a>
|
||||
<a href="offers.html" class="active">Kontakt & Anfrage</a>
|
||||
<a href="leads.html">Leads Dashboard</a>
|
||||
</nav>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay" id="overlay"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<div class="service-container">
|
||||
<!-- Service Header -->
|
||||
<div class="service-header">
|
||||
<div class="service-icon">🌐</div>
|
||||
<h1 class="service-title">Website Entwicklung</h1>
|
||||
<p class="service-subtitle">Moderne, responsive Webseiten, die konvertieren und Ihre Marke perfekt repräsentieren</p>
|
||||
</div>
|
||||
|
||||
<!-- Service Description -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Unsere Webentwicklungsdienstleistungen</h2>
|
||||
<p class="section-text">
|
||||
Wir entwickeln maßgeschneiderte Websites, die nicht nur gut aussehen, sondern auch Ergebnisse liefern.
|
||||
Von der Konzeption über das Design bis zur Implementierung und Wartung begleiten wir Sie durch den gesamten Prozess.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Service Features -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Was wir bieten</h2>
|
||||
<div class="features-grid">
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🎨</div>
|
||||
<h3>Responsive Design</h3>
|
||||
<p>Perfekte Darstellung auf allen Geräten - von Desktop bis Mobile</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">⚡</div>
|
||||
<h3>Performance-Optimierung</h3>
|
||||
<p>Schnelle Ladezeiten und beste Nutzererfahrung</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🔒</div>
|
||||
<h3>SEO-Freundlich</h3>
|
||||
<p>Technische Grundlagen für gute Suchmaschinenplatzierungen</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🔧</div>
|
||||
<h3>CMS-Integration</h3>
|
||||
<p>Einfache Content-Verwaltung für Ihre Mitarbeiter</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🛡️</div>
|
||||
<h3>Sicherheit</h3>
|
||||
<p>Schutz vor Bedrohungen und sichere Datenverarbeitung</p>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📊</div>
|
||||
<h3>Analytics & Tracking</h3>
|
||||
<p>Detaillierte Auswertung Ihrer Website-Performance</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Unser Prozess</h2>
|
||||
<div class="process-timeline">
|
||||
<div class="process-item">
|
||||
<div class="process-number">1</div>
|
||||
<div class="process-content">
|
||||
<h3>Analyse & Konzeption</h3>
|
||||
<p>Wir verstehen Ihre Ziele und entwickeln eine passende Strategie</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">2</div>
|
||||
<div class="process-content">
|
||||
<h3>Design & Prototyping</h3>
|
||||
<p>Visuelle Konzepte und interaktive Prototypen</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">3</div>
|
||||
<div class="process-content">
|
||||
<h3>Entwicklung</h3>
|
||||
<p>Saubere, performante Code-Implementierung</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">4</div>
|
||||
<div class="process-content">
|
||||
<h3>Testing & Launch</h3>
|
||||
<p>Gewissenhafte Tests und erfolgreicher Start</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-item">
|
||||
<div class="process-number">5</div>
|
||||
<div class="process-content">
|
||||
<h3>Support & Wartung</h3>
|
||||
<p>Laufende Optimierung und technische Unterstützung</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Technologies -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Technologien</h2>
|
||||
<div class="tech-grid">
|
||||
<div class="tech-item">HTML5</div>
|
||||
<div class="tech-item">CSS3</div>
|
||||
<div class="tech-item">JavaScript</div>
|
||||
<div class="tech-item">React</div>
|
||||
<div class="tech-item">Vue.js</div>
|
||||
<div class="item">Angular</div>
|
||||
<div class="tech-item">Node.js</div>
|
||||
<div class="tech-item">PHP</div>
|
||||
<div class="tech-item">WordPress</div>
|
||||
<div class="tech-item">Shopify</div>
|
||||
<div class="tech-item">WooCommerce</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="service-section">
|
||||
<h2 class="section-title">Bereit für Ihre neue Website?</h2>
|
||||
<p class="section-text">Lassen Sie uns Ihr Projekt an und wir erstellen ein maßgeschneidertes Angebot.</p>
|
||||
<div class="cta-buttons">
|
||||
<a href="offers.html?service=website" class="cta-btn primary">Projekt starten</a>
|
||||
<a href="offers.html" class="cta-btn secondary">Mehr erfahren</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="../scripts/script.js"></script>
|
||||
<script src="../scripts/cursor.js"></script>
|
||||
<script src="../scripts/scroll-header.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,307 +0,0 @@
|
||||
/* Cookie Consent System - Matches Profice Design System */
|
||||
|
||||
/* Cookie Banner */
|
||||
.cookie-banner {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--primary-light);
|
||||
border-top: 1px solid var(--primary-mid);
|
||||
padding: 20px 40px;
|
||||
z-index: 10000;
|
||||
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(100%);
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.cookie-banner.show {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.cookie-banner-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.cookie-text {
|
||||
flex: 1;
|
||||
color: var(--primary-dark);
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.cookie-text h3 {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.cookie-text p {
|
||||
margin: 0;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.cookie-text a {
|
||||
color: var(--accent-teal);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cookie-text a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cookie-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cookie-btn {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cookie-btn-primary {
|
||||
background: var(--primary-dark);
|
||||
color: var(--primary-light);
|
||||
}
|
||||
|
||||
.cookie-btn-primary:hover {
|
||||
background: var(--primary-mid);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.cookie-btn-secondary {
|
||||
background: transparent;
|
||||
color: var(--primary-dark);
|
||||
border: 2px solid var(--primary-mid);
|
||||
}
|
||||
|
||||
.cookie-btn-secondary:hover {
|
||||
background: var(--primary-mid);
|
||||
color: var(--primary-light);
|
||||
}
|
||||
|
||||
.cookie-btn-settings {
|
||||
background: transparent;
|
||||
color: var(--accent-teal);
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
font-size: 14px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.cookie-btn-settings:hover {
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
/* Cookie Settings Modal */
|
||||
.cookie-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 10001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.cookie-modal.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.cookie-modal-content {
|
||||
background: var(--primary-light);
|
||||
border-radius: 12px;
|
||||
padding: 30px;
|
||||
max-width: 600px;
|
||||
width: 90%;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
transform: scale(0.9);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.cookie-modal.show .cookie-modal-content {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.cookie-modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid var(--primary-mid);
|
||||
}
|
||||
|
||||
.cookie-modal-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: var(--primary-dark);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cookie-modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
color: var(--primary-mid);
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.cookie-modal-close:hover {
|
||||
background: var(--primary-mid);
|
||||
color: var(--primary-light);
|
||||
}
|
||||
|
||||
.cookie-option {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
border: 1px solid var(--primary-mid);
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.cookie-option-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.cookie-option-title {
|
||||
font-weight: 600;
|
||||
color: var(--primary-dark);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cookie-option-description {
|
||||
color: var(--primary-mid);
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cookie-toggle {
|
||||
position: relative;
|
||||
width: 50px;
|
||||
height: 26px;
|
||||
background: var(--primary-mid);
|
||||
border-radius: 13px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.cookie-toggle.active {
|
||||
background: var(--accent-teal);
|
||||
}
|
||||
|
||||
.cookie-toggle-slider {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.cookie-toggle.active .cookie-toggle-slider {
|
||||
transform: translateX(24px);
|
||||
}
|
||||
|
||||
.cookie-toggle.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.cookie-modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 25px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid var(--primary-mid);
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.cookie-banner {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.cookie-banner-content {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cookie-buttons {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.cookie-btn {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cookie-modal-content {
|
||||
padding: 20px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.cookie-modal-footer {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.cookie-btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.cookie-text h3 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.cookie-text p {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.cookie-modal-content {
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/* cursor.css */
|
||||
|
||||
/* Default: System cursor (not custom) */
|
||||
body,
|
||||
html,
|
||||
a,
|
||||
button,
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
.menu-toggle,
|
||||
label {
|
||||
cursor: auto !important;
|
||||
}
|
||||
|
||||
/* Custom cursor only when enabled */
|
||||
body:not(.system-cursor),
|
||||
body:not(.system-cursor) a,
|
||||
body:not(.system-cursor) button,
|
||||
body:not(.system-cursor) input,
|
||||
body:not(.system-cursor) textarea,
|
||||
body:not(.system-cursor) select,
|
||||
body:not(.system-cursor) .menu-toggle,
|
||||
body:not(.system-cursor) label {
|
||||
cursor: none !important;
|
||||
}
|
||||
|
||||
#venom-cursor {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
mix-blend-mode: normal;
|
||||
display: none; /* Hidden by default */
|
||||
}
|
||||
|
||||
/* Show custom cursor only when not system cursor */
|
||||
body:not(.system-cursor) #venom-cursor {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (pointer: coarse) {
|
||||
body, html, a, button, input, textarea, select {
|
||||
cursor: auto !important;
|
||||
}
|
||||
|
||||
#venom-cursor {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
body.system-cursor,
|
||||
body.system-cursor * {
|
||||
cursor: auto !important;
|
||||
}
|
||||
|
||||
body.system-cursor #venom-cursor {
|
||||
display: none !important;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#cursorToggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: 2px solid var(--primary-dark);
|
||||
color: var(--primary-dark);
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
border-radius: 12px;
|
||||
cursor: auto; /* Use system cursor for toggle button */
|
||||
transition: all 0.3s ease;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#cursorToggle:hover {
|
||||
background: var(--primary-dark);
|
||||
color: var(--primary-light);
|
||||
}
|
||||
|
||||
body:not(.system-cursor) #cursorToggle {
|
||||
cursor: none; /* Use custom cursor when custom is enabled */
|
||||
}
|
||||
|
||||
.top-banner.dark-theme #cursorToggle {
|
||||
border-color: var(--primary-light);
|
||||
color: var(--primary-light);
|
||||
}
|
||||
|
||||
.top-banner.dark-theme #cursorToggle:hover {
|
||||
background: var(--primary-light);
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/* Details Page Styles */
|
||||
|
||||
.service-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
padding-bottom: 30px;
|
||||
border-bottom: 2px solid var(--accent-teal);
|
||||
}
|
||||
|
||||
.service-icon-large {
|
||||
font-size: 64px;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.service-title-large {
|
||||
font-size: 36px;
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.service-description-large {
|
||||
font-size: 18px;
|
||||
color: var(--primary-mid);
|
||||
line-height: 1.6;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.service-content {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.service-section {
|
||||
margin-bottom: 40px;
|
||||
padding: 30px;
|
||||
background: var(--primary-light);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 20px rgba(79, 71, 71, 0.1);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 24px;
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: var(--primary-mid);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.feature-list,
|
||||
.benefit-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.feature-list li,
|
||||
.benefit-list li {
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid rgba(119, 119, 100, 0.1);
|
||||
color: var(--primary-dark);
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.feature-list li:before,
|
||||
.benefit-list li:before {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--accent-teal);
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.feature-list li:last-child,
|
||||
.benefit-list li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
margin-top: 30px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.back-button-container {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
padding-top: 30px;
|
||||
border-top: 1px solid rgba(119, 119, 100, 0.2);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.error-message h2 {
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.error-message p {
|
||||
color: var(--primary-mid);
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.service-icon-large {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.service-title-large {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.service-description-large {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.service-section {
|
||||
padding: 20px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cta-btn {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
@@ -1,408 +0,0 @@
|
||||
/* Lead Details Page Styles */
|
||||
|
||||
.lead-details-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 120px 20px 20px 20px;
|
||||
}
|
||||
|
||||
.lead-header {
|
||||
text-align: center;
|
||||
margin-bottom: 50px;
|
||||
padding-bottom: 30px;
|
||||
border-bottom: 3px solid var(--accent-teal);
|
||||
}
|
||||
|
||||
.lead-icon {
|
||||
font-size: 72px;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.lead-title {
|
||||
font-size: 42px;
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.lead-subtitle {
|
||||
font-size: 20px;
|
||||
color: var(--primary-mid);
|
||||
line-height: 1.6;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.lead-details-card {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 8px 30px rgba(79, 71, 71, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
padding: 40px;
|
||||
border-bottom: 1px solid rgba(119, 119, 100, 0.1);
|
||||
}
|
||||
|
||||
.detail-section:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 24px;
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Status Styles */
|
||||
.status-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 8px 16px;
|
||||
border-radius: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.status-new {
|
||||
background: #e3f2fd;
|
||||
color: #1976d2;
|
||||
}
|
||||
|
||||
.status-in-progress {
|
||||
background: #fff3e0;
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
background: #e8f5e8;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.status-cancelled {
|
||||
background: #ffebee;
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.status-info {
|
||||
color: var(--primary-mid);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Info Grid */
|
||||
.info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 25px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
background: var(--primary-light);
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
border-left: 4px solid var(--accent-teal);
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 14px;
|
||||
color: var(--primary-mid);
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 18px;
|
||||
color: var(--primary-dark);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Service Info */
|
||||
.service-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
background: var(--primary-light);
|
||||
padding: 30px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
font-size: 48px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.service-details {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.service-title {
|
||||
font-size: 24px;
|
||||
color: var(--accent-teal);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.service-description {
|
||||
color: var(--primary-mid);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* Description Box */
|
||||
.description-box {
|
||||
background: var(--primary-light);
|
||||
padding: 30px;
|
||||
border-radius: 16px;
|
||||
border-left: 4px solid var(--accent-teal);
|
||||
}
|
||||
|
||||
.description-text {
|
||||
color: var(--primary-dark);
|
||||
line-height: 1.6;
|
||||
font-size: 16px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* Timeline */
|
||||
.timeline {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.timeline::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background: rgba(119, 119, 100, 0.2);
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
margin-bottom: 30px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.timeline-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.timeline-dot {
|
||||
position: absolute;
|
||||
left: -22px;
|
||||
top: 5px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: rgba(119, 119, 100, 0.3);
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
.timeline-item.active .timeline-dot {
|
||||
background: var(--accent-teal);
|
||||
box-shadow: 0 0 0 4px rgba(38, 166, 154, 0.2);
|
||||
}
|
||||
|
||||
.timeline-content h4 {
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.timeline-content p {
|
||||
color: var(--primary-mid);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Action Buttons */
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.action-btn.primary {
|
||||
background: var(--accent-teal);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.action-btn.primary:hover {
|
||||
background: #1e8e82;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.action-btn.secondary {
|
||||
background: var(--primary-light);
|
||||
color: var(--primary-dark);
|
||||
border: 1px solid rgba(119, 119, 100, 0.2);
|
||||
}
|
||||
|
||||
.action-btn.secondary:hover {
|
||||
background: var(--primary-mid);
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Navigation Buttons */
|
||||
.navigation-buttons {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
margin-top: 40px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cta-btn {
|
||||
padding: 16px 32px;
|
||||
border-radius: 30px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cta-btn.primary {
|
||||
background: var(--accent-teal);
|
||||
color: white;
|
||||
border: 2px solid var(--accent-teal);
|
||||
}
|
||||
|
||||
.cta-btn.primary:hover {
|
||||
background: white;
|
||||
color: var(--accent-teal);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(38, 166, 154, 0.3);
|
||||
}
|
||||
|
||||
.cta-btn.secondary {
|
||||
background: transparent;
|
||||
color: var(--primary-dark);
|
||||
border: 2px solid var(--primary-dark);
|
||||
}
|
||||
|
||||
.cta-btn.secondary:hover {
|
||||
background: var(--primary-dark);
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Error Message */
|
||||
.error-message {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 8px 30px rgba(79, 71, 71, 0.1);
|
||||
}
|
||||
|
||||
.error-message h2 {
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.error-message p {
|
||||
color: var(--primary-mid);
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.lead-details-container {
|
||||
padding: 100px 15px 20px 15px;
|
||||
}
|
||||
|
||||
.lead-icon {
|
||||
font-size: 56px;
|
||||
}
|
||||
|
||||
.lead-title {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.lead-subtitle {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
padding: 30px 20px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.info-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.service-info {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
font-size: 64px;
|
||||
}
|
||||
|
||||
.status-container {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons,
|
||||
.navigation-buttons {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-btn,
|
||||
.cta-btn {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print Styles */
|
||||
@media print {
|
||||
.top-banner,
|
||||
.slide-menu,
|
||||
.overlay,
|
||||
.navigation-buttons,
|
||||
.action-buttons {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.lead-details-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.lead-details-card {
|
||||
box-shadow: none;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/* Leads Dashboard Styles */
|
||||
|
||||
.leads-content {
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
.dashboard-container {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 15px 50px rgba(79, 71, 71, 0.1);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.dashboard-title {
|
||||
color: var(--primary-dark);
|
||||
font-size: 28px;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dashboard-subtitle {
|
||||
color: var(--primary-mid);
|
||||
font-size: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
/* Leads Table */
|
||||
.leads-table-wrapper {
|
||||
overflow-x: auto;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(119, 119, 100, 0.15);
|
||||
}
|
||||
|
||||
.leads-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
min-width: 500px;
|
||||
}
|
||||
|
||||
.leads-table thead {
|
||||
background: var(--primary-light);
|
||||
}
|
||||
|
||||
.leads-table th {
|
||||
padding: 16px 20px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: var(--primary-dark);
|
||||
font-size: 14px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.leads-table td {
|
||||
padding: 18px 20px;
|
||||
border-top: 1px solid rgba(119, 119, 100, 0.1);
|
||||
color: var(--primary-dark);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.leads-table tbody tr {
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.leads-table tbody tr:hover {
|
||||
background: rgba(235, 235, 222, 0.5);
|
||||
}
|
||||
|
||||
/* Status Badges */
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 6px 14px;
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.status-badge.completed {
|
||||
background: rgba(102, 187, 106, 0.15);
|
||||
color: var(--accent-green);
|
||||
}
|
||||
|
||||
.status-badge.in-progress {
|
||||
background: rgba(245, 124, 0, 0.15);
|
||||
color: var(--accent-orange);
|
||||
}
|
||||
|
||||
.status-badge.open {
|
||||
background: rgba(119, 119, 100, 0.15);
|
||||
color: var(--primary-mid);
|
||||
}
|
||||
|
||||
/* Action Button */
|
||||
.action-btn {
|
||||
padding: 8px 16px;
|
||||
background: transparent;
|
||||
border: 2px solid var(--accent-teal);
|
||||
color: var(--accent-teal);
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.action-btn:hover {
|
||||
background: var(--accent-teal);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Offers Section */
|
||||
.offers-section {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.offers-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.offer-card {
|
||||
background: var(--primary-light);
|
||||
border-radius: 20px;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.offer-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 40px rgba(79, 71, 71, 0.15);
|
||||
background: white;
|
||||
}
|
||||
|
||||
.offer-icon {
|
||||
font-size: 40px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.offer-title {
|
||||
color: var(--primary-dark);
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.offer-description {
|
||||
color: var(--primary-mid);
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.offer-btn {
|
||||
display: inline-block;
|
||||
padding: 10px 24px;
|
||||
background: var(--accent-teal);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 25px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.offer-btn:hover {
|
||||
background: #1e8e82;
|
||||
box-shadow: 0 5px 20px rgba(38, 166, 154, 0.3);
|
||||
}
|
||||
|
||||
/* Active menu link */
|
||||
.slide-menu a.active {
|
||||
background: var(--primary-light);
|
||||
border-left-color: var(--accent-teal);
|
||||
color: var(--accent-teal);
|
||||
}
|
||||
|
||||
/* Empty state */
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
color: var(--primary-mid);
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 600px) {
|
||||
.dashboard-container {
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
.dashboard-title {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.leads-table th,
|
||||
.leads-table td {
|
||||
padding: 12px 14px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.offer-card {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.offers-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
@@ -1,547 +0,0 @@
|
||||
/* Login Page Styles */
|
||||
|
||||
.login-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
padding: 120px 20px 20px 20px;
|
||||
background: linear-gradient(135deg, var(--primary-light) 0%, white 100%);
|
||||
}
|
||||
|
||||
.login-container {
|
||||
width: 100%;
|
||||
max-width: 450px;
|
||||
background: white;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 20px 60px rgba(79, 71, 71, 0.15);
|
||||
padding: 50px 40px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.login-container::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, var(--accent-teal), var(--accent-green));
|
||||
}
|
||||
|
||||
.login-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.login-icon {
|
||||
font-size: 64px;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-size: 32px;
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
color: var(--primary-mid);
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.login-form .form-group {
|
||||
position: relative;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.login-form .form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
color: var(--primary-dark);
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.login-form .form-group input {
|
||||
width: 100%;
|
||||
padding: 14px 45px 14px 18px;
|
||||
border: 2px solid rgba(119, 119, 100, 0.2);
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
background: var(--primary-light);
|
||||
color: var(--primary-dark);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.login-form .form-group input:focus {
|
||||
border-color: var(--accent-teal);
|
||||
background: white;
|
||||
box-shadow: 0 0 0 4px rgba(38, 166, 154, 0.15);
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
position: absolute;
|
||||
right: 18px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 20px;
|
||||
color: var(--primary-mid);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.password-toggle {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--primary-mid);
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.password-toggle:hover {
|
||||
background: rgba(119, 119, 100, 0.1);
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.form-options {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.checkbox-label input[type="checkbox"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.checkbox-custom {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid rgba(119, 119, 100, 0.3);
|
||||
border-radius: 4px;
|
||||
margin-right: 8px;
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.checkbox-label input[type="checkbox"]:checked + .checkbox-custom {
|
||||
background: var(--accent-teal);
|
||||
border-color: var(--accent-teal);
|
||||
}
|
||||
|
||||
.checkbox-label input[type="checkbox"]:checked + .checkbox-custom::after {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.forgot-password {
|
||||
color: var(--accent-teal);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.forgot-password:hover {
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.login-btn-submit {
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
background: var(--accent-teal);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.login-btn-submit:hover:not(:disabled) {
|
||||
background: #1e8e82;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(38, 166, 154, 0.3);
|
||||
}
|
||||
|
||||
.login-btn-submit:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-loading svg {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.login-divider {
|
||||
text-align: center;
|
||||
margin: 30px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login-divider::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: rgba(119, 119, 100, 0.2);
|
||||
}
|
||||
|
||||
.login-divider span {
|
||||
background: white;
|
||||
padding: 0 20px;
|
||||
color: var(--primary-mid);
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.social-login {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.social-btn {
|
||||
width: 100%;
|
||||
padding: 14px;
|
||||
border: 2px solid rgba(119, 119, 100, 0.2);
|
||||
border-radius: 12px;
|
||||
background: white;
|
||||
color: var(--primary-dark);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.social-btn:hover {
|
||||
border-color: var(--primary-mid);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 15px rgba(79, 71, 71, 0.1);
|
||||
}
|
||||
|
||||
.google-btn:hover {
|
||||
border-color: #4285f4;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: var(--primary-mid);
|
||||
}
|
||||
|
||||
.login-footer a {
|
||||
color: var(--accent-teal);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.login-footer a:hover {
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
/* Messages */
|
||||
.success-message,
|
||||
.error-message {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
transform: translateY(-100%);
|
||||
transition: transform 0.3s ease;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.success-message.show,
|
||||
.error-message.show {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.success-message {
|
||||
background: linear-gradient(135deg, #e8f5e8, #d4edda);
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background: linear-gradient(135deg, #ffebee, #f8d7da);
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.success-icon,
|
||||
.error-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.success-message h3,
|
||||
.error-message h3 {
|
||||
margin-bottom: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.success-message p,
|
||||
.error-message p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Login Button Styles */
|
||||
.login-btn {
|
||||
background: transparent;
|
||||
border: 2px solid var(--primary-dark);
|
||||
color: var(--primary-dark);
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.login-btn:hover {
|
||||
background: var(--primary-dark);
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.register-btn {
|
||||
background: transparent;
|
||||
border: 2px solid var(--primary-dark);
|
||||
color: var(--primary-dark);
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.register-btn:hover {
|
||||
background: var(--primary-dark);
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Register Button (White version) */
|
||||
.login-btn.register {
|
||||
background: transparent;
|
||||
border: 2px solid white;
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.login-btn.register:hover {
|
||||
background: white;
|
||||
color: var(--primary-dark);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Ensure login button is white on register page */
|
||||
body .login-btn {
|
||||
background: transparent !important;
|
||||
border: 2px solid white !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
body .login-btn:hover {
|
||||
background: white !important;
|
||||
color: var(--primary-dark) !important;
|
||||
}
|
||||
|
||||
/* Form Row for Two Columns */
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.form-row .form-group {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Password Strength Indicator */
|
||||
.password-strength {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.strength-bar {
|
||||
flex: 1;
|
||||
height: 4px;
|
||||
background: #e0e0e0;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.strength-bar::before {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
transition: width 0.3s ease, background-color 0.3s ease;
|
||||
background: #f44336;
|
||||
}
|
||||
|
||||
.strength-text {
|
||||
font-size: 12px;
|
||||
color: var(--primary-mid);
|
||||
}
|
||||
|
||||
/* Password Strength Levels */
|
||||
.strength-weak .strength-bar::before {
|
||||
width: 33%;
|
||||
background: #f44336;
|
||||
}
|
||||
|
||||
.strength-medium .strength-bar::before {
|
||||
width: 66%;
|
||||
background: #ff9800;
|
||||
}
|
||||
|
||||
.strength-strong .strength-bar::before {
|
||||
width: 100%;
|
||||
background: #4caf50;
|
||||
}
|
||||
|
||||
.strength-weak .strength-text {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.strength-medium .strength-text {
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.strength-strong .strength-text {
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
/* Terms Links */
|
||||
.terms-link {
|
||||
color: var(--accent-teal);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.terms-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.login-content {
|
||||
padding: 100px 15px 20px 15px;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
padding: 40px 30px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.login-icon {
|
||||
font-size: 56px;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.form-options {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.social-btn {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.login-container {
|
||||
padding: 30px 20px;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.login-form .form-group input {
|
||||
font-size: 16px;
|
||||
padding: 12px 40px 12px 15px;
|
||||
}
|
||||
|
||||
.input-icon,
|
||||
.password-toggle {
|
||||
right: 15px;
|
||||
}
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
/* Service Page Styles */
|
||||
|
||||
.service-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 120px 20px 20px 20px;
|
||||
}
|
||||
|
||||
.service-header {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
padding-bottom: 40px;
|
||||
border-bottom: 3px solid var(--accent-teal);
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
font-size: 72px;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.service-title {
|
||||
font-size: 42px;
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.service-subtitle {
|
||||
font-size: 20px;
|
||||
color: var(--primary-mid);
|
||||
line-height: 1.6;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.service-section {
|
||||
margin-bottom: 50px;
|
||||
padding: 40px;
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 8px 30px rgba(79, 71, 71, 0.1);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 28px;
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
color: var(--primary-mid);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
/* Features Grid */
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 30px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
background: var(--primary-light);
|
||||
padding: 30px;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-item:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 40px rgba(79, 71, 71, 0.15);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 15px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.feature-item h3 {
|
||||
color: var(--accent-teal);
|
||||
margin-bottom: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.feature-item p {
|
||||
color: var(--primary-mid);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* Process Timeline */
|
||||
.process-timeline {
|
||||
max-width: 800px;
|
||||
margin: 40px auto 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.process-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 40px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.process-number {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: var(--accent-teal);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.process-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.process-content h3 {
|
||||
color: var(--primary-dark);
|
||||
margin-bottom: 8px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.process-content p {
|
||||
color: var(--primary-mid);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* Tech Grid */
|
||||
.tech-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
justify-content: center;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.tech-item {
|
||||
background: var(--primary-dark);
|
||||
color: white;
|
||||
padding: 12px 20px;
|
||||
border-radius: 25px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.tech-item:hover {
|
||||
transform: translateY(-2px);
|
||||
background: var(--accent-teal);
|
||||
}
|
||||
|
||||
/* Benefits Grid */
|
||||
.benefits-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 25px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.benefit-item {
|
||||
background: linear-gradient(135deg, var(--accent-teal), var(--accent-green));
|
||||
color: white;
|
||||
padding: 30px;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.benefit-item:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 15px 40px rgba(38, 166, 154, 0.3);
|
||||
}
|
||||
|
||||
.benefit-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 15px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.benefit-item h3 {
|
||||
margin-bottom: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.benefit-item p {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* Use Cases Grid */
|
||||
.use-cases-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 25px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.use-case-item {
|
||||
background: var(--primary-light);
|
||||
padding: 25px;
|
||||
border-radius: 12px;
|
||||
border-left: 4px solid var(--accent-teal);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.use-case-item:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 25px rgba(79, 71, 71, 0.1);
|
||||
}
|
||||
|
||||
.use-case-item h3 {
|
||||
color: var(--accent-teal);
|
||||
margin-bottom: 10px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.use-case-item p {
|
||||
color: var(--primary-mid);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* CTA Buttons */
|
||||
.cta-buttons {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
margin-top: 40px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cta-btn {
|
||||
padding: 16px 32px;
|
||||
border-radius: 30px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cta-btn.primary {
|
||||
background: var(--accent-teal);
|
||||
color: white;
|
||||
border: 2px solid var(--accent-teal);
|
||||
}
|
||||
|
||||
.cta-btn.primary:hover {
|
||||
background: white;
|
||||
color: var(--accent-teal);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(38, 166, 154, 0.3);
|
||||
}
|
||||
|
||||
.cta-btn.secondary {
|
||||
background: transparent;
|
||||
color: var(--primary-dark);
|
||||
border: 2px solid var(--primary-dark);
|
||||
}
|
||||
|
||||
.cta-btn.secondary:hover {
|
||||
background: var(--primary-dark);
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.service-container {
|
||||
padding: 100px 15px 20px 15px;
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
font-size: 56px;
|
||||
}
|
||||
|
||||
.service-title {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.service-subtitle {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.service-section {
|
||||
padding: 30px 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.features-grid,
|
||||
.benefits-grid,
|
||||
.use-cases-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.process-item {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.process-number {
|
||||
margin: 0 auto 15px;
|
||||
}
|
||||
|
||||
.process-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cta-btn {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
11
Profice WebSite/.claude/settings.local.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(for f:*)",
|
||||
"Bash(do grep:*)",
|
||||
"Bash(echo \"ALREADY: $f\")",
|
||||
"Bash(echo \"NEEDS: $f\")",
|
||||
"Bash(done)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1 +1,47 @@
|
||||
Options -Indexes
|
||||
# Security - Disable directory listing
|
||||
Options -Indexes
|
||||
|
||||
# Flowise chat proxy — rewrites /api/v1/prediction/* to PHP proxy (hides real Flowise URL)
|
||||
RewriteEngine On
|
||||
RewriteRule ^api/v1/prediction/(.*)$ scripts/add/flowise-proxy.php [L,QSA,NC]
|
||||
|
||||
# Enable compression
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/plain
|
||||
AddOutputFilterByType DEFLATE text/html
|
||||
AddOutputFilterByType DEFLATE text/xml
|
||||
AddOutputFilterByType DEFLATE text/css
|
||||
AddOutputFilterByType DEFLATE application/xml
|
||||
AddOutputFilterByType DEFLATE application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE application/rss+xml
|
||||
AddOutputFilterByType DEFLATE application/javascript
|
||||
AddOutputFilterByType DEFLATE application/x-javascript
|
||||
AddOutputFilterByType DEFLATE application/json
|
||||
</IfModule>
|
||||
|
||||
# Set caching headers
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
ExpiresByType text/css "access plus 1 month"
|
||||
ExpiresByType application/javascript "access plus 1 month"
|
||||
ExpiresByType image/png "access plus 1 month"
|
||||
ExpiresByType image/jpg "access plus 1 month"
|
||||
ExpiresByType image/jpeg "access plus 1 month"
|
||||
ExpiresByType image/gif "access plus 1 month"
|
||||
ExpiresByType image/ico "access plus 1 month"
|
||||
ExpiresByType image/svg+xml "access plus 1 month"
|
||||
ExpiresByType text/html "access plus 1 hour"
|
||||
</IfModule>
|
||||
|
||||
# Security headers
|
||||
<IfModule mod_headers.c>
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
Header always set X-Frame-Options DENY
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
</IfModule>
|
||||
|
||||
# Force HTTPS (uncomment if you have SSL certificate)
|
||||
# RewriteEngine On
|
||||
# RewriteCond %{HTTPS} off
|
||||
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
89
Profice WebSite/DEPLOYMENT.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Profice Website - Server Deployment Guide
|
||||
|
||||
## 🚀 Ready for Production
|
||||
|
||||
Your website has been prepared for server hosting with the following optimizations:
|
||||
|
||||
### ✅ Completed Setup
|
||||
|
||||
#### 1. **Webhook Configuration Updated**
|
||||
- ✅ Switched to production webhook URLs
|
||||
- ✅ Debug mode disabled for security
|
||||
- ✅ Using correct N8N webhook IDs
|
||||
|
||||
#### 2. **Server Security & Performance (.htaccess)**
|
||||
- ✅ Directory listing disabled
|
||||
- ✅ GZIP compression enabled
|
||||
- ✅ Browser caching configured
|
||||
- ✅ Security headers set
|
||||
- ✅ PHP error display disabled
|
||||
- ✅ HTTPS redirect ready (uncomment when SSL is active)
|
||||
|
||||
#### 3. **Character Encoding Fixed**
|
||||
- ✅ All German special characters corrected
|
||||
- ✅ UTF-8 encoding properly configured
|
||||
|
||||
#### 4. **File Structure Clean**
|
||||
- ✅ Test files removed
|
||||
- ✅ Production-ready configuration
|
||||
|
||||
## 📁 Files to Upload
|
||||
|
||||
Upload the entire `Profice WebSite` folder to your server:
|
||||
|
||||
```
|
||||
Profice WebSite/
|
||||
├── .htaccess # Server configuration
|
||||
├── index.html # Homepage
|
||||
├── sites/ # Subpages
|
||||
│ ├── offers.html
|
||||
│ ├── leads.html
|
||||
│ ├── website.html
|
||||
│ ├── ki-integration.html
|
||||
│ └── automatisation.html
|
||||
├── scripts/ # Backend functionality
|
||||
│ └── add/
|
||||
│ └── send.php # Webhook handler
|
||||
├── style/ # CSS files
|
||||
├── images/ # Image assets
|
||||
└── components/ # Reusable components
|
||||
```
|
||||
|
||||
## 🔧 Server Requirements
|
||||
|
||||
### Minimum Requirements:
|
||||
- ✅ PHP 7.4+ (recommended 8.0+)
|
||||
- ✅ Apache server with .htaccess support
|
||||
- ✅ cURL extension enabled
|
||||
- ✅ JSON extension enabled
|
||||
|
||||
### Optional (for better performance):
|
||||
- SSL certificate (HTTPS)
|
||||
- GZIP compression support
|
||||
- Expires module for caching
|
||||
|
||||
## 🌐 After Upload
|
||||
|
||||
1. **Test the contact form** - Submit a test request
|
||||
2. **Check webhook delivery** - Verify N8N receives requests
|
||||
3. **Test all pages** - Ensure proper navigation
|
||||
4. **Enable HTTPS** (if available) - Uncomment lines 50-53 in .htaccess
|
||||
|
||||
## 🔒 Security Notes
|
||||
|
||||
- All sensitive data (webhooks, tokens) are stored in `send.php`
|
||||
- Debug mode is disabled in production
|
||||
- Security headers are configured
|
||||
- Directory listing is disabled
|
||||
|
||||
## 📞 Support
|
||||
|
||||
If you encounter issues:
|
||||
1. Check server error logs
|
||||
2. Verify PHP extensions (cURL, JSON)
|
||||
3. Test webhook URLs manually
|
||||
4. Ensure file permissions are correct (755 for folders, 644 for files)
|
||||
|
||||
---
|
||||
|
||||
**Your website is now ready for production deployment! 🎉**
|
||||
BIN
Profice WebSite/fonts/montserrat-bold.ttf
Normal file
BIN
Profice WebSite/fonts/montserrat-regular.ttf
Normal file
BIN
Profice WebSite/images/additional/Kein_KI.PNG
Normal file
|
After Width: | Height: | Size: 5.6 MiB |
BIN
Profice WebSite/images/icons/CRM.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
Profice WebSite/images/icons/KI.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
Profice WebSite/images/icons/chat.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
Profice WebSite/images/icons/email.png
Normal file
|
After Width: | Height: | Size: 412 KiB |
BIN
Profice WebSite/images/icons/email_black.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
Profice WebSite/images/icons/email_white.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
Profice WebSite/images/icons/grafik-removebg-preview.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
Profice WebSite/images/icons/mail.PNG
Normal file
|
After Width: | Height: | Size: 3.6 MiB |
BIN
Profice WebSite/images/icons/okay-removebg-preview.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
Profice WebSite/images/icons/phone.PNG
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
Profice WebSite/images/icons/phone_icon.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
Profice WebSite/images/icons/phone_white.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
Profice WebSite/images/icons/pulse-removebg-preview.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
Profice WebSite/images/icons/spider.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
Profice WebSite/images/icons/steam-removebg-preview.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
Profice WebSite/images/icons/team.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
Profice WebSite/images/icons/ticket.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
Profice WebSite/images/icons/uhren-removebg-preview.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
Profice WebSite/images/icons/upload-removebg-preview.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 322 KiB |