/* ═══════════════════════════════════════════════════════════════════════════
   wetter.bymw.de — Held (aktuelle Lage), Stundenband, Tageskarten, Einigkeit.
   Tokens und Ebenen-Leiter kommen aus wetter.css.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Held ──────────────────────────────────────────────────────────────────
   Die Fläche, auf der die Wetteranimation läuft — und die wichtigste Fläche
   der ganzen Seite. Sie folgt dem Muster einer guten Bildunterschrift: OBEN
   freier Himmel, UNTEN eine dunkle Textfläche.

   ⚠️ DAS IST EINE ANTWORT AUF EINEN GEMELDETEN FEHLER, KEIN GESCHMACK. Vorher
   lagen Ortsname und Temperatur mitten auf der Animation und brauchten je einen
   eigenen, per `filter: blur()` auslaufenden Schirm, weil sonst der Untertitel
   über der Sonne bei 1,97:1 stand. Gemessen war das in Ordnung (5,1:1); zu
   SEHEN war ein dunkler Schmierfleck, der auf großen Bildschirmen als Rechteck
   im blauen Nichts hing. Dazu klaffte zwischen Ortsname (oben) und Temperatur
   (unten) auf 2560 px rund 400 px Leere.

   Jetzt trägt EINE Fläche den Kontrast (`.wx-held-blatt`), der obere Teil des
   Himmels bleibt ganz frei, und alle Textblöcke stehen zusammen. Nebenbei
   entfallen sämtliche `backdrop-filter` im Helden — also der teuerste Posten
   auf langsamen Geräten. */
/* ── Die Farbwelt des Himmels ──────────────────────────────────────────────
   ⚠️ DREI FARBEN, GESETZT VON js/app.js, NICHT AUS DEM THEMA. Der Held zeigt
   nicht die Seite, sondern das Wetter: klarer Mittag, bedeckter Nachmittag,
   Dämmerung, Nacht und Gewitter sind fünf verschiedene Stimmungen, und eine
   feste Farbe kann höchstens eine davon treffen.

   ⚠️ `@property` ist hier kein Zierrat, sondern die Bedingung dafür, dass der
   Wechsel WEICH läuft. Ein Farbverlauf lässt sich nicht überblenden; drei
   einzelne Farben schon — aber nur, wenn der Browser weiß, dass es Farben sind.
   Ohne die Deklaration springt die Farbe hart um (kein Fehler, nur weniger
   schön), mit ihr wandert sie über eine Sekunde. */
