/* =========================================================
   components.css – die Bauteile, die jede Seite gleich zeichnet

   Knopf, Abzeichen, Pille und Avatar standen zwangsläufig mehrfach im
   Repo: das Dashboard lädt `style.css`, die Verkaufsseite `landing.css`,
   die Statusseite beide plus `status.css`. Seit Runde 9 sind das vier
   Blätter – und die Gleichheit hielten nur Tests fest, die Werte
   vergleichen. Ein Test, der zwei Kopien gleich hält, ist besser als
   nichts; **eine** Kopie ist besser als der Test.

   Geladen **nach `tokens.css`** (die Werte kommen von dort) und **vor
   dem Seitenblatt** – eine Seite darf eine Variante überschreiben, und
   sie tut es: `.btn-primary` trägt im Dashboard den Verlauf, auf der
   Verkaufsseite die flache Füllung.

   Hier steht nur, was **überall gleich** ist. Was eine Seite allein hat,
   bleibt in ihrem Blatt: `.btn-primary`, `.btn-ghost`, `.btn-danger`,
   `.btn-round` und der Druckblock im Dashboard, `.btn-pfeil` und
   `.btn-status` auf der Verkaufsseite. Die Rechtstexte laden diese Datei
   nicht – sie sind Fließtext und benutzen kein einziges dieser Bauteile.

   Erlaubt sind ausschließlich Token aus `tokens.css`. `style.css`
   überschreibt einige davon (`--surface-2`, `--text`, `--muted`) für das
   Dashboard – definiert ist jedes aber auch öffentlich, sonst fiele die
   Regel auf der Verkaufsseite lautlos aus.
   ========================================================= */

/* -------------------------------------------------------------
   Knöpfe

   Hier standen zwei Systeme nebeneinander. `.btn-small` war keine Größe
   von `.btn`, sondern eine eigenständige Regel weiter unten – 30-mal
   ohne `.btn` benutzt, `.btn` 25-mal ohne sie. Wo beide zusammentrafen,
   gewann schlicht die spätere Regel:
   - `btn btn-ghost btn-small` (8×) bekam von `.btn-small` wieder
     `border: none` und eine Füllung – der Umriss-Knopf sah aus wie ein
     gefüllter, „Suche aufheben" wie „Suchen".
   - `btn btn-primary btn-small` (3×, darunter „Ausführen" in der
     Mod-Queue) verlor den Verlauf an `.btn-small`s Füllung. Die
     wichtigste Aktion der Seite sah aus wie eine Nebensache.
   - `class="btn"` allein (Antwort im Ticket) hatte gar keine Fläche:
     weiße Schrift auf der grauen Vorgabefläche des Browsers.

   Jetzt eine Basis und drei Achsen, die sich nicht ins Gehege kommen –
   Fläche, Größe, Form. Eine Fläche gehört immer dazu:
     Fläche  .btn-primary | .btn-neutral | .btn-ghost | .btn-danger
     Größe   (Vorgabe)    | .btn-sm      | .btn-lg
     Form    .btn-round   (der 22-px-Kreis in Listen)
   Festgenagelt in `tests/test_knoepfe.py`.
*/

.btn {
    /* `inline-flex` statt `inline-block`: der Abstand zwischen Icon und
       Beschriftung kommt damit aus `gap` und muss nicht als Rand am Icon
       hängen (das traf sonst auch Icons ohne Beschriftung). */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    /* Waagerecht zwei Stufen mehr als senkrecht – ein Knopf mit gleichem
       Abstand ringsum wirkt gedrungen. */
    padding: var(--sp-3) var(--sp-5);
    border-radius: var(--radius-md);
    /* Durchsichtige Kante statt gar keiner: sonst wäre der Umriss-Knopf
       2 px höher als der gefüllte daneben. */
    border: 1px solid transparent;
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 700;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    color: #fff;
    transition: transform var(--motion-fast) var(--ease),
                box-shadow var(--motion-fast) var(--ease),
                background var(--motion-fast) var(--ease),
                border-color var(--motion-fast) var(--ease),
                color var(--motion-fast) var(--ease);
}

