/* =========================================================================
   site.css — Produktions-Chrome fuer Website Romy Nießner v2
   Ergaenzt style.css (Design-System) um reine Website-Mechanik, die im
   Design-System-Beispiel (Single-File-Demo) nicht vorkommt:
   Logo als Bild, mobiles Menue (Hamburger), Responsive-Breakpoints,
   Skip-Link. Bewusst getrennt von style.css, damit die Design-System-
   Quelle der Wahrheit (Tokens/Komponenten) sauber spiegelbar bleibt.
   ========================================================================= */

/* Bildmasse (27.09.2026, Review S7): build.py schreibt width/height der echten Datei in
   jedes <img>, damit der Browser den Platz vor dem Laden reserviert. Die Groesse auf der
   Seite bestimmt weiter allein das CSS - diese Zeile sorgt dafuer, dass das
   height-Attribut nie gewinnt, wo das CSS nur die Breite setzt. */
img { height: auto; }

/* [hidden] muss auch gegen display:flex/grid-Komponenten gewinnen (Termin-Teaser) */
[hidden] { display: none !important; }

/* ---- Skip-Link (Barrierefreiheit) ---- */
.skip-link {
  position: absolute; left: 8px; top: -48px;
  background: var(--primary); color: var(--on-primary);
  padding: 10px 18px; border-radius: var(--radius-sm);
  font-family: var(--font-body); font-weight: 700; font-size: 0.875rem;
  z-index: 100; transition: top var(--motion-short) var(--motion-easing);
}
.skip-link:focus { top: 8px; outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }

/* ---- Logo: Bildmarke "Band" + Wortmarke (seit 03.10.2026) ----
   Uebernommen aus den Varianten v2b "B1" (Name + Unterzeile als Text, Karla 600, gesperrte
   Versalien) und "Bildmarke Band" (Romys Wahl, Entwurf Runde 3 Nr. 05). Die Marke ist ein
   zartes SVG - kreisfoermig, am Desktop 64 px hoch (zuerst 78, siehe unten), Handy 56 px;
   der Rand haelt die Kopfzeile auf gleicher Hoehe.
   Davor bis 03.10.2026: Logo als Bild "New Balance" (logo-240/360.png), 78 px seit 26.09.2026. */
.logo { display: inline-flex; align-items: center; gap: 14px; line-height: 1; text-decoration: none; min-width: 0; }
/* Desktop 64 px seit 03.10.2026 (Gigi, Variante B aus 78/70/64/58): mit 78 px blieben nur 6-7 px
   Luft zur Kopfzeilenkante. Der Rand haelt den Kasten auf 62 px, die Kopfzeile bleibt 91 px hoch. */
.logo img.bm { height: 64px; width: auto; display: block; margin: -1px 0; flex: none; }
.wm { display: flex; flex-direction: column; gap: 8px; }
.wm-name { font: 600 1.0625rem/1 var(--font-body); letter-spacing: .16em; text-transform: uppercase; color: var(--primary); }
.wm-zeile { font: 600 .625rem/1.2 var(--font-body); letter-spacing: .2em; text-transform: uppercase; color: var(--on-surface-variant); }
.wm-zeile .nb { white-space: nowrap; }
/* Das groessere Logo darf die Kopfzeile nicht hoeher machen: senkrechte Polsterung
   entsprechend zurueckgenommen (24 -> 14px), Gesamthoehe bleibt wie vorher.
   Gehoert hierher, nicht ins Design-System — es haengt am Logo-als-Bild. */
header { padding-top: 14px; padding-bottom: 14px; }

/* ---- Header-Zeile: Platz fuer Hamburger auf Mobile ---- */
.nav-toggle {
  display: none; /* Desktop: aus */
  flex-direction: column; justify-content: center; gap: var(--space-4);
  width: 44px; height: 44px; padding: 10px; margin: -10px -10px -10px 0;
  background: transparent; border: 0; cursor: pointer;
  border-radius: var(--radius-sm);
}
.nav-toggle span {
  display: block; height: 2px; width: 100%;
  background: var(--on-background); border-radius: 2px;
  transition: transform var(--motion-short) var(--motion-easing),
              opacity var(--motion-short) var(--motion-easing);
}
.nav-toggle:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }

/* Die Kopfzeile trennt sich erst, wenn sie muss (Review-Befund C5c, Georg 16.09.2026,
   Variante C von dreien). Das Problem war nicht der Kontrast der Haarlinie an sich -
   eine Trennlinie ist kein bedeutungstragendes grafisches Objekt, WCAG 1.4.11 greift
   hier gar nicht. Das Problem ist, dass die Kopfzeile sticky ist: beim Scrollen wandert
   Inhalt darunter hindurch, und --outline-variant auf --background bringt nur 1,26:1.
   Leiste und Text wurden dabei zu einer Flaeche.
   Verworfen wurde die Linie auf --outline (3,52:1): wirkt auch ganz oben, wo es nichts
   zu trennen gibt, und ist im Gesamtbild eine spuerbare Verhaertung.
   Der Schatten nutzt --elevation-2, also einen vorhandenen Token. Die Klasse setzt
   main.js; ohne JavaScript bleibt schlicht die Haarlinie - kein Verlust, nur weniger. */
header { transition: box-shadow var(--motion-short) var(--motion-easing); }
body.ist-gescrollt header { box-shadow: var(--elevation-2); }
@media (prefers-reduced-motion: reduce) { header { transition: none; } }

/* Fokusring fuer Kopf- und Fusszeile, ergaenzt 16.09.2026 (Review-Befund C5).
   Diese drei Gruppen hatte kein Selektor abgedeckt: main a:focus-visible greift nur
   INNERHALB von <main>, Navigation, Logo und Footer stehen ausserhalb. Sie fielen
   damit als einzige Stellen der Seite auf den Browser-Standardring zurueck - je nach
   Browser ein duenner blauer Rahmen, der mit Farbwelt A nichts zu tun hat.
   Gleiche Tokens wie ueberall sonst, keine neuen Werte. Sichtbar nur beim Tabben.
   .btn-primary ist ausgenommen: der Knopf hat seine eigene Regel in style.css, und
   der radius-xs hier wuerde seine Pillenform anschneiden.
   Kontrast unkritisch - Kopfzeile auf --background, Footer auf
   --surface-container-low, der Ring in --on-background liegt darauf bei rund 9-11:1.
   Nicht in der Liste, weil bereits abgedeckt: .skip-link (eigene Regel weiter oben,
   bewusst :focus statt :focus-visible) und "Termin buchen" (ist ein .btn-primary). */
nav a:not(.btn-primary):focus-visible,
.logo:focus-visible,
.footer-links a:focus-visible {
  outline: var(--focus-ring); outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-xs);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ---- Bilder: Hochformate begrenzen, damit kurze Textspalten daneben nicht kippen ---- */
.imgfull img { max-height: 460px; }
.two-col-rev .imgfull img, .two-col .imgfull img { max-height: 340px; }