@property --himmel-1 { syntax: '<color>'; inherits: true; initial-value: #1b3570; }
@property --himmel-2 { syntax: '<color>'; inherits: true; initial-value: #112450; }
@property --himmel-3 { syntax: '<color>'; inherits: true; initial-value: #0a1430; }

.wx-held {
  position: relative; overflow: hidden;
  margin-top: var(--sp-16);
  border-radius: var(--r-24);
  --himmel-1: #1b3570; --himmel-2: #112450; --himmel-3: #0a1430;
  background: linear-gradient(165deg, var(--himmel-1) 0%, var(--himmel-2) 52%, var(--himmel-3) 100%);
  transition: --himmel-1 var(--mo-lang) var(--ease-standard),
              --himmel-2 var(--mo-lang) var(--ease-standard),
              --himmel-3 var(--mo-lang) var(--ease-standard);
  box-shadow: var(--sh-3), var(--sh-saum);
  isolation: isolate;          /* eigener Stapelraum: --z-fx wirkt nur hier drin */
  /* ── Parallax ────────────────────────────────────────────────────────────
     `--wx-par` (0…1) schreibt js/ui-parallax.js je Bild; die beiden Wege stehen
     HIER, damit die Tiefe an EINER Stelle einstellbar ist statt verteilt über
     zwei `calc()`.
     ⚠️ Sie müssen deklariert sein, auch wenn JS sie überschreibt: `qa/wetter-
        css.mjs` meldet jede benutzte, aber nirgends definierte Variable — und
        zwar zu Recht, denn ohne Deklaration ist ein Tippfehler im Namen
        vollkommen unsichtbar (die Regel fällt still auf den Rückfallwert
        zurück). Genau so ist es hier beim ersten Anlauf gewesen.
     Die Zahlen sind angesehen, nicht gerechnet: 40 px Himmel gegen 26 px Text
     ergibt den Unterschied, der Tiefe macht; mehr liest sich als Rutschen. */
  --wx-par: 0;
  --wx-par-weg: 40px;
  --wx-par-text: 26px;
  /* ⚠️ Die Mindesthöhen sind GEMESSEN, nicht gewählt: Ladeskelett und fertiger
     Inhalt teilen sie sich, sonst rutscht beim Eintreffen der Daten die halbe
     Seite nach (gemessener CLS 0,47, siehe die Notiz beim Stundenband). Wer die
     Typografie im Helden ändert, misst sie neu — qa/wetter-fein.mjs meldet die
     Abweichung. */
  min-height: 340px;
}
/* ⚠️ Auf dem Desktop höher als früher (300/340/380 → 460/500/560): Der Inhalt
   steht oben, darunter liegt freier Himmel, der sich in die Seite auflöst
   (`.wx-held::after`). Ohne diesen Freiraum liefe der Text in den Auflöse-
   Streifen und verlöre seinen dunklen Grund (qa/wetter-kontrast.mjs). */
@media (min-width: 700px)  { .wx-held { min-height: 460px; } }
@media (min-width: 1000px) { .wx-held { min-height: 500px; } }
@media (min-width: 1600px) { .wx-held { min-height: 560px; } }

/* ⚠️ Der Held folgt NICHT dem Hell/Dunkel-Schalter, sondern dem Wetter und der
   Tageszeit. Ein heller Modus mit einem Nachthimmel wäre kein Widerspruch,
   sondern richtig: Nachts ist der Himmel dunkel, auch wenn die Seite hell ist.
   Deshalb steht hier keine Theme-Regel mehr — die Farben kommen aus
   `himmelFarben()` in js/app.js, und die kennen nur Wetter und Uhrzeit. */

/* ⚠️ `width`/`height` SIND HIER PFLICHT, `inset: 0` GENÜGT NICHT. Ein <canvas>
   ist ein ERSETZTES Element mit einer eigenen Grundgröße (300 × 150). Bei
   absoluter Positionierung löst `width: auto` für solche Elemente nicht „fülle
   den Zwischenraum" auf, sondern „nimm deine Grundgröße" — die Angaben links
   und rechts sind dann überbestimmt, und der Browser verwirft `right`.
   Die Wetteranimation lief dadurch in einem 300 × 150 großen Kasten in der
   oberen linken Ecke des Helden, statt die Karte zu füllen. Auf dem Handy fiel
   das nicht auf (dort ist die Karte kaum breiter), auf dem Desktop stand ein
   hellerer Rechteck-Ausschnitt im Himmel, den man für ein Wolkensprite hielt.
   Gemessen: Karte 1244 × 354, Leinwand 300 × 150. */
.wx-held-fx {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: var(--z-fx);
  /* ⚠️ DER HIMMEL BEWEGT SICH LANGSAMER ALS DER TEXT — das ist der ganze Trick.
     0,28 statt 1 heißt: Rollt die Seite um die Höhe des Helden, wandert der
     Himmel nur gut ein Viertel davon mit. Mehr als 0,35 sieht nach Rutschen
     aus, weniger als 0,2 nach gar nichts (beides angesehen).
     `will-change` steht bewusst NICHT hier: Es zwingt den Browser, die Ebene
     dauerhaft freizustellen, und die Leinwand ist die größte Fläche der Seite.
     `translate3d` allein genügt für den Compositor. */
  transform: translate3d(0, calc(var(--wx-par, 0) * var(--wx-par-weg, 40px)), 0);
}

.wx-held-in {
  position: relative; z-index: var(--z-inhalt);
  display: flex; flex-direction: column; justify-content: flex-start;
  min-height: inherit;
}

/* ⚠️ DER HELDENTEXT WEICHT DER ZIEHGESTE AUS. Am Seitenanfang gibt es keinen
   freien Streifen, in dem ein Zeiger erscheinen könnte: Zwischen Kopfzeile und
   Ortsname liegen gemessen elf Punkte. Ohne dieses Ausweichen legt sich der
   Zeiger beim Ziehen quer über den Ortsnamen — genau das war am ersten Entwurf
   zu sehen.

   Der naheliegende Weg wäre, wie in einer nativen App die ganze SEITE nach
   unten zu schieben. Er wurde verworfen: Darüber käme dann die Seitenfläche
   zum Vorschein, also im Hellmodus ein weißer Streifen über einem dunklen
   Himmel. Hier wandert nur der Text, der Himmel bleibt stehen und füllt weiter
   bis an die Oberkante — er ist ohnehin das, was man beim Ziehen ansieht.

   Bezugsgröße ist `--wx-zieh-t` (0…1 bis zur Schwelle), nicht der rohe Weg:
   Jenseits der Schwelle ist die Entscheidung gefallen, da soll nichts mehr
   wandern. 72 Punkte sind gemessen — so viel braucht es, damit der 38 Punkte
   hohe Zeiger samt Luft über dem Namen Platz hat. `transform` bleibt beim
   Compositor; das läuft bei jedem `touchmove` und darf kein Layout auslösen. */
/* 🚨 ZWEI URSACHEN, EINE ANGABE. Der Textblock wird von zwei Dingen bewegt:
   der Zieh-Geste (72 px) und dem Parallax beim Rollen. Zwei getrennte
   `transform`-Regeln gibt es in CSS nicht — die zweite ersetzt die erste. Und
   zwei Skripte, die dieselbe Eigenschaft schreiben, überschreiben sich je nach
   Reihenfolge; der Zieh-Zeiger stünde dann manchmal wieder auf dem Ortsnamen.
   Deshalb liefert jede Seite nur ihre ZAHL (`--wx-zieh-t`, `--wx-par`).

   🚨 ABER SIE WERDEN NICHT MEHR ADDIERT — sie sitzen auf ZWEI EBENEN, und das
      ist der Kern der Reparatur. Vorher trugen beide Bewegungen dasselbe
      Element (`.wx-held-haupt`), während `.wx-kennzahlen` daneben stehen blieb.
      Für den Parallax ist genau das richtig: Der Text soll beim Rollen nach
      oben wegziehen und die Kennzahlen sollen bleiben — daraus entsteht die
      Tiefe. Für die ZIEHGESTE ist es falsch: Dort schiebt sich der Text nach
      UNTEN, also auf die stehenden Kennzahlen zu. Das ging gut, solange
      zwischen beiden ein handbreites Loch stand; als das Loch beseitigt wurde
      (`space-between`, weiter unten), blieben 20 Punkte Abstand bei 72 Punkten
      Weg — und die Detailzeile schob sich 52 Punkte WEIT ÜBER die Kennzahlen.
      Vom Betreiber fotografiert: „Regenrisiko" und „Gefühlt" übereinander,
      „10 %" quer durch „31°".

      Zwei Geschwister, von denen nur eines mitfährt, kollidieren zwangsläufig,
      sobald der Abstand kleiner wird als der Weg. Die Geste bewegt deshalb das
      ganze Blatt (Text UND Kennzahlen), der Parallax weiterhin nur den Text.
      Damit ist die Kollision strukturell ausgeschlossen — unabhängig davon, wie
      eng es zwischen den beiden künftig wird.
   ⚠️ Dass unten dabei etwas aus dem Bild läuft, ist kein Nebeneffekt, sondern
      der Sinn: `.wx-held` hat `overflow: hidden`, die Kennzahlen schieben sich
      also sauber unter die Kante — genau so fühlt sich natives Ziehen an.
   ⚠️ Die beiden stören einander nicht: Gezogen wird nur am Seitenanfang, und
      dort ist `--wx-par` null. */
.wx-held-blatt {
  transform: translate3d(0, calc(var(--wx-zieh-t, 0) * 72px), 0);
}
.wx-held-haupt {
  transform: translate3d(0, calc(-1 * var(--wx-par, 0) * var(--wx-par-text, 26px)), 0);
  /* Der Text verblasst, während er verschwindet — sonst schiebt er sich unter
     die Kennzahlen und wird für einen Moment unlesbar statt weg zu sein. */
  opacity: calc(1 - var(--wx-par, 0) * 0.55);
}
/* Die Kennzahlen bleiben beim ROLLEN stehen: Sie sind der Grund, warum der Held
   so hoch ist, und sollen bis zuletzt lesbar sein. Beim ZIEHEN fahren sie mit —
   siehe oben. */
@media (prefers-reduced-motion: reduce) {
  .wx-held-fx, .wx-held-haupt, .wx-held-blatt { transform: none; }
  .wx-held-haupt { opacity: 1; }
}
/* Nach dem Loslassen federt das Blatt zurück; WÄHREND der Geste darf nichts
   nachlaufen, sonst hängt der Text hinter dem Finger. */
html:not(.wx-zieht) .wx-held-blatt {
  transition: transform var(--mo-mittel) var(--ease-standard);
}
/* ⚠️ DER FREIE HIMMEL IST EIN EIGENES ELEMENT, KEIN REST. Zuerst hing er an
   `min-height` — und war damit genau dann weg, wenn das Textblatt hoch wurde:
   auf dem Handy gemessen 417 px Blatt in einer 417 px hohen Karte, also NULL
   Himmel. Die Animation lief unter einer deckenden Fläche, und das teuerste
   Stück der Seite war unsichtbar. Als fester Streifen ist der Himmel dagegen
   garantiert, egal wie lang der Ortsname ist. */
.wx-held-in::before { content: ""; flex: 0 0 auto; height: 76px; }
@media (min-width: 700px)  { .wx-held-in::before { height: 92px; } }
@media (min-width: 1600px) { .wx-held-in::before { height: 120px; } }

/* ── Der Einigkeits-Chip im Helden — der Markenkern, ganz oben ──────────────
   🚨 KEIN GLAS, KEIN BALKEN, KEIN backdrop-filter. Genau daran scheiterte die
      alte Kachel im Helden: weißer Text über einer laufenden Animation. Der
      Chip trägt deshalb eine EIGENE, deckende dunkle Fläche (kein Durchscheinen
      des Himmels), weiße Schrift, und die Stufe steckt in der FARBE DER ZAHL —
      nie in der Farbe allein (das Wort steht im aria-label, `qa/wetter-a11y`
      und die Bedeutung hängt nicht am Sehen der Farbe). */
.wx-held-einig {
  align-self: center;
  display: inline-flex; align-items: center; gap: var(--sp-8);
  margin-bottom: var(--sp-12);
  /* Volles Fingerziel (48 px) über die Höhe — der Chip ist tippbar und führt zur
     Karte; `qa/wetter-design.mjs` verlangt 48 px. Vertikal über `min-height`
     zentriert, nicht über Polster, damit die Höhe konstant bleibt. */
  min-height: var(--ziel);
  padding: 0 var(--sp-12) 0 var(--sp-8);
  border-radius: var(--r-pill);
  background: rgba(3, 8, 20, .52);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18), var(--sh-1);
  color: #ffffff; font-size: var(--fs-13); line-height: 1;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform var(--mo-kurz) var(--ease-standard),
              background-color var(--mo-kurz) var(--ease-standard);
}
.wx-held-einig:active { transform: scale(.97); background: rgba(3, 8, 20, .62); }
@media (hover: hover) and (pointer: fine) {
  .wx-held-einig:hover { background: rgba(3, 8, 20, .62); }
}
.wx-held-einig b { font-size: var(--fs-16); font-weight: 800; letter-spacing: -.01em; }
.wx-held-einig-lab { color: rgba(255, 255, 255, .9); font-weight: 600; }
.wx-held-einig-dot {
  width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .12);
}
.wx-held-einig.stufe-hoch   .wx-held-einig-dot { background: #6ee7b7; }
.wx-held-einig.stufe-hoch   b { color: #8ff0cb; }
.wx-held-einig.stufe-mittel .wx-held-einig-dot { background: #ffcf6b; }
.wx-held-einig.stufe-mittel b { color: #ffda8c; }
.wx-held-einig.stufe-gering .wx-held-einig-dot { background: #ff9b9b; }
.wx-held-einig.stufe-gering b { color: #ffb0b0; }
/* Das Ladeskelett des Chips — gleiche Fläche, neutraler Inhalt, damit der Kopf
   des Helden beim Eintreffen der Daten nicht springt. */
.wx-held-einig-lade { cursor: default; padding: 7px var(--sp-12); }
.wx-held-einig-lade .wx-skelett { display: block; height: 1em; }
@media (prefers-reduced-motion: reduce) { .wx-held-einig { transition: none; } }

/* ══════════════════════════════════════════════════════════════════════════
   HANDY: DER HELD IST DER BILDSCHIRM, KEINE KARTE
   ══════════════════════════════════════════════════════════════════════════
   Auf einem Telefon ist die aktuelle Lage nicht ein Element unter anderen —
   sie ist das, wofür die App geöffnet wurde. Eine Karte mit Rand ringsum
   verschenkt dafür an jeder Seite 16 px und trennt den Himmel sichtbar vom
   Rest. Deshalb hier: randlos bis in alle vier Ecken, unter dem schwebenden
   Kopf hindurch, und so hoch, dass die wichtigsten Zahlen ohne Rollen zu sehen
   sind.

   ⚠️ `svh`, nicht `vh` oder `dvh`. `vh` meint die Höhe MIT eingeklappten
   Browserleisten — der Held wäre beim Öffnen zu hoch, und die Kennzahlen
   stünden unter der Adressleiste. `dvh` ändert sich beim Rollen und ließe den
   Helden mitwachsen. `svh` ist die KLEINSTE Höhe, also die, in der es sicher
   passt.

   ⚠️ 86 % statt 100 %: Der Rest der Seite muss angeschnitten sein. Ein Bild,
   das exakt mit dem Bildschirm endet, sieht aus, als wäre da nichts mehr. */
@media (max-width: 699px) {
  .wx-held {
    margin-top: calc(-1 * (var(--kopf-h) + var(--wx-sat)));
    margin-left: calc(-1 * var(--wx-rand-l));
    margin-right: calc(-1 * var(--wx-rand-r));
    /* 🚨 KEINE RUNDUNG am unteren Rand. Der Held läuft randlos bis an die
       Seitenkanten; runde Ecken unten ließen NEBEN der Rundung die Seitenfläche
       durchblitzen — genau die sichtbare Kante/Stufe, die gemeldet wurde
       („Übergang soll wirklich fließend sein"). Mit einer geraden Unterkante
       blendet der `.wx-held::after`-Streifen über die volle Breite nahtlos in
       den Himmel der Seite (`body::before`) über. */
    border-radius: 0;
    /* ⚠️ 78 % der kleinsten Bildschirmhöhe. Mit 86 % klaffte zwischen der
       Tagesspanne und der Kennzahlenleiste ein Loch von rund 400 px — freier
       Himmel ist Atmosphäre, aber ein halber Bildschirm davon ist eine Lücke.
       78 % lassen genug Luft und schneiden zugleich die nächste Karte an, damit
       sichtbar bleibt, dass es weitergeht. */
    min-height: 78svh;
  }
  /* Der Platzhalter oben hält den schwebenden Kopf frei. */
  .wx-held-in::before { height: calc(var(--kopf-h) + var(--wx-sat)); }

  /* ⚠️ Alles MITTIG, wie in jeder guten Wetter-App — und in dieser Reihenfolge:
     Ort, Temperatur, Lage, Spanne. Der Blick fällt auf die Zahl, und von dort
     aus ordnet sich das Übrige darum. Linksbündig gelesen wäre dieselbe
     Information eine Liste; mittig ist sie ein Bild. */
  .wx-held-blatt {
    flex: 1 1 auto; justify-content: center;
    /* Der Verlauf beginnt weiter oben, weil der Text jetzt in der Mitte steht
       und nicht mehr am unteren Rand.
       ⚠️ DIE OBERE HÄLFTE WURDE NACHGEZOGEN (.32/.26 → .38/.34), als der Himmel
       eine Szene wurde. Sonnenschein, Lichtbänder und Horizontglut heben ihn
       zusammen um ein paar Prozent an — für sich genommen jedes unauffällig,
       in Summe genug, dass die Ortszeile bei klarem Tageshimmel auf 4,31:1
       fiel (gefordert sind 4,5:1, gemessen von qa/wetter-kontrast.mjs). Wer die
       Animation heller macht, zieht diesen Schirm mit; die Alternative wäre,
       die Stimmung zurückzubauen, um eine Zeile lesbar zu halten. */
    background: linear-gradient(180deg,
      rgba(6, 11, 30, .44) 0%,
      rgba(6, 11, 30, .40) 34%,
      rgba(6, 11, 30, .56) 72%,
      rgba(6, 11, 30, .78) 100%);
    padding-bottom: calc(var(--sp-24) + var(--wx-sab));
  }
  /* 🚨 DER HELD IST SCHLANK UND ZENTRIERT. Er trug früher zusätzlich eine
     Detailzeile und eine Kennzahlenleiste; um deren Überschuss zu verteilen,
     stand hier `space-between` mit den Kennzahlen als unten festgemachtem Fuß.
     Beides ist ausgezogen (gemeldet: „zu voll gestopft"), der Held zeigt nur
     noch Ort, Temperatur, Zustand, Spanne. Ohne Fuß gibt es keinen Überschuss
     zu verteilen: Der Inhalt wird in der 78-svh-Fläche einfach zentriert, mit
     viel freiem Himmel darum — der ruhige, immersive Eindruck einer
     Premium-Wetter-App. */
  /* 🚨 TIGHTE GRUPPE, KEIN AUSGEDEHNTER BLOCK. Mit `flex: 1` dehnte sich der
     Hauptblock über die ganze Fläche und schob den Chip nach oben — zwischen Chip
     und Ort klaffte ein Loch (fotografiert gemeldet: „logischer anordnen"). Als
     `flex: 0 0 auto` bleibt [Chip · Ort · Lage] eine kompakte Einheit, die das
     Blatt als Ganzes zentriert; der freie Himmel liegt darüber UND darunter, statt
     als Loch mittendrin. */
  .wx-held-haupt {
    align-items: center; text-align: center; gap: var(--sp-8);
    flex: 0 0 auto;
  }
  .wx-ort { justify-content: center; }
  .wx-jetzt { flex-direction: column; align-items: center; gap: var(--sp-6); }
  .wx-jetzt-text { align-items: center; flex-basis: auto; }
  .wx-jetzt-spanne { justify-content: center; }
  /* Die Temperatur ist das Bild, nicht eine Zahl unter anderen. */
  .wx-jetzt-temp { font-size: 6.25rem; letter-spacing: -.05em; }
  .wx-jetzt-sym { width: 88px; height: 88px; }
  .wx-jetzt-lage { font-size: var(--fs-24); }
}

/* ⚠️ Sehr flache Telefone (quer, oder ein sehr kleines Gerät): Dort ist eine
   Bildschirmhöhe zu wenig für Ort, Temperatur, Lage UND Kennzahlen. Der Held
   nimmt dann nur so viel, wie er braucht. */
@media (max-width: 699px) and (max-height: 560px) {
  .wx-held { min-height: 0; }
  .wx-jetzt-temp { font-size: var(--fs-64); }
  .wx-jetzt-sym { width: 64px; height: 64px; }
}

/* ── Das Textblatt ────────────────────────────────────────────────────────
   Ein durchgehender Verlauf von durchsichtig nach dunkel. Er ersetzt die vier
   Einzelschirme UND die Glasflächen der Kennzahlen.

   ⚠️ Die Deckung am unteren Ende ist NACHGERECHNET, nicht geschätzt. Der
   hellste je gemessene Untergrund ist ein Gewitterblitz mit rgb(235,235,237).
   Bei 82 % Deckung bleibt davon rgb(47,50,58) — weißer Text steht darauf mit
   14,4:1. Der Verlauf beginnt schon bei 0 % Höhe leicht zu decken, damit auch
   ein Wert am oberen Blattrand nie unter 4,5:1 fällt. */
.wx-held-blatt {
  padding: var(--sp-20) var(--sp-20) var(--sp-20);
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--sp-12);
  flex: 1 1 auto; justify-content: center;
  /* Der Verlauf trägt den Textkontrast (transparent oben für den freien Himmel,
     dunkel unten). Die Auflösung in die Seitenfarbe macht NICHT dieser Verlauf —
     sie liegt als eigene Ebene `.wx-held::after` UNTER dem Text, damit der dunkle
     Grund unter Temperatur und Spanne erhalten bleibt (sonst fiel weißer Text im
     Hellmodus unter 4,5:1, von qa/wetter-kontrast.mjs gemeldet). */
  background: linear-gradient(180deg,
    rgba(6, 11, 30, 0) 0%,
    rgba(6, 11, 30, .55) 26%,
    rgba(6, 11, 30, .78) 58%,
    rgba(6, 11, 30, .86) 100%);
}
/* 🌅 DIE AUFLÖSUNG IN DIE SEITE — eine eigene Ebene, kein Teil des Text-Verlaufs.
   Ein weicher Streifen am unteren Rand des Helden blendet von durchsichtig auf
   die Seitenfarbe `var(--bg)` über; der Himmel geht damit nahtlos in die Seite
   über, in HELL wie in DUNKEL (`--bg` ist das Theme-Token der Seitenfläche).
   ⚠️ Er liegt ÜBER dem Himmel, aber der Inhalt steht darüber (`--z-inhalt` ist
      die Textebene; dieser Streifen bekommt eine Stufe darunter über die
      Stapelreihenfolge NICHT — deshalb sitzt der Text bewusst oberhalb des
      Streifens: auf dem Handy zentriert mit viel Rand, am Desktop oben
      ausgerichtet). Der Streifen ist `pointer-events: none`. */
.wx-held::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 38%; z-index: var(--z-inhalt); pointer-events: none;
  background: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 34%,
    var(--bg) 100%);
}
@media (min-width: 700px) {
  /* Der Desktop-Held ist flach; zentrierter Inhalt liefe in den Auflöse-Streifen.
     Deshalb steht der Inhalt hier OBEN (unter dem Kopfabstand), der freie Himmel
     samt Auflösung liegt darunter — so bleibt jeder Text auf dunklem Grund. */
  .wx-held-blatt { justify-content: flex-start; }
}
@media (min-width: 1000px) {
  .wx-held-blatt { padding: var(--sp-32) var(--sp-32) var(--sp-32); gap: var(--sp-16); }
}

/* ⚠️ HANDY QUER = KURZER VIEWPORT. Ein iPhone quer ist z. B. 844×390 oder
   932×430: sehr breit, aber nur ~390–430 px HOCH. Ohne diese Regel zwingt
   `min-height: 460px` (bzw. `78svh` im Handy-Zweig) den Helden höher als der
   ganze Bildschirm — man scrollt eine halbe Seite, nur um die Temperatur zu
   sehen (gemeldet: „Landscape absolut nicht gut", fotografiert). Bei kurzem
   Viewport sitzt der Held daher knapp am Inhalt: der freie Himmel oben
   schrumpft, die Kennzahlen stehen als kompakte REIHE (sym · Temperatur · Lage
   nebeneinander statt gestapelt), die Riesenzahl wird kleiner — so passen Held
   UND der angeschnittene erste Kartenrand in EINE Bildschirmhöhe.

   Gilt an JEDER Breite (auch SE quer bei 667 px, das sonst im Handy-Hochkant-
   Zweig mit gestapelter Spalte hängenbliebe). Portrait bleibt unberührt: dort
   ist der Viewport hoch (> 520 px), die Regel greift nicht. Steht NACH allen
   anderen Held-Regeln, damit die Quelle-Reihenfolge hier gewinnt. */
@media (max-height: 520px) {
  /* 🌌 RANDLOS WIE HOCHKANT — kein Kärtchen, keine Abgrenzung. Quer fiel der Held
     sonst in den Desktop-Zweig und wurde ein gerundetes Kärtchen mit sichtbarem
     Rand (gemeldet: „in landscape sieht man eine deutliche Abgrenzung"). Er läuft
     jetzt randlos bis in alle Ecken und unter den schwebenden Kopf — genau wie im
     Hochformat (der Kopf schwebt dort per OR-Bedingung, siehe wetter.css). */
  .wx-held {
    min-height: 0;
    margin-top: calc(-1 * (var(--kopf-h) + var(--wx-sat)));
    margin-left: calc(-1 * var(--wx-rand-l));
    margin-right: calc(-1 * var(--wx-rand-r));
    border-radius: 0;
    box-shadow: none;
  }
  /* Der Platzhalter hält den schwebenden Kopf frei (Held läuft darunter). */
  .wx-held-in::before { height: calc(var(--kopf-h) + var(--wx-sat)); }
  .wx-held-blatt { justify-content: flex-start; padding: var(--sp-16) var(--sp-20); gap: var(--sp-8); }
  .wx-held-haupt { gap: var(--sp-6); }
  /* Kennzahlen als kompakte REIHE statt gestapelt: sym · Temperatur · (Lage +
     Spanne) nebeneinander. `flex-basis: auto` hebt den erzwungenen Umbruch des
     Handy-Hochkant-Zweigs auf, sonst fiele der Text in eine eigene Zeile. */
  .wx-jetzt { flex-direction: row; align-items: center; gap: var(--sp-12); flex-wrap: nowrap; }
  .wx-jetzt-text { align-items: flex-start; flex-basis: auto; }
  .wx-jetzt-spanne { justify-content: flex-start; }
  .wx-jetzt-temp { font-size: var(--fs-44); }
  .wx-jetzt-sym { width: 56px; height: 56px; }
}

/* 🌤️ HIMMEL-SEITE: Der Held ist kein Kärtchen mehr, sondern der obere,
   lebendige Teil EINES durchgehenden Himmels (der Rest kommt aus body::before).
   Deshalb fällt hier das Kartengehabe weg — kein Schlagschatten, keine harte
   Auflöse-Kante gegen eine Seitenfarbe. Der untere Rand des Helden blendet
   stattdessen in den Himmelston der Seite (`--himmel-3`), sodass die animierte
   Leinwand oben nahtlos in den festen Himmel darunter übergeht. Der dunkle
   Textverlauf des Blatts bleibt (Kontrast für Ort und Temperatur). */
html.wx-himmel-seite .wx-held { box-shadow: none; }
/* 🚨 DER HELD BLENDET AUF DEN LEBENDIGEN HIMMELSTON DER SEITE (`--himmel-3`),
   in einen SOLIDEN Streifen am unteren Rand.
   Mehrfach fotografiert gemeldet: „Der Farbverlauf endet hart." GEMESSEN war der
   Held-Boden #09132e (dunkel, vom Text-Blatt), die Seite direkt darunter aber
   ~#12376c. Der Grund: `body::before` ist im Himmel-Modus KEIN statisches
   Dunkelblau, sondern der lebendige Himmel aus `--himmel-1/2/3` (tagsüber
   mittelblau, von app.js gesetzt). Ein Streifen, der auf ein festes `--bg`/dunkel
   blendet, trifft diesen hellen Himmel an der Kante — genau die Stufe. Er blendet
   deshalb auf `--himmel-3`, also DENSELBEN Ton, den die Seite unten trägt.
   ⚠️ VOLL `--himmel-3` schon vor der Unterkante (ab 88 %), damit die letzten
      Pixel sicher die Seitenfarbe tragen; der Verlauf beginnt hoch (30 %), damit
      der dunkle Text-Grund weich in den Himmel übergeht statt hart abzubrechen. */
html.wx-himmel-seite .wx-held::after {
  background: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 30%,
    var(--himmel-3, #0a1430) 88%,
    var(--himmel-3, #0a1430) 100%);
}

/* Der Held ist IMMER dunkel (die Animation braucht einen dunklen Himmel), also
   feste helle Textfarben statt Theme-Token — sonst wäre der Text im Hellmodus
   unsichtbar. Dasselbe Prinzip wie --dark-ink in Kellerkind. */
.wx-held-in, .wx-held-in h1 { color: #ffffff; }
.wx-held-leise { color: rgba(255, 255, 255, .88); }
.wx-held-fein { color: rgba(255, 255, 255, .74); font-size: var(--fs-13); }

/* ══════════════════════════════════════════════════════════════════════════
   DIE MODELLWAHL
   ══════════════════════════════════════════════════════════════════════════ */

/* Der Chip an der Einigkeits-Karte. Er trägt den NAMEN, nicht nur ein Zahnrad:
   Dass gerade ein einzelnes Modell statt aller rechnet, ist genau die
   Information, die man an dieser Stelle braucht. */

.wx-einig-modell {
  display: inline-flex; align-items: center; gap: var(--sp-6);
  min-height: var(--ziel); padding: var(--sp-6) var(--sp-12);
  border-radius: var(--r-pill);
  background: var(--soft); color: var(--body);
  font-size: var(--fs-13); font-weight: 600;
  box-shadow: var(--sh-saum);
  transition: background-color var(--mo-kurz) var(--ease-standard);
}
@media (hover: hover) and (pointer: fine) {
  .wx-einig-modell:hover { background: var(--line); color: var(--ink); }
}
.wx-einig-modell svg { width: 15px; height: 15px; flex: 0 0 auto; opacity: .75; }
.wx-einig-modell span { max-width: 16ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Der Zustand „ein einzelnes Modell": keine Zahl, kein Balken, dafür der Grund.
   ⚠️ Die Karte VERSCHWINDET NICHT. Ohne sie hielte man den Verlust für einen
      Fehler — und sie ist der einzige Ort, an dem die Wahl zurückgenommen
      werden kann. */
.wx-einig.ist-einzeln .wx-einig-stufe { background: var(--soft); color: var(--muted); }

/* ── Der Dialog ───────────────────────────────────────────────────────────
   🚨 KEIN `flex: 1` AUF EINEM KIND. Safaris eigene Regel für <dialog> ist
      `height: fit-content`; ein Flex-Kind mit `flex: 1` hat dann die Basis 0,
      und der Dialog klappt auf Kopfzeilenhöhe zusammen — auf der
      KelRaid-Landingpage gemessen 115 statt 752 px, während Chromium tadellos
      aussah. Deshalb: normaler Blockfluss, `max-height` am Dialog,
      `overflow-y` am Rumpf. */
.wx-mo-dlg {
  width: min(660px, calc(100vw - 2 * var(--sp-16)));
  max-height: min(86svh, 900px);
  /* ⚠️ `margin: auto` MUSS DASTEHEN. Ein <dialog> wird von der Browser-Regel
     zentriert, und die lautet `margin: auto` — wer eine eigene `margin`- oder
     `inset`-Angabe macht (oder wie hier über `padding: 0; border: 0` einen
     eigenen Block anfängt), verliert sie je nach Engine und der Dialog klebt
     oben links in der Ecke. Genau so stand er im ersten Bild. */
  margin: auto;
  padding: 0; border: 0;
  border-radius: var(--r-18);
  background: var(--overlay); color: var(--body);   /* deckend, nicht durchscheinend */
  box-shadow: var(--sh-4);
  overflow: hidden;
}
.wx-mo-dlg::backdrop { background: rgba(6, 12, 28, .58); backdrop-filter: blur(3px); }
/* Sanft herein — und für alle, die keine Bewegung wollen, gar nicht. */
.wx-mo-dlg[open] { animation: wx-mo-auf var(--mo-mittel) var(--ease-rein); }
@keyframes wx-mo-auf { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .wx-mo-dlg[open] { animation: none; } }

.wx-mo-dlg-kopf {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12);
  padding: var(--sp-16) var(--sp-20);
  border-bottom: 1px solid var(--line);
  /* Der Kopf bleibt stehen, während der Rumpf rollt — bei vierzehn Karten
     verliert man sonst, worum es hier überhaupt geht. */
  position: sticky; top: 0; z-index: var(--z-sticky); background: var(--flaeche);
}
.wx-mo-dlg-kopf h2 { font-size: var(--fs-18); font-weight: 700; color: var(--ink); margin: 0; }
.wx-mo-zu {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--ziel); min-height: var(--ziel);
  border-radius: var(--r-pill); background: var(--soft); color: var(--body);
  font-size: var(--fs-20); line-height: 1;
}
@media (hover: hover) and (pointer: fine) {
  .wx-mo-zu:hover { background: var(--line); color: var(--ink); }
}

.wx-mo-dlg-rumpf { padding: var(--sp-16) var(--sp-20) var(--sp-24); overflow-y: auto; max-height: 76svh; }
.wx-mo-intro { font-size: var(--fs-14); color: var(--muted); line-height: 1.55; margin: 0 0 var(--sp-16); }
.wx-mo-intro b { color: var(--ink); }
.wx-mo-laedt { font-size: var(--fs-14); color: var(--muted); padding: var(--sp-24) 0; text-align: center; }

/* ── Eine Modellkarte ──────────────────────────────────────────────────── */
.wx-mo {
  border: 1px solid var(--line); border-radius: var(--r-14);
  padding: var(--sp-12) var(--sp-16);
  margin-bottom: var(--sp-12);
  background: var(--flaeche);
}
/* Das aktive Modell ist HERVORGEHOBEN, nicht nur beschriftet: Wer den Dialog
   öffnet, will als Erstes wissen, was gerade gilt. */
.wx-mo.ist-aktiv { border-color: var(--acc); box-shadow: inset 3px 0 0 var(--acc); }
.wx-mo.ist-ensemble { background: var(--soft); }

.wx-mo-kopf { display: flex; flex-direction: column; gap: 2px; margin-bottom: var(--sp-8); }
.wx-mo-titel { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-8); }
.wx-mo-titel b { font-size: var(--fs-16); font-weight: 700; color: var(--ink); }
.wx-mo-betreiber { font-size: var(--fs-12); color: var(--muted); }
.wx-mo-marke {
  padding: 1px var(--sp-8); border-radius: var(--r-pill);
  font-size: var(--fs-12); font-weight: 700;
}
.wx-mo-marke.ist-tipp  { background: color-mix(in srgb, var(--gut) 14%, transparent); color: var(--gut); }
.wx-mo-marke.ist-aktiv { background: var(--acc); color: var(--acc-ink); }
/* ⚠️ Ein Modell ohne Daten wird MARKIERT, nicht gesperrt. Gesperrt könnte man
   es nie wieder in eine gespeicherte Auswahl aufnehmen, sobald es einmal
   ausgefallen ist — und die Auswahl liegt dauerhaft im Browser. Wer es trotzdem
   ankreuzt, bekommt vom Server die ehrliche Auskunft über die dünne Basis. */
.wx-mo-marke.ist-weg { background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn); }
.wx-mo-kurz { font-size: var(--fs-14); color: var(--body); line-height: 1.55; margin: 0 0 var(--sp-10); }

.wx-mo-tipps { display: flex; flex-wrap: wrap; gap: var(--sp-6); margin-bottom: var(--sp-10); }
.wx-mo-tipp {
  padding: 2px var(--sp-8); border-radius: var(--r-pill);
  font-size: var(--fs-12); font-weight: 600;
  background: var(--soft); color: var(--body);
}
/* ⚠️ Die Farbe trägt hier KEINE Information allein — der Text sagt dasselbe.
   Eine Warnung, die sich nur durch Rot von einer Empfehlung unterscheidet,
   wäre für rund jeden zwölften Mann nicht unterscheidbar. */
.wx-mo-tipp.ist-ort     { background: color-mix(in srgb, var(--acc) 14%, transparent); color: var(--acc); }
.wx-mo-tipp.ist-guete   { background: color-mix(in srgb, var(--gut) 14%, transparent); color: var(--gut); }
.wx-mo-tipp.ist-warnung { background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn); }

.wx-mo-mehr { margin-bottom: var(--sp-12); }
.wx-mo-mehr summary {
  cursor: pointer; font-size: var(--fs-13); font-weight: 600; color: var(--acc);
  min-height: var(--ziel); display: flex; align-items: center;
}
.wx-mo-mehr-in { padding-top: var(--sp-8); }
.wx-mo-dl { margin: 0 0 var(--sp-12); display: grid; gap: 2px; }
.wx-mo-z { display: grid; grid-template-columns: 1fr; gap: 0; padding: var(--sp-6) 0; border-bottom: 1px solid var(--line); }
@media (min-width: 520px) { .wx-mo-z { grid-template-columns: 13em 1fr; gap: var(--sp-12); align-items: baseline; } }
.wx-mo-z dt { font-size: var(--fs-12); color: var(--muted); font-weight: 600; }
.wx-mo-z dd { margin: 0; font-size: var(--fs-13); color: var(--ink); }
.wx-mo-h4 { font-size: var(--fs-13); font-weight: 700; color: var(--ink); margin: var(--sp-12) 0 var(--sp-6); }
.wx-mo-liste { margin: 0; padding-left: 1.15em; display: grid; gap: 3px; }
.wx-mo-liste li { font-size: var(--fs-13); color: var(--body); line-height: 1.5; }
.wx-mo-liste.ist-plus  li::marker { content: "+ "; color: var(--gut); font-weight: 700; }
.wx-mo-liste.ist-minus li::marker { content: "− "; color: var(--warn); font-weight: 700; }
.wx-mo-liste.ist-fuer  li::marker { content: "› "; color: var(--acc); font-weight: 700; }
.wx-mo-link { margin: var(--sp-12) 0 0; font-size: var(--fs-13); }
.wx-mo-link a { color: var(--acc); }

/* ── Die Wahl: Kästchen statt Knöpfe ──────────────────────────────────────
   Aus „dieses Modell verwenden" ist „mitrechnen lassen" geworden — die Wahl ist
   keine Entscheidung FÜR eines mehr, sondern eine Zusammenstellung.
   ⚠️ Die ganze Zeile ist das Fingerziel, nicht nur der Haken: Ein 20-px-Kästchen
      trifft auf dem Handy niemand zuverlässig. Das `<label>` umschliesst beides,
      also schaltet auch ein Tippen auf den Text. */
.wx-mo-wahl {
  display: flex; align-items: center; gap: var(--sp-10);
  min-height: var(--ziel); padding: var(--sp-8) var(--sp-12);
  border-radius: var(--r-10); background: var(--soft);
  font-size: var(--fs-14); font-weight: 600; color: var(--body);
  cursor: pointer;
}
.wx-mo-wahl input { width: 20px; height: 20px; flex: 0 0 auto; accent-color: var(--acc); }
@media (hover: hover) and (pointer: fine) {
  .wx-mo-wahl:hover { filter: brightness(.97); }
  .wx-mo-ok:hover { filter: brightness(1.08); }
}

/* Der Schalter über der Liste. Er steht bewusst NICHT zwischen den Karten:
   „Alle Modelle" ist kein weiteres Modell, sondern eine Aussage über die
   darunter. */
.wx-mo-alle {
  display: flex; align-items: center; gap: var(--sp-10);
  min-height: var(--ziel); margin-bottom: var(--sp-16);
  padding: var(--sp-10) var(--sp-12);
  border-radius: var(--r-10); border: 1px solid var(--line);
  font-size: var(--fs-15); font-weight: 700; color: var(--ink);
  cursor: pointer;
}
.wx-mo-alle input { width: 20px; height: 20px; flex: 0 0 auto; accent-color: var(--acc); }

/* ⚠️ KLEBT UNTEN IM RUMPF, IST ABER KEIN DIALOG-FUSS. Ein Flex-Layout mit
   `flex: 1` am Rumpf klappt in WebKit auf Kopfzeilenhöhe zusammen (Begründung
   im Kopf von js/ui-modelle.js). `position: sticky` im normalen Blockfluss
   nicht. Die negativen Ränder heben das Polster des Rumpfes auf, damit die
   Leiste wirklich bis an die Kanten läuft. */
.wx-mo-leiste {
  position: sticky; bottom: calc(var(--sp-24) * -1);
  display: flex; align-items: center; gap: var(--sp-12);
  margin: var(--sp-16) calc(var(--sp-20) * -1) calc(var(--sp-24) * -1);
  padding: var(--sp-12) var(--sp-20);
  background: var(--flaeche); border-top: 1px solid var(--line);
}
.wx-mo-zahl { flex: 1 1 auto; min-width: 0; font-size: var(--fs-14); color: var(--muted); }
.wx-mo-ok {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--ziel); padding: var(--sp-8) var(--sp-24);
  border-radius: var(--r-pill);
  background: var(--acc); color: var(--acc-ink);
  font-size: var(--fs-15); font-weight: 700;
  transition: filter var(--mo-kurz) var(--ease-standard);
}
.wx-mo-ok:disabled { background: var(--soft); color: var(--muted); cursor: default; }

/* ── Erster Besuch ────────────────────────────────────────────────────────
   Das erste Bild für jemanden, der die Seite nicht kennt — und damit die
   wichtigste Fläche, die es gibt. Sie benutzt dasselbe Heldenblatt wie die
   Vorhersage: freier Himmel oben, Text unten. */
.wx-willkommen-in { display: flex; flex-direction: column; gap: var(--sp-16); }
.wx-willkommen-in h1 {
  font-size: var(--fs-28); font-weight: 700; letter-spacing: -.02em; max-width: 20ch;
}
@media (min-width: 1000px) { .wx-willkommen-in h1 { font-size: var(--fs-34); } }
.wx-willkommen-in p { max-width: 60ch; line-height: 1.6; }

/* Der eine Knopf, der hier zählt. Hell auf dem blauen Himmel — ein Umriss-Knopf
   wäre auf einer Fläche, die von Klar bis Gewitter alles sein kann, mal gut und
   mal gar nicht zu sehen. */
.wx-cta {
  align-self: flex-start;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-8);
  min-height: var(--ziel); padding: var(--sp-10) var(--sp-24);
  border-radius: var(--r-pill);
  background: #ffffff; color: #0d1a3c;
  font-size: var(--fs-15); font-weight: 700;
  box-shadow: var(--sh-2);
  transition: transform var(--mo-kurz) var(--ease-standard),
              box-shadow var(--mo-kurz) var(--ease-standard);
}
.wx-cta svg { width: 18px; height: 18px; flex: 0 0 auto; }
@media (hover: hover) and (pointer: fine) {
  .wx-cta:hover { box-shadow: var(--sh-3); }
}
.wx-cta:active { transform: scale(.97); }
/* ⚠️ Links im Helden brauchen EIGENE Farben. `var(--acc)` ist auf die helle
   bzw. dunkle Seitenfläche abgestimmt — auf dem blauen Himmel wäre Blau auf
   Blau, im Hellmodus sogar unlesbar. Weiß mit Unterstreichung trägt hier. */
.wx-held-in a { color: #ffffff; text-decoration: underline; text-underline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .wx-held-in a:hover { text-decoration-thickness: 2px; }
}

/* ── Ort ──────────────────────────────────────────────────────────────────*/
.wx-ort { display: flex; align-items: baseline; gap: var(--sp-6) var(--sp-10); flex-wrap: wrap; }
.wx-ort h1 {
  font-size: var(--fs-28); font-weight: 700; letter-spacing: -.02em;
  /* Ein sehr langer Ortsname („Sant Julià de Lòria") darf die Zeile umbrechen,
     aber nie über die Karte hinauslaufen. */
  min-width: 0; overflow-wrap: anywhere;
}
/* ⚠️ Die Region steht IMMER in einer eigenen Zeile, auf jeder Breite. Das ist
   nicht nur Hierarchie (Name groß, Region darunter), sondern Voraussetzung für
   ein sprungfreies erstes Bild: Nebeneinander entschied die Summe der
   Wortlängen über den Umbruch — „Regensburg, Bayern, Deutschland" brach um,
   der gleich lange Platzhalter des Ladeskeletts nicht, und beim Eintreffen der
   Daten wuchs die Karte um eine Zeile. Dieselbe Lehre wie beim Textblock der
   Temperatur direkt darunter. */
/* ⚠️ .94 STATT .86 — die Zeile lag bei der Dämmerung auf WebKit bei 4,48:1
   gegen geforderte 4,5:1 (Chromium kam auf 4,52, dieselbe Seite). Ein Zustand,
   der auf einer Engine knapp besteht und auf der anderen knapp durchfällt, ist
   keiner. Die Hierarchie zwischen Ortsname und Region trägt ohnehin die GRÖSSE
   (fs-28 gegen fs-14) und das Gewicht — sechs Prozent Transparenz sind daran
   nicht zu sehen, am Kontrast schon. */
.wx-ort .wx-ort-sub {
  flex-basis: 100%;
  font-size: var(--fs-14); color: rgba(255, 255, 255, .94);
  min-width: 0; overflow-wrap: anywhere;
}
.wx-ort-badge {
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto;
  padding: 2px var(--sp-8); border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .18); font-size: var(--fs-12); font-weight: 600;
  color: #ffffff;
}
.wx-ort-badge svg { width: 12px; height: 12px; }

