Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4526a4f751 | ||
|
|
1448f058d8 | ||
|
|
0141fa752a | ||
|
|
2ba30e2d46 | ||
|
|
dba705f390 | ||
|
|
ab589c23fd | ||
|
|
4e4e4d1337 | ||
|
|
965cde3c41 | ||
|
|
af5177e8b1 | ||
|
|
1e33c525f1 | ||
|
|
01ea3bd07a | ||
|
|
eef49d7bb3 | ||
|
|
93d4d3bba3 | ||
|
|
bc1c5a62fb | ||
|
|
ac8468ca76 | ||
|
|
014422e0b6 | ||
|
|
02c92db1e5 | ||
|
|
92f2703788 | ||
|
|
6648523b04 | ||
|
|
de178b0ceb | ||
|
|
086db21318 | ||
|
|
167dc1dfb1 | ||
|
|
ab516628af | ||
|
|
33dd2fb757 | ||
|
|
8660ea6173 | ||
|
|
911b8864ca |
No files matched your search
@@ -0,0 +1,8 @@
|
||||
.git
|
||||
.gitea
|
||||
.gitignore
|
||||
.dockerignore
|
||||
Dockerfile
|
||||
files/flyer_template.html
|
||||
files/flyer_map.png
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 +0,0 @@
|
||||
{}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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! 🎉**
|
||||
@@ -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);
|
||||
@@ -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!'
|
||||
]
|
||||
];
|
||||
@@ -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));
|
||||
@@ -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}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 81 KiB |
@@ -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 & 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">„Die individuelle Dialyse im grünen Gürtel von Berlin“</div>
|
||||
<div class="motto-sub">2 Standorte • Feriendialyse • 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 & 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 & 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 & Medizintechnik
|
||||
</div>
|
||||
<ul class="check-list">
|
||||
<li><strong>Nephrologische Ambulanz:</strong> Diagnostik & Therapie von Nierenerkrankungen, Blutdruck- und Diabeteseinstellung</li>
|
||||
<li><strong>Funktionsdiagnostik:</strong> Sonographie (Nieren/Abdomen), EKG & 24-Std.-Blutdruckmessung</li>
|
||||
<li><strong>Dialyseverfahren (HD & Online-HDF):</strong> Kreislaufschonend mit Nikkiso <strong>Haemo-Master</strong> & <strong>Fresenius BCM</strong></li>
|
||||
<li><strong>Begleitende Betreuung:</strong> Transplantationsvorbereitung, Nachsorge & 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 & 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 & 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- & 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 – 13:00 Uhr</div>
|
||||
<div><span class="badge-tag">2. Schicht</span> 13:00 – 18:00 Uhr</div>
|
||||
<div><span class="badge-tag">3. Schicht</span> 14:30 – 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 – 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 – 11:30 Uhr</div>
|
||||
<div>14:00 – 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 – 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 & Ambulanz)</div>
|
||||
<span class="loc-badge">16 Plätze</span>
|
||||
</div>
|
||||
<div class="loc-body">
|
||||
<strong>Thorner Straße 1 • 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 • 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 & 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> → Hönower Str. → Waldowstr. → Thorner Str. 1.</p>
|
||||
<p style="color: #0284c7; font-weight: 600;">✓ 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 • 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 & 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 • Zentrum für Nephrologie und Dialyse • Dr. med. Bianca Bischoff & Dr. med. Juliane Hoffzimmer</div>
|
||||
<div>Thorner Str. 1, 12623 Berlin • Blumberger Damm 130, 12685 Berlin</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 547 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 703 KiB |
|
Before Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 894 B After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 368 KiB After Width: | Height: | Size: 194 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 282 KiB After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 329 KiB After Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 259 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 363 KiB After Width: | Height: | Size: 345 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 501 KiB After Width: | Height: | Size: 436 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 259 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 903 B |
|
Before Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 144 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 255 B |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 248 B |
|
Before Width: | Height: | Size: 155 B |
|
Before Width: | Height: | Size: 211 B |
|
Before Width: | Height: | Size: 237 B |
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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 • Berlin-Marzahn' : 'Standortkarte • 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 • Berlin-Mahlsdorf' : 'Standortkarte • 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');
|
||||
}
|
||||
}
|
||||
@@ -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 +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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||