/* ============================================================================
   AS7-Reinigung – Design-System
   Schwarz-Weiß, dunkel. Eine Grotesk für alles, Überschriften nur fetter.

   Es wird keine einzige Schriftdatei geladen – weder von einem externen
   Dienst noch vom eigenen Server. Die Begründung steht als Kommentar in
   Components/App.razor. Symbole sind Inline-SVG (Components/Shared/
   Symbol.razor), also gibt es auch keine Symbolschrift.
   ========================================================================== */


/* ---------- Tokens ---------- */
/*
   Warm statt kühl, passend zu den sonnigen Startbildern: Die Dunkeltöne haben
   einen leichten Braunstich statt des früheren Blaugraus, Schrift und Linien
   sind warmgrau, das helle Band cremefarben. Helligkeit wie zuvor – alle
   Schriftkontraste sind gleich oder besser (faint auf Karte jetzt 4,79:1,
   vorher 3,92:1).

   Wer hier dreht: Die festen Werte rgba(14, 12, 10, …), rgba(18, 15, 12, …)
   und rgba(22, 18, 14, …) weiter unten sind dieselben Töne als Verläufe.
*/
:root {
  --bg: #0f0d0b;
  --panel: #13110e;
  --surface: #171410;
  --card: #1e1a15;
  --card-hover: #25201a;

  --line: #2f2922;
  --line-2: #373028;
  --line-3: #433a31;

  --fg: #f2ece3;
  --fg-2: #e3dbcf;
  --muted: #b3a999;
  --dim: #9a8f81;
  --faint: #908578;
  --on-light-muted: #5b5248;

  /*
     Ein einziger Schriftstapel für die ganze Seite – der Besucher sieht die
     Schrift seines eigenen Geräts: Windows Segoe UI, iPhone/iPad/Mac San
     Francisco (über -apple-system), Android Roboto, Linux das, was
     system-ui dort auflöst.

     Überschriften unterscheiden sich vom Fließtext allein über das Gewicht
     (siehe .display), nicht über eine zweite Schrift. Der frühere
     Serifen-Token für Georgia ist damit entfallen.
  */
  --sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    'Helvetica Neue', Arial, sans-serif;

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 14px;

  --gutter: clamp(20px, 4vw, 52px);
  /* Knapp genug, dass auf einem Bildschirm mehr als ein Abschnitt Platz hat. */
  --section-y: clamp(40px, 5vw, 64px);
  --gap: clamp(14px, 1.8vw, 22px);
  --gap-lg: clamp(34px, 4.5vw, 60px);

  --fs-h1: clamp(42px, 7.2vw, 80px);
  --fs-h1-sub: clamp(36px, 5.2vw, 60px);
  --fs-h2: clamp(28px, 3.7vw, 42px);
  --fs-h3: clamp(17px, 1.6vw, 18px);
  --fs-lead: clamp(16px, 1.35vw, 18px);
  --fs-stat: clamp(34px, 4.2vw, 46px);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --max: 1280px;

  /*
     Höhe der Kopfzeile. Als Token, weil drei Dinge denselben Wert brauchen:
     die Leiste selbst, der Innenabstand der Abschnitte, die unter ihr
     hindurchlaufen (Hero, Kopfbilder), und der Wachposten, der das Umschalten
     von durchsichtig auf deckend auslöst.
  */
  --kopf-hoehe: clamp(64px, 7vw, 84px);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
img, svg, picture { display: block; max-width: 100%; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }

/*
   Eine Schrift, kein Kursiv: Browser setzen diese Elemente von sich aus kursiv
   bzw. <code> in eine Schreibmaschinenschrift. Hier gesammelt zurückgesetzt,
   damit auch künftig eingefügter Text nicht aus der Reihe fällt.
*/
em, i, cite, var, dfn, address { font-style: normal; }
code, kbd, samp, pre { font-family: inherit; font-size: inherit; }
a { color: inherit; text-decoration: none; }
::placeholder { color: var(--faint); opacity: 1; }
::selection { background: var(--fg); color: var(--bg); }

:focus-visible {
  outline: 2px solid var(--fg);
  outline-offset: 3px;
  border-radius: 3px;
}

/*
   Ausnahme für Überschriften, die den Fokus nur programmatisch bekommen.
   <FocusOnNavigate Selector="h1"> aus Routes.razor setzt nach jedem
   Seitenaufruf tabindex="-1" auf die H1 und fokussiert sie, damit
   Screenreader die neue Seite ansagen. Chrome wertet das als
   :focus-visible und zeichnete dadurch einen 2 px breiten cremefarbenen
   Rahmen um den Hero-Claim – auf den hellen Bildern der Diaschau deutlich
   sichtbar.

   Den Ring hier zu entfernen ist keine Verschlechterung der
   Barrierefreiheit: Eine Überschrift ist nicht bedienbar, der Ring zeigt
   also keine Bedienmöglichkeit an. Die Ansage an den Screenreader
   funktioniert unabhängig davon weiter, und jedes tatsächlich bedienbare
   Element behält seinen Fokusrahmen.
*/
h1[tabindex="-1"]:focus,
h1[tabindex="-1"]:focus-visible {
  outline: none;
}

/* Skip-Link für Tastaturnutzung */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--fg);
  color: var(--bg);
  padding: 12px 20px;
  border-radius: 0 0 var(--r-sm) 0;
  font-size: 14px;
}
.skip-link:focus { left: 0; }

/* ---------- Typografie ---------- */

/*
   Alle Display-Elemente an einer Stelle. Sie tragen denselben
   Systemschriftstapel wie der Fließtext, nur deutlich fetter – dieselbe
   Anmutung wie bei AS7 Performance.

   Eine eigene font-family steht hier bewusst nicht mehr: body setzt bereits
   --sans, alles erbt sie von dort. Ebenso entfällt das frühere
   font-variant-numeric: lining-nums – das stellte nur Georgias
   Mediävalziffern gerade, und Systemschriften setzen ohnehin Versalziffern.

   700 statt einer höheren Stufe, weil Segoe UI, San Francisco und Roboto
   alle einen echten Bold-Schnitt mitbringen. Bei 800 oder 900 müssten
   manche Systeme die Fettung rechnerisch erzeugen, was ausgefranst aussieht.
*/
.display,
.brand__name,
.stat__value,
.step__no,
.rating-box__score b {
  font-weight: 700;
}
.display {
  /* Fette Groteske läuft im Großen zu weit – enger als bei der Serife. */
  letter-spacing: -0.03em;
  line-height: 1.05;
  text-wrap: pretty;
  /*
     Lange deutsche Einzelwörter wie „Kindergartenreinigung" passen in fetter
     Grotesk nicht in schmale Spalten – auf der Detailseite liefen sie bei
     1100px um bis zu 106px über. hyphens: auto trennt nach deutscher
     Silbenregel, aber nur, wo der Browser ein Trennwörterbuch hat (lang="de"
     steht in App.razor). Wo es fehlt, zerschnitt overflow-wrap die Titel an
     beliebiger Stelle („Treppenhausreinig|ung"). Die Leistungstitel bekommen
     deshalb zusätzlich weiche Trennstellen im Markup
     (Components/Shared/Trennung.cs); overflow-wrap bleibt als letztes Netz
     gegen seitliches Scrollen.
  */
  hyphens: auto;
  overflow-wrap: break-word;
}
.h1 { font-size: var(--fs-h1); line-height: 1.02; }
.h1-sub { font-size: var(--fs-h1-sub); }
.h2 { font-size: var(--fs-h2); line-height: 1.1; }

/*
   Rubrikzeile über Überschriften. Früher in Großbuchstaben mit weiter
   Laufweite; auf Wunsch jetzt in normaler Schreibung. Dafür etwas größer und
   halbfett, damit sie weiter als Rubrik und nicht als Fließtext gelesen wird.
*/
.eyebrow {
  font-size: 14px;
  font-weight: 600;
  color: var(--fg);
  margin-bottom: 14px;
}
.lead {
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: var(--muted);
  text-wrap: pretty;
}
.muted { color: var(--muted); }
.dim { color: var(--dim); }
.faint { color: var(--faint); }
.measure { max-width: 56ch; }
.measure-tight { max-width: 26ch; }

/* ---------- Layout ---------- */
.container {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: var(--section-y); }
.section--panel { background: var(--panel); }
.section--line { border-top: 1px solid var(--line); }

/* Helles Band – invertiert die Farbwelt */
.band {
  background: var(--fg);
  color: var(--bg);
}
.band .lead, .band .stat-label { color: var(--on-light-muted); }

.section-head {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: clamp(20px, 2.5vw, 30px);
}
.section-head p { margin-top: 14px; }
/* Für Abschnittsüberschriften ohne .section-head – gleicher Abstand nach unten. */
.abschnitt-titel { margin-bottom: clamp(20px, 2.5vw, 30px); }

.grid { display: grid; gap: var(--gap); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

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

.split {
  display: flex;
  gap: var(--gap-lg);
  align-items: flex-start;
}
.split > * { min-width: 0; }
@media (max-width: 900px) { .split { flex-direction: column; } }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid transparent;
  border-radius: 9px;
  padding: 15px 26px;
  font-size: 15px;
  line-height: 1.2;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease),
    color 0.2s var(--ease), transform 0.2s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }

