commit cc4bfa5dbe76db14c9ae6d12d98cf66e4e8d5fff Author: Ihor_Zhekov Date: Fri Jan 30 08:09:50 2026 +0100 cookie added, optimisation diff --git a/Profice WebSite/.htaccess b/Profice WebSite/.htaccess new file mode 100644 index 0000000..45552cb --- /dev/null +++ b/Profice WebSite/.htaccess @@ -0,0 +1 @@ +Options -Indexes \ No newline at end of file diff --git a/Profice WebSite/images/additional/cursor.png b/Profice WebSite/images/additional/cursor.png new file mode 100644 index 0000000..d70d430 Binary files /dev/null and b/Profice WebSite/images/additional/cursor.png differ diff --git a/Profice WebSite/images/additional/spidy.png b/Profice WebSite/images/additional/spidy.png new file mode 100644 index 0000000..2dcc8af Binary files /dev/null and b/Profice WebSite/images/additional/spidy.png differ diff --git a/Profice WebSite/images/icons/iconography-01.jpg b/Profice WebSite/images/icons/iconography-01.jpg new file mode 100644 index 0000000..8743a8a Binary files /dev/null and b/Profice WebSite/images/icons/iconography-01.jpg differ diff --git a/Profice WebSite/images/icons/iconography-01.png b/Profice WebSite/images/icons/iconography-01.png new file mode 100644 index 0000000..4c75a11 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-01.png differ diff --git a/Profice WebSite/images/icons/iconography-02.jpg b/Profice WebSite/images/icons/iconography-02.jpg new file mode 100644 index 0000000..2d5f6aa Binary files /dev/null and b/Profice WebSite/images/icons/iconography-02.jpg differ diff --git a/Profice WebSite/images/icons/iconography-02.png b/Profice WebSite/images/icons/iconography-02.png new file mode 100644 index 0000000..14aaf69 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-02.png differ diff --git a/Profice WebSite/images/icons/iconography-03.jpg b/Profice WebSite/images/icons/iconography-03.jpg new file mode 100644 index 0000000..ca99772 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-03.jpg differ diff --git a/Profice WebSite/images/icons/iconography-03.png b/Profice WebSite/images/icons/iconography-03.png new file mode 100644 index 0000000..ce6f89b Binary files /dev/null and b/Profice WebSite/images/icons/iconography-03.png differ diff --git a/Profice WebSite/images/icons/iconography-04 - Kopie.jpg b/Profice WebSite/images/icons/iconography-04 - Kopie.jpg new file mode 100644 index 0000000..f3e3e3a Binary files /dev/null and b/Profice WebSite/images/icons/iconography-04 - Kopie.jpg differ diff --git a/Profice WebSite/images/icons/iconography-04 - Kopie.png b/Profice WebSite/images/icons/iconography-04 - Kopie.png new file mode 100644 index 0000000..cb3a551 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-04 - Kopie.png differ diff --git a/Profice WebSite/images/icons/iconography-05.jpg b/Profice WebSite/images/icons/iconography-05.jpg new file mode 100644 index 0000000..ac6d288 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-05.jpg differ diff --git a/Profice WebSite/images/icons/iconography-05.png b/Profice WebSite/images/icons/iconography-05.png new file mode 100644 index 0000000..61e57d4 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-05.png differ diff --git a/Profice WebSite/images/icons/iconography-06.jpg b/Profice WebSite/images/icons/iconography-06.jpg new file mode 100644 index 0000000..98e29cb Binary files /dev/null and b/Profice WebSite/images/icons/iconography-06.jpg differ diff --git a/Profice WebSite/images/icons/iconography-06.png b/Profice WebSite/images/icons/iconography-06.png new file mode 100644 index 0000000..1e4f6f1 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-06.png differ diff --git a/Profice WebSite/images/icons/iconography-07 - Kopie.jpg b/Profice WebSite/images/icons/iconography-07 - Kopie.jpg new file mode 100644 index 0000000..64f803a Binary files /dev/null and b/Profice WebSite/images/icons/iconography-07 - Kopie.jpg differ diff --git a/Profice WebSite/images/icons/iconography-07.jpg b/Profice WebSite/images/icons/iconography-07.jpg new file mode 100644 index 0000000..64f803a Binary files /dev/null and b/Profice WebSite/images/icons/iconography-07.jpg differ diff --git a/Profice WebSite/images/icons/iconography-07.png b/Profice WebSite/images/icons/iconography-07.png new file mode 100644 index 0000000..92b3a73 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-07.png differ diff --git a/Profice WebSite/images/icons/iconography-08.jpg b/Profice WebSite/images/icons/iconography-08.jpg new file mode 100644 index 0000000..293a6a1 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-08.jpg differ diff --git a/Profice WebSite/images/icons/iconography-08.png b/Profice WebSite/images/icons/iconography-08.png new file mode 100644 index 0000000..2057da8 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-08.png differ diff --git a/Profice WebSite/images/icons/iconography-09.jpg b/Profice WebSite/images/icons/iconography-09.jpg new file mode 100644 index 0000000..8a816da Binary files /dev/null and b/Profice WebSite/images/icons/iconography-09.jpg differ diff --git a/Profice WebSite/images/icons/iconography-09.png b/Profice WebSite/images/icons/iconography-09.png new file mode 100644 index 0000000..55a4b12 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-09.png differ diff --git a/Profice WebSite/images/icons/iconography-10.jpg b/Profice WebSite/images/icons/iconography-10.jpg new file mode 100644 index 0000000..6de5ef1 Binary files /dev/null and b/Profice WebSite/images/icons/iconography-10.jpg differ diff --git a/Profice WebSite/images/icons/iconography-10.png b/Profice WebSite/images/icons/iconography-10.png new file mode 100644 index 0000000..a1b36ed Binary files /dev/null and b/Profice WebSite/images/icons/iconography-10.png differ diff --git a/Profice WebSite/images/logo/Appicon 1024X1024-01.png b/Profice WebSite/images/logo/Appicon 1024X1024-01.png new file mode 100644 index 0000000..c06e07d Binary files /dev/null and b/Profice WebSite/images/logo/Appicon 1024X1024-01.png differ diff --git a/Profice WebSite/images/logo/LOGO E3.jpg b/Profice WebSite/images/logo/LOGO E3.jpg new file mode 100644 index 0000000..2672503 Binary files /dev/null and b/Profice WebSite/images/logo/LOGO E3.jpg differ diff --git a/Profice WebSite/images/logo/Logo-01-complete.PNG b/Profice WebSite/images/logo/Logo-01-complete.PNG new file mode 100644 index 0000000..98f29e4 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-01-complete.PNG differ diff --git a/Profice WebSite/images/logo/Logo-01.jpg b/Profice WebSite/images/logo/Logo-01.jpg new file mode 100644 index 0000000..4957ea2 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-01.jpg differ diff --git a/Profice WebSite/images/logo/Logo-01.png b/Profice WebSite/images/logo/Logo-01.png new file mode 100644 index 0000000..803c96f Binary files /dev/null and b/Profice WebSite/images/logo/Logo-01.png differ diff --git a/Profice WebSite/images/logo/Logo-02.jpg b/Profice WebSite/images/logo/Logo-02.jpg new file mode 100644 index 0000000..c17416a Binary files /dev/null and b/Profice WebSite/images/logo/Logo-02.jpg differ diff --git a/Profice WebSite/images/logo/Logo-02.png b/Profice WebSite/images/logo/Logo-02.png new file mode 100644 index 0000000..4346e76 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-02.png differ diff --git a/Profice WebSite/images/logo/Logo-03.jpg b/Profice WebSite/images/logo/Logo-03.jpg new file mode 100644 index 0000000..e3f2819 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-03.jpg differ diff --git a/Profice WebSite/images/logo/Logo-03.png b/Profice WebSite/images/logo/Logo-03.png new file mode 100644 index 0000000..42807cd Binary files /dev/null and b/Profice WebSite/images/logo/Logo-03.png differ diff --git a/Profice WebSite/images/logo/Logo-04.jpg b/Profice WebSite/images/logo/Logo-04.jpg new file mode 100644 index 0000000..717a378 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-04.jpg differ diff --git a/Profice WebSite/images/logo/Logo-04.png b/Profice WebSite/images/logo/Logo-04.png new file mode 100644 index 0000000..db015ea Binary files /dev/null and b/Profice WebSite/images/logo/Logo-04.png differ diff --git a/Profice WebSite/images/logo/Logo-05.jpg b/Profice WebSite/images/logo/Logo-05.jpg new file mode 100644 index 0000000..1df8d43 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-05.jpg differ diff --git a/Profice WebSite/images/logo/Logo-05.png b/Profice WebSite/images/logo/Logo-05.png new file mode 100644 index 0000000..1cda111 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-05.png differ diff --git a/Profice WebSite/images/logo/Logo-06.jpg b/Profice WebSite/images/logo/Logo-06.jpg new file mode 100644 index 0000000..d06c645 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-06.jpg differ diff --git a/Profice WebSite/images/logo/Logo-07.jpg b/Profice WebSite/images/logo/Logo-07.jpg new file mode 100644 index 0000000..1dad7b3 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-07.jpg differ diff --git a/Profice WebSite/images/logo/Logo-07.png b/Profice WebSite/images/logo/Logo-07.png new file mode 100644 index 0000000..3224ded Binary files /dev/null and b/Profice WebSite/images/logo/Logo-07.png differ diff --git a/Profice WebSite/images/logo/Logo-08.jpg b/Profice WebSite/images/logo/Logo-08.jpg new file mode 100644 index 0000000..c5cf31c Binary files /dev/null and b/Profice WebSite/images/logo/Logo-08.jpg differ diff --git a/Profice WebSite/images/logo/Logo-08.png b/Profice WebSite/images/logo/Logo-08.png new file mode 100644 index 0000000..64b36ca Binary files /dev/null and b/Profice WebSite/images/logo/Logo-08.png differ diff --git a/Profice WebSite/images/logo/Logo-09.jpg b/Profice WebSite/images/logo/Logo-09.jpg new file mode 100644 index 0000000..fb9917c Binary files /dev/null and b/Profice WebSite/images/logo/Logo-09.jpg differ diff --git a/Profice WebSite/images/logo/Logo-09.png b/Profice WebSite/images/logo/Logo-09.png new file mode 100644 index 0000000..e9cf29d Binary files /dev/null and b/Profice WebSite/images/logo/Logo-09.png differ diff --git a/Profice WebSite/images/logo/Logo-10.jpg b/Profice WebSite/images/logo/Logo-10.jpg new file mode 100644 index 0000000..2384cf8 Binary files /dev/null and b/Profice WebSite/images/logo/Logo-10.jpg differ diff --git a/Profice WebSite/images/logo/Logo-10.png b/Profice WebSite/images/logo/Logo-10.png new file mode 100644 index 0000000..5579f7e Binary files /dev/null and b/Profice WebSite/images/logo/Logo-10.png differ diff --git a/Profice WebSite/index.html b/Profice WebSite/index.html new file mode 100644 index 0000000..1c65d49 --- /dev/null +++ b/Profice WebSite/index.html @@ -0,0 +1,257 @@ + + + + + + Profice - Digitale Lösungen + + + + + +
+
+ +
+ + + +
+ + +
+
+ + + + +
+ +
+ +
+
+