/* ---- Größe */
.btn-sm { padding: var(--sp-1) var(--sp-3); font-size: var(--fs-xs); border-radius: var(--radius-sm); }
.btn-lg { padding: var(--sp-4) var(--sp-6); font-size: var(--fs-md); }

/* ---- Fläche. Nur die neutrale steht hier: sie ist auf beiden Seiten
   dieselbe. `.btn-primary` und `.btn-ghost` sind es **nicht** (Verlauf
   gegen flache Füllung) und stehen deshalb je im Seitenblatt.

   `color` muss mit: die Basis setzt Weiß, weil die gefüllten Flächen es
   tragen. Dieser Knopf hat keine eigene Farbe, sondern eine Aufhellung
   des Untergrunds – im hellen Thema wäre das weiße Schrift auf Grau. */
.btn-neutral { background: var(--tint-3); color: var(--text); }
.btn-neutral:hover { background: var(--tint-4); }

/* Ein Knopf, der nicht kann, hebt sich auch nicht an. */
.btn:disabled, .btn[disabled] { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover, .btn[disabled]:hover { transform: none; }

/* -------------------------------------------------------------
   Badges: eine Fläche, sechs Bedeutungen

   Dieselbe Geschichte wie beim Knopf: `.badge` stand zweimal im
   Stylesheet – hier und 70 Zeilen weiter unten, wo die zweite Regel
   Schriftgröße und Umbruch der ersten überschrieb. Daneben lagen zwei
   Sätze Varianten, die dasselbe meinten und es verschieden machten:
   `.badge-on/-off/-wait` färbten **nur die Schrift** und behielten die
   violette Fläche der Basis („Online" war grüne Schrift auf einer
   Markenpille), `.badge-green/-yellow/-red` färbten Fläche, Kante und
   Schrift. Der Druckblock kannte nur den ersten Satz.

   Die Namen sagen jetzt die **Bedeutung**, nicht die Farbe: ein
   Hell-Design tauscht Farbwerte, keine Klassennamen. Ohne Variante ist
   die Pille neutral – das ist der Regelfall (Zähler hinter einer
   Überschrift, Aktionsname im Protokoll, „Bot").
   ------------------------------------------------------------- */
.badge {
    display: inline-block;
    padding: var(--sp-0) var(--sp-3);
    border-radius: var(--radius-pill);
    background: var(--primary-bg);
    border: 1px solid var(--primary-border);
    font-size: var(--fs-xs);
    font-weight: 700;
    white-space: nowrap;
    color: var(--text);
}
.badge-on     { background: var(--success-bg); border-color: var(--success-border); color: var(--success-text); }
.badge-off    { background: var(--tint-2);     border-color: var(--border-soft);    color: var(--muted); }
.badge-wait   { background: var(--warning-bg); border-color: var(--warning-border); color: var(--warning-text); }
.badge-danger { background: var(--danger-bg);  border-color: var(--danger-border);  color: var(--danger-text); }
.badge-info   { background: var(--info-bg);    border-color: var(--info-border);    color: var(--info-text); }
/* Eine Pille, die schaltet (Befehl an/aus): der Knopf bringt Fläche,
   Rand und Schriftart des Browsers mit. Vorher stand das als
   `style="background:none;border:none;cursor:pointer"` im Template. */
button.badge { cursor: pointer; font-family: inherit; }
/* Eine Pille, die irgendwohin führt (Zustand auf der Serverkarte: „2 Fälle
   warten" → Mod-Queue). Sie behält die Farbe ihres Zustands – die sagt, wie
   dringend es ist; dass man klicken kann, sagt die Kante beim Zeigen. */
a.badge { text-decoration: none; transition: border-color var(--motion-fast) var(--ease); }
a.badge:hover { border-color: currentColor; }

/* -------------------------------------------------------------
   Pillenreihe: wenige Möglichkeiten, eine davon ist aktiv

   Fünfmal dasselbe Bauteil, fünfmal eigene Werte: der Zeitraum der
   Statistik (`.range-pill`), der Zeitraum über den Listen
   (`.filter-knopf`), der Statusfilter der Mod-Queue (der stand als
   `<style>` **im Template** und blieb damit von jeder Prüfung
   unbehelligt), der Bot-Umschalter und der Sprachumschalter. Vier
   färbten die aktive Pille violett, eine blau – auf dem Bildschirm sah
   das aus, als bedeute Blau etwas anderes als Violett.

   Zwei Fassungen, eine Bedeutung:
     .pillen               freie Reihe (Filter über einer Liste)
     .pillen-eingefasst    eingefasster Umschalter in der Topbar
   Der Verzicht auf einen Farbwechsel bei `:hover` ist Absicht: die
   Schriftstärke bleibt gleich, sonst hüpfte die Reihe bei jedem Klick.
   ------------------------------------------------------------- */
.pillen { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.pillen-eingefasst {
    display: inline-flex;
    flex-wrap: nowrap;
    gap: var(--sp-0);
    padding: var(--sp-1);
    border-radius: var(--radius-pill);
    background: var(--tint-2);
}
.pille {
    padding: var(--sp-1) var(--sp-3);
    border: 1px solid var(--surface-2);
    border-radius: var(--radius-pill);
    color: var(--muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}
.pille:hover { border-color: var(--primary); color: var(--text); }
.pille.active {
    background: var(--primary-fill);
    border-color: var(--primary-fill);
    color: #fff;
}
/* Im eingefassten Umschalter trägt schon die Fassung die Kante. */
.pillen-eingefasst .pille { border-color: transparent; }
.pillen-eingefasst .pille:hover { border-color: transparent; color: var(--link); }
/* Der Sprachumschalter zeigt zwei Kürzel, keine Wörter. */
.pille-klein { font-size: var(--fs-2xs); font-weight: 800; letter-spacing: .04em;
               padding: var(--sp-1) var(--sp-2); }
/* Der Bot-Umschalter schickt ein Formular ab (siehe `button.badge`). */
button.pille { cursor: pointer; font-family: inherit; background: none; }

/* -------------------------------------------------------------
   Rundes Bild: Avatar, Serverbild, Marke

   `border-radius: 50%` stand elfmal im Stylesheet, daneben eine feste
   Größe – 26, 28, 30, 32, 40, 64, 88 px, jede an genau einer Stelle
   ausgedacht. Allein das VANTEX-Logo erschien in drei Größen, je nachdem
   welche Seite man ansah. Fünf Bauteile hießen verschieden und taten
   dasselbe: `.member-avatar`, `.member-avatar-sm`, `.ts-avatar`,
   `.guild-icon img`, `.brand-logo`.

   Die Größen bleiben Zahlen, keine Rasterstufen: ein Avatar ist ein
   Bauteilmaß (siehe der Kommentar zur Radienskala in `tokens.css`). Neu
   ist nur, dass es dieselben Zahlen sind.

   `.avatar-initial` ist die Fassung ohne Bild: der Anfangsbuchstabe auf
   dem Verlauf. Discord liefert nicht für jeden ein Bild, und ein leerer
   Kreis sagt weniger als ein Buchstabe.
   ------------------------------------------------------------- */
.avatar {
    display: block;
    border-radius: 50%;
    object-fit: cover;
    flex: none;
    width: 32px; height: 32px;
}
.avatar-xs { width: 28px; height: 28px; }   /* Marke in der Kopfzeile */
.avatar-sm { width: 32px; height: 32px; }   /* Zeile in einer Liste */
.avatar-md { width: 40px; height: 40px; }   /* Transkript */
.avatar-lg { width: 64px; height: 64px; }   /* Server-Kachel */
.avatar-xl { width: 88px; height: 88px; }   /* Mitglieder-Karte */
.avatar-initial {
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--grad-text); color: #fff; font-weight: 800;
}
.avatar-xs.avatar-initial, .avatar-sm.avatar-initial { font-size: var(--fs-xs); }
.avatar-lg.avatar-initial, .avatar-xl.avatar-initial { font-size: var(--fs-2xl); }