.btn--primary { background: var(--fg); color: var(--bg); }
.btn--primary:hover { background: #fff; }

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

/* Auf hellem Band drehen sich die Rollen um */
.band .btn--primary { background: var(--bg); color: var(--fg); }
.band .btn--primary:hover { background: #25201a; }

.btn--sm { padding: 11px 18px; font-size: 14px; border-radius: var(--r-sm); }
.btn--block { width: 100%; }

.link-more {
  font-size: 14px;
  color: var(--fg);
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s var(--ease);
}
.link-more:hover { border-bottom-color: var(--fg); }

/* ---------- Kopfzeile ---------- */
/*
   Kopfzeile: am Seitenanfang durchsichtig, damit Hero und Kopfbilder darunter
   hindurchlaufen; ab dem ersten Scrollen deckend.

   Das Deckendwerden ist kein Schmuck, sondern nötig: Das Kennzahlenband auf der
   Startseite hat einen cremefarbenen Hintergrund (.band). Bliebe die Leiste
   durchsichtig, stünde die helle Schrift der Navigation darauf praktisch
   unsichtbar. Die Klasse setzt site.js über einen Wachposten am Seitenanfang.

   Die Trennlinie unten ist ein box-shadow und kein border: Ein Rahmen zählt zur
   Höhe der Leiste, dann stimmte der negative Außenabstand von Hero und
   Kopfbildern um ein Pixel nicht und oben bliebe ein heller Spalt. Ein Schatten
   wirkt sich nicht auf das Layout aus.
*/
.site-header {
  position: sticky;
  top: 0;
  z-index: 90;
  background: rgba(22, 18, 14, 0.88);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 var(--line);
  transition: background-color 0.25s var(--ease), box-shadow 0.25s var(--ease),
    backdrop-filter 0.25s var(--ease);
}

/*
   Durchsichtig nur, wenn JavaScript läuft – site.js setzt dazu die Klasse js
   auf <html> und beim Scrollen zusätzlich gescrollt. Deckend ist der sichere
   Zustand und deshalb die Vorgabe: Ohne JavaScript gäbe es niemanden, der die
   Leiste über dem cremefarbenen Band wieder deckend schaltet, und die helle
   Schrift stünde dort unlesbar.
*/
.js:not(.gescrollt) .site-header {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: 0 1px 0 transparent;
}

/*
   Weicher Verlauf hinter der durchsichtigen Leiste. Ohne ihn fällt der Kontrast
   der Navigationslinks (heute #b3a999) über den hellen Stellen des ersten Hero-Bildes
   auf 3,19:1 – die WCAG verlangt 4,5:1. Gemessen an den echten Bilddaten unter
   dem bereits vorhandenen Hero-Verlauf: nötig wären 0,33, hier stehen 0,5 bis
   0,62 im Bereich der Schrift, damit kommen alle Bilder auf über 5:1.

   Der Verlauf ist anderthalbmal so hoch wie die Leiste und läuft nach unten aus,
   damit keine sichtbare Kante entsteht. Er liegt immer im Dokument und wird nur
   ein- und ausgeblendet – so läuft er synchron mit dem Farbwechsel der Leiste,
   statt beim Umschalten zu springen.
*/
.site-header::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 150%;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s var(--ease);
  background: linear-gradient(180deg,
    rgba(14, 12, 10, 0.62) 0%,
    rgba(14, 12, 10, 0.5) 50%,
    rgba(14, 12, 10, 0) 100%);
}
.js:not(.gescrollt) .site-header::before { opacity: 1; }
/* Handy/Tablet: Keine Menülinks in der Leiste (nur Logo, Button, Burger) – der
   Verlauf ist dort unnötig und wirkte wie ein dunkler Balken. */
@media (max-width: 899px) {
  .js:not(.gescrollt) .site-header::before { opacity: 0; }
}

/*
   Wachposten: unsichtbar, so hoch wie die Kopfzeile, ganz oben im Dokument.
   Sobald er aus dem Blickfeld gescrollt ist, wird die Leiste deckend. Ein
   IntersectionObserver darauf ist deutlich sparsamer als ein scroll-Ereignis,
   das bei jedem Rad-Tick feuert.
*/
.kopf-posten {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: var(--kopf-hoehe);
  pointer-events: none;
}
/*
   Dreispaltiges Raster statt Flexbox, damit die Bewertung in der Mitte der
   KOPFZEILE sitzt und nicht in der Mitte zwischen Navigation und Aktionen.
   Die beiden äußeren Spalten sind gleich breit, also bleibt die mittlere
   zentriert, egal wie unterschiedlich breit links und rechts sind.
   minmax(0, 1fr) statt 1fr: sonst könnte zu breiter Inhalt seine Spalte
   über die Zeile hinaus aufziehen.

   Die Spalten sind bewusst fest zugewiesen: Navigation links, Bewertung
   mittig, Aktionen rechts. Ohne feste Zuweisung rückten Elemente nach, sobald
   eines ausgeblendet wird. Unter 900px schaltet der Block weiter unten auf
   ein einspaltiges Raster mit Burger-Menü um.
*/
.site-header__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(16px, 2.5vw, 28px);
  height: var(--kopf-hoehe);
  /*
     Hebt die --max von 1280px auf, die .container mitbringt. Sonst sitzt der
     Kopfzeileninhalt auf breiten Bildschirmen als 1280px-Block in der Mitte
     und lässt links wie rechts mehrere hundert Pixel leer – die Marke steht
     dann eben nicht ganz links, sondern eingerückt. Der Innenabstand (gutter)
     bleibt, damit nichts die Bildschirmkante berührt.
  */
  max-width: none;
}
.brand {
  display: flex;
  align-items: center;
  gap: 11px;
}
/*
   Logo in der Kopfzeile: ab 1200px 84px, auf dem Handy 56px – das Bild darf
   so hoch werden wie die Kopfzeile selbst. Der sichtbare Kreis füllt nur 59%
   der PNG-Datei (304 von 512px), rundherum ist gut ein Fünftel transparent.
   Bei 84px Bildgröße ist der Kreis also 50px groß und hat trotzdem rund 17px
   Abstand zur Ober- und Unterkante. Das Logo im Footer hat eine eigene feste
   Größe und ist hiervon nicht betroffen.

   Der Kreis sitzt in der Datei nicht mittig: oben 119px transparenter Rand,
   unten nur 90px. translateY gleicht die halbe Differenz (14,5 von 512px =
   2,83%) aus. Als Prozentwert bezieht sich die Verschiebung auf die eigene
   Bildhöhe und stimmt deshalb bei jeder Logogröße; am Layout ändert sie nichts.
*/
.site-header .brand img {
  width: clamp(56px, 7vw, 84px);
  height: auto;
  transform: translateY(-2.83%);
}
.brand__name {
  font-size: clamp(19px, 2vw, 23px);
  letter-spacing: 0.2px;
  white-space: nowrap;
}

.site-nav {
  grid-column: 1;
  justify-self: start;
  display: flex;
  gap: clamp(16px, 2vw, 26px);
  font-size: 14px;
}

/* Bewertung als mittlere Spalte – führt zur Bewertungsseite. */
.header-rating {
  grid-column: 2;
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 14px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  font-size: 14px;
  white-space: nowrap;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.header-rating:hover { border-color: var(--line-3); background: var(--card); }
.header-rating .stars { font-size: 13px; letter-spacing: 1px; }
.header-rating b { font-weight: 600; }
.header-rating span { color: var(--muted); }
.header-rating .header-rating__quelle {
  font-size: 12px;
  border-left: 1px solid var(--line-2);
  padding-left: 9px;
}
/* Mit fünf Menüpunkten passt das Feld erst ab 1200px neben das Menü (gemessen:
   unter 1180px überlappt es). Darunter fällt es in der Kopfzeile weg – die Note
   steht auf der Startseite gleich unter dem Startbild und auf der Bewertungsseite. */
@media (min-width: 900px) and (max-width: 1199px) {
  .header-rating { display: none; }
}
.site-nav a {
  color: var(--muted);
  padding-block: 6px;
  border-bottom: 1px solid transparent;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.site-nav a:hover { color: var(--fg); }
.site-nav a.active { color: var(--fg); border-bottom-color: var(--fg); }

.header-actions {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 18px;
}

/* Burger */
.burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 42px;
  height: 42px;
  padding: 0 10px;
  background: transparent;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  cursor: pointer;
}
.burger span {
  display: block;
  height: 2px;
  background: var(--fg);
  transition: transform 0.25s var(--ease), opacity 0.2s var(--ease);
}
.burger[aria-expanded='true'] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger[aria-expanded='true'] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded='true'] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.mobile-nav {
  display: none;
  flex-direction: column;
  gap: 2px;
  padding: 8px 0 20px;
  border-top: 1px solid var(--line);
}
.mobile-nav a {
  padding: 15px 2px;
  font-size: 17px;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
}
.mobile-nav a.active { color: var(--fg); }
/* Den Angebots-Button gibt es schon in der Kopfzeile. Im Menü nur dort, wo er in der
   Kopfzeile fehlt (unter 350px, siehe unten) – sonst stand er doppelt da. */
.mobile-nav .btn { display: none; margin-top: 18px; }

/*
   Offenes Handy-Menü: Leiste und Menü immer deckend. Am Seitenanfang ist die Leiste
   sonst durchsichtig – dann schimmerte das Startbild durch das Menü, und der Button
   unten schien frei über dem Bild zu schweben. Der Schatten setzt das Menü vom Bild ab.
*/
.js:not(.gescrollt) .site-header.site-header--menue-offen,
.site-header.site-header--menue-offen {
  background: rgba(22, 18, 14, 0.97);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 var(--line), 0 24px 48px rgba(0, 0, 0, 0.5);
}

