/* ============================================================
   Praxis Krüger — Components
   Alles mit eigener Fläche, Kante oder Zustand: button, badge,
   card, overlay, menu, input. Reiner Text steht in textstile.css.

   In Kirby wird daraus je eine Datei unter site/snippets/ —
   snippet('button'). Die Klasse hier ist das Aussehen, das
   Snippet das Markup. Werte stehen auch hier keine: jede Zeile
   liest ein Token.

   Zustände: die echten Pseudoklassen und daneben eine erzwungene
   Variante (.is-hover, .is-active, .is-focus), damit sich im
   Styleguide alle Zustände nebeneinander zeigen lassen.
   ============================================================ */

/* ---- Button ----
   Eine Handlung, kein Verweis. Vier Lautstärken.

   Aufbau: Label plus optionaler runder Puck mit Pfeil. Der Puck trägt einen
   Kreis als ::before, der beim Überfahren auf Faktor 32 wächst und den Knopf
   von rechts flutet — die Fläche kommt aus dem Icon, nicht aus dem Nichts.
   Ohne <span class="button-icon"> ist es ein gewöhnlicher Knopf ohne Flut.

   Die Flutfarbe setzt jede Variante selbst über --button-flood; das ist kein
   globales Token, sondern eine lokale Eigenschaft — sie bedeutet in jeder
   Variante etwas anderes. */
.button{
  position:relative;display:inline-flex;align-items:center;gap:var(--space-tight);
  font-size:var(--fs-read);line-height:1.1;
  padding:var(--button-pad-y) var(--button-pad-x)
          calc(var(--button-pad-y) + var(--pad-optical));
  text-decoration:none;cursor:pointer;overflow:hidden;
  /* Die Kante liegt als Innenschatten, nicht als border.
     Grund: overflow:hidden beschneidet auf die POLSTERBOX. Mit echtem Rand
     hört die Flut an dessen Innenkante auf und der Rand bleibt in der alten
     Farbe stehen — ein Strich, den niemand gezeichnet hat. Ohne Rand sind
     Polster- und Randbox dieselbe Fläche, und die Flut deckt bis zur Kante.
     Nebeneffekt: alle vier Varianten haben ohnehin gleiche Maße. */
  border:0;
  box-shadow:inset 0 0 0 var(--button-border-width) var(--button-edge, transparent);
  border-radius:var(--radius-button);
  background:transparent;color:var(--fg-base-default);
  -webkit-tap-highlight-color:transparent;
  transition:background-color .25s, border-color .25s, color .25s;
}
.button:focus-visible,.button.is-focus{
  outline:var(--border-width-strong) solid var(--focus-ring);outline-offset:2px;
}
/* Mit Puck ist die Polsterbox rundum dieselbe. Sichtbar ist rechts aber nicht
   die Puckfläche, sondern das Zeichen darin — und das steht nur auf 56 % der
   Puckbreite. Zwischen Pfeilspitze und Knopfkante liegen damit das Polster
   PLUS die halbe Differenz von Puck zu Zeichen. Links stand dem Wort nur das
   Polster zur Verfügung, es klebte an der Kante. Also bekommt das Wort
   dieselbe Luft, die der Pfeil gegenüber ohnehin hat. Gerechnet, nicht
   geschätzt: dieselben Zahlen, aus denen der Puck und sein Zeichen bestehen. */
.button:has(.button-icon){
  padding:var(--button-pad-puck);
  --button-puck-jetzt:max(var(--button-puck), 1.4em);
  --button-zeichen-luft:calc(var(--button-puck-jetzt) * (1 - .56) / 2);
}
/* Zwei optische Korrekturen am Wort, beide aus --pad-optical, dem Token, das
   im System ohnehin für genau diesen Zweck steht:
   nach oben, weil der Glyphenkasten unter der Grundlinie Platz für Unterlängen
   hält, den „Termin buchen“ nicht braucht — mittig gesetzt sitzt die Tinte
   dadurch zu tief;
   nach rechts, weil ein Buchstabe mehr Luft zur Kante braucht als die volle
   Fläche des Pucks gegenüber. */