/* Hero-Foto der Startseite bewusst NICHT beschneiden (Georg 06.09.2026 — der Kopf war
   durch das 460px-Limit + object-fit:cover oben abgeschnitten). Das Bild
   (IMG_1035_cropped, Seitenverhaeltnis 1993:2376) laeuft daher in voller Hoehe im
   natuerlichen Verhaeltnis; die Spaltenbreite bleibt unveraendert. */
.hero-grid .imgfull img { max-height: none; height: auto; }

/* ---- Unterschrift im Hero (ueber dem Kicker) ---- */
.hero-sign {
  display: block; width: 230px; height: auto;
  /* 73px Luft nach oben, 20px nach unten (Georg 06.09.2026, in drei Schritten
     feinjustiert: 78/10 -> 73/15 -> 73/20). */
  margin: var(--space-72) 0 0; margin-left: -6px;   /* optischer Ausgleich des Schwungs links */
}
.hero-sign + .hero-kicker { margin-top: var(--space-20); }

/* ---- Ganze Karte klickbar (Design-System .card ist ein div-Style) ---- */
a.card { display: block; color: var(--on-background); text-decoration: none; }
a.card:hover { box-shadow: var(--elevation-2); transform: translateY(-2px); }
a.card:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }


/* =========================================================================
   Unterseiten-Bausteine (05.09.2026) — reine Seiten-Mechanik, kein Design-System.
   Alles hier benutzt ausschliesslich Tokens aus style.css.
   ========================================================================= */

/* ---- Einheitlicher Seitenkopf aller Unterseiten (05.09.2026) ----
   Jede Unterseite startet gleich: H1 links, optional ein Lead-Satz, kein Bild
   daneben. Bilder beginnen erst im Abschnitt darunter. Unten schmaler gepolstert,
   damit der Titel zum ersten Inhaltsblock gehoert statt allein zu stehen. */
section.page-head { padding-bottom: var(--space-28); }
section.page-head + section { padding-top: var(--space-28); }
/* Folgt auf den Seitenkopf ein farbiger Abschnitt, ist die Kante sichtbar: dann haben
   beide Baender den normalen Abschnittsabstand wie ueberall (Georg 27.09.2026, vorher
   Kopf unten 28 / Folgeabschnitt oben 56). Nur hell auf hell bleibt es eng. */
section.page-head:has(+ section.alt) { padding-bottom: var(--space-72); }
section.page-head + section.alt { padding-top: var(--space-72); }

/* ---- Fuenferreihe der Galerie (Tanztherapie): auf Desktop wirklich fuenf ---- */
.gallery-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }

/* ---- Kontaktzeilen ausserhalb der Kontaktkachel nicht ueber die volle Breite ---- */
.inner > .contact-row { max-width: 440px; }

/* Tertiaerer Button linksbuendig zum Text: .btn-text hat 16px Innenabstand links,
   dadurch startet die Schrift sonst eingerueckt gegen den Absatz darueber. */
.btn-text.flush { margin-left: -16px; }

/* ---- Button-/Linkzeile am Abschnittsende ---- */
.cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-12) var(--space-20); margin-top: var(--space-24); }

/* ---- Zweispalter mit Text links, Bild rechts (Gegenstueck zu .two-col) ---- */
.two-col-rev { display: grid; grid-template-columns: 1.3fr 0.7fr; gap: var(--space-56); align-items: start; }

/* ---- Abstand zwischen Bloecken innerhalb einer Section ---- */
.block { margin-top: var(--space-48); }
/* Sprungziel per Anker (z. B. #walk-and-talk, 03.10.2026): sonst landet die Ueberschrift
   unter der sticky Kopfzeile. */
.block[id], h2[id] { scroll-margin-top: 128px; }
.inner > .block:first-child { margin-top: 0; }
/* Muss auch gegen p.body-text (Spezifitaet 0,1,1) gewinnen */
.mt-md, p.body-text.mt-md, div.mt-md { margin-top: var(--space-24); }
.mt-lg, div.mt-lg { margin-top: var(--space-40); }
/* Seitenkopf: Titel und Lead-Satz brauchen Luft dazwischen (Georg 05.09.2026) */
.page-head p.body-text { margin-top: var(--space-20); }
/* Zweispalter, bei denen die Textspalte deutlich kuerzer ist als das Bild */
.align-center { align-items: center; }
/* .align-stretch / .fixed-square (verworfene Bildvariante) am 27.09.2026 entfernt, Review C4. */


.center { text-align: center; }
.center .quote, .center .body-text { margin-left: auto; margin-right: auto; }

/* ---- Inhaltslinks im Fliesstext (Buttons und Karten ausgenommen) ---- */
main a:not(.btn-primary):not(.btn-secondary):not(.btn-text):not(.card):not(.map-route-link):not(.logo):not(.contact-link):not(.maplibregl-ctrl-attrib-inner a) {
  color: var(--primary); font-weight: 700; text-decoration: underline;
  text-underline-offset: 2px; text-decoration-thickness: 1px;
}
/* Hover-Farbe geaendert 13.09.2026 (Review-Befund C2): vorher Akzent 2 #B98CA0 — der
   erreichte im Hover nur 1,99-2,46:1 und riss damit die 4,5:1 fuer Fliesstext. Akzent 2
   bleibt jetzt das, wofuer er gedacht ist: Flaechen- und Linienfarbe.
   Zwei Varianten wurden am 13.09.2026 als vollstaendige Builds verglichen (Georg):
   "nur dunkler" --primary-hover #4F4961 und "deutlich dunkler" --primary-pressed
   #423C51. Entschieden: --primary-pressed (8,13:1 auf Grund, 7,31:1 auf der
   Wechselflaeche). Bewusst KEINE dickere Unterstreichung als zusaetzliches Signal.
   Die :not()-Liste ist dabei an die Ruhe-Regel darueber angeglichen worden; vorher
   fehlten .map-route-link, .logo und die MapLibre-Attribution, weshalb deren
   color:inherit im Hover verlorenging. */
main a:not(.btn-primary):not(.btn-secondary):not(.btn-text):not(.card):not(.map-route-link):not(.logo):not(.contact-link):not(.maplibregl-ctrl-attrib-inner a):hover { color: var(--primary-pressed); }
main a:focus-visible { outline: var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-xs); }

/* ---- Platzhalterflaechen sichtbar abgrenzen (nur noch im Styleguide benutzt) ---- */
.ph { border: 1px dashed var(--outline-variant); }

/* ---- Aufzaehlungen im Fliesstext ---- */
/* KORREKTUR 26.09.2026: Hier stand font-size:1rem, waehrend der Absatz daneben
   auf 1.125rem steht. Eine Aufzaehlung im Fliesstext IST Fliesstext - der
   Groessensprung war ein Fehler, kein Entwurf. */
ul.body-list {
  font-family: var(--font-body); font-size: 1.125rem; line-height: 1.75;
  max-width: var(--measure); margin: 0 0 var(--space-16); padding-left: 22px; color: var(--on-background);
}
ul.body-list li { margin-bottom: var(--space-8); }