/*
   Umbruchpunkt der Kopfzeile – gemessen, nicht geschätzt. Seit rechts nur
   noch Button und Logo stehen, wird es zuerst links eng, wo Navigation und
   Bewertung zusammenrücken:

     Breite   Luft links   Luft rechts
     1024px      98px        169px
      900px      49px        117px
      850px      29px         96px
      760px      -2px         62px

   Unter 900px übernimmt deshalb das Burger-Menü.
*/
@media (max-width: 899px) {
  .site-nav, .header-rating { display: none; }
  .burger { display: flex; }
  .mobile-nav.open { display: flex; }

  /*
     Navigation und Bewertung sind hier weg, damit stünden nur noch die
     Aktionen in Spalte 3 und die linke Bildschirmhälfte bliebe leer.
     Deshalb wird das Raster einspaltig, die Aktionsleiste nimmt die volle
     Breite und die Marke rückt per order an den Anfang: Logo links,
     Button und Burger rechts – die gewohnte mobile Aufteilung.
  */
  .site-header__inner { grid-template-columns: minmax(0, 1fr); }
  .header-actions {
    grid-column: 1;
    width: 100%;
    justify-content: flex-end;
  }
  .header-actions .brand { order: -1; margin-right: auto; }
}
/*
   Der Angebots-Button bleibt auch auf dem Handy in der Kopfzeile. Nur auf
   sehr schmalen Geräten unter 350px passen Logo (56px), Button und Burger
   nicht mehr nebeneinander – dort wandert der Button ins Menü.
*/
@media (max-width: 349px) {
  .header-actions .btn { display: none; }
  .mobile-nav .btn { display: inline-flex; }
}

/* ---------- Hero ---------- */
/*
   Hero und Kopfbilder laufen unter der Kopfzeile hindurch: Der negative
   Außenabstand zieht sie um die Höhe der Leiste nach oben, der gleich große
   Innenabstand hält den Inhalt wieder darunter. Das Bild liegt auf inset:0 und
   füllt dadurch auch den Streifen hinter der Leiste.
*/
.hero,
.section--kopfbild {
  margin-top: calc(-1 * var(--kopf-hoehe));
}
.hero { padding-top: var(--kopf-hoehe); }
.section--kopfbild { padding-top: calc(var(--section-y) + var(--kopf-hoehe)); }

.hero {
  position: relative;
  display: flex;
  background: var(--panel);
  overflow: hidden;
  isolation: isolate;
}
.hero__inner {
  display: flex;
  flex-direction: column;
  position: relative;
  /* Inhalt mittig – Logo und Claim stehen zentriert im Bild. */
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: clamp(20px, 3vw, 32px);
  /*
    Vollbild: Kopfzeile und Hero füllen zusammen genau den Bildschirm, damit
    alles, was die Firma erklärt – Ortszeile, Spruch, Text, Buttons – ohne
    Scrollen zu sehen ist. svh statt vh, damit auf dem Handy die ein- und
    ausfahrende Adressleiste nichts verdeckt; die vh-Zeile davor ist der
    Rückfall für Browser ohne svh. Untergrenze 460px für sehr flache Fenster.

    Auf breiten, flachen Bildschirmen wird das 16:9-Bild dabei oben und unten
    etwas beschnitten. Das ist gewollt: Der Inhalt hat Vorrang vor dem
    unbeschnittenen Bild.
  */
  min-height: max(460px, calc(100vh - var(--kopf-hoehe)));
  min-height: max(460px, calc(100svh - var(--kopf-hoehe)));
  padding-block: clamp(20px, 3.5svh, 56px);
}
.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  /*
     Einmalige Auftaktfahrt wie zuvor – jetzt auf dem Container statt am Bild,
     damit alle Kacheln gemeinsam fahren. Pro Kachel wäre sie unbrauchbar:
     Kachel 1 ist beim Zyklusende wieder sichtbar und müsste ihren Zoom im
     verdeckten Zeitfenster zurückstellen, sonst springt sie beim Aufblenden.
  */
  animation: heroZoom 18s var(--ease) forwards;
}
@keyframes heroZoom {
  from { transform: scale(1.06); }
  to { transform: scale(1); }
}
/*
   Hero-Diaschau — bewusst rein in CSS, ohne Timer in C#.

   Ein Blazor-Timer würde alle neun Sekunden eine DOM-Änderung über die
   SignalR-Verbindung schicken, pro Besucher, dauerhaft. Für eine reine
   Deko-Schleife ist das verschwendete Serverlast. Schlimmer noch: die Schau
   liefe erst los, wenn der Circuit steht — also ausgerechnet nicht in den
   ersten Sekunden, in denen der Hero angesehen wird. CSS läuft ab dem ersten
   Frame und kostet nichts.

   Takt: acht Bilder, je 9 s sichtbar, 1,5 s Überblendung, 72 s Gesamtumlauf.
   Kommt ein Bild dazu oder fällt eins weg, ändern sich der Umlauf (Anzahl
   mal 9 s), die Versätze und die Prozentwerte in beiden @keyframes. Dort
   stehen 1,5 s, 9 s und 10,5 s jeweils als Anteil am Umlauf:
   1,5/72 = 2,083 %, 9/72 = 12,5 %, 10,5/72 = 14,583 %.
   Versatz von Kachel n: (n − 1) × 9 s − 1,5 s.
*/
.hero {
  --hero-takt: 72s;
}

/*
   Gestapelt statt gekreuzt. Blendete jede Kachel aus, während die nächste
   einblendet, lägen kurzzeitig zwei halbtransparente Ebenen übereinander –
   und in der Mitte der Überblendung schimmerte rund ein Viertel des dunklen
   Untergrunds durch. Das ergibt einen sichtbaren Helligkeitseinbruch.

   Stattdessen liegt jede Kachel ÜBER der vorherigen und blendet nur ein; die
   darunter bleibt deckend, bis sie vollständig verdeckt ist, und springt erst
   dann auf null – unsichtbar, weil sie da niemand mehr sieht. Kachel 1 liegt
   dauerhaft zuunterst und wird nie ausgeblendet, deshalb kann die letzte
   Kachel am Zyklusende sauber auf sie zurückblenden.
*/
.hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
}
.hero__slide:nth-child(1) { opacity: 1; }
.hero__slide:nth-child(n + 2) {
  animation: heroEin var(--hero-takt) linear infinite;
}
.hero__slide:last-child {
  animation-name: heroEinAus;
}
.hero__slide:nth-child(2) { animation-delay: 7.5s; }
.hero__slide:nth-child(3) { animation-delay: 16.5s; }
.hero__slide:nth-child(4) { animation-delay: 25.5s; }
.hero__slide:nth-child(5) { animation-delay: 34.5s; }
.hero__slide:nth-child(6) { animation-delay: 43.5s; }
.hero__slide:nth-child(7) { animation-delay: 52.5s; }
.hero__slide:nth-child(8) { animation-delay: 61.5s; }

/*
   Dieselbe Korrektur wie bei .frame: Bild.razor gibt ein <picture> aus, und
   height:100% am <img> hätte sonst keinen Bezug, an dem es sich ausrichtet.
*/
.hero__slide picture {
  position: absolute;
  inset: 0;
}
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Mittlere Kacheln: 1,5 s einblenden, bis 10,5 s halten, verdeckt auf null springen. */
@keyframes heroEin {
  0%      { opacity: 0; }
  2.083%  { opacity: 1; }
  14.583% { opacity: 1; }
  14.584% { opacity: 0; }
  100%    { opacity: 0; }
}
/* Die letzte Kachel liegt zuoberst, sie muss zurück auf Kachel 1 blenden statt zu springen. */
@keyframes heroEinAus {
  0%      { opacity: 0; }
  2.083%  { opacity: 1; }
  12.5%   { opacity: 1; }
  14.583% { opacity: 0; }
  100%    { opacity: 0; }
}

/*
   Hochformat (Handy, Tablet hochkant): nur die fünf warmen Bilder, jeweils in
   eigener Hochformat-Fassung (Bild.razor, Parameter Hoch). Die drei älteren gibt
   es nur quer; dort zeigte das Handy ein Viertel des Bildes, dreifach vergrößert.

   Fünf Kacheln → 45 s Umlauf: 1,5/45 = 3,333 %, 9/45 = 20 %, 10,5/45 = 23,333 %.
   Die Versätze der Kacheln 2 bis 5 bleiben dieselben wie oben. Steht vor dem
   Block für reduzierte Bewegung, damit der weiterhin gewinnt.
*/
@media (orientation: portrait) {
  .hero { --hero-takt: 45s; }
  .hero__slide--nur-quer { display: none; }
  .hero__slide:nth-child(n + 2) { animation-name: heroEinKurz; }
  .hero__slide:nth-child(5) { animation-name: heroEinAusKurz; }
}
@keyframes heroEinKurz {
  0%      { opacity: 0; }
  3.333%  { opacity: 1; }
  23.333% { opacity: 1; }
  23.334% { opacity: 0; }
  100%    { opacity: 0; }
}
@keyframes heroEinAusKurz {
  0%      { opacity: 0; }
  3.333%  { opacity: 1; }
  20%     { opacity: 1; }
  23.333% { opacity: 0; }
  100%    { opacity: 0; }
}

