/* ============================================================
   code dimension — Komponenten
   ============================================================
   Bauteile, die auf mehreren Seiten und in mehreren
   Inhaltselementen vorkommen: Knoepfe, Symbole, Karten, Kicker,
   Abschnittskoepfe, Chips, Formularfelder.
   ============================================================ */

/* ------------------------------------------------------------
   Knoepfe
   ------------------------------------------------------------ */
.cd-knopf {
  display: inline-flex;
  align-items: center;
  gap: var(--cd-a3);
  /* Polsterung plus Rand ergibt 13/20 — das Mass der Vorlage.
     Der DURCHSICHTIGE Rand ist der Trick: Ohne ihn traegt nur die
     Umriss-Fassung einen Rahmen und ist dadurch zwei Pixel hoeher
     als die gefuellte. Bei automatischer Hoehe zaehlt der Rand mit,
     und box-sizing aendert daran nichts — es wirkt nur dort, wo
     eine Hoehe gesetzt ist. So sind beide Fassungen gleich gross,
     ohne dass irgendwo eine Zahl nachgerechnet werden muss. */
  padding: 12px 19px;
  border: 1px solid transparent;
  border-radius: var(--cd-r-knopf);
  font-family: var(--cd-schrift-text);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .01em;
  line-height: 1.25;
  cursor: pointer;
  transition: background var(--cd-zeit) ease,
              color var(--cd-zeit) ease,
              border-color var(--cd-zeit) ease,
              transform var(--cd-zeit) ease;
}

/* Die Randfarbe steht ausdruecklich dabei, obwohl der Grundknopf
   schon einen durchsichtigen Rand mitbringt: Ohne Angabe waere die
   Farbe currentColor — also Weiss — und der gefuellte Knopf bekaeme
   einen weissen Ring, sobald eine Regel den Rand sichtbar macht. */
.cd-knopf--rot {
  background: var(--cd-rot);
  border-color: var(--cd-rot);
  color: var(--cd-weiss);
}
.cd-knopf--rot:hover {
  background: var(--cd-rot-tief);
  border-color: var(--cd-rot-tief);
  color: var(--cd-weiss);
  transform: translateY(-1px);
}

/* Nur die Randfarbe — Staerke und Polsterung kommen aus dem
   Grundknopf, sonst laufen die beiden Fassungen wieder
   auseinander. */
.cd-knopf--linie {
  background: transparent;
  border-color: var(--cd-linie);
  color: var(--cd-dunkel);
}
.cd-knopf--linie:hover {
  border-color: var(--cd-dunkel);
  color: var(--cd-dunkel);
}

/* Auf dunklem Grund kehrt sich die Randfarbe um — sonst
   verschwindet der Rahmen (1.4.11). */
.cd-auf-dunkel .cd-knopf--linie {
  border-color: var(--cd-linie-auf-dunkel);
  color: var(--cd-weiss);
}
.cd-auf-dunkel .cd-knopf--linie:hover { border-color: var(--cd-weiss); }

/* Der Pfeil laeuft in der Monospace-Schrift und mit eigener
   Zeilenhoehe — sonst wird der Knopf 5 px breiter als in der
   Vorlage und die Navigation verschiebt sich mit. */
.cd-knopf__pfeil {
  font-family: var(--cd-schrift-mono);
  font-size: 14px;
  line-height: 1;
  transition: transform var(--cd-zeit) var(--cd-kurve);
}
.cd-knopf:hover .cd-knopf__pfeil { transform: translateX(3px); }

/* Bewegung nur, wo sie erwuenscht ist. */
@media (prefers-reduced-motion: reduce) {
  .cd-knopf:hover { transform: none; }
  .cd-knopf:hover .cd-knopf__pfeil { transform: none; }
}

/* ------------------------------------------------------------
   Symbole
   ------------------------------------------------------------
   Inline-SVG, nie eine Symbolschrift: Zeichen aus dem
   Privatnutzungsbereich landen sonst im zugaenglichen Namen des
   Links und werden vorgelesen.
   ------------------------------------------------------------ */
.cd-symbol {
  flex: 0 0 auto;
  display: block;
}

/* ------------------------------------------------------------
   Abschnittskopf
   ------------------------------------------------------------
   Zweispaltig: links Titel, rechts Beitext oder Knopf. Unter
   900 px untereinander.
   ------------------------------------------------------------ */
.cd-kopfzeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 26rem);
  align-items: end;
  gap: var(--cd-a6);
  margin-block-end: 52px;
}
.cd-kopfzeile__text { max-inline-size: none; }

/* 11,5px mit .18em Sperrung und 20px Abstand nach unten — so
   steht der Kicker an allen zwoelf Stellen des Entwurfs. Enger
   gesetzt wirkt er wie eine Bildunterschrift statt wie ein
   Abschnittsschild. */
.cd-kicker {
  display: block;
  font-family: var(--cd-schrift-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--cd-rot);
  margin-block-end: 20px;
}
.cd-auf-dunkel .cd-kicker { color: var(--cd-rot-auf-dunkel); }

/* --cd-text-schwach traegt auf hellem Grund KEINEN Text:
   #7E97A2 ergibt auf Weiss 3,07:1 und auf --cd-flaeche-2 2,81:1 —
   beides unter den 4,5:1, die 1.4.3 fuer diese Groesse verlangt.
   Der Token ist fuer Zier gedacht (Trennstriche, Punkte), nicht
   fuer Zeichen, die jemand lesen soll. Die Zeile stand hier
   trotzdem und lief damit auf jeder weissen Referenzkarte
   ("typo3 · 2023") durch die Pruefung.

   Jetzt zwei Farben statt einer, nach demselben Muster wie der
   Kicker eine Zeile weiter unten:
     hell   --cd-text-3          Weiss 5,24:1 · getoent 4,79:1
     dunkel --cd-text-auf-dunkel-2  Bahn 6,28:1 · Karte 5,31:1
   Keine der beiden traegt auf dem jeweils anderen Grund; deshalb
   MUSS die dunkle Regel mitgezogen werden, wenn die helle steht. */
.cd-nummer {
  font-family: var(--cd-schrift-mono);
  font-size: var(--cd-gr-mikro);
  letter-spacing: .1em;
  color: var(--cd-text-3);
}
.cd-auf-dunkel .cd-nummer { color: var(--cd-text-auf-dunkel-2); }

@media (max-width: 900px) {
  .cd-kopfzeile {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: var(--cd-a4);
  }
}

/* ------------------------------------------------------------
   Karten
   ------------------------------------------------------------ */
.cd-karte {
  display: flex;
  flex-direction: column;
  gap: var(--cd-a3);
  padding: var(--cd-a5);
  background: var(--cd-weiss);
  border: 1px solid var(--cd-linie-2);
  border-radius: var(--cd-r-karte);
  transition: border-color var(--cd-zeit) ease, box-shadow var(--cd-zeit) ease;
}
.cd-karte:hover {
  border-color: var(--cd-linie);
  box-shadow: var(--cd-schatten-karte);
}
.cd-karte__titel { font-size: var(--cd-gr-h4); }
.cd-karte__text { font-size: var(--cd-gr-klein); color: var(--cd-text-2); }

/* Symbolkachel, 48 px, rot getoent. */
.cd-karte__kachel {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 48px;
  block-size: 48px;
  border-radius: var(--cd-r-knopf);
  background: color-mix(in srgb, var(--cd-rot) 8%, transparent);
  color: var(--cd-rot);
}

/* Der Weiterlink steht dauerhaft da, nicht erst beim Zeigen —
   ein Ziel, das nur bei :hover erscheint, existiert fuer
   Tastatur und Fingertipp nicht verlaesslich. */
.cd-karte__mehr {
  margin-block-start: auto;
  padding-block-start: var(--cd-a3);
  font-size: var(--cd-gr-klein);
  font-weight: 600;
  color: var(--cd-rot);
}

/* ------------------------------------------------------------
   Chips
   ------------------------------------------------------------ */
.cd-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--cd-a2);
  padding: 6px 12px;
  border: 1px solid var(--cd-linie);
  border-radius: var(--cd-r-feld);
  font-size: var(--cd-gr-klein);
  color: var(--cd-text-2);
}

/* ------------------------------------------------------------
   Abzeichen
   ------------------------------------------------------------
   "Neu", "Top", "Aktion" — ein kurzes Wort, das etwas aus der Reihe
   hebt. Vier Fassungen.

   Es hiess zuerst cd-navmarke und sass nur an Menuepunkten. Dasselbe
   Bauteil wird an einer Referenzkachel gebraucht, und ein Name, der
   den Ort nennt statt die Sache, waere dort eine Luege.

   ES HEISST NICHT cd-marke. Der Name war schon vergeben: cd-marke
   ist die WORTMARKE im Seitenkopf — das Logo. Der Versuch, das
   Abzeichen so zu nennen, hat dem Logo eine rote Pille mit
   Versalien verpasst. "Marke" heisst im Deutschen beides; der
   Klassenname muss sich entscheiden, und er war zuerst beim Logo.

   Steht sie in einem Verweis, gehoert ihr Text zu dessen Namen und
   sie ist kein zweites Ziel im Tabulator.

   Die Schriftgroesse liegt unter der allgemeinen Mindestgroesse.
   Das ist hier vertretbar, weil die Marke kein Text zum Lesen ist
   sondern ein Zeichen neben einem Wort, das in voller Groesse
   danebensteht — und weil ihr Inhalt fuer die Bedienung nicht
   noetig ist.
   ------------------------------------------------------------ */
.cd-abzeichen {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  margin-inline-start: 7px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--cd-rot);
  color: var(--cd-weiss);
  font-family: var(--cd-schrift-mono);
  font-size: 9.5px;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
  /* Die Marke haengt an der Oberkante des Wortes und nicht an der
     Grundlinie — sonst sitzt sie optisch zu tief. */
  align-self: center;
}

.cd-abzeichen--dunkel {
  background: var(--cd-dunkel);
  color: var(--cd-weiss);
}

.cd-abzeichen--linie {
  background: none;
  color: var(--cd-rot);
  border: 1px solid currentColor;
  /* Der Rahmen bringt zwei Pixel mit; ohne den Abzug stuende die
     umrandete Fassung hoeher als die gefuellte. */
  padding: 1px 6px;
}

