Inital Commit
6
html/bilder/about.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
This favicon was generated using the following font:
|
||||
|
||||
- Font Title: Leckerli One
|
||||
- Font Author: Copyright (c) 2011 Gesine Todt (www.gesine-todt.de), with Reserved Font Names "Leckerli"
|
||||
- Font Source: http://fonts.gstatic.com/s/leckerlione/v16/V8mCoQH8VCsNttEnxnGQ-1itLZxcBtItFw.ttf
|
||||
- Font License: SIL Open Font License, 1.1 (http://scripts.sil.org/OFL))
|
||||
BIN
html/bilder/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
html/bilder/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
html/bilder/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
html/bilder/blog.jpg
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
html/bilder/calc.png
Normal file
|
After Width: | Height: | Size: 375 KiB |
BIN
html/bilder/email.jpg
Normal file
|
After Width: | Height: | Size: 375 KiB |
BIN
html/bilder/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 761 B |
BIN
html/bilder/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
html/bilder/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
html/bilder/nextcloud.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
html/bilder/rezepte.jpg
Normal file
|
After Width: | Height: | Size: 117 KiB |
1
html/bilder/site.webmanifest
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||
BIN
html/bilder/stream.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
html/bilder/wiki.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
1
html/drone/assets/fonts
Normal file
@@ -0,0 +1 @@
|
||||
<!-- This file is intentionally left blank. -->
|
||||
1
html/drone/assets/videos
Normal file
@@ -0,0 +1 @@
|
||||
<!-- This file is intentionally left blank. -->
|
||||
23
html/drone/css/components/footer.css
Normal file
@@ -0,0 +1,23 @@
|
||||
.footer {
|
||||
background-color: #2c3e50;
|
||||
color: #ecf0f1;
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #ecf0f1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
45
html/drone/css/components/forms.css
Normal file
@@ -0,0 +1,45 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="email"],
|
||||
textarea {
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
98
html/drone/css/components/header.css
Normal file
@@ -0,0 +1,98 @@
|
||||
/* Header Component Styles - Updated to match Gallery page */
|
||||
header {
|
||||
padding: 1.5rem 0;
|
||||
background: rgba(232, 233, 234, 0.95); /* Match gallery page background */
|
||||
backdrop-filter: blur(8px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
background: var(--gradient-primary);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
.main-nav ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
color: var(--text-dark);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 0.5rem 0.8rem;
|
||||
position: relative;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover, .main-nav a.active {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.main-nav a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: var(--gradient-primary);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover::after, .main-nav a.active::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Mobile responsiveness */
|
||||
@media (max-width: 768px) {
|
||||
.main-nav {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 76px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: calc(100vh - 76px);
|
||||
overflow-y: auto;
|
||||
background: rgba(232, 233, 234, 0.95); /* Changed to match the header background */
|
||||
padding: 1rem 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
38
html/drone/css/components/hero.css
Normal file
@@ -0,0 +1,38 @@
|
||||
.hero {
|
||||
background-image: url('../assets/images/hero-background.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.5rem;
|
||||
margin: 10px 0 20px;
|
||||
}
|
||||
|
||||
.hero .cta-button {
|
||||
background-color: #ffcc00;
|
||||
color: #333;
|
||||
padding: 15px 30px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.hero .cta-button:hover {
|
||||
background-color: #e6b800;
|
||||
}
|
||||
70
html/drone/css/components/mobile-menu.css
Normal file
@@ -0,0 +1,70 @@
|
||||
/* Mobile navigation styles */
|
||||
|
||||
/* Mobile toggle button */
|
||||
.mobile-toggle {
|
||||
display: none;
|
||||
font-size: 1.75rem;
|
||||
color: var(--primary-color);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* Mobile responsiveness */
|
||||
@media (max-width: 768px) {
|
||||
.mobile-toggle {
|
||||
display: block; /* Show on mobile */
|
||||
}
|
||||
|
||||
.main-nav {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: var(--bg-light);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
|
||||
z-index: 999;
|
||||
border-radius: 0 0 10px 10px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.main-nav.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main-nav ul {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 1rem 0;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.main-nav li {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
display: block;
|
||||
padding: 0.75rem;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main-nav a:hover::after,
|
||||
.main-nav a.active::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Ensure footer copyright is visible and properly formatted on mobile */
|
||||
footer .container p {
|
||||
text-align: center;
|
||||
font-size: 0.9rem;
|
||||
margin: 0;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
}
|
||||
99
html/drone/css/main.css
Normal file
@@ -0,0 +1,99 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Arial', sans-serif;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
header {
|
||||
background: #4CAF50;
|
||||
color: #fff;
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 20px;
|
||||
padding-top: 90px; /* This value should match your header height plus any desired spacing */
|
||||
}
|
||||
|
||||
footer {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4CAF50;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: url('../assets/images/hero-bg.jpg') no-repeat center center/cover;
|
||||
height: 400px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
text-align: center;
|
||||
margin-top: -30px; /* Adjust to reduce some of the padding for hero sections */
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="email"],
|
||||
textarea {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #45a049;
|
||||
}
|
||||
46
html/drone/css/normalize.css
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed, footer,
|
||||
header, hgroup, main, menu, nav, output, ruby,
|
||||
section, summary, time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, main, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
40
html/drone/email-test.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// Simple email test script
|
||||
echo "<h1>Email Test</h1>";
|
||||
|
||||
// Check if mail function exists
|
||||
if (!function_exists('mail')) {
|
||||
echo "<p style='color:red'>Error: mail() function is not available!</p>";
|
||||
echo "<p>Make sure PHP is configured with mail support.</p>";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Try to send a test email
|
||||
$to = "monitor@egonetix.de";
|
||||
$subject = "Test Email from Luftglanz";
|
||||
$message = "This is a test email sent from " . $_SERVER['SERVER_NAME'] . " at " . date('Y-m-d H:i:s');
|
||||
$headers = "From: test@" . $_SERVER['SERVER_NAME'] . "\r\n" .
|
||||
"Reply-To: test@" . $_SERVER['SERVER_NAME'] . "\r\n" .
|
||||
"X-Mailer: PHP/" . phpversion();
|
||||
|
||||
$success = mail($to, $subject, $message, $headers);
|
||||
|
||||
if ($success) {
|
||||
echo "<p style='color:green'>Success! Test email was sent to $to</p>";
|
||||
} else {
|
||||
echo "<p style='color:red'>Failed to send email. Check server mail configuration.</p>";
|
||||
|
||||
// Check mail configuration
|
||||
echo "<h2>Mail Configuration:</h2>";
|
||||
echo "<pre>";
|
||||
echo "sendmail_path: " . ini_get('sendmail_path') . "\n";
|
||||
echo "SMTP: " . ini_get('SMTP') . "\n";
|
||||
echo "smtp_port: " . ini_get('smtp_port') . "\n";
|
||||
echo "</pre>";
|
||||
}
|
||||
|
||||
// Display PHP info for debugging
|
||||
echo "<h2>PHP Information:</h2>";
|
||||
echo "<p>PHP Version: " . phpversion() . "</p>";
|
||||
echo "<p>Server Software: " . $_SERVER['SERVER_SOFTWARE'] . "</p>";
|
||||
?>
|
||||
73
html/drone/extract.py
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
# Full Python script to fetch new tickets from Zammad, extract phone numbers, and update the user's profile.
|
||||
import requests
|
||||
import re
|
||||
|
||||
# Configuration
|
||||
ZAMMAD_URL = "https://kontakt.luftglanz.de"
|
||||
API_TOKEN = "iwXhnY-mb1PFqYHZhtjcRQqgJuNTv0ctPkMthbE2yMG1bXm-NyW2ZkMpu9PX1-9P" # Replace this with your actual token
|
||||
|
||||
HEADERS = {
|
||||
"Authorization": f"Token token={API_TOKEN}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
def get_new_tickets():
|
||||
resp = requests.get(f"{ZAMMAD_URL}/api/v1/tickets?state=new", headers=HEADERS)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def get_ticket_articles(ticket_id):
|
||||
resp = requests.get(f"{ZAMMAD_URL}/api/v1/ticket_articles/by_ticket/{ticket_id}", headers=HEADERS)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def extract_phone(text):
|
||||
# Look for "Telefonnummer: <number>" or similar
|
||||
match = re.search(r'(?:Telefonnummer|Tel\.?|Handy|Mobil)[^\d]*(\+?\d[\d\s\-()]{7,})', text, re.IGNORECASE)
|
||||
if match:
|
||||
number = match.group(1).replace(" ", "").replace("-", "")
|
||||
return number
|
||||
# Fallback: generic phone number pattern
|
||||
match = re.search(r'(\+?\d[\d\s\-()]{7,})', text)
|
||||
if match:
|
||||
number = match.group(1).replace(" ", "").replace("-", "")
|
||||
return number
|
||||
return None
|
||||
|
||||
def get_user(user_id):
|
||||
resp = requests.get(f"{ZAMMAD_URL}/api/v1/users/{user_id}", headers=HEADERS)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def update_user_phone_or_mobile(user_id, phone):
|
||||
# If phone starts with 01, treat as mobile
|
||||
field = "mobile" if phone.startswith("01") else "phone"
|
||||
data = {field: phone}
|
||||
resp = requests.put(f"{ZAMMAD_URL}/api/v1/users/{user_id}", json=data, headers=HEADERS)
|
||||
return resp.status_code == 200, field
|
||||
|
||||
def process():
|
||||
tickets = get_new_tickets()
|
||||
for ticket in tickets:
|
||||
ticket_id = ticket["id"]
|
||||
customer_id = ticket["customer_id"]
|
||||
articles = get_ticket_articles(ticket_id)
|
||||
|
||||
for article in articles:
|
||||
body = article.get("body", "")
|
||||
phone = extract_phone(body)
|
||||
|
||||
if phone:
|
||||
user = get_user(customer_id)
|
||||
# Check if the field is already set
|
||||
field = "mobile" if phone.startswith("01") else "phone"
|
||||
if not user.get(field):
|
||||
success, used_field = update_user_phone_or_mobile(customer_id, phone)
|
||||
print(f"Updated user {user['email']} with {used_field} {phone}: {'✅' if success else '❌'}")
|
||||
break
|
||||
|
||||
# Execute the process
|
||||
process()
|
||||
|
||||
|
||||
76
html/drone/form-get-handler.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
// Alternative form handler using GET method
|
||||
// This file works around servers that block POST to PHP files
|
||||
|
||||
// Enable error reporting for debugging
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
// Log to help with debugging
|
||||
error_log("Form-GET-Handler received request: " . date('Y-m-d H:i:s'));
|
||||
error_log("REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD']);
|
||||
|
||||
// Process form data from either GET or POST
|
||||
$formData = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET;
|
||||
|
||||
// Sanitize inputs
|
||||
$name = isset($formData['name']) ? htmlspecialchars($formData['name']) : '';
|
||||
$email = isset($formData['email']) ? filter_var($formData['email'], FILTER_SANITIZE_EMAIL) : '';
|
||||
$phone = isset($formData['phone']) ? htmlspecialchars($formData['phone']) : '';
|
||||
$message = isset($formData['message']) ? htmlspecialchars($formData['message']) : '';
|
||||
$subjectField = isset($formData['subject']) ? htmlspecialchars($formData['subject']) : '';
|
||||
|
||||
// Log the received data
|
||||
error_log("Received data - Name: $name, Email: $email, Phone: $phone");
|
||||
|
||||
// Simple validation
|
||||
$success = false;
|
||||
$errorMessage = '';
|
||||
|
||||
if (empty($name) || empty($email) || empty($message) || empty($subjectField)) {
|
||||
$errorMessage = 'Bitte füllen Sie alle Pflichtfelder aus.';
|
||||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errorMessage = 'Bitte geben Sie eine gültige E-Mail-Adresse ein.';
|
||||
} else {
|
||||
// Construct message for the email
|
||||
$emailBody = $message;
|
||||
if (!empty($phone)) {
|
||||
$emailBody .= "\n\nTelefonnummer: $phone";
|
||||
}
|
||||
|
||||
// Email details
|
||||
$to = "kontakt@luftglanz.de";
|
||||
$subject = $subjectField ?: "Neue Kontaktanfrage von $name";
|
||||
|
||||
// Attempt to send email via internal mail function
|
||||
$mailSent = mail($to, $subject, $emailBody,
|
||||
"From: $name <luftglanz@egonetix.de>\r\n" .
|
||||
"Reply-To: $email\r\n" .
|
||||
"X-Mailer: PHP/" . phpversion()
|
||||
);
|
||||
|
||||
if ($mailSent) {
|
||||
$success = true;
|
||||
} else {
|
||||
$errorMessage = 'Es gab ein Problem beim Senden Ihrer Nachricht. Bitte versuchen Sie es später erneut.';
|
||||
error_log("Mail sending failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the response
|
||||
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
|
||||
// Ajax request - return JSON
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'success' => $success,
|
||||
'message' => $errorMessage
|
||||
]);
|
||||
} else {
|
||||
// Regular form submission - redirect with status
|
||||
if ($success) {
|
||||
header('Location: index.html?form_success=1#contact');
|
||||
} else {
|
||||
header('Location: index.html?form_error=' . urlencode($errorMessage) . '#contact');
|
||||
}
|
||||
}
|
||||
?>
|
||||
63
html/drone/form-test.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Form Test</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
|
||||
form { background: #f8f8f8; padding: 20px; border-radius: 8px; margin-bottom: 30px; }
|
||||
.form-group { margin-bottom: 15px; }
|
||||
label { display: block; margin-bottom: 5px; }
|
||||
input, textarea { width: 100%; padding: 8px; box-sizing: border-box; }
|
||||
button { background: #4CAF50; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; }
|
||||
h2 { margin-top: 30px; color: #333; border-bottom: 1px solid #ddd; padding-bottom: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Form Test - Find a Working Method</h1>
|
||||
<p>This page tests different form submission methods to find one that works on this server.</p>
|
||||
|
||||
<h2>Method 1: Standard POST Form (Original)</h2>
|
||||
<p>This method often gets blocked with a 405 error on some servers.</p>
|
||||
<form action="process-form.php" method="POST">
|
||||
<div class="form-group">
|
||||
<label for="name1">Name:</label>
|
||||
<input type="text" id="name1" name="name" value="Test User" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email1">Email:</label>
|
||||
<input type="email" id="email1" name="email" value="test@example.com" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message1">Message:</label>
|
||||
<textarea id="message1" name="message" rows="4" required>This is a test message using POST method.</textarea>
|
||||
</div>
|
||||
<button type="submit">Submit with POST</button>
|
||||
</form>
|
||||
|
||||
<h2>Method 2: GET Method Form</h2>
|
||||
<p>This method uses GET which may bypass the 405 error.</p>
|
||||
<form action="form-get-handler.php" method="GET">
|
||||
<div class="form-group">
|
||||
<label for="name2">Name:</label>
|
||||
<input type="text" id="name2" name="name" value="Test User" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email2">Email:</label>
|
||||
<input type="email" id="email2" name="email" value="test@example.com" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="phone2">Phone:</label>
|
||||
<input type="tel" id="phone2" name="phone" value="123-456-7890">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message2">Message:</label>
|
||||
<textarea id="message2" name="message" rows="4" required>This is a test message using GET method.</textarea>
|
||||
</div>
|
||||
<button type="submit">Submit with GET</button>
|
||||
</form>
|
||||
|
||||
<p><a href="index.html">Back to Main Page</a></p>
|
||||
</body>
|
||||
</html>
|
||||
BIN
html/drone/images/animation_background.png
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
html/drone/images/animation_background1.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
html/drone/images/drone_from_above.jpg
Normal file
|
After Width: | Height: | Size: 297 KiB |
BIN
html/drone/images/drone_in_action1.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
html/drone/images/drone_in_action2.jpg
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
html/drone/images/drone_in_action_solar1.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
html/drone/images/drone_in_action_solar2.jpg
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
html/drone/images/drone_realistic1.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
BIN
html/drone/images/drone_realistic2.png
Normal file
|
After Width: | Height: | Size: 3.0 MiB |
BIN
html/drone/images/drone_realistic3.png
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
BIN
html/drone/images/drone_realistic4.png
Normal file
|
After Width: | Height: | Size: 3.1 MiB |
BIN
html/drone/images/drone_realistic5.png
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
html/drone/images/drone_realistic6.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
html/drone/images/drone_transparrent_background.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
html/drone/images/favicon_logo.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
html/drone/images/out_team.jpg
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
html/drone/images/products/ago-quart-05l.jpg
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
html/drone/images/products/terrase_before_after.jpg
Normal file
|
After Width: | Height: | Size: 190 KiB |
BIN
html/drone/images/roof.png
Normal file
|
After Width: | Height: | Size: 3.7 MiB |
BIN
html/drone/images/roof1.png
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
html/drone/images/roof2.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
html/drone/images/solarreiniger.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
html/drone/images/spraying_drone.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
html/drone/images/spraying_drone1.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
html/drone/images/spraying_drone2.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
html/drone/images/spraying_drone3.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
html/drone/images/spraying_drone4.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
11
html/drone/includes/navigation.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<nav class="main-nav" id="mainNav">
|
||||
<ul>
|
||||
<li><a href="index.html" data-i18n="nav_home">Startseite</a></li>
|
||||
<li><a href="index.html#services" data-i18n="nav_services">Leistungen</a></li>
|
||||
<li><a href="index.html#how-it-works" data-i18n="nav_how_it_works">Ablauf</a></li>
|
||||
<li><a href="index.html#faq" data-i18n="nav_faq">FAQ</a></li>
|
||||
<li><a href="index.html#contact" data-i18n="nav_contact">Kontakt</a></li>
|
||||
<li><a href="pages/products.html" data-i18n="nav_products">Produkte</a></li>
|
||||
<li><a href="pages/gallery.html" data-i18n="nav_gallery">Galerie</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
1093
html/drone/index.html
Normal file
334
html/drone/js/background-patterns.js
Normal file
@@ -0,0 +1,334 @@
|
||||
/**
|
||||
* Roof Cleaning Drone Background Animations
|
||||
* Creates animated drones with water spray effects
|
||||
*/
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Apply the background to the entire site
|
||||
applyCleanBackground();
|
||||
|
||||
// Add animated drones to hero section
|
||||
enhanceHeroSection();
|
||||
|
||||
// Add water droplet effects to service cards
|
||||
enhanceServiceCards();
|
||||
});
|
||||
|
||||
function applyCleanBackground() {
|
||||
// Remove any existing star/cosmic backgrounds
|
||||
const existingStars = document.querySelector('.stars');
|
||||
if (existingStars) {
|
||||
existingStars.remove();
|
||||
}
|
||||
|
||||
// Add clean background to body
|
||||
document.body.style.background = '#f8f9fa';
|
||||
document.body.style.backgroundImage = `
|
||||
linear-gradient(120deg, rgba(99, 183, 241, 0.1) 0%, transparent 40%),
|
||||
linear-gradient(240deg, rgba(220, 237, 249, 0.2) 0%, transparent 40%)
|
||||
`;
|
||||
|
||||
// Add subtle diagonal pattern
|
||||
const pattern = document.createElement('div');
|
||||
pattern.className = 'clean-pattern';
|
||||
pattern.style.position = 'fixed';
|
||||
pattern.style.top = '0';
|
||||
pattern.style.left = '0';
|
||||
pattern.style.width = '100%';
|
||||
pattern.style.height = '100%';
|
||||
pattern.style.pointerEvents = 'none';
|
||||
pattern.style.opacity = '0.03';
|
||||
pattern.style.zIndex = '-1';
|
||||
pattern.style.backgroundImage = `
|
||||
repeating-linear-gradient(
|
||||
45deg,
|
||||
#3498db,
|
||||
#3498db 2px,
|
||||
transparent 2px,
|
||||
transparent 10px
|
||||
)
|
||||
`;
|
||||
document.body.appendChild(pattern);
|
||||
|
||||
// Update text colors for better contrast on light background
|
||||
document.querySelectorAll('p, h1, h2, h3, h4, h5, h6').forEach(el => {
|
||||
// Only change if still using the dark theme colors
|
||||
if (getComputedStyle(el).color === 'rgb(216, 216, 255)' ||
|
||||
getComputedStyle(el).color === 'rgb(143, 143, 183)') {
|
||||
el.style.color = '#505050';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function enhanceHeroSection() {
|
||||
const heroSection = document.querySelector('.hero');
|
||||
if (!heroSection) return;
|
||||
|
||||
// Remove any existing background
|
||||
if (heroSection.style.backgroundImage.includes('stars-bg.jpg')) {
|
||||
heroSection.style.backgroundImage = 'none';
|
||||
}
|
||||
|
||||
// Create a sky gradient background
|
||||
heroSection.style.background = 'linear-gradient(to bottom, #87CEEB 0%, #e6f7ff 100%)';
|
||||
heroSection.style.position = 'relative';
|
||||
heroSection.style.overflow = 'hidden';
|
||||
|
||||
// Create animation container
|
||||
const animationContainer = document.createElement('div');
|
||||
animationContainer.className = 'drone-animation-container';
|
||||
animationContainer.style.position = 'absolute';
|
||||
animationContainer.style.top = '0';
|
||||
animationContainer.style.left = '0';
|
||||
animationContainer.style.width = '100%';
|
||||
animationContainer.style.height = '100%';
|
||||
animationContainer.style.pointerEvents = 'none';
|
||||
animationContainer.style.zIndex = '1';
|
||||
heroSection.appendChild(animationContainer);
|
||||
|
||||
// Add roof silhouette
|
||||
const roofSilhouette = document.createElement('div');
|
||||
roofSilhouette.className = 'roof-silhouette';
|
||||
roofSilhouette.style.position = 'absolute';
|
||||
roofSilhouette.style.bottom = '0';
|
||||
roofSilhouette.style.left = '0';
|
||||
roofSilhouette.style.width = '100%';
|
||||
roofSilhouette.style.height = '20%';
|
||||
roofSilhouette.style.background = 'url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAwIDIwMCI+PHBhdGggZD0iTTAgMjAwVjE1MEg1MEwxMDAgMTAwTDE1MCAxNTBIMjAwTDI1MCAxMDBMMzAwIDE1MEgzNTBMNDAwIDUwTDQ1MCAxNTBINTAwTDU1MCAxMDBMNjAwIDE1MEg2NTBMNzAwIDEwMEw3NTAgMTUwSDgwMEw4NTAgNTBMOTAwIDE1MEg5NTBMMTAwMCAxMDBMMTA1MCAxNTBIMTEwMEwxMTUwIDEwMEwxMjAwIDE1MFYyMDBIMFoiIGZpbGw9IiNlMGUwZTAiIGZpbGwtb3BhY2l0eT0iMC40Ii8+PC9zdmc+")';
|
||||
roofSilhouette.style.backgroundSize = 'cover';
|
||||
roofSilhouette.style.zIndex = '0';
|
||||
animationContainer.appendChild(roofSilhouette);
|
||||
|
||||
// Create multiple drones with spray effects
|
||||
createCleaningDrone(animationContainer, 20, 30, -1, 20);
|
||||
createCleaningDrone(animationContainer, 60, 20, 1, 25);
|
||||
createCleaningDrone(animationContainer, 40, 50, -1, 30);
|
||||
|
||||
// Add keyframes for animations
|
||||
addDroneAnimationStyles();
|
||||
}
|
||||
|
||||
function createCleaningDrone(container, startX, startY, direction, duration) {
|
||||
// Create drone container
|
||||
const droneElement = document.createElement('div');
|
||||
droneElement.className = 'cleaning-drone';
|
||||
droneElement.style.position = 'absolute';
|
||||
droneElement.style.left = `${startX}%`;
|
||||
droneElement.style.top = `${startY}%`;
|
||||
droneElement.style.width = '60px';
|
||||
droneElement.style.height = '60px';
|
||||
droneElement.style.zIndex = '2';
|
||||
|
||||
// Calculate unique animation name
|
||||
const animationName = `drone-path-${startX}-${startY}`;
|
||||
droneElement.style.animation = `${animationName} ${duration}s linear infinite`;
|
||||
|
||||
// Create drone body
|
||||
const droneBody = document.createElement('div');
|
||||
droneBody.className = 'drone-body';
|
||||
droneBody.style.position = 'relative';
|
||||
droneBody.style.width = '40px';
|
||||
droneBody.style.height = '40px';
|
||||
droneBody.style.borderRadius = '50%';
|
||||
droneBody.style.backgroundColor = '#3498db';
|
||||
droneBody.style.border = '2px solid #2980b9';
|
||||
droneBody.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)';
|
||||
droneBody.style.margin = '0 auto';
|
||||
droneBody.style.zIndex = '2';
|
||||
droneElement.appendChild(droneBody);
|
||||
|
||||
// Add central hub
|
||||
const droneHub = document.createElement('div');
|
||||
droneHub.className = 'drone-hub';
|
||||
droneHub.style.position = 'absolute';
|
||||
droneHub.style.top = '50%';
|
||||
droneHub.style.left = '50%';
|
||||
droneHub.style.width = '15px';
|
||||
droneHub.style.height = '15px';
|
||||
droneHub.style.borderRadius = '50%';
|
||||
droneHub.style.backgroundColor = '#fff';
|
||||
droneHub.style.transform = 'translate(-50%, -50%)';
|
||||
droneHub.style.zIndex = '3';
|
||||
droneBody.appendChild(droneHub);
|
||||
|
||||
// Add propellers
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const propContainer = document.createElement('div');
|
||||
propContainer.className = 'propeller-container';
|
||||
propContainer.style.position = 'absolute';
|
||||
propContainer.style.width = '15px';
|
||||
propContainer.style.height = '15px';
|
||||
|
||||
// Position propellers around drone
|
||||
switch(i) {
|
||||
case 0: // top left
|
||||
propContainer.style.top = '-10px';
|
||||
propContainer.style.left = '-10px';
|
||||
break;
|
||||
case 1: // top right
|
||||
propContainer.style.top = '-10px';
|
||||
propContainer.style.right = '-10px';
|
||||
break;
|
||||
case 2: // bottom left
|
||||
propContainer.style.bottom = '-10px';
|
||||
propContainer.style.left = '-10px';
|
||||
break;
|
||||
case 3: // bottom right
|
||||
propContainer.style.bottom = '-10px';
|
||||
propContainer.style.right = '-10px';
|
||||
break;
|
||||
}
|
||||
|
||||
// Create propeller
|
||||
const propeller = document.createElement('div');
|
||||
propeller.className = 'propeller';
|
||||
propeller.style.width = '100%';
|
||||
propeller.style.height = '100%';
|
||||
propeller.style.borderRadius = '50%';
|
||||
propeller.style.borderTop = '2px solid rgba(255,255,255,0.8)';
|
||||
propeller.style.borderLeft = '2px solid rgba(255,255,255,0.6)';
|
||||
propeller.style.animation = 'spin-propeller 0.15s linear infinite';
|
||||
propContainer.appendChild(propeller);
|
||||
|
||||
droneBody.appendChild(propContainer);
|
||||
}
|
||||
|
||||
// Create water spray effect
|
||||
const waterSpray = document.createElement('div');
|
||||
waterSpray.className = 'water-spray';
|
||||
waterSpray.style.position = 'absolute';
|
||||
waterSpray.style.bottom = '-20px';
|
||||
waterSpray.style.left = '50%';
|
||||
waterSpray.style.transform = 'translateX(-50%)';
|
||||
waterSpray.style.width = '30px';
|
||||
waterSpray.style.height = '50px';
|
||||
waterSpray.style.zIndex = '1';
|
||||
droneElement.appendChild(waterSpray);
|
||||
|
||||
// Add water droplets to the spray
|
||||
for (let i = 0; i < 12; i++) {
|
||||
const droplet = document.createElement('div');
|
||||
droplet.className = 'water-droplet';
|
||||
droplet.style.position = 'absolute';
|
||||
droplet.style.width = `${3 + Math.random() * 3}px`;
|
||||
droplet.style.height = `${5 + Math.random() * 7}px`;
|
||||
droplet.style.backgroundColor = 'rgba(173, 216, 230, 0.7)';
|
||||
droplet.style.borderRadius = '50%';
|
||||
|
||||
// Randomize position within spray
|
||||
const angle = Math.random() * 30 - 15; // -15 to 15 degrees
|
||||
const distance = 5 + Math.random() * 45; // 5 to 50px
|
||||
|
||||
droplet.style.top = `${distance}px`;
|
||||
droplet.style.left = '50%';
|
||||
droplet.style.transform = `translateX(-50%) rotate(${angle}deg)`;
|
||||
|
||||
// Different animation duration for each droplet
|
||||
const fallDuration = 0.5 + Math.random() * 0.5;
|
||||
droplet.style.animation = `fall-droplet ${fallDuration}s infinite linear`;
|
||||
|
||||
waterSpray.appendChild(droplet);
|
||||
}
|
||||
|
||||
// Create path animation for this specific drone
|
||||
const keyframesStyle = document.createElement('style');
|
||||
keyframesStyle.innerHTML = `
|
||||
@keyframes ${animationName} {
|
||||
0% {
|
||||
transform: translateX(${direction > 0 ? '-100px' : '100vw'}) translateY(0px) rotate(${direction > 0 ? '0deg' : '180deg'});
|
||||
}
|
||||
25% {
|
||||
transform: translateX(${direction > 0 ? 'calc(20vw)' : 'calc(80vw - 100px)'}) translateY(-20px) rotate(${direction > 0 ? '0deg' : '180deg'});
|
||||
}
|
||||
50% {
|
||||
transform: translateX(${direction > 0 ? 'calc(40vw)' : 'calc(60vw - 100px)'}) translateY(30px) rotate(${direction > 0 ? '0deg' : '180deg'});
|
||||
}
|
||||
75% {
|
||||
transform: translateX(${direction > 0 ? 'calc(60vw)' : 'calc(40vw - 100px)'}) translateY(-15px) rotate(${direction > 0 ? '0deg' : '180deg'});
|
||||
}
|
||||
100% {
|
||||
transform: translateX(${direction > 0 ? '100vw' : '-100px'}) translateY(10px) rotate(${direction > 0 ? '0deg' : '180deg'});
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(keyframesStyle);
|
||||
|
||||
container.appendChild(droneElement);
|
||||
}
|
||||
|
||||
function addDroneAnimationStyles() {
|
||||
const styleSheet = document.createElement('style');
|
||||
styleSheet.innerHTML = `
|
||||
@keyframes spin-propeller {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes fall-droplet {
|
||||
0% {
|
||||
opacity: 0.8;
|
||||
transform: translateX(-50%) translateY(0) scale(1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(30px) scale(0.5);
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(styleSheet);
|
||||
}
|
||||
|
||||
function enhanceServiceCards() {
|
||||
const serviceCards = document.querySelectorAll('.service-card');
|
||||
if (!serviceCards.length) return;
|
||||
|
||||
serviceCards.forEach(card => {
|
||||
// Update card styling to match clean theme
|
||||
card.style.backgroundColor = 'white';
|
||||
card.style.borderRadius = '10px';
|
||||
card.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.1)';
|
||||
card.style.border = '1px solid rgba(0, 0, 0, 0.05)';
|
||||
card.style.overflow = 'hidden';
|
||||
|
||||
// Add water droplet accent at the top
|
||||
const waterAccent = document.createElement('div');
|
||||
waterAccent.className = 'water-accent';
|
||||
waterAccent.style.height = '5px';
|
||||
waterAccent.style.width = '100%';
|
||||
waterAccent.style.position = 'absolute';
|
||||
waterAccent.style.top = '0';
|
||||
waterAccent.style.left = '0';
|
||||
waterAccent.style.background = 'linear-gradient(90deg, #3498db, #00c2cb)';
|
||||
card.prepend(waterAccent);
|
||||
|
||||
// Add subtle cleaning pattern to each card
|
||||
addCleaningIconToCard(card);
|
||||
});
|
||||
}
|
||||
|
||||
function addCleaningIconToCard(card) {
|
||||
// Create a container for the icon
|
||||
const iconContainer = document.createElement('div');
|
||||
iconContainer.className = 'cleaning-icon';
|
||||
iconContainer.style.position = 'absolute';
|
||||
iconContainer.style.top = '15px';
|
||||
iconContainer.style.right = '15px';
|
||||
iconContainer.style.width = '30px';
|
||||
iconContainer.style.height = '30px';
|
||||
iconContainer.style.opacity = '0.1';
|
||||
|
||||
// Randomly choose between different cleaning icons
|
||||
const icons = [
|
||||
// Water droplet
|
||||
`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 12 3 12 3C12 3 4 7.58172 4 12C4 16.4183 7.58172 20 12 20Z" fill="#3498db"/></svg>`,
|
||||
// Spray bottle
|
||||
`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8 3H11V5H13V3H16V5H14V7H17L19 10V21H6V10L8 7H11V5H8V3ZM8 10V19H17V10L15.8 8H9.2L8 10Z" fill="#3498db"/></svg>`,
|
||||
// Drone
|
||||
`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8C13.1046 8 14 7.10457 14 6C14 4.89543 13.1046 4 12 4C10.8954 4 10 4.89543 10 6C10 7.10457 10.8954 8 12 8Z" fill="#3498db"/><path d="M4 10C5.10457 10 6 9.10457 6 8C6 6.89543 5.10457 6 4 6C2.89543 6 2 6.89543 2 8C2 9.10457 2.89543 10 4 10Z" fill="#3498db"/><path d="M20 10C21.1046 10 22 9.10457 22 8C22 6.89543 21.1046 6 20 6C18.8954 6 18 6.89543 18 8C18 9.10457 18.8954 10 20 10Z" fill="#3498db"/><path d="M12 20C13.1046 20 14 19.1046 14 18C14 16.8954 13.1046 16 12 16C10.8954 16 10 16.8954 10 18C10 19.1046 10.8954 20 12 20Z" fill="#3498db"/><path d="M12 8V16M4 10L10 16M20 10L14 16" stroke="#3498db" stroke-width="2" stroke-linecap="round"/></svg>`
|
||||
];
|
||||
|
||||
// Choose a random icon
|
||||
iconContainer.innerHTML = icons[Math.floor(Math.random() * icons.length)];
|
||||
card.appendChild(iconContainer);
|
||||
}
|
||||
})();
|
||||
139
html/drone/js/bright-theme.js
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* Bright Theme Elements and Visual Enhancements
|
||||
*/
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Add clean sky background to hero section
|
||||
enhanceHeroSection();
|
||||
|
||||
// Add clean visual elements to services section
|
||||
enhanceServicesSection();
|
||||
|
||||
// Add bright UI enhancements
|
||||
applyBrightUIEnhancements();
|
||||
});
|
||||
|
||||
function enhanceHeroSection() {
|
||||
const heroSection = document.querySelector('.hero');
|
||||
if (!heroSection) return;
|
||||
|
||||
// Create and add sky background with subtle clouds
|
||||
heroSection.style.backgroundImage = 'linear-gradient(to bottom, #e6f3ff 0%, #ffffff 100%)';
|
||||
heroSection.style.position = 'relative';
|
||||
heroSection.style.overflow = 'hidden';
|
||||
|
||||
// Add subtle pattern
|
||||
const pattern = document.createElement('div');
|
||||
pattern.className = 'hero-pattern';
|
||||
pattern.style.position = 'absolute';
|
||||
pattern.style.top = 0;
|
||||
pattern.style.left = 0;
|
||||
pattern.style.right = 0;
|
||||
pattern.style.bottom = 0;
|
||||
pattern.style.opacity = 0.3;
|
||||
pattern.style.backgroundImage = 'url("data:image/svg+xml,%3Csvg width=\'100\' height=\'100\' viewBox=\'0 0 100 100\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z\' fill=\'%230078d4\' fill-opacity=\'0.1\' fill-rule=\'evenodd\'/%3E%3C/svg%3E")';
|
||||
heroSection.insertBefore(pattern, heroSection.firstChild);
|
||||
|
||||
// Add animated simple drone icon
|
||||
const droneContainer = document.createElement('div');
|
||||
droneContainer.className = 'drone-animation';
|
||||
droneContainer.style.position = 'absolute';
|
||||
droneContainer.style.top = '20%';
|
||||
droneContainer.style.right = '10%';
|
||||
droneContainer.style.width = '80px';
|
||||
droneContainer.style.height = '80px';
|
||||
droneContainer.style.zIndex = '1';
|
||||
droneContainer.style.animation = 'float 6s ease-in-out infinite';
|
||||
|
||||
// Create drone SVG
|
||||
droneContainer.innerHTML = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 8C13.1046 8 14 7.10457 14 6C14 4.89543 13.1046 4 12 4C10.8954 4 10 4.89543 10 6C10 7.10457 10.8954 8 12 8Z" fill="#0078d4"/>
|
||||
<path d="M4 10C5.10457 10 6 9.10457 6 8C6 6.89543 5.10457 6 4 6C2.89543 6 2 6.89543 2 8C2 9.10457 2.89543 10 4 10Z" fill="#0078d4"/>
|
||||
<path d="M20 10C21.1046 10 22 9.10457 22 8C22 6.89543 21.1046 6 20 6C18.8954 6 18 6.89543 18 8C18 9.10457 18.8954 10 20 10Z" fill="#0078d4"/>
|
||||
<path d="M12 20C13.1046 20 14 19.1046 14 18C14 16.8954 13.1046 16 12 16C10.8954 16 10 16.8954 10 18C10 19.1046 10.8954 20 12 20Z" fill="#0078d4"/>
|
||||
<path d="M12 8V16M4 10L10 16M20 10L14 16" stroke="#0078d4" stroke-width="2" stroke-linecap="round"/>
|
||||
<animate attributeName="opacity" values="0.7;1;0.7" dur="2s" repeatCount="indefinite" />
|
||||
</svg>`;
|
||||
|
||||
heroSection.appendChild(droneContainer);
|
||||
|
||||
// Add the floating animation
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
@keyframes float {
|
||||
0% { transform: translateY(0px) rotate(0deg); }
|
||||
50% { transform: translateY(-15px) rotate(2deg); }
|
||||
100% { transform: translateY(0px) rotate(0deg); }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
function enhanceServicesSection() {
|
||||
const servicesSection = document.getElementById('services');
|
||||
if (!servicesSection) return;
|
||||
|
||||
// Add subtle pattern background
|
||||
servicesSection.style.backgroundImage = 'linear-gradient(120deg, #ffffff 0%, #f8f9fa 100%)';
|
||||
servicesSection.style.position = 'relative';
|
||||
|
||||
// Add cleaning icons to service cards
|
||||
const serviceCards = document.querySelectorAll('.service-card');
|
||||
const icons = [
|
||||
'<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 21L12 12M12 12L21 3M12 12L3 3M12 12L21 21" stroke="#0078d4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
||||
'<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="9" stroke="#0078d4" stroke-width="2"/><path d="M12 7V12L15 15" stroke="#0078d4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
||||
'<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 3v18M3 12h18" stroke="#0078d4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
|
||||
];
|
||||
|
||||
serviceCards.forEach((card, index) => {
|
||||
const icon = document.createElement('div');
|
||||
icon.className = 'service-icon';
|
||||
icon.style.marginBottom = '1.5rem';
|
||||
icon.innerHTML = icons[index % icons.length];
|
||||
card.insertBefore(icon, card.firstChild);
|
||||
});
|
||||
}
|
||||
|
||||
function applyBrightUIEnhancements() {
|
||||
// Enhance buttons
|
||||
const buttons = document.querySelectorAll('.btn-primary');
|
||||
buttons.forEach(button => {
|
||||
button.style.background = 'var(--primary-color)';
|
||||
button.style.boxShadow = '0 4px 12px rgba(0, 120, 212, 0.2)';
|
||||
button.style.border = 'none';
|
||||
|
||||
// Add hover effect
|
||||
button.addEventListener('mouseenter', function() {
|
||||
this.style.background = 'var(--gradient-primary)';
|
||||
this.style.transform = 'translateY(-2px)';
|
||||
});
|
||||
|
||||
button.addEventListener('mouseleave', function() {
|
||||
this.style.background = 'var(--primary-color)';
|
||||
this.style.transform = 'translateY(0)';
|
||||
});
|
||||
});
|
||||
|
||||
// Add roof-related decorative elements to sections
|
||||
const sections = document.querySelectorAll('.section-container');
|
||||
sections.forEach(section => {
|
||||
// Add subtle top decoration
|
||||
const decoration = document.createElement('div');
|
||||
decoration.className = 'section-decoration';
|
||||
decoration.style.height = '4px';
|
||||
decoration.style.width = '100px';
|
||||
decoration.style.background = 'var(--gradient-primary)';
|
||||
decoration.style.borderRadius = '2px';
|
||||
decoration.style.marginBottom = '2rem';
|
||||
|
||||
const title = section.querySelector('.section-title');
|
||||
if (title) {
|
||||
title.style.display = 'flex';
|
||||
title.style.flexDirection = 'column';
|
||||
title.style.alignItems = 'center';
|
||||
title.style.marginBottom = '3rem';
|
||||
title.appendChild(decoration);
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
39
html/drone/js/contact-form.js
Normal file
@@ -0,0 +1,39 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const contactForm = document.getElementById('contact-form');
|
||||
const nameInput = document.getElementById('name');
|
||||
const emailInput = document.getElementById('email');
|
||||
const messageInput = document.getElementById('message');
|
||||
const submitButton = document.getElementById('submit-button');
|
||||
|
||||
contactForm.addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const name = nameInput.value.trim();
|
||||
const email = emailInput.value.trim();
|
||||
const message = messageInput.value.trim();
|
||||
|
||||
if (validateForm(name, email, message)) {
|
||||
// Simulate form submission
|
||||
console.log('Form submitted:', { name, email, message });
|
||||
alert('Thank you for your message! We will get back to you soon.');
|
||||
contactForm.reset();
|
||||
}
|
||||
});
|
||||
|
||||
function validateForm(name, email, message) {
|
||||
if (!name || !email || !message) {
|
||||
alert('Please fill in all fields.');
|
||||
return false;
|
||||
}
|
||||
if (!validateEmail(email)) {
|
||||
alert('Please enter a valid email address.');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateEmail(email) {
|
||||
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return re.test(String(email).toLowerCase());
|
||||
}
|
||||
});
|
||||
86
html/drone/js/dark-mode.js
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Enhanced Styling Controller for Balancer.fi-inspired Theme
|
||||
*/
|
||||
(function() {
|
||||
// Run on page load and after small delay to ensure all elements are available
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
enhanceCosmicStyles();
|
||||
|
||||
// Apply once more after a slight delay to handle dynamically loaded elements
|
||||
setTimeout(enhanceCosmicStyles, 500);
|
||||
});
|
||||
|
||||
function enhanceCosmicStyles() {
|
||||
// Add subtle animations to cards
|
||||
const cards = document.querySelectorAll('.service-card, .step-card, .contact-method, .gallery-item');
|
||||
cards.forEach(function(card) {
|
||||
card.style.transition = 'all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1)';
|
||||
|
||||
// Add hover effects if not already present
|
||||
card.addEventListener('mouseenter', function() {
|
||||
this.style.transform = 'translateY(-10px)';
|
||||
this.style.boxShadow = '0 15px 30px rgba(0, 0, 0, 0.4), 0 0 15px rgba(0, 194, 255, 0.5)';
|
||||
});
|
||||
|
||||
card.addEventListener('mouseleave', function() {
|
||||
this.style.transform = 'translateY(0)';
|
||||
this.style.boxShadow = '0 5px 15px rgba(0, 0, 0, 0.2)';
|
||||
});
|
||||
});
|
||||
|
||||
// Enhance form inputs for cosmic theme
|
||||
const formElements = document.querySelectorAll('input:not(#chatInput), textarea, select');
|
||||
formElements.forEach(function(element) {
|
||||
element.style.backgroundColor = 'rgba(0, 0, 0, 0.2)';
|
||||
element.style.color = 'var(--text-light)';
|
||||
element.style.border = '1px solid rgba(255, 255, 255, 0.1)';
|
||||
element.style.borderRadius = '6px';
|
||||
element.style.padding = '1rem';
|
||||
|
||||
// Add focus effects
|
||||
element.addEventListener('focus', function() {
|
||||
this.style.borderColor = 'var(--accent-color)';
|
||||
this.style.boxShadow = '0 0 0 2px rgba(0, 194, 255, 0.2)';
|
||||
});
|
||||
|
||||
element.addEventListener('blur', function() {
|
||||
this.style.borderColor = 'rgba(255, 255, 255, 0.1)';
|
||||
this.style.boxShadow = 'none';
|
||||
});
|
||||
});
|
||||
|
||||
// Enhance buttons
|
||||
const buttons = document.querySelectorAll('button[type="submit"], .btn-primary, .cta-button');
|
||||
buttons.forEach(function(button) {
|
||||
// Only apply if not already styled
|
||||
if (!button.hasAttribute('data-cosmic-styled')) {
|
||||
button.setAttribute('data-cosmic-styled', 'true');
|
||||
|
||||
// Apply gradient background if not already set
|
||||
if (!button.style.background.includes('gradient')) {
|
||||
button.style.background = 'linear-gradient(90deg, #5846f9, #00c2ff)';
|
||||
}
|
||||
|
||||
button.style.color = 'white';
|
||||
button.style.border = 'none';
|
||||
button.style.borderRadius = '6px';
|
||||
button.style.fontWeight = '600';
|
||||
button.style.padding = '0.8rem 1.5rem';
|
||||
button.style.cursor = 'pointer';
|
||||
button.style.transition = 'all 0.3s ease';
|
||||
button.style.boxShadow = '0 0 15px rgba(0, 194, 255, 0.5)';
|
||||
|
||||
// Add hover effects
|
||||
button.addEventListener('mouseenter', function() {
|
||||
this.style.transform = 'translateY(-2px)';
|
||||
this.style.boxShadow = '0 0 25px rgba(0, 194, 255, 0.7)';
|
||||
});
|
||||
|
||||
button.addEventListener('mouseleave', function() {
|
||||
this.style.transform = 'translateY(0)';
|
||||
this.style.boxShadow = '0 0 15px rgba(0, 194, 255, 0.5)';
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
154
html/drone/js/drone-animation.js
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Drone Animation Controller
|
||||
* Creates floating drone elements with cosmic glow effects
|
||||
*/
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Only run on the homepage
|
||||
if (window.location.pathname.endsWith('index.html') || window.location.pathname.endsWith('/')) {
|
||||
createDroneElements();
|
||||
}
|
||||
});
|
||||
|
||||
function createDroneElements() {
|
||||
const heroSection = document.querySelector('.hero');
|
||||
const servicesSection = document.getElementById('services');
|
||||
|
||||
if (heroSection) {
|
||||
// Create a container for the animated elements
|
||||
const animationContainer = document.createElement('div');
|
||||
animationContainer.className = 'animation-container';
|
||||
animationContainer.style.position = 'absolute';
|
||||
animationContainer.style.top = '0';
|
||||
animationContainer.style.left = '0';
|
||||
animationContainer.style.width = '100%';
|
||||
animationContainer.style.height = '100%';
|
||||
animationContainer.style.overflow = 'hidden';
|
||||
animationContainer.style.pointerEvents = 'none';
|
||||
animationContainer.style.zIndex = '1';
|
||||
heroSection.appendChild(animationContainer);
|
||||
|
||||
// Create floating drone elements
|
||||
createFloatingDrone(animationContainer, 'right', '15%', '20%');
|
||||
createFloatingDrone(animationContainer, 'left', '70%', '60%');
|
||||
|
||||
// Create floating particles
|
||||
for (let i = 0; i < 15; i++) {
|
||||
createGlowingParticle(animationContainer);
|
||||
}
|
||||
}
|
||||
|
||||
if (servicesSection) {
|
||||
// Create subtle background animations for services section
|
||||
const servicesBg = document.createElement('div');
|
||||
servicesBg.className = 'services-bg';
|
||||
servicesBg.style.position = 'absolute';
|
||||
servicesBg.style.top = '0';
|
||||
servicesBg.style.left = '0';
|
||||
servicesBg.style.width = '100%';
|
||||
servicesBg.style.height = '100%';
|
||||
servicesBg.style.overflow = 'hidden';
|
||||
servicesBg.style.pointerEvents = 'none';
|
||||
servicesBg.style.zIndex = '0';
|
||||
servicesSection.style.position = 'relative';
|
||||
servicesSection.insertBefore(servicesBg, servicesSection.firstChild);
|
||||
|
||||
// Create subtle floating particles
|
||||
for (let i = 0; i < 10; i++) {
|
||||
createGlowingParticle(servicesBg, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createFloatingDrone(container, direction, startX, startY) {
|
||||
const drone = document.createElement('div');
|
||||
drone.className = 'floating-drone';
|
||||
drone.style.position = 'absolute';
|
||||
drone.style.width = '80px';
|
||||
drone.style.height = '80px';
|
||||
drone.style.borderRadius = '50%';
|
||||
drone.style.background = 'radial-gradient(circle at center, rgba(88, 70, 249, 0.7), rgba(0, 194, 255, 0.4))';
|
||||
drone.style.boxShadow = '0 0 30px rgba(0, 194, 255, 0.6)';
|
||||
drone.style.left = startX;
|
||||
drone.style.top = startY;
|
||||
drone.style.filter = 'blur(5px)';
|
||||
|
||||
// Create propeller effects
|
||||
const propeller = document.createElement('div');
|
||||
propeller.className = 'propeller';
|
||||
propeller.style.position = 'absolute';
|
||||
propeller.style.width = '100px';
|
||||
propeller.style.height = '100px';
|
||||
propeller.style.left = '-10px';
|
||||
propeller.style.top = '-10px';
|
||||
propeller.style.borderRadius = '50%';
|
||||
propeller.style.border = '2px solid rgba(255, 255, 255, 0.2)';
|
||||
propeller.style.animation = 'spin 2s linear infinite';
|
||||
drone.appendChild(propeller);
|
||||
|
||||
// Add animation properties
|
||||
drone.style.animation = `float-${direction} 15s ease-in-out infinite`;
|
||||
container.appendChild(drone);
|
||||
|
||||
// Add keyframes for floating animation
|
||||
const styleSheet = document.createElement('style');
|
||||
styleSheet.type = 'text/css';
|
||||
styleSheet.innerHTML = `
|
||||
@keyframes float-${direction} {
|
||||
0% { transform: translate(0, 0) rotate(0deg); }
|
||||
25% { transform: translate(${direction === 'left' ? '-' : ''}80px, 40px) rotate(${direction === 'left' ? '-' : ''}5deg); }
|
||||
50% { transform: translate(${direction === 'left' ? '-' : ''}60px, -30px) rotate(${direction === 'left' ? '-' : ''}10deg); }
|
||||
75% { transform: translate(${direction === 'left' ? '-' : ''}100px, 50px) rotate(${direction === 'left' ? '-' : ''}3deg); }
|
||||
100% { transform: translate(0, 0) rotate(0deg); }
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(styleSheet);
|
||||
}
|
||||
|
||||
function createGlowingParticle(container, subtle = false) {
|
||||
const particle = document.createElement('div');
|
||||
particle.className = 'glowing-particle';
|
||||
|
||||
// Set particle style
|
||||
const size = subtle ? Math.random() * 5 + 2 : Math.random() * 10 + 5;
|
||||
const opacity = subtle ? Math.random() * 0.3 + 0.1 : Math.random() * 0.5 + 0.2;
|
||||
|
||||
particle.style.position = 'absolute';
|
||||
particle.style.width = `${size}px`;
|
||||
particle.style.height = `${size}px`;
|
||||
particle.style.borderRadius = '50%';
|
||||
particle.style.background = 'radial-gradient(circle at center, rgba(0, 194, 255, 0.8), rgba(88, 70, 249, 0.4))';
|
||||
particle.style.boxShadow = `0 0 ${size * 2}px rgba(0, 194, 255, ${opacity})`;
|
||||
|
||||
// Random position
|
||||
particle.style.left = `${Math.random() * 100}%`;
|
||||
particle.style.top = `${Math.random() * 100}%`;
|
||||
|
||||
// Add animation with random duration
|
||||
const duration = Math.random() * 20 + 10;
|
||||
particle.style.animation = `float-particle ${duration}s ease-in-out infinite`;
|
||||
container.appendChild(particle);
|
||||
|
||||
// Add keyframes for particle animation if not already added
|
||||
if (!document.querySelector('style[data-animation="particle-float"]')) {
|
||||
const styleSheet = document.createElement('style');
|
||||
styleSheet.type = 'text/css';
|
||||
styleSheet.setAttribute('data-animation', 'particle-float');
|
||||
styleSheet.innerHTML = `
|
||||
@keyframes float-particle {
|
||||
0% { transform: translate(0, 0); }
|
||||
25% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px); }
|
||||
50% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px); }
|
||||
75% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px); }
|
||||
100% { transform: translate(0, 0); }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(styleSheet);
|
||||
}
|
||||
}
|
||||
})();
|
||||
486
html/drone/js/drone-image-animation.js
Normal file
@@ -0,0 +1,486 @@
|
||||
/**
|
||||
* Drone Image Animation with New Background
|
||||
* Uses a single image background with the drone flying over the roof
|
||||
*/
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Only run on pages that have a hero section
|
||||
const heroSection = document.querySelector('.hero');
|
||||
if (heroSection) {
|
||||
// Remove any existing backgrounds or animations
|
||||
if (heroSection.style.backgroundImage) {
|
||||
heroSection.style.backgroundImage = 'none';
|
||||
}
|
||||
|
||||
// Remove any existing animation containers
|
||||
const existingAnimations = heroSection.querySelectorAll('.drone-animation-container, .animation-container, .roof-cleaning-animation');
|
||||
existingAnimations.forEach(el => el.remove());
|
||||
|
||||
// Create our animation with the new background
|
||||
createAnimationWithSingleBackground(heroSection);
|
||||
}
|
||||
});
|
||||
|
||||
function createAnimationWithSingleBackground(container) {
|
||||
// Create animation container with more aggressive full-width styling
|
||||
const animationContainer = document.createElement('div');
|
||||
animationContainer.className = 'drone-animation-container';
|
||||
|
||||
// Position absolutely with negative margins to escape any parent padding
|
||||
animationContainer.style.position = 'absolute';
|
||||
animationContainer.style.top = '0';
|
||||
animationContainer.style.left = '0';
|
||||
animationContainer.style.right = '0'; // Add right: 0 to ensure full width
|
||||
animationContainer.style.width = '100vw'; // Use viewport width
|
||||
animationContainer.style.maxWidth = '100vw'; // Override any max-width restrictions
|
||||
animationContainer.style.marginLeft = 'calc(50% - 50vw)'; // Center regardless of parent padding
|
||||
animationContainer.style.marginRight = 'calc(50% - 50vw)'; // Center regardless of parent padding
|
||||
animationContainer.style.height = '100%';
|
||||
animationContainer.style.overflow = 'hidden';
|
||||
animationContainer.style.pointerEvents = 'none';
|
||||
animationContainer.style.zIndex = '1';
|
||||
|
||||
// Add CSS to fix any scrollbar issues
|
||||
const styleFixForScrollbar = document.createElement('style');
|
||||
styleFixForScrollbar.textContent = `
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.hero {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(styleFixForScrollbar);
|
||||
|
||||
// Fix mobile white space by adjusting the parent container on mobile
|
||||
if (window.innerWidth <= 768) {
|
||||
// Remove potential white space in parent container
|
||||
container.style.paddingBottom = '0';
|
||||
container.style.marginBottom = '0';
|
||||
}
|
||||
|
||||
// Create background using the new image
|
||||
createFullBackground(animationContainer);
|
||||
|
||||
// Create drone elements that will fly over the roof
|
||||
createFlyingDrones(animationContainer);
|
||||
|
||||
// Add everything to the container
|
||||
container.appendChild(animationContainer);
|
||||
|
||||
// Add animation styles
|
||||
addAnimationStyles();
|
||||
|
||||
// Add resize listener to adjust for screen size changes
|
||||
window.addEventListener('resize', function() {
|
||||
adjustForScreenSize(animationContainer);
|
||||
});
|
||||
|
||||
// Initial adjustment for screen size
|
||||
adjustForScreenSize(animationContainer);
|
||||
|
||||
// Position the hero content (text) in the sky area
|
||||
positionHeroContent(container);
|
||||
}
|
||||
|
||||
function createFullBackground(container) {
|
||||
// Create the full background with enhanced full-width styling
|
||||
const backgroundElement = document.createElement('div');
|
||||
backgroundElement.className = 'animation-background';
|
||||
backgroundElement.style.position = 'absolute';
|
||||
backgroundElement.style.top = '0';
|
||||
backgroundElement.style.left = '0';
|
||||
backgroundElement.style.right = '0'; // Add right: 0
|
||||
backgroundElement.style.width = '100vw'; // Use viewport width
|
||||
backgroundElement.style.maxWidth = 'none'; // No max width restrictions
|
||||
backgroundElement.style.height = '100%';
|
||||
backgroundElement.style.backgroundImage = 'url("images/animation_background1.png")';
|
||||
backgroundElement.style.backgroundSize = 'cover';
|
||||
backgroundElement.style.backgroundPosition = 'center center';
|
||||
backgroundElement.style.backgroundRepeat = 'no-repeat';
|
||||
backgroundElement.style.backgroundColor = '#75b0cc';
|
||||
backgroundElement.style.zIndex = '1';
|
||||
|
||||
// Add subtle overlay to improve text visibility
|
||||
const overlay = document.createElement('div');
|
||||
overlay.style.position = 'absolute';
|
||||
overlay.style.top = '0';
|
||||
overlay.style.left = '0';
|
||||
overlay.style.width = '100%';
|
||||
overlay.style.height = '100%';
|
||||
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.1)'; /* Subtle darkening */
|
||||
overlay.style.zIndex = '2';
|
||||
backgroundElement.appendChild(overlay);
|
||||
|
||||
container.appendChild(backgroundElement);
|
||||
|
||||
// Add resize event listener for responsive adjustments
|
||||
window.addEventListener('resize', function() {
|
||||
adjustBackground(backgroundElement);
|
||||
});
|
||||
|
||||
// Initial adjustment
|
||||
adjustBackground(backgroundElement);
|
||||
}
|
||||
|
||||
function adjustBackground(backgroundElement) {
|
||||
const isMobile = window.innerWidth <= 768;
|
||||
const isPortrait = window.innerHeight > window.innerWidth;
|
||||
|
||||
if (isMobile) {
|
||||
if (isPortrait) {
|
||||
// Portrait mobile - fix grey area by using cover and adjusting transform
|
||||
backgroundElement.style.backgroundSize = 'cover';
|
||||
backgroundElement.style.transform = 'translateY(-15%)'; // Move image up instead of using background-position
|
||||
backgroundElement.style.height = '100%'; // Ensure full height
|
||||
} else {
|
||||
// Landscape mobile - also fix using transform
|
||||
backgroundElement.style.backgroundSize = 'cover';
|
||||
backgroundElement.style.transform = 'translateY(-10%)';
|
||||
backgroundElement.style.height = '100%';
|
||||
}
|
||||
} else {
|
||||
// Desktop - standard positioning
|
||||
backgroundElement.style.backgroundSize = 'cover';
|
||||
backgroundElement.style.transform = 'none';
|
||||
backgroundElement.style.backgroundPosition = 'center center';
|
||||
}
|
||||
}
|
||||
|
||||
function positionHeroContent(container) {
|
||||
// Get the hero content (text)
|
||||
const heroContent = container.querySelector('.hero-content');
|
||||
if (heroContent) {
|
||||
// Split the content: Title in sky, rest at top of roof
|
||||
const headline = heroContent.querySelector('h2');
|
||||
const otherContent = document.createElement('div');
|
||||
otherContent.className = 'hero-secondary-content';
|
||||
|
||||
// Get all other elements except the headline
|
||||
const subheading = heroContent.querySelector('p');
|
||||
const ctaButton = heroContent.querySelector('.btn-primary');
|
||||
|
||||
// Set styles for the main container
|
||||
heroContent.style.position = 'relative';
|
||||
heroContent.style.zIndex = '5';
|
||||
heroContent.style.display = 'flex';
|
||||
heroContent.style.flexDirection = 'column';
|
||||
heroContent.style.alignItems = 'center';
|
||||
heroContent.style.justifyContent = 'space-between';
|
||||
heroContent.style.height = '100%';
|
||||
heroContent.style.textShadow = '0 2px 4px rgba(0, 0, 0, 0.3)';
|
||||
|
||||
// Style headline to be in sky - make consistent across all views
|
||||
if (headline) {
|
||||
headline.style.color = '#ffffff';
|
||||
headline.style.margin = '0 auto 2rem';
|
||||
headline.style.maxWidth = '100%'; // Changed from 90% to 100% for better text wrapping
|
||||
headline.style.textAlign = 'center';
|
||||
headline.style.position = 'relative';
|
||||
headline.style.zIndex = '6';
|
||||
headline.style.fontSize = window.innerWidth <= 480 ? '1.5rem' : (window.innerWidth <= 768 ? '1.8rem' : '3rem'); // Reduced from 1.7rem to 1.5rem for smallest screens
|
||||
headline.style.lineHeight = '1.3'; // Add line height for better text spacing
|
||||
headline.style.width = '100%'; // Ensure full width
|
||||
headline.style.wordWrap = 'break-word'; // Improve word wrapping
|
||||
headline.style.hyphens = 'none'; // Changed from 'auto' to 'none'
|
||||
headline.style.wordBreak = 'keep-all'; // Prevent words from breaking
|
||||
headline.style.whiteSpace = 'normal'; // Allow normal wrapping but prevent word splitting
|
||||
|
||||
// More mobile-friendly initial positioning
|
||||
headline.style.marginTop = window.innerWidth <= 768 ? '-3rem' : '-8rem';
|
||||
}
|
||||
|
||||
// Move other content to a separate container
|
||||
if (subheading && ctaButton) {
|
||||
// Remove elements from their current position
|
||||
subheading.remove();
|
||||
ctaButton.remove();
|
||||
|
||||
// Add them to the new container
|
||||
otherContent.appendChild(subheading);
|
||||
otherContent.appendChild(ctaButton);
|
||||
|
||||
// Style the subheading
|
||||
subheading.style.color = '#ffffff';
|
||||
subheading.style.marginBottom = '1.5rem';
|
||||
|
||||
// Style the container for other content
|
||||
otherContent.style.display = 'flex';
|
||||
otherContent.style.flexDirection = 'column';
|
||||
otherContent.style.alignItems = 'center';
|
||||
otherContent.style.position = 'relative';
|
||||
otherContent.style.zIndex = '6';
|
||||
|
||||
// Add the container to the hero content
|
||||
heroContent.appendChild(otherContent);
|
||||
}
|
||||
|
||||
// Adjust positions for different screen sizes
|
||||
adjustHeroContentPositioning(heroContent, headline, otherContent);
|
||||
window.addEventListener('resize', function() {
|
||||
adjustHeroContentPositioning(heroContent, headline, otherContent);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function adjustHeroContentPositioning(heroContent, headline, otherContent) {
|
||||
const isMobile = window.innerWidth <= 768;
|
||||
const isPortrait = window.innerHeight > window.innerWidth;
|
||||
const isSmallPhone = window.innerWidth <= 480;
|
||||
|
||||
// Apply different positioning based on device type and size
|
||||
if (headline) {
|
||||
if (isMobile) {
|
||||
if (isPortrait) {
|
||||
// Portrait mobile - adjust based on device height
|
||||
const viewportHeight = window.innerHeight;
|
||||
if (viewportHeight <= 600) {
|
||||
// Very small device
|
||||
headline.style.marginTop = '-1rem';
|
||||
} else if (viewportHeight <= 800) {
|
||||
// Medium device
|
||||
headline.style.marginTop = '-2rem';
|
||||
} else {
|
||||
// Larger device
|
||||
headline.style.marginTop = '-3rem';
|
||||
}
|
||||
} else {
|
||||
// Landscape mobile
|
||||
headline.style.marginTop = '-2rem';
|
||||
}
|
||||
} else {
|
||||
// Desktop - keep as is
|
||||
headline.style.marginTop = '-8rem';
|
||||
}
|
||||
}
|
||||
|
||||
if (otherContent) {
|
||||
otherContent.style.marginTop = 'auto';
|
||||
|
||||
if (isMobile) {
|
||||
if (isPortrait) {
|
||||
// Portrait mobile - adjust based on device height
|
||||
const viewportHeight = window.innerHeight;
|
||||
if (viewportHeight <= 600) {
|
||||
// More compact spacing for small devices
|
||||
otherContent.style.marginBottom = '3rem';
|
||||
} else if (viewportHeight <= 800) {
|
||||
otherContent.style.marginBottom = '4rem';
|
||||
} else {
|
||||
otherContent.style.marginBottom = '5rem';
|
||||
}
|
||||
|
||||
// Adjust spacing between elements for small devices
|
||||
if (isSmallPhone) {
|
||||
const subheading = otherContent.querySelector('p');
|
||||
if (subheading) {
|
||||
subheading.style.marginBottom = '1rem';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Landscape mobile
|
||||
otherContent.style.marginBottom = '3rem';
|
||||
}
|
||||
} else {
|
||||
// Desktop
|
||||
otherContent.style.marginBottom = '5rem';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function adjustHeroContent(heroContent) {
|
||||
// This function is replaced by the more specific positioning function above
|
||||
// Keep it for compatibility but it no longer needs to do anything
|
||||
}
|
||||
|
||||
function createFlyingDrones(container) {
|
||||
// Create drone path container
|
||||
const dronePathContainer = document.createElement('div');
|
||||
dronePathContainer.className = 'drone-path-container';
|
||||
dronePathContainer.style.position = 'absolute';
|
||||
dronePathContainer.style.top = '0';
|
||||
dronePathContainer.style.left = '0';
|
||||
dronePathContainer.style.width = '100%';
|
||||
dronePathContainer.style.height = '100%';
|
||||
dronePathContainer.style.zIndex = '10';
|
||||
container.appendChild(dronePathContainer);
|
||||
|
||||
// Create drone with responsive sizing
|
||||
createDrone(dronePathContainer, 'drone-path-1', 0);
|
||||
}
|
||||
|
||||
function createDrone(container, pathClass, startDelay = 0, duration = 30) {
|
||||
// Create drone element using the specified drone image
|
||||
const droneElement = document.createElement('div');
|
||||
droneElement.className = `animated-drone ${pathClass}`;
|
||||
droneElement.style.position = 'absolute';
|
||||
droneElement.style.width = '440px'; // Will be adjusted for mobile
|
||||
droneElement.style.height = '300px'; // Will be adjusted for mobile
|
||||
droneElement.style.top = '45%'; // Position for new background
|
||||
droneElement.style.left = '-450px';
|
||||
droneElement.style.zIndex = '15'; // Above all other elements
|
||||
droneElement.style.animation = `${pathClass} ${duration}s linear infinite`;
|
||||
droneElement.style.animationDelay = `${startDelay}s`;
|
||||
|
||||
// Add the drone image
|
||||
const droneImage = document.createElement('img');
|
||||
droneImage.src = 'images/spraying_drone4.png';
|
||||
droneImage.alt = 'Dachreinigungsdrohne';
|
||||
droneImage.style.width = '100%';
|
||||
droneImage.style.height = 'auto';
|
||||
droneImage.style.filter = 'drop-shadow(0 15px 30px rgba(0,0,0,0.25))';
|
||||
droneElement.appendChild(droneImage);
|
||||
|
||||
container.appendChild(droneElement);
|
||||
}
|
||||
|
||||
function adjustForScreenSize(container) {
|
||||
const isMobile = window.innerWidth <= 768;
|
||||
const isPortrait = window.innerHeight > window.innerWidth;
|
||||
|
||||
// Fix white space issue on mobile
|
||||
if (isMobile) {
|
||||
// Adjust parent container (hero section)
|
||||
const heroSection = container.closest('.hero');
|
||||
if (heroSection) {
|
||||
heroSection.style.paddingBottom = '0';
|
||||
heroSection.style.marginBottom = '0';
|
||||
// Ensure full height to bottom of viewport on mobile
|
||||
container.style.minHeight = '100%';
|
||||
}
|
||||
|
||||
// Adjust the main background element to extend fully
|
||||
const backgroundEl = container.querySelector('.animation-background');
|
||||
if (backgroundEl) {
|
||||
backgroundEl.style.bottom = '0';
|
||||
backgroundEl.style.height = '100%';
|
||||
// Add extra height to cover any potential gaps
|
||||
backgroundEl.style.marginBottom = '-2px';
|
||||
}
|
||||
}
|
||||
|
||||
const drones = container.querySelectorAll('.animated-drone');
|
||||
|
||||
// Adjust drone sizes
|
||||
drones.forEach(drone => {
|
||||
if (isMobile) {
|
||||
if (isPortrait) {
|
||||
// Portrait mobile - smaller drone
|
||||
drone.style.width = '150px';
|
||||
drone.style.height = '100px';
|
||||
} else {
|
||||
// Landscape mobile
|
||||
drone.style.width = '180px';
|
||||
drone.style.height = '120px';
|
||||
}
|
||||
} else {
|
||||
// Desktop size
|
||||
drone.style.width = '440px';
|
||||
drone.style.height = '300px';
|
||||
}
|
||||
});
|
||||
|
||||
// Adjust background
|
||||
const background = container.querySelector('.animation-background');
|
||||
if (background) {
|
||||
adjustBackground(background);
|
||||
}
|
||||
|
||||
// Add headline adjustment on resize
|
||||
const headline = document.querySelector('.hero-content h2');
|
||||
if (headline) {
|
||||
// Adjust font size based on screen width for better text wrapping
|
||||
if (window.innerWidth <= 480) {
|
||||
headline.style.fontSize = '1.5rem';
|
||||
headline.style.lineHeight = '1.3';
|
||||
headline.style.maxWidth = '100%';
|
||||
headline.style.padding = '0 0.5rem'; // Add padding for smallest screens
|
||||
headline.style.hyphens = 'none';
|
||||
headline.style.wordBreak = 'keep-all';
|
||||
headline.style.whiteSpace = 'normal';
|
||||
} else if (window.innerWidth <= 768) {
|
||||
headline.style.fontSize = '1.8rem';
|
||||
headline.style.lineHeight = '1.3';
|
||||
headline.style.maxWidth = '100%';
|
||||
headline.style.hyphens = 'none';
|
||||
headline.style.wordBreak = 'keep-all';
|
||||
headline.style.whiteSpace = 'normal';
|
||||
} else {
|
||||
headline.style.fontSize = '3rem';
|
||||
headline.style.lineHeight = '1.2';
|
||||
headline.style.maxWidth = '90%';
|
||||
headline.style.hyphens = 'none';
|
||||
headline.style.wordBreak = 'keep-all';
|
||||
headline.style.whiteSpace = 'normal';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a resize event listener to handle orientation changes
|
||||
window.addEventListener('resize', function() {
|
||||
const animationContainer = document.querySelector('.drone-animation-container');
|
||||
if (animationContainer) {
|
||||
adjustForScreenSize(animationContainer);
|
||||
}
|
||||
});
|
||||
|
||||
function addAnimationStyles() {
|
||||
// Create style element if it doesn't exist
|
||||
if (!document.getElementById('drone-animation-styles')) {
|
||||
const styleElement = document.createElement('style');
|
||||
styleElement.id = 'drone-animation-styles';
|
||||
|
||||
// Add responsive animations with adjusted drone path to match new background
|
||||
styleElement.innerHTML = `
|
||||
@keyframes drone-path-1 {
|
||||
/* First half - path adjusted for new background */
|
||||
0% { left: -450px; top: 45%; transform: rotate(0deg); }
|
||||
5% { left: 10%; top: 43%; transform: rotate(-5deg); }
|
||||
10% { left: 20%; top: 45%; transform: rotate(0deg); }
|
||||
15% { left: 30%; top: 47%; transform: rotate(5deg); }
|
||||
20% { left: 40%; top: 45%; transform: rotate(0deg); }
|
||||
25% { left: 50%; top: 48%; transform: rotate(-3deg); }
|
||||
30% { left: 60%; top: 50%; transform: rotate(0deg); }
|
||||
35% { left: 70%; top: 52%; transform: rotate(3deg); }
|
||||
40% { left: 80%; top: 50%; transform: rotate(0deg); }
|
||||
45% { left: 90%; top: 48%; transform: rotate(-5deg); }
|
||||
50% { left: 100%; top: 45%; transform: rotate(-10deg); }
|
||||
|
||||
/* Second half - return path */
|
||||
55% { left: 90%; top: 48%; transform: rotate(-5deg) scaleX(-1); }
|
||||
60% { left: 80%; top: 50%; transform: rotate(0deg) scaleX(-1); }
|
||||
65% { left: 70%; top: 52%; transform: rotate(3deg) scaleX(-1); }
|
||||
70% { left: 60%; top: 50%; transform: rotate(0deg) scaleX(-1); }
|
||||
75% { left: 50%; top: 48%; transform: rotate(-3deg) scaleX(-1); }
|
||||
80% { left: 40%; top: 45%; transform: rotate(0deg) scaleX(-1); }
|
||||
85% { left: 30%; top: 47%; transform: rotate(5deg) scaleX(-1); }
|
||||
90% { left: 20%; top: 45%; transform: rotate(0deg) scaleX(-1); }
|
||||
95% { left: 10%; top: 43%; transform: rotate(-5deg) scaleX(-1); }
|
||||
100% { left: -450px; top: 45%; transform: rotate(0deg) scaleX(-1); }
|
||||
}
|
||||
|
||||
/* Mobile-specific animations */
|
||||
@media (max-width: 768px) {
|
||||
@keyframes drone-path-1 {
|
||||
/* Adjusted path for mobile - fly higher to match the shifted background */
|
||||
0% { left: -220px; top: 45%; transform: rotate(0deg); }
|
||||
20% { left: 30%; top: 43%; transform: rotate(-5deg); }
|
||||
40% { left: 70%; top: 47%; transform: rotate(5deg); }
|
||||
50% { left: 100%; top: 45%; transform: rotate(-5deg); }
|
||||
60% { left: 70%; top: 47%; transform: rotate(5deg) scaleX(-1); }
|
||||
80% { left: 30%; top: 43%; transform: rotate(-5deg) scaleX(-1); }
|
||||
100% { left: -220px; top: 45%; transform: rotate(0deg) scaleX(-1); }
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
document.head.appendChild(styleElement);
|
||||
}
|
||||
}
|
||||
})();
|
||||
66
html/drone/js/language-manager.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Language Manager
|
||||
* Simplified to use only German language
|
||||
*/
|
||||
|
||||
const languageManager = {
|
||||
currentLang: 'de', // Default language set to German
|
||||
|
||||
init: function() {
|
||||
console.log('Initializing Language Manager');
|
||||
|
||||
// Always use German as the language
|
||||
this.currentLang = 'de';
|
||||
localStorage.setItem('preferredLanguage', 'de');
|
||||
|
||||
// Apply translations
|
||||
this.applyTranslations();
|
||||
|
||||
// Update document language attribute
|
||||
document.documentElement.lang = this.currentLang;
|
||||
|
||||
console.log(`Language Manager initialized with language: ${this.currentLang}`);
|
||||
},
|
||||
|
||||
applyTranslations: function() {
|
||||
if (typeof translations === 'undefined' || !translations['de']) {
|
||||
console.error('German translations not available');
|
||||
return;
|
||||
}
|
||||
|
||||
const elements = document.querySelectorAll('[data-i18n]');
|
||||
elements.forEach(element => {
|
||||
const key = element.getAttribute('data-i18n');
|
||||
const translation = translations['de'][key];
|
||||
if (translation) {
|
||||
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
|
||||
if (element.hasAttribute('placeholder')) {
|
||||
element.setAttribute('placeholder', translation);
|
||||
} else {
|
||||
element.value = translation;
|
||||
}
|
||||
} else {
|
||||
element.textContent = translation;
|
||||
}
|
||||
} else {
|
||||
console.warn(`Missing translation for key: ${key}`);
|
||||
}
|
||||
});
|
||||
|
||||
const altElements = document.querySelectorAll('[data-i18n-alt]');
|
||||
altElements.forEach(element => {
|
||||
const key = element.getAttribute('data-i18n-alt');
|
||||
const translation = translations['de'][key];
|
||||
if (translation) {
|
||||
element.setAttribute('alt', translation);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Applied German translations`);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize the language manager when the DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
languageManager.init();
|
||||
});
|
||||
19
html/drone/js/main.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// This file contains the main JavaScript code for the website, handling general interactivity and functionality.
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Initialize any necessary components or features
|
||||
console.log('Roof Drone Cleaning Website Loaded');
|
||||
|
||||
// Example: Smooth scroll for anchor links
|
||||
const scrollLinks = document.querySelectorAll('a[href^="#"]');
|
||||
scrollLinks.forEach(link => {
|
||||
link.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const targetId = this.getAttribute('href');
|
||||
const targetElement = document.querySelector(targetId);
|
||||
targetElement.scrollIntoView({ behavior: 'smooth' });
|
||||
});
|
||||
});
|
||||
|
||||
// Additional functionality can be added here
|
||||
});
|
||||
45
html/drone/js/mobile-menu.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Mobile navigation functionality
|
||||
* This script handles the mobile hamburger menu behavior
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Mobile navigation toggle
|
||||
const mobileToggle = document.getElementById('mobileToggle');
|
||||
const mainNav = document.getElementById('mainNav');
|
||||
|
||||
if(mobileToggle && mainNav) {
|
||||
mobileToggle.addEventListener('click', function() {
|
||||
mainNav.classList.toggle('active');
|
||||
});
|
||||
}
|
||||
|
||||
// Close mobile menu when a link is clicked
|
||||
const mobileNavLinks = document.querySelectorAll('.main-nav a');
|
||||
mobileNavLinks.forEach(link => {
|
||||
link.addEventListener('click', function() {
|
||||
if (window.innerWidth <= 768) {
|
||||
mainNav.classList.remove('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Close menu when clicking outside
|
||||
document.addEventListener('click', function(event) {
|
||||
if (window.innerWidth <= 768 &&
|
||||
!event.target.closest('.main-nav') &&
|
||||
!event.target.closest('.mobile-toggle') &&
|
||||
mainNav.classList.contains('active')) {
|
||||
mainNav.classList.remove('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure copyright year is 2025 on mobile
|
||||
const footerText = document.querySelector('footer p[data-i18n="footer_text"]');
|
||||
if (footerText) {
|
||||
// Force update the copyright year to 2025 for mobile and desktop
|
||||
const currentText = footerText.innerHTML;
|
||||
const updatedText = currentText.replace(/© \d{4}/, '© 2025');
|
||||
footerText.innerHTML = updatedText;
|
||||
}
|
||||
});
|
||||
28
html/drone/js/navigation.js
Normal file
@@ -0,0 +1,28 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Get current page path
|
||||
const currentPath = window.location.pathname;
|
||||
const isInPagesDirectory = currentPath.includes('/pages/');
|
||||
|
||||
// Handle paths based on directory
|
||||
const navLinks = document.querySelectorAll('#mainNav a');
|
||||
navLinks.forEach(link => {
|
||||
// Get href attribute
|
||||
let href = link.getAttribute('href');
|
||||
|
||||
// Fix paths if in pages directory
|
||||
if (isInPagesDirectory && href.startsWith('index.html')) {
|
||||
link.setAttribute('href', '../' + href);
|
||||
} else if (isInPagesDirectory && href.startsWith('#')) {
|
||||
link.setAttribute('href', '../index.html' + href);
|
||||
} else if (!isInPagesDirectory && href.startsWith('pages/')) {
|
||||
// No change needed for root directory links to pages
|
||||
}
|
||||
|
||||
// Set active class based on current page
|
||||
if ((currentPath.endsWith('/index.html') || currentPath.endsWith('/')) && href === 'index.html') {
|
||||
link.classList.add('active');
|
||||
} else if (currentPath.includes(href) && href !== 'index.html') {
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
268
html/drone/js/roof-cleaning-animation.js
Normal file
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* Roof Cleaning Animation
|
||||
* Shows a drone flying over a dirty roof and cleaning it in a continuous loop
|
||||
*/
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const heroSection = document.querySelector('.hero');
|
||||
if (heroSection) {
|
||||
initRoofCleaningAnimation(heroSection);
|
||||
}
|
||||
});
|
||||
|
||||
function initRoofCleaningAnimation(container) {
|
||||
// Create canvas container
|
||||
const canvasContainer = document.createElement('div');
|
||||
canvasContainer.className = 'roof-cleaning-animation';
|
||||
canvasContainer.style.position = 'absolute';
|
||||
canvasContainer.style.top = '0';
|
||||
canvasContainer.style.left = '0';
|
||||
canvasContainer.style.width = '100%';
|
||||
canvasContainer.style.height = '100%';
|
||||
canvasContainer.style.zIndex = '1';
|
||||
canvasContainer.style.pointerEvents = 'none';
|
||||
canvasContainer.style.overflow = 'hidden';
|
||||
|
||||
// Create canvas element
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = container.offsetWidth;
|
||||
canvas.height = container.offsetHeight;
|
||||
canvas.style.position = 'absolute';
|
||||
canvas.style.top = '0';
|
||||
canvas.style.left = '0';
|
||||
canvas.style.width = '100%';
|
||||
canvas.style.height = '100%';
|
||||
canvasContainer.appendChild(canvas);
|
||||
|
||||
// Add to container
|
||||
container.appendChild(canvasContainer);
|
||||
|
||||
// Set up the animation
|
||||
setupAnimation(canvas);
|
||||
|
||||
// Handle window resize
|
||||
window.addEventListener('resize', function() {
|
||||
canvas.width = container.offsetWidth;
|
||||
canvas.height = container.offsetHeight;
|
||||
setupAnimation(canvas);
|
||||
});
|
||||
}
|
||||
|
||||
function setupAnimation(canvas) {
|
||||
const ctx = canvas.getContext('2d');
|
||||
const width = canvas.width;
|
||||
const height = canvas.height;
|
||||
|
||||
// Animation variables
|
||||
let droneX = -100; // Start off-screen
|
||||
const droneY = height * 0.4; // Position drone at 40% of height
|
||||
const droneWidth = 80;
|
||||
const droneHeight = 40;
|
||||
const droneSpeed = 2;
|
||||
const cleaningWidth = 80; // Width of cleaning path
|
||||
|
||||
// Create offscreen canvases for better performance
|
||||
const roofCanvas = createRoofCanvas(width, height);
|
||||
const cleanCanvas = createCleanCanvas(width, height);
|
||||
const maskCanvas = document.createElement('canvas');
|
||||
maskCanvas.width = width;
|
||||
maskCanvas.height = height;
|
||||
const maskCtx = maskCanvas.getContext('2d');
|
||||
|
||||
// Create drone image
|
||||
const drone = new Image();
|
||||
drone.src = 'images/spraying_drone1.png';
|
||||
|
||||
// Droplets array for water spray
|
||||
const droplets = [];
|
||||
|
||||
// Animation loop
|
||||
function animate() {
|
||||
// Clear the canvas
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
// Draw sky background
|
||||
drawSky(ctx, width, height);
|
||||
|
||||
// Update drone position
|
||||
droneX += droneSpeed;
|
||||
if (droneX > width + 100) {
|
||||
// Reset drone position and partially reset mask for continuous loop
|
||||
droneX = -100;
|
||||
// Reset left side of mask
|
||||
maskCtx.clearRect(0, height * 0.45, width * 0.2, height * 0.55);
|
||||
}
|
||||
|
||||
// Update cleaning mask
|
||||
updateCleaningMask(maskCtx, droneX, droneY, cleaningWidth);
|
||||
|
||||
// Draw dirty roof
|
||||
ctx.drawImage(roofCanvas, 0, 0);
|
||||
|
||||
// Apply cleaning mask to show clean areas
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
ctx.drawImage(maskCanvas, 0, 0);
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
|
||||
// Draw clean roof in masked areas
|
||||
ctx.drawImage(cleanCanvas, 0, 0);
|
||||
|
||||
// Generate water droplets
|
||||
if (Math.random() < 0.3) { // 30% chance each frame
|
||||
createDroplet(droplets, droneX + droneWidth/2, droneY + droneHeight/2);
|
||||
}
|
||||
|
||||
// Update and draw water droplets
|
||||
updateDroplets(ctx, droplets);
|
||||
|
||||
// Draw the drone
|
||||
ctx.drawImage(drone, droneX, droneY, droneWidth, droneHeight);
|
||||
|
||||
// Continue animation loop
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
// Wait for drone image to load before starting animation
|
||||
drone.onload = function() {
|
||||
animate();
|
||||
};
|
||||
}
|
||||
|
||||
function drawSky(ctx, width, height) {
|
||||
// Create gradient for sky
|
||||
const skyGradient = ctx.createLinearGradient(0, 0, 0, height * 0.45);
|
||||
skyGradient.addColorStop(0, '#87CEEB'); // Sky blue
|
||||
skyGradient.addColorStop(1, '#e6f7ff'); // Light blue
|
||||
|
||||
ctx.fillStyle = skyGradient;
|
||||
ctx.fillRect(0, 0, width, height * 0.45);
|
||||
}
|
||||
|
||||
function createRoofCanvas(width, height) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Draw dirty roof
|
||||
const roofY = height * 0.45; // Start roof at 45% of height
|
||||
const roofHeight = height * 0.55; // Roof takes up 55% of height
|
||||
|
||||
// Base roof color (dirty brownish)
|
||||
ctx.fillStyle = '#8B4513';
|
||||
ctx.fillRect(0, roofY, width, roofHeight);
|
||||
|
||||
// Add roof tiles texture
|
||||
ctx.fillStyle = '#6B3501';
|
||||
for (let y = roofY; y < height; y += 20) {
|
||||
for (let x = 0; x < width; x += 60) {
|
||||
const offset = (Math.floor(y / 20) % 2) * 30;
|
||||
ctx.fillRect(x + offset, y, 30, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Add dirt and moss spots
|
||||
for (let i = 0; i < 200; i++) {
|
||||
const spotX = Math.random() * width;
|
||||
const spotY = roofY + Math.random() * roofHeight;
|
||||
const spotSize = 3 + Math.random() * 15;
|
||||
|
||||
ctx.fillStyle = Math.random() > 0.5 ?
|
||||
'rgba(50, 30, 0, 0.4)' : // Dirt
|
||||
'rgba(30, 70, 30, 0.3)'; // Moss
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(spotX, spotY, spotSize, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function createCleanCanvas(width, height) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Draw clean roof
|
||||
const roofY = height * 0.45;
|
||||
const roofHeight = height * 0.55;
|
||||
|
||||
// Base clean roof color (reddish-brown)
|
||||
ctx.fillStyle = '#A0522D';
|
||||
ctx.fillRect(0, roofY, width, roofHeight);
|
||||
|
||||
// Add clean roof tiles texture
|
||||
ctx.fillStyle = '#8B4513';
|
||||
for (let y = roofY; y < height; y += 20) {
|
||||
for (let x = 0; x < width; x += 60) {
|
||||
const offset = (Math.floor(y / 20) % 2) * 30;
|
||||
ctx.fillRect(x + offset, y, 30, 10);
|
||||
}
|
||||
}
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function updateCleaningMask(ctx, droneX, droneY, cleaningWidth) {
|
||||
// Create radial gradient for cleaning effect
|
||||
const gradient = ctx.createRadialGradient(
|
||||
droneX + 40, droneY + 30, 5,
|
||||
droneX + 40, droneY + 30, cleaningWidth
|
||||
);
|
||||
gradient.addColorStop(0, 'rgba(0, 0, 0, 1)');
|
||||
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
|
||||
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.beginPath();
|
||||
ctx.arc(droneX + 40, droneY + 30, cleaningWidth, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
function createDroplet(droplets, x, y) {
|
||||
droplets.push({
|
||||
x: x,
|
||||
y: y,
|
||||
size: 2 + Math.random() * 3,
|
||||
speedX: -1 + Math.random() * 2,
|
||||
speedY: 4 + Math.random() * 2,
|
||||
opacity: 0.7 + Math.random() * 0.3
|
||||
});
|
||||
|
||||
// Limit number of droplets for performance
|
||||
if (droplets.length > 50) {
|
||||
droplets.shift();
|
||||
}
|
||||
}
|
||||
|
||||
function updateDroplets(ctx, droplets) {
|
||||
// Draw water droplets
|
||||
ctx.fillStyle = '#82CAFF';
|
||||
|
||||
for (let i = 0; i < droplets.length; i++) {
|
||||
const droplet = droplets[i];
|
||||
|
||||
// Update position
|
||||
droplet.x += droplet.speedX;
|
||||
droplet.y += droplet.speedY;
|
||||
|
||||
// Reduce opacity as it falls
|
||||
droplet.opacity -= 0.02;
|
||||
|
||||
if (droplet.opacity <= 0) {
|
||||
droplets.splice(i, 1);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Draw droplet
|
||||
ctx.globalAlpha = droplet.opacity;
|
||||
ctx.beginPath();
|
||||
ctx.arc(droplet.x, droplet.y, droplet.size, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
})();
|
||||
94
html/drone/js/star-background.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Dynamic Star Background Generator
|
||||
* Creates an animated cosmic background with stars and nebulae
|
||||
*/
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Create canvas for star background if it doesn't exist
|
||||
if (!document.getElementById('stars-canvas')) {
|
||||
createStarCanvas();
|
||||
}
|
||||
});
|
||||
|
||||
function createStarCanvas() {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.id = 'stars-canvas';
|
||||
canvas.style.position = 'fixed';
|
||||
canvas.style.top = '0';
|
||||
canvas.style.left = '0';
|
||||
canvas.style.width = '100%';
|
||||
canvas.style.height = '100%';
|
||||
canvas.style.zIndex = '-1';
|
||||
canvas.style.pointerEvents = 'none';
|
||||
document.body.prepend(canvas);
|
||||
|
||||
// Make the canvas responsive
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
// Redraw on window resize
|
||||
window.addEventListener('resize', function() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
drawStarBackground(canvas);
|
||||
});
|
||||
|
||||
// Draw initial star background
|
||||
drawStarBackground(canvas);
|
||||
}
|
||||
|
||||
function drawStarBackground(canvas) {
|
||||
const ctx = canvas.getContext('2d');
|
||||
const width = canvas.width;
|
||||
const height = canvas.height;
|
||||
|
||||
// Clear canvas
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
// Create gradient background
|
||||
const bgGradient = ctx.createLinearGradient(0, 0, 0, height);
|
||||
bgGradient.addColorStop(0, '#070b1a');
|
||||
bgGradient.addColorStop(1, '#0c1426');
|
||||
ctx.fillStyle = bgGradient;
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
|
||||
// Draw nebulae
|
||||
drawNebula(ctx, width * 0.2, height * 0.3, width * 0.4, height * 0.4, '#5846f9', 0.05);
|
||||
drawNebula(ctx, width * 0.7, height * 0.7, width * 0.5, height * 0.5, '#00c2ff', 0.05);
|
||||
|
||||
// Draw stars
|
||||
const starCount = Math.floor((width * height) / 1000); // Adaptive star count
|
||||
for (let i = 0; i < starCount; i++) {
|
||||
const x = Math.random() * width;
|
||||
const y = Math.random() * height;
|
||||
const size = Math.random() * 2;
|
||||
const opacity = Math.random() * 0.8 + 0.2;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, size, 0, Math.PI * 2);
|
||||
ctx.fillStyle = `rgba(255, 255, 255, ${opacity})`;
|
||||
ctx.fill();
|
||||
|
||||
// Add glow to some stars
|
||||
if (Math.random() > 0.95) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, size * 4, 0, Math.PI * 2);
|
||||
const glowColor = Math.random() > 0.5 ? '0, 194, 255' : '88, 70, 249';
|
||||
const glow = ctx.createRadialGradient(x, y, size, x, y, size * 4);
|
||||
glow.addColorStop(0, `rgba(${glowColor}, 0.3)`);
|
||||
glow.addColorStop(1, `rgba(${glowColor}, 0)`);
|
||||
ctx.fillStyle = glow;
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawNebula(ctx, x, y, width, height, color, opacity) {
|
||||
const nebulaGradient = ctx.createRadialGradient(x, y, 10, x, y, Math.max(width, height));
|
||||
nebulaGradient.addColorStop(0, `${color}${Math.floor(opacity * 255).toString(16).padStart(2, '0')}`);
|
||||
nebulaGradient.addColorStop(1, 'transparent');
|
||||
|
||||
ctx.fillStyle = nebulaGradient;
|
||||
ctx.fillRect(x - width / 2, y - height / 2, width, height);
|
||||
}
|
||||
})();
|
||||
267
html/drone/js/translations.js
Normal file
@@ -0,0 +1,267 @@
|
||||
const translations = {
|
||||
'de': {
|
||||
// Header
|
||||
'header_title': 'Willkommen bei Luftglanz',
|
||||
'roof_drone': 'Luftglanz',
|
||||
|
||||
// Navigation
|
||||
'nav_home': 'Startseite',
|
||||
'nav_services': 'Leistungen',
|
||||
'nav_how_it_works': 'Ablauf',
|
||||
'nav_faq': 'FAQ',
|
||||
'nav_contact': 'Kontakt',
|
||||
'nav_about': 'Über Uns',
|
||||
'nav_gallery': 'Galerie',
|
||||
'nav_products': 'Produkte',
|
||||
|
||||
// Hero section
|
||||
'hero_title': 'Revolutionäre Dachreinigung mit Drohnentechnologie',
|
||||
'hero_subtitle': 'Schnelle, effiziente und unkomplizierte Reinigungslösungen für Ihr Dach.',
|
||||
|
||||
// Services section
|
||||
'services_title': 'Unsere Leistungen',
|
||||
'services_description': 'Erleben Sie modernste Drohnentechnologie für schnelle und effektive Dachreinigung und Wartung.',
|
||||
'service_standard_title': 'Umfassende Dachreinigung',
|
||||
'service_standard_description': 'Unser fortschrittlicher Reinigungsservice entfernt Schmutz, Moos und Algen.',
|
||||
'service_inspection_title': 'Detaillierte Dachinspektion',
|
||||
'service_inspection_description': 'Unsere Drohnen bieten hochauflösende Inspektionen, um potenzielle Probleme frühzeitig zu erkennen.',
|
||||
'service_solar_title': 'Solaranlagen-Reinigung',
|
||||
'service_solar_description': 'Maximieren Sie die Effizienz Ihrer Solarmodule mit unserem spezialisierten Reinigungsservice.',
|
||||
|
||||
// How it works section
|
||||
'how_it_works_title': 'So funktioniert es',
|
||||
'how_it_works_description': 'Unser optimierter Prozess sorgt für eine schnelle, effektive und stressfreie Dachreinigung.',
|
||||
'how_it_works_step1': 'Inspektion vereinbaren',
|
||||
'how_it_works_step2': 'Drohnenreinigung in Aktion',
|
||||
'how_it_works_step3': 'Genießen Sie ein sauberes Dach',
|
||||
'how_it_works_step1_desc': 'Füllen Sie unser einfaches Formular aus, um ein Angebot zu erhalten und Ihre Inspektion zu planen.',
|
||||
'how_it_works_step2_desc': 'Unsere Techniker kommen mit speziellen Drohnen und Ausrüstung, um Ihr Dach zu reinigen.',
|
||||
'how_it_works_step3_desc': 'Bewundern Sie Ihr sauberes Dach und genießen Sie die verlängerte Lebensdauer Ihres Dachmaterials.',
|
||||
|
||||
// FAQ section
|
||||
'faq_title': 'Häufig gestellte Fragen',
|
||||
'faq_q1': 'Wie lange dauert die Reinigung?',
|
||||
'faq_a1': 'Die meisten Dächer werden innerhalb von 2-4 Stunden gereinigt, abhängig von Größe und Komplexität.',
|
||||
'faq_q2': 'Ist die Drohnenreinigung sicher für mein Dach?',
|
||||
'faq_a2': 'Ja, unsere Drohnen verwenden schonende, nicht-invasive Methoden, die Ihr Dach schützen.',
|
||||
'faq_description': 'Finden Sie Antworten auf häufig gestellte Fragen zu unseren Drohnen-Dachreinigungsdiensten',
|
||||
|
||||
// Contact form
|
||||
'contact_title': 'Kontaktieren Sie uns',
|
||||
'contact_name': 'Ihr Name',
|
||||
'contact_email': 'Ihre E-Mail',
|
||||
'contact_phone': 'Telefonnummer',
|
||||
'contact_address': 'Ihre Adresse',
|
||||
'contact_message': 'Ihre Nachricht',
|
||||
'contact_reset': 'Formular löschen',
|
||||
'contact_send': 'Absenden',
|
||||
'contact_description': 'Kontaktieren Sie uns für ein kostenloses Angebot oder um mehr über unsere Dienstleistungen zu erfahren',
|
||||
|
||||
// Footer
|
||||
'footer_text': '© 2025 Luftglanz. Alle Rechte vorbehalten.',
|
||||
|
||||
// Language selection
|
||||
'language_select': 'DE',
|
||||
|
||||
// Gallery page
|
||||
'gallery_title': 'Unsere Arbeit in Aktion',
|
||||
'gallery_description': 'Entdecken Sie unsere Galerie und sehen Sie, wie unsere Drohnen außergewöhnliche Reinigungsergebnisse liefern.',
|
||||
'gallery_prev': 'Zurück',
|
||||
'gallery_next': 'Weiter',
|
||||
'gallery_image1_alt': 'Drohne reinigt ein Wohnhausdach',
|
||||
'gallery_image2_alt': 'Drohne führt Dachinspektion durch',
|
||||
'gallery_image3_alt': 'Drohne reinigt Solarmodule',
|
||||
'gallery_image4_alt': 'Nahaufnahme des Drohnenreinigungsprozesses',
|
||||
|
||||
// Chatbot
|
||||
'chatbot_title': 'Dachdrohnen-Assistent',
|
||||
'chatbot_greeting': 'Hallo! Wie kann ich Ihnen heute bei Ihren Dachreinigungsbedürfnissen helfen?',
|
||||
'chatbot_placeholder': 'Geben Sie hier Ihre Frage ein...',
|
||||
'chatbot_offline_notice': 'Derzeit offline. Bitte nutzen Sie unser Kontaktformular für Unterstützung.',
|
||||
|
||||
// Company name variations
|
||||
'roof_drone': 'Luftglanz',
|
||||
'roof_drone_cleaning': 'Luftglanz',
|
||||
|
||||
// Additional translations for missing elements
|
||||
'get_quote': 'Kostenloses Angebot',
|
||||
|
||||
// Services page
|
||||
'services_hero_title': 'Professionelle Drohnen-Dachreinigung',
|
||||
'services_hero_subtitle': 'Unsere spezialisierten Drohnen sorgen für schnelle und gründliche Reinigung mit fortschrittlicher Technologie',
|
||||
'service_drone_title': 'Drohnen-Dachreinigung',
|
||||
'service_drone_description': 'Unsere Drohnen sind mit speziellen Sprühsystemen ausgestattet, die effektiv Schmutz, Moos und Algen entfernen. Dieser kontaktlose Ansatz beseitigt das Risiko von Ziegelschäden und Arbeiterunfällen, die mit herkömmlichen Dachreinigungsmethoden verbunden sind.',
|
||||
'service_inspection_detailed_title': 'Inspektionsdienstleistungen',
|
||||
'service_inspection_detailed_description': 'Zusätzlich zur Reinigung können unsere Drohnen detaillierte Inspektionen Ihres Daches durchführen und potenzielle Probleme identifizieren, bevor sie zu kostspieligen Reparaturen werden. Unsere hochauflösenden Kameras erfassen jedes Detail und ermöglichen es uns, fehlende Schindeln, beschädigte Verkleidungen oder andere Probleme zu erkennen, die mit bloßem Auge übersehen werden könnten.',
|
||||
'service_maintenance_title': 'Wartungspakete',
|
||||
'service_maintenance_description': 'Wir bieten verschiedene Wartungspakete an, um Ihr Dach das ganze Jahr über in bestem Zustand zu halten und so Langlebigkeit und Ästhetik zu gewährleisten. Regelmäßige Wartung kann die Lebensdauer Ihres Daches um bis zu 25% verlängern und kostspielige Reparaturen verhindern. Unsere Pakete können an Ihre spezifischen Dachanforderungen und Ihr Budget angepasst werden.',
|
||||
'premium_services_title': 'Premium-Zusatzleistungen',
|
||||
'premium_services_description': 'Neben unseren Kerndienstleistungen bieten wir spezialisierte Behandlungen an, darunter Abdichtungsanwendungen, UV-Schutzbeschichtungen und Wärmescans zur Identifizierung potenzieller Wärmelecks. Diese zusätzlichen Dienstleistungen tragen dazu bei, die Leistung und Energieeffizienz Ihres Daches zu maximieren und seine Gesamtlebensdauer zu verlängern.',
|
||||
'environmental_approach_title': 'Unser Effizienzkonzept',
|
||||
'environmental_approach_description': 'Unsere präzise Drohnenanwendungsmethode reduziert den Wasserverbrauch im Vergleich zu herkömmlichen Hochdruckreinigungstechniken um bis zu 60%. Dies bedeutet eine schnellere, sauberere Reinigung in weniger Zeit.',
|
||||
|
||||
// Contact page
|
||||
'contact_page_description': 'Haben Sie Fragen zu unseren Dienstleistungen oder möchten Sie eine Reinigung planen? Kontaktieren Sie uns mit einer der folgenden Methoden.',
|
||||
'contact_phone_title': 'Telefon',
|
||||
'contact_email_title': 'E-Mail',
|
||||
'contact_address_title': 'Adresse',
|
||||
|
||||
// About page
|
||||
'about_title': 'Über unser Unternehmen',
|
||||
'about_description': 'Bei Dachdrohnen-Reinigung revolutionieren wir die Dachreinigungsbranche mit modernster Drohnentechnologie. Unser Unternehmen wurde 2020 gegründet und unsere Mission ist es, sichere, schnelle und gründliche Reinigungsdienstleistungen ohne die Risiken traditioneller Dachreinigungsmethoden anzubieten.',
|
||||
'our_story_title': 'Unsere Geschichte',
|
||||
'our_story_text': 'Die Idee für Dachdrohnen-Reinigung entstand, als unser Gründer die Gefahren erkannte, denen traditionelle Dachreiniger täglich ausgesetzt sind. Durch die Kombination von Fachwissen in Drohnentechnologie und Reinigungslösungen haben wir eine sicherere und effizientere Methode zur Dachwartung geschaffen.',
|
||||
'our_team_caption': 'Das professionelle Dachdrohnen-Reinigungsteam',
|
||||
'our_team_title': 'Unser Team',
|
||||
'our_team_text': 'Unser Team besteht aus zertifizierten Drohnenbetreibern, Dachwartungsspezialisten und Kundendienstexperten, die sich dafür einsetzen, Ihnen das bestmögliche Erlebnis zu bieten.',
|
||||
'our_technology_title': 'Unsere Technologie',
|
||||
'our_technology_text': 'Wir verwenden speziell entwickelte Drohnen, die mit hochmoderner Reinigungsausrüstung ausgestattet sind, um sicherzustellen, dass Ihr Dach schnell und gründlich gereinigt wird.',
|
||||
|
||||
// Products page
|
||||
'products_title': 'Hochwertige Reinigungsprodukte',
|
||||
'products_subtitle': 'Entdecken Sie unsere professionellen Produkte für eine optimale Dach- und Oberflächenreinigung',
|
||||
'product_details': 'Details ansehen',
|
||||
'product_buy': 'Beim Hersteller kaufen',
|
||||
'application_title': 'Anwendungshinweise',
|
||||
'application_subtitle': 'So erzielen Sie die besten Ergebnisse mit unseren Produkten',
|
||||
'ago_quart_alt': 'AGO Quart Grünbelagentferner',
|
||||
'ago_quart_1l_alt': 'AGO Quart 1 Liter Flasche',
|
||||
'ago_quart_5l_alt': 'AGO Quart 5 Liter Kanister',
|
||||
'ago_sprayer_alt': 'AGO Drucksprüher 5 Liter'
|
||||
},
|
||||
'en': {
|
||||
// Header
|
||||
'header_title': 'Welcome to Luftglanz',
|
||||
'roof_drone': 'Luftglanz',
|
||||
|
||||
// Navigation
|
||||
'nav_home': 'Home',
|
||||
'nav_services': 'Services',
|
||||
'nav_how_it_works': 'How It Works',
|
||||
'nav_faq': 'FAQ',
|
||||
'nav_contact': 'Contact',
|
||||
'nav_about': 'About Us',
|
||||
'nav_gallery': 'Gallery',
|
||||
'nav_products': 'Products',
|
||||
|
||||
// Hero section
|
||||
'hero_title': 'Revolutionary Roof Cleaning with Drone Technology',
|
||||
'hero_subtitle': 'Fast, efficient, and hassle-free cleaning solutions for your roof.',
|
||||
|
||||
// Services section
|
||||
'services_title': 'Our Services',
|
||||
'services_description': 'Experience cutting-edge drone technology for fast and effective roof cleaning and maintenance.',
|
||||
'service_standard_title': 'Comprehensive Roof Cleaning',
|
||||
'service_standard_description': 'Our advanced cleaning service removes dirt, moss, and algae, restoring your roof to its original condition.',
|
||||
'service_inspection_title': 'Detailed Roof Inspection',
|
||||
'service_inspection_description': 'Our drones provide high-resolution inspections to identify potential issues early.',
|
||||
'service_solar_title': 'Solar Panel Cleaning',
|
||||
'service_solar_description': 'Maximize the efficiency of your solar panels with our specialized cleaning service.',
|
||||
|
||||
// How it works section
|
||||
'how_it_works_title': 'How It Works',
|
||||
'how_it_works_description': 'Our streamlined process ensures fast, effective, and stress-free roof cleaning.',
|
||||
'how_it_works_step1': 'Schedule an Inspection',
|
||||
'how_it_works_step2': 'Drone Cleaning in Action',
|
||||
'how_it_works_step3': 'Enjoy a Clean Roof',
|
||||
'how_it_works_step1_desc': 'Fill out our simple form to get a quote and schedule your inspection.',
|
||||
'how_it_works_step2_desc': 'Our technicians arrive with specialized drones and equipment to clean your roof.',
|
||||
'how_it_works_step3_desc': 'Admire your clean roof and enjoy the extended lifespan of your roofing materials.',
|
||||
|
||||
// FAQ section
|
||||
'faq_title': 'Frequently Asked Questions',
|
||||
'faq_q1': 'How long does the cleaning take?',
|
||||
'faq_a1': 'Most roofs are cleaned within 2-4 hours, depending on size and complexity.',
|
||||
'faq_q2': 'Is drone cleaning safe for my roof?',
|
||||
'faq_a2': 'Yes, our drones use gentle, non-invasive methods that protect your roof.',
|
||||
'faq_description': 'Find answers to common questions about our drone roof cleaning services',
|
||||
|
||||
// Contact form
|
||||
'contact_title': 'Contact Us',
|
||||
'contact_name': 'Your Name',
|
||||
'contact_email': 'Your Email',
|
||||
'contact_phone': 'Phone Number',
|
||||
'contact_address': 'Your Address',
|
||||
'contact_message': 'Your Message',
|
||||
'contact_reset': 'Reset Form',
|
||||
'contact_send': 'Send',
|
||||
'contact_description': 'Contact us for a free quote or to learn more about our services',
|
||||
|
||||
// Footer
|
||||
'footer_text': '© 2025 Luftglanz. All rights reserved.',
|
||||
|
||||
// Language selection
|
||||
'language_select': 'EN',
|
||||
|
||||
// Gallery page
|
||||
'gallery_title': 'Our Work in Action',
|
||||
'gallery_description': 'Explore our gallery and see how our drones deliver exceptional cleaning results.',
|
||||
'gallery_prev': 'Previous',
|
||||
'gallery_next': 'Next',
|
||||
'gallery_image1_alt': 'Drone cleaning a residential roof',
|
||||
'gallery_image2_alt': 'Drone performing roof inspection',
|
||||
'gallery_image3_alt': 'Drone cleaning solar panels',
|
||||
'gallery_image4_alt': 'Close-up of drone cleaning process',
|
||||
|
||||
// Chatbot
|
||||
'chatbot_title': 'Roof Drone Assistant',
|
||||
'chatbot_greeting': 'Hello! How can I assist you today with your roof cleaning needs?',
|
||||
'chatbot_placeholder': 'Type your question here...',
|
||||
'chatbot_offline_notice': 'Currently offline. Please use our contact form for assistance.',
|
||||
|
||||
// Company name variations
|
||||
'roof_drone': 'Luftglanz',
|
||||
'roof_drone_cleaning': 'Luftglanz',
|
||||
|
||||
// Additional translations for missing elements
|
||||
'get_quote': 'Get a Free Quote',
|
||||
|
||||
// Services page
|
||||
'services_hero_title': 'Professional Drone Roof Cleaning',
|
||||
'services_hero_subtitle': 'Our specialized drones ensure fast and thorough cleaning with advanced technology',
|
||||
'service_drone_title': 'Drone Roof Cleaning',
|
||||
'service_drone_description': 'Our drones are equipped with specialized spray systems that effectively remove dirt, moss, and algae. This contactless approach eliminates the risk of tile damage and worker accidents associated with traditional roof cleaning methods.',
|
||||
'service_inspection_detailed_title': 'Inspection Services',
|
||||
'service_inspection_detailed_description': 'In addition to cleaning, our drones can perform detailed inspections of your roof, identifying potential issues before they become costly repairs. Our high-resolution cameras capture every detail, allowing us to spot missing shingles, damaged flashing, or other problems that might be overlooked with the naked eye.',
|
||||
'service_maintenance_title': 'Maintenance Packages',
|
||||
'service_maintenance_description': 'We offer various maintenance packages to keep your roof in top condition year-round, ensuring longevity and aesthetics. Regular maintenance can extend the lifespan of your roof by up to 25% and prevent costly repairs. Our packages can be tailored to your specific roof requirements and budget.',
|
||||
'premium_services_title': 'Premium Add-On Services',
|
||||
'premium_services_description': 'In addition to our core services, we offer specialized treatments, including sealing applications, UV protection coatings, and thermal scans to identify potential heat leaks. These additional services help maximize your roof’s performance and energy efficiency while extending its overall lifespan.',
|
||||
'environmental_approach_title': 'Our Efficiency Concept',
|
||||
'environmental_approach_description': 'Our precise drone application method reduces water usage by up to 60% compared to traditional pressure washing techniques. This means faster, cleaner results in less time.',
|
||||
|
||||
// Contact page
|
||||
'contact_page_description': 'Have questions about our services or want to schedule a cleaning? Contact us using one of the following methods.',
|
||||
'contact_phone_title': 'Phone',
|
||||
'contact_email_title': 'Email',
|
||||
'contact_address_title': 'Address',
|
||||
|
||||
// About page
|
||||
'about_title': 'About Our Company',
|
||||
'about_description': 'At Roof Drone Cleaning, we are revolutionizing the roof cleaning industry with cutting-edge drone technology. Founded in 2020, our mission is to provide safe, fast, and thorough cleaning services without the risks of traditional roof cleaning methods.',
|
||||
'our_story_title': 'Our Story',
|
||||
'our_story_text': 'The idea for Roof Drone Cleaning came when our founder recognized the dangers traditional roof cleaners face daily. By combining expertise in drone technology and cleaning solutions, we have created a safer and more efficient method for roof maintenance.',
|
||||
'our_team_caption': 'The Professional Roof Drone Cleaning Team',
|
||||
'our_team_title': 'Our Team',
|
||||
'our_team_text': 'Our team consists of certified drone operators, roof maintenance specialists, and customer service experts dedicated to providing you with the best experience possible.',
|
||||
'our_technology_title': 'Our Technology',
|
||||
'our_technology_text': 'We use specially designed drones equipped with state-of-the-art cleaning equipment to ensure your roof is cleaned quickly and thoroughly.',
|
||||
|
||||
// Products page
|
||||
'products_title': 'High-Quality Cleaning Products',
|
||||
'products_subtitle': 'Discover our professional products for optimal roof and surface cleaning',
|
||||
'product_details': 'View Details',
|
||||
'product_buy': 'Buy from Manufacturer',
|
||||
'application_title': 'Application Instructions',
|
||||
'application_subtitle': 'Achieve the best results with our products',
|
||||
'ago_quart_alt': 'AGO Quart Green Stain Remover',
|
||||
'ago_quart_1l_alt': 'AGO Quart 1 Liter Bottle',
|
||||
'ago_quart_5l_alt': 'AGO Quart 5 Liter Canister',
|
||||
'ago_sprayer_alt': 'AGO Pressure Sprayer 5 Liter'
|
||||
}
|
||||
};
|
||||
|
||||
// Export the translations object
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = translations;
|
||||
}
|
||||
320
html/drone/pages/about.html
Normal file
@@ -0,0 +1,320 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Über Uns - Luftglanz</title>
|
||||
<link rel="icon" href="../images/favicon_logo.png" type="image/png">
|
||||
<link rel="stylesheet" href="../css/normalize.css">
|
||||
<link rel="stylesheet" href="../css/main.css">
|
||||
<link rel="stylesheet" href="../css/components/header.css">
|
||||
<link rel="stylesheet" href="../css/components/footer.css">
|
||||
<link rel="stylesheet" href="../css/components/hero.css">
|
||||
<link rel="stylesheet" href="../css/components/forms.css">
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #3498db; /* Clean blue primary */
|
||||
--accent-color: #00c2cb; /* Teal accent */
|
||||
--secondary-color: #505050;
|
||||
--bg-light: #f8f9fa; /* Very light background */
|
||||
--card-bg: #ffffff; /* White card background */
|
||||
--text-dark: #333333;
|
||||
--text-medium: #505050;
|
||||
--text-light: #707070;
|
||||
--gradient-primary: linear-gradient(90deg, #3498db 0%, #00c2cb 100%);
|
||||
--gradient-secondary: linear-gradient(90deg, #2980b9 0%, #009ea6 100%);
|
||||
--shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
--spacing-section: 5rem 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Inter', 'Segoe UI', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: var(--text-medium);
|
||||
background-color: var(--bg-light);
|
||||
background-image:
|
||||
linear-gradient(120deg, rgba(0, 120, 212, 0.05) 0%, transparent 40%),
|
||||
linear-gradient(240deg, rgba(0, 178, 148, 0.05) 0%, transparent 40%);
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
header {
|
||||
padding: 1.5rem 0;
|
||||
background: rgba(232, 233, 234, 0.95); /* Changed to match --bg-light variable */
|
||||
backdrop-filter: blur(8px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
background: var(--gradient-primary);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.main-nav ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.main-nav li {
|
||||
margin-right: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
color: var(--text-medium);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 0.5rem 0;
|
||||
position: relative;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover, .main-nav a.active {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.main-nav a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: var(--gradient-primary);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover::after, .main-nav a.active::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.main-nav ul {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-nav li {
|
||||
margin-right: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.section-container {
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 10px;
|
||||
margin-bottom: 2rem;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
padding: 2.5rem;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.section-container h2 {
|
||||
color: var(--text-dark);
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: 2rem;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.section-container h2::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
height: 3px;
|
||||
background: var(--gradient-primary);
|
||||
bottom: -0.75rem;
|
||||
left: 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.section-container h3 {
|
||||
color: var(--text-dark);
|
||||
font-size: 1.5rem;
|
||||
margin-top: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.section-container p {
|
||||
color: var(--text-light);
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.team-image-container {
|
||||
margin: 3rem 0 !important;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.team-image-container img {
|
||||
width: 100%;
|
||||
display: block;
|
||||
border-radius: 10px;
|
||||
filter: brightness(0.9);
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
.team-image-container:hover img {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.team-image-container p {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(to top, rgba(255, 255, 255, 0.9), transparent);
|
||||
padding: 2rem 1.5rem 1rem;
|
||||
margin: 0;
|
||||
color: var(--text-medium);
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stars {
|
||||
display: none;
|
||||
}
|
||||
|
||||
main {
|
||||
padding-top: 8rem;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: var(--text-dark);
|
||||
padding: 2rem 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
text-align: center;
|
||||
color: #aaaaaa;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<div class="logo">
|
||||
<img src="../images/favicon_logo.png" alt="Luftglanz Logo" class="logo-img">
|
||||
<h1 data-i18n="roof_drone">Luftglanz</h1>
|
||||
</div>
|
||||
|
||||
<button class="mobile-toggle" id="mobileToggle">
|
||||
<span>☰</span>
|
||||
</button>
|
||||
|
||||
<nav class="main-nav" id="mainNav">
|
||||
<ul>
|
||||
<li><a href="../index.html" data-i18n="nav_home">Home</a></li>
|
||||
<li><a href="../index.html#services" data-i18n="nav_services">Services</a></li>
|
||||
<li><a href="../index.html#how-it-works" data-i18n="nav_how_it_works">How It Works</a></li>
|
||||
<li><a href="../index.html#faq" data-i18n="nav_faq">FAQ</a></li>
|
||||
<li><a href="../index.html#contact" data-i18n="nav_contact">Contact</a></li>
|
||||
<li><a href="products.html" data-i18n="nav_products">Products</a></li>
|
||||
<li><a href="about.html" class="active" data-i18n="nav_about">About Us</a></li>
|
||||
<li><a href="gallery.html" data-i18n="nav_gallery">Gallery</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Language switcher removed -->
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<section class="section-container">
|
||||
<h2 data-i18n="about_title">About Our Company</h2>
|
||||
<p data-i18n="about_description">Bei Dachdrohnen-Reinigung revolutionieren wir die Dachreinigungsbranche mit modernster Drohnentechnologie. Unser Unternehmen wurde 2020 gegründet und unsere Mission ist es, sichere, schnelle und gründliche Reinigungsdienstleistungen ohne die Risiken traditioneller Dachreinigungsmethoden anzubieten.</p>
|
||||
|
||||
<h3 data-i18n="our_story_title">Our Story</h3>
|
||||
<p data-i18n="our_story_text">The idea for Roof Drone Cleaning came when our founder noticed the dangers that traditional roof cleaners faced daily. By combining expertise in drone technology and cleaning solutions, we created a safer, more efficient method for roof maintenance.</p>
|
||||
|
||||
<div class="team-image-container">
|
||||
<img src="../images/out_team.jpg" alt="Our professional team">
|
||||
<p data-i18n="our_team_caption">The Roof Drone Cleaning professional team</p>
|
||||
</div>
|
||||
|
||||
<h3 data-i18n="our_team_title">Our Team</h3>
|
||||
<p data-i18n="our_team_text">Our team consists of certified drone operators, roof maintenance specialists, and customer service experts dedicated to providing you with the best possible experience.</p>
|
||||
|
||||
<h3 data-i18n="our_technology_title">Unsere Technologie</h3>
|
||||
<p data-i18n="our_technology_text">Wir verwenden speziell entwickelte Drohnen, die mit hochmoderner Reinigungsausrüstung ausgestattet sind, um sicherzustellen, dass Ihr Dach schnell und gründlich gereinigt wird.</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p data-i18n="footer_text">© 2023 Luftglanz. Alle Rechte vorbehalten.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="../js/translations.js"></script>
|
||||
<script src="../js/language-manager.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
583
html/drone/pages/contact.html
Normal file
@@ -0,0 +1,583 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kontakt - Luftglanz</title>
|
||||
<link rel="icon" href="../images/favicon_logo.png" type="image/png">
|
||||
<link rel="stylesheet" href="../css/normalize.css">
|
||||
<link rel="stylesheet" href="../css/main.css">
|
||||
<link rel="stylesheet" href="../css/components/header.css">
|
||||
<link rel="stylesheet" href="../css/components/footer.css">
|
||||
<link rel="stylesheet" href="../css/components/hero.css">
|
||||
<link rel="stylesheet" href="../css/components/forms.css">
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #3498db; /* Clean blue primary */
|
||||
--accent-color: #00c2cb; /* Teal accent */
|
||||
--secondary-color: #505050;
|
||||
--bg-light: #f8f9fa; /* Very light background */
|
||||
--card-bg: #ffffff; /* White card background */
|
||||
--text-dark: #333333;
|
||||
--text-medium: #505050;
|
||||
--text-light: #707070;
|
||||
--gradient-primary: linear-gradient(90deg, #3498db 0%, #00c2cb 100%);
|
||||
--gradient-secondary: linear-gradient(90deg, #2980b9 0%, #009ea6 100%);
|
||||
--shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
--spacing-section: 5rem 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Inter', 'Segoe UI', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: var(--text-medium);
|
||||
background-color: var(--bg-light);
|
||||
background-image:
|
||||
linear-gradient(120deg, rgba(0, 120, 212, 0.05) 0%, transparent 40%),
|
||||
linear-gradient(240deg, rgba(0, 178, 148, 0.05) 0%, transparent 40%);
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Header styling */
|
||||
header {
|
||||
padding: 1.5rem 0;
|
||||
background: rgba(232, 233, 234, 0.95); /* Changed to match --bg-light variable */
|
||||
backdrop-filter: blur(8px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
background: var(--gradient-primary);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* Navigation styling */
|
||||
.main-nav ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
color: var(--text-medium);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 0.5rem 0;
|
||||
position: relative;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover, .main-nav a.active {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.main-nav a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: var(--gradient-primary);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover::after, .main-nav a.active::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Section styling */
|
||||
.section-container {
|
||||
padding: 2.5rem;
|
||||
margin-bottom: 2rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
position: relative;
|
||||
color: var(--text-dark);
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.section-title::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
height: 3px;
|
||||
background: var(--gradient-primary);
|
||||
bottom: -1rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.section-description {
|
||||
text-align: center;
|
||||
color: var(--text-light);
|
||||
max-width: 800px;
|
||||
margin: 0 auto 3rem;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
/* Contact info cards */
|
||||
.contact-info {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.contact-method {
|
||||
background-color: var(--card-bg);
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border-radius: 10px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.contact-method:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.contact-method h3 {
|
||||
color: var(--text-dark);
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.3rem;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.contact-method h3::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 2px;
|
||||
background: var(--gradient-primary);
|
||||
bottom: -0.5rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.contact-method p {
|
||||
color: var(--text-light);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Contact form */
|
||||
.contact-form {
|
||||
background-color: var(--card-bg);
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border-radius: 10px;
|
||||
padding: 2.5rem;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text-medium);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-group input,
|
||||
.form-group textarea,
|
||||
.form-group select {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border-radius: 6px;
|
||||
color: var(--text-medium);
|
||||
font-size: 1rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.form-group input:focus,
|
||||
.form-group textarea:focus,
|
||||
.form-group select:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent-color);
|
||||
box-shadow: 0 0 0 2px rgba(0, 194, 203, 0.2);
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--gradient-primary);
|
||||
color: var(--text-dark);
|
||||
border: none;
|
||||
padding: 0.8rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
flex-grow: 1;
|
||||
box-shadow: var(--shadow);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 0 20px rgba(0, 194, 203, 0.6);
|
||||
}
|
||||
|
||||
.btn-primary::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--gradient-secondary);
|
||||
border-radius: 6px;
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-primary:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
color: var(--text-medium);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding: 0.8rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Language Switcher - Updated to match About Us page */
|
||||
.language-switcher {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.language-switcher button {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: var(--text-medium);
|
||||
padding: 0.4rem 0.75rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.language-switcher button.active,
|
||||
.language-switcher button:hover {
|
||||
background: var(--gradient-primary);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
/* Stars Background */
|
||||
.stars {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.star {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
opacity: 0.5;
|
||||
animation: twinkling 4s infinite;
|
||||
}
|
||||
|
||||
@keyframes twinkling {
|
||||
0% { opacity: 0.2; }
|
||||
50% { opacity: 0.5; }
|
||||
100% { opacity: 0.2; }
|
||||
}
|
||||
|
||||
/* Footer styling */
|
||||
footer {
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
padding: 2rem 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
text-align: center;
|
||||
color: var(--text-light);
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
main {
|
||||
padding-top: 8rem;
|
||||
}
|
||||
|
||||
/* Mobile styles */
|
||||
@media (max-width: 768px) {
|
||||
.main-nav {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
padding: 1rem 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.main-nav.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main-nav ul {
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.main-nav li {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 0.5rem 0;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.main-nav li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
display: block;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.contact-form {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.contact-method {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Stars background -->
|
||||
<div class="stars" id="stars"></div>
|
||||
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<div class="logo">
|
||||
<img src="../images/favicon_logo.png" alt="Luftglanz Logo" class="logo-img">
|
||||
<h1 data-i18n="roof_drone">Luftglanz</h1>
|
||||
</div>
|
||||
|
||||
<nav class="main-nav" id="mainNav">
|
||||
<ul>
|
||||
<li><a href="../index.html" data-i18n="nav_home">Home</a></li>
|
||||
<li><a href="../index.html#services" data-i18n="nav_services">Services</a></li>
|
||||
<li><a href="../index.html#how-it-works" data-i18n="nav_how_it_works">How It Works</a></li>
|
||||
<li><a href="../index.html#faq" data-i18n="nav_faq">FAQ</a></li>
|
||||
<li><a href="#" class="active" data-i18n="nav_contact">Contact</a></li>
|
||||
<li><a href="products.html" data-i18n="nav_products">Products</a></li>
|
||||
<li><a href="gallery.html" data-i18n="nav_gallery">Gallery</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Language switcher removed -->
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="section-container">
|
||||
<div class="container">
|
||||
<h2 class="section-title" data-i18n="contact_title">Contact Us</h2>
|
||||
<p class="section-description" data-i18n="contact_page_description">Have questions about our services or want to schedule a cleaning? Get in touch with us using any of the methods below.</p>
|
||||
|
||||
<div class="contact-info">
|
||||
<div class="contact-method">
|
||||
<h3 data-i18n="contact_phone_title">Phone</h3>
|
||||
<p>(555) 123-4567</p>
|
||||
</div>
|
||||
|
||||
<div class="contact-method">
|
||||
<h3 data-i18n="contact_email_title">Email</h3>
|
||||
<p>info@roofdronecleaning.com</p>
|
||||
</div>
|
||||
|
||||
<div class="contact-method">
|
||||
<h3 data-i18n="contact_address_title">Address</h3>
|
||||
<p>123 Cleaning Ave<br>Drone City, DC 10001</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="contact-form">
|
||||
<div class="form-group">
|
||||
<label for="name" data-i18n="contact_name">Name</label>
|
||||
<input type="text" id="name" name="name" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email" data-i18n="contact_email">Email</label>
|
||||
<input type="email" id="email" name="email" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="phone" data-i18n="contact_phone">Phone (Optional)</label>
|
||||
<input type="tel" id="phone" name="phone">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="address" data-i18n="contact_address">Address</label>
|
||||
<input type="text" id="address" name="address">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message" data-i18n="contact_message">Message</label>
|
||||
<textarea id="message" name="message" required rows="4"></textarea>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn-secondary" id="resetForm" data-i18n="contact_reset">Reset</button>
|
||||
<button type="submit" class="btn-primary" data-i18n="contact_send">Send Message</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p data-i18n="footer_text">© 2023 Luftglanz. Alle Rechte vorbehalten.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="../js/translations.js"></script>
|
||||
<script src="../js/language-manager.js"></script>
|
||||
<script>
|
||||
// Add star backgrounds dynamically
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const starsContainer = document.getElementById('stars');
|
||||
const starsCount = 100;
|
||||
|
||||
for(let i = 0; i < starsCount; i++) {
|
||||
const star = document.createElement('div');
|
||||
star.classList.add('star');
|
||||
|
||||
// Random position
|
||||
star.style.left = `${Math.random() * 100}%`;
|
||||
star.style.top = `${Math.random() * 100}%`;
|
||||
|
||||
// Random size
|
||||
const size = Math.random() * 2;
|
||||
star.style.width = `${size}px`;
|
||||
star.style.height = `${size}px`;
|
||||
|
||||
// Random delay for twinkling
|
||||
star.style.animationDelay = `${Math.random() * 4}s`;
|
||||
|
||||
starsContainer.appendChild(star);
|
||||
}
|
||||
|
||||
// Reset form functionality
|
||||
const resetButton = document.getElementById('resetForm');
|
||||
const contactForm = document.querySelector('.contact-form');
|
||||
|
||||
if (resetButton && contactForm) {
|
||||
resetButton.addEventListener('click', function() {
|
||||
contactForm.reset();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
573
html/drone/pages/gallery.html
Normal file
@@ -0,0 +1,573 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Galerie - Luftglanz</title>
|
||||
<link rel="icon" href="../images/favicon_logo.png" type="image/png">
|
||||
<link rel="stylesheet" href="../css/normalize.css">
|
||||
<link rel="stylesheet" href="../css/main.css">
|
||||
<link rel="stylesheet" href="../css/components/header.css">
|
||||
<link rel="stylesheet" href="../css/components/footer.css">
|
||||
<link rel="stylesheet" href="../css/components/hero.css">
|
||||
<link rel="stylesheet" href="../css/components/forms.css">
|
||||
<link rel="stylesheet" href="../css/components/mobile-menu.css">
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #3498db; /* Clean blue primary */
|
||||
--accent-color: #00c2cb; /* Teal accent */
|
||||
--secondary-color: #505050;
|
||||
--bg-light: #f8f9fa; /* Very light background */
|
||||
--card-bg: #ffffff; /* White card background */
|
||||
--text-dark: #333333;
|
||||
--text-medium: #505050;
|
||||
--text-light: #707070;
|
||||
--gradient-primary: linear-gradient(90deg, #3498db 0%, #00c2cb 100%);
|
||||
--gradient-secondary: linear-gradient(90deg, #2980b9 0%, #009ea6 100%);
|
||||
--shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
--spacing-section: 5rem 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Inter', 'Segoe UI', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: var(--text-medium);
|
||||
background-color: var(--bg-light);
|
||||
background-image:
|
||||
linear-gradient(120deg, rgba(0, 120, 212, 0.05) 0%, transparent 40%),
|
||||
linear-gradient(240deg, rgba(0, 178, 148, 0.05) 0%, transparent 40%);
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Header styling */
|
||||
header {
|
||||
padding: 1.5rem 0;
|
||||
background: rgba(232, 233, 234, 0.95); /* Changed to match --bg-light variable */
|
||||
backdrop-filter: blur(8px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
background: var(--gradient-primary);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* Navigation styling */
|
||||
.main-nav ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
color: var(--text-medium);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 0.5rem 0;
|
||||
position: relative;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover, .main-nav a.active {
|
||||
color: var (--accent-color);
|
||||
}
|
||||
|
||||
.main-nav a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: var(--gradient-primary);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover::after, .main-nav a.active::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Section styling */
|
||||
.section-container {
|
||||
padding: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 6rem; /* Increased to move content below header */
|
||||
padding-top: 2rem;
|
||||
}
|
||||
|
||||
.section-container h2 {
|
||||
display: block; /* Changed from none to block */
|
||||
font-size: 2.2rem;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.section-container p {
|
||||
color: var(--text-light);
|
||||
margin-bottom: 2rem;
|
||||
text-align: center;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* Gallery grid styling */
|
||||
.gallery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.gallery-item {
|
||||
position: relative;
|
||||
aspect-ratio: 3/2;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.gallery-item:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.gallery-item::after {
|
||||
content: '🔍';
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.gallery-item:hover::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Lightbox styling */
|
||||
.lightbox {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.lightbox.active {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.lightbox-content {
|
||||
position: relative;
|
||||
max-width: 90%;
|
||||
max-height: 80%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.lightbox-image {
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 5px 30px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.lightbox-close {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
color: white;
|
||||
font-size: 30px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.lightbox-close:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.lightbox-nav {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 20px;
|
||||
transform: translateY(-50%);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.lightbox-nav button {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: white;
|
||||
border: none;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lightbox-nav button:hover {
|
||||
background: var(--gradient-primary);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.lightbox-counter {
|
||||
position: absolute;
|
||||
bottom: -40px;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Adjust main content to start lower */
|
||||
main {
|
||||
padding-top: 5rem; /* Keep this to account for the fixed header */
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Mobile adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.gallery-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.lightbox-nav button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Language Switcher - Updated to match About Us page */
|
||||
.language-switcher {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.language-switcher button {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: var(--text-medium);
|
||||
padding: 0.4rem 0.75rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.language-switcher button.active,
|
||||
.language-switcher button:hover {
|
||||
background: var(--gradient-primary);
|
||||
border-color: transparent;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Remove stars background -->
|
||||
<!-- <div class="stars" id="stars"></div> -->
|
||||
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<div class="logo">
|
||||
<a href="../index.html" style="text-decoration: none; display: flex; align-items: center;">
|
||||
<img src="../images/favicon_logo.png" alt="Luftglanz Logo" class="logo-img">
|
||||
<h1 data-i18n="roof_drone">Luftglanz</h1>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<button class="mobile-toggle" id="mobileToggle" aria-label="Toggle navigation">
|
||||
☰
|
||||
</button>
|
||||
|
||||
<nav class="main-nav" id="mainNav">
|
||||
<ul>
|
||||
<li><a href="../index.html" data-i18n="nav_home">Startseite</a></li>
|
||||
<li><a href="../index.html#services" data-i18n="nav_services">Leistungen</a></li>
|
||||
<li><a href="../index.html#how-it-works" data-i18n="nav_how_it_works">Ablauf</a></li>
|
||||
<li><a href="../index.html#faq" data-i18n="nav_faq">FAQ</a></li>
|
||||
<li><a href="#" class="contact-link" data-i18n="nav_contact">Kontakt</a></li>
|
||||
<li><a href="products.html" data-i18n="nav_products">Produkte</a></li>
|
||||
<li><a href="gallery.html" class="active" data-i18n="nav_gallery">Galerie</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<section class="section-container">
|
||||
<h2 data-i18n="gallery_title">Unsere Arbeit</h2>
|
||||
<p data-i18n="gallery_description">Entdecken Sie unsere Galerie, um zu sehen, wie unsere Drohnen außergewöhnliche Reinigungsergebnisse liefern.</p>
|
||||
|
||||
<div class="gallery-grid">
|
||||
<div class="gallery-item">
|
||||
<img src="../images/drone_realistic1.png" alt="Realistic Drone Cleaning" class="gallery-image" data-i18n-alt="gallery_drone_realistic_alt">
|
||||
</div>
|
||||
<div class="gallery-item">
|
||||
<img src="../images/drone_realistic3.png" alt="Advanced Drone Cleaning Technology" class="gallery-image" data-i18n-alt="gallery_drone_realistic3_alt">
|
||||
</div>
|
||||
<div class="gallery-item">
|
||||
<img src="../images/drone_realistic4.png" alt="Professional Drone Cleaning System" class="gallery-image" data-i18n-alt="gallery_drone_realistic4_alt">
|
||||
</div>
|
||||
<div class="gallery-item">
|
||||
<img src="../images/drone_in_action1.jpg" alt="" data-i18n-alt="gallery_image1_alt">
|
||||
</div>
|
||||
<div class="gallery-item">
|
||||
<img src="../images/drone_realistic5.png" alt="" data-i18n-alt="gallery_image3_alt">
|
||||
</div>
|
||||
<div class="gallery-item">
|
||||
<img src="../images/drone_realistic6.png" alt="" data-i18n-alt="gallery_image4_alt">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div class="lightbox" id="lightbox">
|
||||
<div class="lightbox-content">
|
||||
<img src="" alt="" class="lightbox-image" id="lightbox-image">
|
||||
<div class="lightbox-counter" id="lightbox-counter"></div>
|
||||
</div>
|
||||
<div class="lightbox-close" id="lightbox-close">✕</div>
|
||||
<div class="lightbox-nav">
|
||||
<button id="lightbox-prev" data-i18n="gallery_prev">Zurück</button>
|
||||
<button id="lightbox-next" data-i18n="gallery_next">Weiter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p data-i18n="footer_text">© 2025 Luftglanz. Alle Rechte vorbehalten.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="../js/translations.js"></script>
|
||||
<script src="../js/language-manager.js"></script>
|
||||
<!-- Remove drone animation script -->
|
||||
<!-- <script src="../js/drone-image-animation.js"></script> -->
|
||||
<script src="../js/mobile-menu.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Set up lightbox functionality
|
||||
setupLightbox();
|
||||
});
|
||||
|
||||
function setupLightbox() {
|
||||
// Get all necessary lightbox elements
|
||||
const lightbox = document.getElementById('lightbox');
|
||||
const lightboxImage = document.getElementById('lightbox-image');
|
||||
const lightboxClose = document.getElementById('lightbox-close');
|
||||
const lightboxPrev = document.getElementById('lightbox-prev');
|
||||
const lightboxNext = document.getElementById('lightbox-next');
|
||||
const lightboxCounter = document.getElementById('lightbox-counter');
|
||||
const galleryItems = document.querySelectorAll('.gallery-item img');
|
||||
|
||||
// Make sure elements exist
|
||||
if (!lightbox || !lightboxImage || galleryItems.length === 0) {
|
||||
console.error('Lightbox elements not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Track the current image index
|
||||
let currentIndex = 0;
|
||||
|
||||
// Function to update counter
|
||||
function updateCounter() {
|
||||
if (lightboxCounter) {
|
||||
lightboxCounter.textContent = `${currentIndex + 1} / ${galleryItems.length}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Open lightbox when gallery image is clicked
|
||||
galleryItems.forEach((item, index) => {
|
||||
item.addEventListener('click', function() {
|
||||
currentIndex = index;
|
||||
lightboxImage.src = item.src;
|
||||
lightboxImage.alt = item.alt;
|
||||
lightbox.classList.add('active');
|
||||
document.body.style.overflow = 'hidden'; // Prevent scrolling
|
||||
updateCounter();
|
||||
});
|
||||
});
|
||||
|
||||
// Navigate to previous image
|
||||
if (lightboxPrev) {
|
||||
lightboxPrev.addEventListener('click', function(e) {
|
||||
e.stopPropagation(); // Prevent event bubbling to lightbox
|
||||
currentIndex = (currentIndex > 0) ? currentIndex - 1 : galleryItems.length - 1;
|
||||
lightboxImage.src = galleryItems[currentIndex].src;
|
||||
lightboxImage.alt = galleryItems[currentIndex].alt;
|
||||
updateCounter();
|
||||
});
|
||||
}
|
||||
|
||||
// Navigate to next image
|
||||
if (lightboxNext) {
|
||||
lightboxNext.addEventListener('click', function(e) {
|
||||
e.stopPropagation(); // Prevent event bubbling to lightbox
|
||||
currentIndex = (currentIndex < galleryItems.length - 1) ? currentIndex + 1 : 0;
|
||||
lightboxImage.src = galleryItems[currentIndex].src;
|
||||
lightboxImage.alt = galleryItems[currentIndex].alt;
|
||||
updateCounter();
|
||||
});
|
||||
}
|
||||
|
||||
// Close lightbox when close button is clicked
|
||||
if (lightboxClose) {
|
||||
lightboxClose.addEventListener('click', function() {
|
||||
lightbox.classList.remove('active');
|
||||
document.body.style.overflow = ''; // Re-enable scrolling
|
||||
});
|
||||
}
|
||||
|
||||
// Close lightbox when clicking outside the image
|
||||
lightbox.addEventListener('click', function(e) {
|
||||
if (e.target === lightbox) {
|
||||
lightbox.classList.remove('active');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Prevent closing when clicking on image
|
||||
lightboxImage.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// Keyboard navigation
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (lightbox.classList.contains('active')) {
|
||||
if (e.key === 'ArrowLeft' && lightboxPrev) {
|
||||
lightboxPrev.click();
|
||||
} else if (e.key === 'ArrowRight' && lightboxNext) {
|
||||
lightboxNext.click();
|
||||
} else if (e.key === 'Escape') {
|
||||
lightbox.classList.remove('active');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Handle contact link with consistent offset
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const contactLink = document.querySelector('.contact-link');
|
||||
if (contactLink) {
|
||||
contactLink.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = '../index.html#contact';
|
||||
|
||||
// Apply the same offset as the main page
|
||||
setTimeout(function() {
|
||||
if (window.location.hash === '#contact') {
|
||||
const contactSection = document.querySelector('#contact');
|
||||
if (contactSection) {
|
||||
window.scrollTo({
|
||||
top: contactSection.offsetTop - (-5), // Same -5px offset
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
103
html/drone/pages/products-debug.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Products Debug - Luftglanz</title>
|
||||
<style>
|
||||
/* Minimal styling to ensure visibility */
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.debug-info {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: red;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
z-index: 9999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #e8e9ea;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 40px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.product-card {
|
||||
border: 1px solid #ddd;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="debug-info">DEBUG MODE</div>
|
||||
|
||||
<header>
|
||||
<div class="logo">
|
||||
<img src="../images/favicon_logo.png" alt="Luftglanz Logo" class="logo-img">
|
||||
<h1>Luftglanz</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<h2>Products (Debug Version)</h2>
|
||||
|
||||
<div class="product-card">
|
||||
<h3>AGO Quart Grünbelagentferner</h3>
|
||||
<p>Test product description to verify content visibility</p>
|
||||
<p><strong>Price:</strong> 24,90 €</p>
|
||||
<a href="https://www.agoshop.de/gruenbelagentferner/ago-quart/" target="_blank">View on Manufacturer's Site</a>
|
||||
</div>
|
||||
|
||||
<div class="product-card">
|
||||
<h3>AGO Quart 5 Liter</h3>
|
||||
<p>Test product description to verify content visibility</p>
|
||||
<p><strong>Price:</strong> 99,90 €</p>
|
||||
<a href="https://www.agoshop.de/gruenbelagentferner/ago-quart-5-liter/" target="_blank">View on Manufacturer's Site</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Display debugging information
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('Debug page loaded');
|
||||
|
||||
// Check if elements are visible
|
||||
const header = document.querySelector('header');
|
||||
const main = document.querySelector('main');
|
||||
|
||||
console.log('Header visible:', header.offsetHeight > 0);
|
||||
console.log('Main visible:', main.offsetHeight > 0);
|
||||
|
||||
// Add a timestamp to verify the page is current
|
||||
const debugInfo = document.querySelector('.debug-info');
|
||||
debugInfo.textContent += ' - ' + new Date().toLocaleTimeString();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
427
html/drone/pages/products.html
Normal file
@@ -0,0 +1,427 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Produkte - Luftglanz</title>
|
||||
<link rel="icon" href="../images/favicon_logo.png" type="image/png">
|
||||
<link rel="stylesheet" href="../css/normalize.css">
|
||||
<link rel="stylesheet" href="../css/main.css">
|
||||
<link rel="stylesheet" href="../css/components/header.css">
|
||||
<link rel="stylesheet" href="../css/components/footer.css">
|
||||
<link rel="stylesheet" href="../css/components/mobile-menu.css">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #2980b9;
|
||||
--accent-color: #00adb8;
|
||||
--secondary-color: #444444;
|
||||
--bg-light: #e8e9ea;
|
||||
--card-bg: #f5f5f5;
|
||||
--text-dark: #222222;
|
||||
--text-medium: #444444;
|
||||
--text-light: #606060;
|
||||
--gradient-primary: linear-gradient(90deg, #2980b9 0%, #00adb8 100%);
|
||||
--gradient-secondary: linear-gradient(90deg, #1f6797 0%, #00858e 100%);
|
||||
--shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
|
||||
--spacing-section: 5rem 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', 'Segoe UI', Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--text-medium);
|
||||
background-color: var(--bg-light);
|
||||
background-image:
|
||||
linear-gradient(120deg, rgba(0, 95, 168, 0.05) 0%, transparent 40%),
|
||||
linear-gradient(240deg, rgba(0, 140, 120, 0.05) 0%, transparent 40%);
|
||||
line-height: 1.6;
|
||||
position: relative;
|
||||
overflow-x: hidden; /* Prevent horizontal scrolling */
|
||||
font-size: 0.95rem; /* Base font size to match gallery */
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box; /* Ensure padding is included in width */
|
||||
}
|
||||
|
||||
/* Match main padding exactly to gallery page */
|
||||
main {
|
||||
padding-top: 5rem !important;
|
||||
}
|
||||
|
||||
/* Fix the product section positioning */
|
||||
.product-section {
|
||||
margin-top: 2rem !important; /* Reduced from 6rem to match gallery */
|
||||
padding: 2rem;
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Update to exactly match gallery styling */
|
||||
.main-nav a {
|
||||
color: var(--text-medium);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 0.5rem 0; /* Remove horizontal padding */
|
||||
position: relative;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav ul {
|
||||
gap: 1.5rem; /* Match gallery page spacing exactly */
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 1.4rem; /* Corrected: Changed from 1.7rem to match gallery page exactly */
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
background: var(--gradient-primary);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 40px; /* Explicitly set to match gallery page */
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
header {
|
||||
padding: 1.5rem 0;
|
||||
background: rgba(232, 233, 234, 0.95);
|
||||
backdrop-filter: blur(8px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.mobile-toggle {
|
||||
position: relative;
|
||||
right: 0;
|
||||
margin-left: auto;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap; /* Prevent wrapping that could cause overflow */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Product page specific styling improvements */
|
||||
.product-header h2 {
|
||||
display: block;
|
||||
font-size: 2.2rem;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.product-header p {
|
||||
color: var(--text-light);
|
||||
margin-bottom: 2rem;
|
||||
text-align: center;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.product-showcase {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.product-main {
|
||||
display: flex;
|
||||
gap: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
flex: 0 0 300px;
|
||||
}
|
||||
|
||||
.product-image img {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.product-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.product-title {
|
||||
font-size: 1.6rem; /* Reduced from 1.8rem */
|
||||
color: var(--text-dark);
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
.product-description {
|
||||
margin-bottom: 20px;
|
||||
color: var(--text-medium);
|
||||
}
|
||||
|
||||
.product-description p {
|
||||
font-size: 0.95rem; /* Explicitly match gallery text size */
|
||||
}
|
||||
|
||||
.product-features {
|
||||
margin-bottom: 25px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
.product-features li {
|
||||
margin-bottom: 8px;
|
||||
font-size: 0.95rem; /* Match gallery text size */
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
padding: 10px 22px; /* Slightly smaller button */
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem; /* Reduced button text size */
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--accent-color);
|
||||
}
|
||||
|
||||
/* Mobile styles */
|
||||
@media (max-width: 768px) {
|
||||
.product-main {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Mobile menu styles */
|
||||
#mainNav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mainNav.active {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--bg-light);
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#mainNav ul {
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
#mainNav li {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#mainNav a {
|
||||
display: block;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
#mobileToggle {
|
||||
display: block !important;
|
||||
font-size: 1.75rem;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--primary-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0 10px; /* Reduce padding on mobile */
|
||||
}
|
||||
|
||||
.logo {
|
||||
flex-shrink: 1; /* Allow logo to shrink if needed */
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 1.4rem; /* Slightly smaller on mobile */
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
#mobileToggle {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<div class="logo">
|
||||
<a href="../index.html" style="text-decoration: none; display: flex; align-items: center;">
|
||||
<img src="../images/favicon_logo.png" alt="Luftglanz Logo" class="logo-img">
|
||||
<h1 data-i18n="roof_drone">Luftglanz</h1>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<button class="mobile-toggle" id="mobileToggle" aria-label="Toggle navigation">
|
||||
☰
|
||||
</button>
|
||||
|
||||
<nav class="main-nav" id="mainNav">
|
||||
<ul>
|
||||
<li><a href="../index.html" data-i18n="nav_home">Startseite</a></li>
|
||||
<li><a href="../index.html#services" data-i18n="nav_services">Leistungen</a></li>
|
||||
<li><a href="../index.html#how-it-works" data-i18n="nav_how_it_works">Ablauf</a></li>
|
||||
<li><a href="../index.html#faq" data-i18n="nav_faq">FAQ</a></li>
|
||||
<li><a href="#" class="contact-link" data-i18n="nav_contact">Kontakt</a></li>
|
||||
<li><a href="products.html" class="active" data-i18n="nav_products">Produkte</a></li>
|
||||
<li><a href="gallery.html" data-i18n="nav_gallery">Galerie</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<section class="product-section">
|
||||
<div class="product-header">
|
||||
<h2>AGO Quart Grünbelagentferner</h2>
|
||||
<p>Hocheffektive Lösung gegen Grünbeläge, Algen, Moos und Flechten auf allen Oberflächen</p>
|
||||
</div>
|
||||
|
||||
<div class="product-showcase">
|
||||
<div class="product-main">
|
||||
<div class="product-image">
|
||||
<img src="../images/products/ago-quart-05l.jpg" alt="AGO Quart 100 0,5L Flasche">
|
||||
</div>
|
||||
|
||||
<div class="product-info">
|
||||
<ul class="product-features">
|
||||
<li>Hochkonzentrierte Wirkformel gegen Grünbeläge</li>
|
||||
<li>Selbsttätige Langzeitwirkung ohne Abwaschen</li>
|
||||
<li>Für Dächer, Fassaden, Terrassen, Wege, Zäune</li>
|
||||
<li>Vorbeugender Schutz über Monate</li>
|
||||
<li>Einfache Anwendung durch Aufsprühen</li>
|
||||
<li>Sichtbare Ergebnisse nach 2-3 Tagen</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Updated MELLERUD Solar Panel Cleaner Product Section -->
|
||||
<section class="product-section">
|
||||
<div class="product-header">
|
||||
<h2>MELLERUD Photovoltaik und Solaranlagen-Reiniger</h2>
|
||||
</div>
|
||||
|
||||
<div class="product-showcase">
|
||||
<div class="product-main">
|
||||
<div class="product-image">
|
||||
<img src="../images/solarreiniger.jpg" alt="MELLERUD Photovoltaik und Solaranlagen-Reiniger Konzentrat">
|
||||
</div>
|
||||
|
||||
<div class="product-info">
|
||||
<div class="product-description">
|
||||
<p>Speziell entwickelter Reiniger für die effektive und schonende Reinigung von Photovoltaik- und Solaranlagen. Entfernt zuverlässig Verschmutzungen wie Staub, Ruß, Öl, Fett, Vogelkot und Pollen.</p>
|
||||
</div>
|
||||
|
||||
<ul class="product-features">
|
||||
<li>Materialschonend und rückstandsfrei</li>
|
||||
<li>Verbessert die Leistung und Erträge der Anlagen</li>
|
||||
<li>Biologisch abbaubar und umweltfreundlich</li>
|
||||
<li>Für alle Solar- und Photovoltaikanlagen geeignet</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p data-i18n="footer_text">© 2025 Luftglanz. Alle Rechte vorbehalten.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="../js/translations.js"></script>
|
||||
<script src="../js/language-manager.js"></script>
|
||||
<script>
|
||||
// Direct mobile menu implementation
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const toggle = document.getElementById('mobileToggle');
|
||||
const nav = document.getElementById('mainNav');
|
||||
|
||||
if (toggle && nav) {
|
||||
toggle.addEventListener('click', function() {
|
||||
console.log('Toggle clicked');
|
||||
if (nav.classList.contains('active')) {
|
||||
nav.classList.remove('active');
|
||||
} else {
|
||||
nav.classList.add('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add contact link handler
|
||||
const contactLink = document.querySelector('.contact-link');
|
||||
if (contactLink) {
|
||||
contactLink.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.location.href = '../index.html#contact';
|
||||
|
||||
// Apply the same offset as the main page
|
||||
setTimeout(function() {
|
||||
if (window.location.hash === '#contact') {
|
||||
const contactSection = document.querySelector('#contact');
|
||||
if (contactSection) {
|
||||
window.scrollTo({
|
||||
top: contactSection.offsetTop - (-5), // Same -5px offset
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
425
html/drone/pages/services.html
Normal file
@@ -0,0 +1,425 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Leistungen - Luftglanz</title>
|
||||
<link rel="icon" href="../images/favicon_logo.png" type="image/png">
|
||||
<link rel="stylesheet" href="../css/normalize.css">
|
||||
<link rel="stylesheet" href="../css/main.css">
|
||||
<link rel="stylesheet" href="../css/components/header.css">
|
||||
<link rel="stylesheet" href="../css/components/footer.css">
|
||||
<link rel="stylesheet" href="../css/components/hero.css">
|
||||
<link rel="stylesheet" href="../css/components/forms.css">
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #3498db; /* Clean blue primary */
|
||||
--accent-color: #00c2cb; /* Teal accent */
|
||||
--secondary-color: #505050;
|
||||
--bg-light: #f8f9fa; /* Very light background */
|
||||
--card-bg: #ffffff; /* White card background */
|
||||
--text-dark: #333333;
|
||||
--text-medium: #505050;
|
||||
--text-light: #707070;
|
||||
--gradient-primary: linear-gradient(90deg, #3498db 0%, #00c2cb 100%);
|
||||
--gradient-secondary: linear-gradient(90deg, #2980b9 0%, #009ea6 100%);
|
||||
--shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
--spacing-section: 5rem 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Inter', 'Segoe UI', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: var(--text-medium);
|
||||
background-color: var(--bg-light);
|
||||
background-image:
|
||||
linear-gradient(120deg, rgba(0, 120, 212, 0.05) 0%, transparent 40%),
|
||||
linear-gradient(240deg, rgba(0, 178, 148, 0.05) 0%, transparent 40%);
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Header styling */
|
||||
header {
|
||||
padding: 1.5rem 0;
|
||||
background: rgba(232, 233, 234, 0.95); /* Changed to match --bg-light variable */
|
||||
backdrop-filter: blur(8px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
background: var(--gradient-primary);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* Navigation styling */
|
||||
.main-nav ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
color: var(--text-medium);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 0.5rem 0;
|
||||
position: relative;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover, .main-nav a.active {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.main-nav a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: var(--gradient-primary);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover::after, .main-nav a.active::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Section styling */
|
||||
.section-container {
|
||||
padding: 2.5rem;
|
||||
margin-bottom: 2rem;
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.section-container h2 {
|
||||
color: var(--text-dark);
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: 1rem;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.section-container h2::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
height: 3px;
|
||||
background: var(--gradient-primary);
|
||||
bottom: -0.75rem;
|
||||
left: 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.section-container h3 {
|
||||
color: var(--text-dark);
|
||||
font-size: 1.5rem;
|
||||
margin-top: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
position: relative;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.section-container h3::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0.35rem;
|
||||
height: 1rem;
|
||||
width: 3px;
|
||||
background: var(--gradient-primary);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.section-container p {
|
||||
color: var(--text-light);
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
/* Service cards */
|
||||
.service-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.service-card {
|
||||
background-color: var(--card-bg);
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border-radius: 10px;
|
||||
padding: 2rem;
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.service-card:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.service-card h3 {
|
||||
color: var(--text-dark);
|
||||
font-size: 1.4rem;
|
||||
margin-top: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.service-card h3::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.service-card p {
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
/* Language Switcher - Updated to match About Us page */
|
||||
.language-switcher {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.language-switcher button {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: var(--text-medium);
|
||||
padding: 0.4rem 0.75rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.language-switcher button.active,
|
||||
.language-switcher button:hover {
|
||||
background: var(--gradient-primary);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
/* Remove Stars Background */
|
||||
.stars {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Footer styling */
|
||||
footer {
|
||||
background-color: var(--text-dark);
|
||||
padding: 2rem 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
text-align: center;
|
||||
color: #aaaaaa;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
main {
|
||||
padding-top: 8rem;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Mobile styles */
|
||||
@media (max-width: 768px) {
|
||||
.main-nav {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
padding: 1rem 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.main-nav.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main-nav ul {
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.main-nav li {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 0.5rem 0;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.main-nav li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
display: block;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
.section-container {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<div class="logo">
|
||||
<img src="../images/favicon_logo.png" alt="Luftglanz Logo" class="logo-img">
|
||||
<h1 data-i18n="roof_drone">Luftglanz</h1>
|
||||
</div>
|
||||
|
||||
<nav class="main-nav" id="mainNav">
|
||||
<ul>
|
||||
<li><a href="../index.html" data-i18n="nav_home">Home</a></li>
|
||||
<li><a href="services.html" class="active" data-i18n="nav_services">Services</a></li>
|
||||
<li><a href="../index.html#how-it-works" data-i18n="nav_how_it_works">How It Works</a></li>
|
||||
<li><a href="../index.html#faq" data-i18n="nav_faq">FAQ</a></li>
|
||||
<li><a href="../index.html#contact" data-i18n="nav_contact">Contact</a></li>
|
||||
<li><a href="products.html" data-i18n="nav_products">Products</a></li>
|
||||
<li><a href="gallery.html" data-i18n="nav_gallery">Gallery</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<div class="hero-content">
|
||||
<h2 data-i18n="services_hero_title">Professional <span>Drone Roof Cleaning</span> Services</h2>
|
||||
<p data-i18n="services_hero_subtitle">Our specialized drones deliver thorough cleaning with advanced technology</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section-container">
|
||||
<h2 data-i18n="services_title">Our Services</h2>
|
||||
<p data-i18n="services_description">We offer professional roof cleaning and maintenance services using cutting-edge drone technology that delivers superior results with enhanced safety.</p>
|
||||
|
||||
<div class="service-grid">
|
||||
<div class="service-card" id="standard">
|
||||
<h3 data-i18n="service_drone_title">Drone Roof Cleaning</h3>
|
||||
<p data-i18n="service_drone_description">Unsere Drohnen sind mit speziellen Sprühsystemen ausgestattet, die effektiv Schmutz, Moos und Algen entfernen. Dieser kontaktlose Ansatz beseitigt das Risiko von Ziegelschäden und Arbeiterunfällen, die mit herkömmlichen Dachreinigungsmethoden verbunden sind.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-card" id="inspection">
|
||||
<h3 data-i18n="service_inspection_detailed_title">Inspection Services</h3>
|
||||
<p data-i18n="service_inspection_detailed_description">In addition to cleaning, our drones can perform detailed inspections of your roof, identifying potential issues before they become costly repairs. Our high-resolution cameras capture every detail, allowing us to spot missing shingles, damaged flashing, or other concerns that might be missed by the naked eye.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-card" id="maintenance">
|
||||
<h3 data-i18n="service_maintenance_title">Maintenance Packages</h3>
|
||||
<p data-i18n="service_maintenance_description">We offer various maintenance packages to keep your roof in top condition year-round, ensuring longevity and aesthetic appeal. Regular maintenance can extend your roof's lifespan by up to 25% while preventing costly repairs. Our packages can be customized to fit your specific roofing needs and budget.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 data-i18n="premium_services_title">Premium Add-On Services</h3>
|
||||
<p data-i18n="premium_services_description">Beyond our core services, we offer specialized treatments including waterproofing applications, UV-protective coatings, and thermal scanning to identify potential heat leaks. These additional services help maximize your roof's performance and energy efficiency while extending its overall lifespan.</p>
|
||||
|
||||
<h3 data-i18n="environmental_approach_title">Unser Effizienzkonzept</h3>
|
||||
<p data-i18n="environmental_approach_description">Unsere präzise Drohnenanwendungsmethode reduziert den Wasserverbrauch im Vergleich zu herkömmlichen Hochdruckreinigungstechniken um bis zu 60%. Dies bedeutet eine schnellere, sauberere Reinigung in weniger Zeit.</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p data-i18n="footer_text">© 2023 Luftglanz. Alle Rechte vorbehalten.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="../js/translations.js"></script>
|
||||
<script src="../js/language-manager.js"></script>
|
||||
<script src="../js/drone-image-animation.js"></script>
|
||||
<script>
|
||||
// Smooth scrolling
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const navLinks = document.querySelectorAll('a[href^="#"]');
|
||||
|
||||
navLinks.forEach(link => {
|
||||
link.addEventListener('click', function(e) {
|
||||
if(this.getAttribute('href') !== '#') {
|
||||
e.preventDefault();
|
||||
|
||||
const targetId = this.getAttribute('href');
|
||||
const targetElement = document.querySelector(targetId);
|
||||
|
||||
if (targetElement) {
|
||||
window.scrollTo({
|
||||
top: targetElement.offsetTop - 100,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
|
||||
history.pushState(null, null, targetId);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
24
html/drone/partials/nav.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
<div class="logo">
|
||||
<a href="../index.html" style="text-decoration: none; display: flex; align-items: center;">
|
||||
<img src="../images/favicon_logo.png" alt="Luftglanz Logo" class="logo-img">
|
||||
<h1 data-i18n="roof_drone">Luftglanz</h1>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<nav class="main-nav" id="mainNav">
|
||||
<ul>
|
||||
<li><a href="../index.html" data-i18n="nav_home">Home</a></li>
|
||||
<li><a href="../index.html#services" data-i18n="nav_services">Services</a></li>
|
||||
<li><a href="../index.html#how-it-works" data-i18n="nav_how_it_works">How It Works</a></li>
|
||||
<li><a href="../index.html#faq" data-i18n="nav_faq">FAQ</a></li>
|
||||
<li><a href="../index.html#contact" data-i18n="nav_contact">Contact</a></li>
|
||||
<li><a href="products.html" data-i18n="nav_products">Products</a></li>
|
||||
<li><a href="gallery.html" data-i18n="nav_gallery">Gallery</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
12
html/drone/phptest.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
header('Content-Type: text/html');
|
||||
echo "<html><body>";
|
||||
echo "<h1>PHP Test</h1>";
|
||||
echo "<p>PHP is " . (function_exists('mail') ? 'working' : 'not working') . "!</p>";
|
||||
echo "<p>PHP Version: " . phpversion() . "</p>";
|
||||
echo "<p>Server Software: " . $_SERVER['SERVER_SOFTWARE'] . "</p>";
|
||||
echo "<pre>PHP Info:\n\n";
|
||||
phpinfo();
|
||||
echo "</pre>";
|
||||
echo "</body></html>";
|
||||
?>
|
||||
200
html/drone/process-form.php
Normal file
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
// Maximum error reporting and debugging
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
// Store logs in a variable to display on the page
|
||||
$debug_logs = [];
|
||||
function debug_log($message) {
|
||||
global $debug_logs;
|
||||
$debug_logs[] = $message;
|
||||
error_log($message);
|
||||
}
|
||||
|
||||
// Enhanced error logging settings
|
||||
ini_set('log_errors', 1);
|
||||
ini_set('error_log', 'form_errors.log');
|
||||
debug_log("Log file location: " . ini_get('error_log'));
|
||||
debug_log("======= New Form Submission Attempt: " . date('Y-m-d H:i:s') . " =======");
|
||||
debug_log("Request Method: " . $_SERVER['REQUEST_METHOD']);
|
||||
debug_log("Server Software: " . $_SERVER['SERVER_SOFTWARE']);
|
||||
debug_log("HTTP_ACCEPT: " . $_SERVER['HTTP_ACCEPT']);
|
||||
|
||||
// Debug all inputs received
|
||||
foreach ($_REQUEST as $key => $value) {
|
||||
debug_log("Request parameter: $key = $value");
|
||||
}
|
||||
|
||||
// If direct access without POST, offer a helpful message
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
echo "<html><head><title>Form Processing Error</title>";
|
||||
echo "<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
h1 { color: #d33; }
|
||||
.message { background: #f8f8f8; border: 1px solid #ddd; padding: 15px; margin: 20px 0; }
|
||||
.button { display: inline-block; padding: 10px 15px; background: #4CAF50; color: white; text-decoration: none; border-radius: 4px; }
|
||||
</style></head><body>";
|
||||
echo "<h1>Form Submission Error</h1>";
|
||||
echo "<div class='message'><p>This page is meant to be accessed via a form submission.</p>";
|
||||
echo "<p>It appears you're trying to access it directly. Please submit the form instead.</p>";
|
||||
echo "<p>Current request method: " . $_SERVER['REQUEST_METHOD'] . " (should be POST)</p></div>";
|
||||
echo "<a href='index.html#contact' class='button'>Go to Contact Form</a>";
|
||||
echo "<a href='form-test.html' class='button' style='margin-left: 10px;'>Try Test Form</a>";
|
||||
echo "</body></html>";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Contact form processing script
|
||||
$success = false;
|
||||
$error_message = '';
|
||||
|
||||
// Capture PHP warnings
|
||||
function captureWarning($errno, $errstr, $errfile, $errline) {
|
||||
debug_log("WARNING [$errno]: $errstr in $errfile:$errline");
|
||||
return true;
|
||||
}
|
||||
set_error_handler("captureWarning", E_WARNING);
|
||||
|
||||
// Check if the form was submitted
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
// Log all received POST data
|
||||
debug_log("Form submission received - POST data: " . print_r($_POST, true));
|
||||
|
||||
// Get form data and sanitize inputs
|
||||
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
|
||||
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
|
||||
$phone = filter_input(INPUT_POST, 'phone', FILTER_SANITIZE_STRING);
|
||||
$message = filter_input(INPUT_POST, 'message', FILTER_SANITIZE_STRING);
|
||||
$subjectField = filter_input(INPUT_POST, 'subject', FILTER_SANITIZE_STRING);
|
||||
|
||||
// Log sanitized inputs
|
||||
debug_log("Sanitized form data: Name: $name, Email: $email, Phone: $phone, Message length: " . strlen($message));
|
||||
|
||||
// Basic validation
|
||||
if (empty($name) || empty($email) || empty($message) || empty($subjectField)) {
|
||||
$error_message = 'Bitte füllen Sie alle Pflichtfelder aus.';
|
||||
debug_log("Validation error: $error_message");
|
||||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$error_message = 'Bitte geben Sie eine gültige E-Mail-Adresse ein.';
|
||||
debug_log("Validation error: $error_message");
|
||||
} else {
|
||||
// Prepare email content
|
||||
$to = "monitor@egonetix.de"; // Recipient email address
|
||||
$subject = $subjectField ?: "Neue Kontaktanfrage von luftglanz.de";
|
||||
|
||||
// Only use the message as the email body, but add phone if present
|
||||
$email_body = $message;
|
||||
if (!empty($phone)) {
|
||||
$email_body .= "\n\nTelefonnummer: $phone";
|
||||
}
|
||||
|
||||
// Additional headers
|
||||
$headers = "From: $name <luftglanz@egonetix.de>\r\n" .
|
||||
"Reply-To: $email\r\n" .
|
||||
"X-Mailer: PHP/" . phpversion();
|
||||
|
||||
debug_log("Email headers: " . $headers);
|
||||
debug_log("Preparing to send email to: $to");
|
||||
debug_log("Email subject: $subject");
|
||||
debug_log("Email body: $email_body");
|
||||
|
||||
try {
|
||||
// SMTP settings
|
||||
debug_log("Setting SMTP server to: srvdc01");
|
||||
ini_set("SMTP", "srvdc01");
|
||||
debug_log("SMTP after setting: " . ini_get("SMTP"));
|
||||
|
||||
debug_log("Setting smtp_port to: 25");
|
||||
ini_set("smtp_port", "25");
|
||||
debug_log("smtp_port after setting: " . ini_get("smtp_port"));
|
||||
|
||||
debug_log("Setting sendmail_from to: luftglanz@egonetix.de");
|
||||
ini_set("sendmail_from", "luftglanz@egonetix.de");
|
||||
debug_log("sendmail_from after setting: " . ini_get("sendmail_from"));
|
||||
|
||||
// Set authentication for sending the email
|
||||
$auth = base64_encode("luftglanz:dDmws12*");
|
||||
debug_log("Setting SMTP authentication");
|
||||
ini_set("smtp_auth", $auth);
|
||||
|
||||
debug_log("About to call mail() function");
|
||||
|
||||
// Try to send the email with debugging
|
||||
ob_start(); // Start output buffering to capture any output or warnings
|
||||
$mail_result = mail($to, $subject, $email_body, $headers);
|
||||
$output = ob_get_clean(); // Get the buffered output
|
||||
|
||||
debug_log("mail() function output: " . $output);
|
||||
debug_log("mail() function result: " . ($mail_result ? "TRUE" : "FALSE"));
|
||||
|
||||
if ($mail_result) {
|
||||
$success = true;
|
||||
debug_log("Email appears to have been sent successfully");
|
||||
} else {
|
||||
$error = error_get_last();
|
||||
$error_message = 'Es gab ein Problem beim Senden Ihrer Nachricht. Bitte versuchen Sie es später erneut.';
|
||||
debug_log("Mail function failed. PHP Error: " . ($error ? print_r($error, true) : 'Unknown error'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error_message = 'Ein Fehler ist aufgetreten: ' . $e->getMessage();
|
||||
debug_log("Exception caught: " . $e->getMessage());
|
||||
debug_log("Exception trace: " . $e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If not successful, display debugging information
|
||||
if (!$success) {
|
||||
// Return error with debugging logs for AJAX requests
|
||||
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') {
|
||||
debug_log("Returning JSON response with debug info");
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => $error_message,
|
||||
'debug_logs' => $debug_logs
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Display debug information directly on the page
|
||||
echo "<html><head><title>Form Submission Debug</title>";
|
||||
echo "<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
h1 { color: #d33; }
|
||||
.debug-container { background: #f8f8f8; border: 1px solid #ddd; padding: 15px; margin: 20px 0; }
|
||||
.debug-log { font-family: monospace; white-space: pre-wrap; background: #333; color: #fff; padding: 10px; max-height: 400px; overflow: auto; }
|
||||
.error-message { color: #d33; font-weight: bold; margin: 20px 0; }
|
||||
.button { display: inline-block; padding: 10px 15px; background: #4CAF50; color: white; text-decoration: none; border-radius: 4px; }
|
||||
</style></head><body>";
|
||||
echo "<h1>Form Submission Debugging Output</h1>";
|
||||
echo "<div class='error-message'>Error: $error_message</div>";
|
||||
|
||||
echo "<div class='debug-container'>";
|
||||
echo "<h2>Debug Logs:</h2>";
|
||||
echo "<div class='debug-log'>";
|
||||
foreach ($debug_logs as $log) {
|
||||
echo htmlspecialchars($log) . "\n";
|
||||
}
|
||||
echo "</div></div>";
|
||||
|
||||
echo "<a href='index.html#contact' class='button'>Back to Contact Form</a>";
|
||||
echo "</body></html>";
|
||||
exit;
|
||||
}
|
||||
|
||||
// For successful AJAX requests
|
||||
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') {
|
||||
debug_log("Returning successful JSON response");
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => true, 'message' => '']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// For successful non-AJAX requests, redirect back to the form
|
||||
debug_log("Redirecting to form with success message");
|
||||
header('Location: index.html?form_success=1#contact');
|
||||
debug_log("======= End of Form Submission Processing =======\n");
|
||||
exit;
|
||||
?>
|
||||
60
html/drone/send-email.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
// Simple and reliable email handler based on the successful test
|
||||
$success = false;
|
||||
$errorMessage = '';
|
||||
|
||||
// Log all incoming requests
|
||||
error_log("Email form submission received at " . date('Y-m-d H:i:s'));
|
||||
error_log("REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD']);
|
||||
|
||||
// Process form data from either GET or POST
|
||||
$data = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET;
|
||||
|
||||
// Sanitize and validate inputs
|
||||
$name = isset($data['name']) ? htmlspecialchars($data['name']) : '';
|
||||
$email = isset($data['email']) ? filter_var($data['email'], FILTER_SANITIZE_EMAIL) : '';
|
||||
$phone = isset($data['phone']) ? htmlspecialchars($data['phone']) : '';
|
||||
$message = isset($data['message']) ? htmlspecialchars($data['message']) : '';
|
||||
$subjectField = isset($data['subject']) ? htmlspecialchars($data['subject']) : '';
|
||||
|
||||
// Log the received data
|
||||
error_log("Form data received - Name: $name, Email: $email, Phone: $phone");
|
||||
|
||||
// Basic validation
|
||||
if (empty($name) || empty($email) || empty($message) || empty($subjectField)) {
|
||||
$errorMessage = 'Bitte füllen Sie alle Pflichtfelder aus.';
|
||||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errorMessage = 'Bitte geben Sie eine gültige E-Mail-Adresse ein.';
|
||||
} else {
|
||||
// Format the email body
|
||||
$emailBody = $message;
|
||||
if (!empty($phone)) {
|
||||
$emailBody .= "\n\nTelefonnummer: $phone";
|
||||
}
|
||||
|
||||
// Email details
|
||||
$to = "kontakt@luftglanz.de";
|
||||
$subject = $subjectField ?: "Neue Kontaktanfrage von $name";
|
||||
$headers = "From: $name <luftglanz@egonetix.de>\r\n";
|
||||
$headers .= "Reply-To: $name <$email>\r\n";
|
||||
$headers .= "X-Mailer: PHP/" . phpversion();
|
||||
|
||||
// Send the email using the mail() function that we confirmed works
|
||||
$success = mail($to, $subject, $emailBody, $headers);
|
||||
|
||||
if (!$success) {
|
||||
$errorMessage = 'Es gab ein Problem beim Senden Ihrer Nachricht. Bitte versuchen Sie es später erneut.';
|
||||
error_log("Mail sending failed for $email");
|
||||
} else {
|
||||
error_log("Email sent successfully to $to from $email");
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect back to the form with status
|
||||
if ($success) {
|
||||
header('Location: index.html?form_success=1#contact');
|
||||
} else {
|
||||
header('Location: index.html?form_error=' . urlencode($errorMessage) . '#contact');
|
||||
}
|
||||
exit;
|
||||
?>
|
||||
50
html/drone/simple-handler.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
// Simple form handler with minimal dependencies
|
||||
$success = false;
|
||||
$error = '';
|
||||
|
||||
// Log information regardless of method
|
||||
error_log("Request received at " . date('Y-m-d H:i:s'));
|
||||
error_log("REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD']);
|
||||
|
||||
// Handle either GET or POST
|
||||
$data = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET;
|
||||
|
||||
// Check if we have data
|
||||
if (!empty($data)) {
|
||||
error_log("Form data received: " . print_r($data, true));
|
||||
|
||||
// Get the name from form data
|
||||
$name = isset($data['name']) ? $data['name'] : 'Unbekannt';
|
||||
|
||||
// Prepare message
|
||||
$message = isset($data['message']) ? $data['message'] : '';
|
||||
|
||||
if (!empty($data['phone'])) {
|
||||
$message .= "\n\nTelefonnummer: " . $data['phone'];
|
||||
}
|
||||
|
||||
// Get the subject from form data
|
||||
$subjectField = isset($data['subject']) ? $data['subject'] : '';
|
||||
|
||||
// Use basic PHP mail() function with correct sender address
|
||||
$to = "kontakt@luftglanz.de";
|
||||
$subject = $subjectField ?: "Neue Kontaktanfrage von $name";
|
||||
$headers = "From: $name <luftglanz@egonetix.de>\r\n" .
|
||||
"Reply-To: " . ($data['email'] ?? 'luftglanz@egonetix.de') . "\r\n" .
|
||||
"X-Mailer: PHP/" . phpversion();
|
||||
|
||||
try {
|
||||
$success = mail($to, $subject, $message, $headers);
|
||||
error_log("Mail sent: " . ($success ? "Success" : "Failed"));
|
||||
} catch (Exception $e) {
|
||||
error_log("Mail exception: " . $e->getMessage());
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect back to index.html instead of showing debug page
|
||||
header('Location: index.html?form_status=' . ($success ? 'success' : 'error') .
|
||||
($error ? '&error_message=' . urlencode($error) : ''));
|
||||
exit;
|
||||
?>
|
||||
4
html/drone/test.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
// Simplest possible PHP test file
|
||||
echo "PHP is working! Current time: " . date('Y-m-d H:i:s');
|
||||
?>
|
||||
1
html/drone_bup/assets/fonts
Normal file
@@ -0,0 +1 @@
|
||||
<!-- This file is intentionally left blank. -->
|
||||
1
html/drone_bup/assets/videos
Normal file
@@ -0,0 +1 @@
|
||||
<!-- This file is intentionally left blank. -->
|
||||
23
html/drone_bup/css/components/footer.css
Normal file
@@ -0,0 +1,23 @@
|
||||
.footer {
|
||||
background-color: #2c3e50;
|
||||
color: #ecf0f1;
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #ecf0f1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
45
html/drone_bup/css/components/forms.css
Normal file
@@ -0,0 +1,45 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="email"],
|
||||
textarea {
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
98
html/drone_bup/css/components/header.css
Normal file
@@ -0,0 +1,98 @@
|
||||
/* Header Component Styles - Updated to match Gallery page */
|
||||
header {
|
||||
padding: 1.5rem 0;
|
||||
background: rgba(232, 233, 234, 0.95); /* Match gallery page background */
|
||||
backdrop-filter: blur(8px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
background: var(--gradient-primary);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
.main-nav ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
color: var(--text-dark);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 0.5rem 0.8rem;
|
||||
position: relative;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover, .main-nav a.active {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.main-nav a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: var(--gradient-primary);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.main-nav a:hover::after, .main-nav a.active::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Mobile responsiveness */
|
||||
@media (max-width: 768px) {
|
||||
.main-nav {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 76px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: calc(100vh - 76px);
|
||||
overflow-y: auto;
|
||||
background: rgba(232, 233, 234, 0.95); /* Changed to match the header background */
|
||||
padding: 1rem 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
38
html/drone_bup/css/components/hero.css
Normal file
@@ -0,0 +1,38 @@
|
||||
.hero {
|
||||
background-image: url('../assets/images/hero-background.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.5rem;
|
||||
margin: 10px 0 20px;
|
||||
}
|
||||
|
||||
.hero .cta-button {
|
||||
background-color: #ffcc00;
|
||||
color: #333;
|
||||
padding: 15px 30px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.hero .cta-button:hover {
|
||||
background-color: #e6b800;
|
||||
}
|
||||
70
html/drone_bup/css/components/mobile-menu.css
Normal file
@@ -0,0 +1,70 @@
|
||||
/* Mobile navigation styles */
|
||||
|
||||
/* Mobile toggle button */
|
||||
.mobile-toggle {
|
||||
display: none;
|
||||
font-size: 1.75rem;
|
||||
color: var(--primary-color);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* Mobile responsiveness */
|
||||
@media (max-width: 768px) {
|
||||
.mobile-toggle {
|
||||
display: block; /* Show on mobile */
|
||||
}
|
||||
|
||||
.main-nav {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: var(--bg-light);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
|
||||
z-index: 999;
|
||||
border-radius: 0 0 10px 10px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.main-nav.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main-nav ul {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 1rem 0;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.main-nav li {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-nav a {
|
||||
display: block;
|
||||
padding: 0.75rem;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main-nav a:hover::after,
|
||||
.main-nav a.active::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Ensure footer copyright is visible and properly formatted on mobile */
|
||||
footer .container p {
|
||||
text-align: center;
|
||||
font-size: 0.9rem;
|
||||
margin: 0;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
}
|
||||
99
html/drone_bup/css/main.css
Normal file
@@ -0,0 +1,99 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Arial', sans-serif;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
header {
|
||||
background: #4CAF50;
|
||||
color: #fff;
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 20px;
|
||||
padding-top: 90px; /* This value should match your header height plus any desired spacing */
|
||||
}
|
||||
|
||||
footer {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4CAF50;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: url('../assets/images/hero-bg.jpg') no-repeat center center/cover;
|
||||
height: 400px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
text-align: center;
|
||||
margin-top: -30px; /* Adjust to reduce some of the padding for hero sections */
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="email"],
|
||||
textarea {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #45a049;
|
||||
}
|
||||
46
html/drone_bup/css/normalize.css
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed, footer,
|
||||
header, hgroup, main, menu, nav, output, ruby,
|
||||
section, summary, time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, main, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
40
html/drone_bup/email-test.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// Simple email test script
|
||||
echo "<h1>Email Test</h1>";
|
||||
|
||||
// Check if mail function exists
|
||||
if (!function_exists('mail')) {
|
||||
echo "<p style='color:red'>Error: mail() function is not available!</p>";
|
||||
echo "<p>Make sure PHP is configured with mail support.</p>";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Try to send a test email
|
||||
$to = "monitor@egonetix.de";
|
||||
$subject = "Test Email from Luftglanz";
|
||||
$message = "This is a test email sent from " . $_SERVER['SERVER_NAME'] . " at " . date('Y-m-d H:i:s');
|
||||
$headers = "From: test@" . $_SERVER['SERVER_NAME'] . "\r\n" .
|
||||
"Reply-To: test@" . $_SERVER['SERVER_NAME'] . "\r\n" .
|
||||
"X-Mailer: PHP/" . phpversion();
|
||||
|
||||
$success = mail($to, $subject, $message, $headers);
|
||||
|
||||
if ($success) {
|
||||
echo "<p style='color:green'>Success! Test email was sent to $to</p>";
|
||||
} else {
|
||||
echo "<p style='color:red'>Failed to send email. Check server mail configuration.</p>";
|
||||
|
||||
// Check mail configuration
|
||||
echo "<h2>Mail Configuration:</h2>";
|
||||
echo "<pre>";
|
||||
echo "sendmail_path: " . ini_get('sendmail_path') . "\n";
|
||||
echo "SMTP: " . ini_get('SMTP') . "\n";
|
||||
echo "smtp_port: " . ini_get('smtp_port') . "\n";
|
||||
echo "</pre>";
|
||||
}
|
||||
|
||||
// Display PHP info for debugging
|
||||
echo "<h2>PHP Information:</h2>";
|
||||
echo "<p>PHP Version: " . phpversion() . "</p>";
|
||||
echo "<p>Server Software: " . $_SERVER['SERVER_SOFTWARE'] . "</p>";
|
||||
?>
|
||||
72
html/drone_bup/form-get-handler.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
// Alternative form handler using GET method
|
||||
// This file works around servers that block POST to PHP files
|
||||
|
||||
// Enable error reporting for debugging
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
// Log to help with debugging
|
||||
error_log("Form-GET-Handler received request: " . date('Y-m-d H:i:s'));
|
||||
error_log("REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD']);
|
||||
|
||||
// Process form data from either GET or POST
|
||||
$formData = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET;
|
||||
|
||||
// Sanitize inputs
|
||||
$name = isset($formData['name']) ? htmlspecialchars($formData['name']) : '';
|
||||
$email = isset($formData['email']) ? filter_var($formData['email'], FILTER_SANITIZE_EMAIL) : '';
|
||||
$phone = isset($formData['phone']) ? htmlspecialchars($formData['phone']) : '';
|
||||
$message = isset($formData['message']) ? htmlspecialchars($formData['message']) : '';
|
||||
|
||||
// Log the received data
|
||||
error_log("Received data - Name: $name, Email: $email, Phone: $phone");
|
||||
|
||||
// Simple validation
|
||||
$success = false;
|
||||
$errorMessage = '';
|
||||
|
||||
if (empty($name) || empty($email) || empty($message)) {
|
||||
$errorMessage = 'Bitte füllen Sie alle Pflichtfelder aus.';
|
||||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errorMessage = 'Bitte geben Sie eine gültige E-Mail-Adresse ein.';
|
||||
} else {
|
||||
// Construct message for the email
|
||||
$emailBody = $message;
|
||||
|
||||
// Email details
|
||||
$to = "kontakt@luftglanz.de";
|
||||
$subject = "Neue Kontaktanfrage von $name";
|
||||
|
||||
// Attempt to send email via internal mail function
|
||||
$mailSent = mail($to, $subject, $emailBody,
|
||||
"From: $name <luftglanz@egonetix.de>\r\n" .
|
||||
"Reply-To: $email\r\n" .
|
||||
"X-Mailer: PHP/" . phpversion()
|
||||
);
|
||||
|
||||
if ($mailSent) {
|
||||
$success = true;
|
||||
} else {
|
||||
$errorMessage = 'Es gab ein Problem beim Senden Ihrer Nachricht. Bitte versuchen Sie es später erneut.';
|
||||
error_log("Mail sending failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the response
|
||||
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
|
||||
// Ajax request - return JSON
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'success' => $success,
|
||||
'message' => $errorMessage
|
||||
]);
|
||||
} else {
|
||||
// Regular form submission - redirect with status
|
||||
if ($success) {
|
||||
header('Location: index.html?form_success=1#contact');
|
||||
} else {
|
||||
header('Location: index.html?form_error=' . urlencode($errorMessage) . '#contact');
|
||||
}
|
||||
}
|
||||
?>
|
||||
63
html/drone_bup/form-test.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Form Test</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
|
||||
form { background: #f8f8f8; padding: 20px; border-radius: 8px; margin-bottom: 30px; }
|
||||
.form-group { margin-bottom: 15px; }
|
||||
label { display: block; margin-bottom: 5px; }
|
||||
input, textarea { width: 100%; padding: 8px; box-sizing: border-box; }
|
||||
button { background: #4CAF50; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; }
|
||||
h2 { margin-top: 30px; color: #333; border-bottom: 1px solid #ddd; padding-bottom: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Form Test - Find a Working Method</h1>
|
||||
<p>This page tests different form submission methods to find one that works on this server.</p>
|
||||
|
||||
<h2>Method 1: Standard POST Form (Original)</h2>
|
||||
<p>This method often gets blocked with a 405 error on some servers.</p>
|
||||
<form action="process-form.php" method="POST">
|
||||
<div class="form-group">
|
||||
<label for="name1">Name:</label>
|
||||
<input type="text" id="name1" name="name" value="Test User" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email1">Email:</label>
|
||||
<input type="email" id="email1" name="email" value="test@example.com" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message1">Message:</label>
|
||||
<textarea id="message1" name="message" rows="4" required>This is a test message using POST method.</textarea>
|
||||
</div>
|
||||
<button type="submit">Submit with POST</button>
|
||||
</form>
|
||||
|
||||
<h2>Method 2: GET Method Form</h2>
|
||||
<p>This method uses GET which may bypass the 405 error.</p>
|
||||
<form action="form-get-handler.php" method="GET">
|
||||
<div class="form-group">
|
||||
<label for="name2">Name:</label>
|
||||
<input type="text" id="name2" name="name" value="Test User" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email2">Email:</label>
|
||||
<input type="email" id="email2" name="email" value="test@example.com" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="phone2">Phone:</label>
|
||||
<input type="tel" id="phone2" name="phone" value="123-456-7890">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message2">Message:</label>
|
||||
<textarea id="message2" name="message" rows="4" required>This is a test message using GET method.</textarea>
|
||||
</div>
|
||||
<button type="submit">Submit with GET</button>
|
||||
</form>
|
||||
|
||||
<p><a href="index.html">Back to Main Page</a></p>
|
||||
</body>
|
||||
</html>
|
||||
BIN
html/drone_bup/images/animation_background.png
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
html/drone_bup/images/animation_background1.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
html/drone_bup/images/drone_from_above.jpg
Normal file
|
After Width: | Height: | Size: 297 KiB |
BIN
html/drone_bup/images/drone_in_action1.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
html/drone_bup/images/drone_in_action2.jpg
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
html/drone_bup/images/drone_in_action_solar1.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |