{% extends "v2/base.html" %} {% from "v2/components/score_hero.html" import score_hero %} {% from "v2/components/matrix_mini.html" import matrix_mini %} {% from "v2/components/quote_card.html" import quote_card %} {% from "v2/components/kasten.html" import kasten %} {% from "v2/components/redline.html" import redline %} {% block title %} {% if antrag is defined and antrag %}{{ antrag.title }} — {% endif %}GWÖ-Antragsprüfer {% endblock %} {% block head_extra %} {% if antrag is defined and antrag %} {# ── Open-Graph / Twitter-Card-Meta (#141) ────────────────────────── #} {% set _og_img = "/api/og/" ~ (antrag.drucksache | urlencode) ~ ".png" %} {% if antrag.updated_at_raw %} {% endif %} {% endif %} {% endblock %} {% set v2_active_nav = "durchsuchen" %} {% block main %} {# ── Fehlerfall ──────────────────────────────────────────────────── #} {% if error is defined and error %}

Antrag nicht gefunden

{{ error }}

← Zurück zur Übersicht

{% elif antrag is not defined or not antrag %} {# ── Demo-Daten wenn kein echtes Antrag-Objekt übergeben ────────── #} {% set antrag = { "drucksache": "18/4412", "bundesland": "BW", "parlament": "Landtag", "typ": "Antrag", "datum": "12.04.2026", "analysiert": "14.04.2026", "modell": "qwen-plus", "parteien": ["GRÜNE", "SPD"], "zitate_count": 3, "title": "Kommunale Wärmeplanung bis 2028 verpflichtend machen", "score": 9.1, "verdict_title": "Vorbildlich", "verdict_body": "Starker Beitrag zur ökologischen Nachhaltigkeit und Transparenz auf kommunaler Ebene.", "zusammenfassung": "Der Antrag verpflichtet Kommunen ab 10 000 Einwohner:innen zur Erstellung einer kommunalen Wärmeplanung bis Ende 2028.", "staerkster_wert": { "titel": "Ökologische Nachhaltigkeit", "text": "Verpflichtende Wärmeplanung führt zu messbaren Klimazielen. E3 = ++, D3 = ++." }, "schwaechster_wert": { "titel": "Soziale Gerechtigkeit", "text": "Kostenverteilung auf Mieter:innen versus Eigentümer:innen ist im Antrag nicht geregelt." }, "redline": { "segments": [ {"type": "ctx", "text": "§ 3 Abs. 2 "}, {"type": "del", "text": "auf Antrag"}, {"type": "ins", "text": "verpflichtend"}, {"type": "ctx", "text": " eine sozialverträgliche Umlage"} ] }, "matrix": { "A1": {"rating": 0, "symbol": "○"}, "A2": {"rating": 1, "symbol": "+"}, "A3": {"rating": 2, "symbol": "++"}, "A4": {"rating": 0, "symbol": "○"}, "A5": {"rating": 1, "symbol": "+"}, "B1": {"rating": 0, "symbol": "○"}, "B2": {"rating": 1, "symbol": "+"}, "B3": {"rating": 2, "symbol": "++"}, "B4": {"rating": -1, "symbol": "−"}, "B5": {"rating": 1, "symbol": "+"}, "C1": {"rating": 0, "symbol": "○"}, "C2": {"rating": 1, "symbol": "+"}, "C3": {"rating": 1, "symbol": "+"}, "C4": {"rating": 0, "symbol": "○"}, "C5": {"rating": 2, "symbol": "++"}, "D1": {"rating": 1, "symbol": "+"}, "D2": {"rating": 1, "symbol": "+"}, "D3": {"rating": 2, "symbol": "++"}, "D4": {"rating": 1, "symbol": "+"}, "D5": {"rating": 2, "symbol": "++"}, "E1": {"rating": 1, "symbol": "+"}, "E2": {"rating": 2, "symbol": "++"}, "E3": {"rating": 2, "symbol": "++"}, "E4": {"rating": 1, "symbol": "+"}, "E5": {"rating": 1, "symbol": "+"} }, "zitate": [ { "text": "Wir verpflichten alle Kommunen zu einer verbindlichen kommunalen Wärmeplanung bis 2028.", "source": "Wahlprogramm GRÜNE 2022 · S. 84", "partei": "GRÜNE", "verified": True, "contra": False, "pdf_href": "/api/wahlprogramm-cite?pid=gruene-nrw-2022&seite=84&q=Wärmeplanung" } ], "verbesserungen": [], "staerken": [], "schwaechen": [] } %} {# Fallthrough: Demo-Daten rendern wie echte Daten #} {% set _render = True %} {% else %} {% set _render = True %} {% endif %} {# ── Eigentlicher Detail-Inhalt ──────────────────────────────────── #} {% if _render is defined and _render and antrag is defined and antrag %} {# ── Zurück-Link ─────────────────────────────────────────────────── #}

← Zurück zur Übersicht

{# ── Split-Layout ────────────────────────────────────────────────── #}
{# ── Linke Spalte: Redaktionelle Analyse ── #}
{{ antrag.bundesland | default("") }} {% if antrag.drucksache %} · Drs. {{ antrag.drucksache }}{% endif %} {% if antrag.typ %} · {{ antrag.typ }}{% endif %} {% if antrag.datum %} · eingebracht {{ antrag.datum }}{% endif %}

{{ antrag.title | default("Antrag") }}

{% if antrag.parteien or antrag.analysiert %} {% endif %} {% if antrag.zusammenfassung %}

Zusammenfassung

{{ antrag.zusammenfassung }}

{% endif %} {# Stärkster Wert #} {% if antrag.staerkster_wert and antrag.staerkster_wert.text %}

Stärkster Wert{% if antrag.staerkster_wert.titel %} — {{ antrag.staerkster_wert.titel }}{% endif %}

{{ antrag.staerkster_wert.text }}

{% elif antrag.staerken %}

Stärken

    {% for s in antrag.staerken %}
  • {{ s }}
  • {% endfor %}
{% endif %} {# Schwächster Wert #} {% if antrag.schwaechster_wert and antrag.schwaechster_wert.text %}

Schwächster Wert{% if antrag.schwaechster_wert.titel %} — {{ antrag.schwaechster_wert.titel }}{% endif %}

{{ antrag.schwaechster_wert.text }}

{% elif antrag.schwaechen %}

Schwächen

    {% for s in antrag.schwaechen %}
  • {{ s }}
  • {% endfor %}
{% endif %} {# Verbesserungsvorschläge: alle verbesserungen rendern wenn vorhanden #} {% if antrag.verbesserungen %}

Verbesserungsvorschläge

{% for v in antrag.verbesserungen %}
{% if antrag.verbesserungen | length > 1 %}
Vorschlag {{ loop.index }} von {{ antrag.verbesserungen | length }}
{% endif %} {% from "v2/components/redline.html" import redline %} {% if v.segments %} {{ redline(original=v.original | default(""), segments=v.segments) }} {% else %} {{ redline(original=v.original | default(""), vorschlag=v.vorschlag | default("")) }} {% endif %} {% if v.begruendung %}

{{ v.begruendung }}

{% endif %}
{% endfor %} {% elif antrag.redline and antrag.redline.segments %}

Verbesserungsvorschlag

{% from "v2/components/redline.html" import redline %} {{ redline(segments=antrag.redline.segments) }} {% endif %}
{# .left #} {# ── Rechte Spalte: Bewertungs-Panel ── #}
{# Bewertungs-Header mit Merken-Button rechts — visuelle Einheit (User-Wunsch: „Bewertung passend zu Merken verschieben"). #}
Bewertung
{{ score_hero(antrag.score | default(0), antrag.verdict_title | default(""), antrag.verdict_body | default("")) }} {# ── Namentliche Abstimmung (#106 Phase 1) ── #} {% if antrag.abstimmungsverhalten %} {% set aw = antrag.abstimmungsverhalten %}

Namentliche Abstimmung

{% if aw.datum %}{{ aw.datum }} · {% endif %} {% if aw.accepted %}Angenommen{% else %}Abgelehnt{% endif %}
{% for f in aw.fraktionen %} {% set total = (f.yes + f.no + f.abstain + f.no_show) | int %} {% if total > 0 %}
{{ f.partei }} {{ f.yes }}✓ {{ f.abstain }}○ {{ f.no }}✗
{% if f.yes > 0 %}
{% endif %} {% if f.abstain > 0 %}
{% endif %} {% if f.no > 0 %}
{% endif %}
{% endif %} {% endfor %} {% endif %}{# abstimmungsverhalten #} {# ── Fraktions-aggregierte Plenum-Abstimmung aus Plenarprotokoll (#106) ── #} {% if antrag.plenum_votes %}

Abstimmungsergebnis

{% set ergebnis_color = { "angenommen": "#2da44e", "abgelehnt": "#cf222e", "überwiesen": "#0969da", "zurückgezogen": "#8250df", "bestätigt": "#2da44e", "sammel": "#0969da", } %} {# Konsistenz-Hinweis: GWÖ-Empfehlung vs. tatsächlicher Beschluss. Logik in app/marker.py — siehe ADR 0010. #} {% set _state = consistency_state(antrag.verdict_title, antrag.plenum_votes) %} {% set _decisive = decisive_outcome(antrag.plenum_votes) %} {% if _state %}
{% if _state == 'conflict' %}Mehrheit kontra GWÖ-Empfehlung{% else %}Mehrheit deckt sich mit GWÖ-Empfehlung{% endif %} — Empfohlen: {{ antrag.verdict_title }}; Beschluss: {{ _decisive | capitalize }}.
{% endif %} {% for v in antrag.plenum_votes %}
{{ v.ergebnis | capitalize }}{% if v.einstimmig %} · einstimmig{% endif %} {% if v.quelle_url %} {{ v.quelle_protokoll }} {% else %} {{ v.quelle_protokoll }} {% endif %}
{% if v.fraktionen_ja or v.fraktionen_nein or v.fraktionen_enthaltung %} {# Mehrheits-Bar: Fraktions-Anzahlen pro Lager als Stacked Bar #} {% set _n_ja = v.fraktionen_ja | length %} {% set _n_nein = v.fraktionen_nein | length %} {% set _n_enth = v.fraktionen_enthaltung | length %} {% set _n_total = _n_ja + _n_nein + _n_enth %} {% if _n_total > 0 %}
{% if _n_ja %}
{% endif %} {% if _n_enth %}
{% endif %} {% if _n_nein %}
{% endif %}
{{ _n_ja }}/{{ _n_total }} Fraktionen Ja · {{ _n_nein }} Nein · {{ _n_enth }} Enth.
{% endif %}
{% if v.fraktionen_ja %}
Ja: {% for f in v.fraktionen_ja %} {% set _opp_match = opportunismus_score(f, antrag.fraktions_scores) %} {{ f }}{% if _opp_match is not none %}!{% endif %} {% endfor %}
{% endif %} {% if v.fraktionen_nein %}
Nein: {% for f in v.fraktionen_nein %} {% set _wp_match = heuchelei_score(f, antrag.fraktions_scores) %} {{ f }}{% if _wp_match is not none %}{% endif %} {% endfor %}
{% endif %} {% if v.fraktionen_enthaltung %}
Enth.: {% for f in v.fraktionen_enthaltung %}{{ f }}{% endfor %}
{% endif %}
{# Marker-Legende: nur einblenden wenn auf dem Vote-Block ein ⚠- oder !-Marker tatsächlich vorkam, sonst würde das Bord der Bürgerin Erklärungstext zeigen, wofür sie kein Symbol sieht. #} {% set _has_heuchelei = false %} {% for f in (v.fraktionen_nein or []) %} {% if heuchelei_score(f, antrag.fraktions_scores) is not none %}{% set _has_heuchelei = true %}{% endif %} {% endfor %} {% set _has_opp = false %} {% for f in (v.fraktionen_ja or []) %} {% if opportunismus_score(f, antrag.fraktions_scores) is not none %}{% set _has_opp = true %}{% endif %} {% endfor %} {% if _has_heuchelei or _has_opp %}
{% if _has_heuchelei %} Heuchelei: Nein trotz hoher Wahlprogramm-Übereinstimmung (WP ≥ 7/10) {% endif %} {% if _has_opp %} ! Opportunismus: Ja trotz schwacher Wahlprogramm-Übereinstimmung (WP < 3/10) {% endif %}
{% endif %} {% endif %}
{% endfor %}
Quelle: Plenarprotokoll · automatisch extrahiert
{% endif %}{# plenum_votes #} {% if antrag.matrix %}

Matrix 2.0 · 25 Felder

{{ matrix_mini(antrag.matrix) }} {% endif %} {# Programm-Treue im BELEGE-Layout: pro Partei zwei aufklappbare Blöcke (Wahlprogramm + Parteiprogramm). Summary zeigt Bewertung, expand enthält Einschätzung + Belege. #} {% if antrag.fraktions_scores %}

Programm-Treue pro Fraktion

{% for fs in antrag.fraktions_scores %} {% set wp_score = fs.wahlprogramm.score | float %} {% set pp_score = fs.parteiprogramm.score | float %}
{{ fs.fraktion }} {% if fs.ist_antragsteller %}Antragsteller:in{% endif %} {% if fs.ist_regierung %}Regierungsfraktion{% endif %}
Wahlprogramm {{ "%.0f"|format(wp_score) }}/10
{% if fs.wahlprogramm.begruendung %}
Einschätzung
{{ fs.wahlprogramm.begruendung }}
{% endif %} {% if fs.wahlprogramm.zitate %}
Belege
{% for z in fs.wahlprogramm.zitate %} {{ quote_card(z.text, z.source, True, False, z.pdf_href) }} {% endfor %}
{% endif %}
Parteiprogramm {{ "%.0f"|format(pp_score) }}/10
{% if fs.parteiprogramm.begruendung %}
Einschätzung
{{ fs.parteiprogramm.begruendung }}
{% endif %} {% if fs.parteiprogramm.zitate %}
Belege
{% for z in fs.parteiprogramm.zitate %} {{ quote_card(z.text, z.source, True, False, z.pdf_href) }} {% endfor %}
{% endif %}
{% endfor %}
{% endif %} {# ── News-Match-Box: aktuelle News passend zu diesem Antrag (#170) ── #} {# Aktions-Links #}
PDF-Bericht JSON-Export Permalink
{# ── Voting-Block ─────────────────────────────────────────────── #}
Bewertung treffend?
{# ── Share-Block (analog v1) ───────────────────────────────────── #}
Teilen
{# ── Re-Analyze-Block ─────────────────────────────────────────── #}
{# ── Bewertungs-Historie ───────────────────────────────────────── #}
Bewertungs-Historie
Lade…
{# .right #}
{# .v2-detail #} {# ── Kommentare ───────────────────────────────────────────────────────── #}

Kommentare

Lade…
{# Kommentar-Formular — wird per JS eingeblendet wenn angemeldet #}
{# ── Matrix-Feld-Info-Modal ───────────────────────────────────────────── #} {% endif %}{# _render #} {% endblock %} {% block body_scripts %} {# Matrix-Erklärungen als JSON in den Browser übertragen #} {% if matrix_explanations is defined %} {% endif %} {% if antrag is defined and antrag and antrag.drucksache %} {% endif %} {% endblock %}