/* Der Punkt traegt kein sichtbares Wort. Feste Groesse statt
   Innenabstand: ein Innenabstand um einen leeren Kasten ergaebe je
   nach Schrift eine andere Groesse. */
.cd-abzeichen--punkt {
  inline-size: 7px;
  block-size: 7px;
  min-inline-size: 7px;
  padding: 0;
  align-self: flex-start;
  margin-block-start: 3px;
}

/* Auf dunklem Grund — Fusszeile und dunkle Bahnen. */
.cd-auf-dunkel .cd-abzeichen--dunkel,
.cd-fuss .cd-abzeichen--dunkel {
  background: var(--cd-weiss);
  color: var(--cd-dunkel);
}
.cd-auf-dunkel .cd-abzeichen--linie,
.cd-fuss .cd-abzeichen--linie { color: var(--cd-rot-auf-dunkel); }

/* ------------------------------------------------------------
   Akkordeon
   ------------------------------------------------------------
   Ohne JavaScript bleiben alle Antworten sichtbar — der Inhalt
   steht vor dem Verhalten.
   ------------------------------------------------------------ */
/* Dauer des Aufklappens. Sie steht als eigene Eigenschaft am body
   (Site-Einstellung) und laesst sich an einer Bahn ueberschreiben —
   der Wert wird vererbt, deshalb genuegt der blosse Attributselektor
   ohne Bezug auf das Element, an dem das Attribut haengt.

   0ms ist kein Sonderfall sondern die Abschaltung: eine Bewegung
   ueber 0ms ist ein Sprung. So muss keine Regel weiter unten wissen,
   ob Bewegung ueberhaupt erwuenscht ist. */
[data-klappen="ohne"]  { --cd-klapp: 0ms; }
[data-klappen="sanft"] { --cd-klapp: 260ms; }
[data-klappen="ruhig"] { --cd-klapp: 460ms; }

/* Wer Bewegung abbestellt hat, bekommt keine — unabhaengig von der
   Einstellung. Steht NACH den Fassungen: gleiche Gewichtung, die
   spaetere Regel gewinnt. */
@media (prefers-reduced-motion: reduce) {
  [data-klappen] { --cd-klapp: 0ms; }
}

.cd-akkordeon__punkt {
  border-block-end: 1px solid var(--cd-linie-2);
  /* Nur hier und nicht an der Wurzel: interpolate-size erlaubt es,
     ein auto zu ueberblenden — an der Wurzel gaelte das fuer den
     ganzen Auftritt und koennte anderswo eine Bewegung ausloesen,
     die dort nie vorgesehen war. Die Eigenschaft vererbt sich und
     erreicht so auch ::details-content. */
  interpolate-size: allow-keywords;
}
.cd-akkordeon__frage {
  inline-size: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cd-a4);
  padding-block: var(--cd-a5);
  background: none;
  border: 0;
  text-align: start;
  font-family: var(--cd-schrift-display);
  font-size: var(--cd-gr-h4);
  font-weight: 600;
  cursor: pointer;
}
.cd-akkordeon__zeichen {
  flex: 0 0 auto;
  position: relative;
  inline-size: 16px;
  block-size: 16px;
}
.cd-akkordeon__zeichen::before,
.cd-akkordeon__zeichen::after {
  content: "";
  position: absolute;
  inset-block-start: 7px;
  inset-inline: 0;
  block-size: 2px;
  background: var(--cd-rot);
  /* Das Zeichen laeuft im Takt der Antwort: steht die Dauer auf
     0ms, springt auch das Plus zum Minus. */
  transition: transform var(--cd-klapp, var(--cd-zeit)) var(--cd-kurve);
}
.cd-akkordeon__zeichen::after { transform: rotate(90deg); }

/* Offen heisst Minus: der zweite Strich legt sich auf den ersten.
   Es gibt ZWEI Bauarten von Akkordeon im Haus, und beide muessen
   hier stehen:

   - <button aria-expanded="true">  — dort, wo ein Skript schaltet
   - <details open>                 — dort, wo der Browser schaltet

   Die zweite Zeile stand frueher nur in bahnen/cd_faq.css und war
   auf .cd-faq__punkt gemuenzt. Das Akkordeon der Projektseiten
   benutzt dasselbe Bauteil, aber nicht diese Klasse — dort blieb
   das Zeichen deshalb auf Plus stehen, obwohl die Antwort aufging.
   Eine Regel, die zum Bauteil gehoert, gehoert zum Bauteil. */
.cd-akkordeon__frage[aria-expanded="true"] .cd-akkordeon__zeichen::after,
.cd-akkordeon__punkt[open] .cd-akkordeon__zeichen::after {
  transform: rotate(0deg);
}
/* Die Antwort faehrt auf.
   ::details-content ist der Kasten, den der Browser selbst um den
   Inhalt eines <details> legt. Ohne ihn braeuchte es eine zusaetzliche
   Huelle im Markup und ein Skript, das ihre Hoehe misst — und das
   Akkordeon liefe dann nicht mehr ohne JavaScript.

   block-size laesst sich nur dann von 0 auf auto ueberblenden, wenn
   interpolate-size gilt (oben am Punkt gesetzt). Kann ein Browser das
   nicht, klappt die Antwort schlicht sofort auf: der Inhalt steht in
   beiden Faellen vollstaendig da.

   content-visibility muss mitwandern. Sie kennt keine Zwischenwerte —
   ohne allow-discrete verschwaende die Antwort sofort und die Hoehe
   liefe ins Leere hinterher. transition-behavior steht als eigene
   Zeile und nicht in der Kurzschreibweise: ein Browser, der das Wort
   nicht kennt, verwirft sonst die GANZE transition-Angabe und damit
   auch die Hoehe. */
.cd-akkordeon__punkt::details-content {
  block-size: 0;
  overflow: clip;
  transition:
    block-size var(--cd-klapp, 260ms) var(--cd-kurve),
    content-visibility var(--cd-klapp, 260ms) var(--cd-kurve);
  transition-behavior: allow-discrete;
}
.cd-akkordeon__punkt[open]::details-content { block-size: auto; }

/* Der gemessene Rueckfall fuer Browser ohne interpolate-size. Die
   Klasse setzt das Skript nur dort; ohne Skript bleibt es bei auto
   und damit beim Sprung. */
.cd-klappmass .cd-akkordeon__punkt[open]::details-content {
  block-size: var(--cd-klapphoehe, auto);
}

/* Der Text kommt eine Spur nach. Ohne das faehrt nur ein leerer
   Kasten auf, in dem der Inhalt von der ersten Zehntelsekunde an
   fertig steht.

   Die 0 als Ausgangswert ist unbedenklich: Ist die Antwort zu, hat
   der Browser sie ohnehin nicht gerendert. Und wo ::details-content
   fehlt, blendet wenigstens der Text ein. */
.cd-akkordeon__antwort {
  padding-block-end: var(--cd-a5);
  color: var(--cd-text-2);
  opacity: 0;
  translate: 0 -.4rem;
  transition:
    opacity var(--cd-klapp, 260ms) var(--cd-kurve),
    translate var(--cd-klapp, 260ms) var(--cd-kurve);
}
.cd-akkordeon__punkt[open] .cd-akkordeon__antwort {
  opacity: 1;
  translate: 0 0;
}

/* ------------------------------------------------------------
   Schieber mit Selbstlauf
   ------------------------------------------------------------
   Der Anhalte-Knopf ist Pflicht, sobald der Selbstlauf laeuft
   (WCAG 2.2.2). Er laesst sich im Backend NICHT abschalten.
   ------------------------------------------------------------ */
.cd-schieber { position: relative; }
.cd-schieber__bedienung {
  display: flex;
  align-items: center;
  gap: var(--cd-a2);
  margin-block-start: var(--cd-a5);
}
.cd-schieber__knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 40px;
  block-size: 40px;
  background: var(--cd-weiss);
  border: 1px solid var(--cd-linie);
  border-radius: var(--cd-r-feld);
  cursor: pointer;
}
.cd-schieber__knopf:hover { border-color: var(--cd-dunkel); }
.cd-schieber__punkte { display: flex; gap: 6px; margin-inline-start: var(--cd-a3); }
.cd-schieber__punkt {
  inline-size: 8px;
  block-size: 8px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--cd-linie);
  cursor: pointer;
}
.cd-schieber__punkt[aria-current="true"] { background: var(--cd-rot); }

/* Die Punktreihe ist bewusst flach — ihre Zielflaeche kommt aus
   einem unsichtbaren Polster, damit 2.5.8 trotzdem erfuellt ist. */
.cd-schieber__punkt::before {
  content: "";
  position: absolute;
  inline-size: var(--cd-zielgroesse, 24px);
  block-size: var(--cd-zielgroesse, 24px);
  transform: translate(-50%, -50%);
}

/* ------------------------------------------------------------
   Formularfelder
   ------------------------------------------------------------ */
.cd-feld { display: grid; gap: 6px; }
.cd-feld__label { font-size: var(--cd-gr-klein); font-weight: 600; }
.cd-feld__eingabe {
  inline-size: 100%;
  padding: 12px 14px;
  background: var(--cd-weiss);
  border: 1px solid var(--cd-linie);
  border-radius: var(--cd-r-feld);
  font: inherit;
  /* NICHT inherit. Das Feld bringt seinen eigenen weissen Grund
     mit — die Schrift darf deshalb nicht die der Bahn erben. Auf
     einer dunklen Bahn stand hier helles Grau auf Weiss und kam
     gemessen auf 1,9:1; man sah beim Tippen nicht, was man schrieb.
     Der Grund ist gesetzt, also gehoert die Schrift dazu. */
  color: var(--cd-tinte);
}
/* Der Platzhalter ist Hilfstext und darf leiser sein — aber lesbar.
   --cd-text-schwach traegt auf Weiss nur 3,07:1 und ist fuer Zier
   gedacht, siehe die Notiz zur hellen Insel. */
.cd-feld__eingabe::placeholder { color: var(--cd-text-3); opacity: 1; }
/* OFFEN, bewusst nicht hier entschieden: Der Rahmen ist die Grenze
   eines Bedienelements und braucht nach WCAG 1.4.11 3:1 gegen seinen
   Grund. --cd-linie kommt auf 1,29:1 gegen Weiss und 1,17:1 gegen den
   getoenten Formularkasten. Ein tragender Ton waere --cd-linie-auf-dunkel
   (4,38:1 gegen den Kasten) — das aendert aber das Aussehen JEDES
   Formulars der Seite und ist deshalb eine Entwurfsentscheidung, keine
   Reparatur. */
