Frontend: Masonry-Layout + kompaktere Kacheln, media/* in .gitignore

- CSS Grid → CSS Columns (column-count:4) für echtes Masonry-Layout
  - Karten behalten ihre natürliche Höhe, kein Strecken mehr
  - Responsive: 3 Spalten @1100px, 2 @750px, 1 @500px
- Kacheln kompakter: media-crop 200px→160px, weniger Padding
- Hover: translateY(-3px) statt scale (vermeidet Clipping im Masonry)
- .gitignore: media/* statt media/uploads/ (alle Medien ignorieren)
- import re auf Module-Ebene (war vorher nur lokal in extract_halle)
This commit is contained in:
Hermes Agent
2026-06-17 15:15:02 +02:00
parent 0465b71c3a
commit a14f3582e9
2 changed files with 33 additions and 29 deletions
+32 -28
View File
@@ -15,6 +15,7 @@ Usage:
import json
import os
import re
import sqlite3
import sys
from datetime import datetime
@@ -1648,7 +1649,7 @@ def public_frontend():
if mime.startswith("image/"):
img_tag = (
'<a href="/beitrag/' + str(r["id"]) + '" class="media-preview-link">'
'<div class="media-crop" style="width:100%;height:200px;overflow:hidden;border-radius:8px;">'
'<div class="media-crop" style="width:100%;height:160px;overflow:hidden;border-radius:8px;">'
'<img src="' + src + '" alt="Beitragsbild" loading="lazy" style="width:100%;height:100%;object-fit:cover;">'
'</div></a>'
)
@@ -1750,27 +1751,27 @@ def public_frontend():
.site-header .header-right a { color:#aaa; text-decoration:none; font-size:0.8rem; transition:color 0.2s; }
.site-header .header-right a:hover { color:#fff; }
/* Main grid */
.main-grid { max-width:1200px; margin:1.5rem auto; padding:0 1.5rem; display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:1.2rem; }
/* Main grid — masonry (CSS columns) */
.main-grid { max-width:1300px; margin:1.5rem auto; padding:0 1rem; column-count:4; column-gap:1.2rem; }
/* Card — like SPIEL Essen modules */
.story-card { background:#fff; border-radius:16px; overflow:hidden; box-shadow:0 6px 28px rgba(0,0,0,0.12),0 2px 6px rgba(0,0,0,0.06); transition:transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1),box-shadow 0.3s ease; display:flex; flex-direction:column; }
.story-card:hover { transform:scale(1.04); box-shadow:0 20px 48px rgba(0,0,0,0.2),0 6px 16px rgba(0,0,0,0.1); z-index:10; position:relative; }
/* Card — masonry tiles, compact */
.story-card { background:#fff; border-radius:14px; overflow:hidden; box-shadow:0 4px 18px rgba(0,0,0,0.10),0 1px 4px rgba(0,0,0,0.05); transition:box-shadow 0.25s ease,transform 0.2s ease; display:inline-block; width:100%; margin-bottom:1.2rem; break-inside:avoid; }
.story-card:hover { transform:translateY(-3px); box-shadow:0 8px 32px rgba(0,0,0,0.18),0 3px 10px rgba(0,0,0,0.08); }
.story-card img { width:100%; height:100%; object-fit:cover; display:block; }
.story-card video { width:100%; height:auto; max-height:600px; object-fit:contain; display:block; background:#000; }
.story-card { position:relative; }
.story-halle-badge { position:absolute; top:10px; right:10px; background:#20228a; color:#fff; padding:0.25rem 0.65rem; border-radius:5px; font-size:0.78rem; font-weight:700; letter-spacing:0.03em; z-index:5; box-shadow:0 2px 6px rgba(0,0,0,0.3); }
.story-ausverkauft-badge { position:absolute; top:10px; left:10px; background:#dc3545; color:#fff; padding:0.3rem 0.7rem; border-radius:5px; font-size:0.78rem; font-weight:700; letter-spacing:0.02em; z-index:5; box-shadow:0 2px 6px rgba(0,0,0,0.3); }
.card-content { padding:0.6rem 1rem 0.8rem; display:flex; flex-direction:column; gap:0.25rem; }
.story-meta { display:flex; align-items:center; gap:0.5rem; flex-wrap:wrap; }
.story-type { font-size:0.85rem; }
.story-author { font-weight:600; color:#20228a; font-size:0.82rem; }
.story-date { color:#999; font-size:0.72rem; margin-left:auto; }
.story-time { font-size:0.75rem; color:#666; font-weight:500; }
.card-content { padding:0.45rem 0.85rem 0.55rem; display:flex; flex-direction:column; gap:0.2rem; }
.story-meta { display:flex; align-items:center; gap:0.4rem; flex-wrap:wrap; }
.story-type { font-size:0.8rem; }
.story-author { font-weight:600; color:#20228a; font-size:0.78rem; }
.story-date { color:#999; font-size:0.7rem; margin-left:auto; }
.story-time { font-size:0.7rem; color:#666; font-weight:500; }
.story-time-rel { color:#20228a; font-weight:700; }
.story-preview { display:none; }
.text-only .story-preview { display:block; font-size:0.85rem; line-height:1.45; color:#444; }
.text-only .card-content { padding-top:0.5rem; }
.text-only .story-preview { display:block; font-size:0.8rem; line-height:1.4; color:#444; }
.text-only .card-content { padding-top:0.4rem; }
/* Frontend filter bar */
.frontend-filter { max-width:1100px; margin:1rem auto 0; padding:0 1.5rem; display:flex; gap:0.4rem; flex-wrap:wrap; align-items:center; }
@@ -1809,13 +1810,23 @@ def public_frontend():
.site-footer a { color:#20228a; text-decoration:none; font-weight:600; }
.site-footer a:hover { text-decoration:underline; }
/* Responsive */
@media(max-width:600px) {
.site-header { padding:0.8rem 1rem; }
.main-grid { grid-template-columns:1fr; padding:0 1rem; gap:1rem; }
/* Responsive — masonry column counts */
@media(max-width:1100px) {
.main-grid { column-count:3; }
}
@media(max-width:750px) {
.main-grid { column-count:2; padding:0 0.7rem; column-gap:0.8rem; }
.story-card { margin-bottom:0.8rem; }
}
@media(max-width:500px) {
.main-grid { column-count:1; padding:0 0.8rem; }
.story-card { margin-bottom:1rem; }
.site-header { padding:0.8rem 1rem; }
.submit-bubble { bottom:1rem; right:5rem; }
.chat-overlay { bottom:5rem; right:0.5rem; width:calc(100vw - 1rem); max-height:60vh; }
.chat-bubble { bottom:1rem; right:1rem; }
.submit-overlay { bottom:5rem; right:0.5rem; width:calc(100vw - 1rem); max-height:65vh; }
}
/* ── Chat Bubble + Overlay ────────────────────────────────── */
.chat-bubble { position:fixed; bottom:1.5rem; right:1.5rem; z-index:9999;
width:56px; height:56px; border-radius:50%; background:#20228a;
color:#fff; border:none; cursor:pointer; font-size:1.6rem;
@@ -1856,10 +1867,6 @@ def public_frontend():
transition:background 0.15s; font-family:inherit; }
.chat-footer button:hover { background:#161e6e; }
.chat-footer button:disabled { opacity:0.5; cursor:default; }
@media(max-width:600px) {
.chat-overlay { bottom:5rem; right:0.5rem; width:calc(100vw - 1rem); max-height:60vh; }
.chat-bubble { bottom:1rem; right:1rem; }
}
/* ── Submit Overlay ────────────────────────────────────────── */
.submit-bubble { position:fixed; bottom:1.5rem; right:5.5rem; z-index:9999;
@@ -1898,10 +1905,6 @@ def public_frontend():
.submit-body .submit-btn:disabled { opacity:0.5; cursor:default; }
.submit-body .status-msg { text-align:center; font-size:0.8rem; margin-top:0.6rem;
min-height:1.2rem; }
@media(max-width:600px) {
.submit-overlay { bottom:5rem; right:0.5rem; width:calc(100vw - 1rem); max-height:65vh; }
.submit-bubble { bottom:1rem; right:5rem; }
}
</style>
</head>
<body>
@@ -2200,6 +2203,7 @@ def api_query():
return jsonify({'results': results, 'count': len(results)})
@app.route('/api/chat', methods=['POST'])
def api_chat():
"""Chat agent with read-only access to published submissions."""