/* ── Der Hauptblock: Symbol, Temperatur, Zustand ──────────────────────────
   Auf JEDER Größe eine mittig zentrierte Gruppe [Chip · Ort · Lage]. Früher lag
   auf breiten Schirmen der Ort links und die Lage rechts (space-between), mit dem
   Chip mittig darüber schwebend — genau die unlogische Anordnung, die gemeldet
   wurde. Eine zentrierte Komposition liest sich als EIN Bild, mobil wie am
   Desktop; der Himmel liegt ruhig darum. */
.wx-held-haupt {
  display: flex; flex-direction: column; gap: var(--sp-12);
  align-items: center; text-align: center;
}

.wx-jetzt { display: flex; align-items: center; gap: var(--sp-16); flex-wrap: wrap; }
.wx-jetzt-sym {
  width: 72px; height: 72px; flex: 0 0 auto;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .35));
}
@media (min-width: 1000px) { .wx-jetzt-sym { width: 88px; height: 88px; } }

/* ⚠️ `inline-flex` mit `align-items: flex-start` statt `vertical-align: super`:
   Die Einheit soll an der OBERKANTE der Ziffern stehen. Als `<sup>` hing sie
   an der Schriftlinie und stand dadurch je nach Zahl („8" gegen „35") auf
   unterschiedlicher Höhe. */
.wx-jetzt-temp {
  display: inline-flex; align-items: flex-start; flex: 0 0 auto;
  font-size: var(--fs-64); font-weight: 250; line-height: .88; letter-spacing: -.045em;
  color: #ffffff;
  font-variant-numeric: lining-nums tabular-nums;
}
.wx-jetzt-temp sup {
  font-size: .30em; font-weight: 500; letter-spacing: 0; line-height: 1.35;
  margin-left: .06em; opacity: .92; vertical-align: baseline; top: 0;
}

/* ⚠️ Auf dem Handy bricht der Textblock IMMER in die zweite Zeile — erzwungen
   über `flex-basis: 100%`, nicht dem Zufall überlassen. Vorher entschied die
   Summe der Inhaltsbreiten, ob umbrochen wurde: „34°" passte noch daneben,
   „-12°" nicht mehr. Damit änderte sich die Höhe des Helden je nach Wetter, und
   beim Wechsel vom Ladeskelett zum Inhalt rutschte die halbe Seite nach. */
