- notifications: round sqm_price to whole € in Telegram match messages
(was emitting raw float like "12.345614 €/m²").
- wohnungen: remove the admin-only "Bilder nachladen (N)" button. It
flickered into view whenever a freshly-scraped flat was still in
pending state, which was effectively random from the user's point of
view, and the manual backfill it triggered isn't needed anymore — new
flats are auto-enriched at scrape time. Also drops the dead helpers
it was the sole caller of: enrichment.kick_backfill,
enrichment._backfill_runner, db.flats_needing_enrichment,
db.enrichment_counts.
- lightbox: the modal didn't appear because Tailwind's Play CDN injects
its own .hidden { display: none } rule at runtime, which kept fighting
our class toggle. Switch the show/hide to inline style.display so no
external stylesheet can mask it. Single-class .lightbox now only owns
the layout — the initial-hidden state is on the element via
style="display:none".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Map: replace Leaflet's default marker with a divIcon SVG pin coloured
per state — green when the user has already successfully applied
(status.chip === "ok"), brand-blue otherwise. Same condition also hides
the action buttons in the popup, matching the list view, which already
hid both Bewerben and Ablehnen on success — so the only remaining
action on an applied flat is opening the original ad link.
Image gallery: clicks now open a global lightbox modal instead of a new
tab. The viewer fits each image into the viewport via max-width/height
+ object-fit: contain (uniform sizing regardless of source aspect),
shows × top-right, prev/next arrows on the sides, ←/→/Esc keyboard
nav, and click-on-backdrop to close. Prev arrow is hidden on the first
image and next on the last. Tile changes from <a target="_blank"> to
<button> since the new-tab fallback is no longer wanted.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New Telegram match layout:
Karl-Ziegler-Straße 7 (linked → Google Maps)
12489 Treptow-Köpenick
Miete: 944.12 (18.51 €/m²)
Fläche: 51.0
Zimmer: 2.0
WBS: nicht erforderlich
Zur original Anzeige (→ flat URL)
Zur lazyflat Seite (→ /?flat=<id>)
Deep-link behavior on lazyflat: ?flat=<id> expands the matching row,
scrolls it into view, and pulses a yellow highlight for 3s. The query
param is stripped from history afterwards so reload stays clean.
Unknown flat IDs drop the param silently.
Helpers: _address_lines splits the scraper's "Street, PLZ, District"
into two display lines; _gmaps_url falls back to a maps.google query
when the payload has no explicit link; _wbs_label normalises the
German WBS variants to "erforderlich" / "nicht erforderlich".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Container names, FastAPI titles, email subjects, filenames, brand text,
session cookie, User-Agent, docstrings, README. Volume lazyflat_data and
/data/lazyflat.sqlite already used the new name, so on-disk data is
preserved; dropped the now-obsolete legacy-rename comments.
Side effect: SESSION_COOKIE_NAME change logs everyone out on deploy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
base.html shrinks from a 150-line inline stylesheet to a single <link>;
the CSS moves to web/static/app.css byte-for-byte so there's no visual
change, but the stylesheet is now cacheable independently of the HTML.
Drop hx-on::before-request="this.disabled=true" from the Bewerben /
Ablehnen buttons — it duplicates hx-disabled-elt="find button" on the
parent form, which htmx already applies per request.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>