/* ============================================================
   Komponente: banner
   ------------------------------------------------------------
   Quelle: Figma „Design System" → banner, Komponenten-Satz
   11919:1842, ausgelesen am 04.09.2026.

   Liegt oben am Screen über dem Inhalt, blockiert nicht, und
   BLEIBT STEHEN, BIS DER ZUSTAND ENDET — kein Timer, kein
   Fortschrittsbalken.

   ------------------------------------------------------------
   DIE ABGRENZUNG IST DER GANZE PUNKT
     toast    verschwindet von selbst          → kein ✕
     banner   bleibt, bis der Zustand endet    → ✕ nur, wenn er
              sonst stehen bliebe
     message  dieselbe Gestalt IM FLUSS, unter dem Feld oder im
              Screen                           → nie ein ✕
     dialog   verlangt eine Entscheidung       → nie ein ✕

   Aus der Figma-Doku: „Bleibt der Zustand über die Anzeige
   hinaus bestehen, ist es kein Toast, sondern ein banner."

   ------------------------------------------------------------
   DREI ROLLEN
     fehler   Der Code oder die Eingabe ist das Problem.
     info     Die Ursache liegt weder beim Nutzer noch bei uns
              (offline, Zugang läuft ab).
     zugang   Kein Fehler, sondern ein Zustand. Neutrale Karte,
              KEIN Icon.

   DREI AKTIONEN
     keine    Es gibt nichts zu tun. Token-Fehler tragen nie
              einen Button — denselben Code erneut zu senden
              ändert nichts.
     link     Textlink unter dem Text: „du kannst es nochmal
              versuchen".
     button   Button small rechts daneben: „das ist der Weg".

   DIE MATRIX IST BEWUSST NICHT VOLL BESETZT. `aktion=button`
   gibt es nur bei `rolle=zugang`. Ein Fehler ist kein Fehler
   mehr, wenn wir einen Weg anbieten können, und ein Hinweis
   informiert, statt zu führen. Der Primär-Button bleibt dem
   Zugang vorbehalten, damit „Zugang aktivieren" im ganzen
   Produkt derselbe Knopf ist.

   ZWEI AUSRICHTUNGEN
     mittig   Icon auf halber Höhe. Nur bei keine und button,
              also solange der Text zweizeilig bleibt.
     oben     Icon auf Höhe der ersten Zeile. IMMER bei
              aktion=link — der Link macht den Banner so hoch,
              dass ein mittiges Icon neben dem Nichts stünde.

   Das ✕ gibt es nur bei fehler und info. `zugang` trägt nie
   eines: der Zustand endet erst mit dem Wechsel nach Ziel A.
   Es ist 45 x 45 (§11.2) — NICHT gegen `close icon button
   small` (30) tauschen, der ist für Flächen gedacht, die von
   selbst verschwinden.

   Setzt tokens.css und base.css voraus, für aktion=link
   zusätzlich components/link-button.css und für aktion=button
   components/button.css.

   VERWENDUNG
     <div class="banner banner--fehler banner--oben" role="alert">
       <div class="banner__zeile">
         <div class="banner__row">
           <span class="banner__icon">
             <svg class="ikon" aria-hidden="true">…</svg>
           </span>
           <div class="banner__texte">
             <div class="banner__zeilen">
               <p class="banner__titel">Titel</p>
               <p class="banner__untertitel">Beschreibung</p>
             </div>
             <button class="link-button" type="button">…</button>
           </div>
         </div>
         <button class="banner__schliessen" type="button"
                 aria-label="Meldung schließen">…</button>
       </div>
     </div>

   ------------------------------------------------------------
   GEMESSENE MASSE OHNE TOKEN-GRUNDLAGE
     17,18  Icon (info und attention).
     10     ✕ im Schließen-Knopf.
     3      Blur hinter dem Schließen-Knopf.
   ============================================================ */

.banner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-sm);                    /* 12 */

  width: 100%;                             /* Figma: FILL */
  padding: var(--space-md);                /* 16 */
  border-radius: var(--radius-md);         /* 20 */

  /* Der Strich als innerer Schatten, nicht als border: er liegt
     in Figma INNEN und darf die automatische Höhe nicht
     vergrößern (AGENTS.md §8a). */
  --banner-outline: transparent;
  box-shadow: inset 0 0 0 var(--outline-default) var(--banner-outline);
}

.banner__zeile {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);                    /* 8 */
  width: 100%;
}

.banner__row {
  display: flex;
  flex: 1 0 0;
  min-width: 0;
  gap: var(--space-xs);                    /* 8 */
  align-self: stretch;
  align-items: center;                     /* ausrichtung=mittig */
}

