/* ============================================================
   sAIrmo · Muster — das gemeinsame Formenvokabular der Kunden-App
   ------------------------------------------------------------
   Wozu diese Datei da ist: Spur 1 („Post erstellen", 11.09.2026) hat die Formen
   erfunden, mit denen eine Arbeitsseite bei 1440 x 900 ohne Scrollen auskommt —
   aber sie seitenspezifisch benannt (`.gen-*`, von „generate"). Jede weitere
   Spur haette sich daraufhin ihre eigenen gebaut, und am Ende haette die App
   fuenf Dialekte gesprochen. Hier stehen dieselben Formen unter einem Namen, der
   keiner Seite gehoert: `.ui-*`.

   ⚠️ **Diese Datei gehoert Spur 0 (UI-Fundament).** Andere Spuren BENUTZEN die
   Muster und aendern sie nicht — wer hier etwas dreht, dreht es fuer jede Seite
   der App mit. Was nur zu einer Seite gehoert, bleibt in `app.css` und traegt
   weiter den Seitennamen. Die Faustregel: Wuerde eine zweite Seite dieselbe Regel
   wollen, gehoert sie hierher; sonst nicht.

   ⚠️ **Nicht umbenannt wurden die `data-gen-*`-Attribute.** Die sind keine Form,
   sondern die Verdrahtung von `generate-seite.js` an seine eigene Seite — und die
   Waechter unter `bin/` greifen sie. Ein Klassenname ist ein Stil, ein
   Daten-Attribut ist ein Griff; nur die Stile sind hier allgemein geworden.

   Ladereihenfolge: NACH `app.css` waere falsch — eine Seite muss ein Muster
   ueberschreiben koennen. Deshalb steht diese Datei in `layout.php` VOR `app.css`.

   Probe und Waechter: `bin/muster/muster-probe.html`, `bin/muster/muster-pruefen.js`.
   ============================================================ */

/* ---- Die Kopfzeile einer Arbeitsseite ----------------------------------
   Drei Felder in einer Zeile: links der Rueckweg und der Titel, in der Mitte
   ein Umschalter (falls die Seite einen hat), rechts die Auskunft ueber
   Stufe und Guthaben. Der zentrierte Kopf mit Eyebrow und Untertitel aus
   `_app_pageheader.php` kostete allein ueber 200 px — auf einer Seite, die
   insgesamt 900 haben darf, ist das ein Viertel. */
.ui-kopf {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 1rem;
    margin: 0 0 1rem;
}
.ui-kopf .page-back { font-size: .9rem; }
.ui-kopf h1 { font-size: 1.45rem; line-height: 1.1; margin: .15rem 0 0; }
.ui-kopf-rechts {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: .3rem;
    text-align: right;
    font-size: .85rem;
    color: var(--text-muted);
}
.ui-kopf-rechts strong { color: var(--petrol); }
/* Ein Umschalter in der Mitte bringt seine eigenen Farben mit (die Seite setzt
   sie beim Wechsel); hier wird ihm nur der Platz zugewiesen. */
.ui-kopf [role="tablist"] { margin: 0 !important; }

/* ---- Die Stufen-Pille --------------------------------------------------
   Dieselbe Auskunft wie „Wie viel wir dir abnehmen" auf der Gedächtnis-Seite, nur
   in einer Zeile. Drei Punkte, der erreichte in Apricot; die Punkte sind ein
   Weg, keine Liste — deshalb der Strich dazwischen. */
.ui-stufe {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    text-decoration: none;
    color: var(--text-muted);
    font-size: .82rem;
    border: 1px solid var(--sand);
    border-radius: 999px;
    padding: .25rem .75rem .25rem .55rem;
    background: #fff;
}
.ui-stufe:hover { border-color: var(--border-button); }
.ui-stufe strong { color: var(--petrol); font-weight: 600; }
.ui-stufe .punkte { display: inline-flex; align-items: center; }
.ui-stufe .punkte i {
    width: .5rem; height: .5rem; border-radius: 50%;
    background: var(--kiesel); display: block; position: relative;
}
.ui-stufe .punkte i + i { margin-left: .55rem; }
.ui-stufe .punkte i + i::before {
    content: ""; position: absolute; right: .5rem; top: 50%;
    width: .55rem; height: 2px; background: var(--kiesel); transform: translateY(-1px);
}
.ui-stufe .punkte i.an { background: var(--apricot); outline: 2px solid var(--apricot); outline-offset: 1px; }

