/* ====================================================================
   M&W-Framework  ·  © 2026 Tobias Wachtel — Alle Rechte vorbehalten.
   Geschützter Quellcode — Nutzung nur mit schriftlicher Genehmigung.
   ====================================================================
   assets/grund.css — Grundregeln des Kerns, die VOR jedem Theme geladen
   werden (Gegenstück zu `assets/app.js`).

   Zweierlei gehört hier hinein:

     1. Was am SEITENGERÜST hängt und in jedem Theme gleich gelten soll
        (Fuß unten, Gerätebreite, gesperrter Hintergrund).

     2. Der brauchbare GRUNDZUSTAND der Bausteine, die der Kern SELBST ins
        HTML schreibt: Meldung (`mwToast`), Rückfrage (`mwConfirm`),
        Menü-Zeichen, Abzeichen. Wer ein Element erzeugt, muss auch dafür
        sorgen, dass es benutzbar ankommt — sonst hängt es davon ab, ob ein
        Theme zufällig daran gedacht hat. Genau das ist passiert:
        `themes/admin` kannte `.mw-toast` und `.mw-modal` nicht. Die Meldung
        stand am ENDE der Seite (2 883 px weit unten, nie im Bild), und die
        Rückfrage lag ohne Abdunklung mitten im Text — gemessen, nicht
        vermutet. `themes/papier` fehlt bis heute das Menü-Abzeichen, und
        der Updater fasst fremde Themes nie an (`Aktualisierung.php:24`):
        Was dort fehlt, kann NUR der Kern liefern.

   Alles Übrige — Farben, Abstände und Schrift der SEITE — bleibt Sache des
   Themes.

   WICHTIG — das Theme hat immer das letzte Wort. Es wird NACH dieser Datei
   gebündelt und gewinnt deshalb bei jedem Gleichstand.

   ⚠️ Aber NICHT jede Regel hier ist `:where()`. Es gibt drei Gewichte, und
   jedes hat einen Grund, der an Ort und Stelle noch einmal steht:

     · 0,0,1 — der Normalfall (`body:where(:has(> .fuss))`,
       `div:where(.mw-modal)`): Tag-Name plus `:where()`. Jede Theme-Regel
       mit Klasse (0,1,0) gewinnt, ein Theme-Reset `*{margin:0}` (0,0,0)
       verliert. Ohne `:where()` wöge `body:has(> .fuss)` mehr als ein
       schlichtes `body{…}` im Theme — der Kern würde dem Theme die Regel
       aufzwingen, und genau das soll er nicht.
     · 0,1,0 — für Bausteine, die es nur im Kern gibt (`.nav-zeichen`).
       Hier gibt es nichts zu überstimmen; ein Theme, das mitreden will,
       schreibt ohnehin seinen eigenen Kontext davor.
     · 0,2,0 — nur dort, wo der Kern gewinnen MUSS (`body.geraet-handy
       .inhalt`, die erzwungene Handy-Ansicht). Mit `:where()` kam sie
       gegen `.inhalt{max-width:…}` des Themes nicht an: 1 180 px trotz
       „Handy".
==================================================================== */

/* ── Fuß bleibt unten ────────────────────────────────────────────────
   Das Seitengerüst aus `Seite::rumpf()` ist: header.kopf + main.inhalt +
   footer.fuss untereinander. Stehen die drei einfach hintereinander,
   endet der Fuß dort, wo der Inhalt endet — bei einer kurzen Seite also
   mitten im Fenster, mit einer großen leeren Fläche darunter.

   `:has(> .fuss)` greift nur, wenn die Seite diesem Gerüst folgt. Die
   Anmeldeseite (Layout „leer", ohne Fuß) bleibt dadurch unangetastet —
   dort zentrieren die Themes ihre Karte selbst.

   Bewusst im KERN und nicht nur in `themes/standard`: Jedes App-Theme
   bringt sein eigenes `theme.css` mit und müsste den Fix sonst neu
   erfinden. Genau das ist passiert — in 1.8.3 saß er nur im Standard-
   Theme, und in einer App mit eigenem Theme hing der Fuß weiter. */
body:where(:has(> .fuss)){
  min-height:100vh;
  display:flex;
  flex-direction:column;
}
/* flex:1 0 auto — der Inhalt nimmt den freien Platz ein und schiebt den
   Fuß nach unten, schrumpft aber nie unter seine eigene Höhe (0 = kein
   shrink), damit auf langen Seiten nichts gestaucht wird.

   width:100% ist PFLICHT, nicht Kosmetik: `.inhalt` trägt in praktisch
   jedem Theme `max-width` + `margin:0 auto`. Sobald `body` ein Flex-
   Container ist, unterbinden auto-Margins in der QUERachse das Strecken
   (`align-items:stretch`) — das Element fällt dann auf seine INHALTS-
   breite zurück. Im normalen Blockfluss passiert das nicht, deshalb
   fällt es beim Umstellen auf Flex leicht durch: In 1.8.4 schrumpfte
   `.inhalt` dadurch von 1180 px auf 246 px, ein Kachel-Raster
   (`repeat(auto-fit,minmax(190px,1fr))`) von fünf Spalten auf eine.
   Mit width:100% + max-width verhält es sich wieder wie im Blockfluss. */
body:where(:has(> .fuss)) > :where(.inhalt){
  flex:1 0 auto;
  width:100%;
}
/* Auf dem Handy meint 100vh das Fenster OHNE eingeblendete Adressleiste —
   die Seite wäre dann etwas zu hoch. 100dvh misst den sichtbaren Teil. */
@supports (min-height:100dvh){
  body:where(:has(> .fuss)){ min-height:100dvh; }
}

/* ── Grundstock ──────────────────────────────────────────────────────
   Ab 1.9.0. Hier steht ausschließlich, was Browser-Vorgaben NEUTRALISIERT
   — nichts Gestalterisches. Grund: Ein App-Theme ersetzt `themes/standard`
   vollständig und erbt nichts davon. Alles, was nur dort stand, musste
   jedes Theme neu erfinden; vergaß es eins, sah die App kaputt aus.

   Farben, Abstände und Schriften bleiben Sache des Themes. Der Browser
   färbt Rollbalken, Zahlenfelder und Datumswähler von selbst passend,
   sobald das Theme `color-scheme: light` bzw. `dark` setzt — dafür
   braucht es kein eigenes CSS. */

/* Maße rechnen mit Rand und Innenabstand — sonst sprengt jedes Feld mit
   Innenabstand seine Spalte. Stand bisher nur im Standard-Theme. */
*, *::before, *::after{ box-sizing:border-box; }

/* Formularelemente erben die Schrift der Seite. Ohne das setzt der Browser
   seine eigene (meist 13,33 px Arial) — mitten in einer Oberfläche, die
   überall sonst die Theme-Schrift nutzt.

   BEWUSST nur Familie und Größe, NICHT die Kurzform `font:inherit`: Die
   setzt auch die Zeilenhöhe mit. Ein Knopf, dem das Theme nur `font-size`
   gibt, behielte dann die geerbte Zeilenhöhe (1.5 statt `normal`) und
   würde spürbar höher — gemessen wuchs eine lange Seite dadurch um 5 px.
   Farbe bleibt ebenfalls außen vor: Feldfarben hängen am Theme, ein
   `color:inherit` könnte helle Schrift auf hellem Feld erzeugen. */
:where(input, select, textarea, button){ font-family:inherit; font-size:inherit; }

/* Die kleinen Auf-/Ab-Pfeile an Zahlenfeldern zeichnet der Browser in
   seiner eigenen Optik: hell, klobig, mit eigener Trennlinie. In einem
   dunklen Design sieht das nach Fehler aus, und das Feld wird unnötig
   breit. Sie sind reine Zugabe — verstellen geht weiterhin mit den
   Pfeiltasten, dem Mausrad und der Tastatur. */