.button:has(.button-icon) .button-label{
  top:calc(var(--pad-optical) * -1);
  /* Genau die Luft des Pfeils, ohne Zuschlag: die Seitenluft des Glyphen
     legt von selbst noch ein knappes Pixel drauf, und mehr braucht es
     nicht. */
  margin-left:var(--button-zeichen-luft)}

.button-label{position:relative;z-index:1}
/* Der Puck trägt ein Zeichen, keinen Satz — deshalb eine feste Größe aus
   dem Token. Sie ist aber ein MINDESTMASS, keine feste Kante: steht der Knopf
   in einem größeren Grad, wäre ein fester Puck plötzlich kleiner als die
   Schrift daneben, und der Knopf klemmt. max() lässt ihn mitwachsen, ohne
   dass sich im Fließtextgrad etwas ändert — dort gewinnt weiter das Token. */
.button-icon{
  position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center;
  width:max(var(--button-puck), 1.4em);height:max(var(--button-puck), 1.4em);
  border-radius:var(--radius-puck);color:inherit;
  transition:transform 120ms;
}
.button-icon::before{
  content:'';position:absolute;inset:0;border-radius:var(--radius-puck);z-index:0;
  background:var(--button-flood, transparent);transform:scale(1);
  transition:transform .6s cubic-bezier(.19,1,.22,1), background-color .4s;
}
/* Zwei Zeichen, eine Bedeutung je Zeichen: der waagerechte Pfeil führt
   weiter innerhalb dieser Website, der schräge führt hinaus. Das Zeichen
   steht im Markup, nicht hier — es gehört zum Ziel des Verweises, nicht zur
   Gestalt des Knopfes. */
.button-icon svg{position:relative;z-index:1;width:56%;height:56%;
  fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .3s}
.button:hover .button-icon::before,.button.is-hover .button-icon::before{transform:scale(32)}
.button:hover .button-icon svg,.button.is-hover .button-icon svg{transform:translateX(2px)}
.button:active .button-icon,.button.is-active .button-icon{transform:scale(.95)}
.button:active .button-icon svg,.button.is-active .button-icon svg{transform:none}
/* Wer Bewegung abbestellt hat, bekommt den Zustand ohne die Flut. */
@media (prefers-reduced-motion:reduce){
  .button,.button-icon,.button-icon::before,.button-icon svg{transition:none}
  .button:hover .button-icon::before,.button.is-hover .button-icon::before{transform:scale(1)}
}

/* solid — volle Markenfläche. Höchstens eine pro Ansicht.
   Der Puck ist dunkler als die Fläche und flutet sie auf hover ganz zu. */
.button--solid{background:var(--bg-brand-default);color:var(--fg-on-brand-default);
  --button-flood:var(--bg-wash-negative-subtle)}
.button--solid:hover,.button--solid.is-hover{
  background:var(--bg-brand-hover);--button-flood:var(--bg-wash-negative-strong)}
.button--solid:active,.button--solid.is-active{background:var(--bg-brand-emphasized)}

/* outline — Kante statt Fläche. Der Normalfall.
   Schrift und Kante lesen dieselbe Rolle, und zwar die auf derselben Sprosse
   wie die Vollfläche: derselbe Knopf, einmal gefüllt, einmal offen. Nicht
   fg-brand-default — das ist die Linkfarbe und sitzt tiefer, weil sie als
   Fließtext mehr Kontrast braucht. */
.button--outline{color:var(--fg-brand-emphasized);--button-edge:currentColor;
  --button-flood:var(--bg-wash-subtle)}
.button--outline:hover,.button--outline.is-hover{
  background:var(--bg-brand-default);color:var(--fg-on-brand-default);
  --button-flood:var(--bg-wash-negative-subtle)}
.button--outline:active,.button--outline.is-active{background:var(--bg-brand-emphasized);
  color:var(--fg-on-brand-default)}

/* ghost — nur Text, Fläche erst beim Überfahren. */
/* ghost — nur Text. Die Kante bleibt transparent: kein Strich, aber
   dieselben Maße wie bei solid und outline. */
