22 Commits
Author SHA1 Message Date
chriz 1448f058d8 Link footer adresses.
Build and Push Container Image / Build & Push to Gitea Package Registry (push) Canceled after 0s
2026-10-26 21:52:53 +01:00
chriz 2ba30e2d46 fix build
Build and Push Container Image / Build & Push to Gitea Package Registry (push) Canceled after 0s
2026-10-26 21:14:20 +01:00
chriz ab589c23fd Fix build
Build and Push Container Image / Build & Push to Gitea Package Registry (push) Canceled after 0s
2026-10-26 21:09:41 +01:00
chriz 965cde3c41 .gitea/workflows/docker-publish.yml aktualisiert
Build and Push Container Image / Build & Push to Gitea Package Registry (push) Canceled after 0s
2026-10-26 20:02:29 +00:00
chriz af5177e8b1 design optimizations.
Build and Push Container Image / Build & Push to Gitea Package Registry (push) Canceled after 0s
2026-10-26 20:55:59 +01:00
chriz 1e33c525f1 Add multilingual support (DE default, EN under /en/) 2026-10-23 13:06:56 +02:00
chriz 01ea3bd07a First appointment fixes. 2026-10-21 08:31:00 +02:00
chriz eef49d7bb3 Erstkontakt. 2026-10-20 18:19:06 +02:00
chriz 93d4d3bba3 Ansprechpartner Medizintechnik: 2026-10-20 17:50:04 +02:00
chriz bc1c5a62fb Flyer Optimierungen. 2026-10-20 12:42:38 +02:00
chriz ac8468ca76 Enable HTTP/2 & HTTP/3 2026-10-20 12:02:30 +02:00
chriz 014422e0b6 Accessibility fixes. 2026-10-20 11:11:04 +02:00
chriz 02c92db1e5 add email sat 2026-10-20 10:48:59 +02:00
chriz 92f2703788 Copy Text Optimierung. 2026-10-20 10:28:25 +02:00
chriz 6648523b04 Fix Haemo Master and cleanup files. 2026-10-20 09:26:35 +02:00
chriz de178b0ceb Container fixup. 2026-10-19 22:10:32 +02:00
chriz 086db21318 Legal and content review. 2026-10-19 20:49:57 +02:00
chriz 167dc1dfb1 QM run. 2026-10-19 20:04:00 +02:00
chriz ab516628af Alphe version. 2026-10-19 19:20:55 +02:00
chriz 33dd2fb757 Alpha Version. 2026-10-19 19:05:51 +02:00
chriz 8660ea6173 Rework using Gemini 2026-10-19 18:43:01 +02:00
chriz 911b8864ca Website Update Gemini - 1st run. 2026-10-19 15:54:08 +02:00
213 changed files with 5497 additions and 40959 deletions

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
.git
.gitea
.gitignore
.dockerignore
Dockerfile
files/flyer_template.html
files/flyer_map.png
-61
View File
@@ -1,61 +0,0 @@
name: Build and Push PHP Container Image
on:
push:
branches: [main] # or master / your default branch
# Optional: also on tags
# tags: ['v*']
jobs:
build-and-push:
runs-on: ubuntu-latest
# Recommended for Docker build tools on many self-hosted runners
container:
image: catthehacker/ubuntu:act-latest
env:
REGISTRY: gitea.example.com # ← your Gitea hostname (no https://)
IMAGE_NAME: ${{ gitea.repository }} # owner/repo style, or hard-code owner/image
# Or: IMAGE_NAME: myuser/php-website
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU (for multi-arch, optional)
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Only needed if your Gitea registry is HTTP / self-signed:
# with:
# config-inline: |
# [registry."gitea.example.com"]
# http = true
# insecure = true
- name: Login to Gitea Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Extract metadata / tags
id: meta
run: |
echo "VERSION=$(git describe --tags --always 2>/dev/null || echo ${{ gitea.sha }})" >> $GITHUB_OUTPUT
# or simply use latest + sha
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ gitea.sha }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.VERSION }}
# platforms: linux/amd64,linux/arm64 # uncomment for multi-arch
# cache-from: type=registry,ref=...
# cache-to: type=registry,ref=...,mode=max
+112
View File
@@ -0,0 +1,112 @@
name: Build and Push Container Image
on:
push:
branches:
- main
- multilingual
- redesign
tags:
- 'v*'
workflow_dispatch:
jobs:
build-and-push:
name: Build & Push to Gitea Package Registry
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Ensure Container Build Tools (Docker CLI / Buildah)
run: |
if ! command -v docker >/dev/null 2>&1; then
echo "Docker CLI not found in runner image; installing static Docker CLI..."
curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz | tar xz -C /tmp
mv /tmp/docker/docker /usr/local/bin/docker
chmod +x /usr/local/bin/docker
rm -rf /tmp/docker
fi
docker --version
- name: Build, Validate, and Push Image to Gitea Package Registry
env:
REGISTRY_USER: ${{ gitea.actor }}
REGISTRY_TOKEN: ${{ secrets.GITEATOKEN }}
SERVER_URL: ${{ gitea.server_url }}
REPO_NAME: ${{ gitea.repository }}
REF_NAME: ${{ gitea.ref_name }}
SHA: ${{ gitea.sha }}
run: |
REGISTRY_HOST=$(echo "${SERVER_URL}" | sed -E 's#^https?://##; s#/$##')
IS_HTTP=false
if echo "${SERVER_URL}" | grep -qE '^http://'; then
IS_HTTP=true
fi
IMAGE_PATH=$(echo "${REPO_NAME}" | tr '[:upper:]' '[:lower:]')
FULL_IMAGE="${REGISTRY_HOST}/${IMAGE_PATH}"
SHORT_SHA=$(echo "${SHA}" | cut -c1-7)
SAFE_REF=$(echo "${REF_NAME}" | sed -E 's#[^a-zA-Z0-9_.-]#-#g')
if docker info >/dev/null 2>&1; then
echo "Using Docker daemon via mounted socket..."
docker build --pull \
-t "${FULL_IMAGE}:${SAFE_REF}" \
-t "${FULL_IMAGE}:${SHORT_SHA}" \
-t "${FULL_IMAGE}:latest" \
.
echo "Validating PHP syntax inside built container..."
docker run --rm "${FULL_IMAGE}:${SHORT_SHA}" sh -c 'find /var/www/html -name "*.php" -exec php -l {} +'
echo "Attempting Docker login to ${REGISTRY_HOST}..."
if echo "${REGISTRY_TOKEN}" | docker login "${SERVER_URL}" -u "${REGISTRY_USER}" --password-stdin 2>/dev/null \
|| echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY_HOST}" -u "${REGISTRY_USER}" --password-stdin 2>/dev/null; then
echo "Pushing tags via Docker CLI..."
docker push "${FULL_IMAGE}:${SAFE_REF}"
docker push "${FULL_IMAGE}:${SHORT_SHA}"
docker push "${FULL_IMAGE}:latest"
else
echo "Docker daemon rejected login (plain HTTP registry ${SERVER_URL} not in host insecure-registries)."
echo "Exporting built image with Docker CLI and pushing via skopeo..."
if ! command -v skopeo >/dev/null 2>&1; then
apt-get update && apt-get install -y skopeo
fi
TLS_FLAG="--dest-tls-verify=true"
if [ "${IS_HTTP}" = "true" ]; then
TLS_FLAG="--dest-tls-verify=false"
fi
docker save "${FULL_IMAGE}:${SHORT_SHA}" -o /tmp/image.tar
for TAG in "${SAFE_REF}" "${SHORT_SHA}" "latest"; do
echo "Pushing ${FULL_IMAGE}:${TAG}..."
skopeo copy ${TLS_FLAG} \
--dest-creds "${REGISTRY_USER}:${REGISTRY_TOKEN}" \
"docker-archive:/tmp/image.tar" \
"docker://${FULL_IMAGE}:${TAG}"
done
rm -f /tmp/image.tar
fi
else
echo "Docker socket (/var/run/docker.sock) is not mounted in this runner container."
echo "Falling back to daemonless Buildah..."
if ! command -v buildah >/dev/null 2>&1; then
apt-get update && apt-get install -y buildah
fi
TLS_FLAG="--tls-verify=true"
if [ "${IS_HTTP}" = "true" ]; then
TLS_FLAG="--tls-verify=false"
fi
buildah bud --storage-driver=vfs --isolation=chroot --pull \
-t "${FULL_IMAGE}:${SAFE_REF}" \
-t "${FULL_IMAGE}:${SHORT_SHA}" \
-t "${FULL_IMAGE}:latest" \
.
for TAG in "${SAFE_REF}" "${SHORT_SHA}" "latest"; do
buildah push --storage-driver=vfs ${TLS_FLAG} \
--creds "${REGISTRY_USER}:${REGISTRY_TOKEN}" \
"${FULL_IMAGE}:${TAG}" \
"docker://${FULL_IMAGE}:${TAG}"
done
fi
+45 -12
View File
@@ -1,23 +1,56 @@
Options +FollowSymLinks
#RewriteEngine on
RewriteEngine on
#RewriteCond %{HTTP_HOST} !^www\.dialyse-berlin\.net [NC]
#RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
# Redirect duplicate homepage URLs (/main.html and /index.php) to canonical root /
RewriteRule ^main\.html$ / [R=301,L]
RewriteCond %{THE_REQUEST} \s/+index\.php[\s?] [NC]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^index\.php$ / [R=301,L]
#RewriteCond %{HTTP_HOST} ^www\.dialyse-berlin\.net [NC]
#RewriteCond %{HTTPS} !=on
#RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# Redirect /de/... to canonical root /... (German is the default language)
RewriteRule ^de/?$ / [R=301,L]
RewriteRule ^de/main\.html$ / [R=301,L]
RewriteRule ^de/([0-9a-zA-Z\-]+)\.html$ /$1.html [R=301,L]
# English subpath routing (/en/ and /en/<page>.html)
RewriteRule ^en/main\.html$ /en/ [R=301,L]
RewriteRule ^en/?$ index.php?lang=en&action=main [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^en/([0-9a-zA-Z\-]+)\.html$ index.php?lang=en&action=$1 [QSA,L]
# Clean URL routing for .html pages (German default)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{QUERY_STRING} ([a-zA-Z0-9-_.=&+%]*)
RewriteRule ^([0-9a-zA-Z\-]+).html$ index.php?action=$1&%1 [L]
RewriteRule ^captcha.png$ captcha.php [L]
# Custom 404 handler
ErrorDocument 404 /index.php?action=404
# Advertise HTTP/3 (h3) support via Alt-Svc header
<IfModule mod_headers.c>
Header setIfEmpty Alt-Svc "h3=\":443\"; ma=86400"
</IfModule>
# Gzip / Deflate Compression for Core Web Vitals & PageSpeed
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/xml application/xhtml+xml application/rss+xml application/javascript application/x-javascript application/ld+json image/svg+xml
</IfModule>
# Browser Caching for Static Assets
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/pdf "access plus 7 days"
ExpiresByType font/ttf "access plus 1 year"
</IfModule>
<Files .htaccess>
order allow,deny
deny from all
Require all denied
</Files>
# Allow Robots.txt to pass through muss noch eingebunden werden
-1
View File
@@ -1 +0,0 @@
{}
-260
View File
@@ -1,260 +0,0 @@
# Design Modernization - Before & After
## Visual Improvements
### Header & Navigation
**BEFORE:**
- Static header images taking up space
- Horizontal menu with poor mobile experience
- No mobile navigation option
- Fixed-width layout
**AFTER:**
- Professional gradient header with logo
- Sticky navigation that stays visible while scrolling
- Mobile hamburger menu for small screens
- Responsive container-based layout
### Color Scheme
**BEFORE:**
- Red gradient buttons (#FF5961 to #B2121B)
- Basic black and white text
- No visual hierarchy through color
**AFTER:**
- Professional blue primary (#0066cc)
- Red accent color (#ff6b35) for calls-to-action
- Light blue backgrounds for emphasis (#e6f0ff)
- Consistent color variables throughout
### Typography
**BEFORE:**
- 14px base font size (too small)
- Basic sans-serif (Open Sans embedded)
- Limited heading hierarchy
- Inconsistent margins
**AFTER:**
- 16px base font size (better readability)
- Modern system font stack (faster loading)
- Clear H1-H6 hierarchy
- Consistent 1.6 line-height for readability
- Better spacing throughout
### Forms
**BEFORE:**
- Wide 50% columns (awkward on mobile)
- Basic text inputs
- No focus states
- Poor mobile layout
**AFTER:**
- Responsive grid layout (full width on mobile)
- Modern input styling with borders and shadows
- Blue focus states with visual feedback
- Better spacing and alignment
- Mobile-optimized form layout
### Images & Gallery
**BEFORE:**
- Float-based positioning
- Inline styles
- No responsive sizing
- Basic no styling
**AFTER:**
- Centered display on mobile
- max-width: 300px default (responsive)
- Box shadows for depth
- Border radius for modern look
- Proper spacing
### Tables
**BEFORE:**
- Basic table with minimal styling
- No visual hierarchy
- Hard to read
**AFTER:**
- Gradient header with white text
- Alternating row backgrounds
- Hover effects for interactivity
- Proper padding and spacing
- Professional appearance
### Buttons
**BEFORE:**
- Basic styled buttons
- No hover effects
- Inconsistent sizing
**AFTER:**
- Modern button styling
- Hover states with color change and shadow
- Transform effect on hover (slight lift)
- Consistent padding
- Professional appearance
### Messages & Alerts
**BEFORE:**
- Simple colored boxes
- No clear visual hierarchy
- Basic styling
**AFTER:**
- Professional alert styling
- Success: Green (#d4edda)
- Error: Red (#f8d7da)
- Clear typography
- Better spacing
### Footer
**BEFORE:**
- Simple text footer
- No styling
- Minimal information
**AFTER:**
- Gradient background matching header
- White text for contrast
- Organized information layout
- Professional appearance
### Mobile Experience
**BEFORE:**
- Not mobile-friendly
- No viewport meta tag
- Fixed widths
- Poor touch targets
**AFTER:**
- Fully responsive design
- Viewport meta tag for proper mobile scaling
- Touch-friendly button sizes (minimum 1rem)
- Mobile navigation menu
- Stack-based layout on small screens
### Responsive Breakpoints
**BEFORE:**
- Not responsive (fixed 900px width)
- Same layout on all devices
**AFTER:**
- Mobile: < 768px
- Single column
- Hamburger menu
- Full-width containers
- Tablet: 768px - 1024px
- Optimized spacing
- 2-column forms
- Desktop: > 1024px
- Full multi-column layout
- Side-by-side elements
---
## Technology Changes
### CSS Framework
**BEFORE:**
- `/css/frontend.css` - 600+ lines of mixed styles
- Outdated CSS patterns (float layouts)
- No organization
- Color hardcoded throughout
**AFTER:**
- `/css/modern.css` - 850+ lines, well-organized
- Modern CSS features (CSS Grid, Flexbox, custom properties)
- Organized into clear sections
- Single source of truth for colors (CSS variables)
- Mobile-first approach
### HTML Structure
**BEFORE:**
- Older HTML structure
- Many inline styles
- Background images for design
- No semantic elements
**AFTER:**
- HTML5 semantic elements (<header>, <nav>, <main>, <footer>)
- Minimal inline styles
- CSS-based design (no image backgrounds)
- Proper heading hierarchy
### JavaScript
**BEFORE:**
- jQuery for DOM manipulation
- Basic interaction only
- Modal handling
**AFTER:**
- Modern vanilla JavaScript (with jQuery fallback)
- Mobile menu toggle
- Enhanced interactions
- Better event handling
---
## Performance Benefits
1. **Faster Load Time**: Removed background images from CSS
2. **Better Mobile Performance**: Mobile-first CSS prioritizes essential styles
3. **Cleaner HTML**: Removed inline styles
4. **Modern Caching**: CSS variables reduce repeated values
5. **Accessibility**: Semantic HTML improves screen reader support
---
## Accessibility Improvements
- ✅ Proper heading hierarchy (H1-H6)
- ✅ Semantic HTML5 elements
- ✅ Color contrast meets WCAG standards
- ✅ Focus states on buttons and links
- ✅ Mobile-friendly touch targets
- ✅ Proper form labels
- ✅ Alt text on images
---
## Browser Compatibility
The modernized site works perfectly on:
| Browser | Version | Status |
|---------|---------|--------|
| Chrome | Latest | ✅ Full Support |
| Firefox | Latest | ✅ Full Support |
| Safari | Latest | ✅ Full Support |
| Edge | Latest | ✅ Full Support |
| Mobile Chrome | Latest | ✅ Full Support |
| Mobile Safari | Latest | ✅ Full Support |
| IE 11 | 11+ | ⚠️ Partial (no CSS Grid) |
---
## Summary
The modernization transformed your website from an outdated design to a professional, responsive, modern experience. All functionality is preserved while the user experience is significantly enhanced, especially on mobile devices.
**Key Metrics:**
- 📱 Mobile-friendly: YES
- 🎨 Modern design: YES
- ⚡ Fast loading: YES
- ♿ Accessible: YES
- 🔒 All features preserved: YES
+10 -18
View File
@@ -1,23 +1,15 @@
FROM php:8.5-apache
FROM php:8.5-apache-trixie
# Install common extensions (example)
# RUN docker-php-ext-install
# Use official production php.ini and configure timezone & security settings
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
&& printf "date.timezone = Europe/Berlin\nexpose_php = Off\nsession.cookie_httponly = 1\nsession.use_strict_mode = 1\n" > "$PHP_INI_DIR/conf.d/99-custom.ini"
# Enable Apache modules if needed
RUN a2enmod rewrite
# Enable Apache modules (including HTTP/2) and harden server signature
RUN a2enmod rewrite headers expires deflate http2 \
&& printf "ServerTokens Prod\nServerSignature Off\nProtocols h2 h2c http/1.1\n" > /etc/apache2/conf-available/security-hardening.conf \
&& a2enconf security-hardening
# Copy application code
COPY . /var/www/html/
COPY --chown=www-data:www-data . /var/www/html/
# Disable the legacy HTTPS redirect rules from .htaccess so the container stays on plain HTTP
# RUN sed -i '/RewriteCond %{HTTP_HOST} !^www\\.dialyse-berlin\\.net \[NC\]/,+2d; /RewriteCond %{HTTP_HOST} ^www\\.dialyse-berlin\\.net \[NC\]/,+2d' /var/www/html/.htaccess || true \
# && a2dismod ssl || true
# Set permissions
RUN chown -R www-data:www-data /var/www/html
# Optional: install Composer dependencies if you have a composer.json
# COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# RUN composer install --no-dev --optimize-autoloader
EXPOSE 80
EXPOSE 80
-188
View File
@@ -1,188 +0,0 @@
# Website Modernization Summary
## Dialysezentrum Berlin-Mahlsdorf
### Project Completion ✅
Your nephrology practice website has been successfully modernized with a responsive, professional design.
---
## What Changed
### 1. **Modern Design Framework**
- **New CSS File**: `/css/modern.css` - A comprehensive modern stylesheet with:
- Mobile-first responsive design
- Modern color scheme (professional blue with red accent)
- CSS custom properties (variables) for easy customization
- Smooth transitions and animations
- Professional shadows and rounded corners
### 2. **Responsive Layout**
- **Mobile-Friendly**: Fully responsive on all devices (phones, tablets, desktops)
- **Hamburger Navigation**: Mobile menu appears on small screens
- **Sticky Navigation**: Menu stays accessible while scrolling
- **Modern Header**: Professional gradient header with logo
- **Flexible Content**: All content adapts beautifully to any screen size
### 3. **Improved User Experience**
- **Better Typography**: Modern font stack and better readability
- **Improved Forms**: Modern form styling with better focus states
- **Professional Tables**: Styled tables with alternating rows and hover effects
- **Image Gallery**: Enhanced gallery display with better styling
- **Modern Buttons**: Styled buttons with hover effects and transitions
### 4. **Semantic HTML**
- **Clean Structure**: Updated all PHP templates with semantic HTML5
- **Better Accessibility**: Proper heading hierarchy and semantic elements
- **Organized Content**: Clear sections and better content organization
---
## Files Modified
| File | Changes |
|------|---------|
| `/css/modern.css` | **NEW** - Modern responsive stylesheet |
| `/view/frontend.php` | New header, footer, and responsive layout |
| `/view/navigation.php` | Updated links to routing system |
| `/view/main.php` | Reorganized with sections and modern styling |
| `/view/services.php` | Better organization with h3 headings |
| `/view/team.php` | Improved list formatting |
| `/view/practice.php` | Modern table styling and layout |
| `/view/contact.php` | Responsive map and contact info |
| `/view/contact-form.php` | Modern form with grid layout |
| `/view/imprint.php` | Semantic HTML structure |
| `/view/terms.php` | Better data privacy presentation |
| `/view/error.php` | Helpful 404 page |
---
## Features Preserved ✅
All existing functionality has been maintained:
- ✅ Contact form with validation
- ✅ Image galleries with Lightbox lightbox plugin
- ✅ Google Maps integration
- ✅ Holiday announcement modal
- ✅ Multi-page routing system
- ✅ All German text content
- ✅ SMTP email functionality
- ✅ Session management
- ✅ Captcha system (disabled in form)
---
## Color Scheme
The new design uses a professional medical color palette:
- **Primary Color**: #0066cc (Professional Blue)
- **Primary Dark**: #004a99 (Deep Blue for hover states)
- **Accent Color**: #ff6b35 (Medical Red)
- **Background**: #f8f9fa (Light Gray)
- **Text**: #2c3e50 (Dark Gray for readability)
---
## Responsive Breakpoints
The design is fully responsive at all screen sizes:
- **Mobile**: < 768px (hamburger menu, single column)
- **Tablet**: 768px - 1024px (optimized layout)
- **Desktop**: > 1024px (full multi-column experience)
---
## How to Customize
### Change Colors
Edit the CSS variables in `/css/modern.css`:
```css
:root {
--primary-color: #0066cc; /* Change this */
--accent-color: #ff6b35; /* And this */
/* ... other variables ... */
}
```
### Adjust Layout
Modify grid and container sizes in the CSS file.
### Add More Content
All page templates follow the same modern structure. Simply add content following the existing pattern.
---
## Browser Support
The new design works on:
- ✅ Chrome/Edge (latest)
- ✅ Firefox (latest)
- ✅ Safari (latest)
- ✅ Mobile browsers (iOS Safari, Chrome Mobile)
- ✅ IE 11+ (with some feature degradation)
---
## Performance Improvements
- Cleaner CSS (modern framework approach)
- Better semantic HTML (faster parsing)
- No unnecessary images in design
- Optimized styling for faster rendering
- Mobile-first approach = better mobile performance
---
## Next Steps (Optional Enhancements)
If you want to further enhance the site:
1. **Add Team Photos**: Update team.php to display doctor/staff photos
2. **Blog/News Section**: Add news updates about the practice
3. **Online Appointment Booking**: Integrate appointment system
4. **Patient Portal**: Add login for patient information access
5. **Testimonials Section**: Showcase patient feedback
6. **Enhanced Analytics**: Track visitor behavior
7. **Multi-language Support**: Add English version
---
## Testing Checklist
- [x] Mobile responsive (test on phone/tablet)
- [x] Navigation works on mobile (hamburger menu)
- [x] Forms are functional
- [x] Links navigate correctly
- [x] Images display properly
- [x] All pages accessible
- [x] Contact form works
- [x] Google Maps loads
- [x] Lightbox galleries function
---
## Support & Customization
The CSS is well-organized with clear sections:
- Reset & Base Styles
- Typography
- Layout & Container
- Header & Navigation
- Forms & Buttons
- Content Area
- Footer
- Utilities
Each section is labeled for easy navigation and modification.
---
## Summary
Your website is now modern, professional, and mobile-responsive. The design maintains all existing functionality while providing a contemporary look that builds confidence with patients. The responsive layout ensures excellent experience on all devices, from smartphones to desktop computers.
**Your site is ready to go! 🎉**
-34
View File
@@ -1,34 +0,0 @@
<?php
$captchaText = sha1(microtime());
$captchaText = base64_encode($captchaText);
$captchaText = substr($captchaText, 1, 5);
$_SESSION['key'] = strtolower($captchaText);
$fonts = ["cheapink.ttf"];
$fontsizes = array(25);
$yCorr = array(25);
$img = ImageCreateFromPNG('img/captcha.png');
$color = ImageColorAllocate($img, 40, 40, 40);
$index = rand(0, count($fonts)-1);
$ttf = 'fonts/' . $fonts[$index];
$ttfsize = $fontsizes[$index];
$angle = rand(2, 6);
$t_x = rand(10, 50);
$t_y = 24 + $yCorr[$index];
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Accept-Ranges: bytes");
header("Content-type: image/png");
ImageTtfText($img, $ttfsize, $angle, $t_x, $t_y, $color, $ttf, $captchaText);
ImagePNG($img);
ImageDestroy($img);
+6 -3
View File
@@ -11,8 +11,11 @@ return [
'before' => '2W',
'from' => '2022-12-27',
'until' => '2025-05-02',
'text' => 'Wir suchen aktuell eine(n) Gesundheits- oder Krankenpfleger-(in)/MFA (m/w/d) für den Dialysebereich, sowie eine Küchenkraft/ Dialyseassistenz in Voll- oder Teilzeit. <br>
Gründliche Einarbeitung gewährleistet! Melden Sie sich gern unter <a href="mailto:kontakt@dialyse-berlin.de">kontakt@dialyse-berlin.de</a>. <br>
Wir freuen uns schon Sie kennen zu lernen!'
'text' => 'Wir suchen aktuell eine(n) Gesundheits- oder Krankenpfleger(in) / MFA (m/w/d) für den Dialysebereich sowie eine Küchenkraft / Dialyseassistenz in Voll- oder Teilzeit. <br>
Gründliche Einarbeitung gewährleistet! Melden Sie sich gern unter <a href="mailto:kontakt@dialyse-berlin.net">kontakt@dialyse-berlin.net</a>. <br>
Wir freuen uns schon, Sie kennenzulernen!',
'text_en' => 'We are currently looking for a registered nurse / medical assistant (m/f/d) for our dialysis unit as well as a kitchen / dialysis assistant (full-time or part-time). <br>
Comprehensive onboarding guaranteed! Please contact us at <a href="mailto:kontakt@dialyse-berlin.net">kontakt@dialyse-berlin.net</a>. <br>
We look forward to meeting you!'
]
];
+26 -8
View File
@@ -2,15 +2,25 @@
require_once __DIR__ . '/lib/SendMail.php';
require_once __DIR__ . '/lib/Session.php';
require_once __DIR__ . '/lib/Helper.php';
$session = new Session();
$lang = 'de';
if (isset($_POST['lang']) && in_array($_POST['lang'], ['de', 'en'], true)) {
$lang = $_POST['lang'];
} elseif ($session->has('lang') && in_array($session->get('lang'), ['de', 'en'], true)) {
$lang = $session->get('lang');
}
$isEn = ($lang === 'en');
function validate($data) {
return !empty($data['name']) && !empty($data['email']) && !empty($data['phone']) && !empty($data['message']);
$hasContact = !empty(trim($data['email'] ?? '')) || !empty(trim($data['phone'] ?? ''));
return !empty(trim($data['name'] ?? '')) && $hasContact && !empty(trim($data['message'] ?? ''));
}
function isBot($data) {
return !empty($data['company']) || ($data['check'] != 'send') && (time() - $data['timestamp']) <= 5;
return !empty($data['company']) || (($data['check'] ?? '') != 'send' && (time() - (int)($data['timestamp'] ?? 0)) <= 5);
}
if($_POST && count($_POST) > 0) {
@@ -21,26 +31,34 @@ if($_POST && count($_POST) > 0) {
if(!validate($_POST)) {
$session->set('form', $_POST);
$session->set('alert-class', 'alert-danger');
$session->set('alert', 'Nicht alle Pflichtfelder ausgefüllt.');
$session->set('alert', $isEn
? 'Please fill out all mandatory fields and provide at least an email address or a phone number.'
: 'Bitte füllen Sie alle Pflichtfelder aus und geben Sie mindestens eine E-Mail-Adresse oder Telefonnummer an.');
} else {
$ip = $_SERVER['REMOTE_ADDR'];
$mail = new SendMail();
$mail->setReplyTo($_POST['email'], $_POST['name']);
if(!empty(trim($_POST['email'] ?? ''))) {
$mail->setReplyTo(trim($_POST['email']), trim($_POST['name']));
}
$mail->setTo('kontakt@dialyse-berlin.net', 'Kontaktformular');
// $mail->setTo('dominic.zirpel@web.de', 'Kontaktformular');
$mail->setSubject('Kontaktformular - Dialyse Homepage');
$mail->setBody(sprintf("Name: %s %s\nTelefon: %s\nIP: %s\nE-Mail: %s\n-----------------------------\n%s", $_POST['surname'], $_POST['name'], $_POST['phone'], $ip, $_POST['email'], $_POST['message']));
$mail->setBody(sprintf("Name: %s %s\nTelefon: %s\nIP: %s\nE-Mail: %s\n-----------------------------\n%s", $_POST['surname'] ?? '', $_POST['name'] ?? '', $_POST['phone'] ?? '', $ip, $_POST['email'] ?? '', $_POST['message'] ?? ''));
if($mail->send()) {
$session->remove('form');
$session->set('alert-class', 'alert-success');
$session->set('alert', 'Ihre Anfrage wurde erfolgreich verschickt');
$session->set('alert', $isEn
? 'Your inquiry has been sent successfully.'
: 'Ihre Anfrage wurde erfolgreich verschickt');
} else {
$session->set('form', $_POST);
$session->set('alert-class', 'alert-danger');
$session->set('alert', 'Beim Verschicken Ihrer Anfrage ist ein Fehler aufgetreten!');
$session->set('alert', $isEn
? 'An error occurred while sending your inquiry!'
: 'Beim Verschicken Ihrer Anfrage ist ein Fehler aufgetreten!');
}
}
}
header('Location: kontakt-formular.html');
header('Location: ' . Helper::url('/kontakt-formular.html', $lang));
+2060 -236
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1 +1 @@
.lb-loader,.lightbox{text-align:center;line-height:0;position:absolute;left:0}body.lb-disable-scrolling{overflow:hidden}.lightboxOverlay{position:absolute;top:0;left:0;z-index:9999;background-color:#000;filter:alpha(Opacity=80);opacity:.8;display:none}.lightbox{width:100%;z-index:10000;font-weight:400;outline:0}.lightbox .lb-image{display:block;height:auto;max-width:inherit;max-height:none;border-radius:3px;border:4px solid #fff}.lightbox a img{border:none}.lb-outerContainer{position:relative;width:250px;height:250px;margin:0 auto;border-radius:4px;background-color:#fff}.lb-outerContainer:after{content:"";display:table;clear:both}.lb-loader{top:43%;height:25%;width:100%}.lb-cancel{display:block;width:32px;height:32px;margin:0 auto;background:url(../img/lightbox/loading.gif) no-repeat}.lb-nav{position:absolute;top:0;left:0;height:100%;width:100%;z-index:10}.lb-container>.nav{left:0}.lb-nav a{outline:0;background-image:url(data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}.lb-next,.lb-prev{height:100%;cursor:pointer;display:block}.lb-nav a.lb-prev{width:34%;left:0;float:left;background:url(../img/lightbox/prev.png) left 48% no-repeat;filter:alpha(Opacity=0);opacity:0;-webkit-transition:opacity .6s;-moz-transition:opacity .6s;-o-transition:opacity .6s;transition:opacity .6s}.lb-nav a.lb-prev:hover{filter:alpha(Opacity=100);opacity:1}.lb-nav a.lb-next{width:64%;right:0;float:right;background:url(../img/lightbox/next.png) right 48% no-repeat;filter:alpha(Opacity=0);opacity:0;-webkit-transition:opacity .6s;-moz-transition:opacity .6s;-o-transition:opacity .6s;transition:opacity .6s}.lb-nav a.lb-next:hover{filter:alpha(Opacity=100);opacity:1}.lb-dataContainer{margin:0 auto;padding-top:5px;width:100%;border-bottom-left-radius:4px;border-bottom-right-radius:4px}.lb-dataContainer:after{content:"";display:table;clear:both}.lb-data{padding:0 4px;color:#ccc}.lb-data .lb-details{width:85%;float:left;text-align:left;line-height:1.1em}.lb-data .lb-caption{font-size:13px;font-weight:700;line-height:1em}.lb-data .lb-caption a{color:#4ae}.lb-data .lb-number{display:block;clear:left;padding-bottom:1em;font-size:12px;color:#999}.lb-data .lb-close{display:block;float:right;width:30px;height:30px;background:url(../img/lightbox/close.png) top right no-repeat;text-align:right;outline:0;filter:alpha(Opacity=70);opacity:.7;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.lb-data .lb-close:hover{cursor:pointer;filter:alpha(Opacity=100);opacity:1}
.lb-loader,.lightbox{text-align:center;line-height:0}body.lb-disable-scrolling{overflow:hidden}.lightboxOverlay{position:absolute;top:0;left:0;z-index:9999;background-color:#000;opacity:.8;display:none}.lightbox{position:absolute;left:0;width:100%;z-index:10000;font-weight:400;outline:0}.lightbox .lb-image{display:block;height:auto;max-width:inherit;max-height:none;border-radius:3px;border:4px solid #fff}.lightbox a img{border:none}.lb-outerContainer{position:relative;width:250px;height:250px;margin:0 auto;border-radius:4px;background-color:#fff}.lb-loader,.lb-nav{position:absolute;left:0}.lb-outerContainer:after{content:"";display:table;clear:both}.lb-loader{top:43%;height:25%;width:100%}.lb-cancel{display:block;width:32px;height:32px;margin:0 auto;background:url(../img/lightbox/loading.gif) no-repeat}.lb-nav{top:0;height:100%;width:100%;z-index:10}.lb-container>.nav{left:0}.lb-nav a{outline:0;background-image:url(data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}.lb-next,.lb-prev{height:100%;cursor:pointer;display:block}.lb-nav a.lb-prev{width:34%;left:0;float:left;background:url(../img/lightbox/prev.png) left 48% no-repeat;opacity:0;-webkit-transition:opacity .6s;-moz-transition:opacity .6s;-o-transition:opacity .6s;transition:opacity .6s}.lb-nav a.lb-prev:hover{opacity:1}.lb-nav a.lb-next{width:64%;right:0;float:right;background:url(../img/lightbox/next.png) right 48% no-repeat;opacity:0;-webkit-transition:opacity .6s;-moz-transition:opacity .6s;-o-transition:opacity .6s;transition:opacity .6s}.lb-nav a.lb-next:hover{opacity:1}.lb-dataContainer{margin:0 auto;padding-top:5px;width:100%;border-bottom-left-radius:4px;border-bottom-right-radius:4px}.lb-dataContainer:after{content:"";display:table;clear:both}.lb-data{padding:0 4px;color:#ccc}.lb-data .lb-details{width:85%;float:left;text-align:left;line-height:1.1em}.lb-data .lb-caption{font-size:13px;font-weight:700;line-height:1em}.lb-data .lb-caption a{color:#4ae}.lb-data .lb-number{display:block;clear:left;padding-bottom:1em;font-size:12px;color:#999}.lb-data .lb-close{display:block;float:right;width:30px;height:30px;background:url(../img/lightbox/close.png) top right no-repeat;text-align:right;outline:0;opacity:.7;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.lb-data .lb-close:hover{cursor:pointer;opacity:1}
-723
View File
@@ -1,723 +0,0 @@
/* ============================================
Modern Responsive Design - Nephrology Practice
============================================ */
:root {
--primary-color: #0066cc;
--primary-dark: #004a99;
--primary-light: #e6f0ff;
--accent-color: #ff6b35;
--text-color: #2c3e50;
--text-light: #5a6c7d;
--bg-color: #ffffff;
--bg-light: #f8f9fa;
--border-color: #dee2e6;
--shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.15);
--transition: all 0.3s ease;
}
/* ============================================
Reset & Base Styles
============================================ */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
font-size: 16px;
line-height: 1.6;
color: var(--text-color);
background-color: var(--bg-color);
}
img {
border: 0;
max-width: 100%;
height: auto;
display: block;
}
a {
color: var(--primary-color);
text-decoration: none;
transition: var(--transition);
}
a:hover {
color: var(--primary-dark);
text-decoration: underline;
}
p {
margin-bottom: 1.5rem;
}
/* ============================================
Typography
============================================ */
h1, h2, h3, h4, h5, h6 {
font-weight: 600;
line-height: 1.2;
margin-bottom: 1.5rem;
color: var(--text-color);
}
h1 {
font-size: 2.5rem;
margin-bottom: 2rem;
}
h2 {
font-size: 2rem;
margin-bottom: 1.5rem;
}
h3 {
font-size: 1.5rem;
margin-bottom: 1.25rem;
}
h4 {
font-size: 1.25rem;
}
@media (max-width: 768px) {
h1 {
font-size: 2rem;
}
h2 {
font-size: 1.5rem;
}
h3 {
font-size: 1.25rem;
}
}
/* ============================================
Layout & Container
============================================ */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
@media (max-width: 768px) {
.container {
padding: 0 15px;
}
}
/* ============================================
Header
============================================ */
#outer-container {
display: flex;
flex-direction: column;
min-height: 100vh;
}
#header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);
color: white;
padding: 1rem 0;
box-shadow: var(--shadow);
}
#header-content {
display: flex;
align-items: center;
justify-content: space-between;
}
#header-logo {
font-size: 1.8rem;
font-weight: 700;
color: white;
}
#header-logo-subtitle {
font-size: 0.9rem;
opacity: 0.9;
font-weight: 400;
}
.header-image {
width: 100%;
height: auto;
max-height: 300px;
object-fit: cover;
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);
}
@media (max-width: 768px) {
#header {
padding: 1.5rem 0;
}
#header-logo {
font-size: 1.4rem;
}
#header-logo-subtitle {
font-size: 0.85rem;
}
}
/* ============================================
Navigation
============================================ */
#menu {
background-color: var(--bg-color);
border-bottom: 3px solid var(--primary-color);
position: sticky;
top: 0;
z-index: 1000;
box-shadow: var(--shadow);
}
#menu ul {
list-style-type: none;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
flex-wrap: wrap;
}
#menu ul li {
display: inline-flex;
padding: 0;
}
#menu ul li a {
display: block;
color: var(--text-color);
padding: 1rem 1.5rem;
text-decoration: none;
font-weight: 500;
border-bottom: 3px solid transparent;
transition: var(--transition);
}
#menu ul li a:hover,
#menu ul li a.active {
color: var(--primary-color);
background-color: var(--primary-light);
border-bottom-color: var(--primary-color);
text-decoration: none;
}
/* Mobile Menu Toggle */
#menu-toggle {
display: none;
background: none;
border: none;
color: var(--text-color);
font-size: 1.5rem;
cursor: pointer;
padding: 0.5rem;
}
@media (max-width: 768px) {
#menu ul {
flex-direction: column;
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
position: absolute;
top: 100%;
left: 0;
right: 0;
background: var(--bg-color);
border-bottom: 3px solid var(--primary-color);
}
#menu ul.active {
max-height: 500px;
}
#menu ul li {
width: 100%;
}
#menu ul li a {
border: none;
border-left: 4px solid transparent;
padding: 1rem 1.5rem;
width: 100%;
}
#menu ul li a:hover,
#menu ul li a.active {
border-left-color: var(--primary-color);
background-color: var(--primary-light);
border-bottom: none;
}
#menu-toggle {
display: inline-block;
}
#menu {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}
}
/* ============================================
Content Area
============================================ */
#outer-content {
flex: 1;
padding: 3rem 0;
background-color: var(--bg-light);
}
#inner-content {
max-width: 900px;
margin: 0 auto;
padding: 2rem;
background: var(--bg-color);
border-radius: 8px;
box-shadow: var(--shadow);
}
@media (max-width: 768px) {
#outer-content {
padding: 2rem 0;
}
#inner-content {
padding: 1.5rem;
margin: 0 15px;
}
}
/* ============================================
Footer
============================================ */
#footer {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);
color: white;
padding: 2rem;
text-align: center;
border-top: 3px solid var(--accent-color);
margin-top: auto;
}
#footer a {
color: #e6f0ff;
}
#footer a:hover {
color: white;
text-decoration: underline;
}
/* ============================================
Messages
============================================ */
.errorMessage,
.alert-danger {
padding: 1rem;
border: 1px solid #f5c6cb;
border-radius: 6px;
background: #f8d7da;
color: #721c24;
margin-bottom: 2rem;
font-weight: 500;
}
.successMessage,
.alert-success {
padding: 1rem;
border: 1px solid #c3e6cb;
border-radius: 6px;
background: #d4edda;
color: #155724;
margin-bottom: 2rem;
font-weight: 500;
}
.alert {
padding: 1rem;
border-radius: 6px;
margin-bottom: 2rem;
border: 1px solid transparent;
}
/* ============================================
Forms
============================================ */
form {
margin-bottom: 2rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: var(--text-color);
}
input[type="text"],
input[type="email"],
input[type="phone"],
input[type="tel"],
input[type="password"],
textarea,
select {
width: 100%;
padding: 0.75rem;
margin-bottom: 1.5rem;
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 1rem;
font-family: inherit;
transition: var(--transition);
}
input[type="text"]:focus,
input[type="email"]:focus,
input[type="phone"]:focus,
input[type="tel"]:focus,
input[type="password"]:focus,
textarea:focus,
select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);
}
textarea {
resize: vertical;
min-height: 150px;
}
.ktColumn {
width: calc(50% - 1rem);
display: inline-block;
vertical-align: top;
}
.ktColumn:nth-child(even) {
margin-left: 2rem;
}
@media (max-width: 768px) {
.ktColumn {
width: 100%;
margin-left: 0 !important;
}
}
/* ============================================
Buttons
============================================ */
input[type="submit"],
input[type="button"],
button,
.btn {
padding: 0.75rem 1.5rem;
background: var(--primary-color);
color: white;
border: none;
border-radius: 6px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: var(--transition);
display: inline-block;
text-decoration: none;
}
input[type="submit"]:hover,
input[type="button"]:hover,
button:hover,
.btn:hover {
background: var(--primary-dark);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
input[type="button"]:nth-of-type(1) {
background: var(--border-color);
color: var(--text-color);
}
input[type="button"]:nth-of-type(1):hover {
background: #ccc;
}
#kontaktbuttons {
display: flex;
gap: 1rem;
margin-top: 2rem;
}
#kontaktbuttons input[type="button"],
#kontaktbuttons input[type="submit"] {
flex: 1;
padding: 1rem;
font-size: 1.1rem;
}
@media (max-width: 768px) {
#kontaktbuttons {
flex-direction: column;
}
}
/* ============================================
Lists & Content
============================================ */
ul {
margin-left: 2rem;
margin-bottom: 1.5rem;
}
ul li {
margin-bottom: 0.75rem;
line-height: 1.8;
}
ul ul {
margin-top: 0.75rem;
margin-bottom: 0.75rem;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 2rem;
box-shadow: var(--shadow);
border-radius: 6px;
overflow: hidden;
}
table td {
padding: 1rem;
border-bottom: 1px solid var(--border-color);
}
table tr:last-child td {
border-bottom: none;
}
table tr.tdHead,
table tr:first-child {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);
color: white;
font-weight: 600;
}
table tr:nth-child(even) {
background-color: var(--primary-light);
}
table tr:hover {
background-color: #f0f7ff;
}
.kontakt table tr.tdHead td {
padding: 1rem;
}
.kontakt table td span {
font-weight: 600;
color: var(--primary-color);
}
/* ============================================
Images & Gallery
============================================ */
.floatLeftImage,
.floatRightImage {
margin: 1rem;
padding: 8px;
background: white;
border: 1px solid var(--border-color);
border-radius: 6px;
box-shadow: var(--shadow);
}
.floatLeftImage {
float: left;
}
.floatRightImage {
float: right;
}
@media (max-width: 768px) {
.floatLeftImage,
.floatRightImage {
float: none;
margin: 1rem auto;
max-width: 300px;
}
}
.floatLeftImage img,
.floatRightImage img {
width: 100%;
height: auto;
cursor: pointer;
}
.alignCenter {
text-align: center;
clear: both;
margin: 2rem 0;
}
.alignCenter a {
display: inline-block;
margin: 0.5rem;
border-radius: 6px;
overflow: hidden;
box-shadow: var(--shadow);
transition: var(--transition);
}
.alignCenter a:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
}
.alignCenter img {
width: 150px;
height: 150px;
object-fit: cover;
}
.alignRight {
text-align: right;
}
.clear {
clear: both;
}
/* ============================================
Maps
============================================ */
.profile-map {
border-radius: 6px;
box-shadow: var(--shadow);
margin-bottom: 2rem;
}
/* ============================================
Holiday Dialog
============================================ */
#holiday-wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2000;
display: flex;
align-items: center;
justify-content: center;
}
.holiday-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.holiday-dialog {
position: relative;
background: white;
padding: 2rem;
border-radius: 8px;
max-width: 500px;
box-shadow: var(--shadow-lg);
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.holiday-dialog p {
margin-bottom: 1rem;
}
.holiday-dialog p:last-child {
margin-bottom: 0;
}
/* ============================================
Responsive Utilities
============================================ */
.title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 1rem;
}
.stack {
display: inline-block;
min-width: 70px;
font-weight: 600;
}
.alignCenter {
text-align: center;
}
@media print {
#header,
#menu,
#footer {
display: none;
}
#outer-content {
background: white;
}
#inner-content {
box-shadow: none;
border: none;
}
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

