/* ==========================================================================
   components.css — wiederverwendbare Bausteine
   --------------------------------------------------------------------------
   WOFÜR: Buttons, Karten, das Objektprotokoll-Panel, Leistungslisten,
          FAQ, Formular, Bildrahmen, Hinweisboxen.
   ABHÄNGIG VON: tokens.css, style.css
   BEIM ÄNDERN BEACHTEN: Jeder Baustein steht für sich und kennt seinen
          Kontext nicht. Wenn ein Baustein in einem dunklen Abschnitt anders
          aussehen muss, gibt es dafür eine ...--on-soft-Variante, keine
          Regeln der Form ".section--soft .card" quer über Dateien hinweg.
   ========================================================================== */

/* ==========================================================================
   1. Buttons
   Drei Stufen: .btn--primary (grün, EINE Hauptaktion pro Abschnitt —
   fast immer „Angebot anfordern“), .btn--ghost (Kontur — der Anruf) und
   .link-icon (Textlink mit Symbol — WhatsApp, weiter unten). Grün trägt
   dunkle Schrift — weiß auf Grün erreicht den Kontrastwert nicht.
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  min-height: 52px;
  padding: 0 var(--sp-6);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-brand);
  font-size: var(--fs-small);
  font-weight: 700;
  font-stretch: 104%;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}

.btn svg { width: 18px; height: 18px; fill: currentColor; flex: none; }

/* Beim Zeigen wandert ein grüner Strich einmal um den Knopf und schließt
   sich zum Ring — dieselbe Sprache wie die Summenlinie im Hero, die sich
   selbst zeichnet. Er läuft genau eine Runde (kein Endloskreisen) und
   steht bei prefers-reduced-motion sofort. Der Ring liegt als eigener
   Layer 5 px außerhalb; die Maske stanzt die Fläche aus, sodass nur der
   2 px starke Rand bleibt. Auf :focus-visible bleibt er aus — dort
   zeichnet schon der Fokusring, zwei Ringe wären Lärm. */
@property --btn-sweep {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.btn { position: relative; }

.btn::before {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: var(--radius-pill);
  padding: 2px;
  background: conic-gradient(
      var(--green) 0deg var(--btn-sweep),
      transparent var(--btn-sweep) 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease);
}

@media (hover: hover) {
  .btn:hover::before {
    opacity: 1;
    animation: btn-ring 560ms var(--ease-out) both;
  }
}

@keyframes btn-ring {
  from { --btn-sweep: 0deg; }
  to   { --btn-sweep: 360deg; }
}

.btn--primary { background: var(--green); color: var(--ink); }
.btn--primary:focus-visible { background: var(--green-dark); color: var(--ink); }
@media (hover: hover) {
  .btn--primary:hover { background: var(--green-dark); color: var(--ink); }
}

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line);
}

.btn--ghost:focus-visible { border-color: var(--ink); color: var(--ink); }
@media (hover: hover) {
  .btn--ghost:hover { border-color: var(--ink); color: var(--ink); }
}

.btn--block { width: 100%; }

/* Aktionspaar (Angebot + Telefon), überall gleich aufgebaut */
.actions { display: flex; flex-wrap: wrap; gap: var(--sp-4); }

/* Leise Zeile unter dem Aktionspaar: nimmt dem Hauptknopf die Hürde
   („unverbindlich“), ohne ihn länger zu machen. */
.actions__note {
  margin: var(--sp-3) 0 0;
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* --- Touch ------------------------------------------------------------------
   Auf Touch-Geräten gibt es kein Hover. Alle :hover-Regeln der Seite stehen
   deshalb unter @media (hover: hover) — sonst nimmt iOS den ersten Tipp als
   „Zeigen“ und erst der zweite löst aus. Rückmeldung kommt hier beim
   Drücken. touch-action: manipulation nimmt dem Browser den Doppeltipp-
   Zoom und damit die Wartezeit nach dem ersten Tipp. */
.btn {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

@media (hover: none) {
  .btn--primary:active { background: var(--green-dark); }
  .btn--ghost:active { border-color: var(--ink); background: var(--green-tint); }
}

/* --- Glanz ------------------------------------------------------------------
   Ein schmaler Lichtstreif wischt einmal über die grüne Fläche: beim
   Zeigen — und beim Hero-Knopf (.btn--hero) einmal kurz nach dem Laden,
   als leiser Hinweis, wo es weitergeht. Läuft als Verlauf auf ::after
   (::before gehört dem Ring); der Streif bleibt durch border-radius:
   inherit innerhalb der Pille. prefers-reduced-motion schaltet ihn mit
   allen anderen Animationen ab (style.css, Abschnitt 7). */
.btn--primary::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, 0.55) 50%, transparent 62%) no-repeat;
  background-size: 250% 100%;
  background-position: 130% 0;
  pointer-events: none;
}

@keyframes btn-sheen {
  from { background-position: 130% 0; }
  to   { background-position: -30% 0; }
}

.js .btn--hero::after { animation: btn-sheen 900ms var(--ease-out) 1400ms both; }

@media (hover: hover) {
  .btn--primary:hover::after { animation: btn-sheen 650ms var(--ease-out) both; }
}

