/*
 * Gestaltung der ausgelieferten Seiten.
 *
 * Eigenes, bewusst schlichtes Kundenlogin-Layout. Bootstrap 5 bleibt der
 * Frontend-Stack fuer den vollstaendigen Kunden- und Adminbereich; diese erste
 * Scheibe braucht keine JavaScript-Komponenten und bindet deshalb noch kein
 * ausfuehrbares Frontend-Paket ein.
 *
 * Diese Datei existiert ueberhaupt nur, weil die Content-Security-Policy kein
 * 'unsafe-inline' erlaubt (siehe SecurityHeaders): ein style-Attribut in einer
 * Vorlage wuerde vom Browser verworfen. Gestaltung gehoert deshalb hierher.
 *
 * Keine externen Schriften. default-src 'self' laesst sie ohnehin nicht durch,
 * und eine Schrift von einem fremden Server verraet jedem Aufruf, wer sich
 * gerade anmeldet.
 *
 * Ausgeliefert wird die Datei vom Webserver, nicht von der Anwendung. Wer
 * /assets/ auf public/index.php leitet, bekommt hier eine 404.
 */

:root {
    --schrift: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --grund: #f5f7fa;
    --flaeche: #ffffff;
    --linie: #d9e1e8;
    --text: #141414;
    --text-leise: #53616d;
    /*
     * Die Hausfarbe #4382c3 bleibt unveraendert — sie ist die Marke.
     * Geaendert hat sich nur ihre Rolle: mit 4,0:1 auf Weiss und 3,8:1
     * auf --grund liegt sie ueber der 3:1-Grenze fuer Rahmen, Symbole
     * und Flaechen (WCAG 1.4.11), aber unter den 4,5:1, die Text
     * verlangt (1.4.3). Sie traegt deshalb weiterhin jeden Rahmen, jedes
     * Symbol und jede rein grafische Flaeche, aber keinen kleinen Text
     * mehr — weder als Schriftfarbe noch als Flaeche unter weisser
     * Schrift. Dort steht --akzent-dunkel (5,9:1), im Zeigezustand
     * darunter --akzent-tief. Derselbe Weg wie in admin.css, wo die
     * Aufteilung bereits so steht.
     */
    --akzent: #4382c3;
    --akzent-dunkel: #31679e;
    --akzent-tief: #24507d;
    --warnung: #d78b20;
    --fehler: #a3261f;
    --fehler-grund: #fdeceb;
    --erfolg: #176638;
    --erfolg-grund: #eaf7ef;
    --hinweis-grund: #eaf2fb;
    --hinweis-grund-dunkel: #d7e7f7;
    --radius: 6px;
}

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

body {
    margin: 0;
    background: var(--grund);
    color: var(--text);
    font-family: var(--schrift);
    font-size: 16px;
    line-height: 1.5;
}

.jaba-kundenlogin-inhalt {
    width: min(76rem, calc(100% - 2rem));
    min-height: 28rem;
    margin: 0 auto;
    padding: 3rem 0 4rem;
}

/* Global site chrome ---------------------------------------------------- */

.seitenleiste {
    background: var(--flaeche);
    box-shadow: 0 1px 0 rgb(20 20 20 / 8%);
}

.markenzeile,
.produktnavigation,
.seitenfuss-inhalt,
.seitenfuss-unten {
    width: min(76rem, calc(100% - 2rem));
    margin: 0 auto;
}

.markenzeile {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 5.25rem;
    gap: 1rem;
}

.wortmarke {
    display: inline-flex;
    align-items: baseline;
    color: var(--text);
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: -0.055em;
    text-decoration: none;
}

.wortmarke span {
    color: var(--akzent);
}

.wortmarke small {
    font-size: 0.76em;
    font-weight: 600;
    letter-spacing: -0.04em;
}

.kundenlogin-link {
    min-height: 2.75rem;
    display: inline-flex;
    align-items: center;
    padding: 0.625rem 1rem;
    border: 1px solid var(--akzent);
    color: var(--akzent-dunkel);
    font-weight: 700;
    text-decoration: none;
}

.kundenlogin-link:hover,
.kundenlogin-link:focus-visible {
    background: var(--akzent-dunkel);
    color: #fff;
}

.produktnavigation {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
}

.produktnavigation a {
    min-height: 3rem;
    display: inline-flex;
    align-items: center;
    padding: 0.625rem 1rem;
    border-left: 1px solid rgb(20 20 20 / 8%);
    color: #fff;
    background: var(--akzent-dunkel);
    font-size: 0.875rem;
    font-weight: 700;
    text-decoration: none;
}

.produktnavigation a:hover,
.produktnavigation a:focus-visible {
    background: var(--akzent-tief);
}

.seite {
    max-width: 76rem;
    margin: 0 auto;
    padding: 3rem 1rem 4rem;
}

.seitenfuss {
    background: #17232d;
    color: #dce5ec;
}

.seitenfuss-inhalt {
    display: grid;
    grid-template-columns: minmax(15rem, 2fr) repeat(2, minmax(10rem, 1fr));
    gap: 2rem;
    padding: 3rem 0;
}

.seitenfuss .wortmarke {
    color: #fff;
}

.seitenfuss p {
    max-width: 20rem;
    margin: 0.75rem 0 0;
    color: #b5c3cd;
}

.seitenfuss h2 {
    margin-bottom: 0.75rem;
    color: #fff;
    font-size: 0.875rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

.seitenfuss nav {
    display: grid;
    align-content: start;
    gap: 0.5rem;
}

.seitenfuss a {
    color: #dce5ec;
    text-decoration: none;
}

.seitenfuss a:hover,
.seitenfuss a:focus-visible {
    color: #fff;
    text-decoration: underline;
}

.seitenfuss-unten {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 1rem 0;
    border-top: 1px solid rgb(255 255 255 / 16%);
    color: #b5c3cd;
    font-size: 0.8125rem;
}

.karte {
    background: var(--flaeche);
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    padding: 1.75rem;
}

.karte-anmeldung,
.formular-karte {
    max-width: 40rem;
    margin-right: auto;
    margin-left: auto;
}

/* Dieselbe Breite wie der Rest des Ticketsystems (.nachricht, .antwortbereich
   weiter unten) statt der generischen 40rem eines einzelnen Formulars —
   sonst wirkt ausgerechnet "Ticket öffnen" schmaler als jedes Ticket danach. */
.ticket-formular-karte {
    max-width: 52rem;
}

.karte-anmeldung {
    max-width: 26rem;
}

.fehlerseite {
    max-width: 32rem;
    margin: 3rem auto;
    padding: 3rem 2rem;
    text-align: center;
}

.fehlerseite-symbol {
    display: block;
    margin-bottom: 1rem;
    color: var(--akzent);
    font-size: 3rem;
}

.fehlerseite .uebertitel {
    margin-bottom: 0.5rem;
}

.fehlerseite p {
    color: var(--text-leise);
}

.fehlerseite-aktionen {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.75rem;
    margin-top: 1.5rem;
}

h1 {
    margin: 0 0 1.25rem;
    font-size: 1.375rem;
    font-weight: 600;
}

h2 {
    margin: 0 0 0.75rem;
    font-size: 1.125rem;
}

a {
    color: var(--akzent-dunkel);
}

.seitenkopf,
.ticketkopf {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.ticketkopf h1,
.seitenkopf h1 {
    margin-bottom: 0;
}

.uebertitel,
.referenz,
.metadaten {
    margin: 0 0 0.25rem;
    color: var(--text-leise);
    font-size: 0.8125rem;
}

.uebertitel,
.referenz {
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.zurueck {
    margin-bottom: 1rem;
}

/* --- Navigation --------------------------------------------------------- */

.hauptnavigation {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 2rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--linie);
}

.hauptnavigation ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.hauptnavigation a {
    display: inline-block;
    min-height: 44px;
    padding: 0.625rem 0;
    color: var(--text-leise);
    font-weight: 600;
    text-decoration: none;
}

.hauptnavigation a:hover {
    color: var(--text);
}

/* Die aktuelle Seite traegt aria-current="page". Kein zweites Kennzeichen in
   einer Klasse: eine Auszeichnung, die Screenreader und Auge gemeinsam lesen,
   kann nicht auseinanderlaufen. */
.hauptnavigation a[aria-current="page"] {
    color: var(--akzent-dunkel);
    box-shadow: inset 0 -2px 0 var(--akzent);
}

.kunden-navigation-dropdown {
    position: relative;
    z-index: 10;
}

.kunden-navigation-dropdown summary {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    padding: 0.625rem 0.75rem;
    color: var(--text);
    cursor: pointer;
    font-weight: 600;
    list-style: none;
}

.kunden-navigation-dropdown summary:hover,
.kunden-navigation-dropdown details[open] > summary {
    background: var(--hinweis-grund);
    color: var(--akzent-dunkel);
}

.kunden-navigation-dropdown summary::-webkit-details-marker {
    display: none;
}

.kunden-navigation-dropdown details > ul {
    position: absolute;
    z-index: 2;
    top: 100%;
    left: 0;
    display: block;
    min-width: 14rem;
    padding: 0;
    border: 1px solid var(--linie);
    background: var(--hinweis-grund);
    box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 12%);
}

.kunden-navigation-dropdown details > ul a {
    display: block;
    min-height: 44px;
    padding: 0.7rem 0.9rem;
    color: var(--text);
}

.kunden-navigation-dropdown details > ul a:hover,
.kunden-navigation-dropdown details > ul a:focus-visible {
    background: var(--hinweis-grund-dunkel);
    color: var(--akzent-dunkel);
}

.ticketliste td form {
    display: inline-block;
    margin: 0 0.25rem 0.25rem 0;
}

/* Der Mitarbeiterbereich sieht anders aus als das Kundenlogin. Wer beides
   gleichzeitig offen hat, soll auf einen Blick sehen, wo er gerade klickt. */
.hauptnavigation.verwaltung {
    border-bottom: 3px solid var(--akzent-dunkel);
}

.angemeldet {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.angemeldet .metadaten {
    margin: 0;
    white-space: nowrap;
}

.abmelden button {
    min-height: 44px;
    padding: 0.5rem 0.875rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: var(--text);
    font: inherit;
    cursor: pointer;
}

.abmelden button:hover {
    background: var(--grund);
}

.abmelden button:focus-visible,
.hauptnavigation a:focus-visible {
    outline: 2px solid var(--akzent);
    outline-offset: 2px;
}

/* --- Kennzahlen und Abschnitte ------------------------------------------ */

.kennzahlen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 1rem;
    margin-bottom: 2rem;
}

.kennzahl {
    display: block;
    padding: 1.25rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: inherit;
    text-decoration: none;
}

.kennzahl:hover {
    border-color: var(--akzent);
}

.kennzahl-wert {
    display: block;
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.2;
}

.kennzahlen-kompakt .kennzahl-wert {
    font-size: 1.25rem;
}

.kennzahlen-kompakt .kennzahl-name {
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.kennzahl-name {
    display: block;
    color: var(--text-leise);
    font-size: 0.875rem;
}

.kennzahl-zusatz {
    display: block;
    margin-top: 0.25rem;
    color: var(--akzent-dunkel);
    font-size: 0.875rem;
    font-weight: 600;
}

.abschnitt {
    margin-top: 2rem;
}

/* --- Hosting-Verwaltung: Kachelnavigation und Eintragskarten ------------ */

.hosting-kacheln {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: 0.875rem;
    margin: 1.5rem 0 2rem;
    padding: 0;
    list-style: none;
}

.hosting-kachel {
    display: flex;
    position: relative;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 1.25rem 0.75rem 1rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: var(--text);
    font-weight: 600;
    text-align: center;
    text-decoration: none;
}

.hosting-kachel:hover {
    border-color: var(--akzent);
    background: var(--hinweis-grund);
}

.hosting-kachel[aria-current="page"] {
    border-color: var(--akzent);
    box-shadow: inset 0 0 0 1px var(--akzent);
}

.hosting-kachel i {
    color: var(--akzent);
    font-size: 1.5rem;
}

.hosting-kachel span {
    font-size: 0.875rem;
}

.hosting-kachel .hosting-kachel-anzahl {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    min-width: 1.25rem;
    padding: 0.05rem 0.375rem;
    border-radius: 999px;
    background: var(--akzent-dunkel);
    color: #ffffff;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.25rem;
    text-align: center;
}

.hosting-kachel.hosting-kachel-extern i {
    color: var(--text-leise);
}

.abschnittkopf {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin-bottom: 0.75rem;
}

.abschnittkopf i {
    color: var(--akzent);
    font-size: 1.125rem;
}

.abschnittkopf h2 {
    margin: 0;
}

/* --- Addons auf der Vertragsseite --------------------------------------- */

/* Gebuchte und buchbare Addons stehen in einem Abschnitt und sind trotzdem
   ohne Lesen zu unterscheiden: die gebuchte Kachel ist geschlossen, die
   buchbare gestrichelt. Vorher trugen beide dieselbe Zeile -- der eine
   Abschnitt kuendigte, der andere bestellte, und sie sahen gleich aus. */

.addon-abschnittkopf {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.25rem;
}

.addon-abschnittkopf h2 {
    margin: 0;
}

/* Zweite Ueberschrift im selben Abschnitt: dieselbe Zeile, aber leiser --
   sie teilt den Abschnitt, statt einen neuen aufzumachen. Die CSP laesst
   kein style-Attribut zu, deshalb eine Klasse. */
.addon-abschnittkopf-zweit {
    margin-top: 1.75rem;
}

.addon-abschnittkopf-zweit h2 {
    font-size: 1rem;
}

.addon-zaehler {
    color: var(--text-leise);
    font-size: 0.8125rem;
    white-space: nowrap;
}

.addon-kacheln {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: 0.875rem;
    margin: 0.875rem 0 0;
    padding: 0;
    list-style: none;
}

.addon-kachel {
    display: flex;
    position: relative;
    flex-direction: column;
    gap: 0.625rem;
    padding: 1rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
}

.addon-kachel-kopf {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
}

.addon-kachel-zeichen {
    display: inline-flex;
    width: 2.25rem;
    height: 2.25rem;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--hinweis-grund);
    color: var(--akzent);
    font-size: 1rem;
}

/* Menge und Zustand koennen zusammen auftreten (ein gekuendigtes Addon mit
   Stueckzahl). Beide in eine Zeile rechts oben, statt den Zustand in den
   Namen zu haengen, wo er ihn umbricht. */
.addon-kachel-marken {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.375rem;
}

.addon-kachel-menge {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    border-radius: 999px;
    background: var(--hinweis-grund-dunkel);
    color: #17497f;
    font-size: 0.75rem;
    font-weight: 700;
    white-space: nowrap;
}

.addon-kachel-name {
    margin: 0;
    font-size: 0.9375rem;
    font-weight: 600;
    line-height: 1.35;
}

.addon-kachel-text {
    margin: 0;
    color: var(--text-leise);
    font-size: 0.8125rem;
    line-height: 1.45;
}

/* Der Betrag, der wirklich auf der Rechnung steht, ist die groesste Zahl in
   der Kachel; alles daneben klein und leise. Vorher lief er durch
   `.referenz` und stand deshalb in Versalien -- der Auszeichnung, die sonst
   eine Rubrik markiert. */
.addon-kachel-preis {
    margin: 0;
    color: var(--text);
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1.2;
}

.addon-kachel-preis .addon-kachel-zyklus {
    color: var(--text-leise);
    font-size: 0.8125rem;
    font-weight: 400;
}

.addon-kachel-rechnung {
    margin: 0.125rem 0 0;
    color: var(--text-leise);
    font-size: 0.75rem;
}

.addon-kachel-rechnung:empty {
    display: none;
}

/* Gestrichelt, weil es hier noch nichts gibt -- der Unterschied zum
   gebuchten Addon muss ohne Lesen erkennbar sein. */
.addon-kachel-buchbar {
    border-style: dashed;
    background: var(--grund);
}

.addon-kachel-buchbar .addon-kachel-zeichen {
    border: 1px solid var(--linie);
    background: var(--flaeche);
    color: var(--text-leise);
}

.addon-kachel-buchbar:hover,
.addon-kachel-buchbar:focus-within {
    border-style: solid;
    border-color: var(--akzent);
    background: var(--flaeche);
}

/* Zwei Preise, die Verschiedenes messen: der eine wird heute berechnet, der
   andere jede Periode. Untereinander mit Bezeichnung, weil ein
   "3,27 · 12,00" niemandem sagt, welcher welcher ist. */
.addon-preisliste {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.25rem 0.75rem;
    margin: 0;
    padding: 0.625rem 0 0;
    border-top: 1px solid var(--linie);
}

.addon-preisliste dt {
    color: var(--text-leise);
    font-size: 0.8125rem;
}

.addon-preisliste dd {
    margin: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    text-align: right;
    white-space: nowrap;
}

.addon-preisliste .addon-preis-jetzt {
    color: var(--text);
    font-size: 0.9375rem;
    font-weight: 700;
}

.addon-kachel-fuss {
    margin-top: auto;
    padding-top: 0.25rem;
}

.addon-kachel-fuss .formular {
    margin: 0;
}

.addon-kachel-fuss .formular button {
    width: 100%;
    margin-top: 0;
}

/* Die Kuendigung eines einzelnen Addons ist nicht das, wofuer jemand diese
   Seite aufruft. Sie bleibt erreichbar, aber zugeklappt: ein <details>
   braucht kein JavaScript und ist serverseitig schon zu, bevor ein Skript
   laeuft -- dieselbe Loesung wie bei der einklappbaren Seitenleiste.
   Vorher stand der ganze Bestaetigungssatz offen auf jeder Zeile und
   draengte den Namen des Addons an den Rand. */
.addon-kuendigung {
    margin-top: auto;
    padding-top: 0.625rem;
    border-top: 1px solid var(--linie);
}

.addon-kuendigung > summary {
    color: var(--text-leise);
    font-size: 0.8125rem;
    list-style-position: inside;
    cursor: pointer;
}

.addon-kuendigung > summary:hover {
    color: var(--text);
}

.addon-kuendigung .formular {
    margin: 0.5rem 0 0;
}

.addon-kuendigung .ankreuzfeld {
    align-items: flex-start;
    min-height: 0;
    font-size: 0.8125rem;
    line-height: 1.4;
}

/* Eine Kuendigung ist nicht die Haupthandlung dieser Kachel und darf nicht
   wie eine aussehen. */
.addon-kuendigung .formular button {
    width: 100%;
    border: 1px solid var(--linie);
    background: var(--flaeche);
    color: var(--text);
    font-size: 0.8125rem;
}

.addon-kuendigung .formular button:hover {
    background: var(--grund);
}

/* Gekuendigt heisst: laeuft noch, endet aber. Der Zustand gehoert nach oben
   als Plakette, nicht als weitere Zeile unter den Preis, wo er wie eine
   Preisangabe aussieht. */
.addon-kachel-gekuendigt {
    background: var(--grund);
}

.addon-kachel-gekuendigt .addon-kachel-zeichen {
    background: var(--flaeche);
    color: var(--text-leise);
}

/* Ohne diesen Satz wirkte ein Produkt ohne gebuchte Addons, als fehle etwas:
   der Abschnitt verschwand ganz. */
.addon-leer {
    margin: 0.875rem 0 0;
    padding: 1.25rem;
    border: 1px dashed var(--linie);
    border-radius: var(--radius);
    color: var(--text-leise);
    font-size: 0.875rem;
    text-align: center;
}

@media (max-width: 40rem) {
    .addon-kacheln {
        grid-template-columns: 1fr;
    }
}

.eintragskarten {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(28rem, 1fr));
    gap: 1rem;
}

