/* ============================================================
   IDCF Homepage (Nachbau der Base44-Vorlage) — H4
   Tokens aus base44_referenz/_tokens.json + css_0.css:
   Brand hsl(356 100% 65%) · Ink #1a1a1a · System-Font-Stack (KEIN Webfont,
   Optik = weight 900 + uppercase + letter-spacing -0.05em)
   ============================================================ */
:root {
  --brand: hsl(356, 100%, 65%);
  --brand-dark: hsl(356, 80%, 55%);
  --ink: #1a1a1a;
  --ink-soft: #666;
  --ink-faint: #999;
  --line: #e5e7eb;
  --bg-soft: #f8fafc;
  --dark: #1a1a1a;
  --radius-card: 20px;
  --font: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  --container: 1200px;
}

/* KAP. 217 — die waehlbare Schrift.
   Zwei Stellschrauben, beide mit Rueckfall auf --font: --hp-fontt (Fliesstext) und
   --hp-fonth (Ueberschriften). Wird nichts gewaehlt, setzt HomepageSchrift KEINE
   Zeile — dann greift ueberall wieder genau der bisherige Geraete-Stack.
   Dazu zwei Ausgleiche, die an der GEWAEHLTEN UEBERSCHRIFTEN-SCHRIFT haengen:
   --hp-trackadd gleicht die enge Spur (-0,05em) fuer schmale Schriften aus,
   --hp-lineadd die Zeilenhoehe (0,85). Beide sind ohne Wahl 0 und wirkungslos.
   Warum die Zeilenhoehe: Anton baut 0,13em hoeher als die bisherige Geraete-Schrift
   — bei 0,85 UEBERLAPPTEN die drei Hero-Zeilen sichtbar. Die Werte je Schrift sind
   gemessen (HomepageSchrift::FAMILIEN), nicht geschaetzt. */

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  font-family: var(--hp-fontt, var(--font));
  color: var(--ink);
  background: #fff;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }

.hp-container { max-width: var(--container); margin: 0 auto; padding: 0 24px; }

/* ---------- Typo ---------- */
/* KAP. 217: Ueberschriften duerfen eine eigene Schrift tragen. Ohne Wahl faellt
   --hp-fonth auf --hp-fontt und weiter auf --font zurueck — identisch zu vorher. */
.hp-h1 {
  font-family: var(--hp-fonth, var(--hp-fontt, var(--font)));
  font-size: clamp(56px, 11.4vw, 164px);
  font-weight: 900;
  letter-spacing: calc(-0.05em + var(--hp-trackadd, 0em));
  line-height: calc(0.85 + var(--hp-lineadd, 0));
  text-transform: uppercase;
}
.hp-h2 {
  font-family: var(--hp-fonth, var(--hp-fontt, var(--font)));
  font-size: clamp(38px, 5vw, 72px);
  font-weight: 900;
  letter-spacing: calc(-0.05em + var(--hp-trackadd, 0em));
  line-height: calc(1 + var(--hp-lineadd, 0));
  text-transform: uppercase;
}
.hp-h3 {
  font-family: var(--hp-fonth, var(--hp-fontt, var(--font)));
  font-size: clamp(24px, 3vw, 36px);
  font-weight: 900;
  letter-spacing: calc(-0.03em + var(--hp-trackadd, 0em));
  line-height: calc(1.1 + var(--hp-lineadd, 0));
  text-transform: uppercase;
}
.hp-eyebrow {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 16px;
}
.hp-lead { color: var(--ink-soft); font-size: 17px; max-width: 640px; }

/* ---------- Buttons ---------- */
.hp-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border-radius: 9999px;
  padding: 14px 30px;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.03em;
  cursor: pointer;
  border: none;
  transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.hp-btn:hover { transform: translateY(-1px); }