Transformieren Sie Ihr Unternehmen digital

+

Maßgeschneiderte Lösungen für Web, KI-Integration und Prozessautomatisierung. Wir bringen Ihre Vision in die digitale Realität.

+ +
+
+ [Bild: Digitale Transformation Illustration] +
+
+ +
+

Unternehmenslösungen

+
+

Maßgeschneiderte Lösungen für große Unternehmen mit komplexen Anforderungen.

+
+
+

Skalierbarkeit

+

Lösungen, die mit Ihrem Unternehmen wachsen

+
+
+

Sicherheit

+

Unternehmenssicherheit und Compliance

+
+
+

Integration

+

Nahtlose Integration mit bestehenden Systemen

+
+
+
+
+ +
+

Preise

+
+
+

Starter

+
€999
+

Perfekt für kleine Unternehmen

+
    +
  • Webentwicklung
  • +
  • Grundlegende KI-Integration
  • +
  • 3 Monate Support
  • +
+
+ +
+

Unternehmen

+
Individuell
+

Für große Unternehmen

+
    +
  • Volle Unternehmenslösungen
  • +
  • Custom KI-Entwicklung
  • +
  • 12 Monate Support
  • +
  • Dediziertes Team
  • +
+
+
+
+ +
+

Unsere Expertise

+
+ +
+
+ 🌐 +
+

Webentwicklung

+

Moderne, responsive Webseiten, die konvertieren und Ihre Marke perfekt repräsentieren.

+
+ +
+
+ 🤖 +
+

KI Integration

+

Nutzen Sie die Kraft künstlicher Intelligenz, um Ihre Daten besser zu verstehen und Prozesse zu optimieren.

+
+ +
+
+ ⚙️ +
+

Automatisierung

+

Sparen Sie Zeit und Ressourcen durch intelligente Workflow-Automatisierungen.

+
+
+
+ +
+
+
+

Warum Profice?

+

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.

+
    +
  • Individuelle Beratung
  • +
  • Transparente Prozesse
  • +
  • Zukunftssichere Technologien
  • +
