/* =========================================================
   Kieferorthopädie Krefeld-Hüls — „Warm Editorial"
   Design-System, Layout & Motion · handgeschriebenes CSS
   ---------------------------------------------------------
   Richtung : Magazin / Field-Guide. Nummerierte Sektionen,
              große Grotesk-Headlines (Inter Tight, eng),
              Haarlinien, asymmetrisches Raster, viel Weißraum.
   Schriften: Inter Tight (Display) + Inter (Body) — freie
              Entsprechung zu Sequel Sans Disp/Body (thedrake.ca),
              lokal selbst gehostet, variabel 100–900.
   ========================================================= */

/* ---------- Fonts (lokal, font-display:swap) ---------- */
@font-face{
  font-family:'Inter Tight';
  font-style:normal;
  font-weight:100 900;
  font-display:swap;
  src:url('../assets/fonts/inter-tight-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Inter Tight';
  font-style:normal;
  font-weight:100 900;
  font-display:swap;
  src:url('../assets/fonts/inter-tight-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:100 900;
  font-display:swap;
  src:url('../assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:100 900;
  font-display:swap;
  src:url('../assets/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

@font-face{
  font-family:'Instrument Serif';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url('../assets/fonts/instrument-serif-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Instrument Serif';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url('../assets/fonts/instrument-serif-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* ---------- Design-Tokens ---------- */
:root{
  /* Farbsystem — genau diese 5 + AA-Variante */
  --paper:#FBF8F5;       /* Hintergrund                         */
  --ink:#211C18;         /* Text                                */
  --orange:#EC7405;      /* Markenakzent (Flächen/Icons)        */
  --orange-text:#A8500A; /* Orange-Text auf Papier (WCAG AA)    */
  --espresso:#2B2520;    /* dunkle Sektionen                    */
  --sand:#E7DDD1;        /* Linien / sanfte Flächen             */

  /* abgeleitete Töne (aus dem System, kein neuer Farbton) */
  --graphite:#45403C;            /* dunkles Grau für große Fließtext-Blöcke */
  --ink-70:rgba(33,28,24,.66);   /* Sekundärtext auf Papier      */
  --ink-45:rgba(33,28,24,.46);   /* Tertiär / Captions           */
  --hair:rgba(33,28,24,.14);     /* Haarlinie auf Papier         */
  --paper-2:#F4EEE6;             /* zarte Fläche                 */
  --on-dark:#F4ECE2;             /* Text auf Espresso            */
  --on-dark-60:rgba(244,236,226,.62);
  --hair-dark:rgba(244,236,226,.16);
  --near-black:#0E0C0A;          /* warmes Near-Black (Orbital/Technik)  */
  /* Helles Blau — bewusste Erweiterung des Fünf-Farben-Systems, ausschließlich
     für die selbstzeichnende Linie auf ablauf.html. Erreicht auf Papier 3,4:1
     und genügt damit der Mindestanforderung für grafische Elemente. */
  --sky-line:#4E8DB5;
  /* Grundton des Ablauf-Bildschirms: --orange so weit ins Papier gezogen,
     dass es weich bleibt und Tinte darauf 9,8:1 erreicht. */
  --flow-warm:#F6BC85;
  /* Wie weit der gesamte Bildschirm ins Orange gezogen ist (0…1).
     js/main.js (initWarm) schreibt den Wert aus dem Abstand zum
     Ablauf-Abschnitt; jede Papierfläche mischt sich darüber synchron
     mit dem Scrollweg hin und wieder zurück. */
  --warm:0;
  --surface:color-mix(in srgb, var(--flow-warm) calc(var(--warm) * 100%), var(--paper));

  /* Schrift */
  --font-display:'Inter Tight','Helvetica Neue',Arial,system-ui,sans-serif;
  --font-body:'Inter','Helvetica Neue',Arial,system-ui,sans-serif;
  /* Redaktionelle Serife für die großen Bild-Aussagen (Rundgang, Leistungsliste).
     Instrument Serif steht unter der SIL Open Font License 1.1. */
  --font-serif:'Instrument Serif',Georgia,'Times New Roman',serif;

  /* Form — kantig: keine Pillen mehr, nur eine Haarkante gegen harte Pixelecken */
  --maxw:1240px;
  --gutter:clamp(1.25rem,5vw,3.5rem);
  --rad:2px;
  --rad-sm:2px;
  --rad-pill:2px;

  /* vertikaler Rhythmus */
  --section-y:clamp(4.5rem,10vw,9rem);

  /* Easing */
  --ease-out:cubic-bezier(.16,1,.3,1);
  --spring:cubic-bezier(.34,1.56,.64,1);
}

/* ---------- Reset ---------- */
*,*::before,*::after{box-sizing:border-box}
*{margin:0}
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:6rem;
}
/* Mit JS übernimmt das eigene Smooth-Scrolling (js/main.js) die Führung;
   natives scroll-behavior:smooth würde jeden Lerp-Frame erneut animieren. */
html.js{scroll-behavior:auto}
body{
  font-family:var(--font-body);
  font-weight:400;
  color:var(--ink);
  background:var(--surface);
  font-size:1.0625rem;        /* 17px */
  line-height:1.62;
  letter-spacing:.002em;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img,svg{display:block;max-width:100%}
img{height:auto}
a{color:inherit;text-decoration:none}
button,input,textarea,select{font:inherit;color:inherit}
ul{list-style:none;padding:0}
::selection{background:var(--orange);color:#fff}

/* ---------- Typografie ---------- */
h1,h2,h3,h4{
  font-family:var(--font-display);
  font-weight:540;                 /* Grotesk-Medium — Drake-Optik */
  line-height:1.04;
  letter-spacing:-.022em;
  text-wrap:balance;
}

/* Sektionskopf-Bausteine — schlichtes Label statt Strich + Versalien */
.kicker{
  display:block;
  font-family:var(--font-body);font-weight:500;
  font-size:.94rem;letter-spacing:0;text-transform:none;
  color:var(--ink-70);
}
.section--dark .kicker{color:var(--on-dark-60)}

.lede{
  font-size:clamp(1.12rem,1.8vw,1.4rem);
  line-height:1.5;
  color:var(--ink-70);
  font-weight:400;
}
.measure{max-width:42rem}
.measure-sm{max-width:32rem}

/* ---------- Layout-Helfer ---------- */
.container{
  width:100%;max-width:var(--maxw);margin-inline:auto;
  padding-inline:var(--gutter);
}
.section{padding-block:var(--section-y);background:var(--surface)} /* opak: deckt den Sticky-Hero ab */
.section--dark{background:var(--espresso);color:var(--on-dark)}
.section--dark .lede{color:var(--on-dark-60)}
.section--dark .kicker{color:#F0A35A}

.rule{height:1px;background:var(--hair);border:0}
.section--dark .rule{background:var(--hair-dark)}

/* Sektionskopf: nur noch der Titel. Auf der Startseite nennt das wandernde
   Sektionswort das Thema — ein Label darüber wäre die zweite Nennung. */
.head{display:block}
.head__main{max-width:54rem}
.head__title{
  font-size:clamp(2rem,4.6vw,3.5rem);
  margin:0;
}
/* Unterseiten führen weiter ein Label; dort braucht der Titel seinen Abstand. */
.kicker + .head__main .head__title{margin-top:clamp(1.5rem,3.6vw,2.6rem)}
.head__lede{margin-top:1.1rem}

/* ---------- Buttons — eckig, schwarz/weiß ---------- */
.btn{
  position:relative;
  isolation:isolate;overflow:hidden;
  display:inline-flex;align-items:center;justify-content:center;gap:.6rem;
  font-family:var(--font-body);font-weight:600;font-size:1rem;
  line-height:1;letter-spacing:.005em;white-space:nowrap;
  padding:1.02rem 1.7rem;
  border-radius:var(--rad-pill);
  border:1px solid transparent;
  cursor:pointer;
  min-height:48px;
  transition:background .2s var(--ease-out),color .25s var(--ease-out),
             border-color .2s var(--ease-out);
}
.btn svg{width:1.15em;height:1.15em;flex:0 0 auto}
.btn--primary{background:var(--ink);color:var(--paper)}
.btn--primary:hover,.btn--primary:focus-visible{color:var(--ink)}
.btn--ghost{background:transparent;color:var(--ink);border-color:var(--hair)}
.btn--ghost:hover,.btn--ghost:focus-visible{border-color:var(--ink);color:var(--paper)}
.section--dark .btn--primary{background:var(--on-dark);color:var(--espresso)}
.section--dark .btn--primary:hover,.section--dark .btn--primary:focus-visible{color:var(--on-dark)}
.section--dark .btn--ghost{color:var(--on-dark);border-color:var(--hair-dark)}
.section--dark .btn--ghost:hover,.section--dark .btn--ghost:focus-visible{border-color:var(--on-dark);color:var(--espresso)}

/* Origin-Fill: ein Kreis wächst aus der Cursor-Position und füllt den Button.
   z-index:-1 + isolation:isolate ⇒ die Füllung liegt über dem Button-Hintergrund,
   aber unter Text/Icon (auch unter losem Textinhalt). Ursprung/Größe via main.js. */
.btn__fill{
  position:absolute;top:var(--oy,50%);left:var(--ox,50%);
  width:var(--d,0);height:var(--d,0);
  border-radius:50%;background:var(--paper);
  transform:translate(-50%,-50%) scale(0);
  transition:transform .5s var(--ease-out);
  pointer-events:none;z-index:-1;
}
.btn--ghost .btn__fill{background:var(--ink)}
.section--dark .btn--primary .btn__fill{background:var(--espresso)}
.section--dark .btn--ghost .btn__fill{background:var(--on-dark)}
.btn:hover .btn__fill,
.btn:focus-visible .btn__fill,
.btn:active .btn__fill{transform:translate(-50%,-50%) scale(1)}

/* --- CTA-Variante („Modern Button", Uiverse-Idee): der Kreis wächst aus der
   Mitte, der Pfeil rechts zieht hinaus, ein zweiter rückt von links nach,
   und die Beschriftung gleitet mit. Reines CSS, kantig statt rund. --- */
/* Zum seitlichen Innenabstand: die Pfeile stehen absolut, der Abstand
   zwischen Beschriftung und Pfeil ist deshalb genau
   Innenabstand − .55em (Ruheversatz der Zeile) − 1rem (Pfeilposition)
   − 1.1em (Pfeilbreite). Bei den früheren 1.45rem ergab das −2px, der
   Pfeil klebte also an den Buchstaben. 2.6rem ergeben ~16px Luft, auf
   beiden Seiten gleich. */
.btn--cta{
  gap:.4rem;padding:.86rem 2.6rem;min-height:44px;
  background:transparent;color:var(--ink);
  box-shadow:inset 0 0 0 1.5px var(--ink);
  transition:color .5s var(--ease-out),box-shadow .5s var(--ease-out);
}
.btn--cta .btn__fill{
  top:50%;left:50%;width:0;height:0;background:var(--ink);
  transition:width .7s var(--ease-out),height .7s var(--ease-out);
  transform:translate(-50%,-50%);
}
.btn--cta:hover,.btn--cta:focus-visible{color:var(--paper);box-shadow:inset 0 0 0 1.5px var(--ink)}
.btn--cta:hover .btn__fill,
.btn--cta:focus-visible .btn__fill{width:26rem;height:26rem;transform:translate(-50%,-50%)}
.btn--cta .btn__arr{
  position:absolute;width:1.1em;height:1.1em;
  transition:right .7s var(--ease-out),left .7s var(--ease-out),fill .5s var(--ease-out);
  fill:currentColor;
}
.btn--cta .btn__arr--out{right:1rem}
.btn--cta .btn__arr--in{left:-30%}
.btn--cta .btn__label{
  position:relative;z-index:1;
  transform:translateX(-.55em);
  transition:transform .7s var(--ease-out);
}
.btn--cta:hover .btn__arr--out,.btn--cta:focus-visible .btn__arr--out{right:-30%}
.btn--cta:hover .btn__arr--in,.btn--cta:focus-visible .btn__arr--in{left:1rem}
.btn--cta:hover .btn__label,.btn--cta:focus-visible .btn__label{transform:translateX(.55em)}
.btn--cta:active{scale:.97}

/* Textlink mit Pfeil */
.arrow-link{
  display:inline-flex;align-items:center;gap:.5rem;
  font-weight:600;color:var(--orange-text);
  padding-block:.2rem;
}
.arrow-link svg{width:1.05em;height:1.05em;transition:transform .25s var(--ease-out)}
.arrow-link:hover svg{transform:translateX(4px)}
.section--dark .arrow-link{color:#F0A35A}

/* ---------- Skip-Link ---------- */
.skip{
  position:fixed;left:1rem;top:-4rem;z-index:200;
  background:var(--ink);color:#fff;padding:.7rem 1.1rem;border-radius:var(--rad-sm);
  font-weight:600;transition:top .2s var(--ease-out);
}
.skip:focus{top:1rem}

/* sichtbarer Fokus überall */
:focus-visible{outline:3px solid var(--orange);outline-offset:3px;border-radius:6px}
.section--dark :focus-visible{outline-color:#F6A355}

/* ============================================================
   HEADER — zwei Zustände, kein eigener Hintergrund
   Oben (Seitenanfang): eine Leiste von links nach rechts über die
   volle Breite — [Logo] [Navigation] … [Termin vereinbaren].
   Ab dem ersten Scrollen (.is-stuck): die Navigation weicht der
   kompakten Gruppe [großes Logo] [Menü]; das Menü klappt die
   Kategorien eng untereinander auf. Keine Umrandung, keine
   Glasfläche — der Seitenhintergrund läuft durch.
   ============================================================ */
.site-header{
  position:fixed;top:0;left:0;right:0;z-index:90;
  padding:clamp(.85rem,1.6vw,1.35rem) var(--gutter) 0;
  pointer-events:none;                 /* nur Bedienelemente sind klickbar */
  background:transparent;border:0;
}
.site-header > *{pointer-events:auto}

.nav{display:flex;align-items:center;gap:clamp(1.2rem,3vw,2.6rem);position:relative}
.nav__brand{display:inline-flex;align-items:center;flex:0 0 auto}
.nav__brand img{
  width:auto;height:2.4rem;display:block;
  transition:height .55s var(--ease-out);
}

/* Navigationslinks — im Top-Zustand direkt neben dem Logo */
.nav__links{display:flex;align-items:center;gap:clamp(1rem,2.2vw,2rem);flex:1 1 auto}
.nav__cta{margin-left:auto;flex:0 0 auto}

/* „Menü" — steht am rechten Rand genau auf der Höhe der Leistenmitte, also
   dort, wo im Top-Zustand die Terminschaltfläche sitzt. Dadurch nimmt es nie
   Platz weg, das Raster bleibt ruhig, und beim Scrollen wird aus der
   Schaltfläche sichtbar das Menü.

   Es hängt bewusst NICHT in der Kopfleiste, sondern am Ende des Dokuments
   (js/main.js hängt es dorthin um): nur außerhalb des Stapelkontexts, den die
   feste Leiste aufspannt, erreicht `difference` den Seiteninhalt. Damit hellt
   sich der Knopf über dunklen Flächen von selbst auf und dunkelt über hellen
   nach — dieselbe Mechanik wie beim Sektionswort, ohne jede Umschaltlogik.
   --navmid ist die gemessene Mitte der Leiste (js/main.js: setNavMid). */
.nav__menu{
  position:fixed;z-index:95;right:var(--gutter);top:var(--navmid,2.6rem);
  border:0;background:none;padding:0;cursor:pointer;
  font-family:var(--font-display);font-weight:560;
  letter-spacing:-.01em;color:#fff;
  mix-blend-mode:difference;
  opacity:0;visibility:hidden;pointer-events:none;
  transform:translateY(calc(-50% + .5em));
  transition:opacity .45s var(--ease-out),transform .45s var(--ease-out),
             visibility 0s linear .45s;
}
/* Die Sammelregeln für .rollover setzen beim Überfahren auf --ink zurück —
   hier muss die Schrift Weiß bleiben, sonst fällt das Blenden aus. */
.nav__menu .rollover,
.nav__menu:hover .rollover,
.nav__menu:focus-visible .rollover{color:#fff}
/* „Menü" ↔ „Schließen": Der Knopf steht rechts fest, seine Breite kommt aber
   aus der sichtbaren Zeile. Beim Wechsel wäre das doppelt falsch — das längere
   Wort würde an der Maskenkante abgeschnitten, und sobald die Zeile es
   übernimmt, spränge der Kasten in die Breite und das Wort nach links.
   Ein unsichtbarer Platzhalter (js/main.js legt ihn an) hält deshalb dauerhaft
   die Breite des längeren Wortes; beide Lagen richten sich rechts aus. */
.nav__menu .rollover{text-align:right}
.nav__menu .rollover::before{left:auto;right:0}
.rollover__size{
  display:block;height:0;overflow:hidden;
  visibility:hidden;pointer-events:none;
}

/* --- gescrollt: die Leiste wechselt ihre Gestalt in einem Übergang ---
   display lässt sich nicht überblenden und war die Ursache des Ruckens.
   Stattdessen blenden Links und Terminschaltfläche gestaffelt nach oben weg,
   „Menü" blendet an derselben Stelle ein und das Logo wächst — alles im
   selben Zeitfenster, sodass die Leiste morpht statt umzuspringen. --- */
.nav__link{transition:opacity .42s var(--ease-out),transform .42s var(--ease-out)}
.nav__links{transition:visibility 0s linear 0s}
/* .btn schreibt seine Transition weiter unten in der Motion-Schicht noch
   einmal — deshalb hier beide Klassen, sonst fiele der Rückweg hart zurück. */
.btn.nav__cta{
  transition:opacity .42s var(--ease-out),transform .42s var(--ease-out),
             color .5s var(--ease-out),box-shadow .5s var(--ease-out),
             visibility 0s linear 0s;
}

.is-stuck .nav__link,
.is-stuck .nav__cta{opacity:0;transform:translateY(-.55em)}
/* von links nach rechts auflösen — das liest sich als Bewegung, nicht als Schnitt */
.is-stuck .nav__link:nth-child(2){transition-delay:.035s}
.is-stuck .nav__link:nth-child(3){transition-delay:.07s}
.is-stuck .nav__link:nth-child(4){transition-delay:.105s}
.is-stuck .nav__link:nth-child(5){transition-delay:.14s}
.is-stuck .nav__link:nth-child(6){transition-delay:.175s}
/* erst nach der Blende aus dem Tastaturfluss nehmen */
.is-stuck .nav__links{visibility:hidden;pointer-events:none;transition:visibility 0s linear .62s}
.is-stuck .btn.nav__cta{
  visibility:hidden;pointer-events:none;
  transition:opacity .42s var(--ease-out) .21s,transform .42s var(--ease-out) .21s,
             color .5s var(--ease-out),box-shadow .5s var(--ease-out),
             visibility 0s linear .63s;
}

/* Am Wurzelelement, nicht an der Leiste: der Knopf steht außerhalb von ihr. */
.nav-stuck .nav__menu{
  opacity:1;visibility:visible;pointer-events:auto;
  transform:translateY(-50%);
  transition:opacity .45s var(--ease-out) .16s,transform .45s var(--ease-out) .16s,
             visibility 0s linear 0s;
}
.is-stuck .nav__brand img{height:3.125rem}   /* 2,5× der früheren Scroll-Größe */

/* --- Roll-up-Hover (Vorbild fame-estate.com): die Beschriftung fährt nach
   oben heraus, während dieselbe Beschriftung von unten nachrückt. Die zweite
   Fassung liefert content:attr(data-text) — kein doppeltes Markup. --- */
.rollover{
  position:relative;display:block;overflow:hidden;
  font-family:var(--font-display);font-weight:560;font-size:1.02rem;
  letter-spacing:-.01em;line-height:1.25;color:var(--ink);
  white-space:nowrap;
}
.rollover::before{
  content:attr(data-text);
  position:absolute;left:0;top:0;
  transform:translateY(100%);          /* wartet exakt eine Zeile tiefer */
  transition:transform .4s var(--ease-out);
}
.rollover__in{
  display:block;
  transition:transform .4s var(--ease-out);
}
a:hover > .rollover,a:focus-visible > .rollover,
button:hover > .rollover,button:focus-visible > .rollover,
.rollover:hover,.rollover:focus-visible{color:var(--ink)}
a:hover .rollover__in,a:focus-visible .rollover__in,
button:hover .rollover__in,button:focus-visible .rollover__in{transform:translateY(-100%)}
a:hover .rollover::before,a:focus-visible .rollover::before,
button:hover .rollover::before,button:focus-visible .rollover::before{transform:translateY(0)}
/* Der aktive Abschnitt bleibt dezent markiert, ohne Farbe zu brauchen */
.nav__link.is-active .rollover{opacity:.45}

/* Beim Öffnen wechselt der Knopf von „Menü" auf „Schließen" — mit derselben
   Roll-Bewegung wie beim Überfahren. js/main.js schaltet .is-swap für die
   Bewegung und .is-nofx für den lautlosen Rücksprung danach. */
.rollover.is-swap .rollover__in{transform:translateY(-100%)}
.rollover.is-swap::before{transform:translateY(0)}
.rollover.is-nofx .rollover__in,
.rollover.is-nofx::before{transition:none}

/* --- Menü-Liste: Kategorien eng untereinander, ohne Nummern --- */
.mpanel{
  /* Schwarze Tafel direkt unter dem Wort „Menü" — deshalb rechts ausgerichtet,
     nicht am linken Satzrand. Absolut, damit die geschlossene Liste die Höhe
     der Leiste nicht aufbläht (die steuert Ankersprung und Sektionswort). */
  position:absolute;top:100%;right:var(--gutter);left:auto;
  display:flex;flex-direction:column;align-items:stretch;
  min-width:min(20rem,72vw);
  margin-top:.7rem;padding:.5rem;
  background:#000;border-radius:var(--rad);
  box-shadow:0 30px 70px -30px rgba(0,0,0,.7);
  /* Die Tafel rollt von der Oberkante herunter und wieder hinauf, statt nur
     ein- und auszublenden (Vorbild lusion.co). clip-path schneidet dabei die
     Fläche ab — die Zeilen darin staffeln getrennt davon. */
  visibility:hidden;pointer-events:none;
  clip-path:inset(0 0 100% 0);transform:translateY(-6px);
  transition:clip-path .42s var(--ease-out),transform .42s var(--ease-out),
             visibility 0s linear .42s;
}
.mpanel.open{
  visibility:visible;pointer-events:auto;
  clip-path:inset(0 0 0 0);transform:none;
  transition:clip-path .6s var(--ease-out),transform .6s var(--ease-out),
             visibility 0s linear 0s;
}
.mpanel__link{
  display:flex;align-items:center;justify-content:space-between;gap:1.5rem;
  padding:.5rem .95rem;
  font-family:var(--font-display);font-weight:560;
  font-size:clamp(1.05rem,1.5vw,1.25rem);line-height:1.3;letter-spacing:-.02em;
  color:#fff;border-radius:10px;
  box-shadow:inset 0 0 0 1.5px transparent;
  /* Geschlossen: die Zeilen weichen von unten zurück, und zwar von der
     letzten zur ersten — die Tafel schließt sich damit von unten her. */
  opacity:0;transform:translateY(8px);
  transition:opacity .2s var(--ease-out) calc((4 - var(--i,0))*.028s),
             transform .26s var(--ease-out) calc((4 - var(--i,0))*.028s),
             color .22s var(--ease-out),
             box-shadow .22s var(--ease-out);
}
/* Die Staffelung darf nur den Aufbau verzögern — Schrift und Rahmen müssen
   beim Überfahren sofort umschlagen, sonst hinkt die letzte Zeile nach. */
.mpanel.open .mpanel__link{
  opacity:1;transform:none;
  transition:opacity .35s var(--ease-out) calc(.03s + var(--i,0)*.035s),
             transform .4s var(--ease-out) calc(.03s + var(--i,0)*.035s),
             color .22s var(--ease-out),
             box-shadow .22s var(--ease-out);
}
/* Überfahren: oranger, gerundeter Rahmen statt gefüllter Fläche; der Pfeil
   fährt von links herein und die Beschriftung rückt einen Tick nach vorne. */
.mpanel__link:hover,
.mpanel__link:focus-visible{color:var(--orange);box-shadow:inset 0 0 0 1.5px var(--orange)}
.mpanel__link:focus-visible{outline-offset:-3px}
.mpanel__label{transition:transform .42s var(--ease-out)}
.mpanel__link:hover .mpanel__label,
.mpanel__link:focus-visible .mpanel__label{transform:translateX(.32em)}
/* Der Pfeil steht frei — kein Kästchen. Er kommt von links hereingeglitten
   und läuft beim Verlassen denselben Weg zurück. */
.mpanel__arr{
  box-sizing:border-box;
  width:1.35em;height:1.35em;flex:0 0 auto;color:var(--orange);
  opacity:0;transform:translateX(-.9em);
  transition:opacity .28s var(--ease-out),transform .45s var(--ease-out);
}
.mpanel__link:hover .mpanel__arr,
.mpanel__link:focus-visible .mpanel__arr{opacity:1;transform:none}
.mpanel__link.is-active .mpanel__label{opacity:.55}

/* „Termin vereinbaren" — gesonderter Eintrag am Fuß der Tafel (Vorbild
   lusion.co „LABS"). Er gehört nicht zur Themenliste, deshalb steht er
   abgesetzt und im Orange des Logos: Icon links, Beschriftung, Diagonalpfeil
   rechts. Auf der schwarzen Tafel hebt ihn die gefüllte Fläche klar ab. */
.mpanel__cta{
  display:flex;align-items:center;gap:.85rem;
  margin-top:.6rem;padding:.85rem 1.05rem;
  background:var(--orange);color:#fff;
  border-radius:10px;text-decoration:none;
  font-family:var(--font-display);font-weight:600;
  font-size:clamp(1.05rem,1.5vw,1.25rem);line-height:1.2;letter-spacing:-.02em;
  /* Kommt als letzte Zeile herein, kurz nachdem die Links stehen. */
  opacity:0;transform:translateY(10px);
  transition:opacity .2s var(--ease-out),transform .26s var(--ease-out),
             background .3s var(--ease-out),box-shadow .3s var(--ease-out);
}
.mpanel.open .mpanel__cta{
  opacity:1;transform:none;
  transition:opacity .4s var(--ease-out) .24s,transform .45s var(--ease-out) .24s,
             background .3s var(--ease-out),box-shadow .3s var(--ease-out);
}
.mpanel__cta:hover,.mpanel__cta:focus-visible{background:#CF6405;box-shadow:0 12px 26px -14px rgba(236,116,5,.9)}
.mpanel__cta:focus-visible{outline:2px solid #fff;outline-offset:-4px}
.mpanel__cta-label{flex:1 1 auto}
/* Pfeilwechsel wie auf bongarth.de: beim Überfahren zieht der Pfeil nach oben
   rechts aus dem Feld und ein zweiter rückt von unten links nach. Das Feld ist
   die Maske — es hat eine feste Größe und `overflow:hidden`, damit der zweite
   Pfeil im Ruhezustand vollständig außerhalb liegt und nirgends hervorlugt.
   Beide Lagen sitzen im selben Rasterfeld, also exakt übereinander; der
   Versatz von 190 % der eigenen Kantenlänge trägt sie sicher aus der Maske. */
.mpanel__cta-ico{
  position:relative;flex:0 0 auto;
  width:1.5em;height:1.5em;
  display:grid;place-items:center;
  overflow:hidden;
}
.mpanel__cta-arr{
  grid-area:1/1;
  width:1.2em;height:1.2em;
  transition:transform .5s cubic-bezier(.76,0,.24,1);
}
.mpanel__cta-arr--clone{transform:translate(-190%,190%)}
.mpanel__cta:hover .mpanel__cta-arr,
.mpanel__cta:focus-visible .mpanel__cta-arr{transform:translate(190%,-190%)}
.mpanel__cta:hover .mpanel__cta-arr--clone,
.mpanel__cta:focus-visible .mpanel__cta-arr--clone{transform:translate(0,0)}

/* „Anrufen" — der zweite Eintrag, direkt unter „Termin vereinbaren". Er steht
   bewusst als Rahmen statt als Fläche: zwei gefüllte Orangeblöcke übereinander
   nähmen dem Termin seine Rolle als Hauptaktion. Weil die Tafel auf ALLEN
   Geräten dieselbe ist, hat damit auch die Desktop-Fassung ihren Anrufweg —
   an genau der Stelle, an der oben die Terminschaltfläche sitzt.
   Die Rufnummer stand hier früher daneben; sie steht weiterhin im Fußbereich
   und im Kontaktabschnitt. */
.mpanel__cta--call{
  margin-top:.45rem;
  background:transparent;color:var(--orange);
  box-shadow:inset 0 0 0 1.5px var(--orange);
  transition:opacity .2s var(--ease-out),transform .26s var(--ease-out),
             background .3s var(--ease-out),color .3s var(--ease-out),
             box-shadow .3s var(--ease-out);
}
/* Kommt eine Spur nach dem Termin-Eintrag herein — die Tafel baut sich damit
   bis zur letzten Zeile von oben nach unten auf. */
.mpanel.open .mpanel__cta--call{
  transition:opacity .4s var(--ease-out) .3s,transform .45s var(--ease-out) .3s,
             background .3s var(--ease-out),color .3s var(--ease-out),
             box-shadow .3s var(--ease-out);
}
.mpanel__cta--call:hover,
.mpanel__cta--call:focus-visible{background:var(--orange);color:#fff;box-shadow:inset 0 0 0 1.5px var(--orange)}
.mpanel__cta--call:focus-visible{outline:2px solid var(--orange);outline-offset:2px}

/* Der Schleier hinter der Vollbild-Tafel gibt es nur auf dem Telefon;
   auf Tablet und Rechner bleibt die Tafel eine Tafel. */
.mpanel__veil{display:none}

/* ============================================================
   MENÜ AUF DEM TELEFON — Vollbild (Vorbild bymonolog.com)
   Dort nimmt beim Öffnen eine schwarze Fläche den Bildschirm ein:
   oben links das Logo, oben rechts „Schließen", darunter die Themen
   groß untereinander mit einem Pfeil am rechten Rand. Was unter der
   Fläche noch zu sehen ist, ist die Seite selbst — gemessen liegt
   dort ein `backdrop-filter:blur(5px)` über `rgba(8,8,7,.65)`.
   Genau diese Aufteilung steht hier. Der orange Akzent der bisherigen
   Tafel bleibt: der Pfeil ist orange und beim Antippen legt sich der
   orange Rahmen um die Zeile.
   ============================================================ */
@media (max-width:640px){
  /* Aus der rechtsbündigen Tafel wird eine Fläche über die volle Breite.
     Bildschirmfest statt am Dokument: sonst rutschte sie beim Scrollen mit
     der Kopfleiste weg. Der obere Innenabstand hält genau die Leistenhöhe
     frei — dort stehen Logo und „Schließen", beide liegen darüber. */
  .mpanel{
    position:fixed;top:0;right:0;bottom:auto;left:0;z-index:1;
    min-width:0;margin:0;
    padding:calc(var(--navmid,2rem) + 1.5rem) 1.1rem 1.6rem;
    border-radius:0;box-shadow:0 40px 60px -40px rgba(0,0,0,.9);
  }
  /* Das Logo muss über der schwarzen Fläche stehen. `.nav` ist zwar
     position:relative, aber ohne z-index — es spannt also keinen eigenen
     Stapelkontext auf, und die Marke kann sich innerhalb der Kopfleiste
     über die Tafel legen. */
  .nav__brand{position:relative;z-index:2}

  /* Der Schleier: die Seite bleibt sichtbar, aber unscharf und abgedunkelt.
     Er liegt als erstes Kind der Kopfleiste unter Tafel und Marke und ist
     zugleich die Fläche, mit der man das Menü wieder schließt. */
  .mpanel__veil{
    display:block;position:fixed;inset:0;z-index:0;
    background:rgba(14,12,10,.55);
    backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px);
    opacity:0;visibility:hidden;pointer-events:none;
    transition:opacity .42s var(--ease-out),visibility 0s linear .42s;
  }
  .menu-open .mpanel__veil{
    opacity:1;visibility:visible;pointer-events:auto;
    transition:opacity .5s var(--ease-out),visibility 0s linear 0s;
  }
  /* Solange das Menü offen ist, steht die Seite dahinter still. */
  html.menu-open,html.menu-open body{overflow:hidden}

  /* Die Themen groß untereinander, jede Zeile durch eine Haarlinie
     abgesetzt und mit dem orangen Pfeil am rechten Rand. */
  .mpanel__link{
    padding:.72rem .35rem;
    font-size:clamp(1.9rem,8.6vw,2.9rem);letter-spacing:-.03em;line-height:1.15;
    border-radius:8px;
    border-bottom:1px solid rgba(255,255,255,.16);
    transform:translateY(1.1rem);
    transition:opacity .2s var(--ease-out) calc((4 - var(--i,0))*.03s),
               transform .28s var(--ease-out) calc((4 - var(--i,0))*.03s),
               color .22s var(--ease-out),
               box-shadow .22s var(--ease-out);
  }
  .mpanel.open .mpanel__link{
    transition:opacity .38s var(--ease-out) calc(.05s + var(--i,0)*.055s),
               transform .48s var(--ease-out) calc(.05s + var(--i,0)*.055s),
               color .22s var(--ease-out),
               box-shadow .22s var(--ease-out);
  }
  /* Ohne Mauszeiger gibt es kein Überfahren — der Pfeil steht deshalb
     dauerhaft und in Orange, und der Rahmen kommt beim Antippen. */
  .mpanel__arr{opacity:1;transform:none;width:1.15em;height:1.15em}
  .mpanel__link:active{color:var(--orange);box-shadow:inset 0 0 0 1.5px var(--orange)}
  .mpanel__link:active .mpanel__label{transform:translateX(.32em)}

  .mpanel__cta{margin-top:1.15rem;padding:1rem 1.05rem;font-size:1.14rem}
  .mpanel__cta--call{margin-top:.55rem}
  /* Ohne Mauszeiger gibt es kein Überfahren — der Pfeilwechsel läuft deshalb
     beim Antippen, damit die Schaltfläche auch hier antwortet. */
  .mpanel__cta:active .mpanel__cta-arr{transform:translate(190%,-190%)}
  .mpanel__cta:active .mpanel__cta-arr--clone{transform:translate(0,0)}
}

/* --- Solange die Leiste über dem dunklen Startbild liegt, dreht sie ins
   Helle. js/main.js setzt .on-dark anhand der echten Hero-Unterkante. --- */
/* Die Menü-Tafel steht auf eigenem Schwarz und braucht diese Umschaltung
   nicht — sie würde sonst mit dem orangen Überfahren kollidieren. */
/* „Menü" ist hier nicht dabei: es blendet sich über `difference` selbst
   gegen den Untergrund auf und steht ohnehin außerhalb der Leiste. */
.site-header.on-dark .rollover{color:#fff}
/* Die Praxismarke bleibt auch über dem dunklen Startbild farbig — sie ist das
   Wiedererkennungsmerkmal. Der weiche Schatten trägt sie über helle Stellen
   des Fotos, ohne den Orangeton zu verfälschen. */
.site-header.on-dark .nav__brand img{filter:drop-shadow(0 1px 10px rgba(0,0,0,.55))}
.site-header.on-dark .btn--cta{color:#fff;box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.85)}
.site-header.on-dark .btn--cta .btn__fill{background:#fff}
.site-header.on-dark .btn--cta:hover,
.site-header.on-dark .btn--cta:focus-visible{color:var(--espresso);box-shadow:inset 0 0 0 1.5px #fff}
/* „Menü" bleibt hier bewusst außen vor — es führt oben seine eigene
   Ein-/Ausblendung und würde von dieser Sammelregel überschrieben. */
.site-header .nav__brand img,
.site-header .rollover{transition:filter .4s var(--ease-out),color .4s var(--ease-out),height .55s var(--ease-out)}

/* ============================================================
   WANDERNDES SEKTIONSWORT (Vorbild noth.in)
   Ein festes Band unter der Kopfleiste zeigt das Thema, bei dem
   man gerade ist. Das Wort bleibt kompakt und lesbar und wandert
   über die Länge des Abschnitts von einer Kante zur anderen —
   die Richtung wechselt je Abschnitt. js/main.js rechnet die
   Buchstabenspuren aus und schreibt je Buchstabe --lx/--ls.
   Die Schrift ist weiß und blendet per difference gegen den
   Hintergrund — dadurch stimmt der Kontrast über hellen wie
   dunklen Sektionen ohne jede Umschaltlogik.
   Rein dekorativ: aria-hidden und ohne Mauszeiger-Fang.
   ============================================================ */
/* Die Lage macht CSS, nicht das Skript. Früher stand das Band bildschirmfest
   und ein Scroll-Handler schrieb je Bild den senkrechten Versatz — auf dem
   Rechner fiel das nicht auf, weil das Rad-Scrolling dort selbst im selben
   rAF-Takt läuft. Auf dem Telefon scrollt der Browser jedoch nebenläufig:
   die geschriebene Verschiebung kam immer ein Bild zu spät, und das Wort
   zitterte gegen die Seite. Jetzt hängt jede Spur in einer eigenen,
   dokumentfesten Schiene (.secword__rail) und ist darin `position:sticky` —
   damit steht sie in der Seite still, bis sie die Halteposition erreicht, und
   klebt danach am Bildschirm. Beides erledigt der Browser selbst.
   Das Skript setzt nur noch Anfang und Länge der Schiene (einmal je Kapitel)
   und den waagerechten Lauf der Buchstaben. */
.secword{
  position:absolute;z-index:80;left:0;right:0;top:0;height:0;
  --band:clamp(6.6rem,9.5vh,8rem);  /* Halteposition — JS liest sie hier ab */
  pointer-events:none;
  display:block;                  /* auf jeder Breite, siehe Media Queries */
  mix-blend-mode:difference;
}
/* Die Schiene reicht vom Kapitelanfang bis zu seinem Ende; js/main.js setzt
   top und height. Solange die Spur darin klebt, gilt das Kapitel. */
.secword__rail{position:absolute;left:0;right:0;top:0;height:0}
/* Zwei Spuren: die im Band und die, die von unten nachrückt. --wy2 rückt das
   Wort im Eck-Fall tiefer und gilt in beiden Zuständen gleichermaßen. */
.secword__row{
  position:sticky;top:var(--band);
  width:100%;max-width:var(--maxw);margin-inline:auto;
  padding-inline:var(--gutter);
  height:clamp(1.7rem,2.2vw,2.3rem);
  transform:translate3d(0,var(--wy2,0px),0);
  opacity:0;
  transition:opacity .3s var(--ease-out);
  will-change:transform;
}
.secword__row.is-on{opacity:1}
/* Über dem Leistungs-Foto richtet sich das Wort nicht am Satzspiegel aus,
   sondern an der Bildecke: derselbe Außenabstand wie .svcintro plus ein
   Innenabstand, und ein Stück tiefer — sonst läge es auf der Bildkante
   statt im Bild. js/main.js setzt die Klasse je Kapitel (`corner`). */
.secword__row.is-corner{
  max-width:none;
  padding-inline:calc(clamp(.5rem,1vw,.9rem) + clamp(1.1rem,2.4vw,2.2rem));
  --wy2:clamp(1.7rem,3.6vh,3.2rem);
}
.secword__ch{
  position:absolute;top:0;left:0;
  font-family:var(--font-display);font-weight:700;
  font-size:clamp(1.5rem,1.9vw,2rem);line-height:1;letter-spacing:-.03em;
  text-transform:uppercase;
  color:#fff;
  transform:translate3d(var(--lx,0px),0,0) scale(var(--ls,1));
  transform-origin:50% 50%;           /* mittig stauchen, nicht aus der Ecke */
  will-change:transform;
}
/* Auf dem Telefon rückt die Spur näher unter die Leiste und wird eine Spur
   kleiner — sonst reichte die Strecke, die das Wort zurücklegen kann, kaum
   über seine eigene Breite hinaus und die Wanderung wäre nicht zu erkennen.
   Der Innenabstand ist derselbe wie der Satzspiegel (var(--gutter)). */
@media (max-width:640px){
  .secword{--band:clamp(4.6rem,7.5vh,6rem)}
  .secword__row{height:clamp(1.3rem,5vw,1.7rem)}
  .secword__ch{font-size:clamp(1.15rem,5vw,1.55rem);letter-spacing:-.035em}
  /* Über dem Leistungsfoto steht das Wort im Bild statt auf seiner Kante;
     mobil ist der Bildrand schmaler, der Einzug also kleiner. */
  .secword__row.is-corner{
    padding-inline:calc(clamp(.5rem,1vw,.9rem) + .9rem);
    --wy2:clamp(1.1rem,2.6vh,2rem);
  }
}

/* ============================================================
   HERO
   ============================================================ */
.hero{
  position:relative;
  min-height:100svh;
  display:flex;flex-direction:column;
  padding-block:clamp(5.5rem,12vh,7.5rem) clamp(2.4rem,6vh,4rem); /* Platz für die feste Leiste */
  overflow:hidden;
  background:var(--espresso);          /* trägt, solange das Foto lädt */
}
.hero>.container{position:relative;z-index:1}

/* --- Vollflächiges Praxisfoto + Abdunklung, damit die Typo sicher trägt --- */
.hero__bg{position:absolute;inset:0;z-index:0;overflow:hidden}
.hero__bg img{width:100%;height:100%;object-fit:cover;object-position:50% 42%}
.hero__bg::after{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(180deg,rgba(14,12,10,.62) 0%,rgba(14,12,10,.18) 34%,rgba(14,12,10,.30) 62%,rgba(14,12,10,.80) 100%),
    linear-gradient(90deg,rgba(14,12,10,.55),transparent 62%);
}

/* --- Heller Hero -------------------------------------------------------
   Das Startbild ist ein Studioporträt auf Weiß, kein Umgebungsfoto. Im
   Bereich des Slogans liegen reines Weiß (Studiogrund, Oberteil) und fast
   Schwarz (Haar) unmittelbar nebeneinander — gemessen bleibt dort weder
   weiße noch dunkle Schrift durchgehend lesbar, und kein Verlaufsschleier
   ändert das, ohne das Motiv zuzudecken. Text und Bild teilen sich deshalb
   die Fläche, statt übereinanderzuliegen: Schrift auf Papier, Foto daneben.
   Die Kopfleiste bleibt dunkel, weil js/main.js den hellen Hero nicht mehr
   als dunklen Abschnitt zählt (kein data-dark) — der Schleier hellt ihre
   Zone im Foto zusätzlich auf.
   ---------------------------------------------------------------------- */
.hero--light{background:var(--paper)}
.hero--light .hero__intro p{color:var(--graphite)}
.hero--light .hero__claim{color:var(--ink)}

@media (min-width:1025px){
  .hero--light .hero__bg{left:50%}
  .hero--light .hero__bg::after{
    background:
      /* weiche Kante zur Papierfläche + aufgehellte Zone unter der Kopfleiste */
      linear-gradient(90deg,var(--paper) 0%,rgba(251,248,245,0) 15%),
      linear-gradient(180deg,rgba(251,248,245,.74) 0%,rgba(251,248,245,0) 21%);
  }
  .hero--light .hero__intro{text-align:left}
  .hero--light .hero__intro p{margin-inline:0;max-width:26rem}
  .hero--light .hero__claim{max-width:44%;font-size:clamp(2.9rem,6.6vw,6rem)}
  .hero--light .hero__actions{max-width:44%}
}

@media (max-width:1024px){
  /* Gestapelt: Foto oben, Slogan darunter auf Papier. Die Bildhöhe ist so
     bemessen, dass Slogan und Schaltflächen ohne Scrollen darunter passen. */
  .hero--light{padding-block:0 clamp(1.8rem,4vh,3rem)}
  .hero--light .hero__bg{inset:0 0 auto 0;height:40svh}
  .hero--light .hero__bg::after{
    background:linear-gradient(180deg,rgba(251,248,245,.74) 0%,rgba(251,248,245,0) 24%,rgba(251,248,245,0) 62%,var(--paper) 100%);
  }
  .hero--light .hero__intro{margin-top:calc(40svh + clamp(1rem,2.6vh,1.8rem))}
  .hero--light .hero__copy{padding-top:clamp(1rem,3vh,2rem)}
}
@media (max-width:640px){
  .hero--light .hero__claim{font-size:clamp(2.4rem,10.4vw,3.4rem)}
  .hero--light .hero__actions{margin-top:clamp(1.2rem,2.6vh,1.8rem)}
}
/* Doppelte Klasse: die Weiß-Regeln für den dunklen Hero stehen weiter unten
   in der Datei und würden bei gleicher Spezifität gewinnen. */
.hero--light.hero:not(.hero--sub) .btn--primary{background:var(--ink);color:var(--paper)}
.hero--light.hero:not(.hero--sub) .btn--primary .btn__fill{background:var(--paper)}
.hero--light.hero:not(.hero--sub) .btn--primary:hover,
.hero--light.hero:not(.hero--sub) .btn--primary:focus-visible{color:var(--ink)}
.hero--light.hero:not(.hero--sub) .btn--ghost{color:var(--ink);border-color:var(--hair)}
.hero--light.hero:not(.hero--sub) .btn--ghost .btn__fill{background:var(--ink)}
.hero--light.hero:not(.hero--sub) .btn--ghost:hover,
.hero--light.hero:not(.hero--sub) .btn--ghost:focus-visible{color:var(--paper);border-color:var(--ink)}

/* ============================================================
   HERO — Vollbild-Start: das Foto der beiden Mädchen deckt die ganze
   Fläche (auch hinter der Kopfleiste und hinter dem Slogan). Der Slogan
   sitzt unten bündig im Blocksatz, beide Zeilen fett und mit engstem
   Leading; die Facharzt-Zeile steht links oben unter dem Logo. Der
   Bildausschnitt hält die Gesichter im oberen Bereich frei.
   ============================================================ */
.hero--cover{
  background:#fff;                       /* trägt, solange das Foto lädt */
  padding:0;overflow:hidden;
  display:block;                         /* Kinder liegen absolut */
}

.hero__media{position:absolute;inset:0;z-index:0;overflow:hidden;background:#fff}
/* <picture> ist von Haus aus inline und spannte damit eine Zeile auf, unter der
   das Bild eine Grundlinien-Lücke hinterlassen kann. */
.hero__media picture{display:block;width:100%;height:100%}
.hero__media img{
  width:100%;height:100%;object-fit:cover;
  /* Gesichter oben halten — der Slogan unten deckt so nur Körper/Studiogrund. */
  object-position:50% 30%;display:block;
}
/* Zarter Schleier nur ganz unten, damit die schwarze Schrift trägt; das Bild
   bleibt dahinter sichtbar. */
.hero__media::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,transparent 62%,rgba(251,248,245,.30) 84%,rgba(251,248,245,.58) 100%);
}
/* Blur-to-Sharp nach dem Loader (wie beim früheren Hero, --hs ist registriert). */
.js .hero--cover .hero__media{--hs:0;transition:--hs 1.5s var(--ease-out) .15s}
.js.is-ready .hero--cover .hero__media{--hs:1}
.js .hero--cover .hero__media img{
  filter:blur(calc((1 - var(--hs,1))*14px)) saturate(calc(.92 + var(--hs,1)*.12));
  transform:scale(calc(1.03 + (1 - var(--hs,1))*.04));
}

/* Facharzt-Zeile: links oben, unter dem Logo, mit Abstand zu den Rändern. */
.hero__cred{
  position:absolute;z-index:2;margin:0;
  left:clamp(1.1rem,3vw,2.4rem);
  top:clamp(5.2rem,9.5vh,7.4rem);
  max-width:16rem;
  font-family:var(--font-body);color:var(--ink);line-height:1.3;
}
.hero__cred b{
  display:block;font-family:var(--font-display);font-weight:700;
  font-size:clamp(.9rem,1.2vw,1.08rem);letter-spacing:-.01em;
}
.hero__cred span{
  display:block;margin-top:.28rem;font-weight:500;
  font-size:clamp(.72rem,.95vw,.86rem);letter-spacing:.02em;color:var(--graphite);
}

/* Slogan: unten bündig, von Kante zu Kante, Blocksatz. */
.hero__slogan{
  position:absolute;left:0;right:0;bottom:0;z-index:2;margin:0;
  padding:0 clamp(.35rem,.9vw,.85rem) clamp(.2rem,.9vh,.55rem);
  color:var(--ink);font-family:var(--font-display);
}
.hero__slogan-top,
.hero__slogan-big{
  display:block;text-align:justify;text-align-last:justify;white-space:normal;
}
/* Erste Zeile: fett und deutlich größer als zuvor. Die Größe ist so bemessen,
   dass die (längere) Zeile gerade auf EINE Zeile passt und sie fast füllt — so
   bleiben die Wortabstände klein. Sie ist damit etwas kleiner als die zweite. */
.hero__slogan-top{
  font-weight:820;
  font-size:clamp(1.3rem,9.6vw,12rem);
  line-height:.9;letter-spacing:-.03em;
  color:var(--ink);
}
/* Zweite Zeile: am stärksten und am größten — das Schriftbild der Vorlagen. */
.hero__slogan-big{
  font-weight:900;
  font-size:clamp(1.6rem,10.8vw,13rem);
  line-height:.86;letter-spacing:-.045em;
}

/* ---- Telefon: Porträt der Praxisinhaberin über den ganzen Startbildschirm --
   Die Vorlage ist 1920×1523. Formatfüllend auf 390×844 bleiben davon 704
   Quellpixel Breite stehen; gemessen (Canvas, Helligkeitsschwelle 150) liegt
   ihr Kopf zwischen x=752 und x=1004 (Mitte 878), ihr Körper zwischen x=463
   und x=1263 (Mitte 863). `object-position:43%` legt das Fenster auf
   x=523…1227 und damit seine Mitte auf 875: sie steht mittig im Bild.
   Für 800 px Körperbreite reichen 704 px Fenster nicht — links entfallen 60,
   rechts 36 Quellpixel ihrer Schultern. Das ist der Preis der Mittigkeit;
   bei den früheren 38 % lag das Fenster auf x=462…1166, sie saß sichtbar
   rechts darin.
   Oben ist das Bild dunkel (Holztür), unten hell (Bluse): die Kopfzeile steht
   deshalb in Weiß, der Slogan bleibt in Tinte. Die beiden Schleier sichern
   beides ab.
   ---------------------------------------------------------------------- */
@media (max-width:640px){
  .hero__media{inset:0;height:auto;aspect-ratio:auto}
  .hero__media img{object-position:43% 50%}
  /* Der untere Schleier ist von .3/24 % auf .42/26 % angehoben. Mit dem
     mittigen Ausschnitt (43 %) rückt ihr Haar unter den Slogan, und dort lag
     die dunkelste Stelle je Zeile bei einer Helligkeit von 47/57/60 statt der
     vorherigen 53/76/97. Mit dem stärkeren Schleier sind es 63/76/86 — keine
     Zeile steht damit schlechter als vorher die schlechteste. Der Aufheller
     liegt über ihrer hellen Bluse und ist dort praktisch nicht zu sehen. */
  .hero__media::after{
    background:
      linear-gradient(180deg,rgba(18,14,10,.5) 0%,rgba(18,14,10,.14) 15%,rgba(18,14,10,0) 30%),
      linear-gradient(0deg,rgba(251,248,245,.42) 0%,rgba(251,248,245,0) 26%);
  }
  /* Die Facharzt-Zeile steht wie auf dem Rechner links oben unter dem Logo —
     dort ist der Hintergrund die dunkle Tür, also in Weiß. Gemessen endet sie
     bei y=121 und der Kopf beginnt erst bei y=154; sie verdeckt also nichts. */
  .hero__cred{top:4rem;color:#fff}
  .hero__cred b{text-shadow:0 1px 12px rgba(0,0,0,.45)}
  .hero__cred span{color:rgba(255,255,255,.8);text-shadow:0 1px 12px rgba(0,0,0,.45)}

  /* Der Slogan wird zur Treppe: die obere Zeile bleibt im Blocksatz über die
     volle Breite, darunter steht jedes der drei Wörter auf eigener Zeile —
     links, mittig, rechts. Dadurch tragen sie rund ein Viertel mehr Größe,
     ohne dass eine Zeile umbricht. */
  .hero__slogan{padding-inline:2px;padding-bottom:clamp(.8rem,2.4vh,1.5rem)}
  /* Die obere Zeile steht an ihrer Grenze: bei 10,2vw misst „Wir zaubern
     Ihnen ein" natürlich 384,7 px von 386 verfügbaren. Damit sie auch bei
     abweichender Schriftauslieferung sicher einzeilig bleibt, ist die Laufweite
     hier eine Spur enger als die .03em der Grundregel — das schafft ~8 px Luft. */
  .hero__slogan-top{font-size:clamp(1.3rem,10.2vw,12rem);letter-spacing:-.038em}
  .hero__slogan-big{
    font-size:clamp(1.6rem,14.2vw,13rem);
    text-align:left;text-align-last:left;
  }
  /* text-align-last wird vererbt und gilt für die letzte Zeile eines Blocks.
     Jedes Wort IST eine einzige Zeile, also auch die letzte — ohne diese
     Rücknahme gewönne das geerbte `left` der Elternzeile, und „ins" wie
     „Gesicht" stünden trotz text-align weiterhin links. */
  .hero__word{display:block;text-align-last:auto}
  .hero__word--c{text-align:center}
  .hero__word--r{text-align:right}
}

/* --- Kopfzeile oben mittig (Vorbild bymonolog.com) --- */
.hero__intro{
  position:relative;z-index:1;
  width:100%;max-width:var(--maxw);margin-inline:auto;
  padding-inline:var(--gutter);
  text-align:center;
}
.hero__intro p{
  margin-inline:auto;max-width:34rem;
  font-family:var(--font-body);font-weight:500;
  font-size:clamp(.95rem,1.35vw,1.12rem);line-height:1.55;
  color:#fff;text-wrap:balance;
}

/* --- Slogan unten links, groß und fett (Vorbild wolverineworldwide.com) --- */
.hero__copy{margin-top:auto;padding-top:clamp(3rem,10vh,7rem)}
/* Startseiten-Hero: bleibt beim Scrollen stehen (sticky), die opaken Sektionen
   (z-index 2) schieben sich darüber und geben das Foto frei. Das gilt auf
   jeder Breite — auf dem Telefon lief der Hero eine Zeit lang im Fluss mit,
   dadurch fiel genau dieser Auftakt weg: „Praxis" schob sich nicht mehr über
   das Startbild, sondern folgte ihm nur. */
.js main{position:relative}
.js main>.section{position:relative;z-index:2}
.js .hero:not(.hero--sub){
  position:sticky;top:0;z-index:0;
  min-height:100svh;
  display:flex;align-items:center;
}

/* Warmes „Disco-Ball"-Leuchten über dem Hero: eine langsam kreisende Lichtquelle
   von oben wirft warme, irisierende Lichtflecken nach unten. Markenkonform
   (Orange/Gold/Pfirsich/Sand), bewusst dezent, damit der Text lesbar bleibt. */
.hero__aurora{
  position:absolute;inset:-26% -16% auto -16%;height:128%;
  z-index:0;pointer-events:none;overflow:hidden;
  opacity:.66;
  filter:blur(30px) saturate(118%);
  /* sanfter Grundschein, oben verankert, strahlt nach unten ab */
  background:
    radial-gradient(70% 50% at 50% -10%, rgba(255,214,160,.34), transparent 72%),
    radial-gradient(50% 42% at 22% -4%,  rgba(246,180,90,.20),  transparent 74%),
    radial-gradient(50% 42% at 80% -4%,  rgba(236,116,5,.16),   transparent 74%);
  -webkit-mask-image:linear-gradient(to bottom,#000 34%,transparent 90%);
          mask-image:linear-gradient(to bottom,#000 34%,transparent 90%);
  animation:veilBreathe 10s ease-in-out infinite alternate;
}
/* Vertikale, weiche Lichtschleier auf doppelt breiter Ebene (200%); die Szene
   0–50% ist in 50–100% wiederholt. veilDrift wiegt seitlich (alternate) →
   ruhiges „Unterwasser"-Wogen statt hartem Loop. Oben dichter (Lichtquelle oben). */
.hero__aurora::before{
  content:"";position:absolute;inset:-12% -100% -12% 0;
  background:
    linear-gradient(90deg, transparent 4%,  rgba(255,196,120,.42) 7%,   transparent 11%),
    linear-gradient(90deg, transparent 13%, rgba(255,224,182,.30) 16.5%,transparent 21%),
    linear-gradient(90deg, transparent 23%, rgba(236,116,5,.24)  26%,   transparent 30%),
    linear-gradient(90deg, transparent 33%, rgba(246,180,90,.34)  37%,   transparent 42%),
    linear-gradient(90deg, transparent 44%, rgba(255,170,150,.24) 47%,   transparent 50%),
    linear-gradient(90deg, transparent 54%, rgba(255,196,120,.42) 57%,   transparent 61%),
    linear-gradient(90deg, transparent 63%, rgba(255,224,182,.30) 66.5%,transparent 71%),
    linear-gradient(90deg, transparent 73%, rgba(236,116,5,.24)  76%,   transparent 80%),
    linear-gradient(90deg, transparent 83%, rgba(246,180,90,.34)  87%,   transparent 92%),
    linear-gradient(90deg, transparent 94%, rgba(255,170,150,.24) 97%,   transparent 100%);
  animation:veilDrift 26s ease-in-out infinite alternate;
  will-change:transform;
}
@keyframes veilDrift{
  0%{transform:translate3d(0,0,0)}
  100%{transform:translate3d(-50%,0,0)}
}
@keyframes veilBreathe{
  0%{opacity:.5;transform:scale(1)}
  100%{opacity:.68;transform:scale(1.04)}
}

/* Subpage-Hero: heller Textkopf auf Papier — nimmt die Vollbild-Regeln der
   Startseite ausdrücklich zurück (kein Foto, keine volle Bildschirmhöhe). */
.hero--sub{
  display:block;min-height:0;background:var(--paper);
  padding-block:clamp(7rem,14vw,9rem) clamp(2rem,5vw,3.5rem); /* feste Leiste freihalten */
}
.hero--sub .hero__claim{
  color:var(--ink);font-weight:600;
  font-size:clamp(2rem,5.4vw,4rem);line-height:1;letter-spacing:-.032em;
  max-width:20ch;
}
.hero--sub .lede{color:var(--ink-70)}
.hero__aurora--band{height:100%;inset:0;opacity:.5}
.hero--sub .lede{max-width:42rem}
/* Technik-Gruppen: Fliesstext unter dem Kopf */
.tech-body{max-width:54rem;margin-top:clamp(1.4rem,3vw,2rem)}
.tech-body p+p{margin-top:1rem}
/* Gerätenamen im Fließtext der Unterseiten */
.tech-body b{font-weight:640;color:var(--ink)}

/* Aufmacherfoto der Leistungs-Unterseiten. object-position steht je Seite
   inline, weil die Motive teils hoch- und teils querformatig sind. */
.subfig{
  margin:0;overflow:hidden;
  border-radius:var(--rad);border:1px solid var(--hair);
  aspect-ratio:3/2;
}
.subfig img{width:100%;height:100%;object-fit:cover}
@media (max-width:640px){.subfig{aspect-ratio:4/3}}

/* Der Spruch: groß, fett, linksbündig, weiß — auf allen Geräten gleich gebaut */
.hero__claim{
  font-family:var(--font-display);
  font-weight:800;
  font-size:clamp(2.9rem,9.2vw,8.5rem);
  line-height:.94;
  letter-spacing:-.042em;
  color:#fff;
  margin:0;
  max-width:16ch;
  text-wrap:normal;
}
.hero__claim .claim-l3{display:block}
/* Die dritte Zeile besteht nur aus dem rotierenden Wort — als Block gesetzt,
   damit keine Grundlinien-Mischung mit umgebendem Text entstehen kann. */
.hero__claim .rotator{display:flex}

/* --- Wortrotation (Vorbild React-Bits „RotatingText"): die Buchstaben des
   alten Wortes fahren nach oben hinaus, die des neuen rücken von unten nach —
   versetzt vom letzten Buchstaben her. Der Rahmen maskiert die Bewegung; die
   Innenabstände geben Umlauten und Unterlängen Luft, die negativen Ränder
   halten die Zeile trotzdem exakt an ihrem Platz. --- */
.rotator{
  position:relative;
  display:inline-flex;overflow:hidden;vertical-align:baseline;
  line-height:1;
  /* Unten mindestens die Unterlänge des „g" (gemessen 0,22 em bei Inter Tight
     800) plus Reserve — sonst kappt overflow:hidden „Erfahrung"/„Sorgfalt". */
  padding:.2em .06em .27em 0;
  margin:-.2em -.06em -.27em 0;
}
.rotator__ch.is-out{top:.2em}               /* gleicht den oberen Innenabstand aus */
.rotator__ch{
  display:inline-block;white-space:pre;
  transform:translateY(var(--ry,0));
  transition:transform .62s cubic-bezier(.16,1,.3,1);
  transition-delay:var(--rd,0s);
}
.rotator__ch.is-wait{--ry:140%;transition:none}   /* wartet unsichtbar unterhalb */
.rotator__ch.is-out{--ry:-140%}                   /* fährt oben heraus         */

.hero__actions{display:flex;flex-wrap:wrap;gap:.9rem;margin-top:clamp(1.8rem,3.5vw,2.6rem)}
.hero:not(.hero--sub) .btn--primary{background:#fff;color:var(--espresso)}
.hero:not(.hero--sub) .btn--primary .btn__fill{background:var(--espresso)}
.hero:not(.hero--sub) .btn--primary:hover,
.hero:not(.hero--sub) .btn--primary:focus-visible{color:#fff}
.hero:not(.hero--sub) .btn--ghost{color:#fff;border-color:rgba(255,255,255,.42)}
.hero:not(.hero--sub) .btn--ghost .btn__fill{background:#fff}
.hero:not(.hero--sub) .btn--ghost:hover,
.hero:not(.hero--sub) .btn--ghost:focus-visible{color:var(--espresso);border-color:#fff}

/* ============================================================
   01 · PRAXIS
   ============================================================ */
.praxis__grid{
  display:grid;grid-template-columns:.86fr 1.14fr;
  gap:clamp(2rem,5vw,4.5rem);align-items:start;margin-top:clamp(2.4rem,5vw,4rem);
}
.figure{position:relative;border-radius:var(--rad);overflow:hidden;border:1px solid var(--hair)}
.figure img{width:100%;height:100%;object-fit:cover}
/* <picture> ist von Haus aus inline: ohne diese Zeile spannte es eine Textzeile
   auf und das Bild füllte die Maske nicht mehr aus. */
.figure picture{display:block;width:100%;height:100%}
.figure--portrait{aspect-ratio:4/5}

/* Eingangsfoto mit Bildunterschrift — die Maske sitzt auf dem inneren Feld,
   sonst würde der Clip-Wipe die Zeile darunter mitbeschneiden. */
.praxis__fig{margin:0}
.figcap{
  margin-top:.85rem;font-size:.86rem;line-height:1.5;
  color:var(--ink-45);max-width:34ch;
}

/* Praxis-Text: ein einziger fetter Block in dunklem Grau — bewusst kein
   Schwarz, damit die große Schrift nicht hart auf dem Papier steht. */
.praxis__body{
  font-family:var(--font-display);
  font-weight:620;
  font-size:clamp(1.32rem,2.05vw,1.72rem);
  line-height:1.28;
  letter-spacing:-.021em;
  color:var(--graphite);
  text-wrap:pretty;
}
.praxis__body p + p{margin-top:1em}

/* Sektionsabschluss: Leiste links, Foto rechts. Die Quelle ist hochkant
   (1400×2100) — in der schmalen rechten Spalte steht sie deshalb im eigenen
   Hochformat statt als breites Band. */
.praxis__close{
  display:grid;grid-template-columns:1fr .78fr;
  gap:clamp(2rem,5vw,4.5rem);align-items:start;
  margin-top:clamp(3rem,7vw,5.5rem);
}
.praxis__wide{
  grid-column:2;grid-row:1;margin:0;overflow:hidden;
  border-radius:var(--rad);border:1px solid var(--hair);aspect-ratio:4/5;
}
.praxis__wide img{width:100%;height:100%;object-fit:cover;object-position:50% 32%}

/* ---- Historienleiste ----
   Drei Stationen an einer durchgehenden Linie. Seit das Foto die rechte Spalte
   belegt, läuft die Linie senkrecht: die Füllung folgt --p aus der Scrub-Engine
   (jetzt scaleY), die Punkte rasten gestaffelt ein; die Jahreszahlen zählt
   countFacts() in js/main.js hoch (unverändert). */
.factbar{
  position:relative;grid-column:1;grid-row:1;
  display:grid;grid-template-columns:1fr;gap:clamp(1.8rem,3.4vw,2.8rem);
  margin-top:0;padding-left:clamp(1.6rem,2.6vw,2.4rem);
}
.factbar__track{
  position:absolute;top:.5em;bottom:.5em;left:0;right:auto;
  width:1px;height:auto;background:var(--hair);
}
.factbar__fill{
  display:block;width:100%;height:100%;background:var(--ink);
  transform-origin:50% 0;transform:scaleY(var(--p,0));
}
.fact{position:relative}
/* Stationspunkt auf der Linie — rastet ein, sobald die Füllung ihn erreicht */
.fact::before{
  content:"";position:absolute;top:.42em;
  left:calc((clamp(1.6rem,2.6vw,2.4rem) + 3px)*-1);
  width:7px;height:7px;background:var(--ink);
  transform:scale(0);transition:transform .5s var(--spring);
  transition-delay:calc(var(--fi,0)*.12s);
}
.factbar.in .fact::before{transform:scale(1)}
.fact b{
  display:block;font-family:var(--font-display);font-weight:600;
  font-size:clamp(1.9rem,3.6vw,2.8rem);color:var(--ink);line-height:1;
  letter-spacing:-.03em;font-variant-numeric:tabular-nums;
}
.fact span{
  display:block;margin-top:.55rem;font-size:.88rem;line-height:1.5;
  color:var(--ink-70);max-width:26ch;
}

/* ============================================================
   02 · LEISTUNGEN
   Zwei Teile: der Auftakt (.svcintro) — wechselnde Praxisfotos mit
   dem Praxiszeichen und einem Satz darüber — und darunter die
   Zeilenliste (.svclist) nach dem Muster von locomotive.ca.
   ============================================================ */
.section--svc{padding-top:clamp(.6rem,1.4vw,1.1rem)}

/* --- Auftakt ---
   Das Foto steht dicht an den Rändern (links, rechts, oben) und reicht
   bewusst über eine Bildschirmhöhe hinaus: die Fläche soll hoch wirken,
   nicht bloß breit. Die Ecken sind gerundet — eine gewollte Ausnahme von
   der 2-px-Regel der Minimal Edition. */
.svcintro{
  position:relative;overflow:hidden;
  margin-inline:clamp(.5rem,1vw,.9rem);
  height:min(112svh,74rem);
  border-radius:clamp(10px,1.4vw,18px);
  display:grid;place-items:center;
  background:var(--ink);
}
.svcintro__shots{position:absolute;inset:0}
.svcintro__shots picture{display:block;width:100%;height:100%}
.svcintro__shots img{width:100%;height:100%;object-fit:cover}
/* Die Bildunterschrift der Außenansicht liegt nur auf dem Telefon hier — dort
   steht das Foto in dieser Fläche statt in Sektion 01. */
.svcintro__cap{display:none}
/* Schleier, damit Zeichen und Satz auf jedem der Fotos tragen */
.svcintro__shots::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(14,12,10,.32) 0%,rgba(14,12,10,.58) 62%,rgba(14,12,10,.68) 100%);
}
.svcintro__say{
  position:relative;z-index:1;text-align:center;
  max-width:48rem;padding-inline:clamp(1.5rem,5vw,4rem);
}
.svcintro__line{
  margin:0;color:#fff;
  font-family:var(--font-serif);font-weight:400;
  font-size:clamp(1.6rem,3.4vw,3.1rem);line-height:1.12;letter-spacing:-.015em;
  text-wrap:balance;
}

/* --- Zeilenliste (Vorbild locomotive.ca) ---
   Dort trennt eine Linie je Zeile (`.c-featured-links_item`), und ein
   Bildfeld zwischen den Wörtern fährt von `width:0em` auf `1.5em` auf,
   während der Rest der Zeile zur Seite rückt. Die Taktwerte (.45s beim
   Auffahren, .2s beim Schließen, power4-artige Kurve) sind übernommen. */
.svclist{
  list-style:none;margin:clamp(3rem,7vw,5rem) 0 0;padding:0;
  border-bottom:2px solid var(--ink);
}
.svclist__item{border-top:2px solid var(--ink)}
.svclist__row{
  --enter:.45s;--leave:.2s;--e:cubic-bezier(.23,1,.32,1);
  display:flex;
  padding:clamp(.45rem,1.1vw,.85rem) 0;
  color:var(--ink);text-decoration:none;
}
.svclist__title{
  display:flex;align-items:center;justify-content:center;flex-grow:1;
  line-height:1;text-align:center;
  font-family:var(--font-serif);font-weight:400;
  font-size:clamp(1.9rem,6.2vw,5.2rem);letter-spacing:-.012em;
}
.svclist__word{display:inline-block;transform:translateY(.1em)}
.svclist__word:first-child:not(:last-child){padding-right:.1em}
.svclist__word:last-child:not(:first-child){padding-left:.1em}
.svclist__visual{
  flex:0 0 auto;display:inline-block;position:relative;overflow:hidden;
  vertical-align:bottom;width:0em;
  transition:width var(--leave) var(--e);
  pointer-events:none;border-radius:var(--rad);
}
.svclist__visual::before{content:"";display:block;padding-bottom:1em}
.svclist__visual img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.svclist__row:hover .svclist__visual,
.svclist__row:focus-visible .svclist__visual{width:1.5em;transition-duration:var(--enter)}
/* Die Unterstreichung ist der Hinweis darauf, dass die Zeile anklickbar ist */
.svclist__row:hover .svclist__word,
.svclist__row:focus-visible .svclist__word{
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.1em;
}
/* Ohne Mauszeiger gibt es kein Überfahren. Das Bild stand deshalb dauerhaft
   in der Zeile — auf Wunsch ist es jetzt auch dort unsichtbar und kommt nur
   für den Moment, in dem der Finger auf der Zeile liegt. js/main.js schaltet
   dafür .is-peek (initSvcPeek) und hält es kurz nach, damit das Feld die
   .45 s zum Auffahren überhaupt bekommt. */
.svclist__row.is-peek .svclist__visual{width:1.5em;transition-duration:var(--enter)}
.svclist__row.is-peek .svclist__word{
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.1em;
}

/* ============================================================
   03 · BEHANDLUNGSABLAUF — der ganze Bildschirm wechselt die Farbe
   Die Färbung hängt nicht mehr an einem festen Verlauf im Abschnitt,
   sondern an --warm (0…1): js/main.js misst laufend, wie nah die Mitte
   des Abschnitts der Bildschirmmitte ist, und jede Papierfläche der
   Seite mischt sich über --surface synchron ins Orange. Dadurch wird
   der GESAMTE Bildschirm orangener, je weiter man hierher scrollt —
   und beim Wegscrollen genauso wieder blass. Ein Verlauf im Abschnitt
   könnte das nicht: er färbt immer nur seinen eigenen Ausschnitt.

   Sonst steht hier nichts: eine Aussage auf einer ruhigen Fläche.
   Die fünf Stationen selbst stehen auf ablauf.html (.fly*).
   ============================================================ */
/* Opak wie jeder andere Abschnitt: der Startseiten-Hero ist auf Desktop
   sticky und steht die ganze Seite über hinter dem Inhalt. Nur eine
   deckende Fläche verbirgt ihn. --surface ist derselbe Wert, den auch
   body trägt — die Farbe wandert also weiterhin mit --warm ins Orange
   und wieder zurück, nur auf einer Fläche, die nichts durchlässt. */
.section--flow{
  position:relative;
  padding-block:0;
  background:var(--surface);
}
/* Ohne Skript bleibt --warm auf 0 und der Abschnitt wäre farblos. Dann
   steht die Fläche eben fest im Orange, ohne Rechnerei. */
html:not(.js) .section--flow{background:var(--flow-warm)}

/* Zwei weiche Akzente treiben langsam durch die orangene Fläche. Sie liegen
   ABSOLUT im Abschnitt und werden von dessen overflow beschnitten — sie
   können deshalb weder über die Nachbarabschnitte noch über den sticky Hero
   geraten. Ihre Deckkraft hängt an --warm: außerhalb des Ablaufs sind sie
   gar nicht da. */
.section--flow{overflow:hidden}
.flowbg{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  opacity:var(--warm,0);
}
html:not(.js) .flowbg{opacity:1}
.flowbg__lite{
  position:absolute;
  filter:blur(40px);
  will-change:transform;
}
/* Beide bleiben in der warmen Familie: einer hellt auf, einer vertieft.
   Ein Fremdton würde als Fläche gelesen statt als Licht.
   Die Farbe sitzt im Verlauf, nicht in der Fläche: volle Deckung nur im Kern,
   von dort bis zum Rand nach transparent. Eine gefüllte Form mit clip-path
   hätte ringsum eine Kante — die Unschärfe weicht sie auf, löst sie aber
   nicht auf, und in dieser Größe las sich das als Band statt als Licht. */
/* Beide Maße hängen an der Fensterbreite. Eine Höhe in Prozent bezöge sich auf
   den fast zwei Bildschirme hohen Abschnitt — auf dem Telefon würde daraus ein
   schmaler senkrechter Streifen statt eines Lichts. */
.flowbg__lite--a{
  left:9vw;top:17%;width:clamp(15rem,32vw,34rem);height:clamp(13rem,26vw,30rem);
  opacity:.72;
  background:radial-gradient(closest-side,
    rgba(255,246,236,.95) 0%,
    rgba(255,246,236,.52) 44%,
    rgba(255,246,236,0) 100%);
  animation:flowDriftA 58s ease-in-out infinite alternate;
}
.flowbg__lite--b{
  right:11vw;top:57%;width:clamp(13rem,28vw,30rem);height:clamp(11.5rem,23vw,26rem);
  opacity:.6;
  background:radial-gradient(closest-side,
    rgba(240,160,89,.88) 0%,
    rgba(240,160,89,.44) 46%,
    rgba(240,160,89,0) 100%);
  animation:flowDriftB 71s ease-in-out infinite alternate;
}
/* Eine Unschärfe dieser Größe ist teuer zu rastern. Die Drift steht still,
   solange keine Farbe im Bild ist. Die Regel muss NACH den animation-Kurz-
   formen stehen — die setzen den Laufzustand sonst auf running zurück. */
.flowbg__lite{animation-play-state:paused}
.flowbg.is-warm .flowbg__lite{animation-play-state:running}

@keyframes flowDriftA{
  0%  {transform:translate3d(0,0,0) rotate(0deg) scale(1)}
  50% {transform:translate3d(6vw,-7vh,0) rotate(8deg) scale(1.06)}
  100%{transform:translate3d(-4vw,6vh,0) rotate(-7deg) scale(.96)}
}
@keyframes flowDriftB{
  0%  {transform:translate3d(0,0,0) rotate(0deg) scale(1)}
  50% {transform:translate3d(-7vw,8vh,0) rotate(-9deg) scale(1.08)}
  100%{transform:translate3d(5vw,-5vh,0) rotate(6deg) scale(.97)}
}

/* Der Vor- und Nachlauf von je 44svh ist die Strecke, über die sich die
   Farbe aufbaut: erst danach steht die Aussage mittig im vollen Orange. */
.flowlead{
  position:relative;z-index:1;
  /* 44svh Vorlauf + 100svh für die Aussage + 44svh Nachlauf. Die Summe steht
     hier ausgeschrieben, weil border-box die Polsterung in min-height
     einrechnet — 100svh ergäbe sonst einen Abschnitt ohne Vorlauf. */
  min-height:188svh;
  display:grid;align-content:center;
  padding-block:44svh;
}
.flowlead__title{
  margin:0;
  font-family:var(--font-display);font-weight:560;
  /* Der untere Wert ist so gewählt, dass der Satz auch auf einem schmalen
     Telefon in zwei Zeilen bleibt — mehr wäre keine Aussage mehr, sondern
     ein Absatz. */
  font-size:clamp(2.15rem,7.6vw,7rem);
  line-height:.94;letter-spacing:-.042em;
  color:var(--ink);
  text-wrap:balance;
}
.flowlead__foot{
  display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;
  gap:clamp(1.6rem,4vw,3rem);
  margin-top:clamp(2.4rem,5vw,3.8rem);
}
.flowlead__text{
  margin:0;max-width:46ch;color:var(--ink);
  font-size:clamp(1rem,2.4vw,1.1rem);line-height:1.62;
}
/* Der Weg in den Ablauf trägt jetzt exakt die „Termin vereinbaren"-Choreografie
   (.btn--cta): der Kreis wächst aus der Mitte, der rechte Pfeil fährt hinaus, der
   linke rückt von außen nach, die Beschriftung gleitet mit. Hier bleibt nur die
   Größe der Sektions-Schaltfläche — Farbe, Füllung und Pfeile kommen aus .btn--cta. */
.flowcta{
  flex:0 0 auto;
  font-family:var(--font-display);letter-spacing:-.015em;
  font-size:clamp(1.05rem,1.65vw,1.3rem);
  padding:clamp(1.05rem,1.7vw,1.4rem) clamp(2.2rem,3vw,3rem);
}

@media (max-width:640px){
  .flowlead{min-height:152svh;padding-block:26svh}
  .flowlead__foot{flex-direction:column;align-items:flex-start}
  .flowcta{width:100%}
}

/* ============================================================
   UNTERSEITE ABLAUF (ablauf.html) — die fünf Stationen als Bogenfahrt
   Der Abschnitt wird eine Bildschirmhöhe lang festgehalten. Jede
   Station beschreibt dabei einen Bogen: sie kommt von unten rechts
   herein, steht mittig und zieht nach oben rechts wieder hinaus.
   Senkrecht trägt --q den Weg (+1 unten, 0 mittig, −1 oben),
   waagerecht --qa den Ausschlag nach rechts. Weil --qa aus |q| kommt,
   steht die Station an beiden Enden rechts und nur in der Mitte
   bündig — der Weg ist damit ein Bogen und keine Gerade. --k (0→1)
   ist die Nähe und steuert die Deckkraft. Alles schreibt js/main.js
   (initFly).

   Der Grundton ist derselbe wie im Ablauf-Abschnitt der Startseite:
   flaches Orange unter zwei weichen Lichtkreisen. Anders als dort
   gibt es hier die selbstzeichnende blaue Linie.

   Ruhezustand ohne Skript und bei prefers-reduced-motion: eine
   ruhige, vollständige Liste ohne Festhalten und ohne Bogen.
   ============================================================ */
.fly{position:relative;background:var(--flow-warm)}
.fly__pin{position:relative}
.fly__glow,.fly__spine,.fly__hud{display:none}

.fly__scene{
  list-style:none;margin:0;padding:0;
  display:grid;gap:clamp(3.4rem,9vw,6.5rem);
  padding-block:clamp(7rem,14vw,9rem) clamp(3rem,7vw,5rem);
  padding-inline:max(var(--gutter),calc((100% - var(--maxw))/2));
}
.fly__st{display:grid;align-content:center;gap:clamp(1rem,2.6vw,1.8rem)}
/* Riesig wie beim Vorbild: das Wort füllt die Zeile nahezu aus und
   nimmt damit den größten Teil des Bildschirms ein. */
.fly__title{
  margin:0;
  font-family:var(--font-display);font-weight:560;letter-spacing:-.045em;
  font-size:clamp(2.6rem,15vw,13rem);line-height:.9;color:var(--ink);
}
/* Der kleine Text trägt dieselbe Stärke wie der Praxis-Anfangstext
   (.praxis__body, 620), nur einen Tick kleiner — und steht in Tinte
   statt Graphit, weil er hier die Aussage trägt und kein Beitext ist. */
.fly__text{
  margin:0;
  font-family:var(--font-display);font-weight:620;
  font-size:clamp(1.04rem,1.78vw,1.5rem);
  line-height:1.34;letter-spacing:-.018em;
  color:var(--ink);text-wrap:pretty;
}
.fly__shot{
  margin:0;overflow:hidden;border-radius:var(--rad);
  background:rgba(33,28,24,.08);aspect-ratio:4/3;
}
.fly__shot img{width:100%;height:100%;object-fit:cover;display:block}

@media (min-width:641px){
  .fly__st{
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    column-gap:clamp(1.8rem,4.5vw,3.8rem);
  }
  .fly__title{grid-column:1/-1;grid-row:1}
  .fly__shot{grid-column:1;grid-row:2;justify-self:start;max-height:30svh}
  .fly__text{grid-column:2;grid-row:2;align-self:end;max-width:46ch}
}

/* Auf dem Telefon steht die Station mittig und gehört ganz auf den
   Bildschirm. Das Band der Linie liegt hier nicht mehr seitlich daneben,
   sondern mittig dahinter — der Station stehen also die vollen 350 px des
   Satzspiegels zur Verfügung (gemessen bei 390 px Fensterbreite).
   Gemessen sind „Therapieplan" (das breiteste der fünf Wörter, 228,6 px bei
   42,9 px Schrift) und „Erstberatung" dicht dahinter. Bei 14,5vw sind das
   301 px von 350 — rund 86 % der Zeile, also deutlich präsenter als vorher
   und mit sicherem Abstand zum Rand. Die Wörter tragen alle dieselbe Größe.
   Der Fließtext steht linksbündig und über die volle Breite; mittiger Satz
   liest sich bei fünf Zeilen unruhig. Überschriften bleiben mittig. */
@media (max-width:640px){
  .fly__scene{gap:clamp(2.6rem,8vw,4rem)}
  .fly__st{justify-items:center;text-align:center}
  .fly__title{font-size:clamp(2.4rem,14.5vw,4.6rem);line-height:.94}
  .fly__shot{width:100%;max-width:20rem;justify-self:center}
  .fly__text{
    font-size:1rem;max-width:none;margin-inline:0;
    justify-self:stretch;text-align:left;
  }
}

@media (prefers-reduced-motion:no-preference){
.js .fly{
  --stations:5;          /* Anzahl Stationen — muss zum Markup passen */
  --spine-x:clamp(.6rem,2vw,2rem);
  /* Breiteres Band als früher (war 6vw/104px), damit die dicke Linie Platz
     hat, seitlich zu wandern und einen Kringel zu schlagen. Sie bleibt im
     linken Rand, also über dem Hintergrund und links von Überschrift/Foto. */
  --spine-w:clamp(66px,8.5vw,140px);
  /* Je Station eine volle Bildschirmhöhe Standzeit, in der sich nichts
     verschiebt, und danach knapp eine weitere für die Fahrt zur nächsten.
     Die Standzeit ist der Grund, warum die Fahrt ruhig wirkt: man liest
     eine Station zu Ende, bevor überhaupt wieder etwas in Bewegung gerät.
     Gefahren wird nur ZWISCHEN zwei Stationen, also ein Mal weniger als es
     Stationen gibt; auf die letzte folgt nur noch ihre Standzeit und die
     Bildschirmhöhe, mit der sich der Abschnitt vom Rand löst.
     initFly in js/main.js rechnet mit denselben Anteilen (DWELL/TRAVEL). */
  height:calc((var(--stations) - 1) * 192svh + 200svh);
}
.js .fly__pin{position:sticky;top:0;height:100svh;overflow:hidden}

.js .fly__glow{
  display:block;position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(64% 46% at 8% 78%,  rgba(127,178,212,.5), transparent 72%),
    radial-gradient(58% 42% at 92% 18%, rgba(255,252,246,.6), transparent 70%);
}

/* Die selbstzeichnende Linie wächst über die gesamte Fahrt mit --fp: der
   wachsende Anfang ist ein echtes Linienende (stroke-dashoffset), deshalb bleibt
   dort die runde Kappe stehen statt einer geraden Schnittkante. Sie füllt sich
   beim Vorwärtsscrollen und zieht sich beim Zurückscrollen zurück. Uniform
   skaliert (Höhe treibt, Breite folgt dem Seitenverhältnis) — so bleibt die
   Kappe rund und die Linie überall gleich dick. z-index:0 hält sie hinter
   Überschrift und Foto (z-index:1), ihre Rechts-Ausschläge laufen also dahinter. */
.js .fly__spine{
  display:block;position:absolute;top:0;left:var(--spine-x);z-index:0;
  width:auto;height:100%;pointer-events:none;overflow:visible;
}
/* Dick, rund und in wechselnden Orangetönen (heller/dunkler, nie ein Fremdton)
   über den Verlauf #flyInk. stroke-width in Nutzereinheiten der viewBox
   (120×200); bei ~4,5× Skalierung ergibt 3,4 rund 15 px. pathLength=1 normiert
   den Strich, dashoffset zieht ihn 0→1. */
.fly__spineline{
  fill:none;stroke:url(#flyInk);stroke-width:3.7;
  stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:1;stroke-dashoffset:calc(1 - var(--fp,0));
}

.js .fly__hud{
  display:flex;justify-content:space-between;gap:1rem;
  position:absolute;left:0;right:0;bottom:clamp(1rem,3svh,2.2rem);margin:0;
  padding-inline:max(var(--gutter),calc((100% - var(--maxw))/2));
  font-family:var(--font-body);font-weight:500;font-size:.76rem;
  letter-spacing:.09em;text-transform:uppercase;color:rgba(33,28,24,.5);
  pointer-events:none;
}
.fly__hudcount{font-variant-numeric:tabular-nums;color:var(--ink)}

.js .fly__scene{display:block;position:absolute;inset:0;padding:0;z-index:1}
/* Die Station selbst steht still. Nur die Überschrift reist — Ziffer,
   Foto und Text tauchen an Ort und Stelle auf. */
.js .fly__st{
  position:absolute;top:50%;
  left:calc(var(--spine-x) + var(--spine-w) + clamp(1rem,2.4vw,2rem));
  right:var(--gutter);
  max-width:var(--maxw);margin-inline:auto;
  transform:translate3d(0,-50%,0);
  pointer-events:none;
}
/* Nur die Überschrift kommt von außerhalb des Bildschirms herein: sie
   beschreibt den Bogen (unten rechts → mittig → oben rechts). --qa ist
   der seitliche Ausschlag, --q der senkrechte Weg. */
.js .fly__title{
  transform:
    translate3d(calc(var(--qa,1) * 52vw), calc(var(--q,1) * 92svh), 0)
    rotate(calc(var(--q,1) * -6deg));
  opacity:var(--k,0);
  will-change:transform;
}
/* Foto und Text verschieben sich nicht, sie morphen auf, sobald die Station
   angekommen ist: --m steigt erst kurz vor der Standposition und ist während
   der gesamten Standzeit 1. Die Unschärfe bleibt flach — sie soll die Ankunft
   weich machen, nicht auffallen. */
.js .fly__text{
  opacity:var(--m,0);
  transform:translate3d(0,calc((1 - var(--m,0)) * 1.4rem),0)
            scale(calc(.984 + var(--m,0) * .016));
  filter:blur(calc((1 - var(--m,0)) * 3px));
}
/* Das Foto morpht nicht nur auf, es weitet sich dabei sichtbar aus (Vorbild
   lusion.co, Startseite): der Rahmen wächst von 0.85 auf 1 und die Maske gibt
   ihn von den Rändern her frei. Die Neigung und die Grundvergrößerung des
   Bildes bleiben beim .fx-<img> darunter, deshalb liegt beides hier auf der
   <figure> und nicht auf dem <img>. */
.js .fly__shot{
  opacity:var(--m,0);
  transform:translate3d(0,calc((1 - var(--m,0)) * 1.4rem),0)
            scale(calc(.85 + var(--m,0) * .15));
  clip-path:inset(calc((1 - var(--m,0)) * 15%) round var(--rad));
  filter:blur(calc((1 - var(--m,0)) * 3px));
  will-change:transform,clip-path;
}
.js .fly__st.is-off{visibility:hidden}

/* ---- Die Fahrt auf dem Telefon: mittig statt neben dem Linienband ----
   Die Station stand bisher rechts vom Band der Linie; gemessen ergab
   `--spine-x + --spine-w + Abstand` bei 390 px Breite einen linken Rand von
   91,6 px, sodass ihr nur 278 px blieben. „Therapieplan" ist bei 15vw allein
   311 px breit — die letzten Buchstaben lagen außerhalb und wurden von der
   Maske des Pins abgeschnitten. Genau das war der gemeldete Fehler.
   Hier steht die Station deshalb zwischen den normalen Satzrändern, mittig
   gesetzt, und die Linie läuft mittig dahinter (z-index 0, also hinter
   Überschrift und Foto). */
@media (max-width:640px){
  .js .fly__st{
    left:var(--gutter);right:var(--gutter);
    gap:clamp(1rem,4vw,1.6rem);
  }
  .js .fly__spine{left:50%;transform:translateX(-50%);opacity:.5}
  /* Höhe statt Breite führt: so bleibt die Station auch auf einem flachen
     Telefon vollständig in der gepinnten Bildschirmhöhe. */
  .js .fly__shot{height:24svh;width:auto;max-width:100%;aspect-ratio:4/3}
  .js .fly__hud{font-size:.68rem;letter-spacing:.06em}
}
}

/* ============================================================
   RÜCKWEG ZUR STARTSEITE (Vorbild noomoagency.com)
   Unter der Fußzeile. Beim Weiterscrollen füllt sich die Leiste
   rechts; ist sie voll, wechselt js/main.js auf die Startseite.
   --bp (0→1) ist der Fortschritt (js/main.js: initBackHome).
   Ohne Skript und bei reduzierter Bewegung bleibt eine gewöhnliche,
   voll bedienbare Verweiszeile stehen.
   ============================================================ */
.backhome{position:relative;background:var(--espresso);color:var(--on-dark)}
.backhome__pin{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:clamp(2rem,6vw,4rem);
  padding:clamp(3rem,8vw,6rem) var(--gutter);
  width:100%;max-width:var(--maxw);margin-inline:auto;
}
.backhome__say{
  margin:0;flex:0 1 auto;
  font-family:var(--font-body);font-weight:500;
  font-size:clamp(.8rem,1.5vw,.92rem);line-height:1.65;
  letter-spacing:.08em;text-transform:uppercase;color:var(--on-dark);
}
.backhome__go{
  display:flex;align-items:center;gap:clamp(1rem,2.4vw,1.8rem);
  flex:1 1 20rem;max-width:34rem;
  color:var(--on-dark);text-decoration:none;
  font-family:var(--font-body);font-weight:500;
  font-size:clamp(.8rem,1.5vw,.92rem);letter-spacing:.09em;text-transform:uppercase;
}
.backhome__track{flex:1 1 auto;height:2px;background:rgba(255,255,255,.22);overflow:hidden}
.backhome__fill{
  display:block;height:100%;background:var(--orange);
  transform:scaleX(var(--bp,0));transform-origin:0 50%;
}
.backhome__arr{
  width:1.4em;height:1.4em;flex:0 0 auto;
  transition:transform .4s var(--ease-out);
}
.backhome__go:hover .backhome__arr,
.backhome__go:focus-visible .backhome__arr{transform:translateX(.35em)}

@media (prefers-reduced-motion:no-preference){
  /* 70svh Scrollweg füllen die Leiste — lang genug, dass der Wechsel
     eine Entscheidung bleibt, kurz genug, dass er nicht zäh wird. */
  .js .backhome{min-height:170svh}
  .js .backhome__pin{position:sticky;top:0;height:100svh}
}

/* ============================================================
   04 · TEAM
   ============================================================ */
.team__grid{
  display:grid;grid-template-columns:1.15fr .85fr;
  gap:clamp(2rem,5vw,4rem);align-items:end;margin-top:clamp(2.4rem,5vw,4rem);
}
.team__media{position:relative}
.team__frame{
  position:relative;border-radius:var(--rad);overflow:hidden;
  border:1px solid var(--hair);aspect-ratio:16/10;
  background:linear-gradient(135deg,var(--paper-2),#fff);
}
.team__frame img{width:100%;height:100%;object-fit:cover}
/* Der Ausschnitt sitzt in der Breite knapp: mittig schneidet er rechts die
   äußere Mitarbeiterin an, während links nur Schrankfront und Wand stehen.
   Das Foto rückt deshalb ein Stück nach links. Mehr als das geht nicht —
   die Vergrößerung von 1.14 hält ringsum nur gut 6 % Reserve, und die
   braucht das Kippen beim Überfahren. */
.team__frame img{--fxx:-4.5%}
.team__bio h3{font-size:clamp(1.5rem,2.6vw,2.05rem);font-weight:560;margin-bottom:.6rem}
/* Etwas größer und kräftiger als der übrige Fließtext, aber bewusst unter der
   Überschrift (dem Namen) — sie soll die Zeile bleiben, die zuerst trägt. */
.team__bio p{font-size:clamp(1.15rem,1.3vw,1.24rem);font-weight:460}
.team__bio p+p{margin-top:1rem}
.team__bio .sig{
  margin-top:1.6rem;font-family:var(--font-display);font-variation-settings:'opsz' 60,'WONK' 1;
  font-size:1.3rem;color:var(--ink);
}
.team__bio .sig span{display:block;font-family:var(--font-body);font-size:.82rem;color:var(--ink-45);letter-spacing:.04em;margin-top:.2rem;font-variation-settings:normal}

/* ============================================================
   05 · VERTRAUEN (dunkle Tafel)
   ============================================================ */
.trust__grid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  margin-top:clamp(2.4rem,5vw,3.5rem);
  background:var(--hair-dark);border:1px solid var(--hair-dark);border-radius:var(--rad);overflow:hidden;
}
.trust__cell{
  position:relative;
  background-color:var(--espresso);
  padding:clamp(1.6rem,3vw,2.2rem);
  display:flex;flex-direction:column;gap:.55rem;
  transition:background-color .35s var(--ease-out);
}
.trust__cell:hover{background-color:#352c24}
.trust__cell h3{font-size:1.16rem;font-weight:540;letter-spacing:-.018em;color:var(--on-dark)}
.trust__cell p{color:var(--on-dark-60);font-size:.95rem}
.reviews{
  margin-top:1.6rem;padding:1.2rem 1.4rem;border:1px solid var(--hair-dark);border-radius:var(--rad-sm);
  display:flex;flex-wrap:wrap;align-items:center;gap:.8rem 1.2rem;justify-content:space-between;
  color:var(--on-dark-60);font-size:.92rem;
}
.reviews b{color:var(--on-dark);font-weight:600}

/* ============================================================
   06 · KONTAKT
   ============================================================ */
.contact__grid{
  display:grid;grid-template-columns:.85fr 1.15fr;
  gap:clamp(2rem,5vw,4rem);margin-top:clamp(2.4rem,5vw,3.5rem);align-items:start;
}
.info{display:grid}
.info__row{padding-block:1.05rem;border-top:1px solid var(--hair)}
.info__row:last-child{border-bottom:1px solid var(--hair)}
.info__row b{
  display:block;font-family:var(--font-body);font-weight:500;
  font-size:.86rem;color:var(--ink-45);margin-bottom:.3rem;
}
.info__row a,.info__row p{color:var(--ink)}
.info__row a:hover{color:var(--ink-45)}
.hours{width:100%;border-collapse:collapse;margin-top:.3rem}
.hours th,.hours td{padding:.5rem 0;border-bottom:1px solid var(--hair);font-size:.92rem;text-align:left;vertical-align:top}
.hours tr:last-child th,.hours tr:last-child td{border-bottom:0}
.hours th{font-weight:600;color:var(--ink);white-space:nowrap;padding-right:1rem}
.hours td{color:var(--ink-70)}

/* Formular */
.form{
  background:#fff;border:1px solid var(--hair);border-radius:var(--rad);
  padding:clamp(1.5rem,3vw,2.3rem);box-shadow:0 30px 60px -50px rgba(33,28,24,.6);
}
.form__row{display:grid;gap:1.1rem}
@media (min-width:560px){.form__row--2{grid-template-columns:1fr 1fr}}
.field{margin-bottom:1.1rem}
.field label{display:block;font-weight:600;font-size:.88rem;margin-bottom:.45rem}
.field .req{color:var(--orange-text)}
.field input,.field textarea{
  width:100%;padding:.85rem .95rem;border:1px solid var(--hair);border-radius:var(--rad-sm);
  background:var(--paper);transition:border-color .2s,box-shadow .2s;min-height:48px;
}
.field textarea{min-height:140px;resize:vertical}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--orange);box-shadow:0 0 0 3px rgba(236,116,5,.16)}
.field.invalid input,.field.invalid textarea{border-color:#B4341C;background:#FCF1EE}
.field .error{display:none;color:#9A2C18;font-size:.82rem;margin-top:.4rem}
.field.invalid .error{display:block}
.check{display:grid;grid-template-columns:auto 1fr;gap:.65rem;align-items:start;font-size:.9rem;color:var(--ink-70)}
.check input{width:1.1rem;height:1.1rem;margin-top:.28rem;accent-color:var(--orange)}
.check a{color:var(--orange-text);font-weight:600;text-decoration:underline;text-underline-offset:2px}
.form__note{font-size:.82rem;color:var(--ink-45);margin-top:.8rem}
.form__ok{
  display:none;margin-top:1rem;padding:.9rem 1.1rem;border-radius:var(--rad-sm);
  background:#FBEFE2;border:1px solid #F0CFA6;color:#7A3D05;font-weight:500;
}
.form__ok.show{display:block}

/* Karte — datenschutzfreundlich, Klick-zum-Laden */
.map{margin-top:clamp(2.4rem,5vw,3.5rem);border:1px solid var(--hair);border-radius:var(--rad);overflow:hidden}
.map__shell{position:relative;min-height:340px;background:
  radial-gradient(120% 120% at 30% 20%,var(--paper-2),var(--paper)),
  repeating-linear-gradient(0deg,transparent,transparent 38px,var(--hair) 38px,var(--hair) 39px),
  repeating-linear-gradient(90deg,transparent,transparent 38px,var(--hair) 38px,var(--hair) 39px);
}
.map__cta{
  position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.9rem;text-align:center;padding:1.5rem;
}
.map__cta b{font-family:var(--font-display);font-variation-settings:'opsz' 50;font-weight:520;font-size:1.1rem}
.map__cta p{color:var(--ink-70);font-size:.92rem;max-width:24rem}
.map iframe{display:block;width:100%;height:380px;border:0}

/* ============================================================
   FOOTER
   ============================================================ */
.footer{background:var(--espresso);color:var(--on-dark);padding-block:clamp(3rem,6vw,4.5rem) 2rem}
.footer__grid{display:grid;grid-template-columns:1.5fr 1fr 1fr 1fr;gap:2.5rem}
.footer__brand{display:flex;align-items:center;gap:.7rem;margin-bottom:1.1rem}
.footer__brand img{width:auto;height:1.9rem}
.footer__brand span{font-family:var(--font-display);font-variation-settings:'opsz' 40;font-weight:500;font-size:1.1rem;color:var(--on-dark)}
.footer p{color:var(--on-dark-60);font-size:.94rem;max-width:26rem}
.footer__claim{font-family:var(--font-display);font-variation-settings:'opsz' 60,'WONK' 1;font-style:italic;color:#F0A35A;margin-top:.8rem}
.footer h4{font-size:.74rem;letter-spacing:.18em;text-transform:uppercase;color:var(--on-dark-60);font-family:var(--font-body);font-weight:600;margin-bottom:1.1rem}
.footer__col li{margin-bottom:.6rem}
.footer__col a,.footer__col li{color:var(--on-dark);font-size:.95rem}
.footer__col a:hover{color:#F0A35A}
.footer__note{
  margin-top:2.6rem;padding:1rem 1.2rem;border:1px dashed var(--hair-dark);border-radius:var(--rad-sm);
  color:var(--on-dark-60);font-size:.84rem;
}
.footer__note b{color:var(--on-dark)}
.footer__legal{
  margin-top:1.8rem;padding-top:1.4rem;border-top:1px solid var(--hair-dark);
  display:flex;flex-wrap:wrap;gap:.6rem 1.6rem;justify-content:space-between;align-items:center;
  font-size:.85rem;color:var(--on-dark-60);
}
.footer__legal nav{display:flex;flex-wrap:wrap;gap:1.4rem}
.footer__legal a:hover{color:#F0A35A}

/* Die feste Aktionsleiste am unteren Rand („Anrufen"/„Termin") ist entfallen —
   sie lag auf dem Slogan des Startbilds. Beide Wege stehen jetzt in der
   Menü-Tafel (.mpanel__cta / .mpanel__cta--call), auf allen Geräten. */

/* ============================================================
   MOTION — Scrub-Reveals
   ============================================================ */
/* Reveals sind scrub-gebunden: js/main.js schreibt --p (0→1, geeast und über
   --i gestaffelt) je nach Scroll-Position; CSS mappt den Wert live auf
   Opazität/Weg. NUR mit aktivem JS (.js am <html>) — ohne JS / bei JS-Fehler
   bleiben alle Inhalte sichtbar. */
.js .reveal{
  opacity:var(--p,0);
  transform:translate3d(0,calc((1 - var(--p,0))*30px),0) scale(calc(.985 + var(--p,0)*.015));
}

/* ---- Lese-Reveal (Vorbild tresmarescapital.com): Wörter stehen zunächst
   hellgrau und schwer lesbar und werden beim Scrollen Wort für Wort zu voller
   Tinte. --r (0→1) je Wort setzt js/main.js (initReadReveal) scrub-gebunden;
   ohne JS / ohne gesetztes --r bleibt alles voll deckend (--r Standard 1). ---- */
.js [data-read] .rvw,
.js [data-read] .w>span{opacity:calc(.1 + var(--r,1)*.9)}
/* Wo das Lese-Reveal greift, trägt die Wort-Deckkraft die Einblendung — die
   Block-Einblendung des .reveal-Containers entfällt dort (nur der leichte
   Auftrieb bleibt), damit sich beide nicht überlagern. */
.js .reveal:has([data-read]),
.js [data-read]{opacity:1}

/* Clip-Wipe der Bilder folgt dem Scroll (scrub statt Einmal-Transition) */
.js .clip>img{clip-path:inset(0 0 calc((1 - var(--p,0))*100%) 0)}

/* zeilenweises Headline-Reveal */
.line-reveal{overflow:hidden;display:block}
.js .line-reveal>*{display:block;transform:translateY(108%);transition:transform .8s var(--ease-out);transition-delay:calc(var(--i,0)*.09s)}
.js .line-reveal.in>*{transform:none}

/* ============================================================
   RESPONSIVE — drei bewusst komponierte Tiers
   ============================================================ */

/* ---- TABLET (641–1024px): eigenes Raster ---- */
@media (max-width:1024px){

  /* Die Linkzeile hätte hier keinen Platz mehr: Leiste sofort auf
     [Logo] [Menü] zusammenziehen — sonst bricht sie um. Hier gibt es keinen
     Zustandswechsel, „Menü" steht deshalb von Anfang an. */
  .nav__links,.nav__cta{display:none}
  .nav__menu{
    opacity:1;visibility:visible;pointer-events:auto;
    transform:translateY(-50%);transition:none;
  }
  .nav__brand img{height:2.2rem}
  .is-stuck .nav__brand img{height:2.8rem}

  .praxis__grid{grid-template-columns:1fr;gap:2.4rem}
  .figure--portrait{aspect-ratio:16/10;max-height:30rem}

  /* Nebeneinander wird die linke Spalte hier zu schmal — Foto oben, Leiste
     darunter, das Foto behält aber sein knappes Hochformat. */
  .praxis__close{grid-template-columns:1fr;gap:2.6rem}
  .praxis__wide{grid-column:1;grid-row:auto;max-width:24rem;justify-self:start}
  .factbar{grid-column:1;grid-row:auto}

  .team__grid{grid-template-columns:1fr;gap:2.2rem;align-items:start}
  .team__frame{aspect-ratio:16/9}

  .trust__grid{grid-template-columns:repeat(2,1fr)}

  .contact__grid{grid-template-columns:1fr;gap:2.4rem}

  .footer__grid{grid-template-columns:1fr 1fr;gap:2rem}
}

/* ---- MOBILE (≤640px): gestapelt, Aktionsleiste, kompakt ---- */
@media (max-width:640px){
  :root{--section-y:clamp(3.5rem,12vw,5rem)}

  .site-header{padding:.8rem 1rem 0}
  .nav__brand img{height:2rem}
  .is-stuck .nav__brand img{height:2.5rem}


  .hero{padding-top:5rem}     /* feste Leiste freihalten */
  .hero__claim{font-size:clamp(2.6rem,12.5vw,4rem);max-width:none}

  /* Enger Durchschuss trägt nur, solange die Zeile groß ist. Auf dem Telefon
     fallen die Überschriften auf ihren unteren clamp-Wert zurück, und bei
     line-height 1 stoßen dort Umlautpunkte und Unterlängen aufeinander —
     genau der gequetschte Eindruck. Ein Zehntel mehr genügt. */
  .hero--sub .hero__claim{line-height:1.08;letter-spacing:-.026em}
  .head__title{line-height:1.1}

  /* ---- Luft um die Überschriften der Unterseiten ----
     Gemessen bei 390 px stand im Kopf der Unterseiten das Label unmittelbar
     auf der Überschrift und die Einleitung unmittelbar darunter — zwischen
     allen dreien lagen 0 px, die Überschrift war also von oben und unten
     eingeklemmt. In den Abschnitten waren es 24 px über und 17–27 px unter
     der Überschrift, ebenfalls zu eng. Auf dem Rechner trägt der größere
     Satzspiegel das noch, auf dem Telefon nicht. */
  .hero--sub .kicker{margin-bottom:1.15rem}
  .hero--sub .hero__claim{margin-bottom:1.4rem}
  .kicker + .head__main .head__title{margin-top:2.4rem}
  .head__lede{margin-top:1.6rem}
  .tech-body{margin-top:2.2rem}
  .tour__title{line-height:1.1}
  .hero__intro p{font-size:.92rem;max-width:26rem}
  .hero__actions{flex-direction:column;align-items:stretch}
  .hero__actions .btn{width:100%}

  .trust__grid{grid-template-columns:1fr}

  /* Die senkrechte Linie trägt auch hier, nur enger gesetzt. */
  .factbar{gap:1.4rem;padding-left:1.4rem}
  .fact::before{left:calc((1.4rem + 3px)*-1)}
  .fact b{font-size:1.7rem}
  .fact span{max-width:none}

  .praxis__wide{max-width:none;aspect-ratio:3/4}

  /* ---- Getauschte Fotos: Sektion 01 ↔ Auftakt Leistungen ----
     Die Bilder selbst tauscht <picture> in index.html, hier stimmen nur die
     Flächen dazu:
     · Sektion 01 behält die 16/10-Maske. Das Team-Foto misst 3840×2487 (1,544),
       die Maske 1,6 — es wird also nur um 3,6 % der Höhe beschnitten und steht
       praktisch vollständig im Bild.
     · Der Auftakt der Leistungen wird quadratisch. Die Außenansicht ist
       3840×3840; in der bisherigen Höhe von min(112svh,74rem) — bei 390 px
       Breite 374×945 — blieben von ihr 40 % der Breite stehen, die Hausfront
       wäre auf zwei Fenster zusammengeschnitten. Bei 1:1 ist sie ungeschnitten
       zu sehen, und der Satz darüber hat weiterhin genug Platz.
     · Die Bildunterschrift wechselt mit dem Foto die Sektion. */
  .svcintro{height:auto;aspect-ratio:1/1}
  .figcap--praxis{display:none}
  .svcintro__cap{display:block;margin-inline:var(--gutter)}

  /* Leistungsliste: seit das Bild aus der Zeile ist, steht die volle Breite
     zur Verfügung. Gemessen ist „Abdruckfreie Diagnostik" das längste Wortpaar
     und bei 8,8vw 275 px breit — mit dem kurz eingeblendeten Bildfeld (1.5em)
     zusammen 326 px von 350 px. Die Zeile bleibt damit auch beim Antippen
     einzeilig. Etwas mehr Innenabstand macht sie zugleich sicherer zu treffen. */
  .svclist__title{font-size:clamp(1.6rem,8.8vw,2.6rem)}
  .svclist__row{padding-block:.62rem}

  .footer__grid{grid-template-columns:1fr;gap:1.8rem}
  .footer__legal{flex-direction:column;align-items:flex-start;gap:1rem}
}

/* ============================================================
   RECHTSSEITEN (Impressum / Datenschutz) — gleiches System
   ============================================================ */
.subpage{padding-block:clamp(7rem,12vh,9rem) clamp(2.4rem,6vw,4.5rem)} /* fixe Pille freihalten */
.backlink{
  display:inline-flex;align-items:center;gap:.5rem;
  color:var(--orange-text);font-weight:600;margin-bottom:1.6rem;
}
.backlink svg{width:1.05em;height:1.05em;transition:transform .25s var(--ease-out)}
.backlink:hover svg{transform:translateX(-4px)}
.prose{max-width:46rem}
.prose>p{color:var(--ink-70);margin-bottom:1rem}
.prose h2{
  font-size:clamp(1.4rem,2.6vw,1.95rem);font-family:var(--font-display);
  font-weight:560;
  margin:2.6rem 0 .8rem;padding-top:1.6rem;border-top:1px solid var(--hair);
}
.prose h2:first-of-type{border-top:0;padding-top:0;margin-top:1.6rem}
.prose h3{font-size:1.1rem;font-variation-settings:'opsz' 40;font-weight:560;margin:1.6rem 0 .4rem}
.prose a{color:var(--orange-text);text-decoration:underline;text-underline-offset:2px}
.prose .dash{display:grid;gap:.5rem;margin:0 0 1rem}
.prose .dash li{padding-left:1.3rem;position:relative;color:var(--ink-70)}
.prose .dash li::before{content:"–";position:absolute;left:0;color:var(--orange-text)}
.placeholder-box{
  background:var(--paper-2);border:1px dashed var(--orange);border-radius:var(--rad-sm);
  padding:1rem 1.2rem;margin:1.3rem 0;color:var(--ink-70);font-size:.95rem;
}
.placeholder-box b{color:var(--ink)}

/* ============================================================
   MOTION EDITION — Upgrade-Schicht (Juli 2026)
   Orchestrierte Reveals, Zeilen-/Wort-Masken, Parallax (--plxy),
   Ghost-Ziffern, Scroll-Progress, Grain.
   Alles transform/opacity-basiert (GPU), reduced-motion-sicher.
   ============================================================ */

/* ---- Zeilen-Masken: Hero-Claim gleitet zeilenweise aus der Maske ---- */
/* Der Innenabstand gibt Oberlängen und Umlauten Luft, der negative Rand hält
   die Maskenkante exakt an ihrem Platz — sonst kappt overflow:hidden das ä. */
.lmask{display:block;overflow:hidden;padding-top:.16em;margin-top:-.16em}
.lmask .lm{display:block}
.js .lmask .lm{
  transform:translateY(135%) rotate(2.2deg);
  transform-origin:0 100%;
  transition:transform 1.05s var(--ease-out);
  transition-delay:calc(var(--i,0)*.13s + .08s);
}
.js .hero__claim.in .lm{transform:none}

/* ---- Wort-Masken: Sektionstitel kaskadieren wortweise ---- */
.js [data-split] .w{
  display:inline-block;overflow:hidden;vertical-align:bottom;
  /* Puffer für Ober- und Unterlängen: unten mindestens die Unterlänge des „g"
     (0,22 em bei Inter Tight) plus Reserve, sonst kappt overflow:hidden
     Wörter wie „geführt" oder „Gründe". */
  padding:.1em .02em .26em 0;margin:-.1em -.02em -.26em 0;
}
.js [data-split] .w>span{
  display:inline-block;
  transform:translateY(145%);   /* > 100 % + Puffer, damit nichts hervorlugt */
  transition:transform .85s var(--ease-out);
  transition-delay:calc(var(--wi,0)*.05s + .05s);
}
.js .in .w>span{transform:none}

/* ---- Buchstabentausch in der Riesenschrift (Vorbild lusion.co/about) ----
   Jeder Buchstabe sitzt in einer eigenen Maske und steht doppelt darin:
   __a ist sichtbar, __b wartet unterhalb der Maskenkante. Beim Rollen fährt
   __a nach oben hinaus, __b rückt an seine Stelle; danach setzt js/main.js
   beide lautlos zurück — dieselbe Glyphe, der Sprung ist also unsichtbar.
   Dieselbe Bewegung trägt auch den Eintritt: alle Buchstaben steigen
   gestaffelt aus der Maske auf, sobald die Zeile ins Bild kommt.
   Maskenregel: Innenabstand oben für Umlaute, unten für die Unterlänge,
   beides durch einen gleich großen negativen Rand wieder aufgehoben. Die
   Warteposition liegt bei 160 % — bei einer Zeilenhöhe unter 1 reicht ein
   knapperer Wert nicht, dann lugen Ober- und Unterlängen hervor. */
.swword{display:inline-block;white-space:nowrap}
.swch{
  display:inline-block;position:relative;overflow:hidden;
  padding:.24em .03em .32em 0;margin:-.24em -.03em -.32em 0;
}
.swch__a{display:block}
.swch__b{position:absolute;left:0;top:.24em;display:block}
.js [data-swap] .swch__a,
.js [data-swap] .swch__b{
  transform:translateY(160%);
  transition:transform .9s var(--ease-out);
}
.js [data-swap] .swch__a{transition-delay:calc(var(--ci,0)*.02s)}
.js [data-swap].in .swch__a{transform:none}
.js [data-swap].in .swch.is-roll .swch__a{transform:translateY(-160%);transition:transform .62s var(--ease-out)}
.js [data-swap].in .swch.is-roll .swch__b{transform:none;transition:transform .62s var(--ease-out)}
.swch.is-nofx .swch__a,
.swch.is-nofx .swch__b{transition:none}

/* ---- Parallax: JS setzt --plxy, CSS komponiert die Transformation.
   scale(1.14) = 7% Polster je Seite; data-plx bleibt darunter (max. 6). ---- */
.js img[data-plx]{transform:translate3d(0,var(--plxy,0px),0) scale(1.14)}

/* ---- Foto-Effekt beim Überfahren (Vorbild lusion.co) ----
   Zwei Dinge gleichzeitig: das Bild kippt leicht in die Tiefe und folgt dabei
   dem Zeiger, und im Moment des Eintritts springt es für einen Sekunden-
   bruchteil unscharf, bevor es zurück in die Schärfe zieht — als würde ein
   Objektiv nachfokussieren. Die Neigung liegt auf dem Bild, nicht auf der
   Umrandung: die trägt bereits die Reveal-Transformation. Die Grundvergröße-
   rung (1.07) verdeckt die Ecken, die beim Kippen sonst leer würden, und
   fängt zugleich den weichen Rand der Unschärfe ab.
   js/main.js (initPhotoFX) schreibt --rx/--ry und schaltet .is-focusing. */
.fx{perspective:900px}
.js .fx img{
  transform:translate3d(var(--fxx,0px),var(--plxy,0px),0)
            rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg))
            scale(var(--fxs,1.07));
  /* Der Rückweg in die Schärfe läuft bewusst NICHT auf --ease-out: die
     Kurve setzt fast ohne Anlauf ein, dadurch wirkte das Nachfokussieren
     ruckartig. Eine gleichmäßige Kurve über knapp eine Sekunde liest sich
     wie ein Objektiv, das ruhig scharfstellt (Vorbild lusion.co). */
  transition:transform .5s var(--ease-out),filter .95s cubic-bezier(.25,.46,.45,.94);
}
.js .fx img[data-plx]{--fxs:1.14}
/* 2px: der Impuls soll die Bewegung nur andeuten, nicht das Motiv trüben —
   4px wirkte noch zu abrupt und intensiv. */
.fx.is-focusing img{filter:blur(2px);transition:filter 0s}
/* Der Hero ist auf dem Desktop festgesteckt und stünde beim Scrollen völlig
   still — man sähe erst spät, dass sich etwas tut. Die Hero-Texte ziehen
   deshalb nach oben weg, sobald die erste Sektion hochkommt (js/main.js
   schreibt --heroy aus dem Scrollstand). */
.js .hero__copy{transform:translate3d(0,var(--heroy,0px),0)}

/* ---- Grain: feines Korn auf dunklen Flächen (statisch, günstig) ---- */
.section--dark,.footer{position:relative}
.section--dark::after,.footer::after{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:180px 180px;
}

/* ---- Hero: warmes Blur-to-Sharp nach dem Loader ----
   --hs (0→1) ist als Zahl registriert und damit weich animierbar; Browser ohne
   @property zeigen das Bild schlicht sofort scharf (sauberer Fallback). ---- */
@property --hs{syntax:'<number>';initial-value:0;inherits:true}
.js .hero__bg{--hs:0;transition:--hs 1.5s var(--ease-out) .15s}
.js.is-ready .hero__bg{--hs:1}
.js .hero__bg img{
  filter:blur(calc((1 - var(--hs,1))*14px)) saturate(calc(.9 + var(--hs,1)*.14));
  transform:scale(calc(1.04 + (1 - var(--hs,1))*.05));
}

/* ---- Faktenleiste: Jahreszahlen zählen hoch (js/main.js) ---- */
.fact b.is-counting{font-variant-numeric:tabular-nums}

/* ---- Buttons: magnetisch (JS setzt nur transform) ---- */
.btn{
  transition:background .2s var(--ease-out),color .25s var(--ease-out),
             border-color .2s var(--ease-out),transform .35s var(--ease-out);
}


/* ============================================================
   LOADER — Typo-Reveal: „Kieferorthopädie" und „Krefeld-Hüls" gleiten
   Buchstabe für Buchstabe aus einer gedachten Waagerechten in der
   Bildmitte auf. Danach zieht die weiße Fläche nach oben und gibt die
   Seite frei. js/main.js (initLoader) zerlegt die Zeilen und schaltet
   .go → .is-hide.
   ============================================================ */
.loader{
  position:fixed;inset:0;z-index:300;overflow:hidden;
  background:#fff;                       /* reiner weißer Startbildschirm */
  transition:transform .8s cubic-bezier(.76,0,.24,1);
  will-change:transform;
}
.loader[hidden]{display:none}
.loader.is-hide{transform:translateY(-100%);pointer-events:none}

.ldr{
  position:absolute;inset:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(.15rem,1vh,.55rem);
  text-align:center;padding-inline:1.2rem;
}
/* Jede Zeile ist eine Maske; die Buchstaben darin steigen aus der Waagerechten
   auf. Innenabstand + negativer Rand geben Ober-/Unterlängen Platz. */
.ldr__line{
  display:inline-flex;overflow:hidden;white-space:nowrap;
  font-family:var(--font-display);line-height:1;
  padding:.12em .04em .28em;margin:-.12em -.04em -.28em;
}
.ldr__line--1{
  font-weight:800;letter-spacing:-.03em;color:#0B0A09;
  font-size:clamp(2rem,7.6vw,5.6rem);
}
.ldr__line--2{
  font-weight:700;letter-spacing:.05em;color:var(--orange);
  font-size:clamp(1.05rem,4vw,2.7rem);
}
.ldr__ch{
  display:inline-block;
  /* Warteposition über der Maskenregel-Schwelle (>135 %): bei 115 % lugten die
     Buchstabenoberkanten an der unteren Maskenkante hervor, bevor die Zeile an
     der Reihe war. */
  transform:translateY(140%);
  transition:transform .72s cubic-bezier(.16,1,.3,1) calc(var(--c,0)*.045s);
}
.loader.go .ldr__ch{transform:none}

/* ============================================================
   PRAXISFOTO-CHOREOGRAFIE (Juli 2026, Vorbild noth.in / lamalama)
   1) .tour — gepinnter Rundgang: Flur/Wartebereich füllt den
      Screen und zerfällt beim Scrollen von unten in feine
      Blöcke. Er verschwindet dabei vollständig und legt die
      Bühne frei, die von Anfang an darunter liegt: links die
      Zeile zu den Räumen, rechts der Kunst-Flur.
      js/main.js schreibt --sp (0→1) auf [data-tour].
   2) .rooms — „Unsere | Behandlungsräume" rücken beim Scrollen
      auseinander, dazwischen wachsen die drei Raumfotos auf und
      wechseln im 1,5-Sekunden-Takt (--rp auf [data-rooms]).
   ============================================================ */
/* Ab dem Vollbild-Foto steht die Seite auf Schwarz. Der Wechsel wird nicht
   geschnitten — der Pixel-Übergang des Fotos (js/main.js) legt frei, was
   darunter liegt. */
/* 220vh: die ersten ~62vh Scrollweg tragen das Vollbild ab, der Rest lässt die
   freigelegte Bühne stehen. */
.tour{position:relative;z-index:2;background:#000;height:220vh}
.tour__pin{position:sticky;top:0;height:100svh;overflow:hidden}

/* Die Bühne liegt unter dem Vollbild und wartet dort, bis der Zerfall sie
   erreicht — nichts blendet ein, es wird nur abgetragen. */
.tour__stage{
  position:absolute;inset:0;z-index:1;
  display:grid;grid-template-columns:1fr minmax(0,.8fr);
  align-items:center;gap:clamp(2rem,5vw,4.5rem);
  padding-block:clamp(3rem,8svh,6rem);
  padding-inline:max(var(--gutter),calc((100% - var(--maxw))/2));
}
/* Linke Spalte: die Zeile, und darunter das zweite Foto in eigener Größe. */
.tour__say{
  min-width:0;align-self:center;
  display:flex;flex-direction:column;gap:clamp(1.4rem,3.4vh,2.6rem);
}
/* Redaktionelle Serife statt Grotesk — dieselbe Rolle wie die großen
   Projektzeilen auf locomotive.ca: eine Aussage, die für sich steht. */
.tour__title{
  margin:0;color:#fff;
  font-family:var(--font-serif);font-weight:400;
  font-size:clamp(2.4rem,5.6vw,4.6rem);line-height:1.02;letter-spacing:-.018em;
  text-wrap:balance;
}
/* Das zuvor rechts eingeklemmte Kunst-Foto steht jetzt unter der Zeile links,
   in eigener Größe und mit dem .fx-Effekt. */
.tour__side{
  /* Das Kunst-Foto ist ein Hochformat (2576×3840). In einer Querformat-Maske
     (16/10.5) hätte object-fit:cover oben und unten je die Hälfte weggeschnitten
     und es läge quer im Bild. Die Maske trägt jetzt exakt das Bildseitenver-
     hältnis — so steht das ganze Foto randlos und ohne Beschnitt.
     Über eine feste HÖHE gesteuert (nicht über die Breite): Höhe und max-width
     zugleich zu deckeln würde das Seitenverhältnis brechen und wieder beschneiden.
     align-self:start nimmt die Streckung der Flex-Spalte zurück, die Breite folgt
     aus Höhe × Verhältnis. Die Höhe bleibt in der gepinnten Bühne unter der
     Überschrift. */
  margin:0;align-self:start;
  height:min(46svh,22rem);aspect-ratio:2576/3840;width:auto;max-width:100%;
  overflow:hidden;border-radius:var(--rad);border:1px solid var(--hair-dark);
}
.tour__side img{width:100%;height:100%;object-fit:cover}

.tour__tall{
  margin:0;justify-self:end;align-self:center;
  width:100%;max-width:26rem;aspect-ratio:3/4.2;max-height:100%;
  overflow:hidden;border-radius:var(--rad);border:1px solid var(--hair-dark);
}
.tour__tall img{width:100%;height:100%;object-fit:cover}

/* Rechte Spalte: das große Durchgangsfoto steht allein und nimmt jetzt die
   volle Höhe der Bühne ein — den Platz, den vorher zwei gestapelte Bilder
   geteilt haben. */
.tour__stack{
  justify-self:end;align-self:center;
  display:flex;flex-direction:column;
  width:100%;max-width:29rem;max-height:100%;overflow:hidden;
}
.tour__stack .tour__tall{
  justify-self:auto;align-self:auto;
  width:100%;max-width:none;max-height:100%;min-height:0;
  aspect-ratio:3/3.9;
}

/* Das Vollbild liegt über der Bühne. Das Canvas trägt das Foto, sobald es
   steht — das <img> bleibt für SEO und den Fall ohne JS im Dokument, wird
   dann aber nur noch als Quelle gelesen. */
/* Das Vollbild hängt nicht am Pin fest: --sy ist der bereits in die Sektion
   gescrollte Weg in Pixeln, das Bild wandert exakt um diesen Betrag nach oben
   und verlässt den Bildschirm wie ein ganz normaler Abschnitt. Der Zerfall
   trägt es gleichzeitig von unten ab — beides zusammen lässt es früher
   verschwinden, als es allein durch das Scrollen täte. */
.tour__big{
  position:absolute;inset:0;z-index:2;margin:0;overflow:hidden;
  transform:translate3d(0,calc(var(--sy,0px)*-1),0);
  will-change:transform;
}
.tour__big img{width:100%;height:100%;object-fit:cover}
.tour__canvas{position:absolute;inset:0;display:block}
.tour__big.has-canvas img{visibility:hidden}

/* ---- Behandlungsräume ---- */
.rooms{
  position:relative;z-index:2;background:#000;height:240vh;
  /* Endmaß der Bildkarte: quer und großflächig, über Höhe UND Breite
     gedeckelt, damit sie auf flachen wie schmalen Fenstern in der
     gepinnten Bühne bleibt. */
  --cov-h:min(58svh,31rem);
  --cov-w:min(calc(var(--cov-h)*1.52),54vw);
  /* Die Karte wächst über den Scrollweg. Beide Wörter hängen an ihren
     Eckpunkten und rücken dadurch von selbst mit auseinander. */
  --cov-s:calc(.66 + var(--rp,0)*.34);
  --cov-hw:calc(var(--cov-w)/2*var(--cov-s));   /* halbe Breite, mitskaliert */
  --cov-hh:calc(var(--cov-h)/2*var(--cov-s));   /* halbe Höhe, mitskaliert   */
}
.rooms__pin{position:sticky;top:0;height:100svh;overflow:hidden}
.rooms__stage{position:relative;height:100%}

/* Die beiden Wörter stehen nicht mehr auf einer Zeile: „Unsere" sitzt in der
   oberen linken, „Behandlungsräume" in der unteren rechten Bildecke — jeweils
   um .3em in die Fläche getaucht, damit sie an der Karte kleben statt daneben
   zu schweben. */
.rooms__head{
  position:absolute;inset:0;z-index:2;margin:0;
  color:#fff;
  font-family:var(--font-display);font-weight:600;
  font-size:clamp(1.5rem,3.6vw,4rem);line-height:1;letter-spacing:-.035em;
}
.rooms__word{
  position:absolute;left:50%;top:50%;display:block;
  white-space:nowrap;will-change:transform;
}
.rooms__word--l{
  transform:translate3d(calc(var(--cov-hw)*-1),calc(var(--cov-hh)*-1),0)
            translateY(-100%) translate(.34em,.30em);
}
.rooms__word--r{
  transform:translate3d(var(--cov-hw),var(--cov-hh),0)
            translateX(-100%) translate(-.34em,-.30em);
}

.rooms__cover{
  position:absolute;left:50%;top:50%;z-index:1;
  width:var(--cov-w);height:var(--cov-h);
  transform:translate(-50%,-50%) scale(var(--cov-s));
  clip-path:inset(calc((1 - var(--rp,0))*26%) round var(--rad));
  will-change:transform,clip-path;
}
.rooms__shot{
  position:absolute;inset:0;margin:0;overflow:hidden;
  border-radius:var(--rad);border:1px solid var(--hair-dark);
  opacity:0;transition:opacity .55s var(--ease-out);
}
.rooms__shot.is-on{opacity:1}
.rooms__shot img{width:100%;height:100%;object-fit:cover}

/* Responsive Overrides der Choreografie (NACH den Basis-Regeln, sonst
   gewinnt die Quell-Reihenfolge) */
@media (max-width:1024px){
  .tour{height:200vh}
  .tour__stage{grid-template-columns:1fr;align-content:center;gap:clamp(1.5rem,4vw,2.5rem)}
  .tour__tall{justify-self:start;max-width:min(60vw,20rem);aspect-ratio:3/3.4}
  .rooms{--cov-h:min(48svh,25rem);--cov-w:min(calc(var(--cov-h)*1.5),74vw)}
}
@media (max-width:640px){
  /* ---- Rundgang auf dem Telefon: Vollbild, danach zwei große Fotos ----
     Die beiden Fotos sollen die ganze Breite einnehmen, damit man die Praxis
     wirklich sieht. Nebeneinander im festgehaltenen Bildschirm waren sie
     169 px breit; randlos gestapelt sind es 390 und bei unverändertem
     Seitenverhältnis der Quelle 390×520 (Behandlungsbereich, 1440×1920) und
     390×582 (Kunst-Flur, 2576×3840). Zusammen mit der Zeile sind das ~1150 px
     — das passt in keine Bildschirmhöhe (844), die gepinnte Bühne ist damit
     ausgeschlossen.
     Der Abschnitt läuft deshalb im Fluss: das Vollbild ist der Auftakt und
     zerfällt beim Wegscrollen wie bisher — `--sy` kommt aus dem Scrollweg in
     die Sektion und braucht den Pin nicht (initTour). Weil das Bild jetzt
     selbst mitscrollt, ist die zusätzliche Verschiebung um --sy hier
     zurückgenommen; sonst liefe es doppelt so schnell nach oben und ließe
     eine leere Bildschirmhöhe stehen.
     Reihenfolge über `order` statt über die Quelle: das Foto aus dem
     Behandlungsbereich steht über dem mit dem gelben Bild. `display:contents`
     löst .tour__say auf, damit Zeile und Kunst-Flur eigene Kinder der Bühne
     werden und `order` überhaupt greifen kann. */
  .tour{height:auto}
  .tour__pin{
    position:static;height:auto;overflow:visible;
    display:flex;flex-direction:column;
  }
  .tour__big{
    order:-1;                            /* das Vollbild bleibt der Auftakt */
    position:relative;inset:auto;z-index:2;
    width:100%;height:100svh;flex:0 0 auto;
    aspect-ratio:auto;transform:none;
  }
  .tour__stage{
    position:static;inset:auto;
    display:flex;flex-direction:column;
    /* Ausdrücklich stretch: die Grundregel setzt align-items:center, und in
       einer Flex-Spalte schrumpfte damit jedes Kind auf seine Inhaltsbreite. */
    align-items:stretch;
    gap:clamp(1.1rem,4.5vw,1.8rem);
    padding-block:clamp(2.4rem,9vw,3.6rem);
    padding-inline:0;                    /* die Fotos gehen randlos über die Breite */
  }
  .tour__say{display:contents}
  .tour__title{
    order:0;font-size:clamp(1.5rem,7.2vw,2.6rem);
    padding-inline:var(--gutter);        /* nur die Zeile behält den Satzspiegel */
  }
  .tour__stack{
    order:1;display:block;
    width:100%;max-width:none;max-height:none;overflow:visible;
  }
  .tour__side{order:2}
  /* Randlos über die ganze Breite. Die Umrandung fällt weg: an der
     Bildschirmkante wäre sie eine Linie ohne Gegenüber, und der 2-px-Radius
     ist dort ohnehin nicht zu sehen. */
  .tour__side,
  .tour__stack .tour__tall{
    width:100%;max-width:none;height:auto;max-height:none;
    margin:0;align-self:stretch;
    border:0;border-radius:0;
  }
  .tour__side{aspect-ratio:2576/3840}
  .tour__stack .tour__tall{aspect-ratio:1440/1920}
  /* Dieselbe Aufteilung wie auf dem Rechner — „Unsere" links über der Karte,
     „Behandlungsräume" rechts darunter, beide ein Stück in die Fläche getaucht.
     Statt an den mitskalierten Kartenecken hängen sie hier an den Ecken der
     Bühne: die Karte läuft im Fluss mit und hält über `margin-block` genau die
     Zeilenhöhe minus Überlappung frei. Dadurch stehen beide Wörter innerhalb
     des Satzspiegels und werden nirgends vom Rand abgeschnitten.
     Die Fahrt ist nicht mehr gepinnt (siehe initRooms): --rp läuft, sobald ein
     Stück des Abschnitts zu sehen ist, und ist voll, wenn die Karte in der
     Bildschirmmitte steht. */
  .rooms{
    height:auto;
    --rw:clamp(1.7rem,7.6vw,3rem);   /* Zeilenhöhe der beiden Wörter        */
    --rov:.28;                       /* Anteil davon, der über die Karte ragt */
  }
  .rooms__pin{
    position:static;height:auto;
    padding-block:clamp(3rem,10vw,5rem);padding-inline:var(--gutter);
  }
  /* flow-root, damit die Ränder der Karte nicht aus der Bühne herauslaufen —
     genau sie halten oben und unten den Platz für die beiden Wörter frei. */
  .rooms__stage{position:relative;height:auto;display:flow-root}
  .rooms__head{
    position:absolute;inset:0;z-index:2;margin:0;
    font-size:var(--rw);line-height:1;white-space:nowrap;
  }
  .rooms__word{position:absolute;will-change:transform}
  /* Geschlossen liegen beide Wörter auf der Karte und rücken beim Scrollen an
     ihre Ecken auseinander — dieselbe Bewegung wie auf dem Rechner.
     left/top ausdrücklich zurücknehmen: die Grundregel setzt beide auf 50 %,
     zusammen mit right/bottom ergäbe das eine halb so breite Box statt einer
     Zeile, die sich an der Ecke ausrichtet. */
  .rooms__word--l{
    left:0;top:0;right:auto;bottom:auto;
    transform:translate3d(0,calc((1 - var(--rp,0)) * 1.15em),0);
  }
  .rooms__word--r{
    left:auto;top:auto;right:0;bottom:0;text-align:right;
    transform:translate3d(0,calc((1 - var(--rp,0)) * -1.15em),0);
  }
  /* Quadratisch statt 4/3: die beiden Aufnahmen wechseln sich in derselben
     Fläche ab, eine quer (1920×1440) und eine hoch (1440×1920). Im 4/3-Feld
     verlor die hochkante 44 % ihrer Höhe; im Quadrat verlieren beide gleich
     wenig, nämlich je ein Viertel der langen Seite. */
  .rooms__cover{
    position:relative;left:auto;top:auto;width:100%;height:auto;aspect-ratio:1/1;
    margin-block:calc(var(--rw) * (1 - var(--rov)));
    transform:scale(calc(.87 + var(--rp,0)*.13));transform-origin:50% 50%;
    clip-path:inset(calc((1 - var(--rp,0))*20%) round var(--rad));
  }
}

/* ============================================================
   FOOTER — hoher, redaktioneller Abschluss (nur Startseite;
   die knappen .footer__grid-Regeln bleiben für die Unterseiten)
   ============================================================ */
.footer--grand{padding-block:clamp(4.5rem,9vw,7.5rem) 2rem}
.footx__top{
  display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;
  gap:1.6rem 2.5rem;
  padding-bottom:clamp(2.4rem,5vw,3.6rem);border-bottom:1px solid var(--hair-dark);
}
/* „.footer p"-Basisstile (Größe/Farbe/Breite) gezielt überstimmen */
.footer .footx__claim{
  font-family:var(--font-display);
  font-weight:560;font-size:clamp(1.9rem,4.6vw,3.4rem);line-height:1.06;letter-spacing:-.028em;
  color:var(--on-dark);max-width:18ch;
}
.footer .footx__claim em{font-style:italic;color:#F0A35A}
.footx__grid{
  display:grid;grid-template-columns:1.4fr 1fr 1fr 1.15fr;gap:2.5rem;
  padding-block:clamp(2.4rem,5vw,3.6rem);
}
.footx__addr{font-style:normal;color:var(--on-dark-60);font-size:.94rem;margin-top:.8rem;line-height:1.6}
/* Pfeil-Links in der Spalten-Navigation */
.footx__link{display:inline-flex;align-items:center;gap:.45rem}
.footx__link svg{
  width:.95em;height:.95em;flex:0 0 auto;color:#F0A35A;
  opacity:0;transform:translateX(-6px);
  transition:opacity .25s var(--ease-out),transform .25s var(--ease-out);
}
.footx__link:hover svg,.footx__link:focus-visible svg{opacity:1;transform:none}
/* Live-Ortszeit + ehrlicher Öffnungs-Status */
.footer .footx__clock{
  font-family:var(--font-display);font-variation-settings:'opsz' 60;
  font-variant-numeric:tabular-nums;font-size:clamp(1.5rem,2.4vw,1.95rem);
  color:var(--on-dark);line-height:1.1;max-width:none;
}
.footer .footx__clock span{font-family:var(--font-body);font-size:.85rem;color:var(--on-dark-60)}
.footer .footx__status{
  display:inline-flex;align-items:center;gap:.55rem;margin-top:.6rem;
  color:var(--on-dark-60);font-size:.92rem;max-width:none;
}
.footx__status::before{
  content:"";width:.55rem;height:.55rem;border-radius:50%;flex:0 0 auto;
  background:var(--hair-dark);transition:background .3s var(--ease-out);
}
.footx__status.is-open::before{
  background:var(--orange);box-shadow:0 0 10px rgba(236,116,5,.6);
  animation:statusPulse 2.4s ease-in-out infinite;
}
@keyframes statusPulse{50%{box-shadow:0 0 2px rgba(236,116,5,.2)}}
.footx__totop{
  display:inline-flex;align-items:center;gap:.5rem;margin-top:1.3rem;
  font-weight:600;font-size:.92rem;color:var(--on-dark);
}
.footx__totop:hover{color:#F0A35A}
@media (max-width:1024px){.footx__grid{grid-template-columns:1fr 1fr;gap:2rem}}
@media (max-width:640px){
  .footx__grid{grid-template-columns:1fr;gap:1.8rem}
  .footx__top{align-items:flex-start;flex-direction:column}
}

/* ---------- Reduced Motion ---------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  .reveal,.line-reveal>*{opacity:1!important;transform:none!important}
  .clip>img{clip-path:none!important}
  /* Fotos stehen still und scharf — kein Kippen, kein Nachfokussieren */
  .fx img{transform:none!important;filter:none!important}
  /* Historienleiste: Linie durchgezogen, Punkte gesetzt — ohne Aufbau */
  .factbar__fill{transform:none!important}
  .fact::before{transform:scale(1)!important}
  .hero__aurora,.hero__aurora::before{animation:none!important}
  /* Die Akzente im Ablauf bleiben sichtbar, sie driften nur nicht mehr —
     die Farbe selbst ist keine Bewegung. */
  .flowbg__lite{animation:none!important}
  .portal__shot{transform:none!important;transition:none!important}
  /* Wortrotation: ein Wort steht still, nichts fährt */
  .rotator__ch{transform:none!important;transition:none!important}
  /* wanderndes Sektionswort komplett aus */
  .secword{display:none!important}
  /* Motion-Edition-Schicht neutralisieren */
  .lmask .lm{transform:none!important}
  [data-split] .w>span{transform:none!important;opacity:1!important}
  img[data-plx]{transform:none!important}
  .hero__copy{transform:none!important}
  .js .hero__bg{--hs:1!important}
  .js .hero__bg img{filter:none!important;transform:none!important}
  /* Loader wird per JS übersprungen; hier zusätzlich hart aus */
  .loader{display:none!important}
  /* Foto-Choreografie: statisch und vollständig lesbar */
  .js .hero:not(.hero--sub){position:relative;min-height:0;display:block}
  .tour{height:auto!important}
  .tour__pin{position:static!important;height:auto!important;overflow:visible!important}
  .tour__big{position:relative!important;inset:auto!important;height:70vh}
  .tour__stage{
    position:static!important;grid-template-columns:1fr!important;
    padding-block:clamp(2.5rem,7vw,4rem)!important;
  }
  .tour__tall{justify-self:start!important;max-width:min(80%,26rem)!important;margin-top:2rem}
  /* Auf dem Telefon stehen die beiden Fotos randlos übereinander (siehe
     @media max-width:640px). Diese Breitenbremse gilt nur dem Rechner und muss
     dort zurückgenommen werden: der Telefon-Block steht weiter oben in der
     Datei, seine Angabe ohne !important verliert also gegen die Zeile darüber.
     Die Ausnahme kann deshalb nur hier stehen. */
  @media (max-width:640px){
    .tour__tall{max-width:none!important;margin-top:0!important}
  }
  /* Behandlungsräume: nichts wandert, nichts wechselt — alle drei Fotos
     stehen nebeneinander und die Zeile bleibt in ihrer Endstellung. */
  .rooms{height:auto!important}
  .rooms__pin{position:static!important;height:auto!important;padding-block:clamp(3rem,8vw,5rem)}
  .rooms__stage{display:block!important;height:auto!important}
  /* Auf dem Telefon hängen Überschrift und Wörter an den Ecken der Bühne —
     ohne Bewegung müssen sie zurück in den Fluss, sonst lägen sie über den
     Fotos. */
  .rooms__head{position:static!important;flex-wrap:wrap;white-space:normal}
  .rooms__slot{display:none!important}
  .rooms__word{position:static!important;inset:auto!important;transform:none!important}
  .rooms__cover{
    position:static!important;width:auto!important;height:auto!important;
    transform:none!important;clip-path:none!important;
    display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;
    margin-block:2rem 0!important;
  }
  .rooms__shot{position:static!important;opacity:1!important;aspect-ratio:4/5}
  .footx__status.is-open::before{animation:none!important}
}