.button--ghost{color:var(--fg-base-default);--button-flood:transparent}
.button--ghost:hover,.button--ghost.is-hover{background:var(--bg-base-hover);
  --button-flood:var(--bg-wash-subtle)}
.button--ghost:active,.button--ghost.is-active{background:var(--bg-base-active)}

/* danger — löschen, absagen, widerrufen. */
.button--danger{background:var(--bg-destructive-default);color:var(--fg-on-destructive-default);
  --button-flood:var(--bg-wash-negative-subtle)}
.button--danger:hover,.button--danger.is-hover{background:var(--bg-destructive-emphasized);
  --button-flood:var(--bg-wash-negative-strong)}

/* disabled sieht nicht grau aus, sondern schwach — eine Stufe der Rolle.
   Keine Flut: ein gesperrter Knopf darf nicht auf Berührung reagieren. */
.button[disabled],.button.is-disabled{
  background:var(--bg-base-muted);color:var(--fg-base-subtle);
  cursor:not-allowed;pointer-events:none;--button-flood:transparent}

/* ---- Link ----
   Die einzige Betonung im Fließtext. Fett und kursiv existieren in dieser
   Schrift nicht. Liest fg-brand-default, nicht fg-brand-emphasized: als
   kleiner Text braucht der Verweis mehr Kontrast als eine Knopffläche.

   Die Linie ist ein Verlauf, keine text-decoration. Nur so lässt sie sich
   von links nach rechts aufbauen — text-decoration kennt keine Breite, die
   man animieren könnte. Der Preis: sie läuft durch Unterlängen hindurch,
   statt sie auszusparen. Die Stärke ändert sich beim Überfahren nicht; die
   Linie zeichnet sich neu, das ist das ganze Signal. */
/* Das Zeichen für „führt hinaus“ — derselbe schräge Pfeil wie im Puck des
   Knopfes, damit beides dasselbe sagt. Als Maske, nicht als Schriftzeichen:
   so nimmt es die Farbe des Verweises an und hält seine Strichstärke, statt
   sie von einem Emoji-Font zu erben. */
:root{
  --icon-extern:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E");
}
/* Der Pfeil steht auf der Versalhöhe und ist so hoch wie sie: gemessen, nicht
   geschätzt. Ein halber Buchstabenabstand davor hält ihn vom Wort weg. */
a[data-extern]::after{
  content:'';display:inline-block;
  /* --cap-height ist ein Verhältnis ohne Einheit — erst mal 1em ergibt eine
     Länge. Ohne das Rechnen wäre die Angabe ungültig und das Zeichen fort. */
  width:calc(var(--cap-height, .712) * 1em);
  height:calc(var(--cap-height, .712) * 1em);
  margin-left:.14em;
  background:currentColor;
  -webkit-mask:var(--icon-extern) no-repeat center / contain;
  mask:var(--icon-extern) no-repeat center / contain;
}
/* Im Knopf sagt es schon der Puck — zweimal dasselbe Zeichen wäre eins zu viel. */
.button[data-extern]::after{content:none}

a{
  color:var(--fg-brand-default);text-decoration:none;
  background-image:linear-gradient(currentColor, currentColor);
  background-repeat:no-repeat;
  background-size:100% var(--underline-weight);
  /* y=100% ist die Unterkante des inline-Kastens, und die liegt eine ganze
     Unterlänge unter der Grundlinie — von dort aus gesetzt hinge der Strich
     weit unter dem Wort. Die Unterlänge wird deshalb abgezogen: der Nullpunkt
     ist damit die GRUNDLINIE, und --underline-offset schiebt von dort nach
     unten. --descent misst seite.js an der Schrift. */
  background-position:0 calc(100% - var(--descent, .34em) + var(--underline-offset));
  /* Unterlängen aussparen. Ein Verlauf als Hintergrund kennt kein
     skip-ink — das kann nur text-decoration, und die lässt sich nicht von
     links nach rechts aufbauen. Also andersherum: zwei Kopien des Wortes in
     der Farbe des Grundes liegen zwischen Strich und Schrift und stanzen
     ihn dort aus, wo ein g, j, p, q oder y hindurchläuft. */
  text-shadow:.06em 0 var(--bg-base-default), -.06em 0 var(--bg-base-default);
  /* Bricht der Verweis um, bekommt sonst der GANZE Kasten über beide Zeilen
     eine einzige Linie — quer durch den Umbruch, an der falschen Stelle.
     clone gibt jedem Zeilenstück seine eigene. */
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
}
@keyframes strich-neu{
  from{background-size:0 var(--underline-weight)}
  to  {background-size:100% var(--underline-weight)}
}
/* cubic-bezier(.22,1,.36,1): schnell los, weich aus — dieselbe Kurve wie
   die Flut am Knopf, damit sich das System einheitlich bewegt. */