.eintragskarte {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
}

.eintragskarte-kopf {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--linie);
    font-weight: 600;
    word-break: break-word;
}

.eintragskarte-kopf i {
    flex-shrink: 0;
    color: var(--akzent);
    font-size: 1.0625rem;
}

.eintragskarte details {
    margin-top: 0.25rem;
}

.eintragskarte summary {
    color: var(--akzent-dunkel);
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
}

.eintragskarte .formular {
    margin-top: 0.75rem;
}

/* Ein Verzeichnispfad oder eine Adresse hat keine Umbruchstelle. Ohne das
   waechst die 1fr-Spalte auf die Laenge des Wertes, die Liste wird breiter
   als ihre Karte und am Handy rechts abgeschnitten (gemessen am
   Staging-Reiter, #973; der Installationspfad im WordPress-Reiter lief
   genauso ueber). min-width: 0 gehoert dazu: ein Grid-Kind schrumpft sonst
   nie unter seine Mindestbreite, egal was overflow-wrap sagt. */
.eintragskarte .datenliste dd {
    min-width: 0;
    overflow-wrap: anywhere;
}

.datenliste {
    display: grid;
    grid-template-columns: minmax(9rem, auto) 1fr;
    gap: 0.5rem 1.25rem;
    margin: 0;
}

.datenliste dt {
    color: var(--text-leise);
    font-size: 0.875rem;
    font-weight: 600;
}

.datenliste dd {
    margin: 0;
}

.datenliste-kompakt {
    grid-template-columns: minmax(7rem, auto) 1fr;
    gap: 0.375rem 0.75rem;
    margin-bottom: 2rem;
}

.datenliste .referenz {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 400;
}

/* Status einer WordPress-Installation (Variante E, 15.09.2026 ausgewaehlt):
   duenner Rahmen in der Statusfarbe, eckig wie Buttons und Felder statt der
   runden .status-Pille. Nur im Kundenbereich. */
.installationsstatus {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.1875rem 0.625rem 0.1875rem 0.5rem;
    border: 1px solid currentcolor;
    border-radius: var(--radius);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

.installationsstatus i {
    font-size: 1rem;
}

.installationsstatus-fertig {
    border-color: #1f7a45;
    color: var(--erfolg);
}

.installationsstatus-fehler {
    border-color: var(--fehler);
    color: var(--fehler);
}

.installationsstatus-wartet {
    border-color: var(--akzent-dunkel);
    color: #17497f;
}

.installationsstatus-laeuft {
    border-color: var(--akzent);
    color: #17497f;
}

.installationsstatus-vorbereitung {
    border-color: #6b7680;
    color: #454b52;
}

@media (max-width: 40rem) {
    .installationsstatus {
        white-space: normal;
    }
}

/* --- Domainkontakte: Registry-Kontakte als Raster --------------------- */

/* Vorher lag je Kontakt eine .karte in der Abschnitts-.karte -- doppelter
   Rahmen, doppelter Innenabstand, viel Leerraum rechts. Jetzt ein Raster
   leichter Kacheln, zwei bis drei nebeneinander, Umbruch auf schmalen
   Viewports. */
.kontaktkarten {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: 1rem;
    margin-top: 1.25rem;
}

.kontaktkarte {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
    padding: 1.1rem 1.15rem 1.2rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
}

.kontaktkarte-kopf {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    padding-bottom: 0.6rem;
    border-bottom: 1px solid var(--linie);
    font-size: 1rem;
    font-weight: 600;
    word-break: break-word;
}

.kontaktkarte-kopf i {
    flex-shrink: 0;
    color: var(--akzent);
    font-size: 1rem;
}

/* .datenliste-kompakt bringt sonst 2rem Leerraum unter jede Kachel. */
.kontaktkarte .datenliste-kompakt {
    margin-bottom: 0;
}

/* --- Meldungen ---------------------------------------------------------- */

.meldung {
    margin: 0 0 1.25rem;
    padding: 0.75rem 0.875rem;
    border-radius: var(--radius);
    font-size: 0.9375rem;
}

/* .meldung setzt display in dieser Datei und in admin.css (flex) neu — beides
   schlaegt sonst das UA-Stylesheet fuer [hidden], und eine leere Box mit nur
   dem Icon aus ::before bleibt sichtbar, obwohl sie versteckt sein soll. */
.meldung[hidden] {
    display: none;
}

.meldung-fehler {
    background: var(--fehler-grund);
    border: 1px solid var(--fehler);
    color: var(--fehler);
}

.meldung-erfolg {
    background: var(--erfolg-grund);
    border: 1px solid var(--erfolg);
    color: var(--erfolg);
}

/* Weder Fehler noch Erfolg: ein Zustand, den jemand wissen muss. "Es ist noch
   nichts hinterlegt, also passiert nichts" ist keine Stoerung. */
.meldung-hinweis {
    background: var(--hinweis-grund);
    border: 1px solid var(--akzent);
    color: var(--akzent-dunkel);
}

/* --- Formular ----------------------------------------------------------- */

.feld {
    margin-bottom: 1rem;
}

.feld label {
    display: block;
    margin-bottom: 0.3125rem;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-leise);
}

.feld input,
.feld select,
.feld textarea {
    display: block;
    width: 100%;
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: inherit;
    font: inherit;
}

.feld input:focus-visible,
.feld select:focus-visible,
.feld textarea:focus-visible,
.formular button:not(.tox-tinymce *):focus-visible {
    outline: 2px solid var(--akzent);
    outline-offset: 2px;
}

.feld textarea {
    min-height: 8rem;
    resize: vertical;
}

/* Das TinyMCE-Editorfeld (public/assets/vendor/tinymce) bringt sein eigenes
   Skin-CSS mit; hier nur der Zwischenraum zum umgebenden Formular. */
.feld .tox-tinymce {
    margin-bottom: 0.5rem;
}

.feld-klein {
    max-width: 14rem;
}

/* Die Domain/Hostname-Eingabe auf der Produktseite ist der einzige Schritt
   zwischen "Laufzeit gewaehlt" und "in den Warenkorb" — deshalb groesser
   und mit Icon statt wie ein Formularfeld unter vielen auszusehen. Eigene
   Eingaberegeln statt .feld input, damit das Icon im Feld selbst Platz hat. */
.domainfeld label {
    display: flex;
    align-items: center;
    gap: 0.4375rem;
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--text);
}

.domainfeld label i {
    color: var(--akzent);
}

.domainfeld-eingabe {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    border: 1.5px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    padding: 0 0.875rem;
    transition: border-color .15s ease, box-shadow .15s ease;
}

.domainfeld-eingabe:focus-within {
    border-color: var(--akzent);
    box-shadow: 0 0 0 3px var(--hinweis-grund);
}

.domainfeld-eingabe i {
    color: var(--text-leise);
    flex: none;
}

.domainfeld-eingabe input {
    flex: 1;
    width: auto;
    border: 0;
    outline: 0;
    padding: 0.8125rem 0;
    font-size: 1.0625rem;
    background: transparent;
}

/* Der Fokusring sitzt auf der Umrandung (.domainfeld-eingabe:focus-within),
   nicht zusaetzlich auf dem Feld selbst — sonst zwei ineinander
   verschachtelte Ringe fuer denselben Fokus. */
.domainfeld-eingabe input:focus-visible {
    outline: 0;
}

/* Eine im Domainschritt registrierte oder transferierte Domain: es gibt
   nichts mehr zu fragen (siehe Kommentar in product.html.twig), deshalb eine
   eigene, bestaetigende Kartenoptik statt des editierbaren Eingabefelds. */
.domainfeld-gebunden {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    background: var(--akzent-hell, #eef5fb);
    border: 1px solid var(--akzent);
    border-color: color-mix(in srgb, var(--akzent) 35%, var(--linie));
    border-radius: calc(var(--radius) + 4px);
    padding: 0.875rem 1.125rem;
}

.domainfeld-gebunden-icon {
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius);
    background: var(--akzent);
    display: flex;
    align-items: center;
    justify-content: center;
}

.domainfeld-gebunden-icon i {
    color: #fff;
    font-size: 1.0625rem;
}

.domainfeld-gebunden-info {
    min-width: 0;
    flex: 1;
}

.domainfeld-gebunden-label {
    margin: 0 0 0.125rem;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--akzent-dunkel);
}

.domainfeld-gebunden-name {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--text);
    overflow-wrap: anywhere;
}

.domainfeld-gebunden-abzeichen {
    flex: none;
    display: flex;
    align-items: center;
    gap: 0.375rem;
    background: var(--erfolg-grund);
    color: var(--erfolg);
    font-size: 0.8125rem;
    font-weight: 600;
    padding: 0.3125rem 0.625rem;
    border-radius: 999px;
}

@media (max-width: 26rem) {
    .domainfeld-gebunden {
        flex-wrap: wrap;
    }

    .domainfeld-gebunden-abzeichen {
        margin-left: calc(2.5rem + 0.875rem);
    }
}

/* Kontrollkaestchen und Beschriftung in einer Zeile: das Label ist die
   Trefferflaeche, damit auch der Text angetippt werden kann.

   Spezifitaet bewusst ueber .feld label / .feld input: dort stehen
   display:block und width:100% fuer Textfelder, und die wuerden Checkbox
   und Text sonst untereinander stapeln. */
.ankreuzfeld,
.feld label.ankreuzfeld {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 44px;
    margin-bottom: 0;
    color: var(--text);
    font-size: 0.9375rem;
    font-weight: 400;
    cursor: pointer;
}

.ankreuzfeld input,
.ankreuzfeld input[type="checkbox"],
.feld .ankreuzfeld input,
.feld input[type="checkbox"],
.feld input[type="radio"] {
    display: inline-block;
    flex: 0 0 auto;
    width: 1.125rem;
    height: 1.125rem;
    margin: 0;
    padding: 0;
    border: initial;
    border-radius: 0;
    background: initial;
}

/* Produktlaufzeiten sind wie Checkboxen kleine native Steuerelemente. Ohne
   diese Ausnahme greift die allgemeine Eingaberegel mit width: 100 %, wodurch
   das Radio vor seiner Beschriftung die gesamte Zeile einnimmt. */
.feld input[type="radio"] {
    vertical-align: middle;
}