.wx-jetzt-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
/* ⚠️ Der erzwungene Umbruch gilt nur HOCHKANT (min-height). Quer (kurzer
   Viewport) steht der Textblock bewusst NEBEN der Temperatur — die kompakte
   Reihe der Landscape-Regel oben braucht das, sonst fiele „Klar" in eine eigene
   Zeile. Die CLS-Stabilität, für die dieser Umbruch da ist, betrifft ohnehin nur
   das hohe Format (dort misst qa/wetter-fein.mjs). */
@media (max-width: 699px) and (min-height: 521px) { .wx-jetzt-text { flex-basis: 100%; } }
.wx-jetzt-lage {
  font-size: var(--fs-20); font-weight: 600; color: #ffffff;
  min-width: 0; overflow-wrap: anywhere;
}
/* Höchst- und Tiefstwert als Paar mit Pfeilen — kompakter als „Heute 35° / 25°"
   und auf einen Blick als Spanne lesbar. */
.wx-jetzt-spanne {
  display: flex; align-items: center; gap: var(--sp-12);
  font-size: var(--fs-14); color: rgba(255, 255, 255, .86);
}
.wx-hl { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.wx-hl i { font-style: normal; opacity: .7; font-size: .92em; }

/* ── Die Werte-Karte ──────────────────────────────────────────────────────
   Die acht Nebengrößen des Helden, aus ihm ausgezogen (er wirkte „zu voll
   gestopft und unsauber"). EINE ruhige Karte in der NORMALEN Seitenpalette —
   theme-aware, nicht die festen hellen Held-Farben: Felder in `--flaeche`,
   Haarlinien über `--line`, Beschriftung in `--muted`, Wert in `--ink`.

   🚨 DIE SPALTENZAHL MUSS DIE ACHT FELDER TEILEN — 2 auf dem Handy, 4 auf dem
      Desktop (beide teilen 8). Eine Spaltenzahl, die nicht teilt, ließe
      Rasterplätze leer und den grauen Rastergrund (`--line`) durchscheinen —
      genau der Fehler, der im Stunden-Panel gemeldet wurde.
   ⚠️ IMMER acht Felder (fehlender Wert = „–"), sonst schwankt die Kartenhöhe
      und alles darunter springt beim Eintreffen der Daten. */
.wx-werte-halter { margin-top: var(--sp-16); }
.wx-werte-halter[hidden] { display: none; }
/* Die Überschrift „Heute im Detail" trägt den Abschnittsabstand nach oben (wie
   `.wx-abschnitt`); die Kartenfläche schließt direkt darunter an. Die id-Regel
   sticht die Klassen-Regel oben — das Poster (ohne id) behält seinen Abstand. */
.wx-werte-kopf { margin-top: var(--sp-32); }
#wx-werte { margin-top: 0; }

/* ── Detailkarten im iOS-Wetter-Look ───────────────────────────────────────
   Zwei halbe Karten je Reihe, Wind und Mond über die volle Breite. Jede Karte:
   Kopf (Symbol + Label), große Zahl, erklärender Satz oder Wertzeilen, dazu wo
   es hilft eine Grafik (Kompass, Sonnenbogen, Mondscheibe). Gebaut gegen die
   Screenshots der Apple-Wetter-App.
   ⚠️ FESTE MINDESTHÖHEN je Reihe — das Skelett in index.php spiegelt sie, sonst
      springt beim Eintreffen der Daten alles darunter. */
.wx-werte {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-8);
}
/* Ab Tablet-Breite breiten sich die Detailkarten als echtes Kachelraster über die
   volle Breite aus (statt in zwei schmalen Spalten mit viel Leere rechts). Die
   Grafik-/Vollkarten (Wind, Luft, Pollen, Mond, Klima) bekommen zwei Kacheln
   Breite, damit Kompass, Skala und Mondscheibe Platz haben; `dense` füllt die
   Lücken, die die unterschiedlichen Breiten sonst ließen. Auf dem Handy bleibt
   es beim 2-Spalten-Stapel (Reihenfolge = Wichtigkeit). */
@media (min-width: 700px) {
  .wx-werte {
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    grid-auto-flow: row dense;
  }
  .wx-werte .wx-dk--voll { grid-column: span 2; }
}
/* ⚠️ Mindesthöhe fasst den LÄNGSTEN Satz (drei Zeilen, z. B. „Entspricht
   ungefähr der tatsächlichen Temperatur."). Skelett UND Inhalt teilen sich diese
   Regel — solange der Inhalt hineinpasst, sind beide gleich hoch und es springt
   nichts (qa/wetter-fein.mjs misst genau das). */
.wx-dk {
  display: flex; flex-direction: column; min-width: 0; min-height: 142px;
  padding: var(--sp-12) var(--sp-12);
  background: var(--flaeche); border-radius: var(--r-18);
  box-shadow: var(--sh-1), var(--sh-saum);
}
.wx-dk--voll { grid-column: 1 / -1; flex-direction: row; align-items: stretch; gap: var(--sp-12); min-height: 128px; }
.wx-dk--sonne { min-height: 150px; }
.wx-dk-haupt { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.wx-dk-kopf {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  font-size: var(--fs-12); font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--muted);
}
.wx-dk-kopf svg { width: 14px; height: 14px; flex: 0 0 auto; opacity: .9; }
.wx-dk-kopf span:not(.wx-sr) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wx-dk-wert {
  margin-top: 7px;
  font-size: var(--fs-28); font-weight: 600; color: var(--ink); line-height: 1.08;
  font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Längere Werte („14 Std 51 Min", „976 hPa ↓") passen bei --fs-28 nicht in eine
   halbe Karte und würden abgeschnitten. Kleiner gesetzt stehen sie vollständig;
   die Karten-Mindesthöhe (142px) trägt weiter, es springt nichts. */
.wx-dk-wert--kompakt { font-size: var(--fs-20); }
/* Der Luftdruck-Trendpfeil neben dem Wert. Bewusst NEUTRAL (kein Rot/Grün):
   fallender Druck ist kein „schlecht" — Farbe wäre eine Deutung, und die
   gehört hier so wenig hin wie ein Ratschlag. */
.wx-dk-trend {
  font-size: var(--fs-20); font-weight: 600; color: var(--muted);
  margin-left: 2px; vertical-align: baseline;
}
.wx-dk-satz {
  margin-top: auto; padding-top: 8px;
  font-size: var(--fs-13); color: var(--body); line-height: 1.35;
}
.wx-dk-zeilen { margin-top: 10px; display: flex; flex-direction: column; gap: 5px; }
.wx-dk-zeilen > div {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-8);
  font-size: var(--fs-14); border-top: 1px solid var(--line); padding-top: 5px;
}
.wx-dk-zeilen > div:first-child { border-top: 0; padding-top: 0; }
.wx-dk-zeilen span { color: var(--body); }
.wx-dk-zeilen b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Grafik-Fläche rechts (Kompass, Mond): feste Quadratgröße → runder Kreis, kein
   Layout-Sprung. */
.wx-dk-bild { flex: 0 0 auto; align-self: center; width: 80px; height: 80px; }
.wx-dk-bild svg { display: block; width: 100%; height: 100%; }
.wx-dk--mond .wx-dk-haupt { justify-content: center; }

/* ── Luftqualität (voll, mit AQI-Skala) ───────────────────────────────────────
   ⚠️ `.wx-dk--voll` ist Zeilen-Flex (Haupt | Bild); die Luft-Karte fließt aber
      SPALTIG (Kopf · Wert · Skala · Satz), deshalb hier zurück auf column. */
.wx-dk--luft { flex-direction: column; }
.wx-luft-stufe {
  margin-left: var(--sp-8); font-size: var(--fs-20); font-weight: 700; color: var(--body);
}
/* Ein kleiner Farbpunkt trägt die Stufe zusätzlich zur Farbe — der Text bleibt
   in der Vordergrundfarbe (Kontrast), die Farbe ist nur ein Zusatzsignal. */