/* ---- Der Zwei-Spalten-Rumpf -------------------------------------------
   Links die dunkle Karte mit dem, was der Kunde schreibt; rechts das, was er
   waehlt. Nebeneinander statt untereinander ist der groesste einzelne Gewinn
   an Hoehe, den eine Arbeitsseite machen kann. */
.ui-spalten {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    align-items: stretch;
}
.ui-spalten > .card { margin-bottom: 0; }
/* Die dunkle Karte streckt ihr Textfeld auf die Hoehe der rechten Karte — sonst
   steht links Luft, waehrend rechts die Wahl bis nach unten reicht. */
.ui-spalten > .card-inverse { display: flex; flex-direction: column; }
.ui-spalten > .card-inverse > div:last-child { flex: 1 1 auto; display: flex; flex-direction: column; }
.ui-spalten > .card-inverse > div:last-child textarea { flex: 1 1 auto; min-height: 7rem; resize: none; }

/* ---- Chip-Gruppen mit Zustandsbeschriftung -----------------------------
   ⚠️ **Ein Chip nennt seinen ZUSTAND, nicht sich selbst.** „Symbole & Hashtags ·
   Hashtags + KI-Hinweis" war doppelt gemoppelt (Florian, 11.09.2026). Steht
   etwas an, nennt der Chip WAS ansteht; steht nichts an, nennt er das Angebot.
   Ein Chip, der nichts bewirken kann, ist gesperrt und sagt warum. */