/*
   Wer Bewegung reduziert haben will, bekommt ein stehendes Bild: Kachel 1
   bleibt sichtbar, alles andere steht still.
*/
@media (prefers-reduced-motion: reduce) {
  /* Doppelte Klasse: muss stärker sein als .hero__slide:nth-child(n + 2) oben,
     sonst liefe die Schau trotzdem. */
  .hero__media .hero__slide { animation: none; }
  .hero__media { animation: none; transform: none; }
}
/*
   Warm getönt und in der Mitte deutlich heller als früher (0,45 → 0,25), damit
   die sonnigen Motive warm bleiben statt grau zu wirken. Die Abdunklung, die
   der Text braucht, sitzt stattdessen im ovalen Schatten hinter dem Claim
   (.hero__claim::before). Oben bleibt es dunkel wie zuvor – dort liegt die
   Kopfzeile.

   Gemessen an den Bildpunkten aller acht Bilder, neun Fenstergrößen vom
   Handy bis Full HD, jede Textzeile einzeln: alle 456 Fälle bestehen die
   WCAG (4,5:1 für kleine, 3:1 für große Schrift), der knappste liegt bei
   4,81:1 (Ortszeile auf dem Handy). Wer hier heller dreht oder ein helleres
   Bild dazunimmt, muss neu messen.
*/
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg,
    rgba(24, 18, 12, 0.82) 0%,
    rgba(24, 18, 12, 0.68) 14%,
    rgba(24, 18, 12, 0.25) 42%,
    rgba(24, 18, 12, 0.85) 100%);
}
.hero__logo {
  /*
     Obergrenze 400px, die Datei hat aber nur 512px. Auf Bildschirmen mit
     doppelter Pixeldichte (MacBook, viele Tablets) braucht das Logo dort
     800 Gerätepixel und wird rund 1,5-fach hochgerechnet – die Sprenkel
     werden dann etwas weicher. Für volle Schärfe bräuchte es eine Fassung
     mit mindestens 800px.

     Das Logo bekommt, was in der Höhe übrig bleibt. Am PC brauchen Ortszeile,
     Spruch (eine Zeile), Text (zwei Zeilen), Buttons und Belege zusammen
     gemessen rund 345px, dazu Kopfzeile und Innenabstand (rund 7svh). Auf dem
     Handy sind es durch mehr Zeilen und die untereinanderstehenden Buttons
     rund 425px – dafür begrenzt dort die Breite früher, siehe unten.
  */
  width: clamp(160px, min(30vw, calc(93vh - var(--kopf-hoehe) - 360px)), 440px);
  width: clamp(160px, min(30vw, calc(93svh - var(--kopf-hoehe) - 360px)), 440px);
  height: auto;
  /* img ist per Reset ein Block-Element - text-align zentriert es nicht. */
  margin: 0 auto clamp(14px, 1.8vw, 24px);
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.55))
          drop-shadow(0 2px 10px rgba(0, 0, 0, 0.4));
}
/* Handy: 30 % der Breite wären nur gut 110px. Hier zählt die Höhe mit dem
   größeren Bedarf des Textblocks. */
@media (max-width: 699px) {
  .hero__logo {
    width: clamp(150px, min(55vw, calc(93vh - var(--kopf-hoehe) - 450px)), 240px);
    width: clamp(150px, min(55vw, calc(93svh - var(--kopf-hoehe) - 450px)), 240px);
  }
}

/*
   Enge Radien statt eines weiten Halos. Der vorherige 30-px-Schatten war auf
   dem dunklen Einzelbild unsichtbar, zeichnet auf den hellen Motiven der
   Diaschau aber ein sichtbares graues Rechteck um den Claim. 3 und 10 px
   folgen den Buchstaben, statt eine Fläche zu legen – und tragen trotzdem,
   weil das hellste Motiv im Textband bei 167 von 255 liegt und nicht bei 255.
*/
.hero__title {
  /* Kleiner als .h1, damit das Logo die Hauptrolle hat. .h1 nutzt nur dieser Titel. */
  font-size: clamp(30px, 4.6vw, 56px);
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.6),
    0 2px 10px rgba(0, 0, 0, 0.45);
}

/*
   Ortszeile ganz oben im Claim, über dem Logo – zugleich die H1 der Startseite
   (siehe Home.razor). Bewusst klein: Optisch tragen Logo und Slogan.
*/
.hero__kicker {
  display: block;
  margin-bottom: clamp(12px, 1.6vw, 20px);
  font-size: clamp(15px, 1.25vw, 18px);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0;
  hyphens: manual;
  color: var(--fg-2);
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.6),
    0 2px 10px rgba(0, 0, 0, 0.45);
}

/*
   Weicher ovaler Schatten hinter dem ganzen Textblock. Seit der Hero Ortszeile,
   Text und Buttons trägt und das Logo auf flachen Bildschirmen kleiner wird,
   rutscht der Text in die Bildmitte – genau dorthin, wo der Hero-Verlauf am
   schwächsten ist und die Fensterfront ihren hellen Himmel hat. Gemessen kam
   die kleine Ortszeile dort auf 2,4:1, die WCAG verlangt 4,5:1; nötig waren bis
   zu 0,37 zusätzliche Abdunklung.

   Bewusst nur hinter dem Text und nicht über das ganze Bild: so bleiben die
   Ränder des Bildes hell. Bis 62 % des Ovals voll, danach weicher Auslauf,
   damit keine Kante sichtbar wird. Liegt mit z-index -1 über dem Hero-Verlauf
   (der im Dokument vorher kommt) und unter dem Inhalt.
*/
.hero__claim { position: relative; }
.hero__claim::before {
  content: "";
  position: absolute;
  inset: -15% -30%;
  z-index: -1;
  pointer-events: none;
  /* Warm getönt wie der Hero-Verlauf; 0,6 statt 0,5, seit der Verlauf in der
     Mitte heller ist (siehe .hero__scrim). */
  background: radial-gradient(closest-side,
    rgba(20, 15, 10, 0.6) 0%,
    rgba(20, 15, 10, 0.6) 62%,
    rgba(20, 15, 10, 0) 100%);
}
/*
   Hochformat: Die Ortszeile steht ganz oben im Claim, über dem Logo – genau dort,
   wo die Hochformat-Bilder ihr helles Fenster haben, und am Rand des Ovals. Mit
   15 % fiel sie auf 3,86:1; mit 30 % liegt der schlechteste Fall bei 5,09:1
   (gemessen an allen fünf Hochformat-Bildern, Handys von 360 × 640 bis 390 × 844).
*/
@media (orientation: portrait) {
  .hero__claim::before { inset: -30% -30%; }
}

/* Nur für Screenreader: sorgt für eine Pause zwischen Ortszeile und Spruch. */
.nur-vorlesen {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/*
   Text, Belege und Buttons liegen auf dem Bild. fg-2 statt der gedämpften
   Grautöne, die auf dem dunklen Hintergrund darunter genügten, und derselbe
   enge Schatten wie beim Titel.
*/
.hero__text,
.hero__belege {
  color: var(--fg-2);
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.6),
    0 2px 10px rgba(0, 0, 0, 0.45);
}
.hero__text {
  /* Breit genug für zwei Zeilen am PC – jede Zeile weniger ist Platz fürs Logo. */
  max-width: 62ch;
  margin: clamp(14px, 1.6vw, 22px) auto 0;
  font-size: var(--fs-lead);
  line-height: 1.55;
  text-wrap: pretty;
}
.hero__aktionen {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: clamp(20px, 2.2vw, 30px);
}
.hero__belege {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 22px;
  margin-top: clamp(14px, 1.4vw, 18px);
  font-size: 13px;
}

/*
   Der Rahmen-Button ist für dunklen Grund gemacht – auf dem Bild wäre sein
   dunkelgrauer Rand kaum zu sehen. Ein halbdurchsichtiger Untergrund mit
   hellerem Rand hält ihn auf hellen wie dunklen Motiven lesbar.
*/
.hero .btn--ghost {
  background: rgba(18, 15, 12, 0.4);
  border-color: rgba(242, 236, 227, 0.4);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.hero .btn--ghost:hover { border-color: var(--fg); }

/* ---------- Kennzahlen ---------- */
.stat__value {
  font-size: var(--fs-stat);
  line-height: 1;
}
.stat__label { font-size: 13px; margin-top: 6px; }

/* ---------- Karten ---------- */
.card {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: clamp(20px, 2.2vw, 26px);
  background: var(--card);
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease),
    transform 0.25s var(--ease);
}
.card--link:hover,
a.card:hover {
  border-color: var(--fg);
  background: var(--card-hover);
  transform: translateY(-3px);
}
/*
  Ganze Karte klickbar. Kein <a> um die Karte – darin liegen Buttons, und
  interaktive Elemente dürfen nicht ineinander verschachtelt werden. Stattdessen
  legt sich das ::after des vorhandenen Links unsichtbar über die Karte. Der Link
  bleibt ein echter Link: Tastaturfokus, Mittelklick und Kontextmenü funktionieren.
  Die Karussell-Bedienelemente liegen mit z-index 2 darüber und bleiben bedienbar.
*/
.card--klickbar { position: relative; }
.card--klickbar .link-more::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.card__title { font-size: var(--fs-h3); font-weight: 600; margin-bottom: 9px; }
.card__text { font-size: 14px; line-height: 1.55; color: var(--dim); }

/* Bildrahmen mit fixem Seitenverhältnis */
.frame {
  position: relative;
  overflow: hidden;
  border-radius: 9px;
  background: var(--surface);
}
/*
  <picture> braucht die Höhe explizit: Bild.razor liefert <picture><img>, und
  "height:100%" am img bezieht sich auf das picture. Ohne diese Regel fällt das
  picture auf das Eigenformat des Bildes zurück und der Rahmen bleibt unten leer.
*/
.frame picture { position: absolute; inset: 0; }
.frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease);
}
.card--link:hover .frame img,
a.card:hover .frame img { transform: scale(1.05); }
.frame--4x3 { aspect-ratio: 4 / 3; }
.frame--16x9 { aspect-ratio: 16 / 9; }
.frame--3x2 { aspect-ratio: 3 / 2; }

/* Icon-Kachel der Leistungskarten */
.tile {
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
  background: var(--fg);
  margin-bottom: 20px;
  display: grid;
  place-items: center;
  color: var(--bg);
}
.tile svg { width: 20px; height: 20px; }
.tile--alt { background: var(--dim); }

/* Chips / Tags */
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; }

