Die Relingholme enden hinten bei 3,79 m statt 3,98 m: am Auto laufen sie ueber dem Radlauf aus, der Spoiler sitzt ein Stueck dahinter. Der Spoiler selbst ist an den Enden stumpf abgeschnitten statt spitz - die Spitzen gaben ihm die Form eines Blattes, am Auto hoert er schlicht auf. Die Spiegel ruecken von 1,81 m auf 1,62 m, also an den Fuss der A-Saeule, und die vorderen Seitenscheiben laufen bis 1,66 m nach vorn mit. Vorher stand dort ein Stueck Blech, das es nicht gibt. Die Anhaengerkupplung steht wieder hinten heraus - die Kugel rund neun Zentimeter hinter der Heckkante, so wie am Auto. Dass das nicht wie ein Loch im Umriss aussieht, liegt jetzt an der Farbe: ganz schwarz, damit erkennbar ein Anbauteil und kein fehlendes Blech. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2360 lines
80 KiB
CSS
2360 lines
80 KiB
CSS
/* ==========================================================================
|
|
Grundton der Oberflaeche
|
|
|
|
Die Seite laeuft auf AdminLTE, also auf Bootstrap. Beide beziehen ihre
|
|
Farben aus Variablen - deshalb wird hier nicht Regel fuer Regel
|
|
ueberschrieben, sondern die Palette ausgetauscht: ein paar Variablen am
|
|
Wurzelelement, und Karten, Tabellen, Abzeichen und Knoepfe folgen von
|
|
selbst. Was danach noch kommt, sind wenige gezielte Regeln fuer die Dinge,
|
|
die Bootstrap fest verdrahtet hat (Kartenrahmen, Kopfzeilen, Trennlinien).
|
|
|
|
Die Palette selbst ist die des Jahresvergleichs: ein leicht blaustichiges
|
|
Anthrazit als Grund, eine Spur hellere Flaeche fuer Karten, Haarlinien statt
|
|
Rahmen - und Bernstein als einzige Akzentfarbe, weil das auf dieser Seite
|
|
die Farbe der eigenen Anlage ist. Gruen, Rot und Gelb bleiben den
|
|
Zustaenden vorbehalten und sind kein Schmuck.
|
|
========================================================================== */
|
|
|
|
:root,
|
|
[data-bs-theme="dark"] {
|
|
--ton-grund: #191d20; /* Seitenhintergrund */
|
|
--ton-flaeche: #23282c; /* Karten */
|
|
--ton-flaeche-2: #2b3237; /* Kopfzeilen, Tabellenkopf */
|
|
--ton-linie: rgba(138, 148, 158, .20);
|
|
--ton-linie-satt: rgba(138, 148, 158, .38);
|
|
--ton-schrift: #e8ede9;
|
|
--ton-schrift-2: #9aa6ad;
|
|
--ton-schrift-3: #6f7a81;
|
|
--ton-sonne: #f0b429; /* die eigene Anlage */
|
|
--ton-sonne-rgb: 240, 180, 41;
|
|
--ton-gut: #4caf7d;
|
|
--ton-schlecht: #e06060;
|
|
--ton-radius: .7rem;
|
|
|
|
/* ... und dieselben Werte dort, wo Bootstrap sie sucht. */
|
|
--bs-body-bg: var(--ton-grund);
|
|
--bs-body-bg-rgb: 25, 29, 32;
|
|
--bs-body-color: var(--ton-schrift);
|
|
--bs-body-color-rgb: 232, 237, 233;
|
|
--bs-emphasis-color: #fff;
|
|
--bs-secondary-color: var(--ton-schrift-2);
|
|
--bs-secondary-bg: var(--ton-flaeche-2);
|
|
--bs-tertiary-color: var(--ton-schrift-3);
|
|
--bs-tertiary-bg: var(--ton-flaeche-2);
|
|
--bs-border-color: var(--ton-linie-satt);
|
|
--bs-border-radius: var(--ton-radius);
|
|
--bs-link-color: var(--ton-sonne);
|
|
--bs-link-hover-color: #ffc94d;
|
|
--bs-heading-color: var(--ton-schrift);
|
|
}
|
|
|
|
/* Der Rumpf traegt zwei Grundfarben: die Seite und die Leisten drumherum.
|
|
AdminLTE setzt sie ueber eigene Klassen, die hier auf denselben Ton
|
|
gebracht werden - sonst steht eine Karte auf drei verschiedenen Grautoenen. */
|
|
body.bg-body-tertiary,
|
|
.app-content,
|
|
.app-content-header { background: var(--ton-grund); }
|
|
|
|
.app-header.bg-body,
|
|
.app-sidebar.bg-body-secondary {
|
|
background: var(--ton-flaeche) !important;
|
|
border-color: var(--ton-linie) !important;
|
|
}
|
|
.app-header { box-shadow: 0 1px 0 var(--ton-linie); }
|
|
|
|
/* --- Karten --------------------------------------------------------------
|
|
Eine Karte ist eine Flaeche, kein Kasten: ein Ton heller als der Grund, eine
|
|
Haarlinie als Rand, kein Schlagschatten. Der Schatten trennte frueher, was
|
|
der Farbunterschied jetzt allein leistet. */
|
|
.card {
|
|
background: var(--ton-flaeche);
|
|
border: 1px solid var(--ton-linie);
|
|
border-radius: var(--ton-radius);
|
|
box-shadow: none;
|
|
}
|
|
.card-header {
|
|
background: transparent;
|
|
border-bottom: 1px solid var(--ton-linie);
|
|
padding-inline: 1rem;
|
|
}
|
|
.card-title {
|
|
font-size: 1rem;
|
|
font-weight: 500;
|
|
letter-spacing: -.01em;
|
|
}
|
|
.card-body { padding: 1rem; }
|
|
.card-footer {
|
|
background: transparent;
|
|
border-top: 1px solid var(--ton-linie);
|
|
}
|
|
|
|
/* Werkzeugknoepfe in der Kopfzeile: ruhig, bis man sie braucht. */
|
|
.btn-tool {
|
|
color: var(--ton-schrift-3);
|
|
transition: color .18s, background .18s;
|
|
border-radius: .35rem;
|
|
}
|
|
.btn-tool:hover,
|
|
.btn-tool:focus-visible { color: var(--ton-schrift); background: rgba(138, 148, 158, .12); }
|
|
|
|
/* --- Menue ---------------------------------------------------------------
|
|
Der aktive Punkt traegt die Akzentfarbe, nicht das Blau des Themes -
|
|
sonst haette die Seite zwei Hauptfarben. */
|
|
.sidebar-menu .nav-link {
|
|
border-radius: .45rem;
|
|
color: var(--ton-schrift-2);
|
|
}
|
|
.sidebar-menu .nav-link:hover { background: rgba(138, 148, 158, .1); color: var(--ton-schrift); }
|
|
.sidebar-menu .nav-link.active,
|
|
.sidebar-menu .nav-link.active:hover {
|
|
background: rgba(var(--ton-sonne-rgb), .16);
|
|
color: var(--ton-sonne);
|
|
}
|
|
.sidebar-brand { border-bottom: 1px solid var(--ton-linie); }
|
|
.brand-text { font-weight: 400; letter-spacing: .01em; }
|
|
|
|
/* --- Schrift -------------------------------------------------------------
|
|
Zahlen stehen ueberall in Spalten untereinander - mit Ziffern gleicher
|
|
Breite bleiben sie ausgerichtet, auch wenn sich der Wert aendert. */
|
|
.card-body,
|
|
.table,
|
|
.info-box-number,
|
|
.progress-bar { font-variant-numeric: tabular-nums; }
|
|
|
|
.app-content-header h3 {
|
|
font-weight: 500;
|
|
letter-spacing: -.01em;
|
|
}
|
|
|
|
/* --- Tabellen ------------------------------------------------------------ */
|
|
.table {
|
|
--bs-table-bg: transparent;
|
|
--bs-table-color: var(--ton-schrift);
|
|
--bs-table-border-color: var(--ton-linie);
|
|
--bs-table-hover-bg: rgba(138, 148, 158, .06);
|
|
--bs-table-striped-bg: rgba(138, 148, 158, .04);
|
|
}
|
|
.table > thead {
|
|
color: var(--ton-schrift-2);
|
|
font-size: .82rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* --- Abzeichen -----------------------------------------------------------
|
|
Gedaempft statt grell: ein Abzeichen soll den Zustand sagen, nicht die
|
|
Kachel dominieren. */
|
|
.badge { font-weight: 500; letter-spacing: .01em; }
|
|
.badge.text-bg-secondary {
|
|
background: rgba(138, 148, 158, .18) !important;
|
|
color: var(--ton-schrift-2) !important;
|
|
}
|
|
.badge.text-bg-success {
|
|
background: rgba(76, 175, 125, .18) !important;
|
|
color: var(--ton-gut) !important;
|
|
}
|
|
.badge.text-bg-warning {
|
|
background: rgba(240, 180, 41, .18) !important;
|
|
color: var(--ton-sonne) !important;
|
|
}
|
|
.badge.text-bg-danger {
|
|
background: rgba(224, 96, 96, .18) !important;
|
|
color: var(--ton-schlecht) !important;
|
|
}
|
|
.badge.text-bg-info {
|
|
background: rgba(122, 167, 199, .18) !important;
|
|
color: #9cc4de !important;
|
|
}
|
|
|
|
/* --- Formulare ----------------------------------------------------------- */
|
|
.form-control,
|
|
.form-select {
|
|
background: rgba(0, 0, 0, .18);
|
|
border-color: var(--ton-linie-satt);
|
|
color: var(--ton-schrift);
|
|
}
|
|
.form-control:focus,
|
|
.form-select:focus {
|
|
background: rgba(0, 0, 0, .18);
|
|
border-color: var(--ton-sonne);
|
|
box-shadow: 0 0 0 .2rem rgba(var(--ton-sonne-rgb), .2);
|
|
color: var(--ton-schrift);
|
|
}
|
|
.form-check-input:checked { background-color: var(--ton-sonne); border-color: var(--ton-sonne); }
|
|
.form-check-input:focus { box-shadow: 0 0 0 .2rem rgba(var(--ton-sonne-rgb), .2); }
|
|
|
|
/* Sichtbarer Tastaturfokus, einheitlich - AdminLTE setzt ihn stellenweise ab. */
|
|
a:focus-visible,
|
|
button:focus-visible,
|
|
[tabindex]:focus-visible {
|
|
outline: 2px solid var(--ton-sonne);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* --- Trennlinien und Modals ---------------------------------------------- */
|
|
hr { border-color: var(--ton-linie); opacity: 1; }
|
|
.modal-content {
|
|
background: var(--ton-flaeche);
|
|
border: 1px solid var(--ton-linie-satt);
|
|
border-radius: var(--ton-radius);
|
|
}
|
|
.modal-header,
|
|
.modal-footer { border-color: var(--ton-linie); }
|
|
|
|
|
|
/* ==========================================================================
|
|
Jahresstatistik (js/solar/jahresstatistik.js)
|
|
|
|
Die Tabelle traegt die Seite "Vergangenheit" und steht in kleiner Form auch
|
|
auf der Solarseite. Sie ist zum Lesen einer Zeile gebaut: Kennzahlen links,
|
|
Jahre nebeneinander, die Veraenderung als Zahl - nicht als blosser Pfeil.
|
|
========================================================================== */
|
|
|
|
/* Der Baustein setzt seine Bloecke selbst auf Abstand - und zwar auf denselben
|
|
wie den zwischen den Leitzahlen und den Innenabstand der Karte. Alle Nahtstellen
|
|
sind dadurch gleich weit, gleich ob die Werkzeugleiste dabei ist oder nicht. */
|
|
.jahresstatistik {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--stat-abstand, 1.25rem);
|
|
}
|
|
|
|
/* Der Innenabstand der Karte gehoert zum selben Mass - sonst sitzt die erste
|
|
Kachel enger unter der Ueberschrift als die zweite unter der ersten.
|
|
|
|
Der Vorsatz .app-content ist noetig, nicht schmueckend: weiter unten in
|
|
dieser Datei setzt .app-content .card-body auf dem Handy einen kleineren
|
|
Innenabstand, und bei gleicher Spezifitaet gewaenne die spaetere Regel. */
|
|
.app-content .card-body.statistik { padding: var(--stat-abstand, 1.25rem); }
|
|
|
|
/* Auf dem Handy ruecken alle Nahtstellen zusammen - aber gemeinsam, sonst
|
|
waere die Gleichheit wieder dahin. */
|
|
@media (max-width: 767.98px) {
|
|
.jahresstatistik,
|
|
.app-content .card-body.statistik { --stat-abstand: 1rem; }
|
|
}
|
|
|
|
/* --- Leitzahlen ---------------------------------------------------------- */
|
|
.jahresstatistik .leitzahlen {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
|
gap: var(--stat-abstand, 1.25rem);
|
|
}
|
|
.jahresstatistik .leitzahl {
|
|
background: rgba(138, 148, 158, .07);
|
|
border: 1px solid var(--ton-linie);
|
|
border-radius: var(--ton-radius);
|
|
padding: .9rem 1.05rem 1rem;
|
|
}
|
|
.jahresstatistik .leitzahl .name { font-size: .78rem; color: var(--ton-schrift-2); }
|
|
.jahresstatistik .leitzahl .zahl {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: .35rem;
|
|
margin-top: .3rem;
|
|
font-size: 1.9rem;
|
|
font-weight: 500;
|
|
line-height: 1.1;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.jahresstatistik .leitzahl .einheit {
|
|
font-size: .95rem;
|
|
font-weight: 400;
|
|
color: var(--ton-schrift-2);
|
|
}
|
|
.jahresstatistik .leitzahl .fuss {
|
|
margin-top: .45rem;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: .5rem;
|
|
font-size: .76rem;
|
|
color: var(--ton-schrift-3);
|
|
}
|
|
.jahresstatistik .leitzahl.betont { border-color: rgba(var(--ton-sonne-rgb), .45); }
|
|
.jahresstatistik .leitzahl.betont .zahl { color: var(--ton-sonne); }
|
|
|
|
/* Die Veraenderung: Richtung und Groesse, nicht nur Richtung. */
|
|
.jahresstatistik .delta {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .25rem;
|
|
font-size: .78rem;
|
|
font-variant-numeric: tabular-nums;
|
|
white-space: nowrap;
|
|
}
|
|
.jahresstatistik .delta.gut { color: var(--ton-gut); }
|
|
.jahresstatistik .delta.schlecht { color: var(--ton-schlecht); }
|
|
.jahresstatistik .delta.gleich { color: var(--ton-schrift-3); }
|
|
|
|
/* --- Werkzeugleiste ------------------------------------------------------ */
|
|
.jahresstatistik .werkzeuge {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: .75rem 1.25rem;
|
|
}
|
|
.jahresstatistik .umschalter {
|
|
display: inline-flex;
|
|
border: 1px solid var(--ton-linie-satt);
|
|
border-radius: .45rem;
|
|
overflow: hidden;
|
|
}
|
|
.jahresstatistik .umschalter button {
|
|
appearance: none;
|
|
border: 0;
|
|
background: none;
|
|
color: var(--ton-schrift-2);
|
|
font: inherit;
|
|
font-size: .82rem;
|
|
padding: .4rem .9rem;
|
|
cursor: pointer;
|
|
transition: background .18s, color .18s;
|
|
}
|
|
.jahresstatistik .umschalter button + button { border-left: 1px solid var(--ton-linie-satt); }
|
|
.jahresstatistik .umschalter button:hover { background: rgba(138, 148, 158, .1); }
|
|
.jahresstatistik .umschalter button[aria-pressed="true"] {
|
|
background: rgba(var(--ton-sonne-rgb), .16);
|
|
color: var(--ton-sonne);
|
|
}
|
|
|
|
/* Das Jahrfenster: zwei Pfeile und dazwischen, was gerade zu sehen ist. */
|
|
.jahresstatistik .jahrwahl {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .35rem;
|
|
font-size: .82rem;
|
|
color: var(--ton-schrift-2);
|
|
}
|
|
.jahresstatistik .jahrwahl button {
|
|
appearance: none;
|
|
border: 1px solid var(--ton-linie-satt);
|
|
background: none;
|
|
color: var(--ton-schrift-2);
|
|
border-radius: .35rem;
|
|
width: 1.9rem;
|
|
height: 1.9rem;
|
|
line-height: 1;
|
|
cursor: pointer;
|
|
transition: background .18s, color .18s, opacity .18s;
|
|
}
|
|
.jahresstatistik .jahrwahl button:hover:not(:disabled) {
|
|
background: rgba(138, 148, 158, .12);
|
|
color: var(--ton-schrift);
|
|
}
|
|
.jahresstatistik .jahrwahl button:disabled { opacity: .3; cursor: default; }
|
|
.jahresstatistik .jahrwahl .fenster { font-variant-numeric: tabular-nums; min-width: 5.5rem; text-align: center; }
|
|
|
|
.jahresstatistik .kasten {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .45rem;
|
|
font-size: .82rem;
|
|
color: var(--ton-schrift-2);
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
.jahresstatistik .kasten input { accent-color: var(--ton-sonne); width: 1rem; height: 1rem; }
|
|
|
|
/* --- Die Tabelle --------------------------------------------------------- */
|
|
.jahresstatistik .tafel-scroll {
|
|
overflow-x: auto;
|
|
border: 1px solid var(--ton-linie);
|
|
border-radius: var(--ton-radius);
|
|
}
|
|
.jahresstatistik .tafel {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: .88rem;
|
|
margin: 0;
|
|
}
|
|
.jahresstatistik .tafel thead th {
|
|
background: var(--ton-flaeche-2);
|
|
text-align: right;
|
|
font-weight: 500;
|
|
font-size: .78rem;
|
|
padding: .55rem .9rem .5rem;
|
|
border-bottom: 1px solid var(--ton-linie-satt);
|
|
white-space: nowrap;
|
|
}
|
|
.jahresstatistik .tafel thead th:first-child { text-align: left; }
|
|
.jahresstatistik .tafel thead th.jetzt { color: var(--ton-sonne); }
|
|
.jahresstatistik .tafel thead .zeitraum {
|
|
display: block;
|
|
font-weight: 400;
|
|
font-size: .68rem;
|
|
color: var(--ton-schrift-3);
|
|
letter-spacing: .03em;
|
|
}
|
|
|
|
.jahresstatistik .tafel tbody td {
|
|
padding: .4rem .9rem;
|
|
border-bottom: 1px solid var(--ton-linie);
|
|
text-align: right;
|
|
font-variant-numeric: tabular-nums;
|
|
white-space: nowrap;
|
|
}
|
|
.jahresstatistik .tafel tbody td.name {
|
|
text-align: left;
|
|
width: 40%;
|
|
min-width: 14rem;
|
|
white-space: normal;
|
|
}
|
|
.jahresstatistik .tafel tbody tr:last-child td { border-bottom: 0; }
|
|
@media (hover: hover) {
|
|
.jahresstatistik .tafel tbody tr:hover td { background: rgba(138, 148, 158, .06); }
|
|
.jahresstatistik .tafel tbody tr.gruppe:hover td { background: none; }
|
|
}
|
|
|
|
/* Gruppenkopf: kein Kasten, nur eine Zaesur. */
|
|
.jahresstatistik .tafel tr.gruppe td {
|
|
padding: 1rem .9rem .25rem;
|
|
border-bottom: 1px solid var(--ton-linie-satt);
|
|
font-size: .7rem;
|
|
letter-spacing: .13em;
|
|
text-transform: uppercase;
|
|
color: var(--ton-schrift-3);
|
|
text-align: left;
|
|
}
|
|
|
|
/* Die Summenzeile traegt das Gewicht, die Teile darunter nicht. */
|
|
.jahresstatistik .tafel tr.summe td { font-size: .95rem; }
|
|
.jahresstatistik .tafel tr.summe td.name { font-weight: 500; }
|
|
.jahresstatistik .tafel tr.summe .wert-jetzt { color: var(--ton-sonne); }
|
|
|
|
/* Einrueckung: "davon" teilt die Summe auf, "darin" greift etwas heraus, das
|
|
schon in einer Zeile darueber steckt. */
|
|
.jahresstatistik .tafel td.name .stufe-1 {
|
|
padding-left: 1.4rem;
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
.jahresstatistik .tafel td.name .stufe-1::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: .45rem;
|
|
top: .75em;
|
|
width: .55rem;
|
|
border-top: 1px solid var(--ton-linie-satt);
|
|
}
|
|
.jahresstatistik .tafel tr.teilmenge td { color: var(--ton-schrift-2); font-size: .82rem; }
|
|
|
|
/* Zweite Stufe. Der Strich sitzt tiefer eingerueckt als der der ersten und
|
|
zeigt damit, an welcher Zeile die Teilmenge haengt. */
|
|
.jahresstatistik .tafel td.name .stufe-2 {
|
|
padding-left: 2.8rem;
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
.jahresstatistik .tafel td.name .stufe-2::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: 1.85rem;
|
|
top: .75em;
|
|
width: .55rem;
|
|
border-top: 1px dashed var(--ton-linie-satt);
|
|
}
|
|
.jahresstatistik .tafel .darin {
|
|
font-size: .68rem;
|
|
letter-spacing: .06em;
|
|
text-transform: uppercase;
|
|
color: var(--ton-schrift-3);
|
|
margin-right: .4rem;
|
|
}
|
|
.jahresstatistik .tafel .einheit-klein {
|
|
font-size: .7rem;
|
|
color: var(--ton-schrift-3);
|
|
margin-left: .4rem;
|
|
}
|
|
|
|
.jahresstatistik .tafel .wert-alt { color: var(--ton-schrift-2); }
|
|
.jahresstatistik .tafel .leer { color: var(--ton-schrift-3); text-align: left; }
|
|
|
|
/* Die Gesamtspalte ist eine andere Art Zahl als ein Jahreswert - sie steht
|
|
deshalb abgesetzt und ruhiger. */
|
|
.jahresstatistik .tafel .gesamt {
|
|
border-left: 1px solid var(--ton-linie-satt);
|
|
color: var(--ton-schrift-2);
|
|
}
|
|
.jahresstatistik .tafel thead th.gesamt { color: var(--ton-schrift-2); }
|
|
|
|
/* Aufklappbare Teilzeilen */
|
|
.jahresstatistik .tafel button.klapp {
|
|
appearance: none;
|
|
background: none;
|
|
border: 0;
|
|
color: inherit;
|
|
font: inherit;
|
|
padding: 0;
|
|
cursor: pointer;
|
|
display: inline-flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: .2rem .4rem;
|
|
text-align: left;
|
|
}
|
|
.jahresstatistik .tafel button.klapp .pfeil {
|
|
display: inline-block;
|
|
width: .55rem;
|
|
color: var(--ton-schrift-3);
|
|
transition: transform .18s;
|
|
}
|
|
.jahresstatistik .tafel button.klapp[aria-expanded="true"] .pfeil { transform: rotate(90deg); }
|
|
|
|
/* Was hinter einer zugeklappten Zeile steckt - sonst waere das Zugeklappte
|
|
nicht nur zusammengefasst, sondern verschwunden. */
|
|
.jahresstatistik .tafel .posten {
|
|
margin-left: .55rem;
|
|
padding: .05rem .45rem;
|
|
border: 1px solid var(--ton-linie-satt);
|
|
border-radius: 1rem;
|
|
font-size: .68rem;
|
|
font-weight: 400;
|
|
letter-spacing: .03em;
|
|
color: var(--ton-schrift-3);
|
|
white-space: nowrap;
|
|
}
|
|
@media (hover: hover) {
|
|
.jahresstatistik .tafel button.klapp:hover .posten {
|
|
border-color: var(--ton-sonne);
|
|
color: var(--ton-sonne);
|
|
}
|
|
}
|
|
.jahresstatistik .tafel tr.versteckt { display: none; }
|
|
|
|
/* --- Monatsverlauf ------------------------------------------------------- */
|
|
.jahresstatistik .tafel th.verlauf,
|
|
.jahresstatistik .tafel td.verlauf { width: 7.5rem; }
|
|
.jahresstatistik .spark {
|
|
display: block;
|
|
/* Waagerecht faehrt der Finger die Monate ab, senkrecht scrollt die Seite
|
|
weiter - ohne diese Angabe verschluckt der Browser das Wischen. */
|
|
touch-action: pan-y;
|
|
}
|
|
.jahresstatistik .spark rect.balken { fill: var(--ton-linie-satt); transition: fill .15s; }
|
|
.jahresstatistik .spark rect.balken.jetzt { fill: var(--ton-sonne); }
|
|
.jahresstatistik .spark rect.balken.aktiv { fill: var(--ton-sonne); }
|
|
.jahresstatistik .spark line.basis { stroke: var(--ton-linie); stroke-width: 1; }
|
|
|
|
/* Die ganze Zelle nimmt die Beruehrung an, nicht nur die Balken darin -
|
|
ein SVG-Wurzelelement laesst sich nicht mit Innenabstand vergroessern. */
|
|
.jahresstatistik .tafel td.verlauf { touch-action: pan-y; cursor: crosshair; }
|
|
|
|
.spark-tipp {
|
|
position: fixed;
|
|
z-index: 1080;
|
|
pointer-events: none;
|
|
background: #12161a;
|
|
border: 1px solid var(--ton-linie-satt);
|
|
border-radius: .35rem;
|
|
padding: .3rem .55rem;
|
|
font-size: .75rem;
|
|
font-variant-numeric: tabular-nums;
|
|
box-shadow: 0 .4rem 1.2rem rgba(0, 0, 0, .5);
|
|
opacity: 0;
|
|
transition: opacity .12s;
|
|
}
|
|
.spark-tipp.an { opacity: 1; }
|
|
|
|
/* --- Fussnoten ----------------------------------------------------------- */
|
|
.jahresstatistik .fussnoten {
|
|
display: grid;
|
|
gap: .5rem;
|
|
font-size: .78rem;
|
|
color: var(--ton-schrift-2);
|
|
max-width: 68ch;
|
|
}
|
|
.jahresstatistik .fussnoten p { margin: 0; }
|
|
.jahresstatistik .fussnoten b { color: var(--ton-schrift); font-weight: 500; }
|
|
|
|
@media (max-width: 575.98px) {
|
|
.jahresstatistik .tafel tbody td.name { min-width: 11rem; }
|
|
.jahresstatistik .werkzeuge { gap: .6rem .9rem; }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.jahresstatistik .umschalter button,
|
|
.jahresstatistik .jahrwahl button,
|
|
.jahresstatistik .spark rect.balken,
|
|
.jahresstatistik .tafel button.klapp .pfeil,
|
|
.spark-tipp { transition: none; }
|
|
}
|
|
|
|
|
|
.winddir {
|
|
position:absolute;
|
|
left:60%;
|
|
width:25%;
|
|
height:40%;
|
|
padding: 0;
|
|
background-image: url('../assets/img/arrow.svg');
|
|
background-size:contain;
|
|
background-repeat: no-repeat;
|
|
background-position: center;
|
|
}
|
|
|
|
|
|
/* Schieberegler in den Modals (Autoladung, Heizstab, Thermostat).
|
|
Der gefuellte Anteil kommt aus --background-size, gesetzt von
|
|
bindModalSlider() in js/solar/common.js. */
|
|
input[type='range']::-webkit-slider-runnable-track {
|
|
background: linear-gradient(to right, #00788F, #00788F), #D7D7D7;
|
|
background-size: var(--background-size, 0%) 100%;
|
|
background-repeat: no-repeat;
|
|
}
|
|
|
|
/* Diagramme (Chart.js). Die Hoehe kommt aus diesem Container, nicht aus dem
|
|
canvas - die Charts laufen mit maintainAspectRatio: false. Auf dem Handy
|
|
ist der Container nur rund 300 px breit; mit 400 px Hoehe wird aus einer
|
|
Zeitreihe ein Hochformat, in dem die Zeitachse die kurze Seite ist. */
|
|
.chart-container {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 400px;
|
|
}
|
|
|
|
@media (max-width: 767.98px) {
|
|
.chart-container {
|
|
height: 250px;
|
|
}
|
|
}
|
|
|
|
/* Auf dem Handy gehen von 375 px rund 75 an Innenabstaende verloren, und
|
|
zwischen den Karten stehen 24 px. Beides wird hier enger gefasst - nur
|
|
im Inhaltsbereich, damit Seitenleiste, Kopfzeile und Modals unberuehrt
|
|
bleiben. Die Abstandsklassen von Bootstrap (mb-4) tragen !important,
|
|
deshalb steht es auch hier. */
|
|
@media (max-width: 767.98px) {
|
|
.app-content {
|
|
padding: 0 .25rem;
|
|
}
|
|
|
|
.app-content-header {
|
|
padding: .5rem .25rem;
|
|
}
|
|
|
|
.app-content .row {
|
|
--bs-gutter-x: .5rem;
|
|
}
|
|
|
|
.app-content .card {
|
|
margin-bottom: .75rem !important;
|
|
}
|
|
|
|
/* Nur der Standardwert wird kleiner; eigene Angaben im Markup (p-0 fuer
|
|
das Realtime-SVG) gelten weiter. */
|
|
.app-content .card-body {
|
|
padding: .5rem;
|
|
}
|
|
|
|
/* Die Jahrestabelle scrollt auf dem Handy seitwaerts; damit moeglichst
|
|
viel davon ohne Schieben zu sehen ist, ruecken die Spalten enger
|
|
zusammen. */
|
|
.jahresstatistik .tafel tbody td,
|
|
.jahresstatistik .tafel thead th {
|
|
padding-inline: .55rem;
|
|
}
|
|
}
|
|
|
|
/* Editor der Automatiken. Eine Bedingungszeile traegt Geraet, Messwert,
|
|
Vergleich, Wert, Einheit und den Papierkorb nebeneinander - auf einem
|
|
Handy bleiben davon "Therm OG Bad" und "te" uebrig, weil die Felder in
|
|
der input-group einfach mitschrumpfen. Unter 576 px bekommen deshalb
|
|
Geraet und Messwert je eine eigene Zeile; Vergleich, Wert und Einheit
|
|
sind kurz genug, um zusammen in die naechste zu passen. */
|
|
@media (max-width: 575.98px) {
|
|
/* Die input-group-Klasse muss mit in den Selektor: solar.css wird vor
|
|
AdminLTE geladen, und Bootstraps ".input-group > .form-select" haette
|
|
sonst dasselbe Gewicht und wuerde als spaeteres Blatt gewinnen. */
|
|
.input-group.auto-zeile > .auto-geraet,
|
|
.input-group.auto-zeile > .auto-messwert {
|
|
flex: 1 1 100%;
|
|
width: auto;
|
|
}
|
|
}
|
|
|
|
/* Raum-Modal. Ein Kommando mit mehreren Parametern ("Position+Neigung")
|
|
traegt Beschriftung, zwei Zahlenfelder und den Ausloeseknopf in einer
|
|
input-group - auf einem Handy schrumpfen die Felder dabei auf Nullbreite.
|
|
Eine Mindestbreite laesst die Zeile stattdessen umbrechen. */
|
|
.input-group.raum-cmd > .form-control,
|
|
.input-group.raum-cmd > .form-select {
|
|
min-width: 5rem;
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Raum-Modal: Bedienelemente
|
|
Erzeugt von restricted/roomControls.php, verdrahtet in js/solar/homeMQTT.js.
|
|
-------------------------------------------------------------------------- */
|
|
|
|
/* Die Geraetegruppen als Reiter. Auf einem Handy passen fuenf
|
|
Beschriftungen nicht nebeneinander - dann scrollt die Leiste seitwaerts,
|
|
statt die Namen umzubrechen. Die durchgehende Linie unter den Reitern
|
|
darf dabei nicht mitscrollen, sie gehoert an den unteren Rand. */
|
|
|
|
/* Waehrend ein Kommando unterwegs ist. Ein "Zu" an einer Jalousie dauert
|
|
ueber eine Minute; ohne sichtbare Sperre tippt man in der Zeit nach. */
|
|
.raum-geraet.raum-warte {
|
|
opacity: 0.55;
|
|
pointer-events: none;
|
|
}
|
|
.raum-geraet.raum-warte::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0.5rem;
|
|
right: 0.5rem;
|
|
width: 0.9rem;
|
|
height: 0.9rem;
|
|
border: 2px solid currentColor;
|
|
border-right-color: transparent;
|
|
border-radius: 50%;
|
|
animation: raum-dreht 0.8s linear infinite;
|
|
}
|
|
.raum-geraet {
|
|
position: relative;
|
|
}
|
|
@keyframes raum-dreht {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Regler im Raum-Modal
|
|
|
|
Eigenes Aussehen statt des Bootstrap-Standards: dessen weisse Bahn mit dem
|
|
blauen Griff sticht auf den dunklen Karten heraus, und in einem Raum mit
|
|
drei Jalousien sind das sechs helle Balken. Bahn und Griff tragen deshalb
|
|
dasselbe Blaugruen wie der Temperaturregler, und der ungefuellte Teil ist
|
|
ein Grau, das in beiden Themes traegt.
|
|
|
|
Bewusst nur innerhalb von #roomView: die Regler in den Modals fuer
|
|
Autoladung und Heizstab bleiben, wie sie sind.
|
|
-------------------------------------------------------------------------- */
|
|
#roomView input[type='range'] {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
width: 100%;
|
|
height: 1.5rem;
|
|
padding: 0;
|
|
margin: 0;
|
|
background: transparent;
|
|
}
|
|
#roomView input[type='range']:focus {
|
|
outline: 0;
|
|
}
|
|
/* Getrennt notiert, nicht als Liste: einen Selektor, den er nicht kennt,
|
|
wirft der Browser samt der ganzen Regel weg - und dann bliebe die Bahn
|
|
ungestaltet. */
|
|
#roomView input[type='range']::-webkit-slider-runnable-track {
|
|
height: 0.375rem;
|
|
border: 0;
|
|
border-radius: 0.375rem;
|
|
background: linear-gradient(to right, #00788F, #00788F), rgba(128, 128, 128, 0.32);
|
|
background-size: var(--background-size, 0%) 100%;
|
|
background-repeat: no-repeat;
|
|
}
|
|
#roomView input[type='range']::-moz-range-track {
|
|
height: 0.375rem;
|
|
border: 0;
|
|
border-radius: 0.375rem;
|
|
background: linear-gradient(to right, #00788F, #00788F), rgba(128, 128, 128, 0.32);
|
|
background-size: var(--background-size, 0%) 100%;
|
|
background-repeat: no-repeat;
|
|
}
|
|
#roomView input[type='range']::-webkit-slider-thumb {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
width: 1.05rem;
|
|
height: 1.05rem;
|
|
/* (Bahnhoehe - Griffhoehe) / 2, damit der Griff auf der Bahn sitzt. */
|
|
margin-top: -0.34rem;
|
|
border: 2px solid #fff;
|
|
border-radius: 50%;
|
|
background: #00788F;
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
|
|
}
|
|
#roomView input[type='range']::-moz-range-thumb {
|
|
width: 1.05rem;
|
|
height: 1.05rem;
|
|
border: 2px solid #fff;
|
|
border-radius: 50%;
|
|
background: #00788F;
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
|
|
}
|
|
|
|
/* Schieberegler stehen dicht untereinander (Helligkeit, Farbe). Ohne den
|
|
Abstand kleben Beschriftung und Bahn aneinander.
|
|
Die senkrechten Spalten stehen dagegen nebeneinander - dort wuerde der
|
|
Abstand die zweite Spalte um genau diese 0,35 rem tiefer setzen. */
|
|
.raum-regler + .raum-regler:not(.raum-spalte) {
|
|
margin-top: 0.35rem;
|
|
}
|
|
|
|
/* Messwerte als Gitter statt als Textwurst: ein Stromzaehler hat sechzehn
|
|
Werte, die in einer Zeile niemand findet. auto-fill statt fester Spalten,
|
|
damit auf dem Handy zwei und auf dem Schirm vier nebeneinander passen. */
|
|
.raum-werte {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
|
|
gap: 0.4rem;
|
|
}
|
|
.raum-wert {
|
|
background: rgba(128, 128, 128, 0.08);
|
|
border-radius: 0.35rem;
|
|
padding: 0.3rem 0.45rem;
|
|
overflow: hidden;
|
|
}
|
|
.raum-wert-zahl {
|
|
font-size: 0.95rem;
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
.raum-wert-einheit {
|
|
font-size: 0.7rem;
|
|
font-weight: 400;
|
|
opacity: 0.6;
|
|
}
|
|
.raum-wert-name {
|
|
font-size: 0.68rem;
|
|
opacity: 0.6;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Raum-Modal: Jalousien
|
|
-------------------------------------------------------------------------- */
|
|
|
|
/* Fahrknoepfe, Hoehe und Neigung nebeneinander. Die Neigung nimmt den Rest -
|
|
sie ist die einzige der drei Spalten, die von Breite profitiert. */
|
|
.raum-jalousie {
|
|
display: flex;
|
|
align-items: stretch;
|
|
justify-content: space-between;
|
|
gap: 0.4rem;
|
|
}
|
|
/* Das Fensterbild steht zwischen Knoepfen und Reglern - schmal, mit Luft
|
|
zu beiden Seiten. Der uebrige Platz verteilt sich auf die Zwischenraeume
|
|
(space-between an .raum-jalousie), statt das Bild breitzuziehen. */
|
|
.raum-jalousie .raum-lamellen {
|
|
flex: 0 1 5rem;
|
|
min-width: 2.2rem;
|
|
margin: 0 0.4rem;
|
|
}
|
|
.raum-jalousie .dropdown {
|
|
align-self: flex-start;
|
|
}
|
|
|
|
/* Auf, Stop, Zu untereinander - die Knoepfe zeigen in die Richtung, in die
|
|
sie fahren. Breit genug fuer einen Daumen: sie sind das, was man im
|
|
Vorbeigehen antippt, die Regler daneben braucht man seltener. */
|
|
.raum-fahrt {
|
|
flex: 0 0 3.1rem;
|
|
}
|
|
.raum-fahrt .btn {
|
|
padding: 0.3rem 0;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
/* Eine Spalte mit senkrechtem Regler: Name, oberes Wort, Bahn, unteres
|
|
Wort, Zahl. Breit genug fuer "Position" in der kleinen Schrift. */
|
|
.raum-spalte {
|
|
flex: 0 0 3.4rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
text-align: center;
|
|
}
|
|
.raum-name {
|
|
font-size: 0.62rem;
|
|
opacity: 0.8;
|
|
white-space: nowrap;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
/* Der Kasten, in dem ein gewoehnlicher Regler auf der Seite liegt.
|
|
Gedreht statt writing-mode: so gebaute Regler lassen sich am Handy kaum
|
|
anfassen - das Ziehen wird als Wischen gelesen und blaettert die Seite.
|
|
Gedreht bewegt sich der Regler in seinen eigenen Koordinaten waagerecht,
|
|
und touch-action haelt die Seite still, solange der Finger auf ihm liegt.
|
|
rotate(90deg) legt den kleinen Wert nach oben: "oben" ist 0 %. */
|
|
.raum-senkrecht {
|
|
position: relative;
|
|
width: 1.6rem;
|
|
height: 6.5rem;
|
|
margin: 0.1rem 0;
|
|
}
|
|
#roomView .raum-senkrecht input[type='range'] {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
width: 6.5rem; /* = Hoehe des Kastens, die Laenge der Bahn */
|
|
height: 1.6rem; /* = Breite des Kastens, die Flaeche zum Treffen */
|
|
transform: translate(-50%, -50%) rotate(90deg);
|
|
touch-action: none;
|
|
}
|
|
|
|
/* Die Endstellungen in Worten statt in Prozent. */
|
|
.raum-ende {
|
|
font-size: 0.68rem;
|
|
opacity: 0.65;
|
|
line-height: 1.1;
|
|
}
|
|
|
|
/* Die Lamellen zur Neigung. Ihre Hoehe setzt lamellenZeichnen() in
|
|
js/solar/homeMQTT.js - schmal mit Luft dazwischen heisst offen,
|
|
aneinanderliegend heisst geschlossen. */
|
|
.raum-lamellen {
|
|
display: block;
|
|
align-self: center;
|
|
height: 6.9rem;
|
|
/* Der Rahmen macht aus dem Streifen ein Fenster - ohne ihn liest sich das
|
|
geschlossene Bild wie eine zweite Reglerbahn. */
|
|
background: rgba(0, 120, 143, 0.14);
|
|
border: 1px solid rgba(128, 128, 128, 0.35);
|
|
border-radius: 0.2rem;
|
|
}
|
|
.raum-lamelle {
|
|
fill: currentColor;
|
|
opacity: 0.6;
|
|
stroke: rgba(0, 0, 0, 0.35);
|
|
stroke-width: 0.6;
|
|
vector-effect: non-scaling-stroke;
|
|
}
|
|
.raum-endschiene {
|
|
fill: currentColor;
|
|
opacity: 0.85;
|
|
}
|
|
|
|
/* --- Einstellungen: Preistabellen ------------------------------------ */
|
|
|
|
/* Der Spaltenkopf steht ueber der ersten Zeile und muss deren Einrueckung
|
|
treffen, sonst rutschen Beschriftung und Feld auseinander. Er bleibt
|
|
einzeilig, braucht also keinen senkrechten Gutter - und ohne den entfaellt
|
|
auch Bootstraps negative Marge von selbst. */
|
|
.preis-kopf {
|
|
--bs-gutter-y: 0;
|
|
padding: 0 0.25rem 0.35rem;
|
|
}
|
|
|
|
/* Eine Zeile ist selbst eine .row mit g-2. Bootstrap zieht so eine Reihe um
|
|
die Gutter-Hoehe nach oben und gibt jeder Spalte dieselbe Marge nach unten
|
|
zurueck - gedacht fuer Reihen, die nebeneinander im Raster stehen. Hier
|
|
stehen sie untereinander, und der Zug nach oben frisst den unteren
|
|
Innenabstand der vorigen Zeile auf: auf dem Handy, wo der Papierkorb in
|
|
einer eigenen Zeile landet, klebte er am Trennstrich.
|
|
|
|
Die senkrechte Gutter-Marge wird hier gebraucht - sie haelt die umbrochenen
|
|
Feldzeilen auseinander -, der Zug nach oben nicht. Die Regel braucht eine
|
|
Klasse mehr als Bootstraps .row: solar.css wird vor AdminLTE geladen und
|
|
verliert bei gleicher Spezifitaet. */
|
|
.preis-zeilen .preis-zeile {
|
|
margin-top: 0;
|
|
}
|
|
|
|
/* Oben um die Gutter-Hoehe weniger Innenabstand, damit ueber der ersten und
|
|
unter der letzten Feldzeile gleich viel Luft steht. */
|
|
.preis-zeile {
|
|
padding: 0.15rem 0.25rem 0.65rem;
|
|
border-top: 1px solid rgba(128, 128, 128, 0.25);
|
|
}
|
|
/* Die Einheit ist Beiwerk und darf der Zahl nicht den Platz nehmen: hinter
|
|
"kWh/100 km" bliebe in voller Schrift kaum ein Drittel der Spalte fuer das
|
|
Eingabefeld uebrig. */
|
|
.preis-zeile .input-group-text {
|
|
font-size: 0.75rem;
|
|
padding-left: 0.4rem;
|
|
padding-right: 0.4rem;
|
|
}
|
|
|
|
/* Der Zeitraum, der heute gilt - der einzige, den man beim Nachschlagen
|
|
wirklich sucht. */
|
|
.preis-heute {
|
|
background: rgba(0, 120, 143, 0.12);
|
|
border-radius: 0.4rem;
|
|
}
|
|
|
|
|
|
/* ==========================================================================
|
|
Skoda-Seite (restricted/skoda.php)
|
|
|
|
Farben kommen aus den Bootstrap-Variablen des Themes, damit die Seite dem
|
|
Hell-/Dunkelmodus folgt, ohne eine zweite Palette zu pflegen. Nur die
|
|
Bedeutungsfarben stehen fuer sich: bernstein fuer "offen", gelb fuer
|
|
eingeschaltetes Licht, gruen fuer Laden, rot fuer einen leeren Akku.
|
|
|
|
Sie haengen alle an .skoda-seite (dem <main> der Seite) und werden von dort
|
|
vererbt - Fahrzeugbild, Kennzahlen, Balken und Karte holen sie sich also
|
|
aus einer einzigen Quelle. Wo eine Farbe mit Deckkraft gebraucht wird,
|
|
steht sie zusaetzlich als RGB-Tripel bereit, denn rgba() kann eine
|
|
Hex-Variable nicht aufloesen.
|
|
========================================================================== */
|
|
|
|
.skoda-seite {
|
|
--skoda-offen: #e0904f; /* offene Tuer, Klappe, Fenster */
|
|
--skoda-licht: #f2d16b; /* eingeschaltetes Licht */
|
|
--skoda-laden: #4caf7d; /* Laden, gesunder Ladestand */
|
|
--skoda-laden-rgb: 76, 175, 125;
|
|
--skoda-niedrig: #e06060; /* Ladestand unter 15 Prozent */
|
|
--skoda-ruhe: #7aa7c7; /* Ladestand ohne Ladung */
|
|
--skoda-ruhe-rgb: 122, 167, 199;
|
|
--skoda-pv: #f0b429; /* Strom aus der eigenen Anlage */
|
|
--skoda-netz: #7a8791; /* Strom aus dem Netz */
|
|
--skoda-blech: 128, 138, 148; /* alles Unbeteiligte am Fahrzeug */
|
|
}
|
|
|
|
/* --- Reiter --------------------------------------------------------------
|
|
Eine Bauart fuer die ganze Seite: Einstellungen, Raum-Modal, Automatiken.
|
|
Gebaut werden sie von restricted/reiter.php, umgeschaltet von Bootstrap.
|
|
|
|
Statt der Ordnerlaschen von Bootstrap eine Unterstreichung: die Laschen
|
|
brauchen einen Rahmen um die Flaeche darunter, damit sie nicht in der Luft
|
|
haengen - und der Rahmen ist genau das, was diese Oberflaeche sonst
|
|
nirgends hat. Der aktive Reiter traegt die Akzentfarbe.
|
|
|
|
Jede Regel nennt .nav-tabs UND .reiter, obwohl .reiter allein die Leiste
|
|
schon trifft. Das ist noetig, nicht schmueckend: adminlte.min.css wird nach
|
|
dieser Datei geladen und bringt eigene Regeln fuer .nav-tabs .nav-link mit.
|
|
Bei gleicher Spezifitaet gewaenne die spaetere - der aktive Reiter waere
|
|
weiss statt bernstein. */
|
|
.nav-tabs.reiter {
|
|
border-bottom: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
|
gap: .1rem;
|
|
}
|
|
.nav-tabs.reiter .nav-link {
|
|
border: 0;
|
|
border-bottom: 2px solid transparent;
|
|
border-radius: .35rem .35rem 0 0;
|
|
padding: .45rem .9rem;
|
|
color: var(--ton-schrift-2, #9aa6ad);
|
|
background: transparent;
|
|
transition: color .18s, background .18s, border-color .18s;
|
|
}
|
|
@media (hover: hover) {
|
|
.nav-tabs.reiter .nav-link:hover {
|
|
background: rgba(138, 148, 158, .08);
|
|
color: var(--ton-schrift, #e8ede9);
|
|
border-bottom-color: var(--ton-linie-satt, rgba(138, 148, 158, .38));
|
|
}
|
|
}
|
|
.nav-tabs.reiter .nav-link.active {
|
|
background: transparent;
|
|
color: var(--ton-sonne, #f0b429);
|
|
border-bottom-color: var(--ton-sonne, #f0b429);
|
|
}
|
|
.nav-tabs.reiter .nav-link:focus-visible {
|
|
outline: 2px solid var(--ton-sonne, #f0b429);
|
|
outline-offset: -2px;
|
|
}
|
|
.nav-tabs.reiter .nav-link i { margin-right: .5rem; }
|
|
|
|
/* Schmale Fassung fuer enge Stellen (Raum-Modal): kleinere Reiter, die
|
|
waagerecht scrollen statt umzubrechen - eine Zeile bleibt eine Zeile. */
|
|
.nav-tabs.reiter-schmal {
|
|
flex-wrap: nowrap;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
scrollbar-width: none;
|
|
}
|
|
.nav-tabs.reiter-schmal::-webkit-scrollbar { display: none; }
|
|
.nav-tabs.reiter-schmal .nav-link {
|
|
padding: .3rem .7rem;
|
|
font-size: .8rem;
|
|
white-space: nowrap;
|
|
}
|
|
.nav-tabs.reiter-schmal .nav-link i { margin-right: .3rem; }
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.nav-tabs.reiter .nav-link { transition: none; }
|
|
}
|
|
|
|
/* --- Aufbau der Fahrzeugkachel -------------------------------------------
|
|
Links das Bild, rechts die Zahlen dazu. Die Kachel bricht um, sobald die
|
|
Zahlenspalte unter 24rem faellt; das Bild behaelt dann seine Breite und
|
|
rueckt in die Mitte. Die drei Bloecke rechts verteilen sich ueber die Hoehe
|
|
des Bildes, damit die Kachel unten nicht ausfranst. */
|
|
.skoda-fahrzeug {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
gap: clamp(1rem, 3vw, 2.5rem);
|
|
align-items: stretch;
|
|
}
|
|
.skoda-bild {
|
|
flex: 0 0 auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
/* Die Zahlenspalte laeuft nicht ueber die ganze Breite mit: ein Balken von
|
|
einem Meter Laenge teilt nicht besser als einer von dreissig Zentimetern.
|
|
Auf sehr breiten Schirmen steht die Kachel deshalb mittig statt gedehnt. */
|
|
/* Mittig statt oben buendig: ohne Ladung faellt der Ladestrombalken weg, und
|
|
die uebrigen Bloecke sollen sich dann gleichmaessig neben dem Fahrzeug
|
|
verteilen statt eine Luecke in der Mitte zu lassen. */
|
|
.skoda-daten {
|
|
flex: 1 1 24rem;
|
|
max-width: 48rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
gap: 1.5rem;
|
|
}
|
|
|
|
/* Kleine Beschriftung ueber einem Block oder einer Zahl. Einmal beschrieben,
|
|
von Kennzahlen, Ladestrom und Zustandszeile gemeinsam benutzt. */
|
|
.skoda-marke,
|
|
.kennzahl .k,
|
|
.skoda-fahrleistung .posten .k {
|
|
font-size: .7rem;
|
|
letter-spacing: .09em;
|
|
text-transform: uppercase;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
}
|
|
|
|
/* --- Fahrzeug in Draufsicht ----------------------------------------------
|
|
Massstaeblich: 4648 x 1877 mm ergeben das Seitenverhaeltnis 2,48:1, der
|
|
Radstand von 2765 mm die Lage der Raeder. */
|
|
.skoda-auto {
|
|
width: 100%;
|
|
max-width: 297px; /* 294,4 Einheiten viewBox, eine Einheit ein Bildpunkt */
|
|
height: auto;
|
|
}
|
|
|
|
.skoda-auto .karosserie {
|
|
fill: rgba(var(--skoda-blech), 0.17);
|
|
stroke: rgba(var(--skoda-blech), 0.55);
|
|
stroke-width: 2;
|
|
}
|
|
|
|
/* --- Strasse ------------------------------------------------------------
|
|
Sichtbar nur waehrend der Fahrt, und sie traegt die eigentliche Bewegung.
|
|
|
|
Die Masse stehen im SVG: Leitlinie 6 m Strich auf 12 m Luecke, rechts
|
|
durchgezogen, das Ganze im Viertel des Fahrzeugmassstabs. Hier bleibt die
|
|
Bewegung: eine Umdrehung ist eine Strich-Lueckenlaenge (472,5 Einheiten),
|
|
in 1,08 s - das sind 437 Einheiten je Sekunde und in diesem Massstab gut
|
|
60 km/h. Der Takt der vorbeiziehenden Striche bleibt damit derselbe wie
|
|
zuvor, die Bewegung selbst ist ruhiger.
|
|
|
|
Nur die Leitlinie laeuft. Die durchgezogene Linie hat nichts, woran man
|
|
Bewegung saehe - genau wie in echt. */
|
|
.skoda-auto .strasse { display: none; }
|
|
.skoda-auto.faehrt .strasse { display: block; }
|
|
|
|
.skoda-auto .strasse .belag {
|
|
fill: rgba(8, 10, 12, 0.35);
|
|
}
|
|
|
|
.skoda-auto .strasse line {
|
|
stroke: rgba(232, 237, 233, 0.5);
|
|
stroke-width: 4.2; /* etwas breiter als massstaeblich (3,15), damit
|
|
sich die Markierung vom Fahrtwind abhebt */
|
|
}
|
|
|
|
.skoda-auto .strasse .leitlinie {
|
|
stroke-dasharray: 157.5 315; /* 6 m Strich, 12 m Luecke, geviertelt */
|
|
animation: skoda-leitlinie 1.08s linear infinite;
|
|
}
|
|
|
|
@keyframes skoda-leitlinie {
|
|
from { transform: translateY(0); }
|
|
to { transform: translateY(472.5px); }
|
|
}
|
|
|
|
/* --- Bananenschale ------------------------------------------------------
|
|
Der Ostergruss. Ausgeloest wird er selten und nur waehrend der Fahrt (siehe
|
|
bananeVielleicht() in js/solar/skodaMQTT.js); hier steht, wie er aussieht.
|
|
|
|
Zwei Bewegungen greifen ineinander: die Schale laeuft mit der Strasse mit,
|
|
und wenn sie unter der Vorderachse ist, kommt der Wagen ins Schleudern. Der
|
|
Vorlauf der zweiten Bewegung ist deshalb kein Gefuehl, sondern gerechnet:
|
|
die Schale startet 40 Einheiten ueber dem Bild, die Vorderachse liegt bei
|
|
97, macht 137 Einheiten - bei 437 Einheiten je Sekunde sind das 0,31 s.
|
|
|
|
Der Wagen dreht sich um seinen Schwerpunkt, nicht um die Bildmitte; ohne
|
|
transform-box: view-box bezoege sich transform-origin auf den Rahmen der
|
|
Gruppe und der Bogen saehe falsch aus. */
|
|
.skoda-auto .bananenschale { display: none; }
|
|
.skoda-auto.banane .bananenschale {
|
|
display: block;
|
|
animation: skoda-schale 1.5s linear;
|
|
}
|
|
.skoda-auto .bananenschale use {
|
|
fill: #e8c74a;
|
|
stroke: rgba(120, 92, 12, 0.75);
|
|
stroke-width: 0.8;
|
|
}
|
|
.skoda-auto .bananenschale .strunk { fill: #b8912c; }
|
|
|
|
.skoda-auto.banane #wagen {
|
|
transform-box: view-box;
|
|
transform-origin: 112px 250px;
|
|
animation: skoda-schleudern 1.2s 0.31s ease-in-out;
|
|
}
|
|
|
|
@keyframes skoda-schale {
|
|
from { transform: translateY(-40px); }
|
|
to { transform: translateY(560px); }
|
|
}
|
|
|
|
/* Erst ein Ausbrechen nach rechts, dann das Gegenlenken, dann austrudeln -
|
|
in dieser Reihenfolge faengt sich ein Fahrzeug wieder. */
|
|
@keyframes skoda-schleudern {
|
|
0% { transform: rotate(0deg) translateX(0); }
|
|
18% { transform: rotate(4.5deg) translateX(5px); }
|
|
45% { transform: rotate(-3.5deg) translateX(-4px); }
|
|
70% { transform: rotate(1.8deg) translateX(2px); }
|
|
88% { transform: rotate(-0.7deg) translateX(-1px); }
|
|
100% { transform: rotate(0deg) translateX(0); }
|
|
}
|
|
|
|
/* --- Fahrtwind ----------------------------------------------------------
|
|
Vier Streifen neben dem Wagen, die von vorn nach hinten laufen. Sichtbar
|
|
nur, solange zeichneFahrt() dem SVG die Klasse "faehrt" gibt.
|
|
|
|
Die Laenge der Streifen steckt im Markup (y1/y2), die Bewegung hier: jede
|
|
Spur laeuft in eigenem Takt und mit eigenem Vorlauf ueber das Bild, sonst
|
|
marschieren die vier im Gleichschritt und es sieht nach Zebrastreifen aus
|
|
statt nach Fahrt. Der Weg reicht von weit oberhalb bis weit unterhalb der
|
|
viewBox (-8 bis 508), damit kein Streifen im Bild entsteht oder endet. */
|
|
.skoda-auto .fahrtwind { display: none; }
|
|
.skoda-auto.faehrt .fahrtwind { display: block; }
|
|
/* Die Streifen ueber dem Wagen liegen ueber den beiden Knoepfen; sie duerfen
|
|
deren Beruehrungen nicht abfangen. */
|
|
.skoda-auto .fahrtwind-oben { pointer-events: none; }
|
|
|
|
.skoda-auto .fahrtwind line {
|
|
stroke: rgba(var(--skoda-blech), 0.75);
|
|
stroke-width: 2.5;
|
|
stroke-linecap: round;
|
|
animation: skoda-fahrtwind 1.1s linear infinite;
|
|
}
|
|
/* Vier Spuren, jede mit eigenem Takt und Vorlauf. Sie laufen so schnell wie
|
|
die Strasse darunter - ein Streifen, der die Fahrbahnmarkierung ueberholt,
|
|
faellt sofort auf. Mit der Strasse halbiert sich also auch ihr Tempo. */
|
|
.skoda-auto .fahrtwind .b1 { animation-duration: 1.56s; animation-delay: -0.60s; opacity: .5; }
|
|
.skoda-auto .fahrtwind .b6 { animation-duration: 1.72s; animation-delay: -1.10s; opacity: .5; }
|
|
|
|
/* Ueber dem Fahrzeug: heller, duenner, durchsichtiger. Der Wind zieht ueber
|
|
das Blech hinweg - er soll sich darauf legen, nicht hineinschneiden. Die
|
|
Streifen stehen dafuer in einer eigenen Gruppe am Ende des SVG (siehe
|
|
dort); ihre geringe Deckung haelt Ladestand und Umrisse lesbar. */
|
|
.skoda-auto .fahrtwind .ueber {
|
|
stroke: rgba(232, 237, 233, 0.85);
|
|
stroke-width: 2;
|
|
}
|
|
.skoda-auto .fahrtwind .b7 { animation-duration: 1.48s; animation-delay: -0.40s; opacity: .34; }
|
|
.skoda-auto .fahrtwind .b10 { animation-duration: 1.64s; animation-delay: -0.90s; opacity: .34; }
|
|
|
|
@keyframes skoda-fahrtwind {
|
|
from { transform: translateY(0); }
|
|
to { transform: translateY(680px); }
|
|
}
|
|
|
|
/* Wer Bewegung abbestellt hat, bekommt sie nicht - aber auch keine leere
|
|
Stelle: die Streifen stehen dann ruhig neben dem Wagen, und das Abzeichen
|
|
"unterwegs" im Kopf der Kachel sagt es ohnehin in Worten. */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.skoda-auto .fahrtwind line {
|
|
animation: none;
|
|
transform: translateY(250px);
|
|
opacity: .45;
|
|
}
|
|
/* Auch die Leitlinie bleibt stehen - zu sehen ist dann eine Standaufnahme
|
|
statt einer Fahrt, und das Abzeichen "unterwegs" sagt den Rest. */
|
|
.skoda-auto .strasse .leitlinie {
|
|
animation: none;
|
|
}
|
|
/* Der Ostergruss faellt ganz aus: ein schleuderndes Fahrzeug ist genau die
|
|
Art Bewegung, die abbestellt wurde. Ausgeloest wird er hier gar nicht
|
|
erst - das prueft das Skript zusaetzlich. */
|
|
.skoda-auto.banane .bananenschale,
|
|
.skoda-auto.banane #wagen {
|
|
animation: none;
|
|
}
|
|
.skoda-auto.banane .bananenschale { display: none; }
|
|
}
|
|
|
|
/* Die Reifen liegen als unterste Lage unter der ganzen Karosserie (siehe die
|
|
Schichtung in restricted/skoda.php). Sie sind deshalb HELLER als das Blech
|
|
gezeichnet, nicht dunkler: alles, was ueber ihnen liegt, hellt sie auf, und
|
|
ein fast schwarzer Reifen unter zwei getoenten Flaechen sah aus wie gar kein
|
|
Reifen. Grau statt Gummischwarz - dafuer ueberhaupt zu sehen. */
|
|
.skoda-auto .rad rect {
|
|
fill: rgba(74, 80, 88, 0.85);
|
|
/* Der Umriss traegt den Reifen, nicht die Fuellung: unter der Motorhaube
|
|
liegen zwei getoente Flaechen uebereinander, und die schlucken jeden
|
|
Fuellton. Eine helle Kontur kommt dagegen durch - dieselbe Sprache wie
|
|
bei der Akkuplatte, die auch nur als Umriss durch den Boden scheint. */
|
|
stroke: rgba(150, 162, 174, 0.55);
|
|
stroke-width: 1.6;
|
|
}
|
|
.skoda-auto .spiegel rect { fill: rgba(var(--skoda-blech), 0.55); }
|
|
/* Die Kupplung ist schwarz und bleibt es: sie steht hinten heraus und liegt
|
|
dort auf dem Hintergrund, nicht unter dem Blech - sie braucht die
|
|
Aufhellung der Reifen also nicht. */
|
|
.skoda-auto .kupplung rect,
|
|
.skoda-auto .kupplung circle { fill: rgba(10, 12, 14, 0.95); }
|
|
/* Dachspoiler und Reling sind an diesem Fahrzeug schwarz, nicht lackiert -
|
|
und nur dadurch heben sie sich vom Dach ab, auf dem sie liegen. Vorher
|
|
hatten sie den Ton des Blechs und verschwanden darin. */
|
|
.skoda-auto .spoiler { fill: rgba(26, 29, 33, 0.85); }
|
|
|
|
/* Dachreling als Linie mit runden Enden - eine Strichstaerke beschreibt sie
|
|
vollstaendig, und die Enden runden sich von selbst. */
|
|
.skoda-auto .reling line {
|
|
stroke: rgba(26, 29, 33, 0.85);
|
|
stroke-width: 6;
|
|
stroke-linecap: round;
|
|
}
|
|
.skoda-auto .sicke {
|
|
fill: none;
|
|
stroke: rgba(var(--skoda-blech), 0.35);
|
|
stroke-width: 1.5;
|
|
}
|
|
|
|
/* Das Tech-Deck Face: beim Enyaq eine glaenzend schwarze Blende ueber die
|
|
volle Bugbreite. Von oben sieht man ihre Oberkante. */
|
|
/* Die Blende ist glaenzendes Schwarz, aber nicht das dunkelste im Bild: mit
|
|
voller Deckung sprang sie nach vorn und las sich wie ein Loch statt wie eine
|
|
Flaeche. Etwas durchscheinend und mit ruhiger Kante bleibt sie das, was sie
|
|
ist - eine Blende auf dem Blech. */
|
|
.skoda-auto .techdeck {
|
|
fill: rgba(20, 24, 30, 0.66);
|
|
stroke: rgba(var(--skoda-blech), 0.3);
|
|
stroke-width: 1;
|
|
}
|
|
|
|
.skoda-auto .scheibe,
|
|
.skoda-auto .dach {
|
|
fill: rgba(var(--skoda-blech), 0.28);
|
|
stroke: rgba(var(--skoda-blech), 0.45);
|
|
stroke-width: 1.5;
|
|
}
|
|
|
|
/* Grundzustand aller schaltbaren Teile: geschlossen und unauffaellig. */
|
|
.skoda-auto .teil > *,
|
|
.skoda-auto .teil > g > * {
|
|
fill: rgba(var(--skoda-blech), 0.34);
|
|
stroke: rgba(var(--skoda-blech), 0.6);
|
|
stroke-width: 1.5;
|
|
transition: fill .25s, stroke .25s, filter .25s;
|
|
}
|
|
|
|
.skoda-auto .teil-fenster > rect { fill: rgba(var(--skoda-blech), 0.5); }
|
|
|
|
/* Die Heckscheibe liegt in der Heckklappe - sie geht mit ihr auf, also ist
|
|
sie kein eigenes Teil. Aussehen soll sie trotzdem wie Glas und nicht wie
|
|
Blech; die Regel steht nach der allgemeinen und gewinnt damit. */
|
|
.skoda-auto .teil > .scheibe {
|
|
fill: rgba(var(--skoda-blech), 0.28);
|
|
stroke: rgba(var(--skoda-blech), 0.45);
|
|
}
|
|
/* Steht die Klappe offen, faerbt sich auch ihre Scheibe - nur durchsichtiger
|
|
als das Blech, sonst waere das Glas ploetzlich das Kraeftigste am Heck.
|
|
Der Rahmen kommt aus der allgemeinen Regel und ist damit derselbe. */
|
|
.skoda-auto .teil.offen > .scheibe { fill: rgba(224, 144, 79, 0.42); }
|
|
|
|
/* --- Antriebsbatterie ----------------------------------------------------
|
|
Die Platte im Fahrzeugboden ist die Ladestandsanzeige der Seite. Welche
|
|
Farbe sie traegt, steht in einer einzigen Variablen: die Zustandsklasse am
|
|
<svg> setzt --akku-farbe, und Huelle, Fuellung, Pegelkante, Stroemung und
|
|
Verlauf lesen sie von dort. Ein weiterer Zustand ist damit eine Zeile und
|
|
keine Suche durch die Datei. */
|
|
.skoda-auto { --akku-farbe: var(--skoda-ruhe); }
|
|
.skoda-auto.akku-laedt { --akku-farbe: var(--skoda-laden); }
|
|
.skoda-auto.akku-niedrig { --akku-farbe: var(--skoda-niedrig); }
|
|
.skoda-auto.akku-unbekannt { --akku-farbe: rgb(var(--skoda-blech)); }
|
|
|
|
/* Der Farbverlauf steht in <defs> und damit ausserhalb der Akkugruppe -
|
|
deshalb haengt --akku-farbe am <svg> und nicht an .akku. */
|
|
.skoda-auto #akkuVerlauf stop { stop-color: var(--akku-farbe); }
|
|
|
|
.skoda-auto .akku .huelle {
|
|
fill: rgba(8, 10, 12, .35);
|
|
stroke: var(--akku-farbe);
|
|
stroke-opacity: .55;
|
|
stroke-width: 1.5;
|
|
}
|
|
.skoda-auto .akku .fuellung {
|
|
fill: url(#akkuVerlauf);
|
|
stroke: none;
|
|
transition: y .8s ease, height .8s ease;
|
|
}
|
|
|
|
/* Die helle Kante auf der Fuellung. Sie macht den Stand auch dort ablesbar,
|
|
wo die getoente Flaeche darunter kaum auffaellt. */
|
|
.skoda-auto .akku .kante {
|
|
fill: var(--akku-farbe);
|
|
transition: y .8s ease;
|
|
}
|
|
.skoda-auto.akku-laedt .akku .kante {
|
|
filter: drop-shadow(0 0 5px var(--akku-farbe));
|
|
}
|
|
|
|
/* Modulfugen. Sie liegen auf 20, 40, 60 und 80 Prozent und sind damit
|
|
zugleich die Skala, an der sich der Stand ablesen laesst. */
|
|
.skoda-auto .akku .fugen line {
|
|
stroke: rgba(var(--skoda-blech), 0.4);
|
|
stroke-width: 1;
|
|
stroke-dasharray: 3 4;
|
|
}
|
|
|
|
/* Ladestrom: Streifen, die im gefuellten Teil nach vorn wandern. Der Schnitt
|
|
auf den Pegel kommt aus #akkuPegel, das zeichneAkku() mitfuehrt. */
|
|
.skoda-auto .akku .stroemung { opacity: 0; transition: opacity .4s; }
|
|
.skoda-auto .akku .stroemung rect { fill: var(--akku-farbe); }
|
|
.skoda-auto.akku-laedt .akku .stroemung { opacity: .4; }
|
|
.skoda-auto.akku-laedt .akku .stroemung .bahn {
|
|
animation: akkuStroemung 2.4s linear infinite;
|
|
}
|
|
@keyframes akkuStroemung {
|
|
from { transform: translateY(0); }
|
|
to { transform: translateY(-54px); } /* genau ein Streifenabstand */
|
|
}
|
|
|
|
/* Zielmarke. Sie wird als Ganzes verschoben, damit Linie und Beschriftung
|
|
zusammenbleiben und der Weg dorthin weich laeuft. */
|
|
.skoda-auto .akku .zielmarke { transition: transform .8s ease; }
|
|
.skoda-auto .akku .zielmarke line {
|
|
stroke: var(--bs-body-color, #e8ede9);
|
|
stroke-width: 1.5;
|
|
stroke-dasharray: 5 3;
|
|
opacity: .6;
|
|
}
|
|
.skoda-auto .akku .zielmarke text {
|
|
fill: var(--bs-body-color, #e8ede9);
|
|
font-size: 10px;
|
|
font-weight: 500;
|
|
text-anchor: end;
|
|
opacity: .8;
|
|
}
|
|
|
|
/* Zahlen in der Platte. Der dunkle Umriss liegt hinter der Fuellung der
|
|
Zeichen (paint-order), damit sie ueber geladenem wie leerem Teil der
|
|
Platte gleich gut lesbar bleiben. */
|
|
.skoda-auto .akku text {
|
|
paint-order: stroke;
|
|
stroke: rgba(8, 10, 12, .7);
|
|
stroke-linejoin: round;
|
|
stroke-width: 2.5;
|
|
}
|
|
.skoda-auto .akku .wert {
|
|
fill: var(--bs-body-color, #e8ede9);
|
|
font-size: 40px;
|
|
font-weight: 600;
|
|
text-anchor: middle;
|
|
font-variant-numeric: tabular-nums;
|
|
stroke-width: 4;
|
|
}
|
|
.skoda-auto .akku .wert .einheit {
|
|
font-size: 17px;
|
|
font-weight: 500;
|
|
opacity: .65;
|
|
}
|
|
.skoda-auto .akku .neben {
|
|
fill: var(--bs-body-color, #e8ede9);
|
|
fill-opacity: .8;
|
|
font-size: 14px;
|
|
text-anchor: middle;
|
|
}
|
|
|
|
/* Der Weg des Ladestroms vom Anschluss in die Platte. Die Striche laufen in
|
|
Fahrtrichtung des Stroms, also zum Akku hin. */
|
|
.skoda-auto .ladefluss {
|
|
fill: none;
|
|
stroke: var(--skoda-laden);
|
|
stroke-width: 2.5;
|
|
stroke-linecap: round;
|
|
stroke-dasharray: 3 7;
|
|
opacity: 0;
|
|
transition: opacity .3s;
|
|
}
|
|
.skoda-auto.akku-laedt .ladefluss {
|
|
opacity: .95;
|
|
animation: akkuFluss 1s linear infinite;
|
|
}
|
|
@keyframes akkuFluss {
|
|
from { stroke-dashoffset: 20; }
|
|
to { stroke-dashoffset: 0; }
|
|
}
|
|
|
|
/* Offen: bernstein und leicht leuchtend. Die Farbe allein traegt die Aussage
|
|
nicht - die Zeile unter dem Bild benennt jedes offene Teil zusaetzlich. */
|
|
.skoda-auto .teil.offen > *,
|
|
.skoda-auto .teil.offen > g > * {
|
|
fill: var(--skoda-offen);
|
|
stroke: var(--skoda-offen);
|
|
filter: drop-shadow(0 0 6px rgba(224, 144, 79, 0.65));
|
|
}
|
|
|
|
/* Licht: vorn die vier LED-Elemente je Seite, hinten das Leuchtenband. */
|
|
.skoda-auto .teil-licht.an > rect {
|
|
fill: var(--skoda-licht);
|
|
stroke: var(--skoda-licht);
|
|
filter: drop-shadow(0 0 8px rgba(242, 209, 107, 0.75));
|
|
}
|
|
.skoda-auto .teil-licht.an > rect.rueck {
|
|
fill: #e06060;
|
|
stroke: #e06060;
|
|
filter: drop-shadow(0 0 8px rgba(224, 96, 96, 0.7));
|
|
}
|
|
|
|
/* Ladeanschluss. Er ist gebaut wie der Klimaknopf; den Ladezustand traegt
|
|
nicht die Form, sondern die Farbe: blau wie jeder Knopf, gruen solange
|
|
geladen wird, dazu das Pulsen als Schein um die Scheibe. Die Scheibe selbst
|
|
bleibt deckend - gruen ausgefuellt verschluckte sie den Blitz. */
|
|
.skoda-auto .teil-stecker .glyphe { stroke-width: 2.2; }
|
|
.skoda-auto .teil-stecker.laedt .ring,
|
|
.skoda-auto .teil-stecker.laedt .flaeche { stroke: var(--skoda-laden); }
|
|
.skoda-auto .teil-stecker.laedt .glyphe { stroke: var(--skoda-laden); }
|
|
.skoda-auto .teil-stecker.laedt .flaeche {
|
|
animation: skodaPuls 1.8s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes skodaPuls {
|
|
0%, 100% { filter: drop-shadow(0 0 3px rgba(76, 175, 125, 0.5)); }
|
|
50% { filter: drop-shadow(0 0 12px rgba(76, 175, 125, 0.95)); }
|
|
}
|
|
|
|
/* Hervorheben, wenn der zugehoerige Eintrag darunter beruehrt wird - und
|
|
umgekehrt. Sichtbarer Fokus, damit das auch mit der Tastatur geht. */
|
|
.skoda-auto .teil.hervor > *,
|
|
.skoda-auto .teil.hervor > g > * {
|
|
stroke: var(--bs-primary, #0d6efd);
|
|
stroke-width: 2.5;
|
|
}
|
|
@media (hover: hover) {
|
|
.skoda-auto .teil:hover > *,
|
|
.skoda-auto .teil > g:hover > * {
|
|
stroke: var(--bs-primary, #0d6efd);
|
|
stroke-width: 2.5;
|
|
}
|
|
}
|
|
.skoda-auto .teil:focus,
|
|
.skoda-auto .teil > g:focus { outline: none; }
|
|
.skoda-auto .teil:focus-visible > *,
|
|
.skoda-auto .teil > g:focus-visible > * {
|
|
stroke: var(--bs-primary, #0d6efd);
|
|
stroke-width: 3;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.skoda-auto .teil > *,
|
|
.skoda-auto .teil > g > * { transition: none; }
|
|
.skoda-auto .teil-stecker.laedt .flaeche { animation: none; }
|
|
/* Der Ladestand bleibt sichtbar, nur nicht mehr in Bewegung. */
|
|
.skoda-auto .akku .fuellung,
|
|
.skoda-auto .akku .kante,
|
|
.skoda-auto .akku .zielmarke { transition: none; }
|
|
.skoda-auto.akku-laedt .akku .stroemung .bahn,
|
|
.skoda-auto.akku-laedt .ladefluss,
|
|
.skoda-auto.klima-laeuft .steuer .luefter .blaetter { animation: none; }
|
|
}
|
|
|
|
/* --- Zustandszeile unter dem Fahrzeug ------------------------------------ */
|
|
.skoda-teile {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: .35rem;
|
|
justify-content: flex-start;
|
|
margin-top: .45rem;
|
|
}
|
|
.skoda-teile .chip {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .35rem;
|
|
font-size: .78rem;
|
|
padding: .2rem .55rem;
|
|
border-radius: 1rem;
|
|
border: 1px solid var(--bs-border-color, rgba(128, 128, 128, .35));
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
cursor: default;
|
|
white-space: nowrap;
|
|
}
|
|
/* Ein Punkt vor dem Wort traegt dieselbe Aussage wie die Farbe im Bild und
|
|
macht die Zeile auf einen Blick ueberfliegbar. */
|
|
.skoda-teile .chip::before {
|
|
content: "";
|
|
width: .45rem;
|
|
height: .45rem;
|
|
border-radius: 50%;
|
|
background: rgba(var(--skoda-blech), .75);
|
|
flex: 0 0 auto;
|
|
}
|
|
.skoda-teile .chip.offen { border-color: var(--skoda-offen); color: var(--skoda-offen); }
|
|
.skoda-teile .chip.offen::before { background: var(--skoda-offen); }
|
|
.skoda-teile .chip.an::before { background: var(--skoda-licht); }
|
|
.skoda-teile .chip.hervor {
|
|
border-color: var(--bs-primary, #0d6efd);
|
|
color: var(--bs-body-color, #e8ede9);
|
|
}
|
|
|
|
/* Auf Beruehrungsgeraeten sind die Ziele zu klein: eine Fingerkuppe deckt
|
|
rund 9 mm ab, die Chips waren keine 6 mm hoch. Gleiches gilt fuer die
|
|
Fahrtzeilen und den Umschalter. */
|
|
@media (pointer: coarse) {
|
|
.skoda-teile { gap: .5rem; }
|
|
.skoda-teile .chip {
|
|
font-size: .85rem;
|
|
padding: .45rem .8rem;
|
|
cursor: pointer;
|
|
}
|
|
.skoda-liste .zeile { padding: .75rem .9rem; }
|
|
.skoda-umschalter button { font-size: .85rem; padding: .5rem .9rem; }
|
|
}
|
|
.skoda-teile .chip.an { border-color: var(--skoda-licht); color: var(--skoda-licht); }
|
|
|
|
/* --- Kennzahlen neben dem Fahrzeug ---------------------------------------
|
|
Was sich nicht ins Bild zeichnen laesst, steht in gleich gebauten Kacheln:
|
|
Zeichen, Bezeichnung, Wert und bei Bedarf eine Nebenzeile. Eine Kachel
|
|
bekommt die Klasse .aktiv, solange ihre Zahl gerade etwas aussagt - die
|
|
Ladeleistung waehrend des Ladens, das Klima, solange es laeuft. Welche
|
|
Farbe die Hervorhebung traegt, steht in --kennzahl-rgb. */
|
|
.skoda-kennzahlen {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
|
|
gap: .75rem;
|
|
}
|
|
.kennzahl {
|
|
--kennzahl-rgb: var(--skoda-laden-rgb);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .75rem;
|
|
padding: .7rem .85rem;
|
|
border: 1px solid var(--bs-border-color, rgba(128, 128, 128, .25));
|
|
border-radius: .7rem;
|
|
background: rgba(var(--skoda-blech), .07);
|
|
transition: border-color .3s, background .3s;
|
|
}
|
|
.kennzahl .zeichen {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: 0 0 auto;
|
|
width: 2.1rem;
|
|
height: 2.1rem;
|
|
border-radius: 50%;
|
|
background: rgba(var(--skoda-blech), .16);
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
transition: background .3s, color .3s;
|
|
}
|
|
.kennzahl .text { display: flex; flex-direction: column; min-width: 0; }
|
|
.kennzahl .v {
|
|
font-size: 1.2rem;
|
|
line-height: 1.3;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.kennzahl .neben {
|
|
font-size: .72rem;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
}
|
|
.kennzahl .neben:empty { display: none; }
|
|
|
|
.kennzahl.aktiv {
|
|
border-color: rgba(var(--kennzahl-rgb), .5);
|
|
background: rgba(var(--kennzahl-rgb), .1);
|
|
}
|
|
.kennzahl.aktiv .zeichen {
|
|
background: rgba(var(--kennzahl-rgb), .2);
|
|
color: rgb(var(--kennzahl-rgb));
|
|
}
|
|
#skodaKachelKlima { --kennzahl-rgb: var(--skoda-ruhe-rgb); }
|
|
|
|
/* --- Fahrleistung --------------------------------------------------------
|
|
Drei Zahlen nebeneinander, durch einen Strich getrennt. Kein Kasten und
|
|
keine Kachel: es ist eine Nebenauskunft, kein Messwert des Augenblicks.
|
|
Ein Wert, dessen Zeitraum weiter zurueckreicht als die Aufzeichnung, wird
|
|
gestrichelt unterstrichen und nennt im Titel, seit wann gemessen wird. */
|
|
.skoda-fahrleistung .reihe {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: .35rem 1.4rem;
|
|
margin-top: .5rem;
|
|
}
|
|
.skoda-fahrleistung .posten {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 5.5rem;
|
|
}
|
|
.skoda-fahrleistung .posten + .posten {
|
|
border-left: 1px solid var(--bs-border-color, rgba(128, 128, 128, .25));
|
|
padding-left: 1.4rem;
|
|
}
|
|
/* Auf dem Handy zaehlt jeder Millimeter: die Trennstriche weichen, damit die
|
|
drei Zahlen in einer Zeile bleiben statt in zwei umzubrechen. */
|
|
@media (max-width: 30rem) {
|
|
.skoda-fahrleistung .reihe { gap: .3rem .9rem; }
|
|
.skoda-fahrleistung .posten { min-width: 0; }
|
|
.skoda-fahrleistung .posten + .posten { border-left: none; padding-left: 0; }
|
|
}
|
|
|
|
.skoda-fahrleistung .posten .v {
|
|
font-size: 1.15rem;
|
|
line-height: 1.3;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
/* --- Erklärungen ---------------------------------------------------------
|
|
Ein Element mit Erklärung traegt ein Info-Zeichen. Das ist der einzige
|
|
Hinweis darauf, dass es dort etwas zu lesen gibt - am Zeiger genuegte das
|
|
Ueberfahren, am Finger gibt es das nicht. Angetippt oder ueberfahren oeffnet
|
|
setzeHinweis() ein Popover; das Zeichen sagt vorher, dass sich das lohnt. */
|
|
/* Kein Textmarkieren beim Antippen: der Finger trifft Text, gemeint ist der
|
|
Auslöser - eine blau markierte Zahl waere die falsche Antwort darauf. */
|
|
.hat-hinweis {
|
|
cursor: help;
|
|
-webkit-user-select: none;
|
|
user-select: none;
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
.skoda-fahrleistung .posten.hat-hinweis .v::after,
|
|
#skodaVerbrauchBasis.hat-hinweis::after {
|
|
content: "\f431"; /* bi-info-circle */
|
|
font-family: bootstrap-icons;
|
|
font-size: .78em;
|
|
margin-left: .3em;
|
|
opacity: .65;
|
|
vertical-align: .05em;
|
|
}
|
|
.hat-hinweis:focus { outline: none; }
|
|
.hat-hinweis:focus-visible {
|
|
outline: 2px solid var(--bs-primary, #4b8fd6);
|
|
outline-offset: 3px;
|
|
border-radius: .2rem;
|
|
}
|
|
|
|
/* Das Fenster selbst: dunkel wie die Kacheln, schmal genug zum Lesen. Auf dem
|
|
Handy darf es die halbe Breite einnehmen, mehr nicht. */
|
|
.skoda-erklaerung {
|
|
--bs-popover-max-width: 22rem;
|
|
--bs-popover-bg: #23282c;
|
|
--bs-popover-border-color: rgba(128, 138, 148, .35);
|
|
--bs-popover-body-color: var(--bs-body-color, #e8ede9);
|
|
--bs-popover-body-padding-x: .8rem;
|
|
--bs-popover-body-padding-y: .6rem;
|
|
--bs-popover-font-size: .82rem;
|
|
box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .45);
|
|
}
|
|
|
|
/* --- Herkunft des Ladestroms ---------------------------------------------
|
|
Der Balken teilt die Ladeleistung in den Anteil aus der eigenen Anlage und
|
|
den Rest aus dem Netz. Die Legende nennt beide Anteile in Zahlen - ein
|
|
Farbstueck allein sagt nicht, wie viel es ist. */
|
|
.skoda-quelle .kopf {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: baseline;
|
|
gap: .75rem;
|
|
margin-bottom: .4rem;
|
|
}
|
|
.skoda-quelle .summe {
|
|
font-size: .85rem;
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
}
|
|
.skoda-balken {
|
|
display: flex;
|
|
height: .8rem;
|
|
border-radius: .4rem;
|
|
overflow: hidden;
|
|
background: rgba(var(--skoda-blech), 0.2);
|
|
}
|
|
.skoda-balken > div { transition: width .5s ease; }
|
|
.skoda-balken .teil-pv { background: var(--skoda-pv); }
|
|
.skoda-balken .teil-netz { background: var(--skoda-netz); }
|
|
|
|
.skoda-quelle .legende {
|
|
display: flex;
|
|
gap: 1.1rem;
|
|
margin-top: .45rem;
|
|
font-size: .78rem;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
}
|
|
.skoda-quelle .legende span { display: inline-flex; align-items: center; gap: .35rem; }
|
|
.skoda-quelle .legende b {
|
|
color: var(--bs-body-color, #e8ede9);
|
|
font-weight: 600;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.skoda-quelle .legende .pkt { width: .55rem; height: .55rem; border-radius: 50%; }
|
|
.skoda-quelle .legende .pkt.pv { background: var(--skoda-pv); }
|
|
.skoda-quelle .legende .pkt.netz { background: var(--skoda-netz); }
|
|
|
|
/* --- Listen (Ladungen, Fahrten) ------------------------------------------ */
|
|
/* Der Innenabstand oben trennt die erste Zeile von der Ueberschrift. Ohne
|
|
ihn klebt sie am Umschalter, was auf dem Handy besonders auffaellt. */
|
|
.skoda-liste {
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
padding-top: .5rem;
|
|
}
|
|
.skoda-liste .zeile {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: baseline;
|
|
gap: .75rem;
|
|
padding: .5rem .9rem;
|
|
border-top: 1px solid var(--bs-border-color, rgba(128, 128, 128, .25));
|
|
}
|
|
.skoda-liste .zeile:first-child { border-top: none; }
|
|
@media (hover: hover) {
|
|
.skoda-liste .zeile:hover { background: rgba(128, 138, 148, 0.08); }
|
|
}
|
|
.skoda-liste .wann { font-size: .82rem; color: var(--bs-secondary-color, #9aa0a6); }
|
|
.skoda-liste .was { font-size: .95rem; font-variant-numeric: tabular-nums; text-align: right; }
|
|
.skoda-liste .neben { display: block; font-size: .75rem; color: var(--bs-secondary-color, #9aa0a6); }
|
|
.skoda-liste .leer { padding: 1.5rem .9rem; color: var(--bs-secondary-color, #9aa0a6); }
|
|
|
|
/* Umschalter kWh <-> Prozent in der Ueberschrift der Fahrtenliste. Welche
|
|
Einheit sichtbar ist, entscheidet die Klasse auf der Kachel - so bleibt die
|
|
Auswahl bestehen, wenn die Liste neu gebaut wird. */
|
|
.zeigt-kwh .v-prozent,
|
|
.zeigt-prozent .v-kwh,
|
|
.zeigt-prozent #skodaVerbrauchBasis { display: none; }
|
|
|
|
.skoda-umschalter {
|
|
display: inline-flex;
|
|
border: 1px solid var(--bs-border-color, rgba(128, 128, 128, .35));
|
|
border-radius: .3rem;
|
|
overflow: hidden;
|
|
}
|
|
.skoda-umschalter button {
|
|
background: none;
|
|
border: none;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
font-size: .72rem;
|
|
line-height: 1;
|
|
padding: .25rem .5rem;
|
|
cursor: pointer;
|
|
}
|
|
.skoda-umschalter button + button {
|
|
border-left: 1px solid var(--bs-border-color, rgba(128, 128, 128, .35));
|
|
}
|
|
.skoda-umschalter button:hover { background: rgba(128, 138, 148, .12); }
|
|
.skoda-umschalter button.aktiv {
|
|
background: rgba(128, 138, 148, .22);
|
|
color: var(--bs-body-color, #e8ede9);
|
|
}
|
|
.skoda-umschalter button:focus-visible {
|
|
outline: 2px solid var(--bs-primary, #0d6efd);
|
|
outline-offset: -2px;
|
|
}
|
|
|
|
/* Fahrtzeilen, die sich auf der Karte zeigen lassen. Der Zeiger und die
|
|
Markierung sind der einzige Hinweis darauf - ohne den waere die Kopplung
|
|
nicht zu erraten. */
|
|
.skoda-liste .zeile.anklickbar { cursor: pointer; }
|
|
.skoda-liste .zeile.anklickbar:focus-visible {
|
|
outline: 2px solid var(--bs-primary, #0d6efd);
|
|
outline-offset: -2px;
|
|
}
|
|
/* Dieselbe Farbe wie die gewaehlte Linie auf der Karte - die Zuordnung
|
|
zwischen Zeile und Linie soll ohne Nachdenken erkennbar sein. */
|
|
.skoda-liste .zeile.gewaehlt {
|
|
background: rgba(224, 144, 79, 0.14);
|
|
box-shadow: inset 3px 0 0 #e0904f;
|
|
}
|
|
|
|
/* --- Karte (Leaflet) -----------------------------------------------------
|
|
Die Kacheln kommen ueber ajax/tile.php aus dem eigenen Zwischenspeicher.
|
|
OpenStreetMap-Kacheln sind hell; im dunklen Dashboard wuerden sie wie ein
|
|
Scheinwerfer wirken. invert + hue-rotate dreht sie ins Dunkle, ohne einen
|
|
zweiten Anbieter samt eigener Bedingungen ins Spiel zu bringen. Der Filter
|
|
sitzt auf den Kacheln allein - Marker, Linien und Bedienelemente behalten
|
|
ihre Farben. */
|
|
.skoda-karte {
|
|
height: 420px;
|
|
width: 100%;
|
|
border-radius: .4rem;
|
|
background: rgba(128, 138, 148, 0.12);
|
|
z-index: 0; /* sonst legt sich die Karte ueber die Seitenleiste */
|
|
}
|
|
|
|
.skoda-karte .leaflet-tile-pane {
|
|
filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.9);
|
|
}
|
|
|
|
/* Bedienelemente und Sprechblasen an das dunkle Theme angleichen. */
|
|
.skoda-karte .leaflet-bar a,
|
|
.skoda-karte .leaflet-bar a:hover {
|
|
background: #23282c;
|
|
color: var(--bs-body-color, #e8ede9);
|
|
border-bottom-color: #33393e;
|
|
}
|
|
.skoda-karte .leaflet-bar a:hover { background: #2d3338; }
|
|
|
|
.skoda-karte .leaflet-popup-content-wrapper,
|
|
.skoda-karte .leaflet-popup-tip {
|
|
background: #23282c;
|
|
color: var(--bs-body-color, #e8ede9);
|
|
box-shadow: 0 3px 14px rgba(0, 0, 0, .5);
|
|
}
|
|
.skoda-karte .leaflet-popup-content { margin: .6rem .8rem; line-height: 1.5; }
|
|
.skoda-karte .leaflet-popup-close-button { color: var(--bs-secondary-color, #9aa0a6); }
|
|
|
|
/* Die Nennung von OpenStreetMap ist Pflicht und darf nicht versteckt werden -
|
|
nur ruhiger gesetzt, damit sie das Bild nicht dominiert.
|
|
|
|
Ohne Hintergrundkasten, dafuer mit Schattenwurf: ein durchsichtiger
|
|
Hintergrund allein liesse den Text ueber hellen Kartenstellen verschwinden,
|
|
und unlesbar waere so gut wie versteckt. Der Schatten haelt ihn auf jedem
|
|
Untergrund erkennbar, ohne einen Balken ins Bild zu setzen. */
|
|
/* Der doppelte Klassenname ist noetig, nicht Zierde: Leaflet setzt den
|
|
Hintergrund ueber .leaflet-container .leaflet-control-attribution, also mit
|
|
derselben Spezifitaet wie ein einfaches .skoda-karte davor - und leaflet.css
|
|
wird spaeter geladen, gewinnt bei Gleichstand also. Der Kartencontainer
|
|
traegt beide Klassen, damit sticht diese Regel. */
|
|
.skoda-karte.leaflet-container .leaflet-control-attribution {
|
|
background: transparent;
|
|
color: #c9d0d6;
|
|
font-size: .68rem;
|
|
padding: 0 .4rem;
|
|
text-shadow: 0 1px 2px rgba(0, 0, 0, .9), 0 0 4px rgba(0, 0, 0, .75);
|
|
}
|
|
.skoda-karte.leaflet-container .leaflet-control-attribution a {
|
|
color: #a9c8f0;
|
|
text-shadow: inherit;
|
|
}
|
|
|
|
.skoda-kartenlegende {
|
|
display: inline-flex;
|
|
gap: .9rem;
|
|
font-size: .75rem;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
}
|
|
.skoda-kartenlegende span { display: inline-flex; align-items: center; gap: .3rem; }
|
|
.skoda-kartenlegende .pkt { width: .55rem; height: .55rem; border-radius: 50%; }
|
|
.skoda-kartenlegende .pkt.jetzt { background: #4caf7d; }
|
|
.skoda-kartenlegende .pkt.halt { background: #8a949c; }
|
|
.skoda-kartenlegende .lin {
|
|
width: 1.1rem;
|
|
border-top: 2px dashed #8a949c;
|
|
}
|
|
|
|
/* --- Befund -------------------------------------------------------------- */
|
|
.skoda-befund .zahl {
|
|
font-size: 2.4rem;
|
|
font-weight: 600;
|
|
line-height: 1.1;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.skoda-befund .zahl .einheit {
|
|
font-size: .95rem;
|
|
font-weight: 400;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
margin-left: .35rem;
|
|
}
|
|
.skoda-befund dl { margin: 1rem 0 0; display: grid; gap: .5rem; }
|
|
.skoda-befund dl > div { display: flex; justify-content: space-between; gap: 1rem; }
|
|
.skoda-befund dt {
|
|
font-weight: 400;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
font-size: .85rem;
|
|
}
|
|
.skoda-befund dd { margin: 0; font-variant-numeric: tabular-nums; font-size: .9rem; }
|
|
|
|
/* --- Steuerung ----------------------------------------------------------
|
|
Die Befehle sitzen im Modal, das ueber die anklickbaren Stellen im
|
|
Fahrzeugbild aufgeht. */
|
|
.skoda-steuerung .knoepfe { display: flex; flex-wrap: wrap; gap: .5rem; }
|
|
.skoda-steuerung .knoepfe button { flex: 1 1 11rem; }
|
|
.skoda-steuerung .temperatur {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: .75rem;
|
|
font-size: .9rem;
|
|
}
|
|
.skoda-steuerung .temperatur span { display: flex; align-items: center; gap: .35rem; }
|
|
.skoda-steuerung .temperatur input { width: 5.5rem; }
|
|
|
|
@media (pointer: coarse) {
|
|
.skoda-steuerung .knoepfe button { padding: .7rem 1rem; }
|
|
}
|
|
|
|
.skoda-rueckmeldung {
|
|
font-size: .9rem;
|
|
padding: .5rem .75rem;
|
|
border-radius: .35rem;
|
|
display: none;
|
|
}
|
|
.skoda-rueckmeldung.warte,
|
|
.skoda-rueckmeldung.gut,
|
|
.skoda-rueckmeldung.schlecht { display: block; }
|
|
.skoda-rueckmeldung.warte { background: rgba(128, 138, 148, .16); color: var(--bs-secondary-color, #9aa0a6); }
|
|
.skoda-rueckmeldung.gut { background: rgba(76, 175, 125, .16); color: #6fd3a0; }
|
|
.skoda-rueckmeldung.schlecht { background: rgba(224, 96, 96, .16); color: #f08a8a; }
|
|
|
|
/* --- Anklickbare Stellen im Fahrzeugbild --------------------------------
|
|
Der Ring unterscheidet Bedienung von Anzeige: die uebrigen Teile zeigen
|
|
nur ihren Zustand, diese beiden aendern etwas. */
|
|
.skoda-auto .steuer { cursor: pointer; }
|
|
.skoda-auto .steuer .ring {
|
|
fill: none;
|
|
stroke: var(--bs-primary, #4b8fd6);
|
|
stroke-width: 1.5;
|
|
stroke-dasharray: 3 3;
|
|
opacity: .55;
|
|
transition: opacity .2s, stroke-width .2s;
|
|
}
|
|
/* Der Knopf sitzt mitten auf der Akkuplatte und muss sich gegen jeden
|
|
Fuellstand behaupten - gegen die dunkle leere Zelle ebenso wie gegen die
|
|
gefuellte. Eine durchscheinende Flaeche kann das nicht: sie nimmt die Farbe
|
|
an, die zufaellig darunter liegt. Deshalb eine eigene, deckende Scheibe. */
|
|
.skoda-auto .steuer .flaeche {
|
|
fill: rgba(10, 13, 17, .92);
|
|
stroke: var(--bs-primary, #4b8fd6);
|
|
stroke-width: 1.5;
|
|
filter: drop-shadow(0 0 3px rgba(0, 0, 0, .55));
|
|
}
|
|
.skoda-auto .steuer .glyphe {
|
|
fill: none;
|
|
stroke: #7db3f0; /* dieselbe Farbe wie die Luefterfluegel */
|
|
stroke-width: 1.8;
|
|
stroke-linecap: round;
|
|
stroke-linejoin: round;
|
|
}
|
|
|
|
/* Luefterrad des Klimaknopfs. Es dreht sich, solange die Klimatisierung
|
|
arbeitet - dasselbe Mittel wie beim Ladeanschluss: der Zustand steht als
|
|
Klasse am <svg>, die Form bleibt, wo sie ist. */
|
|
.skoda-auto .steuer .luefter use { fill: #7db3f0; }
|
|
.skoda-auto .steuer .luefter .nabe { fill: rgba(10, 13, 17, .92); }
|
|
.skoda-auto .steuer .luefter .blaetter { transform-origin: 0 0; }
|
|
.skoda-auto.klima-laeuft .steuer .luefter .blaetter {
|
|
animation: klimaDreht 3.2s linear infinite;
|
|
}
|
|
@keyframes klimaDreht {
|
|
from { transform: rotate(0deg); }
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
@media (hover: hover) {
|
|
.skoda-auto .steuer:hover .ring { opacity: 1; stroke-width: 2.5; }
|
|
}
|
|
.skoda-auto .steuer:focus { outline: none; }
|
|
.skoda-auto .steuer:focus-visible .ring { opacity: 1; stroke-width: 3; }
|
|
|
|
.skoda-hinweis {
|
|
margin: .6rem 0 0;
|
|
font-size: .75rem;
|
|
color: var(--bs-secondary-color, #9aa0a6);
|
|
text-align: center;
|
|
}
|
|
|
|
.skoda-alter { font-size: .85rem; }
|
|
|
|
/* === Einstellungen: Werte auf den Home-Kacheln ===========================
|
|
Eine Zeile je Raum, aufklappbar. Die Zeile zeigt im zugeklappten Zustand
|
|
schon, was auf der Kachel steht - sonst muesste man zwanzig Raeume
|
|
aufklappen, um einen zu finden. */
|
|
|
|
.kachel-etage { margin-bottom: 1.25rem; }
|
|
.kachel-etage:last-child { margin-bottom: 0; }
|
|
.kachel-etage-name {
|
|
font-size: .7rem;
|
|
letter-spacing: .13em;
|
|
text-transform: uppercase;
|
|
color: var(--ton-schrift-3, #6f7a81);
|
|
margin-bottom: .35rem;
|
|
}
|
|
|
|
.kachel-zeile {
|
|
border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
|
border-radius: .5rem;
|
|
margin-bottom: .4rem;
|
|
overflow: hidden;
|
|
}
|
|
.kachel-zeile.offen { border-color: var(--ton-linie-satt, rgba(138, 148, 158, .38)); }
|
|
|
|
.kachel-kopf {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .6rem;
|
|
width: 100%;
|
|
padding: .5rem .75rem;
|
|
background: none;
|
|
border: 0;
|
|
color: inherit;
|
|
font: inherit;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
}
|
|
@media (hover: hover) {
|
|
.kachel-kopf:hover { background: rgba(138, 148, 158, .08); }
|
|
}
|
|
.kachel-kopf .pfeil {
|
|
color: var(--ton-schrift-3, #6f7a81);
|
|
transition: transform .18s;
|
|
flex: 0 0 auto;
|
|
}
|
|
.kachel-zeile.offen .kachel-kopf .pfeil { transform: rotate(90deg); }
|
|
.kachel-kopf .name { min-width: 8rem; }
|
|
.kachel-kopf .werte {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: .3rem;
|
|
flex: 1 1 auto;
|
|
}
|
|
.kachel-chip {
|
|
font-size: .72rem;
|
|
padding: .1rem .45rem;
|
|
border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
|
border-radius: 1rem;
|
|
color: var(--ton-schrift-2, #9aa6ad);
|
|
white-space: nowrap;
|
|
}
|
|
.kachel-chip.leer { font-style: italic; }
|
|
.kachel-chip .bi { margin-right: .3rem; opacity: .8; }
|
|
|
|
.kachel-editor {
|
|
padding: .25rem .75rem .75rem;
|
|
border-top: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
|
}
|
|
|
|
/* Eine Wertzeile. Auf breiten Schirmen nebeneinander, auf dem Handy
|
|
untereinander - die Felder sind zu kurz, um sie zu quetschen. */
|
|
.kachel-wert {
|
|
display: grid;
|
|
grid-template-columns: 7.5rem minmax(10rem, 1fr) 7rem 5.5rem 9.5rem auto;
|
|
gap: .4rem;
|
|
align-items: center;
|
|
padding: .5rem 0;
|
|
border-bottom: 1px dashed var(--ton-linie, rgba(138, 148, 158, .2));
|
|
}
|
|
.kachel-wert:last-of-type { border-bottom: 0; }
|
|
/* Symbolname mit Vorschau davor: die Vorschau sagt, was der Name bedeutet -
|
|
"moisture" allein sagt es nicht. */
|
|
.kachel-wert .kw-symbol {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .35rem;
|
|
}
|
|
.kachel-wert .kw-symbol-schau {
|
|
flex: none;
|
|
width: 1.5rem;
|
|
text-align: center;
|
|
font-size: 1.05rem;
|
|
line-height: 1;
|
|
color: var(--ton-schrift-2, #9aa6ad);
|
|
}
|
|
.kachel-wert .kw-symbol-schau .unbekannt { color: var(--ton-schlecht, #e06060); }
|
|
.kachel-wert .kw-symbol input { min-width: 0; }
|
|
|
|
.kachel-wert .kw-schalter {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .5rem;
|
|
white-space: nowrap;
|
|
}
|
|
.kachel-wert .kw-schalter label {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .25rem;
|
|
font-size: .78rem;
|
|
color: var(--ton-schrift-2, #9aa6ad);
|
|
cursor: pointer;
|
|
}
|
|
|
|
@media (max-width: 991.98px) {
|
|
.kachel-wert {
|
|
grid-template-columns: 1fr 1fr;
|
|
}
|
|
.kachel-wert .kw-topic { grid-column: 1 / -1; }
|
|
}
|
|
|
|
.kachel-fuss {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .75rem;
|
|
margin-top: .75rem;
|
|
}
|
|
|
|
/* === Geraetetafel (Einstellungen) ========================================
|
|
Sechzig Zeilen, in denen die meiste Arbeit an einer Handvoll haengt: den
|
|
Geraeten ohne Raum und denen, die seit Monaten schweigen. Beide sind
|
|
markiert, damit man sie nicht suchen muss - der Rest bleibt ruhig. */
|
|
.geraete-sieb {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .9rem;
|
|
margin-bottom: .75rem;
|
|
}
|
|
.geraete-sieb input[type="search"] { max-width: 22rem; }
|
|
.geraete-sieb .form-check { flex: none; }
|
|
|
|
/* Kein eigener Rollbalken: die Tafel ist so lang, wie sie ist, und die Seite
|
|
scrollt als Ganzes. Ein Kasten mit eigenem Balken in einer Karte, die selbst
|
|
in einer scrollenden Seite steht, ist ein Balken zu viel - man weiss beim
|
|
Wischen nie, welcher der beiden gerade dran ist. */
|
|
.geraete-tafel {
|
|
/* Bewusst ohne Rahmen und ohne overflow: beides machte aus der Tafel
|
|
wieder einen eigenen Scroll-Kasten, und der klebende Tabellenkopf haette
|
|
nichts mehr, woran er kleben kann. */
|
|
margin-bottom: 0;
|
|
}
|
|
/* Der Kopf bleibt trotzdem stehen: er klebt an der Kopfzeile der Seite, denn
|
|
gescrollt wird bei AdminLTE in .app-main, und dort ist oben die Navigation.
|
|
Ab Zeile zwanzig weiss man sonst nicht mehr, welche Spalte der Raum war. */
|
|
.geraete-tafel thead th {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 1;
|
|
background: var(--ton-flaeche-2, #2b3237);
|
|
font-size: .72rem;
|
|
letter-spacing: .08em;
|
|
text-transform: uppercase;
|
|
color: var(--ton-schrift-3, #6f7a81);
|
|
white-space: nowrap;
|
|
border-bottom: 1px solid var(--bs-border-color, #2c3034);
|
|
box-shadow: 0 1px 0 var(--ton-grund, #191d20); /* deckt die Zeile darunter */
|
|
}
|
|
.geraete-tafel td { vertical-align: middle; }
|
|
.geraete-tafel .name { line-height: 1.25; }
|
|
.geraete-tafel .name .neben {
|
|
display: block;
|
|
font-size: .72rem;
|
|
color: var(--ton-schrift-3, #6f7a81);
|
|
}
|
|
.geraete-tafel .raum { min-width: 11rem; }
|
|
.geraete-tafel .raum select { min-width: 9rem; }
|
|
.geraete-tafel .alter { color: var(--ton-schrift-2, #9aa4ab); white-space: nowrap; }
|
|
.geraete-tafel .alter.lange { color: var(--ton-sonne, #f0b429); }
|
|
/* Ohne Raum: eine Kante links statt einer eingefaerbten Zeile - Letzteres
|
|
sieht bei zwanzig offenen Geraeten nach Fehler aus, ist aber nur Arbeit.
|
|
Als ::before und nicht als border, weil Bootstrap Tabellenzellen im
|
|
Hover mit einem inset-Schatten fuellt und den Rand damit ueberdeckt. */
|
|
.geraete-tafel tr.ohne-raum td:first-child { position: relative; }
|
|
.geraete-tafel tr.ohne-raum td:first-child::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0; top: 0; bottom: 0;
|
|
width: 3px;
|
|
background: var(--ton-sonne, #f0b429);
|
|
}
|
|
|
|
/* Der Papierkorb haelt sich zurueck, bis man ihn braucht. */
|
|
.geraete-tafel .geraet-weg {
|
|
color: var(--ton-schrift-3, #6f7a81);
|
|
border-color: transparent;
|
|
line-height: 1;
|
|
}
|
|
.geraete-tafel .geraet-weg:hover:not(:disabled),
|
|
.geraete-tafel .geraet-weg:focus-visible:not(:disabled) {
|
|
color: var(--ton-schlecht, #e06060);
|
|
border-color: var(--ton-schlecht, #e06060);
|
|
}
|
|
.geraete-tafel .geraet-weg:disabled { opacity: .25; }
|
|
|
|
.geraete-fuss {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
gap: .75rem;
|
|
margin-top: .5rem;
|
|
}
|
|
|
|
@media (max-width: 575.98px) {
|
|
.geraete-sieb { flex-wrap: wrap; }
|
|
.geraete-sieb input[type="search"] { max-width: none; }
|
|
}
|
|
|
|
/* === Protokollseite ======================================================
|
|
Ein Log liest sich nur in einer Schrift mit fester Breite: die Zeitstempel
|
|
stehen dann untereinander, und das Auge findet die Stelle, an der etwas
|
|
anders wird. Die Zeilen umbrechen statt seitlich zu scrollen - ein
|
|
Traceback ist lang, und waagerecht zu blaettern verliert man sofort. */
|
|
.log-ausgabe {
|
|
max-height: calc(100vh - 22rem);
|
|
min-height: 20rem;
|
|
overflow-y: auto;
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
font-size: .78rem;
|
|
line-height: 1.45;
|
|
background: var(--bs-body-bg, #1b1e21);
|
|
border: 1px solid var(--bs-border-color, #2c3034);
|
|
border-radius: .375rem;
|
|
}
|
|
|
|
.log-ausgabe .log-zeile {
|
|
display: flex;
|
|
gap: .6rem;
|
|
padding: .1rem .6rem;
|
|
border-left: 3px solid transparent;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
.log-ausgabe .log-zeile:hover { background: rgba(255, 255, 255, .04); }
|
|
|
|
.log-ausgabe .log-zeit { flex: 0 0 5rem; color: var(--bs-secondary-color, #8b9198); }
|
|
.log-ausgabe .log-level { flex: 0 0 4.5rem; font-weight: 600; }
|
|
.log-ausgabe .log-text { flex: 1 1 auto; }
|
|
|
|
/* Fortsetzungszeilen - die zweite bis letzte Zeile eines Tracebacks - tragen
|
|
kein eigenes Level. Sie bleiben in der Farbe ihrer Kopfzeile, ruecken aber
|
|
ein: so sieht man auf einen Blick, was zusammengehoert. */
|
|
.log-ausgabe .log-fortsetzung .log-text { padding-left: 1.2rem; opacity: .85; }
|
|
|
|
.log-ausgabe .log-debug { color: var(--bs-secondary-color, #8b9198); }
|
|
.log-ausgabe .log-info .log-level { color: #6ea8dc; }
|
|
.log-ausgabe .log-warning { border-left-color: #d9a441; background: rgba(217, 164, 65, .07); }
|
|
.log-ausgabe .log-warning .log-level { color: #d9a441; }
|
|
.log-ausgabe .log-error { border-left-color: #e06060; background: rgba(224, 96, 96, .09); }
|
|
.log-ausgabe .log-error .log-level { color: #f08a8a; }
|
|
|
|
/* Tagestrenner: das Datum steht einmal da, nicht in jeder Zeile. */
|
|
.log-ausgabe .log-tag {
|
|
position: sticky;
|
|
top: 0;
|
|
padding: .15rem .6rem;
|
|
font-size: .72rem;
|
|
letter-spacing: .04em;
|
|
color: var(--bs-secondary-color, #8b9198);
|
|
background: var(--bs-tertiary-bg, #23272b);
|
|
border-top: 1px solid var(--bs-border-color, #2c3034);
|
|
border-bottom: 1px solid var(--bs-border-color, #2c3034);
|
|
}
|
|
|
|
/* Die Dateiliste links: der aktive Eintrag wird von AdminLTE eingefaerbt,
|
|
die Zustandszeile darunter soll trotzdem lesbar bleiben. */
|
|
.log-liste .log-wahl.active .text-secondary,
|
|
.log-liste .log-wahl.active .text-warning { color: rgba(255, 255, 255, .75) !important; }
|
|
|
|
/* Etagenschalter im Grundriss der Home-Ansicht.
|
|
|
|
Vorher waren sie ein duenner Ring in einem Amber (#aa7713), das sonst
|
|
nirgends im Dashboard vorkommt - und alle vier sahen immer gleich aus,
|
|
die aktive Etage war an ihnen nicht zu erkennen. Jetzt tragen sie
|
|
dieselbe Scheibe wie die Kacheln im Grundriss, und die aktive Etage
|
|
bekommt die Akzentfarbe der Schieberegler. */
|
|
.floorBtn { cursor: pointer; }
|
|
|
|
.floorBtn circle {
|
|
fill: #0006;
|
|
stroke: #9aa0a6;
|
|
stroke-width: 4;
|
|
opacity: .55;
|
|
transition: stroke .25s ease, opacity .25s ease;
|
|
}
|
|
|
|
.floorBtn text {
|
|
font: 600 34px Poppins, system-ui, sans-serif;
|
|
fill: #9aa0a6;
|
|
opacity: .8;
|
|
transition: fill .25s ease, opacity .25s ease;
|
|
/* Der Kreis faengt den Klick, nicht die Beschriftung - sonst wandert der
|
|
Textcursor ueber die Schrift, sobald man sie streift. */
|
|
user-select: none;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.floorBtn:hover circle { opacity: .8; }
|
|
.floorBtn:hover text { opacity: 1; }
|
|
|
|
.floorBtn.active circle { stroke: #00788F; opacity: 1; }
|
|
.floorBtn.active text { fill: #e8ede9; opacity: 1; }
|