.cd-feld__eingabe:focus-visible { border-color: var(--cd-rot); }
.cd-feld__fehler { font-size: var(--cd-gr-klein); color: var(--cd-rot); }

/* Pflichtkennzeichen nicht allein ueber Farbe. */
.cd-feld__pflicht::after { content: " *"; color: var(--cd-rot); }

/* ------------------------------------------------------------
   Bahnen auf dunklem oder rotem Grund
   ------------------------------------------------------------ */
.cd-auf-dunkel { background: var(--cd-dunkel); color: var(--cd-text-auf-dunkel); }
.cd-auf-dunkel h1, .cd-auf-dunkel h2, .cd-auf-dunkel h3, .cd-auf-dunkel h4 { color: var(--cd-weiss); }
.cd-auf-dunkel a { color: var(--cd-weiss); }

/* Das rote Band traegt in der Vorlage merklich weniger Luft als
   eine helle Bahn — 96 statt 118 bei 1440px. Eine gesaettigte
   Flaeche wiegt optisch schwerer; mit derselben Luft wirkte sie
   aufgeblasen. Gesetzt wird der TOKEN und nicht das padding: so
   sticht eine Stufe, die die Redaktion am Element waehlt,
   weiterhin. */
.cd-auf-rot { --cd-bahn: clamp(52px, 6.7vw, 96px); }

.cd-auf-rot { background: var(--cd-rot); color: var(--cd-weiss); }
.cd-auf-rot h1, .cd-auf-rot h2, .cd-auf-rot h3, .cd-auf-rot h4 { color: var(--cd-weiss); }
.cd-auf-rot a { color: var(--cd-weiss); }
.cd-auf-rot :where(a, button, [tabindex]):focus-visible { outline-color: var(--cd-weiss); }

/* ------------------------------------------------------------
   Modalbox
   ------------------------------------------------------------
   Gebaut auf <dialog>. Fokusfalle, Esc und inerter Hintergrund
   kommen vom Element selbst — hier steht nur das Aussehen.

   Der Grundstil in basis.css setzt dialog ausdruecklich NICHT
   zurueck. Bitte auch hier nichts an border, padding oder
   display des dialog-Elements aendern, das haengt zusammen.
   ------------------------------------------------------------ */
.cd-modal {
  inline-size: min(100% - 32px, 720px);
  max-block-size: min(100% - 32px, 900px);
  margin: auto;
  overflow: visible;
}

.cd-modal__kasten {
  position: relative;
  max-block-size: min(100vh - 32px, 900px);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--cd-weiss);
  border-radius: var(--cd-r-karte);
  box-shadow: var(--cd-schatten-mega);
}

/* Der Schliessen-Knopf liegt UEBER dem Inhalt und scrollt nicht
   mit — sonst waere der Ausweg nach dem Scrollen weg. 44 px
   erfuellen die Zielgroesse mit Reserve (WCAG 2.5.8). */
.cd-modal__schliessen {
  position: sticky;
  inset-block-start: 0;
  float: inline-end;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px;
  block-size: 44px;
  margin: 12px 12px 0 0;
  background: var(--cd-flaeche-2);
  border: 0;
  border-radius: var(--cd-r-feld);
  color: var(--cd-tinte);
  cursor: pointer;
  transition: background var(--cd-zeit) ease, color var(--cd-zeit) ease;
}
.cd-modal__schliessen:hover {
  background: var(--cd-rot);
  color: var(--cd-weiss);
}
.cd-modal__kreuz {
  inline-size: 16px;
  block-size: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}

/* Das Inhaltselement bringt seine eigene Bahn mit. In der Box
   braucht sie weder Aussenabstaende noch getoenten Grund — sonst
   steht eine Karte in einer Karte. Der Kasten selbst polstert. */
.cd-modal__inhalt > .cd-bahn {
  padding-block: 0;
  background: transparent;
  border: 0;
}
.cd-modal__inhalt .cd-bahn__inhalt {
  max-inline-size: none;
  padding: 36px 40px 40px;
}
.cd-modal__inhalt .cd-kontakt__panel {
  padding: 0;
  background: transparent;
  border: 0;
}
/* Einspaltig ohne Lesebreitenbegrenzung: Die Box gibt die Breite
   bereits vor, eine zweite Begrenzung liesse sie rechts leer. */
.cd-modal__inhalt .cd-kontakt__raster {
  grid-template-columns: minmax(0, 1fr);
  max-inline-size: none;
  gap: var(--cd-a6);
}

/* Die Seite dahinter darf nicht mitscrollen. */
.cd-modal-offen { overflow: hidden; }

@media (max-width: 600px) {
  /* max-inline-size gehoert dazu: Der Browser-Grundstil setzt auf
     dialog ein max-width: calc(100% - 6px - 2em) — also 38 px
     Abzug. Ohne die Ruecknahme blieb die Box trotz inline-size:100%
     eingerueckt, waehrend .cd-modal__kasten darunter schon die
     Ecken abraeumte: ein eingerueckter Kasten mit eckigen Ecken.
     Gemessen 352 px statt 390 px. */
  .cd-modal { inline-size: 100%; max-inline-size: 100%; max-block-size: 100%; }
  .cd-modal__kasten { border-radius: 0; max-block-size: 100vh; }
  .cd-modal__inhalt .cd-bahn__inhalt { padding: var(--cd-a5); }
}

/* ============================================================
   Anhalte-Knopf als Uhr
   ============================================================
   Der Knopf der beiden Schieber fuellt sich rot, bis der naechste
   Wechsel kommt. Die verbleibende Zeit steht damit dort, wo auch
   der Schalter dafuer sitzt.

   Die Dauer kommt als --cd-takt aus dem Skript; die Klasse
   cd-takt--laeuft setzt es ebenfalls — ohne Selbstlauf gibt es
   keine Fuellung. Angehalten friert die Fuellung ein statt zu
   verschwinden: sie zeigt dann, wo die Runde stehengeblieben ist.

   @property ist noetig, damit die Fuellhoehe ueberhaupt animierbar
   ist. Ohne die Angabe springt der Verlauf von 0 auf 100 statt zu
   laufen — eine gewoehnliche Variable ist fuer den Browser nur
   Text.
   ============================================================ */
@property --cd-fuell {
  syntax: "<length-percentage>";
  inherits: false;
  initial-value: 0%;
}

.cd-takt {
  position: relative;
  isolation: isolate;
}

.cd-takt--laeuft::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  /* Der Knopf laeuft von UNTEN nach OBEN voll — wie ein Glas.
     Das liest sich schneller als ein Kreis: die Kante steigt, und
     wo sie steht, ist der Rest der Runde. */
  background: linear-gradient(to top, var(--cd-rot) var(--cd-fuell), transparent 0);
  animation: cd-takt var(--cd-takt, 6500ms) linear infinite;
}

/* AUF DUNKLEM GRUND ZWEIMAL FALSCH, beides am 24.08.2026 gemessen.
   1. Die Fuellung nahm --cd-rot. Gegen die dunkle Bahn sind das
      2,52 : 1 — im Haus gilt dort die aufgehellte Fassung.
   2. Sie fuellte den Knopf im VOLLTON. Damit war von drei Knoepfen
      ausgerechnet der unwichtigste der auffaelligste, und die Bahn
      hatte einen roten Block, der mit dem Zitat um die
      Aufmerksamkeit stritt.

   Die Idee bleibt: Der Knopf laeuft von unten nach oben voll wie ein
   Glas. Nur eben halbdeckend — 2,10 : 1 gegen die Bahn, sichtbar als
   steigende Kante, aber ohne zu schreien. Das weisse Zeichen darauf
   liegt danach bei 7,33 : 1 statt 6,10.

   Die Fuellung ist reine Zier (der Zaehler sagt den Stand in Worten),
   sie braucht also keine 3 : 1. */
.cd-auf-dunkel .cd-takt--laeuft::before {
  background: linear-gradient(to top,
    color-mix(in srgb, var(--cd-rot-auf-dunkel) 50%, transparent) var(--cd-fuell),
    transparent 0);
}

/* Angehalten — von Hand, mit dem Zeiger oder ueber den Fokus. */
.cd-takt--laeuft[data-cd-ruht="1"]::before {
  animation-play-state: paused;
}

@keyframes cd-takt {
  from { --cd-fuell: 0%; }
  to { --cd-fuell: 100%; }
}

/* Wer Bewegung abbestellt hat, bekommt keine laufende Fuellung.
   Der Selbstlauf ist dann ohnehin aus — die Regel ist das Netz
   fuer den Fall, dass die Klasse doch gesetzt wird. */
@media (prefers-reduced-motion: reduce) {
  .cd-takt--laeuft::before { animation: none; }
}

/* ============================================================
   Menuepunkt als Knopf
   ============================================================
   Gesetzt wird das in den Seiteneigenschaften (cd_nav_knopf). Der
   Punkt bleibt ein Link — nur seine Gestalt aendert sich.

   Bewusst die LINIEN-Fassung und nicht der rote Vollknopf: In der
   Hauptnavigation steht rechts bereits "Angebot anfordern" in Rot.
   Zwei rote Flaechen nebeneinander nehmen sich gegenseitig die
   Wirkung.
   ============================================================ */
.cd-navknopf {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  border: 1px solid currentColor;
  border-radius: var(--cd-r-knopf);
  font-weight: 600;
  line-height: 1.2;
  transition: background var(--cd-zeit) ease, color var(--cd-zeit) ease,
              border-color var(--cd-zeit) ease;
}

.cd-navknopf:hover,
.cd-navknopf:focus-visible {
  background: var(--cd-rot);
  border-color: var(--cd-rot);
  color: var(--cd-weiss);
}

/* Der rote Punkt davor kennzeichnet den Notfallweg — dasselbe
   Zeichen wie in der Kopfleiste. Er ist Zier und traegt deshalb
   kein eigenes Wort: die Beschriftung sagt bereits, worum es geht. */
.cd-fuss__knopf::before {
  content: "";
  inline-size: 7px;
  block-size: 7px;
  border-radius: 50%;
  background: var(--cd-rot);
  flex: 0 0 auto;
}