/* ---- Kontaktkachel ---- */
.contact-card {
  background: var(--surface-container); border-radius: var(--radius-md);
  padding: var(--space-28); box-shadow: var(--elevation-1);
}
/* Zusatzzeile im Termin-Teaser (Leistungsname) */
.teaser-service { margin: 0; }

/* Buchungsmaske als eigenes Element auf der Flaeche (Georg 06.09.2026).
   Linksbuendig zum uebrigen Inhalt, nicht zentriert (Georg 06.09.2026). */
.booking-card { max-width: var(--measure); margin: 0; }
.booking-card .pss-fit { margin-top: var(--space-20); }
.booking-card > .fine-print { margin-top: var(--space-20); }

.contact-row { display: flex; gap: var(--space-16); align-items: flex-start; padding: var(--space-12) 0; border-bottom: 1px solid var(--outline-variant); }
.contact-row:last-of-type { border-bottom: none; }
.contact-ico {
  flex: 0 0 34px; height: 34px; border-radius: var(--radius-sm);
  background: var(--primary-container); color: var(--on-primary-container);
  display: flex; align-items: center; justify-content: center;
}
.contact-label { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--on-surface-variant); }
.contact-value { font-size: 1.125rem; line-height: 1.5; color: var(--on-background); }
/* Telefon/E-Mail: ohne Unterstreichung ruhiger - Icon, Label und Farbe machen
   klar, dass es Links sind; unterstrichen wird erst beim Hover/Fokus. */
.contact-value a,
main .contact-value a { color: var(--primary); font-weight: 700; text-decoration: none; }
.contact-value a:hover, .contact-value a:focus-visible { text-decoration: underline; }


/* ---- Sprechzeiten-Block: Einleitung eng an die Tabelle, Hinweis abgesetzt ---- */
p.body-text.hours-intro { margin-bottom: var(--space-4); }
.hours-note { font-family: var(--font-body); font-size: 0.9375rem; line-height: 1.57;
  color: var(--on-surface-variant); margin-top: var(--space-24); }

/* ---- Honorar-Liste ---- */
.price-list { max-width: 420px; }
.price-row { display: flex; justify-content: space-between; gap: var(--space-16); padding: var(--space-12) 0; border-bottom: 1px solid var(--outline-variant); font-size: 1.125rem; }
.price-row:last-child { border-bottom: none; }
.price-row .price { font-weight: 700; white-space: nowrap; }

/* ---- Rechtstexte (Impressum / Datenschutz) ---- */
/* AUSNAHME von der 18 (Georg 26.09.2026): Impressum und Datenschutz sind lange
   Pflichttexte, keine Lesetexte - die Type-Scale fuehrt Body Small ausdruecklich
   als "Feingedrucktes, Bildunterschriften, Rechtstext-Detail". Groesse und
   Ueberschrift bleiben deshalb bewusst auf 1rem. Wer das hier "nachzieht",
   macht die Entscheidung rueckgaengig. Nur die Kante wandert auf die Lesebreite. */
.legal-item { border-bottom: 1px solid var(--outline-variant); padding: var(--space-20) 0; max-width: var(--measure); }
.legal-item:last-child { border-bottom: none; padding-bottom: 0; }
.legal-item h3 { font-family: var(--font-body); font-weight: 700; font-size: 1rem; line-height: 1.5; margin: 0 0 var(--space-8); }
.legal-item p { font-family: var(--font-body); font-size: 1rem; line-height: 1.625; margin: 0 0 var(--space-12); color: var(--on-background); }
.legal-item p:last-child { margin-bottom: 0; }
.legal-item a { color: var(--primary); font-weight: 700; }

/* ---- Raumfoto-Reihe ---- */
.room-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: var(--space-20); margin-bottom: var(--space-24); }

/* =========================================================================
   Karte Kontaktseite — MapLibre GL + OpenFreeMap (Positron), self-hosted JS/CSS.
   Look = Farbwelt A (der Wireframe-Umschalter neutral/Farbwelt entfaellt hier).
   ========================================================================= */
.map-wrap {
  position: relative; width: 100%; height: 420px; border-radius: var(--radius-md);
  overflow: hidden; background: var(--surface-variant); box-shadow: var(--elevation-1);
}
/* Doppelt abgesichert gegen maplibre-gl.css (.maplibregl-map{position:relative}):
   der .map-wrap-Prefix hebt die Spezifitaet, unabhaengig von der Ladereihenfolge. */
.map-wrap .map-canvas { position: absolute; inset: 0; height: 100%; }
/* Marker auf Akzent 1 geaendert 16.09.2026 (Review-Befund C3, Georg waehlte Variante B
   aus vier gebauten Varianten). Vorher Akzent 2 (--secondary, Altrosa): auf den hellen
   Positron-Kacheln nur 2,53:1. Der Marker ist die einzige Ortsangabe IN der Karte, also
   bedeutungstragend - WCAG 2.1 SC 1.4.11 verlangt 3:1. Akzent 1 bringt an derselben
   Stelle 6,28:1.
   Verworfen wurden: Altrosa mit dunkler Kante und Akzent-1-Kante um einen rosa Punkt -
   beide erfuellen 1.4.11 ueber die Kante, wirken aber unruhiger. Vergleichsseite lag in
   "Claude outputs/20260916_Vergleich_Kartenmarker.html" (nicht versioniert).
   ACHTUNG beim Aendern: --secondary faellt hier durch, weil der Marker eine Flaeche
   OHNE Text ist. Nicht versehentlich zurueckdrehen. */
/* KEIN position hier (Georg 27.09.2026): MapLibre setzt .maplibregl-marker auf
   position:absolute und verschiebt per transform. Ein position:relative aus diesem
   Stylesheet gewinnt (es laedt spaeter) und legt die Marker in den normalen Fluss -
   jeder weitere Marker rutscht dann um die Hoehe der vorigen nach unten. absolute
   ist fuer die Kinder (.ring, .dot, .t) genauso Bezugsrahmen. */