/* Der Pfeil im Hauptknopf steht bereit und rückt beim Zeigen nach —
   die allgemeine Regel dafür steht in style.css (.btn:hover svg). */
.btn--hero svg { margin-right: -4px; }

/* --- Textlink mit Symbol ----------------------------------------------------
   Dritte Stufe nach .btn--primary und .btn--ghost: für Wege, die es geben
   soll, die aber nicht mit dem Hauptknopf konkurrieren (WhatsApp neben
   Telefon). Volle Trefferfläche, auch ohne Rahmen. */
.link-icon {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 44px;
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--green-text);
  text-decoration: none;
  touch-action: manipulation;
  transition: color var(--dur-fast) var(--ease);
}

.link-icon svg { width: 18px; height: 18px; fill: currentColor; flex: none; }

.link-icon:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

@media (hover: hover) {
  .link-icon:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
}

/* ==========================================================================
   2. Objektprotokoll — das Signature-Element
   Ein Datenblock im Stil eines Objektprotokolls: schmale Versal-Labels,
   Linienraster, klare Werte. Wird für Vertrauensangaben, Leistungsumfang,
   Ablauf und Kontaktdaten benutzt. Ersetzt die üblichen Icon-Kacheln.
   ========================================================================== */
.protocol {
  border: var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  overflow: hidden;   /* damit die Kopfzeile die Rundung mitnimmt */
}

.protocol__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  background: var(--green-tint);
  border-bottom: 1px solid var(--line-green);
}

.protocol__title {
  margin: 0;
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--green-text);
}

.protocol__stamp {
  font-family: var(--font-label);
  font-size: 0.6875rem;
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--green-text);
}

.protocol__row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
}

.protocol__row + .protocol__row { border-top: var(--border); }

.protocol__key {
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

.protocol__value {
  font-family: var(--font-brand);
  font-size: 1.0625rem;
  font-weight: 700;
  font-stretch: 104%;
  text-align: right;
  color: var(--ink);
}

.protocol__value a { color: inherit; text-decoration: none; }
@media (hover: hover) {
  .protocol__value a:hover { color: var(--green-text); }
}

/* Variante für grün getönte Abschnitte: das Panel bleibt weiß und hebt
   sich dadurch von der Fläche ab. */
.protocol--on-soft {
  border-color: var(--line-green);
  box-shadow: var(--shadow-hover);
}

/* ==========================================================================
   3. Vertrauensleiste — Zahlen statt Icons
   ========================================================================== */
.facts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-4);
}

@media (max-width: 860px) { .facts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .facts { grid-template-columns: 1fr; } }

.facts__item {
  padding: var(--sp-6) var(--sp-5);
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  transition: box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}

@media (hover: hover) {
  .facts__item:hover {
    box-shadow: var(--shadow-hover);
    transform: translateY(-2px);
  }
}

/* Grüner Strich über dem Kurzlabel: gibt der Kachel einen Anker */
.facts__key::before {
  content: "";
  display: block;
  width: 2rem;
  height: 3px;
  margin-bottom: var(--sp-4);
  background: var(--green);
  border-radius: var(--radius-pill);
}

/* Kurzlabel über der Zahl: sagt, wovon die Zahl handelt. Typografie wie
   .register, damit die Kachelköpfe klingen wie die Abschnittsreiter. */
.facts__key {
  display: block;
  margin-bottom: var(--sp-2);
  font-family: var(--font-label);
  font-size: 0.6875rem;
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--green-text);
}

.facts__value {
  display: block;
  font-family: var(--font-brand);
  font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.35rem);
  font-weight: 700;
  font-stretch: 114%;
  letter-spacing: -0.02em;
  line-height: 1.06;
  color: var(--ink);
  margin-bottom: var(--sp-3);
  /* Platz für zwei Zeilen, damit die Erklärtexte aller vier Kacheln auf
     derselben Höhe beginnen — auch wenn nur ein Wert umbricht. */
  min-height: calc(2 * 1.06em);
}

.facts__label {
  display: block;
  font-size: var(--fs-small);
  color: var(--text-muted);
  line-height: 1.45;
}

/* ==========================================================================
   4. Leistungskarten
   Bewusst NICHT vier gleich große Kacheln — die Größen kommen aus dem
   Raster in pages.css. Die Karte selbst kennt nur ihr Innenleben.
   ========================================================================== */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow-card);
  transition: border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}

a.card:focus-within {
  border-color: var(--green);
  box-shadow: var(--shadow-hover);
  transform: translateY(-3px);
}
@media (hover: hover) {
  a.card:hover {
    border-color: var(--green);
    box-shadow: var(--shadow-hover);
    transform: translateY(-3px);
  }
}

.card__media {
  position: relative;
  overflow: hidden;
  background: var(--paper);
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 400ms var(--ease);
}

@media (hover: hover) {
  a.card:hover .card__media img { transform: scale(1.03); }
}

.card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--sp-5) var(--sp-5) var(--sp-6);
}

.card__index {
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--green-text);
  margin-bottom: var(--sp-3);
}

.card__title { margin-bottom: var(--sp-3); }

.card__text {
  color: var(--text-muted);
  font-size: var(--fs-small);
  margin-bottom: var(--sp-5);
}