+
+
+ [Bild: Team bei der Arbeit] +
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Profice WebSite/scripts/add/send.php b/Profice WebSite/scripts/add/send.php new file mode 100644 index 0000000..01322a0 --- /dev/null +++ b/Profice WebSite/scripts/add/send.php @@ -0,0 +1,642 @@ + $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 => true, + 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]; + } + + return [ + 'success' => $httpCode >= 200 && $httpCode < 300, + 'http_code' => $httpCode + ]; +} + +// ========================================== +// 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' => 'analytics', + 'id' => GTM_CONTAINER_ID + ]; + } + + // Facebook Pixel + if ($preferences['marketing'] && !empty(FB_PIXEL_ID)) { + $scripts['fb'] = [ + 'type' => 'marketing', + 'id' => FB_PIXEL_ID + ]; + } + + // Google Ads + if ($preferences['marketing'] && !empty(GADS_CONVERSION_ID) && GADS_CONVERSION_ID !== 'AW-XXXXXXXXXX') { + $scripts['gads'] = [ + 'type' => 'marketing', + 'id' => GADS_CONVERSION_ID + ]; + } + + // LinkedIn + if ($preferences['marketing'] && !empty(LINKEDIN_PARTNER_ID)) { + $scripts['linkedin'] = [ + 'type' => 'marketing', + 'id' => LINKEDIN_PARTNER_ID + ]; + } + + return $scripts; +} + +function trackEvent($eventName, $eventData, $preferences) { + $results = []; + + // Server-side Google Analytics tracking + if ($preferences['analytics'] && !empty(GA_MEASUREMENT_ID) && !empty(GA_API_SECRET)) { + $results['ga'] = sendGAEvent($eventName, $eventData); + } + + // Server-side Facebook Conversions API + if ($preferences['marketing'] && !empty(FB_PIXEL_ID) && !empty(FB_ACCESS_TOKEN)) { + $results['fb'] = sendFBEvent($eventName, $eventData); + } + + return $results; +} + +function sendGAEvent($eventName, $eventData) { + if (empty(GA_API_SECRET)) return ['success' => false, 'error' => 'No API secret']; + + $url = 'https://www.google-analytics.com/mp/collect?measurement_id=' . GA_MEASUREMENT_ID . '&api_secret=' . GA_API_SECRET; + + $payload = [ + 'client_id' => $eventData['client_id'] ?? uniqid(), + 'events' => [[ + 'name' => $eventName, + 'params' => $eventData + ]] + ]; + + return sendToWebhook($payload, $url); +} + +function sendFBEvent($eventName, $eventData) { + if (empty(FB_ACCESS_TOKEN)) return ['success' => false, 'error' => 'No access token']; + + $url = 'https://graph.facebook.com/v18.0/' . FB_PIXEL_ID . '/events?access_token=' . FB_ACCESS_TOKEN; + + $payload = [ + 'data' => [[ + 'event_name' => $eventName, + 'event_time' => time(), + 'action_source' => 'website', + 'user_data' => [ + 'client_ip_address' => getClientIP(), + 'client_user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '' + ], + 'custom_data' => $eventData + ]] + ]; + + return sendToWebhook($payload, $url); +} + +// ========================================== +// STORAGE FUNCTIONS +// ========================================== + +function storeLead($formData) { + $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_'), + 'datum' => date('d.m.Y'), + 'dienstleistung' => $formData['service'] ?? 'Allgemein', + 'status' => 'open', + 'statusText' => 'Offen', + 'description' => $formData['description'] ?? '', + 'name' => $formData['name'] ?? '', + 'contact' => $formData['contact'] ?? '', + 'organisation' => $formData['organisation'] ?? '', + 'timestamp' => date('c') + ]; + + 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($consentData) { + $consentFile = __DIR__ . '/data/cookie_consents.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) ?: []; + } + + // Remove existing consent for this IP + $ip = getClientIP(); + $consents = array_filter($consents, function($c) use ($ip) { + return ($c['ip_address'] ?? '') !== $ip; + }); + + $consentData['id'] = uniqid('consent_'); + $consentData['ip_address'] = $ip; + $consentData['timestamp'] = date('c'); + + array_unshift($consents, $consentData); + $consents = array_slice($consents, 0, 1000); + + file_put_contents($consentFile, json_encode($consents, JSON_PRETTY_PRINT)); +} + +function getCookieConsentByIP() { + $consentFile = __DIR__ . '/data/cookie_consents.json'; + + if (!file_exists($consentFile)) { + return null; + } + + $consents = json_decode(file_get_contents($consentFile), true) ?: []; + $ip = getClientIP(); + + foreach ($consents as $consent) { + if (($consent['ip_address'] ?? '') === $ip) { + return $consent; + } + } + + return 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', + 'ip_address' => getClientIP() + ]; + + $webhookResult = sendToWebhook($formData); + + if ($webhookResult['success']) { + storeLead($formData); + } + + sendResponse(true, 'Formular erfolgreich gesendet'); +} + +function handleLoginForm($data) { + $required = ['email', 'password']; + foreach ($required as $field) { + if (empty($data[$field])) { + sendResponse(false, "Pflichtfeld fehlt: {$field}", null, 400); + } + } + + $formData = [ + 'email' => sanitizeInput($data['email']), + 'password' => $data['password'], // Don't sanitize password + 'remember' => $data['remember'] ?? false, + 'timestamp' => date('c'), + 'source' => 'login_form', + 'ip_address' => getClientIP() + ]; + + $webhookResult = sendToWebhook($formData); + + sendResponse(true, 'Anmeldung verarbeitet'); +} + +function handleRegisterForm($data) { + $required = ['name', 'email', 'password']; + foreach ($required as $field) { + if (empty($data[$field])) { + sendResponse(false, "Pflichtfeld fehlt: {$field}", null, 400); + } + } + + $formData = [ + 'name' => sanitizeInput($data['name']), + 'email' => sanitizeInput($data['email']), + 'password' => $data['password'], + 'company' => sanitizeInput($data['company'] ?? ''), + 'phone' => sanitizeInput($data['phone'] ?? ''), + 'timestamp' => date('c'), + 'source' => 'register_form', + 'ip_address' => getClientIP() + ]; + + $webhookResult = sendToWebhook($formData); + + sendResponse(true, 'Registrierung erfolgreich'); +} + +function handleLeadForm($data) { + $formData = [ + 'lead_data' => $data, + 'timestamp' => date('c'), + 'source' => 'lead_form', + 'ip_address' => getClientIP() + ]; + + $webhookResult = sendToWebhook($formData); + + sendResponse(true, 'Lead erfolgreich gesendet'); +} + +function handleCookieConsent($data) { + if (empty($data['preferences'])) { + sendResponse(false, 'Preferences fehlen', null, 400); + } + + $consentData = [ + 'hasConsented' => true, + 'preferences' => $data['preferences'], + 'source' => 'cookie_consent' + ]; + + storeCookieConsent($consentData); + + // Get tracking scripts based on consent + $scripts = loadTrackingScripts($data['preferences']); + + // Send consent event to webhook + $webhookData = [ + 'event_type' => 'cookie_consent_update', + 'preferences' => $data['preferences'], + 'timestamp' => date('c'), + 'ip_address' => getClientIP() + ]; + sendToWebhook($webhookData); + + sendResponse(true, 'Cookie-Einstellungen gespeichert', ['scripts' => $scripts]); +} + +function handleGetCookieConsent($data) { + $consent = getCookieConsentByIP(); + + if ($consent) { + // Get tracking scripts based on saved consent + $scripts = []; + if (!empty($consent['preferences'])) { + $scripts = loadTrackingScripts($consent['preferences']); + } + + sendResponse(true, 'Consent gefunden', [ + 'hasConsented' => $consent['hasConsented'] ?? false, + 'preferences' => $consent['preferences'] ?? [], + 'scripts' => $scripts + ]); + } else { + sendResponse(false, 'Kein Consent gefunden', null, 404); + } +} + +function handleGetTrackingConfig($data) { + $config = getTrackingConfig(); + sendResponse(true, 'Tracking-Konfiguration', $config); +} + +function handleTrackEvent($data) { + if (empty($data['event_name'])) { + sendResponse(false, 'Event name fehlt', null, 400); + } + + $preferences = $data['preferences'] ?? ['analytics' => false, 'marketing' => false]; + $results = trackEvent($data['event_name'], $data['event_data'] ?? [], $preferences); + + sendResponse(true, 'Event getrackt', $results); +} + +// ========================================== +// 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()); + sendResponse(false, 'Interner Serverfehler', null, 500); +} +?> \ No newline at end of file diff --git a/Profice WebSite/scripts/cookie-consent.js b/Profice WebSite/scripts/cookie-consent.js new file mode 100644 index 0000000..6f7177d --- /dev/null +++ b/Profice WebSite/scripts/cookie-consent.js @@ -0,0 +1,423 @@ +/** + * 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(); +}); diff --git a/Profice WebSite/scripts/cursor.js b/Profice WebSite/scripts/cursor.js new file mode 100644 index 0000000..d51d316 --- /dev/null +++ b/Profice WebSite/scripts/cursor.js @@ -0,0 +1,210 @@ +// 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(); +}); \ No newline at end of file diff --git a/Profice WebSite/scripts/details.js b/Profice WebSite/scripts/details.js new file mode 100644 index 0000000..5aa0f81 --- /dev/null +++ b/Profice WebSite/scripts/details.js @@ -0,0 +1,124 @@ +// details.js + +document.addEventListener("DOMContentLoaded", function() { + const serviceDetails = { + 'seo-optimierung': { + title: 'SEO Optimierung', + icon: '🔍', + description: 'Verbessern Sie Ihre Sichtbarkeit in Suchmaschinen und erreichen Sie mehr Kunden online.', + fullDescription: 'Unsere SEO-Optimierungsdienste helfen Ihnen, in Suchmaschinen besser gefunden zu werden. Wir analysieren Ihre Website, identifizieren Optimierungspotenziale und implementieren bewährte Strategien, um Ihr Ranking zu verbessern und mehr qualifizierte Besucher anzuziehen.', + features: [ + 'Keyword-Analyse und -Recherche', + 'On-Page Optimierung', + 'Technische SEO-Audits', + 'Content-Strategie', + 'Link-Building', + 'Performance-Tracking' + ], + benefits: [ + 'Höhere Sichtbarkeit in Suchmaschinen', + 'Mehr qualifizierte Besucher', + 'Verbesserte Conversion-Raten', + 'Langfristiger ROI' + ] + }, + 'cloud-migration': { + title: 'Cloud Migration', + icon: '☁️', + description: 'Modernisieren Sie Ihre IT-Infrastruktur mit sicheren und skalierbaren Cloud-Lösungen.', + fullDescription: 'Wir begleiten Sie bei der Migration Ihrer IT-Systeme in die Cloud. Von der Analyse Ihrer bestehenden Infrastruktur bis zur vollständigen Implementierung sorgen wir für einen reibungslosen Übergang mit minimalem Geschäftsausfall.', + features: [ + 'Infrastruktur-Analyse', + 'Migrationsplanung', + 'Datenübertragung', + 'Sicherheit & Compliance', + 'Performance-Optimierung', + 'Schulung & Support' + ], + benefits: [ + 'Kosteneinsparungen', + 'Bessere Skalierbarkeit', + 'Erhöhte Sicherheit', + 'Flexiblere Arbeitsweise' + ] + }, + 'datenanalyse': { + title: 'Datenanalyse', + icon: '📊', + description: 'Gewinnen Sie wertvolle Einblicke aus Ihren Daten mit unseren Analyse-Lösungen.', + fullDescription: 'Wir helfen Ihnen, Ihre Daten in wertvolle Erkenntnisse umzuwandeln. Mit modernen Analyse-Tools und -Methoden identifizieren wir Trends, Muster und Chancen, die Ihre Geschäftsentscheidungen verbessern.', + features: [ + 'Datenerfassung & -bereinigung', + 'Statistische Analyse', + 'Visualisierung & Dashboards', + 'Predictive Analytics', + 'Berichterstellung', + 'Consulting' + ], + benefits: [ + 'Bessere Entscheidungen', + 'Prozessoptimierung', + 'Kostensenkungen', + 'Wettbewerbsvorteile' + ] + } + }; + + const urlParams = new URLSearchParams(window.location.search); + const serviceId = urlParams.get('service'); + const detailsContainer = document.getElementById('service-details'); + + if (serviceId && serviceDetails[serviceId]) { + const service = serviceDetails[serviceId]; + + detailsContainer.innerHTML = ` +
+
${service.icon}
+