/* Beschreibungen aus dem Katalog duerfen bewusst HTML enthalten. Die frueher
   verwendete Klasse .br stammt aus dem bestehenden Auftritt und steht fuer
   einen eigenen Leistungs-Punkt. */
.produktbeschreibung > :first-child {
    margin-top: 0;
}

.produktbeschreibung > :last-child {
    margin-bottom: 0;
}

.produktbeschreibung .br {
    display: block;
}

/* Mehrzeilige Einwilligungstexte (AGB, DSGVO): das Kaestchen bleibt an der
   ersten Textzeile ausgerichtet, statt bei align-items:center in der Mitte
   des ganzen umgebrochenen Absatzes zu schweben. */
.feld label.ankreuzfeld.ankreuzfeld-mehrzeilig {
    align-items: flex-start;
    min-height: 0;
    line-height: 1.4;
}

.ankreuzfeld-mehrzeilig input {
    margin-top: 0.2rem;
}

/* Die eine Einwilligungs-Checkbox, die beim letzten Versuch fehlte: roter
   Rahmen um genau dieses Kaestchen statt nur einer Meldung weit oben auf der
   Seite, plus eine eigene, kleinere Fehlermeldung direkt darunter. */
.checkout-einwilligungen .ankreuzfeld-fehler {
    border: 1px solid var(--fehler);
    border-radius: 0.375rem;
    background: var(--fehler-grund);
    padding: 0.5rem 0.625rem;
}

.checkout-einwilligungen .ankreuzfeld-fehlermeldung {
    margin: 0.375rem 0 0.75rem;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
}

/* --- Laufzeitauswahl (Produktseite) --------------------------------------
   Eigene, groessere Radios statt der kleinen nativen Formular-Radios: die
   Laufzeit ist die zentrale Entscheidung auf der Produktseite, nicht ein
   Feld unter vielen. */

.laufzeiten {
    display: grid;
    gap: 0.625rem;
    margin: 0 0 1rem;
    padding: 0;
    border: 0;
}

.laufzeiten legend {
    padding: 0 0 0.5rem;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-leise);
}

/* Jede Laufzeit als eigene Karte statt einer schlichten Zeile: die
   Auswahl ist eine der wichtigsten Entscheidungen auf der Produktseite,
   die ausgewaehlte Karte hebt sich deshalb mit Flaeche und Rahmen ab,
   nicht nur mit einem gefuellten Radio-Punkt. */
.laufzeit-option {
    display: flex;
    position: relative;
    align-items: center;
    gap: 0.6875rem;
    min-height: 3.25rem;
    padding: 0 0.875rem;
    background: var(--flaeche);
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    color: var(--text);
    font-size: 0.9375rem;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}

.laufzeit-option:hover {
    border-color: var(--akzent);
}

.laufzeit-option:has(input:checked) {
    background: var(--hinweis-grund);
    border-color: var(--akzent);
    box-shadow: 0 0 0 1px var(--akzent);
}

.laufzeit-option input[type="radio"] {
    appearance: none;
    flex: none;
    width: 1.125rem;
    height: 1.125rem;
    margin: 0;
    border: 2px solid var(--akzent);
    border-radius: 50%;
    background: var(--flaeche);
    position: relative;
    cursor: pointer;
}

.laufzeit-option input[type="radio"]:checked::after {
    content: "";
    position: absolute;
    inset: 2px;
    border-radius: 50%;
    background: var(--akzent);
}

.laufzeit-option input[type="radio"]:focus-visible {
    outline: 2px solid var(--akzent);
    outline-offset: 2px;
}

.laufzeit-name {
    flex: 1;
    font-weight: 500;
}

.laufzeit-preis {
    color: var(--text);
    font-weight: 600;
    white-space: nowrap;
}

/* Empfehlung auf einer Laufzeit — eine redaktionelle Auszeichnung
   (ShopController::product(), 'isRecommended'), kein Preisvorteil und keine
   Aussage ueber andere Kunden. Deshalb der Akzentton statt der Erfolgsfarbe,
   die anderswo einen echten Rabatt markiert.

   Als Faehnchen, das die obere Kante der Karte ueberlappt, statt als
   Inline-Tag neben dem Preis — dafuer extra Platz oben an der Karte
   (.laufzeit-option-empfohlen) und position:relative, das .laufzeit-option
   schon fuer den Radio-Kreis mitbringt. */
.laufzeit-option-empfohlen {
    margin-top: 0.7rem;
}

.laufzeit-abzeichen {
    position: absolute;
    top: -0.7rem;
    left: 0.875rem;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.625rem;
    border-radius: 999px;
    background: var(--akzent-dunkel);
    color: #ffffff;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    white-space: nowrap;
    box-shadow: 0 2px 4px rgb(67 130 195 / 35%);
}

.laufzeit-abzeichen i {
    font-size: 0.625rem;
}

/* Der Bestellen-Button bleibt auf dem Handy erreichbar, ohne dass man sich
   an einer langen Beschreibung oder vielen Optionen vorbeischeiben muss. Nur
   unterhalb von 40rem: auf dem Desktop steht das Formular ohnehin nah genug
   am oberen Rand, und ein fixierter Balken wuerde dort nur Platz nehmen. */
@media (max-width: 40rem) {
    .formular-absenden {
        position: sticky;
        bottom: 0;
        margin: 1rem -1.75rem -1.75rem;
        padding: 0.75rem 1.75rem calc(0.75rem + env(safe-area-inset-bottom, 0px));
        background: var(--flaeche);
        border-top: 1px solid var(--linie);
    }

    .formular-absenden button {
        margin-top: 0;
    }
}

/* Nur der Textteil neben dem Kaestchen darf den Restplatz nehmen. Seit dem
   gezeichneten Kontrollkaestchen (#805) steckt das Kaestchen selbst in einer
   <span class="haken-feld">, die bewegung.js einfuegt — ein Span im selben
   Label. Ohne die Ausnahme gewinnt diese Regel (0,1,1) gegen .haken-feld
   (0,1,0), das Kaestchen bekommt flex-grow: 1 und zieht sich ueber den
   ganzen freien Platz: je kuerzer der Text, desto breiter der Kasten. Der
   Kindkombinator haelt die Regel zugleich von .t-check fern, das innerhalb
   der Huelle liegt. */
.ankreuzfeld-mehrzeilig > span:not(.haken-feld) {
    flex: 1 1 auto;
}

/* --- Produktseite: Hauptspalte + staendig sichtbare Bestellzusammenfassung
   ------------------------------------------------------------------------
   Zwei Spalten auf dem Desktop, eine auf dem Handy — dieselbe Reihenfolge
   im Markup (Beschreibung, dann Formular, dann die Zusammenfassung), damit
   ein schmaler Bildschirm sie einfach untereinander stapelt. */
.produkt-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 20rem;
    gap: 1.5rem;
    align-items: start;
}

@media (max-width: 60rem) {
    .produkt-layout {
        grid-template-columns: 1fr;
    }
}

.produkt-auswahl {
    position: sticky;
    top: 1.5rem;
}

@media (max-width: 60rem) {
    /* Auf dem Handy nichts zum Nachscrollen — die Zusammenfassung liegt
       ohnehin direkt unter dem Formular. */
    .produkt-auswahl {
        position: static;
    }
}

.produkt-auswahl-betrag {
    margin: 0 0 0.25rem;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.2;
}

.produkt-auswahl-betrag span {
    font-size: 1rem;
    font-weight: 500;
    color: var(--text-leise);
}

/* Genau ein Preis ist sichtbar: der der angehakten Laufzeit. Die Radios
   tragen dafuer eine ID je BillingCycle-Wert (product.html.twig), eine
   feste, kleine, seit Jahren stabile Aufzaehlung — kein Skript noetig,
   dieselbe :has()-Technik wie .laufzeit-option:has(input:checked). */
.produkt-auswahl-preis {
    display: none;
}

.produkt-layout:has(#zyklus-one_time:checked) .produkt-auswahl-preis-one_time,
.produkt-layout:has(#zyklus-monthly:checked) .produkt-auswahl-preis-monthly,
.produkt-layout:has(#zyklus-quarterly:checked) .produkt-auswahl-preis-quarterly,
.produkt-layout:has(#zyklus-semiannually:checked) .produkt-auswahl-preis-semiannually,
.produkt-layout:has(#zyklus-annually:checked) .produkt-auswahl-preis-annually,
.produkt-layout:has(#zyklus-biennially:checked) .produkt-auswahl-preis-biennially,
.produkt-layout:has(#zyklus-triennially:checked) .produkt-auswahl-preis-triennially {
    display: block;
}

/* Der Bestellen-Button in der Zusammenfassung haengt per form="produkt-
   bestellen" am Formular in der Hauptspalte, steht also ausserhalb von
   .formular und bekommt dessen Gestaltung nicht automatisch mit. */
.produkt-auswahl button:not(.tox-tinymce *) {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    min-height: 44px;
    margin-top: 0.5rem;
    padding: 0.625rem 1rem;
    border: 0;
    border-radius: var(--radius);
    background: var(--akzent-dunkel);
    color: #ffffff;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.produkt-auswahl button:not(.tox-tinymce *):hover {
    background: var(--akzent-tief);
}

/* --- Produktseite: Vorteile-Checkliste (Product::highlightLines()) -----
   Kurze, admin-gepflegte Stichpunkte, getrennt von der freien HTML-
   Beschreibung darueber — deshalb eine eigene, schlichte Liste statt in
   .produktbeschreibung eingemischt zu werden. */
.produkt-vorteile {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.625rem 1.5rem;
    margin: 1rem 0 0;
    padding: 0;
    list-style: none;
}

/* Feste zwei Spalten statt auto-fit: bei drei oder vier Punkten liess
   auto-fit eine dritte Spalte entstehen, die dann eine einzelne, allein
   stehende Zeile darunter zurueckliess — hier bleibt die Liste ein
   gleichmaessiges Raster, ungeachtet der Anzahl. */
@media (max-width: 26rem) {
    .produkt-vorteile {
        grid-template-columns: 1fr;
    }
}

.produktbeschreibung + .produkt-vorteile {
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--linie);
}

.produkt-vorteile li {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.9375rem;
}

.produkt-vorteile li i {
    margin-top: 0.1875rem;
    color: var(--erfolg);
    flex: none;
}

/* Ueberschrift mit Icon vor der Vorteile-Checkliste und vor der
   Warum-JABA-Karte — beide Abschnitte sonst ohne erkennbaren Einstieg. */
.abschnittskopf {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin: 0 0 1rem;
}

.abschnittskopf i {
    color: var(--akzent);
    font-size: 1.125rem;
    flex: none;
}

.abschnittskopf h2 {
    margin: 0;
    font-size: 1.1875rem;
    font-weight: 700;
    color: var(--text);
}

/* --- Produktseite: "Warum JABA"-Karte ----------------------------------- */

.produkt-warum {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.125rem 1.5rem;
    margin: 1rem 0 0;
    padding: 0;
    list-style: none;
}

@media (max-width: 26rem) {
    .produkt-warum {
        grid-template-columns: 1fr;
    }
}

.produkt-warum li {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
}

.produkt-warum-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 2.125rem;
    height: 2.125rem;
    border-radius: var(--radius);
    background: rgba(67, 130, 195, 0.12);
}

.produkt-warum-icon i {
    color: var(--akzent);
    font-size: 1rem;
}

.produkt-warum li strong {
    display: block;
    font-size: 0.9375rem;
    color: var(--text);
    margin-bottom: 0.125rem;
}

.produkt-warum li span:last-child {
    font-size: 0.875rem;
    color: var(--text-leise);
    line-height: 1.5;
}

/* The auth form itself is capped at 38rem for readable field widths, but
   that leaves the two consent rows wrapping one word early on wide screens
   even though the card around the form has plenty of room. Letting just
   these rows grow past the form's own column uses that room without
   widening the actual input fields. Bounded so it never runs past the card
   on narrower windows. */
@media (min-width: 56rem) {
    .auth-formular .ankreuzfeld-mehrzeilig {
        width: max-content;
        max-width: 48rem;
    }
}

.feldhinweis {
    margin: 0.375rem 0 0;
    color: var(--text-leise);
    font-size: 0.8125rem;
}

/* :not(.tox-tinymce *) — TinyMCE's eigene Werkzeugknoepfe sind ebenfalls
   <button>-Elemente; ohne die Ausnahme sprengt die erzwungene 44px-Hoehe
   ihr eigenes, viel engeres Layout. Siehe admin.css fuer denselben Fall
   und warum `all: revert` hier nicht der richtige Weg gewesen waere. */
.formular button:not(.tox-tinymce *) {
    /* Volle Breite und 44 px hoch: auf dem Handy bedienbar, ohne zu zielen. */
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 44px;
    margin-top: 0.5rem;
    padding: 0.625rem 1rem;
    border: 0;
    border-radius: var(--radius);
    background: var(--akzent-dunkel);
    color: #ffffff;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.formular button:not(.tox-tinymce *):hover {
    background: var(--akzent-tief);
}

.formular button.sekundaer {
    border: 1px solid var(--linie);
    background: var(--flaeche);
    color: var(--text);
}

.formular button.sekundaer:hover {
    background: var(--grund);
}

.formular .password-generator-button {
    display: inline-flex;
    width: auto;
    align-items: center;
    justify-content: flex-start;
    align-self: flex-start;
    justify-self: start;
    gap: 0.45rem;
    min-width: 11.1rem;
    margin-top: 0.5rem;
}

.formular-schliessen {
    margin-top: 1rem;
}

/* Payment methods are a customer-only composition of the existing card and
   form primitives. The scoped classes keep their denser desktop layout away
   from account forms and staff views. */
.payment-methods-page-header {
    margin-bottom: 1.75rem;
}

.payment-methods-card {
    overflow: hidden;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
}

.payment-methods-card-header {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.5rem 1.75rem;
    border-bottom: 1px solid var(--linie);
    background: var(--hinweis-grund);
}

.payment-methods-card-icon,
.payment-methods-method-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--flaeche);
    color: var(--akzent);
}

.payment-methods-card-icon {
    width: 3rem;
    height: 3rem;
    font-size: 1.25rem;
}

.payment-methods-card-header h2,
.payment-methods-card-header p,
.payment-methods-saved-item h4,
.payment-methods-saved-item p,
.payment-methods-empty p {
    margin: 0;
}

.payment-methods-card-header h2 {
    font-size: 1.25rem;
}

.payment-methods-card-header p,
.payment-methods-saved-details p,
.payment-methods-empty > p:not(.payment-methods-empty-heading) {
    margin-top: 0.25rem;
    color: var(--text-leise);
}

.payment-methods-card-body {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    gap: 2rem;
    padding: 1.75rem;
}

.payment-methods-card-body h3 {
    margin: 0 0 1rem;
    font-size: 1rem;
}

.payment-methods-setup-form {
    max-width: 25rem;
}

.payment-methods-setup-form .feld {
    margin-bottom: 0;
}

.payment-methods-setup-form .payment-methods-add-button {
    display: inline-flex;
    width: auto;
}

.payment-methods-hint {
    display: flex;
    gap: 0.625rem;
    margin: 1rem 0 0;
    padding: 0.875rem 1rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--hinweis-grund);
    color: var(--text-leise);
    font-size: 0.875rem;
    line-height: 1.45;
}

.payment-methods-hint i {
    margin-top: 0.125rem;
    color: var(--akzent);
}

.payment-methods-saved-list {
    display: grid;
    gap: 0.75rem;
}

.payment-methods-saved-item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.75rem 1rem;
    padding: 1rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
}

