/* ===========================================================================
   E-S-P · Polish-Pass (Auslieferungsreife)
   Lädt nach design-pass.css und gewinnt daher bei gleicher Spezifität.
   Jede Regel behebt einen gemessenen Befund, keine kosmetische Streuung.
   ========================================================================= */

/* ---------------------------------------------------------------------------
   P1. rem-Basis: Schriftkollaps zwischen 767 px und 1440 px
   Die Vorlage skaliert die Wurzelschriftgröße rein proportional zur
   Viewportbreite:
     @media (min-width:992px)              html { font-size: 1.1111vw }
     @media (767px … 991px)                html { font-size: 1.4111vw }
   Gemessen ergibt das bei 768 px eine rem-Basis von 10,84 px — Fließtext
   landet bei 10,8 px, die CTA-Beschriftung bei 8,1 px. Auf einem 1024-px-
   Laptop sind es 11,4 px. Das ist keine Geschmacksfrage, sondern unlesbar.

   Die Fluid-Idee der Vorlage bleibt erhalten: oberhalb von 1440 px (dort
   ergibt 1.1111vw exakt 16 px) skaliert das Design unverändert weiter mit.
   Darunter greift eine Untergrenze von 16 px, damit die Typoskala der
   Referenzbreite 1440 px nicht nach unten wegbricht.
   -------------------------------------------------------------------------- */
@media only screen and (min-width: 992px) {
  html {
    font-size: max(1.1111vw, 16px);
  }
}

@media only screen and (max-width: 991px) and (min-width: 767px) {
  html {
    font-size: max(1.4111vw, 16px);
  }
}

/* ---------------------------------------------------------------------------
   P2. Zielgrößen: Schaltflächen unter 44 px
   Gemessen: sechs „Beratung anfragen" bei 135 × 35 px (1440 px) und sieben
   Ziele unter 44 px Breite (768 px). Die Vorlage setzt die Höhe am inneren
   Wrapper; der Link selbst blieb ohne Maß. Er trägt sie jetzt.
   -------------------------------------------------------------------------- */
a.button_link,
a.button_main_link {
  min-block-size: 44px;
  display: flex;
  align-items: center;
}

/* Der innere Wrapper trägt den Roll-up und muss die Fläche mit ausfüllen,
   sonst sitzt die Beschriftung nach dem Höhenzuwachs oben am Rand. */
a.button_link > .button_main_wrap,
a.button_main_link > .button_main_wrap {
  block-size: 100%;
  display: flex;
  align-items: center;
}