.map-marker { width: 30px; height: 30px; cursor: pointer; }
.map-marker .ring { position: absolute; inset: 0; margin: auto; width: 26px; height: 26px; border-radius: 50%; border: 2px solid var(--primary); animation: mapPulse 2.6s ease-out infinite; }
.map-marker .dot { position: absolute; inset: 0; margin: auto; width: 12px; height: 12px; border-radius: 50%; background: var(--primary); }
@keyframes mapPulse { 0% { transform: scale(.9); opacity: .9; } 70% { transform: scale(1.7); opacity: 0; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .map-marker .ring { animation: none; } }
/* Rahmen fuer Karte + Kaertchen: das Kaertchen positioniert sich gegen diesen Block,
   nicht gegen .map-wrap (das clippt). Georg 06.09.2026. */
.map-block { position: relative; }

/* Karten-Kaertchen (Variante E, Georg 06.09.2026): steht dauerhaft unten rechts IN der
   Karte, nicht mehr als aufklappbares Panel. Auf schmalen Bildschirmen rutscht es unter
   die Karte (siehe Media-Query weiter unten) — dort verdeckt es sonst zu viel Karte. */
.map-info {
  position: absolute; z-index: 30; right: 16px; bottom: 16px; width: 300px; max-width: calc(100% - 32px);
  background: color-mix(in srgb, var(--surface-container) 94%, transparent); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-radius: var(--radius-md); padding: var(--space-16) 18px; color: var(--on-background);
  box-shadow: var(--elevation-2);
}
.map-info strong { font-family: var(--font-head); font-weight: 600; font-size: 1rem; display: block; }
.map-info p { margin: var(--space-8) 0 0; font-size: 0.9375rem; line-height: 1.5; color: var(--on-surface-variant); }
.map-route-link { display: inline-flex; align-items: center; gap: var(--space-8); margin-top: var(--space-12); font-size: 0.9375rem; font-weight: 700; color: var(--primary); text-decoration: none; border-bottom: 1px solid var(--primary); }
.map-route-link:hover { color: var(--primary-pressed); border-color: var(--primary-pressed); }

/* =========================================================================
   Parken unter der Karte (Georg 26.09.2026, Variante P4 aus varianten/20260926_Parken).
   Zwei Kaertchen ohne Minikarte, P-Pins auf der Hauptkarte. Der Praxis-Punkt bleibt
   der Blickfang (Ring + Puls); die P-Pins sind gefuellt in Akzent 1 wie der Praxis-Punkt
   (Georg 27.09.2026 - vorher weiss mit Kante, wirkte neben dem lila Punkt fremd).
   Schilder nur auf Nachfrage. Das P in den Kaertchen sieht aus wie die Kontakt-Icons
   (.contact-ico) - Romy fand das weisse P mit Kante zu gross (27.09.2026). Hervorgehoben
   wird nur die Kachel ueber den Rahmen, das P selbst aendert sich dabei nicht.
   Immer genau EIN Punkt aktiv (.is-hot) - das fuehrt das Skript in kontakt.html.j2;
   bewusst kein :hover fuer Schild/Rahmen, sonst stuenden zwei gleichzeitig da.
   ========================================================================= */
.park { margin-top: var(--space-40); }
.park-lead { margin-top: var(--space-4); }
.park-grid { list-style: none; margin: var(--space-16) 0 0; padding: 0; display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-16); }
.park-card { background: var(--surface-container); border-radius: var(--radius-md);
  box-shadow: var(--elevation-1); padding: var(--space-16) 18px; display: flex; gap: var(--space-16); align-items: flex-start;
  transition: box-shadow var(--motion-medium) var(--motion-easing); }
.park-card.is-hot { box-shadow: 0 0 0 2px var(--primary), var(--elevation-1); }
/* Gleiche Groesse wie .contact-ico (34 px, Georg 27.09.2026). */
.park-ico { flex: 0 0 34px; width: 34px; height: 34px; border-radius: var(--radius-sm);
  background: var(--primary-container); color: var(--on-primary-container);
  font: 600 1rem/34px var(--font-body); text-align: center; }
.park-body { min-width: 0; }
.park-body strong { font-family: var(--font-head); font-weight: 600; font-size: 1rem; line-height: 1.35; display: block; }
/* 26.09.2026 eine Stufe mitgezogen, wie alles Kleingedruckte. Die Kacheln
   selbst bleiben auf Kartengroesse - sie fallen unter die Karten-Ausnahme. */
.park-body p { margin: var(--space-8) 0 0; font-size: 0.9375rem; line-height: 1.5; color: var(--on-surface-variant); }
.park-body .park-weg { margin-top: 2px; font-size: 0.875rem; }
.park-body .map-route-link { margin-top: var(--space-8); }

.map-marker.maplibregl-marker { z-index: 3; }
.park-pin { display: block; width: 24px; height: 24px; padding: 0; margin: 0; border: 0;
  background: none; font-family: var(--font-body); cursor: pointer; z-index: 1; }
.park-pin.maplibregl-marker.is-hot { z-index: 4; }
.park-pin .p { display: block; width: 24px; height: 24px; box-sizing: border-box; border-radius: 6px;
  background: var(--primary); border: 2px solid var(--primary); color: #fff; font-weight: 700; font-size: 0.75rem;
  line-height: 20px; text-align: center; box-shadow: 0 1px 3px hsl(var(--shadow) / .28); }
.park-pin .t { position: absolute; top: 50%; left: calc(100% + 6px); transform: translateY(-50%);
  background: var(--primary); color: #fff; font-size: 0.75rem; font-weight: 700; line-height: 1.3;
  padding: var(--space-4) 9px; border-radius: var(--radius-pill); white-space: nowrap; box-shadow: var(--elevation-2);
  opacity: 0; visibility: hidden; transition: opacity var(--motion-short), visibility var(--motion-short); pointer-events: none; }
.park-pin.links .t, .map-marker.links .t { left: auto; right: calc(100% + 6px); }
.park-pin.oben .t, .map-marker.oben .t { top: auto; bottom: calc(100% + 6px); left: 50%; right: auto;
  transform: translateX(calc(-50% + var(--dx, 0px))); }
/* Schild auch am Praxis-Punkt, gleiche Form wie bei den Pins */
.map-marker .t { position: absolute; top: 50%; left: calc(100% + 4px); transform: translateY(-50%);
  background: var(--primary); color: #fff; font-family: var(--font-body); font-size: 0.75rem; font-weight: 700;
  line-height: 1.3; padding: var(--space-4) 9px; border-radius: var(--radius-pill); white-space: nowrap;
  box-shadow: var(--elevation-2); opacity: 0; visibility: hidden;
  transition: opacity var(--motion-short), visibility var(--motion-short); pointer-events: none; }
.map-marker.maplibregl-marker.is-hot { z-index: 5; }
/* Kein :hover im CSS - sonst koennten zwei Schilder gleichzeitig stehen. Den einen
   aktiven Punkt fuehrt das Skript (Georg 26.09.2026). */
.park-pin.is-hot .t, .map-marker.is-hot .t { opacity: 1; visibility: visible; }
.park-pin:focus-visible { outline: var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-sm); }

@media (max-width: 860px) { .park-grid { grid-template-columns: 1fr; gap: var(--space-12); } }
@media (prefers-reduced-motion: reduce) { .park-card, .park-pin .t, .map-marker .t { transition: none; } }
/* Hoehere Spezifitaet als maplibre-gl.css: dessen <link> steht im head_extra-Block
   und damit NACH site.css - ohne den .map-wrap-Prefix wuerde es hier gewinnen. */