.badge {
  font-size: 12px;
  background: var(--fg);
  color: var(--bg);
  padding: 5px 10px;
  border-radius: 999px;
  white-space: nowrap;
}

/* Auswählbarer Filter-/Auswahl-Chip */
.toggle-chip {
  font-size: 13px;
  border: 1px solid var(--line-2);
  background: var(--card);
  color: var(--muted);
  padding: 9px 15px;
  border-radius: 999px;
  cursor: pointer;
  user-select: none;
  transition: all 0.2s var(--ease);
}
.toggle-chip:hover { border-color: var(--dim); color: var(--fg); }
.toggle-chip[aria-pressed='true'] {
  background: var(--fg);
  border-color: var(--fg);
  color: var(--bg);
}

/*
  ---------- Kopfbild für Unterseiten ----------
  Gleiche Technik wie der Hero: Bild absolut hinter dem Inhalt, darüber ein Verlauf.
  Der Schleier ist dichter als hero__scrim – über dem Hero steht nur eine Headline,
  über diesen Köpfen stehen Fließtext und Kennzahlen.
*/
.section--kopfbild { position: relative; overflow: hidden; isolation: isolate; }
.kopfbild__media { position: absolute; inset: 0; z-index: -2; }
.kopfbild__media picture { position: absolute; inset: 0; }
.kopfbild__media img { width: 100%; height: 100%; object-fit: cover; }
/*
   Warm und heller als früher (Mitte 0,6 statt 0,74), damit die sonnigen Fotos
   durchscheinen. Der zweite Verlauf dunkelt nur links nach, wo der Text steht,
   und läuft nach rechts aus. Dafür steht der Einleitungstext in fg-2 statt im
   gedämpften Grau (siehe unten).

   Gemessen an den Bildpunkten aller vier Kopfbilder bei sieben Fenstergrößen vom
   Handy bis Full HD, jede Textzeile einzeln: alle 112 Fälle bestehen die WCAG,
   der knappste liegt bei 5,02:1 (Bewertungsseite auf dem Handy). Wer hier heller
   dreht oder ein anderes Bild einsetzt, muss neu messen.
*/
.kopfbild__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(90deg,
      rgba(18, 15, 12, 0.4) 0%,
      rgba(18, 15, 12, 0.2) 60%,
      rgba(18, 15, 12, 0) 100%),
    linear-gradient(180deg,
      rgba(18, 15, 12, 0.8) 0%,
      rgba(18, 15, 12, 0.6) 50%,
      rgba(18, 15, 12, 0.85) 100%);
}
.section--kopfbild .lead {
  color: var(--fg-2);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

/* ---------- Bildwechsler auf den Leistungsseiten ---------- */
.wechsler__bild {
  position: absolute;
  inset: 0;
  animation: bildEin 0.45s var(--ease);
}
.wechsler__bild picture { position: absolute; inset: 0; }
.wechsler__bild img { width: 100%; height: 100%; object-fit: cover; }

@keyframes bildEin {
  from { opacity: 0; transform: scale(1.03); }
  to   { opacity: 1; transform: none; }
}

.wechsler__leiste { display: flex; gap: 10px; margin-top: 10px; }

.wechsler__daumen {
  flex: 1 1 0;
  min-width: 0;
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  cursor: pointer;
  transition: border-color 0.25s var(--ease);
}
.wechsler__daumen picture { position: absolute; inset: 0; }
.wechsler__daumen img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.5;
  transition: opacity 0.25s var(--ease);
}
.wechsler__daumen:hover img { opacity: 0.82; }
.wechsler__daumen.is-aktiv { border-color: var(--fg); }
.wechsler__daumen.is-aktiv img { opacity: 1; }

/*
  ---------- Karussell in den Leistungskarten ----------
  Pfeile und Punkte statt einer Miniaturleiste: sechs Karten mit je vier Miniaturen
  wären 24 zusätzliche Bilder beim Seitenaufbau. So lädt nur das sichtbare Bild.
*/
.karussell::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 46%;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(14, 12, 10, 0) 0%, rgba(14, 12, 10, 0.58) 100%);
}