${service.title}

+

${service.description}

+
+ +
+
+

Beschreibung

+

${service.fullDescription}

+
+ +
+

Unsere Leistungen

+
    + ${service.features.map(feature => `
  • ${feature}
  • `).join('')} +
+
+ +
+

Ihre Vorteile

+
    + ${service.benefits.map(benefit => `
  • ${benefit}
  • `).join('')} +
+
+ +
+

Interesse?

+

Kontaktieren Sie uns für eine persönliche Beratung und ein maßgeschneidertes Angebot.

+ +
+
+ `; + + // Update page title + document.title = `Profice - ${service.title}`; + } else { + // Fallback if no service specified + detailsContainer.innerHTML = ` +
+

Service nicht gefunden

+

Der angeforderte Service konnte nicht gefunden werden.

+ Zurück zum Dashboard +
+ `; + } +}); diff --git a/Profice WebSite/scripts/lead-details.js b/Profice WebSite/scripts/lead-details.js new file mode 100644 index 0000000..2c35d5b --- /dev/null +++ b/Profice WebSite/scripts/lead-details.js @@ -0,0 +1,203 @@ +// lead-details.js + +document.addEventListener("DOMContentLoaded", function() { + const urlParams = new URLSearchParams(window.location.search); + const leadId = urlParams.get('id'); + const detailsContainer = document.getElementById('leadDetailsContent'); + + function getLeads() { + const storedLeads = localStorage.getItem('myLeads'); + if (storedLeads) { + return JSON.parse(storedLeads); + } else { + return []; + } + } + + function getStatusClass(status) { + const statusClasses = { + 'neu': 'status-new', + 'in-bearbeitung': 'status-in-progress', + 'abgeschlossen': 'status-completed', + 'storniert': 'status-cancelled' + }; + return statusClasses[status] || 'status-new'; + } + + function formatDate(dateString) { + const date = new Date(dateString); + return date.toLocaleDateString('de-DE', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + } + + if (leadId && detailsContainer) { + const leadsData = getLeads(); + const lead = leadsData.find(l => l.id == leadId); + + if (lead) { + detailsContainer.innerHTML = ` +
+ +
+

Status

+
+ ${lead.statusText} +

Letzte Aktualisierung: ${formatDate(lead.datum)}

+
+
+ + +
+

Kontaktinformationen

+
+
+
Name
+
${lead.name || 'Nicht angegeben'}
+
+
+
Organisation
+
${lead.organisation || 'Nicht angegeben'}
+
+
+
Kontakt
+
${lead.contact || 'Nicht angegeben'}
+
+
+
Budget
+
${lead.budget || 'Nicht angegeben'}
+
+
+
+ + +
+

Dienstleistung

+
+
${getServiceIcon(lead.dienstleistung)}
+
+

${lead.dienstleistung}

+

${getServiceDescription(lead.dienstleistung)}

+
+
+
+ + + ${lead.description ? ` +
+

Projektbeschreibung

+
+

${lead.description}

+
+
+ ` : ''} + + +
+

Zeitstrahl

+
+
+
+
+

Anfrage erhalten

+

${formatDate(lead.datum)}

+
+
+
+
+
+

In Bearbeitung

+

${lead.status !== 'neu' ? 'Anfrage wird bearbeitet' : 'Ausstehend'}

+
+
+
+
+
+

Abgeschlossen

+

${lead.status === 'abgeschlossen' ? 'Projekt erfolgreich abgeschlossen' : 'Ausstehend'}

+
+
+
+
+ + +
+

Aktionen

+
+ + + +
+
+
+ `; + + // Update page title + document.title = `Profice - Anfrage von ${lead.name || 'Unbekannt'}`; + } else { + detailsContainer.innerHTML = ` +
+

Anfrage nicht gefunden

+

Die angeforderte Anfrage konnte nicht gefunden werden.

+ Zurück zum Dashboard +
+ `; + } + } else { + detailsContainer.innerHTML = ` +
+

Keine Anfrage-ID angegeben

+

Bitte navigieren Sie über das Leads Dashboard zu den Details.

+ Zum Dashboard +
+ `; + } +}); + +function getServiceIcon(service) { + const icons = { + 'Website': '🌐', + 'KI Integration': '🤖', + 'Automatisation': '⚙️', + 'Unabhängige Wahl': '🎯' + }; + return icons[service] || '📋'; +} + +function getServiceDescription(service) { + const descriptions = { + 'Website': 'Moderne, responsive Webseiten, die konvertieren und Ihre Marke perfekt repräsentieren.', + 'KI Integration': 'Nutzen Sie die Kraft künstlicher Intelligenz, um Ihre Daten besser zu verstehen und Prozesse zu optimieren.', + 'Automatisation': 'Sparen Sie Zeit und Ressourcen durch intelligente Workflow-Automatisierungen.', + 'Unabhängige Wahl': 'Maßgeschneiderte Lösungen für Ihre spezifischen Anforderungen.' + }; + return descriptions[service] || 'Individuelle Dienstleistung.'; +} + +function shareLead() { + if (navigator.share) { + navigator.share({ + title: document.title, + text: 'Details meiner Projektanfrage bei Profice', + url: window.location.href + }); + } else { + // Fallback for browsers that don't support Web Share API + navigator.clipboard.writeText(window.location.href); + alert('Link wurde in die Zwischenablage kopiert!'); + } +} + +function exportLead() { + window.print(); +} diff --git a/Profice WebSite/scripts/leads.js b/Profice WebSite/scripts/leads.js new file mode 100644 index 0000000..18fb993 --- /dev/null +++ b/Profice WebSite/scripts/leads.js @@ -0,0 +1,75 @@ +// 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 = ` + + +

Keine Anfragen vorhanden