.map-wrap .maplibregl-ctrl-attrib { font-size: 0.625rem; }
.map-wrap .maplibregl-ctrl-attrib a { text-decoration: none; font-weight: 400; color: inherit; }
/* MapLibre-Hinweis „Zum Zoomen Strg …“: Standard-Schleier ist rgba(0,0,0,.4) —
   weisser Text darauf liegt ueber hellen Kacheln nur bei ~2,8:1. Auf Markenton
   abgedunkelt, damit auch dieser Hinweis WCAG AA erreicht. */
.map-wrap .maplibregl-cooperative-gesture-screen { background: rgba(51,46,58,.72); font-family: var(--font-body); }
.map-fallback { font-size: 1.125rem; line-height: 1.6; color: var(--on-background); margin-top: var(--space-16); }
/* Sichtbarer Ersatz, wenn der Kartendienst nicht antwortet (statt grauer Flaeche) */
.map-wrap.has-error { display: flex; align-items: center; justify-content: center; text-align: center; padding: var(--space-24); }
.map-wrap.has-error .map-canvas { display: none; }
/* Faellt die Karte aus, rutscht das Kaertchen unter die Fehlermeldung — sonst liegt es
   absolut positioniert darueber. Gleiche Darstellung wie auf schmalen Bildschirmen. */
.map-wrap.has-error { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.map-wrap.has-error + .map-info {
  position: static; right: auto; bottom: auto; width: auto; max-width: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  background: var(--surface-container); backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: var(--elevation-1); padding: 18px;
}
.map-error-note { font-family: var(--font-body); font-size: 1.125rem; line-height: 1.6; color: var(--on-surface-variant); max-width: 42ch; }

/* =========================================================================
   Lemniscus-Vollembed (#pss) — nur die laut Lemniscus-Doku erlaubten Variablen
   und Wrapper-IDs. Alles andere (Buttons, Formularelemente) bleibt systembedingt
   im Lemniscus-Blau, siehe 06_Lemniscus_Integration.md — das ist kein Fehler.
   WICHTIG: font-size von html und #pss muessen identisch sein (Doku).
   Bis 16.09.2026 stand dafuer hier "html { font-size: 1rem }" - beide Seiten der
   Gleichung hart auf 16. Das nagelte die Wurzelgroesse fest und haette eine
   rem-Skala wirkungslos gemacht (Review-Befund C5b). Jetzt traegt #pss "1rem":
   damit ist es per Definition identisch mit html, egal was der Browser als
   Standardschriftgroesse liefert. Die Lemniscus-Vorgabe ist so strenger erfuellt
   als vorher, nicht lockerer. html bleibt bewusst ungesetzt.
   ========================================================================= */
#pss {
  font-size: 1rem;
  min-width: 400px;
  /* Unterstreichung Akzent 1 statt Altrosa (27.09.2026, Farbrollen: markiert eine
     Auswahl, also "Handlung"). Literal, siehe unten. */
  --pss-infos-underline-color: #5B5470;
  /* #E8E0E6 ist Neutral-90, also derselbe Ton wie --background: eine Stufe
     unter der Karte, in der die Maske sitzt. Bleibt bewusst ein Literal -
     Lemniscus liest seine eigenen Variablen, var() waere ein Risiko. */
  --pss-tab-underline-color: #E8E0E6;
  --pss-tab-selected-underline-color: #5B5470;
  --pss-slots-button-selected-color: #5B5470;
  --pss-appname-color: #332E3A;
  --pss-font-family: 'Karla', -apple-system, sans-serif;
}
#pss-wrapper { max-width: 900px; }
/* Kein eigener Kasten um die Buchungsmaske: die Maske bringt ihre eigene Flaeche
   mit, ein zusaetzlicher Schatten sah an den Ecken ausgefranst aus (Georg 05.09.2026). */
#pss-main { background: transparent; box-shadow: none; padding: 0; }
#pss-teaser { margin-bottom: var(--space-16); }
/* Solange das Lemniscus-Script nichts gerendert hat: Ladehinweis statt Leerflaeche */
#pss:empty {
  min-height: 240px; display: flex; align-items: center; justify-content: center;
  text-align: center; color: var(--on-surface-variant); font-family: var(--font-body); font-size: 0.875rem;
}
#pss:empty::before { content: "Die Online-Terminvergabe wird geladen \2026"; }
/* Rahmen um die skalierte Maske. overflow-x:auto ist die Rueckfallebene ohne
   JavaScript: dann bleibt die Maske 400px breit und laesst sich schieben, statt
   abgeschnitten zu werden. Mit JavaScript greift die Skalierung. */
.pss-fit { overflow-x: auto; }
.pss-scale { transform-origin: top left; }
/* WICHTIG (Georg 08.09.2026): Sobald skaliert wird, darf der Rahmen KEIN
   Scroll-Container mehr sein. Eine per transform verkleinerte Box meldet ihren
   Platzbedarf unskaliert weiter, also bleibt hinter der passend gesetzten Hoehe
   ein unsichtbarer Scrollbereich uebrig - bei 390px 34px waagrecht und 42px
   senkrecht, bei 320px 104/130px. Auf dem Handy fing dieser Bereich die
   Wischgeste komplett ab: beim Wischen ueber der Maske scrollte die Seite gar
   nicht. overflow:hidden nimmt ihm die Scrollbarkeit (ueberall unterstuetzt),
   overflow:clip ist dasselbe eine Stufe sauberer (kein Scrollport, ab Safari 16).
   Sichtbar abgeschnitten wird dabei nichts: die skalierte Maske ist schmaler und
   niedriger als der Rahmen, weggeschnitten wird nur der Phantom-Platzbedarf.
   Absichtlich KEIN touch-action hier - das wuerde auch das Aufziehen mit zwei
   Fingern verhindern, und wer die Maske vergroessern will, soll das koennen. */
.pss-fit.is-scaled { overflow: hidden; overflow: clip; -webkit-overflow-scrolling: auto; }
/* Die Hoehe wird auf .pss-box gesetzt, nicht auf .pss-fit: dann stimmt der
   Platzbedarf des Inhalts mit dem Sichtbaren ueberein, und die Ebene unten kann
   senkrecht scrollen, ohne hinter der Maske ins Leere zu laufen. */
.pss-box { position: relative; }

/* =========================================================================
   Vollflaechige Buchungs-Ebene auf dem Handy (Georg 08.09.2026)
   -------------------------------------------------------------------------
   Warum ueberhaupt: eingebettet bleiben auf schmalen Geraeten nur 374 px fuer
   eine Maske, die 400 braucht (Faktor 0,935; auf einem iPhone SE 0,76). In einer
   Ebene ueber den ganzen Bildschirm bekommt sie die volle Viewport-Breite, also
   0,975 bzw. 0,8 - und es gibt genau einen Scroll-Bereich, naemlich den, den man
   auch erwartet.

   Wichtig fuers Widget: die Maske liegt hier von Anfang an drin und ist schon
   beim Laden in voller Breite ausgelegt. Geschlossen ist sie nur
   visibility:hidden (NICHT display:none - das haette Breite 0 und die Maske
   wuerde falsch rechnen) und inert. Oeffnen macht sie bloss sichtbar; kein
   DOM-Umzug, keine spaete Initialisierung.

   Alles hier haengt an .pss-sheet auf <body>, das das Skript setzt. Ohne
   JavaScript bleibt es bei der eingebetteten Maske mit Schiebe-Rahmen.
   ========================================================================= */
