diff --git a/AGENTS.md b/AGENTS.md
index dec1760..7ff0546 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,6 +1,8 @@
# AGENTS.md — Project state, review findings, open items, and working rules
-**Last updated: 2026-09-03** (Der Regler stellt den Schlaf-Timeout des Dongles, flespi lesend und
+**Last updated: 2026-09-04** (Geraetezeit statt Ankunftszeit - die Wurzel hinter der 3-km-Fahrt:
+das Fahrtfenster stand in Geraetezeit, der Verlauf war nach Ankunftszeit sortiert. Dazu die neun
+Paritaetsbefunde und die verunreinigte Batteriehistorie, `2026.9.4.1`, Abschnitt CB. Davor: Der Regler stellt den Schlaf-Timeout des Dongles, flespi lesend und
schreibend, die eigene Warteschlange wieder entfallen, `2026.9.3.10`, Abschnitt BZ. Davor: Zugaenge: die Dienste-Token aus App und Panel bedienbar, der Wert kommt nie
zurueck, `2026.9.3.8`, Abschnitt BY. Davor: „Fahrt beenden“ auf Knopfdruck mit vorlaeufigem Ende, Schieberegler in
5-Minuten-Schritten und im Tagmodus sichtbar, `2026.9.3.7`, Abschnitt BX.
@@ -9310,3 +9312,153 @@ performance.getEntriesByType("resource")
gespeicherte Stand stammt von vor dem Filter aus `.11`, und `wunsch_uebernehmen()`
liest zu Recht nicht neu, solange das Ziel schon unterwegs ist. Ein Druck auf
„Jetzt lesen" räumt es weg.
+
+## CB. Device time vs. arrival time — the root cause behind a 3-km trip (2026.9.4.1)
+
+Owner report: the last trip is 3 km long, "and in reality considerably longer". It became the
+longest single investigation of this project, and almost every hypothesis along the way was wrong.
+The findings are recorded in that order on purpose — the wrong turns are the useful part.
+
+### What the device actually did
+
+Nothing wrong. Measured against the recorder, the FMM003 recorded the drive **completely**: 48 GPS
+records in the trip window, first at 23:09:40 in Schottenau/Eichstaett, last at 23:17:48 at Am Anger
+in Adelschlag, largest gap between two records 30 s, and three independent distance measures that
+agree — track 6,758 km, GNSS counter 6,877 km, CAN odometer 7,0 km.
+
+What ended at 23:17:48 was the *supply*: the owner pulled the plug about 40 s after the car came to
+rest at home, with the engine still running (`run_time_since_engine_start` counted 144 to 632 s
+without a break). From then on there was no CAN, hence no RPM, hence — `ignition_detection.source`
+is 8, RPM only — an "ignition off" report 180 s later, which the device could only send at 23:24:27.
+
+**Discarded along the way, each after measuring:** a loose OBD contact (the supply oscillation on
+03.09 was the *vehicle's* own charging behaviour — its `control_module_voltage` swung just as much);
+a vehicle-side power cut (a gateway blocks CAN, not 12 V, and the supply came back *while parked*,
+the opposite of any known behaviour); overcurrent (an FMM003 draws about 0,1 A against a 7,5–15 A
+fuse, and a blown fuse reads 0,00 V, not the observed 1,1 V); a firmware update (the GNSS counter
+ran through the event without a reset, 13,725 to 13,753 to 14,015); deep sleep during the drive.
+
+**The 1,1 V is not the internal battery** — that is a separate AVL element (67, range 3,0–4,2 V)
+which this device does not send at all. It is the residual on a floating input after the plug comes
+out.
+
+### Why nothing arrived for ten minutes — and it was not a radio hole
+
+The device sends no network elements (signal strength, RSRP, cell) in its records, so "radio hole"
+was an assumption, not a finding. flespi's own connection log settled it: the session opened at
+23:12:57 stayed **open for 703 seconds and carried 16 messages**, then closed with `close_code 12` at
+23:24:37 — the same second in which the device opened a new one to a different flespi address, over
+which 35 messages went out in 119 s. The proof that the old session was dead in both directions:
+flespi pushed our own `sleep_mode` setting over it at 23:19:15 and got nothing for 5 1/2 minutes;
+over the fresh connection the same setting was confirmed in 17 seconds. The device kept writing into
+a socket that no longer carried anything, and recovered only because losing external power forced it
+to reinitialise. Pulling the plug is what delivered the data.
+
+`/gw/devices/{id}/logs` is readable with the existing "device configuration" token (telemetry and
+messages are not — 403). **It is the fastest way to tell a coverage problem from a dead session** —
+use it before theorising.
+
+**Confirmed from the device's own `config_24.cfg`** (gzip'd plaintext, `gunzip` reads it), which was
+the configuration running that evening — 1000 Open Link Timeout 60 s, 1001 Response Timeout 30 s,
+1002 Sort by = 1 (Oldest), **1003 Network Ping Timeout = 0, disabled**, and **1004 Acknowledgment
+Type = 0, TCP/IP**. With ACK over TCP/IP the device trusts its own stack instead of an
+application-level answer, so the 30-second Response Timeout never gets anything to act on; with
+Network Ping at 0 there is no independent liveness check either. There was no mechanism that *could*
+have noticed. Recommended to the owner: **ACK Type to AVL** and **Network Ping to 60 s**; 1000 and
+1001 unchanged.
+
+The same file confirms **`400 = 180`** — `ZUENDUNG_NACHLAUF_S = 180` is right, and the earlier doubt
+("maybe 60, from flespi's `ign.stop`") is settled. Independently measured at three clean
+ignition-off events: 183 / 184 / 184 s. Also `11800 = 0`: the trip scenario is switched off in the
+device, so the 900-second `NACHLAUF_S` currently does not exist at all.
+
+### The defect, and it is ours
+
+**The trip window is in device time; the recorder is indexed by arrival time.** Since 2026-09-01
+(section AY) `ts_start`/`ts_end` come from `MELDEZEIT_SENSOR`, while `verlauf._rohverlauf()` stamped
+every point with `zustand.last_updated`. Two clocks — and the device buffers.
+
+Measured lag *during drives*: 02.09. median 4 s (11 % over 60 s); 03.09. evening median 83 s
+(60 % over 60 s, worst 641 s). Over the whole recorder the median is 78 s. This is normal operation
+of a buffering device, not an exception.
+
+Consequences, all from that one cause: 26 of 48 route points stored; 3,0 instead of 7 km; and the
+backlog arriving out of order (the current record first, then the buffer oldest-first), which
+`strecke_aus_zaehler()` correctly read as a counter reset and turned into 9,8 km.
+
+**The fix sits at the one place every consumer passes through.** `verlauf_lesen()` takes an optional
+`meldezeit_id`; with it, every point carries the **device time** of the record it belongs to, and
+`wert_bei()`, `wert_ab()`, `zaehlerstrecke()`, `route_aus_verlauf()`, `hoechstwert_im_fenster()` and
+`naechster_wert()` all work in the same clock as the window. New: `NACHREICHFENSTER` (6 h — the read
+window must extend past `ende`, or the late records are never read at all), `ZUORDNUNG_MAX_S` (1 s;
+a point with no mark in reach keeps its arrival time, which also protects entities of *other*
+integrations), and the pure, testable `geraetezeit_zuordnen()`.
+
+**Second riegel, from the same investigation:** `RUECKSETZ_ANTEIL = 0.5` in `strecke_aus_zaehler()`.
+A backward step only counts as a counter reset if the new value falls far below the old one. The
+real reset went 0,415 to 0; the ordering artefact went 6,891 to 6,848. Reading the latter as a reset
+booked the whole counter as distance — 87 metres became 13,7 km.
+
+**Third: `ts_end` is clamped to the last sign of life.** `_letzter_datensatz()` in
+`fahrterkennung.py`. The nachlauf subtraction is a calculation, not a measurement, and on 03.09 it
+placed the end four minutes after the last record that exists.
+
+**Proven against the real recording**, read-only, with the production functions: CAN odometer 3,0 to
+**7,0 km** (21332 to 21339), GNSS counter 2,952 to **6,877 km**, route 26 to **47 points** with the
+last one in Adelschlag, trip end 23:21:57 (736 s) to **23:17:48** (487 s).
+
+12 regression tests in `tests/verlauf/test_geraetezeit.py`; all 60 backend tests green. Deployed to
+`audi_ha_test`, clean restart, and it immediately gave two trips a distance that had **none** before
+(`t-f5837cd8160b` 6,958 km and `t-98425e4f140e` 6,857 km, both previously rejected as a backward
+jump).
+
+**What it does not do:** repair `t-66c4209276e7`. The screening only ever fills empty fields, so the
+stored 3,0 km and the wrong end stay until someone clears them — the owner's data and their call.
+
+### Tooling note that cost real time
+
+`.replace(/.$/, "")` — an unescaped dot, which strips *any* last character — was in both codebases
+("Gelesen vor 3 Tag."). Fixing it through a Node script written by a quoted heredoc failed silently:
+a doubled backslash in the heredoc arrives single in the JS source and vanishes in the string, so
+search and replacement were identical and the script reported success. **Build a backslash as
+`String.fromCharCode(92)`, or pass the strings through a JSON file, and always verify afterwards
+with `grep -c -F`.**
+
+### Parity findings of 2026-09-03/04, all resolved
+
+Source-level comparison of routes, services, visible strings, map code and tile order. Clean: 24
+routes identical, all 28 services wired on the correct side (`entitaeten_schreiben` is panel-only by
+the parity rule's own carve-out; `screening_jetzt` is called by neither frontend).
+
+1. **`replace(/.$/, "")`** — real bug, both sides (see above).
+2. **Dongle tile wording** — the app said "15 ist unterwegs zum Geraet" and "wir rechnen mit 15", the
+ panel "-> 15, unterwegs" and "(wir: 15)". Aligned to the panel; `Wertzeile` gained a `warnung`
+ prop so a deviating value is coloured `var(--warn)` as it is in the panel.
+3. **"Zugaenge" tile** sat tenth in the app, second in the panel. Moved.
+4. **Einzelbeleg map** — the app drew the generic black start dot with a "Start" tooltip. Now the CI
+ `poi` pin with its silhouette (verbatim from the panel), a popup with station name and address,
+ and the centre button; new `.dm-kartenbox`, `.dm-kartensteuerung--klein`, `.dm-nadel`.
+5. **Einzelfahrt map** — `bindTooltip("Start")` became `bindPopup("Start · " + address)` as in the
+ panel. A tooltip is practically invisible on a phone, and the address is the point.
+6. **Einzelfahrt row order** — Verbrauch moved behind Hoechstgeschwindigkeit.
+7. **PDF rejection** — "Bitte den Beleg als PDF auswaehlen." to "Nur PDF-Belege werden unterstuetzt".
+8. **Token dialog** — "Token fuer Gitea loeschen?" to "Token loeschen?"; footnote aligned.
+9. **"Fahrt beenden"** in the panel had no loading state, unlike its own dongle button. Now
+ `FAHRTENDE_LAEUFT` with "Wird beendet ...", the same mechanism.
+
+Still open, unchanged: `.dm-fussnote` across 35 sites; `Versicherung.tsx`'s sub-screens never
+individually re-verified; the unreproduced map-layer icon report; the unreproduced "Batteriespannung
+row not clickable on desktop".
+
+### Battery history is contaminated by bench measurements
+
+Found while clarifying that the 12,2 V after the drive was the owner's desk power supply.
+`batterie.py` only checks 10–15,5 V, and a power supply at 12,2 V passes. Checked every stored daily
+minimum against whether the vehicle was reporting over CAN within plus/minus 5 minutes: **3 of 16
+days pass, 13 do not** — including 2026-09-03 (12,149 V at 23:56, the desk). These values feed the
+resting voltage, the SOC, the SOH trend and the fallback shown in "Mein Audi / Zustand".
+
+**Not built, proposed:** require a fresh CAN value near the voltage reading before recording it —
+the same mechanism as `wert_in_naehe()` with its 300 s window for the outside temperature. Without a
+vehicle, nothing gets recorded. The 13 existing entries are the owner's data; removal is via the
+swipe gesture in the measurement list.
diff --git a/companion-app/src/screens/Einstellungen.tsx b/companion-app/src/screens/Einstellungen.tsx
index 3495bab..004ae24 100644
--- a/companion-app/src/screens/Einstellungen.tsx
+++ b/companion-app/src/screens/Einstellungen.tsx
@@ -396,6 +396,66 @@ export function Einstellungen({
+ {zugaenge.length > 0 && (
+
+ Zugänge
+ {/* Aufklappbar, weil die Token im Alltag nichts zu suchen haben —
+ man fasst sie an, wenn einer abgelaufen ist, und sonst nie. */}
+ {zugaenge.map((z) => (
+
+ {z.gesetzt ? (z.rest ? `gesetzt · …${z.rest}` : "gesetzt") : "nicht gesetzt"}
+
+ }
+ >
+
}
+
+ Ein gespeicherter Token wird nie wieder angezeigt — nur ob einer hinterlegt ist.
+ Dieselben Felder gibt es unter Einstellungen → Geräte &
+ Dienste → Audi Dashboard → Konfigurieren.
+
+
+ )}
+
Fahrt beenden
@@ -448,7 +509,7 @@ export function Einstellungen({
{dongle.stand?.gelesen_am
// Der Punkt der Abkürzung ist zugleich der Satzpunkt - sonst
// stünde dort "vor 1 Std..".
- ? `Gelesen ${standAlter(dongle.stand.gelesen_am).replace(/.$/, "")}. `
+ ? `Gelesen ${standAlter(dongle.stand.gelesen_am).replace(/\.$/, "")}. `
: "Noch nicht gelesen. "}
Der Regler oben schreibt den Schlaf-Timeout sofort hierher; bis das Gerät sich
das nächste Mal meldet, steht die Änderung als „unterwegs" daneben.
@@ -744,65 +805,6 @@ export function Einstellungen({
)}
- {zugaenge.length > 0 && (
-
- Zugänge
- {/* Aufklappbar, weil die Token im Alltag nichts zu suchen haben —
- man fasst sie an, wenn einer abgelaufen ist, und sonst nie. */}
- {zugaenge.map((z) => (
-
- {z.gesetzt ? (z.rest ? `gesetzt · …${z.rest}` : "gesetzt") : "nicht gesetzt"}
-
- }
- >
-
+ )
}
diff --git a/companion-app/src/screens/TankDetail.tsx b/companion-app/src/screens/TankDetail.tsx
index 677c9f8..50bfec7 100644
--- a/companion-app/src/screens/TankDetail.tsx
+++ b/companion-app/src/screens/TankDetail.tsx
@@ -69,7 +69,7 @@ export function TankDetail({ id, geheZu }: { id: string | undefined; geheZu: (na
return (
<>
-
+
@@ -367,7 +367,7 @@ function BelegKnopf({
const hochladen = async (datei: File) => {
setzeMeldung(null)
if (datei.type !== "application/pdf" && !datei.name.toLowerCase().endsWith(".pdf")) {
- setzeMeldung({ art: "fehler", text: "Bitte den Beleg als PDF auswählen." })
+ setzeMeldung({ art: "fehler", text: "Nur PDF-Belege werden unterstützt" })
return
}
setzeLaeuft(true)
diff --git a/companion-app/src/screens/Tanken.tsx b/companion-app/src/screens/Tanken.tsx
index b17d9d5..d9e5d70 100644
--- a/companion-app/src/screens/Tanken.tsx
+++ b/companion-app/src/screens/Tanken.tsx
@@ -223,7 +223,7 @@ function TankFormular({
const belegLesen = async (datei: File) => {
setzeFehler(null)
if (datei.type !== "application/pdf" && !datei.name.toLowerCase().endsWith(".pdf")) {
- setzeFehler("Bitte den Beleg als PDF auswählen.")
+ setzeFehler("Nur PDF-Belege werden unterstützt")
return
}
setzeBelegLaeuft(true)
diff --git a/companion-app/src/screens/TankstellenKarte.tsx b/companion-app/src/screens/TankstellenKarte.tsx
index ad38de4..080fc26 100644
--- a/companion-app/src/screens/TankstellenKarte.tsx
+++ b/companion-app/src/screens/TankstellenKarte.tsx
@@ -15,7 +15,13 @@ import type { Koordinate } from "../daten/geokodierung"
import { Leerzustand } from "./bausteine"
import { Karte } from "./Karte"
-export function TankstellenKarte({ adresse }: { adresse: string | null | undefined }) {
+export function TankstellenKarte({
+ name,
+ adresse,
+}: {
+ name?: string | null | undefined
+ adresse: string | null | undefined
+}) {
const [position, setzePosition] = useState(null)
const [geprueft, setzeGeprueft] = useState(false)
@@ -32,7 +38,10 @@ export function TankstellenKarte({ adresse }: { adresse: string | null | undefin
}
}, [adresse])
- if (position) return
+ // Wie im Panel (tankstelleAufKarteZeigen): die CI-Nadel mit Name und
+ // Anschrift im Popup, dazu der Knopf, der wieder darauf zentriert.
+ if (position)
+ return
// Solange die Auflösung läuft: eine leere Kartenfläche, wie im Panel (die
// Karte steht dort schon, die Nadel kommt nach). Bewusst nicht die
// Ladeanzeige der Seite - die meldet „der Bildschirm ist noch nicht da".
diff --git a/companion-app/src/screens/bausteine.tsx b/companion-app/src/screens/bausteine.tsx
index 4417671..f111e99 100644
--- a/companion-app/src/screens/bausteine.tsx
+++ b/companion-app/src/screens/bausteine.tsx
@@ -256,6 +256,7 @@ export function Wertzeile({
wert,
zusatz,
hinweis,
+ warnung,
}: {
label: ReactNode
wert: ReactNode
@@ -264,11 +265,20 @@ export function Wertzeile({
Angabe - fuer Zeilen, deren rechte Seite nur beschreibt, was hinter der
Kachel liegt, statt selbst ein Messwert zu sein. */
hinweis?: boolean
+ /** Hebt den Wert als abweichend hervor (var(--warn)), wie das Panel es bei
+ einem Dongle-Wert tut, der nicht zu unserer Einstellung passt. */
+ warnung?: boolean
}) {
return (
{label}
-
+
{wert}
{zusatz && {zusatz}}
diff --git a/companion-app/src/stile/screens.css b/companion-app/src/stile/screens.css
index a5cb9f6..c16b73c 100644
--- a/companion-app/src/stile/screens.css
+++ b/companion-app/src/stile/screens.css
@@ -1696,6 +1696,30 @@ button.dm-listenzeile {
transform: scale(0.94);
}
+/* Karte mit eigener Bedienung darauf (Einzelbeleg). Der Kasten traegt die
+ Positionierung, damit der Knopf sich an DIESER Karte ausrichtet und nicht am
+ naechsten Vorfahren weiter oben - dieselbe Ueberlegung wie .mapbox im Panel. */
+.dm-kartenbox {
+ position: relative;
+ border-radius: var(--r-tile);
+ overflow: hidden;
+}
+/* Kleine Variante: die Belegkarte ist nur gut 200px hoch, ein 48er-Knopf mit
+ 16px Abstand verdeckte davon ein Viertel. */
+.dm-kartensteuerung--klein {
+ top: 10px;
+ right: 10px;
+}
+.dm-kartensteuerung--klein button {
+ width: 36px;
+ height: 36px;
+}
+/* Die CI-Nadel traegt ihre Farben selbst; der Schatten hebt sie von den
+ Kartenkacheln ab, wie .fahrzeug-pin im Panel. */
+.dm-nadel {
+ filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
+}
+
.dm-standortmenu {
position: absolute;
z-index: 410;
@@ -1995,3 +2019,8 @@ button.dm-listenzeile {
.dm-token-gesetzt { color: var(--ok); }
.dm-token-offen { color: var(--fg3); }
+
+/* Abweichender Wert - im Panel steht er in var(--warn), hier ebenso. */
+.dm-wertzeile__warnung {
+ color: var(--warn);
+}
diff --git a/custom_components/audi_dashboard/fahrterkennung.py b/custom_components/audi_dashboard/fahrterkennung.py
index 1f35bbc..8713c8f 100644
--- a/custom_components/audi_dashboard/fahrterkennung.py
+++ b/custom_components/audi_dashboard/fahrterkennung.py
@@ -31,6 +31,7 @@ from .verlauf import (
MINDESTDAUER_S,
fahrtsignal,
geraetezeit,
+ geraetezeit_plausibel,
verlauf_lesen,
zeit_normalisiert,
)
@@ -180,6 +181,34 @@ def leere_fahrt(
+async def _letzter_datensatz(
+ k: Koordinator, start_ts: datetime.datetime, bis: datetime.datetime
+) -> datetime.datetime | None:
+ """Der letzte Datensatz, den das Geraet im Fenster [start_ts, bis]
+ geschrieben hat - in seiner eigenen Zeit.
+
+ Der Meldezeit-Sensor traegt als WERT die Geraetezeit; hier ist also nichts
+ umzustempeln, der Wert ist die Antwort. Gelesen wird bis jetzt, weil ein
+ Datensatz aus dem Fenster erst Minuten spaeter ankommen kann (siehe
+ verlauf.NACHREICHFENSTER)."""
+ sensor = k.zuordnung.werte.MELDEZEIT_SENSOR
+ if not sensor:
+ return None
+ jetzt = datetime.datetime.now(datetime.UTC)
+ reihe = await verlauf_lesen(k.hass, sensor, start_ts, max(jetzt, bis))
+ letzter: datetime.datetime | None = None
+ for _ts, wert in reihe:
+ try:
+ gemeldet = datetime.datetime.fromtimestamp(float(wert), datetime.UTC)
+ except (TypeError, ValueError, OSError, OverflowError):
+ continue
+ if not geraetezeit_plausibel(gemeldet, jetzt):
+ continue
+ if start_ts < gemeldet <= bis and (letzter is None or gemeldet > letzter):
+ letzter = gemeldet
+ return letzter
+
+
async def _echtes_ende(
k: Koordinator,
start_ts: datetime.datetime,
@@ -220,6 +249,27 @@ async def _echtes_ende(
return start_ts
if ueber_trip:
await _nachlauf_gegenpruefen(k, start_ts, signal_ende, gerechnet)
+
+ # Nie hinter dem letzten Lebenszeichen des Geraets.
+ #
+ # Der Nachlauf ist eine Rechnung, kein Messwert: er unterstellt, dass die
+ # gemeldete Zuendung wirklich eine verzoegerte Zuendung war. Am 03.09.2026
+ # war sie das nicht - der Dongle war um 23:17:48 stromlos (Stecker
+ # gezogen), meldete deshalb ZUENDUNG_NACHLAUF_S spaeter mangels Drehzahl
+ # -aus- und konnte den Datensatz erst um 23:24:27 absetzen. Abzueglich der
+ # 180 s ergab das ein Fahrtende um 23:21:57 - vier Minuten nach dem
+ # letzten Datensatz, den es ueberhaupt gibt. Das Auto stand da laengst.
+ #
+ # Was wir wissen koennen, endet beim letzten Datensatz. Alles danach waere
+ # erfunden, und eine erfundene Zahl ist schlechter als eine knappe.
+ letzter = await _letzter_datensatz(k, start_ts, gerechnet)
+ if letzter is not None and letzter < gerechnet:
+ _LOGGER.info(
+ "Fahrtende auf %s geklemmt - danach hat das Geraet nichts mehr "
+ "gemeldet (gerechnet waere %s gewesen)",
+ letzter.isoformat(), gerechnet.isoformat(),
+ )
+ return letzter
return gerechnet
@@ -244,7 +294,9 @@ async def _nachlauf_gegenpruefen(
sensor = k.zuordnung.werte.ZUENDUNG_SENSOR
if not sensor or sensor == fahrtsignal(k.zuordnung.werte):
return
- punkte = await verlauf_lesen(k.hass, sensor, start_ts, signal_ende)
+ punkte = await verlauf_lesen(
+ k.hass, sensor, start_ts, signal_ende, k.zuordnung.werte.MELDEZEIT_SENSOR
+ )
aus = [ts for ts, wert in punkte if wert == "off"]
if not aus:
return
@@ -724,7 +776,9 @@ async def _letztes_lebenszeichen(
Kilometerstände ohnehin nach.
"""
jetzt = datetime.datetime.now(datetime.UTC)
- punkte = await verlauf_lesen(k.hass, sensor, seit, jetzt)
+ punkte = await verlauf_lesen(
+ k.hass, sensor, seit, jetzt, k.zuordnung.werte.MELDEZEIT_SENSOR
+ )
if punkte:
return punkte[-1][0]
diff --git a/custom_components/audi_dashboard/frontend/app/bundle.json b/custom_components/audi_dashboard/frontend/app/bundle.json
index 288f6e8..060fcba 100644
--- a/custom_components/audi_dashboard/frontend/app/bundle.json
+++ b/custom_components/audi_dashboard/frontend/app/bundle.json
@@ -1 +1 @@
-{"version":"2026.9.3.15","sha256":"00c71560c2cd991fa145a79a8d475a6cc4359eaa39342056f406bd3c2ee272c5","bytes":269191,"gebaut":"2026-09-03T19:21:06Z"}
\ No newline at end of file
+{"version":"2026.9.4.1","sha256":"473807fbe06bc94882a3b53fa76d167a64a15d9470c0a6f993c7042a8bf009b6","bytes":270085,"gebaut":"2026-09-04T00:09:13Z"}
\ No newline at end of file
diff --git a/custom_components/audi_dashboard/frontend/app/bundle.zip b/custom_components/audi_dashboard/frontend/app/bundle.zip
index 290bae8..793d380 100644
Binary files a/custom_components/audi_dashboard/frontend/app/bundle.zip and b/custom_components/audi_dashboard/frontend/app/bundle.zip differ
diff --git a/custom_components/audi_dashboard/frontend/audi-dashboard-app.js b/custom_components/audi_dashboard/frontend/audi-dashboard-app.js
index 4e85cd1..d37c469 100644
--- a/custom_components/audi_dashboard/frontend/audi-dashboard-app.js
+++ b/custom_components/audi_dashboard/frontend/audi-dashboard-app.js
@@ -1624,7 +1624,9 @@ function teaser() {
weder Strecke noch Verbrauch. Ein Strich behauptete, ein Wert fehle -
richtig ist, dass es ihn noch nicht gibt. */""}
Aktuelle Fahrtläuft
-