Commit Graph

149 Commits

Author SHA1 Message Date
Peter Meier 77fee9b1c2 feat(stellungnahme): Step-0 als Cards, Step-3 ohne Mindest-Auswahl, Steckbrief default offen
Deploy / verify (push) Successful in 54s
Deploy / deploy (push) Successful in 1m3s
Step 0 (Gebietskontext):
- Gebiets-Nummer (W-37) deutlich größer: text-4xl tracking-tight
- Detail-Felder als Cards: rounded-lg border-wald-200 bg-white/70 p-3 shadow-sm
- Icons (Gemeinden, Fläche, Anlagen geplant, Max. Höhe, Investor, Status)
  oben links als eigenes Element statt inline; size-5 text-wald-600
- Labels: text-sm sm:text-base font-semibold text-wald-800 whitespace-nowrap
  (kleiner auf Mobile damit "Anlagen geplant" in der Card bleibt)
- Werte: text-stein-600 (grau) mit mt-1 Abstand
- Steckbrief-<details> default open

Step 2 (Allgemeine Argumente):
- "Weiter"-Button nicht mehr disabled bei 0 Auswahl — Mindest-Auswahl
  weggefallen, Anzahl nur im Label wenn >0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 11:43:01 +02:00
Peter Meier 3f39b5b1a8 fix(stellungnahme): Mini-Map mobile square + Gebiet zentriert (fitBoundsPadding-Prop)
Deploy / verify (push) Successful in 1m5s
Deploy / deploy (push) Successful in 1m12s
2026-05-30 11:25:36 +02:00
Peter Meier bd67f0c568 feat(nav): navgroup-Dropdowns im Header + Fix Overflow-Clipping
Deploy / verify (push) Successful in 1m3s
Deploy / deploy (push) Successful in 1m12s
- layout.server.ts: NavLink um optional children?: NavLink[] erweitert.
  navHeader-Resolve von 'links' auf 'all' (navgroup-sub-links werden mit
  aufgelöst). Resolver-Loop erkennt navgroup-Entries (_type==='navgroup'
  oder Shape label+links) und baut NavLink mit Children + Parent-URL.
- Header.svelte: Desktop-Dropdown mit Hover/Focus-Open + ARIA (haspopup,
  expanded, role=menu/menuitem). Mobile: collapsible Submenu via
  openSubmenu-State, slide-animiert; "– Übersicht"-Link wenn Parent
  selbst eine URL hat. isActiveTree(): Parent gilt aktiv wenn ein Child
  aktiv ist.
- Overflow-Fix: .gradient-blob-bg setzt overflow:hidden → clipte den
  Desktop-Dropdown. Neue Variante .gradient-blob-bg-inner als absoluter
  Inner-Layer (eigenes overflow-hidden), Header selbst bleibt
  overflow-visible. Bestehende .gradient-blob-bg-Nutzungen (z.B.
  DeadlineBannerBlock) unverändert.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 08:50:51 +02:00