+650
View File
@@ -0,0 +1,650 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Praxis-Flyer | Dialysezentrum Berlin-Mahlsdorf</title>
<style>
@page {
size: A4 portrait;
margin: 0;
}
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Open Sans', Arial, Helvetica, sans-serif;
color: #1e293b;
background: #ffffff;
line-height: 1.45;
font-size: 9pt;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.page {
width: 210mm;
height: 297mm;
position: relative;
padding: 9.5mm 11.5mm 8.5mm;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* Header */
.flyer-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 3mm;
border-bottom: 2px solid #0284c7;
margin-bottom: 3.5mm;
}
.brand {
display: flex;
align-items: center;
}
.header-right {
display: flex;
align-items: center;
gap: 3.2mm;
}
.header-contact {
text-align: right;
font-size: 8.8pt;
color: #07384d;
line-height: 1.42;
}
.header-contact strong {
color: #07384d;
}
.header-contact .web-link {
color: #0284c7;
font-weight: 700;
}
.header-qr-box {
width: 15.5mm;
height: 15.5mm;
padding: 1.1mm;
background: #ffffff;
border: 1px solid #cbd5e1;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.header-qr {
width: 100%;
height: 100%;
display: block;
}
/* Motto Banner */
.motto-banner {
background: linear-gradient(135deg, #07384d 0%, #0b4f6c 100%);
color: #ffffff;
border-radius: 6px;
padding: 3.2mm 4.5mm;
margin-bottom: 3.5mm;
display: flex;
justify-content: space-between;
align-items: center;
gap: 3mm;
}
.motto-text {
font-size: 10.2pt;
font-weight: 700;
font-style: italic;
color: #f0f9ff;
white-space: nowrap;
}
.motto-sub {
font-size: 8pt;
color: #bae6fd;
white-space: nowrap;
font-weight: 600;
}
/* Physicians Row */
.physicians-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 3.4mm;
margin-bottom: 3.6mm;
}
.physician-card {
background: #f8fafc;
border: 1px solid #e2e8f0;
border-left: 3.5px solid #0284c7;
border-radius: 6px;
padding: 3mm 3.4mm;
}
.physician-name {
font-size: 9.4pt;
font-weight: 700;
color: #07384d;
line-height: 1.25;
}
.physician-role {
font-size: 7.2pt;
font-weight: 600;
color: #0284c7;
margin-top: 0.8mm;
line-height: 1.3;
white-space: nowrap;
}
/* Main 2-Column Content Grid */
.content-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3.8mm;
flex: 1;
margin-bottom: 3.5mm;
}
.col-stack {
display: flex;
flex-direction: column;
gap: 3.5mm;
height: 100%;
}
.section-card {
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 6px;
padding: 3.8mm 4.2mm;
}
.section-card.card-grow {
flex: 1;
display: flex;
flex-direction: column;
}
.card-header {
display: flex;
align-items: center;
gap: 6px;
font-size: 9.6pt;
font-weight: 700;
color: #07384d;
margin-bottom: 2.5mm;
padding-bottom: 1.5mm;
border-bottom: 1px solid #e2e8f0;
}
.card-header svg {
width: 14px;
height: 14px;
fill: #0284c7;
flex-shrink: 0;
}
/* Lists & Details */
.check-list {
list-style: none;
font-size: 8.8pt;
color: #334155;
display: flex;
flex-direction: column;
justify-content: space-around;
flex: 1;
gap: 2.2mm;
}
.check-list li {
position: relative;
padding-left: 14px;
line-height: 1.42;
}
.check-list li::before {
content: "✓";
position: absolute;
left: 0;
top: 0;
color: #0284c7;
font-weight: bold;
font-size: 8.8pt;
}
/* Schedule rows */
.sched-list {
display: flex;
flex-direction: column;
justify-content: space-around;
flex: 1;
}
.sched-item {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 8.5pt;
padding: 1.8mm 0;
border-bottom: 1px dashed #e2e8f0;
line-height: 1.42;
}
.sched-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
.sched-title {
font-weight: 700;
color: #07384d;
white-space: nowrap;
}
.sched-hours {
text-align: right;
color: #1e293b;
}
.badge-tag {
background: #e0f2fe;
color: #0369a1;
font-size: 7pt;
font-weight: 700;
padding: 0.5px 4px;
border-radius: 3px;
margin-right: 3px;
}
/* Locations */
.loc-block {
margin-bottom: 2.8mm;
font-size: 8.6pt;
line-height: 1.45;
}
.loc-block:last-child {
margin-bottom: 0;
}
.loc-head-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.7mm;
}
.loc-head {
font-weight: 700;
color: #07384d;
font-size: 9pt;
}
.loc-badge {
background: #e0f2fe;
color: #0369a1;
font-size: 7.2pt;
font-weight: 700;
padding: 0.5mm 2.2mm;
border-radius: 99px;
}
.loc-body {
color: #475569;
}
.loc-body strong {
color: #07384d;
}
/* Anfahrt & Map */
.anfahrt-flex {
display: flex;
gap: 3.5mm;
align-items: center;
}
.anfahrt-text {
flex: 1;
font-size: 8.5pt;
color: #475569;
line-height: 1.42;
}
.anfahrt-text p {
margin-bottom: 2mm;
}
.anfahrt-text p:last-child {
margin-bottom: 0;
}
.map-thumb {
width: 39mm;
height: 44mm;
object-fit: contain;
border: 1px solid #cbd5e1;
border-radius: 5px;
background: #ffffff;
padding: 1mm;
flex-shrink: 0;
}
/* Photo Showcase Card */
.photo-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2.8mm;
flex: 1;
}
.photo-item {
position: relative;
border-radius: 5px;
overflow: hidden;
border: 1px solid #cbd5e1;
height: 100%;
min-height: 62mm;
}
.photo-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(7, 56, 77, 0.9), rgba(7, 56, 77, 0));
color: #ffffff;
font-size: 6.5pt;
font-weight: 600;
padding: 4mm 1.5mm 1.5mm;
text-align: center;
white-space: nowrap;
}
/* Bottom Callout & Footer */
.footer-callout {
background: linear-gradient(135deg, #07384d 0%, #0284c7 100%);
color: #ffffff;
border-radius: 6px;
padding: 3mm 4.5mm;
display: flex;
justify-content: space-between;
align-items: center;
gap: 4mm;
}
.callout-left {
flex: 1;
min-width: 0;
}
.callout-title {
font-size: 9pt;
font-weight: 700;
margin-bottom: 0.4mm;
white-space: nowrap;
}
.callout-sub {
font-size: 7.4pt;
color: #e0f2fe;
white-space: nowrap;
}
.callout-channels {
display: flex;
gap: 5mm;
align-items: center;
flex-shrink: 0;
}
.callout-item {
text-align: right;
}
.callout-item small {
display: block;
font-size: 6pt;
font-weight: 600;
color: #bae6fd;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.callout-item .channel-val {
font-size: 8.8pt;
font-weight: 800;
color: #ffffff;
white-space: nowrap;
}
.flyer-bottom-info {
border-top: 1px solid #e2e8f0;
padding-top: 1.4mm;
margin-top: 1.6mm;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: 0.4mm;
font-size: 6.6pt;
color: #64748b;
line-height: 1.3;
}
</style>
</head>
<body>
<div class="page">
<!-- Top Brand Header -->
<div class="flyer-header">
<div class="brand">
<img src="file:///d:/web-repo2/img/logo_dialysezentrum.png" style="height: 15.5mm; width: auto; object-fit: contain;" alt="Dialysezentrum Berlin-Mahlsdorf">
</div>
<div class="header-right">
<div class="header-contact">
<div><strong>Praxis für Nephrologie &amp; Dialyse</strong></div>
<div>Web: <span class="web-link">www.dialyse-berlin.net</span></div>
</div>
<div class="header-qr-box">
<svg class="header-qr" viewBox="0 0 29 29" shape-rendering="crispEdges" aria-label="QR-Code www.dialyse-berlin.net"><path fill="#07384d" d="M0,0h1v1h-1zM1,0h1v1h-1zM2,0h1v1h-1zM3,0h1v1h-1zM4,0h1v1h-1zM5,0h1v1h-1zM6,0h1v1h-1zM8,0h1v1h-1zM9,0h1v1h-1zM10,0h1v1h-1zM22,0h1v1h-1zM23,0h1v1h-1zM24,0h1v1h-1zM25,0h1v1h-1zM26,0h1v1h-1zM27,0h1v1h-1zM28,0h1v1h-1zM0,1h1v1h-1zM6,1h1v1h-1zM11,1h1v1h-1zM12,1h1v1h-1zM16,1h1v1h-1zM17,1h1v1h-1zM18,1h1v1h-1zM19,1h1v1h-1zM22,1h1v1h-1zM28,1h1v1h-1zM0,2h1v1h-1zM2,2h1v1h-1zM3,2h1v1h-1zM4,2h1v1h-1zM6,2h1v1h-1zM9,2h1v1h-1zM10,2h1v1h-1zM12,2h1v1h-1zM13,2h1v1h-1zM15,2h1v1h-1zM16,2h1v1h-1zM17,2h1v1h-1zM20,2h1v1h-1zM22,2h1v1h-1zM24,2h1v1h-1zM25,2h1v1h-1zM26,2h1v1h-1zM28,2h1v1h-1zM0,3h1v1h-1zM2,3h1v1h-1zM3,3h1v1h-1zM4,3h1v1h-1zM6,3h1v1h-1zM8,3h1v1h-1zM10,3h1v1h-1zM11,3h1v1h-1zM12,3h1v1h-1zM14,3h1v1h-1zM15,3h1v1h-1zM16,3h1v1h-1zM18,3h1v1h-1zM22,3h1v1h-1zM24,3h1v1h-1zM25,3h1v1h-1zM26,3h1v1h-1zM28,3h1v1h-1zM0,4h1v1h-1zM2,4h1v1h-1zM3,4h1v1h-1zM4,4h1v1h-1zM6,4h1v1h-1zM8,4h1v1h-1zM9,4h1v1h-1zM10,4h1v1h-1zM11,4h1v1h-1zM12,4h1v1h-1zM13,4h1v1h-1zM14,4h1v1h-1zM16,4h1v1h-1zM17,4h1v1h-1zM18,4h1v1h-1zM22,4h1v1h-1zM24,4h1v1h-1zM25,4h1v1h-1zM26,4h1v1h-1zM28,4h1v1h-1zM0,5h1v1h-1zM6,5h1v1h-1zM8,5h1v1h-1zM11,5h1v1h-1zM13,5h1v1h-1zM14,5h1v1h-1zM15,5h1v1h-1zM19,5h1v1h-1zM20,5h1v1h-1zM22,5h1v1h-1zM28,5h1v1h-1zM0,6h1v1h-1zM1,6h1v1h-1zM2,6h1v1h-1zM3,6h1v1h-1zM4,6h1v1h-1zM5,6h1v1h-1zM6,6h1v1h-1zM8,6h1v1h-1zM10,6h1v1h-1zM12,6h1v1h-1zM14,6h1v1h-1zM16,6h1v1h-1zM18,6h1v1h-1zM20,6h1v1h-1zM22,6h1v1h-1zM23,6h1v1h-1zM24,6h1v1h-1zM25,6h1v1h-1zM26,6h1v1h-1zM27,6h1v1h-1zM28,6h1v1h-1zM8,7h1v1h-1zM10,7h1v1h-1zM11,7h1v1h-1zM14,7h1v1h-1zM17,7h1v1h-1zM19,7h1v1h-1zM0,8h1v1h-1zM4,8h1v1h-1zM6,8h1v1h-1zM7,8h1v1h-1zM8,8h1v1h-1zM9,8h1v1h-1zM10,8h1v1h-1zM12,8h1v1h-1zM13,8h1v1h-1zM14,8h1v1h-1zM15,8h1v1h-1zM16,8h1v1h-1zM17,8h1v1h-1zM19,8h1v1h-1zM20,8h1v1h-1zM21,8h1v1h-1zM22,8h1v1h-1zM23,8h1v1h-1zM24,8h1v1h-1zM25,8h1v1h-1zM28,8h1v1h-1zM2,9h1v1h-1zM5,9h1v1h-1zM8,9h1v1h-1zM10,9h1v1h-1zM11,9h1v1h-1zM17,9h1v1h-1zM18,9h1v1h-1zM22,9h1v1h-1zM23,9h1v1h-1zM24,9h1v1h-1zM25,9h1v1h-1zM26,9h1v1h-1zM27,9h1v1h-1zM28,9h1v1h-1zM0,10h1v1h-1zM1,10h1v1h-1zM3,10h1v1h-1zM6,10h1v1h-1zM9,10h1v1h-1zM13,10h1v1h-1zM14,10h1v1h-1zM15,10h1v1h-1zM17,10h1v1h-1zM20,10h1v1h-1zM22,10h1v1h-1zM23,10h1v1h-1zM24,10h1v1h-1zM28,10h1v1h-1zM3,11h1v1h-1zM7,11h1v1h-1zM8,11h1v1h-1zM10,11h1v1h-1zM11,11h1v1h-1zM12,11h1v1h-1zM13,11h1v1h-1zM15,11h1v1h-1zM16,11h1v1h-1zM17,11h1v1h-1zM18,11h1v1h-1zM20,11h1v1h-1zM21,11h1v1h-1zM22,11h1v1h-1zM24,11h1v1h-1zM25,11h1v1h-1zM27,11h1v1h-1zM28,11h1v1h-1zM1,12h1v1h-1zM4,12h1v1h-1zM6,12h1v1h-1zM9,12h1v1h-1zM10,12h1v1h-1zM11,12h1v1h-1zM12,12h1v1h-1zM13,12h1v1h-1zM17,12h1v1h-1zM20,12h1v1h-1zM21,12h1v1h-1zM27,12h1v1h-1zM0,13h1v1h-1zM1,13h1v1h-1zM3,13h1v1h-1zM4,13h1v1h-1zM5,13h1v1h-1zM10,13h1v1h-1zM11,13h1v1h-1zM12,13h1v1h-1zM13,13h1v1h-1zM14,13h1v1h-1zM16,13h1v1h-1zM17,13h1v1h-1zM18,13h1v1h-1zM20,13h1v1h-1zM22,13h1v1h-1zM24,13h1v1h-1zM25,13h1v1h-1zM26,13h1v1h-1zM27,13h1v1h-1zM28,13h1v1h-1zM1,14h1v1h-1zM2,14h1v1h-1zM6,14h1v1h-1zM7,14h1v1h-1zM10,14h1v1h-1zM11,14h1v1h-1zM12,14h1v1h-1zM16,14h1v1h-1zM18,14h1v1h-1zM20,14h1v1h-1zM21,14h1v1h-1zM24,14h1v1h-1zM25,14h1v1h-1zM26,14h1v1h-1zM28,14h1v1h-1zM3,15h1v1h-1zM4,15h1v1h-1zM5,15h1v1h-1zM9,15h1v1h-1zM10,15h1v1h-1zM12,15h1v1h-1zM14,15h1v1h-1zM17,15h1v1h-1zM20,15h1v1h-1zM22,15h1v1h-1zM27,15h1v1h-1zM28,15h1v1h-1zM3,16h1v1h-1zM5,16h1v1h-1zM6,16h1v1h-1zM7,16h1v1h-1zM10,16h1v1h-1zM13,16h1v1h-1zM14,16h1v1h-1zM15,16h1v1h-1zM16,16h1v1h-1zM17,16h1v1h-1zM18,16h1v1h-1zM19,16h1v1h-1zM20,16h1v1h-1zM21,16h1v1h-1zM23,16h1v1h-1zM27,16h1v1h-1zM0,17h1v1h-1zM2,17h1v1h-1zM3,17h1v1h-1zM5,17h1v1h-1zM7,17h1v1h-1zM12,17h1v1h-1zM17,17h1v1h-1zM18,17h1v1h-1zM22,17h1v1h-1zM23,17h1v1h-1zM24,17h1v1h-1zM25,17h1v1h-1zM27,17h1v1h-1zM28,17h1v1h-1zM2,18h1v1h-1zM6,18h1v1h-1zM8,18h1v1h-1zM13,18h1v1h-1zM14,18h1v1h-1zM15,18h1v1h-1zM18,18h1v1h-1zM20,18h1v1h-1zM21,18h1v1h-1zM22,18h1v1h-1zM24,18h1v1h-1zM26,18h1v1h-1zM28,18h1v1h-1zM4,19h1v1h-1zM9,19h1v1h-1zM10,19h1v1h-1zM13,19h1v1h-1zM15,19h1v1h-1zM16,19h1v1h-1zM17,19h1v1h-1zM19,19h1v1h-1zM22,19h1v1h-1zM27,19h1v1h-1zM28,19h1v1h-1zM0,20h1v1h-1zM1,20h1v1h-1zM4,20h1v1h-1zM6,20h1v1h-1zM7,20h1v1h-1zM8,20h1v1h-1zM9,20h1v1h-1zM13,20h1v1h-1zM17,20h1v1h-1zM19,20h1v1h-1zM20,20h1v1h-1zM21,20h1v1h-1zM22,20h1v1h-1zM23,20h1v1h-1zM24,20h1v1h-1zM25,20h1v1h-1zM28,20h1v1h-1zM8,21h1v1h-1zM13,21h1v1h-1zM14,21h1v1h-1zM16,21h1v1h-1zM17,21h1v1h-1zM18,21h1v1h-1zM20,21h1v1h-1zM24,21h1v1h-1zM28,21h1v1h-1zM0,22h1v1h-1zM1,22h1v1h-1zM2,22h1v1h-1zM3,22h1v1h-1zM4,22h1v1h-1zM5,22h1v1h-1zM6,22h1v1h-1zM8,22h1v1h-1zM9,22h1v1h-1zM10,22h1v1h-1zM11,22h1v1h-1zM16,22h1v1h-1zM18,22h1v1h-1zM19,22h1v1h-1zM20,22h1v1h-1zM22,22h1v1h-1zM24,22h1v1h-1zM25,22h1v1h-1zM26,22h1v1h-1zM28,22h1v1h-1zM0,23h1v1h-1zM6,23h1v1h-1zM10,23h1v1h-1zM11,23h1v1h-1zM12,23h1v1h-1zM14,23h1v1h-1zM17,23h1v1h-1zM19,23h1v1h-1zM20,23h1v1h-1zM24,23h1v1h-1zM27,23h1v1h-1zM0,24h1v1h-1zM2,24h1v1h-1zM3,24h1v1h-1zM4,24h1v1h-1zM6,24h1v1h-1zM8,24h1v1h-1zM9,24h1v1h-1zM10,24h1v1h-1Line truncated
</div>
</div>
</div>
<!-- Motto Banner -->
<div class="motto-banner">
<div class="motto-text">&bdquo;Die individuelle Dialyse im grünen Gürtel von Berlin&ldquo;</div>
<div class="motto-sub">2 Standorte &bull; Feriendialyse &bull; Barrierefrei</div>
</div>
<!-- Physicians Row -->
<div class="physicians-row">
<div class="physician-card">
<div class="physician-name">Dr. med. Bianca Bischoff</div>
<div class="physician-role">Fachärztin für Innere Medizin &amp; Nephrologie</div>
</div>
<div class="physician-card">
<div class="physician-name">Dr. med. Juliane Hoffzimmer</div>
<div class="physician-role">Fachärztin für Innere Medizin &amp; Nephrologie</div>
</div>
<div class="physician-card">
<div class="physician-name">Dr. med. Claudia Körner</div>
<div class="physician-role">Fachärztin für Innere Medizin</div>
</div>
</div>
<!-- Main 2-Column Content -->
<div class="content-grid">
<!-- LEFT COLUMN: Leistungen, Komfort & Behandlungszeiten -->
<div class="col-stack">
<!-- Leistungen -->
<div class="section-card card-grow">
<div class="card-header">
<svg viewBox="0 0 24 24"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/></svg>
Leistungsspektrum &amp; Medizintechnik
</div>
<ul class="check-list">
<li><strong>Nephrologische Ambulanz:</strong> Diagnostik &amp; Therapie von Nierenerkrankungen, Blutdruck- und Diabeteseinstellung</li>
<li><strong>Funktionsdiagnostik:</strong> Sonographie (Nieren/Abdomen), EKG &amp; 24-Std.-Blutdruckmessung</li>
<li><strong>Dialyseverfahren (HD &amp; Online-HDF):</strong> Kreislaufschonend mit Nikkiso <strong>Haemo-Master</strong> &amp; <strong>Fresenius BCM</strong></li>
<li><strong>Begleitende Betreuung:</strong> Transplantationsvorbereitung, Nachsorge &amp; individuelle Ernährungsberatung</li>
</ul>
</div>
<!-- Feriendialyse & Komfort -->
<div class="section-card">
<div class="card-header">
<svg viewBox="0 0 24 24"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>
Feriendialyse &amp; Patientenkomfort
</div>
<ul class="check-list">
<li><strong>Ganzjährige Feriendialysen</strong> für Berlin-Besucher in barrierefreien Praxisräumen</li>
<li><strong>Persönliche Betreuung</strong> durch 3 Fachärztinnen sowie 23 Pflege- und Servicekräfte</li>
<li><strong>Wohlfühlatmosphäre</strong> mit kostenlosem WLAN, Patienten-TV, Imbiss &amp; Getränken</li>
</ul>
</div>
<!-- Öffnungszeiten -->
<div class="section-card card-grow">
<div class="card-header">
<svg viewBox="0 0 24 24"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></svg>
Behandlungs- &amp; Sprechzeiten
</div>
<div class="sched-list">
<div class="sched-item">
<div class="sched-title">Dialyse (Mo, Mi, Fr):</div>
<div class="sched-hours">
<div><span class="badge-tag">1. Schicht</span> 07:00 &ndash; 13:00 Uhr</div>
<div><span class="badge-tag">2. Schicht</span> 13:00 &ndash; 18:00 Uhr</div>
<div><span class="badge-tag">3. Schicht</span> 14:30 &ndash; 20:00 Uhr</div>
</div>
</div>
<div class="sched-item">
<div class="sched-title">Dialyse (Di, Do, Sa):</div>
<div class="sched-hours"><span class="badge-tag">1. Schicht</span> 07:00 &ndash; 13:00 Uhr</div>
</div>
<div class="sched-item">
<div class="sched-title">Ambulanz (Mo, Mi, Fr):</div>
<div class="sched-hours">
<div>08:30 &ndash; 11:30 Uhr</div>
<div>14:00 &ndash; 17:00 Uhr (n. Vereinb.)</div>
</div>
</div>
<div class="sched-item">
<div class="sched-title">Ambulanz (Di, Do):</div>
<div class="sched-hours">08:30 &ndash; 12:00 Uhr</div>
</div>
</div>
</div>
</div>
<!-- RIGHT COLUMN: Standorte, Anfahrt & Praxis-Einblicke -->
<div class="col-stack">
<!-- Standorte -->
<div class="section-card">
<div class="card-header">
<svg viewBox="0 0 24 24"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5a2.5 2.5 0 0 1 0-5 2.5 2.5 0 0 1 0 5z"/></svg>
Unsere Standorte in Berlin
</div>
<div class="loc-block">
<div class="loc-head-row">
<div class="loc-head">Zentrumsdialyse (Hauptpraxis &amp; Ambulanz)</div>
<span class="loc-badge">16 Plätze</span>
</div>
<div class="loc-body">
<strong>Thorner Straße 1 &bull; 12623 Berlin-Mahlsdorf</strong>
</div>
</div>
<div class="loc-block" style="border-top: 1px dashed #e2e8f0; padding-top: 2.4mm;">
<div class="loc-head-row">
<div class="loc-head">Satellitendialyse Berlin-Marzahn</div>
<span class="loc-badge">18 Plätze</span>
</div>
<div class="loc-body">
<strong>Blumberger Damm 130 &bull; 12685 Berlin</strong><br>
Eingang: Pritzhagener Weg 21
</div>
</div>
</div>
<!-- Anfahrt & Skizze -->
<div class="section-card">
<div class="card-header">
<svg viewBox="0 0 24 24"><path d="M20.5 3l-.16.03L15 5.1 9 3 3.36 4.9c-.21.07-.36.25-.36.48V20.5c0 .28.22.5.5.5l.16-.03L9 18.9l6 2.1 5.64-1.9c.21-.07-.36-.25-.36-.48V3.5c0-.28-.22-.5-.5-.5zM15 19l-6-2.11V5l6 2.11V19z"/></svg>
Anfahrt &amp; Parken (Hauptpraxis)
</div>
<div class="anfahrt-flex">
<div class="anfahrt-text">
<p><strong>ÖPNV:</strong> S-Bahn <strong>S5</strong> oder Regionalbahn bis <strong>S-Bhf. Mahlsdorf</strong> (wenige Gehminuten).</p>
<p><strong>Pkw:</strong> Über <strong>B1/B5 (Alt-Mahlsdorf)</strong> &rarr; Hönower Str. &rarr; Waldowstr. &rarr; Thorner Str. 1.</p>
<p style="color: #0284c7; font-weight: 600;">&#x2713; Parkplätze direkt vor der Praxis.</p>
</div>
<img src="file:///d:/web-repo2/files/flyer_map.png" class="map-thumb" alt="Lageplan">
</div>
</div>
<!-- Praxis-Einblicke (2 Bilder) -->
<div class="section-card card-grow">
<div class="card-header">
<svg viewBox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
Einblicke in unsere Praxis
</div>
<div class="photo-grid">
<div class="photo-item" style="background: url('file:///d:/web-repo2/img/gallery/praxis1.jpg') 92% 65% / cover no-repeat;">
<div class="photo-caption">Praxisgebäude &bull; Thorner Str. 1</div>
</div>
<div class="photo-item" style="background: url('file:///d:/web-repo2/img/gallery/behandlung2.jpg') center center / cover no-repeat;">
<div class="photo-caption">Dialyseplatz mit Nikkiso-Technik</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bottom Action Callout -->
<div class="footer-callout">
<div class="callout-left">
<div class="callout-title">Kontakt &amp; Terminvereinbarung</div>
<div class="callout-sub">Wir beraten Sie gern persönlich</div>
</div>
<div class="callout-channels">
<div class="callout-item">
<small>Tel. Dialyse</small>
<div class="channel-val">030 / 566 24 84</div>
</div>
<div class="callout-item">
<small>Tel. Ambulanz</small>
<div class="channel-val">030 / 566 25 39</div>
</div>
<div class="callout-item">
<small>E-Mail</small>
<div class="channel-val">kontakt@dialyse-berlin.net</div>
</div>
</div>
</div>
<!-- Bottom Info Line -->
<div class="flyer-bottom-info">
<div>Dialysezentrum Berlin-Mahlsdorf &bull; Zentrum für Nephrologie und Dialyse &bull; Dr. med. Bianca Bischoff &amp; Dr. med. Juliane Hoffzimmer</div>
<div>Thorner Str. 1, 12623 Berlin &bull; Blumberger Damm 130, 12685 Berlin</div>
</div>
</div>
</body>
</html>
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 703 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 894 B

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 KiB

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 KiB

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 KiB

After

Width:  |  Height:  |  Size: 345 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 KiB

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 903 B

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 B

+9 -1
View File
@@ -6,8 +6,12 @@ require_once __DIR__ . '/lib/Session.php';
$session = new Session();
$lang = (isset($_GET['lang']) && $_GET['lang'] === 'en') ? 'en' : 'de';
Helper::setLang($lang);
$session->set('lang', $lang);
$loadFile = function($filename) {
global $config, $session;
global $config, $session, $lang;
ob_start();
include $filename;
@@ -34,6 +38,9 @@ switch ($action) {
case 'team':
$content = $loadFile('view/team.php');
break;
case 'ersttermin':
$content = $loadFile('view/first-appointment.php');
break;
case 'kontakt':
$content = $loadFile('view/contact.php');
break;
@@ -48,6 +55,7 @@ switch ($action) {
break;
default:
http_response_code(404);
$action = '404';
$content = $loadFile('view/error.php');
}
+71 -26
View File
@@ -1,35 +1,80 @@
function initialize() {
var geocoder = new google.maps.Geocoder();
/**
* Contact and Map Helpers
* Dialysezentrum Berlin-Mahlsdorf
*/
geocoder.geocode( { 'address': 'Thorner Straße 1,12623 Berlin'}, function(results, status) {
if(status == google.maps.GeocoderStatus.OK) {
var myOptions = {
zoom: 15,
center: results[0].geometry.location,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
navigationControl: true,
navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}
};
function sending(user, domain, tld) {
user = user || 'kontakt';
domain = domain || 'dialyse-berlin';
tld = tld || 'net';
window.location.href = 'mailto:' + user + '@' + domain + '.' + tld;
return true;
}
var map = new google.maps.Map(document.getElementById("googlemap"), myOptions);
function initObfuscatedEmails() {
// Dynamically reconstruct obfuscated email links and text for real visitors
$('.mail-obf').each(function() {
var $el = $(this);
var u = $el.attr('data-usr') || $el.data('usr');
var d = $el.attr('data-dom') || $el.data('dom');
var t = $el.attr('data-tld') || $el.data('tld');
if (u && d && t) {
var email = u + '@' + d + '.' + t;
$el.attr('href', 'mailto:' + email);
var $val = $el.find('.mail-val');
if ($val.length) {
$val.removeClass('c-rev').text(email);
}
}
});
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map
});
} else {
alert("Geocode was not successful for the following reason: " + status);
$('.mail-obf-text').each(function() {
var $el = $(this);
var u = $el.attr('data-usr') || $el.data('usr');
var d = $el.attr('data-dom') || $el.data('dom');
var t = $el.attr('data-tld') || $el.data('tld');
if (u && d && t) {
var email = u + '@' + d + '.' + t;
var $val = $el.find('.mail-val');
if ($val.length) {
$val.removeClass('c-rev').text(email);
} else {
$el.text(email);
}
}
});
}
initialize();
$(function() {
initObfuscatedEmails();
});
function sending() {
var text = "%6D%61%69%6C%74%6F:%6B%6F%6E%74%61%6B%74@%64%69%61%6C%79%73%65%2D%62%65%72%6C%69%6E%2E%6E%65%74";
function showMapLocation(loc) {
var isEn = (document.documentElement.lang || 'de').toLowerCase() === 'en';
var $frame = $('#mapFrame');
var $headerTitle = $('#mapHeaderTitle');
var $addrText = $('#mapAddressText');
var $extLink = $('#mapExternalLink');
var $btnMahlsdorf = $('#btnMapMahlsdorf');
var $btnSatellit = $('#btnMapSatellit');
location.href = decodeURI(text);
return true;
}
if (loc === 'satellit') {
$frame.attr('src', 'https://maps.google.com/maps?q=Blumberger+Damm+130,+12685+Berlin&t=&z=15&ie=UTF8&iwloc=&output=embed');
$frame.attr('title', isEn ? 'Map Satellite Dialysis Berlin-Marzahn' : 'Karte Satellitendialyse Berlin-Marzahn');
$headerTitle.html(isEn ? 'Location Map &bull; Berlin-Marzahn' : 'Standortkarte &bull; Berlin-Marzahn');
$addrText.text(isEn ? 'Blumberger Damm 130 (Entrance Pritzhagener Weg 21), 12685 Berlin' : 'Blumberger Damm 130 (Eingang Pritzhagener Weg 21), 12685 Berlin');
$extLink.attr('href', 'https://www.google.com/maps/place/Dialysezentrum+Berlin-Mahlsdorf+LC/@52.5428128,13.5716785,17z/data=!3m1!4b1!4m6!3m5!1s0x47a84991f9d5111b:0xda0b4785760166c5!8m2!3d52.5428128!4d13.5716785!16s%2Fg%2F1ts_5mmj');
$btnMahlsdorf.removeClass('btn-primary').addClass('btn-outline-primary').attr('aria-pressed', 'false');
$btnSatellit.removeClass('btn-outline-primary').addClass('btn-primary').attr('aria-pressed', 'true');
} else {
$frame.attr('src', 'https://maps.google.com/maps?q=Thorner+Stra%C3%9Fe+1,+12623+Berlin&t=&z=15&ie=UTF8&iwloc=&output=embed');
$frame.attr('title', isEn ? 'Map Center Dialysis Berlin-Mahlsdorf' : 'Karte Zentrumsdialyse Berlin-Mahlsdorf');
$headerTitle.html(isEn ? 'Location Map &bull; Berlin-Mahlsdorf' : 'Standortkarte &bull; Berlin-Mahlsdorf');
$addrText.text('Thorner Straße 1, 12623 Berlin');
$extLink.attr('href', 'https://www.google.com/maps/place/Dialysezentrum+Berlin-Mahlsdorf/@52.5078291,13.6092903,17z/data=!3m1!4b1!4m6!3m5!1s0x47a84991f9c57f7f:0xad4486f559442067!8m2!3d52.5078291!4d13.6092903!16s%2Fg%2F1tdqghgn');
$btnMahlsdorf.removeClass('btn-outline-primary').addClass('btn-primary').attr('aria-pressed', 'true');
$btnSatellit.removeClass('btn-primary').addClass('btn-outline-primary').attr('aria-pressed', 'false');
}
}
-38
View File
@@ -1,38 +0,0 @@
/*!
* jQuery JavaScript Library v3.4.1
* https://jquery.com/
*
* Includes Sizzle.js
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2019-05-01T21:04Z
*/
!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";function c(a,b,c){c=c||ia;var d,e,f=c.createElement("script");if(f.text=a,b)for(d in wa)(e=b[d]||b.getAttribute&&b.getAttribute(d))&&f.setAttribute(d,e);c.head.appendChild(f).parentNode.removeChild(f)}function d(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?oa[pa.call(a)]||"object":typeof a}function e(a){var b=!!a&&"length"in a&&a.length,c=d(a);return!ua(a)&&!va(a)&&("array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a)}function f(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}function g(a,b,c){return ua(b)?ya.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?ya.grep(a,function(a){return a===b!==c}):"string"!=typeof b?ya.grep(a,function(a){return na.call(b,a)>-1!==c}):ya.filter(b,a,c)}function h(a,b){for(;(a=a[b])&&1!==a.nodeType;);return a}function i(a){var b={};return ya.each(a.match(Ja)||[],function(a,c){b[c]=!0}),b}function j(a){return a}function k(a){throw a}function l(a,b,c,d){var e;try{a&&ua(e=a.promise)?e.call(a).done(b).fail(c):a&&ua(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}function m(){ia.removeEventListener("DOMContentLoaded",m),a.removeEventListener("load",m),ya.ready()}function n(a,b){return b.toUpperCase()}function o(a){return a.replace(Na,"ms-").replace(Oa,n)}function p(){this.expando=ya.expando+p.uid++}function q(a){return"true"===a||"false"!==a&&("null"===a?null:a===+a+""?+a:Sa.test(a)?JSON.parse(a):a)}function r(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Ta,"-$&").toLowerCase(),"string"==typeof(c=a.getAttribute(d))){try{c=q(c)}catch(a){}Ra.set(a,b,c)}else c=void 0;return c}function s(a,b,c,d){var e,f,g=20,h=d?function(){return d.cur()}:function(){return ya.css(a,b,"")},i=h(),j=c&&c[3]||(ya.cssNumber[b]?"":"px"),k=a.nodeType&&(ya.cssNumber[b]||"px"!==j&&+i)&&Va.exec(ya.css(a,b));if(k&&k[3]!==j){for(i/=2,j=j||k[3],k=+i||1;g--;)ya.style(a,b,k+j),(1-f)*(1-(f=h()/i||.5))<=0&&(g=0),k/=f;k*=2,ya.style(a,b,k+j),c=c||[]}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}function t(a){var b,c=a.ownerDocument,d=a.nodeName,e=ab[d];return e||(b=c.body.appendChild(c.createElement(d)),e=ya.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),ab[d]=e,e)}function u(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=Qa.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&$a(d)&&(e[f]=t(d))):"none"!==c&&(e[f]="none",Qa.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}function v(a,b){var c;return c=void 0!==a.getElementsByTagName?a.getElementsByTagName(b||"*"):void 0!==a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&f(a,b)?ya.merge([a],c):c}function w(a,b){for(var c=0,d=a.length;c<d;c++)Qa.set(a[c],"globalEval",!b||Qa.get(b[c],"globalEval"))}function x(a,b,c,e,f){for(var g,h,i,j,k,l,m=b.createDocumentFragment(),n=[],o=0,p=a.length;o<p;o++)if((g=a[o])||0===g)if("object"===d(g))ya.merge(n,g.nodeType?[g]:g);else if(fb.test(g)){for(h=h||m.appendChild(b.createElement("div")),i=(cb.exec(g)||["",""])[1].toLowerCase(),j=eb[i]||eb._default,h.innerHTML=j[1]+ya.htmlPrefilter(g)+j[2],l=j[0];l--;)h=h.lastChild;ya.merge(n,h.childNodes),h=m.firstChild,h.textContent=""}else n.push(b.createTextNode(g));for(m.textContent="",o=0;g=n[o++];)if(e&&ya.inArray(g,e)>-1)f&&f.push(g);else if(k=Ya(g),h=v(m.appendChild(g),"script"),k&&w(h),c)for(l=0;g=h[l++];)db.test(g.type||"")&&c.push(g);return m}function y(){return!0}function z(){return!1}function A(a,b){return a===B()==("focus"===b)}function B(){try{return ia.activeElement}catch(a){}}function C(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)C(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),!1===e)e=z;else if(!e)return a;return 1===f&&(g=e,e=function(a){return ya().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=ya.guid++)),a.each(function(){ya.event.add(this,b,e,d,c)})}function D(a,b,c){if(!c)return void(void 0===Qa.get(a,b)&&ya.event.add(a,b,y));Qa.set(a,b,!1),ya.event.add(a,b,{namespace:!1,handler:function(a){var d,e,f=Qa.get(this,b);if(1&a.isTrigger&&this[b]){if(f.length)(ya.event.special[b]||{}).delegateType&&a.stopPropagation();else if(f=ka.call(arguments),Qa.set(this,b,f),d=c(this,b),this[b](),e=Qa.get(this,b),f!==e||d?Qa.set(this,b,!1):e={},f!==e)return a.stopImmediatePropagation(),a.preventDefault(),e.value}else f.length&&(Qa.set(this,b,{value:ya.event.trigger(ya.extend(f[0],ya.Event.prototype),f.slice(1),this)}),a.stopImmediatePropagation())}})}function E(a,b){return f(a,"table"Line truncated
* Sizzle CSS Selector Engine v2.3.4
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://js.foundation/
*
* Date: 2019-04-08
*/
function(a){function b(a,b,c,d){var e,f,g,h,i,j,k,m=b&&b.ownerDocument,o=b?b.nodeType:9;if(c=c||[],"string"!=typeof a||!a||1!==o&&9!==o&&11!==o)return c;if(!d&&((b?b.ownerDocument||b:P)!==H&&G(b),b=b||H,J)){if(11!==o&&(i=ta.exec(a)))if(e=i[1]){if(9===o){if(!(g=b.getElementById(e)))return c;if(g.id===e)return c.push(g),c}else if(m&&(g=m.getElementById(e))&&N(b,g)&&g.id===e)return c.push(g),c}else{if(i[2])return _.apply(c,b.getElementsByTagName(a)),c;if((e=i[3])&&w.getElementsByClassName&&b.getElementsByClassName)return _.apply(c,b.getElementsByClassName(e)),c}if(w.qsa&&!V[a+" "]&&(!K||!K.test(a))&&(1!==o||"object"!==b.nodeName.toLowerCase())){if(k=a,m=b,1===o&&la.test(a)){for((h=b.getAttribute("id"))?h=h.replace(xa,ya):b.setAttribute("id",h=O),j=A(a),f=j.length;f--;)j[f]="#"+h+" "+n(j[f]);k=j.join(","),m=ua.test(a)&&l(b.parentNode)||b}try{return _.apply(c,m.querySelectorAll(k)),c}catch(b){V(a,!0)}finally{h===O&&b.removeAttribute("id")}}}return C(a.replace(ia,"$1"),b,c,d)}function c(){function a(c,d){return b.push(c+" ")>x.cacheLength&&delete a[b.shift()],a[c+" "]=d}var b=[];return a}function d(a){return a[O]=!0,a}function e(a){var b=H.createElement("fieldset");try{return!!a(b)}catch(a){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function f(a,b){for(var c=a.split("|"),d=c.length;d--;)x.attrHandle[c[d]]=b}function g(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)for(;c=c.nextSibling;)if(c===b)return-1;return a?1:-1}function h(a){return function(b){return"input"===b.nodeName.toLowerCase()&&b.type===a}}function i(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function j(a){return function(b){return"form"in b?b.parentNode&&!1===b.disabled?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&Aa(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function k(a){return d(function(b){return b=+b,d(function(c,d){for(var e,f=a([],c.length,b),g=f.length;g--;)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function l(a){return a&&void 0!==a.getElementsByTagName&&a}function m(){}function n(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function o(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=R++;return b.first?function(b,c,e){for(;b=b[d];)if(1===b.nodeType||g)return a(b,c,e);return!1}:function(b,c,i){var j,k,l,m=[Q,h];if(i){for(;b=b[d];)if((1===b.nodeType||g)&&a(b,c,i))return!0}else for(;b=b[d];)if(1===b.nodeType||g)if(l=b[O]||(b[O]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===Q&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}return!1}}function p(a){return a.length>1?function(b,c,d){for(var e=a.length;e--;)if(!a[e](b,c,d))return!1;return!0}:a[0]}function q(a,c,d){for(var e=0,f=c.length;e<f;e++)b(a,c[e],d);return d}function r(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function s(a,b,c,e,f,g){return e&&!e[O]&&(e=s(e)),f&&!f[O]&&(f=s(f,g)),d(function(d,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=d||q(b||"*",h.nodeType?[h]:h,[]),s=!a||!d&&b?p:r(p,m,a,h,i),t=c?f||(d?a:o||e)?[]:g:s;if(c&&c(s,t,h,i),e)for(j=r(t,n),e(j,[],h,i),k=j.length;k--;)(l=j[k])&&(t[n[k]]=!(s[n[k]]=l));if(d){if(f||a){if(f){for(j=[],k=t.length;k--;)(l=t[k])&&j.push(s[k]=l);f(null,t=[],j,i)}for(k=t.length;k--;)(l=t[k])&&(j=f?ba(d,l):m[k])>-1&&(d[j]=!(g[j]=l))}}else t=r(t===g?t.splice(o,t.length):t),f?f(null,g,t,i):_.apply(g,t)})}function t(a){for(var b,c,d,e=a.length,f=x.relative[a[0].type],g=f||x.relative[" "],h=f?1:0,i=o(function(a){return a===b},g,!0),j=o(function(a){return ba(b,a)>-1},g,!0),k=[function(a,c,d){var e=!f&&(d||c!==D)||((b=c).nodeType?i(a,c,d):j(a,c,d));return b=null,e}];h<e;h++)if(c=x.relative[a[h].type])k=[o(p(k),c)];else{if(c=x.filter[a[h].type].apply(null,a[h].matches),c[O]){for(d=++h;d<e&&!x.relative[a[d].type];d++);return s(h>1&&p(k),h>1&&n(a.slice(0,h-1).concat({value:" "===a[h-2].type?"*":""})).replace(ia,"$1"),c,h<d&&t(a.slice(h,d)),d<e&&t(a=a.slice(d)),d<e&&n(a))}k.push(c)}return p(k)}function u(a,c){var e=c.length>0,f=a.length>0,g=function(d,g,h,i,j){var k,l,m,n=0,o="0",p=d&&[],q=[],s=D,t=d||f&&x.find.TAG("*",j),u=Q+=null==s?1:Math.random()||.1,v=t.length;for(j&&(D=g===H||g||j);o!==v&&null!=(k=t[o]);o++){if(f&&k){for(l=0,g||k.ownerDocument===H||(G(k),h=!J);m=a[l++];)if(m(k,g||H,h)){i.push(k);break}j&&(Q=u)}e&&((k=!m&&k)&&n--,d&&p.push(k))}if(n+=o,e&&o!==n){for(l=0;m=c[l++];)m(p,q,g,h);if(d){if(n>0)for(;o--;)p[o]||q[o]||(q[o]=Z.call(i));q=r(q)}_.apply(i,q),j&&!d&&q.length>0&&n+c.length>1&&b.uniqueSort(i)}return j&&(Q=u,D=s),p};return e?d(g):g}var v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O="sizzle"+1*new Date,P=a.document,Q=0,R=0,S=c(),T=c(),U=c(),V=c(),W=function(a,b){return a===b&&(F=!0),0},X={}.hasOwnProperty,Y=[],Z=Y.pop,$=Y.push,_=Y.push,aa=Y.slice,ba=function(a,b){for(var c=0,d=a.length;c<Line truncated
* Lightbox v2.11.3
* by Lokesh Dhakar
*
* More info:
* http://lokeshdhakar.com/projects/lightbox2/
*
* Copyright Lokesh Dhakar
* Released under the MIT license
* https://github.com/lokesh/lightbox2/blob/master/LICENSE
*
* @preserve
*/
function(a,b){"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.lightbox=b(a.jQuery)}(this,function(a){function b(b){this.album=[],this.currentImageIndex=void 0,this.init(),this.options=a.extend({},this.constructor.defaults),this.option(b)}return b.defaults={albumLabel:"Image %1 of %2",alwaysShowNavOnTouchDevices:!1,fadeDuration:600,fitImagesInViewport:!0,imageFadeDuration:600,positionFromTop:50,resizeDuration:700,showImageNumberLabel:!0,wrapAround:!1,disableScrolling:!1,sanitizeTitle:!1},b.prototype.option=function(b){a.extend(this.options,b)},b.prototype.imageCountLabel=function(a,b){return this.options.albumLabel.replace(/%1/g,a).replace(/%2/g,b)},b.prototype.init=function(){var b=this;a(document).ready(function(){b.enable(),b.build()})},b.prototype.enable=function(){var b=this;a("body").on("click","a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]",function(c){return b.start(a(c.currentTarget)),!1})},b.prototype.build=function(){if(!(a("#lightbox").length>0)){var b=this;a('<div id="lightboxOverlay" tabindex="-1" class="lightboxOverlay"></div><div id="lightbox" tabindex="-1" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt=""/><div class="lb-nav"><a class="lb-prev" aria-label="Previous image" href="" ></a><a class="lb-next" aria-label="Next image" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div>').appendTo(a("body")),this.$lightbox=a("#lightbox"),this.$overlay=a("#lightboxOverlay"),this.$outerContainer=this.$lightbox.find(".lb-outerContainer"),this.$container=this.$lightbox.find(".lb-container"),this.$image=this.$lightbox.find(".lb-image"),this.$nav=this.$lightbox.find(".lb-nav"),this.containerPadding={top:parseInt(this.$container.css("padding-top"),10),right:parseInt(this.$container.css("padding-right"),10),bottom:parseInt(this.$container.css("padding-bottom"),10),left:parseInt(this.$container.css("padding-left"),10)},this.imageBorderWidth={top:parseInt(this.$image.css("border-top-width"),10),right:parseInt(this.$image.css("border-right-width"),10),bottom:parseInt(this.$image.css("border-bottom-width"),10),left:parseInt(this.$image.css("border-left-width"),10)},this.$overlay.hide().on("click",function(){return b.end(),!1}),this.$lightbox.hide().on("click",function(c){"lightbox"===a(c.target).attr("id")&&b.end()}),this.$outerContainer.on("click",function(c){return"lightbox"===a(c.target).attr("id")&&b.end(),!1}),this.$lightbox.find(".lb-prev").on("click",function(){return 0===b.currentImageIndex?b.changeImage(b.album.length-1):b.changeImage(b.currentImageIndex-1),!1}),this.$lightbox.find(".lb-next").on("click",function(){return b.currentImageIndex===b.album.length-1?b.changeImage(0):b.changeImage(b.currentImageIndex+1),!1}),this.$nav.on("mousedown",function(a){3===a.which&&(b.$nav.css("pointer-events","none"),b.$lightbox.one("contextmenu",function(){setTimeout(function(){this.$nav.css("pointer-events","auto")}.bind(b),0)}))}),this.$lightbox.find(".lb-loader, .lb-close").on("click",function(){return b.end(),!1})}},b.prototype.start=function(b){function c(a){d.album.push({alt:a.attr("data-alt"),link:a.attr("href"),title:a.attr("data-title")||a.attr("title")})}var d=this,e=a(window);e.on("resize",a.proxy(this.sizeOverlay,this)),this.sizeOverlay(),this.album=[];var f,g=0,h=b.attr("data-lightbox");if(h){f=a(b.prop("tagName")+'[data-lightbox="'+h+'"]');for(var i=0;i<f.length;i=++i)c(a(f[i])),f[i]===b[0]&&(g=i)}else if("lightbox"===b.attr("rel"))c(b);else{f=a(b.prop("tagName")+'[rel="'+b.attr("rel")+'"]');for(var j=0;j<f.length;j=++j)c(a(f[j])),f[j]===b[0]&&(g=j)}var k=e.scrollTop()+this.options.positionFromTop,l=e.scrollLeft();this.$lightbox.css({top:k+"px",left:l+"px"}).fadeIn(this.options.fadeDuration),this.options.disableScrolling&&a("body").addClass("lb-disable-scrolling"),this.changeImage(g)},b.prototype.changeImage=function(b){var c=this,d=this.album[b].link,e=d.split(".").slice(-1)[0],f=this.$lightbox.find(".lb-image");this.disableKeyboardNav(),this.$overlay.fadeIn(this.options.fadeDuration),a(".lb-loader").fadeIn("slow"),this.$lightbox.find(".lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption").hide(),this.$outerContainer.addClass("animating");var g=new Image;g.onload=function(){var h,i,j,k,l,m;f.attr({alt:c.album[b].alt,src:d}),a(g),f.width(g.width),f.height(g.height),m=a(window).width(),l=a(window).height(),k=m-c.containerPadding.left-c.containerPadding.right-c.imageBorderWidth.left-c.imageBorderWidth.right-20,j=l-c.containerPadding.top-c.containerPadding.bottom-c.imageBorderWidLine truncated
//# sourceMappingURL=lightbox-plus-jquery.min.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"sources":["lightbox-plus-jquery.js"],"names":["global","factory","module","exports","document","w","Error","window","this","noGlobal","DOMEval","code","node","doc","i","val","script","createElement","text","preservedScriptAttributes","getAttribute","setAttribute","head","appendChild","parentNode","removeChild","toType","obj","class2type","toString","call","isArrayLike","length","type","isFunction","isWindow","nodeName","elem","name","toLowerCase","winnow","elements","qualifier","not","jQuery","grep","nodeType","indexOf","filter","sibling","cur","dir","createOptions","options","object","each","match","rnothtmlwhite","_","flag","Identity","v","Thrower","ex","adoptValue","value","resolve","reject","noValue","method","promise","done","fail","then","apply","undefined","slice","completed","removeEventListener","ready","fcamelCase","all","letter","toUpperCase","camelCase","string","replace","rmsPrefix","rdashAlpha","Data","expando","uid","getData","data","rbrace","test","JSON","parse","dataAttr","key","rmultiDash","e","dataUser","set","adjustCSS","prop","valueParts","tween","adjusted","scale","maxIterations","currentValue","css","initial","unit","cssNumber","initialInUnit","rcssNum","exec","style","start","end","getDefaultDisplay","temp","ownerDocument","display","defaultDisplayMap","body","showHide","show","values","index","dataPriv","get","isHiddenWithinTree","getAll","context","tag","ret","getElementsByTagName","querySelectorAll","merge","setGlobalEval","elems","refElements","l","buildFragment","scripts","selection","ignored","tmp","wrap","attached","j","fragment","createDocumentFragment","nodes","rhtml","rtagName","wrapMap","_default","innerHTML","htmlPrefilter","lastChild","childNodes","firstChild","textContent","push","createTextNode","inArray","isAttached","rscriptType","returnTrue","returnFalse","expectSync","safeActiveElement","activeElement","err","on","types","selector","fn","one","origFn","event","off","arguments","guid","add","leverageNative","el","namespace","handler","notAsync","result","saved","isTrigger","special","delegateType","stopPropagation","stopImmediatePropagation","preventDefault","trigger","extend","Event","prototype","manipulationTarget","content","children","disableScript","restoreScript","removeAttribute","cloneCopyEvent","src","dest","pdataOld","pdataCur","udataOld","udataCur","events","hasData","access","handle","fixInput","rcheckableType","checked","defaultValue","domManip","collection","args","callback","concat","first","hasScripts","iNoClone","valueIsFunction","support","checkClone","rchecked","self","eq","html","map","clone","contains","_evalUrl","noModule","nonce","rcleanScript","remove","keepData","cleanData","curCSS","computed","width","minWidth","maxWidth","getStyles","getPropertyValue","pixelBoxStyles","rnumnonpx","rboxStyle","addGetHookIf","conditionFn","hookFn","vendorPropName","capName","cssPrefixes","emptyStyle","finalPropName","final","cssProps","vendorProps","setPositiveNumber","subtract","matches","Math","max","boxModelAdjustment","dimension","box","isBorderBox","styles","computedVal","extra","delta","cssExpand","ceil","getWidthOrHeight","boxSizingNeeded","boxSizingReliable","valueIsBorderBox","offsetProp","parseFloat","getClientRects","Tween","easing","init","schedule","inProgress","hidden","requestAnimationFrame","setTimeout","fx","interval","tick","createFxNow","fxNow","Date","now","genFx","includeWidth","which","attrs","height","opacity","createTween","animation","Animation","tweeners","defaultPrefilter","props","opts","toggle","hooks","oldfire","propTween","restoreDisplay","isBox","anim","orig","dataShow","queue","_queueHooks","unqueued","empty","fire","always","rfxtypes","isEmptyObject","overflow","overflowX","overflowY","propFilter","specialEasing","Array","isArray","cssHooks","expand","properties","stopped","prefilters","deferred","Deferred","currentTime","remaining","startTime","duration","percent","tweens","run","notifyWith","resolveWith","originalProperties","originalOptions","stop","gotoEnd","rejectWith","bind","progress","complete","timer","stripAndCollapse","join","getClass","classesToArray","buildParams","prefix","traditional","rbracket","addToPrefiltersOrTransports","structure","dataTypeExpression","func","dataType","dataTypes","unshift","inspectPrefiltersOrTransports","jqXHR","inspect","selected","inspected","prefilterOrFactory","dataTypeOrTransport","seekingTransport","transports","ajaxExtend","target","deep","flatOptions","ajaxSettings","ajaxHandleResponses","s","responses","ct","finalDataType","firstDataType","contents","shift","mimeType","getResponseHeader","converters","ajaxConvert","response","isSuccess","conv2","current","conv","prev","responseFields","dataFilter","split","throws","state","error","arr","getProto","Object","getPrototypeOf","hasOwn","hasOwnProperty","fnToString","ObjectFunctionString","version","rtrim","jquery","constructor","toArray","num","pushStack","prevObject","last","len","sort","splice","copy","copyIsArray"Line truncated
+15
View File
@@ -0,0 +1,15 @@
/*!
* Lightbox v2.11.5
* by Lokesh Dhakar
*
* More info:
* http://lokeshdhakar.com/projects/lightbox2/
*
* Copyright Lokesh Dhakar
* Released under the MIT license
* https://github.com/lokesh/lightbox2/blob/master/LICENSE
*
* @preserve
*/
!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.lightbox=b(a.jQuery)}(this,function(a){function b(b){this.album=[],this.currentImageIndex=void 0,this.init(),this.options=a.extend({},this.constructor.defaults),this.option(b)}return b.defaults={albumLabel:"Image %1 of %2",alwaysShowNavOnTouchDevices:!1,fadeDuration:600,fitImagesInViewport:!0,imageFadeDuration:600,positionFromTop:50,resizeDuration:700,showImageNumberLabel:!0,wrapAround:!1,disableScrolling:!1,sanitizeTitle:!1},b.prototype.option=function(b){a.extend(this.options,b)},b.prototype.imageCountLabel=function(a,b){return this.options.albumLabel.replace(/%1/g,a).replace(/%2/g,b)},b.prototype.init=function(){var b=this;a(document).ready(function(){b.enable(),b.build()})},b.prototype.enable=function(){var b=this;a("body").on("click","a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]",function(c){return b.start(a(c.currentTarget)),!1})},b.prototype.build=function(){if(!(a("#lightbox").length>0)){var b=this;a('<div id="lightboxOverlay" tabindex="-1" class="lightboxOverlay"></div><div id="lightbox" tabindex="-1" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt=""/><div class="lb-nav"><a class="lb-prev" role="button" tabindex="0" aria-label="Previous image" href="" ></a><a class="lb-next" role="button" tabindex="0" aria-label="Next image" href="" ></a></div><div class="lb-loader"><a class="lb-cancel" role="button" tabindex="0"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close" role="button" tabindex="0"></a></div></div></div></div>').appendTo(a("body")),this.$lightbox=a("#lightbox"),this.$overlay=a("#lightboxOverlay"),this.$outerContainer=this.$lightbox.find(".lb-outerContainer"),this.$container=this.$lightbox.find(".lb-container"),this.$image=this.$lightbox.find(".lb-image"),this.$nav=this.$lightbox.find(".lb-nav"),this.containerPadding={top:parseInt(this.$container.css("padding-top"),10),right:parseInt(this.$container.css("padding-right"),10),bottom:parseInt(this.$container.css("padding-bottom"),10),left:parseInt(this.$container.css("padding-left"),10)},this.imageBorderWidth={top:parseInt(this.$image.css("border-top-width"),10),right:parseInt(this.$image.css("border-right-width"),10),bottom:parseInt(this.$image.css("border-bottom-width"),10),left:parseInt(this.$image.css("border-left-width"),10)},this.$overlay.hide().on("click",function(){return b.end(),!1}),this.$lightbox.hide().on("click",function(c){"lightbox"===a(c.target).attr("id")&&b.end()}),this.$outerContainer.on("click",function(c){return"lightbox"===a(c.target).attr("id")&&b.end(),!1}),this.$lightbox.find(".lb-prev").on("click",function(){return 0===b.currentImageIndex?b.changeImage(b.album.length-1):b.changeImage(b.currentImageIndex-1),!1}),this.$lightbox.find(".lb-next").on("click",function(){return b.currentImageIndex===b.album.length-1?b.changeImage(0):b.changeImage(b.currentImageIndex+1),!1}),this.$nav.on("mousedown",function(a){3===a.which&&(b.$nav.css("pointer-events","none"),b.$lightbox.one("contextmenu",function(){setTimeout(function(){this.$nav.css("pointer-events","auto")}.bind(b),0)}))}),this.$lightbox.find(".lb-loader, .lb-close").on("click keyup",function(a){if("click"===a.type||"keyup"===a.type&&(13===a.which||32===a.which))return b.end(),!1})}},b.prototype.start=function(b){function c(a){d.album.push({alt:a.attr("data-alt"),link:a.attr("href"),title:a.attr("data-title")||a.attr("title")})}var d=this,e=a(window);e.on("resize",a.proxy(this.sizeOverlay,this)),this.sizeOverlay(),this.album=[];var f,g=0,h=b.attr("data-lightbox");if(h){f=a(b.prop("tagName")+'[data-lightbox="'+h+'"]');for(var i=0;i<f.length;i=++i)c(a(f[i])),f[i]===b[0]&&(g=i)}else if("lightbox"===b.attr("rel"))c(b);else{f=a(b.prop("tagName")+'[rel="'+b.attr("rel")+'"]');for(var j=0;j<f.length;j=++j)c(a(f[j])),f[j]===b[0]&&(g=j)}var k=e.scrollTop()+this.options.positionFromTop,l=e.scrollLeft();this.$lightbox.css({top:k+"px",left:l+"px"}).fadeIn(this.options.fadeDuration),this.options.disableScrolling&&a("body").addClass("lb-disable-scrolling"),this.changeImage(g)},b.prototype.changeImage=function(b){var c=this,d=this.album[b].link,e=d.split(".").slice(-1)[0],f=this.$lightbox.find(".lb-image");this.disableKeyboardNav(),this.$overlay.fadeIn(this.options.fadeDuration),a(".lb-loader").fadeIn("slow"),this.$lightbox.find(".lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption").hide(),this.$outerContainer.addClass("animating");var g=new Image;g.onload=function(){var h,i,j,k,l,m;f.attr({alt:c.album[b].alt,src:d}),a(g),f.width(g.width),f.height(g.height);var n=g.width/g.height;m=a(windLine truncated
//# sourceMappingURL=lightbox.min.map
+119 -2
View File
@@ -1,8 +1,38 @@
<?php
class Helper {
public static function parseHolidays($config) {
$text = $config['holidays']['text'];
private static $currentLang = 'de';
public static function setLang($lang) {
self::$currentLang = ($lang === 'en') ? 'en' : 'de';
}
public static function getLang() {
return self::$currentLang;
}
/**
* Build a language-aware internal URL.
* German (default): / or /leistungen.html
* English: /en/ or /en/leistungen.html
*/
public static function url($path = '/', $lang = null) {
$targetLang = $lang !== null ? $lang : self::$currentLang;
$cleanPath = '/' . ltrim($path, '/');
if ($cleanPath === '/index.php' || $cleanPath === '/main.html') {
$cleanPath = '/';
}
if ($targetLang === 'en') {
return $cleanPath === '/' ? '/en/' : '/en' . $cleanPath;
}
return $cleanPath;
}
public static function parseHolidays($config, $lang = null) {
$targetLang = $lang !== null ? $lang : self::$currentLang;
$text = ($targetLang === 'en' && !empty($config['holidays']['text_en']))
? $config['holidays']['text_en']
: $config['holidays']['text'];
$from = DateTime::createFromFormat('Y-m-d', $config['holidays']['from']);
$until = DateTime::createFromFormat('Y-m-d', $config['holidays']['until']);
$text = preg_replace('/\{\{from\}\}/', $from->format('d.m.Y'), $text);
@@ -36,4 +66,91 @@ class Helper {
return ($dialogShowFrom <= $today && $until > $today);
}
/**
* Generate an obfuscated email link to protect against automated spambot harvesting.
* Raw HTML contains no plain email address or mailto: link.
* Splitting into data attributes with CSS bidi-override fallback renders correctly visually,
* while JavaScript dynamically activates the live mailto link for real human visitors.
*
* @param string $email
* @param string|null $label Optional text/label before or wrapping the email
* @param array $attrs Optional HTML attributes (class, style, title, icon, etc.)
* @return string
*/
public static function obfuscateEmail($email, $label = null, $attrs = []) {
if (strpos($email, '@') === false) {
return htmlspecialchars($email);
}
list($user, $domainPart) = explode('@', $email, 2);
$lastDot = strrpos($domainPart, '.');
if ($lastDot !== false) {
$domain = substr($domainPart, 0, $lastDot);
$tld = substr($domainPart, $lastDot + 1);
} else {
$domain = $domainPart;
$tld = '';
}
$reversed = strrev($email);
$baseClass = isset($attrs['class']) ? $attrs['class'] . ' mail-obf' : 'mail-obf';
$title = isset($attrs['title']) ? ' title="' . htmlspecialchars($attrs['title']) . '"' : '';
$style = isset($attrs['style']) ? ' style="' . htmlspecialchars($attrs['style']) . '"' : '';
$id = isset($attrs['id']) ? ' id="' . htmlspecialchars($attrs['id']) . '"' : '';
$content = '';
if (isset($attrs['icon']) && !empty($attrs['icon'])) {
$content .= $attrs['icon'] . ' ';
}
if ($label !== null && $label !== '') {
$content .= htmlspecialchars($label) . ' ';
}
$content .= '<span class="mail-val c-rev">' . htmlspecialchars($reversed) . '</span>';
return sprintf(
'<a href="javascript:void(0);" class="%s" data-usr="%s" data-dom="%s" data-tld="%s"%s%s%s>%s</a>',
htmlspecialchars($baseClass),
htmlspecialchars($user),
htmlspecialchars($domain),
htmlspecialchars($tld),
$title,
$style,
$id,
$content
);
}
/**
* Obfuscate plain text email (non-link).
*/
public static function obfuscateEmailText($email, $attrs = []) {
if (strpos($email, '@') === false) {
return htmlspecialchars($email);
}
list($user, $domainPart) = explode('@', $email, 2);
$lastDot = strrpos($domainPart, '.');
if ($lastDot !== false) {
$domain = substr($domainPart, 0, $lastDot);
$tld = substr($domainPart, $lastDot + 1);
} else {
$domain = $domainPart;
$tld = '';
}
$reversed = strrev($email);
$baseClass = isset($attrs['class']) ? $attrs['class'] . ' mail-obf-text' : 'mail-obf-text';
$style = isset($attrs['style']) ? ' style="' . htmlspecialchars($attrs['style']) . '"' : '';
return sprintf(
'<span class="%s" data-usr="%s" data-dom="%s" data-tld="%s"%s><span class="mail-val c-rev">%s</span></span>',
htmlspecialchars($baseClass),
htmlspecialchars($user),
htmlspecialchars($domain),
htmlspecialchars($tld),
$style,
htmlspecialchars($reversed)
);
}
}
Loaded 100 of 213 files, more files were not shown because too many files have changed in this diff. Show more