.pss-open { display: none; }

@media (max-width: 600px) {
  body.pss-sheet .pss-open { display: inline-flex; width: 100%; justify-content: center; }

  body.pss-sheet .pss-fit {
    position: fixed; inset: 0; z-index: 60;
    margin: 0; padding: 0;
    background: var(--surface-container);
    overflow-x: hidden; overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    visibility: hidden;
  }
  body.pss-sheet.pss-offen .pss-fit { visibility: visible; }
  /* iOS-Safari (01.10.2026, Gigi): Mit der Adresszeile oben legt Safari unten eine
     eigene Leiste ueber die Seite. Eine Ebene mit inset:0 reicht bis unter diese
     Leiste - die Maske war genau bildschirmhoch, ihr letzter Knopf
     ("Online-Terminvergabe starten") lag darunter und war erst nach einem Tipp zu
     sehen. Deshalb zweierlei: (1) Hoehe in dvh, das ist die tatsaechlich sichtbare
     Hoehe ohne die Leisten (inset:0 bleibt die Rueckfallebene fuer aeltere
     Browser); (2) unten ein Polster aus Ebenen-Hintergrund, damit sich der letzte
     Knopf auch dann ueber eine Leiste schieben laesst, wenn sie die Ebene
     ueberdeckt. Beides schadet anderswo nicht: das Polster ist nur leere Flaeche. */
  @supports (height: 100dvh) {
    body.pss-sheet .pss-fit { bottom: auto; height: 100dvh; }
  }
  body.pss-sheet .pss-fit::after {
    content: ""; display: block;
    height: calc(env(safe-area-inset-bottom, 0px) + 96px);
  }
  /* Kopfzeile der Ebene: haelt den Schliessen-Knopf beim Scrollen oben */
  body.pss-sheet .pss-sheet-kopf {
    position: sticky; top: 0; z-index: 1;
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-12); padding: 10px 14px;
    background: var(--surface-container);
    border-bottom: 1px solid var(--outline-variant);
  }
  body.pss-sheet .pss-sheet-titel {
    font-family: var(--font-head); font-weight: 700; font-size: 1.0625rem;
    color: var(--on-background);
  }
  /* Wenn die Ebene offen ist, soll die Seite dahinter nicht mitscrollen */
  html.pss-gesperrt, body.pss-gesperrt { overflow: hidden; }
}
/* Ausserhalb der Ebene braucht die Kopfzeile nicht zu erscheinen */
.pss-sheet-kopf { display: none; }
@media (max-width: 600px) { body.pss-sheet .pss-sheet-kopf { display: flex; } }

/* =========================================================================
   Responsive
   ========================================================================= */

/* Tablet und kleiner: Hamburger an, Nav als aufklappbares Panel */
@media (max-width: 860px) {
  header { padding: var(--space-16) var(--space-24); }
  .logo img.bm { height: 56px; margin: -6px 0; }
  .wm-name { font-size: .875rem; letter-spacing: .13em; }
  .wm-zeile { font-size: .5625rem; }
  .js .nav-toggle { display: flex; }

  nav {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--background);
    border-bottom: 1px solid var(--outline-variant);
    box-shadow: var(--elevation-2);
    padding: var(--space-8) var(--space-24) var(--space-20);
  }
  /* Eingeklappt nur mit JavaScript (Review S5, 27.09.2026). Ohne: Links offen
     unter dem Logo, im Fluss statt als Panel. */
  .js nav { display: none; }
  .js nav.is-open { display: flex; }
  html:not(.js) header { flex-wrap: wrap; }
  html:not(.js) nav {
    display: flex; position: static; width: 100%;
    box-shadow: none; border-bottom: 0; padding: var(--space-8) 0 0;
  }
  nav a:not(.btn-primary) {
    font-family: var(--font-body); font-size: 1.125rem; font-weight: 600;
    padding: 14px 0; border-bottom: 1px solid var(--outline-variant);
  }
  nav a:not(.btn-primary):hover { border-bottom-color: var(--outline-variant); }
  nav a.active { border-bottom: 1px solid var(--outline-variant); }
  nav .btn-primary { margin-top: var(--space-16); justify-content: center; }

  section { padding: var(--space-48) var(--space-24); }
  /* Eine linke Kante fuer Kopf, Inhalt und Fuss (27.09.2026, Review D5): vorher
     Kopf 24, Inhalt 72 (Abschnitt 24 + .inner 48), Fuss 48 px. Jetzt alles 24. */
  .inner { padding: 0; }
  footer { padding: var(--space-32) var(--space-24); }

  .hero-grid,
  .inner.two-col,
  .two-col-rev { grid-template-columns: 1fr; gap: var(--space-32); }
  /* Bild bei Text-links-Layouts unter den Text lassen (Reihenfolge stimmt dort schon) */

  .room-grid { grid-template-columns: 1fr; }
  .gallery-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .map-wrap { height: 320px; }
  /* Karten-Kaertchen unter die Karte statt darin (Georg 06.09.2026, Vorbild wdc2026.org):
     im Kartenausschnitt verdeckt es auf schmalen Bildschirmen zu viel. .map-wrap bekommt
     dafuer nur unten eckige Ecken, damit Karte und Kaertchen als ein Block lesen. */
  .map-wrap { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
  .map-info {
    position: static; right: auto; bottom: auto; width: auto; max-width: none;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
    background: var(--surface-container); backdrop-filter: none; -webkit-backdrop-filter: none;
    box-shadow: var(--elevation-1); padding: 18px;
  }
  /* Die mobile Ueberschriften-Leiter zieht am 26.09.2026 mit der Skala eine Stufe
     hoch. Ohne das waere .section-h (jetzt 1.5rem, hier nicht heruntergesetzt)
     GROESSER als .section-h-lg gewesen - die Reihenfolge der Rollen waere auf dem
     Telefon gekippt. Deshalb bekommt .section-h hier zusaetzlich einen eigenen
     mobilen Wert, den es vorher nicht brauchte. */
  h1.page-h1 { font-size: 1.875rem; }
  h2.section-h-lg { font-size: 1.625rem; }
  h2.section-h { font-size: 1.375rem; }
  .contact-card { padding: 22px; }
  /* Lemniscus braucht laut Doku >= 400px Inhaltsbreite. Auf schmalen Geraeten wird die
     Maske deshalb skaliert (Skript auf termin-buchen.html) — damit der Faktor moeglichst
     nah an 1 bleibt, bekommt sie hier so viel Breite wie moeglich: der Kasten wird
     schmaler gepolstert und die Maske ragt in die Polsterung hinein.
     Siehe Wissensbasis-Thema 02 "Lemniscus (my/OT) einbinden" §5. */
  /* Nur fuer die Rueckfallebene ohne JavaScript: dort bleibt die Maske 400px
     breit und wird geschoben. Bei aktiver Skalierung hebt .is-scaled das auf. */
  .pss-fit:not(.is-scaled) { -webkit-overflow-scrolling: touch; }
  /* Die Polsterung von <section> kostet hier 24px pro Seite (.inner hat seit
     27.09.2026 keine eigene mehr, Review D5). Der Buchungskasten holt sich 12px davon zurueck und steht damit 12px vom
     Bildschirmrand — genug, dass er weiter als Kasten lesbar bleibt (runde Ecken,
     Schatten), aber breit genug, dass die Maske meist gar nicht skaliert werden muss.
     Bewusst feste Werte statt 100vw: vw rechnet die Scrollleiste mit und erzeugt auf
     dem Desktop waagrechtes Scrollen. */
  .booking-card { margin-left: -12px; margin-right: -12px; padding-left: 14px; padding-right: 14px; }
  .booking-card .pss-fit { margin-left: -14px; margin-right: -14px; }
  /* Bild im Hero/Portrait unter den Text auf Mobile */
  .hero-grid > .imgfull { order: -1; }
  /* Einspaltig wuerde das ungeschnittene Hochformat sonst riesig — Breite begrenzen
     statt das Bild wieder zu beschneiden (Georg 06.09.2026). */
  .hero-grid > .imgfull { max-width: 420px; width: 100%; margin-inline: auto; }

  .grid3 { grid-template-columns: 1fr; }

  .location-row { flex-direction: column; align-items: flex-start; gap: var(--space-16); }

  h1.hero-h1 { font-size: 2.25rem; }

  .teaser-row { flex-direction: column; align-items: flex-start; gap: var(--space-12); }
  /* Einspaltig darf der Satz nicht auf seine flex-basis wachsen, sonst klafft
     eine Luecke zwischen Satz und Knopf. */
  .teaser-satz { flex: 0 1 auto; }
}