Peter Meier 940b9beb7f feat(windkarte): stellungnahmeUrl-Feld + Einwendung-erstellen-Button im Detail-Panel
Deploy / verify (push) Successful in 1m7s
Deploy / deploy (push) Successful in 1m19s
2026-05-29 09:14:36 +02:00
Peter Meier 0be73adc51 feat(stellungnahme): a11y, Suche, Frist-Status, Steckbrief & Map mobil
Deploy / verify (push) Successful in 57s
Deploy / deploy (push) Successful in 1m38s
- Titel klickbar als <label> (Tastatur/Screenreader), aria-live auf Ausgabe
- Neustart mit Rückfrage, mailto-Längen-Guard (>1900 Zeichen)
- Frist-abgelaufen-Banner statt kommentarlos verschwinden
- Suchfeld filtert allgemeine Argumente live
- <details>-Chevron dreht beim Aufklappen
- Steckbrief einklappbar + scrollbar, Single-Newlines als Hard-Break
- Mini-Map responsive Höhe (h-56 mobil → h-80 desktop)
- Ausgabe-Buttons text-sm/text-[11px], mobil umbrechend; Mail-Link no-underline
- gebietsBez-Deklaration vor Verwendung gezogen (svelte-check Fehler)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:41:43 +02:00
Peter Meier 5d0a634359 fix(stellungnahme): Mail-Link no-underline, Ausgabe-Buttons kleiner
Deploy / verify (push) Failing after 47s
Deploy / deploy (push) Has been skipped
2026-05-28 14:27:10 +02:00
Peter Meier e80d9eef7e feat(stellungnahme): E-Mail-Button immer zeigen (leerer Empfänger = an sich selbst)
Deploy / verify (push) Failing after 51s
Deploy / deploy (push) Has been skipped
2026-05-28 14:25:21 +02:00
Peter Meier a872a015d9 fix(stellungnahme): Ausgabe-Buttons mobil umbrechen statt overflowen
Deploy / verify (push) Failing after 47s
Deploy / deploy (push) Has been skipped
2026-05-28 14:23:47 +02:00
Peter Meier 8194d8639d feat(stellungnahme): Einleitung/Abschluss via CMS-Felder pflegbar
Deploy / verify (push) Failing after 46s
Deploy / deploy (push) Has been skipped
2026-05-28 13:35:31 +02:00
Peter Meier 4e46e82770 feat(stellungnahme): Button subtiles Wiggle-Rotate statt bounce
Deploy / verify (push) Failing after 50s
Deploy / deploy (push) Has been skipped
2026-05-28 13:32:08 +02:00
Peter Meier 2bae9b3e5d fix(stellungnahme): Button animate-bounce statt ping
Deploy / verify (push) Failing after 47s
Deploy / deploy (push) Has been skipped
2026-05-28 13:31:07 +02:00
Peter Meier 16bb8af12c feat(stellungnahme): Text-erstellen-Button pulsiert (animate-ping)
Deploy / verify (push) Failing after 47s
Deploy / deploy (push) Has been skipped
2026-05-28 13:29:44 +02:00
Peter Meier 6bc6781b3c fix(stellungnahme): Zurück-Button in Step 5 links
Deploy / verify (push) Failing after 44s
Deploy / deploy (push) Has been skipped
2026-05-28 13:29:01 +02:00
Peter Meier d45e691171 feat(stellungnahme): Notizfeld pro Argument + editierbare Einleitung/Abschluss
Deploy / verify (push) Failing after 50s
Deploy / deploy (push) Has been skipped
- Notizfeld an jedem Argument (expanded) → erscheint im Output als "Anmerkung:"
- Einleitung und Abschluss in Step 5 via <details> editierbar
- Beide mit Zurücksetzen-Button auf Default
- Alles in localStorage persistiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 13:27:07 +02:00
Peter Meier 28170a8549 fix(stellungnahme): Disclaimer prominenter mit Rahmen und Großbuchstaben
Deploy / verify (push) Successful in 52s
Deploy / deploy (push) Successful in 1m5s
2026-05-27 16:37:54 +02:00
Peter Meier 2d1967ec38 feat(stellungnahme): Entwurfs-Disclaimer im generierten Dokument
Deploy / verify (push) Successful in 53s
Deploy / deploy (push) Successful in 1m37s
2026-05-27 16:36:53 +02:00
Peter Meier 8f260044e6 fix(stellungnahme): bulletPoints statt Prosatext im generierten Dokument
Deploy / verify (push) Successful in 57s
Deploy / deploy (push) Successful in 1m36s
2026-05-27 16:34:43 +02:00
Peter Meier 5f5bd06a78 feat(stellungnahme): E-Mail, Name in Grußformel, Datum-Fix, UX-Polish
Deploy / verify (push) Successful in 57s
Deploy / deploy (push) Successful in 1m9s
- E-Mail-Button: mailto-Link wenn recipientEmail im Block gesetzt
- Name in Grußformel: "Mit freundlichen Grüßen\n\nMax Mustermann"
- Datum-Fix: heute in buildText() berechnet, nicht beim Render
- Disabled-Hint: roter Hinweis wenn Name fehlt
- "Alle ab" klappt Gruppe ein (Symmetrie zu "Alle" öffnet)
- Schritt X von Y unter Step-Indikator
- recipientEmail-Feld in StellingnahmeGeneratorBlockData

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 16:32:25 +02:00
Peter Meier ff383b8b3b fix(stellungnahme): mode const nicht in resetAll zuweisen
Deploy / verify (push) Successful in 55s
Deploy / deploy (push) Successful in 1m5s
2026-05-27 16:02:53 +02:00
Peter Meier cfb74096d1 feat(stellungnahme): Modus-Auswahl entfernen, immer Fertigtext
Deploy / verify (push) Failing after 45s
Deploy / deploy (push) Has been skipped
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 16:00:39 +02:00
Peter Meier 96dd88247d feat(stellungnahme): UX-Verbesserungen, localStorage, Mini-Map, Druck
Deploy / verify (push) Successful in 55s
Deploy / deploy (push) Successful in 1m39s
- localStorage: Formularstand + Ausgabe-Historie (max 5) persistieren
- Fortsetzen-Banner: gespeicherte Sitzung erkannt → Sprung zu letztem Schritt
- Neustart-Button: alles inkl. localStorage leeren
- Frist-Banner: deadline-Feld in StellingnahmeGeneratorBlockData, Ampelfarben
- Step 1 überspringen wenn keine ortskonkreten Argumente vorhanden
- Step-Indikator: goTo() statt step= (scrollt jetzt korrekt)
- "Alle wählen" öffnet Gruppe automatisch
- Download als .txt neben Kopieren/Drucken
- <pre> → <div> für konsistentes Schriftbild im Output
- Mini-Map für Vorranggebiet in Step 0 (tap-to-activate, fitBoundsMaxZoom=13)
- WindkarteMap: fitBoundsMaxZoom-Prop ergänzt
- Druckausgabe: 13pt Serif, 2cm Ränder, kein Markdown im Fertigtext

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 15:57:27 +02:00
Peter Meier 6d0861bb0a feat(stellungnahme): Einwendungs-Assistent für Windvorranggebiete
Deploy / verify (push) Successful in 59s
Deploy / deploy (push) Successful in 2m37s
5-Schritt-Wizard: Gebietskontext → Argumente wählen → Ausgabeform →
persönliche Betroffenheit → Absender + Ausgabe. Alle Eingaben bleiben
lokal im Browser (kein Server-Transfer). Fertigtext- und Leitfaden-Modus.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 14:41:00 +02:00
Peter Meier d781b3140e feat(calendar-compact): polish + global not-prose opt-out support
Deploy / verify (push) Successful in 1m4s
Deploy / deploy (push) Successful in 1m9s
CalendarCompact:
- denser layout (smaller padding/font/badge), header icon size-8
- icon stein-900 (black), subtle wald gradient background
- rounded-sm to match design tokens (was rounded-lg)
- list items link to linkTo + "#event-<slug>" anchor; <svelte:element>
  falls back to div when no linkTo is set