.payment-methods-saved-details {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-width: 0;
}

.payment-methods-saved-details h4 {
    overflow-wrap: anywhere;
    font-size: 1rem;
}

.payment-methods-method-icon {
    width: 2.5rem;
    height: 2.5rem;
    background: var(--hinweis-grund);
}

.payment-methods-status {
    align-self: start;
    margin: 0;
    padding: 0.25rem 0.5rem;
    border-radius: var(--radius);
    font-size: 0.8125rem;
    font-weight: 600;
}

.payment-methods-status-active {
    background: var(--erfolg-grund);
    color: var(--erfolg);
}

.payment-methods-status-inactive {
    background: var(--grund);
    color: var(--text-leise);
}

.payment-methods-actions {
    display: flex;
    flex-wrap: wrap;
    grid-column: 1 / -1;
    gap: 0.5rem;
}

.payment-methods-actions form {
    flex: 1 1 14rem;
}

.payment-methods-actions button {
    width: 100%;
}

.payment-methods-empty {
    display: grid;
    justify-items: center;
    padding: 2rem 1rem;
    border: 1px dashed var(--linie);
    border-radius: var(--radius);
    color: var(--text-leise);
    text-align: center;
}

.payment-methods-empty > i {
    margin-bottom: 0.75rem;
    color: var(--akzent);
    font-size: 2rem;
}

.payment-methods-empty-heading {
    color: var(--text);
    font-weight: 600;
}

.schaltflaeche {
    display: inline-flex;
    gap: 0.5rem;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    padding: 0.625rem 1rem;
    border-radius: var(--radius);
    background: var(--akzent-dunkel);
    color: #ffffff;
    font-weight: 600;
    text-decoration: none;
}

.schaltflaeche:hover {
    background: var(--akzent-tief);
}

.schaltflaeche.sekundaer {
    border: 1px solid var(--linie);
    background: var(--flaeche);
    color: var(--text);
}

.schaltflaeche.sekundaer:hover {
    background: var(--grund);
}

.hosting-aktionen {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.hosting-panel-login {
    padding-top: 1.5rem;
    border-top: 1px solid var(--linie);
}

.hosting-panel-login .schaltflaeche {
    margin-bottom: 1.25rem;
}

.hosting-panel-login p {
    margin: 0 0 0.75rem;
}

.hosting-panel-login ul {
    margin: 0.75rem 0;
    padding-left: 2.5rem;
}

.hosting-panel-login li {
    margin-bottom: 0.25rem;
}

.erfolg-symbol {
    color: var(--erfolg);
}

.fehler-symbol {
    color: var(--fehler);
}

/* --- Ticketuebersicht --------------------------------------------------- */

.tabellenrahmen {
    overflow-x: auto;
    background: var(--flaeche);
    border: 1px solid var(--linie);
    border-radius: var(--radius);
}

.ticketliste {
    width: 100%;
    border-collapse: collapse;
}

.ticketliste th,
.ticketliste td {
    padding: 0.75rem;
    border-bottom: 1px solid var(--linie);
    text-align: left;
    vertical-align: top;
}

.ticketliste th {
    color: var(--text-leise);
    font-size: 0.8125rem;
}

.ticketliste tbody tr:last-child td {
    border-bottom: 0;
}

/*
 * Rechnungsposten (issue #552): die schmalen Spalten sollen ohne
 * Seitwaertsscrollen auf eine uebliche Fensterbreite passen. Betraege und
 * Kennzahlen brechen deshalb nicht um; nur die Bezeichnung flieszt und
 * bekommt den uebrigen Platz. Der overflow-x-Rahmen bleibt als Auffangnetz
 * fuer sehr schmale Fenster.
 */
.rechnungsposten {
    font-variant-numeric: tabular-nums;
}

.rechnungsposten th,
.rechnungsposten td {
    padding: 0.6rem 0.6rem;
    white-space: nowrap;
}

.rechnungsposten th:nth-child(2),
.rechnungsposten td:nth-child(2) {
    white-space: normal;
    width: 100%;
}

/*
 * DNS-Eintraege (issue #550): fuenf Spalten mit rohen Eingabefeldern
 * sprengten auf einer ueblichen Fensterbreite die Inhaltsspalte, sodass die
 * Tabelle seitwaerts scrollte. Feste Spaltenbreiten halten sie jetzt auf
 * Fensterbreite; die Felder bekommen denselben Rahmen wie .feld-Eingaben
 * (die DNS-Zeilen liegen nicht in einem .feld-Wrapper). Unter 56rem klappt
 * jede Zeile in eine Karte -- die generische .ticketliste-Stapelung greift
 * erst bei 48rem, was fuer neun Felder je Zeile zu spaet ist.
 */
.dns-eintraege {
    table-layout: fixed;
}

.dns-eintraege .dns-spalte-name { width: 23%; }
.dns-eintraege .dns-spalte-typ  { width: 15%; }
.dns-eintraege .dns-spalte-wert { width: 32%; }
.dns-eintraege .dns-spalte-prio { width: 13%; }
.dns-eintraege .dns-spalte-ttl  { width: 17%; }

.dns-eintraege th,
.dns-eintraege td {
    padding: 0.6rem 0.5rem;
}

.dns-eintraege input,
.dns-eintraege select {
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    padding: 0.5rem 0.55rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: inherit;
    font: inherit;
    text-overflow: ellipsis;
}

.dns-eintraege input:focus-visible,
.dns-eintraege select:focus-visible {
    outline: 2px solid var(--akzent);
    outline-offset: 1px;
}

.ticketlink,
.referenz {
    display: block;
}

.ticketlink {
    font-weight: 600;
}

.status {
    display: inline-block;
    padding: 0.1875rem 0.5rem;
    border-radius: 999px;
    font-size: 0.8125rem;
    white-space: nowrap;
}

.status-offen {
    background: #fff0dc;
    color: #744000;
}

.status-antwort {
    background: var(--hinweis-grund);
    color: #17497f;
}

/* Zahlung ausstehend (#753): bezahlt, aber beim Anbieter noch nicht
   abgeschlossen. Die ruhige Hinweisfarbe statt des Orange von "offen" -
   von dem Kunden wird gerade nichts erwartet. */
.status-ausstehend {
    background: var(--hinweis-grund);
    color: #17497f;
}

.status-geschlossen {
    background: #eceef1;
    color: #454b52;
}

.status-aktiv {
    background: var(--erfolg-grund);
    color: var(--erfolg);
}

.status-warnung {
    background: var(--fehler-grund);
    color: var(--fehler);
}

/* Empfaenger einer Mailvorlage (17.09.2026). Zwei Pillen statt einer, weil
   die Frage "Kunde oder wir?" eine Ja/Nein-Frage ist und beide Antworten
   sofort lesbar sein muessen — eine unmarkierte Zeile wuerde man fuer
   "noch nicht gesetzt" halten. Die interne traegt die kraeftigere Farbe:
   sie ist die Ausnahme (8 von 44) und die, bei der ein Irrtum teuer ist,
   weil dort Hostnamen und Betraege stehen duerfen, die kein Kunde sieht. */
.status-kundenmail {
    background: var(--hinweis-grund);
    color: #17497f;
}

.status-intern {
    background: #f3e8fb;
    color: #5b2d82;
}

.leerstand {
    text-align: center;
}

/* --- Tickets im Mitarbeiterbereich -------------------------------------- */

/* Suchleiste, Filterleiste und Stufenliste standen bis zum 15.08.2026 hier,
   obwohl sie ausschliesslich im Mitarbeiterbereich vorkommen. Sie banden Mass
   und Farbe ihrer Knoepfe und Felder an den umgebenden Container und haben
   damit genau die Abweichungen erzeugt, die admin.css seither zentral regelt.
   Sie stehen jetzt dort — als reine Anordnung, ohne eigene Masse. */

/* Eine interne Notiz steht neben dem, was der Kunde sieht. Der Unterschied
   darf keine Frage der Aufmerksamkeit sein: eigener Rahmen, eigene Farbe,
   ausgeschriebene Kennzeichnung darueber. */
.nachricht-intern {
    border-color: #b8860b;
    border-left-width: 4px;
    background: #fdf6e3;
}

.internkennzeichen {
    margin: 0 0 0.5rem;
    color: #744000;
    font-size: 0.8125rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.abschnitt-intern {
    border-left: 4px solid #b8860b;
}

/* --- Protokoll ---------------------------------------------------------- */

.protokoll .zeitpunkt {
    white-space: nowrap;
}

.protokolltext {
    margin: 0.375rem 0 0;
}

.protokolldetails {
    margin-top: 0.5rem;
    font-size: 0.8125rem;
}

.protokolldetails summary {
    cursor: pointer;
    color: var(--akzent-dunkel);
}

.protokolldetails pre {
    margin: 0.5rem 0 0;
    padding: 0.625rem;
    overflow-x: auto;
    border-radius: var(--radius);
    background: var(--grund);
    font-size: 0.8125rem;
}

/* Die Spaltenueberschrift sagt einem sehenden Menschen, was in das Feld
   gehoert. Ein Screenreader liest das Feld einzeln vor und braucht trotzdem
   eine eigene Beschriftung. */
/* --- Sprungmarke -------------------------------------------------------- */

/*
    Der erste Tabstopp jeder Kundenseite. Unsichtbar, bis sie den Fokus
    bekommt — dann steht sie oben links ueber allem.

    `body > .sprungmarke` statt `.sprungmarke`, weil die uebernommenen
    WordPress-Stylesheets (wp-style-neu.css, wp-apccss.css) global
    `a { outline: 0 }` und `a:focus { outline: 0 }` setzen und nach dieser
    Datei geladen werden. Die hoehere Spezifitaet gewinnt unabhaengig von
    der Reihenfolge; der eigene Rahmen wird hier ausdruecklich gesetzt,
    damit die Marke nicht ohne sichtbaren Fokus dasteht.
*/
body > .sprungmarke {
    position: absolute;
    top: 0;
    left: -9999px;
    z-index: 1000;
    padding: 0.75rem 1rem;
    background: #17232d;
    color: #ffffff;
    font-family: var(--schrift);
    font-weight: 700;
    text-decoration: none;
}

body > .sprungmarke:focus {
    left: 0;
    outline: 3px solid var(--akzent-dunkel);
    outline-offset: 2px;
}

/*
    Das Sprungziel selbst darf keinen Fokusrahmen zeichnen: <main> ist nur
    programmatisch fokussierbar (tabindex="-1") und wird nie angetabbt.
*/
#main-body:focus {
    outline: none;
}

/*
    Die Fehlermeldung bekommt den Fokus, damit sie vorgelesen wird
    (siehe templates/_fehlermeldung.html.twig). Sie ist aber kein
    Bedienelement und wird nie angetabbt — ein Fokusrahmen um einen roten
    Kasten waere nur Laerm, die Meldung ist schon die auffaelligste
    Stelle der Seite.
*/
.meldung-fehler:focus {
    outline: none;
}

.nurfuerhilfsmittel {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* --- Unterhaltung ------------------------------------------------------- */

.nachrichten {
    display: grid;
    gap: 1rem;
    margin: 1.5rem 0;
}

.nachricht {
    max-width: 52rem;
    padding: 1rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
}

.nachricht-kunde {
    margin-left: auto;
    background: var(--hinweis-grund);
}

.nachricht header {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.75rem;
    color: var(--text-leise);
    font-size: 0.8125rem;
}

.nachrichtentext {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* Formatiert ueber den WYSIWYG-Editor (ticket-editor.js) statt reiner Text
   mit manuellen Zeilenumbruechen — echte Absaetze/Listen tragen ihren
   eigenen Abstand, pre-wrap wuerde ihn verdoppeln. Das Zuruecksetzen stand
   bis zum 22.09.2026 nur in diesem Kommentar: das Element traegt beide
   Klassen, pre-wrap aus .nachrichtentext galt weiter, und der Zeilenumbruch,
   den TinyMCE zwischen zwei Absaetze schreibt, erschien als Leerzeile. */
.nachrichtentext-html {
    white-space: normal;
    overflow-wrap: anywhere;
}

.nachrichtentext-html p,
.nachrichtentext-html ul,
.nachrichtentext-html ol,
.nachrichtentext-html blockquote {
    margin: 0;
}

.nachrichtentext-html ul,
.nachrichtentext-html ol {
    padding-left: 1.5rem;
}

.nachrichtentext-html blockquote {
    padding-left: 0.75rem;
    border-left: 3px solid var(--linie);
    color: var(--text-leise);
}

.anlagen {
    margin: 1rem 0 0;
    padding-left: 1.25rem;
}

.anlagen span {
    color: var(--text-leise);
    font-size: 0.8125rem;
}

.anlage-hinzufuegen {
    margin-top: 1rem;
    font-size: 0.875rem;
}

.anlage-hinzufuegen summary {
    cursor: pointer;
    color: var(--akzent-dunkel);
}

.formular-anlage {
    margin-top: 0.75rem;
}

.antwortbereich {
    max-width: 52rem;
}

@media (max-width: 48rem) {
    .markenzeile {
        min-height: 4.5rem;
    }

    .produktnavigation {
        width: 100%;
    }

    .produktnavigation a {
        flex: 1 1 auto;
        justify-content: center;
        padding-right: 0.75rem;
        padding-left: 0.75rem;
    }

    .seite {
        padding-top: 1.5rem;
    }

    .seitenfuss-inhalt {
        grid-template-columns: 1fr 1fr;
    }

    .seitenfuss-inhalt > :first-child {
        grid-column: 1 / -1;
    }

    .seitenfuss-unten {
        align-items: flex-start;
        flex-direction: column;
    }

    .hauptnavigation {
        align-items: stretch;
        flex-direction: column;
        gap: 0.5rem;
    }

    .abmelden button {
        width: 100%;
    }

    .datenliste {
        grid-template-columns: 1fr;
        gap: 0 0;
    }

    .datenliste dd {
        margin-bottom: 0.75rem;
    }

    .seitenkopf,
    .ticketkopf {
        align-items: stretch;
        flex-direction: column;
    }

    .ticketkopf .status {
        align-self: flex-start;
    }

    .payment-methods-card-body {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }

    .ticketliste thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
    }

    .ticketliste,
    .ticketliste tbody,
    .ticketliste tr,
    .ticketliste td {
        display: block;
    }

    .ticketliste tr {
        padding: 0.5rem 0;
        border-bottom: 1px solid var(--linie);
    }

    .ticketliste td {
        padding: 0.25rem 0.75rem;
        border: 0;
    }

    .nachricht {
        max-width: 95%;
    }
}

/*
 * DNS-Eintraege stapeln frueher als die uebrige .ticketliste (issue #550):
 * jede Zeile wird eine Karte, jedes Feld traegt sein Label darueber -- so
 * wie ein .feld im uebrigen Kundenbereich. Nach dem 48rem-Block, damit die
 * Kartenoptik bei sehr schmalen Fenstern gewinnt.
 */
@media (max-width: 56rem) {
    .dns-eintraege thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
    }

    .dns-eintraege,
    .dns-eintraege tbody,
    .dns-eintraege tr,
    .dns-eintraege td {
        display: block;
    }

    .dns-eintraege tbody tr {
        margin: 0.75rem;
        padding: 0.5rem 0.25rem;
        border: 1px solid var(--linie);
        border-radius: var(--radius);
    }

    .dns-eintraege td {
        padding: 0.4rem 0.75rem;
        border: 0;
    }

    .dns-eintraege td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 0.3125rem;
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--text-leise);
    }
}