/* ausrichtung=oben: das Icon steht auf Höhe der ERSTEN Zeile,
   nicht auf halber Banner-Höhe. */
.banner--oben .banner__row {
  align-items: flex-start;
}

/* Das Icon sitzt in einem Kasten mit 4 Polster oben und unten —
   so kommt es auf dieselbe optische Achse wie die erste
   Textzeile, deren Zeilenhöhe 150 % ist. Dieselbe Lösung wie in
   message.css. */
.banner__icon {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  padding-block: var(--space-2xs);         /* 4 */
}

.banner__icon .ikon {
  display: block;
  overflow: visible;
  width: 17.18px;                          /* gemessen, siehe Kopf */
  height: 17.18px;
}

.banner__texte {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-xs);                    /* 8 */
  flex: 1 0 0;
  min-width: 0;
}

/* Die 8 Einrückung links stehen an den ZEILEN, nicht am Icon —
   so bleibt der Text auch dann eingerückt, wenn es kein Icon
   gibt (rolle=zugang). */
.banner__zeilen {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2xs);                   /* 4 */
  padding-left: var(--space-xs);           /* 8 */
  width: 100%;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

.banner__titel {
  margin: 0;
  font-family: var(--font-family-inter);
  font-size: var(--font-size-title-text);
  line-height: var(--line-height-title-text);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--letter-spacing-small-text-bold);   /* 1 % */
}

.banner__untertitel {
  margin: 0;
  font-family: var(--font-family-inter);
  font-size: var(--font-size-small-text);
  line-height: var(--line-height-small-text);
  font-weight: var(--font-weight-regular);
}

/* ------------------------------------------------------------
   Rollen
   ------------------------------------------------------------
   Farbe ist NIE das alleinige Signal (WCAG 1.4.1): fehler und
   info tragen zusätzlich ihr Icon, zugang trägt keines und ist
   daran zu erkennen, dass es neutral ist.
   ------------------------------------------------------------ */

.banner--fehler {
  background-color: var(--warning-red-fill);
  --banner-outline: var(--red-label-stroke);
}

.banner--fehler .banner__icon {
  color: var(--red-label-text);
}

.banner--info {
  background-color: var(--blue-label-fill);
  --banner-outline: var(--blue-label-stroke);
}

.banner--info .banner__icon {
  color: var(--blue-label-text);
}

/* Zugang ist kein Fehler, sondern ein Zustand — deshalb die
   neutrale Karte und kein Icon. */
.banner--zugang {
  background-color: var(--surface-card);
  --banner-outline: var(--label-outline);
}

/* ------------------------------------------------------------
   Schließen
   ------------------------------------------------------------
   45 x 45 nach §11.2, mit Blur dahinter: der Banner liegt in
   #101–#111 über dem Kamerabild, und dort trägt eine
   durchsichtige Fläche die Lesbarkeit nicht (§18).
   ------------------------------------------------------------ */

.banner__schliessen {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  width: 45px;                             /* gemessen, siehe Kopf */
  height: 45px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-full);
  background: none;
  backdrop-filter: blur(3px);              /* gemessen, siehe Kopf */
  color: var(--text-primary);
  cursor: pointer;
}

.banner__schliessen .ikon {
  display: block;
  overflow: visible;
  width: 10px;                             /* gemessen, siehe Kopf */
  height: 10px;
}

@media (hover: hover) and (pointer: fine) {
  .banner__schliessen:hover {
    background-color: var(--button-icon-button-fill-hover);
  }
}

.banner__schliessen:active {
  background-color: var(--button-icon-button-fill-press);
  box-shadow: inset 0 0 0 var(--outline-default) var(--button-icon-button-outline-press);
}

.banner__schliessen {
  transition:
    background-color calc(var(--motion-press) * var(--motion-scale)) var(--motion-ease-out),
    box-shadow       calc(var(--motion-press) * var(--motion-scale)) var(--motion-ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .banner__schliessen {
    transition: none;
  }
}

/* ============================================================
   OFFEN
   ------------------------------------------------------------
   · Hover und Press am Schließen-Knopf stehen nicht an der
     Komponente. Beide sind hier aus dem Icon-Button übernommen,
     weil es derselbe Knopf in anderer Umgebung ist.
   · Die Rolle `zugang` mit `aktion=button` verlangt einen
     Button small rechts NEBEN dem Text. Die Anordnung dafür
     steht in Figma nur als eine Variante da; hier ist sie noch
     nicht gebaut.
   ============================================================ */
