Kachelueberschriften bekommen Luft, Profil raeumt ausgemusterte Felder auf

Der Abstand zwischen Kachelueberschrift und erster Inhaltszeile war 0, 10 oder
12px, je nachdem ob das folgende Element einen eigenen oberen Rand mitbrachte.
Bei 0 klebte die Ueberschrift an der Zeile und las sich als deren Beischrift.
Jetzt einheitlich 14px, gesetzt am Kopf selbst - benachbarte Raender fallen
zusammen, vorhandene 10/12 werden also angehoben statt addiert, und absolut
gesetzte Nachbarn wie das Zahnrad bleiben unberuehrt. Nur die erste
Beschriftung einer Kachel: .label/.ads-eyebrow tragen auch Inhaltszeilen wie
die Anschrift des Autohauses, die bleiben unveraendert.

Der urspruengliche Auftrag lautete "Panel wie App setzen" und beruhte auf einer
Falschaussage von mir: ich hatte die 10px-Grossschrift aus dem Design-System
gelesen statt die App zu messen. Die App ueberschreibt sie dort absichtlich auf
den Panel-Wert; beide waren laengst identisch.

Dazu: _profil_aufraeumen() entfernt ausgemusterte Profilfelder einmalig beim
Start, Anlass ist fahrzeug.hauptuntersuchung_faellig. Ohne das bliebe der tote
Schluessel fuer immer stehen, weil beide Oberflaechen das Profil vollstaendig
zurueckschreiben. An der Testinstanz geprueft, einschliesslich zweitem Start
ohne Schreibvorgang.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-05 02:36:16 +02:00
parent e9c16325cc
commit ddcd9396b0
7 changed files with 150 additions and 2 deletions
+66
View File
@@ -11598,3 +11598,69 @@ Der eigentliche Grund auf der **realen** Instanz ist ein anderer und heute
zuerst gefunden worden: dort wurden ueberhaupt keine Fahrten erkannt, weil die
Erkennung still das Trip-Signal des Dongles bevorzugte, das nie ankam. Ohne
Fahrten kein Radstand.
## CT. Kachelueberschriften: der Abstand war das Problem, nicht die Schrift (2026.9.5.11)
Auftrag: *"Kachelueberschriften im Panel wie in der App setzen"*. Der Auftrag
beruhte auf einer Falschaussage von mir - ich hatte behauptet, die App setze
dort 10px in Grossschrift mit 0.2em Sperrung. Das steht so im **Design-System**,
das die App an dieser Stelle aber absichtlich ueberschreibt. Live gemessen sind
beide identisch:
| | Panel `.label` | App `.ads-eyebrow` |
|---|---|---|
| Groesse | 13px | 13px |
| Gewicht | 400 | 400 |
| Farbe | rgb(142,142,147) | rgb(142,142,147) |
| Grossschrift | nein | nein |
| Sperrung | 0.13px | 0.13px |
`companion-app/src/stile/audi-schrift.css` traegt die Begruendung seit dem
29.08.2026: die App soll optisch moeglichst identisch zum Panel sein. "Panel wie
App" waere also folgenlos geblieben. **Lehre: die gerenderte Oberflaeche messen,
nicht die Quelle des Pakets lesen** - dieselbe Verwechslung wie beim
Ringe-Fehlalarm in Abschnitt CS, am selben Tag.
### Was tatsaechlich fehlte
Der Abstand zwischen Ueberschrift und erster Inhaltszeile haengt davon ab, ob
das folgende Element zufaellig einen eigenen oberen Rand mitbringt. Gemessen
ueber fuenf Seiten: **0px, 10px, 12px** - je nach Kachel. Bei 0px klebt die
Ueberschrift an der ersten Zeile und liest sich als deren Beischrift.
Der Rand sitzt jetzt an der Ueberschrift selbst, nicht am folgenden Element:
.tile > .label:first-child { margin-bottom: 14px }
.ads-tile > .ads-eyebrow:first-child { margin-bottom: 14px }
Drei Gruende fuer genau diese Bauweise:
* `.tile`/`.ads-tile` sind normale Blockcontainer - benachbarte Raender fallen
zusammen. Vorhandene 10 oder 12px werden dadurch auf 14 **angehoben statt
addiert**. Ein `+ *`-Selektor haette sie addiert.
* Absolut gesetzte Nachbarn (Zahnrad, Chevron) stehen nicht im Fluss und
bleiben unberuehrt. Ein `margin-top` auf ihnen haette das Zahnrad erneut aus
der Ecke geschoben - genau der Fehler aus Abschnitt CS.
* `:first-child` trifft nur die Ueberschrift. `.label`/`.ads-eyebrow` tragen
auch Inhaltszeilen (die Anschrift des Autohauses), und die bleiben wie sie
sind - Entscheidung des Eigentuemers.
Nachgemessen: alle Kachelkoepfe auf beiden Seiten bei 14px, Anschrift
unveraendert 13px, Zahnrad weiter bei 8/8.
### Einmalige Bereinigung des Profils
Auf Wunsch des Eigentuemers entfernt `_profil_aufraeumen()` in `koordinator.py`
ausgemusterte Profilfelder beim Start - Anlass ist
`fahrzeug.hauptuntersuchung_faellig` aus Abschnitt CR. Ohne das bliebe der tote
Schluessel fuer immer stehen: beide Oberflaechen lesen das Profil, aendern
einzelne Felder und schreiben es vollstaendig zurueck, unbekannte Schluessel
ueberleben das also.
Geschrieben wird nur, wenn wirklich etwas wegfaellt. An der Testinstanz
geprueft: Schluessel gesetzt, Neustart, Logzeile *"Ausgemusterte Profilfelder
entfernt: fahrzeug.hauptuntersuchung_faellig"*, Schluessel weg - und beim
zweiten Neustart keine Meldung und kein Schreibvorgang.
Weitere ausgemusterte Felder gehoeren in `AUSGEMUSTERTE_PROFILFELDER`, nicht in
neuen Sondercode.
+20
View File
@@ -522,6 +522,26 @@ button.dm-serviceblock:active {
.dm-serviceblock > .ads-fig {
margin-top: 8px;
}
.dm-servicefig svg {
color: var(--fg2);
flex: none;
}
/* `.zahnrad` im Panel: rechts oben in der Kachel, 44px Trefferfläche,
17px Symbol. */
/* Luft unter der Kachelueberschrift.
Der Abstand zur ersten Inhaltszeile haengt heute davon ab, ob das
folgende Element zufaellig einen eigenen oberen Rand mitbringt - am
05.09.2026 gemessen: 0px, 10px oder 12px, quer durch die Kacheln. Wo er
0 war, klebte die Ueberschrift an der ersten Zeile und las sich als deren
Beischrift statt als Titel (gemeldet: "Anstehende Termine" wirkte, als
gehoere es zu Oelwechsel).
Der Rand steht bewusst an der UEBERSCHRIFT, nicht am folgenden Element:
.ads-tile ist ein normaler Blockcontainer, benachbarte Raender fallen
also zusammen. Vorhandene 10 oder 12px werden dadurch auf 14 angehoben
statt addiert, und absolut gesetzte Nachbarn - Zahnrad, Chevron - bleiben
unberuehrt, weil sie gar nicht im Fluss stehen.
Nur die ERSTE Beschriftung einer Kachel: .ads-eyebrow traegt auch
Inhaltszeilen wie die Anschrift des Autohauses, und die sollen bleiben,
@@ -1 +1 @@
{"version":"2026.9.5.10","sha256":"6bdd14f277d1d3f6f2c24dc0ab660f2751daac8fc71efdb14440df87fe7a5af6","bytes":324448,"gebaut":"2026-09-05T00:22:21Z"}
{"version":"2026.9.5.11","sha256":"66b5170e70ed6879bea70b44bebef30a04b6f0a7ea3d072bd32b7cc0c1c9e412","bytes":324454,"gebaut":"2026-09-05T00:34:25Z"}
@@ -345,6 +345,26 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
.zahnrad:hover { background: var(--tile-2); color: var(--fg); }
.zahnrad:active { background: var(--tile-2); color: var(--fg); transform: scale(.92); }
.zahnrad svg { width: 17px; height: 17px; }
/* Luft unter der Kachelueberschrift.
Der Abstand zur ersten Inhaltszeile haengt heute davon ab, ob das
folgende Element zufaellig einen eigenen oberen Rand mitbringt - am
05.09.2026 gemessen: 0px, 10px oder 12px, quer durch die Kacheln. Wo er
0 war, klebte die Ueberschrift an der ersten Zeile und las sich als deren
Beischrift statt als Titel (gemeldet: "Anstehende Termine" wirkte, als
gehoere es zu Oelwechsel).
Der Rand steht bewusst an der UEBERSCHRIFT, nicht am folgenden Element:
.tile ist ein normaler Blockcontainer, benachbarte Raender fallen
also zusammen. Vorhandene 10 oder 12px werden dadurch auf 14 angehoben
statt addiert, und absolut gesetzte Nachbarn - Zahnrad, Chevron - bleiben
unberuehrt, weil sie gar nicht im Fluss stehen.
Nur die ERSTE Beschriftung einer Kachel: .label traegt auch
Inhaltszeilen wie die Anschrift des Autohauses, und die sollen bleiben,
wie sie sind (Entscheidung des Eigentuemers, 05.09.2026). */
.tile > .label:first-child { margin-bottom: 14px; }
/* Titelzeile nie unter dem Zahnrad/Chevron hindurchlaufen lassen - und die
Zeile hoch genug für die 44px-Trefferfläche des Zahnrads machen. Ohne die
Mindesthöhe ragte es in den Kachelinhalt und lag auf dem ersten Knopf
@@ -93,6 +93,15 @@ from .zuordnung import Zuordnung
_LOGGER = logging.getLogger(__name__)
# Profilfelder, die es einmal gab und die niemand mehr liest.
#
# Sie einfach stehenzulassen ist keine Loesung: beide Oberflaechen lesen das
# Profil, aendern einzelne Felder und schreiben es vollstaendig zurueck -
# unbekannte Schluessel ueberleben das fuer immer. Siehe _profil_aufraeumen().
AUSGEMUSTERTE_PROFILFELDER: dict[str, tuple[str, ...]] = {
"fahrzeug": ("hauptuntersuchung_faellig",),
}
# Wie weit zurück nach dem letzten Zündungswechsel gesucht wird, wenn der
# Parkbeginn nach einem Neustart fehlt. Sieben Tage decken jede realistische
# Standzeit ab und bleiben eine Abfrage, die der recorder in einem Rutsch
@@ -191,6 +200,7 @@ class Koordinator:
"Fahrzeug einrichten eingetragen."
)
await self.zuordnung.anwenden()
await self._profil_aufraeumen()
await self._laufzeit_laden()
# Die "Zustand"-Kachel soll die zuletzt gemessene Batteriespannung
# auch direkt nach einem Neustart zeigen, nicht erst "unbekannt" bis
@@ -213,6 +223,38 @@ class Koordinator:
async_at_started(self.hass, self._nach_start)
)
async def _profil_aufraeumen(self) -> None:
"""Entfernt ausgemusterte Felder einmalig aus dem Fahrzeugprofil.
Beide Oberflächen lesen das Profil, ändern darin einzelne Felder und
schreiben es vollständig zurück - unbekannte Schlüssel überleben das
also für immer. Ein ausgemustertes Feld bliebe damit in jeder
Profildatei stehen, obwohl es niemand mehr liest.
`hauptuntersuchung_faellig` ist der Anlass (Abschnitt CR in
AGENTS.md): es hatte in keiner Oberfläche ein Eingabefeld und im
Backend kein Schema, überstimmte von dort aber die Ableitung der
Hauptuntersuchung. Seit 2026.9.5.3 liest es niemand mehr.
Geschrieben wird nur, wenn wirklich etwas wegfällt - sonst wäre das
bei jedem Start ein Schreibvorgang ohne Änderung."""
profil = await self.ablage.profil_lesen()
if profil is None:
return
entfernt: list[str] = []
for bereich, felder in AUSGEMUSTERTE_PROFILFELDER.items():
teil = profil.get(bereich)
if not isinstance(teil, dict):
continue
for feld in felder:
if feld in teil:
teil.pop(feld)
entfernt.append(bereich + "." + feld)
if not entfernt:
return
await self.ablage.profil_schreiben(profil)
_LOGGER.info("Ausgemusterte Profilfelder entfernt: %s", ", ".join(entfernt))
async def _nach_start(self, _hass: HomeAssistant) -> None:
await fahrterkennung.nach_neustart_fortsetzen(self)
await self._parkbeginn_nachholen()
@@ -1,7 +1,7 @@
{
"domain": "audi_dashboard",
"name": "Audi Dashboard",
"version": "2026.9.5.10",
"version": "2026.9.5.11",
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
"codeowners": [