@media (max-width: 30rem) {
    .payment-methods-card-header,
    .payment-methods-card-body {
        padding: 1.25rem;
    }

    .payment-methods-card-header {
        align-items: flex-start;
    }

    .payment-methods-saved-item {
        grid-template-columns: 1fr;
    }

    .payment-methods-status {
        justify-self: start;
    }

    .payment-methods-actions form {
        flex-basis: 100%;
    }
}
/* Only rendered for a staff-initiated customer impersonation. */
.impersonation-rueckkehr {
    position: fixed;
    z-index: 20;
    right: 0;
    top: 50%;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 0.625rem;
    color: var(--text-leise);
    background: var(--flaeche);
    border: 1px solid var(--linie);
    border-right: 0;
    border-radius: var(--radius) 0 0 var(--radius);
    box-shadow: 0 1px 3px rgb(20 20 20 / 15%);
    writing-mode: vertical-rl;
    text-decoration: none;
}

.impersonation-rueckkehr:hover,
.impersonation-rueckkehr:focus-visible {
    color: var(--flaeche);
    background: var(--akzent-dunkel);
}

/* --- Merkmalsliste -------------------------------------------------------
   Zweispaltiges Haekchen-Raster fuer Produktmerkmale (Bestellprozess,
   Produktseiten). Einspaltig auf schmalen Viewports. */

.merkmalsliste {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6875rem 1.625rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.merkmalsliste li {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
}

.merkmalsliste i {
    flex: none;
    margin-top: 0.15rem;
    color: var(--akzent);
}

@media (max-width: 700px) {
    .merkmalsliste {
        grid-template-columns: 1fr;
    }
}

/* --- Abschnittstrenner -----------------------------------------------------
   Ueberschrift mittig auf einer horizontalen Linie, fuer laengere Formulare
   mit mehreren thematischen Bloecken (z. B. Bestellprozess-Schritte). */

.abschnittstrenner {
    position: relative;
    margin: 2rem 0 1.5rem;
    text-align: center;
    border-top: 1px solid var(--linie);
}

.abschnittstrenner span {
    position: relative;
    top: -0.8125rem;
    padding: 0 0.875rem;
    background: var(--flaeche);
    color: var(--text-leise);
    font-size: 0.875rem;
    font-weight: 600;
}

/* --- Cloud XL: Konten, Gruppen, Apps ---------------------------------------
   Die Kontenansicht ist die einzige Stelle im Kundenbereich mit einer
   Seitenleiste. Der Grund ist die Sache selbst: Gruppen sind kein Unterpunkt
   der Konten, sondern die zweite Achse derselben Tabelle — wer eine Gruppe
   anwaehlt, filtert die Konten, und wer ein Konto ansieht, sieht seine
   Gruppen.

   Das Zielbild kam als eigenstaendige HTML-Datei mit eigener Farbliste
   (--jaba-primary, --jaba-heading, --danger). Uebernommen ist der Aufbau —
   Kennzahlen, Karten mit eigenem Kopf, Chips, kleine Zeilenknoepfe —, die
   Farben kommen aus den Variablen dieses Kundenbereichs. Zwei Farbwelten in
   einer Datei waeren der Anfang vom Ende der Einheitlichkeit, und --akzent
   ist ohnehin genau das Blau des Zielbilds. */

.cloudxl-seitenkopf {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.cloudxl-seitenkopf h2 {
    margin: 0;
    font-size: 1.5rem;
}

/* Kennzahlen ---------------------------------------------------------------
   Die ersten beiden sind Links und filtern die Tabelle, die dritte ist eine
   reine Zahl — Gruppen filtert man in der Seitenleiste, nicht hier. */

.cloudxl-kennzahlen {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.875rem;
    margin-bottom: 1.25rem;
}

.cloudxl-kennzahl {
    display: block;
    padding: 1rem 1.125rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--hinweis-grund);
    color: var(--text);
    text-decoration: none;
}

a.cloudxl-kennzahl:hover {
    border-color: var(--akzent);
}

a.cloudxl-kennzahl[aria-current="page"] {
    border-color: var(--akzent);
    box-shadow: inset 0 0 0 1px var(--akzent);
}

.cloudxl-kennzahl-name {
    display: flex;
    align-items: center;
    gap: 0.4375rem;
    margin-bottom: 0.375rem;
    color: var(--text-leise);
    font-size: 0.8125rem;
    font-weight: 600;
}

.cloudxl-kennzahl-name i {
    color: var(--akzent);
}

.cloudxl-kennzahl strong {
    font-size: 1.5rem;
    line-height: 1.2;
}

/* Karten -------------------------------------------------------------------
   Eigene Klasse statt .karte: diese Karten haben einen abgesetzten Kopf und
   einen Koerper ohne Innenabstand (die Tabelle soll die Kante beruehren),
   waehrend .karte ueberall sonst 1.75rem rundum setzt. */

/* `stretch` statt `start`: die Gruppen-Karte hat immer weniger Zeilen als
   die Kontentabelle, und mit `start` endete sie deutlich frueher — zwei
   Karten mit sichtbar verschiedenen Unterkanten nebeneinander. Gestreckt
   reichen beide bis zur Hoehe der hoeheren; der Inhalt bleibt oben, darunter
   bleibt bei der kuerzeren Karte einfach Weissraum. */
.cloudxl-konten {
    display: grid;
    grid-template-columns: 19rem minmax(0, 1fr);
    align-items: stretch;
    gap: 1.25rem;
}

.cloudxl-karte {
    min-width: 0;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);

    /* Klippt die randbuendige Tabelle auf die abgerundeten Ecken. */
    overflow: hidden;
}

/* Die Gruppen-Seitenleiste traegt keine randbuendige Tabelle, aber ein
   Aufklapp-Popover ("+" Neue Gruppe), das breiter ist als die 19rem-Spalte.
   `overflow: hidden` schnitt es an der Kartenkante ab; hier darf es heraus. */
.cloudxl-konten > .cloudxl-karte:first-child {
    overflow: visible;
}

.cloudxl-kartenkopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.875rem 1.125rem;
    border-bottom: 1px solid var(--linie);
    background: var(--hinweis-grund);
}

.cloudxl-kartenkopf h2 {
    margin: 0;
    font-size: 1.0625rem;
}

/* "Gruppen" und "Alle Konten" sind Arbeitsflaechen, keine Seitentitel — die
   eigentliche Ueberschrift der Seite ist "Benutzer- & Gruppenverwaltung"
   darueber. Kleiner, mit Icon, im selben gedaempften Stil wie die
   Kennzahlen-Beschriftungen (.cloudxl-kennzahl-name) daneben. */
h2.cloudxl-kartenkopf-klein {
    display: flex;
    align-items: center;
    gap: 0.4375rem;
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-leise);
}

h2.cloudxl-kartenkopf-klein i {
    color: var(--akzent);
    font-size: 0.875rem;
}

.cloudxl-kartenkopf-hinweis {
    color: var(--text-leise);
    font-size: 0.8125rem;
    text-align: right;
}

.cloudxl-kartenkoerper {
    padding: 1rem 1.125rem 1.125rem;
}

/* Gruppen in der Seitenleiste ---------------------------------------------- */

.cloudxl-suche {
    display: flex;
    position: relative;
    align-items: center;
    margin-bottom: 0.75rem;
}

.cloudxl-suche i {
    position: absolute;
    left: 0.75rem;
    color: var(--text-leise);
    font-size: 0.8125rem;
    pointer-events: none;
}

/* `input[type="search"]` statt nur `input`: assets/jaba/wp-style-neu.css
   (Teil des unveraenderten JABA-Theme-Blocks, Regel 1) setzt fuer denselben
   Selektortyp ebenfalls `padding: 3px`, mit derselben Spezifitaet und
   geladen nach app.css — zuletzt gewann also das Theme. Das Attribut macht
   unsere Regel spezifischer, ohne das Theme anzufassen. */
.cloudxl-suche input[type="search"] {
    width: 100%;

    /* 2.25rem statt der Icon-Position (0.75rem) plus Icon-Breite: sonst
       beruehrt der erste Buchstabe des Platzhalters die Lupe. */
    padding: 0.4375rem 0.625rem 0.4375rem 2.25rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: inherit;
    font: inherit;
    font-size: 0.875rem;

    /* Ohne das legt WebKit sein eigenes Lupensymbol samt Innenabstand vor
       den Platzhaltertext — genau ueber unser eigenes Icon. */
    appearance: none;
    -webkit-appearance: none;
}

.cloudxl-suche input::-webkit-search-decoration,
.cloudxl-suche input::-webkit-search-cancel-button {
    display: none;
}

/* Konten- und Gruppensuche gehen beide an den Server — beide Listen sind auf
   25 Eintraege gekuerzt, und was nicht im Dokument steht, kann der Browser
   nicht finden. Also braucht jede einen Absendeknopf: das Feld nimmt den
   Platz, der Knopf bleibt so breit wie sein Wort und rutscht in der schmalen
   Seitenleiste von selbst in die zweite Zeile. */