.cd-fuss__knopf:hover::before,
.cd-fuss__knopf:focus-visible::before {
  background: var(--cd-weiss);
}

/* Getoenter Grund — die dritte Fassung neben weiss und dunkel. Sie
   trennt zwei helle Bahnen voneinander, ohne den Abschnitt so
   herauszuheben wie der dunkle Grund. */
.cd-auf-getoent { background: var(--cd-flaeche-2); }

/* Kopfton — derselbe Hellblauton, auf dem der Seitenkopf steht
   (--cd-flaeche-3, #E9EEF1). „getoent" daneben ist mit #F2F5F7 eine
   Spur heller; nebeneinander sieht man den Unterschied, einzeln
   nicht. Der Kopfton ist deshalb kein zweites Grau sondern die
   Zusage „diese Bahn gehoert optisch zum Seitenkopf".

   ZWEI KLASSEN IM SELEKTOR, nicht eine: Einzelne Bahnen malen
   ihren Grund selbst — .cd-cta--hell setzt Weiss, und das steht in
   bahnen.css, also SPAETER als diese Datei. Bei gleichem Gewicht
   gewinnt das Spaetere, und die Grundfarbe waere wirkungslos
   gewesen, ohne dass irgendetwas darauf hinweist. Mit .cd-bahn
   davor wiegt die Regel mehr als jede solche Bahnklasse.

   Bewusst NUR fuer den Kopfton: „getoent" so nachzuziehen wuerde
   Bahnen aendern, die heute still von der weissen Bahnfarbe
   ueberschrieben werden — das waere eine Nebenwirkung und keine
   Absicht. */
.cd-bahn.cd-auf-kopfton { background: var(--cd-flaeche-3); }

/* ============================================================
   Bewegung der Zeichnungen
   ============================================================
   Waehlbar je Bahn (data-symbolbewegung). Alle Zeichnungen des
   Hauses sind gestrichen und nicht gefuellt — darauf baut vor
   allem "zeichnen" auf.

   Wer Bewegung abbestellt hat, bekommt keine. Die Regel steht am
   Ende und nimmt alles zurueck.
   ============================================================ */
/* ------------------------------------------------------------
   ZWEI EBENEN
   ------------------------------------------------------------
   data-symbolbewegung steht an der BAHN und gilt fuer alle
   Zeichnungen darin. data-bewegung steht an der einzelnen
   ZEICHNUNG und sticht die Bahn — dafuer traegt jede Bahnregel ein
   :not([data-bewegung]) und geht der Zeichnung mit eigener Angabe
   damit aus dem Weg.

   Zwei sich widersprechende Regeln ueber die Gewichtung zu
   entscheiden waere hier zu wenig: "pulsieren" ist eine Animation,
   "anheben" eine Transformation beim Zeigen — die beissen sich
   nicht, sie laufen beide. Nur ein ausdruecklicher Ausschluss
   trennt sie sauber.

   svg.cd-symbol[...] statt .cd-symbol[...]: Der Elementname bringt
   das noetige Quentchen Gewicht, damit die Zeichnungsregel die
   Bahnregel auch dann sticht, wenn beide dieselbe Eigenschaft
   setzen.
   ------------------------------------------------------------ */
[data-symbolbewegung] .cd-symbol,
svg.cd-symbol[data-bewegung] {
  transition: transform .28s var(--cd-kurve);
}

/* --- beim Zeigen anheben --- */
[data-symbolbewegung="heben"] :is(a, li, .cd-karten__feld):hover .cd-symbol:not([data-bewegung]),
:is(a, li, .cd-karten__feld):hover svg.cd-symbol[data-bewegung="heben"] {
  transform: translateY(-3px) scale(1.08);
}

/* --- beim Zeigen drehen --- */
[data-symbolbewegung="drehen"] :is(a, li, .cd-karten__feld):hover .cd-symbol:not([data-bewegung]),
:is(a, li, .cd-karten__feld):hover svg.cd-symbol[data-bewegung="drehen"] {
  transform: rotate(-8deg) scale(1.06);
}

/* --- ruhig pulsieren ---
   Sehr flach und langsam: eine Zeichnung, die auf sich aufmerksam
   macht, waehrend daneben gelesen wird, stoert mehr als sie hilft. */
[data-symbolbewegung="pulsieren"] .cd-symbol:not([data-bewegung]),
svg.cd-symbol[data-bewegung="pulsieren"] {
  /* Ein Durchlauf mehr waere ueber fuenf Sekunden und damit nach
     WCAG 2.2.2 anhaltepflichtig. Ausdruecklich OHNE "both": mit
     Fuellmodus bliebe der transform-Wert stehen und wuerde
     "heben" und "drehen" ueberschreiben, sobald jemand auf die
     Karte zeigt. */
  animation: cd-symbolpuls 2.4s ease-in-out 2;
}
@keyframes cd-symbolpuls {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.07); }
}

/* --- beim Auftritt zeichnen ---
   Der Strich entsteht, sobald die Bahn auftritt. 240 ist grosszuegig
   gewaehlt: laenger als der laengste Pfad im Vorrat, damit kein
   Zeichen halb gezeichnet stehenbleibt. */
[data-symbolbewegung="zeichnen"] .cd-symbol:not([data-bewegung]) :is(path, circle, rect, line, polyline),
svg.cd-symbol[data-bewegung="zeichnen"] :is(path, circle, rect, line, polyline) {
  stroke-dasharray: 240;
  stroke-dashoffset: 240;
}
html.cd-bewegung [data-symbolbewegung="zeichnen"].cd-ein .cd-symbol:not([data-bewegung]) :is(path, circle, rect, line, polyline),
html.cd-bewegung .cd-ein svg.cd-symbol[data-bewegung="zeichnen"] :is(path, circle, rect, line, polyline) {
  animation: cd-symbolzeichnen .9s var(--cd-kurve) forwards;
}
@keyframes cd-symbolzeichnen {
  to { stroke-dashoffset: 0; }
}

/* Ohne Skript tritt keine Bahn auf — dann muss die Zeichnung von
   Anfang an vollstaendig dastehen. */
html:not(.cd-bewegung) [data-symbolbewegung="zeichnen"] .cd-symbol :is(path, circle, rect, line, polyline),
html:not(.cd-bewegung) svg.cd-symbol[data-bewegung="zeichnen"] :is(path, circle, rect, line, polyline) {
  stroke-dashoffset: 0;
}

/* "ohne Bewegung" am einzelnen Zeichen. Es steht ausdruecklich da
   und ist nicht dasselbe wie ein leeres Feld: leer heisst "wie an
   der Bahn", dies hier nimmt die Bahneinstellung zurueck. Die
   Rueckstellung von stroke-dashoffset ist noetig, falls die Bahn
   auf "zeichnen" steht — sonst bliebe das Zeichen unsichtbar. */
svg.cd-symbol[data-bewegung="keine"],
svg.cd-symbol[data-bewegung="keine"] :is(path, circle, rect, line, polyline) {
  animation: none;
  transform: none;
  transition: none;
  stroke-dashoffset: 0;
}

@media (prefers-reduced-motion: reduce) {
  [data-symbolbewegung] .cd-symbol,
  [data-symbolbewegung] .cd-symbol :is(path, circle, rect, line, polyline),
  svg.cd-symbol[data-bewegung],
  svg.cd-symbol[data-bewegung] :is(path, circle, rect, line, polyline) {
    animation: none;
    transition: none;
    transform: none;
    stroke-dashoffset: 0;
  }
}


/* ============================================================
   Grosser Knopf
   ============================================================
   Die Knopfform fuer Abschlussbaender: volle Breite, Beschriftung
   links, Zeichen rechts am Rand. Sie gilt im Handlungsband (cd_cta)
   UND im Abschluss der Projektseiten — beide Bauteile nennen
   dieselbe Regel, sonst laufen sie wieder auseinander. Vorher hatte
   jede Stelle ihre eigene: 62, 45, 58 und 32 px, drei Schriftgroessen
   und zwei Symbolseiten.

   Die Regel setzt ausschliesslich GEOMETRIE — keine Farbe, keinen
   Rand. Die Fuellung bleibt Sache der Klassen am Element, sonst
   waere ein .cd-knopf--linie hier stumm.

   DIE HOEHE KOMMT AUS DER POLSTERUNG und nicht aus min-block-size.
   Das ist kein Geschmack: In basis.css setzt die Zielgroessen-Regel
   nach WCAG 2.5.8 ein min-block-size auf a[href] — Element plus
   Attribut, und damit staerker als jede einzelne Klasse. Wer die
   Knopfhoehe ueber min-block-size und eine Klasse setzt, verliert
   dort lautlos.
   ============================================================ */
.cd-grossknopf,
.cd-cta__knoepfe:not(.cd-cta__knoepfe--reihe) > a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  inline-size: 100%;
  /* 19 + 1 px Rand = 20 */
  padding: 19px 27px;
  /* NUR Staerke und Art, KEINE Farbe. Die Kurzform
     `border: 1px solid transparent` setzt auch die Farbe, und dieser
     Selektor ist staerker als die Fuellklassen daneben — ein
     .cd-knopf--linie im Stapel haette danach einen durchsichtigen
     Rand gehabt und der rote Knopf ebenso. Die Farbe bleibt Sache
     der Klasse am Element; wer eine Fuellung setzt, setzt auch die
     Randfarbe dazu. */
  border-style: solid;
  border-width: 1px;
  border-radius: var(--cd-r-knopf);
  font-family: var(--cd-schrift-display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -.012em;
  line-height: 1.2;
  text-align: start;
  transition: background var(--cd-zeit) ease, color var(--cd-zeit) ease,
              border-color var(--cd-zeit) ease;
}

/* Auf schmalen Schirmen etwas kleiner — die Aufteilung bleibt. */
@media (max-width: 600px) {
  .cd-grossknopf,
  .cd-cta__knoepfe:not(.cd-cta__knoepfe--reihe) > a {
    font-size: 16px;
    padding: calc(var(--cd-a4) - 1px) calc(var(--cd-a5) - 1px);
  }
}