/* Zwischenbreite: Galerie dreispaltig */
@media (max-width: 1060px) and (min-width: 861px) {
  .gallery-5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Kleine Phones */
@media (max-width: 460px) {
  header { padding: 14px 18px; }
  section { padding: var(--space-40) 18px; }
  footer { padding: var(--space-32) 18px; }
  /* Hier kostet <section> nur noch 18px pro Seite — der Kasten holt 10px zurueck und
     steht wie vorher 8px vom Bildschirmrand. */
  .booking-card { margin-left: -10px; margin-right: -10px; }
  h1.hero-h1 { font-size: 2rem; }
  h1.page-h1 { font-size: 1.75rem; }
  .map-wrap { height: 280px; }
}


/* ---- Bild im Zweispalter ungeschnitten (Georg 26.09.2026) ----
   Das 340-px-Limit fuer Zweispalter-Bilder schnitt beim Hochformat unter
   "Mein fachlicher Hintergrund." den Kopf ab. .uncropped laesst das Bild in
   seinem natuerlichen Verhaeltnis laufen (bei 339 px Spaltenbreite ~508 px hoch).
   Muss nach der 340-px-Regel oben stehen (gleiche Spezifitaet). */
.imgfull.uncropped img { max-height: none; height: auto; }
/* Einspaltig (Tablet/Handy) waere das Hochformat ungebremst bis ~1200 px hoch.
   Dort wieder begrenzen, aber mit dem Ausschnitt oben, damit der Kopf drin bleibt. */
@media (max-width: 860px) {
  .imgfull.uncropped img { max-height: 560px; object-position: 50% 15%; }
}

/* ---- Verfuegbarkeits-Hinweis auf der Startseite (Georg 26.09.2026) ----
   Umschaltbar ueber SITE.availability_variant. Die Kachel-Varianten davor (volle
   Breite, dann T3 in der Hero-Spalte) sind entfallen; .teaser & Co. bleiben in
   style.css als Vorlage fuer den geparkten Live-Teaser. */
/* K2 (aktiv): Pille ueber der Hero-Ueberschrift */
.hero-badge { margin-bottom: var(--space-24); }
.hero-badge svg { flex: none; }
/* K1 (Alternative): schmale Leiste unter der Kopfzeile */
.notice-bar { background: var(--secondary-container); color: var(--on-secondary-container); font-size: 0.9375rem; line-height: 1.45; }
.notice-bar-in { max-width: 1120px; margin: 0 auto; padding: 6px var(--space-48); display: flex; align-items: center; gap: var(--space-12); }
.notice-bar-ico { display: flex; flex: none; }
.notice-bar-in .btn-text { margin-left: auto; color: var(--on-secondary-container); white-space: nowrap; }
@media (max-width: 860px) {
  .notice-bar-in { padding: 10px 18px; flex-wrap: wrap; gap: var(--space-4) var(--space-12); font-size: 0.875rem; }
  .notice-bar-txt { flex: 1 1 200px; }
  .notice-bar-in .btn-text { margin-left: -16px; padding-top: var(--space-4); padding-bottom: 6px; }
}

/* ---- Groesseres Bild im Zweispalter (Georg 26.09.2026) ----
   "Welche Rolle die Musik spielt." und "Mein fachlicher Hintergrund.": Bildspalte
   ~30 % breiter (0.9fr statt 0.7fr). */
/* Nur zweispaltig: stuende die Regel ungeschuetzt hier, ueberschriebe sie den
   einspaltigen 860er-Block weiter oben (spaeter in der Datei gewinnt) - das Bild
   schrumpfte auf dem Handy auf ~110 px (27.09.2026 gefunden). */
@media (min-width: 861px) { .two-col-rev.img-large { grid-template-columns: 1.1fr 0.9fr; } }

/* ---- Bildbreite und -ausrichtung im Zweispalter (27.09.2026, Review D3) ----
   Ersetzt die Einmal-Klassen .w90, .w92 und .h-278. Nur zweispaltig; einspaltig volle
   Breite. .h-278 war am Desktop ohnehin die volle Spaltenbreite (438 px bei 436 px
   Spalte) und ist ersatzlos weg - die Hoehe folgt dem Seitenverhaeltnis der Datei. */
@media (min-width: 861px) {
  .imgfull.bild-90 { width: 90%; }
  .imgfull.rechts { justify-self: end; }
}

/* ---- Bild, das nie beschnitten werden darf (Georg 26.09.2026) ----
   Der Schriftzug oben auf der Tanztherapie-Seite: einspaltig wuerde .uncropped
   ihn auf 560 px kappen und "Therapie" abschneiden. Stattdessen die Breite
   begrenzen, wie beim Hero-Foto. */
@media (max-width: 860px) {
  .imgfull.whole { max-width: 420px; width: 100%; margin-inline: auto; }
  .imgfull.whole img { max-height: none; }
}

/* ---- Seitenkopf mit Hochformat auf "Angebot & Ablauf" (Variante A1, Georg 27.09.2026) ----
   Seitenueberschrift, Einleitung und "Was ich anbiete." links, rechts ein Hochformat 4:5,
   das oben mit der Ueberschrift beginnt. Einspaltig steht das Bild ganz oben.
*/
.offer-head-grid { display: grid; grid-template-columns: 1.25fr 0.85fr; gap: var(--space-64); align-items: start; }
.offer-head p.body-text { margin-top: var(--space-20); }
.offer-head-list { margin-top: var(--space-48); }
.offer-head-img img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; max-height: none; }
@media (max-width: 860px) {
  .offer-head-grid { grid-template-columns: 1fr; gap: var(--space-28); }
  /* Bildposition einspaltig seit 27.09.2026 ueber .bild-nach-titel (unten): unter der
     Seitenueberschrift statt ganz oben (Georg). */
}