a:hover,a.is-hover{
  animation:strich-neu var(--underline-speed) cubic-bezier(.22,1,.36,1);
}
a:focus-visible,a.is-focus{outline:var(--border-width-strong) solid var(--focus-ring);
  outline-offset:2px;background-image:none}
@media (prefers-reduced-motion:reduce){
  a:hover,a.is-hover{animation:none}
}
/* ---- Auswahl ----
   Markierter Text. Ohne das nimmt der Browser sein eigenes Blau — die einzige
   Farbe im System, die niemand gesetzt hat. */
::selection{background:var(--bg-selection-default);color:var(--fg-selection-default)}

/* Bausteine, die selbst Verweis sein können, bringen ihre Farbe mit — und
   brauchen die Aussparung nicht, weil sie keinen Strich tragen. Ohne das
   läge die Stanzfarbe des Fließtextes auf ihrem eigenen Grund und machte die
   Schrift fett. */
a.button,a.card,a.menu-link,.menu a,.menu--display a{
  background-image:none;animation:none;text-shadow:none}

/* ---- Badge ----
   Kurze Auszeichnung an einem Element. Keine Handlung, kein Verweis.
   Das einzige runde Element im ganzen System. */
/* Polsterung in em, damit sie mit der Schrift des Badges mitwächst.
   Unten etwas mehr als oben: die Zeile sitzt sonst optisch zu tief, weil
   zwischen Versalhöhe und Oberkante mehr Luft steckt als unter der Grundlinie. */
.badge{display:inline-block;font-size:var(--fs-caption);line-height:1.3;
  padding:var(--badge-pad-y) var(--badge-pad-x)
          calc(var(--badge-pad-y) + var(--pad-optical));border-radius:var(--radius-badge);
  background:var(--bg-base-muted);color:var(--fg-base-default);
  vertical-align:.06em;white-space:nowrap}
/* Eine Auszeichnung ist keine Handlung, trägt also keine Markenfarbe.
   Sie tönt statt zu decken — dadurch unterscheidet sie sich vom normalen
   Badge, ohne eine zweite Farbe ins System zu bringen. */
.badge--wash{background:var(--bg-wash-subtle);color:var(--fg-base-default)}
.badge--danger{background:var(--bg-destructive-subtle);color:var(--fg-destructive-default)}

/* ---- Card ----
   Fläche mit eigenem Grund, die auf der Seite liegt — flach, nicht gehoben.
   Die Kante steckt als ganzes Kürzel im Token: eine card ohne Kante gibt es
   nicht. Unsichtbar wird sie, indem border-card-default auf den Grund zeigt. */
.card{background:var(--bg-card-default);color:var(--fg-card-default);
  border:var(--card-border);border-radius:var(--radius-card);padding:var(--space-block)}
/* Card als Verweis: dann hat sie Zustände. */
.card--interactive{display:block;text-decoration:none;color:inherit}
.card--interactive:hover,.card--interactive.is-hover{background:var(--bg-card-hover)}
.card--interactive:active,.card--interactive.is-active{background:var(--bg-base-active)}
.card--interactive:focus-visible,.card--interactive.is-focus{
  outline:var(--border-width-strong) solid var(--focus-ring);outline-offset:2px}