.cloudxl-listensuche {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.cloudxl-listensuche .cloudxl-suche {
    flex: 1 1 10rem;
    margin-bottom: 0;
}

/* Die Kontensuche ist eine eigene Zeile zwischen Kartenkopf und Tabelle ... */
.cloudxl-kontosuche {
    padding: 0.75rem 1.125rem;
    border-bottom: 1px solid var(--linie);
}

/* ... die Gruppensuche steht im Kartenkoerper und bringt nur den Abstand
   mit, den das Feld dort vorher selbst hatte. */
.cloudxl-kartenkoerper > .cloudxl-listensuche {
    margin-bottom: 0.75rem;
}

.cloudxl-suchhinweis {
    margin: -0.375rem 0 0.75rem;
    font-size: 0.8125rem;
}

.cloudxl-gruppen {
    display: grid;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.cloudxl-gruppe {
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
}

.cloudxl-gruppe-aktiv {
    border-color: var(--akzent);
    background: var(--hinweis-grund);
}

.cloudxl-gruppe-kopf {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.cloudxl-gruppe-kopf i {
    flex: 0 0 auto;
    color: var(--akzent);
    font-size: 0.875rem;
}

.cloudxl-gruppe-name {
    flex: 1 1 auto;
    overflow: hidden;
    font-size: 0.875rem;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cloudxl-gruppe-aktionen {
    display: flex;
    position: relative;
    align-items: center;
    gap: 0.75rem;
    margin-top: 0.5rem;
    padding-top: 0.4375rem;
    border-top: 1px solid var(--linie);
}

.cloudxl-gruppe-aktionen a,
.cloudxl-textknopf {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    border: 0;
    background: none;
    color: var(--akzent-dunkel);
    font: inherit;
    font-size: 0.8125rem;
    cursor: pointer;
    text-decoration: none;
}

.cloudxl-gruppe-aktionen a:hover,
.cloudxl-textknopf:hover {
    text-decoration: underline;
}

.cloudxl-gefahr {
    color: var(--fehler);
}

.cloudxl-zaehler {
    flex: 0 0 auto;
    min-width: 1.5rem;
    padding: 0 0.4375rem;
    border-radius: 999px;
    background: var(--hinweis-grund);
    color: var(--akzent-dunkel);
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.5rem;
    text-align: center;
}

.cloudxl-gruppe-aktiv .cloudxl-zaehler,
.cloudxl-appfilter-knopf[aria-pressed="true"] .cloudxl-zaehler {
    background: var(--akzent-dunkel);
    color: #ffffff;
}

/* Knoepfe ------------------------------------------------------------------
   Breite nach Text, nie ueber die volle Zeile. .formular button waere hier
   falsch: das ist die 44px hohe Hauptaktion eines Formulars, und eine
   Tabellenzeile braucht etwas, das neben eine Zeile passt. */

.cloudxl-kleinknopf {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    width: auto;
    min-height: 1.875rem;
    padding: 0 0.625rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: var(--text);
    font: inherit;
    font-size: 0.75rem;

    /* Ohne das bricht "Administration hinzufuegen" in der schmalen Spalte auf
       zwei Zeilen, und der Knopf wird anderthalbmal so hoch wie vorgesehen.
       Fuer die Breite hat die Tabelle ihren eigenen Waagerecht-Lauf. */
    white-space: nowrap;
    cursor: pointer;
}

.cloudxl-kleinknopf:hover {
    border-color: var(--akzent);
    background: var(--hinweis-grund);
}

.cloudxl-kleinknopf.cloudxl-gefahr:hover {
    border-color: var(--fehler);
    background: var(--fehler-grund);
}

.cloudxl-symbolknopf {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: var(--akzent);
    cursor: pointer;
}

.cloudxl-symbolknopf:hover {
    border-color: var(--akzent);
    background: var(--hinweis-grund);
}

.cloudxl-suche input:focus-visible,
.cloudxl-appfilter-knopf:focus-visible,
.cloudxl-symbolknopf:focus-visible,
.cloudxl-kleinknopf:focus-visible,
.cloudxl-textknopf:focus-visible,
.cloudxl-chip-weg:focus-visible,
.cloudxl-menueeintrag > summary:focus-visible {
    outline: 2px solid var(--akzent);
    outline-offset: 2px;
}

/* Klappen statt Modals: ein <details> braucht kein JavaScript, und ohne
   JavaScript soll hier nichts unerreichbar sein. */

.cloudxl-klappe {
    position: relative;
}

.cloudxl-werkzeuge {
    display: inline-block;
    margin-top: 0.4375rem;
}

.cloudxl-klappe > summary {
    list-style: none;
}

.cloudxl-klappe > summary::-webkit-details-marker {
    display: none;
}

/* Ein geschlossenes <details> malt seinen Inhalt zwar nicht, misst ihn aber
   weiterhin — und ein absolut gesetztes Aufklappfeld von 17rem schob auf dem
   Handy die ganze Seite nach rechts, ohne dass etwas zu sehen war.
   Zugeklappt heisst hier deshalb wirklich weg. */
.cloudxl-klappe:not([open]) > .cloudxl-formular,
.cloudxl-klappe:not([open]) > .inline-form {
    display: none;
}

.cloudxl-klappe > .cloudxl-formular {
    position: absolute;
    z-index: 20;
    top: calc(100% + 0.375rem);
    left: 0;
    width: 17rem;
    max-width: calc(100vw - 2rem);
    padding: 0.875rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    box-shadow: 0 0.5rem 1.5rem rgb(20 20 20 / 12%);
}

.cloudxl-klappe-rechts > .cloudxl-formular,
.cloudxl-klappe-rechts > .inline-form {
    right: 0;
    left: auto;
}

/* Kontoaktionen-Menue: ein Knopf statt drei nebeneinander (E-Mail, Passwort,
   Loeschen). Der Aussenknopf oeffnet eine Liste, jeder Eintrag darin ist
   selbst ein <details> und klappt sein Formular direkt darunter auf statt
   danebenschwebend — innerhalb eines schon rechts verankerten Menues haette
   ein zweites schwebendes Popover leicht am Bildschirmrand angeeckt. */
.cloudxl-aktionsmenue > .cloudxl-aktionsmenue-liste {
    position: absolute;
    z-index: 20;
    top: calc(100% + 0.375rem);
    right: 0;
    width: 15rem;
    max-width: calc(100vw - 2rem);
    padding: 0.375rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    box-shadow: 0 0.5rem 1.5rem rgb(20 20 20 / 12%);
}

.cloudxl-klappe:not([open]) > .cloudxl-aktionsmenue-liste {
    display: none;
}

.cloudxl-menueeintrag > summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 2.25rem;
    padding: 0 0.5rem;
    border-radius: calc(var(--radius) - 2px);
    color: var(--text);
    font-size: 0.8125rem;
    cursor: pointer;
}

.cloudxl-menueeintrag > summary:hover,
.cloudxl-menueeintrag > summary:focus-visible {
    background: var(--hinweis-grund);
}

.cloudxl-menueeintrag > summary i {
    flex: 0 0 auto;
    width: 1rem;
    color: var(--text-leise);
    text-align: center;
}

.cloudxl-menueeintrag > summary.cloudxl-gefahr {
    color: var(--fehler);
}

.cloudxl-menueeintrag > summary.cloudxl-gefahr i {
    color: var(--fehler);
}

.cloudxl-menueeintrag > summary.cloudxl-gefahr:hover,
.cloudxl-menueeintrag > summary.cloudxl-gefahr:focus-visible {
    background: var(--fehler-grund);
}

.cloudxl-menue-trenner {
    height: 1px;
    margin: 0.375rem 0.25rem;
    background: var(--linie);
}

/* Innerhalb des Menues waechst das Formular nach unten (Akkordeon) statt
   als eigenes schwebendes Feld daneben — sonst muesste eine zweite
   Randrichtung fuer Popover-in-Popover geloest werden, ohne echten Nutzen. */
.cloudxl-aktionsmenue-liste .cloudxl-klappe > .inline-form,
.cloudxl-aktionsmenue-liste .cloudxl-klappe > .cloudxl-formular {
    position: static;
    z-index: auto;
    width: 100%;
    max-width: none;
    margin-top: 0.25rem;
    box-shadow: none;
}

/* Kleine Aktionsformulare der Kontoverwaltung (Issue #395).
   Klassen nach dem Issue, Farben und Radius aus dem Kunden-Designsystem.
   Geschachtelt unter .inline-form, damit .form-group aus dem JABA-Kopf
   nicht mitgeändert wird. */

.inline-form {
    position: absolute;
    z-index: 20;
    top: calc(100% + 0.375rem);
    left: 0;
    box-sizing: border-box;

    /* Feste Breite, keine prozentuale: das Aufklappfeld haengt an einem
       <details>, das sich auf die Breite seines Summary-Knopfs (2rem)
       zusammenzieht — `100%` waere damit 2rem und quetschte das Formular zu
       einem Streifen. Dieselbe Loesung wie bei .cloudxl-formular daneben. */
    width: 20.625rem;
    max-width: calc(100vw - 2rem);
    margin-top: 0;
    padding: 0.875rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    box-shadow: 0 0.5rem 1.375rem rgb(30 58 95 / 10%);
}

.inline-form.is-compact {
    width: 17rem;
    padding: 0.8125rem;
}

.inline-form.is-wide {
    width: 22.5rem;
}

.inline-form-header {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    margin-bottom: 0.8125rem;
}

.inline-form-icon {
    display: grid;
    flex: 0 0 2rem;
    place-items: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: var(--hinweis-grund);
    color: var(--akzent);
    font-size: 0.9375rem;
}

.inline-form-copy h3 {
    margin: 0 0 0.1875rem;
    color: var(--text);
    font-size: 0.875rem;
    font-weight: 600;
}

.inline-form-copy p {
    margin: 0;
    color: var(--text-leise);
    font-size: 0.6875rem;
    line-height: 1.4;
}

.inline-form .form-group {
    margin-bottom: 0.75rem;
}

.inline-form .form-label {
    display: block;
    margin-bottom: 0.375rem;
    color: var(--text);
    font-size: 0.75rem;
    font-weight: 600;
}

.inline-form .form-input,
.inline-form .form-select {
    box-sizing: border-box;
    width: 100%;
    height: 2.375rem;
    padding: 0 0.625rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--grund);
    color: var(--text);
    font: inherit;
    font-size: 0.75rem;
}

.inline-form .form-input:hover,
.inline-form .form-select:hover {
    border-color: var(--akzent);
}

.inline-form .form-input:focus,
.inline-form .form-select:focus {
    outline: none;
    border-color: var(--akzent);
    background: var(--flaeche);
    box-shadow: 0 0 0 3px var(--hinweis-grund);
}

.inline-form .form-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.inline-form .form-button-primary,
.inline-form .form-button-secondary {
    width: auto;
    min-height: 2.25rem;
    padding: 0 0.75rem;
    border-radius: var(--radius);
    font: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
}

.inline-form .form-button-primary {
    border: 1px solid var(--akzent-dunkel);
    background: var(--akzent-dunkel);
    color: #ffffff;
}

.inline-form .form-button-primary:hover {
    border-color: var(--akzent-tief);
    background: var(--akzent-tief);
}

.inline-form .form-button-primary:focus-visible,
.inline-form .form-button-secondary:focus-visible {
    outline: 2px solid var(--akzent);
    outline-offset: 2px;
}

.inline-form .form-button-secondary {
    border: 1px solid var(--akzent);
    background: var(--flaeche);
    color: var(--text);
}

.inline-form .form-button-secondary:hover {
    border-color: var(--akzent);
    background: var(--hinweis-grund);
    color: var(--akzent-dunkel);
}

@media (max-width: 760px) {
    .inline-form,
    .inline-form.is-compact,
    .inline-form.is-wide {
        width: calc(100vw - 2rem);
    }
}

.cloudxl-formular .feld:last-of-type {
    margin-bottom: 0.75rem;
}

.cloudxl-formular .ankreuzfeld {
    margin-bottom: 0.5rem;
}

.cloudxl-frage {
    margin: 0 0 0.5rem;
    font-size: 0.9375rem;
}

/* Tabelle ------------------------------------------------------------------ */

.cloudxl-tabellenrahmen {
    overflow-x: auto;
}

.cloudxl-tabelle {
    width: 100%;

    /* Vier Spalten mit Chips und Knoepfen brauchen Platz. Unterhalb dieser
       Breite laeuft der Rahmen darum waagerecht, statt die Spalten
       zusammenzuquetschen. */
    min-width: 46rem;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.cloudxl-tabelle th,
.cloudxl-tabelle td {
    padding: 0.75rem 0.875rem;
    border-bottom: 1px solid var(--linie);
    text-align: left;
    vertical-align: top;
}

/* Nur die Datenzeilen, nicht die Kopfzeile: die Gruppen-Karte daneben
   listet ihre Eintraege als 90px hohe Kaertchen (Kopfzeile, Trennlinie,
   Aktionszeile). Ohne diesen Zuschlag wirkten die Kontenzeilen dagegen
   sichtbar geduckt — zwei Listen nebeneinander mit unterschiedlichem Takt. */
.cloudxl-tabelle tbody td {
    padding-top: 1.5rem;
    padding-bottom: 1.5rem;
}

.cloudxl-tabelle thead th {
    background: var(--flaeche);
    color: var(--text-leise);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.cloudxl-tabelle tbody tr:hover td,
.cloudxl-tabelle tbody tr:hover th {
    background: var(--hinweis-grund);
}

.cloudxl-tabelle tbody tr:last-child th,
.cloudxl-tabelle tbody tr:last-child td {
    border-bottom: 0;
}

/* `display: flex` direkt auf dem <th> liess die Zelle aus dem
   Tabellen-Zeilenhoehenausgleich herausfallen: sie schrumpfte auf ihren
   Inhalt (Avatar + Name, ~55px) statt die Zeilenhoehe der ueberigen, viel
   volleren Zellen (Chips, Knoepfe, Balken — oft 130px+) zu uebernehmen, und
   stand dadurch oben abgeschnitten in der Zeile. Das Flex-Layout wandert
   deshalb in ein inneres <div>; das <th> selbst bleibt eine normale
   Tabellenzelle und wird ganz regulaer vertikal zentriert. */
.cloudxl-tabelle th.cloudxl-konto {
    vertical-align: middle;
    font-weight: 700;
}

.cloudxl-konto-inhalt {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Nicht umbrechbar, mit Absicht: die Tabelle ist bereits fuers waagerechte
   Scrollen gebaut (min-width: 46rem auf .cloudxl-tabelle, siehe dort). Mit
   `overflow-wrap: anywhere` sinkt der Mindestbeitrag dieser Zelle zur
   automatischen Spaltenberechnung praktisch auf null — der Browser zog der
   Spalte dann kaum Breite zu, und "1487" stand als vier Zeilen mit je einer
   Ziffer untereinander, sobald irgendeine andere Spalte mehr Platz verlangte
   als verfuegbar war. Ein einzelner Kontoname bricht so nie um; ist die
   Tabelle insgesamt zu breit, greift der Waagerecht-Scroll wie vorgesehen. */
.cloudxl-kontoname {
    white-space: nowrap;
}

/* Rein visuell, kein Backend-Feld: die ersten beiden Zeichen des Kontonamens.
   Nextcloud zeigt an dieser Stelle ein Profilbild, das es hier nicht gibt. */
.cloudxl-signet {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 1.875rem;
    height: 1.875rem;
    border-radius: 999px;
    background: var(--akzent);
    color: #ffffff;
    font-size: 0.6875rem;
    font-weight: 700;
}

.cloudxl-zeilenaktionen {
    white-space: nowrap;
}

.cloudxl-quota { min-width: 12rem; }
.cloudxl-quota-kopf { display: flex; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.35rem; color: var(--text); font-size: 0.75rem; font-weight: 700; white-space: nowrap; }
.cloudxl-quota-balken { width: 100%; height: 0.75rem; accent-color: var(--akzent); }
.cloudxl-quota-warning .cloudxl-quota-balken { accent-color: var(--warnung); }
.cloudxl-quota-danger .cloudxl-quota-balken { accent-color: var(--fehler); }
.cloudxl-quota .cloudxl-werkzeuge { margin-top: 0.5rem; }

/* Speicherplatz der Instanz auf der Informations-Kachel (aus Froxlor). */
.cloudxl-speicher { display: flex; flex-direction: column; gap: 0.4rem; align-items: flex-start; }
.cloudxl-speicher-wert { font-variant-numeric: tabular-nums; }
.cloudxl-speicher .cloudxl-quota-balken { width: 100%; max-width: 18rem; }

/* Chips -------------------------------------------------------------------- */

.cloudxl-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.cloudxl-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    min-height: 1.6875rem;
    padding: 0.125rem 0.3125rem 0.125rem 0.5rem;
    border: 1px solid var(--linie);
    border-radius: 999px;
    background: var(--hinweis-grund);
    color: var(--text);
    font-size: 0.6875rem;
    white-space: nowrap;
}

.cloudxl-chip i {
    color: var(--akzent);
    font-size: 0.6875rem;
}

.cloudxl-chip form {
    display: inline-flex;
}

.cloudxl-chip-weg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.125rem;
    height: 1.125rem;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--text-leise);
    font-size: 0.6875rem;
    cursor: pointer;
}

.cloudxl-chip-weg:hover {
    background: var(--fehler-grund);
    color: var(--fehler);
}

/* Apps --------------------------------------------------------------------- */

.cloudxl-appfilter {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.cloudxl-appfilter-knopf {
    display: inline-flex;
    align-items: center;
    gap: 0.4375rem;
    padding: 0.375rem 0.75rem;
    border: 1px solid var(--linie);
    border-radius: 999px;
    background: var(--flaeche);
    color: var(--text);
    font: inherit;
    font-size: 0.875rem;
    cursor: pointer;
}

.cloudxl-appfilter-knopf[aria-pressed="true"] {
    border-color: var(--akzent);
    background: var(--akzent-dunkel);
    color: #ffffff;
}

.cloudxl-apps {
    margin: 0;
    padding: 0;
    list-style: none;
}

.cloudxl-app {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--linie);
}

.cloudxl-app:last-of-type {
    border-bottom: 0;
}

.cloudxl-app-titel {
    display: flex;
    flex: 1 1 14rem;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.cloudxl-app-kennung {
    color: var(--text-leise);
    font-size: 0.8125rem;
    overflow-wrap: anywhere;
}

.cloudxl-appform {
    flex: 0 0 auto;
}

.cloudxl-pille {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 0.375rem;
    padding: 0.1875rem 0.625rem;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 600;
}

.cloudxl-pille-an {
    background: var(--erfolg-grund);
    color: var(--erfolg);
}

.cloudxl-pille-aus {
    background: var(--grund);
    color: var(--text-leise);
}

/* Ladeanzeige -----------------------------------------------------------------
   Manche Kundenseiten entstehen erst, wenn eine langsame externe Abfrage
   beantwortet ist -- CloudXL wartet auf die Nextcloud des Kunden (.cloudxl-
   laden), die Domain- und Hosting-Seiten auf Registry, WHOIS oder Provisioning
   (.seiten-laden, siehe templates/_seiten-laden.html.twig, #554). Bis dahin
   passiert im Browser sichtbar nichts, und genau daraus entsteht der Eindruck,
   die Seite sei kaputt. Der Balken laeuft unbestimmt: wie lange ein fremder
   Dienst braucht, weiss hier niemand, und ein Prozentwert waere eine Zahl, die
   sich jemand ausgedacht hat. Beide Ueberzuege teilen sich dieses Aussehen. */

.cloudxl-laden,
.seiten-laden {
    display: flex;
    position: fixed;
    z-index: 100;
    inset: 0;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgb(20 20 20 / 45%);
}

.cloudxl-laden[hidden],
.seiten-laden[hidden] {
    display: none;
}

.cloudxl-laden-karte,
.seiten-laden-karte {
    width: min(22rem, 100%);
    padding: 1.5rem;
    border-radius: var(--radius);
    background: var(--flaeche);
    box-shadow: 0 1rem 2rem rgb(20 20 20 / 25%);
    text-align: center;
}

.cloudxl-laden-titel,
.seiten-laden-titel {
    margin: 0 0 0.875rem;
    font-size: 1rem;
    font-weight: 600;
}

.cloudxl-laden-balken,
.seiten-laden-balken {
    overflow: hidden;
    height: 0.375rem;
    border-radius: 999px;
    background: var(--hinweis-grund);
}

.cloudxl-laden-balken span,
.seiten-laden-balken span {
    display: block;
    width: 40%;
    height: 100%;
    border-radius: 999px;
    background: var(--akzent);
    animation: seiten-laden-lauf 1.4s ease-in-out infinite;
}

@keyframes seiten-laden-lauf {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(250%); }
}

/* Wer Bewegung abgestellt hat, bekommt einen ruhenden Balken statt gar
   keiner Rueckmeldung. */
@media (prefers-reduced-motion: reduce) {
    .cloudxl-laden-balken span,
    .seiten-laden-balken span {
        width: 100%;
        animation: none;
    }
}

.cloudxl-laden-text,
.seiten-laden-text {
    margin: 0.875rem 0 0;
    color: var(--text-leise);
    font-size: 0.8125rem;
}

/* Kleinteile --------------------------------------------------------------- */

.cloudxl-leer {
    padding: 0.75rem 0.25rem;
    color: var(--text-leise);
    font-size: 0.9375rem;
}

.cloudxl-mehr {
    margin: 1rem 0 0;
    text-align: center;
}

.cloudxl-karte > .cloudxl-mehr {
    margin: 0;
    padding: 0.875rem 1.125rem;
    border-top: 1px solid var(--linie);
}

.cloudxl-nur-vorleser {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    border: 0;
    clip-path: inset(50%);
    white-space: nowrap;
}

.cloudxl-dialog {
    max-width: min(28rem, calc(100vw - 2rem));
    padding: 1.25rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    color: var(--text);
}

.cloudxl-dialog::backdrop {
    background: rgb(20 20 20 / 45%);
}

.cloudxl-dialog-frage {
    margin: 0 0 1rem;
}

.cloudxl-dialog-knoepfe {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.5rem;
}

.cloudxl-dialog-knoepfe button {
    padding: 0.5rem 1rem;
    border: 0;
    border-radius: var(--radius);
    background: var(--akzent-dunkel);
    color: #ffffff;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.cloudxl-dialog-knoepfe button.sekundaer {
    border: 1px solid var(--linie);
    background: var(--flaeche);
    color: var(--text);
}

/* Mit JavaScript stellt der Dialog die Frage; das Kaestchen im Formular
   bleibt als Traeger von confirm=1 erhalten, aber der Kunde soll nicht
   zweimal dasselbe bestaetigen. */
.cloudxl-js form[data-bestaetigen] > .cloudxl-frage,
.cloudxl-js form[data-bestaetigen] > .ankreuzfeld {
    display: none;
}

@media (max-width: 60rem) {
    .cloudxl-konten {
        grid-template-columns: 1fr;
    }

    .cloudxl-kennzahlen {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 30rem) {
    .cloudxl-seitenkopf {
        align-items: flex-start;
        flex-direction: column;
    }

    .cloudxl-kartenkoerper {
        padding: 0.875rem;
    }

    .cloudxl-tabelle th,
    .cloudxl-tabelle td {
        padding: 0.5rem;
    }

    .cloudxl-app {
        align-items: flex-start;
    }
}

/* "Neues Konto": Modal statt schmalem Aufklapp-Popover -------------------- */

/* Ohne JavaScript ist es ein <details>, das sein Formular als Block aufklappt;
   zugeklappt ist es wirklich weg (wie .cloudxl-formular daneben). */
.account-create:not([open]) > .account-create-backdrop {
    display: none;
}

.account-create > .account-create-backdrop {
    margin-top: 0.5rem;
}

.account-create-dialog {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--flaeche);
    box-shadow: 0 0.75rem 2rem rgb(30 58 95 / 12%);
}

/* Mit JavaScript hebt cloudxl.js dasselbe Markup zu einem zentrierten Modal. */
.cloudxl-js .account-create[open] > .account-create-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: grid;
    place-items: center;
    margin-top: 0;
    padding: 1.25rem;
    background: rgb(30 58 95 / 18%);
}

.cloudxl-js .account-create-dialog {
    width: min(40rem, 100%);
    max-height: calc(100vh - 2.5rem);
}

body.cloudxl-modal-offen {
    overflow: hidden;
}

.account-create-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.25rem 1.375rem 1.125rem;
    border-bottom: 1px solid var(--linie);
    background: var(--grund);
}