/* ============================================================
   Geraete als technische Zeichnung
   ============================================================
   Bildschirmfotos stehen darin statt nackt. Gestrichen und nicht
   gefuellt — dieselbe Sprache wie die Symbole und die
   Schema-Zeichnungen im Backend.

   Die Linienfarbe kommt aus currentColor: So passt sich das Geraet
   dem Grund an, auf dem es steht, ohne zweite Fassung.
   ============================================================ */
.cd-geraet {
  position: relative;
  /* Nicht --cd-linie: Das ist die Farbe fuer Trennstriche IM Text,
     bei 1,5 px Kante um eine helle Flaeche verschwindet sie. Eine
     technische Zeichnung braucht eine Kante, die man sieht — hier
     der Nebentextton, gedeckt genug um nicht zu schreien. */
  color: var(--cd-text-3);
  inline-size: 100%;
}

.cd-geraet__scheibe {
  position: relative;
  overflow: hidden;
  background: var(--cd-flaeche-3);
}
.cd-geraet__scheibe img {
  inline-size: 100%;
  block-size: 100%;
  display: block;
  object-fit: cover;
  object-position: top center;
}

/* ==================================================================
   Geraete-Zeichnung mit Browserleiste  —  Laptop und Monitor
   Technische Zeichnung: nur Striche, keine Flaechen. Jede Linie holt
   ihre Farbe aus currentColor, damit dieselbe Zeichnung auf hellem
   und auf dunklem Grund traegt, ohne zweiten Regelsatz.
   Hier wird NIE `color` gesetzt - die Sektion bestimmt die Tinte.
   ================================================================== */

.cd-geraet--laptop,
.cd-geraet--monitor{
  /* Alle Masse an einer Stelle. Wer die Zeichnung nachjustiert, fasst
     Variablen an und nicht die Regeln darunter. */
  --cd-geraet-strich: 1.5px;
  --cd-geraet-rand: 4px;            /* Blende zwischen Rahmen und Bild */
  --cd-geraet-radius: 8px;

  /* Die Leiste waechst MIT der Schrift statt gegen sie: erst das Feld
     aus der Mikroschrift ableiten, dann die Leiste aus dem Feld. So
     kann eine groessere Grundschrift die Leiste nie sprengen. */
  --cd-geraet-feld: calc(var(--cd-gr-mikro) * 1.4 + var(--cd-a1));
  --cd-geraet-leiste: calc(var(--cd-geraet-feld) + var(--cd-a2));

  /* Die Fensterpunkte bleiben in px: die Maske unten zeichnet 1:1,
     nur so bleibt der Strich wirklich 1,5 px breit. */
  --cd-geraet-punkt: 7px;
  --cd-geraet-punktreihe: calc(var(--cd-geraet-punkt) * 3 + var(--cd-a1) * 2);
  --cd-geraet-pfeil: 7px;

  /* Drei OFFENE Kreise als Maskenform. Ein Hintergrundbild koennte
     currentColor nicht erben (eigenes Dokument), box-shadow-Kopien
     waeren gefuellte Scheiben statt Ringe. */
  --cd-geraet-fensterpunkte: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29 7"><g fill="none" stroke="%23000" stroke-width="1.5"><circle cx="3.5" cy="3.5" r="2.75"/><circle cx="14.5" cy="3.5" r="2.75"/><circle cx="25.5" cy="3.5" r="2.75"/></g></svg>');

  /* Die Leiste richtet sich nach der SPALTE, nicht nach dem Fenster:
     dasselbe Geraet steht mal breit im Text, mal in einer Kachel. */
  container: cd-geraet / inline-size;
}

.cd-geraet--laptop{
  --cd-geraet-sockel: 12px;
  /* Die Basis ist breiter als der Deckel - der Platz dafuer kommt aus
     dem Innenabstand, damit nichts aus dem Kasten ragt. */
  padding-inline: clamp(6px, 4%, 18px);
  padding-block-end: var(--cd-geraet-sockel);
}

.cd-geraet--monitor{
  --cd-geraet-rand: 8px;            /* Monitore haben eine echte Blende */
  --cd-geraet-radius: 6px;
  --cd-geraet-hals: 22px;
  --cd-geraet-platte: 8px;
  padding-block-end: calc(var(--cd-geraet-hals) + var(--cd-geraet-platte));
}

/* --- Gehaeuse ---------------------------------------------------- */

.cd-geraet--laptop .cd-geraet__deckel,
.cd-geraet--monitor .cd-geraet__deckel{
  box-sizing: border-box;
  border: var(--cd-geraet-strich) solid currentColor;
  border-radius: var(--cd-geraet-radius);
  /* Oben wird die Leiste ausgespart, ringsum die Blende. Die Scheibe
     rueckt dadurch von selbst an die richtige Stelle. */
  padding-block-start: calc(var(--cd-geraet-rand) + var(--cd-geraet-leiste));
  padding-inline: var(--cd-geraet-rand);
  padding-block-end: var(--cd-geraet-rand);
}

.cd-geraet--laptop .cd-geraet__scheibe,
.cd-geraet--monitor .cd-geraet__scheibe{
  box-sizing: border-box;
  /* Die Trennlinie zwischen Fensterrahmen und Seite haengt an der
     Scheibe, nicht an einem Pseudo: sie ist genau so breit wie der
     Bildschirm und spart ein Element fuer die Pfeiltaste ein. */
  border-block-start: var(--cd-geraet-strich) solid currentColor;
  /* Innenradius = Aussenradius minus Rahmen minus Blende. Ohne das
     schaut die Bildecke ueber die gezeichnete Ecke hinaus. */
  border-end-start-radius: max(0px, calc(var(--cd-geraet-radius) - var(--cd-geraet-strich) - var(--cd-geraet-rand)));
  border-end-end-radius:   max(0px, calc(var(--cd-geraet-radius) - var(--cd-geraet-strich) - var(--cd-geraet-rand)));
}

/* DAS SEITENVERHAELTNIS GEHOERT AN DIE SCHEIBE und nicht an die
   Aufnahme. Ohne es hat die Zeichnung so lange keine Hoehe, bis das
   Bild geladen ist — gemessen 50 px statt 250, und beim Nachladen
   springt der halbe Abschnitt.

   Die Werte sind die der Aufnahmen: 1440 x 900 ist 16:10, ein
   Monitor zeigt 16:9. Tablet und Handy bringen ihres schon mit. */
.cd-geraet--laptop .cd-geraet__scheibe{ aspect-ratio: 16 / 10; }
.cd-geraet--monitor .cd-geraet__scheibe{ aspect-ratio: 16 / 9; }

/* --- Fensterleiste: drei Punkte + Pfeiltaste ---------------------- */

.cd-geraet--laptop .cd-geraet__deckel::before,
.cd-geraet--monitor .cd-geraet__deckel::before{
  content: "";
  position: absolute;
  inset-block-start: calc(var(--cd-geraet-rand) + (var(--cd-geraet-leiste) - var(--cd-geraet-punkt)) / 2);
  inset-inline-start: calc(var(--cd-geraet-rand) + var(--cd-a2));
  inline-size: var(--cd-geraet-punktreihe);
  block-size: var(--cd-geraet-punkt);
  -webkit-mask: var(--cd-geraet-fensterpunkte) no-repeat 0 0 / 100% 100%;
          mask: var(--cd-geraet-fensterpunkte) no-repeat 0 0 / 100% 100%;
  pointer-events: none;
}

/* Ohne Maskenunterstuetzung waere das ein gefuellter Balken statt drei
   Ringen - dann lieber gar keine Punkte zeichnen. */
@supports ((-webkit-mask-image: url("i.svg")) or (mask-image: url("i.svg"))){
  .cd-geraet--laptop .cd-geraet__deckel::before,
  .cd-geraet--monitor .cd-geraet__deckel::before{ background-color: currentColor; }
}

.cd-geraet--laptop .cd-geraet__deckel::after,
.cd-geraet--monitor .cd-geraet__deckel::after{
  content: "";
  position: absolute;
  box-sizing: border-box;
  inset-block-start: calc(var(--cd-geraet-rand) + (var(--cd-geraet-leiste) - var(--cd-geraet-pfeil)) / 2);
  inset-inline-start: calc(var(--cd-geraet-rand) + var(--cd-a2) + var(--cd-geraet-punktreihe) + var(--cd-a2));
  inline-size: var(--cd-geraet-pfeil);
  block-size: var(--cd-geraet-pfeil);
  /* Zwei Kanten einer Ecke, um 45 Grad gedreht, ergeben ein "<".
     Die Pfeiltaste haengt am Deckel und NICHT an der Adresszeile:
     die klemmt ihre eigenen Kinder weg (overflow: hidden). */
  border-inline-start: var(--cd-geraet-strich) solid currentColor;
  border-block-end: var(--cd-geraet-strich) solid currentColor;
  transform: rotate(45deg);
  pointer-events: none;
}

/* --- Adresszeile (das eine erlaubte Element) ---------------------- */

.cd-geraet__adresse{
  position: absolute;
  box-sizing: border-box;
  inset-block-start: calc(var(--cd-geraet-rand) + (var(--cd-geraet-leiste) - var(--cd-geraet-feld)) / 2);
  /* Blende + Luft + Punktreihe + Luft + Pfeil + Luft */
  inset-inline-start: calc(var(--cd-geraet-rand) + var(--cd-a2) + var(--cd-geraet-punktreihe)
                           + var(--cd-a2) + var(--cd-geraet-pfeil) + var(--cd-a3));
  inset-inline-end: calc(var(--cd-geraet-rand) + var(--cd-a2));
  block-size: var(--cd-geraet-feld);
  padding-inline: var(--cd-a2);
  border: var(--cd-geraet-strich) solid currentColor;
  border-radius: 999px;
  font-family: var(--cd-schrift-mono);
  font-size: var(--cd-gr-mikro);
  line-height: calc(var(--cd-geraet-feld) - var(--cd-geraet-strich) * 2);
  /* Die Adresse ist Zeichnung, nicht Inhalt: sie darf nie umbrechen
     und nie die Leiste sprengen. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* Eine gezeichnete URL soll nicht in die Zwischenablage geraten und
     keine Klicks abfangen. */
  user-select: none;
  pointer-events: none;
}

/* --- Laptop: Basis und Griffmulde --------------------------------- */