/* ---- Overlay ----
   Menu, popover, dialog. Liegt über der Seite, darum eigener Grund und
   eigene Kante. Kein Schatten: die Fläche trennt sich über ihren Grund,
   nicht über eine Wolke darunter. */
.overlay{background:var(--bg-overlay-default);color:var(--fg-overlay-default);
  border:var(--overlay-border);border-radius:var(--radius-overlay);
  padding:var(--space-tight)}

/* ---- Menu ----
   Liste von Verweisen. Trägt die Zustände auf der Fläche, nicht in der Schrift. */
/* Satzbreite gilt für Fließtext, nicht für eine Navigation — sonst hören
   die Trennlinien mitten auf der Seite auf. */
.menu{list-style:none;margin:0;padding:0;max-width:none}
.menu li{margin:0;padding:0}
.menu li::before{content:none}
.menu a{display:block;text-decoration:none;color:var(--fg-base-default);
  padding:var(--space-tight);
  border-bottom:var(--border-width-hairline) solid var(--border-base-muted)}
.menu a:hover,.menu a.is-hover{background:var(--bg-base-hover)}
.menu a:active,.menu a.is-active{background:var(--bg-base-active)}
.menu a[aria-current="page"],.menu a.is-current{background:var(--bg-base-emphasized)}
.menu a:focus-visible,.menu a.is-focus{
  outline:var(--border-width-strong) solid var(--focus-ring);outline-offset:-2px}

/* ---- Menu, display grade ----
   Die Hauptnavigation der Seite. Dieselbe Komponente im Displaygrad:
   die Zeile trägt sich über die Größe, nicht über eine Fläche.
   Der Abstand kommt aus der Skala — bei 85 px Schrift sind 18 px Polster
   ein Fünftel der Buchstabenhöhe, und die Zeilen kleben zusammen. */
.menu--display a{
  display:flex;align-items:baseline;min-width:0;
  font-size:var(--fs-nav);line-height:var(--lh-title-nav, var(--lh-display));
  letter-spacing:var(--tracking-nav, var(--tracking-display));
  /* Unten mehr als oben, und zwar gemessen, nicht geschätzt: bei line-height 1
     ragt der Glyphenkasten oben wie unten über die Zeilenbox hinaus, aber
     unterschiedlich weit. Von der Zeilenoberkante bis zur Versalhöhe sind es
     +0,20 em, von der Unterlänge bis zur Unterkante −0,11 em. Mit gleicher
     Polsterung steht über dem Wort doppelt so viel Luft wie darunter, und die
     Trennlinie drängt sich an die Unterlängen. Die 0,31 em gleichen genau
     diese Differenz aus — Versalhöhe 0,712, Ascent 1,169, Descent 0,340. */
  padding:var(--space-block) 0 calc(var(--space-block) + var(--menu-optical));
  transition:color .13s;
}
/* Ein langer Titel bricht um, statt in drei Punkten zu enden. Solange eine
   Nummer rechts stand, war das nicht möglich — jetzt gehört die Zeile dem
   Wort allein. text-wrap:balance verteilt die Zeilen gleich lang, statt ein
   einzelnes Wort auf die zweite zu werfen. */
.menu--display a > :first-child{min-width:0;text-wrap:balance}
/* Der Einzug beim Überfahren verschiebt das Wort, statt die Zeile zu
   verengen. Mit Polsterung wurde der Platz schmaler, und ein langer Titel
   brach mitten im Übergang um. transform verändert keine Breite. */
.menu--display a > :first-child{
  transition:transform .13s}
.menu--display a:hover,.menu--display a.is-hover{
  background:var(--bg-base-hover);color:var(--fg-brand-default)}
.menu--display a:hover > :first-child,
.menu--display a.is-hover > :first-child{
  transform:translateX(var(--space-tight))}
.menu--display a[aria-current="page"],.menu--display a.is-current{
  background:var(--bg-base-emphasized)}
/* Noch nicht erreichbar — zurückgenommen, aber nicht ausgegraut. */
.menu--display a.is-locked{color:var(--fg-base-subtle)}

