Raum-Modal, Zeitleiste und Automatik-Editor zeigten drei verschiedene Zeichen; bi-blinds gibt es in der Icon-Schrift gar nicht. Das neue Symbol liegt als CSS-Maske in solar.css und verhaelt sich wie ein Icon aus der Schrift. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4139 lines
178 KiB
CSS
4139 lines
178 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;
|
||
|
||
/* Zwei Radien statt einem. Der grosse gilt fuer Flaechen (Karten, Modale,
|
||
Eingabefelder), der kleine fuer alles, was in einer Reihe steht -
|
||
Schalter, kleine Knoepfe, Abzeichen. Bootstrap kennt beide, benutzte
|
||
bisher aber nur den grossen; der kleine stand auf seiner Vorgabe von
|
||
.25rem und wirkte daneben eckig. */
|
||
--ton-radius: .875rem;
|
||
--ton-radius-klein: .5rem;
|
||
|
||
/* Die Anzeigeschrift. Poppins liegt seit jeher unter assets/fonts und trug
|
||
bisher nur die Etagenknoepfe im Aussenplan - eine ganze Schrift fuer vier
|
||
Buchstaben. Als Variable traegt sie jetzt alle Ueberschriften: waermer
|
||
und eine Spur weniger technisch als die Source Sans 3 des Fliesstextes,
|
||
ohne dass eine zweite Datei geladen wird. Zahlenkolonnen und Fliesstext
|
||
bleiben unberuehrt - Poppins hat keine Tabellenziffern. */
|
||
--font-anzeige: Poppins, system-ui, -apple-system, "Segoe UI", sans-serif;
|
||
|
||
/* ... 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-border-radius-sm: var(--ton-radius-klein);
|
||
--bs-link-color: var(--ton-sonne);
|
||
--bs-link-hover-color: #ffc94d;
|
||
--bs-heading-color: var(--ton-schrift);
|
||
}
|
||
|
||
/* Ueberschriften in der Anzeigeschrift. Bewusst nur Ueberschriften: der
|
||
Fliesstext und alle Zahlenkolonnen bleiben bei der Schrift des Themes,
|
||
weil Poppins keine Tabellenziffern mitbringt und Messwerte sonst
|
||
springen wuerden. */
|
||
h1, h2, h3, h4, h5, h6,
|
||
.h1, .h2, .h3, .h4, .h5, .h6,
|
||
.card-title,
|
||
.modal-title {
|
||
font-family: var(--font-anzeige);
|
||
font-weight: 600;
|
||
letter-spacing: -.01em;
|
||
}
|
||
|
||
/* 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); }
|
||
|
||
/* --- Eigene Symbole ------------------------------------------------------
|
||
Fuer Dinge, die Bootstrap Icons nicht kennt. Gezeichnet als Maske in
|
||
currentColor, damit sie sich wie ein Symbol aus der Schrift verhalten:
|
||
<i class="bi bi-beschattung"></i> - Groesse, Farbe und Ausrichtung wie
|
||
bei allen anderen. bootstrap-icons.min.css laedt nach dieser Datei, daher
|
||
.bi doppelt im Selektor.
|
||
|
||
bi-beschattung: Kasten, zwei Lamellen, Endleiste - ein Raffstore. Bewusst
|
||
nur vier Balken mit viel Luft dazwischen: mit Fuehrungsschienen und drei
|
||
Lamellen lief das Zeichen bei 16 px zu einem Block zusammen. Ueberall dasselbe: Raum-Modal, Zeitleiste, Editor.
|
||
-------------------------------------------------------------------------- */
|
||
.bi.bi-beschattung::before {
|
||
content: "";
|
||
width: 1em;
|
||
height: 1em;
|
||
background-color: currentColor;
|
||
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 16 16%22%3E%3Crect x=%221.5%22 y=%221.6%22 width=%2213%22 height=%222.6%22 rx=%22.9%22/%3E%3Crect x=%222.6%22 y=%225.7%22 width=%2210.8%22 height=%221.7%22 rx=%22.85%22/%3E%3Crect x=%222.6%22 y=%228.6%22 width=%2210.8%22 height=%221.7%22 rx=%22.85%22/%3E%3Crect x=%221.5%22 y=%2211.8%22 width=%2213%22 height=%222.6%22 rx=%22.9%22/%3E%3C/svg%3E") center / contain no-repeat;
|
||
mask: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 16 16%22%3E%3Crect x=%221.5%22 y=%221.6%22 width=%2213%22 height=%222.6%22 rx=%22.9%22/%3E%3Crect x=%222.6%22 y=%225.7%22 width=%2210.8%22 height=%221.7%22 rx=%22.85%22/%3E%3Crect x=%222.6%22 y=%228.6%22 width=%2210.8%22 height=%221.7%22 rx=%22.85%22/%3E%3Crect x=%221.5%22 y=%2211.8%22 width=%2213%22 height=%222.6%22 rx=%22.9%22/%3E%3C/svg%3E") center / contain no-repeat;
|
||
}
|
||
|
||
/* --- 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;
|
||
}
|
||
}
|
||
|
||
/* --------------------------------------------------------------------------
|
||
Drei Klassen, die der Automatik-Editor gebraucht hat - hier, nicht dort
|
||
|
||
Sie stehen absichtlich in der gemeinsamen Datei und nicht als Sonderfall
|
||
im Editor. Zwei davon sind allgemein genug, um anderswo zu taugen; die
|
||
dritte ist eine echte Ausnahme und als einzelne Klasse auch als solche
|
||
erkennbar.
|
||
-------------------------------------------------------------------------- */
|
||
|
||
/* Ein Auswahlfeld, das wie Text aussieht, bis man es anfaehrt.
|
||
|
||
Eine Bedingung hat sechs Bestandteile, aber nur zwei davon traegt man
|
||
wirklich ein: Vergleich und Wert. Standen alle sechs als gleich schwere
|
||
Kaesten nebeneinander, sagte nichts mehr, worauf es ankommt. Die
|
||
gepunktete Linie sagt "anklickbar", ohne den Platz und das Gewicht eines
|
||
Eingabefelds zu nehmen.
|
||
|
||
Bewusst allgemein: dieselbe Not haben das Raum-Modal und die
|
||
Kachel-Einstellungen, wo ebenfalls jede Kleinigkeit in einem Kasten
|
||
steht. Taugt fuer <select> wie fuer <button>. */
|
||
.feld-als-text {
|
||
appearance: none;
|
||
-webkit-appearance: none;
|
||
max-width: 100%;
|
||
padding: 0 0 1px;
|
||
border: 0;
|
||
border-bottom: 1px dashed var(--ton-linie-satt);
|
||
border-radius: 0;
|
||
background: none;
|
||
color: inherit;
|
||
font: inherit;
|
||
text-align: left;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.feld-als-text:hover,
|
||
.feld-als-text:focus-visible {
|
||
border-bottom-color: var(--bs-link-color);
|
||
color: var(--bs-emphasis-color);
|
||
outline: 0;
|
||
}
|
||
|
||
/* Ein Messwert, wie er in diesem Moment dasteht.
|
||
|
||
Steht neben einer Bedingung und beantwortet die Frage, die man wirklich
|
||
hat: "warum laeuft die nicht?". Das ist die Ausnahme unter den dreien -
|
||
Bedingungen gibt es sonst nirgends auf der Seite. */
|
||
.wert-jetzt {
|
||
font-size: .8125rem;
|
||
color: var(--ton-schrift-3);
|
||
font-variant-numeric: tabular-nums;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.wert-jetzt b { font-weight: 400; color: var(--ton-schrift-2); }
|
||
.wert-jetzt.erfuellt b { color: var(--ton-gut); }
|
||
|
||
/* Erfuellt oder noch nicht. Bewusst kein Rot: eine Bedingung, die gerade
|
||
nicht zutrifft, ist der Normalfall und kein Fehler. */
|
||
.punkt {
|
||
display: inline-block;
|
||
width: .7rem;
|
||
height: .7rem;
|
||
border: 1.5px solid var(--ton-schrift-3);
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.punkt.an {
|
||
border-color: var(--ton-gut);
|
||
background: var(--ton-gut);
|
||
}
|
||
|
||
/* Atmet leise, wo etwas mitlaeuft - ein Wort "live" daneben braucht es dann
|
||
nicht. */
|
||
.punkt.atmet { animation: punkt-atmen 2.4s ease-in-out infinite; }
|
||
|
||
@keyframes punkt-atmen {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: .35; }
|
||
}
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.punkt.atmet { animation: none; }
|
||
}
|
||
|
||
|
||
/* --------------------------------------------------------------------------
|
||
Editor der Automatiken: die Bedingungszeile
|
||
|
||
Frueher eine input-group aus sechs gleich schweren Kaesten. Jetzt ein
|
||
Raster, in dem Geraet und Messwert uebereinander stehen (das Geraet
|
||
beantwortet "woher", nicht "was") und nur Vergleich und Wert noch wie
|
||
Eingabefelder aussehen.
|
||
|
||
Auf schmalen Schirmen bricht die Zeile in zwei: oben, worum es geht,
|
||
unten der Vergleich. Frueher schrumpften die Felder stattdessen mit, bis
|
||
von "Thermostat OG Bad" ein "Therm" uebrig war.
|
||
-------------------------------------------------------------------------- */
|
||
.auto-zeile {
|
||
display: grid;
|
||
grid-template-columns: 1.75rem minmax(0, 1fr) 5.25rem 8rem 8.5rem .75rem 1.75rem;
|
||
grid-template-areas: "sym was op wert jetzt punkt weg";
|
||
gap: .625rem;
|
||
align-items: center;
|
||
padding: .45rem .55rem;
|
||
border-radius: var(--ton-radius-klein);
|
||
}
|
||
|
||
.auto-zeile:nth-of-type(even) { background: rgba(255, 255, 255, .022); }
|
||
|
||
.auto-zeile > .auto-symbol { grid-area: sym; color: var(--ton-schrift-2); }
|
||
.auto-zeile > .auto-was { grid-area: was; min-width: 0; }
|
||
.auto-zeile > .auto-op { grid-area: op; }
|
||
.auto-zeile > .auto-wert { grid-area: wert; }
|
||
.auto-zeile > .wert-jetzt { grid-area: jetzt; }
|
||
.auto-zeile > .punkt { grid-area: punkt; }
|
||
.auto-zeile > .auto-weg { grid-area: weg; }
|
||
.auto-zeile > .auto-werte { grid-area: werte; }
|
||
|
||
/* Die Aktionszeile: dasselbe Raster, andere Spalten. Statt Vergleich, Wert
|
||
und laufendem Messwert steht dort ein Block mit den Parametern des
|
||
Kommandos - mal keiner ("Auf"), mal zwei ("Position+Neigung"). */
|
||
.auto-zeile.tat {
|
||
grid-template-columns: 1.75rem minmax(0, 1fr) auto 1.75rem;
|
||
grid-template-areas: "sym was werte weg";
|
||
}
|
||
|
||
/* Eine Zeile ohne Geraet: dann gibt es nur eines zu tun, und das darf die
|
||
ganze Breite haben. Vergleich, Wert und der laufende Messwert gibt es in
|
||
diesem Zustand noch gar nicht - ihre Spalten stuenden sonst nur leer
|
||
herum, waehrend die eine Schaltflaeche in eine schmale Spalte gequetscht
|
||
waere. */
|
||
.auto-zeile.leer { grid-template-areas: "sym was was was was punkt weg"; }
|
||
|
||
/* Geraet klein und matt ueber dem Messwert - und trotzdem anklickbar. */
|
||
.auto-was { display: flex; flex-direction: column; gap: .05rem; }
|
||
|
||
/* Nur in der Bedingungszeile: die Aktionszeile benutzt .auto-geraet
|
||
weiterhin als vollwertige Auswahlflaeche und darf davon nichts
|
||
abbekommen. */
|
||
/* Nicht in der leeren Zeile: dort traegt derselbe Knopf zusaetzlich
|
||
.feld-als-text und ist die einzige Handlung, die es gibt - klein und matt
|
||
waere er dort genau die Falle, die er vorher war. Die Klasse .auto-geraet
|
||
behaelt er trotzdem, weil daran haengt, WAS er ist: der Klick-Horcher
|
||
erkennt ihn daran. Verhalten und Aussehen sind absichtlich zwei
|
||
verschiedene Klassen. */
|
||
.auto-was > .auto-geraet:not(.feld-als-text) {
|
||
align-self: start;
|
||
max-width: 100%;
|
||
padding: 0;
|
||
border: 0;
|
||
background: none;
|
||
color: var(--ton-schrift-3);
|
||
font-size: .72rem;
|
||
line-height: 1.3;
|
||
text-align: left;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.auto-was > .auto-geraet:not(.feld-als-text):hover,
|
||
.auto-was > .auto-geraet:not(.feld-als-text):focus-visible {
|
||
color: var(--bs-link-color);
|
||
outline: 0;
|
||
}
|
||
|
||
.auto-messwert { align-self: start; }
|
||
|
||
/* Der Papierkorb erscheint erst beim Ueberfahren. Acht rote Knoepfe im
|
||
Ruhezustand zogen alle Aufmerksamkeit auf die seltenste Handlung.
|
||
Wo es kein Ueberfahren gibt, steht er dauerhaft da. */
|
||
.auto-zeile > .auto-weg {
|
||
padding: 0;
|
||
border: 0;
|
||
background: none;
|
||
color: var(--ton-schrift-3);
|
||
opacity: 0;
|
||
transition: opacity .15s ease, color .15s ease;
|
||
}
|
||
|
||
.auto-zeile:hover > .auto-weg,
|
||
.auto-zeile:focus-within > .auto-weg { opacity: 1; }
|
||
.auto-zeile > .auto-weg:hover { color: var(--ton-schlecht); }
|
||
|
||
@media (hover: none) {
|
||
.auto-zeile > .auto-weg { opacity: 1; }
|
||
}
|
||
|
||
/* Ein Segment je Bedingung, im Kopf des Bandes und ueber jeder Gruppe.
|
||
Eine Zahl allein ("2 von 4") liest man, die Reihe sieht man. */
|
||
.auto-segment {
|
||
width: .8rem;
|
||
height: .3rem;
|
||
border-radius: .15rem;
|
||
background: var(--ton-linie-satt);
|
||
}
|
||
|
||
.auto-segment.an { background: var(--ton-gut); }
|
||
|
||
/* Was der Browser nicht entscheiden kann, bleibt hohl - siehe ZEITARTEN in
|
||
autoActionFuncs.js. */
|
||
.auto-segment.offen {
|
||
background: none;
|
||
box-shadow: inset 0 0 0 1px var(--ton-linie-satt);
|
||
}
|
||
|
||
@media (max-width: 767.98px) {
|
||
.auto-zeile {
|
||
grid-template-columns: 1.75rem 5.25rem minmax(0, 1fr) .75rem 1.75rem;
|
||
/* Drei Zeilen statt zwei: der laufende Wert quetschte sich sonst mit
|
||
dem Wertfeld in dieselbe Reihe und blieb als "gerad…" stehen. Auf
|
||
einem Handy ist Hoehe billig und Breite teuer. */
|
||
grid-template-areas:
|
||
"sym was was punkt weg"
|
||
"sym op wert wert wert"
|
||
"sym jetzt jetzt jetzt jetzt";
|
||
row-gap: .35rem;
|
||
}
|
||
|
||
.auto-zeile.leer { grid-template-areas: "sym was was punkt weg"; }
|
||
|
||
.auto-zeile.tat {
|
||
grid-template-columns: 1.75rem minmax(0, 1fr) 1.75rem;
|
||
grid-template-areas:
|
||
"sym was weg"
|
||
"sym werte werte";
|
||
}
|
||
|
||
.auto-zeile.tat.leer { grid-template-areas: "sym was weg"; }
|
||
}
|
||
|
||
/* --------------------------------------------------------------------------
|
||
Raum-Modal (Klick auf einen Raum im Grundriss)
|
||
Markup: ajax/room.php + restricted/roomControls.php,
|
||
Verhalten: js/solar/raumfenster.js. Gleiche Bauart wie Lade-, Heiz- und
|
||
Bewaesserungsfenster (.lade): Akzentfarbe je Bereich, Stufen statt
|
||
Schieber, jede Wahl gilt sofort.
|
||
|
||
Alle Regeln tragen .rf davor: solar.css laedt vor AdminLTE, und die
|
||
Knoepfe hier setzen die Bootstrap-Gestaltung mit all: unset zurueck.
|
||
-------------------------------------------------------------------------- */
|
||
#modalEV .modal-dialog:has(.rf) { max-width: 42rem; }
|
||
#modalEV .modal-content:has(.rf) .modal-footer { display: none; }
|
||
#modalEV .modal-title .rf-etage { font-size: .7rem; font-weight: 600; padding: .05rem .5rem; border-radius: 99px; background: rgba(255, 255, 255, .07); color: var(--ton-schrift-2, #9aa6ad); vertical-align: middle; font-family: var(--bs-body-font-family); }
|
||
|
||
.rf { display: grid; gap: .75rem; padding: .9rem 1rem .8rem; --a: #60afbf; }
|
||
.rf h3 { margin: 0; font-size: .68rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.rf .rf-leer { margin: 0; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.rf .rf-meldung { font-size: .76rem; color: var(--ton-schrift-3, #6f7a81); }
|
||
.rf .rf-meldung.gut { color: #6cbe58; }
|
||
.rf .rf-meldung.fehler { color: #e5624f; }
|
||
.rf .bi { line-height: 1; }
|
||
|
||
/* Waehrend ein Kommando unterwegs ist - Lampen, Schalter, Heizung. Jalousien
|
||
zeigen stattdessen "faehrt…" (.rf-bewegt). */
|
||
.rf .raum-geraet, .rf .rf-heiz { position: relative; }
|
||
.rf .raum-warte { opacity: .6; pointer-events: none; }
|
||
.rf .raum-warte::after {
|
||
content: ""; position: absolute; top: .55rem; right: .55rem; width: .85rem; height: .85rem;
|
||
border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
|
||
animation: raum-dreht .8s linear infinite;
|
||
}
|
||
@keyframes raum-dreht { to { transform: rotate(360deg); } }
|
||
|
||
/* Reiter als Kacheln mit Zustand */
|
||
.rf .rf-reiter { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: .4rem; overflow-x: auto; scrollbar-width: none; }
|
||
.rf .rf-reiter::-webkit-scrollbar { display: none; }
|
||
.rf .rf-reiter button {
|
||
all: unset; box-sizing: border-box; cursor: pointer; min-width: 6.5rem;
|
||
display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: .5rem; align-items: center;
|
||
padding: .45rem .6rem; border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); border: 1.5px solid transparent;
|
||
transition: background .2s, border-color .2s;
|
||
}
|
||
.rf .rf-reiter button:hover { background: #313940; }
|
||
.rf .rf-reiter button:focus-visible { outline: 2px solid var(--c); outline-offset: 1px; }
|
||
.rf .rf-reiter .rf-sym { grid-row: span 2; width: 1.9rem; height: 1.9rem; border-radius: .55rem; display: grid; place-items: center; background: rgba(255, 255, 255, .06); color: var(--c); font-size: 1rem; }
|
||
.rf .rf-reiter b { font-weight: 500; font-size: .84rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.rf .rf-reiter .rf-st { font-size: .72rem; color: var(--ton-schrift-2, #9aa6ad); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
|
||
.rf .rf-reiter .rf-st:empty::before { content: "\00a0"; }
|
||
.rf .rf-reiter button[aria-selected="true"] { border-color: var(--c); background: color-mix(in srgb, var(--c) 11%, var(--ton-flaeche-2, #2b3237)); }
|
||
.rf .rf-reiter button[aria-selected="true"] .rf-sym { background: color-mix(in srgb, var(--c) 24%, transparent); }
|
||
.rf .rf-flaeche { display: grid; gap: .6rem; animation: rf-auf .25s cubic-bezier(.2, .7, .2, 1); }
|
||
.rf .rf-flaeche[hidden] { display: none; }
|
||
@keyframes rf-auf { from { opacity: 0; transform: translateY(4px); } }
|
||
|
||
/* Bausteine */
|
||
.rf .rf-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
|
||
.rf .rf-chip { all: unset; box-sizing: border-box; cursor: pointer; padding: .32rem .7rem; border-radius: 99px; background: #363d43; font-size: .8rem; font-weight: 500; display: inline-flex; align-items: center; gap: .35rem; font-variant-numeric: tabular-nums; }
|
||
.rf .rf-chip:hover { background: #3f474e; }
|
||
.rf .rf-chip span { opacity: .7; }
|
||
.rf .rf-chip[aria-pressed="true"] { background: var(--a); color: #0c1a1d; font-weight: 600; }
|
||
.rf .rf-chip:focus-visible { outline: 2px solid var(--a); outline-offset: 1px; }
|
||
.rf .rf-pille { font-size: .7rem; font-weight: 600; border-radius: 99px; padding: .05rem .5rem; background: rgba(255, 255, 255, .06); color: var(--ton-schrift-2, #9aa6ad); white-space: nowrap; display: inline-flex; align-items: center; gap: .3rem; }
|
||
.rf .rf-pille:empty { display: none; }
|
||
.rf .rf-pille.faehrt { color: #60afbf; background: rgba(96, 175, 191, .15); }
|
||
.rf .rf-pille.faehrt::before { content: ""; width: .4rem; height: .4rem; border-radius: 50%; background: currentColor; animation: rf-puls 1.2s infinite; }
|
||
@keyframes rf-puls { 50% { opacity: .3; } }
|
||
.rf .rf-link { all: unset; cursor: pointer; color: #60afbf; font-weight: 500; margin-left: auto; }
|
||
.rf .rf-link:hover { text-decoration: underline; }
|
||
.rf .rf-link:focus-visible { outline: 2px solid #60afbf; outline-offset: 2px; border-radius: 3px; }
|
||
.rf .rf-kopf-zeile { display: flex; align-items: center; gap: .5rem; min-width: 0; }
|
||
.rf .rf-kopf-zeile > b { font-weight: 500; font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.rf .rf-kopf-zeile .rf-pille { margin-left: auto; }
|
||
.rf .rf-mehr { flex: none; }
|
||
.rf .rf-kopf-zeile b + .rf-mehr, .rf .rf-kopf-zeile .rf-pille:empty + .rf-mehr, .rf .rf-lampe-name + .rf-mehr { margin-left: auto; }
|
||
.rf .rf-mehr-knopf { all: unset; cursor: pointer; width: 1.75rem; height: 1.75rem; display: grid; place-items: center; border-radius: .5rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.rf .rf-mehr-knopf:hover { background: #363d43; }
|
||
.rf .rf-karte { display: grid; gap: .5rem; padding: .7rem .75rem; border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); }
|
||
.rf .rf-karte .btn { --bs-btn-padding-y: .2rem; }
|
||
.rf details.rf-effekte summary { cursor: pointer; font-size: .8rem; color: var(--ton-schrift-2, #9aa6ad); list-style: none; display: flex; align-items: center; gap: .35rem; }
|
||
.rf details.rf-effekte summary::-webkit-details-marker { display: none; }
|
||
.rf details.rf-effekte summary::after { content: "›"; font-size: 1rem; transition: transform .2s; }
|
||
.rf details.rf-effekte[open] summary::after { transform: rotate(90deg); }
|
||
.rf details.rf-effekte[open] { display: grid; gap: .5rem; }
|
||
|
||
/* Regler wie im Ladefenster */
|
||
.rf input[type="range"] { -webkit-appearance: none; appearance: none; width: 100%; height: 1.9rem; background: transparent; margin: 0; }
|
||
.rf input[type="range"]::-webkit-slider-runnable-track { height: .5rem; border-radius: .25rem; background: linear-gradient(90deg, var(--a) 0 var(--wert, 0%), #394046 var(--wert, 0%)); }
|
||
.rf input[type="range"]::-moz-range-track { height: .5rem; border-radius: .25rem; background: linear-gradient(90deg, var(--a) 0 var(--wert, 0%), #394046 var(--wert, 0%)); }
|
||
.rf input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 1.5rem; height: 1.5rem; margin-top: -.5rem; border-radius: 50%; background: #fff; border: 4px solid var(--a); box-shadow: 0 .15rem .5rem rgba(0, 0, 0, .4); }
|
||
.rf input[type="range"]::-moz-range-thumb { width: 1rem; height: 1rem; border-radius: 50%; background: #fff; border: 4px solid var(--a); }
|
||
.rf input[type="range"]:focus-visible { outline: 2px solid var(--a); outline-offset: 4px; }
|
||
|
||
/* --- Beschattung --- */
|
||
.rf .rf-alle { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; padding: .6rem .7rem; border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); }
|
||
.rf .rf-alle h3 { margin-right: auto; }
|
||
.rf .rf-alle .bi { font-size: .8rem; }
|
||
|
||
.rf .rf-behang { display: grid; grid-template-columns: 4.75rem minmax(0, 1fr); gap: .85rem; padding: .7rem; border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); border: 1.5px solid transparent; transition: border-color .3s; }
|
||
.rf .rf-behang.rf-bewegt { border-color: rgba(96, 175, 191, .6); }
|
||
.rf .rf-behang-mitte { display: grid; gap: .5rem; min-width: 0; align-content: start; }
|
||
|
||
/* Das Fenster: dunkles Glas mit Tageslicht-Schimmer, helle Lamellen, die
|
||
Unterleiste im Akzent. Ueber die ganze Hoehe der Karte. */
|
||
.rf .rf-fenster { position: relative; min-height: 6rem; padding: .25rem; border-radius: .75rem; background: #1c2226; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07); touch-action: none; }
|
||
.rf .rf-fenster[data-rf-zieh] { cursor: ns-resize; }
|
||
.rf .rf-glas { position: relative; height: 100%; border-radius: .5rem; overflow: hidden;
|
||
background: radial-gradient(120% 55% at 80% 0%, rgba(126, 214, 230, .5), transparent 60%), linear-gradient(170deg, #1f4c5a 0%, #173640 55%, #122a31 100%); }
|
||
.rf .rf-glas::after { content: ""; position: absolute; inset: 0; background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, .09) 44%, transparent 52%); pointer-events: none; }
|
||
.rf .rf-behang-teil { position: absolute; left: 0; right: 0; top: 0; height: 0; overflow: hidden; transition: height .35s cubic-bezier(.2, .7, .2, 1); }
|
||
.rf .rf-lamellen { position: absolute; left: 0; right: 0; bottom: 3px; display: grid; gap: 1.5px; }
|
||
.rf .rf-lamellen i { display: block; height: 5px; border-radius: 3px; background: linear-gradient(180deg, #e9f1f3, #b9c9cf); transform: scaleY(var(--kipp, 1)); box-shadow: 0 1px 0 rgba(0, 0, 0, .25); transition: transform .35s; }
|
||
.rf .rf-panzer { position: absolute; inset: 0 0 3px; background: repeating-linear-gradient(0deg, #d5e0e4 0 5px, #a9bac0 5px 6.5px); }
|
||
.rf .rf-schiene { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; border-radius: 2px; background: #60afbf; box-shadow: 0 0 8px rgba(96, 175, 191, .7); }
|
||
|
||
.rf .rf-fahrt { display: grid; grid-template-columns: 1fr auto auto 1fr; gap: .35rem; }
|
||
.rf .rf-fahrt button { all: unset; box-sizing: border-box; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: .35rem; height: 2.4rem; padding: 0 .6rem; border-radius: .6rem; background: #363d43; font-weight: 600; font-size: .86rem; }
|
||
.rf .rf-fahrt button:hover { background: #3f474e; }
|
||
.rf .rf-fahrt button:active { transform: scale(.97); }
|
||
.rf .rf-fahrt button:focus-visible { outline: 2px solid #60afbf; outline-offset: 1px; }
|
||
.rf .rf-fahrt .rf-stop { width: 2.75rem; }
|
||
.rf .rf-fahrt .rf-my .bi { color: #f7c000; font-size: .8rem; }
|
||
.rf .rf-fahrt .rf-my.aktiv { background: color-mix(in srgb, #f7c000 16%, #363d43); box-shadow: inset 0 0 0 1.5px #f7c000; }
|
||
|
||
.rf .rf-reihe { display: grid; grid-template-columns: 4.3rem minmax(0, 1fr); align-items: center; gap: .5rem; }
|
||
.rf .rf-reihe-titel { font-size: .76rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.rf .rf-segment { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 3px; padding: 3px; border-radius: .6rem; background: #22292d; }
|
||
.rf .rf-segment button { all: unset; box-sizing: border-box; cursor: pointer; text-align: center; padding: .3rem .1rem; border-radius: .45rem; font-size: .76rem; font-weight: 500; color: var(--ton-schrift-2, #9aa6ad); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
||
.rf .rf-segment button:hover { color: var(--ton-schrift, #e8ede9); }
|
||
.rf .rf-segment button[aria-checked="true"] { background: #363d43; color: var(--ton-schrift, #e8ede9); box-shadow: inset 0 0 0 1.5px var(--a); }
|
||
.rf .rf-segment button:focus-visible { outline: 2px solid var(--a); }
|
||
|
||
.rf .rf-my-zeile { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; font-size: .76rem; color: var(--ton-schrift-3, #6f7a81); min-height: 1.5rem; }
|
||
.rf .rf-my-zeile > .bi { color: #f7c000; font-size: .72rem; }
|
||
.rf .rf-my-zeile.frage { padding: .35rem .5rem; border-radius: .55rem; background: rgba(247, 192, 0, .08); color: var(--ton-schrift, #e8ede9); }
|
||
.rf .rf-my-knoepfe { display: inline-flex; gap: .3rem; margin-left: auto; }
|
||
.rf .rf-my-zeile .rf-chip { padding: .2rem .6rem; font-size: .76rem; }
|
||
.rf .rf-my-zeile .rf-chip.ja { background: #f7c000; color: #1a1406; font-weight: 600; }
|
||
|
||
/* --- Heizung --- */
|
||
.rf .rf-heiz { display: grid; grid-template-columns: 10.5rem minmax(0, 1fr); gap: 1rem; align-items: center; --a: #e5624f; }
|
||
.rf .rf-ring { position: relative; width: 10.5rem; aspect-ratio: 1; max-width: 100%; }
|
||
.rf .rf-ring svg { width: 100%; height: 100%; display: block; touch-action: none; }
|
||
.rf .rf-ring-spur { fill: none; stroke: #2b3237; stroke-width: 12; stroke-linecap: round; }
|
||
.rf .rf-ring-ist { fill: none; stroke: url(#rfHeizVerlauf); stroke-width: 12; stroke-linecap: round; transition: stroke-dasharray .6s cubic-bezier(.2, .7, .2, 1); }
|
||
.rf .rf-ring-griff { fill: none; stroke: transparent; stroke-width: 36; cursor: pointer; }
|
||
.rf .rf-ring-soll { fill: #fff; stroke: #e5624f; stroke-width: 4; cursor: grab; transform-box: view-box; transform-origin: 85px 85px; transition: transform .35s cubic-bezier(.2, .7, .2, 1); }
|
||
.rf .rf-heiz.zieht .rf-ring-soll { cursor: grabbing; transition: none; }
|
||
.rf .rf-ring-soll:focus-visible { outline: none; stroke: #fff; fill: #e5624f; }
|
||
.rf .rf-ring-mitte { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; pointer-events: none; }
|
||
.rf .rf-ring-mitte small { font-size: .7rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.rf .rf-ring-mitte b { font-size: 1.9rem; font-weight: 600; line-height: 1.05; font-variant-numeric: tabular-nums; }
|
||
.rf .rf-ring-mitte b small { font-size: .95rem; font-weight: 500; color: var(--ton-schrift, #e8ede9); }
|
||
.rf .rf-ring-mitte span { font-size: .74rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.rf .rf-heiz-rechts { display: grid; gap: .6rem; min-width: 0; }
|
||
.rf .rf-stepper { display: grid; grid-template-columns: 3rem minmax(0, 1fr) 3rem; align-items: center; gap: .5rem; background: var(--ton-flaeche-2, #2b3237); border-radius: .85rem; padding: .35rem; }
|
||
.rf .rf-stepper button { all: unset; cursor: pointer; height: 3rem; border-radius: .6rem; display: grid; place-items: center; background: #363d43; font-size: 1.4rem; font-weight: 500; }
|
||
.rf .rf-stepper button:hover { background: #3f474e; }
|
||
.rf .rf-stepper button:active { transform: scale(.95); }
|
||
.rf .rf-stepper button:focus-visible { outline: 2px solid #e5624f; }
|
||
.rf .rf-stepper output { text-align: center; font-size: 1.55rem; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.15; }
|
||
.rf .rf-stepper output small { display: block; font-size: .7rem; font-weight: 400; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.rf .rf-hinweis { padding: .45rem .65rem; border-radius: .6rem; background: rgba(255, 255, 255, .05); color: var(--ton-schrift-2, #9aa6ad); font-size: .8rem; display: flex; gap: .45rem; align-items: flex-start; }
|
||
.rf .rf-hinweis[hidden] { display: none; }
|
||
.rf .rf-hinweis.an { background: rgba(229, 98, 79, .12); color: #f3b3a9; }
|
||
.rf .rf-hinweis .bi { margin-top: .15rem; }
|
||
.rf .rf-pillen { display: flex; flex-wrap: wrap; gap: .35rem; }
|
||
.rf .rf-pillen .rf-pille { font-size: .74rem; padding: .15rem .6rem; }
|
||
.rf .rf-pillen .rf-pille[hidden] { display: none; }
|
||
|
||
/* --- Licht --- */
|
||
.rf .rf-lampe { display: grid; gap: .55rem; padding: .7rem; border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); --a: #f7c000; }
|
||
.rf .rf-lampe-kopf { display: flex; align-items: center; gap: .7rem; }
|
||
.rf .rf-birne { all: unset; cursor: pointer; flex: none; width: 3rem; height: 3rem; border-radius: .9rem; display: grid; place-items: center; background: #22292d; color: var(--ton-schrift-3, #6f7a81); font-size: 1.35rem; transition: background .3s, box-shadow .3s, color .3s; }
|
||
.rf .rf-birne[aria-pressed="true"] { color: #1a1406; background: var(--farbe, #ffd27a); box-shadow: 0 0 0 4px color-mix(in srgb, var(--farbe, #ffd27a) 22%, transparent), 0 .35rem 1.3rem color-mix(in srgb, var(--farbe, #ffd27a) 45%, transparent); }
|
||
.rf .rf-birne:focus-visible { outline: 2px solid #f7c000; outline-offset: 3px; }
|
||
.rf .rf-lampe-name { display: grid; min-width: 0; }
|
||
.rf .rf-lampe-name b { font-weight: 500; font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.rf .rf-lampe-name span { font-size: .76rem; color: var(--ton-schrift-2, #9aa6ad); font-variant-numeric: tabular-nums; }
|
||
.rf .rf-lampe-regler { display: grid; gap: .5rem; transition: opacity .3s; }
|
||
.rf .rf-lampe.aus .rf-lampe-regler { opacity: .5; }
|
||
.rf .rf-hell::-webkit-slider-runnable-track { background: linear-gradient(90deg, #4a3f22 0, var(--farbe, #ffd27a) var(--wert, 0%), #394046 var(--wert, 0%)) !important; }
|
||
.rf .rf-hell::-moz-range-track { background: linear-gradient(90deg, #4a3f22 0, var(--farbe, #ffd27a) var(--wert, 0%), #394046 var(--wert, 0%)) !important; }
|
||
.rf .rf-farben { display: flex; flex-wrap: wrap; gap: .45rem; align-items: center; }
|
||
.rf .rf-farbe { all: unset; box-sizing: border-box; cursor: pointer; width: 1.65rem; height: 1.65rem; border-radius: 50%; background: var(--f); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .25); transition: transform .15s; position: relative; }
|
||
.rf .rf-farbe:hover { transform: scale(1.1); }
|
||
.rf .rf-farbe[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--ton-flaeche-2, #2b3237), 0 0 0 4px var(--f); }
|
||
.rf .rf-farbe:focus-visible, .rf .rf-farbe-eigen:focus-within { outline: 2px solid #f7c000; outline-offset: 3px; }
|
||
.rf .rf-farbe-eigen { background: conic-gradient(#f55, #fd5, #5f7, #5df, #75f, #f5d, #f55); }
|
||
.rf .rf-farbe-eigen input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; }
|
||
/* Preset, Effekt: Titel links, Chips oder Picker rechts. Lange Listen
|
||
klappen als durchsuchbarer Kasten unter der Zeile auf. */
|
||
.rf .rf-liste { display: grid; grid-template-columns: 4.3rem minmax(0, 1fr); align-items: start; gap: .4rem .5rem; padding-top: .55rem; border-top: 1px solid rgba(255, 255, 255, .06); }
|
||
.rf .rf-liste + .rf-liste { border-top: 0; padding-top: 0; }
|
||
.rf .rf-liste > .rf-reihe-titel { padding-top: .35rem; }
|
||
.rf .rf-liste .rf-chip { padding: .28rem .65rem; font-size: .78rem; }
|
||
.rf .rf-liste .rf-chip[aria-pressed="true"] { color: #1a1406; }
|
||
.rf .rf-picker-knopf { all: unset; box-sizing: border-box; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: .5rem; min-width: 0; padding: .38rem .7rem; border-radius: .6rem; background: #22292d; font-size: .82rem; font-weight: 500; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06); }
|
||
.rf .rf-picker-knopf span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.rf .rf-picker-knopf .bi { font-size: .75rem; color: var(--ton-schrift-2, #9aa6ad); transition: transform .2s; }
|
||
.rf .rf-picker-knopf:hover { background: #283035; }
|
||
.rf .rf-picker-knopf[aria-expanded="true"] { box-shadow: inset 0 0 0 1.5px var(--a); }
|
||
.rf .rf-picker-knopf[aria-expanded="true"] .bi { transform: rotate(180deg); }
|
||
.rf .rf-picker-knopf:focus-visible { outline: 2px solid var(--a); outline-offset: 1px; }
|
||
.rf .rf-picker { grid-column: 1 / -1; display: grid; gap: .45rem; padding: .5rem; border-radius: .65rem; background: #22292d; animation: rf-auf .2s cubic-bezier(.2, .7, .2, 1); }
|
||
.rf .rf-picker[hidden] { display: none; }
|
||
.rf .rf-suche { all: unset; box-sizing: border-box; width: 100%; padding: .4rem .65rem; border-radius: .5rem; background: var(--ton-flaeche-2, #2b3237); color: var(--ton-schrift, #e8ede9); font-size: .82rem; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08); }
|
||
.rf .rf-suche::placeholder { color: var(--ton-schrift-3, #6f7a81); }
|
||
.rf .rf-suche:focus { box-shadow: inset 0 0 0 1.5px var(--a); }
|
||
.rf .rf-picker-liste { display: flex; flex-wrap: wrap; align-content: flex-start; gap: .3rem; max-height: 11rem; overflow-y: auto; padding-right: .25rem; scrollbar-width: thin; scrollbar-color: #3f474e transparent; }
|
||
.rf .rf-picker-liste .rf-chip[hidden] { display: none; }
|
||
@media (max-width: 575.98px) {
|
||
.rf .rf-liste { grid-template-columns: 1fr; gap: .3rem; }
|
||
.rf .rf-liste > .rf-reihe-titel { padding-top: 0; }
|
||
}
|
||
|
||
/* --- Schalter --- */
|
||
.rf .rf-schalter-liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); gap: .5rem; }
|
||
.rf .rf-schalter { all: unset; box-sizing: border-box; cursor: pointer; display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: .6rem; align-items: center; padding: .6rem; border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); border: 1.5px solid transparent; position: relative; }
|
||
.rf .rf-schalter .rf-sym { grid-row: span 2; width: 2.1rem; height: 2.1rem; border-radius: .6rem; display: grid; place-items: center; background: #22292d; color: var(--ton-schrift-3, #6f7a81); }
|
||
.rf .rf-schalter b { font-weight: 500; font-size: .84rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.rf .rf-schalter .rf-st { font-size: .72rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.rf .rf-schalter[aria-pressed="true"] { border-color: #6cbe58; }
|
||
.rf .rf-schalter[aria-pressed="true"] .rf-sym { background: rgba(108, 190, 88, .18); color: #6cbe58; }
|
||
.rf .rf-schalter:focus-visible { outline: 2px solid #6cbe58; }
|
||
|
||
/* --- Messwerte und Sonstiges --- */
|
||
.rf .raum-werte { display: grid; grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr)); gap: .4rem; }
|
||
.rf .raum-wert { background: rgba(255, 255, 255, .04); border-radius: .5rem; padding: .3rem .5rem; overflow: hidden; }
|
||
.rf .raum-wert-zahl { font-size: .95rem; font-weight: 600; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.rf .raum-wert-einheit { font-size: .7rem; font-weight: 400; opacity: .6; }
|
||
.rf .raum-wert-name { font-size: .68rem; opacity: .6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
/* Ein Kommando mit mehreren Parametern traegt Beschriftung, Felder und Knopf
|
||
in einer input-group - ohne Mindestbreite schrumpfen die Felder am Handy
|
||
auf nichts. */
|
||
.rf .input-group.raum-cmd > .form-control,
|
||
.rf .input-group.raum-cmd > .form-select { min-width: 5rem; }
|
||
|
||
/* --- Handy --- */
|
||
@media (max-width: 575.98px) {
|
||
.rf { padding: .75rem .75rem .7rem; }
|
||
.rf .rf-reiter button { grid-template-columns: 1fr; justify-items: center; text-align: center; padding: .4rem .25rem; row-gap: .1rem; min-width: 5.5rem; }
|
||
.rf .rf-reiter .rf-sym { grid-row: auto; width: 1.6rem; height: 1.6rem; }
|
||
.rf .rf-reiter b { font-size: .76rem; }
|
||
.rf .rf-reiter .rf-st { font-size: .68rem; }
|
||
.rf .rf-behang { grid-template-columns: 3.6rem minmax(0, 1fr); gap: .6rem; padding: .6rem; }
|
||
/* Ueber die ganze Kartenhoehe waere das Fenster hier ein Strich - also ein
|
||
festes Seitenverhaeltnis, oben ausgerichtet. */
|
||
.rf .rf-fenster { align-self: start; height: auto; aspect-ratio: 9 / 16; min-height: 0; }
|
||
.rf .rf-behang .rf-kopf-zeile { flex-wrap: wrap; row-gap: .15rem; }
|
||
.rf .rf-behang .rf-kopf-zeile > b { flex: 1 1 calc(100% - 2.5rem); }
|
||
.rf .rf-behang .rf-kopf-zeile .rf-pille { order: 3; margin-left: 0; }
|
||
.rf .rf-fahrt button { padding: 0 .4rem; }
|
||
.rf .rf-reihe { grid-template-columns: 1fr; gap: .2rem; }
|
||
.rf .rf-heiz { grid-template-columns: 1fr; justify-items: center; }
|
||
.rf .rf-heiz-rechts { width: 100%; }
|
||
}
|
||
|
||
/* --- 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) und sind schwarz wie am Auto. Unter zwei
|
||
getoenten Flaechen bleibt davon nicht viel uebrig, vorn unter der Haube fast
|
||
nichts - das ist so gewollt. Von oben saehe man die Reifen ohnehin nicht;
|
||
sie stehen im Bild, damit die Achsen einen Ort haben, nicht damit man sie
|
||
liest. */
|
||
.skoda-auto .rad rect { fill: rgba(14, 16, 19, 0.95); }
|
||
.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 .kw-format {
|
||
width: auto;
|
||
font-size: .78rem;
|
||
padding-top: .1rem;
|
||
padding-bottom: .1rem;
|
||
}
|
||
.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 var(--font-anzeige);
|
||
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; }
|
||
|
||
/* ===========================================================================
|
||
Einstellungen -> Grundriss (js/solar/grundriss.js)
|
||
|
||
Links der Plan, rechts die Formulare. Die Kachel im Plan sieht aus wie auf
|
||
der Startseite (restricted/home.php): dunkles Rechteck, weisse Schrift -
|
||
nur ohne Messwerte, dafuer mit Rand, wenn sie gewaehlt ist.
|
||
=========================================================================== */
|
||
.gr-etagen {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: .4rem;
|
||
margin-bottom: .9rem;
|
||
}
|
||
/* Eine Klasse mehr als Bootstrap: solar.css laedt vor AdminLTE. */
|
||
.gr-etagen .btn.gr-etage {
|
||
display: inline-flex;
|
||
align-items: baseline;
|
||
gap: .4rem;
|
||
border: 1px solid var(--ton-linie-satt, rgba(138, 148, 158, .38));
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
}
|
||
.gr-etagen .btn.gr-etage.aktiv {
|
||
border-color: #00788F;
|
||
color: var(--ton-schrift, #e8ede9);
|
||
background: rgba(0, 120, 143, .18);
|
||
}
|
||
.gr-etage-code { font: 600 .9rem var(--font-anzeige); }
|
||
.gr-etage-name { font-size: .75rem; }
|
||
.gr-etage-std { font-size: .65rem; color: var(--ton-sonne, #f0b429); }
|
||
|
||
.gr-plan-huelle {
|
||
position: relative;
|
||
border-radius: var(--ton-radius-klein, .5rem);
|
||
overflow: hidden;
|
||
background: #0b0d10;
|
||
}
|
||
.gr-plan-huelle.platzieren .gr-plan { cursor: crosshair; }
|
||
.gr-plan-leer {
|
||
aspect-ratio: 4 / 3;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 2rem;
|
||
text-align: center;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
font-size: .85rem;
|
||
}
|
||
.gr-plan {
|
||
display: block;
|
||
width: 100%;
|
||
height: auto;
|
||
touch-action: none;
|
||
user-select: none;
|
||
}
|
||
.gr-ohne-bild {
|
||
fill: var(--ton-schrift-3, #6f7a81);
|
||
font: 12px sans-serif;
|
||
text-anchor: middle;
|
||
}
|
||
.gr-kachel { cursor: grab; }
|
||
.gr-kachel.zieht { cursor: grabbing; }
|
||
.gr-kachel rect {
|
||
fill: #0006;
|
||
stroke: #ffffff55;
|
||
stroke-width: .5;
|
||
}
|
||
.gr-kachel:hover rect { stroke: #ffffffaa; }
|
||
.gr-kachel.gewaehlt rect { stroke: var(--ton-sonne, #f0b429); stroke-width: 1; }
|
||
.gr-kachel text {
|
||
fill: #fff;
|
||
font: 4.8px sans-serif;
|
||
text-anchor: middle;
|
||
pointer-events: none;
|
||
}
|
||
.gr-geist rect {
|
||
fill: rgba(240, 180, 41, .28);
|
||
stroke: var(--ton-sonne, #f0b429);
|
||
stroke-width: .8;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.gr-block {
|
||
border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||
border-radius: var(--ton-radius-klein, .5rem);
|
||
padding: .6rem .75rem;
|
||
margin-bottom: .6rem;
|
||
}
|
||
.gr-block-titel {
|
||
font-size: .7rem;
|
||
letter-spacing: .13em;
|
||
text-transform: uppercase;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
margin-bottom: .35rem;
|
||
}
|
||
.gr-knoepfe {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: .35rem;
|
||
margin-top: .6rem;
|
||
}
|
||
/* Papierkorb wie in der Geraetetafel: erst rot, wenn man ihn anfasst. */
|
||
.gr-knoepfe .btn.gr-etage-weg,
|
||
.gr-knoepfe .btn.gr-raum-weg {
|
||
margin-left: auto;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
}
|
||
.gr-knoepfe .btn.gr-etage-weg:hover,
|
||
.gr-knoepfe .btn.gr-raum-weg:hover { color: var(--ton-schlecht, #e06060); }
|
||
|
||
.gr-raeume { display: flex; flex-direction: column; gap: .15rem; }
|
||
.gr-raum {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: .4rem;
|
||
padding: .1rem .3rem;
|
||
border-radius: .35rem;
|
||
}
|
||
.gr-raum.gewaehlt { background: rgba(240, 180, 41, .12); }
|
||
.gr-raum-name {
|
||
flex: 1 1 auto;
|
||
background: none;
|
||
border: 0;
|
||
padding: .2rem 0;
|
||
color: inherit;
|
||
font: inherit;
|
||
font-size: .88rem;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
}
|
||
.gr-raum-stand { color: var(--ton-schrift-3, #6f7a81); font-size: .8rem; }
|
||
.gr-raum .btn.gr-platzieren { padding: 0 .45rem; font-size: .75rem; }
|
||
|
||
/* ===========================================================================
|
||
Automatismen als Zeitleiste (js/solar/zeitleiste.js)
|
||
|
||
Eine Bahn je Geraeteart, die Spur ist der Tag von 0 bis 24 Uhr. Die Nacht
|
||
liegt als leichter Schatten dahinter, jetzt ist eine duenne Linie in der
|
||
Sonnenfarbe. Jede Bahn traegt ihre Akzentfarbe als --zl-farbe; Punkte,
|
||
Balken und Etiketten nehmen sie auf.
|
||
=========================================================================== */
|
||
.zl {
|
||
--zl-linie: var(--ton-linie, rgba(138, 148, 158, .2));
|
||
--zl-farbe: #9aa6ad;
|
||
--zl-farbe-rgb: 154, 166, 173;
|
||
}
|
||
.zl-bahn-licht { --zl-farbe: #f0b429; --zl-farbe-rgb: 240, 180, 41; }
|
||
.zl-bahn-beschattung { --zl-farbe: #5fb0dc; --zl-farbe-rgb: 95, 176, 220; }
|
||
.zl-bahn-heizung { --zl-farbe: #e8836a; --zl-farbe-rgb: 232, 131, 106; }
|
||
.zl-bahn-bewaesserung { --zl-farbe: #4cc18a; --zl-farbe-rgb: 76, 193, 138; }
|
||
.zl-bahn-schalter { --zl-farbe: #b59cf0; --zl-farbe-rgb: 181, 156, 240; }
|
||
|
||
/* Kopf */
|
||
.zl-kopf {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: .6rem 1rem;
|
||
margin-bottom: .9rem;
|
||
}
|
||
.zl-tag .btn.zl-tag-name { min-width: 9.5rem; font-variant-numeric: tabular-nums; }
|
||
.zl-etagen { display: flex; flex-wrap: wrap; gap: .3rem; }
|
||
.zl-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: .35rem;
|
||
padding: .2rem .65rem;
|
||
border: 1px solid var(--zl-linie);
|
||
border-radius: 999px;
|
||
background: transparent;
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
font: 500 .8rem var(--font-anzeige, inherit);
|
||
cursor: pointer;
|
||
transition: background .15s, border-color .15s, color .15s;
|
||
}
|
||
.zl-chip:hover { border-color: var(--ton-linie-satt, rgba(138, 148, 158, .38)); color: var(--ton-schrift, #e8ede9); }
|
||
.zl-chip.an {
|
||
background: rgba(0, 120, 143, .22);
|
||
border-color: #00788F;
|
||
color: var(--ton-schrift, #e8ede9);
|
||
}
|
||
.zl-chip.leer { opacity: .55; }
|
||
.zl-chip-zahl {
|
||
font-size: .68rem;
|
||
padding: 0 .35rem;
|
||
border-radius: 999px;
|
||
background: rgba(138, 148, 158, .18);
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
}
|
||
.zl-zahl {
|
||
margin-left: auto;
|
||
font-size: .8rem;
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
white-space: nowrap;
|
||
}
|
||
.zl-zahl-leise { color: var(--ton-schrift-3, #6f7a81); }
|
||
|
||
/* Raster */
|
||
.zl-rahmen {
|
||
overflow-x: auto;
|
||
border-radius: var(--ton-radius-klein, .5rem);
|
||
}
|
||
.zl-raster { position: relative; }
|
||
.zl-zeile {
|
||
display: grid;
|
||
grid-template-columns: var(--zl-kopf) minmax(0, 1fr);
|
||
}
|
||
.zl-bahn .zl-spur { border-top: 1px solid var(--zl-linie); }
|
||
.zl-bahn-kopf {
|
||
position: sticky;
|
||
left: 0;
|
||
z-index: 3;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: .45rem;
|
||
padding: .6rem .6rem 0 0;
|
||
background: var(--ton-flaeche, #23282c);
|
||
font: 500 .82rem var(--font-anzeige, inherit);
|
||
color: var(--ton-schrift, #e8ede9);
|
||
}
|
||
.zl-bahn-kopf .bi { color: var(--zl-farbe); font-size: .95rem; line-height: 1.1; }
|
||
/* Schmal nur das Symbol; der Name steht im Hinweis beim Antippen der Eintraege. */
|
||
.zl-rahmen.schmal .zl-bahn-kopf { justify-content: center; padding-right: 0; }
|
||
.zl-rahmen.schmal .zl-bahn-kopf span { display: none; }
|
||
.zl-bahn-zahl {
|
||
margin-left: auto;
|
||
font-size: .68rem;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
}
|
||
.zl-spur {
|
||
position: relative;
|
||
min-height: 38px;
|
||
/* Alle drei Stunden eine Linie, jede volle Stunde ein Hauch. */
|
||
background-image:
|
||
linear-gradient(to right, rgba(138, 148, 158, .16) 1px, transparent 1px),
|
||
linear-gradient(to right, rgba(138, 148, 158, .06) 1px, transparent 1px);
|
||
background-size: 12.5% 100%, 4.1667% 100%;
|
||
}
|
||
.zl-nacht {
|
||
position: absolute;
|
||
top: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, .24);
|
||
pointer-events: none;
|
||
}
|
||
.zl-jetzt {
|
||
position: absolute;
|
||
top: 0;
|
||
bottom: 0;
|
||
width: 0;
|
||
border-left: 1.5px solid var(--ton-sonne, #f0b429);
|
||
opacity: .8;
|
||
z-index: 2;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* Achse */
|
||
.zl-achse .zl-bahn-kopf { padding-top: 0; }
|
||
.zl-achse .zl-spur { height: 26px; min-height: 0; background: none; }
|
||
.zl-stunde {
|
||
position: absolute;
|
||
bottom: 4px;
|
||
transform: translateX(-50%);
|
||
font-size: .7rem;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.zl-stunde.anfang { transform: none; }
|
||
.zl-stunde.ende { transform: translateX(-100%); }
|
||
.zl-sonne {
|
||
position: absolute;
|
||
top: -2px;
|
||
transform: translateX(-50%);
|
||
font-size: .78rem;
|
||
color: var(--ton-sonne, #f0b429);
|
||
opacity: .75;
|
||
cursor: help;
|
||
}
|
||
.zl-jetzt-marke {
|
||
position: absolute;
|
||
top: 1px;
|
||
transform: translateX(-50%);
|
||
padding: 0 .35rem;
|
||
border-radius: 999px;
|
||
background: var(--ton-sonne, #f0b429);
|
||
color: #1b1f22;
|
||
font: 600 .66rem var(--font-anzeige, inherit);
|
||
z-index: 2;
|
||
}
|
||
|
||
/* Eintraege */
|
||
.zl-ding {
|
||
position: absolute;
|
||
height: 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
z-index: 1;
|
||
}
|
||
.zl-ding:hover { z-index: 4; }
|
||
.zl-marke {
|
||
flex: none;
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: 50%;
|
||
border: 2px solid var(--zl-farbe);
|
||
background: var(--ton-flaeche, #23282c);
|
||
box-sizing: border-box;
|
||
}
|
||
.zl-punkt { transform: translateX(-6px); }
|
||
.zl-punkt.links { flex-direction: row-reverse; transform: translateX(calc(-100% + 6px)); }
|
||
.zl-etikett {
|
||
margin-left: 6px;
|
||
padding: .1rem .5rem;
|
||
border-radius: 6px;
|
||
border: 1px solid transparent;
|
||
background: rgba(var(--zl-farbe-rgb), .1);
|
||
color: var(--ton-schrift, #e8ede9);
|
||
font-size: .75rem;
|
||
line-height: 1.35;
|
||
white-space: nowrap;
|
||
transition: background .15s, border-color .15s;
|
||
}
|
||
.zl-punkt.links .zl-etikett { margin-left: 0; margin-right: 6px; }
|
||
.zl-etikett b {
|
||
font-weight: 600;
|
||
margin-right: .4rem;
|
||
color: var(--zl-farbe);
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.zl-etikett .bi-check2 { color: var(--ton-gut, #4caf7d); }
|
||
.zl-ding:hover .zl-etikett {
|
||
background: rgba(var(--zl-farbe-rgb), .2);
|
||
border-color: rgba(var(--zl-farbe-rgb), .45);
|
||
}
|
||
|
||
/* Zustaende */
|
||
.zl-ding.gelaufen .zl-marke { background: var(--zl-farbe); }
|
||
.zl-ding.vorbei { opacity: .5; }
|
||
.zl-ding.vorbei .zl-etikett b { color: var(--ton-schrift-2, #9aa6ad); }
|
||
.zl-ding.aktiv .zl-marke { box-shadow: 0 0 0 3px rgba(var(--zl-farbe-rgb), .25); }
|
||
/* Nicht dran: statt eines gestrichelten Kreises nur ein kleiner blasser Punkt
|
||
dicht am Etikett - das Kalender-Symbol darin sagt schon, was los ist. Die
|
||
Marke behaelt ihre 12px, damit Zeit, Stapeln und Kettenlinien stimmen. */
|
||
.zl-ding.nichtdran .zl-marke {
|
||
border: 0;
|
||
background: radial-gradient(circle, var(--ton-schrift-3, #6f7a81) 2.5px, transparent 3px);
|
||
}
|
||
.zl-punkt.nichtdran .zl-etikett { margin-left: 1px; }
|
||
.zl-punkt.nichtdran.links .zl-etikett { margin-left: 0; margin-right: 1px; }
|
||
.zl-ding.nichtdran .zl-etikett {
|
||
background: transparent;
|
||
border: 1px dashed var(--zl-linie);
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
}
|
||
.zl-ding.nichtdran .zl-etikett b { color: var(--ton-schrift-3, #6f7a81); }
|
||
.zl-nichtdran {
|
||
margin-right: .35rem;
|
||
font-size: .72rem;
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
}
|
||
|
||
/* Zeitfenster: der Balken traegt Laeufe und die frueheste Marke. */
|
||
.zl-fenster { min-width: 10px; }
|
||
.zl-balken {
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
top: 8px;
|
||
height: 8px;
|
||
border-radius: 4px;
|
||
background: rgba(var(--zl-farbe-rgb), .22);
|
||
border: 1px solid rgba(var(--zl-farbe-rgb), .4);
|
||
}
|
||
.zl-fenster .zl-etikett {
|
||
position: relative;
|
||
margin-left: 0;
|
||
background: var(--ton-flaeche, #23282c);
|
||
border-color: rgba(var(--zl-farbe-rgb), .3);
|
||
}
|
||
/* Reicht der Platz bis zum rechten Rand nicht, wird der Name gekuerzt. */
|
||
.zl-etikett.gekappt {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.zl-lauf {
|
||
margin-left: .25rem;
|
||
color: var(--ton-gut, #4caf7d);
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.zl-fenster.nichtdran .zl-balken { background: transparent; border-style: dashed; border-color: var(--zl-linie); }
|
||
.zl-marke-innen {
|
||
position: absolute;
|
||
top: 50%;
|
||
width: 10px;
|
||
height: 10px;
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
|
||
/* Ketten */
|
||
.zl-ketten {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
overflow: visible;
|
||
}
|
||
/* Die Linie liegt ueber dem Raster, aber unter den Etiketten. Ein dunkler
|
||
Grund darunter trennt sie von den Stundenlinien, sonst verschwindet sie
|
||
dort, wo sie eine kreuzt. */
|
||
.zl-ketten .zl-kette-grund {
|
||
fill: none;
|
||
stroke: var(--ton-flaeche, #23282c);
|
||
stroke-width: 4;
|
||
opacity: .7;
|
||
}
|
||
.zl-ketten .zl-kette {
|
||
fill: none;
|
||
stroke: rgba(214, 222, 227, .72);
|
||
stroke-width: 1.6;
|
||
stroke-dasharray: 4 3;
|
||
transition: stroke .15s;
|
||
}
|
||
.zl-ketten .zl-kette-ende { fill: rgba(214, 222, 227, .85); transition: fill .15s; }
|
||
.zl-ketten .zl-kette.hell { stroke: var(--ton-sonne, #f0b429); stroke-dasharray: none; }
|
||
.zl-ketten .zl-kette-ende.hell { fill: var(--ton-sonne, #f0b429); }
|
||
|
||
.zl-leer {
|
||
padding: 1.2rem 0 .6rem 132px;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
font-size: .85rem;
|
||
}
|
||
|
||
/* Baender */
|
||
.zl-baender {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: .45rem;
|
||
margin-top: .8rem;
|
||
padding-top: .7rem;
|
||
border-top: 1px solid var(--zl-linie);
|
||
}
|
||
.zl-band {
|
||
display: grid;
|
||
grid-template-columns: 132px minmax(0, 1fr);
|
||
align-items: start;
|
||
}
|
||
.zl-band-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
|
||
@media (max-width: 575.98px) {
|
||
.zl-band { grid-template-columns: minmax(0, 1fr); gap: .3rem; }
|
||
.zl-zahl { margin-left: 0; }
|
||
}
|
||
.zl-band-titel {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: .4rem;
|
||
padding-top: .2rem;
|
||
font: 500 .82rem var(--font-anzeige, inherit);
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
}
|
||
.zl-band-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: .4rem;
|
||
padding: .2rem .6rem;
|
||
border-radius: 6px;
|
||
border: 1px solid var(--zl-linie);
|
||
background: rgba(138, 148, 158, .07);
|
||
color: var(--ton-schrift, #e8ede9);
|
||
font-size: .75rem;
|
||
cursor: pointer;
|
||
}
|
||
.zl-band-chip:hover { border-color: var(--ton-linie-satt, rgba(138, 148, 158, .38)); }
|
||
.zl-band-pause .zl-band-chip { color: var(--ton-schrift-2, #9aa6ad); }
|
||
.zl-band-chip.nichtdran { border-style: dashed; }
|
||
.zl-band-etage {
|
||
font-size: .64rem;
|
||
padding: 0 .3rem;
|
||
border-radius: 4px;
|
||
background: rgba(138, 148, 158, .16);
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
}
|
||
|
||
/* Legende */
|
||
.zl-legende {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: .4rem 1.1rem;
|
||
margin-top: .8rem;
|
||
font-size: .72rem;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
}
|
||
.zl-legende span { display: inline-flex; align-items: center; gap: .4rem; }
|
||
.zl-legende i { display: inline-block; }
|
||
.zl-l-punkt { width: 10px; height: 10px; border-radius: 50%; border: 2px solid #5fb0dc; }
|
||
.zl-l-punkt.gelaufen { background: #5fb0dc; }
|
||
.zl-l-punkt.nichtdran { border-style: dashed; border-color: var(--ton-schrift-3, #6f7a81); }
|
||
.zl-l-balken { width: 22px; height: 7px; border-radius: 4px; background: rgba(95, 176, 220, .22); border: 1px solid rgba(95, 176, 220, .4); }
|
||
.zl-l-kette { width: 22px; border-top: 1.2px dashed rgba(154, 166, 173, .7); }
|
||
|
||
/* Karte zu einem Eintrag: schwebt ueber der Zeitleiste, Akzent der Bahn. */
|
||
.zl { position: relative; }
|
||
.zl-karte {
|
||
position: absolute;
|
||
z-index: 20;
|
||
width: min(22rem, 100%);
|
||
padding: .7rem .85rem .75rem;
|
||
border-radius: var(--ton-radius-klein, .5rem);
|
||
border: 1px solid rgba(var(--zl-farbe-rgb), .45);
|
||
border-top: 3px solid var(--zl-farbe);
|
||
background: var(--ton-flaeche-2, #2b3237);
|
||
box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
|
||
font-size: .8rem;
|
||
}
|
||
.zl-karte-kopf {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: .45rem;
|
||
margin-bottom: .45rem;
|
||
}
|
||
.zl-karte-kopf .bi { color: var(--zl-farbe); }
|
||
.zl-karte-name {
|
||
flex: 1 1 auto;
|
||
font: 500 .92rem var(--font-anzeige, inherit);
|
||
color: var(--ton-schrift, #e8ede9);
|
||
}
|
||
.zl-karte .btn-close.zl-karte-zu { font-size: .6rem; opacity: .6; }
|
||
.zl-karte-zeile {
|
||
display: flex;
|
||
gap: .5rem;
|
||
align-items: baseline;
|
||
padding: .12rem 0;
|
||
color: var(--ton-schrift, #e8ede9);
|
||
}
|
||
.zl-karte-zeile .bi { color: var(--ton-schrift-3, #6f7a81); flex: none; }
|
||
.zl-karte-stand.gut, .zl-karte-stand.gut .bi { color: var(--ton-gut, #4caf7d); }
|
||
.zl-karte-stand.leise { color: var(--ton-schrift-2, #9aa6ad); }
|
||
.zl-karte-wenn {
|
||
margin-top: .35rem;
|
||
padding-top: .35rem;
|
||
border-top: 1px solid var(--zl-linie);
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
font-size: .72rem;
|
||
line-height: 1.4;
|
||
max-height: 5.6em;
|
||
overflow: auto;
|
||
}
|
||
.zl-karte-knoepfe {
|
||
display: flex;
|
||
gap: .35rem;
|
||
margin-top: .65rem;
|
||
}
|
||
.zl-karte-knoepfe .btn.zl-karte-weg {
|
||
margin-left: auto;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
}
|
||
.zl-karte-knoepfe .btn.zl-karte-weg:hover { color: var(--ton-schlecht, #e06060); }
|
||
|
||
/* ===========================================================================
|
||
Einfuehrung (restricted/einfuehrung.php, js/solar/einfuehrung.js)
|
||
|
||
Eine Folie: links das Bild in einem ruhigen Rahmen (Handy-Aufnahmen
|
||
schmal wie ein Telefon, Desktop-Aufnahmen breit), rechts der Text mit den
|
||
nummerierten Erklaerungen. Auf schmalen Schirmen untereinander.
|
||
=========================================================================== */
|
||
.ef {
|
||
max-width: 1180px;
|
||
margin: 0 auto 2rem;
|
||
outline: none;
|
||
}
|
||
.ef-kopf {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: .6rem 1rem;
|
||
margin-bottom: .6rem;
|
||
}
|
||
.ef-teile { display: flex; gap: .35rem; flex-wrap: wrap; }
|
||
.ef-teil {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: .5rem;
|
||
padding: .3rem .8rem .3rem .35rem;
|
||
border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||
border-radius: 999px;
|
||
background: transparent;
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
font: 500 .85rem var(--font-anzeige, inherit);
|
||
cursor: pointer;
|
||
transition: background .15s, border-color .15s, color .15s;
|
||
}
|
||
.ef-teil-nr {
|
||
display: inline-grid;
|
||
place-items: center;
|
||
width: 1.5rem;
|
||
height: 1.5rem;
|
||
border-radius: 50%;
|
||
background: rgba(138, 148, 158, .18);
|
||
font-size: .75rem;
|
||
}
|
||
.ef-teil.aktiv {
|
||
border-color: var(--ton-sonne, #f0b429);
|
||
color: var(--ton-schrift, #e8ede9);
|
||
background: rgba(var(--ton-sonne-rgb, 240, 180, 41), .1);
|
||
}
|
||
.ef-teil.aktiv .ef-teil-nr { background: var(--ton-sonne, #f0b429); color: #1b1f22; }
|
||
.ef-kopf .form-select.ef-kapitel { width: auto; min-width: 12rem; margin-left: auto; }
|
||
.ef-zaehler {
|
||
font-size: .8rem;
|
||
color: var(--ton-schrift-3, #6f7a81);
|
||
font-variant-numeric: tabular-nums;
|
||
min-width: 3.5rem;
|
||
text-align: right;
|
||
}
|
||
.ef-fortschritt {
|
||
height: 3px;
|
||
border-radius: 2px;
|
||
background: var(--ton-linie, rgba(138, 148, 158, .2));
|
||
margin-bottom: 1.2rem;
|
||
overflow: hidden;
|
||
}
|
||
.ef-fortschritt span {
|
||
display: block;
|
||
height: 100%;
|
||
width: 0;
|
||
background: var(--ton-sonne, #f0b429);
|
||
transition: width .35s ease;
|
||
}
|
||
|
||
/* Buehne und Folie */
|
||
.ef-buehne { position: relative; }
|
||
.ef-folie {
|
||
display: grid;
|
||
gap: 2rem;
|
||
align-items: center;
|
||
padding: 1.6rem;
|
||
border-radius: var(--ton-radius, .875rem);
|
||
background: var(--ton-flaeche, #23282c);
|
||
border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||
min-height: 34rem;
|
||
}
|
||
.ef-folie.mit-bild.form-handy { grid-template-columns: minmax(0, 330px) minmax(0, 1fr); }
|
||
.ef-folie.mit-bild.form-breit { grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); }
|
||
.ef-folie.ohne-bild { grid-template-columns: minmax(0, 46rem); justify-content: center; }
|
||
.ef-folie.rein-vor { animation: ef-rein-vor .32s ease both; }
|
||
.ef-folie.rein-rueck { animation: ef-rein-rueck .32s ease both; }
|
||
@keyframes ef-rein-vor { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }
|
||
@keyframes ef-rein-rueck { from { opacity: 0; transform: translateX(-18px); } to { opacity: 1; transform: none; } }
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.ef-folie.rein-vor, .ef-folie.rein-rueck { animation: none; }
|
||
}
|
||
|
||
.ef-bild { margin: 0; justify-self: center; width: 100%; }
|
||
.ef-rahmen {
|
||
position: relative;
|
||
border-radius: 14px;
|
||
overflow: visible;
|
||
box-shadow: 0 18px 40px rgba(0, 0, 0, .35);
|
||
}
|
||
.ef-rahmen img {
|
||
display: block;
|
||
width: 100%;
|
||
height: auto;
|
||
border-radius: 14px;
|
||
border: 1px solid var(--ton-linie-satt, rgba(138, 148, 158, .38));
|
||
}
|
||
/* Handy-Aufnahmen in einem angedeuteten Telefon. */
|
||
.form-handy .ef-rahmen {
|
||
max-width: 330px;
|
||
margin: 0 auto;
|
||
padding: 10px;
|
||
border-radius: 30px;
|
||
background: #0d0f11;
|
||
border: 1px solid rgba(138, 148, 158, .3);
|
||
}
|
||
.form-handy .ef-rahmen img { border-radius: 22px; border: 0; }
|
||
|
||
/* Die nummerierten Punkte im Bild */
|
||
.ef-marke {
|
||
position: absolute;
|
||
transform: translate(-50%, -50%);
|
||
display: grid;
|
||
place-items: center;
|
||
width: 26px;
|
||
height: 26px;
|
||
border-radius: 50%;
|
||
background: var(--ton-sonne, #f0b429);
|
||
color: #1b1f22;
|
||
font: 700 .8rem var(--font-anzeige, inherit);
|
||
box-shadow: 0 0 0 3px rgba(27, 31, 34, .85), 0 4px 10px rgba(0, 0, 0, .45);
|
||
cursor: pointer;
|
||
z-index: 2;
|
||
transition: transform .15s ease, box-shadow .15s ease;
|
||
}
|
||
.ef-marke::after {
|
||
content: "";
|
||
position: absolute;
|
||
inset: -6px;
|
||
border-radius: 50%;
|
||
border: 2px solid rgba(var(--ton-sonne-rgb, 240, 180, 41), .55);
|
||
animation: ef-puls 2.4s ease-out infinite;
|
||
}
|
||
.ef-marke.hell { transform: translate(-50%, -50%) scale(1.25); box-shadow: 0 0 0 3px rgba(27, 31, 34, .85), 0 0 0 8px rgba(var(--ton-sonne-rgb, 240, 180, 41), .35); }
|
||
@keyframes ef-puls { 0% { transform: scale(.8); opacity: .9; } 70%, 100% { transform: scale(1.5); opacity: 0; } }
|
||
@media (prefers-reduced-motion: reduce) { .ef-marke::after { animation: none; opacity: 0; } }
|
||
|
||
/* Text */
|
||
.ef-kapitelname {
|
||
font-size: .72rem;
|
||
letter-spacing: .12em;
|
||
text-transform: uppercase;
|
||
color: var(--ton-sonne, #f0b429);
|
||
margin-bottom: .4rem;
|
||
}
|
||
.ef-titel {
|
||
font: 600 1.7rem/1.2 var(--font-anzeige, inherit);
|
||
color: var(--ton-schrift, #e8ede9);
|
||
margin: 0 0 .8rem;
|
||
}
|
||
.ef-einleitung {
|
||
font-size: 1.02rem;
|
||
line-height: 1.6;
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
margin-bottom: 1.1rem;
|
||
}
|
||
.ef-einleitung b, .ef-marken b, .ef-punkte b, .ef-tipp b { color: var(--ton-schrift, #e8ede9); font-weight: 600; }
|
||
.ef-marken {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0 0 1rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: .35rem;
|
||
}
|
||
.ef-marken li {
|
||
display: flex;
|
||
gap: .7rem;
|
||
align-items: flex-start;
|
||
padding: .45rem .6rem;
|
||
border-radius: 10px;
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
line-height: 1.5;
|
||
cursor: pointer;
|
||
transition: background .15s;
|
||
}
|
||
.ef-marken li:hover, .ef-marken li.hell { background: rgba(var(--ton-sonne-rgb, 240, 180, 41), .09); }
|
||
.ef-marke-nr {
|
||
flex: none;
|
||
display: grid;
|
||
place-items: center;
|
||
width: 22px;
|
||
height: 22px;
|
||
margin-top: 1px;
|
||
border-radius: 50%;
|
||
background: var(--ton-sonne, #f0b429);
|
||
color: #1b1f22;
|
||
font: 700 .72rem var(--font-anzeige, inherit);
|
||
}
|
||
.ef-punkte {
|
||
padding-left: 1.1rem;
|
||
margin: 0 0 1rem;
|
||
color: var(--ton-schrift-2, #9aa6ad);
|
||
line-height: 1.6;
|
||
}
|
||
.ef-punkte li { margin-bottom: .45rem; }
|
||
.ef-punkte li::marker { color: var(--ton-sonne, #f0b429); }
|
||
.ef-tipp {
|
||
display: flex;
|
||
gap: .6rem;
|
||
align-items: flex-start;
|
||
margin: .4rem 0 0;
|
||
padding: .7rem .9rem;
|
||
border-radius: 10px;
|
||
background: rgba(0, 120, 143, .14);
|
||
border: 1px solid rgba(0, 120, 143, .35);
|
||
color: var(--ton-schrift, #e8ede9);
|
||
font-size: .92rem;
|
||
line-height: 1.5;
|
||
}
|
||
.ef-tipp .bi { color: #35b6cf; margin-top: .1rem; }
|
||
|
||
/* Fuss */
|
||
.ef-fuss {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
margin-top: 1rem;
|
||
}
|
||
.ef-punkte-nav {
|
||
flex: 1 1 auto;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
gap: 5px;
|
||
}
|
||
.ef-punkt {
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background: rgba(138, 148, 158, .3);
|
||
cursor: pointer;
|
||
transition: background .15s, transform .15s;
|
||
}
|
||
.ef-punkt.neuer-teil { margin-left: 10px; }
|
||
.ef-punkt.aktiv { background: var(--ton-sonne, #f0b429); transform: scale(1.35); }
|
||
|
||
@media (max-width: 991.98px) {
|
||
.ef-folie.mit-bild.form-handy,
|
||
.ef-folie.mit-bild.form-breit { grid-template-columns: minmax(0, 1fr); gap: 1.4rem; }
|
||
.ef-folie { padding: 1rem; min-height: 0; }
|
||
.form-handy .ef-rahmen { max-width: 280px; }
|
||
.ef-titel { font-size: 1.4rem; }
|
||
.ef-kopf .form-select.ef-kapitel { margin-left: 0; flex: 1 1 12rem; }
|
||
.ef-punkte-nav { display: none; }
|
||
.ef-fuss { justify-content: space-between; position: sticky; bottom: 0; padding: .6rem 0; background: var(--ton-grund, #191d20); z-index: 5; }
|
||
}
|
||
|
||
/* Ansicht umschalten: eine Klasse mehr als Bootstrap (solar.css laedt vorher). */
|
||
.zl-ansicht .btn.active {
|
||
background: rgba(0, 120, 143, .25);
|
||
border-color: #00788F;
|
||
color: var(--ton-schrift, #e8ede9);
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Energiefluss-Übersicht (js/solar/energiefluss.js, Katalog in
|
||
js/solar/energieflussKatalog.js).
|
||
|
||
Farben je Kreis kommen als --farbe aus dem Katalog, Breite und Tempo der
|
||
Flüsse als --breite/--dauer aus dem Renderer. Alles Übrige steht hier.
|
||
Transformationen liegen nie auf Elementen mit transform-Attribut (Kreis-
|
||
gruppe, Plakette) - CSS würde deren Lage überschreiben.
|
||
========================================================================== */
|
||
.enf-behaelter { position: relative; }
|
||
svg.enf {
|
||
display: block; width: 100%; height: auto; max-height: 80vh;
|
||
font-family: "Poppins", system-ui, sans-serif;
|
||
user-select: none; -webkit-tap-highlight-color: transparent;
|
||
}
|
||
svg.enf.enf-hoch { max-height: none; }
|
||
|
||
/* --- Kreis ------------------------------------------------------------- */
|
||
.enf .enf-hof { fill: #1c2024; stroke: rgba(255, 255, 255, .06); stroke-width: 1.5; transition: stroke .3s, stroke-width .3s; }
|
||
.enf .enf-spur { fill: none; stroke: #2b3139; stroke-width: 14; }
|
||
.enf .enf-bogen {
|
||
fill: none; stroke-width: 14; stroke-dasharray: 0 100;
|
||
transition: stroke-dasharray 1s cubic-bezier(.2, .7, .2, 1), stroke-dashoffset 1s cubic-bezier(.2, .7, .2, 1), stroke .4s;
|
||
}
|
||
.enf .enf-scheibe { fill: #20252b; }
|
||
.enf .enf-wert { fill: var(--ton-schrift, #e8ede9); font-size: 32px; font-weight: 600; text-anchor: middle; font-variant-numeric: tabular-nums; }
|
||
.enf .enf-neben { fill: var(--ton-schrift-2, #9aa6ad); font-size: 14.5px; text-anchor: middle; font-variant-numeric: tabular-nums; }
|
||
.enf .enf-name {
|
||
fill: var(--ton-schrift-2, #9aa6ad); font-size: 16px; font-weight: 600; text-anchor: middle; letter-spacing: .08em; text-transform: uppercase;
|
||
/* Kontur in Kartenfarbe: bleibt lesbar, wo ein Fluss unter dem Namen durchlaeuft. */
|
||
paint-order: stroke; stroke: var(--ton-flaeche, #23282c); stroke-width: 7px; stroke-linejoin: round;
|
||
}
|
||
|
||
.enf .enf-koerper { transform-box: view-box; transform-origin: 0 0; transition: transform .3s cubic-bezier(.2, .7, .2, 1), opacity .6s; }
|
||
.enf .enf-ruhe .enf-koerper { opacity: .6; }
|
||
.enf .enf-ruhe .enf-name { opacity: .7; }
|
||
.enf .enf-aus { opacity: .3; }
|
||
.enf .enf-aus .enf-spur { stroke-dasharray: 8 8; }
|
||
|
||
.enf .enf-klickbar { cursor: pointer; outline: none; }
|
||
.enf .enf-klickbar:hover .enf-koerper { transform: scale(1.045); }
|
||
.enf .enf-klickbar:hover .enf-hof,
|
||
.enf .enf-klickbar:focus-visible .enf-hof { stroke: var(--farbe); stroke-width: 3; }
|
||
.enf .enf-tipp circle { fill: #262c33; stroke: #3a424b; stroke-width: 1.5; }
|
||
.enf .enf-tipp path { fill: none; stroke: var(--farbe); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; transition: transform .25s; }
|
||
.enf .enf-klickbar:hover .enf-tipp path { transform: translateX(2px); }
|
||
|
||
/* --- Füllstand als Welle ------------------------------------------------ */
|
||
.enf .enf-fuellung {
|
||
--r: 67;
|
||
transform: translateY(calc(var(--r) * (1 - 2 * var(--stand)) * 1px));
|
||
transition: transform 1.4s cubic-bezier(.2, .7, .2, 1);
|
||
}
|
||
.enf .enf-welle { fill: var(--farbe); fill-opacity: .14; animation: enf-wogen 8s linear infinite; }
|
||
@keyframes enf-wogen { to { transform: translateX(calc(var(--r) * 2px)); } }
|
||
|
||
/* --- Symbole ------------------------------------------------------------ */
|
||
.enf .enf-symbol { color: var(--farbe); fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
|
||
.enf .enf-s-fein { stroke-width: 1.1; opacity: .75; }
|
||
.enf .enf-s-kern { fill: currentColor; fill-opacity: .2; transition: fill-opacity .6s; }
|
||
.enf .enf-an .enf-s-kern { fill-opacity: .55; }
|
||
.enf .enf-s-strahlen { transform-box: view-box; transform-origin: 0 0; opacity: .55; transition: opacity .6s; }
|
||
.enf .enf-an .enf-s-strahlen { opacity: 1; animation: enf-drehen 30s linear infinite; }
|
||
@keyframes enf-drehen { to { transform: rotate(360deg); } }
|
||
|
||
.enf .enf-s-stand {
|
||
fill: currentColor; stroke: none; opacity: .45;
|
||
transform-box: fill-box; transform-origin: 50% 100%;
|
||
transform: scaleY(var(--stand, 0)); transition: transform 1.2s cubic-bezier(.2, .7, .2, 1);
|
||
}
|
||
.enf .enf-s-blitz { fill: currentColor; stroke: none; opacity: 0; transition: opacity .4s; }
|
||
.enf .enf-sym-akku .enf-s-blitz { fill: #fff; }
|
||
.enf .enf-s-blitz.enf-s-an,
|
||
.enf .enf-laden .enf-s-blitz,
|
||
.enf .enf-an.enf-knoten .enf-sym-wallbox .enf-s-blitz { opacity: 1; }
|
||
.enf .enf-laden .enf-s-blitz,
|
||
.enf .enf-an .enf-sym-wallbox .enf-s-blitz { animation: enf-puls 1.8s ease-in-out infinite; }
|
||
@keyframes enf-puls { 50% { opacity: .35; } }
|
||
|
||
.enf .enf-an .enf-s-welle { animation: enf-puls 1.4s ease-in-out infinite; }
|
||
.enf .enf-s-ebene { fill: currentColor; stroke: none; opacity: .38; }
|
||
.enf .enf-an .enf-sym-wallbox .enf-s-kabel { stroke-dasharray: 2.4 2.4; animation: enf-kabel .9s linear infinite; }
|
||
@keyframes enf-kabel { to { stroke-dashoffset: -4.8; } }
|
||
.enf .enf-s-temps rect { stroke: none; fill: #2b3139; opacity: .9; transition: fill 1.5s; }
|
||
.enf .enf-s-spirale { stroke-width: 1.3; transition: stroke .4s; }
|
||
.enf .enf-an .enf-s-spirale { stroke: #ffb04a; animation: enf-gluehen 1.1s ease-in-out infinite alternate; }
|
||
@keyframes enf-gluehen { to { stroke: #ff5a2a; } }
|
||
|
||
/* --- Plaketten ---------------------------------------------------------- */
|
||
.enf .enf-plakette { animation: enf-einblenden .5s both; animation-delay: calc(var(--i) * 80ms); }
|
||
.enf .enf-plakette circle,
|
||
.enf .enf-plakette rect { fill: #1c2024; stroke: var(--pfarbe); stroke-width: 2; }
|
||
.enf .enf-plakette-glyph { font-family: bootstrap-icons; font-size: 16px; fill: var(--pfarbe); text-anchor: middle; dominant-baseline: central; }
|
||
.enf .enf-plakette-text { font-size: 14px; font-weight: 600; fill: var(--ton-schrift, #e8ede9); dominant-baseline: central; }
|
||
|
||
/* --- Bewässerung --------------------------------------------------------- */
|
||
.enf .enf-zone-glyph { font-family: bootstrap-icons; font-size: 17px; fill: currentColor; color: #6c757d; text-anchor: middle; dominant-baseline: central; transition: color .4s; }
|
||
.enf .enf-zone-bild { color: #6c757d; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; transition: color .4s; }
|
||
.enf .enf-zone-name { font-size: 15px; fill: var(--ton-schrift-2, #9aa6ad); dominant-baseline: central; }
|
||
.enf .enf-zone-status { font-size: 15px; font-weight: 600; fill: var(--ton-schrift, #e8ede9); text-anchor: end; dominant-baseline: central; font-variant-numeric: tabular-nums; }
|
||
|
||
/* --- Flüsse -------------------------------------------------------------- */
|
||
.enf .enf-bett {
|
||
fill: none; stroke: #252b31; stroke-linecap: round;
|
||
stroke-width: calc(var(--breite, 0) * 1px + 5px);
|
||
stroke-dasharray: 1 1; stroke-dashoffset: 1;
|
||
transition: stroke-width .8s;
|
||
animation: enf-zeichnen .9s cubic-bezier(.5, 0, .2, 1) forwards; animation-delay: var(--verz);
|
||
}
|
||
@keyframes enf-zeichnen { to { stroke-dashoffset: 0; } }
|
||
.enf .enf-strom,
|
||
.enf .enf-strom-hof {
|
||
fill: none; stroke: var(--farbe); stroke-linecap: round;
|
||
stroke-dasharray: 0 20;
|
||
/* Stufen statt stetig: stroke-dashoffset laeuft nicht auf dem Compositor,
|
||
jede Stufe ist ein Neuzeichnen. 20 je Abschnitt sehen fluessig aus. */
|
||
/* Dauer fest 1 s; das Tempo je Fluss setzt energiefluss.js über playbackRate. */
|
||
animation: enf-fliessen 1s steps(20) infinite;
|
||
transition: stroke-width .8s, opacity .6s;
|
||
}
|
||
.enf .enf-strom { stroke-width: calc(var(--breite, 0) * 1px); }
|
||
.enf .enf-strom-hof { stroke-width: calc(var(--breite, 0) * 1.9px); opacity: .14; }
|
||
.enf .enf-rueck .enf-strom,
|
||
.enf .enf-rueck .enf-strom-hof { animation-direction: reverse; }
|
||
.enf .enf-still .enf-strom,
|
||
.enf .enf-still .enf-strom-hof { opacity: 0; animation: none; }
|
||
@keyframes enf-fliessen { to { stroke-dashoffset: -20; } }
|
||
|
||
/* --- Auftritt ------------------------------------------------------------ */
|
||
.enf .enf-koerper { animation: enf-erscheinen .7s cubic-bezier(.2, .9, .3, 1.25) backwards; animation-delay: var(--verz); }
|
||
.enf .enf-name { animation: enf-einblenden .7s backwards; animation-delay: calc(var(--verz) + 150ms); }
|
||
@keyframes enf-erscheinen { from { opacity: 0; transform: scale(.55); } }
|
||
@keyframes enf-einblenden { from { opacity: 0; } }
|
||
|
||
.enf.enf-pause,
|
||
.enf.enf-pause * { animation-play-state: paused !important; }
|
||
|
||
/* --- Bearbeiten (Einstellungen) ------------------------------------------ */
|
||
.enf.enf-bearbeiten .enf-koerper,
|
||
.enf.enf-bearbeiten .enf-name,
|
||
.enf.enf-bearbeiten .enf-bett { animation: none; stroke-dashoffset: 0; }
|
||
.enf.enf-bearbeiten .enf-ziehbar { cursor: grab; touch-action: none; }
|
||
.enf.enf-bearbeiten .enf-zieht { cursor: grabbing; }
|
||
.enf.enf-bearbeiten .enf-zieht .enf-hof { stroke: var(--farbe); stroke-width: 3; }
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.enf, .enf * { animation: none !important; transition: none !important; }
|
||
.enf .enf-bett { stroke-dashoffset: 0; }
|
||
}
|
||
|
||
/* --- Einstellungen: Reiter "Übersicht" ------------------------------------ */
|
||
.enf-vorschau { background: var(--ton-grund, #191d20); border-radius: var(--ton-radius, .875rem); padding: .5rem; position: sticky; top: 4.5rem; }
|
||
.enf-e-zeile {
|
||
display: grid; grid-template-columns: auto minmax(0, 1fr) auto 1.2rem; gap: .35rem .7rem; align-items: center;
|
||
padding: .45rem 0; border-bottom: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||
}
|
||
.enf-e-zeile.enf-e-aus .enf-e-name { opacity: .5; }
|
||
.enf-e-name { display: flex; align-items: center; gap: .55rem; margin: 0; }
|
||
.enf-e-punkt { flex: 0 0 auto; width: .7rem; height: .7rem; border-radius: 50%; background: var(--farbe); box-shadow: 0 0 0 3px color-mix(in srgb, var(--farbe) 22%, transparent); }
|
||
.enf-e-eltern { white-space: nowrap; }
|
||
.enf-e-flaechen { grid-column: 2 / -1; padding: .2rem 0 .3rem; }
|
||
.enf-e-flaeche { display: grid; grid-template-columns: 2.2rem minmax(0, 1fr) 4.2rem 4.2rem 1.2rem; gap: .35rem; align-items: center; margin-bottom: .3rem; }
|
||
.enf-e-flaeche .form-control.form-control-color { width: 2.2rem; height: 1.9rem; padding: .15rem; }
|
||
|
||
/* ==========================================================================
|
||
Anlage-Ansicht (js/solar/anlage.js, Katalog js/solar/anlageKatalog.js).
|
||
Dieselben Töne wie die Energiefluss-Übersicht.
|
||
========================================================================== */
|
||
.anl { display: grid; gap: .9rem; }
|
||
.anl .anl-flaechen { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: .6rem; }
|
||
.anl .anl-flaeche { background: var(--ton-grund, #191d20); border-radius: .8rem; padding: .6rem .85rem .55rem; display: grid; gap: .35rem; }
|
||
.anl .anl-flaeche-kopf { display: flex; align-items: baseline; gap: .5rem; }
|
||
.anl .anl-flaeche-kopf i { width: .6rem; height: .6rem; border-radius: 50%; background: var(--farbe); align-self: center; box-shadow: 0 0 0 3px color-mix(in srgb, var(--farbe) 25%, transparent); }
|
||
.anl .anl-flaeche-kopf span { font-weight: 600; color: var(--ton-schrift, #e8ede9); }
|
||
.anl .anl-flaeche-kopf b { margin-left: auto; font-size: 1.2rem; font-weight: 600; font-variant-numeric: tabular-nums; }
|
||
.anl .anl-flaeche-balken { height: 5px; border-radius: 3px; background: #2b3139; overflow: hidden; }
|
||
.anl .anl-flaeche-balken span { display: block; height: 100%; background: var(--farbe); border-radius: 3px; transition: width 1s cubic-bezier(.2, .7, .2, 1); }
|
||
.anl .anl-flaeche small { color: var(--ton-schrift-3, #6f7a81); font-size: .76rem; }
|
||
@media (max-width: 575.98px) {
|
||
/* Auf dem Handy drei schmale Kacheln nebeneinander statt drei Zeilen. */
|
||
.anl .anl-flaechen { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .4rem; }
|
||
.anl .anl-flaeche { padding: .45rem .55rem; }
|
||
.anl .anl-flaeche-kopf { flex-wrap: wrap; gap: .1rem .4rem; }
|
||
.anl .anl-flaeche-kopf span { font-size: .8rem; }
|
||
.anl .anl-flaeche-kopf b { margin-left: 0; width: 100%; font-size: 1rem; }
|
||
.anl .anl-flaeche small { display: none; }
|
||
}
|
||
|
||
.anl .anl-plan-rahmen { background: var(--ton-grund, #191d20); border-radius: .9rem; padding: .4rem; }
|
||
svg.anl-plan { display: block; width: 100%; height: auto; max-height: 72vh; font-family: "Poppins", system-ui, sans-serif; user-select: none; -webkit-tap-highlight-color: transparent; }
|
||
svg.anl-plan.anl-hoch { max-height: none; }
|
||
|
||
.anl-plan .anl-dachflaeche { fill: var(--farbe); fill-opacity: .06; stroke: var(--farbe); stroke-opacity: .18; stroke-width: 22; stroke-linejoin: round; }
|
||
.anl-plan .anl-bereich { fill: var(--farbe); fill-opacity: .035; stroke: var(--farbe); stroke-opacity: .25; stroke-width: 2; stroke-dasharray: 7 7; }
|
||
|
||
.anl-plan .anl-teil { transform-box: fill-box; transform-origin: center; animation: anl-auf .55s cubic-bezier(.2, .9, .3, 1.2) backwards; animation-delay: calc(var(--d) * 1ms); }
|
||
@keyframes anl-auf { from { opacity: 0; transform: scale(.4); } }
|
||
.anl-plan .anl-koerper { fill: #2f353c; stroke: rgba(255, 255, 255, .1); stroke-width: 1; transition: fill 1s, stroke .2s, stroke-width .2s; }
|
||
.anl-plan .anl-platte .anl-koerper,
|
||
.anl-plan .anl-string .anl-koerper { fill: var(--fuellung, #3b3a32); }
|
||
.anl-plan .anl-platte.anl-offline .anl-koerper { fill: #262b31; stroke: #5c646d; stroke-dasharray: 4 3; }
|
||
.anl-plan .anl-zellen,
|
||
.anl-plan .anl-glanz { pointer-events: none; }
|
||
.anl-plan .anl-glanz { fill: #fff; opacity: 0; }
|
||
/* Lichtwelle: jede Platte hellt kurz auf, versetzt nach ihrer Lage. */
|
||
.anl-plan.anl-sonnig .anl-hell .anl-glanz {
|
||
animation: anl-glanz 7s ease-in-out infinite; animation-delay: calc(var(--glanz) * 7s); }
|
||
@keyframes anl-glanz { 0%, 100% { opacity: 0; } 7% { opacity: .3; } 15% { opacity: 0; } }
|
||
|
||
.anl-plan .anl-platte,
|
||
.anl-plan .anl-string { cursor: pointer; }
|
||
.anl-plan .anl-platte:hover .anl-koerper,
|
||
.anl-plan .anl-string:hover .anl-koerper { stroke: rgba(255, 255, 255, .7); stroke-width: 2; }
|
||
.anl-plan .anl-geschwister .anl-koerper { stroke: #e3e6ea; stroke-width: 2; stroke-dasharray: 6 4; }
|
||
.anl-plan .anl-gewaehlt .anl-koerper { stroke: #fff; stroke-width: 3.5; stroke-dasharray: none; }
|
||
|
||
.anl-plan .anl-w { font-size: 17px; font-weight: 600; fill: #c9d0d6; text-anchor: middle; dominant-baseline: central; pointer-events: none; font-variant-numeric: tabular-nums; }
|
||
.anl-plan .anl-hell .anl-w { fill: #15181c; }
|
||
.anl-plan .anl-offline .anl-w { fill: #8d96a0; }
|
||
.anl-plan.anl-klein .anl-w { display: none; }
|
||
|
||
.anl-plan .anl-warnung { display: none; pointer-events: none; }
|
||
.anl-plan .anl-schwach .anl-warnung { display: inline; }
|
||
.anl-plan .anl-warnung circle { fill: #e5624f; stroke: #1c2024; stroke-width: 2; }
|
||
.anl-plan .anl-warnung .anl-warnung-hof { stroke: none; opacity: .5; transform-box: fill-box; transform-origin: center; animation: anl-puls 1.8s ease-out infinite; }
|
||
@keyframes anl-puls { from { transform: scale(.6); opacity: .6; } to { transform: scale(1.5); opacity: 0; } }
|
||
.anl-plan .anl-warnung text { fill: #fff; font-size: 13px; font-weight: 700; text-anchor: middle; dominant-baseline: central; }
|
||
|
||
.anl-plan .anl-schild { pointer-events: none; }
|
||
.anl-plan .anl-schild rect { fill: rgba(21, 24, 28, .86); stroke: rgba(255, 255, 255, .08); }
|
||
.anl-plan .anl-schild-wert { font-size: 23px; font-weight: 600; fill: var(--ton-schrift, #e8ede9); text-anchor: middle; dominant-baseline: central; font-variant-numeric: tabular-nums; }
|
||
.anl-plan .anl-schild-name { font-size: 11px; font-weight: 600; fill: var(--ton-schrift-2, #9aa6ad); text-anchor: middle; dominant-baseline: central; text-transform: uppercase; letter-spacing: .08em; }
|
||
.anl-plan .anl-nord path { fill: #808090; }
|
||
.anl-plan .anl-nord text { fill: #808090; font-size: 15px; font-weight: 600; text-anchor: middle; }
|
||
.anl-plan.anl-pause,
|
||
.anl-plan.anl-pause * { animation-play-state: paused !important; }
|
||
|
||
.anl .anl-legende { display: flex; flex-wrap: wrap; gap: .3rem 1.1rem; font-size: .78rem; color: var(--ton-schrift-2, #9aa6ad); padding: 0 .3rem; }
|
||
.anl .anl-legende i { display: inline-block; width: .75rem; height: .75rem; border-radius: 3px; margin-right: .35rem; vertical-align: -.1rem; }
|
||
.anl .anl-l-verlauf { width: 2.6rem !important; background: linear-gradient(90deg, #3b3a32, #f7c000); }
|
||
.anl .anl-l-warnung { background: #e5624f; border-radius: 50% !important; color: #fff; font-style: normal; font-size: .6rem; font-weight: 700; text-align: center; line-height: .75rem; }
|
||
.anl .anl-l-offline { background: #262b31; box-shadow: inset 0 0 0 1px #5c646d; }
|
||
|
||
.anl .anl-unten { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: .9rem; align-items: start; }
|
||
@media (max-width: 860px) { .anl .anl-unten { grid-template-columns: minmax(0, 1fr); } }
|
||
.anl .anl-fach { background: var(--ton-grund, #191d20); border-radius: .9rem; padding: .9rem 1rem; display: grid; gap: .7rem; align-content: start; }
|
||
.anl .anl-ueberschrift { font-size: .78rem; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--ton-schrift-2, #9aa6ad); margin: 0; }
|
||
.anl .anl-kopf { display: flex; justify-content: space-between; align-items: center; gap: .6rem; }
|
||
.anl .anl-pille { font-size: .72rem; font-weight: 600; border-radius: 99px; padding: .1rem .55rem; white-space: nowrap; color: var(--ton-schrift-2, #9aa6ad); background: rgba(255, 255, 255, .06); }
|
||
.anl .anl-pille.anl-ok { color: #6cbe58; background: rgba(108, 190, 88, .13); }
|
||
.anl .anl-pille.anl-warn { color: #e8a33a; background: rgba(232, 163, 58, .14); }
|
||
.anl .anl-pille.anl-krit { color: #e5624f; background: rgba(229, 98, 79, .14); }
|
||
.anl .anl-gross { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .8rem; }
|
||
.anl .anl-gross b { font-size: 2rem; font-weight: 600; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--ton-schrift, #e8ede9); }
|
||
.anl .anl-gross span { color: var(--ton-schrift-2, #9aa6ad); font-size: .88rem; }
|
||
.anl .anl-funken { width: 100%; height: auto; display: block; }
|
||
.anl .anl-gitter { stroke: #2a3037; }
|
||
.anl .anl-funken-flaeche { fill: rgba(247, 192, 0, .14); }
|
||
.anl .anl-funken-linie { fill: none; stroke: #f7c000; stroke-width: 2; stroke-linejoin: round; }
|
||
.anl .anl-funken-punkt { fill: #f7c000; }
|
||
.anl .anl-achse { fill: var(--ton-schrift-3, #6f7a81); font-size: 10px; }
|
||
.anl .anl-funken-leer { color: var(--ton-schrift-3, #6f7a81); font-size: .82rem; padding: .7rem 0; }
|
||
.anl .anl-paare { display: grid; grid-template-columns: auto 1fr; gap: .25rem .9rem; font-size: .88rem; margin: 0; }
|
||
.anl .anl-paare dt { color: var(--ton-schrift-2, #9aa6ad); font-weight: 400; }
|
||
.anl .anl-paare dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
|
||
.anl .anl-hinweis { font-size: .84rem; color: var(--ton-schrift-2, #9aa6ad); margin: 0; }
|
||
.anl button.anl-link { all: unset; cursor: pointer; color: #8fb8de; }
|
||
.anl button.anl-link:hover { text-decoration: underline; }
|
||
|
||
.anl .anl-wr,
|
||
.anl .anl-eingaenge,
|
||
.anl .anl-hinweise { list-style: none; margin: 0; padding: 0; display: grid; gap: .15rem; }
|
||
.anl .anl-wr button,
|
||
.anl .anl-eingaenge button,
|
||
.anl .anl-hinweise button { all: unset; box-sizing: border-box; cursor: pointer; width: 100%; border-radius: .5rem; padding: .42rem .55rem; transition: background .2s; }
|
||
.anl .anl-wr button:hover,
|
||
.anl .anl-eingaenge button:hover,
|
||
.anl .anl-hinweise button:hover { background: var(--ton-flaeche-2, #2b3237); }
|
||
.anl .anl-wr button:focus-visible,
|
||
.anl .anl-eingaenge button:focus-visible,
|
||
.anl .anl-hinweise button:focus-visible,
|
||
.anl button.anl-link:focus-visible { outline: 2px solid #8fb8de; outline-offset: 1px; }
|
||
.anl .anl-wr button { display: grid; grid-template-columns: minmax(0, 1fr) auto 6.5rem; gap: .7rem; align-items: center; font-size: .9rem; }
|
||
.anl .anl-wr button > .anl-pille { justify-self: end; }
|
||
.anl .anl-wr button[aria-pressed="true"] { background: var(--ton-flaeche-2, #2b3237); box-shadow: inset 3px 0 0 #f7c000; }
|
||
.anl .anl-wr-name small { display: block; color: var(--ton-schrift-3, #6f7a81); font-size: .74rem; }
|
||
.anl .anl-wr-wert { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
|
||
.anl .anl-wr-last { display: block; width: 4rem; height: 3px; margin: .25rem 0 0 auto; border-radius: 2px; background: #2b3139; overflow: hidden; }
|
||
.anl .anl-wr-last span { display: block; height: 100%; background: #f7c000; transition: width 1s; }
|
||
.anl .anl-eingaenge button { display: grid; grid-template-columns: 6.5rem minmax(0, 1fr) 4.2rem; gap: .6rem; align-items: center; font-size: .86rem; }
|
||
.anl .anl-eingaenge b { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
|
||
.anl .anl-balken { height: 7px; border-radius: 4px; background: #2b3139; overflow: hidden; }
|
||
.anl .anl-balken span { display: block; height: 100%; border-radius: 4px; background: #f7c000; transition: width .8s cubic-bezier(.2, .7, .2, 1); }
|
||
.anl .anl-balken.anl-mittel span { background: #c98a22; }
|
||
.anl .anl-balken.anl-schwach span { background: #e5624f; }
|
||
.anl .anl-balken.anl-offline span,
|
||
.anl .anl-balken.anl-dunkel span { background: #5c646d; }
|
||
.anl .anl-hinweise button { display: flex; align-items: center; gap: .6rem; font-size: .88rem; }
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.anl *, .anl-plan * { animation: none !important; transition: none !important; }
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Speicher-Ansicht (js/solar/speicher.js). Töne wie Übersicht und Anlage.
|
||
========================================================================== */
|
||
.spk { display: grid; gap: .9rem; }
|
||
.spk .spk-meldung { border-radius: .7rem; padding: .55rem .9rem; font-size: .88rem; background: rgba(232, 163, 58, .12); color: #e8a33a; }
|
||
.spk .spk-meldung.spk-fehler { background: rgba(229, 98, 79, .14); color: #e5624f; }
|
||
.spk .spk-fach { background: var(--ton-grund, #191d20); border-radius: .9rem; padding: .9rem 1rem; display: grid; gap: .7rem; align-content: start; min-width: 0; }
|
||
.spk .spk-kopf { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: .4rem .8rem; }
|
||
.spk .spk-ueberschrift { font-size: .78rem; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--ton-schrift-2, #9aa6ad); margin: 0; }
|
||
.spk .spk-stand { font-size: .78rem; color: var(--ton-schrift-3, #6f7a81); }
|
||
.spk .spk-leer { color: var(--ton-schrift-3, #6f7a81); font-size: .85rem; margin: .5rem 0; }
|
||
|
||
/* Kennzahlen */
|
||
.spk .spk-kennzahlen { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .6rem; }
|
||
@media (max-width: 991.98px) { .spk .spk-kennzahlen { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
||
.spk .spk-notiz { font-size: .74rem; color: var(--ton-schrift-3, #6f7a81); margin-top: -.4rem; }
|
||
.spk .spk-einheit { font-weight: 600; }
|
||
.spk .spk-kachel { position: relative; background: var(--ton-grund, #191d20); border-radius: .8rem; padding: .65rem .85rem .7rem; display: grid; gap: .1rem; overflow: hidden; }
|
||
.spk .spk-kachel-titel { font-size: .74rem; color: var(--ton-schrift-2, #9aa6ad); display: flex; align-items: center; gap: .4rem; }
|
||
.spk .spk-kachel-titel i { font-family: bootstrap-icons; font-style: normal; font-size: .9rem; color: #6cbe58; }
|
||
.spk .spk-kachel b { font-size: 1.45rem; font-weight: 600; color: var(--ton-schrift, #e8ede9); font-variant-numeric: tabular-nums; line-height: 1.25; }
|
||
.spk .spk-kachel small { font-size: .74rem; color: var(--ton-schrift-3, #6f7a81); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.spk .spk-kachel.spk-gut b { color: #8fd37a; }
|
||
.spk .spk-kachel.spk-warm b { color: #e8a33a; }
|
||
.spk .spk-kachel.spk-warm .spk-kachel-titel i { color: #e8a33a; }
|
||
.spk .spk-kachel.spk-krit b,
|
||
.spk .spk-kachel.spk-krit .spk-kachel-titel i { color: #e5624f; }
|
||
.spk .spk-kachel-balken { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: #2b3139; }
|
||
.spk .spk-kachel-balken span { display: block; height: 100%; background: linear-gradient(90deg, #4f8fb8, #6cbe58); transition: width 1.2s cubic-bezier(.2, .7, .2, 1); }
|
||
|
||
/* Turm und Detail */
|
||
.spk .spk-mitte { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: .9rem; align-items: start; }
|
||
@media (max-width: 991.98px) { .spk .spk-mitte { grid-template-columns: minmax(0, 1fr); } }
|
||
.spk .spk-turm { position: relative; display: grid; gap: 4px; }
|
||
.spk .spk-bmu {
|
||
display: flex; align-items: center; gap: .6rem; padding: .5rem .8rem; font-size: .82rem;
|
||
background: linear-gradient(#2c3238, #24292f); border: 1px solid #333a42; border-radius: .7rem .7rem .25rem .25rem;
|
||
}
|
||
.spk .spk-bmu b { font-weight: 600; }
|
||
.spk .spk-bmu span:last-child { color: var(--ton-schrift-3, #6f7a81); font-size: .74rem; margin-left: auto; }
|
||
.spk .spk-led { width: .55rem; height: .55rem; border-radius: 50%; background: #444b53; }
|
||
.spk .spk-led.an { background: #6cbe58; box-shadow: 0 0 .5rem #6cbe58; animation: spk-led 2.4s ease-in-out infinite; }
|
||
@keyframes spk-led { 50% { opacity: .55; } }
|
||
.spk .spk-modul {
|
||
all: unset; box-sizing: border-box; cursor: pointer; position: relative; overflow: hidden;
|
||
display: grid; grid-template-columns: 2.2rem minmax(0, 1fr) 7.4rem; gap: .7rem; align-items: center;
|
||
padding: .45rem .7rem; border-radius: .25rem; border: 1px solid #2f363d;
|
||
background: linear-gradient(90deg, #1f2429, #262c32 50%, #1f2429);
|
||
transition: border-color .2s, box-shadow .2s;
|
||
animation: spk-modul-auf .5s cubic-bezier(.2, .9, .3, 1.1) backwards; animation-delay: calc(var(--i) * 45ms);
|
||
}
|
||
@keyframes spk-modul-auf { from { opacity: 0; transform: translateY(8px); } }
|
||
.spk .spk-modul:hover { border-color: #46505a; }
|
||
.spk .spk-modul:focus-visible { outline: 2px solid #8fb8de; outline-offset: 1px; }
|
||
.spk .spk-modul.gewaehlt { border-color: #6cbe58; box-shadow: inset 3px 0 0 #6cbe58; }
|
||
.spk .spk-nr { font-weight: 600; color: var(--ton-schrift-2, #9aa6ad); font-size: .9rem; }
|
||
.spk .spk-zellen { display: grid; grid-template-columns: repeat(16, minmax(0, 1fr)); gap: 2px; height: 2rem; align-items: end; }
|
||
.spk .spk-zellen i { display: block; height: var(--h); background: var(--f); border-radius: 2px 2px 1px 1px; transition: height 1s cubic-bezier(.2, .7, .2, 1), background 1s; }
|
||
.spk .spk-werte { text-align: right; line-height: 1.25; font-variant-numeric: tabular-nums; }
|
||
.spk .spk-werte b { display: block; font-size: .8rem; font-weight: 600; }
|
||
.spk .spk-werte small { font-size: .74rem; color: var(--ton-schrift-3, #6f7a81); }
|
||
.spk .spk-sockel { height: .6rem; margin-top: -2px; border-radius: 0 0 .6rem .6rem; background: #1a1e22; border: 1px solid #2f363d; border-top: 0; }
|
||
/* Laden: Licht wandert nach oben durch die Module, Entladen nach unten. */
|
||
.spk .spk-turm.spk-laden .spk-modul::after,
|
||
.spk .spk-turm.spk-entladen .spk-modul::after {
|
||
content: ""; position: absolute; inset: 0; pointer-events: none;
|
||
background: linear-gradient(90deg, transparent, rgba(108, 190, 88, .16), transparent);
|
||
transform: translateX(-100%); animation: spk-strom 2.6s ease-in-out infinite;
|
||
}
|
||
.spk .spk-turm.spk-laden .spk-modul::after { animation-delay: calc((8 - var(--i)) * 180ms); }
|
||
.spk .spk-turm.spk-entladen .spk-modul::after { background: linear-gradient(90deg, transparent, rgba(232, 163, 58, .14), transparent); animation-delay: calc(var(--i) * 180ms); }
|
||
@keyframes spk-strom { 0% { transform: translateX(-100%); } 60%, 100% { transform: translateX(100%); } }
|
||
.spk.spk-pause *,
|
||
.spk-pause .spk * { animation-play-state: paused !important; }
|
||
.spk .spk-legende { display: flex; flex-wrap: wrap; gap: .3rem 1rem; font-size: .76rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.spk .spk-legende i { display: inline-block; width: .7rem; height: .7rem; border-radius: 2px; margin-right: .35rem; vertical-align: -.08rem; }
|
||
|
||
.spk .spk-pille { font-size: .72rem; font-weight: 600; border-radius: 99px; padding: .1rem .55rem; }
|
||
.spk .spk-pille.ok { color: #6cbe58; background: rgba(108, 190, 88, .13); }
|
||
.spk .spk-pille.warn { color: #e8a33a; background: rgba(232, 163, 58, .14); }
|
||
.spk .spk-gross { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .8rem; }
|
||
.spk .spk-gross b { font-size: 2rem; font-weight: 600; line-height: 1.1; color: var(--ton-schrift, #e8ede9); font-variant-numeric: tabular-nums; }
|
||
.spk .spk-gross span { color: var(--ton-schrift-2, #9aa6ad); font-size: .88rem; }
|
||
.spk .spk-zellchart { width: 100%; height: auto; display: block; }
|
||
.spk .spk-zelle { transform-box: fill-box; transform-origin: 50% 100%; animation: spk-zelle .6s cubic-bezier(.2, .9, .3, 1.1) backwards; animation-delay: calc(var(--j) * 25ms); }
|
||
.spk .spk-zelle.markiert { stroke: #fff; stroke-width: 1.5; }
|
||
@keyframes spk-zelle { from { transform: scaleY(0); } }
|
||
.spk .spk-gitter { stroke: #2a3037; stroke-width: 1; }
|
||
.spk .spk-mittel { stroke: #8d96a0; stroke-dasharray: 3 3; }
|
||
.spk .spk-achse { fill: var(--ton-schrift-3, #6f7a81); font-size: 10px; font-family: "Poppins", system-ui, sans-serif; }
|
||
.spk .spk-fuehler { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 3px; }
|
||
.spk .spk-fuehler span { text-align: center; font-size: .74rem; font-weight: 600; padding: .2rem 0; border-radius: .3rem; color: #15181c; background: var(--f); font-variant-numeric: tabular-nums; }
|
||
.spk .spk-paare { display: grid; grid-template-columns: auto 1fr; gap: .25rem .9rem; font-size: .86rem; margin: 0; }
|
||
.spk .spk-paare dt { color: var(--ton-schrift-2, #9aa6ad); font-weight: 400; }
|
||
.spk .spk-paare dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
|
||
|
||
/* Verlauf */
|
||
.spk .spk-diagramme { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: .9rem; }
|
||
@media (max-width: 991.98px) { .spk .spk-diagramme { grid-template-columns: minmax(0, 1fr); } }
|
||
.spk .spk-zeitraum { display: inline-flex; gap: 2px; padding: 2px; border-radius: .5rem; background: #23282c; }
|
||
.spk .spk-zeitraum button { all: unset; cursor: pointer; font-size: .76rem; font-weight: 600; padding: .15rem .6rem; border-radius: .4rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.spk .spk-zeitraum button.aktiv { background: #2f363d; color: var(--ton-schrift, #e8ede9); }
|
||
.spk .spk-zeitraum button:focus-visible { outline: 2px solid #8fb8de; }
|
||
.spk .spk-diagramm { position: relative; min-height: 190px; }
|
||
.spk .spk-verlauf { display: block; width: 100%; height: auto; touch-action: pan-y; }
|
||
.spk .spk-flaeche { opacity: .22; }
|
||
.spk .spk-linie { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
|
||
.spk .spk-verlauf.neu .spk-linie { stroke-dasharray: 1 1; stroke-dashoffset: 1; animation: spk-zeichnen 1.2s cubic-bezier(.5, 0, .2, 1) forwards; animation-delay: calc(var(--i) * 150ms); }
|
||
.spk .spk-verlauf.neu .spk-flaeche { animation: spk-einblenden 1.2s backwards; }
|
||
@keyframes spk-zeichnen { to { stroke-dashoffset: 0; } }
|
||
@keyframes spk-einblenden { from { opacity: 0; } }
|
||
.spk .spk-zeiger { stroke: rgba(255, 255, 255, .35); stroke-width: 1; pointer-events: none; }
|
||
.spk .spk-tipp {
|
||
position: absolute; top: .4rem; z-index: 2; pointer-events: none; min-width: 9rem;
|
||
background: rgba(21, 24, 28, .94); border: 1px solid #333a42; border-radius: .55rem; padding: .4rem .6rem;
|
||
font-size: .76rem; display: grid; gap: .1rem; box-shadow: 0 .4rem 1rem rgba(0, 0, 0, .35);
|
||
}
|
||
.spk .spk-tipp b { font-weight: 600; margin-bottom: .1rem; }
|
||
.spk .spk-tipp span { display: flex; align-items: center; gap: .4rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.spk .spk-tipp em { font-style: normal; margin-left: auto; padding-left: .8rem; color: var(--ton-schrift, #e8ede9); font-variant-numeric: tabular-nums; }
|
||
.spk .spk-tipp i,
|
||
.spk .spk-reihen i { display: inline-block; width: .6rem; height: .6rem; border-radius: 2px; }
|
||
.spk .spk-reihen { display: flex; flex-wrap: wrap; gap: .2rem 1rem; font-size: .76rem; color: var(--ton-schrift-2, #9aa6ad); margin-top: .2rem; }
|
||
.spk .spk-reihen span { display: inline-flex; align-items: center; gap: .35rem; }
|
||
@media (max-width: 575.98px) {
|
||
.spk .spk-kennzahlen { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .45rem; }
|
||
.spk .spk-kachel b { font-size: 1.2rem; }
|
||
.spk .spk-modul { grid-template-columns: 1.8rem minmax(0, 1fr) 5.6rem; gap: .45rem; padding: .4rem .5rem; }
|
||
.spk .spk-werte b { font-size: .72rem; }
|
||
}
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.spk *, .spk *::after { animation: none !important; transition: none !important; }
|
||
.spk .spk-verlauf.neu .spk-linie { stroke-dashoffset: 0; }
|
||
}
|
||
|
||
/* ==========================================================================
|
||
Anzeige-Modus (index.php?action=anzeige, js/solar/anzeige.js): die
|
||
Solar-Seite auf einem festen Display, z.B. Raspberry Pi mit 800 x 480.
|
||
Leiste links; die Realtime-Karte füllt genau einen Bildschirm, die
|
||
Diagramme folgen darunter und rasten beim Wischen karteweise ein.
|
||
========================================================================== */
|
||
html:has(body.anzeige) { scroll-snap-type: y proximity; scrollbar-width: none; }
|
||
html:has(body.anzeige)::-webkit-scrollbar { display: none; }
|
||
body.anzeige { -webkit-tap-highlight-color: transparent; }
|
||
body.anzeige-ohne-maus,
|
||
body.anzeige-ohne-maus * { cursor: none !important; }
|
||
|
||
.anzeige .anzeige-leiste {
|
||
position: fixed; left: 0; top: 0; bottom: 0; width: 3.2rem; z-index: 1030;
|
||
display: flex; flex-direction: column; align-items: center; gap: .4rem; padding: .5rem 0;
|
||
background: var(--ton-flaeche, #23282c); border-right: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||
}
|
||
.anzeige .anzeige-leiste button {
|
||
all: unset; box-sizing: border-box; width: 2.6rem; height: 2.6rem; border-radius: .7rem;
|
||
display: grid; place-items: center; font-size: 1.3rem; color: var(--ton-schrift-2, #9aa6ad);
|
||
}
|
||
.anzeige .anzeige-leiste button[aria-pressed="true"] { background: var(--ton-flaeche-2, #2b3237); color: #f7c000; }
|
||
.anzeige .anzeige-fuss { margin-top: auto; display: grid; justify-items: center; gap: .3rem; }
|
||
.anzeige .anzeige-punkt { width: .6rem; height: .6rem; border-radius: 50%; background: #e5624f; }
|
||
.anzeige .anzeige-punkt.warn { background: #e8a33a; }
|
||
.anzeige .anzeige-punkt.gut { background: #6cbe58; }
|
||
.anzeige .anzeige-uhr { font-size: .72rem; font-weight: 600; color: var(--ton-schrift-2, #9aa6ad); font-variant-numeric: tabular-nums; }
|
||
|
||
.anzeige .app-wrapper { display: block; }
|
||
.anzeige .app-main { margin-left: 3.2rem; }
|
||
.anzeige .app-content-header { display: none; }
|
||
.anzeige .app-content { padding: 0 .35rem; }
|
||
.anzeige .app-content .container-fluid { padding: 0; }
|
||
.anzeige .app-content .row { --bs-gutter-x: 0; }
|
||
.anzeige .app-content .card { scroll-snap-align: start; }
|
||
|
||
/* Realtime-Karte: ein ganzer Bildschirm, ohne Kopf - die Leiste ersetzt ihn. */
|
||
.anzeige .card#energieflussKarte { height: 100vh; margin-bottom: .5rem !important; border: 0; border-radius: 0; background: transparent; }
|
||
.anzeige .card#energieflussKarte .card-header { display: none !important; }
|
||
.anzeige .card#energieflussKarte .card-body { height: 100%; padding: .2rem 0 !important; }
|
||
.anzeige #energiefluss { height: 100%; overflow: hidden; }
|
||
.anzeige #energiefluss svg.enf { width: 100%; height: 100%; max-height: none; }
|
||
.anzeige #anlage,
|
||
.anzeige #speicher { height: 100%; overflow-y: auto; scrollbar-width: none; }
|
||
|
||
/* Die Umbrüche von Anlage und Speicher richten sich nach der Fensterbreite
|
||
und würden am 800er-Display zu früh greifen. */
|
||
.anzeige .anl svg.anl-plan { max-height: calc(100vh - 7.5rem); }
|
||
.anzeige .spk .spk-kennzahlen { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .35rem; }
|
||
.anzeige .spk .spk-kachel { padding: .4rem .55rem .45rem; }
|
||
.anzeige .spk .spk-kachel b { font-size: 1.05rem; }
|
||
.anzeige .spk .spk-kachel small,
|
||
.anzeige .spk .spk-kachel-titel { font-size: .66rem; }
|
||
.anzeige .spk .spk-mitte,
|
||
.anzeige .spk .spk-diagramme { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: .5rem; }
|
||
.anzeige .spk .spk-fach { padding: .6rem .7rem; gap: .5rem; }
|
||
.anzeige .spk .spk-modul { grid-template-columns: 1.7rem minmax(0, 1fr) 5.4rem; gap: .4rem; padding: .3rem .45rem; }
|
||
.anzeige .spk .spk-zellen { height: 1.4rem; }
|
||
.anzeige .spk .spk-werte b { font-size: .68rem; }
|
||
.anzeige .spk .spk-werte small { font-size: .62rem; }
|
||
.anzeige .spk .spk-gross b { font-size: 1.4rem; }
|
||
|
||
/* Bedienfenster: passen auf 480 px Höhe und lassen sich mit dem Finger bedienen. */
|
||
.anzeige .modal-dialog { margin: .4rem auto; }
|
||
.anzeige .modal-body { max-height: calc(100vh - 9rem); overflow-y: auto; }
|
||
.anzeige .modal .form-range { height: 2rem; }
|
||
.anzeige .modal .btn { min-height: 2.4rem; }
|
||
|
||
/* Ruhig (Vorgabe am Pi): alles Zierwerk aus, nur die Flüsse laufen - in
|
||
groben Stufen, damit ein Raspberry Pi 3 nicht dauernd neu zeichnet. */
|
||
.anzeige-ruhig *,
|
||
.anzeige-ruhig *::after { animation: none !important; }
|
||
.anzeige-ruhig .enf .enf-bett,
|
||
.anzeige-ruhig .spk .spk-verlauf.neu .spk-linie { stroke-dashoffset: 0; }
|
||
.anzeige-ruhig .enf .enf-strom-hof { display: none; }
|
||
.anzeige-ruhig .enf .enf-strom { animation: enf-fliessen 1s steps(8) infinite !important; }
|
||
.anzeige-ruhig .enf .enf-rueck .enf-strom { animation-direction: reverse !important; }
|
||
.anzeige-ruhig .enf .enf-still .enf-strom,
|
||
.anzeige-ruhig .enf.enf-pause .enf-strom { animation: none !important; }
|
||
.anzeige-ruhig .enf .enf-koerper { transition: none; }
|
||
|
||
/* ==========================================================================
|
||
Ladefenster der Wallboxen (ajax/carForm.php, js/solar/ladefenster.js).
|
||
Oben der Zustand, dann ein Knopf, darunter Modus, Planung, Strom.
|
||
========================================================================== */
|
||
.lade { display: grid; gap: 1rem; padding: 1rem 1.1rem 1.1rem; --lade-wallbox: #60afbf; }
|
||
.lade .lade-links,
|
||
.lade .lade-rechts { display: grid; gap: .9rem; align-content: start; min-width: 0; }
|
||
|
||
.lade .lade-status { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: .9rem; align-items: center; }
|
||
.lade .lade-ring { position: relative; width: 7.5rem; height: 7.5rem; }
|
||
.lade .lade-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
|
||
.lade .lade-spur { fill: none; stroke: #2b3237; stroke-width: 12; }
|
||
.lade .lade-ist { fill: none; stroke: #6cbe58; stroke-width: 12; stroke-linecap: round; stroke-dasharray: 0 100; transition: stroke-dasharray .7s cubic-bezier(.2, .7, .2, 1); }
|
||
.lade .lade-ziel { fill: none; stroke: var(--lade-wallbox); stroke-width: 12; opacity: .45; stroke-dasharray: 0 100; transition: stroke-dasharray .7s, stroke-dashoffset .7s; }
|
||
.lade .lade-ring-mitte { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
|
||
.lade .lade-ring-mitte b { font-size: 1.55rem; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
|
||
.lade .lade-ring-mitte span { font-size: .7rem; color: var(--lade-wallbox); font-weight: 600; margin-top: .25rem; }
|
||
.lade .lade-text { display: grid; gap: .25rem; min-width: 0; }
|
||
.lade .lade-auto { font-size: .8rem; color: var(--ton-schrift-2, #9aa6ad); display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
|
||
.lade .lade-pille { font-size: .68rem; font-weight: 600; border-radius: 99px; padding: .05rem .5rem; background: rgba(255, 255, 255, .06); color: var(--ton-schrift-2, #9aa6ad); }
|
||
.lade .lade-pille:empty { display: none; }
|
||
.lade .lade-pille.an { color: #6cbe58; background: rgba(108, 190, 88, .14); }
|
||
.lade .lade-gross { font-size: 1.45rem; font-weight: 600; font-variant-numeric: tabular-nums; }
|
||
.lade .lade-gross small { font-size: .8rem; font-weight: 400; color: var(--ton-schrift-2, #9aa6ad); margin-left: .35rem; }
|
||
.lade .lade-zeile { font-size: .82rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.lade .lade-zeile:empty { display: none; }
|
||
|
||
.lade .lade-start {
|
||
all: unset; box-sizing: border-box; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: .6rem;
|
||
height: 3.1rem; border-radius: .9rem; font-weight: 600; font-size: 1rem;
|
||
background: linear-gradient(180deg, #6cbe58, #57a646); color: #0f1a0c; box-shadow: 0 .35rem 1rem rgba(108, 190, 88, .22);
|
||
transition: transform .15s, filter .2s;
|
||
}
|
||
.lade .lade-start:hover { filter: brightness(1.06); }
|
||
.lade .lade-start:active { transform: scale(.98); }
|
||
.lade .lade-start:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
|
||
.lade .lade-start.laeuft { background: linear-gradient(180deg, #3a4147, #30363b); color: var(--ton-schrift, #e8ede9); box-shadow: none; border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2)); }
|
||
.lade .lade-start.aus { background: #2b3237; color: var(--ton-schrift-3, #6f7a81); box-shadow: none; cursor: default; }
|
||
.lade .lade-start.aus .lade-punkt { display: none; }
|
||
.lade .lade-start.gesperrt { background: linear-gradient(180deg, #e8a33a, #cf8f2c); color: #1d1406; box-shadow: 0 .35rem 1rem rgba(232, 163, 58, .2); }
|
||
.lade .lade-punkt { width: .55rem; height: .55rem; border-radius: 50%; background: currentColor; }
|
||
.lade .lade-start.laeuft .lade-punkt { background: #6cbe58; animation: lade-puls 1.6s infinite; }
|
||
@keyframes lade-puls { 0% { box-shadow: 0 0 0 0 rgba(108, 190, 88, .6); } 70%, 100% { box-shadow: 0 0 0 .5rem rgba(108, 190, 88, 0); } }
|
||
.lade .lade-erklaerung { padding: .5rem .7rem; border-radius: .6rem; background: rgba(96, 175, 191, .1); color: #bfe3ea; font-size: .8rem; }
|
||
.lade .lade-erklaerung:empty { display: none; }
|
||
|
||
.lade .lade-abschnitt { display: grid; gap: .45rem; }
|
||
.lade h3 { margin: 0; font-size: .7rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.lade .lade-modi { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .45rem; }
|
||
.lade .lade-modus {
|
||
all: unset; box-sizing: border-box; cursor: pointer; display: grid; gap: .2rem; justify-items: start; padding: .6rem .65rem;
|
||
border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); border: 1.5px solid transparent; transition: border-color .2s, background .2s;
|
||
}
|
||
.lade .lade-modus:hover { background: #333b41; }
|
||
.lade .lade-modus:focus-visible { outline: 2px solid var(--lade-wallbox); outline-offset: 1px; }
|
||
.lade .lade-modus b { font-weight: 600; font-size: .88rem; }
|
||
.lade .lade-modus > span:last-child { font-size: .7rem; color: var(--ton-schrift-2, #9aa6ad); line-height: 1.3; }
|
||
.lade .lade-sym { width: 1.7rem; height: 1.7rem; border-radius: .5rem; display: grid; place-items: center; background: rgba(255, 255, 255, .06); }
|
||
.lade .lade-sym svg { width: 1.1rem; height: 1.1rem; stroke: var(--c); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
||
.lade .lade-modus[aria-checked="true"] { border-color: var(--c); background: color-mix(in srgb, var(--c) 12%, var(--ton-flaeche-2, #2b3237)); }
|
||
.lade .lade-modus[aria-checked="true"] .lade-sym { background: color-mix(in srgb, var(--c) 25%, transparent); }
|
||
|
||
.lade .lade-planung { display: grid; gap: .7rem; padding: .7rem .75rem; border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); animation: lade-auf .3s cubic-bezier(.2, .7, .2, 1); }
|
||
.lade .lade-planung[hidden] { display: none; }
|
||
@keyframes lade-auf { from { opacity: 0; transform: translateY(-.35rem); } }
|
||
.lade .lade-plan-zeile { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; }
|
||
.lade .lade-plan-zeile label { font-size: .82rem; color: var(--ton-schrift-2, #9aa6ad); margin: 0; }
|
||
.lade .lade-plan-zeile output { font-weight: 600; font-variant-numeric: tabular-nums; }
|
||
.lade .lade-plan-zeile output small { color: var(--ton-schrift-2, #9aa6ad); font-weight: 400; margin-left: .3rem; }
|
||
.lade input[type="range"] { -webkit-appearance: none; appearance: none; width: 100%; height: 1.9rem; background: transparent; margin: 0; }
|
||
.lade input[type="range"]::-webkit-slider-runnable-track { height: .5rem; border-radius: .25rem; background: linear-gradient(90deg, #6cbe58 0 var(--ist, 0%), var(--lade-wallbox) var(--ist, 0%) var(--wert, 0%), #394046 var(--wert, 0%)); }
|
||
.lade input[type="range"]::-moz-range-track { height: .5rem; border-radius: .25rem; background: linear-gradient(90deg, #6cbe58 0 var(--ist, 0%), var(--lade-wallbox) var(--ist, 0%) var(--wert, 0%), #394046 var(--wert, 0%)); }
|
||
.lade input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 1.6rem; height: 1.6rem; margin-top: -.55rem; border-radius: 50%; background: #fff; border: 4px solid var(--lade-wallbox); box-shadow: 0 .15rem .5rem rgba(0, 0, 0, .4); }
|
||
.lade input[type="range"]::-moz-range-thumb { width: 1.1rem; height: 1.1rem; border-radius: 50%; background: #fff; border: 4px solid var(--lade-wallbox); }
|
||
.lade input[type="range"]:focus-visible { outline: 2px solid var(--lade-wallbox); outline-offset: 4px; }
|
||
.lade .lade-marken { display: flex; justify-content: space-between; font-size: .68rem; color: var(--ton-schrift-3, #6f7a81); margin-top: -.2rem; }
|
||
.lade .lade-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
|
||
.lade .lade-chip { all: unset; cursor: pointer; padding: .35rem .7rem; border-radius: 99px; background: #363d43; font-size: .8rem; font-weight: 500; font-variant-numeric: tabular-nums; }
|
||
.lade .lade-chip[aria-pressed="true"] { background: var(--lade-wallbox); color: #0c1a1d; font-weight: 600; }
|
||
.lade .lade-chip:focus-visible { outline: 2px solid var(--lade-wallbox); outline-offset: 1px; }
|
||
.lade .lade-chip-eigen { position: relative; display: inline-flex; align-items: center; gap: .35rem; }
|
||
.lade .lade-chip-eigen .bi { font-size: .85em; }
|
||
/* Unsichtbar, aber an Ort und Stelle: der Wähler öffnet sich am Knopf. */
|
||
.lade .lade-zeitfeld { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; pointer-events: none; border: 0; padding: 0; }
|
||
|
||
.lade .lade-strom { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .3rem; padding: .25rem; border-radius: .75rem; background: var(--ton-flaeche-2, #2b3237); }
|
||
.lade .lade-strom button { all: unset; cursor: pointer; text-align: center; padding: .45rem .2rem; border-radius: .55rem; display: grid; gap: .05rem; }
|
||
.lade .lade-strom button b { font-weight: 600; }
|
||
.lade .lade-strom button span { font-size: .68rem; color: var(--ton-schrift-2, #9aa6ad); }
|
||
.lade .lade-strom button[aria-checked="true"] { background: #363d43; box-shadow: inset 0 0 0 1.5px var(--lade-wallbox); }
|
||
.lade .lade-strom button:focus-visible { outline: 2px solid var(--lade-wallbox); }
|
||
.lade .lade-meldung { font-size: .76rem; color: var(--ton-schrift-3, #6f7a81); }
|
||
.lade .lade-meldung.gut { color: #6cbe58; }
|
||
.lade .lade-meldung.fehler { color: #e5624f; }
|
||
@media (max-width: 420px) { .lade .lade-modus > span:last-child { display: none; } }
|
||
|
||
.lade .lade-pille.warn { color: #e8a33a; background: rgba(232, 163, 58, .14); }
|
||
.lade .lade-pille.blau { color: #6fb3e8; background: rgba(75, 159, 214, .15); }
|
||
.lade .lade-modi.zwei { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||
|
||
/* --- Heizstab (ajax/heater.php, bedienfenster.js) --- */
|
||
/* Akzent: Regler und gewählte Chips im Rot der Karte "Fest" statt Türkis. */
|
||
.lade.heiz { --lade-wallbox: #e5624f; }
|
||
.lade.heiz .lade-status { grid-template-columns: 5.5rem minmax(0, 1fr); }
|
||
.lade .heiz-tank { width: 5.5rem; }
|
||
.lade .heiz-tank svg { width: 100%; height: auto; display: block; }
|
||
.lade .heiz-tank rect[data-heiz] { fill: #2b3237; transition: fill 1.5s; }
|
||
.lade .heiz-huelle { fill: none; stroke: #9aa6ad; stroke-width: 2.5; stroke-linecap: round; }
|
||
.lade .heiz-spirale { fill: none; stroke: rgba(255, 255, 255, .35); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; transition: stroke .4s; }
|
||
.lade .heiz-spirale.an { stroke: #ffb04a; animation: lade-gluehen 1.1s ease-in-out infinite alternate; }
|
||
@keyframes lade-gluehen { to { stroke: #ff5a2a; } }
|
||
.lade .heiz-tank text { fill: #fff; font-size: 13px; font-weight: 600; text-anchor: middle; paint-order: stroke; stroke: rgba(0, 0, 0, .35); stroke-width: 3px; }
|
||
.lade .heiz-tank text.klein { font-size: 11px; }
|
||
.lade .heiz-regler { --ist: 0%; }
|
||
|
||
/* --- Bewässerung (ajax/watering.php, bedienfenster.js) --- */
|
||
.lade.wasser { gap: .8rem; --lade-wallbox: #4b9fd6; }
|
||
.lade .wasser-zonen { display: grid; gap: .55rem; }
|
||
.lade .wasser-zone {
|
||
display: grid; gap: .5rem; padding: .65rem .75rem; border-radius: .8rem; background: var(--ton-flaeche-2, #2b3237);
|
||
border: 1.5px solid transparent; transition: border-color .3s;
|
||
}
|
||
.lade .wasser-zone.laeuft { border-color: #20c997; }
|
||
.lade .wasser-kopf { display: flex; align-items: center; gap: .6rem; }
|
||
.lade .wasser-bild { width: 2.1rem; height: 2.1rem; flex: 0 0 auto; display: grid; place-items: center; border-radius: .6rem; background: rgba(75, 159, 214, .14); color: #6fb3e8; }
|
||
.lade .wasser-zone.laeuft .wasser-bild { background: rgba(32, 201, 151, .16); color: #20c997; }
|
||
.lade .wasser-bild svg { width: 1.35rem; height: 1.35rem; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
|
||
.lade .wasser-titel { display: grid; min-width: 0; margin-right: auto; }
|
||
.lade .wasser-titel b { font-weight: 600; }
|
||
.lade .wasser-titel span { font-size: .78rem; color: var(--ton-schrift-2, #9aa6ad); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.lade .wasser-fuss { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; }
|
||
.lade .wasser-fuss .lade-chips { flex: 1 1 auto; }
|
||
.lade .wasser-fuss .lade-chip { padding: .3rem .6rem; font-size: .76rem; }
|
||
.lade .lade-start.wasser-knopf { height: 2.4rem; padding: 0 1rem; font-size: .9rem; flex: 0 0 auto; background: linear-gradient(180deg, #4b9fd6, #3b88bf); color: #06121b; box-shadow: 0 .3rem .9rem rgba(75, 159, 214, .22); }
|
||
.lade .lade-start.wasser-knopf .lade-punkt { display: none; }
|
||
.lade .lade-start.wasser-knopf.laeuft { background: linear-gradient(180deg, #3a4147, #30363b); color: var(--ton-schrift, #e8ede9); box-shadow: none; }
|
||
.lade .lade-start.wasser-knopf.laeuft .lade-punkt { display: block; background: #20c997; }
|
||
.lade .wasser-info { font-size: .72rem; color: var(--ton-schrift-3, #6f7a81); }
|
||
.lade .wasser-info:empty { display: none; }
|
||
.lade .wasser-ablaeufe .lade-chip[aria-pressed="true"] { background: #20c997; color: #06150f; }
|
||
|
||
/* Am 800er-Display zweispaltig ohne Scrollen. */
|
||
.anzeige #modalEV .modal-dialog:has(.lade) { max-width: 46rem; }
|
||
.anzeige .lade { grid-template-columns: 15rem minmax(0, 1fr); gap: 1rem; padding: .7rem .9rem; }
|
||
.anzeige .lade .lade-status { grid-template-columns: 1fr; justify-items: center; text-align: center; gap: .5rem; }
|
||
.anzeige .lade .lade-auto { justify-content: center; }
|
||
.anzeige .lade .lade-modus > span:last-child { display: none; }
|
||
.anzeige .lade .lade-rechts,
|
||
.anzeige .lade .lade-links { gap: .6rem; }
|
||
.anzeige #modalEV .modal-body:has(.lade) { max-height: none; overflow: visible; }
|
||
.anzeige #modalEV .modal-content:has(.lade) .modal-footer { display: none; }
|
||
.anzeige #modalEV .modal-content:has(.lade) .modal-header { padding: .45rem .9rem; }
|
||
.anzeige .lade.heiz .lade-status { grid-template-columns: 1fr; justify-items: center; }
|
||
.anzeige .lade.heiz .heiz-tank { width: 6.5rem; }
|
||
.anzeige .lade.wasser { grid-template-columns: 1fr; }
|
||
.anzeige .lade.wasser .wasser-zonen { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||
.anzeige .lade.wasser .wasser-fuss { flex-direction: column; align-items: stretch; }
|
||
.anzeige .lade.wasser .wasser-knopf { width: 100%; justify-content: center; }
|
||
|
||
/* --- Karte: Umschalter Übersicht / Anlage -------------------------------- */
|
||
.enf-umschalter { display: inline-flex; gap: 2px; padding: 3px; border-radius: var(--ton-radius-klein, .5rem); background: var(--ton-grund, #191d20); }
|
||
.enf-umschalter .btn.btn-sm { border: 0; color: var(--ton-schrift-2, #9aa6ad); font-weight: 600; padding: .2rem .8rem; }
|
||
.enf-umschalter .btn.btn-sm.active { background: var(--ton-flaeche-2, #2b3237); color: var(--ton-schrift, #e8ede9); }
|
||
.enf-ansicht[hidden] { display: none !important; }
|
||
.enf-ansicht.enf-rein { animation: enf-ansicht-rein .35s cubic-bezier(.2, .7, .2, 1); }
|
||
@keyframes enf-ansicht-rein { from { opacity: 0; transform: scale(.98); } }
|