Kleinere Befunde und Dokumentation aus dem Review
Frontend, kleinere Befunde: - Das Standort-Menue liess sich nur wischen oder ueber den Kartenmarker oeffnen. Der Griff ist jetzt ein Knopf mit aria-expanded, damit auch per Tastatur erreichbar; der Umschalter Strasse/Satellit hat aria-pressed und ein Label, das den Zustand nennt. - Der Filterschalter "Nur passende Sensoren anzeigen" wirkte nicht, solange eine Auswahlliste offen war: der Klick-Handler ersetzte das Overlay-DOM, bevor das change-Ereignis des Kontrollkaestchens ausgeliefert wurde. Er wird jetzt vor dem Schliessen der Liste behandelt. - Der Theme-Wechsel zeichnete nicht neu, die Leaflet-Kacheln blieben bis zum naechsten Backend-Update im alten Stil - seit der Dauerkarte auf der Uebersicht deutlich sichtbar. - Toter Code entfernt (fahrzeugGlyphPfade, .dot.neutral) und zwei Kommentare berichtigt, die Gegenteiliges behaupteten. Dokumentation: - AGENTS.md widersprach sich an sechs Stellen. Berichtigt: Fahrterkennung laeuft ueber die Zuendung, nicht ueber WLAN; Datenweg ist flespi, nicht MQTT; Modulzahl und Zeilenzahl stimmen wieder; Entity-IDs werden im Setup-Menue zugeordnet, nicht in einstellungen.py; STANDORT_TRACKER ist belegt, nicht leer. - SPECIFICATION.md beschreibt durchgehend den Stand vor der FMM003- Umstellung. Statt es zu Teilen umzuschreiben und dabei Ungenauigkeiten zu riskieren, steht jetzt ein datierter Hinweis am Anfang, der die drei geaenderten Punkte benennt und auf AGENTS.md verweist. Alles Uebrige des Dokuments gilt unveraendert weiter. - INSTALL.md: Die zirkulaere Schrittfolge (Schritt 4 verweist auf 9, Schritt 7 auf 4) ist als solche benannt und aufgeloest. Die Override-Datei ist mit Pfad genannt, samt dem Hinweis, dass sie gesichert wird. Und die drei mit Test-Entitaeten der Entwicklungsinstanz vorbelegten Rollen sind erwaehnt - auf einer frischen Installation zeigen sie ins Leere. - README, Profilvorlage: WLAN-Reste entfernt, zwei Falschaussagen aus dem ersten Review nachgezogen (Statistik rechnet echt, die 97-Prozent-Volltankungsregel wurde entfernt), Dateiuebersicht um die fuenf fehlenden pyscript-Dateien und entitaeten.py ergaenzt. - update.ps1 liefert jetzt auch shell_beleg_parser.py aus. Die Datei liegt in data/, ist aber Code - Aenderungen am Belegleser, dem einzigen getesteten Teil des Projekts, kamen bisher auf keiner Instanz an. - design/README: Zwei Dateien der Inhaltstabelle liegen gar nicht in dem Ordner, weshalb das Board aus der Repo-Kopie heraus leer bleibt - jetzt vermerkt. Ausserdem die Behauptung berichtigt, die Auflage ruehre audi-dashboard-app.js nicht an: der Stylesheet-Loader wurde dort ergaenzt. Geprueft: Panel laedt, alle neun pyscript-Entitaeten werden veroeffentlicht, Zuordnen und Zuruecksetzen funktionieren, keine neuen Fehler im Protokoll.
This commit is contained in:
@@ -93,8 +93,13 @@ Anders als früher wird dafür **nicht** mehr `pyscript/modules/
|
||||
einstellungen.py` von Hand bearbeitet — das übernimmt ein grafisches
|
||||
Setup-Menü direkt in der App: **Mein Audi → Einstellungen → Fahrzeug
|
||||
einrichten → Einrichten → „Setup — Sensoren zuordnen"** (letzter Punkt,
|
||||
erscheint erst nach Klick auf „Einrichten"). Dafür muss die App bereits
|
||||
laufen, siehe Schritt 9 zuerst.
|
||||
erscheint erst nach Klick auf „Einrichten").
|
||||
|
||||
> **Reihenfolge beachten:** Dieser Schritt braucht eine bereits laufende App.
|
||||
> Arbeite deshalb erst die Schritte 5 bis 9 ab (Token, Neustart, Prüfung,
|
||||
> Restarbeiten, Frontend) und komm dann hierher zurück. Schritt 7 verweist
|
||||
> seinerseits auf die hier vorgenommene Zuordnung — das ist kein Widerspruch,
|
||||
> sondern schlicht die Reihenfolge: erst starten, dann zuordnen, dann prüfen.
|
||||
|
||||
Das Setup-Menü listet jede Sensor-Rolle, die die App kennt (Zündung/
|
||||
Fahrterkennung, Kilometerstand, Tankfüllstand, Standort, Batteriespannung,
|
||||
@@ -104,6 +109,16 @@ anzeigen" grenzt auf die erwartete Domäne/Einheit ein) und schreibt die
|
||||
Auswahl direkt in eine Override-Datei — `einstellungen.py` selbst bleibt
|
||||
unverändert.
|
||||
|
||||
Die Override-Datei ist `/config/audi_dashboard/entitaeten.json`. Sie wird von
|
||||
der automatischen Sicherung und vom Backup-Export mit erfasst; ein
|
||||
Wiederherstellen spielt die Zuordnung also mit zurück.
|
||||
|
||||
**Hinweis zu den Vorgabewerten:** Drei Rollen sind in `einstellungen.py` mit
|
||||
den Test-Entitäten der Entwicklungsinstanz vorbelegt (Zündung, Batterie-
|
||||
spannung, Standort — jeweils `*_testzone_fmm003`). Auf einer frischen
|
||||
Installation zeigen sie ins Leere; das Setup-Menü meldet dann „Entität nicht
|
||||
gefunden". Einfach die eigenen Entitäten zuordnen, damit ist es erledigt.
|
||||
|
||||
**Zwingend, damit die Fahrterkennung läuft:**
|
||||
- **Zündung/ACC-Status** (`ZUENDUNG_SENSOR`) — ein `binary_sensor`, `on`
|
||||
= Fahrt läuft. Kommt vom Teltonika FMM003 (z. B.
|
||||
@@ -226,8 +241,9 @@ Der `panel_custom`-Eintrag aus Schritt 3 zeigt auf
|
||||
Prototyp. Das Gerät braucht dafür zusätzlich zur Tailscale-Verbindung
|
||||
normalen Internetzugang — sonst bleibt die Karte auf der Fahrt- und
|
||||
Tankvorgang-Detailseite leer.
|
||||
- **Statistik-Seite** zeigt weiterhin Beispielzahlen aus dem Prototyp,
|
||||
keine echte Auswertung der eigenen Fahrten — eigenes Arbeitspaket.
|
||||
- **Statistik-Seite** wertet die eigenen Fahrten und Tankvorgänge echt aus
|
||||
(Zeiträume, Verbrauch, Tag/Nacht, privat/Arbeitsweg). Sie bleibt nur so
|
||||
lange leer, wie noch keine Fahrten und Tankungen erfasst sind.
|
||||
|
||||
## Schritt 10 — künftige Updates einspielen, ohne die App neu zu bauen
|
||||
|
||||
|
||||
+16
-6
@@ -96,22 +96,26 @@ Datendateien — nie App-Code oder -Konfiguration.
|
||||
`fahrterkennung.py`.
|
||||
- **Bilder fehlen** (§7a) — Ordner `www/bilder/` ist noch leer. Layout
|
||||
springt nicht (Maße sind reserviert), aber die Flächen bleiben leer.
|
||||
- **Statistik-Seite** zeigt weiterhin Beispielzahlen aus dem Prototyp, keine
|
||||
echte Auswertung der erfassten Fahrten.
|
||||
- **Leaflet lädt per CDN**, wie im Prototyp — braucht zusätzlich zu
|
||||
Tailscale echten Internetzugang auf dem Gerät.
|
||||
|
||||
## Was schon funktioniert (getestet)
|
||||
|
||||
- Fahrterkennung über WLAN mit Pausenregel (`task.unique` + `task.sleep`)
|
||||
- Fahrterkennung über den Zündungssensor mit Pausenregel (`task.unique` + `task.sleep`);
|
||||
bis 2026-08-12 lief sie über den WLAN-Sensor des iPhones
|
||||
- Zweistufiger Fahrtabschluss per Recorder-Historie-Screening, inklusive
|
||||
Verkettung direkt anschließender Fahrten
|
||||
- Reifenzähler per direkter Subtraktion, kein `utility_meter`
|
||||
- Belegverarbeitung inklusive 97-%-Volltankungsregel und Duplikatserkennung
|
||||
über `receipt_key`
|
||||
- Belegverarbeitung mit Duplikatserkennung über `receipt_key` (die zunächst
|
||||
geplante 97-%-Volltankungsregel wurde per Änderungswunsch entfernt, siehe
|
||||
Kopfkommentar in `pyscript/belegverarbeitung.py`)
|
||||
- Manuelle Fallback-Wege für Fahrten und Tankvorgänge ohne Beleg
|
||||
- Frontend: Übersicht, Fahrtenliste, Navigation zwischen allen Ansichten,
|
||||
Datenadapter Profil→Oberfläche, Schreibaktionen über `hass.callService`
|
||||
- Statistik-Seite mit echter Auswertung aus Fahrten und Tankvorgängen
|
||||
(Zeiträume, Verbrauch, Tag/Nacht, privat/Arbeitsweg)
|
||||
- Setup-Menü für die Sensor-Zuordnung, inklusive Sicherung in
|
||||
`data/entitaeten.json`
|
||||
|
||||
## Dateiübersicht
|
||||
|
||||
@@ -129,12 +133,18 @@ homeassistant/
|
||||
│ ├── modules/
|
||||
│ │ ├── einstellungen.py zentrale Entity-ID-Konfiguration (Schritt 4)
|
||||
│ │ ├── profil.py Datenzugriff (§6)
|
||||
│ │ ├── entitaeten.py Sensor-Zuordnung aus dem Setup-Menü
|
||||
│ │ ├── fahrtabschluss_logik.py Screening-Logik (§7.2)
|
||||
│ │ └── frontend_veroeffentlichung.py Zustände fürs Frontend (§10 Punkt 7 Ersatz)
|
||||
│ ├── fahrterkennung.py §7.1
|
||||
│ ├── fahrterkennung.py §7.1 (Zündungssensor, früher WLAN)
|
||||
│ ├── fahrtabschluss.py §7.2 (Trigger-Registrierung)
|
||||
│ ├── tankerkennung.py §7.4 (automatische Erkennung am Füllstandsanstieg)
|
||||
│ ├── reifenzaehler.py §7.5
|
||||
│ ├── belegverarbeitung.py §7.4, §7.7
|
||||
│ ├── batterieverlauf.py 12-V-Spannung, Tagesminimum/-maximum
|
||||
│ ├── bilderverwaltung.py Upload/Löschen der Fahrzeugfotos
|
||||
│ ├── backup.py tägliche Sicherung und Wiederherstellung
|
||||
│ ├── updateverwaltung.py Update suchen und installieren
|
||||
│ └── frontend_api.py Lese-/Schreib-Anbindung fürs Frontend
|
||||
├── www/
|
||||
│ ├── audi-dashboard-panel.js Lade-Stub (zeigt configuration.yaml hierher), ändert sich kaum
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"_hinweis": "Vorlage ohne echte Fahrzeug-/Personendaten. Vor der Installation nach fahrzeugprofil.json kopieren und die Platzhalter unten ersetzen (VIN, Kennzeichen, Erstzulassung, HU-Termin, WLAN-Name, Versicherung, Werkstatt, Servicebuch) - am einfachsten über den Button 'Einrichten' in den Einstellungen der App, sobald sie einmal läuft. Diese Datei selbst bleibt bewusst im Repo (siehe .gitignore), die echte fahrzeugprofil.json nicht.",
|
||||
"_hinweis": "Vorlage ohne echte Fahrzeug-/Personendaten. Vor der Installation nach fahrzeugprofil.json kopieren und die Platzhalter unten ersetzen (VIN, Kennzeichen, Erstzulassung, HU-Termin, Versicherung, Werkstatt, Servicebuch) - am einfachsten über den Button 'Einrichten' in den Einstellungen der App, sobald sie einmal läuft. Diese Datei selbst bleibt bewusst im Repo (siehe .gitignore), die echte fahrzeugprofil.json nicht.",
|
||||
|
||||
"fahrzeug": {
|
||||
"fin": "",
|
||||
|
||||
@@ -21,10 +21,16 @@
|
||||
ohne Cache und lädt den eigentlichen Code darüber immer frisch nach
|
||||
(siehe Kopfkommentar in www/audi-dashboard-panel.js).
|
||||
|
||||
Absichtlich NICHT kopiert: data/ - das würde ein bereits laufendes
|
||||
Fahrzeugprofil, die Fahrten- und Tankvorgänge-Archive überschreiben. Die
|
||||
data/-Dateien sind nur die Erstbefüllung für die einmalige Installation
|
||||
(siehe INSTALL.md Schritt 2).
|
||||
Absichtlich NICHT kopiert: die Datenbestände in data/ - das würde ein
|
||||
bereits laufendes Fahrzeugprofil, die Fahrten- und Tankvorgänge-Archive
|
||||
sowie die Sensor-Zuordnung überschreiben. Diese Dateien sind nur die
|
||||
Erstbefüllung für die einmalige Installation (siehe INSTALL.md Schritt 2).
|
||||
|
||||
Eine Ausnahme davon ist shell_beleg_parser.py: die Datei liegt zwar in
|
||||
data/, ist aber Code, kein Datenbestand - belegverarbeitung.py ruft sie
|
||||
als Unterprozess aus /config/audi_dashboard/ auf. Ohne diese Ausnahme
|
||||
käme jede Änderung am Belegleser (dem einzigen getesteten Teil des
|
||||
Projekts) auf keiner Instanz an.
|
||||
|
||||
.PARAMETER Ziel
|
||||
Pfad zum config-Verzeichnis von Home Assistant, z. B. ein per Samba
|
||||
@@ -55,6 +61,13 @@ Copy-Item "$hier\www\audi-dashboard-panel.js" "$Ziel\www\audi-dashboard-panel.js
|
||||
Copy-Item "$hier\www\audi-dashboard.css" "$Ziel\www\audi-dashboard.css" -Force
|
||||
Copy-Item "$hier\www\audi-dashboard-ios.css" "$Ziel\www\audi-dashboard-ios.css" -Force
|
||||
|
||||
# Code, der in data/ liegt (siehe Kopfkommentar) - der Ordner selbst wird
|
||||
# bewusst nicht gespiegelt, diese eine Datei aber schon.
|
||||
if (Test-Path "$Ziel\audi_dashboard") {
|
||||
Copy-Item "$hier\data\shell_beleg_parser.py" "$Ziel\audi_dashboard\shell_beleg_parser.py" -Force
|
||||
Write-Host " Belegleser aktualisiert"
|
||||
}
|
||||
|
||||
if (Test-Path "$hier\www\bilder") {
|
||||
Write-Host "Kopiere www/bilder/ ..." -ForegroundColor Cyan
|
||||
New-Item -ItemType Directory -Force -Path "$Ziel\www\bilder" | Out-Null
|
||||
|
||||
@@ -500,13 +500,6 @@ const STANDORT_PEEK_PX = 96; // sichtbarer Anteil im geschlossenen Zustand, muss
|
||||
|
||||
function standortBekannt() { return CAR.standortLat != null && CAR.standortLon != null; }
|
||||
|
||||
/* Fahrzeug-Symbol im myAudi-Stil: einfaches Top-down-Glyph, noch fuer
|
||||
Vorschauen in Gebrauch; die Kartenmarkierung nutzt poi-car (Audi CI). */
|
||||
function fahrzeugGlyphPfade() {
|
||||
return `<path d="M5 15.3 6.4 9.9a2 2 0 0 1 1.9-1.5h7.4a2 2 0 0 1 1.9 1.5l1.4 5.4"/>
|
||||
<path d="M4.6 15.3h14.8a.9.9 0 0 1 .9.9v1.1a.9.9 0 0 1-.9.9H4.6a.9.9 0 0 1-.9-.9v-1.1a.9.9 0 0 1 .9-.9Z"/>
|
||||
<path d="M7.4 11.4h9.2"/>`;
|
||||
}
|
||||
/* Kartenmarkierung: poi-car aus dem Audi-CI-Satz (assets/icons/poi-car.svg).
|
||||
Die Spitze sitzt unten, deshalb ankert Leaflet am unteren Rand. */
|
||||
function fahrzeugMarkerSVG(px = 34) {
|
||||
@@ -514,12 +507,14 @@ function fahrzeugMarkerSVG(px = 34) {
|
||||
}
|
||||
|
||||
/* Fahrzustand fürs Menü: "fährt" solange die aktuelle Fahrt noch offen ist
|
||||
(siehe fahrterkennung.py), sonst "steht" - erst ab der in "Fahrten
|
||||
zusammenfassen" hinterlegten Pausenzeit (CONFIG.pauseMin) gilt der
|
||||
Stillstand als endgültig genug für "Letzter Parkplatz" statt eines
|
||||
bloßen Zwischenstopps. Ohne echtes Bewegungssignal vom Fahrzeug (siehe
|
||||
AGENTS.md, FMM003/flespi offen) ist das die beste Näherung aus den
|
||||
bereits vorhandenen Fahrtdaten. */
|
||||
(siehe fahrterkennung.py), sonst "steht". Ohne echtes Bewegungssignal vom
|
||||
Fahrzeug (siehe AGENTS.md, FMM003/flespi offen) ist das die beste Näherung
|
||||
aus den bereits vorhandenen Fahrtdaten.
|
||||
|
||||
parkplatz unterscheidet einen endgültigen Stillstand (laenger als die in
|
||||
"Fahrten zusammenfassen" hinterlegte Pausenzeit) von einem blossen
|
||||
Zwischenstopp. Das Feld ist vorbereitet, wird aber derzeit von keiner
|
||||
Ansicht gelesen - eine "Letzter Parkplatz"-Anzeige gibt es noch nicht. */
|
||||
function standortZustand() {
|
||||
const t = TRIPS[0];
|
||||
if (t && t.status === "offen") return { faehrt: true, seitTs: null, parkplatz: false };
|
||||
@@ -812,7 +807,8 @@ function vStandort() {
|
||||
<div class="standort-vollbild">
|
||||
<div id="smap" class="standort-karte"></div>
|
||||
<div class="kartensteuerung">
|
||||
<button type="button" data-standort-layer aria-label="Kartendarstellung wählen">
|
||||
<button type="button" data-standort-layer aria-pressed="${SMAP_STIL === "satellit"}"
|
||||
aria-label="${SMAP_STIL === "satellit" ? "Satellitenansicht, zur Straßenkarte wechseln" : "Straßenkarte, zur Satellitenansicht wechseln"}">
|
||||
${ciSVG(CI.mapLayer, 22)}
|
||||
</button>
|
||||
<button type="button" data-standort-fahrzeug aria-label="Fahrzeug auf der Karte suchen">
|
||||
@@ -827,7 +823,12 @@ function vStandort() {
|
||||
</div>
|
||||
<div class="standortmenu" id="standortmenu">
|
||||
<div class="standortmenu-griffzone">
|
||||
<div class="standortmenu-griff"></div>
|
||||
<!-- Als Knopf, nicht als reines div: sonst laesst sich das Menue
|
||||
ausschliesslich per Wischgeste oder Klick auf den Kartenmarker
|
||||
oeffnen und ist mit Tastatur gar nicht erreichbar. -->
|
||||
<button type="button" class="standortmenu-griff" data-standort-umschalten
|
||||
aria-expanded="${STANDORTMENU_OFFEN}" aria-controls="standortmenu"
|
||||
aria-label="Fahrzeugdetails ${STANDORTMENU_OFFEN ? "einklappen" : "aufklappen"}"></button>
|
||||
<button type="button" class="standortmenu-schliessen" data-standort-schliessen aria-label="Schließen">
|
||||
<svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M5 5l10 10M15 5 5 15"/></svg>
|
||||
</button>
|
||||
@@ -3095,6 +3096,12 @@ function ereignisseVerdrahten() {
|
||||
ROOT.getElementById("theme").addEventListener("click", () => {
|
||||
themeSetzen(HOST.dataset.theme === "nacht" ? "tag" : "nacht");
|
||||
themeIcon();
|
||||
/* Neu zeichnen, damit auch die Leaflet-Kacheln den Stil wechseln: die
|
||||
Kachel-URL wird beim Aufbau aus TILES[theme] gewaehlt und nicht
|
||||
nachtraeglich aktualisiert. Ohne dies blieb die Karte bis zum naechsten
|
||||
Backend-Update im alten Stil - seit der Dauerkarte auf der Uebersicht
|
||||
deutlich sichtbar. */
|
||||
render();
|
||||
});
|
||||
// Wischgeste über Pointer Events (nicht Touch Events), damit dieselbe
|
||||
// Logik auch mit der Maus funktioniert (z. B. beim Testen im Browser).
|
||||
@@ -3316,6 +3323,14 @@ function ereignisseVerdrahten() {
|
||||
// Klick irgendwo sonst im Popup (aber nicht auf den Catcher, der schon
|
||||
// oben behandelt wurde) schließt ein offenes Dropdown, ohne das ganze
|
||||
// Popup zu verlassen.
|
||||
/* Den Filterschalter VOR dem Schliessen der Auswahlliste behandeln.
|
||||
Sonst ersetzt render() unten das Overlay-DOM, bevor das
|
||||
change-Ereignis des Kontrollkaestchens ausgeliefert wird - der
|
||||
Schalter sprang dann beim naechsten Zeichnen einfach zurueck. */
|
||||
if (e.target.closest("[data-setup-nurpassend]") || e.target.closest(".switch")) {
|
||||
const kasten = ROOT.querySelector("[data-setup-nurpassend]");
|
||||
if (kasten) { setupNurPassend = !setupNurPassend; render(); return; }
|
||||
}
|
||||
if (setupSucheOffen && !e.target.closest(".entitaet-combo")) { setupSucheOffen = null; setupSuchtext = ""; render(); return; }
|
||||
return;
|
||||
}
|
||||
@@ -3590,6 +3605,7 @@ function ereignisseVerdrahten() {
|
||||
if (art) { const tr = TRIPS.find((x) => x.trip_id === art.dataset.art); tr.art = tr.art === "arbeitsweg" ? "privat" : "arbeitsweg"; render(); return; }
|
||||
// Standort (Vollbild) - Karten-/Menü-Bedienung manipuliert SMAP/das Menü-
|
||||
// DOM direkt statt über render() (siehe Kopfkommentar Standort-Abschnitt).
|
||||
if (e.target.closest("[data-standort-umschalten]")) { standortMenuUmschalten(); return; }
|
||||
if (e.target.closest("[data-standort-layer]")) { SMAP_STIL = SMAP_STIL === "satellit" ? "strasse" : "satellit"; standortTiles(); return; }
|
||||
if (e.target.closest("[data-standort-fahrzeug]")) { standortAufFahrzeug(); return; }
|
||||
if (e.target.closest("[data-standort-user]")) { standortAufUser(); return; }
|
||||
|
||||
@@ -749,7 +749,19 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
||||
}
|
||||
.standortmenu.offen { transform: translateY(0); }
|
||||
.standortmenu-griffzone { padding: 10px 0 14px; touch-action: none; cursor: grab; position: relative; }
|
||||
.standortmenu-griff { width: 36px; height: 4px; border-radius: 2px; background: var(--line-strong); margin: 0 auto; }
|
||||
/* Der Griff ist jetzt ein Knopf (Tastaturzugang zum Menue). Die Knopf-
|
||||
Voreinstellungen des Browsers werden deshalb zurueckgesetzt; die
|
||||
Trefferflaeche waechst per Pseudo-Element auf 44px, ohne den sichtbaren
|
||||
Strich zu vergroessern. */
|
||||
.standortmenu-griff {
|
||||
position: relative; display: block; width: 36px; height: 4px;
|
||||
border: 0; padding: 0; border-radius: 2px;
|
||||
background: var(--line-strong); margin: 0 auto; cursor: pointer;
|
||||
}
|
||||
.standortmenu-griff::after {
|
||||
content: ""; position: absolute; left: 50%; top: 50%;
|
||||
transform: translate(-50%, -50%); width: 88px; height: 44px;
|
||||
}
|
||||
.standortmenu-schliessen {
|
||||
position: absolute; top: 14px; right: 0; width: 32px; height: 32px; border-radius: 50%;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
@@ -762,7 +774,6 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
||||
.standortmenu-adresse { font-size: 13.5px; color: var(--fg2); margin-top: 20px; }
|
||||
.standortmenu-status { display: flex; align-items: center; gap: 9px; margin-top: 8px; font-size: 13.5px; color: var(--fg2); }
|
||||
.standortmenu-status svg { color: var(--fg3); flex: 0 0 auto; }
|
||||
.dot.neutral { background: var(--fg3); }
|
||||
.standortmenu-werte { display: flex; align-items: center; gap: 10px; margin-top: 8px; font-size: 13.5px; color: var(--fg2); }
|
||||
.standortmenu-werte svg { color: var(--fg3); flex: 0 0 auto; }
|
||||
.standortmenu-aktionen { display: flex; gap: 10px; margin-top: 18px; padding-bottom: 4px; }
|
||||
|
||||
Reference in New Issue
Block a user