.cd-geraet--laptop::before{
  content: "";
  position: absolute;
  box-sizing: border-box;
  inset-block-end: 0;
  inset-inline: 0;
  /* Einen Strich hoeher als der Sockel: so liegt die Oberkante der
     Basis exakt AUF der Unterkante des Deckels - eine Linie, nicht
     zwei nebeneinander. */
  block-size: calc(var(--cd-geraet-sockel) + var(--cd-geraet-strich));
  border: var(--cd-geraet-strich) solid currentColor;
  border-end-start-radius: 6px;
  border-end-end-radius: 6px;
  pointer-events: none;
}

.cd-geraet--laptop::after{
  content: "";
  position: absolute;
  inset-block-end: calc((var(--cd-geraet-sockel) - var(--cd-geraet-strich)) / 2);
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: 18%;
  max-inline-size: 72px;
  block-size: 0;
  /* Andeutung der Griffmulde - ein Strich genuegt, ein Kasten waere
     schon ein zweites Bauteil. */
  border-block-start: var(--cd-geraet-strich) solid currentColor;
  pointer-events: none;
}

/* --- Monitor: Hals und Standplatte -------------------------------- */

.cd-geraet--monitor::before{
  content: "";
  position: absolute;
  inset-block-end: var(--cd-geraet-platte);
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: 16%;
  min-inline-size: 28px;
  max-inline-size: 64px;
  block-size: var(--cd-geraet-hals);
  /* Nur die zwei Seitenkanten: oben schliesst der Deckel ab, unten
     die Platte. Ein Rahmen ringsum waere eine Kiste, kein Hals. */
  border-inline: var(--cd-geraet-strich) solid currentColor;
  pointer-events: none;
}

.cd-geraet--monitor::after{
  content: "";
  position: absolute;
  box-sizing: border-box;
  inset-block-end: 0;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: 42%;
  min-inline-size: 96px;
  max-inline-size: 150px;
  block-size: var(--cd-geraet-platte);
  border: var(--cd-geraet-strich) solid currentColor;
  border-radius: 3px;
  pointer-events: none;
}

/* --- Schmale Spalten ---------------------------------------------- */

/* ACHTUNG BEIM NACHJUSTIEREN: Eine Container-Abfrage misst den
   INHALTSKASTEN. Der Laptop traegt aussen clamp(6px, 4%, 18px)
   Innenabstand fuer die breitere Basis — bei 379 px Spalte sind das
   nur noch 348 px = 21,8 rem. Eine Schwelle bei 22 rem griff
   deshalb genau dort, wo die Zeichnung eigentlich reichlich Platz
   hat: Die Adresse verschwand in der Galeriereihe.
   Die Schwellen liegen jetzt entsprechend tiefer. */

@container cd-geraet (inline-size < 12rem){
  /* Die Leiste BLEIBT - sie ist das Zeichen "das hier ist eine
     Website". Nur der Text geht.

     Zwischen 12 und 22 rem wird die Adresse NICHT mehr versteckt:
     Sie schrumpft ohnehin nicht, sondern bekommt bei Platzmangel
     drei Punkte (text-overflow). Eine gekuerzte Adresse sagt mehr
     als eine leere Pille. */
  .cd-geraet__adresse{
    inset-inline-start: calc(var(--cd-geraet-rand) + var(--cd-a2)
                             + var(--cd-geraet-punktreihe) + var(--cd-a3));
    font-size: 0;
  }
  /* Die Pfeiltaste faellt zuerst: sie ist die Zutat mit dem geringsten
     Erkennungswert. */
  .cd-geraet--laptop .cd-geraet__deckel::after,
  .cd-geraet--monitor .cd-geraet__deckel::after{ display: none; }
}

@container cd-geraet (inline-size < 9rem){
  /* Unter ~144 px waere die Leiste ein Fuenftel der Bildhoehe. Dann
     verschwindet die Fensterzeichnung ganz - lieber ein sauberer
     Rahmen als ein zugestellter Kopf. */
  .cd-geraet--laptop .cd-geraet__deckel,
  .cd-geraet--monitor .cd-geraet__deckel{
    padding-block-start: var(--cd-geraet-rand);
  }
  .cd-geraet--laptop .cd-geraet__scheibe,
  .cd-geraet--monitor .cd-geraet__scheibe{ border-block-start: 0; }
  .cd-geraet--laptop .cd-geraet__deckel::before,
  .cd-geraet--monitor .cd-geraet__deckel::before,
  .cd-geraet__adresse{ display: none; }
}

/* --- Sonderfaelle -------------------------------------------------- */

@media (forced-colors: active){
  /* Im Kontrastmodus wird background-color auf die Flaechenfarbe
     gezwungen - die Punkte waeren unsichtbar. */
  .cd-geraet--laptop .cd-geraet__deckel::before,
  .cd-geraet--monitor .cd-geraet__deckel::before{ background-color: CanvasText; }
}

[dir="rtl"] .cd-geraet--laptop .cd-geraet__deckel::after,
[dir="rtl"] .cd-geraet--monitor .cd-geraet__deckel::after{
  /* border-inline-start kippt im RTL-Satz auf die andere Seite, rotate
     dreht aber weiter physisch. Ohne diese Korrektur zeigt die
     Zuruecktaste nach oben statt nach rechts. */
  transform: rotate(-45deg);
}

/* ============================================================
   Handy — zwei Fassungen
   ============================================================
   Beide sprechen dieselbe Grammatik wie --laptop und --monitor:
   Gehaeuselinie, Scheibenlinie, ein Merkmal auf der Scheibe.
   Unterschieden werden sie nur an den Zuegen, die man auf einem
   Foto auch erkennen wuerde — Eckenrundung, Randbreite,
   Aussparung, Tastenseite. Keine Marken, nur Silhouette.

   Warum Prozent statt Pixel: Die Zeichnung wird zwischen 14rem
   und 9rem eingesetzt. Eine Ecke in px waere unten zu rund und
   oben zu kantig; in Prozent bleibt das Verhaeltnis stehen. Nur
   die Strichstaerke bleibt bei 1,5px, und die kleinsten Teile
   bekommen mit max() einen Pixelboden, damit sie unten nicht
   zu Matsch zusammenlaufen.

   Einfuegen nach dem Block --handy und VOR der Regel
   .cd-auf-dunkel .cd-geraet, damit die Farbvererbung zuletzt steht.
   ============================================================ */

/* ------------------------------------------------------------
   Gemeinsame Grundlage beider Handy-Fassungen
   ------------------------------------------------------------ */
.cd-geraet--iphone,
.cd-geraet--galaxy {
  /* Die Seitentasten stehen neben dem Gehaeuse. Der Streifen
     reserviert ihre 4px, damit die Zeichnung nicht aus ihrem
     eigenen Kasten ragt und an einem overflow weiter oben
     abgeschnitten wird. Beidseitig, damit das Geraet in seinem
     Platz mittig bleibt — auch bei nur einer Taste. */
  box-sizing: border-box;
  padding-inline: var(--cd-a1);

  /* Hochkant braucht eine Obergrenze, sonst wird aus dem Handy eine
     Litfasssaeule. Wo mehrere Geraete nebeneinander stehen, setzt
     die Galeriereihe eine engere Grenze — die gilt dann dort. */
  max-inline-size: 14rem;
  margin-inline: auto;

  /* Netz gegen die Mindestbreite, die ein Grid-/Flex-Kind aus
     seinem Inhalt zieht — das Galeriestueck ist ein Grid. */
  min-inline-size: 0;
}

/* Rahmen und Innenabstand sollen die geerbten 100% nicht
   sprengen; ohne das laeuft der Prozent-Rand ueber. */
.cd-geraet--iphone .cd-geraet__deckel,
.cd-geraet--iphone .cd-geraet__scheibe,
.cd-geraet--galaxy .cd-geraet__deckel,
.cd-geraet--galaxy .cd-geraet__scheibe {
  box-sizing: border-box;
}

/* Die Zutaten auf der Scheibe. z-index wie bei --handy: Sie
   liegen ueber der Aufnahme, nicht darunter. */
.cd-geraet--iphone .cd-geraet__scheibe::before,
.cd-geraet--iphone .cd-geraet__scheibe::after,
.cd-geraet--galaxy .cd-geraet__scheibe::before {
  content: "";
  position: absolute;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: 1;
}

/* Die Seitentasten. Sie haengen am aeusseren Kasten, weil dessen
   Innenabstand ihren Platz vorhaelt: inset 0 setzt sie genau in
   diesen Streifen, buendig an die Gehaeuselinie. */
.cd-geraet--iphone::before,
.cd-geraet--iphone::after,
.cd-geraet--galaxy::after {
  content: "";
  position: absolute;
  inline-size: var(--cd-a1);
  border: 1.5px solid currentColor;
  pointer-events: none;
}

/* ------------------------------------------------------------
   (a) Sehr runde Fassung: Pille oben, Bedienbalken unten,
       Tasten auf beiden Seiten
   ------------------------------------------------------------ */
.cd-geraet--iphone .cd-geraet__deckel {
  border: 1.5px solid currentColor;

  /* Prozent-Innenabstand bezieht sich auf ALLEN Seiten auf die
     Breite — dadurch ist der Steg ringsum gleich stark. Der
     Pixelboden haelt bei 9rem den Abstand zwischen Gehaeuse-
     und Scheibenlinie offen, sonst verschmelzen beide. */
  padding: max(4px, 2.6%);

  /* Zwei Werte, weil ein einzelner Prozentwert auf diesem hohen
     Kasten eifoermige Ecken erzeugt: der zweite Wert ist der
     erste mal Breite/Hoehe (hier rund 0,48). */
  border-radius: 16.4% / 7.8%;
}

.cd-geraet--iphone .cd-geraet__scheibe {
  aspect-ratio: 9 / 19.5;
  border: 1.5px solid currentColor;
  /* 14% der Breite entsprechen 6,5% der Hoehe (Faktor 0,46). */
  border-radius: 14% / 6.5%;
}

/* Die Pille — das eine Merkmal, an dem diese Fassung erkannt
   wird. Hoehe aus dem Seitenverhaeltnis statt aus der
   Scheibenhoehe: so bleibt sie bei jeder Groesse eine Pille. */
.cd-geraet--iphone .cd-geraet__scheibe::before {
  inset-block-start: 1.6%;
  inline-size: 30%;
  aspect-ratio: 3.6 / 1;
  min-block-size: 9px; /* darunter wird aus der Pille ein Strich */
  border: 1.5px solid currentColor;
  border-radius: 999px;
}