:where(input[type="number"]){ appearance:textfield; -moz-appearance:textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button{ -webkit-appearance:none; appearance:none; margin:0; }

/* Medien sprengen nie das Layout — ein zu großes Bild schiebt sonst die
   ganze Seite seitlich auf und erzeugt eine waagerechte Bildlaufleiste. */
:where(img, svg, video, canvas){ max-width:100%; }

/* Sichtbarer Fokus für Tastaturbedienung. `:focus-visible` erscheint nur
   bei Tastatur, nicht beim Mausklick. `currentColor` passt sich der
   Textfarbe des Themes an, ohne eine eigene Farbe vorzugeben. */
:where(:focus-visible){ outline:2px solid currentColor; outline-offset:2px; }

/* ── Menü-Knopf: der Grundzustand ────────────────────────────────────
   Den Knopf (☰) liefert der Kern (`Seite::navigation`), und `app.js`
   klappt damit das Menü auf. Ob er ÜBERHAUPT sichtbar ist und ob das
   Menü eingeklappt wird, stand bis 1.10.0 nur in `themes/standard` — ein
   App-Theme bekam also ein Bedienelement, das dauerhaft sichtbar und
   wirkungslos war. Man merkt so etwas schlecht, weil nichts fehlt,
   sondern etwas zu viel da ist.

   Hier steht deshalb nur die FUNKTION: wann der Knopf erscheint und dass
   `.nav.offen` das Menü zeigt. Aussehen (Farbe, Rahmen, Größe, Anordnung
   der Einträge) bleibt vollständig beim Theme.

   Der Umschaltpunkt 820px ist eine Vorgabe. Ein Theme mit eigener Grenze
   setzt seine eigene Media-Query — sie kommt später im Bündel und gewinnt;
   für den Bereich dazwischen dort `display:none` bzw. `display:flex`
   ausdrücklich setzen.

   ACHTUNG bei der Gewichtung: Das Ein-/Ausklappen steht hier BEWUSST nicht
   in `:where()`. Ein Theme setzt typischerweise `.nav{display:flex}` — mit
   `:where()` (Gewicht 0) käme der Kern dagegen nicht an, das Menü bliebe im
   schmalen Fenster ausgeklappt und der Knopf sinnlos (genau so gemessen).
   `.nav:not(.offen)` wiegt eine Klasse mehr und gewinnt. Ein Theme, das es
   anders will, überschreibt es mit `.kopf .nav{…}`. Beim reinen Aussehen
   (`.nav-schalter` im Ruhezustand) bleibt es bei `:where()`.

   WER DIE RICHTUNG DREHT, MUSS DIE AUSRICHTUNG MITDREHEN: Ein Theme setzt für
   die waagerechte Leiste fast immer `.nav{align-items:center}` — völlig richtig.
   Klappt der Kern dieselbe Leiste zur Spalte um, zentriert genau diese Regel die
   Einträge plötzlich WAAGERECHT und lässt sie auf Textbreite schrumpfen: ein
   schmaler, mittiger Stapel statt einer Liste. Deshalb gehören `align-items` und
   `flex-basis` hier dazu — sonst ist die Funktion nur halb hergestellt. Gemessen
   in der Energie-Zentrale (Theme „orbit"), Fenster 390 px.

   Die Mindestgröße des Knopfes ist ebenfalls Funktion, nicht Optik: Ohne sie war
   die Tap-Fläche 18 × 23 px — zu klein zum Treffen. Aussehen (Rahmen, Farbe,
   Schrift) bleibt beim Theme, deshalb per `:where()`. */
:where(.nav-schalter){ display:none; min-width:40px; min-height:40px; }

@media (max-width:820px){
  .nav-schalter{ display:block; }
  .nav:not(.offen){ display:none; }
  .nav.offen{ display:flex; flex-direction:column; align-items:stretch; flex-basis:100%; }
}

/* Dasselbe für die erzwungene Ansicht (Fuß-Umschalter Computer/Tablet/Handy):
   Dort zählt nicht die Fensterbreite, sondern die Wahl des Benutzers. */
body.geraet-handy .nav-schalter, body.geraet-tablet .nav-schalter{ display:block; }
body.geraet-handy .nav:not(.offen), body.geraet-tablet .nav:not(.offen){ display:none; }
body.geraet-handy .nav.offen, body.geraet-tablet .nav.offen{
  display:flex; flex-direction:column; align-items:stretch; flex-basis:100%;
}

/* Das aufgeklappte Menü braucht einen HINTERGRUND — sonst liegen die Einträge
   ohne Abgrenzung auf dem Seiteninhalt und es sieht aus, als schwebten sie
   (gemessen: `rgba(0,0,0,0)`, gemeldet als „poppt einfach oberhalb auf").
   Der Kern stellt hier nur die Lesbarkeit sicher; die Farbe kommt aus der
   Theme-Variable, der Rückfall greift nur, wenn ein Theme sie nicht setzt.
   Rundung und Innenabstand sind bewusst minimal — per `:where()` überschreibt
   ein Theme beides mit einer einzigen Regel. */
@media (max-width:820px){
  :where(.nav.offen){
    background:var(--karte, rgba(20,22,28,.97));
    border-radius:10px; padding:8px; gap:2px;
  }
}
:where(body.geraet-handy, body.geraet-tablet) :where(.nav.offen){
  background:var(--karte, rgba(20,22,28,.97));
  border-radius:10px; padding:8px; gap:2px;
}

/* ── Ansichtswahl: darf umbrechen ───────────────────────────────────
   Seit der vierten Position („Automatisch", 1.11.3) passt die Zeile nicht
   mehr in ein schmales Fenster: gemessen 412 px bei 390 px Fensterbreite —
   die Seite bekam dadurch eine WAAGERECHTE Bildlaufleiste. Umbrechen statt
   überstehen; Farben und Abstände bleiben beim Theme. */
:where(.ansicht-wahl){ display:inline-flex; flex-wrap:wrap; justify-content:center; }
:where(.fuss){ flex-wrap:wrap; }

/* ── Erzwungene Ansicht am großen Bildschirm ─────────────────────────
   Wer im Fuß „Handy" oder „Tablet" wählt, will die schmale Darstellung sehen
   — bisher passierte am Desktop fast nichts. Nur OBERHALB des Umschaltpunkts,
   damit sich auf einem echten Handy nichts ändert.

   ⚠️ Das ist eine Annäherung, keine Simulation: Die `@media (max-width:…)`-
   Regeln eines Themes beziehen sich auf das FENSTER, nicht auf diese Breite —
   sie greifen hier also nicht. Wer eine originalgetreue Vorschau will, hängt
   seine Handy-Regeln zusätzlich an `body.geraet-handy` (so macht es
   `themes/standard`). Genau daran liegt es, wenn die Umschaltung in einem
   App-Theme „nichts tut".

   ACHTUNG Gewichtung — hier bewusst OHNE `:where()`: Ein Theme setzt für den
   Inhalt fast immer `.inhalt{max-width:…}` (Gewicht 0,1,0). Mit `:where()`
   käme der Kern mit Gewicht 0,0,1 nicht dagegen an, und die erzwungene Ansicht
   bliebe wirkungslos — genau so gemessen (1180 px trotz „Handy"). Dieselbe
   Falle wie beim Menü in 1.11.3. `body.geraet-handy .inhalt` wiegt 0,2,0 und
   gewinnt; ein Theme überschreibt es mit `body.geraet-handy .kopf .inhalt`
   oder eigener Angabe. */
@media (min-width:821px){
  body.geraet-handy > .kopf,  body.geraet-handy > .inhalt,  body.geraet-handy > .fuss { max-width:430px; margin-inline:auto; }
  body.geraet-tablet > .kopf, body.geraet-tablet > .inhalt, body.geraet-tablet > .fuss{ max-width:834px; margin-inline:auto; }
}

/* ── Fenster (Dialoge): die Seite dahinter darf nicht scrollen ───────
   Solange ein Fenster offen ist, trägt `body` die Klasse `mw-gesperrt`
   (gesetzt von `assets/app.js`, siehe `mwSeiteSperren`). Ohne das scrollt
   das Mausrad über dem abgedunkelten Rand die Seite DARUNTER weg, während
   das Fenster selbst stehen bleibt.

   Damit der Inhalt beim Sperren nicht um die Breite der verschwindenden
   Bildlaufleiste springt, gleicht `app.js` sie mit einem Innenabstand aus —
   und nur dann. `scrollbar-gutter:stable` wäre der kürzere Weg, kostet aber
   DAUERHAFT Platz: gemessen 10 px weniger Inhaltsbreite bei 375 px Fenster,
   auch wenn gar kein Fenster offen ist. */
body.mw-gesperrt{ overflow:hidden; }

/* Und das Fenster muss SELBST scrollen können — sonst ist ein langer Inhalt
   unerreichbar, sobald die Seite dahinter gesperrt ist. Betrifft den Kasten
   im Fenster, nicht den abgedunkelten Hintergrund: Der trägt `aria-modal`
   in aller Regel am inneren Element (`<div class="…-box" role="dialog"
   aria-modal="true">`). Höhe und Aussehen bestimmt weiterhin das Theme. */
:where([aria-modal="true"]){ max-height:calc(100dvh - 2rem); overflow:auto; }
@supports not (max-height:100dvh){
  :where([aria-modal="true"]){ max-height:calc(100vh - 2rem); }
}

/* ── Meldungen (mwToast) und Rückfragen (mwConfirm): Grundzustand ─────
   Beide erzeugt der Kern (`assets/app.js`) — also sorgt der Kern dafür,
   dass sie in JEDEM Theme sichtbar, modal und über der Seite liegen.
   Bis 1.30.0 standen die Regeln nur in den Themes; `themes/admin` hatte
   keine: Meldung und Rückfrage hingen unterhalb der Seite, ohne Abdunklung.

   Gewichtung `div:where(.x)` = 0,0,1 — wie `body:where(…)` oben:
     · jede Theme-Regel mit Klasse/ID (0,1,0 / 1,0,0) gewinnt;
     · gegen einen Theme-Reset `*{margin:0;padding:0}` (0,0,0) gewinnt der
       Kern — sonst hätte ein Theme ohne eigene Regeln ein Fenster ohne
       Innenabstand.
   ⚠️ NUR Eigenschaften, die standard, orbit UND papier selbst setzen.
   Alles darüber hinaus sickert in ein Theme, das es bewusst weglässt
   (papier: kein Schatten am Fenster, kein Weichzeichner).
   ⚠️ Die Tag-Namen hängen am Markup in app.js (div/p/button). */
div:where(#mw-toasts){
  position:fixed; right:20px; bottom:20px; z-index:2000;
  display:flex; flex-direction:column; gap:10px;
  max-width:min(340px, calc(100vw - 40px));
}
div:where(.mw-toast){
  padding:12px 16px; border-radius:10px; font-size:14px;
  background:var(--karte-fest, var(--karte, #fff)); color:var(--text, #1f2d3d);
  border:1px solid var(--rand, #e3e8f0); border-left:4px solid var(--blau, #2563eb);
  box-shadow:0 8px 30px rgba(15,23,42,.16);
  transition:opacity .4s, transform .4s;
}
div:where(.mw-toast-erfolg){ border-left-color:var(--ok, #16a34a); }
div:where(.mw-toast-fehler){ border-left-color:var(--gefahr, #dc2626); color:var(--fehler-text, #b91c1c); }
/* „gespeichert, aber es tut nicht, was du erwartest" — z. B. „Oeffentlich"
   an einer Seite, die Anmeldung verlangt (module/seiten, ab 1.41.1). */
div:where(.mw-toast-warnung){ border-left-color:var(--gelb, #d97706); }
div:where(.mw-toast-weg){ opacity:0; transform:translateY(8px); }

div:where(.mw-modal-hg){
  position:fixed; inset:0; z-index:3000;
  display:flex; align-items:center; justify-content:center;
  background:rgba(15,23,42,.45);
}
div:where(.mw-modal){
  background:var(--karte-fest, var(--karte, #fff)); color:var(--text, #1f2d3d);
  border:1px solid var(--rand, #e3e8f0); border-radius:12px;
  padding:22px 24px; width:calc(100% - 40px); max-width:380px;
}
p:where(.mw-modal-text){ margin:0 0 18px; font-size:15px; }
div:where(.mw-modal-knoepfe){ display:flex; justify-content:flex-end; gap:10px; }
:where(.mw-modal-knoepfe) > button{
  padding:9px 16px; border-radius:8px; border:0;
  font-size:14px; font-weight:600; cursor:pointer; font-family:inherit;
}
button:where(.mw-modal-ja){ background:var(--blau, #2563eb); color:var(--blau-text, #fff); }
button:where(.mw-modal-nein){ background:transparent; border:1px solid var(--rand, #e3e8f0); color:var(--text-leise, #64748b); }
/* Fokusring: der Kern-Ring `currentColor` wäre auf „Ja" (weiße Schrift)
   weiß auf weißem Fenster — unsichtbar. Ein Theme mit eigenem
   `:focus-visible` (orbit, 0,1,0) gewinnt weiterhin. */
button:where(.mw-modal-ja:focus-visible, .mw-modal-nein:focus-visible){
  outline:2px solid var(--blau, #2563eb); outline-offset:2px;
}

/* ── Abzeichen am Menüpunkt und Punkt an der zugeklappten Gruppe ──────
   `Menue::abzeichen()` hängt ein `<span class="nav-abzeichen">` an einen
   Eintrag („Update 1.31.0", künftig die Zahl ungelesener Nachrichten);
   steckt das Abzeichen in einer ZUGEKLAPPTEN Gruppe, setzt `Menue` beim
   Kopf zusätzlich `<span class="nav-punkt">` (Menue.php:192, :334).

   ⚠️ WARUM im Kern und nicht im Theme: Bis 1.30.0 stand die Gestaltung
   nur in `themes/standard` und `themes/orbit`. `themes/papier` hat sie
   NICHT — dort wäre das Abzeichen ein nackter Inline-Span und der leere
   Punkt (kein Text, keine Fläche) vollständig unsichtbar. Und genau
   dorthin kommt der Hinweis nie von allein: Der Updater fasst fremde
   Themes grundsätzlich nicht an (`Aktualisierung.php:24`), ein Nachtrag
   müsste auf jeder Installation von Hand geschehen. Ein Hinweis, den man
   je nach Theme sieht oder nicht sieht, ist kein Hinweis.

   Farben theme-neutral über zwei Variablen mit Rückfall. ⚠️ Beide oder
   keine: Wer nur `--abzeichen-bg` umsetzt, bekommt irgendwann weiße
   Schrift auf hellem Grund. Ein einzelner Farbwert wie `--warnung` taugt
   hier nicht — in `orbit` ist das ein HELLES Amber mit dunkler Schrift,
   in `admin` ein dunkles Ocker mit heller. Der Rückfall #b45309/#fff ist
   der Wert aus `themes/standard` (Kontrast 4,6:1).

   Gewicht 0,0,1 wie der Block darüber: `themes/standard` (0,1,0) und
   `themes/orbit` (0,1,0) behalten ihre eigene Fassung unverändert. */
span:where(.nav-abzeichen){
  display:inline-block; margin-left:6px; padding:1px 7px; border-radius:999px;
  background:var(--abzeichen-bg, #b45309); color:var(--abzeichen-text, #fff);
  font-size:11px; font-weight:600; line-height:1.5; vertical-align:middle;
}
/* Ohne Text ist es nur ein Punkt — ein leeres Oval mit Innenabstand sähe
   aus wie ein Darstellungsfehler.
   ⚠️ `:empty` steht INNERHALB von `:where()`. Außerhalb wöge die Regel
   0,1,1 (eine Pseudoklasse zählt wie eine Klasse) und schlüge dem Theme
   sein eigenes `.nav-abzeichen` aus der Hand — die Spezifitäts-Falle. */
span:where(.nav-abzeichen:empty){
  padding:0; width:8px; height:8px; border-radius:50%; margin-left:5px;
}
span:where(.nav-punkt){
  display:inline-block; width:8px; height:8px; border-radius:50%;
  background:var(--abzeichen-bg, #b45309); margin-left:6px; vertical-align:middle;
}

/* Knopf „App installieren" (ab 1.20.1). Er zeigt sich nur auf Handy/Tablet
   und nur, wenn die Installation wirklich möglich ist — sichtbar gemacht
   wird er von `app.js`. Gestaltung bleibt beim Theme, das hier ist nur ein
   brauchbarer Grundzustand. */
:where(.mw-install) {
    display: inline-flex; align-items: center; gap: 6px;
    margin-left: 10px; padding: 5px 12px;
    border: 1px solid currentColor; border-radius: 999px;
    background: transparent; color: inherit;
    font: inherit; font-size: .92em; cursor: pointer;
}
:where(.mw-install)[hidden] { display: none; }
:where(.mw-install-zeichen) { font-weight: 700; line-height: 1; }

/* ── Bereichsumschalter — GRUNDGERÜST, gehört in den KERN ──────────────
   `Seite::bereichsWahl()` erzeugt diese Leiste in JEDEM Theme. Bisher
   standen ihre Regeln nur in `themes/standard` und `themes/admin` — ein
   App-Theme kannte sie nicht, und dann erschien neben jedem Symbol auch
   noch sein NAME. Genau so gemeldet von Tobias: „die 3 Symbole sind da,
   aber die Schrift ist immer noch da."

   Der Kern erzeugt ein Bedienelement → der Kern muss auch dafür sorgen,
   dass es benutzbar aussieht. Ein Theme darf es danach umfärben (diese
   Datei wird VOR dem Theme geladen), aber es muss nichts mehr wissen.

   Farben kommen aus Variablen mit Rückfall: Wer `--karte-tief` setzt,
   bekommt seine Farbe; wer nicht, bekommt einen brauchbaren Wert. */
.mw-bereiche {
    display: flex; gap: 2px; padding: 3px; margin-left: auto;
    background: var(--karte-tief, #eef2f8); border-radius: 10px;
}
.mw-bereich {
    display: grid; place-items: center;
    width: 34px; height: 30px; border-radius: 8px;
    color: var(--text-leise, #5a6b80); text-decoration: none;
}
/* ⚠️ Der Name wird VERSTECKT, nicht entfernt.
   `display:none` nähme ihn auch Screenreadern weg — dann hieße der Link
   nur noch „Link". Diese Form hält ihn im Dokument, aber aus dem Bild. */
.mw-bereich-text {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
}
.mw-bereich-zeichen { display: block; }
.mw-bereich:hover { background: var(--karte, rgba(255,255,255,.75)); color: var(--text, #1f2d3d); }
/* Bewusst NICHT `a.mw-bereich.aktiv`: Diese Regel steht hinter `:hover`,
   gewinnt also schon durch die Reihenfolge. Mit dem `a` davor wäre sie
   stärker als die Regel eines Themes — der Kern würde das Theme
   überstimmen, und genau andersherum ist es gemeint. */
.mw-bereich.aktiv { background: var(--blau, #2563eb); color: #fff; }
/* Auf schmalen Schirmen bleibt die Leiste, wo sie ist — drei Symbole
   brauchen keine eigene Zeile. Genau dafür sind sie da. */
@media (max-width: 640px) {
    .mw-bereich { width: 32px; height: 28px; }
}



/* Gemeinsame Inhalts-Fläche – EINE Klasse auf allen Karten/Boxen (Theme-Hook: hier ansetzen, dann ziehen alle mit) */
.mw-flaeche{ background:var(--karte, #ffffff); border:1px solid var(--rand, #e3e8f0); border-radius:16px; }

/* Segmentregler (Aus · An · Auto o. Ä.) — generischer Baustein, siehe Seite::segment().
   Gleiche Optik wie die Sprach-/Ansicht-Umschalter, nur wiederverwendbar. */
.mw-segment{
  position:relative;                 /* Bezug für die gleitende Markierung */
  display:inline-flex; padding:3px; gap:2px;
  border:1px solid var(--rand, #e3e8f0); border-radius:999px; background:var(--karte, #ffffff);
}
/* Die blaue Markierung ist ein EIGENES Element und gleitet über die Leiste —
   beim Ziehen folgt sie dem Finger, beim Loslassen rastet sie sanft ein.
   Wird per JS ergänzt; ohne JS bleibt der Hintergrund am aktiven Knopf. */
.mw-segment-pille{
  position:absolute; top:3px; bottom:3px; left:0; width:0;
  border-radius:999px; background:var(--blau, #2563eb);
  box-shadow:0 1px 3px rgba(37,99,235,.35);
  transition:transform .26s cubic-bezier(.34,1.3,.64,1), width .26s ease;
  pointer-events:none; z-index:0;
}
.mw-segment.mw-segment-glatt > button{ position:relative; z-index:1; }
/* Doppelt gemoppelt vermeiden: mit gleitender Pille darf der Knopf selbst KEINEN
   Hintergrund mehr haben (höhere Spezifität, damit die Reihenfolge egal ist). */
.mw-segment.mw-segment-glatt > button.aktiv{ background:transparent; box-shadow:none; }
/* Beim Ziehen wird die Markierung durchscheinend — sie zeigt dann nur, WO man
   gerade ist; gültig wird der Wert erst beim Loslassen. */
.mw-segment.zieht > .mw-segment-pille{ opacity:.55; box-shadow:none; }
.mw-segment.zieht > button.aktiv{ color:var(--blau, #2563eb); }

/* Verzögerung vor dem Melden (data-verzoegerung="1500"): ein dünner Balken läuft
   unten durch und zeigt, dass gleich etwas passiert — man kann es noch abfangen
   (zurück auf die Ausgangsposition oder Escape). */
.mw-segment-uhr{
  position:absolute; left:6px; right:6px; bottom:2px; height:2px;
  border-radius:2px; background:var(--blau, #2563eb); pointer-events:none;
  transform-origin:left center;
  animation-name:mw-segment-uhr-lauf; animation-timing-function:linear; animation-fill-mode:forwards;
}
.mw-segment.wartet > .mw-segment-pille{ opacity:.75; }
@media (prefers-reduced-motion: reduce){ .mw-segment-uhr{ animation:none; transform:scaleX(1); opacity:.5; } }
@media (prefers-reduced-motion: reduce){ .mw-segment-pille{ transition:none; } }
.mw-segment > button{
  padding:6px 14px; border:0; border-radius:999px; background:transparent;
  color:var(--text-leise, #64748b); font:inherit; font-size:13.5px; line-height:1.2;
  cursor:pointer; white-space:nowrap; transition:background .12s, color .12s;
}
.mw-segment > button:hover:not(.aktiv){ color:var(--blau, #2563eb); background:var(--blau-hell, #eff4ff); }
.mw-segment > button.aktiv{ background:var(--blau, #2563eb); color:#fff; box-shadow:0 1px 3px rgba(37,99,235,.35); }
.mw-segment > button:focus-visible{ outline:2px solid var(--blau, #2563eb); outline-offset:2px; }
/* Wischen: der Finger soll den aktiven Knopf schieben, nicht die Seite scrollen */
.mw-segment{ touch-action:none; }
.mw-segment > button{ user-select:none; -webkit-user-select:none; }
.mw-segment.zieht > button{ transition:none; }
.mw-segment.zieht > button.aktiv{ box-shadow:0 2px 8px rgba(37,99,235,.45); }
/* Auf schmalen Schirmen über die volle Breite, damit die Positionen tippbar bleiben */
@media (max-width: 480px){
  .mw-segment{ display:flex; width:100%; }
  .mw-segment > button{ flex:1; text-align:center; padding:8px 6px; }
}

/* ── Öffentliche Startseite ───────────────────────────────────────── */
.mw-start { display: grid; gap: 20px; }
.mw-start-block {
  background: var(--karte, #fff);
  border: 1px solid var(--rand, #e2e8f0);
  border-radius: 14px;
  padding: 56px 40px;
  text-align: center;
}
.mw-start-block h1 { font-size: 32px; margin: 0 0 12px; line-height: 1.2; }
.mw-start-text {
  color: var(--text-leise, #64748b); font-size: 17px;
  margin: 0 auto 28px; max-width: 620px;
}
.mw-start-knoepfe { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
/* Knöpfe auf der Startseite nie unterstrichen — sie sind Schaltflächen,
   keine Fließtext-Verweise. */
.mw-start-knoepfe .knopf,
.mw-start-knoepfe .knopf:hover { text-decoration: none; }

@media (max-width: 700px) {
  .mw-start-block { padding: 38px 22px; }
  .mw-start-block h1 { font-size: 25px; }
}
/* ── Kacheln, Schalter (Pillen) und Dashboard-Raster ───────────────────
   Standen bisher NUR im Verwaltungs-Design — dabei erscheinen Kacheln
   auch im ARBEITSBEREICH, also unter dem Theme der App. Ohne diese
   Regeln hat eine Kachel kein Raster, und der Schiebeschalter zeigt
   weder Bahn noch Knopf. Fast alles hier ist Struktur; die zwei festen
   Farben sind bewusst neutral. */


/* ── Kachelraster ──────────────────────────────────────────────────── */
.mw-dashboard {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  align-items: start;
}
.mw-dash-spalte { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.mw-kachel { padding: 0; overflow: hidden; position: relative; }
.mw-kachel + .mw-kachel { margin-top: 0; }

.mw-kachel-kopf {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--rand, #e3e8f0);
  background: linear-gradient(#fbfcfe, #f6f8fc);
}
.mw-kachel-titel { font-size: 15px; font-weight: 650; margin: 0; flex: 1 1 auto; }
.mw-kachel-inhalt { padding: 16px; }
.mw-kachel-inhalt > :first-child { margin-top: 0; }
.mw-kachel-inhalt > :last-child { margin-bottom: 0; }

/* Das Zahnrad — der kürzeste Weg von der Kachel in ihre Einstellungen.
   Bleibt blass, bis man die Kachel berührt: sichtbar genug, um zu wissen,
   dass es da ist, leise genug, um nicht zu stören. */
.mw-kachel-zahn {
  background: none; border: 0; cursor: pointer;
  color: var(--text-leise, #64748b); opacity: .45;
  font-size: 15px; line-height: 1;
  padding: 6px; border-radius: 6px;
  flex: 0 0 auto;
}
.mw-kachel:hover .mw-kachel-zahn { opacity: 1; }
.mw-kachel-zahn:hover { background: #eef2f9; color: var(--blau, #2563eb); }
.mw-kachel-zahn:focus-visible { opacity: 1; outline: 2px solid var(--blau, #2563eb); outline-offset: 1px; }

/* Kachel ohne Überschrift: kein Kopfbalken, das Zahnrad schwebt in der Ecke. */
.mw-kachel-ohne-kopf > .mw-kachel-zahn {
  position: absolute; top: 8px; right: 8px; z-index: 2;
}
.mw-kachel-ohne-kopf > .mw-kachel-inhalt { padding-right: 44px; }

/* „+ Kachel hinzufügen" — zeigt, dass hier noch etwas hinkommen kann. */
.mw-kachel-neu-zeile { margin-top: 18px; }
.mw-kachel-neu {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 20px;
  border: 2px dashed #c3d0e4;
  border-radius: var(--radius, 16px);
  color: var(--text-leise, #64748b);
  text-decoration: none;
  background: rgba(255,255,255,.5);
}
.mw-kachel-neu:hover { border-color: var(--blau, #2563eb); color: var(--blau, #2563eb); background: #fff; }
.mw-kachel-neu-plus {
  display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 8px;
  background: #e3ebf7; color: var(--blau, #2563eb); font-size: 18px; font-weight: 700;
}
.mw-kachel-neu:hover .mw-kachel-neu-plus { background: var(--blau, #2563eb); color: #fff; }

/* ── Schiebeschalter („Pille") ──────────────────────────────────────
   Nachgebaut nach Joomlas `switcher`: graue Bahn, bei „an" grün, der
   runde Knopf wandert. Darunter liegt eine echte Checkbox — sie wird
   ganz normal abgeschickt und ist tastaturbedienbar.
   Der Zustand ist damit auf einen Blick zu sehen; ein Häkchen muss man
   lesen, und bei zwanzig Schaltern untereinander liest man es nicht. */
.mw-pille {
  display: flex; align-items: center; gap: 11px;
  cursor: pointer; user-select: none;
}
.mw-pille input {
  position: absolute; opacity: 0; width: 0; height: 0;   /* da, aber unsichtbar */
}
.mw-pille-bahn {
  position: relative; flex: 0 0 auto;
  width: 46px; height: 26px;
  background: #cbd5e1;
  border-radius: 999px;
  transition: background .18s ease;
}
.mw-pille-knopf {
  position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px;
  background: #fff; border-radius: 50%;
  box-shadow: 0 1px 3px rgba(16,29,46,.3);
  transition: transform .18s ease;
}
.mw-pille input:checked ~ .mw-pille-bahn            { background: var(--gruen, #2563eb); }
.mw-pille input:checked ~ .mw-pille-bahn .mw-pille-knopf { transform: translateX(20px); }
/* Tastatur: der Fokusring gehört sichtbar an die Bahn, nicht an die
   unsichtbare Checkbox — sonst weiß niemand, wo er gerade steht. */
.mw-pille input:focus-visible ~ .mw-pille-bahn {
  outline: 2px solid var(--blau, #2563eb); outline-offset: 2px;
}

/* Ja/Nein daneben — genau eines ist sichtbar. */
.mw-pille-wort { flex: 0 0 auto; min-width: 34px; font-size: 13px; color: var(--text-leise, #64748b); }
.mw-pille-an   { display: none; }
.mw-pille input:checked ~ .mw-pille-wort .mw-pille-aus { display: none; }
.mw-pille input:checked ~ .mw-pille-wort .mw-pille-an  { display: inline; color: var(--gruen, #2563eb); font-weight: 600; }

/* ── Schmale Bildschirme ───────────────────────────────────────────── */
@media (max-width: 1100px) {
  .mw-dashboard { grid-template-columns: minmax(0, 1fr); }
}
/* ── Menü-Zeichen ──────────────────────────────────────────────────────
   `Menue::baue()` gibt vor jedem Eintrag ein Zeichen aus und kapselt die
   Beschriftung in `.nav-text`. Nur so kann ein Theme die Beschriftung
   ausblenden und die Leiste schmal machen, statt sie hinter einem
   Klappmenü verschwinden zu lassen (Wunsch von Tobias, 23.08.).

   Hier steht nur, was das ZEICHEN SELBST ausmacht — wo die Navigation
   sitzt und wann der Text weicht, entscheidet weiterhin das Theme. */
/* ⚠️ ZEICHEN SIND STANDARDMÄSSIG AUS — sie ersetzen die Beschriftung,
   sie begleiten sie nicht.
   In 1.23.7 standen sie IMMER neben dem Text. In einer Kopfzeilen-
   Navigation mit App-Theme sah das falsch aus; Tobias an der
   Energie-Zentrale: *„die Icons sollen natürlich nur erscheinen, wenn
   kein Platz mehr ist für die Schrift … das sieht sehr komisch aus."*
   Er hat recht: Ein Zeichen NEBEN dem Wort trägt nichts bei, es macht
   die Zeile nur breiter. Sinn hat es erst, wenn das Wort weichen muss.

   Ein Theme schaltet sie deshalb dort ein, wo es `.nav-text` ausblendet —
   und nur dort. Beides gehört zusammen; wer eins ohne das andere setzt,
   bekommt entweder doppelte Information oder gar keine. */
.nav-zeichen {
    display: none;
    flex: 0 0 auto;
    width: 18px; height: 18px;
    /* Für den Fall, dass ein Theme sie einblendet: `inline-block`, NICHT
       `block`. In einer Kopfzeilen-Navigation ist der Link oft kein
       Flex-Container — mit `block` rutscht die Beschriftung darunter und
       der Menüpunkt wird doppelt so hoch. */
    vertical-align: -0.22em;
}
/* Rückfall für Module ohne bekanntes Zeichen: der Anfangsbuchstabe.
   Bewusst dieselbe Grundfläche wie ein SVG, damit nichts springt.
   ⚠️ Rahmen statt Füllung: Mit `background: currentColor` hätte der
   Buchstabe dieselbe Farbe wie seine Fläche und wäre unsichtbar. So
   nehmen Rahmen UND Buchstabe die Textfarbe an — in jedem Theme. */
/* ⚠️ HIER STEHT BEWUSST KEIN `display`.
   Mit `display:grid` hätte diese Regel das `display:none` von
   `.nav-zeichen` überschrieben — gleiche Spezifität, aber später in der
   Datei. Der Buchstabe wäre also SICHTBAR geblieben, obwohl Zeichen aus
   sein sollen: genau der Fehler, den 1.23.8 beheben will, nur für Module
   ohne bekanntes Zeichen. Gemessen, nicht überlegt.
   Die Zentrierung setzt das Theme dort, wo es die Zeichen einblendet. */
.nav-zeichen-buchstabe {
    place-items: center;
    border-radius: 5px;
    border: 1.5px solid currentColor;
    font-size: 10px; font-weight: 700; line-height: 1;
}

/* Das kleine Zahnrad hinter einem Einstellungs-Verweis (`Menue::einstellung`,
   ab 1.44.0): „diese Zeile öffnet Einstellungen, keine Liste". Anders als
   `.nav-zeichen` IMMER sichtbar — es ersetzt keine Beschriftung, es ergänzt
   sie. Leise, damit es neben dem Wort nicht schreit; `margin-left:auto`
   schiebt es in Flex-Zeilen (Seitenleiste) an den rechten Rand. */
svg:where(.nav-marke){
  flex:0 0 auto; margin-left:auto; padding-left:6px; box-sizing:content-box;
  opacity:.55; vertical-align:-0.12em;
}

/* Trennlinie im Menü (Menue::trenner) und der Schnellzugriff „+". */
.nav-trenner {
    height: 1px; margin: 7px 12px;
    background: currentColor; opacity: .22;
}
/* Link und „+" in EINER Zeile — das „+" bleibt rechts am Rand. */
.nav-zeile { display: flex; align-items: center; gap: 2px; }
.nav-zeile > a:first-child { flex: 1 1 auto; min-width: 0; }
.nav-schnell {
    flex: 0 0 auto; display: inline-grid; place-items: center;
    width: 26px; height: 26px; margin-left: 4px;
    border-radius: 6px; text-decoration: none;
    font-size: 16px; line-height: 1; opacity: .75;
}
.nav-schnell:hover { opacity: 1; background: rgba(127,127,127,.25); }

/* ====================================================================
   Jarvis-Web · themes/jarvis/theme.css
   Dunkles Iron-Man/Jarvis-Design. Die Sprachanimation (Kern + Ringe +
   Sprachband) läuft als Canvas-Hintergrund aus themes/jarvis/theme.js
   (global, hinter dem Inhalt). Hier: Farben, Glas-Panels, Layout.
   App-eigenes Theme – vom Kern-Update nicht angefasst.
   ==================================================================== */

:root{
  --bg:#02070d;
  --blau:#54d7ff; --blau-dunkel:#8be7ff; --blau-hell:rgba(84,215,255,.12);
  --gruen:#54d7ff; --gruen-dunkel:#8be7ff; --mint:#54d7ff;
  --orange:#ff9a3d;
  --text:#eaf6ff; --text-leise:#93a9b8;
  --karte:#0a1a26; --rand:rgba(90,205,255,.22);
  --glas:rgba(8,22,34,.60);
  /* Kern-Formularfelder (Framework 1.2.1) zentral dunkel einfärben –
     ersetzt das frühere .ein-feld-„Pflaster". Wirkt auf Einstellungs- UND
     Login-Felder, da beide im Kern var(--feld-*) nutzen. */
  --feld-bg:rgba(4,14,22,.85); --feld-text:var(--text); --feld-rand:var(--rand);
  --font:'Segoe UI',system-ui,-apple-system,sans-serif;
}

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

html,body{ min-height:100%; }
body{
  position:relative;
  min-height:100vh;
  color:var(--text);
  font-family:var(--font);
  line-height:1.5;
  background:var(--bg);
  overflow-x:hidden;
}

/* Canvas-Hintergrund (aus theme.js) hinter allem, Inhalt darüber.
   Das Verschmelzen mit dem Hintergrund macht theme.js selbst (screen im
   Canvas), darum hier kein mix-blend-mode. */
#jv-bg{ position:fixed; inset:0; z-index:0; }
.kopf,.inhalt,.fuss,.inhalt-leer{ position:relative; z-index:1; }

/* Kopf */
.kopf{
  position:sticky; top:0; z-index:100;
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:14px 28px;
  background:rgba(3,10,18,.72);
  backdrop-filter:blur(14px);
  border-bottom:1px solid var(--rand);
}
.marke{ font-weight:800; font-size:18px; color:var(--blau); text-decoration:none; letter-spacing:1.5px;
  text-shadow:0 0 20px rgba(84,215,255,.5); }
.nav{ display:flex; gap:6px; align-items:center; }
.nav a{ padding:8px 14px; border-radius:9px; color:var(--text-leise); text-decoration:none; font-size:14px;
  transition:background .15s, color .15s; }
.nav a:hover,.nav a.aktiv{ background:var(--blau-hell); color:var(--blau); }

.nav-abmelden{ padding:8px 14px; border:1px solid var(--rand); border-radius:9px;
  background:transparent; color:var(--text-leise); font-size:14px; cursor:pointer; font-family:var(--font); }
.nav-abmelden:hover{ background:var(--blau-hell); color:var(--blau); border-color:var(--blau); }

/* Inhalt */
.inhalt{ max-width:1080px; margin:0 auto; padding:44px 28px 72px; }
.seiten-titel{ font-size:30px; font-weight:800; margin-bottom:24px; color:#f3fbff;
  text-shadow:0 0 26px rgba(84,215,255,.3); }

/* Glas-Panel über der Animation */
.karte{
  background:var(--glas);
  border:1px solid var(--rand); border-radius:18px;
  padding:22px 24px;
  backdrop-filter:blur(16px);
  box-shadow:0 20px 60px rgba(0,0,0,.45), inset 0 0 40px rgba(40,185,255,.05);
}
.karte-gross{ margin-bottom:24px; }
.willkommen{ font-size:18px; }

.kacheln{ display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:16px; }
.karte-label{ font-size:12px; letter-spacing:1px; text-transform:uppercase; color:var(--text-leise); }
.karte-wert{ font-size:24px; font-weight:700; margin-top:6px; color:var(--blau); text-shadow:0 0 16px rgba(84,215,255,.35); }

/* Fuß */
.fuss{ display:flex; flex-wrap:wrap; align-items:center; justify-content:center; gap:10px 18px;
  padding:20px 24px; color:var(--text-leise); font-size:13px; border-top:1px solid var(--rand);
  background:rgba(3,10,18,.5); backdrop-filter:blur(10px); }

a{ color:var(--blau); }

/* Formularfelder */
input, select, textarea{
  background:rgba(4,14,22,.85); color:var(--text);
  border:1px solid var(--rand); border-radius:10px; font-family:inherit;
}
input::placeholder, textarea::placeholder{ color:#5f7788; }
input:focus, select:focus, textarea:focus{ outline:none; border-color:var(--blau); box-shadow:0 0 0 3px rgba(84,215,255,.18); }
select option{ background:#0a1a26; color:var(--text); }

/* Auto-Ausfüllen: Chrome/Edge färben gespeicherte Logins weiß/gelb – dunkel erzwingen. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active{
  -webkit-text-fill-color:var(--feld-text, #eaf6ff) !important;
  -webkit-box-shadow:0 0 0 1000px rgba(4,14,22,.95) inset !important;
  caret-color:var(--feld-text, #eaf6ff);
  transition:background-color 9999s ease-out 0s;
}

/* (Kein .ein-feld-Override mehr nötig: die Einstellungsfelder ziehen seit
   Framework 1.2.1 über die oben gesetzten --feld-*-Variablen automatisch mit.) */

/* Knöpfe */
.knopf{ padding:11px 22px; border:1px solid rgba(84,215,255,.5); border-radius:11px;
  background:linear-gradient(135deg, rgba(13,128,180,.85), rgba(18,67,93,.92));
  color:#eaf8ff; font-size:15px; font-weight:600; cursor:pointer; font-family:inherit;
  box-shadow:0 0 22px rgba(47,190,240,.14); transition:filter .15s; }
.knopf:hover{ filter:brightness(1.15); }
.knopf-leise{ background:rgba(17,39,54,.6); border:1px solid var(--rand); color:var(--text-leise); box-shadow:none; }
.knopf-leise:hover{ color:var(--blau); border-color:var(--blau); filter:none; background:rgba(29,62,82,.75); }
.knopf-gefahr{ background:linear-gradient(135deg,#c23a2a,#7d241a); border-color:rgba(255,140,90,.5); color:#fff; }

/* Toasts */
#mw-toasts{ position:fixed; right:20px; bottom:20px; z-index:2000; display:flex; flex-direction:column; gap:10px; max-width:340px; }
.mw-toast{ padding:12px 16px; border-radius:11px; font-size:14px; background:rgba(8,22,32,.96); color:var(--text);
  border:1px solid var(--rand); border-left:4px solid var(--blau); box-shadow:0 12px 40px rgba(0,0,0,.5);
  opacity:1; transform:translateY(0); transition:opacity .4s, transform .4s; }
.mw-toast-erfolg{ border-left-color:#54d7ff; }
.mw-toast-fehler{ border-left-color:#ff6a5a; color:#ffb4ab; }
.mw-toast-weg{ opacity:0; transform:translateY(8px); }

/* Bestätigungsdialog */
.mw-modal-hg{ position:fixed; inset:0; z-index:3000; display:flex; align-items:center; justify-content:center;
  background:rgba(1,6,12,.66); backdrop-filter:blur(3px); }
.mw-modal{ background:linear-gradient(180deg, rgba(12,30,44,.98), rgba(6,18,28,.98)); color:var(--text);
  border:1px solid var(--rand); border-radius:14px; padding:22px 24px; width:calc(100% - 40px); max-width:380px;
  box-shadow:0 24px 70px rgba(0,0,0,.6); }
.mw-modal-text{ margin-bottom:18px; font-size:15px; }
.mw-modal-knoepfe{ display:flex; justify-content:flex-end; gap:10px; }
.mw-modal-knoepfe button{ padding:9px 16px; border-radius:10px; border:0; font-size:14px; font-weight:600; cursor:pointer; font-family:var(--font); }
.mw-modal-ja{ background:linear-gradient(135deg, rgba(13,128,180,.9), rgba(18,67,93,.95)); color:#eaf8ff; border:1px solid rgba(84,215,255,.5); }
.mw-modal-nein{ background:rgba(17,39,54,.7); border:1px solid var(--rand); color:var(--text-leise); }

/* Umschalter */
.ansicht-wahl{ display:inline-flex; align-items:center; gap:6px; }
.ansicht-wahl button{ background:transparent; border:1px solid var(--rand); border-radius:8px; color:var(--text-leise);
  font-size:12px; padding:3px 9px; cursor:pointer; font-family:var(--font); }
.ansicht-wahl button:hover{ color:var(--blau); border-color:var(--blau); }
.ansicht-wahl button.aktiv{ background:var(--blau-hell); color:var(--blau); border-color:var(--blau); }
.sprach-wahl{ display:inline-flex; align-items:center; padding:2px; border:1px solid var(--rand); border-radius:999px; background:rgba(6,20,30,.6); }
.sprach-wahl button{ border:0; background:transparent; border-radius:999px; color:var(--text-leise);
  font-size:12px; font-weight:700; letter-spacing:.3px; padding:4px 12px; cursor:pointer; font-family:var(--font); transition:background .15s, color .15s; }
.sprach-wahl button:hover:not(.aktiv){ color:var(--blau); background:var(--blau-hell); }
.sprach-wahl button.aktiv{ background:var(--blau-hell); color:var(--blau); box-shadow:0 0 12px rgba(84,215,255,.3); }
.nav-schalter{ display:none; background:transparent; border:1px solid var(--rand); border-radius:9px;
  color:var(--text); font-size:20px; line-height:1; padding:5px 12px; cursor:pointer; font-family:var(--font); }

/* ── Login/Ersteinrichtung: Karte schwebt zentriert über dem Kern ──── */
.inhalt-leer{ min-height:100vh; display:flex; align-items:center; justify-content:center; padding:24px; }
html body.seite-leer{ background:var(--bg); color:var(--text); }
body.seite-leer .auth{ width:100%; max-width:410px; }
body.seite-leer .auth-karte{
  background:rgba(6,18,28,.22); backdrop-filter:blur(5px);
  border:1px solid var(--rand); border-top:3px solid var(--blau); border-radius:18px;
  box-shadow:0 26px 80px rgba(0,0,0,.45), inset 0 0 44px rgba(40,185,255,.05);
}
/* Text auf der transparenten Karte lesbar halten (Schatten gegen den hellen Kern) */
body.seite-leer .auth-titel,
body.seite-leer .auth-info,
body.seite-leer .auth-karte label{ text-shadow:0 1px 6px rgba(0,10,18,.85); }
body.seite-leer .auth-marke{ color:var(--blau); text-shadow:0 0 16px rgba(84,215,255,.45); }
body.seite-leer .auth-titel{ color:#f3fbff; }
body.seite-leer .auth-info{ color:var(--text-leise); }
body.seite-leer .auth-karte label{ color:#cfe4f2; }
body.seite-leer .auth-tipp{ color:#7f96a6; }
/* Login-Felder ziehen über --feld-* mit (Framework 1.2.2) – kein eigener input-Override mehr. */
body.seite-leer .auth-karte button{
  background:linear-gradient(135deg, rgba(13,128,180,.9), rgba(18,67,93,.95));
  border:1px solid rgba(84,215,255,.5); color:#eaf8ff; box-shadow:0 0 24px rgba(47,190,240,.16); }
body.seite-leer .auth-karte button:hover{ filter:brightness(1.15); }
body.seite-leer .auth-fehler{ background:rgba(120,30,24,.35); color:#ffb4ab; border:1px solid rgba(255,120,90,.4); }
body.seite-leer .auth-karte code{ background:rgba(84,215,255,.12); color:#bfeaff; }

/* ── Login-Effekt: sobald Jarvis spricht (body bekommt .jv-aktiv), fällt die
   Box nach unten und die Felder (E-Mail, Passwort, Anmelden) legen sich
   waagerecht unter die Animation. Sanfter Übergang. ── */
body.seite-leer .auth{ transition:transform 1s cubic-bezier(.22,1,.36,1), max-width 1s cubic-bezier(.22,1,.36,1); }
body.seite-leer .auth-karte,
body.seite-leer .auth-karte label,
body.seite-leer .auth-karte button,
body.seite-leer #login-form, body.seite-leer #setup-form{ transition:all .8s cubic-bezier(.22,1,.36,1); }

body.seite-leer.jv-aktiv .auth{ transform:translateY(30vh); max-width:980px; }
body.seite-leer.jv-aktiv .auth-oben,
body.seite-leer.jv-aktiv .auth-titel,
body.seite-leer.jv-aktiv .auth-info{ display:none; }             /* flache Leiste: nur die Felder */
body.seite-leer.jv-aktiv .auth-karte{ padding:16px 20px; }
body.seite-leer.jv-aktiv #login-form,
body.seite-leer.jv-aktiv #setup-form{
  display:flex; flex-direction:row; align-items:flex-end; flex-wrap:wrap; gap:14px;
}
body.seite-leer.jv-aktiv #login-form label,
body.seite-leer.jv-aktiv #setup-form label{ flex:1 1 190px; margin-bottom:0; }
body.seite-leer.jv-aktiv .auth-karte button{ width:auto; flex:0 0 auto; margin-top:0; }
body.seite-leer.jv-aktiv .auth-fehler{ flex-basis:100%; margin:0; }

/* Responsiv */
@media (max-width: 820px){
  .kopf{ flex-wrap:wrap; padding:12px 18px; }
  .nav-schalter{ display:block; }
  .nav{ display:none; flex-basis:100%; flex-direction:column; gap:4px; padding-top:10px; }
  .nav.offen{ display:flex; }
  .nav a, .nav-abmelden{ width:100%; text-align:left; }
  .inhalt{ padding:28px 18px 56px; }
  .seiten-titel{ font-size:25px; }
}
@media (max-width: 560px){
  .kopf{ padding:10px 14px; }
  .marke{ font-size:16px; }
  .inhalt{ padding:20px 14px 44px; }
  .seiten-titel{ font-size:21px; margin-bottom:18px; }
  .karte{ padding:16px; border-radius:14px; }
  .kacheln{ grid-template-columns:1fr; }
  #mw-toasts{ left:14px; right:14px; max-width:none; }
}
body.geraet-handy .nav-schalter, body.geraet-tablet .nav-schalter{ display:block; }
body.geraet-handy .kopf, body.geraet-tablet .kopf{ flex-wrap:wrap; }
body.geraet-handy .nav, body.geraet-tablet .nav{ display:none; flex-basis:100%; flex-direction:column; gap:4px; padding-top:10px; }
body.geraet-handy .nav.offen, body.geraet-tablet .nav.offen{ display:flex; }
body.geraet-handy .nav a, body.geraet-handy .nav-abmelden,
body.geraet-tablet .nav a, body.geraet-tablet .nav-abmelden{ width:100%; text-align:left; }
body.geraet-tablet .inhalt{ max-width:760px; }
body.geraet-handy  .inhalt{ max-width:460px; }
body.geraet-handy  .kacheln{ grid-template-columns:1fr; }

/* ====================================================================
   Nachgezogen 1.22.0: verschachtelte Menüs (Dropdowns) + Segmentregler.
   Diese Bausteine waren nur im standard-Theme gestylt — im jarvis-Theme
   fehlten sie, dadurch erschienen Menü-Pfeile und Umschalter als grelle
   weiße Browser-Kästen auf dunklem Grund. Hier in der jarvis-Palette.
   ==================================================================== */

/* -- Verschachtelte Menüs / Dropdowns ------------------------------- */
.nav-gruppe{ position:relative; display:flex; align-items:center; }
.nav-kopf{ display:inline-flex; align-items:center; gap:4px; }
.nav-gruppe-kopf{ padding:8px 14px; border:0; border-radius:9px; background:transparent;
  color:var(--text-leise); font:inherit; font-size:14px; cursor:pointer; }
.nav-gruppe-kopf:hover{ background:var(--blau-hell); color:var(--blau); }
.nav-pfeil{ font-size:10px; opacity:.7; }
.nav-auf{ border:0; background:transparent; color:var(--text-leise); cursor:pointer;
  font-size:11px; line-height:1; padding:7px 6px; border-radius:6px; margin-left:-8px; }
.nav-auf:hover{ color:var(--blau); background:var(--blau-hell); }
.nav-gruppe.aktiv-pfad > .nav-kopf{ color:var(--blau); }
.nav-abzeichen{ display:inline-block; margin-left:6px; padding:1px 7px; border-radius:999px;
  background:var(--orange); color:#06131e; font-size:11px; font-weight:700; line-height:1.5; vertical-align:middle; }
.nav-abzeichen:empty{ padding:0; width:8px; height:8px; border-radius:50%; margin-left:5px; }
.nav-punkt{ display:inline-block; width:8px; height:8px; border-radius:50%;
  background:var(--orange); margin-left:6px; vertical-align:middle; }
.nav a.aktiv .nav-abzeichen, .nav-kopf.aktiv .nav-abzeichen{ background:var(--blau); color:#06131e; }
.nav-unter{ display:none; position:absolute; top:100%; left:0; z-index:120;
  min-width:190px; padding:6px; margin-top:6px; flex-direction:column; gap:2px;
  background:var(--karte); border:1px solid var(--rand); border-radius:12px;
  box-shadow:0 16px 40px rgba(0,0,0,.55); }
.nav-unter::before{ content:''; position:absolute; left:0; right:0; top:-10px; height:10px; }
.nav-unter a, .nav-unter .nav-gruppe-kopf, .nav-unter .nav-kopf{ width:100%; text-align:left; white-space:nowrap; }
.nav-unter .nav-gruppe{ display:flex; }
.nav-unter .nav-gruppe .nav-kopf{ flex:1; }
.nav-unter .nav-unter{ top:-7px; left:100%; margin:0 0 0 6px; }
.nav-unter .nav-unter::before{ left:-10px; right:auto; top:0; bottom:0; width:10px; height:auto; }
.nav-gruppe.auf > .nav-unter{ display:flex; }
@media (hover:hover) and (pointer:fine){
  .nav-gruppe:hover > .nav-unter, .nav-gruppe:focus-within > .nav-unter{ display:flex; }
}

/* -- Segmentregler (Aus · An · Auto o. Ä.) -------------------------- */
.mw-segment{ position:relative; display:inline-flex; padding:3px; gap:2px;
  border:1px solid var(--rand); border-radius:999px; background:var(--karte); }
.mw-segment > button{ position:relative; z-index:1; border:0; background:transparent;
  color:var(--text-leise); border-radius:999px; padding:6px 14px; font:inherit;
  font-size:14px; cursor:pointer; font-family:var(--font); white-space:nowrap; }
.mw-segment > button:hover:not(.aktiv){ color:var(--blau); background:var(--blau-hell); }
.mw-segment > button.aktiv{ color:var(--blau); background:var(--blau-hell); }
.mw-segment-pille{ position:absolute; top:3px; bottom:3px; left:0; width:0;
  border-radius:999px; background:var(--blau-hell); box-shadow:0 0 12px rgba(84,215,255,.25);
  transition:transform .26s cubic-bezier(.34,1.3,.64,1), width .26s ease; pointer-events:none; z-index:0; }
.mw-segment.mw-segment-glatt > button{ position:relative; z-index:1; }
.mw-segment.mw-segment-glatt > button.aktiv{ background:transparent; box-shadow:none; }
.mw-segment.zieht > .mw-segment-pille{ opacity:.55; box-shadow:none; }
.mw-segment.zieht > button.aktiv{ color:var(--blau); }
.mw-segment-uhr{ position:absolute; left:6px; right:6px; bottom:2px; height:2px;
  border-radius:2px; background:var(--blau); pointer-events:none; transform-origin:left center;
  animation-name:mw-segment-uhr-lauf; animation-timing-function:linear; animation-fill-mode:forwards; }
@keyframes mw-segment-uhr-lauf{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }
.mw-segment.wartet > .mw-segment-pille{ opacity:.75; }
@media (prefers-reduced-motion: reduce){ .mw-segment-uhr{ animation:none; transform:scaleX(1); opacity:.5; } }
@media (prefers-reduced-motion: reduce){ .mw-segment-pille{ transition:none; } }

/* Gemeinsame Flächen-Klasse (Karten/Gruppen) — war nur im standard-Theme. */
.mw-flaeche{ background:var(--glas); border:1px solid var(--rand); border-radius:14px; }

