    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    :root {
      --bg:       #0f172a;
      --surface:  #1e293b;
      --surface2: #263348;
      --border:   #334155;
      --text:     #f1f5f9;
      --text2:    #94a3b8;
      --text3:    #64748b;
      --accent:   #06b6d4;
      --accent2:  #0891b2;
      --green:    #22c55e;
      --yellow:   #eab308;
      --red:      #ef4444;
      --orange:   #f97316;
      --radius:   14px;
      --gap:      16px;
      --header-basis: 57px;
      --kopie-h: 0px;                       /* wird zum Banner, s.u. */
      --header-h: calc(var(--header-basis) + var(--kopie-h));
    }

    html { height: 100%; }
    /* body MUSS mitwachsen duerfen. Mit height:100% war die Box exakt
       bildschirmhoch, waehrend der Inhalt darueber hinauslief — und ein
       haftendes Element (die Statusleiste) ist an die Box seines Elternteils
       gebunden. Am Telefon rutschte sie deshalb nach etwa 600 px doch noch
       aus dem Bild. */
    body { min-height: 100%; background: var(--bg); color: var(--text);
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      -webkit-font-smoothing: antialiased; }

    /* ── Header ── */
    header {
      display: grid; grid-template-columns: 1fr auto 1fr;
      align-items: center;
      padding: 14px 20px 12px; border-bottom: 1px solid var(--border);
      background: var(--surface); position: fixed; top: 0; left: 0; right: 0; z-index: 101;
    }
    .logo { font-size: 20px; font-weight: 700; letter-spacing: .18em;
      color: var(--accent); text-transform: uppercase;
      /* Nie umbrechen: die Versionsnummer rutschte sonst unter den Schriftzug
         und machte die Kopfzeile eine Zeile hoeher. Passt sie nicht mehr
         daneben, wird sie ausgeblendet (siehe _kopfLogoPruefen in core.js). */
      white-space: nowrap; min-width: 0; }
    .logo.ohne-version .logo-ver { display: none; }
    .logo span { color: var(--text2); font-weight: 400; font-size: 13px;
      letter-spacing: .04em; margin-left: 10px; }
    .header-right { display: flex; align-items: center; gap: 10px; justify-self: end; grid-column: 3; }
    .conn-badge { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--text2); }
    .conn-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--red); transition: background .4s; }
    .conn-dot.ok   { background: var(--green); }
    .conn-dot.warn { background: var(--yellow); animation: pulse 1.5s infinite; }
    @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.35} }

    /* ── Icon button (shared) ── */
    .icon-btn {
      background: none; border: 1px solid var(--border); border-radius: 8px;
      color: var(--text2); cursor: pointer; padding: 6px 8px;
      display: flex; align-items: center; transition: all .15s;
    }
    .icon-btn:hover { background: var(--surface2); color: var(--accent); border-color: var(--accent2); }
    .icon-btn:focus { outline: none; }
    /* aktive Seite: blauer Rahmen-Indikator (wie zuvor nur beim Internet-Button) */
    .icon-btn.nav-active { border-color: var(--accent2); color: var(--accent);
      box-shadow: 0 0 0 1px var(--accent2); }

    /* ── Burger-Menü (nur Mobile) ── */
    .burger-wrap { position: relative; display: none; }
    .burger-menu { position: absolute; top: calc(100% + 8px); right: 0; z-index: 200;
      background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
      padding: 6px; min-width: 160px; display: flex; flex-direction: column; gap: 2px;
      box-shadow: 0 8px 24px rgba(0,0,0,.4); }
    .burger-menu.hidden { display: none; }
    .burger-item { background: none; border: none; color: var(--text1); cursor: pointer;
      padding: 9px 12px; border-radius: 8px; font-size: 14px; text-align: left;
      display: flex; align-items: center; gap: 10px; transition: background .12s; }
    .burger-item:hover { background: var(--surface2); }
    .burger-alarm-count { background: var(--red); color: #fff; border-radius: 999px;
      font-size: 10px; font-weight: 700; padding: 1px 6px; margin-left: 4px; }
    .burger-alarm-count.hidden { display: none; }
    /* Roter Punkt auf dem Burger-Button wenn Alarme aktiv */
    #burgerBtn.has-alarm::after { content: ''; position: absolute; top: 4px; right: 4px;
      width: 7px; height: 7px; background: var(--red); border-radius: 50%; border: 1.5px solid var(--surface); }
    #burgerBtn { position: relative; }
    /* Ab hier traegt das Burger-Menue die Werkzeugknoepfe.
       Die Schwelle lag bei 600 px — und genau darueber erschienen ALLE acht
       Icon-Knoepfe auf einmal. Am Geraet gemessen: .header-right springt damit
       von 213 auf 501 px, zusammen mit dem Logo passt das nicht in eine Zeile,
       und die Kopfzeile bricht auf 96 px um (bei 640 px Fensterbreite). Weil
       --header-h eine feste Zahl war, verschwanden dann 23 px der Statusleiste
       dahinter, und die Detailseiten begannen ebenfalls zu hoch.
       Erst ab rund 830 px passt die volle Knopfreihe neben Logo und Uhr. */
    @media (max-width: 900px) {
      .burger-hide { display: none !important; }
      .burger-wrap { display: block; }
      .header-right { justify-content: flex-end; margin-left: auto; gap: 6px; }
      /* Internet: nur Anzeige, kein Button-Verhalten. Die Alarmglocke daneben
         bleibt ausdruecklich tippbar — ein Alarm will geoeffnet werden. */
      #connInetBtn { pointer-events: none; cursor: default;
        background: none !important; border-color: transparent !important;
        box-shadow: none !important; padding: 4px 2px; }
    }
    /* ── Kiosk-Chrome (fester Display): linke Sidebar + Slide-down Topbar ──
       Im Kiosk-Modus werden Header (oben) und alte Bottom-Nav entfernt. */
    :root { --kiosk-side-w: 84px; --kiosk-handle-h: 22px; }
    .kiosk-nav { display: none; }                 /* alte Bottom-Nav: aus */

    .kiosk-mode header { display: none; }

    /* Linke Sidebar */
    .kiosk-sidebar { display: none; }
    .kiosk-mode .kiosk-sidebar {
      display: flex; flex-direction: column; gap: 6px;
      position: fixed; top: 0; left: 0; bottom: 0; width: var(--kiosk-side-w);
      background: var(--surface); border-right: 1px solid var(--border);
      padding: 12px 8px; z-index: 60;
    }
    .kiosk-side-btn {
      display: flex; flex-direction: column; align-items: center; gap: 6px;
      padding: 14px 4px; border: none; background: none; color: var(--text3);
      border-radius: 14px; cursor: pointer; font-size: 11px; font-weight: 600;
      transition: background .15s, color .15s; -webkit-tap-highlight-color: transparent;
    }
    .kiosk-side-btn:hover  { background: var(--surface2); color: var(--accent); }
    .kiosk-side-btn.active { background: var(--surface2); color: var(--accent); }
    .kiosk-side-btn.active svg { filter: drop-shadow(0 0 4px var(--accent)); }

    .kiosk-mode main {
      padding-left: calc(var(--kiosk-side-w) + var(--gap));
      padding-top: calc(var(--gap) + var(--kiosk-handle-h));
      padding-bottom: var(--gap);
    }
    .kiosk-mode .overlay { padding-left: var(--kiosk-side-w); padding-bottom: 0; }

    /* Slide-down Topbar */
    .kiosk-top { display: none; }
    .kiosk-mode .kiosk-top {
      display: block; position: fixed; top: 0; left: var(--kiosk-side-w); right: 0;
      z-index: 65; pointer-events: none;
    }
    .kiosk-top-panel {
      pointer-events: auto; background: var(--surface);
      border-bottom: 1px solid var(--border);
      border-bottom-left-radius: 18px; border-bottom-right-radius: 18px;
      padding: 16px 22px 18px; box-shadow: 0 10px 30px rgba(0,0,0,.4);
      transform: translateY(-100%); transition: transform .32s cubic-bezier(.4,0,.2,1);
    }
    .kiosk-top.open .kiosk-top-panel { transform: translateY(0); }
    .kiosk-top-handle {
      pointer-events: auto; position: absolute; top: 0; left: 50%;
      transform: translateX(-50%); width: 72px; height: var(--kiosk-handle-h);
      background: var(--surface); border: 1px solid var(--border); border-top: none;
      border-bottom-left-radius: 12px; border-bottom-right-radius: 12px;
      color: var(--text3); cursor: pointer; display: flex; align-items: center;
      justify-content: center; transition: color .15s;
    }
    .kiosk-top-handle:hover { color: var(--accent); }
    .kiosk-top-handle svg { transition: transform .32s; }
    .kiosk-top.open .kiosk-top-handle svg { transform: rotate(180deg); }

    .ktp-status { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
    .ktp-clock  { font-size: 28px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text); }
    .ktp-batt   { display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 600; color: var(--text3); }
    .ktp-quick  { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; }
    .ktp-tile   { background: var(--surface2); border: 1px solid var(--border); border-radius: 14px;
      padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; min-height: 78px; justify-content: space-between; }
    .ktp-tile.disabled { opacity: .45; }
    .ktp-tile-lbl { font-size: 11px; color: var(--text3); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
    .ktp-toggle { border: 1px solid var(--border); background: var(--surface); color: var(--text2);
      border-radius: 10px; padding: 9px; font-size: 14px; font-weight: 700; cursor: pointer;
      font-family: inherit; transition: all .15s; }
    .ktp-toggle:hover:not(:disabled) { border-color: var(--accent2); }
    .ktp-toggle:disabled { cursor: not-allowed; }
    .ktp-toggle.on  { background: #22c55e22; border-color: #22c55e; color: #22c55e; }
    .ktp-range { width: 100%; accent-color: var(--accent2); cursor: pointer; }

    /* Mini-Toast */
    .mini-toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(20px);
      background: var(--surface); border: 1px solid var(--border); color: var(--text);
      padding: 10px 18px; border-radius: 10px; font-size: 13px; z-index: 9998;
      box-shadow: 0 8px 24px rgba(0,0,0,.4); opacity: 0; transition: opacity .2s, transform .2s; pointer-events: none; }
    .mini-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

    /* ── Kachel-Engine (Grid) ───────────────────────────────────────────────
       Eine Basis-Einheit: normale Kachel = Quadrat (Breite == Höhe).
       half = halbe Höhe · wide = doppelte Breite (gleiche Höhe).
       Spaltenzahl + Zeilenhöhe setzt JS (_applyGrid in display.js);
       grid-auto-flow:dense packt automatisch — keine Lücken oben. */
    main { display: grid; gap: var(--gap); padding: var(--gap);
      padding-top: calc(var(--header-h) + var(--gap));
      grid-template-columns: 1fr;          /* ab 640px von JS gesetzt */
      grid-auto-flow: row dense; }
    @media (min-width: 1024px) { main { max-width: 1240px; margin: 0 auto; } }
    @media (min-width: 1600px) { main { max-width: 1660px; } }
    #wartungHomeBody { overflow: hidden; }

    /* ── Heizung ──────────────────────────────────────────────────────────
       Kachel: nur Zustand, Preset-Wahl und die Raeume. Alles Weitere steht
       auf der Detailseite. */
    .hz-leer { font-size: 13px; color: var(--text3); padding: 4px 0; }
    .hz-kopf { display: flex; align-items: baseline; gap: 10px;
      flex-wrap: wrap; margin-bottom: 12px; }
    .hz-zustand  { font-size: 22px; font-weight: 700; line-height: 1; }
    .hz-leistung { font-size: 14px; font-weight: 700; color: var(--text2);
      font-variant-numeric: tabular-nums; }
    .hz-vorlauf  { margin-left: auto; font-size: 12px; color: var(--text3);
      font-variant-numeric: tabular-nums; white-space: nowrap; }

    .hz-presets { display: flex; flex-wrap: wrap; gap: 6px; }
    .hz-preset  { font-family: inherit; font-size: 12px; font-weight: 600;
      padding: 6px 11px; border-radius: 9px; cursor: pointer; white-space: nowrap;
      border: 1px solid var(--border); background: var(--surface2); color: var(--text2);
      transition: border-color .15s, color .15s; }
    .hz-preset:hover:not(:disabled) { border-color: var(--accent2); }
    .hz-preset.an { border-color: var(--accent); color: var(--accent); }
    .hz-preset:disabled { opacity: .5; cursor: default; }
    .hz-preset:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

    .hz-raeume { display: flex; flex-direction: column; gap: 2px; margin-top: 12px; }
    /* Bei zehn Raeumen lief die Liste unten aus der Kachel heraus — die Kachel
       hat im Raster eine feste Hoehe und overflow:hidden. Die Kachel zeigt
       deshalb nur die ersten Raeume und sagt, wie viele noch folgen; alle
       stehen auf der Detailseite. Eine scrollende Liste waere hier falsch:
       ein Tipp auf die Kachel oeffnet die Detailseite, Scrollen und Tippen
       kaemen sich auf dem Touchscreen ins Gehege. */
    .hz-mehr { font-size: 12px; color: var(--text3); padding: 6px 2px 0; }
    /* [hidden] muss gewinnen: die eingebaute Browserregel [hidden]{display:none}
       hat nur Element-Spezifitaet und wird von .hz-raum{display:grid} geschlagen —
       ausgeblendete Zeilen belegten dadurch weiter Platz und schoben die
       Fusszeile aus der Kachel. */
    [hidden] { display: none !important; }
    /* Werte, die aus einer alten Meldung stammen: sichtbar, aber zurueckgenommen. */
    .hz-alt { opacity: .45; }
    .hz-weg { color: var(--yellow); border: 1px solid var(--yellow);
      border-radius: 8px; padding: 7px 10px; margin-bottom: 10px; }
    .hz-raum   { display: grid; align-items: baseline; gap: 8px;
      grid-template-columns: minmax(0, 1fr) auto auto auto 14px;
      padding: 4px 0; font-size: 13px; font-variant-numeric: tabular-nums; }
    .hz-raum + .hz-raum { border-top: 1px solid var(--border); }
    .hz-raum-aus { opacity: .5; }
    /* In der Raumkarte darf NICHT die ganze Karte gedaempft werden: der
       Schalter oben rechts muss ablesbar bleiben, sonst findet man den Weg
       zurueck nicht. opacity auf der Karte liesse sich im Kind nicht wieder
       zuruecknehmen (eigener Stapelkontext), deshalb wird gezielt der Inhalt
       gedaempft und die Kopfzeile bleibt klar. */
    .hz-raumkarte.hz-raum-aus { opacity: 1; }
    .hz-raumkarte.hz-raum-aus .hz-soll,
    .hz-raumkarte.hz-raum-aus .sb-stats,
    .hz-raumkarte.hz-raum-aus .hz-presets,
    .hz-raumkarte.hz-raum-aus .hz-tempo { opacity: .5; }
    .hz-raum-name  { color: var(--text2); overflow: hidden;
      text-overflow: ellipsis; white-space: nowrap; }
    .hz-raum-ist   { font-weight: 700; }
    .hz-raum-ist i, .hz-raum-soll i { font-style: normal; font-size: 10px; color: var(--text3); }
    .hz-raum-pfeil { color: var(--text3); font-size: 11px; }
    .hz-raum-soll  { color: var(--text2); font-weight: 600; }
    .hz-raum-flag  { display: flex; justify-content: flex-end; }
    .hz-punkt   { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
    .hz-aus-txt { font-size: 10px; color: var(--text3); }

    .hz-hinweis { font-size: 12px; color: var(--text3); margin-top: 10px; }
    .hz-fehler  { color: var(--red); }
    /* Erfundene Werte muessen unuebersehbar als solche erkennbar sein. */
    /* Ein Schaltbefehl steht 60 s an, bevor er wirkt — das muss sichtbar sein,
       sonst wirkt die Anlage traege statt bedacht. */
    .hz-pending { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
      margin: 10px 0; padding: 7px 10px; border-radius: 9px;
      background: var(--surface2); font-size: 12px; color: var(--yellow);
      font-variant-numeric: tabular-nums; }
    .hz-mini { font-family: inherit; font-size: 11px; font-weight: 600;
      padding: 3px 9px; border-radius: 7px; cursor: pointer;
      border: 1px solid var(--border); background: var(--surface); color: var(--text2); }
    .hz-mini:hover { border-color: var(--accent2); }

    /* ── Heizung: Detailseite ── */
    .hz-raeume-grid { display: grid; gap: var(--gap); margin-bottom: var(--gap);
      grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); align-items: stretch; }
    .hz-raumkarte { margin-bottom: 0; }
    .hz-soll { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
      gap: 14px; align-items: center; margin-top: 4px; }
    .hz-soll-mitte { text-align: center; min-width: 0; }
    .hz-soll-wert  { display: block; font-size: 30px; font-weight: 700; line-height: 1.1;
      font-variant-numeric: tabular-nums; }
    .hz-soll-wert i { font-style: normal; font-size: 13px; color: var(--text2);
      font-weight: 600; margin-left: 2px; }
    .hz-soll-ist   { display: block; font-size: 12px; color: var(--text3);
      font-variant-numeric: tabular-nums; margin-top: 2px; }
    /* Geblaesestaerke im Handbetrieb — erscheint nur, wenn der Raum auf Hand steht */
    .hz-tempo { margin-top: 12px; }
    .hz-tempo-kopf { display: flex; justify-content: space-between; align-items: baseline;
      font-size: 12px; color: var(--text2); margin-bottom: 6px; }
    .hz-tempo-kopf span { color: var(--text); font-variant-numeric: tabular-nums; }
    .hz-tempo-kopf b { font-size: 15px; font-weight: 700; }
    /* Griffflaeche fuer den Finger am Touchscreen, nicht nur fuer die Maus */
    .hz-tempo-regler { width: 100%; height: 28px; accent-color: var(--accent2);
      cursor: pointer; touch-action: none; }
    .hz-tempo-regler:disabled { opacity: .5; cursor: default; }
    .hz-tempo-regler:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

    .hz-rund { font-family: inherit; font-size: 20px; font-weight: 700; line-height: 1;
      width: 44px; height: 44px; border-radius: 50%; cursor: pointer; flex-shrink: 0;
      border: 1px solid var(--border); background: var(--surface2); color: var(--text); }
    .hz-rund:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
    .hz-rund:disabled { opacity: .5; cursor: default; }
    .hz-rund:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

    /* ── Stromverlauf (eigene Seite) ──────────────────────────────────────
       Nach Cerbo-Vorbild: Erzeugung als gestapelte Flaeche, Verbrauch als
       Linie darueber, darunter die Energiesummen des Fensters. */
    .vl-karte { background: var(--surface); border: 1px solid var(--border);
      border-radius: var(--radius); padding: 16px 18px;
      max-width: 1500px; margin: 0 auto; }
    .vl-kopf  { display: flex; align-items: center; gap: 10px;
      flex-wrap: wrap; margin-bottom: 14px; }
    .vl-bereiche { display: flex; gap: 6px; flex-wrap: wrap; }
    .vl-btn   { font-family: inherit; font-size: 12px; font-weight: 600;
      padding: 6px 12px; border-radius: 9px; cursor: pointer;
      border: 1px solid var(--border); background: var(--surface2); color: var(--text2); }
    .vl-btn:hover { border-color: var(--accent2); }
    .vl-btn.an { border-color: var(--accent); color: var(--accent); }
    .vl-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
    .vl-chart { width: 100%; height: 300px; display: block; }
    /* Wochentrend: fuellt die Kachel aus.
       Vorher stand er auf festen 210 px, waehrend die Kachel im Raster auf die
       Zeilenhoehe gestreckt wird — darunter blieb sichtbar Luft stehen. Jetzt
       waechst das Diagramm mit; 210 px bleiben die Untergrenze, damit die
       sieben Balkenpaare auch in einer flachen Zeile lesbar sind. */
    .vl-week-chart { width: 100%; height: 210px; min-height: 210px;
      flex: 1; display: block; }
    .vl-titel { font-size: 11px; font-weight: 700; letter-spacing: .08em;
      text-transform: uppercase; color: var(--text3); }
    .vl-legende { display: flex; align-items: center; gap: 12px; margin-left: auto;
      font-size: 10px; color: var(--text3); flex-wrap: wrap; }
    .vl-legende i { display: inline-block; width: 8px; height: 8px; border-radius: 2px;
      margin-right: 5px; vertical-align: -1px; }
    /* Leerzustand: KEIN gezeichnetes Diagramm mit erfundener Achse. */
    .vl-leer { display: flex; align-items: center; justify-content: center;
      min-height: 120px; padding: 22px 16px; text-align: center;
      font-size: 13px; color: var(--text3); line-height: 1.6; }
    @media (max-width: 639px) { .vl-chart { height: 220px; } }
    .vl-summen { display: grid; gap: 10px 22px; margin-top: 14px;
      padding-top: 14px; border-top: 1px solid var(--border);
      grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
    .vl-summe-zeile { display: flex; align-items: center; gap: 9px; font-size: 13px; min-width: 0; }
    .vl-punkt { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
    .vl-name  { color: var(--text2); overflow: hidden;
      text-overflow: ellipsis; white-space: nowrap; }
    .vl-wh    { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
    .vl-hinweis { font-size: 12px; color: var(--text3); margin-top: 10px; }

    /* ── Batterie: die Antwort zuerst ─────────────────────────────────────
       Die Seite beantwortete bisher nirgends die Frage, mit der man sie
       oeffnet: reicht der Strom? Der Shunt liefert dafuer kein ttg, aus
       Restenergie und Verbrauch laesst es sich aber rechnen. */
    .ba-antwort { display: grid; gap: 22px 28px; align-items: center;
      grid-template-columns: 200px minmax(0, 1fr); }
    @media (max-width: 700px) { .ba-antwort { grid-template-columns: 1fr; gap: 16px; } }
    .ba-ring     { width: 100%; max-width: 200px; height: auto; display: block; margin: 0 auto; }
    .ba-ring-num { font-size: 40px; font-weight: 700; font-family: inherit; }
    .ba-ring-lbl { font-size: 11px; font-weight: 600; fill: var(--text3); font-family: inherit; }
    .ba-kopf     { font-size: clamp(20px, 3.4vw, 27px); font-weight: 700;
      line-height: 1.2; letter-spacing: -.01em; text-wrap: balance; }
    .ba-kopf small { display: block; font-size: 13px; font-weight: 500;
      color: var(--text3); margin-top: 6px; letter-spacing: 0; }
    .ba-kette { display: flex; flex-wrap: wrap; gap: 6px 20px; margin-top: 14px;
      font-size: 13px; color: var(--text3); font-variant-numeric: tabular-nums; }
    .ba-kette b { color: var(--text2); font-weight: 600; }

    /* ── Batterie: gerichtete Bilanz ── */
    .ba-fluss { display: grid; gap: 18px; align-items: center;
      grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
    @media (max-width: 760px) { .ba-fluss { grid-template-columns: 1fr; gap: 14px; } }
    .ba-seite { display: flex; flex-direction: column; gap: 9px; min-width: 0; }
    .ba-zeile { display: grid; grid-template-columns: 9px minmax(0, 1fr) auto;
      gap: 9px; align-items: center; font-size: 13px; }
    .ba-punkt { width: 9px; height: 9px; border-radius: 3px; }
    .ba-name  { color: var(--text2); overflow: hidden;
      text-overflow: ellipsis; white-space: nowrap; }
    .ba-watt  { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
    .ba-bahn  { grid-column: 2 / 4; height: 5px; border-radius: 3px;
      background: var(--surface2); overflow: hidden; margin-top: -3px; }
    .ba-bahn div { height: 100%; border-radius: 3px; transition: width .4s ease; }
    .ba-mitte { display: flex; flex-direction: column; align-items: center;
      gap: 3px; padding: 0 8px; white-space: nowrap; }
    .ba-mitte b { font-size: 25px; font-weight: 700; line-height: 1;
      font-variant-numeric: tabular-nums; }
    .ba-mitte span { font-size: 10px; font-weight: 700; letter-spacing: .08em;
      text-transform: uppercase; color: var(--text3); }
    .ba-pfeil { color: var(--text3); font-size: 17px; line-height: 1; }
    @media (max-width: 760px) { .ba-pfeil { transform: rotate(90deg); } }

    /* ── Batterie: Zellen als Abweichung vom Mittel ───────────────────────
       Absolute 3.335 gegen 3.340 sagt beim Draufschauen nichts. Die
       Abweichung zeigt sofort, welche Zelle ausreisst. */
    .ba-zellen { display: flex; flex-direction: column; gap: 8px; }
    /* Fuenf Spalten: Nummer, Spannung, Abweichungsbahn, Millivolt, Temperatur.
       Die Temperaturspalte traegt die zweite Farbe der Karte und wird nur
       gefuellt, wenn ueberhaupt eine Zelle eine Temperatur meldet — das
       Element bleibt aber erhalten, sonst verrutscht das Raster der Zeile. */
    .ba-zeile-z { display: grid;
      grid-template-columns: 24px 62px minmax(0, 1fr) 58px auto;
      gap: 9px; align-items: center; font-size: 12px; }
    .ba-znr   { color: var(--text3); font-weight: 700; }
    /* Absolute Zellspannung — ersetzt die frueher nur mobil gezeigte Kachel. */
    .ba-zv    { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
    .ba-zv small { color: var(--text3); font-weight: 600; font-size: 10px; }
    .ba-bahn-z{ position: relative; height: 16px; background: var(--surface2); border-radius: 4px; }
    .ba-null  { position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: var(--border); }
    .ba-bar-z { position: absolute; top: 3px; bottom: 3px; border-radius: 2px; transition: all .4s ease; }
    /* Ueber der Skala: der Balken ist geklemmt. Ohne Markierung wuerde eine
       Zelle mit 200 mV Abweichung genauso aussehen wie eine mit 76 mV. */
    .ba-bar-ueber { border-radius: 2px 0 0 2px;
      background-image: linear-gradient(135deg, rgba(255,255,255,.45) 25%, transparent 25%,
        transparent 50%, rgba(255,255,255,.45) 50%, rgba(255,255,255,.45) 75%, transparent 75%);
      background-size: 6px 6px; }
    .ba-mv    { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
    .ba-zt    { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums;
      min-width: 30px; font-size: 11px; }
    @media (max-width: 420px) {
      /* Auf sehr schmalen Geraeten hat die Bahn sonst weniger Platz als die
         Zahlen daneben — dann lieber die Bahn schmaler als die Werte kuerzen. */
      .ba-zeile-z { grid-template-columns: 20px 54px minmax(0, 1fr) 48px auto;
        gap: 6px; font-size: 11px; }
      .ba-zt { min-width: 26px; font-size: 10px; }
    }

    /* ── Batterie-Detail: Servicebatterie als EINE Karte ───────────────────
       Vorher war die Bank auf zwei Kacheln zerlegt (Shunt-Werte hier,
       BMS-Werte dort) und die BMS-Zellen standen neben der Starterbatterie,
       mit der sie nichts zu tun haben. Shunt und BMS sind zwei Messquellen
       DERSELBEN Batterie und gehoeren deshalb zusammen.
       Die Energieringe zeigen die Quellen als wachsende Kreise um den SOC. */
    .sb-card { background: var(--surface); border: 1px solid var(--border);
      border-radius: var(--radius); padding: 20px; margin-bottom: var(--gap); }
    .sb-hd { display: flex; align-items: center; gap: 8px; margin-bottom: 16px;
      font-size: 12px; font-weight: 700; letter-spacing: .07em;
      text-transform: uppercase; color: var(--text2); }
    .sb-hd .chip { margin-left: auto; }
    /* Die Kopfzeile setzt Grossbuchstaben — in den Chips stehen aber Einheiten,
       und aus "19 mV" wurde damit "19 MV", also Megavolt. */
    .sb-hd .chip { text-transform: none; letter-spacing: .02em; }
    /* Nur der ERSTE Chip wird nach rechts geschoben — die folgenden reihen sich
       daneben ein, statt auseinandergerissen zu werden. */
    .sb-hd .chip ~ .chip { margin-left: 0; }
    .sb-grid { display: grid; gap: 24px; align-items: center;
      grid-template-columns: 230px 190px minmax(0, 1fr); }
    @media (max-width: 1050px) { .sb-grid { grid-template-columns: 230px minmax(0, 1fr); } }
    @media (max-width: 700px)  { .sb-grid { grid-template-columns: 1fr; } }


    /* Kennzahlen — Spalten breit genug, dass kein Label abgeschnitten wird */
    .sb-stats { display: grid; gap: 16px 18px;
      grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); }
    .st   { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
    .st-l { font-size: 10px; font-weight: 700; letter-spacing: .08em;
      text-transform: uppercase; color: var(--text3);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .st-v { font-size: 20px; font-weight: 700; line-height: 1.15;
      font-variant-numeric: tabular-nums; white-space: nowrap; }
    .st-v small { font-size: 11px; font-weight: 600; color: var(--text2); margin-left: 3px; }

    /* Zellen gehoeren zur Servicebatterie und stehen deshalb IN deren Karte */
    .sb-cells    { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); }
    .sb-cells-hd { display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
      font-size: 10px; font-weight: 700; letter-spacing: .08em;
      text-transform: uppercase; color: var(--text3); }
    /* 62px: bei 320px Geraetebreite bleiben nach Kartenpolster und Luecken
       rund 68px je Spalte — mit 74px waere die vierte Zelle allein in eine
       zweite Reihe gerutscht. */
    .cellrow { display: grid; gap: 8px;
      grid-template-columns: repeat(auto-fit, minmax(62px, 1fr)); }
    .cell    { background: var(--surface2); border-radius: 9px; padding: 8px 6px; text-align: center; }
    .cell-nr { font-size: 10px; font-weight: 700; color: var(--text3); }
    .cell-v  { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
    .cell-t  { font-size: 10px; color: var(--text3); font-variant-numeric: tabular-nums; }
    .cell.lo .cell-v { color: var(--yellow); }   /* niedrigste Zelle */
    .cell.hi .cell-v { color: var(--accent); }   /* hoechste Zelle */
    .chip    { font-size: 10px; font-weight: 700; padding: 2px 8px; border-radius: 6px;
      background: var(--surface2); color: var(--text3); white-space: nowrap; }
    .chip.on   { background: #22c55e1a; color: var(--green); }
    .chip.warn { background: #eab3081a; color: var(--yellow); }
    .chip.err  { background: #ef44441a; color: var(--red); }

    /* Starterbatterie: eigene, bewusst kleinere Karte — hat mit der Bank nichts zu tun */
    .starter { background: var(--surface); border: 1px solid var(--border);
      border-radius: var(--radius); padding: 20px; margin-bottom: var(--gap);
      display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }

    /* Widerspruch zwischen eingestellter Bankkapazitaet und BMS-Restenergie.
       Bewusst auffaellig: die Autonomie-Aussage darueber haengt daran. */
    .ba-streit { display: flex; align-items: flex-start; gap: 8px; margin-top: 12px;
      padding: 9px 12px; border-radius: 8px; font-size: 12px; line-height: 1.5;
      color: var(--yellow); background: rgba(234,179,8,.10);
      border: 1px solid rgba(234,179,8,.35); }
    .ba-streit svg { flex-shrink: 0; margin-top: 2px; }
    .ba-streit b { color: var(--text1); }

    /* Geraete-Kacheln unter dem Verlauf: gleich hoch, kein Treppeneffekt */
    .bd-flow { display: grid; gap: var(--gap); margin-bottom: var(--gap);
      grid-template-columns: repeat(auto-fit, minmax(178px, 1fr)); align-items: stretch; }
    .bd-src  { background: var(--surface); border: 1px solid var(--border);
      border-left: 3px solid var(--border); border-radius: var(--radius);
      padding: 16px; display: flex; flex-direction: column; gap: 10px; min-width: 0;
      /* Die Kacheln fuellen die Rasterzeile. Ohne space-between klebt alles
         oben und unten bleibt ein Streifen Luft — die Kachel sieht dann aus,
         als waere sie zu gross geraten, statt bewusst so hoch zu sein. */
      justify-content: space-between; }
    .bd-src-ok { border-left-color: var(--green); }
    .bd-src-warn { border-left-color: var(--yellow); }
    .bd-src-err { border-left-color: var(--red); }
    .bd-src-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
    .bd-src-name { font-size: 11px; font-weight: 700; letter-spacing: .06em;
      text-transform: uppercase; color: var(--text2); min-width: 0;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .bd-src-head .chip { margin-left: auto; }
    .bd-src-main { display: flex; align-items: baseline; gap: 4px;
      font-variant-numeric: tabular-nums; }
    .bd-src-main b { font-size: 26px; font-weight: 700; line-height: 1; }
    .bd-src-main span { font-size: 12px; font-weight: 600; color: var(--text2); }
    .bd-src-sub { font-size: 12px; color: var(--text3); margin-top: auto;
      font-variant-numeric: tabular-nums;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* ── Gemeinsamer Start ────────────────────────────────────────────────
       Die Kacheln haengen an verschiedenen Quellen (/api/status, waterlevel,
       weather, wartung, Heizung) mit sehr verschiedenen Antwortzeiten. Ohne
       diese Sperre baut sich die Seite beim Neuladen stueckweise auf. Mit
       opacity statt display bleibt das Layout gerechnet — Canvas-Breiten
       stimmen also von Anfang an, was bei display:none nicht der Fall waere. */
    /* Waehrend des Starts: die Oberflaeche liegt unscharf darunter, davor ein
       Ladekreis. Vorher wurde sie schlicht ausgeblendet — das war ruhiger, aber
       man sah eine leere Seite und wusste nicht, ob noch etwas kommt. Unscharf
       zeigt, dass gleich etwas da ist, und verhindert trotzdem, dass man
       halbfertige Zahlen abliest. */
    html.startet main,
    html.startet .statusbar {
      filter: blur(7px);
      opacity: .45;
      pointer-events: none;
      user-select: none;
    }
    main, .statusbar { transition: filter .35s ease, opacity .35s ease; }

    .ladeschirm {
      position: fixed; inset: 0; z-index: 250;
      display: flex; flex-direction: column; align-items: center; justify-content: center;
      gap: 16px; pointer-events: none;
      background: color-mix(in srgb, var(--bg) 45%, transparent);
      transition: opacity .3s ease;
    }
    /* Sobald der Start freigegeben ist, ist die Klasse weg — dann auch der
       Schirm. Kein eigener Zeitgeber: er haengt an derselben Entscheidung wie
       die Kacheln, sonst laufen beide auseinander. */
    html:not(.startet) .ladeschirm { opacity: 0; visibility: hidden; }
    /* Steht die Anmeldung an, hat sie Vorrang — zwei uebereinanderliegende
       Schirme waeren nur verwirrend. */
    html.anmeldung-offen .ladeschirm { display: none; }

    .lade-kreis {
      width: 38px; height: 38px; border-radius: 50%;
      border: 3px solid color-mix(in srgb, var(--accent) 22%, transparent);
      border-top-color: var(--accent);
      animation: lade-dreh .8s linear infinite;
    }
    @keyframes lade-dreh { to { transform: rotate(360deg); } }
    @media (prefers-reduced-motion: reduce) {
      /* Wer Bewegung abbestellt hat, bekommt ein Pulsieren statt der Drehung. */
      .lade-kreis { animation: lade-puls 1.4s ease-in-out infinite; }
      @keyframes lade-puls { 50% { opacity: .3; } }
    }
    .lade-text {
      font-size: 12px; font-weight: 600; letter-spacing: .06em;
      text-transform: uppercase; color: var(--text2);
    }
    main, .statusbar { opacity: 1; transition: opacity .18s ease; }

    /* ── Kacheln anordnen ─────────────────────────────────────────────────
       Eigener Modus statt dauerhaftem Ziehen: am Kartentisch haengt ein
       Touchscreen, und ein versehentlich verschobenes Dashboard waere
       aergerlicher als ein Klick mehr zum Einschalten. */
    .ordnen-leiste { position: fixed; left: 50%; transform: translateX(-50%);
      bottom: calc(14px + env(safe-area-inset-bottom, 0px)); z-index: 300;
      display: flex; align-items: center; gap: 12px;
      background: var(--surface); border: 1px solid var(--accent);
      border-radius: 999px; padding: 9px 10px 9px 18px;
      box-shadow: 0 6px 24px rgba(0,0,0,.45); }
    .ordnen-leiste.hidden { display: none; }
    .ordnen-text { font-size: 13px; color: var(--text2); white-space: nowrap; }
    .ordnen-btn { background: var(--surface2); border: 1px solid var(--border);
      color: var(--text); border-radius: 999px; padding: 7px 14px;
      font-size: 13px; font-family: inherit; cursor: pointer; white-space: nowrap; }
    .ordnen-btn:hover { background: var(--border); }
    .ordnen-fertig { background: var(--accent); border-color: var(--accent); color: #06202b; font-weight: 600; }
    @media (max-width: 420px) {
      .ordnen-text { display: none; }
      .ordnen-leiste { padding: 9px 10px; }
    }
    /* Im Ordnen-Modus: Kachel als greifbar markieren, Auswahl unterdruecken. */
    body.kacheln-ordnen main > .card {
      cursor: grab; outline: 1px dashed var(--accent); outline-offset: -3px;
      user-select: none; -webkit-user-select: none; touch-action: none; }
    body.kacheln-ordnen main > .card:active { cursor: grabbing; }
    body.kacheln-ordnen main > .card.kachel-zieht {
      opacity: .65; outline-style: solid; transform: scale(.985);
      box-shadow: 0 8px 26px rgba(0,0,0,.5); }

    /* ── Statusleiste ─────────────────────────────────────────────────────
       Alle Kernwerte in einer dichten Zeile ueber den Kacheln. Jedes Feld
       fuehrt per Tap in die zugehoerige Detailansicht. Steht bewusst
       AUSSERHALB des Kachel-Grids: main setzt grid-auto-rows per JS auf
       Kachelhoehe, das wuerde die Leiste sonst auf Kachelgroesse aufblasen. */
    /* Die Statusleiste bleibt beim Scrollen stehen. Sie sitzt dafuer in einem
       eigenen Halter statt selbst sticky zu sein: die Leiste ist abgerundet
       und seitlich eingerueckt, der durchlaufende Inhalt waere sonst an den
       Ecken und neben ihr zu sehen. Der Halter traegt den Seitenhintergrund
       und die Abstaende, die vorher an der Leiste hingen. */
    .statusbar-halter {
      position: sticky; top: var(--header-h); z-index: 60;
      padding: var(--gap) var(--gap);
      background: var(--bg);
      transition: padding .18s ease;
    }
    /* Traegt den Abstand zur festen Kopfzeile und dient zugleich als Fuehler:
       sobald er unter die Kopfzeile rutscht, schaltet die Leiste auf kompakt
       (siehe _leisteKompaktFuehren in core.js). Ein eigenes Element statt
       margin am Halter, weil ein Beobachter etwas braucht, das NICHT
       mitwandert. */
    .statusbar-fuehler { height: var(--header-h); }
    .statusbar {
      margin: 0;
      /* Feste Spaltenzahl statt auto-fit: auto-fit hat zwischen 641 und
         ~690 px genau FUENF Spalten gebildet, das sechste Feld stand dann
         allein in einer zweiten Zeile neben vier leeren Zellen. */
      display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
      gap: 1px;                                  /* 1px Spalt = Haarlinie */
      background: var(--border);                 /* scheint durch den Spalt */
      border: 1px solid var(--border);
      border-radius: var(--radius); overflow: hidden;
      /* Seiten und Oberkante gehen MIT der Bewegung weg, nicht auf einen
         Schlag am Ende. Auf ganze Pixel gerundet, weil eine halbe Randlinie
         als hellerer Streifen erscheint. */
      border-top-width:   round(calc(1px * (1 - var(--leiste-eng))), 1px);
      border-left-width:  round(calc(1px * (1 - var(--leiste-eng))), 1px);
      border-right-width: round(calc(1px * (1 - var(--leiste-eng))), 1px);
    }
    main { padding-top: 0;     /* Kopf- und Leistenabstand traegt der Halter */
      /* Beim Umschalten auf die kompakte Leiste wird der Streifen um rund
         35 px flacher. Ohne diese Zeile verankert der Browser die Ansicht an
         einer Kachel und korrigiert dafuer den Scrollstand — dadurch rutscht
         der Fuehler wieder ins Bild, die Leiste klappt auf, der Scrollstand
         wird erneut korrigiert, und das Ganze flackert genau an der Schwelle.
         Nur hier abgeschaltet, nicht global: an anderer Stelle ist die
         Verankerung nuetzlich. */
      overflow-anchor: none; }

    /* ── Die Leiste dockt beim Scrollen an die Kopfzeile ──────────────────
       Sie schrumpft dabei nicht auf einen Schlag, sondern haengt am
       Scrollstand: --leiste-eng laeuft von 0 (oben, volle Leiste) bis 1
       (angedockt, flacher Streifen), und alle Groessen werden daraus
       gerechnet. Dadurch wird die Leiste von der obersten Kachel nach oben
       geschoben, statt an einer Schwelle umzuklappen.

       --leiste-eng ist ueber @property als Zahl angemeldet; nur dann laesst
       sich eine eigene Eigenschaft ueberhaupt animieren und weitervererben. */
    @property --leiste-eng {
      syntax: '<number>'; inherits: true; initial-value: 0;
    }
    @keyframes leiste-andocken { to { --leiste-eng: 1; } }

    /* Der bevorzugte Weg: die Animation laeuft am Scrollstand des Dokuments
       entlang, nicht an einem scroll-Handler. Sie ist genau ueber die Strecke
       gespannt, die die Leiste bis zum Andocken zuruecklegt. */
    @supports (animation-timeline: scroll()) {
      body {
        animation: leiste-andocken linear both;
        animation-timeline: scroll(root block);
        animation-range: 0 var(--header-h);
      }
    }
    /* Rueckfall fuer Browser ohne scroll-gesteuerte Animation (aeltere
       Chromium-Fassungen, Safari): dort schaltet der Beobachter aus core.js
       die Klasse, und der Uebergang laeuft ueber eine Transition. */
    @supports not (animation-timeline: scroll()) {
      body { transition: --leiste-eng .2s linear; }
      body.leiste-kompakt { --leiste-eng: 1; }
    }
    @media (prefers-reduced-motion: reduce) {
      body { transition: none; }
    }

    /* Alle Groessen aus dem Fortschritt gerechnet. */
    .statusbar-halter { padding: calc(var(--gap) * (1 - var(--leiste-eng))); }
    .statusbar        { border-radius: calc(var(--radius) * (1 - var(--leiste-eng))); }
    /* Groessen und Abstaende sind unten bei den Grunddefinitionen aus dem
       Fortschritt gerechnet — dort, wo sie je Bildbreite ohnehin stehen.
       Hier oben stuenden sie VOR ihnen und waeren wirkungslos. */

    /* Spaltenzahl und Randlinien lassen sich nicht stufenlos rechnen — die
       schaltet weiterhin der Beobachter, und zwar erst am Ende der Bewegung,
       wenn die Felder ohnehin schon flach sind. */
    /* Frueher schaltete hier die Klasse .leiste-kompakt Schriftgroessen,
       Randlinien und Breite auf einen Schlag um. Am Ende der Bewegung sprang
       die Leiste dadurch um 9 px flacher und 72 px breiter, und weil die
       Klasse an einem Beobachter haengt, kam der Sprung beim schnellen
       Scrollen auch noch verspaetet. Alles, was sich rechnen laesst, haengt
       jetzt am Fortschritt --leiste-eng und laeuft mit dem Finger mit. */


    .sb-item {
      background: var(--surface); border: 0; margin: 0;
      /* Aus dem Andock-Fortschritt gerechnet (--leiste-eng, siehe oben):
         beim Scrollen wird das Feld flacher, statt an einer Schwelle
         umzuklappen. */
      padding: calc(10px - 5px * var(--leiste-eng))
               calc(12px - 4px * var(--leiste-eng))
               calc(11px - 5px * var(--leiste-eng));
      /* Auf GANZE Pixel gerundet: bei gebrochenen Werten faellt die
         Reihenhoehe zwischen zwei Pixel, und der 1-px-Spalt zwischen den
         Reihen rastert mal als ein, mal als zwei Pixel — die mittlere
         Trennlinie wurde dabei sichtbar dicker und wieder duenner. Die Zeile
         darueber bleibt als Rueckfall fuer Browser ohne round() stehen.

         Nur noch am Telefon (weiter unten): dort stehen zwei Reihen
         uebereinander, und der Spalt dazwischen ist die Trennlinie, um die es
         geht. In der breiten Ansicht gibt es nur EINE Reihe und damit keine
         mittlere Linie — dort wird ungerundet gerechnet, sonst kippen fuenf
         gerundete Groessen gleichzeitig und die Leiste ruckt in 5-px-Stufen
         durch die Bewegung, statt zu gleiten. */
      min-width: 0;
      display: flex; flex-direction: column;
      gap: calc(2px * (1 - var(--leiste-eng)));
      font-family: inherit; color: inherit; text-align: left;
      cursor: pointer; transition: background .15s;
      position: relative; overflow: hidden;   /* traegt den Hintergrundgraphen */
    }
    /* Verlauf der letzten 24 Stunden als Hintergrund. Er liegt hinter dem
       Text, nimmt keine Klicks an und faerbt sich mit dem Zustand des Feldes
       (siehe .sb-ok/.sb-low/.sb-warn weiter unten) — die Flaeche wird nach
       unten hin durchsichtig, damit die Zeile darunter lesbar bleibt. */
    .sb-spark {
      /* Volle Feldhoehe, damit der Hoechstwert der Skala (bei Prozentwerten
         100 %) wirklich an der OBERKANTE des Feldes liegt und die Hoehe der
         Flaeche sich ablesen laesst. */
      position: absolute; inset: 0;
      pointer-events: none; z-index: 0;
      color: var(--text3);                    /* Vorgabe, bis ein Zustand greift */
    }
    .sb-spark svg { display: block; width: 100%; height: 100%; }
    /* Waagerechter Balken: fuellt das Feld von links nach rechts. Anders als
       der Verlauf zeigt er keinen Weg, sondern den Stand — deshalb eine
       gleichmaessige Flaeche mit klarer Kante statt eines Verlaufs. */
    .sb-balken {
      position: absolute; inset: 0 auto 0 0; width: 0;
      background: currentColor; opacity: .18;
      pointer-events: none; z-index: 0;
      color: var(--text3);
      transition: width .5s ease;
    }
    /* Wasser ist blau — Zahl und Balken. Nur im normalen Zustand: faellt der
       Stand unter die Schwellen, gewinnen weiter Gelb und Rot, sonst ginge
       genau die Warnung verloren, fuer die die Farben da sind. */
    .sb-item.sb-wasser.sb-ok .sb-val b,
    .sb-item.sb-wasser.sb-ok .sb-balken { color: var(--accent); }

    .sb-item.sb-ok   .sb-balken { color: var(--green); }
    .sb-item.sb-low  .sb-balken { color: var(--yellow); }
    .sb-item.sb-warn .sb-balken { color: var(--red); }
    .sb-item.sb-idle .sb-balken { color: var(--text3); }
    /* Der Inhalt gehoert ueber den Graphen. */
    .sb-lbl, .sb-val, .sb-sub { position: relative; z-index: 1; }
    .sb-item:hover, .sb-item:active { background: var(--surface2); }
    .sb-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
    /* Zeilenhoehen bewusst in ganzen Pixeln: mit "normal" ist die Zeile
       gebrochen hoch, damit auch die Reihe — und der 1-px-Spalt zwischen den
       beiden Reihen liegt dann zwischen zwei Bildpunkten und wirkt mal
       dicker, mal duenner. */
    .sb-lbl { font-size: calc(10px - 1px * var(--leiste-eng));
      line-height: calc(12px - 1px * var(--leiste-eng));
      font-weight: 700; letter-spacing: calc(.08em - .03em * var(--leiste-eng));
      text-transform: uppercase; color: var(--text3);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .sb-val { display: flex; align-items: baseline; gap: 3px;
      line-height: calc(20px - 4px * var(--leiste-eng));
      color: var(--text); font-variant-numeric: tabular-nums; }
    .sb-val b { font-size: calc(21px - 6px * var(--leiste-eng)); font-weight: 700; }
    .sb-val i { font-size: calc(11px - 2px * var(--leiste-eng)); font-style: normal;
      font-weight: 600; color: var(--text2); }
    /* Die Unterzeile geht als Erste: bei 40 % des Weges ist sie schon
       unsichtbar, damit sie nicht bis zuletzt gequetscht mitlaeuft. */
    .sb-sub { font-size: 11px; line-height: 13px; color: var(--text3);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
      max-height: calc(15px * (1 - var(--leiste-eng)));
      opacity: calc(1 - 2.5 * var(--leiste-eng)); }
    /* Zustandsfarben: nur der Zahlenwert faerbt sich, nie die ganze Flaeche */
    .sb-item.sb-ok   .sb-val b { color: var(--green); }
    .sb-item.sb-low  .sb-val b { color: var(--yellow); }
    .sb-item.sb-warn .sb-val b { color: var(--red); }
    .sb-item.sb-idle .sb-val b { color: var(--text2); }
    /* Der Graph traegt dieselbe Zustandsfarbe wie die Zahl darueber. */
    .sb-item.sb-ok   .sb-spark { color: var(--green); }
    .sb-item.sb-low  .sb-spark { color: var(--yellow); }
    .sb-item.sb-warn .sb-spark { color: var(--red); }
    .sb-item.sb-idle .sb-spark { color: var(--text3); }
    .sb-item.sb-stale .sb-val b,
    .sb-item.sb-stale .sb-sub { opacity: .45; }  /* Wert veraltet, Sensor stumm */
    /* Ruhiger im Hintergrund, je flacher die Leiste wird: auf 40 px Hoehe
       arbeitet die volle Deckkraft gegen die kleine Schrift. */
    .sb-spark  { opacity: calc(.9 - .25 * var(--leiste-eng)); }
    .sb-balken { opacity: calc(.18 - .05 * var(--leiste-eng)); }

    /* Bis 700 px zwei Zeilen a drei Feldern — darunter reicht die Breite fuer
       sechs nebeneinander nicht, ohne dass die Unterzeilen abschneiden.
       Genau deshalb sind es SECHS Felder: bei fuenf haette die zweite Zeile
       eine Luecke. */
    @media (max-width: 700px) {
      .statusbar { grid-template-columns: repeat(3, minmax(0, 1fr)); }

      /* Und sie BLEIBEN zwei Zeilen, auch angedockt. Aus zwei Zeilen zu je
         drei Feldern eine Zeile mit sechs zu machen war verwirrend: die
         Felder wechselten mitten in der Bewegung den Platz, und drei davon
         landeten woanders. Ohne Umbruch ist der ganze Weg stufenlos.
         Muss NACH der 6-Spalten-Regel weiter oben stehen — gleiche
         Spezifitaet, es entscheidet die Reihenfolge. */
      body.leiste-kompakt .statusbar { grid-template-columns: repeat(3, minmax(0, 1fr)); }

      /* Die Kopfzeile hat sich hier zeitweise nach oben aus dem Bild
         geschoben, um Platz fuer die zweite Reihe zu machen. Auf Wunsch des
         Eigners wieder raus: ohne sie wirkte die Seite fremd, und Menue und
         Alarmglocke waren nicht mehr erreichbar.

         Angedockt dafuer so flach wie moeglich — und der Weg dorthin ist auch
         hier gerechnet statt geschaltet, damit die Schrift mitlaeuft, statt in
         einem Schritt zu springen. Zeilenhoehen bleiben ganzzahlig. */
      .sb-lbl   { letter-spacing: calc(.08em - .04em * var(--leiste-eng));
                  line-height: round(calc(12px - 1px * var(--leiste-eng)), 1px); }
      .sb-val   { line-height: round(calc(20px - 4px * var(--leiste-eng)), 1px); }
      .sb-sub   { max-height: round(calc(15px * (1 - var(--leiste-eng))), 1px); }
      .sb-item  { gap: round(calc(2px * (1 - var(--leiste-eng))), 1px); }
    }
    @media (max-width: 640px) {
      .sb-item { padding: calc(9px - 4px * var(--leiste-eng))
                          calc(10px - 5px * var(--leiste-eng))
                          calc(10px - 4px * var(--leiste-eng));
                 padding: round(calc(9px - 4px * var(--leiste-eng)), 1px)
                          round(calc(10px - 5px * var(--leiste-eng)), 1px)
                          round(calc(10px - 4px * var(--leiste-eng)), 1px); }
      .sb-val b { font-size: 18px; }
    }
    /* Sehr schmal (bis 380 px): dichter setzen. Sonst schnitt die Unterzeile
       der Batterie ("13.38 V . -12.7 A") in der 320-px-Spalte ab. */
    @media (max-width: 380px) {
      .sb-item { padding: calc(8px - 3px * var(--leiste-eng))
                          calc(8px - 4px * var(--leiste-eng))
                          calc(9px - 3px * var(--leiste-eng));
                 padding: round(calc(8px - 3px * var(--leiste-eng)), 1px)
                          round(calc(8px - 4px * var(--leiste-eng)), 1px)
                          round(calc(9px - 3px * var(--leiste-eng)), 1px); }
      .sb-lbl  { font-size: 9px; letter-spacing: .05em; }
      .sb-val b { font-size: 17px; }
      .sb-val i { font-size: 10px; }
      .sb-sub  { font-size: 10px; }
    }
    /* Breite Schirme: Leiste exakt so breit wie das Kachelraster darunter */
    @media (min-width: 1024px) {
      /* Angedockt geht die Leiste ueber die volle Breite wie die Kopfzeile,
         sonst zeigten die Luecken links und rechts sie als eigenen Streifen.
         Der Weg dorthin ist gerechnet, nicht geschaltet; max(0px, …) haelt die
         Leiste in schmalen Fenstern davon ab, schmaler zu werden statt breiter. */
      .statusbar { --sb-breit: calc(1240px - 2 * var(--gap));
        max-width: calc(var(--sb-breit) + max(0px, 100vw - var(--sb-breit)) * var(--leiste-eng));
        margin-left: auto; margin-right: auto; }
    }
    @media (min-width: 1600px) {
      .statusbar { --sb-breit: calc(1660px - 2 * var(--gap)); }
    }
    /* Kiosk: kein Header, dafuer Sidebar links — Leiste zieht mit */
    .kiosk-mode .statusbar {
      margin-top: calc(var(--gap) + var(--kiosk-handle-h));
      margin-left: calc(var(--kiosk-side-w) + var(--gap));
    }
    .kiosk-mode main { padding-top: var(--gap); }

    /* Innenaufbau: Titel immer oben, Inhalt füllt den Rest der Kachel.
       Bei wide wird .tile-content zur Zeile: links normal, rechts Extra. */
    .tile-content { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 14px; }
    .tile-main { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
    /* min-height:0 laesst .tile-main unter seine Inhaltshoehe schrumpfen —
       noetig, weil es sonst ueber die Kachel hinauswaechst (gemessen 426 px
       Inhalt in einer 392 px hohen Kachel) und die Fusszeile hinausschiebt.
       NUR im mehrspaltigen Raster: dort haben die Kacheln eine feste
       Zeilenhoehe. Einspaltig sind sie inhaltsgross, und dieselbe Regel liesse
       sie auf null zusammenfallen. */
    body.raster-mehrspaltig .tile-main { min-height: 0; }
    /* Bei schmalen Spalten sind die Kacheln flach (die Zeilenhoehe haengt an
       der Spaltenbreite). Dort kosten 14 px zwischen fuenf Bloecken 56 px —
       ein Viertel der Kachel. */
    @media (min-width: 601px) and (max-width: 860px) {
      body.raster-mehrspaltig .card-heizung .tile-main { gap: 8px; }
    }
    .tile-wide-side { display: none; }
    .tile--wide .tile-content { flex-direction: row; align-items: stretch; gap: 22px; }
    .tile--wide .tile-main { flex: 1 1 0; }
    .tile--wide .tile-wide-side { display: flex; flex: 1 1 0; min-width: 0; flex-direction: column;
      gap: 10px; justify-content: center; border-left: 1px solid var(--surface2); padding-left: 22px; }
    /* Halbe Kacheln: wenig Inhalt -> vertikal zentrieren */
    .tile--half .tile-main { justify-content: center; }

    /* Größen-Sichtbarkeit */
    .tile-hidden { display: none !important; }   /* schlägt inline display aus Daten-Updates */
    /* Kachel ist eingeschaltet, hat aber keine Daten (Tanks/Batterie).
       _applyGrid() rechnet sie aus dem Raster heraus, statt sie wieder
       aufzureißen. */
    .tile-nodata { display: none !important; }
    .tile-show-half, .tile-show-wide { display: none; }
    .tile--half .tile-show-half { display: block; }
    .tile--wide .tile-show-wide { display: block; }
    .tile--half .tile-hide-half { display: none !important; }

    /* ── Batterie ─────────────────────────────────────────────────────────── */
    /* Gauge nimmt den vertikalen Slack (zentriert), Wert-Zellen bleiben flach
       (TODO #5: wenig Leerraum über/unter der Zahl). */
    .card-battery .gauge-wrap { flex: 1; justify-content: center; margin: 0; min-height: 132px; }
    .card-battery .gauge-svg  { width: 184px; height: 129px; }
    .card-battery .batt-grid .batt-item { padding: 7px 10px; }
    .card-battery .batt-sub { margin-top: 2px; }
    /* half: kompakte Schlüsselwerte (SOC · Spannung · Strom · Restkap.) */
    .tile--half.card-battery .gauge-wrap,
    .tile--half.card-battery .batt-grid,
    .tile--half.card-battery .batt-sub,
    .tile--half.card-battery .src-row { display: none; }
    .batt-half { display: none; }
    .tile--half.card-battery .batt-half { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
    .batt-half-soc  { font-size: 46px; font-weight: 800; line-height: 1; }
    .batt-half-stat { font-size: 11px; color: var(--text3); text-transform: uppercase; letter-spacing: .05em; }
    .batt-half-stat b { display: block; color: var(--text); font-size: 19px; font-weight: 700; margin-top: 3px; text-transform: none; }
    /* wide: rechts SOC-Verlauf (Graph) + Kennzahlen */
    .tile--wide.card-battery .tile-wide-side { justify-content: flex-start; gap: 12px; }
    .batt-wide-hd { font-size: 11px; font-weight: 700; text-transform: uppercase;
      letter-spacing: .08em; color: var(--text3); margin: 0; }
    .batt-wide-chart { flex: 1; width: 100%; min-height: 80px; display: block; }
    .batt-wide-foot { display: flex; justify-content: space-between; gap: 16px; }
    .batt-wide-stat { display: flex; flex-direction: column; gap: 2px; }
    .batt-wide-stat b { font-size: 20px; font-weight: 700; color: var(--text); }
    .batt-wide-lbl { font-size: 11px; color: var(--text3); text-transform: uppercase; letter-spacing: .04em; }

    /* ── Tanks ────────────────────────────────────────────────────────────── */
    .tile--half.card-tanks .tank-bar-wrap { min-height: 0; }
    .tile--half.card-tanks .tank-pct-below { display: none; }
    .tile--half.card-tanks .tank-name      { font-size: 11px; margin: 0; }

    /* ── Beleuchtung ──────────────────────────────────────────────────────── */
    .tile--half.card-lights .channels-block,
    .tile--half.card-lights .divider { display: none; }
    /* Kanal-Balken füllen den oberen Bereich, Preset-Buttons bleiben normal groß */
    .card-lights .channels-block { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 4px; }
    .card-lights .channels-row { flex: 1; min-height: 36px; }
    .card-lights .presets-grid { flex: 0 0 auto; }
    .preset-btn { justify-content: center; }
    /* half: kompakte Buttons, die in die halbe Höhe passen (nicht abschneiden) */
    .tile--half.card-lights .presets-grid { gap: 6px; min-height: 0; grid-auto-rows: minmax(0, 1fr); }
    .tile--half.card-lights .preset-btn { padding: 6px; gap: 3px; min-height: 0; overflow: hidden; }
    .tile--half.card-lights .preset-emoji { font-size: 18px; }
    .tile--half.card-lights .preset-name  { font-size: 10px; }
    /* wide: rechte Spalte = Zonen-Slider, füllt das Panel */
    .lights-wide { display: flex; flex-direction: column; height: 100%; gap: 10px; }
    .lights-wide-hd { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--text3); }
    .lights-wide-sliders { display: flex; justify-content: space-around; align-items: stretch;
      flex: 1; min-height: 0; gap: 6px; }
    .lights-slider-item { display: flex; flex-direction: column; align-items: center; gap: 8px; flex: 1; min-width: 0; }
    .lights-vslider { writing-mode: vertical-lr; direction: rtl; width: 30px; flex: 1; min-height: 90px;
      cursor: pointer; accent-color: var(--accent2); }
    .lights-relay-btn { width: 44px; height: 44px; border-radius: 10px; border: 1.5px solid var(--border);
      background: var(--surface2); color: var(--text2); cursor: pointer; font-size: 18px; transition: background .15s; }
    .lights-relay-btn.active { background: var(--green); color: #fff; border-color: var(--green); }
    .lights-slider-lbl { font-size: 10px; color: var(--text3); font-weight: 600; text-align: center;
      line-height: 1.1; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* ── 230V ─────────────────────────────────────────────────────────────── */
    /* Inhalt gleichmäßig verteilen statt großer Lücken; 2×2-Grid füllt unten. */
    #inverterCard:not(.tile--half) { justify-content: space-between; }
    #inverterCard .gauge-svg { width: 168px; height: 118px; }
    #inverterCard #invIndicatorRow { display: none !important; } /* Status steht im Grid */
    #inverterCard .batt-grid { gap: 8px; }
    .tile--half#inverterCard .gauge-wrap,
    .tile--half#inverterCard .batt-grid { display: none; }
    .inv-half-summary { padding: 4px 0; }
    .tile--half#inverterCard .inv-half-summary { flex: 1; display: flex; align-items: center; }
    .inv-half-pct     { font-size: 32px; font-weight: 700; color: var(--text); }
    .inv-half-sep     { color: var(--text3); margin: 0 4px; }

    /* ── Wartung ── (Fortschrittsleiste unter dem Titel + einspaltige Liste) ── */
    .w-progress { display: flex; gap: 2px; height: 8px; border-radius: 4px; overflow: hidden; }
    .w-prog-seg { border-radius: 3px; }
    #wartungHomeBody { flex: 1; min-width: 0; }
    /* half: nur die nächste Aufgabe */
    .tile--half.card-wartung .w-home-row ~ .w-home-row { display: none; }

    /* Inverter-Button-Gruppe */
    .shore-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border); flex-shrink: 0; }
    .shore-dot.on { background: var(--green); box-shadow: 0 0 4px var(--green); }

    .inv-btn { flex: 1; padding: 10px; border-radius: 10px; font-size: 14px; font-weight: 700;
      cursor: pointer; border: 1px solid var(--border); background: var(--surface2); color: var(--text2);
      transition: all .15s; }
    .inv-btn:hover { background: var(--surface); }
    .inv-btn.active-on  { background: #22c55e22; border-color: #22c55e; color: #22c55e; }
    .inv-btn.active-eco { background: #eab30822; border-color: #eab308; color: #eab308; }
    .inv-btn.active-off { background: #ef444422; border-color: #ef4444; color: #ef4444; }

    .inv-pill { position: relative; display: flex; align-items: center;
      height: 42px; border-radius: 21px; border: 1.5px solid var(--border);
      background: var(--surface2); cursor: pointer; user-select: none;
      overflow: hidden; transition: border-color .25s; }
    .inv-pill.on { border-color: var(--green); }
    .inv-pill-thumb { position: absolute; top: 3px; left: 3px;
      width: calc(50% - 3px); height: calc(100% - 6px);
      border-radius: 18px; background: var(--border);
      transition: transform .28s cubic-bezier(.4,0,.2,1), background .25s;
      z-index: 0; }
    .inv-pill.on .inv-pill-thumb { transform: translateX(calc(100% + 0px)); background: var(--green); }
    .inv-pill-label { position: relative; z-index: 1; flex: 1; text-align: center;
      font-size: 12px; font-weight: 700; color: var(--text3);
      transition: color .25s; pointer-events: none; }
    .inv-pill.on  .inv-pill-label.right { color: var(--text); }
    .inv-pill:not(.on) .inv-pill-label.left  { color: var(--text); }

    /* ── Cards ── */
    .card { background: var(--surface); border: 1px solid var(--border);
      border-radius: var(--radius); padding: 20px;
      display: flex; flex-direction: column; gap: 16px; overflow: hidden; }
    .card--alarm { border-color: var(--red) !important; box-shadow: 0 0 0 1px var(--red)33; transition: border-color .3s; }
    .tank-bar-wrap--alarm { border-color: var(--red) !important; box-shadow: 0 0 0 2px var(--red)55; }

    /* ── Wetter tile ── */
    .card-wx .wx-grid { flex: 1; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
    .wx-day { background: var(--surface2); border-radius: 12px; padding: 10px 4px;
      display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; }
    .wx-day-name { font-size: 11px; color: var(--text3); text-transform: uppercase; letter-spacing: .05em; font-weight: 700; }
    .wx-icon { font-size: 30px; line-height: 1; }
    .wx-temp b { font-size: 18px; font-weight: 700; color: var(--text); }
    .wx-temp span { font-size: 13px; color: var(--text3); }
    .wx-row { font-size: 12px; color: var(--text2); white-space: nowrap; }
    .wx-half { flex: 1; align-items: center; gap: 18px; }
    .tile--half.card-wx .wx-half { display: flex; }   /* nur in halber Höhe zeigen */
    .wx-half-icon { font-size: 46px; line-height: 1; }
    .wx-half-temp { font-size: 36px; font-weight: 800; color: var(--text); line-height: 1; }
    .wx-half-sub { font-size: 13px; color: var(--text2); margin-top: 4px; }

    /* ── Wasserstand tile ── */
    .card-wl .wl-tile-body { flex: 1; display: flex; flex-direction: column; gap: 8px; }
    .wl-tile-spark { flex: 1; width: 100%; min-height: 48px; display: block; }
    .tile--half.card-wl .tile-show-half { flex: 1; display: flex; flex-direction: column; justify-content: center; }
    .wl-tile-main { display: flex; align-items: baseline; gap: 6px; }
    .wl-tile-big  { font-size: 44px; font-weight: 800; color: var(--text); line-height: 1; }
    .wl-tile-trend { font-size: 26px; margin-left: 2px; }
    .wl-tile-station { font-size: 13px; color: var(--text3); margin-top: 6px; }
    .wl-tile-compact { display: flex; align-items: baseline; gap: 6px; }

    /* ── Wartungsplan ── */
    @keyframes wblink { 0%,100%{opacity:1} 50%{opacity:.2} }
    .w-blink { animation: wblink 1.1s ease-in-out infinite; }
    .w-cat { margin-bottom: 12px; }
    .w-cat-hd { display:flex; align-items:center; gap:8px; padding:12px 4px 8px;
      font-size:11px; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
      color:var(--text2); border-bottom:2px solid; margin-bottom:2px; }
    .w-dot { width:9px; height:9px; border-radius:50%; flex-shrink:0; }
    .w-task { display:flex; align-items:center; gap:10px; padding:11px 8px;
      border-bottom:1px solid var(--surface2); cursor:pointer; border-radius:6px; }
    .w-task:hover { background:var(--surface2); }
    .w-task:last-child { border-bottom:none; }
    .w-task-name { flex:1; font-size:14px; }
    .w-task-interval { font-size:11px; color:var(--text3); white-space:nowrap; }
    .w-task-due { font-size:12px; font-weight:600; white-space:nowrap; text-align:right; min-width:80px; }
    .w-status-dot { width:8px; height:8px; border-radius:50%; flex-shrink:0; }
    .w-home-row { display:flex; justify-content:space-between; align-items:center;
      padding:6px 0; border-bottom:1px solid var(--surface2); font-size:13px; }
    .w-home-row:last-child { border-bottom:none; }
    .w-home-badge { display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:10px; }
    .w-badge-pill { font-size:12px; font-weight:700; padding:3px 10px; border-radius:20px; }
    .w-home-cat { font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:.05em;
      color:var(--text2); white-space:nowrap; flex-shrink:0; padding:2px 5px; border-radius:4px; }
    .card-title { display: flex; align-items: center; gap: 8px; font-size: 11px;
      font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--text3); }
    .card-title svg { flex-shrink: 0; }
    .card-link { margin-left: auto; font-size: 10px; color: var(--text3); font-weight: 400;
      letter-spacing: .04em; text-transform: none; }

    /* ── Battery card — clickable ── */
    .card-battery {
      cursor: pointer; transition: border-color .2s, box-shadow .2s;
      -webkit-tap-highlight-color: transparent; user-select: none;
    }
    .card-battery:hover { border-color: var(--accent2); box-shadow: 0 0 0 1px var(--accent2); }


    /* ── SOC Gauge ── */
    .gauge-wrap { display: flex; flex-direction: column; align-items: center; gap: 4px; }
    .gauge-svg { width: 160px; height: 112px; overflow: visible; }
    .gauge-track { fill: none; stroke: var(--border); stroke-width: 10; stroke-linecap: round; }
    .gauge-value { fill: none; stroke-width: 10; stroke-linecap: round;
      transition: stroke-dasharray .7s ease, stroke .5s; }
    .gauge-center { text-anchor: middle; dominant-baseline: middle; }
    .gauge-pct   { font-size: 28px; font-weight: 700; fill: var(--text); }
    .gauge-label { font-size: 11px; fill: var(--text3); letter-spacing: .08em; }

    .batt-unit-switch { cursor:pointer; margin-left:4px; display:inline-flex; align-items:center; gap:1px; }
    .batt-unit-sw { font-size:9px; font-weight:700; padding:1px 4px; border-radius:3px;
      color:var(--text3); text-transform:none; letter-spacing:0; transition:all .15s; }
    .batt-unit-sw.active { color:var(--text); background:var(--surface2); }

    /* ── Battery grid ── */
    .batt-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
    .batt-center-btn {
      position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
      height: 26px; padding: 0 10px; border-radius: 13px;
      background: var(--accent); border: none;
      color: var(--bg); font-size: 10px; font-weight: 700;
      cursor: pointer; z-index: 2; white-space: nowrap;
      display: flex; align-items: center; gap: 4px;
      box-shadow: 0 0 0 3px var(--surface), 0 2px 6px rgba(0,0,0,0.4);
      transition: filter .1s;
    }
    .batt-center-btn:active  { filter: brightness(.85); }
    .batt-center-btn span    { pointer-events: none; }
    .btu-sep  { opacity: .35; margin: 0 2px; font-weight: 400; }
    .btu-active { opacity: 1; }
    .batt-center-btn span:not(.btu-active):not(.btu-sep) { opacity: .35; }
    .batt-item { background: var(--surface2); border-radius: 10px; padding: 7px 10px; text-align: center; }
    .batt-grid .batt-item:nth-child(2) { border-bottom-right-radius: 16px; }
    .batt-grid .batt-item:nth-child(3) { border-bottom-left-radius:  16px; }
    .batt-grid .batt-item:nth-child(4) { border-top-right-radius:    16px; }
    .batt-grid .batt-item:nth-child(5) { border-top-left-radius:     16px; }
    .batt-item .label { font-size: 9px; color: var(--text3); margin-bottom: 2px; letter-spacing: .06em; text-transform: uppercase; }
    .batt-item .value { font-size: 18px; font-weight: 700; line-height: 1; }
    .batt-item .unit  { font-size: 10px; color: var(--text2); margin-left: 2px; }
    .batt-sub, .hz-sub { display: flex; justify-content: space-between; padding-top: 4px;
      border-top: 1px solid var(--border); flex-wrap: wrap; gap: 4px;
      margin-top: -8px; }
    .batt-sub-item, .hz-sub-item { font-size: 12px; color: var(--text2); }
    .batt-sub-item b, .hz-sub-item b { color: var(--text); font-weight: 600; }
    /* Die Fusszeile steht immer unten, die Raumliste davor gibt nach. */
    .hz-sub { margin-top: auto; gap: 10px; flex-wrap: wrap; }

    /* ── Source Progress Bars (rechts neben Gauge) ── */
    .src-bar-hd { font-size: 8px; font-weight: 700; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3);
      border-bottom: 1px solid var(--border); padding-bottom: 3px;
      width: 90px; text-align: right; display: block; line-height: 1;
      /* Linke BMS-Rows auf 18px anheben um mit Bars gleich zu sein */ }
    .src-bar { position: relative; width: 90px; height: 15px;
      background: var(--surface2); border-radius: 999px; overflow: hidden;
      border: 1px solid var(--border); }
    .src-bar-fill { position: absolute; left: 0; top: 0; height: 100%;
      background: var(--green); border-radius: 999px; width: 0%;
      transition: width .6s cubic-bezier(.4,0,.2,1); }
    .src-bar-text, .src-bar-text-dark {
      position: absolute; top: 0; left: 0; right: 0;
      display: flex; align-items: center; justify-content: flex-end; height: 100%;
      font-size: 11px; font-weight: 400;
      padding: 0 8px; white-space: nowrap; box-sizing: border-box; }
    .src-bar-text      { color: var(--text3); z-index: 1; }
    .src-bar-text-dark { color: #1a2f10; z-index: 2; clip-path: inset(0 100% 0 0); }

    /* ── Power sources (Solar / Alternator) ── */
    .src-row { display: flex; gap: 8px; flex-wrap: wrap; }
    .src-row.hidden { display: none; }
    .src-item { display: none; flex: 1; min-width: 110px; align-items: center; gap: 6px;
      background: var(--surface2); border-radius: 8px; padding: 7px 11px; font-size: 12px; color: var(--text2); }
    .src-item.visible { display: flex; }
    .src-icon { font-size: 14px; line-height: 1; }
    .src-val  { font-size: 15px; font-weight: 700; }
    .src-solar .src-val { color: var(--yellow); }
    .src-alt   .src-val { color: var(--accent); }

    .val-green  { color: var(--green)  !important; }
    .val-yellow { color: var(--yellow) !important; }
    .val-red    { color: var(--red)    !important; }
    .val-orange { color: var(--orange) !important; }
    .val-accent { color: var(--accent) !important; }

    /* ── Tanks ── */
    .card-tanks { cursor: pointer; -webkit-tap-highlight-color: transparent;
      transition: border-color .2s; }
    .card-tanks:hover { border-color: var(--accent2); }

    /* Jede anklickbare Kachel hebt sich beim Ueberfahren ab — und zwar gleich.
       Vorher war das je Klasse einzeln gepflegt und existierte nur fuer
       Batterie und Tanks; Beleuchtung, Wasserstand, Wartungsplan und Heizung
       fielen durch, obwohl sie genauso klickbar sind. Der Selektor haengt am
       onclick statt an einer Klassenliste, damit die naechste neue Kachel die
       Hervorhebung automatisch mitbringt. */
    .card[onclick] { cursor: pointer; }
    .card[onclick]:hover {
      border-color: var(--accent2);
      box-shadow: 0 0 0 1px var(--accent2);
    }
    @media (hover: none) { .card[onclick]:hover { box-shadow: none; } }
    .tanks-row { display: flex; gap: 16px; flex: 1; }
    .tank { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 10px; }
    .tank-name { font-size: 12px; color: var(--text2); }
    .tank-bar-wrap { flex: 1; width: 100%; min-height: 120px; background: var(--surface2);
      border-radius: 10px; position: relative; overflow: hidden; border: 1px solid var(--border); }
    .tank-fill { position: absolute; bottom: 0; left: 0; right: 0;
      border-radius: 0 0 10px 10px; transition: height .8s ease, background .5s;
      background: var(--green); }
    .tank-pct-label { position: absolute; inset: 0; display: flex; flex-direction: column;
      align-items: center; justify-content: center; gap: 0; }
    .tank-val-big  { font-size: 28px; font-weight: 700; color: var(--text);
      text-shadow: 0 1px 6px rgba(0,0,0,.7); line-height: 1; }
    .tank-val-unit { font-size: 15px; font-weight: 600; color: var(--text);
      text-shadow: 0 1px 4px rgba(0,0,0,.7); opacity: .75; margin-top: 2px; }
    .tank-pct-below { font-size: 13px; color: var(--text2); }

    /* ── Lights ── */
    .presets-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: 10px; }
    @media (max-width: 400px) { .presets-grid { grid-template-columns: repeat(2,1fr); } }
    .preset-btn { background: var(--surface2); border: 1px solid var(--border);
      border-radius: 12px; padding: 14px 10px; cursor: pointer;
      display: flex; flex-direction: column; align-items: center; gap: 6px;
      transition: all .15s; color: var(--text);
      user-select: none; -webkit-tap-highlight-color: transparent; }
    .preset-btn:hover:not(.disabled) { border-color: var(--accent2); background: #1a3244; }
    .preset-btn:active:not(.disabled) { transform: scale(.96); }
    .preset-btn.active { border-color: var(--accent); background: rgba(6,182,212,.12);
      box-shadow: 0 0 0 1px var(--accent); }
    .preset-btn.disabled { opacity: .35; cursor: not-allowed; }
    .preset-emoji { font-size: 22px; line-height: 1; }
    .preset-name  { font-size: 12px; font-weight: 500; text-align: center; line-height: 1.2; }
    .channels-row { display: flex; gap: 5px; align-items: flex-end; height: 32px; }
    .ch-bar-wrap { flex: 1; height: 100%; background: var(--surface2); border-radius: 4px;
      position: relative; overflow: hidden; }
    .ch-bar { position: absolute; bottom: 0; left: 0; right: 0; background: var(--accent);
      border-radius: 4px; transition: height .5s ease; opacity: .85; }
    .ch-bar.relay { background: var(--orange); }
    .channels-label { display: flex; gap: 5px; margin-top: 4px; }
    .ch-num { flex: 1; text-align: center; font-size: 9px; color: var(--text3); }
    .divider { height: 1px; background: var(--border); margin: 0 -4px; }

    /* ── Full-screen overlay (shared base) ── */
    /* Overlay startet UNTER der Haupt-Topbar — diese bleibt sichtbar */
    .overlay { position: fixed; top: var(--header-h); left: 0; right: 0; bottom: 0;
      background: var(--bg); z-index: 100; display: flex; flex-direction: column; }
    .overlay.hidden { display: none; }
    /* Schlanke, randlose Kopfzeile — kein zweiter Balken */
    .ov-header { display: flex; align-items: center;
      padding: 12px 16px 4px; background: transparent; flex-shrink: 0; gap: 8px; }
    .ov-title { flex: 1; text-align: left; font-size: 15px; font-weight: 700;
      letter-spacing: .02em; text-transform: none; color: var(--text1);
      display: flex; align-items: center; gap: 8px; }
    .ov-header-spacer { width: 0; flex-shrink: 0; }
    /* Zwei Knoepfe im Overlay-Kopf (Stromverlauf + Energiefluss). Auf schmalen
       Geraeten duerfen sie umbrechen, statt den Titel zu zerquetschen. */
    .ov-head-btns { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
      justify-content: flex-end; }
    @media (max-width: 560px) {
      /* Mit zwei beschrifteten Knoepfen bleibt fuer den Titel nichts uebrig —
         bei 320 px zerbrach "Batterie — Details" mitten im Gedankenstrich.
         Unter 560 px zeigen die Knoepfe nur ihr Symbol; die Beschriftung
         steht weiterhin im title-/aria-label-Attribut. */
      .ov-head-btns .monday-refresh { padding: 6px 9px; gap: 0; }
      .ov-head-btns .monday-refresh .btn-text { display: none; }
    }
    .ov-body { flex: 1; overflow-y: auto; padding: 12px 16px 16px; }

    /* ── Zentrierte Modals (statt Bottom-Sheets) ── */
    .center-modal-bg { display: none; position: fixed; inset: 0; z-index: 199;
      background: rgba(0,0,0,.55); backdrop-filter: blur(2px); }
    .center-modal { display: none; position: fixed; top: 50%; left: 50%;
      transform: translate(-50%, -50%); z-index: 200;
      width: calc(100% - 32px); max-width: 560px; max-height: 88vh; overflow-y: auto;
      background: var(--surface); border: 1px solid var(--border);
      border-radius: 16px; padding: 20px;
      box-shadow: 0 24px 64px rgba(0,0,0,.55); }
    .center-modal-hd { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
    .center-modal-close { margin-left: auto; background: var(--surface2); border: 1px solid var(--border);
      color: var(--text2); width: 32px; height: 32px; border-radius: 8px; cursor: pointer;
      display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
    .center-modal-close:hover { background: var(--border); color: var(--text1); }

    /* ── Zahleneingaben: Spinner-Pfeile ausblenden ── */
    input[type=number]::-webkit-inner-spin-button,
    input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
    input[type=number] { -moz-appearance: textfield; appearance: textfield; }

    /* ── Battery detail — 3-column page grid ── */
    /* ── Neue Batterie-Detail-Seite (2-spaltig) ── */
    .bd2-layout { display: grid; grid-template-columns: 300px 1fr; gap: 16px; align-items: stretch; }
    @media (max-width: 860px) { .bd2-layout { grid-template-columns: 1fr; } }
    .bd2-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
      padding: 18px 20px; display: flex; flex-direction: column; gap: 14px; }
    .bd2-chart-card { flex: 1; }
    .bd2-canvas { flex: 1; min-height: 0; width: 100% !important; cursor: crosshair; }
    .bd2-section-hd { font-size: 10px; font-weight: 700; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3); }
    .bd2-kv-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
    .bd2-kv { background: var(--surface2); border-radius: 8px; padding: 9px 11px; }
    .bd2-kv-label { font-size: 10px; color: var(--text3); text-transform: uppercase;
      letter-spacing: .06em; margin-bottom: 4px; }
    .bd2-kv-val { font-size: 20px; font-weight: 700; line-height: 1; display: flex;
      align-items: baseline; gap: 3px; }
    .bd2-kv-unit { font-size: 12px; color: var(--text2); font-weight: 400; }
    .bd2-stat-row { display: flex; gap: 10px; flex-wrap: wrap; }
    .bd2-stat { font-size: 13px; color: var(--text2); display: flex; gap: 5px; align-items: baseline; }
    .bd2-stat-l { font-size: 10px; color: var(--text3); text-transform: uppercase; letter-spacing:.04em; }

    /* ── Batterie-Detailseite: Raster ─────────────────────────────────────
       Vorher lagen fuenf Karten in voller Breite untereinander (Desktop
       1485 px hoch). Die Kennzahlenzeile endete bei 40 % der Breite, ein
       78-W-Balken war 1300 px lang, und man musste dreimal scrollen, um die
       Geraete zu sehen. Zwei Spalten nutzen die Breite; unter 1100 px faellt
       das Raster auf eine Spalte zurueck, die Reihenfolge bleibt dieselbe. */
    .bd-grid {
      display: grid; gap: var(--gap);
      max-width: 1500px; margin: 0 auto; padding: 16px; box-sizing: border-box;
      grid-template-columns: 1fr;
      grid-template-areas: "antwort" "bilanz" "zellen" "geraete" "verlauf"
                           "energie" "woche" "starter";
      /* Die Rasterflaeche ist so hoch wie das Fenster. Ohne align-content
         verteilt der Browser die Restzhoehe auf die Zeilen: die Zeilen werden
         hoeher als ihr Inhalt, und mit align-items:start klebten die Karten
         oben darin. Am Geraet gemessen ergab das 53 px Luft zwischen
         Geraetekacheln und Starterkarte, waehrend ueberall sonst 16 px stehen.
         Zeilen also nach Inhalt, ueberschuessige Hoehe bleibt unten. */
      align-content: start;
      /* Und innerhalb einer Zeile fuellen die Karten die volle Zeilenhoehe —
         sonst standen Bilanz (168 px) und Zellen (185 px) nebeneinander
         unterschiedlich hoch. */
      align-items: stretch;
    }
    /* Die Karte selbst muss die Zelle auch ausfuellen, nicht nur das Rasterfeld. */
    .bd-grid > div > .sb-card,
    .bd-grid > .bd-flow,
    .bd-grid > div > .starter,
    .bd-grid > div > .bd-card { height: 100%; box-sizing: border-box; }
    @media (min-width: 1100px) {
      .bd-grid {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        /* Links die Energie (was fliesst jetzt, was floss vorher), rechts der
           Zustand der Hardware (Zellen, Geraete). Die beiden Spalten sind so
           auch ungefaehr gleich hoch — bei "Verlauf ueber die volle Breite"
           stand rechts eine halbe Bildschirmhoehe leer. */
        grid-template-areas:
          "antwort antwort"
          "bilanz  zellen"
          "verlauf geraete"
          "verlauf starter"
          "energie woche";
      }
    }
    .bd-a-antwort { grid-area: antwort; }
    .bd-a-bilanz  { grid-area: bilanz; }
    .bd-a-zellen  { grid-area: zellen; }
    .bd-a-geraete { grid-area: geraete; }
    .bd-a-verlauf { grid-area: verlauf; }
    .bd-a-starter { grid-area: starter; }
    /* Stromverlauf und 7-Tage-Trend, von der frueheren Unterseite hierher.
       Sie behalten ihre .vl-karte-Optik, muessen sich im Raster aber wie die
       uebrigen Karten verhalten: kein eigener Aussenabstand, volle Zeilenhoehe. */
    .bd-a-energie { grid-area: energie; }
    .bd-a-woche   { grid-area: woche; }
    .bd-grid > .vl-karte { margin: 0; height: 100%; box-sizing: border-box; }
    /* Nur die Wochenkachel wird zur Spalte: dann kann das Canvas darin die
       Resthoehe uebernehmen. Beim Feinverlauf ist das nicht gewollt — der hat
       unter dem Diagramm noch Summen und Hinweiszeile. */
    .bd-grid > .bd-a-woche { display: flex; flex-direction: column; }
    /* Im Raster erzeugt jede Karte ihren eigenen Abstand ueber gap — die alten
       Einzel-Abstaende wuerden sich addieren. */
    .bd-grid .sb-card,
    .bd-grid .starter,
    .bd-grid .bd-flow { margin-bottom: 0; }
    /* Die Geraetekacheln stehen jetzt in einer halben Spalte: zwei nebeneinander
       statt vier, damit die Wattzahl gross bleibt. */
    @media (min-width: 1100px) {
      .bd-a-geraete { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }
    /* Der Verlauf spannt links zwei Rasterzeilen, damit rechts unter den
       Geraeten kein toter Raum bleibt. Er darf die Hoehe ausfuellen. */
    @media (min-width: 1100px) { .bd-a-verlauf { align-self: stretch; } }
    .bd-a-verlauf { display: flex; }
    .bd-a-verlauf > .bd-pg-chart { grid-area: auto; flex: 1; min-width: 0; }

    /* Altes Grid (nicht mehr für battOverlay genutzt, kann bleiben) */
    .bd-pg {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      grid-template-areas:
        "batt   cells   sources"
        "chart  chart   starter";
      gap: 14px; max-width: 1500px; margin: 0 auto; align-items: start;
    }
    /* flex:1 ohne Deckel liess den Verlauf auf 647 px anwachsen — mehr Hoehe
       macht eine Kurve nicht lesbarer, sie schiebt nur alles Weitere nach
       unten aus dem Blick. */
    /* Im Raster liegt der Verlauf ueber die volle Breite: flacher als frueher,
       sonst nimmt eine meist ruhige Kurve wieder das halbe Bild. */
    .bd-pg-chart canvas.chart { flex: 1; min-height: 200px; max-height: 260px; }
    .bd-pg-batt    { grid-area: batt; }
    .bd-pg-chart   { grid-area: chart; }
    .bd-pg-cells   { grid-area: cells; }
    .bd-pg-sources { grid-area: sources; }
    .bd-pg-starter { grid-area: starter; }
    @media (max-width: 1023px) {
      .bd-pg {
        grid-template-columns: 1fr 1fr;
        grid-template-areas:
          "batt   cells"
          "sources starter"
          "chart  chart";
      }
    }
    @media (max-width: 639px) {
      .bd-pg {
        grid-template-columns: 1fr;
        grid-template-areas: "batt" "chart" "cells" "sources" "starter";
      }
    }

    /* ── Battery detail — card layout ── */
    .bd-page { max-width: 900px; margin: 0 auto; display: flex; flex-direction: column; gap: 14px; }
    .bd-card {
      background: var(--surface); border: 1px solid var(--border);
      /* Ein Innenabstand fuer alle Karten (20 px), einer fuer die kleineren
         Geraetekacheln (16 px). Vorher waren es vier verschiedene:
         20 / 14+16 / 14+18 / 18+20. */
      border-radius: var(--radius); padding: 20px;
      display: flex; flex-direction: column; gap: 14px;
    }
    .bd-card-hd {
      font-size: 11px; font-weight: 600; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3);
      padding-bottom: 10px; border-bottom: 1px solid var(--border);
    }
    .bd-card-hd-row {
      display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px;
      font-size: 11px; font-weight: 600; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3);
      padding-bottom: 10px; border-bottom: 1px solid var(--border);
    }
    .bd-ov-row { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
    .bd-soc-block { display: flex; flex-direction: column; gap: 8px; min-width: 130px; flex-shrink: 0; }
    .bd-soc-head  { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
    .bd-soc-num   { font-size: 58px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
    .bd-soc-pct-unit { font-size: 22px; color: var(--text2); font-weight: 400; }
    .bd-soc-dir   { font-size: 14px; color: var(--text2); align-self: center; }
    .bd-soc-sec   { font-size: 12px; color: var(--text3); }
    .bd-kv-grid   { flex: 1; min-width: 200px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
    .bd-kv-item   { background: var(--surface2); border-radius: 10px; padding: 10px 12px; display: flex; flex-direction: column; }
    .bd-kv-label  { font-size: 10px; color: var(--text3); letter-spacing: .06em; text-transform: uppercase; margin-bottom: 4px; }
    .bd-kv-line   { display: flex; align-items: baseline; gap: 3px; }
    .bd-kv-val    { font-size: 22px; font-weight: 700; line-height: 1; }
    .bd-kv-unit   { font-size: 12px; color: var(--text2); font-weight: 400; }
    .bd-kv-sec    { font-size: 11px; color: var(--text3); margin-top: 4px; }
    .bd-stat-row  { display: flex; flex-wrap: wrap; gap: 8px; }
    .bd-stat      { flex: 1; min-width: 100px; background: var(--surface2); border-radius: 8px; padding: 10px 12px; }
    .bd-stat-label { font-size: 10px; color: var(--text3); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px; }
    .bd-stat-val  { font-size: 15px; font-weight: 600; }
    .bd-stat-unit { font-size: 11px; color: var(--text2); margin-left: 2px; }
    .bd-3col      { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
    .bd-3col-item { background: var(--surface2); border-radius: 10px; padding: 14px; text-align: center; display: flex; flex-direction: column; align-items: center; }
    .bd-3col-label { font-size: 10px; color: var(--text3); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 8px; }
    .bd-3col-val  { font-size: 26px; font-weight: 700; display: flex; align-items: baseline; gap: 3px; }

    /* ── Cell mini grid (inside service battery card) ── */
    .bd-cell-mini-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
    .bd-cell-mini-item { background: var(--surface); border: 2px solid var(--border);
      border-radius: 9px; padding: 8px 10px; transition: border-color .4s; }
    .bd-cell-mini-nr { font-size: 9px; color: var(--text3); letter-spacing:.06em;
      text-transform: uppercase; margin-bottom: 4px; }
    .bd-cell-mini-v  { font-size: 17px; font-weight: 700; line-height: 1; }
    .bd-cell-mini-t  { font-size: 11px; color: var(--text2); margin-top: 3px; }

    /* ── Mini stats row (restkapazität, zyklen, letzte Ladung) ── */
    .bd-mini-row { display: flex; gap: 6px; flex-wrap: wrap; }
    .bd-mini-item { flex: 1; min-width: 68px; background: var(--surface2);
      border-radius: 8px; padding: 8px 10px; }
    .bd-mini-val  { font-size: 14px; font-weight: 600; margin-top: 2px; }

    /* ── Min/Max footer row in battery card ── */
    .bd-minmax-row { display: flex; align-items: center; gap: 8px; font-size: 12px;
      color: var(--text3); padding-top: 10px; border-top: 1px solid var(--surface2);
      margin-top: auto; flex-wrap: wrap; }

    /* ── Solar column ── */
    .bd-solar-list { display: flex; flex-direction: column; gap: 7px; }
    .bd-solar-item { display: flex; align-items: center; justify-content: space-between;
      background: var(--surface2); border-radius: 8px; padding: 9px 12px; }
    .bd-solar-name { font-size: 13px; color: var(--text2); }
    .bd-solar-vals { display: flex; align-items: baseline; gap: 8px; }
    .bd-solar-w    { font-size: 16px; font-weight: 700; color: var(--yellow); }
    .bd-solar-v    { font-size: 12px; color: var(--text3); }
    .bd-solar-total { background: var(--surface2); border-radius: 8px; padding: 10px 12px; }
    .bd-solar-total-val { font-size: 22px; font-weight: 700; color: var(--yellow); margin-top: 2px; }

    /* ── Placeholder card (dashed border) ── */
    .bd-card-ph { border-style: dashed; opacity: .55; }
    .bd-ph-body { flex: 1; display: flex; flex-direction: column;
      align-items: center; justify-content: center; gap: 8px;
      padding: 28px 0; color: var(--text3); }
    .bd-ph-icon { font-size: 26px; }
    .bd-ph-text { font-size: 13px; }

    /* ── Battery detail layout (legacy — kept for ov-body compat) ── */
    .bd-label { font-size: 10px; color: var(--text3); letter-spacing: .06em;
      text-transform: uppercase; margin-bottom: 4px; }
    .bd-unit { font-size: 12px; color: var(--text2); margin-left: 2px; font-weight: 400; }

    /* ── bd-sec (connectivity detail grid) ── */
    .bd-sec-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
    .bd-sec-item { background: var(--surface2); border-radius: 8px; padding: 9px 11px; }
    .bd-sec-val  { font-size: 15px; font-weight: 600; margin-top: 2px; }

    /* ── Charts ── */
    .chart-section { display: flex; flex-direction: column; gap: 14px; }
    .chart-card { background: var(--surface); border: 1px solid var(--border);
      border-radius: var(--radius); padding: 14px 16px; }
    .chart-header { display: flex; justify-content: space-between; align-items: baseline;
      margin-bottom: 10px; }
    .chart-title { font-size: 11px; font-weight: 600; letter-spacing: .08em;
      text-transform: uppercase; color: var(--text3); }
    .chart-current { font-size: 18px; font-weight: 700; }
    .chart-unit { font-size: 11px; color: var(--text2); margin-left: 2px; }
    canvas.chart { width: 100%; height: 80px; display: block; border-radius: 6px; }

    /* ── Alarm badge ── */
    .alarm-btn { position: relative; }
    .alarm-badge {
      position: absolute; top: -5px; right: -5px;
      background: var(--red); color: #fff; border-radius: 50%;
      min-width: 16px; height: 16px; padding: 0 3px;
      font-size: 10px; font-weight: 700;
      display: flex; align-items: center; justify-content: center;
      pointer-events: none;
    }
    .alarm-badge.hidden { display: none; }

    /* ── Alarm overlay tabs ── */
    .tabs { display: flex; border-bottom: 1px solid var(--border); margin-bottom: 16px; }
    .tab-btn {
      padding: 10px 18px; font-size: 13px; font-weight: 500;
      border: none; background: none; color: var(--text2); cursor: pointer;
      border-bottom: 2px solid transparent; margin-bottom: -1px;
      transition: all .15s; font-family: inherit;
    }
    .tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
    .tab-pane { display: none; }
    .tab-pane.active { display: block; }

    /* ── Alarm cards ── */
    .alarm-list { display: flex; flex-direction: column; gap: 10px; }
    .alarm-empty { color: var(--text3); text-align: center; padding: 50px 20px; font-size: 14px; }
    .alarm-card {
      background: var(--surface); border: 1px solid var(--border);
      border-radius: var(--radius); padding: 14px 16px;
      display: flex; flex-direction: column; gap: 8px;
      transition: opacity .3s;
    }
    .alarm-card.warning  { border-left: 3px solid var(--yellow); }
    .alarm-card.critical { border-left: 3px solid var(--red); }
    .alarm-card.acknowledged { opacity: .55; }
    .alarm-card.resolved { border-left-color: var(--border); }
    .alarm-header { display: flex; align-items: center; gap: 8px; }
    .alarm-severity-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
    .warning  .alarm-severity-dot { background: var(--yellow); }
    .critical .alarm-severity-dot { background: var(--red); }
    .resolved .alarm-severity-dot { background: var(--border); }
    .alarm-name { font-size: 14px; font-weight: 600; flex: 1; }
    .alarm-time { font-size: 11px; color: var(--text3); }
    .alarm-detail { font-size: 12px; color: var(--text2); }
    .alarm-detail b { color: var(--text); }
    .alarm-resolved-badge {
      font-size: 11px; color: var(--green); font-weight: 600;
      display: flex; align-items: center; gap: 4px;
    }
    .alarm-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 2px; }
    .alarm-ack-btn, .alarm-del-btn {
      border: 1px solid var(--border); border-radius: 6px;
      padding: 5px 12px; font-size: 12px; cursor: pointer;
      font-family: inherit; transition: all .15s; background: none; color: var(--text2);
    }
    .alarm-ack-btn:hover { background: var(--surface2); color: var(--accent); border-color: var(--accent2); }
    .alarm-del-btn:hover { background: rgba(239,68,68,.1); color: var(--red); border-color: var(--red); }
    .ack-all-row { display: flex; justify-content: flex-end; margin-bottom: 12px; }

    /* ── Alarm rules ── */
    .rule-cat-nav { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; }
    .rule-cat-btn { background: var(--surface2); border: 1px solid var(--border); color: var(--text2);
      padding: 7px 14px; border-radius: 20px; font-size: 13px; cursor: pointer; font-weight: 500; }
    .rule-cat-btn:hover { background: var(--border); }
    .rule-cat-btn.active { background: var(--accent2, #3b82f6); color: #fff; border-color: transparent; }
    .rule-cat-btn .rc-count { font-size: 11px; opacity: .7; margin-left: 4px; }
    .rule-list { display: flex; flex-direction: column; gap: 2px; margin-bottom: 20px; }
    .rule-row {
      display: flex; flex-direction: column; gap: 6px;
      padding: 12px 0; border-bottom: 1px solid var(--surface2);
    }
    .rule-row:last-child { border-bottom: none; }
    .rule-row.no-data { opacity: .45; }
    .rule-header { display: flex; align-items: center; gap: 10px; }
    .rule-toggle { position: relative; display: inline-block; width: 36px; height: 20px; flex-shrink: 0; }
    .rule-toggle input { opacity: 0; width: 0; height: 0; position: absolute; }
    .rule-slider {
      position: absolute; inset: 0; background: var(--border);
      border-radius: 20px; cursor: pointer; transition: background .2s;
    }
    .rule-slider::before {
      content: ''; position: absolute; width: 14px; height: 14px;
      left: 3px; top: 3px; background: #fff; border-radius: 50%;
      transition: transform .2s;
    }
    .rule-toggle input:checked + .rule-slider { background: var(--accent); }
    .rule-toggle input:checked + .rule-slider::before { transform: translateX(16px); }
    .rule-name { flex: 1; font-size: 13px; color: var(--text); }
    .rule-threshold-wrap { display: flex; align-items: center; gap: 5px; }
    .rule-op   { font-size: 12px; color: var(--text3); white-space: nowrap; }
    .rule-unit { font-size: 12px; color: var(--text3); }
    .rule-input {
      width: 72px; background: var(--surface2); border: 1px solid var(--border);
      border-radius: 6px; padding: 5px 8px; color: var(--text); font-size: 13px;
      outline: none; text-align: right; font-family: inherit;
    }
    .rule-input:focus { border-color: var(--accent); }
    .rule-severity { font-size: 10px; font-weight: 600; padding: 2px 6px;
      border-radius: 4px; white-space: nowrap; border: none; cursor: pointer; }
    .rule-severity.warning  { background: rgba(234,179,8,.15);  color: var(--yellow); }
    .rule-severity.critical { background: rgba(239,68,68,.15); color: var(--red); }
    .rule-no-data { font-size: 11px; color: var(--text3); font-style: italic; padding-left: 46px; }

    /* ── Dual-range slider ── */
    .dr-wrap { padding: 4px 0 2px; }
    .dr-vals { display: flex; justify-content: space-between; font-size: 12px;
               color: var(--accent); font-variant-numeric: tabular-nums; margin-bottom: 4px; }
    .dr-track { position: relative; height: 44px; display: flex; align-items: center; }
    .dr-track-bg { position: absolute; left: 22px; right: 22px; height: 4px;
                   top: 50%; transform: translateY(-50%);
                   background: var(--surface2); border-radius: 2px; }
    .dr-fill { position: absolute; height: 4px; top: 50%; transform: translateY(-50%);
               background: var(--accent); border-radius: 2px; pointer-events: none; }
    .dr-thumb {
      position: absolute; width: 44px; height: 44px;
      display: flex; align-items: center; justify-content: center;
      cursor: grab; touch-action: none; transform: translateX(-50%);
      z-index: 2;
    }
    .dr-thumb::after {
      content: ''; width: 18px; height: 18px; border-radius: 50%;
      background: var(--accent); border: 2px solid #fff;
      box-shadow: 0 1px 4px rgba(0,0,0,.5);
    }
    .dr-thumb:active { cursor: grabbing; }
    .dr-bounds { display: flex; justify-content: space-between; font-size: 10px;
                 color: var(--text3); padding: 0 0; margin-top: 2px; }

    /* ── Settings ── */
    .settings-section { margin-bottom: 28px; }
    .settings-section-title {
      font-size: 11px; font-weight: 600; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3); margin-bottom: 4px;
      padding-bottom: 8px; border-bottom: 1px solid var(--border);
    }
    .settings-row {
      display: flex; align-items: center; gap: 12px;
      padding: 10px 0; border-bottom: 1px solid var(--surface2);
    }
    .settings-row:last-child { border-bottom: none; }
    .settings-label { font-size: 13px; color: var(--text2); min-width: 120px; flex-shrink: 0; }
    .settings-input {
      flex: 1; background: var(--surface2); border: 1px solid var(--border);
      border-radius: 8px; padding: 9px 12px; color: var(--text); font-size: 14px;
      outline: none; transition: border-color .15s; font-family: inherit;
    }
    .settings-input:focus { border-color: var(--accent); }
    .settings-input.narrow { max-width: 100px; }
    .settings-color-wrap {
      display: flex; align-items: center; gap: 8px;
    }
    .settings-color {
      width: 44px; height: 38px; padding: 3px; border-radius: 8px;
      border: 1px solid var(--border); background: var(--surface2);
      cursor: pointer; flex-shrink: 0;
    }
    .settings-actions {
      display: flex; gap: 10px; justify-content: flex-end; margin-top: 24px;
    }
    .btn-primary {
      background: var(--accent); color: #0f172a; border: none;
      border-radius: 8px; padding: 10px 20px; font-size: 14px; font-weight: 600;
      cursor: pointer; transition: background .15s; font-family: inherit;
    }
    .btn-primary:hover { background: var(--accent2); }
    .btn-primary:disabled { opacity: .5; cursor: not-allowed; }
    .btn-secondary {
      background: var(--surface2); color: var(--text); border: 1px solid var(--border);
      border-radius: 8px; padding: 7px 14px; font-size: 13px; font-weight: 600;
      cursor: pointer; transition: background .15s, border-color .15s; font-family: inherit;
    }
    .btn-secondary:hover { background: var(--surface); border-color: var(--accent2); }
    .settings-feedback {
      font-size: 13px; color: var(--green); margin-right: auto;
      align-self: center; opacity: 0; transition: opacity .3s;
    }
    .settings-feedback.show { opacity: 1; }
    .settings-feedback.error { color: var(--red); }

    /* ── Network overlay — device cards ── */
    .net-grid { display: grid; gap: 12px;
      grid-template-columns: 1fr; max-width: 1100px; margin: 0 auto; }
    @media (min-width: 550px)  { .net-grid { grid-template-columns: 1fr 1fr; } }
    @media (min-width: 900px)  { .net-grid { grid-template-columns: 1fr 1fr 1fr; } }

    .net-device-card { background: var(--surface); border: 1px solid var(--border);
      border-radius: var(--radius); overflow: hidden; }
    .net-device-header { display: flex; align-items: center; gap: 8px;
      padding: 10px 12px; border-bottom: 1px solid var(--border);
      background: var(--surface2); }
    .net-device-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
    .net-device-dot.ok   { background: var(--green); box-shadow: 0 0 4px var(--green); }
    .net-device-dot.warn { background: var(--yellow); animation: pulse 1.5s infinite; }
    .net-device-dot.old  { background: var(--border); }
    .net-device-name { font-size: 13px; font-weight: 600; color: var(--text); flex: 1;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .net-device-src  { font-size: 11px; color: var(--text3); font-family: monospace;
      background: var(--surface); border: 1px solid var(--border); border-radius: 4px;
      padding: 1px 5px; flex-shrink: 0; }

    .net-pgn-list { padding: 0; }
    .net-pgn-row { display: flex; align-items: center; gap: 8px;
      padding: 5px 12px; border-bottom: 1px solid var(--surface2); }
    .net-pgn-row:last-child { border-bottom: none; }
    /* Direkte Kinder (Router-Kachel): desc nimmt Restbreite, iv rechts */
    .net-pgn-row > .net-pgn-desc { flex: 1; font-size: 12px; color: var(--text2); }
    .net-pgn-iv { font-size: 12px; color: var(--text); white-space: nowrap; font-weight: 500; }
    /* CAN-Kacheln: dot + info-Block + iv-badge */
    .net-pgn-dot-wrap { flex-shrink: 0; display: flex; align-items: center; padding-right: 2px; }
    .net-pgn-dot { width: 5px; height: 5px; border-radius: 50%; }
    .net-pgn-dot.ok   { background: var(--green); }
    .net-pgn-dot.warn { background: var(--yellow); }
    .net-pgn-dot.old  { background: var(--border); }
    .net-pgn-info { flex: 1; min-width: 0; }
    .net-pgn-desc { font-size: 12px; color: var(--text); }
    .net-pgn-num  { font-size: 10px; color: var(--text3); font-family: monospace; margin-top: 1px; }
    .net-inst-badge { display: inline-block; font-size: 9px; background: var(--accent);
      color: #fff; border-radius: 3px; padding: 0 4px; margin-left: 4px;
      vertical-align: middle; line-height: 16px; }
    .net-iv-badge { font-size: 10px; color: var(--text3); white-space: nowrap;
      flex-shrink: 0; font-family: monospace; }
    .net-pgn-row:hover { background: var(--surface2); border-radius: 4px; }

    .net-empty { color: var(--text3); text-align: center; padding: 60px 20px; font-size: 14px; }

    /* ── PGN-Detail Modal ── */
    .pgn-nav-btn { background: var(--surface2); border: 1px solid var(--border); color: var(--text);
      border-radius: 6px; padding: 3px 10px; cursor: pointer; font-size: 14px; line-height: 1.4; }
    .pgn-nav-btn:hover { background: var(--border); }
    .pgn-field-row { display: flex; justify-content: space-between; align-items: baseline;
      padding: 7px 16px; border-bottom: 1px solid var(--surface2); }
    .pgn-field-row.alarm { background: rgba(239,68,68,.08); }
    .pgn-field-row:last-child { border-bottom: none; }
    .pgn-field-name { font-size: 12px; color: var(--text2); flex-shrink: 0; margin-right: 12px; }
    .pgn-field-val  { font-size: 13px; font-weight: 600; color: var(--text); text-align: right; }
    .pgn-field-empty { padding: 24px 16px; color: var(--text3); font-size: 13px; text-align: center; }

    /* ── Light detail — channel cards ── */
    #chSlidersWrap {
      display: grid; grid-template-columns: 1fr; gap: 10px; margin-bottom: 10px;
    }
    @media (min-width: 540px) {
      #chSlidersWrap { grid-template-columns: 1fr 1fr; }
    }
    .ch-card {
      background: var(--surface2); border-radius: 14px; padding: 16px 18px;
    }
    .ch-card-header {
      display: flex; align-items: center; gap: 10px; margin-bottom: 14px;
    }
    .ch-card-num {
      font-size: 10px; font-weight: 700; color: var(--text3);
      background: var(--border); border-radius: 4px; padding: 2px 7px; flex-shrink: 0;
    }
    .ch-card-name { flex: 1; font-size: 15px; font-weight: 600; color: var(--text); }
    .ch-card-val {
      font-size: 22px; font-weight: 700; color: var(--accent);
      font-variant-numeric: tabular-nums; min-width: 48px; text-align: right;
    }
    .ch-slider-big {
      width: 100%; -webkit-appearance: none; appearance: none;
      height: 10px; border-radius: 5px; outline: none; cursor: pointer;
      background: linear-gradient(to right, var(--accent) 0%, var(--border) 0%);
    }
    .ch-slider-big::-webkit-slider-thumb {
      -webkit-appearance: none; width: 34px; height: 34px; border-radius: 50%;
      background: var(--accent); border: 3px solid #fff;
      box-shadow: 0 2px 8px rgba(0,0,0,.5); cursor: pointer;
    }
    .ch-slider-big::-moz-range-thumb {
      width: 28px; height: 28px; border-radius: 50%;
      background: var(--accent); border: 3px solid #fff; cursor: pointer;
    }
    .relay-card {
      display: flex; align-items: center; gap: 16px;
      background: var(--surface2); border-radius: 14px; padding: 18px;
    }
    .relay-card-info { flex: 1; }
    .relay-card-name { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 3px; }
    .relay-status { font-size: 12px; color: var(--text3); }
    .relay-btn {
      padding: 12px 32px; border-radius: 10px; font-size: 15px; font-weight: 700;
      cursor: pointer; font-family: inherit; border: 1px solid var(--border);
      transition: all .15s; letter-spacing: .04em; flex-shrink: 0;
    }
    .relay-btn.on  { background: var(--orange); border-color: var(--orange); color: #fff; box-shadow: 0 0 0 3px rgba(249,115,22,.2); }
    .relay-btn.off { background: var(--surface); color: var(--text3); }

    /* ── Preset save sheet ── */
    .preset-sheet-bg {
      position: fixed; inset: 0; z-index: 199; background: rgba(0,0,0,.45);
      display: none;
    }
    .preset-sheet {
      position: fixed; left: 0; right: 0; bottom: 0; z-index: 200;
      background: var(--surface); border-top: 1px solid var(--border);
      border-radius: 18px 18px 0 0; padding: 20px;
      max-height: 75vh; overflow-y: auto; display: none;
    }
    .preset-sheet-handle {
      width: 36px; height: 4px; background: var(--border);
      border-radius: 2px; margin: 0 auto 16px;
    }
    .preset-sheet-title {
      font-size: 11px; font-weight: 600; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3); margin-bottom: 16px;
    }
    .preset-save-grid {
      display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
    }
    @media (max-width: 380px) { .preset-save-grid { grid-template-columns: 1fr; } }
    .preset-save-card {
      background: var(--surface2); border: 1px solid var(--border);
      border-radius: 10px; padding: 10px 12px;
      display: flex; flex-direction: column; gap: 8px;
    }
    .preset-save-card-top { display: flex; align-items: center; gap: 6px; }
    .preset-save-card-emoji { font-size: 16px; }
    .preset-edit-name {
      flex: 1; min-width: 0; background: var(--surface); border: 1px solid var(--border);
      border-radius: 6px; padding: 6px 8px; color: var(--text); font-size: 13px;
      outline: none; font-family: inherit; transition: border-color .15s;
    }
    .preset-edit-name:focus { border-color: var(--accent); }
    .preset-save-card-btn {
      width: 100%; background: var(--surface); border: 1px solid var(--border);
      border-radius: 7px; padding: 8px; font-size: 12px; font-weight: 600;
      color: var(--text2); cursor: pointer; font-family: inherit;
      transition: all .15s; display: flex; align-items: center; justify-content: center; gap: 5px;
    }
    .preset-save-card-btn:hover { background: var(--accent); border-color: var(--accent); color: #0f172a; }
    .preset-save-card-btn.saved { background: rgba(34,197,94,.15); border-color: var(--green); color: var(--green); }
    .light-section-title {
      font-size: 11px; font-weight: 600; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3);
      padding-bottom: 8px; margin-bottom: 4px;
      border-bottom: 1px solid var(--border);
    }

    /* ── Chart controls ── */
    .chart-controls {
      display: flex; justify-content: space-between; align-items: center;
      flex-wrap: wrap; gap: 8px; margin-bottom: 10px;
    }
    .chart-tog-group, .chart-range-group { display: flex; gap: 4px; flex-wrap: wrap; }
    .chart-tog {
      background: var(--surface2); border: 1px solid var(--border);
      border-radius: 6px; padding: 4px 10px; font-size: 11px; font-weight: 600;
      cursor: pointer; color: var(--text3); transition: all .15s; font-family: inherit;
    }
    .chart-tog.active { color: var(--text); border-color: var(--accent2); background: rgba(6,182,212,.1); }
    .chart-range {
      background: var(--surface2); border: 1px solid var(--border);
      border-radius: 6px; padding: 4px 8px; font-size: 11px;
      cursor: pointer; color: var(--text3); transition: all .15s; font-family: inherit;
    }
    .chart-range.active { color: var(--accent); border-color: var(--accent); background: rgba(6,182,212,.08); }
    .chart-legend { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 8px; }
    .chart-legend-item { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text2); }
    .chart-legend-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
    .chart-legend-val { font-size: 14px; font-weight: 700; }


    /* ── BMS section ── */
    .bms-section-title {
      font-size: 11px; font-weight: 600; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3);
      padding-bottom: 8px; border-bottom: 1px solid var(--border);
      margin-bottom: 12px;
    }
    .bms-flags-row { display: flex; gap: 6px; flex-wrap: wrap; margin: 12px 0; }
    .bms-flag {
      display: flex; align-items: center; gap: 5px; padding: 4px 10px;
      border-radius: 20px; font-size: 11px; font-weight: 600; border: 1px solid;
    }
    .bms-flag.ok   { background: rgba(34,197,94,.1);  border-color: rgba(34,197,94,.4);  color: var(--green); }
    .bms-flag.warn { background: rgba(234,179,8,.1);  border-color: rgba(234,179,8,.4);  color: var(--yellow); }
    .bms-flag.err  { background: rgba(239,68,68,.1);  border-color: rgba(239,68,68,.4);  color: var(--red); }
    .bms-flag.off  { background: var(--surface2); border-color: var(--border); color: var(--text3); }
    .bms-cell-grid {
      display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
      gap: 8px; margin-top: 12px;
    }
    .bms-cell {
      background: var(--surface); border: 2px solid var(--border);
      border-radius: 10px; padding: 12px; text-align: center;
      transition: border-color .4s;
    }
    .bms-cell .cell-num  { font-size: 10px; color: var(--text3); margin-bottom: 6px; letter-spacing: .06em; text-transform: uppercase; }
    .bms-cell .cell-volt { font-size: 22px; font-weight: 700; line-height: 1; }
    .bms-cell .cell-temp { font-size: 13px; color: var(--text2); margin-top: 6px; }

    /* ── Battery detail layout ── */
    .bd-layout { display: grid; grid-template-columns: 1fr; gap: 14px;
      max-width: 1200px; margin: 0 auto; }
    @media (min-width: 860px) {
      .bd-layout { grid-template-columns: 340px 1fr; align-items: start; }
    }
    .bd-label { font-size: 10px; color: var(--text3); letter-spacing: .06em;
      text-transform: uppercase; margin-bottom: 4px; }
    .bd-unit { font-size: 12px; color: var(--text2); margin-left: 2px; font-weight: 400; }

    /* ── Charge source donut ── */
    .charge-src-wrap {
      display: flex; align-items: center; gap: 14px;
      background: var(--surface2); border-radius: 10px; padding: 12px 14px;
      margin-top: 12px;
    }
    .charge-src-legend { flex: 1; display: flex; flex-direction: column; gap: 7px; }
    .charge-src-row { display: flex; align-items: center; gap: 7px; font-size: 12px; }
    .charge-src-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
    .charge-src-label { flex: 1; color: var(--text2); }
    .charge-src-val { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
    .charge-src-pct { font-size: 10px; color: var(--text3); margin-left: 3px; }

    /* BMS pack row */
    .bms-pack-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
    .bms-pack-item {
      flex: 1; min-width: 90px; background: var(--surface2);
      border-radius: 8px; padding: 10px 12px;
    }
    .bms-pack-val { font-size: 17px; font-weight: 600; margin-top: 3px; }

    /* ── Connectivity icon dot ── */
    .conn-inet-wrap { position: relative; display: flex; align-items: center; justify-content: center; }
    .conn-inet-dot {
      position: absolute; bottom: -1px; right: -1px;
      width: 8px; height: 8px; border-radius: 50%;
      background: var(--text3); border: 1.5px solid var(--surface);
      transition: background .4s;
    }

    /* ── Connectivity overlay ── */
    .conn-section-title {
      font-size: 11px; font-weight: 600; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3);
      padding-bottom: 8px; border-bottom: 1px solid var(--border);
      margin-bottom: 12px;
    }
    .conn-active-banner {
      background: var(--surface2); border-radius: var(--radius);
      padding: 16px 18px; margin-bottom: 16px;
      display: flex; flex-direction: column; gap: 6px;
    }
    .conn-active-type {
      display: flex; align-items: center; gap: 10px;
    }
    .conn-active-icon { font-size: 22px; line-height: 1; }
    .conn-active-label { font-size: 20px; font-weight: 700; }
    .conn-fallback { font-size: 13px; color: var(--text2); }
    .conn-signal-bar-wrap {
      height: 6px; background: var(--surface2); border-radius: 3px;
      overflow: hidden; margin-bottom: 3px;
    }
    .conn-signal-bar-fill {
      height: 100%; border-radius: 3px;
      transition: width .6s ease, background .5s;
    }

    /* ── WiFi clients list ── */
    .wifi-client-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--surface2); font-size: 13px; }
    .wifi-client-row:last-child { border-bottom: none; }
    .wifi-client-name { flex: 1; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .wifi-client-ip   { font-size: 11px; color: var(--text3); font-variant-numeric: tabular-nums; white-space: nowrap; }
    .wifi-client-sig  { font-size: 11px; color: var(--text3); min-width: 55px; text-align: right; }
    .wifi-client-mac  { font-size: 10px; color: var(--text3); opacity: .6; white-space: nowrap; }
    /* ── Connectivity card grid ── */
    .conn-cards-grid { display: grid; grid-template-columns: 1fr; gap: 14px; }
    @media (min-width: 620px) { .conn-cards-grid { grid-template-columns: 1fr 1fr; } }
    .conn-card-body { padding: 12px 14px; }

    /* SOC progress bar */
    .soc-bar-wrap {
      height: 7px; background: var(--surface2); border-radius: 4px;
      overflow: hidden; margin-bottom: 12px;
    }
    .soc-bar-fill {
      height: 100%; border-radius: 4px; background: var(--green);
      transition: width .7s ease, background .5s;
    }

    /* Mobile: compact topbar */
    @media (max-width: 500px) {
      :root { --header-basis: 51px; }
      .logo-sub, .logo-ver { display: none; }
      #topbarClock { display: none !important; }
      header { padding: 10px 12px 9px; }
      .header-right { gap: 6px; }
    }

    /* Back-arrow close button */
    .ov-close-arrow {
      background: none; border: none; color: var(--text2);
      font-size: 22px; cursor: pointer; padding: 4px 10px 4px 4px;
      line-height: 1; display: flex; align-items: center; gap: 6px;
      transition: color .15s;
    }
    .ov-close-arrow:hover { color: var(--text); }
    .ov-close-arrow svg { flex-shrink: 0; }
    /* ── Stauplan ── */
    .stauplan-layout { max-width: 1100px; margin: 0 auto; padding: 16px; display: grid; grid-template-columns: minmax(180px, 320px) 1fr; gap: 20px; align-items: start; }
    @media (max-width: 700px) { .stauplan-layout { grid-template-columns: 1fr; } }
    .stauplan-fach { cursor: pointer; transition: fill .18s, stroke .18s; }
    .stauplan-fach:hover:not(.sp-sel) { fill: rgba(255,255,255,0.07) !important; }
    .stauplan-fach.sp-sel { stroke-width: 2.5 !important; }
    .sp-dot { display: inline-block; width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
    .stauplan-right { display: flex; flex-direction: column; gap: 10px; }
    .stauplan-filter-bar { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; font-size: 12px; }
    .stauplan-filter-label { font-weight: 600; flex: 1; }
    .stauplan-clear-btn { background: none; border: none; color: var(--text3); cursor: pointer; font-size: 12px; padding: 2px 6px; border-radius: 6px; }
    .stauplan-clear-btn:hover { background: var(--surface2); color: var(--text1); }
    .stauplan-search { width: 100%; box-sizing: border-box; padding: 9px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; color: var(--text1); font-size: 14px; margin-bottom: 12px; outline: none; }
    .stauplan-search:focus { border-color: var(--accent); }
    .stauplan-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
    .stauplan-tbl th { text-align: left; padding: 7px 10px; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--text3); border-bottom: 1px solid var(--border); }
    .stauplan-tbl td { padding: 10px; border-bottom: 1px solid var(--surface2); }
    .stauplan-tbl tr:last-child td { border-bottom: none; }
    .stauplan-tbl tbody tr:hover td { background: var(--surface2); }
    .stauplan-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; padding: 2px 8px; border-radius: 20px; color: #fff; font-weight: 600; white-space: nowrap; }
    /* ── Monday overlay ── */
    .monday-body { max-width: 860px; margin: 0 auto; padding: 16px; display: flex; flex-direction: column; gap: 0; }
    .monday-group-hd { display: flex; align-items: center; gap: 9px; padding: 20px 4px 9px; font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--text2); border-bottom: 2px solid var(--border); margin-bottom: 2px; }
    .monday-group-dot { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; }
    .monday-item { display: flex; align-items: center; gap: 12px; padding: 11px 6px; border-bottom: 1px solid var(--surface2); cursor: default; }
    .monday-item:last-child { border-bottom: none; }
    .monday-item-name { flex: 1; font-size: 14px; line-height: 1.4; }
    .monday-status-pill { font-size: 11px; font-weight: 700; padding: 4px 11px; border-radius: 20px; cursor: pointer; white-space: nowrap; color: #fff; flex-shrink: 0; transition: filter .15s; letter-spacing: .02em; }
    .monday-status-pill:hover { filter: brightness(1.15); }
    .monday-status-pill.empty { background: var(--surface2) !important; color: var(--text3); }
    .monday-empty { color: var(--text3); font-size: 13px; text-align: center; padding: 48px 0; }
    .monday-refresh { background: none; border: 1px solid var(--border); border-radius: 8px; color: var(--text2); padding: 5px 12px; font-size: 12px; cursor: pointer; display: flex; align-items: center; gap: 6px; }
    .monday-refresh:hover { background: var(--surface2); }
    .monday-refresh svg { transition: transform .5s; }
    .monday-refresh.spinning svg { transform: rotate(360deg); }
    .status-picker { position: fixed; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 8px 28px rgba(0,0,0,.5); z-index: 300; min-width: 170px; overflow: hidden; }
    .status-picker-item { display: flex; align-items: center; gap: 10px; padding: 10px 14px; cursor: pointer; font-size: 13px; font-weight: 500; }
    .status-picker-item:hover { background: var(--surface2); }
    .status-picker-dot { width: 13px; height: 13px; border-radius: 3px; flex-shrink: 0; }
  

    /* ── Energiefluss (Schema im Victron-Stil) ── */
    .flow-card { max-width: 1700px; margin: 0 auto; padding: 20px 28px;
      background: radial-gradient(120% 120% at 50% 0%, #16263f 0%, #0e1a2e 100%);
      border: 1px solid var(--border); border-radius: 18px; }
    /* Fuellt die Flaeche: vorher deckelte max-width:800px das Schema, in einem
       1400px breiten Fenster stand es klein in der Mitte mit breiten Raendern. */
    .flow-schema { width: 100%; height: 100%; display: block; }
    .flow-edge { fill: none; stroke: #3c5269; stroke-width: 1.6; }
    /* animierter Fluss (Menge bekannt): laufende Punkte */
    .flow-edge-dot { fill: none; stroke-width: 4.5; stroke-linecap: round;
      stroke-dasharray: 0.1 13; opacity: 0; transition: opacity .3s; }
    .flow-edge-dot.on { opacity: 1; animation: flowdots 1s linear infinite; }
    .flow-edge-dot.flow-rev { animation-direction: reverse; }
    /* Strom fließt, Menge unbekannt: farbige Strich-Punkt-Linie, kein Lauf */
    .flow-edge-dot.static { opacity: 1; animation: none; stroke-dasharray: 7 7; stroke-width: 3.5; }
    /* Ruhende Leitung: durchgezogen und ausgegraut. Sie zeigt die Verkabelung,
       ohne zu behaupten, dass dort gerade Strom fliesst. */
    .flow-edge-dot.idle { opacity: .5; animation: none; stroke-dasharray: none;
      stroke-width: 2; stroke: #35485f; }
    @keyframes flowdots { to { stroke-dashoffset: -26; } }
    .flow-box { fill: #162438; stroke: #283d5a; stroke-width: 1.3; }
    .flow-box-main { fill: #1a3050; stroke: var(--accent); stroke-width: 2;
      filter: drop-shadow(0 0 10px rgba(6,182,212,.45)); }
    .flow-g.dim { opacity: .5; }
    .flow-g.dim .flow-box { fill: #111e30; stroke: #223347; }
    .flow-name { fill: #5a7a9c; font-size: 12px; font-weight: 600; letter-spacing: .06em;
      text-anchor: middle; text-transform: uppercase; dominant-baseline: middle; }
    .flow-val  { fill: #ddeeff; font-size: 22px; font-weight: 800; text-anchor: middle; }
    .flow-sub  { fill: #7a9ab8; font-size: 11px; text-anchor: middle; }
    .flow-icon { fill: #3d6080; stroke: #3d6080; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.3; }

    /* ── Settings: Kategorie-Navigation + Unterseiten ── */
    .set-nav { display: flex; gap: 6px; flex-wrap: wrap; padding: 14px 16px;
      position: sticky; top: 0; z-index: 5; background: var(--bg);
      border-bottom: 1px solid var(--border); }
    .set-nav-btn { background: var(--surface); border: 1px solid var(--border); color: var(--text2);
      padding: 8px 14px; border-radius: 999px; font-size: 13px; cursor: pointer; font-weight: 600;
      display: inline-flex; align-items: center; gap: 6px; transition: background .15s, color .15s, border-color .15s; }
    .set-nav-btn:hover { background: var(--surface2); color: var(--text); }
    .set-nav-btn.active { background: var(--accent2); color: #fff; border-color: transparent; }
    .set-pane { display: none; padding: 22px 16px 28px; max-width: 660px; margin: 0 auto; }
    .set-pane.active { display: block; }
    .set-pane-net { max-width: 100%; }
    .set-card { background: var(--surface); border: 1px solid var(--border);
      border-radius: var(--radius); padding: 16px 18px; margin-bottom: 16px; }
    .set-card-hd { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
      color: var(--text3); margin-bottom: 12px; }


    /* ── Datenquelle (Kopfzeile) ─────────────────────────────────────────── */
    /* Sagt, WOHER die Daten kommen — der Punkt daneben nur, OB etwas kommt. */
    .quelle-chip {
      display: flex; align-items: center; gap: 5px;
      background: none; border: 1px solid var(--border); border-radius: 999px;
      padding: 4px 9px 4px 7px; cursor: pointer;
      font-size: 11px; font-weight: 600; letter-spacing: .04em;
      color: var(--text2); transition: all .2s;
    }
    .quelle-chip:hover { border-color: var(--text3); }
    .quelle-chip.ok    { color: var(--green);  border-color: color-mix(in srgb, var(--green) 40%, transparent); }
    .quelle-chip.warn  { color: var(--yellow); border-color: color-mix(in srgb, var(--yellow) 55%, transparent);
                         background: color-mix(in srgb, var(--yellow) 12%, transparent); }
    .quelle-chip svg { flex: 0 0 auto; }
    @media (max-width: 560px) { .quelle-txt { display: none; } .quelle-chip { padding: 4px 6px; } }

    .quelle-pop {
      position: fixed; top: calc(var(--header-basis) - 4px); right: 12px; z-index: 130;
      width: min(320px, calc(100vw - 24px));
      background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
      box-shadow: 0 12px 32px rgba(0,0,0,.38); padding: 14px 15px;
    }
    .quelle-pop.hidden { display: none; }
    .qp-kopf { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 11px; }
    .qp-weg  { display: flex; align-items: center; margin-bottom: 11px; }
    .qw-knoten {
      flex: 1 1 0; text-align: center; font-size: 10px; font-weight: 600;
      padding: 6px 3px; border-radius: 7px; line-height: 1.25;
      background: var(--bg); color: var(--text3); border: 1px solid var(--border);
    }
    .qw-knoten.an  { color: var(--text); border-color: var(--text3); }
    .qw-knoten.aus { color: var(--yellow); border-color: color-mix(in srgb, var(--yellow) 45%, transparent);
                     border-style: dashed; }
    .qw-strich { flex: 0 0 14px; height: 1px; background: var(--border); }
    .qp-text  { font-size: 12px; line-height: 1.5; color: var(--text2); }
    .qp-alter { font-size: 12px; color: var(--text2); margin-top: 9px;
                padding-top: 9px; border-top: 1px solid var(--border); }
    .qp-alter b { color: var(--text); }

    /* ── Kopie-Modus ─────────────────────────────────────────────────────── */
    /* Liegt nur die gespeicherte Kopie vor, muss das unuebersehbar sein und
       kein Schalter darf mehr so aussehen, als wuerde er etwas bewirken. */
    html.nur-kopie { --kopie-h: 38px; }
    .kopie-banner {
      position: fixed; top: var(--header-basis); left: 0; right: 0; z-index: 100;
      height: var(--kopie-h); box-sizing: border-box;
      display: flex; align-items: center; gap: 9px;
      padding: 0 16px; overflow: hidden;
      background: color-mix(in srgb, var(--yellow) 17%, var(--surface));
      border-bottom: 1px solid color-mix(in srgb, var(--yellow) 45%, transparent);
      font-size: 12px; color: var(--text);
    }
    .kopie-banner.hidden { display: none; }
    .kb-mark {
      flex: 0 0 auto; font-size: 10px; font-weight: 800; letter-spacing: .08em;
      text-transform: uppercase; color: var(--bg); background: var(--yellow);
      padding: 3px 8px; border-radius: 5px;
    }
    .kb-txt { flex: 1 1 auto; line-height: 1.3; }
    .kb-txt b { font-weight: 700; }
    @media (max-width: 560px) {
      html.nur-kopie { --kopie-h: 46px; }
      .kopie-banner { padding: 0 11px; gap: 7px; font-size: 11px; align-items: center; }
      .kb-mark { font-size: 9px; padding: 2px 6px; }
    }

    /* Alles, was ans Boot schreibt, wird sichtbar stillgelegt.

       Die Liste ist aus dem laufenden DOM erhoben, nicht geraten: jeder
       Klick-Handler der Oberflaeche wurde einmal aufgelistet und danach
       einzeln einsortiert. Bewusst NICHT gesperrt ist alles, was nur die
       Ansicht aendert (Overlays oeffnen, Reiter, Zeitbereiche, Einheiten,
       Filter) — im Kopie-Modus darf man weiter alles ansehen, nur nichts
       bewirken.

       Ein Muster wie [onclick^="save"] waere kuerzer, wuerde aber irgendwann
       einen Ansichts-Handler mitnehmen, der zufaellig so heisst. Deshalb
       ausgeschriebene Namen.

       Kommt spaeter ein Schalter dazu und wird hier vergessen, bleibt er
       sichtbar bedienbar — greifen tut er trotzdem nicht: der Waechter an
       fetch() (quelle.js) laesst keine schreibende Anfrage durch. Diese
       Liste ist die Hoeflichkeit, der Waechter die Sicherung. */

    /* Schalter mit Ereignis-Empfaenger statt onclick */
    html.nur-kopie .lights-vslider,
    html.nur-kopie .lights-relay-btn,
    html.nur-kopie .preset-btn,
    html.nur-kopie .ch-slider-big,
    html.nur-kopie .hz-preset,
    html.nur-kopie .hz-mini,
    html.nur-kopie .hz-rund,
    /* Strom und Anlage */
    html.nur-kopie [onclick*="toggleRelay"],
    html.nur-kopie [onclick*="_toggleRelayFromWide"],
    html.nur-kopie [onclick*="toggleInverter"],
    html.nur-kopie [onclick*="setChargerMode"],
    html.nur-kopie [onclick*="saveChargerSettings"],
    /* Heizung */
    html.nur-kopie [onclick*="hzPreset"],
    html.nur-kopie [onclick*="hzHand"],
    html.nur-kopie [onclick*="hzModus"],
    html.nur-kopie [onclick*="hzSoll"],
    html.nur-kopie [onclick*="hzLuefter"],
    html.nur-kopie [onclick*="hzPruefen"],
    html.nur-kopie [onclick*="hzAbbrechen"],
    html.nur-kopie [onclick*="hzEinstellungenSpeichern"],
    /* System */
    html.nur-kopie [onclick*="syncTime"],
    html.nur-kopie [onclick*="runUpdate"],
    html.nur-kopie [onclick*="saveSettings"],
    html.nur-kopie [onclick*="saveRules"],
    html.nur-kopie [onclick*="ackAllAlarms"],
    /* Wartung, Stauplan, Aufgaben */
    html.nur-kopie [onclick*="saveWartungTask"],
    html.nur-kopie [onclick*="saveWartungDone"],
    html.nur-kopie [onclick*="saveWartungSettings"],
    html.nur-kopie [onclick*="addWartungCat"],
    html.nur-kopie [onclick*="deleteWartungCat"],
    html.nur-kopie [onclick*="deleteWartungTask"],
    html.nur-kopie [onclick*="saveStauEdit"],
    html.nur-kopie [onclick*="deleteStauItem"],
    html.nur-kopie [onclick*="selectFach"],
    html.nur-kopie [onclick*="createMondayItem"] {
      opacity: .34 !important; filter: grayscale(1);
      pointer-events: none !important; cursor: not-allowed !important;
    }

    /* ── Anmeldung ───────────────────────────────────────────────────────── */
    /* Legt sich ueber die Oberflaeche, statt sie zu ersetzen: der Verlauf des
       Ladens bleibt sichtbar, und nach dem Anmelden ist man dort, wo man war. */
    .anmeldung {
      position: fixed; inset: 0; z-index: 400;
      display: flex; align-items: center; justify-content: center; padding: 20px;
      background: color-mix(in srgb, var(--bg) 88%, transparent);
      backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
    }
    .anmeldung.hidden { display: none; }
    .anm-karte {
      width: min(360px, 100%); box-sizing: border-box;
      background: var(--surface); border: 1px solid var(--border);
      border-radius: 16px; padding: 26px 24px 22px;
      box-shadow: 0 20px 60px rgba(0,0,0,.45);
      display: flex; flex-direction: column; gap: 14px;
    }
    .anm-marke {
      font-size: 19px; font-weight: 700; letter-spacing: .18em;
      color: var(--accent); text-transform: uppercase; text-align: center;
    }
    .anm-marke span {
      display: block; font-size: 10px; font-weight: 500; letter-spacing: .16em;
      color: var(--text3); margin-top: 4px;
    }
    .anm-wohin {
      text-align: center; font-size: 12px; color: var(--text2);
      margin: -6px 0 4px; padding-bottom: 12px; border-bottom: 1px solid var(--border);
    }
    .anm-feld { display: flex; flex-direction: column; gap: 5px; }
    .anm-feld span {
      font-size: 10px; font-weight: 700; letter-spacing: .09em;
      text-transform: uppercase; color: var(--text3);
    }
    .anm-feld input {
      background: var(--bg); border: 1px solid var(--border); border-radius: 9px;
      padding: 11px 12px; color: var(--text); font-size: 15px; font-family: inherit;
      /* 15px und nicht kleiner: darunter zoomt iOS beim Antippen in das Feld
         hinein, und die Maske sitzt danach schief. */
      transition: border-color .15s;
    }
    .anm-feld input:focus { outline: none; border-color: var(--accent); }
    .anm-fehler {
      font-size: 12px; line-height: 1.4; color: var(--red);
      background: color-mix(in srgb, var(--red) 12%, transparent);
      border: 1px solid color-mix(in srgb, var(--red) 35%, transparent);
      border-radius: 8px; padding: 8px 10px;
    }
    .anm-fehler.hidden { display: none; }
    .anm-knopf {
      margin-top: 4px; padding: 12px; border: none; border-radius: 9px;
      background: var(--accent); color: var(--bg);
      font-size: 14px; font-weight: 700; font-family: inherit; letter-spacing: .03em;
      cursor: pointer; transition: opacity .15s;
    }
    .anm-knopf:hover { opacity: .9; }
    .anm-knopf:disabled { opacity: .55; cursor: default; }

    /* Solange die Maske steht, soll dahinter nichts scrollen oder blinken. */
    html.anmeldung-offen body { overflow: hidden; }

    /* Der Hinweis, dass noch gar kein Konto besteht — dieselbe Leiste wie beim
       Kopie-Modus, aber in ruhigerem Ton: es ist kein Fehler, sondern der
       Zustand vor der Einrichtung. */
    .kopie-banner.offen-hinweis {
      background: color-mix(in srgb, var(--accent) 13%, var(--surface));
      border-bottom-color: color-mix(in srgb, var(--accent) 40%, transparent);
    }
    .kopie-banner.offen-hinweis .kb-mark { background: var(--accent); }

    /* ── Was jemand nicht darf, steht ihm nicht im Weg ────────────────────── */
    /* Dieselbe Mechanik wie im Kopie-Modus, aus demselben Grund: ein Schalter,
       der nur abweist, ist schlimmer als keiner. Die Entscheidung faellt am
       Endpunkt — das hier ist Hoeflichkeit, kein Schutz.
       `kein-konto` nimmt die Schonfrist aus: solange es keine Konten gibt,
       ist absichtlich alles offen. */
    html:not(.darf-schalten):not(.kein-konto) .lights-vslider,
    html:not(.darf-schalten):not(.kein-konto) .lights-relay-btn,
    html:not(.darf-schalten):not(.kein-konto) .preset-btn,
    html:not(.darf-schalten):not(.kein-konto) .ch-slider-big,
    html:not(.darf-schalten):not(.kein-konto) .hz-preset,
    html:not(.darf-schalten):not(.kein-konto) .hz-rund,
    html:not(.darf-schalten):not(.kein-konto) [onclick*="toggleRelay"],
    html:not(.darf-schalten):not(.kein-konto) [onclick*="toggleInverter"],
    html:not(.darf-schalten):not(.kein-konto) [onclick*="setChargerMode"],
    html:not(.darf-schalten):not(.kein-konto) [onclick*="hzPreset"],
    html:not(.darf-schalten):not(.kein-konto) [onclick*="hzModus"],
    html:not(.darf-schalten):not(.kein-konto) [onclick*="hzSoll"] {
      opacity: .34 !important; filter: grayscale(1);
      pointer-events: none !important; cursor: not-allowed !important;
    }

    .qp-wegtitel {
      font-size: 9px; font-weight: 700; letter-spacing: .1em;
      text-transform: uppercase; color: var(--text3); margin-bottom: 6px;
    }