- not-prose on root so global content margins/list/link rules don't
  apply to the card subtree

blog-utils.resolveCalendarBlocks:
- when items array is empty, fall back to the full calendar_item pool
  (both default and compact variant get this) — saves editors from
  re-listing items on every page.

app.css: add `:where(:not(.not-prose *))` to .content p/h1-h4,
main a (link colour + underline), main ul/ol so subtrees marked
not-prose stop inheriting the global prose-like defaults.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 09:16:21 +02:00
Peter Meier b7bcdd76ee feat(calendar): compact variant for next-events teaser
Deploy / verify (push) Successful in 1m8s
Deploy / deploy (push) Successful in 1m13s
Calendar block now supports variant: "default" | "compact".
- default = full calendar (unchanged)
- compact = next N events (default 3) + link to a target page

New CalendarCompactBlock.svelte: small card with month/day badge,
title, date/time/location line, "Alle kommenden Termine →" footer
link resolved from the schema's linkTo reference. Filters to future
events (12h tolerance for running ones).

BlockRenderer dispatches by block.variant inside the calendar case.
Schema (cms_content/_types/core/calendar.json5) adds variant + linkTo
+ limit fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 08:49:08 +02:00
Peter Meier 6a1069f908 fix(form): shrink sm inputs to text-xs, align consent checkbox top
Deploy / verify (push) Successful in 54s
Deploy / deploy (push) Successful in 1m3s
- TextInput/Textarea size="sm": text-xs, tighter padding (h-9, px-2.5
  py-1.5) so placeholder/value match label scale.
- Checkbox: new size prop (sm = h-4 w-4 + text-xs leading-snug).
  Switched container to flex/items-start so multi-line labels align
  with checkbox top instead of vertically centering and pushing the
  box halfway down the paragraph.
- ContactForm: consent checkbox uses size="sm"; privacy note + error
  hint at text-[0.7rem] leading-snug to match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 14:33:34 +02:00
Peter Meier 81c82c33e6 perf: review-fixes (N+1, waterfalls, sanitize-cache, lazy strommix)
Deploy / verify (push) Successful in 56s
Deploy / deploy (push) Successful in 1m3s
- blog-utils.resolvePostOverviewBlocks: parallel getPostBySlug via
  Promise.all + .catch(null) instead of sequential await loop.