+ + + `; + return; + } + + tableBody.innerHTML = leadsData.map(lead => ` + + ${lead.datum} + ${lead.dienstleistung} + + ${lead.statusText} + + + Details ansehen + + + `).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); \ No newline at end of file diff --git a/Profice WebSite/scripts/login.js b/Profice WebSite/scripts/login.js new file mode 100644 index 0000000..60a5c8e --- /dev/null +++ b/Profice WebSite/scripts/login.js @@ -0,0 +1,217 @@ +// 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; +} diff --git a/Profice WebSite/scripts/register.js b/Profice WebSite/scripts/register.js new file mode 100644 index 0000000..5dda79a --- /dev/null +++ b/Profice WebSite/scripts/register.js @@ -0,0 +1,272 @@ +// 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'); + } + } +} diff --git a/Profice WebSite/scripts/script.js b/Profice WebSite/scripts/script.js new file mode 100644 index 0000000..a03fbae --- /dev/null +++ b/Profice WebSite/scripts/script.js @@ -0,0 +1,151 @@ +/** + * 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(); + }); + } +}); \ No newline at end of file diff --git a/Profice WebSite/scripts/scroll-header.js b/Profice WebSite/scripts/scroll-header.js new file mode 100644 index 0000000..7299505 --- /dev/null +++ b/Profice WebSite/scripts/scroll-header.js @@ -0,0 +1,83 @@ +// 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(); +}); diff --git a/Profice WebSite/sites/automatisation.html b/Profice WebSite/sites/automatisation.html new file mode 100644 index 0000000..9111066 --- /dev/null +++ b/Profice WebSite/sites/automatisation.html @@ -0,0 +1,213 @@ + + + + + + Profice - Automatisierung + + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+
+ +
+
⚙️
+

Automatisierung

+

Sparen Sie Zeit und Ressourcen durch intelligente Workflow-Automatisierungen

+
+ + +
+

Unsere Automatisierungslösungen

+

+ 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. +

+
+ + +
+

Was wir automatisieren können

+
+
+
📧
+

E-Mail-Automatisierung

+

Automatische Antwortverwaltung und E-Mail-Kampagnen

+
+
+
📄
+

Datenverarbeitung

+

Automatische Datenmigration und -bereinigung

+
+
+
📋
+

Report-Generierung

+

Automatische Erstellung von Berichten und Analysen

+
+
+
🔄
+

Workflow-Integration

+

Verbindung verschiedener Systeme für nahtlose Prozesse

+
+
+
📊
+

Monitoring

+

Automatische Systemüberwachung und Alarmierung

+
+
+
🎯
+

Task-Management

+

Intelligente Aufgabenverteilung und -verfolgung

+
+
+
+ + +
+

Unser Automatisierungsprozess

+
+
+
1
+
+

Prozessanalyse

+

Identifizierung von Automatisierungspotenzialen

+
+
+
+
2
+
+

Lösungsdesign

+

Entwicklung maßgeschneiderter Automatisierungslösungen

+
+
+
+
3
+
+

Implementierung

+

Setup und Konfiguration der Automatisierungstools

+
+
+
+
4
+
+

Testing

+

Gewissenhafte Tests vor der Live-Schaltung

+
+
+
+
5
+
+

Monitoring

+

Laufende Überwachung und Optimierung

+
+
+
+
+ + +
+

Automatisierungstechnologien

+
+
Zapier
+
+
+ + +
+

Ihre Vorteile

+
+
+
⏰️
+

Zeitersparnis

+

Bis zu 80% Zeitersparnis bei wiederkehrenden Aufgaben

+
+
+
🎯
+

Qualitätssteigerung

+

Reduzierung menschlicher Fehler und konsistente Ergebnisse

+
+
+
💰
+

Kostensenkung

+

Optimierung von Ressourcen und Betriebskosten

+
+
+
📈
+

Skalierbarkeit

+

Einfache Handhabung wachsender Geschäftsanforderungen

+
+
+
😊
+

Mitarbeiterzufriedenheit

+

Fokus auf kreative und strategische Aufgaben

+
+
+ + + +
+

Bereit für mehr Effizienz?

+

Lassen Sie uns Ihre Prozesse analysieren und Potenziale identifizieren.

+ +
+ +
+ + + + + + diff --git a/Profice WebSite/sites/details.html b/Profice WebSite/sites/details.html new file mode 100644 index 0000000..8fb2e55 --- /dev/null +++ b/Profice WebSite/sites/details.html @@ -0,0 +1,76 @@ + + + + + + Profice - Service Details + + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+ +
+ + + + + + + diff --git a/Profice WebSite/sites/ki-integration.html b/Profice WebSite/sites/ki-integration.html new file mode 100644 index 0000000..77f9ba1 --- /dev/null +++ b/Profice WebSite/sites/ki-integration.html @@ -0,0 +1,217 @@ + + + + + + Profice - KI Integration + + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+
+ +
+
🤖
+

KI Integration

+

Nutzen Sie die Kraft künstlicher Intelligenz, um Ihre Daten besser zu verstehen und Prozesse zu optimieren

+
+ + +
+

Unsere KI-Dienstleistungen

+

+ 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. +

+
+ + +
+

Was wir bieten

+
+
+
📊
+

Datenanalyse

+

Intelligente Auswertung Ihrer Geschäftsdaten für bessere Entscheidungen

+
+
+
🤖
+

Chatbots

+

24/7 Kundenbetreuung und automatisierte Kommunikation

+
+
+
⚙️
+

Prozessautomatisierung

+

Automatisierung wiederkehrender Aufgaben zur Effizienzsteigerung

+
+
+
🔍
+

Bilderkennung

+

Automatische Analyse von Bildern und Dokumenten

+
+
+
📈
+

Vorhersagemodelle

+

Prognosen für Trends und Geschäftsentwicklungen

+
+
+
🎯
+

Personalisierung

+

Individuelle KI-Lösungen für Ihre spezifischen Bedürfnisse

+
+
+
+ + +
+

Unser KI-Integrationsprozess

+
+
+
1
+
+

Analyse & Potenzial

+

Identifizierung von KI-Einsatzmöglichkeiten in Ihrem Unternehmen

+
+
+
+
2
+
+

Datenstrategie

+

Planung der Datenerfassung und -verarbeitung

+
+
+
+
3
+
+

Modellentwicklung

+

Training oder Auswahl passender KI-Modelle

+
+
+
+
4
+
+

Integration

+

Nahtlose Anbindung an Ihre bestehenden Systeme

+
+
+
+
5
+
+

Optimierung

+

Kontinuierliche Verbesserung der KI-Modelle

+
+
+
+
+ + +
+

KI-Technologien

+
+
TensorFlow
+
PyTorch
+
Scikit-learn
+
OpenAI API
+
Google Cloud AI
+
Azure ML
+
AWS SageMaker
+
Hugging Face
+
LangChain
+
Dialogflow
+
+
+ + +
+

Anwendungsfälle

+
+
+

Kundenservice

+

Intelligente Chatbots für 24/7 Unterstützung

+
+
+

Vertrieb

+

Predictive Lead Scoring und Verkaufsoptimierung

+
+
+

Marketing

+

Personalisierte Kampagnen und Content-Optimierung

+
+
+

Finanzen

+

Betrugsprüfung und Risikoanalyse

+
+
+

Produktion

+

Qualitätssicherung und Predictive Maintenance

+
+
+
+ + +
+

Bereit für KI in Ihrem Unternehmen?

+

Lassen Sie uns die Potenziale für Ihr Unternehmen analysieren.

+ +
+
+
+ + + + + + diff --git a/Profice WebSite/sites/lead-details.html b/Profice WebSite/sites/lead-details.html new file mode 100644 index 0000000..efd5a52 --- /dev/null +++ b/Profice WebSite/sites/lead-details.html @@ -0,0 +1,87 @@ + + + + + + Profice - Anfrage Details + + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+
+ +
+
📋
+

Anfrage Details

+

Alle Informationen zu Ihrer Projektanfrage

+
+ + +
+ +
+ + + +
+
+ + + + + + + diff --git a/Profice WebSite/sites/leads.html b/Profice WebSite/sites/leads.html new file mode 100644 index 0000000..78cfd8b --- /dev/null +++ b/Profice WebSite/sites/leads.html @@ -0,0 +1,117 @@ + + + + + + Profice - Leads Dashboard + + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+ +
+

Meine Anfragen

+

Übersicht Ihrer aktuellen Projektanfragen

+ +
+ + + + + + + + + + + + +
DatumDienstleistungStatusAktion
+
+
+ + +
+

Andere Angebote von uns

+

Entdecken Sie weitere Dienstleistungen

+ +
+
+
🔍
+

SEO Optimierung

+

Verbessern Sie Ihre Sichtbarkeit in Suchmaschinen und erreichen Sie mehr Kunden online.

+ Details ansehen +
+ +
+
☁️
+

Cloud Migration

+

Modernisieren Sie Ihre IT-Infrastruktur mit sicheren und skalierbaren Cloud-Lösungen.

+ Details ansehen +
+ +
+
📊
+

Datenanalyse

+

Gewinnen Sie wertvolle Einblicke aus Ihren Daten mit unseren Analyse-Lösungen.

+ Details ansehen +
+
+
+
+ + + + + + diff --git a/Profice WebSite/sites/login.html b/Profice WebSite/sites/login.html new file mode 100644 index 0000000..67c8da8 --- /dev/null +++ b/Profice WebSite/sites/login.html @@ -0,0 +1,138 @@ + + + + + + Profice - Anmeldung + + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+ +
+ + + + + + + diff --git a/Profice WebSite/sites/offers.html b/Profice WebSite/sites/offers.html new file mode 100644 index 0000000..16a42c3 --- /dev/null +++ b/Profice WebSite/sites/offers.html @@ -0,0 +1,114 @@ + + + + + + Profice + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+
+

Kontaktieren Sie uns

+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ +
+

Vielen Dank!

+

Ihre Anfrage wurde erfolgreich gesendet. Wir melden uns bald bei Ihnen.

+
+
+
+ + + + + + \ No newline at end of file diff --git a/Profice WebSite/sites/register.html b/Profice WebSite/sites/register.html new file mode 100644 index 0000000..df45d01 --- /dev/null +++ b/Profice WebSite/sites/register.html @@ -0,0 +1,174 @@ + + + + + + Registrierung - Profice + + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+ +
+ + + + + + + diff --git a/Profice WebSite/sites/website.html b/Profice WebSite/sites/website.html new file mode 100644 index 0000000..996b65f --- /dev/null +++ b/Profice WebSite/sites/website.html @@ -0,0 +1,191 @@ + + + + + + Profice - Website Entwicklung + + + + + + +
+
+ +
+ +
+ + +
+
+ + + + + +
+ + +
+
+ +
+
🌐
+

Website Entwicklung

+

Moderne, responsive Webseiten, die konvertieren und Ihre Marke perfekt repräsentieren

+
+ + +
+

Unsere Webentwicklungsdienstleistungen

+

+ 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. +

+
+ + +
+

Was wir bieten

+
+
+
🎨
+

Responsive Design

+

Perfekte Darstellung auf allen Geräten - von Desktop bis Mobile

+
+
+
+

Performance-Optimierung

+

Schnelle Ladezeiten und beste Nutzererfahrung

+
+
+
🔒
+

SEO-Freundlich

+

Technische Grundlagen für gute Suchmaschinenplatzierungen

+
+
+
🔧
+

CMS-Integration

+

Einfache Content-Verwaltung für Ihre Mitarbeiter

+
+
+
🛡️
+

Sicherheit

+

Schutz vor Bedrohungen und sichere Datenverarbeitung

+
+
+
📊
+

Analytics & Tracking

+

Detaillierte Auswertung Ihrer Website-Performance

+
+
+
+ + +
+

Unser Prozess

+
+
+
1
+
+

Analyse & Konzeption

+

Wir verstehen Ihre Ziele und entwickeln eine passende Strategie

+
+
+
+
2
+
+

Design & Prototyping

+

Visuelle Konzepte und interaktive Prototypen

+
+
+
+
3
+
+

Entwicklung

+

Saubere, performante Code-Implementierung

+
+
+
+
4
+
+

Testing & Launch

+

Gewissenhafte Tests und erfolgreicher Start

+
+
+
+
5
+
+

Support & Wartung

+

Laufende Optimierung und technische Unterstützung

+
+
+
+
+ + +
+

Technologien

+
+
HTML5
+
CSS3
+
JavaScript
+
React
+
Vue.js
+
Angular
+
Node.js
+
PHP
+
WordPress
+
Shopify
+
WooCommerce
+
+
+ + +
+

Bereit für Ihre neue Website?

+

Lassen Sie uns Ihr Projekt an und wir erstellen ein maßgeschneidertes Angebot.

+ +
+
+
+ + + + + + diff --git a/Profice WebSite/style/cookie-consent.css b/Profice WebSite/style/cookie-consent.css new file mode 100644 index 0000000..4cefaca --- /dev/null +++ b/Profice WebSite/style/cookie-consent.css @@ -0,0 +1,307 @@ +/* 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; + } +} diff --git a/Profice WebSite/style/cursor.css b/Profice WebSite/style/cursor.css new file mode 100644 index 0000000..f757c04 --- /dev/null +++ b/Profice WebSite/style/cursor.css @@ -0,0 +1,98 @@ +/* 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); +} \ No newline at end of file diff --git a/Profice WebSite/style/design.css b/Profice WebSite/style/design.css new file mode 100644 index 0000000..6d689e6 --- /dev/null +++ b/Profice WebSite/style/design.css @@ -0,0 +1,1042 @@ +:root { + --primary-dark: #4F4747; + --primary-light: #EBEBDE; + --primary-mid: #777764; + --accent-orange: #F57C00; + --accent-teal: #26A69A; + --accent-green: #66BB6A; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +body { + background-color: var(--primary-light); + color: var(--primary-dark); + min-height: 100vh; +} + +/* Top Banner */ +.top-banner { + background-color: var(--primary-light); + color: var(--primary-dark); + padding: 5px 40px; + height: 90px; + display: flex; + align-items: center; + justify-content: space-between; + position: sticky; + top: 0; + z-index: 1001; + border-bottom: 1px solid #4f47471a; + transition: height 0.25s cubic-bezier(0.4, 0, 0.2, 1), + padding 0.25s cubic-bezier(0.4, 0, 0.2, 1); + will-change: height, padding; + transform: translateZ(0); + backface-visibility: hidden; + contain: layout style paint; +} + +.top-banner-left { + display: flex; + align-items: center; + flex: 1; +} + +.top-banner-center { + display: flex; + justify-content: center; + flex: 2; +} + +.top-banner-right { + display: flex; + justify-content: flex-end; + flex: 1; +} + +.top-banner.scrolled { + padding: 2px 30px; + height: 60px; +} + +.top-banner.scrolled .menu-toggle, +.top-banner.scrolled #cursorToggle { + width: 35px; + height: 35px; +} + +.top-banner.scrolled .opening-hours { + font-size: 12px; + padding: 8px 15px; +} + +.banner-left { + display: flex; + align-items: center; + gap: 15px; +} + +.banner-left #cursorToggle { + margin-right: 15px; +} + +.search-container { + display: flex; + align-items: center; + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 25px; + padding: 8px 8px 8px 15px; + transition: all 0.3s ease; + order: 1; + width: 250px; +} + +.search-container:hover { + background: rgba(255, 255, 255, 0.15); + border-color: rgba(255, 255, 255, 0.3); +} + +.search-container form { + display: flex; + align-items: center; + width: 100%; +} + +.search-field { + background: transparent; + border: none; + color: white; + font-size: 14px; + width: 100%; + outline: none; + padding: 0; + margin-right: 8px; +} + +.search-field::placeholder { + color: rgba(255, 255, 255, 0.7); +} + +.search-field:focus::placeholder { + color: rgba(255, 255, 255, 0.5); +} + +.search-btn { + background: rgba(255, 255, 255, 0.2); + border: none; + color: white; + cursor: pointer; + padding: 6px; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.3s ease; + border-radius: 50%; + flex-shrink: 0; +} + +.search-btn:hover { + background: rgba(255, 255, 255, 0.3); +} + +.search-container { + display: flex; + align-items: center; + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 25px; + padding: 8px 8px 8px 15px; + transition: all 0.3s ease; + order: 1; + width: 250px; +} + +.search-container:hover { + background: rgba(255, 255, 255, 0.15); + border-color: rgba(255, 255, 255, 0.3); +} + +.search-container form { + display: flex; + align-items: center; + width: 100%; +} + +.search-field { + background: transparent; + border: none; + color: white; + font-size: 14px; + width: 100%; + outline: none; + padding: 0; + margin-right: 8px; +} + +.search-field::placeholder { + color: rgba(255, 255, 255, 0.7); +} + +.search-field:focus::placeholder { + color: rgba(255, 255, 255, 0.5); +} + +.search-btn { + background: rgba(255, 255, 255, 0.2); + border: none; + color: white; + cursor: pointer; + padding: 6px; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.3s ease; + border-radius: 50%; + flex-shrink: 0; +} + +.search-btn:hover { + background: rgba(255, 255, 255, 0.3); +} + +.main-nav { + display: flex; + align-items: center; + gap: 25px; +} + +.nav-link { + text-decoration: none; + color: white; + font-weight: 500; + font-size: 18px; + padding: 8px 12px; + border-radius: 8px; + transition: color 0.3s ease, transform 0.2s ease, background 0.3s ease; + position: relative; +} + +.nav-link:hover { + color: white; + transform: translateY(-2px); + background: rgba(255, 255, 255, 0.1); +} + +.nav-link::after { + content: ''; + position: absolute; + bottom: -5px; + left: 0; + width: 0; + height: 2px; + background: var(--accent-teal); + transition: width 0.3s ease; +} + +.nav-link:hover::after { + width: 100%; +} + +.logo-link { + text-decoration: none; + display: flex; + align-items: center; + gap: 0; + margin-left: 0; + margin-right: 15px; +} + +.logo { + height: 50px; + width: auto; + transition: height 0.25s cubic-bezier(0.4, 0, 0.2, 1); + will-change: height; +} + +.top-banner.scrolled .logo { + height: 35px; +} + +.opening-hours { + font-size: 14px; + color: var(--primary-mid); + background: rgba(79, 71, 71, 0.08); + padding: 10px 20px; + border-radius: 25px; + transition: font-size 0.25s cubic-bezier(0.4, 0, 0.2, 1), padding 0.25s cubic-bezier(0.4, 0, 0.2, 1); + will-change: font-size, padding; +} + +.menu-toggle { + background: transparent; + border: 2px solid var(--primary-dark); + color: var(--primary-dark); + width: 45px; + height: 45px; + border-radius: 12px; + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 5px; + transition: background 0.3s ease, color 0.3s ease, width 0.25s cubic-bezier(0.4, 0, 0.2, 1), height 0.25s cubic-bezier(0.4, 0, 0.2, 1); + will-change: width, height; +} + +#cursorToggle { + background: transparent; + border: 2px solid var(--primary-dark); + color: var(--primary-dark); + width: 60px; + height: 60px; + border-radius: 12px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1), height 0.25s cubic-bezier(0.4, 0, 0.2, 1), background 0.3s ease, border-color 0.3s ease; + will-change: width, height; +} + +.cursor-icon { + width: 60px; + height: 60px; + object-fit: contain; + transition: opacity 0.3s ease; + opacity: 1 !important; + filter: none !important; +} + +#cursorToggle:hover { + background: var(--primary-dark); +} + +#cursorToggle:hover .cursor-icon { + filter: brightness(0) invert(1) !important; + opacity: 1 !important; +} + +.menu-toggle:hover { + background: var(--primary-dark); +} + +.menu-toggle:hover span { + background: var(--primary-light); +} + +.menu-toggle span { + display: block; + width: 20px; + height: 2px; + background: var(--primary-dark); + border-radius: 2px; + transition: all 0.3s ease; +} + +.menu-toggle.active { + background: var(--primary-dark); +} + +.menu-toggle.active span { + background: var(--primary-light); +} + +.menu-toggle.active span:nth-child(1) { + transform: rotate(45deg) translate(5px, 5px); +} + +.menu-toggle.active span:nth-child(2) { + opacity: 0; +} + +.menu-toggle.active span:nth-child(3) { + transform: rotate(-45deg) translate(5px, -5px); +} + +/* Slide Menu */ +.slide-menu { + position: fixed; + top: 110px; + left: -280px; + width: 280px; + background: white; + box-shadow: 4px 0 25px rgba(79, 71, 71, 0.15); + border-radius: 0 20px 20px 0; + padding: 30px 0; + transition: left 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), top 0.3s ease; + z-index: 1000; +} + +.top-banner.scrolled ~ .slide-menu, +.top-banner.scrolled + .overlay + .slide-menu { + top: 80px; +} + +.slide-menu.active { + left: 0; +} + +.slide-menu a { + display: block; + padding: 18px 30px; + color: var(--primary-dark); + text-decoration: none; + font-size: 17px; + font-weight: 500; + transition: all 0.3s ease; + border-left: 4px solid transparent; +} + +.slide-menu a:hover { + background: var(--primary-light); + border-left-color: var(--accent-teal); + padding-left: 40px; + color: var(--accent-teal); +} + +.slide-menu a.active { + background: var(--primary-light); + border-left-color: var(--accent-teal); + color: var(--accent-teal); +} + +/* Main Content */ +.main-content { + max-width: 700px; + margin: 50px auto; + padding: 110px 20px 20px 20px; + transition: padding-top 0.2s ease-out; +} + +.form-container { + background: white; + padding: 45px; + border-radius: 24px; + box-shadow: 0 15px 50px rgba(79, 71, 71, 0.1); +} + +.form-title { + color: var(--primary-dark); + font-size: 28px; + margin-bottom: 35px; + text-align: center; + font-weight: 600; +} + +.form-group { + margin-bottom: 24px; +} + +.form-group label { + display: block; + margin-bottom: 8px; + color: var(--primary-mid); + font-weight: 500; + font-size: 14px; +} + +.form-group input, +.form-group textarea, +.form-group select { + width: 100%; + padding: 14px 18px; + border: 2px solid rgba(119, 119, 100, 0.2); + border-radius: 14px; + font-size: 16px; + transition: all 0.3s ease; + background: var(--primary-light); + color: var(--primary-dark); +} + +.form-group input:focus, +.form-group textarea:focus, +.form-group select:focus { + outline: none; + border-color: var(--accent-teal); + background: white; + box-shadow: 0 0 0 4px rgba(38, 166, 154, 0.15); +} + +.form-group textarea { + min-height: 120px; + resize: vertical; +} + +.form-group select { + cursor: pointer; + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%234F4747' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 14px center; + background-size: 18px; +} + +.submit-btn { + width: 100%; + padding: 16px; + background: var(--accent-teal); + color: white; + border: none; + border-radius: 25px; + font-size: 17px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + text-transform: uppercase; + letter-spacing: 1px; +} + +.submit-btn:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(38, 166, 154, 0.35); + background: #1e8e82; +} + +.submit-btn:active { + transform: translateY(0); +} + +/* Login Button Styles */ +.login-btn { + 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; + position: relative; + z-index: 10; + pointer-events: auto; +} + +.login-btn:hover { + background: white; + color: var(--primary-dark); + 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); +} + +/* Top Banner Right Layout */ +.top-banner-right { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 15px; + flex: 1; + position: relative; + z-index: 10; +} + +/* Service Details Buttons */ +.service-details { + display: flex; + gap: 15px; + margin-top: 15px; + flex-wrap: wrap; + justify-content: center; +} + +.service-btn { + padding: 12px 24px; + background: var(--accent-teal); + color: white; + text-decoration: none; + border-radius: 25px; + font-size: 14px; + font-weight: 500; + transition: all 0.3s ease; + display: inline-block; +} + +.service-btn:hover { + background: white; + color: var(--accent-teal); + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(38, 166, 154, 0.3); +} + +/* Success Message */ +.success-message { + display: none; + text-align: center; + padding: 30px; + color: var(--accent-teal); +} + +.success-message.show { + display: block; +} + +.success-message h3 { + font-size: 24px; + margin-bottom: 10px; +} + +/* Overlay */ +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(79, 71, 71, 0.3); + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + z-index: 999; +} + +.overlay.active { + opacity: 1; + visibility: visible; +} + +@media (max-width: 600px) { + .top-banner { + flex-direction: column; + gap: 15px; + text-align: center; + padding: 15px 20px; + } + + .banner-left { + width: 100%; + justify-content: center; + } + + .form-container { + padding: 25px; + } + + .logo { + height: 100px; + width: auto; + } +} + +/* ADDITIONS FOR HOME PAGE & DARK HEADER */ + + +/* 1. Dark Header Theme */ +.top-banner.dark-theme { + background-color: var(--primary-dark); + color: var(--primary-light); + border-bottom: 1px solid rgba(235, 235, 222, 0.1); +} + +.top-banner.dark-theme .company-name { + color: var(--primary-light); +} + +.top-banner.dark-theme .opening-hours { + background: rgba(235, 235, 222, 0.1); + color: var(--primary-light); +} + +.top-banner.dark-theme .menu-toggle { + border-color: var(--primary-light); +} + +.top-banner.dark-theme .menu-toggle span { + background: var(--primary-light); +} + +.top-banner.dark-theme .menu-toggle:hover { + background: var(--primary-light); +} + +.top-banner.dark-theme .menu-toggle:hover span { + background: var(--primary-dark); +} + +/* 2. Home Page Layout */ +.home-content { + max-width: 1200px; + margin: 0 auto; + padding: 110px 20px 20px 20px; + transition: padding-top 0.2s ease-out; +} + +/* Hero Section */ +.hero-section { + display: flex; + align-items: center; + justify-content: space-between; + padding: 80px 20px; + gap: 40px; + min-height: 80vh; +} + +.hero-text { + flex: 1; + max-width: 600px; +} + +.hero-text h1 { + font-size: 48px; + line-height: 1.2; + margin-bottom: 24px; + color: var(--primary-dark); + font-weight: 700; +} + +.hero-text p { + font-size: 18px; + line-height: 1.6; + margin-bottom: 35px; + color: var(--primary-mid); +} + +.hero-buttons { + display: flex; + gap: 15px; +} + +.cta-btn { + padding: 15px 30px; + border-radius: 30px; + font-size: 16px; + font-weight: 600; + text-decoration: none; + transition: all 0.3s ease; +} + +.cta-btn.primary { + background-color: var(--accent-teal); + color: white; + border: 2px solid var(--accent-teal); +} + +.cta-btn.primary:hover { + background-color: #1e8e82; + border-color: #1e8e82; + transform: translateY(-2px); + box-shadow: 0 10px 20px rgba(38, 166, 154, 0.2); +} + +.cta-btn.secondary { + background-color: transparent; + color: var(--primary-dark); + border: 2px solid var(--primary-dark); +} + +.cta-btn.secondary:hover { + background-color: var(--primary-dark); + color: var(--primary-light); +} + +.hero-image-placeholder { + flex: 1; + height: 400px; + background-color: rgba(119, 119, 100, 0.1); + border-radius: 24px; + display: flex; + align-items: center; + justify-content: center; + border: 2px dashed var(--primary-mid); + color: var(--primary-mid); +} + +/* Services Section */ +.services-section { + padding: 60px 20px; + margin-bottom: 60px; +} + +.section-title { + text-align: center; + font-size: 32px; + color: var(--primary-dark); + margin-bottom: 50px; +} + +.services-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 30px; +} + +.service-card { + background: white; + padding: 40px; + border-radius: 24px; + box-shadow: 0 15px 50px rgba(79, 71, 71, 0.05); + transition: transform 0.3s ease; + text-align: center; +} + +.service-card:hover { + transform: translateY(-10px); +} + +.service-icon { + font-size: 48px; + margin-bottom: 20px; + color: var(--accent-teal); +} + +.service-card h3 { + font-size: 22px; + color: var(--primary-dark); + margin-bottom: 15px; +} + +.service-card p { + color: var(--primary-mid); + line-height: 1.6; +} + +/* Info Section */ +.info-section { + background-color: white; + padding: 80px 40px; + border-radius: 24px; + margin-bottom: 80px; + box-shadow: 0 15px 50px rgba(79, 71, 71, 0.05); +} + +.info-container { + display: flex; + align-items: center; + gap: 50px; +} + +.info-content { + flex: 1; +} + +.info-content h2 { + font-size: 32px; + color: var(--primary-dark); + margin-bottom: 20px; +} + +.info-content p { + color: var(--primary-mid); + font-size: 17px; + line-height: 1.6; + margin-bottom: 30px; +} + +.info-list { + list-style: none; +} + +.info-list li { + margin-bottom: 15px; + padding-left: 30px; + position: relative; + color: var(--primary-dark); + font-weight: 500; +} + +.info-list li::before { + content: "✓"; + position: absolute; + left: 0; + color: var(--accent-green); + font-weight: bold; +} + +.info-image-placeholder { + flex: 1; + height: 300px; + background-color: var(--primary-light); + border-radius: 16px; + display: flex; + align-items: center; + justify-content: center; + border: 2px dashed var(--primary-mid); + color: var(--primary-mid); +} + +/* Enterprise Section */ +.enterprise-section { + padding: 80px 20px; + background: white; + text-align: center; +} + +.enterprise-content { + max-width: 800px; + margin: 0 auto; +} + +.enterprise-features { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 30px; + margin-top: 50px; +} + +.feature-item { + background: var(--primary-light); + padding: 30px; + border-radius: 16px; + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.feature-item:hover { + transform: translateY(-5px); + box-shadow: 0 10px 30px rgba(79, 71, 71, 0.1); +} + +.feature-item h3 { + color: var(--accent-teal); + margin-bottom: 15px; + font-size: 20px; +} + +.feature-item p { + color: var(--primary-mid); + line-height: 1.6; +} + +/* Pricing Section */ +.pricing-section { + padding: 80px 20px; + background: var(--primary-light); + text-align: center; +} + +.pricing-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 30px; + max-width: 1000px; + margin: 50px auto 0; +} + +.pricing-card { + background: white; + padding: 40px 30px; + border-radius: 16px; + box-shadow: 0 5px 20px rgba(79, 71, 71, 0.1); + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.pricing-card:hover { + transform: translateY(-5px); + box-shadow: 0 15px 40px rgba(79, 71, 71, 0.15); +} + +.pricing-card.featured { + border: 2px solid var(--accent-teal); + transform: scale(1.05); +} + +.pricing-card h3 { + color: var(--primary-dark); + font-size: 24px; + margin-bottom: 20px; +} + +.price { + font-size: 36px; + font-weight: bold; + color: var(--accent-teal); + margin-bottom: 15px; +} + +.pricing-card p { + color: var(--primary-mid); + margin-bottom: 25px; +} + +.pricing-card ul { + list-style: none; + text-align: left; +} + +.pricing-card li { + padding: 8px 0; + border-bottom: 1px solid rgba(119, 119, 100, 0.1); + color: var(--primary-dark); +} + +.pricing-card li:before { + content: "✓ "; + color: var(--accent-teal); + font-weight: bold; + margin-right: 8px; +} + +/* Responsive Home */ +@media (max-width: 900px) { + .hero-section { + flex-direction: column; + text-align: center; + padding-top: 40px; + } + + .hero-text h1 { + font-size: 36px; + } + + .hero-buttons { + justify-content: center; + } + + .info-container { + flex-direction: column-reverse; + } + + .hero-image-placeholder, + .info-image-placeholder { + width: 100%; + } +} + +/* Navigation responsive */ +@media (max-width: 768px) { + .main-nav { + display: none; + } + + .top-banner { + justify-content: space-between; + } + + .banner-left { + flex: 1; + } + + .opening-hours { + display: none; + } +} \ No newline at end of file diff --git a/Profice WebSite/style/details.css b/Profice WebSite/style/details.css new file mode 100644 index 0000000..2e13d8c --- /dev/null +++ b/Profice WebSite/style/details.css @@ -0,0 +1,151 @@ +/* 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; + } +} diff --git a/Profice WebSite/style/lead-details.css b/Profice WebSite/style/lead-details.css new file mode 100644 index 0000000..51ee4ae --- /dev/null +++ b/Profice WebSite/style/lead-details.css @@ -0,0 +1,408 @@ +/* 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; + } +} diff --git a/Profice WebSite/style/leads.css b/Profice WebSite/style/leads.css new file mode 100644 index 0000000..017cc0c --- /dev/null +++ b/Profice WebSite/style/leads.css @@ -0,0 +1,219 @@ +/* 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; + } +} diff --git a/Profice WebSite/style/login.css b/Profice WebSite/style/login.css new file mode 100644 index 0000000..f877ec7 --- /dev/null +++ b/Profice WebSite/style/login.css @@ -0,0 +1,547 @@ +/* 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; + } +} diff --git a/Profice WebSite/style/service.css b/Profice WebSite/style/service.css new file mode 100644 index 0000000..aafe64e --- /dev/null +++ b/Profice WebSite/style/service.css @@ -0,0 +1,339 @@ +/* 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; + } +}