.karussell__pfeil {
  position: absolute;
  top: 50%;
  z-index: 2;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(242, 236, 227, 0.25);
  border-radius: 50%;
  background: rgba(18, 15, 12, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  padding: 0;
  color: var(--fg);
  cursor: pointer;
  opacity: 0;
  transform: translateY(-50%);
  transition: opacity 0.2s var(--ease), background-color 0.2s var(--ease),
    border-color 0.2s var(--ease);
}
.karussell__pfeil svg {
  display: block;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.karussell__pfeil--zurueck { left: 10px; }
.karussell__pfeil--vor { right: 10px; }
.karussell:hover .karussell__pfeil,
.karussell__pfeil:focus-visible { opacity: 1; }
.karussell__pfeil:hover { background: rgba(18, 15, 12, 0.82); border-color: var(--fg); }

/* Ohne Hover (Touch) sind die Pfeile dauerhaft sichtbar. */
@media (hover: none) {
  .karussell__pfeil { opacity: 1; }
}

.karussell__punkte {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 6px;
  display: flex;
  justify-content: center;
  gap: 2px;
}
.karussell__punkt {
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.karussell__punkt::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(242, 236, 227, 0.42);
  transition: background-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.karussell__punkt:hover::before { background: rgba(242, 236, 227, 0.78); }
.karussell__punkt.is-aktiv::before { background: var(--fg); transform: scale(1.35); }

/* ---------- Portfolio-Kacheln (Bild, Schleier, Titel) ---------- */
.portfolio {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 900px) { .portfolio { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .portfolio { grid-template-columns: minmax(0, 1fr); } }

.portfolio__card {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.portfolio__card picture { position: absolute; inset: 0; }
.portfolio__card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease);
}

/*
  Statt einer Akzentfarbe ein dunkler Schleier: die Palette kennt nur Schwarz und
  Papierweiß. Der Verlauf nach unten hält den Titel lesbar, die Grundfläche darunter
  zieht alle Bilder auf eine gemeinsame Tonalität – auch die helleren.
*/
.portfolio__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg,
      rgba(14, 12, 10, 0.34) 0%,
      rgba(14, 12, 10, 0.60) 52%,
      rgba(14, 12, 10, 0.93) 100%),
    rgba(18, 15, 12, 0.40);
  transition: opacity 0.25s var(--ease);
}
.portfolio__title {
  position: absolute;
  left: clamp(16px, 1.8vw, 22px);
  right: clamp(16px, 1.8vw, 22px);
  bottom: clamp(14px, 1.6vw, 20px);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.3;
  color: var(--fg);
}

.portfolio__card:hover { border-color: var(--fg); transform: translateY(-3px); }
.portfolio__card:hover img { transform: scale(1.05); }
.portfolio__card:hover .portfolio__scrim { opacity: 0.72; }

/* ---------- Kennzahlen ---------- */
/* Auch auf dem Handy zwei nebeneinander – untereinander füllten die vier Zahlen
   allein einen halben Bildschirm. */
.kennzahlen { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* Mit Google-Note drei Werte, ohne zwei. */
.kennzahlen:not(:has(> :nth-child(4))) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.kennzahlen:not(:has(> :nth-child(3))) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 759px) {
  .kennzahlen,
  .kennzahlen:not(:has(> :nth-child(4))) { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 20px; }
  .kennzahlen > :nth-child(3):last-child { grid-column: 1 / -1; }
}
/* Die Google-Note führt zur Bewertungsseite. */
.stat--link { display: block; }
.stat--link:hover .stat__label { text-decoration: underline; text-underline-offset: 2px; }

/* ---------- Leistungskarten (kompakt) ---------- */
/*
   Vier Spalten ab 700px, darunter zwei. Vorher waren es zwei Spalten mit je rund 700px
   hohen Karten: Die acht Leistungen brauchten am PC 3.000px, auf dem Handy 4.900px.
   Drei Spalten wären auf Tablets naheliegend, lassen bei acht Leistungen aber in der
   letzten Reihe eine Lücke – acht geht nur in zwei oder vier glatt auf.
*/
.leistungen-raster {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 699px) {
  .leistungen-raster { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
}

/*
   Bild randlos oben, Text darunter. overflow:hidden rundet die oberen Bildecken mit ab.
   container-type macht die Karte zum Bezug für die @container-Regel weiter unten:
   Ob der Kurztext Platz hat, hängt an der Breite der Karte, nicht des Bildschirms.
*/
.leistung {
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  container-type: inline-size;
}
.leistung .karussell { border-radius: 0; }
.leistung__abzeichen {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  font-size: 11px;
  padding: 4px 9px;
}
.leistung__inhalt {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: clamp(12px, 1.4vw, 18px);
}
.leistung__titel {
  font-size: clamp(16px, 1.4vw, 20px);
  line-height: 1.2;
  margin-bottom: 6px;
}
.leistung__text {
  font-size: 14px;
  line-height: 1.5;
  color: var(--dim);
  margin-bottom: 12px;
}
/* margin-top:auto schiebt den Link nach unten – die Links einer Reihe fluchten. */
.leistung .link-more { margin-top: auto; font-size: 13px; }

/*
   Schmale Karten (Handy, Tablet hochkant): Bild und Titel genügen, die ganze Karte ist
   ohnehin anklickbar. Der Kurztext stünde bei rund 160px Kartenbreite in sechs, sieben
   Zeilen. Ab etwa 210px – kleine Laptops aufwärts – hat er Platz.
*/
/* Kleinste Handys: „Details ansehen →" lief bei 320px um 4px aus der Karte. */
@container (max-width: 150px) {
  .leistung .link-more { font-size: 12px; }
}
@container (max-width: 210px) {
  .leistung__text { display: none; }
  .leistung__titel { margin-bottom: 8px; }
  .leistung .karussell__pfeil { width: 28px; height: 28px; }
  .leistung .karussell__pfeil svg { width: 15px; height: 15px; }
  .leistung .karussell__pfeil--zurueck { left: 6px; }
  .leistung .karussell__pfeil--vor { right: 6px; }
}
/* Handy: keine Pfeile auf den Leistungsbildern – sie verdeckten auf den kleinen Karten
   das halbe Motiv. Blättern geht weiter über die Punkte unten im Bild. */
@media (max-width: 699px) {
  .leistung .karussell__pfeil { display: none; }
}

/* ---------- Qualitätsschritte ---------- */
.schritte {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.step { border-top: 2px solid var(--line); padding-top: 16px; }
.step--first { border-top-color: var(--fg); }
.step__bild {
  aspect-ratio: 16 / 9;
  margin-bottom: 14px;
  border-radius: var(--r-md);
}
/*
   Handy: Bild klein links, Text rechts. Untereinander mit Bild über voller Breite
   brauchten die drei Schritte 1.400px.
*/
@media (max-width: 759px) {
  .schritte { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .step {
    display: grid;
    grid-template-columns: 108px minmax(0, 1fr);
    gap: 14px;
    align-items: start;
    padding-top: 14px;
  }
  .step__bild { aspect-ratio: 4 / 3; margin-bottom: 0; }
}
.step__no {
  font-size: 30px;
  line-height: 1;
  color: var(--fg);
}
.step h3 { font-size: 17px; font-weight: 600; margin: 8px 0 6px; }
@media (max-width: 759px) {
  .step__no { font-size: 20px; }
  .step h3 { font-size: 16px; margin: 4px 0 4px; }
}

/* ---------- Wischbare Reihe (Handy) ---------- */
/*
   Unter 760px werden Kartenraster damit zu einer waagerecht wischbaren Reihe: eine
   Karte zu 85 % sichtbar, die nächste lugt hervor und zeigt, dass es weitergeht.
   Die Reihe reicht bis an den Bildschirmrand, der Inhalt beginnt trotzdem bündig.
*/
@media (max-width: 759px) {
  .wischreihe {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    margin-inline: calc(-1 * var(--gutter));
    padding-inline: var(--gutter);
    scroll-padding-inline: var(--gutter);
    padding-bottom: 6px;
    scrollbar-width: none;
  }
  .wischreihe::-webkit-scrollbar { display: none; }
  .wischreihe > * { flex: 0 0 85%; scroll-snap-align: start; }
}

/* ---------- Bewertungen (aus dem Google-Profil, ohne Profilbilder) ---------- */
.stars { color: var(--fg); font-size: 15px; letter-spacing: 2px; }
.stars .off { color: var(--line-2); }

/*
   „Google Maps" als Quellenangabe – so, wie Google es für Text vorschreibt:
   normale Schrift (400), 12 bis 16px, kein Umbruch, keine geänderte Schreibweise,
   Farbe Weiß auf dunklem bzw. #1F1F1F auf hellem Grund.
*/
.gm-quelle {
  /* Schriftgröße erbt – überall, wo die Klasse steht, sind es 12 bis 13px. */
  font-weight: 400;
  letter-spacing: normal;
  white-space: nowrap;
  color: #fff;
}
.band .gm-quelle { color: #1f1f1f; }
/* Sonst gewänne .header-rating span (gedämpftes Grau). */
.header-rating .gm-quelle { color: #fff; }

/* Spalte, damit die Fußzeilen nebeneinanderstehender Karten auf einer Höhe liegen. */
.review { display: flex; flex-direction: column; }
.review__kopf {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  margin-bottom: 16px;
}
.review__zeit { font-size: 12px; color: var(--dim); }
/* pre-line: Absätze aus Google bleiben erhalten. */
.review__text {
  font-size: 15px;
  line-height: 1.65;
  color: var(--fg-2);
  white-space: pre-line;
  overflow-wrap: break-word;
  margin-bottom: 20px;
}
/* Auf der Startseite gekürzt – der volle Text steht hinter „Ansehen". */
.review__text--kurz {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 6;
  line-clamp: 6;
  overflow: hidden;
}
.review__foot {
  display: flex;
  align-items: center;
  gap: 12px;
  border-top: 1px solid var(--line);
  padding-top: 16px;
  margin-top: auto;
}
.review__autor {
  display: flex;
  flex-direction: column;
  min-width: 0;
  font-size: 14px;
  line-height: 1.4;
}
.review__autor a { color: var(--fg); overflow-wrap: anywhere; }
.review__autor a:hover { text-decoration: underline; text-underline-offset: 2px; }
.review__auf { font-size: 12px; color: var(--dim); }
.review__quelle {
  margin-left: auto;
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}
.review__quelle:hover { color: var(--fg); }

/*
   ---------- Bewertungs-Laufband (Startseite) ----------
   Drei gleiche Reihen hintereinander, die Spur wandert um ein Drittel = genau eine Reihe,
   dann beginnt sie von vorn – ohne sichtbaren Sprung. Abstand per margin statt gap, damit
   jede Reihe ihren Abstand am Ende mitbringt und das Drittel exakt stimmt.
   Tempo: rund 13 s je Karte (--band-dauer kommt aus Home.razor).
*/
.bewertungs-band {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 48px, #000 calc(100% - 48px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 48px, #000 calc(100% - 48px), transparent 100%);
}
.bewertungs-band__spur {
  display: flex;
  width: max-content;
  animation: bewertungen-laufen var(--band-dauer, 65s) linear infinite;
}
.bewertungs-band__reihe { display: flex; }
.bewertungs-band__reihe > .review {
  flex: 0 0 clamp(272px, 78vw, 360px);
  margin-right: var(--gap);
}
/* Die Einblendung beim Scrollen passt nicht zu Karten, die ohnehin durchs Bild laufen. */
.bewertungs-band .reveal { opacity: 1; transform: none; }
.bewertungs-band:hover .bewertungs-band__spur,
.bewertungs-band:focus-within .bewertungs-band__spur,
.bewertungs-band.ist-angehalten .bewertungs-band__spur { animation-play-state: paused; }
@keyframes bewertungen-laufen { to { transform: translateX(-33.3333%); } }

.bewertungs-band__fuss {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 20px;
}
.bewertungs-band__knopf {
  margin-top: 18px;
  padding: 6px 0;
  border: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
}
.bewertungs-band__knopf:hover { color: var(--fg); }

/* Bewegung reduziert: Band steht, lässt sich wischen; Kopien und Knopf entfallen. */
@media (prefers-reduced-motion: reduce) {
  .bewertungs-band { overflow-x: auto; -webkit-mask-image: none; mask-image: none; scroll-snap-type: x mandatory; }
  .bewertungs-band__spur { animation: none; }
  .bewertungs-band__reihe[aria-hidden="true"] { display: none; }
  .bewertungs-band__reihe > .review { scroll-snap-align: start; }
  .bewertungs-band__knopf { display: none; }
}

/* ---------- Partner-Logos (Startseite) ---------- */
.partner-logos { display: flex; flex-wrap: wrap; gap: var(--gap); }
.partner-logos__kachel {
  flex: 0 1 260px;
  display: grid;
  place-items: center;
  padding: clamp(14px, 2vw, 24px) clamp(18px, 2.6vw, 32px);
  background: #fff;
  border-radius: var(--r-md);
  transition: transform 0.25s var(--ease);
}
.partner-logos__kachel:hover { transform: translateY(-2px); }
.partner-logos__kachel img { width: 100%; max-width: 220px; height: auto; }
/* Handy: zwei Kacheln je Reihe – mit drei und mehr Partnern nebeneinander wären die
   Logos nur noch gut 70px breit. */
@media (max-width: 620px) {
  .partner-logos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .partner-logos__kachel { min-width: 0; }
}

/* ---------- Referenzen: je Partner eine Karte ---------- */
/*
   Hintergrund wie auf allen Seiten: Kopfbild oben, darunter der normale dunkle
   Seitenhintergrund. Je Partner ein Abschnitt mit EINER Karte, in der Firma und
   Bewertung zusammenstehen; jede Karte passt in eine Bildschirmhöhe.

   Abstände und Schriftgrößen in der Karte richten sich nach Breite UND Höhe
   (min(vw, svh)). Gemessen bei vielen Größen vom kleinsten iPhone (320 × 568) und
   Handys im Querformat bis Full HD. Wer Inhalt dazunimmt, muss neu messen.

   Kein scroll-snap mehr: Das Einrasten zog die Seite auf dem Handy immer wieder
   auf die Karte, an den Seitenanfang kam man nicht mehr.
*/
/* Zwei Karten je Reihe ab 900px, darunter eine. Karten einer Reihe sind gleich hoch;
   Fuß und Hinweis sitzen dabei unten (die Stimme wächst, siehe .partner-karte__stimme). */
.partner-raster {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
  align-items: stretch;
}
@media (max-width: 899px) {
  .partner-raster { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Die Karte: Firma oben, Bewertung darunter, Verfasser unten ---- */
.partner-karte {
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* Wie alle Karten der Seite (.card): Rahmen und Fläche aus den Grundfarben. */
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--card);
  overflow: hidden;
  /* Sprung von der Startseite (/referenzen#…): nicht unter der festen Kopfzeile landen. */
  scroll-margin-top: calc(var(--kopf-hoehe) + 20px);
}
/* Karte ohne Bewertung (nur Kopf) neben einer mit Bewertung: nicht künstlich strecken. */
.partner-karte:has(> .partner-karte__kopf:only-child) { align-self: start; }

.partner-karte__kopf {
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.8vw, 22px);
  padding: clamp(12px, min(2vw, 2.6svh), 24px) clamp(14px, min(2.6vw, 3.4svh), 36px);
  border-bottom: 1px solid var(--line);
  background: var(--card-hover);
}
/* Karte ohne Bewertung: nur der Kopf – keine Trennlinie über dem Kartenrand. */
.partner-karte__kopf:last-child { border-bottom: 0; }
/* Logos sind meist dunkel auf Weiß – sie bekommen eine eigene helle Fläche. */
.partner-karte__logo {
  flex: none;
  display: block;
  width: clamp(104px, min(16vw, 22svh), 210px);
  padding: clamp(7px, 1.2svh, 12px) clamp(9px, 1.4svh, 16px);
  background: #fff;
  border-radius: var(--r-md);
  transition: transform 0.25s var(--ease);
}
.partner-karte__logo:hover { transform: translateY(-2px); }
.partner-karte__logo img { width: 100%; height: auto; }
.partner-karte__firma { min-width: 0; flex: 1; }
.partner-karte__name { font-size: clamp(15px, min(1.6vw, 2.4svh), 20px); font-weight: 600; line-height: 1.3; }
.partner-karte__fakten { font-size: clamp(12px, min(1.15vw, 1.8svh), 14px); color: var(--fg-2); margin: 2px 0 3px; }
.partner-karte__link {
  display: inline-block;
  padding-block: 3px;
  font-size: clamp(12px, min(1.1vw, 1.8svh), 14px);
  color: var(--fg);
  border-bottom: 1px solid rgba(242, 236, 227, 0.4);
}
.partner-karte__link:hover { border-bottom-color: var(--fg); }
.partner-karte__nr { flex: none; align-self: flex-start; font-size: 12px; color: var(--dim); }
/* Sehr schmal: Die Nummer nähme dem Firmennamen eine Zeile weg. */
@media (max-width: 380px) {
  .partner-karte__nr { display: none; }
}

/*
   Partner ohne freigegebenes Logo: Kürzel auf der hellen Logofläche – genau so groß wie
   eine Logo-Kachel. Ein unsichtbarer Platzhalter im Seitenverhältnis der Logos (842:250)
   gibt die Höhe vor, das Kürzel liegt mittig darüber.
*/
.partner-karte__logo--kuerzel {
  display: grid;
  font-size: clamp(18px, 2.4vw, 26px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  color: #5b5248;
}
.partner-karte__logo--kuerzel::before { content: ""; grid-area: 1 / 1; aspect-ratio: 842 / 250; }
.partner-karte__logo--kuerzel > span { grid-area: 1 / 1; place-self: center; }

.partner-karte__stimme { flex: 1 0 auto; padding: clamp(14px, min(2.4vw, 3.2svh), 34px) clamp(14px, min(2.6vw, 3.4svh), 36px) 0; }
.partner-karte__sterne {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: clamp(8px, 1.6svh, 16px);
}
.partner-karte__zeichen {
  display: block;
  height: 0.42em;
  overflow: hidden;
  font-size: clamp(54px, min(6vw, 9svh), 92px);
  line-height: 1;
  font-weight: 700;
  color: var(--dim);
}
.partner-karte__sterne .stars { font-size: clamp(14px, 2svh, 18px); letter-spacing: 3px; }
.partner-karte__text {
  font-size: clamp(14px, min(1.55vw, 2.45svh), 23px);
  line-height: 1.5;
  font-weight: 500;
  color: var(--fg);
  white-space: pre-line;
  text-wrap: pretty;
}

.partner-karte__fuss {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 18px;
  padding: clamp(10px, 2svh, 22px) clamp(14px, min(2.6vw, 3.4svh), 36px) 0;
}
.partner-karte__person {
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-size: clamp(12px, min(1.1vw, 1.8svh), 14px);
  color: var(--muted);
}
.partner-karte__person a { color: var(--fg); font-weight: 600; font-size: 1.07em; }
.partner-karte__person a:hover { text-decoration: underline; text-underline-offset: 2px; }
/* Wunschname des Partners vorne, Googles Name klein darunter. */
.partner-karte__anzeigename { color: var(--fg); font-weight: 600; font-size: 1.07em; }
.partner-karte__google-name { font-size: 12px; color: var(--dim); }
.partner-karte__google-name a { color: var(--fg-2); font-weight: 400; font-size: inherit; text-decoration: underline; text-underline-offset: 2px; }
.partner-karte__aktionen { display: flex; flex-wrap: wrap; gap: 8px 10px; }
.partner-karte__hinweis {
  padding: clamp(8px, 1.5svh, 16px) clamp(14px, min(2.6vw, 3.4svh), 36px) clamp(12px, min(2vw, 2.6svh), 24px);
  font-size: 12px;
  line-height: 1.5;
  color: var(--dim);
}
.partner-karte__hinweis a { color: var(--fg-2); text-decoration: underline; text-underline-offset: 2px; }
/* Ohne Hinweis (keine Bewertung) braucht der Fuß selbst den unteren Abstand. */
.partner-karte__fuss:last-child { padding-bottom: clamp(12px, min(2vw, 2.6svh), 24px); }

/*
   Niedrige Fenster: kleine Handys hochkant (unter 760px Höhe) und alle Handys quer.
   Der Website-Link fällt weg (das Logo ist selbst der Link), kleinere Buttons,
   engere Abstände.
*/
@media (max-height: 760px) and (orientation: portrait), (max-height: 520px) {
  .partner-karte__link { display: none; }
}
/* Erst wenn es dann noch nicht reicht, wird das Zitat nach einigen Zeilen gekürzt –
   der volle Text steht hinter „Bei Google ansehen". */
@media (max-height: 520px) and (orientation: landscape) {
  .partner-karte__text {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
  }
}
/* Handys: Buttons kompakt in einer Reihe, bei sehr schmal oder flach mit kürzerem Text. */
@media (max-width: 440px) {
  .partner-karte__aktionen .btn { padding: 8px 12px; font-size: 13px; }
}
@media (max-width: 380px), (max-height: 520px) {
  .partner-karte__aktionen .btn { padding: 8px 11px; font-size: 13px; }
  .ref-lang { display: none; }
}

@media (max-height: 520px) and (orientation: landscape) {
  .partner-karte__kopf { padding-block: 8px; }
  .partner-karte__logo { width: 96px; padding: 6px 8px; }
  .partner-karte__stimme { padding-top: 10px; }
  .partner-karte__sterne { margin-bottom: 4px; }
  .partner-karte__fuss { padding-top: 8px; }
  .partner-karte__hinweis { padding-top: 6px; padding-bottom: 10px; }
}
/* Sehr niedrige Handy-Bildschirme (kleinste iPhones, Handys quer): schmalerer Rand,
   damit Karte samt Rand in eine Höhe passt. Laptops behalten den üblichen Abstand. */
@media (max-height: 600px) and (max-width: 940px) {
  .partner-abschnitt { padding-block: 20px; }
}
/*
   Zwei Spalten: Jede Karte ist nur halb so breit wie früher. Zitat, Anführungszeichen
   und Logo-Kachel würden sonst für die schmale Karte zu groß (gerechnet war mit 920px).
*/
@media (min-width: 900px) {
  .partner-karte__logo { width: clamp(110px, min(11vw, 20svh), 180px); }
  .partner-karte__text { font-size: clamp(15px, min(1.15vw, 2.2svh), 18px); }
  .partner-karte__zeichen { font-size: clamp(44px, min(4vw, 7svh), 64px); }
  .partner-karte__kopf,
  .partner-karte__stimme,
  .partner-karte__fuss,
  .partner-karte__hinweis { padding-inline: clamp(16px, 1.8vw, 28px); }
}
/* Steht bewusst am Ende des Abschnitts: muss die Grundregeln darüber überschreiben. */
/* Kleinste Handys quer (um 375px hoch): das dekorative Anführungszeichen weg, noch enger. */
@media (max-height: 400px) and (orientation: landscape) {
  .partner-karte__zeichen { display: none; }
  .partner-karte__text {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
  }
  .partner-karte__kopf { padding-block: 6px; }
}

/* Quelle und Sortierung unter den Karten – Google verlangt beides. */
.google-hinweis {
  margin-top: 18px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--dim);
}
.google-hinweis a {
  color: var(--fg-2);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Pflichthinweis zur Herkunft der Bewertungen (§ 5b Abs. 3 UWG), Bewertungsseite. */
.bewertungs-hinweis { max-width: 72ch; margin: 0; }
.bewertungs-hinweis h2 { font-size: 18px; margin: 0 0 10px; }
.bewertungs-hinweis p { font-size: 14px; line-height: 1.7; color: var(--muted); }
.bewertungs-hinweis p + p { margin-top: 10px; }
.bewertungs-hinweis a { color: var(--fg); text-decoration: underline; text-underline-offset: 2px; }

.rating-box {
  flex: none;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 26px 30px;
  background: var(--card);
  min-width: 240px;
}
.rating-box__score { display: flex; align-items: baseline; gap: 10px; }
.rating-box__score b {
  font-size: 52px;
  line-height: 1;
}
.rating-box__aktionen { display: flex; flex-direction: column; gap: 8px; }

/* ---------- Formulare ---------- */
.field { display: block; margin-bottom: 18px; }
.field__label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 7px; }
.input, .select, .textarea {
  width: 100%;
  border: 1px solid #3a332b;
  border-radius: var(--r-sm);
  padding: 14px;
  background: var(--surface);
  color: var(--fg);
  transition: border-color 0.2s var(--ease);
}
.input:hover, .select:hover, .textarea:hover { border-color: var(--line-3); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--fg);
}
.textarea { resize: vertical; min-height: 120px; }
.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23a5a29c' stroke-width='1.5'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 12px;
  padding-right: 38px;
}
.select option { background: var(--surface); color: var(--fg); }

.checkbox {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  cursor: pointer;
  font-size: 13px;
  line-height: 1.5;
  color: var(--dim);
}
.checkbox input { position: absolute; opacity: 0; width: 0; height: 0; }
.checkbox__box {
  width: 19px;
  height: 19px;
  flex: none;
  margin-top: 1px;
  border: 1px solid var(--line-3);
  border-radius: 4px;
  display: grid;
  place-items: center;
  color: var(--bg);
  transition: background-color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.checkbox input:checked + .checkbox__box { background: var(--fg); border-color: var(--fg); }
.checkbox input:checked + .checkbox__box::after { content: '✓'; font-size: 12px; line-height: 1; }
.checkbox input:focus-visible + .checkbox__box { outline: 2px solid var(--fg); outline-offset: 2px; }
.checkbox a { color: var(--fg); border-bottom: 1px solid var(--line-3); }

.dropzone {
  border: 1px dashed var(--line-3);
  border-radius: 10px;
  padding: 20px;
  text-align: center;
  transition: border-color 0.2s var(--ease);
}
.dropzone:hover { border-color: var(--dim); }

.progress { display: flex; gap: 10px; margin-bottom: 30px; }
.progress > i {
  flex: 1;
  height: 3px;
  background: var(--line);
  border-radius: 2px;
  transition: background-color 0.3s var(--ease);
}
.progress > i.on { background: var(--fg); }

.step-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--faint);
  margin-bottom: 18px;
}
/* Schritt-Überschrift im Anfrageformular: bekommt beim Schrittwechsel den Fokus (ohne
   Rahmen, sie ist kein Bedienelement) und bleibt dabei unter der festen Kopfzeile sichtbar. */
h2.step-label { line-height: 1.4; scroll-margin-top: 110px; }
.step-label:focus { outline: none; }

/* Schritt 2: Kurzfassung der Objektangaben mit „Ändern". */
.anfrage-zusammenfassung {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 16px;
  margin-bottom: 22px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg-2);
}
.anfrage-zusammenfassung button {
  padding: 4px 0;
  border: 0;
  background: none;
  color: var(--fg);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* Datenschutz-Hinweis über dem Senden-Knopf (statt Einwilligungs-Häkchen). */
.formular-hinweis { font-size: 13px; line-height: 1.6; color: var(--muted); max-width: 62ch; }
.formular-hinweis a { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; }

.error-text { color: #f2b8b8; font-size: 13px; margin-top: 6px; }
.input.invalid, .select.invalid { border-color: #7d4a4a; }

/* ---------- Preistabelle (Detailseite) ---------- */
.spec {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
.spec > div { background: var(--card); padding: 22px; }
/* h2 mitgestylt: im Impressum sind es echte Ueberschriften, kein <b>. */
.spec b, .spec h2 { display: block; font-size: 16px; font-weight: 600; margin-bottom: 8px; }
.spec p { font-size: 14px; line-height: 1.55; color: var(--dim); }

/* ---------- Langer Rechtstext (Datenschutzerklärung) ---------- */
/* 72 Zeichen je Zeile – darüber wird ein langer Text spürbar schwerer zu lesen. */
.rechtstext { max-width: 72ch; }
.rechtstext h2 {
  font-size: clamp(18px, 1.6vw, 21px);
  font-weight: 700;
  color: var(--fg);
  margin: clamp(30px, 3.5vw, 42px) 0 10px;
}
.rechtstext h3 {
  font-size: 16px;
  font-weight: 600;
  color: var(--fg);
  margin: 22px 0 6px;
}
.rechtstext p,
.rechtstext li { font-size: 15px; line-height: 1.7; color: var(--fg-2); }
.rechtstext p + p { margin-top: 10px; }
/* Der Reset nimmt Listen die Aufzählungszeichen – im Fließtext braucht es sie. */
.rechtstext ul { list-style: disc; padding-left: 22px; margin: 8px 0 10px; }
.rechtstext li + li { margin-top: 4px; }
.rechtstext a { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; }
.rechtstext strong { color: var(--fg); font-weight: 600; }

/* Kurzfassung oben und der Widerspruchshinweis, den Art. 21 Abs. 4 DSGVO gesondert
   hervorgehoben verlangt. */
.rechtstext__kurz,
.rechtstext__hinweis {
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  background: var(--card);
  padding: clamp(18px, 2.2vw, 24px);
}
.rechtstext__kurz h2 { margin-top: 0; }
.rechtstext__hinweis { margin: 22px 0; border-left: 3px solid var(--fg); }
.rechtstext__hinweis h3 { margin-top: 0; }

/* Tabelle wischt auf dem Handy seitlich, statt die Seite breiter zu machen. */
.rechtstext__tabelle { overflow-x: auto; margin: 12px 0; }
.rechtstext table { width: 100%; min-width: 520px; border-collapse: collapse; font-size: 14px; }
.rechtstext th,
.rechtstext td {
  text-align: left;
  vertical-align: top;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  color: var(--fg-2);
  line-height: 1.5;
}
.rechtstext th { color: var(--fg); font-weight: 600; }
.rechtstext code { color: var(--fg); word-break: break-word; }
.rechtstext__stand { margin-top: 32px; font-size: 13px; color: var(--faint); }
@media (max-width: 620px) { .spec { grid-template-columns: minmax(0, 1fr); } }

.priceline {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 16px 0;
  border-top: 1px solid var(--line);
  font-size: 15px;
}
.priceline:last-child { border-bottom: 1px solid var(--line); }

.facts { display: flex; flex-wrap: wrap; gap: 26px; }
.facts dt { font-size: 12px; color: var(--faint); margin-bottom: 4px; }
.facts dd { margin: 0; font-size: 15px; }

.sticky-card { position: sticky; top: 104px; }
@media (max-width: 900px) { .sticky-card { position: static; } }

.breadcrumb { font-size: 13px; color: var(--faint); margin-bottom: 20px; }
.breadcrumb a:hover { color: var(--fg); }

/* ---------- Fußzeile ---------- */
.site-footer {
  background: var(--bg);
  color: var(--dim);
  border-top: 1px solid var(--line);
  padding-block: var(--section-y);
}
.site-footer h4 { color: var(--fg); font-size: 13px; font-weight: 400; margin-bottom: 8px; }
.site-footer li a, .site-footer li { font-size: 13px; line-height: 2.1; }
.site-footer li a:hover { color: var(--fg); }
/* Auf 320px passten Logo und Name in 20px nicht in die Zeile. */
.footer-marke { font-size: clamp(17px, 5.4vw, 20px); }
/* Logo + Name als Ganzes so breit wie nötig: Chrome zählt bei einer Flex-Zeile sonst nur
   das breiteste Einzelteil als Mindestbreite – die Spalte blieb 34px zu schmal. */
.site-footer .brand { min-width: max-content; }
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  justify-content: space-between;
  border-top: 1px solid var(--line);
  padding-top: 18px;
  margin-top: clamp(24px, 3vw, 36px);
  font-size: 12px;
}
.footer-bottom nav { display: flex; gap: 18px; }

/* Button im Handy-Menü: .mobile-nav a färbte seine Schrift grau – auf hellem
   Grund kaum lesbar, wirkte deaktiviert. */
.mobile-nav .btn--primary { color: var(--bg); }

/* Preiszeilen: auf schmalen Bildschirmen rutscht der Wert sauber unter das Label. */
.priceline { flex-wrap: wrap; column-gap: 16px; row-gap: 2px; }
.priceline > span:last-child { margin-left: auto; text-align: right; }

/* Tippflächen mindestens 24px hoch (WCAG 2.5.8) – Fußzeile, Brotkrumen, Karten-Links. */
.site-footer li a,
.footer-bottom nav a,
.breadcrumb a,
.review__quelle,
.review__autor a,
.leistung .link-more { display: inline-block; padding-block: 4px; }

/*
   Vier Spalten am PC. Darunter zwei: Marke und Kontakt über die volle Breite, die
   beiden Linklisten nebeneinander – einspaltig war der Footer auf dem Handy 800px hoch.
*/
/* Die Markenspalte ist mindestens so breit wie „AS7 Gebäudereinigung" (bricht nicht um,
   min-content), der Beschreibungssatz darunter darf umbrechen. Vorher ragte der Name
   zwischen 900 und 1040px in die Spalte „Leistungen"; mit max-content wurde die Spalte so
   breit wie der ganze Satz und quetschte die übrigen. Vier Spalten erst ab 1000px. */
.footer-raster { grid-template-columns: minmax(min-content, 1.3fr) repeat(2, minmax(0, 1fr)) minmax(0, 1.3fr); column-gap: clamp(24px, 3vw, 48px); }
@media (max-width: 999px) {
  .footer-raster { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 24px; }
  .footer-raster > :first-child,
  .footer-raster > :last-child { grid-column: 1 / -1; }
}

/* Kontaktseite: das Gebäudefoto in der Seitenspalte ist reine Dekoration. Sobald die
   Spalte unter das Formular rutscht, fällt es weg. */
@media (max-width: 900px) {
  .kontakt__bild { display: none; }
}

/* ---------- Scroll-Reveal ---------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
  will-change: opacity, transform;
}
.reveal.shown { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* ---------- Blazor-Fehleranzeige ---------- */
#blazor-error-ui {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background: var(--fg);
  color: var(--bg);
  padding: 14px 20px;
  font-size: 14px;
  box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.5);
}
#blazor-error-ui .dismiss { cursor: pointer; float: right; padding: 0 8px; }
.blazor-error-boundary {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 20px;
  color: var(--fg);
}