.account-create-icon {
    display: grid;
    flex: 0 0 2.625rem;
    place-items: center;
    width: 2.625rem;
    height: 2.625rem;
    border-radius: 50%;
    background: var(--hinweis-grund);
    color: var(--akzent);
    font-size: 1.0625rem;
}

.account-create-copy {
    flex: 1 1 auto;
}

.account-create-copy h3 {
    margin: 0 0 0.25rem;
    color: var(--text);
    font-size: 1.0625rem;
}

.account-create-copy p {
    margin: 0;
    color: var(--text-leise);
    font-size: 0.8125rem;
    line-height: 1.45;
}

.account-create-close {
    display: grid;
    flex: 0 0 auto;
    place-items: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-leise);
    font-size: 1rem;
    cursor: pointer;
}

.account-create-close:hover {
    border-color: var(--linie);
    background: var(--flaeche);
    color: var(--text);
}

.account-create-form {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
}

.account-create-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 1.25rem 1.375rem;
}

.account-form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.875rem 1.125rem;
}

.account-create-form .form-group {
    margin: 0;
}

.account-create-form .form-group.full {
    grid-column: 1 / -1;
}

.account-create-form .form-label {
    display: block;
    margin-bottom: 0.4375rem;
    color: var(--text);
    font-size: 0.75rem;
    font-weight: 600;
}

.account-create-form .form-input,
.account-create-form .form-select {
    box-sizing: border-box;
    width: 100%;
    min-height: 2.5rem;
    padding: 0 0.6875rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--grund);
    color: var(--text);
    font: inherit;
    font-size: 0.8125rem;
}

.account-create-form .form-input:focus,
.account-create-form .form-select:focus {
    outline: none;
    border-color: var(--akzent);
    background: var(--flaeche);
    box-shadow: 0 0 0 3px var(--hinweis-grund);
}

.account-create-form .feldhinweis {
    margin: 0.4375rem 0 0;
}

.account-multiselect-native[hidden] {
    display: none;
}

.account-create-footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.5rem;
    padding: 1rem 1.375rem;
    border-top: 1px solid var(--linie);
    background: var(--flaeche);
}

.account-create-primary,
.account-create-secondary {
    min-height: 2.5rem;
    padding: 0 1rem;
    border-radius: var(--radius);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
}

.account-create-primary {
    border: 1px solid var(--akzent-dunkel);
    background: var(--akzent-dunkel);
    color: #ffffff;
}

.account-create-primary:hover {
    border-color: var(--akzent-tief);
    background: var(--akzent-tief);
}

.account-create-secondary {
    border: 1px solid var(--linie);
    background: var(--flaeche);
    color: var(--text);
}

.account-create-secondary:hover {
    border-color: var(--akzent);
    background: var(--hinweis-grund);
}

.account-create-primary:focus-visible,
.account-create-secondary:focus-visible,
.account-create-close:focus-visible {
    outline: 2px solid var(--akzent);
    outline-offset: 2px;
}

/* Chip-Mehrfachauswahl — eine Komponente fuer Gruppen und Gruppenadministration. */
.account-multiselect {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.account-multiselect-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.account-multiselect-chips:empty {
    display: none;
}

.account-multiselect-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: 1.75rem;
    padding: 0 0.5rem;
    border: 1px solid var(--linie);
    border-radius: 999px;
    background: var(--hinweis-grund);
    color: var(--text);
    font-size: 0.75rem;
}

.account-multiselect-chip-weg {
    display: grid;
    place-items: center;
    width: 1rem;
    height: 1rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-leise);
    font-size: 0.6875rem;
    cursor: pointer;
}

.account-multiselect-chip-weg:hover {
    color: var(--fehler);
}

.account-multiselect-input {
    box-sizing: border-box;
    width: 100%;
    min-height: 2.5rem;
    padding: 0 0.6875rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    background: var(--grund);
    color: var(--text-leise);
    font: inherit;
    font-size: 0.8125rem;
}

.account-multiselect-input:focus {
    outline: none;
    border-color: var(--akzent);
    background: var(--flaeche);
    box-shadow: 0 0 0 3px var(--hinweis-grund);
}

.account-multiselect-input:disabled {
    opacity: 0.55;
}

/* Smartphone: Bottom-Sheet, volle Breite, von unten. */
@media (max-width: 40rem) {
    .cloudxl-js .account-create[open] > .account-create-backdrop {
        place-items: end center;
        padding: 0;
    }

    .cloudxl-js .account-create-dialog {
        width: 100%;
        max-height: 92vh;
        border-width: 1px 0 0;
        border-radius: 0.625rem 0.625rem 0 0;
    }

    .account-form-grid {
        grid-template-columns: 1fr;
    }

    .account-create-footer {
        position: sticky;
        bottom: 0;
    }
}

/*
    Der AuthCode auf der Domainseite.

    Gross, mit Abstand zwischen den Zeichen und in einer Schrift mit klarer
    Null: der Code wird abgetippt oder kopiert, und eine verwechselte 0/O
    schickt den Kunden zu einem Support, der ihm nicht helfen kann.
*/
.authcode code {
    display: inline-block;
    padding: 0.75rem 1rem;
    background: #f1f5f9;
    border: 1px solid #bfdbfe;
    border-radius: 0.5rem;
    font-family: ui-monospace, "SFMono-Regular", "Cascadia Mono", "Liberation Mono", monospace;
    font-size: 1.125rem;
    letter-spacing: 0.08em;
    word-break: break-all;
    user-select: all;
}

/*
    Sicherheitspruefung (ALTCHA) in Anmelde-, Registrier-, Reset- und
    Kassenformularen, siehe templates/_altcha.html.twig. Eine leise Zeile,
    keine Karte: im Normalfall ist sie fertig, bevor jemand hinsieht.
*/
.altcha-pruefung {
    margin: 0;

    /* In den zweispaltigen Formularen (Registrierung, Kasse) ueber die volle Breite. */
    grid-column: 1 / -1;
}

.altcha-status {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--text-leise);
}

.altcha-status-fehler {
    color: var(--fehler);
}

/* --- AV-Vertrag: Abschluss per Klick (#796) -------------------------------
   Der vollstaendige Vertragstext steht vor dem Haekchen in einer eigenen
   Scroll-Box, damit er gelesen werden kann, ohne dass die Seite mit ihm
   endlos wird. Die Box ist per Tastatur fokussierbar (tabindex im Template),
   sonst liesse sie sich ohne Maus nicht scrollen. */
.av-vertrag-abschluss {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--linie);
}

.av-vertrag-sprache {
    margin-bottom: 1.5rem;
}

.av-vertrag-text {
    max-height: 28rem;
    overflow-y: auto;
    margin: 0.5rem 0 1.5rem;
    padding: 1rem 1.25rem;
    border: 1px solid var(--linie);
    border-radius: 6px;
    background: var(--flaeche);
    font-size: 0.9rem;
    line-height: 1.55;
}

.av-vertrag-text h5 {
    margin: 1.25rem 0 0.5rem;
    font-size: 0.95rem;
}

.av-vertrag-text p,
.av-vertrag-text ul,
.av-vertrag-text ol {
    margin: 0 0 0.75rem;
}

.av-vertrag-text__titel {
    text-align: center;
}

/* --- Bewegung im Kundenbereich -------------------------------------------
   Sieben Muster aus transitions.dev, an den Stellen, an denen sie etwas
   sagen: ein Untermenue waechst aus seinem Menuepunkt, ein Pflichtfeld zeigt
   durch Schuetteln, wo es fehlt, eine bezahlte Rechnung bekommt ihren Haken.
   Keine Bibliothek (Regel 9), nur CSS und bewegung.js.

   Zwei Regeln gelten fuer alles hier:
   1. Ohne JavaScript sieht und funktioniert alles wie vorher. Was ein Skript
      braucht, setzt erst das Skript in Gang; was reines CSS ist, endet immer
      im sichtbaren Ruhezustand.
   2. "Bewegung reduzieren" im Betriebssystem schaltet jede Animation ab
      (Block am Ende dieses Abschnitts; das Skript fragt dieselbe
      Einstellung ab). */
:root {
    --bewegung-kurz: 150ms;
    --bewegung-schnell: 250ms;
    --bewegung-ruhig: 500ms;
    --bewegung-weich: cubic-bezier(0.22, 1, 0.36, 1);
    --dropdown-pre-scale: 0.97;
    --dropdown-closing-scale: 0.99;
    --shake-distance: 6px;
    --shake-overshoot: 4px;
    --shake-dur-a: 80ms;
    --shake-dur-b: 60ms;
    --shake-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --shimmer-dur: 2000ms;
    --shimmer-band: 400%;
    --stagger-distance: 12px;
    --stagger-blur: 3px;
    --check-box: 150ms;
    --check-draw: 350ms;
    --check-uncheck: 150ms;
    --check-len: 15;
}

/* 1. Untermenue der Hauptnavigation (Menu dropdown). Das <details> bleibt;
   das Oeffnen ist reines CSS, das Schliessen spielt bewegung.js mit
   der Klasse is-closing ab, bevor es open wegnimmt. */
.kunden-navigation-dropdown details[open] > ul {
    transform-origin: top left;
    animation: t-dropdown-open var(--bewegung-schnell) var(--bewegung-weich);
}

.kunden-navigation-dropdown details.is-closing > ul {
    opacity: 0;
    transform: scale(var(--dropdown-closing-scale));
    transition:
        transform var(--bewegung-kurz) var(--bewegung-weich),
        opacity var(--bewegung-kurz) var(--bewegung-weich);
}

@keyframes t-dropdown-open {
    from {
        opacity: 0;
        transform: scale(var(--dropdown-pre-scale));
    }
}

.kunden-navigation-dropdown summary .fa-chevron-down {
    transition: transform var(--bewegung-schnell) var(--bewegung-weich);
}

.kunden-navigation-dropdown details[open]:not(.is-closing) > summary .fa-chevron-down {
    transform: rotate(180deg);
}

/* 2. Aufklappbare Bereiche (Accordion expand): die Hoehe tweent
   bewegung.js ueber die Web Animations API, weil sich die Hoehe eines
   <details> in CSS allein nur in Chromium animieren laesst. Hier steht nur,
   was der Inhalt dabei tut. */