- blog-utils.resolveCalendarBlocks: same fix for calendar items.
- [...slug] page load: SearchableText/Calendar/DeadlineBanner now run
  parallel after tagsMap (was strict waterfall).
- sanitize-blocks: LRU cache keyed on raw html input — sanitize-html is
  ~ms/KB, the same content repeats across pages and cache hits.
- cms.getNormalizedTranslations: WeakMap-memoised the per-request
  Object.entries normalize loop on top of the existing 5-min bundle TTL.
- cms.cached: opt-in dev cache via DEV_CACHE_CMS=1 (default still off).
- rusty-image.ensureTransformedImage: was async-wrapping a sync URL
  builder; made sync, removed awaits at call sites — saves microtasks.
- BlockRenderer: lazy-load StrommixBlock (~220 KB) via dynamic import
  in the template — pages without the live-strommix widget no longer
  ship its bundle.

Also: enabled Caddy zstd+gzip on windwiderstand.de vhost (server-side
edit; verified `content-encoding: zstd` on response).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 12:30:15 +02:00
Peter Meier d03afe780e feat(contact): add Cloudflare Turnstile captcha
Deploy / verify (push) Failing after 44s
Deploy / deploy (push) Has been skipped
Client renders explicit Turnstile widget (flexible, light theme) when
PUBLIC_TURNSTILE_SITE_KEY is set. Token sent with form payload, server
verifies via siteverify endpoint before forwarding to CMS. Skipped
entirely when no site key configured (dev fallback). New i18n keys:
contact_captcha_pending, contact_server_error_captcha. Deploy workflow
forwards PUBLIC_TURNSTILE_SITE_KEY + TURNSTILE_SECRET.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:37:09 +02:00
Peter Meier 94a8feeb67 feat(contact): full validation, CMS-translated strings, smaller UI
Deploy / verify (push) Failing after 47s
Deploy / deploy (push) Has been skipped
- contact-form-validation.ts: shared client+server validator returning
  {key, params} so messages can be translated via the CMS bundle.
- ContactFormComponent: 3 honeypots, subject field, GDPR consent
  checkbox, character counter, inline per-field errors after submit,
  uses useTranslate() everywhere.
- /api/contact: origin allowlist, multiple honeypot check, client-age
  gate, server-side re-validation, forwards X-Forwarded-For + UA to
  CMS forms plugin with consent timestamp in payload.
- TextInput/Textarea: new size="sm" variant (rounded-sm, shadow-sm,
  h-10, smaller padding/text). Default "md" unchanged.
- translations.ts: 37 new contact_* keys.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:28:23 +02:00
Peter Meier 8575572183 refactor: consolidate block dispatch into BlockRenderer
ContentRows now delegates to BlockRenderer instead of maintaining its
own parallel if-else chain. Single source of truth for all block types.
Adds internal_component support (ContactFormComponent via /api/contact).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:12:49 +02:00
Peter Meier 9e05fbb2ba feat: add internal_component block type with contact form
InternalComponentBlock dispatches on `component` field value.
ContactFormComponent submits via /api/contact (SvelteKit proxy →
CMS /api/forms/kontakt/submit) with honeypot + client_age_ms.
BlockRenderer and block-types.ts updated accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:01:47 +02:00
Peter Meier 50d68a17ca fix(windkarte): Kriterien-Accordion text-xs, Titel 2-zeilig
Deploy / verify (push) Successful in 54s
Deploy / deploy (push) Successful in 1m5s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 14:52:03 +02:00
Peter Meier 8e43169b23 feat(windkarte): Stellungnahme-Kriterien per Windvorranggebiet
Deploy / verify (push) Successful in 56s
Deploy / deploy (push) Successful in 1m38s
Jedes Windvorranggebiet kann jetzt 1–n text_fragment-Einträge als
Stellungnahme-Kriterien referenzieren. Das Panel lädt diese lazy beim
Öffnen und zeigt sie als aufklappbare Accordion-Sektion.