.hp-btn .arr { transition: transform 0.15s ease; }
.hp-btn:hover .arr { transform: translateX(3px); }
.hp-btn--brand { background: var(--brand); color: #fff; }
.hp-btn--brand:hover { background: var(--brand-dark); }
.hp-btn--dark { background: var(--dark); color: #fff; }
.hp-btn--ghost { background: transparent; color: #fff; border: 1.5px solid rgba(255, 255, 255, 0.85); }
.hp-btn--ghost:hover { background: #fff; color: var(--ink); }
.hp-btn--upper { text-transform: uppercase; }

/* Abstand unter dem festen Seitenkopf — nur fuer Abschnitts-Seiten OHNE
   durchsichtigen Kopf (Homepage-Editor Stufe 3, 27.07.2026). Der Kopf ist
   `position:fixed` und .hp-header__in hoch (76px); ohne diesen Abstand rutscht
   der erste Baustein darunter. Die festen Seiten bringen ihren eigenen Abstand
   mit und bekommen diese Klasse bewusst NICHT. */
/* KAP. 212 (09.08.2026): Die Hoehe der Kopfleiste steht an DREI Stellen — hier, an der
   Leiste selbst und am Aufhaengepunkt des Handy-Menues. Alle drei haengen jetzt an
   derselben Stellschraube --hp-headh; der Rueckfall ist der bisherige Wert 76 px. */
.hp-underhead { padding-top: var(--hp-headh, 76px); }

/* ---------- Header ---------- */
.hp-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 60;
  transition: background 0.25s ease, box-shadow 0.25s ease;
  background: var(--hp-headbg, #fff);
  box-shadow: 0 1px 0 var(--line);
}
.hp-header__in {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 24px;
  height: var(--hp-headh, 76px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.hp-logo img { height: var(--hp-logoh, 58px); width: auto; transition: filter 0.25s ease; }
.hp-nav { display: flex; align-items: center; gap: 26px; }
/* ── KAP. 235 (Teil 2) — DIE TEXTE DER KOPFLEISTE SIND EINSTELLBAR ──────────
   Ueber diesen vier Elementen liegen 18 `!important`-Regeln; ein Inline-Stil
   verliert gegen jede davon. Sie lesen darum ab jetzt ihre Stellschraube —
   mit dem HEUTIGEN Wert als Rueckfall. Ohne Einstellung entsteht die
   `:root`-Zeile gar nicht, und jede dieser Regeln rechnet Zeichen fuer Zeichen
   wie vorher. Belegt durch 72 Messwerte in 9 Kopfleisten-Zustaenden x 2 Breiten,
   vorher und nachher (/root/k235_kopf_VORHER.txt gegen _NACHHER.txt).
   Die :hover-Regeln bleiben ABSICHTLICH unangetastet: sonst naehme eine
   gewaehlte Farbe dem Knopf seine Reaktion beim Zeigen. */
.hp-nav a {
  font-size: var(--hp-navsize, 14px);
  font-weight: var(--hp-navweight, 500);
  line-height: var(--hp-navlh, inherit);
  color: var(--hp-navcol, var(--ink));
  transition: color 0.15s ease;
}
.hp-nav a:hover { color: var(--brand); }
.hp-nav .hp-btn { color: #fff; }
/* Der Anmelde-Knopf bekommt seine eigenen drei Werte. Ohne sie faellt er auf
   genau das zurueck, was `.hp-nav a` ihm heute schon gibt (14px/500) — die
   `.hp-cta`-Angaben darunter (13px) verlieren ohnehin gegen `.hp-nav a`, das ist
   im Browser nachgemessen und kein Schluss aus der Spezifitaet. */
.hp-nav a.hp-cta,
.hp-cta-handy{
  font-size: var(--hp-ctasize, var(--hp-navsize, 14px));
  font-weight: var(--hp-ctaweight, var(--hp-navweight, 500));
  line-height: var(--hp-ctalh, inherit);
}

/* transparente Variante auf dunklem Hero (bis zum Scrollen) */
.hp-header--overlay:not(.is-solid) { background: transparent; box-shadow: none; }
.hp-header--overlay:not(.is-solid) .hp-logo img { filter: brightness(0) invert(1); }
/* KAP. 235: hier stand `#fff` ohne Stellschraube — die eingestellte Menue-Farbe
   wirkte ueber einem Hero deshalb NICHT. Das war ein Regler, der auf der
   Startseite nichts tat; jetzt liest auch diese Regel ihn, mit `#fff` als
   Rueckfall. */
.hp-header--overlay:not(.is-solid) .hp-nav a { color: var(--hp-navcol, #fff); }
.hp-header--overlay:not(.is-solid) .hp-nav a:hover { color: var(--brand); }
/* CTA auf dem Hero: nur weisser Rand, erst bei Hover gefuellt (Feinschliff-Runde 1, P3) */
.hp-header--overlay:not(.is-solid) .hp-nav .hp-cta,
.hp-header--overlay:not(.is-solid) .hp-cta-handy{ background: transparent; border: 1.5px solid rgba(255, 255, 255, 0.9); color: var(--hp-ctacol, #fff) !important; }
.hp-header--overlay:not(.is-solid) .hp-nav .hp-cta:hover,
.hp-header--overlay:not(.is-solid) .hp-cta-handy:hover{ background: #fff; color: var(--ink) !important; }
.hp-cta { background: var(--brand); color: var(--hp-ctacol, #fff) !important; text-transform: uppercase; padding: 11px 24px; font-size: 13px; }

/* ══ J52 (30.08.2026) — DER ANMELDE-KNOPF AM TELEFON ═══════════════════════
   Andys Wortlaut: „auf dem pc frontend koennen sich die leute anmelden oben
   recht, auf dem handy nicht da muessen die erst ins menue [...] ich brauche
   im menue handy einen button fuer die anmeldung."

   AUF DEM PC AENDERT SICH NICHTS: der zweite Knopf steht auf display:none.
   Alle 14 Varianten-Regeln der Kopfleiste (overlay, dunkel, Umriss, Link,
   Grossbuchstaben) tragen ihn seit diesem Kapitel mit im Selektor — damit
   folgt der Handy-Knopf JEDER Einstellung, die Andy am PC-Knopf trifft, ohne
   dass irgendwo eine zweite Wahrheit entsteht (R38). Sichtbar wird er erst
   in der Handy-Regel unten in @media (max-width: 900px). */
.hp-cta-handy { display: none; }

/* ── KAP. 212 — die einstellbaren Zustaende der Kopfleiste ──────────────────
   Alle greifen NUR mit Klasse. Ohne Einstellung traegt der Kopf keine davon. */
/* nicht kleben: der Kopf laeuft mit, der Abstand darunter entfaellt */
/* Ohne Hero laeuft die Leiste im normalen Fluss mit (nimmt ihren Platz selbst
   ein — der Abstand darunter entfaellt in der Ansicht). Ueber einem Hero bleibt
   sie schwebend, sonst wuerde sie das Bild nach unten schieben. */
.hp-header--frei { position: static; }
.hp-header--frei.hp-header--overlay { position: absolute; }
/* Dunkler Hintergrund — dieselbe Behandlung wie ueber einem dunklen Hero.
   Eine selbst gewaehlte Menue-Farbe steht als Rueckfallwert drin und gewinnt. */
.hp-header--dunkel:not(.hp-header--overlay) .hp-logo img { filter: brightness(0) invert(1); }
.hp-header--dunkel:not(.hp-header--overlay) .hp-nav a { color: var(--hp-navcol, #fff); }
.hp-header--dunkel:not(.hp-header--overlay) .hp-burger span { background: var(--hp-navcol, #fff); }
.hp-header--dunkel:not(.hp-header--overlay).hp-header--knopf-umriss .hp-nav .hp-cta,
.hp-header--dunkel:not(.hp-header--overlay).hp-header--knopf-umriss .hp-cta-handy{
  border-color: rgba(255, 255, 255, 0.9); color: var(--hp-ctacol, #fff) !important; }
.hp-header--dunkel:not(.hp-header--overlay).hp-header--knopf-umriss .hp-nav .hp-cta:hover,
.hp-header--dunkel:not(.hp-header--overlay).hp-header--knopf-umriss .hp-cta-handy:hover{
  background: #fff; color: var(--ink) !important; }
.hp-header--dunkel:not(.hp-header--overlay).hp-header--knopf-link .hp-nav .hp-cta,
.hp-header--dunkel:not(.hp-header--overlay).hp-header--knopf-link .hp-cta-handy{
  color: var(--hp-ctacol, var(--hp-navcol, #fff)) !important; }
/* keine Trennlinie */
.hp-header--ohnelinie { box-shadow: none; }
/* Anmelde-Knopf: nur Umriss bzw. wie ein Link */
.hp-header--knopf-umriss .hp-nav .hp-cta,
.hp-header--knopf-umriss .hp-cta-handy{ background: transparent; border: 1.5px solid var(--brand); color: var(--hp-ctacol, var(--brand)) !important; }
.hp-header--knopf-umriss .hp-nav .hp-cta:hover,
.hp-header--knopf-umriss .hp-cta-handy:hover{ background: var(--brand); color: #fff !important; }
.hp-header--knopf-link .hp-nav .hp-cta,
.hp-header--knopf-link .hp-cta-handy{ background: transparent; border: 0; padding: 0; color: var(--hp-ctacol, var(--hp-navcol, var(--ink))) !important; font-weight: var(--hp-ctaweight, var(--hp-navweight, 500)); }
.hp-header--knopf-link .hp-nav .hp-cta:hover,
.hp-header--knopf-link .hp-cta-handy:hover{ color: var(--brand) !important; }
/* Knopf-Text ohne Grossbuchstaben */
.hp-header--knopf-normal .hp-nav .hp-cta,
.hp-header--knopf-normal .hp-cta-handy{ text-transform: none; }

/* Dropdown "Dance Camps" */
.hp-drop { position: relative; }
.hp-drop > a::after { content: " ▾"; font-size: 11px; }
.hp-drop__menu {
  position: absolute;
  top: calc(100% + 10px);
  left: -12px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
  padding: 8px;
  min-width: 200px;
  display: none;
}
.hp-drop:hover .hp-drop__menu, .hp-drop:focus-within .hp-drop__menu { display: block; }
.hp-drop__menu::before { content: ""; position: absolute; top: -12px; left: 0; right: 0; height: 12px; }
/* KAP. 235: die Rueckfaelle sind die HEUTIGEN Werte, im Browser nachgemessen —
   14px/500 kommen von `.hp-nav a`, nicht vom Grund-CSS. `inherit` waere hier
   FALSCH: der Elternteil `.hp-drop__menu` steht auf 16px. */
.hp-drop__menu a { display: block; padding: 10px 14px; border-radius: 8px; color: var(--hp-subcol, var(--ink)) !important;
  font-size: var(--hp-subsize, var(--hp-navsize, 14px)); font-weight: var(--hp-subweight, var(--hp-navweight, 500)); line-height: var(--hp-sublh, inherit); }
.hp-drop__menu a:hover { background: var(--bg-soft); color: var(--ink) !important; }
.hp-drop__menu .soon { color: var(--hp-sooncol, var(--ink-faint)) !important; font-size: var(--hp-soonsize, 12px);
  font-weight: var(--hp-soonweight, inherit); line-height: var(--hp-soonlh, inherit); }

/* Burger (mobil) */
.hp-burger { display: none; background: none; border: 0; width: 40px; height: 40px; cursor: pointer; }
.hp-burger span { display: block; height: 2px; margin: 5px 8px; background: var(--ink); transition: 0.2s; }
.hp-header--overlay:not(.is-solid) .hp-burger span { background: #fff; }

@media (max-width: 900px) {
  .hp-nav {
    display: none;
    position: absolute;
    top: var(--hp-headh, 76px); left: 0; right: 0;
    /* KAP. 213: derselbe Hintergrund wie die Leiste — sonst passte die eingestellte
       Schriftfarbe nicht zum Untergrund. */
    background: var(--hp-headbg, #fff);
    flex-direction: column;
    align-items: stretch;
    padding: 12px 24px 20px;
    gap: 4px;
    box-shadow: 0 16px 32px rgba(0, 0, 0, 0.12);
  }
  .hp-nav.open { display: flex; }
  /* KAP. 213: die eingestellte Menue-Farbe gilt auch hier. Ohne Eingabe bleibt es
     bei var(--ink) — also genau wie bisher. Die Schriftgroesse bleibt bewusst bei
     16px: am Handy zaehlt die Tippflaeche, nicht der Desktop-Regler. */
  .hp-nav a { padding: 12px 4px; font-size: 16px; color: var(--hp-navcol, var(--ink)) !important; }
  /* KAP. 235 — DIE FALLE, DIE HIER FAST ZUGESCHLAGEN HAETTE:
     Die neue Regel `.hp-drop__menu a{font-size:…}` oben hat die Spezifitaet
     (0,2,1) und schlaegt damit `.hp-nav a{font-size:16px}` (0,1,1) — auch hier
     drin. Ohne diese Zeile waere der Untermenue-Text am Handy von 16 auf 14 px
     geschrumpft, ohne dass jemand einen Regler bewegt haette. Der Rueckfall
     lautet deshalb HIER 16px, nicht 14. Gefunden durch die Messung in beiden
     Breiten, nicht durch Nachdenken. */
  .hp-drop__menu a { color: var(--hp-subcol, var(--hp-navcol, var(--ink))) !important; font-size: var(--hp-subsize, 16px); }
  .hp-drop__menu a:hover { background: transparent; }
  .hp-drop__menu .soon { color: var(--hp-sooncol, var(--hp-navcol, var(--ink-faint))) !important; opacity: .6; }
  /* Der Anmelde-Knopf braucht hier eine eigene Zeile: `.hp-nav a` traegt
     `!important` und wuerde seine Farbe sonst ueberschreiben.
     ⚠ UND SEINE GROESSE MUSS MIT: die neue Regel `.hp-nav a.hp-cta{font-size:…}`
     oben hat (0,2,1) und schlaegt `.hp-nav a{font-size:16px}` (0,1,1) auch hier
     drin. Ohne diese Zeile schrumpfte der Anmelde-Knopf am Telefon von 16 auf
     14 px — ohne dass jemand einen Regler bewegt haette. Gefunden von der
     Messung in beiden Breiten (9 Zustaende x 2 Breiten, vorher gegen nachher);
     ein Byte-Beweis haette es NICHT gefunden, weil im HTML alles gleich bleibt. */
  .hp-nav a.hp-cta,
  .hp-cta-handy{ color: var(--hp-ctacol, var(--hp-navcol, var(--ink))) !important; font-size: var(--hp-ctasize, 16px); }
  /* Dunkler Hintergrund ohne eigene Schriftfarbe: hell schreiben, sonst dunkel auf dunkel. */
  .hp-header--dunkel .hp-nav a { color: var(--hp-navcol, #fff) !important; }
  .hp-header--dunkel .hp-nav a.hp-cta,
  .hp-header--dunkel .hp-cta-handy{ color: var(--hp-ctacol, var(--hp-navcol, #fff)) !important; }
  .hp-header--dunkel .hp-drop__menu a { color: var(--hp-subcol, var(--hp-navcol, #fff)) !important; }
  .hp-header--dunkel .hp-drop__menu .soon { color: var(--hp-sooncol, var(--hp-navcol, #fff)) !important; opacity: .6; }
  .hp-drop__menu { display: block; position: static; border: 0; box-shadow: none; padding: 0 0 0 16px; }
  .hp-burger { display: block; order: 2; }

  /* ══ J52 — HIER WIRD DER KNOPF SICHTBAR ══════════════════════════════════
     GEMESSEN, WARUM ES EIN ZWEITER KNOPF SEIN MUSS: der Knopf im Menue ist
     ein Kind von `.hp-nav`, und die steht hier oben auf `display:none`. Ein
     Kind eines display:none-Elements ist mit keinem CSS wieder sichtbar zu
     machen — gemessen am Telefon: der Knopf meldete display:inline-flex und
     trotzdem 0 x 0 px, weil sein Elternteil weg war.

     🔴 UND DIE ZWEITE MESSUNG, DIE DAS AUSSEHEN BESTIMMT HAT:
     Andys Logo steht auf logo_hoehe = 110 px und ist damit 211 px BREIT.
     Auf einem iPhone 13 (390 px) bleiben nach den Raendern 342 px; Logo plus
     Burger belegen davon schon 251 px. Fuer den Knopf war also von vornherein
     kein Platz „daneben" — deshalb:
       · der Abstand in der Leiste geht am Telefon von 24 auf 12 px,
       · der Knopf wird kompakt (12 px, enge Polsterung),
       · und das Logo darf schrumpfen, statt die Leiste zu sprengen.
     Ueber 900 px passiert nichts davon. */
  .hp-header__in { gap: 12px; }
  /* Das Logo gibt nach, wenn es eng wird — vorher lief es aus der Leiste heraus.
     `height:auto` mit `max-height` haelt dabei das Seitenverhaeltnis. */
  .hp-logo { flex: 0 1 auto; min-width: 0; }
  .hp-logo img { max-width: 100%; height: auto; max-height: var(--hp-logoh, 58px); }
  /* 🔴 DREI KLASSEN, UND ZWAR MIT ABSICHT: die Look-Vorlage V9 schreibt
     `body[data-hp-look="v9"] .hp-btn { font-size:14.5px; padding:14px 28px }`.
     Das ist (0,2,1) und wird SPAETER geladen als diese Datei — eine Regel mit
     nur `.hp-cta-handy` (0,1,0) verliert dagegen lautlos. Gemessen, nicht
     geschlossen: der Knopf kam mit 206 px Breite heraus und drueckte Andys
     Logo von 211 auf 94 px zusammen. `.hp-header__in .hp-btn.hp-cta-handy`
     ist (0,3,0) und gewinnt — ohne ein einziges !important. */
  .hp-header__in .hp-btn.hp-cta-handy {
    display: inline-flex;
    order: 1;
    flex: 0 0 auto;
    margin-left: auto;          /* schiebt Knopf und Burger zusammen nach rechts */
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 0;
    line-height: 1.15;
    padding: 9px 14px;
    /* Dieselbe Stellschraube wie am PC-Knopf, nur mit kleinerem Rueckfall:
       am Telefon zaehlt, dass Logo, Knopf und Burger nebeneinander passen. */
    font-size: var(--hp-ctasize, 12px);
    /* Der PC-Knopf steht in der pre-wrap-Liste des Textkatalogs. Dieselbe
       Bedeutung hier von Hand, damit ein Zeilenumbruch in Andys Beschriftung
       auf beiden Wegen gleich wirkt. */
    white-space: pre-wrap;
    /* Und die zwei Zeilen, die Andys Logo retten. `min-content` macht den
       Kasten so breit wie sein LAENGSTES WORT — „JETZT ANMELDEN" steht dann
       zweizeilig und braucht rund 95 statt 206 px. `max-width` ist die
       Notbremse fuer eine sehr lange Beschriftung.
       Gemessen (iPhone 13, 342 px Innenbreite):
         ohne diese zwei Zeilen : Knopf 206 px, Logo 94 px (von 211)
         mit ihnen              : Knopf  95 px, Logo 187 px */
    width: min-content;
    max-width: 40%;
  }
  /* Der Burger darf NICHT mitschrumpfen — ohne diese Zeile wurde er von
     40 auf 18 px zusammengedrueckt (gemessen). */
  .hp-header__in .hp-burger { flex: 0 0 auto; }
}

/* ---------- Hero ---------- */
.hp-hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  color: #fff;
  overflow: hidden;
  background: var(--dark);
}
.hp-hero__media, .hp-hero__media img, .hp-hero__media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* SPONSOR-LOGOS (26.07.2026). Position und Breite kommen als Stellschrauben aus dem Editor.
   Die Breite ist ein Prozentwert der Hero-Breite — auf dem Telefon waren 8 % gemessene
   31 px, also unlesbar. Am Handy deshalb vergroessern UND die Position so klemmen, dass
   das groessere Logo nicht ueber den Rand ragt. */
.hp-hero__sp { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.hp-hero__splogo {
  position: absolute;
  /* Klemmung jetzt auch auf dem Desktop (27.07.2026): das Logo bleibt, wo es hingezogen
     wurde, und rueckt NUR dann nach innen, wenn es sonst ueber den Rand ragen wuerde.
     Die Breite bleibt unveraendert — bestehende Platzierungen verschieben sich damit
     hoechstens um die halbe Logo-Breite, und auch nur ganz am Rand. */
  left: clamp(calc(var(--sp-w) / 2), var(--sp-x), calc(100% - var(--sp-w) / 2));
  top: var(--sp-y);
  width: var(--sp-w);
  transform: translate(-50%, -50%);
  object-fit: contain;
}
@media (max-width: 640px) {
  .hp-hero__splogo {
    --sp-eff: clamp(64px, calc(var(--sp-w) * 2.6), 38%);
    width: var(--sp-eff);
    left: clamp(calc(var(--sp-eff) / 2), var(--sp-x), calc(100% - var(--sp-eff) / 2));
  }
}

/* HANDY-HERO (26.07.2026): zwei Geraete-Ebenen, umgeschaltet per Breakpoint.
   Bewusst KEIN <source media> — das ist bei <video> in den Browsern unzuverlaessig.
   Ohne eigene Handy-Datei wird nur EINE Ebene ohne Geraete-Klasse gerendert, dann
   greift keine dieser Regeln und es bleibt exakt beim Stand davor. */
.hp-hero__dev { position: absolute; inset: 0; }
/* ══ KAP. 266 (ENDSPURT D.2) — DER HERO ALS SLIDESHOW ═══════════════════════
   Die Regeln greifen NUR an einer Ebene mit der Klasse `--show`, und die
   entsteht nur, wenn wirklich ein zweites Bild eingestellt ist. Bei einem Bild
   aendert sich damit weder am HTML noch an der Darstellung ein Zeichen.

   🔴 DIE BILDER LIEGEN OHNEHIN SCHON UEBEREINANDER. `.hp-hero__media img`
   traegt seit jeher `position:absolute; inset:0; object-fit:cover` (Zeile 299).
   Es braucht also keinen neuen Kasten und keine neue Positionierung — nur die
   Sichtbarkeit. Das ist der Grund, warum dieser Baustein so wenig CSS braucht.

   🔴 DAS ERSTE BILD BLEIBT SICHTBAR, WENN NICHTS LAEUFT. `--show > picture`
   setzt `opacity:0` — aber nur fuer die ZUSATZBILDER. Das Grundbild kommt aus
   `_hero_medium` und ist das erste `picture`; es bekommt `opacity:1`, solange
   kein Skript etwas anderes sagt. Ohne JavaScript, mit abgestellter Bewegung
   oder bei einem Fehler im Skript steht also das Bild da, das auch vorher da
   stand — nie ein schwarzer Kasten. */
.hp-hero__dev--show > picture { opacity: 0; transition: opacity .9s ease-in-out; }
/* OHNE Skript (oder bevor es startet): das erste Bild steht. */
.hp-hero__dev--show > picture:first-child { opacity: 1; }
/* ⚠ SOBALD DAS SKRIPT LAEUFT, ENTSCHEIDET ALLEIN `an` — auch fuer das erste Bild.
   GEMESSEN, nicht geahnt (k266_slideshow_pruefen.js, erster Lauf): ohne diese
   zwei Zeilen blieb Bild 1 dauerhaft sichtbar („Bild 1 + Bild 2"). Beim Uebergang
   von Bild 2 auf Bild 3 blitzte es darunter durch, weil beide gerade halb
   durchsichtig waren. Die Klasse setzt das Skript selbst — damit gilt der
   Rueckfall oben genau so lange, wie wirklich kein Skript arbeitet. */
.hp-hero__dev--show--laeuft > picture:first-child { opacity: 0; }
.hp-hero__dev--show--laeuft > picture.an,
.hp-hero__dev--show > picture.an { opacity: 1; }
/* Wer Bewegung abgestellt hat, sieht das erste Bild und sonst nichts. Das
   Skript steigt zusaetzlich selbst aus (s. hero.blade.php) — beides zusammen,
   weil eine Ruecksicht, die an EINER Stelle haengt, eine Stelle zu wenig hat. */
@media (prefers-reduced-motion: reduce) {
  .hp-hero__dev--show > picture { transition: none; opacity: 0; }
  .hp-hero__dev--show > picture:first-child { opacity: 1; }
}
.hp-hero__dev--mob { display: none; }
@media (max-width: 640px) {
  .hp-hero__dev--desk { display: none; }
  .hp-hero__dev--mob { display: block; }
}
.hp-hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  /* KAP. 240 (Andys B1): Die drei Deckkraefte des eingebauten Schleiers sind jetzt
     Stellschrauben. Die Vorgaben sind EXAKT die bisherigen festen Werte
     (0.62 / 0.48 / 0.82) — ohne gesetzte Variable rendert die Zeile pixelgleich.
     Gesetzt werden sie als Inline-Variablen an .hp-hero (hero.blade.php), nur
     wenn im Hero-Bedienfeld ein eigener Wert steht. */
  background: linear-gradient(180deg, rgba(10, 10, 12, var(--hp-hero-schleier-oben, 0.62)) 0%, rgba(10, 10, 12, var(--hp-hero-schleier-mitte, 0.48)) 40%, rgba(10, 10, 12, var(--hp-hero-schleier-unten, 0.82)) 100%);
}
/* KAP. 240 (Andys B4b): die HOEHE der Marken-Zeile — ein BAUSTEIN-Regler wie
   marke.groesse, deshalb HIER und nicht in der Look-Datei (der Look-Waechter
   verlangt dort zu Recht eine Attribut-Bindung). Das Merkmal data-hp-marke-hoehe
   setzt hero.blade.php NUR bei gesetztem cfg-Wert `marke.hoehe`; ohne Wert
   existiert weder Merkmal noch Variable und es gilt das heutige Mass (geerbte
   line-height 1.6). Das Element .hp-hero__marke entsteht ohnehin nur bei aktiver
   Look-Vorlage (HomepageLook::heroMarke) — bei Mandanten ohne Look trifft die
   Regel nichts. Keine konkurrierende line-height-Regel in beiden CSS-Dateien,
   die Lade-Reihenfolge ist damit egal. */
.hp-hero[data-hp-marke-hoehe] .hp-hero__marke {
  line-height: var(--hp-marke-hoehe);
}
/* Feinschliff-Runde 1 (P4): Titel mittiger im Hero, Datum+Stadt darunter unten rechts. */
.hp-hero__in {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1440px;
  margin: 0 auto;
  padding: 130px 32px 64px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 24px;
}
.hp-hero__in .hp-h1 { margin-top: auto; margin-bottom: auto; }
/* Datum-Block: KLEIN, gesperrt, links- und rechtsbuendig zur Stadtbreite.
   inline-block => Blockbreite = Stadtwort; das Datum wird darauf gesperrt (justify). */
.hp-hero__event { text-align: left; display: inline-block; align-self: flex-end; }
.hp-hero__date {
  display: block;
  font-size: clamp(15px, 1.8vw, 26px);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brand); /* Feinschliff-Runde 1 (P5): Brand-Rot statt Weiss (Andy-Entscheidung) */
  text-align: justify;
  text-align-last: justify;
  margin-bottom: 6px;
}
.hp-hero__city {
  display: block;
  font-family: var(--hp-fonth, var(--hp-fontt, var(--font)));
  font-size: clamp(44px, 6vw, 86px);
  font-weight: 900;
  letter-spacing: calc(-0.025em + var(--hp-trackadd, 0em));
  line-height: calc(1 + var(--hp-lineadd, 0));
  text-transform: uppercase;
}

/* kleiner Seiten-Hero (FAQ / Ueber uns) */
.hp-hero--page { min-height: 46vh; align-items: center; text-align: center; }
.hp-hero--page .hp-hero__in { justify-content: center; align-items: center; padding: 140px 24px 64px; }
.hp-hero--page .hp-hero__in .hp-h1 { margin: 0; }

/* ══ KAP. 255 — DIE BEZUGSRAHMEN FUERS FREIE STELLEN ════════════════════════
   Ein frei gesetzter Text bekommt `position:absolute` und zaehlt seine Prozente
   gegen den naechsten POSITIONIERTEN Vorfahren. Bis hierher hatte fast kein
   Baustein einen — der Text waere auf `<body>` gesprungen und irgendwo auf der
   Seite gelandet. Genau diese Falle hat in Kap. 252 Zeit gekostet und steht in
   hero.blade.php ausgeschrieben.

   🔴 WARUM DAS HIER RISIKO TRAEGT UND DER A/B ES NICHT FINDET: CSS aendert kein
   einziges HTML-Zeichen. Der Byte-Beweis bleibt gruen, auch wenn sich das BILD
   verschiebt. Diese Zeilen sind darum ausdruecklich Sache des Bild-Waechters.

   Was sie tun koennen: `position:relative` erzeugt einen neuen Stapel-Kontext.
   Ein absolut gesetztes Kind, das heute gegen einen HOEHEREN Vorfahren zaehlt,
   zaehlte danach gegen diesen Kasten. Nachgesehen: alle absolut gesetzten
   Elemente dieses Stylesheets (19 Stueck) sitzen bereits in einem eigenen
   positionierten Kasten — Hero, Event-Karte, Dozenten-Karte, Lightbox, Video.
   Keines haengt an einem der Kaesten hier. Belegt wird das trotzdem am Bild,
   nicht an dieser Aufzaehlung. */
.hp-section, .hp-container, .hp-section__head { position: relative; }
/* Die Kaesten INNERHALB eines Abschnitts, in denen einzelne Texte sitzen. Ein
   Kachel-Titel soll in SEINER Kachel wandern, nicht ueber den ganzen Abschnitt —
   sonst zieht der Bediener ihn aus seiner Karte heraus und wundert sich.
   `.hp-stat` und `.hp-bt__t` hatten bisher gar keine eigene Regel. */
.hp-card, .hp-avatar, .hp-pricecard, .hp-ctablock,
.hp-faq details, .hp-stat, .hp-bt__t, .hp-footer { position: relative; }
/* KAP. 256: der Kasten eines Countdown-Zaehlers. Zahl und Zeiteinheit sollen in
   IHREM Kasten wandern, nicht ueber das ganze Band aus vier Kaesten.
   `.hp-countdown__k` hatte bisher keine Position; in ihm sitzt kein einziges
   absolut gesetztes Element (nachgesehen: `b` ist `display:block`, `span` ist
   inline, beide im Fluss) — es kann also nichts an ihm haengenbleiben. */
.hp-countdown__k { position: relative; }
/* KAP. 258: der Umschalt-Kasten einer Stadt auf der Preis-Seite. Was zu EINER Stadt
   gehoert (Planungs-Text, Gruppen-Hinweis), soll in IHREM Kasten wandern und nicht
   ueber die ganze Seite. `[data-stadt-panel]` ist ein funktionaler Anker — das Skript
   schaltet daran um —, keine Kosmetik, die jemand wegraeumt.
   Er traegt kein absolut gesetztes Kind: die Preis-Karten und der Hinweis stehen im
   Fluss (nachgesehen, nicht angenommen). Kein Pixel bewegt: /root/abgabe/k258/beweise/. */
[data-stadt-panel] { position: relative; }
/* KAP. 258: der Preis einer Karte. Der ALTE Preis sitzt als `<span>` IN ihm — derselbe
   Fall wie Zeile 2 im Aufruf-Band (Kap. 256). Ohne diese Zeile haengt der alte Preis
   an `.hp-pricecard`, SOLANGE der Preis nicht gezogen ist, und springt danach an den
   Preis-Kasten: der Bezugsrahmen haenge also davon ab, ob ein ANDERER Regler benutzt
   wurde. Kein absolut gesetztes Kind ausser diesem; kein Pixel bewegt (nachgemessen). */
.hp-pricecard__price { position: relative; }
/* KAP. 259: der Block-Kasten des Bausteins `abschnitte`. Die Klasse ist NEU — bis
   heute trug der Kasten keine (Andys Entscheidung M1/A, 22.08.2026). Ueberschrift und
   Text sollen in IHREM Block wandern; ohne Anker haetten sie gegen den ganzen
   Container gezaehlt und waeren, weil EIN Reglersatz fuer ALLE Bloecke gilt, beim
   ersten Ziehen uebereinandergerutscht.
   🔴 SIE TRAEGT AUSSCHLIESSLICH DIE POSITION, kein Aussehen: der Kasten sieht danach
   Pixel fuer Pixel aus wie vorher (nachgemessen, /root/abgabe/k259/beweise/).
   Der Aufruf-Kasten braucht dazu seine Ueberschrift als Rahmen — Zeile 2 sitzt als
   `<span class="rot">` darin, derselbe Fall wie im Aufruf-Band des Events (Kap. 256). */
.hp-abschnitt { position: relative; }
.hp-ctablock .hp-h2 { position: relative; }
/* KAP. 256: die Ueberschrift des dunklen Aufruf-Bandes. Sie ist der einzige Text im
   Haus, in dem ein ZWEITER beweglicher Text sitzt — `event_cta` setzt Zeile 2 als
   `<span>` in den `<h2>` von Zeile 1 (Markup seit Kap. 242). Ohne diese Zeile haengt
   Zeile 2 an `.hp-container`, SOLANGE Zeile 1 nicht gezogen ist, und springt danach an
   den `<h2>`: der Bezugsrahmen haenge also davon ab, ob ein ANDERER Regler benutzt
   wurde. Mit ihr ist der `<h2>` immer der Rahmen, und der Katalog kann ihn nennen.

   🔴 WARUM NICHT `.hp-h2` GANZ ALLGEMEIN — gemessen, nicht befuerchtet: mit der
   allgemeinen Fassung war die STARTSEITE ein anderes Bild (`/root/k256_bild.js`,
   Vollbild-Foto, Byte-Vergleich). Die Geometrie war identisch, die MALREIHENFOLGE
   nicht: ein positioniertes Element wird spaeter gemalt als ein Kasten im Fluss und
   deckt damit ab, was es vorher nicht abgedeckt hat. Deshalb genau der eine Kasten,
   in dem der Fall auftritt — nachgewiesen ueber alle zwoelf Seiten.

   Der Doppel-Selektor trifft zwei Stellen mit demselben Markup: den Baustein
   `event_cta` und den Alt-Weg in `event.blade.php` (Z. 182). `stats` benutzt dieselben
   zwei Klassen an einem `<div>` und hat keine `.hp-h2` — dort greift die Regel nicht. */
.hp-section--dark.hp-skew .hp-h2 { position: relative; }

/* ---------- Sektionen ---------- */
.hp-section { padding: 96px 0; }
.hp-section--soft { background: var(--bg-soft); }
.hp-section--dark { background: var(--dark); color: #fff; }
.hp-section__head { margin-bottom: 48px; }

/* leichte Schraegkante (Vorlage) */
.hp-skew { transform: skewY(-1.6deg); }
.hp-skew > .hp-unskew { transform: skewY(1.6deg); }

/* ---------- Karten ---------- */
.hp-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; }
.hp-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 28px; }
/* KAP. 217: nur das Event-Karten-Raster ist in der Spaltenzahl einstellbar.
   Steht die Schraube nicht, sind es 3 — identisch zu .hp-grid-3. Die Regel steht
   NACH .hp-grid-3 (gleiche Spezifitaet, spaeter gewinnt) und VOR der Handy-Regel,
   damit am Handy weiterhin eine Spalte bleibt. */
.hp-evgrid { grid-template-columns: repeat(var(--evk-cols, 3), 1fr); }
@media (max-width: 900px) { .hp-grid-3, .hp-grid-2, .hp-evgrid { grid-template-columns: 1fr; } }

.hp-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 32px;
}
.hp-card--flat { box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); border: 0; }

/* ══ KAP. 262 (C.1) — DAS BILD FUELLT DIE KACHEL, DER TEXT LIEGT DARAUF ══════
   Bis hierher stand der Text einer Kachel IMMER unter dem Bild: das `<img>` ist
   das erste Kind im Fluss, danach Ueberschrift und Text. Der Kommentar in
   kachel_reihe.blade.php sagte es selbst — „KEIN freies Ziehen: der Text der
   Kacheln steht UNTER dem Bild, nicht darauf".

   Ziehen konnte man die Texte schon seit Kap. 255 (Rahmen `.hp-card`) — nur gab
   es nichts, worauf sie haetten wandern koennen. Diese Klasse liefert das:
   dieselbe Bauform, die sich an der Event-Karte bewaehrt hat (Z. 516 ff.) —
   Bild absolut ueber die volle Flaeche, Abdunkler darueber, Text obenauf.

   🔴 SIE ENTSTEHT NUR, WENN DER KUNDE SIE EINSCHALTET. Ohne den Schalter
   „Bild fuellt die Kachel" traegt keine Karte diese Klasse, und an keiner
   bestehenden Seite aendert sich ein Zeichen. `.hp-card` selbst bleibt
   unangetastet — insbesondere bekommt es KEIN `overflow:hidden`, das haette
   jede Karte im Haus betroffen. */
.hp-card--bildfuellt {
  position: relative;
  overflow: hidden;
  border: 0;
  color: #fff;
  min-height: var(--kb-hoehe, 260px);
}
.hp-card--bildfuellt > .hp-card__bild {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
/* Der Abdunkler. Ohne ihn ist heller Text auf hellem Foto unlesbar — dieselbe
   Lehre wie bei der Event-Karte, wo er seit Kap. 217 fest eingebaut ist. */
.hp-card--bildfuellt::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 35%, rgba(0, 0, 0, var(--kb-dim, 0.72)) 100%);
}
/* Ueber den Abdunkler — und `position:relative`, damit die z-Ebene ueberhaupt
   zaehlt. Ein frei gezogener Text wird von `freiStil()` auf `absolute` gesetzt
   und behaelt seine z-Ebene dabei. */
.hp-card--bildfuellt > h3,
.hp-card--bildfuellt > p {
  position: relative;
  z-index: 2;
}
.hp-card--bildfuellt > p { color: rgba(255, 255, 255, 0.82) !important; }

/* Event-Karte (Foto, unten Text) */
/* KAP. 217 — die Event-Karten sind einstellbar geworden. Jede Stellschraube traegt
   als Rueckfall exakt den Wert, der vorher fest hier stand: ohne Eingabe rendert die
   Karte Pixel fuer Pixel wie bisher. Die Werte setzt der Baustein als style am
   <section> (event_karten.blade.php), damit zwei Event-Karten-Abschnitte auf einer
   Seite sich nicht gegenseitig ueberschreiben. */
.hp-eventcard {
  position: relative;
  border-radius: var(--evk-radius, var(--radius-card));
  overflow: hidden;
  aspect-ratio: var(--evk-ratio, 4 / 4.4);
  display: block;
  background: var(--dark);
  color: var(--evk-col, #fff);
}
.hp-eventcard img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease; opacity: 0.92; }
.hp-eventcard:hover img { transform: scale(1.04); }
.hp-eventcard::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0, 0, 0, 0) 45%, rgba(0, 0, 0, 0.78) 100%); }
/* KAP. 217: zusaetzliche Abdunklung — dieselbe Bauart wie beim Hero und beim
   Seiten-Kopfbild (R38). Die Ebene entsteht nur bei gesetztem Regler; z-index 1
   legt sie ueber Bild UND Verlauf, der Text (z-index 2) bleibt darueber. */
.hp-eventcard__dim { position: absolute; inset: 0; z-index: 1; }
.hp-eventcard__txt { position: absolute; z-index: 2; left: 24px; right: 24px; bottom: 22px; }
/* ══ KAP. 263 (C.3) — DER TEXTKASTEN ALS TRAGFAEHIGER BEZUGSRAHMEN ═══════════
   Stadt, Datum und Link teilten sich bis hierher EINEN Satz Regler: der Kasten
   liess sich verschieben, die drei Texte darin nicht einzeln.

   Der Grund war nicht Bequemlichkeit, sondern Geometrie — GEMESSEN:
   `.hp-eventcard__txt` ist so hoch wie sein Inhalt. Stellt man seine Kinder frei
   (`position:absolute`), faellt er zusammen:
       heute 90 px · nur die Stadt frei 49 px · Stadt+Datum 29 px · alle drei 0 px
   Bei Hoehe 0 rechnen alle Prozente gegen nichts, und jeder Text landet an
   derselben Stelle.

   🔴 DIESE KLASSE KOMMT NUR DAZU, WENN WIRKLICH EIN TEXT FREI STEHT. Dann
   spannt der Kasten von oben bis unten und ist ein stabiler Rahmen; die Kinder
   bleiben per Flex unten, wo sie heute schon stehen. Im Grundzustand traegt sie
   niemand — dort aendert sich kein Zeichen und kein Pixel.

   `align-items:flex-start` ist noetig, weil Flex seine Kinder sonst auf die
   volle Breite streckt: gemessen wuchs der Link-Text dabei von 125 auf 275 px. */
.hp-eventcard__txt--frei {
  top: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
}
.hp-eventcard__date { font-size: 12.5px; font-weight: 600; opacity: 0.85; }
.hp-eventcard__city { font-family: var(--hp-fonth, var(--hp-fontt, var(--font))); font-size: var(--evk-city, 26px); font-weight: 900; letter-spacing: calc(-0.02em + var(--hp-trackadd, 0em)); }
.hp-eventcard__more { font-size: 13.5px; font-weight: 700; margin-top: 6px; display: inline-block; }
.hp-eventcard__more .arr { display: inline-block; transition: transform 0.15s; }
.hp-eventcard:hover .hp-eventcard__more .arr { transform: translateX(3px); }

/* Dozenten-Fotokachel (Event-Seite / Uebersicht) */
.hp-dzcard {
  position: relative;
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 4 / 4.6;
  background: var(--dark);
  color: #fff;
  display: block;
}
.hp-dzcard img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top center; transition: transform 0.4s ease; }
.hp-dzcard:hover img { transform: scale(1.05); }
.hp-dzcard::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.75) 100%); }
.hp-dzcard__txt { position: absolute; z-index: 2; left: 20px; bottom: 16px; right: 20px; }
.hp-dzcard__name { font-family: var(--hp-fonth, var(--hp-fontt, var(--font))); font-weight: 800; font-size: 19px; }
.hp-dzcard__style { font-size: 12.5px; opacity: 0.8; }

/* runder Avatar (Startseite) */
.hp-avatar { text-align: center; }
.hp-avatar__img {
  width: min(184px, 100%); height: auto; /* Feinschliff-Runde 1 (P6): deutlich groesser */
  aspect-ratio: 1;
  border-radius: 50%;
  object-fit: cover;
  object-position: top center;
  margin: 0 auto 14px;
}
.hp-avatar__name { font-weight: 700; font-size: 14.5px; }
.hp-avatar__style { font-size: 12.5px; color: var(--ink-faint); }
.hp-avatars { display: grid; grid-template-columns: repeat(6, 1fr); gap: 20px; }
/* KAP. 210 (09.08.2026) — Form der Trainer-Bilder waehlbar. OHNE Klasse bleibt es
   rund wie bisher; die Grundregel oben wird nicht angefasst. */
.hp-avatars--form-abgerundet .hp-avatar__img { border-radius: 18px; }
.hp-avatars--form-eckig .hp-avatar__img { border-radius: 0; }
@media (max-width: 900px) { .hp-avatars { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) { .hp-avatars { grid-template-columns: repeat(2, 1fr); } }
/* XL-Variante fuer die Dozenten-Uebersicht (Feinschliff-Runde 1, P6) */
.hp-avatars--xl { grid-template-columns: repeat(4, 1fr); gap: 32px; row-gap: 44px; }
.hp-avatars--xl .hp-avatar__img { width: min(248px, 100%); }
.hp-avatars--xl .hp-avatar__name { font-size: 17px; }
.hp-avatars--xl .hp-avatar__style { font-size: 13.5px; }
@media (max-width: 900px) { .hp-avatars--xl { grid-template-columns: repeat(2, 1fr); } }

/* Video-Embeds Dozenten-Einzelseite (Feinschliff-Runde 1, P7) */
.hp-videos { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; margin-top: 28px; }
@media (max-width: 800px) { .hp-videos { grid-template-columns: 1fr; } }
.hp-video { border-radius: var(--radius-card); overflow: hidden; background: #000; }
.hp-video iframe { display: block; width: 100%; height: 100%; border: 0; }
.hp-video--yt { aspect-ratio: 16 / 9; }
.hp-video--ig { aspect-ratio: 4 / 5; max-width: 420px; }

/* Preis-Karte */
.hp-pricecard {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 34px 30px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.06);
  display: flex;
  flex-direction: column;
}
.hp-pricecard--dark { background: var(--dark); color: #fff; border-color: var(--dark); }
.hp-pricecard__tag { font-size: 13px; font-weight: 700; color: var(--brand); margin-bottom: 10px; }
.hp-pricecard__price { font-family: var(--hp-fonth, var(--hp-fontt, var(--font))); font-size: 52px; font-weight: 900; letter-spacing: calc(-0.03em + var(--hp-trackadd, 0em)); line-height: 1; margin-bottom: 8px; }
.hp-pricecard__old { font-size: 17px; font-weight: 600; color: var(--ink-faint); text-decoration: line-through; margin-left: 8px; }
.hp-pricecard ul { margin: 18px 0 26px; display: grid; gap: 10px; }
.hp-pricecard li { font-size: 14.5px; display: flex; gap: 10px; align-items: baseline; }
.hp-pricecard li::before { content: "✓"; color: var(--brand); font-weight: 800; }
.hp-pricecard .hp-btn { margin-top: auto; justify-content: center; }
.hp-badge {
  display: inline-block;
  background: var(--brand);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  border-radius: 999px;
  padding: 4px 12px;
  margin-bottom: 12px;
  width: fit-content;
}

/* Info-Kachel (klein, grau) */
.hp-tile { background: var(--bg-soft); border-radius: 14px; padding: 18px 12px; text-align: center; }
.hp-tile b { display: block; font-size: 19px; color: var(--brand); }
.hp-tile span { font-size: 12px; color: var(--ink-soft); }

/* ---------- Stats-Band ---------- */
.hp-stats { display: grid; grid-template-columns: repeat(var(--cols, 4), 1fr); gap: 24px; text-align: center; }
@media (max-width: 700px) { .hp-stats { grid-template-columns: repeat(2, 1fr); } }
.hp-stat b { display: block; font-family: var(--hp-fonth, var(--hp-fontt, var(--font))); font-size: clamp(34px, 4vw, 48px); font-weight: 900; color: var(--brand); letter-spacing: calc(-0.02em + var(--hp-trackadd, 0em)); }
.hp-stat span { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.75; }

/* ---------- FAQ-Akkordeon ---------- */
.hp-faq { max-width: 720px; margin: 0 auto; }
.hp-faq details { border-bottom: 1px solid var(--line); }
.hp-faq summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 22px 4px;
  font-weight: 600;
  font-size: 16px;
}
.hp-faq summary::-webkit-details-marker { display: none; }
.hp-faq summary::after { content: "+"; font-size: 22px; font-weight: 400; color: var(--ink-faint); transition: transform 0.2s; }
.hp-faq details[open] summary::after { transform: rotate(45deg); }
.hp-faq .a { padding: 0 4px 22px; color: var(--ink-soft); font-size: 15px; white-space: pre-wrap; }

/* ---------- CTA-Block ---------- */
.hp-ctablock {
  background: var(--dark);
  color: #fff;
  border-radius: var(--radius-card);
  padding: clamp(48px, 7vw, 88px) 32px;
  text-align: center;
}
.hp-ctablock .hp-h2 { margin-bottom: 14px; }
.hp-ctablock p { color: rgba(255, 255, 255, 0.7); margin-bottom: 28px; }
.hp-ctablock .rot { color: var(--brand); }

/* ══ KAP. 262 (C.2) — DER TEXT DARF AUF DAS HINTERGRUNDBILD ══════════════════
   Der Aufruf-Baustein kennt seit jeher ein Hintergrundbild — es liegt am
   `<section>`. Sichtbar war davon aber nur der Rand: `.hp-ctablock` traegt einen
   DECKENDEN `background: var(--dark)` und legt sich genau ueber die Flaeche, auf
   der der Text steht. Der Kommentar in cta.blade.php sagte es selbst — „der Text
   steht hier nicht auf einem Bild, sondern im dunklen Kasten".

   Diese Klasse nimmt den deckenden Grund zurueck und ersetzt ihn durch einen
   Abdunkler, durch den das Bild sichtbar bleibt. Der Text liegt danach auf dem
   Bild statt daneben — und `cta.text` kann mit seinem vorhandenen Zieh-Rahmen
   `.hp-ctablock` frei darauf wandern.

   🔴 SIE ENTSTEHT NUR MIT SCHALTER UND BILD. Auf Andys Seite ist
   `hintergrund.bild` ein leerer Text; dort greift der Zweig auch dann nicht,
   wenn der Schalter an waere. `.hp-ctablock` selbst bleibt unangetastet. */
.hp-ctablock--bildfuellt {
  background: linear-gradient(rgba(10, 10, 12, var(--cta-dim, 0.55)), rgba(10, 10, 12, var(--cta-dim, 0.55)));
  position: relative;
  overflow: hidden;
}

/* ---------- Footer ---------- */
.hp-footer { position: relative; border-top: 1px solid var(--line); padding: 64px 0 40px; overflow: hidden; background: #fff; }
.hp-footer__wm {
  position: absolute;
  right: 4%; top: -8%;
  height: 130%;
  opacity: 0.05;
  pointer-events: none;
}
.hp-footer__grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 40px; position: relative; z-index: 2; }
@media (max-width: 800px) { .hp-footer__grid { grid-template-columns: 1fr; } }
.hp-footer__logo img { height: 46px; margin-bottom: 14px; }
.hp-footer p, .hp-footer a { font-size: 14px; color: var(--ink-soft); }
.hp-footer h4 { font-size: 13px; font-weight: 700; margin-bottom: 14px; color: var(--ink); }
.hp-footer li { margin-bottom: 9px; }
.hp-footer a:hover { color: var(--brand); }
.hp-social { display: flex; gap: 10px; margin-top: 18px; }
.hp-social a {
  width: 38px; height: 38px;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
}
.hp-copy { position: relative; z-index: 2; margin-top: 44px; font-size: 12.5px; color: var(--ink-faint); }

/* ---------- Diverses ---------- */
.hp-imgsplit { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 56px; align-items: center; }
/* KAP. 260: Bezugsrahmen fuer die drei Texte des Event-Intros. Die Textspalte selbst
   ist ein <div> OHNE Klasse — eine neue haette ein Byte gekostet, das nicht bestellt war;
   der Zweispalter tut es genauso, und der Text darf dann auch ueber das Bild wandern.
   Kein absolut gesetztes Kind darin (nachgesehen), kein Pixel bewegt. */
.hp-imgsplit { position: relative; }
@media (max-width: 900px) { .hp-imgsplit { grid-template-columns: 1fr; } }
.hp-imgsplit img { border-radius: var(--radius-card); aspect-ratio: 3 / 3.6; object-fit: cover; width: 100%; }

.hp-toggle { display: inline-flex; background: var(--bg-soft); border-radius: 999px; padding: 5px; gap: 4px; }
.hp-toggle button {
  border: 0;
  background: transparent;
  padding: 10px 22px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 14px;
  color: var(--ink-soft);
  cursor: pointer;
  font-family: var(--hp-fontt, var(--font));
}
.hp-toggle button.active { background: var(--dark); color: #fff; }

.hp-note { text-align: center; font-size: 13.5px; color: var(--ink-soft); margin-top: 28px; }
.hp-note .dot { color: var(--brand); }

.hp-backlink { display: inline-flex; gap: 8px; font-size: 14px; color: var(--ink-soft); margin: 96px 0 24px; }
.hp-backlink:hover { color: var(--brand); }

/* Galerie (Dozenten-Einzelseite) */
.hp-gallery { columns: 3; column-gap: 24px; }
@media (max-width: 800px) { .hp-gallery { columns: 2; } }
.hp-gallery > * { break-inside: avoid; margin-bottom: 24px; border-radius: var(--radius-card); overflow: hidden; }

/* Chips */
.hp-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 8px 16px;
  font-size: 13.5px;
  font-weight: 600;
}

/* ═══════════════════════════════════════════════════════════════════════════
   STUFE 5 (27.07.2026) — die neuen Bausteine
   Alles neue Klassen; an den bestehenden Regeln aendert sich nichts.
   Handy: Galerie und Bild-Text klappen auf EINE Spalte, die Logo-Reihe bricht um.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---------- Galerie ---------- */
.hp-gal { display: grid; grid-template-columns: repeat(var(--cols, 3), 1fr); gap: 14px; }
.hp-gal__i { margin: 0; overflow: hidden; border-radius: 12px; background: var(--bg-soft); }
.hp-gal__i img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; transition: transform 0.35s ease; }
.hp-gal__i:hover img { transform: scale(1.04); }
.hp-gal[data-lb] .hp-gal__i { cursor: zoom-in; }

/* Grossansicht (nur wenn im Baustein eingeschaltet) */
.hp-lb { position: fixed; inset: 0; z-index: 200; background: rgba(10, 10, 12, 0.93);
  display: flex; align-items: center; justify-content: center; padding: 28px; }
.hp-lb img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 8px; }
.hp-lb__x { position: absolute; top: 12px; right: 18px; width: 40px; height: 40px; border: 0;
  background: none; color: #fff; font-size: 30px; line-height: 1; cursor: pointer; }

/* ---------- Partner-/Logo-Reihe ---------- */
.hp-logos { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 28px 44px; }
.hp-logos__i { display: flex; align-items: center; }
.hp-logos img { height: var(--logoh, 48px); width: auto; max-width: 100%; object-fit: contain;
  filter: grayscale(1); opacity: 0.62; transition: filter 0.2s ease, opacity 0.2s ease; }
.hp-logos__i:hover img { filter: grayscale(0); opacity: 1; }

/* ---------- Video ---------- */
.hp-video { position: relative; width: 100%; aspect-ratio: 16 / 9; overflow: hidden;
  border-radius: 14px; background: #000; }
.hp-video iframe, .hp-video video { position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; display: block; object-fit: cover; }

/* ---------- Trenner ---------- */
.hp-trenner__l { height: 1px; background: var(--line); }

/* ---------- Bild-Text-Split ---------- */
.hp-bt { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: center; }
.hp-bt__b img { width: 100%; border-radius: 16px; display: block; }
.hp-bt__t .hp-lead { max-width: none; }

/* ---------- Handy ---------- */
@media (max-width: 860px) {
  .hp-gal { grid-template-columns: repeat(2, 1fr); }
  .hp-bt { grid-template-columns: 1fr; gap: 26px; }
}
@media (max-width: 640px) {
  .hp-gal { grid-template-columns: 1fr; gap: 12px; }
  .hp-logos { gap: 22px 28px; }
  .hp-lb { padding: 14px; }
}

/* ── Kap. 201: Hochkant-Player (Instagram, TikTok) ──────────────────────────────
   Die allgemeine Regel `.hp-video { aspect-ratio: 16/9 }` weiter oben in dieser Datei
   ueberschrieb das 4:5 der Hochkant-Kachel: gleiche Staerke, aber spaeter notiert.
   Folge (gemessen 07.08.2026): Kachel 420x236 statt 420x525 — Hochkant-Videos wurden
   auf Querformat gequetscht. Zwei Klassen statt einer gewinnen den Vergleich. */
.hp-videos .hp-video--ig { aspect-ratio: 4 / 5; max-width: 420px; }

/* ---------- Laufband (KAP. 222, 11.08.2026) ----------
   Ein eigener Baustein. Diese Regeln kosten kein einziges Zeichen im HTML, solange
   niemand das Laufband einfuegt — es gibt den Baustein dann schlicht nicht.
   Jede Stellschraube hat den Wert der Vorlage als Rueckfall; ohne Eingabe im
   Bedienfeld sieht das Band aus wie in V9.
   Warum der Inhalt doppelt im HTML steht: die Zeile schiebt sich um genau die
   Haelfte ihrer Breite — nur so springt beim Neubeginn nichts. */
.hp-laufband {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--lb-bg, var(--bg-soft));
  overflow: hidden;
  padding: 16px 0;
}
.hp-laufband__zeile {
  display: flex;
  white-space: nowrap;
  animation: hp-lauf var(--lb-dauer, 38s) linear infinite;
}
.hp-laufband span {
  font-size: var(--lb-size, 12.5px);
  letter-spacing: 0.32em;
  font-weight: 800;
  color: var(--lb-col, var(--ink-soft));
  text-transform: uppercase;
  padding-right: 36px;
}
@keyframes hp-lauf {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
/* Wer weniger Bewegung eingestellt hat, bekommt ein stehendes Band statt gar keines. */
@media (prefers-reduced-motion: reduce) {
  .hp-laufband__zeile { animation: none; }
}

/* ---------- Untermenü am Handy (KAP. 222 / Paket 4, 11.08.2026) ----------
   Den Knopf setzt das Skript ein (homepage.js) — deshalb steht er nicht im HTML und
   die Seiten bleiben byte-gleich. Am großen Bildschirm ist er unsichtbar: dort öffnet
   das Menü weiterhin beim Darüberfahren. */
.hp-drop__auf { display: none; }
@media (max-width: 900px) {
  .hp-drop { display: flex; flex-wrap: wrap; align-items: center; }
  .hp-drop > a { flex: 1 1 auto; }
  .hp-drop__auf {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Groß genug zum Treffen mit dem Daumen — kleiner wäre am Telefon Glückssache. */
    width: 44px;
    height: 44px;
    background: none;
    border: 0;
    padding: 0;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    color: var(--hp-navcol, var(--ink));
    transition: transform 0.2s ease;
  }
  /* Zugeklappt ist der neue Normalzustand — vorher stand die Liste immer offen.
     ABER nur, wenn das Skript gelaufen ist und den Knopf gesetzt hat: sonst wäre das
     Untermenü am Handy gar nicht mehr erreichbar. Dieselbe Absicherung wie bei den
     Look-Effekten — ein Ausfall des Skripts darf nie etwas unbedienbar machen. */
  body.hp-drop-js .hp-drop .hp-drop__menu { display: none; }
  body.hp-drop-js .hp-drop--offen .hp-drop__menu { display: block; }
  .hp-drop--offen .hp-drop__auf { transform: rotate(180deg); }
  .hp-drop__menu { flex: 1 0 100%; }
}

/* ---------- Countdown (KAP. 222, 11.08.2026) ----------
   Wie das Laufband ein eigener Baustein: ohne Einfuegen kein Zeichen im HTML.
   Steht kein Camp an, rendert der Baustein gar nichts — dann ist auch hier nichts. */
.hp-countdown { padding: 86px 0; text-align: center; border-bottom: 1px solid var(--line); }
.hp-countdown__lbl {
  font-size: 11.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brand);
  font-weight: 800;
  margin-bottom: 24px;
}
.hp-countdown__g { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.hp-countdown__k {
  min-width: 132px;
  padding: 22px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--bg-soft);
}
.hp-countdown__k b {
  display: block;
  font-family: var(--hp-fonth, var(--hp-fontt, var(--font)));
  font-size: 44px;
  font-weight: 900;
  letter-spacing: calc(-0.035em + var(--hp-trackadd, 0em));
  /* Gleich breite Ziffern: ohne das zappelt der Kasten bei jedem Sekundenwechsel. */
  font-variant-numeric: tabular-nums;
}
.hp-countdown__k span {
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
@media (max-width: 560px) { .hp-countdown__k { min-width: 40%; padding: 16px 10px; } }

/* ---------- Getippte Leerzeichen bleiben stehen (KAP. 236, 18.08.2026) ----------
   Wer zwei Leerzeichen tippt, soll zwei sehen. `normal` faltet jede Folge von
   Leerzeichen zu genau einem zusammen; `pre-wrap` behaelt sie und bricht die
   Zeile trotzdem weiter um.

   WARUM ALS KLASSENREGEL UND NICHT INLINE: ein Inline-Stil muesste bedingungslos
   an JEDEM Textelement stehen — sonst wirkte er nie. Damit stuende an jedem
   Element ein `style`, wo heute keines steht, und die eiserne Bedingung „nicht
   gesetzt = kein Zeichen im HTML" fiele fuer null sichtbaren Gewinn. Diese Regel
   aendert kein Byte im gerenderten HTML.

   DIE LISTE IST ABGELEITET, NICHT GETIPPT.
   Quelle: App\Support\HomepageTextStil::katalog(), Feld `sel` jedes Eintrags
   (52 Eintraege -> 23 verschiedene Selektoren), erzeugt am 18.08.2026.
   Kommt ein Katalog-Eintrag dazu, gehoert sein `sel` hierher. Eine von Hand
   gepflegte Liste veraltet beim naechsten Eintrag — daran ist in Kap. 228 schon
   einmal ein Katalog gestorben.
   Zusaetzlich drin, weil ohne Katalog-Eintrag: `.hp-h1`.

   BEWUSST DRAUSSEN: `.hp-social a` (Katalog-Eintrag `footer.social`). Der
   Selektor trifft keinen Text, sondern einen KASTEN — darin steckt ein <svg>
   und die Einrueckung des Quelltextes. Die Regel gehoert ans Textelement, nie
   an den Kasten: sonst wuerde Quell-Einrueckung sichtbar. (Gemessen bleibt der
   Kasten heute bei 38x38 px, weil er ein Flex-Kasten fester Groesse ist — diese
   Rettung ist Zufall und traegt keine Regel.)

   NICHT ANGEFASST: die vier `white-space: pre-line` als INLINE-Stil in
   homepage/dozent.blade.php:21 und homepage/event.blade.php:28,124,129. Dort
   haengen 5 Trainer-Biografien mit Mehrfach-Leerzeichen. Inline schlaegt diese
   Klassenregel ohnehin — die Biografien bleiben, wie sie sind.

   GEMESSEN vor dem Einbau (getBoundingClientRect JEDES Elements, 31 oeffentliche
   Seiten beider Mandanten, 1280 px und 600 px mit aufgeklappter Kopfleiste,
   Grund-Look und V9): 0 Elemente bewegen sich. Nullprobe 0; Kontrolle
   `.hp-container` (ein Kasten) bewegt 2266 — der Messer wird also rot, wenn
   sich wirklich etwas verschiebt. */
.hp-avatar__name,
.hp-avatar__style,
.hp-card h3,
.hp-card p,
.hp-ctablock p,
.hp-drop__menu .soon,
.hp-drop__menu a,
.hp-eyebrow,
.hp-faq .a,
.hp-faq summary,
.hp-footer h4,
.hp-footer ul li a,
.hp-footer__logo p:first-of-type,
.hp-footer__logo p:nth-of-type(2),
.hp-h1,
.hp-hero__city,
.hp-hero__date,
.hp-lead,
.hp-nav a,
.hp-nav a.hp-cta,
.hp-stat b,
.hp-stat span,
h2 {
  white-space: pre-wrap;
}

/* ---------- KAP. 245 — EINEN EINZELNEN TEXT AM HANDY VERSTECKEN ----------
   Gegenstueck zu `App\Support\HomepageTextStil::handy()`. Das Attribut steht
   NUR an einem Element, an dem jemand den Schalter umgelegt hat; ohne
   Umlegen entsteht es nicht, und dann trifft diese Regel nichts. Sie aendert
   darum kein Byte am gerenderten HTML — was sie aendert, ist ausschliesslich
   das Verhalten der Elemente, die den Merker tragen.

   WARUM DIESE REGEL UEBERHAUPT IM STYLESHEET STEHT UND NICHT AM ELEMENT:
   „nur am Handy verstecken" braucht eine BEDINGUNG (`@media`). Ein
   `style`-Attribut kennt keine Bedingungen, nur Werte — dort liesse sich das
   nicht ausdruecken. Ein `display:none`, das immer gilt, waere das Gegenteil
   des Gewuenschten.

   DIE GRENZE IST NICHT GEWAEHLT, SIE IST NACHGESCHLAGEN: 640 px ist
   `App\Support\HomepageBaustein::HANDY_BIS` — dieselbe Zahl, mit der schon
   `mobilCss()` seine Handy-Regeln baut und mit der die drei bestehenden
   Handy-Baender dieser Datei schalten (Z. 323, 337, 704). Eine zweite Grenze
   waere ein zweiter Weg fuer dieselbe Sache (R38); wer sie hier aendert, muss
   sie dort mitaendern. `/root/k245_stil_probe.php`, Teil D, haelt beide Zahlen
   gegeneinander und wird rot, wenn sie auseinanderlaufen.

   `!important`, weil die bereglerten Texte ihre Werte als INLINE-Stil tragen
   (`HomepageTextStil::attr()`) — und einzelne Vorlagen dort auch `display`
   setzen (z. B. das `display:block` an den Hinweiszeilen). Ohne `!important`
   gewaenne der Inline-Stil, und der Schalter liesse sich umlegen, ohne dass
   etwas passiert. */
@media (max-width: 640px) {
  [data-hp-handy="aus"] { display: none !important; }
}

/* ---------- Kontaktformular (KAP. 265 / ENDSPURT D.1) ----------
   Der erste Baustein mit einem Formular. Ohne Einfuegen entsteht kein Zeichen im
   HTML — wie bei jedem anderen Baustein auch.

   🔴 KEINE FESTE FARBE, KEINE FESTE SCHRIFT. Alles kommt aus denselben
   Stellschrauben wie ueberall (`--line`, `--brand`, `--ink-soft`, `--bg-soft`,
   `--radius-card`). Ein Formular, das seine eigenen Farben mitbraechte, saehe
   bei jedem zweiten Mietkunden fremd aus.

   🔴 DIE EINGABEFELDER BEKOMMEN 16px SCHRIFT — MIT ABSICHT. Alles darunter
   laesst iOS beim Antippen in das Feld hineinzoomen, und der Besucher steht
   danach mit verschobener Seite da. Das ist kein Gestaltungswunsch, das ist die
   Grenze, ab der Safari eingreift. */
.hp-kontakt { padding: 86px 0; border-bottom: 1px solid var(--line); }
/* Ueberschrift und Einleitung tragen `hp-h2` bzw. `hp-lead` — sie sehen damit
   aus wie in jedem anderen Baustein und folgen der Look-Vorlage. Die eigenen
   Klassen daneben stellen NUR den Abstand; eine eigene Schriftgroesse hier waere
   eine zweite Wahrheit neben dem Katalog. */
.hp-kontakt__title { margin: 0 0 12px; }
.hp-kontakt__intro { margin: 0 0 28px; }
.hp-kontakt__form { max-width: 640px; }
.hp-kontakt__feld { margin-bottom: 18px; }
.hp-kontakt__label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.hp-kontakt__pflicht { color: var(--brand); margin-left: 3px; }
.hp-kontakt__form input[type="text"],
.hp-kontakt__form input[type="email"],
.hp-kontakt__form input[type="tel"],
.hp-kontakt__form select,
.hp-kontakt__form textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: #fff;
  font: inherit;
  font-size: 16px;          /* s. Kopf — darunter zoomt iOS hinein */
  line-height: 1.45;
  color: inherit;
}
.hp-kontakt__form textarea { resize: vertical; min-height: 140px; }
.hp-kontakt__form input:focus-visible,
.hp-kontakt__form select:focus-visible,
.hp-kontakt__form textarea:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}
/* Der Haken steht NEBEN seiner Beschriftung, nicht darueber — sonst liest sich
   „Ich stimme zu" wie eine Ueberschrift ohne Bezug. */
.hp-kontakt__haken { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.hp-kontakt__haken input { margin-top: 3px; flex: 0 0 auto; }
.hp-kontakt__haken .hp-kontakt__label { margin: 0; font-weight: 400; font-size: 14px; }
.hp-kontakt__btn {
  display: inline-block;
  padding: 13px 26px;
  border: 0;
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.04em;
  cursor: pointer;
}
.hp-kontakt__btn:hover { filter: brightness(1.08); }
/* Bestaetigung und Fehler: dieselbe Bauform, andere Farbe. `role=status` bzw.
   `role=alert` stehen im Markup — ein Vorleser sagt sie damit von selbst an. */
.hp-kontakt__danke,
.hp-kontakt__fehler {
  padding: 16px 18px;
  border-radius: var(--radius-card);
  border: 1px solid var(--line);
  background: var(--bg-soft);
  max-width: 640px;
  line-height: 1.5;
}
.hp-kontakt__danke { border-color: var(--brand); }
.hp-kontakt__fehler { margin-bottom: 20px; border-color: #C0392B; color: #8E2A1F; }
/* KAP. 265: der Bezugsrahmen fuer die frei setzbaren Texte dieses Bausteins.
   `.hp-container` traegt bereits `position:relative` (Zeile 426) — das ist der
   Rahmen, den der Katalog nennt. Hier steht nichts absolut Gesetztes im Weg
   (nachgesehen: das Formular ist ein normaler Fluss aus Bloecken). */