details.is-animating {
    overflow: hidden;
}

details.is-animating > :not(summary) {
    transition:
        opacity var(--bewegung-schnell) var(--bewegung-weich),
        filter var(--bewegung-schnell) var(--bewegung-weich);
}

details.is-collapsing > :not(summary) {
    opacity: 0;
    filter: blur(2px);
}

/* 3. Fehler (Error state shake): die seitenweite Fehlermeldung nach einem
   fehlgeschlagenen POST und das eine fehlende Einwilligungs-Haekchen
   schuetteln einmal beim Laden. Ein im Browser fehlendes Pflichthaekchen
   bekommt is-shaking von bewegung.js. */
.jaba-kundenlogin-inhalt .meldung-fehler[role="alert"],
.ankreuzfeld-fehler,
.is-shaking {
    animation: t-input-shake calc(var(--shake-dur-a) * 2 + var(--shake-dur-b) * 2) linear;
}

@keyframes t-input-shake {
    0% { transform: translateX(0); animation-timing-function: var(--shake-ease); }
    28.57% { transform: translateX(var(--shake-distance)); animation-timing-function: var(--shake-ease); }
    57.14% { transform: translateX(calc(var(--shake-distance) * -1)); animation-timing-function: var(--shake-ease); }
    78.57% { transform: translateX(var(--shake-overshoot)); animation-timing-function: var(--shake-ease); }
    100% { transform: translateX(0); }
}

/* 4. Ankreuzfelder (Checkbox check). Das echte Kontrollkaestchen bleibt,
   unsichtbar ueber dem gezeichneten Kaestchen: Tastatur, Formular und
   Vorleseprogramm sehen weiter ein normales Kontrollkaestchen. Die Huelle
   legt bewegung.js an; ohne Skript bleibt es beim Browser-Kaestchen. */
.haken-feld {
    position: relative;
    display: inline-grid;
    flex: 0 0 auto;
    width: 1.125rem;
    height: 1.125rem;
}

.ankreuzfeld-mehrzeilig .haken-feld {
    margin-top: 0.2rem;
}

.ankreuzfeld .haken-feld input[type="checkbox"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.haken-feld .t-check {
    display: grid;
    place-items: center;
    border-radius: 4px;
    background: var(--flaeche);
    box-shadow: inset 0 0 0 1.5px var(--text-leise);
    pointer-events: none;
    transition:
        background var(--check-box) var(--bewegung-weich),
        box-shadow var(--check-box) var(--bewegung-weich);
}

.haken-feld input:checked + .t-check {
    background: var(--akzent-dunkel);
    box-shadow: inset 0 0 0 1.5px var(--akzent-dunkel);
}

.haken-feld input:focus-visible + .t-check {
    outline: 2px solid var(--akzent);
    outline-offset: 2px;
}

.haken-feld input:disabled + .t-check {
    opacity: 0.5;
}

.t-check svg {
    width: 0.72rem;
    height: 0.72rem;
    overflow: visible;
    fill: none;
    stroke: #ffffff;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.t-check svg path {
    stroke-dasharray: var(--check-len);
    stroke-dashoffset: var(--check-len);
    transition: stroke-dashoffset var(--check-uncheck) var(--bewegung-weich);
}

.haken-feld input:checked + .t-check svg path {
    stroke-dashoffset: 0;
    transition: stroke-dashoffset var(--check-draw) var(--bewegung-weich);
}

/* 5. Sicherheitspruefung (Shimmer text): altcha.js setzt t-shimmer und
   data-text, solange gerechnet wird. */
.t-shimmer {
    position: relative;
    display: inline-block;
    color: var(--text-leise);
}

.t-shimmer::before {
    content: attr(data-text);
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: linear-gradient(90deg, transparent 0%, transparent 40%, var(--text) 50%, transparent 60%, transparent 100%);
    background-size: var(--shimmer-band) 100%;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    animation: t-shimmer var(--shimmer-dur) linear infinite;
}

@keyframes t-shimmer {
    0% { background-position: 100% 0; }
    100% { background-position: 0% 0; }
}

/* 6. Zahlung eingegangen (Success check): reines CSS, startet beim Laden.
   stroke-dasharray ist die Laenge des Hakens in payment-returned.html.twig
   (M5 12.5 l4.5 4.5 L19 7.5: 6,4 + 13,4 = 19,8, aufgerundet 21). */
.zahlung-kopf {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.zahlung-kopf h1 {
    margin: 0;
}

.zahlung-haken {
    display: grid;
    flex: 0 0 auto;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    background: var(--erfolg-grund);
    color: var(--erfolg);
}

.t-success-check {
    display: inline-block;
    transform-origin: center;
    will-change: transform, opacity, filter;
    animation:
        t-check-fade var(--bewegung-ruhig) var(--bewegung-weich) both,
        t-check-rotate var(--bewegung-ruhig) var(--bewegung-weich) both,
        t-check-blur var(--bewegung-ruhig) var(--bewegung-weich) both,
        t-check-bob var(--bewegung-ruhig) cubic-bezier(0.34, 1.35, 0.64, 1) both;
}

.t-success-check svg {
    display: block;
    width: 1.625rem;
    height: 1.625rem;
    overflow: visible;
    fill: none;
    stroke: currentColor;
    stroke-width: 3;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.t-success-check svg path {
    stroke-dasharray: 21;
    stroke-dashoffset: 21;
    animation: t-check-draw var(--bewegung-ruhig) var(--bewegung-weich) 80ms forwards;
}

@keyframes t-check-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes t-check-rotate { from { transform: rotate(80deg); } to { transform: rotate(0deg); } }
@keyframes t-check-blur { from { filter: blur(10px); } to { filter: blur(0); } }
@keyframes t-check-bob { from { translate: 0 40px; } to { translate: 0 0; } }
@keyframes t-check-draw { to { stroke-dashoffset: 0; } }

/* 7. Rueckmeldung nach dem Speichern (Texts reveal): die Erfolgs- oder
   Hinweismeldung nach einer Umleitung steigt kurz nach dem Seitenaufbau ein.
   Reines CSS, endet immer sichtbar. Fehlermeldungen nicht: die kommen sofort
   und schuetteln (3). */
.jaba-kundenlogin-inhalt .meldung-erfolg[role="status"],
.jaba-kundenlogin-inhalt .meldung-hinweis[role="status"] {
    animation: t-meldung-einblenden var(--bewegung-ruhig) var(--bewegung-weich) 120ms both;
}

@keyframes t-meldung-einblenden {
    from {
        opacity: 0;
        transform: translateY(var(--stagger-distance));
        filter: blur(var(--stagger-blur));
    }
}

@media (prefers-reduced-motion: reduce) {
    .kunden-navigation-dropdown details[open] > ul,
    .kunden-navigation-dropdown details.is-closing > ul,
    .kunden-navigation-dropdown summary .fa-chevron-down,
    details.is-animating > :not(summary),
    .jaba-kundenlogin-inhalt .meldung-fehler[role="alert"],
    .ankreuzfeld-fehler,
    .is-shaking,
    .haken-feld .t-check,
    .t-check svg path,
    .jaba-kundenlogin-inhalt .meldung-erfolg[role="status"],
    .jaba-kundenlogin-inhalt .meldung-hinweis[role="status"] {
        animation: none !important;
        transition: none !important;
    }

    .t-shimmer::before {
        animation: none !important;
    }

    .t-success-check {
        animation: none !important;
        opacity: 1;
    }

    .t-success-check svg path {
        animation: none !important;
        stroke-dashoffset: 0 !important;
    }
}

/* Spam-Filter je Postfach (#951), Gestaltung C ab #954, an der echten
   Kartenbreite und an gemessenen Kanten nachgezogen in #962.

   **Die Breite, die zaehlt, ist die der Karte, nicht die des Fensters.**
   `.eintragskarten` ist `minmax(28rem, 1fr)`: auf einem 1440er Schirm
   stehen zwei Spalten, jede Karte ist rund 505 px breit. Eine
   `max-width`-Abfrage auf das Fenster greift dort nie. Der schmale
   Aufbau ist deshalb der Normalfall, und eine Container-Query breitet
   ihn erst aus, wenn die Karte wirklich Platz hat. Ein Browser ohne
   `@container` bleibt beim schmalen Aufbau, der ueberall traegt.

   **Die Formulare tragen `formular`**, weil daran die Hausfarbe der
   Knoepfe haengt (`.formular button` → `--akzent-dunkel`). Was hier
   zurueckgenommen wird, sind nur Abstaende, die das Raster selbst regelt
   — und zwar mit `.formular` im Selektor, sonst verliert die Regel gegen
   `.formular button:not(...)` und der Knopf sitzt acht Pixel zu tief. */
.aufklapp-zeile {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.25rem;
    padding: 0.125rem 0;
    color: var(--akzent-dunkel);
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
}

.aufklapp-zeile:hover,
.aufklapp-zeile:focus-visible {
    color: var(--akzent-tief);
}

.aufklapp-zeile .aufklapp-pfeil {
    width: 0.75rem;
    color: var(--text-leise);
    font-size: 0.75rem;
}

.spamfilter {
    container-type: inline-size;
    margin: 0.5rem 0 0.75rem;
    border: 1px solid var(--linie);
    border-radius: var(--radius);
    overflow: hidden;
}

/* Eine Hoehe fuer Eingabefeld, Auswahlfeld und Knopf: sonst steht ein
   `select` 4 px niedriger als das `input` daneben, und genau das sieht
   krumm aus. 44 px ist zugleich das Mass, das `.formular button` fuer
   die Bedienung am Handy vorgibt. */
.spamfilter .feld input,
.spamfilter .feld select {
    min-height: 44px;
}

/* Einstellungen ---------------------------------------------------------- */

.formular.spamfilter-leiste,
.formular.spamfilter-neu,
.spamfilter-tabelle .formular {
    margin-top: 0;
}

.formular.spamfilter-leiste button,
.formular.spamfilter-neu button,
.spamfilter-tabelle .formular button {
    margin-top: 0;
}

.spamfilter-leiste {
    display: grid;
    grid-template-columns: 6.5rem 1fr;
    align-items: end;
    gap: 0.875rem 1rem;
    padding: 1rem;
    background: var(--grund);
}

/* `customer-area.css` setzt `#main-body .feld { margin-bottom: 0.75rem }`.
   Das ist eine ID, gegen die keine Klassenregel ankommt — und weil das
   Raster hier `align-items: end` benutzt, sass der Knopf daneben genau
   diese zwoelf Pixel tiefer als das Feld. Deshalb steht der Praefix hier
   ebenfalls, und nur an den Stellen, wo er noetig ist. Wer diese Regeln
   verschiebt, prueft sie im Kundenbereich, nicht allein. */
.spamfilter-leiste .feld,
#main-body .spamfilter-leiste .feld {
    margin: 0;
    min-width: 0;
}

.spamfilter-leiste .spamfilter-schalter {
    grid-column: 1 / -1;
    margin: 0;
}

.spamfilter-speichern {
    grid-column: 1 / -1;
    justify-self: start;
    white-space: nowrap;
}

.spamfilter-leiste-hinweis {
    margin: 0;
    padding: 0 1rem 1rem;
    background: var(--grund);
    border-bottom: 1px solid var(--linie);
    color: var(--text-leise);
    font-size: 0.8125rem;
}

.spamfilter-aus {
    margin: 1rem 1rem 0;
}

/* Regeln ----------------------------------------------------------------- */

.spamfilter-regelwerk {
    padding: 1rem;
}

.spamfilter-regelwerk h4 {
    margin: 0 0 0.875rem;
}

.spamfilter-neu {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: end;
    gap: 0.875rem 0.75rem;
}

.spamfilter-neu .feld,
#main-body .spamfilter-neu .feld {
    margin: 0;
    min-width: 0;
}

.spamfilter-feld-art {
    grid-column: 1 / -1;
}

.spamfilter-tabelle {
    width: 100%;
    border-collapse: collapse;
    margin: 1.25rem 0 0.75rem;
    table-layout: fixed;
}

.spamfilter-tabelle th {
    padding: 0.4rem 0.5rem;
    border-bottom: 2px solid var(--linie);
    color: var(--text-leise);
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    text-align: left;
    text-transform: uppercase;
}

.spamfilter-tabelle th:first-child {
    width: 8.5rem;
    padding-left: 0;
}

.spamfilter-tabelle th:last-child {
    width: 3.5rem;
    padding-right: 0;
}

.spamfilter-tabelle td {
    padding: 0.5rem;
    border-bottom: 1px solid var(--linie);
    font-size: 0.875rem;
    vertical-align: middle;
}

.spamfilter-tabelle td:first-child {
    padding-left: 0;
}

.spamfilter-tabelle .spamfilter-spalte-aktion {
    padding-right: 0;
}

.spamfilter-adresse {
    overflow-wrap: anywhere;
}

.spamfilter-marke {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.1rem 0.55rem;
    border: 1px solid currentcolor;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
}

.spamfilter-marke.ist-akzeptiert {
    color: var(--erfolg);
}

.spamfilter-marke.ist-abgelehnt {
    color: var(--fehler);
}

/* Nur ein Symbol: den Absender nennt `aria-label`, und in einer Karte von
   440 px sind 90 px fuer das Wort "Entfernen" die Spalte, die der
   E-Mail-Adresse fehlt. Rechtsbuendig in seiner Zelle, nie darueber
   hinaus — ein Knopf, der den Tabellenrand um sechs Pixel ueberragt,
   laesst die ganze Spalte schief aussehen. */
.spamfilter-tabelle .formular button.spamfilter-entfernen,
#main-body .spamfilter-tabelle .formular button.spamfilter-entfernen {
    width: auto;
    min-width: 0;
    min-height: 2.25rem;
    margin-left: auto;
    padding: 0.4rem 0.7rem;
    border: 1px solid var(--linie);
    background: var(--flaeche);
    color: var(--fehler);
    line-height: 1;
}

#main-body .spamfilter-tabelle .formular button.spamfilter-entfernen:hover,
.spamfilter-tabelle .formular button.spamfilter-entfernen:hover {
    background: var(--fehler-grund);
}

.spamfilter-leer td {
    color: var(--text-leise);
}

/* Breite Karte: eine Spalte im Raster, also Platz fuer je eine Zeile. */
@container (min-width: 34rem) {
    .spamfilter-leiste {
        grid-template-columns: 6.5rem minmax(10rem, 18rem) auto 1fr;
        gap: 1rem;
    }

    .spamfilter-leiste .spamfilter-schalter {
        grid-column: auto;
    }

    .spamfilter-speichern {
        grid-column: auto;
        justify-self: end;
    }

    .spamfilter-neu {
        grid-template-columns: 13rem 1fr auto;
    }

    .spamfilter-feld-art {
        grid-column: auto;
    }

    .spamfilter-tabelle th:first-child {
        width: 11rem;
    }
}

.feld-ausgegraut {
    opacity: 0.55;
}
