ui(antrag-detail): Programm-Treue als 2-Spalten-Grid, Trennlinien raus

User-Feedback: vorherige Pillen-Variante zu schmal/dicht. Stattdessen
gewünscht: Layout wie ursprünglich (head + 2 Programm-Reihen), aber
mit weniger Whitespace und ohne Trennlinien — und die Partei in eine
linke Spalte gezogen, damit head und Programm-Rows nebeneinander
sitzen statt stapeln.

Layout: ``.v3-fraktion`` als CSS-Grid mit zwei Spalten:
- links (140px–25%): Fraktion-Name + Pillen vertikal
- rechts (1fr): zwei Programm-Reihen (Wahlprogramm / Parteiprogramm)
  ohne border-top zwischen den Reihen, padding 3px statt 10/8,
  font kleiner (11px statt 12px).
This commit is contained in:
Dotty Dotter 2026-05-09 01:23:53 +02:00
parent 2f700adbb8
commit 35fed45339
2 changed files with 69 additions and 71 deletions

View File

@ -183,17 +183,25 @@
flex-direction: column; flex-direction: column;
gap: 6px; gap: 6px;
} }
/* Zwei-Spalten-Layout: links Fraktion-Meta (Name + Pillen),
rechts beide Programm-Reihen. Spart vertikalen Platz, weil head
und Programm-Rows in derselben Höhe nebeneinander sitzen. */
.v3-fraktion { .v3-fraktion {
background: var(--surface); background: var(--surface);
border: 1px solid var(--hairline); border: 1px solid var(--hairline);
border-radius: 4px; border-radius: 4px;
padding: 6px 12px; padding: 6px 12px;
display: grid;
grid-template-columns: minmax(140px, 0.25fr) 1fr;
column-gap: 16px;
align-items: start;
} }
.v3-fraktion-row { .v3-fraktion-meta {
display: flex; display: flex;
align-items: center; flex-direction: column;
gap: 8px; gap: 3px;
flex-wrap: wrap; align-items: flex-start;
padding-top: 2px;
} }
.v3-fraktion-name { .v3-fraktion-name {
font-family: var(--font-sans); font-family: var(--font-sans);
@ -202,7 +210,6 @@
letter-spacing: 0.02em; letter-spacing: 0.02em;
color: var(--ecg-dark); color: var(--ecg-dark);
} }
.v3-fraktion-spacer { flex: 1 1 auto; }
.v3-pill { .v3-pill {
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 10px; font-size: 10px;
@ -214,12 +221,13 @@
.v3-pill-antrag { color: #bf6c10; background: rgba(247, 148, 29, 0.15); } .v3-pill-antrag { color: #bf6c10; background: rgba(247, 148, 29, 0.15); }
.v3-pill-reg { color: #1e6a90; background: rgba(0, 157, 165, 0.15); } .v3-pill-reg { color: #1e6a90; background: rgba(0, 157, 165, 0.15); }
/* Kompakte Programm-Pillen rechts in der Fraktion-Zeile. .v3-fraktion-progs {
Aufklappbar via <details>; aufgeklappt fließt der Body unter display: flex;
die Zeile in voller Breite. */ flex-direction: column;
/* Keine Trennlinien zwischen WP- und PP-Reihe — nur knapp gestapelt. */
}
.v3-prog { .v3-prog {
/* details als grid-item: in der flex-row, body wandert beim Aufklappen /* Keine border zwischen Programm-Reihen — auf User-Wunsch. */
dank flex-basis:100% auf eigene Zeile. */
} }
.v3-prog > summary { .v3-prog > summary {
list-style: none; list-style: none;
@ -229,59 +237,47 @@
} }
.v3-prog > summary::-webkit-details-marker { display: none; } .v3-prog > summary::-webkit-details-marker { display: none; }
.v3-prog-pill { .v3-prog-row {
display: inline-flex; display: flex;
align-items: center; align-items: baseline;
gap: 6px; gap: 8px;
padding: 2px 8px; padding: 3px 0; /* von 10/8 auf 3 — minimaler Whitespace */
border: 1px solid var(--hairline);
border-radius: 3px;
background: rgba(0, 0, 0, 0.015);
transition: background 0.12s ease, border-color 0.12s ease;
} }
.v3-prog-pill:hover { .v3-prog-label {
background: rgba(0, 0, 0, 0.04); font-family: var(--font-mono);
border-color: var(--ecg-blue); font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--ecg-dark);
font-weight: 600;
transition: color 0.12s ease;
} }
.v3-prog-pill::before { .v3-prog-label::before {
content: "▸"; content: "▸";
display: inline-block; display: inline-block;
margin-right: 4px;
font-size: 9px; font-size: 9px;
opacity: 0.55; opacity: 0.55;
transition: transform 0.15s ease; transition: transform 0.15s ease;
margin-right: 1px;
} }
.v3-prog[open] > .v3-prog-pill::before { .v3-prog[open] > summary .v3-prog-label::before {
transform: rotate(90deg); transform: rotate(90deg);
} }
.v3-prog-pill-label { .v3-prog > summary:hover .v3-prog-label { color: var(--ecg-blue); }
font-family: var(--font-mono); .v3-prog-spacer { flex: 1 1 auto; }
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--ecg-dark);
font-weight: 700;
}
.v3-prog-score { .v3-prog-score {
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 11px; font-size: 11px;
font-weight: 700; font-weight: 700;
padding: 1px 6px; padding: 1px 7px;
border-radius: 3px; border-radius: 3px;
} }
.v3-prog-score.good { background: var(--score-chip-green-bg); color: var(--score-chip-green-fg); } .v3-prog-score.good { background: var(--score-chip-green-bg); color: var(--score-chip-green-fg); }
.v3-prog-score.mid { background: var(--score-chip-mid-bg); color: var(--score-chip-mid-fg); } .v3-prog-score.mid { background: var(--score-chip-mid-bg); color: var(--score-chip-mid-fg); }
.v3-prog-score.low { background: var(--score-chip-red-bg); color: var(--score-chip-red-fg); } .v3-prog-score.low { background: var(--score-chip-red-bg); color: var(--score-chip-red-fg); }
/* Body bricht aus der flex-row aus und nimmt die volle Breite,
sobald details aufgeklappt ist. */
.v3-prog-body { .v3-prog-body {
flex-basis: 100%; padding: 4px 0 6px 14px;
width: 100%;
margin-top: 8px;
padding: 8px 4px 4px;
border-top: 1px dashed var(--hairline);
} }
.v3-prog-text { .v3-prog-text {
font-size: 13.5px; font-size: 13.5px;

View File

@ -263,39 +263,41 @@
{% for fs in antrag.fraktions_scores %} {% for fs in antrag.fraktions_scores %}
{% if fs.fraktion | lower not in _missing_set %} {% if fs.fraktion | lower not in _missing_set %}
<div class="v3-fraktion"> <div class="v3-fraktion">
<div class="v3-fraktion-row"> <div class="v3-fraktion-meta">
<span class="v3-fraktion-name">{{ fs.fraktion }}</span> <span class="v3-fraktion-name">{{ fs.fraktion }}</span>
{% if fs.ist_antragsteller %}<span class="v3-pill v3-pill-antrag">Antragsteller:in</span>{% endif %} {% if fs.ist_antragsteller %}<span class="v3-pill v3-pill-antrag">Antragsteller:in</span>{% endif %}
{% if fs.ist_regierung %}<span class="v3-pill v3-pill-reg">Regierungsfraktion</span>{% endif %} {% if fs.ist_regierung %}<span class="v3-pill v3-pill-reg">Regierungsfraktion</span>{% endif %}
<span class="v3-fraktion-spacer"></span> </div>
{% for prog_key, prog_label, prog_short in [("wahlprogramm","Wahlprogramm","WP"),("parteiprogramm","Parteiprogramm","PP")] %} <div class="v3-fraktion-progs">
{% set p = fs[prog_key] %} {% for prog_key, prog_label in [("wahlprogramm","Wahlprogramm"),("parteiprogramm","Parteiprogramm")] %}
{% set p_score = p.score | float %} {% set p = fs[prog_key] %}
<details class="v3-prog"> {% set p_score = p.score | float %}
<summary class="v3-prog-pill" title="{{ prog_label }}"> <details class="v3-prog">
<span class="v3-prog-pill-label">{{ prog_short }}</span> <summary class="v3-prog-row">
<span class="v3-prog-score <span class="v3-prog-label">{{ prog_label }}</span>
{% if p_score >= 7 %}good{% elif p_score >= 4 %}mid{% else %}low{% endif %}">{{ "%.0f"|format(p_score) }}/10</span> <span class="v3-prog-spacer"></span>
</summary> <span class="v3-prog-score
<div class="v3-prog-body"> {% if p_score >= 7 %}good{% elif p_score >= 4 %}mid{% else %}low{% endif %}">{{ "%.0f"|format(p_score) }}/10</span>
{% if p.begruendung %}<p class="v3-prog-text"><strong>{{ prog_label }}:</strong> {{ p.begruendung }}</p>{% endif %} </summary>
{% if p.zitate %} <div class="v3-prog-body">
<div class="v3-prog-zitate"> {% if p.begruendung %}<p class="v3-prog-text">{{ p.begruendung }}</p>{% endif %}
{% for z in p.zitate %} {% if p.zitate %}
{{ quote_card(z.text, z.source, True, False, z.pdf_href) }} <div class="v3-prog-zitate">
{% endfor %} {% for z in p.zitate %}
</div> {{ quote_card(z.text, z.source, True, False, z.pdf_href) }}
{% else %} {% endfor %}
<p class="v3-prog-no-zitate">
Keine wörtlich passenden Stellen im {{ prog_label }} gefunden.
Die Bewertung beruht auf inhaltlicher Auslegung — entweder benennt das Programm
das konkrete Thema nicht explizit, oder es bleibt zu allgemein, um wörtlich
zugeordnet zu werden.
</p>
{% endif %}
</div> </div>
</details> {% else %}
{% endfor %} <p class="v3-prog-no-zitate">
Keine wörtlich passenden Stellen im {{ prog_label }} gefunden.
Die Bewertung beruht auf inhaltlicher Auslegung — entweder benennt das Programm
das konkrete Thema nicht explizit, oder es bleibt zu allgemein, um wörtlich
zugeordnet zu werden.
</p>
{% endif %}
</div>
</details>
{% endfor %}
</div> </div>
</div> </div>
{% endif %}{# fraktion nicht in fehlende_programme #} {% endif %}{# fraktion nicht in fehlende_programme #}