e1d570992e
Drei zusammengehörige Teile in einem Repository: - homeassistant/ Das fertige, im Einsatz befindliche Home-Assistant-Panel (panel_custom Custom Element + pyscript-Backend). Echte Fahrzeug- und Personendaten (fahrzeugprofil.json, fahrten.jsonl, tankvorgaenge.jsonl, Tankbelege) bleiben per .gitignore außen vor; die anonymisierte Vorlage fahrzeugprofil.example.json ist mit dabei. - design-system/ Eigenständige React-Komponentenbibliothek (@audi-dash/ui), die die visuelle Sprache des Panels nachbildet - ohne Audi-Markenzeichen und ohne die lizenzierte Hausschrift. Dient als Grundlage für Claude Design. War bis hierher ein eigenes Repository und ist in dieses eingeschmolzen worden. - companion-app/ Datenschicht der neuen App DataMetric360 (iOS/Android via Capacitor, zusätzlich als Iframe im HA-Dashboard). Noch ohne Oberfläche: REST- und WebSocket-Zugriff auf Home Assistant plus Warteschlange für Änderungen ohne Netz. Ersetzt das eingespritzte hass-Objekt, das nur innerhalb des HA-Frontends existiert. Dazu die Projektdokumentation: SPECIFICATION.md (Ist-Stand des Panels), COMPANION_APP_ARCHITECTURE.md (Architekturentscheidungen der neuen App), AUDIT_2026-08-10.md, DESIGN_BRIEF_DATAMETRIC360.md und der ursprüngliche Bauauftrag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1946 lines
184 KiB
HTML
1946 lines
184 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de" data-theme="nacht">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>RS 4 Avant — Oberflächenmuster</title>
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css">
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
|
||
<style>
|
||
@font-face{font-family:"Audi Type";src:url(data:font/woff2;base64,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) format("woff2");font-weight:400;font-style:normal;font-display:swap}
|
||
@font-face{font-family:"Audi Type Wide";src:url(data:font/woff2;base64,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) format("woff2");font-weight:300;font-style:normal;font-display:swap}
|
||
@font-face{font-family:"Audi Type Extended";src:url(data:font/woff2;base64,d09GMgABAAAAADyIABEAAAAAe5wAADwoAAQHrgAAAAAAAAAAAAAAAAAAAAAAAAAAG54SHDYGYBaXOgCCcghgCYMeERAKgaV0gZYQATYCJAODdAuCAgAEIAWEcAcgDIUbG4pxVQdqcB6CEGj5F29kINg4BGIEW1HUYkmqSfD/x+PGGFiAXf0sNmw22ZRudNMKux+Ed5MhiXVctUnlEkJqwbh44YjXPZ1Sg4eUcj+kkW/6UikyPt7YmvSIzeetPRzVd+OnP+XV1WAQY3Om9fxoarRxBo7zUXP9aK73zWxy2YQ/AJAqACpkV4kKhaxQFarC1P3eDtC8Tv3zaioeMzVTw9RsLGyTm5mY3pieqXjdb6KmPxnvRT/+vefft29f6bN4/vn9/vdjnfuuH0QzHopEsyh2SeYVj2Kh0EQzNBIlEylV/t9z2LHEKJK59yGb1ldAXa+Bq1tNorEltWTZnjGNR8ZF7/LsPwIMwsuyS2JH6QXJ7eSaFly+9SNARZj/3FUN7IQpbNJvco4hYYMDPFzTEj9wn/uXJnwDVKlwQz3lJj2QdnTvfhm5/2eSgtBVFbLGULaZbbYAPMncsVuSRwSO6MOR6rsAGJwX04RLpeQdQHz+86gUwH8BCvJAnq/mWYsFjDVYx7SUKxU7sGBGG8pIRtXZ8P9/Nq3SavVAL8vj53laYltHEM/4MFqg6MJLgupfv7q6uoSGGcFC2z5oD8ry7huNtaCWbJlm5ghJlgfkRQ3uMWCQHQfhpTFgfByk6REz7nxAb4EPgLIIPAl0LQm2soiqeHuzLHRL7nokOF1ERIZsD3nvYzT/RzqWoGe/yB+HbWXxO1+jWCZGRCFZll+//SMIYCnXSjvY60YDVC9nJsUBqteTWLGA6h1GSjygSgPgbnF2eycpHhBlFqgahrznVSpdX5ZPQPa6R12d/DTiGTFh1rJzBdCIvAjEJcVJlCRFsRKVGg3x4s2XiLSU0NrAtEFSKWktjxYwbRC69OgzAGUIxpjtkZD0wGSFxiHhhC5y0hKO2SFQDpyhR8zQB35qz5Bql+28gWmDRN3s0qPPAJQhGGO2rYDmlBC8x0COKVnjY3mdodBFlVq1GnKCAIMQLVurNu2I5OkhEVtTieyQCYks+arUdEk8KseqjU+tfXKwRTDKLpRrx4zAZBGuVyIqF5f0Nk0IZzuzWbgVMh2YWeZnNoxk/FoB5blLMPZJQp4XnP4lDNZh6wsdWaB2Qmq6P5c0fvvUrmVXWfx+K2qblm1qZENKzDSkphQIOnJyVB250cO9oQRVyggfuSo1lJ3kcJP2zgvlEtkuJzDgdsMRis/uFu1VJrON6q16MduC2ZsdzjuQwPaoJAGvSMmZz/BggILR6MTSFv9/+Q8vuNU13W6Wc6eGjdrkFcT66oeMc7jcRoFxQE2iqmcKFKz2ITp2VXi7ohuUjPIns5uc3R2W7dCyiJMn6waUWqAWsaiMbnZSUs1OVktG0SuP6EbcKes9Gf5VJmz1aNZr3mhnGq/loe6VknvZrd0Ov8xc82zc9sop38Z+W+m21EFZWAys46/kLgQmf+1HCZl2qCq47UYw51GDb496X9xkhyx5SMCU7Vevj4PUo1Jj9tdwdKioDDhDXAkXZYeWAznQ1oacmsasJkpO06Yz3+KXPhjTft6nlYWM3UfPOACTaqiWJ6+PTcOutLEdrnsXVEX7pegwlSNmGb2C6ppU3dcQXrlVCsPeTvP7JBcQYpU94Qw/yu28O+uZNAVQ9ZBvOtzOaTfKTluGCnFV0LTuW5X1p73r1bpG7yIK9sxAZxj2OMXjFxGH6lZJ5bsVi0ffqXrm91V1MV8r0q1K0qZcx+oHgff7hLK48DZKzLijc8CtH6KbuyEXk95UTrVNBxdwaAmov3paQA/TzIeN/Os+hEgmjcsTEiGVlC1XrHzFEpQqlapCvTSNWuRphwczisLMVEgLNKVl0lSILkFOtywTSj267KAQg5K6xZLF5nD1074gl0fKzCWjftqA6I4xgHg4OlaceD1hJZAoubeAbDBdqrR2BzKAyjxpiGclSaILqulUvOKppaIz8lEeXeMRtPcorOszBGLIydPESAktrUyTKRG1GJWYZOxWpp+hNksSOzwgjnPM7HE8x1QE0RGPTDvrYq8IAz6YJCQOcCEjLZxt4Yvy/wn/v013uHHLYiwi2zoDwHksDW687im8YhNVchsDNJHHQC6ptnOljFqbrgPorrIuXONTRLQh4LJskFeokjjKcxgwKkZVZNxRvYLWSIBFLE6ANEHW4oOKQs1SUSkbQNWlHV7K6IzGhIxFNLYzPnmlal1H11moU5JduugNemA/2NutCAC8q9wV42P56YlSkG3d0JhdFled9WbC3Rq+S+AAAtI3NklAD6G8ZMXIYKfLPhJyp83NphOxdXGhhvzI4XM/RHMlJfMvpdlaDrCC4mzwuVf+SpduUjzS/IFK8kemyIokJ4q86ClIfisWJXGUxX8VCfnFtpXbKuRKxapM/uvSqLWa7SR/XQEdAuyRUckvKxwj8EnJjyqaAiQIQOCwvEmhCIbi2IS8ZFEkTc2Sp10cNpczTx5+CfhCDovkHpcEVgq3TG6EQkRAQpyzXF2KK5dz4851HtdcyIXCgyfyqHL2KjRU3rzmIyff4scHne/85RhQAvkLErBgOYSUUMEYQsaUfVgJx8QSJkL4ImUXVaJFihG1WNnGFbZY8eLGkU1CScSRJGHJsk4pqZKlSVm6rDJKpnRZMpYty0MlR/blynNo+a8sCkqhPEXyVyx/SSlVpEzxyuWrKJXKVClftbw1pVaVOtWrl6ehNKrTpH6H5W4uXE1aHNaqeW1ytZcOrTq1rUvO7tKjE0/XeuXoK/14BvRuUPahMmzAEYM7KtuxctwRJxzdSVlHyqgTxzfm5MYHWU6VCXynjW1S5qkybcKM05uVaa7Mm7ZgZosyLpVl885Y2IoMq2XNsrPO7Jz06+W8NRvOuuDcNqXbKhdtuOTCtqW9XK646KpLuybN9XLDFTdd3Y7Ut8ptN9xxc3elulfuu+2BO9uV8mF55P499sSDPZ2leFaee+SFx3sp+avy2jNvPN9byd6VPa+893ofJP1YPll8tu6LJF/LN4fvzv2Q+Gf55fHb649vfyX6Vz2r4MD6D/z93WP3duxsNKFFKypbtFp9zymXThMo06ADWQiWeLmG8U1Zs+Oex5567SPwDfijlWudADf9/w/pyjXqRMEQgbNSu6ntzn+hZXr9C1IJagUAqHMAdSpj6YgDKBTAXPhggvtt/94+eAYIKEeGQ5iXZuAiz6KPKHnmh3zSIxinZYSGdAgvNPSTIfL4+kMgZMq7IVmSFAShBEWJFnOM/2udKEmyFKlmuPMRwJOmbDny5KtVr0GjJi1atcPAwsHz5cZPIFnH2EuXIVOuAoWKzFhw3yeBGWWRDZHIj6KooLprrr54Xvsoj/DkR2wqqJriVl+N13rt1ueu5xRGMJWLuhMAVPzHA/9/HHiCQMWcC96DUTH4ArxXQtwy5X9MtNF3AOg6ZWykpeUUjefT0ArNkoYZ9VoEPtftpfpB6FqVIeEcjkUErShGOF/o3psDhazKXzXlA7CFFqa9FtGyLm0B5jvS1R4Vseh0OzXwchGpLugqxV6tGHR6DK/V3wVAjwOhKVerEoKv/F2I2KFlF58xFxAxXLVq6E358R/U+AD9tbJeFwLm56udb8bp/Z0s391pAaBZytHlc92e1J1/bIKdnzlqFb3TlKCr+Tp4YyM+4LTg01AaM6BKO7pTpmomM/TYlYWg6c/n9hREAEDnyx/GHgTKT/r7TcfA5w3lNL8xIrA/aUxPYGALfjMPgLCtHwZo5YID9Kthi3tqvSf9RW0mlwEQwWAJGPl/GuBcvQkQedHe+wlI2gEYv235LiB1OQAAnP/H7enoCiYt7vDtyf8WSyjhzhpAUFwsOgTEttJ32YWVJ+MCUbJW9PNr+Rie4nJgdOuD4ZeK8ZooeJdFId76oi50EU6nebQeh+gLc+QPVWR7F9zzzp1c65+7pRClSKbPy7ZqcydffLdcBkPNtbnYXG8rERc1h8Hah/un3+v1Ueyausv+0rXVtDe7zxGdXtT6vMoLWcGM4uGnVvi+EEp57kgh9FI8N3NDIOhhKGyASMholGAoqCvGiJhaWsMUoIdKjgYtIDySdMwl4vt3MhaEx1HXtvflHUultJXTXDCokJaQsiAo6w6cxwjiBKjSiBJAnAkiUn7uvf5N4SKtIfehlCbPIygU+HoC9N498FW8gLCkWOBdE9R21jtworXOm0dSog5S9x3OzghQjVwaVNhFBokandb8ZCA1dDVgttkrAE5LXuyL0xLD5LsJjsIATaE9x6FOhqmqTyI6w7UmcWeikxEeReAV6HZsY2MH3wHCpIMKsDlDMSU3o8Vlrl4snIUyvTkqpxKdqeQzUyp5klw/k+lCjl/V9C+5ULHf7+V6CNdevfqgdxAAIzTvjpykS4e7o+yC1lzlXPrbcEsg1sEXjKAdplLr8vJCbWyqDRYQ2MzJyj8czEISGadQv+KqDEefhjlD0IcNPsBBbszmmB1k0VsyfY5mP6wpmIcFvdquTr1DKlZiEUgPCFjYcsLiXBbWKjbC7Qy5YsJzWAbxQHEBLsvTXmTAydcH0sL6u5kS1jRZbHdvjj4Q4GaZXqB3ndGxSHF0H0gsIAMsbqR/67awb9+X5ZIAMADl+GkrWZ1ftrmqosM0Ak8Z00pGGVdWYLn1BlshPioJ1zr/Po8wDcrz/1MCN/fZh0ECLnur5cMwAR132Ds8+zIdd9qexbJNyV6SRxzFnoOXKLKD9GB2vAE/eMcUjpL7Pn7+9OluA1LmNq5hBaiKTin4Knio8B5YJiRzTzlsMK07hqEegw3fUCFOKzm7nh6xH1iNZ2q26IUB+mTSLRWcM+zmndAJpr3dvx8WyExp4ujICMBInpbtVi+58dw9BOodLub+8WEsWaI6gxNnJhboFgVqzyIBiUC/1U3GRSKCjCmcXMW5rOYNnrq22btp90+2sf3U5m5lHZ/w4oYyyrtGNgAwbnt0PrQknNiE03bLLorbKCJNStaHfXYz2dkVSi2zQLAoZZuxv/z+WJZTw1+kTMvpaN0DN1gSD1GOFxr0+B9icg8q9eFCCBN/FOeJfaQvhIm8S0e6k/snZyP8PpyIfZjz60EQ1EZx3CIYLcpqZFBeEV6lnD7fuH8WiKzUkdtEgOtowIxpxqdbxifO5JmDz2TUbRmcNxEBJg6/pARYmkjmUj0nNhEoaL0YxF7/+cpGHzyUbq1OeC+r6R8vnkzL1TBLqy2YK9+ecNNjlgilaHR3ZGhhZOBUVnNj+awmIwKNv9QBOta01h3iSztWFN2XanCa0DOcxeHIJoq7fpQNfCYuPnR7deSgLkg20ICRz8kAj4JVGPrk8eeRlQ7pxL1UZKJ+yBosxlmHHQ8WYhcq160RAk7SlrtG0jblrvPlnQ3GZLUU7oW8WJeS0rrPJlX91d7zxD4h3oxJ7zseqP7b91G0Rdu5VLr2NxcRWYhwZaenJ5Ixkak+SDee9/UK7lMaY/1LUSCYPi1Qk0mGBjUUSrZQYwGE6RVyPpsVIhTHhOPRif0hr9/7zRWfE7a0pFHWXP3ULtMaykrGfEk4ZCs2XmcmVQKR83ntJ7zI8W4rlRjTAmcm6hzg+Db3J5ms0ieLaT7ydYi4KlevbzZmCRBQpxDrwSxqA8DSysIJzlDkfkkKE4Nh0WLr35Zs5zJMIaiSfW8qplPNB/JnofN5PRkbMTKpM248N5yu5jKMvtPnT0MuFArjcMf1JtwCBRmKwGEGgey42Xn33v4q5tkoZBttKfLjssl2+c6ByVLfMJZ0hJTKhANLMKxqgUMBr0VJO/Rwe1a+zWHZGt+UAm+ObPEuAvn0oJKg/dmc8aQpeCM0UkuAVOkAsXZ/YQtlBP20fJwF0Rtwf9tTEyGu5Ql3+dqWV9aLOZ3vGgyg/6LBPpxKJRXff3L8UAPTMT31+H8I7HcdWnWdXFj/t9vdwLdb/d9fbGlA6OGKJ+WlcUTKB+WV04/y8nf8zeVJ/+320R3hiY53RH2bmxcuboemGM5lFLUTZtjdfn9OrP6rdqe3G37U6zHXdZCFvLnRqyL/xmyGnJeK64lKZvHPpmrazyrcEJJJnvN6kmgqnFGzzcuM5K2HQPTnOJEJ8O0wT0jbo1tt0mTU2CqZfdjtpq7kd8ezkeXVpGtl/9PnehtICpRBDjK6YLOttS3OPFcQEDhi8GcHm1X8gE8A5W9OVN7z+adbWSei9gg6A8cpRoe5aJw3fQH+K2OPEef2NtxMIJs0vtrmCVCNhoRrbgjVc3ArT8SzND17ndtRUL9nao+aw+hTCgKryKjY9elU27dPGfnvkBhxbl/KMsDwS3kIgFa7WA8Bpi/rAyDr9SEtH2D6puUDfePVYBwFYPplg7JF3wMvgwkfkIpP9/rwnIdwoR4apvPl/cOyBMexi15pXW6PwCrv3eZS81uwt5oMZKX0niLJUCY5zvCtzZ7WK8mY9yfD4qf0hLYdOImb444KOVem6/foEINjNSlZssl/+pS89xfCoAQ4HKZKmTgLSa8HlG5A+hCb3D6lG2q9upqM+njswctd3aSDG9xn6m8FH8mTadnm16/73zPIFO1F0b14RlmhPQdLsPFRQVzKuk6uPikt1G55I2UFy3wRy6Ls8Nf3gpCByLgD92aontSjNPwnW79nNOVmWh99/Hqmx9AsHsDwvSb7Ounl1iCge7opUUJSkq7Q6NqMuMtt1j2vFmBvbUWW33sHTnlTbBtC0i2X5rJYdwgX+fjlqUMjOusv2uj9acKUHRf7VPcR0nKi3SUmH/65NMhk8M7jajGsDnceH1nifgb267+5FFJf5X5niqHb3BJV4rYIMLn4CpgmT6GJoILHExM7ZV/oAkai+UVmr1nnOnp2OPLI45MoovSfhaW/LRW+3tl9kyOL1MOIc3nHpo3t3kaO1CQNW8+EbHEwG1+VTniwM83Pg+SeUvucK1EK+KaOHEG5TzY3w7p7Ap90hvgOzGfo4684Mf7aGkf5ZDiMaD/+I3u5x/2qpRuMIOUbeFI7IFtNWCuajMnddyv0ZD0tTchX6jcfTWhwDipzfHx64pZsKn++tOKXd1+yVDNV8kipwCjPVaxuZ3tYNBPlPiGT5UsusrAkfICHQ/NGr/jgJX2FbaMVhc+u8w+nnKWObbm0/HerG6FdXPq1+hif+hk6WG8zmqAFnzM/+Au+4UjRZpJ9NK+iPplKH2w+ogF+7TgRkJWMLnMPIFcMpwjEjqFyDJ/5rrF4mQltqIWM1SWH8Ec/su2OGhz8ZX4B66LDIHtB1lBPTcRU2xu/aZ5HtvhGcCxK3L1xhZ3J/zhzDpWmnwLOh3emxh62mc3I9X52dO0/zzNhEEUxrOKOaQEMv3nTGFRffB1NmAd9gA+DER8i5rkFS7jnJQYiVAlvOb/7WuvSfVrrSmqByj2u+d5nThYKY0efJMdp3ty0R14a+Odtn/ZOofXSoPXOJ9FRRBLDCg3p4PYp3jqsWHnwFIqaykNRw29Vf6ly5a7a6/3m9kpH5Ummi1Ik08iplh7k1ECb4hrJW9Xi6aJ08QS0Py2LFBVCqt8uiuV2Sb54AWoXC5NpZ/OcY+N53mXXepMCrSTMUivXDyaXHkTnqOPsGytxKOSTTN3wZ6esbjzZBl/b1MG5VejgXHANJc44rNc2OMZbmApPx6+rPQ0xYHms6bOYrJU1Jgv/NEQ4Jd1GHh/c7WiD6xH9mZQAMPy4IICJ6/7xKxMEMHw7zQB8IWXD2Xo04DzmISS7RRR9J/l4f+oW6n3JSqjXlJrYA3J7o+fzyFsHtyymnPD67rXkhGJNRb51rYj/lOYp5HGau6Wi8BpGvc+YrzEF8uEqWnyKXG+v3XL/2zoQ9mWmdz/Zw1Gcy5UTVnA2P+61hLwM5nRLoO8kDfcnrtu9yFsPC5jTlHhE6aih7HLuqm+aj+Pw+qRKCic/oPmYzyR40p7vTbZQFD6D0egyPqkxKxVSL2v5KepCV+MVT5HujqDXE51iZF+qGbxTCv0omd+fueHwumA9ym9FQ37Xp62B8iBgVn5Ep82sKsi8vMGApz4o7d6sYP4x/By3dsP9T2t/xIf5HjGPfptE0UTpBEW2ejRYjkGw7YBNaq6D7AtBErq51jG7kMxvYxhbqmum4w4EHZnPD5sRm1xkZf0Hz4X+ED6gb/cncWuw9qa7cOsoDd0HevcA3plIu9ksafOUNVVXcNLpXAxMlAWKUomSzKgH9kvs64/+fmFIhzZf/E3puckNHMOISQ40Xcfehr6XFfoeOnLQ435j+1XDIkY+AMYoxMSdni3+5UJVvgV4mhnUWS1Mgw+shDGfBPaCqlRTwJe9dbU4qodky8Vc6+869uVyZnQy1JjkIDTF9LVPDf1KgPV3FGoYhkJ+2294Eo0TrdyN5lzvWP/SrFm1s/ncNPrXZs1myRlx3GcNdQec0SKKvBN3vD11AXUvczWUNqUidpfc0uhhRF9t578/A+g7U8Fiwo+ClsGzDmP+7jbyKTEy64d/ClvXFIWiw2H3Zhr3OycY09tFsQnR6kTQOexj3Xz2jsYqZjg8s8ppgoOQTZdxVPIW5Cpef/ZUMsAoyqepI+iWYSFrE7KCOR1EtlVPgzaTzKIQXD0bhLKea27uItdODdJw7CYpyKTPpjq4QTfBxZdDakbPaSXoDD+ZT0xT+/XDgIy1psoFnz0Dz239uQ6Jmg9RLZ9vARbNMcFh3Q4slEOTJ6nJ8Uk5FOe1LpO83kw/b5YwbBkfZl1Lh0tGGcI2EhuNVHIc410NJSCsz84yFmY0EfIBZ5CLt4UxVTFUJknMwCwKYf3IGTkWfpn41qD00BfoTZ8TpYgAstvlgr/BBogj8Tc1VjFDHAdl0mV1p+HRvWwjxSjv5ouoiH3HcNttIY6MARzlsmVyxBnMRJA7mZwiCvuYZeqH+aHiSH8IP43A/8leOVl0FfexcCOUdkr+33VkbYLz1vAuHjev+GW5EznSlr2O+1rfHfl3ha8YPDp0ktbs819cevo+2PpP9ldcbMaDN3D3dFPDxpeV6G2VM8Yn0Xgdmc93m5PsqupPD955+SeI5kcoC7aXNZIC35OLySyoWS4lovmj520WhQi0tMK69OWvBD+3LDOL3Rch6S/3hhkA9QYFi4eLWNS8x56Nai+oVXlW02xuz4fn/D74wmwD7Qym6+HV5hG3DV+qJgUsHhhX6zZNJeLD8bbutAb8RWSu5pKZdvxqKXMwKod8rq5lI+YLXkmzxX9M4qhSt1alforxFF2PoLFgfcfwnUoafUiyQSPTzAdv6m9r6+7d4LSFzDu4BNdmI/p7ObowaGuo/SVbHm+jQTFR2iYriBYGfhyO22sW13lMmIjKrcAdCYvHTee0j+XeYf0nV2nkqovE9GCk69ePJ2wXdAS86x17kCHioq3ZHLejeF5/xBqj6a03ztLmqGco5koXiuJcBsX6Nbh2SUxcLQtrX1BT/Kr8pLP4I3eFhZgj+hKhsxlhhwPpQYXHvN9DG4fBtHdzkwbIa/Bfz2qS1KeFTxt1gGpaJKaC0ZNyX6gfJcjaaGPfYOtaVQauWCxXNk2VEmwXayKmd6z1I3I4nT6egZBNlnGUxwePB+aa3SbaHQ/dILzUK2Zf11h06A1LrcCOcWxkMmVxSt6CzYprz76DQo0iKfWN/pegudEbkEXHkQA3G/UhY66eAcIGo1CO4IKcsiTwypUxhHCKrmoKezb9WqQNItNe2Q/RKI4IFCPJ1MeQOSmsoRbSO6BC7GzYfifpqhiCOzGrfo6hFMK2GcqIzAOppbkSWbmd1IxOlEh1aoqTDsHA4v2mN/EaknUtgR2aMEwFuR9WNyxWWa8qW7D2XxBn0MRfNYBipJ801DQYMdFsdf+Kl+gb+ZfOsksjclX131DoWuKjKuFtAvs161pca0dE4cr9tYlL5c8CRUzcjJQReQmAp0LW4EPmZSAIXaoFuKtmse4GfAAIhvj7dSrFmh06R/WOGfTLE6Wa9GcjPXh/sO53OIY7iu5AFGv2n7z/zk6y7rOEqUkzKQsdg5iObGGlRpLZ0BQMAZ1Z5/va/ATjmeJ3o//YLCNWSBT0Ee6j6X/V0rJv+tddT8RnVWOPMg653Sidnuq5Xv0iO8Va+Geinem0Feofik73DDYTrbylJ8RhcD02KSMyv7Cso9bHeXuUpjymBu5OmUTtJwlDk8859Rk9A0TvPL3tlquq4k613OXOqXp0cPFO8d/wqgZILs0iXryqwtkaHwBg5/tQAGnQYGLdM4h5hb697vFN+DWBNKS6HghCV1MAWdvezJcZ/XFrgY9we7pfMwD2reXjYtlWeD/x0Yju4USqjLWjVOJ6b9I1oSTNNzavKA9DN+NHkfhwPdWMSUHOqN2Wbmf2xZ0NfIjb0/2GWst6YSRGWd06hBPgAhOnd8ZWHSvG+HfGBZZZtXCrgOq9Ev23u8Dc3CIxh3kMmuNDLPbXlnCZBUFyCo6ouwX6xB52/liHjVb2cnCIU6JJh7kqejrk00Jj8CWGvbKMGvw7QWqmsp8tMkSOIB1GUaI4ZYX4Ztq4SVENQxtZuuIuc9IQZMG8um6kiLuctT7+HSOwp1bQc5XQ9eCjFCm4zOAOIC/9gPoYMhu0LzixwNeisBUi4XzQtLp70PwP7dnKXtJebkrH5HkxYnBvL4FmQ3trD2OrfuIQ8iRPSYqou7A2zFMKhm4Vw0kVG0SPOf8VKfQ3mZYN7Hps4GxCgGNiT11+2bP6sOrEG6zVFyhZmiJGFoYUM2CaRQnSKVD2X9KpAd1kStGfIgh1NiaaYmJOH6AJJxVIaO0UVLRvaIxPpquj1jjJ3dxbLQAebjsYXd4Yw6du2Ozo7II4bRBFcegHuwjtYFOO1jP4B+2/MhXBy9Lj2p2WKSRsCNLCxoWDHrCK1ehZzdC+GN5c5DUQHuQ6VFB/PCvUzA8bcZwVbjsUXdYYy/fcsAW++IizYvOy46pD2q1QvGKwOUcTfNE/mXINPN9ZR81fexH7e08am1JDXOuwoWqja9kkJSOMdgrFj27OtDQy9Roesqrg5uauJ0FPv4DXXWlALNdRdaAzUA4XCO8PbIQEPKEFHYZnOYf70p294EaWXlCsqzlbDusGoth0uFezUrN9mk19A5tGW1m+/hrtubKIk8G5KWeGP24bvRgNh4lijfczJONlEndzV475i9k1TbSMhzPeMeZvyxq1TjlliXjZB3zHhrdQ28z1/19BxDrC3xXZmEXu1jWeJKzF1AY+buevF90MumFPlw2GdsZxSlG84Brmx9Nrgi0OkWmW28RBsRNyJ9S6IKVGot56GVWGbVq9yl2gpv3owyI6D/B8ZnY2poHKCh88n2rkeD4rFAjCfZGbcGrxdT0URjmkO2xXKCYvDPvjlAoH9XflDRsa/HHZjKopcON6JaUtf6nM8IiqMGNecs5+fvuQ3rHTvshBkb0t05pY5+2QcypzRkOox6g008hw0LUuJW+hCnRotkUIvhpSSSyKTq1mnCRc0t8ruxzme0ZGZTO2bAYLmOnH7dzIsZVsb/hmcD0oexIjJcCYGA8Fct/I3ANvmgZpMCzIqrOGl9R3pVJRirmjjwl2dzPjjz0WCbs83yTlTVNsvnah9jtJCiLsN3Ey4O8nUkHj62ZTZfr/gqf9y2dbd2N/2JQWLJqWUjyjbHCYk+yLHm9hQqrUYbV+yw5XvKncmtNMo2HPwUFpj7KfxreCxqtz55ze1lb7XR2oeUXspETo+gzqN7vmsAOqLI6ExqG3Ek/xmldjHyKzhhez0Zu7GapCLAGnokPpeLZeHpFuX8NilFiQhhY5sXWD1Szmc60baAY/7+op1nDuQvFHDKhu1SqDHTyIviMte4/Uked1d+ZaPcRqz50rfoeR+t+grPjQAce7crIPSF253rPYdhnXvfILi4MvckRpqjD9poFgzdUbsOytdhnnvdILcwNPc4RpKjDdJjZ0y/tUQRM/+oGdnovLBIn/WCm5xqRddNDEXxS9zMes4XCNE7X+oif2Bq50jbZUNoU0mNeRwj0aBxmA6XixgMpf0x+4LGhMZLDeLuanqZRa3Ukt2AvaSFZyp90i+5DTK+7Lt+/dhMY1QQOnelOXAYZv1zJAoPDgwwiwhPV9IlkvyCVI46rDRwtFrd7S3+r3kFMBhTmkHmZC6PhSjhZ2OTzIhRZzR/mSzWl6eb7HsXhOFHc86JVBQdIfuX3QfY5ZRqzAWIOnmE9GAkoVzzIYkqebAN7ZMJHJjf+1nYahOkOc7DbCSkY59cvA5a9DTqmH0eHZ2nXJHwAGuXl9agnyYgobRCbM13bJ9O8qyi881058kZvgn0O1tHOJoLkiM5Bhro7weuhBkPlLDFmHQfbWvG3/3URKrfqUGeQHbiEkPx1TQw71b+/OvhX0B6dgrKwmcyBLs+ReAQAw/KLMAJlTxMb9ejqqNvspz6MWCsq7XWbZLSFCM9fl+iM4M7aU4AT4pKOj+KFrpxtfuiv3PXfjNSbeQEvtI2ymVfWSnpT9kr2vOQ8jKkX4usmP6a6r3pfOXKRjTA8JTV153XnQbCCW+CZBxB2s3zuogXzHnm3Ln8PeSptlW6x8lphApTPtRPZ5NIMgf/FvmBx05758/GYO+M6Mvs+xpGfg684zSeX9HtdLc8O25hqkyG78Y6gsLYDp184DgnDcduoPS3oo/F60jXrklbqKk7i1mFr/Jy1ja8VXQ6+i/WSD9FqjY4vteME1IR/H1/61ICOTLbePGsC/BazmlbYRxkKGIkVW15Wr+IZ++hOchpaAlewCv72RS8LHfDKGsbvYXjXYe48FdlGxE9czLnL6ZjnJ/SFcK/S920JsUaFTc9NzN6tIFH1W6SUq7VN98QqH6XfsdI4ScbF+pPenppLVnzNHJrMVCf7EBHjZb9n7mnOGROUILzeFMZ11tfvSWefCCJalgmubvxvNoCNxLh9SxSkG0KFBDbu9mJnm/NPYy4mn2bCVtxJ8VDLDdmrSEaONF9iFV5ewjRbfh9lKquwhyT970iwD+Y/bYyaiwcIMxOYhWb5Sjyc+17zuNM0u7/TYKswIW5mrlHRx8fy6ztsfOD8Y+aSs2vVL2YWF7mdsYZuqSn86b+PrhHHQp1u3gpQYSSmB8QL9LErCAupNAv8ES8P87y211oqoAxqtxMSoiC+a6QLL74LWsSM722+4d+NUh9+W0A7v7pO4gzjhk56EXnvFrwW8+ey2IdtSzJU8ajDP9G1iayAPCHJlAIAOC3pHMJUBAAwX+kNAf2z8w98GFGqiTvjgY6MZBE4xJuGV/+/xvBkcTjr77mj/rZjfChWLDBeKSBL0Njia0ooP9a/YLwx+ZDxt9ZZuQqvV7dceV5+QGxEnD6scfGp7gpoSiTxE9AoqHI8XZPabJ0MeuJ8LGI7PrMAfiU5zvlQzslW9n2WPPi1auEArPFO6/xP4stGw5Rzd3A182faj4X6lwta/6hcQLeRwlnkWAaHr70JOJLbilrDJkDyD154X/AeiUwscesIyXXYOT9/lgtkRuOuiZVdp5WZRyS+vG5A9eUwoBSneeg1yFvp3c/fHPSc3II8IxY46LiyQS9a/prGq/6ik8VrvKpSwJaSfRKVei0SQgwQorCb1dSDhsaWOwS4HnVLtce9Hjw98PY+hLgefUuzx7EEn8dzlV69V5QN0h6plQD4lueoyEIyuv4z1VZ5ejFsTjUzQMXYRFhXTTbu+4bwmIep22DjuumiErrjTZuDpzY9fsdfhI/UACQpx8oivHw1VI8r68L7+u5c4eWPgwCc/HImjwW3ECZwR3uieLx9Hqg8QjxcPMFANT56VfPV27rVuYvfmwweBMpo+PfYD5l5Zjb6v2ofA1jKyNfETsRIeT+d6ZuswrciOJCuCDtTYWXPTlCanrxERtFzUfMKf43nofKQ12YFoTWAd7prTLCDqDYubT9KtTWNzFrO6Fklj3Uv5Qy9p2f7jPH4bMVLrT9UkiuDF7lnbbinTxDFaVHGSpoqJwXcXPbpymUDxq37DD67mllg1LwusYaSLB9OasyxImjSC9cAAw+WBJMDzI3Sr+fG6nZ520nPVdtLzA7+TXqgvrZc6Wz2n9UoH1fNPes6jtvMdD8F0pF7derHT0WtbL9V2tJWQQt1f/GBVDHZWgvS9nxKGAkC6iznCewDnscchmtpergtanwYlsJtlvjj/QHLyDqumm5OI/u5Z07C/LDIAsLfZq8s0mAwEkvM2wFCxs7Q23Nz7+9tRoIgxkJIoPjdqbsjGeFyaQKkJtAg4d2CUER0EAdPM6v2YpDf1vlIKMj7Em7yb5IbI8Tuwf+c5PXt42hjQ1qD2m3HUiJr75uecx01T03pu6MacVdCbsaZLh6RpaV07TBI/mWhtJ9SB2Ml+HLFE9rdWHSEYe37rN+loPh5Pzx4Wew8nJ2sDUmiUZWMQkxuJadPTxbxCBmtQMQKHwPe8YgUQxblBkhnQhELStvOyPKHJQOrZlCU9LaWE49/5956BLw0ic29+Njw2xqfCgPqAjaxlgfGor1TAhPQPDIduGwAvGQB11j0jgXwiLuNI9htDPfQBDx7OqpRlQnrUc7BoNetvBRxAPf677TYmXAvp87Qv9Mlu3DrsdnozlxdApF/dV7IEh4hNbvJRGewpjehA7+lfUxFQyiTMZkaMLc22+GLDczAahirJpIOwnDlwYmAsLN+PSkTqsc8ES8fO3/52x9wyAQFbrc67iJwycuoMaOTBCnyOqvKZK2mZg3Pm77Qw63MzRQHHUHnuO8vSkJOTcG4SCfGNIS9I0iOOc2Ed0pRmfAphc5bRzCFnIJAjrACP79mO3Ni+UTMlVTULt4pJKh0UyBIK5oIBeX6Si8jlkNzOTZ6UYua5SzOalcgjGgpoa0t41ugSRojcGF1OS4bQGy05xhKnFJ8y6QFtOVtuSWDEDkxJXCH41P8cAyGNLKGMg7bKNJGIHy0DzHGnGvE0ogV5NxW0g7PXVqsGZZy3KgyS3KcGkpSmMrnEroKX5AVNU4fMsxnJQIZtqWtzRe3GF5frk+3JJ+tPNOK1Rn9E7Lb56dU3h8vh7Xa+Gw/fHDt9tJvPawz9216ox25X/5sKeugG7VyFA4ulcSS+56/cZZSM10fzN4S3WoepQTsY0LB1w2iXzU23KmdFqNa0o3mNJGuQqt1Panp459Br269yfo8lQPtiCFcU53pHTy5It9JYr08MFumCjDWUgpE3WZALr+/lKrXU4+OqzFq5Bykxw8grf1gBB8NbrgyIdCAiPk9SUs0dlNKUWg1irpub3W8cUdLZoQE/jdscw6D71EGHDkHQ1xAFrkf4LPrjgACB/xNSAGI9YRpkecIjniVSie/Nlt2jdSHLNW5rUoVS9iQyuzeSKg9dsz0pZVHnWZjWyGxYh2HmyVp6qneXBBn6eLIx4T3HF0lwYtcbvxL2VOpoiCE3N5bQV2mKsuzgEhr6LNDW2Q6QAWM1KAlpWCMIHKVwsG6vQJS8z6oq+k1yqV7GIrZZ2wLKJ37gEOI4VwgKS1E7r3IFSoWZsPhvU0kJotRkIlJaCyjoQRjzBC1dSaSQbusB8biEd8w6UMMNdmuFrFeQpMpk9zDRrVcm841PHfzFsposCZRomnbCEDgDr3g34TUqWxbb+O1aoegVNJsUupmbwif16lsC6E4s6KRdhrZlS7os0XWkCFpa6xcaxfLom1rsNLbbNwokU8jzWiMkRkLafGLqbOqgsy38PONKIes41VuSHVRvzL5ePa+bSVWTrEQL4rGuyjPTeP9WoTlRCNcaq9WiWUiKNI1h87G/veqvchSrlS76Mqmw9C/6xHbz5jjvG4UqVdC0apemWhm9McPg96xrXF37VevaAp3LQRljne/bztJ4CIFHTHaBPTCP6jUeDsby3E3Wy9JlvpQqchCdszTLldncX9wvP3HoruL1mFzH1yW2290Y59jturHr5DgGkzLWTNnkJEFlgqbMQyNsJke0CjqLzRXvzujcWU6YlUitHLFgczpXizdtwd/4A40g3LCZ9iGYVdsEGmvBqWKSleCyBBEcdF6S0MQIgDHWmVIqXkPlxoQvSF2iqiIXlAhDF/kZoog5V6K0zPR8zoofmALMZELGwoAHcxOfAqtrCjr4fixMhzCkER+KYhbRqES8so2Oi25X7JDE65tMpH0NJXfxqCxQk7C91L5V0CuFhPlPpFNybj9ZMln9wCAb9+Hx7fn0ji+6qi3R+Wclzs+fus4+sccST+QpYkRfKWGP+BWjym/WzhvV3RWb03eyopzKwpRlptD2kg4WEVorYzCGWyXCNqIbeHsHXcCUi11/Z8/XCmWvYHhTmnZpyrlhK2PizIqoWS5afrzIdnxReoR0lJq1bfmzaj8Pk8+DV2dL0lGOdt2qrkRrXdxn0JWQF7apB80qWj32pqstusq3NatK1CQTB4iC1bg/k6ur3kiM46kKSF3lrsyVQ9uOJVMHp1duNi/Qw4fP888V5O1JfiRxfHyiMMtzOftmaWZJWjNff/NUwr9wmEy+9fMOt7dHbjb/m28KfOvbb8m32wU6sIVRsI7brMCOby//87mONWqtIKio50aszJz1RbGQQoOjRM8LMNqzvl8wJhfSiTkZQFfhyYIx4sShyDie5JJEyrlZ+NB0ZZKG89kwLRz8pERsfTLNo7PgC1bjszSWPoSkT3zlmf9Qn8BKr876pCUWb/jy4A91T0ilFZEVunKFybyQRPbOyNLlJk0b4rSQeZWXlShbWJiSthNFcMI6DBuR+ESGdVIQf6eTwhY1yjgo4cP3WWkdnGNlzLOA0JbLQtY71lxBMaNAnvLJqqZHlRnAhFCUl0HN9D2mVmUTsbgZ3mQ2D+CSvbzMmbT0JNDvVTBrFPmulRk2Xq/tJsAuM0jTwEO1ewFSDdm22K1itIfuhXeDqTHY3T4n1vYlezy0W/JjGqWISQ0didME9/1LqPIAycpENGuR51NTlurkUASwfcF0BlTsdABBAnAPKFAttOWsZTZDhLKInYgjFEHQPmRzQ1h1W7Q6ekZwgrbUkk6TvficpLewhKbGhkXe/5YFo0v446UNsQTPPng80OBvQK7MQ1KW+fhTi0iGrtNRlJML6XRl4TFkkEQZwj1H74fziZj6Xe4Uh+YcTCvrCWmoyeExS2gOYr1jGZvJw6fNLiFBOWbmVlEmjcyhrH6FqP4tWxtnH37GyC6N5hxDyhFFA+kNh0M8XZ+/O36XwxxnsGVlqmpqTDyd2jj2LHlzVwT3Bw8kQZojen93uvNOT/sDNftQNL16d3nUtncnJslUluPo6OROZbi87GRP7F2FN/4TFxPR3EXx5v1w+4irR4s9tuF0UoalDQXwGILc7vyrCJfH55f+bhpiNpn5uzJCoZLCJ2Tn76zPi7pBbN1ZRLhGeALK40ozL7/85/9ePL8ofPXV9xrPx8/FpBZsmintNtqY4t/8v/mz97/3yw7vr3+vvCYH8v795OU45Zu/maBYcH7+4vsvhOjZL3bChD/STN7HGzDMcluTc9MVZ4JILi3ZnAqEeArGt3qL4hepmU7zRoPkGtr3ibZkmmBmAz9BYO7gfrhDOGjL1x9ZtTHaQQ2ZDqHVZY/aXH2IwZbOobQqDLGCLYnxUhxOg7d36k1z/elMYj5fX6wVJuHFpxcan346Ib25mWzM1yX0JyWur/XlaYFsNtNZmF3qSz9hchGp+VQkOwTq2c/PrV/+Fwn/LyXIn0iQO4XD4ZpcSTxvJD5OBH6fpGlCVr7/TMhH3MeNef7vHPLv/v5P/v5wePm1sxwvSfb3f58hz4usyLIXKX/t5dcyLOxLjMPDlaCAH0N85i9fm+bTZ5qs+0YoVxIhkWhtuDH7BLpIkrHbcScvaLQrsu7UGW9IkbaKA1S2cDbXR5lSciEumBCasQAj2OZaicgTntk95HnkYUK4wVYTDTeb7Ww9Bcnz2dZWIEV2ZrdQlY6lLNB9LW5uJ25rMI5HHs4mGs6dnXyQs0a3l+MoL2cVLqvqUqZl4uGBJ18mWlY2VJJv3fZ+7C75MrLcEAkGDUK4tS/7kmXbmMu3XBpPMEUJt7y+wkkqlV6ljuQ8o8RL1ggTwmwZcX1MJ1OFZjBom6ZdB2kHh2mLpv8xdjKtsV7LrlsDSKSUfa7wi9k+aZALjeNj4hbmrHaBZ39JT/v94eREz4vD4ZyWOT7XlBAGxHtHbC5Kcp8jGyhK4QKkhRCK8x3fqoXTNXj3k8bkXIOERy93L3yLuzuydTbvVytk30Vj9qmhbzLj0fh50pme8S3JX1mmnDc+aby5UDh5EzABL/KGw/Xkoe+36UGKsxUXNGiIE8cfrJ+Lpy8kTj9I/GRPT39/KeETicr6/u/8PpHfKfi9CX7/9x/l7+bG7/zObn2X4fEiw6/bRyvHDDLJMBzK8AnVn7VrMcYx7jUjP941t/31bOtZLDGkz5/NzFlgkFvOBkMrjaY5M2e5UfP39zd3wfXt9TjeDENw08+aYFbXN9UsdyvQa7cmuAnsjeOXrLU3fg0F7IHJJRZXxr7xsAe7h/vhh+O9Fp6eXigcb/Ljavb44+ocgATeD+QHz9W14OOPKT5+/1Hu1HaYjtP9KsX6aD117fcyd6AvlOL7s4DozW1piDSF78GCHegVtYkvk7+bDHVbZkkeZX4rkWU8x2CE4lRIDEPOuc2LObteJS3Pm8ZzZT1hxfjLIlVJpOMgcJ6BH+s4QaJTKJmoJPGUcp7ItQvFnvSJowUrCo8x53nWPaNUOLJYjbj0DeCGKHwaO6tPiLrW2rNWW0GZpfL9bS3zhDbcZPB4BkY95nmSMUhpwZjAhYrTxi0fWw4PUoBzC6Q9PEboxTCG2LGKKEuENnxMi+hj5CKjLckVt6G1pJRLaTlAjKTQK3JqpXT8OoTxHoQOYJiQUSvj/NrkzAoxQLIWlEpOenArU0dt/GqXxipquYbiagrCtCZCWBLRLMcpboTWinJjnis8ZgWlnbUihSZxyzkc6CwIM2NS38FCWs0t1dBMKSOonkJYc3hk4wUZ250bSUaZMMIaI5m2kgkLMCgQPnqjy8twEaUetRHfc+bx9Hxhk/qt3xw9G08IIUG2Z0HGituifX4vCtUmS3xJUO6lIaU/a8LC0tfg0Pdpfe5NVerEIC4yxOht4Mfp0+35rd/sZkk0ExRgqn5mWVAzSzXBmUz7mBgQ0f+m/0PcozMEMP4205Y2y0joMZCcRCHyPHPrNDKM0Kg7kuTvIs9+oeIKIIA2/ni09v+izkvb/zMACADw51fMNrGcI9P/ov4HXeRIjxAkK2Qpgjt9ugTZT0bGn4KHAQHaG1n988PtKA3dALhf2x6dob9honchmifabX/GnJ1c7nEnrcYwJ2e00eBByUrMNhgrp5MrAmfkNtCEQ8BK8qpur4LVXp4JHoj6kL6+zjvbmHBBjsPPgf4I2zrGardnEgzax2BgJkFFCLfH7gNX2uLGewTAvQcGhg7gHl6c3e/tRrZ0IGofkGGrD8GCTHXM/G4Hr4udYeHTT2RkcqRSHTAF4gttEcgv4AiUzIriNiP8fzI/gIIRBzemsgTTj7WzdG+8ggkv1qN/mvpz0RWNh7yaHXFkRSaOTC62ohG/gxrWNMIIPzNwxlAOBlm/lJTaZKBjOhfNTyYqXN42sTTRDUygPL+yVcAvKlEAJl04YpYoJcYSauzF+CQ58PsyLZM3TVE2ap/gZGkV7ieVaO/65WLY66p7hLP8kQlry2qofAEnIDEyYDOT67psoYNfBABXfQBEvSfCzkYcYPSWUMoYFpkLLJkArQfSsSS7FI9lTjUeK8wW4VhNZXUeq0usS3OHlNZLeCzJokWKNzSclk2Zbeg4hlRxyGlzQrTMmZYkh39xROXOl9HvSMocsWboJI5k7J2Nw4J0pfJSXK9Uul6c38EdGcKGKtWITAulxcVZZoZ38IbnzGSJtFTAavpAygE+HSEiZFxVDDMwim9SVJmacjyO4AiX6vephkck45tOQNl0H/YsTYJZ6XDRoU2rBGPZHhlKYAQEpfNRDAODYbA4suHcf9PhGEnsxi43WStF7CIDWm0R5bMfEKriwGOrVqpclaQ4d2rsPw8RAvXhz6nRHrx0v06Eur/R/67fDGV+jArcO1eipS7kie/Bem8kycb+m5IfyO8N09PBOO9NL2GOD9HaIA1z3S28i8I8wjWs8tt87EVYgD5lpRcWIg1s3f0j2/1jm/0Tq/1Ty7bMnB+yNaPV0bkJKaOjCxgU4dGlYZcHh1QG7fboWq/J/KMbnTJxO7TgPHLmI3rflMF0swYP5g0iaBhTdQgbBrvbw7ZhI2+ClX4aNvZwNAeHh0yc7U3apk62bTOsVdvc4SxsgTza527Y0lp3mRO2shBtunHWmQ9t/Xb5tts/GV96zaHnaGX84b9mDneUo2tRy9rU2EBDkCFHgfIIjohVVh/AkZAZmZMVWZMNGUNEiFTvAbISXFKzmiOoiwq1ZZZbYeXsfmsszmqWAhQSwkJ4iAlBjuDIPJbH80Re+WZVeboe6kkP6+E9pgd5wCOjYlQusSW+pJb0LjPcGIM55GQTm9xhJ7+id4yDmPtvBFliY1guTnF0AiSQOlEn60wdIh8YVaMa8WKxJOfa1KZ/hhOkg5d2gIHNn1InUlJdpykwueDTf8mZ+UZrAQ==) format("woff2");font-weight:400;font-style:italic;font-display:swap}
|
||
|
||
/* ---- Farbrollen. Nacht = Grundzustand, Tag als Umschaltung. ---------- */
|
||
:root[data-theme="nacht"]{
|
||
--canvas:#161b23; /* dunkles Blaugrau wie in der myAudi App */
|
||
--tile:#1f2733;
|
||
--tile-2:#2a3341;
|
||
--line:rgba(255,255,255,.10);
|
||
--line-strong:rgba(255,255,255,.20);
|
||
--fg:#FFFFFF; --fg2:#9aa1ad; --fg3:#657081;
|
||
--ok:#15da15; --warn:#ffaa00; --bad:#fd2c4e;
|
||
--shade:rgba(255,255,255,.05);
|
||
}
|
||
:root[data-theme="tag"]{
|
||
--canvas:#FFFFFF;
|
||
--tile:#f2f2f2;
|
||
--tile-2:#e5e5e5;
|
||
--line:rgba(0,0,0,.10);
|
||
--line-strong:rgba(0,0,0,.22);
|
||
--fg:#000000; --fg2:#4c4c4c; --fg3:#666666;
|
||
--ok:#0DA20D; --warn:#ffaa00; --bad:#eb0d3f;
|
||
--shade:rgba(0,0,0,.04);
|
||
}
|
||
:root{ --red:#F50537; --r-tile:20px; --r-pill:999px; }
|
||
|
||
*{box-sizing:border-box;margin:0;padding:0}
|
||
html,body{height:100%}
|
||
body{
|
||
background:#111;font-family:"Audi Type",Helvetica,Arial,sans-serif;font-weight:400;
|
||
display:flex;align-items:center;justify-content:center;padding:22px 14px;
|
||
-webkit-font-smoothing:antialiased;font-variant-numeric:tabular-nums;
|
||
}
|
||
.phone{
|
||
width:100%;max-width:412px;height:min(880px,calc(100vh - 44px));
|
||
background:var(--canvas);color:var(--fg);
|
||
display:flex;flex-direction:column;overflow:hidden;position:relative;
|
||
transition:background .25s ease,color .25s ease;
|
||
}
|
||
|
||
/* ---------------- Kopf ---------------- */
|
||
.topbar{display:flex;align-items:flex-start;gap:12px;padding:16px 20px 6px;flex:0 0 auto}
|
||
.back{width:20px;height:20px;border:0;background:none;padding:0;cursor:pointer;display:none;align-items:center}
|
||
.back.on{display:flex}
|
||
.back svg{stroke:var(--fg);fill:none;stroke-width:1.3}
|
||
.head{flex:1 1 auto;min-width:0}
|
||
.eyebrow{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--fg3);margin-bottom:5px}
|
||
.title{font-size:23px;font-weight:400;letter-spacing:-.015em;line-height:1.15;
|
||
white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.sync{display:flex;align-items:center;gap:8px;margin-top:7px;font-size:12.5px;color:var(--fg3)}
|
||
.sync svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.4}
|
||
.rings{
|
||
height:26px;width:auto;flex:0 0 auto;display:flex;align-items:center;justify-content:center;
|
||
}
|
||
.rings{background:none;border:0;padding:0;cursor:pointer}
|
||
.rings svg{height:19px;width:auto;display:block;color:var(--fg)}
|
||
.badge{display:flex;align-items:flex-end;gap:11px}
|
||
.badge svg{height:27px;width:auto;display:block;color:var(--fg)}
|
||
.badge .zusatz{font-family:"Audi Type Extended",sans-serif;font-style:italic;
|
||
font-size:23px;line-height:1;letter-spacing:.005em;padding-bottom:1px}
|
||
.themebtn{
|
||
width:34px;height:34px;border:1px solid var(--line);background:none;color:var(--fg2);
|
||
cursor:pointer;border-radius:var(--r-pill);flex:0 0 auto;
|
||
display:flex;align-items:center;justify-content:center;
|
||
}
|
||
.themebtn svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.4}
|
||
.themebtn:hover{color:var(--fg);border-color:var(--line-strong)}
|
||
|
||
main{flex:1 1 auto;overflow-y:auto;overscroll-behavior:contain;padding:0 20px 34px}
|
||
main::-webkit-scrollbar{width:0}
|
||
|
||
/* ---------------- Bausteine ---------------- */
|
||
.tile{position:relative;background:var(--tile);border-radius:var(--r-tile);padding:22px;margin-bottom:12px}
|
||
.tile.flat{background:none;padding:0}
|
||
.tilebtn{display:block;width:100%;text-align:left;border:0;font-family:inherit;
|
||
color:inherit;cursor:pointer;position:relative}
|
||
.tilebtn:hover{background:var(--tile-2)}
|
||
.zahnrad{position:absolute;top:16px;right:16px;width:34px;height:34px;border:0;background:none;
|
||
cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:var(--r-pill)}
|
||
.zahnrad:hover{background:var(--tile-2)}
|
||
.zahnrad svg{width:18px;height:18px;stroke:var(--fg3);fill:none;stroke-width:1.3;stroke-linecap:round}
|
||
.zahnrad:hover svg{stroke:var(--fg)}
|
||
.tilebtn .go{position:absolute;top:24px;right:22px;width:6px;height:10px;
|
||
stroke:var(--fg3);fill:none;stroke-width:1.3}
|
||
.seg{display:flex;gap:8px;margin-top:14px}
|
||
.seg button{flex:1;border:1px solid var(--line-strong);background:none;color:var(--fg2);
|
||
font-family:inherit;font-size:11px;letter-spacing:.12em;text-transform:uppercase;
|
||
padding:11px 8px;border-radius:var(--r-pill);cursor:pointer}
|
||
.seg button.on{border-color:var(--red);color:var(--fg)}
|
||
.feld{display:flex;justify-content:space-between;align-items:center;gap:14px;
|
||
padding:12px 0;border-bottom:1px solid var(--line)}
|
||
.feld label{font-size:13px;color:var(--fg2)}
|
||
.feld input,.feld select{background:var(--tile-2);border:1px solid var(--line);
|
||
color:var(--fg);font-family:inherit;font-size:13.5px;padding:8px 11px;border-radius:6px;
|
||
text-align:right;min-width:132px}
|
||
.mitEinheit{display:inline-flex;align-items:center;gap:8px}
|
||
.mitEinheit input{min-width:92px;text-align:right}
|
||
.mitEinheit span{font-size:13px;color:var(--fg2)}
|
||
.notiz{width:100%;margin-top:12px;background:var(--tile-2);border:1px solid var(--line);
|
||
border-radius:8px;color:var(--fg);font-family:inherit;font-size:13.5px;line-height:1.6;
|
||
padding:12px 13px;resize:vertical}
|
||
.feld input[type=checkbox]{min-width:0;width:19px;height:19px;accent-color:var(--red)}
|
||
.aktion{display:block;width:100%;margin-top:16px;border:1px solid var(--line-strong);
|
||
background:none;color:var(--fg);font-family:inherit;font-size:11px;letter-spacing:.14em;
|
||
text-transform:uppercase;padding:14px;border-radius:var(--r-pill);cursor:pointer}
|
||
.aktion:hover{border-color:var(--red)}
|
||
.label{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--fg3);display:block}
|
||
.fig{font-family:"Audi Type Wide",sans-serif;font-weight:300;letter-spacing:-.02em;line-height:.95}
|
||
.unit{font-family:"Audi Type",sans-serif;font-size:.32em;color:var(--fg2);margin-left:.32em;letter-spacing:0}
|
||
.sport{font-family:"Audi Type Extended",sans-serif;font-style:italic;letter-spacing:.005em}
|
||
|
||
.rows{margin-top:4px}
|
||
.row{display:flex;justify-content:space-between;align-items:baseline;gap:14px;padding:13px 0;border-bottom:1px solid var(--line)}
|
||
.row:last-child{border-bottom:0}
|
||
.row dt{font-size:13px;color:var(--fg2)}
|
||
.row dd{font-size:14px;text-align:right}
|
||
.row dd small{display:block;font-size:11px;color:var(--fg3);margin-top:3px}
|
||
.row dd .label{display:block;text-align:right}
|
||
.werte{display:block;color:var(--fg);font-size:14px;white-space:nowrap}
|
||
|
||
.pill{display:inline-block;font-size:10px;letter-spacing:.14em;text-transform:uppercase;
|
||
border:1px solid var(--line-strong);border-radius:var(--r-pill);padding:6px 12px;color:var(--fg2)}
|
||
.pill.work{border-color:var(--red);color:var(--red)}
|
||
|
||
/* ---------------- Start ---------------- */
|
||
.carbox{position:relative;text-align:center;padding:30px 0 0;display:block;width:100%;background:none;border:0}
|
||
.carbox img{width:100%;display:block;-webkit-tap-highlight-color:transparent}
|
||
/* Feste Bildhöhe: Front- und Seitenansicht wirken dadurch gleich groß */
|
||
.carfix{width:100%;max-width:100%;height:206px;object-fit:contain;display:block}
|
||
.carfix.klein{height:165px}
|
||
/* Radbild klein und rechtsbündig oben in der Kachel */
|
||
.radbild{position:absolute;top:22px;right:22px;width:78px;height:78px;object-fit:contain;display:block}
|
||
.radph{position:absolute;top:22px;right:22px;width:78px;height:78px;border:1px dashed var(--line-strong);
|
||
border-radius:50%}
|
||
/* Kopfbereich hält die Höhe des Radbilds frei, damit die Felder darunter
|
||
denselben Abstand haben wie das Bild nach oben und rechts. */
|
||
.radkopf{min-height:78px;padding-right:96px}
|
||
/* Fahrbahn unter dem Fahrzeug: eine angedeutete Oberfläche, die das Auto
|
||
auf den Boden stellt, ohne selbst Aufmerksamkeit zu ziehen.
|
||
Innenraum- und Detailbilder bekommen keine. */
|
||
.szene{position:relative;border-radius:var(--r-tile);overflow:hidden;margin-bottom:26px}
|
||
.szene img{position:relative;z-index:2}
|
||
.szene.strasse::before{content:"";position:absolute;left:0;right:0;bottom:0;height:30%;z-index:1;
|
||
background:
|
||
radial-gradient(ellipse 42% 40% at 50% 76%, rgba(0,0,0,.55) 0%, rgba(0,0,0,0) 72%),
|
||
linear-gradient(180deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.045) 40%,
|
||
rgba(255,255,255,.075) 100%);}
|
||
.szene.strasse::after{content:"";position:absolute;left:0;right:0;bottom:0;height:30%;z-index:1;
|
||
background:linear-gradient(90deg, var(--canvas) 0%, rgba(0,0,0,0) 22%,
|
||
rgba(0,0,0,0) 78%, var(--canvas) 100%);}
|
||
/* Verschneite Fahrbahn bei montierten Winterrädern */
|
||
.szene.winter::before{content:"";position:absolute;left:0;right:0;bottom:0;height:38%;z-index:1;
|
||
background-image:url("bilder/fahrbahn-schnee.webp");
|
||
background-size:cover;background-position:center bottom;}
|
||
.szene.winter::after{content:"";position:absolute;left:0;right:0;bottom:0;height:38%;z-index:1;
|
||
background:
|
||
radial-gradient(ellipse 40% 44% at 50% 78%, rgba(28,48,70,.5) 0%, rgba(28,48,70,0) 70%),
|
||
linear-gradient(90deg, var(--canvas) 0%, rgba(0,0,0,0) 20%,
|
||
rgba(0,0,0,0) 80%, var(--canvas) 100%);}
|
||
:root[data-theme="tag"] .szene.strasse::before{
|
||
background:
|
||
radial-gradient(ellipse 42% 40% at 50% 76%, rgba(0,0,0,.28) 0%, rgba(0,0,0,0) 72%),
|
||
linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.05) 40%, rgba(0,0,0,.085) 100%);}
|
||
.status{display:flex;align-items:center;gap:12px;padding:16px 0 4px}
|
||
.dot{width:11px;height:11px;border-radius:50%;flex:0 0 auto;background:var(--ok)}
|
||
.dot.bad{background:var(--bad)}
|
||
.status .t{font-size:14px}
|
||
.status .s{font-size:11px;color:var(--fg3);margin-top:3px}
|
||
.duo{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px}
|
||
.duo .tile{margin:0}
|
||
.tankzeile{display:flex;align-items:flex-end;justify-content:space-between;gap:16px}
|
||
.pct{font-size:15px;color:var(--fg2);padding-bottom:9px}
|
||
/* Kilometer und Monat nebeneinander. Bricht bei fünfstelligen Kilometern um,
|
||
statt die Kachel zu überfüllen. */
|
||
.zweizeiler{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
|
||
flex-wrap:wrap;margin-top:14px}
|
||
.nebenwert{font-size:13px;color:var(--fg2);white-space:nowrap}
|
||
.marke{display:inline-flex;align-items:center;gap:8px}
|
||
.marke img{height:16px;width:auto;display:block}
|
||
.marke .ph{font-size:8px;letter-spacing:.12em;text-transform:uppercase;color:var(--fg3);
|
||
border:1px dashed var(--line-strong);border-radius:3px;padding:3px 5px;line-height:1}
|
||
.balken{height:4px;border-radius:var(--r-pill);background:var(--line);margin-top:18px;overflow:hidden}
|
||
.balken i{display:block;height:100%;border-radius:var(--r-pill);background:var(--fg)}
|
||
.ringwrap{position:relative;width:150px;margin:6px auto 0}
|
||
.ringwrap .mid{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
|
||
|
||
/* ---------------- Aufklappen ---------------- */
|
||
.acc-h{
|
||
width:100%;border:0;background:none;color:inherit;font-family:inherit;cursor:pointer;text-align:left;
|
||
display:flex;align-items:center;gap:13px;padding:16px 0;border-bottom:1px solid var(--line);
|
||
}
|
||
.mark{width:9px;height:9px;flex:0 0 auto;position:relative}
|
||
.mark::before,.mark::after{content:"";position:absolute;background:var(--fg3);transition:transform .18s,background .18s}
|
||
.mark::before{left:0;top:4px;width:9px;height:1px}
|
||
.mark::after{left:4px;top:0;width:1px;height:9px}
|
||
.acc-h[aria-expanded="true"] .mark::after{transform:scaleY(0)}
|
||
.acc-h[aria-expanded="true"] .mark::before{background:var(--red)}
|
||
.acc-h .k{flex:1 1 auto;font-size:15px}
|
||
.acc-h .v{font-size:11.5px;color:var(--fg2);text-align:right;line-height:1.5}
|
||
.acc-b{display:none}
|
||
.acc-b.on{display:block}
|
||
.lvl2 .acc-h{padding-left:22px}
|
||
.lvl2 .acc-h .k{font-size:13.5px}
|
||
.leaf{
|
||
width:100%;border:0;border-bottom:1px solid var(--line);background:none;color:inherit;
|
||
font-family:inherit;cursor:pointer;text-align:left;display:flex;align-items:center;gap:12px;
|
||
padding:13px 0 13px 44px;
|
||
}
|
||
.leaf:hover,.acc-h:hover{background:var(--shade)}
|
||
.leaf .k{flex:1 1 auto;font-size:13.5px}
|
||
.leaf .k small,.leaf .v small{display:block;font-size:11px;color:var(--fg3);margin-top:3px}
|
||
.leaf .v{font-size:13px;color:var(--fg2);text-align:right}
|
||
.chev{width:6px;height:10px;flex:0 0 auto;stroke:var(--fg3);fill:none;stroke-width:1.3}
|
||
|
||
/* ---------------- Karte ---------------- */
|
||
.mapbox{position:relative;width:100%;aspect-ratio:4/3;border-radius:var(--r-tile);overflow:hidden;background:var(--tile)}
|
||
.mapbox .leaflet-container{position:absolute;inset:0;height:100%;width:100%;background:var(--tile);
|
||
font-family:inherit;font-size:10px}
|
||
.mapbox .leaflet-control-attribution{background:rgba(0,0,0,.45);color:#cfd4dc;font-size:9px}
|
||
:root[data-theme="tag"] .mapbox .leaflet-control-attribution{background:rgba(255,255,255,.7);color:#4c4c4c}
|
||
.mapbox .leaflet-control-attribution a{color:inherit}
|
||
.mapbox .leaflet-control-zoom a{background:var(--tile);color:var(--fg);border-color:var(--line)}
|
||
|
||
/* ---------------- Statistik ---------------- */
|
||
.quad{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:14px}
|
||
.quad .n{font-family:"Audi Type Wide",sans-serif;font-weight:300;font-size:17px;letter-spacing:-.02em}
|
||
.quad .l{font-size:9px;letter-spacing:.12em;text-transform:uppercase;color:var(--fg3);margin-top:6px}
|
||
.bar{display:flex;height:4px;border-radius:var(--r-pill);overflow:hidden;margin-top:16px;gap:2px}
|
||
.bar i{display:block;height:100%;border-radius:var(--r-pill)}
|
||
.legend{display:flex;gap:18px;margin-top:12px;flex-wrap:wrap}
|
||
.legend span{font-size:11px;color:var(--fg2);display:flex;align-items:center;gap:7px}
|
||
.legend i{width:8px;height:8px;border-radius:50%;display:block}
|
||
.tile-h{width:100%;border:0;background:none;color:inherit;font-family:inherit;cursor:pointer;text-align:left;display:block}
|
||
.tile-b{display:none;margin-top:6px}
|
||
.tile-b.on{display:block}
|
||
|
||
/* ---------------- Reiter ---------------- */
|
||
.tabbar{flex:0 0 auto;display:grid;grid-template-columns:repeat(5,1fr);border-top:1px solid var(--line);background:var(--canvas)}
|
||
.tab{background:none;border:0;border-top:2px solid transparent;margin-top:-1px;cursor:pointer;
|
||
font-family:inherit;color:var(--fg3);padding:11px 2px 13px;font-size:9px;letter-spacing:.08em;
|
||
text-transform:uppercase;display:flex;flex-direction:column;align-items:center;gap:6px}
|
||
.tab svg{width:21px;height:21px;stroke:currentColor;fill:none;stroke-width:1.3;
|
||
stroke-linecap:round;stroke-linejoin:round}
|
||
.tab svg polygon{fill:none;stroke:currentColor;stroke-width:1.3}
|
||
.tab:hover{color:var(--fg2)}
|
||
.tab.on{color:var(--fg);border-top-color:var(--red)}
|
||
.tab.on svg polygon{fill:var(--red);stroke:var(--red)}
|
||
.tabbar.ohne .tab span{display:none}
|
||
.tabbar.ohne .tab{padding:16px 2px 18px;gap:0}
|
||
.tabbar.ohne .tab svg{width:23px;height:23px}
|
||
:focus-visible{outline:2px solid var(--red);outline-offset:2px}
|
||
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="phone">
|
||
<div class="topbar">
|
||
<button class="back" id="back" aria-label="Zurück"><svg viewBox="0 0 12 20"><polyline points="10,1 1,10 10,19"/></svg></button>
|
||
<div class="head"><div class="eyebrow" id="eyebrow">Fahrzeug</div><div class="title" id="title">Übersicht</div>
|
||
<div class="sync" id="sync"><svg viewBox="0 0 16 16"><path d="M14 8a6 6 0 1 1-1.8-4.3"/><polyline points="14,1 14,4.2 10.8,4.2"/></svg><span></span></div></div>
|
||
<button class="themebtn" id="theme" aria-label="Tag- oder Nachtmodus">
|
||
<svg id="themeicon" viewBox="0 0 20 20"></svg></button>
|
||
<button class="rings" id="ringsbtn" aria-label="Einstellungen"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 289 100" fill="currentColor" aria-hidden="true"> <defs/> <defs> <clipPath id="audiRingsClip" clipPathUnits="userSpaceOnUse"> <path d="M0 100h289V0H0z"/> </clipPath> </defs> <g clip-path="url(#audiRingsClip)" transform="matrix(1 0 0 -1 0 100.00040017)"> <path d="M239 11.1914c-8.885 0-17.075 3.008-23.624 8.05 6.646 8.489 10.624 19.165 10.624 30.759 0 11.593-3.978 22.269-10.624 30.759 6.549 5.041 14.739 8.05 23.624 8.05 21.399 0 38.809-17.41 38.809-38.809 0-21.4-17.41-38.809-38.809-38.809m-86.625 8.05c6.647 8.489 10.625 19.165 10.625 30.759 0 11.593-3.978 22.269-10.624 30.759 6.548 5.041 14.74 8.05 23.624 8.05 8.885 0 17.075-3.009 23.624-8.05-6.646-8.49-10.624-19.166-10.624-30.759 0-11.594 3.978-22.27 10.624-30.759-6.549-5.042-14.739-8.05-23.624-8.05-8.884 0-17.076 3.008-23.625 8.05m-63 0C96.022 27.7304 100 38.4064 100 50.0004c0 11.593-3.978 22.269-10.624 30.759 6.548 5.041 14.74 8.05 23.624 8.05 8.884 0 17.076-3.009 23.624-8.05-6.646-8.49-10.624-19.166-10.624-30.759 0-11.594 3.978-22.27 10.624-30.759-6.548-5.042-14.74-8.05-23.624-8.05-8.884 0-17.076 3.008-23.625 8.05m-78.184 30.759c0 21.399 17.41 38.809 38.809 38.809 8.884 0 17.076-3.009 23.624-8.05C66.978 72.2694 63 61.5934 63 50.0004c0-11.594 3.978-22.27 10.624-30.759-6.548-5.042-14.74-8.05-23.624-8.05-21.399 0-38.809 17.409-38.809 38.809M81.5 27.3734c-4.593 6.375-7.309 14.187-7.309 22.627 0 8.439 2.716 16.252 7.309 22.627 4.593-6.375 7.309-14.188 7.309-22.627 0-8.44-2.716-16.252-7.309-22.627m63 0c-4.593 6.375-7.309 14.187-7.309 22.627 0 8.439 2.716 16.252 7.309 22.627 4.593-6.375 7.309-14.188 7.309-22.627 0-8.44-2.716-16.252-7.309-22.627m63 0c-4.593 6.375-7.309 14.187-7.309 22.627 0 8.439 2.716 16.252 7.309 22.627 4.593-6.375 7.309-14.188 7.309-22.627 0-8.44-2.716-16.252-7.309-22.627m31.5 72.627c-11.932 0-22.896-4.207-31.5-11.207-8.604 7-19.568 11.207-31.5 11.207-11.932 0-22.896-4.207-31.5-11.207-8.604 7-19.569 11.207-31.5 11.207-11.932 0-22.896-4.207-31.5-11.207-8.604 7-19.569 11.207-31.5 11.207-27.57 0-50-22.43-50-50 0-27.571 22.43-50 50-50 11.931 0 22.896 4.206 31.5 11.207C90.104 4.2064 101.068.0004 113 .0004c11.931 0 22.896 4.206 31.5 11.207 8.604-7.001 19.568-11.207 31.5-11.207 11.932 0 22.896 4.206 31.5 11.207 8.604-7.001 19.568-11.207 31.5-11.207 27.57 0 50 22.429 50 50 0 27.57-22.43 50-50 50"/> </g> </svg></button>
|
||
</div>
|
||
<main id="view"></main>
|
||
<nav class="tabbar" id="tabbar"></nav>
|
||
</div>
|
||
|
||
<script>
|
||
/* ================================================================
|
||
AUSTAUSCHBAR — hier Bild, Ringe und Fahrzeugtitel hinterlegen.
|
||
Beide Bildfelder nehmen eine URL oder einen data:-String.
|
||
Leer lassen zeigt einen Platzhalter.
|
||
================================================================ */
|
||
const CONFIG = {
|
||
fahrzeugtitel : "RS 4 Avant competition", // Klartext für Kopfzeile und Vorlesefunktion
|
||
fahrzeugzusatz : "Avant competition", // steht neben dem Typenschild
|
||
fahrzeuguntertitel : "quattro · 331 kW",
|
||
kennzeichen : "IN·RS 400",
|
||
// Fahrzeugbilder: siehe BILDER weiter unten, durch Antippen umschaltbar
|
||
markenlogo : "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4wIgogICB3aWR0aD0iNjAyLjM2MjE4IgogICBoZWlnaHQ9IjU2MS42MTQxNCIKICAgaWQ9InN2ZzE4ODQiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnMxODg2IiAvPgogIDxnCiAgICAgaWQ9ImxheWVyMSI+CiAgICA8ZwogICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTQ4LjgxODkxLC0yNTEuNTU1MSkiCiAgICAgICBpZD0iZzE4OTQiPgogICAgICA8cGF0aAogICAgICAgICBkPSJNIDcyLjM1MzU1LDYxMC41NzE4MyBDIDY3LjQzNjE0OSw1ODcuOTc1MDkgNjYuNTM1NDQsNTc5LjA2Mjk3IDY2LjUzNTQ0LDU1NS41NDM1NiBDIDY2LjUzNTQ0LDM5Ni41ODk3NSAxOTIuNjUxMywyNjkuMjY4MDkgMzQ5Ljk4NTQ3LDI2OS4yNjgwOSBDIDUwNy4zNDE2MSwyNjkuMjYxMDEgNjMzLjQ2NDU2LDM5Ni41OTY4MyA2MzMuNDY0NTYsNTU1LjU0MzU2IEMgNjMzLjQ2NDU2LDU3OS4wNjI5NyA2MzIuNTYzODUsNTg3Ljk4MjU0IDYyNy42NDY0NSw2MTAuNTc5MjcgTCA1NDAuMzc1ODYsNjc0LjU0MTI3IEwgNTI3LjA3NjQxLDc4MS4yMjc0MSBMIDM4My4xMjE0Miw3ODEuMjI3NDEgTCAzNzMuOTE4NzQsNzg4LjA0NzU3IEMgMzY3LjAyNTU5LDc5My4wNDUwNSAzNTguMDA0MzMsNzk1LjQ1NjI3IDM0OS43MDIzNiw3OTUuNDU2MjcgQyAzNDAuNzg5ODgsNzk1LjQ1NjI3IDMzMy4wNzYxLDc5Mi43NjkwMyAzMjQuMTg1NTksNzg2LjU2NjExIEwgMzE2LjQ3MTgxLDc4MS4yMjc0MSBMIDE3Mi4zMzUwNCw3ODEuMjI3NDEgTCAxNTguODMyNTYsNjc0LjU0MTI3IEwgNzIuMzUzNTUsNjEwLjU3MTgzIEwgNzIuMzUzNTUsNjEwLjU3MTgzIHogIgogICAgICAgICBzdHlsZT0iZmlsbDojZGYwMDI0O2ZpbGwtcnVsZTpldmVub2RkIgogICAgICAgICBpZD0iXzQ2Nzc0Mzc2IiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJNIDMyMS42NzIzMiw3MzEuNDgzNjMgTCAzMzMuODk2NzMsNzQwLjc5NTQ1IEMgMzM4LjU4MTY5LDc0NC41MTQ1IDM0NS4yOTM0Myw3NDcuMTAwNDEgMzQ5Ljk4NTQ3LDc0Ny4xMDA0MSBDIDM1NC42OTk0OSw3NDcuMDkyOTYgMzYxLjQxMDg3LDc0NC41MTQ1IDM2Ni4xMDMyNyw3NDAuNzk1NDUgTCAzNzguMzI3NjgsNzMxLjQ4MzYzIEwgNDg0LjAyNTk0LDczMS40ODM2MyBMIDQ5NS4wNDQ1Niw2NDMuODA2MjcgTCA1NzkuMDE3NzUsNTgyLjM2NDYyIEMgNTgyLjMyMjU5LDU2OS42NDYyOCA1ODIuOTEwNzgsNTY0LjgzNzY1IDU4Mi45MTA3OCw1NTIuODI0MDcgQyA1ODIuOTEwNzgsNTM3Ljc5NTg0IDU3OS4wMTAzMSw1MTguOTk3ODkgNTczLjAxNzg3LDUwNS42OTg0NCBMIDU3Mi44MTQ0OCw1MDUuMTc1NDUgTCA0MjAuNzYwOSw2NTguNzI1MzcgTCA1NjcuMDk4MDcsNDc3LjY2MTY3IEMgNTYxLjMwOTM2LDQ1Mi4xMzc0NiA1NDkuNzc0ODQsNDMxLjgyOSA1MzEuODYzMDcsNDE1LjA5Mzk2IEwgNTMxLjA3MTQ5LDQxNC4zODkxOSBMIDM5OS40NDI2LDY0My44MDYyNyBMIDUxNS4yNTg3OCwzOTMuMDcwODkgTCA1MTQuNjQ4NjIsMzkyLjI3OTMxIEMgNDk5LjQyNDQ1LDM3MS42NTA4OSA0ODAuNDA4NTgsMzU3Ljk1MjExIDQ1NS40MDAyNywzNDkuNDQ2NCBMIDM3NC42MTYwNiw2MzQuMzkyNzcgTCA0MzIuODgzNjIsMzM3Ljk0MTI4IEMgNDE1LjU2MDA0LDMyNy45MTAxOCAzOTQuNzUwMiwzMjIuNjE1NDIgMzczLjUxMTk3LDMyMi42MTU0MiBDIDM2Ny43MjI5MSwzMjIuNjE1NDIgMzY1LjcxODExLDMyMi43MTcxMSAzNjAuNDE1OTEsMzIzLjMwNTMgTCAzNDkuNjAwNjcsNjMxLjc4NTI1IEwgMzM1LjY5MTA2LDMyMy41MDg2OCBDIDMyOS45NzQ2NSwzMjIuOTIwNDkgMzI3Ljg3NTU5LDMyMi44MTg4IDMyMy4yNjMyNywzMjIuODE4OCBDIDMwMi45Njg5OCwzMjIuODE4OCAyODQuNDM5OTYsMzI3LjcxNDI0IDI2NS4yMjA3MSwzMzguMzI2MDkgTCAyNjMuOTIwMzIsMzM5LjAzMDg1IEwgMzI1LjE4MDU1LDYzNC45MTU3NiBMIDI0NC4yODcyMSwzNDkuODQ2MDggQyAyMTguMzg1NjMsMzU4LjYzNDkgMTk3LjI2MzYzLDM3My43NjQ4MiAxODQuMTQ1NTksMzkyLjk3NjYzIEwgMzAxLjE0NTk1LDY0My4wMTQ3IEwgMTcwLjIzNTk5LDQxMi4wOTQxOSBDIDE1Mi4xMjA4Myw0MjYuNzk1MzcgMTM3LjQxMjU2LDQ1MS4wNDgyNSAxMzEuNDkyNzYsNDc2LjE1Nzg5IEwgMjc4LjYyMTg1LDY1OS4xMjUwNSBMIDEyNi4yOTE5LDUwNC4zODM4OCBMIDEyNS45Nzk3Myw1MDQuOTc5NTEgQyAxMTkuNjgyMjEsNTE4LjI5MzQ4IDExNS44ODM0Myw1MzYuNDIzMTcgMTE1Ljg4MzQzLDU1My40MzQyMyBDIDExNS44OTA1Miw1NjMuNjI0NzggMTE3LjA4OTIyLDU3Mi45NjU2NSAxMTkuNjc1MTIsNTgzLjI2NTMzIEwgMjA1LjM2OTY1LDY0Ni4yMTA0MSBMIDIxNS44NzIzNyw3MzEuNDgzNjMgTCAzMjEuNjcyMzIsNzMxLjQ4MzYzIHogIgogICAgICAgICBzdHlsZT0iZmlsbDojZjZlMDAwO2ZpbGwtcnVsZTpldmVub2RkIgogICAgICAgICBpZD0iXzQ2MTU3MDQ4IiAvPgogICAgPC9nPgogIDwvZz4KPC9zdmc+Cg==", // Bildmarke des Kraftstoffanbieters
|
||
markenname : "Shell",
|
||
startbild : "Frontansicht", // Bild der Übersicht, in den Einstellungen änderbar
|
||
version : "0.18",
|
||
tankvolumen : 58,
|
||
nachtVon : "18:59", // Nacht = 18:59 bis 05:59
|
||
nachtBis : "05:59",
|
||
pauseMin : 15 // kürzere Unterbrechungen zählen als eine Fahrt
|
||
};
|
||
|
||
|
||
const CAR = {
|
||
fin:"WUAZZZF48PA902804", details:"2.9 TFSI quattro competition · 331 kW · 450 PS",
|
||
erstzulassung:"08/2023", odo:20140, tankPct:62, spannung:12.4,
|
||
gesichert:true, standAlter:"vor 34 Min.",
|
||
hu:"08/2026", inspektionKm:4800, inspektionTage:212, oelKm:2100,
|
||
smartdeal:{aktiv:true, laeuftAb:"2027-03-31"},
|
||
oel:{modus:"hersteller", km:15000, monate:12, herstellerKm:30000, herstellerMonate:24},
|
||
versicherung:{
|
||
gesellschaft:"Audi Versicherung",
|
||
vertrag:"Haftpflicht, Vollkasko und Teilkasko, Schutzbrief Mobilität",
|
||
nummer:"VW-1971391586",
|
||
service:"0800 11 222 88", notfall:"+49 531 3939 7430", // Schaden-Notruf, rund um die Uhr
|
||
beitrag:2068.45, steueranteil:330.25, steuersatz:"19 %",
|
||
gueltigAb:"2026-08-13", zahlweise:"jährlich",
|
||
teile:[
|
||
{bez:"Haftpflicht und Schutzbrief Mobilität", betrag:293.32, sf:"SF 18", sfAlt:"SF 17", satz:"30 %", satzAlt:"30 %"},
|
||
{bez:"Vollkasko inklusive Teilkasko", betrag:1775.13, sf:"SF 17", sfAlt:"SF 16", satz:"26 %", satzAlt:"27 %"}
|
||
],
|
||
selbst:[["Vollkasko","500 €"],["Teilkasko","150 €"]],
|
||
/* Schutzbrief Mobilität, Zusatzvereinbarung KRB 4121/01.
|
||
Alle Beträge aus dem Bedingungswerk. */
|
||
schutzbrief:{
|
||
stand:"KRB 4121/01, Fassung 10.2021",
|
||
gilt:"Europa einschließlich europäischer und asiatischer Türkei sowie außereuropäische EU-Gebiete",
|
||
versichert:"Halter, berechtigter Fahrer und berechtigte Insassen, inklusive Gepäck, privater Ladung und mitgeführtem Anhänger",
|
||
ausloeser:["Panne — jeder Betriebs-, Bruch- oder Bremsschaden","Unfall","Diebstahl",
|
||
"Krankheit, Verletzung oder Tod auf einer Reise","Naturkatastrophe"],
|
||
/* Der zentrale Punkt: diese drei Leistungen schließen einander aus. */
|
||
entweder:[
|
||
{bez:"Weiterkommen", grenze:"Bahn 1. Klasse bis 1 200 km, darüber Linienflug Economy",
|
||
zusatz:"Taxi zum und vom Bahnhof bis 100 €"},
|
||
{bez:"Übernachten", grenze:"3 Nächte, je 100 € und Person", zusatz:""},
|
||
{bez:"Mietwagen", grenze:"bis zu 14 Tage, bis das Fahrzeug repariert ist", zusatz:""}
|
||
],
|
||
gruppen:[
|
||
{titel:"Am Schadenort", posten:[
|
||
["Pannenhilfe vor Ort","bis 100 €","einschließlich verwendeter Kleinteile"],
|
||
["Abschleppen","bis 200 €","zur nächsten Werkstatt, Gepäck und Ladung eingeschlossen"],
|
||
["Bergen","volle Kosten","wenn das Fahrzeug von der Straße abgekommen ist"],
|
||
["Falschbetankung","bis 500 €","Entfernen des Treibstoffs, Folgeschäden ausgeschlossen"]]},
|
||
{titel:"Das Fahrzeug", posten:[
|
||
["Rücktransport zur Wunschwerkstatt","volle Kosten","wenn nicht binnen 3 Werktagen fahrbereit, nicht bei Totalschaden"],
|
||
["Unterstellung","bis 14 Tage",""],
|
||
["Unterstellung bei Totalschaden","bis 14 Tage","bis zur Verzollung oder Verschrottung"],
|
||
["Schlüsselverlust","Versandkosten","Ersatzschlüssel selbst nicht ersetzt"],
|
||
["Schlüssel eingeschlossen","Öffnen übernommen",""]]},
|
||
{titel:"Im Ausland", posten:[
|
||
["Ersatzteilversand","Versandkosten","wenn vor Ort nicht beschaffbar"],
|
||
["Rücktransport","volle Kosten","wenn nicht binnen 3 Werktagen fahrbereit und Reparatur nicht teurer als ein gleichwertiger Gebrauchtwagen"],
|
||
["Rückholung nach Reparatur","volle Kosten",""],
|
||
["Verzollung","Verfahrensgebühren","Zoll und Steuern nicht enthalten"],
|
||
["Verschrottung","volle Kosten",""],
|
||
["Todesfall","bis 5 000 €","Bestattung im Ausland oder Überführung"],
|
||
["Rückreise in besonderen Fällen","bis 2 500 € je Person","schwere Erkrankung naher Angehöriger, erheblicher Schaden am Eigentum"]]},
|
||
{titel:"Personen", posten:[
|
||
["Krankenrücktransport","volle Kosten","ärztlich angeordnet, plus 3 Nächte à 100 €"],
|
||
["Rückholung von Kindern","Bahn 1. Klasse","zusätzlich bis 100 € für Taxi"],
|
||
["Krankenbesuch","bis 500 €","ab zwei Wochen Krankenhausaufenthalt"],
|
||
["Fahrzeugabholung bei Fahrerausfall","volle Kosten","selbst gefahren 0,40 € je km, plus 3 Nächte à 100 €"],
|
||
["Medizinischer Beratungsservice","telefonisch","kein Notarzt, keine Diagnose"]]},
|
||
{titel:"Naturkatastrophe", posten:[
|
||
["Übernachtung","3 Nächte à 100 €","je Person"],
|
||
["Verpflegung","3 Tage à 15 €","je Person"],
|
||
["Taxi und öffentliche Verkehrsmittel","bis 100 €",""]]}
|
||
],
|
||
nicht:[
|
||
["Rennen","Auch behördlich genehmigte Veranstaltungen mit Höchstgeschwindigkeit — samt Übungsfahrten"],
|
||
["Vorsatz","kein Versicherungsschutz"],
|
||
["Grobe Fahrlässigkeit","Leistung wird der Schwere entsprechend gekürzt"],
|
||
["Krieg, innere Unruhen, Staatsgewalt","kein Versicherungsschutz"],
|
||
["Kernenergie","kein Versicherungsschutz"]
|
||
],
|
||
pflichten:[
|
||
"Vor Inanspruchnahme einer Leistung Weisung des Versicherers einholen, soweit möglich",
|
||
"Schadenereignis binnen einer Woche melden",
|
||
"Behördliche Ermittlungen unverzüglich mitteilen",
|
||
"Originalbelege zum Nachweis der Kosten aufbewahren",
|
||
"Schaden nach Möglichkeit mindern"
|
||
],
|
||
rang:"Besteht Anspruch gegen einen Dritten, etwa aus einer Automobilclub-Mitgliedschaft, geht dieser vor. Wendest du dich zuerst an den Versicherer, ist er zur Vorleistung verpflichtet."
|
||
},
|
||
leistungen:[
|
||
{gruppe:"Haftpflicht", posten:[
|
||
"Versicherungssumme 100 Mio. €, Personenschäden bis 15 Mio. € je Person",
|
||
"Umweltschadensgesetz 5 Mio. € je Fall, 10 Mio. € im Jahr",
|
||
"MallorcaDeckung für Mietwagen im europäischen Ausland"]},
|
||
{gruppe:"Kasko", posten:[
|
||
"Vollkasko mit 500 € Selbstbeteiligung",
|
||
"Teilkasko mit 150 € Selbstbeteiligung",
|
||
"Unfall sowie mut- und böswillige Handlungen Dritter",
|
||
"Hackerangriff auf die Fahrzeugsoftware mitversichert",
|
||
"Elementarereignisse, Entwendung, Brand, Explosion, Glasbruch",
|
||
"Zusammenstoß mit Tieren jeglicher Art",
|
||
"Tierbiss inklusive Folgeschäden bis 10.000 €",
|
||
"Kurzschluss an der Verkabelung inklusive Folgeschäden bis 10.000 €",
|
||
"Fahrzeugteile und Zubehör bis 20.000 € beitragsfrei"]},
|
||
{gruppe:"Nach einem Totalschaden", posten:[
|
||
"Neupreisentschädigung bei Totalschaden binnen 12 Monaten nach Erstzulassung",
|
||
"Zulassungs- und Verwaltungskosten für das Ersatzfahrzeug bis 200 €",
|
||
"Überführungskosten bei Neuwagenkauf bis 1.000 €",
|
||
"Austausch der Schlösser bis 1.000 € bei Raub oder Einbruchdiebstahl der Schlüssel"]},
|
||
{gruppe:"Werkstatt", posten:[
|
||
"Werkstattsteuerung über das Fachwerkstattnetz des Versicherers",
|
||
"Außerhalb des Netzes nur 80 % der Reparaturkosten, abzüglich Selbstbeteiligung",
|
||
"Reparatur nach Herstellervorgaben mit Originalteilen oder gleichwertigen Teilen"]},
|
||
{gruppe:"Mobilität", posten:[
|
||
"Schutzbrief Mobilität, europaweit rund um die Uhr",
|
||
"Pannen- und Unfallhilfe, auch bei Diebstahl oder Fahrerausfall",
|
||
"Ersatzmobilität, wenn das Fahrzeug nicht binnen 60 Minuten fahrbereit ist"]},
|
||
{gruppe:"Automatisierte Fahrfunktionen", posten:[
|
||
"Kein Rabattverlust, wenn allein die automatisierte Fahrfunktion den Schaden verursacht hat",
|
||
"Nachweis durch die gespeicherten Fahrzeugdaten zum Schadenereignis"]}
|
||
]},
|
||
steuer:{betrag:434, zeitraum:"jährlich", faellig:"", grundlage:"Hubraum und CO₂-Ausstoß",
|
||
lastschrift:true, finanzamt:"Hauptzollamt"},
|
||
kmProTag: 18.3, // aus dem Servicebuch: 19 864 km in 1 085 Tagen
|
||
/* Technische Daten aus dem Fahrzeugdatenblatt (FIN WUAZZZF48PA902804). */
|
||
technik:[
|
||
{gruppe:"Motor", posten:[
|
||
["Bauart","V6 Ottomotor, Direkteinspritzung, Biturbo"],
|
||
["Hubraum","2 894 cm³"],
|
||
["Leistung","331 kW / 450 PS bei 5 700–6 700 min⁻¹"],
|
||
["Maximales Drehmoment","600 Nm bei 2 000–5 000 min⁻¹"],
|
||
["Abgasreinigung","Katalysator, Lambdasonde, Ottopartikelfilter"],
|
||
["Abgasnorm","EU6 AP"],
|
||
["Motormanagement","vollelektronisch"]]},
|
||
{gruppe:"Kraftübertragung", posten:[
|
||
["Getriebe","8-Gang tiptronic"],
|
||
["Antrieb","quattro, permanent, selbstsperrendes Mittendifferenzial"],
|
||
["Kupplung","hydraulischer Drehmomentwandler mit Überbrückung"]]},
|
||
{gruppe:"Fahrleistungen", posten:[
|
||
["0 auf 100 km/h","3,9 s"],
|
||
["Höchstgeschwindigkeit","290 km/h"],
|
||
["Effizienzklasse","E"],
|
||
["Fahrgeräusch","70 dB(A)"]]},
|
||
{gruppe:"Fahrwerk, Lenkung, Bremsen", posten:[
|
||
["Fahrwerk","RS-Sportfahrwerk"],
|
||
["Vorderachse","5-Lenker, Rohrstabilisator"],
|
||
["Hinterachse","5-Lenker, Rohrstabilisator"],
|
||
["Lenkung","elektromechanisch, geschwindigkeitsabhängig"],
|
||
["Wendekreis","ca. 11,7 m"],
|
||
["Bremsanlage","RS-Stahlbremse, Sättel rot glänzend"],
|
||
["Vorn","Faustsattel, Scheibe innenbelüftet"],
|
||
["Hinten","Faustsattel mit elektrischer Parkbremse, innenbelüftet"]]},
|
||
{gruppe:"Räder und Reifen", posten:[
|
||
["Räder","Leichtmetall 9J × 20, Audi Sport"],
|
||
["Reifen","275/30 R20 97Y XL"],
|
||
["Pannenhilfe","Reifenreparaturset, kein Ersatzrad"],
|
||
["Radschrauben","Standard"],
|
||
["Anzugsmoment","120 Nm"]]},
|
||
{gruppe:"Maße, Gewichte, Volumen", posten:[
|
||
["Leergewicht","1 820 kg"],
|
||
["Zulässiges Gesamtgewicht","2 350 kg"],
|
||
["Dachlast / Stützlast","90 / 80 kg"],
|
||
["Anhängelast gebremst","2 100 kg bei 8 %, 1 900 kg bei 12 %"],
|
||
["Anhängelast ungebremst","750 kg"],
|
||
["Gepäckraum","495 / 1 495 l"],
|
||
["Tankinhalt","58 l, erhöhtes Füllvolumen für quattro"]]},
|
||
{gruppe:"Bordnetz", posten:[
|
||
["Batterie","420 A, 75 Ah"],
|
||
["Generator","100–150 A"],
|
||
["Kältemittel","R1234yf"]]},
|
||
{gruppe:"Wartung", posten:[
|
||
["Serviceanzeige","30 000 km oder 2 Jahre, variabel"],
|
||
["Garantie","Anschlussgarantie 3 Jahre, max. 100 000 km"]]}
|
||
],
|
||
|
||
/* Ausstattung. Sonderausstattung vollständig, Serienausstattung auf das
|
||
Aussagekräftige gekürzt — Einträge wie „Kein Selbstabholer" sind
|
||
Produktionsmerkmale und im Alltag ohne Nutzen. */
|
||
ausstattung:[
|
||
{gruppe:"RS-Paket", sonder:["RS competition","RS-Designpaket rot","RS-Komfortpaket",
|
||
"RS-Sportabgasanlage plus","RS-Sportfahrwerk","RS-Stahlbremsanlage, Sättel rot glänzend",
|
||
"Bremssättel rot lackiert","Anhebung der Höchstgeschwindigkeit auf 290 km/h",
|
||
"Sicherheitsgurte schwarz mit rotem Rand","RS-Einstiegsleisten"]},
|
||
{gruppe:"Außen", sonder:["Optikpaket schwarz plus","Optikpaket schwarz glänzend",
|
||
"Panorama-Glasdach","Dachreling schwarz","Anhängevorrichtung",
|
||
"Gepäckraumklappe elektrisch öffnend und schließend",
|
||
"Matrix-LED-Scheinwerfer mit dynamischer Lichtinszenierung",
|
||
"LED-Heckleuchten mit dynamischer Lichtinszenierung",
|
||
"Außenspiegel elektrisch, beheiz- und anklappbar, abblendend, mit Memory",
|
||
"Außenspiegelgehäuse in Wagenfarbe","Sonnenschutzverglasung abgedunkelt"]},
|
||
{gruppe:"Innen", sonder:["Mikrofaser Dinamica/Leder mit Wabensteppung und RS-Stickung",
|
||
"Sportsitze plus vorn","Vordersitze elektrisch mit Memory für den Fahrersitz",
|
||
"Sitzheizung vorn und hinten","Lendenwirbelstütze mit Massagefunktion",
|
||
"Dekoreinlagen Carbon Köper matt","Ambiente-Lichtpaket plus",
|
||
"3-Zonen-Komfortklimaautomatik","Lederlenkrad 3-Speichen mit Lenkradheizung",
|
||
"Innenspiegel automatisch abblendend, rahmenlos","USB-Ladeschnittstellen im Fond",
|
||
"Sonnenschutzrollo hinten","Fußmatten RS-Designpaket"]},
|
||
{gruppe:"Infotainment", sonder:["MMI Navigation plus mit MMI touch","Audi virtual cockpit plus",
|
||
"Head-up-Display","Bang & Olufsen Premium Sound System mit 3D-Klang","Audi phone box",
|
||
"LTE-Unterstützung für Audi phone box","Audi connect Navigation & Infotainment"]},
|
||
{gruppe:"Assistenz", sonder:["Assistenzpaket Tour","Assistenzpaket Stadt mit Parken",
|
||
"Audi adaptive cruise control","Audi active lane assist","Halteassistent",
|
||
"Parkassistent mit Einparkhilfe plus","Umgebungskameras",
|
||
"Kamerabasierte Verkehrszeichenerkennung","Audi pre sense rear und basic",
|
||
"Garagentoröffner","Komfortschlüssel mit sensorgesteuerter Heckklappe"]},
|
||
{gruppe:"Serie, ausgewählt", sonder:["Audi drive select","Audi pre sense city",
|
||
"Spurwechselwarnung","Reifendruck-Kontrollanzeige","Start-Stop-System",
|
||
"Audi connect Notruf & Service mit Remote & Control","Smartphone-Interface",
|
||
"Kraftstoffbehälter mit erhöhtem Füllvolumen","Pedalerie und Fußstütze aus Edelstahl"]}
|
||
],
|
||
|
||
reifen:{aktiv:"Sommer",
|
||
wechsel:{datum:"2026-10-15", vereinbart:false},
|
||
anzugsmoment:120, // Nm
|
||
sommer:{bild:"bilder/rad-sommer.webp", km:31240,marke:"Continental",modell:"SportContact 7",dot:"1224",mass:"275/30 R20 97Y XL",
|
||
druck:"2,5 / 2,4 bar",kauf:"04/2024",kommentar:"Profiltiefe 5,1 mm bei der letzten Kontrolle"},
|
||
winter:{bild:"bilder/rad-winter.webp", km:24870,marke:"Michelin",modell:"Pilot Alpin 5",dot:"3822",mass:"265/35 R19",
|
||
druck:"2,6 / 2,5 bar",kauf:"10/2022",kommentar:"Eingelagert beim Autohaus"}},
|
||
service:{
|
||
autohaus:{name:"Audi AG Kundendienst Center Ingolstadt",
|
||
adresse:"Auto-Union-Straße, 85045 Ingolstadt",
|
||
tel:"0841 8930600", mail:"kundendienstcenter.ingolstadt@audi.de",
|
||
pos:[48.78108, 11.42408]},
|
||
/* Die Termine werden nicht gespeichert, sondern aus Servicebuch und
|
||
Einstellungen berechnet. Gespeichert wird nur, was vereinbart wurde. */
|
||
vereinbart:{},
|
||
buch:[
|
||
{datum:"23.07.2026", km:19874, art:"Ölwechsel-Service (flexibel)", werkstatt:"Audi AG Kundendienst Center Ingolstadt", kosten:null},
|
||
{datum:"20.10.2025", km:13335, art:"Inspektion", werkstatt:"Audi AG Kundendienst Center Ingolstadt", kosten:null},
|
||
{datum:"11.07.2025", km:10000, art:"Ölwechsel-Service (flexibel)", werkstatt:"Audi AG Kundendienst Center Ingolstadt", kosten:null},
|
||
{datum:"11.10.2024", km:1500, art:"Ölwechsel-Service (flexibel)", werkstatt:"Audi AG Kundendienst Center Ingolstadt", kosten:null},
|
||
{datum:"04.08.2023", km:10, art:"Übergabe-Inspektion", werkstatt:"Audi AG Kundendienst Center Ingolstadt", kosten:null}
|
||
]}
|
||
};
|
||
|
||
const TRIPS = [
|
||
{id:"t1",jahr:2026,monat:"Juli",tag:"29.07.",zeit:"07:12",von:"Ingolstadt, Am Westpark",nach:"München, Leopoldstr.",
|
||
kmA:87220,kmE:87308,dist:88,dauer:"1:04 h",schnitt:82,max:171,kosten:18.55,art:"Arbeitsweg",nacht:false,
|
||
a:[48.7628,11.4030],b:[48.1600,11.5860]},
|
||
{id:"t2",jahr:2026,monat:"Juli",tag:"29.07.",zeit:"19:40",von:"München, Leopoldstr.",nach:"Ingolstadt, Am Westpark",
|
||
kmA:87308,kmE:87396,dist:88,dauer:"0:58 h",schnitt:91,max:184,kosten:18.12,art:"Arbeitsweg",nacht:true,
|
||
a:[48.1600,11.5860],b:[48.7628,11.4030]},
|
||
{id:"t3",jahr:2026,monat:"Juli",tag:"27.07.",zeit:"10:35",von:"Ingolstadt, Am Westpark",nach:"Rain am Lech, Salbeiweg",
|
||
kmA:87074,kmE:87142,dist:68,dauer:"0:51 h",schnitt:80,max:158,kosten:14.41,art:"Privat",nacht:false,
|
||
a:[48.7628,11.4030],b:[48.6890,10.9160]},
|
||
{id:"t4",jahr:2026,monat:"Juni",tag:"18.06.",zeit:"14:05",von:"Ingolstadt, Am Westpark",nach:"Regensburg, Donaupark",
|
||
kmA:86412,kmE:86528,dist:116,dauer:"1:19 h",schnitt:88,max:176,kosten:23.90,art:"Privat",nacht:false,
|
||
a:[48.7628,11.4030],b:[49.0195,12.0975]},
|
||
{id:"t5",jahr:2025,monat:"Dezember",tag:"22.12.",zeit:"20:15",von:"Ingolstadt, Am Westpark",nach:"Garmisch, Hauptstr.",
|
||
kmA:79880,kmE:80062,dist:182,dauer:"2:11 h",schnitt:83,max:169,kosten:36.40,art:"Privat",nacht:true,
|
||
a:[48.7628,11.4030],b:[47.4917,11.0955]}
|
||
];
|
||
|
||
/* rabatt = Ersparnis durch SmartDeal, summe = tatsächlich gezahlt */
|
||
const FILLS = [
|
||
{id:"f1",pctVor:26,pctNach:100,jahr:2026,monat:"Juli",datum:"29.07.2026",zeit:"16:05",liter:42.96,summe:90.60,rabatt:12.46,
|
||
odo:87396,seit:322,station:"A. Zrenner GmbH",adresse:"Pascalstr. 8, 85057 Ingolstadt",beleg:true,pos:[48.7476,11.4497]},
|
||
{id:"f2",pctVor:18,pctNach:100,jahr:2026,monat:"Juli",datum:"27.07.2026",zeit:"11:28",liter:47.61,summe:100.88,rabatt:13.81,
|
||
odo:87074,seit:546,station:"Thomas Bauch GmbH",adresse:"Salbeiweg 2, 86641 Rain am Lech",beleg:true,pos:[48.6903,10.9174]},
|
||
{id:"f3",pctVor:22,pctNach:100,jahr:2026,monat:"Juni",datum:"14.06.2026",zeit:"08:12",liter:45.20,summe:94.42,rabatt:13.11,
|
||
odo:86528,seit:498,station:"A. Zrenner GmbH",adresse:"Pascalstr. 8, 85057 Ingolstadt",beleg:true,pos:[48.7476,11.4497]},
|
||
{id:"f4",pctVor:30,pctNach:96,jahr:2025,monat:"Dezember",datum:"20.12.2025",zeit:"17:41",liter:44.10,summe:85.95,rabatt:12.79,
|
||
odo:79880,seit:512,station:"Thomas Bauch GmbH",adresse:"Salbeiweg 2, 86641 Rain am Lech",beleg:true,pos:[48.6903,10.9174]}
|
||
];
|
||
|
||
/* ---------------------------------------------------------------- */
|
||
const $ = s => document.querySelector(s);
|
||
const de = (n,d=0)=>n.toLocaleString("de-DE",{minimumFractionDigits:d,maximumFractionDigits:d});
|
||
const eur = n => de(n,2);
|
||
const esc = s => String(s).replace(/[&<>"]/g,c=>({"&":"&","<":"<",">":">",'"':"""}[c]));
|
||
const sum = (a,f)=>a.reduce((s,x)=>s+f(x),0);
|
||
/* Durchschnittspreis IMMER mengengewichtet: Summe Kosten / Summe Liter */
|
||
const schnittpreis = list => sum(list,f=>f.summe)/sum(list,f=>f.liter);
|
||
|
||
/* Symbole der Navigationsleiste. „Mein Audi" nutzt die RS-Raute aus dem
|
||
Typenschild — als Umriss, gefüllt sobald der Reiter aktiv ist. */
|
||
const ICONS = {
|
||
home :'<path d="M4 17a9 9 0 0 1 18 0"/><path d="M13 17l5.5-5"/><circle cx="13" cy="17" r="1.3"/>',
|
||
audi :'<polygon points="21.6,5 16.5,19 2.4,19 7.5,5" transform="translate(0,0)"/>',
|
||
trips:'<circle cx="6" cy="6" r="2.2"/><circle cx="18" cy="18" r="2.2"/><path d="M8 7.5c4 1.5 4.5 3 3 5s-1 3.5 4.5 5"/>',
|
||
stat :'<path d="M4 20V9.5M10 20V4.5M16 20v-8M22 20H2"/>',
|
||
fuel :'<path d="M4.5 20V6.2c0-.9.8-1.7 1.7-1.7h5.6c1 0 1.7.8 1.7 1.7V20"/><path d="M3 20h12.5"/><path d="M4.5 11h10.5"/><path d="M17 20v-8.5a2 2 0 0 0-2-2"/><path d="M17 11.5V7.8l-2-2.3"/>'
|
||
};
|
||
|
||
|
||
const TABS = [
|
||
{id:"home", label:"Übersicht", eyebrow:"Fahrzeug", title:"Übersicht"},
|
||
{id:"audi", label:"Mein Audi", eyebrow:"Fahrzeug", title:CONFIG.fahrzeugtitel},
|
||
{id:"trips",label:"Fahrten", eyebrow:"Fahrtenbuch",title:"Fahrten"},
|
||
{id:"stat", label:"Statistik", eyebrow:"Auswertung", title:"Statistik"},
|
||
{id:"fuel", label:"Tanken", eyebrow:"Kraftstoff", title:"Tanken"}
|
||
];
|
||
let route = {name:"home"};
|
||
const ZURUECK = {trip:"trips", fill:"fuel", service:"audi", reifen:"audi", ident:"audi",
|
||
vers:"audi", kosten:"audi", schutz:"vers",
|
||
werkstatt:"service", sbuch:"service", einst:"home"};
|
||
|
||
/* ---------- Grafik ---------- */
|
||
function badge(){
|
||
return `<div class="badge"><?xml version="1.0" encoding="UTF-8"?><svg aria-label="RS 4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 425 100"><polygon points="140 0 103.603 100 0 100 36.397 0 140 0" style="fill:#f50537;"/><path d="M279.9435,15c13.89,0,23.0062,9.5991,18.3107,22.5h-16.5c2.1994-6.0428-2.4854-9.5-6.5423-9.5h-48.5c-10,0-10.9525,2.617-12.6388,7.25-1.327,3.646-1.046,7.25,7.3612,7.25h48.5c12.7976,0,24.4649,5.5913,18.7656,21.25-5.1069,14.031-8.473,21.25-34.2344,21.25h-48.5c-22.238,0-20.8261-15.589-17.9467-23.5h16.5c-1.5172,4.1686-2.3153,10.5,6.1783,10.5h48.5c9.0063,0,11.2814-3.5205,13.0028-8.25,2.3539-6.4674-.7024-8.25-6.9972-8.25h-48.5c-16.0991,0-23.0423-9.5-19.1296-20.25,5.1394-14.1202,7.854-20.25,33.8704-20.25h48.5Z" style="fill:currentColor;"/><path d="M165.478,15h-70l-25.478,70h16.5l9.4633-26h59.5518c4.7471,0,6.8294,4.4041,4.2185,25.9165h16.9999v-8.9007c0-5.2722,0-17.0158-5.796-23.4287,6.8742-3.3009,10.0555-7.4061,12.8643-15.1234,4.6956-12.9009-4.4339-22.4637-18.3239-22.4637ZM100.6949,46l6.5515-18h53.5c4.0569,0,8.7549,3.4209,6.5555,9.4637-2.1993,6.0427-5.3154,8.5363-13.1069,8.5363h-53.5Z" style="fill:currentColor;"/><path d="M408.4969,59l16.0201-44h-24.75l-80.2974,39.2816-6.4489,17.7184h74.25l-4.7316,13h16.5s4.7316-13,4.7316-13h16.4977l4.7316-13h-16.5031ZM392.0022,59h-53.6829l64.966-31h0l-11.2831,31Z" style="fill:currentColor;"/></svg><span class="zusatz">${esc(CONFIG.fahrzeugzusatz)}</span></div>`;
|
||
}
|
||
const BILDER = [{name:"Seitenansicht",src:"bilder/seitenansicht.webp"},{name:"Front schräg",src:"bilder/front-schraeg.webp"},{name:"Frontansicht",src:"bilder/frontansicht.webp"},{name:"Heckansicht",src:"bilder/heckansicht.webp"},{name:"Cockpit",src:"bilder/cockpit.webp"},{name:"Scheinwerfer",src:"bilder/scheinwerfer.webp"},{name:"Sitze",src:"bilder/sitze.webp"}];
|
||
let bild = 0;
|
||
|
||
/* modus "fest": ein festes Bild, kein Umschalten (Übersicht).
|
||
modus "galerie": durchschaltbar per Antippen (Mein Audi).
|
||
Die Bildfläche hat in beiden Fällen dieselbe Höhe, damit Front- und
|
||
Seitenansicht gleich groß wirken. */
|
||
function startIndex(){
|
||
const i = BILDER.findIndex(b => b.name === CONFIG.startbild);
|
||
return i < 0 ? 0 : i;
|
||
}
|
||
|
||
/* Für die Seitenansicht liegt eine zweite Fassung mit montierten Winterrädern
|
||
bereit. Nur diese Perspektive zeigt die Räder groß genug, dass sich der
|
||
Austausch lohnt — die übrigen Ansichten bleiben unverändert. */
|
||
const SEITE_WINTER = "bilder/seitenansicht-winter.webp";
|
||
function bildSrc(i){
|
||
const b = BILDER[i];
|
||
return (b.name === "Seitenansicht" && CAR.reifen.aktiv === "Winter") ? SEITE_WINTER : b.src;
|
||
}
|
||
|
||
function carImg(modus){
|
||
if(modus === "fest"){
|
||
const b = BILDER[startIndex()];
|
||
return `<img class="carfix klein" src="${bildSrc(startIndex())}" alt="${esc(CONFIG.fahrzeugtitel)}">`;
|
||
}
|
||
return `<img id="carimg" class="carfix" src="${bildSrc(bild)}"
|
||
alt="${esc(CONFIG.fahrzeugtitel)}">
|
||
<div class="dots" id="dots">${BILDER.map((_,i)=>
|
||
`<i class="${i===bild?"on":""}"></i>`).join("")}</div>`;
|
||
}
|
||
|
||
/* Antippen schaltet weiter. Nur die betroffenen Knoten werden getauscht,
|
||
damit die Scrollposition erhalten bleibt. */
|
||
/* Bildmarke des Anbieters. Geschützte Zeichen werden nicht nachgezeichnet —
|
||
hier steht ein Platz, in den die Originaldatei eingesetzt wird. */
|
||
function markenlogo(){
|
||
if(!CAR.smartdeal.aktiv) return "";
|
||
return CONFIG.markenlogo
|
||
? `<img src="${esc(CONFIG.markenlogo)}" alt="${esc(CONFIG.markenname)}">`
|
||
: `<span class="ph">Logo</span>`;
|
||
}
|
||
|
||
/* Cockpit, Sitze und der Scheinwerfer-Ausschnitt zeigen keine Fahrbahn —
|
||
eine verschneite Straße hinter einem Innenraumfoto wäre Unsinn. */
|
||
const OHNE_SZENE = ["Cockpit","Sitze","Scheinwerfer"];
|
||
function szeneKlasse(i){
|
||
if(!bodenAn) return "";
|
||
if(OHNE_SZENE.includes(BILDER[i].name)) return "";
|
||
return CAR.reifen.aktiv === "Winter" ? "winter" : "strasse";
|
||
}
|
||
|
||
function bildWeiter(){
|
||
bild = (bild + 1) % BILDER.length;
|
||
const img=document.getElementById("carimg");
|
||
if(!img) return;
|
||
img.src = bildSrc(bild);
|
||
const sz=document.getElementById("szene");
|
||
if(sz) sz.className = "szene " + szeneKlasse(bild);
|
||
[...document.getElementById("dots").children].forEach((d,i)=>
|
||
d.classList.toggle("on", i===bild));
|
||
}
|
||
|
||
/* ---------- Termine und Vorhersage ---------- */
|
||
const heute = new Date(2026,7,3);
|
||
const dTag = 86400000;
|
||
const mmjj = d => String(d.getMonth()+1).padStart(2,"0")+"/"+String(d.getFullYear()).slice(2);
|
||
const dedat = d => d.toLocaleDateString("de-DE",{day:"2-digit",month:"2-digit",year:"numeric"});
|
||
|
||
/* Aus der durchschnittlichen Tagesleistung ableiten, wann ein Kilometerstand
|
||
erreicht ist. Grundlage ist die Statistik, nicht eine Annahme. */
|
||
/* Die Tagesleistung wird aus dem ältesten Servicebuch-Eintrag und dem
|
||
aktuellen Kilometerstand berechnet — sie wächst also mit jedem gefahrenen
|
||
Kilometer mit, statt ein fester Wert zu bleiben. */
|
||
function dat(s){ const [d,m,j]=s.split(".").map(Number); return new Date(j,m-1,d); }
|
||
|
||
/* Zwei Zeiträume, gewichtet gemischt:
|
||
- langfristig: der gesamte bekannte Verlauf seit dem ältesten Eintrag
|
||
- aktuell: seit dem letzten Service, also seit dem Zurücksetzen des Zählers
|
||
Direkt nach einem Service ist der aktuelle Zeitraum zu kurz für eine
|
||
belastbare Aussage, deshalb überwiegt zunächst der Langzeitwert. Mit jedem
|
||
Tag verschiebt sich das Gewicht, nach etwa einem halben Jahr zählt allein
|
||
der aktuelle Abschnitt. Die Vorhersage wird also genauer, je näher das Ziel
|
||
rückt — und startet nach jedem Service neu. */
|
||
const MISCHDAUER = 180;
|
||
|
||
function tagesleistung(){
|
||
const b=CAR.service.buch;
|
||
if(!b.length) return {wert:CAR.kmProTag, quelle:"Vorgabe", tage:0, km:0};
|
||
|
||
const alt = b[b.length-1];
|
||
const tageGesamt = Math.max(1, (heute - dat(alt.datum))/dTag);
|
||
const langfristig = (CAR.odo - alt.km)/tageGesamt;
|
||
|
||
const letzter = b[0];
|
||
const tageSeit = (heute - dat(letzter.datum))/dTag;
|
||
const kmSeit = CAR.odo - letzter.km;
|
||
|
||
if(tageSeit < 14 || kmSeit <= 0)
|
||
return {wert:langfristig, quelle:"gesamter Verlauf", tage:Math.round(tageGesamt), km:CAR.odo-alt.km};
|
||
|
||
const aktuell = kmSeit/tageSeit;
|
||
const g = Math.min(1, tageSeit/MISCHDAUER);
|
||
return {
|
||
wert: langfristig*(1-g) + aktuell*g,
|
||
quelle: g>=1 ? "seit dem letzten Service" : "gemischt, "+Math.round(g*100)+" % aktueller Abschnitt",
|
||
tage: Math.round(tageSeit), km: kmSeit
|
||
};
|
||
}
|
||
|
||
function kmProTag(){ return tagesleistung().wert; }
|
||
|
||
function prognose(zielKm){
|
||
const rest = zielKm - CAR.odo;
|
||
if(rest <= 0) return {tage:0, datum:heute};
|
||
const tage = Math.round(rest / kmProTag());
|
||
return {tage, datum:new Date(heute.getTime() + tage*dTag)};
|
||
}
|
||
|
||
/* Kalendereintrag als ICS. iOS öffnet die Datei direkt in der Kalender-App. */
|
||
function ics(titel, datum, ort, notiz){
|
||
const tag = datum.replace(/-/g,"");
|
||
const naechster = new Date(new Date(datum).getTime()+dTag)
|
||
.toISOString().slice(0,10).replace(/-/g,"");
|
||
const text = [
|
||
"BEGIN:VCALENDAR","VERSION:2.0","PRODID:-//RS4 Dashboard//DE","BEGIN:VEVENT",
|
||
"UID:"+Date.now()+"@rs4.local",
|
||
"DTSTAMP:"+new Date().toISOString().replace(/[-:]/g,"").split(".")[0]+"Z",
|
||
"DTSTART;VALUE=DATE:"+tag, "DTEND;VALUE=DATE:"+naechster,
|
||
"SUMMARY:"+titel, "LOCATION:"+(ort||""), "DESCRIPTION:"+(notiz||""),
|
||
"BEGIN:VALARM","TRIGGER:-P2D","ACTION:DISPLAY","DESCRIPTION:"+titel,"END:VALARM",
|
||
"END:VEVENT","END:VCALENDAR"].join("\r\n");
|
||
const a=document.createElement("a");
|
||
a.href="data:text/calendar;charset=utf-8,"+encodeURIComponent(text);
|
||
a.download=titel.replace(/[^\wäöüÄÖÜß ]/g,"").replace(/\s+/g,"-")+".ics";
|
||
document.body.appendChild(a); a.click(); a.remove();
|
||
}
|
||
|
||
function ring(pct){
|
||
const r=64,c=2*Math.PI*r,on=c*pct/100;
|
||
return `<div class="ringwrap">
|
||
<svg width="150" height="150" viewBox="0 0 150 150">
|
||
<circle cx="75" cy="75" r="${r}" fill="none" stroke="var(--line)" stroke-width="2"/>
|
||
<circle cx="75" cy="75" r="${r}" fill="none" stroke="var(--red)" stroke-width="2"
|
||
stroke-linecap="round" stroke-dasharray="${on} ${c}" transform="rotate(-90 75 75)"/>
|
||
</svg>
|
||
<div class="mid">
|
||
<div class="fig" style="font-size:40px">${pct}<span class="unit">%</span></div>
|
||
<span class="label" style="margin-top:8px">${de(CONFIG.tankvolumen*pct/100,1)} Liter</span>
|
||
</div></div>`;
|
||
}
|
||
let MAP=null, TILE=null;
|
||
const TILES={
|
||
nacht:"https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
|
||
tag :"https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png"
|
||
};
|
||
const ATTR='© OpenStreetMap · CARTO';
|
||
|
||
function mapBox(){ return `<div class="mapbox"><div id="map"></div></div>`; }
|
||
|
||
/* Aus Start und Ziel einen plausiblen Streckenverlauf erzeugen.
|
||
Im Betrieb steht hier der tatsaechlich aufgezeichnete Track aus §4. */
|
||
function fakeTrack(a,b,n=13){
|
||
const pts=[]; let seed=Math.round((a[0]+b[1])*1000);
|
||
const rnd=()=>{ seed=(seed*1103515245+12345)&0x7fffffff; return seed/0x7fffffff-0.5; };
|
||
for(let i=0;i<=n;i++){
|
||
const t=i/n, k=Math.sin(t*Math.PI);
|
||
pts.push([ a[0]+(b[0]-a[0])*t + rnd()*0.05*k, a[1]+(b[1]-a[1])*t + rnd()*0.05*k ]);
|
||
}
|
||
pts[0]=a; pts[n]=b; return pts;
|
||
}
|
||
|
||
function tiles(){
|
||
if(!MAP) return;
|
||
const url=TILES[document.documentElement.dataset.theme];
|
||
if(TILE) MAP.removeLayer(TILE);
|
||
TILE=L.tileLayer(url,{maxZoom:19,attribution:ATTR}).addTo(MAP);
|
||
}
|
||
|
||
function initMap(){
|
||
const el=document.getElementById("map");
|
||
if(!el || typeof L==="undefined") return;
|
||
MAP=L.map(el,{zoomControl:true,attributionControl:true,scrollWheelZoom:false});
|
||
TILE=null; tiles();
|
||
const rot=getComputedStyle(document.documentElement).getPropertyValue("--red").trim()||"#F50537";
|
||
|
||
if(route.name==="trip"){
|
||
const t=TRIPS.find(x=>x.id===route.id);
|
||
const track=fakeTrack(t.a,t.b);
|
||
const line=L.polyline(track,{color:rot,weight:2.5,opacity:.9}).addTo(MAP);
|
||
/* Stützpunkte sichtbar machen — der Verlauf ist eine Naeherung, keine luekenlose Spur */
|
||
track.slice(1,-1).forEach(pt=>L.circleMarker(pt,
|
||
{radius:2.5,color:rot,weight:0,fillColor:rot,fillOpacity:.85}).addTo(MAP));
|
||
L.circleMarker(t.a,{radius:6,color:"#fff",weight:2,fillColor:"#000",fillOpacity:1}).addTo(MAP)
|
||
.bindPopup("Start · "+t.von);
|
||
L.circleMarker(t.b,{radius:6,color:rot,weight:2,fillColor:rot,fillOpacity:1}).addTo(MAP)
|
||
.bindPopup("Ziel · "+t.nach);
|
||
MAP.fitBounds(line.getBounds(),{padding:[26,26]});
|
||
} else if(route.name==="fill"){
|
||
const f=FILLS.find(x=>x.id===route.id);
|
||
MAP.setView(f.pos,14);
|
||
L.circleMarker(f.pos,{radius:7,color:rot,weight:2,fillColor:rot,fillOpacity:.85}).addTo(MAP)
|
||
.bindPopup(f.station+"<br>"+f.adresse);
|
||
}
|
||
setTimeout(()=>MAP.invalidateSize(),60);
|
||
}
|
||
|
||
/* ---------- Ansichten ---------- */
|
||
function teaser(){
|
||
const t=TRIPS[0], f=FILLS[0];
|
||
return `<div class="tile"><span class="label">Zuletzt</span>
|
||
<button class="leaf" style="padding-left:0" data-go="trip:${t.id}">
|
||
<span class="k">Letzte Fahrt<small>${t.tag} · ${esc(t.von.split(",")[0])} → ${esc(t.nach.split(",")[0])}</small></span>
|
||
<span class="v">${de(t.dist)} km<small>${t.dauer}</small></span>
|
||
<svg class="chev" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg></button>
|
||
<button class="leaf" style="padding-left:0;border-bottom:0" data-go="fill:${f.id}">
|
||
<span class="k">Letzter Tankvorgang<small>${f.datum} · ${esc(f.station)}</small></span>
|
||
<span class="v">${de(f.liter,2)} l<small>${eur(f.summe)} €</small></span>
|
||
<svg class="chev" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg></button></div>`;
|
||
}
|
||
|
||
/* Der zeitlich nächste aller Termine — nicht einfach der erste in der Liste. */
|
||
function naechsterTermin(){
|
||
return termine().slice().sort((a,b)=>a.ziel-b.ziel)[0];
|
||
}
|
||
|
||
/* Einheitliche Beschreibung eines Termins für alle Ansichten */
|
||
/* Zwei Sichtweisen auf denselben Termin: das in den Einstellungen gewählte
|
||
Intervall und die Vorgabe des Herstellers. Beide werden nebeneinander
|
||
gezeigt, keine ist verbindlich. */
|
||
function intervalle(t){
|
||
const oel=CAR.oel, b=t.basis;
|
||
if(!b) return null;
|
||
|
||
const bauen=(km, monate) => ({
|
||
km: km ? b.km + km : null,
|
||
datum: monatePlus(b.datum, monate)
|
||
});
|
||
|
||
if(t.art==="Hauptuntersuchung"){
|
||
const eig = bauen(null, 24);
|
||
return {hersteller:null, eigen:eig, prognose:eig.datum};
|
||
}
|
||
|
||
const eKm = t.art==="Ölwechsel"
|
||
? (oel.modus==="hersteller" ? oel.herstellerKm : Math.min(oel.km, oel.herstellerKm))
|
||
: 30000;
|
||
const eM = t.art==="Ölwechsel"
|
||
? (oel.modus==="hersteller" ? oel.herstellerMonate : Math.min(oel.monate, oel.herstellerMonate))
|
||
: 24;
|
||
|
||
const eig = bauen(eKm, eM);
|
||
const her = t.art==="Ölwechsel" ? bauen(oel.herstellerKm, oel.herstellerMonate) : bauen(30000, 24);
|
||
/* Voraussichtlich: wann der eigene Zielkilometerstand nach der gemessenen
|
||
Fahrleistung erreicht ist — oder das Zeitintervall, falls es früher greift. */
|
||
const perKm = prognose(eig.km).datum;
|
||
return {hersteller:her, eigen:eig, prognose: perKm < eig.datum ? perKm : eig.datum};
|
||
}
|
||
|
||
function terminText(t){
|
||
const restKm = t.km!==null ? t.km-CAR.odo : null;
|
||
const haupt = t.zuerst==="km" && restKm!==null ? "in "+de(restKm)+" km" : dedat(t.datum);
|
||
const neben = t.zuerst==="km"
|
||
? "voraussichtlich "+dedat(t.kmDatum)+" · oder "+dedat(t.datum)
|
||
: (t.km!==null ? "oder in "+de(restKm)+" km" : "aus dem Servicebuch fortgeschrieben");
|
||
return {haupt, neben, restKm};
|
||
}
|
||
|
||
function vHome(){
|
||
const g = CAR.gesichert;
|
||
return `
|
||
<div class="szene ${szeneKlasse(startIndex())}"><div class="carbox">${carImg("fest")}</div></div>
|
||
<div class="tile flat" style="margin-bottom:22px">
|
||
${badge()}
|
||
<span class="label" style="margin-top:12px">${esc(CONFIG.kennzeichen)} · ${esc(CONFIG.fahrzeuguntertitel)}</span>
|
||
<div class="status">
|
||
<span class="dot ${g?"":"bad"}"></span>
|
||
<div><div class="t">${g?"Sicher abgestellt":"Nicht sicher abgestellt"}</div>
|
||
<div class="s">${g?"Verriegelt · Türen zu · Fenster zu":"Beifahrerfenster offen"}</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tile flat" style="margin-bottom:26px">
|
||
<div class="tankzeile">
|
||
<div class="fig" style="font-size:60px">418<span class="unit">km</span></div>
|
||
<span class="pct">${CAR.tankPct} %</span>
|
||
</div>
|
||
<div class="balken"><i style="width:${CAR.tankPct}%"></i></div>
|
||
<span class="label" style="margin-top:12px">Reichweite</span>
|
||
</div>
|
||
|
||
<div class="duo">
|
||
<div class="tile"><span class="label">Kilometerstand</span>
|
||
<div class="fig" style="font-size:29px;margin-top:14px">${de(CAR.odo)}<span class="unit">km</span></div></div>
|
||
${(()=>{const t=naechsterTermin();
|
||
return `<div class="tile"><span class="label">Nächster ${esc(t.art)}</span>
|
||
<div class="zweizeiler">
|
||
<span class="fig" style="font-size:29px">${t.zuerst==="km"?de(t.km-CAR.odo):mmjj(t.datum)}<span class="unit">${t.zuerst==="km"?"km":""}</span></span>
|
||
<span class="nebenwert">${t.zuerst==="km"?mmjj(t.kmDatum):"fällig"}</span>
|
||
</div></div>`;})()}
|
||
</div>
|
||
${teaser()}`;
|
||
}
|
||
|
||
function vAudi(){
|
||
const r=CAR.reifen, a=r[r.aktiv.toLowerCase()], sv=CAR.service;
|
||
return `
|
||
<div class="szene ${szeneKlasse(bild)}" id="szene"><div class="carbox">${carImg("galerie")}</div></div>
|
||
<div class="tile flat" style="margin:14px 0 16px">
|
||
${badge()}
|
||
<span class="label" style="margin-top:12px">${esc(CONFIG.kennzeichen)}</span>
|
||
</div>
|
||
<button class="tile tilebtn" data-go="ident:x">
|
||
<span class="label">Identität</span>
|
||
<svg class="go" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg>
|
||
<dl class="rows" style="margin-top:10px">
|
||
<div class="row"><dt>Fahrgestellnummer</dt><dd>${CAR.fin}</dd></div>
|
||
<div class="row"><dt>Details</dt><dd>${CAR.details}</dd></div>
|
||
<div class="row"><dt>Erstzulassung</dt><dd>${CAR.erstzulassung}</dd></div>
|
||
<div class="row"><dt>Ausführung</dt><dd>competition</dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Ausstattung</dt>
|
||
<dd>${CAR.ausstattung.reduce((n,g)=>n+g.sonder.length,0)} Positionen</dd></div>
|
||
</dl></button>
|
||
<div class="tile"><span class="label">Zustand</span><dl class="rows">
|
||
<div class="row"><dt>Kilometerstand</dt><dd>${de(CAR.odo)} km</dd></div>
|
||
<div class="row"><dt>Tankfüllung</dt><dd>${de(CONFIG.tankvolumen*CAR.tankPct/100,1)} l<small>${CAR.tankPct} % von ${CONFIG.tankvolumen} l</small></dd></div>
|
||
<div class="row"><dt>Batteriespannung</dt><dd>${de(CAR.spannung,1)} V</dd></div></dl></div>
|
||
|
||
<button class="tile tilebtn" data-go="service:x">
|
||
<span class="label">Service</span>
|
||
<svg class="go" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg>
|
||
<dl class="rows" style="margin-top:12px">
|
||
${termine().map((t,i,arr)=>{const x=terminText(t);
|
||
return `<div class="row" ${i===arr.length-1?'style="border-bottom:0"':""}>
|
||
<dt>${t.art}</dt><dd>${x.haupt}<small>${x.neben}</small></dd></div>`;}).join("")}
|
||
</dl></button>
|
||
|
||
<button class="tile tilebtn" data-go="kosten:x">
|
||
<span class="label">Kosten</span>
|
||
<svg class="go" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg>
|
||
${(()=>{const k=kosten(kostenJahr);
|
||
const teile=[k.kraftstoff,k.service,k.versicherung,k.steuer].filter(x=>x!==null);
|
||
const su=teile.reduce((a,b)=>a+b,0);
|
||
return `<div class="fig" style="font-size:34px;margin-top:12px">${eur(su)}<span class="unit">€</span></div>
|
||
<span class="label" style="margin-top:10px">${kostenJahr} · ${teile.length} von 4 Posten erfasst</span>`;})()}
|
||
</button>
|
||
|
||
<button class="tile tilebtn" data-go="vers:x">
|
||
<span class="label">Versicherung und Steuer</span>
|
||
<svg class="go" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg>
|
||
<dl class="rows" style="margin-top:10px">
|
||
<div class="row"><dt>Versicherung</dt><dd>${eur(CAR.versicherung.beitrag)} €<small>im Jahr</small></dd></div>
|
||
<div class="row"><dt>Kfz-Steuer</dt><dd>${eur(CAR.steuer.betrag)} €<small>${esc(CAR.steuer.zeitraum)}</small></dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Zusammen</dt>
|
||
<dd>${eur(CAR.versicherung.beitrag + CAR.steuer.betrag)} €<small>feste Kosten im Jahr</small></dd></div>
|
||
</dl></button>
|
||
|
||
<button class="tile tilebtn" data-go="reifen:x">
|
||
<span class="label">Reifen · ${r.aktiv} montiert</span>
|
||
<svg class="go" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg>
|
||
<dl class="rows" style="margin-top:10px">
|
||
<div class="row"><dt>${a.marke} ${a.modell}</dt><dd>${a.mass}</dd></div>
|
||
<div class="row"><dt>Laufleistung</dt><dd>${de(a.km)} km</dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Wechseltermin</dt>
|
||
<dd>${dedat(new Date(r.wechsel.datum))}<small>${r.wechsel.vereinbart?"vereinbart":"offen"}</small></dd></div>
|
||
</dl></button>`;
|
||
}
|
||
|
||
/* ---------- Service ---------- */
|
||
let svAuswahl = 0; // welcher Termin gerade bearbeitet wird
|
||
|
||
function vService(){
|
||
const sv=CAR.service;
|
||
return `
|
||
<div class="tile"><span class="label">Anstehende Termine</span>
|
||
<dl class="rows" style="margin-top:10px">
|
||
${termine().map((t,i,arr)=>{
|
||
const iv = intervalle(t);
|
||
if(!iv) return `<div class="row" ${i===arr.length-1?'style="border-bottom:0"':""}>
|
||
<dt>${t.art}</dt><dd style="color:var(--fg3)">kein Eintrag im Servicebuch</dd></div>`;
|
||
const anzeige = iv.hersteller || iv.eigen;
|
||
return `<div class="row" ${i===arr.length-1?'style="border-bottom:0"':""}>
|
||
<dt>${t.art}
|
||
${t.vereinbart ? `<br><span style="color:var(--red);font-size:11px">Werkstatt am ${dedat(new Date(t.vereinbart))}</span>` : ""}
|
||
</dt>
|
||
<dd>
|
||
${iv.hersteller ? `<span class="label" style="margin-bottom:6px">Herstellervorgabe</span>` : ""}
|
||
<span class="werte">${anzeige.km!==null?de(anzeige.km)+" km · ":""}${dedat(anzeige.datum)}</span>
|
||
<small>Voraussichtlich: ${dedat(iv.prognose)}${iv.eigen.km!==null?" / "+de(iv.eigen.km)+" km":""}</small>
|
||
</dd>
|
||
</div>`;}).join("")}
|
||
</dl>
|
||
${(()=>{const t=tagesleistung(); return `
|
||
<dl class="rows" style="margin-top:16px">
|
||
<div class="row"><dt>Fahrleistung</dt><dd>${de(t.wert,1)} km je Tag</dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Grundlage</dt><dd>${t.quelle}</dd></div>
|
||
|
||
</dl>
|
||
<span class="label" style="margin-top:14px">Nach jedem Service beginnt die Messung neu</span>`;})()}
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Termin vereinbaren</span>
|
||
${(()=>{const ts=termine(), t=ts[Math.min(svAuswahl,ts.length-1)];
|
||
const vorschlag = CAR.service.vereinbart[t.art]
|
||
|| (t.ziel ? t.ziel.toISOString().slice(0,10) : "");
|
||
return `
|
||
<div class="feld"><label for="svArt">Wofür</label>
|
||
<select id="svArt" data-svsel>${ts.map((x,i)=>
|
||
`<option value="${i}" ${i===svAuswahl?"selected":""}>${x.art}</option>`).join("")}</select></div>
|
||
<div class="feld" style="border-bottom:0"><label for="svDat">Werkstatttermin am</label>
|
||
<input id="svDat" type="date" value="${vorschlag}" data-vereinbart="${esc(t.art)}"></div>
|
||
<span class="label" style="margin-top:14px">Fälligkeit und Intervall kommen aus Servicebuch und
|
||
Einstellungen und lassen sich hier nicht überschreiben</span>
|
||
<button class="aktion" data-ics="service">In den Kalender übernehmen</button>
|
||
${CAR.service.vereinbart[t.art]?`<button class="aktion" data-loeschen="${esc(t.art)}">Termin verwerfen</button>`:""}`;})()}
|
||
</div>
|
||
|
||
<div class="tile">
|
||
<span class="label">Autohaus</span>
|
||
<button class="zahnrad" data-go="werkstatt:x" aria-label="Angaben ändern">
|
||
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/>
|
||
<path d="M19.1 14.6a1.5 1.5 0 0 0 .3 1.7l.1.1a1.8 1.8 0 1 1-2.6 2.6l-.1-.1a1.5 1.5 0 0 0-1.7-.3 1.5 1.5 0 0 0-.9 1.4v.2a1.8 1.8 0 1 1-3.6 0V20a1.5 1.5 0 0 0-1-1.4 1.5 1.5 0 0 0-1.7.3l-.1.1a1.8 1.8 0 1 1-2.6-2.6l.1-.1a1.5 1.5 0 0 0 .3-1.7 1.5 1.5 0 0 0-1.4-.9H4a1.8 1.8 0 1 1 0-3.6h.2a1.5 1.5 0 0 0 1.4-1 1.5 1.5 0 0 0-.3-1.7l-.1-.1a1.8 1.8 0 1 1 2.6-2.6l.1.1a1.5 1.5 0 0 0 1.7.3H9.8a1.5 1.5 0 0 0 .9-1.4V4a1.8 1.8 0 1 1 3.6 0v.2a1.5 1.5 0 0 0 .9 1.4 1.5 1.5 0 0 0 1.7-.3l.1-.1a1.8 1.8 0 1 1 2.6 2.6l-.1.1a1.5 1.5 0 0 0-.3 1.7v.1a1.5 1.5 0 0 0 1.4.9h.2a1.8 1.8 0 1 1 0 3.6H20a1.5 1.5 0 0 0-1.4.9z"/></svg>
|
||
</button>
|
||
<div style="font-size:15px;margin-top:12px">${esc(sv.autohaus.name)}</div>
|
||
<span class="label" style="margin-top:8px">${esc(sv.autohaus.adresse)}</span>
|
||
<a class="aktion" href="tel:${esc(sv.autohaus.tel.replace(/\s/g,""))}"
|
||
style="display:block;text-decoration:none;text-align:center;margin-top:16px">Anrufen · ${esc(sv.autohaus.tel)}</a>
|
||
<a class="aktion" target="_blank" rel="noopener"
|
||
href="https://maps.google.com/?q=${sv.autohaus.pos?sv.autohaus.pos.join(","):encodeURIComponent(sv.autohaus.adresse)}"
|
||
style="display:block;text-decoration:none;text-align:center">In Karten öffnen</a>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Servicebuch</span>
|
||
${sv.buch.map((e,i)=>`<button class="leaf" style="padding-left:0" data-go="sbuch:${i}">
|
||
<span class="k">${esc(e.art)}<small>${esc(e.werkstatt)}</small></span>
|
||
<span class="v">${e.datum}<small>${de(e.km)} km${e.kosten!=null?" · "+eur(e.kosten)+" €":""}</small></span>
|
||
<svg class="chev" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg></button>`).join("")}
|
||
<button class="aktion" data-sbneu>Eintrag hinzufügen</button>
|
||
</div>`;
|
||
}
|
||
|
||
/* ---------- Identität und Ausstattung ---------- */
|
||
function vIdent(){
|
||
return `
|
||
<div class="tile"><span class="label">Fahrzeug</span>
|
||
<dl class="rows" style="margin-top:10px">
|
||
<div class="row"><dt>Modell</dt><dd>${esc(CONFIG.fahrzeugtitel)}</dd></div>
|
||
<div class="row"><dt>Ausführung</dt><dd>competition</dd></div>
|
||
<div class="row"><dt>Fahrgestellnummer</dt><dd>${CAR.fin}</dd></div>
|
||
<div class="row"><dt>Motor und Leistung</dt><dd>${CAR.details}</dd></div>
|
||
<div class="row"><dt>Erstzulassung</dt><dd>${CAR.erstzulassung}</dd></div>
|
||
<div class="row"><dt>Kennzeichen</dt><dd>${esc(CONFIG.kennzeichen)}</dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Zulassung</dt><dd>Deutschland</dd></div>
|
||
</dl></div>
|
||
${CAR.technik.map(g=>`<div class="tile"><span class="label">${g.gruppe}</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${g.posten.map((pp,i)=>`<div class="row" ${i===g.posten.length-1?'style="border-bottom:0"':""}>
|
||
<dt>${esc(pp[0])}</dt>
|
||
<dd style="${pp[1]?"":"color:var(--fg3)"}">${pp[1]?esc(pp[1]):"noch offen"}</dd></div>`).join("")}
|
||
</dl></div>`).join("")}
|
||
${CAR.ausstattung.map(g=>`<div class="tile"><span class="label">${g.gruppe}</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${g.sonder.map((x,i)=>`<div class="row" ${i===g.sonder.length-1?'style="border-bottom:0"':""}>
|
||
<dt style="color:var(--fg)">${esc(x)}</dt><dd></dd></div>`).join("")}
|
||
</dl></div>`).join("")}
|
||
<button class="aktion">Daten bearbeiten</button>`;
|
||
}
|
||
|
||
/* Wird ein Service eingetragen, rückt der zugehörige Termin um ein Intervall
|
||
weiter — der Zähler beginnt damit an derselben Stelle neu, an der die Arbeit
|
||
tatsächlich gemacht wurde. */
|
||
/* Fälligkeiten aus dem letzten Eintrag der jeweiligen Art plus Intervall.
|
||
Kilometer und Zeit gelten parallel — fällig ist, was zuerst eintritt. */
|
||
function monatePlus(datum, monate){
|
||
const d = dat(datum); d.setMonth(d.getMonth()+monate); return d;
|
||
}
|
||
|
||
function letzterEintrag(stichwort){
|
||
return CAR.service.buch.find(e => e.art.toLowerCase().includes(stichwort)) || null;
|
||
}
|
||
|
||
function termine(){
|
||
const oel = CAR.oel;
|
||
/* Eigenes Intervall darf die Herstellervorgabe nicht überschreiten */
|
||
const oelKm = oel.modus==="hersteller" ? oel.herstellerKm : Math.min(oel.km, oel.herstellerKm);
|
||
const oelM = oel.modus==="hersteller" ? oel.herstellerMonate : Math.min(oel.monate, oel.herstellerMonate);
|
||
|
||
const bauen = (art, basis, kmIntervall, monate, ersatzDatum) => {
|
||
const kmZiel = basis && kmIntervall ? basis.km + kmIntervall : null;
|
||
const datZiel = basis ? monatePlus(basis.datum, monate)
|
||
: (ersatzDatum ? monatePlus(ersatzDatum, monate) : null);
|
||
const kmDatum = kmZiel!==null ? prognose(kmZiel).datum : null;
|
||
/* Fällig ist, was zuerst eintritt */
|
||
const zuerst = (kmDatum && datZiel) ? (kmDatum < datZiel ? "km" : "zeit")
|
||
: (kmDatum ? "km" : "zeit");
|
||
return {art, km:kmZiel, datum:datZiel, kmDatum, zuerst, basis,
|
||
ziel: zuerst==="km" ? kmDatum : datZiel,
|
||
vereinbart: CAR.service.vereinbart[art] || null};
|
||
};
|
||
|
||
return [
|
||
bauen("Ölwechsel", letzterEintrag("öl"), oelKm, oelM),
|
||
bauen("Inspektion", letzterEintrag("inspektion"), 30000, 24),
|
||
bauen("Hauptuntersuchung", letzterEintrag("hauptuntersuchung"), null, 24, "01.08.2023")
|
||
];
|
||
}
|
||
|
||
/* ---------- Werkstatt ---------- */
|
||
function vWerkstatt(){
|
||
const a=CAR.service.autohaus;
|
||
return `
|
||
<div class="tile"><span class="label">Angaben zum Autohaus</span>
|
||
<div class="feld"><label>Name</label><input value="${esc(a.name)}" data-ah="name"></div>
|
||
<div class="feld"><label>Adresse</label><input value="${esc(a.adresse)}" data-ah="adresse"></div>
|
||
<div class="feld"><label>Telefon</label><input type="tel" value="${esc(a.tel)}" data-ah="tel"></div>
|
||
<div class="feld"><label>E-Mail</label>
|
||
<input type="email" value="${esc(a.mail||"")}" data-ah="mail" placeholder="noch offen"></div>
|
||
<div class="feld" style="border-bottom:0"><label>Koordinaten</label>
|
||
<input value="${a.pos?a.pos.join(", "):""}" data-ah="pos" placeholder="Breite, Länge"></div>
|
||
<span class="label" style="margin-top:14px">Die Koordinaten steuern die Kartenschaltfläche.
|
||
Ohne sie wird die Adresse gesucht</span>
|
||
</div>`;
|
||
}
|
||
|
||
/* ---------- Servicebuch-Eintrag ---------- */
|
||
function vSbuch(){
|
||
const i=parseInt(route.id,10), e=CAR.service.buch[i];
|
||
if(!e) return `<div class="tile">Eintrag nicht gefunden</div>`;
|
||
return `
|
||
<div class="tile"><span class="label">${esc(e.art)}</span>
|
||
<div class="fig" style="font-size:40px;margin-top:12px">${de(e.km)}<span class="unit">km</span></div>
|
||
<span class="label" style="margin-top:12px">${e.datum} · ${esc(e.werkstatt)}</span>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Eintrag</span>
|
||
<div class="feld"><label>Datum</label><input value="${esc(e.datum)}" data-sb="${i}|datum"></div>
|
||
<div class="feld"><label>Kilometerstand</label>
|
||
<span class="mitEinheit"><input type="number" value="${e.km}" data-sb="${i}|km"><span>km</span></span></div>
|
||
<div class="feld"><label>Art</label><input value="${esc(e.art)}" data-sb="${i}|art"></div>
|
||
<div class="feld"><label>Werkstatt</label><input value="${esc(e.werkstatt)}" data-sb="${i}|werkstatt"></div>
|
||
<div class="feld" style="border-bottom:0"><label>Kosten</label>
|
||
<span class="mitEinheit"><input type="number" step="0.01" value="${e.kosten ?? ""}"
|
||
data-sb="${i}|kosten" placeholder="noch offen"><span>€</span></span></div>
|
||
<span class="label" style="margin-top:14px">Kosten fließen in die Jahresübersicht ein</span>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Durchgeführte Arbeiten</span>
|
||
<textarea class="notiz" data-sb="${i}|arbeiten" rows="7"
|
||
placeholder="Was wurde gemacht, welche Teile wurden getauscht, was ist aufgefallen">${esc(e.arbeiten||"")}</textarea>
|
||
<span class="label" style="margin-top:12px">Beim Verkauf ist diese Liste mehr wert als die Rechnung —
|
||
sie zeigt, dass gepflegt wurde</span>
|
||
</div>`;
|
||
}
|
||
|
||
/* ---------- Kosten ---------- */
|
||
const KM_JAHR = {2026:6680, 2025:6900};
|
||
let kostenJahr = 2026;
|
||
|
||
function kosten(j){
|
||
const zahl = x => { const n=parseFloat(String(x).replace(",",".")); return isNaN(n)?null:n; };
|
||
const kraftstoff = sum(FILLS.filter(f=>f.jahr===j), f=>f.summe);
|
||
const service = sum(CAR.service.buch.filter(e=>e.datum.endsWith(String(j)) && e.kosten!=null), e=>e.kosten);
|
||
return {
|
||
kraftstoff, service,
|
||
versicherung: zahl(CAR.versicherung.beitrag),
|
||
steuer: zahl(CAR.steuer.betrag),
|
||
km: KM_JAHR[j] || null
|
||
};
|
||
}
|
||
|
||
function vKosten(){
|
||
const j=kostenJahr, k=kosten(j);
|
||
const posten=[
|
||
["Kraftstoff", k.kraftstoff, "aus den erfassten Tankvorgängen"],
|
||
["Service und Wartung", k.service, "aus dem Servicebuch"],
|
||
["Versicherung", k.versicherung, "Jahresbeitrag"],
|
||
["Kfz-Steuer", k.steuer, "Jahresbetrag"]
|
||
];
|
||
const bekannt = posten.filter(p=>p[1]!==null && p[1]!==undefined);
|
||
const summe = sum(bekannt, p=>p[1]);
|
||
const fehlt = posten.length - bekannt.length;
|
||
return `
|
||
<div class="tile"><span class="label">Gesamtkosten ${j}</span>
|
||
<div class="fig" style="font-size:48px;margin-top:12px">${eur(summe)}<span class="unit">€</span></div>
|
||
${k.km?`<span class="label" style="margin-top:14px">${de(k.km)} km · ${de(summe/k.km*100,2)} € je 100 km</span>`:""}
|
||
${fehlt?`<div style="margin-top:16px;border-left:2px solid var(--warn);padding-left:14px;
|
||
font-size:12.5px;color:var(--fg2);line-height:1.55">
|
||
${fehlt===1?"Ein Posten fehlt noch":fehlt+" Posten fehlen noch"} — die Summe ist bis dahin
|
||
unvollständig und nicht als Jahresbilanz zu lesen.</div>`:""}
|
||
<div class="seg" style="margin-top:18px">
|
||
${Object.keys(KM_JAHR).sort((a,b)=>b-a).map(y=>
|
||
`<button data-kjahr="${y}" class="${+y===j?"on":""}">${y}</button>`).join("")}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Aufteilung</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${posten.map(([bez,wert,quelle],i)=>`<div class="row" ${i===posten.length-1?'style="border-bottom:0"':""}>
|
||
<dt>${bez}<br><span style="color:var(--fg3);font-size:11px">${quelle}</span></dt>
|
||
<dd style="${wert===null?"color:var(--fg3)":""}">${wert===null?"noch offen":eur(wert)+" €"}
|
||
${wert!==null&&summe?`<small>${de(wert/summe*100,0)} %</small>`:""}</dd></div>`).join("")}
|
||
</dl>
|
||
<div class="bar" style="margin-top:20px">
|
||
${bekannt.map(([bez,wert],i)=>`<i style="flex:${wert};background:${
|
||
["var(--red)","var(--fg)","var(--fg2)","var(--fg3)"][i]}"></i>`).join("")}
|
||
</div>
|
||
<div class="legend">${bekannt.map(([bez],i)=>`<span><i style="background:${
|
||
["var(--red)","var(--fg)","var(--fg2)","var(--fg3)"][i]}"></i>${bez}</span>`).join("")}</div>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Je Kilometer</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${bekannt.map(([bez,wert],i)=>`<div class="row" ${i===bekannt.length-1?'style="border-bottom:0"':""}>
|
||
<dt>${bez}</dt><dd>${k.km?de(wert/k.km*100,2)+" € / 100 km":"—"}</dd></div>`).join("")}
|
||
</dl></div>`;
|
||
}
|
||
|
||
/* ---------- Versicherung und Steuer ---------- */
|
||
function feldZeile(bez, wert, id, typ){
|
||
return `<div class="feld"><label for="${id}">${bez}</label>
|
||
<input id="${id}" type="${typ||"text"}" value="${esc(wert||"")}" placeholder="noch offen"></div>`;
|
||
}
|
||
|
||
function vVers(){
|
||
const v=CAR.versicherung;
|
||
return `
|
||
<div class="tile"><span class="label">Jahresbeitrag ab ${dedat(new Date(v.gueltigAb))}</span>
|
||
<div class="fig" style="font-size:46px;margin-top:12px">${eur(v.beitrag)}<span class="unit">€</span></div>
|
||
<span class="label" style="margin-top:14px">${v.zahlweise} · enthält ${eur(v.steueranteil)} € Versicherungsteuer (${v.steuersatz})</span>
|
||
<dl class="rows" style="margin-top:16px">
|
||
${v.teile.map((t,i)=>`<div class="row" ${i===v.teile.length-1?'style="border-bottom:0"':""}>
|
||
<dt>${esc(t.bez)}<br><span style="color:var(--fg3);font-size:11px">${t.sf} · Beitragssatz ${t.satz}</span></dt>
|
||
<dd>${eur(t.betrag)} €<small>${de(t.betrag/v.beitrag*100,0)} %</small></dd></div>`).join("")}
|
||
</dl>
|
||
<div class="bar" style="margin-top:18px">
|
||
${v.teile.map((t,i)=>`<i style="flex:${t.betrag};background:${i?"var(--fg2)":"var(--red)"}"></i>`).join("")}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Beitrag anpassen</span>
|
||
<div class="feld" style="border-bottom:0"><label for="vBeitrag">Jahresbeitrag</label>
|
||
<span class="mitEinheit"><input id="vBeitrag" type="number" step="0.01" value="${v.beitrag}"
|
||
data-vbeitrag><span>€</span></span></div>
|
||
<span class="label" style="margin-top:14px">Bei einer Beitragsanpassung hier ändern —
|
||
die Jahreskosten rechnen sofort neu</span>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Vertrag</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
<div class="row"><dt>Gesellschaft</dt><dd>${esc(v.gesellschaft)}</dd></div>
|
||
<div class="row"><dt>Umfang</dt><dd>${esc(v.vertrag)}</dd></div>
|
||
<div class="row"><dt>Vertragsnummer</dt><dd>${esc(v.nummer)}</dd></div>
|
||
${v.selbst.map(([b,w])=>`<div class="row"><dt>Selbstbeteiligung ${b}</dt><dd>${w}</dd></div>`).join("")}
|
||
<div class="row" style="border-bottom:0"><dt>Schadenfreiheitsklasse</dt>
|
||
<dd>${v.teile.map(t=>t.sf).join(" / ")}<small>zuvor ${v.teile.map(t=>t.sfAlt).join(" / ")}</small></dd></div>
|
||
</dl></div>
|
||
|
||
<div class="tile"><span class="label">Schaden-Notruf · rund um die Uhr</span>
|
||
<a class="aktion" href="tel:${esc(v.service.replace(/\s/g,""))}"
|
||
style="display:block;text-decoration:none;margin-top:14px;text-align:center">
|
||
Inland · ${esc(v.service)}</a>
|
||
<a class="aktion" href="tel:${esc(v.notfall.replace(/\s/g,""))}"
|
||
style="display:block;text-decoration:none;text-align:center">
|
||
Ausland · ${esc(v.notfall)}</a>
|
||
<span class="label" style="margin-top:16px">Inland kostenfrei. Beide Nummern gehören zusätzlich in
|
||
die Kontakte des iPhones — im Pannenfall ist oft kein Netz für das Dashboard da</span>
|
||
</div>
|
||
|
||
<button class="tile tilebtn" data-go="schutz:x">
|
||
<span class="label">Schutzbrief Mobilität</span>
|
||
<svg class="go" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg>
|
||
<div style="font-size:14px;margin-top:12px">Panne, Unfall, Diebstahl, Fahrerausfall</div>
|
||
<span class="label" style="margin-top:10px">Nummern und Leistungen für den Ernstfall</span>
|
||
</button>
|
||
|
||
${v.leistungen.map(g=>`<div class="tile"><span class="label">${g.gruppe}</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${g.posten.map((x,i)=>`<div class="row" ${i===g.posten.length-1?'style="border-bottom:0"':""}>
|
||
<dt style="color:var(--fg)">${esc(x)}</dt><dd></dd></div>`).join("")}
|
||
</dl></div>`).join("")}
|
||
|
||
${vSteuer()}`;
|
||
}
|
||
|
||
/* Für den Ernstfall gebaut: oben die Nummer, dann in einem Blick, was der
|
||
Versicherer übernimmt und wo eigene Kosten entstehen können. Keine langen
|
||
Absätze — wer an der Leitplanke steht, liest keine Fließtexte. */
|
||
function vSchutz(){
|
||
const v=CAR.versicherung, sb=v.schutzbrief;
|
||
return `
|
||
<div class="tile">
|
||
<span class="label">Zuerst anrufen</span>
|
||
<a class="aktion" href="tel:${esc(v.service.replace(/\s/g,""))}"
|
||
style="display:block;text-decoration:none;margin-top:14px;text-align:center;
|
||
border-color:var(--red);color:var(--fg)">Inland · ${esc(v.service)}</a>
|
||
<a class="aktion" href="tel:${esc(v.notfall.replace(/\s/g,""))}"
|
||
style="display:block;text-decoration:none;text-align:center">Ausland · ${esc(v.notfall)}</a>
|
||
<div style="margin-top:16px;border-left:2px solid var(--warn);padding-left:14px;
|
||
font-size:13px;color:var(--fg2);line-height:1.6">
|
||
<b style="color:var(--fg);font-weight:400">Weisung einholen ist Pflicht.</b> Vor Inanspruchnahme
|
||
einer Leistung musst du dich melden, soweit die Umstände es zulassen. Selbst beauftragte
|
||
Abschleppdienste, Hotels oder Mietwagen können sonst unbezahlt bleiben.
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Die Entscheidung am Schadenort</span>
|
||
<div style="font-size:13px;color:var(--fg2);line-height:1.6;margin-top:10px">
|
||
Diese drei Leistungen schließen einander aus. Wer eine nimmt, verliert den Anspruch auf die
|
||
anderen beiden — das ist die einzige Entscheidung, die vor Ort wirklich Geld kostet.</div>
|
||
<dl class="rows" style="margin-top:14px">
|
||
${sb.entweder.map((x,i)=>`<div class="row" ${i===sb.entweder.length-1?'style="border-bottom:0"':""}>
|
||
<dt style="color:var(--fg)">${esc(x.bez)}</dt>
|
||
<dd>${esc(x.grenze)}${x.zusatz?`<small>${esc(x.zusatz)}</small>`:""}</dd></div>`).join("")}
|
||
</dl>
|
||
<span class="label" style="margin-top:16px">Mobilität wird binnen 60 Minuten organisiert</span>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Wann der Schutzbrief greift</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${sb.ausloeser.map((a,i)=>`<div class="row" ${i===sb.ausloeser.length-1?'style="border-bottom:0"':""}>
|
||
<dt style="color:var(--fg)">${esc(a)}</dt><dd></dd></div>`).join("")}
|
||
</dl>
|
||
<span class="label" style="margin-top:16px">Gilt in ${esc(sb.gilt)}</span>
|
||
<span class="label" style="margin-top:8px">Versichert: ${esc(sb.versichert)}</span>
|
||
</div>
|
||
|
||
${sb.gruppen.map(g=>`<div class="tile"><span class="label">${g.titel}</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${g.posten.map((pp,i)=>`<div class="row" ${i===g.posten.length-1?'style="border-bottom:0"':""}>
|
||
<dt style="color:var(--fg)">${esc(pp[0])}${pp[2]?`<br><span style="color:var(--fg3);font-size:11px">${esc(pp[2])}</span>`:""}</dt>
|
||
<dd>${esc(pp[1])}</dd></div>`).join("")}
|
||
</dl></div>`).join("")}
|
||
|
||
<div class="tile"><span class="label">Nicht versichert</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${sb.nicht.map((n,i)=>`<div class="row" ${i===sb.nicht.length-1?'style="border-bottom:0"':""}>
|
||
<dt style="color:var(--fg)">${esc(n[0])}<br>
|
||
<span style="color:var(--fg3);font-size:11px">${esc(n[1])}</span></dt><dd></dd></div>`).join("")}
|
||
</dl></div>
|
||
|
||
<div class="tile"><span class="label">Deine Pflichten</span>
|
||
<dl class="rows" style="margin-top:8px">
|
||
${sb.pflichten.map((x,i)=>`<div class="row" ${i===sb.pflichten.length-1?'style="border-bottom:0"':""}>
|
||
<dt style="color:var(--fg)">${esc(x)}</dt><dd></dd></div>`).join("")}
|
||
</dl>
|
||
<div style="margin-top:16px;font-size:12.5px;color:var(--fg2);line-height:1.6">${esc(sb.rang)}</div>
|
||
<span class="label" style="margin-top:14px">${esc(sb.stand)}</span>
|
||
</div>`;
|
||
}
|
||
|
||
function vSteuer(){
|
||
const t=CAR.steuer;
|
||
return `
|
||
<div class="tile" style="margin-top:26px"><span class="label">Kfz-Steuer</span>
|
||
<div class="feld"><label for="stBetrag">Betrag</label>
|
||
<span class="mitEinheit"><input id="stBetrag" type="number" step="1" value="${t.betrag}"
|
||
data-steuer><span>€</span></span></div>
|
||
<div class="feld"><label for="stZeit">Zeitraum</label>
|
||
<select id="stZeit"><option>jährlich</option><option>halbjährlich</option></select></div>
|
||
<div class="feld"><label for="stFaellig">Nächste Fälligkeit</label>
|
||
<input id="stFaellig" type="date" value="${t.faellig}"></div>
|
||
<div class="feld" style="border-bottom:0"><label for="stLast">Lastschrift erteilt</label>
|
||
<input id="stLast" type="checkbox" ${t.lastschrift?"checked":""}></div>
|
||
</div>
|
||
|
||
`;
|
||
}
|
||
|
||
/* ---------- Einstellungen ---------- */
|
||
let beschriftung = true;
|
||
let bodenAn = true;
|
||
|
||
function csvDatei(name, kopf, zeilen){
|
||
const txt = [kopf.join(";")].concat(zeilen.map(r=>r.join(";"))).join("\r\n");
|
||
const a=document.createElement("a");
|
||
a.href="data:text/csv;charset=utf-8,"+encodeURIComponent("\ufeff"+txt);
|
||
a.download=name; document.body.appendChild(a); a.click(); a.remove();
|
||
}
|
||
|
||
function vEinst(){
|
||
return `
|
||
<div class="tile"><span class="label">Darstellung</span>
|
||
<div class="seg">
|
||
<button data-mode="nacht" class="${document.documentElement.dataset.theme==="nacht"?"on":""}">Nacht</button>
|
||
<button data-mode="tag" class="${document.documentElement.dataset.theme==="tag"?"on":""}">Tag</button>
|
||
</div>
|
||
<div class="feld" style="margin-top:16px;border-bottom:0">
|
||
<label for="schrift">Beschriftung in der Menüleiste</label>
|
||
<input id="schrift" type="checkbox" data-schrift ${beschriftung?"checked":""}></div>
|
||
<span class="label" style="margin-top:14px">Aus zeigt nur die Symbole und gibt etwas Höhe frei</span>
|
||
<div class="feld" style="margin-top:16px;border-bottom:0">
|
||
<label for="boden">Fahrbahn unter dem Fahrzeug</label>
|
||
<input id="boden" type="checkbox" data-boden ${bodenAn?"checked":""}></div>
|
||
<span class="label" style="margin-top:14px">Angedeutete Fahrbahn mit Schatten, nur bei Außenansichten</span>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Bild der Übersicht</span>
|
||
<div class="feld" style="border-bottom:0"><label for="startbild">Ansicht</label>
|
||
<select id="startbild" data-startbild>${BILDER.map(b=>
|
||
`<option ${b.name===CONFIG.startbild?"selected":""}>${b.name}</option>`).join("")}</select></div>
|
||
<img class="carfix" style="margin-top:16px" src="${BILDER[startIndex()].src}" alt="">
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Kraftstoff-Rabatt</span>
|
||
<div class="feld"><label for="sdAktiv">Shell SmartDeal nutzen</label>
|
||
<input id="sdAktiv" type="checkbox" data-sd ${CAR.smartdeal.aktiv?"checked":""}></div>
|
||
<div class="feld" style="border-bottom:0"><label for="sdBis">Läuft ab am</label>
|
||
<input id="sdBis" type="date" value="${CAR.smartdeal.laeuftAb}" ${CAR.smartdeal.aktiv?"":"disabled"}></div>
|
||
${CAR.smartdeal.aktiv?`<span class="label" style="margin-top:14px">Nach diesem Datum wird der Rabatt
|
||
nicht mehr erwartet — bleibt er auf dem Beleg aus, ist das dann kein Fehler</span>`:
|
||
`<span class="label" style="margin-top:14px">Ersparnis und Bildmarke werden ausgeblendet</span>`}
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Fahrten zusammenfassen</span>
|
||
<div class="feld" style="border-bottom:0"><label for="pause">Pause bis</label>
|
||
<span class="mitEinheit"><input id="pause" type="number" step="5" min="0"
|
||
value="${CONFIG.pauseMin}" data-pause><span>Minuten</span></span></div>
|
||
<span class="label" style="margin-top:14px">Steigst du kürzer als diese Zeit aus — etwa zum Tanken —,
|
||
bleibt es eine zusammenhängende Fahrt statt zweier</span>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Ölwechsel-Intervall</span>
|
||
<div class="seg">
|
||
<button data-oel="hersteller" class="${CAR.oel.modus==="hersteller"?"on":""}">Herstellervorgabe</button>
|
||
<button data-oel="eigen" class="${CAR.oel.modus==="eigen"?"on":""}">Eigenes</button>
|
||
</div>
|
||
${CAR.oel.modus==="hersteller"
|
||
? `<dl class="rows" style="margin-top:16px">
|
||
<div class="row"><dt>Laufleistung</dt><dd>${de(CAR.oel.herstellerKm)} km</dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Zeit</dt><dd>${CAR.oel.herstellerMonate} Monate</dd></div>
|
||
</dl>
|
||
<span class="label" style="margin-top:14px">Aus dem Fahrzeug gelesen</span>`
|
||
: `<div class="feld" style="margin-top:6px"><label for="oelKm">Nach Laufleistung</label>
|
||
<select id="oelKm" data-oelkm>${[5000,10000,15000,20000].map(k=>
|
||
`<option value="${k}" ${k===CAR.oel.km?"selected":""}>${de(k)} km</option>`).join("")}</select></div>
|
||
<div class="feld" style="border-bottom:0"><label for="oelM">Nach Zeit</label>
|
||
<select id="oelM" data-oelm>${[12,24].map(m=>
|
||
`<option value="${m}" ${m===CAR.oel.monate?"selected":""}>${m===12?"1 Jahr":"2 Jahre"}</option>`).join("")}</select></div>
|
||
<span class="label" style="margin-top:14px">Fällig wird, was zuerst eintritt</span>`}
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Fahrzeugprofil</span>
|
||
<span class="label" style="margin-top:10px;color:var(--fg2);letter-spacing:0;
|
||
text-transform:none;font-size:12.5px;line-height:1.6">
|
||
Alles Fahrzeugspezifische liegt in einer einzigen Datei: Stammdaten, technische Daten,
|
||
Ausstattung, Reifen, Versicherung, Steuer und Werkstatt. Für ein anderes Fahrzeug wird nur
|
||
diese Datei getauscht — die App selbst bleibt unverändert.</span>
|
||
<button class="aktion" data-profil="export">Profil sichern</button>
|
||
<label class="aktion" style="display:block;text-align:center;cursor:pointer">
|
||
Profil laden<input type="file" accept="application/json" data-profil="import" hidden></label>
|
||
<dl class="rows" style="margin-top:16px">
|
||
<div class="row"><dt>Datei</dt><dd>fahrzeug.json</dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Bearbeitbar mit</dt>
|
||
<dd>jedem Texteditor<small>auch im Datei-Editor von Home Assistant</small></dd></div>
|
||
</dl>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Daten ausgeben</span>
|
||
<span class="label" style="margin-top:10px;color:var(--fg2);letter-spacing:0;text-transform:none;font-size:12.5px">
|
||
Semikolon als Trennzeichen und deutsches Zahlenformat, damit die Dateien ohne Umweg in
|
||
Tabellenprogrammen aufgehen.</span>
|
||
<button class="aktion" data-csv="fahrten">Fahrten als CSV</button>
|
||
<button class="aktion" data-csv="tanken">Tankvorgänge als CSV</button>
|
||
<button class="aktion" data-csv="service">Servicebuch als CSV</button>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Sicherung</span>
|
||
<dl class="rows">
|
||
<div class="row"><dt>Letzte Sicherung</dt><dd>03.08.2026<small>04:00 Uhr · 2,4 MB</small></dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Umfang</dt>
|
||
<dd>Fahrten, Tankvorgänge<small>Servicebuch, Stammdaten, Belege</small></dd></div>
|
||
</dl>
|
||
<div class="feld" style="margin-top:6px"><label for="bkAuto">Automatisch sichern</label>
|
||
<input id="bkAuto" type="checkbox" checked></div>
|
||
<div class="feld" style="border-bottom:0"><label for="bkInt">Rhythmus</label>
|
||
<select id="bkInt">
|
||
<option>täglich</option><option selected>wöchentlich</option><option>monatlich</option>
|
||
</select></div>
|
||
<button class="aktion">Jetzt sichern</button>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Version</span>
|
||
<dl class="rows">
|
||
<div class="row"><dt>Dashboard</dt><dd>${CONFIG.version}</dd></div>
|
||
<div class="row"><dt>Fahrzeugdaten</dt><dd>EU Data Act<small>Abruf alle 15 Minuten</small></dd></div>
|
||
<div class="row"><dt>Letzter Abruf</dt><dd>${CAR.standAlter}</dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Position</dt><dd>iPhone<small>Companion App</small></dd></div>
|
||
</dl></div>`;
|
||
}
|
||
|
||
/* ---------- Reifen ---------- */
|
||
function vReifen(){
|
||
const r=CAR.reifen;
|
||
/* Jedes Feld schreibt beim Verlassen direkt in den Datensatz zurück.
|
||
Die Laufleistung ist ebenfalls änderbar — beim Wechsel auf einen bereits
|
||
gefahrenen Satz muss der Startwert von Hand gesetzt werden können. */
|
||
const feld = (k, schluessel, bez, typ) => {
|
||
const t = r[k];
|
||
return `<div class="feld"><label>${bez}</label>
|
||
<input type="${typ||"text"}" value="${esc(t[schluessel] ?? "")}"
|
||
data-rf="${k}|${schluessel}" placeholder="noch offen"></div>`;
|
||
};
|
||
|
||
const satz = k => {
|
||
const t=r[k], aktiv = r.aktiv.toLowerCase()===k;
|
||
return `<div class="tile">
|
||
${t.bild ? `<img class="radbild" src="${esc(t.bild)}" alt="${esc(t.marke)} ${esc(t.modell)}">`
|
||
: `<div class="radph"></div>`}
|
||
<div class="radkopf">
|
||
<span class="label">${k==="sommer"?"Sommer":"Winter"}${aktiv?" · montiert":""}</span>
|
||
<div class="fig" style="font-size:32px;margin-top:14px">${de(t.km)}<span class="unit">km</span></div>
|
||
</div>
|
||
<div style="margin-top:22px">
|
||
${feld(k,"marke","Hersteller")}
|
||
${feld(k,"modell","Modell")}
|
||
${feld(k,"mass","Größe")}
|
||
${feld(k,"dot","DOT")}
|
||
${feld(k,"druck","Solldruck")}
|
||
${feld(k,"km","Laufleistung in km","number")}
|
||
${feld(k,"kauf","Gekauft")}
|
||
${feld(k,"kommentar","Kommentar")}
|
||
</div>
|
||
<span class="label" style="margin-top:16px">Änderungen wirken sofort</span>
|
||
</div>`;
|
||
};
|
||
|
||
return `
|
||
<div class="tile"><span class="label">Montiert</span>
|
||
<div class="seg">
|
||
<button data-satz="Sommer" class="${r.aktiv==="Sommer"?"on":""}">Sommer</button>
|
||
<button data-satz="Winter" class="${r.aktiv==="Winter"?"on":""}">Winter</button>
|
||
</div>
|
||
<span class="label" style="margin-top:14px">Das Umschalten leitet die gefahrenen Kilometer auf den gewählten Satz um</span>
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Beim Wechsel</span>
|
||
<button class="zahnrad" data-nmauf aria-label="Anzugsmoment ändern">
|
||
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/>
|
||
<path d="M19.1 14.6a1.5 1.5 0 0 0 .3 1.7l.1.1a1.8 1.8 0 1 1-2.6 2.6l-.1-.1a1.5 1.5 0 0 0-1.7-.3 1.5 1.5 0 0 0-.9 1.4v.2a1.8 1.8 0 1 1-3.6 0V20a1.5 1.5 0 0 0-1-1.4 1.5 1.5 0 0 0-1.7.3l-.1.1a1.8 1.8 0 1 1-2.6-2.6l.1-.1a1.5 1.5 0 0 0 .3-1.7 1.5 1.5 0 0 0-1.4-.9H4a1.8 1.8 0 1 1 0-3.6h.2a1.5 1.5 0 0 0 1.4-1 1.5 1.5 0 0 0-.3-1.7l-.1-.1a1.8 1.8 0 1 1 2.6-2.6l.1.1a1.5 1.5 0 0 0 1.7.3H9.8a1.5 1.5 0 0 0 .9-1.4V4a1.8 1.8 0 1 1 3.6 0v.2a1.5 1.5 0 0 0 .9 1.4 1.5 1.5 0 0 0 1.7-.3l.1-.1a1.8 1.8 0 1 1 2.6 2.6l-.1.1a1.5 1.5 0 0 0-.3 1.7v.1a1.5 1.5 0 0 0 1.4.9h.2a1.8 1.8 0 1 1 0 3.6H20a1.5 1.5 0 0 0-1.4.9z"/></svg>
|
||
</button>
|
||
<div class="fig" style="font-size:34px;margin-top:12px">${de(r.anzugsmoment)}<span class="unit">Nm</span></div>
|
||
<span class="label" style="margin-top:10px">Anzugsmoment der Radschrauben</span>
|
||
${nmOffen?`
|
||
<div style="margin-top:18px;border-top:1px solid var(--line);padding-top:16px">
|
||
<div class="feld" style="border-bottom:0"><label for="nm">Neuer Wert</label>
|
||
<span class="mitEinheit"><input id="nm" type="number" step="5" min="0"
|
||
value="${r.anzugsmoment}"><span>Nm</span></span></div>
|
||
<button class="aktion" data-nmspeichern>Speichern</button>
|
||
<button class="aktion" data-nmauf>Abbrechen</button>
|
||
</div>`:""}
|
||
</div>
|
||
|
||
<div class="tile"><span class="label">Wechseltermin</span>
|
||
<div class="feld"><label for="rfDat">Geplant am</label>
|
||
<input id="rfDat" type="date" value="${r.wechsel.datum}"></div>
|
||
<div class="feld" style="border-bottom:0"><label for="rfOk">Termin vereinbart</label>
|
||
<input id="rfOk" type="checkbox" ${r.wechsel.vereinbart?"checked":""}></div>
|
||
<button class="aktion" data-ics="reifen">In den Kalender übernehmen</button>
|
||
</div>
|
||
|
||
${satz("sommer")}
|
||
${satz("winter")}`;
|
||
}
|
||
|
||
function vTrips(){
|
||
const jahre=[...new Set(TRIPS.map(t=>t.jahr))].sort((a,b)=>b-a);
|
||
let h=`<div class="tile">`;
|
||
jahre.forEach((j,ji)=>{
|
||
const tj=TRIPS.filter(t=>t.jahr===j);
|
||
h+=`<button class="acc-h" aria-expanded="${ji===0}" data-acc="y${j}"><span class="mark"></span>
|
||
<span class="k">${j}</span><span class="v">${de(sum(tj,t=>t.dist))} km<br>${tj.length} Fahrten</span></button>
|
||
<div class="acc-b ${ji===0?"on":""}" id="y${j}">`;
|
||
[...new Set(tj.map(t=>t.monat))].forEach((m,mi)=>{
|
||
const tm=tj.filter(t=>t.monat===m);
|
||
h+=`<div class="lvl2"><button class="acc-h" aria-expanded="${mi===0}" data-acc="m${j}${m}">
|
||
<span class="mark"></span><span class="k">${m}</span>
|
||
<span class="v">${de(sum(tm,t=>t.dist))} km</span></button>
|
||
<div class="acc-b ${mi===0?"on":""}" id="m${j}${m}">`;
|
||
tm.forEach(t=>{ h+=`<button class="leaf" data-go="trip:${t.id}">
|
||
<span class="k">${t.tag} ${esc(t.von.split(",")[0])} → ${esc(t.nach.split(",")[0])}
|
||
<small>${t.art} · ${t.dauer}${t.nacht?" · Nacht":""}</small></span>
|
||
<span class="v">${de(t.dist)} km<small>${eur(t.kosten)} €</small></span>
|
||
<svg class="chev" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg></button>`; });
|
||
h+=`</div></div>`;
|
||
});
|
||
h+=`</div>`;
|
||
});
|
||
return h + `</div>
|
||
${fahrtOffen?`<div class="tile"><span class="label">Neue Fahrt</span>
|
||
<div class="feld"><label>Datum</label><input type="date" value="2026-08-03"></div>
|
||
<div class="feld"><label>Startzeit</label><input type="time" value="08:00"></div>
|
||
<div class="feld"><label>Dauer in Minuten</label><input type="number" placeholder="0"></div>
|
||
<div class="feld"><label>Startort</label><input placeholder="Ort oder Adresse"></div>
|
||
<div class="feld"><label>Zielort</label><input placeholder="Ort oder Adresse"></div>
|
||
<div class="feld"><label>Kilometerstand Start</label><input type="number" value="${CAR.odo}"></div>
|
||
<div class="feld"><label>Kilometerstand Ende</label><input type="number" placeholder="${CAR.odo}"></div>
|
||
<div class="feld" style="border-bottom:0"><label>Art der Fahrt</label>
|
||
<select><option>Privat</option><option>Arbeitsweg</option></select></div>
|
||
<button class="aktion">Speichern</button></div>`:""}
|
||
<button class="aktion" data-fahrt>${fahrtOffen?"Abbrechen":"Fahrt erfassen"}</button>`;
|
||
}
|
||
|
||
function vTrip(id){
|
||
const t=TRIPS.find(x=>x.id===id);
|
||
return `
|
||
${mapBox()}
|
||
<div class="tile flat" style="margin:18px 0 14px">
|
||
<span class="label">Distanz</span>
|
||
<div class="fig" style="font-size:52px;margin-top:10px">${de(t.dist)}<span class="unit">km</span></div>
|
||
<div style="margin-top:15px">
|
||
<button class="pill ${t.art==="Arbeitsweg"?"work":""}" data-art="${t.id}"
|
||
style="cursor:pointer;font-family:inherit">${t.art}</button>
|
||
${t.nacht?'<span class="pill" style="margin-left:8px">Nachtfahrt</span>':""}</div>
|
||
<span class="label" style="margin-top:12px">Vorbelegung privat · tippen zum Umschalten</span>
|
||
</div>
|
||
<div class="tile"><dl class="rows">
|
||
<div class="row"><dt>Startort</dt><dd>${esc(t.von)}<small>${t.tag} ${t.zeit} Uhr</small></dd></div>
|
||
<div class="row"><dt>Zielort</dt><dd>${esc(t.nach)}</dd></div>
|
||
<div class="row"><dt>Startkilometer</dt><dd>${de(t.kmA)} km</dd></div>
|
||
<div class="row"><dt>Endkilometer</dt><dd>${de(t.kmE)} km</dd></div>
|
||
<div class="row"><dt>Dauer</dt><dd>${t.dauer}</dd></div>
|
||
<div class="row"><dt>Ø Geschwindigkeit</dt><dd>${de(t.schnitt)} km/h</dd></div>
|
||
<div class="row"><dt>Kraftstoffkosten</dt><dd>${eur(t.kosten)} €<small>${de(t.kosten/t.dist*100,2)} € je 100 km</small></dd></div>
|
||
</dl></div>`;
|
||
}
|
||
|
||
function quad(t,v){return `<span class="label" style="margin-top:20px">${t}</span>
|
||
<div class="quad">${v.map(x=>`<div><div class="n">${x[0]}</div><div class="l">${x[1]}</div></div>`).join("")}</div>`;}
|
||
function statTile(id,label,fig,unit,extra,body){
|
||
return `<div class="tile"><button class="tile-h" aria-expanded="false" data-acc="${id}">
|
||
<span class="label">${label}</span>
|
||
<div style="display:flex;align-items:flex-end;justify-content:space-between;gap:14px;margin-top:12px">
|
||
<div class="fig" style="font-size:34px">${fig}<span class="unit">${unit}</span></div>
|
||
<span class="label" style="padding-bottom:5px">${extra}</span></div>
|
||
</button><div class="tile-b" id="${id}">${body}</div></div>`;
|
||
}
|
||
/* Beispielzahlen, abgeleitet aus der tatsächlichen Fahrleistung von
|
||
18,3 km je Tag. Formatierung durchgehend über de(), damit überall
|
||
derselbe Tausenderpunkt steht. */
|
||
const ST = {
|
||
kmJahr:6680, kmMonat:557, kmWoche:128, kmTag:18,
|
||
hJahr:121, hMonat:10, hWoche:2.3, hTag:0.3,
|
||
lJahr:534, lMonat:45, lWoche:10, lTag:0,
|
||
eJahr:1127, eMonat:94, eWoche:21, eTag:0,
|
||
tagKm:5210, nachtKm:1470, arbeitKm:4275, privatKm:2405,
|
||
fahrtenArbeit:96, fahrtenPrivat:44
|
||
};
|
||
|
||
function vStat(){
|
||
return `
|
||
${statTile("s1","Distanz und Fahrzeit 2026",de(ST.kmJahr),"km",de(ST.hJahr)+" h",
|
||
quad("Gefahrene Distanz",[[de(ST.kmJahr),"Jahr"],[de(ST.kmMonat),"Monat"],
|
||
[de(ST.kmWoche),"Woche"],[de(ST.kmTag),"Tag"]])+
|
||
quad("Fahrzeit",[[de(ST.hJahr),"Jahr h"],[de(ST.hMonat),"Monat h"],
|
||
[de(ST.hWoche,1),"Woche h"],[de(ST.hTag,1),"Tag h"]]))}
|
||
${statTile("s2","Getankte Menge und Kosten 2026",de(ST.lJahr),"l",de(ST.eJahr)+" €",
|
||
quad("Getankte Liter",[[de(ST.lJahr),"Jahr"],[de(ST.lMonat),"Monat"],
|
||
[de(ST.lWoche),"Woche"],[de(ST.lTag),"Tag"]])+
|
||
quad("Kraftstoffkosten",[[de(ST.eJahr),"Jahr €"],[de(ST.eMonat),"Monat €"],
|
||
[de(ST.eWoche),"Woche €"],[eur(0),"Tag €"]]))}
|
||
${statTile("s3","Durchschnittsverbrauch","8,0","l/100 km","2026",
|
||
quad("Je Zeitraum",[["8,0","Jahr"],["7,6","Monat"],["7,4","Woche"],["–","Tag"]]))}
|
||
${statTile("s4","Tag und Nacht","78","% bei Tag",de(ST.tagKm)+" km",
|
||
`<div class="bar"><i style="flex:78;background:var(--fg)"></i><i style="flex:22;background:var(--fg3)"></i></div>
|
||
<div class="legend"><span><i style="background:var(--fg)"></i>Tag · ${de(ST.tagKm)} km</span>
|
||
<span><i style="background:var(--fg3)"></i>Nacht · ${de(ST.nachtKm)} km</span></div>
|
||
<span class="label" style="margin-top:16px">Nacht = ${CONFIG.nachtVon} bis ${CONFIG.nachtBis} Uhr</span>`)}
|
||
${statTile("s5","Art der Fahrten","64","% Arbeitsweg",de(ST.arbeitKm)+" km",
|
||
`<div class="bar"><i style="flex:64;background:var(--red)"></i><i style="flex:36;background:var(--fg3)"></i></div>
|
||
<div class="legend"><span><i style="background:var(--red)"></i>Arbeitsweg · ${de(ST.arbeitKm)} km</span>
|
||
<span><i style="background:var(--fg3)"></i>Privat · ${de(ST.privatKm)} km</span></div>
|
||
<dl class="rows" style="margin-top:18px">
|
||
<div class="row"><dt>Fahrten Arbeitsweg</dt><dd>${de(ST.fahrtenArbeit)}</dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Fahrten privat</dt><dd>${de(ST.fahrtenPrivat)}</dd></div></dl>`)}`;
|
||
}
|
||
|
||
let neuOffen = false;
|
||
let nmOffen = false;
|
||
let fahrtOffen = false;
|
||
|
||
function vFuel(){
|
||
const jahre=[...new Set(FILLS.map(f=>f.jahr))].sort((a,b)=>b-a);
|
||
let h=`<div class="tile">`;
|
||
jahre.forEach((j,ji)=>{
|
||
const fj=FILLS.filter(f=>f.jahr===j);
|
||
h+=`<button class="acc-h" aria-expanded="${ji===0}" data-acc="fy${j}"><span class="mark"></span>
|
||
<span class="k">${j}</span><span class="v">Ø ${de(schnittpreis(fj),3)} €/l<br>${de(sum(fj,f=>f.seit))} km · ${eur(sum(fj,f=>f.summe))} €<br>
|
||
<span class="marke" style="justify-content:flex-end">${markenlogo()} − ${eur(sum(fj,f=>f.rabatt))} €</span></span></button>
|
||
<div class="acc-b ${ji===0?"on":""}" id="fy${j}">`;
|
||
[...new Set(fj.map(f=>f.monat))].forEach((m,mi)=>{
|
||
const fm=fj.filter(f=>f.monat===m);
|
||
h+=`<div class="lvl2"><button class="acc-h" aria-expanded="${mi===0}" data-acc="fm${j}${m}">
|
||
<span class="mark"></span><span class="k">${m}</span>
|
||
<span class="v">Ø ${de(schnittpreis(fm),3)} €/l<br>${de(sum(fm,f=>f.seit))} km · ${eur(sum(fm,f=>f.summe))} €</span></button>
|
||
<div class="acc-b ${mi===0?"on":""}" id="fm${j}${m}">`;
|
||
fm.forEach(f=>{ h+=`<button class="leaf" data-go="fill:${f.id}">
|
||
<span class="k">${f.datum}<small>${esc(f.station)}</small></span>
|
||
<span class="v">${de(f.liter,2)} l<small>${de(f.summe/f.liter,3)} €/l · ${eur(f.summe)} €</small></span>
|
||
<svg class="chev" viewBox="0 0 6 10"><polyline points="1,1 5,5 1,9"/></svg></button>`; });
|
||
h+=`</div></div>`;
|
||
});
|
||
h+=`</div>`;
|
||
});
|
||
return h + `</div>
|
||
${neuOffen?`<div class="tile"><span class="label">Neuer Tankvorgang</span>
|
||
<div class="feld"><label>Datum</label><input type="date" value="2026-08-03"></div>
|
||
<div class="feld"><label>Uhrzeit</label><input type="time" value="16:05"></div>
|
||
<div class="feld"><label>Kraftstoff</label>
|
||
<select>${["V-Power Racing","Super Plus","Super (95)"].map(k=>`<option>${k}</option>`).join("")}</select></div>
|
||
<div class="feld"><label>Getankte Liter</label><input type="number" step="0.01" placeholder="0,00"></div>
|
||
<div class="feld"><label>Kosten in Euro</label><input type="number" step="0.01" placeholder="0,00"></div>
|
||
<div class="feld"><label>Kilometerstand</label><input type="number" value="${CAR.odo}"></div>
|
||
<div class="feld" style="border-bottom:0"><label>Tankstelle</label><input placeholder="Name und Ort"></div>
|
||
<button class="aktion" data-beleg>Beleg hochladen und auswerten</button>
|
||
<button class="aktion">Speichern</button></div>`:""}
|
||
<button class="aktion" data-neu>${neuOffen?"Abbrechen":"Tankvorgang erfassen"}</button>`;
|
||
}
|
||
|
||
/* Volltankung wird nicht abgefragt, sondern aus dem Füllstand nach dem Tanken
|
||
abgeleitet. Ab 97 Prozent gilt die Füllung als voll — darunter liegt die
|
||
Auflösung der Fahrzeugmeldung. */
|
||
function istVoll(f){ return f.pctNach >= 97; }
|
||
|
||
function vFill(id){
|
||
const f=FILLS.find(x=>x.id===id);
|
||
const voll=istVoll(f);
|
||
const preis=f.summe/f.liter, listenpreis=(f.summe+f.rabatt)/f.liter;
|
||
return `
|
||
${mapBox()}
|
||
<div class="tile flat" style="margin:18px 0 14px">
|
||
<span class="label">Getankt</span>
|
||
<div class="fig" style="font-size:52px;margin-top:10px">${de(f.liter,2)}<span class="unit">l</span></div>
|
||
</div>
|
||
<div class="tile"><dl class="rows">
|
||
<div class="row"><dt>Zeitpunkt</dt><dd>${f.datum}<small>${f.zeit} Uhr</small></dd></div>
|
||
<div class="row"><dt>Kilometerstand</dt><dd>${de(f.odo)} km</dd></div>
|
||
<div class="row"><dt>Gefahrene Distanz</dt><dd>${de(f.seit)} km<small>seit der letzten Füllung</small></dd></div>
|
||
<div class="row"><dt>Getankte Liter</dt><dd>${de(f.liter,2)} l</dd></div>
|
||
<div class="row"><dt>Kosten</dt><dd>${eur(f.summe)} €</dd></div>
|
||
<div class="row"><dt>Preis je Liter</dt><dd>${de(preis,3)} €</dd></div>
|
||
<div class="row"><dt><span class="marke">${markenlogo()} SmartDeal</span></dt><dd>− ${eur(f.rabatt)} €<small>Listenpreis ${de(listenpreis,3)} €/l</small></dd></div>
|
||
<div class="row"><dt>Volltankung</dt>
|
||
<dd>${voll?"ja":"nein"}<small>Füllstand danach ${f.pctNach} %, davor ${f.pctVor} %</small></dd></div>
|
||
<div class="row"><dt>Verbrauch</dt>
|
||
<dd>${voll?de(f.liter/f.seit*100,1)+" l/100 km":"—"}<small>${voll?"zwischen zwei Volltankungen":"nur bei Volltankung belastbar"}</small></dd></div>
|
||
<div class="row"><dt>Tankstelle</dt><dd>${esc(f.station)}<small>${esc(f.adresse)}</small></dd></div>
|
||
<div class="row" style="border-bottom:0"><dt>Beleg</dt>
|
||
<dd>${f.beleg?"hinterlegt":"fehlt"}<small>${f.beleg?"Werte aus dem Beleg übernommen":"Kosten bisher geschätzt"}</small></dd></div>
|
||
</dl>
|
||
<button class="aktion" data-beleg>${f.beleg?"Beleg ersetzen":"Beleg hochladen und auswerten"}</button>
|
||
</div>`;
|
||
}
|
||
|
||
/* ---------- Steuerung ---------- */
|
||
/* Bleibt die Ansicht dieselbe und wird nur neu aufgebaut — etwa weil ein
|
||
Schalter umgelegt wurde —, behält die Seite ihre Scrollposition. Nur beim
|
||
echten Wechsel der Ansicht wird nach oben gesprungen. */
|
||
let letzteAnsicht = null;
|
||
|
||
function render(){
|
||
const v=$("#view"), b=$("#back");
|
||
const merkeScroll = v.scrollTop;
|
||
const gleicheAnsicht = letzteAnsicht === route.name + "|" + (route.id || "");
|
||
let head;
|
||
if(route.name==="home"){ head=["Fahrzeug","Übersicht"]; v.innerHTML=vHome(); }
|
||
else if(route.name==="trip"){ head=["Fahrt","Einzelfahrt"]; v.innerHTML=vTrip(route.id); }
|
||
else if(route.name==="fill"){ head=["Tankvorgang","Einzelbeleg"]; v.innerHTML=vFill(route.id); }
|
||
else if(route.name==="service"){ head=["Wartung","Service"]; v.innerHTML=vService(); }
|
||
else if(route.name==="reifen"){ head=["Fahrzeug","Reifen"]; v.innerHTML=vReifen(); }
|
||
else if(route.name==="einst"){ head=["App","Einstellungen"]; v.innerHTML=vEinst(); }
|
||
else if(route.name==="ident"){ head=["Fahrzeug","Identität und Technik"]; v.innerHTML=vIdent(); }
|
||
else if(route.name==="vers"){ head=["Fahrzeug","Versicherung und Steuer"]; v.innerHTML=vVers(); }
|
||
else if(route.name==="kosten"){ head=["Fahrzeug","Kosten"]; v.innerHTML=vKosten(); }
|
||
else if(route.name==="schutz"){ head=["Im Ernstfall","Schutzbrief"]; v.innerHTML=vSchutz(); }
|
||
else if(route.name==="werkstatt"){ head=["Service","Autohaus"]; v.innerHTML=vWerkstatt(); }
|
||
else if(route.name==="sbuch"){ head=["Servicebuch","Eintrag"]; v.innerHTML=vSbuch(); }
|
||
else { const t=TABS.find(x=>x.id===route.name); head=[t.eyebrow,t.title];
|
||
v.innerHTML={audi:vAudi,trips:vTrips,stat:vStat,fuel:vFuel}[route.name](); }
|
||
$("#eyebrow").textContent=head[0]; $("#title").textContent=head[1];
|
||
const sy=$("#sync");
|
||
sy.style.display = route.name==="home" ? "flex" : "none";
|
||
sy.querySelector("span").textContent = "Aktualisiert " + CAR.standAlter;
|
||
b.classList.toggle("on", !!ZURUECK[route.name]);
|
||
v.scrollTop = gleicheAnsicht ? merkeScroll : 0;
|
||
letzteAnsicht = route.name + "|" + (route.id || "");
|
||
if(MAP){ MAP.remove(); MAP=null; TILE=null; }
|
||
if(route.name==="trip"||route.name==="fill") initMap();
|
||
document.querySelectorAll(".tab").forEach(el=>el.classList.toggle("on",el.dataset.tab===route.name));
|
||
}
|
||
const go=(name,id)=>{route={name,id};render();};
|
||
|
||
$("#tabbar").innerHTML = TABS.map(t=>
|
||
`<button class="tab" data-tab="${t.id}">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">${ICONS[t.id]}</svg><span>${t.label}</span>
|
||
</button>`).join("");
|
||
$("#tabbar").addEventListener("click",e=>{const b=e.target.closest(".tab"); if(b) go(b.dataset.tab);});
|
||
$("#back").addEventListener("click",()=>go(ZURUECK[route.name]||"home"));
|
||
const ICON = {
|
||
sonne:'<circle cx="10" cy="10" r="4"/><path d="M10 1v2M10 17v2M1 10h2M17 10h2M3.9 3.9l1.4 1.4M14.7 14.7l1.4 1.4M16.1 3.9l-1.4 1.4M5.3 14.7l-1.4 1.4"/>',
|
||
mond :'<path d="M16.5 12.4A7 7 0 1 1 7.6 3.5a5.6 5.6 0 0 0 8.9 8.9z"/>'
|
||
};
|
||
function themeIcon(){ $("#themeicon").innerHTML = document.documentElement.dataset.theme==="nacht" ? ICON.sonne : ICON.mond; }
|
||
$("#ringsbtn").addEventListener("click",()=>go("einst"));
|
||
$("#theme").addEventListener("click",()=>{
|
||
const el=document.documentElement;
|
||
el.dataset.theme = el.dataset.theme==="nacht" ? "tag" : "nacht";
|
||
themeIcon(); tiles();
|
||
});
|
||
document.addEventListener("change",e=>{
|
||
if(e.target.dataset.profil==="import"){
|
||
const datei=e.target.files[0];
|
||
if(!datei) return;
|
||
const leser=new FileReader();
|
||
leser.onload=()=>{
|
||
try{
|
||
const p=JSON.parse(leser.result);
|
||
if(p.config) Object.assign(CONFIG,p.config);
|
||
if(p.fahrzeug) Object.assign(CAR,p.fahrzeug);
|
||
bild=0; render();
|
||
}catch(err){ alert("Die Datei ließ sich nicht lesen: "+err.message); }
|
||
};
|
||
leser.readAsText(datei);
|
||
return;
|
||
}
|
||
const vb=e.target.dataset.vereinbart;
|
||
if(vb){ CAR.service.vereinbart[vb]=e.target.value; render(); return; }
|
||
const ah=e.target.dataset.ah;
|
||
if(ah){
|
||
CAR.service.autohaus[ah] = ah==="pos"
|
||
? (e.target.value.split(",").map(x=>parseFloat(x.trim())).filter(x=>!isNaN(x)).slice(0,2) || null)
|
||
: e.target.value;
|
||
render(); return;
|
||
}
|
||
const sb=e.target.dataset.sb;
|
||
if(sb){
|
||
const [i,feld]=sb.split("|");
|
||
const eintrag=CAR.service.buch[+i];
|
||
eintrag[feld] = (feld==="km") ? (parseInt(e.target.value,10)||0)
|
||
: (feld==="kosten") ? (e.target.value===""?null:parseFloat(e.target.value))
|
||
: e.target.value;
|
||
render(); return;
|
||
}
|
||
const rf=e.target.dataset.rf;
|
||
if(rf){
|
||
const [k,schluessel]=rf.split("|");
|
||
const wert=e.target.value;
|
||
CAR.reifen[k][schluessel] = (schluessel==="km") ? (parseInt(wert,10)||0) : wert;
|
||
render();
|
||
return;
|
||
}
|
||
if(e.target.dataset.schrift!==undefined){
|
||
beschriftung = e.target.checked;
|
||
$("#tabbar").classList.toggle("ohne", !beschriftung);
|
||
return; }
|
||
if(e.target.dataset.steuer!==undefined){ CAR.steuer.betrag=parseFloat(e.target.value)||0; render(); return; }
|
||
if(e.target.dataset.vbeitrag!==undefined){ CAR.versicherung.beitrag=parseFloat(e.target.value)||0; render(); return; }
|
||
if(e.target.dataset.pause!==undefined){ CONFIG.pauseMin=parseInt(e.target.value,10)||0; return; }
|
||
if(e.target.dataset.sd!==undefined){ CAR.smartdeal.aktiv=e.target.checked; render(); return; }
|
||
if(e.target.dataset.oelkm!==undefined){ CAR.oel.km=parseInt(e.target.value,10); return; }
|
||
if(e.target.dataset.oelm!==undefined){ CAR.oel.monate=parseInt(e.target.value,10); return; }
|
||
if(e.target.dataset.boden!==undefined){ bodenAn=e.target.checked; render(); return; }
|
||
if(e.target.dataset.startbild!==undefined){ CONFIG.startbild=e.target.value; render(); return; }
|
||
if(e.target.dataset.svsel!==undefined){ svAuswahl=parseInt(e.target.value,10); render(); return; }
|
||
});
|
||
document.addEventListener("click",e=>{
|
||
if(e.target.id==="carimg"){ bildWeiter(); return; }
|
||
|
||
if(e.target.closest("[data-nmauf]")){ nmOffen=!nmOffen; render(); return; }
|
||
if(e.target.closest("[data-nmspeichern]")){
|
||
const wert=parseInt($("#nm").value,10);
|
||
if(!isNaN(wert) && wert>0) CAR.reifen.anzugsmoment=wert;
|
||
nmOffen=false; render(); return;
|
||
}
|
||
if(e.target.closest("[data-sbneu]")){
|
||
CAR.service.buch.unshift({datum:"04.08.2026", km:CAR.odo, art:"Neuer Eintrag",
|
||
werkstatt:CAR.service.autohaus.name, kosten:null, arbeiten:""});
|
||
go("sbuch","0"); return;
|
||
}
|
||
if(e.target.closest("[data-neu]")){ neuOffen=!neuOffen; render(); return; }
|
||
if(e.target.closest("[data-fahrt]")){ fahrtOffen=!fahrtOffen; render(); return; }
|
||
if(e.target.closest("[data-beleg]")){
|
||
alert("Hier öffnet sich die Dateiauswahl. Der Parser liest Menge, Preis, "
|
||
+ "Rabatt und Tankstelle aus dem Beleg und trägt sie ein.");
|
||
return; }
|
||
const del=e.target.closest("[data-loeschen]");
|
||
if(del){ delete CAR.service.vereinbart[del.dataset.loeschen]; render(); return; }
|
||
const kj=e.target.closest("[data-kjahr]");
|
||
if(kj){ kostenJahr=parseInt(kj.dataset.kjahr,10); render(); return; }
|
||
const oel=e.target.closest("[data-oel]");
|
||
if(oel){ CAR.oel.modus=oel.dataset.oel; render(); return; }
|
||
const mode=e.target.closest("[data-mode]");
|
||
if(mode){ document.documentElement.dataset.theme=mode.dataset.mode; themeIcon(); tiles(); render(); return; }
|
||
const pr=e.target.closest("[data-profil]");
|
||
if(pr && pr.dataset.profil==="export"){
|
||
const profil={config:CONFIG, fahrzeug:CAR};
|
||
const a=document.createElement("a");
|
||
a.href="data:application/json;charset=utf-8,"+
|
||
encodeURIComponent(JSON.stringify(profil,null,2));
|
||
a.download="fahrzeug.json"; document.body.appendChild(a); a.click(); a.remove();
|
||
return;
|
||
}
|
||
const cs=e.target.closest("[data-csv]");
|
||
if(cs){
|
||
const w=cs.dataset.csv;
|
||
if(w==="fahrten") csvDatei("fahrten.csv",
|
||
["Datum","Start","Ziel","km","Dauer","Ø km/h","Kosten €","Art"],
|
||
TRIPS.map(t=>[t.tag,t.von,t.nach,de(t.dist),t.dauer,de(t.schnitt),eur(t.kosten),t.art]));
|
||
else if(w==="tanken") csvDatei("tankvorgaenge.csv",
|
||
["Datum","Uhrzeit","Station","Liter","€/l","Kosten €","SmartDeal €","km"],
|
||
FILLS.map(f=>[f.datum,f.zeit,f.station,de(f.liter,2),de(f.summe/f.liter,3),
|
||
eur(f.summe),eur(f.rabatt),de(f.odo)]));
|
||
else csvDatei("servicebuch.csv",["Datum","km","Art","Werkstatt","Kosten €"],
|
||
CAR.service.buch.map(e2=>[e2.datum,de(e2.km),e2.art,e2.werkstatt,e2.kosten!=null?eur(e2.kosten):""]));
|
||
return; }
|
||
const satz=e.target.closest("[data-satz]");
|
||
if(satz){ CAR.reifen.aktiv=satz.dataset.satz; render(); return; }
|
||
|
||
const k=e.target.closest("[data-ics]");
|
||
if(k){
|
||
if(k.dataset.ics==="service"){
|
||
const ts=termine(), t=ts[Math.min(svAuswahl,ts.length-1)];
|
||
const datum=$("#svDat").value;
|
||
CAR.service.vereinbart[t.art]=datum;
|
||
ics(`${CONFIG.fahrzeugtitel}: ${t.art}`, datum, CAR.service.autohaus.name,
|
||
t.km!==null ? `Fällig bei ${de(t.km)} km · ${CAR.service.autohaus.adresse}`
|
||
: CAR.service.autohaus.adresse);
|
||
render();
|
||
} else {
|
||
const dat=$("#rfDat").value;
|
||
CAR.reifen.wechsel.datum=dat;
|
||
CAR.reifen.wechsel.vereinbart=$("#rfOk").checked;
|
||
const ziel = CAR.reifen.aktiv==="Sommer" ? "Winter" : "Sommer";
|
||
ics(`${CONFIG.fahrzeugtitel}: Reifenwechsel auf ${ziel}`, dat,
|
||
CAR.service.autohaus.name, `Umstellung des Zählers auf den ${ziel}satz nicht vergessen`);
|
||
}
|
||
return;
|
||
}
|
||
const a=e.target.closest("[data-acc]");
|
||
if(a){ const b=document.getElementById(a.dataset.acc);
|
||
a.setAttribute("aria-expanded", b.classList.toggle("on")); return; }
|
||
const art=e.target.closest("[data-art]");
|
||
if(art){ const tr=TRIPS.find(x=>x.id===art.dataset.art);
|
||
tr.art = tr.art==="Arbeitsweg" ? "Privat" : "Arbeitsweg"; render(); return; }
|
||
const g=e.target.closest("[data-go]");
|
||
if(g){ const [n,i]=g.dataset.go.split(":"); go(n,i); }
|
||
});
|
||
themeIcon();
|
||
render();
|
||
</script>
|
||
</body>
|
||
</html>
|