/* ---- Menü als Overlay ----
   Es legt sich über die Seite, statt sie zu verdrängen: rechts angeschlagen,
   volle Höhe. Zu ist es nicht weg, sondern ragt mit einem Anschnitt herein —
   ein dunkler Streifen am Rand, in dem das Zeichen sitzt.

   --menue-breite     wie breit es offen ist
   --menue-anschnitt  wieviel davon immer zu sehen ist
   --menue-fahrt      0 zu, 1 offen, dazwischen der Finger
   Die Kurve ist dieselbe wie die Flut am Knopf: schnell los, weich aus. */
/* Solange die Schrift noch nicht gemessen ist, steht der Anschnitt nicht
   fest — dann darf das Panel auch nicht dorthin fahren, sondern einfach da
   sein. seite.js setzt die Marke, sobald die Messung steht. */
html:not([data-schrift-bereit]) .menu-panel{transition:none}
.menu-panel{
  position:fixed;inset:0 0 0 auto;z-index:50;
  width:var(--menue-breite);
  display:flex;flex-direction:column;
  /* Seitlich kein Polster am Panel, sondern an den Zeilen: so laufen deren
     Flächen und Trennlinien bis an die Kante durch, während der Satz
     denselben Abstand hält wie vorher.
     Oben beginnt die Liste unter dem Zeichen — der Wert ist dessen Höhe samt
     Polster, aus denselben Maßen gerechnet, die das Zeichen selbst hat. */
  padding:calc(var(--burger-spalt) + var(--burger-strich) + var(--gutter) * 2) 0 var(--gutter);
  overflow-y:auto;overscroll-behavior:contain;
  background:var(--bg-overlay-default);color:var(--fg-overlay-default);
  /* Keine Kante: der Streifen trennt sich über seinen eigenen Grund vom
     Rest der Seite, nicht über einen Strich darauf. Jede Linie an dieser
     Stelle liest sich als Naht. */
  transform:translateX(calc((1 - var(--menue-fahrt, 0)) * (100% - var(--menue-anschnitt, 0px))));
  transition:transform .55s cubic-bezier(.19,1,.22,1);
  touch-action:pan-y;
}
/* Der Streifen bleibt sichtbar, die Liste nicht: sonst bliebe sie für
   Tabulator und Sprachausgabe erreichbar, obwohl niemand sie lesen kann. */
/* Geschlossen bleibt der Anschnitt leer. Angeschnittene Wörter im
   Displaygrad sind zu laut für das, was sie sagen sollen — der dunkle
   Streifen und das Zeichen darin genügen als Ankündigung.
   Aus Maus, Tastatur und Vorlesehilfe nimmt das geschlossene Panel
   zusätzlich inert (seite.js). */
.menu-panel:not(.ist-offen) .menu{visibility:hidden}
.menu-panel.wird-gezogen{transition:none;cursor:grabbing;user-select:none}
/* Das seitliche Polster sitzt an der Zeile, nicht am Panel: Fläche und
   Trennlinie laufen damit bis an die Kante, der Satz behält seinen Abstand.
   Der Einzug beim Überfahren sitzt am Wort, nicht an der Zeile. */
.menu-panel .menu a{padding-inline:var(--gutter)}

/* Die Fläche neben dem Menü. Sie verdunkelt nichts — sie fängt nur den
   Klick, der schließt. Deshalb ohne Grund und ohne Übergang. */
.menu-scrim{position:fixed;inset:0;z-index:49;pointer-events:none}
.menu-scrim.ist-offen{pointer-events:auto}

/* Der Auslöser steht oben rechts und bleibt dort, auch wenn das Menü offen
   ist — er liegt über dem Panel. Zwei Striche, die sich zum Kreuz drehen:
   ein Element, zwei Zustände, keine zwei Knöpfe an zwei Orten.
   Kein Zeichensatz, keine Grafik. Maße in einem Token, damit das Zeichen
   zur Seite passt und nicht zu ihr geschätzt wird. */