.card__more {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 700;
  font-size: var(--fs-small);
  color: var(--green-text);
}

.card__more svg {
  width: 16px;
  height: 16px;
  fill: currentColor;
  transition: transform var(--dur-fast) var(--ease);
}

@media (hover: hover) {
  a.card:hover .card__more svg { transform: translateX(3px); }
}

/* ==========================================================================
   5. Leistungslisten mit Häkchen
   ========================================================================== */
.check-list { list-style: none; margin-bottom: var(--sp-5); }

.check-list li {
  position: relative;
  padding-left: 1.9rem;
  margin-bottom: var(--sp-3);
  line-height: 1.55;
}

.check-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 0.85rem;
  height: 0.5rem;
  border-left: 2px solid var(--green);
  border-bottom: 2px solid var(--green);
  transform: rotate(-45deg);
}

/* Zwei Spalten nur, wenn jede mindestens 19rem breit werden kann. Sonst
   fällt die Liste von selbst auf eine Spalte zurück — das richtet sich nach
   dem Platz im Container, nicht nach der Fensterbreite. */
.check-list--two-col { columns: 19rem 2; column-gap: var(--sp-7); }
.check-list--two-col li { break-inside: avoid; }

/* ==========================================================================
   6. Ablauf in Schritten
   Nummerierung ist hier inhaltlich richtig: die Schritte laufen tatsächlich
   in dieser Reihenfolge ab.
   ========================================================================== */
.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-6);
  counter-reset: step;
  list-style: none;
}

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

.steps__item {
  counter-increment: step;
  padding: var(--sp-6);
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  transition: box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}

@media (hover: hover) {
  .steps__item:hover {
    box-shadow: var(--shadow-hover);
    transform: translateY(-2px);
  }
}

.steps__item::before {
  content: "Schritt " counter(step);
  display: block;
  margin-bottom: var(--sp-4);
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--green-text);
}

.steps__item h3 { margin-bottom: var(--sp-3); }
.steps__item p { color: var(--text-muted); font-size: var(--fs-small); }

/* Auf grün getönter Fläche */
.section--soft .steps__item { border-color: var(--line-green); }

/* ==========================================================================
   7. FAQ — <details>, funktioniert ohne JavaScript
   ========================================================================== */
.faq {
  border: var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.faq__item + .faq__item { border-top: var(--border); }

.faq__item summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-5);
  padding: var(--sp-5);
  cursor: pointer;
  list-style: none;
  font-family: var(--font-brand);
  font-size: var(--fs-h4);
  font-weight: 700;
  font-stretch: 106%;
  color: var(--ink);
}

.faq__item summary::-webkit-details-marker { display: none; }

/* Plus, das beim Öffnen zum Minus wird — reines CSS */
.faq__item summary::after {
  content: "";
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 0.35em;
  background:
    linear-gradient(var(--green), var(--green)) center / 100% 2px no-repeat,
    linear-gradient(var(--green), var(--green)) center / 2px 100% no-repeat;
  /* dieselbe Feder wie Menü-Knopf und Kontakt-Schnellwahl */
  transition: transform var(--dur-slow) var(--ease-spring);
}

.faq__item[open] summary::after {
  background: linear-gradient(var(--green), var(--green)) center / 100% 2px no-repeat;
  transform: rotate(180deg);
}

@media (hover: hover) {
  .faq__item summary:hover { color: var(--green-text); }
}

.faq__answer {
  padding: 0 var(--sp-5) var(--sp-5);
  max-width: 68ch;
  color: var(--text-muted);
}

.faq__item summary { transition: background var(--dur-fast) var(--ease),
                                 color var(--dur-fast) var(--ease); }
@media (hover: hover) {
  .faq__item summary:hover { background: var(--green-tint); }
}
.faq__item[open] summary { background: var(--green-tint); }

/* Die Antwort federt mit derselben Bewegung ein wie alle Listen der
   Seite (pop-in aus style.css, Abschnitt 7). */
.faq__answer-inner { overflow: hidden; }

.faq__item[open] .faq__answer { animation: pop-in 420ms var(--ease-spring); }

/* ==========================================================================
   8. Formular
   ========================================================================== */
.form { display: grid; gap: var(--sp-6); }

.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); }

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

.field { display: flex; flex-direction: column; gap: var(--sp-2); }

.field label {
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

.field .req { color: var(--green-text); }

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 52px;
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}

.field textarea { min-height: 8rem; resize: vertical; line-height: 1.5; }

@media (hover: hover) {
  .field input:hover,
  .field textarea:hover,
  .field select:hover { border-color: var(--grey); }
}

.field input:focus,
.field textarea:focus,
.field select:focus { border-color: var(--green-text); }

/* Fehlerzustand — wird von form.js gesetzt, Farbe ist nicht das einzige
   Signal: es kommt immer ein Text dazu. */
.field[data-invalid="true"] input,
.field[data-invalid="true"] textarea,
.field[data-invalid="true"] select { border-color: var(--error); border-width: 2px; }

.field__error {
  display: none;
  font-size: var(--fs-small);
  color: var(--error-text);
}

.field[data-invalid="true"] .field__error { display: block; }