/* Kompakte Icon- und Textziele in Kopfleiste und Fußbereich */
.esp-nav-band a,
.footer_contact-list a,
.footer-small-link,
.esp-direct-contact a {
  min-block-size: 44px;
  min-inline-size: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Der Sprunglink ist erst bei Fokus sichtbar und darf dann nicht schrumpfen. */
.esp-skip-link {
  min-block-size: 44px;
  font-size: max(0.875rem, 14px);
  display: inline-flex;
  align-items: center;
}

/* ---------------------------------------------------------------------------
   P3. Kleintext-Untergrenze
   Gemessen: Leistungslabels bei 12,5 px (390 px), Eyebrow-Zeilen bei 11,2 px
   (1440 px). Unter 13 px verliert die Instrument Sans in Versalien mit weitem
   Tracking spürbar an Lesbarkeit.
   -------------------------------------------------------------------------- */
/* Die Klassen sind doppelt notiert: die Vorlage setzt dieselben Elemente in
   ihren Media-Queries über zweistufige Selektoren, gegen die eine einfache
   Klasse verliert. Die Verdopplung gleicht die Spezifität an, ohne !important
   zu streuen. */
.label-style-1.label-style-1,
.esp-eyebrow.esp-eyebrow,
.trusted-bar_service.trusted-bar_service,
.footer_link.footer_link,
.esp-service-point.esp-service-point,
.esp-direct-contact__label.esp-direct-contact__label,
.esp-footer-services__label.esp-footer-services__label,
.esp-wordmark__descriptor.esp-wordmark__descriptor {
  font-size: max(0.8125rem, 13px);
}

/* Die Schaltflächen-Beschriftung liegt doppelt vor: .button_text zeichnet den
   Ruhezustand über seinen text-shadow, .clickable_text trägt den zugänglichen
   Text. Beide müssen exakt gleich groß bleiben, sonst versetzt sich der
   Roll-up gegen seinen festen Versatz von -36px. */
.button_text.button_text,
.clickable_text.clickable_text {
  font-size: max(0.8125rem, 13px);
}

/* ---------------------------------------------------------------------------
   P4. Bildfläche vor dem Laden reservieren
   Kein Bild trug width/height oder aspect-ratio — jedes Nachladen verschob
   den Textfluss darunter. Die Seitenverhältnisse stammen aus den echten
   Dateimaßen (siehe tools/polish-pass.mjs, das sie als Attribute setzt).
   -------------------------------------------------------------------------- */
img[width][height] {
  block-size: auto;
}

/* ---------------------------------------------------------------------------
   P5. Anfrageformular
   Der primäre CTA heißt „Beratung anfragen", führte aber nur auf tel:/mailto:.
   Damit existierte im gesamten Dokument kein Eingabezustand — weder leer,
   noch sendend, noch fehlerhaft. Das Formular schließt den Conversion-Pfad
   und trägt die vier Zustände sichtbar.
   -------------------------------------------------------------------------- */
.esp-request {
  background-color: var(--esp-blue-900);
  color: var(--esp-white);
  /* Oben der Abschnittsrhythmus der Vorlage. Unten zusätzlich die 20rem, um
     die .overlap_section den Footer hochzieht — sonst schöbe sich der Footer
     über den Absende-Knopf statt in Leerraum. */
  padding-block-start: clamp(4.75rem, 8vw, 7.5rem);
  padding-block-end: calc(20rem + clamp(4.75rem, 8vw, 7.5rem));
}

.esp-request__layout {
  display: grid;
  gap: clamp(2.5rem, 5vw, 5rem);
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: start;
}

@media (max-width: 991px) {
  .esp-request__layout {
    grid-template-columns: minmax(0, 1fr);
  }
}

.esp-request__intro {
  display: grid;
  gap: 1rem;
  align-content: start;
}

/* heading_text trägt seine Größe nur im Rasterkontext der Vorlage — außerhalb
   fiel die Überschrift auf 16 px zurück. Sie steht hier auf der Stufe der
   übrigen Abschnittsüberschriften (56 px bei 1440 px). */
.esp-request__heading {
  margin: 0;
  font-size: clamp(2.25rem, 3.9vw, 3.5rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--esp-white);
}

.esp-request__lead {
  max-inline-size: 36ch;
  margin: 0;
  font-size: max(1.0625rem, 17px);
  line-height: 1.55;
  color: color-mix(in oklch, var(--esp-white) 78%, transparent);
}

.esp-request__alt {
  margin: 0;
  font-size: max(0.9375rem, 15px);
  color: color-mix(in oklch, var(--esp-white) 62%, transparent);
}

.esp-request__alt a {
  color: var(--esp-white);
  font-weight: 600;
  text-decoration-color: var(--esp-red);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

.esp-request__alt a:hover {
  color: color-mix(in oklch, var(--esp-white) 82%, var(--esp-red));
}

.esp-request .esp-eyebrow {
  margin: 0;
  color: color-mix(in oklch, var(--esp-white) 64%, transparent);
}

.esp-form {
  display: grid;
  gap: 1.25rem;
  container-type: inline-size;
}

.esp-form__grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@container (max-width: 34rem) {
  .esp-form__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.esp-field {
  display: grid;
  gap: 0.5rem;
}

.esp-field--wide {
  grid-column: 1 / -1;
}

.esp-field__label {
  font-size: max(0.8125rem, 13px);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: color-mix(in oklch, var(--esp-white) 78%, transparent);
}

.esp-field__label[data-optional]::after {
  content: " · optional";
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: none;
  color: color-mix(in oklch, var(--esp-white) 52%, transparent);
}

.esp-field__control {
  inline-size: 100%;
  min-block-size: 48px;
  padding: 0.75rem 1rem;
  font: inherit;
  font-size: max(1rem, 16px); /* unter 16px zoomt iOS beim Fokus hinein */
  color: var(--esp-white);
  background-color: color-mix(in oklch, var(--esp-white) 7%, transparent);
  /* 22 % ergaben gemessen 1,97:1 gegen die Abschnittsfläche — WCAG 1.4.11
     verlangt 3,0 für die Begrenzung eines Bedienelements. 42 % liefert 3,4. */
  border: 1px solid color-mix(in oklch, var(--esp-white) 42%, transparent);
  border-radius: 0.25rem;
  transition:
    border-color 150ms ease,
    background-color 150ms ease;
}

textarea.esp-field__control {
  min-block-size: 7.5rem;
  resize: vertical;
}

.esp-field__control::placeholder {
  color: color-mix(in oklch, var(--esp-white) 42%, transparent);
}

.esp-field__control:hover {
  border-color: color-mix(in oklch, var(--esp-white) 62%, transparent);
}

.esp-field__control:focus-visible {
  outline: 2px solid var(--esp-red);
  outline-offset: 2px;
  border-color: color-mix(in oklch, var(--esp-white) 72%, transparent);
  background-color: color-mix(in oklch, var(--esp-white) 11%, transparent);
}

/* Fehlerzustand — Farbe ist nie das einzige Signal, der Text steht darunter. */
.esp-field__control[aria-invalid="true"] {
  border-color: var(--esp-red);
  background-color: color-mix(in oklch, var(--esp-red) 12%, transparent);
}

.esp-field__error {
  display: none;
  font-size: max(0.8125rem, 13px);
  line-height: 1.4;
  color: color-mix(in oklch, var(--esp-red) 62%, var(--esp-white));
}

.esp-field__error::before {
  content: "✕ ";
  font-weight: 700;
}

.esp-field__control[aria-invalid="true"] ~ .esp-field__error {
  display: block;
}

.esp-form__footer {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.5rem;
  align-items: center;
  justify-content: space-between;
}

.esp-form__note {
  max-inline-size: 34ch;
  font-size: max(0.8125rem, 13px);
  line-height: 1.5;
  color: color-mix(in oklch, var(--esp-white) 62%, transparent);
}

/* Ausweg ohne JavaScript: der Versand läuft über request-form.js, das Formular
   hat bewusst kein action-Ziel. Ohne JS wird der Knopf ersetzt statt wirkungslos. */
.esp-form__noscript {
  display: none;
  max-inline-size: 46ch;
  padding: 0.875rem 1rem;
  border: 1px solid color-mix(in oklch, var(--esp-white) 42%, transparent);
  border-inline-start: 3px solid var(--esp-red);
  border-radius: 0.25rem;
  font-size: max(0.875rem, 14px);
  line-height: 1.5;
  color: var(--esp-white);
}

.esp-form__noscript a {
  color: var(--esp-white);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.esp-form__submit {
  min-block-size: 48px;
  padding: 0.75rem 1.75rem;
  font: inherit;
  font-size: max(1rem, 16px);
  font-weight: 600;
  color: var(--esp-blue-900);
  background-color: var(--esp-white);
  border: 0;
  border-block-end: 3px solid var(--esp-red);
  border-radius: 0.25rem;
  cursor: pointer;
  transition:
    transform 150ms ease,
    background-color 150ms ease,
    border-color 150ms ease;
}

.esp-form__submit:hover {
  background-color: color-mix(in oklch, var(--esp-white) 88%, var(--esp-red));
  transform: translateY(-1px);
}

.esp-form__submit:active {
  transform: translateY(1px);
  border-block-end-width: 2px;
}

.esp-form__submit:focus-visible {
  outline: 2px solid var(--esp-red);
  outline-offset: 3px;
}

/* Ladezustand — Beschriftung wechselt, Fläche bleibt maßgleich. */
.esp-form__submit[data-state="sending"] {
  cursor: progress;
  color: color-mix(in oklch, var(--esp-blue-900) 66%, transparent);
}

.esp-form__submit[data-state="sending"]::before {
  content: "";
  display: inline-block;
  inline-size: 0.875em;
  block-size: 0.875em;
  margin-inline-end: 0.5em;
  vertical-align: -0.1em;
  border: 2px solid color-mix(in oklch, var(--esp-blue-900) 30%, transparent);
  border-block-start-color: var(--esp-red);
  border-radius: 50%;
  animation: esp-spin 700ms linear infinite;
}

@keyframes esp-spin {
  to {
    transform: rotate(1turn);
  }
}

.esp-form__submit:disabled {
  cursor: not-allowed;
  opacity: 0.72;
  transform: none;
}

/* Rückmeldezone: eine Fläche, drei mögliche Zustände. */
.esp-form__status {
  display: none;
  gap: 0.75rem;
  padding: 1rem 1.25rem;
  font-size: max(0.9375rem, 15px);
  line-height: 1.5;
  border-radius: 0.25rem;
  border-inline-start: 3px solid transparent;
}

.esp-form__status[data-state="success"],
.esp-form__status[data-state="error"] {
  display: flex;
}

.esp-form__status[data-state="success"] {
  color: var(--esp-white);
  background-color: color-mix(in oklch, var(--esp-white) 10%, transparent);
  border-inline-start-color: var(--esp-white);
}

.esp-form__status[data-state="error"] {
  color: var(--esp-white);
  background-color: color-mix(in oklch, var(--esp-red) 16%, transparent);
  border-inline-start-color: var(--esp-red);
}

.esp-form__status a {
  color: inherit;
  text-underline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .esp-form__submit,
  .esp-field__control {
    transition: none;
  }

  .esp-form__submit[data-state="sending"]::before {
    animation-duration: 2.4s;
  }
}

/* ---------------------------------------------------------------------------
   P6. Rechtliche Trennzeichen sitzen hochgestellt
   Die 44-px-Zielgröße aus P2 macht .footer-small-link zum inline-flex-Element,
   die Trenner-Spans zwischen den Links bleiben aber inline und richten sich
   an der Textgrundlinie aus — die Punkte wandern optisch nach oben. Der
   Flex-Container selbst zentriert seine Kinder vertikal, damit Links und
   Trenner auf einer Höhe stehen.
   -------------------------------------------------------------------------- */
nav[aria-label="Rechtliches"] {
  align-items: center;
}

/* ---------------------------------------------------------------------------
   P7. Ablauf-CTA: die geparkte Zweitbeschriftung ragte in die Fläche
   Die Vorlage legt die Beschriftung doppelt an: `.button_text` parkt per
   translateY(2em) unterhalb der Schaltfläche, sichtbar ist im Ruhezustand nur
   sein text-shadow mit dem Gegenversatz 0 -2em. Der Rollup-Effekt soll beide
   im Hover gemeinsam nach oben fahren.

   Gemessen im Abschnitt #ablauf (1440x900, document.fonts.ready + 1500 ms):
     .button_main_wrap   y 5110 … 5154 (44 px hoch, overflow: hidden)
     .button_text        y 5152 … 5165 (13 px, transform translateY(26px))
   Der Parkweg von 2em ist bei der in P3 auf 13 px fixierten Schriftgröße
   26 px lang, bis zur Unterkante des Wraps sind es aber 28 px. Die obersten
   2 px der geparkten Glyphen bleiben deshalb innerhalb des Clip-Rechtecks
   stehen und lesen sich als abgeschnittene zweite Textzeile unter dem Label.

   Der Rollup läuft hier ohnehin nicht: gemessen sind Ruhe- und Hover-Zustand
   dieser Schaltfläche pixelgleich, die Laufzeit-Interaktion der Vorlage hängt
   nur an der Kopfleiste. Die Beschriftung wird deshalb wie in design-pass D2
   stillgelegt — der echte Text rückt exakt an die Stelle, an der bisher sein
   Schatten stand (5152 - 26 = 5126), der Ruhezustand bleibt unverändert.
   Es ist die einzige geparkte Beschriftung im Dokument (Rest bereits still).
   -------------------------------------------------------------------------- */
.section_home-how .button_main_wrap > .button_text {
  transform: none;
  text-shadow: none;
}

/* ---------------------------------------------------------------------------
   P8. FAQ: die rote Hover-Kachel der Vorlage schaute beidseitig heraus
   Die Vorlage legt hinter jede Akkordeon-Zeile `.accordion_toggle_hover` —
   eine rote Fläche (#e20f15), position: absolute, z-index 1, die im Ruhe-
   zustand auf translateY(-60px) parkt und im Hover auf translate(0,0) fährt.
   Der Redesign-Pass (R5) hat den Hover-Zustand aber neu gesetzt: eine helle
   Fläche auf `.accordion_toggle_button` plus roter Rand links.

   Gemessen im Hover (Zeile „Was gehört zu einer Videoüberwachung?"):
     .accordion_toggle_hover    x 615, Breite 785  (volle Zeilenbreite)
     .accordion_toggle_button   x 631, Breite 753  (beidseitig 16 px schmaler)
   Die helle Fläche deckt die rote Kachel also nur in der Mitte ab; links und
   rechts bleiben je 16 px Rot stehen. Das ist kein Zwischenzustand, sondern
   stabil, solange der Zeiger auf der Zeile steht — im Audit-Screenshot war er
   dort geparkt, weil der Klick auf „Ablehnen" bei (1076, 825) lag und die
   Zeile beim Scrollen unter den stehenden Zeiger geriet.

   Die Kachel ist im neuen Zustandsmodell funktionslos und wird abgeschaltet.
   -------------------------------------------------------------------------- */
.accordion_toggle_hover {
  display: none;
}

/* ---------------------------------------------------------------------------
   P9. #alle-leistungen: Foto in die Slider-Kachel
   Die `cs-featured_thumbnail-wrapper` trug bisher nur die beiden Theme-Lotties
   (Desktop/Mobil) — auf dem Blueprint-Raster blieb ein rot gerahmtes Rechteck
   mit der Ziffer darin. Neben den bereits bebilderten Service-Cards las sich
   der Slider dadurch als unfertig.

   Das Foto liegt als eigenes `<figure>` ueber den Lotties (die als Raster
   darunter bleiben und im Radius-Spalt an den Ecken sichtbar sind). Rundung
   und 1px-Rahmen spiegeln `figure.esp-service-photo` aus den Service-Cards;
   der Rahmenton ist auf den hellen Gelbgrund dieser Sektion gedreht
   (Blau statt Weiss), sonst waere er unsichtbar.

   EIN <img> je Slide deckt Desktop und Mobil ab: der Wrapper selbst existiert
   nur einmal, `hide-/show-mobile-landscape` schaltet ausschliesslich die
   beiden Lottie-Ebenen. Ein zweites Bildelement waere reine Doppellast.
   -------------------------------------------------------------------------- */
.cs-featured_thumbnail-wrapper .cs-featured_photo {
  position: absolute;
  inset: 0;
  z-index: 1;
  margin: 0;
  overflow: hidden;
  border: 1px solid color-mix(in oklch, var(--esp-blue-900) 18%, transparent);
  border-radius: 0.25rem;
}

.cs-featured_thumbnail-wrapper .cs-featured_photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Lokaler Verlauf statt Flaechen-Scrim: ein ganzflaechiges Overlay hat das
   Motiv blau eingefaerbt und Fotoqualitaet gekostet. Der Verlauf sitzt jetzt
   nur unter der Ziffer, aussen liegt exakt 0% Overlay auf dem Motiv.

   Anker 75%/50%, nicht 50%/50%: der Wrapper ist ein Flex-Container, in dem die
   beiden Lottie-Ebenen echte Flex-Items sind. Die dem Breakpoint entsprechende
   Ebene nimmt die halbe Breite, die andere faellt auf 0 - die Ziffernflaeche
   erbt die rechte Haelfte und zentriert darin. Gemessen an allen Kacheln:
   Glyphenmitte cx 0,750 / cy 0,500 bei 1440 UND bei 390. Ein auf 50%/50%
   zentrierter Verlauf lag daneben und liess die Ziffer bei 1,83:1 stehen.

   Ellipse 30%x28% -> ca. ein Viertel der Kachelflaeche; die Glyphen messen
   15%x14% (1440) bzw. 13%x20% (390) und liegen damit im dichten Kern. */
.cs-featured_thumbnail-wrapper .cs-featured_photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 30% 28% at 75% 50%,
    color-mix(in oklch, var(--esp-blue-900) 80%, transparent) 0%,
    color-mix(in oklch, var(--esp-blue-900) 72%, transparent) 38%,
    color-mix(in oklch, var(--esp-blue-900) 30%, transparent) 72%,
    transparent 100%
  );
}

/* Weisse Ziffer nur dort, wo tatsaechlich ein Foto liegt. Das Scoping ist
   generisch (Geschwister-Kombinator statt :has(), damit es nicht an der
   Browser-Unterstuetzung haengt) — Slide 06 wurde spaeter bebildert und war
   ohne CSS-Aenderung mit abgedeckt. */
.cs-featured_photo ~ .esp-service-index {
  position: relative;
  z-index: 2;
  color: var(--esp-white);
  text-shadow: 0 2px 20px color-mix(in oklch, var(--esp-blue-900) 68%, transparent);
}