/* Bedienbalken. Gefuellt wie bei --handy, weil ein umrandeter
   Balken bei 1,5px Hoehe nur eine doppelte Linie waere. */
.cd-geraet--iphone .cd-geraet__scheibe::after {
  inset-block-end: 1.2%;
  inline-size: 34%;
  block-size: 1.5px;
  border-radius: 1px;
  background: currentColor;
}

/* Lautstaerke links. Die Gehaeuselinie ist zugleich die vierte
   Seite der Taste — ein eigener Strich daneben ergaebe eine
   Doppellinie, die bei 9rem verklumpt. */
.cd-geraet--iphone::before {
  inset-inline-start: 0;
  inset-block-start: 19%;
  block-size: 13%;
  border-inline-end: 0;
  border-start-start-radius: 2px;
  border-end-start-radius: 2px;
}

/* Standby rechts, tiefer angesetzt als die Lautstaerke — dieser
   Versatz ist der eigentliche Wiedererkennungswert. */
.cd-geraet--iphone::after {
  inset-inline-end: 0;
  inset-block-start: 25%;
  block-size: 11%;
  border-inline-start: 0;
  border-start-end-radius: 2px;
  border-end-end-radius: 2px;
}

/* ------------------------------------------------------------
   (b) Kantigere Fassung: Loch mittig oben, schmaler Rand,
       eine einzige Taste rechts
   ------------------------------------------------------------ */
.cd-geraet--galaxy .cd-geraet__deckel {
  border: 1.5px solid currentColor;
  /* Schmaler als (a) — der duenne Rand ist hier ein
     Erkennungsmerkmal, der Pixelboden rettet ihn bei 9rem. */
  padding: max(3px, 1.6%);
  border-radius: 11% / 5%;
}

.cd-geraet--galaxy .cd-geraet__scheibe {
  aspect-ratio: 9 / 20;
  border: 1.5px solid currentColor;
  /* Deutlich weniger rund als (a): 9% statt 14%. */
  border-radius: 9% / 4%;
}

/* Das Kameraloch. Untergrenze in px, weil ein Ring aus zwei
   1,5px-Kanten unterhalb von 6px kein Loch mehr zeigt. */
.cd-geraet--galaxy .cd-geraet__scheibe::before {
  inset-block-start: 1.6%;
  inline-size: max(6px, 5%);
  aspect-ratio: 1;
  border: 1.5px solid currentColor;
  border-radius: 50%;
}

/* Genau eine Taste, und zwar rechts. Dass links nichts steht,
   unterscheidet diese Fassung auf den ersten Blick von (a). */
.cd-geraet--galaxy::after {
  inset-inline-end: 0;
  inset-block-start: 23%;
  block-size: 9%;
  border-inline-start: 0;
  border-start-end-radius: 2px;
  border-end-end-radius: 2px;
}

/* ============================================================
   .cd-geraet--tablet  —  Tablet, hoch und quer
   Technische Zeichnung: zwei parallele Konturen (Gehaeuse und
   Scheibe) plus ein Punkt fuer die Frontkamera. Keine Flaeche,
   kein Schatten, keine eigene Farbe — jede Linie ist
   currentColor, damit dieselbe Zeichnung auf hellem und auf
   dunklem Grund traegt.
   ============================================================ */

.cd-geraet--tablet {
  --cd-geraet-strich: 1.5px;
  --cd-geraet-rand: var(--cd-a3);   /* Randbahn, ringsum gleich breit */
  --cd-geraet-radius: var(--cd-a4);
  --cd-geraet-punkt: 6px;           /* Frontkamera, gestrichen statt gefuellt */

  /* Die Scheibe bekommt ihre Hoehe aus aspect-ratio. In Flex- und
     Grid-Spalten leitet der Browser daraus eine Mindestbreite ab und
     die Zeichnung sprengt die Spalte — hier abgeraeumt. */
  min-inline-size: 0;
}

/* Gehaeuse: eine geschlossene Kontur. Die Randbahn entsteht als
   padding und nicht als Abstand am Kind — nur so bleibt sie auf allen
   vier Seiten gleich, egal welches Seitenverhaeltnis die Scheibe hat. */
.cd-geraet--tablet .cd-geraet__deckel {
  box-sizing: border-box;           /* sonst schiebt das padding den Deckel ueber die 100 % */
  border: var(--cd-geraet-strich) solid currentColor;
  border-radius: var(--cd-geraet-radius);
  padding: var(--cd-geraet-rand);
  background: none;                 /* gestrichen, nicht gefuellt */
}

/* Scheibe: zweite Kontur, parallel zur ersten. Der Innenradius wird
   aus Aussenradius minus Randbahn abgeleitet, damit die beiden Linien
   in den Ecken gleichmaessig weit auseinander laufen. */
.cd-geraet--tablet .cd-geraet__scheibe {
  box-sizing: border-box;
  border: var(--cd-geraet-strich) solid currentColor;
  border-radius: max(0px, calc(var(--cd-geraet-radius) - var(--cd-geraet-rand)));
  aspect-ratio: 3 / 4;              /* hoch */
}

/* Frontkamera — reine Zier, deshalb Pseudoelement: im Baum fuer
   Vorleseprogramme taucht sie gar nicht erst auf, ein Extra-Element
   waere Ballast ohne Aussage.
   Zentriert wird ueber die Achse, auf der inset 0 steht, plus
   margin: auto. Drehen heisst dann nur: Achsen tauschen — kein
   transform, keine zweite Kamera. */
.cd-geraet--tablet .cd-geraet__deckel::before {
  /* Auf dem Pseudoelement deklariert, nicht am Wurzelknoten: var()
     in einer Variablen wird dort aufgeloest, wo die Variable steht.
     Haengt sie oben, wuerde ein spaeter geaenderter --cd-geraet-rand
     die Kamera nicht mehr mitnehmen. */
  --cd-geraet-punkt-bahn: calc((var(--cd-geraet-rand) - var(--cd-geraet-punkt)) / 2);

  content: "";
  position: absolute;
  box-sizing: border-box;
  inline-size: var(--cd-geraet-punkt);
  block-size: var(--cd-geraet-punkt);
  border: var(--cd-geraet-strich) solid currentColor;
  border-radius: 50%;

  /* Hoch: kurze Kante ist oben. Versatz auf der Blockachse,
     Zentrierung auf der Inline-Achse. */
  inset-block: var(--cd-geraet-punkt-bahn) auto;
  inset-inline: 0;
  margin-block: 0;
  margin-inline: auto;
}

/* Quer: die kurze Kante ist jetzt die vordere schmale Seite. */
.cd-geraet--tablet.cd-geraet--quer .cd-geraet__scheibe {
  aspect-ratio: 4 / 3;
}

/* Zweite und letzte Kameraregel: dieselben vier Eigenschaften,
   Achsen vertauscht. Versatz auf der Inline-Achse, Zentrierung
   auf der Blockachse. */
.cd-geraet--tablet.cd-geraet--quer .cd-geraet__deckel::before {
  inset-block: 0;
  inset-inline: var(--cd-geraet-punkt-bahn) auto;
  margin-block: auto;
  margin-inline: 0;
}

/* Optional — kann ersatzlos entfallen.
   Eine feste 12px-Randbahn wirkt an einer 700px breiten Darstellung
   duenn wie ein Bilderrahmen. Der Wert wird an genau einer Stelle
   gedreht, Kamerasitz und Innenradius rechnen mit. */
@supports (container-type: inline-size) {
  .cd-geraet--tablet {
    container-type: inline-size;
  }

  /* Abgefragt wird der Deckel, nicht das Geraet selbst: ein Element
     ist nie sein eigener Container. */
  @container (min-inline-size: 560px) {
    .cd-geraet--tablet .cd-geraet__deckel {
      --cd-geraet-rand: var(--cd-a4);
      --cd-geraet-radius: var(--cd-a5);
      --cd-geraet-punkt: 8px;
    }
  }
}

/* Auf dunklem Grund traegt die Zeichnung die helle Linie — sie
   erbt sie ueber currentColor, deshalb genuegt eine Farbe. */
.cd-auf-dunkel .cd-geraet { color: var(--cd-text-auf-dunkel-2); }

/* ============================================================
   Rechenaufgabe im Formular
   ============================================================
   Zweite Huerde neben dem Honigtopf. Bewusst wie ein normales
   Pflichtfeld gestaltet und nicht als Warnkasten: Es ist eine Frage
   an den Besucher, kein Vorwurf.

   Das Feld bleibt schmal — eine zweistellige Zahl braucht keine
   Formularbreite, und ein kurzes Feld sagt ohne Worte, wie viel
   erwartet wird.
   ============================================================ */
.cd-rechnung {
  display: grid;
  gap: 6px;
  margin-block-start: var(--cd-a5);
  max-inline-size: 28rem;
}
.cd-rechnung__label {
  font-weight: 600;
  font-size: var(--cd-gr-klein);
  color: var(--cd-tinte);
}
.cd-rechnung__feld {
  inline-size: 7rem;
  padding: 11px 14px;
  border: 1px solid var(--cd-linie-3);
  border-radius: var(--cd-r-feld);
  background: var(--cd-weiss);
  font-family: var(--cd-schrift-text);
  font-size: var(--cd-gr-text);
  color: var(--cd-tinte);
}
.cd-rechnung__feld:focus-visible {
  border-color: var(--cd-rot);
}
.cd-rechnung__hinweis {
  margin: 0;
  color: var(--cd-text-3);
  font-size: var(--cd-gr-klein);
}

/* Auf dunklem Grund: Das Feld bleibt hell (es ist eine Eingabe),
   Beschriftung und Hinweis ziehen nach. */
.cd-auf-dunkel .cd-rechnung__label {
  color: var(--cd-weiss);
}
.cd-auf-dunkel .cd-rechnung__hinweis {
  color: var(--cd-text-auf-dunkel);
}

/* Datenschutz-Modal: Titel und Ladehinweis. Der Inhalt selbst
   kommt aus der Datenschutzseite und bringt seine eigenen Stile
   mit — hier steht nur der Rahmen darum. */