/* .offer-band (Variante A2) am 27.09.2026 entfernt, Review C4. */

/* ---- 404-Seite: Fussleiste immer am unteren Rand (Georg 27.09.2026) ----
   Die Seite ist kurz; ohne das endet der Footer mitten im Bildschirm. Nur hier
   gesetzt, damit die langen Seiten unberuehrt bleiben. body traegt seit 27.09.2026
   die Klasse page-<name> (base.html.j2). */
body.page-404 { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
body.page-404 main { flex: 1 0 auto; }

/* ---- Kontaktkachel: kurzer Hinweis unter einem Kontaktweg (WhatsApp, 27.09.2026) ---- */
.contact-note { font-family: var(--font-body); font-size: 0.875rem; line-height: 1.5;
  color: var(--on-surface-variant); margin-top: 2px; }
.contact-note a { color: var(--primary); }

/* ---- Terminbuchung: Rueckfall, wenn der Kalender nicht laedt (27.09.2026, Review S4) ----
   Dann weder der "Freie Termine anzeigen"-Knopf noch die leere Maske - nur der Hinweis. */
.pss-ausfall { margin-top: var(--space-20); }
.pss-ausfall a { color: var(--primary); font-weight: 700; }
body.pss-ausgefallen .pss-open,
body.pss-ausgefallen .pss-fit { display: none !important; }

/* ---- Zeilenumbrueche (27.09.2026, Review D15) ----
   Ueberschriften und Zitate gleichmaessig verteilen, Fliesstext ohne einzelnes
   Wort in der letzten Zeile. Browser ohne Unterstuetzung ignorieren es folgenlos. */
h1, h2, h3 { text-wrap: balance; }
/* Zitate bewusst NICHT balance: das kuerzte ihre Zeilen je nach Text auf 516-649 px -
   Zitate liefen dadurch unterschiedlich breit (Georg 27.09.2026). pretty reicht. */
.quote p { text-wrap: pretty; }
p, li, figcaption, .faq-a { text-wrap: pretty; }
/* E-Mail-Adresse nicht am Bindestrich trennen - "praxis- / newbalance.de" las sich
   wie zwei Adressen. */
.contact-value a { white-space: nowrap; }

/* ---- Bild so hoch wie der Text daneben (27.09.2026, Georg) ----
   "Mein fachlicher Hintergrund.": das Portraet war hoeher als der Text (430 zu 383 px).
   Statt einer Breite, die nur zu genau diesem Text passt, fuellt das Bild die Hoehe der
   Textspalte und schneidet oben/unten per object-fit (Kopf bleibt drin). Nur zweispaltig. */
@media (min-width: 861px) {
  .imgfull.bild-texthoch { align-self: stretch; position: relative; min-height: 260px; }
  .imgfull.bild-texthoch img { position: absolute; inset: 0; width: 100%; height: 100%;
    max-height: none; object-fit: cover; object-position: 50% 20%; }
}

/* ---- Gleiche Abstaende oben und unten in jedem Abschnitt (27.09.2026, Georg) ----
   Unten kam zum Abschnittsabstand der Aussenabstand des letzten Elements dazu
   (Absatz 16, Bilderreihe 24, ...): oben 72, unten bis zu 120 px. Das letzte Element
   eines Abschnitts - auch verschachtelt in Spalte oder Block - hat deshalb unten keinen. */
section > .inner > :last-child,
section > .inner > :last-child > :last-child,
section > .inner > :last-child > :last-child > :last-child { margin-bottom: 0; }
@media (max-width: 860px) {
  section.page-head:has(+ section.alt) { padding-bottom: var(--space-48); }
  section.page-head + section.alt { padding-top: var(--space-48); }
}
@media (max-width: 460px) {
  section.page-head:has(+ section.alt) { padding-bottom: var(--space-40); }
  section.page-head + section.alt { padding-top: var(--space-40); }
}

/* ---- Einspaltig: Bild direkt unter die Ueberschrift (Georg 27.09.2026) ----
   Am Handy stand das Bild bisher je nach Quelltext-Reihenfolge ueber der Ueberschrift
   oder unter dem ganzen Text. Mit .bild-nach-titel am Raster gilt einspaltig:
   Ueberschrift -> Bild -> Rest des Textes. Beginnt die Textspalte nicht mit einer
   Ueberschrift (Tanztherapie oben, die H1 steht dort ausserhalb des Rasters), steht
   das Bild vor dem Text. Technik: die Textspalte wird per display:contents aufgeloest,
   ihre Kinder werden selbst Rasterzellen und per order sortiert. Zweispaltig
   unveraendert. Genutzt auf: Startseite "Wer dich begleitet.", Tanztherapie oben und
   "Welche Rolle die Musik spielt.", Angebot & Ablauf oben.
   Selektoren bewusst mit "section > .inner": sonst gewinnen .inner.two-col (Abstand)
   und die Letztes-Kind-Regel "section > .inner > :last-child" (Bildabstand). */
@media (max-width: 860px) {
  section > .inner.bild-nach-titel { row-gap: 0; }
  .bild-nach-titel > div:not(.imgfull) { display: contents; }
  .bild-nach-titel > div:not(.imgfull) > * { order: 2; }
  .bild-nach-titel > div:not(.imgfull) > :is(h1, h2):first-child { order: 0; }
  .bild-nach-titel > div:not(.imgfull) > h1:first-child { margin-bottom: var(--space-20); }
  .bild-nach-titel > div:not(.imgfull) > a { justify-self: start; }
  section > .inner.bild-nach-titel > .imgfull { order: 1; margin-bottom: var(--space-24); }
  /* Angebot & Ablauf: der Einleitungsabsatz hat oben 20 px Abstand zur H1 - unter dem
     Bild waeren das 44 px. */
  .offer-head .bild-nach-titel p.body-text { margin-top: 0; }
}

/* Wortmarke auf schmalen Handys (aus v2b "B1"): Unterzeile bricht nach "und" um */
@media (max-width: 460px) {
  .wm { gap: 6px; }
  .wm-zeile { line-height: 1.5; letter-spacing: .16em; }
}
