Initial commit: baseline static site builder (templates, content, build.py)
This commit is contained in:
commit
d4a85a7787
|
|
@ -0,0 +1,23 @@
|
|||
# Python
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Virtual environment
|
||||
venv/
|
||||
.env
|
||||
|
||||
# Build outputs
|
||||
../builds/
|
||||
build/
|
||||
dist/
|
||||
|
||||
# Logs
|
||||
../logs/
|
||||
*.log
|
||||
|
||||
# Media binaries (optional)
|
||||
../media/
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
import os
|
||||
import datetime
|
||||
import shutil
|
||||
import yaml
|
||||
import markdown
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
CONTENT_PAGES_DIR = os.path.join(BASE_DIR, "content", "de", "pages")
|
||||
STATIC_SRC = os.path.join(BASE_DIR, "static")
|
||||
TEMPLATES_DIR = os.path.join(BASE_DIR, "templates")
|
||||
DIST_BASE = os.path.join(os.path.dirname(BASE_DIR), "builds", "preview")
|
||||
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(TEMPLATES_DIR),
|
||||
autoescape=select_autoescape(["html", "xml"]),
|
||||
)
|
||||
|
||||
def load_pages():
|
||||
pages = []
|
||||
for filename in os.listdir(CONTENT_PAGES_DIR):
|
||||
if not filename.endswith(".yaml"):
|
||||
continue
|
||||
path = os.path.join(CONTENT_PAGES_DIR, filename)
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
data = yaml.safe_load(f)
|
||||
pages.append(data)
|
||||
return pages
|
||||
|
||||
def render_page(page):
|
||||
template_name = "page.html" # all use same template for now
|
||||
template = env.get_template(template_name)
|
||||
# Process blocks and render markdown for prose
|
||||
blocks = []
|
||||
for b in page.get("blocks", []):
|
||||
block = dict(b) # shallow copy
|
||||
|
||||
# Markdown rendering for prose blocks: overwrite `content` with HTML
|
||||
if block.get("type") == "prose" and "content" in block:
|
||||
block["content"] = markdown.markdown(
|
||||
block["content"],
|
||||
extensions=["extra", "sane_lists"]
|
||||
)
|
||||
|
||||
# Markdown rendering for card_grid card texts
|
||||
if block.get("type") == "card_grid" and "cards" in block:
|
||||
new_cards = []
|
||||
for c in block["cards"]:
|
||||
card = dict(c)
|
||||
if "text" in card:
|
||||
card["text"] = markdown.markdown(
|
||||
card["text"],
|
||||
extensions=["extra", "sane_lists"]
|
||||
)
|
||||
new_cards.append(card)
|
||||
block["cards"] = new_cards
|
||||
|
||||
blocks.append(block)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
html = template.render(
|
||||
page=page, # NEW: pass whole page object
|
||||
title=page.get("title", ""),
|
||||
language=page.get("language", "de"),
|
||||
blocks=blocks,
|
||||
current_year=datetime.date.today().year,
|
||||
)
|
||||
return html
|
||||
|
||||
|
||||
def write_page(page, html):
|
||||
slug = page.get("slug", "index")
|
||||
# For now, every page goes to /slug/index.html
|
||||
out_dir = os.path.join(DIST_BASE, slug)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
out_path = os.path.join(out_dir, "index.html")
|
||||
with open(out_path, "w", encoding="utf-8") as f:
|
||||
f.write(html)
|
||||
print(f"Wrote {out_path}")
|
||||
|
||||
def copy_static():
|
||||
if not os.path.isdir(STATIC_SRC):
|
||||
print(f"No static dir at {STATIC_SRC}, skipping.")
|
||||
return
|
||||
static_dst = os.path.join(DIST_BASE, "static")
|
||||
if os.path.exists(static_dst):
|
||||
shutil.rmtree(static_dst)
|
||||
shutil.copytree(STATIC_SRC, static_dst)
|
||||
print(f"Copied static assets to {static_dst}")
|
||||
|
||||
def main():
|
||||
os.makedirs(DIST_BASE, exist_ok=True)
|
||||
|
||||
pages = load_pages()
|
||||
for page in pages:
|
||||
html = render_page(page)
|
||||
write_page(page, html)
|
||||
|
||||
copy_static()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
title: Photo Antiquaria
|
||||
slug: photo-antiquaria
|
||||
language: de
|
||||
|
||||
blocks:
|
||||
- type: full_width_image
|
||||
src: /static/images/photo-antiquaria-hero.jpg
|
||||
alt: Photo Antiquaria – ausgewählte Hefte
|
||||
caption: Die Mitglieder-Zeitschrift des Club Daguerre
|
||||
fade_speed: 1s
|
||||
vignette_strength: 0.8
|
||||
|
||||
- type: hero
|
||||
title: Photo Antiquaria
|
||||
subtitle: Die Mitglieder-Zeitschrift des Club Daguerre
|
||||
|
||||
- type: prose
|
||||
heading: Die Mitglieder-Zeitschrift des Club Daguerre
|
||||
content: |
|
||||
Ihre Mitgliedschaft im Club Daguerre umfasst auch den Bezug unserer
|
||||
Mitgliederzeitschrift **Photo Antiquaria**.
|
||||
|
||||
Clubmitglieder erhalten exklusiven digitalen Zugriff mit Schlagwortsuche
|
||||
auf sämtliche Ausgaben der *Photo Antiquaria* und auf **Club Daguerre aktuell**.
|
||||
So lassen sich fünf Jahrzehnte Club- und Fotogeschichte gezielt erschließen.
|
||||
|
||||
Unser Magazin erscheint im Regelfall viermal im Jahr in hochwertiger
|
||||
Druckqualität mit reich bebilderten Beiträgen zur Foto- und Filmgeschichte,
|
||||
ihren Verfahren und Geräten.
|
||||
|
||||
Die Redaktion – derzeit Wolfgang Kuttig und Dr. Heinz Kamp – sammelt,
|
||||
kuratiert und gestaltet die eingehenden Beiträge. Autorinnen und Autoren
|
||||
sind vor allem Clubmitglieder, aber auch weitere ausgewiesene Kenner der
|
||||
Materie und engagierte Sammlerinnen und Sammler, die ihr Wissen teilen möchten.
|
||||
|
||||
Die thematische Bandbreite reicht von bekannten und weniger bekannten
|
||||
Fotografen und ihren Arbeiten über Kameras und Projektoren bis hin zu
|
||||
Firmen- und Technikgeschichte, historischen Verfahren sowie Einblicken in
|
||||
das Clubleben. Pro Ausgabe stehen in der Regel deutlich über 60 Seiten zur
|
||||
Verfügung – eine kontinuierliche Plattform für Forschung, Dokumentation
|
||||
und Austausch innerhalb des Clubs.
|
||||
|
||||
Beiträge und Anfragen zur Photo Antiquaria richten Sie bitte an unsere
|
||||
Redaktion unter **redaktion@club-daguerre.de**.
|
||||
|
||||
- type: prose
|
||||
heading: Leseprobe
|
||||
content: |
|
||||
Einen typischen Beitrag aus der *Photo Antiquaria* stellen wir Ihnen als
|
||||
Leseprobe zur Verfügung: ein ausführlicher Artikel zur **Voigtländer
|
||||
Prominent**. Er vermittelt gut, wie tief und zugleich anschaulich unsere
|
||||
Autorinnen und Autoren in ihre Themen einsteigen.
|
||||
|
||||
Die Leseprobe wird im Rahmen der neuen Club-Daguerre-Webseite an
|
||||
geeigneter Stelle verlinkt – zum Beispiel über das *Sammelsurium* oder
|
||||
die Seite **Digitale Dienste**.
|
||||
|
||||
- type: card_grid
|
||||
heading: Bisher erschienen…
|
||||
columns: 2
|
||||
cards:
|
||||
- title: Photo Antiquaria 2025
|
||||
image: /static/images/pa-2025.jpg
|
||||
image_alt: Photo Antiquaria 2025
|
||||
text: |
|
||||
Schwerpunkte im Jahrgang 2025:
|
||||
|
||||
- 50 Jahre Digitalkameras – Rückblick und Ausblick
|
||||
- Die Erfolgsgeschichte von **ARRI**
|
||||
- Unser neues Ehrenmitglied **Jan Beenken**
|
||||
- Weitere Beiträge zur Kamera- und Industriegeschichte
|
||||
button_text: Zum Jahrgang 2025
|
||||
button_url: /jahrgang-2025/
|
||||
|
||||
- title: Photo Antiquaria 2024
|
||||
image: /static/images/pa-2024.jpg
|
||||
image_alt: Photo Antiquaria 2024
|
||||
text: |
|
||||
Schwerpunkte im Jahrgang 2024:
|
||||
|
||||
- 50 Jahre Club Daguerre – Jubiläumsausgabe der *Photo Antiquaria*
|
||||
- Das erste Foto in Deutschland und seine historische Einordnung
|
||||
- Ein Beitrag zur **Rolleiflex SL 26**
|
||||
- Weitere Artikel zur Kamera- und Fotogeschichte
|
||||
button_text: Zum Jahrgang 2024
|
||||
button_url: /jahrgang-2024/
|
||||
|
||||
- title: Photo Antiquaria 2023
|
||||
image: /static/images/pa-2023.jpg
|
||||
image_alt: Photo Antiquaria 2023
|
||||
text: |
|
||||
Schwerpunkte im Jahrgang 2023:
|
||||
|
||||
- Beitrag zu **Gottlieb Zulauf & Co.**, einem Schweizer Kamerahersteller
|
||||
- Artikel zur **Prontor-Wechselfassung**
|
||||
- Spurensuche zu **Barnacks Leica Nr. 105**
|
||||
- Externe Entfernungsmesser und ihr Einsatz in der Praxis
|
||||
button_text: Zum Jahrgang 2023
|
||||
button_url: /jahrgang-2023/
|
||||
|
||||
- title: Photo Antiquaria 2022
|
||||
image: /static/images/pa-2022.jpg
|
||||
image_alt: Photo Antiquaria 2022
|
||||
text: |
|
||||
Schwerpunkte im Jahrgang 2022:
|
||||
|
||||
- Beobachtungskameras und ihre Rolle in der Literatur
|
||||
- Die **King Regula III** mit Wechselobjektiven
|
||||
- Die **Bermpohl-Dreifarbenkamera** für Stereoaufnahmen
|
||||
- Restaurierung einer **Beira II** und weitere Praxisberichte
|
||||
button_text: Zum Jahrgang 2022
|
||||
button_url: /jahrgang-2022/
|
||||
|
||||
- title: Photo Antiquaria 2021
|
||||
image: /static/images/pa-2021.jpg
|
||||
image_alt: Photo Antiquaria 2021
|
||||
text: |
|
||||
Schwerpunkte im Jahrgang 2021:
|
||||
|
||||
- Die **Agfa Ambi Silette** und ihre Objektive
|
||||
- *25 Jahre APS* – Rückblick auf ein System
|
||||
- Die lang erwartete **Kodak Retina II**
|
||||
- **Momme Andresen** – Schöpfer einer neuen Entwicklergeneration
|
||||
button_text: Zum Jahrgang 2021
|
||||
button_url: /jahrgang-2021/
|
||||
|
||||
- title: Photo Antiquaria 2020
|
||||
image: /static/images/pa-2020.jpg
|
||||
image_alt: Photo Antiquaria 2020
|
||||
text: |
|
||||
Schwerpunkte im Jahrgang 2020:
|
||||
|
||||
- **Minor** und **Colibri** – Kleinstkameras aus München
|
||||
- Ein Blick auf die Filmfabrik **Agfa Wolfen**
|
||||
- Expeditionen des Forschers **Sven Hedin**
|
||||
- Die außergewöhnliche **Mentorett** und weitere Raritäten
|
||||
button_text: Zum Jahrgang 2020
|
||||
button_url: /jahrgang-2020/
|
||||
|
||||
|
|
@ -0,0 +1,572 @@
|
|||
/* === GLOBAL DARK THEME ===================================== */
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #000000;
|
||||
color: #e6e6e6;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
|
||||
"Helvetica Neue", Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #ffcc66;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
color: #ffe299;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* === GLOBAL SHELL FADE-IN ================================= */
|
||||
|
||||
.cd-header,
|
||||
.cd-main,
|
||||
.cd-footer {
|
||||
opacity: 0;
|
||||
transform: translateY(4px);
|
||||
transition:
|
||||
opacity 1.0s ease-out,
|
||||
transform 1.0s ease-out;
|
||||
}
|
||||
|
||||
body.cd-ready .cd-header,
|
||||
body.cd-ready .cd-main,
|
||||
body.cd-ready .cd-footer {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
|
||||
/* === HEADER (desktop) ===================================== */
|
||||
|
||||
.cd-header {
|
||||
background: #ffffff;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
position: relative;
|
||||
z-index: 500; /* ensure dropdown is above hero image */
|
||||
}
|
||||
|
||||
.cd-header-inner {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0.75rem 1.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.cd-logo {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.cd-logo-image {
|
||||
height: 72px;
|
||||
width: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.cd-site-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cd-nav { }
|
||||
|
||||
.cd-nav-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 1.8rem;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.cd-nav-item a {
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.cd-nav-item a:hover {
|
||||
color: #000;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cd-nav-active a {
|
||||
color: #000;
|
||||
border-bottom: 2px solid #000;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* === DESKTOP "Mehr" DROPDOWN =============================== */
|
||||
|
||||
.cd-nav-more {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.cd-nav-more-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
font: inherit;
|
||||
color: #444;
|
||||
cursor: default;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.cd-nav-more-label::after {
|
||||
content: "▾";
|
||||
font-size: 0.7em;
|
||||
}
|
||||
|
||||
.cd-nav-more-menu {
|
||||
position: absolute;
|
||||
top: 120%;
|
||||
right: 0;
|
||||
min-width: 260px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
|
||||
margin: 0;
|
||||
padding: 0.35rem 0;
|
||||
list-style: none;
|
||||
display: none;
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
.cd-nav-more-menu .cd-nav-item a {
|
||||
display: block;
|
||||
padding: 0.35rem 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
color: #333;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cd-nav-more-menu .cd-nav-item a:hover {
|
||||
background: #f4f4f4;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Show dropdown on hover (desktop) */
|
||||
.cd-nav-more:hover .cd-nav-more-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Hamburger (desktop hidden) */
|
||||
|
||||
.cd-nav-toggle {
|
||||
display: none;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
.cd-nav-toggle-bar {
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
margin: 3px 0;
|
||||
background: #333;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
/* === MAIN LAYOUT ========================================== */
|
||||
|
||||
.cd-main {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 2.5rem 1.25rem 3.5rem;
|
||||
}
|
||||
|
||||
.cd-main h1,
|
||||
.cd-main h2,
|
||||
.cd-main h3,
|
||||
.cd-main h4 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.cd-main p {
|
||||
color: #e0e0e0;
|
||||
margin: 0 0 0.9rem;
|
||||
}
|
||||
|
||||
/* === FOOTER =============================================== */
|
||||
|
||||
.cd-footer {
|
||||
border-top: 1px solid #222;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.cd-footer-inner {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 1rem 1.25rem;
|
||||
font-size: 0.85rem;
|
||||
color: #aaaaaa;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.cd-footer-links {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.cd-footer-inner a {
|
||||
color: #ffcc66;
|
||||
}
|
||||
.cd-footer-inner a:hover {
|
||||
color: #ffe299;
|
||||
}
|
||||
|
||||
/* Shared link transitions */
|
||||
.cd-nav-item a,
|
||||
.cd-footer-inner a {
|
||||
transition:
|
||||
color 0.18s ease-out,
|
||||
border-color 0.18s ease-out,
|
||||
background-color 0.18s ease-out;
|
||||
}
|
||||
|
||||
/* === BLOCKS BASE ========================================== */
|
||||
|
||||
.block {
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
/* Hero block (title + subtitle) */
|
||||
|
||||
.block-hero {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-text h1 {
|
||||
margin: 0 0 0.75rem;
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
margin: 0;
|
||||
font-size: 1.05rem;
|
||||
color: #d0d0d0;
|
||||
}
|
||||
|
||||
/* Prose */
|
||||
|
||||
.block-prose h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.75rem;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.prose-content p {
|
||||
margin: 0 0 0.9rem;
|
||||
}
|
||||
|
||||
/* Prose lists */
|
||||
|
||||
.prose-content ul,
|
||||
.prose-content ol {
|
||||
margin: 0 0 0.9rem 0;
|
||||
padding-left: 1.3rem;
|
||||
}
|
||||
|
||||
.prose-content li {
|
||||
margin: 0.1rem 0 0.1rem 0;
|
||||
}
|
||||
|
||||
/* === FULL-WIDTH IMAGE BLOCK (Option D) ==================== */
|
||||
|
||||
.block-full-width-image {
|
||||
position: relative;
|
||||
margin-bottom: 2.7rem;
|
||||
overflow: hidden; /* keep vignette & shadow inside block */
|
||||
}
|
||||
|
||||
.block-full-width-image .cd-figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Image itself: inset, rounded, border, shadow, base state */
|
||||
.block-full-width-image img {
|
||||
max-width: 860px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
border-radius: 14px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
box-shadow: 0 0 40px rgba(0, 0, 0, 0.55);
|
||||
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
transition:
|
||||
opacity var(--fade-speed, 0.8s) ease,
|
||||
transform var(--fade-speed, 0.8s) ease;
|
||||
}
|
||||
|
||||
/* Vignette overlay */
|
||||
.block-full-width-image::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 0;
|
||||
transform: translateX(-50%);
|
||||
width: 100%;
|
||||
max-width: 860px;
|
||||
height: 100%;
|
||||
border-radius: 14px;
|
||||
pointer-events: none;
|
||||
box-shadow:
|
||||
inset 0 0 calc(60px * var(--vignette-strength, 0.75))
|
||||
rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
/* Caption */
|
||||
.block-full-width-image figcaption {
|
||||
text-align: center;
|
||||
margin-top: 0.55rem;
|
||||
color: #aaaaaa;
|
||||
font-size: 0.9rem;
|
||||
font-style: italic;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
/* Fade-in activated */
|
||||
.block-full-width-image.cd-visible img {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* === CARD GRID ============================================ */
|
||||
|
||||
.block-card-grid h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
display: grid;
|
||||
gap: 1.5rem;
|
||||
align-items: stretch; /* equal-height rows */
|
||||
}
|
||||
|
||||
.card-grid-cols-2 {
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
}
|
||||
.card-grid-cols-3 {
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
}
|
||||
.card-grid-cols-4 {
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
}
|
||||
|
||||
/* Card shell */
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: #111111;
|
||||
border: 1px solid #333333;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 0 24px rgba(0, 0, 0, 0.45);
|
||||
transition:
|
||||
box-shadow 0.22s ease-out,
|
||||
transform 0.18s ease-out,
|
||||
border-color 0.18s ease-out;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow:
|
||||
0 8px 28px rgba(0, 0, 0, 0.6),
|
||||
0 0 12px rgba(255, 204, 102, 0.15);
|
||||
border-color: #555555;
|
||||
}
|
||||
|
||||
/* Card image: uniform heights */
|
||||
|
||||
.card-image {
|
||||
height: 260px;
|
||||
overflow: hidden;
|
||||
background: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.card-image img {
|
||||
height: 100%;
|
||||
width: auto;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Card body & text */
|
||||
|
||||
.card-body {
|
||||
padding: 1rem 1.1rem 1.1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
margin: 0 0 0.5rem;
|
||||
font-size: 1.05rem;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
font-size: 0.95rem;
|
||||
color: #d2d2d2;
|
||||
}
|
||||
|
||||
/* Lists inside cards */
|
||||
|
||||
.card-text ul,
|
||||
.card-text ol {
|
||||
margin: 0.5rem 0 0.9rem 0;
|
||||
padding-left: 1.4rem;
|
||||
}
|
||||
|
||||
.card-text li {
|
||||
margin: 0.25rem 0;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.card-text ul li::marker {
|
||||
color: #ffcc66;
|
||||
font-size: 1.05em;
|
||||
}
|
||||
|
||||
/* Card actions: button at bottom, centered */
|
||||
|
||||
.card-actions {
|
||||
margin-top: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Frosted-glass button */
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 0.45rem 1.2rem;
|
||||
border-radius: 24px;
|
||||
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
backdrop-filter: blur(4px);
|
||||
|
||||
color: #ffffff;
|
||||
border: 1px solid rgba(255, 255, 255, 0.28);
|
||||
text-decoration: none;
|
||||
font-size: 0.92rem;
|
||||
|
||||
transition:
|
||||
background-color 0.22s ease,
|
||||
border-color 0.22s ease,
|
||||
box-shadow 0.25s ease,
|
||||
transform 0.18s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background: rgba(255, 255, 255, 0.22);
|
||||
border-color: rgba(255, 255, 255, 0.45);
|
||||
box-shadow:
|
||||
0 0 18px rgba(255, 255, 255, 0.25),
|
||||
0 0 8px rgba(255, 204, 102, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Optional subtle divider under big grids */
|
||||
.card-grid::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255,255,255,0.05) 0%,
|
||||
rgba(255,255,255,0.18) 50%,
|
||||
rgba(255,255,255,0.05) 100%
|
||||
);
|
||||
margin: 2.5rem 0;
|
||||
}
|
||||
|
||||
/* === MOBILE HEADER / NAV ================================= */
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.cd-header-inner {
|
||||
padding: 0.5rem 0.9rem;
|
||||
}
|
||||
|
||||
.cd-logo-image {
|
||||
height: 54px;
|
||||
}
|
||||
|
||||
.cd-nav-toggle {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cd-nav {
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #ffffff;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
transform: translateY(-110%);
|
||||
transition: transform 0.18s ease-out;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
body.cd-nav-open .cd-nav {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.cd-nav-list {
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
padding: 0.5rem 1rem 0.75rem;
|
||||
}
|
||||
|
||||
.cd-nav-item a {
|
||||
display: block;
|
||||
padding: 0.3rem 0;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
/* Mobile: Mehr becomes inline list items */
|
||||
|
||||
.cd-nav-more {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.cd-nav-more-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cd-nav-more-menu {
|
||||
position: static;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
display: block !important;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cd-nav-more-menu .cd-nav-item a {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
.css-9s1hn{background-color:#FFFFFF;}.css-1c375l0 .hugeTitleFontSize h1:not(.customScale){font-size:64px !important;}.css-1c375l0 h1:not(.customScale){font-size:48px !important;}.css-1c375l0 h2:not(.customScale), .css-1c375l0 .smallTitleFontSize h1, [data-css-1c375l0] .smallTitleFontSize h1, .css-1c375l0 h1.smallTitleFontSize, [data-css-1c375l0] h1.smallTitleFontSize{font-size:36px !important;}.css-1c375l0 h3:not(.customScale), .css-1c375l0 h4:not(.customScale), [data-css-1c375l0] h4:not(.customScale), .css-1c375l0 h5:not(.customScale), [data-css-1c375l0] h5:not(.customScale), .css-1c375l0 h6:not(.customScale), [data-css-1c375l0] h6:not(.customScale){font-size:24px !important;}.css-1c375l0 li:not(.customScale){font-size:18px !important;}.css-1c375l0 p:not(.customScale){font-size:18px !important;}.css-1c375l0 .customScale p, .css-1c375l0 .customScale h1, [data-css-1c375l0] .customScale h1, .css-1c375l0 .customScale h2, [data-css-1c375l0] .customScale h2, .css-1c375l0 .customScale h3, [data-css-1c375l0] .customScale h3, .css-1c375l0 .customScale h4, [data-css-1c375l0] .customScale h4, .css-1c375l0 .customScale h5, [data-css-1c375l0] .customScale h5, .css-1c375l0 .customScale h6, [data-css-1c375l0] .customScale h6{font-size:inherit !important;}@media only screen and (max-width: 1280px){.css-1c375l0 h1:not(.customScale){font-size:36px !important;}.css-1c375l0 h2:not(.customScale), .css-1c375l0 .smallTitleFontSize h1, [data-css-1c375l0] .smallTitleFontSize h1, .css-1c375l0 h1.smallTitleFontSize, [data-css-1c375l0] h1.smallTitleFontSize{font-size:24px !important;}.css-1c375l0 h3:not(.customScale), .css-1c375l0 h4:not(.customScale), [data-css-1c375l0] h4:not(.customScale), .css-1c375l0 h5:not(.customScale), [data-css-1c375l0] h5:not(.customScale), .css-1c375l0 h6:not(.customScale), [data-css-1c375l0] h6:not(.customScale){font-size:18px !important;}.css-1c375l0 p:not(.customScale){font-size:16px !important;}.css-1c375l0 li:not(.customScale){font-size:16px !important;}.css-1c375l0 .customScale p, .css-1c375l0 .customScale li, [data-css-1c375l0] .customScale li, .css-1c375l0 .customScale h1, [data-css-1c375l0] .customScale h1, .css-1c375l0 .customScale h2, [data-css-1c375l0] .customScale h2, .css-1c375l0 .customScale h3, [data-css-1c375l0] .customScale h3, .css-1c375l0 .customScale h4, [data-css-1c375l0] .customScale h4, .css-1c375l0 .customScale h5, [data-css-1c375l0] .customScale h5, .css-1c375l0 .customScale h6, [data-css-1c375l0] .customScale h6{font-size:inherit !important;}}@media only screen and (max-width: 800px){.css-1c375l0 .hugeTitleFontSize h1:not(.customScale){font-size:40px !important;}}.css-q2nxa6{background-color:#000000;}.css-1sxfiya{min-height:calc(100vh - 80px);}.css-1xo07ii{background-color:rgba(0, 0, 0, 0.55);}.css-xi3bv8{background-color:#FFFFFF !important;border-radius:5px !important;}.css-1wta0f{border-color:transparent !important;}.css-gpurr0{color:#fff;transition:all .2s ease-in;-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 180 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
|
|
@ -0,0 +1,159 @@
|
|||
<!doctype html>
|
||||
<html lang="{{ page.language or 'de' }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{ page.title }} | Club Daguerre e.V.</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- Optional: legacy Jimdo theme CSS (can be removed later if desired) -->
|
||||
<link rel="stylesheet" href="/static/dg_theme_base.css">
|
||||
<link rel="stylesheet" href="/static/dg_theme_ab12c3.css">
|
||||
|
||||
<!-- Our main theme -->
|
||||
<link rel="stylesheet" href="/static/css/site.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- HEADER -->
|
||||
<header class="cd-header">
|
||||
<div class="cd-header-inner">
|
||||
<a href="/" class="cd-logo">
|
||||
<img src="/static/logo.png" alt="Club Daguerre" class="cd-logo-image">
|
||||
<span class="cd-site-title">CLUB DAGUERRE E.V.</span>
|
||||
</a>
|
||||
|
||||
<button class="cd-nav-toggle" type="button"
|
||||
aria-expanded="false"
|
||||
aria-controls="cd-nav">
|
||||
<span class="cd-nav-toggle-bar"></span>
|
||||
<span class="cd-nav-toggle-bar"></span>
|
||||
<span class="cd-nav-toggle-bar"></span>
|
||||
</button>
|
||||
|
||||
<nav class="cd-nav" id="cd-nav">
|
||||
<ul class="cd-nav-list">
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'index' else '' }}">
|
||||
<a href="/">Home</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'der-club' else '' }}">
|
||||
<a href="/der-club/">Der Club</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'photo-antiquaria' else '' }}">
|
||||
<a href="/photo-antiquaria/">Photo Antiquaria</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'regionaltreffen' else '' }}">
|
||||
<a href="/regionaltreffen/">Regionaltreffen</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'jahrestreffen' else '' }}">
|
||||
<a href="/jahrestreffen/">Jahrestreffen</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'sammlerwissen-kompakt' else '' }}">
|
||||
<a href="/sammlerwissen-kompakt/">Sammlerwissen kompakt</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'mitglied-werden' else '' }}">
|
||||
<a href="/mitglied-werden/">Mitglied werden</a>
|
||||
</li>
|
||||
|
||||
<!-- DESKTOP: Mehr as dropdown. MOBILE: items appear inline. -->
|
||||
<li class="cd-nav-item cd-nav-more">
|
||||
<span class="cd-nav-more-label">Mehr</span>
|
||||
<ul class="cd-nav-more-menu">
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'bewahren' else '' }}">
|
||||
<a href="/bewahren/">Bewahren</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'workshops' else '' }}">
|
||||
<a href="/workshops/">Workshops</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'nachrichten' else '' }}">
|
||||
<a href="/nachrichten/">Nachrichten</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'sammelsurium' else '' }}">
|
||||
<a href="/sammelsurium/">Sammelsurium</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'club-intern' else '' }}">
|
||||
<a href="/club-intern/">Club intern</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'digitale-dienste' else '' }}">
|
||||
<a href="/digitale-dienste/">Digitale Dienste</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'ehrenvorsitzender-ehrenmitglieder' else '' }}">
|
||||
<a href="/ehrenvorsitzender-ehrenmitglieder/">
|
||||
Ehrenvorsitzender / Ehrenmitglieder
|
||||
</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'english-language-summary' else '' }}">
|
||||
<a href="/english-language-summary/">English Language Summary</a>
|
||||
</li>
|
||||
<li class="cd-nav-item {{ 'cd-nav-active' if page.slug == 'kontakte' else '' }}">
|
||||
<a href="/kontakte/">Kontakt</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<main class="cd-main">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<footer class="cd-footer">
|
||||
<div class="cd-footer-inner">
|
||||
<div>© {{ current_year }} Club Daguerre e.V.</div>
|
||||
<div class="cd-footer-links">
|
||||
<a href="/impressum/">Impressum</a>
|
||||
<a href="/datenschutz/">Datenschutz</a>
|
||||
<a href="/cookie-einstellungen/">Cookie-Einstellungen</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
function init() {
|
||||
// Mark shell as ready for fade-in (slight delay so initial state is applied)
|
||||
requestAnimationFrame(function () {
|
||||
document.body.classList.add('cd-ready');
|
||||
});
|
||||
|
||||
// Mobile nav toggle
|
||||
var btn = document.querySelector('.cd-nav-toggle');
|
||||
if (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
var isOpen = document.body.classList.toggle('cd-nav-open');
|
||||
btn.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
// Hero image fade-in
|
||||
var hero = document.querySelector('.block-full-width-image');
|
||||
if (hero && 'IntersectionObserver' in window) {
|
||||
var ob = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (entry.isIntersecting) {
|
||||
hero.classList.add('cd-visible');
|
||||
ob.disconnect();
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.3 });
|
||||
ob.observe(hero);
|
||||
} else if (hero) {
|
||||
hero.classList.add('cd-visible');
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<section class="block block-card-grid">
|
||||
{% if block.heading %}
|
||||
<h2>{{ block.heading }}</h2>
|
||||
{% endif %}
|
||||
|
||||
<div class="card-grid card-grid-cols-{{ block.columns or 3 }}">
|
||||
{% for card in block.cards %}
|
||||
<article class="card">
|
||||
{% if card.image %}
|
||||
<div class="card-image">
|
||||
<img src="{{ card.image }}" alt="{{ card.image_alt or '' }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">{{ card.title }}</h3>
|
||||
{% if card.text %}
|
||||
<div class="card-text">
|
||||
{{ card.text | safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if card.button_url %}
|
||||
<div class="card-actions">
|
||||
<a href="{{ card.button_url }}" class="btn">
|
||||
{{ card.button_text or "Mehr erfahren" }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<section class="block block-full-width-image"
|
||||
style="
|
||||
--fade-speed: {{ block.fade_speed or '0.8s' }};
|
||||
--vignette-strength: {{ block.vignette_strength or '0.75' }};
|
||||
">
|
||||
<figure class="cd-figure">
|
||||
{% if block.src %}
|
||||
<img src="{{ block.src }}" alt="{{ block.alt or '' }}">
|
||||
{% endif %}
|
||||
{% if block.caption %}
|
||||
<figcaption>{{ block.caption }}</figcaption>
|
||||
{% endif %}
|
||||
</figure>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<section class="block block-hero block-hero-{{ block.align|default('center') }}">
|
||||
<div class="hero-inner">
|
||||
{% if block.image %}
|
||||
<div class="hero-image">
|
||||
<img src="{{ block.image }}" alt="{{ block.image_alt or block.title }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="hero-text">
|
||||
<h1>{{ block.title }}</h1>
|
||||
{% if block.subtitle %}
|
||||
<p class="hero-subtitle">{{ block.subtitle }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<section class="block block-prose">
|
||||
{% if block.heading %}
|
||||
<h2>{{ block.heading }}</h2>
|
||||
{% endif %}
|
||||
<div class="prose-content">
|
||||
{{ block.content | safe }}
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% for block in blocks %}
|
||||
{% include "blocks/" + block.type + ".html" %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
Loading…
Reference in New Issue