.cd-datenschutzmodal__titel {
  margin: 0;
  padding: var(--cd-a5) var(--cd-a6) var(--cd-a4);
  font-size: var(--cd-gr-h3);
  line-height: 1.25;
}
.cd-datenschutzmodal__laedt {
  margin: 0;
  padding: 0 var(--cd-a6) var(--cd-a6);
  color: var(--cd-text-3);
}
/* Der nachgeladene Inhalt braucht denselben Innenabstand wie der
   Titel — er kommt als nackte Bahn aus der Seite. */
.cd-modal__inhalt[data-cd-dsziel] {
  padding: 0 var(--cd-a6) var(--cd-a6);
}
.cd-modal__inhalt[data-cd-dsziel] > .cd-bahn:first-child {
  padding-block-start: 0;
}

/* ------------------------------------------------------------
   Spinner
   ------------------------------------------------------------
   Sitzt im Knopf, solange ein Vorgang laeuft. Der Knopftext bleibt
   stehen — ein Knopf, der waehrend des Wartens seine Beschriftung
   verliert, laesst den Nutzer raten, was er gerade ausgeloest hat.

   aria-hidden am Element und aria-busy am Knopf: Die Drehung ist
   ein BILD des Wartens, die Ansage macht der Knopf.

   WER BEWEGUNG ABBESTELLT HAT, bekommt keine Drehung — aber sehr
   wohl ein Zeichen. Ein Punkt, der nur blasser wird, sagt dasselbe
   ohne Drehung; ganz wegzulassen hiesse, dass diese Nutzer als
   einzige nicht sehen, dass etwas laeuft.
   ------------------------------------------------------------ */
.cd-spinner {
  display: inline-block;
  inline-size: 14px;
  block-size: 14px;
  margin-inline-end: .6ch;
  border: 2px solid currentColor;
  border-block-start-color: transparent;
  border-radius: 50%;
  opacity: .8;
  animation: cd-drehen .7s linear infinite;
  /* Der Ring soll die Zeile nicht auseinanderziehen. */
  vertical-align: -2px;
}

@keyframes cd-drehen {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .cd-spinner {
    animation: cd-pulsen 1.2s ease-in-out infinite;
    border-block-start-color: currentColor;
  }
  @keyframes cd-pulsen {
    0%, 100% { opacity: .25; }
    50% { opacity: .9; }
  }
}

/* Ein laufender Knopf bleibt lesbar und ist nur nicht mehr
   bedienbar. Kein Ausgrauen bis zur Unkenntlichkeit — der Text ist
   die einzige Auskunft darueber, was gerade laeuft. */
button[aria-busy="true"] {
  cursor: progress;
  opacity: .72;
}

/* Ein Vorgang, der nicht durchging, faerbt seinen Rahmen. Die
   Begruendung steht als Satz im Meldebereich daneben — Farbe allein
   traegt keine Information. */
.cd-aktion--fehler .cd-knopf {
  border-color: var(--cd-rot);
  color: var(--cd-rot);
}

/* ------------------------------------------------------------
   Hinweis „KI-generiert"
   ------------------------------------------------------------
   Zwei Fassungen, gewaehlt nach der Groesse der Ansicht. Das
   Partial Bauteile/KiHinweis entscheidet, welche kommt.

   Zur Schriftgroesse: 11.5px und nicht die 9.5px der Marke
   nebenan. Die Marke ist ein Zeichen neben einem Wort, das in
   voller Groesse danebensteht — dieser Hinweis dagegen ist die
   Angabe selbst und muss gelesen werden koennen. Er hat keinen
   Text neben sich, der ihn erklaert.
   ------------------------------------------------------------ */
.cd-kihinweis {
  font-family: var(--cd-schrift-mono);
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Die Marke sitzt unten links. Oben ist beides belegt — links die
   Projektmarke, rechts die Fallstudien-Marke. */
.cd-kihinweis--marke {
  position: absolute;
  inset-block-end: var(--cd-a3);
  inset-inline-start: var(--cd-a3);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 999px;
  /* 82 Prozent Deckung und nicht weniger: der Grund liegt auf einem
     beliebigen Motiv. Selbst vor einer weissen Flaeche bleiben rund
     8,6:1 gegen die weisse Schrift — der Kontrast darf nicht davon
     abhaengen, was das Bild an dieser Stelle gerade zeigt. */
  background: color-mix(in srgb, var(--cd-dunkel) 82%, transparent);
  color: var(--cd-weiss);
  backdrop-filter: blur(6px);
  /* Die Marke gehoert zum Bild und nicht zur Bedienung: ein Klick
     soll den darunterliegenden Verweis treffen. */
  pointer-events: none;
}

/* Die Zeile unter der Kachel. Zurueckhaltend, aber lesbar — sie
   traegt dieselbe Angabe wie die Marke, nur ohne Grund. */
.cd-kihinweis--unterschrift {
  margin-block: var(--cd-a2) 0;
  color: var(--cd-text-3);
}

.cd-auf-dunkel .cd-kihinweis--unterschrift,
.cd-fuss .cd-kihinweis--unterschrift {
  color: var(--cd-text-auf-dunkel-2);
}

/* ------------------------------------------------------------
   Modalfenster: Auftritt und Ladezustand
   ------------------------------------------------------------
   Ein <dialog> erscheint von sich aus schlagartig. Bei einem
   Fenster, das den Inhalt erst holt, ist das die schlechtere
   Haelfte des Problems — die schlimmere war, dass es ueberhaupt
   erst NACH dem Laden aufging: man klickte, und sichtbar geschah
   nichts. Beides gehoert zusammen behandelt.

   Die Bewegung ist kurz und klein. Sie soll sagen "hier kommt ein
   Fenster", nicht sich selbst vorfuehren.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
  .cd-modal[open] {
    animation: cd-modal-auf var(--cd-zeit) var(--cd-kurve) both;
  }
  .cd-modal[open]::backdrop {
    animation: cd-schleier-auf var(--cd-zeit) ease both;
  }
}

@keyframes cd-modal-auf {
  from { opacity: 0; transform: translateY(10px) scale(.99); }
  to   { opacity: 1; transform: none; }
}

@keyframes cd-schleier-auf {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Der Ladezustand im Fenster. Der Ring ist das vorhandene
   Bauteil .cd-spinner — es bringt die Ruecksicht auf abbestellte
   Bewegung schon mit, und ein zweiter Ring waere ein zweiter Ort,
   an dem das gepflegt werden muesste.

   aria-hidden am Ring, die Ansage macht der Text daneben: Ein
   Vorleseprogramm soll "Die Hinweise werden geladen" hoeren und
   kein Bild beschrieben bekommen. */
.cd-modal__laden {
  display: flex;
  align-items: center;
  gap: var(--cd-a3);
  padding: var(--cd-a6) 0;
  color: var(--cd-text-2);
  font-size: var(--cd-gr-klein);
}

.cd-modal__laden .cd-spinner {
  inline-size: 18px;
  block-size: 18px;
  margin-inline-end: 0;
  color: var(--cd-rot);
}

/* Solange geladen wird, bleibt das Fenster ruhig: kein Springen,
   wenn der Text ankommt. Eine Mindesthoehe haelt den Platz. */
.cd-modal__inhalt[aria-busy="true"] {
  min-block-size: 8rem;
}

/* Der Ring in einem Verweis. Zwei Kleinigkeiten, die sonst
   auffallen: Er erbt die Unterstreichung des Links, und ohne
   Abstand klebt er am ersten Buchstaben. */
a > .cd-spinner {
  text-decoration: none;
  margin-inline-end: .5ch;
  vertical-align: -1px;
}

/* Die Fehlermeldung eines Feldes auf dunklem Grund. --cd-rot
   kommt dort auf 2,52:1 und ist damit unter jeder Schwelle —
   ausgerechnet der Satz, der sagt, was schiefging. Auf Anthrazit
   traegt --cd-rot-auf-dunkel mit 4,62:1.

   Die helle Insel im Formularkasten dreht es in cd_kontakt.css
   wieder zurueck: dort steht die Meldung auf Weiss. */
.cd-auf-dunkel .cd-feld__fehler,
.cd-auf-rot .cd-feld__fehler {
  color: var(--cd-rot-auf-dunkel);
}

/* ------------------------------------------------------------
   Ladeschleier — der Vorgang deckt die ganze Seite
   ------------------------------------------------------------
   Beim Nachladen einer Liste wechselt ein Teil der Seite seinen
   Inhalt. Ohne sichtbares Zeichen sieht das aus, als sei der Klick
   ins Leere gegangen — und der zweite Klick kommt, bevor der erste
   angekommen ist.

   GANZFLAECHIG UND NICHT NUR AM KNOPF: Der Schleier sperrt
   zugleich die Bedienung. Wer waehrend des Ladens dreimal auf
   "Seite 3" klickt, loest sonst drei Abrufe aus, und die Antworten
   kommen in beliebiger Reihenfolge zurueck.

   Er traegt role="status" und einen Text: Ein Vorgang ohne
   Seitenwechsel ist fuer eine Vorlesehilfe sonst unsichtbar. Der
   Text steht nur fuer sie da (cd-nurlesen), sichtbar ist der Ring.

   Der Ring ist derselbe wie ueberall (.cd-spinner), nur groesser
   gestellt — ein zweiter waere ein zweiter Ort, an dem die
   Ruecksicht auf abbestellte Bewegung gepflegt werden muesste.
   ------------------------------------------------------------ */
.cd-schleier {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: grid;
  place-items: center;
  /* Nicht deckend: Man soll sehen, WO man ist — der Schleier ist
     eine Zwischenzeit, kein Seitenwechsel. */
  background: color-mix(in srgb, var(--cd-grund) 72%, transparent);
  backdrop-filter: blur(2px);
  /* Der Einblendweg verhindert das Aufblitzen bei einer schnellen
     Antwort: Wer in 80 ms fertig ist, zeigt gar nichts. */
  opacity: 0;
  animation: cd-schleier-auf .18s ease .12s forwards;
}

.cd-schleier[hidden] { display: none; }

@keyframes cd-schleier-auf {
  to { opacity: 1; }
}

.cd-schleier__ring {
  inline-size: 44px;
  block-size: 44px;
  border-width: 3px;
  margin-inline-end: 0;
  color: var(--cd-rot);
}

@media (prefers-reduced-motion: reduce) {
  .cd-schleier { animation: none; opacity: 1; }
}