.menu-knopf{
  position:fixed;top:0;right:0;z-index:51;
  /* Seitlich genau die Luft des Anschnitts — daraus ist seine Breite
     gerechnet, also sitzt das Zeichen darin mittig, ohne dass die Mitte
     irgendwo ausgerechnet werden müsste. */
  display:block;padding:var(--gutter) var(--menue-luft, var(--gutter));
  background:none;border:0;cursor:pointer;color:var(--fg-base-default)}
/* Drei Striche. Der mittlere IST der Kasten, die beiden anderen hängen als
   ::before und ::after oben und unten daran — so braucht es kein drittes
   Element im Markup. --burger-spalt ist der Abstand vom obersten zum
   untersten Strich, also die Höhe des Zeichens. */
.menu-knopf i{display:block;position:relative;
  width:var(--burger-breite);height:var(--burger-strich);
  margin:calc(var(--burger-spalt) / 2) 0;
  background:currentColor;
  transition:background-color .2s}
.menu-knopf i::before,.menu-knopf i::after{
  content:'';position:absolute;left:0;right:0;height:100%;
  background:currentColor;
  transition:transform .45s cubic-bezier(.19,1,.22,1)}
.menu-knopf i::before{top:calc(var(--burger-spalt) / -2)}
.menu-knopf i::after{top:calc(var(--burger-spalt) / 2)}
/* Offen: der mittlere verschwindet, die beiden anderen fahren in die Mitte
   und drehen sich zum Kreuz. Ein Element, zwei Zustände. */
.menu-knopf[aria-expanded="true"] i{background-color:transparent}
.menu-knopf[aria-expanded="true"] i::before{
  transform:translateY(calc(var(--burger-spalt) / 2)) rotate(45deg)}
.menu-knopf[aria-expanded="true"] i::after{
  transform:translateY(calc(var(--burger-spalt) / -2)) rotate(-45deg)}
.menu-knopf:hover{color:var(--fg-brand-default)}
/* Kein Kasten um drei Striche — die Striche selbst zeigen den Fokus an. */
.menu-knopf:focus-visible{outline:none;color:var(--focus-ring)}

@media (prefers-reduced-motion:reduce){
  .menu-panel,.menu-knopf i,
  .menu-knopf i::before,.menu-knopf i::after{transition:none}
}

/* ---- Input ----
   Eingabe im Kontaktformular. Kante wie eine card, Fläche wie die Seite. */
.input{display:block;width:100%;max-width:calc(var(--zeilenmass) * 1ch);
  font-size:var(--fs-read);line-height:var(--lh-body);
  padding:var(--input-pad-y) var(--input-pad-x);
  color:var(--fg-base-default);background:var(--bg-base-default);
  border:var(--border-width-default) solid var(--border-base-default);
  border-radius:var(--radius-input)}
.input::placeholder{color:var(--fg-base-subtle)}
.input:focus-visible,.input.is-focus{outline:var(--border-width-strong) solid var(--focus-ring);
  outline-offset:2px;border-color:var(--border-brand-strong)}
.input.is-invalid{border-color:var(--border-destructive-default)}
/* Die Fehlermeldung darunter — nie nur Farbe, immer auch Text. */
.input-error{font-size:var(--fs-caption);line-height:1.4;
  color:var(--fg-destructive-default);margin:var(--space-tight) 0 0}

/* ---- Stamp ----
   Text auf voller Fläche, ersetzt das Logo. Höchstens einmal pro Seite. */
.stamp{display:inline-block;background:var(--bg-base-negative);color:var(--fg-base-negative);
  font-size:var(--fs-lead);line-height:1.05;
  padding:var(--stamp-pad-y) var(--stamp-pad-x)
          calc(var(--stamp-pad-y) + var(--pad-optical))}

/* ---- Callout ----
   Ganzer Kasten, nicht nur eine Zeile. Für Hinweise und Warnungen. */
.callout{background:var(--bg-base-subtle);color:var(--fg-base-default);
  border-left:var(--border-width-strong) solid var(--border-base-emphasized);
  padding:var(--space-tight) var(--space-block)}
.callout--danger{background:var(--bg-destructive-subtle);color:var(--fg-destructive-emphasized);
  border-left-color:var(--border-destructive-default)}