.wx-luft-stufe::before {
  content: ""; display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  margin-right: 5px; vertical-align: baseline; background: var(--muted);
}
.wx-luft-stufe.stufe-sehrgut::before     { background: #2fae55; }
.wx-luft-stufe.stufe-gut::before         { background: #8cc63f; }
.wx-luft-stufe.stufe-maessig::before     { background: #f2c53d; }
.wx-luft-stufe.stufe-schlecht::before    { background: #ef8a3c; }
.wx-luft-stufe.stufe-sehrschlecht::before{ background: #e35141; }
.wx-luft-stufe.stufe-extrem::before      { background: #a24ac0; }
/* Die Skala: die sechs AQI-Bänder als Verlauf, rein dekorativ (aria-hidden).
   Der Zeiger sitzt bei `anteil` und ist auf JEDEM Band sichtbar (weiß mit
   dunklem Ring). */
.wx-luft-skala {
  position: relative; height: 8px; border-radius: 999px; margin-top: var(--sp-12);
  background: linear-gradient(90deg, #2fae55 0%, #8cc63f 20%, #f2c53d 40%, #ef8a3c 60%, #e35141 80%, #a24ac0 100%);
}
.wx-luft-zeiger {
  position: absolute; top: 50%; width: 14px; height: 14px; border-radius: 50%;
  transform: translate(-50%, -50%); background: #ffffff;
  box-shadow: 0 0 0 2px rgba(6, 11, 30, .55), var(--sh-1);
}

/* ── Klima-Einordnung (voll) ──────────────────────────────────────────────── */
.wx-dk--klima { flex-direction: column; }
/* ⚠️ Die Sätze der vollbreiten Text-Karten (Klima, Pollen) sind mal EINE Zeile
   („Derzeit nicht verfügbar."), mal ZWEI („… Ø 24° Höchstwert (2006–2025). Eine
   Quelle."), je nachdem, ob die Daten (Archiv-Mittel bzw. Pollenwerte) vorliegen.
   Ohne feste Höhe springt die Karte beim Eintreffen der Daten (gemessen: Klima
   8 px, Pollen 16 px, qa/wetter-fein.mjs). Zwei Textzeilen + die 8-px-Polsterung
   fest reserviert (border-box); das Skelett trägt dieselbe Regel → gleich hoch. */
.wx-dk--klima .wx-dk-satz,
.wx-dk--pollen .wx-dk-satz { min-height: calc(2 * 1.35em + 8px); }
/* Der Vorzeichen-Wert ist bewusst NEUTRAL (kein Rot/Grün) — wärmer/kälter als
   das Mittel ist eine Tatsache, keine Wertung (wie der Luftdruck-Trend). */

/* ── Pollenflug (voll) ─────────────────────────────────────────────────────── */
.wx-dk--pollen { flex-direction: column; }
.wx-pollen-stufe {
  margin-left: var(--sp-8); font-size: var(--fs-20); font-weight: 700; color: var(--body);
}
.wx-pollen-stufe::before {
  content: ""; display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  margin-right: 5px; vertical-align: baseline; background: var(--muted);
}
.wx-pollen-stufe.stufe-niedrig::before { background: #8cc63f; }
.wx-pollen-stufe.stufe-mittel::before  { background: #ef8a3c; }
.wx-pollen-stufe.stufe-hoch::before    { background: #e35141; }

/* Sonnenbogen: volle Breite der Karte. Feste `aspect-ratio` statt fester Höhe —
   so ist das Box-Verhältnis exakt das des viewBox (100:30), die SVG skaliert
   GLEICHMÄSSIG und die Sonne bleibt rund. Das leere Skelett trägt über
   aspect-ratio dieselbe Höhe wie der Inhalt (kein Sprung). */
.wx-dk-bogen { margin-top: 10px; width: 100%; aspect-ratio: 100 / 30; }
.wx-dk-bogen svg { display: block; width: 100%; height: 100%; }
.wx-bogen-hor { stroke: var(--line); stroke-width: 1; }
.wx-bogen-bahn { fill: none; stroke: rgba(255, 255, 255, .35); stroke-width: 2; stroke-linecap: round; }
.wx-bogen-sonne { fill: var(--acc-2); }
.wx-bogen-sonne.ist-weg { opacity: .45; }

/* Mondscheibe. */
.wx-mond-dunkel { fill: rgba(255, 255, 255, .12); }
.wx-mond-hell { fill: #eaf1ff; }
.wx-mond-rand { fill: none; stroke: rgba(255, 255, 255, .22); stroke-width: 1.5; }

/* Kompass. */
.wx-komp-tick { stroke: rgba(255, 255, 255, .22); stroke-width: 1; }
.wx-komp-tick.lang { stroke: rgba(255, 255, 255, .4); stroke-width: 1.4; }
.wx-komp-himmel { fill: var(--muted); font-size: 11px; font-weight: 700; text-anchor: middle; }
.wx-komp-wert { fill: var(--ink); font-size: 24px; font-weight: 600; text-anchor: middle; }
.wx-komp-einheit { fill: var(--muted); font-size: 9px; text-anchor: middle; }
.wx-komp-n { fill: var(--acc-2); }
.wx-komp-s { fill: rgba(255, 255, 255, .55); }

/* ── Die Vorhersage in Worten ──────────────────────────────────────────────
   Eine Karte, die nur Text trägt — und deshalb wie ein Absatz aussehen darf und
   nicht wie ein Datenfeld. Größere Schrift, mehr Zeilenhöhe, eine Zeilenlänge,
   die man liest statt überfliegt.

   ⚠️ `max-width` in `ch`: Ab rund 70 Zeichen je Zeile verliert das Auge beim
   Rücksprung die Zeile. Auf einem 3440-px-Schirm liefe der Satz sonst über
   1400 px — technisch tadellos und praktisch unlesbar. */
/* ── Amtliche Unwetterwarnungen (DWD) ──────────────────────────────────────
   Ganz oben, farbig nach Stärke (1..4: gelb · orange · rot · violett). Eine
   Warnung mit Beschreibung ist ein Knopf, der den Text aufklappt. */
.wx-warnungen { margin-top: var(--sp-16); display: flex; flex-direction: column; gap: var(--sp-8); }
.wx-warnungen[hidden] { display: none; }
.wx-warn {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: var(--sp-10); width: 100%; text-align: left;
  padding: var(--sp-12) var(--sp-16);
  border-radius: var(--r-14);
  border-left: 4px solid var(--warn);
  background: color-mix(in srgb, var(--warn) 15%, var(--flaeche));
  color: var(--ink); box-shadow: var(--sh-1), var(--sh-saum);
}
.wx-warn[data-fest] { cursor: default; }
.wx-warn-ikon { display: inline-flex; }
.wx-warn-ikon svg { width: 22px; height: 22px; color: var(--warn); }
.wx-warn-kopf { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.wx-warn-kopf b { font-size: var(--fs-15); font-weight: 700; color: var(--ink); line-height: 1.25; }
.wx-warn-zeit { font-size: var(--fs-12); color: var(--body); }
.wx-warn-pfeil { color: var(--body); display: grid; place-items: center; }
.wx-warn-pfeil svg { width: 18px; height: 18px; transition: transform var(--mo-mittel) var(--ease-standard); }
.wx-warn[aria-expanded="true"] .wx-warn-pfeil svg { transform: rotate(180deg); }
.wx-warn-text {
  grid-column: 1 / -1; display: none;
  font-size: var(--fs-13); line-height: 1.5; color: var(--body); padding-top: var(--sp-8);
}
.wx-warn[aria-expanded="true"] .wx-warn-text { display: block; }
.wx-warn.stufe-3 { border-left-color: var(--schlecht); background: color-mix(in srgb, var(--schlecht) 15%, var(--flaeche)); }
.wx-warn.stufe-3 .wx-warn-ikon svg { color: var(--schlecht); }
.wx-warn.stufe-4 { border-left-color: var(--warn-extrem); background: color-mix(in srgb, var(--warn-extrem) 17%, var(--flaeche)); }
.wx-warn.stufe-4 .wx-warn-ikon svg { color: var(--warn-extrem); }

/* ── Das zuletzt genaueste Modell (gemessene Güte) ─────────────────────────
   Eine dezente Zeile unter der Einigkeits-Karte, die das Alleinstellungsmerkmal
   nach vorn holt und zur Methodenseite führt. Bewusst leise (kein zweiter
   Aufmacher neben dem Helden), aber anklickbar. */
.wx-guete {
  display: flex; align-items: center; gap: var(--sp-8);
  margin-top: var(--sp-12); padding: var(--sp-10) var(--sp-12);
  border-radius: var(--r-14);
  background: var(--flaeche); box-shadow: var(--sh-1), var(--sh-saum);
  color: var(--body); font-size: var(--fs-13); line-height: 1.35;
}
.wx-guete[hidden] { display: none; }
.wx-guete-ik { flex: 0 0 auto; display: grid; place-items: center; }
.wx-guete-ik svg { width: 16px; height: 16px; color: var(--acc-2); }
.wx-guete-txt { flex: 1 1 auto; min-width: 0; }
.wx-guete-txt b { color: var(--ink); font-weight: 600; }
.wx-guete-mehr { flex: 0 0 auto; display: grid; place-items: center; color: var(--muted); }
.wx-guete-mehr svg { width: 16px; height: 16px; transform: rotate(-90deg); }
@media (hover: hover) and (pointer: fine) {
  .wx-guete:hover { background: var(--soft); }
}
.wx-guete:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

.wx-worte-halter { margin-top: var(--sp-16); }
.wx-worte-halter[hidden] { display: none; }
.wx-worte {
  padding: var(--sp-16) var(--sp-20);
  border-radius: var(--r-18);
  background: var(--flaeche);
  box-shadow: var(--sh-1), var(--sh-saum), var(--sh-glanz);
  border-left: 3px solid var(--acc);
}
@media (min-width: 1000px) { .wx-worte { padding: var(--sp-20) var(--sp-24); } }
/* ⚠️ DIE KARTE HAT EINE FESTE ZEILENZAHL — und das ist der Grund, warum sie
   überhaupt so gebaut ist. Der Text ist der einzige Inhalt der Seite, dessen
   LÄNGE mit dem Wetter schwankt: drei Sätze an einem ruhigen Tag, acht bei
   Sturm mit Umschwung und geringer Modell-Einigkeit. Auf dem Handy sind das
   vier bis elf Zeilen. Ein Ladeskelett kann dafür keine passende Höhe haben —
   gemessen sprang die Karte beim Eintreffen der Daten um 41 px, und alles
   darunter mit ihr.

   Also: fest geklemmt auf so viele Zeilen, wie an dieser Breite ein typischer
   Text braucht, plus dieselbe Zahl als `min-height`. Damit ist die Höhe
   KONSTANT — kurzer Text wird nicht kleiner, langer nicht größer.
   ⚠️ Geklemmter Text ist nur dann zulässig, wenn es einen Weg zum vollständigen
   gibt (Hausregel aus der KelRaid-Landingpage). Den baut js/app.js: Wo wirklich
   etwas abgeschnitten ist, wird die Karte zur Schaltfläche und klappt auf. Wo
   nicht, gibt es keine Schaltfläche — ein Knopf, der nichts tut, ist schlimmer
   als keiner. */
.wx-worte { position: relative; }

.wx-worte p {
  margin: 0; max-width: 68ch;
  font-size: var(--fs-16); line-height: 1.65; color: var(--body);
  /* 🚨 KEINE KLEMMUNG MEHR — der Text steht vollständig, es gibt keinen Pfeil.
     Die frühere `-webkit-line-clamp`-Klemmung samt reserviertem Pfeil-Einzug
     ist ersatzlos weg (zweimal gemeldet: „braucht kein Toggle").

     🚨 DIE MINDESTHÖHE IST NUR EIN KLEINER BODEN (ZWEI ZEILEN), KEINE RESERVE
        FÜR DEN LÄNGSTEN TEXT. Vorher waren es vier bis acht Zeilen; bei einem
        kurzen Zwei-Zeilen-Text (der Normalfall an klaren Tagen) stand darunter
        ein großer leerer Kasten — zweimal mit Foto gemeldet („unnötig hoch").
        Jetzt hugst die Karte ihren Text: zwei Zeilen sind der häufige Fall und
        zugleich die Höhe des Ladeskeletts (zwei Balken, index.php) — der Text
        springt beim Eintreffen also nicht. Ein längerer Text WÄCHST darüber
        hinaus (keine Klemmung, kein Pfeil); das geschieht selten, unter dem
        Helden und den Werte-Kacheln, also unter der Falz — der `qa/wetter-fein`-
        Check erlaubt Wachstum und ahndet nur SCHRUMPFUNG (leeren Kasten). */
  min-height: calc(2 * 1.65em);
}
/* Im Ladezustand sind es drei Balken — der Platzhalter soll wie ein Absatz
   aussehen, nicht wie eine Zeile. */
.wx-worte .wx-skelett { display: block; margin-bottom: 4px; }

/* ── iOS-Zusammenfassungen ─────────────────────────────────────────────────
   Die Kurzzeile über dem Stundenband und der 3-Tage-Ausblick über den
   Wochenkarten. Beide: `min-height` als Boden (Skelett == typische Länge),
   Wachstum erlaubt, Schrumpfen nicht — dieselbe Regel wie die Worte-Karte.
   Beide Elemente bleiben stehen, auch wenn ihr Text fehlt (keine Kollaps →
   kein Sprung); der Server füllt sie an jedem normalen Tag. */
.wx-kurz {
  margin: 0 0 var(--sp-12);
  font-size: var(--fs-15); line-height: 1.45; color: var(--body);
  max-width: 62ch; min-height: 1.45em;
}
.wx-ausblick {
  margin: 0 0 var(--sp-12);
  font-size: var(--fs-14); line-height: 1.5; color: var(--body);
  max-width: 68ch; min-height: calc(2 * 1.5em);
}
.wx-ausblick .wx-skelett { display: block; margin-bottom: 4px; }

/* 7-Tage-Temperaturverlauf — Hoch/Tief-Kurve über die Woche. Feste Höhe (das
   Skelett trägt dieselbe), damit die Kartenreihe darunter nicht springt. Die
   Farben sind dieselben wie der Temperaturbalken der Tageskarte: kühl → warm. */
.wx-trend {
  height: 138px; margin: 0 0 var(--sp-12);
  border-radius: var(--r-14); background: var(--soft);
  box-shadow: var(--sh-saum); overflow: hidden;
}
.wx-trend svg { display: block; width: 100%; height: 100%; }
.wx-trend .wx-skelett { border-radius: var(--r-14); }
.wx-trend-flaeche { fill: var(--acc); opacity: .09; }
.wx-trend-hoch { fill: none; stroke: #ffb347; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.wx-trend-tief { fill: none; stroke: #4da3ff; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.wx-trend-pkt.hoch { fill: #ffb347; }
.wx-trend-pkt.tief { fill: #4da3ff; }
.wx-trend-pkt.heute { stroke: var(--soft); stroke-width: 2; }
/* ⚠️ Schrift MITTIG über/unter dem Punkt; die viewBox bekommt die echte
   Pixelbreite (ui-tage.js), deshalb verzerrt „none" die Glyphen nicht. */
.wx-trend-lab { text-anchor: middle; font-size: 12px; font-weight: 700; }
.wx-trend-lab.hoch { fill: var(--ink); }
.wx-trend-lab.tief { fill: var(--body); font-weight: 600; }
.wx-trend-tag { text-anchor: middle; font-size: 11px; fill: var(--muted); }
.wx-trend-tag.heute { fill: var(--ink); font-weight: 700; }

/* ── Regen-Nowcast über dem Band ────────────────────────────────────────────
   Eine hervorgehobene, aber ruhige Zeile: Tropfen + Ansage + sichtbarer
   Quellenhinweis (EINE Quelle, deshalb ausgewiesen). Erscheint nur, wenn es
   etwas zu melden gibt — kein reserviertes Skelett. */
.wx-nowcast {
  display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap;
  margin: 0 0 var(--sp-12); padding: var(--sp-10) var(--sp-12);
  border-radius: var(--r-14);
  background: color-mix(in srgb, var(--acc) 14%, var(--flaeche));
  border-left: 3px solid var(--acc);
  box-shadow: var(--sh-1), var(--sh-saum);
  font-size: var(--fs-14); line-height: 1.35; color: var(--ink);
}
.wx-nowcast[hidden] { display: none; }
.wx-nowcast-ik { flex: 0 0 auto; display: grid; place-items: center; }
.wx-nowcast-ik svg { width: 18px; height: 18px; color: var(--acc-2); }
.wx-nowcast-txt { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.wx-nowcast-q {
  flex: 0 0 auto; font-size: var(--fs-12); font-weight: 400; color: var(--muted);
}
/* 📊 Regen-Nowcast als Balkendiagramm — ein Balken je 15-Min-Slot. Volle Breite
   (`flex-basis: 100%`) unter der Textzeile. Trockene Slots stehen als leiser
   3-px-Stummel (durchgehende Zeitleiste), nasse wachsen und färben sich in die
   Akzentfarbe. `--h` (0…1) kommt je Balken per Inline-Style; hier als 0
   deklariert, damit qa/wetter-css.mjs es kennt. */
.wx-nc-grafik { flex: 1 1 100%; margin-top: var(--sp-6); }
.wx-nc-balken { display: flex; align-items: flex-end; gap: 3px; height: 40px; }
.wx-nc-b {
  --h: 0;
  flex: 1 1 0; min-width: 0;
  height: calc(var(--h) * 100%); min-height: 3px;
  border-radius: 3px 3px 0 0;
  background: color-mix(in srgb, var(--acc) 22%, transparent);
}
.wx-nc-b.ist-nass { background: var(--acc); }
.wx-nc-achse {
  display: flex; justify-content: space-between; margin-top: 4px;
  font-size: var(--fs-12); color: var(--muted);
}
/* 🌧️ Regen im Tagesverlauf — eine Karte mit 24 Stunden-Balken
   (Regenwahrscheinlichkeit). Wie der Nowcast-Balken: leise Stummel für trockene
   Stunden, Akzentfarbe für nasse. */
.wx-rv {
  margin: 0 0 var(--sp-12); padding: var(--sp-12);
  background: var(--flaeche); border-radius: var(--r-18);
  box-shadow: var(--sh-1), var(--sh-saum);
}
.wx-rv[hidden] { display: none; }
.wx-rv-balken { display: flex; align-items: flex-end; gap: 2px; height: 56px; margin-top: var(--sp-8); }
.wx-rv-b {
  --h: 0; flex: 1 1 0; min-width: 0;
  height: calc(var(--h) * 100%); min-height: 3px;
  border-radius: 2px 2px 0 0;
  background: color-mix(in srgb, var(--acc) 20%, transparent);
}
.wx-rv-b.ist-nass { background: var(--acc); }
.wx-rv-achse {
  display: flex; justify-content: space-between; margin-top: 4px;
  font-size: var(--fs-12); color: var(--muted);
}

/* ══════════════════════════════════════════════════════════════════════════
   AUF GROSSEN SCHIRMEN: MEHR ALS EINE KARTE PRO REIHE
   ══════════════════════════════════════════════════════════════════════════
   Gemeldet: „Auf großem Bildschirm nicht die Karten sinnlos in die Breite
   ziehen — den Platz gut nutzen, mehr als eine Karte pro Reihe." Zu Recht: Eine
   Textkarte oder eine Werteleiste über 1400 px breit liest sich schlechter, nicht
   besser. Ab 1000 px wird `#wx-inhalt` deshalb ein Zwei-Spalten-Raster:

   • Voll über beide Spalten bleibt, was von Natur aus breit ist: der Held (das
     Banner), das waagerechte Stundenband und das Tage-Raster (beide in ihrem
     `.wx-abschnitt`), sowie die Hinweiszeile.
   • Nebeneinander stehen die kompakten Karten: links Werte + Text-Vorhersage
     gestapelt, rechts die Modell-Einigkeit — die spannt beide Zeilen, damit die
     Höhen sich ausgleichen (die Einigkeits-Karte ist die höchste der drei).
   ⚠️ Die Abstände macht der `gap` des Rasters; die eigenen `margin-top` der
      Halter/Abschnitte würden ihn verdoppeln, also hier auf 0. */
@media (min-width: 1000px) {
  /* ⚠️ DAS RASTER SITZT AUF #wx-seite, NICHT #wx-inhalt. #wx-seite ist die
     Ortsseite, die beim Wischen verschoben wird; sie ist zugleich der direkte
     Elternknoten von Held/Werte/Einigkeit/Abschnitten — nur so greifen die
     Spaltenregeln (`> .wx-abschnitt` etc.). Der feste Punkte-Indikator liegt
     außerhalb und nimmt am Raster nicht teil. */
  #wx-seite {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-16);
    align-items: start;
  }
  #wx-seite > * { margin-top: 0; }
  /* ⚠️ Reihenfolge im DOM: Held → Text → Stundenband → Sieben Tage → Detailkarten
     → Einigkeit → Güte. Die Vorhersage (Stunden + Tage, beide volle Breite) steht
     ganz oben; erst DARUNTER die zweispaltige Detailfläche (Werte links, Einigkeit
     rechts). So muss man nicht an allen Detailkarten des heutigen Tages vorbei,
     um zu den nächsten Tagen zu gelangen (auf dem Handy dieselbe Reihenfolge, nur
     einspaltig). */
  /* Alles volle Breite: Die Detailkarten (#wx-werte) breiten sich als eigenes
     mehrspaltiges Raster über die ganze Breite aus (siehe .wx-werte unten),
     statt in einer halben Spalte zu stapeln und rechts eine große Leere zu
     lassen. Die Einigkeit steht als volle Karte darunter. */
  #wx-held,
  #wx-hinweis,
  #wx-worte,
  .wx-werte-kopf,
  #wx-werte,
  #wx-einigkeit,
  #wx-guete,
  #wx-seite > .wx-abschnitt { grid-column: 1 / -1; }
}
/* ⚠️ KEINE DRITTE SPALTE. Ein erster Anlauf stellte ab 1500 px auf drei Spalten
   (Werte | Text | Einigkeit); die Werte-Karte wurde dabei so schmal, dass ihre
   4 inneren Spalten die Beschriftungen abschnitten („Regenri…", „Unterga"), und
   die unterschiedlich hohen Karten ließen große Löcher. Zwei Spalten nutzen den
   Platz gut, ohne etwas zu quetschen — die Gesamtbreite deckelt ohnehin
   `.wx-wrap`. */

/* ── Modell-Einigkeit ──────────────────────────────────────────────────────
   Der Markenkern dieser Seite: das Einzige, was keine andere Wetterseite zeigt.

   ⚠️ SIE STEHT SEIT DIESEM UMBAU NEBEN DEM HELDEN, NICHT DARIN. Als schmale
   Glaskachel in der rechten Heldenhälfte war ausgerechnet der wichtigste eigene
   Inhalt der Seite die am schlechtesten lesbare Fläche: weißer Fließtext auf
   halbdurchsichtigem Glas über einer laufenden Animation. Als eigene Karte in
   der normalen Seitenpalette hat sie Kontrast aus dem Stylesheet statt aus einer
   Rechnung, Platz für die Erklärung — und den Rang, der ihr zusteht.

   ⚠️ Heißt in der Oberfläche IMMER „Modell-Einigkeit", nie „Trefferquote":
   Ensemblespreizung ist keine kalibrierte Trefferwahrscheinlichkeit. */
.wx-einig-halter { margin-top: var(--sp-16); }
.wx-einig-halter[hidden] { display: none; }

/* ⚠️ `flex-start`, nicht `center`. Zugeklappt ist die Karte zwei Zeilen hoch,
   da fällt der Unterschied nicht auf; aufgeklappt ist sie es nicht mehr, und
   die große Zahl hing dann mittig neben einer langen Aufschlüsselung — weit
   unterhalb der Überschrift, zu der sie gehört. Oben bleibt sie neben
   „Modell-Einigkeit" stehen, wo man sie liest. */
.wx-einig {
  display: flex; flex-direction: column; gap: var(--sp-12);
  padding: var(--sp-16) var(--sp-20);
  border-radius: var(--r-18);
  background: var(--flaeche);
  box-shadow: var(--sh-1), var(--sh-saum), var(--sh-glanz);
}
@media (min-width: 1000px) { .wx-einig { padding: var(--sp-20) var(--sp-24); } }

/* Zahl + Titel bilden EINE Kopfzeile: die große Zahl links, Beschriftung und
   Stufe rechts daneben. So steht die Beschriftung neben der Zahl statt darunter
   — auf dem Handy spart das die Zeile, in der die Zahl sonst allein stand.
   Balken, Erklärsatz und Knöpfe liegen darunter über die volle Breite. */
.wx-einig-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-8) var(--sp-16);
}

/* Die Zahl trägt die Karte — sie steht groß und für sich, links neben der
   Beschriftung, statt als fette Ziffer mitten im Fließtext. */
.wx-einig-zahl {
  flex: 0 0 auto; display: flex; align-items: baseline; gap: 1px;
  color: var(--acc); white-space: nowrap;
}
.wx-einig-zahl b { font-size: var(--fs-44); font-weight: 700; line-height: .95; letter-spacing: -.03em; }
.wx-einig-zahl span { font-size: var(--fs-18); font-weight: 600; }
.wx-einig.stufe-mittel .wx-einig-zahl { color: var(--warn); }
.wx-einig.stufe-gering .wx-einig-zahl { color: var(--schlecht); }

.wx-einig-text { flex: 1 1 auto; min-width: 0; }

/* ⚠️ Der Titel darf UMBRECHEN. Neben der großen Zahl bleibt bei 150 % Systemschrift
   auf 360 px zu wenig Platz für „Modell-Einigkeit" in einer Zeile; mit `nowrap`
   ragte die Beschriftung quer aus der Karte (von `qa/wetter-design.mjs` gefangen).
   Der Titelblock trägt deshalb `flex-wrap` am Kopf: reicht der Platz neben der Zahl
   nicht, rutscht er als Ganzes unter sie (der frühere Stapel-Fall) — im Normalfall
   steht er daneben. Die Stufen-Pille bleibt `nowrap` (eine Pille bricht nicht um). */
.wx-einig-kopf {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
}
.wx-einig-lab {
  font-size: var(--fs-15); font-weight: 600; color: var(--ink);
}
/* 🚨 DIE STUFEN-PILLE TRÄGT IHRE FARBE IM PUNKT, NICHT IM GRUND. Ein erster
   Entwurf tönte den GRUND in der Stufenfarbe — und fiel prompt durch die
   Kontrastprüfung (3,82:1 in Hell): Ein Grund in der Textfarbe verschluckt die
   Schrift, genau die Falle, vor der die Hausregel warnt. Deshalb bleibt der
   Grund neutral (`--soft`, in beiden Themen sicher), und die Farbe steckt in
   einem Punkt davor (`currentColor` = die Stufenfarbe). Das liest sich als
   gefüllte, farbige Pille, ohne die eigene Schrift zu schwächen — und passt zum
   Punkt im Helden-Chip. */
.wx-einig-stufe {
  display: inline-flex; align-items: center; gap: var(--sp-6);
  padding: 3px var(--sp-8) 3px var(--sp-6); border-radius: var(--r-pill);
  font-size: var(--fs-12); font-weight: 700; white-space: nowrap;
  background: var(--soft); box-shadow: var(--sh-saum);
  color: var(--gut);
}
.wx-einig-stufe::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto;
  background: currentColor;
}
.wx-einig.stufe-mittel .wx-einig-stufe { color: var(--warn); }
.wx-einig.stufe-gering .wx-einig-stufe { color: var(--schlecht); }

.wx-einig-bar {
  position: relative; height: 8px;
  border-radius: var(--r-pill); background: var(--soft);
  box-shadow: var(--sh-saum); overflow: hidden;
}
.wx-einig-bar i {
  position: absolute; inset: 0 auto 0 0; border-radius: inherit;
  background: linear-gradient(90deg, var(--acc), #7fe9c4);
  transition: width var(--mo-lang) var(--ease-standard);
}
.wx-einig.stufe-mittel .wx-einig-bar i { background: linear-gradient(90deg, #ffb347, #ffd88a); }
.wx-einig.stufe-gering .wx-einig-bar i { background: linear-gradient(90deg, #ff7a7a, #ffb0a0); }
@media (prefers-reduced-motion: reduce) { .wx-einig-bar i { transition: none; } }

/* ⚠️ DER ERKLÄRSATZ IST DER EINZIGE ORT DER SEITE, AN DEM DAS LADESKELETT NICHT
   VON SELBST PASST. Überall sonst haben Platzhalter und Inhalt dieselbe Form;
   hier ist der Inhalt ein SATZ, und wie viele Zeilen der braucht, hängt an der
   Breite: gemessen drei Zeilen unter 560 px, zwei bis 834 px, darüber eine. Das
   Skelett hatte immer zwei — auf dem Handy war es 20 px zu kurz (alles darunter
   rutschte beim Eintreffen der Daten nach), auf dem Tablet 21 px zu lang.

   Deshalb zweierlei: eine Mindesthöhe in ZEILEN (die Karte kann damit nicht
   kleiner werden als der fertige Satz), und ein Skelett aus drei Balken, von
   denen die Media-Queries genau so viele stehen lassen, wie der Satz dort
   Zeilen hat. ⚠️ Die beiden Schwellen 560 und 834 sind GEMESSEN, nicht gewählt:
   Wer den Satz ändert, misst sie nach — `qa/wetter-fein.mjs` vergleicht das
   erste Bild mit dem fertigen und meldet die Abweichung auf den Pixel. */
.wx-einig-fuss {
  margin-top: var(--sp-8); font-size: var(--fs-13); color: var(--muted); line-height: 1.5;
  min-height: 4.5em;                      /* drei Zeilen */
}
/* ⚠️ EIN BALKEN IST GENAU EINE ZEILE HOCH. Als `inline-block` (die Vorgabe für
   `.wx-skelett`) baut er eine Zeilenbox, die ein paar Punkte höher ist als
   reiner Text — gemessen war das Skelett dadurch 41 px hoch, der fertige Satz
   39 px, und die Karte schrumpfte beim Eintreffen der Daten um zwei Punkte.
   Zwei Punkte sieht niemand; sie sind aber der Beleg, dass hier die Zeilenzahl
   NICHT gilt, und beim nächsten Textwechsel wird eine Zeile daraus. */
.wx-einig-fuss .wx-skelett { display: block; height: 1.5em; margin: 0; }
/* Dasselbe im Kopf: `inline-block` mit `vertical-align: middle` baut eine
   Zeilenbox, die einen Punkt höher ist als der Text, der später dort steht.
   Als Block ist der Balken genau eine Textzeile hoch. */
.wx-einig-kopf .wx-skelett { display: block; }
@media (min-width: 560px) {
  .wx-einig-fuss { min-height: 3em; }     /* zwei */
  .wx-einig-fuss .wx-skelett:nth-child(3) { display: none; }
}
@media (min-width: 834px) {
  .wx-einig-fuss { min-height: 1.5em; }   /* eine */
  .wx-einig-fuss .wx-skelett:nth-child(2) { display: none; }
}
.wx-einig-fuss a { color: var(--acc); }

/* ── „Details": die Antwort auf „warum ausgerechnet diese Zahl?" ───────────
   Der Knopf steht VOR dem Link auf die Methodenseite. Er beantwortet die Frage
   dieses Tages, der Link das Verfahren im Allgemeinen — und wer nur den Link
   hatte, landete immer beim Allgemeinen (so gemeldet). */
/* ⚠️ Die REIHE hält die Höhe, nicht ihr Inhalt. Ohne `min-height` ergab sich
   sie aus dem Knopf — und der ist im Ladeskelett ein <span> mit derselben
   Klasse, aber ohne Symbol und ohne Schrift. Gemessen wich die Karte dadurch um
   ein bis zwei Punkte ab, je nach Breite. Ein Sprung von zwei Punkten sieht
   niemand, aber er ist der Anfang: Sobald jemand den Knopftext ändert, wird
   daraus eine Zeile. */
.wx-einig-tat {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--sp-8) var(--sp-10); margin-top: var(--sp-12);
  min-height: var(--ziel);
}
.wx-einig-mehr {
  display: inline-flex; align-items: center; gap: var(--sp-6);
  min-height: var(--ziel); padding: var(--sp-6) var(--sp-16);
  border-radius: var(--r-pill);
  background: var(--soft); color: var(--ink);
  font-size: var(--fs-13); font-weight: 600;
  box-shadow: var(--sh-saum);
  transition: background-color var(--mo-kurz) var(--ease-standard);
}
@media (hover: hover) and (pointer: fine) {
  .wx-einig-mehr:hover { background: var(--line); }
}
.wx-einig-mehr svg {
  width: 16px; height: 16px;
  transition: transform var(--mo-mittel) var(--ease-standard);
}
.wx-einig-mehr.ist-offen svg { transform: rotate(180deg); }
/* Der Weg zur Methodenseite steht jetzt als leiser Textlink UNTER den beiden
   Knöpfen (eigene Zeile), nicht mehr in der Knopfreihe. Der zweite Weg, ruhig
   gesetzt — der erste ist der Details-Knopf. */
.wx-einig-link {
  display: inline-block; margin-top: var(--sp-10);
  color: var(--acc); font-size: var(--fs-13);
}
.wx-einig-warum[hidden] { display: none; }
.wx-einig-warum { margin-top: var(--sp-12); }

/* ⚠️ ZEILENLÄNGE DECKELN. Auf dem Desktop ist die Karte über 1200 px breit; die
   vier Balken liefen dann von Rand zu Rand und die Zahl stand einen halben Meter
   von ihrer Beschriftung entfernt. Der Block bekommt deshalb ein Textmaß — er
   ist Fließtext mit Balken, keine Tabelle. */
.wx-warum { max-width: 68ch; }
/* ⚠️ EIN SATZ, KEINE ÜBERSCHRIFT. Er stand in derselben Größe und Stärke da wie
   „Modell-Einigkeit" darüber — zwei fette Zeilen kurz hintereinander, von denen
   die zweite länger ist als die erste. Gemeldet als „wirkt nicht
   professionell", und das ist die richtige Beschreibung: Wo zwei Dinge gleich
   laut sind, gibt es keine Hierarchie mehr, nur noch Lautstärke. Er fasst die
   vier Zeilen darunter zusammen, also gehört er zu ihnen — nicht über sie. */
.wx-warum-satz {
  margin: 0 0 var(--sp-10); font-size: var(--fs-13); font-weight: 400;
  color: var(--body); line-height: 1.5;
}
.wx-warum-satz b { font-weight: 700; color: var(--ink); }
.wx-warum-liste { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-12); }
/* Beschriftung links, Beitrag rechts, darunter Balken und Klartext über die
   volle Breite — auf jeder Größe dieselbe Ordnung, damit die vier Zeilen als
   Reihe lesbar bleiben statt als vier Absätze. */
.wx-warum-teil {
  display: grid; grid-template-columns: 1fr auto; gap: 2px var(--sp-10);
  align-items: baseline;
}
.wx-warum-lab { font-size: var(--fs-13); font-weight: 600; color: var(--body); }
.wx-warum-wert {
  font-size: var(--fs-13); color: var(--muted); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.wx-warum-bar {
  grid-column: 1 / -1; height: 6px; border-radius: var(--r-pill);
  background: var(--soft); overflow: hidden;
}
.wx-warum-bar i { display: block; height: 100%; border-radius: var(--r-pill); background: var(--acc); }

/* ── Jede Zeile trägt ihre Farbe ──────────────────────────────────────────
   Balken UND Zahl, damit auch eine Zeile mit „0 von 35" — deren Balken man
   naturgemäß nicht sieht — als schwach erkennbar ist statt als kaputt. */
.wx-warum-teil.ist-gut    .wx-warum-bar i { background: var(--gut); }
.wx-warum-teil.ist-mittel .wx-warum-bar i { background: var(--warn); }
.wx-warum-teil.ist-schwach .wx-warum-bar i { background: var(--schlecht); }
.wx-warum-teil.ist-gut    .wx-warum-wert { color: var(--gut); font-weight: 600; }
.wx-warum-teil.ist-mittel .wx-warum-wert { color: var(--warn); font-weight: 600; }
.wx-warum-teil.ist-schwach .wx-warum-wert { color: var(--schlecht); font-weight: 600; }

/* Der Teil, den der Satz darüber beim Namen nennt, wird auch gezeigt: ein
   Strich an der Kante und ein kräftigerer Name. Ohne diese Verbindung muss man
   die genannte Zeile unter vier gleich aussehenden erst suchen.

   🚨 DER STRICH IST NEUTRAL, NICHT ROT — hier stecken ZWEI verschiedene Fragen
      nebeneinander, und sie dürfen nicht dieselbe Farbsprache benutzen:
      • Balken und Zahl beantworten „wie gut trägt dieser Teil?" (der erreichte
        Anteil, also auch die Breite des Balkens).
      • Der Strich beantwortet „welchen Teil nennt der Satz darüber?" — und das
        ist der grösste absolute VERLUST (Gewicht minus Beitrag), nicht der
        schlechteste Anteil.
      Beides fällt regelmässig auseinander: Gemessen zog „Streuung der Werte"
      mit 19 von 35 am stärksten nach unten (16 Punkte Verlust), während
      „Einigkeit beim Niederschlag" mit 5 von 20 den schlechteren Anteil hat
      (15 Punkte Verlust, aber nur 25 % erreicht). Ein roter Strich an der
      markierten Zeile las sich dann als Widerspruch: Die rot gefärbte Zeile
      daneben sah schlechter aus als die angeblich schlimmste. */
/* 🚨 DER STRICH SCHIEBT DIE ZEILE NICHT EIN. Gemeldet: „keine Ahnung warum die
   Detail-Karte links minimal eingerutscht ist." Ursache war `padding-left: 10px`
   bei nur `margin-left: -3px` — der Text der markierten Zeile stand damit 7 px
   rechts von den übrigen. Jetzt hebt der negative Rand das Polster GENAU auf
   (−12 + 3 Rahmen + 9 Polster = 0): der Text steht auf derselben linken Kante wie
   alle anderen Zeilen, der Strich liegt im Innenabstand der Karte (≥ 16 px). */
.wx-warum-teil.ist-schwaechster {
  margin-left: -12px;
  border-left: 3px solid var(--acc);
  padding-left: 9px;
}
.wx-warum-teil.ist-schwaechster .wx-warum-lab { color: var(--ink); font-weight: 700; }
.wx-warum-txt {
  grid-column: 1 / -1; font-size: var(--fs-13); color: var(--muted); line-height: 1.5;
}
.wx-warum-fuss {
  margin: var(--sp-12) 0 0; font-size: var(--fs-13); color: var(--muted); line-height: 1.5;
}
/* Die Worterklärung zu „Stimmen" — eine Stufe leiser als der Rest der Fußzeile.
   Sie beantwortet eine Frage, die nur hat, wer sie stellt; wer sie nicht stellt,
   soll nicht über sie stolpern. */
.wx-warum-fn { opacity: .78; }
/* ⚠️ EIGENE ZEILE, volles Fingerziel. Im Satz war der Link 15 px hoch — im
   Detail-Panel ist er der einzige Weg zur Methodenseite, und dort trifft man
   ihn mit dem Daumen nicht. `align-self: start` verhindert, dass er in einem
   Grid-Elternteil auf die volle Breite gezogen wird. */
.wx-warum-mehr {
  display: inline-flex; align-items: center; align-self: start;
  min-height: var(--ziel); margin-top: 2px;
  color: var(--acc); font-size: var(--fs-13); font-weight: 600;
}

/* ── Modell-Einigkeit auf der Tageskarte ───────────────────────────────────
   🚨 Ein kurzer, gefüllter Balken plus ein Wort — deutlich klarer als die
   früheren vier Punkte (gemeldet: „hier kann man nur schlecht die Einigkeit
   erkennen"). Der Balken zeigt die Größenordnung, das Wort benennt sie, die
   Farbe kommt aus der Stufe. Dieselben drei Farben wie zuvor die Punkte. */
.wx-tag-einig { display: inline-flex; align-items: center; gap: 5px; min-width: 0; }
.wx-tag-einig-bar {
  width: 30px; height: 5px; flex: 0 0 auto;
  border-radius: 999px; background: var(--line-stark); overflow: hidden;
}
.wx-tag-einig-bar i {
  display: block; height: 100%; border-radius: inherit; background: var(--gut);
  transition: width var(--mo-kurz) var(--ease-standard);
}
.wx-tag-einig-wort {
  font-size: var(--fs-12); font-weight: 700; color: var(--gut); white-space: nowrap;
}
.wx-tag-einig.stufe-mittel .wx-tag-einig-bar i { background: var(--warn); }
.wx-tag-einig.stufe-mittel .wx-tag-einig-wort { color: var(--warn); }
.wx-tag-einig.stufe-gering .wx-tag-einig-bar i { background: var(--schlecht); }
.wx-tag-einig.stufe-gering .wx-tag-einig-wort { color: var(--schlecht); }
@media (prefers-reduced-motion: reduce) { .wx-tag-einig-bar i { transition: none; } }

/* Legende im Abschnittskopf: zeigt EINMAL denselben Balken, den jede Karte
   trägt, statt ihn auf jeder Karte unerklärt zu lassen. */
.wx-legende { display: inline-flex; align-items: center; gap: var(--sp-6); white-space: nowrap; }

/* ── Stundenband ──────────────────────────────────────────────────────────*/
.wx-stunden {
  display: flex; gap: var(--sp-8);
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  padding-bottom: var(--sp-8);
  /* Die Liste rollt in SICH — die Seite darf nie waagerecht scrollen. Der
     negative Rand zieht sie bis an die Bildschirmkante (dort sieht ein Band
     angeschnitten aus, und genau das lädt zum Wischen ein), das gleich große
     Polster setzt die erste Kachel wieder an den Textrand. ⚠️ Beide Zahlen
     kommen aus DERSELBEN Variablen wie das Polster der Hülle — im Querformat
     mit Ausschnitt ist das nicht mehr `--sp-16`, und eine zweite Zahl hier
     würde das Band unter den Ausschnitt schieben. */
  margin-left: calc(-1 * var(--wx-rand-l)); padding-left: var(--wx-rand-l);
  margin-right: calc(-1 * var(--wx-rand-r)); padding-right: var(--wx-rand-r);
  /* ⚠️ OHNE DIESE ZWEI ZEILEN IST DAS POLSTER OBEN WIRKUNGSLOS — und genau so
     stand die erste Kachel 18 px weiter links als jede Überschrift und jede
     Tageskarte darunter. Der Grund ist nicht das Polster, sondern das
     Einrasten: `scroll-snap-align: start` richtet die Kachel am *Snapport* aus,
     und der beginnt standardmäßig an der RAHMENkante des Rollbereichs, nicht an
     der Polsterkante. Der Browser rollt also beim Aufbau um genau die
     Polsterbreite weiter — gemessen scrollLeft = 18 auf einem Band, das nie
     jemand angefasst hatte. `scroll-padding` verschiebt den Snapport auf die
     Polsterkante; damit rastet die erste Kachel bei scrollLeft 0 ein und steht
     bündig zum übrigen Inhalt. Dieselben Variablen wie oben, sonst laufen die
     drei Zahlen für dieselbe Kante auseinander. */
  scroll-padding-left: var(--wx-rand-l);
  scroll-padding-right: var(--wx-rand-r);
  /* ⚠️ An den Kanten LÄUFT das Band aus, statt hart abgeschnitten zu werden.
     Vorher endete es an der Hüllenkante mitten in einer Kachel: „07" war zu
     lesen, die Temperatur darunter nicht mehr — ein abgeschnittener Text, der
     wie ein Layoutfehler aussieht statt wie „hier geht es weiter". Der Verlauf
     beginnt erst NACH dem Polster, damit die erste Kachel voll deckend bleibt.
     Eine Maske ist eine statische Ebene und kostet im Betrieb nichts. */
  --wx-band-fade: var(--sp-24);
  -webkit-mask-image: linear-gradient(90deg, transparent 0,
    #000 var(--wx-rand-l), #000 calc(100% - var(--wx-band-fade)), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0,
    #000 var(--wx-rand-l), #000 calc(100% - var(--wx-band-fade)), transparent 100%);
  scrollbar-width: thin;
  /* ⚠️ Ohne das gibt der Browser die Wischgeste am Ende des Bandes an die SEITE
     weiter — und auf dem Handy heißt „waagerecht wischen, wo nichts mehr rollt"
     Zurück-Navigation. Man wischt durch die 48 Stunden und landet unversehens
     auf der vorigen Seite. `contain` hält die Geste im Band. */
  overscroll-behavior-x: contain;
}
.wx-stunden::-webkit-scrollbar { height: 6px; }
.wx-stunden::-webkit-scrollbar-thumb { background: var(--line-stark); border-radius: var(--r-pill); }

/* ⚠️ `position: relative` ist hier KEINE Kosmetik, sondern hält die Seite
   zusammen. In der Kachel steht ein `.wx-sr`-Text für Screenreader, und der ist
   `position: absolute`. Ein absolut positioniertes Element wird NUR von einem
   Vorfahren beschnitten, der selbst positioniert ist — ohne diese Zeile hängen
   die 48 Vorlesetexte an der Seite statt am Band, und die Seite wurde damit
   4255 statt 1440 Pixel breit (von qa/wetter-ui.mjs gemessen und gemeldet).
   Das Band selbst rollte dabei völlig korrekt; sichtbar war nur, dass die ganze
   Seite waagerecht schob. Gilt für JEDE Kachel mit `.wx-sr` in einem Roller. */
/* ⚠️ `min-height` ist hier KEINE Kosmetik, sondern der Grund, warum die Seite
   beim Laden nicht springt. Das Ladeskelett und die fertige Kachel teilen sich
   diese Zahl — vorher hatte das Skelett eine geratene Inline-Höhe (104 px), die
   Kachel wurde 132 px, und ALLES darunter rutschte nach. Gemessener CLS: 0,47.
   Die Werte stammen aus der Messung der echten Kacheln je Stufe, nicht aus dem
   Gefühl; innerhalb einer Stufe sind sie auf das Pixel stabil. */
.wx-std {
  position: relative;
  flex: 0 0 auto; scroll-snap-align: start;
  width: 68px; min-height: 132px; padding: var(--sp-10) var(--sp-6);
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-6);
  border-radius: var(--r-14); background: var(--flaeche);
  box-shadow: var(--sh-saum), var(--sh-glanz);
  text-align: center;
}
@media (min-width: 1000px) { .wx-std { width: 78px; min-height: 144px; } }
@media (min-width: 1600px) { .wx-std { min-height: 154px; } }
/* 🚨 DIE AKTUELLE STUNDE TRÄGT EINE INNENKANTE, KEINEN AUSSENRING. Gemeldet:
   „Die Umrandung der Karte ist sehr komisch." Ursache war `--sh-ring-acc` — ein
   2-px-Ring 2 px AUSSERHALB der Kachel. Neben der eigenen Kante der Kachel las
   er sich als schwebende Doppellinie. Eine Innenkante (`inset`) folgt der
   Rundung exakt und sitzt bündig; nichts schwebt mehr daneben. (Ist diese
   Stunde zugleich die gewählte, gewinnt ohnehin die gefüllte Fläche unten.) */
.wx-std.ist-jetzt { background: var(--soft); box-shadow: inset 0 0 0 1.5px var(--acc), var(--sh-glanz); }

/* 🚨 DIE ANGETIPPTE STUNDE MUSS MAN SEHEN. Gemeldet: „Wenn man eine Stunde
   anklickt für weitere Details, hat man keinen Indikator an der UI."
   Die Ursache war kein Feinschliff, sondern eine Lücke: `ui-stunden.js` setzt
   beim Klick brav `.ist-gewaehlt` auf die Kachel — es gab dafür aber KEINE
   EINZIGE CSS-Regel. Die Klasse landete im DOM und bewirkte nichts. Im Bild
   klappte unten ein Panel auf, und oben war nicht zu erkennen, wozu es gehört;
   bei 48 nebeneinanderliegenden Kacheln ist das die einzige Frage, die zählt.

   ⚠️ EINE GEFÜLLTE FLÄCHE, KEINE ZWEITE KANTE. `.ist-jetzt` trägt bereits eine
      Akzent-Innenkante — eine zweite daneben wäre nicht unterscheidbar, und die
      aktuelle Stunde ist oft genau die, die man antippt. Gefüllt gegen
      umrandet ist auf einen Blick verschieden, auch nebeneinander.
   ⚠️ Der Zeiger unten verbindet Kachel und Panel. Ohne ihn ist die Markierung
      eine Auszeichnung; mit ihm ist sie eine Zuordnung — und genau die war die
      Beschwerde. Er sitzt IN der Kachel und rollt deshalb mit dem Band mit. */
.wx-std.ist-gewaehlt {
  background: var(--acc);
  /* 🚨 GAR KEIN SCHATTEN. Dreimal gemeldet — zuletzt „Der Schatten ist
     immernoch!!!". Erst war er `box-shadow` (nur am Rechteck, unter dem Zeiger
     abgebrochen), dann `filter: drop-shadow` (sauber um die ganze Sprechblase) —
     aber der Betreiber wollte nie einen SCHÖNEREN Schatten, sondern KEINEN. Die
     gefüllte Akzentfläche und der Zeiger unten heben die gewählte Stunde bereits
     eindeutig ab; ein nach außen geworfener Schatten war die Beschwerde selbst.
     Nur die Kanten aus `.wx-std` bleiben (`--sh-saum`/`--sh-glanz`, beide inset
     — sie liegen INNERHALB und werfen nichts nach außen). */
}
/* Alle Kindfarben mitziehen — sie sind einzeln gesetzt und würden sonst auf
   der Akzentfläche stehenbleiben (Regenzahl in Akzentblau auf Akzentblau). */
.wx-std.ist-gewaehlt .wx-std-zeit,
.wx-std.ist-gewaehlt .wx-std-temp,
.wx-std.ist-gewaehlt .wx-std-regen { color: var(--acc-ink); }
.wx-std.ist-gewaehlt .wx-std-sym { color: var(--acc-ink); }
.wx-std.ist-gewaehlt::after {
  content: ""; position: absolute; left: 50%; bottom: -7px;
  width: 14px; height: 14px; margin-left: -7px;
  background: var(--acc);
  clip-path: polygon(50% 100%, 0 0, 100% 0);
}
/* Ist die gewählte Stunde zugleich die aktuelle, gewinnt die Auswahl — sonst
   lägen Ring und Füllung übereinander. */
/* Der Ring der aktuellen Stunde weicht der Füllung; der Schatten kommt aus dem
   `drop-shadow` von `.ist-gewaehlt` (nicht doppelt als box-shadow dazu). */
.wx-std.ist-jetzt.ist-gewaehlt { background: var(--acc); box-shadow: none; }
.wx-std-zeit { font-size: var(--fs-13); color: var(--body); font-weight: 600; }
.wx-std-sym { width: 30px; height: 30px; }
.wx-std-temp { font-size: var(--fs-15); font-weight: 600; color: var(--ink); }
.wx-std-regen {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: var(--fs-12); color: var(--acc); min-height: 1.25em; font-weight: 600;
}
.wx-std-regen svg { width: 10px; height: 10px; flex: 0 0 auto; }
.wx-std.ist-gewaehlt .wx-std-regen svg { color: var(--acc-ink); }
/* ── Sonnenkachel im Band ──────────────────────────────────────────────────
   Sieht aus wie eine Stunde, ist aber keine: kein Knopf, kein Rahmen, gedämpfte
   Farbe. Sie markiert einen Zeitpunkt im Verlauf, sie zeigt keine Vorhersage. */
.wx-std.ist-sonne {
  background: transparent; box-shadow: none;
  color: var(--muted); cursor: default;
  /* ⚠️ BREITE NACH INHALT, nicht die feste Kachelbreite. Eine Stundenkachel
     trägt „34°", diese hier trägt „↓ Untergang" — bei großer Systemschrift
     ragte das Wort gemessen 31 px über die 78 px breite Kachel hinaus. Die
     Mindestbreite hält sie im Raster der übrigen Kacheln. */
  width: auto; min-width: 68px; padding-inline: var(--sp-12);
}
.wx-std.ist-sonne .wx-std-sym { width: 24px; height: 24px; color: var(--acc-2); }
.wx-std.ist-sonne .wx-std-zeit { color: var(--body); }
.wx-std-sonne {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: var(--fs-12); color: var(--muted); white-space: nowrap;
}
.wx-std-sonne i { font-style: normal; opacity: .7; }

/* Tagestrenner MIT Beschriftung. Ohne sie war es ein Zwischenraum, der zwar
   auffällt, aber nichts sagt. */
/* ⚠️ Der Trenner ist eine eigene SPALTE, keine 1-px-Linie mit einer Beschriftung
   obendrauf. Als Linie stand das Wort quer über den Nachbarkacheln — die haben
   einen eigenen Grund und übermalten es, sichtbar blieb „Morge". Eine Spalte mit
   eigener Breite kann nichts überdecken und nichts verdecken. */
.wx-std-tag {
  position: relative; flex: 0 0 auto; align-self: stretch;
  display: grid; place-items: center;
  /* Breite nach dem Wort, nicht 1 px: Als Haarlinie mit einer Beschriftung
     obendrauf stand das Wort quer über den Nachbarkacheln, die einen eigenen
     Grund haben und es übermalten — sichtbar blieb „Morge". */
  padding-inline: var(--sp-10);
}
/* Die Linie liegt HINTER der Beschriftung und läuft über die ganze Höhe. */
.wx-std-tag::before {
  content: ""; position: absolute; top: var(--sp-8); bottom: var(--sp-8); left: 50%;
  width: 1px; background: var(--line-stark);
}
.wx-std-tag i {
  position: relative;
  font-style: normal; font-size: var(--fs-12); font-weight: 700;
  color: var(--muted); white-space: nowrap;
  letter-spacing: .06em; text-transform: uppercase;
  background: var(--bg); padding: var(--sp-6) 4px;
}

/* ── Die aufgeklappte Stunde ───────────────────────────────────────────────
   Dasselbe Muster wie beim Tages-Panel: Die Fläche erscheint UNTER dem Band,
   nicht als Überlagerung. Ein Popover über einem waagerechten Roller verdeckt
   genau die Kacheln, zwischen denen man gerade vergleicht. */
.wx-std-detail { margin-top: var(--sp-12); }
.wx-std-detail[hidden] { display: none; }
.wx-sd {
  padding: var(--sp-16);
  border-radius: var(--r-14);
  background: var(--flaeche);
  box-shadow: var(--sh-1), var(--sh-saum), var(--sh-glanz);
  animation: wx-auf-kurz var(--mo-mittel) var(--ease-rein);
}
@keyframes wx-auf-kurz { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .wx-sd { animation: none; } }

.wx-sd-kopf { display: flex; align-items: center; gap: var(--sp-12); margin-bottom: var(--sp-12); }
.wx-sd-sym { width: 40px; height: 40px; flex: 0 0 auto; }
.wx-sd-wann { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.wx-sd-wann b { color: var(--ink); font-size: var(--fs-15); font-weight: 700; }
.wx-sd-wann span { color: var(--muted); font-size: var(--fs-13); }
.wx-sd-temp {
  flex: 0 0 auto; font-size: var(--fs-24); font-weight: 700; color: var(--ink);
  white-space: nowrap;
}
.wx-sd-zu {
  flex: 0 0 auto; width: var(--ziel); height: var(--ziel);
  display: grid; place-items: center; border-radius: var(--r-pill);
  color: var(--muted); box-shadow: var(--sh-saum);
  transition: background-color var(--mo-kurz) var(--ease-standard),
              color var(--mo-kurz) var(--ease-standard);
}
.wx-sd-zu:active{ background: var(--soft); color: var(--ink); }
@media (hover: hover) and (pointer: fine) {
  .wx-sd-zu:hover { background: var(--soft); color: var(--ink); }
}
.wx-sd-zu svg { width: 16px; height: 16px; }

/* Dieselbe Leiste wie im Helden — Haarlinien über den Rasterhintergrund
   (`--line`), die Felder in `--soft` darüber. 🚨 DIE SPALTENZAHL MUSS DIE ZAHL
   DER FELDER TEILEN, sonst bleibt im Raster ein Platz leer und der graue
   Rasterhintergrund scheint durch (genau der gemeldete graue Kasten). Es sind
   SECHS Felder — also 2 oder 3 Spalten, NIE 4 (das ließe zwei Plätze leer). */
/* 🚨 DUNKLER KARTENGRUND (`--flaeche`), NICHT die helle Rasterlinie `--line`.
   Gemeldet: „Warum ist die Farbe bei den Details oben nicht dieselbe wie bei
   früh/mittags/abends?" Die Verlaufs-Kacheln (`.wx-tag-ab`) sind `--soft` auf
   dem dunklen `--flaeche` der Tageskarte und lesen sich ruhig; hier lag
   dieselbe `--soft`-Fläche auf `--line` (im Himmel-Modus eine HELLE Linie) und
   wusch aus. Mit `--flaeche` als Grund sitzen die Felder auf demselben Dunkel
   wie früh/mittags/abends — gleiche Farbe. */
.wx-sd-werte {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px;
  border-radius: var(--r-10); background: var(--flaeche); overflow: hidden;
}
@media (min-width: 620px) { .wx-sd-werte { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.wx-sd-wert {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
  padding: var(--sp-10) var(--sp-12); background: var(--soft);
}
.wx-sd-wert span {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  font-size: var(--fs-12); color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wx-sd-wert span svg { width: 14px; height: 14px; flex: 0 0 auto; opacity: .8; }
.wx-sd-wert b {
  font-size: var(--fs-16); font-weight: 700; color: var(--ink); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── Tageskarten ──────────────────────────────────────────────────────────
   Ein Raster mit sieben Spalten auf dem Desktop, eine Liste auf dem Handy.
   Das Detail-Panel ist ein Rasterkind über die VOLLE Breite und rutscht durch
   die automatische Platzierung von selbst in die Zeile unter seine Karte. */
/* ⚠️ Die Spaltenzahl steht NICHT fest, sie ergibt sich aus einer Mindestbreite
   in `rem` — und `rem` heißt: Sie wächst mit der eingestellten Schriftgröße mit.
   Vorher waren es feste 7 Spalten ab 1000 px. Bei 150 % Systemschrift passte der
   Inhalt („31° 16°" plus Symbol) nicht mehr in die 130 px breite Spalte und
   stand gemessen 38 px außerhalb des Bildschirms. Mit `auto-fit` fällt das
   Raster in dem Moment von sieben auf fünf oder vier Spalten zurück, in dem es
   eng wird — ohne dass irgendwo eine weitere Media-Query dafür nötig wäre. */
.wx-tage {
  display: grid; gap: var(--sp-8);
  grid-template-columns: 1fr;
}
@media (min-width: 700px) {
  .wx-tage { grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); }
}

/* Dieselbe Begründung wie bei .wx-std: Skelett und Karte teilen sich die
   Mindesthöhe, damit beim Eintreffen der Daten nichts nachrutscht.
   ⚠️ Die Karte trägt jetzt DREI Zeilen mehr (Wetterwort, Regen/Einigkeit-Zeile,
   Tagesverlauf früh/mittags/abends). Gemessen liegt der Inhalt bei ~194 px, das
   strukturgleiche Skelett bei ~199 px; die Mindesthöhe deckt BEIDE ab, damit
   min-height auf jeder Engine greift und nichts springt (qa/wetter-fein). */
.wx-tag {
  position: relative; text-align: left; width: 100%;
  min-height: 200px;
  padding: var(--sp-12);
  border-radius: var(--r-14); background: var(--flaeche); color: var(--body);
  box-shadow: var(--sh-saum), var(--sh-glanz);
  /* ⚠️ FLEX MIT UMBRUCH STATT EINES RASTERS MIT BREAKPOINT — und das ist hier
     kein Geschmack, sondern die einzige Bauweise, die stimmt. Ob Tag, Symbol,
     Regenwert und Temperaturspanne nebeneinander passen, hängt nicht an der
     Gerätebreite allein, sondern am Verhältnis von Breite zu SCHRIFTGRÖSSE: Bei
     150 % Systemschrift stand der Höchstwert auf einem 360-px-Gerät gemessen
     46 px außerhalb der Karte, bei normaler Schrift passt dieselbe Zeile bequem.
     Eine Pixel-Media-Query sieht diesen Unterschied nicht. Eine em-Query auch
     nicht zuverlässig — in Media-Queries meint `em` die VOREINGESTELLTE
     Schriftgröße des Browsers, nicht die des Dokuments.
     Ein Flex-Umbruch braucht die Frage gar nicht zu beantworten: Die Spanne
     bekommt eine Wunschbreite, und wenn die nicht mehr danebenpasst, rutscht sie
     von selbst in die nächste Zeile. Auf jeder Breite, bei jeder Schriftgröße. */
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-10);
  /* 🚨 `align-content: flex-start` — die Zeilen packen sich OBEN, nicht über die
     ganze Kartenhöhe verteilt. „Heute" verliert am Abend seinen Verlauf (früh/
     mittags sind vorbei, < 2 Abschnitte → keine Kachelzeile); mit der Standard-
     Verteilung sprang die Temperaturspanne dann in die Kartenmitte und ließ
     einen großen Spalt über sich (fotografiert gemeldet: „Heute sieht neben
     Morgen nicht gut aus"). Oben gepackt steht die Spanne direkt unter dem Kopf
     wie bei jedem anderen Tag; die feste Mindesthöhe (Skelett == Inhalt) trägt
     die Restluft unten, wo sie nicht stört. */
  align-content: flex-start;
  /* Rundum gleicher Innenabstand (var(--sp-12)); der Aufklapp-Pfeil sitzt oben
     rechts mit demselben Abstand und wird NICHT über einen breiteren rechten
     Rand freigehalten — der ließ die rechte Seite eingerückt wirken. Platz für
     den Pfeil reserviert stattdessen die Kopfzeile selbst (.wx-tag-info). */
  transition: background-color var(--mo-kurz) var(--ease-standard),
              transform var(--mo-kurz) var(--ease-standard),
              box-shadow var(--mo-kurz) var(--ease-standard);
}
@media (hover: hover) and (pointer: fine) {
  .wx-tag:hover { background: var(--soft); }
}
/* ⚠️ `@media (hover: hover)`: Auf einem Berührungsbildschirm gibt es kein
   Überfahren — ein angehobener Zustand bliebe dort nach dem Antippen einfach
   stehen (der bekannte „klebende Hover"). */
@media (hover: hover) {
  .wx-tag:hover { transform: translateY(-1px); box-shadow: var(--sh-2), var(--sh-saum), var(--sh-glanz); }
  .wx-std:hover { background: var(--soft); }
}
/* Eine Karte ist zu groß, um zu „sinken" — sie zieht sich beim Antippen leicht
   zusammen. Das liest sich auch am Rand des Blickfelds als Antwort. */
.wx-tag:active { transform: scale(.975); background: var(--soft); }
.wx-tag[aria-expanded="true"] { background: var(--soft); box-shadow: var(--sh-saum), var(--sh-ring-acc); }

@media (min-width: 700px) {
  .wx-tag {
    display: grid; grid-template-columns: 1fr; justify-items: center; text-align: center;
    padding: var(--sp-16) var(--sp-12); gap: var(--sp-8);
    min-height: 180px;
  }
}
@media (min-width: 1000px) { .wx-tag { min-height: 210px; } }

/* 🚨 DIE NAMENSSPALTE HAT EINE FESTE BREITE — daran hing der ganze Eindruck.
   Sie war inhaltsbreit, also war „Heute" breiter als „Do" und „Morgen" breiter
   als beide. Weil Symbol und Regenwert danach kommen, verschob sich in JEDER
   Karte alles um ein paar Punkte: Die sieben Wettersymbole standen auf sieben
   verschiedenen Senkrechten, die Prozentzahlen ebenso. Einzeln sieht man das
   nicht, untereinander sieht man nichts anderes mehr — gemeldet als „wirkt
   nicht professionell". Fluchtende Spalten sind der Unterschied zwischen einer
   Liste und einer Tabelle.
   ⚠️ `em`, nicht `px`: Die Breite muss mit der Schriftgröße mitwachsen, sonst
   ragt „Morgen" bei 150 % Systemschrift in die Symbolspalte. Anders als in
   einer Media-Query meint `em` hier die Schriftgröße DIESES Elements — genau
   das, was gebraucht wird. */
/* ⚠️ `min()` STATT EINER FESTEN BREITE — sonst sprengt die Spalte die Karte.
   Der erste Anlauf setzte die Breite fest, und `qa/wetter-design.mjs` meldete
   prompt: bei 3440 px und 24 px Systemschrift stehen die Tageskarten in mehreren
   Spalten, jede einzelne ist also SCHMAL, während 8,4em auf 202 px anwachsen.
   „Morgen05.08." ragte damit quer aus seiner Karte. Die Flucht der Spalten ist
   eine Wohltat, solange Platz da ist, und ein Fehler, sobald sie ihn erzwingt —
   deshalb gilt der Wunsch nur bis zu einem Anteil der Kartenbreite. */
.wx-tag-name {
  font-size: var(--fs-14); font-weight: 700; color: var(--ink);
  flex: 0 0 auto; min-width: min(4.8em, 38%);
}
.wx-tag-name small { display: block; font-size: var(--fs-12); font-weight: 400; color: var(--muted); }
@media (min-width: 700px) {
  .wx-tag-name small { display: inline; margin-left: 4px; }
  /* Name und Datum stehen hier nebeneinander — die Spalte braucht mehr. */
  .wx-tag-name { min-width: min(8.4em, 38%); }
}
.wx-tag-sym { width: 36px; height: 36px; }
@media (min-width: 700px) { .wx-tag-sym { width: 52px; height: 52px; } }

/* ── Info-Spalte: Wetterwort oben, darunter Regen + Einigkeit ──────────────
   Das ausgeschriebene Wetterwort (heiter/Regen …) sitzt direkt neben dem
   Symbol — das ist der „erste Blick", den der Betreiber wollte. Regenwert und
   Einigkeit stehen eine Zeile tiefer als ruhige Zusatzangaben. */
.wx-tag-info {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  flex: 1 1 auto; min-width: 0;
}
/* Nur die Kopfzeile hält den Platz für den Aufklapp-Pfeil frei (er liegt oben
   rechts, nur auf dem Handy). So kann der Kartenrand rundum gleich sein und die
   Spanne/Verlaufs-Kacheln darunter reichen bündig bis zum gleichen Rand. */
@media (max-width: 699px) { .wx-tag-info { margin-right: var(--sp-24); } }
@media (min-width: 700px) { .wx-tag-info { align-items: center; } }
.wx-tag-wort { font-size: var(--fs-14); font-weight: 700; color: var(--ink); white-space: nowrap; }
.wx-tag-zeile { display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap; min-width: 0; }
.wx-tag-regen { color: var(--acc); font-weight: 700; white-space: nowrap; font-size: var(--fs-12); }
/* ⚠️ Eigene Größe, nicht die des Browsers. `<small>` verkleinert von sich aus
   auf 0,8em — aus 14 px werden 11,25 px, und damit unterschreitet die Regenmenge
   die kleinste Größe, die diese Seite ausliefert (12 px, siehe die Tabelle in
   wetter.css). Ein `<small>` ohne eigene Größe erbt sich unter jede Grenze. */
.wx-tag-regen small {
  font-size: var(--fs-12); font-weight: 400; color: var(--muted); margin-left: 4px;
}

/* ── Tagesverlauf: früh / mittags / abends ─────────────────────────────────
   Drei kleine Kacheln in eigener, voller Zeile. Jede trägt Beschriftung, ein
   kleines Symbol und die Temperatur. Fehlen die Daten (ferner Tag, vergangene
   Abschnitte), liefert der Server `abschnitte` leer und die Zeile entfällt. */
/* 🚨 GLEICH BREITE SPALTEN, DIE DIE VOLLE BREITE FÜLLEN. Zweimal gemeldet: erst
   „nicht gleichmäßig aufgeteilt", dann „wenn nur zwei Karten da sind, sollen sie
   die Breite aufteilen, die da ist". `grid-auto-flow: column` + `grid-auto-columns:
   1fr` teilt die volle Breite in so viele gleiche Spalten, wie Abschnitte da sind
   — zwei → 50/50, drei → Drittel. Kein festes 3-Raster mit leerer Spalte mehr. */
.wx-tag-verlauf {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  flex: 1 1 100%; gap: var(--sp-6); width: 100%;
  margin-top: 2px;
}
.wx-tag-ab {
  min-width: 0; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: var(--sp-6) 2px;
  border-radius: var(--r-10); background: var(--soft);
  font-size: var(--fs-12);
}
/* ⚠️ `min-width: 0` + `overflow: hidden` an der Zelle sind kein Schmuck: Ohne
   sie gibt die nowrap-Beschriftung „mittags" der KARTE eine große Mindestbreite,
   und sobald das Detail-Panel die Rasterspalten auf sehr breiten Schirmen
   staucht (nur WebKit reflowt so), ragt der Verlauf quer aus der Karte
   (qa/wetter-design). Schrumpfbare Zellen senken die Mindestbreite der Karte;
   nur im äußersten Fall wird eine Beschriftung um ein, zwei Pixel geklemmt. */
.wx-tag-ab em {
  font-style: normal; color: var(--muted); font-size: var(--fs-12);
  white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.wx-tag-ab-sym { width: 24px; height: 24px; }
.wx-tag-ab-sym svg { width: 100%; height: 100%; display: block; }
.wx-tag-ab b { color: var(--ink); font-weight: 700; font-size: var(--fs-13); }

/* ── Die Tagesspanne ──────────────────────────────────────────────────────
   Tief, Balken, Höchstwert — EINE Zeile, auf jeder Bildschirmgröße. Alle sieben
   Balken teilen sich den Maßstab der ganzen Woche; damit beantwortet die Reihe
   „wird es wärmer oder kälter?" ohne dass man Zahlen vergleichen müsste.
   ⚠️ Auf dem Handy gab es den Balken vorher gar nicht — er hätte sich in eine
   wenige Pixel breite Rasterspalte gequetscht. Er hat jetzt eine eigene, und
   zwar die einzige, die wächst. */
.wx-tag-spanne {
  display: flex; align-items: center; gap: var(--sp-8); min-width: 0;
  font-size: var(--fs-16);
  /* ⚠️ AUF DEM HANDY IMMER EINE EIGENE ZEILE, nicht „je nachdem, ob es passt".
     Mit einer Wunschbreite entschied die Breite der Zahlen über den Umbruch —
     und das Ladeskelett hat andere Zahlen als der Inhalt: In Firefox passte das
     Skelett in eine Zeile und der fertige Inhalt nicht, die Kartenreihe wuchs
     beim Eintreffen der Daten um 33 px (Chromium und WebKit brachen in beiden
     Fällen um, dort fiel es nicht auf). Ein Umbruch, der vom Zahlenwert abhängt,
     ist keine Gestaltung, sondern ein Zufall.
     Zwei feste Zeilen sind ohnehin die bessere Aufteilung: Der Temperaturbalken
     bekommt die volle Breite und lässt sich damit überhaupt erst ablesen. */
  flex: 1 1 100%;
}
.wx-tag-name, .wx-tag-sym { flex: 0 0 auto; }
@media (min-width: 700px) {
  .wx-tag-spanne { width: 100%; flex: 0 0 auto; }
  /* Auf breiten Karten stehen Info-Spalte und Verlauf unter dem Symbol und
     füllen die Kartenbreite — `min-width: 0`, damit sie sie nie sprengen. */
  .wx-tag-info { width: 100%; min-width: 0; overflow: hidden; }
  .wx-tag-verlauf { width: 100%; min-width: 0; }
}
.wx-tag-min { color: var(--muted); white-space: nowrap; }
.wx-tag-max { color: var(--ink); font-weight: 700; white-space: nowrap; }
.wx-tag-leer { color: var(--muted); font-size: var(--fs-13); }

.wx-tag-bar {
  position: relative; flex: 1 1 auto; min-width: 24px; height: 5px;
  border-radius: var(--r-pill); background: var(--soft);
  box-shadow: var(--sh-saum);
}
.wx-tag-bar i {
  position: absolute; top: 0; bottom: 0; border-radius: inherit;
  background: linear-gradient(90deg, #4da3ff, #ffb347);
}

/* ⚠️ Der Pfeil liegt ABSOLUT am rechten Rand. Als Flex-Kind würde er beim
   Umbruch mit in die zweite Zeile rutschen und dort unter der Temperaturspanne
   landen — ein Aufklapp-Pfeil, der je nach Schriftgröße die Zeile wechselt.
   Sein Platz ist über `padding-right` an der Karte freigehalten. */
/* 🚨 OBEN RECHTS, mit demselben Abstand wie links. Gemeldet: „Der Toggle sollte
   oben rechts sein und der Abstand gleichmäßig wie links." Vorher lag der Pfeil
   über die volle Höhe zentriert (`top:0; bottom:0`) und klebte mit nur 6 px am
   rechten Rand — während der Inhalt links 12 px Abstand hat. Jetzt sitzt er in
   der oberen rechten Ecke mit `var(--sp-12)` zu Kante und Deckel, genau wie der
   Inhalt links. */
.wx-tag-pfeil {
  position: absolute; top: var(--sp-12); right: var(--sp-12); bottom: auto;
  color: var(--muted); display: grid; place-items: center; line-height: 0;
  transition: color var(--mo-kurz) var(--ease-standard);
}
.wx-tag-pfeil svg {
  width: 18px; height: 18px;
  transition: transform var(--mo-mittel) var(--ease-standard);
}
@media (hover: hover) and (pointer: fine) {
  .wx-tag:hover .wx-tag-pfeil { color: var(--body); }
}
.wx-tag[aria-expanded="true"] .wx-tag-pfeil { color: var(--acc); }
.wx-tag[aria-expanded="true"] .wx-tag-pfeil svg { transform: rotate(180deg); }
/* Ab Tablet ist die ganze Kachel sichtbar ein Knopf; ein Pfeil in der Mitte
   einer zentrierten Kachel wäre ein Fremdkörper. */
@media (min-width: 700px) { .wx-tag-pfeil { display: none; } }

/* Tag ohne Daten — die Woche wird NICHT stillschweigend verkürzt. */
.wx-tag.ist-leer { opacity: .55; cursor: default; }
@media (hover: hover) and (pointer: fine) {
  .wx-tag.ist-leer:hover { background: var(--flaeche); }
}

/* ── Detail-Panel: Hülle und Zwischenzustände ─────────────────────────────
   ⚠️ Diese wenigen Regeln stehen bewusst HIER und nicht in details.css: Das
   Panel-Stylesheet wird erst beim ersten Aufklappen nachgeladen (zusammen mit
   ui-details.js — zusammen rund 24 kB, die niemand braucht, der nie einen Tag
   öffnet). Container, Ladehinweis und Fehlerfläche müssen aber schon stehen,
   BEVOR das Nachgeladene da ist, sonst blitzt für einen Moment ungestaltetes
   Markup auf. */
.wx-detail {
  grid-column: 1 / -1;            /* volle Breite unter der zugehörigen Karte */
  /* 🚨 min-width:0 ist PFLICHT. Als Rasterkind hat das Panel `min-width:auto`,
     also die MIN-CONTENT-Breite seines Inhalts — und das waagerecht rollende
     Stundenband (24 Spalten) ist ~960 px breit. Ohne diese Zeile bläht sich das
     Panel auf die Bandbreite auf und schiebt die ganze Seite waagerecht über den
     Rand (gemeldet auf WebKit: 977 > 412). Mit min-width:0 bleibt es spaltenbreit
     und das Band rollt in seinem eigenen overflow-x. */
  min-width: 0;
  border-radius: var(--r-14);
  background: var(--flaeche);
  box-shadow: var(--sh-2), var(--sh-saum);
  overflow: hidden;
}
.wx-detail[hidden] { display: none; }
.wx-detail-laedt { padding: var(--sp-24); text-align: center; color: var(--muted); font-size: var(--fs-13); }
.wx-detail-fehler { padding: var(--sp-16); color: var(--schlecht); font-size: var(--fs-13); }

/* ⚠️ Im DOM steht das Panel direkt HINTER seiner Karte — das ist für Screen-
   reader und die Tabulator-Reihenfolge richtig, und auf dem Handy (eine Spalte)
   erscheint es damit genau unter der angetippten Zeile.
   Auf dem Desktop wäre genau das aber falsch: Ein Rasterkind über alle sieben
   Spalten passt nicht mehr in die angefangene Zeile, rutscht in die nächste —
   und die erste Zeile bleibt mit vier von sieben Karten halb leer stehen (so
   gesehen, als Do angetippt war).
   `order` löst beides auf einmal: Die Platzierung im Raster folgt `order`, die
   Vorlese- und Tabulator-Reihenfolge weiter dem DOM. Das Panel landet also
   optisch unter der VOLLSTÄNDIGEN Kartenreihe, ohne dass es im DOM wandert. */
@media (min-width: 700px) {
  .wx-tag { order: 0; }
  .wx-detail { order: 1; }
}