.ui-chip-gruppen {
    display: flex; flex-direction: column; align-items: flex-start; gap: .55rem;
    margin-top: auto; padding-top: .9rem; border-top: 1px solid var(--sand);
}
.ui-chip-gruppe { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.ui-chip {
    display: inline-flex; align-items: center; gap: .45rem;
    border: 1px solid var(--border-button); background: #fff; color: var(--petrol);
    border-radius: 999px; padding: .45rem 1rem;
    font: inherit; font-size: .9rem; font-weight: 500; cursor: pointer; white-space: nowrap;
}
.ui-chip .dot { width: .55rem; height: .55rem; border-radius: 999px; background: var(--kiesel); flex: 0 0 auto; }
.ui-chip[data-on="1"] { background: var(--petrol); color: #fff; border-color: var(--petrol); }
.ui-chip[data-on="1"] .dot { background: var(--apricot); }
.ui-chip .zahl { font-weight: 400; opacity: .8; }
.ui-chip[disabled] { opacity: .5; cursor: not-allowed; }

/* ---- Beschriftung und Segment-Umschalter -------------------------------
   Eine Zeile „Was: [dies][das]". Die Beschriftung hat eine Mindestbreite,
   damit mehrere solche Zeilen untereinander eine Kante bilden. */
.ui-lbl { font-size: .85rem; color: var(--text-muted); min-width: 5.2rem; }
.ui-seg {
    display: inline-flex; border: 1px solid var(--border-field);
    border-radius: 8px; overflow: hidden;
}
.ui-seg button {
    border: 0; background: #fff; padding: .35rem .75rem;
    font: inherit; font-size: .85rem; color: var(--petrol); cursor: pointer;
}
.ui-seg button[aria-pressed="true"] { background: var(--petrol); color: #fff; font-weight: 600; }
.ui-seg button[disabled] { color: var(--kiesel); background: var(--stein); cursor: not-allowed; }

/* ---- Kleinteile: Zeile, Hinweis, Aktionsreihe -------------------------- */
.ui-zeile { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; margin-top: .45rem; }
.ui-hinweis { font-size: .78rem; font-style: italic; color: var(--text-muted); }
.ui-aktion { display: flex; align-items: center; gap: 1rem; margin: .6rem 0 0; flex-wrap: wrap; }

/* ---- Die Fensterkarte --------------------------------------------------
   Eine Karte, die vorher auf der Seite stand und jetzt in einem Fenster sitzt,
   legt ihren eigenen Rahmen ab — den bringt das Fenster mit. Ohne das sieht man
   zwei Kaesten ineinander.

   ⚠️ **`body.theme-app` davor ist kein Zierrat, sondern der ganze Punkt.** Die
   Regel hiess bis zum 12.09.2026 `.fenster .gen-fenster-karte` (0,2,0) und
   verlor gegen `body.theme-app .card` in app.css (0,2,1) — sie hat also seit
   ihrem ersten Tag NICHTS getan, und im Layout-Fenster von „Post erstellen"
   stand ein Kasten im Kasten (gemessen 12.09.2026: padding 28px, border 1px,
   obwohl beides auf 0 stehen sollte). Aufgefallen ist es erst, als es einen
   Waechter dafuer gab. **Eine Regel, die keiner misst, kann auch einfach nicht
   wirken** — und sieht dabei genauso aus wie eine, die wirkt. */
body.theme-app .fenster .ui-fenster-karte { padding: 0; border: 0; box-shadow: none; background: transparent; margin: 0; }

/* ---- Die Liste mit eigenem Scrollbereich -------------------------------
   Fuer Posts, Feed und Kalender. **Hier gilt der Rahmen, nicht der Inhalt:**
   Kopf und Filter stehen fest, gescrollt wird nur die Liste, und zwar in ihrem
   eigenen Bereich. Wer 28 Posts auf einen Bildschirm quetscht, hat die Aufgabe
   falsch verstanden (Papier Paragraf 3, Abnahmepunkt 2).

   **Die Hoehe kommt von der Seite, nicht von hier.** Wie viel ueber der Liste
   steht, weiss nur die Seite; sie sagt es ueber `--ui-liste-oben` (Vorgabe
   18rem — Kopf, Filterzeile und die Polster von `main`). Die Vorgabe ist
   bewusst grosszuegig: Lieber scrollt die Liste einmal zu frueh in sich selbst,
   als dass sie die Seite aufblaeht.

   **Was wirklich traegt — gemessen, nicht behauptet (12.09.2026):** Hier stand
   zuerst, `min-height: 0` sei das Entscheidende, weil ein Flex-Kind sonst auf
   seine Inhaltshoehe wachse. Die Gegenprobe hat das widerlegt: Nimmt man die
   Zeile heraus, aendert sich **nichts** — fuer einen Scroll-Container ist die
   automatische Mindesthoehe ohnehin null. Rot wird der Waechter bei den zwei
   Eigenschaften, die es wirklich ausmachen:

     `max-height` am `.ui-liste`   ohne sie waechst die Arbeitsflaeche von
                                   2841 px auf 13479 px (240 Eintraege)
     `overflow-y` am Rollbereich   ohne sie ist der letzte Eintrag abgeschnitten
                                   und nicht mehr erreichbar

   `min-height: 0` bleibt trotzdem stehen: Es kostet nichts und faengt den Fall
   ab, dass jemand spaeter `overflow` aendert. Aber es ist die Absicherung, nicht
   der Mechanismus — und ein Kommentar, der das Falsche als Grund nennt, schickt
   den naechsten Leser in die falsche Richtung.

   ⚠️ **`overscroll-behavior: contain`**, sonst scrollt eine Wischgeste am Ende
   der Liste die Seite dahinter weiter (Scroll-Chaining) — am Handy die
   haeufigste Ursache dafuer, dass man beim Lesen die Seite verliert. */
.ui-liste {
    display: flex;
    flex-direction: column;
    min-height: 0;
    max-height: calc(100dvh - var(--ui-liste-oben, 18rem));
}
.ui-liste-kopf,
.ui-liste-filter { flex: 0 0 auto; }
.ui-liste-filter { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: 0 0 .75rem; }
.ui-liste-rollen {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Ein abgeschnittener letzter Eintrag sagt „hier geht es weiter" — eine
       Liste, die genau auf der Kante endet, sieht vollstaendig aus. */
    padding-bottom: .25rem;
}
/* Am Handy scrollt die Seite selbst; eine Liste mit eigenem Bereich waere dort
   ein Fenster im Fenster und nimmt dem Daumen den langen Weg. */
@media (max-width: 720px) {
    .ui-liste { max-height: none; }
    .ui-liste-rollen { overflow-y: visible; }
}

/* ---- Schmale Fenster --------------------------------------------------- */
@media (max-width: 900px) {
    .ui-kopf { grid-template-columns: 1fr; }
    .ui-kopf .ui-kopf-rechts { align-items: flex-start; text-align: left; }
    .ui-spalten { grid-template-columns: 1fr; }
}