/* Honeypot gegen Spam: für Menschen unsichtbar, für Bots ausfüllbar.
   Bewusst nicht display: none — das übergehen viele Bots. Und bewusst nicht
   left: -9999px: das schiebt das Feld aus dem Dokument heraus und macht die
   Seite messbar breiter als das Fenster. Die Clip-Technik nimmt keinen
   Platz ein und verschiebt nichts. */
.form__trap {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.form__consent {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-3);
  align-items: start;
  font-size: var(--fs-small);
  color: var(--text-muted);
}

.form__consent input {
  width: 22px;
  height: 22px;
  min-height: 0;
  margin-top: 2px;
  border-radius: 6px;
  accent-color: var(--green-dark);
}

.form__status {
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--line-green);
  border-radius: var(--radius-sm);
  background: var(--green-soft);
  font-size: var(--fs-small);
}

.form__status[hidden] { display: none; }
.form__status--error { border-color: var(--error-line); background: var(--error-soft); }

/* ==========================================================================
   9. Bilder
   Der Mäanderrahmen markiert das Hauptbild eines Abschnitts — sparsam.
   ========================================================================== */
.figure { margin: 0; }

.figure img { width: 100%; border-radius: var(--radius); }

.figure figcaption {
  margin-top: var(--sp-3);
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* Hauptbild eines Abschnitts: etwas stärker gerundet und leicht
   abgesetzt, damit es als Blickpunkt trägt. */
.figure--framed img {
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

/* ==========================================================================
   10. Hinweisbox — für rechtliche Platzhalter und Anmerkungen
   ========================================================================== */
.notice {
  padding: var(--sp-5);
  border: 1px solid var(--line-green);
  border-radius: var(--radius);
  background: var(--green-tint);
  box-shadow: var(--shadow-card);
  font-size: var(--fs-small);
  color: var(--text-muted);
}

.notice strong { color: var(--ink); }

/* ==========================================================================
   11. Zitat / Referenz
   ========================================================================== */
.quote {
  margin: 0;
  padding: var(--sp-6);
  border: var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.quote blockquote {
  margin: 0 0 var(--sp-5);
  font-family: var(--font-brand);
  font-size: var(--fs-h4);
  font-weight: 400;
  font-stretch: 104%;
  line-height: 1.45;
}

.quote figcaption {
  font-size: var(--fs-small);
  color: var(--text-muted);
}

.quote figcaption strong { display: block; color: var(--ink); }

/* ==========================================================================
   12. Tabelle (Impressum, Leistungsabgrenzung)
   ========================================================================== */
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-small);
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.table th,
.table td {
  padding: var(--sp-4);
  text-align: left;
  vertical-align: top;
  border-bottom: var(--border);
}

.table thead th { background: var(--green-tint); color: var(--green-text); }

.table tbody tr { transition: background var(--dur-fast) var(--ease); }
@media (hover: hover) {
  .table tbody tr:hover { background: var(--green-tint); }
}

.table th {
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

.table-scroll { overflow-x: auto; }

/* Unter 640 px passt die Tabelle nicht mehr nebeneinander. Statt sie
   seitlich scrollen zu lassen (die dritte Spalte verschwand ohne Hinweis,
   jede Zeile wurde über 100 px hoch) wird sie zur Protokoll-Liste: jede
   Zeile ein Block, die erste Zelle als Titel, die übrigen als
   Label-Wert-Paare. Das Label kommt aus data-label am <td>. Die
   role-Attribute im HTML halten die Tabellen-Semantik für Screenreader,
   die display: block sonst verwirft. */
@media (max-width: 640px) {
  .table,
  .table tbody,
  .table tr,
  .table td { display: block; }

  .table thead {               /* bleibt für Screenreader, wie .visually-hidden */
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .table tr { padding: var(--sp-4) var(--sp-5); }
  .table tr + tr { border-top: var(--border); }
  .table td { padding: 0; border: 0; }

  .table td:first-child {      /* die Aufgabe als Titel des Blocks */
    margin-bottom: var(--sp-3);
    font-family: var(--font-brand);
    font-size: 1.0625rem;
    font-weight: 700;
    font-stretch: 104%;
    color: var(--ink);
  }

  .table td[data-label] {      /* Label links, Wert daneben, linksbündig */
    display: grid;
    grid-template-columns: 6rem 1fr;
    gap: var(--sp-3);
    align-items: baseline;
  }
  .table td[data-label] + td[data-label] { margin-top: var(--sp-2); }

  .table td[data-label]::before {
    content: attr(data-label);
    font-family: var(--font-label);
    font-size: var(--fs-label);
    font-weight: 600;
    font-stretch: var(--width-label);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--text-muted);
  }
}

/* ==========================================================================
   13. Anfragestrecke (Funnel)
   Wird nur auf /angebot-anfordern.html verwendet, gehört aber hierher, weil
   die Teile (Auswahlkacheln, Fortschritt) wiederverwendbar sind.
   Gesteuert von assets/js/funnel.js — dort steht auch, wie data-show-if
   die Fragen an Kundentyp und Leistung koppelt.
   ========================================================================== */

/* Fortschritt */
.funnel__progress {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}

.funnel__progress-track {
  flex: 1;
  height: 8px;
  background: var(--green-soft);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.funnel__progress-bar {
  height: 100%;
  width: 25%;
  background: var(--green);
  border-radius: var(--radius-pill);
  transition: width var(--dur) var(--ease);
}

.funnel__progress-text {
  flex: none;
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Ein Schritt. Ohne JavaScript stehen alle sichtbar untereinander. */
.funnel__step {
  border: 0;
  padding: 0;
  margin: 0 0 var(--sp-7);
}

/* Ohne JavaScript stehen alle Schritte untereinander und das Formular
   funktioniert als ein Stück. Erst funnel.js blendet sie einzeln ein. */
[data-enhanced="true"] .funnel__step { margin-bottom: 0; }
[data-enhanced="true"] .funnel__step[hidden] { display: none; }

.funnel__step legend {
  padding: 0;
  margin-bottom: var(--sp-2);
  font-family: var(--font-brand);
  font-size: var(--fs-h3);
  font-weight: 700;
  font-stretch: var(--width-display);
  letter-spacing: -0.015em;
  color: var(--ink);
}

.funnel__step:focus { outline: none; }

.funnel__hint {
  margin-bottom: var(--sp-5);
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* Auswahlkacheln statt Radiobuttons: große Trefferfläche, sichtbarer
   Zustand, ein Klick genügt. */
.choices {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}

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

.choice {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}

@media (hover: hover) {
  .choice:hover {
    border-color: var(--green);
    background: var(--green-tint);
    transform: translateY(-2px);
    box-shadow: var(--shadow-card);
  }
}

.choice input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

/* Eigenes Kästchen, damit Zustand und Trefferfläche stimmen */
.choice__box {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 2px;
  border: 2px solid var(--line);
  border-radius: 7px;
  background: var(--surface);
  transition: border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}

.choice input[type="radio"] + .choice__box { border-radius: 50%; }

.choice input:checked + .choice__box {
  border-color: var(--green-dark);
  background: var(--green) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23241A15'%3E%3Cpath d='M9.6 16.2 5.4 12l-1.4 1.4 5.6 5.6 12-12L20.2 5.6z'/%3E%3C/svg%3E") center / 14px no-repeat;
}

.choice:has(input:checked) {
  border-color: var(--green);
  background: var(--green-soft);
}

.choice input:focus-visible + .choice__box {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

.choice__text { display: block; }

.choice__title {
  display: block;
  font-weight: 700;
  font-size: 1rem;
  color: var(--ink);
}

.choice__note {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* Navigation zwischen den Schritten */
.funnel__nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
  margin-top: var(--sp-5);
}

.funnel__nav .btn--ghost { order: -1; }

/* Jeder Schritt federt beim Erscheinen ein — dieselbe Bewegung wie alle
   Listen der Seite (pop-in aus style.css, Abschnitt 7). Nur unter .js:
   ohne JavaScript steht die Strecke statisch und nichts soll zappeln. */
.js .funnel__step:not([hidden]) { animation: pop-in 420ms var(--ease-spring) both; }

.funnel__error {
  margin-top: var(--sp-3);
  font-size: var(--fs-small);
  color: var(--error-text);
}

.funnel__error[hidden] { display: none; }

/* Vertrauensspalte neben der Strecke */
.funnel__aside .protocol + .protocol { margin-top: var(--sp-4); }

/* --- Dynamische Fragen -------------------------------------------------
   funnel.js blendet alles mit data-show-if aus, was nicht zur Auswahl
   passt (Kundentyp, Leistung, angekreuzte Aufgabe). Das hidden-Attribut
   allein reicht nicht: .choice ist display: flex und würde gewinnen. */
[data-funnel] [hidden] { display: none !important; }

/* Zwischenfrage innerhalb eines Schritts („Wie oft?“, „Ab wann?“) */
.funnel__question {
  margin: var(--sp-6) 0 var(--sp-3);
  font-family: var(--font-brand);
  font-size: var(--fs-h4);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.funnel__question:first-child { margin-top: 0; }

/* Zusatz „optional“ hinter einer Frage */
.funnel__optional {
  margin-left: var(--sp-2);
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
  vertical-align: middle;
}

/* Fragenblock je Leistung: ein Strich obendrüber, der Leistungsname als
   Chip. Kein eigener Hintergrund — die Karte ist schon weiß. */
.funnel__block {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: var(--border);
}

.funnel__tag {
  display: inline-block;
  margin-right: var(--sp-2);
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  background: var(--green-soft);
  color: var(--green-text);
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  vertical-align: middle;
}

/* Kompakte Kacheln für Aufgabenlisten: drei Spalten, weniger Polster */
.choices--compact { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.choices--compact .choice { padding: var(--sp-3) var(--sp-4); }
.choices--compact .choice__title { font-size: var(--fs-small); }

@media (max-width: 900px) { .choices--compact { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .choices--compact { grid-template-columns: 1fr; } }

/* Die fünfte Karte („Service nicht dabei?“) läuft über die ganze Breite */
.choice--wide { grid-column: 1 / -1; }

/* Fehlende Auswahl: Rahmen um die ganze Gruppe, dazu immer der Text
   in .funnel__error — Farbe ist nie das einzige Signal. */
[data-require-choice][data-invalid="true"] {
  outline: 2px solid var(--error);
  outline-offset: 6px;
  border-radius: var(--radius-sm);
}

/* Hinweis unter einem Feld */
.field__hint {
  margin: 0;
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* Drei Felder nebeneinander (Treppenhäuser, Etagen, Einheiten) */
.form__row--three { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 640px) { .form__row--three { grid-template-columns: 1fr; } }

/* Datei-Upload: die native Schaltfläche im Stil der Chips */
.field input[type="file"] {
  min-height: 0;
  padding: var(--sp-3);
  font-size: var(--fs-small);
  cursor: pointer;
}

.field input[type="file"]::file-selector-button {
  margin-right: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--green-soft);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

/* Zusammenfassung im letzten Schritt: die Schlüssel sind länger als in
   anderen Protokollen („Gebäudereinigung, Arbeiten“) und die Werte sind
   Listen. Beide Spalten dürfen deshalb unter ihre Wortbreite schrumpfen —
   sonst weitet die Zeile das 12-Spalten-Raster (1fr = min-content) und die
   Seite scrollt auf dem Handy waagerecht. Unter 560 px steht der Schlüssel
   über dem Wert. */
.funnel__summary .protocol__row { grid-template-columns: minmax(0, 1fr) minmax(0, auto); }
.funnel__summary .protocol__key,
.funnel__summary .protocol__value { overflow-wrap: anywhere; }

@media (max-width: 560px) {
  .funnel__summary .protocol__row { grid-template-columns: 1fr; gap: var(--sp-1); }
  .funnel__summary .protocol__value { text-align: left; }
}

/* Nach erfolgreichem Versand bleibt im letzten Schritt nur die Meldung
   stehen — die geleerten Felder darunter wären verwirrend. */
.funnel--sent .funnel__step > :not(.form__status) { display: none; }
.funnel--sent .form__status { margin-top: 0; }

/* Solange nichts angegeben ist */
.funnel__summary:empty::before {
  content: "Noch keine Angaben.";
  display: block;
  padding: var(--sp-3) 0;
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* ==========================================================================
   14. Schneefall — nur auf den Winterdienst-Flächen
   Dekoration, sonst nichts: aria-hidden im HTML, hier ohne Zeigereingaben.
   Gefüllt von assets/js/snow.js, das die Werte je Flocke als Custom
   Properties setzt. Deshalb reicht hier eine einzige Keyframes-Regel.
   ========================================================================== */
.snow {
  position: absolute;
  inset: 0;
  overflow: clip;
  pointer-events: none;
  border-radius: inherit;   /* folgt der Rundung der Fläche darunter */
}

.snow__flake {
  position: absolute;
  left: var(--snow-x, 50%);
  width: var(--snow-size, 5px);
  height: var(--snow-size, 5px);
  border-radius: 50%;
  background: var(--snow-color, var(--white));
  opacity: 0;
  animation: snowfall var(--snow-duration, 12s) linear var(--snow-delay, 0s) infinite;
  will-change: top, transform;
}

/* Eine Bahn für alle: fallen, dabei seitlich wandern, am Rand ausblenden.
   ACHTUNG, hier steckt die Falle: Der Fall läuft über `top`, weil sich
   Prozentwerte dort auf die HÖHE DES CONTAINERS beziehen. Bei
   `transform: translateY(%)` wären sie auf die Größe der Flocke selbst
   bezogen, also auf wenige Pixel — die Flocken würden praktisch stehen
   bleiben. Der seitliche Versatz läuft weiterhin über transform, weil er
   in Pixeln angegeben ist. */
@keyframes snowfall {
  0%   { top: -8%; transform: translateX(0); opacity: 0; }
  10%  { opacity: var(--snow-opacity, 0.5); }
  88%  { opacity: var(--snow-opacity, 0.5); }
  100% { top: 108%; transform: translateX(var(--snow-drift, 0px)); opacity: 0; }
}

/* Auf hellen Flächen sind weiße Flocken unsichtbar. Dort fallen sie in
   einem kühlen Grau, das sich vom Off-White gerade abhebt. */
.snow--light { --snow-color: var(--snow-light); }

@media (prefers-reduced-motion: reduce) {
  .snow { display: none; }
}

/* ==========================================================================
   15. Leistungsverzeichnis — die Positionsliste im Hero
   Eine Karte im Stil einer Rechnung: vier Positionen (die vier Gewerke),
   darunter die Summe. Jede Position trägt zwei Textebenen — erst das
   Problem, darunter die Leistung, die es löst. Die Problemzeile wird mit
   einer feinen grünen Linie durchgestrichen: erledigt.

   OHNE JAVASCRIPT: Der Grundzustand ist der fertige Zustand — alle
   Problemzeilen sind durchgestrichen. Erst assets/js/ledger.js schaltet
   mit .ledger--cycling in den Modus, in dem reihum genau eine Position
   hervorgehoben und gestrichen wird.

   BEIM ÄNDERN BEACHTEN:
   - .ledger__problem MUSS inline bleiben (kein display: block, kein
     Grid-/Flex-Kind). Die Streichlinie ist ein background-Verlauf mit
     box-decoration-break: clone — nur inline bekommt so jedes umbrochene
     Zeilenfragment seine eigene Linie in Zeilenmitte.
   - Der Aktivzustand ändert nur Farbe, Opacity und Transform, nie
     Geometrie. So verursacht die Rotation keinerlei Layoutsprünge.
   ========================================================================== */
.ledger {
  border: var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  overflow: hidden;   /* damit die Kopfzeile die Rundung mitnimmt */
}

.ledger__head {
  display: flex;
  flex-wrap: wrap;   /* wird die Spalte schmal, rutscht der Chip unter den Titel */
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  background: var(--green-tint);
  border-bottom: 1px solid var(--line-green);
}

.ledger__title {
  margin: 0;
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--green-text);
}

/* Chip wie beim Primärknopf: grüne Fläche, dunkle Schrift */
.ledger__stamp {
  padding: 2px var(--sp-3);
  border-radius: var(--radius-pill);
  background: var(--green);
  color: var(--ink);
  font-family: var(--font-label);
  font-size: 0.6875rem;
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  white-space: nowrap;
}

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

.ledger__list li + li { border-top: var(--border); }

.ledger__row {
  position: relative;   /* für den Schnee in der Winterdienst-Zeile */
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: start;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  text-decoration: none;
  color: inherit;
  transition: background var(--dur) var(--ease);
}

.ledger__pos {
  padding-top: 0.2em;   /* optisch auf die Problemzeile ausgerichtet */
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ledger__text { display: block; min-width: 0; }

/* Die Streichlinie ist derselbe Trick wie bei .mark: ein background-
   Verlauf, dessen Breite animiert wird. Bleibt die Zeile inline, streicht
   box-decoration-break: clone jedes umbrochene Fragment einzeln durch. */
.ledger__problem {
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--text-muted);
  background-image: linear-gradient(var(--green-text), var(--green-text));
  background-repeat: no-repeat;
  background-size: 100% 1px;   /* Grundzustand: gestrichen, also erledigt */
  background-position: 0 55%;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  transition: background-size 600ms var(--ease-out);
}

.ledger__solution {
  display: block;
  margin-top: 2px;
  font-family: var(--font-brand);
  font-size: var(--fs-body);
  font-weight: 700;
  font-stretch: 104%;
  color: var(--ink);
  transition: color var(--dur) var(--ease);
}

.ledger__arrow {
  width: 16px;
  height: 16px;
  margin-top: 0.35em;
  fill: var(--green-text);
  opacity: 0;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

/* Interaktiver Modus (nur mit ledger.js): erst ist nichts gestrichen,
   dann streicht reihum genau die aktive Position ihr Problem durch. */
.ledger--cycling .ledger__problem { background-size: 0% 1px; }
.ledger--cycling li.is-active .ledger__problem { background-size: 100% 1px; }

/* Aktive Position und Hover sehen gleich aus — Hover ist zugleich der
   Fallback ohne JavaScript. */
.ledger__list li.is-active .ledger__row { background: var(--green-tint); }
@media (hover: hover) {
  .ledger__row:hover { background: var(--green-tint); }
}

.ledger__list li.is-active .ledger__solution { color: var(--green-text); }
@media (hover: hover) {
  .ledger__row:hover .ledger__solution { color: var(--green-text); }
}

.ledger__list li.is-active .ledger__arrow,
.ledger__row:focus-visible .ledger__arrow { opacity: 1; transform: translateX(3px); }
@media (hover: hover) {
  .ledger__row:hover .ledger__arrow { opacity: 1; transform: translateX(3px); }
}

/* Fokusring nach innen — die Karte schneidet mit overflow: hidden ab */
.ledger__row:focus-visible { outline-offset: -3px; }

/* --- Jede Position trägt ihr eigenes Augenzwinkern, nur solange sie
   aktiv ist: Tropfen beim Hausmeister (der tropfende Hahn), Glanz bei
   der Reinigung, fallendes Laub im Grünen, Schnee im Winterdienst.
   Tropfen und Laub reiten auf der Schnee-Mechanik aus snow.js — nur
   Form, Farbe und Tempo weichen ab. Die festen Verzögerungen je Flocke
   überschreiben die zufälligen aus snow.js, damit die wenigen Teilchen
   versetzt statt im Gleichtakt fallen. ------------------------------------ */
.ledger__row .snow { opacity: 0; transition: opacity var(--dur-slow) var(--ease); }
.ledger__list li.is-active .ledger__row .snow { opacity: 1; }

/* Pos. 01 — Wassertropfen: schneller Fall, Tropfenform */
.snow--drops .snow__flake {
  border-radius: 45% 45% 62% 62%;
  animation-duration: 2.6s;
}
.snow--drops .snow__flake:nth-child(1) { animation-delay: -0.9s; }
.snow--drops .snow__flake:nth-child(2) { animation-delay: -2.1s; }

/* Pos. 03 — Laub: Blattform in hellem Grün, gemächlicher Fall */
.snow--laub { --snow-color: var(--green-light); }
.snow--laub .snow__flake {
  border-radius: 0.15em 65% 0.15em 65%;
  animation-duration: 6s;
}
.snow--laub .snow__flake:nth-child(1) { animation-delay: -1s; }
.snow--laub .snow__flake:nth-child(2) { animation-delay: -3s; }
.snow--laub .snow__flake:nth-child(3) { animation-delay: -5s; }

/* Pos. 02 — Glanz: ein Lichtstreif wischt kurz nach der Aktivierung
   einmal diagonal über die frisch geputzte Zeile. Der Streif steht an
   Anfang und Ende außerhalb der Fläche, deshalb springt nichts. */
.ledger__row--glanz::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(105deg,
      transparent 42%, var(--white) 50%, transparent 58%) no-repeat;
  background-size: 220% 100%;
  background-position: 180% 0;
}

.ledger__list li.is-active .ledger__row--glanz::after {
  animation: ledger-glanz 1100ms var(--ease-out) 400ms 1;
}

@keyframes ledger-glanz {
  from { background-position: 180% 0; opacity: 0.55; }
  to   { background-position: -80% 0; opacity: 0.55; }
}

/* Die Summe steht unter einer doppelten Linie — der Schlussstrich einer
   Rechnung. */
.ledger__sum {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--green);
}

.ledger__sum::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--green);
}

.ledger__sum-label {
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 600;
  font-stretch: var(--width-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--green-text);
}

.ledger__sum-value {
  font-family: var(--font-brand);
  font-size: var(--fs-body);
  font-weight: 700;
  font-stretch: 104%;
  text-align: right;
  color: var(--ink);
}

/* Schmale Viewports: das Pos.-Label wird zur Kopfzeile der Position,
   der Pfeil rückt daneben, der Text bekommt die volle Breite. Ohne die
   linke Spalte brechen Problem und Leistungsname deutlich seltener um,
   die Karte wird kürzer und ruhiger. */
@media (max-width: 600px) {
  .ledger__row {
    grid-template-columns: 1fr auto;
    row-gap: var(--sp-2);
    align-items: center;
  }
  .ledger__pos { grid-area: 1 / 1; padding-top: 0; }
  .ledger__arrow { grid-area: 1 / 2; margin-top: 0; }
  .ledger__text { grid-area: 2 / 1 / 3 / 3; }

  /* Die Summe bekommt ihre eigene Zeile; eine Schriftstufe kleiner
     bleibt der Wert auch auf schmalen Telefonen einzeilig. */
  .ledger__sum-label { width: 100%; }
  .ledger__sum-value { font-size: var(--fs-small); }
}

/* Wer Bewegung reduziert hat, sieht sofort den fertigen Zustand — das
   Skript steigt dann ohnehin aus, das hier ist der doppelte Boden. */
@media (prefers-reduced-motion: reduce) {
  .ledger--cycling .ledger__problem,
  .ledger__problem { background-size: 100% 1px; transition: none; }
  .ledger__row,
  .ledger__solution,
  .ledger__arrow { transition: none; }
}

/* ==========================================================================
   16. Animierte Symbole (Lottie) — gesteuert von assets/js/lottie.js
   Ein Container .lottie, darin ein Standbild (<img class="lottie__fallback">)
   für alle, die keine Bewegung bekommen: ohne JavaScript, bei
   prefers-reduced-motion, wenn die Datei fehlt. Sobald die Animation
   geladen ist, trägt der Container data-lottie-state="ready" und das
   Standbild verschwindet. Die Größe legt allein --lottie-size fest —
   das Symbol selbst ist ein SVG, das sich in den Kasten einpasst.
   Die vier Einbauorte:
     .card__icon      über der Positionsnummer einer Leistungskarte
     .steps__icon     über „Schritt n“ im Ablauf (order: -1 schiebt es vor
                      das ::before-Pseudoelement, das den Zähler trägt)
     .protocol__icon  rechts in der Kopfzeile eines Datenblatts
     .page-icon       über dem Registerreiter auf Danke- und Fehlerseite
   ========================================================================== */
.lottie {
  position: relative;
  display: block;
  width: var(--lottie-size, 64px);
  height: var(--lottie-size, 64px);
  flex: none;
  pointer-events: none;   /* nie im Weg — die Karte darunter bleibt klickbar */
}

/* overflow: visible, damit ein Symbol, das beim Schwingen kurz über seine
   Leinwand hinausragt (der Schraubenschlüssel), nicht abgeschnitten wird —
   die Leinwand ist eng um die Ruhelage geschnitten. */
.lottie svg { display: block; width: 100%; height: 100%; overflow: visible; }

.lottie__fallback {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.lottie[data-lottie-state="ready"] .lottie__fallback { display: none; }

.card__icon { margin-bottom: var(--sp-4); }

.steps__item { display: flex; flex-direction: column; }
.steps__icon { order: -1; margin-bottom: var(--sp-4); }

/* In der Kopfzeile des Datenblatts: die Zeile bleibt so hoch wie ohne
   Symbol — die negativen Ränder lassen es in den Innenabstand ragen. */
.protocol__icon {
  --lottie-size: 40px;
  align-self: center;
  margin: -12px 0;
}

.page-icon {
  --lottie-size: 96px;
  margin-bottom: var(--sp-5);
}

/* Die „404“ ist breiter als hoch */
.page-icon--wide { width: 168px; height: 119px; }