Außerdem: alle hardcodierten Strings im Karten-Block (Panel, Map,
Block) durch t()-Aufrufe ersetzt; 7 neue Translation-Keys ergänzt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 14:22:35 +02:00
Peter Meier a3f545d727 feat(windkarte): add per-area geo export + dynamic favicon
Deploy / verify (push) Successful in 1m1s
Deploy / deploy (push) Successful in 1m8s
- /api/vorranggebiete.geojson + .kml endpoints (filter via ?id=W-XX)
- Download-Buttons in WindAreaPanel pro selektiertes Gebiet
- Hover-Tooltip auf Polygon zeigt Fläche, geplante Anlagen, Höhe, Gemeinden
- Favicon + apple-touch-icon dynamisch aus data.logoUrl (CMS-Logo)
- alte windrad-PNGs in static/favicons/ entfernt
- WindkarteBlock list-fetch: _limit statt limit (RustyCMS-Param)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 12:14:58 +02:00
Peter Meier 12e0d4e3b8 ui: carousel swipe, org peek, deadline banner fixes
Deploy / verify (push) Successful in 53s
Deploy / deploy (push) Successful in 1m3s
- Carousel: touch swipe support (40px threshold)
- OrganisationsBlock: 1.5 cards on mobile to hint at more content
- DeadlineBanner: left-aligned text, shrink-0 close button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:46:23 +02:00
Peter Meier 9d58c92e94 ui: card-surface utility, rounded corners, calendar polish, banner layout
Deploy / verify (push) Successful in 1m1s
Deploy / deploy (push) Successful in 1m9s
- Add .card-surface utility (@layer components): rounded-sm border shadow-sm
- Card.svelte, CalendarBlock, SearchableTextBlock, BlogOverview use card-surface
- OrganisationsBlock: logo h-12 rounded-sm, description style cleanup, pt-1 for hover clip fix
- DeadlineBanner: container-custom width constraint, text left-aligned
- WindAreaPanel stats: card-surface
- CalendarBlock: rounded-sm day headers, past days opacity-20 + diagonal strike
- Add .day-past pseudo-element utility for diagonal line

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:32:42 +02:00
Peter Meier f08e3bb790 windkarte: scroll map into view when URL hash selects an area
Deploy / verify (push) Successful in 54s
Deploy / deploy (push) Successful in 1m4s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:45:46 +02:00
Peter Meier cd362fb811 windkarte: Rechtskräftig default hidden, remove Entwurf-2-voraussichtlich, 2km/5km rings on by default
Deploy / verify (push) Successful in 58s
Deploy / deploy (push) Successful in 1m6s
- Hide status badge for rechtskraeftig in WindAreaPanel
- Default hiddenStatuses=["rechtskraeftig"] so polygons start hidden
- Fix: call restyleAll after geojsonLayer init so initial hidden state applies
- Default hiddenRings=[] so 2km+5km buffer rings show on selection
- Remove entwurf_2_voraussichtlich from legend
- Lower maxZoom 12→11 for more context on feature select

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:26:19 +02:00
Peter Meier 4a72142555 WindAreaPanel: compact key-value rows instead of cards
Label left, value right, divided rows. No more padded bg cards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:18:38 +02:00
Peter Meier 823adde1fa WindAreaPanel: stats single column layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:18:06 +02:00
Peter Meier f55f409158 WindAreaPanel: render notizen as HTML with prose styles
Was output as escaped plain text. Field contains HTML from the CMS editor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:16:46 +02:00
Peter Meier 250865893e FilesBlock: icon size-4 → size-5
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:46:52 +02:00
Peter Meier 07b6317b94 FilesBlock: mt-0.5 on icon for top alignment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:46:38 +02:00
Peter Meier 07f17e880e FilesBlock: top-align icon with text
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:45:48 +02:00
Peter Meier baa4b9aae4 FilesBlock: allow description to wrap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:45:17 +02:00
Peter Meier 61e01c127f FilesBlock: size as inline badge after filename
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:44:46 +02:00
Peter Meier 887a6bda3e FilesBlock: remove default link underline
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:43:57 +02:00
Peter Meier 774ac893ec FilesBlock: description on second line below filename
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:43:10 +02:00
Peter Meier 1284be9c42 FilesBlock: size label smaller + no-wrap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:42:32 +02:00
Peter Meier 325f95487f FilesBlock: move size under icon, drop redundant ext label
Icon already communicates file type. Size now sits below the icon
in a fixed-width left column. Ext text removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:41:40 +02:00
Peter Meier 1825b7d9fe FilesBlock: compact single-row layout
Reduce padding, smaller icon, filename + ext/size on one line.
Description hidden on mobile, truncated on desktop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:39:09 +02:00