This commit is contained in:
2026-03-31 14:22:09 +02:00
commit 01a0fdba47
5 changed files with 963 additions and 0 deletions

3
Dockerfile Normal file
View File

@@ -0,0 +1,3 @@
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
COPY logo.png /usr/share/nginx/html/logo.png

18
docker-compose.yml Normal file
View File

@@ -0,0 +1,18 @@
services:
meineordi-web:
build: .
container_name: meineordi-web
restart: unless-stopped
ports:
- "8080:80"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost/"]
interval: 30s
timeout: 5s
retries: 3
networks:
- nginx_internal_network
networks:
nginx_internal_network:
external: true

28
gitea-stack.yml Normal file
View File

@@ -0,0 +1,28 @@
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
USER_UID: "1000"
USER_GID: "1000"
GITEA__database__DB_TYPE: sqlite3
GITEA__server__DOMAIN: git.stranto.com
GITEA__server__ROOT_URL: http://git.stranto.com
GITEA__server__SSH_DOMAIN: git.stranto.com
volumes:
- gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
networks:
nginx_internal_network: {}
volumes:
gitea-data:
networks:
nginx_internal_network:
external: true

781
index.html Normal file
View File

@@ -0,0 +1,781 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Dr. med. Carina Kautsch Ärztin für Allgemeinmedizin in 1160 Wien. Öffnungszeiten, Leistungen und Kontakt." />
<title>Dr. Carina Kautsch Allgemeinmedizin Wien</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;0,700;1,400&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet" />
<style>
/* ─── Reset & Base ─────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
font-family: 'DM Sans', sans-serif;
font-size: 18px;
color: #222;
background: #fff;
line-height: 1.6;
}
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
/* ─── Variables ─────────────────────────────────────────── */
:root {
--red: #C8102E;
--red-dk: #a00d24;
--bg-alt: #f7f7f7;
--shadow: 0 6px 28px rgba(0,0,0,.14);
--radius: 12px;
}
/* ─── Animations ────────────────────────────────────────── */
@keyframes fadeUp {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes floatLogo {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-12px); }
}
/* ─── Header / Nav ──────────────────────────────────────── */
header {
position: sticky;
top: 0;
z-index: 100;
background: #fff;
border-bottom: 1px solid #eee;
box-shadow: 0 2px 12px rgba(0,0,0,.07);
}
nav {
max-width: 1100px;
margin: 0 auto;
padding: 0 24px;
height: 68px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.nav-logo img { height: 42px; width: auto; }
.nav-links {
display: flex;
align-items: center;
gap: 28px;
list-style: none;
}
.nav-links a {
font-size: 15px;
font-weight: 500;
color: #444;
transition: color .2s;
}
.nav-links a:hover { color: var(--red); }
.nav-phone {
display: inline-flex;
align-items: center;
gap: 8px;
background: var(--red);
color: #fff;
font-weight: 600;
font-size: 15px;
padding: 9px 18px;
border-radius: 8px;
white-space: nowrap;
transition: background .2s;
}
.nav-phone:hover { background: var(--red-dk); }
/* Hamburger */
.hamburger {
display: none;
flex-direction: column;
gap: 5px;
cursor: pointer;
background: none;
border: none;
padding: 4px;
}
.hamburger span {
display: block;
width: 26px;
height: 2px;
background: #333;
border-radius: 2px;
transition: all .3s;
}
.hamburger.open span:nth-child(1) { transform: rotate(45deg) translate(5px, 5px); }
.hamburger.open span:nth-child(2) { opacity: 0; }
.hamburger.open span:nth-child(3) { transform: rotate(-45deg) translate(5px, -5px); }
.mobile-menu {
display: none;
flex-direction: column;
background: #fff;
border-top: 1px solid #eee;
padding: 16px 24px 20px;
gap: 16px;
}
.mobile-menu.open { display: flex; }
.mobile-menu a {
font-size: 17px;
font-weight: 500;
color: #333;
padding: 6px 0;
border-bottom: 1px solid #f0f0f0;
}
.mobile-menu a:last-child { border-bottom: none; }
.mobile-menu .nav-phone {
margin-top: 4px;
justify-content: center;
}
/* ─── Section Helpers ───────────────────────────────────── */
section { padding: 72px 24px; }
section.alt { background: var(--bg-alt); }
.section-inner {
max-width: 1100px;
margin: 0 auto;
}
.section-title {
font-family: 'Cormorant Garamond', serif;
font-size: clamp(2rem, 4vw, 2.8rem);
font-weight: 700;
color: var(--red);
margin-bottom: 10px;
}
.section-sub {
font-size: 16px;
color: #666;
margin-bottom: 40px;
}
/* ─── Hero ──────────────────────────────────────────────── */
#hero {
padding: 80px 24px 60px;
position: relative;
overflow: hidden;
min-height: 520px;
}
.hero-watermark {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 480px;
opacity: .04;
pointer-events: none;
user-select: none;
}
.hero-inner {
max-width: 1100px;
margin: 0 auto;
display: flex;
align-items: center;
gap: 48px;
position: relative;
}
.hero-text {
flex: 1;
animation: fadeUp .7s ease both;
}
.hero-text h1 {
font-family: 'Cormorant Garamond', serif;
font-size: clamp(2.4rem, 5vw, 3.6rem);
font-weight: 700;
line-height: 1.15;
color: #111;
margin-bottom: 12px;
}
.hero-text h1 span { color: var(--red); }
.hero-text p {
font-size: 18px;
color: #555;
margin-bottom: 32px;
max-width: 480px;
}
.hero-cta {
display: flex;
gap: 14px;
flex-wrap: wrap;
}
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 13px 26px;
border-radius: 9px;
font-size: 16px;
font-weight: 600;
transition: all .2s;
cursor: pointer;
border: none;
}
.btn-primary { background: var(--red); color: #fff; }
.btn-primary:hover { background: var(--red-dk); transform: translateY(-2px); }
.btn-outline { background: transparent; color: var(--red); border: 2px solid var(--red); }
.btn-outline:hover { background: var(--red); color: #fff; transform: translateY(-2px); }
.hero-logo-wrap {
flex-shrink: 0;
animation: fadeUp .7s .2s ease both;
}
.hero-logo-wrap img {
width: 280px;
animation: floatLogo 4s ease-in-out infinite;
}
.hero-cards {
max-width: 1100px;
margin: 48px auto 0;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
animation: fadeUp .7s .35s ease both;
}
.hero-card {
background: var(--bg-alt);
border-radius: var(--radius);
padding: 20px 18px;
display: flex;
align-items: flex-start;
gap: 14px;
}
.hero-card-icon { font-size: 26px; line-height: 1; flex-shrink: 0; }
.hero-card-label {
font-size: 13px;
color: #888;
font-weight: 500;
text-transform: uppercase;
letter-spacing: .04em;
}
.hero-card-value {
font-size: 15px;
font-weight: 600;
color: #222;
margin-top: 2px;
}
/* ─── Öffnungszeiten ────────────────────────────────────── */
.hours-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
max-width: 600px;
}
.hour-card {
background: #fff;
border-radius: var(--radius);
box-shadow: var(--shadow);
border-left: 4px solid var(--red);
padding: 18px 22px;
display: flex;
justify-content: space-between;
align-items: center;
transition: transform .2s, box-shadow .2s;
}
.hour-card:hover { transform: translateY(-3px); box-shadow: 0 10px 36px rgba(0,0,0,.17); }
.hour-day { font-weight: 600; color: #333; }
.hour-time { color: var(--red); font-weight: 600; font-size: 15px; }
.hour-closed { color: #aaa; font-style: italic; }
/* ─── Schließzeiten ─────────────────────────────────────── */
#schliesszeiten .no-closures {
background: #fff;
border-radius: var(--radius);
padding: 28px 28px;
border: 2px dashed #ddd;
color: #888;
font-style: italic;
max-width: 480px;
}
.closure-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.closure-card {
background: #fff;
border-radius: var(--radius);
box-shadow: var(--shadow);
border-top: 4px solid var(--red);
padding: 22px 24px;
}
.closure-dates {
font-family: 'Cormorant Garamond', serif;
font-size: 1.4rem;
font-weight: 700;
color: var(--red);
margin-bottom: 4px;
}
.closure-reason {
font-weight: 600;
color: #333;
margin-bottom: 12px;
}
.closure-deputy-label {
font-size: 13px;
text-transform: uppercase;
letter-spacing: .04em;
color: #999;
margin-bottom: 6px;
}
.closure-deputy-name { font-weight: 600; color: #222; margin-bottom: 2px; }
.closure-deputy-detail { font-size: 15px; color: #555; line-height: 1.5; }
/* ─── Leistungen ────────────────────────────────────────── */
.leistungen-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.leistung-card {
background: #fff;
border-radius: var(--radius);
box-shadow: 0 3px 18px rgba(0,0,0,.08);
padding: 28px 24px;
transition: transform .2s, box-shadow .2s;
}
.leistung-card:hover { transform: translateY(-4px); box-shadow: 0 8px 30px rgba(0,0,0,.13); }
.leistung-icon { font-size: 2.2rem; margin-bottom: 14px; }
.leistung-title { font-weight: 700; font-size: 17px; margin-bottom: 8px; color: #222; }
.leistung-desc { font-size: 15px; color: #666; line-height: 1.55; }
/* ─── Aktuelles ─────────────────────────────────────────── */
.aktuelles-list {
display: flex;
flex-direction: column;
gap: 16px;
max-width: 780px;
}
.aktuell-item {
background: #fff;
border-radius: var(--radius);
box-shadow: 0 3px 18px rgba(0,0,0,.08);
padding: 22px 26px;
border-left: 4px solid var(--red);
}
.aktuell-title { font-weight: 700; color: #222; margin-bottom: 6px; font-size: 17px; }
.aktuell-body { font-size: 15px; color: #555; line-height: 1.6; }
/* ─── Kontakt ────────────────────────────────────────────── */
.kontakt-inner {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 48px;
align-items: start;
}
.kontakt-rows { display: flex; flex-direction: column; gap: 18px; }
.kontakt-row {
display: flex;
align-items: flex-start;
gap: 16px;
}
.kontakt-icon {
font-size: 22px;
flex-shrink: 0;
margin-top: 2px;
}
.kontakt-label { font-size: 13px; color: #999; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 2px; }
.kontakt-value { font-size: 17px; font-weight: 500; color: #222; }
.kontakt-value a:hover { color: var(--red); }
.map-wrap {
border-radius: var(--radius);
overflow: hidden;
box-shadow: var(--shadow);
}
.map-wrap iframe {
width: 100%;
height: 360px;
border: 0;
display: block;
}
/* ─── Footer ────────────────────────────────────────────── */
footer {
background: #1a1a1a;
color: #aaa;
padding: 36px 24px;
text-align: center;
}
.footer-inner {
max-width: 1100px;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
footer img { height: 38px; filter: brightness(0) invert(1); opacity: .7; }
footer p { font-size: 14px; }
footer a { color: #ccc; }
footer a:hover { color: #fff; }
/* ─── Responsive ────────────────────────────────────────── */
@media (max-width: 900px) {
.leistungen-grid { grid-template-columns: repeat(2, 1fr); }
.hero-cards { grid-template-columns: repeat(2, 1fr); }
.kontakt-inner { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
.nav-links, .nav-phone { display: none; }
.hamburger { display: flex; }
.hero-inner { flex-direction: column-reverse; text-align: center; }
.hero-logo-wrap img { width: 180px; margin: 0 auto; }
.hero-cta { justify-content: center; }
.hero-text p { margin: 0 auto 32px; }
.hours-grid { grid-template-columns: 1fr; }
}
@media (max-width: 540px) {
.hero-cards { grid-template-columns: 1fr; }
.leistungen-grid { grid-template-columns: 1fr; }
section { padding: 52px 16px; }
}
</style>
</head>
<body>
<!-- ═══════════════════════════════════════════════════════════
SCHLIESSZEITEN — edit only this array to manage holidays
═══════════════════════════════════════════════════════════ -->
<script>
const SCHLIESSZEITEN = [
{
dates: "30.3. 3.4.",
reason: "Karwoche",
deputy: "Dr. Irene Lachawitz",
deputyAddr: "1160 Wien, Neulerchenfelderstraße 14/6",
deputyPhone: "01 / 406 31 04",
deputyHours: "Mo & Mi 812 Uhr · Di & Do 1418 Uhr · Fr 1216 Uhr"
},
// Add more closures here:
// {
// dates: "DD.MM. DD.MM.",
// reason: "Urlaub",
// deputy: "Dr. Vorname Nachname",
// deputyAddr: "1160 Wien, Musterstraße 1",
// deputyPhone: "01 / 000 00 00",
// deputyHours: "MoFr 812 Uhr"
// },
];
</script>
<!-- ─── Header ───────────────────────────────────────────── -->
<header>
<nav>
<a class="nav-logo" href="#hero">
<img src="/logo.png" alt="meineOrdi Logo" />
</a>
<ul class="nav-links">
<li><a href="#oeffnungszeiten">Öffnungszeiten</a></li>
<li><a href="#leistungen">Leistungen</a></li>
<li><a href="#aktuelles">Aktuelles</a></li>
<li><a href="#kontakt">Kontakt</a></li>
</ul>
<a class="nav-phone" href="tel:+4314931773">
📞 +43 1 493 17 73
</a>
<button class="hamburger" id="hamburger" aria-label="Menü öffnen">
<span></span><span></span><span></span>
</button>
</nav>
<div class="mobile-menu" id="mobile-menu">
<a href="#oeffnungszeiten">Öffnungszeiten</a>
<a href="#leistungen">Leistungen</a>
<a href="#aktuelles">Aktuelles</a>
<a href="#kontakt">Kontakt</a>
<a class="nav-phone" href="tel:+4314931773">📞 +43 1 493 17 73</a>
</div>
</header>
<!-- ─── Hero ─────────────────────────────────────────────── -->
<section id="hero">
<img class="hero-watermark"
src="/logo.png"
alt="" aria-hidden="true" />
<div class="hero-inner">
<div class="hero-text">
<h1>Ihre Ärztin für<br><span>Allgemeinmedizin</span><br>in Wien</h1>
<p>Dr. med. Carina Kautsch persönliche, umfassende medizinische Betreuung in 1160 Wien.</p>
<div class="hero-cta">
<a class="btn btn-primary" href="tel:+4314931773">📞 Jetzt anrufen</a>
<a class="btn btn-outline" href="#oeffnungszeiten">Öffnungszeiten</a>
</div>
</div>
<div class="hero-logo-wrap">
<img src="/logo.png" alt="meineOrdi" />
</div>
</div>
<div class="hero-cards">
<div class="hero-card">
<div class="hero-card-icon">📍</div>
<div>
<div class="hero-card-label">Adresse</div>
<div class="hero-card-value">Pfenninggeldgasse 1B/3<br>A-1160 Wien</div>
</div>
</div>
<div class="hero-card">
<div class="hero-card-icon">📞</div>
<div>
<div class="hero-card-label">Telefon</div>
<div class="hero-card-value">+43 / 1 / 493 17 73</div>
</div>
</div>
<div class="hero-card">
<div class="hero-card-icon">✉️</div>
<div>
<div class="hero-card-label">E-Mail</div>
<div class="hero-card-value">info@meineordi.at</div>
</div>
</div>
<div class="hero-card">
<div class="hero-card-icon">🕐</div>
<div>
<div class="hero-card-label">Heute</div>
<div class="hero-card-value" id="todays-hours"></div>
</div>
</div>
</div>
</section>
<!-- ─── Öffnungszeiten ────────────────────────────────────── -->
<section id="oeffnungszeiten" class="alt">
<div class="section-inner">
<h2 class="section-title">Öffnungszeiten</h2>
<p class="section-sub">Bitte vereinbaren Sie telefonisch einen Termin.</p>
<div class="hours-grid">
<div class="hour-card">
<span class="hour-day">Montag</span>
<span class="hour-time">14:00 19:00</span>
</div>
<div class="hour-card">
<span class="hour-day">Dienstag</span>
<span class="hour-time">14:00 18:00</span>
</div>
<div class="hour-card">
<span class="hour-day">Mittwoch</span>
<span class="hour-time">07:30 11:30</span>
</div>
<div class="hour-card">
<span class="hour-day">Donnerstag</span>
<span class="hour-time">13:00 17:00</span>
</div>
<div class="hour-card">
<span class="hour-day">Freitag</span>
<span class="hour-time">09:00 12:00</span>
</div>
<div class="hour-card">
<span class="hour-day">Sa / So</span>
<span class="hour-closed">geschlossen</span>
</div>
</div>
</div>
</section>
<!-- ─── Schließzeiten ─────────────────────────────────────── -->
<section id="schliesszeiten">
<div class="section-inner">
<h2 class="section-title">Schließzeiten</h2>
<p class="section-sub">Vertretung während der Abwesenheit</p>
<div id="closure-container"></div>
</div>
</section>
<!-- ─── Leistungen ────────────────────────────────────────── -->
<section id="leistungen" class="alt">
<div class="section-inner">
<h2 class="section-title">Leistungen</h2>
<p class="section-sub">Umfassende allgemeinmedizinische Versorgung für die ganze Familie.</p>
<div class="leistungen-grid">
<div class="leistung-card">
<div class="leistung-icon">🩺</div>
<div class="leistung-title">Allgemeine Untersuchung</div>
<div class="leistung-desc">Vorsorgeuntersuchungen, Gesundencheck und allgemeine Diagnostik.</div>
</div>
<div class="leistung-card">
<div class="leistung-icon">💊</div>
<div class="leistung-title">Rezepte & Überweisungen</div>
<div class="leistung-desc">Ausstellung von Rezepten, Überweisungen und ärztlichen Attesten.</div>
</div>
<div class="leistung-card">
<div class="leistung-icon">🩸</div>
<div class="leistung-title">Laboruntersuchungen</div>
<div class="leistung-desc">Blutabnahme und Auswertung gängiger Laborparameter direkt in der Ordination.</div>
</div>
<div class="leistung-card">
<div class="leistung-icon">❤️</div>
<div class="leistung-title">Chronische Erkrankungen</div>
<div class="leistung-desc">Langzeitbetreuung bei Diabetes, Bluthochdruck, Schilddrüsenerkrankungen u. v. m.</div>
</div>
<div class="leistung-card">
<div class="leistung-icon">🌡️</div>
<div class="leistung-title">Akutbehandlung</div>
<div class="leistung-desc">Behandlung akuter Erkrankungen und Verletzungen, Krankmeldungen.</div>
</div>
<div class="leistung-card">
<div class="leistung-icon">💉</div>
<div class="leistung-title">Impfungen</div>
<div class="leistung-desc">Reise- und Standardimpfungen nach aktuellem Impfplan.</div>
</div>
</div>
</div>
</section>
<!-- ─── Aktuelles ─────────────────────────────────────────── -->
<section id="aktuelles">
<div class="section-inner">
<h2 class="section-title">Aktuelles</h2>
<p class="section-sub">Wichtige Hinweise aus der Ordination</p>
<div class="aktuelles-list">
<div class="aktuell-item">
<div class="aktuell-title">Rezeptbestellung</div>
<div class="aktuell-body">
Rezepte für Dauermedikamente können telefonisch oder per E-Mail bestellt werden.
Bitte geben Sie Name, Geburtsdatum und die gewünschten Medikamente an.
Die Abholung ist nach Vereinbarung möglich.
</div>
</div>
<div class="aktuell-item">
<div class="aktuell-title">Diabetiker-Bedarf</div>
<div class="aktuell-body">
Für die Verordnung von Diabetes-Hilfsmitteln (Teststreifen, Insulinnadeln etc.)
ist ein aktuelles Laborbefund erforderlich. Bitte rechtzeitig einen Termin vereinbaren.
</div>
</div>
<div class="aktuell-item">
<div class="aktuell-title">Krankmeldungen</div>
<div class="aktuell-body">
Krankmeldungen werden nur nach persönlicher Untersuchung ausgestellt.
Telefonische Krankschreibungen sind leider nicht möglich.
</div>
</div>
</div>
</div>
</section>
<!-- ─── Kontakt & Standort ────────────────────────────────── -->
<section id="kontakt" class="alt">
<div class="section-inner">
<h2 class="section-title">Kontakt & Standort</h2>
<p class="section-sub">Wir freuen uns auf Ihren Besuch.</p>
<div class="kontakt-inner">
<div class="kontakt-rows">
<div class="kontakt-row">
<div class="kontakt-icon">📍</div>
<div>
<div class="kontakt-label">Adresse</div>
<div class="kontakt-value">Pfenninggeldgasse 1B/3<br>A-1160 Wien</div>
</div>
</div>
<div class="kontakt-row">
<div class="kontakt-icon">📞</div>
<div>
<div class="kontakt-label">Telefon</div>
<div class="kontakt-value"><a href="tel:+4314931773">+43 / 1 / 493 17 73</a></div>
</div>
</div>
<div class="kontakt-row">
<div class="kontakt-icon">✉️</div>
<div>
<div class="kontakt-label">E-Mail</div>
<div class="kontakt-value"><a href="mailto:info@meineordi.at">info@meineordi.at</a></div>
</div>
</div>
<div class="kontakt-row">
<div class="kontakt-icon">👩‍⚕️</div>
<div>
<div class="kontakt-label">Ärztin</div>
<div class="kontakt-value">Dr. med. Carina Kautsch<br>Ärztin für Allgemeinmedizin</div>
</div>
</div>
</div>
<div class="map-wrap">
<iframe
src="https://www.openstreetmap.org/export/embed.html?bbox=16.325%2C48.200%2C16.340%2C48.210&layer=mapnik&marker=48.2052%2C16.3317"
title="Standort der Ordination"
loading="lazy"
allowfullscreen>
</iframe>
</div>
</div>
</div>
</section>
<!-- ─── Footer ────────────────────────────────────────────── -->
<footer>
<div class="footer-inner">
<img src="/logo.png" alt="meineOrdi" />
<p>
&copy; <span id="footer-year"></span> Dr. med. Carina Kautsch &nbsp;·&nbsp;
Ärztin für Allgemeinmedizin &nbsp;·&nbsp; 1160 Wien
</p>
<p style="font-size:13px;">
<a href="#impressum">Impressum</a> &nbsp;·&nbsp; <a href="#datenschutz">Datenschutz</a>
</p>
</div>
</footer>
<!-- ─── Scripts ───────────────────────────────────────────── -->
<script>
// Hamburger menu
const hamburger = document.getElementById('hamburger');
const mobileMenu = document.getElementById('mobile-menu');
hamburger.addEventListener('click', () => {
hamburger.classList.toggle('open');
mobileMenu.classList.toggle('open');
});
mobileMenu.querySelectorAll('a').forEach(a => {
a.addEventListener('click', () => {
hamburger.classList.remove('open');
mobileMenu.classList.remove('open');
});
});
// Footer year
document.getElementById('footer-year').textContent = new Date().getFullYear();
// Today's hours in hero card
(function() {
const hours = {
1: '14:00 19:00',
2: '14:00 18:00',
3: '07:30 11:30',
4: '13:00 17:00',
5: '09:00 12:00',
};
const day = new Date().getDay(); // 0=Sun, 1=Mon, …
const el = document.getElementById('todays-hours');
el.textContent = hours[day] || 'Geschlossen';
})();
// Render closure cards
function renderClosures() {
const container = document.getElementById('closure-container');
if (!SCHLIESSZEITEN || SCHLIESSZEITEN.length === 0) {
container.innerHTML = '<p class="no-closures">Derzeit keine Schließzeiten geplant.</p>';
return;
}
const cards = SCHLIESSZEITEN.map(c => `
<div class="closure-card">
<div class="closure-dates">${c.dates}</div>
<div class="closure-reason">${c.reason}</div>
<div class="closure-deputy-label">Vertretung</div>
<div class="closure-deputy-name">${c.deputy}</div>
<div class="closure-deputy-detail">
${c.deputyAddr}<br>
Tel: ${c.deputyPhone}<br>
${c.deputyHours}
</div>
</div>
`).join('');
container.innerHTML = `<div class="closure-cards">${cards}</div>`;
}
renderClosures();
</script>
</body>
</html>

View File

@@ -0,0 +1,133 @@
# Project Summary: meineordi.at Website Redesign
## Overview
Complete static HTML redesign of the medical practice website for **Dr. med. Carina Kautsch**, Ärztin für Allgemeinmedizin, replacing a Joomla 3 CMS with a single self-contained `index.html` file served via nginx in Docker.
**Live site (old):** https://meineordi.at/
**Logo URL:** https://meineordi.at/images/meineordi/logo.png
---
## Practice Information
| Field | Value |
|---|---|
| Doctor | Dr. med. Carina Kautsch |
| Specialty | Ärztin für Allgemeinmedizin |
| Address | Pfenninggeldgasse 1B/3, A-1160 Wien |
| Phone | +43 / 1 / 493 17 73 |
| Email | info@meineordi.at |
### Opening Hours
| Day | Hours |
|---|---|
| Montag | 14:00 19:00 |
| Dienstag | 14:00 18:00 |
| Mittwoch | 07:30 11:30 |
| Donnerstag | 13:00 17:00 |
| Freitag | 09:00 12:00 |
| Sa / So | geschlossen |
---
## Current Deliverable
### File: `index.html`
A single fully self-contained HTML file. No framework, no build step, no CMS.
**Sections (top to bottom):**
1. Sticky header with logo + nav links + phone button
2. Hero — logo image large on right, headline + CTA buttons left, 4 quick-info cards below
3. Öffnungszeiten — 2-column grid of hour boxes with shadows
4. Schließzeiten — dynamically rendered from JS array (see below)
5. Leistungen — 6-item service grid with emoji icons
6. Aktuelles — 3 notice items (prescriptions, diabetes supplies, sick notes)
7. Kontakt & Standort — contact rows + embedded OpenStreetMap iframe
8. Footer with logo
### Design Decisions
- **Fonts:** Cormorant Garamond (headings/serif) + DM Sans (body), loaded from Google Fonts
- **Primary color:** `#C8102E` (red from meineOrdi logo) — fixed, not auto-extracted
- **Background:** Pure white `#ffffff`, alt-sections `#f7f7f7`
- **Base font size:** 18px (deliberately larger for older patients)
- **Opening hours boxes:** white cards with strong drop shadow (`box-shadow: 0 6px 28px rgba(0,0,0,.14)`) and subtle red border, hover lift effect
- **Logo:** displayed in navbar (42px height), large in hero section (280px, float animation), subtle watermark behind hero, inverted white in footer
- **Map:** OpenStreetMap embed — no Google API key required
- **Mobile:** Fully responsive, hamburger menu below 768px, logo shifts above text on mobile
- **Animations:** CSS `fadeUp` on hero elements, `floatLogo` on hero logo
### Closure/Holiday Management (no CMS needed)
At the very top of `<body>` is a clearly commented JavaScript array:
```js
const SCHLIESSZEITEN = [
{
dates: "30.3. 3.4.",
reason: "Karwoche",
deputy: "Dr. Irene Lachawitz",
deputyAddr: "1160 Wien, Neulerchenfelderstraße 14/6",
deputyPhone: "01 / 406 31 04",
deputyHours: "Mo & Mi 812 Uhr · Di & Do 1418 Uhr · Fr 1216 Uhr"
},
// ... more entries
];
```
The `renderClosures()` function at the bottom of the script reads this array and builds the closure cards dynamically. Empty array → "Keine Schließzeiten" message shown automatically. This is the ONLY place that needs editing to manage holidays.
---
## Docker Setup
### Files
```
meineordi-docker.tar.gz
├── Dockerfile
├── index.html
└── docker-compose.yml
```
### Dockerfile
```dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
```
### docker-compose.yml
```yaml
services:
meineordi-web:
image: meineordi-web:latest
container_name: meineordi-web
restart: unless-stopped
ports:
- "8080:80"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost/"]
interval: 30s
timeout: 5s
retries: 3
```
### Build & Deploy
```bash
# Build image (must be done on the Docker host)
docker build -t meineordi-web:latest .
# Deploy via Portainer → Stacks → Add stack → paste docker-compose.yml
# OR run directly:
docker compose up -d
```
**Note:** The image must be built locally on the Docker host (or pushed to a registry) before Portainer can use it. The compose file references `meineordi-web:latest` as a pre-built local image, not a registry image.
---
## Possible Next Steps / Open Items
- **Reverse proxy integration** — The compose file currently exposes port 8080 directly. If the server uses Nginx Proxy Manager, Traefik, or Caddy, the `ports:` mapping should be replaced with a shared Docker network and proxy labels/config.
- **Registry/CI** — For easier updates, the image could be pushed to a private registry (e.g. Gitea with built-in registry, or Docker Hub) so Portainer can pull updates without SSH access.
- **HTTPS / domain** — Point `meineordi.at` DNS to the new server and configure SSL termination at the reverse proxy level.
- **Logo CORS** — The logo is loaded cross-origin from `meineordi.at`. Once the site is self-hosted, copy `logo.png` into the Docker image alongside `index.html` and reference it as `/logo.png` to avoid any cross-origin issues and eliminate the external dependency.
- **Content updates** — All content (hours, notices, services) is hardcoded in `index.html`. If more frequent edits are needed, consider a simple JSON config file mounted as a Docker volume, or a minimal admin UI built on top.
- **Imprint / Datenschutz** — Austrian law (ECG / DSGVO) requires an Impressum and Datenschutzerklärung. These pages don't exist yet.